Skip to content

added animation system#1948

Open
mariotee wants to merge 2 commits intomainfrom
feat/animation-system
Open

added animation system#1948
mariotee wants to merge 2 commits intomainfrom
feat/animation-system

Conversation

@mariotee
Copy link
Copy Markdown
Collaborator

feat: added defeat animation for units and upgrades

feat: added animation for shield breaks

chore: prep for animations prefs

feat: added healing animation

feat: added defeat animation for units and upgrades

feat: added animation for shield breaks

chore: prep for animations prefs

feat: added healing animation
@mariotee mariotee changed the title added animation system and damge animation effects added animation system Nov 24, 2025
@@ -0,0 +1,323 @@
import { AnimationType, type AnimationEvent } from './AnimationTypes';

// Animation duration constants (in milliseconds)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

These feel like details that should be managed on the client side

* Helper functions for constructing animation events.
* Provides static builder methods for common game actions.
*/
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'd prefer that we conform to the TS recommended practice here and use a collection of exported functions instead of a static class

/**
* Creates a damage animation event for a single target.
*
* @param targetId - Card UUID or base identifier (P1BASE/P2BASE)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is there a reason that we need to use the special PXBASE code instead of just sending the uuid for the base?

targetId: string,
amount: number,
sourceId?: string,
metadata?: Record<string, unknown>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We try very hard not to use untyped collections like these, even for configuration objects. Copilot should be able to declare explicit interface types really easily, so let's do that

public static damage(
targetId: string,
amount: number,
sourceId?: string,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What's the point of sourceId? Looks like we aren't really using it for anything

event.damageDealt = event.card.addDamage(eventDamageAmount, event.damageSource);

// Store animation data on the event to be processed in batch after the event window resolves
if (event.damageDealt > 0 && event.context?.game) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We can remove the event.context?.game check, if that isn't present we have much bigger problems lol

const isUpgrade = card.isUpgrade();

// Check if this is a shield token being defeated
if (card.isTokenUpgrade() && card.internalName === 'shield' && card.parentCard) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: we can do card.isShield() instead of checking internalName

shieldUuid: card.uuid, // The specific shield token being removed
};
} else {
// For units, include their upgrades so they can be animated
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We shouldn't do this here, separate defeat events will be automatically generated for each upgrade

const isUpgrade = card.isUpgrade();

// Check if this is a shield token being defeated
if (card.isTokenUpgrade() && card.internalName === 'shield' && card.parentCard) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not sure where to put this but, the animation sequencing looks a bit weird when a unit with a shield is defeat via an effect like Takedown. The shield defeat happens first, then the unit defeat. Imo they should both happen at the same time.

* Manages animation queue during game state updates on the server.
* Handles queuing, optimization, and serialization of animation events.
*/
export class ServerAnimationQueue {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We probably need to discuss how to reset this when an undo happens, probably just need to make sure it gets cleared out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants