284 lines
9.8 KiB
C#
284 lines
9.8 KiB
C#
using System.Collections;
|
|
using UnityEngine;
|
|
using UHFPS.Tools;
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
namespace UHFPS.Runtime
|
|
{
|
|
public class LanternItem : PlayerItemBehaviour
|
|
{
|
|
[System.Serializable]
|
|
public struct HandleVariationStruct
|
|
{
|
|
public MinMax HandleVariation;
|
|
public float HandleVariationSpeed;
|
|
}
|
|
|
|
public ItemGuid FuelInventoryItem;
|
|
public Transform HandleBone;
|
|
public Light LanternLight;
|
|
public MeshRenderer LanternFlame;
|
|
public MinMax HandleLimits;
|
|
public Axis HandleAxis;
|
|
|
|
public float HandleGravityTime = 0.2f;
|
|
public float HandleForwardAngle = -90f;
|
|
public float FlameChangeSpeed = 1f;
|
|
public float FlameLightIntensity = 1f;
|
|
public float FlameAlphaFadeStart = 0.2f;
|
|
|
|
public MinMax FlameFlickerLimits;
|
|
public float FlameFlickerSpeed;
|
|
|
|
public HandleVariationStruct HandleIdleVariation;
|
|
public HandleVariationStruct HandleWalkVariation;
|
|
public float VariationBlendTime;
|
|
public bool UseHandleVariation;
|
|
|
|
public bool InfiniteFuel = false;
|
|
public float FuelReloadTime = 2f;
|
|
public ushort FuelLife = 320;
|
|
public Percentage FuelPercentage = 100;
|
|
|
|
public string LanternDrawState = "LanternDraw";
|
|
public string LanternHideState = "LanternHide";
|
|
public string LanternReloadStartState = "Lantern_Reload_Start";
|
|
public string LanternReloadEndState = "Lantern_Reload_End";
|
|
public string LanternIdleState = "LanternIdle";
|
|
|
|
public string LanternHideTrigger = "Hide";
|
|
public string LanternReloadTrigger = "Reload";
|
|
public string LanternReloadEndTrigger = "ReloadEnd";
|
|
|
|
public SoundClip LanternDraw;
|
|
public SoundClip LanternHide;
|
|
public SoundClip LanternReload;
|
|
|
|
private AudioSource audioSource;
|
|
private CanvasGroup lanternPanel;
|
|
private CanvasGroup lanternFlame;
|
|
|
|
private bool updateHandle;
|
|
private float handleAngle;
|
|
private float handleVelocity;
|
|
|
|
private float flameLerp;
|
|
private float targetFlame;
|
|
private float flameIntensity;
|
|
private float variationBlend;
|
|
private float variationVelocity;
|
|
|
|
public float lanternFuel;
|
|
private float currentFuel;
|
|
|
|
private bool isEquipped;
|
|
private bool isBusy;
|
|
|
|
public override string Name => "Lantern";
|
|
|
|
public override bool IsBusy() => !isEquipped || isBusy;
|
|
|
|
public override bool CanCombine() => isEquipped && !isBusy;
|
|
|
|
private void Awake()
|
|
{
|
|
audioSource = GetComponent<AudioSource>();
|
|
GameManager gameManager = GameManager.Instance;
|
|
|
|
var behaviours = gameManager.GraphicReferences.Value["Lantern"];
|
|
lanternPanel = (CanvasGroup)behaviours[0];
|
|
lanternFlame = (CanvasGroup)behaviours[1];
|
|
|
|
if (!SaveGameManager.GameWillLoad)
|
|
{
|
|
currentFuel = FuelPercentage.From(FuelLife);
|
|
UpdateFuel();
|
|
}
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
if (!updateHandle)
|
|
return;
|
|
|
|
float lookY = LookController.LookRotation.y;
|
|
MinMax lookLimits = LookController.VerticalLimits;
|
|
Vector3 movement = PlayerStateMachine.Controller.velocity;
|
|
|
|
float lookInverse1 = Mathf.InverseLerp(lookLimits.min, 0, lookY);
|
|
float lookInverse2 = Mathf.InverseLerp(0, lookLimits.max, lookY);
|
|
|
|
float lerp1 = Mathf.Lerp(HandleLimits.min, HandleForwardAngle, lookInverse1);
|
|
float lerp2 = Mathf.Lerp(HandleForwardAngle, HandleLimits.max, lookInverse2);
|
|
|
|
float targetInverse = lookInverse1 + lookInverse2;
|
|
float targetAngle = Mathf.Lerp(lerp1, lerp2, targetInverse);
|
|
|
|
float movementVariation = 0f;
|
|
if (UseHandleVariation)
|
|
{
|
|
float idleNoise = Mathf.PerlinNoise(Time.time * HandleIdleVariation.HandleVariationSpeed, 0);
|
|
float idleVariation = Mathf.Lerp(HandleIdleVariation.HandleVariation.RealMin, HandleIdleVariation.HandleVariation.RealMax, idleNoise);
|
|
|
|
float walkNoise = Mathf.PerlinNoise(Time.time * HandleWalkVariation.HandleVariationSpeed, 0);
|
|
float walkVariation = Mathf.Lerp(HandleWalkVariation.HandleVariation.RealMin, HandleWalkVariation.HandleVariation.RealMax, walkNoise);
|
|
|
|
movement.y = 0f;
|
|
movement = Vector3.ClampMagnitude(movement, 1f);
|
|
variationBlend = Mathf.SmoothDamp(variationBlend, movement.magnitude, ref variationVelocity, VariationBlendTime);
|
|
movementVariation = Mathf.Lerp(idleVariation, walkVariation, variationBlend);
|
|
}
|
|
|
|
handleAngle = Mathf.SmoothDamp(handleAngle, targetAngle, ref handleVelocity, HandleGravityTime);
|
|
HandleBone.localRotation = Quaternion.AngleAxis(handleAngle + movementVariation, HandleAxis.Convert());
|
|
}
|
|
|
|
public override void OnUpdate()
|
|
{
|
|
if (!updateHandle)
|
|
return;
|
|
|
|
float flicker = Mathf.PerlinNoise(Time.time * FlameFlickerSpeed, 0);
|
|
flameIntensity = Mathf.Lerp(FlameFlickerLimits.RealMin, FlameFlickerLimits.RealMax, flicker) * FlameLightIntensity;
|
|
|
|
if (isEquipped && !isBusy && !InfiniteFuel)
|
|
{
|
|
// lantern fuel
|
|
currentFuel = currentFuel > 0 ? currentFuel -= Time.deltaTime : 0;
|
|
UpdateFuel();
|
|
}
|
|
|
|
float fuelFlameIntensity = flameIntensity * lanternFuel;
|
|
flameLerp = Mathf.MoveTowards(flameLerp, targetFlame, Time.deltaTime * FlameChangeSpeed);
|
|
LanternLight.intensity = Mathf.Lerp(0f, fuelFlameIntensity, flameLerp);
|
|
}
|
|
|
|
private void UpdateFuel()
|
|
{
|
|
lanternFuel = Mathf.InverseLerp(0, FuelLife, currentFuel);
|
|
lanternFlame.alpha = lanternFuel;
|
|
|
|
if (LanternFlame != null)
|
|
{
|
|
float mappedT = Mathf.InverseLerp(0, FlameAlphaFadeStart, currentFuel);
|
|
float flameAlpha = Mathf.Lerp(1, 0, 1 - mappedT);
|
|
LanternFlame.material.SetFloat("_Fade", flameAlpha);
|
|
}
|
|
}
|
|
|
|
public override void OnItemCombine(InventoryItem combineItem)
|
|
{
|
|
if (combineItem.ItemGuid != FuelInventoryItem || !isEquipped)
|
|
return;
|
|
|
|
Inventory.Instance.RemoveItem(combineItem, 1);
|
|
Animator.SetTrigger(LanternReloadTrigger);
|
|
StartCoroutine(ReloadLantern());
|
|
isBusy = true;
|
|
}
|
|
|
|
IEnumerator ReloadLantern()
|
|
{
|
|
yield return new WaitForAnimatorClip(Animator, LanternReloadStartState);
|
|
|
|
audioSource.PlayOneShotSoundClip(LanternReload);
|
|
yield return new WaitForSeconds(FuelReloadTime);
|
|
|
|
Animator.SetTrigger(LanternReloadEndTrigger);
|
|
currentFuel = FuelPercentage.From(FuelLife);
|
|
UpdateFuel();
|
|
|
|
yield return new WaitForAnimatorClip(Animator, LanternReloadEndState);
|
|
|
|
isBusy = false;
|
|
}
|
|
|
|
public override void OnItemSelect()
|
|
{
|
|
CanvasGroupFader.StartFadeInstance(lanternPanel, true, 5f);
|
|
|
|
ItemObject.SetActive(true);
|
|
StartCoroutine(SelectLantern());
|
|
audioSource.PlayOneShotSoundClip(LanternDraw);
|
|
|
|
flameLerp = 0f;
|
|
targetFlame = 1f;
|
|
updateHandle = true;
|
|
isEquipped = false;
|
|
isBusy = false;
|
|
}
|
|
|
|
IEnumerator SelectLantern()
|
|
{
|
|
yield return new WaitForAnimatorClip(Animator, LanternDrawState);
|
|
isEquipped = true;
|
|
}
|
|
|
|
public override void OnItemDeselect()
|
|
{
|
|
CanvasGroupFader.StartFadeInstance(lanternPanel, false, 5f,
|
|
() => lanternPanel.gameObject.SetActive(false));
|
|
|
|
StopAllCoroutines();
|
|
StartCoroutine(HideLantern());
|
|
Animator.SetTrigger(LanternHideTrigger);
|
|
audioSource.PlayOneShotSoundClip(LanternHide);
|
|
|
|
targetFlame = 0f;
|
|
isBusy = true;
|
|
}
|
|
|
|
IEnumerator HideLantern()
|
|
{
|
|
yield return new WaitForAnimatorClip(Animator, LanternHideState);
|
|
yield return new WaitUntil(() => flameLerp <= 0f);
|
|
ItemObject.SetActive(false);
|
|
updateHandle = false;
|
|
isEquipped = false;
|
|
isBusy = false;
|
|
}
|
|
|
|
public override void OnItemActivate()
|
|
{
|
|
lanternPanel.alpha = 1f;
|
|
lanternPanel.gameObject.SetActive(true);
|
|
|
|
StopAllCoroutines();
|
|
ItemObject.SetActive(true);
|
|
Animator.Play(LanternIdleState);
|
|
|
|
flameLerp = 1f;
|
|
targetFlame = 1f;
|
|
|
|
updateHandle = true;
|
|
isEquipped = true;
|
|
isBusy = false;
|
|
}
|
|
|
|
public override void OnItemDeactivate()
|
|
{
|
|
lanternPanel.alpha = 0f;
|
|
lanternPanel.gameObject.SetActive(false);
|
|
|
|
StopAllCoroutines();
|
|
ItemObject.SetActive(false);
|
|
updateHandle = false;
|
|
isEquipped = false;
|
|
isBusy = false;
|
|
}
|
|
|
|
public override StorableCollection OnCustomSave()
|
|
{
|
|
return new StorableCollection()
|
|
{
|
|
{ "currentFuel", currentFuel }
|
|
};
|
|
}
|
|
|
|
public override void OnCustomLoad(JToken data)
|
|
{
|
|
currentFuel = FuelPercentage.From(FuelLife);
|
|
UpdateFuel();
|
|
}
|
|
}
|
|
} |