using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using MontanaJohns.Core; using MontanaJohns.Items; using UnityEngine; namespace MontanaJohns.Actors { [RequireComponent(typeof(Rigidbody2D))] public abstract class Actor : MonoBehaviour { [SerializeField] protected float gravityScale = 1.5f; [SerializeField] protected Stats baseStats = Stats.DefaultBaseStats(); [SerializeField] protected Transform groundCheckPoint; protected Rigidbody2D _rigidBody; protected SpriteRenderer _renderer; protected Animator _animator; protected Transform _transform; protected Stats stats; protected Active activeItem; protected bool isGrappling; protected Vector2? grapplePoint = null; protected LayerMask groundLayers; protected Collection items; protected int jumpCount; protected Vector2 acceleration; public int health; protected virtual void Awake() { _rigidBody = GetComponent(); _transform = GetComponent(); _renderer = GetComponent(); _animator = GetComponent(); groundLayers = LayerMask.GetMask("Grapple", "Ground"); } protected virtual void Start() { _rigidBody.freezeRotation = true; _rigidBody.collisionDetectionMode = CollisionDetectionMode2D.Continuous; _rigidBody.gravityScale = gravityScale; items = new(); stats = baseStats; health = stats.maxHealth; jumpCount = stats.maxJumps; } protected virtual void FixedUpdate() { if (!_animator.GetBool("airborn") && !Physics2D.OverlapCircle(groundCheckPoint.position, 0.2f, groundLayers)) { _animator.SetTrigger("fall"); StartCoroutine(Falling()); } } public virtual void Move(float input) { var target = new Vector2(input * stats.speedMultiplier * 10, _rigidBody.velocity.y); _rigidBody.velocity = Vector2.SmoothDamp(_rigidBody.velocity, target, ref acceleration, .05f); _animator.SetBool("moving", Mathf.Abs(_rigidBody.velocity.x) > 1); if (_rigidBody.velocity.x < -0.001) { _renderer.flipX = true; for (int i = 0; i < transform.childCount; i++) { var rot = transform.GetChild(i).rotation; rot.y = 180f; transform.GetChild(i).rotation = rot; } } else if (_rigidBody.velocity.x > 0.001) { _renderer.flipX = false; for (int i = 0; i < transform.childCount; i++) { var rot = transform.GetChild(i).rotation; rot.y = 0f; transform.GetChild(i).rotation = rot; } } } public virtual void MoveY(float input) { var target = new Vector2(_rigidBody.velocity.x, input * stats.speedMultiplier * 10); _rigidBody.velocity = Vector2.SmoothDamp(_rigidBody.velocity, target, ref acceleration, .05f); } public virtual void Jump() { if(Physics2D.OverlapCircle(groundCheckPoint.position, 0.2f, groundLayers)) { jumpCount = stats.maxJumps; } if (jumpCount > 0) { jumpCount--; _rigidBody.AddForce(Vector2.up * stats.jumpForce); _animator.SetTrigger("jump"); _animator.SetBool("airborn", true); StartCoroutine(Falling()); } } public virtual void Use() { Vector2? grapplePoint; if (activeItem != null) { grapplePoint = activeItem.Use(); if (grapplePoint != null) isGrappling = true; else isGrappling = false; } else grapplePoint = null; this.grapplePoint = grapplePoint; } public virtual void AddItem(Item item) { items.Add(item); stats = baseStats + items.Select(i => i.stats).Sum(); } public virtual void TakeDamage(int damage) { health -= damage; } public virtual void Grapple(float xInput, float yInput, Vector2 grapplePoint) { Move(xInput); MoveY(yInput); } IEnumerator Falling() { _animator.SetBool("airborn", true); while (!Physics2D.OverlapCircle(groundCheckPoint.position, 0.2f, groundLayers)) { yield return new WaitForEndOfFrame(); } _animator.SetBool("airborn", false); yield break; } } }