diff --git a/changelog.txt b/changelog.txt index 156244941..c0706ac74 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 09/27/2014 == +Kayen: Implemented perl function $mob->GetSpellStat(spell_id, identifier, slot); +Note: identifier is the stat field in spells_new, slot is used for certain effects like effectid, base,base2, max ect. +Example $mob->GetSpellStat(121, "range"); //Returns spell range +Example $mob->GetSpellStat(121, "effectid", 1); //Returns the the value of effectid1 +This will allow you to pull almost all the data for any spell in quest files. + == 09/24/2014 == Uleat: Re-ordered server opcodes and handlers to give them some predictability of location (I need this for the inventory re-enumeration.) demonstar55: Added helper function bool EQEmu::IsTradeskill(uint32 skill) diff --git a/zone/effects.cpp b/zone/effects.cpp index 10748c0e1..7822d2e5e 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -56,7 +56,7 @@ int32 NPC::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { value -= target->GetFcDamageAmtIncoming(this, spell_id)/spells[spell_id].buffduration; } - value += dmg*SpellFocusDMG/100; + value += dmg*GetSpellFocusDMG()/100; if (AI_HasSpellsEffects()){ int16 chance = 0; @@ -275,7 +275,7 @@ int32 NPC::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { //Scale all NPC spell healing via SetSpellFocusHeal(value) - value += value*SpellFocusHeal/100; + value += value*GetSpellFocusHeal()/100; if (target) { value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id); diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index dabc1c46f..869efb019 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -407,8 +407,18 @@ void Lua_NPC::SetSpellFocusHeal(int focus) { self->SetSpellFocusHeal(focus); } -float Lua_NPC::GetSlowMitigation() { +int Lua_NPC::GetSpellFocusDMG() { Lua_Safe_Call_Int(); + return self->GetSpellFocusDMG(); +} + +int Lua_NPC::GetSpellFocusHeal() { + Lua_Safe_Call_Int(); + return self->GetSpellFocusHeal(); +} + +float Lua_NPC::GetSlowMitigation() { + Lua_Safe_Call_Real(); return self->GetSlowMitigation(); } @@ -535,6 +545,8 @@ luabind::scope lua_register_npc() { .def("RemoveAISpell", (void(Lua_NPC::*)(int))&Lua_NPC::RemoveAISpell) .def("SetSpellFocusDMG", (void(Lua_NPC::*)(int))&Lua_NPC::SetSpellFocusDMG) .def("SetSpellFocusHeal", (void(Lua_NPC::*)(int))&Lua_NPC::SetSpellFocusHeal) + .def("GetSpellFocusDMG", (void(Lua_NPC::*)(int))&Lua_NPC::GetSpellFocusDMG) + .def("GetSpellFocusHeal", (void(Lua_NPC::*)(int))&Lua_NPC::GetSpellFocusHeal) .def("GetSlowMitigation", (int(Lua_NPC::*)(void))&Lua_NPC::GetSlowMitigation) .def("GetAttackSpeed", (float(Lua_NPC::*)(void))&Lua_NPC::GetAttackSpeed) .def("GetAccuracyRating", (int(Lua_NPC::*)(void))&Lua_NPC::GetAccuracyRating) diff --git a/zone/lua_npc.h b/zone/lua_npc.h index 7db7f7e4b..2b201f323 100644 --- a/zone/lua_npc.h +++ b/zone/lua_npc.h @@ -107,6 +107,8 @@ public: void RemoveAISpell(int spell_id); void SetSpellFocusDMG(int focus); void SetSpellFocusHeal(int focus); + int GetSpellFocusDMG(); + int GetSpellFocusHeal(); float GetSlowMitigation(); float GetAttackSpeed(); int GetAccuracyRating(); diff --git a/zone/lua_spell.cpp b/zone/lua_spell.cpp index 597982770..e99b9ba84 100644 --- a/zone/lua_spell.cpp +++ b/zone/lua_spell.cpp @@ -419,6 +419,56 @@ bool Lua_Spell::GetAllowRest() { return self->AllowRest; } +bool Lua_Spell::GetInCombat() { + Lua_Safe_Call_Bool(); + return self->InCombat; +} + +bool Lua_Spell::GetOutOfCombat() { + Lua_Safe_Call_Bool(); + return self->OutofCombat; +} + +int Lua_Spell::GetAEMaxTargets() { + Lua_Safe_Call_Int(); + return self->aemaxtargets; +} + +int Lua_Spell::GetMaxTargets() { + Lua_Safe_Call_Int(); + return self->maxtargets; +} + +bool Lua_Spell::GetPersistDeath() { + Lua_Safe_Call_Bool(); + return self->persistdeath; +} + +float Lua_Spell::GetMinDist() { + Lua_Safe_Call_Real(); + return self->min_dist; +} + +float Lua_Spell::GetMinDistMod() { + Lua_Safe_Call_Real(); + return self->min_dist_mod; +} + +float Lua_Spell::GetMaxDist() { + Lua_Safe_Call_Real(); + return self->max_dist; +} + +float Lua_Spell::GetMaxDistMod() { + Lua_Safe_Call_Real(); + return self->max_dist_mod; +} + +float Lua_Spell::GetMinRange() { + Lua_Safe_Call_Real(); + return self->min_range; +} + int Lua_Spell::GetDamageShieldType() { Lua_Safe_Call_Int(); return self->DamageShieldType; @@ -501,6 +551,16 @@ luabind::scope lua_register_spell() { .def("PowerfulFlag", &Lua_Spell::GetPowerfulFlag) .def("CastRestriction", &Lua_Spell::GetCastRestriction) .def("AllowRest", &Lua_Spell::GetAllowRest) + .def("InCombat", &Lua_Spell::GetInCombat) + .def("OutOfCombat", &Lua_Spell::GetOutOfCombat) + .def("AEMaxTargets", &Lua_Spell::GetAEMaxTargets) + .def("MaxTargets", &Lua_Spell::GetMaxTargets) + .def("PersistDeath", &Lua_Spell::GetPersistDeath) + .def("MinDist", &Lua_Spell::GetMinDist) + .def("MinDistMod", &Lua_Spell::GetMinDistMod) + .def("MaxDist", &Lua_Spell::GetMaxDist) + .def("MaxDistMod", &Lua_Spell::GetMaxDistMod) + .def("MinRange", &Lua_Spell::GetMinRange) .def("DamageShieldType", &Lua_Spell::GetDamageShieldType); } diff --git a/zone/lua_spell.h b/zone/lua_spell.h index 9a8435cc5..bfa5a19ed 100644 --- a/zone/lua_spell.h +++ b/zone/lua_spell.h @@ -96,6 +96,16 @@ public: int GetPowerfulFlag(); int GetCastRestriction(); bool GetAllowRest(); + bool GetInCombat(); + bool GetOutOfCombat(); + int GetAEMaxTargets(); + int GetMaxTargets(); + bool GetPersistDeath(); + float GetMinDist(); + float GetMinDistMod(); + float GetMaxDist(); + float GetMaxDistMod(); + float GetMinRange(); int GetDamageShieldType(); }; diff --git a/zone/mob.cpp b/zone/mob.cpp index 06e125aab..8a4253c19 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4993,3 +4993,119 @@ float Mob::HeadingAngleToMob(Mob *other) return (90.0 - angle + 270.0) * 511.5 * 0.0027777778; } +int32 Mob::GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot) +{ + if (!IsValidSpell(spell_id)) + return 0; + + if (!identifier) + return 0; + + int32 stat = 0; + + if (slot > 0) + slot = slot - 1; + + std::string id = identifier; + for(int i = 0; i < id.length(); ++i) + { + id[i] = tolower(id[i]); + } + + if (slot < 16){ + if (id == "classes") {stat = spells[spell_id].classes[slot]; } + else if (id == "dieties") {stat = spells[spell_id].deities[slot];} + } + + if (slot < 12){ + if (id == "base") {stat = spells[spell_id].base[slot];} + else if (id == "base2") {stat = spells[spell_id].base2[slot];} + else if (id == "max") {stat = spells[spell_id].max[slot];} + else if (id == "formula") {spells[spell_id].formula[slot];} + else if (id == "effectid") {spells[spell_id].effectid[slot];} + } + + if (slot < 4){ + if (id == "components") { spells[spell_id].components[slot];} + else if (id == "component_counts") {spells[spell_id].component_counts[slot];} + else if (id == "NoexpendReagent") {spells[spell_id].NoexpendReagent[slot];} + } + + if (id == "range") {stat = spells[spell_id].range; } + else if (id == "aoerange") {stat = spells[spell_id].aoerange;} + else if (id == "pushback") {stat = spells[spell_id].pushback;} + else if (id == "pushup") {stat = spells[spell_id].pushup;} + else if (id == "cast_time") {stat = spells[spell_id].cast_time;} + else if (id == "recovery_time") {stat = spells[spell_id].recovery_time;} + else if (id == "recast_time") {stat = spells[spell_id].recast_time;} + else if (id == "buffdurationformula") {stat = spells[spell_id].buffdurationformula;} + else if (id == "buffduration") {stat = spells[spell_id].buffduration;} + else if (id == "AEDuration") {stat = spells[spell_id].AEDuration;} + else if (id == "mana") {stat = spells[spell_id].mana;} + //else if (id == "LightType") {stat = spells[spell_id].LightType;} - Not implemented + else if (id == "goodEffect") {stat = spells[spell_id].goodEffect;} + else if (id == "Activated") {stat = spells[spell_id].Activated;} + else if (id == "resisttype") {stat = spells[spell_id].resisttype;} + else if (id == "targettype") {stat = spells[spell_id].targettype;} + else if (id == "basedeiff") {stat = spells[spell_id].basediff;} + else if (id == "skill") {stat = spells[spell_id].skill;} + else if (id == "zonetype") {stat = spells[spell_id].zonetype;} + else if (id == "EnvironmentType") {stat = spells[spell_id].EnvironmentType;} + else if (id == "TimeOfDay") {stat = spells[spell_id].TimeOfDay;} + else if (id == "CastingAnim") {stat = spells[spell_id].CastingAnim;} + else if (id == "SpellAffectIndex") {stat = spells[spell_id].SpellAffectIndex; } + else if (id == "disallow_sit") {stat = spells[spell_id].disallow_sit; } + //else if (id == "spellanim") {stat = spells[spell_id].spellanim; } - Not implemented + else if (id == "uninterruptable") {stat = spells[spell_id].uninterruptable; } + else if (id == "ResistDiff") {stat = spells[spell_id].ResistDiff; } + else if (id == "dot_stacking_exemp") {stat = spells[spell_id].dot_stacking_exempt; } + else if (id == "RecourseLink") {stat = spells[spell_id].RecourseLink; } + else if (id == "no_partial_resist") {stat = spells[spell_id].no_partial_resist; } + else if (id == "short_buff_box") {stat = spells[spell_id].short_buff_box; } + else if (id == "descnum") {stat = spells[spell_id].descnum; } + else if (id == "effectdescnum") {stat = spells[spell_id].effectdescnum; } + else if (id == "npc_no_los") {stat = spells[spell_id].npc_no_los; } + else if (id == "reflectable") {stat = spells[spell_id].reflectable; } + else if (id == "bonushate") {stat = spells[spell_id].bonushate; } + else if (id == "EndurCost") {stat = spells[spell_id].EndurCost; } + else if (id == "EndurTimerIndex") {stat = spells[spell_id].EndurTimerIndex; } + else if (id == "IsDisciplineBuf") {stat = spells[spell_id].IsDisciplineBuff; } + else if (id == "HateAdded") {stat = spells[spell_id].HateAdded; } + else if (id == "EndurUpkeep") {stat = spells[spell_id].EndurUpkeep; } + else if (id == "numhitstype") {stat = spells[spell_id].numhitstype; } + else if (id == "numhits") {stat = spells[spell_id].numhits; } + else if (id == "pvpresistbase") {stat = spells[spell_id].pvpresistbase; } + else if (id == "pvpresistcalc") {stat = spells[spell_id].pvpresistcalc; } + else if (id == "pvpresistcap") {stat = spells[spell_id].pvpresistcap; } + else if (id == "spell_category") {stat = spells[spell_id].spell_category; } + else if (id == "can_mgb") {stat = spells[spell_id].can_mgb; } + else if (id == "dispel_flag") {stat = spells[spell_id].dispel_flag; } + else if (id == "MinResist") {stat = spells[spell_id].MinResist; } + else if (id == "MaxResist") {stat = spells[spell_id].MaxResist; } + else if (id == "viral_targets") {stat = spells[spell_id].viral_targets; } + else if (id == "viral_timer") {stat = spells[spell_id].viral_timer; } + else if (id == "NimbusEffect") {stat = spells[spell_id].NimbusEffect; } + else if (id == "directional_start") {stat = spells[spell_id].directional_start; } + else if (id == "directional_end") {stat = spells[spell_id].directional_end; } + else if (id == "not_extendable") {stat = spells[spell_id].not_extendable; } + else if (id == "suspendable") {stat = spells[spell_id].suspendable; } + else if (id == "viral_range") {stat = spells[spell_id].viral_range; } + else if (id == "spellgroup") {stat = spells[spell_id].spellgroup; } + else if (id == "rank") {stat = spells[spell_id].rank; } + else if (id == "powerful_flag") {stat = spells[spell_id].powerful_flag; } + else if (id == "CastRestriction") {stat = spells[spell_id].CastRestriction; } + else if (id == "AllowRest") {stat = spells[spell_id].AllowRest; } + else if (id == "InCombat") {stat = spells[spell_id].InCombat; } + else if (id == "OutofCombat") {stat = spells[spell_id].OutofCombat; } + else if (id == "aemaxtargets") {stat = spells[spell_id].aemaxtargets; } + else if (id == "maxtargets") {stat = spells[spell_id].maxtargets; } + else if (id == "persistdeath") {stat = spells[spell_id].persistdeath; } + else if (id == "min_dist") {stat = spells[spell_id].min_dist; } + else if (id == "min_dist_mod") {stat = spells[spell_id].min_dist_mod; } + else if (id == "max_dist") {stat = spells[spell_id].max_dist; } + else if (id == "min_range") {stat = spells[spell_id].min_range; } + else if (id == "DamageShieldType") {stat = spells[spell_id].DamageShieldType; } + + return stat; +} + diff --git a/zone/mob.h b/zone/mob.h index cf6a032e5..2617e98e2 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -620,6 +620,7 @@ public: void CalcSpellPowerDistanceMod(uint16 spell_id, float range, Mob* caster = nullptr); inline int16 GetSpellPowerDistanceMod() const { return SpellPowerDistanceMod; }; inline void SetSpellPowerDistanceMod(int16 value) { SpellPowerDistanceMod = value; }; + int32 GetSpellStat(uint32 spell_id, const char *identifier, uint8 slot = 0); void ModSkillDmgTaken(SkillUseTypes skill_num, int value); int16 GetModSkillDmgTaken(const SkillUseTypes skill_num); diff --git a/zone/npc.h b/zone/npc.h index b23522bee..f1e4c790c 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -136,10 +136,6 @@ public: int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr); int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr); - inline void SetSpellFocusDMG(int32 NewSpellFocusDMG) {SpellFocusDMG = NewSpellFocusDMG;} - inline void SetSpellFocusHeal(int32 NewSpellFocusHeal) {SpellFocusHeal = NewSpellFocusHeal;} - int32 SpellFocusDMG; - int32 SpellFocusHeal; virtual void SetTarget(Mob* mob); virtual uint16 GetSkill(SkillUseTypes skill_num) const { if (skill_num <= HIGHEST_SKILL) { return skills[skill_num]; } return 0; } @@ -387,6 +383,12 @@ public: inline void SetHealScale(float amt) { healscale = amt; } inline float GetHealScale() { return healscale; } + + inline void SetSpellFocusDMG(int32 NewSpellFocusDMG) {SpellFocusDMG = NewSpellFocusDMG;} + inline int32 GetSpellFocusDMG() const { return SpellFocusDMG;} + + inline void SetSpellFocusHeal(int32 NewSpellFocusHeal) {SpellFocusHeal = NewSpellFocusHeal;} + inline int32 GetSpellFocusHeal() const {return SpellFocusHeal;} uint32 GetSpawnKillCount(); int GetScore(); @@ -452,6 +454,8 @@ protected: uint32 npc_mana; float spellscale; float healscale; + int32 SpellFocusDMG; + int32 SpellFocusHeal; //pet crap: uint16 pet_spell_id; diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 53a5aade8..762246519 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -8137,6 +8137,39 @@ XS(XS_Mob_GetFlurryChance) XSRETURN(1); } +XS(XS_Mob_GetSpellStat); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Mob_GetSpellStat) +{ + dXSARGS; + if (items < 3 || items > 4) + Perl_croak(aTHX_ "Usage: Mob::GetSpellStat(THIS, itemid, stat, slot)"); + { + Mob * THIS; + int32 RETVAL; + uint32 spellid = (uint32)SvUV(ST(1)); + Const_char * stat = (Const_char *)SvPV_nolen(ST(2)); + uint8 slot = (uint8)SvUV(ST(3)); + dXSTARG; + + if (sv_derived_from(ST(0), "Mob")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Mob *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Mob"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + if (items > 4) { slot = 0; } + + + RETVAL = THIS->GetSpellStat(spellid, stat, slot); + XSprePUSH; PUSHi((IV)RETVAL); + } + XSRETURN(1); +} + + #ifdef __cplusplus extern "C" #endif @@ -8436,6 +8469,7 @@ XS(boot_Mob) newXSproto(strcpy(buf, "IsMeleeDisabled"), XS_Mob_IsMeleeDisabled, file, "$$"); newXSproto(strcpy(buf, "SetFlurryChance"), XS_Mob_SetFlurryChance, file, "$$"); newXSproto(strcpy(buf, "GetFlurryChance"), XS_Mob_GetFlurryChance, file, "$"); + newXSproto(strcpy(buf, "GetSpellStat"), XS_Mob_GetSpellStat, file, "$$$$"); XSRETURN_YES; } diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index dcc66b886..c1f8d8828 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -1991,6 +1991,32 @@ XS(XS_NPC_SetSpellFocusDMG) XSRETURN_EMPTY; } +XS(XS_NPC_GetSpellFocusDMG); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSpellFocusDMG) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSpellFocusDMG(THIS)"); + { + NPC * THIS; + int32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetSpellFocusDMG(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + XS(XS_NPC_SetSpellFocusHeal); /* prototype to pass -Wmissing-prototypes */ XS(XS_NPC_SetSpellFocusHeal) { @@ -2015,6 +2041,32 @@ XS(XS_NPC_SetSpellFocusHeal) XSRETURN_EMPTY; } +XS(XS_NPC_GetSpellFocusHeal); /* prototype to pass -Wmissing-prototypes */ +XS(XS_NPC_GetSpellFocusHeal) +{ + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: NPC::GetSpellFocusHeal(THIS)"); + { + NPC * THIS; + int32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "NPC")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(NPC *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type NPC"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->GetSpellFocusHeal(); + XSprePUSH; PUSHu((UV)RETVAL); + } + XSRETURN(1); +} + XS(XS_NPC_GetSlowMitigation); /* prototype to pass -Wmissing-prototypes */ XS(XS_NPC_GetSlowMitigation) { @@ -2286,8 +2338,10 @@ XS(boot_NPC) newXSproto(strcpy(buf, "RemoveAISpell"), XS_NPC_RemoveSpellFromNPCList, file, "$$"); newXSproto(strcpy(buf, "SetSpellFocusDMG"), XS_NPC_SetSpellFocusDMG, file, "$$"); newXSproto(strcpy(buf, "SetSpellFocusHeal"), XS_NPC_SetSpellFocusHeal, file, "$$"); - newXSproto(strcpy(buf, "GetSlowMitigation"), XS_NPC_GetAttackSpeed, file, "$"); - newXSproto(strcpy(buf, "GetAttackSpeed"), XS_NPC_GetSlowMitigation, file, "$"); + newXSproto(strcpy(buf, "GetSpellFocusDMG"), XS_NPC_GetSpellFocusDMG, file, "$"); + newXSproto(strcpy(buf, "GetSpellFocusHeal"), XS_NPC_GetSpellFocusHeal, file, "$"); + newXSproto(strcpy(buf, "GetSlowMitigation"), XS_NPC_GetSlowMitigation, file, "$"); + newXSproto(strcpy(buf, "GetAttackSpeed"), XS_NPC_GetAttackSpeed, file, "$"); newXSproto(strcpy(buf, "GetAccuracyRating"), XS_NPC_GetAccuracyRating, file, "$"); newXSproto(strcpy(buf, "GetSpawnKillCount"), XS_NPC_GetSpawnKillCount, file, "$"); newXSproto(strcpy(buf, "GetScore"), XS_NPC_GetScore, file, "$");