Totem Climb (#660)

* setup

* scroll stuff

* tons of stuff

* totem bop

* bopping and new assets

* soem more

* frog fit

* fixed order of operation issue

* triple proto

* wow i love super curves

* TRIPLE JUMP

* frog fall

* the spinny

* dragon initial

* functional dragon

* fixed un bug

* the deets

* the deets have been fixed

* miss stuff

* smol fix

* no log

* fixed some issues

* switch to next state

* particle

* remove useless logic

* zoomed out

* sound and line fix

* new bg sheet

* minor tweaks

* pillar tops

* background objects

* background tweak

* triple sound tweak

* background rework

* frog wings and new jump anim

* fix

* birds

* disable pillars

* landing end

* fix again

* minor fix

* fixes and icon

* background scroll logic rework

* put in fixed sheet

* fixed sounds
This commit is contained in:
Rapandrasmus
2024-01-28 04:43:54 +01:00
committed by GitHub
parent 30f94f4f98
commit 3e20013a1a
120 changed files with 47387 additions and 0 deletions

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 94d255678def8bf46b2a3d4bd2482a56
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,84 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace HeavenStudio.Games.Scripts_TotemClimb
{
public class TCBackgroundManager : MonoBehaviour
{
private const int BACKGROUND_OBJECT_AMOUNT = 18;
[SerializeField] private Transform _objectsParent;
[SerializeField] private List<BackgroundScrollPair> _objects;
private void Awake()
{
foreach (var o in _objects)
{
o.InitClones(_objectsParent);
}
}
private void Update()
{
foreach (var o in _objects)
{
o.ScrollClones();
}
}
[System.Serializable]
private class BackgroundScrollPair
{
public Transform first;
public Transform second;
public float moveSpeed = 1.0f;
private List<Transform> _objects = new();
private List<float> _objectOffsets = new();
private float _xDistance;
private float GetDistance()
{
return second.localPosition.x - first.localPosition.x;
}
public void InitClones(Transform parent)
{
_xDistance = GetDistance();
_objects.Add(first);
_objectOffsets.Add(first.localPosition.x);
_objects.Add(second);
_objectOffsets.Add(second.localPosition.x);
for (int i = 0; i < BACKGROUND_OBJECT_AMOUNT; i++)
{
Transform spawnedObject = Instantiate(first, parent);
spawnedObject.localPosition = new Vector3(second.localPosition.x + (_xDistance * (i + 1)), first.localPosition.y, first.localPosition.z);
_objects.Add(spawnedObject);
_objectOffsets.Add(spawnedObject.localPosition.x);
}
}
public void ScrollClones()
{
for (int i = 0; i < _objects.Count; i++)
{
var b = _objects[i];
var bOffset = _objectOffsets[i];
float songPos = Conductor.instance.songPosition;
b.localPosition = new Vector3(bOffset - (songPos * moveSpeed), b.localPosition.y);
float fullDistance = (BACKGROUND_OBJECT_AMOUNT + 2) * _xDistance;
if (b.localPosition.x <= -fullDistance / 2)
{
_objectOffsets[i] = bOffset + fullDistance;
}
}
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 90e9c132b6e784648806d42dd19243a8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,67 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace HeavenStudio.Games.Scripts_TotemClimb
{
public class TCBirdManager : MonoBehaviour
{
[SerializeField] private float _speedX;
[SerializeField] private float _speedY;
[SerializeField] private Transform _birdRef;
[SerializeField] private Transform _deathThresholdPoint;
[SerializeField] private Sprite _penguinSprite;
private List<Bird> _birds = new();
private void Update()
{
foreach (var bird in _birds)
{
if (bird.birdTransform == null) continue;
bird.birdTransform.localPosition -= new Vector3(_speedX * bird.speed * Time.deltaTime, _speedY * bird.speed * Time.deltaTime);
if (bird.birdTransform.localPosition.x <= _deathThresholdPoint.localPosition.x)
{
Destroy(bird.birdTransform.gameObject);
}
}
_birds.RemoveAll(x => x.birdTransform == null);
}
public void AddBird(float speed, bool penguin, int amount)
{
amount = Mathf.Clamp(amount, 1, 3);
Transform spawnedBird = Instantiate(_birdRef, transform);
if (penguin)
{
spawnedBird.GetComponent<SpriteRenderer>().sprite = _penguinSprite;
spawnedBird.GetChild(0).GetComponent<SpriteRenderer>().sprite = _penguinSprite;
spawnedBird.GetChild(1).GetComponent<SpriteRenderer>().sprite = _penguinSprite;
}
spawnedBird.gameObject.SetActive(true);
if (amount >= 2) spawnedBird.GetChild(0).gameObject.SetActive(true);
if (amount == 3) spawnedBird.GetChild(1).gameObject.SetActive(true);
_birds.Add(new Bird(speed, spawnedBird));
}
private struct Bird
{
public float speed;
public Transform birdTransform;
public Bird(float mSpeed, Transform mBirdTransform)
{
speed = mSpeed;
birdTransform = mBirdTransform;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 91d6e7654abbb4c4699731e94d8fd77e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,27 @@
using HeavenStudio.Util;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace HeavenStudio.Games.Scripts_TotemClimb
{
public class TCDragon : MonoBehaviour
{
[NonSerialized] public double beat;
[SerializeField] private Animator _anim;
[SerializeField] private Transform _jumperPoint;
public Transform JumperPoint => _jumperPoint;
public void Hold()
{
_anim.DoScaledAnimationAsync("Hold", 0.25f);
}
public void Release()
{
_anim.DoScaledAnimationAsync("Release", 0.5f);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 335111224b4eaf141a5209624ea6a23b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,17 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace HeavenStudio.Games.Scripts_TotemClimb
{
public class TCEndTotem : MonoBehaviour
{
[SerializeField] private TCTotemManager _totemManager;
public void ActivateFeatherEffect()
{
_totemManager.ActivateEndParticles();
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f25c0a7294f326943badf87e217ae1b1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,61 @@
using HeavenStudio.Util;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace HeavenStudio.Games.Scripts_TotemClimb
{
public class TCFrog : MonoBehaviour
{
[NonSerialized] public double beat;
[SerializeField] private Animator _animLeft;
[SerializeField] private Animator _animMiddle;
[SerializeField] private Animator _animRight;
[SerializeField] private Animator _anim;
[SerializeField] private Transform _jumperPointLeft;
[SerializeField] private Transform _jumperPointMiddle;
[SerializeField] private Transform _jumperPointRight;
public Transform JumperPointLeft => _jumperPointLeft;
public Transform JumperPointMiddle => _jumperPointMiddle;
public Transform JumperPointRight => _jumperPointRight;
private bool _hasWings = false;
private bool _flapSet = false; // I hate unity
private void Update()
{
if (!_anim.GetCurrentAnimatorStateInfo(0).IsName("Wings") && _hasWings && !_flapSet)
{
_anim.Play("Wings", 0, 0);
_flapSet = true;
}
}
public void FallPiece(int part)
{
if (_hasWings) _anim.Play("WingsNoFlap", 0, 0);
switch (part)
{
case -1:
_animLeft.DoScaledAnimationAsync("Fall", 0.5f);
break;
case 0:
_animMiddle.DoScaledAnimationAsync("Fall", 0.5f);
break;
default:
_animRight.DoScaledAnimationAsync("Fall", 0.5f);
break;
}
}
public void SetHasWings()
{
_hasWings = true;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 81963aa088010e041935d18a5b18a894
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,56 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace HeavenStudio.Games.Scripts_TotemClimb
{
public class TCGroundManager : MonoBehaviour
{
private const int GROUND_AMOUNT = 6;
[Header("Components")]
[SerializeField] private Transform _groundFirst;
[SerializeField] private Transform _groundSecond;
private List<Transform> _grounds = new();
private Transform _scrollTransform;
private float _groundDistance;
private float _groundStart;
private int _groundIndex = 0;
private void Awake()
{
_scrollTransform = transform.parent;
_groundStart = _groundFirst.localPosition.x;
_groundDistance = _groundSecond.localPosition.x - _groundFirst.localPosition.x;
_grounds.Add(_groundFirst);
_grounds.Add(_groundSecond);
for (int i = 2; i < GROUND_AMOUNT; i++)
{
Transform spawnedGround = Instantiate(_groundFirst, transform);
spawnedGround.localPosition = new Vector3(_groundStart + (_groundDistance * i), spawnedGround.localPosition.y);
_grounds.Add(spawnedGround);
}
}
private void Update()
{
float currentScrollX = _scrollTransform.localPosition.x;
float currentDistance = _groundStart + (_groundDistance * _groundIndex);
if (currentScrollX >= currentDistance + (_groundDistance * GROUND_AMOUNT / 2))
{
var g = _grounds[_groundIndex % GROUND_AMOUNT];
g.localPosition = new Vector3(g.localPosition.x + (_groundDistance * GROUND_AMOUNT), g.localPosition.y);
_groundIndex++;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5f01311f73b954b4bae83be6f232a500
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,420 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using HeavenStudio.Util;
namespace HeavenStudio.Games.Scripts_TotemClimb
{
public class TCJumper : SuperCurveObject
{
[SerializeField] private Transform _initialPoint;
[SerializeField] private ParticleSystem _highParticle;
[SerializeField] private ParticleSystem _highMissParticle;
[SerializeField] private ParticleSystem _jumpParticle;
[SerializeField] private float _jumpHeight = 2f;
[SerializeField] private float _jumpHeightTriple = 1f;
[SerializeField] private float _jumpHighHeight = 6f;
private Path _path;
private Animator _anim;
private TotemClimb _game;
private double _startBeat;
private double _onPlayBeat;
private IEnumerator _currentStateCo;
private void Awake()
{
_anim = GetComponent<Animator>();
_game = TotemClimb.instance;
}
public void InitPath(double beat, double onPlayBeat)
{
_onPlayBeat = onPlayBeat;
_startBeat = beat;
_path = new Path();
_path.positions = new PathPos[2];
_path.positions[0] = new PathPos()
{
duration = 1 - (float)Conductor.instance.SecsToBeats(Minigame.justEarlyTime, Conductor.instance.GetBpmAtBeat(beat)),
target = _initialPoint,
height = _jumpHeight
};
if (_game.IsHighBeat(beat))
{
_path.positions[1] = new PathPos()
{
target = _game.GetDragonPointAtBeat(beat)
};
}
else
{
_path.positions[1] = new PathPos()
{
target = _game.IsTripleBeat(beat) ? _game.GetJumperFrogPointAtBeat(beat, -1) : _game.GetJumperPointAtBeat(beat)
};
}
}
public void StartJumping(double beat, bool miss = false, bool nearMiss = false)
{
bool nextIsTriple = _game.IsTripleBeat(beat + 1);
bool nextIsHigh = _game.IsHighBeat(beat + 1);
SwitchToNextState(JumpCo(beat, miss, nearMiss));
if (beat + 1 >= _game.EndBeat) return;
if (nextIsHigh)
{
_game.ScheduleInput(beat, 1, Minigame.InputAction_BasicPress, JustHold, Empty, Empty);
_game.ScheduleInput(beat, 3, Minigame.InputAction_FlickRelease, JustRelease, MissRelease, Empty);
}
else _game.ScheduleInput(beat, 1, Minigame.InputAction_BasicPress, nextIsTriple ? JustTripleEnter : Just, nextIsTriple ? MissTripleEnter : Miss, Empty);
}
public void HighJump(double beat, bool miss)
{
bool nextIsTriple = _game.IsTripleBeat(beat + 2);
bool nextIsHigh = _game.IsHighBeat(beat + 2);
SwitchToNextState(JumpHighCo(beat, miss));
if (beat + 2 >= _game.EndBeat) return;
if (nextIsHigh)
{
_game.ScheduleInput(beat, 2, Minigame.InputAction_BasicPress, JustHold, Empty, Empty);
_game.ScheduleInput(beat, 4, Minigame.InputAction_FlickRelease, JustRelease, MissRelease, Empty);
}
else _game.ScheduleInput(beat, 2, Minigame.InputAction_BasicPress, nextIsTriple ? JustTripleEnter : Just, nextIsTriple ? MissTripleEnter : Miss, Empty);
}
public void TripleJumping(double beat, bool enter, bool miss = false, bool nearMiss = false)
{
SwitchToNextState(JumpTripleCo(beat, enter, miss, nearMiss));
if (beat + 0.5 >= _game.EndBeat) return;
_game.ScheduleInput(beat, 0.5, Minigame.InputAction_BasicPress, enter ? JustTripleExit : Just, enter ? MissTripleExit : Miss, Empty);
}
public void Bop()
{
_anim.DoScaledAnimationAsync("Bop", 0.5f);
}
private IEnumerator JumpCo(double beat, bool miss, bool nearMiss)
{
if (beat >= _startBeat)
{
_path = new Path();
_path.positions = new PathPos[2];
_path.positions[0] = new PathPos()
{
duration = (_game.EndBeat <= beat + 1) ? 1 : 1 - (float)Conductor.instance.SecsToBeats(Minigame.justEarlyTime, Conductor.instance.GetBpmAtBeat(beat + 1)),
height = _jumpHeight,
target = _game.IsTripleBeat(beat) ? _game.GetJumperFrogPointAtBeat(beat, 1) : _game.GetJumperPointAtBeat(beat)
};
if (beat + 1 >= _onPlayBeat && _game.EndBeat <= beat + 1 && _game.UseEndTotem)
{
_path.positions[1] = new PathPos()
{
target = _game.EndJumperPoint
};
}
else if (_game.IsHighBeat(beat + 1))
{
_path.positions[1] = new PathPos()
{
target = _game.GetDragonPointAtBeat(beat + 1)
};
}
else
{
_path.positions[1] = new PathPos()
{
target = _game.IsTripleBeat(beat + 1) ? _game.GetJumperFrogPointAtBeat(beat + 1, -1) : _game.GetJumperPointAtBeat(beat + 1)
};
}
}
if (!miss) _anim.DoScaledAnimationAsync(nearMiss ? "NearMiss" : "Jump", 0.5f);
else _anim.DoScaledAnimationAsync("Miss", 0.5f);
float normalizedBeat = Conductor.instance.GetPositionFromBeat(beat, _path.positions[0].duration);
bool playedFall = false;
while(normalizedBeat < 1f)
{
transform.position = GetPathPositionFromBeat(_path, Math.Clamp(Conductor.instance.songPositionInBeatsAsDouble, beat, beat + _path.positions[0].duration), beat);
if (normalizedBeat >= 0.5f && !playedFall)
{
if (!miss && !nearMiss) _anim.Play("Fall", 0, 0);
playedFall = true;
}
normalizedBeat = Conductor.instance.GetPositionFromBeat(beat, _path.positions[0].duration);
yield return null;
}
transform.position = GetPathPositionFromBeat(_path, beat + _path.positions[0].duration, beat);
_anim.Play("Idle", 0, 0);
if (beat + 1 >= _onPlayBeat && _game.EndBeat <= beat + 1)
{
SoundByte.PlayOneShotGame("totemClimb/totemland");
if (_game.UseEndTotem)
{
_game.DoEndTotemEvents(beat + 1);
gameObject.SetActive(false);
}
}
}
private IEnumerator JumpTripleCo(double beat, bool enter, bool miss, bool nearMiss)
{
if (beat >= _startBeat)
{
_path = new Path();
_path.positions = new PathPos[2];
_path.positions[0] = new PathPos()
{
duration = 0.5f - (float)Conductor.instance.SecsToBeats(Minigame.justEarlyTime, Conductor.instance.GetBpmAtBeat(beat + 0.5)),
height = _jumpHeightTriple,
target = _game.GetJumperFrogPointAtBeat(beat, enter ? -1 : 0)
};
_path.positions[1] = new PathPos()
{
target = _game.GetJumperFrogPointAtBeat(beat + 0.5, enter ? 0 : 1)
};
}
if (!miss) _anim.DoScaledAnimationAsync(nearMiss ? "NearMiss" : "Jump", 0.5f);
else _anim.DoScaledAnimationAsync("Miss", 0.5f);
float normalizedBeat = Conductor.instance.GetPositionFromBeat(beat, _path.positions[0].duration);
bool playedFall = false;
while (normalizedBeat < 1f)
{
transform.position = GetPathPositionFromBeat(_path, Math.Clamp(Conductor.instance.songPositionInBeatsAsDouble, beat, beat + _path.positions[0].duration), beat);
if (normalizedBeat >= 0.5f && !playedFall)
{
if (!miss && !nearMiss) _anim.Play("Fall", 0, 0);
playedFall = true;
}
normalizedBeat = Conductor.instance.GetPositionFromBeat(beat, _path.positions[0].duration);
yield return null;
}
_anim.Play("Idle", 0, 0);
}
private IEnumerator JumpHighCo(double beat, bool miss)
{
if (beat >= _startBeat)
{
_path = new Path();
_path.positions = new PathPos[2];
_path.positions[0] = new PathPos()
{
duration = (_game.EndBeat <= beat + 2) ? 2 : 2 - (float)Conductor.instance.SecsToBeats(Minigame.justEarlyTime, Conductor.instance.GetBpmAtBeat(beat + 2)),
height = _jumpHighHeight,
target = _game.GetDragonPointAtBeat(beat)
};
if (beat + 2 >= _onPlayBeat && _game.EndBeat <= beat + 2 && _game.UseEndTotem)
{
_path.positions[1] = new PathPos()
{
target = _game.EndJumperPoint
};
}
else if (_game.IsHighBeat(beat + 2))
{
_path.positions[1] = new PathPos()
{
target = _game.GetDragonPointAtBeat(beat + 2)
};
}
else
{
_path.positions[1] = new PathPos()
{
target = _game.IsTripleBeat(beat + 2) ? _game.GetJumperFrogPointAtBeat(beat + 2, -1) : _game.GetJumperPointAtBeat(beat + 2)
};
}
}
if (!miss)
{
_anim.Play("HighJump", 0, 0);
_highParticle.PlayScaledAsync(0.5f);
}
else
{
_anim.DoScaledAnimationAsync("HighMiss", 0.5f);
_highMissParticle.PlayScaledAsync(0.5f);
}
float normalizedBeat = Conductor.instance.GetPositionFromBeat(beat, _path.positions[0].duration);
bool playedFall = false;
while (normalizedBeat < 1f)
{
transform.position = GetPathPositionFromBeat(_path, Math.Clamp(Conductor.instance.songPositionInBeatsAsDouble, beat, beat + _path.positions[0].duration), beat);
if (normalizedBeat >= 0.5f && !playedFall)
{
if (!miss) _anim.Play("HighFall", 0, 0);
playedFall = true;
}
normalizedBeat = Conductor.instance.GetPositionFromBeat(beat, _path.positions[0].duration);
yield return null;
}
transform.position = GetPathPositionFromBeat(_path, beat + _path.positions[0].duration, beat);
_anim.Play("Idle", 0, 0);
_highParticle.Stop();
_highMissParticle.Stop();
if (beat + 2 >= _onPlayBeat && _game.EndBeat <= beat + 2)
{
SoundByte.PlayOneShotGame("totemClimb/totemland");
if (_game.UseEndTotem)
{
_game.DoEndTotemEvents(beat + 2);
gameObject.SetActive(false);
}
}
}
private IEnumerator HoldCo(double beat)
{
float normalizedBeat = Conductor.instance.GetPositionFromBeat(beat, 2);
Transform dragonPoint = _game.GetDragonPointAtBeat(beat);
bool canUnHold = true;
while (normalizedBeat < 1f)
{
normalizedBeat = Conductor.instance.GetPositionFromBeat(beat, 2);
transform.position = dragonPoint.position;
if (!_game.IsExpectingInputNow(Minigame.InputAction_FlickRelease)
&& (PlayerInput.GetIsAction(Minigame.InputAction_FlickRelease) || PlayerInput.GetIsAction(Minigame.InputAction_BasicRelease))
&& canUnHold)
{
_anim.DoScaledAnimationAsync("UnHold", 0.5f);
_game.ScoreMiss();
canUnHold = false;
}
if (PlayerInput.GetIsAction(Minigame.InputAction_BasicPress) && !canUnHold)
{
_anim.DoScaledAnimationAsync("Hold", 0.5f);
SoundByte.PlayOneShot("nearMiss");
_game.ScoreMiss();
canUnHold = true;
}
yield return null;
}
}
private void SwitchToNextState(IEnumerator coroutine)
{
_highParticle.Stop();
_highMissParticle.Stop();
if (_currentStateCo != null) StopCoroutine(_currentStateCo);
_currentStateCo = coroutine;
StartCoroutine(_currentStateCo);
}
private void Just(PlayerActionEvent caller, float state)
{
bool isTriple = _game.IsTripleBeat(caller.startBeat + caller.timer);
StartJumping(caller.startBeat + caller.timer, false, state >= 1f || state <= -1f);
_game.BopTotemAtBeat(caller.startBeat + caller.timer);
if (isTriple) _game.FallFrogAtBeat(caller.startBeat + caller.timer, 1);
if (state >= 1f || state <= -1f)
{
if (caller.startBeat + caller.timer >= _onPlayBeat) SoundByte.PlayOneShot("nearMiss");
return;
}
_jumpParticle.PlayScaledAsync(0.5f);
if (caller.startBeat + caller.timer >= _onPlayBeat) SoundByte.PlayOneShotGame(isTriple ? "totemClimb/totemlandb" : "totemClimb/totemland");
}
private void JustTripleEnter(PlayerActionEvent caller, float state)
{
TripleJumping(caller.startBeat + caller.timer, true, false, state >= 1f || state <= -1f);
_game.FallFrogAtBeat(caller.startBeat + caller.timer, -1);
if (state >= 1f || state <= -1f)
{
if (caller.startBeat + caller.timer >= _onPlayBeat) SoundByte.PlayOneShot("nearMiss");
return;
}
_jumpParticle.PlayScaledAsync(0.5f);
if (caller.startBeat + caller.timer >= _onPlayBeat) SoundByte.PlayOneShotGame("totemClimb/totemland");
}
private void JustTripleExit(PlayerActionEvent caller, float state)
{
TripleJumping(caller.startBeat + caller.timer, false, false, state >= 1f || state <= -1f);
_game.FallFrogAtBeat(caller.startBeat + caller.timer, 0);
if (state >= 1f || state <= -1f)
{
if (caller.startBeat + caller.timer >= _onPlayBeat) SoundByte.PlayOneShot("nearMiss");
return;
}
_jumpParticle.PlayScaledAsync(0.5f);
if (caller.startBeat + caller.timer >= _onPlayBeat) SoundByte.PlayOneShotGame("totemClimb/totemland");
}
private void JustHold(PlayerActionEvent caller, float state)
{
if (caller.startBeat + caller.timer >= _onPlayBeat) SoundByte.PlayOneShotGame("totemClimb/chargejump");
_game.HoldDragonAtBeat(caller.startBeat + caller.timer);
SwitchToNextState(HoldCo(caller.startBeat + caller.timer));
_anim.DoScaledAnimationAsync("Hold", 0.5f);
if (state >= 1f || state <= -1f)
{
if (caller.startBeat + caller.timer >= _onPlayBeat) SoundByte.PlayOneShot("nearMiss");
return;
}
}
private void JustRelease(PlayerActionEvent caller, float state)
{
HighJump(caller.startBeat + caller.timer, state >= 1f && state <= -1f);
_game.ReleaseDragonAtBeat(caller.startBeat + caller.timer);
if (caller.startBeat + caller.timer >= _onPlayBeat) SoundByte.PlayOneShotGame("totemClimb/superjumpgood");
if (state >= 1f || state <= -1f)
{
if (caller.startBeat + caller.timer >= _onPlayBeat) SoundByte.PlayOneShot("nearMiss");
return;
}
_jumpParticle.PlayScaledAsync(0.5f);
}
private void Miss(PlayerActionEvent caller)
{
StartJumping(caller.startBeat + caller.timer, true);
_game.BopTotemAtBeat(caller.startBeat + caller.timer);
if (_game.IsTripleBeat(caller.startBeat + caller.timer)) _game.FallFrogAtBeat(caller.startBeat + caller.timer, 1);
if (caller.startBeat + caller.timer >= _onPlayBeat) SoundByte.PlayOneShot("miss");
}
private void MissTripleEnter(PlayerActionEvent caller)
{
TripleJumping(caller.startBeat + caller.timer, true, true);
_game.FallFrogAtBeat(caller.startBeat + caller.timer, -1);
if (caller.startBeat + caller.timer >= _onPlayBeat) SoundByte.PlayOneShot("miss");
}
private void MissTripleExit(PlayerActionEvent caller)
{
TripleJumping(caller.startBeat + caller.timer, false, true);
_game.FallFrogAtBeat(caller.startBeat + caller.timer, 0);
if (caller.startBeat + caller.timer >= _onPlayBeat) SoundByte.PlayOneShot("miss");
}
private void MissRelease(PlayerActionEvent caller)
{
HighJump(caller.startBeat + caller.timer, true);
_game.ReleaseDragonAtBeat(caller.startBeat + caller.timer);
if (caller.startBeat + caller.timer >= _onPlayBeat) SoundByte.PlayOneShot("miss");
}
private void Empty(PlayerActionEvent caller) { }
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3d5cda388abec014e89845a44e2a9ab4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,173 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using HeavenStudio.Util;
namespace HeavenStudio.Games.Scripts_TotemClimb
{
public class TCPillarManager : MonoBehaviour
{
private const int PILLAR_AMOUNT_X = 12;
private const int PILLAR_AMOUNT_Y = 3;
[Header("Components")]
[SerializeField] private Transform _pillarFirst;
[SerializeField] private Transform _pillarSecond;
[SerializeField] private Transform _pillarUp;
private List<List<Transform>> _pillars = new();
private Transform _scrollTransform;
private float _pillarDistanceX;
private float _pillarStartX;
private float _pillarDistanceY;
private float _pillarStartY;
private int _pillarIndexX = 0;
private int _pillarIndexY = 0;
private float _endDistance = float.MaxValue;
private bool _hasReachedEnd = false;
private void Awake()
{
gameObject.SetActive(!GetStartBeatParam());
_scrollTransform = transform.parent;
_endDistance = ((float)GetBeatDistance() * 1.45f) + _pillarStartY;
_pillarStartX = _pillarFirst.localPosition.x;
_pillarDistanceX = _pillarSecond.localPosition.x - _pillarFirst.localPosition.x;
_pillarStartY = _pillarFirst.localPosition.y;
_pillarDistanceY = _pillarUp.localPosition.y - _pillarFirst.localPosition.y;
for (int i = 0; i < PILLAR_AMOUNT_Y; i++) _pillars.Add(new());
_pillars[0].Add(_pillarFirst);
_pillars[0].Add(_pillarSecond);
_pillars[1].Add(_pillarUp);
if (_pillarFirst.localPosition.y + _pillarDistanceY >= _endDistance)
{
_pillarFirst.GetChild(0).gameObject.SetActive(true);
_pillarSecond.GetChild(0).gameObject.SetActive(true);
_pillarUp.gameObject.SetActive(false);
}
else if (_pillarUp.localPosition.y + _pillarDistanceY >= _endDistance)
{
_pillarUp.GetChild(0).gameObject.SetActive(true);
}
for (int i = 0; i < PILLAR_AMOUNT_Y; i++)
{
if (_hasReachedEnd) break;
for (int j = 0; j < PILLAR_AMOUNT_X; j++)
{
if (_pillars.ElementAtOrDefault(i).ElementAtOrDefault(j) != null) continue;
Transform spawnedPillar = Instantiate(_pillarFirst, transform);
spawnedPillar.localPosition = new Vector3(_pillarStartX + (_pillarDistanceX * j), spawnedPillar.localPosition.y + (_pillarDistanceY * i));
_pillars[i].Add(spawnedPillar);
if (spawnedPillar.localPosition.y + _pillarDistanceY >= _endDistance)
{
spawnedPillar.GetChild(0).gameObject.SetActive(true);
_hasReachedEnd = true;
}
}
}
}
private void Update()
{
PillarUpdate();
}
private void PillarUpdate()
{
float currentScrollX = _scrollTransform.localPosition.x;
float currentDistanceX = _pillarStartX + (_pillarDistanceX * _pillarIndexX);
if (currentScrollX >= currentDistanceX + (_pillarDistanceX * PILLAR_AMOUNT_X / 2))
{
foreach (var pillarRow in _pillars)
{
if (pillarRow.Count <= _pillarIndexX % PILLAR_AMOUNT_X) continue;
var p = pillarRow[_pillarIndexX % PILLAR_AMOUNT_X];
if (p == null) continue;
p.localPosition = new Vector3(p.localPosition.x + (_pillarDistanceX * PILLAR_AMOUNT_X), p.localPosition.y);
}
_pillarIndexX++;
PillarUpdate();
}
if (_hasReachedEnd) return;
float currentScrollY = _scrollTransform.localPosition.y;
float currentDistanceY = _pillarStartY + (_pillarDistanceY * _pillarIndexY) + (_pillarDistanceY * PILLAR_AMOUNT_Y / 2);
if (currentScrollY >= currentDistanceY)
{
foreach (var p in _pillars[_pillarIndexY % PILLAR_AMOUNT_Y])
{
if (p == null) continue;
p.localPosition = new Vector3(p.localPosition.x, p.localPosition.y + (_pillarDistanceY * PILLAR_AMOUNT_Y));
if (currentDistanceY + _pillarDistanceY >= _endDistance)
{
p.GetChild(0).gameObject.SetActive(true);
_hasReachedEnd = true;
}
}
_pillarIndexY++;
PillarUpdate();
}
}
private double GetBeatDistance()
{
var allGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat <= Conductor.instance.songPositionInBeatsAsDouble && x.datamodel is "gameManager/switchGame/totemClimb");
double lastGameSwitchBeat = 0;
if (allGameSwitches.Count > 0) lastGameSwitchBeat = allGameSwitches[^1].beat;
var nextGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat > lastGameSwitchBeat && x.datamodel != "gameManager/switchGame/totemClimb");
double nextGameSwitchBeat = double.MaxValue;
if (nextGameSwitches.Count > 0)
{
nextGameSwitchBeat = nextGameSwitches[0].beat;
}
var allStarts = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "start" }).FindAll(x => x.beat >= lastGameSwitchBeat && x.beat < nextGameSwitchBeat);
if (allStarts.Count == 0) return double.MaxValue;
double startBeat = allStarts[0].beat;
var allPillarEnds = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "above" }).FindAll(x => x.beat >= startBeat && x.beat < nextGameSwitchBeat);
if (allPillarEnds.Count == 0) return double.MaxValue;
return allPillarEnds[0].beat - startBeat;
}
private bool GetStartBeatParam()
{
var allGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat <= Conductor.instance.songPositionInBeatsAsDouble && x.datamodel is "gameManager/switchGame/totemClimb");
double lastGameSwitchBeat = 0;
if (allGameSwitches.Count > 0) lastGameSwitchBeat = allGameSwitches[^1].beat;
var nextGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat > lastGameSwitchBeat && x.datamodel != "gameManager/switchGame/totemClimb");
double nextGameSwitchBeat = double.MaxValue;
if (nextGameSwitches.Count > 0)
{
nextGameSwitchBeat = nextGameSwitches[0].beat;
}
var allStarts = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "start" }).FindAll(x => x.beat >= lastGameSwitchBeat && x.beat < nextGameSwitchBeat);
if (allStarts.Count == 0) return false;
return allStarts[0]["hide"];
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 99aece23798354a489e4efc915601eab
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,22 @@
using HeavenStudio.Util;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace HeavenStudio.Games.Scripts_TotemClimb
{
public class TCTotem : MonoBehaviour
{
[NonSerialized] public double beat;
[SerializeField] private Animator _anim;
[SerializeField] private Transform _jumperPoint;
public Transform JumperPoint => _jumperPoint;
public void Bop()
{
_anim.DoScaledAnimationAsync("Bop", 0.5f);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 494645cb1b3cdeb418bae2a7e19fd269
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,250 @@
using HeavenStudio.Util;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace HeavenStudio.Games.Scripts_TotemClimb
{
public class TCTotemManager : MonoBehaviour
{
[SerializeField] private Transform _totemTransform;
[SerializeField] private Transform _frogTransform;
[SerializeField] private Transform _endTotemTransform;
[SerializeField] private Animator _endTotemAnimator;
[SerializeField] private Transform _endJumperPoint;
[SerializeField] private ParticleSystem _endParticleLeft;
[SerializeField] private ParticleSystem _endParticleRight;
[SerializeField] private TCDragon _dragon;
[SerializeField] private float _xDistance;
[SerializeField] private float _yDistance;
[SerializeField] private int _totemAmount = 12;
private Transform _scrollTransform;
private float _totemStartX;
private float _totemStartY;
private List<TCTotem> _totems = new();
private List<TCFrog> _frogs = new();
private List<TCDragon> _dragons = new();
private int _totemIndex = 0;
private float _pillarEndDistance;
private bool _usingEndTotem = false;
public Transform EndJumperPoint => _endJumperPoint;
public Animator EndTotemAnimator => _endTotemAnimator;
private TotemClimb _game;
private void Awake()
{
_game = TotemClimb.instance;
_scrollTransform = transform.parent;
_totemStartX = _totemTransform.localPosition.x;
_totemStartY = _totemTransform.localPosition.y;
var pillarEnd = GetPillarEndBeatDistance();
_pillarEndDistance = pillarEnd;
_totems.Add(_totemTransform.GetComponent<TCTotem>());
for (int i = 1; i < _totemAmount; i++)
{
Transform spawnedTotem = Instantiate(_totemTransform, transform);
spawnedTotem.transform.localPosition = new Vector3(_totemStartX + (_xDistance * i), _totemStartY + (_yDistance * i));
_totems.Add(spawnedTotem.GetComponent<TCTotem>());
}
}
public void InitBeats(double startBeat, double endBeat, bool useEndTotem)
{
_usingEndTotem = useEndTotem;
for (int i = 0; i < _totems.Count; i++)
{
_totems[i].beat = startBeat + i;
_totems[i].transform.gameObject.SetActive(_totems[i].beat - (_usingEndTotem ? 0 : 1) < _game.EndBeat && !_game.IsTripleOrHighBeat(_totems[i].beat));
}
bool startBeatParam = GetStartBeatParam();
foreach (var e in _game._tripleEvents)
{
for (int i = 0; i < e.length; i += 2)
{
double beat = e.beat + i;
Transform spawnedFrog = Instantiate(_frogTransform, transform);
spawnedFrog.transform.localPosition += new Vector3(_xDistance * (float)(beat - startBeat), _yDistance * (float)(beat - startBeat));
if (spawnedFrog.transform.localPosition.y >= _pillarEndDistance || startBeatParam) spawnedFrog.GetComponent<TCFrog>().SetHasWings();
spawnedFrog.gameObject.SetActive(true);
spawnedFrog.GetComponent<TCFrog>().beat = beat;
_frogs.Add(spawnedFrog.GetComponent<TCFrog>());
}
}
foreach (var e in _game._highJumpEvents)
{
double beat = e.beat;
TCDragon spawnedDragon = Instantiate(_dragon, transform);
spawnedDragon.transform.localPosition += new Vector3(_xDistance * (float)(beat - startBeat), _yDistance * (float)(beat - startBeat));
spawnedDragon.gameObject.SetActive(true);
spawnedDragon.beat = beat;
_dragons.Add(spawnedDragon);
}
if (useEndTotem)
{
_endTotemTransform.gameObject.SetActive(true);
_endTotemTransform.localPosition += new Vector3(_xDistance * (float)(endBeat - startBeat), _yDistance * (float)(endBeat - startBeat));
}
}
public void ActivateEndParticles()
{
_endParticleLeft.PlayScaledAsync(0.5f);
_endParticleRight.PlayScaledAsync(0.5f);
}
public void BopTotemAtBeat(double beat)
{
var t = _totems.Find(x => x.beat == beat);
if (t == null) return;
t.Bop();
}
public Transform GetJumperPointAtBeat(double beat)
{
var t = _totems.Find(x => x.beat == beat);
if (t == null)
{
Debug.Log($"Jumper Point unavaible at beat {beat}.");
return null;
}
return t.JumperPoint;
}
public Transform GetJumperFrogPointAtBeat(double beat, int part)
{
var f = _frogs.Find(x => beat >= x.beat && beat < x.beat + 2);
if (f == null)
{
Debug.Log($"Jumper Frog Point unavaible at beat {beat}.");
return null;
}
switch (part)
{
case -1:
return f.JumperPointLeft;
case 0:
return f.JumperPointMiddle;
default:
return f.JumperPointRight;
}
}
public void FallFrogAtBeat(double beat, int part)
{
var f = _frogs.Find(x => beat >= x.beat && beat < x.beat + 2);
if (f == null)
{
Debug.Log($"Frog unavaible at beat {beat}.");
return;
}
f.FallPiece(part);
}
public Transform GetHighJumperPointAtBeat(double beat)
{
var d = _dragons.Find(x => beat >= x.beat && beat < x.beat + 4);
if (d == null)
{
Debug.Log($"Jumper Dragon Point unavaible at beat {beat}.");
return null;
}
return d.JumperPoint;
}
public void HoldDragonAtBeat(double beat)
{
var d = _dragons.Find(x => beat >= x.beat && beat < x.beat + 4);
if (d == null)
{
Debug.Log($"Dragon unavaible at beat {beat}.");
return;
}
d.Hold();
}
public void ReleaseDragonAtBeat(double beat)
{
var d = _dragons.Find(x => beat >= x.beat && beat < x.beat + 4);
if (d == null)
{
Debug.Log($"Dragon unavaible at beat {beat}.");
return;
}
d.Release();
}
private void Update()
{
float currentScrollX = _scrollTransform.localPosition.x;
float currentDistanceX = _totemStartX + (_xDistance * _totemIndex);
if (currentScrollX >= currentDistanceX + (_xDistance * _totemAmount / 2))
{
var t = _totems[_totemIndex % _totemAmount];
t.transform.localPosition = new Vector3(t.transform.localPosition.x + (_xDistance * _totemAmount), t.transform.localPosition.y + (_yDistance * _totemAmount));
t.beat += _totemAmount;
t.transform.gameObject.SetActive(t.beat - (_usingEndTotem ? 0 : 1) < _game.EndBeat && !_game.IsTripleOrHighBeat(t.beat));
_totemIndex++;
}
}
private float GetPillarEndBeatDistance()
{
var allGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat <= Conductor.instance.songPositionInBeatsAsDouble && x.datamodel is "gameManager/switchGame/totemClimb");
double lastGameSwitchBeat = 0;
if (allGameSwitches.Count > 0) lastGameSwitchBeat = allGameSwitches[^1].beat;
var nextGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat > lastGameSwitchBeat && x.datamodel != "gameManager/switchGame/totemClimb");
double nextGameSwitchBeat = double.MaxValue;
if (nextGameSwitches.Count > 0)
{
nextGameSwitchBeat = nextGameSwitches[0].beat;
}
var allStarts = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "start" }).FindAll(x => x.beat >= lastGameSwitchBeat && x.beat < nextGameSwitchBeat);
if (allStarts.Count == 0) return float.MaxValue;
double startBeat = allStarts[0].beat;
var allPillarEnds = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "above" }).FindAll(x => x.beat >= startBeat && x.beat < nextGameSwitchBeat);
if (allPillarEnds.Count == 0) return float.MaxValue;
return (float)(allPillarEnds[0].beat - startBeat) * 1.45f;
}
private bool GetStartBeatParam()
{
var allGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat <= Conductor.instance.songPositionInBeatsAsDouble && x.datamodel is "gameManager/switchGame/totemClimb");
double lastGameSwitchBeat = 0;
if (allGameSwitches.Count > 0) lastGameSwitchBeat = allGameSwitches[^1].beat;
var nextGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat > lastGameSwitchBeat && x.datamodel != "gameManager/switchGame/totemClimb");
double nextGameSwitchBeat = double.MaxValue;
if (nextGameSwitches.Count > 0)
{
nextGameSwitchBeat = nextGameSwitches[0].beat;
}
var allStarts = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "start" }).FindAll(x => x.beat >= lastGameSwitchBeat && x.beat < nextGameSwitchBeat);
if (allStarts.Count == 0) return false;
return allStarts[0]["hide"];
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 09d47a9ccd9cfbe419ae4739d230b1df
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,567 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using HeavenStudio.Util;
using HeavenStudio.Games.Scripts_TotemClimb;
using Jukebox;
using System;
namespace HeavenStudio.Games.Loaders
{
using static Minigames;
public static class TotemClimbLoader
{
public static Minigame AddGame(EventCaller eventCaller)
{
return new Minigame("totemClimb", "Totem Climb", "FFFFFF", false, false, new()
{
new("start", "Start Jumping")
{
preFunction = delegate { if (eventCaller.currentEntity["cue"]) TotemClimb.StartCueIn(eventCaller.currentEntity.beat); },
parameters = new List<Param>()
{
new("cue", true, "Cue-In"),
new("hide", false, "Hide Fence")
}
},
new("triple", "Triple Jumping")
{
preFunction = delegate
{
var e = eventCaller.currentEntity;
TotemClimb.TripleJumpSound(e.beat, e.length, e["enter"], e["exit"]);
},
defaultLength = 2f,
resizable = true,
parameters = new()
{
new("enter", true, "Enter Cue Sound"),
new("exit", true, "Exit Cue Sound"),
}
},
new("high", "High Jump")
{
preFunction = delegate
{
double beat = eventCaller.currentEntity.beat;
MultiSound.Play(new MultiSound.Sound[]
{
new MultiSound.Sound("count-ins/ready1", beat - 2f),
new MultiSound.Sound("count-ins/ready2", beat - 1f),
}, false, true);
},
defaultLength = 4f
},
new("startCue", "Normal Jump Cue")
{
preFunction = delegate
{
TotemClimb.StartCueIn(eventCaller.currentEntity.beat + 2);
},
defaultLength = 2f
},
new("tripleCue", "Triple Jump Cue")
{
preFunction = delegate
{
TotemClimb.TripleCueIn(eventCaller.currentEntity.beat + 2);
},
defaultLength = 2f
},
new("bird", "Bird")
{
function = delegate
{
var e = eventCaller.currentEntity;
TotemClimb.instance.SpawnBird(e["speed"], (TotemClimb.BirdType)e["type"] == TotemClimb.BirdType.Penguin, e["amount"]);
},
parameters = new List<Param>()
{
new("speed", new EntityTypes.Float(1, 100, 3), "Speed Multiplier"),
new("type", TotemClimb.BirdType.KingFisher, "Type"),
new("amount", new EntityTypes.Integer(1, 3, 1), "Amount")
}
},
new("above", "Fences End")
{
},
new("stop", "Stop Jumping")
{
parameters = new List<Param>()
{
new("anim", true, "Has Ending Animation")
}
},
new("bop", "Bop")
{
function = delegate { TotemClimb.instance.Bop(eventCaller.currentEntity.beat, eventCaller.currentEntity.length, eventCaller.currentEntity.beat); },
resizable = true,
defaultLength = 4f
}
});
}
}
}
namespace HeavenStudio.Games
{
public class TotemClimb : Minigame
{
public enum BirdType
{
KingFisher,
Penguin
}
[Header("Components")]
[SerializeField] private Transform _cameraTransform;
[SerializeField] private Transform _scrollTransform;
[SerializeField] private TCJumper _jumper;
[SerializeField] private TCTotemManager _totemManager;
[SerializeField] private TCBirdManager _birdManager;
[Header("Properties")]
[SerializeField] private float _scrollSpeedX = 3.838f;
[SerializeField] private float _scrollSpeedY = 1.45f;
private double _startBeat = double.MaxValue;
public double StartBeat => _startBeat;
private double _endBeat = double.MaxValue;
public double EndBeat => _endBeat;
private double _pillarEndBeat = double.MaxValue;
public double PillarEndBeat => _pillarEndBeat;
private bool _useEndTotem = false;
public bool UseEndTotem => _useEndTotem;
[NonSerialized] public List<RiqEntity> _tripleEvents = new();
[NonSerialized] public List<RiqEntity> _highJumpEvents = new();
public static TotemClimb instance;
private void Awake()
{
instance = this;
}
public void SpawnBird(float speed, bool penguin, int amount)
{
_birdManager.AddBird(speed, penguin, amount);
}
public override void OnGameSwitch(double beat)
{
CalculateStartAndEndBeat(beat);
GetHighJumpEvents();
GetTripleEvents();
HandleBopsOnStart(beat);
_totemManager.InitBeats(_startBeat, _endBeat, _useEndTotem);
_jumper.InitPath(_startBeat, beat);
}
public override void OnPlay(double beat)
{
var allGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat <= beat && x.datamodel is "gameManager/switchGame/totemClimb");
double lastGameSwitchBeat = 0;
if (allGameSwitches.Count > 0) lastGameSwitchBeat = allGameSwitches[^1].beat;
CalculateStartAndEndBeat(lastGameSwitchBeat);
GetHighJumpEvents();
GetTripleEvents();
HandleBopsOnStart(beat);
_totemManager.InitBeats(_startBeat, _endBeat, _useEndTotem);
_jumper.InitPath(_startBeat, beat);
}
private void CalculateStartAndEndBeat(double beat)
{
var nextGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat > beat && x.datamodel != "gameManager/switchGame/totemClimb");
double nextGameSwitchBeat = double.MaxValue;
if (nextGameSwitches.Count > 0)
{
nextGameSwitchBeat = nextGameSwitches[0].beat;
}
var allStarts = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "start" }).FindAll(x => x.beat >= beat && x.beat < nextGameSwitchBeat);
if (allStarts.Count == 0) return;
_startBeat = allStarts[0].beat;
BeatAction.New(this, new()
{
new(_startBeat - 1, delegate { _jumper.StartJumping(_startBeat - 1); })
});
var allPillarEnds = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "above" }).FindAll(x => x.beat >= _startBeat && x.beat < nextGameSwitchBeat);
if (allPillarEnds.Count > 0) _pillarEndBeat = allPillarEnds[0].beat;
var allStops = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "stop" }).FindAll(x => x.beat > _startBeat && x.beat < nextGameSwitchBeat);
if (allStops.Count == 0) return;
_endBeat = allStops[0].beat;
_useEndTotem = allStops[0]["anim"];
}
private void HandleBopsOnStart(double beat)
{
var e = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "bop" }).Find(x => x.beat < beat && x.beat + x.length > beat);
if (e == null) return;
Bop(e.beat, e.length, beat);
}
private void GetHighJumpEvents()
{
var highs = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "high" }).FindAll(x => x.beat >= _startBeat && x.beat < _endBeat);
if (highs.Count == 0) return;
highs.Sort((x, y) => x.beat.CompareTo(y.beat));
var tempHighs = new List<RiqEntity>();
double goodAfterBeat = _startBeat;
foreach (var h in highs)
{
if (h.beat >= goodAfterBeat && IsOnBeat(_startBeat, h.beat))
{
tempHighs.Add(h);
goodAfterBeat = h.beat + 4;
}
}
_highJumpEvents = tempHighs;
}
private void GetTripleEvents()
{
var triples = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "triple" }).FindAll(x => x.beat >= _startBeat && x.beat + x.length <= _endBeat);
if (triples.Count == 0) return;
triples.Sort((x, y) => x.beat.CompareTo(y.beat));
var tempTriples = new List<RiqEntity>();
double lastLengthBeat = _startBeat;
foreach (var t in triples)
{
if (t.beat >= lastLengthBeat && IsOnBeat(_startBeat, t.beat))
{
if (_highJumpEvents.Find(x => x.beat + 4f > t.beat && x.beat + 4 < t.beat + t.length + 4) != null) continue;
tempTriples.Add(t);
lastLengthBeat = t.beat + t.length;
}
}
_tripleEvents = tempTriples;
}
private void Update()
{
var cond = Conductor.instance;
ScrollUpdate(cond);
}
public void BopTotemAtBeat(double beat)
{
_totemManager.BopTotemAtBeat(beat);
}
public Transform GetJumperPointAtBeat(double beat)
{
return _totemManager.GetJumperPointAtBeat(beat);
}
public Transform GetJumperFrogPointAtBeat(double beat, int part)
{
return _totemManager.GetJumperFrogPointAtBeat(beat, part);
}
public Transform GetDragonPointAtBeat(double beat)
{
return _totemManager.GetHighJumperPointAtBeat(beat);
}
public void HoldDragonAtBeat(double beat)
{
_totemManager.HoldDragonAtBeat(beat);
}
public void ReleaseDragonAtBeat(double beat)
{
_totemManager.ReleaseDragonAtBeat(beat);
}
public void FallFrogAtBeat(double beat, int part)
{
_totemManager.FallFrogAtBeat(beat, part);
}
public void Bop(double beat, float length, double callBeat)
{
List<BeatAction.Action> actions = new();
for (int i = 0; i < length; i++)
{
double bopBeat = beat + i;
if (bopBeat < callBeat) continue;
actions.Add(new(bopBeat, delegate
{
BopJumper(bopBeat);
}));
}
if (actions.Count > 0) BeatAction.New(this, actions);
}
private void BopJumper(double beat)
{
if (beat >= _startBeat && beat < _endBeat) return;
_jumper.Bop();
}
private void ScrollUpdate(Conductor cond)
{
if (_startBeat == double.MaxValue) return;
double beatDistance = _endBeat - _startBeat;
float normalizedBeat = Mathf.Clamp(cond.GetPositionFromBeat(_startBeat, 1), 0f, (float)beatDistance);
if (IsHighBeatBasedOnStart(normalizedBeat))
{
var h = GetHighJumpAtBeatBasedOnStart(normalizedBeat);
if (h != null)
{
double highBeat = h.beat - _startBeat;
if (normalizedBeat >= highBeat + 2)
{
normalizedBeat = Mathf.Clamp(normalizedBeat - 2 + (cond.GetPositionFromBeat(h.beat + 2, 2) * 2), (float)highBeat, (float)highBeat + 4);
}
else if (normalizedBeat >= highBeat)
{
normalizedBeat = Mathf.Clamp(normalizedBeat, 0f, (float)highBeat);
}
}
}
_scrollTransform.localPosition = new Vector3(normalizedBeat * _scrollSpeedX, normalizedBeat * _scrollSpeedY);
_cameraTransform.localPosition = new Vector3(_scrollTransform.localPosition.x * -2, _scrollTransform.localPosition.y * -2);
}
private static bool IsOnBeat(double startBeat, double targetBeat)
{
return (targetBeat - startBeat) % 1 == 0;
}
public bool IsTripleBeat(double beat)
{
if (_tripleEvents.Count == 0) return false;
return _tripleEvents.Find(x => beat >= x.beat && beat < x.beat + x.length) != null;
}
public bool IsHighBeat(double beat)
{
if (_highJumpEvents.Count == 0) return false;
return _highJumpEvents.Find(x => beat >= x.beat && beat < x.beat + 4) != null;
}
public bool IsHighBeatBasedOnStart(double beat)
{
if (_highJumpEvents.Count == 0) return false;
return _highJumpEvents.Find(x => beat >= x.beat - _startBeat && beat < x.beat - _startBeat + 4) != null;
}
public RiqEntity GetHighJumpAtBeatBasedOnStart(double beat)
{
if (_highJumpEvents.Count == 0) return null;
return _highJumpEvents.Find(x => beat >= x.beat - _startBeat && beat < x.beat - _startBeat + 4);
}
public bool IsTripleOrHighBeat(double beat)
{
return IsHighBeat(beat) || IsTripleBeat(beat);
}
public void DoEndTotemEvents(double beat)
{
SoundByte.PlayOneShotGame("totemClimb/finallanding", beat);
_totemManager.EndTotemAnimator.DoScaledAnimationAsync("Land", 0.5f);
SoundByte.PlayOneShotGame("totemClimb/openwings", beat + 1);
BeatAction.New(this, new()
{
new(beat + 1, delegate
{
_totemManager.EndTotemAnimator.DoScaledAnimationAsync("OpenWings", 0.5f);
})
});
}
public Transform EndJumperPoint => _totemManager.EndJumperPoint;
public static void StartCueIn(double beat)
{
MultiSound.Play(new MultiSound.Sound[]
{
new("totemClimb/beatchange", beat - 2),
new("totemClimb/beatchange", beat - 1),
}, true, true);
}
public static void TripleCueIn(double beat)
{
MultiSound.Play(new MultiSound.Sound[]
{
new("totemClimb/beatchange", beat - 2),
new("totemClimb/beatchange", beat - 1.5),
new("totemClimb/beatchange", beat - 1),
}, true, true);
}
public static void TripleJumpSound(double beat, float length, bool enterSound, bool exitSound)
{
if (!enterSound && !exitSound) return;
List<RiqEntity> triplesGlobal = new();
List<RiqEntity> highsGlobal = new();
length = Mathf.Max(length, 2f);
List<MultiSound.Sound> soundsEnter = new()
{
new("totemClimb/beatchange", beat - 2),
new("totemClimb/beatchange", beat - 1.5f),
new("totemClimb/beatchange", beat - 1f),
};
List<MultiSound.Sound> soundsToPlay = new();
var allGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat <= beat && x.datamodel is "gameManager/switchGame/totemClimb");
double lastGameSwitchBeat = 0;
if (allGameSwitches.Count > 0) lastGameSwitchBeat = allGameSwitches[^1].beat;
SetUpEvents(lastGameSwitchBeat);
if (triplesGlobal.Count == 0) return;
bool doEnterSound = true;
double checkBeatEnter = beat - 1;
while (IsHighBeat(checkBeatEnter))
{
checkBeatEnter -= 4;
if (IsTripleBeat(checkBeatEnter))
{
doEnterSound = false;
}
}
if (doEnterSound && enterSound) soundsToPlay.AddRange(soundsEnter);
bool doExitSound = true;
double checkBeatExit = beat + length;
while (IsHighBeat(checkBeatExit))
{
checkBeatExit += 4;
if (IsTripleBeat(checkBeatExit))
{
doExitSound = false;
}
}
List<MultiSound.Sound> soundsExit = new()
{
new("totemClimb/beatchange", checkBeatExit - 2),
new("totemClimb/beatchange", checkBeatExit - 1),
};
if (doExitSound && exitSound) soundsToPlay.AddRange(soundsExit);
if (soundsToPlay.Count > 0) MultiSound.Play(soundsToPlay.ToArray(), true, true);
void SetUpEvents(double beat)
{
double startBeat = double.MaxValue;
double endBeat = double.MaxValue;
var nextGameSwitches = EventCaller.GetAllInGameManagerList("gameManager", new string[] { "switchGame" }).FindAll(x => x.beat > beat && x.datamodel != "gameManager/switchGame/totemClimb");
double nextGameSwitchBeat = double.MaxValue;
if (nextGameSwitches.Count > 0)
{
nextGameSwitchBeat = nextGameSwitches[0].beat;
}
var allStarts = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "start" }).FindAll(x => x.beat >= beat && x.beat < nextGameSwitchBeat);
if (allStarts.Count > 0)
{
startBeat = allStarts[0].beat;
}
var allStops = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "stop" }).FindAll(x => x.beat > startBeat && x.beat < nextGameSwitchBeat);
if (allStops.Count > 0)
{
endBeat = allStops[0].beat;
}
var highs = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "high" }).FindAll(x => x.beat >= startBeat && x.beat < endBeat);
if (highs.Count > 0)
{
highs.Sort((x, y) => x.beat.CompareTo(y.beat));
var tempHighs = new List<RiqEntity>();
double goodAfterBeat = startBeat;
foreach (var h in highs)
{
if (h.beat >= goodAfterBeat && IsOnBeat(startBeat, h.beat))
{
tempHighs.Add(h);
goodAfterBeat = h.beat + 4;
}
}
highsGlobal = tempHighs;
}
var triples = EventCaller.GetAllInGameManagerList("totemClimb", new string[] { "triple" }).FindAll(x => x.beat >= startBeat && x.beat + x.length <= endBeat);
if (triples.Count == 0) return;
triples.Sort((x, y) => x.beat.CompareTo(y.beat));
var tempTriples = new List<RiqEntity>();
double lastLengthBeat = startBeat;
foreach (var t in triples)
{
if (t.beat >= lastLengthBeat && IsOnBeat(startBeat, t.beat))
{
if (highsGlobal.Find(x => x.beat + 4f > t.beat && x.beat + 4 < t.beat + t.length + 4) != null) continue;
tempTriples.Add(t);
lastLengthBeat = t.beat + t.length;
}
}
triplesGlobal = tempTriples;
}
bool IsTripleBeat(double beat)
{
if (triplesGlobal.Count == 0) return false;
return triplesGlobal.Find(x => beat >= x.beat && beat < x.beat + x.length) != null;
}
bool IsHighBeat(double beat)
{
if (highsGlobal.Count == 0) return false;
return highsGlobal.Find(x => beat >= x.beat && beat < x.beat + 4) != null;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6aac43315a1bc47429ebddacaa0a6f05
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -33,6 +33,7 @@ namespace HeavenStudio.Editor
// This two are from unity answer (I mixed up)
public void CreateWaveForm()
{
if (audio == null || audio.clip == null) return;
resolution = audio.clip.frequency / resolution;
samples = new float[audio.clip.samples * audio.clip.channels];