카테고리 없음
[unity]CharacterData
SKIAP
2020. 10. 21. 20:53
using System;
using CreatorKitCodeInternal;
using UnityEngine;
using Random = UnityEngine.Random;
namespace CreatorKitCode
{
/// <summary>
/// This defines a character in the game. The name Character is used in a loose sense, it just means something that
/// can be attacked and have some stats including health. It could also be an inanimate object like a breakable box.
/// </summary>
public class CharacterData : HighlightableObject
{
public string CharacterName;
public StatSystem Stats;
/// <summary>
/// The starting weapon equipped when the Character is created. Set through the Unity Editor.
/// </summary>
public Weapon StartingWeapon;
public InventorySystem Inventory = new InventorySystem();
public EquipmentSystem Equipment = new EquipmentSystem();
public AudioClip[] HitClip;
/// <summary>
/// Callback for when that CharacterData receive damage. E.g. used by the player character to trigger the right
/// animation
/// </summary>
public Action OnDamage { get; set; }
/// <summary>
/// Will return true if the attack cooldown have reached 0. False otherwise.
/// </summary>
public bool CanAttack
{
get { return m_AttackCoolDown <= 0.0f; }
}
float m_AttackCoolDown;
public void Init()
{
Stats.Init(this);
Inventory.Init(this);
Equipment.Init(this);
if (StartingWeapon != null)
{
StartingWeapon.UsedBy(this);
Equipment.InitWeapon(StartingWeapon, this);
}
}
void Awake()
{
Animator anim = GetComponentInChildren<Animator>();
if(anim != null)
SceneLinkedSMB<CharacterData>.Initialise(anim, this);
}
// Update is called once per frame
void Update()
{
Stats.Tick();
if (m_AttackCoolDown > 0.0f)
m_AttackCoolDown -= Time.deltaTime;
}
/// <summary>
/// Will check if that CharacterData can reach the given target with its currently equipped weapon. Will rarely
/// be called, as the function CanAttackTarget will call this AND also check if the cooldown is finished.
/// </summary>
/// <param name="target">The CharacterData you want to reach</param>
/// <returns>True if you can reach the target, False otherwise</returns>
public bool CanAttackReach(CharacterData target)
{
return Equipment.Weapon.CanHit(this, target);
}
/// <summary>
/// Will check if the target is attackable. This in effect check :
/// - If the target is in range of the weapon
/// - If this character attack cooldown is finished
/// - If the target isn't already dead
/// </summary>
/// <param name="target">The CharacterData you want to reach</param>
/// <returns>True if the target can be attacked, false if any of the condition isn't met</returns>
public bool CanAttackTarget(CharacterData target)
{
if (target.Stats.CurrentHealth == 0)
return false;
if (!CanAttackReach(target))
return false;
if (m_AttackCoolDown > 0.0f)
return false;
return true;
}
/// <summary>
/// Call when the character die (health reach 0).
/// </summary>
public void Death()
{
Stats.Death();
}
/// <summary>
/// Attack the given target. NOTE : this WON'T check if the target CAN be attacked, you should make sure before
/// with the CanAttackTarget function.
/// </summary>
/// <param name="target">The CharacterData you want to attack</param>
public void Attack(CharacterData target)
{
Equipment.Weapon.Attack(this, target);
}
/// <summary>
/// This need to be called as soon as an attack is triggered, it will start the cooldown. This is separate from
/// the actual Attack function as AttackTriggered will be called at the beginning of the animation while the
/// Attack function (doing the actual attack and damage) will be called by an animation event to match the animation
/// </summary>
public void AttackTriggered()
{
//Agility reduce by 0.5% the cooldown to attack (e.g. if agility = 50, 25% faster to attack)
m_AttackCoolDown = Equipment.Weapon.Stats.Speed - (Stats.stats.agility * 0.5f * 0.001f * Equipment.Weapon.Stats.Speed);
}
/// <summary>
/// Damage the Character by the AttackData given as parameter. See the documentation for that class for how to
/// add damage to that attackData. (this will be done automatically by weapons, but you may need to fill it
/// manually when writing special elemental effect)
/// </summary>
/// <param name="attackData"></param>
public void Damage(Weapon.AttackData attackData)
{
if (HitClip.Length != 0)
{
SFXManager.PlaySound(SFXManager.Use.Player, new SFXManager.PlayData()
{
Clip = HitClip[Random.Range(0, HitClip.Length)],
PitchMax = 1.1f,
PitchMin = 0.8f,
Position = transform.position
});
}
Stats.Damage(attackData);
OnDamage?.Invoke();
}
}
}