Initial commit: Tiny Tackle Heroes Unity project
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
using System.Collections.Generic;
|
||||
using BumpCombat.Combat;
|
||||
using BumpCombat.Core;
|
||||
using BumpCombat.Constants;
|
||||
using BumpCombat.Enemies;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BumpCombat.Player
|
||||
{
|
||||
[DisallowMultipleComponent]
|
||||
public sealed class PlayerStats : CharacterModel
|
||||
{
|
||||
private const string PressureStreakSourceId = "player.pressure-streak";
|
||||
private readonly HashSet<int> pressureStreakProcessedEnemyLifetimes = new();
|
||||
private RunManager subscribedRunManager;
|
||||
private PlayerHealth playerHealth;
|
||||
private float pressureStreakExpiresAt = -1f;
|
||||
private float pressureStreakLastKillAt = -1f;
|
||||
|
||||
public override float MoveSpeed => Evaluate(
|
||||
CharacterStat.MoveSpeed,
|
||||
GameplayConstants.Current.Player.BaseMoveSpeed);
|
||||
public override float MaxHealth => Evaluate(
|
||||
CharacterStat.MaxHealth,
|
||||
GameplayConstants.Current.Player.BaseMaxHealth);
|
||||
|
||||
public int PressureStreakKillCount { get; private set; }
|
||||
public int PressureStreakKillTarget => Mathf.Max(
|
||||
1,
|
||||
GameplayConstants.Current.Player.PressureStreakKillTarget);
|
||||
public float PressureStreakRemaining => Mathf.Max(
|
||||
0f,
|
||||
pressureStreakExpiresAt - GetCombatTime());
|
||||
public bool IsPressureStreakWindowActive => PressureStreakRemaining > 0f;
|
||||
public bool IsPressureStreakActive => IsPressureStreakWindowActive
|
||||
&& GetStackCount(
|
||||
PressureStreakSourceId,
|
||||
CharacterStat.MoveSpeed) > 0;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
playerHealth = GetComponent<PlayerHealth>();
|
||||
if (playerHealth != null)
|
||||
{
|
||||
playerHealth.OnDied += HandlePlayerDied;
|
||||
}
|
||||
|
||||
CombatEvents.OnValidHit += HandleValidHit;
|
||||
RefreshRunManagerSubscription();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
RefreshRunManagerSubscription();
|
||||
if (subscribedRunManager != null
|
||||
&& !subscribedRunManager.IsTitleScreen
|
||||
&& !subscribedRunManager.IsGameOver)
|
||||
{
|
||||
HandleRunStarted();
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
RefreshRunManagerSubscription();
|
||||
RefreshPressureStreak();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
CombatEvents.OnValidHit -= HandleValidHit;
|
||||
if (playerHealth != null)
|
||||
{
|
||||
playerHealth.OnDied -= HandlePlayerDied;
|
||||
}
|
||||
|
||||
UnsubscribeRunManager();
|
||||
ResetPressureStreak();
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
CombatEvents.OnValidHit -= HandleValidHit;
|
||||
if (playerHealth != null)
|
||||
{
|
||||
playerHealth.OnDied -= HandlePlayerDied;
|
||||
}
|
||||
|
||||
UnsubscribeRunManager();
|
||||
}
|
||||
|
||||
public void RefreshPressureStreak()
|
||||
{
|
||||
float now = GetCombatTime();
|
||||
PrunePressureStreak(now);
|
||||
if (pressureStreakExpiresAt > 0f && now >= pressureStreakExpiresAt)
|
||||
{
|
||||
ClearPressureStreakBuff();
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleValidHit(CombatHitResult result)
|
||||
{
|
||||
if (result.Attacker != gameObject
|
||||
|| !result.IsOrdinaryBump
|
||||
|| result.IsArtifactHit
|
||||
|| result.Damage <= 0f
|
||||
|| result.Target == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((playerHealth != null && playerHealth.CurrentHealth <= 0f)
|
||||
|| RunManager.Instance?.IsGameOver == true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EnemyController enemy = result.Target.GetComponent<EnemyController>()
|
||||
?? result.Target.GetComponentInParent<EnemyController>();
|
||||
if (enemy == null || !enemy.IsDead)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int lifetimeIdentity = enemy.SpawnLifetimeIdentity;
|
||||
if (lifetimeIdentity <= 0)
|
||||
{
|
||||
lifetimeIdentity = enemy.GetInstanceID();
|
||||
}
|
||||
|
||||
if (!pressureStreakProcessedEnemyLifetimes.Add(lifetimeIdentity))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float now = GetCombatTime();
|
||||
RefreshPressureStreak();
|
||||
if (pressureStreakLastKillAt < 0f
|
||||
|| now - pressureStreakLastKillAt
|
||||
> Mathf.Max(
|
||||
0f,
|
||||
GameplayConstants.Current.Player.PressureStreakWindowSeconds))
|
||||
{
|
||||
PressureStreakKillCount = 0;
|
||||
}
|
||||
|
||||
PressureStreakKillCount++;
|
||||
pressureStreakLastKillAt = now;
|
||||
pressureStreakExpiresAt = now
|
||||
+ Mathf.Max(
|
||||
0f,
|
||||
GameplayConstants.Current.Player.PressureStreakDuration);
|
||||
|
||||
if (PressureStreakKillCount >= PressureStreakKillTarget)
|
||||
{
|
||||
EnsurePressureStreakBuff();
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveModifiersFromSource(PressureStreakSourceId);
|
||||
}
|
||||
}
|
||||
|
||||
private void PrunePressureStreak(float now)
|
||||
{
|
||||
if (pressureStreakLastKillAt >= 0f
|
||||
&& now - pressureStreakLastKillAt
|
||||
> Mathf.Max(
|
||||
0f,
|
||||
GameplayConstants.Current.Player.PressureStreakWindowSeconds))
|
||||
{
|
||||
PressureStreakKillCount = 0;
|
||||
pressureStreakLastKillAt = -1f;
|
||||
ClearPressureStreakBuff();
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsurePressureStreakBuff()
|
||||
{
|
||||
if (GetStackCount(
|
||||
PressureStreakSourceId,
|
||||
CharacterStat.MoveSpeed) > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AddModifier(new StatModifier(
|
||||
PressureStreakSourceId,
|
||||
CharacterStat.MoveSpeed,
|
||||
ModifierOperation.Increased,
|
||||
Mathf.Max(
|
||||
0f,
|
||||
GameplayConstants.Current.Player.PressureStreakMoveSpeedIncrease)));
|
||||
}
|
||||
|
||||
private void ClearPressureStreakBuff()
|
||||
{
|
||||
RemoveModifiersFromSource(PressureStreakSourceId);
|
||||
pressureStreakExpiresAt = -1f;
|
||||
}
|
||||
|
||||
private void ResetPressureStreak()
|
||||
{
|
||||
pressureStreakProcessedEnemyLifetimes.Clear();
|
||||
PressureStreakKillCount = 0;
|
||||
pressureStreakLastKillAt = -1f;
|
||||
ClearPressureStreakBuff();
|
||||
}
|
||||
|
||||
private void HandlePlayerDied()
|
||||
{
|
||||
ResetPressureStreak();
|
||||
}
|
||||
|
||||
private void HandleRunStarted()
|
||||
{
|
||||
ResetPressureStreak();
|
||||
}
|
||||
|
||||
private void HandleGameOver()
|
||||
{
|
||||
ResetPressureStreak();
|
||||
}
|
||||
|
||||
private float GetCombatTime()
|
||||
{
|
||||
RunManager current = RunManager.Instance;
|
||||
return current != null ? current.ElapsedTime : Time.time;
|
||||
}
|
||||
|
||||
private void RefreshRunManagerSubscription()
|
||||
{
|
||||
RunManager current = RunManager.Instance;
|
||||
if (subscribedRunManager == current)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UnsubscribeRunManager();
|
||||
subscribedRunManager = current;
|
||||
if (subscribedRunManager == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
subscribedRunManager.OnRunStarted += HandleRunStarted;
|
||||
subscribedRunManager.OnGameOver += HandleGameOver;
|
||||
}
|
||||
|
||||
private void UnsubscribeRunManager()
|
||||
{
|
||||
if (subscribedRunManager == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
subscribedRunManager.OnRunStarted -= HandleRunStarted;
|
||||
subscribedRunManager.OnGameOver -= HandleGameOver;
|
||||
subscribedRunManager = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user