diff --git a/zone/aggro.cpp b/zone/aggro.cpp index d23732df4..33221b63a 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -468,6 +468,12 @@ bool Mob::IsAttackAllowed(Mob *target, bool isSpellAttack) return false; } + if (target->GetSpecialAbility(IMMUNE_DAMAGE_CLIENT) && IsClient()) + return false; + + if (target->GetSpecialAbility(IMMUNE_DAMAGE_NPC) && IsNPC()) + return false; + // can't damage own pet (applies to everthing) Mob *target_owner = target->GetOwner(); Mob *our_owner = GetOwner(); diff --git a/zone/attack.cpp b/zone/attack.cpp index 2531024ee..3f614598a 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2667,6 +2667,12 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b if (IsFamiliar() || GetSpecialAbility(IMMUNE_AGGRO)) return; + if (GetSpecialAbility(IMMUNE_AGGRO_NPC) && other->IsNPC()) + return; + + if (GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && other->IsClient()) + return; + if (spell_id != SPELL_UNKNOWN && NoDetrimentalSpellAggro(spell_id)) return; @@ -2758,8 +2764,11 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b else { // cb:2007-08-17 // owner must get on list, but he's not actually gained any hate yet - if (!owner->GetSpecialAbility(IMMUNE_AGGRO)) - { + if ( + !owner->GetSpecialAbility(IMMUNE_AGGRO) && + !(this->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && owner->IsClient()) && + !(this->GetSpecialAbility(IMMUNE_AGGRO_NPC) && owner->IsNPC()) + ) { if (owner->IsClient() && !CheckAggro(owner)) owner->CastToClient()->AddAutoXTarget(this); hate_list.AddEntToHateList(owner, 0, 0, false, !iBuffTic); @@ -2768,12 +2777,24 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b } if (mypet && !mypet->IsHeld() && !mypet->IsPetStop()) { // I have a pet, add other to it - if (!mypet->IsFamiliar() && !mypet->GetSpecialAbility(IMMUNE_AGGRO)) + if ( + !mypet->IsFamiliar() && + !mypet->GetSpecialAbility(IMMUNE_AGGRO) && + !(mypet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && this->IsClient()) && + !(mypet->GetSpecialAbility(IMMUNE_AGGRO_NPC) && this->IsNPC()) + ) { mypet->hate_list.AddEntToHateList(other, 0, 0, bFrenzy); + } } else if (myowner) { // I am a pet, add other to owner if it's NPC/LD - if (myowner->IsAIControlled() && !myowner->GetSpecialAbility(IMMUNE_AGGRO)) + if ( + myowner->IsAIControlled() && + !myowner->GetSpecialAbility(IMMUNE_AGGRO) && + !(this->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && myowner->IsClient()) && + !(this->GetSpecialAbility(IMMUNE_AGGRO_NPC) && myowner->IsNPC()) + ) { myowner->hate_list.AddEntToHateList(other, 0, 0, bFrenzy); + } } if (other->GetTempPetCount()) @@ -3467,8 +3488,19 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const // pets that have GHold will never automatically add NPCs // pets that have Hold and no Focus will add NPCs if they're engaged // pets that have Hold and Focus will not add NPCs - if (pet && !pet->IsFamiliar() && !pet->GetSpecialAbility(IMMUNE_AGGRO) && !pet->IsEngaged() && attacker && attacker != this && !attacker->IsCorpse() && !pet->IsGHeld() && !attacker->IsTrap()) - { + if ( + pet && + !pet->IsFamiliar() && + !pet->GetSpecialAbility(IMMUNE_AGGRO) && + !pet->IsEngaged() && + attacker && + !(pet->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && attacker->IsClient()) && + !(pet->GetSpecialAbility(IMMUNE_AGGRO_NPC) && attacker->IsNPC()) && + attacker != this && + !attacker->IsCorpse() && + !pet->IsGHeld() && + !attacker->IsTrap() + ) { if (!pet->IsHeld()) { LogAggro("Sending pet [{}] into battle due to attack", pet->GetName()); if (IsClient()) { diff --git a/zone/client.cpp b/zone/client.cpp index 726d736e2..12105109f 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2433,13 +2433,17 @@ bool Client::CheckIncreaseSkill(EQ::skills::SkillType skillid, Mob *against_who, char buffer[24] = { 0 }; snprintf(buffer, 23, "%d %d", skillid, skillval); parse->EventPlayer(EVENT_USE_SKILL, this, buffer, 0); - if(against_who) - { - if(against_who->GetSpecialAbility(IMMUNE_AGGRO) || against_who->IsClient() || - GetLevelCon(against_who->GetLevel()) == CON_GRAY) - { + if (against_who) { + if ( + against_who->GetSpecialAbility(IMMUNE_AGGRO) || + against_who->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) || + against_who->IsClient() || + GetLevelCon(against_who->GetLevel()) == CON_GRAY + ) { //false by default - if( !mod_can_increase_skill(skillid, against_who) ) { return(false); } + if (!mod_can_increase_skill(skillid, against_who)) { + return false; + } } } diff --git a/zone/common.h b/zone/common.h index c05c6a95b..fd513bdde 100644 --- a/zone/common.h +++ b/zone/common.h @@ -195,7 +195,11 @@ enum { COUNTER_AVOID_DAMAGE = 44, PROX_AGGRO = 45, IMMUNE_RANGED_ATTACKS = 46, - MAX_SPECIAL_ATTACK = 47 + IMMUNE_DAMAGE_CLIENT = 47, + IMMUNE_DAMAGE_NPC = 48, + IMMUNE_AGGRO_CLIENT = 49, + IMMUNE_AGGRO_NPC = 50, + MAX_SPECIAL_ATTACK = 51 }; typedef enum { //fear states diff --git a/zone/entity.cpp b/zone/entity.cpp index b2b4b3706..f48b371ce 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -4135,8 +4135,13 @@ void EntityList::AddTempPetsToHateList(Mob *owner, Mob* other, bool bFrenzy) NPC* n = it->second; if (n->GetSwarmInfo()) { if (n->GetSwarmInfo()->owner_id == owner->GetID()) { - if (!n->GetSpecialAbility(IMMUNE_AGGRO)) + if ( + !n->GetSpecialAbility(IMMUNE_AGGRO) && + !(n->GetSpecialAbility(IMMUNE_AGGRO_CLIENT) && other->IsClient()) && + !(n->GetSpecialAbility(IMMUNE_AGGRO_NPC) && other->IsNPC()) + ) { n->hate_list.AddEntToHateList(other, 0, 0, bFrenzy); + } } } ++it; diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index f8379b82e..53d277b12 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -2708,7 +2708,11 @@ luabind::scope lua_register_special_abilities() { luabind::value("ignore_root_aggro_rules", static_cast(IGNORE_ROOT_AGGRO_RULES)), luabind::value("casting_resist_diff", static_cast(CASTING_RESIST_DIFF)), luabind::value("counter_avoid_damage", static_cast(COUNTER_AVOID_DAMAGE)), - luabind::value("immune_ranged_attacks", static_cast(IMMUNE_RANGED_ATTACKS)) + luabind::value("immune_ranged_attacks", static_cast(IMMUNE_RANGED_ATTACKS)), + luabind::value("immune_damage_client", static_cast(IMMUNE_DAMAGE_CLIENT)), + luabind::value("immune_damage_npc", static_cast(IMMUNE_DAMAGE_NPC)), + luabind::value("immune_aggro_client", static_cast(IMMUNE_AGGRO_CLIENT)), + luabind::value("immune_aggro_npc", static_cast(IMMUNE_AGGRO_NPC)) ]; } diff --git a/zone/mob.cpp b/zone/mob.cpp index d58ee4b54..825ae2538 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3132,6 +3132,12 @@ void Mob::ExecWeaponProc(const EQ::ItemInstance *inst, uint16 spell_id, Mob *on, return; } + if (on->GetSpecialAbility(IMMUNE_DAMAGE_CLIENT) && IsClient()) + return; + + if (on->GetSpecialAbility(IMMUNE_DAMAGE_NPC) && IsNPC()) + return; + if (IsNoCast()) return;