This commit is contained in:
SecretsOTheP 2014-02-13 12:02:37 -05:00
commit e5fd0f5d75
26 changed files with 960 additions and 1069 deletions

View File

@ -118,6 +118,14 @@ SET(EQEMU_DEBUG_LEVEL 5 CACHE STRING "EQEmu debug level:
10 - More errors than you ever wanted to see"
)
SET(EQEMU_STREAM_SEND_RATE 1048576 CACHE STRING "Advanced: Base amount of data stream can send before throttle.")
SET(EQEMU_STREAM_DECAY_RATE 78642 CACHE STRING "Advanced: Base amount of data stream recovers per tic.")
SET(EQEMU_STREAM_RETRANSMIT_TIMEOUT_MUL 3.0 CACHE STRING "Advanced: Multiplier on retransmit timeout.")
SET(EQEMU_STREAM_RETRANSMIT_TIMEOUT_MAX 5000 CACHE STRING "Advanced: Max in ms for retransmit timeout timer.")
SET(EQEMU_STREAM_AVERAGE_DELTA_MAX 2500 CACHE STRING "Advanced: The maximum average delta in ms allowed.")
SET(EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS TRUE CACHE BOOL "Advanced: Whether or not acked packets can be retransmitted")
MARK_AS_ADVANCED(EQEMU_STREAM_SEND_RATE EQEMU_STREAM_DECAY_RATE EQEMU_STREAM_RETRANSMIT_TIMEOUT_MUL EQEMU_STREAM_RETRANSMIT_TIMEOUT_MAX EQEMU_STREAM_AVERAGE_DELTA_MAX EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS)
#NPC Types Cache Behavior
OPTION(EQEMU_DEPOP_INVALIDATES_CACHE "#repop invalidates the npc_types cache (will cause a larger database hit on #repop but is more convienent)." ON)
@ -169,6 +177,16 @@ ADD_DEFINITIONS(-DEQDEBUG=${EQEMU_DEBUG_LEVEL})
ADD_DEFINITIONS(-DINVERSEXY)
ADD_DEFINITIONS(-DFIELD_ITEMS)
ADD_DEFINITIONS(-DMAP_DIR="./Maps")
ADD_DEFINITIONS(-DRATEBASE=${EQEMU_STREAM_SEND_RATE})
ADD_DEFINITIONS(-DDECAYBASE=${EQEMU_STREAM_DECAY_RATE})
ADD_DEFINITIONS(-DRETRANSMIT_TIMEOUT_MULT=${EQEMU_STREAM_RETRANSMIT_TIMEOUT_MUL})
ADD_DEFINITIONS(-DRETRANSMIT_TIMEOUT_MAX=${EQEMU_STREAM_RETRANSMIT_TIMEOUT_MAX})
ADD_DEFINITIONS(-DAVERAGE_DELTA_MAX=${EQEMU_STREAM_AVERAGE_DELTA_MAX})
IF(EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS)
ADD_DEFINITIONS(-DRETRANSMIT_ACKED_PACKETS=true)
ELSE(EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS)
ADD_DEFINITIONS(-DRETRANSMIT_ACKED_PACKETS=false)
ENDIF(EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS)
#Find everything we need
FIND_PACKAGE(ZLIB REQUIRED)

View File

@ -3,14 +3,16 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50)
== 02/10/2014 ==
demonstar55 (Secrets): Re-wrote the entity list to be a std::map. This should be used for direct entityID lookups and is noticably faster performance-wise. Also should result in less nil pointers potentially.
Secrets: Fixed a crash issue that could occur on #repop related to quest timers.
Kayen: Divine Arbiration and other similar spell effects will now utilize a spell range check.
Kayen: Revised how heal amount is calculated to properly incorporate all current focus effects/bonuses.
Kayen: Various updates/fixes/clean-ups to focus effect related code. Focus effect limits should now all work properly.
== 02/09/2014 ==
Sorvani: Added new spawn condition onchange action: DoRepopIfReady. Choosing this will not repop mobs when the spawn condition is enabled if they have an existing respawn timer. Additionally, this condition will not even attempt repop when the condition is is changed to disabled. Will be in use on PEQ for: Cragbeast Queen in Natimbi.
Secrets: Fixed a weird crash issue with deletion of pointers if task loading fails.
== 02/2/2014 ==
Kayen: Revised how spell/dot damage is calculated to properly incorporated all current focus effects/bonuses.
Kayen: Revised how spell/dot damage is calculated to properly incorporate all current focus effects/bonuses.
Required SQL: utils/sql/git/2014_02_02_SpellCriticalsAA.sql

View File

@ -21,13 +21,29 @@
#define FLAG_COMPRESSED 0x01
#define FLAG_ENCODED 0x04
#define RATEBASE 1048576 // 1 MB
#define DECAYBASE 78642 // RATEBASE/10
#ifndef RATEBASE
#define RATEBASE 1048576
#endif
#ifndef DECAYBASE
#define DECAYBASE 78642
#endif
#ifndef RETRANSMIT_TIMEOUT_MULT
#define RETRANSMIT_TIMEOUT_MULT 3.0
#endif
#ifndef RETRANSMIT_TIMEOUT_MAX
#define RETRANSMIT_TIMEOUT_MAX 5000
#endif
#ifndef AVERAGE_DELTA_MAX
#define AVERAGE_DELTA_MAX 2500
#endif
#ifndef RETRANSMIT_ACKED_PACKETS
#define RETRANSMIT_ACKED_PACKETS true
#endif
#pragma pack(1)
struct SessionRequest {
@ -62,9 +78,6 @@ struct SessionStats {
#pragma pack()
class OpcodeManager;
//extern OpcodeManager *EQNetworkOpcodeManager;
//class EQStreamFactory;
class EQStreamPair;
class EQRawApplicationPacket;
@ -142,8 +155,6 @@ class EQStream : public EQStreamInterface {
OpcodeManager **OpMgr;
// EQStreamFactory *const Factory;
EQRawApplicationPacket *MakeApplicationPacket(EQProtocolPacket *p);
EQRawApplicationPacket *MakeApplicationPacket(const unsigned char *buf, uint32 len);
EQProtocolPacket *MakeProtocolPacket(const unsigned char *buf, uint32 len);
@ -167,8 +178,6 @@ class EQStream : public EQStreamInterface {
void SetSession(uint32 s) { Session=s; }
void ProcessPacket(EQProtocolPacket *p);
// virtual void DispatchPacket(EQApplicationPacket *p) { p->DumpRaw(); }
bool Stale(uint32 now, uint32 timeout=30) { return (LastPacket && (now-LastPacket) > timeout); }
@ -190,7 +199,6 @@ class EQStream : public EQStreamInterface {
EQStream() { init(); remote_ip = 0; remote_port = 0; State=UNESTABLISHED; StreamType=UnknownStream; compressed=true; encoded=false; app_opcode_size=2; bytes_sent=0; bytes_recv=0; create_time=Timer::GetTimeSeconds(); }
EQStream(sockaddr_in addr) { init(); remote_ip=addr.sin_addr.s_addr; remote_port=addr.sin_port; State=UNESTABLISHED; StreamType=UnknownStream; compressed=true; encoded=false; app_opcode_size=2; bytes_sent=0; bytes_recv=0; create_time=Timer::GetTimeSeconds(); }
virtual ~EQStream() { RemoveData(); SetState(CLOSED); }
// inline void SetFactory(EQStreamFactory *f) { Factory=f; }
void SetMaxLen(uint32 length) { MaxLen=length; }
//interface used by application (EQStreamInterface)
@ -219,10 +227,8 @@ class EQStream : public EQStreamInterface {
inline EQStreamState GetState() { EQStreamState s; MState.lock(); s=State; MState.unlock(); return s; }
// static EQProtocolPacket *Read(int eq_fd, sockaddr_in *from);
static SeqOrder CompareSequence(uint16 expected_seq , uint16 seq);
// void Close() { SendDisconnect(); }
bool CheckActive() { return GetState()==ESTABLISHED; }
bool CheckClosed() { return GetState()==CLOSED; }
void SetOpcodeSize(uint8 s) { app_opcode_size = s; }

View File

@ -36,6 +36,7 @@
#define EFFECT_COUNT 12
#define MAX_SPELL_TRIGGER 12 // One for each slot(only 6 for AA since AA use 2)
#define MAX_RESISTABLE_EFFECTS 12 // Number of effects that are typcially checked agianst resists.
#define MaxLimitInclude 12 //Number(x 0.5) of focus Limiters that have inclusive checksm used when calcing focus effects
const int Z_AGGRO=10;
@ -289,8 +290,8 @@ typedef enum {
#define SE_LimitMinDur 140 // implemented
#define SE_LimitInstant 141 // implemented
#define SE_LimitMinLevel 142 // implemented
#define SE_LimitCastTime 143 // implemented
#define SE_FfCastTimeMax 144 // not used
#define SE_LimitCastTimeMin 143 // implemented
#define SE_LimitCastTimeMax 144 // implemented (*not used in any known live spell)
#define SE_Teleport2 145 // implemented - Banishment of the Pantheon
#define SE_ElectricityResist 146 // *not implemented (Lightning Rod: 23233)
#define SE_PercentalHeal 147 // implemented
@ -442,7 +443,7 @@ typedef enum {
#define SE_FrontalStunResist 293 // implemented[AA] - Reduce chance to be stunned from front.
#define SE_CriticalSpellChance 294 // implemented - increase chance to critical hit and critical damage modifier.
//#define SE_ReduceTimerSpecial 295 // not used
#define SE_SpellVulnerability 296 // implemented - increase in incoming spell damage
#define SE_FcSpellVulnerability 296 // implemented - increase in incoming spell damage
#define SE_FcDamageAmtIncoming 297 // implemented - debuff that adds points damage to spells cast on target (focus effect).
#define SE_ChangeHeight 298 // implemented
#define SE_WakeTheDead 299 // implemented
@ -457,7 +458,7 @@ typedef enum {
#define SE_SuspendMinion 308 // not implemented as bonus
#define SE_YetAnotherGate 309 // implemented
#define SE_ReduceReuseTimer 310 // implemented
#define SE_CombatSkills 311 // implemented
#define SE_LimitCombatSkills 311 // implemented - Excludes focus from procs (except if proc is a memorizable spell)
#define SE_Sanctuary 312 // *not implemented
#define SE_ForageAdditionalItems 313 // implemented[AA] - chance to forage additional items
#define SE_Invisibility2 314 // implemented - fixed duration invisible
@ -494,7 +495,7 @@ typedef enum {
#define SE_AssassinationLevel 345 // not implemented as bonus - AA Assisination max level to kill
#define SE_HeadShotLevel 346 // not implemented as bonus - AA HeadShot max level to kill
#define SE_DoubleRangedAttack 347 // implemented - chance at an additional archery attack (consumes arrow)
#define SE_LimitManaCost 348 // implemented
#define SE_LimitManaMin 348 // implemented
#define SE_ShieldEquipHateMod 349 // implemented[AA] Increase melee hate when wearing a shield.
#define SE_ManaBurn 350 // implemented - Drains mana for damage/heal at a defined ratio up to a defined maximum amount of mana.
#define SE_PersistentEffect 351 // *not implemented. creates a trap/totem that casts a spell (spell id + base1?) when anything comes near it. can probably make a beacon for this
@ -535,22 +536,22 @@ typedef enum {
#define SE_CastOnCurer 386 // implemented - Casts a spell on the person curing
#define SE_CastOnCure 387 // implemented - Casts a spell on the cured person
#define SE_SummonCorpseZone 388 // *not implemented - summons a corpse from any zone(nec AA)
#define SE_Forceful_Rejuv 389 // Refresh spell icons
#define SE_SetRecastTimer 390 // *not implemented - Sets recast timers to specific value, focus limited.
#define SE_IncreaseHitDmgTaken 391 // implemented - Most likely a simple negative mitigation modifier (Warlords fury: 23528)
#define SE_AdditionalHeal2 392 // implemented - Adds or removes healing from spells
#define SE_HealRate2 393 // implemented - HealRate with focus restrictions.
#define SE_FcTimerRefresh 389 // implemented - Refresh spell icons
#define SE_FcTimerLockout 390 // *not implemented - Sets recast timers to specific value, focus limited.
#define SE_LimitManaMax 391 // implemented
#define SE_FcHealAmt 392 // implemented - Adds or removes healing from spells
#define SE_FcHealPctIncoming 393 // implemented - HealRate with focus restrictions.
#define SE_FcHealAmtIncoming 394 // implemented - Adds/Removes amount of healing on target by X value with foucs restrictions.
#define SE_CriticalHealRate 395 // implemented[AA] - Increases chance of having a heal crit when cast on you. [focus limited]
#define SE_AdditionalHeal 396 // implemented - Adds a direct healing amount to spells
#define SE_FcHealPctCritIncoming 395 // implemented[AA] - Increases chance of having a heal crit when cast on you. [focus limited]
#define SE_FcHealAmtCrit 396 // implemented - Adds a direct healing amount to spells
#define SE_PetMeleeMitigation 397 // *not implemented[AA] - additional mitigation to your pets.
#define SE_SwarmPetDuration 398 // implemented - Affects the duration of swarm pets
#define SE_Twincast 399 // implemented - cast 2 spells for every 1
#define SE_FcTwincast 399 // implemented - cast 2 spells for every 1
#define SE_HealGroupFromMana 400 // implemented - Drains mana and heals for each point of mana drained
#define SE_ManaDrainWithDmg 401 // implemented - Deals damage based on the amount of mana drained
#define SE_EndDrainWithDmg 402 // implemented - Deals damage for the amount of endurance drained
#define SE_Ff_SpellClass 403 // *not implemented -
#define SE_LimitExcludeSkill 404 // implemented - Limit a focus to exclude spells cast using a specific skill.
#define SE_LimitSpellClass 403 // *not implemented - unclear what this refers too (not 'right click' spell bar)
#define SE_LimitSpellSubclass 404 // *not implemented - unclear what this refers too (not 'right click' spell bar)
#define SE_TwoHandBluntBlock 405 // implemented - chance to block attacks when using two hand blunt weapons (similiar to shield block)
#define SE_CastonNumHitFade 406 // implemented - casts a spell when a buff fades due to its numhits being depleted
#define SE_CastonFocusEffect 407 // implemented - casts a spell if focus limits are met (ie triggers when a focus effects is applied)
@ -560,16 +561,16 @@ typedef enum {
#define SE_LimitClass 411 // implemented - Limits to spells of a certain class (Note: The class value in dbase is +1 in relation to item class value)
#define SE_LimitRace 412 // implemented - Limits to spells cast by a certain race (Note: not used in any known live spells)
#define SE_FcBaseEffects 413 // implemented - Increases the power of bard songs, skill attacks, runes, bard allowed foci, damage/heal
#define SE_LimitSpellSkill 414 // implemented - Limit a focus to include spells cast using a specific skill.
#define SE_LimitCastingSkill 414 // implemented - Limit a focus to include spells cast using a specific skill.
//#define SE_FFItemClass 415 // not used
#define SE_ACv2 416 // implemented - New AC spell effect
#define SE_ManaRegen_v2 417 // implemented - New mana regen effect
#define SE_SkillDamageAmount2 418 // implemented - adds skill damage directly to certain attacks
#define SE_AddMeleeProc 419 // implemented - Adds a proc
#define SE_FcLimitUse 420 // implemented - increases numhits count by percent (Note: not used in any known live spells)
#define SE_IncreaseNumHits 421 // implemented[AA] - increases number of hits a buff has till fade. (focus)
#define SE_FfLimitUseMin 422 // implemented - limit a focus to require a min amount of numhits value (used with above)
#define SE_FfLimitUseType 423 // implemented - limit a focus to require a certain numhits type
#define SE_FcIncreaseNumHits 421 // implemented[AA] - increases number of hits a buff has till fade. (focus)
#define SE_LimitUseMin 422 // implemented - limit a focus to require a min amount of numhits value (used with above)
#define SE_LimitUseType 423 // implemented - limit a focus to require a certain numhits type
#define SE_GravityEffect 424 // implemented - Pulls/pushes you toward/away the mob at a set pace
#define SE_Display 425 // *not implemented - Illusion: Flying Dragon(21626)
#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window

View File

@ -1212,6 +1212,10 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
case SE_CriticalMend:
newbon->CriticalMend += base1;
break;
case SE_HealRate:
newbon->HealRate += base1;
break;
}
}
}
@ -1603,10 +1607,6 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
newbon->MeleeMitigation -= effect_value;
break;
case SE_IncreaseHitDmgTaken:
newbon->MeleeMitigation += effect_value;
break;
case SE_CriticalHitChance:
{
@ -2773,12 +2773,12 @@ uint8 Mob::IsFocusEffect(uint16 spell_id,int effect_index, bool AA,uint32 aa_eff
case SE_TriggerOnCast:
//return focusTriggerOnCast;
return 0; //This is calculated as an actual bonus
case SE_SpellVulnerability:
case SE_FcSpellVulnerability:
return focusSpellVulnerability;
case SE_BlockNextSpellFocus:
//return focusBlockNextSpell;
return 0; //This is calculated as an actual bonus
case SE_Twincast:
case SE_FcTwincast:
return focusTwincast;
case SE_SympatheticProc:
return focusSympatheticProc;
@ -2792,24 +2792,26 @@ uint8 Mob::IsFocusEffect(uint16 spell_id,int effect_index, bool AA,uint32 aa_eff
return focusFcDamageAmtIncoming;
case SE_FcHealAmtIncoming:
return focusFcHealAmtIncoming;
case SE_HealRate2:
return focusHealRate;
case SE_FcHealPctIncoming:
return focusFcHealPctIncoming;
case SE_FcBaseEffects:
return focusFcBaseEffects;
case SE_IncreaseNumHits:
case SE_FcIncreaseNumHits:
return focusIncreaseNumHits;
case SE_FcLimitUse:
return focusFcLimitUse;
case SE_FcMute:
return focusFcMute;
case SE_FcTimerRefresh:
return focusFcTimerRefresh;
case SE_FcStunTimeMod:
return focusFcStunTimeMod;
case SE_CriticalHealRate:
return focusCriticalHealRate;
case SE_AdditionalHeal2:
return focusAdditionalHeal2;
case SE_AdditionalHeal:
return focusAdditionalHeal;
case SE_FcHealPctCritIncoming:
return focusFcHealPctCritIncoming;
case SE_FcHealAmt:
return focusFcHealAmt;
case SE_FcHealAmtCrit:
return focusFcHealAmtCrit;
}
return 0;
}
@ -3115,12 +3117,6 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
aabonuses.MeleeMitigation = effect_value;
break;
case SE_IncreaseHitDmgTaken:
spellbonuses.MeleeMitigation = effect_value;
itembonuses.MeleeMitigation = effect_value;
aabonuses.MeleeMitigation = effect_value;
break;
case SE_CriticalHitChance:
{
for(int e = 0; e < HIGHEST_SKILL+1; e++)

View File

@ -6736,7 +6736,7 @@ int16 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id)
if((spell.classes[(GetClass()%16) - 1]) < base1)
LimitFound = true;
break;
case SE_LimitCastTime:
case SE_LimitCastTimeMin:
if (spell.cast_time < base1)
LimitFound = true;
break;
@ -6782,7 +6782,7 @@ int16 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id)
}
break;
case SE_LimitManaCost:
case SE_LimitManaMin:
if(spell.mana < base1)
LimitFound = true;
break;
@ -6800,7 +6800,7 @@ int16 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id)
}
break;
case SE_CombatSkills:
case SE_LimitCombatSkills:
// 1 is for disciplines only
if(base1 == 1 && !IsDiscipline(spell_id))
LimitFound = true;
@ -6817,13 +6817,13 @@ int16 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id)
break;
case SE_LimitSpellSkill:
case SE_LimitCastingSkill:
LimitSpellSkill = true;
if(base1 == spell.skill)
SpellSkill_Found = true;
break;
case SE_LimitExcludeSkill:{
case SE_LimitSpellSubclass:{
int16 spell_skill = spell.skill * -1;
if(base1 == spell_skill)
LimitFound = true;
@ -6941,7 +6941,7 @@ int16 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id)
}
break;
}
case SE_SpellVulnerability:
case SE_FcSpellVulnerability:
{
if(type == focusSpellVulnerability)
{
@ -6958,7 +6958,7 @@ int16 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id)
}
break;
}
case SE_Twincast:
case SE_FcTwincast:
{
if(type == focusTwincast)
{
@ -7010,37 +7010,30 @@ int16 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id)
break;
}
case SE_CriticalHealRate:
{
if (type == focusCriticalHealRate)
case SE_FcHealAmtIncoming:
if(type == focusFcHealAmtIncoming)
value = base1;
break;
}
case SE_AdditionalHeal:
{
if(type == focusAdditionalHeal)
case SE_FcHealPctCritIncoming:
if (type == focusFcHealPctCritIncoming)
value = base1;
break;
}
case SE_AdditionalHeal2:
{
if(type == focusAdditionalHeal2)
case SE_FcHealAmtCrit:
if(type == focusFcHealAmtCrit)
value = base1;
break;
}
case SE_HealRate2:
{
if(type == focusHealRate)
case SE_FcHealAmt:
if(type == focusFcHealAmt)
value = base1;
break;
case SE_FcHealPctIncoming:
if(type == focusFcHealPctIncoming)
value = base1;
break;
}
case SE_FcBaseEffects:
{
@ -7057,7 +7050,7 @@ int16 Bot::CalcBotAAFocus(BotfocusType type, uint32 aa_ID, uint16 spell_id)
break;
}
case SE_IncreaseNumHits:
case SE_FcIncreaseNumHits:
{
if(type == focusIncreaseNumHits)
value = base1;
@ -7338,7 +7331,7 @@ int16 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
return(0);
break;
case SE_LimitCastTime:
case SE_LimitCastTimeMin:
if (spells[spell_id].cast_time < (uint16)focus_spell.base[i])
return(0);
break;
@ -7398,7 +7391,7 @@ int16 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
}
break;
case SE_LimitManaCost:
case SE_LimitManaMin:
if(spell.mana < focus_spell.base[i])
return 0;
break;
@ -7413,7 +7406,7 @@ int16 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
break;
case SE_CombatSkills:
case SE_LimitCombatSkills:
// 1 is for disciplines only
if(focus_spell.base[i] == 1 && !IsDiscipline(spell_id))
return 0;
@ -7429,13 +7422,13 @@ int16 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
return 0;
break;
case SE_LimitSpellSkill:
case SE_LimitCastingSkill:
LimitSpellSkill = true;
if(focus_spell.base[i] == spell.skill)
SpellSkill_Found = true;
break;
case SE_LimitExcludeSkill:{
case SE_LimitSpellSubclass:{
int16 spell_skill = spell.skill * -1;
if(focus_spell.base[i] == spell_skill)
return 0;
@ -7602,7 +7595,7 @@ int16 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
break;
}
case SE_SpellVulnerability:
case SE_FcSpellVulnerability:
{
if(bottype == BotfocusSpellVulnerability)
{
@ -7619,7 +7612,7 @@ int16 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
}
break;
}
case SE_Twincast:
case SE_FcTwincast:
{
if(bottype == BotfocusTwincast)
{
@ -7660,45 +7653,30 @@ int16 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
break;
}
case SE_FcDamageAmtIncoming:
{
if(bottype == BotfocusFcDamageAmtIncoming)
case SE_FcHealAmtIncoming:
if(bottype == BotfocusFcHealAmtIncoming)
value = focus_spell.base[i];
break;
}
case SE_CriticalHealRate:
{
if (bottype == BotfocusCriticalHealRate)
case SE_FcHealPctCritIncoming:
if (bottype == BotfocusFcHealPctCritIncoming)
value = focus_spell.base[i];
break;
}
case SE_AdditionalHeal:
{
if(bottype == BotfocusAdditionalHeal)
case SE_FcHealAmtCrit:
if(bottype == BotfocusFcHealAmtCrit)
value = focus_spell.base[i];
break;
}
case SE_AdditionalHeal2:
{
if(bottype == BotfocusAdditionalHeal2)
case SE_FcHealAmt:
if(bottype == BotfocusFcHealAmt)
value = focus_spell.base[i];
break;
}
case SE_HealRate2:
{
if(bottype == BotfocusHealRate)
case SE_FcHealPctIncoming:
if(bottype == BotfocusFcHealPctIncoming)
value = focus_spell.base[i];
break;
}
case SE_FcBaseEffects:
{
@ -7715,7 +7693,7 @@ int16 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
break;
}
case SE_IncreaseNumHits:
case SE_FcIncreaseNumHits:
{
if(bottype == BotfocusIncreaseNumHits)
value = focus_spell.base[i];
@ -9119,23 +9097,6 @@ void Bot::SetAttackTimer() {
}
}
int32 Bot::Additional_SpellDmg(uint16 spell_id, bool bufftick)
{
int32 spell_dmg = 0;
spell_dmg += GetBotFocusEffect(BotfocusFcDamageAmtCrit, spell_id);
spell_dmg += GetBotFocusEffect(BotfocusFcDamageAmt, spell_id);
//For DOTs you need to apply the damage over the duration of the dot to each tick (this is how live did it)
if (bufftick){
int duration = CalcBuffDuration(this, this, spell_id);
if (duration > 0)
return spell_dmg /= duration;
else
return 0;
}
return spell_dmg;
}
int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
if (spells[spell_id].targettype == ST_Self)
@ -9196,7 +9157,7 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id);
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value += GetExtraSpellDmg(spell_id, itembonuses.SpellDmg, value)*ratio/100;
value += GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio/100;
entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s delivers a critical blast! (%d)", GetName(), -value);
@ -9220,70 +9181,73 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
value -= GetBotFocusEffect(BotfocusFcDamageAmt, spell_id);
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value += GetExtraSpellDmg(spell_id, itembonuses.SpellDmg, value);
value += GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value);
return value;
}
int32 Bot::Additional_Heal(uint16 spell_id)
{
int32 heal_amt = 0;
int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (target == nullptr)
target = this;
heal_amt += GetBotFocusEffect(BotfocusAdditionalHeal, spell_id);
heal_amt += GetBotFocusEffect(BotfocusAdditionalHeal2, spell_id);
if (heal_amt){
int duration = CalcBuffDuration(this, this, spell_id);
if (duration > 0)
return heal_amt /= duration;
}
return heal_amt;
}
int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value) {
int32 modifier = 100;
int16 heal_amt = 0;
modifier += GetBotFocusEffect(BotfocusImprovedHeal, spell_id);
modifier += GetBotFocusEffect(BotfocusFcBaseEffects, spell_id);
heal_amt += Additional_Heal(spell_id);
int chance = 0;
int32 value_BaseEffect = 0;
int16 chance = 0;
int8 modifier = 1;
bool Critical = false;
value_BaseEffect = value + (value*GetBotFocusEffect(BotfocusFcBaseEffects, spell_id)/100);
value = value_BaseEffect;
value += int(value_BaseEffect*GetBotFocusEffect(BotfocusImprovedHeal, spell_id)/100);
// Instant Heals
if(spells[spell_id].buffduration < 1) {
uint8 botlevel = GetLevel();
uint8 botclass = GetClass();
// Formula = HealAmt * (casttime + recastime) / 7; Cant trigger off spell less than 5 levels below and cant heal more than the spell itself.
if(this->itembonuses.HealAmt && spells[spell_id].classes[(botclass%16) - 1] >= botlevel - 5) {
heal_amt = this->itembonuses.HealAmt * (spells[spell_id].cast_time + spells[spell_id].recast_time) / 7000;
if(heal_amt > value)
heal_amt = value;
}
// Check for buffs that affect the healrate of the target and critical heal rate of target
if(GetTarget()) {
value += value * GetHealRate(spell_id) / 100;
chance += GetCriticalHealRate(spell_id);
}
chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance;
//Live AA - Healing Gift, Theft of Life
chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance;
chance += target->GetFocusIncoming(focusFcHealPctCritIncoming, SE_FcHealPctCritIncoming, this, spell_id);
if (spellbonuses.CriticalHealDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay);
if(chance && (MakeRandomInt(0,99) < chance)) {
Critical = true;
modifier = 2; //At present time no critical heal amount modifier SPA exists.
}
value *= modifier;
value += GetBotFocusEffect(BotfocusFcHealAmtCrit, spell_id) * modifier;
value += GetBotFocusEffect(BotfocusFcHealAmt, spell_id);
value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id);
if(MakeRandomInt(0,99) < chance) {
entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s performs an exceptional heal! (%d)", GetName(), ((value * modifier / 50) + heal_amt*2));
return ((value * modifier / 50) + heal_amt*2);
}
else{
return ((value * modifier / 100) + heal_amt);
}
if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier;
value += value*target->GetHealRate(spell_id, this)/100;
if (Critical)
entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s performs an exceptional heal! (%d)", GetName(), value);
return value;
}
// Hots
//Heal over time spells. [Heal Rate and Additional Healing effects do not increase this value]
else {
chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance;
if(MakeRandomInt(0,99) < chance)
return ((value * modifier / 50) + heal_amt*2);
chance = itembonuses.CriticalHealOverTime + spellbonuses.CriticalHealOverTime + aabonuses.CriticalHealOverTime;
chance += target->GetFocusIncoming(focusFcHealPctCritIncoming, SE_FcHealPctCritIncoming, this, spell_id);
if (spellbonuses.CriticalRegenDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay);
if(chance && (MakeRandomInt(0,99) < chance))
return (value * 2);
}
return ((value * modifier / 100) + heal_amt);
return value;
}
int32 Bot::GetActSpellCasttime(uint16 spell_id, int32 casttime) {

View File

@ -86,13 +86,14 @@ public:
BotfocusSwarmPetDuration,
BotfocusReduceRecastTime,
BotfocusBlockNextSpell,
BotfocusHealRate,
BotfocusFcHealPctIncoming,
BotfocusFcDamageAmtIncoming,
BotfocusFcHealAmtIncoming,
BotfocusFcBaseEffects,
BotfocusIncreaseNumHits,
BotfocusCriticalHealRate,
BotfocusAdditionalHeal2,
BotfocusAdditionalHeal,
BotfocusFcHealPctCritIncoming,
BotfocusFcHealAmt,
BotfocusFcHealAmtCrit,
};
enum BotTradeType { // types of trades a bot can do
@ -301,10 +302,8 @@ public:
// Mob Spell Virtual Override Methods
virtual void SpellProcess();
int32 Additional_SpellDmg(uint16 spell_id, bool bufftick = false);
int32 Additional_Heal(uint16 spell_id);
virtual int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target);
virtual int32 GetActSpellHealing(uint16 spell_id, int32 value);
virtual int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr);
virtual int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr);
virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime);
virtual int32 GetActSpellCost(uint16 spell_id, int32 cost);
virtual float GetActSpellRange(uint16 spell_id, float range);

View File

@ -427,7 +427,6 @@ Client::~Client() {
eqs->Close();
eqs->ReleaseFromUse();
//entity_list.RemoveClient(this);
UninitializeBuffSlots();
}
@ -1083,10 +1082,12 @@ void Client::ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_s
{
// Emotes for Underfoot and later.
// crash protection -- cheater
if (strlen(message) > 512)
message[1023] = '\0';
size_t msg_len = strlen(message);
if (msg_len > 512)
message[512] = '\0';
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Emote, 4 + strlen(message) + strlen(GetName()) + 2);
EQApplicationPacket* outapp = new EQApplicationPacket(OP_Emote, 4 + msg_len + strlen(GetName()) + 2);
Emote_Struct* es = (Emote_Struct*)outapp->pBuffer;
char *Buffer = (char *)es;
Buffer += 4;

View File

@ -472,11 +472,9 @@ public:
inline virtual int16 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath + 11; }
int32 Additional_SpellDmg(uint16 spell_id, bool bufftick = false);
int32 Additional_Heal(uint16 spell_id);
float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false);
int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob *target = nullptr);
int32 GetActSpellHealing(uint16 spell_id, int32 value);
int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr);
int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr);
int32 GetActSpellCost(uint16 spell_id, int32);
int32 GetActSpellDuration(uint16 spell_id, int32);
int32 GetActSpellCasttime(uint16 spell_id, int32);

View File

@ -7361,6 +7361,8 @@ void Client::Handle_OP_Emote(const EQApplicationPacket *app)
// Calculate new packet dimensions
Emote_Struct* in = (Emote_Struct*)app->pBuffer;
in->message[1023] = '\0';
const char* name = GetName();
uint32 len_name = strlen(name);
uint32 len_msg = strlen(in->message);
@ -11624,6 +11626,7 @@ void Client::Handle_OP_GMSearchCorpse(const EQApplicationPacket *app)
}
GMSearchCorpse_Struct *gmscs = (GMSearchCorpse_Struct *)app->pBuffer;
gmscs->Name[63] = '\0';
char errbuf[MYSQL_ERRMSG_SIZE];
char* Query = 0;

View File

@ -71,19 +71,20 @@ typedef enum { //focus types
focusSwarmPetDuration,
focusReduceRecastTime,
focusBlockNextSpell,
focusHealRate,
focusFcHealPctIncoming,
focusFcDamageAmtIncoming,
focusFcHealAmtIncoming,
focusFcBaseEffects,
focusIncreaseNumHits,
focusFcLimitUse,
focusFcMute,
focusFcTimerRefresh,
focusFcStunTimeMod,
focusCriticalHealRate,
focusAdditionalHeal2,
focusAdditionalHeal,
focusFcHealPctCritIncoming,
focusFcHealAmt,
focusFcHealAmtCrit,
} focusType; //Any new FocusType needs to be added to the Mob::IsFocus function
#define HIGHEST_FOCUS focusAdditionalHeal //Should always be last focusType in enum
#define HIGHEST_FOCUS focusFcHealAmtCrit //Should always be last focusType in enum
enum {
SPECATK_SUMMON = 1,
@ -120,7 +121,8 @@ enum {
LEASH = 32,
TETHER = 33,
DESTRUCTIBLE_OBJECT = 34,
NO_HARM_FROM_CLIENT = 35
NO_HARM_FROM_CLIENT = 35,
MAX_SPECIAL_ATTACK = 36
};
typedef enum { //fear states

View File

@ -40,23 +40,6 @@ float Client::GetActSpellRange(uint16 spell_id, float range, bool IsBard)
}
int32 Client::Additional_SpellDmg(uint16 spell_id, bool bufftick)
{
int32 spell_dmg = 0;
spell_dmg += GetFocusEffect(focusFcDamageAmtCrit, spell_id);
spell_dmg += GetFocusEffect(focusFcDamageAmt, spell_id);
//For DOTs you need to apply the damage over the duration of the dot to each tick (this is how live did it)
if (bufftick){
int duration = CalcBuffDuration(this, this, spell_id);
if (duration > 0)
return spell_dmg /= duration;
else
return 0;
}
return spell_dmg;
}
int32 NPC::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
//Quest scale all NPC spell damage via $npc->SetSpellFocusDMG(value)
@ -138,7 +121,7 @@ int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
value -= GetFocusEffect(focusFcDamageAmt, spell_id);
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value += GetExtraSpellDmg(spell_id, itembonuses.SpellDmg, value)*ratio/100;
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio/100;
entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s delivers a critical blast! (%d)", GetName(), -value);
@ -162,7 +145,7 @@ int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
value -= GetFocusEffect(focusFcDamageAmt, spell_id);
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value += GetExtraSpellDmg(spell_id, itembonuses.SpellDmg, value);
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value);
return value;
}
@ -184,7 +167,7 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
if (chance > 0 && (MakeRandomInt(1, 100) <= chance)) {
int32 ratio = 100;
int32 ratio = 200;
ratio += itembonuses.DotCritDmgIncrease + spellbonuses.DotCritDmgIncrease + aabonuses.DotCritDmgIncrease;
value = value_BaseEffect*ratio/100;
@ -199,8 +182,11 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
int(GetFocusEffect(focusFcDamageAmtCrit, spell_id)*ratio/100) +
GetFocusEffect(focusFcDamageAmt, spell_id);
if (extra_dmg)
extra_dmg /= CalcBuffDuration(this, this, spell_id);
if (extra_dmg) {
int duration = CalcBuffDuration(this, this, spell_id);
if (duration > 0)
extra_dmg /= duration;
}
value -= extra_dmg;
@ -220,41 +206,18 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
GetFocusEffect(focusFcDamageAmtCrit, spell_id) +
GetFocusEffect(focusFcDamageAmt, spell_id);
if (extra_dmg)
extra_dmg /= CalcBuffDuration(this, this, spell_id);
if (extra_dmg) {
int duration = CalcBuffDuration(this, this, spell_id);
if (duration > 0)
extra_dmg /= duration;
}
value -= extra_dmg;
return value;
}
/*
int32 modifier = 100;
int16 spell_dmg = 0;
int16 critChance = 0;
int32 ratio = 0;
modifier += GetFocusEffect(focusImprovedDamage, spell_id);
critChance += itembonuses.CriticalDoTChance + spellbonuses.CriticalDoTChance + aabonuses.CriticalDoTChance;
ratio += itembonuses.DotCritDmgIncrease + spellbonuses.DotCritDmgIncrease + aabonuses.DotCritDmgIncrease;
spell_dmg += Additional_SpellDmg(spell_id,true);
if (spellbonuses.CriticalDotDecay)
critChance += GetDecayEffectValue(spell_id, SE_CriticalDotDecay);
if (critChance > 0){
if (MakeRandomInt(0, 99) < critChance){
modifier += modifier*ratio/100;
return (((value*modifier/100)-spell_dmg)*2);
}
}
return ((value*modifier/100)-spell_dmg);
*/
int32 Mob::GetExtraSpellDmg(uint16 spell_id, int32 extra_spell_dmg, int32 base_spell_dmg)
int32 Mob::GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_spell_dmg)
{
int total_cast_time = 0;
@ -264,105 +227,98 @@ int32 Mob::GetExtraSpellDmg(uint16 spell_id, int32 extra_spell_dmg, int32 base_s
total_cast_time = spells[spell_id].recovery_time + spells[spell_id].cast_time;
if (total_cast_time > 0 && total_cast_time <= 2500)
extra_spell_dmg = extra_spell_dmg*25/100;
extra_spell_amt = extra_spell_amt*25/100;
else if (total_cast_time > 2500 && total_cast_time < 7000)
extra_spell_dmg = extra_spell_dmg*(0.167*((total_cast_time - 1000)/1000));
extra_spell_amt = extra_spell_amt*(0.167*((total_cast_time - 1000)/1000));
else
extra_spell_dmg = extra_spell_dmg * total_cast_time / 7000;
extra_spell_amt = extra_spell_amt * total_cast_time / 7000;
extra_spell_dmg = -extra_spell_dmg;
if(extra_spell_dmg*2 < base_spell_dmg)
if(extra_spell_amt*2 < base_spell_dmg)
return 0;
return extra_spell_dmg;
return extra_spell_amt;
}
//Scale all NPC spell healing via SetSpellFocusHeal(value)
int32 NPC::GetActSpellHealing(uint16 spell_id, int32 value) {
int32 NPC::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
int32 modifier = 100;
modifier += SpellFocusHeal;
//Scale all NPC spell healing via SetSpellFocusHeal(value)
// Check for buffs that affect the healrate of the target
if(this->GetTarget())
{
value += value * GetHealRate(spell_id) / 100;
}
value += value*SpellFocusHeal/100;
return (value * modifier / 100);
if (target) {
value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id);
value += value*target->GetHealRate(spell_id, this)/100;
}
return value;
}
int32 Client::Additional_Heal(uint16 spell_id)
{
int32 heal_amt = 0;
int32 Client::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (target == nullptr)
target = this;
heal_amt += GetFocusEffect(focusAdditionalHeal, spell_id);
heal_amt += GetFocusEffect(focusAdditionalHeal2, spell_id);
heal_amt -= GetFocusEffect(focusFcHealAmtIncoming, spell_id);
if (heal_amt){
int duration = CalcBuffDuration(this, this, spell_id);
if (duration > 0)
return heal_amt /= duration;
}
return heal_amt;
}
int32 Client::GetActSpellHealing(uint16 spell_id, int32 value) {
int32 modifier = 100;
int16 heal_amt = 0;
modifier += GetFocusEffect(focusImprovedHeal, spell_id);
modifier += GetFocusEffect(focusFcBaseEffects, spell_id);
heal_amt += Additional_Heal(spell_id);
int chance = 0;
int32 value_BaseEffect = 0;
int16 chance = 0;
int8 modifier = 1;
bool Critical = false;
value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id)/100);
value = value_BaseEffect;
value += int(value_BaseEffect*GetFocusEffect(focusImprovedHeal, spell_id)/100);
// Instant Heals
if(spells[spell_id].buffduration < 1)
{
// Formula = HealAmt * (casttime + recastime) / 7; Cant trigger off spell less than 5 levels below and cant heal more than the spell itself.
if(this->itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) {
heal_amt = this->itembonuses.HealAmt * (spells[spell_id].cast_time + spells[spell_id].recast_time) / 7000;
if(heal_amt > value)
heal_amt = value;
}
if(spells[spell_id].buffduration < 1) {
// Check for buffs that affect the healrate of the target and critical heal rate of target
if(GetTarget()){
value += value * GetHealRate(spell_id) / 100;
chance += GetCriticalHealRate(spell_id);
}
chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance;
//Live AA - Healing Gift, Theft of Life
chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance;
chance += target->GetFocusIncoming(focusFcHealPctCritIncoming, SE_FcHealPctCritIncoming, this, spell_id);
if (spellbonuses.CriticalRegenDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay);
if (spellbonuses.CriticalHealDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay);
if(chance && (MakeRandomInt(0,99) < chance)) {
Critical = true;
modifier = 2; //At present time no critical heal amount modifier SPA exists.
}
value *= modifier;
value += GetFocusEffect(focusFcHealAmtCrit, spell_id) * modifier;
value += GetFocusEffect(focusFcHealAmt, spell_id);
value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id);
if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier;
if(MakeRandomInt(0,99) < chance) {
entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s performs an exceptional heal! (%d)", GetName(), ((value * modifier / 50) + heal_amt*2));
return ((value * modifier / 50) + heal_amt*2);
}
else{
return ((value * modifier / 100) + heal_amt);
}
value += value*target->GetHealRate(spell_id, this)/100;
if (Critical)
entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s performs an exceptional heal! (%d)", GetName(), value);
return value;
}
// Hots
//Heal over time spells. [Heal Rate and Additional Healing effects do not increase this value]
else {
chance += itembonuses.CriticalHealOverTime + spellbonuses.CriticalHealOverTime + aabonuses.CriticalHealOverTime;
chance = itembonuses.CriticalHealOverTime + spellbonuses.CriticalHealOverTime + aabonuses.CriticalHealOverTime;
chance += target->GetFocusIncoming(focusFcHealPctCritIncoming, SE_FcHealPctCritIncoming, this, spell_id);
if (spellbonuses.CriticalRegenDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay);
chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay);
if(MakeRandomInt(0,99) < chance)
return ((value * modifier / 50) + heal_amt*2);
if(chance && (MakeRandomInt(0,99) < chance))
return (value * 2);
}
return ((value * modifier / 100) + heal_amt);
return value;
}
int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
{
// Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell

View File

@ -2031,12 +2031,12 @@ bool EntityList::RemoveMob(uint16 delete_id)
auto it = mob_list.find(delete_id);
if (it != mob_list.end()) {
if (npc_list.find(delete_id) != npc_list.end())
if (npc_list.count(delete_id))
entity_list.RemoveNPC(delete_id);
else if (client_list.find(delete_id) != client_list.end())
else if (client_list.count(delete_id))
entity_list.RemoveClient(delete_id);
safe_delete(it->second);
if (corpse_list.find(delete_id) == corpse_list.end())
if (!corpse_list.count(delete_id))
free_ids.push(it->first);
mob_list.erase(it);
return true;
@ -2054,7 +2054,7 @@ bool EntityList::RemoveMob(Mob *delete_mob)
while (it != mob_list.end()) {
if (it->second == delete_mob) {
safe_delete(it->second);
if (corpse_list.find(it->first) == corpse_list.end())
if (!corpse_list.count(it->first))
free_ids.push(it->first);
mob_list.erase(it);
return true;

View File

@ -1057,17 +1057,27 @@ void Client::LeaveGroup() {
isgrouped = false;
}
void Group::HealGroup(uint32 heal_amt, Mob* caster)
void Group::HealGroup(uint32 heal_amt, Mob* caster, int32 range)
{
if (!caster)
return;
if (!range)
range = 200;
float distance;
float range2 = range*range;
int numMem = 0;
unsigned int gi = 0;
for(; gi < MAX_GROUP_MEMBERS; gi++)
{
if(members[gi]){
numMem += 1;
distance = caster->DistNoRoot(*members[gi]);
if(distance <= range2){
numMem += 1;
}
}
}
@ -1075,23 +1085,38 @@ void Group::HealGroup(uint32 heal_amt, Mob* caster)
for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++)
{
if(members[gi]){
//members[gi]->SetHP(members[gi]->GetHP() + heal_amt);
members[gi]->HealDamage(heal_amt, caster);
members[gi]->SendHPUpdate();
distance = caster->DistNoRoot(*members[gi]);
if(distance <= range2){
members[gi]->HealDamage(heal_amt, caster);
members[gi]->SendHPUpdate();
}
}
}
}
void Group::BalanceHP(int32 penalty)
void Group::BalanceHP(int32 penalty, int32 range, Mob* caster)
{
if (!caster)
return;
if (!range)
range = 200;
int dmgtaken = 0, numMem = 0;
float distance;
float range2 = range*range;
unsigned int gi = 0;
for(; gi < MAX_GROUP_MEMBERS; gi++)
{
if(members[gi]){
dmgtaken += (members[gi]->GetMaxHP() - members[gi]->GetHP());
numMem += 1;
distance = caster->DistNoRoot(*members[gi]);
if(distance <= range2){
dmgtaken += (members[gi]->GetMaxHP() - members[gi]->GetHP());
numMem += 1;
}
}
}
@ -1100,27 +1125,42 @@ void Group::BalanceHP(int32 penalty)
for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++)
{
if(members[gi]){
if((members[gi]->GetMaxHP() - dmgtaken) < 1){ //this way the ability will never kill someone
members[gi]->SetHP(1); //but it will come darn close
members[gi]->SendHPUpdate();
}
else{
members[gi]->SetHP(members[gi]->GetMaxHP() - dmgtaken);
members[gi]->SendHPUpdate();
distance = caster->DistNoRoot(*members[gi]);
if(distance <= range2){
if((members[gi]->GetMaxHP() - dmgtaken) < 1){ //this way the ability will never kill someone
members[gi]->SetHP(1); //but it will come darn close
members[gi]->SendHPUpdate();
}
else{
members[gi]->SetHP(members[gi]->GetMaxHP() - dmgtaken);
members[gi]->SendHPUpdate();
}
}
}
}
}
void Group::BalanceMana(int32 penalty)
void Group::BalanceMana(int32 penalty, int32 range, Mob* caster)
{
if (!caster)
return;
if (!range)
range = 200;
float distance;
float range2 = range*range;
int manataken = 0, numMem = 0;
unsigned int gi = 0;
for(; gi < MAX_GROUP_MEMBERS; gi++)
{
if(members[gi]){
manataken += (members[gi]->GetMaxMana() - members[gi]->GetMana());
numMem += 1;
if(members[gi]){
distance = caster->DistNoRoot(*members[gi]);
if(distance <= range2){
manataken += (members[gi]->GetMaxMana() - members[gi]->GetMana());
numMem += 1;
}
}
}
@ -1129,15 +1169,18 @@ void Group::BalanceMana(int32 penalty)
for(gi = 0; gi < MAX_GROUP_MEMBERS; gi++)
{
if(members[gi]){
if((members[gi]->GetMaxMana() - manataken) < 1){
members[gi]->SetMana(1);
if (members[gi]->IsClient())
members[gi]->CastToClient()->SendManaUpdate();
}
else{
members[gi]->SetMana(members[gi]->GetMaxMana() - manataken);
if (members[gi]->IsClient())
members[gi]->CastToClient()->SendManaUpdate();
distance = caster->DistNoRoot(*members[gi]);
if(distance <= range2){
if((members[gi]->GetMaxMana() - manataken) < 1){
members[gi]->SetMana(1);
if (members[gi]->IsClient())
members[gi]->CastToClient()->SendManaUpdate();
}
else{
members[gi]->SetMana(members[gi]->GetMaxMana() - manataken);
if (members[gi]->IsClient())
members[gi]->CastToClient()->SendManaUpdate();
}
}
}
}

View File

@ -86,9 +86,9 @@ public:
uint16 GetAvgLevel();
bool LearnMembers();
void VerifyGroup();
void BalanceHP(int32 penalty);
void BalanceMana(int32 penalty);
void HealGroup(uint32 heal_amt, Mob* caster);
void BalanceHP(int32 penalty, int32 range = 0, Mob* caster = nullptr);
void BalanceMana(int32 penalty, int32 range = 0, Mob* caster = nullptr);
void HealGroup(uint32 heal_amt, Mob* caster, int32 range = 0);
inline void SetGroupAAs(GroupLeadershipAA_Struct *From) { memcpy(&LeaderAbilities, From, sizeof(GroupLeadershipAA_Struct)); }
inline void GetGroupAAs(GroupLeadershipAA_Struct *Into) { memcpy(Into, &LeaderAbilities, sizeof(GroupLeadershipAA_Struct)); }
void UpdateGroupAAs();

View File

@ -2771,22 +2771,6 @@ int16 Merc::GetFocusEffect(focusType type, uint16 spell_id) {
return realTotal + realTotal2 + realTotal3;
}
int32 Merc::Additional_SpellDmg(uint16 spell_id, bool bufftick)
{
int32 spell_dmg = 0;
spell_dmg += GetFocusEffect(focusFcDamageAmtCrit, spell_id);
spell_dmg += GetFocusEffect(focusFcDamageAmt, spell_id);
//For DOTs you need to apply the damage over the duration of the dot to each tick (this is how live did it)
if (bufftick){
int duration = CalcBuffDuration(this, this, spell_id);
if (duration > 0)
return spell_dmg /= duration;
else
return 0;
}
return spell_dmg;
}
int32 Merc::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
@ -2836,7 +2820,7 @@ int32 Merc::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
value -= GetFocusEffect(focusFcDamageAmt, spell_id);
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value += GetExtraSpellDmg(spell_id, itembonuses.SpellDmg, value)*ratio/100;
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio/100;
value = (value * GetSpellScale() / 100);
@ -2862,76 +2846,75 @@ int32 Merc::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
value -= GetFocusEffect(focusFcDamageAmt, spell_id);
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value += GetExtraSpellDmg(spell_id, itembonuses.SpellDmg, value);
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value);
value = (value * GetSpellScale() / 100);
return value;
}
int32 Merc::Additional_Heal(uint16 spell_id)
{
int32 heal_amt = 0;
int32 Merc::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (target == nullptr)
target = this;
heal_amt += GetFocusEffect(focusAdditionalHeal, spell_id);
heal_amt += GetFocusEffect(focusAdditionalHeal2, spell_id);
heal_amt += GetFocusEffect(focusFcHealAmtIncoming, spell_id);
if (heal_amt){
int duration = CalcBuffDuration(this, this, spell_id);
if (duration > 0)
return heal_amt /= duration;
}
return heal_amt;
}
int32 Merc::GetActSpellHealing(uint16 spell_id, int32 value) {
int32 modifier = 100;
int16 heal_amt = 0;
modifier += GetFocusEffect(focusImprovedHeal, spell_id);
modifier += GetFocusEffect(focusFcBaseEffects, spell_id);
heal_amt += Additional_Heal(spell_id);
int chance = 0;
int32 value_BaseEffect = 0;
int16 chance = 0;
int8 modifier = 1;
bool Critical = false;
value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id)/100);
value = value_BaseEffect;
value += int(value_BaseEffect*GetFocusEffect(focusImprovedHeal, spell_id)/100);
// Instant Heals
if(spells[spell_id].buffduration < 1)
{
// Formula = HealAmt * (casttime + recastime) / 7; Cant trigger off spell less than 5 levels below and cant heal more than the spell itself.
if(this->itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) {
heal_amt = this->itembonuses.HealAmt * (spells[spell_id].cast_time + spells[spell_id].recast_time) / 7000;
if(heal_amt > value)
heal_amt = value;
}
if(spells[spell_id].buffduration < 1) {
// Check for buffs that affect the healrate of the target and critical heal rate of target
if(GetTarget()){
value += value * GetHealRate(spell_id) / 100;
chance += GetCriticalHealRate(spell_id);
}
chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance;
//Live AA - Healing Gift, Theft of Life
chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance;
chance += target->GetFocusIncoming(focusFcHealPctCritIncoming, SE_FcHealPctCritIncoming, this, spell_id);
if (spellbonuses.CriticalHealDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay);
if(chance && (MakeRandomInt(0,99) < chance)) {
Critical = true;
modifier = 2; //At present time no critical heal amount modifier SPA exists.
}
value *= modifier;
value += GetFocusEffect(focusFcHealAmtCrit, spell_id) * modifier;
value += GetFocusEffect(focusFcHealAmt, spell_id);
value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id);
if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier;
if(MakeRandomInt(0,99) < chance) {
entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s performs an exceptional heal! (%d)", GetName(), ((value * modifier / 50) + heal_amt*2));
heal_amt = ((value * modifier / 50) + heal_amt*2);
}
else{
heal_amt = ((value * modifier / 100) + heal_amt);
}
value += value*target->GetHealRate(spell_id, this)/100;
if (Critical)
entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s performs an exceptional heal! (%d)", GetName(), value);
return value;
}
// Hots
//Heal over time spells. [Heal Rate and Additional Healing effects do not increase this value]
else {
chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance;
if(MakeRandomInt(0,99) < chance)
heal_amt = ((value * modifier / 50) + heal_amt*2);
chance = itembonuses.CriticalHealOverTime + spellbonuses.CriticalHealOverTime + aabonuses.CriticalHealOverTime;
chance += target->GetFocusIncoming(focusFcHealPctCritIncoming, SE_FcHealPctCritIncoming, this, spell_id);
if (spellbonuses.CriticalRegenDecay)
chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay);
if(chance && (MakeRandomInt(0,99) < chance))
return (value * 2);
}
heal_amt = (heal_amt * GetHealScale() / 100);
return heal_amt;
return value;
}
int32 Merc::GetActSpellCost(uint16 spell_id, int32 cost)

View File

@ -77,10 +77,8 @@ public:
Corpse* GetGroupMemberCorpse();
// Merc Spell Casting Methods
int32 Additional_SpellDmg(uint16 spell_id, bool bufftick = false);
int32 Additional_Heal(uint16 spell_id);
virtual int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr);
virtual int32 GetActSpellHealing(uint16 spell_id, int32 value);
virtual int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr);
virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime);
virtual int32 GetActSpellCost(uint16 spell_id, int32 cost);
int8 GetChanceToCastBySpellType(int16 spellType);

View File

@ -385,16 +385,6 @@ Mob::Mob(const char* in_name,
Mob::~Mob()
{
// Our Entity ID is set to 0 in NPC::Death. This leads to mobs hanging around for a while in
// the entity list, even after they have been destroyed. Use our memory pointer to remove the mob
// if our EntityID is 0.
//
/*if(GetID() > 0)
entity_list.RemoveMob(GetID());
else
entity_list.RemoveMob(this);*/
AI_Stop();
if (GetPet()) {
if (GetPet()->Charmed())
@ -402,8 +392,6 @@ Mob::~Mob()
else
SetPet(0);
}
ClearSpecialAbilities();
EQApplicationPacket app;
CreateDespawnPacket(&app, !IsCorpse());
@ -3336,7 +3324,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id)
int buff_count = GetMaxTotalSlots();
for(int i = 0; i < buff_count; i++)
{
if(IsEffectInSpell(buffs[i].spellid, SE_Twincast))
if(IsEffectInSpell(buffs[i].spellid, SE_FcTwincast))
{
int32 focus = CalcFocusEffect(focusTwincast, buffs[i].spellid, spell_id);
if(focus > 0)
@ -3378,7 +3366,7 @@ int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining)
int buff_count = GetMaxTotalSlots();
for(int i = 0; i < buff_count; i++) {
if((IsValidSpell(buffs[i].spellid) && IsEffectInSpell(buffs[i].spellid, SE_SpellVulnerability))){
if((IsValidSpell(buffs[i].spellid) && IsEffectInSpell(buffs[i].spellid, SE_FcSpellVulnerability))){
int32 focus = caster->CalcFocusEffect(focusSpellVulnerability, buffs[i].spellid, spell_id);
@ -3429,37 +3417,19 @@ int16 Mob::GetSkillDmgTaken(const SkillUseTypes skill_used)
return skilldmg_mod;
}
int16 Mob::GetHealRate(uint16 spell_id)
{
Mob* target = GetTarget();
int16 Mob::GetHealRate(uint16 spell_id, Mob* caster) {
int16 heal_rate = 0;
if (target){
heal_rate = target->itembonuses.HealRate + target->spellbonuses.HealRate;
if (target->IsClient())
heal_rate += target->CastToClient()->GetFocusEffect(focusHealRate, spell_id);
if(heal_rate < -99)
heal_rate = -99;
}
heal_rate += itembonuses.HealRate + spellbonuses.HealRate + aabonuses.HealRate;
heal_rate += GetFocusIncoming(focusFcHealPctIncoming, SE_FcHealPctIncoming, caster, spell_id);
if(heal_rate < -99)
heal_rate = -99;
return heal_rate;
}
int16 Mob::GetCriticalHealRate(uint16 spell_id)
{
Mob* target = GetTarget();
int16 critical_heal_rate = 0;
if (target && target->IsClient())
critical_heal_rate = target->CastToClient()->GetFocusEffect(focusCriticalHealRate, spell_id);
return critical_heal_rate;
}
bool Mob::TryFadeEffect(int slot)
{
if(IsValidSpell(buffs[slot].spellid))
@ -4669,7 +4639,7 @@ int8 Mob::GetDecayEffectValue(uint16 spell_id, uint16 spelleffect) {
if (!IsValidSpell(spell_id))
return false;
int spell_level = spells[spell_id].classes[(GetClass()%16) - 1];
int spell_level = spells[spell_id].classes[(GetClass()%16) - 1];
int effect_value = 0;
int lvlModifier = 100;
@ -4679,15 +4649,15 @@ int8 Mob::GetDecayEffectValue(uint16 spell_id, uint16 spelleffect) {
for (int i = 0; i < EFFECT_COUNT; i++){
if(spells[buffs[slot].spellid].effectid[i] == spelleffect) {
int critchance = spells[buffs[slot].spellid].base[i];
int critchance = spells[buffs[slot].spellid].base[i];
int decay = spells[buffs[slot].spellid].base2[i];
int lvldiff = spell_level - spells[buffs[slot].spellid].max[i];
int lvldiff = spell_level - spells[buffs[slot].spellid].max[i];
if(lvldiff > 0 && decay > 0)
{
lvlModifier -= decay*lvldiff;
lvlModifier -= decay*lvldiff;
if (lvlModifier > 0){
critchance = (critchance*lvlModifier)/100;
critchance = (critchance*lvlModifier)/100;
effect_value += critchance;
}
}
@ -4907,111 +4877,74 @@ bool Mob::HasSpellEffect(int effectid)
}
int Mob::GetSpecialAbility(int ability) {
if (SpecialAbilities.count(ability))
return SpecialAbilities.at(ability).level;
return 0;
}
int Mob::GetSpecialAbilityParam(int ability, int param) {
if(param >= MAX_SPECIAL_ATTACK_PARAMS || param < 0) {
if(ability >= MAX_SPECIAL_ATTACK || ability < 0) {
return 0;
}
auto iter = SpecialAbilities.find(ability);
if(iter != SpecialAbilities.end()) {
return iter->second.params[param];
return SpecialAbilities[ability].level;
}
int Mob::GetSpecialAbilityParam(int ability, int param) {
if(param >= MAX_SPECIAL_ATTACK_PARAMS || param < 0 || ability >= MAX_SPECIAL_ATTACK || ability < 0) {
return 0;
}
return 0;
return SpecialAbilities[ability].params[param];
}
void Mob::SetSpecialAbility(int ability, int level) {
auto iter = SpecialAbilities.find(ability);
if(iter != SpecialAbilities.end()) {
SpecialAbility spec = iter->second;
spec.level = level;
SpecialAbilities[ability] = spec;
} else {
SpecialAbility spec;
memset(&spec, 0, sizeof spec);
spec.level = level;
spec.timer = nullptr;
SpecialAbilities[ability] = spec;
}
}
void Mob::SetSpecialAbilityParam(int ability, int param, int value) {
if(param >= MAX_SPECIAL_ATTACK_PARAMS || param < 0) {
if(ability >= MAX_SPECIAL_ATTACK || ability < 0) {
return;
}
auto iter = SpecialAbilities.find(ability);
if(iter != SpecialAbilities.end()) {
SpecialAbility spec = iter->second;
spec.params[param] = value;
SpecialAbilities[ability] = spec;
} else {
SpecialAbility spec;
memset(&spec, 0, sizeof spec);
spec.params[param] = value;
spec.timer = nullptr;
SpecialAbilities[ability] = spec;
SpecialAbilities[ability].level = level;
}
void Mob::SetSpecialAbilityParam(int ability, int param, int value) {
if(param >= MAX_SPECIAL_ATTACK_PARAMS || param < 0 || ability >= MAX_SPECIAL_ATTACK || ability < 0) {
return;
}
SpecialAbilities[ability].params[param] = value;
}
void Mob::StartSpecialAbilityTimer(int ability, uint32 time) {
auto iter = SpecialAbilities.find(ability);
if(iter != SpecialAbilities.end()) {
SpecialAbility spec = iter->second;
if(spec.timer) {
spec.timer->Start(time);
} else {
spec.timer = new Timer(time);
spec.timer->Start();
}
if (ability >= MAX_SPECIAL_ATTACK || ability < 0) {
return;
}
SpecialAbilities[ability] = spec;
if(SpecialAbilities[ability].timer) {
SpecialAbilities[ability].timer->Start(time);
} else {
SpecialAbility spec;
memset(&spec, 0, sizeof spec);
spec.timer = new Timer(time);
spec.timer->Start();
SpecialAbilities[ability] = spec;
SpecialAbilities[ability].timer = new Timer(time);
SpecialAbilities[ability].timer->Start();
}
}
void Mob::StopSpecialAbilityTimer(int ability) {
auto iter = SpecialAbilities.find(ability);
if(iter != SpecialAbilities.end()) {
SpecialAbility spec = iter->second;
if(spec.timer) {
delete spec.timer;
spec.timer = nullptr;
}
SpecialAbilities[ability] = spec;
if (ability >= MAX_SPECIAL_ATTACK || ability < 0) {
return;
}
safe_delete(SpecialAbilities[ability].timer);
}
Timer *Mob::GetSpecialAbilityTimer(int ability) {
auto iter = SpecialAbilities.find(ability);
if(iter != SpecialAbilities.end()) {
return iter->second.timer;
if (ability >= MAX_SPECIAL_ATTACK || ability < 0) {
return nullptr;
}
return nullptr;
return SpecialAbilities[ability].timer;
}
void Mob::ClearSpecialAbilities() {
auto iter = SpecialAbilities.begin();
while(iter != SpecialAbilities.end()) {
if(iter->second.timer) {
delete iter->second.timer;
for(int a = 0; a < MAX_SPECIAL_ATTACK; ++a) {
SpecialAbilities[a].level = 0;
safe_delete(SpecialAbilities[a].timer);
for(int p = 0; p < MAX_SPECIAL_ATTACK_PARAMS; ++p) {
SpecialAbilities[a].params[p] = 0;
}
++iter;
}
SpecialAbilities.clear();
}
void Mob::ProcessSpecialAbilities(const std::string str) {

View File

@ -40,6 +40,18 @@ public:
enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard };
struct SpecialAbility {
SpecialAbility() {
level = 0;
timer = nullptr;
for(int i = 0; i < MAX_SPECIAL_ATTACK_PARAMS; ++i) {
params[i] = 0;
}
}
~SpecialAbility() {
safe_delete(timer);
}
int level;
Timer *timer;
int params[MAX_SPECIAL_ATTACK_PARAMS];
@ -172,7 +184,7 @@ public:
void NegateSpellsBonuses(uint16 spell_id);
virtual float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false) { return range;}
virtual int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr) { return value; }
virtual int32 GetActSpellHealing(uint16 spell_id, int32 value) { return value; }
virtual int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr) { return value; }
virtual int32 GetActSpellCost(uint16 spell_id, int32 cost){ return cost;}
virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration){ return duration;}
virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime);
@ -548,10 +560,10 @@ public:
void TrySympatheticProc(Mob *target, uint32 spell_id);
bool TryFadeEffect(int slot);
uint16 GetSpellEffectResistChance(uint16 spell_id);
int16 GetHealRate(uint16 spell_id);
int16 GetCriticalHealRate(uint16 spell_id);
int16 GetHealRate(uint16 spell_id, Mob* caster = nullptr);
int32 GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining);
int32 GetFcDamageAmtIncoming(Mob *caster, uint32 spell_id, bool use_skill = false, uint16 skill=0);
int32 GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spell_id);
int16 GetSkillDmgTaken(const SkillUseTypes skill_used);
void DoKnockback(Mob *caster, uint32 pushback, uint32 pushup);
int16 CalcResistChanceBonus();
@ -574,7 +586,7 @@ public:
bool DoHPToManaCovert(uint16 mana_cost = 0);
int32 ApplySpellEffectiveness(Mob* caster, int16 spell_id, int32 value, bool IsBard = false);
int8 GetDecayEffectValue(uint16 spell_id, uint16 spelleffect);
int32 GetExtraSpellDmg(uint16 spell_id, int32 extra_spell_dmg, int32 base_spell_dmg);
int32 GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_spell_dmg);
void ModSkillDmgTaken(SkillUseTypes skill_num, int value);
int16 GetModSkillDmgTaken(const SkillUseTypes skill_num);
@ -1177,7 +1189,7 @@ protected:
void InsertQuestGlobal(int charid, int npcid, int zoneid, const char *name, const char *value, int expdate);
uint16 emoteid;
std::map<int, SpecialAbility> SpecialAbilities;
SpecialAbility SpecialAbilities[MAX_SPECIAL_ATTACK];
bool bEnraged;
bool destructibleobject;

View File

@ -353,7 +353,6 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, float x, float y, float z, float
NPC::~NPC()
{
//entity_list.RemoveNPC(GetID());
AI_Stop();
if(proximity != nullptr) {
@ -361,9 +360,6 @@ NPC::~NPC()
safe_delete(proximity);
}
//clear our spawn limit record if we had one.
//entity_list.LimitRemoveNPC(this);
safe_delete(NPCTypedata_ours);
{

View File

@ -110,7 +110,7 @@ public:
int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr);
int32 GetActSpellHealing(uint16 spell_id, int32 value);
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;

View File

@ -461,11 +461,17 @@ uint32 Raid::GetTotalRaidDamage(Mob* other)
return total;
}
void Raid::HealGroup(uint32 heal_amt, Mob* caster, uint32 gid)
void Raid::HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, int32 range)
{
if (!caster)
return;
if (!range)
range = 200;
float distance;
float range2 = range*range;
int numMem = 0;
unsigned int gi = 0;
for(; gi < MAX_RAID_MEMBERS; gi++)
@ -473,7 +479,10 @@ void Raid::HealGroup(uint32 heal_amt, Mob* caster, uint32 gid)
if(members[gi].member){
if(members[gi].GroupNumber == gid)
{
numMem += 1;
distance = caster->DistNoRoot(*members[gi].member);
if(distance <= range2){
numMem += 1;
}
}
}
}
@ -484,25 +493,41 @@ void Raid::HealGroup(uint32 heal_amt, Mob* caster, uint32 gid)
if(members[gi].member){
if(members[gi].GroupNumber == gid)
{
members[gi].member->SetHP(members[gi].member->GetHP() + heal_amt);
members[gi].member->SendHPUpdate();
distance = caster->DistNoRoot(*members[gi].member);
if(distance <= range2){
members[gi].member->SetHP(members[gi].member->GetHP() + heal_amt);
members[gi].member->SendHPUpdate();
}
}
}
}
}
void Raid::BalanceHP(int32 penalty, uint32 gid)
void Raid::BalanceHP(int32 penalty, uint32 gid, int32 range, Mob* caster)
{
if (!caster)
return;
if (!range)
range = 200;
int dmgtaken = 0, numMem = 0;
int gi = 0;
float distance;
float range2 = range*range;
for(; gi < MAX_RAID_MEMBERS; gi++)
{
if(members[gi].member){
if(members[gi].GroupNumber == gid)
{
dmgtaken += (members[gi].member->GetMaxHP() - members[gi].member->GetHP());
numMem += 1;
distance = caster->DistNoRoot(*members[gi].member);
if(distance <= range2){
dmgtaken += (members[gi].member->GetMaxHP() - members[gi].member->GetHP());
numMem += 1;
}
}
}
}
@ -514,21 +539,33 @@ void Raid::BalanceHP(int32 penalty, uint32 gid)
if(members[gi].member){
if(members[gi].GroupNumber == gid)
{
if((members[gi].member->GetMaxHP() - dmgtaken) < 1){//this way the ability will never kill someone
members[gi].member->SetHP(1); //but it will come darn close
members[gi].member->SendHPUpdate();
}
else{
members[gi].member->SetHP(members[gi].member->GetMaxHP() - dmgtaken);
members[gi].member->SendHPUpdate();
distance = caster->DistNoRoot(*members[gi].member);
if(distance <= range2){
if((members[gi].member->GetMaxHP() - dmgtaken) < 1){//this way the ability will never kill someone
members[gi].member->SetHP(1); //but it will come darn close
members[gi].member->SendHPUpdate();
}
else{
members[gi].member->SetHP(members[gi].member->GetMaxHP() - dmgtaken);
members[gi].member->SendHPUpdate();
}
}
}
}
}
}
void Raid::BalanceMana(int32 penalty, uint32 gid)
void Raid::BalanceMana(int32 penalty, uint32 gid, int32 range, Mob* caster)
{
if (!caster)
return;
if (!range)
range = 200;
float distance;
float range2 = range*range;
int manataken = 0, numMem = 0;
int gi = 0;
for(; gi < MAX_RAID_MEMBERS; gi++)
@ -536,8 +573,11 @@ void Raid::BalanceMana(int32 penalty, uint32 gid)
if(members[gi].member){
if(members[gi].GroupNumber == gid)
{
manataken += (members[gi].member->GetMaxMana() - members[gi].member->GetMana());
numMem += 1;
distance = caster->DistNoRoot(*members[gi].member);
if(distance <= range2){
manataken += (members[gi].member->GetMaxMana() - members[gi].member->GetMana());
numMem += 1;
}
}
}
}
@ -549,15 +589,18 @@ void Raid::BalanceMana(int32 penalty, uint32 gid)
if(members[gi].member){
if(members[gi].GroupNumber == gid)
{
if((members[gi].member->GetMaxMana() - manataken) < 1){
members[gi].member->SetMana(1);
if (members[gi].member->IsClient())
members[gi].member->CastToClient()->SendManaUpdate();
}
else{
members[gi].member->SetMana(members[gi].member->GetMaxMana() - manataken);
if (members[gi].member->IsClient())
members[gi].member->CastToClient()->SendManaUpdate();
distance = caster->DistNoRoot(*members[gi].member);
if(distance <= range2){
if((members[gi].member->GetMaxMana() - manataken) < 1){
members[gi].member->SetMana(1);
if (members[gi].member->IsClient())
members[gi].member->CastToClient()->SendManaUpdate();
}
else{
members[gi].member->SetMana(members[gi].member->GetMaxMana() - manataken);
if (members[gi].member->IsClient())
members[gi].member->CastToClient()->SendManaUpdate();
}
}
}
}

View File

@ -147,9 +147,9 @@ public:
void CastGroupSpell(Mob* caster,uint16 spellid, uint32 gid);
void SplitExp(uint32 exp, Mob* other);
uint32 GetTotalRaidDamage(Mob* other);
void BalanceHP(int32 penalty, uint32 gid);
void BalanceMana(int32 penalty, uint32 gid);
void HealGroup(uint32 heal_amt, Mob* caster, uint32 gid);
void BalanceHP(int32 penalty, uint32 gid, int32 range = 0, Mob* caster = nullptr);
void BalanceMana(int32 penalty, uint32 gid, int32 range = 0, Mob* caster = nullptr);
void HealGroup(uint32 heal_amt, Mob* caster, uint32 gid, int32 range = 0);
void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr);
void GroupBardPulse(Mob* caster, uint16 spellid, uint32 gid);

View File

@ -502,8 +502,11 @@ void Spawn2::SpawnConditionChanged(const SpawnCondition &c, int16 old_value) {
break;
case SpawnCondition::DoRepopIfReady:
_log(SPAWNS__CONDITIONS, "Spawn2 %d: Our condition is now %s. Forcing a repop if repsawn timer is expired.", spawn2_id, new_state?"enabled":"disabled");
if(npcthis != nullptr)
if(npcthis != nullptr) {
_log(SPAWNS__CONDITIONS, "Spawn2 %d: Our npcthis is currently not null. The zone thinks it is %s. Forcing a depop.", spawn2_id, npcthis->GetName());
npcthis->Depop(false); //remove the current mob
npcthis = nullptr;
}
if(new_state) { // only get repawn timer remaining when the SpawnCondition is enabled.
timer_remaining = database.GetSpawnTimeLeft(spawn2_id,zone->GetInstanceID());
_log(SPAWNS__CONDITIONS,"Spawn2 %d: Our condition is now %s. The respawn timer_remaining is %d. Forcing a repop if it is <= 0.", spawn2_id, new_state?"enabled":"disabled", timer_remaining);

File diff suppressed because it is too large Load Diff

View File

@ -2689,7 +2689,7 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
effect1 == SE_LimitMinDur ||
effect1 == SE_LimitInstant ||
effect1 == SE_LimitMinLevel ||
effect1 == SE_LimitCastTime)
effect1 == SE_LimitCastTimeMin)
continue;
/*