Capacity + Health and Mana bars

This commit is contained in:
Crizomb 2025-01-21 12:59:14 +01:00
parent b21d392ff6
commit 7d3b4ced0e
41 changed files with 1739 additions and 32 deletions

View file

@ -16,6 +16,8 @@ public abstract class AbstractUnit : MonoBehaviour
public abstract void TakeDamage(float damage);
public abstract void Heal(float heal);
public abstract void AddArmor(float armor);
public abstract void RemoveArmor(float armor);
void Awake()
{

View file

@ -44,12 +44,13 @@ public class AttackHandler : MonoBehaviour
if (targetUnit.IsTeamA == _minecraftUnit.IsTeamA) continue;
targetUnit.TakeDamage(damage);
_minecraftUnit.Capacity.AddMana(damage);
hasHit = true;
Vector3 knockbackVector = knockbackHorizontalForce * (target.transform.position - transform.position).normalized
+ knockbackVerticalForce * Vector3.up;
// Knockback logic specific to MinecraftUnit (can't force other team to do our weird impl)
// logic specific if targetUnit is MinecraftUnit
if (targetUnit is MinecraftUnit)
{
MinecraftUnit minecraftTarget = (MinecraftUnit)targetUnit;

View file

@ -17,6 +17,7 @@ public class Arrow : ProjectileHandler
minecraftUnit.StartCoroutine(minecraftUnit.MovementHandler.TakeImpulse(knockback));
}
unit.TakeDamage(baseDamage);
_minecraftUnitOrigin.Capacity.AddMana(baseDamage);
}
Destroy(this.gameObject);

View file

@ -26,7 +26,7 @@ public class AttackProjectile : AttackHandler
Vector3 diffVector = Vector3.ProjectOnPlane(targetUnit.transform.position - spawnPos.position, Vector3.up);
Vector3 launchVectorNormalized = (localLaunchVector.x * diffVector.normalized + localLaunchVector.y * Vector3.up).normalized;
projectileHandler.LaunchProjectile(launchVectorNormalized * arrowBaseSpeed, _minecraftUnit.IsTeamA);
projectileHandler.LaunchProjectile(launchVectorNormalized * arrowBaseSpeed, _minecraftUnit.IsTeamA, _minecraftUnit);
return true;
}

View file

@ -22,7 +22,7 @@ public class HealthPotion : ProjectileHandler
if (targetUnit.IsTeamA != FromTeamA) continue;
targetUnit.Heal(healthAdd);
_minecraftUnitOrigin.Capacity.AddMana(healthAdd);
}
CoroutineManager.Instance.StartCoroutine(ExplodeVisual());
Destroy(gameObject);

View file

@ -10,6 +10,7 @@ public class ProjectileHandler : MonoBehaviour
[SerializeField] protected float _lifeSpan = 8.0f;
protected Rigidbody RigidBody;
protected bool FromTeamA;
protected MinecraftUnit _minecraftUnitOrigin;
void Awake()
{
@ -28,10 +29,12 @@ public class ProjectileHandler : MonoBehaviour
if (RigidBody.linearVelocity.magnitude >= 1f) transform.forward = RigidBody.linearVelocity.normalized;
}
public void LaunchProjectile(Vector3 baseSpeed, bool fromTeamA)
public void LaunchProjectile(Vector3 baseSpeed, bool fromTeamA, MinecraftUnit minecraftUnit)
{
RigidBody.linearVelocity = baseSpeed;
FromTeamA = fromTeamA;
_minecraftUnitOrigin = minecraftUnit;
}
}

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6a9e2d1e9e9f8774395ab8c8b44e8dba
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,23 @@
using UnityEngine;
using UnityEngine.UI;
public class HealthBar : MonoBehaviour
{
[SerializeField] private HealthHandler healthHandler;
[SerializeField] private Slider healthSlider;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
healthSlider.maxValue = healthHandler.MaxHealth;
}
void Update()
{
healthSlider.value = healthHandler.CurrentHealth;
}
// Update is called once per frame
void LateUpdate()
{
transform.LookAt(Camera.main.transform);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: da56039456f5041c88cca65308f23ca0

View file

@ -0,0 +1,21 @@
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
public class ManaBars : MonoBehaviour
{
[SerializeField] private BaseCapacity capacity;
[SerializeField] private Slider manaSlider;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
manaSlider.maxValue = capacity.MaxMana;
}
void Update()
{
manaSlider.value = capacity.Mana;
}
// Child of healthbar, rotation is handled by healthbar
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: bc83878e8ee5d68b2b4f5622c7100b52

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d76dce105c83372aebd5f8d8f33ee08b
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,39 @@
using UnityEngine;
public class BaseCapacity : MonoBehaviour
{
[field: SerializeField] public float MaxMana { get; private set; }
[field: SerializeField] public float Mana { get; private set; }
protected float ManaCost;
protected AbstractUnit _unit;
// Called every frame
protected virtual bool CapacityCall()
{
return true;
}
public void AddMana(float manaAdd)
{
Mana = Mathf.Max(Mana + manaAdd, MaxMana);
}
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
_unit = GetComponent<AbstractUnit>();
}
// Update is called once per frame
void Update()
{
if (Mana >= ManaCost)
{
bool capacityLaunched = CapacityCall();
if (capacityLaunched) Mana -= ManaCost;
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: adbf6613bee8e8088b3389c62d61b845

View file

@ -0,0 +1,33 @@
using UnityEngine;
using System.Collections;
public class GolemDefense : BaseCapacity
{
[SerializeField] private float armorGain;
[SerializeField] private float buffTime;
[SerializeField] private SphereCollider buffArea;
protected override bool CapacityCall()
{
Collider[] hitColliders = Physics.OverlapSphere(transform.position, buffArea.radius, buffArea.includeLayers);
foreach (Collider target in hitColliders)
{
if (!target.CompareTag("Unit")) continue;
AbstractUnit targetUnit = target.GetComponent<AbstractUnit>();
if (targetUnit.IsTeamA == _unit.IsTeamA)
{
CoroutineManager.Instance.StartCoroutine(AddThenRemoveArmor(targetUnit));
}
}
return hitColliders.Length > 0;
}
private IEnumerator AddThenRemoveArmor(AbstractUnit targetUnit)
{
targetUnit.AddArmor(armorGain);
yield return new WaitForSeconds(buffTime);
targetUnit.RemoveArmor(armorGain);
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1ca640aad27b1da9d87fdc4302aa0cd3

View file

@ -3,9 +3,9 @@ using UnityEngine;
[RequireComponent(typeof(MinecraftUnit))]
public class HealthHandler : MonoBehaviour
{
[SerializeField] private float maxHealth;
[SerializeField] private float currentHealth;
[SerializeField] private float armor;
[field: SerializeField] public float MaxHealth{ get; private set; }
[field: SerializeField] public float CurrentHealth{ get; private set; }
[field: SerializeField] public float Armor{ get; private set; }
private MinecraftUnit _minecraftUnit;
@ -17,31 +17,27 @@ public class HealthHandler : MonoBehaviour
public void TakeDamage(float damage)
{
Debug.Assert(damage >= 0, "Damage cannot be negative, use Heal if you want to heal");
currentHealth -= Mathf.Max(0, damage-armor);
if (currentHealth <= 0) Death();
CurrentHealth -= Mathf.Max(0, damage-Armor);
_minecraftUnit.Capacity.AddMana(damage);
if (CurrentHealth <= 0) Death();
}
public void Heal(float value)
{
Debug.Assert(value >= 0, "value can't be less than zero");
currentHealth = Mathf.Min(currentHealth + value, maxHealth);
CurrentHealth = Mathf.Min(CurrentHealth + value, MaxHealth);
}
public float GetArmor()
public void AddArmor(float armorBoost)
{
return armor;
Debug.Assert(armorBoost >= 0, "armorBoost can't be less than zero, use RemoveArmor instead");
Armor += armorBoost;
}
public void EquipArmor(float armorBoost)
public void RemoveArmor(float armorBoost)
{
Debug.Assert(armorBoost >= 0, "armorBoost can't be less than zero, use UnEquipArmor instead");
armor += armorBoost;
}
public void UnEquipArmor(float armorBoost)
{
Debug.Assert(armorBoost >= 0, "armorBoost can't be less than zero, use EquipArmor instead");
armor -= armorBoost;
Debug.Assert(armorBoost >= 0, "armorBoost can't be less than zero, use AddArmor instead");
Armor -= armorBoost;
}
public void Death(float delay = 0)

View file

@ -6,16 +6,18 @@ using UnityEngine.AI;
[DisallowMultipleComponent]
[RequireComponent(typeof(Rigidbody), typeof(HealthHandler), typeof(AttackHandler))]
[RequireComponent(typeof(MovementHandler))]
[RequireComponent(typeof(MovementHandler), typeof(BaseCapacity))]
public class MinecraftUnit : AbstractUnit
{
[field: SerializeField] public Rigidbody Body { get; private set; }
[field: SerializeField] public HealthHandler HealthHandler { get; private set; }
[field: SerializeField] public AttackHandler AttackHandler { get; private set; }
[field: SerializeField] public MovementHandler MovementHandler { get; private set; }
[field: SerializeField] public BaseCapacity Capacity { get; private set; }
// Not required
[field: SerializeField] public Animator Animator { get; private set; }
@ -34,4 +36,15 @@ public class MinecraftUnit : AbstractUnit
{
HealthHandler.Heal(heal);
}
public override void AddArmor(float armor)
{
HealthHandler.AddArmor(armor);
}
public override void RemoveArmor(float armor)
{
HealthHandler.RemoveArmor(armor);
}
}