123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- using Sirenix.OdinInspector;
- using QFSW.MOP2;
- using KairoEngine.Core;
- using KairoEngine.Inventory;
- namespace KairoEngine.CharacterSystem
- {
- public class DamageController : MonoBehaviour
- {
- public CharacterController character;
- [SerializeField, ShowInInspector] private int hitPoints = 100;
- [SerializeField, ShowInInspector]private int maxHitPoints = 100;
- [SerializeField, ShowInInspector] private int armorPoints = 4;
- //public GameObject hitPrefab;
- public string hitFxName = "BloodSpillFx";
- public int HP { get { return hitPoints; } }
- public int maxHP { get { return maxHitPoints; } }
- public int armor { get { return armorPoints; } }
- private List<Bullet> bulletHits = new List<Bullet>();
- void Start()
- {
- if(HP <= 0)
- {
- character.Die();
- DamageEvents.DeathEvent(this, null);
- }
- }
- public void OnCollisionEnter(Collision collision)
- {
- Vector3 point = collision.contacts[0].point;
- if (collision.gameObject.tag == "Bullet")
- {
- Bullet bullet = collision.gameObject.GetComponent<Bullet>();
- Damage(bullet, point);
- }
- DamageEmitter damageEmitter = collision.gameObject.GetComponent<DamageEmitter>();
- if(damageEmitter != null)
- {
- if(damageEmitter.character != character && damageEmitter.enabled == true)
- {
- Damage(damageEmitter, point);
- }
-
- }
- }
- public void Damage(Bullet bullet, Vector3 point, DamagePoint damagePoint = null)
- {
- float damageMultiplier = 1f;
- if(damagePoint != null) damageMultiplier = damagePoint.damageMultiplier;
- // Don't damage the shooter
- if(bullet.character == character) return;
- // Each bullet only damages once
- for (int i = 0; i < bulletHits.Count; i++)
- {
- if(bulletHits[i] == bullet) return;
- }
- bulletHits.Add(bullet);
- StartCoroutine(Timer.Start(0.5f, false, () => { bulletHits.Remove(bullet); }));
- // Get firearm properties to calculate damage
- ItemBaseFirearm firearmItem = (ItemBaseFirearm)bullet.firearmRef.item;
- int firearmDamage = firearmItem.CalculateDamage(bullet.firearmRef, bullet.startPos, point);
- // Distance damage falloff calculation
- float travelDistance = Vector3.Distance(bullet.startPos, bullet.transform.position);
- if(travelDistance < firearmItem.minDistance)
- {
- firearmDamage = (int)((float)firearmDamage * 1.25f);
- }
- else if(travelDistance > firearmItem.halfDistance)
- {
- float modifier = ((firearmItem.maxDistance - firearmItem.halfDistance)/100) * (travelDistance - firearmItem.halfDistance);
- firearmDamage = (int)((float)firearmDamage - (float)firearmDamage * modifier);
- if(firearmDamage < 0) firearmDamage = 0;
- }
- else if(travelDistance > firearmItem.maxDistance)
- {
- firearmDamage = 0;
- }
- // Critical Hit calculation
- bool criticalHit = false;
- float roll = Random.Range(0, 100);
- if(roll <= firearmItem.criticalChanceModifier) criticalHit = true;
- // Calculate damage
- int armorPiercing = bullet.firearmRef.ammoType.armorPiercing;
- int damage = CalculateDamage(firearmDamage, armorPiercing);
- if(criticalHit) damage = damage * 2;
- damage = Mathf.FloorToInt(damage * damageMultiplier);
- // Remove hitpoints and start events
- //if(damage == 0) return;
- hitPoints -= damage;
- GameObject obj = bullet.character.gameObject;
- DamageData damageData = new DamageData(this, damagePoint, damage, obj, bullet.character, bullet, null, point, bullet.startPos, hitPoints <= 0);
- DamageEvents.DamageEvent(damageData);
- if(character != null)
- {
- character.Injury();
- if(hitPoints <= 0)
- {
- character.Die();
- DamageEvents.DeathEvent(this, bullet.character);
- }
- }
- SpawnHitFX(point);
-
- }
- public void Damage(DamageEmitter damageEmitter, Vector3 point, DamagePoint damagePoint = null)
- {
- int damage = CalculateDamage(damageEmitter.damage, damageEmitter.armorPiercing);
- hitPoints -= damage;
- GameObject obj = damageEmitter.character.gameObject;
- DamageData damageData = new DamageData(this, damagePoint, damage, obj, damageEmitter.character, null, damageEmitter, point, obj.transform.position, hitPoints <= 0);
- DamageEvents.DamageEvent(damageData);
- if(character != null)
- {
- character.Injury();
-
- if(hitPoints <= 0)
- {
- character.Die();
- if(damageEmitter.character != null) DamageEvents.DeathEvent(this, damageEmitter.character);
- }
- }
- SpawnHitFX(point);
- }
- private int CalculateDamage(int baseDamage, int armorPiercing)
- {
- int defense = armor - armorPiercing;
- if(defense < 0) defense = 0;
- int damage = baseDamage - defense;
- if(damage < 0) damage = 0;
- return damage;
- }
-
- private void SpawnHitFX(Vector3 position)
- {
- //if(hitPrefab == null) return;
- //var prefab = Instantiate(hitPrefab, position, transform.rotation) as GameObject;
- MasterObjectPooler.Instance.GetPool(hitFxName).GetObject(position, transform.rotation);
- }
-
- public void Heal(int value)
- {
- if(hitPoints + value < maxHitPoints) hitPoints += value;
- else
- {
- value = maxHitPoints - hitPoints;
- hitPoints = maxHitPoints;
- }
- DamageEvents.HealEvent(this, value);
- }
- public void SetHP(int value) => hitPoints = value;
- public void SetMaxHP(int value) => maxHitPoints = value;
- public void SetArmor(int value) => armorPoints = value;
- }
- }
|