-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
1,099 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[submodule "Everest"] | ||
path = Everest | ||
url = https://github.com/EverestAPI/Everest.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio 14 | ||
VisualStudioVersion = 14.0.25420.1 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GhostMod", "GhostMod\GhostMod.csproj", "{4ABF8C07-C533-407E-9EC9-534C2916C907}" | ||
EndProject | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Celeste.Mod.mm", "Everest\Celeste.Mod.mm\Celeste.Mod.mm.csproj", "{D5D0239D-FF95-4897-9484-1898AB7E82F5}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{4ABF8C07-C533-407E-9EC9-534C2916C907}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{4ABF8C07-C533-407E-9EC9-534C2916C907}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{4ABF8C07-C533-407E-9EC9-534C2916C907}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{4ABF8C07-C533-407E-9EC9-534C2916C907}.Release|Any CPU.Build.0 = Release|Any CPU | ||
{D5D0239D-FF95-4897-9484-1898AB7E82F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{D5D0239D-FF95-4897-9484-1898AB7E82F5}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{D5D0239D-FF95-4897-9484-1898AB7E82F5}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{D5D0239D-FF95-4897-9484-1898AB7E82F5}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# NOTES: | ||
# The # Symbol at the start of a line counts as a Comment. To include in dialog, use a \# | ||
# The . Symbol will cause a pause unless escaped with \. (ex: Mr. Oshiro has a pause, Mr\. Oshiro does not) | ||
# Newlines automatically create a Page Break, unless there is an {n} command on the previous line | ||
# Commands: Anything inside of curly braces {...} is a command and should not be translated. | ||
|
||
# Inline Text Commands: | ||
# {~}wavy text{/~} | ||
# {!}impact text{/!} | ||
# {>> x}changes speed at which characters are displayed{>>} | ||
# {# 000000}this text is black{#} (uses HEX color values) | ||
# {+MENU_BEGIN} inserts the dialog from the MENU_BEGIN value (in English, "CLIMB") | ||
# {n} creates a newline, without a page break | ||
# {0.5} creates a 0.5 second pause | ||
# {big}this text is large{/big} | ||
|
||
# Gameplay Control Commands (should never change) | ||
# {trigger x} this triggers an in-game event | ||
# {anchor} controls the visual position of the textbox in-game | ||
|
||
# Ghost Module Options | ||
MODOPTIONS_GHOSTMODULE_TITLE= Ghost-eline | ||
MODOPTIONS_GHOSTMODULE_MODE= Mode | ||
MODOPTIONS_GHOSTMODULE_MODE_OFF= OFF | ||
MODOPTIONS_GHOSTMODULE_MODE_RECORD= RECORD | ||
MODOPTIONS_GHOSTMODULE_MODE_PLAY= PLAY | ||
MODOPTIONS_GHOSTMODULE_MODE_ON= BOTH | ||
MODOPTIONS_GHOSTMODULE_NAME= Ghost Name | ||
MODOPTIONS_GHOSTMODULE_SHOWOTHERNAMES= Show Other's Names | ||
MODOPTIONS_GHOSTMODULE_INNEROPACITY= Near Ghost Visibility | ||
MODOPTIONS_GHOSTMODULE_INNERHAIROPACITY= Near Ghost Hair Visibility | ||
MODOPTIONS_GHOSTMODULE_OUTEROPACITY= Far Ghost Visibility | ||
MODOPTIONS_GHOSTMODULE_OUTERHAIROPACITY= Far Ghost Hair Visibility | ||
MODOPTIONS_GHOSTMODULE_INNERRADIUS= Near Ghost Radius | ||
MODOPTIONS_GHOSTMODULE_BORDERSIZE= Gradient Region | ||
MODOPTIONS_GHOSTMODULE_SHOWDEATHS= Show Recorded Deaths | ||
MODOPTIONS_GHOSTMODULE_GHOSTCOUNT= Ghosts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
using FMOD.Studio; | ||
using Microsoft.Xna.Framework; | ||
using Monocle; | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using YamlDotNet.Serialization; | ||
|
||
namespace Celeste.Mod.Ghost { | ||
public class Ghost : Actor { | ||
|
||
public Player Player; | ||
|
||
public PlayerSprite Sprite; | ||
public PlayerHair Hair; | ||
public int MachineState; | ||
|
||
public GhostData Data; | ||
public int FrameIndex = 0; | ||
public GhostFrame? ForcedFrame; | ||
public GhostFrame PrevFrame => ForcedFrame ?? (Data == null ? default(GhostFrame) : Data[FrameIndex - 1]); | ||
public GhostFrame Frame => ForcedFrame ?? (Data == null ? default(GhostFrame) : Data[FrameIndex]); | ||
public bool AutoForward = true; | ||
|
||
public GhostName Name; | ||
|
||
protected float alpha; | ||
protected float alphaHair; | ||
|
||
protected bool playerHadControl; | ||
|
||
public Ghost(Player player) | ||
: this(player, null) { | ||
} | ||
public Ghost(Player player, GhostData data) | ||
: base(player.Position) { | ||
Player = player; | ||
Data = data; | ||
|
||
Depth = 1; | ||
|
||
Sprite = new PlayerSprite(player.Sprite.Mode); | ||
Sprite.HairCount = player.Sprite.HairCount; | ||
Add(Hair = new PlayerHair(Sprite)); | ||
Add(Sprite); | ||
|
||
Hair.Color = Player.NormalHairColor; | ||
} | ||
|
||
public override void Added(Scene scene) { | ||
base.Added(scene); | ||
|
||
Hair.Facing = Frame.Facing; | ||
Hair.Start(); | ||
UpdateHair(); | ||
|
||
if (Data != null && Data.Name != GhostModule.Settings.Name) | ||
Scene.Add(Name = new GhostName(this, Data.Name)); | ||
} | ||
|
||
public override void Removed(Scene scene) { | ||
base.Removed(scene); | ||
|
||
Name?.RemoveSelf(); | ||
} | ||
|
||
public void UpdateHair() { | ||
if (!Frame.HasData) | ||
return; | ||
|
||
Hair.Color = Frame.HairColor; | ||
Hair.Alpha = alphaHair; | ||
Hair.Facing = Frame.Facing; | ||
Hair.SimulateMotion = Frame.HairSimulateMotion; | ||
} | ||
|
||
public void UpdateSprite() { | ||
if (!Frame.HasData) | ||
return; | ||
|
||
Position = Frame.Position; | ||
Sprite.Rotation = Frame.Rotation; | ||
Sprite.Scale = Frame.Scale; | ||
Sprite.Scale.X = Sprite.Scale.X * (float) Frame.Facing; | ||
Sprite.Color = Frame.Color * alpha; | ||
|
||
Sprite.Rate = Frame.SpriteRate; | ||
Sprite.Justify = Frame.SpriteJustify; | ||
|
||
try { | ||
if (Sprite.CurrentAnimationID != Frame.CurrentAnimationID) | ||
Sprite.Play(Frame.CurrentAnimationID); | ||
Sprite.SetAnimationFrame(Frame.CurrentAnimationFrame); | ||
} catch { | ||
// Play likes to fail randomly as the ID doesn't exist in an underlying dict. | ||
// Let's ignore this for now. | ||
} | ||
} | ||
|
||
public override void Update() { | ||
Visible = ((GhostModule.Settings.Mode & GhostModuleMode.Play) == GhostModuleMode.Play); | ||
Visible &= Frame.HasData; | ||
if (Data != null && Data.Dead) | ||
Visible &= GhostModule.Settings.ShowDeaths; | ||
|
||
if (Player.InControl && AutoForward && ForcedFrame == null) { | ||
do { | ||
FrameIndex++; | ||
} while ( | ||
(PrevFrame.HasData && !PrevFrame.InControl) || // Skip any frames we're not in control in. | ||
(!PrevFrame.HasData && FrameIndex < Data.Frames.Count) // Skip any frames not containing the data chunk. | ||
); | ||
} | ||
playerHadControl = Player.InControl; | ||
|
||
UpdateSprite(); | ||
UpdateHair(); | ||
|
||
if (Data != null && Data.Opacity != null) { | ||
alpha = Data.Opacity.Value; | ||
alphaHair = Data.Opacity.Value; | ||
} else { | ||
float dist = (Player.Position - Position).LengthSquared(); | ||
dist -= GhostModule.Settings.InnerRadiusDist; | ||
if (dist < 0f) | ||
dist = 0f; | ||
if (GhostModule.Settings.BorderSize == 0) { | ||
dist = dist < GhostModule.Settings.InnerRadiusDist ? 0f : 1f; | ||
} else { | ||
dist /= GhostModule.Settings.BorderSizeDist; | ||
} | ||
alpha = Calc.LerpClamp(GhostModule.Settings.InnerOpacityFactor, GhostModule.Settings.OuterOpacityFactor, dist); | ||
alphaHair = Calc.LerpClamp(GhostModule.Settings.InnerHairOpacityFactor, GhostModule.Settings.OuterHairOpacityFactor, dist); | ||
} | ||
|
||
Visible &= alpha > 0f; | ||
|
||
if (Name != null) | ||
Name.Alpha = alpha; | ||
|
||
base.Update(); | ||
} | ||
|
||
} | ||
} |
Oops, something went wrong.