mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 09:31:30 +00:00
Merge branch 'master' into RunQueryToDatabaseQuery_database
Conflicts: changelog.txt common/spdat.h zone/attack.cpp zone/bonuses.cpp zone/common.h zone/mob.h zone/special_attacks.cpp zone/spell_effects.cpp
This commit is contained in:
commit
cff96b23a8
@ -233,7 +233,7 @@ OPTION(EQEMU_BUILD_SOCKET_SERVER "Build the socket server." OFF)
|
|||||||
OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF)
|
OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF)
|
||||||
OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON)
|
OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON)
|
||||||
OPTION(EQEMU_BUILD_LUA "Build Lua parser." OFF)
|
OPTION(EQEMU_BUILD_LUA "Build Lua parser." OFF)
|
||||||
OPTION(EQEMU_BUILD_CLIENT_FILES "Build Client Inport/Export Data Programs." ON)
|
OPTION(EQEMU_BUILD_CLIENT_FILES "Build Client Import/Export Data Programs." ON)
|
||||||
|
|
||||||
#C++11 stuff
|
#C++11 stuff
|
||||||
IF(NOT MSVC)
|
IF(NOT MSVC)
|
||||||
|
|||||||
@ -1,5 +1,17 @@
|
|||||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
== 07/5/2014 ==
|
||||||
|
Kayen: Updated SE_Sanctuary - Adjust way hate lowering effect worked to be more accurate
|
||||||
|
Kayen: Updated SE_SympatheticProc - Revised proc rate formula to be accurate to live.
|
||||||
|
Sympathetic foci on items with proc rate mod will now benefit from that modifier.
|
||||||
|
Sympathetic foci can now be placed on AA's (This should always be slot1 in the AA)
|
||||||
|
Kayen: Implemented SE_IllusionPersistence- Allows illusions to last until you die or the illusion is forcibly removed.
|
||||||
|
Kayen: Added rule 'PreNerftBardAEDot' for SE_BardAEDot to allow it to once again do damage to moving targets. (Set to true)
|
||||||
|
Kayen: Completely revised SE_SkillProc, SE_LimitToSkill, SE_SkillProcSuccess to overall just work better and more accurately, AA support.
|
||||||
|
|
||||||
|
Required SQL: utils/sql/git/required/2014_07_04_AA_Update.sql
|
||||||
|
|
||||||
|
|
||||||
== 07/2/2014 ==
|
== 07/2/2014 ==
|
||||||
Kayen: Implemented SE_Sanctuary - Places caster at bottom hate list, effect fades if caster cast spell on targets other than self.
|
Kayen: Implemented SE_Sanctuary - Places caster at bottom hate list, effect fades if caster cast spell on targets other than self.
|
||||||
Kayen: Implemented SE_ResourceTap - Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end.
|
Kayen: Implemented SE_ResourceTap - Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end.
|
||||||
|
|||||||
@ -310,6 +310,7 @@ RULE_INT ( Spells, FRProjectileItem_SOF, 80684) // Item id for SOF clients for F
|
|||||||
RULE_INT ( Spells, FRProjectileItem_NPC, 80684) // Item id for NPC Fire 'spell projectile'.
|
RULE_INT ( Spells, FRProjectileItem_NPC, 80684) // Item id for NPC Fire 'spell projectile'.
|
||||||
RULE_BOOL ( Spells, UseLiveSpellProjectileGFX, false) // Use spell projectile graphics set in the spells_new table (player_1). Server must be using UF+ spell file.
|
RULE_BOOL ( Spells, UseLiveSpellProjectileGFX, false) // Use spell projectile graphics set in the spells_new table (player_1). Server must be using UF+ spell file.
|
||||||
RULE_BOOL ( Spells, FocusCombatProcs, false) //Allow all combat procs to receive focus effects.
|
RULE_BOOL ( Spells, FocusCombatProcs, false) //Allow all combat procs to receive focus effects.
|
||||||
|
RULE_BOOL ( Spells, PreNerfBardAEDoT, false) //Allow bard AOE dots to damage targets when moving.
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY( Combat )
|
RULE_CATEGORY( Combat )
|
||||||
|
|||||||
@ -37,6 +37,8 @@
|
|||||||
#define MAX_SPELL_TRIGGER 12 // One for each slot(only 6 for AA since AA use 2)
|
#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 MAX_RESISTABLE_EFFECTS 12 // Number of effects that are typcially checked agianst resists.
|
||||||
#define MaxLimitInclude 16 //Number(x 0.5) of focus Limiters that have inclusive checks used when calcing focus effects
|
#define MaxLimitInclude 16 //Number(x 0.5) of focus Limiters that have inclusive checks used when calcing focus effects
|
||||||
|
#define MAX_SKILL_PROCS 4 //Number of spells to check skill procs from. (This is arbitrary) [Single spell can have multiple proc checks]
|
||||||
|
|
||||||
|
|
||||||
const int Z_AGGRO=10;
|
const int Z_AGGRO=10;
|
||||||
|
|
||||||
@ -385,7 +387,7 @@ typedef enum {
|
|||||||
#define SE_ChannelChanceSpells 235 // implemented[AA] - chance to channel from SPELLS *No longer used on live.
|
#define SE_ChannelChanceSpells 235 // implemented[AA] - chance to channel from SPELLS *No longer used on live.
|
||||||
//#define SE_FreePet 236 // not used
|
//#define SE_FreePet 236 // not used
|
||||||
#define SE_GivePetGroupTarget 237 // implemented[AA] - (Pet Affinity)
|
#define SE_GivePetGroupTarget 237 // implemented[AA] - (Pet Affinity)
|
||||||
//#define SE_IllusionPersistence 238 // *not implemented - lends persistence to your illusionary disguises, causing them to last until you die or the illusion is forcibly removed.
|
#define SE_IllusionPersistence 238 // implemented - lends persistence to your illusionary disguises, causing them to last until you die or the illusion is forcibly removed.
|
||||||
//#define SE_FeignedCastOnChance 239 // *not implemented as bonus - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you.
|
//#define SE_FeignedCastOnChance 239 // *not implemented as bonus - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you.
|
||||||
//#define SE_StringUnbreakable 240 // not used [Likely related to above - you become immune to feign breaking on a resisted spell and have a good chance of feigning through a spell that successfully lands upon you.]
|
//#define SE_StringUnbreakable 240 // not used [Likely related to above - you become immune to feign breaking on a resisted spell and have a good chance of feigning through a spell that successfully lands upon you.]
|
||||||
#define SE_ImprovedReclaimEnergy 241 // implemented - increase the amount of mana returned to you when reclaiming your pet.
|
#define SE_ImprovedReclaimEnergy 241 // implemented - increase the amount of mana returned to you when reclaiming your pet.
|
||||||
@ -576,7 +578,7 @@ typedef enum {
|
|||||||
//#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window
|
//#define SE_IncreaseExtTargetWindow 426 // *not implmented[AA] - increases the capacity of your extended target window
|
||||||
#define SE_SkillProc 427 // implemented - chance to proc when using a skill(ie taunt)
|
#define SE_SkillProc 427 // implemented - chance to proc when using a skill(ie taunt)
|
||||||
#define SE_LimitToSkill 428 // implemented - limits what skills will effect a skill proc
|
#define SE_LimitToSkill 428 // implemented - limits what skills will effect a skill proc
|
||||||
#define SE_SkillProc2 429 // implemented - chance to proc when using a skill (most have hit limits)
|
#define SE_SkillProcSuccess 429 // implemented - chance to proc when tje skill in use successfully fires.
|
||||||
//#define SE_PostEffect 430 // *not implemented - Fear of the Dark(27641) - Alters vision
|
//#define SE_PostEffect 430 // *not implemented - Fear of the Dark(27641) - Alters vision
|
||||||
//#define SE_PostEffectData 431 // *not implemented - Fear of the Dark(27641) - Alters vision
|
//#define SE_PostEffectData 431 // *not implemented - Fear of the Dark(27641) - Alters vision
|
||||||
//#define SE_ExpandMaxActiveTrophyBen 432 // not used
|
//#define SE_ExpandMaxActiveTrophyBen 432 // not used
|
||||||
|
|||||||
34
utils/sql/git/required/2014_06_25_AA_Updates.sql
Normal file
34
utils/sql/git/required/2014_06_25_AA_Updates.sql
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
-- AA MGB update
|
||||||
|
UPDATE altadv_vars SET spellid = 5228 WHERE skill_id = 128;
|
||||||
|
UPDATE aa_actions SET spell_id = 5228, nonspell_action = 0 WHERE aaid = 128;
|
||||||
|
|
||||||
|
-- AA Project Illusion update
|
||||||
|
UPDATE altadv_vars SET spellid = 5227 WHERE skill_id = 643;
|
||||||
|
UPDATE aa_actions SET spell_id = 5227, nonspell_action = 0 WHERE aaid = 643;
|
||||||
|
|
||||||
|
-- AA Improved Reclaim Energy
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('180', '1', '241', '95', '0');
|
||||||
|
|
||||||
|
-- AA Headshot
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('644', '1', '217', '0', '32000');
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('644', '2', '346', '46', '0');
|
||||||
|
|
||||||
|
-- AA Anatomy (Rogue Assassinate)
|
||||||
|
INSERT INTO `altadv_vars` (`skill_id`, `name`, `cost`, `max_level`, `hotkey_sid`, `hotkey_sid2`, `title_sid`, `desc_sid`, `type`, `spellid`, `prereq_skill`, `prereq_minpoints`, `spell_type`, `spell_refresh`, `classes`, `berserker`, `class_type`, `cost_inc`, `aa_expansion`, `special_category`, `sof_type`, `sof_cost_inc`, `sof_max_level`, `sof_next_skill`, `clientver`, `account_time_required`, `sof_current_level`,`sof_next_id`,`level_inc`) VALUES ('1604', 'Anatomy', '5', '3', '4294967295', '4294967295', '1604', '1604', '1', '4294967295', '0', '0', '0', '0', '512', '0', '60', '1', '10', '4294967295', '3', '0', '3', '1604', '1', '0', '0', '0', '0');
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1604', '1', '439', '0', '32000');
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1604', '2', '345', '48', '0');
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1605', '1', '439', '0', '32000');
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1605', '2', '345', '51', '0');
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1606', '1', '439', '0', '32000');
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('1606', '2', '345', '53', '0');
|
||||||
|
|
||||||
|
-- AA Finishing Blow Fix
|
||||||
|
DELETE FROM aa_effects WHERE aaid = 199 AND slot = 2;
|
||||||
|
DELETE FROM aa_effects WHERE aaid = 200 AND slot = 2;
|
||||||
|
DELETE FROM aa_effects WHERE aaid = 201 AND slot = 2;
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('119', '1', '278', '500', '32000');
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('119', '2', '440', '50', '200');
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('120', '1', '278', '500', '32000');
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('120', '2', '440', '52', '200');
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('121', '1', '278', '500', '32000');
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('121', '2', '440', '54', '200');
|
||||||
6
utils/sql/git/required/2014_07_04_AA_Updates.sql
Normal file
6
utils/sql/git/required/2014_07_04_AA_Updates.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
-- AA Permanent Illusion
|
||||||
|
INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('158', '1', '238', '1', '0');
|
||||||
|
|
||||||
|
-- AA Sanctuary
|
||||||
|
INSERT INTO `altadv_vars` (`skill_id`, `name`, `cost`, `max_level`, `hotkey_sid`, `hotkey_sid2`, `title_sid`, `desc_sid`, `type`, `spellid`, `prereq_skill`, `prereq_minpoints`, `spell_type`, `spell_refresh`, `classes`, `berserker`, `class_type`, `cost_inc`, `aa_expansion`, `special_category`, `sof_type`, `sof_cost_inc`, `sof_max_level`, `sof_next_skill`, `clientver`, `account_time_required`, `sof_current_level`,`sof_next_id`,`level_inc`) VALUES ('1209', 'Sanctuary', '12', '1', '1209', '4294967295', '1209', '1209', '3', '5912', '0', '0', '14', '4320', '4', '0', '70', '0', '8', '4294967295', '3', '0', '1', '1209', '1', '0', '0', '0', '0');
|
||||||
|
INSERT INTO `aa_actions` (`aaid`, `rank`, `reuse_time`, `spell_id`, `target`, `nonspell_action`, `nonspell_mana`, `nonspell_duration`, `redux_aa`, `redux_rate`, `redux_aa2`, `redux_rate2`) VALUES ('1209', '0', '4320', '5912', '1', '0', '0', '0', '0', '0', '0', '0');
|
||||||
274
zone/attack.cpp
274
zone/attack.cpp
@ -1359,8 +1359,11 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
|
|||||||
|
|
||||||
MeleeLifeTap(damage);
|
MeleeLifeTap(damage);
|
||||||
|
|
||||||
if (damage > 0)
|
if (damage > 0){
|
||||||
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
CheckNumHitsRemaining(NUMHIT_OutgoingHitSuccess);
|
||||||
|
if (HasSkillProcSuccess() && other && other->GetHP() > 0)
|
||||||
|
TrySkillProc(other, skillinuse, 0, true, Hand);
|
||||||
|
}
|
||||||
|
|
||||||
//break invis when you attack
|
//break invis when you attack
|
||||||
if(invisible) {
|
if(invisible) {
|
||||||
@ -2018,9 +2021,12 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
|
|||||||
if (!GetTarget())
|
if (!GetTarget())
|
||||||
return true; //We killed them
|
return true; //We killed them
|
||||||
|
|
||||||
if(!bRiposte && other->GetHP() > 0 ) {
|
if(!bRiposte && other && other->GetHP() > 0) {
|
||||||
TryWeaponProc(nullptr, weapon, other, Hand); //no weapon
|
TryWeaponProc(nullptr, weapon, other, Hand); //no weapon
|
||||||
TrySpellProc(nullptr, weapon, other, Hand);
|
TrySpellProc(nullptr, weapon, other, Hand);
|
||||||
|
|
||||||
|
if (damage > 0 && HasSkillProcSuccess())
|
||||||
|
TrySkillProc(other, skillinuse, 0, true, Hand);
|
||||||
}
|
}
|
||||||
|
|
||||||
TriggerDefensiveProcs(nullptr, other, Hand, damage);
|
TriggerDefensiveProcs(nullptr, other, Hand, damage);
|
||||||
@ -3426,9 +3432,20 @@ bool Mob::HasDefensiveProcs() const
|
|||||||
|
|
||||||
bool Mob::HasSkillProcs() const
|
bool Mob::HasSkillProcs() const
|
||||||
{
|
{
|
||||||
for (int i = 0; i < MAX_PROCS; i++)
|
|
||||||
if (SkillProcs[i].spellID != SPELL_UNKNOWN)
|
for(int i = 0; i < MAX_SKILL_PROCS; i++){
|
||||||
|
if (spellbonuses.SkillProc[i] || itembonuses.SkillProc[i] || aabonuses.SkillProc[i])
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mob::HasSkillProcSuccess() const
|
||||||
|
{
|
||||||
|
for(int i = 0; i < MAX_SKILL_PROCS; i++){
|
||||||
|
if (spellbonuses.SkillProcSuccess[i] || itembonuses.SkillProcSuccess[i] || aabonuses.SkillProcSuccess[i])
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3911,22 +3928,7 @@ float Mob::GetProcChances(float ProcBonus, uint16 weapon_speed, uint16 hand)
|
|||||||
int mydex = GetDEX();
|
int mydex = GetDEX();
|
||||||
float ProcChance = 0.0f;
|
float ProcChance = 0.0f;
|
||||||
|
|
||||||
switch (hand) {
|
weapon_speed = GetWeaponSpeedbyHand(hand);
|
||||||
case 13:
|
|
||||||
weapon_speed = attack_timer.GetDuration();
|
|
||||||
break;
|
|
||||||
case 14:
|
|
||||||
weapon_speed = attack_dw_timer.GetDuration();
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
weapon_speed = ranged_timer.GetDuration();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//calculate the weapon speed in ms, so we can use the rule to compare against.
|
|
||||||
// fast as a client can swing, so should be the floor of the proc chance
|
|
||||||
if (weapon_speed < RuleI(Combat, MinHastedDelay))
|
|
||||||
weapon_speed = RuleI(Combat, MinHastedDelay);
|
|
||||||
|
|
||||||
if (RuleB(Combat, AdjustProcPerMinute)) {
|
if (RuleB(Combat, AdjustProcPerMinute)) {
|
||||||
ProcChance = (static_cast<float>(weapon_speed) *
|
ProcChance = (static_cast<float>(weapon_speed) *
|
||||||
@ -3948,25 +3950,10 @@ float Mob::GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 w
|
|||||||
ProcBonus = 0;
|
ProcBonus = 0;
|
||||||
ProcChance = 0;
|
ProcChance = 0;
|
||||||
|
|
||||||
switch(hand){
|
weapon_speed = GetWeaponSpeedbyHand(hand);
|
||||||
case 13:
|
|
||||||
weapon_speed = attack_timer.GetDuration();
|
|
||||||
break;
|
|
||||||
case 14:
|
|
||||||
weapon_speed = attack_dw_timer.GetDuration();
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
//calculate the weapon speed in ms, so we can use the rule to compare against.
|
ProcChance = (static_cast<float>(weapon_speed) * RuleR(Combat, AvgDefProcsPerMinute) / 60000.0f); // compensate for weapon_speed being in ms
|
||||||
//weapon_speed = ((int)(weapon_speed*(100.0f+attack_speed)*PermaHaste));
|
ProcBonus += static_cast<float>(myagi) * RuleR(Combat, DefProcPerMinAgiContrib) / 100.0f;
|
||||||
if(weapon_speed < RuleI(Combat, MinHastedDelay)) // fast as a client can swing, so should be the floor of the proc chance
|
|
||||||
weapon_speed = RuleI(Combat, MinHastedDelay);
|
|
||||||
|
|
||||||
ProcChance = ((float)weapon_speed * RuleR(Combat, AvgDefProcsPerMinute) / 60000.0f); // compensate for weapon_speed being in ms
|
|
||||||
ProcBonus += float(myagi) * RuleR(Combat, DefProcPerMinAgiContrib) / 100.0f;
|
|
||||||
ProcChance = ProcChance + (ProcChance * ProcBonus);
|
ProcChance = ProcChance + (ProcChance * ProcBonus);
|
||||||
|
|
||||||
mlog(COMBAT__PROCS, "Defensive Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus);
|
mlog(COMBAT__PROCS, "Defensive Proc chance %.2f (%.2f from bonuses)", ProcChance, ProcBonus);
|
||||||
@ -3981,13 +3968,9 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand, int dam
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bSkillProc = HasSkillProcs();
|
|
||||||
bool bDefensiveProc = HasDefensiveProcs();
|
bool bDefensiveProc = HasDefensiveProcs();
|
||||||
|
|
||||||
if (!bDefensiveProc && !bSkillProc)
|
if (!bDefensiveProc)
|
||||||
return;
|
|
||||||
|
|
||||||
if (!bDefensiveProc && (bSkillProc && damage >= 0))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float ProcChance, ProcBonus;
|
float ProcChance, ProcBonus;
|
||||||
@ -4000,30 +3983,15 @@ void Mob::TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand, int dam
|
|||||||
|
|
||||||
if (bDefensiveProc){
|
if (bDefensiveProc){
|
||||||
for (int i = 0; i < MAX_PROCS; i++) {
|
for (int i = 0; i < MAX_PROCS; i++) {
|
||||||
if (DefensiveProcs[i].spellID != SPELL_UNKNOWN) {
|
if (IsValidSpell(DefensiveProcs[i].spellID)) {
|
||||||
int chance = ProcChance * (DefensiveProcs[i].chance);
|
float chance = ProcChance * (static_cast<float>(DefensiveProcs[i].chance)/100.0f);
|
||||||
if ((MakeRandomInt(0, 100) < chance)) {
|
if ((MakeRandomFloat(0, 1) <= chance)) {
|
||||||
ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on);
|
ExecWeaponProc(nullptr, DefensiveProcs[i].spellID, on);
|
||||||
CheckNumHitsRemaining(NUMHIT_DefensiveSpellProcs,0,DefensiveProcs[i].base_spellID);
|
CheckNumHitsRemaining(NUMHIT_DefensiveSpellProcs,0,DefensiveProcs[i].base_spellID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bSkillProc && damage < 0){
|
|
||||||
|
|
||||||
if (damage == -1)
|
|
||||||
TrySkillProc(on, SkillBlock, ProcChance);
|
|
||||||
|
|
||||||
if (damage == -2)
|
|
||||||
TrySkillProc(on, SkillParry, ProcChance);
|
|
||||||
|
|
||||||
if (damage == -3)
|
|
||||||
TrySkillProc(on, SkillRiposte, ProcChance);
|
|
||||||
|
|
||||||
if (damage == -4)
|
|
||||||
TrySkillProc(on, SkillDodge, ProcChance);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) {
|
void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) {
|
||||||
@ -4059,6 +4027,7 @@ void Mob::TryWeaponProc(const ItemInst* weapon_g, Mob *on, uint16 hand) {
|
|||||||
|
|
||||||
void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 hand)
|
void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on, uint16 hand)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!weapon)
|
if (!weapon)
|
||||||
return;
|
return;
|
||||||
uint16 skillinuse = 28;
|
uint16 skillinuse = 28;
|
||||||
@ -4135,8 +4104,6 @@ void Mob::TryWeaponProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: Powersource procs
|
// TODO: Powersource procs
|
||||||
if (HasSkillProcs())
|
|
||||||
TrySkillProc(on, skillinuse, ProcChance);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -4217,6 +4184,14 @@ void Mob::TrySpellProc(const ItemInst *inst, const Item_Struct *weapon, Mob *on,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HasSkillProcs() && hand != 11){ //We check ranged skill procs within the attack functions.
|
||||||
|
uint16 skillinuse = 28;
|
||||||
|
if (weapon)
|
||||||
|
skillinuse = GetSkillByItemType(weapon->ItemType);
|
||||||
|
|
||||||
|
TrySkillProc(on, skillinuse, 0, false, hand);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4560,7 +4535,7 @@ uint16 Mob::GetDamageTable(SkillUseTypes skillinuse)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::TrySkillProc(Mob *on, uint16 skill, float chance)
|
void Mob::TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success, uint16 hand, bool IsDefensive)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!on) {
|
if (!on) {
|
||||||
@ -4569,17 +4544,174 @@ void Mob::TrySkillProc(Mob *on, uint16 skill, float chance)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < MAX_PROCS; i++) {
|
if (!spellbonuses.LimitToSkill[skill] && !itembonuses.LimitToSkill[skill] && !aabonuses.LimitToSkill[skill])
|
||||||
if (SkillProcs[i].spellID != SPELL_UNKNOWN){
|
return;
|
||||||
if (PassLimitToSkill(SkillProcs[i].base_spellID,skill)){
|
|
||||||
int ProcChance = chance * (float)SkillProcs[i].chance;
|
/*Allow one proc from each (Spell/Item/AA)
|
||||||
if ((MakeRandomInt(0, 100) < ProcChance)) {
|
Kayen: Due to limited avialability of effects on live it is too difficult
|
||||||
ExecWeaponProc(nullptr, SkillProcs[i].spellID, on);
|
to confirm how they stack at this time, will adjust formula when more data is avialablle to test.*/
|
||||||
CheckNumHitsRemaining(NUMHIT_OffensiveSpellProcs,0, SkillProcs[i].base_spellID);
|
bool CanProc = true;
|
||||||
|
|
||||||
|
uint16 base_spell_id = 0;
|
||||||
|
uint16 proc_spell_id = 0;
|
||||||
|
float ProcMod = 0;
|
||||||
|
float chance = 0;
|
||||||
|
|
||||||
|
if (IsDefensive)
|
||||||
|
chance = on->GetSkillProcChances(ReuseTime, hand);
|
||||||
|
else
|
||||||
|
chance = GetSkillProcChances(ReuseTime, hand);
|
||||||
|
|
||||||
|
if (spellbonuses.LimitToSkill[skill]){
|
||||||
|
|
||||||
|
for(int e = 0; e < MAX_SKILL_PROCS; e++){
|
||||||
|
|
||||||
|
if (CanProc &&
|
||||||
|
(!Success && spellbonuses.SkillProc[e] && IsValidSpell(spellbonuses.SkillProc[e]))
|
||||||
|
|| (Success && spellbonuses.SkillProcSuccess[e] && IsValidSpell(spellbonuses.SkillProcSuccess[e]))) {
|
||||||
|
base_spell_id = spellbonuses.SkillProc[e];
|
||||||
|
base_spell_id = 0;
|
||||||
|
ProcMod = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < EFFECT_COUNT; i++) {
|
||||||
|
|
||||||
|
if (spells[base_spell_id].effectid[i] == SE_SkillProc) {
|
||||||
|
proc_spell_id = spells[base_spell_id].base[i];
|
||||||
|
ProcMod = static_cast<float>(spells[base_spell_id].base2[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (spells[base_spell_id].effectid[i] == SE_LimitToSkill && spells[base_spell_id].effectid[i] <= HIGHEST_SKILL) {
|
||||||
|
|
||||||
|
if (CanProc && spells[base_spell_id].base[i] == skill && IsValidSpell(proc_spell_id)) {
|
||||||
|
float final_chance = chance * (ProcMod / 100.0f);
|
||||||
|
if (MakeRandomFloat(0, 1) <= final_chance) {
|
||||||
|
ExecWeaponProc(nullptr, proc_spell_id, on);
|
||||||
|
CheckNumHitsRemaining(NUMHIT_OffensiveSpellProcs,0, base_spell_id);
|
||||||
|
CanProc = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
proc_spell_id = 0;
|
||||||
|
ProcMod = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itembonuses.LimitToSkill[skill]){
|
||||||
|
CanProc = true;
|
||||||
|
for(int e = 0; e < MAX_SKILL_PROCS; e++){
|
||||||
|
|
||||||
|
if (CanProc &&
|
||||||
|
(!Success && itembonuses.SkillProc[e] && IsValidSpell(itembonuses.SkillProc[e]))
|
||||||
|
|| (Success && itembonuses.SkillProcSuccess[e] && IsValidSpell(itembonuses.SkillProcSuccess[e]))) {
|
||||||
|
base_spell_id = itembonuses.SkillProc[e];
|
||||||
|
base_spell_id = 0;
|
||||||
|
ProcMod = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < EFFECT_COUNT; i++) {
|
||||||
|
|
||||||
|
if (spells[base_spell_id].effectid[i] == SE_SkillProc) {
|
||||||
|
proc_spell_id = spells[base_spell_id].base[i];
|
||||||
|
ProcMod = static_cast<float>(spells[base_spell_id].base2[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (spells[base_spell_id].effectid[i] == SE_LimitToSkill && spells[base_spell_id].effectid[i] <= HIGHEST_SKILL) {
|
||||||
|
|
||||||
|
if (CanProc && spells[base_spell_id].base[i] == skill && IsValidSpell(proc_spell_id)) {
|
||||||
|
float final_chance = chance * (ProcMod / 100.0f);
|
||||||
|
if (MakeRandomFloat(0, 1) <= final_chance) {
|
||||||
|
ExecWeaponProc(nullptr, proc_spell_id, on);
|
||||||
|
CanProc = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
proc_spell_id = 0;
|
||||||
|
ProcMod = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsClient() && aabonuses.LimitToSkill[skill]){
|
||||||
|
|
||||||
|
CanProc = true;
|
||||||
|
uint32 effect = 0;
|
||||||
|
int32 base1 = 0;
|
||||||
|
int32 base2 = 0;
|
||||||
|
uint32 slot = 0;
|
||||||
|
|
||||||
|
for(int e = 0; e < MAX_SKILL_PROCS; e++){
|
||||||
|
|
||||||
|
if (CanProc &&
|
||||||
|
(!Success && aabonuses.SkillProc[e])
|
||||||
|
|| (Success && aabonuses.SkillProcSuccess[e])){
|
||||||
|
int aaid = aabonuses.SkillProc[e];
|
||||||
|
base_spell_id = 0;
|
||||||
|
ProcMod = 0;
|
||||||
|
|
||||||
|
std::map<uint32, std::map<uint32, AA_Ability> >::const_iterator find_iter = aa_effects.find(aaid);
|
||||||
|
if(find_iter == aa_effects.end())
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (std::map<uint32, AA_Ability>::const_iterator iter = aa_effects[aaid].begin(); iter != aa_effects[aaid].end(); ++iter) {
|
||||||
|
effect = iter->second.skill_id;
|
||||||
|
base1 = iter->second.base1;
|
||||||
|
base2 = iter->second.base2;
|
||||||
|
slot = iter->second.slot;
|
||||||
|
|
||||||
|
if (effect == SE_SkillProc) {
|
||||||
|
proc_spell_id = base1;
|
||||||
|
ProcMod = static_cast<float>(base2);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (effect == SE_LimitToSkill && effect <= HIGHEST_SKILL) {
|
||||||
|
|
||||||
|
if (CanProc && base1 == skill && IsValidSpell(proc_spell_id)) {
|
||||||
|
float final_chance = chance * (ProcMod / 100.0f);
|
||||||
|
|
||||||
|
if (MakeRandomFloat(0, 1) <= final_chance) {
|
||||||
|
ExecWeaponProc(nullptr, proc_spell_id, on);
|
||||||
|
CanProc = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
proc_spell_id = 0;
|
||||||
|
ProcMod = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float Mob::GetSkillProcChances(uint16 ReuseTime, uint16 hand) {
|
||||||
|
|
||||||
|
uint16 weapon_speed;
|
||||||
|
float ProcChance = 0;
|
||||||
|
|
||||||
|
if (!ReuseTime && hand) {
|
||||||
|
|
||||||
|
weapon_speed = GetWeaponSpeedbyHand(hand);
|
||||||
|
|
||||||
|
ProcChance = static_cast<float>(weapon_speed) * (RuleR(Combat, AvgProcsPerMinute) / 60000.0f);
|
||||||
|
|
||||||
|
if (hand != 13)
|
||||||
|
ProcChance /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
ProcChance = static_cast<float>(ReuseTime) * (RuleR(Combat, AvgProcsPerMinute) / 60000.0f);
|
||||||
|
|
||||||
|
return ProcChance;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
|
bool Mob::TryRootFadeByDamage(int buffslot, Mob* attacker) {
|
||||||
|
|||||||
@ -1329,6 +1329,45 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SE_IllusionPersistence:
|
||||||
|
newbon->IllusionPersistence = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SE_LimitToSkill:{
|
||||||
|
if (base1 <= HIGHEST_SKILL)
|
||||||
|
newbon->LimitToSkill[base1] = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SE_SkillProc:{
|
||||||
|
for(int e = 0; e < MAX_SKILL_PROCS; e++)
|
||||||
|
{
|
||||||
|
if(newbon->SkillProc[e] && newbon->SkillProc[e] == aaid)
|
||||||
|
break; //Do not use the same aa id more than once.
|
||||||
|
|
||||||
|
else if(!newbon->SkillProc[e]){
|
||||||
|
newbon->SkillProc[e] = aaid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SE_SkillProcSuccess:{
|
||||||
|
|
||||||
|
for(int e = 0; e < MAX_SKILL_PROCS; e++)
|
||||||
|
{
|
||||||
|
if(newbon->SkillProcSuccess[e] && newbon->SkillProcSuccess[e] == aaid)
|
||||||
|
break; //Do not use the same spell id more than once.
|
||||||
|
|
||||||
|
else if(!newbon->SkillProcSuccess[e]){
|
||||||
|
newbon->SkillProcSuccess[e] = aaid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2876,6 +2915,47 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SE_IllusionPersistence:
|
||||||
|
newbon->IllusionPersistence = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SE_LimitToSkill:{
|
||||||
|
if (effect_value <= HIGHEST_SKILL){
|
||||||
|
newbon->LimitToSkill[effect_value] = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SE_SkillProc:{
|
||||||
|
|
||||||
|
for(int e = 0; e < MAX_SKILL_PROCS; e++)
|
||||||
|
{
|
||||||
|
if(newbon->SkillProc[e] && newbon->SkillProc[e] == spell_id)
|
||||||
|
break; //Do not use the same spell id more than once.
|
||||||
|
|
||||||
|
else if(!newbon->SkillProc[e]){
|
||||||
|
newbon->SkillProc[e] = spell_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SE_SkillProcSuccess:{
|
||||||
|
|
||||||
|
for(int e = 0; e < MAX_SKILL_PROCS; e++)
|
||||||
|
{
|
||||||
|
if(newbon->SkillProcSuccess[e] && newbon->SkillProcSuccess[e] == spell_id)
|
||||||
|
break; //Do not use the same spell id more than once.
|
||||||
|
|
||||||
|
else if(!newbon->SkillProcSuccess[e]){
|
||||||
|
newbon->SkillProcSuccess[e] = spell_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
|
//Special custom cases for loading effects on to NPC from 'npc_spels_effects' table
|
||||||
if (IsAISpellEffect) {
|
if (IsAISpellEffect) {
|
||||||
|
|
||||||
@ -4356,6 +4436,17 @@ void Mob::NegateSpellsBonuses(uint16 spell_id)
|
|||||||
aabonuses.FactionModPct = effect_value;
|
aabonuses.FactionModPct = effect_value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SE_MeleeVulnerability:
|
||||||
|
spellbonuses.MeleeVulnerability = effect_value;
|
||||||
|
itembonuses.MeleeVulnerability = effect_value;
|
||||||
|
aabonuses.MeleeVulnerability = effect_value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SE_IllusionPersistence:
|
||||||
|
spellbonuses.IllusionPersistence = effect_value;
|
||||||
|
itembonuses.IllusionPersistence = effect_value;
|
||||||
|
aabonuses.IllusionPersistence = effect_value;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
zone/bot.cpp
26
zone/bot.cpp
@ -3292,7 +3292,7 @@ bool Bot::CheckBotDoubleAttack(bool tripleAttack) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod, int16 focus, bool CanRiposte)
|
void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime)
|
||||||
{
|
{
|
||||||
if (!CanDoSpecialAttack(other))
|
if (!CanDoSpecialAttack(other))
|
||||||
return;
|
return;
|
||||||
@ -3396,10 +3396,11 @@ void Bot::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
|||||||
other->Stun(100);
|
other->Stun(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CanSkillProc && HasSkillProcs()){
|
if (CanSkillProc && HasSkillProcs())
|
||||||
float chance = 10.0f*RuleR(Combat, AvgProcsPerMinute)/60000.0f;
|
TrySkillProc(other, skillinuse, ReuseTime);
|
||||||
TrySkillProc(other, skillinuse, chance);
|
|
||||||
}
|
if (CanSkillProc && (damage > 0) && HasSkillProcSuccess())
|
||||||
|
TrySkillProc(other, skillinuse, ReuseTime, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bot::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) {
|
void Bot::ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg) {
|
||||||
@ -7641,10 +7642,8 @@ int16 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel
|
|||||||
{
|
{
|
||||||
if(bottype == BotfocusSympatheticProc)
|
if(bottype == BotfocusSympatheticProc)
|
||||||
{
|
{
|
||||||
float ProcChance, ProcBonus;
|
|
||||||
int16 ProcRateMod = focus_spell.base[i]; //Baseline is 100 for most Sympathetic foci
|
float ProcChance = GetSympatheticProcChances(spell_id, focus_spell.base[i]);
|
||||||
int32 cast_time = GetActSpellCasttime(spell_id, spells[spell_id].cast_time);
|
|
||||||
GetSympatheticProcChances(ProcBonus, ProcChance, cast_time, ProcRateMod);
|
|
||||||
|
|
||||||
if(MakeRandomFloat(0, 1) <= ProcChance)
|
if(MakeRandomFloat(0, 1) <= ProcChance)
|
||||||
value = focus_id;
|
value = focus_id;
|
||||||
@ -8104,10 +8103,11 @@ void Bot::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
|
|||||||
//who->Stun(100); Kayen: This effect does not stun on live, it only moves the NPC.
|
//who->Stun(100); Kayen: This effect does not stun on live, it only moves the NPC.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasSkillProcs()){
|
if (HasSkillProcs())
|
||||||
float chance = (float)ReuseTime*RuleR(Combat, AvgProcsPerMinute)/60000.0f;
|
TrySkillProc(who, skill, ReuseTime*1000);
|
||||||
TrySkillProc(who, skill, chance);
|
|
||||||
}
|
if (max_damage > 0 && HasSkillProcSuccess())
|
||||||
|
TrySkillProc(who, skill, ReuseTime*1000, true);
|
||||||
|
|
||||||
if(max_damage == -3 && !(who->GetHP() <= 0))
|
if(max_damage == -3 && !(who->GetHP() <= 0))
|
||||||
DoRiposte(who);
|
DoRiposte(who);
|
||||||
|
|||||||
@ -185,7 +185,7 @@ public:
|
|||||||
virtual void RogueAssassinate(Mob* other);
|
virtual void RogueAssassinate(Mob* other);
|
||||||
virtual void DoClassAttacks(Mob *target, bool IsRiposte=false);
|
virtual void DoClassAttacks(Mob *target, bool IsRiposte=false);
|
||||||
virtual bool TryHeadShot(Mob* defender, SkillUseTypes skillInUse);
|
virtual bool TryHeadShot(Mob* defender, SkillUseTypes skillInUse);
|
||||||
virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false);
|
virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false, int ReuseTime =0);
|
||||||
virtual void ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg);
|
virtual void ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg);
|
||||||
bool CanDoSpecialAttack(Mob *other);
|
bool CanDoSpecialAttack(Mob *other);
|
||||||
virtual int32 CheckAggroAmount(uint16 spellid);
|
virtual int32 CheckAggroAmount(uint16 spellid);
|
||||||
|
|||||||
@ -776,7 +776,10 @@ public:
|
|||||||
int GetSpentAA() { return m_pp.aapoints_spent; }
|
int GetSpentAA() { return m_pp.aapoints_spent; }
|
||||||
void RefundAA();
|
void RefundAA();
|
||||||
void IncrementAA(int aa_id);
|
void IncrementAA(int aa_id);
|
||||||
|
int32 GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect, bool GetBase1, bool GetBase2);
|
||||||
|
int32 GetAAEffectid(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, true, false,false); }
|
||||||
|
int32 GetAABase1(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, false, true,false); }
|
||||||
|
int32 GetAABase2(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, false, false,true); }
|
||||||
int16 acmod();
|
int16 acmod();
|
||||||
|
|
||||||
// Item methods
|
// Item methods
|
||||||
|
|||||||
@ -9490,13 +9490,6 @@ void Client::CompleteConnect()
|
|||||||
AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100+spells[buffs[j1].spellid].base2[x1],buffs[j1].spellid);
|
AddRangedProc(GetProcID(buffs[j1].spellid, x1), 100+spells[buffs[j1].spellid].base2[x1],buffs[j1].spellid);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SE_SkillProc2:
|
|
||||||
case SE_SkillProc:
|
|
||||||
{
|
|
||||||
AddSkillProc(GetProcID(buffs[j1].spellid, x1), 100+spells[buffs[j1].spellid].base2[x1],buffs[j1].spellid);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -375,6 +375,9 @@ struct StatBonuses {
|
|||||||
bool Sanctuary; // Sanctuary effect, lowers place on hate list until cast on others.
|
bool Sanctuary; // Sanctuary effect, lowers place on hate list until cast on others.
|
||||||
int16 FactionModPct; // Modifies amount of faction gained.
|
int16 FactionModPct; // Modifies amount of faction gained.
|
||||||
int16 MeleeVulnerability; // Weakness/mitigation to melee damage
|
int16 MeleeVulnerability; // Weakness/mitigation to melee damage
|
||||||
|
bool LimitToSkill[HIGHEST_SKILL+2]; // Determines if we need to search for a skill proc.
|
||||||
|
uint16 SkillProc[MAX_SKILL_PROCS]; // Max number of spells containing skill_procs.
|
||||||
|
uint16 SkillProcSuccess[MAX_SKILL_PROCS]; // Max number of spells containing skill_procs_success.
|
||||||
|
|
||||||
// AAs
|
// AAs
|
||||||
int8 Packrat; //weight reduction for items, 1 point = 10%
|
int8 Packrat; //weight reduction for items, 1 point = 10%
|
||||||
@ -431,7 +434,7 @@ struct StatBonuses {
|
|||||||
uint32 Assassinate[2]; // Assassinate AA (Massive dmg vs humaniod w/ assassinate) 0= ? 1= Dmg
|
uint32 Assassinate[2]; // Assassinate AA (Massive dmg vs humaniod w/ assassinate) 0= ? 1= Dmg
|
||||||
uint8 AssassinateLevel; // Max Level Assassinate will be effective at.
|
uint8 AssassinateLevel; // Max Level Assassinate will be effective at.
|
||||||
int32 PetMeleeMitigation; // Add AC to owner's pet.
|
int32 PetMeleeMitigation; // Add AC to owner's pet.
|
||||||
|
bool IllusionPersistence; // Causes illusions not to fade.
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|||||||
@ -308,6 +308,16 @@ Mob *HateList::GetTop(Mob *center)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cur->ent->Sanctuary()) {
|
||||||
|
if(hate == -1)
|
||||||
|
{
|
||||||
|
top = cur->ent;
|
||||||
|
hate = 1;
|
||||||
|
}
|
||||||
|
++iterator;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(cur->ent->DivineAura() || cur->ent->IsMezzed() || cur->ent->IsFeared()){
|
if(cur->ent->DivineAura() || cur->ent->IsMezzed() || cur->ent->IsFeared()){
|
||||||
if(hate == -1)
|
if(hate == -1)
|
||||||
{
|
{
|
||||||
|
|||||||
58
zone/mob.cpp
58
zone/mob.cpp
@ -2753,14 +2753,6 @@ void Mob::Warp( float x, float y, float z )
|
|||||||
SendPosition();
|
SendPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mob::DivineAura() const
|
|
||||||
{
|
|
||||||
if (spellbonuses.DivineAura)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16 Mob::GetResist(uint8 type) const
|
int16 Mob::GetResist(uint8 type) const
|
||||||
{
|
{
|
||||||
if (IsNPC())
|
if (IsNPC())
|
||||||
@ -3042,6 +3034,34 @@ void Mob::TriggerDefensiveProcs(const ItemInst* weapon, Mob *on, uint16 hand, in
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
on->TryDefensiveProc(weapon, this, hand, damage);
|
on->TryDefensiveProc(weapon, this, hand, damage);
|
||||||
|
|
||||||
|
//Defensive Skill Procs
|
||||||
|
if (damage < 0 && damage >= -4) {
|
||||||
|
uint16 skillinuse = 0;
|
||||||
|
switch (damage) {
|
||||||
|
case (-1):
|
||||||
|
skillinuse = SkillBlock;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (-2):
|
||||||
|
skillinuse = SkillParry;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (-3):
|
||||||
|
skillinuse = SkillRiposte;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (-4):
|
||||||
|
skillinuse = SkillDodge;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (on->HasSkillProcs())
|
||||||
|
on->TrySkillProc(this, skillinuse, 0, false, hand, true);
|
||||||
|
|
||||||
|
if (on->HasSkillProcSuccess())
|
||||||
|
on->TrySkillProc(this, skillinuse, 0, true, hand, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::SetDeltas(float dx, float dy, float dz, float dh) {
|
void Mob::SetDeltas(float dx, float dy, float dz, float dh) {
|
||||||
@ -4706,6 +4726,28 @@ bool Mob::PassLimitToSkill(uint16 spell_id, uint16 skill) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16 Mob::GetWeaponSpeedbyHand(uint16 hand) {
|
||||||
|
|
||||||
|
uint16 weapon_speed = 0;
|
||||||
|
switch (hand) {
|
||||||
|
|
||||||
|
case 13:
|
||||||
|
weapon_speed = attack_timer.GetDuration();
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
weapon_speed = attack_dw_timer.GetDuration();
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
weapon_speed = ranged_timer.GetDuration();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (weapon_speed < RuleI(Combat, MinHastedDelay))
|
||||||
|
weapon_speed = RuleI(Combat, MinHastedDelay);
|
||||||
|
|
||||||
|
return weapon_speed;
|
||||||
|
}
|
||||||
|
|
||||||
int8 Mob::GetDecayEffectValue(uint16 spell_id, uint16 spelleffect) {
|
int8 Mob::GetDecayEffectValue(uint16 spell_id, uint16 spelleffect) {
|
||||||
|
|
||||||
if (!IsValidSpell(spell_id))
|
if (!IsValidSpell(spell_id))
|
||||||
|
|||||||
18
zone/mob.h
18
zone/mob.h
@ -506,9 +506,8 @@ public:
|
|||||||
bool AddDefensiveProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN);
|
bool AddDefensiveProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN);
|
||||||
bool RemoveDefensiveProc(uint16 spell_id, bool bAll = false);
|
bool RemoveDefensiveProc(uint16 spell_id, bool bAll = false);
|
||||||
bool HasDefensiveProcs() const;
|
bool HasDefensiveProcs() const;
|
||||||
bool AddSkillProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN);
|
|
||||||
bool RemoveSkillProc(uint16 spell_id, bool bAll = false);
|
|
||||||
bool HasSkillProcs() const;
|
bool HasSkillProcs() const;
|
||||||
|
bool HasSkillProcSuccess() const;
|
||||||
bool AddProcToWeapon(uint16 spell_id, bool bPerma = false, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN);
|
bool AddProcToWeapon(uint16 spell_id, bool bPerma = false, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN);
|
||||||
bool RemoveProcFromWeapon(uint16 spell_id, bool bAll = false);
|
bool RemoveProcFromWeapon(uint16 spell_id, bool bAll = false);
|
||||||
bool HasProcs() const;
|
bool HasProcs() const;
|
||||||
@ -700,9 +699,9 @@ public:
|
|||||||
int32 ReduceAllDamage(int32 damage);
|
int32 ReduceAllDamage(int32 damage);
|
||||||
|
|
||||||
virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false, bool CanAvoid=true);
|
virtual void DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage, int32 min_damage = 1, int32 hate_override = -1, int ReuseTime = 10, bool HitChance=false, bool CanAvoid=true);
|
||||||
virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* item=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0);
|
virtual void DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const Item_Struct* item=nullptr, uint16 weapon_damage=0, int16 chance_mod=0,int16 focus=0, int ReuseTime=0);
|
||||||
virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false);
|
virtual void DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod=0, int16 focus=0, bool CanRiposte=false, int ReuseTime=0);
|
||||||
virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0);
|
virtual void DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon=nullptr, const ItemInst* Ammo=nullptr, uint16 weapon_damage=0, int16 chance_mod=0, int16 focus=0, int ReuseTime=0);
|
||||||
bool CanDoSpecialAttack(Mob *other);
|
bool CanDoSpecialAttack(Mob *other);
|
||||||
bool Flurry(ExtraAttackOptions *opts);
|
bool Flurry(ExtraAttackOptions *opts);
|
||||||
bool Rampage(ExtraAttackOptions *opts);
|
bool Rampage(ExtraAttackOptions *opts);
|
||||||
@ -819,7 +818,8 @@ public:
|
|||||||
inline int& GetNextIncHPEvent() { return nextinchpevent; }
|
inline int& GetNextIncHPEvent() { return nextinchpevent; }
|
||||||
void SetNextIncHPEvent( int inchpevent );
|
void SetNextIncHPEvent( int inchpevent );
|
||||||
|
|
||||||
bool DivineAura() const;
|
inline bool DivineAura() const { return spellbonuses.DivineAura; }
|
||||||
|
inline bool Sanctuary() const { return spellbonuses.Sanctuary; }
|
||||||
|
|
||||||
bool HasNPCSpecialAtk(const char* parse);
|
bool HasNPCSpecialAtk(const char* parse);
|
||||||
int GetSpecialAbility(int ability);
|
int GetSpecialAbility(int ability);
|
||||||
@ -986,7 +986,7 @@ protected:
|
|||||||
bool focused;
|
bool focused;
|
||||||
void CalcSpellBonuses(StatBonuses* newbon);
|
void CalcSpellBonuses(StatBonuses* newbon);
|
||||||
virtual void CalcBonuses();
|
virtual void CalcBonuses();
|
||||||
void TrySkillProc(Mob *on, uint16 skill, float chance);
|
void TrySkillProc(Mob *on, uint16 skill, uint16 ReuseTime, bool Success = false, uint16 hand = 0, bool IsDefensive = false);
|
||||||
bool PassLimitToSkill(uint16 spell_id, uint16 skill);
|
bool PassLimitToSkill(uint16 spell_id, uint16 skill);
|
||||||
bool PassLimitClass(uint32 Classes_, uint16 Class_);
|
bool PassLimitClass(uint32 Classes_, uint16 Class_);
|
||||||
void TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand = 13, int damage=0);
|
void TryDefensiveProc(const ItemInst* weapon, Mob *on, uint16 hand = 13, int damage=0);
|
||||||
@ -998,6 +998,8 @@ protected:
|
|||||||
virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed = 30, uint16 hand = 13);
|
virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 weapon_speed = 30, uint16 hand = 13);
|
||||||
virtual float GetSpecialProcChances(uint16 hand);
|
virtual float GetSpecialProcChances(uint16 hand);
|
||||||
virtual float GetAssassinateProcChances(uint16 ReuseTime);
|
virtual float GetAssassinateProcChances(uint16 ReuseTime);
|
||||||
|
virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0);
|
||||||
|
uint16 GetWeaponSpeedbyHand(uint16 hand);
|
||||||
int GetWeaponDamage(Mob *against, const Item_Struct *weapon_item);
|
int GetWeaponDamage(Mob *against, const Item_Struct *weapon_item);
|
||||||
int GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate = nullptr);
|
int GetWeaponDamage(Mob *against, const ItemInst *weapon_item, uint32 *hate = nullptr);
|
||||||
int GetKickDamage();
|
int GetKickDamage();
|
||||||
@ -1009,7 +1011,7 @@ protected:
|
|||||||
Map::Vertex UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChange, bool &NodeReached);
|
Map::Vertex UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChange, bool &NodeReached);
|
||||||
void PrintRoute();
|
void PrintRoute();
|
||||||
|
|
||||||
virtual float GetSympatheticProcChances(float &ProcBonus, float &ProcChance, int32 cast_time, int16 ProcRateMod);
|
virtual float GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 ItemProcRate = 0);
|
||||||
|
|
||||||
enum {MAX_PROCS = 4};
|
enum {MAX_PROCS = 4};
|
||||||
tProc PermaProcs[MAX_PROCS];
|
tProc PermaProcs[MAX_PROCS];
|
||||||
|
|||||||
@ -171,10 +171,11 @@ void Mob::DoSpecialAttackDamage(Mob *who, SkillUseTypes skill, int32 max_damage,
|
|||||||
//who->Stun(100); Kayen: This effect does not stun on live, it only moves the NPC.
|
//who->Stun(100); Kayen: This effect does not stun on live, it only moves the NPC.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasSkillProcs()){
|
if (HasSkillProcs())
|
||||||
float chance = (float)ReuseTime*RuleR(Combat, AvgProcsPerMinute)/60000.0f;
|
TrySkillProc(who, skill, ReuseTime*1000);
|
||||||
TrySkillProc(who, skill, chance);
|
|
||||||
}
|
if (max_damage > 0 && HasSkillProcSuccess())
|
||||||
|
TrySkillProc(who, skill, ReuseTime*1000, true);
|
||||||
|
|
||||||
if(max_damage == -3 && !who->HasDied())
|
if(max_damage == -3 && !who->HasDied())
|
||||||
DoRiposte(who);
|
DoRiposte(who);
|
||||||
@ -847,7 +848,7 @@ void Client::RangedAttack(Mob* other, bool CanDoubleAttack) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus)
|
void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const ItemInst* Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime)
|
||||||
{
|
{
|
||||||
if (!CanDoSpecialAttack(other))
|
if (!CanDoSpecialAttack(other))
|
||||||
return;
|
return;
|
||||||
@ -874,6 +875,9 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item
|
|||||||
else
|
else
|
||||||
WDmg = weapon_damage;
|
WDmg = weapon_damage;
|
||||||
|
|
||||||
|
if (focus) //From FcBaseEffects
|
||||||
|
WDmg += WDmg*focus/100;
|
||||||
|
|
||||||
if((WDmg > 0) || (ADmg > 0))
|
if((WDmg > 0) || (ADmg > 0))
|
||||||
{
|
{
|
||||||
if(WDmg < 0)
|
if(WDmg < 0)
|
||||||
@ -948,7 +952,6 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item
|
|||||||
other->MeleeMitigation(this, TotalDmg, minDmg);
|
other->MeleeMitigation(this, TotalDmg, minDmg);
|
||||||
if(TotalDmg > 0)
|
if(TotalDmg > 0)
|
||||||
{
|
{
|
||||||
TotalDmg += TotalDmg*focus/100;
|
|
||||||
ApplyMeleeDamageBonus(SkillArchery, TotalDmg);
|
ApplyMeleeDamageBonus(SkillArchery, TotalDmg);
|
||||||
TotalDmg += other->GetFcDamageAmtIncoming(this, 0, true, SkillArchery);
|
TotalDmg += other->GetFcDamageAmtIncoming(this, 0, true, SkillArchery);
|
||||||
TotalDmg += (itembonuses.HeroicDEX / 10) + (TotalDmg * other->GetSkillDmgTaken(SkillArchery) / 100) + GetSkillDmgAmt(SkillArchery);
|
TotalDmg += (itembonuses.HeroicDEX / 10) + (TotalDmg * other->GetSkillDmgTaken(SkillArchery) / 100) + GetSkillDmgAmt(SkillArchery);
|
||||||
@ -968,19 +971,32 @@ void Mob::DoArcheryAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item
|
|||||||
|
|
||||||
other->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillArchery);
|
other->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillArchery);
|
||||||
|
|
||||||
|
if (TotalDmg > 0 && HasSkillProcSuccess() && GetTarget() && other && !other->HasDied()){
|
||||||
|
if (ReuseTime)
|
||||||
|
TrySkillProc(other, SkillArchery, ReuseTime);
|
||||||
|
else
|
||||||
|
TrySkillProc(other, SkillArchery, 0, true, 11);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//try proc on hits and misses
|
//try proc on hits and misses
|
||||||
if((RangeWeapon != nullptr) && GetTarget() && other && (other->GetHP() > -10))
|
if((RangeWeapon != nullptr) && GetTarget() && other && !other->HasDied())
|
||||||
{
|
{
|
||||||
TryWeaponProc(RangeWeapon, other, 11);
|
TryWeaponProc(RangeWeapon, other, 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Arrow procs because why not?
|
//Arrow procs because why not?
|
||||||
if((Ammo != NULL) && GetTarget() && other && (other->GetHP() > -10))
|
if((Ammo != NULL) && GetTarget() && other && !other->HasDied())
|
||||||
{
|
{
|
||||||
TryWeaponProc(Ammo, other, 11);
|
TryWeaponProc(Ammo, other, 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (HasSkillProcs() && GetTarget() && other && !other->HasDied()){
|
||||||
|
if (ReuseTime)
|
||||||
|
TrySkillProc(other, SkillArchery, ReuseTime);
|
||||||
|
else
|
||||||
|
TrySkillProc(other, SkillArchery, 0, false, 11);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NPC::RangedAttack(Mob* other)
|
void NPC::RangedAttack(Mob* other)
|
||||||
@ -1253,7 +1269,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item_Struct* item, uint16 weapon_damage, int16 chance_mod,int16 focus)
|
void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Item_Struct* item, uint16 weapon_damage, int16 chance_mod,int16 focus, int ReuseTime)
|
||||||
{
|
{
|
||||||
if (!CanDoSpecialAttack(other))
|
if (!CanDoSpecialAttack(other))
|
||||||
return;
|
return;
|
||||||
@ -1271,6 +1287,9 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
|
|||||||
else
|
else
|
||||||
WDmg = weapon_damage;
|
WDmg = weapon_damage;
|
||||||
|
|
||||||
|
if (focus) //From FcBaseEffects
|
||||||
|
WDmg += WDmg*focus/100;
|
||||||
|
|
||||||
int32 TotalDmg = 0;
|
int32 TotalDmg = 0;
|
||||||
|
|
||||||
uint32 Assassinate_Dmg = 0;
|
uint32 Assassinate_Dmg = 0;
|
||||||
@ -1294,7 +1313,6 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
|
|||||||
other->MeleeMitigation(this, TotalDmg, minDmg);
|
other->MeleeMitigation(this, TotalDmg, minDmg);
|
||||||
if(TotalDmg > 0)
|
if(TotalDmg > 0)
|
||||||
{
|
{
|
||||||
TotalDmg += TotalDmg*focus/100;
|
|
||||||
ApplyMeleeDamageBonus(SkillThrowing, TotalDmg);
|
ApplyMeleeDamageBonus(SkillThrowing, TotalDmg);
|
||||||
TotalDmg += other->GetFcDamageAmtIncoming(this, 0, true, SkillThrowing);
|
TotalDmg += other->GetFcDamageAmtIncoming(this, 0, true, SkillThrowing);
|
||||||
TotalDmg += (itembonuses.HeroicDEX / 10) + (TotalDmg * other->GetSkillDmgTaken(SkillThrowing) / 100) + GetSkillDmgAmt(SkillThrowing);
|
TotalDmg += (itembonuses.HeroicDEX / 10) + (TotalDmg * other->GetSkillDmgTaken(SkillThrowing) / 100) + GetSkillDmgAmt(SkillThrowing);
|
||||||
@ -1309,10 +1327,25 @@ void Mob::DoThrowingAttackDmg(Mob* other, const ItemInst* RangeWeapon, const Ite
|
|||||||
TotalDmg = -5;
|
TotalDmg = -5;
|
||||||
|
|
||||||
other->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillThrowing);
|
other->Damage(this, TotalDmg, SPELL_UNKNOWN, SkillThrowing);
|
||||||
|
|
||||||
|
if (TotalDmg > 0 && HasSkillProcSuccess() && GetTarget() && other && !other->HasDied()){
|
||||||
|
if (ReuseTime)
|
||||||
|
TrySkillProc(other, SkillThrowing, ReuseTime);
|
||||||
|
else
|
||||||
|
TrySkillProc(other, SkillThrowing, 0, true, 11);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((RangeWeapon != nullptr) && GetTarget() && other && (other->GetHP() > -10))
|
if((RangeWeapon != nullptr) && GetTarget() && other && (other->GetHP() > -10))
|
||||||
TryWeaponProc(RangeWeapon, other, 11);
|
TryWeaponProc(RangeWeapon, other, 11);
|
||||||
|
|
||||||
|
if (HasSkillProcs() && GetTarget() && other && !other->HasDied()){
|
||||||
|
if (ReuseTime)
|
||||||
|
TrySkillProc(other, SkillThrowing, ReuseTime);
|
||||||
|
else
|
||||||
|
TrySkillProc(other, SkillThrowing, 0, false, 11);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse) {
|
void Mob::SendItemAnimation(Mob *to, const Item_Struct *item, SkillUseTypes skillInUse) {
|
||||||
@ -1891,6 +1924,7 @@ void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) {
|
|||||||
Mob *hate_top = who->GetHateMost();
|
Mob *hate_top = who->GetHateMost();
|
||||||
|
|
||||||
float level_difference = GetLevel() - who->GetLevel();
|
float level_difference = GetLevel() - who->GetLevel();
|
||||||
|
bool Success = false;
|
||||||
|
|
||||||
//Support for how taunt worked pre 2000 on LIVE - Can not taunt NPC over your level.
|
//Support for how taunt worked pre 2000 on LIVE - Can not taunt NPC over your level.
|
||||||
if ((RuleB(Combat,TauntOverLevel) == false) && (level_difference < 0) || who->GetSpecialAbility(IMMUNE_TAUNT)){
|
if ((RuleB(Combat,TauntOverLevel) == false) && (level_difference < 0) || who->GetSpecialAbility(IMMUNE_TAUNT)){
|
||||||
@ -1940,6 +1974,7 @@ void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) {
|
|||||||
if (hate_top && hate_top != this){
|
if (hate_top && hate_top != this){
|
||||||
newhate = (who->GetNPCHate(hate_top) - who->GetNPCHate(this)) + 1;
|
newhate = (who->GetNPCHate(hate_top) - who->GetNPCHate(this)) + 1;
|
||||||
who->CastToNPC()->AddToHateList(this, newhate);
|
who->CastToNPC()->AddToHateList(this, newhate);
|
||||||
|
Success = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
who->CastToNPC()->AddToHateList(this,12);
|
who->CastToNPC()->AddToHateList(this,12);
|
||||||
@ -1955,10 +1990,12 @@ void Mob::Taunt(NPC* who, bool always_succeed, float chance_bonus) {
|
|||||||
else
|
else
|
||||||
Message_StringID(MT_SpellFailure,FAILED_TAUNT);
|
Message_StringID(MT_SpellFailure,FAILED_TAUNT);
|
||||||
|
|
||||||
if (HasSkillProcs()){
|
if (HasSkillProcs())
|
||||||
float chance = (float)TauntReuseTime*RuleR(Combat, AvgProcsPerMinute)/60000.0f;
|
TrySkillProc(who, SkillTaunt, TauntReuseTime*1000);
|
||||||
TrySkillProc(who, SkillTaunt, chance);
|
|
||||||
}
|
|
||||||
|
if (Success && HasSkillProcSuccess())
|
||||||
|
TrySkillProc(who, SkillTaunt, TauntReuseTime*1000, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2045,20 +2082,7 @@ float Mob::GetSpecialProcChances(uint16 hand)
|
|||||||
float ProcChance = 0.0f;
|
float ProcChance = 0.0f;
|
||||||
float ProcBonus = 0.0f;
|
float ProcBonus = 0.0f;
|
||||||
|
|
||||||
switch (hand) {
|
weapon_speed = GetWeaponSpeedbyHand(hand);
|
||||||
case 13:
|
|
||||||
weapon_speed = attack_timer.GetDuration();
|
|
||||||
break;
|
|
||||||
case 14:
|
|
||||||
weapon_speed = attack_dw_timer.GetDuration();
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
weapon_speed = ranged_timer.GetDuration();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (weapon_speed < RuleI(Combat, MinHastedDelay))
|
|
||||||
weapon_speed = RuleI(Combat, MinHastedDelay);
|
|
||||||
|
|
||||||
if (RuleB(Combat, AdjustSpecialProcPerMinute)) {
|
if (RuleB(Combat, AdjustSpecialProcPerMinute)) {
|
||||||
ProcChance = (static_cast<float>(weapon_speed) *
|
ProcChance = (static_cast<float>(weapon_speed) *
|
||||||
@ -2066,7 +2090,7 @@ float Mob::GetSpecialProcChances(uint16 hand)
|
|||||||
ProcBonus += static_cast<float>(mydex/35) + static_cast<float>(itembonuses.HeroicDEX / 25);
|
ProcBonus += static_cast<float>(mydex/35) + static_cast<float>(itembonuses.HeroicDEX / 25);
|
||||||
ProcChance += ProcChance * ProcBonus / 100.0f;
|
ProcChance += ProcChance * ProcBonus / 100.0f;
|
||||||
} else {
|
} else {
|
||||||
/*PRE 2014 CHANGE Dev Quote - "Elidroth SOE:Proc chance is a function of your base hardcapped Dexterity / 35 + Heroic Dexterity / 25.”
|
/*PRE 2014 CHANGE Dev Quote - "Elidroth SOE:Proc chance is a function of your base hardcapped Dexterity / 35 + Heroic Dexterity / 25.
|
||||||
Kayen: Most reports suggest a ~ 6% chance to Headshot which consistent with above.*/
|
Kayen: Most reports suggest a ~ 6% chance to Headshot which consistent with above.*/
|
||||||
|
|
||||||
ProcChance = (static_cast<float>(mydex/35) + static_cast<float>(itembonuses.HeroicDEX / 25))/100.0f;
|
ProcChance = (static_cast<float>(mydex/35) + static_cast<float>(itembonuses.HeroicDEX / 25))/100.0f;
|
||||||
@ -2138,7 +2162,7 @@ float Mob::GetAssassinateProcChances(uint16 ReuseTime)
|
|||||||
return ProcChance;
|
return ProcChance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod, int16 focus, bool CanRiposte)
|
void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime)
|
||||||
{
|
{
|
||||||
if (!CanDoSpecialAttack(other))
|
if (!CanDoSpecialAttack(other))
|
||||||
return;
|
return;
|
||||||
@ -2155,6 +2179,9 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
|||||||
|
|
||||||
if(weapon_damage > 0){
|
if(weapon_damage > 0){
|
||||||
|
|
||||||
|
if (focus) //From FcBaseEffects
|
||||||
|
weapon_damage += weapon_damage*focus/100;
|
||||||
|
|
||||||
if(GetClass() == BERSERKER){
|
if(GetClass() == BERSERKER){
|
||||||
int bonus = 3 + GetLevel()/10;
|
int bonus = 3 + GetLevel()/10;
|
||||||
weapon_damage = weapon_damage * (100+bonus) / 100;
|
weapon_damage = weapon_damage * (100+bonus) / 100;
|
||||||
@ -2190,7 +2217,6 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
|||||||
other->AvoidDamage(this, damage, CanRiposte);
|
other->AvoidDamage(this, damage, CanRiposte);
|
||||||
other->MeleeMitigation(this, damage, min_hit);
|
other->MeleeMitigation(this, damage, min_hit);
|
||||||
if(damage > 0) {
|
if(damage > 0) {
|
||||||
damage += damage*focus/100;
|
|
||||||
ApplyMeleeDamageBonus(skillinuse, damage);
|
ApplyMeleeDamageBonus(skillinuse, damage);
|
||||||
damage += other->GetFcDamageAmtIncoming(this, 0, true, skillinuse);
|
damage += other->GetFcDamageAmtIncoming(this, 0, true, skillinuse);
|
||||||
damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse);
|
damage += (itembonuses.HeroicSTR / 10) + (damage * other->GetSkillDmgTaken(skillinuse) / 100) + GetSkillDmgAmt(skillinuse);
|
||||||
@ -2244,10 +2270,11 @@ void Mob::DoMeleeSkillAttackDmg(Mob* other, uint16 weapon_damage, SkillUseTypes
|
|||||||
SpellFinished(904, other, 10, 0, -1, spells[904].ResistDiff);
|
SpellFinished(904, other, 10, 0, -1, spells[904].ResistDiff);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CanSkillProc && HasSkillProcs()){
|
if (CanSkillProc && HasSkillProcs())
|
||||||
float chance = 10.0f*RuleR(Combat, AvgProcsPerMinute)/60000.0f;
|
TrySkillProc(other, skillinuse, ReuseTime);
|
||||||
TrySkillProc(other, skillinuse, chance);
|
|
||||||
}
|
if (CanSkillProc && (damage > 0) && HasSkillProcSuccess())
|
||||||
|
TrySkillProc(other, skillinuse, ReuseTime, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mob::CanDoSpecialAttack(Mob *other)
|
bool Mob::CanDoSpecialAttack(Mob *other)
|
||||||
|
|||||||
@ -1430,7 +1430,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
for(int x = 0; x < 7; x++){
|
for(int x = 0; x < 7; x++){
|
||||||
SendWearChange(x);
|
SendWearChange(x);
|
||||||
}
|
}
|
||||||
if(caster && caster->GetAA(aaPermanentIllusion))
|
if(caster && (caster->spellbonuses.IllusionPersistence || caster->aabonuses.IllusionPersistence
|
||||||
|
|| caster->itembonuses.IllusionPersistence))
|
||||||
buffs[buffslot].persistant_buff = 1;
|
buffs[buffslot].persistant_buff = 1;
|
||||||
else
|
else
|
||||||
buffs[buffslot].persistant_buff = 0;
|
buffs[buffslot].persistant_buff = 0;
|
||||||
@ -1772,20 +1773,6 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SE_SkillProc2:
|
|
||||||
case SE_SkillProc:
|
|
||||||
{
|
|
||||||
uint16 procid = GetProcID(spell_id, i);
|
|
||||||
#ifdef SPELL_EFFECT_SPAM
|
|
||||||
snprintf(effect_desc, _EDLEN, "Weapon Proc: %s (id %d)", spells[effect_value].name, procid);
|
|
||||||
#endif
|
|
||||||
if(spells[spell_id].base2[i] == 0)
|
|
||||||
AddSkillProc(procid, 100, spell_id);
|
|
||||||
else
|
|
||||||
AddSkillProc(procid, spells[spell_id].base2[i]+100, spell_id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SE_NegateAttacks:
|
case SE_NegateAttacks:
|
||||||
{
|
{
|
||||||
#ifdef SPELL_EFFECT_SPAM
|
#ifdef SPELL_EFFECT_SPAM
|
||||||
@ -2256,6 +2243,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
*Max is lower value then Weapon base, possibly min hit vs Weapon Damage range ie. MakeRandInt(max,base)
|
*Max is lower value then Weapon base, possibly min hit vs Weapon Damage range ie. MakeRandInt(max,base)
|
||||||
*/
|
*/
|
||||||
int16 focus = 0;
|
int16 focus = 0;
|
||||||
|
int ReuseTime = spells[spell_id].recast_time + spells[spell_id].recovery_time;
|
||||||
|
|
||||||
if(caster->IsClient())
|
if(caster->IsClient())
|
||||||
focus = caster->CastToClient()->GetFocusEffect(focusFcBaseEffects, spell_id);
|
focus = caster->CastToClient()->GetFocusEffect(focusFcBaseEffects, spell_id);
|
||||||
@ -2263,15 +2251,15 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
switch(spells[spell_id].skill)
|
switch(spells[spell_id].skill)
|
||||||
{
|
{
|
||||||
case SkillThrowing:
|
case SkillThrowing:
|
||||||
caster->DoThrowingAttackDmg(this, nullptr, nullptr, spells[spell_id].base[i],spells[spell_id].base2[i], focus);
|
caster->DoThrowingAttackDmg(this, nullptr, nullptr, spells[spell_id].base[i],spells[spell_id].base2[i], focus, ReuseTime);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SkillArchery:
|
case SkillArchery:
|
||||||
caster->DoArcheryAttackDmg(this, nullptr, nullptr, spells[spell_id].base[i],spells[spell_id].base2[i],focus);
|
caster->DoArcheryAttackDmg(this, nullptr, nullptr, spells[spell_id].base[i],spells[spell_id].base2[i],focus,ReuseTime);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
caster->DoMeleeSkillAttackDmg(this, spells[spell_id].base[i], spells[spell_id].skill, spells[spell_id].base2[i], focus);
|
caster->DoMeleeSkillAttackDmg(this, spells[spell_id].base[i], spells[spell_id].skill, spells[spell_id].base2[i], focus, ReuseTime);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2329,7 +2317,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
if (buffslot >= 0)
|
if (buffslot >= 0)
|
||||||
break;
|
break;
|
||||||
//This effect does no damage if target is moving.
|
//This effect does no damage if target is moving.
|
||||||
if (IsMoving())
|
if (!RuleB(Spells, PreNerfBardAEDoT) && IsMoving())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// for offensive spells check if we have a spell rune on
|
// for offensive spells check if we have a spell rune on
|
||||||
@ -2735,22 +2723,6 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SE_Sanctuary:
|
|
||||||
{
|
|
||||||
std::list<NPC*> npc_list;
|
|
||||||
entity_list.GetNPCList(npc_list);
|
|
||||||
|
|
||||||
for(std::list<NPC*>::iterator itr = npc_list.begin(); itr != npc_list.end(); ++itr) {
|
|
||||||
|
|
||||||
NPC* npc = *itr;
|
|
||||||
|
|
||||||
if (npc && npc->CheckAggro(this))
|
|
||||||
npc->SetHate(caster, 1);
|
|
||||||
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handled Elsewhere
|
// Handled Elsewhere
|
||||||
case SE_ImmuneFleeing:
|
case SE_ImmuneFleeing:
|
||||||
case SE_NegateSpellEffect:
|
case SE_NegateSpellEffect:
|
||||||
@ -2984,6 +2956,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
|
|||||||
case SE_AssassinateLevel:
|
case SE_AssassinateLevel:
|
||||||
case SE_FactionModPct:
|
case SE_FactionModPct:
|
||||||
case SE_LimitSpellClass:
|
case SE_LimitSpellClass:
|
||||||
|
case SE_Sanctuary:
|
||||||
|
case SE_PetMeleeMitigation:
|
||||||
|
case SE_SkillProc:
|
||||||
|
case SE_SkillProcSuccess:
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -3403,7 +3379,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
|
|||||||
{
|
{
|
||||||
effect_value = CalcSpellEffectValue(spell_id, i, caster_level, caster);
|
effect_value = CalcSpellEffectValue(spell_id, i, caster_level, caster);
|
||||||
|
|
||||||
if (IsMoving() || invulnerable || /*effect_value > 0 ||*/ DivineAura())
|
if ((!RuleB(Spells, PreNerfBardAEDoT) && IsMoving()) || invulnerable || /*effect_value > 0 ||*/ DivineAura())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(effect_value < 0) {
|
if(effect_value < 0) {
|
||||||
@ -3630,21 +3606,6 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SE_Sanctuary:
|
|
||||||
{
|
|
||||||
std::list<NPC*> npc_list;
|
|
||||||
entity_list.GetNPCList(npc_list);
|
|
||||||
|
|
||||||
for(std::list<NPC*>::iterator itr = npc_list.begin(); itr != npc_list.end(); ++itr) {
|
|
||||||
|
|
||||||
NPC* npc = *itr;
|
|
||||||
|
|
||||||
if (npc && npc->CheckAggro(this))
|
|
||||||
npc->SetHate(caster, 1);
|
|
||||||
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
@ -3712,14 +3673,6 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SE_SkillProc2:
|
|
||||||
case SE_SkillProc:
|
|
||||||
{
|
|
||||||
uint16 procid = GetProcID(buffs[slot].spellid, i);
|
|
||||||
RemoveSkillProc(procid);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SE_DefensiveProc:
|
case SE_DefensiveProc:
|
||||||
{
|
{
|
||||||
uint16 procid = GetProcID(buffs[slot].spellid, i);
|
uint16 procid = GetProcID(buffs[slot].spellid, i);
|
||||||
@ -4084,39 +4037,41 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses)
|
|||||||
CalcBonuses();
|
CalcBonuses();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No longer used.
|
int32 Client::GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect, bool GetBase1, bool GetBase2)
|
||||||
int16 Client::CalcAAFocusEffect(focusType type, uint16 focus_spell, uint16 spell_id)
|
|
||||||
{
|
{
|
||||||
uint32 slots = 0;
|
int32 aa_effects_data[3] = { 0 };
|
||||||
uint32 aa_AA = 0;
|
uint32 effect = 0;
|
||||||
uint32 aa_value = 0;
|
int32 base1 = 0;
|
||||||
|
int32 base2 = 0;
|
||||||
|
uint32 slot = 0;
|
||||||
|
|
||||||
int32 value = 0;
|
|
||||||
// Iterate through all of the client's AAs
|
std::map<uint32, std::map<uint32, AA_Ability> >::const_iterator find_iter = aa_effects.find(aa_ID);
|
||||||
for (int i = 0; i < MAX_PP_AA_ARRAY; i++)
|
if(find_iter == aa_effects.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (std::map<uint32, AA_Ability>::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter)
|
||||||
{
|
{
|
||||||
aa_AA = this->aa[i]->AA;
|
effect = iter->second.skill_id;
|
||||||
aa_value = this->aa[i]->value;
|
base1 = iter->second.base1;
|
||||||
if (aa_AA > 0 || aa_value > 0)
|
base2 = iter->second.base2;
|
||||||
{
|
slot = iter->second.slot;
|
||||||
slots = zone->GetTotalAALevels(aa_AA);
|
|
||||||
if (slots > 0)
|
if (slot && slot == slot_id) {
|
||||||
for(int j = 1;j <= slots; j++)
|
|
||||||
{
|
if (GetEffect)
|
||||||
switch (aa_effects[aa_AA][j].skill_id)
|
return effect;
|
||||||
{
|
|
||||||
case SE_TriggerOnCast:
|
if (GetBase1)
|
||||||
// If focus_spell matches the spell listed in the DB, load these restrictions
|
return base1;
|
||||||
if(type == focusTriggerOnCast && focus_spell == aa_effects[aa_AA][j].base1)
|
|
||||||
value = CalcAAFocus(type, aa_AA, spell_id);
|
if (GetBase2)
|
||||||
break;
|
return base2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
return 0;
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id)
|
int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id)
|
||||||
@ -4496,8 +4451,10 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id)
|
|||||||
value = base1;
|
value = base1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
//Note if using these as AA, make sure this is first focus used.
|
||||||
case SE_SympatheticProc:
|
case SE_SympatheticProc:
|
||||||
//No AA support at this time.
|
if(type == focusSympatheticProc)
|
||||||
|
value = base2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SE_FcDamageAmt:
|
case SE_FcDamageAmt:
|
||||||
@ -4962,16 +4919,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo
|
|||||||
|
|
||||||
case SE_SympatheticProc:
|
case SE_SympatheticProc:
|
||||||
if(type == focusSympatheticProc) {
|
if(type == focusSympatheticProc) {
|
||||||
float ProcChance, ProcBonus;
|
|
||||||
int16 ProcRateMod = focus_spell.base[i]; //Baseline is 100 for most Sympathetic foci
|
|
||||||
int32 cast_time = GetActSpellCasttime(spell_id, spells[spell_id].cast_time);
|
|
||||||
GetSympatheticProcChances(ProcBonus, ProcChance, cast_time, ProcRateMod);
|
|
||||||
|
|
||||||
if(MakeRandomFloat(0, 1) <= ProcChance)
|
|
||||||
value = focus_id;
|
value = focus_id;
|
||||||
|
|
||||||
else
|
|
||||||
value = 0;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -5089,8 +5037,8 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
uint16 proc_spellid = 0;
|
uint16 proc_spellid = 0;
|
||||||
uint8 SizeProcList = 0;
|
|
||||||
uint8 MAX_SYMPATHETIC = 10;
|
uint8 MAX_SYMPATHETIC = 10;
|
||||||
|
float ProcChance = 0.0f;
|
||||||
|
|
||||||
std::vector<int> SympatheticProcList;
|
std::vector<int> SympatheticProcList;
|
||||||
|
|
||||||
@ -5101,7 +5049,7 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
|
|||||||
|
|
||||||
for(int x=0; x<=21; x++)
|
for(int x=0; x<=21; x++)
|
||||||
{
|
{
|
||||||
if (SizeProcList > MAX_SYMPATHETIC)
|
if (SympatheticProcList.size() > MAX_SYMPATHETIC)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TempItem = nullptr;
|
TempItem = nullptr;
|
||||||
@ -5109,20 +5057,22 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
|
|||||||
if (!ins)
|
if (!ins)
|
||||||
continue;
|
continue;
|
||||||
TempItem = ins->GetItem();
|
TempItem = ins->GetItem();
|
||||||
if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) {
|
if (TempItem && TempItem->Focus.Effect > 0 && IsValidSpell(TempItem->Focus.Effect)) {
|
||||||
|
|
||||||
proc_spellid = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id);
|
proc_spellid = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id);
|
||||||
|
|
||||||
if (proc_spellid > 0)
|
if (IsValidSpell(proc_spellid)){
|
||||||
{
|
|
||||||
|
ProcChance = GetSympatheticProcChances(spell_id, spells[TempItem->Focus.Effect].base[0], TempItem->ProcRate);
|
||||||
|
|
||||||
|
if(MakeRandomFloat(0, 1) <= ProcChance)
|
||||||
SympatheticProcList.push_back(proc_spellid);
|
SympatheticProcList.push_back(proc_spellid);
|
||||||
SizeProcList = SympatheticProcList.size();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int y = 0; y < MAX_AUGMENT_SLOTS; ++y)
|
for(int y = 0; y < MAX_AUGMENT_SLOTS; ++y)
|
||||||
{
|
{
|
||||||
if (SizeProcList > MAX_SYMPATHETIC)
|
if (SympatheticProcList.size() > MAX_SYMPATHETIC)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ItemInst *aug = nullptr;
|
ItemInst *aug = nullptr;
|
||||||
@ -5130,14 +5080,16 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
|
|||||||
if(aug)
|
if(aug)
|
||||||
{
|
{
|
||||||
const Item_Struct* TempItemAug = aug->GetItem();
|
const Item_Struct* TempItemAug = aug->GetItem();
|
||||||
if (TempItemAug && TempItemAug->Focus.Effect > 0 && TempItemAug->Focus.Effect != SPELL_UNKNOWN) {
|
if (TempItemAug && TempItemAug->Focus.Effect > 0 && IsValidSpell(TempItemAug->Focus.Effect)) {
|
||||||
|
|
||||||
proc_spellid = CalcFocusEffect(type, TempItemAug->Focus.Effect, spell_id);
|
proc_spellid = CalcFocusEffect(type, TempItemAug->Focus.Effect, spell_id);
|
||||||
|
|
||||||
if (proc_spellid > 0)
|
if (IsValidSpell(proc_spellid)){
|
||||||
{
|
|
||||||
|
ProcChance = GetSympatheticProcChances(spell_id, spells[TempItem->Focus.Effect].base[0], TempItemAug->ProcRate);
|
||||||
|
|
||||||
|
if(MakeRandomFloat(0, 1) <= ProcChance)
|
||||||
SympatheticProcList.push_back(proc_spellid);
|
SympatheticProcList.push_back(proc_spellid);
|
||||||
SizeProcList = SympatheticProcList.size();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5152,26 +5104,57 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) {
|
|||||||
uint32 buff_max = GetMaxTotalSlots();
|
uint32 buff_max = GetMaxTotalSlots();
|
||||||
for (buff_slot = 0; buff_slot < buff_max; buff_slot++) {
|
for (buff_slot = 0; buff_slot < buff_max; buff_slot++) {
|
||||||
|
|
||||||
if (SizeProcList > MAX_SYMPATHETIC)
|
if (SympatheticProcList.size() > MAX_SYMPATHETIC)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
focusspellid = buffs[buff_slot].spellid;
|
focusspellid = buffs[buff_slot].spellid;
|
||||||
if (focusspellid == 0 || focusspellid >= SPDAT_RECORDS)
|
if (IsValidSpell(focusspellid))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
proc_spellid = CalcFocusEffect(type, focusspellid, spell_id);
|
proc_spellid = CalcFocusEffect(type, focusspellid, spell_id);
|
||||||
|
|
||||||
if (proc_spellid > 0)
|
if (IsValidSpell(proc_spellid)){
|
||||||
{
|
|
||||||
|
ProcChance = GetSympatheticProcChances(spell_id, spells[focusspellid].base[0]);
|
||||||
|
|
||||||
|
if(MakeRandomFloat(0, 1) <= ProcChance)
|
||||||
SympatheticProcList.push_back(proc_spellid);
|
SympatheticProcList.push_back(proc_spellid);
|
||||||
SizeProcList = SympatheticProcList.size();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SizeProcList > 0)
|
/*Note: At present, ff designing custom AA to have a sympathetic proc effect, only use one focus
|
||||||
|
effect within the aa_effects data for each AA*[No live AA's use this effect to my knowledge]*/
|
||||||
|
if (aabonuses.FocusEffects[type]){
|
||||||
|
|
||||||
|
uint32 aa_AA = 0;
|
||||||
|
uint32 aa_value = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_PP_AA_ARRAY; i++)
|
||||||
{
|
{
|
||||||
uint8 random = MakeRandomInt(0, SizeProcList-1);
|
aa_AA = this->aa[i]->AA;
|
||||||
|
aa_value = this->aa[i]->value;
|
||||||
|
if (aa_AA < 1 || aa_value < 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (SympatheticProcList.size() > MAX_SYMPATHETIC)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
proc_spellid = CalcAAFocus(type, aa_AA, spell_id);
|
||||||
|
|
||||||
|
if (IsValidSpell(proc_spellid)){
|
||||||
|
|
||||||
|
ProcChance = GetSympatheticProcChances(spell_id, GetAABase1(aa_AA, 1));
|
||||||
|
|
||||||
|
if(MakeRandomFloat(0, 1) <= ProcChance)
|
||||||
|
SympatheticProcList.push_back(proc_spellid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SympatheticProcList.size() > 0)
|
||||||
|
{
|
||||||
|
uint8 random = MakeRandomInt(0, SympatheticProcList.size()-1);
|
||||||
int FinalSympatheticProc = SympatheticProcList[random];
|
int FinalSympatheticProc = SympatheticProcList[random];
|
||||||
SympatheticProcList.clear();
|
SympatheticProcList.clear();
|
||||||
return FinalSympatheticProc;
|
return FinalSympatheticProc;
|
||||||
@ -5674,17 +5657,31 @@ bool Mob::AffectedBySpellExcludingSlot(int slot, int effect)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Mob::GetSympatheticProcChances(float &ProcBonus, float &ProcChance, int32 cast_time, int16 ProcRateMod) {
|
float Mob::GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 ItemProcRate) {
|
||||||
|
|
||||||
ProcChance = 0;
|
float ProcChance = 0.0f;
|
||||||
|
int32 total_cast_time = 0;
|
||||||
|
float cast_time_mod = 0.0f;
|
||||||
|
ProcRateMod -= 100;
|
||||||
|
|
||||||
|
|
||||||
|
if (spells[spell_id].recast_time >= spells[spell_id].recovery_time)
|
||||||
|
total_cast_time = spells[spell_id].recast_time + spells[spell_id].cast_time;
|
||||||
|
else
|
||||||
|
total_cast_time = spells[spell_id].recovery_time + spells[spell_id].cast_time;
|
||||||
|
|
||||||
|
if (total_cast_time > 0 && total_cast_time <= 2500)
|
||||||
|
cast_time_mod = 0.25f;
|
||||||
|
else if (total_cast_time > 2500 && total_cast_time < 7000)
|
||||||
|
cast_time_mod = 0.167*((static_cast<float>(total_cast_time) - 1000.0f)/1000.0f);
|
||||||
|
else
|
||||||
|
cast_time_mod = static_cast<float>(total_cast_time) / 7000.0f;
|
||||||
|
|
||||||
|
ProcChance = (RuleR(Casting, AvgSpellProcsPerMinute)/100.0f) * (static_cast<float>(100.0f + ProcRateMod) / 10.0f)
|
||||||
|
* cast_time_mod * (static_cast<float>(100.0f + ItemProcRate)/100.0f);
|
||||||
|
|
||||||
if(cast_time > 0)
|
|
||||||
{
|
|
||||||
ProcChance = ((float)cast_time * RuleR(Casting, AvgSpellProcsPerMinute) / 60000.0f);
|
|
||||||
ProcChance = ProcChance * (float)(ProcRateMod/100);
|
|
||||||
}
|
|
||||||
return ProcChance;
|
return ProcChance;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mob::DoHPToManaCovert(uint16 mana_cost)
|
bool Mob::DoHPToManaCovert(uint16 mana_cost)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -5103,37 +5103,6 @@ bool Mob::RemoveDefensiveProc(uint16 spell_id, bool bAll)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mob::AddSkillProc(uint16 spell_id, uint16 iChance, uint16 base_spell_id)
|
|
||||||
{
|
|
||||||
if(spell_id == SPELL_UNKNOWN)
|
|
||||||
return(false);
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < MAX_PROCS; i++) {
|
|
||||||
if (SkillProcs[i].spellID == SPELL_UNKNOWN) {
|
|
||||||
SkillProcs[i].spellID = spell_id;
|
|
||||||
SkillProcs[i].chance = iChance;
|
|
||||||
SkillProcs[i].base_spellID = base_spell_id;
|
|
||||||
mlog(SPELLS__PROCS, "Added spell-granted skill proc spell %d with chance %d to slot %d", spell_id, iChance, i);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Mob::RemoveSkillProc(uint16 spell_id, bool bAll)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < MAX_PROCS; i++) {
|
|
||||||
if (bAll || SkillProcs[i].spellID == spell_id) {
|
|
||||||
SkillProcs[i].spellID = SPELL_UNKNOWN;
|
|
||||||
SkillProcs[i].chance = 0;
|
|
||||||
SkillProcs[i].base_spellID = SPELL_UNKNOWN;
|
|
||||||
mlog(SPELLS__PROCS, "Removed Skill proc %d from slot %d", spell_id, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Mob::AddRangedProc(uint16 spell_id, uint16 iChance, uint16 base_spell_id)
|
bool Mob::AddRangedProc(uint16 spell_id, uint16 iChance, uint16 base_spell_id)
|
||||||
{
|
{
|
||||||
if(spell_id == SPELL_UNKNOWN)
|
if(spell_id == SPELL_UNKNOWN)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user