Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: last projectile spell casting #2174

Merged
merged 3 commits into from
Mar 12, 2024
Merged

fix: last projectile spell casting #2174

merged 3 commits into from
Mar 12, 2024

Conversation

Arufonsu
Copy link
Contributor

Fixes #1683
Which reported 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 corresponding 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.

Bug:

2022-12-11.12-21-06.mp4

After the fix:

2024-03-09.19-08-42.mp4

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.
@Arufonsu Arufonsu added the bug Something isn't working label Mar 10, 2024
@Arufonsu Arufonsu requested review from a team March 10, 2024 05:00
@Arufonsu Arufonsu self-assigned this Mar 10, 2024
Comment on lines -5441 to -5452
//Check if the caster has the right ammunition if a projectile
if (spell.SpellType == SpellType.CombatSpell &&
spell.Combat.TargetType == SpellTargetType.Projectile &&
spell.Combat.ProjectileId != Guid.Empty)
{
var projectileBase = spell.Combat.Projectile;
if (projectileBase != null && projectileBase.AmmoItemId != Guid.Empty)
{
TryTakeItem(projectileBase.AmmoItemId, projectileBase.AmmoRequired);
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this out to the override void CastSpell because this was removing projectiles before we could even cast them out properly, which leads to the actual bug of not being able to properly use the last projectile

Comment on lines 5463 to 5470
// Player is not casting a spell, cast now!
CastTime = 0;
CastSpell(Spells[SpellCastSlot].SpellId, SpellCastSlot);
CastTarget = null;
}
else
{
//Tell the client we are channeling the spell
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explanation for removal: duplicated logic, we were already doing this here:

//Cast timers
if (CastTime != 0 && !IsCasting && SpellCastSlot < Spells.Count && SpellCastSlot >= 0)
{
CastTime = 0;
CastSpell(Spells[SpellCastSlot].SpellId, SpellCastSlot);
CastTarget = null;
}

Comment on lines -2482 to -2497
// Player cooldown handling is done elsewhere!
if (this is Player player)
{
player.UpdateCooldown(spellBase);

// Trigger the global cooldown, if we're allowed to.
if (!spellBase.IgnoreGlobalCooldown)
{
player.UpdateGlobalCooldown();
}
}
else
{
SpellCooldowns[Spells[spellSlot].SpellId] =
Timing.Global.MillisecondsUtc + spellBase.CooldownDuration;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Players have their own CastSpell override method so i moved these over

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To get rid of any type-checking (there's still a this is not Player in the changes), you should instead figure out what this logic is doing, make it a virtual Entity method, and create an overrided version in Player. Then, replace this chunk of code with a call to that method, and let inheritance take over.

Copy link
Contributor

@AlexVild AlexVild left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly seems fine, one comment, otherwise I just expect that you have tested this thoroughly and have ensured there are no new bugs created with some of the logic that was removed/moved.

Comment on lines -2482 to -2497
// Player cooldown handling is done elsewhere!
if (this is Player player)
{
player.UpdateCooldown(spellBase);

// Trigger the global cooldown, if we're allowed to.
if (!spellBase.IgnoreGlobalCooldown)
{
player.UpdateGlobalCooldown();
}
}
else
{
SpellCooldowns[Spells[spellSlot].SpellId] =
Timing.Global.MillisecondsUtc + spellBase.CooldownDuration;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To get rid of any type-checking (there's still a this is not Player in the changes), you should instead figure out what this logic is doing, make it a virtual Entity method, and create an overrided version in Player. Then, replace this chunk of code with a call to that method, and let inheritance take over.

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.
refactors the player logic to consume spell projectiles as the ConsumeSpellProjectile method
@Arufonsu Arufonsu requested review from AlexVild and a team March 10, 2024 16:27
@Arufonsu Arufonsu requested a review from a team March 10, 2024 16:35
@Arufonsu
Copy link
Contributor Author

just to make sure, some extra testing with NPCs, all good:

2024-03-11-23-15-02.mp4

@Arufonsu Arufonsu merged commit 21b1d7f into main Mar 12, 2024
1 check passed
Arufonsu added a commit that referenced this pull request Mar 14, 2024
Restored quick casting functionality for spell items, resolving my mess from PR #2174. Also ensured last projectile removal for quick casted spells is working as expected.
@Arufonsu Arufonsu mentioned this pull request Mar 14, 2024
Arufonsu added a commit that referenced this pull request Mar 16, 2024
Restored quick casting functionality for spell items, resolving my mess from PR #2174. Also ensured last projectile removal for quick casted spells is working as expected.
@Arufonsu Arufonsu added bug fix and removed bug Something isn't working labels May 23, 2024
@lodicolo lodicolo deleted the fix/1683 branch January 2, 2025 20:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

bug: spells do not correctly shoot their last ammunition
3 participants