[Spells] AE Duration effect (Rains) will now work with Target Ring and PBAE spells. (#2000)

* done

* Update beacon.cpp

* [Spells] AE Duration effect (Rains) will now work with Target Ring and PBAE spells.

Mackals suggestions implemented.
This commit is contained in:
KayenEQ 2022-02-16 10:12:13 -05:00 committed by GitHub
parent 8ec80644ee
commit ba3c19ad0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 19 deletions

View File

@ -412,6 +412,7 @@ RULE_BOOL(Spells, DOTsScaleWithSpellDmg, false, "Allow SpellDmg stat to affect D
RULE_BOOL(Spells, HOTsScaleWithHealAmt, false, "Allow HealAmt stat to affect HoT spells")
RULE_BOOL(Spells, CompoundLifetapHeals, true, "True: Lifetap heals calculate damage bonuses and then heal bonuses. False: Lifetaps heal using the amount damaged to mob.")
RULE_BOOL(Spells, UseFadingMemoriesMaxLevel, false, "Enables to limit field in spell data to set the max level that over which an NPC will ignore fading memories effect and not lose aggro.")
RULE_BOOL(Spells, FixBeaconHeading, false, "Beacon spells use casters heading to fix live bug. False: Live like heading always 0.")
RULE_CATEGORY_END()
RULE_CATEGORY(Combat)

View File

@ -364,10 +364,19 @@ bool IsImprovedDamageSpell(uint16 spell_id)
bool IsAEDurationSpell(uint16 spell_id)
{
if (IsValidSpell(spell_id) &&
(spells[spell_id].target_type == ST_AETarget || spells[spell_id].target_type == ST_UndeadAE) &&
spells[spell_id].aoe_duration != 0)
/*
There are plenty of spells with aoe_duration set at single digit numbers, but these
do not act as duration effects.
*/
if (IsValidSpell(spell_id) &&
spells[spell_id].aoe_duration >= 2500 &&
( spells[spell_id].target_type == ST_AETarget ||
spells[spell_id].target_type == ST_UndeadAE ||
spells[spell_id].target_type == ST_AECaster ||
spells[spell_id].target_type == ST_Ring)
) {
return true;
}
return false;
}

View File

@ -52,10 +52,10 @@ extern Zone* zone;
// if lifetime is 0 this is a permanent beacon.. not sure if that'll be
// useful for anything
Beacon::Beacon(Mob *at_mob, int lifetime)
Beacon::Beacon(const glm::vec4 &in_pos, int lifetime)
:Mob
(
nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, at_mob->GetPosition(), 0, 0, 0,
nullptr, nullptr, 0, 0, 0, INVISIBLE_MAN, 0, BT_NoTarget, 0, 0, 0, 0, 0, in_pos, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, EQ::TintProfile(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false
),
remove_timer(lifetime),
@ -121,16 +121,19 @@ bool Beacon::Process()
void Beacon::AELocationSpell(Mob *caster, uint16 cast_spell_id, int16 resist_adjust)
{
if(!IsValidSpell(cast_spell_id) || !caster)
if (!IsValidSpell(cast_spell_id) || !caster) {
return;
}
caster_id = caster->GetID();
spell_id = cast_spell_id;
this->resist_adjust = resist_adjust;
spell_iterations = spells[spell_id].aoe_duration / 2500;
spell_iterations = spell_iterations < 1 ? 1 : spell_iterations; // at least 1
if (spells[spell_id].aoe_max_targets)
if (spells[spell_id].aoe_max_targets) {
max_targets = spells[spell_id].aoe_max_targets;
}
spell_timer.Start(2500);
spell_timer.Trigger();
}

View File

@ -30,7 +30,7 @@ struct ExtraAttackOptions;
class Beacon : public Mob
{
public:
Beacon(Mob *at_mob, int lifetime);
Beacon(const glm::vec4 &in_pos, int lifetime);
~Beacon();
//abstract virtual function implementations requird by base abstract class

View File

@ -704,13 +704,16 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp
}
if (check_on_casting){
if (spells[spell_id].target_type == ST_AEClientV1 ||
spells[spell_id].target_type == ST_AECaster ||
spells[spell_id].target_type == ST_Ring ||
spells[spell_id].target_type == ST_Beam) {
return true;
}
if (!spell_target) {
if (IsGroupSpell(spell_id) ||
spells[spell_id].target_type == ST_AEClientV1 ||
spells[spell_id].target_type == ST_AECaster ||
spells[spell_id].target_type == ST_Ring ||
spells[spell_id].target_type == ST_Beam) {
if (IsGroupSpell(spell_id)){
return true;
}
else if (spells[spell_id].target_type == ST_Self) {
@ -728,7 +731,6 @@ bool Mob::DoCastingChecksOnTarget(bool check_on_casting, int32 spell_id, Mob *sp
if (!spell_target){
return false;
}
/*
Spells that use caster_restriction field which requires specific conditions on target to be met before casting.
[Insufficient mana first]
@ -2278,12 +2280,25 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui
LogSpells("Spell [{}]: target type [{}], target [{}], AE center [{}]", spell_id, CastAction, spell_target?spell_target->GetName():"NONE", ae_center?ae_center->GetName():"NONE");
// if a spell has the AEDuration flag, it becomes an AE on target
// spell that's recast every 2500 msec for AEDuration msec. There are
// spells of all kinds of target types that do this, strangely enough
// TODO: finish this
// spell that's recast every 2500 msec for AEDuration msec.
if(IsAEDurationSpell(spell_id)) {
// the spells are AE target, but we aim them on a beacon
Mob *beacon_loc = spell_target ? spell_target : this;
glm::vec4 beacon_loc;
if (spells[spell_id].target_type == ST_Ring) {
beacon_loc = glm::vec4{ GetTargetRingX(),GetTargetRingY(), GetTargetRingZ(), GetHeading()};
}
else {
if (spell_target) {
beacon_loc = spell_target->GetPosition();
}
else {
beacon_loc = GetPosition();
}
}
// live has a bug where the heading is always north
if (!RuleB(Spells, FixBeaconHeading)) {
beacon_loc.w = 0.0f;
}
auto beacon = new Beacon(beacon_loc, spells[spell_id].aoe_duration);
entity_list.AddBeacon(beacon);
LogSpells("Spell [{}]: AE duration beacon created, entity id [{}]", spell_id, beacon->GetName());