Skip to content

Commit

Permalink
Recorded Player class
Browse files Browse the repository at this point in the history
  • Loading branch information
Raoul1808 committed Sep 26, 2022
1 parent a4f59ae commit 7d8ffe0
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 32 deletions.
157 changes: 157 additions & 0 deletions Entities/RecordedPlayer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
using System;
using Celeste;
using Monocle;
using System.Collections.Generic;
using Microsoft.Xna.Framework;

namespace RecordingStations.Entities
{
public class RecordedPlayer : Actor
{
public bool IsDone;
public List<Player.ChaserState> Timeline;

private PlayerSprite _playerSprite;
private PlayerHair _playerHair;

private int _frameIndex;
private float _currentTime;
private float _endTime;

private int FrameCount => Timeline.Count;

public RecordedPlayer(Vector2 position, List<Player.ChaserState> timeline) : base(position)
{
Depth = 9008;
Timeline = timeline;
Position = position;
_frameIndex = 0;
_currentTime = timeline[0].TimeStamp;
_endTime = timeline[FrameCount - 1].TimeStamp;
_playerSprite = new PlayerSprite(PlayerSpriteMode.Playback);
Add(_playerHair = new PlayerHair(_playerSprite));
Add(_playerSprite);
for (int index = 0; index < 10; ++index)
_playerHair.AfterUpdate();
Collider = new Hitbox(8f, 11f, -4f, -11f);
Add(new PlayerCollider(OnBouncePlayer));

PlaySound("appear");
}

private void OnBouncePlayer(Player player)
{
if (player.StateMachine.State == Player.StNormal && player.Speed.Y > 0f && player.Bottom <= Top + 3f)
{
Dust.Burst(player.BottomCenter, -1.57079637f, 8);
((Level) Scene).DirectionalShake(Vector2.UnitY, 0.05f);
Input.Rumble(RumbleStrength.Light, RumbleLength.Medium);
player.Bounce(Top + 2f);
player.Play("event:/game/general/thing_booped");
}
}

public override void Removed(Scene scene)
{
PlaySound("disappear");
base.Removed(scene);
}

public override void Update()
{
// Note: Most (if not all) the code present in this function
// was taken from the PlayerPlayback class.
// I tried inheriting from this class directly, without any success,
// thus completely remaking it in the mod.

if (Scene == null)
return;

_currentTime += Engine.DeltaTime;
base.Update();
if (_frameIndex >= FrameCount - 1 || _currentTime >= _endTime)
{
RemoveSelf();
}

var currentState = Timeline[_frameIndex];
bool wasOnGround = CollideCheck<Solid>(Position - Vector2.UnitY);
Position = currentState.Position;
_playerSprite.Scale = currentState.Scale;
string previousAnimationId = _playerSprite.CurrentAnimationID;
if (currentState.Animation != _playerSprite.CurrentAnimationID && currentState.Animation != null && _playerSprite.Has(currentState.Animation))
_playerSprite.Play(currentState.Animation, true);
string currentAnimationId = _playerSprite.CurrentAnimationID;
if (_playerSprite.Scale.X != 0.0f)
_playerHair.Facing = (Facings) Math.Sign(_playerSprite.Scale.X);
_playerSprite.Color = _playerHair.Color = currentState.HairColor;

if (!wasOnGround && CollideCheck<Solid>(Position - Vector2.UnitY))
PlaySound("land");

if (previousAnimationId != currentAnimationId)
{
// Handle sounds
int frame = _playerSprite.CurrentAnimationFrame;
switch (currentAnimationId)
{
// Jump
case "jumpFast":
case "jumpSlow":
PlaySound("jump");
break;

// Dreamblock
case "dreamDashIn":
PlaySound("dreamblock_sequence");
break;

// Dash
// TODO: second dash?
case "dash":
PlaySound(currentState.Scale.X > 0.0f ? "dash_red_right" : "dash_red_left");
break;

// Climb
case "climbUp":
case "climbDown":
case "wallslide":
PlaySound("grab");
break;

// Normal walk cases
case "runSlow_carry":
case "runFast":
case "runSlow":
case "walk":
case "runWind":
case "carryTheoWalk":
if (frame == 0 || frame == 6)
PlaySound("footstep");
break;

// Special walk cases
case "flip" when frame == 4:
case "runStumble" when frame == 6:
case "push" when frame == 8 || frame == 15:
case "idleC" when _playerSprite.Mode == PlayerSpriteMode.MadelineNoBackpack &&
(frame == 3 || frame == 6 || frame == 8 || frame == 11):
PlaySound("footstep");
break;
}
}

while (_frameIndex < FrameCount - 1 && _currentTime >= Timeline[_frameIndex + 1].TimeStamp)
_frameIndex++;

if (!Scene.OnInterval(0.1f))
return;
TrailManager.Add(Position, _playerSprite, _playerHair, _playerSprite.Scale, _playerHair.Color, Depth + 1);
}

private void PlaySound(string id)
{
Audio.Play("event:/new_content/char/tutorial_ghost/" + id, Position);
}
}
}
58 changes: 57 additions & 1 deletion Entities/RecordingStation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using Celeste.Mod.Entities;
using Microsoft.Xna.Framework;
using Monocle;
using System.Collections.Generic;
using Celeste.Mod;

namespace RecordingStations.Entities
{
Expand All @@ -11,7 +13,19 @@ namespace RecordingStations.Entities
[CustomEntity("RecordingStations/RecordingStation")]
public class RecordingStation : Entity
{
public enum RecordingMode
{
Idle,
Recording,
Playback,
}

public TalkComponent InteractComponent;

public static RecordingMode CurrentMode { get; private set; } = RecordingMode.Idle;

private static List<Player.ChaserState> _recordedStates = new List<Player.ChaserState>();
private static RecordedPlayer _playerPlayback = null;

public RecordingStation(EntityData data, Vector2 offset)
: base (data.Position + offset)
Expand All @@ -28,9 +42,51 @@ public RecordingStation(EntityData data, Vector2 offset)
Add(image);
}

public static void PlayerRecord(On.Celeste.Player.orig_Update orig, Player player)
{
if (CurrentMode == RecordingMode.Recording)
{
_recordedStates.Add(new Player.ChaserState(player));
}
orig(player);
}

public void Interact(Player player)
{
RecordingSystem.AdvanceNext();
NextRecordingMode();
}

public static void NextRecordingMode()
{
CurrentMode++;
if (CurrentMode > RecordingMode.Playback)
CurrentMode = RecordingMode.Idle;

Logger.Log("RecStation", "Changed state to " + CurrentMode);

switch (CurrentMode)
{
case RecordingMode.Idle:
Cleanup();
break;

case RecordingMode.Playback:
PlayBack();
break;
}
}

private static void Cleanup()
{
if (_playerPlayback != null)
Engine.Scene.Remove(_playerPlayback);
_recordedStates.Clear();
}

private static void PlayBack()
{
Logger.Log("RecPlayback", "Playing back " + _recordedStates.Count + " frames");
Engine.Scene.Add(_playerPlayback = new RecordedPlayer(_recordedStates[0].Position, _recordedStates));
}
}
}
2 changes: 1 addition & 1 deletion RecordingStations.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Entities\RecordedPlayer.cs" />
<Compile Include="Entities\RecordingStation.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RecordingStationsModule.cs" />
<Compile Include="RecordingSystem.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Ahorn\entities\recordingStation.jl" />
Expand Down
5 changes: 3 additions & 2 deletions RecordingStationsModule.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Celeste.Mod;
using RecordingStations.Entities;

namespace RecordingStations
{
Expand All @@ -16,12 +17,12 @@ public RecordingStationsModule()

public override void Load()
{
Logger.Log("RecStation", "Hello from RecordingStationsModule!");
On.Celeste.Player.Update += RecordingStation.PlayerRecord;
}

public override void Unload()
{
Logger.Log("RecStation", "Goodbye from RecordingStationsModule!");
On.Celeste.Player.Update -= RecordingStation.PlayerRecord;
}
}
}
28 changes: 0 additions & 28 deletions RecordingSystem.cs

This file was deleted.

0 comments on commit 7d8ffe0

Please sign in to comment.