diff --git a/changelog.txt b/changelog.txt index d21af0a8b..eff2f9460 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,16 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 04/15/2014 == +Akkadius: Exported $client->SendMarqueeMessage(type, priority, fade_in, fade_out, duration, msg) - Will be available for simple plugin use +Akkadius: Exported $client->ExpeditionMessage(THIS, ExpdID, Message) - In use with custom expedition mod that will be released soon + +== 04/12/2014 == +Kayen: Fixed an with the slow mitigation code that would cause it to spam the message. Optimized the way the variable is handled for slow mitigation. + +Required SQL: utils/sql/git/required/2014_04_12_SlowMitigation.sql +Note: This changes the variable type in the sql table from FLOAT to INT and updates your database. +(When setting slow mitigation 50 = 50%, 100 = 100% ect. You can also set > 100 which will cause slow to become haste now with appropriate in game msg given) + == 04/10/2014 == Kayen: Added 'no_target_hotkey' field to npc_types table. This will prevent the NPC from being targeted with F8 (Warning: Will also turn it's name YELLOW) Kayen: Added a rule to make all (Player cast) Swarm Pets not targetable with F8 (nearest NPC) by default (Warning: Will also turn pets names YELLOW). This is semi-hack but it works. diff --git a/utils/sql/git/required/2014_04_12_SlowMitigation.sql b/utils/sql/git/required/2014_04_12_SlowMitigation.sql new file mode 100644 index 000000000..f2ac0d68d --- /dev/null +++ b/utils/sql/git/required/2014_04_12_SlowMitigation.sql @@ -0,0 +1,7 @@ +-- Convert all values from FLOAT to INT +UPDATE npc_types SET slow_mitigation = slow_mitigation * 100; + +-- Change variable type from FLOAT TO INT +ALTER TABLE npc_types MODIFY slow_mitigation smallint(4); + + diff --git a/zone/StringIDs.h b/zone/StringIDs.h index 05bbffdec..c916b1de0 100644 --- a/zone/StringIDs.h +++ b/zone/StringIDs.h @@ -243,12 +243,12 @@ #define TRADESKILL_LEARN_RECIPE 3457 //You have learned the recipe %1! #define EXPEDITION_MIN_REMAIN 3551 //You only have %1 minutes remaining before this expedition comes to an end. #define REWIND_WAIT 4059 //You must wait a bit longer before using the rewind command again. -#define CORPSEDRAG_LIMIT 4061 //You are already dragging as much as you can! -#define CORPSEDRAG_ALREADY 4062 //You are already dragging %1. +#define CORPSEDRAG_LIMIT 4061 //You are already dragging as much as you can! +#define CORPSEDRAG_ALREADY 4062 //You are already dragging %1. #define CORPSEDRAG_SOMEONE_ELSE 4063 //Someone else is dragging %1. -#define CORPSEDRAG_BEGIN 4064 //You begin to drag %1. -#define CORPSEDRAG_STOPALL 4065 //You stop dragging the corpses. -#define CORPSEDRAG_STOP 4066 //You stop dragging the corpse. +#define CORPSEDRAG_BEGIN 4064 //You begin to drag %1. +#define CORPSEDRAG_STOPALL 4065 //You stop dragging the corpses. +#define CORPSEDRAG_STOP 4066 //You stop dragging the corpse. #define WHOALL_NO_RESULTS 5029 //There are no players in EverQuest that match those who filters. #define PETITION_NO_DELETE 5053 //You do not have a petition in the queue. #define PETITION_DELETED 5054 //Your petition was successfully deleted. @@ -300,6 +300,10 @@ #define GAIN_RAID_LEADERSHIP_EXP 8789 // #define BUFF_MINUTES_REMAINING 8799 //%1 (%2 minutes remaining) #define FEAR_TOO_HIGH 9035 //Your target is too high of a level for your fear spell. +#define SLOW_MOSTLY_SUCCESSFUL 9029 //Your spell was mostly successful. +#define SLOW_PARTIALLY_SUCCESSFUL 9030 // Your spell was partially successful. +#define SLOW_SLIGHTLY_SUCCESSFUL 9031 //Your spell was slightly successful. +#define SPELL_OPPOSITE_EFFECT 9032 //Your spell may have had the opposite effect of what you desired. #define YOU_HEAL 9068 //You have healed %1 for %2 points of damage. #define YOUR_HIT_DOT 9072 //%1 has taken %2 damage from your %3. #define HIT_NON_MELEE 9073 //%1 hit %2 for %3 points of non-melee damage. diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 56f8b9f5f..c726333f2 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1338,19 +1338,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne } } else if ((effect_value - 100) < 0) { // Slow - //Slow Mitigation works by taking the amount that would be slowed, and adding a multiplied version of the difference. int real_slow_value = (100 - effect_value) * -1; - if (slow_mitigation){ - int new_effect_value = SlowMitigation(false,caster,real_slow_value); - if (new_effect_value < newbon->haste) { - newbon->haste = new_effect_value; - SlowMitigation(true,caster); - } - } - else { - if (real_slow_value < newbon->haste) - newbon->haste = real_slow_value; - } + real_slow_value -= ((real_slow_value * GetSlowMitigation()/100)); + if (real_slow_value < newbon->haste) + newbon->haste = real_slow_value; } break; } @@ -1365,6 +1356,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne } else if ((effect_value - 100) < 0) { // Slow int real_slow_value = (100 - effect_value) * -1; + real_slow_value -= ((real_slow_value * GetSlowMitigation()/100)); if (real_slow_value < newbon->hastetype2) newbon->hastetype2 = real_slow_value; } @@ -1374,6 +1366,7 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne case SE_AttackSpeed3: { if (effect_value < 0){ //Slow + effect_value -= ((effect_value * GetSlowMitigation()/100)); if (effect_value < newbon->hastetype3) newbon->hastetype3 = effect_value; } @@ -1392,18 +1385,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne effect_value = effect_value * -1; if (effect_value > 0 && effect_value > newbon->inhibitmelee) { - - if (slow_mitigation){ - int new_effect_value = SlowMitigation(false,caster,effect_value); - if (new_effect_value > newbon->inhibitmelee) { - newbon->inhibitmelee = new_effect_value; - SlowMitigation(true,caster); - } - } - - else if (effect_value > newbon->inhibitmelee) { + effect_value -= ((effect_value * GetSlowMitigation()/100)); + if (effect_value > newbon->inhibitmelee) newbon->inhibitmelee = effect_value; - } } break; diff --git a/zone/client.cpp b/zone/client.cpp index 58b1455e2..a2cbc3dc6 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8236,3 +8236,29 @@ void Client::PlayMP3(const char* fname) safe_delete(outapp); } +void Client::ExpeditionSay(const char *str, int ExpID) { + char errbuf[MYSQL_ERRMSG_SIZE]; + char* query = 0; + MYSQL_RES *result; + MYSQL_ROW row; + + if (!database.RunQuery(query,MakeAnyLenString(&query, "SELECT `player_name` FROM `cust_inst_players` WHERE `inst_id` = %i", ExpID),errbuf,&result)){ + safe_delete_array(query); + return; + } + + safe_delete_array(query); + + if(result) + this->Message(14, "You say to the expedition, '%s'", str); + + while((row = mysql_fetch_row(result))) { + const char* CharName = row[0]; + if(strcmp(CharName, this->GetCleanName()) != 0) + worldserver.SendEmoteMessage(CharName, 0, 0, 14, "%s says to the expedition, '%s'", this->GetCleanName(), str); + // ChannelList->CreateChannel(ChannelName, ChannelOwner, ChannelPassword, true, atoi(row[3])); + } + + mysql_free_result(result); + +} \ No newline at end of file diff --git a/zone/client.h b/zone/client.h index 28bb7db73..23188b24d 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1171,6 +1171,7 @@ public: std::string GetAccountFlag(std::string flag); float GetDamageMultiplier(SkillUseTypes); void Consume(const Item_Struct *item, uint8 type, int16 slot, bool auto_consume); void PlayMP3(const char* fname); + void ExpeditionSay(const char *str, int ExpID); int mod_client_damage(int damage, SkillUseTypes skillinuse, int hand, const ItemInst* weapon, Mob* other); bool mod_client_message(char* message, uint8 chan_num); bool mod_can_increase_skill(SkillUseTypes skillid, Mob* against_who); diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index 1dd61cc91..41524af15 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -408,7 +408,7 @@ void Lua_NPC::SetSpellFocusHeal(int focus) { } float Lua_NPC::GetSlowMitigation() { - Lua_Safe_Call_Real(); + Lua_Safe_Call_Int(); return self->GetSlowMitigation(); } @@ -526,7 +526,7 @@ 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("GetSlowMitigation", (float(Lua_NPC::*)(void))&Lua_NPC::GetSlowMitigation) + .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) .def("GetSpawnKillCount", (int(Lua_NPC::*)(void))&Lua_NPC::GetSpawnKillCount) diff --git a/zone/mob.cpp b/zone/mob.cpp index 67bd8e76d..f6d7a7073 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4649,33 +4649,21 @@ void Mob::CastOnNumHitFade(uint32 spell_id) } } -int Mob::SlowMitigation(bool slow_msg, Mob *caster, int slow_value) +void Mob::SlowMitigation(Mob* caster) { - float int_slow_mitigation = slow_mitigation * 100.0f; - - if (int_slow_mitigation > 100.0f) - return 0; - - if (slow_msg) + if (GetSlowMitigation() && caster && caster->IsClient()) { - if (caster && caster->IsClient()) - { - if ((int_slow_mitigation > 0.0f) && (int_slow_mitigation < 26.0f)) - caster->Message(262, "Your spell was mostly successful"); + if ((GetSlowMitigation() > 0) && (GetSlowMitigation() < 26)) + caster->Message_StringID(MT_SpellFailure, SLOW_MOSTLY_SUCCESSFUL); - else if ((int_slow_mitigation >= 26.0f) && (int_slow_mitigation < 74.0f)) - caster->Message(262, "Your spell was partially successful"); + else if ((GetSlowMitigation() >= 26) && (GetSlowMitigation() < 74)) + caster->Message_StringID(MT_SpellFailure, SLOW_PARTIALLY_SUCCESSFUL); - else if ((int_slow_mitigation >= 74.0f) && (int_slow_mitigation < 101.0f)) - caster->Message(262, "Your spell was slightly successful"); - } - return 0; - } + else if ((GetSlowMitigation() >= 74) && (GetSlowMitigation() < 101)) + caster->Message_StringID(MT_SpellFailure, SLOW_SLIGHTLY_SUCCESSFUL); - else - { - slow_value -= (slow_value * static_cast(int_slow_mitigation) / 100); - return slow_value; + else if (GetSlowMitigation() > 100) + caster->Message_StringID(MT_SpellFailure, SPELL_OPPOSITE_EFFECT); } } diff --git a/zone/mob.h b/zone/mob.h index bf3399251..d79f30867 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -580,7 +580,7 @@ public: void CastOnCurer(uint32 spell_id); void CastOnCure(uint32 spell_id); void CastOnNumHitFade(uint32 spell_id); - int SlowMitigation(bool slow_msg=false, Mob *caster = nullptr,int slow_value = 0); + void SlowMitigation(Mob* caster); int16 GetCritDmgMob(uint16 skill); int16 GetMeleeDamageMod_SE(uint16 skill); int16 GetMeleeMinDamageMod_SE(uint16 skill); @@ -598,6 +598,7 @@ public: bool PassCastRestriction(bool UseCastRestriction = true, int16 value = 0, bool IsDamage = true); bool ImprovedTaunt(); bool TryRootFadeByDamage(int buffslot, Mob* attacker); + int16 GetSlowMitigation() const {return slow_mitigation;} void ModSkillDmgTaken(SkillUseTypes skill_num, int value); int16 GetModSkillDmgTaken(const SkillUseTypes skill_num); @@ -1023,7 +1024,7 @@ protected: Timer attack_dw_timer; Timer ranged_timer; float attack_speed; //% increase/decrease in attack speed (not haste) - float slow_mitigation; // Allows for a slow mitigation based on a % in decimal form. IE, 1 = 100% mitigation, .5 is 50% + float slow_mitigation; // Allows for a slow mitigation (100 = 100%, 50% = 50%) Timer tic_timer; Timer mana_timer; diff --git a/zone/npc.cpp b/zone/npc.cpp index 20bc025fc..2611300d8 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -2004,7 +2004,7 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue) if(id == "slow_mitigation") { - slow_mitigation = atof(val.c_str()); + slow_mitigation = atoi(val.c_str()); return; } if(id == "loottable_id") diff --git a/zone/npc.h b/zone/npc.h index 406be550f..55bed4abc 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -233,7 +233,7 @@ public: uint32 GetMaxDMG() const {return max_dmg;} uint32 GetMinDMG() const {return min_dmg;} - float GetSlowMitigation() const {return slow_mitigation;} + int16 GetSlowMitigation() const {return slow_mitigation;} float GetAttackSpeed() const {return attack_speed;} bool IsAnimal() const { return(bodytype == BT_Animal); } uint16 GetPetSpellID() const {return pet_spell_id;} diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index da81c03d7..0bab3cfb0 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -5898,6 +5898,64 @@ XS(XS_Client_PlayMP3) XSRETURN_EMPTY; } +XS(XS_Client_ExpeditionMessage); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_ExpeditionMessage) +{ + dXSARGS; + if (items != 3) + Perl_croak(aTHX_ "Usage: Client::ExpeditionMessage(THIS, ExpdID, Message)"); + { + Client * THIS; + int ExpdID = (int)SvUV(ST(1)); + const char * Message = (const char *)SvPV_nolen(ST(2)); + dXSTARG; + + if (sv_derived_from(ST(0), "Client")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Client *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Client"); + if(THIS == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + THIS->ExpeditionSay(Message, ExpdID); + } + XSRETURN_EMPTY; +} + +//Client::SendMarqueeMessage(uint32 type, uint32 priority, uint32 fade_in, uint32 fade_out, uint32 duration, std::string msg) + +XS(XS_Client_SendMarqueeMessage); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_SendMarqueeMessage) +{ + dXSARGS; + if (items != 7) + Perl_croak(aTHX_ "Usage: Client::SendMarqueeMessage(THIS, type, priority, fade_in, fade_out, duration, msg)"); + { + Client * THIS; + uint32 type = (uint32)SvUV(ST(1)); + uint32 priority = (uint32)SvUV(ST(2)); + uint32 fade_in = (uint32)SvUV(ST(3)); + uint32 fade_out = (uint32)SvUV(ST(4)); + uint32 duration = (uint32)SvUV(ST(5)); + std::string msg = (std::string)SvPV_nolen(ST(6)); + dXSTARG; + + if (sv_derived_from(ST(0), "Client")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Client *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Client"); + if(THIS == NULL) + Perl_croak(aTHX_ "THIS is NULL, avoiding crash."); + + THIS->SendMarqueeMessage(type, priority, fade_in, fade_out, duration, msg); + } + XSRETURN_EMPTY; +} + #ifdef __cplusplus extern "C" #endif @@ -6134,6 +6192,8 @@ XS(boot_Client) newXSproto(strcpy(buf, "SilentMessage"), XS_Client_SilentMessage, file, "$$"); newXSproto(strcpy(buf, "PlayMP3"), XS_Client_PlayMP3, file, "$;$"); newXSproto(strcpy(buf, "SendTargetCommand"), XS_Client_SendTargetCommand, file, "$$"); + newXSproto(strcpy(buf, "ExpeditionMessage"), XS_Client_ExpeditionMessage, file, "$$$"); + newXSproto(strcpy(buf, "SendMarqueeMessage"), XS_Client_SendMarqueeMessage, file, "$$$$$$$"); XSRETURN_YES; } diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index 2ab0ca036..891709113 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -2023,7 +2023,7 @@ XS(XS_NPC_GetSlowMitigation) Perl_croak(aTHX_ "Usage: NPC::GetSlowMitigation(THIS)"); { NPC * THIS; - float RETVAL; + int16 RETVAL; dXSTARG; if (sv_derived_from(ST(0), "NPC")) { @@ -2036,7 +2036,7 @@ XS(XS_NPC_GetSlowMitigation) Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); RETVAL = THIS->GetSlowMitigation(); - XSprePUSH; PUSHn((double)RETVAL); + XSprePUSH; PUSHn((UV)RETVAL); } XSRETURN(1); } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index ad7e273fd..6b48627d4 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -284,20 +284,31 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) #ifdef SPELL_EFFECT_SPAM snprintf(effect_desc, _EDLEN, "Percental Heal: %+i (%d%% max)", spell.max[i], effect_value); #endif - //im not 100% sure about this implementation. - //the spell value forumula dosent work for these... at least spell 3232 anyways - int32 val = spell.max[i]; + int32 val = GetMaxHP() * spell.base[i] / 100; - if(caster) - val = caster->GetActSpellHealing(spell_id, val, this); + //This effect can also do damage by percent. + if (val < 0) { - int32 mhp = GetMaxHP(); - int32 cap = mhp * spell.base[i] / 100; + if (-val > spell.max[i]) + val = -spell.max[i]; - if(cap < val) - val = cap; + if (caster) + val = caster->GetActSpellDamage(spell_id, val, this); - if(val > 0) + } + + else + { + if (val > spell.max[i]) + val = spell.max[i]; + + if(caster) + val = caster->GetActSpellHealing(spell_id, val, this); + } + + if (val < 0) + Damage(caster, -val, spell_id, spell.skill, false, buffslot, false); + else HealDamage(val, caster); break; @@ -2624,14 +2635,37 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) HealDamage(dmg, caster); } } + + break; } case SE_Taunt: { if (IsNPC()) caster->Taunt(this->CastToNPC(), false, spell.base[i]); + + break; } + case SE_AttackSpeed: + if (spell.base[i] < 100) + SlowMitigation(caster); + break; + + case SE_AttackSpeed2: + if (spell.base[i] < 100) + SlowMitigation(caster); + break; + + case SE_AttackSpeed3: + if (spell.base[i] < 0) + SlowMitigation(caster); + break; + + case SE_AttackSpeed4: + SlowMitigation(caster); + break; + // Handled Elsewhere case SE_ImmuneFleeing: case SE_NegateSpellEffect: @@ -2717,10 +2751,6 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_DivineSave: case SE_Accuracy: case SE_Flurry: - case SE_AttackSpeed: - case SE_AttackSpeed2: - case SE_AttackSpeed3: - case SE_AttackSpeed4: case SE_ImprovedDamage: case SE_ImprovedHeal: case SE_IncreaseSpellHaste: diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 119d83cc2..893a1a27a 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1273,7 +1273,7 @@ const NPCType* ZoneDatabase::GetNPCType (uint32 id) { tmpNPCType->see_improved_hide = atoi(row[r++])==0?false:true; tmpNPCType->ATK = atoi(row[r++]); tmpNPCType->accuracy_rating = atoi(row[r++]); - tmpNPCType->slow_mitigation = atof(row[r++]); + tmpNPCType->slow_mitigation = atoi(row[r++]); tmpNPCType->maxlevel = atoi(row[r++]); tmpNPCType->scalerate = atoi(row[r++]); tmpNPCType->private_corpse = atoi(row[r++]) == 1 ? true : false; diff --git a/zone/zonedump.h b/zone/zonedump.h index ab8f88d23..39c6b39d7 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -111,7 +111,7 @@ struct NPCType int accuracy_rating; //10 = 1% accuracy bool findable; //can be found with find command bool trackable; - float slow_mitigation; // Slow mitigation % in decimal form. + int16 slow_mitigation; uint8 maxlevel; uint32 scalerate; bool private_corpse;