Compare commits

...

49 Commits

Author SHA1 Message Date
Trust 2434bab697 Updated for bypass all rule 2024-02-25 16:00:44 -05:00
Trust 7a5a755033 [Bug Fix] Cleanup NPC Mana Tap Logic
Mana Tap rule logic was invalid - Cleaned up and simplified, either we care about npc mana or we dont.
2024-02-25 15:20:58 -05:00
Alex King 35fe38cd09 [Quest API] Add Pet Owner Methods to Perl/Lua (#4115)
* [Quest API] Add Pet Owner Methods to Perl/Lua

- Add `$mob->IsPetOwnerBot()`.
- Add `$mob->IsPetOwnerClient()`.
- Add `$mob->IsPetOwnerNPC()`.

- Add `mob:IsPetOwnerBot()`.
- Add `mob:IsPetOwnerClient()`.
- Add `mob:IsPetOwnerNPC()`.

- Allows operators to use these short hands instead of doing a `GetOwner() && GetOwner()->IsClient()`.

* Update npc.cpp
2024-02-25 00:38:34 -05:00
Chris Miles eb3664a444 [Release] 22.45.0 (#4121) 2024-02-24 23:06:37 -06:00
Alex King a244509d63 [Quest API] Export Combat Record to Death Events (#4112)
# Perl
- Add `$combat_start_time`, `$combat_end_time`, `$damage_received`, and `$healing_received` to death events for NPCs.

# Lua
- Add `e.combat_start_time`, `e.combat_end_time`, `e.damage_received`, and `e.healing_received` to death events for NPCs.

# Notes
- Allows operators to hook in to the combat record logic so they can log the start and end of combat as well as the damage/healing received over the course of the fight.
2024-02-24 22:57:49 -06:00
Alex King 873c128f46 [Bug Fix] Fix Bot Weapons with No Races (#4110)
# Notes
- Bot weapons that have no races were not causing damage and saying the target was invulnerable because we were not checking the `Bots:AllowBotEquipAnyRaceGear` rule.
2024-02-24 22:55:40 -06:00
Alex King 8314f2348c [Quest API] Add Bot Methods to Perl/Lua (#4113)
* [Quest API] Add Bot Methods to Perl/Lua

# Perl
- Add `quest::GetBotClassByID(bot_id)`.
- Add `quest::GetBotGenderByID(bot_id)`.
- Add `quest::GetBotIDsByCharacterID(character_id)`.
- Add `quest::GetBotIDsByCharacterID(character_id, class_id)`.
- Add `quest::GetBotLevelByID(bot_id)`.
- Add `quest::GetBotNameByID(bot_id)`.
- Add `quest::GetBotRaceByID(bot_id)`.

# Lua
- Add `eq.get_bot_class_by_id(bot_id)`.
- Add `eq.get_bot_gender_by_id(bot_id)`.
- Add `eq.get_bot_ids_by_character_id(character_id)`.
- Add `eq.get_bot_ids_by_character_id(character_id, class_id)`.
- Add `eq.get_bot_level_by_id(bot_id)`.
- Add `eq.get_bot_name_by_id(bot_id)`.
- Add `eq.get_bot_race_by_id(bot_id)`.

# Notes
- Allows operators to get a list of a player's bot IDs, get a bot's class, gender, level, name, and race.

* Update bot_database.cpp
2024-02-24 22:53:21 -06:00
Alex King 29720f95ed [Quest API] Add GetAugmentIDs() to Perl/Lua (#4114)
# Perl
- Add `$questitem->GetAugmentIDs()`.

# Lua
- Add `iteminst:GetAugmentIDs()`.

# Notes
- Allows operators to get a list of augment IDs from an item instance directly without using the inventory method.
2024-02-24 22:52:07 -06:00
Alex King a478fd2600 [Quest API] Add GetNPCSpellsEffectsID() to Perl/Lua (#4117)
# Perl
- Add `$npc->GetNPCSpellsEffectsID()`.

# Lua
- Add `npc:GetNPCSpellsEffectsID()`.

# Notes
- Allows operator's to get an NPC's spell effects ID.
2024-02-24 22:51:37 -06:00
Alex King f57c37e9c5 [Quest API] Add Pet Methods to Perl/Lua (#4116)
* [Quest API] Add Pet Methods to Perl/Lua

# Perl
- Add `$mob->IsAnimation()`.
- Add `$mob->IsCharmed()`.
- Add `$mob->IsFamiliar()`.
- Add `$mob->IsTargetLockPet()`.

# Lua
- Add `mob:IsAnimation()`.
- Add `mob:IsCharmed()`.
- Add `mob:IsFamiliar()`.
- Add `mob:IsTargetLockPet()`.

# Notes
- These methods were not exported and could be useful for operators.

* Update perl_mob.cpp
2024-02-24 22:51:21 -06:00
Mitch Freeman b9fb4babba [Guilds] Fixes for Guild Bank (#4120)
Updates guild bank functionality
- Allows QTY 100 in guild bank
- Removes bug when deposit area is full and a UF or RoF2 client attempts to deposit another item
- Attempt to deposit a nodrop item in RoF2 creates a dupe situation
2024-02-24 22:50:14 -06:00
Mitch Freeman c2e4082045 [Bug Fix] Crash on Ubuntu 22.04 (#4119)
Ubuntu 22.04 as of Feb 25 2024 was crashing when sending guild tributes on zone in.  Issue was caused by an overrun on string copies.
Updated to use strn0cpy, crash was resolved.
2024-02-24 22:46:42 -06:00
Paul Coene e1dee55ecd [Beacon] Revert a few lines of PR #4024 that broke beacons (#4118) 2024-02-24 16:18:17 -05:00
JJ 1632ff04b0 [Repositories] Update zone base repository from #4084 (#4111) 2024-02-22 21:39:31 -05:00
Fryguy 873209dbc0 [Bug Fix] Fix hotzone string error (#4109)
The Strings entry was from a newer client. Moved text to a raw message.
2024-02-22 17:15:22 -05:00
Mitch Freeman a00b2eb382 [Bug Fix] Added additional Guild-related crash checks (#4105) 2024-02-21 19:44:05 -05:00
Alex King 67d8250b1c [Quest API] Add Hatelist Count Methods to Perl/Lua (#4106)
# Perl
- Add `$mob->GetHateListCount()`.# Perl
- Add `$mob->GetHateListCount()`.
- Add `$mob->GetHateListBotCount()`.
- Add `$mob->GetHateListClientCount()`.
- Add `$mob->GetHateListNPCCount()`.

# Lua
- Add `mob:GetHateListCount()`.
- Add `mob:GetHateListBotCount()`.
- Add `mob:GetHateListClientCount()`.
- Add `mob:GetHateListNPCCount()`.

# Notes
- Allows operators to more easily get a total entity count of a Mob's hate list, can do an overall count, or specifically bots, clients, or NPCs.
2024-02-20 22:39:57 -06:00
Alex King f505c2cfd2 [Feature] Add Augments to Starting Items for Bots/Players (#4100)
* [Feature] Add Augments to Starting Items for Bots/Players

- Adds support for augments to `bot_starting_items` and `starting_items`.
- Will allow operators to kit bots/players out with augmented gear from the start if they so choose.

* Update database_update_manifest.cpp

* Update client.cpp
2024-02-20 22:23:22 -06:00
Fryguy a221e50cc2 [Bug Fix] Add safety check to SummonAllCharacterCorpses. (#4107)
Should prevent an empty vector from being passed to the repository.
2024-02-20 22:21:56 -06:00
JJ 32c5d4d9f6 [Database] Add content_database flag for zone changes (#4104) 2024-02-20 18:03:12 -05:00
Paul Coene ce4716e9a5 [Factions] Fix issue with npcedit and cached factions (#4103)
* [Factions] Fix issue with npcedit and cached factions

* Load no matter what
2024-02-20 17:47:44 -05:00
JJ a99ce4fbdb [Bug Fix] Revert 2df7d19 (#4101)
* [Bug Fix] Revert https://github.com/EQEmu/Server/commit/2df7d19f975cb21dd4eb7d6c7d40656cf58ed138
This change breaks lich-type spells as seen in #4098. Per comment on original change, also don't see where Runes come into play.

* Revert invis change

* [Bug Fix] Correct Rune damage check location for invis break.

Correct the location of the CommonBreakInvis for runes. Appologize for the incorrect location. Thank you JJ for pointing me to the PR that caused the issue.

---------

Co-authored-by: Trust <fryguy503@gmail.com>
2024-02-19 22:35:32 -06:00
JJ dcfc54d408 [Logs] Fix log in BaseGuildManager::IsGuildLeader() (#4102)
Looks like typos created invalid escapes
2024-02-19 22:34:52 -06:00
Alex King c13ec5a06d [Repositories] Cleanup and Convert Character Creation to Repositories (#4053)
* [Repositories] Cleanup and Convert Character Creation to Repositories

# Notes
- Converts `Database::GetCharacterID()`, `Database::SaveCharacterCreate()`, and `Client::OPCharCreate` to repositories.
- Cleanup a spot we were doing a queries in a loop.

* Cleanup

* Update database.cpp

* Update database.cpp
2024-02-19 20:45:18 -06:00
Chris Miles d182fc3613 [Expansions] Zone Expansion Version Routing (#4084)
* Expansion version routing

* CheckForImproperContentFiles rule

* Update world_content_service.cpp

* Update client.cpp

* Update client.cpp

* Update CheckForImproperContentFiles

* Remove nek pok check

* Remove file checking

* Remove

* Command and dev tools menu tweaks

* Update world_content_service.cpp

* Update world_content_service.cpp

* Update version path

* Update content_filter_criteria.h

* Update content_filter_criteria.h

* Update quest_parser_collection.cpp

* Update comments

* PR feedback

* Update client_packet.cpp

* Remove notes column for display cleanliness
2024-02-19 20:35:17 -06:00
Alex King 5a89fcfb78 [Quest API] Add Entity Variable Events to Perl/Lua (#4092)
* [Quest API] Add Entity Variable Events to Perl/Lua

- Add `EVENT_ENTITY_VARIABLE_DELETE`.
- Add `EVENT_ENTITY_VARIABLE_SET`.
- Add `EVENT_ENTITY_VARIABLE_UPDATE`.
- All export `$variable_name` and `$variable_value`.

- Add `event_entity_variable_delete`.
- Add `event_entity_variable_set`.
- Add `event_entity_variable_update`.
- All export `e.variable_name` and `e.variable_value`.

- Allows operators to perform operations when entity variables are cleared, deleted, set, or updated.

* Update mob.cpp

* Cleanup.

* Cleanup

* Update mob.cpp

* Update lua_general.cpp

* Update embparser_api.cpp
2024-02-19 20:34:33 -06:00
Alex King db3601c25c [Quest API] Add Timer Events to Perl/Lua (#4099)
* [Quest API] Add Timer Events to Perl/Lua

# DRAFT

* Cleanup
2024-02-19 03:51:16 -06:00
Alex King 137a9f835a [Quest API] Add spell cast methods to Lua (#4096)
# Notes
- Add `eq.cast_spell(spell_id)` and `eq.self_cast(spell_id)` to Lua.
- Lua did not have a `quest::castspell(spell_id)` or `quest::selfcast(spell_id)` equivalent, so this adds them.
2024-02-19 02:35:30 -06:00
Alex King 4ad46b54df [Bug Fix] Fix Sympathetic Procs for Bots/Mercenariess (#4086)
# Notes
- Bots and Mercenaries were being rejected at the top of this method despite us allowing them to use this method where it's called.
2024-02-19 02:21:47 -06:00
Alex King 3f46210639 [Bots] Cleanup empty bot_commands files (#4095)
* [Bots] Cleanup empty `bot_commands` files

# Notes
- These files were part of the conversion of bot commands to individual files, these commands are part of overarching commands and therefore do not have their own files.
- These were not removed when initially committed.

* Update bot_command.cpp

* Update bot_command.cpp
2024-02-19 02:19:56 -06:00
Alex King 6ec63969bb [Bug Fix] Fix issue with IsEntOnHateList (#4097)
# Notes
- We were not validating pointer in `IsEntOnHateList()`.
2024-02-19 01:52:19 -06:00
JJ 767846f7e5 [Bug Fix] Aura effect spell id from #3964 (#4094)
Auras were trying to cast another aura spell vice the spell effect
2024-02-18 17:13:32 -05:00
Fryguy 04bb9bf39c [Feature] Hot Zone Bonus XP Notice (#4091)
When in Hotzones, a bonus XP notice will let players know the hotzone is enabled.
2024-02-18 11:24:01 -05:00
Mitch Freeman e6df5be1ed [Bug Fix] Update database_schema to add guild_permissions (#4085)
* Update database_schema to add guild_permissions

* Reordered
2024-02-16 18:09:18 -05:00
hg 6bb2f97b74 [Code] Update fmt to 10.2.1 (#4071)
This fixes MSVC compile warnings for stdext::checked_array_iterator
which were deprecated in STL for VS 2022 17.8:

https://github.com/microsoft/STL/wiki/Changelog#vs-2022-178
2024-02-16 00:29:04 -06:00
hg 86f39743fc [Quest API] Add tracebacks to Lua error messages (#4079)
This adds an error msg handler for lua calls to add a stack trace to
error messages. Lua 5.1 does not have luaL_traceback like luajit and lua
5.2+ so debug.traceback() is used directly as the msg handler.

The traceback will add more detail to errors than just logging package
and event names. Exceptions in C++ binds and luabind errors will now
show script context instead of just the error message.

e.g., for a luabind overload error:

  No matching overload found, candidates:
  void signal(int,int,int)
  void signal(int,int)
  stack traceback:
    [C]: in function 'signal'
    quests/arena/player.lua:10: in function 'somefn'
    quests/arena/player.lua:27: in function <quests/arena/player.lua:17>
2024-02-16 00:27:37 -06:00
Alex King 447fc026a8 [Repositories] Convert Zone Flags to Repositories (#4077)
# Notes
- Converts `ClearZoneFlag()`, `LoadZoneFlags()`, and `SetZoneFlag()` to repositories.
2024-02-16 00:27:08 -06:00
Chris Miles 7408df933c [Database] Remove "item_tick" from database schema per https://github.com/EQEmu/Server/pull/3985 (#4083) 2024-02-16 00:23:23 -06:00
JJ 2f59e70c6b [Bug Fix] Fix manifest check on base_data change (#4082) 2024-02-15 19:04:26 -05:00
Alex King eb8514eea8 [Bug Fix] Fix fix_z Query (#4080)
# Notes
- This query was not working properly due to using backticks instead of single quotes.
2024-02-15 11:51:07 -05:00
Alex King f498bac574 [Bug Fix] Fix ObjectContentsRepository using content_db (#4076)
# Notes
- `*this` was using content database, causing this not to work on servers using sharded databases.
2024-02-14 18:34:43 -05:00
Alex King 9a0b3a4c36 [Bug Fix] Fix #wpadd Query (#4078)
# Notes
- `GetNextWaypoint()` was getting a null value and crashing in `Strings::ToInt()`.
2024-02-14 18:28:31 -05:00
Chris Miles 34ea870717 [Opcodes] Fix opcode reloading (#4075) 2024-02-13 19:40:23 -05:00
Alex King d68c1a7a6c [Quest API] Add IsInAGuild() to Perl/Lua (#4066)
# Perl
- Add `$client->IsInAGuild()`.

# Lua
- Add `client:IsInAGuild()`.

# Notes
- Allows operators to more accurately tell if a player is in a group.
- `GuildID()` returns `uint32` max value if the player isn't in a guild so conditions using it must check for a value over a certain point, this is just a bool that simplifies that logic.
2024-02-13 19:27:43 -05:00
Akkadius c50100fcdb [Hotfix] Fix issues where we're using the wrong database pointers 2024-02-12 21:41:52 -06:00
JJ 20cdc1e63d [Release] 22.44.4 (#4074)
### Fixes

* Fix ClearSpawnTimers() ([#4073](https://github.com/EQEmu/Server/pull/4073)) @Kinglykrab 2024-02-13
2024-02-12 20:34:40 -06:00
Alex King 43c7523ee1 [Hotfix] Fix ClearSpawnTimers() (#4073)
# Notes
- This wasn't a part of my other pull request.
- We were clearing `spawn2_list` before using it in `ClearSpawnTimers()`.
2024-02-12 21:12:30 -05:00
JJ e060d97798 [Release] 22.44.3 (#4072)
### Fixes

* Fix Issue with ClearSpawnTimers() ([#4070](https://github.com/EQEmu/Server/pull/4070)) @Kinglykrab 2024-02-13
2024-02-12 19:20:04 -06:00
Alex King 435b6142b8 [Bug Fix] Fix Issue with ClearSpawnTimers() (#4070)
# Notes
- We were using the improper ID for this and not checking if the vector was empty before using.
2024-02-12 20:00:45 -05:00
100 changed files with 3897 additions and 1641 deletions
+103
View File
@@ -1,3 +1,106 @@
## [22.45.0] 2/24/2024
### Beacon
* Revert a few lines of PR #4024 that broke beacons ([#4118](https://github.com/EQEmu/Server/pull/4118)) @noudess 2024-02-24
### Bots
* Cleanup empty `bot_commands` files ([#4095](https://github.com/EQEmu/Server/pull/4095)) @Kinglykrab 2024-02-19
* Remove Alt Combat Functionality ([#4067](https://github.com/EQEmu/Server/pull/4067)) @Kinglykrab 2024-02-12
### Code
* Update fmt to 10.2.1 ([#4071](https://github.com/EQEmu/Server/pull/4071)) @hgtw 2024-02-16
* Use explicit conversions for enum formatting ([#4064](https://github.com/EQEmu/Server/pull/4064)) @hgtw 2024-02-12
### Database
* Add content_database flag for zone changes ([#4104](https://github.com/EQEmu/Server/pull/4104)) @joligario 2024-02-20
* Remove "item_tick" from database schema per https://github.com/EQEmu/Server/pull/3985 ([#4083](https://github.com/EQEmu/Server/pull/4083)) @Akkadius 2024-02-16
### Expansions
* Zone Expansion Version Routing ([#4084](https://github.com/EQEmu/Server/pull/4084)) @Akkadius 2024-02-20
### Factions
* Fix issue with npcedit and cached factions ([#4103](https://github.com/EQEmu/Server/pull/4103)) @noudess 2024-02-20
### Feature
* Add Augments to Starting Items for Bots/Players ([#4100](https://github.com/EQEmu/Server/pull/4100)) @Kinglykrab 2024-02-21
* Hot Zone Bonus XP Notice ([#4091](https://github.com/EQEmu/Server/pull/4091)) @fryguy503 2024-02-18
### Fixes
* Add safety check to SummonAllCharacterCorpses. ([#4107](https://github.com/EQEmu/Server/pull/4107)) @fryguy503 2024-02-21
* Added additional Guild-related crash checks ([#4105](https://github.com/EQEmu/Server/pull/4105)) @neckkola 2024-02-22
* Aura effect spell id from #3964 ([#4094](https://github.com/EQEmu/Server/pull/4094)) @joligario 2024-02-18
* Crash on Ubuntu 22.04 ([#4119](https://github.com/EQEmu/Server/pull/4119)) @neckkola 2024-02-25
* Fix #wpadd Query ([#4078](https://github.com/EQEmu/Server/pull/4078)) @Kinglykrab 2024-02-14
* Fix Bot Weapons with No Races ([#4110](https://github.com/EQEmu/Server/pull/4110)) @Kinglykrab 2024-02-25
* Fix ClearSpawnTimers() ([#4073](https://github.com/EQEmu/Server/pull/4073)) @Kinglykrab 2024-02-13
* Fix Issue with ClearSpawnTimers() ([#4070](https://github.com/EQEmu/Server/pull/4070)) @Kinglykrab 2024-02-13
* Fix ObjectContentsRepository using content_db ([#4076](https://github.com/EQEmu/Server/pull/4076)) @Kinglykrab 2024-02-14
* Fix Sympathetic Procs for Bots/Mercenariess ([#4086](https://github.com/EQEmu/Server/pull/4086)) @Kinglykrab 2024-02-19
* Fix fix_z Query ([#4080](https://github.com/EQEmu/Server/pull/4080)) @Kinglykrab 2024-02-15
* Fix hotzone string error ([#4109](https://github.com/EQEmu/Server/pull/4109)) @fryguy503 2024-02-22
* Fix issue with IsEntOnHateList ([#4097](https://github.com/EQEmu/Server/pull/4097)) @Kinglykrab 2024-02-19
* Fix manifest check on `base_data` change ([#4082](https://github.com/EQEmu/Server/pull/4082)) @joligario 2024-02-16
* Revert 2df7d19 ([#4101](https://github.com/EQEmu/Server/pull/4101)) @joligario 2024-02-20
* Update database_schema to add guild_permissions ([#4085](https://github.com/EQEmu/Server/pull/4085)) @neckkola 2024-02-16
### Guilds
* Fixes for Guild Bank ([#4120](https://github.com/EQEmu/Server/pull/4120)) @neckkola 2024-02-25
### Logs
* Fix log in BaseGuildManager::IsGuildLeader() ([#4102](https://github.com/EQEmu/Server/pull/4102)) @joligario 2024-02-20
### Opcodes
* Fix opcode reloading ([#4075](https://github.com/EQEmu/Server/pull/4075)) @Akkadius 2024-02-14
### Quest API
* Add Bot Methods to Perl/Lua ([#4113](https://github.com/EQEmu/Server/pull/4113)) @Kinglykrab 2024-02-25
* Add Entity Variable Events to Perl/Lua ([#4092](https://github.com/EQEmu/Server/pull/4092)) @Kinglykrab 2024-02-20
* Add GetAugmentIDs() to Perl/Lua ([#4114](https://github.com/EQEmu/Server/pull/4114)) @Kinglykrab 2024-02-25
* Add GetNPCSpellsEffectsID() to Perl/Lua ([#4117](https://github.com/EQEmu/Server/pull/4117)) @Kinglykrab 2024-02-25
* Add Hatelist Count Methods to Perl/Lua ([#4106](https://github.com/EQEmu/Server/pull/4106)) @Kinglykrab 2024-02-21
* Add IsInAGuild() to Perl/Lua ([#4066](https://github.com/EQEmu/Server/pull/4066)) @Kinglykrab 2024-02-14
* Add Pet Methods to Perl/Lua ([#4116](https://github.com/EQEmu/Server/pull/4116)) @Kinglykrab 2024-02-25
* Add Timer Events to Perl/Lua ([#4099](https://github.com/EQEmu/Server/pull/4099)) @Kinglykrab 2024-02-19
* Add spell cast methods to Lua ([#4096](https://github.com/EQEmu/Server/pull/4096)) @Kinglykrab 2024-02-19
* Add tracebacks to Lua error messages ([#4079](https://github.com/EQEmu/Server/pull/4079)) @hgtw 2024-02-16
* Export Combat Record to Death Events ([#4112](https://github.com/EQEmu/Server/pull/4112)) @Kinglykrab 2024-02-25
### Repositories
* Cleanup and Convert Character Creation to Repositories ([#4053](https://github.com/EQEmu/Server/pull/4053)) @Kinglykrab 2024-02-20
* Convert Zone Flags to Repositories ([#4077](https://github.com/EQEmu/Server/pull/4077)) @Kinglykrab 2024-02-16
* Update `zone` base repository from #4084 ([#4111](https://github.com/EQEmu/Server/pull/4111)) @joligario 2024-02-23
## [22.44.5] - 2/12/2024
### Fixes
* [Hotfix] Fix issues where we're using the wrong database pointers @Akkadius
## [22.44.4] - 2/12/2024
### Fixes
* Fix ClearSpawnTimers() ([#4073](https://github.com/EQEmu/Server/pull/4073)) @Kinglykrab 2024-02-13
## [22.44.3] - 2/12/2024
### Fixes
* Fix Issue with ClearSpawnTimers() ([#4070](https://github.com/EQEmu/Server/pull/4070)) @Kinglykrab 2024-02-13
## [22.44.2] - 2/12/2024
### Bots
+102 -24
View File
@@ -1,28 +1,11 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "world_content_service.h"
#include <utility>
#include <glm/vec3.hpp>
#include "../database.h"
#include "../rulesys.h"
#include "../eqemu_logsys.h"
#include "../repositories/content_flags_repository.h"
#include "../repositories/instance_list_repository.h"
WorldContentService::WorldContentService()
@@ -119,7 +102,7 @@ std::vector<std::string> WorldContentService::GetContentFlagsDisabled()
/**
* @param content_flags
*/
void WorldContentService::SetContentFlags(const std::vector<ContentFlagsRepository::ContentFlags>& content_flags)
void WorldContentService::SetContentFlags(const std::vector<ContentFlagsRepository::ContentFlags> &content_flags)
{
WorldContentService::content_flags = content_flags;
}
@@ -167,14 +150,14 @@ bool WorldContentService::DoesPassContentFiltering(const ContentFlags &f)
}
// if we don't have any enabled flag in enabled flags, we fail
for (const auto& flag: Strings::Split(f.content_flags)) {
for (const auto &flag: Strings::Split(f.content_flags)) {
if (!Strings::Contains(GetContentFlagsEnabled(), flag)) {
return false;
}
}
// if we don't have any disabled flag in disabled flags, we fail
for (const auto& flag: Strings::Split(f.content_flags_disabled)) {
for (const auto &flag: Strings::Split(f.content_flags_disabled)) {
if (!Strings::Contains(GetContentFlagsDisabled(), flag)) {
return false;
}
@@ -200,6 +183,7 @@ void WorldContentService::ReloadContentFlags()
}
SetContentFlags(set_content_flags);
SetContentZones(ZoneRepository::All(*m_content_database));
}
Database *WorldContentService::GetDatabase() const
@@ -214,6 +198,18 @@ WorldContentService *WorldContentService::SetDatabase(Database *database)
return this;
}
Database *WorldContentService::GetContentDatabase() const
{
return m_content_database;
}
WorldContentService *WorldContentService::SetContentDatabase(Database *database)
{
WorldContentService::m_content_database = database;
return this;
}
void WorldContentService::SetContentFlag(const std::string &content_flag_name, bool enabled)
{
auto flags = ContentFlagsRepository::GetWhere(
@@ -238,3 +234,85 @@ void WorldContentService::SetContentFlag(const std::string &content_flag_name, b
ReloadContentFlags();
}
// SetZones sets the zones for the world content service
// this is used for zone routing middleware
// we pull the zone list from the zone repository and feed from the zone store for now
// we're holding a copy in the content service - but we're talking 250kb of data in memory to handle routing of zoning
WorldContentService *WorldContentService::SetContentZones(const std::vector<BaseZoneRepository::Zone>& zones)
{
m_zones = zones;
LogInfo("Loaded [{}] zones", m_zones.size());
return this;
}
// HandleZoneRoutingMiddleware is meant to handle content and context aware zone routing
//
// example # 1
// lavastorm (pre-don) version 0 (classic)
// lavastorm (don) version 1
// we want to route players to the correct version of lavastorm based on the current server side expansion
// in order to do that the simplest and cleanest way we intercept the zoning process and route players to an "instance" of the zone
// the reason why we're doing this is because all of the zoning logic already is handled by two keys "zone_id" and "instance_id"
// we can leverage static, never expires instances to handle this but to the client they don't see it any other way than a public normal zone
// scripts handle all the same way, you don't have to think about instances, the middleware will handle the magic
// the versions of zones are represented by two zone entries that have potentially different min/max expansion and/or different content flags
// we decide to route the client to the correct version of the zone based on the current server side expansion
// example # 2
void WorldContentService::HandleZoneRoutingMiddleware(ZoneChange_Struct *zc)
{
// if we're already in an instance, we don't want to route the player to another instance
if (zc->instanceID > 0) {
return;
}
for (auto &z: m_zones) {
if (z.zoneidnumber == zc->zoneID) {
auto f = ContentFlags{
.min_expansion = z.min_expansion,
.max_expansion = z.max_expansion,
.content_flags = z.content_flags,
.content_flags_disabled = z.content_flags_disabled
};
if (DoesPassContentFiltering(f)) {
LogInfo(
"Attempting to route player to zone [{}] ({}) version [{}] long_name [{}]",
z.short_name,
z.zoneidnumber,
z.version,
z.long_name
);
auto instances = InstanceListRepository::GetWhere(
*GetDatabase(),
fmt::format(
"zone = {} AND version = {} AND never_expires = 1 AND is_global = 1",
z.zoneidnumber,
z.version
)
);
if (!instances.empty()) {
auto instance = instances.front();
zc->instanceID = instance.id;
LogInfo(
"Routed player to instance [{}] of zone [{}] ({}) version [{}] long_name [{}] notes [{}]",
instance.id,
z.short_name,
z.zoneidnumber,
z.version,
z.long_name,
instance.notes
);
break;
}
}
}
}
}
+10 -20
View File
@@ -1,29 +1,10 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef EQEMU_WORLD_CONTENT_SERVICE_H
#define EQEMU_WORLD_CONTENT_SERVICE_H
#include <string>
#include <vector>
#include "../repositories/content_flags_repository.h"
#include "../repositories/zone_repository.h"
class Database;
@@ -182,14 +163,23 @@ public:
WorldContentService * SetDatabase(Database *database);
Database *GetDatabase() const;
WorldContentService * SetContentDatabase(Database *database);
Database *GetContentDatabase() const;
void SetContentFlag(const std::string &content_flag_name, bool enabled);
void HandleZoneRoutingMiddleware(ZoneChange_Struct *zc);
WorldContentService * SetContentZones(const std::vector<ZoneRepository::Zone>& zones);
private:
int current_expansion{};
std::vector<ContentFlagsRepository::ContentFlags> content_flags;
// reference to database
Database *m_database;
Database *m_content_database;
// holds a record of the zone table from the database
std::vector<ZoneRepository::Zone> m_zones = {};
};
extern WorldContentService content_service;
+167 -340
View File
@@ -30,6 +30,11 @@
#include <string.h>
#include "../common/repositories/account_repository.h"
#include "../common/repositories/character_bind_repository.h"
#include "../common/repositories/character_data_repository.h"
#include "../common/repositories/character_languages_repository.h"
#include "../common/repositories/character_leadership_abilities_repository.h"
#include "../common/repositories/character_skills_repository.h"
// Disgrace: for windows compile
#ifdef _WINDOWS
@@ -454,363 +459,185 @@ bool Database::DeleteCharacter(char *character_name)
bool Database::SaveCharacterCreate(uint32 character_id, uint32 account_id, PlayerProfile_Struct *pp)
{
std::string query = StringFormat(
"REPLACE INTO `character_data` ("
"id,"
"account_id,"
"`name`,"
"last_name,"
"gender,"
"race,"
"class,"
"`level`,"
"deity,"
"birthday,"
"last_login,"
"time_played,"
"pvp_status,"
"level2,"
"anon,"
"gm,"
"intoxication,"
"hair_color,"
"beard_color,"
"eye_color_1,"
"eye_color_2,"
"hair_style,"
"beard,"
"ability_time_seconds,"
"ability_number,"
"ability_time_minutes,"
"ability_time_hours,"
"title,"
"suffix,"
"exp,"
"points,"
"mana,"
"cur_hp,"
"str,"
"sta,"
"cha,"
"dex,"
"`int`,"
"agi,"
"wis,"
"face,"
"y,"
"x,"
"z,"
"heading,"
"pvp2,"
"pvp_type,"
"autosplit_enabled,"
"zone_change_count,"
"drakkin_heritage,"
"drakkin_tattoo,"
"drakkin_details,"
"toxicity,"
"hunger_level,"
"thirst_level,"
"ability_up,"
"zone_id,"
"zone_instance,"
"leadership_exp_on,"
"ldon_points_guk,"
"ldon_points_mir,"
"ldon_points_mmc,"
"ldon_points_ruj,"
"ldon_points_tak,"
"ldon_points_available,"
"tribute_time_remaining,"
"show_helm,"
"career_tribute_points,"
"tribute_points,"
"tribute_active,"
"endurance,"
"group_leadership_exp,"
"raid_leadership_exp,"
"group_leadership_points,"
"raid_leadership_points,"
"air_remaining,"
"pvp_kills,"
"pvp_deaths,"
"pvp_current_points,"
"pvp_career_points,"
"pvp_best_kill_streak,"
"pvp_worst_death_streak,"
"pvp_current_kill_streak,"
"aa_points_spent,"
"aa_exp,"
"aa_points,"
"group_auto_consent,"
"raid_auto_consent,"
"guild_auto_consent,"
"RestTimer) "
"VALUES ("
"%u," // id
"%u," // account_id
"'%s'," // `name`
"'%s'," // last_name
"%u," // gender
"%u," // race
"%u," // class
"%u," // `level`
"%u," // deity
"%u," // birthday
"%u," // last_login
"%u," // time_played
"%u," // pvp_status
"%u," // level2
"%u," // anon
"%u," // gm
"%u," // intoxication
"%u," // hair_color
"%u," // beard_color
"%u," // eye_color_1
"%u," // eye_color_2
"%u," // hair_style
"%u," // beard
"%u," // ability_time_seconds
"%u," // ability_number
"%u," // ability_time_minutes
"%u," // ability_time_hours
"'%s'," // title
"'%s'," // suffix
"%u," // exp
"%u," // points
"%u," // mana
"%u," // cur_hp
"%u," // str
"%u," // sta
"%u," // cha
"%u," // dex
"%u," // `int`
"%u," // agi
"%u," // wis
"%u," // face
"%f," // y
"%f," // x
"%f," // z
"%f," // heading
"%u," // pvp2
"%u," // pvp_type
"%u," // autosplit_enabled
"%u," // zone_change_count
"%u," // drakkin_heritage
"%u," // drakkin_tattoo
"%u," // drakkin_details
"%i," // toxicity
"%i," // hunger_level
"%i," // thirst_level
"%u," // ability_up
"%u," // zone_id
"%u," // zone_instance
"%u," // leadership_exp_on
"%u," // ldon_points_guk
"%u," // ldon_points_mir
"%u," // ldon_points_mmc
"%u," // ldon_points_ruj
"%u," // ldon_points_tak
"%u," // ldon_points_available
"%u," // tribute_time_remaining
"%u," // show_helm
"%u," // career_tribute_points
"%u," // tribute_points
"%u," // tribute_active
"%u," // endurance
"%u," // group_leadership_exp
"%u," // raid_leadership_exp
"%u," // group_leadership_point
"%u," // raid_leadership_points
"%u," // air_remaining
"%u," // pvp_kills
"%u," // pvp_deaths
"%u," // pvp_current_points
"%u," // pvp_career_points
"%u," // pvp_best_kill_streak
"%u," // pvp_worst_death_streak
"%u," // pvp_current_kill_strea
"%u," // aa_points_spent
"%u," // aa_exp
"%u," // aa_points
"%u," // group_auto_consent
"%u," // raid_auto_consent
"%u," // guild_auto_consent
"%u" // RestTimer
")",
character_id, // " id, "
account_id, // " account_id, "
Strings::Escape(pp->name).c_str(), // " `name`, "
Strings::Escape(pp->last_name).c_str(), // " last_name, "
pp->gender, // " gender, "
pp->race, // " race, "
pp->class_, // " class, "
pp->level, // " `level`, "
pp->deity, // " deity, "
pp->birthday, // " birthday, "
pp->lastlogin, // " last_login, "
pp->timePlayedMin, // " time_played, "
pp->pvp, // " pvp_status, "
pp->level2, // " level2, "
pp->anon, // " anon, "
pp->gm, // " gm, "
pp->intoxication, // " intoxication, "
pp->haircolor, // " hair_color, "
pp->beardcolor, // " beard_color, "
pp->eyecolor1, // " eye_color_1, "
pp->eyecolor2, // " eye_color_2, "
pp->hairstyle, // " hair_style, "
pp->beard, // " beard, "
pp->ability_time_seconds, // " ability_time_seconds, "
pp->ability_number, // " ability_number, "
pp->ability_time_minutes, // " ability_time_minutes, "
pp->ability_time_hours, // " ability_time_hours, "
Strings::Escape(pp->title).c_str(), // " title, "
Strings::Escape(pp->suffix).c_str(), // " suffix, "
pp->exp, // " exp, "
pp->points, // " points, "
pp->mana, // " mana, "
pp->cur_hp, // " cur_hp, "
pp->STR, // " str, "
pp->STA, // " sta, "
pp->CHA, // " cha, "
pp->DEX, // " dex, "
pp->INT, // " `int`, "
pp->AGI, // " agi, "
pp->WIS, // " wis, "
pp->face, // " face, "
pp->y, // " y, "
pp->x, // " x, "
pp->z, // " z, "
pp->heading, // " heading, "
pp->pvp2, // " pvp2, "
pp->pvptype, // " pvp_type, "
pp->autosplit, // " autosplit_enabled, "
pp->zone_change_count, // " zone_change_count, "
pp->drakkin_heritage, // " drakkin_heritage, "
pp->drakkin_tattoo, // " drakkin_tattoo, "
pp->drakkin_details, // " drakkin_details, "
pp->toxicity, // " toxicity, "
pp->hunger_level, // " hunger_level, "
pp->thirst_level, // " thirst_level, "
pp->ability_up, // " ability_up, "
pp->zone_id, // " zone_id, "
pp->zoneInstance, // " zone_instance, "
pp->leadAAActive, // " leadership_exp_on, "
pp->ldon_points_guk, // " ldon_points_guk, "
pp->ldon_points_mir, // " ldon_points_mir, "
pp->ldon_points_mmc, // " ldon_points_mmc, "
pp->ldon_points_ruj, // " ldon_points_ruj, "
pp->ldon_points_tak, // " ldon_points_tak, "
pp->ldon_points_available, // " ldon_points_available, "
pp->tribute_time_remaining, // " tribute_time_remaining, "
pp->showhelm, // " show_helm, "
pp->career_tribute_points, // " career_tribute_points, "
pp->tribute_points, // " tribute_points, "
pp->tribute_active, // " tribute_active, "
pp->endurance, // " endurance, "
pp->group_leadership_exp, // " group_leadership_exp, "
pp->raid_leadership_exp, // " raid_leadership_exp, "
pp->group_leadership_points, // " group_leadership_points, "
pp->raid_leadership_points, // " raid_leadership_points, "
pp->air_remaining, // " air_remaining, "
pp->PVPKills, // " pvp_kills, "
pp->PVPDeaths, // " pvp_deaths, "
pp->PVPCurrentPoints, // " pvp_current_points, "
pp->PVPCareerPoints, // " pvp_career_points, "
pp->PVPBestKillStreak, // " pvp_best_kill_streak, "
pp->PVPWorstDeathStreak, // " pvp_worst_death_streak, "
pp->PVPCurrentKillStreak, // " pvp_current_kill_streak, "
pp->aapoints_spent, // " aa_points_spent, "
pp->expAA, // " aa_exp, "
pp->aapoints, // " aa_points, "
pp->groupAutoconsent, // " group_auto_consent, "
pp->raidAutoconsent, // " raid_auto_consent, "
pp->guildAutoconsent, // " guild_auto_consent, "
pp->RestTimer // " RestTimer) "
);
QueryDatabase(query);
auto c = CharacterDataRepository::NewEntity();
/* Save Bind Points */
query = StringFormat(
"REPLACE INTO `character_bind` (id, zone_id, instance_id, x, y, z, heading, slot)"
" VALUES (%u, %u, %u, %f, %f, %f, %f, %i), "
"(%u, %u, %u, %f, %f, %f, %f, %i), "
"(%u, %u, %u, %f, %f, %f, %f, %i), "
"(%u, %u, %u, %f, %f, %f, %f, %i), "
"(%u, %u, %u, %f, %f, %f, %f, %i)",
character_id, pp->binds[0].zone_id, 0, pp->binds[0].x, pp->binds[0].y, pp->binds[0].z, pp->binds[0].heading, 0,
character_id, pp->binds[1].zone_id, 0, pp->binds[1].x, pp->binds[1].y, pp->binds[1].z, pp->binds[1].heading, 1,
character_id, pp->binds[2].zone_id, 0, pp->binds[2].x, pp->binds[2].y, pp->binds[2].z, pp->binds[2].heading, 2,
character_id, pp->binds[3].zone_id, 0, pp->binds[3].x, pp->binds[3].y, pp->binds[3].z, pp->binds[3].heading, 3,
character_id, pp->binds[4].zone_id, 0, pp->binds[4].x, pp->binds[4].y, pp->binds[4].z, pp->binds[4].heading, 4
);
QueryDatabase(query);
c.id = character_id;
c.account_id = account_id;
c.name = pp->name;
c.last_name = pp->last_name;
c.gender = pp->gender;
c.race = pp->race;
c.class_ = pp->class_;
c.level = pp->level;
c.deity = pp->deity;
c.birthday = pp->birthday;
c.last_login = pp->lastlogin;
c.time_played = pp->timePlayedMin;
c.pvp_status = pp->pvp;
c.level2 = pp->level2;
c.anon = pp->anon;
c.gm = pp->gm;
c.intoxication = pp->intoxication;
c.hair_color = pp->haircolor;
c.beard_color = pp->beardcolor;
c.eye_color_1 = pp->eyecolor1;
c.eye_color_2 = pp->eyecolor2;
c.hair_style = pp->hairstyle;
c.beard = pp->beard;
c.ability_time_seconds = pp->ability_time_seconds;
c.ability_number = pp->ability_number;
c.ability_time_minutes = pp->ability_time_minutes;
c.ability_time_hours = pp->ability_time_hours;
c.title = pp->title;
c.suffix = pp->suffix;
c.exp = pp->exp;
c.points = pp->points;
c.mana = pp->mana;
c.cur_hp = pp->cur_hp;
c.str = pp->STR;
c.sta = pp->STA;
c.cha = pp->CHA;
c.dex = pp->DEX;
c.int_ = pp->INT;
c.agi = pp->AGI;
c.wis = pp->WIS;
c.face = pp->face;
c.y = pp->y;
c.x = pp->x;
c.z = pp->z;
c.heading = pp->heading;
c.pvp2 = pp->pvp2;
c.pvp_type = pp->pvptype;
c.autosplit_enabled = pp->autosplit;
c.zone_change_count = pp->zone_change_count;
c.drakkin_heritage = pp->drakkin_heritage;
c.drakkin_tattoo = pp->drakkin_tattoo;
c.drakkin_details = pp->drakkin_details;
c.toxicity = pp->toxicity;
c.hunger_level = pp->hunger_level;
c.thirst_level = pp->thirst_level;
c.ability_up = pp->ability_up;
c.zone_id = pp->zone_id;
c.zone_instance = pp->zoneInstance;
c.leadership_exp_on = pp->leadAAActive;
c.ldon_points_guk = pp->ldon_points_guk;
c.ldon_points_mir = pp->ldon_points_mir;
c.ldon_points_mmc = pp->ldon_points_mmc;
c.ldon_points_ruj = pp->ldon_points_ruj;
c.ldon_points_tak = pp->ldon_points_tak;
c.ldon_points_available = pp->ldon_points_available;
c.tribute_time_remaining = pp->tribute_time_remaining;
c.show_helm = pp->showhelm;
c.career_tribute_points = pp->career_tribute_points;
c.tribute_points = pp->tribute_points;
c.tribute_active = pp->tribute_active;
c.endurance = pp->endurance;
c.group_leadership_exp = pp->group_leadership_exp;
c.raid_leadership_exp = pp->raid_leadership_exp;
c.group_leadership_points = pp->group_leadership_points;
c.raid_leadership_points = pp->raid_leadership_points;
c.air_remaining = pp->air_remaining;
c.pvp_kills = pp->PVPKills;
c.pvp_deaths = pp->PVPDeaths;
c.pvp_current_points = pp->PVPCurrentPoints;
c.pvp_career_points = pp->PVPCareerPoints;
c.pvp_best_kill_streak = pp->PVPBestKillStreak;
c.pvp_worst_death_streak = pp->PVPWorstDeathStreak;
c.pvp_current_kill_streak = pp->PVPCurrentKillStreak;
c.aa_points_spent = pp->aapoints_spent;
c.aa_exp = pp->expAA;
c.aa_points = pp->aapoints;
c.group_auto_consent = pp->groupAutoconsent;
c.raid_auto_consent = pp->raidAutoconsent;
c.guild_auto_consent = pp->guildAutoconsent;
c.RestTimer = pp->RestTimer;
CharacterDataRepository::ReplaceOne(*this, c);
std::vector<CharacterBindRepository::CharacterBind> character_binds;
character_binds.reserve(5);
auto b = CharacterBindRepository::NewEntity();
b.id = character_id;
for (uint8 slot_id = 0; slot_id < 5; slot_id++) {
b.zone_id = pp->binds[slot_id].zone_id;
b.x = pp->binds[slot_id].x;
b.y = pp->binds[slot_id].y;
b.z = pp->binds[slot_id].z;
b.heading = pp->binds[slot_id].heading;
b.slot = slot_id;
character_binds.emplace_back(b);
}
CharacterBindRepository::ReplaceMany(*this, character_binds);
/* HoTT Ability */
if (RuleB(Character, GrantHoTTOnCreate)) {
query = StringFormat(
"INSERT INTO `character_leadership_abilities` (id, slot, `rank`) VALUES (%u, %i, %i)",
character_id,
14,
1
CharacterLeadershipAbilitiesRepository::InsertOne(
*this,
CharacterLeadershipAbilitiesRepository::CharacterLeadershipAbilities{
.id = character_id,
.slot = LeadershipAbilitySlot::HealthOfTargetsTarget,
.rank_ = 1
}
);
QueryDatabase(query);
}
/* Save Skills */
int firstquery = 0;
for (int i = 0; i < MAX_PP_SKILL; i++) {
if (pp->skills[i] > 0) {
if (firstquery != 1) {
firstquery = 1;
query = StringFormat(
"REPLACE INTO `character_skills` (id, skill_id, value) VALUES (%u, %u, %u)",
character_id,
i,
pp->skills[i]
);
} else {
query = query + StringFormat(", (%u, %u, %u)", character_id, i, pp->skills[i]);
}
}
}
QueryDatabase(query);
std::vector<CharacterSkillsRepository::CharacterSkills> character_skills;
/* Save Language */
firstquery = 0;
for (int i = 0; i < MAX_PP_LANGUAGE; i++) {
if (pp->languages[i] > 0) {
if (firstquery != 1) {
firstquery = 1;
query = StringFormat(
"REPLACE INTO `character_languages` (id, lang_id, value) VALUES (%u, %u, %u)",
character_id,
i,
pp->languages[i]
);
} else {
query = query + StringFormat(", (%u, %u, %u)", character_id, i, pp->languages[i]);
character_skills.reserve(MAX_PP_SKILL);
for (uint16 slot_id = 0; slot_id < MAX_PP_SKILL; slot_id++) {
character_skills.emplace_back(
CharacterSkillsRepository::CharacterSkills{
.id = character_id,
.skill_id = slot_id,
.value = static_cast<uint16_t>(pp->skills[slot_id])
}
}
);
}
QueryDatabase(query);
CharacterSkillsRepository::ReplaceMany(*this, character_skills);
std::vector<CharacterLanguagesRepository::CharacterLanguages> character_languages;
character_languages.reserve(MAX_PP_LANGUAGE);
for (uint16 slot_id = 0; slot_id < MAX_PP_LANGUAGE; slot_id++) {
character_languages.emplace_back(
CharacterLanguagesRepository::CharacterLanguages{
.id = character_id,
.lang_id = slot_id,
.value = static_cast<uint16_t>(pp->languages[slot_id])
}
);
}
CharacterLanguagesRepository::ReplaceMany(*this, character_languages);
return true;
}
uint32 Database::GetCharacterID(const char *name) {
const auto query = fmt::format(
"SELECT `id` FROM `character_data` WHERE `name` = '{}'",
Strings::Escape(name)
uint32 Database::GetCharacterID(const std::string& name)
{
const auto& l = CharacterDataRepository::GetWhere(
*this,
fmt::format(
"`name` = '{}'",
Strings::Escape(name)
)
);
auto results = QueryDatabase(query);
if (!results.Success() || !results.RowCount()) {
if (l.empty()) {
return 0;
}
auto row = results.begin();
return Strings::ToUnsignedInt(row[0]);
auto e = l.front();
return e.id;
}
/*
+1 -1
View File
@@ -125,7 +125,7 @@ public:
uint32 GetAccountIDByChar(const char* charname, uint32* oCharID = 0);
uint32 GetAccountIDByChar(uint32 char_id);
uint32 GetAccountIDByName(std::string account_name, std::string loginserver, int16* status = 0, uint32* lsid = 0);
uint32 GetCharacterID(const char *name);
uint32 GetCharacterID(const std::string& name);
uint32 GetCharacterInfo(std::string character_name, uint32 *account_id, uint32 *zone_id, uint32 *instance_id);
uint32 GetGuildIDByCharID(uint32 char_id);
uint32 GetGroupIDByCharID(uint32 char_id);
+47 -2
View File
@@ -5247,7 +5247,7 @@ MODIFY COLUMN `name` varchar(200) CHARACTER SET latin1 COLLATE latin1_swedish_ci
ManifestEntry{
.version = 9257,
.description = "2024_01_16_ground_spawns_fix_z.sql",
.check = "SHOW COLUMNS FROM `ground_spawns` LIKE `fix_z`",
.check = "SHOW COLUMNS FROM `ground_spawns` LIKE 'fix_z'",
.condition = "empty",
.match = "",
.sql = R"(
@@ -5259,7 +5259,7 @@ ADD COLUMN `fix_z` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 AFTER `respawn_timer`;
ManifestEntry{
.version = 9258,
.description = "2024_02_04_base_data.sql",
.check = "SHOW COLUMNS FROM `base_data` LIKE `hp_regen`",
.check = "SHOW COLUMNS FROM `base_data` LIKE 'hp_regen'",
.condition = "empty",
.match = "",
.sql = R"(
@@ -5365,6 +5365,51 @@ ALTER TABLE `character_corpses` MODIFY COLUMN `time_of_death` datetime NOT NULL
.sql = R"(
ALTER TABLE `object_contents` MODIFY COLUMN `droptime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP;
)"
},
ManifestEntry{
.version = 9263,
.description = "2024_02_16_rearrange_zone_columns.sql",
.check = "show columns from zone like 'note'",
.condition = "missing",
.match = "varchar(200)",
.sql = R"(
ALTER TABLE `zone`
MODIFY COLUMN `id` int(10) NOT NULL AUTO_INCREMENT FIRST,
MODIFY COLUMN `zoneidnumber` int(4) NOT NULL DEFAULT 0 AFTER `id`,
MODIFY COLUMN `version` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `zoneidnumber`,
MODIFY COLUMN `short_name` varchar(32) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `version`,
MODIFY COLUMN `long_name` text CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL AFTER `short_name`,
MODIFY COLUMN `min_status` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `long_name`,
MODIFY COLUMN `note` varchar(200) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `map_file_name`,
MODIFY COLUMN `min_expansion` tinyint(4) NOT NULL DEFAULT -1 AFTER `note`,
MODIFY COLUMN `max_expansion` tinyint(4) NOT NULL DEFAULT -1 AFTER `min_expansion`,
MODIFY COLUMN `content_flags` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `max_expansion`,
MODIFY COLUMN `content_flags_disabled` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `content_flags`,
MODIFY COLUMN `expansion` tinyint(3) NOT NULL DEFAULT 0 AFTER `content_flags_disabled`,
MODIFY COLUMN `file_name` varchar(16) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL AFTER `expansion`,
MODIFY COLUMN `safe_x` float NOT NULL DEFAULT 0 AFTER `file_name`,
MODIFY COLUMN `safe_y` float NOT NULL DEFAULT 0 AFTER `safe_x`,
MODIFY COLUMN `safe_z` float NOT NULL DEFAULT 0 AFTER `safe_y`,
MODIFY COLUMN `safe_heading` float NOT NULL DEFAULT 0 AFTER `safe_z`;
)",
.content_schema_update = true
},
ManifestEntry{
.version = 9264,
.description = "2024_02_18_starting_items_augments.sql",
.check = "SHOW COLUMNS FROM `starting_items` LIKE 'augment_one'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `starting_items`
ADD COLUMN `augment_one` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `item_charges`,
ADD COLUMN `augment_two` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_one`,
ADD COLUMN `augment_three` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_two`,
ADD COLUMN `augment_four` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_three`,
ADD COLUMN `augment_five` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_four`,
ADD COLUMN `augment_six` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_five`;
)",
.content_schema_update = true
}
// -- template; copy/paste this when you need to create a new entry
// ManifestEntry{
@@ -123,6 +123,22 @@ ALTER TABLE `bot_pets` DROP FOREIGN KEY `FK_bot_pets_1`;
ALTER TABLE `bot_pet_buffs` DROP FOREIGN KEY `FK_bot_pet_buffs_1`;
ALTER TABLE `bot_pet_inventories` DROP FOREIGN KEY `FK_bot_pet_inventories_1`;
ALTER TABLE `bot_stances` DROP FOREIGN KEY `FK_bot_stances_1`;
)"
},
ManifestEntry{
.version = 9043,
.description = "2024_02_18_bot_starting_items_augments.sql",
.check = "SHOW COLUMNS FROM `bot_starting_items` LIKE 'augment_one'",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `bot_starting_items`
ADD COLUMN `augment_one` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `item_charges`,
ADD COLUMN `augment_two` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_one`,
ADD COLUMN `augment_three` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_two`,
ADD COLUMN `augment_four` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_three`,
ADD COLUMN `augment_five` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_four`,
ADD COLUMN `augment_six` int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `augment_five`;
)"
}
// -- template; copy/paste this when you need to create a new entry
+1 -1
View File
@@ -146,6 +146,7 @@ namespace DatabaseSchema {
"friends",
"guild_bank",
"guild_members",
"guild_permissions",
"guild_ranks",
"guild_relations",
"guild_tributes",
@@ -333,7 +334,6 @@ namespace DatabaseSchema {
"group_leaders",
"instance_list",
"ip_exemptions",
"item_tick",
"lfguild",
"merc_buffs",
"merchantlist_temp",
+4
View File
@@ -1127,4 +1127,8 @@ namespace RaidLootType {
constexpr uint32 EntireRaid = 4;
}
namespace LeadershipAbilitySlot {
constexpr uint16 HealthOfTargetsTarget = 14;
}
#endif /*COMMON_EQ_CONSTANTS_H*/
+1 -1
View File
@@ -1090,7 +1090,7 @@ bool BaseGuildManager::IsGuildLeader(uint32 guild_id, uint32 char_id) const
LogGuilds("Check leader for char [{}]: invalid guild", char_id);
return (false); //invalid guild
}
LogGuilds("Check leader for guild [{}]\, char [{}]\: leader id=[{}]", guild_id, char_id, res->second->leader);
LogGuilds("Check leader for guild [{}], char [{}]: leader id=[{}]", guild_id, char_id, res->second->leader);
return (char_id == res->second->leader);
}
+12 -2
View File
@@ -75,9 +75,18 @@ class BaseGuildManager
virtual ~BaseGuildManager();
//this must be called before doing anything else with this object
void SetDatabase(Database *db)
BaseGuildManager * SetDatabase(Database *db)
{
m_db = db;
return this;
}
BaseGuildManager * SetContentDatabase(Database *db)
{
m_content_db = db;
return this;
}
bool LoadGuilds();
@@ -194,7 +203,8 @@ class BaseGuildManager
std::map<uint32, GuildInfo *> m_guilds; //we own the pointers in this map
void ClearGuilds(); //clears internal structure
Database *m_db; //we do not own this
Database *m_db;
Database *m_content_db;
bool _StoreGuildDB(uint32 guild_id);
GuildInfo* _CreateGuild(uint32 guild_id, std::string guild_name, uint32 leader_char_id, uint8 minstatus, std::string guild_motd, std::string motd_setter, std::string Channel, std::string URL, uint32 favour);
+11
View File
@@ -1801,6 +1801,17 @@ uint32 EQ::ItemInstance::GetItemGuildFavor() const
return 0;
}
std::vector<uint32> EQ::ItemInstance::GetAugmentIDs() const
{
std::vector<uint32> augments;
for (uint8 slot_id = invaug::SOCKET_BEGIN; slot_id <= invaug::SOCKET_END; slot_id++) {
augments.push_back(GetAugment(slot_id) ? GetAugmentItemID(slot_id) : 0);
}
return augments;
}
//
// class EvolveInfo
//
+1
View File
@@ -300,6 +300,7 @@ namespace EQ
int GetItemHeroicCorrup(bool augments = false) const;
int GetItemHaste(bool augments = false) const;
uint32 GetItemGuildFavor() const;
std::vector<uint32> GetAugmentIDs() const;
protected:
//////////////////////////
@@ -24,6 +24,12 @@ public:
uint32_t classes;
uint32_t item_id;
uint8_t item_charges;
uint32_t augment_one;
uint32_t augment_two;
uint32_t augment_three;
uint32_t augment_four;
uint32_t augment_five;
uint32_t augment_six;
uint8_t min_status;
int32_t slot_id;
int8_t min_expansion;
@@ -45,6 +51,12 @@ public:
"classes",
"item_id",
"item_charges",
"augment_one",
"augment_two",
"augment_three",
"augment_four",
"augment_five",
"augment_six",
"min_status",
"slot_id",
"min_expansion",
@@ -62,6 +74,12 @@ public:
"classes",
"item_id",
"item_charges",
"augment_one",
"augment_two",
"augment_three",
"augment_four",
"augment_five",
"augment_six",
"min_status",
"slot_id",
"min_expansion",
@@ -113,6 +131,12 @@ public:
e.classes = 0;
e.item_id = 0;
e.item_charges = 1;
e.augment_one = 0;
e.augment_two = 0;
e.augment_three = 0;
e.augment_four = 0;
e.augment_five = 0;
e.augment_six = 0;
e.min_status = 0;
e.slot_id = -1;
e.min_expansion = -1;
@@ -160,12 +184,18 @@ public:
e.classes = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.item_charges = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 1;
e.min_status = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 0;
e.slot_id = row[6] ? static_cast<int32_t>(atoi(row[6])) : -1;
e.min_expansion = row[7] ? static_cast<int8_t>(atoi(row[7])) : -1;
e.max_expansion = row[8] ? static_cast<int8_t>(atoi(row[8])) : -1;
e.content_flags = row[9] ? row[9] : "";
e.content_flags_disabled = row[10] ? row[10] : "";
e.augment_one = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augment_two = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augment_three = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_four = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_five = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augment_six = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.min_status = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 0;
e.slot_id = row[12] ? static_cast<int32_t>(atoi(row[12])) : -1;
e.min_expansion = row[13] ? static_cast<int8_t>(atoi(row[13])) : -1;
e.max_expansion = row[14] ? static_cast<int8_t>(atoi(row[14])) : -1;
e.content_flags = row[15] ? row[15] : "";
e.content_flags_disabled = row[16] ? row[16] : "";
return e;
}
@@ -203,12 +233,18 @@ public:
v.push_back(columns[2] + " = " + std::to_string(e.classes));
v.push_back(columns[3] + " = " + std::to_string(e.item_id));
v.push_back(columns[4] + " = " + std::to_string(e.item_charges));
v.push_back(columns[5] + " = " + std::to_string(e.min_status));
v.push_back(columns[6] + " = " + std::to_string(e.slot_id));
v.push_back(columns[7] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[8] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[9] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[10] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
v.push_back(columns[5] + " = " + std::to_string(e.augment_one));
v.push_back(columns[6] + " = " + std::to_string(e.augment_two));
v.push_back(columns[7] + " = " + std::to_string(e.augment_three));
v.push_back(columns[8] + " = " + std::to_string(e.augment_four));
v.push_back(columns[9] + " = " + std::to_string(e.augment_five));
v.push_back(columns[10] + " = " + std::to_string(e.augment_six));
v.push_back(columns[11] + " = " + std::to_string(e.min_status));
v.push_back(columns[12] + " = " + std::to_string(e.slot_id));
v.push_back(columns[13] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[14] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[15] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[16] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -235,6 +271,12 @@ public:
v.push_back(std::to_string(e.classes));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.min_status));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.min_expansion));
@@ -275,6 +317,12 @@ public:
v.push_back(std::to_string(e.classes));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.min_status));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.min_expansion));
@@ -319,12 +367,18 @@ public:
e.classes = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.item_charges = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 1;
e.min_status = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 0;
e.slot_id = row[6] ? static_cast<int32_t>(atoi(row[6])) : -1;
e.min_expansion = row[7] ? static_cast<int8_t>(atoi(row[7])) : -1;
e.max_expansion = row[8] ? static_cast<int8_t>(atoi(row[8])) : -1;
e.content_flags = row[9] ? row[9] : "";
e.content_flags_disabled = row[10] ? row[10] : "";
e.augment_one = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augment_two = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augment_three = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_four = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_five = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augment_six = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.min_status = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 0;
e.slot_id = row[12] ? static_cast<int32_t>(atoi(row[12])) : -1;
e.min_expansion = row[13] ? static_cast<int8_t>(atoi(row[13])) : -1;
e.max_expansion = row[14] ? static_cast<int8_t>(atoi(row[14])) : -1;
e.content_flags = row[15] ? row[15] : "";
e.content_flags_disabled = row[16] ? row[16] : "";
all_entries.push_back(e);
}
@@ -354,12 +408,18 @@ public:
e.classes = row[2] ? static_cast<uint32_t>(strtoul(row[2], nullptr, 10)) : 0;
e.item_id = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
e.item_charges = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 1;
e.min_status = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 0;
e.slot_id = row[6] ? static_cast<int32_t>(atoi(row[6])) : -1;
e.min_expansion = row[7] ? static_cast<int8_t>(atoi(row[7])) : -1;
e.max_expansion = row[8] ? static_cast<int8_t>(atoi(row[8])) : -1;
e.content_flags = row[9] ? row[9] : "";
e.content_flags_disabled = row[10] ? row[10] : "";
e.augment_one = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.augment_two = row[6] ? static_cast<uint32_t>(strtoul(row[6], nullptr, 10)) : 0;
e.augment_three = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_four = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_five = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augment_six = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.min_status = row[11] ? static_cast<uint8_t>(strtoul(row[11], nullptr, 10)) : 0;
e.slot_id = row[12] ? static_cast<int32_t>(atoi(row[12])) : -1;
e.min_expansion = row[13] ? static_cast<int8_t>(atoi(row[13])) : -1;
e.max_expansion = row[14] ? static_cast<int8_t>(atoi(row[14])) : -1;
e.content_flags = row[15] ? row[15] : "";
e.content_flags_disabled = row[16] ? row[16] : "";
all_entries.push_back(e);
}
@@ -439,6 +499,12 @@ public:
v.push_back(std::to_string(e.classes));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.min_status));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.min_expansion));
@@ -472,6 +538,12 @@ public:
v.push_back(std::to_string(e.classes));
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.min_status));
v.push_back(std::to_string(e.slot_id));
v.push_back(std::to_string(e.min_expansion));
@@ -26,6 +26,12 @@ public:
std::string zone_id_list;
uint32_t item_id;
uint8_t item_charges;
uint32_t augment_one;
uint32_t augment_two;
uint32_t augment_three;
uint32_t augment_four;
uint32_t augment_five;
uint32_t augment_six;
int32_t status;
int32_t inventory_slot;
int8_t min_expansion;
@@ -49,6 +55,12 @@ public:
"zone_id_list",
"item_id",
"item_charges",
"augment_one",
"augment_two",
"augment_three",
"augment_four",
"augment_five",
"augment_six",
"status",
"inventory_slot",
"min_expansion",
@@ -68,6 +80,12 @@ public:
"zone_id_list",
"item_id",
"item_charges",
"augment_one",
"augment_two",
"augment_three",
"augment_four",
"augment_five",
"augment_six",
"status",
"inventory_slot",
"min_expansion",
@@ -121,6 +139,12 @@ public:
e.zone_id_list = "";
e.item_id = 0;
e.item_charges = 1;
e.augment_one = 0;
e.augment_two = 0;
e.augment_three = 0;
e.augment_four = 0;
e.augment_five = 0;
e.augment_six = 0;
e.status = 0;
e.inventory_slot = -1;
e.min_expansion = -1;
@@ -170,12 +194,18 @@ public:
e.zone_id_list = row[4] ? row[4] : "";
e.item_id = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.item_charges = row[6] ? static_cast<uint8_t>(strtoul(row[6], nullptr, 10)) : 1;
e.status = row[7] ? static_cast<int32_t>(atoi(row[7])) : 0;
e.inventory_slot = row[8] ? static_cast<int32_t>(atoi(row[8])) : -1;
e.min_expansion = row[9] ? static_cast<int8_t>(atoi(row[9])) : -1;
e.max_expansion = row[10] ? static_cast<int8_t>(atoi(row[10])) : -1;
e.content_flags = row[11] ? row[11] : "";
e.content_flags_disabled = row[12] ? row[12] : "";
e.augment_one = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_two = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_three = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augment_four = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.augment_five = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.augment_six = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0;
e.status = row[13] ? static_cast<int32_t>(atoi(row[13])) : 0;
e.inventory_slot = row[14] ? static_cast<int32_t>(atoi(row[14])) : -1;
e.min_expansion = row[15] ? static_cast<int8_t>(atoi(row[15])) : -1;
e.max_expansion = row[16] ? static_cast<int8_t>(atoi(row[16])) : -1;
e.content_flags = row[17] ? row[17] : "";
e.content_flags_disabled = row[18] ? row[18] : "";
return e;
}
@@ -215,12 +245,18 @@ public:
v.push_back(columns[4] + " = '" + Strings::Escape(e.zone_id_list) + "'");
v.push_back(columns[5] + " = " + std::to_string(e.item_id));
v.push_back(columns[6] + " = " + std::to_string(e.item_charges));
v.push_back(columns[7] + " = " + std::to_string(e.status));
v.push_back(columns[8] + " = " + std::to_string(e.inventory_slot));
v.push_back(columns[9] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[10] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[11] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[12] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
v.push_back(columns[7] + " = " + std::to_string(e.augment_one));
v.push_back(columns[8] + " = " + std::to_string(e.augment_two));
v.push_back(columns[9] + " = " + std::to_string(e.augment_three));
v.push_back(columns[10] + " = " + std::to_string(e.augment_four));
v.push_back(columns[11] + " = " + std::to_string(e.augment_five));
v.push_back(columns[12] + " = " + std::to_string(e.augment_six));
v.push_back(columns[13] + " = " + std::to_string(e.status));
v.push_back(columns[14] + " = " + std::to_string(e.inventory_slot));
v.push_back(columns[15] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[16] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[17] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[18] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
auto results = db.QueryDatabase(
fmt::format(
@@ -249,6 +285,12 @@ public:
v.push_back("'" + Strings::Escape(e.zone_id_list) + "'");
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.status));
v.push_back(std::to_string(e.inventory_slot));
v.push_back(std::to_string(e.min_expansion));
@@ -291,6 +333,12 @@ public:
v.push_back("'" + Strings::Escape(e.zone_id_list) + "'");
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.status));
v.push_back(std::to_string(e.inventory_slot));
v.push_back(std::to_string(e.min_expansion));
@@ -337,12 +385,18 @@ public:
e.zone_id_list = row[4] ? row[4] : "";
e.item_id = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.item_charges = row[6] ? static_cast<uint8_t>(strtoul(row[6], nullptr, 10)) : 1;
e.status = row[7] ? static_cast<int32_t>(atoi(row[7])) : 0;
e.inventory_slot = row[8] ? static_cast<int32_t>(atoi(row[8])) : -1;
e.min_expansion = row[9] ? static_cast<int8_t>(atoi(row[9])) : -1;
e.max_expansion = row[10] ? static_cast<int8_t>(atoi(row[10])) : -1;
e.content_flags = row[11] ? row[11] : "";
e.content_flags_disabled = row[12] ? row[12] : "";
e.augment_one = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_two = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_three = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augment_four = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.augment_five = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.augment_six = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0;
e.status = row[13] ? static_cast<int32_t>(atoi(row[13])) : 0;
e.inventory_slot = row[14] ? static_cast<int32_t>(atoi(row[14])) : -1;
e.min_expansion = row[15] ? static_cast<int8_t>(atoi(row[15])) : -1;
e.max_expansion = row[16] ? static_cast<int8_t>(atoi(row[16])) : -1;
e.content_flags = row[17] ? row[17] : "";
e.content_flags_disabled = row[18] ? row[18] : "";
all_entries.push_back(e);
}
@@ -374,12 +428,18 @@ public:
e.zone_id_list = row[4] ? row[4] : "";
e.item_id = row[5] ? static_cast<uint32_t>(strtoul(row[5], nullptr, 10)) : 0;
e.item_charges = row[6] ? static_cast<uint8_t>(strtoul(row[6], nullptr, 10)) : 1;
e.status = row[7] ? static_cast<int32_t>(atoi(row[7])) : 0;
e.inventory_slot = row[8] ? static_cast<int32_t>(atoi(row[8])) : -1;
e.min_expansion = row[9] ? static_cast<int8_t>(atoi(row[9])) : -1;
e.max_expansion = row[10] ? static_cast<int8_t>(atoi(row[10])) : -1;
e.content_flags = row[11] ? row[11] : "";
e.content_flags_disabled = row[12] ? row[12] : "";
e.augment_one = row[7] ? static_cast<uint32_t>(strtoul(row[7], nullptr, 10)) : 0;
e.augment_two = row[8] ? static_cast<uint32_t>(strtoul(row[8], nullptr, 10)) : 0;
e.augment_three = row[9] ? static_cast<uint32_t>(strtoul(row[9], nullptr, 10)) : 0;
e.augment_four = row[10] ? static_cast<uint32_t>(strtoul(row[10], nullptr, 10)) : 0;
e.augment_five = row[11] ? static_cast<uint32_t>(strtoul(row[11], nullptr, 10)) : 0;
e.augment_six = row[12] ? static_cast<uint32_t>(strtoul(row[12], nullptr, 10)) : 0;
e.status = row[13] ? static_cast<int32_t>(atoi(row[13])) : 0;
e.inventory_slot = row[14] ? static_cast<int32_t>(atoi(row[14])) : -1;
e.min_expansion = row[15] ? static_cast<int8_t>(atoi(row[15])) : -1;
e.max_expansion = row[16] ? static_cast<int8_t>(atoi(row[16])) : -1;
e.content_flags = row[17] ? row[17] : "";
e.content_flags_disabled = row[18] ? row[18] : "";
all_entries.push_back(e);
}
@@ -461,6 +521,12 @@ public:
v.push_back("'" + Strings::Escape(e.zone_id_list) + "'");
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.status));
v.push_back(std::to_string(e.inventory_slot));
v.push_back(std::to_string(e.min_expansion));
@@ -496,6 +562,12 @@ public:
v.push_back("'" + Strings::Escape(e.zone_id_list) + "'");
v.push_back(std::to_string(e.item_id));
v.push_back(std::to_string(e.item_charges));
v.push_back(std::to_string(e.augment_one));
v.push_back(std::to_string(e.augment_two));
v.push_back(std::to_string(e.augment_three));
v.push_back(std::to_string(e.augment_four));
v.push_back(std::to_string(e.augment_five));
v.push_back(std::to_string(e.augment_six));
v.push_back(std::to_string(e.status));
v.push_back(std::to_string(e.inventory_slot));
v.push_back(std::to_string(e.min_expansion));
@@ -0,0 +1,392 @@
/**
* DO NOT MODIFY THIS FILE
*
* This repository was automatically generated and is NOT to be modified directly.
* Any repository modifications are meant to be made to the repository extending the base.
* Any modifications to base repositories are to be made by the generator only
*
* @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://docs.eqemu.io/developer/repositories
*/
#ifndef EQEMU_BASE_ZONE_FLAGS_REPOSITORY_H
#define EQEMU_BASE_ZONE_FLAGS_REPOSITORY_H
#include "../../database.h"
#include "../../strings.h"
#include <ctime>
class BaseZoneFlagsRepository {
public:
struct ZoneFlags {
int32_t charID;
int32_t zoneID;
};
static std::string PrimaryKey()
{
return std::string("charID");
}
static std::vector<std::string> Columns()
{
return {
"charID",
"zoneID",
};
}
static std::vector<std::string> SelectColumns()
{
return {
"charID",
"zoneID",
};
}
static std::string ColumnsRaw()
{
return std::string(Strings::Implode(", ", Columns()));
}
static std::string SelectColumnsRaw()
{
return std::string(Strings::Implode(", ", SelectColumns()));
}
static std::string TableName()
{
return std::string("zone_flags");
}
static std::string BaseSelect()
{
return fmt::format(
"SELECT {} FROM {}",
SelectColumnsRaw(),
TableName()
);
}
static std::string BaseInsert()
{
return fmt::format(
"INSERT INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static ZoneFlags NewEntity()
{
ZoneFlags e{};
e.charID = 0;
e.zoneID = 0;
return e;
}
static ZoneFlags GetZoneFlags(
const std::vector<ZoneFlags> &zone_flagss,
int zone_flags_id
)
{
for (auto &zone_flags : zone_flagss) {
if (zone_flags.charID == zone_flags_id) {
return zone_flags;
}
}
return NewEntity();
}
static ZoneFlags FindOne(
Database& db,
int zone_flags_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
zone_flags_id
)
);
auto row = results.begin();
if (results.RowCount() == 1) {
ZoneFlags e{};
e.charID = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.zoneID = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
return e;
}
return NewEntity();
}
static int DeleteOne(
Database& db,
int zone_flags_id
)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {} = {}",
TableName(),
PrimaryKey(),
zone_flags_id
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int UpdateOne(
Database& db,
const ZoneFlags &e
)
{
std::vector<std::string> v;
auto columns = Columns();
v.push_back(columns[0] + " = " + std::to_string(e.charID));
v.push_back(columns[1] + " = " + std::to_string(e.zoneID));
auto results = db.QueryDatabase(
fmt::format(
"UPDATE {} SET {} WHERE {} = {}",
TableName(),
Strings::Implode(", ", v),
PrimaryKey(),
e.charID
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static ZoneFlags InsertOne(
Database& db,
ZoneFlags e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.charID));
v.push_back(std::to_string(e.zoneID));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseInsert(),
Strings::Implode(",", v)
)
);
if (results.Success()) {
e.charID = results.LastInsertedID();
return e;
}
e = NewEntity();
return e;
}
static int InsertMany(
Database& db,
const std::vector<ZoneFlags> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.charID));
v.push_back(std::to_string(e.zoneID));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseInsert(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static std::vector<ZoneFlags> All(Database& db)
{
std::vector<ZoneFlags> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{}",
BaseSelect()
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
ZoneFlags e{};
e.charID = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.zoneID = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
all_entries.push_back(e);
}
return all_entries;
}
static std::vector<ZoneFlags> GetWhere(Database& db, const std::string &where_filter)
{
std::vector<ZoneFlags> all_entries;
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE {}",
BaseSelect(),
where_filter
)
);
all_entries.reserve(results.RowCount());
for (auto row = results.begin(); row != results.end(); ++row) {
ZoneFlags e{};
e.charID = row[0] ? static_cast<int32_t>(atoi(row[0])) : 0;
e.zoneID = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
all_entries.push_back(e);
}
return all_entries;
}
static int DeleteWhere(Database& db, const std::string &where_filter)
{
auto results = db.QueryDatabase(
fmt::format(
"DELETE FROM {} WHERE {}",
TableName(),
where_filter
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int Truncate(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"TRUNCATE TABLE {}",
TableName()
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int64 GetMaxId(Database& db)
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COALESCE(MAX({}), 0) FROM {}",
PrimaryKey(),
TableName()
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static int64 Count(Database& db, const std::string &where_filter = "")
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT COUNT(*) FROM {} {}",
TableName(),
(where_filter.empty() ? "" : "WHERE " + where_filter)
)
);
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
}
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const ZoneFlags &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.charID));
v.push_back(std::to_string(e.zoneID));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<ZoneFlags> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.charID));
v.push_back(std::to_string(e.zoneID));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
};
#endif //EQEMU_BASE_ZONE_FLAGS_REPOSITORY_H
File diff suppressed because it is too large Load Diff
@@ -103,7 +103,7 @@ public:
{
auto results = db.QueryDatabase(
fmt::format(
"SELECT MAX(`number`) FROM `{}` WHERE `zoneid` = {} AND `gridid` = {}",
"SELECT COALESCE(MAX(`number`), 0) FROM `{}` WHERE `zoneid` = {} AND `gridid` = {}",
TableName(),
zone_id,
grid_id
@@ -0,0 +1,50 @@
#ifndef EQEMU_ZONE_FLAGS_REPOSITORY_H
#define EQEMU_ZONE_FLAGS_REPOSITORY_H
#include "../database.h"
#include "../strings.h"
#include "base/base_zone_flags_repository.h"
class ZoneFlagsRepository: public BaseZoneFlagsRepository {
public:
/**
* This file was auto generated and can be modified and extended upon
*
* Base repository methods are automatically
* generated in the "base" version of this repository. The base repository
* is immutable and to be left untouched, while methods in this class
* are used as extension methods for more specific persistence-layer
* accessors or mutators.
*
* Base Methods (Subject to be expanded upon in time)
*
* Note: Not all tables are designed appropriately to fit functionality with all base methods
*
* InsertOne
* UpdateOne
* DeleteOne
* FindOne
* GetWhere(std::string where_filter)
* DeleteWhere(std::string where_filter)
* InsertMany
* All
*
* Example custom methods in a repository
*
* ZoneFlagsRepository::GetByZoneAndVersion(int zone_id, int zone_version)
* ZoneFlagsRepository::GetWhereNeverExpires()
* ZoneFlagsRepository::GetWhereXAndY()
* ZoneFlagsRepository::DeleteWhereXAndY()
*
* Most of the above could be covered by base methods, but if you as a developer
* find yourself re-using logic for other parts of the code, its best to just make a
* method that can be re-used easily elsewhere especially if it can use a base repository
* method and encapsulate filters there
*/
// Custom extended repository methods here
};
#endif //EQEMU_ZONE_FLAGS_REPOSITORY_H
+2 -1
View File
@@ -495,6 +495,7 @@ RULE_BOOL(Spells, EvacClearCharmPet, false, "Enable to have evac in zone clear c
RULE_BOOL(Spells, ManaTapsRequireNPCMana, false, "Enabling will require target to have mana to tap. Default off as many npc's are caster class with 0 mana and need fixed.")
RULE_INT(Spells, HarmTouchCritRatio, 200, "Harmtouch crit bonus, on top of BaseCritRatio")
RULE_BOOL(Spells, UseClassicSpellFocus, false, "Enabling will tell the server to handle random focus damage as classic spell imports lack the limit values.")
RULE_BOOL(Spells, ManaTapsOnAnyClass, false, "Enabling this will allow you to cast mana taps on any class, this will bypass ManaTapsRequireNPCMana rule.")
RULE_CATEGORY_END()
RULE_CATEGORY(Combat)
@@ -890,7 +891,7 @@ RULE_INT(Expansion, AutoGrantAAExpansion, -1, "Expansion to auto grant AAs up to
RULE_CATEGORY_END()
RULE_CATEGORY(Instances)
RULE_INT(Instances, ReservedInstances, 30, "Number of instance IDs which are reserved for globals. This value should not be changed while a server is running")
RULE_INT(Instances, ReservedInstances, 100, "Number of instance IDs which are reserved for globals. This value should not be changed while a server is running")
RULE_BOOL(Instances, RecycleInstanceIds, true, "Setting whether free instance IDs should be recycled to prevent them from gradually running out at 32k")
RULE_INT(Instances, GuildHallExpirationDays, 90, "Amount of days before a Guild Hall instance expires")
RULE_CATEGORY_END()
+17 -2
View File
@@ -461,7 +461,13 @@ bool SharedDatabase::SetStartingItems(
{
const EQ::ItemData *item_data;
const auto &l = StartingItemsRepository::All(*this);
const auto& l = StartingItemsRepository::GetWhere(
*this,
fmt::format(
"TRUE {}",
ContentFilterCriteria::apply()
)
);
if (l.empty()) {
return false;
@@ -515,7 +521,16 @@ bool SharedDatabase::SetStartingItems(
continue;
}
const auto *inst = CreateBaseItem(item_data, item_charges);
const auto* inst = CreateItem(
item_data,
item_charges,
e.augment_one,
e.augment_two,
e.augment_three,
e.augment_four,
e.augment_five,
e.augment_six
);
if (slot < EQ::invslot::slotCharm) {
slot = inv->FindFreeSlot(false, false);
+3 -3
View File
@@ -25,7 +25,7 @@
// Build variables
// these get injected during the build pipeline
#define CURRENT_VERSION "22.44.2-dev" // always append -dev to the current version for custom-builds
#define CURRENT_VERSION "22.45.0-dev" // always append -dev to the current version for custom-builds
#define LOGIN_VERSION "0.8.0"
#define COMPILE_DATE __DATE__
#define COMPILE_TIME __TIME__
@@ -42,8 +42,8 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9262
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9042
#define CURRENT_BINARY_DATABASE_VERSION 9264
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9043
#endif
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "eqemu-server",
"version": "22.44.2",
"version": "22.45.0",
"repository": {
"type": "git",
"url": "https://github.com/EQEmu/Server.git"
+1
View File
@@ -168,6 +168,7 @@ int main(int argc, char **argv)
content_service.SetCurrentExpansion(RuleI(Expansion, CurrentExpansion));
content_service.SetDatabase(&database)
->SetContentDatabase(&content_db)
->SetExpansionContext()
->ReloadContentFlags();
+5 -5
View File
@@ -56,7 +56,7 @@ void Adventure::AddPlayer(std::string character_name, bool add_client_to_instanc
{
if(!PlayerExists(character_name))
{
int32 character_id = database.GetCharacterID(character_name.c_str());
int32 character_id = database.GetCharacterID(character_name);
if(character_id && add_client_to_instance)
{
database.AddClientToInstance(instance_id, character_id);
@@ -72,7 +72,7 @@ void Adventure::RemovePlayer(std::string character_name)
{
if((*iter).compare(character_name) == 0)
{
int32 character_id = database.GetCharacterID(character_name.c_str());
int32 character_id = database.GetCharacterID(character_name);
if (character_id)
{
database.RemoveClientFromInstance(instance_id, character_id);
@@ -312,7 +312,7 @@ void Adventure::Finished(AdventureWinStatus ws)
}
zoneserver_list.SendPacket(current->zone(), current->instance(), pack);
database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter).c_str()), GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter)), GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
delete pack;
}
else
@@ -337,7 +337,7 @@ void Adventure::Finished(AdventureWinStatus ws)
afe.points = 0;
}
adventure_manager.AddFinishedEvent(afe);
database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter).c_str()), GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter)), GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
}
}
else
@@ -363,7 +363,7 @@ void Adventure::Finished(AdventureWinStatus ws)
}
adventure_manager.AddFinishedEvent(afe);
database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter).c_str()), GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
database.UpdateAdventureStatsEntry(database.GetCharacterID((*iter)), GetTemplate()->theme, (ws != AWS_Lose) ? true : false);
}
++iter;
}
+125 -138
View File
@@ -50,6 +50,7 @@
#include "../common/zone_store.h"
#include "../common/repositories/account_repository.h"
#include "../common/repositories/player_event_logs_repository.h"
#include "../common/repositories/inventory_repository.h"
#include "../common/events/player_event_logs.h"
#include <iostream>
@@ -1613,10 +1614,18 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
inv.SetInventoryVersion(EQ::versions::ConvertClientVersionBitToClientVersion(m_ClientVersionBit));
inv.SetGMInventory(false); // character cannot have gm flag at this point
time_t bday = time(nullptr);
time_t bday = time(nullptr);
in_addr in;
int stats_sum = cc->STR + cc->STA + cc->AGI + cc->DEX + cc->WIS + cc->INT + cc->CHA;
const uint32 stats_sum = (
cc->AGI +
cc->CHA +
cc->DEX +
cc->INT +
cc->STA +
cc->STR +
cc->WIS
);
in.s_addr = GetIP();
@@ -1629,7 +1638,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
);
LogInfo("Name [{}]", name);
LogInfo(
"Race [{}] Class [{}] Gender [{}] Deity [{}] Start zone [{}] Tutorial [{}]",
"race [{}] class [{}] gender [{}] deity [{}] start_zone [{}] tutorial [{}]",
cc->race,
cc->class_,
cc->gender,
@@ -1637,21 +1646,20 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
cc->start_zone,
cc->tutorial ? "true" : "false"
);
LogInfo("STR STA AGI DEX WIS INT CHA Total");
LogInfo(
" [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}]",
cc->STR,
cc->STA,
"AGI [{}] CHA [{}] DEX [{}] INT [{}] STA [{}] STR [{}] WIS [{}] Total [{}]",
cc->AGI,
cc->DEX,
cc->WIS,
cc->INT,
cc->CHA,
cc->DEX,
cc->INT,
cc->STA,
cc->STR,
cc->WIS,
stats_sum
);
LogInfo("Face [{}] Eye colors [{}] [{}]", cc->face, cc->eyecolor1, cc->eyecolor2);
LogInfo("Hairstyle [{}] Haircolor [{}]", cc->hairstyle, cc->haircolor);
LogInfo("Beard [{}] Beardcolor [{}]", cc->beard, cc->beardcolor);
LogInfo("Face [{}] Eye Colors [{}] [{}]", cc->face, cc->eyecolor1, cc->eyecolor2);
LogInfo("Hair [{}] Hair Color [{}]", cc->hairstyle, cc->haircolor);
LogInfo("Beard [{}] Beard Color [{}]", cc->beard, cc->beardcolor);
/* Validate the char creation struct */
if (m_ClientVersionBit & EQ::versions::maskSoFAndLater) {
@@ -1669,39 +1677,39 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
/* Convert incoming cc_s to the new PlayerProfile_Struct */
memset(&pp, 0, sizeof(PlayerProfile_Struct)); // start building the profile
strn0cpy(pp.name, name, 63);
strn0cpy(pp.name, name, sizeof(pp.name));
pp.race = cc->race;
pp.class_ = cc->class_;
pp.gender = cc->gender;
pp.deity = cc->deity;
pp.STR = cc->STR;
pp.STA = cc->STA;
pp.AGI = cc->AGI;
pp.DEX = cc->DEX;
pp.WIS = cc->WIS;
pp.INT = cc->INT;
pp.CHA = cc->CHA;
pp.face = cc->face;
pp.eyecolor1 = cc->eyecolor1;
pp.eyecolor2 = cc->eyecolor2;
pp.hairstyle = cc->hairstyle;
pp.haircolor = cc->haircolor;
pp.beard = cc->beard;
pp.beardcolor = cc->beardcolor;
pp.drakkin_heritage = cc->drakkin_heritage;
pp.drakkin_tattoo = cc->drakkin_tattoo;
pp.drakkin_details = cc->drakkin_details;
pp.birthday = bday;
pp.lastlogin = bday;
pp.level = 1;
pp.points = 5;
pp.cur_hp = 1000; // 1k hp during dev only
pp.hunger_level = 6000;
pp.thirst_level = 6000;
pp.race = cc->race;
pp.class_ = cc->class_;
pp.gender = cc->gender;
pp.deity = cc->deity;
pp.STR = cc->STR;
pp.STA = cc->STA;
pp.AGI = cc->AGI;
pp.DEX = cc->DEX;
pp.WIS = cc->WIS;
pp.INT = cc->INT;
pp.CHA = cc->CHA;
pp.face = cc->face;
pp.eyecolor1 = cc->eyecolor1;
pp.eyecolor2 = cc->eyecolor2;
pp.hairstyle = cc->hairstyle;
pp.haircolor = cc->haircolor;
pp.beard = cc->beard;
pp.beardcolor = cc->beardcolor;
pp.drakkin_heritage = cc->drakkin_heritage;
pp.drakkin_tattoo = cc->drakkin_tattoo;
pp.drakkin_details = cc->drakkin_details;
pp.birthday = bday;
pp.lastlogin = bday;
pp.level = 1;
pp.points = 5;
pp.cur_hp = 1000;
pp.hunger_level = 6000;
pp.thirst_level = 6000;
/* Set default skills for everybody */
pp.skills[EQ::skills::SkillSwimming] = RuleI(Skills, SwimmingStartValue);
pp.skills[EQ::skills::SkillSwimming] = RuleI(Skills, SwimmingStartValue);
pp.skills[EQ::skills::SkillSenseHeading] = RuleI(Skills, SenseHeadingStartValue);
/* Set Racial and Class specific language and skills */
@@ -1710,13 +1718,12 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
SetClassStartingSkills(&pp);
SetClassLanguages(&pp);
// strcpy(pp.servername, WorldConfig::get()->ShortName.c_str());
memset(pp.spell_book, std::numeric_limits<uint8>::max(), (sizeof(uint32) * EQ::spells::SPELLBOOK_SIZE));
memset(pp.mem_spells, std::numeric_limits<uint8>::max(), (sizeof(uint32) * EQ::spells::SPELL_GEM_COUNT));
memset(pp.spell_book, 0xFF, (sizeof(uint32) * EQ::spells::SPELLBOOK_SIZE));
memset(pp.mem_spells, 0xFF, (sizeof(uint32) * EQ::spells::SPELL_GEM_COUNT));
for (auto& buff : pp.buffs)
buff.spellid = 0xFFFF;
for (auto& b : pp.buffs) {
b.spellid = std::numeric_limits<uint16>::max();
}
/* If server is PVP by default, make all character set to it. */
pp.pvp = database.GetServerType() == 1 ? 1 : 0;
@@ -1728,56 +1735,38 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
pp.zone_id = RuleI(World, SoFStartZoneID);
cc->start_zone = pp.zone_id;
}
}
else {
} else {
LogInfo("Found [TitaniumStartZoneID] rule setting [{}]", RuleI(World, TitaniumStartZoneID));
if (RuleI(World, TitaniumStartZoneID) > 0) { /* if there's a startzone variable put them in there */
pp.zone_id = RuleI(World, TitaniumStartZoneID);
pp.zone_id = RuleI(World, TitaniumStartZoneID);
cc->start_zone = pp.zone_id;
}
}
/* use normal starting zone logic to either get defaults, or if startzone was set, load that from the db table.*/
bool ValidStartZone = content_db.GetStartZone(&pp, cc, m_ClientVersionBit & EQ::versions::maskTitaniumAndEarlier);
if (!ValidStartZone){
/* use normal starting zone logic to either get defaults, or if startzone was set, load that from the db table.*/
const bool is_valid_start_zone = content_db.GetStartZone(&pp, cc, m_ClientVersionBit & EQ::versions::maskTitaniumAndEarlier);
if (!is_valid_start_zone){
return false;
}
/* just in case */
if (!pp.zone_id) {
pp.zone_id = 1; // qeynos
pp.zone_id = Zones::QEYNOS;
pp.x = pp.y = pp.z = -1;
}
/* Set Home Binds -- yep, all of them */
pp.binds[1].zone_id = pp.zone_id;
pp.binds[1].x = pp.x;
pp.binds[1].y = pp.y;
pp.binds[1].z = pp.z;
pp.binds[1].heading = pp.heading;
pp.binds[2].zone_id = pp.zone_id;
pp.binds[2].x = pp.x;
pp.binds[2].y = pp.y;
pp.binds[2].z = pp.z;
pp.binds[2].heading = pp.heading;
pp.binds[3].zone_id = pp.zone_id;
pp.binds[3].x = pp.x;
pp.binds[3].y = pp.y;
pp.binds[3].z = pp.z;
pp.binds[3].heading = pp.heading;
pp.binds[4].zone_id = pp.zone_id;
pp.binds[4].x = pp.x;
pp.binds[4].y = pp.y;
pp.binds[4].z = pp.z;
pp.binds[4].heading = pp.heading;
for (uint8 slot_id = 1; slot_id < 5; slot_id++) {
pp.binds[slot_id].zone_id = pp.zone_id;
pp.binds[slot_id].x = pp.x;
pp.binds[slot_id].y = pp.y;
pp.binds[slot_id].z = pp.z;
pp.binds[slot_id].heading = pp.heading;
}
/* Overrides if we have the tutorial flag set! */
if (cc->tutorial && RuleB(World, EnableTutorialButton)) {
pp.zone_id = RuleI(World, TutorialZoneID);
auto z = GetZone(pp.zone_id);
if (z) {
pp.x = z->safe_x;
@@ -1787,17 +1776,17 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
}
/* Will either be the same as home or tutorial if enabled. */
if(RuleB(World, StartZoneSameAsBindOnCreation)) {
if (RuleB(World, StartZoneSameAsBindOnCreation)) {
pp.binds[0].zone_id = pp.zone_id;
pp.binds[0].x = pp.x;
pp.binds[0].y = pp.y;
pp.binds[0].z = pp.z;
pp.binds[0].x = pp.x;
pp.binds[0].y = pp.y;
pp.binds[0].z = pp.z;
pp.binds[0].heading = pp.heading;
}
if (GetZone(pp.zone_id)) {
LogInfo(
"Current location [{}] [{}] [{:.2f}] [{:.2f}] [{:.2f}] [{:.2f}]",
"Current location zone_short_name [{}] zone_id [{}] x [{:.2f}] y [{:.2f}] z [{:.2f}] heading [{:.2f}]",
ZoneName(pp.zone_id),
pp.zone_id,
pp.x,
@@ -1809,37 +1798,34 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc)
if (GetZone(pp.binds[0].zone_id)) {
LogInfo(
"Bind location [{}] [{}] [{:.2f}] [{:.2f}] [{:.2f}]",
"Bind location zone_short_name [{}] zone_id [{}] x [{:.2f}] y [{:.2f}] z [{:.2f}] heading [{:.2f}]",
ZoneName(pp.binds[0].zone_id),
pp.binds[0].zone_id,
pp.binds[0].x,
pp.binds[0].y,
pp.binds[0].z
pp.binds[0].z,
pp.binds[4].heading
);
}
if (GetZone(pp.binds[4].zone_id)) {
LogInfo(
"Home location [{}] [{}] [{:.2f}] [{:.2f}] [{:.2f}]",
"Home location zone_short_name [{}] zone_id [{}] x [{:.2f}] y [{:.2f}] z [{:.2f}] heading [{:.2f}]",
ZoneName(pp.binds[4].zone_id),
pp.binds[4].zone_id,
pp.binds[4].x,
pp.binds[4].y,
pp.binds[4].z
pp.binds[4].z,
pp.binds[4].heading
);
}
/* Starting Items inventory */
content_db.SetStartingItems(&pp, &inv, pp.race, pp.class_, pp.deity, pp.zone_id, pp.name, GetAdmin());
// now we give the pp and the inv we made to StoreCharacter
// to see if we can store it
if (!StoreCharacter(GetAccountID(), &pp, &inv)) {
LogInfo("Character creation failed: [{}]", pp.name);
return false;
}
LogInfo("Character creation successful: [{}]", pp.name);
return true;
const bool success = StoreCharacter(GetAccountID(), &pp, &inv);
LogInfo("Character creation {} for [{}]", success ? "succeeded" : "failed", pp.name);
return success;
}
// returns true if the request is ok, false if there's an error
@@ -2312,56 +2298,57 @@ bool Client::StoreCharacter(
EQ::InventoryProfile *p_inventory_profile
)
{
uint32 character_id = 0;
char zone[50];
character_id = database.GetCharacterID(p_player_profile_struct->name);
const uint32 character_id = database.GetCharacterID(p_player_profile_struct->name);
if (!character_id) {
LogError("StoreCharacter: no character id");
return false;
}
const char *zone_name = ZoneName(p_player_profile_struct->zone_id);
if (zone_name == nullptr) {
/* Zone not in the DB, something to prevent crash... */
strn0cpy(zone, "qeynos", 49);
p_player_profile_struct->zone_id = 1;
}
else {
strn0cpy(zone, zone_name, 49);
const std::string& zone_name = zone_store.GetZoneName(p_player_profile_struct->zone_id, true);
if (Strings::EqualFold(zone_name, "UNKNOWN")) {
p_player_profile_struct->zone_id = Zones::QEYNOS;
}
database.SaveCharacterCreate(character_id, account_id, p_player_profile_struct);
std::string invquery;
for (int16 i = EQ::invslot::EQUIPMENT_BEGIN; i <= EQ::invbag::BANK_BAGS_END;) {
const EQ::ItemInstance *new_inventory_item = p_inventory_profile->GetItem(i);
if (new_inventory_item) {
invquery = StringFormat(
"INSERT INTO `inventory` (charid, slotid, itemid, charges, color) VALUES (%u, %i, %u, %i, %u)",
character_id,
i,
new_inventory_item->GetItem()->ID,
new_inventory_item->GetCharges(),
new_inventory_item->GetColor()
);
std::vector<InventoryRepository::Inventory> v;
auto results = database.QueryDatabase(invquery);
auto e = InventoryRepository::NewEntity();
e.charid = character_id;
for (int16 slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invbag::BANK_BAGS_END;) {
const auto inst = p_inventory_profile->GetItem(slot_id);
if (inst) {
e.slotid = slot_id;
e.itemid = inst->GetItem()->ID;
e.charges = inst->GetCharges();
e.color = inst->GetColor();
e.augslot1 = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN);
e.augslot2 = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 1);
e.augslot3 = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 2);
e.augslot4 = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 3);
e.augslot5 = inst->GetAugmentItemID(EQ::invaug::SOCKET_BEGIN + 4);
e.augslot6 = inst->GetAugmentItemID(EQ::invaug::SOCKET_END);
v.emplace_back(e);
}
if (i == EQ::invslot::slotCursor) {
i = EQ::invbag::GENERAL_BAGS_BEGIN;
if (slot_id == EQ::invslot::slotCursor) {
slot_id = EQ::invbag::GENERAL_BAGS_BEGIN;
continue;
} else if (slot_id == EQ::invbag::CURSOR_BAG_END) {
slot_id = EQ::invslot::BANK_BEGIN;
continue;
} else if (slot_id == EQ::invslot::BANK_END) {
slot_id = EQ::invbag::BANK_BAGS_BEGIN;
continue;
}
else if (i == EQ::invbag::CURSOR_BAG_END) {
i = EQ::invslot::BANK_BEGIN;
continue;
}
else if (i == EQ::invslot::BANK_END) {
i = EQ::invbag::BANK_BAGS_BEGIN;
continue;
}
i++;
slot_id++;
}
if (!v.empty()) {
InventoryRepository::InsertMany(database, v);
}
return true;
@@ -2388,7 +2375,7 @@ void Client::RecordPossibleHack(const std::string& message)
}
}
void Client::SendGuildTributeFavorAndTimer(uint32 favor, uint32 time_remaining)
void Client::SendGuildTributeFavorAndTimer(uint32 favor, uint32 time_remaining)
{
auto cle = GetCLE();
if (!cle) {
+11 -2
View File
@@ -325,7 +325,7 @@ bool WorldGuildManager::LoadTributes()
tribute_list.clear();
auto tributes = TributesRepository::All(*m_db);
auto tributes = TributesRepository::All(*m_content_db);
for (auto const& t : tributes) {
td.name = t.name;
td.description = t.descr;
@@ -336,7 +336,7 @@ bool WorldGuildManager::LoadTributes()
LogInfo("Loaded [{}] tributes", Strings::Commify(tributes.size()));
auto tribute_levels = TributeLevelsRepository::GetWhere(*m_db, "TRUE ORDER BY tribute_id, level");
auto tribute_levels = TributeLevelsRepository::GetWhere(*m_content_db, "TRUE ORDER BY tribute_id, level");
for (auto const& t : tribute_levels) {
uint32 id = t.tribute_id;
@@ -369,6 +369,10 @@ bool WorldGuildManager::LoadTributes()
bool WorldGuildManager::RefreshGuild(uint32 guild_id)
{
auto temp_guild = GetGuildByGuildID(guild_id);
if (!temp_guild) {
return false;
}
BaseGuildManager::GuildInfo temp_guild_detail;
if (temp_guild) {
@@ -389,6 +393,11 @@ bool WorldGuildManager::RefreshGuild(uint32 guild_id)
LogGuilds("Found guild id [{}]. Loading details.....", db_guild.id);
_CreateGuild(db_guild.id, db_guild.name, db_guild.leader, db_guild.minstatus, db_guild.motd, db_guild.motd_setter, db_guild.channel, db_guild.url, db_guild.favor);
auto guild = GetGuildByGuildID(guild_id);
if (!guild) {
LogError("Error refreshing guild id {}", guild_id);
return false;
}
auto where_filter = fmt::format("guild_id = '{}'", guild_id);
auto guild_ranks = GuildRanksRepository::GetWhere(*m_db, where_filter);
for (auto const& r : guild_ranks) {
+2 -1
View File
@@ -264,7 +264,7 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv)
}
}
guild_mgr.SetDatabase(&database);
guild_mgr.SetDatabase(&database)->SetContentDatabase(&content_db);
LogInfo("Purging expired data buckets");
database.PurgeAllDeletedDataBuckets();
@@ -381,6 +381,7 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv)
LogInfo("Initializing [WorldContentService]");
content_service.SetDatabase(&database)
->SetContentDatabase(&content_db)
->SetExpansionContext()
->ReloadContentFlags();
+1
View File
@@ -1367,6 +1367,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
}
case ServerOP_ReloadOpcodes: {
ReloadAllPatches();
zoneserver_list.SendPacket(pack);
break;
}
case ServerOP_CZDialogueWindow:
+35 -9
View File
@@ -1164,14 +1164,27 @@ int64 Mob::GetWeaponDamage(Mob *against, const EQ::ItemInstance *weapon_item, in
// check for items being illegally attained
if (weapon_item) {
if (!weapon_item->GetItem())
if (!weapon_item->GetItem()) {
return 0;
}
if (weapon_item->GetItemRequiredLevel(true) > GetLevel())
if (weapon_item->GetItemRequiredLevel(true) > GetLevel()) {
return 0;
}
if (!weapon_item->IsEquipable(GetBaseRace(), GetClass()))
if (!weapon_item->IsClassEquipable(GetClass())) {
return 0;
}
if (
!weapon_item->IsRaceEquipable(GetBaseRace()) &&
(
!IsBot() ||
(IsBot() && !RuleB(Bots, AllowBotEquipAnyRaceGear))
)
) {
return 0;
}
}
if (against->GetSpecialAbility(IMMUNE_MELEE_NONMAGICAL)) {
@@ -2980,12 +2993,16 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
if (parse->HasQuestSub(GetNPCTypeID(), EVENT_DEATH_COMPLETE)) {
const auto& export_string = fmt::format(
"{} {} {} {} {}",
"{} {} {} {} {} {} {} {} {}",
killer_mob ? killer_mob->GetID() : 0,
damage,
spell,
static_cast<int>(attack_skill),
entity_id
entity_id,
m_combat_record.GetStartTime(),
m_combat_record.GetEndTime(),
m_combat_record.GetDamageReceived(),
m_combat_record.GetHealingReceived()
);
std::vector<std::any> args = { corpse };
@@ -2996,12 +3013,16 @@ bool NPC::Death(Mob* killer_mob, int64 damage, uint16 spell, EQ::skills::SkillTy
// Zone controller process EVENT_DEATH_ZONE (Death events)
if (parse->HasQuestSub(ZONE_CONTROLLER_NPC_ID, EVENT_DEATH_ZONE)) {
const auto& export_string = fmt::format(
"{} {} {} {} {}",
"{} {} {} {} {} {} {} {} {}",
killer_mob ? killer_mob->GetID() : 0,
damage,
spell,
static_cast<int>(attack_skill),
entity_id
entity_id,
m_combat_record.GetStartTime(),
m_combat_record.GetEndTime(),
m_combat_record.GetDamageReceived(),
m_combat_record.GetHealingReceived()
);
std::vector<std::any> args = { corpse, this };
@@ -4071,6 +4092,10 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
//see if any runes want to reduce this damage
if (!IsValidSpell(spell_id)) {
if (IsClient()) {
CommonBreakInvisible();
}
damage = ReduceDamage(damage);
LogCombat("Melee Damage reduced to [{}]", damage);
damage = ReduceAllDamage(damage);
@@ -4102,8 +4127,9 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
TryTriggerThreshHold(damage, SE_TriggerSpellThreshold, attacker);
}
if (IsClient()) {
CommonBreakInvisible();
if (IsClient() && CastToClient()->sneaking) {
CastToClient()->sneaking = false;
SendAppearancePacket(AppearanceType::Sneak, 0);
}
if (attacker && attacker->IsClient() && attacker->CastToClient()->sneaking) {
+2 -2
View File
@@ -942,12 +942,12 @@ bool ZoneDatabase::GetAuraEntry(uint16 spell_id, AuraRecord& r)
return false;
}
auto e = l.front();
auto& e = l.front();
strn0cpy(r.name, e.name.c_str(), sizeof(r.name));
r.npc_type = e.npc_type;
r.spell_id = spell_id;
r.spell_id = e.spell_id;
r.distance = e.distance * e.distance;
r.aura_type = e.aura_type;
r.spawn_type = e.spawn_type;
+4 -6
View File
@@ -140,11 +140,8 @@ bool Beacon::Process()
if (caster && spell_iterations-- && max_targets) {
// NPCs should never be affected by an AE they cast. PB AEs shouldn't affect caster either
// I don't think any other cases that get here matter
const bool affect_caster = (
!caster->IsNPC() &&
!caster->IsAIControlled() &&
spells[spell_id].target_type != ST_AECaster
);
const bool affect_caster = (!caster->IsNPC() && !caster->IsAIControlled()) &&
spells[spell_id].target_type != ST_AECaster;
entity_list.AESpell(caster, this, spell_id, affect_caster, resist_adjust, &max_targets);
} else {
// spell is done casting, or caster disappeared
@@ -172,7 +169,8 @@ void Beacon::AELocationSpell(Mob *caster, uint16 cast_spell_id, int16 in_resist_
caster_id = caster->GetID();
spell_id = cast_spell_id;
resist_adjust = in_resist_adjust;
spell_iterations = ((spells[spell_id].aoe_duration / 2500) < 1) ? 1 : spell_iterations;
spell_iterations = spells[spell_id].aoe_duration / 2500;
spell_iterations = spell_iterations < 1 ? 1 : spell_iterations; // at least 1
if (spells[spell_id].aoe_max_targets) {
max_targets = spells[spell_id].aoe_max_targets;
+7
View File
@@ -8527,10 +8527,17 @@ void Bot::AddBotStartingItems(uint16 race_id, uint8 class_id)
(CanRaceEquipItem(e.item_id) || RuleB(Bots, AllowBotEquipAnyRaceGear))
) {
auto i = BotInventoriesRepository::NewEntity();
i.bot_id = GetBotID();
i.slot_id = e.slot_id;
i.item_id = e.item_id;
i.inst_charges = e.item_charges;
i.augment_1 = e.augment_one;
i.augment_2 = e.augment_two;
i.augment_3 = e.augment_three;
i.augment_4 = e.augment_four;
i.augment_5 = e.augment_five;
i.augment_6 = e.augment_six;
v.emplace_back(i);
}
-12
View File
@@ -2143,23 +2143,19 @@ bool helper_spell_list_fail(Client *bot_owner, bcst_list* spell_list, BCEnum::Sp
#include "bot_commands/escape.cpp"
#include "bot_commands/find_aliases.cpp"
#include "bot_commands/follow.cpp"
#include "bot_commands/follow_distance.cpp"
#include "bot_commands/guard.cpp"
#include "bot_commands/heal_rotation.cpp"
#include "bot_commands/help.cpp"
#include "bot_commands/hold.cpp"
#include "bot_commands/identify.cpp"
#include "bot_commands/inspect_message.cpp"
#include "bot_commands/inventory.cpp"
#include "bot_commands/invisibility.cpp"
#include "bot_commands/item_use.cpp"
#include "bot_commands/levitation.cpp"
#include "bot_commands/list.cpp"
#include "bot_commands/lull.cpp"
#include "bot_commands/mesmerize.cpp"
#include "bot_commands/movement_speed.cpp"
#include "bot_commands/name.cpp"
#include "bot_commands/out_of_combat.cpp"
#include "bot_commands/owner_option.cpp"
#include "bot_commands/pet.cpp"
#include "bot_commands/pick_lock.cpp"
@@ -2167,26 +2163,18 @@ bool helper_spell_list_fail(Client *bot_owner, bcst_list* spell_list, BCEnum::Sp
#include "bot_commands/precombat.cpp"
#include "bot_commands/pull.cpp"
#include "bot_commands/release.cpp"
#include "bot_commands/report.cpp"
#include "bot_commands/resistance.cpp"
#include "bot_commands/resurrect.cpp"
#include "bot_commands/rune.cpp"
#include "bot_commands/send_home.cpp"
#include "bot_commands/size.cpp"
#include "bot_commands/spell.cpp"
#include "bot_commands/stance.cpp"
#include "bot_commands/stop_melee_level.cpp"
#include "bot_commands/suffix.cpp"
#include "bot_commands/summon.cpp"
#include "bot_commands/summon_corpse.cpp"
#include "bot_commands/surname.cpp"
#include "bot_commands/suspend.cpp"
#include "bot_commands/taunt.cpp"
#include "bot_commands/teleport.cpp"
#include "bot_commands/timer.cpp"
#include "bot_commands/toggle_archer.cpp"
#include "bot_commands/toggle_helm.cpp"
#include "bot_commands/track.cpp"
#include "bot_commands/update.cpp"
#include "bot_commands/view_combos.cpp"
#include "bot_commands/water_breathing.cpp"
-1
View File
@@ -1 +0,0 @@
#include "../bot_command.h"
-1
View File
@@ -1 +0,0 @@
#include "../bot_command.h"
-1
View File
@@ -1 +0,0 @@
#include "../bot_command.h"
-1
View File
@@ -1 +0,0 @@
#include "../bot_command.h"
-1
View File
@@ -1 +0,0 @@
#include "../bot_command.h"
-1
View File
@@ -1 +0,0 @@
#include "../bot_command.h"
-1
View File
@@ -1 +0,0 @@
#include "../bot_command.h"
-1
View File
@@ -1 +0,0 @@
#include "../bot_command.h"
-1
View File
@@ -1 +0,0 @@
#include "../bot_command.h"
-1
View File
@@ -1 +0,0 @@
#include "../bot_command.h"
-1
View File
@@ -1 +0,0 @@
#include "../bot_command.h"
-1
View File
@@ -1 +0,0 @@
#include "../bot_command.h"
+62
View File
@@ -2318,3 +2318,65 @@ bool BotDatabase::SaveBotCasterRange(const uint32 bot_id, const uint32 bot_caste
return BotDataRepository::UpdateOne(database, e);
}
const uint8 BotDatabase::GetBotClassByID(const uint32 bot_id)
{
const auto& e = BotDataRepository::FindOne(database, bot_id);
return e.bot_id ? e.class_ : Class::None;
}
const uint8 BotDatabase::GetBotGenderByID(const uint32 bot_id)
{
const auto& e = BotDataRepository::FindOne(database, bot_id);
return e.bot_id ? e.gender : Gender::Neuter;
}
std::vector<uint32> BotDatabase::GetBotIDsByCharacterID(const uint32 character_id, uint8 class_id)
{
std::vector<uint32> v;
const auto& l = BotDataRepository::GetWhere(
database,
fmt::format(
"`owner_id` = {}{}",
character_id,
(
class_id ?
fmt::format(
" AND `class` = {}",
class_id
) :
""
)
)
);
for (const auto& e : l) {
v.push_back(e.bot_id);
}
return v;
}
const uint8 BotDatabase::GetBotLevelByID(const uint32 bot_id)
{
const auto& e = BotDataRepository::FindOne(database, bot_id);
return e.bot_id ? e.level : 0;
}
const std::string& BotDatabase::GetBotNameByID(const uint32 bot_id)
{
const auto& e = BotDataRepository::FindOne(database, bot_id);
return e.bot_id ? e.name : std::string();
}
const uint16 BotDatabase::GetBotRaceByID(const uint32 bot_id)
{
const auto& e = BotDataRepository::FindOne(database, bot_id);
return e.bot_id ? e.race : Race::Doug;
}
+7
View File
@@ -160,6 +160,13 @@ public:
uint32 GetRaceClassBitmask(uint32 bot_race);
const uint8 GetBotClassByID(const uint32 bot_id);
const uint8 GetBotGenderByID(const uint32 bot_id);
std::vector<uint32> GetBotIDsByCharacterID(const uint32 character_id, uint8 class_id = Class::None);
const uint8 GetBotLevelByID(const uint32 bot_id);
const std::string& GetBotNameByID(const uint32 bot_id);
const uint16 GetBotRaceByID(const uint32 bot_id);
class fail {
public:
/* fail::Bot functions */
+32 -8
View File
@@ -71,6 +71,7 @@ extern volatile bool RunLoops;
#include "../common/events/player_events.h"
#include "../common/events/player_event_logs.h"
#include "dialogue_window.h"
#include "../common/zone_store.h"
extern QueryServ* QServ;
@@ -9108,6 +9109,7 @@ void Client::ShowDevToolsMenu()
*/
menu_show += Saylink::Silent("#showzonepoints", "Zone Points");
menu_show += " | " + Saylink::Silent("#showzonegloballoot", "Zone Global Loot");
menu_show += " | " + Saylink::Silent("#show content_flags", "Content Flags");
/**
* Reload
@@ -9165,14 +9167,6 @@ void Client::ShowDevToolsMenu()
Message(Chat::White, "Developer Tools Menu");
Message(
Chat::White,
fmt::format(
"Current Expansion | {}",
content_service.GetCurrentExpansionName()
).c_str()
);
Message(
Chat::White,
fmt::format(
@@ -9288,6 +9282,36 @@ void Client::ShowDevToolsMenu()
);
SendChatLineBreak();
Message(
Chat::White,
fmt::format(
"Current Expansion | {} ({})",
content_service.GetCurrentExpansionName(),
content_service.GetCurrentExpansion()
).c_str()
);
auto z = GetZoneVersionWithFallback(zone->GetZoneID(), zone->GetInstanceVersion());
if (z) {
Message(
Chat::White,
fmt::format(
"Current Zone | [{}] ({}) version [{}] instance_id [{}] min/max expansion ({}/{}) content_flags [{}]",
z->short_name,
z->long_name,
z->version,
zone->GetInstanceID(),
z->min_expansion,
z->max_expansion,
z->content_flags
).c_str()
);
}
SendChatLineBreak();
}
void Client::SendChatLineBreak(uint16 color) {
+14 -10
View File
@@ -954,7 +954,6 @@ void Client::CompleteConnect()
heroforge_wearchange_timer.Start(250);
RecordStats();
AutoGrantAAPoints();
// enforce some rules..
@@ -7760,15 +7759,6 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app)
case GuildBankDeposit: // Deposit Item
{
if (GuildBanks->IsAreaFull(GuildID(), GuildBankDepositArea))
{
MessageString(Chat::Red, GUILD_BANK_FULL);
GuildBankDepositAck(true, sentAction);
return;
}
EQ::ItemInstance *CursorItemInst = GetInv().GetItem(EQ::invslot::slotCursor);
bool Allowed = true;
@@ -7784,6 +7774,18 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app)
const EQ::ItemData* CursorItem = CursorItemInst->GetItem();
if (GuildBanks->IsAreaFull(GuildID(), GuildBankDepositArea))
{
MessageString(Chat::Red, GUILD_BANK_FULL);
GuildBankDepositAck(true, sentAction);
if (ClientVersion() >= EQ::versions::ClientVersion::RoF) {
GetInv().PopItem(EQ::invslot::slotCursor);
PushItemOnCursor(CursorItem, true);
}
return;
}
if (!CursorItem->NoDrop || CursorItemInst->IsAttuned())
{
Allowed = false;
@@ -7811,6 +7813,7 @@ void Client::Handle_OP_GuildBank(const EQApplicationPacket *app)
GuildBankDepositAck(true, sentAction);
if (ClientVersion() >= EQ::versions::ClientVersion::RoF) {
GetInv().PopItem(EQ::invslot::slotCursor);
PushItemOnCursor(CursorItem, true);
}
return;
@@ -17138,3 +17141,4 @@ void Client::Handle_OP_GuildTributeDonatePlat(const EQApplicationPacket *app)
RequestGuildFavorAndTimer(GuildID());
}
}
+1 -1
View File
@@ -1072,7 +1072,7 @@ void Client::OPRezzAnswer(uint32 Action, uint32 SpellID, uint16 ZoneID, uint16 I
SetMana(GetMaxMana() / 20);
SetEndurance(GetMaxEndurance() / 20);
}
if(spells[SpellID].base_value[0] < 100 && spells[SpellID].base_value[0] > 0 && PendingRezzXP > 0) {
SetEXP(((int)(GetEXP()+((float)((PendingRezzXP / 100) * spells[SpellID].base_value[0])))),
GetAAXP(),true);
+20
View File
@@ -71,3 +71,23 @@ float CombatRecord::GetHealedReceivedPerSecond() const
double time_in_combat = TimeInCombat();
return time_in_combat > 0 ? (m_heal_received / time_in_combat) : m_heal_received;
}
time_t CombatRecord::GetStartTime() const
{
return m_start_time;
}
time_t CombatRecord::GetEndTime() const
{
return m_end_time;
}
int64 CombatRecord::GetDamageReceived() const
{
return m_damage_received;
}
int64 CombatRecord::GetHealingReceived() const
{
return m_heal_received;
}
+4
View File
@@ -14,6 +14,10 @@ public:
double TimeInCombat() const;
float GetDamageReceivedPerSecond() const;
float GetHealedReceivedPerSecond() const;
time_t GetStartTime() const;
time_t GetEndTime() const;
int64 GetDamageReceived() const;
int64 GetHealingReceived() const;
private:
std::string m_mob_name;
time_t m_start_time = 0;
+45 -1
View File
@@ -193,6 +193,13 @@ const char* QuestEventSubroutines[_LargestEventID] = {
"EVENT_ALT_CURRENCY_LOSS",
"EVENT_CRYSTAL_GAIN",
"EVENT_CRYSTAL_LOSS",
"EVENT_TIMER_PAUSE",
"EVENT_TIMER_RESUME",
"EVENT_TIMER_START",
"EVENT_TIMER_STOP",
"EVENT_ENTITY_VARIABLE_DELETE",
"EVENT_ENTITY_VARIABLE_SET",
"EVENT_ENTITY_VARIABLE_UPDATE",
// Add new events before these or Lua crashes
"EVENT_SPELL_EFFECT_BOT",
@@ -1668,11 +1675,21 @@ void PerlembParser::ExportEventVariables(
break;
}
case EVENT_TIMER: {
case EVENT_TIMER:
case EVENT_TIMER_STOP: {
ExportVar(package_name.c_str(), "timer", data);
break;
}
case EVENT_TIMER_PAUSE:
case EVENT_TIMER_RESUME:
case EVENT_TIMER_START: {
Seperator sep(data);
ExportVar(package_name.c_str(), "timer", sep.arg[0]);
ExportVar(package_name.c_str(), "duration", sep.arg[1]);
break;
}
case EVENT_SIGNAL: {
ExportVar(package_name.c_str(), "signal", data);
break;
@@ -2007,6 +2024,13 @@ void PerlembParser::ExportEventVariables(
ExportVar(package_name.c_str(), "killer_skill", sep.arg[3]);
ExportVar(package_name.c_str(), "killed_entity_id", sep.arg[4]);
if (sep.arg[5]) {
ExportVar(package_name.c_str(), "combat_start_time", sep.arg[5]);
ExportVar(package_name.c_str(), "combat_end_time", sep.arg[6]);
ExportVar(package_name.c_str(), "damage_received", sep.arg[7]);
ExportVar(package_name.c_str(), "healing_received", sep.arg[8]);
}
if (extra_pointers && extra_pointers->size() >= 1) {
Corpse* corpse = std::any_cast<Corpse*>(extra_pointers->at(0));
if (corpse) {
@@ -2409,6 +2433,26 @@ void PerlembParser::ExportEventVariables(
break;
}
case EVENT_ENTITY_VARIABLE_DELETE:
case EVENT_ENTITY_VARIABLE_SET: {
if (extra_pointers && extra_pointers->size() == 2) {
ExportVar(package_name.c_str(), "variable_name", std::any_cast<std::string>(extra_pointers->at(0)).c_str());
ExportVar(package_name.c_str(), "variable_value", std::any_cast<std::string>(extra_pointers->at(1)).c_str());
}
break;
}
case EVENT_ENTITY_VARIABLE_UPDATE: {
if (extra_pointers && extra_pointers->size() == 3) {
ExportVar(package_name.c_str(), "variable_name", std::any_cast<std::string>(extra_pointers->at(0)).c_str());
ExportVar(package_name.c_str(), "old_value", std::any_cast<std::string>(extra_pointers->at(1)).c_str());
ExportVar(package_name.c_str(), "new_value", std::any_cast<std::string>(extra_pointers->at(2)).c_str());
}
break;
}
default: {
break;
}
+95 -13
View File
@@ -313,12 +313,12 @@ int Perl__getinventoryslotid(std::string identifier)
return result;
}
void Perl__castspell(int spell_id, int target_id)
void Perl__castspell(uint16 spell_id, uint16 target_id)
{
quest_manager.castspell(spell_id, target_id);
}
void Perl__selfcast(int spell_id)
void Perl__selfcast(uint16 spell_id)
{
quest_manager.selfcast(spell_id);
}
@@ -353,47 +353,67 @@ void Perl__zoneraid(const char* zone_name)
quest_manager.ZoneRaid(zone_name);
}
bool Perl__hastimer(const char* timer_name)
bool Perl__hastimer(std::string timer_name)
{
return quest_manager.hastimer(timer_name);
}
bool Perl__ispausedtimer(const char* timer_name)
bool Perl__ispausedtimer(std::string timer_name)
{
return quest_manager.ispausedtimer(timer_name);
}
uint32_t Perl__getremainingtimeMS(const char* timer_name)
uint32_t Perl__getremainingtimeMS(std::string timer_name)
{
return quest_manager.getremainingtimeMS(timer_name);
}
uint32_t Perl__gettimerdurationMS(const char* timer_name)
uint32_t Perl__gettimerdurationMS(std::string timer_name)
{
return quest_manager.gettimerdurationMS(timer_name);
}
void Perl__settimer(const char* timer_name, int seconds)
void Perl__settimer(std::string timer_name, uint32 seconds)
{
quest_manager.settimer(timer_name, seconds);
}
void Perl__settimerMS(const char* timer_name, int milliseconds)
void Perl__settimer(std::string timer_name, uint32 seconds, Mob* m)
{
quest_manager.settimer(timer_name, seconds);
}
void Perl__settimer(std::string timer_name, uint32 seconds, EQ::ItemInstance* inst)
{
quest_manager.settimer(timer_name, seconds);
}
void Perl__settimerMS(std::string timer_name, uint32 milliseconds)
{
quest_manager.settimerMS(timer_name, milliseconds);
}
void Perl__pausetimer(const char* timer_name)
void Perl__settimerMS(std::string timer_name, uint32 milliseconds, Mob* m)
{
quest_manager.settimerMS(timer_name, milliseconds, m);
}
void Perl__settimerMS(std::string timer_name, uint32 milliseconds, EQ::ItemInstance* inst)
{
quest_manager.settimerMS(timer_name, milliseconds, inst);
}
void Perl__pausetimer(std::string timer_name)
{
quest_manager.pausetimer(timer_name);
}
void Perl__resumetimer(const char* timer_name)
void Perl__resumetimer(std::string timer_name)
{
quest_manager.resumetimer(timer_name);
}
void Perl__stoptimer(const char* timer_name)
void Perl__stoptimer(std::string timer_name)
{
quest_manager.stoptimer(timer_name);
}
@@ -5762,6 +5782,57 @@ std::string Perl__convert_money_to_string(perl::hash table)
return Strings::Money(platinum, gold, silver, copper);
}
uint8 Perl__GetBotClassByID(uint32 bot_id)
{
return database.botdb.GetBotClassByID(bot_id);
}
uint8 Perl__GetBotGenderByID(uint32 bot_id)
{
return database.botdb.GetBotGenderByID(bot_id);
}
perl::array Perl__GetBotIDsByCharacterID(uint32 character_id)
{
perl::array result;
const auto bot_ids = database.botdb.GetBotIDsByCharacterID(character_id);
for (int i = 0; i < bot_ids.size(); i++) {
result.push_back(bot_ids[i]);
}
return result;
}
perl::array Perl__GetBotIDsByCharacterID(uint32 character_id, uint8 class_id)
{
perl::array result;
const auto bot_ids = database.botdb.GetBotIDsByCharacterID(character_id, class_id);
for (int i = 0; i < bot_ids.size(); i++) {
result.push_back(bot_ids[i]);
}
return result;
}
uint8 Perl__GetBotLevelByID(uint32 bot_id)
{
return database.botdb.GetBotLevelByID(bot_id);
}
std::string Perl__GetBotNameByID(uint32 bot_id)
{
return database.botdb.GetBotNameByID(bot_id);
}
uint16 Perl__GetBotRaceByID(uint32 bot_id)
{
return database.botdb.GetBotRaceByID(bot_id);
}
void perl_register_quest()
{
perl::interpreter perl(PERL_GET_THX);
@@ -5792,6 +5863,13 @@ void perl_register_quest()
package.add("FlagInstanceByGroupLeader", &Perl__FlagInstanceByGroupLeader);
package.add("FlagInstanceByRaidLeader", &Perl__FlagInstanceByRaidLeader);
package.add("FlyMode", &Perl__FlyMode);
package.add("GetBotClassByID", &Perl__GetBotClassByID);
package.add("GetBotGenderByID", &Perl__GetBotGenderByID);
package.add("GetBotIDsByCharacterID", (perl::array(*)(uint32))&Perl__GetBotIDsByCharacterID);
package.add("GetBotIDsByCharacterID", (perl::array(*)(uint32, uint8))&Perl__GetBotIDsByCharacterID);
package.add("GetBotLevelByID", &Perl__GetBotLevelByID);
package.add("GetBotNameByID", &Perl__GetBotNameByID);
package.add("GetBotRaceByID", &Perl__GetBotRaceByID);
package.add("GetCharactersInInstance", &Perl__GetCharactersInInstance);
package.add("GetInstanceID", &Perl__GetInstanceID);
package.add("GetInstanceIDByCharID", &Perl__GetInstanceIDByCharID);
@@ -6606,8 +6684,12 @@ void perl_register_quest()
package.add("settarget", &Perl__settarget);
package.add("settime", (void(*)(int, int))&Perl__settime);
package.add("settime", (void(*)(int, int, bool))&Perl__settime);
package.add("settimer", &Perl__settimer);
package.add("settimerMS", &Perl__settimerMS);
package.add("settimer", (void(*)(std::string, uint32))&Perl__settimer),
package.add("settimer", (void(*)(std::string, uint32, EQ::ItemInstance*))&Perl__settimer),
package.add("settimer", (void(*)(std::string, uint32, Mob*))&Perl__settimer),
package.add("settimerMS", (void(*)(std::string, uint32))&Perl__settimerMS);
package.add("settimerMS", (void(*)(std::string, uint32, EQ::ItemInstance*))&Perl__settimerMS);
package.add("settimerMS", (void(*)(std::string, uint32, Mob*))&Perl__settimerMS);
package.add("sfollow", &Perl__sfollow);
package.add("shout", &Perl__shout);
package.add("shout2", &Perl__shout2);
+7
View File
@@ -135,6 +135,13 @@ typedef enum {
EVENT_ALT_CURRENCY_LOSS,
EVENT_CRYSTAL_GAIN,
EVENT_CRYSTAL_LOSS,
EVENT_TIMER_PAUSE,
EVENT_TIMER_RESUME,
EVENT_TIMER_START,
EVENT_TIMER_STOP,
EVENT_ENTITY_VARIABLE_DELETE,
EVENT_ENTITY_VARIABLE_SET,
EVENT_ENTITY_VARIABLE_UPDATE,
// Add new events before these or Lua crashes
EVENT_SPELL_EFFECT_BOT,
+20 -10
View File
@@ -625,19 +625,29 @@ void Client::SetEXP(uint64 set_exp, uint64 set_aaxp, bool isrezzexp) {
else MessageString(Chat::Experience, REZ_REGAIN);
} else {
if (membercount > 1) {
if (RuleI(Character, ShowExpValues) > 0)
if (RuleI(Character, ShowExpValues) > 0) {
Message(Chat::Experience, "You have gained %s party experience! %s", exp_amount_message.c_str(), exp_percent_message.c_str());
else MessageString(Chat::Experience, GAIN_GROUPXP);
}
else if (IsRaidGrouped()) {
if (RuleI(Character, ShowExpValues) > 0)
} else if (zone->IsHotzone()) {
Message(Chat::Experience, "You gain party experience (with a bonus)!");
} else {
MessageString(Chat::Experience, GAIN_GROUPXP);
}
} else if (IsRaidGrouped()) {
if (RuleI(Character, ShowExpValues) > 0) {
Message(Chat::Experience, "You have gained %s raid experience! %s", exp_amount_message.c_str(), exp_percent_message.c_str());
else MessageString(Chat::Experience, GAIN_RAIDEXP);
}
else {
if (RuleI(Character, ShowExpValues) > 0)
} else if (zone->IsHotzone()) {
Message(Chat::Experience, "You gained raid experience (with a bonus)!");
} else {
MessageString(Chat::Experience, GAIN_RAIDEXP);
}
} else {
if (RuleI(Character, ShowExpValues) > 0) {
Message(Chat::Experience, "You have gained %s experience! %s", exp_amount_message.c_str(), exp_percent_message.c_str());
else MessageString(Chat::Experience, GAIN_XP);
} else if (zone->IsHotzone()) {
Message(Chat::Experience, "You gain experience (with a bonus)!");
} else {
MessageString(Chat::Experience, GAIN_XP);
}
}
}
}
+3 -3
View File
@@ -1161,7 +1161,7 @@ void Expedition::AddLockoutByCharacterName(
{
if (!character_name.empty())
{
uint32_t character_id = database.GetCharacterID(character_name.c_str());
uint32_t character_id = database.GetCharacterID(character_name);
AddLockoutByCharacterID(character_id, expedition_name, event_name, seconds, uuid);
}
}
@@ -1180,7 +1180,7 @@ bool Expedition::HasLockoutByCharacterName(
{
if (!character_name.empty())
{
uint32_t character_id = database.GetCharacterID(character_name.c_str());
uint32_t character_id = database.GetCharacterID(character_name);
return HasLockoutByCharacterID(character_id, expedition_name, event_name);
}
return false;
@@ -1214,7 +1214,7 @@ void Expedition::RemoveLockoutsByCharacterName(
{
if (!character_name.empty())
{
uint32_t character_id = database.GetCharacterID(character_name.c_str());
uint32_t character_id = database.GetCharacterID(character_name);
RemoveLockoutsByCharacterID(character_id, expedition_name, event_name);
}
}
+1 -1
View File
@@ -126,7 +126,7 @@ bool ExpeditionRequest::CanGroupRequest(Group* group)
// Group::GetLeaderName() is broken if group formed across zones, ask database instead
m_leader_name = m_leader ? m_leader->GetName() : GetGroupLeaderName(group->GetID()); // group->GetLeaderName();
m_leader_id = m_leader ? m_leader->CharacterID() : database.GetCharacterID(m_leader_name.c_str());
m_leader_id = m_leader ? m_leader->CharacterID() : database.GetCharacterID(m_leader_name);
std::vector<std::string> member_names;
member_names.emplace_back(m_leader_name); // leader always added first
+2 -2
View File
@@ -80,7 +80,7 @@ void command_instance(Client *c, const Seperator *sep)
std::string character_name = sep->arg[3];
uint16 instance_id = static_cast<uint16>(Strings::ToUnsignedInt(sep->arg[2]));
uint32 character_id = database.GetCharacterID(character_name.c_str());
uint32 character_id = database.GetCharacterID(character_name);
if (instance_id <= 0 || character_id <= 0) {
c->Message(Chat::White, "You must enter a valid Instance ID and player name.");
return;
@@ -270,7 +270,7 @@ void command_instance(Client *c, const Seperator *sep)
std::string character_name = sep->arg[3];
uint16 instance_id = static_cast<uint16>(Strings::ToUnsignedInt(sep->arg[2]));
uint32 character_id = database.GetCharacterID(character_name.c_str());
uint32 character_id = database.GetCharacterID(character_name);
if (instance_id <= 0 || character_id <= 0) {
c->Message(Chat::White, "You must enter a valid Instance ID and player name.");
return;
+1 -1
View File
@@ -13,7 +13,7 @@ void command_movechar(Client *c, const Seperator *sep)
database.GetCharNameByID(Strings::ToUnsignedInt(sep->arg[1])) :
sep->arg[1]
);
const uint32 character_id = database.GetCharacterID(character_name.c_str());
const uint32 character_id = database.GetCharacterID(character_name);
if (!character_id) {
c->Message(
Chat::White,
+2
View File
@@ -5,6 +5,7 @@
#include "show/buffs.cpp"
#include "show/buried_corpse_count.cpp"
#include "show/client_version_summary.cpp"
#include "show/content_flags.cpp"
#include "show/currencies.cpp"
#include "show/distance.cpp"
#include "show/emotes.cpp"
@@ -64,6 +65,7 @@ void command_show(Client *c, const Seperator *sep)
Cmd{.cmd = "buffs", .u = "buffs", .fn = ShowBuffs, .a = {"#showbuffs"}},
Cmd{.cmd = "buried_corpse_count", .u = "buried_corpse_count", .fn = ShowBuriedCorpseCount, .a = {"#getplayerburiedcorpsecount"}},
Cmd{.cmd = "client_version_summary", .u = "client_version_summary", .fn = ShowClientVersionSummary, .a = {"#cvs"}},
Cmd{.cmd = "content_flags", .u = "content_flags", .fn = ShowContentFlags, .a = {"#showcontentflags"}},
Cmd{.cmd = "currencies", .u = "currencies", .fn = ShowCurrencies, .a = {"#viewcurrencies"}},
Cmd{.cmd = "distance", .u = "distance", .fn = ShowDistance, .a = {"#distance"}},
Cmd{.cmd = "emotes", .u = "emotes", .fn = ShowEmotes, .a = {"#emoteview"}},
+30
View File
@@ -0,0 +1,30 @@
#include "../../client.h"
#include "../../dialogue_window.h"
void ShowContentFlags(Client *c, const Seperator *sep)
{
Client *t = c;
if (c->GetTarget() && c->GetTarget()->IsClient()) {
t = c->GetTarget()->CastToClient();
}
std::string flags = DialogueWindow::TableRow(
DialogueWindow::TableCell("id") +
DialogueWindow::TableCell("flag_name") +
DialogueWindow::TableCell("enabled")
);
for (auto &f: ContentFlagsRepository::All(database)) {
flags += DialogueWindow::TableRow(
DialogueWindow::TableCell(std::to_string(f.id)) +
DialogueWindow::TableCell(f.flag_name) +
DialogueWindow::TableCell(
f.enabled ?
DialogueWindow::ColorMessage("forest_green", "yes") :
DialogueWindow::ColorMessage("red", "no")
)
);
}
c->SendPopupToClient("Server Content Flag Settings", DialogueWindow::Table(flags).c_str());
}
+1 -1
View File
@@ -16,7 +16,7 @@ void command_summon(Client *c, const Seperator *sep)
if (arguments == 1) {
std::string character_name = sep->arg[1];
auto character_id = database.GetCharacterID(character_name.c_str());
auto character_id = database.GetCharacterID(character_name);
if (!character_id) {
c->Message(
Chat::White,
+47 -40
View File
@@ -514,14 +514,18 @@ void ZoneGuildManager::ProcessWorldPacket(ServerPacket *pack)
}
case ServerOP_GuildPermissionUpdate: {
if (is_zone_loaded) {
auto *sgpus = (ServerGuildPermissionUpdate_Struct *) pack->pBuffer;
auto res = m_guilds.find(sgpus->guild_id);
if (sgpus->function_value) {
res->second->functions[sgpus->function_id].perm_value |= (1UL << (8 - sgpus->rank));
}
else {
res->second->functions[sgpus->function_id].perm_value &= ~(1UL << (8 - sgpus->rank));
}
auto *sgpus = (ServerGuildPermissionUpdate_Struct *)pack->pBuffer;
auto guild = GetGuildByGuildID(sgpus->guild_id);
if (!guild) {
return;
}
if (sgpus->function_value) {
guild->functions[sgpus->function_id].perm_value |= (1UL << (8 - sgpus->rank));
}
else {
guild->functions[sgpus->function_id].perm_value &= ~(1UL << (8 - sgpus->rank));
}
auto outapp = new EQApplicationPacket(OP_GuildUpdate, sizeof(GuildPermission_Struct));
auto *guuacs = (GuildPermission_Struct *) outapp->pBuffer;
@@ -797,7 +801,7 @@ void GuildBankManager::SendGuildBank(Client *c)
outapp->WriteUInt32(Item->Icon);
if (Item->Stackable) {
outapp->WriteUInt32(guild_bank->Items.DepositArea[i].Quantity);
outapp->WriteUInt8(Item->StackSize == guild_bank->Items.DepositArea[i].Quantity ? 0 : 1);
outapp->WriteUInt8(Item->StackSize == guild_bank->Items.DepositArea[i].Quantity ? 1 : 1);
} else {
outapp->WriteUInt32(1);
outapp->WriteUInt8(0);
@@ -821,7 +825,7 @@ void GuildBankManager::SendGuildBank(Client *c)
outapp->WriteUInt32(Item->Icon);
if (Item->Stackable) {
outapp->WriteUInt32(guild_bank->Items.MainArea[i].Quantity);
outapp->WriteUInt8(Item->StackSize == guild_bank->Items.MainArea[i].Quantity ? 0 : 1);
outapp->WriteUInt8(Item->StackSize == guild_bank->Items.MainArea[i].Quantity ? 1 : 1);
} else {
outapp->WriteUInt32(1);
outapp->WriteUInt8(0);
@@ -858,7 +862,7 @@ void GuildBankManager::SendGuildBank(Client *c)
{
if(guild_bank->Items.DepositArea[i].Quantity == Item->StackSize)
gbius->Init(GuildBankItemUpdate, 1, i, GuildBankDepositArea, 1, Item->ID, Item->Icon,
guild_bank->Items.DepositArea[i].Quantity, guild_bank->Items.DepositArea[i].Permissions, 0, 0);
guild_bank->Items.DepositArea[i].Quantity, guild_bank->Items.DepositArea[i].Permissions, 1, 0);
else
gbius->Init(GuildBankItemUpdate, 1, i, GuildBankDepositArea, 1, Item->ID, Item->Icon,
guild_bank->Items.DepositArea[i].Quantity, guild_bank->Items.DepositArea[i].Permissions, 1, 0);
@@ -896,7 +900,7 @@ void GuildBankManager::SendGuildBank(Client *c)
{
if(guild_bank->Items.MainArea[i].Quantity == Item->StackSize)
gbius->Init(GuildBankItemUpdate, 1, i, GuildBankMainArea, 1, Item->ID, Item->Icon,
guild_bank->Items.MainArea[i].Quantity, guild_bank->Items.MainArea[i].Permissions, 0, Useable);
guild_bank->Items.MainArea[i].Quantity, guild_bank->Items.MainArea[i].Permissions, 1, Useable);
else
gbius->Init(GuildBankItemUpdate, 1, i, GuildBankMainArea, 1, Item->ID, Item->Icon,
guild_bank->Items.MainArea[i].Quantity, guild_bank->Items.MainArea[i].Permissions, 1, Useable);
@@ -1018,7 +1022,7 @@ bool GuildBankManager::AddItem(uint32 GuildID, uint8 Area, uint32 ItemID, int32
else
{
if(QtyOrCharges == Item->StackSize)
gbius.Init(GuildBankItemUpdate, 1, Slot, Area, 1, ItemID, Item->Icon, Item->Stackable ? QtyOrCharges : 1, Permissions, 0, 0);
gbius.Init(GuildBankItemUpdate, 1, Slot, Area, 1, ItemID, Item->Icon, Item->Stackable ? QtyOrCharges : 1, Permissions, 1, 0);
else
gbius.Init(GuildBankItemUpdate, 1, Slot, Area, 1, ItemID, Item->Icon, Item->Stackable ? QtyOrCharges : 1, Permissions, 1, 0);
}
@@ -1085,7 +1089,7 @@ int GuildBankManager::Promote(uint32 guildID, int slotID)
{
if((*iter)->Items.MainArea[mainSlot].Quantity == Item->StackSize)
gbius.Init(GuildBankItemUpdate, 1, mainSlot, GuildBankMainArea, 1, Item->ID, Item->Icon,
(*iter)->Items.MainArea[mainSlot].Quantity, 0, 0, 0);
(*iter)->Items.MainArea[mainSlot].Quantity, 0, 1, 0);
else
gbius.Init(GuildBankItemUpdate, 1, mainSlot, GuildBankMainArea, 1, Item->ID, Item->Icon,
(*iter)->Items.MainArea[mainSlot].Quantity, 0, 1, 0);
@@ -1141,7 +1145,7 @@ void GuildBankManager::SetPermissions(uint32 guildID, uint16 slotID, uint32 perm
{
if((*iter)->Items.MainArea[slotID].Quantity == Item->StackSize)
gbius.Init(GuildBankItemUpdate, 1, slotID, GuildBankMainArea, 1, Item->ID, Item->Icon,
(*iter)->Items.MainArea[slotID].Quantity, (*iter)->Items.MainArea[slotID].Permissions, 0, 0);
(*iter)->Items.MainArea[slotID].Quantity, (*iter)->Items.MainArea[slotID].Permissions, 1, 0);
else
gbius.Init(GuildBankItemUpdate, 1, slotID, GuildBankMainArea, 1, Item->ID, Item->Icon,
(*iter)->Items.MainArea[slotID].Quantity, (*iter)->Items.MainArea[slotID].Permissions, 1, 0);
@@ -1384,7 +1388,7 @@ bool GuildBankManager::MergeStacks(uint32 GuildID, uint16 SlotID)
GuildBankItemUpdate_Struct gbius;
if(BankArea[i].Quantity == Item->StackSize)
gbius.Init(GuildBankItemUpdate, 1, i, GuildBankMainArea, 1, ItemID, Item->Icon, BankArea[i].Quantity, BankArea[i].Permissions, 0, 0);
gbius.Init(GuildBankItemUpdate, 1, i, GuildBankMainArea, 1, ItemID, Item->Icon, BankArea[i].Quantity, BankArea[i].Permissions, 1, 0);
else
gbius.Init(GuildBankItemUpdate, 1, i, GuildBankMainArea, 1, ItemID, Item->Icon, BankArea[i].Quantity, BankArea[i].Permissions, 1, 0);
@@ -1489,16 +1493,20 @@ bool GuildBankManager::AllowedToWithdraw(uint32 GuildID, uint16 Area, uint16 Slo
void ZoneGuildManager::UpdateRankPermission(uint32 gid, uint32 charid, uint32 fid, uint32 rank, uint32 value)
{
auto res = m_guilds.find(gid);
if (value) {
res->second->functions[fid].perm_value |= (1UL << (8 - rank));
}
else {
res->second->functions[fid].perm_value &= ~(1UL << (8 - rank));
}
auto query = fmt::format("UPDATE guild_permissions SET permission = {} WHERE perm_id = {} AND guild_id = {};", res->second->functions[fid].perm_value, fid, gid);
auto results = m_db->QueryDatabase(query);
auto guild = GetGuildByGuildID(gid);
if (!guild) {
return;
}
if (value) {
guild->functions[fid].perm_value |= (1UL << (8 - rank));
}
else {
guild->functions[fid].perm_value &= ~(1UL << (8 - rank));
}
auto query = fmt::format("UPDATE guild_permissions SET permission = {} WHERE perm_id = {} AND guild_id = {};",
guild->functions[fid].perm_value, fid, gid);
auto results = m_db->QueryDatabase(query);
}
void ZoneGuildManager::SendPermissionUpdate(uint32 guild_id, uint32 rank, uint32 function_id, uint32 value)
@@ -1534,21 +1542,20 @@ void ZoneGuildManager::SendRankName(uint32 guild_id, uint32 rank, std::string ra
void ZoneGuildManager::SendAllRankNames(uint32 guild_id, uint32 char_id)
{
auto guild = m_guilds.find(guild_id);
auto c = entity_list.GetClientByCharID(char_id);
if (c)
{
auto outapp = new EQApplicationPacket(OP_GuildUpdate, sizeof(GuildUpdateUCPStruct));
GuildUpdateUCPStruct* gucp = (GuildUpdateUCPStruct*)outapp->pBuffer;
for (int i = GUILD_LEADER; i <= GUILD_RECRUIT; i++)
{
gucp->payload.rank_name.rank = i;
strn0cpy(gucp->payload.rank_name.rank_name, guild->second->rank_names[i].c_str(), sizeof(gucp->payload.rank_name.rank_name));
gucp->action = GuildUpdateRanks;
c->QueuePacket(outapp);
}
safe_delete(outapp);
}
auto guild = GetGuildByGuildID(guild_id);
auto c = entity_list.GetClientByCharID(char_id);
if (guild && c) {
auto outapp = new EQApplicationPacket(OP_GuildUpdate, sizeof(GuildUpdateUCPStruct));
GuildUpdateUCPStruct *gucp = (GuildUpdateUCPStruct *)outapp->pBuffer;
for (int i = GUILD_LEADER; i <= GUILD_RECRUIT; i++) {
gucp->payload.rank_name.rank = i;
strn0cpy(gucp->payload.rank_name.rank_name, guild->rank_names[i].c_str(),
sizeof(gucp->payload.rank_name.rank_name));
gucp->action = GuildUpdateRanks;
c->QueuePacket(outapp);
}
safe_delete(outapp);
}
}
BaseGuildManager::GuildInfo* ZoneGuildManager::GetGuildByGuildID(uint32 guild_id)
+31 -7
View File
@@ -73,20 +73,18 @@ void HateList::WipeHateList(bool npc_only) {
}
}
bool HateList::IsEntOnHateList(Mob *mob)
bool HateList::IsEntOnHateList(Mob* m)
{
if (Find(mob))
return true;
return false;
return m ? Find(m) != nullptr : false;
}
struct_HateList* HateList::Find(Mob* m)
{
if (!m) {
if (!m || list.empty()) {
return nullptr;
}
for (auto* e : list) {
for (auto e : list) {
if (e->entity_on_hatelist && e->entity_on_hatelist == m) {
return e;
}
@@ -685,7 +683,33 @@ int64 HateList::GetEntHateAmount(Mob *in_entity, bool damage)
}
bool HateList::IsHateListEmpty() {
return(list.size() == 0);
return list.empty();
}
uint32 HateList::GetHateListCount(HateListCountType count_type)
{
if (count_type == HateListCountType::All) {
return list.size();
}
uint32 count = 0;
for (const auto& e : list) {
Mob* m = e->entity_on_hatelist;
if (
m &&
(
(count_type == HateListCountType::Bot && m->IsBot()) ||
(count_type == HateListCountType::Client && m->IsClient()) ||
(count_type == HateListCountType::NPC && m->IsNPC())
)
) {
count++;
}
}
return count;
}
void HateList::PrintHateListToClient(Client *c)
+9 -1
View File
@@ -36,6 +36,13 @@ struct struct_HateList {
uint32 last_modified; // we need to remove this if it gets higher than 10 mins
};
enum class HateListCountType {
Bot = 0,
Client = 1,
NPC = 2,
All = 3,
};
class HateList {
public:
HateList();
@@ -48,9 +55,10 @@ public:
Mob *GetMobWithMostHateOnList(bool skip_mezzed = false);
Mob *GetEscapingMobOnHateList(Mob *center, float range = 0.0f, bool first = false);
bool IsEntOnHateList(Mob *mob);
bool IsEntOnHateList(Mob* m);
bool IsHateListEmpty();
bool RemoveEntFromHateList(Mob *ent);
uint32 GetHateListCount(HateListCountType count_type = HateListCountType::All);
int AreaRampage(Mob *caster, Mob *target, int count, ExtraAttackOptions *opts);
int GetSummonedPetCountOnHateList();
+7
View File
@@ -3290,6 +3290,12 @@ int Lua_Client::GetEXPPercentage()
return self->GetEXPPercentage();
}
bool Lua_Client::IsInAGuild()
{
Lua_Safe_Call_Bool();
return self->IsInAGuild();
}
luabind::scope lua_register_client() {
return luabind::class_<Lua_Client, Lua_Mob>("Client")
.def(luabind::constructor<>())
@@ -3578,6 +3584,7 @@ luabind::scope lua_register_client() {
.def("IsDueling", (bool(Lua_Client::*)(void))&Lua_Client::IsDueling)
.def("IsEXPEnabled", (bool(Lua_Client::*)(void))&Lua_Client::IsEXPEnabled)
.def("IsGrouped", (bool(Lua_Client::*)(void))&Lua_Client::IsGrouped)
.def("IsInAGuild", (bool(Lua_Client::*)(void))&Lua_Client::IsInAGuild)
.def("IsLD", (bool(Lua_Client::*)(void))&Lua_Client::IsLD)
.def("IsMedding", (bool(Lua_Client::*)(void))&Lua_Client::IsMedding)
.def("IsRaidGrouped", (bool(Lua_Client::*)(void))&Lua_Client::IsRaidGrouped)
+1
View File
@@ -495,6 +495,7 @@ public:
void ClearXTargets();
int GetAAEXPPercentage();
int GetEXPPercentage();
bool IsInAGuild();
void ApplySpell(int spell_id);
void ApplySpell(int spell_id, int duration);
+114 -29
View File
@@ -299,35 +299,35 @@ void lua_disable_spawn2(int spawn2_id) {
quest_manager.disable_spawn2(spawn2_id);
}
void lua_set_timer(const char *timer, int time_ms) {
void lua_set_timer(std::string timer, uint32 time_ms) {
quest_manager.settimerMS(timer, time_ms);
}
void lua_set_timer(const char *timer, int time_ms, Lua_ItemInst inst) {
void lua_set_timer(std::string timer, uint32 time_ms, Lua_ItemInst inst) {
quest_manager.settimerMS(timer, time_ms, inst);
}
void lua_set_timer(const char *timer, int time_ms, Lua_Mob mob) {
void lua_set_timer(std::string timer, uint32 time_ms, Lua_Mob mob) {
quest_manager.settimerMS(timer, time_ms, mob);
}
void lua_set_timer(const char *timer, int time_ms, Lua_Encounter enc) {
void lua_set_timer(std::string timer, uint32 time_ms, Lua_Encounter enc) {
quest_manager.settimerMS(timer, time_ms, enc);
}
void lua_stop_timer(const char *timer) {
void lua_stop_timer(std::string timer) {
quest_manager.stoptimer(timer);
}
void lua_stop_timer(const char *timer, Lua_ItemInst inst) {
void lua_stop_timer(std::string timer, Lua_ItemInst inst) {
quest_manager.stoptimer(timer, inst);
}
void lua_stop_timer(const char *timer, Lua_Mob mob) {
void lua_stop_timer(std::string timer, Lua_Mob mob) {
quest_manager.stoptimer(timer, mob);
}
void lua_stop_timer(const char *timer, Lua_Encounter enc) {
void lua_stop_timer(std::string timer, Lua_Encounter enc) {
quest_manager.stoptimer(timer, enc);
}
@@ -347,27 +347,27 @@ void lua_stop_all_timers(Lua_Encounter enc) {
quest_manager.stopalltimers(enc);
}
void lua_pause_timer(const char *timer) {
void lua_pause_timer(std::string timer) {
quest_manager.pausetimer(timer);
}
void lua_resume_timer(const char *timer) {
void lua_resume_timer(std::string timer) {
quest_manager.resumetimer(timer);
}
bool lua_is_paused_timer(const char *timer) {
bool lua_is_paused_timer(std::string timer) {
return quest_manager.ispausedtimer(timer);
}
bool lua_has_timer(const char *timer) {
bool lua_has_timer(std::string timer) {
return quest_manager.hastimer(timer);
}
uint32 lua_get_remaining_time(const char *timer) {
uint32 lua_get_remaining_time(std::string timer) {
return quest_manager.getremainingtimeMS(timer);
}
uint32 lua_get_timer_duration(const char *timer) {
uint32 lua_get_timer_duration(std::string timer) {
return quest_manager.gettimerdurationMS(timer);
}
@@ -5406,6 +5406,75 @@ std::string lua_convert_money_to_string(luabind::adl::object table)
return Strings::Money(platinum, gold, silver, copper);
}
void lua_cast_spell(uint16 spell_id, uint16 target_id)
{
quest_manager.castspell(spell_id, target_id);
}
void lua_self_cast(uint16 spell_id)
{
quest_manager.selfcast(spell_id);
}
uint8 lua_get_bot_class_by_id(uint32 bot_id)
{
return database.botdb.GetBotClassByID(bot_id);
}
uint8 lua_get_bot_gender_by_id(uint32 bot_id)
{
return database.botdb.GetBotGenderByID(bot_id);
}
luabind::object lua_get_bot_ids_by_character_id(lua_State* L, uint32 character_id)
{
auto lua_table = luabind::newtable(L);
const auto& l = database.botdb.GetBotIDsByCharacterID(character_id);
if (!l.empty()) {
int index = 1;
for (const auto& i : l) {
lua_table[index] = i;
index++;
}
}
return lua_table;
}
luabind::object lua_get_bot_ids_by_character_id(lua_State* L, uint32 character_id, uint8 class_id)
{
auto lua_table = luabind::newtable(L);
const auto& l = database.botdb.GetBotIDsByCharacterID(character_id, class_id);
if (!l.empty()) {
int index = 1;
for (const auto& i : l) {
lua_table[index] = i;
index++;
}
}
return lua_table;
}
uint8 lua_get_bot_level_by_id(uint32 bot_id)
{
return database.botdb.GetBotLevelByID(bot_id);
}
std::string lua_get_bot_name_by_id(uint32 bot_id)
{
return database.botdb.GetBotNameByID(bot_id);
}
uint16 lua_get_bot_race_by_id(uint32 bot_id)
{
return database.botdb.GetBotRaceByID(bot_id);
}
#define LuaCreateNPCParse(name, c_type, default_value) do { \
cur = table[#name]; \
if(luabind::type(cur) != LUA_TNIL) { \
@@ -5613,20 +5682,20 @@ luabind::scope lua_register_general() {
luabind::def("spawn_from_spawn2", (Lua_Mob(*)(uint32))&lua_spawn_from_spawn2),
luabind::def("enable_spawn2", &lua_enable_spawn2),
luabind::def("disable_spawn2", &lua_disable_spawn2),
luabind::def("has_timer", (bool(*)(const char*))&lua_has_timer),
luabind::def("get_remaining_time", (uint32(*)(const char*))&lua_get_remaining_time),
luabind::def("get_timer_duration", (uint32(*)(const char*))&lua_get_timer_duration),
luabind::def("set_timer", (void(*)(const char*, int))&lua_set_timer),
luabind::def("set_timer", (void(*)(const char*, int, Lua_ItemInst))&lua_set_timer),
luabind::def("set_timer", (void(*)(const char*, int, Lua_Mob))&lua_set_timer),
luabind::def("set_timer", (void(*)(const char*, int, Lua_Encounter))&lua_set_timer),
luabind::def("stop_timer", (void(*)(const char*))&lua_stop_timer),
luabind::def("stop_timer", (void(*)(const char*, Lua_ItemInst))&lua_stop_timer),
luabind::def("stop_timer", (void(*)(const char*, Lua_Mob))&lua_stop_timer),
luabind::def("stop_timer", (void(*)(const char*, Lua_Encounter))&lua_stop_timer),
luabind::def("pause_timer", (void(*)(const char*))&lua_pause_timer),
luabind::def("resume_timer", (void(*)(const char*))&lua_resume_timer),
luabind::def("is_paused_timer", (bool(*)(const char*))&lua_is_paused_timer),
luabind::def("has_timer", (bool(*)(std::string))&lua_has_timer),
luabind::def("get_remaining_time", (uint32(*)(std::string))&lua_get_remaining_time),
luabind::def("get_timer_duration", (uint32(*)(std::string))&lua_get_timer_duration),
luabind::def("set_timer", (void(*)(std::string, uint32))&lua_set_timer),
luabind::def("set_timer", (void(*)(std::string, uint32, Lua_ItemInst))&lua_set_timer),
luabind::def("set_timer", (void(*)(std::string, uint32, Lua_Mob))&lua_set_timer),
luabind::def("set_timer", (void(*)(std::string, uint32, Lua_Encounter))&lua_set_timer),
luabind::def("stop_timer", (void(*)(std::string))&lua_stop_timer),
luabind::def("stop_timer", (void(*)(std::string, Lua_ItemInst))&lua_stop_timer),
luabind::def("stop_timer", (void(*)(std::string, Lua_Mob))&lua_stop_timer),
luabind::def("stop_timer", (void(*)(std::string, Lua_Encounter))&lua_stop_timer),
luabind::def("pause_timer", (void(*)(std::string))&lua_pause_timer),
luabind::def("resume_timer", (void(*)(std::string))&lua_resume_timer),
luabind::def("is_paused_timer", (bool(*)(std::string))&lua_is_paused_timer),
luabind::def("stop_all_timers", (void(*)(void))&lua_stop_all_timers),
luabind::def("stop_all_timers", (void(*)(Lua_ItemInst))&lua_stop_all_timers),
luabind::def("stop_all_timers", (void(*)(Lua_Mob))&lua_stop_all_timers),
@@ -6187,6 +6256,15 @@ luabind::scope lua_register_general() {
luabind::def("get_spell_resurrection_sickness_check", &lua_get_spell_resurrection_sickness_check),
luabind::def("get_spell_nimbus_effect", &lua_get_spell_nimbus_effect),
luabind::def("convert_money_to_string", &lua_convert_money_to_string),
luabind::def("cast_spell", &lua_cast_spell),
luabind::def("self_cast", &lua_self_cast),
luabind::def("get_bot_class_by_id", &lua_get_bot_class_by_id),
luabind::def("get_bot_gender_by_id", &lua_get_bot_gender_by_id),
luabind::def("get_bot_ids_by_character_id", (luabind::object(*)(lua_State*, uint32))&lua_get_bot_ids_by_character_id),
luabind::def("get_bot_ids_by_character_id", (luabind::object(*)(lua_State*, uint32,uint8))&lua_get_bot_ids_by_character_id),
luabind::def("get_bot_level_by_id", &lua_get_bot_level_by_id),
luabind::def("get_bot_name_by_id", &lua_get_bot_name_by_id),
luabind::def("get_bot_race_by_id", &lua_get_bot_race_by_id),
/*
Cross Zone
*/
@@ -6644,7 +6722,14 @@ luabind::scope lua_register_events() {
luabind::value("alt_currency_gain", static_cast<int>(EVENT_ALT_CURRENCY_GAIN)),
luabind::value("alt_currency_loss", static_cast<int>(EVENT_ALT_CURRENCY_LOSS)),
luabind::value("crystal_gain", static_cast<int>(EVENT_CRYSTAL_GAIN)),
luabind::value("crystal_loss", static_cast<int>(EVENT_CRYSTAL_LOSS))
luabind::value("crystal_loss", static_cast<int>(EVENT_CRYSTAL_LOSS)),
luabind::value("timer_pause", static_cast<int>(EVENT_TIMER_PAUSE)),
luabind::value("timer_resume", static_cast<int>(EVENT_TIMER_RESUME)),
luabind::value("timer_start", static_cast<int>(EVENT_TIMER_START)),
luabind::value("timer_stop", static_cast<int>(EVENT_TIMER_STOP)),
luabind::value("entity_variable_delete", static_cast<int>(EVENT_ENTITY_VARIABLE_DELETE)),
luabind::value("entity_variable_set", static_cast<int>(EVENT_ENTITY_VARIABLE_SET)),
luabind::value("entity_variable_update", static_cast<int>(EVENT_ENTITY_VARIABLE_UPDATE))
)];
}
+21
View File
@@ -317,6 +317,26 @@ void Lua_ItemInst::ItemSay(const char* text, uint8 language_id) // @categories I
quest_manager.GetInitiator()->ChannelMessageSend(self->GetItem()->Name, 0, ChatChannel_Say, language_id, Language::MaxValue, text);
}
luabind::object Lua_ItemInst::GetAugmentIDs(lua_State* L)
{
auto lua_table = luabind::newtable(L);
if (d_) {
auto self = reinterpret_cast<NativeType*>(d_);
const auto& augment_ids = self->GetAugmentIDs();
int index = 1;
for (auto augment_id : augment_ids) {
lua_table[index] = augment_id;
index++;
}
}
return lua_table;
}
luabind::scope lua_register_iteminst() {
return luabind::class_<Lua_ItemInst>("ItemInst")
.def(luabind::constructor<>())
@@ -331,6 +351,7 @@ luabind::scope lua_register_iteminst() {
.def("CountAugmentByID", (int(Lua_ItemInst::*)(uint32))&Lua_ItemInst::CountAugmentByID)
.def("DeleteCustomData", (void(Lua_ItemInst::*)(const std::string &))&Lua_ItemInst::DeleteCustomData)
.def("GetAugment", (Lua_ItemInst(Lua_ItemInst::*)(int))&Lua_ItemInst::GetAugment)
.def("GetAugmentIDs", (luabind::object(Lua_ItemInst::*)(lua_State*))&Lua_ItemInst::GetAugmentIDs)
.def("GetAugmentItemID", (uint32(Lua_ItemInst::*)(int))&Lua_ItemInst::GetAugmentItemID)
.def("GetAugmentType", (int(Lua_ItemInst::*)(void))&Lua_ItemInst::GetAugmentType)
.def("GetCharges", (int(Lua_ItemInst::*)(void))&Lua_ItemInst::GetCharges)
+1
View File
@@ -89,6 +89,7 @@ public:
std::string GetName();
void ItemSay(const char* text);
void ItemSay(const char* text, uint8 language_id);
luabind::object GetAugmentIDs(lua_State* L);
private:
bool cloned_;
+77
View File
@@ -3201,6 +3201,72 @@ uint32 Lua_Mob::GetMobTypeIdentifier()
return self->GetMobTypeIdentifier();
}
uint32 Lua_Mob::GetHateListCount()
{
Lua_Safe_Call_Int();
return self->GetHateListCount();
}
uint32 Lua_Mob::GetHateListBotCount()
{
Lua_Safe_Call_Int();
return self->GetHateListCount(HateListCountType::Bot);
}
uint32 Lua_Mob::GetHateListClientCount()
{
Lua_Safe_Call_Int();
return self->GetHateListCount(HateListCountType::Client);
}
uint32 Lua_Mob::GetHateListNPCCount()
{
Lua_Safe_Call_Int();
return self->GetHateListCount(HateListCountType::NPC);
}
bool Lua_Mob::IsAnimation()
{
Lua_Safe_Call_Bool();
return self->IsAnimation();
}
bool Lua_Mob::IsCharmed()
{
Lua_Safe_Call_Bool();
return self->IsCharmed();
}
bool Lua_Mob::IsFamiliar()
{
Lua_Safe_Call_Bool();
return self->IsFamiliar();
}
bool Lua_Mob::IsTargetLockPet()
{
Lua_Safe_Call_Bool();
return self->IsTargetLockPet();
}
bool Lua_Mob::IsPetOwnerBot()
{
Lua_Safe_Call_Bool();
return self->IsPetOwnerBot();
}
bool Lua_Mob::IsPetOwnerClient()
{
Lua_Safe_Call_Bool();
return self->IsPetOwnerClient();
}
bool Lua_Mob::IsPetOwnerNPC()
{
Lua_Safe_Call_Bool();
return self->IsPetOwnerNPC();
}
luabind::scope lua_register_mob() {
return luabind::class_<Lua_Mob, Lua_Entity>("Mob")
.def(luabind::constructor<>())
@@ -3460,12 +3526,16 @@ luabind::scope lua_register_mob() {
.def("GetHateList", &Lua_Mob::GetHateList)
.def("GetHateListBots", (Lua_HateList(Lua_Mob::*)(void))&Lua_Mob::GetHateListBots)
.def("GetHateListBots", (Lua_HateList(Lua_Mob::*)(uint32))&Lua_Mob::GetHateListBots)
.def("GetHateListBotCount", &Lua_Mob::GetHateListBotCount)
.def("GetHateListClients", (Lua_HateList(Lua_Mob::*)(void))&Lua_Mob::GetHateListClients)
.def("GetHateListClients", (Lua_HateList(Lua_Mob::*)(uint32))&Lua_Mob::GetHateListClients)
.def("GetHateListClientCount", &Lua_Mob::GetHateListClientCount)
.def("GetHateListNPCs", (Lua_HateList(Lua_Mob::*)(void))&Lua_Mob::GetHateListNPCs)
.def("GetHateListNPCs", (Lua_HateList(Lua_Mob::*)(uint32))&Lua_Mob::GetHateListNPCs)
.def("GetHateListNPCCount", &Lua_Mob::GetHateListNPCCount)
.def("GetHateListByDistance", (Lua_HateList(Lua_Mob::*)(void))&Lua_Mob::GetHateListByDistance)
.def("GetHateListByDistance", (Lua_HateList(Lua_Mob::*)(uint32))&Lua_Mob::GetHateListByDistance)
.def("GetHateListCount", &Lua_Mob::GetHateListCount)
.def("GetHateRandom", (Lua_Mob(Lua_Mob::*)(void))&Lua_Mob::GetHateRandom)
.def("GetHateRandomBot", (Lua_Bot(Lua_Mob::*)(void))&Lua_Mob::GetHateRandomBot)
.def("GetHateRandomClient", (Lua_Client(Lua_Mob::*)(void))&Lua_Mob::GetHateRandomClient)
@@ -3573,15 +3643,18 @@ luabind::scope lua_register_mob() {
.def("InterruptSpell", (void(Lua_Mob::*)(void))&Lua_Mob::InterruptSpell)
.def("IsAIControlled", (bool(Lua_Mob::*)(void))&Lua_Mob::IsAIControlled)
.def("IsAmnesiad", (bool(Lua_Mob::*)(void))&Lua_Mob::IsAmnesiad)
.def("IsAnimation", &Lua_Mob::IsAnimation)
.def("IsAttackAllowed", (bool(Lua_Mob::*)(Lua_Mob))&Lua_Mob::IsAttackAllowed)
.def("IsAttackAllowed", (bool(Lua_Mob::*)(Lua_Mob,bool))&Lua_Mob::IsAttackAllowed)
.def("IsBeneficialAllowed", (bool(Lua_Mob::*)(Lua_Mob))&Lua_Mob::IsBeneficialAllowed)
.def("IsBerserk", &Lua_Mob::IsBerserk)
.def("IsBlind", (bool(Lua_Mob::*)(void))&Lua_Mob::IsBlind)
.def("IsCasting", &Lua_Mob::IsCasting)
.def("IsCharmed", &Lua_Mob::IsCharmed)
.def("IsEliteMaterialItem", (uint32(Lua_Mob::*)(uint8))&Lua_Mob::IsEliteMaterialItem)
.def("IsEngaged", (bool(Lua_Mob::*)(void))&Lua_Mob::IsEngaged)
.def("IsEnraged", (bool(Lua_Mob::*)(void))&Lua_Mob::IsEnraged)
.def("IsFamiliar", &Lua_Mob::IsFamiliar)
.def("IsFeared", (bool(Lua_Mob::*)(void))&Lua_Mob::IsFeared)
.def("IsFindable", (bool(Lua_Mob::*)(void))&Lua_Mob::IsFindable)
.def("IsHorse", &Lua_Mob::IsHorse)
@@ -3593,6 +3666,9 @@ luabind::scope lua_register_mob() {
.def("IsMoving", &Lua_Mob::IsMoving)
.def("IsPausedTimer", &Lua_Mob::IsPausedTimer)
.def("IsPet", (bool(Lua_Mob::*)(void))&Lua_Mob::IsPet)
.def("IsPetOwnerBot", &Lua_Mob::IsPetOwnerBot)
.def("IsPetOwnerClient", &Lua_Mob::IsPetOwnerClient)
.def("IsPetOwnerNPC", &Lua_Mob::IsPetOwnerNPC)
.def("IsRoamer", (bool(Lua_Mob::*)(void))&Lua_Mob::IsRoamer)
.def("IsRooted", (bool(Lua_Mob::*)(void))&Lua_Mob::IsRooted)
.def("IsRunning", (bool(Lua_Mob::*)(void))&Lua_Mob::IsRunning)
@@ -3600,6 +3676,7 @@ luabind::scope lua_register_mob() {
.def("IsStunned", (bool(Lua_Mob::*)(void))&Lua_Mob::IsStunned)
.def("IsTargetable", (bool(Lua_Mob::*)(void))&Lua_Mob::IsTargetable)
.def("IsTargeted", &Lua_Mob::IsTargeted)
.def("IsTargetLockPet", &Lua_Mob::IsTargetLockPet)
.def("IsTemporaryPet", &Lua_Mob::IsTemporaryPet)
.def("IsTrackable", (bool(Lua_Mob::*)(void))&Lua_Mob::IsTrackable)
.def("IsWarriorClass", &Lua_Mob::IsWarriorClass)
+11
View File
@@ -566,6 +566,17 @@ public:
std::string GetRacePlural();
bool IsTemporaryPet();
uint32 GetMobTypeIdentifier();
uint32 GetHateListCount();
uint32 GetHateListBotCount();
uint32 GetHateListClientCount();
uint32 GetHateListNPCCount();
bool IsAnimation();
bool IsCharmed();
bool IsFamiliar();
bool IsTargetLockPet();
bool IsPetOwnerBot();
bool IsPetOwnerClient();
bool IsPetOwnerNPC();
};
#endif
+9 -3
View File
@@ -378,7 +378,7 @@ bool Lua_NPC::GetFollowCanRun() {
return self->GetFollowCanRun();
}
int Lua_NPC::GetNPCSpellsID() {
uint32 Lua_NPC::GetNPCSpellsID() {
Lua_Safe_Call_Int();
return self->GetNPCSpellsID();
}
@@ -825,6 +825,12 @@ void Lua_NPC::SetNPCAggro(bool in_npc_aggro)
self->SetNPCAggro(in_npc_aggro);
}
uint32 Lua_NPC::GetNPCSpellsEffectsID()
{
Lua_Safe_Call_Int();
return self->GetNPCSpellsEffectsID();
}
luabind::scope lua_register_npc() {
return luabind::class_<Lua_NPC, Lua_Mob>("NPC")
.def(luabind::constructor<>())
@@ -887,8 +893,8 @@ luabind::scope lua_register_npc() {
.def("GetNPCAggro", (bool(Lua_NPC::*)(void))&Lua_NPC::GetNPCAggro)
.def("GetNPCFactionID", (int(Lua_NPC::*)(void))&Lua_NPC::GetNPCFactionID)
.def("GetNPCHate", (int64(Lua_NPC::*)(Lua_Mob))&Lua_NPC::GetNPCHate)
.def("GetNPCSpellsID", (int(Lua_NPC::*)(void))&Lua_NPC::GetNPCSpellsID)
.def("GetNPCSpellsID", (int(Lua_NPC::*)(void))&Lua_NPC::GetNPCSpellsID)
.def("GetNPCSpellsEffectsID", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetNPCSpellsEffectsID)
.def("GetNPCSpellsID", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetNPCSpellsID)
.def("GetNPCStat", (float(Lua_NPC::*)(std::string))&Lua_NPC::GetNPCStat)
.def("GetPetSpellID", (int(Lua_NPC::*)(void))&Lua_NPC::GetPetSpellID)
.def("GetPlatinum", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetPlatinum)
+2 -1
View File
@@ -102,7 +102,7 @@ public:
int GetFollowID();
int GetFollowDistance();
bool GetFollowCanRun();
int GetNPCSpellsID();
uint32 GetNPCSpellsID();
int GetSpawnPointID();
float GetSpawnPointX();
float GetSpawnPointY();
@@ -184,6 +184,7 @@ public:
void SetBucket(std::string bucket_name, std::string bucket_value, std::string expiration);
bool GetNPCAggro();
void SetNPCAggro(bool in_npc_aggro);
uint32 GetNPCSpellsEffectsID();
};
#endif
+125 -78
View File
@@ -175,7 +175,14 @@ const char *LuaEvents[_LargestEventID] = {
"event_alt_currency_gain",
"event_alt_currency_loss",
"event_crystal_gain",
"event_crystal_loss"
"event_crystal_loss",
"event_timer_pause",
"event_timer_resume",
"event_timer_start",
"event_timer_stop",
"event_entity_variable_delete",
"event_entity_variable_set",
"event_entity_variable_update"
};
extern Zone *zone;
@@ -190,6 +197,14 @@ std::map<std::string, std::list<lua_registered_event>> lua_encounter_events_regi
std::map<std::string, bool> lua_encounters_loaded;
std::map<std::string, Encounter *> lua_encounters;
// use debug.traceback() for errors (luaL_traceback is only in luajit and lua 5.2+)
static void PushErrorHandler(lua_State* L)
{
lua_getglobal(L, "debug");
lua_getfield(L, -1, "traceback");
lua_remove(L, -2);
}
LuaParser::LuaParser() {
for (int i = 0; i < _LargestEventID; ++i) {
NPCArgumentDispatch[i] = handle_npc_null;
@@ -200,40 +215,47 @@ LuaParser::LuaParser() {
BotArgumentDispatch[i] = handle_bot_null;
}
NPCArgumentDispatch[EVENT_SAY] = handle_npc_event_say;
NPCArgumentDispatch[EVENT_AGGRO_SAY] = handle_npc_event_say;
NPCArgumentDispatch[EVENT_PROXIMITY_SAY] = handle_npc_event_say;
NPCArgumentDispatch[EVENT_TRADE] = handle_npc_event_trade;
NPCArgumentDispatch[EVENT_HP] = handle_npc_event_hp;
NPCArgumentDispatch[EVENT_TARGET_CHANGE] = handle_npc_single_mob;
NPCArgumentDispatch[EVENT_CAST_ON] = handle_npc_cast;
NPCArgumentDispatch[EVENT_KILLED_MERIT] = handle_npc_single_client;
NPCArgumentDispatch[EVENT_SLAY] = handle_npc_single_mob;
NPCArgumentDispatch[EVENT_ENTER] = handle_npc_single_client;
NPCArgumentDispatch[EVENT_EXIT] = handle_npc_single_client;
NPCArgumentDispatch[EVENT_TASK_ACCEPTED] = handle_npc_task_accepted;
NPCArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_npc_popup;
NPCArgumentDispatch[EVENT_WAYPOINT_ARRIVE] = handle_npc_waypoint;
NPCArgumentDispatch[EVENT_WAYPOINT_DEPART] = handle_npc_waypoint;
NPCArgumentDispatch[EVENT_HATE_LIST] = handle_npc_hate;
NPCArgumentDispatch[EVENT_COMBAT] = handle_npc_hate;
NPCArgumentDispatch[EVENT_SIGNAL] = handle_npc_signal;
NPCArgumentDispatch[EVENT_TIMER] = handle_npc_timer;
NPCArgumentDispatch[EVENT_DEATH] = handle_npc_death;
NPCArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_npc_death;
NPCArgumentDispatch[EVENT_DEATH_ZONE] = handle_npc_death;
NPCArgumentDispatch[EVENT_CAST] = handle_npc_cast;
NPCArgumentDispatch[EVENT_CAST_BEGIN] = handle_npc_cast;
NPCArgumentDispatch[EVENT_FEIGN_DEATH] = handle_npc_single_client;
NPCArgumentDispatch[EVENT_ENTER_AREA] = handle_npc_area;
NPCArgumentDispatch[EVENT_LEAVE_AREA] = handle_npc_area;
NPCArgumentDispatch[EVENT_LOOT_ZONE] = handle_npc_loot_zone;
NPCArgumentDispatch[EVENT_SPAWN_ZONE] = handle_npc_spawn_zone;
NPCArgumentDispatch[EVENT_PAYLOAD] = handle_npc_payload;
NPCArgumentDispatch[EVENT_DESPAWN_ZONE] = handle_npc_despawn_zone;
NPCArgumentDispatch[EVENT_DAMAGE_GIVEN] = handle_npc_damage;
NPCArgumentDispatch[EVENT_DAMAGE_TAKEN] = handle_npc_damage;
NPCArgumentDispatch[EVENT_LOOT_ADDED] = handle_npc_loot_added;
NPCArgumentDispatch[EVENT_SAY] = handle_npc_event_say;
NPCArgumentDispatch[EVENT_AGGRO_SAY] = handle_npc_event_say;
NPCArgumentDispatch[EVENT_PROXIMITY_SAY] = handle_npc_event_say;
NPCArgumentDispatch[EVENT_TRADE] = handle_npc_event_trade;
NPCArgumentDispatch[EVENT_HP] = handle_npc_event_hp;
NPCArgumentDispatch[EVENT_TARGET_CHANGE] = handle_npc_single_mob;
NPCArgumentDispatch[EVENT_CAST_ON] = handle_npc_cast;
NPCArgumentDispatch[EVENT_KILLED_MERIT] = handle_npc_single_client;
NPCArgumentDispatch[EVENT_SLAY] = handle_npc_single_mob;
NPCArgumentDispatch[EVENT_ENTER] = handle_npc_single_client;
NPCArgumentDispatch[EVENT_EXIT] = handle_npc_single_client;
NPCArgumentDispatch[EVENT_TASK_ACCEPTED] = handle_npc_task_accepted;
NPCArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_npc_popup;
NPCArgumentDispatch[EVENT_WAYPOINT_ARRIVE] = handle_npc_waypoint;
NPCArgumentDispatch[EVENT_WAYPOINT_DEPART] = handle_npc_waypoint;
NPCArgumentDispatch[EVENT_HATE_LIST] = handle_npc_hate;
NPCArgumentDispatch[EVENT_COMBAT] = handle_npc_hate;
NPCArgumentDispatch[EVENT_SIGNAL] = handle_npc_signal;
NPCArgumentDispatch[EVENT_TIMER] = handle_npc_timer;
NPCArgumentDispatch[EVENT_DEATH] = handle_npc_death;
NPCArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_npc_death;
NPCArgumentDispatch[EVENT_DEATH_ZONE] = handle_npc_death;
NPCArgumentDispatch[EVENT_CAST] = handle_npc_cast;
NPCArgumentDispatch[EVENT_CAST_BEGIN] = handle_npc_cast;
NPCArgumentDispatch[EVENT_FEIGN_DEATH] = handle_npc_single_client;
NPCArgumentDispatch[EVENT_ENTER_AREA] = handle_npc_area;
NPCArgumentDispatch[EVENT_LEAVE_AREA] = handle_npc_area;
NPCArgumentDispatch[EVENT_LOOT_ZONE] = handle_npc_loot_zone;
NPCArgumentDispatch[EVENT_SPAWN_ZONE] = handle_npc_spawn_zone;
NPCArgumentDispatch[EVENT_PAYLOAD] = handle_npc_payload;
NPCArgumentDispatch[EVENT_DESPAWN_ZONE] = handle_npc_despawn_zone;
NPCArgumentDispatch[EVENT_DAMAGE_GIVEN] = handle_npc_damage;
NPCArgumentDispatch[EVENT_DAMAGE_TAKEN] = handle_npc_damage;
NPCArgumentDispatch[EVENT_LOOT_ADDED] = handle_npc_loot_added;
NPCArgumentDispatch[EVENT_TIMER_PAUSE] = handle_npc_timer_pause_resume_start;
NPCArgumentDispatch[EVENT_TIMER_RESUME] = handle_npc_timer_pause_resume_start;
NPCArgumentDispatch[EVENT_TIMER_START] = handle_npc_timer_pause_resume_start;
NPCArgumentDispatch[EVENT_TIMER_STOP] = handle_npc_timer_stop;
NPCArgumentDispatch[EVENT_ENTITY_VARIABLE_DELETE] = handle_npc_entity_variable;
NPCArgumentDispatch[EVENT_ENTITY_VARIABLE_SET] = handle_npc_entity_variable;
NPCArgumentDispatch[EVENT_ENTITY_VARIABLE_UPDATE] = handle_npc_entity_variable;
PlayerArgumentDispatch[EVENT_SAY] = handle_player_say;
PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage;
@@ -314,6 +336,13 @@ LuaParser::LuaParser() {
PlayerArgumentDispatch[EVENT_ALT_CURRENCY_LOSS] = handle_player_alt_currency_gain_loss;
PlayerArgumentDispatch[EVENT_CRYSTAL_GAIN] = handle_player_crystal_gain_loss;
PlayerArgumentDispatch[EVENT_CRYSTAL_LOSS] = handle_player_crystal_gain_loss;
PlayerArgumentDispatch[EVENT_TIMER_PAUSE] = handle_player_timer_pause_resume_start;
PlayerArgumentDispatch[EVENT_TIMER_RESUME] = handle_player_timer_pause_resume_start;
PlayerArgumentDispatch[EVENT_TIMER_START] = handle_player_timer_pause_resume_start;
PlayerArgumentDispatch[EVENT_TIMER_STOP] = handle_player_timer_stop;
PlayerArgumentDispatch[EVENT_ENTITY_VARIABLE_DELETE] = handle_player_entity_variable;
PlayerArgumentDispatch[EVENT_ENTITY_VARIABLE_SET] = handle_player_entity_variable;
PlayerArgumentDispatch[EVENT_ENTITY_VARIABLE_UPDATE] = handle_player_entity_variable;
ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click;
ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click;
@@ -326,6 +355,10 @@ LuaParser::LuaParser() {
ItemArgumentDispatch[EVENT_UNAUGMENT_ITEM] = handle_item_augment;
ItemArgumentDispatch[EVENT_AUGMENT_INSERT] = handle_item_augment_insert;
ItemArgumentDispatch[EVENT_AUGMENT_REMOVE] = handle_item_augment_remove;
ItemArgumentDispatch[EVENT_TIMER_PAUSE] = handle_item_timer_pause_resume_start;
ItemArgumentDispatch[EVENT_TIMER_RESUME] = handle_item_timer_pause_resume_start;
ItemArgumentDispatch[EVENT_TIMER_START] = handle_item_timer_pause_resume_start;
ItemArgumentDispatch[EVENT_TIMER_STOP] = handle_item_timer_stop;
SpellArgumentDispatch[EVENT_SPELL_EFFECT_CLIENT] = handle_spell_event;
SpellArgumentDispatch[EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT] = handle_spell_event;
@@ -336,27 +369,34 @@ LuaParser::LuaParser() {
EncounterArgumentDispatch[EVENT_ENCOUNTER_LOAD] = handle_encounter_load;
EncounterArgumentDispatch[EVENT_ENCOUNTER_UNLOAD] = handle_encounter_unload;
BotArgumentDispatch[EVENT_CAST] = handle_bot_cast;
BotArgumentDispatch[EVENT_CAST_BEGIN] = handle_bot_cast;
BotArgumentDispatch[EVENT_CAST_ON] = handle_bot_cast;
BotArgumentDispatch[EVENT_COMBAT] = handle_bot_combat;
BotArgumentDispatch[EVENT_DEATH] = handle_bot_death;
BotArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_bot_death;
BotArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_bot_popup_response;
BotArgumentDispatch[EVENT_SAY] = handle_bot_say;
BotArgumentDispatch[EVENT_SIGNAL] = handle_bot_signal;
BotArgumentDispatch[EVENT_SLAY] = handle_bot_slay;
BotArgumentDispatch[EVENT_TARGET_CHANGE] = handle_bot_target_change;
BotArgumentDispatch[EVENT_TIMER] = handle_bot_timer;
BotArgumentDispatch[EVENT_TRADE] = handle_bot_trade;
BotArgumentDispatch[EVENT_USE_SKILL] = handle_bot_use_skill;
BotArgumentDispatch[EVENT_PAYLOAD] = handle_bot_payload;
BotArgumentDispatch[EVENT_EQUIP_ITEM_BOT] = handle_bot_equip_item;
BotArgumentDispatch[EVENT_UNEQUIP_ITEM_BOT] = handle_bot_equip_item;
BotArgumentDispatch[EVENT_DAMAGE_GIVEN] = handle_bot_damage;
BotArgumentDispatch[EVENT_DAMAGE_TAKEN] = handle_bot_damage;
BotArgumentDispatch[EVENT_LEVEL_UP] = handle_bot_level_up;
BotArgumentDispatch[EVENT_LEVEL_DOWN] = handle_bot_level_down;
BotArgumentDispatch[EVENT_CAST] = handle_bot_cast;
BotArgumentDispatch[EVENT_CAST_BEGIN] = handle_bot_cast;
BotArgumentDispatch[EVENT_CAST_ON] = handle_bot_cast;
BotArgumentDispatch[EVENT_COMBAT] = handle_bot_combat;
BotArgumentDispatch[EVENT_DEATH] = handle_bot_death;
BotArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_bot_death;
BotArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_bot_popup_response;
BotArgumentDispatch[EVENT_SAY] = handle_bot_say;
BotArgumentDispatch[EVENT_SIGNAL] = handle_bot_signal;
BotArgumentDispatch[EVENT_SLAY] = handle_bot_slay;
BotArgumentDispatch[EVENT_TARGET_CHANGE] = handle_bot_target_change;
BotArgumentDispatch[EVENT_TIMER] = handle_bot_timer;
BotArgumentDispatch[EVENT_TRADE] = handle_bot_trade;
BotArgumentDispatch[EVENT_USE_SKILL] = handle_bot_use_skill;
BotArgumentDispatch[EVENT_PAYLOAD] = handle_bot_payload;
BotArgumentDispatch[EVENT_EQUIP_ITEM_BOT] = handle_bot_equip_item;
BotArgumentDispatch[EVENT_UNEQUIP_ITEM_BOT] = handle_bot_equip_item;
BotArgumentDispatch[EVENT_DAMAGE_GIVEN] = handle_bot_damage;
BotArgumentDispatch[EVENT_DAMAGE_TAKEN] = handle_bot_damage;
BotArgumentDispatch[EVENT_LEVEL_UP] = handle_bot_level_up;
BotArgumentDispatch[EVENT_LEVEL_DOWN] = handle_bot_level_down;
BotArgumentDispatch[EVENT_TIMER_PAUSE] = handle_bot_timer_pause_resume_start;
BotArgumentDispatch[EVENT_TIMER_RESUME] = handle_bot_timer_pause_resume_start;
BotArgumentDispatch[EVENT_TIMER_START] = handle_bot_timer_pause_resume_start;
BotArgumentDispatch[EVENT_TIMER_STOP] = handle_bot_timer_stop;
BotArgumentDispatch[EVENT_ENTITY_VARIABLE_DELETE] = handle_bot_entity_variable;
BotArgumentDispatch[EVENT_ENTITY_VARIABLE_SET] = handle_bot_entity_variable;
BotArgumentDispatch[EVENT_ENTITY_VARIABLE_UPDATE] = handle_bot_entity_variable;
#endif
L = nullptr;
@@ -416,13 +456,14 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M
int start = lua_gettop(L);
try {
int npop = 1;
int npop = 2;
PushErrorHandler(L);
if(l_func != nullptr) {
l_func->push(L);
} else {
lua_getfield(L, LUA_REGISTRYINDEX, package_name.c_str());
lua_getfield(L, -1, sub_name);
npop = 2;
npop = 3;
}
lua_createtable(L, 0, 0);
@@ -437,7 +478,7 @@ int LuaParser::_EventNPC(std::string package_name, QuestEventID evt, NPC* npc, M
Client *c = (init && init->IsClient()) ? init->CastToClient() : nullptr;
quest_manager.StartQuest(npc, c);
if(lua_pcall(L, 1, 1, 0)) {
if(lua_pcall(L, 1, 1, start + 1)) {
std::string error = lua_tostring(L, -1);
AddError(error);
quest_manager.EndQuest();
@@ -509,13 +550,14 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client *
int start = lua_gettop(L);
try {
int npop = 1;
int npop = 2;
PushErrorHandler(L);
if(l_func != nullptr) {
l_func->push(L);
} else {
lua_getfield(L, LUA_REGISTRYINDEX, package_name.c_str());
lua_getfield(L, -1, sub_name);
npop = 2;
npop = 3;
}
lua_createtable(L, 0, 0);
@@ -529,7 +571,7 @@ int LuaParser::_EventPlayer(std::string package_name, QuestEventID evt, Client *
arg_function(this, L, client, data, extra_data, extra_pointers);
quest_manager.StartQuest(client, client);
if(lua_pcall(L, 1, 1, 0)) {
if(lua_pcall(L, 1, 1, start + 1)) {
std::string error = lua_tostring(L, -1);
AddError(error);
quest_manager.EndQuest();
@@ -586,13 +628,14 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl
int start = lua_gettop(L);
try {
int npop = 1;
int npop = 2;
PushErrorHandler(L);
if(l_func != nullptr) {
l_func->push(L);
} else {
lua_getfield(L, LUA_REGISTRYINDEX, package_name.c_str());
lua_getfield(L, -1, sub_name);
npop = 2;
npop = 3;
}
lua_createtable(L, 0, 0);
@@ -612,7 +655,7 @@ int LuaParser::_EventItem(std::string package_name, QuestEventID evt, Client *cl
arg_function(this, L, client, item, mob, data, extra_data, extra_pointers);
quest_manager.StartQuest(client, client, item);
if(lua_pcall(L, 1, 1, 0)) {
if(lua_pcall(L, 1, 1, start + 1)) {
std::string error = lua_tostring(L, -1);
AddError(error);
quest_manager.EndQuest();
@@ -666,13 +709,14 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, Mob* mob,
int start = lua_gettop(L);
try {
int npop = 1;
int npop = 2;
PushErrorHandler(L);
if(l_func != nullptr) {
l_func->push(L);
} else {
lua_getfield(L, LUA_REGISTRYINDEX, package_name.c_str());
lua_getfield(L, -1, sub_name);
npop = 2;
npop = 3;
}
lua_createtable(L, 0, 0);
@@ -693,7 +737,7 @@ int LuaParser::_EventSpell(std::string package_name, QuestEventID evt, Mob* mob,
arg_function(this, L, mob, client, spell_id, data, extra_data, extra_pointers);
quest_manager.StartQuest(mob, client, nullptr, const_cast<SPDat_Spell_Struct*>(&spells[spell_id]));
if(lua_pcall(L, 1, 1, 0)) {
if(lua_pcall(L, 1, 1, start + 1)) {
std::string error = lua_tostring(L, -1);
AddError(error);
quest_manager.EndQuest();
@@ -745,6 +789,7 @@ int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std::
int start = lua_gettop(L);
try {
PushErrorHandler(L);
lua_getfield(L, LUA_REGISTRYINDEX, package_name.c_str());
lua_getfield(L, -1, sub_name);
@@ -758,22 +803,22 @@ int LuaParser::_EventEncounter(std::string package_name, QuestEventID evt, std::
arg_function(this, L, enc, data, extra_data, extra_pointers);
quest_manager.StartQuest(enc, nullptr, nullptr, nullptr, encounter_name);
if(lua_pcall(L, 1, 1, 0)) {
if(lua_pcall(L, 1, 1, start + 1)) {
std::string error = lua_tostring(L, -1);
AddError(error);
quest_manager.EndQuest();
lua_pop(L, 2);
lua_pop(L, 3);
return 0;
}
quest_manager.EndQuest();
if(lua_isnumber(L, -1)) {
int ret = static_cast<int>(lua_tointeger(L, -1));
lua_pop(L, 2);
lua_pop(L, 3);
return ret;
}
lua_pop(L, 2);
lua_pop(L, 3);
} catch(std::exception &ex) {
AddError(fmt::format("Lua Exception | [{}] for Encounter [{}]: {}", sub_name, encounter_name, ex.what()));
@@ -1124,10 +1169,11 @@ void LuaParser::LoadScript(std::string filename, std::string package_name) {
}
auto top = lua_gettop(L);
PushErrorHandler(L);
if(luaL_loadfile(L, filename.c_str())) {
std::string error = lua_tostring(L, -1);
AddError(error);
lua_pop(L, 1);
lua_pop(L, 2);
return;
}
@@ -1147,10 +1193,10 @@ void LuaParser::LoadScript(std::string filename, std::string package_name) {
lua_setfenv(L, -2); //set the env to the table we made
if(lua_pcall(L, 0, 0, 0)) {
if(lua_pcall(L, 0, 0, top + 1)) {
std::string error = lua_tostring(L, -1);
AddError(error);
lua_pop(L, 1);
lua_pop(L, 2);
}
else {
loaded_[package_name] = true;
@@ -1599,13 +1645,14 @@ int LuaParser::_EventBot(
int start = lua_gettop(L);
try {
int npop = 1;
int npop = 2;
PushErrorHandler(L);
if(l_func != nullptr) {
l_func->push(L);
} else {
lua_getfield(L, LUA_REGISTRYINDEX, package_name.c_str());
lua_getfield(L, -1, sub_name);
npop = 2;
npop = 3;
}
lua_createtable(L, 0, 0);
@@ -1620,7 +1667,7 @@ int LuaParser::_EventBot(
auto* c = (init && init->IsClient()) ? init->CastToClient() : nullptr;
quest_manager.StartQuest(bot, c);
if(lua_pcall(L, 1, 1, 0)) {
if(lua_pcall(L, 1, 1, start + 1)) {
std::string error = lua_tostring(L, -1);
AddError(error);
quest_manager.EndQuest();
+225
View File
@@ -321,6 +321,18 @@ void handle_npc_death(
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[4]));
lua_setfield(L, -2, "killed_entity_id");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[5]));
lua_setfield(L, -2, "combat_start_time");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[6]));
lua_setfield(L, -2, "combat_end_time");
lua_pushinteger(L, Strings::ToBigInt(sep.arg[7]));
lua_setfield(L, -2, "damage_received");
lua_pushinteger(L, Strings::ToBigInt(sep.arg[8]));
lua_setfield(L, -2, "healing_received");
if (extra_pointers && extra_pointers->size() >= 1) {
Lua_Corpse l_corpse(std::any_cast<Corpse*>(extra_pointers->at(0)));
luabind::adl::object l_corpse_o = luabind::adl::object(L, l_corpse);
@@ -553,6 +565,67 @@ void handle_npc_loot_added(
}
}
void handle_npc_timer_pause_resume_start(
QuestInterface *parse,
lua_State* L,
NPC* npc,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushstring(L, sep.arg[0]);
lua_setfield(L, -2, "timer");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[1]));
lua_setfield(L, -2, "duration");
}
void handle_npc_timer_stop(
QuestInterface *parse,
lua_State* L,
NPC* npc,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushstring(L, data.c_str());
lua_setfield(L, -2, "timer");
}
void handle_npc_entity_variable(
QuestInterface *parse,
lua_State* L,
NPC* npc,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
)
{
if (extra_pointers) {
if (extra_pointers->size() == 2) {
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(0)).c_str());
lua_setfield(L, -2, "variable_name");
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(1)).c_str());
lua_setfield(L, -2, "variable_value");
} else if (extra_pointers->size() == 3) {
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(0)).c_str());
lua_setfield(L, -2, "variable_name");
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(1)).c_str());
lua_setfield(L, -2, "old_value");
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(2)).c_str());
lua_setfield(L, -2, "new_value");
}
}
}
// Player
void handle_player_say(
QuestInterface *parse,
@@ -1565,6 +1638,35 @@ void handle_player_alt_currency_gain_loss(
lua_setfield(L, -2, "total");
}
void handle_player_entity_variable(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
)
{
if (extra_pointers) {
if (extra_pointers->size() == 2) {
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(0)).c_str());
lua_setfield(L, -2, "variable_name");
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(1)).c_str());
lua_setfield(L, -2, "variable_value");
} else if (extra_pointers->size() == 3) {
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(0)).c_str());
lua_setfield(L, -2, "variable_name");
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(1)).c_str());
lua_setfield(L, -2, "old_value");
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(2)).c_str());
lua_setfield(L, -2, "new_value");
}
}
}
// Item
void handle_item_click(
QuestInterface *parse,
@@ -1731,6 +1833,39 @@ void handle_item_null(
) {
}
void handle_item_timer_pause_resume_start(
QuestInterface *parse,
lua_State* L,
Client* client,
EQ::ItemInstance* item,
Mob *mob,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushstring(L, sep.arg[0]);
lua_setfield(L, -2, "timer");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[1]));
lua_setfield(L, -2, "duration");
}
void handle_item_timer_stop(
QuestInterface *parse,
lua_State* L,
Client* client,
EQ::ItemInstance* item,
Mob *mob,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushstring(L, data.c_str());
lua_setfield(L, -2, "timer");
}
// Spell
void handle_spell_event(
QuestInterface *parse,
@@ -2061,6 +2196,35 @@ void handle_player_augment_remove(
lua_setfield(L, -2, "destroyed");
}
void handle_player_timer_pause_resume_start(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushstring(L, sep.arg[0]);
lua_setfield(L, -2, "timer");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[1]));
lua_setfield(L, -2, "duration");
}
void handle_player_timer_stop(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushstring(L, data.c_str());
lua_setfield(L, -2, "timer");
}
// Bot
void handle_bot_null(
@@ -2453,4 +2617,65 @@ void handle_bot_level_down(
lua_setfield(L, -2, "levels_lost");
}
void handle_bot_timer_pause_resume_start(
QuestInterface *parse,
lua_State* L,
Bot* bot,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushstring(L, sep.arg[0]);
lua_setfield(L, -2, "timer");
lua_pushinteger(L, Strings::ToUnsignedInt(sep.arg[1]));
lua_setfield(L, -2, "duration");
}
void handle_bot_timer_stop(
QuestInterface *parse,
lua_State* L,
Bot* bot,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushstring(L, data.c_str());
lua_setfield(L, -2, "timer");
}
void handle_bot_entity_variable(
QuestInterface *parse,
lua_State* L,
Bot* bot,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
)
{
if (extra_pointers) {
if (extra_pointers->size() == 2) {
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(0)).c_str());
lua_setfield(L, -2, "variable_name");
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(1)).c_str());
lua_setfield(L, -2, "variable_value");
} else if (extra_pointers->size() == 3) {
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(0)).c_str());
lua_setfield(L, -2, "variable_name");
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(1)).c_str());
lua_setfield(L, -2, "old_value");
lua_pushstring(L, std::any_cast<std::string>(extra_pointers->at(2)).c_str());
lua_setfield(L, -2, "new_value");
}
}
}
#endif
+109
View File
@@ -220,6 +220,36 @@ void handle_npc_loot_added(
std::vector<std::any> *extra_pointers
);
void handle_npc_timer_pause_resume_start(
QuestInterface *parse,
lua_State* L,
NPC* npc,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
void handle_npc_timer_stop(
QuestInterface *parse,
lua_State* L,
NPC* npc,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
void handle_npc_entity_variable(
QuestInterface *parse,
lua_State* L,
NPC* npc,
Mob *init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
// Player
void handle_player_say(
QuestInterface *parse,
@@ -770,6 +800,33 @@ void handle_player_crystal_gain_loss(
std::vector<std::any> *extra_pointers
);
void handle_player_timer_pause_resume_start(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
void handle_player_timer_stop(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
void handle_player_entity_variable(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
// Item
void handle_item_click(
QuestInterface *parse,
@@ -870,6 +927,28 @@ void handle_item_null(
std::vector<std::any> *extra_pointers
);
void handle_item_timer_pause_resume_start(
QuestInterface *parse,
lua_State* L,
Client* client,
EQ::ItemInstance* item,
Mob *mob,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
void handle_item_timer_stop(
QuestInterface *parse,
lua_State* L,
Client* client,
EQ::ItemInstance* item,
Mob *mob,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
// Spell
void handle_spell_event(
QuestInterface *parse,
@@ -1112,5 +1191,35 @@ void handle_bot_level_down(
std::vector<std::any> *extra_pointers
);
void handle_bot_timer_pause_resume_start(
QuestInterface *parse,
lua_State* L,
Bot* bot,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
void handle_bot_timer_stop(
QuestInterface *parse,
lua_State* L,
Bot* bot,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
void handle_bot_entity_variable(
QuestInterface *parse,
lua_State* L,
Bot* bot,
Mob* init,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
#endif
#endif
+3 -1
View File
@@ -318,7 +318,7 @@ int main(int argc, char **argv)
}
/* Guilds */
guild_mgr.SetDatabase(&database);
guild_mgr.SetDatabase(&database)->SetContentDatabase(&content_db);
GuildBanks = nullptr;
#ifdef _EQDEBUG
@@ -402,6 +402,8 @@ int main(int argc, char **argv)
}
content_service.SetDatabase(&database)
->SetContentDatabase(&content_db)
->SetContentZones(zone_store.GetZones())
->SetExpansionContext()
->ReloadContentFlags();
+114 -41
View File
@@ -392,6 +392,7 @@ Mob::Mob(
pet_stop = false;
pet_regroup = false;
_IsTempPet = false;
pet_owner_bot = false;
pet_owner_client = false;
pet_owner_npc = false;
pet_targetlock_id = 0;
@@ -5547,6 +5548,24 @@ bool Mob::ClearEntityVariables()
return false;
}
if (
(IsBot() && parse->BotHasQuestSub(EVENT_ENTITY_VARIABLE_DELETE)) ||
(IsClient() && parse->PlayerHasQuestSub(EVENT_ENTITY_VARIABLE_DELETE)) ||
(IsNPC() && parse->HasQuestSub(GetNPCTypeID(), EVENT_ENTITY_VARIABLE_DELETE))
) {
for (const auto& e : m_EntityVariables) {
std::vector<std::any> args = { e.first, e.second };
if (IsBot()) {
parse->EventBot(EVENT_ENTITY_VARIABLE_DELETE, CastToBot(), nullptr, "", 0, &args);
} else if (IsClient()) {
parse->EventPlayer(EVENT_ENTITY_VARIABLE_DELETE, CastToClient(), "", 0, &args);
} else if (IsNPC()) {
parse->EventNPC(EVENT_ENTITY_VARIABLE_DELETE, CastToNPC(), nullptr, "", 0, &args);
}
}
}
m_EntityVariables.clear();
return true;
}
@@ -5563,6 +5582,23 @@ bool Mob::DeleteEntityVariable(std::string variable_name)
}
m_EntityVariables.erase(v);
if (
(IsBot() && parse->BotHasQuestSub(EVENT_ENTITY_VARIABLE_DELETE)) ||
(IsClient() && parse->PlayerHasQuestSub(EVENT_ENTITY_VARIABLE_DELETE)) ||
(IsNPC() && parse->HasQuestSub(GetNPCTypeID(), EVENT_ENTITY_VARIABLE_DELETE))
) {
std::vector<std::any> args = { v->first, v->second };
if (IsBot()) {
parse->EventBot(EVENT_ENTITY_VARIABLE_DELETE, CastToBot(), nullptr, "", 0, &args);
} else if (IsClient()) {
parse->EventPlayer(EVENT_ENTITY_VARIABLE_DELETE, CastToClient(), "", 0, &args);
} else if (IsNPC()) {
parse->EventNPC(EVENT_ENTITY_VARIABLE_DELETE, CastToNPC(), nullptr, "", 0, &args);
}
}
return true;
}
@@ -5573,22 +5609,22 @@ std::string Mob::GetEntityVariable(std::string variable_name)
}
const auto& v = m_EntityVariables.find(variable_name);
if (v != m_EntityVariables.end()) {
return v->second;
}
return std::string();
return v != m_EntityVariables.end() ? v->second : std::string();
}
std::vector<std::string> Mob::GetEntityVariables()
{
std::vector<std::string> l;
if (m_EntityVariables.empty()) {
return l;
}
l.reserve(m_EntityVariables.size());
for (const auto& v : m_EntityVariables) {
l.push_back(v.first);
l.emplace_back(v.first);
}
return l;
@@ -5600,12 +5636,7 @@ bool Mob::EntityVariableExists(std::string variable_name)
return false;
}
const auto& v = m_EntityVariables.find(variable_name);
if (v != m_EntityVariables.end()) {
return true;
}
return false;
return m_EntityVariables.find(variable_name) != m_EntityVariables.end();
}
void Mob::SetEntityVariable(std::string variable_name, std::string variable_value)
@@ -5614,6 +5645,34 @@ void Mob::SetEntityVariable(std::string variable_name, std::string variable_valu
return;
}
const QuestEventID event_id = (
!EntityVariableExists(variable_name) ?
EVENT_ENTITY_VARIABLE_SET :
EVENT_ENTITY_VARIABLE_UPDATE
);
if (
(IsBot() && parse->BotHasQuestSub(event_id)) ||
(IsClient() && parse->PlayerHasQuestSub(event_id)) ||
(IsNPC() && parse->HasQuestSub(GetNPCTypeID(), event_id))
) {
std::vector<std::any> args;
if (event_id != EVENT_ENTITY_VARIABLE_UPDATE) {
args = { variable_name, variable_value };
} else {
args = { variable_name, GetEntityVariable(variable_name), variable_value };
}
if (IsBot()) {
parse->EventBot(event_id, CastToBot(), nullptr, "", 0, &args);
} else if (IsClient()) {
parse->EventPlayer(event_id, CastToClient(), "", 0, &args);
} else if (IsNPC()) {
parse->EventNPC(event_id, CastToNPC(), nullptr, "", 0, &args);
}
}
m_EntityVariables[variable_name] = variable_value;
}
@@ -6044,40 +6103,54 @@ bool Mob::TryFadeEffect(int slot)
return false;
}
void Mob::TrySympatheticProc(Mob *target, uint32 spell_id)
void Mob::TrySympatheticProc(Mob* target, uint32 spell_id)
{
if(target == nullptr || !IsValidSpell(spell_id) || !IsClient())
if (!target || !IsValidSpell(spell_id) || !IsOfClientBotMerc()) {
return;
uint16 focus_spell = GetSympatheticFocusEffect(focusSympatheticProc,spell_id);
if(!IsValidSpell(focus_spell))
return;
uint16 focus_trigger = GetSympatheticSpellProcID(focus_spell);
if(!IsValidSpell(focus_trigger))
return;
// For beneficial spells, if the triggered spell is also beneficial then proc it on the target
// if the triggered spell is detrimental, then it will trigger on the caster(ie cursed items)
if(IsBeneficialSpell(spell_id))
{
if(IsBeneficialSpell(focus_trigger))
SpellFinished(focus_trigger, target);
else
SpellFinished(focus_trigger, this, EQ::spells::CastingSlot::Item, 0, -1, spells[focus_trigger].resist_difficulty);
}
// For detrimental spells, if the triggered spell is beneficial, then it will land on the caster
// if the triggered spell is also detrimental, then it will land on the target
else
{
if(IsBeneficialSpell(focus_trigger))
SpellFinished(focus_trigger, this);
else
SpellFinished(focus_trigger, target, EQ::spells::CastingSlot::Item, 0, -1, spells[focus_trigger].resist_difficulty);
const uint16 focus_spell = GetSympatheticFocusEffect(focusSympatheticProc, spell_id);
if (!IsValidSpell(focus_spell)) {
return;
}
const uint16 focus_trigger = GetSympatheticSpellProcID(focus_spell);
if (!IsValidSpell(focus_trigger)) {
return;
}
if (IsBeneficialSpell(spell_id)) {
// For beneficial spells, if the triggered spell is also beneficial then proc it on the target
// if the triggered spell is detrimental, then it will trigger on the caster(ie cursed items)
if (IsBeneficialSpell(focus_trigger)) {
SpellFinished(focus_trigger, target);
} else {
SpellFinished(
focus_trigger,
this,
EQ::spells::CastingSlot::Item,
0,
-1,
spells[focus_trigger].resist_difficulty
);
}
} else {
// For detrimental spells, if the triggered spell is beneficial, then it will land on the caster
// if the triggered spell is also detrimental, then it will land on the target
if (IsBeneficialSpell(focus_trigger)) {
SpellFinished(focus_trigger, this);
} else {
SpellFinished(
focus_trigger,
target,
EQ::spells::CastingSlot::Item,
0,
-1,
spells[focus_trigger].resist_difficulty
);
}
}
CheckNumHitsRemaining(NumHit::MatchingSpells, -1, focus_spell);
+8 -4
View File
@@ -769,6 +769,7 @@ public:
Client* GetHateClosestClient(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed, EntityFilterType::Clients)->CastToClient(); }
NPC* GetHateClosestNPC(bool skip_mezzed = false) { return hate_list.GetClosestEntOnHateList(this, skip_mezzed, EntityFilterType::NPCs)->CastToNPC(); }
bool IsEngaged() { return(!hate_list.IsHateListEmpty()); }
inline uint32 GetHateListCount(HateListCountType count_type = HateListCountType::All) { return hate_list.GetHateListCount(count_type); }
bool HasPrimaryAggro() { return PrimaryAggro; }
bool HasAssistAggro() { return AssistAggro; }
void SetPrimaryAggro(bool value) { PrimaryAggro = value; if (value) AssistAggro = false; }
@@ -1075,10 +1076,12 @@ public:
inline int16 GetTempPetCount() const { return count_TempPet; }
inline void SetTempPetCount(int16 i) { count_TempPet = i; }
bool HasPetAffinity() { if (aabonuses.GivePetGroupTarget || itembonuses.GivePetGroupTarget || spellbonuses.GivePetGroupTarget) return true; return false; }
inline bool IsPetOwnerBot() const { return pet_owner_bot; }
inline void SetPetOwnerBot(bool b) { pet_owner_bot = b; }
inline bool IsPetOwnerClient() const { return pet_owner_client; }
inline void SetPetOwnerClient(bool value) { pet_owner_client = value; }
inline void SetPetOwnerClient(bool b) { pet_owner_client = b; }
inline bool IsPetOwnerNPC() const { return pet_owner_npc; }
inline void SetPetOwnerNPC(bool value) { pet_owner_npc = value; }
inline void SetPetOwnerNPC(bool b) { pet_owner_npc = b; }
inline bool IsTempPet() const { return _IsTempPet; }
inline void SetTempPet(bool value) { _IsTempPet = value; }
inline bool IsHorse() { return is_horse; }
@@ -1837,8 +1840,9 @@ protected:
bool hasTempPet;
bool _IsTempPet;
int16 count_TempPet;
bool pet_owner_client; //Flags regular and pets as belonging to a client
bool pet_owner_npc; //Flags regular and pets as belonging to a npc
bool pet_owner_bot; // Flags pets as belonging to a Bot
bool pet_owner_client; // Flags pets as belonging to a Client
bool pet_owner_npc; // Flags pets as belonging to an NPC
uint32 pet_targetlock_id;
glm::vec3 m_TargetRing;
+10 -3
View File
@@ -2162,7 +2162,9 @@ void NPC::PetOnSpawn(NewSpawn_Struct* ns)
}
}
if (swarm_owner->IsNPC()) {
if (swarm_owner->IsBot()) {
SetPetOwnerBot(true);
} else if (swarm_owner->IsNPC()) {
SetPetOwnerNPC(true);
}
} else if (GetOwnerID()) {
@@ -2179,8 +2181,13 @@ void NPC::PetOnSpawn(NewSpawn_Struct* ns)
}
}
} else {
if (entity_list.GetNPCByID(GetOwnerID())) {
SetPetOwnerNPC(true);
Mob* owner = entity_list.GetMob(GetOwnerID());
if (owner) {
if (owner->IsBot()) {
SetPetOwnerBot(true);
} else if (owner->IsNPC()) {
SetPetOwnerNPC(true);
}
}
}
}
+6
View File
@@ -3098,6 +3098,11 @@ int Perl_Client_GetEXPPercentage(Client* self)
return self->GetEXPPercentage();
}
bool Perl_Client_IsInAGuild(Client* self)
{
return self->IsInAGuild();
}
void perl_register_client()
{
perl::interpreter perl(PERL_GET_THX);
@@ -3386,6 +3391,7 @@ void perl_register_client()
package.add("IsDueling", &Perl_Client_IsDueling);
package.add("IsEXPEnabled", &Perl_Client_IsEXPEnabled);
package.add("IsGrouped", &Perl_Client_IsGrouped);
package.add("IsInAGuild", &Perl_Client_IsInAGuild);
package.add("IsLD", &Perl_Client_IsLD);
package.add("IsMedding", &Perl_Client_IsMedding);
package.add("IsRaidGrouped", &Perl_Client_IsRaidGrouped);
+66
View File
@@ -3340,6 +3340,61 @@ std::string Perl_Mob_GetRacePlural(Mob* self)
return self->GetRacePlural();
}
uint32 Perl_Mob_GetHateListCount(Mob* self)
{
return self->GetHateListCount();
}
uint32 Perl_Mob_GetHateListBotCount(Mob* self)
{
return self->GetHateListCount(HateListCountType::Bot);
}
uint32 Perl_Mob_GetHateListClientCount(Mob* self)
{
return self->GetHateListCount(HateListCountType::Client);
}
uint32 Perl_Mob_GetHateListNPCCount(Mob* self)
{
return self->GetHateListCount(HateListCountType::NPC);
}
bool Perl_Mob_IsAnimation(Mob* self)
{
return self->IsAnimation();
}
bool Perl_Mob_IsCharmed(Mob* self)
{
return self->IsCharmed();
}
bool Perl_Mob_IsFamiliar(Mob* self)
{
return self->IsFamiliar();
}
bool Perl_Mob_IsTargetLockPet(Mob* self)
{
return self->IsTargetLockPet();
}
bool Perl_Mob_IsPetOwnerBot(Mob* self)
{
return self->IsPetOwnerBot();
}
bool Perl_Mob_IsPetOwnerClient(Mob* self)
{
return self->IsPetOwnerClient();
}
bool Perl_Mob_IsPetOwnerNPC(Mob* self)
{
return self->IsPetOwnerNPC();
}
void perl_register_mob()
{
perl::interpreter perl(PERL_GET_THX);
@@ -3585,12 +3640,16 @@ void perl_register_mob()
package.add("GetHateList", &Perl_Mob_GetHateList);
package.add("GetHateListBots", (perl::array(*)(Mob*))&Perl_Mob_GetHateListBots);
package.add("GetHateListBots", (perl::array(*)(Mob*, uint32))&Perl_Mob_GetHateListBots);
package.add("GetHateListBotCount", &Perl_Mob_GetHateListBotCount);
package.add("GetHateListClients", (perl::array(*)(Mob*))&Perl_Mob_GetHateListClients);
package.add("GetHateListClients", (perl::array(*)(Mob*, uint32))&Perl_Mob_GetHateListClients);
package.add("GetHateListClientCount", &Perl_Mob_GetHateListClientCount);
package.add("GetHateListNPCs", (perl::array(*)(Mob*))&Perl_Mob_GetHateListNPCs);
package.add("GetHateListNPCs", (perl::array(*)(Mob*, uint32))&Perl_Mob_GetHateListNPCs);
package.add("GetHateListNPCCount", &Perl_Mob_GetHateListNPCCount);
package.add("GetHateListByDistance", (perl::array(*)(Mob*))&Perl_Mob_GetHateListByDistance);
package.add("GetHateListByDistance", (perl::array(*)(Mob*, uint32))&Perl_Mob_GetHateListByDistance);
package.add("GetHateListCount", &Perl_Mob_GetHateListCount);
package.add("GetHateRandom", &Perl_Mob_GetHateRandom);
package.add("GetHateRandomBot", &Perl_Mob_GetHateRandomBot);
package.add("GetHateRandomClient", &Perl_Mob_GetHateRandomClient);
@@ -3701,6 +3760,7 @@ void perl_register_mob()
package.add("InterruptSpell", (void(*)(Mob*, uint16))&Perl_Mob_InterruptSpell);
package.add("IsAIControlled", &Perl_Mob_IsAIControlled);
package.add("IsAmnesiad", &Perl_Mob_IsAmnesiad);
package.add("IsAnimation", &Perl_Mob_IsAnimation);
package.add("IsAttackAllowed", (bool(*)(Mob*, Mob*))&Perl_Mob_IsAttackAllowed);
package.add("IsAttackAllowed", (bool(*)(Mob*, Mob*, bool))&Perl_Mob_IsAttackAllowed);
package.add("IsAura", &Perl_Mob_IsAura);
@@ -3710,6 +3770,7 @@ void perl_register_mob()
package.add("IsBlind", &Perl_Mob_IsBlind);
package.add("IsBot", &Perl_Mob_IsBot);
package.add("IsCasting", &Perl_Mob_IsCasting);
package.add("IsCharmed", &Perl_Mob_IsCharmed);
package.add("IsClient", &Perl_Mob_IsClient);
package.add("IsCorpse", &Perl_Mob_IsCorpse);
package.add("IsDoor", &Perl_Mob_IsDoor);
@@ -3717,6 +3778,7 @@ void perl_register_mob()
package.add("IsEncounter", &Perl_Mob_IsEncounter);
package.add("IsEngaged", &Perl_Mob_IsEngaged);
package.add("IsEnraged", &Perl_Mob_IsEnraged);
package.add("IsFamiliar", &Perl_Mob_IsFamiliar);
package.add("IsFeared", &Perl_Mob_IsFeared);
package.add("IsFindable", &Perl_Mob_IsFindable);
package.add("IsHorse", &Perl_Mob_IsHorse);
@@ -3735,6 +3797,9 @@ void perl_register_mob()
package.add("IsOfClientBotMerc", &Perl_Mob_IsOfClientBotMerc);
package.add("IsPausedTimer", &Perl_Mob_IsPausedTimer);
package.add("IsPet", &Perl_Mob_IsPet);
package.add("IsPetOwnerBot", &Perl_Mob_IsPetOwnerBot);
package.add("IsPetOwnerClient", &Perl_Mob_IsPetOwnerClient);
package.add("IsPetOwnerNPC", &Perl_Mob_IsPetOwnerNPC);
package.add("IsPlayerCorpse", &Perl_Mob_IsPlayerCorpse);
package.add("IsRoamer", &Perl_Mob_IsRoamer);
package.add("IsRooted", &Perl_Mob_IsRooted);
@@ -3743,6 +3808,7 @@ void perl_register_mob()
package.add("IsStunned", &Perl_Mob_IsStunned);
package.add("IsTargetable", &Perl_Mob_IsTargetable);
package.add("IsTargeted", &Perl_Mob_IsTargeted);
package.add("IsTargetLockPet", &Perl_Mob_IsTargetLockPet);
package.add("IsTemporaryPet", &Perl_Mob_IsTemporaryPet);
package.add("IsTrackable", &Perl_Mob_IsTrackable);
package.add("IsTrap", &Perl_Mob_IsTrap);
+6
View File
@@ -786,6 +786,11 @@ void Perl_NPC_SetNPCAggro(NPC* self, bool in_npc_aggro) // @categories Script Ut
self->SetNPCAggro(in_npc_aggro);
}
uint32 Perl_NPC_GetNPCSpellsEffectsID(NPC* self)
{
return self->GetNPCSpellsEffectsID();
}
void perl_register_npc()
{
@@ -851,6 +856,7 @@ void perl_register_npc()
package.add("GetNPCAggro", &Perl_NPC_GetNPCAggro);
package.add("GetNPCFactionID", &Perl_NPC_GetNPCFactionID);
package.add("GetNPCHate", &Perl_NPC_GetNPCHate);
package.add("GetNPCSpellsEffectsID", &Perl_NPC_GetNPCSpellsEffectsID);
package.add("GetNPCSpellsID", &Perl_NPC_GetNPCSpellsID);
package.add("GetNPCStat", &Perl_NPC_GetNPCStat);
package.add("GetPetSpellID", &Perl_NPC_GetPetSpellID);
+15
View File
@@ -275,6 +275,20 @@ EQ::ItemData* Perl_QuestItem_GetUnscaledItem(EQ::ItemInstance* self) {
return const_cast<EQ::ItemData*>(self->GetUnscaledItem());
}
perl::array Perl_QuestItem_GetAugmentIDs(EQ::ItemInstance* self)
{
perl::array result;
const auto& augment_ids = self->GetAugmentIDs();
for (int i = 0; i < augment_ids.size(); i++) {
result.push_back(augment_ids[i]);
}
return result;
}
void perl_register_questitem()
{
perl::interpreter perl(PERL_GET_THX);
@@ -287,6 +301,7 @@ void perl_register_questitem()
package.add("CountAugmentByID", &Perl_QuestItem_CountAugmentByID);
package.add("DeleteCustomData", &Perl_QuestItem_DeleteCustomData);
package.add("GetAugment", &Perl_QuestItem_GetAugment);
package.add("GetAugmentIDs", &Perl_QuestItem_GetAugmentIDs);
package.add("GetAugmentItemID", &Perl_QuestItem_GetAugmentItemID);
package.add("GetAugmentType", &Perl_QuestItem_GetAugmentType);
package.add("GetCharges", &Perl_QuestItem_GetCharges);
+50
View File
@@ -830,11 +830,21 @@ QuestInterface* QuestParserCollection::GetQIByNPCQuest(uint32 npc_id, std::strin
zone->GetShortName()
);
const std::string& zone_versioned_path = fmt::format(
"{}/{}/v{}",
path.GetQuestsPath(),
zone->GetShortName(),
zone->GetInstanceVersion()
);
std::vector<std::string> file_names = {
fmt::format("{}/{}", zone_versioned_path, npc_id), // Local versioned by NPC ID ./quests/zone/v0/10.ext
fmt::format("{}/{}", zone_versioned_path, npc_name), // Local versioned by NPC Name ./quests/zone/v0/npc.ext
fmt::format("{}/{}", zone_path, npc_id), // Local by NPC ID
fmt::format("{}/{}", zone_path, npc_name), // Local by NPC Name
fmt::format("{}/{}", global_path, npc_id), // Global by NPC ID
fmt::format("{}/{}", global_path, npc_name), // Global by NPC ID
fmt::format("{}/default", zone_versioned_path), // Zone Default ./quests/zone/v0/default.ext
fmt::format("{}/default", zone_path), // Zone Default
fmt::format("{}/default", global_path), // Global Default
};
@@ -877,7 +887,15 @@ QuestInterface* QuestParserCollection::GetQIByPlayerQuest(std::string& filename)
zone->GetShortName()
);
const std::string& zone_versioned_path = fmt::format(
"{}/{}/v{}",
path.GetQuestsPath(),
zone->GetShortName(),
zone->GetInstanceVersion()
);
std::vector<std::string> file_names = {
fmt::format("{}/player", zone_versioned_path), // Local by Instance Version ./quests/zone/v0/player.ext
fmt::format("{}/player_v{}", zone_path, zone->GetInstanceVersion()), // Local by Instance Version
fmt::format("{}/player", zone_path), // Local
fmt::format("{}/player", global_path) // Global
@@ -969,7 +987,15 @@ QuestInterface* QuestParserCollection::GetQIBySpellQuest(uint32 spell_id, std::s
zone->GetShortName()
);
const std::string& zone_versioned_path = fmt::format(
"{}/{}/v{}/spells",
path.GetQuestsPath(),
zone->GetShortName(),
zone->GetInstanceVersion()
);
std::vector<std::string> file_names = {
fmt::format("{}/{}", zone_versioned_path, spell_id), // Local versioned by Spell ID ./quests/zone/v0/spells/10.ext
fmt::format("{}/{}", zone_path, spell_id), // Local
fmt::format("{}/{}", global_path, spell_id), // Global
fmt::format("{}/default", zone_path), // Local Default
@@ -1013,7 +1039,15 @@ QuestInterface* QuestParserCollection::GetQIByItemQuest(std::string item_script,
zone->GetShortName()
);
const std::string& zone_versioned_path = fmt::format(
"{}/{}/v{}/items",
path.GetQuestsPath(),
zone->GetShortName(),
zone->GetInstanceVersion()
);
std::vector<std::string> file_names = {
fmt::format("{}/{}", zone_versioned_path, item_script), // Local versioned by Item Script ./quests/zone/v0/items/10.ext
fmt::format("{}/{}", zone_path, item_script), // Local
fmt::format("{}/{}", global_path, item_script), // Global
fmt::format("{}/default", zone_path), // Local Default
@@ -1057,7 +1091,15 @@ QuestInterface* QuestParserCollection::GetQIByEncounterQuest(std::string encount
zone->GetShortName()
);
const std::string& zone_versioned_path = fmt::format(
"{}/{}/v{}/encounters",
path.GetQuestsPath(),
zone->GetShortName(),
zone->GetInstanceVersion()
);
std::vector<std::string> file_names = {
fmt::format("{}/{}", zone_versioned_path, encounter_name), // Local versioned ./quests/zone/v0/encounters/name.ext
fmt::format("{}/{}", zone_path, encounter_name), // Local
fmt::format("{}/{}", global_path, encounter_name) // Global
};
@@ -1099,7 +1141,15 @@ QuestInterface* QuestParserCollection::GetQIByBotQuest(std::string& filename)
zone->GetShortName()
);
const std::string& zone_versioned_path = fmt::format(
"{}/{}/v{}",
path.GetQuestsPath(),
zone->GetShortName(),
zone->GetInstanceVersion()
);
std::vector<std::string> file_names = {
fmt::format("{}/bot", zone_versioned_path), // Local versioned by Instance Version ./quests/zone/v0/bot.ext
fmt::format("{}/bot_v{}", zone_path, zone->GetInstanceVersion()), // Local by Instance Version
fmt::format("{}/bot", zone_path), // Local
fmt::format("{}/bot", global_path) // Global
+599 -198
View File
@@ -396,19 +396,39 @@ void QuestManager::incstat(int stat, int value) {
initiator->IncStats(stat, value);
}
void QuestManager::castspell(int spell_id, int target_id) {
void QuestManager::castspell(uint16 spell_id, uint16 target_id)
{
QuestManagerCurrentQuestVars();
if (owner) {
Mob *tgt = entity_list.GetMob(target_id);
if(tgt != nullptr)
owner->SpellFinished(spell_id, tgt, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].resist_difficulty);
Mob* t = entity_list.GetMob(target_id);
if (t) {
owner->SpellFinished(
spell_id,
t,
EQ::spells::CastingSlot::Item,
0,
-1,
spells[spell_id].resist_difficulty
);
}
}
}
void QuestManager::selfcast(int spell_id) {
void QuestManager::selfcast(uint16 spell_id)
{
QuestManagerCurrentQuestVars();
if (initiator)
initiator->SpellFinished(spell_id, initiator, EQ::spells::CastingSlot::Item, 0, -1, spells[spell_id].resist_difficulty);
if (initiator) {
initiator->SpellFinished(
spell_id,
initiator,
EQ::spells::CastingSlot::Item,
0,
-1,
spells[spell_id].resist_difficulty
);
}
}
void QuestManager::addloot(
@@ -480,317 +500,698 @@ void QuestManager::ZoneRaid(const char *zone_name) {
}
}
void QuestManager::settimer(const char* timer_name, int seconds, Mob* mob) {
void QuestManager::settimer(const std::string& timer_name, uint32 seconds, Mob* m)
{
QuestManagerCurrentQuestVars();
if(questitem) {
if (questitem) {
questitem->SetTimer(timer_name, seconds * 1000);
if (parse->ItemHasQuestSub(questitem, EVENT_TIMER_START)) {
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
seconds * 1000
);
parse->EventItem(EVENT_TIMER_START, nullptr, questitem, nullptr, export_string, 0);
}
return;
}
std::list<QuestTimer>::iterator cur = QTimerList.begin(), end;
end = QTimerList.end();
const auto m = mob ? mob : owner;
while (cur != end) {
if (cur->mob && cur->mob == m && cur->name == timer_name) {
cur->Timer_.Enable();
cur->Timer_.Start(seconds * 1000, false);
return;
}
++cur;
if (!m && !owner) {
return;
}
QTimerList.emplace_back(QuestTimer(seconds * 1000, owner, timer_name));
Mob* mob = m ? m : owner;
if (!mob) {
return;
}
const bool has_start_event = (
(mob->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_START)) ||
(mob->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_START)) ||
(mob->IsNPC() && parse->HasQuestSub(mob->GetNPCTypeID(), EVENT_TIMER_START))
);
if (!QTimerList.empty()) {
for (auto e : QTimerList) {
if (e.mob && e.mob == mob && e.name == timer_name) {
e.Timer_.Enable();
e.Timer_.Start(seconds * 1000, false);
if (has_start_event) {
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
seconds * 1000
);
if (mob->IsClient()) {
parse->EventPlayer(EVENT_TIMER_START, mob->CastToClient(), export_string, 0);
} else if (mob->IsBot()) {
parse->EventBot(EVENT_TIMER_START, mob->CastToBot(), nullptr, export_string, 0);
} else if (mob->IsNPC()) {
parse->EventNPC(EVENT_TIMER_START, mob->CastToNPC(), nullptr, export_string, 0);
}
}
return;
}
}
}
QTimerList.emplace_back(QuestTimer(seconds * 1000, mob, timer_name));
if (has_start_event) {
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
seconds * 1000
);
if (mob->IsClient()) {
parse->EventPlayer(EVENT_TIMER_START, mob->CastToClient(), export_string, 0);
} else if (mob->IsBot()) {
parse->EventBot(EVENT_TIMER_START, mob->CastToBot(), nullptr, export_string, 0);
} else if (mob->IsNPC()) {
parse->EventNPC(EVENT_TIMER_START, mob->CastToNPC(), nullptr, export_string, 0);
}
}
}
void QuestManager::settimerMS(const char* timer_name, int milliseconds) {
void QuestManager::settimerMS(const std::string& timer_name, uint32 milliseconds)
{
QuestManagerCurrentQuestVars();
if(questitem) {
questitem->SetTimer(timer_name, milliseconds);
if (!owner) {
return;
}
std::list<QuestTimer>::iterator cur = QTimerList.begin(), end;
const bool has_start_event = (
(owner->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_START)) ||
(owner->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_START)) ||
(owner->IsNPC() && parse->HasQuestSub(owner->GetNPCTypeID(), EVENT_TIMER_START))
);
end = QTimerList.end();
while (cur != end) {
if(cur->mob && cur->mob == owner && cur->name == timer_name)
{
cur->Timer_.Enable();
cur->Timer_.Start(milliseconds, false);
return;
if (questitem) {
questitem->SetTimer(timer_name, milliseconds);
if (parse->ItemHasQuestSub(questitem, EVENT_TIMER_START)) {
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
milliseconds
);
parse->EventItem(EVENT_TIMER_START, nullptr, questitem, nullptr, export_string, 0);
}
return;
}
if (!QTimerList.empty()) {
for (auto e : QTimerList) {
if (e.mob && e.mob == owner && e.name == timer_name) {
e.Timer_.Enable();
e.Timer_.Start(milliseconds, false);
if (has_start_event) {
const std::string& export_string = fmt::format(
"{} {}",
e.name,
milliseconds
);
if (owner->IsClient()) {
parse->EventPlayer(EVENT_TIMER_START, owner->CastToClient(), export_string, 0);
} else if (owner->IsBot()) {
parse->EventBot(EVENT_TIMER_START, owner->CastToBot(), nullptr, export_string, 0);
} else if (owner->IsNPC()) {
parse->EventNPC(EVENT_TIMER_START, owner->CastToNPC(), nullptr, export_string, 0);
}
}
return;
}
}
++cur;
}
QTimerList.emplace_back(QuestTimer(milliseconds, owner, timer_name));
if (has_start_event) {
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
milliseconds
);
if (owner->IsClient()) {
parse->EventPlayer(EVENT_TIMER_START, owner->CastToClient(), export_string, 0);
} else if (owner->IsBot()) {
parse->EventBot(EVENT_TIMER_START, owner->CastToBot(), nullptr, export_string, 0);
} else if (owner->IsNPC()) {
parse->EventNPC(EVENT_TIMER_START, owner->CastToNPC(), nullptr, export_string, 0);
}
}
}
void QuestManager::settimerMS(const char* timer_name, int milliseconds, EQ::ItemInstance *inst) {
void QuestManager::settimerMS(const std::string& timer_name, uint32 milliseconds, EQ::ItemInstance* inst)
{
if (inst) {
inst->SetTimer(timer_name, milliseconds);
}
}
void QuestManager::settimerMS(const char* timer_name, int milliseconds, Mob *mob) {
std::list<QuestTimer>::iterator cur = QTimerList.begin(), end;
end = QTimerList.end();
while (cur != end) {
if (cur->mob && cur->mob == mob && cur->name == timer_name)
{
cur->Timer_.Enable();
cur->Timer_.Start(milliseconds, false);
return;
}
++cur;
void QuestManager::settimerMS(const std::string& timer_name, uint32 milliseconds, Mob* m)
{
if (!m) {
return;
}
QTimerList.emplace_back(QuestTimer(milliseconds, mob, timer_name));
const bool has_start_event = (
(m->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_START)) ||
(m->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_START)) ||
(m->IsNPC() && parse->HasQuestSub(m->GetNPCTypeID(), EVENT_TIMER_START))
);
if (!QTimerList.empty()) {
for (auto e : QTimerList) {
if (e.mob && e.mob == m && e.name == timer_name) {
e.Timer_.Enable();
e.Timer_.Start(milliseconds, false);
if (has_start_event) {
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
milliseconds
);
if (m->IsClient()) {
parse->EventPlayer(EVENT_TIMER_START, m->CastToClient(), export_string, 0);
} else if (m->IsBot()) {
parse->EventBot(EVENT_TIMER_START, m->CastToBot(), nullptr, export_string, 0);
} else if (m->IsNPC()) {
parse->EventNPC(EVENT_TIMER_START, m->CastToNPC(), nullptr, export_string, 0);
}
}
return;
}
}
}
QTimerList.emplace_back(QuestTimer(milliseconds, m, timer_name));
if (has_start_event) {
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
milliseconds
);
if (m->IsClient()) {
parse->EventPlayer(EVENT_TIMER_START, m->CastToClient(), export_string, 0);
} else if (m->IsBot()) {
parse->EventBot(EVENT_TIMER_START, m->CastToBot(), nullptr, export_string, 0);
} else if (m->IsNPC()) {
parse->EventNPC(EVENT_TIMER_START, m->CastToNPC(), nullptr, export_string, 0);
}
}
}
void QuestManager::stoptimer(const char* timer_name) {
void QuestManager::stoptimer(const std::string& timer_name)
{
QuestManagerCurrentQuestVars();
if (questitem) {
questitem->StopTimer(timer_name);
if (parse->ItemHasQuestSub(questitem, EVENT_TIMER_STOP)) {
parse->EventItem(EVENT_TIMER_STOP, nullptr, questitem, nullptr, timer_name, 0);
}
return;
}
std::list<QuestTimer>::iterator cur = QTimerList.begin(), end;
if (!owner) {
return;
}
end = QTimerList.end();
while (cur != end) {
if (cur->mob && cur->mob == owner && cur->name == timer_name) {
QTimerList.erase(cur);
return;
if (QTimerList.empty()) {
return;
}
const bool has_stop_event = (
(owner->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_STOP)) ||
(owner->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_STOP)) ||
(owner->IsNPC() && parse->HasQuestSub(owner->GetNPCTypeID(), EVENT_TIMER_STOP))
);
for (auto e = QTimerList.begin(); e != QTimerList.end(); ++e) {
LogInfo("Current [{}] Timer [{}]", e->name, timer_name);
if (e->mob && e->mob == owner && e->name == timer_name) {
LogInfo("Matched [{}] Timer [{}]", e->name, timer_name);
if (has_stop_event) {
if (owner->IsClient()) {
parse->EventPlayer(EVENT_TIMER_STOP, owner->CastToClient(), timer_name, 0);
} else if (owner->IsBot()) {
parse->EventBot(EVENT_TIMER_STOP, owner->CastToBot(), nullptr, timer_name, 0);
} else if (owner->IsNPC()) {
parse->EventNPC(EVENT_TIMER_STOP, owner->CastToNPC(), nullptr, timer_name, 0);
}
}
QTimerList.erase(e);
break;
}
++cur;
}
}
void QuestManager::stoptimer(const char* timer_name, EQ::ItemInstance *inst) {
void QuestManager::stoptimer(const std::string& timer_name, EQ::ItemInstance* inst)
{
if (inst) {
inst->StopTimer(timer_name);
}
}
void QuestManager::stoptimer(const char* timer_name, Mob *mob) {
std::list<QuestTimer>::iterator cur = QTimerList.begin(), end;
void QuestManager::stoptimer(const std::string& timer_name, Mob* m)
{
if (!m) {
return;
}
end = QTimerList.end();
while (cur != end) {
if (cur->mob && cur->mob == mob && cur->name == timer_name) {
QTimerList.erase(cur);
return;
if (QTimerList.empty()) {
return;
}
const bool has_stop_event = (
(m->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_STOP)) ||
(m->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_STOP)) ||
(m->IsNPC() && parse->HasQuestSub(m->GetNPCTypeID(), EVENT_TIMER_STOP))
);
for (auto e = QTimerList.begin(); e != QTimerList.end();) {
if (e->mob && e->mob == m) {
if (has_stop_event) {
if (m->IsClient()) {
parse->EventPlayer(EVENT_TIMER_STOP, m->CastToClient(), e->name, 0);
} else if (m->IsBot()) {
parse->EventBot(EVENT_TIMER_STOP, m->CastToBot(), nullptr, e->name, 0);
} else if (m->IsNPC()) {
parse->EventNPC(EVENT_TIMER_STOP, m->CastToNPC(), nullptr, e->name, 0);
}
}
QTimerList.erase(e);
break;
}
++cur;
}
}
void QuestManager::stopalltimers() {
void QuestManager::stopalltimers()
{
QuestManagerCurrentQuestVars();
if(questitem) {
if (questitem) {
if (parse->ItemHasQuestSub(questitem, EVENT_TIMER_STOP)) {
auto item_timers = questitem->GetTimers();
if (item_timers.empty()) {
return;
}
for (auto e = item_timers.begin(); e != item_timers.end(); ++e) {
if (parse->ItemHasQuestSub(questitem, EVENT_TIMER_STOP)) {
parse->EventItem(EVENT_TIMER_STOP, nullptr, questitem, nullptr, e->first, 0);
}
}
}
questitem->ClearTimers();
return;
}
std::list<QuestTimer>::iterator cur = QTimerList.begin(), end, tmp;
if (!owner) {
return;
}
end = QTimerList.end();
while (cur != end) {
if(cur->mob && cur->mob == owner)
cur = QTimerList.erase(cur);
else
++cur;
if (QTimerList.empty()) {
return;
}
const bool has_stop_event = (
(owner->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_STOP)) ||
(owner->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_STOP)) ||
(owner->IsNPC() && parse->HasQuestSub(owner->GetNPCTypeID(), EVENT_TIMER_STOP))
);
for (auto e = QTimerList.begin(); e != QTimerList.end();) {
if (e->mob && e->mob == owner) {
if (has_stop_event) {
if (owner->IsClient()) {
parse->EventPlayer(EVENT_TIMER_STOP, owner->CastToClient(), e->name, 0);
} else if (owner->IsBot()) {
parse->EventBot(EVENT_TIMER_STOP, owner->CastToBot(), nullptr, e->name, 0);
} else if (owner->IsNPC()) {
parse->EventNPC(EVENT_TIMER_STOP, owner->CastToNPC(), nullptr, e->name, 0);
}
}
e = QTimerList.erase(e);
} else {
++e;
}
}
}
void QuestManager::stopalltimers(EQ::ItemInstance *inst) {
void QuestManager::stopalltimers(EQ::ItemInstance* inst)
{
if (inst) {
if (parse->ItemHasQuestSub(inst, EVENT_TIMER_STOP)) {
auto item_timers = inst->GetTimers();
if (item_timers.empty()) {
return;
}
for (auto e = item_timers.begin(); e != item_timers.begin(); ++e) {
if (parse->ItemHasQuestSub(inst, EVENT_TIMER_STOP)) {
parse->EventItem(EVENT_TIMER_STOP, nullptr, inst, nullptr, e->first, 0);
}
}
}
inst->ClearTimers();
}
}
void QuestManager::stopalltimers(Mob *mob) {
std::list<QuestTimer>::iterator cur = QTimerList.begin(), end, tmp;
end = QTimerList.end();
while (cur != end) {
if (cur->mob && cur->mob == mob)
cur = QTimerList.erase(cur);
else
++cur;
}
}
void QuestManager::pausetimer(const char* timer_name, Mob* mob) {
QuestManagerCurrentQuestVars();
if (!mob && !owner) {
void QuestManager::stopalltimers(Mob* m)
{
if (!m) {
return;
}
std::list<QuestTimer>::iterator cur = QTimerList.begin(), end;
std::list<PausedTimer>::iterator pcur = PTimerList.begin(), pend;
PausedTimer pt;
uint32 milliseconds = 0;
if (QTimerList.empty()) {
return;
}
const auto m = mob ? mob : owner;
const bool has_stop_event = (
(m->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_STOP)) ||
(m->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_STOP)) ||
(m->IsNPC() && parse->HasQuestSub(m->GetNPCTypeID(), EVENT_TIMER_STOP))
);
pend = PTimerList.end();
while (pcur != pend) {
if (pcur->owner && pcur->owner == m && pcur->name == timer_name) {
LogQuests("Timer [{}] is already paused for [{}]. Returning", timer_name, owner->GetName());
for (auto e = QTimerList.begin(); e != QTimerList.end();) {
if (e->mob && e->mob == m) {
if (has_stop_event) {
if (m->IsClient()) {
parse->EventPlayer(EVENT_TIMER_STOP, m->CastToClient(), e->name, 0);
} else if (m->IsBot()) {
parse->EventBot(EVENT_TIMER_STOP, m->CastToBot(), nullptr, e->name, 0);
} else if (m->IsNPC()) {
parse->EventNPC(EVENT_TIMER_STOP, m->CastToNPC(), nullptr, e->name, 0);
}
}
e = QTimerList.erase(e);
} else {
++e;
}
}
}
void QuestManager::pausetimer(const std::string& timer_name, Mob* m)
{
QuestManagerCurrentQuestVars();
if (!m && !owner) {
return;
}
Mob* mob = m ? m : owner;
if (!mob) {
return;
}
if (QTimerList.empty()) {
return;
}
for (const auto& e : PTimerList) {
if (e.owner && e.owner == mob && e.name == timer_name) {
LogQuests("Timer [{}] is already paused for [{}]", timer_name, owner->GetName());
return;
}
++pcur;
}
end = QTimerList.end();
while (cur != end) {
if (cur->mob && cur->mob == m && cur->name == timer_name) {
milliseconds = cur->Timer_.GetRemainingTime();
QTimerList.erase(cur);
break;
uint32 milliseconds = 0;
const bool has_pause_event = (
(mob->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_PAUSE)) ||
(mob->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_PAUSE)) ||
(mob->IsNPC() && parse->HasQuestSub(mob->GetNPCTypeID(), EVENT_TIMER_PAUSE))
);
if (!QTimerList.empty()) {
for (auto e = QTimerList.begin(); e != QTimerList.end(); ++e) {
if (e->mob && e->mob == mob && e->name == timer_name) {
milliseconds = e->Timer_.GetRemainingTime();
QTimerList.erase(e);
break;
}
}
}
PTimerList.emplace_back(
PausedTimer{
.owner = owner,
.name = timer_name,
.time = milliseconds
}
);
if (has_pause_event) {
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
milliseconds
);
if (mob->IsClient()) {
parse->EventPlayer(EVENT_TIMER_PAUSE, mob->CastToClient(), export_string, 0);
} else if (mob->IsBot()) {
parse->EventBot(EVENT_TIMER_PAUSE, mob->CastToBot(), nullptr, export_string, 0);
} else if (mob->IsNPC()) {
parse->EventNPC(EVENT_TIMER_PAUSE, mob->CastToNPC(), nullptr, export_string, 0);
}
++cur;
}
std::string timername = timer_name;
pt.name = timername;
pt.owner = owner;
pt.time = milliseconds;
LogQuests("Pausing timer [{}] for [{}] with [{}] ms remaining", timer_name, owner->GetName(), milliseconds);
PTimerList.push_back(pt);
}
void QuestManager::resumetimer(const char* timer_name, Mob* mob) {
void QuestManager::resumetimer(const std::string& timer_name, Mob* m)
{
QuestManagerCurrentQuestVars();
if (!mob && !owner) {
if (!m && !owner) {
return;
}
std::list<QuestTimer>::iterator cur = QTimerList.begin(), end;
std::list<PausedTimer>::iterator pcur = PTimerList.begin(), pend;
PausedTimer pt;
uint32 milliseconds = 0;
const auto m = mob ? mob : owner;
Mob* mob = m ? m : owner;
pend = PTimerList.end();
while (pcur != pend) {
if (pcur->owner && pcur->owner == m && pcur->name == timer_name) {
milliseconds = pcur->time;
PTimerList.erase(pcur);
break;
}
++pcur;
}
if (milliseconds == 0) {
LogQuests("Paused timer [{}] not found or has expired. Returning", timer_name);
if (!mob) {
return;
}
end = QTimerList.end();
while (cur != end) {
if (cur->mob && cur->mob == m && cur->name == timer_name) {
cur->Timer_.Enable();
cur->Timer_.Start(milliseconds, false);
LogQuests("Resuming timer [{}] for [{}] with [{}] ms remaining",
timer_name,
owner->GetName(),
milliseconds);
return;
if (PTimerList.empty()) {
return;
}
for (auto e = PTimerList.begin(); e != PTimerList.end(); ++e) {
if (e->owner && e->owner == mob && e->name == timer_name) {
milliseconds = e->time;
PTimerList.erase(e);
break;
}
}
if (!milliseconds) {
LogQuests("Paused timer [{}] not found or has expired.", timer_name);
return;
}
const bool has_resume_event = (
(mob->IsClient() && parse->PlayerHasQuestSub(EVENT_TIMER_RESUME)) ||
(mob->IsBot() && parse->BotHasQuestSub(EVENT_TIMER_RESUME)) ||
(mob->IsNPC() && parse->HasQuestSub(mob->GetNPCTypeID(), EVENT_TIMER_RESUME))
);
if (!QTimerList.empty()) {
for (auto e : QTimerList) {
if (e.mob && e.mob == mob && e.name == timer_name) {
e.Timer_.Enable();
e.Timer_.Start(milliseconds, false);
LogQuests(
"Resuming timer [{}] for [{}] with [{}] ms remaining",
timer_name,
owner->GetName(),
milliseconds
);
if (has_resume_event) {
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
milliseconds
);
if (mob->IsClient()) {
parse->EventPlayer(EVENT_TIMER_RESUME, mob->CastToClient(), export_string, 0);
} else if (mob->IsBot()) {
parse->EventBot(EVENT_TIMER_RESUME, mob->CastToBot(), nullptr, export_string, 0);
} else if (mob->IsNPC()) {
parse->EventNPC(EVENT_TIMER_RESUME, mob->CastToNPC(), nullptr, export_string, 0);
}
}
return;
}
}
++cur;
}
QTimerList.emplace_back(QuestTimer(milliseconds, m, timer_name));
LogQuests("Creating a new timer and resuming [{}] for [{}] with [{}] ms remaining", timer_name, owner->GetName(), milliseconds);
if (has_resume_event) {
const std::string& export_string = fmt::format(
"{} {}",
timer_name,
milliseconds
);
if (mob->IsClient()) {
parse->EventPlayer(EVENT_TIMER_RESUME, mob->CastToClient(), export_string, 0);
} else if (mob->IsBot()) {
parse->EventBot(EVENT_TIMER_RESUME, mob->CastToBot(), nullptr, export_string, 0);
} else if (mob->IsNPC()) {
parse->EventNPC(EVENT_TIMER_RESUME, mob->CastToNPC(), nullptr, export_string, 0);
}
}
LogQuests(
"Creating a new timer and resuming [{}] for [{}] with [{}] ms remaining",
timer_name,
owner->GetName(),
milliseconds
);
}
bool QuestManager::ispausedtimer(const char* timer_name, Mob* mob) {
bool QuestManager::ispausedtimer(const std::string& timer_name, Mob* m)
{
QuestManagerCurrentQuestVars();
std::list<PausedTimer>::iterator pcur = PTimerList.begin(), pend;
const auto m = mob ? mob : owner;
pend = PTimerList.end();
while (pcur != pend) {
if (pcur->owner && pcur->owner == m && pcur->name == timer_name) {
return true;
}
++pcur;
if (!m && !owner) {
return false;
}
return false;
Mob* mob = m ? m : owner;
if (!mob) {
return false;
}
const auto& e = std::find_if(
PTimerList.begin(),
PTimerList.end(),
[&timer_name, &mob](PausedTimer e) {
return e.owner && e.owner == mob && e.name == timer_name;
}
);
return e != PTimerList.end();
}
bool QuestManager::hastimer(const char* timer_name, Mob* mob) {
bool QuestManager::hastimer(const std::string& timer_name, Mob* m)
{
QuestManagerCurrentQuestVars();
std::list<QuestTimer>::iterator cur = QTimerList.begin(), end;
const auto m = mob ? mob : owner;
end = QTimerList.end();
while (cur != end) {
if (cur->mob && cur->mob == m && cur->name == timer_name) {
if (cur->Timer_.Enabled()) {
return true;
}
}
++cur;
if (!m && !owner) {
return false;
}
return false;
Mob* mob = m ? m : owner;
if (!mob) {
return false;
}
const auto& e = std::find_if(
QTimerList.begin(),
QTimerList.end(),
[&timer_name, &mob](QuestTimer e) {
return e.mob && e.mob == mob && e.name == timer_name;
}
);
return e != QTimerList.end();
}
uint32 QuestManager::getremainingtimeMS(const char* timer_name, Mob* mob) {
uint32 QuestManager::getremainingtimeMS(const std::string& timer_name, Mob* m)
{
QuestManagerCurrentQuestVars();
std::list<QuestTimer>::iterator cur = QTimerList.begin(), end;
const auto m = mob ? mob : owner;
end = QTimerList.end();
while (cur != end) {
if (cur->mob && cur->mob == m && cur->name == timer_name) {
if (cur->Timer_.Enabled()) {
return cur->Timer_.GetRemainingTime();
}
}
++cur;
if (!m && !owner) {
return 0;
}
return 0;
const auto mob = m ? m : owner;
if (!mob) {
return 0;
}
const auto& e = std::find_if(
QTimerList.begin(),
QTimerList.end(),
[&timer_name, &mob](QuestTimer e) {
return e.mob && e.mob == mob && e.name == timer_name;
}
);
return e != QTimerList.end() ? e->Timer_.GetRemainingTime() : 0;
}
uint32 QuestManager::gettimerdurationMS(const char* timer_name, Mob* mob) {
uint32 QuestManager::gettimerdurationMS(const std::string& timer_name, Mob* m)
{
QuestManagerCurrentQuestVars();
std::list<QuestTimer>::iterator cur = QTimerList.begin(), end;
const auto m = mob ? mob : owner;
end = QTimerList.end();
while (cur != end) {
if (cur->mob && cur->mob == m && cur->name == timer_name) {
if (cur->Timer_.Enabled()) {
return cur->Timer_.GetDuration();
}
}
++cur;
if (!m && !owner) {
return 0;
}
return 0;
const auto mob = m ? m : owner;
if (!mob) {
return 0;
}
const auto& e = std::find_if(
QTimerList.begin(),
QTimerList.end(),
[&timer_name, &mob](QuestTimer e) {
return e.mob && e.mob == mob && e.name == timer_name;
}
);
return e != QTimerList.end() ? e->Timer_.GetDuration() : 0;
}
void QuestManager::emote(const char *str) {
+19 -19
View File
@@ -44,9 +44,9 @@ class QuestManager {
};
struct PausedTimer {
Mob * owner;
Mob* owner;
std::string name;
uint32 time;
uint32 time;
};
public:
QuestManager();
@@ -75,28 +75,28 @@ public:
void disable_spawn2(uint32 spawn2_id);
void setstat(int stat, int value);
void incstat(int stat, int value);
void castspell(int spell_id, int target_id);
void selfcast(int spell_id);
void castspell(uint16 spell_id, uint16 target_id);
void selfcast(uint16 spell_id);
void addloot(int item_id, int charges = 0, bool equipitem = true, int aug1 = 0, int aug2 = 0, int aug3 = 0, int aug4 = 0, int aug5 = 0, int aug6 = 0);
void Zone(const char *zone_name);
void ZoneGroup(const char *zone_name);
void ZoneRaid(const char *zone_name);
void settimer(const char* timer_name, int seconds, Mob* mob = nullptr);
void settimerMS(const char* timer_name, int milliseconds);
void settimerMS(const char* timer_name, int milliseconds, EQ::ItemInstance *inst);
void settimerMS(const char* timer_name, int milliseconds, Mob *mob);
void stoptimer(const char* timer_name);
void stoptimer(const char* timer_name, EQ::ItemInstance *inst);
void stoptimer(const char* timer_name, Mob *mob);
void settimer(const std::string& timer_name, uint32 seconds, Mob* m = nullptr);
void settimerMS(const std::string& timer_name, uint32 milliseconds);
void settimerMS(const std::string& timer_name, uint32 milliseconds, EQ::ItemInstance* inst);
void settimerMS(const std::string& timer_name, uint32 milliseconds, Mob* m);
void stoptimer(const std::string& timer_name);
void stoptimer(const std::string& timer_name, EQ::ItemInstance* inst);
void stoptimer(const std::string& timer_name, Mob* m);
void stopalltimers();
void stopalltimers(EQ::ItemInstance *inst);
void stopalltimers(Mob *mob);
void pausetimer(const char* timer_name, Mob* mob = nullptr);
void resumetimer(const char* timer_name, Mob* mob = nullptr);
bool ispausedtimer(const char* timer_name, Mob* mob = nullptr);
bool hastimer(const char* timer_name, Mob* mob = nullptr);
uint32 getremainingtimeMS(const char* timer_name, Mob* mob = nullptr);
uint32 gettimerdurationMS(const char* timer_name, Mob* mob = nullptr);
void stopalltimers(EQ::ItemInstance* inst);
void stopalltimers(Mob* m);
void pausetimer(const std::string& timer_name, Mob* m = nullptr);
void resumetimer(const std::string& timer_name, Mob* m = nullptr);
bool ispausedtimer(const std::string& timer_name, Mob* m = nullptr);
bool hastimer(const std::string& timer_name, Mob* m = nullptr);
uint32 getremainingtimeMS(const std::string& timer_name, Mob* m = nullptr);
uint32 gettimerdurationMS(const std::string& timer_name, Mob* m = nullptr);
void emote(const char *str);
void shout(const char *str);
void shout2(const char *str);
+2 -2
View File
@@ -440,14 +440,14 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList<Spawn2*> &spa
std::unordered_map<uint32, uint32> spawn_times;
timeval tv;
timeval tv{};
gettimeofday(&tv, nullptr);
/* Bulk Load NPC Types Data into the cache */
content_db.LoadNPCTypesData(0, true);
const auto& l = RespawnTimesRepository::GetWhere(
*this,
database,
fmt::format(
"`instance_id` = {}",
zone->GetInstanceID()
+1 -10
View File
@@ -223,16 +223,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot,
// check to see if target is a caster mob before performing a mana tap
if(GetTarget() && IsManaTapSpell(spell_id)) {
if (
GetTarget()->GetCasterClass() == 'N' &&
(
!RuleB(Spells, ManaTapsRequireNPCMana) ||
(
RuleB(Spells, ManaTapsRequireNPCMana) &&
GetTarget()->GetMana() == 0
)
)
) {
if (!RuleB(Spells, ManaTapsOnAnyClass) && GetTarget()->GetCasterClass() != 'N' && RuleB(Spells, ManaTapsRequireNPCMana) && GetTarget()->GetMana() == 0) {
InterruptSpell(TARGET_NO_MANA, 0x121, spell_id);
return false;
}
+6
View File
@@ -483,6 +483,10 @@
#define NO_CAST_OUT_OF_COMBAT 9191 //You can not cast this spell while out of combat.
#define NO_ABILITY_IN_COMBAT 9192 //You can not use this ability while in combat.
#define NO_ABILITY_OUT_OF_COMBAT 9194 //You can not use this ability while out of combat.
#define GAIN_GROUPXP_BONUS 9298 //You gain party experience (with a bonus)!
#define GAIN_GROUPXP_PENALTY 9301 //You gain party experience (with a penalty)!
#define GAIN_RAIDXP_BONUS 9302 //You gained raid experience (with a bonus)!
#define GAIN_RAIDXP_PENALTY 9303 //You gained raid experience (with a penalty)!
#define LESSER_SPELL_VERSION 11004 //%1 is a lesser version of %2 and cannot be scribed
#define AE_RAMPAGE 11015 //%1 goes on a WILD RAMPAGE!
#define GROUP_IS_FULL 12000 //You cannot join that group, it is full.
@@ -562,6 +566,8 @@
#define TOGGLE_OFF 13173 //Asking server to turn OFF all incoming tells for you.
#define DUEL_INPROGRESS 13251 //You have already accepted a duel with someone else cowardly dog.
#define OTHER_HIT_DOT 13327 //%1 has taken %2 damage from %3 by %4.
#define GAIN_XP_BONUS 14541 //You gain experience (with a bonus)!
#define GAIN_XP_PENALTY 14542 //You gain experience (with a penalty)!
#define GENERIC_MISS 15041 //%1 missed %2
#endif
+3 -3
View File
@@ -411,7 +411,7 @@ void Client::SendGuildTributes()
gtas->ability.tiers[ti].tribute_item_id = htonl(t.second.tiers[ti].tribute_item_id);
gtas->ability.tiers[ti].level = htonl(t.second.tiers[ti].level);
}
strcpy(gtas->ability.name, t.second.name.data());
strn0cpy(gtas->ability.name, t.second.name.data(), t.second.name.length());
FastQueuePacket(&outapp);
}
}
@@ -432,7 +432,7 @@ void Client::SendGuildTributeDetails(uint32 tribute_id, uint32 tier)
t->tribute_id = tribute_id;
t->tier = tier;
t->tribute_id2 = tribute_id;
strncpy(&t->description, td.description.c_str(), len);
strn0cpy(&t->description, td.description.c_str(), len);
QueuePacket(outapp);
safe_delete(outapp);
@@ -556,7 +556,7 @@ void Client::SendGuildTributeOptInToggle(const GuildTributeMemberToggle* in)
EQApplicationPacket* outapp = new EQApplicationPacket(OP_GuildOptInOut, sizeof(GuildTributeOptInOutReply_Struct));
GuildTributeOptInOutReply_Struct* data = (GuildTributeOptInOutReply_Struct*)outapp->pBuffer;
strncpy(data->player_name, in->player_name, 64);
strn0cpy(data->player_name, in->player_name, sizeof(data->player_name));
data->guild_id = in->guild_id;
data->no_donations = in->no_donations;
data->tribute_toggle = in->tribute_toggle;
+7
View File
@@ -58,6 +58,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "bot_command.h"
#include "../common/events/player_event_logs.h"
#include "../common/repositories/guild_tributes_repository.h"
#include "../common/patches/patches.h"
extern EntityList entity_list;
extern Zone* zone;
@@ -1978,6 +1979,12 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
}
break;
}
case ServerOP_ReloadOpcodes:
{
zone->SendReloadMessage("Opcodes");
ReloadAllPatches();
break;
}
case ServerOP_ReloadAlternateCurrencies:
{
if (zone && zone->IsLoaded()) {
+16 -14
View File
@@ -1898,6 +1898,10 @@ void Zone::Repop(bool is_forced)
return;
}
if (is_forced) {
ClearSpawnTimers();
}
LinkedListIterator<Spawn2 *> iterator(spawn2_list);
iterator.Reset();
@@ -1905,10 +1909,6 @@ void Zone::Repop(bool is_forced)
iterator.RemoveCurrent();
}
if (is_forced) {
ClearSpawnTimers();
}
npc_scale_manager->LoadScaleData();
entity_list.ClearTrapPointers();
@@ -2649,22 +2649,24 @@ void Zone::ClearSpawnTimers()
iterator.Reset();
std::vector<std::string> respawn_ids;
std::vector<uint32> respawn_ids;
while (iterator.MoreElements()) {
respawn_ids.emplace_back(std::to_string(iterator.GetData()->GetID()));
respawn_ids.emplace_back(iterator.GetData()->spawn2_id);
iterator.Advance();
}
RespawnTimesRepository::DeleteWhere(
database,
fmt::format(
"`instance_id` = {} AND `id` IN ({})",
GetInstanceID(),
Strings::Implode(", ", respawn_ids)
)
);
if (!respawn_ids.empty()) {
RespawnTimesRepository::DeleteWhere(
database,
fmt::format(
"`instance_id` = {} AND `id` IN ({})",
GetInstanceID(),
Strings::Join(respawn_ids, ", ")
)
);
}
}
uint32 Zone::GetSpawnKillCount(uint32 in_spawnid) {
+3
View File
@@ -114,6 +114,9 @@ void Zone::ReloadNPCFactions()
NpcFactionRepository::NpcFaction* Zone::GetNPCFaction(const uint32 npc_faction_id)
{
// Maybe we're being asked to load an npc_faction not yet used in the zone
LoadNPCFaction(npc_faction_id);
for (auto& e : m_npc_factions) {
if (e.id == npc_faction_id) {
return &e;
+6 -4
View File
@@ -214,7 +214,7 @@ void ZoneDatabase::LoadWorldContainer(uint32 parent_id, EQ::ItemInstance* contai
}
const auto& l = ObjectContentsRepository::GetWhere(
*this,
database,
fmt::format(
"`parentid` = {}",
parent_id
@@ -271,7 +271,7 @@ void ZoneDatabase::SaveWorldContainer(uint32 zone_id, uint32 parent_id, const EQ
}
ObjectContentsRepository::ReplaceOne(
*this,
database,
ObjectContentsRepository::ObjectContents{
.zoneid = zone_id,
.parentid = parent_id,
@@ -293,7 +293,7 @@ void ZoneDatabase::SaveWorldContainer(uint32 zone_id, uint32 parent_id, const EQ
void ZoneDatabase::DeleteWorldContainer(uint32 parent_id, uint32 zone_id)
{
ObjectContentsRepository::DeleteWhere(
*this,
database,
fmt::format(
"`parentid` = {} AND `zoneid` = {}",
parent_id,
@@ -3988,7 +3988,9 @@ bool ZoneDatabase::SummonAllCharacterCorpses(
}
}
CharacterCorpsesRepository::ReplaceMany(*this, l);
if (!l.empty()) {
CharacterCorpsesRepository::ReplaceMany(*this, l);
}
return corpse_count > 0;
}
+34 -38
View File
@@ -35,6 +35,7 @@ extern WorldServer worldserver;
extern Zone* zone;
#include "../common/repositories/character_peqzone_flags_repository.h"
#include "../common/repositories/zone_flags_repository.h"
#include "../common/events/player_event_logs.h"
@@ -71,6 +72,8 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
int(zone_mode)
);
content_service.HandleZoneRoutingMiddleware(zc);
uint16 target_zone_id = 0;
auto target_instance_id = zc->instanceID;
ZonePoint* zone_point = nullptr;
@@ -1067,53 +1070,48 @@ void Client::GoToDeath() {
MovePC(m_pp.binds[0].zone_id, m_pp.binds[0].instance_id, 0.0f, 0.0f, 0.0f, 0.0f, 1, ZoneToBindPoint);
}
void Client::ClearZoneFlag(uint32 zone_id) {
void Client::ClearZoneFlag(uint32 zone_id)
{
if (!HasZoneFlag(zone_id)) {
return;
}
zone_flags.erase(zone_id);
std::string query = fmt::format(
"DELETE FROM zone_flags WHERE charID = {} AND zoneID = {}",
CharacterID(),
zone_id
ZoneFlagsRepository::DeleteWhere(
database,
fmt::format(
"`charID` = {} AND `zoneID` = {}",
CharacterID(),
zone_id
)
);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
LogError("MySQL Error while trying to clear zone flag for [{}]: [{}]", GetName(), results.ErrorMessage().c_str());
}
}
bool Client::HasZoneFlag(uint32 zone_id) const {
bool Client::HasZoneFlag(uint32 zone_id) const
{
return zone_flags.find(zone_id) != zone_flags.end();
}
void Client::LoadZoneFlags() {
const auto query = fmt::format(
"SELECT zoneID from zone_flags WHERE charID = {}",
CharacterID()
void Client::LoadZoneFlags()
{
const auto& l = ZoneFlagsRepository::GetWhere(
database,
fmt::format(
"`charID` = {}",
CharacterID()
)
);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
LogError("MySQL Error while trying to load zone flags for [{}]: [{}]", GetName(), results.ErrorMessage().c_str());
return;
}
if (!results.RowCount()) {
return;
}
zone_flags.clear();
for (auto row : results) {
zone_flags.insert(Strings::ToUnsignedInt(row[0]));
for (const auto& e : l) {
zone_flags.insert(e.zoneID);
}
}
void Client::SendZoneFlagInfo(Client *to) const {
void Client::SendZoneFlagInfo(Client* to) const
{
if (zone_flags.empty()) {
to->Message(
Chat::White,
@@ -1178,23 +1176,21 @@ void Client::SendZoneFlagInfo(Client *to) const {
);
}
void Client::SetZoneFlag(uint32 zone_id) {
void Client::SetZoneFlag(uint32 zone_id)
{
if (HasZoneFlag(zone_id)) {
return;
}
zone_flags.insert(zone_id);
const auto query = fmt::format(
"INSERT INTO zone_flags (charID, zoneID) VALUES ({}, {})",
CharacterID(),
zone_id
ZoneFlagsRepository::InsertOne(
database,
ZoneFlagsRepository::ZoneFlags{
.charID = static_cast<int32_t>(CharacterID()),
.zoneID = static_cast<int32_t>(zone_id)
}
);
auto results = database.QueryDatabase(query);
if (!results.Success()) {
LogError("MySQL Error while trying to set zone flag for [{}]: [{}]", GetName(), results.ErrorMessage().c_str());
}
}
void Client::ClearPEQZoneFlag(uint32 zone_id) {