Compare commits

...

41 Commits

Author SHA1 Message Date
Chris Miles 158396937a [Release] 22.3.0 (#2842)
* [Release] 22.3.0

* Update version.h

* Redirect stderr

* Update should-release to filter non-master

* Update should-release
2023-02-06 20:12:04 -06:00
Aeadoin fb1467284c [Bots] Add Additional HeroicStr modifiers. (#2837) 2023-02-06 21:07:38 -05:00
Aeadoin 14addd4869 [Feature] Add IsOfClientBotMerc() virtual method. (#2843) 2023-02-06 21:03:48 -05:00
Chris Miles 0a114fae9a [Doors] Have NPCs trigger double doors (#2821) 2023-02-06 17:47:03 -06:00
Chris Miles 2b224d42ad [Rules] Fix rule updates that affected bot booting checks (#2841) 2023-02-06 17:31:50 -06:00
Natedog2012 155ec9ac0d [Quest API] Add rule AlternateAugmentationSealer for using a different bagtype (#2831)
* [Quest API] Add rule AlternateAugmentationSealer for using a different bagtype as an alternate augmentation sealer. Use EVENT_COMBINE with UseAugmentContainer

* Default it to be off or bagtype 53 (BagTypeAugmentationSealer)
2023-02-06 17:30:16 -06:00
Chris Miles 25b4b97c41 [DB Updates] Add Windows MySQL path auto detection for users where the path is not found (#2836) 2023-02-06 17:25:34 -06:00
Joel 839f31b24d [Rule] Added rule to bypass level based haste caps (#2835) 2023-02-06 17:25:17 -06:00
Chris Miles 20728c31c4 [Crash] Fix crash in bot command botdyearmor (#2832)
* [Crash] Fix crash in bot command botdyearmor

* Update bot_command.cpp
2023-02-06 17:24:49 -06:00
Chris Miles c6eb12ac16 [Crash] Fix IsUnderwaterOnly crash where npc data references can be stale (#2830)
* [Crash] Fix IsUnderwaterOnly crash where npc data references can be stale

* m_ prefix
2023-02-06 17:24:38 -06:00
Chris Miles 34d21d4056 [Crash] Fix command crash with #npcedit weapon when second weapon not passed ni (#2829) 2023-02-06 17:24:24 -06:00
Chris Miles d369b47ef4 [Tasks] Implement alternate currency rewards (#2827)
* Reward currency on task completion

* Handle reward window

* Tweaks
2023-02-06 17:24:13 -06:00
Chris Miles 404f7cada8 [Pathing] Improvements to handling tight corridors pathing, clipping detection and recovery (#2826) 2023-02-06 17:24:03 -06:00
Chris Miles 823e73336d [Command] #list now searches without case sensitivity (#2825) 2023-02-06 17:23:50 -06:00
Chris Miles 0da6391be3 [Doors] Remove door dev tools spam on client controlled doors (#2824)
* [Doors] Remove door dev tools spam on client controlled doors

* Update client_packet.cpp

* Update client_packet.cpp

* Update ruletypes.h
2023-02-06 17:23:40 -06:00
Chris Miles 0348cb6b8e [Fix] Fix NPC ghosting at safe coordinates (#2823)
* [Fix] Fix NPC ghosting at safe coordinates

* Tweak order

* Handle another case
2023-02-06 17:23:29 -06:00
Vayle b385a4385f [Rules] Add rule to ignore name filter on chat channel creation. (#2820)
* [Rules] Add rule to ignore name filter on chat channel creation.

* Conditional reorder
2023-02-06 17:22:12 -06:00
Chris Miles 6a9228ed6e [Lua] Resolve stoi Exception (#2736)
* [Lua] Resolve stoi Exception

* Change fallback for wp, not really needed for safety

* Change to Strings::ToInt
2023-02-06 17:22:01 -06:00
Vayle 8031bf0bcb [Quest API] Add EVENT_TASKACCEPTED to Player scope (#2822)
* Add EVENT_TASKACCEPTED to player scope

* Formatting
2023-02-05 22:53:37 -05:00
Alex King c1584da9cc [Quest API] Default ScaleNPC to always scale. (#2818)
* [Quest API] Default ScaleNPC to always scale.

# Notes
- ScaleNPC will now always override stats, with the option to override special abilities.

* Update npc_scale_manager.h
2023-02-05 22:52:52 -05:00
Alex King ee6f6f683c [Commands] Remove extraneous else from #weather (#2819)
# Notes
- Condition falls back to sending message and can't turn weather off.
2023-02-01 06:05:32 -05:00
Akkadius 60707a14db [Hotfix] Post revert build fix for https://github.com/EQEmu/Server/commit/54050924d81d1f83268fe01f9c2b36fe10626601 2023-01-31 20:37:13 -06:00
Akkadius 54050924d8 Revert "[Quest API] Cleanup string copies and push_backs. (#2807)"
This reverts commit bcc2e022dc.
2023-01-31 20:30:34 -06:00
Aeadoin f727c9f75a [Bug Fix] Fix does_augment_fit_slot method. (#2817)
* [Bug Fix] DoesAugmentFit finds if an Aug Slot is free, changed overload method to check if Aug fits slot.

* Tweak/add lua
2023-01-31 21:11:12 -05:00
Alex King f410c89815 [Quest API] Add Override Parameters to ScaleNPC() in Perl/Lua. (#2816)
# Perl
- Add `$npc->ScaleNPC(level, always_scale_stats)`.
- Add `$npc->ScaleNPC(level, always_scale_stats, always_scale_special_abilities)`.

# Lua
- Add `npc:ScaleNPC(level, always_scale_stats)`.
- Add `npc:ScaleNPC(level, always_scale_stats, always_scale_special_abilities)`.

# Notes
- Allows operators to not have to set stats to 0 in order for scaling to kick in when scripting.
- Special ability override is separate in case you don't want to override some inherent special abilities the NPC has from a script or otherwise.
2023-01-31 21:11:05 -05:00
Natedog2012 2e575652f6 [Bug fix]#reload static should now properly fill the entity_lists for… (#2815)
* [Bug fix]#reload static should now properly fill the entity_lists for objects / doors / groundspawns
The individual #reload commands WILL still have issues when trying to use #list afterwards!

* Point ReloadDoors, ReloadGroundSpawns, ReloadObjects all to reload static to avoid entity_list data missing
2023-01-31 16:32:25 -06:00
Natedog2012 8e831dce36 [Bug fix]#reload aa will now refresh the AA table properly for every client when changes are made (#2814) 2023-01-30 20:24:02 -06:00
Alex King 040c092795 [Quest API] Add Augment Slot support to does_augment_fit (#2813)
* [Quest API] Add Augment Slot support to does_augment_fit

# Notes
- Allows you to check if the supplied augment ID fits in the specified augment slot of the item instance provided.

* Update item_instance.cpp
2023-01-30 21:18:16 -05:00
Alex King a25952910a [Quest API] Add EVENT_ITEM_CLICK_CLIENT and EVENT_ITEM_CLICK_CAST_CLIENT to Perl/Lua. (#2810)
* [Quest API] Add EVENT_ITEM_CLICK_CLIENT and EVENT_ITEM_CLICK_CAST_CLIENT to Perl/Lua.

# Perl
- Add `EVENT_ITEM_CLICK_CLIENT`.
- Add `EVENT_ITEM_CLICK_CAST_CLIENT`.
- Both events export `$item_id`, `$item_name`, `$slot_id`, and `$spell_id`.

# Lua
- Add `event_item_click_client`.
- Add `event_item_click_cast_client`.
- Both events export `e.item_id`, `e.item_name`, `e.slot_id`, `e.spell_id`, and `e.item`.

# Notes
- Allows operators to handle item clicks in player scripts instead of item-specific scripts.

* Update lua_parser_events.cpp

* Remove optional bool.
2023-01-30 05:01:12 -06:00
Natedog2012 66896a3121 [Quest API] Add GetItemCooldown to return the time remaining on items… (#2811)
* [Quest API] Add GetItemCooldown to return the time remaining on items in seconds

* Change GetItemCooldown to uint32 for timers up to 130 years
2023-01-30 00:04:06 -06:00
Paul Coene 4d2418af9d [Bug Fix] BuffLevelRestrictions were restricting group buffs if mob targeted (#2809) 2023-01-29 18:52:03 -05:00
Chris Miles 265b32f46f [Readme] Update build badges with Drone 2023-01-29 17:06:48 -06:00
Alex King 1cde55c535 [Quest API] Add LDoN Methods to Perl/Lua (#2799)
# Perl
- Add `$npc->GetLDoNLockedSkill()`.
- Add `$npc->GetLDoNTrapType()`.
- Add `$npc->GetLDoNTrapSpellID()`.
- Add `$npc->IsLDoNLocked()`.
- Add `$npc->IsLDoNTrapped()`.
- Add `$npc->IsLDoNTrapDetected()`.
- Add `$npc->SetLDoNLocked(is_locked)`.
- Add `$npc->SetLDoNLockedSkill(skill_value)`.
- Add `$npc->SetLDoNTrapped(is_trapped)`.
- Add `$npc->SetLDoNTrapDetected(is_detected)`.
- Add `$npc->SetLDoNTrapSpellID(spell_id)`.
- Add `$npc->SetLDoNTrapType(trap_type)`.

# Lua
- Add `npc:GetLDoNLockedSkill()`.
- Add `npc:GetLDoNTrapType()`.
- Add `npc:GetLDoNTrapSpellID()`.
- Add `npc:IsLDoNLocked()`.
- Add `npc:IsLDoNTrapped()`.
- Add `npc:IsLDoNTrapDetected()`.
- Add `npc:SetLDoNLocked(is_locked)`.
- Add `npc:SetLDoNLockedSkill(skill_value)`.
- Add `npc:SetLDoNTrapped(is_trapped)`.
- Add `npc:SetLDoNTrapDetected(is_detected)`.
- Add `npc:SetLDoNTrapSpellID(spell_id)`.
- Add `npc:SetLDoNTrapType(trap_type)`.

# Notes
- Adds these methods to allow LDoN traps to be set by a script.
2023-01-29 14:29:31 -06:00
Michael 369b5c2921 [Bug] Fixing % based mob see invis (#2802)
This was preventing anything other than 0 or 1 to be passed, but per the current design, the see_invis can be anything from 0 to MAX 25499, which can give you level 254 invis. See design notes in Mob::GetSeeInvisibleLevelFromNPCStat.
2023-01-29 14:26:55 -06:00
Alex King bcc2e022dc [Quest API] Cleanup string copies and push_backs. (#2807)
# Notes
- Several places use `push_back` instead of `emplace_back`.
- Several places use `std::string` instead of `const std::string&`.
2023-01-29 15:14:49 -05:00
Alex King 0fef46a6c1 [Feature] Add Min/Max Status to Merchants (#2806)
# Notes
- Allows operators to set a minimum and maximum status that an item will show for players.
- Allows operators to have items on a merchant that only a GM can see.
- Some servers may use status for different things, so having a minimum and a maximum will allow for more functionality.
- Default of `min_status` is `0` (Player) and default of `max_status` is `255` (Max).
2023-01-29 15:03:41 -05:00
Alex King b867d40774 [Quest API] Add EVENT_DAMAGE_GIVEN and EVENT_DAMAGE_TAKEN to Perl/Lua. (#2804)
* [Quest API] Add EVENT_DAMAGE_GIVEN and EVENT_DAMAGE_TAKEN to Perl/Lua.

# Perl
- Add `EVENT_DAMAGE_GIVEN`.
- Add `EVENT_DAMAGE_TAKEN`.
- Both events export `$entity_id`, `$damage`, `$spell_id`, `$skill_id`, `$is_damage_shield`, `$is_avoidable`, `$buff_slot`, `$is_buff_tic`, `$special_attack`.

# Lua
- Add `event_damage_given`.
- Add `event_damage_taken`.
- Both events export `e.entity_id`, `e.damage`, `e.spell_id`, `e.skill_id`, `e.is_damage_shield`, `e.is_avoidable`, `e.buff_slot`, `e.is_buff_tic`, `e.special_attack`, and `e.other`.

# Notes
- These events allow operators to have events fire based on damage given or taken, as well as keep better track of a Bot, Client, or NPC's damage per second or otherwise.
- Special Attack is only useful for NPCs, but allows you to see if the attack is Rampage, AERampage, or Chaotic Stab.

* Cleanup.
2023-01-29 14:35:17 -05:00
Aeadoin a489290eba [Bots] Add GetAugmentIDsBySlotID & AddItem with table ref Methods. (#2805)
* [Bots] Add GetAugmentIDsBySlotID & AddItem with table ref Methods.

* Return invalid slots to owner.
2023-01-29 12:49:44 -05:00
Alex King 549d731849 [Bug Fix] Resolve issue with max buff count being 25 in ROF2. (#2800)
# Notes
- This allows ROF2 to properly utilize their max buff count.
- May cause issues with older clients.
2023-01-28 17:40:11 -06:00
Natedog2012 68a34565f9 [Bugfix] Add SetItemCooldown to tell client exact timer of item when clicked and export to perl and lua (#2795)
Items that are on cooldown but client doesn't show.. clicking item will fix the timer in client
2023-01-27 17:31:14 -06:00
Aeadoin c05f951f81 [Bots] Add Override methods for GetMax Buffs/Songs/Total slots (#2801) 2023-01-27 18:00:50 -05:00
81 changed files with 1913 additions and 702 deletions
+78
View File
@@ -1,3 +1,81 @@
## [22.3.0] - 02/06/2023
### Bots
* Add GetAugmentIDsBySlotID & AddItem with table ref Methods. ([#2805](https://github.com/EQEmu/Server/pull/2805)) ([Aeadoin](https://github.com/Aeadoin)) 2023-01-29
### Commands
* #list now searches without case sensitivity ([#2825](https://github.com/EQEmu/Server/pull/2825)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06
* Remove extraneous else from #weather ([#2819](https://github.com/EQEmu/Server/pull/2819)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-01
### Crash
* Fix IsUnderwaterOnly crash where npc data references can be stale ([#2830](https://github.com/EQEmu/Server/pull/2830)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06
* Fix command crash with #npcedit weapon when second weapon not passed ni ([#2829](https://github.com/EQEmu/Server/pull/2829)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06
* Fix crash in bot command botdyearmor ([#2832](https://github.com/EQEmu/Server/pull/2832)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06
### DB Updates
* Add Windows MySQL path auto detection for users where the path is not found ([#2836](https://github.com/EQEmu/Server/pull/2836)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06
### Doors
* Have NPCs trigger double doors ([#2821](https://github.com/EQEmu/Server/pull/2821)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06
* Remove door dev tools spam on client controlled doors ([#2824](https://github.com/EQEmu/Server/pull/2824)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06
### Feature
* Add Min/Max Status to Merchants ([#2806](https://github.com/EQEmu/Server/pull/2806)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-29
### Fixes
* #reload aa will now refresh the AA table properly for every client when changes are made ([#2814](https://github.com/EQEmu/Server/pull/2814)) ([Natedog2012](https://github.com/Natedog2012)) 2023-01-31
* #reload static should now properly fill the entity_lists for… ([#2815](https://github.com/EQEmu/Server/pull/2815)) ([Natedog2012](https://github.com/Natedog2012)) 2023-01-31
* BuffLevelRestrictions were restricting group buffs if mob targeted ([#2809](https://github.com/EQEmu/Server/pull/2809)) ([noudess](https://github.com/noudess)) 2023-01-29
* Fix does_augment_fit_slot method. ([#2817](https://github.com/EQEmu/Server/pull/2817)) ([Aeadoin](https://github.com/Aeadoin)) 2023-02-01
* Fix NPC ghosting at safe coordinates ([#2823](https://github.com/EQEmu/Server/pull/2823)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06
* Fixing % based mob see invis ([#2802](https://github.com/EQEmu/Server/pull/2802)) ([fryguy503](https://github.com/fryguy503)) 2023-01-29
* Resolve issue with max buff count being 25 in ROF2. ([#2800](https://github.com/EQEmu/Server/pull/2800)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-28
### Hotfix
* Post revert build fix for https://github.com/EQEmu/Server/commit/54050924d81d1f83268fe01f9c2b36fe10626601 ([Akkadius](https://github.com/Akkadius)) 2023-02-01
### Lua
* Resolve stoi Exception ([#2736](https://github.com/EQEmu/Server/pull/2736)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06
### Pathing
* Improvements to handling tight corridors pathing, clipping detection and recovery ([#2826](https://github.com/EQEmu/Server/pull/2826)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06
### Quest API
* Add Augment Slot support to does_augment_fit ([#2813](https://github.com/EQEmu/Server/pull/2813)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-31
* Add EVENT_DAMAGE_GIVEN and EVENT_DAMAGE_TAKEN to Perl/Lua. ([#2804](https://github.com/EQEmu/Server/pull/2804)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-29
* Add EVENT_ITEM_CLICK_CLIENT and EVENT_ITEM_CLICK_CAST_CLIENT to Perl/Lua. ([#2810](https://github.com/EQEmu/Server/pull/2810)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-30
* Add EVENT_TASKACCEPTED to Player scope ([#2822](https://github.com/EQEmu/Server/pull/2822)) ([Valorith](https://github.com/Valorith)) 2023-02-06
* Add GetItemCooldown to return the time remaining on items… ([#2811](https://github.com/EQEmu/Server/pull/2811)) ([Natedog2012](https://github.com/Natedog2012)) 2023-01-30
* Add LDoN Methods to Perl/Lua ([#2799](https://github.com/EQEmu/Server/pull/2799)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-01-29
* Add Override Parameters to ScaleNPC() in Perl/Lua. ([#2816](https://github.com/EQEmu/Server/pull/2816)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-01
* Add rule AlternateAugmentationSealer for using a different bagtype ([#2831](https://github.com/EQEmu/Server/pull/2831)) ([Natedog2012](https://github.com/Natedog2012)) 2023-02-06
* Default ScaleNPC to always scale. ([#2818](https://github.com/EQEmu/Server/pull/2818)) ([Kinglykrab](https://github.com/Kinglykrab)) 2023-02-06
### Readme
* Update build badges with Drone ([Akkadius](https://github.com/Akkadius)) 2023-01-29
### Rules
* Add rule to ignore name filter on chat channel creation. ([#2820](https://github.com/EQEmu/Server/pull/2820)) ([Valorith](https://github.com/Valorith)) 2023-02-06
* Added rule to bypass level based haste caps ([#2835](https://github.com/EQEmu/Server/pull/2835)) ([jcr4990](https://github.com/jcr4990)) 2023-02-06
* Fix rule updates that affected bot booting checks ([#2841](https://github.com/EQEmu/Server/pull/2841)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06
### Tasks
* Implement alternate currency rewards ([#2827](https://github.com/EQEmu/Server/pull/2827)) ([Akkadius](https://github.com/Akkadius)) 2023-02-06
## [22.2.0] - 01/27/2023
### Bots
+3 -3
View File
@@ -1,7 +1,7 @@
# EQEmulator Core Server
|Travis CI (Linux)|Appveyor (Windows x86) |Appveyor (Windows x64) |
|:---:|:---:|:---:|
|[![Linux CI](https://travis-ci.org/EQEmu/Server.svg?branch=master)](https://travis-ci.org/EQEmu/Server) |[![Build status](https://ci.appveyor.com/api/projects/status/v3utuu0dttm2cqd0?svg=true)](https://ci.appveyor.com/project/KimLS/server) |[![Build status](https://ci.appveyor.com/api/projects/status/scr25kmntx36c1ub?svg=true)](https://ci.appveyor.com/project/KimLS/server-87crp) |
| Drone (Linux x64) | Drone (Windows x64) |
|:---:|:---:|
|[![Build Status](http://drone.akkadius.com/api/badges/EQEmu/Server/status.svg)](http://drone.akkadius.com/EQEmu/Server) |[![Build Status](http://drone.akkadius.com/api/badges/EQEmu/Server/status.svg)](http://drone.akkadius.com/EQEmu/Server) |
***
+3 -2
View File
@@ -476,10 +476,11 @@ bool Database::CheckDatabaseConversions() {
CheckDatabaseConvertPPDeblob();
CheckDatabaseConvertCorpseDeblob();
RuleManager::Instance()->LoadRules(this, "default", false);
auto *r = RuleManager::Instance();
r->LoadRules(this, "default", false);
if (!RuleB(Bots, Enabled) && DoesTableExist("bot_data")) {
LogInfo("Bot tables found but rule not enabled, enabling");
RuleManager::Instance()->SetRule("Bots:Enabled", "true", this, true, true);
r->SetRule("Bots:Enabled", "true", this, true, true);
}
/* Run EQEmu Server script (Checks for database updates) */
+3
View File
@@ -1028,4 +1028,7 @@ enum ZoningMessage : int8
ZoneNoExperience = -7
};
#define ALT_CURRENCY_ID_RADIANT 4
#define ALT_CURRENCY_ID_EBON 5
#endif /*COMMON_EQ_CONSTANTS_H*/
+12 -10
View File
@@ -29,7 +29,7 @@
#include "textures.h"
static const uint32 BUFF_COUNT = 25;
static const uint32 BUFF_COUNT = 42;
static const uint32 PET_BUFF_COUNT = 30;
static const uint32 MAX_MERC = 100;
static const uint32 MAX_MERC_GRADES = 10;
@@ -3632,17 +3632,19 @@ struct LevelAppearance_Struct { //Sends a little graphic on level up
};
struct MerchantList {
uint32 id;
uint32 slot;
uint32 item;
int16 faction_required;
int8 level_required;
uint16 alt_currency_cost;
uint32 classes_required;
uint8 probability;
uint32 id;
uint32 slot;
uint32 item;
int16 faction_required;
int8 level_required;
uint8 min_status;
uint8 max_status;
uint16 alt_currency_cost;
uint32 classes_required;
uint8 probability;
std::string bucket_name;
std::string bucket_value;
uint8 bucket_comparison;
uint8 bucket_comparison;
};
struct TempMerchantList {
+17 -5
View File
@@ -358,15 +358,27 @@ int8 EQ::ItemInstance::AvailableAugmentSlot(int32 augment_type) const
return (i <= invaug::SOCKET_END) ? i : INVALID_INDEX;
}
bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augtype, uint8 slot) const
bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const
{
if (!m_item || !m_item->IsClassCommon())
return false;
if (!m_item || !m_item->IsClassCommon()) {
return false;
}
if ((!GetItem(slot) && m_item->AugSlotVisible[slot]) && augtype == -1 || (m_item->AugSlotType[slot] && ((1 << (m_item->AugSlotType[slot] - 1)) & augtype))) {
if (
(
!GetItem(slot) &&
m_item->AugSlotVisible[slot]
) &&
augment_type == -1 ||
(
m_item->AugSlotType[slot] &&
((1 << (m_item->AugSlotType[slot] - 1)) & augment_type)
)
) {
return true;
}
return false;
return false;
}
// Retrieve item inside container
+2 -2
View File
@@ -101,8 +101,8 @@ namespace EQ
//
bool IsAugmentable() const;
bool AvailableWearSlot(uint32 aug_wear_slots) const;
int8 AvailableAugmentSlot(int32 augtype) const;
bool IsAugmentSlotAvailable(int32 augtype, uint8 slot) const;
int8 AvailableAugmentSlot(int32 augment_type) const;
bool IsAugmentSlotAvailable(int32 augment_type, uint8 slot) const;
inline int32 GetAugmentType() const { return ((m_item) ? m_item->AugType : 0); }
inline bool IsExpendable() const { return ((m_item) ? ((m_item->Click.Type == item::ItemEffectExpendable) || (m_item->ItemType == item::ItemTypePotion)) : false); }
@@ -16,6 +16,7 @@
#include "../../strings.h"
#include <ctime>
class BaseMerchantlistRepository {
public:
struct Merchantlist {
@@ -24,6 +25,8 @@ public:
int32_t item;
int16_t faction_required;
uint8_t level_required;
uint8_t min_status;
uint8_t max_status;
uint16_t alt_currency_cost;
int32_t classes_required;
int32_t probability;
@@ -49,6 +52,8 @@ public:
"item",
"faction_required",
"level_required",
"min_status",
"max_status",
"alt_currency_cost",
"classes_required",
"probability",
@@ -70,6 +75,8 @@ public:
"item",
"faction_required",
"level_required",
"min_status",
"max_status",
"alt_currency_cost",
"classes_required",
"probability",
@@ -125,6 +132,8 @@ public:
e.item = 0;
e.faction_required = -100;
e.level_required = 0;
e.min_status = 0;
e.max_status = 255;
e.alt_currency_cost = 0;
e.classes_required = 65535;
e.probability = 100;
@@ -160,8 +169,9 @@ public:
{
auto results = db.QueryDatabase(
fmt::format(
"{} WHERE id = {} LIMIT 1",
"{} WHERE {} = {} LIMIT 1",
BaseSelect(),
PrimaryKey(),
merchantlist_id
)
);
@@ -175,16 +185,18 @@ public:
e.item = static_cast<int32_t>(atoi(row[2]));
e.faction_required = static_cast<int16_t>(atoi(row[3]));
e.level_required = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.alt_currency_cost = static_cast<uint16_t>(strtoul(row[5], nullptr, 10));
e.classes_required = static_cast<int32_t>(atoi(row[6]));
e.probability = static_cast<int32_t>(atoi(row[7]));
e.bucket_name = row[8] ? row[8] : "";
e.bucket_value = row[9] ? row[9] : "";
e.bucket_comparison = static_cast<uint8_t>(strtoul(row[10], nullptr, 10));
e.min_expansion = static_cast<int8_t>(atoi(row[11]));
e.max_expansion = static_cast<int8_t>(atoi(row[12]));
e.content_flags = row[13] ? row[13] : "";
e.content_flags_disabled = row[14] ? row[14] : "";
e.min_status = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
e.max_status = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.alt_currency_cost = static_cast<uint16_t>(strtoul(row[7], nullptr, 10));
e.classes_required = static_cast<int32_t>(atoi(row[8]));
e.probability = static_cast<int32_t>(atoi(row[9]));
e.bucket_name = row[10] ? row[10] : "";
e.bucket_value = row[11] ? row[11] : "";
e.bucket_comparison = static_cast<uint8_t>(strtoul(row[12], nullptr, 10));
e.min_expansion = static_cast<int8_t>(atoi(row[13]));
e.max_expansion = static_cast<int8_t>(atoi(row[14]));
e.content_flags = row[15] ? row[15] : "";
e.content_flags_disabled = row[16] ? row[16] : "";
return e;
}
@@ -223,16 +235,18 @@ public:
v.push_back(columns[2] + " = " + std::to_string(e.item));
v.push_back(columns[3] + " = " + std::to_string(e.faction_required));
v.push_back(columns[4] + " = " + std::to_string(e.level_required));
v.push_back(columns[5] + " = " + std::to_string(e.alt_currency_cost));
v.push_back(columns[6] + " = " + std::to_string(e.classes_required));
v.push_back(columns[7] + " = " + std::to_string(e.probability));
v.push_back(columns[8] + " = '" + Strings::Escape(e.bucket_name) + "'");
v.push_back(columns[9] + " = '" + Strings::Escape(e.bucket_value) + "'");
v.push_back(columns[10] + " = " + std::to_string(e.bucket_comparison));
v.push_back(columns[11] + " = " + std::to_string(e.min_expansion));
v.push_back(columns[12] + " = " + std::to_string(e.max_expansion));
v.push_back(columns[13] + " = '" + Strings::Escape(e.content_flags) + "'");
v.push_back(columns[14] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
v.push_back(columns[5] + " = " + std::to_string(e.min_status));
v.push_back(columns[6] + " = " + std::to_string(e.max_status));
v.push_back(columns[7] + " = " + std::to_string(e.alt_currency_cost));
v.push_back(columns[8] + " = " + std::to_string(e.classes_required));
v.push_back(columns[9] + " = " + std::to_string(e.probability));
v.push_back(columns[10] + " = '" + Strings::Escape(e.bucket_name) + "'");
v.push_back(columns[11] + " = '" + Strings::Escape(e.bucket_value) + "'");
v.push_back(columns[12] + " = " + std::to_string(e.bucket_comparison));
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(
@@ -259,6 +273,8 @@ public:
v.push_back(std::to_string(e.item));
v.push_back(std::to_string(e.faction_required));
v.push_back(std::to_string(e.level_required));
v.push_back(std::to_string(e.min_status));
v.push_back(std::to_string(e.max_status));
v.push_back(std::to_string(e.alt_currency_cost));
v.push_back(std::to_string(e.classes_required));
v.push_back(std::to_string(e.probability));
@@ -303,6 +319,8 @@ public:
v.push_back(std::to_string(e.item));
v.push_back(std::to_string(e.faction_required));
v.push_back(std::to_string(e.level_required));
v.push_back(std::to_string(e.min_status));
v.push_back(std::to_string(e.max_status));
v.push_back(std::to_string(e.alt_currency_cost));
v.push_back(std::to_string(e.classes_required));
v.push_back(std::to_string(e.probability));
@@ -351,16 +369,18 @@ public:
e.item = static_cast<int32_t>(atoi(row[2]));
e.faction_required = static_cast<int16_t>(atoi(row[3]));
e.level_required = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.alt_currency_cost = static_cast<uint16_t>(strtoul(row[5], nullptr, 10));
e.classes_required = static_cast<int32_t>(atoi(row[6]));
e.probability = static_cast<int32_t>(atoi(row[7]));
e.bucket_name = row[8] ? row[8] : "";
e.bucket_value = row[9] ? row[9] : "";
e.bucket_comparison = static_cast<uint8_t>(strtoul(row[10], nullptr, 10));
e.min_expansion = static_cast<int8_t>(atoi(row[11]));
e.max_expansion = static_cast<int8_t>(atoi(row[12]));
e.content_flags = row[13] ? row[13] : "";
e.content_flags_disabled = row[14] ? row[14] : "";
e.min_status = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
e.max_status = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.alt_currency_cost = static_cast<uint16_t>(strtoul(row[7], nullptr, 10));
e.classes_required = static_cast<int32_t>(atoi(row[8]));
e.probability = static_cast<int32_t>(atoi(row[9]));
e.bucket_name = row[10] ? row[10] : "";
e.bucket_value = row[11] ? row[11] : "";
e.bucket_comparison = static_cast<uint8_t>(strtoul(row[12], nullptr, 10));
e.min_expansion = static_cast<int8_t>(atoi(row[13]));
e.max_expansion = static_cast<int8_t>(atoi(row[14]));
e.content_flags = row[15] ? row[15] : "";
e.content_flags_disabled = row[16] ? row[16] : "";
all_entries.push_back(e);
}
@@ -390,16 +410,18 @@ public:
e.item = static_cast<int32_t>(atoi(row[2]));
e.faction_required = static_cast<int16_t>(atoi(row[3]));
e.level_required = static_cast<uint8_t>(strtoul(row[4], nullptr, 10));
e.alt_currency_cost = static_cast<uint16_t>(strtoul(row[5], nullptr, 10));
e.classes_required = static_cast<int32_t>(atoi(row[6]));
e.probability = static_cast<int32_t>(atoi(row[7]));
e.bucket_name = row[8] ? row[8] : "";
e.bucket_value = row[9] ? row[9] : "";
e.bucket_comparison = static_cast<uint8_t>(strtoul(row[10], nullptr, 10));
e.min_expansion = static_cast<int8_t>(atoi(row[11]));
e.max_expansion = static_cast<int8_t>(atoi(row[12]));
e.content_flags = row[13] ? row[13] : "";
e.content_flags_disabled = row[14] ? row[14] : "";
e.min_status = static_cast<uint8_t>(strtoul(row[5], nullptr, 10));
e.max_status = static_cast<uint8_t>(strtoul(row[6], nullptr, 10));
e.alt_currency_cost = static_cast<uint16_t>(strtoul(row[7], nullptr, 10));
e.classes_required = static_cast<int32_t>(atoi(row[8]));
e.probability = static_cast<int32_t>(atoi(row[9]));
e.bucket_name = row[10] ? row[10] : "";
e.bucket_value = row[11] ? row[11] : "";
e.bucket_comparison = static_cast<uint8_t>(strtoul(row[12], nullptr, 10));
e.min_expansion = static_cast<int8_t>(atoi(row[13]));
e.max_expansion = static_cast<int8_t>(atoi(row[14]));
e.content_flags = row[15] ? row[15] : "";
e.content_flags_disabled = row[16] ? row[16] : "";
all_entries.push_back(e);
}
+10 -1
View File
@@ -385,7 +385,16 @@ void RuleManager::_SaveRule(Database *db, RuleType type, uint16 index) {
e.rule_value = rule_value;
e.notes = rule_notes;
RuleValuesRepository::UpdateOne(*db, e);
db->QueryDatabase(
fmt::format(
"UPDATE rule_values SET rule_value = '{}', notes = '{}' WHERE ruleset_id = {} AND rule_name = '{}'",
rule_value,
Strings::Escape(rule_notes),
e.ruleset_id,
e.rule_name
)
);
return;
}
+5
View File
@@ -200,6 +200,7 @@ RULE_INT(Character, ExperiencePercentCapPerKill, -1, "Caps the percentage of exp
RULE_BOOL(Character, EnableGroupEXPModifier, true, "Enable or disable the group experience modifier based on number of players in group, default is true")
RULE_REAL(Character, GroupMemberEXPModifier, 0.2, "Sets the group experience modifier per members between 2 and 5, default is 0.2")
RULE_REAL(Character, FullGroupEXPModifier, 2.16, "Sets the group experience modifier for a full group, default is 2.16")
RULE_BOOL(Character, IgnoreLevelBasedHasteCaps, false, "Ignores hard coded level based haste caps.")
RULE_CATEGORY_END()
RULE_CATEGORY(Mercs)
@@ -317,6 +318,7 @@ RULE_BOOL(Map, FixPathingZOnSendTo, false, "Try to repair Z coordinates in the S
RULE_BOOL(Map, FixZWhenPathing, true, "Automatically fix NPC Z coordinates when moving/pathing/engaged (Far less CPU intensive than its predecessor)")
RULE_REAL(Map, DistanceCanTravelBeforeAdjustment, 10.0, "Distance a mob can path before FixZ is called, depends on FixZWhenPathing")
RULE_BOOL(Map, MobZVisualDebug, false, "Displays spell effects determining whether or not NPC is hitting Best Z calcs (blue for hit, red for miss)")
RULE_BOOL(Map, MobPathingVisualDebug, false, "Displays nodes in pathing points in realtime to help with visual debugging")
RULE_REAL(Map, FixPathingZMaxDeltaSendTo, 20, "At runtime in SendTo: maximum change in Z to allow the BestZ code to apply")
RULE_INT(Map, FindBestZHeightAdjust, 1, "Adds this to the current Z before seeking the best Z position")
RULE_CATEGORY_END()
@@ -583,6 +585,7 @@ RULE_INT(Range, SongMessages, 75, "The packet range in which song messages are s
RULE_INT(Range, ClientPositionUpdates, 300, "Distance in which the own changed position is communicated to other clients")
RULE_INT(Range, CriticalDamage, 80, "The packet range in which critical hit messages are sent")
RULE_INT(Range, MobCloseScanDistance, 600, "Close scan distance")
RULE_INT(Range, MaxDistanceToClickDoors, 100, "Max distance that a client can click a door from (Client says 'You can't reach that' at roughly 25-50 for most doors)")
RULE_CATEGORY_END()
RULE_CATEGORY(Bots)
@@ -623,6 +626,7 @@ RULE_BOOL(Chat, EnableVoiceMacros, true, "Enable voice macros")
RULE_BOOL(Chat, EnableMailKeyIPVerification, true, "Setting whether the authenticity of the client should be verified via its IP address when accessing the InGame mailbox")
RULE_BOOL(Chat, EnableAntiSpam, true, "Enable anti-spam system for chat")
RULE_BOOL(Chat, SuppressCommandErrors, false, "Do not suppress command errors by default")
RULE_BOOL(Chat, ChannelsIgnoreNameFilter, false, "Ignore name filtering when creating new chat channels")
RULE_INT(Chat, MaxPermanentPlayerChannels, 0, "Maximum number of permanent chat channels a player can make. Default 0.")
RULE_INT(Chat, MinStatusToBypassAntiSpam, 100, "Minimum status to bypass the anti-spam system")
RULE_INT(Chat, MinimumMessagesPerInterval, 4, "Minimum number of chat messages allowed per interval. The karma value is added to this value")
@@ -744,6 +748,7 @@ RULE_BOOL(Inventory, DeleteTransformationMold, true, "False if you want mold to
RULE_BOOL(Inventory, AllowAnyWeaponTransformation, false, "Weapons can use any weapon transformation")
RULE_BOOL(Inventory, TransformSummonedBags, false, "Transforms summoned bags into disenchanted ones instead of deleting")
RULE_BOOL(Inventory, AllowMultipleOfSameAugment, false, "Allows multiple of the same augment to be placed in an item via #augmentitem or MQ2, set to true to allow")
RULE_INT(Inventory, AlternateAugmentationSealer, 53, "Allows RoF+ clients to augment items from a special container type")
RULE_CATEGORY_END()
RULE_CATEGORY(Client)
+20
View File
@@ -763,3 +763,23 @@ std::string Strings::Random(size_t length)
std::generate_n(str.begin(), length, randchar);
return str;
}
// a wrapper for stoi which will return a fallback if the string
// fails to cast to a number
int Strings::ToInt(const std::string &s, int fallback)
{
return Strings::IsNumber(s) ? std::stoi(s) : fallback;
}
std::string Strings::RemoveNumbers(std::string s)
{
int current = 0;
for (int i = 0; i < s.length(); i++) {
if (!isdigit(s[i])) {
s[current] = s[i];
current++;
}
}
return s.substr(0, current);
}
+2
View File
@@ -86,7 +86,9 @@ class Strings {
public:
static bool Contains(std::vector<std::string> container, std::string element);
static bool Contains(const std::string& subject, const std::string& search);
static int ToInt(const std::string &s, int fallback = 0);
static bool IsNumber(const std::string &s);
static std::string RemoveNumbers(std::string s);
static bool IsFloat(const std::string &s);
static const std::string ToLower(std::string s);
static const std::string ToUpper(std::string s);
+2 -2
View File
@@ -25,7 +25,7 @@
// Build variables
// these get injected during the build pipeline
#define CURRENT_VERSION "22.2.0-dev" // always append -dev to the current version for custom-builds
#define CURRENT_VERSION "22.3.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,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9218
#define CURRENT_BINARY_DATABASE_VERSION 9219
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9037
#endif
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "eqemu-server",
"version": "22.2.0",
"version": "22.3.0",
"repository": {
"type": "git",
"url": "https://github.com/EQEmu/Server.git"
+1 -1
View File
@@ -78,7 +78,7 @@ ChatChannel *ChatChannelList::CreateChannel(
{
uint8 max_perm_player_channels = RuleI(Chat, MaxPermanentPlayerChannels);
if (!database.CheckChannelNameFilter(name)) {
if (!RuleB(Chat, ChannelsIgnoreNameFilter) && !database.CheckChannelNameFilter(name)) {
if (!(owner == SYSTEM_OWNER)) {
return nullptr;
}
+4 -2
View File
@@ -224,8 +224,10 @@ bool UCSDatabase::GetVariable(const char *varname, char *varvalue, uint16 varval
bool UCSDatabase::LoadChatChannels()
{
LoadFilteredNamesFromDB();
{
if (!RuleB(Chat, ChannelsIgnoreNameFilter)) {
LoadFilteredNamesFromDB();
}
LoadReservedNamesFromDB();
LogInfo("Loading chat channels from the database");
+2 -2
View File
@@ -27,5 +27,5 @@ zip -j eqemu-server-linux-x64.zip ./build/bin/*
ls -lsh | grep zip
sudo apt-get update && sudo apt-get install -y rclone
rclone config create remote ftp env_auth true > /dev/null
rclone copy eqemu-server-linux-x64.zip remote:
rclone ls remote:
rclone copy eqemu-server-linux-x64.zip remote: 2>&1
rclone ls remote: 2>&1
+1 -1
View File
@@ -1,6 +1,6 @@
module should-release
go 1.19
go 1.18
require (
github.com/google/go-github/v41 v41.0.0
@@ -10,6 +10,7 @@ import (
"log"
"net/http"
"os"
"os/exec"
"path/filepath"
"strings"
)
@@ -59,6 +60,29 @@ func main() {
}
}
out, err := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD").Output()
if err != nil {
log.Fatal(err)
}
currentBranch := strings.TrimSpace(string(out))
if currentBranch != "master" {
fmt.Printf("Not on master, no need to release\n")
fmt.Printf("Exiting code 78 to halt pipeline steps gracefully\n")
os.Exit(78)
}
if len(os.Getenv("RCLONE_FTP_PASS")) == 0 {
fmt.Printf("Missing RCLONE_FTP_PASS no need to deploy\n")
fmt.Printf("Exiting code 78 to halt pipeline steps gracefully\n")
os.Exit(78)
}
if len(os.Getenv("GH_RELEASE_GITHUB_API_TOKEN")) == 0 {
fmt.Printf("Missing GH_RELEASE_GITHUB_API_TOKEN no need to deploy\n")
fmt.Printf("Exiting code 78 to halt pipeline steps gracefully\n")
os.Exit(78)
}
if len(packageJsonFile) == 0 {
fmt.Printf("Could not find package.json\n")
os.Exit(1)
Binary file not shown.
+2 -2
View File
@@ -37,8 +37,8 @@ try
dir *.zip
rclone config create remote ftp env_auth true
rclone copy eqemu-server-windows-x64.zip remote:
rclone ls remote:
rclone copy eqemu-server-windows-x64.zip remote: 2>&1
rclone ls remote: 2>&1
}
catch
{
+19
View File
@@ -1199,6 +1199,25 @@ sub get_mysql_path
}
}
}
if ($path eq "") {
my @files;
my $start_dir = trim(`echo %programfiles%`);
find(
sub {
if ($#files > 0) {
return;
}
push @files, $File::Find::name unless $File::Find::name!~/mysql.exe/i;
},
$start_dir
);
for my $file (@files) {
if ($file=~/mysql.exe/i) {
$path = $file;
last;
}
}
}
}
if ($OS eq "Linux") {
$path = `which mysql`;
+1
View File
@@ -472,6 +472,7 @@
9216|2023_01_15_merc_data.sql|SHOW TABLES LIKE 'mercs'|empty|
9217|2023_01_15_chatchannel_reserved_names.sql|SHOW TABLES LIKE 'chatchannel_reserved_names'|empty|
9218|2023_01_24_item_recast.sql|show columns from character_item_recast like '%recast_type%'|contains|smallint
9219|2023_01_29_merchant_status_requirements.sql|SHOW COLUMNS FROM merchantlist LIKE 'min_status'|empty|
# Upgrade conditions:
# This won't be needed after this system is implemented, but it is used database that are not
@@ -0,0 +1,3 @@
ALTER TABLE `merchantlist`
ADD COLUMN `min_status` tinyint(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `level_required`,
ADD COLUMN `max_status` tinyint(3) UNSIGNED NOT NULL DEFAULT 255 AFTER `min_status`;
+5 -4
View File
@@ -1,5 +1,6 @@
#include "../../common/version.h"
#include "../../common/json/json.h"
#include "../../common/rulesys.h"
void WorldserverCLI::DatabaseVersion(int argc, char **argv, argh::parser &cmd, std::string &description)
{
@@ -9,13 +10,13 @@ void WorldserverCLI::DatabaseVersion(int argc, char **argv, argh::parser &cmd, s
return;
}
Json::Value database_version;
Json::Value v;
database_version["database_version"] = CURRENT_BINARY_DATABASE_VERSION;
database_version["bots_database_version"] = CURRENT_BINARY_BOTS_DATABASE_VERSION;
v["database_version"] = CURRENT_BINARY_DATABASE_VERSION;
v["bots_database_version"] = RuleB(Bots, Enabled) ? CURRENT_BINARY_BOTS_DATABASE_VERSION : 0;
std::stringstream payload;
payload << database_version;
payload << v;
std::cout << payload.str() << std::endl;
}
+5 -5
View File
@@ -290,16 +290,16 @@ bool WorldBoot::DatabaseLoadRoutines(int argc, char **argv)
}
}
if (!ignore_db) {
LogInfo("Checking Database Conversions");
database.CheckDatabaseConversions();
}
// logging system init
auto logging = LogSys.SetDatabase(&database)
->SetLogPath(path.GetLogPath())
->LoadLogDatabaseSettings();
if (!ignore_db) {
LogInfo("Checking Database Conversions");
database.CheckDatabaseConversions();
}
if (RuleB(Logging, WorldGMSayLogging)) {
logging->SetGMSayHandler(&WorldBoot::GMSayHookCallBackProcessWorld);
}
+107 -15
View File
@@ -871,16 +871,16 @@ int Mob::ACSum(bool skip_caps)
int ac = 0; // this should be base AC whenever shrouds come around
ac += itembonuses.AC; // items + food + tribute
int shield_ac = 0;
if (HasShieldEquiped() && IsClient()) {
auto client = CastToClient();
auto inst = client->GetInv().GetItem(EQ::invslot::slotSecondary);
if (HasShieldEquiped() && (IsClient() || IsBot())) {
auto inst = (IsClient()) ? GetInv().GetItem(EQ::invslot::slotSecondary) : CastToBot()->GetBotItem(EQ::invslot::slotSecondary);
if (inst) {
if (inst->GetItemRecommendedLevel(true) <= GetLevel())
if (inst->GetItemRecommendedLevel(true) <= GetLevel()) {
shield_ac = inst->GetItemArmorClass(true);
else
shield_ac = client->CalcRecommendedLevelBonus(GetLevel(), inst->GetItemRecommendedLevel(true), inst->GetItemArmorClass(true));
} else {
shield_ac = CalcRecommendedLevelBonus(GetLevel(), inst->GetItemRecommendedLevel(true), inst->GetItemArmorClass(true));
}
}
shield_ac += client->GetHeroicSTR() / 10;
shield_ac += GetHeroicSTR() / 10;
}
// EQ math
ac = (ac * 4) / 3;
@@ -3820,6 +3820,98 @@ void Mob::CommonDamage(Mob* attacker, int64 &damage, const uint16 spell_id, cons
//final damage has been determined.
SetHP(int64(GetHP() - damage));
const auto has_bot_given_event = parse->BotHasQuestSub(EVENT_DAMAGE_GIVEN);
const auto has_bot_taken_event = parse->BotHasQuestSub(EVENT_DAMAGE_TAKEN);
const auto has_npc_given_event = (
(
IsNPC() &&
parse->HasQuestSub(CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_GIVEN)
) ||
(
attacker->IsNPC() &&
parse->HasQuestSub(attacker->CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_GIVEN)
)
);
const auto has_npc_taken_event = (
(
IsNPC() &&
parse->HasQuestSub(CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_TAKEN)
) ||
(
attacker->IsNPC() &&
parse->HasQuestSub(attacker->CastToNPC()->GetNPCTypeID(), EVENT_DAMAGE_TAKEN)
)
);
const auto has_player_given_event = parse->PlayerHasQuestSub(EVENT_DAMAGE_GIVEN);
const auto has_player_taken_event = parse->PlayerHasQuestSub(EVENT_DAMAGE_TAKEN);
const auto has_given_event = (
has_bot_given_event ||
has_npc_given_event ||
has_player_given_event
);
const auto has_taken_event = (
has_bot_taken_event ||
has_npc_taken_event ||
has_player_taken_event
);
std::vector<std::any> args;
if (has_taken_event) {
const auto export_string = fmt::format(
"{} {} {} {} {} {} {} {} {}",
attacker ? attacker->GetID() : 0,
damage,
spell_id,
static_cast<int>(skill_used),
FromDamageShield ? 1 : 0,
avoidable ? 1 : 0,
buffslot,
iBuffTic ? 1 : 0,
static_cast<int>(special)
);
if (IsBot() && has_bot_taken_event) {
parse->EventBot(EVENT_DAMAGE_TAKEN, CastToBot(), attacker ? attacker : nullptr, export_string, 0);
} else if (IsClient() && has_player_taken_event) {
args.push_back(attacker ? attacker : nullptr);
parse->EventPlayer(EVENT_DAMAGE_TAKEN, CastToClient(), export_string, 0, &args);
} else if (IsNPC() && has_npc_taken_event) {
parse->EventNPC(EVENT_DAMAGE_TAKEN, CastToNPC(), attacker ? attacker : nullptr, export_string, 0);
}
}
if (has_given_event && attacker) {
const auto export_string = fmt::format(
"{} {} {} {} {} {} {} {} {}",
GetID(),
damage,
spell_id,
static_cast<int>(skill_used),
FromDamageShield ? 1 : 0,
avoidable ? 1 : 0,
buffslot,
iBuffTic ? 1 : 0,
static_cast<int>(special)
);
if (attacker->IsBot() && has_bot_given_event) {
parse->EventBot(EVENT_DAMAGE_GIVEN, attacker->CastToBot(), this, export_string, 0);
} else if (attacker->IsClient() && has_player_given_event) {
args.push_back(this);
parse->EventPlayer(EVENT_DAMAGE_GIVEN, attacker->CastToClient(), export_string, 0, &args);
} else if (attacker->IsNPC() && has_npc_given_event) {
parse->EventNPC(EVENT_DAMAGE_GIVEN, attacker->CastToNPC(), this, export_string, 0);
}
}
if (HasDied()) {
bool IsSaved = false;
@@ -5701,16 +5793,16 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
TryCriticalHit(defender, hit, opts);
hit.damage_done += hit.min_damage;
if (IsClient()) {
if (IsClient() || IsBot()) {
int extra = 0;
switch (hit.skill) {
case EQ::skills::SkillThrowing:
case EQ::skills::SkillArchery:
extra = CastToClient()->GetHeroicDEX() / 10;
break;
default:
extra = CastToClient()->GetHeroicSTR() / 10;
break;
case EQ::skills::SkillThrowing:
case EQ::skills::SkillArchery:
extra = GetHeroicDEX() / 10;
break;
default:
extra = GetHeroicSTR() / 10;
break;
}
hit.damage_done += extra;
}
+1 -1
View File
@@ -128,7 +128,7 @@ void Client::CalcBonuses()
consume_food_timer.SetTimer(timer);
}
int Client::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat)
int Mob::CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat)
{
if( (reclevel > 0) && (level < reclevel) )
{
+6
View File
@@ -376,6 +376,11 @@ public:
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) override
{ return Mob::Attack(other, Hand, FromRiposte, IsStrikethrough, IsFromSpell, opts); }
[[nodiscard]] int GetMaxBuffSlots() const override { return EQ::spells::LONG_BUFFS; }
[[nodiscard]] int GetMaxSongSlots() const override { return EQ::spells::SHORT_BUFFS; }
[[nodiscard]] int GetMaxDiscSlots() const override { return EQ::spells::DISC_BUFFS; }
[[nodiscard]] int GetMaxTotalSlots() const override { return EQ::spells::TOTAL_BUFFS; }
bool GetBotOwnerDataBuckets();
bool GetBotDataBuckets();
bool CheckDataBucket(std::string bucket_name, std::string bucket_value, uint8 bucket_comparison);
@@ -467,6 +472,7 @@ public:
bool IsBotArcher() { return m_bot_archery_setting; }
bool IsBotCharmer() { return _botCharmer; }
bool IsBot() const override { return true; }
bool IsOfClientBotMerc() const override { return true; }
bool GetRangerAutoWeaponSelect() { return _rangerAutoWeaponSelect; }
BotRoleType GetBotRole() { return _botRole; }
EQ::constants::StanceType GetBotStance() { return _botStance; }
+1 -1
View File
@@ -5754,7 +5754,7 @@ void bot_subcommand_bot_dye_armor(Client *c, const Seperator *sep)
return;
}
if (helper_is_help_or_usage(sep->arg[1])) {
if (helper_is_help_or_usage(sep->arg[1]) || !sep->arg[1] || (sep->arg[1] && !Strings::IsNumber(sep->arg[1]))) {
c->Message(
Chat::White,
fmt::format(
+96
View File
@@ -10498,6 +10498,94 @@ void Client::ResetItemCooldown(uint32 item_id)
}
}
void Client::SetItemCooldown(uint32 item_id, bool use_saved_timer, uint32 in_seconds)
{
EQ::ItemInstance *item = nullptr;
const EQ::ItemData* item_d = database.GetItem(item_id);
if (!item_d) {
return;
}
int recast_type = item_d->RecastType;
auto timestamps = database.GetItemRecastTimestamps(CharacterID());
uint32 total_time = 0;
uint32 current_time = static_cast<uint32>(std::time(nullptr));
uint32 final_time = 0;
const auto timer_type = item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM ? item_d->RecastType : item_id;
const int timer_id = recast_type != RECAST_TYPE_UNLINKED_ITEM ? (pTimerItemStart + recast_type) : (pTimerNegativeItemReuse * item_id);
if (use_saved_timer) {
if (item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM) {
total_time = timestamps.count(item_d->RecastType) ? timestamps.at(item_d->RecastType) : 0;
} else {
total_time = timestamps.count(item_id) ? timestamps.at(item_id) : 0;
}
} else {
total_time = current_time + in_seconds;
}
if (total_time > current_time) {
final_time = total_time - current_time;
}
static const int16 slots[][2] = {
{ EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END },
{ EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END },
{ EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END},
{ EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END },
{ EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END },
{ EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END },
{ EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END },
};
const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]);
for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) {
for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) {
item = GetInv().GetItem(slot_id);
if (item) {
item_d = item->GetItem();
if (item_d && item->GetID() == item_id || (item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM && item_d->RecastType == recast_type)) {
item->SetRecastTimestamp(total_time);
SendItemPacket(slot_id, item, ItemPacketCharmUpdate);
}
}
}
}
//Start timers and update in database only when timer is changed
if (!use_saved_timer) {
GetPTimers().Clear(&database, timer_id);
GetPTimers().Start((timer_id), in_seconds);
database.UpdateItemRecast(
CharacterID(),
timer_type,
GetPTimers().Get(timer_id)->GetReadyTimestamp()
);
}
SendItemRecastTimer(recast_type, final_time, true);
}
uint32 Client::GetItemCooldown(uint32 item_id)
{
const EQ::ItemData* item_d = database.GetItem(item_id);
if (!item_d) {
return 0;
}
int recast_type = item_d->RecastType;
auto timestamps = database.GetItemRecastTimestamps(CharacterID());
const auto timer_type = recast_type != RECAST_TYPE_UNLINKED_ITEM ? recast_type : item_id;
uint32 total_time = 0;
uint32 current_time = static_cast<uint32>(std::time(nullptr));
uint32 final_time = 0;
total_time = timestamps.count(timer_type) ? timestamps.at(timer_type) : 0;
if (total_time > current_time) {
final_time = total_time - current_time;
}
return final_time;
}
void Client::RemoveItem(uint32 item_id, uint32 quantity)
{
EQ::ItemInstance *item = nullptr;
@@ -11872,3 +11960,11 @@ void Client::SendPath(Mob* target)
SendPathPacket(points);
}
void Client::UseAugmentContainer(int container_slot) {
auto in_augment = new AugmentItem_Struct[sizeof(AugmentItem_Struct)];
in_augment->container_slot = container_slot;
in_augment->augment_slot = -1;
Object::HandleAugmentation(this, in_augment, nullptr);
safe_delete_array(in_augment);
}
+5 -1
View File
@@ -278,6 +278,7 @@ public:
bool KeyRingCheck(uint32 item_id);
void KeyRingList();
virtual bool IsClient() const { return true; }
bool IsOfClientBotMerc() const override { return true; }
void CompleteConnect();
bool TryStacking(EQ::ItemInstance* item, uint8 type = ItemPacketTrade, bool try_worn = true, bool try_cursor = true);
void SendTraderPacket(Client* trader, uint32 Unknown72 = 51);
@@ -952,6 +953,7 @@ public:
void MemorizeSpell(uint32 slot, uint32 spellid, uint32 scribing, uint32 reduction = 0);
// Item methods
void UseAugmentContainer(int container_slot);
void EVENT_ITEM_ScriptStopReturn();
uint32 NukeItem(uint32 itemnum, uint8 where_to_check =
(invWhereWorn | invWherePersonal | invWhereBank | invWhereSharedBank | invWhereTrading | invWhereCursor));
@@ -967,6 +969,8 @@ public:
void DeleteItemInInventory(int16 slot_id, int16 quantity = 0, bool client_update = false, bool update_db = true);
int CountItem(uint32 item_id);
void ResetItemCooldown(uint32 item_id);
void SetItemCooldown(uint32 item_id, bool use_saved_timer = false, uint32 in_seconds = 1);
uint32 GetItemCooldown(uint32 item_id);
void RemoveItem(uint32 item_id, uint32 quantity = 1);
bool SwapItem(MoveItem_Struct* move_in);
void SwapItemResync(MoveItem_Struct* move_slots);
@@ -1679,7 +1683,6 @@ protected:
void CalcItemBonuses(StatBonuses* newbon);
void AddItemBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool isAug = false, bool isTribute = false, int rec_override = 0, bool ammo_slot_item = false);
void AdditiveWornBonuses(const EQ::ItemInstance *inst, StatBonuses* newbon, bool isAug = false);
int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat);
void CalcEdibleBonuses(StatBonuses* newbon);
void ProcessItemCaps();
void MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message = true);
@@ -2081,6 +2084,7 @@ private:
bool m_bot_precombat;
bool CanTradeFVNoDropItem();
void SendMobPositions();
};
#endif
+3 -3
View File
@@ -1031,14 +1031,14 @@ int Client::CalcHaste()
h += spellbonuses.hastetype2 > 10 ? 10 : spellbonuses.hastetype2;
}
// 26+ no cap, 1-25 10
if (level > 25) { // 26+
if (level > 25 || RuleB(Character, IgnoreLevelBasedHasteCaps)) { // 26+
h += itembonuses.haste;
}
else { // 1-25
h += itembonuses.haste > 10 ? 10 : itembonuses.haste;
}
// 60+ 100, 51-59 85, 1-50 level+25
if (level > 59) { // 60+
if (level > 59 || RuleB(Character, IgnoreLevelBasedHasteCaps)) { // 60+
cap = RuleI(Character, HasteCap);
}
else if (level > 50) { // 51-59
@@ -1052,7 +1052,7 @@ int Client::CalcHaste()
h = cap;
}
// 51+ 25 (despite there being higher spells...), 1-50 10
if (level > 50) { // 51+
if (level > 50 || RuleB(Character, IgnoreLevelBasedHasteCaps)) { // 51+
cap = RuleI(Character, Hastev3Cap);
if (spellbonuses.hastetype3 > cap) {
h += cap;
+135 -17
View File
@@ -778,6 +778,12 @@ void Client::CompleteConnect()
parse->EventPlayer(EVENT_ENTER_ZONE, this, "", 0);
// the way that the client deals with positions during the initial spawn struct
// is subtly different from how it deals with getting a position update
// if a mob is slightly in the wall or slightly clipping a floor they will be
// sent to a succor point
SendMobPositions();
SetLastPositionBeforeBulkUpdate(GetPosition());
/* This sub event is for if a player logs in for the first time since entering world. */
@@ -4168,8 +4174,26 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
{
if (GetLevel() >= item->Click.Level2)
{
EQ::ItemInstance* p_inst = (EQ::ItemInstance*)inst;
int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot);
auto* p_inst = (EQ::ItemInstance*) inst;
int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem(
EVENT_ITEM_CLICK_CAST,
this,
p_inst,
nullptr,
"",
castspell->inventoryslot
);
}
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
std::vector<std::any> args;
args.emplace_back(p_inst);
i = parse->EventPlayer(EVENT_ITEM_CLICK_CAST_CLIENT, this, std::to_string(castspell->inventoryslot), 0, &args);
}
if (i == 0) {
CastSpell(item->Click.Effect, castspell->target_id, slot, item->CastTime, 0, 0, castspell->inventoryslot);
}
@@ -4187,8 +4211,26 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app)
}
else
{
EQ::ItemInstance* p_inst = (EQ::ItemInstance*)inst;
int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", castspell->inventoryslot);
auto* p_inst = (EQ::ItemInstance*) inst;
int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem(
EVENT_ITEM_CLICK_CAST,
this,
p_inst,
nullptr,
"",
castspell->inventoryslot
);
}
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
std::vector<std::any> args;
args.emplace_back(p_inst);
i = parse->EventPlayer(EVENT_ITEM_CLICK_CAST_CLIENT, this, std::to_string(castspell->inventoryslot), 0, &args);
}
if (i == 0) {
CastSpell(item->Click.Effect, castspell->target_id, slot, item->CastTime, 0, 0, castspell->inventoryslot);
@@ -4343,27 +4385,46 @@ void Client::Handle_OP_ClickDoor(const EQApplicationPacket *app)
return;
}
// set door selected
if (IsDevToolsEnabled()) {
float distance = DistanceNoZ(GetPosition(), currentdoor->GetPosition());
LogDoors(
"Door [{}] client handle, client distance from door [{:.2f}]",
currentdoor->GetDoorID(),
distance
);
bool within_distance = distance < RuleI(Range, MaxDistanceToClickDoors);
// distance gate this because some doors are client controlled and the client
// will spam door click even across the zone to force a door back into desired state
if (IsDevToolsEnabled() && within_distance) {
SetDoorToolEntityId(currentdoor->GetEntityID());
DoorManipulation::CommandHeader(this);
Message(
Chat::White,
fmt::format(
"Door ({}) [{}]",
currentdoor->GetEntityID(),
currentdoor->GetDoorID(),
Saylink::Silent("#door edit")
).c_str()
);
}
std::string export_string = fmt::format("{}", cd->doorid);
std::vector<std::any> args;
args.push_back(currentdoor);
if (parse->EventPlayer(EVENT_CLICK_DOOR, this, export_string, 0, &args) == 0)
{
// don't spam scripts with client controlled doors if not within distance
if (within_distance) {
std::string export_string = fmt::format("{}", cd->doorid);
std::vector<std::any> args;
args.push_back(currentdoor);
if (parse->EventPlayer(EVENT_CLICK_DOOR, this, export_string, 0, &args) == 0) {
currentdoor->HandleClick(this, 0);
}
}
else {
// we let this pass because client controlled doors require this to force the linked doors
// back into state
currentdoor->HandleClick(this, 0);
}
}
void Client::Handle_OP_ClickObject(const EQApplicationPacket *app)
@@ -8836,9 +8897,18 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
if (m_inv.SupportsClickCasting(slot_id) || ((item->ItemType == EQ::item::ItemTypePotion || item->PotionBelt) && m_inv.SupportsPotionBeltCasting(slot_id))) // sanity check
{
EQ::ItemInstance* p_inst = (EQ::ItemInstance*)inst;
auto* p_inst = (EQ::ItemInstance*) inst;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK)) {
parse->EventItem(EVENT_ITEM_CLICK, this, p_inst, nullptr, "", slot_id);
}
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CLIENT)) {
std::vector<std::any> args;
args.emplace_back(p_inst);
parse->EventPlayer(EVENT_ITEM_CLICK_CLIENT, this, std::to_string(slot_id), 0, &args);
}
parse->EventItem(EVENT_ITEM_CLICK, this, p_inst, nullptr, "", slot_id);
inst = m_inv[slot_id];
if (!inst)
{
@@ -8928,18 +8998,37 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
if (item->RecastDelay > 0)
{
if (item->RecastType != RECAST_TYPE_UNLINKED_ITEM && !GetPTimers().Expired(&database, (pTimerItemStart + item->RecastType), false)) {
SendItemRecastTimer(item->RecastType); //Problem: When you loot corpse, recast display is not present. This causes it to display again. Could not get to display when sending from looting.
SetItemCooldown(item->ID, true);
SendSpellBarEnable(item->Click.Effect);
LogSpells("Casting of [{}] canceled: item spell reuse timer not expired", spell_id);
return;
} else if (item->RecastType == RECAST_TYPE_UNLINKED_ITEM && !GetPTimers().Expired(&database, (pTimerNegativeItemReuse * item->ID), false)) {
SetItemCooldown(item->ID, true);
SendSpellBarEnable(item->Click.Effect);
LogSpells("Casting of [{}] canceled: item spell reuse timer not expired", spell_id);
return;
}
}
int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, p_inst, nullptr, "", slot_id);
int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem(
EVENT_ITEM_CLICK_CAST,
this,
p_inst,
nullptr,
"",
slot_id
);
}
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
std::vector<std::any> args;
args.emplace_back(p_inst);
i = parse->EventPlayer(EVENT_ITEM_CLICK_CAST_CLIENT, this, std::to_string(slot_id), 0, &args);
}
inst = m_inv[slot_id];
if (!inst)
{
@@ -8988,7 +9077,25 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app)
}
}
int i = parse->EventItem(EVENT_ITEM_CLICK_CAST, this, clickaug, nullptr, "", slot_id);
int i = 0;
if (parse->ItemHasQuestSub(p_inst, EVENT_ITEM_CLICK_CAST)) {
i = parse->EventItem(
EVENT_ITEM_CLICK_CAST,
this,
clickaug,
nullptr,
"",
slot_id
);
}
if (parse->PlayerHasQuestSub(EVENT_ITEM_CLICK_CAST_CLIENT)) {
std::vector<std::any> args;
args.emplace_back(clickaug);
i = parse->EventPlayer(EVENT_ITEM_CLICK_CAST_CLIENT, this, std::to_string(slot_id), 0, &args);
}
inst = m_inv[slot_id];
if (!inst)
{
@@ -15648,3 +15755,14 @@ bool Client::CanTradeFVNoDropItem()
return false;
}
void Client::SendMobPositions()
{
auto p = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
auto *s = (PlayerPositionUpdateServer_Struct *) p->pBuffer;
for (auto &m: entity_list.GetMobList()) {
m.second->MakeSpawnUpdate(s);
QueuePacket(p, false);
}
safe_delete(p);
}
+3
View File
@@ -872,6 +872,9 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
continue;
}
if (!EQ::ValueWithin(Admin(), static_cast<int16>(ml.min_status), static_cast<int16>(ml.max_status))) {
continue;
}
int32 faction_id = npc ? npc->GetPrimaryFaction() : 0;
int32 faction_level = (
+5 -1
View File
@@ -121,6 +121,7 @@ Doors::~Doors()
bool Doors::Process()
{
if (m_close_timer.Enabled() && m_close_timer.Check() && IsDoorOpen()) {
LogDoorsDetail("door open and timer triggered door_id [{}] open_type [{}]", GetDoorID(), m_open_type);
if (m_open_type == 40 || GetTriggerType() == 1) {
auto outapp = new EQApplicationPacket(OP_MoveDoor, sizeof(MoveDoor_Struct));
MoveDoor_Struct *md = (MoveDoor_Struct *) outapp->pBuffer;
@@ -627,11 +628,13 @@ void Doors::ForceOpen(Mob *sender, bool alt_mode)
if (!alt_mode) { // original function
if (!m_is_open) {
if (!m_disable_timer) {
LogDoorsDetail("door_id [{}] starting timer", md->doorid);
m_close_timer.Start();
}
m_is_open = true;
}
else {
LogDoorsDetail("door_id [{}] disable timer", md->doorid);
m_close_timer.Disable();
if (!m_disable_timer) {
m_is_open = false;
@@ -640,6 +643,7 @@ void Doors::ForceOpen(Mob *sender, bool alt_mode)
}
else { // alternative function
if (!m_disable_timer) {
LogDoorsDetail("door_id [{}] alt starting timer", md->doorid);
m_close_timer.Start();
}
m_is_open = true;
@@ -840,7 +844,7 @@ void Doors::CreateDatabaseEntry()
return;
}
auto e = DoorsRepository::NewEntity();
e.id = GetDoorDBID();
+33
View File
@@ -171,6 +171,10 @@ const char *QuestEventSubroutines[_LargestEventID] = {
"EVENT_AUGMENT_REMOVE_CLIENT",
"EVENT_EQUIP_ITEM_BOT",
"EVENT_UNEQUIP_ITEM_BOT",
"EVENT_DAMAGE_GIVEN",
"EVENT_DAMAGE_TAKEN",
"EVENT_ITEM_CLICK_CLIENT",
"EVENT_ITEM_CLICK_CAST_CLIENT",
// Add new events before these or Lua crashes
"EVENT_SPELL_EFFECT_BOT",
"EVENT_SPELL_EFFECT_BUFF_TIC_BOT"
@@ -1711,6 +1715,20 @@ void PerlembParser::ExportEventVariables(
break;
}
case EVENT_ITEM_CLICK_CAST_CLIENT:
case EVENT_ITEM_CLICK_CLIENT: {
ExportVar(package_name.c_str(), "slot_id", data);
if (extra_pointers && extra_pointers->size() == 1) {
auto* item = std::any_cast<EQ::ItemInstance*>(extra_pointers->at(0));
if (item) {
ExportVar(package_name.c_str(), "item_id", item->GetID());
ExportVar(package_name.c_str(), "item_name", item->GetItem()->Name);
ExportVar(package_name.c_str(), "spell_id", item->GetItem()->Click.Effect);
}
}
break;
}
case EVENT_GROUP_CHANGE: {
if (mob && mob->IsClient()) {
ExportVar(package_name.c_str(), "grouped", mob->IsGrouped());
@@ -2031,6 +2049,21 @@ void PerlembParser::ExportEventVariables(
break;
}
case EVENT_DAMAGE_GIVEN:
case EVENT_DAMAGE_TAKEN:{
Seperator sep(data);
ExportVar(package_name.c_str(), "entity_id", sep.arg[0]);
ExportVar(package_name.c_str(), "damage", sep.arg[1]);
ExportVar(package_name.c_str(), "spell_id", sep.arg[2]);
ExportVar(package_name.c_str(), "skill_id", sep.arg[3]);
ExportVar(package_name.c_str(), "is_damage_shield", sep.arg[4]);
ExportVar(package_name.c_str(), "is_avoidable", sep.arg[5]);
ExportVar(package_name.c_str(), "buff_slot", sep.arg[6]);
ExportVar(package_name.c_str(), "is_buff_tic", sep.arg[7]);
ExportVar(package_name.c_str(), "special_attack", sep.arg[8]);
break;
}
default: {
break;
}
+7 -1
View File
@@ -3981,6 +3981,11 @@ int8 Perl__does_augment_fit(EQ::ItemInstance* inst, uint32 augment_id)
return quest_manager.DoesAugmentFit(inst, augment_id);
}
int8 Perl__does_augment_fit_slot(EQ::ItemInstance* inst, uint32 augment_id, uint8 augment_slot)
{
return quest_manager.DoesAugmentFit(inst, augment_id, augment_slot);
}
void perl_register_quest()
{
perl::interpreter perl(PERL_GET_THX);
@@ -4326,7 +4331,8 @@ void perl_register_quest()
package.add("doanim", (void(*)(int, int, bool))&Perl__doanim);
package.add("doanim", (void(*)(int, int, bool, int))&Perl__doanim);
package.add("do_augment_slots_match", &Perl__do_augment_slots_match);
package.add("does_augment_fit", &Perl__does_augment_fit);
package.add("does_augment_fit", (int8(*)(EQ::ItemInstance*, uint32))&Perl__does_augment_fit);
package.add("does_augment_fit_slot", (int8(*)(EQ::ItemInstance*, uint32, uint8))&Perl__does_augment_fit_slot);
package.add("echo", &Perl__echo);
package.add("emote", &Perl__emote);
package.add("enable_proximity_say", &Perl__enable_proximity_say);
+5 -1
View File
@@ -718,6 +718,8 @@ void EntityList::AddNPC(NPC *npc, bool send_spawn_packet, bool dont_queue)
}
}
npc->SendPositionToClients();
entity_list.ScanCloseMobs(npc->close_mobs, npc, true);
npc->DispatchZoneControllerEvent(EVENT_SPAWN_ZONE, npc, "", 0, nullptr);
@@ -844,8 +846,10 @@ void EntityList::CheckSpawnQueue()
NPC *pnpc = it->second;
pnpc->SendArmorAppearance();
pnpc->SetAppearance(pnpc->GetGuardPointAnim(), false);
if (!pnpc->IsTargetable())
if (!pnpc->IsTargetable()) {
pnpc->SendTargetable(false);
}
pnpc->SendPositionToClients();
}
safe_delete(outapp);
iterator.RemoveCurrent();
+15 -14
View File
@@ -67,20 +67,21 @@ public:
Entity();
virtual ~Entity();
virtual bool IsClient() const { return false; }
virtual bool IsNPC() const { return false; }
virtual bool IsMob() const { return false; }
virtual bool IsMerc() const { return false; }
virtual bool IsCorpse() const { return false; }
virtual bool IsPlayerCorpse() const { return false; }
virtual bool IsNPCCorpse() const { return false; }
virtual bool IsObject() const { return false; }
virtual bool IsDoor() const { return false; }
virtual bool IsTrap() const { return false; }
virtual bool IsBeacon() const { return false; }
virtual bool IsEncounter() const { return false; }
virtual bool IsBot() const { return false; }
virtual bool IsAura() const { return false; }
virtual bool IsClient() const { return false; }
virtual bool IsNPC() const { return false; }
virtual bool IsMob() const { return false; }
virtual bool IsMerc() const { return false; }
virtual bool IsCorpse() const { return false; }
virtual bool IsPlayerCorpse() const { return false; }
virtual bool IsNPCCorpse() const { return false; }
virtual bool IsObject() const { return false; }
virtual bool IsDoor() const { return false; }
virtual bool IsTrap() const { return false; }
virtual bool IsBeacon() const { return false; }
virtual bool IsEncounter() const { return false; }
virtual bool IsBot() const { return false; }
virtual bool IsAura() const { return false; }
virtual bool IsOfClientBotMerc() const { return false; }
virtual bool Process() { return false; }
virtual bool Save() { return true; }
+4
View File
@@ -116,6 +116,10 @@ typedef enum {
EVENT_AUGMENT_REMOVE_CLIENT,
EVENT_EQUIP_ITEM_BOT,
EVENT_UNEQUIP_ITEM_BOT,
EVENT_DAMAGE_GIVEN,
EVENT_DAMAGE_TAKEN,
EVENT_ITEM_CLICK_CLIENT,
EVENT_ITEM_CLICK_CAST_CLIENT,
// Add new events before these or Lua crashes
EVENT_SPELL_EFFECT_BOT,
EVENT_SPELL_EFFECT_BUFF_TIC_BOT,
+11 -37
View File
@@ -34,12 +34,10 @@ void command_list(Client *c, const Seperator *sep)
std::string search_string;
if (sep->arg[2]) {
search_string = sep->arg[2];
search_string = Strings::ToLower(sep->arg[2]);
}
/**
* NPC
*/
// NPC
if (search_type.find("npcs") != std::string::npos) {
auto &entity_list_search = entity_list.GetMobList();
@@ -51,11 +49,7 @@ void command_list(Client *c, const Seperator *sep)
entity_count++;
std::string entity_name = entity->GetName();
/**
* Filter by name
*/
std::string entity_name = Strings::ToLower(entity->GetName());
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
continue;
}
@@ -81,9 +75,7 @@ void command_list(Client *c, const Seperator *sep)
}
}
/**
* Client
*/
// Client
if (search_type.find("players") != std::string::npos) {
auto &entity_list_search = entity_list.GetClientList();
@@ -92,7 +84,7 @@ void command_list(Client *c, const Seperator *sep)
entity_count++;
std::string entity_name = entity->GetName();
std::string entity_name = Strings::ToLower(entity->GetName());
/**
* Filter by name
@@ -122,9 +114,7 @@ void command_list(Client *c, const Seperator *sep)
}
}
/**
* Corpse
*/
// Corpse
if (search_type.find("corpses") != std::string::npos) {
auto &entity_list_search = entity_list.GetCorpseList();
@@ -133,11 +123,7 @@ void command_list(Client *c, const Seperator *sep)
entity_count++;
std::string entity_name = entity->GetName();
/**
* Filter by name
*/
std::string entity_name = Strings::ToLower(entity->GetName());
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
continue;
}
@@ -163,9 +149,7 @@ void command_list(Client *c, const Seperator *sep)
}
}
/**
* Doors
*/
// Doors
if (search_type.find("doors") != std::string::npos) {
auto &entity_list_search = entity_list.GetDoorsList();
@@ -174,11 +158,7 @@ void command_list(Client *c, const Seperator *sep)
entity_count++;
std::string entity_name = entity->GetDoorName();
/**
* Filter by name
*/
std::string entity_name = Strings::ToLower(entity->GetDoorName());
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
continue;
}
@@ -205,9 +185,7 @@ void command_list(Client *c, const Seperator *sep)
}
}
/**
* Objects
*/
// Objects
if (search_type.find("objects") != std::string::npos) {
auto &entity_list_search = entity_list.GetObjectList();
@@ -216,11 +194,7 @@ void command_list(Client *c, const Seperator *sep)
entity_count++;
std::string entity_name = entity->GetModelName();
/**
* Filter by name
*/
std::string entity_name = Strings::ToLower(entity->GetModelName());
if (search_string.length() > 0 && entity_name.find(search_string) == std::string::npos) {
continue;
}
+9
View File
@@ -29,6 +29,7 @@ void command_loc(Client *c, const Seperator *sep)
glm::vec3 hit;
auto best_z = zone->zonemap->FindBestZ(tarloc, &hit);
auto fixed_z = c->GetFixedZ(c->GetPosition());
if (best_z != BEST_Z_INVALID) {
c->Message(
@@ -39,6 +40,14 @@ void command_loc(Client *c, const Seperator *sep)
best_z
).c_str()
);
c->Message(
Chat::White,
fmt::format(
"Fixed Z for {} | {:.2f}",
c->GetTargetDescription(target, TargetDescriptionType::UCSelf),
fixed_z
).c_str()
);
} else {
c->Message(Chat::White, "Could not find Best Z.");
}
+2 -2
View File
@@ -536,14 +536,14 @@ void command_npcedit(Client *c, const Seperator *sep)
} else if (!strcasecmp(sep->arg[1], "weapon")) {
if (sep->IsNumber(2)) {
auto primary_model = std::stoul(sep->arg[2]);
uint32_t secondary_model = sep->IsNumber(3) ? std::stoul(sep->arg[3]) : 0;
uint32_t secondary_model = sep->arg[3] && sep->IsNumber(3) ? std::stoul(sep->arg[3]) : 0;
n.d_melee_texture1 = primary_model;
n.d_melee_texture2 = secondary_model;
d = fmt::format(
"{} will have Model {} set to their Primary and Model {} set to their Secondary on repop.",
npc_id_string,
Strings::Commify(sep->arg[2]),
sep->IsNumber(3) ? Strings::Commify(sep->arg[3]) : 0
sep->arg[3] && sep->IsNumber(3) ? Strings::Commify(sep->arg[3]) : 0
);
} else {
c->Message(
-4
View File
@@ -22,10 +22,6 @@ void command_weather(Client *c, const Seperator *sep)
weather_message = "Raindrops begin to fall from the sky.";
new_weather = EQ::constants::WeatherTypes::Raining;
new_intensity = 0x01; // This is how it's done in Fear, and you can see a decent distance with it at this value
} else {
c->Message(Chat::White, "Usage: #weather [0|1|2] - [Off|Rain|Snow]");
c->Message(Chat::White, "Usage: #weather 3 [Type] [Intensity] - Manually set weather type and intensity");
return;
}
zone->zone_weather = new_weather;
+63
View File
@@ -8,6 +8,7 @@
#include "lua_iteminst.h"
#include "lua_mob.h"
#include "lua_group.h"
#include "lua_item.h"
void Lua_Bot::AddBotItem(uint16 slot_id, uint32 item_id) {
Lua_Safe_Call_Void();
@@ -393,6 +394,66 @@ void Lua_Bot::SendSpellAnim(uint16 target_id, uint16 spell_id)
self->SendSpellAnim(target_id, spell_id);
}
luabind::object Lua_Bot::GetAugmentIDsBySlotID(lua_State* L, int16 slot_id) const {
auto lua_table = luabind::newtable(L);
if (d_) {
auto self = reinterpret_cast<NativeType*>(d_);
auto augments = self->GetInv().GetAugmentIDsBySlotID(slot_id);
int index = 1;
for (auto item_id : augments) {
lua_table[index] = item_id;
index++;
}
}
return lua_table;
}
void Lua_Bot::AddItem(const luabind::object& item_table) {
Lua_Safe_Call_Void();
if (luabind::type(item_table) != LUA_TTABLE) {
return;
}
auto item_id = luabind::object_cast<uint32>(item_table["item_id"]);
int16 charges = luabind::object_cast<uint32>(item_table["charges"]);
uint32 augment_one = luabind::type(item_table["augment_one"]) != LUA_TNIL ? luabind::object_cast<uint32>(item_table["augment_one"]) : 0;
uint32 augment_two = luabind::type(item_table["augment_two"]) != LUA_TNIL ? luabind::object_cast<uint32>(item_table["augment_two"]) : 0;
uint32 augment_three = luabind::type(item_table["augment_three"]) != LUA_TNIL ? luabind::object_cast<uint32>(item_table["augment_three"]) : 0;
uint32 augment_four = luabind::type(item_table["augment_four"]) != LUA_TNIL ? luabind::object_cast<uint32>(item_table["augment_four"]) : 0;
uint32 augment_five = luabind::type(item_table["augment_five"]) != LUA_TNIL ? luabind::object_cast<uint32>(item_table["augment_five"]) : 0;
uint32 augment_six = luabind::type(item_table["augment_six"]) != LUA_TNIL ? luabind::object_cast<uint32>(item_table["augment_six"]) : 0;
bool attuned = luabind::type(item_table["attuned"]) != LUA_TNIL ? luabind::object_cast<bool>(item_table["attuned"]) : false;
uint16 slot_id = luabind::type(item_table["slot_id"]) != LUA_TNIL ? luabind::object_cast<uint16>(item_table["slot_id"]) : EQ::invslot::slotCursor;
if (slot_id <= EQ::invslot::slotAmmo) {
self->AddBotItem(
slot_id,
item_id,
charges,
attuned,
augment_one,
augment_two,
augment_three,
augment_four,
augment_five,
augment_six
);
} else {
self->GetOwner()->CastToClient()->SummonItem(
item_id,
charges,
augment_one,
augment_two,
augment_three,
augment_four,
augment_five,
augment_six,
attuned,
slot_id
);
}
}
luabind::scope lua_register_bot() {
return luabind::class_<Lua_Bot, Lua_Mob>("Bot")
.def(luabind::constructor<>())
@@ -405,6 +466,7 @@ luabind::scope lua_register_bot() {
.def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32,uint32))&Lua_Bot::AddBotItem)
.def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32,uint32,uint32))&Lua_Bot::AddBotItem)
.def("AddBotItem", (void(Lua_Bot::*)(uint16,uint32,int16,bool,uint32,uint32,uint32,uint32,uint32,uint32))&Lua_Bot::AddBotItem)
.def("AddItem", (void(Lua_Bot::*)(luabind::adl::object))&Lua_Bot::AddItem)
.def("ApplySpell", (void(Lua_Bot::*)(int))&Lua_Bot::ApplySpell)
.def("ApplySpell", (void(Lua_Bot::*)(int,int))&Lua_Bot::ApplySpell)
.def("ApplySpell", (void(Lua_Bot::*)(int,int,bool))&Lua_Bot::ApplySpell)
@@ -424,6 +486,7 @@ luabind::scope lua_register_bot() {
.def("Fling", (void(Lua_Bot::*)(float,float,float,float,bool,bool))&Lua_Bot::Fling)
.def("GetAugmentAt", (Lua_ItemInst(Lua_Bot::*)(int16,uint8))&Lua_Bot::GetAugmentAt)
.def("GetAugmentIDAt", (int(Lua_Bot::*)(int16,uint8))&Lua_Bot::GetAugmentIDAt)
.def("GetAugmentIDsBySlotID", (luabind::object(Lua_Bot::*)(lua_State* L,int16))&Lua_Bot::GetAugmentIDsBySlotID)
.def("GetBaseAGI", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseAGI)
.def("GetBaseCHA", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseCHA)
.def("GetBaseDEX", (int(Lua_Bot::*)(void))&Lua_Bot::GetBaseDEX)
+3
View File
@@ -8,6 +8,7 @@ class Bot;
class Lua_Bot;
class Lua_Mob;
class Lua_Group;
class Lua_Inventory;
namespace luabind {
struct scope;
@@ -36,6 +37,7 @@ public:
void AddBotItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four);
void AddBotItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four, uint32 augment_five);
void AddBotItem(uint16 slot_id, uint32 item_id, int16 charges, bool attuned, uint32 augment_one, uint32 augment_two, uint32 augment_three, uint32 augment_four, uint32 augment_five, uint32 augment_six);
void AddItem(const luabind::object& item_table);
uint32 CountBotItem(uint32 item_id);
Lua_ItemInst GetBotItem(uint16 slot_id);
uint32 GetBotItemIDBySlot(uint16 slot_id);
@@ -59,6 +61,7 @@ public:
void Camp(bool save_to_database);
Lua_ItemInst GetAugmentAt(int16 slot_id, uint8 augment_index);
int GetAugmentIDAt(int16 slot_id, uint8 augment_index);
luabind::object GetAugmentIDsBySlotID(lua_State* L, int16 slot_id) const;
Lua_ItemInst GetItemAt(int16 slot_id);
int GetItemIDAt(int16 slot_id);
void SendSpellAnim(uint16 target_id, uint16 spell_id);
+21
View File
@@ -3020,6 +3020,24 @@ void Lua_Client::ResetItemCooldown(uint32 item_id)
self->ResetItemCooldown(item_id);
}
void Lua_Client::SetItemCooldown(uint32 item_id, uint32 in_time)
{
Lua_Safe_Call_Void();
self->SetItemCooldown(item_id, false, in_time);
}
uint32 Lua_Client::GetItemCooldown(uint32 item_id)
{
Lua_Safe_Call_Int();
return self->GetItemCooldown(item_id);
}
void Lua_Client::UseAugmentContainer(int container_slot)
{
Lua_Safe_Call_Void();
self->UseAugmentContainer(container_slot);
}
luabind::scope lua_register_client() {
return luabind::class_<Lua_Client, Lua_Mob>("Client")
.def(luabind::constructor<>())
@@ -3210,6 +3228,7 @@ luabind::scope lua_register_client() {
.def("GetInventory", (Lua_Inventory(Lua_Client::*)(void))&Lua_Client::GetInventory)
.def("GetInvulnerableEnvironmentDamage", (bool(Lua_Client::*)(void))&Lua_Client::GetInvulnerableEnvironmentDamage)
.def("GetItemIDAt", (int(Lua_Client::*)(int))&Lua_Client::GetItemIDAt)
.def("GetItemCooldown", (uint32(Lua_Client::*)(uint32))&Lua_Client::GetItemCooldown)
.def("GetLDoNLosses", (int(Lua_Client::*)(void))&Lua_Client::GetLDoNLosses)
.def("GetLDoNLossesTheme", (int(Lua_Client::*)(int))&Lua_Client::GetLDoNLossesTheme)
.def("GetLDoNPointsTheme", (int(Lua_Client::*)(int))&Lua_Client::GetLDoNPointsTheme)
@@ -3454,6 +3473,7 @@ luabind::scope lua_register_client() {
.def("SetHunger", (void(Lua_Client::*)(int))&Lua_Client::SetHunger)
.def("SetInvulnerableEnvironmentDamage", (void(Lua_Client::*)(int))&Lua_Client::SetInvulnerableEnvironmentDamage)
.def("SetIPExemption", (void(Lua_Client::*)(int))&Lua_Client::SetIPExemption)
.def("SetItemCooldown", (void(Lua_Client::*)(uint32,uint32))&Lua_Client::SetItemCooldown)
.def("SetLanguageSkill", (void(Lua_Client::*)(int,int))&Lua_Client::SetLanguageSkill)
.def("SetMaterial", (void(Lua_Client::*)(int,uint32))&Lua_Client::SetMaterial)
.def("SetPEQZoneFlag", (void(Lua_Client::*)(uint32))&Lua_Client::SetPEQZoneFlag)
@@ -3539,6 +3559,7 @@ luabind::scope lua_register_client() {
.def("UpdateLDoNPoints", (void(Lua_Client::*)(uint32,int))&Lua_Client::UpdateLDoNPoints)
.def("UpdateTaskActivity", (void(Lua_Client::*)(int,int,int))&Lua_Client::UpdateTaskActivity)
.def("UseDiscipline", (bool(Lua_Client::*)(int,int))&Lua_Client::UseDiscipline)
.def("UseAugmentContainer", (void(Lua_Client::*)(int))&Lua_Client::UseAugmentContainer)
.def("WorldKick", (void(Lua_Client::*)(void))&Lua_Client::WorldKick);
}
+3
View File
@@ -463,6 +463,9 @@ public:
bool CanEnterZone(std::string zone_short_name, int16 instance_version);
void SendPath(Lua_Mob target);
void ResetItemCooldown(uint32 item_id);
void SetItemCooldown(uint32 item_id, uint32 in_time);
uint32 GetItemCooldown(uint32 item_id);
void UseAugmentContainer(int container_slot);
void ApplySpell(int spell_id);
void ApplySpell(int spell_id, int duration);
+12 -2
View File
@@ -3700,6 +3700,11 @@ int8 lua_does_augment_fit(Lua_ItemInst inst, uint32 augment_id)
return quest_manager.DoesAugmentFit(inst, augment_id);
}
int8 lua_does_augment_fit_slot(Lua_ItemInst inst, uint32 augment_id, uint8 augment_slot)
{
return quest_manager.DoesAugmentFit(inst, augment_id, augment_slot);
}
#define LuaCreateNPCParse(name, c_type, default_value) do { \
cur = table[#name]; \
if(luabind::type(cur) != LUA_TNIL) { \
@@ -4217,7 +4222,8 @@ luabind::scope lua_register_general() {
luabind::def("do_anim", (void(*)(int,int,bool))&lua_do_anim),
luabind::def("do_anim", (void(*)(int,int,bool,int))&lua_do_anim),
luabind::def("do_augment_slots_match", &lua_do_augment_slots_match),
luabind::def("does_augment_fit", &lua_does_augment_fit),
luabind::def("does_augment_fit", (int8(*)(Lua_ItemInst, uint32))&lua_does_augment_fit),
luabind::def("does_augment_fit_slot", (int8(*)(Lua_ItemInst, uint32, uint8))&lua_does_augment_fit_slot),
/*
Cross Zone
*/
@@ -4627,7 +4633,11 @@ luabind::scope lua_register_events() {
luabind::value("augment_insert_client", static_cast<int>(EVENT_AUGMENT_INSERT_CLIENT)),
luabind::value("augment_remove_client", static_cast<int>(EVENT_AUGMENT_REMOVE_CLIENT)),
luabind::value("equip_item_bot", static_cast<int>(EVENT_EQUIP_ITEM_BOT)),
luabind::value("unequip_item_bot", static_cast<int>(EVENT_UNEQUIP_ITEM_BOT))
luabind::value("unequip_item_bot", static_cast<int>(EVENT_UNEQUIP_ITEM_BOT)),
luabind::value("damage_given", static_cast<int>(EVENT_DAMAGE_GIVEN)),
luabind::value("damage_taken", static_cast<int>(EVENT_DAMAGE_TAKEN)),
luabind::value("item_click_client", static_cast<int>(EVENT_ITEM_CLICK_CLIENT)),
luabind::value("item_click_cast_client", static_cast<int>(EVENT_ITEM_CLICK_CAST_CLIENT))
)];
}
+85 -6
View File
@@ -573,12 +573,6 @@ void Lua_NPC::RecalculateSkills()
self->RecalculateSkills();
}
void Lua_NPC::ScaleNPC(uint8 npc_level)
{
Lua_Safe_Call_Void();
self->ScaleNPC(npc_level);
}
bool Lua_NPC::IsRaidTarget()
{
Lua_Safe_Call_Bool();
@@ -701,6 +695,78 @@ void Lua_NPC::SetKeepsSoldItems(bool keeps_sold_items) {
self->SetKeepsSoldItems(keeps_sold_items);
}
bool Lua_NPC::IsLDoNTrapped() {
Lua_Safe_Call_Bool();
return self->IsLDoNTrapped();
}
void Lua_NPC::SetLDoNTrapped(bool is_trapped) {
Lua_Safe_Call_Void();
self->SetLDoNTrapped(is_trapped);
}
uint8 Lua_NPC::GetLDoNTrapType() {
Lua_Safe_Call_Int();
return self->GetLDoNTrapType();
}
void Lua_NPC::SetLDoNTrapType(uint8 trap_type) {
Lua_Safe_Call_Void();
self->SetLDoNTrapType(trap_type);
}
uint16 Lua_NPC::GetLDoNTrapSpellID() {
Lua_Safe_Call_Int();
return self->GetLDoNTrapSpellID();
}
void Lua_NPC::SetLDoNTrapSpellID(uint16 spell_id) {
Lua_Safe_Call_Void();
self->SetLDoNTrapSpellID(spell_id);
}
bool Lua_NPC::IsLDoNLocked() {
Lua_Safe_Call_Bool();
return self->IsLDoNLocked();
}
void Lua_NPC::SetLDoNLocked(bool is_locked) {
Lua_Safe_Call_Void();
self->SetLDoNLocked(is_locked);
}
uint16 Lua_NPC::GetLDoNLockedSkill() {
Lua_Safe_Call_Int();
return self->GetLDoNLockedSkill();
}
void Lua_NPC::SetLDoNLockedSkill(uint16 skill_value) {
Lua_Safe_Call_Void();
self->SetLDoNLockedSkill(skill_value);
}
bool Lua_NPC::IsLDoNTrapDetected() {
Lua_Safe_Call_Bool();
return self->IsLDoNTrapDetected();
}
void Lua_NPC::SetLDoNTrapDetected(bool is_detected) {
Lua_Safe_Call_Void();
self->SetLDoNTrapDetected(is_detected);
}
void Lua_NPC::ScaleNPC(uint8 npc_level)
{
Lua_Safe_Call_Void();
self->ScaleNPC(npc_level);
}
void Lua_NPC::ScaleNPC(uint8 npc_level, bool override_special_abilities)
{
Lua_Safe_Call_Void();
self->ScaleNPC(npc_level, true, override_special_abilities);
}
luabind::scope lua_register_npc() {
return luabind::class_<Lua_NPC, Lua_Mob>("NPC")
.def(luabind::constructor<>())
@@ -753,6 +819,9 @@ luabind::scope lua_register_npc() {
.def("GetMaxDamage", (uint32(Lua_NPC::*)(int))&Lua_NPC::GetMaxDamage)
.def("GetMaxWp", (int(Lua_NPC::*)(void))&Lua_NPC::GetMaxWp)
.def("GetMinDMG", (uint32(Lua_NPC::*)(void))&Lua_NPC::GetMinDMG)
.def("GetLDoNLockedSkill", (uint16(Lua_NPC::*)(void))&Lua_NPC::GetLDoNLockedSkill)
.def("GetLDoNTrapType", (uint8(Lua_NPC::*)(void))&Lua_NPC::GetLDoNTrapType)
.def("GetLDoNTrapSpellID", (uint16(Lua_NPC::*)(void))&Lua_NPC::GetLDoNTrapSpellID)
.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)
@@ -784,6 +853,9 @@ luabind::scope lua_register_npc() {
.def("HasItem", (bool(Lua_NPC::*)(uint32))&Lua_NPC::HasItem)
.def("IsAnimal", (bool(Lua_NPC::*)(void))&Lua_NPC::IsAnimal)
.def("IsGuarding", (bool(Lua_NPC::*)(void))&Lua_NPC::IsGuarding)
.def("IsLDoNLocked", (bool(Lua_NPC::*)(void))&Lua_NPC::IsLDoNLocked)
.def("IsLDoNTrapped", (bool(Lua_NPC::*)(void))&Lua_NPC::IsLDoNTrapped)
.def("IsLDoNTrapDetected", (bool(Lua_NPC::*)(void))&Lua_NPC::IsLDoNTrapDetected)
.def("IsOnHatelist", (bool(Lua_NPC::*)(Lua_Mob))&Lua_NPC::IsOnHatelist)
.def("IsRaidTarget", (bool(Lua_NPC::*)(void))&Lua_NPC::IsRaidTarget)
.def("IsRareSpawn", (bool(Lua_NPC::*)(void))&Lua_NPC::IsRareSpawn)
@@ -808,6 +880,7 @@ luabind::scope lua_register_npc() {
.def("SaveGuardSpot", (void(Lua_NPC::*)(bool))&Lua_NPC::SaveGuardSpot)
.def("SaveGuardSpot", (void(Lua_NPC::*)(float,float,float,float))&Lua_NPC::SaveGuardSpot)
.def("ScaleNPC", (void(Lua_NPC::*)(uint8))&Lua_NPC::ScaleNPC)
.def("ScaleNPC", (void(Lua_NPC::*)(uint8,bool))&Lua_NPC::ScaleNPC)
.def("SendPayload", (void(Lua_NPC::*)(int))&Lua_NPC::SendPayload)
.def("SendPayload", (void(Lua_NPC::*)(int,std::string))&Lua_NPC::SendPayload)
.def("SetCopper", (void(Lua_NPC::*)(uint32))&Lua_NPC::SetCopper)
@@ -817,6 +890,12 @@ luabind::scope lua_register_npc() {
.def("SetGold", (void(Lua_NPC::*)(uint32))&Lua_NPC::SetGold)
.def("SetGrid", (void(Lua_NPC::*)(int))&Lua_NPC::SetGrid)
.def("SetKeepsSoldItems", (void(Lua_NPC::*)(bool))&Lua_NPC::SetKeepsSoldItems)
.def("SetLDoNLocked", (void(Lua_NPC::*)(bool))&Lua_NPC::SetLDoNLocked)
.def("SetLDoNLockedSkill", (void(Lua_NPC::*)(uint16))&Lua_NPC::SetLDoNLockedSkill)
.def("SetLDoNTrapped", (void(Lua_NPC::*)(bool))&Lua_NPC::SetLDoNTrapped)
.def("SetLDoNTrapDetected", (void(Lua_NPC::*)(bool))&Lua_NPC::SetLDoNTrapDetected)
.def("SetLDoNTrapSpellID", (void(Lua_NPC::*)(uint16))&Lua_NPC::SetLDoNTrapSpellID)
.def("SetLDoNTrapType", (void(Lua_NPC::*)(uint8))&Lua_NPC::SetLDoNTrapType)
.def("SetNPCFactionID", (void(Lua_NPC::*)(int))&Lua_NPC::SetNPCFactionID)
.def("SetPetSpellID", (void(Lua_NPC::*)(int))&Lua_NPC::SetPetSpellID)
.def("SetPlatinum", (void(Lua_NPC::*)(uint32))&Lua_NPC::SetPlatinum)
+14 -1
View File
@@ -141,7 +141,6 @@ public:
void SetSimpleRoamBox(float box_size, float move_distance, int move_delay);
void RecalculateSkills();
void ReloadSpells();
void ScaleNPC(uint8 npc_level);
bool IsRaidTarget();
bool IsRareSpawn();
void ChangeLastName(std::string last_name);
@@ -161,6 +160,20 @@ public:
void SendPayload(int payload_id, std::string payload_value);
bool GetKeepsSoldItems();
void SetKeepsSoldItems(bool keeps_sold_items);
bool IsLDoNTrapped();
void SetLDoNTrapped(bool is_trapped);
uint8 GetLDoNTrapType();
void SetLDoNTrapType(uint8 trap_type);
uint16 GetLDoNTrapSpellID();
void SetLDoNTrapSpellID(uint16 spell_id);
bool IsLDoNLocked();
void SetLDoNLocked(bool is_locked);
uint16 GetLDoNLockedSkill();
void SetLDoNLockedSkill(uint16 skill_value);
bool IsLDoNTrapDetected();
void SetLDoNTrapDetected(bool is_detected);
void ScaleNPC(uint8 npc_level);
void ScaleNPC(uint8 npc_level, bool override_special_abilities);
};
#endif
+137 -124
View File
@@ -158,6 +158,10 @@ const char *LuaEvents[_LargestEventID] = {
"event_augment_remove_client",
"event_equip_item_bot",
"event_unequip_item_bot",
"event_damage_given",
"event_damage_taken",
"event_item_click_client",
"event_item_click_cast_client"
};
extern Zone *zone;
@@ -173,145 +177,154 @@ std::map<std::string, bool> lua_encounters_loaded;
std::map<std::string, Encounter *> lua_encounters;
LuaParser::LuaParser() {
for(int i = 0; i < _LargestEventID; ++i) {
NPCArgumentDispatch[i] = handle_npc_null;
PlayerArgumentDispatch[i] = handle_player_null;
ItemArgumentDispatch[i] = handle_item_null;
SpellArgumentDispatch[i] = handle_spell_null;
for (int i = 0; i < _LargestEventID; ++i) {
NPCArgumentDispatch[i] = handle_npc_null;
PlayerArgumentDispatch[i] = handle_player_null;
ItemArgumentDispatch[i] = handle_item_null;
SpellArgumentDispatch[i] = handle_spell_null;
EncounterArgumentDispatch[i] = handle_encounter_null;
BotArgumentDispatch[i] = handle_bot_null;
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_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_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;
PlayerArgumentDispatch[EVENT_SAY] = handle_player_say;
PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage;
PlayerArgumentDispatch[EVENT_DEATH] = handle_player_death;
PlayerArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_player_death;
PlayerArgumentDispatch[EVENT_TIMER] = handle_player_timer;
PlayerArgumentDispatch[EVENT_DISCOVER_ITEM] = handle_player_discover_item;
PlayerArgumentDispatch[EVENT_FISH_SUCCESS] = handle_player_fish_forage_success;
PlayerArgumentDispatch[EVENT_FORAGE_SUCCESS] = handle_player_fish_forage_success;
PlayerArgumentDispatch[EVENT_CLICK_OBJECT] = handle_player_click_object;
PlayerArgumentDispatch[EVENT_CLICK_DOOR] = handle_player_click_door;
PlayerArgumentDispatch[EVENT_SIGNAL] = handle_player_signal;
PlayerArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_player_popup_response;
PlayerArgumentDispatch[EVENT_PLAYER_PICKUP] = handle_player_pick_up;
PlayerArgumentDispatch[EVENT_CAST] = handle_player_cast;
PlayerArgumentDispatch[EVENT_CAST_BEGIN] = handle_player_cast;
PlayerArgumentDispatch[EVENT_CAST_ON] = handle_player_cast;
PlayerArgumentDispatch[EVENT_TASK_FAIL] = handle_player_task_fail;
PlayerArgumentDispatch[EVENT_ZONE] = handle_player_zone;
PlayerArgumentDispatch[EVENT_DUEL_WIN] = handle_player_duel_win;
PlayerArgumentDispatch[EVENT_DUEL_LOSE] = handle_player_duel_loss;
PlayerArgumentDispatch[EVENT_LOOT] = handle_player_loot;
PlayerArgumentDispatch[EVENT_TASK_STAGE_COMPLETE] = handle_player_task_stage_complete;
PlayerArgumentDispatch[EVENT_TASK_COMPLETE] = handle_player_task_update;
PlayerArgumentDispatch[EVENT_TASK_UPDATE] = handle_player_task_update;
PlayerArgumentDispatch[EVENT_TASK_BEFORE_UPDATE] = handle_player_task_update;
PlayerArgumentDispatch[EVENT_COMMAND] = handle_player_command;
PlayerArgumentDispatch[EVENT_COMBINE_SUCCESS] = handle_player_combine;
PlayerArgumentDispatch[EVENT_COMBINE_FAILURE] = handle_player_combine;
PlayerArgumentDispatch[EVENT_FEIGN_DEATH] = handle_player_feign;
PlayerArgumentDispatch[EVENT_ENTER_AREA] = handle_player_area;
PlayerArgumentDispatch[EVENT_LEAVE_AREA] = handle_player_area;
PlayerArgumentDispatch[EVENT_RESPAWN] = handle_player_respawn;
PlayerArgumentDispatch[EVENT_UNHANDLED_OPCODE] = handle_player_packet;
PlayerArgumentDispatch[EVENT_USE_SKILL] = handle_player_use_skill;
PlayerArgumentDispatch[EVENT_TEST_BUFF] = handle_test_buff;
PlayerArgumentDispatch[EVENT_COMBINE_VALIDATE] = handle_player_combine_validate;
PlayerArgumentDispatch[EVENT_BOT_COMMAND] = handle_player_bot_command;
PlayerArgumentDispatch[EVENT_WARP] = handle_player_warp;
PlayerArgumentDispatch[EVENT_COMBINE] = handle_player_quest_combine;
PlayerArgumentDispatch[EVENT_CONSIDER] = handle_player_consider;
PlayerArgumentDispatch[EVENT_CONSIDER_CORPSE] = handle_player_consider_corpse;
PlayerArgumentDispatch[EVENT_EQUIP_ITEM_CLIENT] = handle_player_equip_item;
PlayerArgumentDispatch[EVENT_UNEQUIP_ITEM_CLIENT] = handle_player_equip_item;
PlayerArgumentDispatch[EVENT_SKILL_UP] = handle_player_skill_up;
PlayerArgumentDispatch[EVENT_LANGUAGE_SKILL_UP] = handle_player_skill_up;
PlayerArgumentDispatch[EVENT_ALT_CURRENCY_MERCHANT_BUY] = handle_player_alt_currency_merchant;
PlayerArgumentDispatch[EVENT_SAY] = handle_player_say;
PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage;
PlayerArgumentDispatch[EVENT_DEATH] = handle_player_death;
PlayerArgumentDispatch[EVENT_DEATH_COMPLETE] = handle_player_death;
PlayerArgumentDispatch[EVENT_TIMER] = handle_player_timer;
PlayerArgumentDispatch[EVENT_DISCOVER_ITEM] = handle_player_discover_item;
PlayerArgumentDispatch[EVENT_FISH_SUCCESS] = handle_player_fish_forage_success;
PlayerArgumentDispatch[EVENT_FORAGE_SUCCESS] = handle_player_fish_forage_success;
PlayerArgumentDispatch[EVENT_CLICK_OBJECT] = handle_player_click_object;
PlayerArgumentDispatch[EVENT_CLICK_DOOR] = handle_player_click_door;
PlayerArgumentDispatch[EVENT_SIGNAL] = handle_player_signal;
PlayerArgumentDispatch[EVENT_POPUP_RESPONSE] = handle_player_popup_response;
PlayerArgumentDispatch[EVENT_PLAYER_PICKUP] = handle_player_pick_up;
PlayerArgumentDispatch[EVENT_CAST] = handle_player_cast;
PlayerArgumentDispatch[EVENT_CAST_BEGIN] = handle_player_cast;
PlayerArgumentDispatch[EVENT_CAST_ON] = handle_player_cast;
PlayerArgumentDispatch[EVENT_TASK_FAIL] = handle_player_task_fail;
PlayerArgumentDispatch[EVENT_ZONE] = handle_player_zone;
PlayerArgumentDispatch[EVENT_DUEL_WIN] = handle_player_duel_win;
PlayerArgumentDispatch[EVENT_DUEL_LOSE] = handle_player_duel_loss;
PlayerArgumentDispatch[EVENT_LOOT] = handle_player_loot;
PlayerArgumentDispatch[EVENT_TASK_STAGE_COMPLETE] = handle_player_task_stage_complete;
PlayerArgumentDispatch[EVENT_TASK_ACCEPTED] = handle_player_task_accepted;
PlayerArgumentDispatch[EVENT_TASK_COMPLETE] = handle_player_task_update;
PlayerArgumentDispatch[EVENT_TASK_UPDATE] = handle_player_task_update;
PlayerArgumentDispatch[EVENT_TASK_BEFORE_UPDATE] = handle_player_task_update;
PlayerArgumentDispatch[EVENT_COMMAND] = handle_player_command;
PlayerArgumentDispatch[EVENT_COMBINE_SUCCESS] = handle_player_combine;
PlayerArgumentDispatch[EVENT_COMBINE_FAILURE] = handle_player_combine;
PlayerArgumentDispatch[EVENT_FEIGN_DEATH] = handle_player_feign;
PlayerArgumentDispatch[EVENT_ENTER_AREA] = handle_player_area;
PlayerArgumentDispatch[EVENT_LEAVE_AREA] = handle_player_area;
PlayerArgumentDispatch[EVENT_RESPAWN] = handle_player_respawn;
PlayerArgumentDispatch[EVENT_UNHANDLED_OPCODE] = handle_player_packet;
PlayerArgumentDispatch[EVENT_USE_SKILL] = handle_player_use_skill;
PlayerArgumentDispatch[EVENT_TEST_BUFF] = handle_test_buff;
PlayerArgumentDispatch[EVENT_COMBINE_VALIDATE] = handle_player_combine_validate;
PlayerArgumentDispatch[EVENT_BOT_COMMAND] = handle_player_bot_command;
PlayerArgumentDispatch[EVENT_WARP] = handle_player_warp;
PlayerArgumentDispatch[EVENT_COMBINE] = handle_player_quest_combine;
PlayerArgumentDispatch[EVENT_CONSIDER] = handle_player_consider;
PlayerArgumentDispatch[EVENT_CONSIDER_CORPSE] = handle_player_consider_corpse;
PlayerArgumentDispatch[EVENT_EQUIP_ITEM_CLIENT] = handle_player_equip_item;
PlayerArgumentDispatch[EVENT_UNEQUIP_ITEM_CLIENT] = handle_player_equip_item;
PlayerArgumentDispatch[EVENT_SKILL_UP] = handle_player_skill_up;
PlayerArgumentDispatch[EVENT_LANGUAGE_SKILL_UP] = handle_player_skill_up;
PlayerArgumentDispatch[EVENT_ALT_CURRENCY_MERCHANT_BUY] = handle_player_alt_currency_merchant;
PlayerArgumentDispatch[EVENT_ALT_CURRENCY_MERCHANT_SELL] = handle_player_alt_currency_merchant;
PlayerArgumentDispatch[EVENT_MERCHANT_BUY] = handle_player_merchant;
PlayerArgumentDispatch[EVENT_MERCHANT_SELL] = handle_player_merchant;
PlayerArgumentDispatch[EVENT_INSPECT] = handle_player_inspect;
PlayerArgumentDispatch[EVENT_AA_BUY] = handle_player_aa_buy;
PlayerArgumentDispatch[EVENT_AA_GAIN] = handle_player_aa_gain;
PlayerArgumentDispatch[EVENT_PAYLOAD] = handle_player_payload;
PlayerArgumentDispatch[EVENT_LEVEL_UP] = handle_player_level_up;
PlayerArgumentDispatch[EVENT_LEVEL_DOWN] = handle_player_level_down;
PlayerArgumentDispatch[EVENT_GM_COMMAND] = handle_player_gm_command;
PlayerArgumentDispatch[EVENT_BOT_CREATE] = handle_player_bot_create;
PlayerArgumentDispatch[EVENT_AUGMENT_INSERT_CLIENT] = handle_player_augment_insert;
PlayerArgumentDispatch[EVENT_AUGMENT_REMOVE_CLIENT] = handle_player_augment_remove;
PlayerArgumentDispatch[EVENT_MERCHANT_BUY] = handle_player_merchant;
PlayerArgumentDispatch[EVENT_MERCHANT_SELL] = handle_player_merchant;
PlayerArgumentDispatch[EVENT_INSPECT] = handle_player_inspect;
PlayerArgumentDispatch[EVENT_AA_BUY] = handle_player_aa_buy;
PlayerArgumentDispatch[EVENT_AA_GAIN] = handle_player_aa_gain;
PlayerArgumentDispatch[EVENT_PAYLOAD] = handle_player_payload;
PlayerArgumentDispatch[EVENT_LEVEL_UP] = handle_player_level_up;
PlayerArgumentDispatch[EVENT_LEVEL_DOWN] = handle_player_level_down;
PlayerArgumentDispatch[EVENT_GM_COMMAND] = handle_player_gm_command;
PlayerArgumentDispatch[EVENT_BOT_CREATE] = handle_player_bot_create;
PlayerArgumentDispatch[EVENT_AUGMENT_INSERT_CLIENT] = handle_player_augment_insert;
PlayerArgumentDispatch[EVENT_AUGMENT_REMOVE_CLIENT] = handle_player_augment_remove;
PlayerArgumentDispatch[EVENT_DAMAGE_GIVEN] = handle_player_damage;
PlayerArgumentDispatch[EVENT_DAMAGE_TAKEN] = handle_player_damage;
PlayerArgumentDispatch[EVENT_ITEM_CLICK_CAST_CLIENT] = handle_player_item_click;
PlayerArgumentDispatch[EVENT_ITEM_CLICK_CLIENT] = handle_player_item_click;
ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click;
ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click;
ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click;
ItemArgumentDispatch[EVENT_TIMER] = handle_item_timer;
ItemArgumentDispatch[EVENT_WEAPON_PROC] = handle_item_proc;
ItemArgumentDispatch[EVENT_LOOT] = handle_item_loot;
ItemArgumentDispatch[EVENT_EQUIP_ITEM] = handle_item_equip;
ItemArgumentDispatch[EVENT_UNEQUIP_ITEM] = handle_item_equip;
ItemArgumentDispatch[EVENT_AUGMENT_ITEM] = handle_item_augment;
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] = handle_item_timer;
ItemArgumentDispatch[EVENT_WEAPON_PROC] = handle_item_proc;
ItemArgumentDispatch[EVENT_LOOT] = handle_item_loot;
ItemArgumentDispatch[EVENT_EQUIP_ITEM] = handle_item_equip;
ItemArgumentDispatch[EVENT_UNEQUIP_ITEM] = handle_item_equip;
ItemArgumentDispatch[EVENT_AUGMENT_ITEM] = handle_item_augment;
ItemArgumentDispatch[EVENT_UNAUGMENT_ITEM] = handle_item_augment;
ItemArgumentDispatch[EVENT_AUGMENT_INSERT] = handle_item_augment_insert;
ItemArgumentDispatch[EVENT_AUGMENT_REMOVE] = handle_item_augment_remove;
SpellArgumentDispatch[EVENT_SPELL_EFFECT_CLIENT] = handle_spell_event;
SpellArgumentDispatch[EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT] = handle_spell_event;
SpellArgumentDispatch[EVENT_SPELL_FADE] = handle_spell_event;
SpellArgumentDispatch[EVENT_SPELL_EFFECT_CLIENT] = handle_spell_event;
SpellArgumentDispatch[EVENT_SPELL_EFFECT_BUFF_TIC_CLIENT] = handle_spell_event;
SpellArgumentDispatch[EVENT_SPELL_FADE] = handle_spell_event;
SpellArgumentDispatch[EVENT_SPELL_EFFECT_TRANSLOCATE_COMPLETE] = handle_translocate_finish;
EncounterArgumentDispatch[EVENT_TIMER] = handle_encounter_timer;
EncounterArgumentDispatch[EVENT_ENCOUNTER_LOAD] = handle_encounter_load;
EncounterArgumentDispatch[EVENT_TIMER] = handle_encounter_timer;
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_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;
#endif
L = nullptr;
+253 -107
View File
@@ -120,12 +120,12 @@ void handle_npc_event_hp(
if(extra_data == 1) {
lua_pushinteger(L, -1);
lua_setfield(L, -2, "hp_event");
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "inc_hp_event");
}
else
{
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "hp_event");
lua_pushinteger(L, -1);
lua_setfield(L, -2, "inc_hp_event");
@@ -191,7 +191,7 @@ void handle_npc_task_accepted(
l_client_o.push(L);
lua_setfield(L, -2, "other");
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "task_id");
}
@@ -209,7 +209,7 @@ void handle_npc_popup(
l_mob_o.push(L);
lua_setfield(L, -2, "other");
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "popup_id");
}
@@ -227,7 +227,7 @@ void handle_npc_waypoint(
l_mob_o.push(L);
lua_setfield(L, -2, "other");
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data, -1));
lua_setfield(L, -2, "wp");
}
@@ -245,7 +245,7 @@ void handle_npc_hate(
l_mob_o.push(L);
lua_setfield(L, -2, "other");
lua_pushboolean(L, std::stoi(data) == 0 ? false : true);
lua_pushboolean(L, Strings::ToInt(data) == 0 ? false : true);
lua_setfield(L, -2, "joined");
}
@@ -259,7 +259,7 @@ void handle_npc_signal(
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "signal");
}
@@ -274,7 +274,7 @@ void handle_npc_payload(
) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "payload_id");
lua_pushstring(L, sep.argplus[1]);
@@ -309,13 +309,13 @@ void handle_npc_death(
lua_setfield(L, -2, "other");
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "killer_id");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "damage");
int spell_id = std::stoi(sep.arg[2]);
int spell_id = Strings::ToInt(sep.arg[2]);
if(IsValidSpell(spell_id)) {
Lua_Spell l_spell(&spells[spell_id]);
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
@@ -328,7 +328,7 @@ void handle_npc_death(
lua_setfield(L, -2, "spell");
}
lua_pushinteger(L, std::stoi(sep.arg[3]));
lua_pushinteger(L, Strings::ToInt(sep.arg[3]));
lua_setfield(L, -2, "skill_id");
if (extra_pointers && extra_pointers->size() >= 1)
@@ -357,7 +357,7 @@ void handle_npc_cast(
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
int spell_id = std::stoi(data);
int spell_id = Strings::ToInt(data);
if(IsValidSpell(spell_id)) {
Lua_Spell l_spell(&spells[spell_id]);
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
@@ -453,6 +453,50 @@ void handle_npc_despawn_zone(
lua_setfield(L, -2, "other");
}
void handle_npc_damage(
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_pushnumber(L, std::stoul(sep.arg[0]));
lua_setfield(L, -2, "entity_id");
lua_pushnumber(L, std::stoll(sep.arg[1]));
lua_setfield(L, -2, "damage");
lua_pushnumber(L, std::stoi(sep.arg[2]));
lua_setfield(L, -2, "spell_id");
lua_pushnumber(L, std::stoi(sep.arg[3]));
lua_setfield(L, -2, "skill_id");
lua_pushboolean(L, std::stoi(sep.arg[4]) == 0 ? false : true);
lua_setfield(L, -2, "is_damage_shield");
lua_pushboolean(L, std::stoi(sep.arg[5]) == 0 ? false : true);
lua_setfield(L, -2, "is_avoidable");
lua_pushnumber(L, std::stoi(sep.arg[6]));
lua_setfield(L, -2, "buff_slot");
lua_pushboolean(L, std::stoi(sep.arg[7]) == 0 ? false : true);
lua_setfield(L, -2, "is_buff_tic");
lua_pushnumber(L, std::stoi(sep.arg[8]));
lua_setfield(L, -2, "special_attack");
Lua_Mob l_mob(init);
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
l_mob_o.push(L);
lua_setfield(L, -2, "other");
}
// Player
void handle_player_say(
QuestInterface *parse,
@@ -478,13 +522,13 @@ void handle_player_environmental_damage(
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "env_damage");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "env_damage_type");
lua_pushinteger(L, std::stoi(sep.arg[2]));
lua_pushinteger(L, Strings::ToInt(sep.arg[2]));
lua_setfield(L, -2, "env_final_damage");
}
@@ -498,19 +542,19 @@ void handle_player_death(
) {
Seperator sep(data.c_str());
Mob *o = entity_list.GetMobID(std::stoi(sep.arg[0]));
Mob *o = entity_list.GetMobID(Strings::ToInt(sep.arg[0]));
Lua_Mob l_mob(o);
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
l_mob_o.push(L);
lua_setfield(L, -2, "other");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "killer_id");
lua_pushinteger(L, std::stoi(sep.arg[2]));
lua_pushinteger(L, Strings::ToInt(sep.arg[2]));
lua_setfield(L, -2, "damage");
int spell_id = std::stoi(sep.arg[3]);
int spell_id = Strings::ToInt(sep.arg[3]);
if(IsValidSpell(spell_id)) {
Lua_Spell l_spell(&spells[spell_id]);
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
@@ -523,7 +567,7 @@ void handle_player_death(
lua_setfield(L, -2, "spell");
}
lua_pushinteger(L, std::stoi(sep.arg[4]));
lua_pushinteger(L, Strings::ToInt(sep.arg[4]));
lua_setfield(L, -2, "skill");
}
@@ -611,7 +655,7 @@ void handle_player_signal(
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "signal");
}
@@ -625,7 +669,7 @@ void handle_player_payload(
) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "payload_id");
lua_pushstring(L, sep.argplus[1]);
@@ -640,7 +684,7 @@ void handle_player_popup_response(
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "popup_id");
}
@@ -668,7 +712,7 @@ void handle_player_cast(
) {
Seperator sep(data.c_str());
int spell_id = std::stoi(sep.arg[0]);
int spell_id = Strings::ToInt(sep.arg[0]);
if(IsValidSpell(spell_id)) {
Lua_Spell l_spell(&spells[spell_id]);
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
@@ -681,10 +725,10 @@ void handle_player_cast(
lua_setfield(L, -2, "spell");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "caster_id");
lua_pushinteger(L, std::stoi(sep.arg[2]));
lua_pushinteger(L, Strings::ToInt(sep.arg[2]));
lua_setfield(L, -2, "caster_level");
}
@@ -696,7 +740,7 @@ void handle_player_task_fail(
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "task_id");
}
@@ -710,22 +754,22 @@ void handle_player_zone(
) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "from_zone_id");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "from_instance_id");
lua_pushinteger(L, std::stoi(sep.arg[2]));
lua_pushinteger(L, Strings::ToInt(sep.arg[2]));
lua_setfield(L, -2, "from_instance_version");
lua_pushinteger(L, std::stoi(sep.arg[3]));
lua_pushinteger(L, Strings::ToInt(sep.arg[3]));
lua_setfield(L, -2, "zone_id");
lua_pushinteger(L, std::stoi(sep.arg[4]));
lua_pushinteger(L, Strings::ToInt(sep.arg[4]));
lua_setfield(L, -2, "instance_id");
lua_pushinteger(L, std::stoi(sep.arg[5]));
lua_pushinteger(L, Strings::ToInt(sep.arg[5]));
lua_setfield(L, -2, "instance_version");
}
@@ -785,13 +829,25 @@ void handle_player_task_stage_complete(
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "task_id");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "activity_id");
}
void handle_player_task_accepted(
QuestInterface* parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
) {
lua_pushinteger(L, std::stoi(data));
lua_setfield(L, -2, "task_id");
}
void handle_player_task_update(
QuestInterface *parse,
lua_State* L,
@@ -801,13 +857,13 @@ void handle_player_task_update(
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "count");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "activity_id");
lua_pushinteger(L, std::stoi(sep.arg[2]));
lua_pushinteger(L, Strings::ToInt(sep.arg[2]));
lua_setfield(L, -2, "task_id");
}
@@ -888,7 +944,7 @@ void handle_player_respawn(
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "option");
lua_pushboolean(L, extra_data == 1 ? true : false);
@@ -931,10 +987,10 @@ void handle_player_use_skill(
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "skill_id");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "skill_level");
}
@@ -966,10 +1022,10 @@ void handle_player_combine_validate(
int zone_id = -1;
int tradeskill_id = -1;
if (strcmp(sep.arg[0], "check_zone") == 0) {
zone_id = std::stoi(sep.arg[1]);
zone_id = Strings::ToInt(sep.arg[1]);
}
else if (strcmp(sep.arg[0], "check_tradeskill") == 0) {
tradeskill_id = std::stoi(sep.arg[1]);
tradeskill_id = Strings::ToInt(sep.arg[1]);
}
lua_pushinteger(L, zone_id);
@@ -1031,7 +1087,7 @@ void handle_player_quest_combine(
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "container_slot");
}
@@ -1043,7 +1099,7 @@ void handle_player_consider(
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "entity_id");
}
@@ -1055,7 +1111,7 @@ void handle_player_consider_corpse(
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "corpse_entity_id");
}
@@ -1082,16 +1138,16 @@ void handle_player_aa_buy(
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "aa_cost");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "aa_id");
lua_pushinteger(L, std::stoi(sep.arg[2]));
lua_pushinteger(L, Strings::ToInt(sep.arg[2]));
lua_setfield(L, -2, "aa_previous_id");
lua_pushinteger(L, std::stoi(sep.arg[3]));
lua_pushinteger(L, Strings::ToInt(sep.arg[3]));
lua_setfield(L, -2, "aa_next_id");
}
@@ -1103,7 +1159,7 @@ void handle_player_aa_gain(
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "aa_gained");
}
@@ -1155,19 +1211,92 @@ void handle_player_bot_create(
lua_pushstring(L, sep.arg[0]);
lua_setfield(L, -2, "bot_name");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "bot_id");
lua_pushinteger(L, std::stoi(sep.arg[2]));
lua_pushinteger(L, Strings::ToInt(sep.arg[2]));
lua_setfield(L, -2, "bot_race");
lua_pushinteger(L, std::stoi(sep.arg[3]));
lua_pushinteger(L, Strings::ToInt(sep.arg[3]));
lua_setfield(L, -2, "bot_class");
lua_pushinteger(L, std::stoi(sep.arg[4]));
lua_pushinteger(L, Strings::ToInt(sep.arg[4]));
lua_setfield(L, -2, "bot_gender");
}
void handle_player_damage(
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_pushnumber(L, std::stoul(sep.arg[0]));
lua_setfield(L, -2, "entity_id");
lua_pushnumber(L, std::stoll(sep.arg[1]));
lua_setfield(L, -2, "damage");
lua_pushnumber(L, std::stoi(sep.arg[2]));
lua_setfield(L, -2, "spell_id");
lua_pushnumber(L, std::stoi(sep.arg[3]));
lua_setfield(L, -2, "skill_id");
lua_pushboolean(L, std::stoi(sep.arg[4]) == 0 ? false : true);
lua_setfield(L, -2, "is_damage_shield");
lua_pushboolean(L, std::stoi(sep.arg[5]) == 0 ? false : true);
lua_setfield(L, -2, "is_avoidable");
lua_pushnumber(L, std::stoi(sep.arg[6]));
lua_setfield(L, -2, "buff_slot");
lua_pushboolean(L, std::stoi(sep.arg[7]) == 0 ? false : true);
lua_setfield(L, -2, "is_buff_tic");
lua_pushnumber(L, std::stoi(sep.arg[8]));
lua_setfield(L, -2, "special_attack");
if (extra_pointers && extra_pointers->size() >= 1) {
Lua_Mob l_mob(std::any_cast<Mob*>(extra_pointers->at(0)));
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
l_mob_o.push(L);
lua_setfield(L, -2, "other");
}
}
void handle_player_item_click(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushnumber(L, std::stoi(data));
lua_setfield(L, -2, "slot_id");
if (extra_pointers && extra_pointers->size() >= 1) {
lua_pushnumber(L, std::any_cast<EQ::ItemInstance*>(extra_pointers->at(0))->GetID());
lua_setfield(L, -2, "item_id");
lua_pushstring(L, std::any_cast<EQ::ItemInstance*>(extra_pointers->at(0))->GetItem()->Name);
lua_setfield(L, -2, "item_name");
lua_pushnumber(L, std::any_cast<EQ::ItemInstance*>(extra_pointers->at(0))->GetItem()->Click.Effect);
lua_setfield(L, -2, "spell_id");
Lua_ItemInst l_item(std::any_cast<EQ::ItemInstance*>(extra_pointers->at(0)));
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
l_item_o.push(L);
lua_setfield(L, -2, "item");
}
}
// Item
void handle_item_click(
QuestInterface *parse,
@@ -1366,16 +1495,16 @@ void handle_spell_event(
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "caster_id");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "tics_remaining");
lua_pushinteger(L, std::stoi(sep.arg[2]));
lua_pushinteger(L, Strings::ToInt(sep.arg[2]));
lua_setfield(L, -2, "caster_level");
lua_pushinteger(L, std::stoi(sep.arg[3]));
lua_pushinteger(L, Strings::ToInt(sep.arg[3]));
lua_setfield(L, -2, "buff_slot");
Lua_Spell l_spell(spell_id);
@@ -1424,10 +1553,10 @@ void handle_player_equip_item(
Seperator sep(data.c_str());
lua_pushnumber(L, std::stoi(sep.arg[0]));
lua_pushnumber(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "item_quantity");
lua_pushnumber(L, std::stoi(sep.arg[1]));
lua_pushnumber(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "slot_id");
Lua_ItemInst l_item(extra_data);
@@ -1515,16 +1644,16 @@ void handle_player_skill_up(
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "skill_id");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "skill_value");
lua_pushinteger(L, std::stoi(sep.arg[2]));
lua_pushinteger(L, Strings::ToInt(sep.arg[2]));
lua_setfield(L, -2, "skill_max");
lua_pushinteger(L, std::stoi(sep.arg[3]));
lua_pushinteger(L, Strings::ToInt(sep.arg[3]));
lua_setfield(L, -2, "is_tradeskill");
}
@@ -1537,13 +1666,13 @@ void handle_player_language_skill_up(
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "skill_id");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "skill_value");
lua_pushinteger(L, std::stoi(sep.arg[2]));
lua_pushinteger(L, Strings::ToInt(sep.arg[2]));
lua_setfield(L, -2, "skill_max");
}
@@ -1556,19 +1685,19 @@ void handle_player_alt_currency_merchant(
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "currency_id");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "npc_id");
lua_pushinteger(L, std::stoi(sep.arg[2]));
lua_pushinteger(L, Strings::ToInt(sep.arg[2]));
lua_setfield(L, -2, "merchant_id");
lua_pushinteger(L, std::stoi(sep.arg[3]));
lua_pushinteger(L, Strings::ToInt(sep.arg[3]));
lua_setfield(L, -2, "item_id");
lua_pushinteger(L, std::stoi(sep.arg[4]));
lua_pushinteger(L, Strings::ToInt(sep.arg[4]));
lua_setfield(L, -2, "item_cost");
}
@@ -1581,19 +1710,19 @@ void handle_player_merchant(
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "npc_id");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "merchant_id");
lua_pushinteger(L, std::stoi(sep.arg[2]));
lua_pushinteger(L, Strings::ToInt(sep.arg[2]));
lua_setfield(L, -2, "item_id");
lua_pushinteger(L, std::stoi(sep.arg[3]));
lua_pushinteger(L, Strings::ToInt(sep.arg[3]));
lua_setfield(L, -2, "item_quantity");
lua_pushinteger(L, std::stoi(sep.arg[4]));
lua_pushinteger(L, Strings::ToInt(sep.arg[4]));
lua_setfield(L, -2, "item_cost");
}
@@ -1619,7 +1748,7 @@ void handle_player_augment_insert(
lua_pushinteger(L, std::stoul(sep.arg[0]));
lua_setfield(L, -2, "item_id");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "item_slot");
lua_pushinteger(L, std::stoul(sep.arg[2]));
@@ -1651,7 +1780,7 @@ void handle_player_augment_remove(
lua_pushinteger(L, std::stoul(sep.arg[0]));
lua_setfield(L, -2, "item_id");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "item_slot");
lua_pushinteger(L, std::stoul(sep.arg[2]));
@@ -1688,7 +1817,7 @@ void handle_bot_cast(
) {
Seperator sep(data.c_str());
int spell_id = std::stoi(sep.arg[0]);
int spell_id = Strings::ToInt(sep.arg[0]);
if (IsValidSpell(spell_id)) {
Lua_Spell l_spell(&spells[spell_id]);
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
@@ -1701,10 +1830,10 @@ void handle_bot_cast(
lua_setfield(L, -2, "spell");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "caster_id");
lua_pushinteger(L, std::stoi(sep.arg[2]));
lua_pushinteger(L, Strings::ToInt(sep.arg[2]));
lua_setfield(L, -2, "caster_level");
}
@@ -1722,7 +1851,7 @@ void handle_bot_combat(
l_mob_o.push(L);
lua_setfield(L, -2, "other");
lua_pushboolean(L, std::stoi(data) == 0 ? false : true);
lua_pushboolean(L, Strings::ToInt(data) == 0 ? false : true);
lua_setfield(L, -2, "joined");
}
@@ -1737,16 +1866,16 @@ void handle_bot_death(
) {
Seperator sep(data.c_str());
Mob *o = entity_list.GetMobID(std::stoi(sep.arg[0]));
Mob *o = entity_list.GetMobID(Strings::ToInt(sep.arg[0]));
Lua_Mob l_mob(o);
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
l_mob_o.push(L);
lua_setfield(L, -2, "other");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "damage");
int spell_id = std::stoi(sep.arg[2]);
int spell_id = Strings::ToInt(sep.arg[2]);
if (IsValidSpell(spell_id)) {
Lua_Spell l_spell(&spells[spell_id]);
luabind::adl::object l_spell_o = luabind::adl::object(L, l_spell);
@@ -1759,7 +1888,7 @@ void handle_bot_death(
lua_setfield(L, -2, "spell");
}
lua_pushinteger(L, std::stoi(sep.arg[3]));
lua_pushinteger(L, Strings::ToInt(sep.arg[3]));
lua_setfield(L, -2, "skill");
}
@@ -1777,7 +1906,7 @@ void handle_bot_popup_response(
l_mob_o.push(L);
lua_setfield(L, -2, "other");
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "popup_id");
}
@@ -1811,7 +1940,7 @@ void handle_bot_signal(
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushinteger(L, std::stoi(data));
lua_pushinteger(L, Strings::ToInt(data));
lua_setfield(L, -2, "signal");
}
@@ -1826,7 +1955,7 @@ void handle_bot_payload(
) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "payload_id");
lua_pushstring(L, sep.argplus[1]);
@@ -1944,10 +2073,10 @@ void handle_bot_use_skill(
std::vector<std::any> *extra_pointers
) {
Seperator sep(data.c_str());
lua_pushinteger(L, std::stoi(sep.arg[0]));
lua_pushinteger(L, Strings::ToInt(sep.arg[0]));
lua_setfield(L, -2, "skill_id");
lua_pushinteger(L, std::stoi(sep.arg[1]));
lua_pushinteger(L, Strings::ToInt(sep.arg[1]));
lua_setfield(L, -2, "skill_level");
}
@@ -1977,7 +2106,7 @@ void handle_bot_equip_item(
lua_setfield(L, -2, "item");
}
void handle_bot_unequip_item(
void handle_bot_damage(
QuestInterface *parse,
lua_State* L,
Bot* bot,
@@ -1986,22 +2115,39 @@ void handle_bot_unequip_item(
uint32 extra_data,
std::vector<std::any> *extra_pointers
) {
lua_pushnumber(L, extra_data);
lua_setfield(L, -2, "item_id");
Seperator sep(data.c_str());
lua_pushnumber(L, std::stoi(sep.arg[0]));
lua_setfield(L, -2, "item_quantity");
lua_pushnumber(L, std::stoul(sep.arg[0]));
lua_setfield(L, -2, "entity_id");
lua_pushnumber(L, std::stoi(sep.arg[1]));
lua_setfield(L, -2, "slot_id");
lua_pushnumber(L, std::stoll(sep.arg[1]));
lua_setfield(L, -2, "damage");
Lua_ItemInst l_item(extra_data);
luabind::adl::object l_item_o = luabind::adl::object(L, l_item);
l_item_o.push(L);
lua_setfield(L, -2, "item");
lua_pushnumber(L, std::stoi(sep.arg[2]));
lua_setfield(L, -2, "spell_id");
lua_pushnumber(L, std::stoi(sep.arg[3]));
lua_setfield(L, -2, "skill_id");
lua_pushboolean(L, std::stoi(sep.arg[4]) == 0 ? false : true);
lua_setfield(L, -2, "is_damage_shield");
lua_pushboolean(L, std::stoi(sep.arg[5]) == 0 ? false : true);
lua_setfield(L, -2, "is_avoidable");
lua_pushnumber(L, std::stoi(sep.arg[6]));
lua_setfield(L, -2, "buff_slot");
lua_pushboolean(L, std::stoi(sep.arg[7]) == 0 ? false : true);
lua_setfield(L, -2, "is_buff_tic");
lua_pushnumber(L, std::stoi(sep.arg[8]));
lua_setfield(L, -2, "special_attack");
Lua_Mob l_mob(init);
luabind::adl::object l_mob_o = luabind::adl::object(L, l_mob);
l_mob_o.push(L);
lua_setfield(L, -2, "other");
}
#endif
+37 -1
View File
@@ -210,6 +210,16 @@ void handle_npc_despawn_zone(
std::vector<std::any> *extra_pointers
);
void handle_npc_damage(
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,
@@ -373,6 +383,15 @@ void handle_player_task_stage_complete(
std::vector<std::any> *extra_pointers
);
void handle_player_task_accepted(
QuestInterface* parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any>* extra_pointers
);
void handle_player_task_update(
QuestInterface *parse,
lua_State* L,
@@ -652,6 +671,23 @@ void handle_player_augment_remove(
std::vector<std::any> *extra_pointers
);
void handle_player_damage(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
void handle_player_item_click(
QuestInterface *parse,
lua_State* L,
Client* client,
std::string data,
uint32 extra_data,
std::vector<std::any> *extra_pointers
);
// Item
void handle_item_click(
@@ -965,7 +1001,7 @@ void handle_bot_equip_item(
std::vector<std::any> *extra_pointers
);
void handle_bot_unequip_item(
void handle_bot_damage(
QuestInterface *parse,
lua_State* L,
Bot* bot,
+1
View File
@@ -123,6 +123,7 @@ public:
bool UseDiscipline(int32 spell_id, int32 target);
virtual bool IsMerc() const { return true; }
bool IsOfClientBotMerc() const override { return true; }
virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
static Merc* LoadMerc(Client *c, MercTemplate* merc_template, uint32 merchant_id, bool updateFromDB = false);
+3 -1
View File
@@ -657,7 +657,7 @@ public:
inline int32 GetHeroicStrikethrough() const { return heroic_strikethrough; }
inline const bool GetKeepsSoldItems() const { return keeps_sold_items; }
inline void SetKeepsSoldItems(bool in_keeps_sold_items) { keeps_sold_items = in_keeps_sold_items; }
int CalcRecommendedLevelBonus(uint8 level, uint8 reclevel, int basestat);
void CopyHateList(Mob* to);
//Group
@@ -1451,6 +1451,8 @@ public:
void SetManualFollow(bool flag) { m_manual_follow = flag; }
bool GetManualFollow() const { return m_manual_follow; }
void DrawDebugCoordinateNode(std::string node_name, const glm::vec4 vec);
protected:
void CommonDamage(Mob* other, int64 &damage, const uint16 spell_id, const EQ::skills::SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic, eSpecialAttacks specal = eSpecialAttacks::None);
static uint16 GetProcID(uint16 spell_id, uint8 effect_index);
+7 -1
View File
@@ -999,7 +999,13 @@ void Mob::AI_Process() {
}
if (door->GetTriggerDoorID() > 0) {
continue;
auto trigger_door = entity_list.GetDoorsByDoorID(door->GetTriggerDoorID());
if (trigger_door) {
if (Strings::RemoveNumbers(door->GetDoorName()) !=
Strings::RemoveNumbers(trigger_door->GetDoorName())) {
continue;
}
}
}
if (door->GetDoorParam() > 0) {
+9 -2
View File
@@ -138,7 +138,7 @@ public:
return true;
}
//Send a movement packet when you start moving
//Send a movement packet when you start moving
double current_time = static_cast<double>(Timer::GetCurrentTime()) / 1000.0;
int current_speed = 0;
@@ -1053,6 +1053,13 @@ void MobMovementManager::FillCommandStruct(
position_update->delta_z = FloatToEQ13(delta_z);
position_update->delta_heading = FloatToEQ10(delta_heading);
position_update->animation = (mob->IsBot() ? (int) ((float) anim / 1.785714f) : anim);
if (RuleB(Map, MobPathingVisualDebug)) {
mob->DrawDebugCoordinateNode(
fmt::format("{} position update", mob->GetCleanName()),
mob->GetPosition()
);
}
}
/**
@@ -1093,7 +1100,7 @@ void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMove
}
// Below for npcs that can traverse land or water so they don't sink
else if (who->GetFlyMode() == GravityBehavior::Water &&
zone->watermap->InLiquid(who->GetPosition()) &&
zone->watermap->InLiquid(who->GetPosition()) &&
zone->watermap->InLiquid(glm::vec3(x, y, z)) &&
zone->zonemap->CheckLoS(who->GetPosition(), glm::vec3(x, y, z))) {
auto iter = _impl->Entries.find(who);
+71 -60
View File
@@ -160,42 +160,43 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi
size = 5;
}
taunting = false;
proximity = nullptr;
copper = 0;
silver = 0;
gold = 0;
platinum = 0;
max_dmg = npc_type_data->max_dmg;
min_dmg = npc_type_data->min_dmg;
attack_count = npc_type_data->attack_count;
grid = 0;
wp_m = 0;
max_wp = 0;
save_wp = 0;
spawn_group_id = 0;
swarmInfoPtr = nullptr;
spellscale = npc_type_data->spellscale;
healscale = npc_type_data->healscale;
pAggroRange = npc_type_data->aggroradius;
pAssistRange = npc_type_data->assistradius;
findable = npc_type_data->findable;
trackable = npc_type_data->trackable;
MR = npc_type_data->MR;
CR = npc_type_data->CR;
DR = npc_type_data->DR;
FR = npc_type_data->FR;
PR = npc_type_data->PR;
Corrup = npc_type_data->Corrup;
PhR = npc_type_data->PhR;
STR = npc_type_data->STR;
STA = npc_type_data->STA;
AGI = npc_type_data->AGI;
DEX = npc_type_data->DEX;
INT = npc_type_data->INT;
WIS = npc_type_data->WIS;
CHA = npc_type_data->CHA;
npc_mana = npc_type_data->Mana;
taunting = false;
proximity = nullptr;
copper = 0;
silver = 0;
gold = 0;
platinum = 0;
max_dmg = npc_type_data->max_dmg;
min_dmg = npc_type_data->min_dmg;
attack_count = npc_type_data->attack_count;
grid = 0;
wp_m = 0;
max_wp = 0;
save_wp = 0;
spawn_group_id = 0;
swarmInfoPtr = nullptr;
spellscale = npc_type_data->spellscale;
healscale = npc_type_data->healscale;
pAggroRange = npc_type_data->aggroradius;
pAssistRange = npc_type_data->assistradius;
findable = npc_type_data->findable;
trackable = npc_type_data->trackable;
MR = npc_type_data->MR;
CR = npc_type_data->CR;
DR = npc_type_data->DR;
FR = npc_type_data->FR;
PR = npc_type_data->PR;
Corrup = npc_type_data->Corrup;
PhR = npc_type_data->PhR;
STR = npc_type_data->STR;
STA = npc_type_data->STA;
AGI = npc_type_data->AGI;
DEX = npc_type_data->DEX;
INT = npc_type_data->INT;
WIS = npc_type_data->WIS;
CHA = npc_type_data->CHA;
npc_mana = npc_type_data->Mana;
m_is_underwater_only = npc_type_data->underwater;
//quick fix of ordering if they screwed it up in the DB
if (max_dmg < min_dmg) {
@@ -371,16 +372,16 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi
}
}
ldon_trapped = false;
ldon_trap_type = 0;
ldon_spell_id = 0;
ldon_locked = false;
ldon_locked_skill = 0;
ldon_trap_detected = false;
SetLDoNTrapped(false);
SetLDoNTrapType(0);
SetLDoNTrapSpellID(0);
SetLDoNLocked(false);
SetLDoNLockedSkill(0);
SetLDoNTrapDetected(false);
if (npc_type_data->trap_template > 0) {
std::map<uint32, std::list<LDoNTrapTemplate *> >::iterator trap_ent_iter;
std::list<LDoNTrapTemplate *> trap_list;
std::list<LDoNTrapTemplate *> trap_list;
trap_ent_iter = zone->ldon_trap_entry_list.find(npc_type_data->trap_template);
if (trap_ent_iter != zone->ldon_trap_entry_list.end()) {
@@ -390,26 +391,25 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi
std::advance(trap_list_iter, zone->random.Int(0, trap_list.size() - 1));
LDoNTrapTemplate *trap_template = (*trap_list_iter);
if (trap_template) {
if ((uint8) trap_template->spell_id > 0) {
ldon_trapped = true;
ldon_spell_id = trap_template->spell_id;
}
else {
ldon_trapped = false;
ldon_spell_id = 0;
if (trap_template->spell_id > 0) {
SetLDoNTrapped(true);
SetLDoNTrapSpellID(trap_template->spell_id);
} else {
SetLDoNTrapped(false);
SetLDoNTrapSpellID(0);
}
ldon_trap_type = (uint8) trap_template->type;
SetLDoNTrapType(static_cast<uint8>(trap_template->type));
if (trap_template->locked > 0) {
ldon_locked = true;
ldon_locked_skill = trap_template->skill;
}
else {
ldon_locked = false;
ldon_locked_skill = 0;
SetLDoNLocked(true);
SetLDoNLockedSkill(trap_template->skill);
} else {
SetLDoNLocked(false);
SetLDoNLockedSkill(0);
}
ldon_trap_detected = 0;
SetLDoNTrapDetected(false);
}
}
}
@@ -3692,7 +3692,7 @@ void NPC::ReloadSpells() {
AI_AddNPCSpellsEffects(GetNPCSpellsEffectsID());
}
void NPC::ScaleNPC(uint8 npc_level) {
void NPC::ScaleNPC(uint8 npc_level, bool always_scale, bool override_special_abilities) {
if (GetLevel() != npc_level) {
SetLevel(npc_level);
RecalculateSkills();
@@ -3700,7 +3700,7 @@ void NPC::ScaleNPC(uint8 npc_level) {
}
npc_scale_manager->ResetNPCScaling(this);
npc_scale_manager->ScaleNPC(this);
npc_scale_manager->ScaleNPC(this, always_scale, override_special_abilities);
}
bool NPC::IsGuard()
@@ -3784,3 +3784,14 @@ int NPC::GetRolledItemCount(uint32 item_id)
return rolled_count;
}
void NPC::SendPositionToClients()
{
auto p = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
auto *s = (PlayerPositionUpdateServer_Struct *) p->pBuffer;
for (auto &c: entity_list.GetClientList()) {
MakeSpawnUpdate(s);
c.second->QueuePacket(p, false);
}
safe_delete(p);
}
+13 -9
View File
@@ -119,7 +119,7 @@ public:
virtual void Damage(Mob* from, int64 damage, uint16 spell_id, EQ::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None);
bool Attack(Mob* other, int Hand = EQ::invslot::slotPrimary, bool FromRiposte = false, bool IsStrikethrough = false,
bool IsFromSpell = false, ExtraAttackOptions *opts = nullptr) override;
virtual bool HasRaid() { return false; }
virtual bool HasRaid() { return false; }
virtual bool HasGroup() { return false; }
virtual Raid* GetRaid() { return 0; }
virtual Group* GetGroup() { return 0; }
@@ -413,22 +413,22 @@ public:
void ModifyNPCStat(std::string stat, std::string value);
virtual void SetLevel(uint8 in_level, bool command = false);
bool IsLDoNTrapped() const { return (ldon_trapped); }
bool IsLDoNTrapped() const { return ldon_trapped; }
void SetLDoNTrapped(bool n) { ldon_trapped = n; }
uint8 GetLDoNTrapType() const { return (ldon_trap_type); }
uint8 GetLDoNTrapType() const { return ldon_trap_type; }
void SetLDoNTrapType(uint8 n) { ldon_trap_type = n; }
uint16 GetLDoNTrapSpellID() const { return (ldon_spell_id); }
uint16 GetLDoNTrapSpellID() const { return ldon_spell_id; }
void SetLDoNTrapSpellID(uint16 n) { ldon_spell_id = n; }
bool IsLDoNLocked() const { return (ldon_locked); }
bool IsLDoNLocked() const { return ldon_locked; }
void SetLDoNLocked(bool n) { ldon_locked = n; }
uint16 GetLDoNLockedSkill() const { return (ldon_locked_skill); }
uint16 GetLDoNLockedSkill() const { return ldon_locked_skill; }
void SetLDoNLockedSkill(uint16 n) { ldon_locked_skill = n; }
bool IsLDoNTrapDetected() const { return (ldon_trap_detected); }
bool IsLDoNTrapDetected() const { return ldon_trap_detected; }
void SetLDoNTrapDetected(bool n) { ldon_trap_detected = n; }
const bool GetCombatEvent() const { return combat_event; }
@@ -437,7 +437,7 @@ public:
/* Only allows players that killed corpse to loot */
const bool HasPrivateCorpse() const { return NPCTypedata_ours ? NPCTypedata_ours->private_corpse : NPCTypedata->private_corpse; }
virtual const bool IsUnderwaterOnly() const { return NPCTypedata_ours ? NPCTypedata_ours->underwater : NPCTypedata->underwater; }
virtual const bool IsUnderwaterOnly() const { return m_is_underwater_only; }
const char* GetRawNPCTypeName() const { return NPCTypedata_ours ? NPCTypedata_ours->name : NPCTypedata->name; }
virtual int GetKillExpMod() const { return NPCTypedata_ours ? NPCTypedata_ours->exp_mod : NPCTypedata->exp_mod; }
@@ -531,11 +531,13 @@ public:
inline bool IsSkipAutoScale() const { return skip_auto_scale; }
void ScaleNPC(uint8 npc_level);
void ScaleNPC(uint8 npc_level, bool always_scale = false, bool override_special_abilities = false);
void RecalculateSkills();
void ReloadSpells();
void SendPositionToClients();
static LootDropEntries_Struct NewLootDropEntry();
protected:
@@ -672,6 +674,8 @@ protected:
QGlobalCache *qGlobals;
uint32 adventure_template_id;
bool m_is_underwater_only = false;
//mercenary stuff
std::list<MercType> mercTypeList;
std::list<MercData> mercDataList;
+103 -73
View File
@@ -26,7 +26,11 @@
/**
* @param npc
*/
void NpcScaleManager::ScaleNPC(NPC *npc)
void NpcScaleManager::ScaleNPC(
NPC *npc,
bool always_scale,
bool override_special_abilities
)
{
if (npc->IsSkipAutoScale() || npc->GetNPCTypeID() == 0) {
return;
@@ -49,65 +53,84 @@ void NpcScaleManager::ScaleNPC(NPC *npc)
return;
}
if (npc->GetAC() == 0 && is_auto_scaled) {
npc->ModifyNPCStat("ac", std::to_string(scale_data.ac).c_str());
if (always_scale || (npc->GetAC() == 0 && is_auto_scaled)) {
npc->ModifyNPCStat("ac", std::to_string(scale_data.ac));
}
if (npc->GetMaxHP() == 0) {
npc->ModifyNPCStat("max_hp", std::to_string(scale_data.hp).c_str());
if (always_scale || npc->GetMaxHP() == 0) {
npc->ModifyNPCStat("max_hp", std::to_string(scale_data.hp));
npc->Heal();
}
if (npc->GetAccuracyRating() == 0) {
npc->ModifyNPCStat("accuracy", std::to_string(scale_data.accuracy).c_str());
if (always_scale || npc->GetAccuracyRating() == 0) {
npc->ModifyNPCStat("accuracy", std::to_string(scale_data.accuracy));
}
if (npc->GetSlowMitigation() == 0) {
npc->ModifyNPCStat("slow_mitigation", std::to_string(scale_data.slow_mitigation).c_str());
if (always_scale || npc->GetSlowMitigation() == 0) {
npc->ModifyNPCStat("slow_mitigation", std::to_string(scale_data.slow_mitigation));
}
if (npc->GetATK() == 0) {
npc->ModifyNPCStat("atk", std::to_string(scale_data.attack).c_str());
if (always_scale || npc->GetATK() == 0) {
npc->ModifyNPCStat("atk", std::to_string(scale_data.attack));
}
if (npc->GetSTR() == 0) {
npc->ModifyNPCStat("str", std::to_string(scale_data.strength).c_str());
if (always_scale || npc->GetSTR() == 0) {
npc->ModifyNPCStat("str", std::to_string(scale_data.strength));
}
if (npc->GetSTA() == 0) {
npc->ModifyNPCStat("sta", std::to_string(scale_data.stamina).c_str());
if (always_scale || npc->GetSTA() == 0) {
npc->ModifyNPCStat("sta", std::to_string(scale_data.stamina));
}
if (npc->GetDEX() == 0) {
npc->ModifyNPCStat("dex", std::to_string(scale_data.dexterity).c_str());
if (always_scale || npc->GetDEX() == 0) {
npc->ModifyNPCStat("dex", std::to_string(scale_data.dexterity));
}
if (npc->GetAGI() == 0) {
npc->ModifyNPCStat("agi", std::to_string(scale_data.agility).c_str());
if (always_scale || npc->GetAGI() == 0) {
npc->ModifyNPCStat("agi", std::to_string(scale_data.agility));
}
if (npc->GetINT() == 0) {
npc->ModifyNPCStat("int", std::to_string(scale_data.intelligence).c_str());
if (always_scale || npc->GetINT() == 0) {
npc->ModifyNPCStat("int", std::to_string(scale_data.intelligence));
}
if (npc->GetWIS() == 0) {
npc->ModifyNPCStat("wis", std::to_string(scale_data.wisdom).c_str());
if (always_scale || npc->GetWIS() == 0) {
npc->ModifyNPCStat("wis", std::to_string(scale_data.wisdom));
}
if (npc->GetCHA() == 0) {
npc->ModifyNPCStat("cha", std::to_string(scale_data.charisma).c_str());
if (always_scale || npc->GetCHA() == 0) {
npc->ModifyNPCStat("cha", std::to_string(scale_data.charisma));
}
if (npc->GetMR() == 0) {
npc->ModifyNPCStat("mr", std::to_string(scale_data.magic_resist).c_str());
if (always_scale || npc->GetMR() == 0) {
npc->ModifyNPCStat("mr", std::to_string(scale_data.magic_resist));
}
if (npc->GetCR() == 0) {
npc->ModifyNPCStat("cr", std::to_string(scale_data.cold_resist).c_str());
if (always_scale || npc->GetCR() == 0) {
npc->ModifyNPCStat("cr", std::to_string(scale_data.cold_resist));
}
if (npc->GetFR() == 0) {
npc->ModifyNPCStat("fr", std::to_string(scale_data.fire_resist).c_str());
if (always_scale || npc->GetFR() == 0) {
npc->ModifyNPCStat("fr", std::to_string(scale_data.fire_resist));
}
if (npc->GetPR() == 0) {
npc->ModifyNPCStat("pr", std::to_string(scale_data.poison_resist).c_str());
if (always_scale || npc->GetPR() == 0) {
npc->ModifyNPCStat("pr", std::to_string(scale_data.poison_resist));
}
if (npc->GetDR() == 0) {
npc->ModifyNPCStat("dr", std::to_string(scale_data.disease_resist).c_str());
if (always_scale || npc->GetDR() == 0) {
npc->ModifyNPCStat("dr", std::to_string(scale_data.disease_resist));
}
if (npc->GetCorrup() == 0 && is_auto_scaled) {
npc->ModifyNPCStat("cor", std::to_string(scale_data.corruption_resist).c_str());
if (always_scale || (npc->GetCorrup() == 0 && is_auto_scaled)) {
npc->ModifyNPCStat("cor", std::to_string(scale_data.corruption_resist));
}
if (npc->GetPhR() == 0 && is_auto_scaled) {
npc->ModifyNPCStat("phr", std::to_string(scale_data.physical_resist).c_str());
if (always_scale || (npc->GetPhR() == 0 && is_auto_scaled)) {
npc->ModifyNPCStat("phr", std::to_string(scale_data.physical_resist));
}
if (npc->GetMinDMG() == 0 && npc->GetMaxDMG() == 0) {
if (always_scale || npc->GetMinDMG() == 0) {
int min_dmg = scale_data.min_dmg;
if (RuleB(Combat, UseNPCDamageClassLevelMods)) {
int32 class_level_damage_mod = GetClassLevelDamageMod(npc->GetLevel(), npc->GetClass());
@@ -116,9 +139,10 @@ void NpcScaleManager::ScaleNPC(NPC *npc)
LogNPCScaling("ClassLevelDamageMod::min_dmg base: [{}] calc: [{}]", scale_data.min_dmg, min_dmg);
}
npc->ModifyNPCStat("min_hit", std::to_string(min_dmg).c_str());
npc->ModifyNPCStat("min_hit", std::to_string(min_dmg));
}
if (npc->GetMaxDMG() == 0) {
if (always_scale || npc->GetMaxDMG() == 0) {
int max_dmg = scale_data.max_dmg;
if (RuleB(Combat, UseNPCDamageClassLevelMods)) {
int32 class_level_damage_mod = GetClassLevelDamageMod(npc->GetLevel(), npc->GetClass());
@@ -127,22 +151,27 @@ void NpcScaleManager::ScaleNPC(NPC *npc)
LogNPCScaling("ClassLevelDamageMod::max_dmg base: [{}] calc: [{}]", scale_data.max_dmg, max_dmg);
}
npc->ModifyNPCStat("max_hit", std::to_string(max_dmg).c_str());
npc->ModifyNPCStat("max_hit", std::to_string(max_dmg));
}
if (npc->GetHPRegen() == 0 && is_auto_scaled) {
npc->ModifyNPCStat("hp_regen", std::to_string(scale_data.hp_regen_rate).c_str());
if (always_scale || (npc->GetHPRegen() == 0 && is_auto_scaled)) {
npc->ModifyNPCStat("hp_regen", std::to_string(scale_data.hp_regen_rate));
}
if (npc->GetAttackDelay() == 0) {
npc->ModifyNPCStat("attack_delay", std::to_string(scale_data.attack_delay).c_str());
if (always_scale || npc->GetAttackDelay() == 0) {
npc->ModifyNPCStat("attack_delay", std::to_string(scale_data.attack_delay));
}
if (npc->GetSpellScale() == 0) {
npc->ModifyNPCStat("spell_scale", std::to_string(scale_data.spell_scale).c_str());
if (always_scale || npc->GetSpellScale() == 0) {
npc->ModifyNPCStat("spell_scale", std::to_string(scale_data.spell_scale));
}
if (npc->GetHealScale() == 0) {
npc->ModifyNPCStat("heal_scale", std::to_string(scale_data.heal_scale).c_str());
if (always_scale || npc->GetHealScale() == 0) {
npc->ModifyNPCStat("heal_scale", std::to_string(scale_data.heal_scale));
}
if (!npc->HasSpecialAbilities() && is_auto_scaled) {
npc->ModifyNPCStat("special_abilities", scale_data.special_abilities.c_str());
if (override_special_abilities || (!npc->HasSpecialAbilities() && is_auto_scaled)) {
npc->ModifyNPCStat("special_abilities", scale_data.special_abilities);
}
if (LogSys.log_settings[Logs::NPCScaling].is_category_enabled == 1) {
@@ -161,18 +190,18 @@ void NpcScaleManager::ScaleNPC(NPC *npc)
npc_level,
npc_type,
(is_auto_scaled ? "true" : "false"),
scale_log.c_str()
scale_log
);
}
}
void NpcScaleManager::ResetNPCScaling(NPC *npc)
void NpcScaleManager::ResetNPCScaling(NPC* npc)
{
for (const auto &scaling_stat : scaling_stats) {
auto stat_name = fmt::format("modify_stat_{}", scaling_stat);
auto reset_value = std::to_string(0);
if (npc->EntityVariableExists(stat_name)) {
npc->ModifyNPCStat(scaling_stat.c_str(), reset_value.c_str());
npc->ModifyNPCStat(scaling_stat, reset_value);
}
}
}
@@ -430,24 +459,25 @@ std::string NpcScaleManager::GetNPCScalingTypeName(NPC *&npc)
* @param npc
* @return
*/
bool NpcScaleManager::IsAutoScaled(NPC *npc)
bool NpcScaleManager::IsAutoScaled(NPC* npc)
{
return
(npc->GetHP() == 0 &&
npc->GetMaxDMG() == 0 &&
npc->GetMinDMG() == 0 &&
npc->GetSTR() == 0 &&
npc->GetSTA() == 0 &&
npc->GetDEX() == 0 &&
npc->GetAGI() == 0 &&
npc->GetINT() == 0 &&
npc->GetWIS() == 0 &&
npc->GetCHA() == 0 &&
npc->GetMR() == 0 &&
npc->GetFR() == 0 &&
npc->GetCR() == 0 &&
npc->GetPR() == 0 &&
npc->GetDR() == 0);
return (
npc->GetHP() == 0 &&
npc->GetMaxDMG() == 0 &&
npc->GetMinDMG() == 0 &&
npc->GetSTR() == 0 &&
npc->GetSTA() == 0 &&
npc->GetDEX() == 0 &&
npc->GetAGI() == 0 &&
npc->GetINT() == 0 &&
npc->GetWIS() == 0 &&
npc->GetCHA() == 0 &&
npc->GetMR() == 0 &&
npc->GetFR() == 0 &&
npc->GetCR() == 0 &&
npc->GetPR() == 0 &&
npc->GetDR() == 0
);
}
/**
+3 -3
View File
@@ -86,9 +86,9 @@ public:
"special_abilities"
};
void ScaleNPC(NPC * npc);
void ResetNPCScaling(NPC * npc);
bool IsAutoScaled(NPC * npc);
void ScaleNPC(NPC* npc, bool always_scale = false, bool override_special_abilities = false);
void ResetNPCScaling(NPC* npc);
bool IsAutoScaled(NPC* npc);
bool LoadScaleData();
global_npc_scale GetGlobalScaleDataForTypeLevel(int8 npc_type, int npc_level);
+62
View File
@@ -385,6 +385,66 @@ void Perl_Bot_Camp(Bot* self, bool save_to_database) // @categories Script Utili
self->Camp(save_to_database);
}
perl::array Perl_Bot_GetAugmentIDsBySlotID(Bot* self, int16 slot_id)
{
perl::array result;
auto augments = self->GetInv().GetAugmentIDsBySlotID(slot_id);
for (int i = 0; i < augments.size(); ++i) {
result.push_back(augments[i]);
}
return result;
}
void Perl_Bot_AddItem(Bot *self, perl::reference table_ref)
{
perl::hash table = table_ref;
if (!table.exists("item_id") || !table.exists("charges"))
{
return;
}
uint32 item_id = table["item_id"];
int16 charges = table["charges"];
uint32 augment_one = table.exists("augment_one") ? table["augment_one"] : 0;
uint32 augment_two = table.exists("augment_two") ? table["augment_two"] : 0;
uint32 augment_three = table.exists("augment_three") ? table["augment_three"] : 0;
uint32 augment_four = table.exists("augment_four") ? table["augment_four"] : 0;
uint32 augment_five = table.exists("augment_five") ? table["augment_five"] : 0;
uint32 augment_six = table.exists("augment_six") ? table["augment_six"] : 0;
bool attuned = table.exists("attuned") && table["attuned"];
uint16 slot_id = table.exists("slot_id") ? table["slot_id"] : EQ::invslot::slotCursor;
if (slot_id <= EQ::invslot::slotAmmo) {
self->AddBotItem(
slot_id,
item_id,
charges,
attuned,
augment_one,
augment_two,
augment_three,
augment_four,
augment_five,
augment_six
);
} else {
self->GetOwner()->CastToClient()->SummonItem(
item_id,
charges,
augment_one,
augment_two,
augment_three,
augment_four,
augment_five,
augment_six,
attuned,
slot_id
);
}
}
void perl_register_bot()
{
perl::interpreter state(PERL_GET_THX);
@@ -400,6 +460,7 @@ void perl_register_bot()
package.add("AddBotItem", (void(*)(Bot*, uint16, uint32, uint16, bool, uint32, uint32, uint32, uint32))&Perl_Bot_AddBotItem);
package.add("AddBotItem", (void(*)(Bot*, uint16, uint32, uint16, bool, uint32, uint32, uint32, uint32, uint32))&Perl_Bot_AddBotItem);
package.add("AddBotItem", (void(*)(Bot*, uint16, uint32, uint16, bool, uint32, uint32, uint32, uint32, uint32, uint32))&Perl_Bot_AddBotItem);
package.add("AddItem", &Perl_Bot_AddItem);
package.add("ApplySpell", (void(*)(Bot*, int))&Perl_Bot_ApplySpell);
package.add("ApplySpell", (void(*)(Bot*, int, int))&Perl_Bot_ApplySpell);
package.add("ApplySpell", (void(*)(Bot*, int, int, bool))&Perl_Bot_ApplySpell);
@@ -420,6 +481,7 @@ void perl_register_bot()
package.add("Fling", (void(*)(Bot*, float, float, float, float, bool, bool))&Perl_Bot_Fling);
package.add("GetAugmentAt", &Perl_Bot_GetAugmentAt);
package.add("GetAugmentIDAt", &Perl_Bot_GetAugmentIDAt);
package.add("GetAugmentIDsBySlotID", &Perl_Bot_GetAugmentIDsBySlotID);
package.add("GetBaseAGI", &Perl_Bot_GetBaseAGI);
package.add("GetBaseCHA", &Perl_Bot_GetBaseCHA);
package.add("GetBaseDEX", &Perl_Bot_GetBaseDEX);
+18
View File
@@ -2877,6 +2877,21 @@ void Perl_Client_ResetItemCooldown(Client* self, uint32 item_id)
self->ResetItemCooldown(item_id);
}
void Perl_Client_SetItemCooldown(Client* self, uint32 item_id, uint32 in_time)
{
self->SetItemCooldown(item_id, false, in_time);
}
uint32 Perl_Client_GetItemCooldown(Client* self, uint32 item_id)
{
return self->GetItemCooldown(item_id);
}
void Perl_Client_UseAugmentContainer(Client* self, int container_slot)
{
self->UseAugmentContainer(container_slot);
}
void perl_register_client()
{
perl::interpreter perl(PERL_GET_THX);
@@ -3071,6 +3086,7 @@ void perl_register_client()
package.add("GetInventory", &Perl_Client_GetInventory);
package.add("GetInvulnerableEnvironmentDamage", &Perl_Client_GetInvulnerableEnvironmentDamage);
package.add("GetItemAt", &Perl_Client_GetItemAt);
package.add("GetItemCooldown", &Perl_Client_GetItemCooldown);
package.add("GetItemIDAt", &Perl_Client_GetItemIDAt);
package.add("GetItemInInventory", &Perl_Client_GetItemInInventory);
package.add("GetLDoNLosses", &Perl_Client_GetLDoNLosses);
@@ -3313,6 +3329,7 @@ void perl_register_client()
package.add("SetHunger", &Perl_Client_SetHunger);
package.add("SetIPExemption", &Perl_Client_SetIPExemption);
package.add("SetInvulnerableEnvironmentDamage", &Perl_Client_SetInvulnerableEnvironmentDamage);
package.add("SetItemCooldown", &Perl_Client_SetItemCooldown);
package.add("SetLanguageSkill", &Perl_Client_SetLanguageSkill);
package.add("SetMaterial", &Perl_Client_SetMaterial);
package.add("SetPEQZoneFlag", &Perl_Client_SetPEQZoneFlag);
@@ -3402,6 +3419,7 @@ void perl_register_client()
package.add("UpdateWho", (void(*)(Client*))&Perl_Client_UpdateWho);
package.add("UpdateWho", (void(*)(Client*, uint8))&Perl_Client_UpdateWho);
package.add("UseDiscipline", &Perl_Client_UseDiscipline);
package.add("UseAugmentContainer", &Perl_Client_UseAugmentContainer);
package.add("WorldKick", &Perl_Client_WorldKick);
}
+84 -6
View File
@@ -594,11 +594,6 @@ void Perl_NPC_RecalculateSkills(NPC* self) // @categories Skills and Recipes
self->RecalculateSkills();
}
void Perl_NPC_ScaleNPC(NPC* self, uint8 npc_level)
{
return self->ScaleNPC(npc_level);
}
bool Perl_NPC_IsRaidTarget(NPC* self)
{
return self->IsRaidTarget();
@@ -690,6 +685,76 @@ void Perl_NPC_SetKeepsSoldItems(NPC* self, bool keeps_sold_items)
self->SetKeepsSoldItems(keeps_sold_items);
}
bool Perl_NPC_IsLDoNTrapped(NPC* self)
{
return self->IsLDoNTrapped();
}
void Perl_NPC_SetLDoNTrapped(NPC* self, bool is_trapped)
{
self->SetLDoNTrapped(is_trapped);
}
uint8 Perl_NPC_GetLDoNTrapType(NPC* self)
{
return self->GetLDoNTrapType();
}
void Perl_NPC_SetLDoNTrapType(NPC* self, uint8 trap_type)
{
self->SetLDoNTrapType(trap_type);
}
uint16 Perl_NPC_GetLDoNTrapSpellID(NPC* self)
{
return self->GetLDoNTrapSpellID();
}
void Perl_NPC_SetLDoNTrapSpellID(NPC* self, uint16 spell_id)
{
self->SetLDoNTrapSpellID(spell_id);
}
bool Perl_NPC_IsLDoNLocked(NPC* self)
{
return self->IsLDoNLocked();
}
void Perl_NPC_SetLDoNLocked(NPC* self, bool is_locked)
{
self->SetLDoNLocked(is_locked);
}
uint16 Perl_NPC_GetLDoNLockedSkill(NPC* self)
{
return self->GetLDoNLockedSkill();
}
void Perl_NPC_SetLDoNLockedSkill(NPC* self, uint16 skill_value)
{
self->SetLDoNLockedSkill(skill_value);
}
bool Perl_NPC_IsLDoNTrapDetected(NPC* self)
{
return self->IsLDoNTrapDetected();
}
void Perl_NPC_SetLDoNTrapDetected(NPC* self, bool is_detected)
{
self->SetLDoNTrapDetected(is_detected);
}
void Perl_NPC_ScaleNPC(NPC* self, uint8 npc_level)
{
return self->ScaleNPC(npc_level);
}
void Perl_NPC_ScaleNPC(NPC* self, uint8 npc_level, bool override_special_abilities)
{
return self->ScaleNPC(npc_level, override_special_abilities);
}
void perl_register_npc()
{
perl::interpreter perl(PERL_GET_THX);
@@ -742,6 +807,9 @@ void perl_register_npc()
package.add("GetHealScale", &Perl_NPC_GetHealScale);
package.add("GetItemIDBySlot", &Perl_NPC_GetItemIDBySlot);
package.add("GetKeepsSoldItems", &Perl_NPC_GetKeepsSoldItems);
package.add("GetLDoNLockedSkill", &Perl_NPC_GetLDoNLockedSkill);
package.add("GetLDoNTrapType", &Perl_NPC_GetLDoNTrapType);
package.add("GetLDoNTrapSpellID", &Perl_NPC_GetLDoNTrapSpellID);
package.add("GetLootList", &Perl_NPC_GetLootList);
package.add("GetLoottableID", &Perl_NPC_GetLoottableID);
package.add("GetMaxDMG", &Perl_NPC_GetMaxDMG);
@@ -777,6 +845,9 @@ void perl_register_npc()
package.add("HasItem", &Perl_NPC_HasItem);
package.add("IsAnimal", &Perl_NPC_IsAnimal);
package.add("IsGuarding", &Perl_NPC_IsGuarding);
package.add("IsLDoNLocked", &Perl_NPC_IsLDoNLocked);
package.add("IsLDoNTrapped", &Perl_NPC_IsLDoNTrapped);
package.add("IsLDoNTrapDetected", &Perl_NPC_IsLDoNTrapDetected);;
package.add("IsOnHatelist", &Perl_NPC_IsOnHatelist);
package.add("IsRaidTarget", &Perl_NPC_IsRaidTarget);
package.add("IsRareSpawn", &Perl_NPC_IsRareSpawn);
@@ -806,11 +877,18 @@ void perl_register_npc()
package.add("SaveGuardSpot", (void(*)(NPC*))&Perl_NPC_SaveGuardSpot);
package.add("SaveGuardSpot", (void(*)(NPC*, bool))&Perl_NPC_SaveGuardSpot);
package.add("SaveGuardSpot", (void(*)(NPC*, float, float, float, float))&Perl_NPC_SaveGuardSpot);
package.add("ScaleNPC", &Perl_NPC_ScaleNPC);
package.add("ScaleNPC", (void(*)(NPC*, uint8))&Perl_NPC_ScaleNPC);
package.add("ScaleNPC", (void(*)(NPC*, uint8, bool))&Perl_NPC_ScaleNPC);
package.add("SendPayload", (void(*)(NPC*, int))&Perl_NPC_SendPayload);
package.add("SendPayload", (void(*)(NPC*, int, std::string))&Perl_NPC_SendPayload);
package.add("SetCopper", &Perl_NPC_SetCopper);
package.add("SetKeepsSoldItems", &Perl_NPC_SetKeepsSoldItems);
package.add("SetLDoNLocked", &Perl_NPC_SetLDoNLocked);
package.add("SetLDoNLockedSkill", &Perl_NPC_SetLDoNLockedSkill);
package.add("SetLDoNTrapped", &Perl_NPC_SetLDoNTrapped);
package.add("SetLDoNTrapDetected", &Perl_NPC_SetLDoNTrapDetected);
package.add("SetLDoNTrapSpellID", &Perl_NPC_SetLDoNTrapSpellID);
package.add("SetLDoNTrapType", &Perl_NPC_SetLDoNTrapType);
package.add("SetGold", &Perl_NPC_SetGold);
package.add("SetGrid", &Perl_NPC_SetGrid);
package.add("SetNPCFactionID", &Perl_NPC_SetNPCFactionID);
+8 -8
View File
@@ -103,8 +103,8 @@ void QuestParserCollection::RemoveEncounter(const std::string name) {
}
}
bool QuestParserCollection::HasQuestSub(uint32 npcid, QuestEventID evt, bool check_encounters) {
return HasQuestSubLocal(npcid, evt) || HasQuestSubGlobal(evt) || (check_encounters && NPCHasEncounterSub(npcid, evt));
bool QuestParserCollection::HasQuestSub(uint32 npcid, QuestEventID evt) {
return HasQuestSubLocal(npcid, evt) || HasQuestSubGlobal(evt) || NPCHasEncounterSub(npcid, evt);
}
bool QuestParserCollection::NPCHasEncounterSub(uint32 npc_id, QuestEventID evt) {
@@ -162,8 +162,8 @@ bool QuestParserCollection::HasQuestSubGlobal(QuestEventID evt) {
return false;
}
bool QuestParserCollection::PlayerHasQuestSub(QuestEventID evt, bool check_encounters) {
return PlayerHasQuestSubLocal(evt) || PlayerHasQuestSubGlobal(evt) || (check_encounters && PlayerHasEncounterSub(evt));
bool QuestParserCollection::PlayerHasQuestSub(QuestEventID evt) {
return PlayerHasQuestSubLocal(evt) || PlayerHasQuestSubGlobal(evt) || PlayerHasEncounterSub(evt);
}
bool QuestParserCollection::PlayerHasEncounterSub(QuestEventID evt) {
@@ -207,8 +207,8 @@ bool QuestParserCollection::SpellHasEncounterSub(uint32 spell_id, QuestEventID e
return HasEncounterSub(evt, package_name);
}
bool QuestParserCollection::SpellHasQuestSub(uint32 spell_id, QuestEventID evt, bool check_encounters) {
if (check_encounters && SpellHasEncounterSub(spell_id, evt)) {
bool QuestParserCollection::SpellHasQuestSub(uint32 spell_id, QuestEventID evt) {
if (SpellHasEncounterSub(spell_id, evt)) {
return true;
}
@@ -241,11 +241,11 @@ bool QuestParserCollection::ItemHasEncounterSub(EQ::ItemInstance* item, QuestEve
return false;
}
bool QuestParserCollection::ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt, bool check_encounters) {
bool QuestParserCollection::ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt) {
if (itm == nullptr)
return false;
if (check_encounters && ItemHasEncounterSub(itm, evt)) {
if (ItemHasEncounterSub(itm, evt)) {
return true;
}
+4 -4
View File
@@ -67,10 +67,10 @@ public:
void ReloadQuests(bool reset_timers = true);
void RemoveEncounter(const std::string name);
bool HasQuestSub(uint32 npcid, QuestEventID evt, bool check_encounters = false);
bool PlayerHasQuestSub(QuestEventID evt, bool check_encounters = false);
bool SpellHasQuestSub(uint32 spell_id, QuestEventID evt, bool check_encounters = false);
bool ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt, bool check_encounters = false);
bool HasQuestSub(uint32 npcid, QuestEventID evt);
bool PlayerHasQuestSub(QuestEventID evt);
bool SpellHasQuestSub(uint32 spell_id, QuestEventID evt);
bool ItemHasQuestSub(EQ::ItemInstance *itm, QuestEventID evt);
bool BotHasQuestSub(QuestEventID evt);
int EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data,
+5 -1
View File
@@ -3969,7 +3969,7 @@ bool QuestManager::DoAugmentSlotsMatch(uint32 item_one, uint32 item_two)
return true;
}
int8 QuestManager::DoesAugmentFit(EQ::ItemInstance* inst, uint32 augment_id)
int8 QuestManager::DoesAugmentFit(EQ::ItemInstance* inst, uint32 augment_id, uint8 augment_slot)
{
if (!inst) {
return INVALID_INDEX;
@@ -3980,5 +3980,9 @@ int8 QuestManager::DoesAugmentFit(EQ::ItemInstance* inst, uint32 augment_id)
return INVALID_INDEX;
}
if (augment_slot != 255) {
return !inst->IsAugmentSlotAvailable(aug_inst->AugType, augment_slot) ? INVALID_INDEX : augment_slot;
}
return inst->AvailableAugmentSlot(aug_inst->AugType);
}
+1 -1
View File
@@ -346,7 +346,7 @@ public:
std::string GetRecipeName(uint32 recipe_id);
bool HasRecipeLearned(uint32 recipe_id);
bool DoAugmentSlotsMatch(uint32 item_one, uint32 item_two);
int8 DoesAugmentFit(EQ::ItemInstance* inst, uint32 augment_id);
int8 DoesAugmentFit(EQ::ItemInstance* inst, uint32 augment_id, uint8 augment_slot = 255);
Bot *GetBot() const;
Client *GetInitiator() const;
+21 -5
View File
@@ -3205,8 +3205,10 @@ bool Mob::CheckSpellLevelRestriction(Mob *caster, uint16 spell_id)
// NON GM clients might be restricted by rule setting
if (caster->IsClient()) {
if (RuleB(Spells, BuffLevelRestrictions)) {
check_for_restrictions = true;
if (IsClient()) { // Only restrict client on client for this rule
if (RuleB(Spells, BuffLevelRestrictions)) {
check_for_restrictions = true;
}
}
}
// NPCS might be restricted by rule setting
@@ -6413,7 +6415,7 @@ void Client::SetItemRecastTimer(int32 spell_id, uint32 inventory_slot)
recast_delay = std::max(recast_delay, 0);
if (recast_delay > 0) {
if (recast_type != RECAST_TYPE_UNLINKED_ITEM) {
GetPTimers().Start((pTimerItemStart + recast_type), static_cast<uint32>(recast_delay));
database.UpdateItemRecast(
@@ -6439,14 +6441,14 @@ void Client::SetItemRecastTimer(int32 spell_id, uint32 inventory_slot)
void Client::DeleteItemRecastTimer(uint32 item_id)
{
const auto* d = database.GetItem(item_id);
if (!d) {
return;
}
const auto recast_type = d->RecastType != RECAST_TYPE_UNLINKED_ITEM ? d->RecastType : item_id;
const int timer_id = d->RecastType != RECAST_TYPE_UNLINKED_ITEM ? (pTimerItemStart + recast_type) : (pTimerNegativeItemReuse * item_id);
database.DeleteItemRecast(CharacterID(), recast_type);
GetPTimers().Clear(&database, timer_id);
@@ -7000,3 +7002,17 @@ void Mob::SetHP(int64 hp)
current_hp = hp;
}
void Mob::DrawDebugCoordinateNode(std::string node_name, const glm::vec4 vec)
{
NPC* node = nullptr;
for (const auto& n : entity_list.GetNPCList()) {
if (n.second->GetCleanName() == node_name) {
node = n.second;
break;
}
}
if (!node) {
node = NPC::SpawnNodeNPC(node_name, "", GetPosition());
}
}
+11
View File
@@ -1072,6 +1072,16 @@ void ClientTaskState::RewardTask(Client *c, const TaskInformation *ti, ClientTas
c->AddCrystals(ti->reward_points, 0);
} else if (ti->reward_point_type == static_cast<int32_t>(zone->GetCurrencyID(EBON_CRYSTAL))) {
c->AddCrystals(0, ti->reward_points);
} else {
for (const auto& ac : zone->AlternateCurrencies) {
if (ti->reward_point_type == ac.id) {
const EQ::ItemData *item = database.GetItem(ac.item_id);
if (item) {
c->AddAlternateCurrencyValue(ti->reward_point_type, ti->reward_points);
c->Message(Chat::Yellow, fmt::format("You have received ({}) {}!", ti->reward_points, item->Name).c_str());
}
}
}
}
}
}
@@ -2125,6 +2135,7 @@ void ClientTaskState::AcceptNewTask(
if (npc) {
parse->EventNPC(EVENT_TASK_ACCEPTED, npc, client, export_string, 0);
}
parse->EventPlayer(EVENT_TASK_ACCEPTED, client, export_string, 0);
}
void ClientTaskState::ProcessTaskProximities(Client *client, float x, float y, float z)
+44 -12
View File
@@ -706,9 +706,9 @@ void TaskManager::SharedTaskSelector(Client* client, Mob* mob, const std::vector
validation_failed = true;
auto it = std::find_if(request.members.begin(), request.members.end(),
[&](const SharedTaskMember& member) {
return member.character_id == shared_task_members.front().character_id;
});
[&](const SharedTaskMember& member) {
return member.character_id == shared_task_members.front().character_id;
});
if (it != request.members.end()) {
if (request.group_type == SharedTaskRequestGroupType::Group) {
@@ -761,14 +761,14 @@ bool TaskManager::CanOfferSharedTask(int task_id, const SharedTaskRequest& reque
if (task->min_level > 0 && request.lowest_level < task->min_level)
{
LogTasksDetail("lowest level [{}] is below task [{}] min level [{}]",
request.lowest_level, task_id, task->min_level);
request.lowest_level, task_id, task->min_level);
return false;
}
if (task->max_level > 0 && request.highest_level > task->max_level)
{
LogTasksDetail("highest level [{}] exceeds task [{}] max level [{}]",
request.highest_level, task_id, task->max_level);
request.highest_level, task_id, task->max_level);
return false;
}
@@ -1154,6 +1154,10 @@ void TaskManager::SendActiveTaskDescription(
+ sizeof(TaskDescriptionData1_Struct) + t->description.length() + 1
+ sizeof(TaskDescriptionData2_Struct) + 1 + sizeof(TaskDescriptionTrailer_Struct);
std::string reward = t->reward;
bool is_don_reward = (t->reward_point_type == ALT_CURRENCY_ID_RADIANT ||
t->reward_point_type == ALT_CURRENCY_ID_EBON);
// If there is an item make the reward text into a link to the item (only the first item if a list
// is specified). I have been unable to get multiple item links to work.
//
@@ -1173,7 +1177,34 @@ void TaskManager::SendActiveTaskDescription(
}
}
packet_length += t->reward.length() + 1 + t->item_link.length() + 1;
// display alternate currency in reward window manually
// there may be a more formal packet structure for displaying this but this is what it is for
// now to have bare minimum support
if (t->reward_point_type > 0 && t->reward_points > 0 && !is_don_reward) {
for (const auto& ac : zone->AlternateCurrencies) {
if (t->reward_point_type == ac.id) {
const EQ::ItemData *item = database.GetItem(ac.item_id);
if (item) {
std::string currency_description = fmt::format(
"{} ({})",
item->Name,
t->reward_points
);
reward = currency_description;
EQ::SayLinkEngine l;
l.SetLinkType(EQ::saylink::SayLinkItemData);
l.SetItemData(item);
l.SetTaskUse();
l.SetProxyText(currency_description.c_str());
t->item_link = l.GenerateLink();
}
}
}
}
packet_length += reward.length() + 1 + t->item_link.length() + 1;
char *Ptr;
TaskDescriptionHeader_Struct *task_description_header;
@@ -1190,7 +1221,7 @@ void TaskManager::SendActiveTaskDescription(
task_description_header->open_window = bring_up_task_journal;
task_description_header->task_type = static_cast<uint32>(t->type);
task_description_header->reward_type = t->reward_point_type;
task_description_header->reward_type = is_don_reward ? t->reward_point_type : 0;
Ptr = (char *) task_description_header + sizeof(TaskDescriptionHeader_Struct);
@@ -1224,16 +1255,17 @@ void TaskManager::SendActiveTaskDescription(
// we actually have 2 strings here. One is max length 96 and not parsed for item links
// We actually skipped past that string incorrectly before, so TODO: fix item link string
sprintf(Ptr, "%s", t->reward.c_str());
Ptr += t->reward.length() + 1;
sprintf(Ptr, "%s", reward.c_str());
Ptr += reward.length() + 1;
// second string is parsed for item links
sprintf(Ptr, "%s", t->item_link.c_str());
Ptr += t->item_link.length() + 1;
tdt = (TaskDescriptionTrailer_Struct *) Ptr;
// shared tasks show radiant/ebon crystal reward, non-shared tasks show generic points
tdt->Points = t->reward_points;
tdt->Points = is_don_reward ? t->reward_points : 0;
tdt->has_reward_selection = 0; // TODO: new rewards window
@@ -1720,7 +1752,7 @@ void TaskManager::SyncClientSharedTaskRemoveLocalIfNotExists(Client *c, ClientTa
CharacterActivitiesRepository::DeleteWhere(database, delete_where);
c->MessageString(Chat::Yellow, TaskStr::NO_LONGER_MEMBER_TITLE,
m_task_data[cts->m_active_shared_task.task_id].title.c_str());
m_task_data[cts->m_active_shared_task.task_id].title.c_str());
// remove as active task if doesn't exist
cts->m_active_shared_task = {};
@@ -1830,7 +1862,7 @@ bool TaskManager::IsActiveTaskComplete(ClientTaskInformation& client_task)
for (int i = 0; i < task_data->activity_count; ++i)
{
if (client_task.activity[i].activity_state != ActivityCompleted &&
!task_data->activity_information[i].optional)
!task_data->activity_information[i].optional)
{
return false;
}
+1 -1
View File
@@ -59,7 +59,7 @@ void Object::HandleAugmentation(Client* user, const AugmentItem_Struct* in_augme
inst = user_inv.GetItem(in_augment->container_slot);
if (inst) {
const EQ::ItemData* item = inst->GetItem();
if (item && inst->IsType(EQ::item::ItemClassBag) && item->BagType == EQ::item::BagTypeAugmentationSealer) { // We have found an appropriate inventory augmentation sealer
if (item && inst->IsType(EQ::item::ItemClassBag) && (item->BagType == EQ::item::BagTypeAugmentationSealer || item->BagType == RuleI(Inventory, AlternateAugmentationSealer))) { // We have found an appropriate inventory augmentation sealer
container = inst;
// Verify that no more than two items are in container to guarantee no inadvertant wipes.
+1 -1
View File
@@ -875,7 +875,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
}
bool quest_npc = false;
if (parse->HasQuestSub(tradingWith->GetNPCTypeID(), EVENT_TRADE, true)) {
if (parse->HasQuestSub(tradingWith->GetNPCTypeID(), EVENT_TRADE)) {
// This is a quest NPC
quest_npc = true;
}
+10 -10
View File
@@ -1040,16 +1040,16 @@ int64 Mob::TuneACSum(bool skip_caps, int ac_override, int add_ac)
}
int shield_ac = 0;
if (HasShieldEquiped() && IsClient()) {
auto client = CastToClient();
auto inst = client->GetInv().GetItem(EQ::invslot::slotSecondary);
if (HasShieldEquiped() && (IsClient() || IsBot())) {
auto inst = (IsClient()) ? GetInv().GetItem(EQ::invslot::slotSecondary) : CastToBot()->GetBotItem(EQ::invslot::slotSecondary);
if (inst) {
if (inst->GetItemRecommendedLevel(true) <= GetLevel())
if (inst->GetItemRecommendedLevel(true) <= GetLevel()) {
shield_ac = inst->GetItemArmorClass(true);
else
shield_ac = client->CalcRecommendedLevelBonus(GetLevel(), inst->GetItemRecommendedLevel(true), inst->GetItemArmorClass(true));
} else {
shield_ac = CalcRecommendedLevelBonus(GetLevel(), inst->GetItemRecommendedLevel(true),inst->GetItemArmorClass(true));
}
}
shield_ac += client->GetHeroicSTR() / 10;
shield_ac += GetHeroicSTR() / 10;
}
// EQ math
ac = (ac * 4) / 3;
@@ -1490,15 +1490,15 @@ void Mob::TuneCommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraA
hit.damage_done = min_mod;
hit.damage_done += hit.min_damage;
if (IsClient()) {
if (IsClient() || IsBot()) {
int extra = 0;
switch (hit.skill) {
case EQ::skills::SkillThrowing:
case EQ::skills::SkillArchery:
extra = CastToClient()->GetHeroicDEX() / 10;
extra = GetHeroicDEX() / 10;
break;
default:
extra = CastToClient()->GetHeroicSTR() / 10;
extra = GetHeroicSTR() / 10;
break;
}
hit.damage_done += extra;
+24 -7
View File
@@ -771,17 +771,15 @@ float Mob::GetFixedZ(const glm::vec3 &destination, int32 z_find_offset) {
float new_z = destination.z;
if (zone->HasMap()) {
if (flymode == GravityBehavior::Flying)
if (flymode == GravityBehavior::Flying) {
return new_z;
}
if (zone->HasWaterMap() && zone->watermap->InLiquid(glm::vec3(m_Position)))
if (zone->HasWaterMap() && zone->watermap->InLiquid(glm::vec3(m_Position))) {
return new_z;
}
/*
* Any more than 5 in the offset makes NPC's hop/snap to ceiling in small corridors
*/
new_z = FindDestGroundZ(destination, z_find_offset);
new_z = FindDestGroundZ(destination, (-GetZOffset() / 2));
if (new_z != BEST_Z_INVALID) {
new_z += GetZOffset();
@@ -790,6 +788,20 @@ float Mob::GetFixedZ(const glm::vec3 &destination, int32 z_find_offset) {
}
}
// prevent ceiling clipping
// if client is close in distance (not counting Z) and we clipped up into a ceiling
// this helps us snap back down (or up) if it were to happen
// other fixes were put in place to prevent clipping into the ceiling to begin with
if (std::abs(new_z - m_Position.z) > 15) {
LogFixZ("TRIGGER clipping detection");
auto t = GetTarget();
if (t && DistanceNoZ(GetPosition(), t->GetPosition()) < 20) {
new_z = FindDestGroundZ(t->GetPosition(), -t->GetZOffset());
new_z += GetZOffset();
GMMove(t->GetPosition().x, t->GetPosition().y, new_z, t->GetPosition().w);
}
}
auto duration = timer.elapsed();
LogFixZ("[{}] returned [{}] at [{}] [{}] [{}] - Took [{}]",
@@ -833,6 +845,10 @@ void Mob::FixZ(int32 z_find_offset /*= 5*/, bool fix_client_z /*= false*/) {
}
m_Position.z = new_z;
if (RuleB(Map, MobPathingVisualDebug)) {
DrawDebugCoordinateNode(fmt::format("{} new fixed z node", GetCleanName()), GetPosition());
}
}
else {
if (RuleB(Map, MobZVisualDebug)) {
@@ -928,6 +944,7 @@ float Mob::GetZOffset() const {
case RACE_RABBIT_668:
offset = 5.0f;
break;
case RACE_WURM_158:
case RACE_BLIND_DREAMER_669:
offset = 7.0f;
break;
+4 -27
View File
@@ -1904,6 +1904,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
if (zone && zone->IsLoaded()) {
zone->SendReloadMessage("Alternate Advancement Data");
zone->LoadAlternateAdvancement();
entity_list.SendAlternateAdvancementStats();
}
break;
}
@@ -1938,16 +1939,6 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
content_service.SetExpansionContext()->ReloadContentFlags();
break;
}
case ServerOP_ReloadDoors:
{
if (zone && zone->IsLoaded()) {
zone->SendReloadMessage("Doors");
entity_list.RemoveAllDoors();
zone->LoadZoneDoors();
entity_list.RespawnAllDoors();
}
break;
}
case ServerOP_ReloadDzTemplates:
{
if (zone)
@@ -1957,14 +1948,6 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
}
break;
}
case ServerOP_ReloadGroundSpawns:
{
if (zone && zone->IsLoaded()) {
zone->SendReloadMessage("Ground Spawns");
zone->LoadGroundSpawns();
}
break;
}
case ServerOP_ReloadLevelEXPMods:
{
if (zone && zone->IsLoaded()) {
@@ -1994,15 +1977,6 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
}
break;
}
case ServerOP_ReloadObjects:
{
if (zone && zone->IsLoaded()) {
zone->SendReloadMessage("Objects");
entity_list.RemoveAllObjects();
zone->LoadZoneObjects();
}
break;
}
case ServerOP_ReloadPerlExportSettings:
{
zone->SendReloadMessage("Perl Event Export Settings");
@@ -2015,6 +1989,9 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset(), true);
break;
}
case ServerOP_ReloadDoors:
case ServerOP_ReloadGroundSpawns:
case ServerOP_ReloadObjects:
case ServerOP_ReloadStaticZoneData: {
if (zone && zone->IsLoaded()) {
zone->SendReloadMessage("Static Zone Data");
+40 -46
View File
@@ -59,6 +59,7 @@
#include "zone_reload.h"
#include "../common/repositories/criteria/content_filter_criteria.h"
#include "../common/repositories/content_flags_repository.h"
#include "../common/repositories/merchantlist_repository.h"
#include "../common/repositories/rule_sets_repository.h"
#include "../common/repositories/zone_points_repository.h"
#include "../common/serverinfo.h"
@@ -611,45 +612,34 @@ void Zone::LoadNewMerchantData(uint32 merchantid) {
std::list<MerchantList> merchant_list;
auto query = fmt::format(
SQL(
SELECT
item,
slot,
faction_required,
level_required,
alt_currency_cost,
classes_required,
probability,
bucket_name,
bucket_value,
bucket_comparison
FROM merchantlist
WHERE merchantid = {} {}
ORDER BY slot
),
merchantid,
ContentFilterCriteria::apply()
const auto& l = MerchantlistRepository::GetWhere(
content_db,
fmt::format(
"merchantid = {} {} ORDER BY slot",
merchantid,
ContentFilterCriteria::apply()
)
);
auto results = content_db.QueryDatabase(query);
if (!results.Success()) {
return;
if (l.empty()) {
return;
}
for (auto row : results) {
for (const auto& e : l) {
MerchantList ml;
ml.id = merchantid;
ml.item = std::stoul(row[0]);
ml.slot = std::stoul(row[1]);
ml.faction_required = static_cast<int16>(std::stoi(row[2]));
ml.level_required = static_cast<uint8>(std::stoul(row[3]));
ml.alt_currency_cost = static_cast<uint16>(std::stoul(row[4]));
ml.classes_required = std::stoul(row[5]);
ml.probability = static_cast<uint8>(std::stoul(row[6]));
ml.bucket_name = row[7];
ml.bucket_value = row[8];
ml.bucket_comparison = static_cast<uint8>(std::stoul(row[9]));
ml.id = merchantid;
ml.item = e.item;
ml.slot = e.slot;
ml.faction_required = e.faction_required;
ml.level_required = e.level_required;
ml.min_status = e.min_status;
ml.max_status = e.max_status;
ml.alt_currency_cost = e.alt_currency_cost;
ml.classes_required = e.classes_required;
ml.probability = e.probability;
ml.bucket_name = e.bucket_name;
ml.bucket_value = e.bucket_value;
ml.bucket_comparison = e.bucket_comparison;
merchant_list.push_back(ml);
}
@@ -665,6 +655,8 @@ void Zone::GetMerchantDataForZoneLoad() {
item,
faction_required,
level_required,
min_status,
max_status,
alt_currency_cost,
classes_required,
probability,
@@ -725,16 +717,18 @@ void Zone::GetMerchantDataForZoneLoad() {
continue;
}
mle.slot = std::stoul(row[1]);
mle.item = std::stoul(row[2]);
mle.faction_required = static_cast<int16>(std::stoi(row[3]));
mle.level_required = static_cast<uint8>(std::stoul(row[4]));
mle.alt_currency_cost = static_cast<uint16>(std::stoul(row[5]));
mle.classes_required = std::stoul(row[6]);
mle.probability = static_cast<uint8>(std::stoul(row[7]));
mle.bucket_name = row[8];
mle.bucket_value = row[9];
mle.bucket_comparison = static_cast<uint8>(std::stoul(row[10]));
mle.slot = std::stoul(row[1]);
mle.item = std::stoul(row[2]);
mle.faction_required = static_cast<int16>(std::stoi(row[3]));
mle.level_required = static_cast<uint8>(std::stoul(row[4]));
mle.min_status = static_cast<uint8>(std::stoul(row[5]));
mle.max_status = static_cast<uint8>(std::stoul(row[6]));
mle.alt_currency_cost = static_cast<uint16>(std::stoul(row[7]));
mle.classes_required = std::stoul(row[8]);
mle.probability = static_cast<uint8>(std::stoul(row[9]));
mle.bucket_name = row[10];
mle.bucket_value = row[11];
mle.bucket_comparison = static_cast<uint8>(std::stoul(row[12]));
merchant_list->second.push_back(mle);
}
@@ -1237,6 +1231,8 @@ bool Zone::Init(bool is_static) {
void Zone::ReloadStaticData() {
LogInfo("Reloading Zone Static Data");
entity_list.RemoveAllObjects(); //Ground spawns are also objects we clear list then fill it
entity_list.RemoveAllDoors(); //Some objects are also doors so clear list before filling
if (!content_db.LoadStaticZonePoints(&zone_point_list, GetShortName(), GetInstanceVersion())) {
LogError("Loading static zone points failed");
@@ -1255,14 +1251,12 @@ void Zone::ReloadStaticData() {
LogError("Reloading ground spawns failed. continuing");
}
entity_list.RemoveAllObjects();
LogInfo("Reloading World Objects from DB");
if (!LoadZoneObjects())
{
LogError("Reloading World Objects failed. continuing");
}
entity_list.RemoveAllDoors();
LoadZoneDoors();
entity_list.RespawnAllDoors();
+1 -1
View File
@@ -2094,7 +2094,7 @@ const NPCType *ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load
}
}
t->see_invis = n.see_invis != 0;
t->see_invis = n.see_invis;
t->see_invis_undead = n.see_invis_undead != 0; // Set see_invis_undead flag
if (!RuleB(NPC, DisableLastNames) && !n.lastname.empty()) {