Skip to content

Commit

Permalink
Merge pull request #29 from Govorunb/fumo
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexejhero authored Nov 6, 2023
2 parents a61b8d1 + ef45790 commit b735ed4
Show file tree
Hide file tree
Showing 56 changed files with 2,874 additions and 150 deletions.
10 changes: 5 additions & 5 deletions SCHIZO/Creatures/Components/CustomCreatureTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ namespace SCHIZO.Creatures.Components;

partial class CustomCreatureTool
{
public override string animToolName => referenceAnimation.ToString().ToLower();
public override string animToolName => data.referenceAnimation.ToString().ToLower();

private new void Awake()
{
if (subnauticaModel) subnauticaModel.SetActive(IS_SUBNAUTICA);
if (belowZeroModel) belowZeroModel.SetActive(IS_BELOWZERO);
if (data.subnauticaModel) data.subnauticaModel.SetActive(IS_SUBNAUTICA);
if (data.belowZeroModel) data.belowZeroModel.SetActive(IS_BELOWZERO);

if (IS_BELOWZERO)
{
leftHandIKTarget = leftHandIKTargetOverrideBZ;
rightHandIKTarget = rightHandIKTargetOverrideBZ;
leftHandIKTarget = data.leftHandIKTargetOverrideBZ;
rightHandIKTarget = data.rightHandIKTargetOverrideBZ;
}

base.Awake();
Expand Down
60 changes: 60 additions & 0 deletions SCHIZO/Items/Components/CustomPlayerTool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System.Text;

namespace SCHIZO.Items.Components;

public abstract partial class CustomPlayerTool
{
public override string animToolName => data.referenceAnimation.ToString().ToLower();

protected new void Awake()
{
if (data.subnauticaModel) data.subnauticaModel.SetActive(IS_SUBNAUTICA);
if (data.belowZeroModel) data.belowZeroModel.SetActive(IS_BELOWZERO);

if (IS_BELOWZERO)
{
leftHandIKTarget = data.leftHandIKTargetOverrideBZ;
rightHandIKTarget = data.rightHandIKTargetOverrideBZ;
}

base.Awake();
}

private int cachedPrimaryUseTextHash;
private int cachedSecondaryUseTextHash;
private int cachedAltUseTextHash;
private string cachedFullUseText;

public override string GetCustomUseText()
{
string primaryText = hasPrimaryUse ? LanguageCache.GetButtonFormat(primaryUseText, GameInput.Button.RightHand) : "";
string secondaryText = hasSecondaryUse ? LanguageCache.GetButtonFormat(secondaryUseText, GameInput.Button.LeftHand) : "";
string altText = hasAltUse ? LanguageCache.GetButtonFormat(altUseText, GameInput.Button.AltTool) : "";

int primaryHash = primaryText.GetHashCode();
int secondaryHash = secondaryText.GetHashCode();
int altHash = altText.GetHashCode();

if (cachedPrimaryUseTextHash != primaryHash
|| cachedSecondaryUseTextHash != secondaryHash
|| cachedAltUseTextHash != altHash)
{
cachedPrimaryUseTextHash = primaryHash;
cachedSecondaryUseTextHash = secondaryHash;
cachedAltUseTextHash = altHash;

StringBuilder sb = new();
sb.Append(primaryText);
if (secondaryText.Length > 0 && sb.Length > 0)
sb.Append(", ");
sb.Append(secondaryText);
if (altText.Length > 0 && sb.Length > 0)
sb.Append(", ");
sb.Append(altText);

cachedFullUseText = sb.ToString();
}

return cachedFullUseText;
}
}
4 changes: 4 additions & 0 deletions SCHIZO/Items/Data/ItemData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,8 @@ protected override void PostRegister()
{
UnityPrefab.CreateAndRegister(ModItem);
}
#if UNITY_EDITOR
[ContextMenu("Set Loader/Fumo Item")]
private void CreateFumoItemLoader() => AssignItemLoader(CreateInstance<FumoItem.FumoItemLoader>());
#endif
}
23 changes: 23 additions & 0 deletions SCHIZO/Items/FumoItem/FumoItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Diagnostics.CodeAnalysis;
using Nautilus.Handlers;

namespace SCHIZO.Items.FumoItem;

public sealed class FumoItem : UnityPrefab
{
[SetsRequiredMembers]
public FumoItem(ModItem modItem) : base(modItem)
{
}

public override void Register()
{
CraftDataHandler.SetEquipmentType(ModItem, EquipmentType.Hand);
CraftDataHandler.SetQuickSlotType(ModItem, QuickSlotType.Selectable);

base.Register();
#if BELOWZERO
CraftDataHandler.SetColdResistance(ModItem, 20);
#endif
}
}
20 changes: 20 additions & 0 deletions SCHIZO/Items/FumoItem/FumoItemLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Nautilus.Handlers;
using SCHIZO.Helpers;
using UnityEngine;

namespace SCHIZO.Items.FumoItem;

partial class FumoItemLoader
{
public override void Load()
{
new FumoItem(itemData.ModItem).Register();
// TODO: move to a "coordinated spawns" scriptable object?
if (RetargetHelpers.Pick(spawnSN, spawnBZ))
{
Vector3 pos = RetargetHelpers.Pick(spawnPositionSN, spawnPositionBZ);
Vector3 rot = RetargetHelpers.Pick(spawnRotationSN, spawnRotationBZ);
CoordinatedSpawnsHandler.RegisterCoordinatedSpawn(new SpawnInfo(itemData.ModItem, pos, rot));
}
}
}
31 changes: 31 additions & 0 deletions SCHIZO/Items/FumoItem/FumoItemTool.BelowZero.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using UnityEngine;

namespace SCHIZO.Items.FumoItem;

public partial class FumoItemTool
{
private (Transform parent, Vector3 localPosOffset) GetHugOffset(float distScale)
{
// TODO: move just the arms instead of the entire body (IK)
Transform parent = transform.root.Find("body").GetChild(0);

// to chest (a bit lower than camera/face)
Vector3 worldDirectionToPlayer = usingPlayer.transform.position + _chestOffset - transform.position;
Vector3 worldOffset = Vector3.Slerp(Vector3.zero, worldDirectionToPlayer * _hugDistance, Mathf.Clamp01(distScale));
Vector3 localOffset = parent.worldToLocalMatrix.MultiplyVector(worldOffset);

// in BZ the camera is attached to the body
Transform cam = transform.root.Find("camPivot/camRoot/camOffset/pdaCamPivot");
cam.localPosition = cam.worldToLocalMatrix.MultiplyVector(-worldOffset);

return (parent, localOffset);
}

private void ApplyColdResistBuff(int buff)
{
if (!usingPlayer) return;
BodyTemperature bodyTemperature = usingPlayer.GetComponent<BodyTemperature>();
if (!bodyTemperature) return;
bodyTemperature.coldResistEquipmentBuff += buff;
}
}
25 changes: 25 additions & 0 deletions SCHIZO/Items/FumoItem/FumoItemTool.Subnautica.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System.Diagnostics;
using UnityEngine;

namespace SCHIZO.Items.FumoItem;

partial class FumoItemTool
{
private (Transform parent, Vector3 localPosOffset) GetHugOffset(float distScale)
{
// TODO: move just the arms instead of the entire body (IK)
Transform parent = transform.root.Find("body").GetChild(0);

// to chest (a bit lower than camera/face)
Vector3 worldDirectionToPlayer = usingPlayer.transform.position + _chestOffset - transform.position;
Vector3 localDirectionToPlayer = parent.worldToLocalMatrix.MultiplyVector(worldDirectionToPlayer);
Vector3 offset = Vector3.Slerp(Vector3.zero, localDirectionToPlayer * _hugDistance, Mathf.Clamp01(distScale));

return (parent, offset);
}

[Conditional("BELOWZERO")]
private void ApplyColdResistBuff(int _)
{
}
}
191 changes: 191 additions & 0 deletions SCHIZO/Items/FumoItem/FumoItemTool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
using System.Collections;
using UnityEngine;

namespace SCHIZO.Items.FumoItem;

partial class FumoItemTool
{
public bool IsHugging => _isHugging;
public bool IsFlushed => _isFlushed;

private const float _hugTransitionDuration = 0.2f;
private float _hugDistScale;
private float _nextHugTime;
private readonly Vector3 _chestOffset = new(0, -0.1f, 0);

private bool _isHugging;
private float _hugTime;
private const float _hugDistance = 0.5f;
private Vector3 _prevHugPosOffset;
private bool _hugEffectApplied;
private const float _hugMoveSpeedMulti = 0.7f;

private bool _flushOnAltUse;
private bool _flushOnHug;
private bool _isFlushed;
private const float _flushedZscalar = 2f;

private GroundMotor _groundMotor;

public new void Awake()
{
_flushOnAltUse = Random.Range(0f, 1f) < 0.05f;
hasAltUse = _flushOnAltUse;
_flushOnHug = !_flushOnAltUse && Random.Range(0f, 1f) < 0.5f;

base.Awake();
}

public void FixedUpdate()
{
if (!usingPlayer) return;
if (!_flushOnHug) return;

if (_isHugging)
{
_hugTime += Time.fixedDeltaTime;
if (_hugTime > 10f) SetFlushed(true);
}
else
{
_hugTime = 0;
if (_hugDistScale == 0f) SetFlushed(false);
}
}

public void Update()
{
if (!usingPlayer) return;

float delta = Time.deltaTime / _hugTransitionDuration;
_hugDistScale = _isHugging
? Mathf.Min(1, _hugDistScale + delta)
: Mathf.Max(0, _hugDistScale - delta);

UpdateHugPos(_hugDistScale);
}

private void UpdateHugPos(float distScale)
{
(Transform parent, Vector3 offset) = GetHugOffset(distScale);

Vector3 delta = offset - _prevHugPosOffset;
parent.localPosition += delta;
_prevHugPosOffset = offset;
}

public override void OnDraw(Player p)
{
p.isUnderwater.changedEvent.AddHandler(this, GroundSpeedHack);
base.OnDraw(p);
}

public override void OnHolster()
{
usingPlayer.isUnderwater.changedEvent.RemoveHandler(this, GroundSpeedHack);
// need to reset immediately, otherwise PDA opens in the wrong location
UpdateHugPos(0);
StopHugging();
if (_isFlushed) SetFlushed(false);
base.OnHolster();
}

public override bool OnRightHandDown() => false; // don't play floater release anim

public override bool OnRightHandHeld()
{
if (!_isHugging && Time.time > _nextHugTime)
StartHugging();
return base.OnRightHandHeld();
}

public override bool OnRightHandUp()
{
StopHugging();
return base.OnRightHandUp();
}

public override bool OnAltDown()
{
if (!_flushOnAltUse) return false;

return SetFlushed(true) && base.OnAltDown();
}

public override bool OnAltUp()
{
if (!_flushOnAltUse) return false;

return SetFlushed(false) && base.OnAltUp();
}

public void StartHugging()
{
if (_isHugging || !usingPlayer) return;
_isHugging = true;

if (_hugEffectApplied) return;
ApplyMoveSpeedMulti(_hugMoveSpeedMulti);
ApplyColdResistBuff(hugColdResistBuff);
_hugEffectApplied = true;
}

public void StopHugging()
{
if (!_isHugging || !usingPlayer) return;
_isHugging = false;
_nextHugTime = Time.time + hugCooldown;

if (!_hugEffectApplied) return;
ApplyMoveSpeedMulti(1f/_hugMoveSpeedMulti);
ApplyColdResistBuff(-hugColdResistBuff);
_hugEffectApplied = false;
}

// a formal apology for the following code may be issued to any Subnautica dev or modder on request
private void ApplyMoveSpeedMulti(float multi)
{
Player player = usingPlayer ? usingPlayer : Player.main;
if (!player) return;
if (!_groundMotor) _groundMotor = player.GetComponent<GroundMotor>();

ApplyGroundMoveSpeedMulti(multi);
// this is fortunately enough to change underwater swim speed
_groundMotor.GetComponent<UnderwaterMotor>().debugSpeedMult *= multi;
}

private void GroundSpeedHack(Utils.MonitoredValue<bool> isUnderwater)
{
if (!_isHugging || isUnderwater.value) return;
StartCoroutine(GroundSpeedHackCoro(_hugMoveSpeedMulti));

IEnumerator GroundSpeedHackCoro(float multi)
{
yield return null;
ApplyGroundMoveSpeedMulti(multi);
}
}

private void ApplyGroundMoveSpeedMulti(float multi)
{
_groundMotor.forwardMaxSpeed *= multi;
_groundMotor.strafeMaxSpeed *= multi;
_groundMotor.backwardMaxSpeed *= multi;
}

public bool SetFlushed(bool flushed)
{
if (_isFlushed == flushed) return false;

_isFlushed = flushed;
ApplyZScaleMulti(flushed ? _flushedZscalar : 1 / _flushedZscalar);
return true;
}

private void ApplyZScaleMulti(float multi)
{
Vector3 scale = fumoModel.localScale;
scale.z *= multi;
fumoModel.localScale = scale;
}
}
Loading

0 comments on commit b735ed4

Please sign in to comment.