Skip to content

Commit

Permalink
Add a short self interrupt duration on attack to NPCs
Browse files Browse the repository at this point in the history
* Prevents NPCs from starting casting immediately after a melee swing, which looked a little silly.
* The duration should be lower than their melee swing interval, otherwise they'll never cast after entering melee range. Currently set to half their attack speed.
  • Loading branch information
bm01 committed Jul 10, 2024
1 parent 6a82df1 commit 13b6685
Show file tree
Hide file tree
Showing 5 changed files with 11 additions and 24 deletions.
2 changes: 1 addition & 1 deletion GameServer/ECS-Components/Actions/AttackAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ protected virtual bool PrepareMeleeAttack()
if (_target is GamePlayer playerTarget && playerTarget.IsSitting)
_effectiveness *= 2;

_interruptDuration = mainHandAttackSpeed;
_interruptDuration = mainHandAttackSpeed; // Shouldn't this take left hand into account?
return true;
}

Expand Down
4 changes: 2 additions & 2 deletions GameServer/ECS-Components/AttackComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1649,8 +1649,8 @@ static void PrintDetailedCombatLog(GamePlayer player, double armorFactor, double
ad.Target.StartInterruptTimer(interruptDuration, ad.AttackType, ad.Attacker);

// If we're attacking via melee, start an interrupt timer on ourselves so we cannot swing + immediately cast.
if (ad.IsMeleeAttack && owner.StartInterruptTimerOnItselfOnMeleeAttack())
owner.StartInterruptTimer(owner.SpellInterruptDuration, ad.AttackType, ad.Attacker);
if (ad.IsMeleeAttack)
owner.StartInterruptTimer(owner.SelfInterruptDurationOnMeleeAttack, ad.AttackType, ad.Attacker);

owner.OnAttackEnemy(ad);
return ad;
Expand Down
6 changes: 1 addition & 5 deletions GameServer/gameobjects/GameLiving.cs
Original file line number Diff line number Diff line change
Expand Up @@ -980,15 +980,11 @@ public virtual void StartInterruptTimer(int duration, eAttackType attackType, Ga
}
}

public virtual bool StartInterruptTimerOnItselfOnMeleeAttack()
{
return true;
}

public GameObject LastInterrupter { get; private set; }
public long InterruptTime { get; private set; }
public long SelfInterruptTime { get; private set; }
public long InterruptRemainingDuration => !IsBeingInterrupted ? 0 : Math.Max(InterruptTime, SelfInterruptTime) - GameLoop.GameLoopTime;
public virtual int SelfInterruptDurationOnMeleeAttack => 3000;
public virtual bool IsBeingInterrupted => IsBeingInterruptedIgnoreSelfInterrupt || SelfInterruptTime > GameLoop.GameLoopTime;
public virtual bool IsBeingInterruptedIgnoreSelfInterrupt => InterruptTime > GameLoop.GameLoopTime;

Expand Down
12 changes: 6 additions & 6 deletions GameServer/gameobjects/GameNPC.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3036,8 +3036,11 @@ public override void StartInterruptTimer(int duration, AttackData.eAttackType at
// Increase substantially the base interrupt timer duration for non player controlled NPCs
// so that they don't start attacking immediately after the attacker's melee swing interval.
// It makes repositioning them easier without having to constantly attack them.
if (Brain is not IControlledBrain controlledBrain || controlledBrain.GetPlayerOwner() == null)
duration += 2500;
if (attacker != this)
{
if (Brain is not IControlledBrain controlledBrain || controlledBrain.GetPlayerOwner() == null)
duration += 2500;
}

base.StartInterruptTimer(duration, attackType, attacker);
}
Expand All @@ -3056,10 +3059,7 @@ protected override bool CheckRangedAttackInterrupt(GameLiving attacker, AttackDa
return interrupted;
}

public override bool StartInterruptTimerOnItselfOnMeleeAttack()
{
return false;
}
public override int SelfInterruptDurationOnMeleeAttack => AttackSpeed(ActiveWeapon) / 2;

/// <summary>
/// The time to wait before each mob respawn
Expand Down
11 changes: 1 addition & 10 deletions GameServer/gameobjects/Theurgist/TheurgistIcePet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,7 @@ public class TheurgistIcePet : TheurgistPet
public TheurgistIcePet(INpcTemplate npcTemplate) : base(npcTemplate) { }

// Ice pets stay permanently interrupted after their first one.
// This will break if these values are reset for any reason.
public override bool IsBeingInterrupted => InterruptTime > 0 || SelfInterruptTime > 0;
public override bool IsBeingInterrupted => InterruptTime > 0;
public override bool IsBeingInterruptedIgnoreSelfInterrupt => InterruptTime > 0;

// They are however able to cast after hitting someone in melee but not getting interrupted.
// So it's important that it doesn't add an interrupt timer on itself.
// TODO: Maybe find a way to differentiate both.
public override bool StartInterruptTimerOnItselfOnMeleeAttack()
{
return false;
}
}
}

0 comments on commit 13b6685

Please sign in to comment.