#action / item system

1 messages · Page 1 of 1 (latest)

cold flicker
#

this is kind of how I set it up:

public abstract class Action
{
    public string Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }

    public Action(string id, string name, string description)
    {
        Id = id;
        Name = name;
        Description = description;
    }

    public override string ToString()
    {
        return $"{Name} ({Id})";
    }

    public override bool Equals(object obj)
    {
        if (obj is Action)
        {
            Action action = (Action)obj;
            return Id == action.Id;
        }
        return false;
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }

    public abstract bool CanExecute(Character character);

    // Start the action
    public abstract void Execute(Character character);

    // Update loop for the character 
    public abstract void Update(Character character);

    // Fixed update loop for the character - for physics, etc
    public abstract void FixedUpdate(Character character);

    public abstract void Cleanup(Character character);

}```
#
public abstract class AnimationAction : Action
{
    protected AnimationAction(string id, string name, string description) : base(id, name, description)
    {
    }

    // Trigger the effect of the action - mainly for animations
    public abstract void TriggerEffect(Character character);

}```
#
using UnityEngine;

public class SwingHammer : AnimationAction
{
    public SwingHammer() : base(System.Guid.NewGuid().ToString(), "SwingHammer", "Swing Hammer")
    {

    }


    public SwingHammer(string id, string name, string description) : base(id, name, description)
    {

    }


    public override bool CanExecute(Character character)
    {
        return true;
    }

    public override void Execute(Character character)
    {
        // Play animation
        character.PlayAnimation("hammering");
    }

    public override void Update(Character character)
    {
        return;
    }

    public override void FixedUpdate(Character character)
    {
        return;
    }

    public override void TriggerEffect(Character character)
    {
        // Create hitbox in front of character on certain frame
        Debug.Log("Hammer damage would apply now");

        // Check if hitbox collides with enemy

        // If so deal damage

    }

    public override void Cleanup(Character character)
    {
        character.PlayAnimation("idle");
    }
}```
#

whereas a different action like "MoveTo" would be

#
using Pathfinding;
using UnityEngine;

public class MoveTo : Action
{
    // A* pathfinding
    public Vector2 target;
    protected float nextWaypointDistance = .2f;
    protected Path path;
    protected int currentWaypoint = 0;

    public Seeker seeker;

    public MoveTo(string id, string name, string description) : base(id, name, description)
    {

    }

    public MoveTo(Vector2 target) : base(System.Guid.NewGuid().ToString(), "MoveTo", "Move to a target location")
    {
        this.target = target;
    }

    public override bool CanExecute(Character character)
    {
        // TODO: Check if the target is reachable
        return true;
    }

    public override void Execute(Character character)
    {
        seeker = character.GetComponent<Seeker>();
        seeker.StartPath(character.transform.position, target, OnPathComplete);
    }


    public override void Update(Character character)
    {
        return;
    }

    public override void FixedUpdate(Character character)
    {
        if (currentWaypoint >= path.vectorPath.Count)
        {
            character.FinishAction();
            return;
        }

        // Direction to the next waypoint
        Vector2 direction = ((Vector2)path.vectorPath[currentWaypoint] - character.rb.position).normalized;

        if (direction != Vector2.zero)
        {
            // Flip the sprite if necessary
            character.Flip(direction.x);

            // Play the walking animation
            character.PlayAnimation("walking");
        }

        // Move the character
        character.rb.MovePosition(character.rb.position + direction * character.Speed * Time.fixedDeltaTime);

        // Distance to the next waypoint
        float distance = Vector2.Distance(character.rb.position, path.vectorPath[currentWaypoint]);

        if (distance < nextWaypointDistance)
        {
            currentWaypoint++;
        }
    }

    public void OnPathComplete(Path p)
    {
        if (!p.error)
        {
            path = p;
        }
    }

    public override void Cleanup(Character character)
    {
        return;
    }
}```
#

and so then my characters have a queue of these actions that they'll do

#

the goal here is to have the player and NPCs have the same structure

#

which is a core part of my game

wide pulsar
#

Why would you want a queue of actions?

cold flicker
#

for players, yeah it's not as useful, but again am trying to make it so players and NPCs have action to the same actions

#

so I don't have to rewrite custom logic

#

so if a player can mine a rock so can an NPC