Latest WIP on Weekend 1 appearance stuff

This commit is contained in:
Eric Myllyoja 2022-08-16 20:26:34 -04:00
parent 2760a9ae9a
commit fe9a319814
20 changed files with 83 additions and 80 deletions

View File

@ -19,7 +19,6 @@ import openfl.display.Sprite;
import openfl.events.AsyncErrorEvent; import openfl.events.AsyncErrorEvent;
import openfl.events.MouseEvent; import openfl.events.MouseEvent;
import openfl.events.NetStatusEvent; import openfl.events.NetStatusEvent;
import openfl.filters.ShaderFilter;
import openfl.media.Video; import openfl.media.Video;
import openfl.net.NetStream; import openfl.net.NetStream;
@ -580,7 +579,8 @@ class TitleState extends MusicBeatState
if (cheatActive && curBeat % 2 == 0) if (cheatActive && curBeat % 2 == 0)
swagShader.update(0.125); swagShader.update(0.125);
logoBl.animation.play('bump', true); if (logoBl != null)
logoBl.animation.play('bump', true);
danceLeft = !danceLeft; danceLeft = !danceLeft;

View File

@ -1,16 +0,0 @@
package funkin.modding;
import polymod.hscript.HScriptable;
/**
* Functions annotated with @:hscript will call the relevant script.
* Functions annotated with @:hookable can be reassigned.
* NOTE: If you receive the following error when making a function use @:hookable:
* `Cannot access this or other member field in variable initialization`
* This is because you need to perform calls and assignments using a static variable referencing the target object.
*/
@:hscript({
// ALL of these values are added to ALL scripts in the child classes.
context: [FlxG, FlxSprite, Math, Paths, Std]
})
interface IHook extends HScriptable {}

View File

@ -220,14 +220,14 @@ class PolymodHandler
{ {
// Forcibly clear scripts so that scripts can be edited. // Forcibly clear scripts so that scripts can be edited.
ModuleHandler.clearModuleCache(); ModuleHandler.clearModuleCache();
polymod.hscript.PolymodScriptClass.clearScriptClasses(); Polymod.clearScripts();
// Forcibly reload Polymod so it finds any new files. // Forcibly reload Polymod so it finds any new files.
// TODO: Replace this with loadEnabledMods(). // TODO: Replace this with loadEnabledMods().
funkin.modding.PolymodHandler.loadAllMods(); funkin.modding.PolymodHandler.loadAllMods();
// Reload scripted classes so stages and modules will update. // Reload scripted classes so stages and modules will update.
polymod.hscript.PolymodScriptClass.registerAllScriptClasses(); Polymod.registerAllScriptClasses();
// Reload everything that is cached. // Reload everything that is cached.
// Currently this freezes the game for a second but I guess that's tolerable? // Currently this freezes the game for a second but I guess that's tolerable?

View File

@ -1,7 +1,7 @@
package funkin.modding.base; package funkin.modding.base;
import flixel.addons.display.FlxRuntimeShader; import flixel.addons.display.FlxRuntimeShader;
import funkin.modding.IHook; import polymod.hscript.HScriptedClass;
@:hscriptClass @:hscriptClass
class ScriptedFlxRuntimeShader extends FlxRuntimeShader implements IHook {} class ScriptedFlxRuntimeShader extends FlxRuntimeShader implements HScriptedClass {}

View File

@ -1,7 +1,7 @@
package funkin.modding.base; package funkin.modding.base;
import flixel.FlxSprite; import flixel.FlxSprite;
import funkin.modding.IHook; import polymod.hscript.HScriptedClass;
@:hscriptClass @:hscriptClass
class ScriptedFlxSprite extends FlxSprite implements IHook {} class ScriptedFlxSprite extends FlxSprite implements HScriptedClass {}

View File

@ -1,7 +1,7 @@
package funkin.modding.base; package funkin.modding.base;
import flixel.group.FlxSpriteGroup; import flixel.group.FlxSpriteGroup;
import funkin.modding.IHook; import polymod.hscript.HScriptedClass;
@:hscriptClass @:hscriptClass
class ScriptedFlxSpriteGroup extends FlxSpriteGroup implements IHook {} class ScriptedFlxSpriteGroup extends FlxSpriteGroup implements HScriptedClass {}

View File

@ -1,7 +1,7 @@
package funkin.modding.base; package funkin.modding.base;
import flixel.FlxState; import flixel.FlxState;
import funkin.modding.IHook; import polymod.hscript.HScriptedClass;
@:hscriptClass @:hscriptClass
class ScriptedFlxState extends FlxState implements IHook {} class ScriptedFlxState extends FlxState implements HScriptedClass {}

View File

@ -1,7 +1,7 @@
package funkin.modding.base; package funkin.modding.base;
import flixel.FlxSubState; import flixel.FlxSubState;
import funkin.modding.IHook; import polymod.hscript.HScriptedClass;
@:hscriptClass @:hscriptClass
class ScriptedFlxSubState extends FlxSubState implements IHook {} class ScriptedFlxSubState extends FlxSubState implements HScriptedClass {}

View File

@ -1,7 +1,7 @@
package funkin.modding.base; package funkin.modding.base;
import flixel.addons.transition.FlxTransitionableState; import flixel.addons.transition.FlxTransitionableState;
import funkin.modding.IHook; import polymod.hscript.HScriptedClass;
@:hscriptClass @:hscriptClass
class ScriptedFlxTransitionableState extends FlxTransitionableState implements IHook {} class ScriptedFlxTransitionableState extends FlxTransitionableState implements HScriptedClass {}

View File

@ -1,7 +1,7 @@
package funkin.modding.base; package funkin.modding.base;
import flixel.addons.ui.FlxUIState; import flixel.addons.ui.FlxUIState;
import funkin.modding.IHook; import polymod.hscript.HScriptedClass;
@:hscriptClass @:hscriptClass
class ScriptedFlxUIState extends FlxUIState implements IHook {} class ScriptedFlxUIState extends FlxUIState implements HScriptedClass {}

View File

@ -1,7 +1,7 @@
package funkin.modding.base; package funkin.modding.base;
import funkin.MusicBeatState; import funkin.MusicBeatState;
import funkin.modding.IHook; import polymod.hscript.HScriptedClass;
@:hscriptClass @:hscriptClass
class ScriptedMusicBeatState extends MusicBeatState implements IHook {} class ScriptedMusicBeatState extends MusicBeatState implements HScriptedClass {}

View File

@ -1,7 +1,7 @@
package funkin.modding.base; package funkin.modding.base;
import funkin.MusicBeatSubstate; import funkin.MusicBeatSubstate;
import funkin.modding.IHook; import polymod.hscript.HScriptedClass;
@:hscriptClass @:hscriptClass
class ScriptedMusicBeatSubstate extends MusicBeatSubstate implements IHook {} class ScriptedMusicBeatSubstate extends MusicBeatSubstate implements HScriptedClass {}

View File

@ -1,6 +1,6 @@
package funkin.modding.module; package funkin.modding.module;
import funkin.modding.IHook; import polymod.hscript.HScriptedClass;
@:hscriptClass @:hscriptClass
class ScriptedModule extends Module implements IHook {} class ScriptedModule extends Module implements HScriptedClass {}

View File

@ -1,7 +1,7 @@
package funkin.play; package funkin.play;
import flixel.FlxSprite;
import flixel.FlxObject; import flixel.FlxObject;
import flixel.FlxSprite;
import flixel.system.FlxSound; import flixel.system.FlxSound;
import flixel.util.FlxColor; import flixel.util.FlxColor;
import flixel.util.FlxTimer; import flixel.util.FlxTimer;
@ -183,13 +183,13 @@ class GameOverSubstate extends MusicBeatSubstate
playingJeffQuote = true; playingJeffQuote = true;
playJeffQuote(); playJeffQuote();
// Start music at lower volume // Start music at lower volume
startDeathMusic(0.2); startDeathMusic(0.2, false);
} }
default: default:
// Start music at normal volume once the initial death animation finishes. // Start music at normal volume once the initial death animation finishes.
if (boyfriend.getCurrentAnimation().startsWith('firstDeath') && boyfriend.isAnimationFinished()) if (boyfriend.getCurrentAnimation().startsWith('firstDeath') && boyfriend.isAnimationFinished())
{ {
startDeathMusic(); startDeathMusic(1.0, false);
} }
} }
} }
@ -206,7 +206,7 @@ class GameOverSubstate extends MusicBeatSubstate
if (!isEnding) if (!isEnding)
{ {
isEnding = true; isEnding = true;
startDeathMusic(); // isEnding changes this function's behavior. startDeathMusic(1.0, true); // isEnding changes this function's behavior.
boyfriend.playAnimation('deathConfirm' + animationSuffix, true); boyfriend.playAnimation('deathConfirm' + animationSuffix, true);
@ -243,17 +243,16 @@ class GameOverSubstate extends MusicBeatSubstate
* Starts the death music at the appropriate volume. * Starts the death music at the appropriate volume.
* @param startingVolume * @param startingVolume
*/ */
function startDeathMusic(?startingVolume:Float = 1):Void function startDeathMusic(?startingVolume:Float = 1, ?force:Bool = false):Void
{ {
if (!isEnding) var musicPath = Paths.music('gameOver' + musicSuffix);
if (isEnding)
{ {
gameOverMusic.loadEmbedded(Paths.music('gameOver' + musicSuffix)); musicPath = Paths.music('gameOverEnd' + musicSuffix);
gameOverMusic.volume = startingVolume;
gameOverMusic.play();
} }
else if (!gameOverMusic.playing || force)
{ {
gameOverMusic.loadEmbedded(Paths.music('gameOverEnd' + musicSuffix)); gameOverMusic.loadEmbedded(musicPath);
gameOverMusic.volume = startingVolume; gameOverMusic.volume = startingVolume;
gameOverMusic.play(); gameOverMusic.play();
} }

View File

@ -20,7 +20,6 @@ import funkin.Note;
import funkin.Section.SwagSection; import funkin.Section.SwagSection;
import funkin.SongLoad.SwagSong; import funkin.SongLoad.SwagSong;
import funkin.charting.ChartingState; import funkin.charting.ChartingState;
import funkin.modding.IHook;
import funkin.modding.events.ScriptEvent; import funkin.modding.events.ScriptEvent;
import funkin.modding.events.ScriptEventDispatcher; import funkin.modding.events.ScriptEventDispatcher;
import funkin.play.GameOverSubstate; import funkin.play.GameOverSubstate;
@ -38,6 +37,7 @@ import funkin.ui.stageBuildShit.StageOffsetSubstate;
import funkin.util.Constants; import funkin.util.Constants;
import funkin.util.SortUtil; import funkin.util.SortUtil;
import lime.ui.Haptic; import lime.ui.Haptic;
import polymod.hscript.HScriptedClass;
using StringTools; using StringTools;
@ -45,7 +45,7 @@ using StringTools;
import Discord.DiscordClient; import Discord.DiscordClient;
#end #end
class PlayState extends MusicBeatState implements IHook class PlayState extends MusicBeatState
{ {
/** /**
* STATIC VARIABLES * STATIC VARIABLES

View File

@ -166,15 +166,19 @@ class BaseCharacter extends Bopper
return _data.flipX; return _data.flipX;
} }
function findCountAnimations(prefix:String):Array<Int> { function findCountAnimations(prefix:String):Array<Int>
{
var animNames:Array<String> = this.animation.getNameList(); var animNames:Array<String> = this.animation.getNameList();
var result:Array<Int> = []; var result:Array<Int> = [];
for (anim in animNames) { for (anim in animNames)
if (anim.startsWith(prefix)) { {
if (anim.startsWith(prefix))
{
var comboNum:Null<Int> = Std.parseInt(anim.substring(prefix.length)); var comboNum:Null<Int> = Std.parseInt(anim.substring(prefix.length));
if (comboNum != null) { if (comboNum != null)
{
result.push(comboNum); result.push(comboNum);
} }
} }
@ -189,15 +193,16 @@ class BaseCharacter extends Bopper
* Reset the character so it can be used at the start of the level. * Reset the character so it can be used at the start of the level.
* Call this when restarting the level. * Call this when restarting the level.
*/ */
public function resetCharacter(resetCamera:Bool = true):Void { public function resetCharacter(resetCamera:Bool = true):Void
{
// Reset the animation offsets. This will modify x and y to be the absolute position of the character. // Reset the animation offsets. This will modify x and y to be the absolute position of the character.
this.animOffsets = [0, 0]; this.animOffsets = [0, 0];
// Now we can set the x and y to be their original values without having to account for animOffsets. // Now we can set the x and y to be their original values without having to account for animOffsets.
this.resetPosition(); this.resetPosition();
// Make sure we are playing the idle animation (to reapply animOffsets)... // Make sure we are playing the idle animation (to reapply animOffsets)...
this.dance(); this.dance(true); // Force to avoid the old animation playing with the wrong offset at the start of the song.
// ...then update the hitbox so that this.width and this.height are correct. // ...then update the hitbox so that this.width and this.height are correct.
this.updateHitbox(); this.updateHitbox();
@ -205,7 +210,7 @@ class BaseCharacter extends Bopper
if (resetCamera) if (resetCamera)
this.resetCameraFocusPoint(); this.resetCameraFocusPoint();
} }
/** /**
* Set the sprite scale to the appropriate value. * Set the sprite scale to the appropriate value.
* @param scale * @param scale
@ -252,7 +257,7 @@ class BaseCharacter extends Bopper
// trace('${this.animation.getNameList()}'); // trace('${this.animation.getNameList()}');
// trace('Combo note counts: ' + this.comboNoteCounts); // trace('Combo note counts: ' + this.comboNoteCounts);
// trace('Drop note counts: ' + this.dropNoteCounts); // trace('Drop note counts: ' + this.dropNoteCounts);
super.onCreate(event); super.onCreate(event);
} }
@ -314,6 +319,11 @@ class BaseCharacter extends Bopper
// Handle character note hold time. // Handle character note hold time.
if (getCurrentAnimation().startsWith("sing")) if (getCurrentAnimation().startsWith("sing"))
{ {
// TODO: Rework this code (and all character animations ugh)
// such that the hold time is handled by padding frames,
// and reverting to the idle animation is done when `isAnimationFinished()`.
// This lets you add frames to the end of the sing animation to ease back into the idle!
holdTimer += event.elapsed; holdTimer += event.elapsed;
var singTimeMs:Float = singTimeCrochet * (Conductor.crochet * 0.001); // x beats, to ms. var singTimeMs:Float = singTimeCrochet * (Conductor.crochet * 0.001); // x beats, to ms.
// Without this check here, the player character would only play the `sing` animation // Without this check here, the player character would only play the `sing` animation
@ -454,8 +464,11 @@ class BaseCharacter extends Bopper
{ {
// If the note is from the same strumline, play the sing animation. // If the note is from the same strumline, play the sing animation.
this.playSingAnimation(event.note.data.dir, false); this.playSingAnimation(event.note.data.dir, false);
} else if (characterType == GF) { }
if (event.note.mustPress && this.comboNoteCounts.contains(event.comboCount)) { else if (characterType == GF)
{
if (event.note.mustPress && this.comboNoteCounts.contains(event.comboCount))
{
trace('Playing GF combo animation: combo${event.comboCount}'); trace('Playing GF combo animation: combo${event.comboCount}');
this.playAnimation('combo${event.comboCount}', true, true); this.playAnimation('combo${event.comboCount}', true, true);
} }
@ -479,19 +492,24 @@ class BaseCharacter extends Bopper
{ {
// If the note is from the same strumline, play the sing animation. // If the note is from the same strumline, play the sing animation.
this.playSingAnimation(event.note.data.dir, true); this.playSingAnimation(event.note.data.dir, true);
} else if (event.note.mustPress && characterType == GF) { }
else if (event.note.mustPress && characterType == GF)
{
var dropAnim = ''; var dropAnim = '';
// Choose the combo drop anim to play. // Choose the combo drop anim to play.
// If there are several (for example, drop10 and drop50) the highest one will be used. // If there are several (for example, drop10 and drop50) the highest one will be used.
// If the combo count is too low, no animation will be played. // If the combo count is too low, no animation will be played.
for (count in dropNoteCounts) { for (count in dropNoteCounts)
if (event.comboCount >= count) { {
if (event.comboCount >= count)
{
dropAnim = 'drop${count}'; dropAnim = 'drop${count}';
} }
} }
if (dropAnim != '') { if (dropAnim != '')
{
trace('Playing GF combo drop animation: ${dropAnim}'); trace('Playing GF combo drop animation: ${dropAnim}');
this.playAnimation(dropAnim, true, true); this.playAnimation(dropAnim, true, true);
} }
@ -549,6 +567,7 @@ enum CharacterType
* - If the player misses or hits a ghost note, plays the appropriate `singDIR-miss` animation until BF is done singing. * - If the player misses or hits a ghost note, plays the appropriate `singDIR-miss` animation until BF is done singing.
*/ */
BF; BF;
/** /**
* The DAD character has the following behaviors. * The DAD character has the following behaviors.
* - At idle, dances with `danceLeft` and `danceRight` if available, or `idle` if not. * - At idle, dances with `danceLeft` and `danceRight` if available, or `idle` if not.
@ -557,6 +576,7 @@ enum CharacterType
* - When the CPU misses a note (NOTE: This only happens via script, not by default), plays the appropriate `singDIR-miss` animation until DAD is done singing. * - When the CPU misses a note (NOTE: This only happens via script, not by default), plays the appropriate `singDIR-miss` animation until DAD is done singing.
*/ */
DAD; DAD;
/** /**
* The GF character has the following behaviors. * The GF character has the following behaviors.
* - At idle, dances with `danceLeft` and `danceRight` if available, or `idle` if not. * - At idle, dances with `danceLeft` and `danceRight` if available, or `idle` if not.
@ -569,6 +589,7 @@ enum CharacterType
* - No drop animation will play if one isn't applicable (i.e. if the combo count is too low). * - No drop animation will play if one isn't applicable (i.e. if the combo count is too low).
*/ */
GF; GF;
/** /**
* The OTHER character will only perform the `danceLeft`/`danceRight` or `idle` animation by default, depending on what's available. * The OTHER character will only perform the `danceLeft`/`danceRight` or `idle` animation by default, depending on what's available.
* Additional behaviors can be performed via scripts. * Additional behaviors can be performed via scripts.

View File

@ -1,9 +1,9 @@
package funkin.play.character; package funkin.play.character;
import funkin.modding.IHook;
import funkin.play.character.MultiSparrowCharacter; import funkin.play.character.MultiSparrowCharacter;
import funkin.play.character.PackerCharacter; import funkin.play.character.PackerCharacter;
import funkin.play.character.SparrowCharacter; import funkin.play.character.SparrowCharacter;
import polymod.hscript.HScriptedClass;
/** /**
* Note: Making a scripted class extending BaseCharacter is not recommended. * Note: Making a scripted class extending BaseCharacter is not recommended.
@ -11,13 +11,13 @@ import funkin.play.character.SparrowCharacter;
* and can't use one of the built-in render modes. * and can't use one of the built-in render modes.
*/ */
@:hscriptClass @:hscriptClass
class ScriptedBaseCharacter extends BaseCharacter implements IHook {} class ScriptedBaseCharacter extends BaseCharacter implements HScriptedClass {}
@:hscriptClass @:hscriptClass
class ScriptedSparrowCharacter extends SparrowCharacter implements IHook {} class ScriptedSparrowCharacter extends SparrowCharacter implements HScriptedClass {}
@:hscriptClass @:hscriptClass
class ScriptedMultiSparrowCharacter extends MultiSparrowCharacter implements IHook {} class ScriptedMultiSparrowCharacter extends MultiSparrowCharacter implements HScriptedClass {}
@:hscriptClass @:hscriptClass
class ScriptedPackerCharacter extends PackerCharacter implements IHook {} class ScriptedPackerCharacter extends PackerCharacter implements HScriptedClass {}

View File

@ -1,6 +1,6 @@
package funkin.play.stage; package funkin.play.stage;
import funkin.modding.IHook; import polymod.hscript.HScriptedClass;
@:hscriptClass @:hscriptClass
class ScriptedBopper extends Bopper implements IHook {} class ScriptedBopper extends Bopper implements HScriptedClass {}

View File

@ -1,6 +1,6 @@
package funkin.play.stage; package funkin.play.stage;
import funkin.modding.IHook; import polymod.hscript.HScriptedClass;
@:hscriptClass @:hscriptClass
class ScriptedStage extends Stage implements IHook {} class ScriptedStage extends Stage implements HScriptedClass {}

View File

@ -4,7 +4,6 @@ import flixel.FlxSprite;
import flixel.group.FlxSpriteGroup; import flixel.group.FlxSpriteGroup;
import flixel.math.FlxPoint; import flixel.math.FlxPoint;
import flixel.util.FlxSort; import flixel.util.FlxSort;
import funkin.modding.IHook;
import funkin.modding.IScriptedClass; import funkin.modding.IScriptedClass;
import funkin.modding.events.ScriptEvent; import funkin.modding.events.ScriptEvent;
import funkin.modding.events.ScriptEventDispatcher; import funkin.modding.events.ScriptEventDispatcher;
@ -19,7 +18,7 @@ import funkin.util.assets.FlxAnimationUtil;
* *
* A Stage is comprised of one or more props, each of which is a FlxSprite. * A Stage is comprised of one or more props, each of which is a FlxSprite.
*/ */
class Stage extends FlxSpriteGroup implements IHook implements IPlayStateScriptedClass class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass
{ {
public final stageId:String; public final stageId:String;
public final stageName:String; public final stageName:String;