mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-17 03:08:26 +00:00
[Quest API] Add Client Spell Methods to Perl/Lua. (#2550)
* [Quest API] Add Client Spell Methods to Perl/Lua. # Perl - Add `$client->ApplySpell(spell_id)`. - Add `$client->ApplySpell(spell_id, duration)`. - Add `$client->ApplySpell(spell_id, duration, allow_pets)`. - Add `$client->ApplySpell(spell_id, duration, allow_pets, is_raid_group_only)`. - Add `$client->ApplySpell(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`. - Add `$client->ApplySpellGroup(spell_id)`. - Add `$client->ApplySpellGroup(spell_id, duration)`. - Add `$client->ApplySpellGroup(spell_id, duration, allow_pets)`. - Add `$client->ApplySpellGroup(spell_id, duration, allow_pets, is_raid_group_only)`. - Add `$client->ApplySpellGroup(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`. - Add `$client->ApplySpellRaid(spell_id)`. - Add `$client->ApplySpellRaid(spell_id, duration)`. - Add `$client->ApplySpellRaid(spell_id, duration, allow_pets)`. - Add `$client->ApplySpellRaid(spell_id, duration, allow_pets, is_raid_group_only)`. - Add `$client->ApplySpellRaid(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`. - Add `$client->SetSpellDuration(spell_id)`. - Add `$client->SetSpellDuration(spell_id, duration)`. - Add `$client->SetSpellDuration(spell_id, duration, allow_pets)`. - Add `$client->SetSpellDuration(spell_id, duration, allow_pets, is_raid_group_only)`. - Add `$client->SetSpellDuration(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`. - Add `$client->SetSpellDurationGroup(spell_id)`. - Add `$client->SetSpellDurationGroup(spell_id, duration)`. - Add `$client->SetSpellDurationGroup(spell_id, duration, allow_pets)`. - Add `$client->SetSpellDurationGroup(spell_id, duration, allow_pets, is_raid_group_only)`. - Add `$client->SetSpellDurationGroup(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`. - Add `$client->SetSpellDurationRaid(spell_id)`. - Add `$client->SetSpellDurationRaid(spell_id, duration)`. - Add `$client->SetSpellDurationRaid(spell_id, duration, allow_pets)`. - Add `$client->SetSpellDurationRaid(spell_id, duration, allow_pets, is_raid_group_only)`. - Add `$client->SetSpellDurationRaid(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`. # Lua - Add `client:ApplySpell(spell_id)`. - Add `client:ApplySpell(spell_id, duration)`. - Add `client:ApplySpell(spell_id, duration, allow_pets)`. - Add `client:ApplySpell(spell_id, duration, allow_pets, is_raid_group_only)`. - Add `client:ApplySpell(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`. - Add `client:ApplySpellGroup(spell_id)`. - Add `client:ApplySpellGroup(spell_id, duration)`. - Add `client:ApplySpellGroup(spell_id, duration, allow_pets)`. - Add `client:ApplySpellGroup(spell_id, duration, allow_pets, is_raid_group_only)`. - Add `client:ApplySpellGroup(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`. - Add `client:ApplySpellRaid(spell_id)`. - Add `client:ApplySpellRaid(spell_id, duration)`. - Add `client:ApplySpellRaid(spell_id, duration, allow_pets)`. - Add `client:ApplySpellRaid(spell_id, duration, allow_pets, is_raid_group_only)`. - Add `client:ApplySpellRaid(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`. - Add `client:SetSpellDuration(spell_id)`. - Add `client:SetSpellDuration(spell_id, duration)`. - Add `client:SetSpellDuration(spell_id, duration, allow_pets)`. - Add `client:SetSpellDuration(spell_id, duration, allow_pets, is_raid_group_only)`. - Add `client:SetSpellDuration(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`. - Add `client:SetSpellDurationGroup(spell_id)`. - Add `client:SetSpellDurationGroup(spell_id, duration)`. - Add `client:SetSpellDurationGroup(spell_id, duration, allow_pets)`. - Add `client:SetSpellDurationGroup(spell_id, duration, allow_pets, is_raid_group_only)`. - Add `client:SetSpellDurationGroup(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`. - Add `client:SetSpellDurationRaid(spell_id)`. - Add `client:SetSpellDurationRaid(spell_id, duration)`. - Add `client:SetSpellDurationRaid(spell_id, duration, allow_pets)`. - Add `client:SetSpellDurationRaid(spell_id, duration, allow_pets, is_raid_group_only)`. - Add `client:SetSpellDurationRaid(spell_id, duration, allow_pets, is_raid_group_only, allow_bots)`. # Notes - Allows operators extremely easy shorthands to cast on entire groups and raid groups and optionally include their bots and pets. - Default functionality for Raid is that it only casts on your group, set `is_raid_group_only` to `false` to cast on the entire Raid. * Cleanup. * Remove Raid parameter from Solo/Group methods.
This commit is contained in:
+318
-179
@@ -3274,7 +3274,7 @@ bool Mob::HasDiscBuff()
|
||||
// stacking problems, and -2 if this is not a buff
|
||||
// if caster is null, the buff will be added with the caster level being
|
||||
// the level of the mob
|
||||
int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_override, bool disable_buff_overrwrite)
|
||||
int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_override, bool disable_buff_overwrite)
|
||||
{
|
||||
int buffslot, ret, caster_level, emptyslot = -1;
|
||||
bool will_overwrite = false;
|
||||
@@ -3370,7 +3370,7 @@ int Mob::AddBuff(Mob *caster, uint16 spell_id, int duration, int32 level_overrid
|
||||
|
||||
// at this point we know that this buff will stick, but we have
|
||||
// to remove some other buffs already worn if will_overwrite is true
|
||||
if (will_overwrite && !disable_buff_overrwrite) {
|
||||
if (will_overwrite && !disable_buff_overwrite) {
|
||||
std::vector<int>::iterator cur, end;
|
||||
cur = overwrite_slots.begin();
|
||||
end = overwrite_slots.end();
|
||||
@@ -3515,14 +3515,21 @@ int Mob::CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite)
|
||||
// and if you don't want effects just return false. interrupting here will
|
||||
// break stuff
|
||||
//
|
||||
bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectiveness, bool use_resist_adjust, int16 resist_adjust,
|
||||
bool isproc, int level_override, int32 duration_override, bool disable_buff_overrwrite)
|
||||
{
|
||||
bool Mob::SpellOnTarget(
|
||||
uint16 spell_id,
|
||||
Mob *spelltar,
|
||||
int reflect_effectiveness,
|
||||
bool use_resist_adjust,
|
||||
int16 resist_adjust,
|
||||
bool isproc,
|
||||
int level_override,
|
||||
int duration_override,
|
||||
bool disable_buff_overwrite
|
||||
) {
|
||||
auto spellOwner = GetOwnerOrSelf();
|
||||
|
||||
// well we can't cast a spell on target without a target
|
||||
if(!spelltar)
|
||||
{
|
||||
if (!spelltar) {
|
||||
LogSpells("Unable to apply spell [{}] without a target", spell_id);
|
||||
Message(Chat::Red, "SOT: You must have a target for this spell.");
|
||||
return false;
|
||||
@@ -3532,11 +3539,17 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsValidSpell(spell_id))
|
||||
if (!IsValidSpell(spell_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(IsDetrimentalSpell(spell_id) && !IsAttackAllowed(spelltar, true) && !IsResurrectionEffects(spell_id) && !IsEffectInSpell(spell_id, SE_BindSight)) {
|
||||
if(!IsClient() || !CastToClient()->GetGM()) {
|
||||
if (
|
||||
IsDetrimentalSpell(spell_id) &&
|
||||
!IsAttackAllowed(spelltar, true) &&
|
||||
!IsResurrectionEffects(spell_id) &&
|
||||
!IsEffectInSpell(spell_id, SE_BindSight)
|
||||
) {
|
||||
if (!IsClient() || !CastToClient()->GetGM()) {
|
||||
MessageString(Chat::SpellFailure, SPELL_NO_HOLD);
|
||||
return false;
|
||||
}
|
||||
@@ -3548,12 +3561,28 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
// these target types skip pcnpc only check (according to dev quotes)
|
||||
// other AE spells this is redundant, oh well
|
||||
// 1 = PCs, 2 = NPCs
|
||||
if (spells[spell_id].pcnpc_only_flag && spells[spell_id].target_type != ST_AETargetHateList &&
|
||||
spells[spell_id].target_type != ST_HateList) {
|
||||
if (spells[spell_id].pcnpc_only_flag == 1 && !spelltar->IsClient() && !spelltar->IsMerc() && !spelltar->IsBot())
|
||||
if (
|
||||
spells[spell_id].pcnpc_only_flag &&
|
||||
spells[spell_id].target_type != ST_AETargetHateList &&
|
||||
spells[spell_id].target_type != ST_HateList
|
||||
) {
|
||||
if (
|
||||
spells[spell_id].pcnpc_only_flag == 1 &&
|
||||
!spelltar->IsClient() &&
|
||||
!spelltar->IsMerc() &&
|
||||
!spelltar->IsBot()
|
||||
) {
|
||||
return false;
|
||||
else if (spells[spell_id].pcnpc_only_flag == 2 && (spelltar->IsClient() || spelltar->IsMerc() || spelltar->IsBot()))
|
||||
} else if (
|
||||
spells[spell_id].pcnpc_only_flag == 2 &&
|
||||
(
|
||||
spelltar->IsClient() ||
|
||||
spelltar->IsMerc() ||
|
||||
spelltar->IsBot()
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 caster_level = level_override > 0 ? level_override : GetCasterLevel(spell_id);
|
||||
@@ -3570,12 +3599,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
Action_Struct* action = (Action_Struct*) action_packet->pBuffer;
|
||||
|
||||
// select source
|
||||
if(IsClient() && CastToClient()->GMHideMe())
|
||||
{
|
||||
if (IsClient() && CastToClient()->GMHideMe()) {
|
||||
action->source = spelltar->GetID();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
action->source = GetID();
|
||||
// this is a hack that makes detrimental buffs work client to client
|
||||
// TODO figure out how to do this right
|
||||
@@ -3591,12 +3617,9 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
}
|
||||
|
||||
// select target
|
||||
if (IsEffectInSpell(spell_id, SE_BindSight))
|
||||
{
|
||||
if (IsEffectInSpell(spell_id, SE_BindSight)) {
|
||||
action->target = GetID();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
action->target = spelltar->GetID();
|
||||
}
|
||||
|
||||
@@ -3609,10 +3632,13 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
action->instrument_mod = GetInstrumentMod(spell_id);
|
||||
action->effect_flag = 0;
|
||||
|
||||
if(spelltar != this && spelltar->IsClient()) // send to target
|
||||
if (spelltar != this && spelltar->IsClient()) { // send to target
|
||||
spelltar->CastToClient()->QueuePacket(action_packet);
|
||||
if(IsClient()) // send to caster
|
||||
}
|
||||
|
||||
if (IsClient()) { // send to caster
|
||||
CastToClient()->QueuePacket(action_packet);
|
||||
}
|
||||
|
||||
// send to people in the area, ignoring caster and target
|
||||
entity_list.QueueCloseClients(
|
||||
@@ -3626,12 +3652,13 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
);
|
||||
|
||||
/* Send the EVENT_CAST_ON event */
|
||||
std::string export_string = fmt::format(
|
||||
const auto export_string = fmt::format(
|
||||
"{} {} {}",
|
||||
spell_id,
|
||||
GetID(),
|
||||
caster_level
|
||||
);
|
||||
|
||||
if (spelltar->IsNPC()) {
|
||||
parse->EventNPC(EVENT_CAST_ON, spelltar->CastToNPC(), this, export_string, 0);
|
||||
} else if (spelltar->IsClient()) {
|
||||
@@ -3642,7 +3669,6 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
mod_spell_cast(spell_id, spelltar, reflect_effectiveness, use_resist_adjust, resist_adjust, isproc);
|
||||
|
||||
if (!DoCastingChecksOnTarget(false, spell_id, spelltar)) {
|
||||
@@ -3654,25 +3680,37 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
if (RuleB(Spells, EnableBlockedBuffs)) {
|
||||
// We return true here since the caster's client should act like normal
|
||||
if (spelltar->IsBlockedBuff(spell_id)) {
|
||||
LogSpells("Spell [{}] not applied to [{}] as it is a Blocked Buff",
|
||||
spell_id, spelltar->GetName());
|
||||
LogSpells(
|
||||
"Spell [{}] not applied to [{}] as it is a Blocked Buff",
|
||||
spell_id,
|
||||
spelltar->GetName()
|
||||
);
|
||||
safe_delete(action_packet);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (spelltar->IsPet() && spelltar->GetOwner() &&
|
||||
spelltar->GetOwner()->IsBlockedPetBuff(spell_id)) {
|
||||
LogSpells("Spell [{}] not applied to [{}] ([{}]'s pet) as it is a Pet Blocked Buff",
|
||||
spell_id, spelltar->GetName(), spelltar->GetOwner()->GetName());
|
||||
if (
|
||||
spelltar->IsPet() &&
|
||||
spelltar->GetOwner() &&
|
||||
spelltar->GetOwner()->IsBlockedPetBuff(spell_id)
|
||||
) {
|
||||
LogSpells(
|
||||
"Spell [{}] not applied to [{}] ([{}]'s pet) as it is a Pet Blocked Buff",
|
||||
spell_id,
|
||||
spelltar->GetName(),
|
||||
spelltar->GetOwner()->GetName()
|
||||
);
|
||||
safe_delete(action_packet);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// invuln mobs can't be affected by any spells, good or bad, except if caster is casting a spell with 'cast_not_standing' on self.
|
||||
if ((spelltar->GetInvul() && !spelltar->DivineAura()) ||
|
||||
if (
|
||||
(spelltar->GetInvul() && !spelltar->DivineAura()) ||
|
||||
(spelltar != this && spelltar->DivineAura()) ||
|
||||
(spelltar == this && spelltar->DivineAura() && !IgnoreCastingRestriction(spell_id))) {
|
||||
(spelltar == this && spelltar->DivineAura() && !IgnoreCastingRestriction(spell_id))
|
||||
) {
|
||||
LogSpells("Casting spell [{}] on [{}] aborted: they are invulnerable", spell_id, spelltar->GetName());
|
||||
safe_delete(action_packet);
|
||||
return false;
|
||||
@@ -3680,7 +3718,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
|
||||
//cannot hurt untargetable mobs
|
||||
bodyType bt = spelltar->GetBodyType();
|
||||
if(bt == BT_NoTarget || bt == BT_NoTarget2) {
|
||||
if (bt == BT_NoTarget || bt == BT_NoTarget2) {
|
||||
if (RuleB(Pets, UnTargetableSwarmPet)) {
|
||||
if (spelltar->IsNPC()) {
|
||||
if (!spelltar->CastToNPC()->GetSwarmOwner()) {
|
||||
@@ -3704,30 +3742,24 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
// Not sure if all 3 should be stacking
|
||||
//This is not live like behavior (~Kayen confirmed 2/2/22)
|
||||
if (!RuleB(Spells, AllowDoubleInvis)) {
|
||||
if (IsEffectInSpell(spell_id, SE_Invisibility))
|
||||
{
|
||||
if (spelltar->invisible)
|
||||
{
|
||||
if (IsEffectInSpell(spell_id, SE_Invisibility)) {
|
||||
if (spelltar->invisible) {
|
||||
spelltar->MessageString(Chat::SpellFailure, ALREADY_INVIS, GetCleanName());
|
||||
safe_delete(action_packet);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsEffectInSpell(spell_id, SE_InvisVsUndead))
|
||||
{
|
||||
if (spelltar->invisible_undead)
|
||||
{
|
||||
if (IsEffectInSpell(spell_id, SE_InvisVsUndead)) {
|
||||
if (spelltar->invisible_undead) {
|
||||
spelltar->MessageString(Chat::SpellFailure, ALREADY_INVIS, GetCleanName());
|
||||
safe_delete(action_packet);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsEffectInSpell(spell_id, SE_InvisVsAnimals))
|
||||
{
|
||||
if (spelltar->invisible_animals)
|
||||
{
|
||||
if (IsEffectInSpell(spell_id, SE_InvisVsAnimals)) {
|
||||
if (spelltar->invisible_animals) {
|
||||
spelltar->MessageString(Chat::SpellFailure, ALREADY_INVIS, GetCleanName());
|
||||
safe_delete(action_packet);
|
||||
return false;
|
||||
@@ -3735,15 +3767,10 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
}
|
||||
}
|
||||
|
||||
if(!(IsClient() && CastToClient()->GetGM()) && !IsHarmonySpell(spell_id)) // GMs can cast on anything
|
||||
{
|
||||
if (!(IsClient() && CastToClient()->GetGM()) && !IsHarmonySpell(spell_id)) {// GMs can cast on anything
|
||||
// Beneficial spells check
|
||||
if(IsBeneficialSpell(spell_id))
|
||||
{
|
||||
if(IsClient() && //let NPCs do beneficial spells on anybody if they want, should be the job of the AI, not the spell code to prevent this from going wrong
|
||||
spelltar != this)
|
||||
{
|
||||
|
||||
if (IsBeneficialSpell(spell_id)) {
|
||||
if (IsClient() && spelltar != this) {//let NPCs do beneficial spells on anybody if they want, should be the job of the AI, not the spell code to prevent this from going wrong
|
||||
Client* pClient = nullptr;
|
||||
Raid* pRaid = nullptr;
|
||||
Group* pBasicGroup = nullptr;
|
||||
@@ -3765,60 +3792,89 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
pClient = CastToClient();
|
||||
pRaid = entity_list.GetRaidByClient(pClient);
|
||||
pBasicGroup = entity_list.GetGroupByMob(this);
|
||||
if(pRaid)
|
||||
if (pRaid) {
|
||||
nGroup = pRaid->GetGroup(pClient) + 1;
|
||||
}
|
||||
|
||||
//Target client pointers
|
||||
if(spelltar->IsClient())
|
||||
{
|
||||
if (spelltar->IsClient()) {
|
||||
pClientTarget = spelltar->CastToClient();
|
||||
pRaidTarget = entity_list.GetRaidByClient(pClientTarget);
|
||||
pBasicGroupTarget = entity_list.GetGroupByMob(spelltar);
|
||||
if(pRaidTarget)
|
||||
if (pRaidTarget) {
|
||||
nGroupTarget = pRaidTarget->GetGroup(pClientTarget) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(spelltar->IsPet())
|
||||
{
|
||||
if (spelltar->IsPet()) {
|
||||
Mob *owner = spelltar->GetOwner();
|
||||
if(owner->IsClient())
|
||||
{
|
||||
if (owner->IsClient()) {
|
||||
pClientTargetPet = owner->CastToClient();
|
||||
pRaidTargetPet = entity_list.GetRaidByClient(pClientTargetPet);
|
||||
pBasicGroupTargetPet = entity_list.GetGroupByMob(owner);
|
||||
if(pRaidTargetPet)
|
||||
if (pRaidTargetPet) {
|
||||
nGroupTargetPet = pRaidTargetPet->GetGroup(pClientTargetPet) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if((!IsAllianceSpellLine(spell_id) && !IsBeneficialAllowed(spelltar)) ||
|
||||
if (
|
||||
(!IsAllianceSpellLine(spell_id) && !IsBeneficialAllowed(spelltar)) ||
|
||||
(IsGroupOnlySpell(spell_id) &&
|
||||
!(
|
||||
(pBasicGroup && ((pBasicGroup == pBasicGroupTarget) || (pBasicGroup == pBasicGroupTargetPet))) || //Basic Group
|
||||
|
||||
((nGroup != cnWTF) && ((nGroup == nGroupTarget) || (nGroup == nGroupTargetPet))) || //Raid group
|
||||
|
||||
(spelltar == GetPet()) //should be able to cast grp spells on self and pet despite grped status.
|
||||
(
|
||||
pBasicGroup &&
|
||||
(
|
||||
pBasicGroup == pBasicGroupTarget ||
|
||||
pBasicGroup == pBasicGroupTargetPet
|
||||
)
|
||||
) || //Basic Group
|
||||
(
|
||||
nGroup != cnWTF &&
|
||||
(
|
||||
nGroup == nGroupTarget ||
|
||||
nGroup == nGroupTargetPet
|
||||
)
|
||||
) || //Raid group
|
||||
spelltar == GetPet() //should be able to cast grp spells on self and pet despite grped status.
|
||||
)
|
||||
)
|
||||
)
|
||||
{
|
||||
if(spells[spell_id].target_type == ST_AEBard) {
|
||||
) {
|
||||
if (spells[spell_id].target_type == ST_AEBard) {
|
||||
//if it was a beneficial AE bard song don't spam the window that it would not hold
|
||||
LogSpells("Beneficial ae bard song [{}] can't take hold [{}] -> [{}], IBA? [{}]", spell_id, GetName(), spelltar->GetName(), IsBeneficialAllowed(spelltar));
|
||||
LogSpells(
|
||||
"Beneficial ae bard song [{}] can't take hold [{}] -> [{}], IBA? [{}]",
|
||||
spell_id,
|
||||
GetName(),
|
||||
spelltar->GetName(),
|
||||
IsBeneficialAllowed(spelltar)
|
||||
);
|
||||
} else {
|
||||
LogSpells("Beneficial spell [{}] can't take hold [{}] -> [{}], IBA? [{}]", spell_id, GetName(), spelltar->GetName(), IsBeneficialAllowed(spelltar));
|
||||
LogSpells(
|
||||
"Beneficial spell [{}] can't take hold [{}] -> [{}], IBA? [{}]",
|
||||
spell_id,
|
||||
GetName(),
|
||||
spelltar->GetName(),
|
||||
IsBeneficialAllowed(spelltar)
|
||||
);
|
||||
MessageString(Chat::SpellFailure, SPELL_NO_HOLD);
|
||||
}
|
||||
safe_delete(action_packet);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( !IsAttackAllowed(spelltar, true) && !IsResurrectionEffects(spell_id) && !IsEffectInSpell(spell_id, SE_BindSight)) // Detrimental spells - PVP check
|
||||
{
|
||||
LogSpells("Detrimental spell [{}] can't take hold [{}] -> [{}]", spell_id, GetName(), spelltar->GetName());
|
||||
} else if (
|
||||
!IsAttackAllowed(spelltar, true) &&
|
||||
!IsResurrectionEffects(spell_id) &&
|
||||
!IsEffectInSpell(spell_id, SE_BindSight)
|
||||
) { // Detrimental spells - PVP check
|
||||
LogSpells(
|
||||
"Detrimental spell [{}] can't take hold [{}] -> [{}]",
|
||||
spell_id,
|
||||
GetName(),
|
||||
spelltar->GetName()
|
||||
);
|
||||
spelltar->MessageString(Chat::SpellFailure, YOU_ARE_PROTECTED, GetCleanName());
|
||||
safe_delete(action_packet);
|
||||
return false;
|
||||
@@ -3829,8 +3885,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
// but we need to check special cases and resists
|
||||
|
||||
// check immunities
|
||||
if(spelltar->IsImmuneToSpell(spell_id, this))
|
||||
{
|
||||
if (spelltar->IsImmuneToSpell(spell_id, this)) {
|
||||
//the above call does the message to the client if needed
|
||||
LogSpells("Spell [{}] can't take hold due to immunity [{}] -> [{}]", spell_id, GetName(), spelltar->GetName());
|
||||
safe_delete(action_packet);
|
||||
@@ -3838,30 +3893,36 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
}
|
||||
|
||||
//check for AE_Undead
|
||||
if(spells[spell_id].target_type == ST_UndeadAE){
|
||||
if(spelltar->GetBodyType() != BT_SummonedUndead &&
|
||||
if (spells[spell_id].target_type == ST_UndeadAE){
|
||||
if (
|
||||
spelltar->GetBodyType() != BT_SummonedUndead &&
|
||||
spelltar->GetBodyType() != BT_Undead &&
|
||||
spelltar->GetBodyType() != BT_Vampire)
|
||||
{
|
||||
spelltar->GetBodyType() != BT_Vampire
|
||||
) {
|
||||
safe_delete(action_packet);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Need this to account for special AOE cases.
|
||||
if (IsClient() && IsHarmonySpell(spell_id) && !HarmonySpellLevelCheck(spell_id, spelltar)) {
|
||||
if (
|
||||
IsClient() &&
|
||||
IsHarmonySpell(spell_id) &&
|
||||
!HarmonySpellLevelCheck(spell_id, spelltar)
|
||||
) {
|
||||
MessageString(Chat::SpellFailure, SPELL_NO_EFFECT);
|
||||
safe_delete(action_packet);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Block next spell effect should be used up first(since its blocking the next spell)
|
||||
if(CanBlockSpell()) {
|
||||
if (CanBlockSpell()) {
|
||||
int buff_count = GetMaxTotalSlots();
|
||||
int focus = 0;
|
||||
for (int b=0; b < buff_count; b++) {
|
||||
if(IsEffectInSpell(buffs[b].spellid, SE_BlockNextSpellFocus)) {
|
||||
for (int b = 0; b < buff_count; b++) {
|
||||
if (IsEffectInSpell(buffs[b].spellid, SE_BlockNextSpellFocus)) {
|
||||
focus = CalcFocusEffect(focusBlockNextSpell, buffs[b].spellid, spell_id);
|
||||
if(focus) {
|
||||
if (focus) {
|
||||
CheckNumHitsRemaining(NumHit::MatchingSpells, b);
|
||||
MessageString(Chat::SpellFailure, SPELL_WOULDNT_HOLD);
|
||||
safe_delete(action_packet);
|
||||
@@ -3883,67 +3944,83 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
|
||||
There are a few spells in database that are not detrimental that have Reflectable field set, however from testing, they do not actually reflect.
|
||||
*/
|
||||
if(spells[spell_id].reflectable && !reflect_effectiveness && spelltar && this != spelltar && IsDetrimentalSpell(spell_id) &&
|
||||
(spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE] || spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE] || spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE])) {
|
||||
if (
|
||||
spells[spell_id].reflectable &&
|
||||
!reflect_effectiveness &&
|
||||
spelltar &&
|
||||
this != spelltar &&
|
||||
IsDetrimentalSpell(spell_id) &&
|
||||
(
|
||||
spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE] ||
|
||||
spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE] ||
|
||||
spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE]
|
||||
)
|
||||
) {
|
||||
bool can_spell_reflect = false;
|
||||
switch(RuleI(Spells, ReflectType))
|
||||
{
|
||||
case REFLECT_DISABLED:
|
||||
break;
|
||||
|
||||
case REFLECT_SINGLE_TARGET_SPELLS_ONLY:
|
||||
{
|
||||
if(spells[spell_id].target_type == ST_Target) {
|
||||
for(int y = 0; y < 16; y++) {
|
||||
switch (RuleI(Spells, ReflectType)) {
|
||||
case REFLECT_SINGLE_TARGET_SPELLS_ONLY: {
|
||||
if (spells[spell_id].target_type == ST_Target) {
|
||||
for (int y = 0; y < 16; y++) {
|
||||
if (spells[spell_id].classes[y] < 255) {
|
||||
can_spell_reflect = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case REFLECT_ALL_PLAYER_SPELLS:
|
||||
{
|
||||
for(int y = 0; y < 16; y++) {
|
||||
case REFLECT_ALL_PLAYER_SPELLS: {
|
||||
for (int y = 0; y < 16; y++) {
|
||||
if (spells[spell_id].classes[y] < 255) {
|
||||
can_spell_reflect = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case RELFECT_ALL_SINGLE_TARGET_SPELLS:
|
||||
{
|
||||
case RELFECT_ALL_SINGLE_TARGET_SPELLS: {
|
||||
if (spells[spell_id].target_type == ST_Target) {
|
||||
can_spell_reflect = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case REFLECT_ALL_SPELLS: //This is live like behavior
|
||||
case REFLECT_ALL_SPELLS: {//This is live like behavior
|
||||
can_spell_reflect = true;
|
||||
|
||||
default:
|
||||
}
|
||||
case REFLECT_DISABLED:
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (can_spell_reflect) {
|
||||
|
||||
if (can_spell_reflect) {
|
||||
int reflect_resist_adjust = 0;
|
||||
int reflect_effectiveness_mod = 0; //Need value of 100 to do baseline unmodified damage.
|
||||
|
||||
if (spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE] && zone->random.Roll(spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE])) {
|
||||
reflect_resist_adjust = spelltar->spellbonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD];
|
||||
reflect_effectiveness_mod = spelltar->spellbonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] ? spelltar->spellbonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] : 100;
|
||||
}
|
||||
else if (spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE] && zone->random.Roll(spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE])) {
|
||||
if (
|
||||
spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE] &&
|
||||
zone->random.Roll(spelltar->spellbonuses.reflect[SBIndex::REFLECT_CHANCE])
|
||||
) {
|
||||
reflect_resist_adjust = spelltar->spellbonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD];
|
||||
reflect_effectiveness_mod = spelltar->spellbonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS]
|
||||
? spelltar->spellbonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] : 100;
|
||||
} else if (
|
||||
spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE] &&
|
||||
zone->random.Roll(spelltar->aabonuses.reflect[SBIndex::REFLECT_CHANCE])
|
||||
) {
|
||||
reflect_effectiveness_mod = 100;
|
||||
reflect_resist_adjust = spelltar->aabonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD];
|
||||
}
|
||||
else if (spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE] && zone->random.Roll(spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE])) {
|
||||
reflect_resist_adjust = spelltar->itembonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD];
|
||||
reflect_effectiveness_mod = spelltar->itembonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] ? spelltar->itembonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] : 100;
|
||||
} else if (
|
||||
spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE] &&
|
||||
zone->random.Roll(spelltar->itembonuses.reflect[SBIndex::REFLECT_CHANCE])
|
||||
) {
|
||||
reflect_resist_adjust = spelltar->itembonuses.reflect[SBIndex::REFLECT_RESISTANCE_MOD];
|
||||
reflect_effectiveness_mod = spelltar->itembonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS]
|
||||
? spelltar->itembonuses.reflect[SBIndex::REFLECT_DMG_EFFECTIVENESS] : 100;
|
||||
}
|
||||
|
||||
if (reflect_effectiveness_mod) {
|
||||
|
||||
if (RuleB(Spells, ReflectMessagesClose)) {
|
||||
entity_list.MessageCloseString(
|
||||
this, /* Sender */
|
||||
@@ -3954,8 +4031,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
GetCleanName(), /* Message 1 */
|
||||
spelltar->GetCleanName() /* Message 2 */
|
||||
);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
MessageString(Chat::Spells, SPELL_REFLECT, GetCleanName(), spelltar->GetCleanName());
|
||||
}
|
||||
|
||||
@@ -3971,40 +4047,62 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
// resist check - every spell can be resisted, beneficial or not
|
||||
// add: ok this isn't true, eqlive's spell data is fucked up, buffs are
|
||||
// not all unresistable, so changing this to only check certain spells
|
||||
if(IsResistableSpell(spell_id))
|
||||
{
|
||||
if (IsResistableSpell(spell_id)) {
|
||||
spelltar->BreakInvisibleSpells(); //Any detrimental spell cast on you will drop invisible (can be AOE, non damage ect).
|
||||
|
||||
if (IsCharmSpell(spell_id) || IsMezSpell(spell_id) || IsFearSpell(spell_id))
|
||||
spell_effectiveness = spelltar->ResistSpell(spells[spell_id].resist_type, spell_id, this, use_resist_adjust, resist_adjust, true, false, false, level_override);
|
||||
else
|
||||
spell_effectiveness = spelltar->ResistSpell(spells[spell_id].resist_type, spell_id, this, use_resist_adjust, resist_adjust, false, false, false, level_override);
|
||||
if (
|
||||
IsCharmSpell(spell_id) ||
|
||||
IsMezSpell(spell_id) ||
|
||||
IsFearSpell(spell_id)
|
||||
) {
|
||||
spell_effectiveness = spelltar->ResistSpell(
|
||||
spells[spell_id].resist_type,
|
||||
spell_id,
|
||||
this,
|
||||
use_resist_adjust,
|
||||
resist_adjust,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
level_override
|
||||
);
|
||||
} else {
|
||||
spell_effectiveness = spelltar->ResistSpell(
|
||||
spells[spell_id].resist_type,
|
||||
spell_id,
|
||||
this,
|
||||
use_resist_adjust,
|
||||
resist_adjust,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
level_override
|
||||
);
|
||||
}
|
||||
|
||||
if(spell_effectiveness < 100)
|
||||
{
|
||||
if(spell_effectiveness == 0 || !IsPartialCapableSpell(spell_id) )
|
||||
{
|
||||
if (spell_effectiveness < 100) {
|
||||
if (spell_effectiveness == 0 || !IsPartialCapableSpell(spell_id)) {
|
||||
LogSpells("Spell [{}] was completely resisted by [{}]", spell_id, spelltar->GetName());
|
||||
|
||||
if (spells[spell_id].resist_type == RESIST_PHYSICAL){
|
||||
MessageString(Chat::SpellFailure, PHYSICAL_RESIST_FAIL,spells[spell_id].name);
|
||||
spelltar->MessageString(Chat::SpellFailure, YOU_RESIST, spells[spell_id].name);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
MessageString(Chat::SpellFailure, TARGET_RESISTED, spells[spell_id].name);
|
||||
spelltar->MessageString(Chat::SpellFailure, YOU_RESIST, spells[spell_id].name);
|
||||
}
|
||||
|
||||
if (spelltar->IsAIControlled()) {
|
||||
int32 aggro = CheckAggroAmount(spell_id, spelltar);
|
||||
auto aggro = CheckAggroAmount(spell_id, spelltar);
|
||||
if (aggro > 0) {
|
||||
if (!IsHarmonySpell(spell_id))
|
||||
if (!IsHarmonySpell(spell_id)) {
|
||||
spelltar->AddToHateList(this, aggro);
|
||||
else if (!spelltar->PassCharismaCheck(this, spell_id))
|
||||
} else if (!spelltar->PassCharismaCheck(this, spell_id)) {
|
||||
spelltar->AddToHateList(this, aggro);
|
||||
}
|
||||
} else {
|
||||
int newhate = spelltar->GetHateAmount(this) + aggro;
|
||||
spelltar->SetHateAmountOnEnt(this, std::max(1, newhate));
|
||||
int64 newhate = spelltar->GetHateAmount(this) + aggro;
|
||||
spelltar->SetHateAmountOnEnt(this, std::max(static_cast<int64>(1), newhate));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4025,33 +4123,41 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
spelltar->CastToClient()->BreakSneakWhenCastOn(this, false);
|
||||
spelltar->CastToClient()->BreakFeignDeathWhenCastOn(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
spell_effectiveness = 100;
|
||||
}
|
||||
|
||||
if (spells[spell_id].feedbackable && (spelltar->spellbonuses.SpellDamageShield || spelltar->itembonuses.SpellDamageShield || spelltar->aabonuses.SpellDamageShield)) {
|
||||
if (
|
||||
spells[spell_id].feedbackable &&
|
||||
(
|
||||
spelltar->spellbonuses.SpellDamageShield ||
|
||||
spelltar->itembonuses.SpellDamageShield ||
|
||||
spelltar->aabonuses.SpellDamageShield
|
||||
)
|
||||
) {
|
||||
spelltar->DamageShield(this, true);
|
||||
}
|
||||
|
||||
if (spelltar->IsAIControlled() && IsDetrimentalSpell(spell_id) && !IsHarmonySpell(spell_id)) {
|
||||
int32 aggro_amount = CheckAggroAmount(spell_id, spelltar, isproc);
|
||||
if (
|
||||
spelltar->IsAIControlled() &&
|
||||
IsDetrimentalSpell(spell_id) &&
|
||||
!IsHarmonySpell(spell_id)
|
||||
) {
|
||||
auto aggro_amount = CheckAggroAmount(spell_id, spelltar, isproc);
|
||||
LogSpells("Spell [{}] cast on [{}] generated [{}] hate", spell_id,
|
||||
spelltar->GetName(), aggro_amount);
|
||||
if (aggro_amount > 0) {
|
||||
spelltar->AddToHateList(this, aggro_amount);
|
||||
} else {
|
||||
int32 newhate = spelltar->GetHateAmount(this) + aggro_amount;
|
||||
spelltar->SetHateAmountOnEnt(this, std::max(newhate, 1));
|
||||
int64 newhate = spelltar->GetHateAmount(this) + aggro_amount;
|
||||
spelltar->SetHateAmountOnEnt(this, std::max(newhate, static_cast<int64>(1)));
|
||||
}
|
||||
} else if (IsBeneficialSpell(spell_id) && !IsSummonPCSpell(spell_id)) {
|
||||
if (this != spelltar && IsClient()){
|
||||
if (spelltar->IsClient()) {
|
||||
CastToClient()->UpdateRestTimer(spelltar->CastToClient()->GetRestTimer());
|
||||
}
|
||||
else if (spelltar->IsPet()) {
|
||||
Mob *owner = spelltar->GetOwner();
|
||||
} else if (spelltar->IsPet()) {
|
||||
auto* owner = spelltar->GetOwner();
|
||||
if (owner && owner != this && owner->IsClient()) {
|
||||
CastToClient()->UpdateRestTimer(owner->CastToClient()->GetRestTimer());
|
||||
}
|
||||
@@ -4059,23 +4165,39 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
}
|
||||
|
||||
entity_list.AddHealAggro(
|
||||
spelltar, this,
|
||||
CheckHealAggroAmount(spell_id, spelltar, (spelltar->GetMaxHP() - spelltar->GetHP())));
|
||||
spelltar,
|
||||
this,
|
||||
CheckHealAggroAmount(
|
||||
spell_id,
|
||||
spelltar,
|
||||
(spelltar->GetMaxHP() - spelltar->GetHP())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// make sure spelltar is high enough level for the buff
|
||||
if(RuleB(Spells, BuffLevelRestrictions) && !spelltar->CheckSpellLevelRestriction(spell_id))
|
||||
{
|
||||
if (RuleB(Spells, BuffLevelRestrictions) && !spelltar->CheckSpellLevelRestriction(spell_id)) {
|
||||
LogSpells("Spell [{}] failed: recipient did not meet the level restrictions", spell_id);
|
||||
if(!IsBardSong(spell_id))
|
||||
if (!IsBardSong(spell_id)) {
|
||||
MessageString(Chat::SpellFailure, SPELL_TOO_POWERFUL);
|
||||
}
|
||||
|
||||
safe_delete(action_packet);
|
||||
return false;
|
||||
}
|
||||
|
||||
// cause the effects to the target
|
||||
if(!spelltar->SpellEffect(this, spell_id, spell_effectiveness, level_override, reflect_effectiveness, duration_override, disable_buff_overrwrite))
|
||||
{
|
||||
if (
|
||||
!spelltar->SpellEffect(
|
||||
this,
|
||||
spell_id,
|
||||
spell_effectiveness,
|
||||
level_override,
|
||||
reflect_effectiveness,
|
||||
duration_override,
|
||||
disable_buff_overwrite
|
||||
)
|
||||
) {
|
||||
// if SpellEffect returned false there's a problem applying the
|
||||
// spell. It's most likely a buff that can't stack.
|
||||
LogSpells("Spell [{}] could not apply its effects [{}] -> [{}]\n", spell_id, GetName(), spelltar->GetName());
|
||||
@@ -4087,18 +4209,27 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
}
|
||||
|
||||
//Check SE_Fc_Cast_Spell_On_Land SPA 481 on target, if hit by this spell and Conditions are Met then target will cast the specified spell.
|
||||
if (spelltar)
|
||||
if (spelltar) {
|
||||
spelltar->CastSpellOnLand(this, spell_id);
|
||||
}
|
||||
|
||||
if (IsValidSpell(spells[spell_id].recourse_link) && spells[spell_id].recourse_link != spell_id)
|
||||
SpellFinished(spells[spell_id].recourse_link, this, CastingSlot::Item, 0, -1, spells[spells[spell_id].recourse_link].resist_difficulty);
|
||||
if (IsValidSpell(spells[spell_id].recourse_link) && spells[spell_id].recourse_link != spell_id) {
|
||||
SpellFinished(
|
||||
spells[spell_id].recourse_link,
|
||||
this,
|
||||
CastingSlot::Item,
|
||||
0,
|
||||
-1,
|
||||
spells[spells[spell_id].recourse_link].resist_difficulty
|
||||
);
|
||||
}
|
||||
|
||||
if (IsDetrimentalSpell(spell_id)) {
|
||||
|
||||
CheckNumHitsRemaining(NumHit::OutgoingSpells);
|
||||
|
||||
if (spelltar)
|
||||
if (spelltar) {
|
||||
spelltar->CheckNumHitsRemaining(NumHit::IncomingSpells);
|
||||
}
|
||||
}
|
||||
|
||||
// send the action packet again now that the spell is successful
|
||||
@@ -4107,16 +4238,17 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
// the complete sequence is 2 actions and 1 damage message
|
||||
action->effect_flag = 0x04; // this is a success flag
|
||||
|
||||
if(spells[spell_id].push_back != 0.0f || spells[spell_id].push_up != 0.0f)
|
||||
{
|
||||
if (spelltar->IsClient())
|
||||
{
|
||||
if (!IsBuffSpell(spell_id))
|
||||
{
|
||||
if (spells[spell_id].push_back != 0.0f || spells[spell_id].push_up != 0.0f) {
|
||||
if (spelltar->IsClient()) {
|
||||
if (!IsBuffSpell(spell_id)) {
|
||||
spelltar->CastToClient()->cheat_manager.SetExemptStatus(KnockBack, true);
|
||||
}
|
||||
}
|
||||
else if (RuleB(Spells, NPCSpellPush) && !spelltar->IsPermaRooted() && !spelltar->IsPseudoRooted() && spelltar->ForcedMovement == 0) {
|
||||
} else if (
|
||||
RuleB(Spells, NPCSpellPush) &&
|
||||
!spelltar->IsPermaRooted() &&
|
||||
!spelltar->IsPseudoRooted() &&
|
||||
!spelltar->ForcedMovement
|
||||
) {
|
||||
spelltar->m_Delta.x += action->force * g_Math.FastSin(action->hit_heading);
|
||||
spelltar->m_Delta.y += action->force * g_Math.FastCos(action->hit_heading);
|
||||
spelltar->m_Delta.z += action->hit_pitch;
|
||||
@@ -4124,17 +4256,18 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
}
|
||||
}
|
||||
|
||||
if (spelltar->IsClient() && IsEffectInSpell(spell_id, SE_ShadowStep))
|
||||
{
|
||||
if (spelltar->IsClient() && IsEffectInSpell(spell_id, SE_ShadowStep)) {
|
||||
spelltar->CastToClient()->cheat_manager.SetExemptStatus(ShadowStep, true);
|
||||
}
|
||||
|
||||
if(!IsEffectInSpell(spell_id, SE_BindAffinity))
|
||||
{
|
||||
if(spelltar != this && spelltar->IsClient()) // send to target
|
||||
if (!IsEffectInSpell(spell_id, SE_BindAffinity)) {
|
||||
if (spelltar != this && spelltar->IsClient()) {// send to target
|
||||
spelltar->CastToClient()->QueuePacket(action_packet);
|
||||
if(IsClient()) // send to caster
|
||||
}
|
||||
|
||||
if(IsClient()) {// send to caster
|
||||
CastToClient()->QueuePacket(action_packet);
|
||||
}
|
||||
}
|
||||
|
||||
message_packet = new EQApplicationPacket(OP_Damage, sizeof(CombatDamage_Struct));
|
||||
@@ -4148,7 +4281,12 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
cd->hit_pitch = action->hit_pitch;
|
||||
cd->damage = 0;
|
||||
|
||||
if (!IsLifetapSpell(spell_id) && !IsEffectInSpell(spell_id, SE_BindAffinity) && !IsAENukeSpell(spell_id) && !IsDamageSpell(spell_id)) {
|
||||
if (
|
||||
!IsLifetapSpell(spell_id) &&
|
||||
!IsEffectInSpell(spell_id, SE_BindAffinity) &&
|
||||
!IsAENukeSpell(spell_id) &&
|
||||
!IsDamageSpell(spell_id)
|
||||
) {
|
||||
entity_list.QueueCloseClients(
|
||||
spelltar, /* Sender */
|
||||
message_packet, /* Packet */
|
||||
@@ -4159,6 +4297,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, int reflect_effectivenes
|
||||
(spellOwner->IsClient() ? FilterPCSpells : FilterNPCSpells) /* Message Filter Type: (8 or 9) */
|
||||
);
|
||||
}
|
||||
|
||||
safe_delete(action_packet);
|
||||
safe_delete(message_packet);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user