diff --git a/world/console.cpp b/world/console.cpp index 194507663..57161487d 100644 --- a/world/console.cpp +++ b/world/console.cpp @@ -466,6 +466,7 @@ void Console::ProcessCommand(const char* command) { if (admin >= 100) { SendMessage(1, " LSReconnect"); SendMessage(1, " signalcharbyname charname ID"); + SendMessage(1, " reloadworld"); } } else if (strcasecmp(sep.arg[0], "ping") == 0) { @@ -835,6 +836,15 @@ void Console::ProcessCommand(const char* command) { } } } + else if (strcasecmp(sep.arg[0], "reloadworld") == 0 && admin > 101) + { + SendEmoteMessage(0,0,0,15,"Reloading World..."); + ServerPacket* pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct)); + ReloadWorld_Struct* RW = (ReloadWorld_Struct*) pack->pBuffer; + RW->Option = 1; + zoneserver_list.SendPacket(pack); + safe_delete(pack); + } else { SendMessage(1, "Command unknown."); } diff --git a/zone/attack.cpp b/zone/attack.cpp index ee4eaf400..51574b4b9 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1850,7 +1850,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool damage = (max_dmg+eleBane); } - damage = mod_npc_damage(damage, skillinuse, Hand, &weapon_inst, other); + damage = mod_npc_damage(damage, skillinuse, Hand, weapon, other); int32 hate = damage; if(IsPet()) @@ -2114,10 +2114,13 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ski Group *kg = entity_list.GetGroupByClient(give_exp_client); Raid *kr = entity_list.GetRaidByClient(give_exp_client); + int32 finalxp = EXP_FORMULA; + finalxp = give_exp_client->mod_client_xp(finalxp, this); + if(kr) { if(!IsLdonTreasure) { - kr->SplitExp((EXP_FORMULA), this); + kr->SplitExp((finalxp), this); if(killerMob && (kr->IsRaidMember(killerMob->GetName()) || kr->IsRaidMember(killerMob->GetUltimateOwner()->GetName()))) killerMob->TrySpellOnKill(killed_level,spell); } @@ -2158,7 +2161,7 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ski else if (give_exp_client->IsGrouped() && kg != nullptr) { if(!IsLdonTreasure) { - kg->SplitExp((EXP_FORMULA), this); + kg->SplitExp((finalxp), this); if(killerMob && (kg->IsGroupMember(killerMob->GetName()) || kg->IsGroupMember(killerMob->GetUltimateOwner()->GetName()))) killerMob->TrySpellOnKill(killed_level,spell); } @@ -2207,7 +2210,7 @@ bool NPC::Death(Mob* killerMob, int32 damage, uint16 spell, SkillType attack_ski if(GetOwner() && GetOwner()->IsClient()){ } else { - give_exp_client->AddEXP((EXP_FORMULA), conlevel); // Pyro: Comment this if NPC death crashes zone + give_exp_client->AddEXP((finalxp), conlevel); // Pyro: Comment this if NPC death crashes zone if(killerMob && (killerMob->GetID() == give_exp_client->GetID() || killerMob->GetUltimateOwner()->GetID() == give_exp_client->GetID())) killerMob->TrySpellOnKill(killed_level,spell); } diff --git a/zone/client.cpp b/zone/client.cpp index f0ce91056..172d18ea1 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2322,7 +2322,7 @@ bool Client::CheckIncreaseSkill(SkillType skillid, Mob *against_who, int chancem GetLevelCon(against_who->GetLevel()) == CON_GREEN) { //false by default - return mod_can_increase_skill(skillid, against_who); + if( !mod_can_increase_skill(skillid, against_who) ) { return(false); } } } diff --git a/zone/client.h b/zone/client.h index bbf853dc0..7d71f4dba 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1130,7 +1130,7 @@ public: void LoadAccountFlags(); void SetAccountFlag(std::string flag, std::string val); std::string GetAccountFlag(std::string flag); float GetDamageMultiplier(SkillType); - int mod_client_damage(int damage, SkillType skillinuse, int hand, ItemInst* weapon, Mob* other); + int mod_client_damage(int damage, SkillType skillinuse, int hand, const ItemInst* weapon, Mob* other); bool mod_client_message(char* message, uint8 chan_num); bool mod_can_increase_skill(SkillType skillid, Mob* against_who); int16 mod_increase_skill_chance(int16 chance, Mob* against_who); @@ -1142,10 +1142,13 @@ public: int16 mod_pet_power(int16 act_power, uint16 spell_id); float mod_tradeskill_chance(float chance, DBTradeskillRecipe_Struct *spec); float mod_tradeskill_skillup(float chance_stage2); - int32 mod_tribute_item_value(int32 pts); + int32 mod_tribute_item_value(int32 pts, const ItemInst* item); void mod_client_death_npc(Mob* killerMob); void mod_client_death_duel(Mob* killerMob); void mod_client_death_env(); + int32 mod_client_xp(int32 in_exp, NPC *npc); + uint32 mod_client_xp_for_level(uint32 xp, uint16 check_level); + int mod_client_haste_cap(int cap); protected: friend class Mob; diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 73774ca6b..eaab0ba81 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1230,8 +1230,6 @@ int16 Client::CalcSTR() { int16 mod = aabonuses.STR; - if(val>255 && GetLevel() <= 60) - val = 255; STR = val + mod; if(STR < 1) @@ -1249,8 +1247,6 @@ int16 Client::CalcSTA() { int16 mod = aabonuses.STA; - if(val>255 && GetLevel() <= 60) - val = 255; STA = val + mod; if(STA < 1) @@ -1267,9 +1263,6 @@ int16 Client::CalcAGI() { int16 val = m_pp.AGI + itembonuses.AGI + spellbonuses.AGI - CalcAlcoholPhysicalEffect();; int16 mod = aabonuses.AGI; - if(val>255 && GetLevel() <= 60) - val = 255; - int16 str = GetSTR(); //Encumbered penalty @@ -1296,8 +1289,6 @@ int16 Client::CalcDEX() { int16 mod = aabonuses.DEX; - if(val>255 && GetLevel() <= 60) - val = 255; DEX = val + mod; if(DEX < 1) @@ -1315,8 +1306,6 @@ int16 Client::CalcINT() { int16 mod = aabonuses.INT; - if(val>255 && GetLevel() <= 60) - val = 255; INT = val + mod; if(m_pp.intoxication) @@ -1344,8 +1333,6 @@ int16 Client::CalcWIS() { int16 mod = aabonuses.WIS; - if(val>255 && GetLevel() <= 60) - val = 255; WIS = val + mod; if(m_pp.intoxication) @@ -1373,8 +1360,6 @@ int16 Client::CalcCHA() { int16 mod = aabonuses.CHA; - if(val>255 && GetLevel() <= 60) - val = 255; CHA = val + mod; if(CHA < 1) @@ -1412,6 +1397,8 @@ int Client::CalcHaste() { cap = RuleI(Character, HasteCap); } + cap = mod_client_haste_cap(cap); + if(h > cap) h = cap; h += spellbonuses.hastetype3; diff --git a/zone/exp.cpp b/zone/exp.cpp index b05aa3608..95cbcb5e6 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -485,7 +485,10 @@ uint32 Client::GetEXPForLevel(uint16 check_level) mod *= 1000; - return(uint32(base * mod)); + uint32 finalxp = uint32(base * mod); + finalxp = mod_client_xp_for_level(finalxp, check_level); + + return(finalxp); } void Client::AddLevelBasedExp(uint8 exp_percentage, uint8 max_level) { diff --git a/zone/mob.h b/zone/mob.h index d370c10da..1f982a0fc 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -808,13 +808,14 @@ public: int32 mod_monk_special_damage(int32 ndamage, SkillType skill_type); int32 mod_backstab_damage(int32 ndamage); int mod_archery_bonus_chance(int bonuschance, const ItemInst* RangeWeapon); - uint32 mod_archery_bonus_damage(uint32 MaxDmg); - int32 mod_archery_damage(int32 TotalDmg, bool hasbonus); + uint32 mod_archery_bonus_damage(uint32 MaxDmg, const ItemInst* RangeWeapon); + int32 mod_archery_damage(int32 TotalDmg, bool hasbonus, const ItemInst* RangeWeapon); uint16 mod_throwing_damage(uint16 MaxDmg); int32 mod_cast_time(int32 cast_time); int mod_buff_duration(int res, Mob* caster, Mob* target, uint16 spell_id); int mod_spell_stack(uint16 spellid1, int caster_level1, Mob* caster1, uint16 spellid2, int caster_level2, Mob* caster2); int mod_spell_resist(int resist_chance, int level_mod, int resist_modifier, int target_resist, uint8 resist_type, uint16 spell_id, Mob* caster); + void mod_spell_cast(uint16 spell_id, Mob* spelltar, bool reflect, bool use_resist_adjust, int16 resist_adjust, bool isproc); protected: void CommonDamage(Mob* other, int32 &damage, const uint16 spell_id, const SkillType attack_skill, bool &avoidable, const int8 buffslot, const bool iBuffTic); diff --git a/zone/mod_functions.cpp b/zone/mod_functions.cpp index c2599c547..bf559d733 100644 --- a/zone/mod_functions.cpp +++ b/zone/mod_functions.cpp @@ -13,6 +13,8 @@ #include "client.h" #include "worldserver.h" #include "QuestParserCollection.h" +#include "event_codes.h" +#include "embparser.h" #include #include @@ -21,50 +23,169 @@ extern Zone* zone; extern WorldServer worldserver; +//All functions that modify a value are passed the value as it was computed by default formulas and bonuses. In most cases this should be the final value that will be used. + +//These are called when a zone boots or is repopped void Zone::mod_init() { return; } void Zone::mod_repop() { return; } +//Pre-spawn hook called from the NPC object to be spawned void NPC::mod_prespawn(Spawn2 *sp) { return; } -int NPC::mod_npc_damage(int damage, SkillType skillinuse, int hand, ItemInst* weapon, Mob* other) { return(damage); } + +//Base damage from NPC::Attack +int NPC::mod_npc_damage(int damage, SkillType skillinuse, int hand, const Item_Struct* weapon, Mob* other) { return(damage); } + +//Mob c has been given credit for a kill. This is called after the regular EVENT_KILLED_MERIT event. void NPC::mod_npc_killed_merit(Mob* c) { return; } + +//Mob oos has been given credit for a kill. This is called after the regular EVENT_DEATH event. void NPC::mod_npc_killed(Mob* oos) { return; } -int Client::mod_client_damage(int damage, SkillType skillinuse, int hand, ItemInst* weapon, Mob* other) { return(damage); } -bool Client::mod_client_message(char* message, uint8 chan_num) { return(true); } //Potentially dangerous string handling here +//Base damage from Client::Attack - can cover myriad skill types +int Client::mod_client_damage(int damage, SkillType skillinuse, int hand, const ItemInst* weapon, Mob* other) { return(damage); } + +//message is char[4096], don't screw it up. Return true for normal behavior, false to return immediately. +// Channels: +// 0 - Guild Chat +// 2 - Group Chat +// 3 - Shout +// 4 - Auction +// 5 - Out of Character +// 6 - Broadcast +// 7 - Tell +// 8 - Say +// 11 - GMSay +// 15 - Raid Chat +// 20 - UCS Relay for UF client and later +// 22 - Emotes for UF and later +bool Client::mod_client_message(char* message, uint8 chan_num) { return(true); } + +//Skillup override. When this is called the regular skillup check has failed. Return false to proceed with default behavior. +//This will NOT allow a client to increase skill past a cap. bool Client::mod_can_increase_skill(SkillType skillid, Mob* against_who) { return(false); } + +//chance of general skill increase, rolled against 0-99 where higher chance is better. int16 Client::mod_increase_skill_chance(int16 chance, Mob* against_who) { return(chance); } + +//Max percent of health you can bind wound starting with default value for class, item, and AA bonuses int Client::mod_bindwound_percent(int max_percent, Mob* bindmob) { return(max_percent); } + +//Final bind HP value after bonuses int Client::mod_bindwound_hp(int bindhps, Mob* bindmob) { return(bindhps); } + +//Client haste as calculated by default formulas - In percent from 0-100 int Client::mod_client_haste(int h) { return(h); } + +//Haste cap override +int Client::mod_client_haste_cap(int cap) { return(cap); } + +//This is called when a client cons a mob void Client::mod_consider(Mob* tmob, Consider_Struct* con) { return; } -bool Client::mod_saylink(const std::string&, bool silentsaylink) { return(true); } + +//Return true to continue with normal behavior, false returns in the parent function +bool Client::mod_saylink(const std::string& response, bool silentsaylink) { return(true); } + +//Client pet power as calculated by default formulas and bonuses int16 Client::mod_pet_power(int16 act_power, uint16 spell_id) { return(act_power); } + +//Chance to combine rolled against a random 0-99 where higher is better. float Client::mod_tradeskill_chance(float chance, DBTradeskillRecipe_Struct *spec) { return(chance); } + +//Chance to skillup rolled against a random 0-99 where higher is better. float Client::mod_tradeskill_skillup(float chance_stage2) { return(chance_stage2); } -int32 Client::mod_tribute_item_value(int32 pts) { return(pts); } + +//Tribute value override +int32 Client::mod_tribute_item_value(int32 pts, const ItemInst* item) { return(pts); } + +//Death reporting void Client::mod_client_death_npc(Mob* killerMob) { return; } void Client::mod_client_death_duel(Mob* killerMob) { return; } void Client::mod_client_death_env() { return; } +//Calculated xp before consider modifier, called whenever a client gets XP for killing a mob. +int32 Client::mod_client_xp(int32 in_xp, NPC *npc) { return(in_xp); } + +//Client XP formula. Changes here will cause clients to change level after gaining or losing xp. +//Either modify this before your server goes live, or be prepared to write a quest script that fixes levels. +//To adjust how much XP is given per kill, use mod_client_xp +uint32 Client::mod_client_xp_for_level(uint32 xp, uint16 check_level) { return(xp); } + +//effect_vallue - Spell effect value as calculated by default formulas. You will want to ignore effects that don't lend themselves to scaling - pet ID's, gate coords, etc. int Mob::mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster) { return(effect_value); } + +//chancetohit - 0 to 100 percent - set over 1000 for a guaranteed hit float Mob::mod_hit_chance(float chancetohit, SkillType skillinuse, Mob* attacker) { return(chancetohit); } + +//Final riposte chance float Mob::mod_riposte_chance(float ripostechance, Mob* attacker) { return(ripostechance); } + +//Final block chance float Mob::mod_block_chance(float blockchance, Mob* attacker) { return(blockchance); } + +//Final parry chance float Mob::mod_parry_chance(float parrychance, Mob* attacker) { return(parrychance); } + +//Final dodge chance float Mob::mod_dodge_chance(float dodgechance, Mob* attacker) { return(dodgechance); } + +//Monk AC Bonus weight cap. Defined in Combat:MonkACBonusWeight +//Usually 15, a monk under this weight threshold gets an AC bonus float Mob::mod_monk_weight(float monkweight, Mob* attacker) { return(monkweight); } + +//Mitigation rating is compared to incoming attack rating. Higher is better. float Mob::mod_mitigation_rating(float mitigation_rating, Mob* attacker) { return(mitigation_rating); } float Mob::mod_attack_rating(float attack_rating, Mob* defender) { return(attack_rating); } + +//Kick damage after all other bonuses are applied int32 Mob::mod_kick_damage(int32 dmg) { return(dmg); } + +//Slam and bash damage after all other bonuses are applied int32 Mob::mod_bash_damage(int32 dmg) { return(dmg); } + +//Frenzy damage after all other bonuses are applied int32 Mob::mod_frenzy_damage(int32 dmg) { return(dmg); } + +//Special attack damage after all other bonuses are applied. int32 Mob::mod_monk_special_damage(int32 ndamage, SkillType skill_type) { return(ndamage); } + +//ndamage - Backstab damage as calculated by default formulas int32 Mob::mod_backstab_damage(int32 ndamage) { return(ndamage); } + +//Chance for 50+ archery bonus damage if Combat:UseArcheryBonusRoll is true. Base is Combat:ArcheryBonusChance int Mob::mod_archery_bonus_chance(int bonuschance, const ItemInst* RangeWeapon) { return(bonuschance); } -uint32 Mob::mod_archery_bonus_damage(uint32 MaxDmg) { return(MaxDmg); } -int32 Mob::mod_archery_damage(int32 TotalDmg, bool hasbonus) { return(TotalDmg); } + +//Archery bonus damage +uint32 Mob::mod_archery_bonus_damage(uint32 MaxDmg, const ItemInst* RangeWeapon) { return(MaxDmg); } + +//Final archery damage including bonus if it was applied. +int32 Mob::mod_archery_damage(int32 TotalDmg, bool hasbonus, const ItemInst* RangeWeapon) { return(TotalDmg); } + +//Thrown weapon damage after all other calcs uint16 Mob::mod_throwing_damage(uint16 MaxDmg) { return(MaxDmg); } + +//Spell cast time in milliseconds - will not sync with client cast time bar, but does work. int32 Mob::mod_cast_time(int32 cast_time) { return(cast_time); } + +//res - Default buff duration formula int Mob::mod_buff_duration(int res, Mob* caster, Mob* target, uint16 spell_id) { return(res); } + +//Spell stack override - If this returns anything < 2, it will ignore all other stacking rules. +// See spells.cpp: Mob::CheckStackConflict +// 0 - No conflict +// 1 - Overwrite, spellid1 is replaced by spellid2 +// -1 - Blocked, spellid2 will not land +// 2 - Default stacking behavior int Mob::mod_spell_stack(uint16 spellid1, int caster_level1, Mob* caster1, uint16 spellid2, int caster_level2, Mob* caster2) { return(2); } -int Mob::mod_spell_resist(int resist_chance, int level_mod, int resist_modifier, int target_resist, uint8 resist_type, uint16 spell_id, Mob* caster) { return(resist_chance + level_mod + resist_modifier + target_resist); } + +//Sum of various resists rolled against a value of 200. +int Mob::mod_spell_resist(int resist_chance, int level_mod, int resist_modifier, int target_resist, uint8 resist_type, uint16 spell_id, Mob* caster) { + int final = resist_chance + level_mod + resist_modifier + target_resist; + return(final); +} + +//Spell is cast by this on spelltar, called from spellontarget after the event_cast_on NPC event +void Mob::mod_spell_cast(uint16 spell_id, Mob* spelltar, bool reflect, bool use_resist_adjust, int16 resist_adjust, bool isproc) { return; } + +//This is called right before regular event processing (the switch block) +//It is intended to be used for exporting new variables to new or existing events. +void PerlembParser::mod_quest_event(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, ItemInst* iteminst, Mob* mob, uint32 extradata, bool global, std::string packagename) { return; } diff --git a/zone/mod_functions_base.cpp b/zone/mod_functions_base.cpp index c2599c547..bf559d733 100644 --- a/zone/mod_functions_base.cpp +++ b/zone/mod_functions_base.cpp @@ -13,6 +13,8 @@ #include "client.h" #include "worldserver.h" #include "QuestParserCollection.h" +#include "event_codes.h" +#include "embparser.h" #include #include @@ -21,50 +23,169 @@ extern Zone* zone; extern WorldServer worldserver; +//All functions that modify a value are passed the value as it was computed by default formulas and bonuses. In most cases this should be the final value that will be used. + +//These are called when a zone boots or is repopped void Zone::mod_init() { return; } void Zone::mod_repop() { return; } +//Pre-spawn hook called from the NPC object to be spawned void NPC::mod_prespawn(Spawn2 *sp) { return; } -int NPC::mod_npc_damage(int damage, SkillType skillinuse, int hand, ItemInst* weapon, Mob* other) { return(damage); } + +//Base damage from NPC::Attack +int NPC::mod_npc_damage(int damage, SkillType skillinuse, int hand, const Item_Struct* weapon, Mob* other) { return(damage); } + +//Mob c has been given credit for a kill. This is called after the regular EVENT_KILLED_MERIT event. void NPC::mod_npc_killed_merit(Mob* c) { return; } + +//Mob oos has been given credit for a kill. This is called after the regular EVENT_DEATH event. void NPC::mod_npc_killed(Mob* oos) { return; } -int Client::mod_client_damage(int damage, SkillType skillinuse, int hand, ItemInst* weapon, Mob* other) { return(damage); } -bool Client::mod_client_message(char* message, uint8 chan_num) { return(true); } //Potentially dangerous string handling here +//Base damage from Client::Attack - can cover myriad skill types +int Client::mod_client_damage(int damage, SkillType skillinuse, int hand, const ItemInst* weapon, Mob* other) { return(damage); } + +//message is char[4096], don't screw it up. Return true for normal behavior, false to return immediately. +// Channels: +// 0 - Guild Chat +// 2 - Group Chat +// 3 - Shout +// 4 - Auction +// 5 - Out of Character +// 6 - Broadcast +// 7 - Tell +// 8 - Say +// 11 - GMSay +// 15 - Raid Chat +// 20 - UCS Relay for UF client and later +// 22 - Emotes for UF and later +bool Client::mod_client_message(char* message, uint8 chan_num) { return(true); } + +//Skillup override. When this is called the regular skillup check has failed. Return false to proceed with default behavior. +//This will NOT allow a client to increase skill past a cap. bool Client::mod_can_increase_skill(SkillType skillid, Mob* against_who) { return(false); } + +//chance of general skill increase, rolled against 0-99 where higher chance is better. int16 Client::mod_increase_skill_chance(int16 chance, Mob* against_who) { return(chance); } + +//Max percent of health you can bind wound starting with default value for class, item, and AA bonuses int Client::mod_bindwound_percent(int max_percent, Mob* bindmob) { return(max_percent); } + +//Final bind HP value after bonuses int Client::mod_bindwound_hp(int bindhps, Mob* bindmob) { return(bindhps); } + +//Client haste as calculated by default formulas - In percent from 0-100 int Client::mod_client_haste(int h) { return(h); } + +//Haste cap override +int Client::mod_client_haste_cap(int cap) { return(cap); } + +//This is called when a client cons a mob void Client::mod_consider(Mob* tmob, Consider_Struct* con) { return; } -bool Client::mod_saylink(const std::string&, bool silentsaylink) { return(true); } + +//Return true to continue with normal behavior, false returns in the parent function +bool Client::mod_saylink(const std::string& response, bool silentsaylink) { return(true); } + +//Client pet power as calculated by default formulas and bonuses int16 Client::mod_pet_power(int16 act_power, uint16 spell_id) { return(act_power); } + +//Chance to combine rolled against a random 0-99 where higher is better. float Client::mod_tradeskill_chance(float chance, DBTradeskillRecipe_Struct *spec) { return(chance); } + +//Chance to skillup rolled against a random 0-99 where higher is better. float Client::mod_tradeskill_skillup(float chance_stage2) { return(chance_stage2); } -int32 Client::mod_tribute_item_value(int32 pts) { return(pts); } + +//Tribute value override +int32 Client::mod_tribute_item_value(int32 pts, const ItemInst* item) { return(pts); } + +//Death reporting void Client::mod_client_death_npc(Mob* killerMob) { return; } void Client::mod_client_death_duel(Mob* killerMob) { return; } void Client::mod_client_death_env() { return; } +//Calculated xp before consider modifier, called whenever a client gets XP for killing a mob. +int32 Client::mod_client_xp(int32 in_xp, NPC *npc) { return(in_xp); } + +//Client XP formula. Changes here will cause clients to change level after gaining or losing xp. +//Either modify this before your server goes live, or be prepared to write a quest script that fixes levels. +//To adjust how much XP is given per kill, use mod_client_xp +uint32 Client::mod_client_xp_for_level(uint32 xp, uint16 check_level) { return(xp); } + +//effect_vallue - Spell effect value as calculated by default formulas. You will want to ignore effects that don't lend themselves to scaling - pet ID's, gate coords, etc. int Mob::mod_effect_value(int effect_value, uint16 spell_id, int effect_type, Mob* caster) { return(effect_value); } + +//chancetohit - 0 to 100 percent - set over 1000 for a guaranteed hit float Mob::mod_hit_chance(float chancetohit, SkillType skillinuse, Mob* attacker) { return(chancetohit); } + +//Final riposte chance float Mob::mod_riposte_chance(float ripostechance, Mob* attacker) { return(ripostechance); } + +//Final block chance float Mob::mod_block_chance(float blockchance, Mob* attacker) { return(blockchance); } + +//Final parry chance float Mob::mod_parry_chance(float parrychance, Mob* attacker) { return(parrychance); } + +//Final dodge chance float Mob::mod_dodge_chance(float dodgechance, Mob* attacker) { return(dodgechance); } + +//Monk AC Bonus weight cap. Defined in Combat:MonkACBonusWeight +//Usually 15, a monk under this weight threshold gets an AC bonus float Mob::mod_monk_weight(float monkweight, Mob* attacker) { return(monkweight); } + +//Mitigation rating is compared to incoming attack rating. Higher is better. float Mob::mod_mitigation_rating(float mitigation_rating, Mob* attacker) { return(mitigation_rating); } float Mob::mod_attack_rating(float attack_rating, Mob* defender) { return(attack_rating); } + +//Kick damage after all other bonuses are applied int32 Mob::mod_kick_damage(int32 dmg) { return(dmg); } + +//Slam and bash damage after all other bonuses are applied int32 Mob::mod_bash_damage(int32 dmg) { return(dmg); } + +//Frenzy damage after all other bonuses are applied int32 Mob::mod_frenzy_damage(int32 dmg) { return(dmg); } + +//Special attack damage after all other bonuses are applied. int32 Mob::mod_monk_special_damage(int32 ndamage, SkillType skill_type) { return(ndamage); } + +//ndamage - Backstab damage as calculated by default formulas int32 Mob::mod_backstab_damage(int32 ndamage) { return(ndamage); } + +//Chance for 50+ archery bonus damage if Combat:UseArcheryBonusRoll is true. Base is Combat:ArcheryBonusChance int Mob::mod_archery_bonus_chance(int bonuschance, const ItemInst* RangeWeapon) { return(bonuschance); } -uint32 Mob::mod_archery_bonus_damage(uint32 MaxDmg) { return(MaxDmg); } -int32 Mob::mod_archery_damage(int32 TotalDmg, bool hasbonus) { return(TotalDmg); } + +//Archery bonus damage +uint32 Mob::mod_archery_bonus_damage(uint32 MaxDmg, const ItemInst* RangeWeapon) { return(MaxDmg); } + +//Final archery damage including bonus if it was applied. +int32 Mob::mod_archery_damage(int32 TotalDmg, bool hasbonus, const ItemInst* RangeWeapon) { return(TotalDmg); } + +//Thrown weapon damage after all other calcs uint16 Mob::mod_throwing_damage(uint16 MaxDmg) { return(MaxDmg); } + +//Spell cast time in milliseconds - will not sync with client cast time bar, but does work. int32 Mob::mod_cast_time(int32 cast_time) { return(cast_time); } + +//res - Default buff duration formula int Mob::mod_buff_duration(int res, Mob* caster, Mob* target, uint16 spell_id) { return(res); } + +//Spell stack override - If this returns anything < 2, it will ignore all other stacking rules. +// See spells.cpp: Mob::CheckStackConflict +// 0 - No conflict +// 1 - Overwrite, spellid1 is replaced by spellid2 +// -1 - Blocked, spellid2 will not land +// 2 - Default stacking behavior int Mob::mod_spell_stack(uint16 spellid1, int caster_level1, Mob* caster1, uint16 spellid2, int caster_level2, Mob* caster2) { return(2); } -int Mob::mod_spell_resist(int resist_chance, int level_mod, int resist_modifier, int target_resist, uint8 resist_type, uint16 spell_id, Mob* caster) { return(resist_chance + level_mod + resist_modifier + target_resist); } + +//Sum of various resists rolled against a value of 200. +int Mob::mod_spell_resist(int resist_chance, int level_mod, int resist_modifier, int target_resist, uint8 resist_type, uint16 spell_id, Mob* caster) { + int final = resist_chance + level_mod + resist_modifier + target_resist; + return(final); +} + +//Spell is cast by this on spelltar, called from spellontarget after the event_cast_on NPC event +void Mob::mod_spell_cast(uint16 spell_id, Mob* spelltar, bool reflect, bool use_resist_adjust, int16 resist_adjust, bool isproc) { return; } + +//This is called right before regular event processing (the switch block) +//It is intended to be used for exporting new variables to new or existing events. +void PerlembParser::mod_quest_event(QuestEventID event, uint32 objid, const char * data, NPC* npcmob, ItemInst* iteminst, Mob* mob, uint32 extradata, bool global, std::string packagename) { return; } diff --git a/zone/npc.h b/zone/npc.h index 3c25c4dd7..1a8b871ce 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -352,7 +352,7 @@ public: uint32 GetSpawnKillCount(); int GetScore(); void mod_prespawn(Spawn2 *sp); - int mod_npc_damage(int damage, SkillType skillinuse, int hand, ItemInst* weapon, Mob* other); + int mod_npc_damage(int damage, SkillType skillinuse, int hand, const Item_Struct* weapon, Mob* other); void mod_npc_killed_merit(Mob* c); void mod_npc_killed(Mob* oos); diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index c89445bd2..0ac61e3cc 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -129,8 +129,8 @@ XS(XS_NPC_AddLootTable); /* prototype to pass -Wmissing-prototypes */ XS(XS_NPC_AddLootTable) { dXSARGS; - if (items != 1) - Perl_croak(aTHX_ "Usage: NPC::AddLootTable(THIS)"); + if (items < 1) + Perl_croak(aTHX_ "Usage: NPC::AddLootTable(THIS, [loottable_id])"); { NPC * THIS; diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 9d1f133f7..a472a3209 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -862,7 +862,7 @@ uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) { spells[curspell].classes[initiator->GetPP().class_-1] <= max_level && //maximum level spells[curspell].classes[initiator->GetPP().class_-1] >= min_level && //minimum level spells[curspell].skill != 52 && - ( !RuleB(Spells, UseCHAScribeHack) || spells[curspell].effectid[EFFECT_COUNT - 1] != 10 ) + spells[curspell].effectid[EFFECT_COUNT - 1] != 10 ) { if (book_slot == -1) //no more book slots diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 568d8078d..e2c2d5e7f 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -907,7 +907,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item { MaxDmg *= (float)2; hate *= (float)2; - MaxDmg = mod_archery_bonus_damage(MaxDmg); + MaxDmg = mod_archery_bonus_damage(MaxDmg, RangeWeapon); mlog(COMBAT__RANGED, "Ranger. Double damage success roll, doubling damage to %d", MaxDmg); Message_StringID(MT_CritMelee, BOW_DOUBLE_DAMAGE); @@ -940,7 +940,7 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item TotalDmg += other->GetAdditionalDamage(this, 0, true, ARCHERY); TotalDmg += (itembonuses.HeroicDEX / 10) + (TotalDmg * other->GetSkillDmgTaken(ARCHERY) / 100) + GetSkillDmgAmt(ARCHERY); - TotalDmg = mod_archery_damage(TotalDmg, dobonus); + TotalDmg = mod_archery_damage(TotalDmg, dobonus, RangeWeapon); TryCriticalHit(other, ARCHERY, TotalDmg); other->AddToHateList(this, hate, 0, false); diff --git a/zone/spells.cpp b/zone/spells.cpp index ff50ab464..aab165935 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3086,6 +3086,8 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect, bool use_r parse->EventNPC(EVENT_CAST_ON, spelltar->CastToNPC(), this, temp1, 0); } + mod_spell_cast(spell_id, spelltar, reflect, use_resist_adjust, resist_adjust, isproc); + // now check if the spell is allowed to land // invuln mobs can't be affected by any spells, good or bad diff --git a/zone/tribute.cpp b/zone/tribute.cpp index 2f25fc660..5d2ceff4d 100644 --- a/zone/tribute.cpp +++ b/zone/tribute.cpp @@ -247,7 +247,7 @@ int32 Client::TributeItem(uint32 slot, uint32 quantity) { //figure out what its worth int32 pts = inst->GetItem()->Favor; - pts = mod_tribute_item_value(pts); + pts = mod_tribute_item_value(pts, m_inv[slot]); if(pts < 1) { Message(13, "This item is worthless for favor.");