Untitled
unknown
csharp
3 years ago
6.6 kB
10
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...