Skip to content

Commit 21b1d7f

Browse files
authored
fix: last projectile spell casting (AscensionGameDev#2174)
* fix: last projectile spell casting: This commit addresses a bug where a spell with ammunition requirements would consume the last projectile without actually casting it out. It is also intended to provide additional chore changes and move player related code out to it's own overrides. Files changed: 1. Entity.cs - Moved projectile removal to player's CastSpell override method. Also moved the player's specific handlers for spell's cooldown to player's CastSpell override method. 2. Player.cs - Removed redundant and repeated code within the UseSpell method (ie. CastSpell(..) is already called within Entity's Update method when required) and added projectile removal and cooldown handlers within the CastSpell override method. * day's review: polymorphism: As suggested by review, applies polymorphism to handle the cooldown update. We now have a virtual method in the Entity class that is overridden in the Player class. This way, we avoid type checking and let the correct method be called based on the object's type. * chore: ConsumeSpellProjectile: refactors the player logic to consume spell projectiles as the ConsumeSpellProjectile method
1 parent 0886191 commit 21b1d7f

File tree

2 files changed

+64
-43
lines changed

2 files changed

+64
-43
lines changed

Intersect.Server.Core/Entities/Entity.cs

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,20 @@ public virtual void Update(long timeMs)
377377
}
378378
}
379379

380+
/// <summary>
381+
/// Updates the entity's spell cooldown for the specified <paramref name="spellBase"/>.
382+
/// <para> This method is called when a spell is casted by an entity. </para>
383+
/// </summary>
384+
public virtual void UpdateSpellCooldown(SpellBase spellBase, int spellSlot)
385+
{
386+
if (spellSlot < 0 || spellSlot >= Options.MaxPlayerSkills)
387+
{
388+
return;
389+
}
390+
391+
SpellCooldowns[Spells[spellSlot].SpellId] = Timing.Global.MillisecondsUtc + spellBase.CooldownDuration;
392+
}
393+
380394
/// <summary>
381395
/// Determines if this entity can move in the specified <paramref name="direction"/>.
382396
/// </summary>
@@ -2477,25 +2491,7 @@ public virtual void CastSpell(Guid spellId, int spellSlot = -1)
24772491
break;
24782492
}
24792493

2480-
if (spellSlot >= 0 && spellSlot < Options.MaxPlayerSkills)
2481-
{
2482-
// Player cooldown handling is done elsewhere!
2483-
if (this is Player player)
2484-
{
2485-
player.UpdateCooldown(spellBase);
2486-
2487-
// Trigger the global cooldown, if we're allowed to.
2488-
if (!spellBase.IgnoreGlobalCooldown)
2489-
{
2490-
player.UpdateGlobalCooldown();
2491-
}
2492-
}
2493-
else
2494-
{
2495-
SpellCooldowns[Spells[spellSlot].SpellId] =
2496-
Timing.Global.MillisecondsUtc + spellBase.CooldownDuration;
2497-
}
2498-
}
2494+
UpdateSpellCooldown(spellBase, spellSlot);
24992495
}
25002496
finally
25012497
{

Intersect.Server.Core/Entities/Player.cs

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,26 @@ public override void Update(long timeMs)
891891
}
892892
}
893893

894+
/// <summary>
895+
/// Updates the player's spell cooldown for the specified <paramref name="spellBase"/>.
896+
/// <para> This method is called when a spell is casted by a player. </para>
897+
/// </summary>
898+
public override void UpdateSpellCooldown(SpellBase spellBase, int spellSlot)
899+
{
900+
if (spellSlot < 0 || spellSlot >= Options.MaxPlayerSkills)
901+
{
902+
return;
903+
}
904+
905+
this.UpdateCooldown(spellBase);
906+
907+
// Trigger the global cooldown, if we're allowed to.
908+
if (!spellBase.IgnoreGlobalCooldown)
909+
{
910+
this.UpdateGlobalCooldown();
911+
}
912+
}
913+
894914
public void RemoveEvent(Guid id, bool sendLeave = true)
895915
{
896916
Event outInstance;
@@ -5419,7 +5439,6 @@ public void UseSpell(int spellSlot, Entity target)
54195439
target = this;
54205440
}
54215441

5422-
54235442
if (CastTime == 0)
54245443
{
54255444
CastTime = Timing.Global.Milliseconds + spell.CastDuration;
@@ -5439,36 +5458,16 @@ public void UseSpell(int spellSlot, Entity target)
54395458
// retargeting for auto self-cast on friendly when targeting hostile
54405459
CastTarget = target;
54415460

5442-
//Check if the caster has the right ammunition if a projectile
5443-
if (spell.SpellType == SpellType.CombatSpell &&
5444-
spell.Combat.TargetType == SpellTargetType.Projectile &&
5445-
spell.Combat.ProjectileId != Guid.Empty)
5446-
{
5447-
var projectileBase = spell.Combat.Projectile;
5448-
if (projectileBase != null && projectileBase.AmmoItemId != Guid.Empty)
5449-
{
5450-
TryTakeItem(projectileBase.AmmoItemId, projectileBase.AmmoRequired);
5451-
}
5452-
}
5453-
54545461
if (spell.CastAnimationId != Guid.Empty)
54555462
{
54565463
PacketSender.SendAnimationToProximity(
54575464
spell.CastAnimationId, 1, base.Id, MapId, 0, 0, Dir, MapInstanceId
54585465
); //Target Type 1 will be global entity
54595466
}
54605467

5461-
// Check if the player isn't casting a spell already.
5462-
if (!IsCasting)
5463-
{
5464-
// Player is not casting a spell, cast now!
5465-
CastTime = 0;
5466-
CastSpell(Spells[SpellCastSlot].SpellId, SpellCastSlot);
5467-
CastTarget = null;
5468-
}
5469-
else
5468+
//Tell the client we are channeling the spell
5469+
if (IsCasting)
54705470
{
5471-
//Tell the client we are channeling the spell
54725471
PacketSender.SendEntityCastTime(this, spellNum);
54735472
}
54745473
}
@@ -5484,7 +5483,7 @@ public void UseSpell(int spellSlot, Entity target)
54845483
public override void CastSpell(Guid spellId, int spellSlot = -1)
54855484
{
54865485
var spellBase = SpellBase.Get(spellId);
5487-
if (spellBase == null)
5486+
if (spellBase == null || spellSlot < 0 || spellSlot >= Options.MaxPlayerSkills)
54885487
{
54895488
return;
54905489
}
@@ -5506,6 +5505,32 @@ public override void CastSpell(Guid spellId, int spellSlot = -1)
55065505

55075506
break;
55085507
}
5508+
5509+
UpdateSpellCooldown(spellBase, spellSlot);
5510+
5511+
ConsumeSpellProjectile(spellBase);
5512+
}
5513+
5514+
/// <summary>
5515+
/// Checks if the caster has the required projectile(s) for the spell and tries to take them.
5516+
/// This method is used when a spell that requires projectile is casted.
5517+
/// If the spell has a valid ProjectileId, it retrieves the projectile and checks if it has a valid AmmoItemId.
5518+
/// If it does, it attempts to take the required amount of ammo from the player's inventory.
5519+
/// </summary>
5520+
/// <param name="spellBase">The spell that is being cast.</param>
5521+
private void ConsumeSpellProjectile(SpellBase spellBase)
5522+
{
5523+
// Check if the caster has the required projectile(s) for the spell and try to take it/them.
5524+
if (spellBase.SpellType == SpellType.CombatSpell &&
5525+
spellBase.Combat.TargetType == SpellTargetType.Projectile &&
5526+
spellBase.Combat.ProjectileId != Guid.Empty)
5527+
{
5528+
var projectileBase = spellBase.Combat.Projectile;
5529+
if (projectileBase != null && projectileBase.AmmoItemId != Guid.Empty)
5530+
{
5531+
TryTakeItem(projectileBase.AmmoItemId, projectileBase.AmmoRequired);
5532+
}
5533+
}
55095534
}
55105535

55115536
public bool TryGetEquipmentSlot(int equipmentSlot, out int inventorySlot)

0 commit comments

Comments
 (0)