mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-13 14:41:28 +00:00
[Rule] Add rule for NPC Level Based Buff Restrictions. (#2708)
* [Rule] Add rule for NPC Level Based Buff Restrictions. * Erroneous whitespace * Change prefix on log message * Added log message when GM casts
This commit is contained in:
parent
9e3539295b
commit
ca0ae3cb98
@ -426,6 +426,7 @@ RULE_BOOL(Spells, BuffsFadeOnDeath, true, "Disable to keep buffs from fading on
|
|||||||
RULE_BOOL(Spells, IllusionsAlwaysPersist, false, "Allows Illusions to persist beyond death and zoning always.")
|
RULE_BOOL(Spells, IllusionsAlwaysPersist, false, "Allows Illusions to persist beyond death and zoning always.")
|
||||||
RULE_BOOL(Spells, UseItemCastMessage, false, "Enable to use the \"item begins to glow\" messages when casting from an item.")
|
RULE_BOOL(Spells, UseItemCastMessage, false, "Enable to use the \"item begins to glow\" messages when casting from an item.")
|
||||||
RULE_BOOL(Spells, TargetsTargetRequiresCombatRange, true, "Disable to remove combat range requirement from Target's Target Spell Target Type")
|
RULE_BOOL(Spells, TargetsTargetRequiresCombatRange, true, "Disable to remove combat range requirement from Target's Target Spell Target Type")
|
||||||
|
RULE_BOOL(Spells, NPCBuffLevelRestrictions, false, "Impose BuffLevelRestrictions on NPCs if true")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Combat)
|
RULE_CATEGORY(Combat)
|
||||||
|
|||||||
@ -560,7 +560,6 @@ public:
|
|||||||
inline virtual int32 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath + 11; }
|
inline virtual int32 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath + 11; }
|
||||||
|
|
||||||
virtual bool CheckFizzle(uint16 spell_id);
|
virtual bool CheckFizzle(uint16 spell_id);
|
||||||
virtual bool CheckSpellLevelRestriction(uint16 spell_id);
|
|
||||||
virtual int GetCurrentBuffSlots() const;
|
virtual int GetCurrentBuffSlots() const;
|
||||||
virtual int GetCurrentSongSlots() const;
|
virtual int GetCurrentSongSlots() const;
|
||||||
virtual int GetCurrentDiscSlots() const { return 1; }
|
virtual int GetCurrentDiscSlots() const { return 1; }
|
||||||
|
|||||||
@ -373,7 +373,7 @@ public:
|
|||||||
bool DoCastingChecksZoneRestrictions(bool check_on_casting, int32 spell_id);
|
bool DoCastingChecksZoneRestrictions(bool check_on_casting, int32 spell_id);
|
||||||
bool DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob* spell_target);
|
bool DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob* spell_target);
|
||||||
virtual bool CheckFizzle(uint16 spell_id);
|
virtual bool CheckFizzle(uint16 spell_id);
|
||||||
virtual bool CheckSpellLevelRestriction(uint16 spell_id);
|
virtual bool CheckSpellLevelRestriction(Mob *caster, uint16 spell_id);
|
||||||
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);
|
virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster);
|
||||||
virtual float GetAOERange(uint16 spell_id);
|
virtual float GetAOERange(uint16 spell_id);
|
||||||
void InterruptSpell(uint16 spellid = SPELL_UNKNOWN);
|
void InterruptSpell(uint16 spellid = SPELL_UNKNOWN);
|
||||||
|
|||||||
@ -735,11 +735,11 @@ bool ZoneDatabase::GetBasePetItems(int32 equipmentset, uint32 *items) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Pet::CheckSpellLevelRestriction(uint16 spell_id)
|
bool Pet::CheckSpellLevelRestriction(Mob *caster, uint16 spell_id)
|
||||||
{
|
{
|
||||||
auto owner = GetOwner();
|
auto owner = GetOwner();
|
||||||
if (owner)
|
if (owner)
|
||||||
return owner->CheckSpellLevelRestriction(spell_id);
|
return owner->CheckSpellLevelRestriction(caster, spell_id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ struct NPCType;
|
|||||||
class Pet : public NPC {
|
class Pet : public NPC {
|
||||||
public:
|
public:
|
||||||
Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 power);
|
Pet(NPCType *type_data, Mob *owner, PetType type, uint16 spell_id, int16 power);
|
||||||
virtual bool CheckSpellLevelRestriction(uint16 spell_id);
|
virtual bool CheckSpellLevelRestriction(Mob *caster, uint16 spell_id);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -734,10 +734,6 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
bool ignore_on_casting = false;
|
bool ignore_on_casting = false;
|
||||||
bool ignore_if_npc_or_gm = false;
|
|
||||||
if (!IsClient() || (IsClient() && CastToClient()->GetGM())) {
|
|
||||||
ignore_if_npc_or_gm = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (check_on_casting) {
|
if (check_on_casting) {
|
||||||
if (spells[spell_id].target_type == ST_AEClientV1 ||
|
if (spells[spell_id].target_type == ST_AEClientV1 ||
|
||||||
@ -803,15 +799,9 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp
|
|||||||
/*
|
/*
|
||||||
Prevent buffs from being cast on targets who don't meet level restriction
|
Prevent buffs from being cast on targets who don't meet level restriction
|
||||||
*/
|
*/
|
||||||
if (!ignore_if_npc_or_gm && RuleB(Spells, BuffLevelRestrictions)) {
|
|
||||||
// casting_spell_targetid is guaranteed to be what we went, check for ST_Self for now should work though
|
if (!spell_target->CheckSpellLevelRestriction(this, spell_id)) {
|
||||||
if (spells[spell_id].target_type != ST_Self && !spell_target->CheckSpellLevelRestriction(spell_id)) {
|
return false;
|
||||||
LogSpells("Spell [{}] failed: recipient did not meet the level restrictions", spell_id);
|
|
||||||
if (!IsBardSong(spell_id)) {
|
|
||||||
MessageString(Chat::SpellFailure, SPELL_TOO_POWERFUL);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Prevents buff from being cast based on tareget ing PC OR NPC (1 = PCs, 2 = NPCs)
|
Prevents buff from being cast based on tareget ing PC OR NPC (1 = PCs, 2 = NPCs)
|
||||||
@ -1161,6 +1151,9 @@ void Mob::InterruptSpell(uint16 message, uint16 color, uint16 spellid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LogSpells("Interrupt: casting_spell_id [{}] casting_spell_slot [{}]",
|
||||||
|
casting_spell_id, (int) casting_spell_slot);
|
||||||
|
|
||||||
if(casting_spell_id && IsNPC()) {
|
if(casting_spell_id && IsNPC()) {
|
||||||
CastToNPC()->AI_Event_SpellCastFinished(false, static_cast<uint16>(casting_spell_slot));
|
CastToNPC()->AI_Event_SpellCastFinished(false, static_cast<uint16>(casting_spell_slot));
|
||||||
}
|
}
|
||||||
@ -1275,8 +1268,9 @@ void Mob::StopCastSpell(int32 spell_id, bool send_spellbar_enable)
|
|||||||
-AA that fail at CastSpell because they never get timer set.
|
-AA that fail at CastSpell because they never get timer set.
|
||||||
-Instant cast items that fail at CastSpell because they never get timer set.
|
-Instant cast items that fail at CastSpell because they never get timer set.
|
||||||
*/
|
*/
|
||||||
if (casting_spell_id && IsNPC()) {
|
// Often called before spell_id and slot are set. For NPCs always update AI
|
||||||
CastToNPC()->AI_Event_SpellCastFinished(false, static_cast<uint16>(casting_spell_slot));
|
if (IsNPC()) {
|
||||||
|
CastToNPC()->AI_Event_SpellCastFinished(false, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (send_spellbar_enable) {
|
if (send_spellbar_enable) {
|
||||||
@ -3210,29 +3204,60 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2,
|
|||||||
// spells 1-50: no restrictons
|
// spells 1-50: no restrictons
|
||||||
// 51-65: SpellLevel/2+15
|
// 51-65: SpellLevel/2+15
|
||||||
// 66+ Group Spells 62, Single Target 61
|
// 66+ Group Spells 62, Single Target 61
|
||||||
bool Mob::CheckSpellLevelRestriction(uint16 spell_id)
|
bool Mob::CheckSpellLevelRestriction(Mob *caster, uint16 spell_id)
|
||||||
{
|
{
|
||||||
return true;
|
bool check_for_restrictions = false;
|
||||||
}
|
bool can_cast = true;
|
||||||
|
|
||||||
bool Client::CheckSpellLevelRestriction(uint16 spell_id)
|
if (!caster) {
|
||||||
{
|
LogSpells("[CheckSpellLevelRestriction] No caster");
|
||||||
int SpellLevel = GetMinLevel(spell_id);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Only check for beneficial buffs
|
if (caster->IsClient() && caster->CastToClient()->GetGM()) {
|
||||||
if (IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) {
|
LogSpells("[CheckSpellLevelRestriction] GM casting - No restrictions");
|
||||||
if (SpellLevel > 65) {
|
return true;
|
||||||
if (IsGroupSpell(spell_id) && GetLevel() < 62)
|
}
|
||||||
return false;
|
|
||||||
else if (GetLevel() < 61)
|
// NON GM clients might be restricted by rule setting
|
||||||
return false;
|
if (caster->IsClient()) {
|
||||||
} else if (SpellLevel > 50) { // 51-65
|
if (RuleB(Spells, BuffLevelRestrictions)) {
|
||||||
if (GetLevel() < (SpellLevel / 2 + 15))
|
check_for_restrictions = true;
|
||||||
return false;
|
}
|
||||||
|
}
|
||||||
|
// NPCS might be restricted by rule setting
|
||||||
|
else if (RuleB(Spells, NPCBuffLevelRestrictions)) {
|
||||||
|
check_for_restrictions = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check_for_restrictions) {
|
||||||
|
int spell_level = GetMinLevel(spell_id);
|
||||||
|
|
||||||
|
// Only check for beneficial buffs
|
||||||
|
if (IsBuffSpell(spell_id) && IsBeneficialSpell(spell_id)) {
|
||||||
|
if (spell_level > 65) {
|
||||||
|
if (IsGroupSpell(spell_id) && GetLevel() < 62) {
|
||||||
|
can_cast = false;
|
||||||
|
}
|
||||||
|
else if (GetLevel() < 61) {
|
||||||
|
can_cast = false;
|
||||||
|
}
|
||||||
|
} else if (spell_level > 50) { // 51-65
|
||||||
|
if (GetLevel() < (spell_level / 2 + 15)) {
|
||||||
|
can_cast = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
if (!can_cast) {
|
||||||
|
LogSpells("Spell [{}] failed: recipient did not meet the level restrictions", spell_id);
|
||||||
|
if (!IsBardSong(spell_id)) {
|
||||||
|
caster->MessageString(Chat::SpellFailure, SPELL_TOO_POWERFUL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return can_cast;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 Mob::GetFirstBuffSlot(bool disc, bool song)
|
uint32 Mob::GetFirstBuffSlot(bool disc, bool song)
|
||||||
@ -4175,12 +4200,7 @@ bool Mob::SpellOnTarget(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// make sure spelltar is high enough level for the buff
|
// make sure spelltar is high enough level for the buff
|
||||||
if (RuleB(Spells, BuffLevelRestrictions) && !spelltar->CheckSpellLevelRestriction(spell_id)) {
|
if (!spelltar->CheckSpellLevelRestriction(this, spell_id)) {
|
||||||
LogSpells("Spell [{}] failed: recipient did not meet the level restrictions", spell_id);
|
|
||||||
if (!IsBardSong(spell_id)) {
|
|
||||||
MessageString(Chat::SpellFailure, SPELL_TOO_POWERFUL);
|
|
||||||
}
|
|
||||||
|
|
||||||
safe_delete(action_packet);
|
safe_delete(action_packet);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user