Untitled
unknown
csharp
2 years ago
6.6 kB
4
Indexable
using System; using System.Collections.Generic; using System.Linq; using Entitas; using GameplayModules.Stats; using GridScene; using Unity.Mathematics; using UnityEngine; using Random = UnityEngine.Random; public class BaseAttackInstance : MonoBehaviour { [SerializeField] private float _outDuration; [SerializeField] private GameObject[] _activateOnOut; [SerializeField] private GameObject[] _deactivateOnOut; [SerializeField] protected float HitRadius; [SerializeField] protected GameObject DebugHitZone; #region Temporary [SerializeField] private float _knockBackMaxForce = 10.0f; [SerializeField] private float _knockBackFadeSpeed = 1.0f; [SerializeField] private float _knockBackDuration = 1.0f; #endregion Temporary private GameObject _attackEnemyHitVfx; private GameObject _attackObstacleHitVfx; private bool _isPaused; private bool _isDestroying; private Contexts _contexts; protected GridManager GridManager; protected List<uint> EnemyIds = new List<uint>(); protected Dictionary<EStat, float> StatsLevel = new Dictionary<EStat, float>(); public Action<BaseAttackInstance> OnInstanceDestroyed; protected bool IsUpdating => !_isDestroying && !_isPaused; public bool IsPaused { set => _isPaused = value; } public virtual void Initialize(Dictionary<EStat, float> statsLevel, GameObject attackEnemyHitVfx, GameObject obstacleHitVfx) { StatsLevel = statsLevel; _attackEnemyHitVfx = attackEnemyHitVfx; _attackObstacleHitVfx = obstacleHitVfx; GridManager = GridManager.Instance; _contexts = Contexts.sharedInstance; } protected void ApplyDamage(uint[] enemyId) { float damage = StatsLevel[EStat.Damage]; float stunDuration = StatsLevel[EStat.StunDuration]; float slowedDuration = StatsLevel[EStat.SlowDuration]; float slowedSpeedPenalty = StatsLevel[EStat.SlowSpeedPenalty]; float criticalChance = StatsLevel[EStat.CriticalChance]; if (Random.Range(0, 1f) < criticalChance) { damage *= StatsLevel[EStat.CriticalDamage]; } GameEntity[] entities = Contexts.sharedInstance.game.GetEntities(Matcher<GameEntity>.AllOf(GameMatcher.EnemyId, GameMatcher.Health)); foreach (var gameEntity in entities) { if (!enemyId.Contains(gameEntity.enemyId.value)) continue; float damageReceived = damage - gameEntity.health.Armor * Mathf.Clamp01(1f - StatsLevel[EStat.ArmorPenetration]); gameEntity.health.DamageReceived += damageReceived; EnemyIds.Add(gameEntity.enemyId.value); ApplyEffect(gameEntity, stunDuration, slowedDuration, slowedSpeedPenalty); SpawnEnemyHitVfx(); } ApplyKnockBack(entities, enemyId); } private void ApplyKnockBack(GameEntity[] ges, uint[] ids) { GameEntity impactEntity = _contexts.game.CreateEntity(); impactEntity.AddImpact(true); impactEntity.AddImpactIds(ids); float2[] directions = new float2[ges.Length]; float[] forces = new float[ges.Length]; float[] durations = new float[ges.Length]; float[] elapsedTimes = new float[ges.Length]; float[] fadeSpeeds = new float[ges.Length]; for (int iEntity = 0; iEntity < ges.Length; iEntity++) { directions[iEntity] = GetKnockBackDirection(ges[iEntity]); forces[iEntity] = _knockBackMaxForce; durations[iEntity] = _knockBackDuration; elapsedTimes[iEntity] = 0.0f; fadeSpeeds[iEntity] = _knockBackFadeSpeed; } impactEntity.AddImpactDirections(directions); impactEntity.AddImpactForces(forces); impactEntity.AddImpactDurations(durations); impactEntity.AddImpactElapsedTimes(elapsedTimes); impactEntity.AddImpactFadeSpeeds(fadeSpeeds); impactEntity.AddRepulsionForce(0.0f); } private void ApplyEffect(GameEntity gameEntity, float stunDuration, float slowedDuration, float slowedSpeedPenalty) { if (slowedDuration > 0f) { if (slowedSpeedPenalty > gameEntity.enemySpeed.SlowedSpeedPenalty || (Math.Abs(slowedSpeedPenalty - gameEntity.enemySpeed.SlowedSpeedPenalty) < 0.01f && slowedDuration > gameEntity.enemySpeed.SlowedTimer)) { gameEntity.enemySpeed.SlowedTimer = slowedDuration; gameEntity.enemySpeed.SlowedSpeedPenalty = slowedSpeedPenalty; } } if (stunDuration > 0f && stunDuration > gameEntity.enemySpeed.StunTimer) { gameEntity.enemySpeed.StunTimer = stunDuration; } } private void SpawnEnemyHitVfx() { if (_attackEnemyHitVfx == null) return; Transform attackTransform = transform; Instantiate(_attackEnemyHitVfx, attackTransform.position, attackTransform.rotation); } protected virtual float2 GetKnockBackDirection(GameEntity ge) { Vector3 pos3 = GridManager.PlayerTransform.position; float2 pos2 = new float2(pos3.x, pos3.z); return math.normalize(ge.position.value - pos2); } protected void SpawnObstacleHitVfx(Vector3 obstaclePosition) { if (_attackObstacleHitVfx == null) return; Transform attackTransform = transform; Instantiate(_attackObstacleHitVfx, obstaclePosition, attackTransform.rotation); } protected virtual void DetectHit() { } public virtual void DestroyInstance() { _isDestroying = true; OnInstanceDestroyed?.Invoke(this); if (_outDuration > 0f) { foreach (var go in _activateOnOut) { go.SetActive(true); } foreach (var go in _deactivateOnOut) { go.SetActive(false); } Invoke(nameof(DestroyObject), _outDuration); } else { DestroyObject(); } } private void DestroyObject() { if (gameObject != null) { Destroy(gameObject); //gameobject is already destroyed when you stop the game (sometimes) } } }
Editor is loading...