[Quest API] Add EVENT_CHARM_START and EVENT_CHARM_END (#5013)

This commit is contained in:
Alex King 2025-09-15 09:14:46 -04:00 committed by GitHub
parent dcaa0ecdaa
commit 6506ad5b51
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 56 additions and 55 deletions

View File

@ -208,6 +208,8 @@ const char* QuestEventSubroutines[_LargestEventID] = {
"EVENT_SPELL_BLOCKED",
"EVENT_READ_ITEM",
"EVENT_PET_COMMAND",
"EVENT_CHARM_START",
"EVENT_CHARM_END",
// Add new events before these or Lua crashes
"EVENT_SPELL_EFFECT_BOT",

View File

@ -146,6 +146,8 @@ typedef enum {
EVENT_SPELL_BLOCKED,
EVENT_READ_ITEM,
EVENT_PET_COMMAND,
EVENT_CHARM_START,
EVENT_CHARM_END,
// Add new events before these or Lua crashes
EVENT_SPELL_EFFECT_BOT,

View File

@ -6992,7 +6992,9 @@ luabind::scope lua_register_events() {
luabind::value("entity_variable_update", static_cast<int>(EVENT_ENTITY_VARIABLE_UPDATE)),
luabind::value("aa_loss", static_cast<int>(EVENT_AA_LOSS)),
luabind::value("read", static_cast<int>(EVENT_READ_ITEM)),
luabind::value("pet_command", static_cast<int>(EVENT_PET_COMMAND))
luabind::value("pet_command", static_cast<int>(EVENT_PET_COMMAND)),
luabind::value("charm_start", static_cast<int>(EVENT_CHARM_START)),
luabind::value("charm_end", static_cast<int>(EVENT_CHARM_END))
)];
}

View File

@ -189,7 +189,9 @@ const char *LuaEvents[_LargestEventID] = {
"event_aa_loss",
"event_spell_blocked",
"event_read_item",
"event_pet_command"
"event_pet_command",
"event_charm_start",
"event_charm_end"
};
extern Zone *zone;
@ -266,6 +268,8 @@ LuaParser::LuaParser() {
NPCArgumentDispatch[EVENT_ENTITY_VARIABLE_UPDATE] = handle_npc_entity_variable;
NPCArgumentDispatch[EVENT_SPELL_BLOCKED] = handle_npc_spell_blocked;
NPCArgumentDispatch[EVENT_PET_COMMAND] = handle_npc_pet_command;
NPCArgumentDispatch[EVENT_CHARM_START] = handle_npc_single_mob;
NPCArgumentDispatch[EVENT_CHARM_END] = handle_npc_single_mob;
PlayerArgumentDispatch[EVENT_SAY] = handle_player_say;
PlayerArgumentDispatch[EVENT_ENVIRONMENTAL_DAMAGE] = handle_player_environmental_damage;

View File

@ -3285,62 +3285,55 @@ void NPC::DepopSwarmPets()
}
}
void NPC::ModifyStatsOnCharm(bool is_charm_removed)
void NPC::ModifyStatsOnCharm(bool remove_charm, Mob* charmer)
{
if (is_charm_removed) {
if (charm_ac) {
AC = default_ac;
if (!remove_charm && parse->HasQuestSub(GetNPCTypeID(), EVENT_CHARM_START)) {
parse->EventNPC(EVENT_CHARM_START, this, charmer, "", 0);
} else if (remove_charm && parse->HasQuestSub(GetNPCTypeID(), EVENT_CHARM_END)) {
parse->EventNPC(EVENT_CHARM_END, this, charmer, "", 0);
}
if (charm_attack_delay) {
attack_delay = default_attack_delay;
const int new_ac = remove_charm ? default_ac : charm_ac;
const int new_attack_delay = remove_charm ? default_attack_delay : charm_attack_delay;
const int new_accuracy_rating = remove_charm ? default_accuracy_rating : charm_accuracy_rating;
const int new_avoidance_rating = remove_charm ? default_avoidance_rating : charm_avoidance_rating;
const int new_atk = remove_charm ? default_atk : charm_atk;
const int new_min_dmg = remove_charm ? default_min_dmg : charm_min_dmg;
const int new_max_dmg = remove_charm ? default_max_dmg : charm_max_dmg;
if (new_ac) {
AC = new_ac;
}
if (charm_accuracy_rating) {
accuracy_rating = default_accuracy_rating;
if (new_attack_delay) {
attack_delay = new_attack_delay;
}
if (charm_avoidance_rating) {
avoidance_rating = default_avoidance_rating;
if (new_accuracy_rating) {
accuracy_rating = new_accuracy_rating;
}
if (charm_atk) {
ATK = default_atk;
if (new_avoidance_rating) {
avoidance_rating = new_avoidance_rating;
}
if (charm_min_dmg || charm_max_dmg) {
base_damage = round((default_max_dmg - default_min_dmg) / 1.9);
min_damage = default_min_dmg - round(base_damage / 10.0);
if (new_atk) {
ATK = new_atk;
}
if (new_min_dmg || new_max_dmg) {
base_damage = std::round((new_max_dmg - new_min_dmg) / 1.9);
min_damage = new_min_dmg - std::round(base_damage / 10.0);
}
if (RuleB(Spells, CharmDisablesSpecialAbilities)) {
if (remove_charm) {
ProcessSpecialAbilities(default_special_abilities);
}
SetAttackTimer();
CalcAC();
return;
}
if (charm_ac) {
AC = charm_ac;
}
if (charm_attack_delay) {
attack_delay = charm_attack_delay;
}
if (charm_accuracy_rating) {
accuracy_rating = charm_accuracy_rating;
}
if (charm_avoidance_rating) {
avoidance_rating = charm_avoidance_rating;
}
if (charm_atk) {
ATK = charm_atk;
}
if (charm_min_dmg || charm_max_dmg) {
base_damage = round((charm_max_dmg - charm_min_dmg) / 1.9);
min_damage = charm_min_dmg - round(base_damage / 10.0);
}
if (RuleB(Spells, CharmDisablesSpecialAbilities)) {
} else {
ClearSpecialAbilities();
}
}
// the rest of the stats aren't cached, so lets just do these two instead of full CalcBonuses()
SetAttackTimer();
CalcAC();
}

View File

@ -346,7 +346,7 @@ public:
int64 GetNPCHPRegen() const { return hp_regen + itembonuses.HPRegen + spellbonuses.HPRegen; }
inline const char* GetAmmoIDfile() const { return ammo_idfile; }
void ModifyStatsOnCharm(bool is_charm_removed);
void ModifyStatsOnCharm(bool remove_charm, Mob* charmer);
//waypoint crap
int GetMaxWp() const { return max_wp; }

View File

@ -835,12 +835,11 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove
SendAppearancePacket(AppearanceType::Pet, caster->GetID(), true, true);
}
if (IsClient())
{
if (IsClient()) {
CastToClient()->AI_Start();
} else if (IsNPC()) {
CastToNPC()->SetPetSpellID(0); //not a pet spell.
CastToNPC()->ModifyStatsOnCharm(false);
CastToNPC()->ModifyStatsOnCharm(false, caster);
}
bool bBreak = false;
@ -4418,10 +4417,9 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
case SpellEffect::Charm:
{
if(IsNPC())
{
if (IsNPC()) {
CastToNPC()->RestoreGuardSpotCharm();
CastToNPC()->ModifyStatsOnCharm(true);
CastToNPC()->ModifyStatsOnCharm(true, GetOwner());
}
SendAppearancePacket(AppearanceType::Pet, 0, true, true);