136 lines
3.3 KiB
C#
136 lines
3.3 KiB
C#
using EntityStates;
|
|
using EntityStates.ChildMonster;
|
|
using UnityEngine;
|
|
using UnityEngine.Networking;
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace RoR2;
|
|
|
|
[RequireComponent(typeof(EntityStateMachine))]
|
|
[RequireComponent(typeof(CharacterBody))]
|
|
public class ChildMonsterController : MonoBehaviour
|
|
{
|
|
public CharacterBody characterBody;
|
|
|
|
public EntityStateMachine stateMachine;
|
|
|
|
public GameObject tpEffectPrefab;
|
|
|
|
[Tooltip("If Child receives this much cumulative damage, they will start trying to teleport.")]
|
|
[FormerlySerializedAs("frolicThreshold")]
|
|
public float cumulativeDamageThresholdBeforeFrolic = 10f;
|
|
|
|
[Tooltip("Does not apply to 'falling off cliffs!' teleporting.")]
|
|
public float teleportCooldown = 20f;
|
|
|
|
[Tooltip("Which skill slot is 'Frolic' (teleport) categorized as.")]
|
|
public SkillSlot frolicSkillSlot;
|
|
|
|
private float inAirTimer;
|
|
|
|
public float amountToFallBeforeTp = 1.5f;
|
|
|
|
private float cachedYPosition;
|
|
|
|
private SkillLocator skillLocator;
|
|
|
|
private float lastTeleportTimestamp = -1f;
|
|
|
|
private float healthAtLastTeleport;
|
|
|
|
private BaseState requestedTeleportState;
|
|
|
|
private bool hasAuthority;
|
|
|
|
private void Start()
|
|
{
|
|
skillLocator = characterBody.skillLocator;
|
|
cachedYPosition = characterBody.corePosition.y;
|
|
hasAuthority = Util.HasEffectiveAuthority(characterBody.networkIdentity);
|
|
RegisterTeleport(addInvincibility: false);
|
|
lastTeleportTimestamp = -1f;
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (characterBody == null || !characterBody.healthComponent.alive)
|
|
{
|
|
return;
|
|
}
|
|
TryRefreshTeleportAbility();
|
|
if (hasAuthority)
|
|
{
|
|
HandleFalling();
|
|
HandleCumulativeDamage();
|
|
if (requestedTeleportState != null)
|
|
{
|
|
SetNextStateToTeleport();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SetNextStateToTeleport()
|
|
{
|
|
if (stateMachine.CanInterruptState(requestedTeleportState.GetMinimumInterruptPriority()))
|
|
{
|
|
stateMachine.SetNextState(requestedTeleportState);
|
|
requestedTeleportState = null;
|
|
}
|
|
}
|
|
|
|
private void HandleFalling()
|
|
{
|
|
if (!characterBody.characterMotor.isGrounded && characterBody.corePosition.y < cachedYPosition)
|
|
{
|
|
inAirTimer += Time.deltaTime;
|
|
}
|
|
else
|
|
{
|
|
inAirTimer = 0f;
|
|
}
|
|
cachedYPosition = characterBody.corePosition.y;
|
|
if (inAirTimer > amountToFallBeforeTp)
|
|
{
|
|
inAirTimer = 0f;
|
|
requestedTeleportState = new FrolicAway();
|
|
}
|
|
}
|
|
|
|
private void TryRefreshTeleportAbility()
|
|
{
|
|
if (lastTeleportTimestamp != -1f && CheckTeleportAvailable())
|
|
{
|
|
lastTeleportTimestamp = -1f;
|
|
}
|
|
}
|
|
|
|
private void HandleCumulativeDamage()
|
|
{
|
|
if (requestedTeleportState == null && CheckTeleportAvailable() && healthAtLastTeleport - characterBody.healthComponent.health >= cumulativeDamageThresholdBeforeFrolic)
|
|
{
|
|
requestedTeleportState = new Frolic();
|
|
}
|
|
}
|
|
|
|
public bool CheckTeleportAvailable()
|
|
{
|
|
if (lastTeleportTimestamp != -1f)
|
|
{
|
|
return Time.time - lastTeleportTimestamp >= teleportCooldown;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public void RegisterTeleport(bool addInvincibility = true)
|
|
{
|
|
lastTeleportTimestamp = Time.time;
|
|
healthAtLastTeleport = characterBody.healthComponent.health;
|
|
requestedTeleportState = null;
|
|
skillLocator.GetSkill(frolicSkillSlot)?.DeductStock(100);
|
|
if (addInvincibility && NetworkServer.active && !characterBody.HasBuff(RoR2Content.Buffs.HiddenInvincibility))
|
|
{
|
|
characterBody.AddTimedBuff(RoR2Content.Buffs.HiddenInvincibility, 1.5f);
|
|
}
|
|
}
|
|
}
|