1
0
Fork 0
mirror of https://github.com/ninjamuffin99/Funkin.git synced 2025-11-26 06:09:02 +00:00

Merge branch 'rewrite/master' into bugfix/freeplay-afk-fixes

This commit is contained in:
Eric 2024-03-26 19:35:10 -04:00 committed by GitHub
commit 88c973f1ae
22 changed files with 245 additions and 44 deletions

View file

@ -13,8 +13,9 @@ jobs:
apt update apt update
apt install -y sudo git curl unzip apt install -y sudo git curl unzip
- name: Fix git config on posix runner - name: Fix git config on posix runner
# this can't be {{ github.workspace }} because that's not docker-aware
run: | run: |
git config --global --add safe.directory ${{ github.workspace }} git config --global --add safe.directory $GITHUB_WORKSPACE
- name: Get checkout token - name: Get checkout token
uses: actions/create-github-app-token@v1 uses: actions/create-github-app-token@v1
id: app_token id: app_token
@ -90,8 +91,9 @@ jobs:
runs-on: [self-hosted, macos] runs-on: [self-hosted, macos]
steps: steps:
- name: Fix git config on posix runner - name: Fix git config on posix runner
# this can't be {{ github.workspace }} because that's not docker-aware
run: | run: |
git config --global --add safe.directory ${{ github.workspace }} git config --global --add safe.directory $GITHUB_WORKSPACE
- name: Get checkout token - name: Get checkout token
uses: actions/create-github-app-token@v1 uses: actions/create-github-app-token@v1
id: app_token id: app_token

15
.vscode/settings.json vendored
View file

@ -204,6 +204,21 @@
"label": "HTML5 / Debug (Watch)", "label": "HTML5 / Debug (Watch)",
"target": "html5", "target": "html5",
"args": ["-debug", "-watch", "-DFORCE_DEBUG_VERSION"] "args": ["-debug", "-watch", "-DFORCE_DEBUG_VERSION"]
},
{
"label": "macOS / Debug",
"target": "mac",
"args": ["-debug", "-DFORCE_DEBUG_VERSION"]
},
{
"label": "macOS / Release",
"target": "mac",
"args": ["-release"]
},
{
"label": "macOS / Release (GitHub Actions)",
"target": "mac",
"args": ["-release", "-DGITHUB_BUILD"]
} }
], ],
"cmake.configureOnOpen": false, "cmake.configureOnOpen": false,

2
assets

@ -1 +1 @@
Subproject commit 3e8bea70e7dcc76df67a0e87b85ef28ed5140371 Subproject commit 5f1726f1b0c11fc747b7473708cf4e5f28be05f1

View file

@ -35,7 +35,15 @@ class Conductor
* You can also do stuff like store a reference to the Conductor and pass it around or temporarily replace it, * You can also do stuff like store a reference to the Conductor and pass it around or temporarily replace it,
* or have a second Conductor running at the same time, or other weird stuff like that if you need to. * or have a second Conductor running at the same time, or other weird stuff like that if you need to.
*/ */
public static var instance:Conductor = new Conductor(); public static var instance(get, never):Conductor;
static var _instance:Null<Conductor> = null;
static function get_instance():Conductor
{
if (_instance == null) _instance = new Conductor();
return _instance;
}
/** /**
* Signal fired when the current Conductor instance advances to a new measure. * Signal fired when the current Conductor instance advances to a new measure.
@ -523,6 +531,6 @@ class Conductor
*/ */
public static function reset():Void public static function reset():Void
{ {
Conductor.instance = new Conductor(); _instance = new Conductor();
} }
} }

View file

@ -55,6 +55,13 @@ abstract class BaseRegistry<T:(IRegistryEntry<J> & Constructible<EntryConstructo
this.entries = new Map<String, T>(); this.entries = new Map<String, T>();
this.scriptedEntryIds = []; this.scriptedEntryIds = [];
// Lazy initialization of singletons should let this get called,
// but we have this check just in case.
if (FlxG.game != null)
{
FlxG.console.registerObject('registry$registryId', this);
}
} }
/** /**

View file

@ -15,7 +15,14 @@ class ConversationRegistry extends BaseRegistry<Conversation, ConversationData>
public static final CONVERSATION_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; public static final CONVERSATION_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x";
public static final instance:ConversationRegistry = new ConversationRegistry(); public static var instance(get, never):ConversationRegistry;
static var _instance:Null<ConversationRegistry> = null;
static function get_instance():ConversationRegistry
{
if (_instance == null) _instance = new ConversationRegistry();
return _instance;
}
public function new() public function new()
{ {

View file

@ -15,7 +15,14 @@ class DialogueBoxRegistry extends BaseRegistry<DialogueBox, DialogueBoxData>
public static final DIALOGUEBOX_DATA_VERSION_RULE:thx.semver.VersionRule = "1.1.x"; public static final DIALOGUEBOX_DATA_VERSION_RULE:thx.semver.VersionRule = "1.1.x";
public static final instance:DialogueBoxRegistry = new DialogueBoxRegistry(); public static var instance(get, never):DialogueBoxRegistry;
static var _instance:Null<DialogueBoxRegistry> = null;
static function get_instance():DialogueBoxRegistry
{
if (_instance == null) _instance = new DialogueBoxRegistry();
return _instance;
}
public function new() public function new()
{ {

View file

@ -15,7 +15,14 @@ class SpeakerRegistry extends BaseRegistry<Speaker, SpeakerData>
public static final SPEAKER_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; public static final SPEAKER_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x";
public static final instance:SpeakerRegistry = new SpeakerRegistry(); public static var instance(get, never):SpeakerRegistry;
static var _instance:Null<SpeakerRegistry> = null;
static function get_instance():SpeakerRegistry
{
if (_instance == null) _instance = new SpeakerRegistry();
return _instance;
}
public function new() public function new()
{ {

View file

@ -15,7 +15,14 @@ class LevelRegistry extends BaseRegistry<Level, LevelData>
public static final LEVEL_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; public static final LEVEL_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x";
public static final instance:LevelRegistry = new LevelRegistry(); public static var instance(get, never):LevelRegistry;
static var _instance:Null<LevelRegistry> = null;
static function get_instance():LevelRegistry
{
if (_instance == null) _instance = new LevelRegistry();
return _instance;
}
public function new() public function new()
{ {

View file

@ -15,7 +15,14 @@ class NoteStyleRegistry extends BaseRegistry<NoteStyle, NoteStyleData>
public static final NOTE_STYLE_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; public static final NOTE_STYLE_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x";
public static final instance:NoteStyleRegistry = new NoteStyleRegistry(); public static var instance(get, never):NoteStyleRegistry;
static var _instance:Null<NoteStyleRegistry> = null;
static function get_instance():NoteStyleRegistry
{
if (_instance == null) _instance = new NoteStyleRegistry();
return _instance;
}
public function new() public function new()
{ {

View file

@ -40,10 +40,17 @@ class SongRegistry extends BaseRegistry<Song, SongMetadata>
} }
/** /**
* TODO: What if there was a Singleton macro which created static functions * TODO: What if there was a Singleton macro which automatically created the property for us?
* that redirected to the instance?
*/ */
public static final instance:SongRegistry = new SongRegistry(); public static var instance(get, never):SongRegistry;
static var _instance:Null<SongRegistry> = null;
static function get_instance():SongRegistry
{
if (_instance == null) _instance = new SongRegistry();
return _instance;
}
public function new() public function new()
{ {

View file

@ -15,7 +15,14 @@ class StageRegistry extends BaseRegistry<Stage, StageData>
public static final STAGE_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x"; public static final STAGE_DATA_VERSION_RULE:thx.semver.VersionRule = "1.0.x";
public static final instance:StageRegistry = new StageRegistry(); public static var instance(get, never):StageRegistry;
static var _instance:Null<StageRegistry> = null;
static function get_instance():StageRegistry
{
if (_instance == null) _instance = new StageRegistry();
return _instance;
}
public function new() public function new()
{ {

View file

@ -1364,7 +1364,10 @@ class PlayState extends MusicBeatSubState
} }
// Only zoom camera if we are zoomed by less than 35%. // Only zoom camera if we are zoomed by less than 35%.
if (FlxG.camera.zoom < (1.35 * defaultCameraZoom) && cameraZoomRate > 0 && Conductor.instance.currentBeat % cameraZoomRate == 0) if (Preferences.zoomCamera
&& FlxG.camera.zoom < (1.35 * defaultCameraZoom)
&& cameraZoomRate > 0
&& Conductor.instance.currentBeat % cameraZoomRate == 0)
{ {
// Zoom camera in (1.5%) // Zoom camera in (1.5%)
currentCameraZoom += cameraZoomIntensity * defaultCameraZoom; currentCameraZoom += cameraZoomIntensity * defaultCameraZoom;
@ -2106,8 +2109,7 @@ class PlayState extends MusicBeatSubState
holdNote.handledMiss = true; holdNote.handledMiss = true;
// We dropped a hold note. // We dropped a hold note.
// Mute vocals and play miss animation, but don't penalize. // Play miss animation, but don't penalize.
vocals.opponentVolume = 0;
currentStage.getOpponent().playSingAnimation(holdNote.noteData.getDirection(), true); currentStage.getOpponent().playSingAnimation(holdNote.noteData.getDirection(), true);
} }
} }
@ -2939,7 +2941,10 @@ class PlayState extends MusicBeatSubState
if (overrideMusic) if (overrideMusic)
{ {
// Stop the music. Do NOT destroy it, something still references it! // Stop the music. Do NOT destroy it, something still references it!
FlxG.sound.music.pause(); if (FlxG.sound.music != null)
{
FlxG.sound.music.pause();
}
if (vocals != null) if (vocals != null)
{ {
vocals.pause(); vocals.pause();
@ -2949,7 +2954,10 @@ class PlayState extends MusicBeatSubState
else else
{ {
// Stop and destroy the music. // Stop and destroy the music.
FlxG.sound.music.pause(); if (FlxG.sound.music != null)
{
FlxG.sound.music.pause();
}
if (vocals != null) if (vocals != null)
{ {
vocals.destroy(); vocals.destroy();

View file

@ -109,7 +109,7 @@ class ResultState extends MusicBeatSubState
add(gf); add(gf);
var boyfriend:FlxSprite = FunkinSprite.createSparrow(640, -200, 'resultScreen/resultBoyfriendGOOD'); var boyfriend:FlxSprite = FunkinSprite.createSparrow(640, -200, 'resultScreen/resultBoyfriendGOOD');
boyfriend.animation.addByPrefix("fall", "Boyfriend Good", 24, false); boyfriend.animation.addByPrefix("fall", "Boyfriend Good Anim0", 24, false);
boyfriend.visible = false; boyfriend.visible = false;
boyfriend.animation.finishCallback = function(_) { boyfriend.animation.finishCallback = function(_) {
boyfriend.animation.play('fall', true, false, 14); boyfriend.animation.play('fall', true, false, 14);
@ -164,7 +164,7 @@ class ResultState extends MusicBeatSubState
add(blackTopBar); add(blackTopBar);
var resultsAnim:FunkinSprite = FunkinSprite.createSparrow(-200, -10, "resultScreen/results"); var resultsAnim:FunkinSprite = FunkinSprite.createSparrow(-200, -10, "resultScreen/results");
resultsAnim.animation.addByPrefix("result", "results", 24, false); resultsAnim.animation.addByPrefix("result", "results instance 1", 24, false);
resultsAnim.animation.play("result"); resultsAnim.animation.play("result");
add(resultsAnim); add(resultsAnim);

View file

@ -76,10 +76,17 @@ class AnimateAtlasCharacter extends BaseCharacter
{ {
trace('Creating Animate Atlas character: ' + this.characterId); trace('Creating Animate Atlas character: ' + this.characterId);
var atlasSprite:FlxAtlasSprite = loadAtlasSprite(); try
setSprite(atlasSprite); {
var atlasSprite:FlxAtlasSprite = loadAtlasSprite();
setSprite(atlasSprite);
loadAnimations(); loadAnimations();
}
catch (e)
{
throw "Exception thrown while building FlxAtlasSprite: " + e;
}
super.onCreate(event); super.onCreate(event);
} }

View file

@ -5,6 +5,7 @@ import flixel.FlxSprite;
import flixel.tweens.FlxEase; import flixel.tweens.FlxEase;
import flixel.tweens.FlxTween; import flixel.tweens.FlxTween;
import flixel.util.FlxColor; import flixel.util.FlxColor;
import flixel.util.FlxSignal;
import flixel.util.FlxTimer; import flixel.util.FlxTimer;
#if html5 #if html5
import funkin.graphics.video.FlxVideo; import funkin.graphics.video.FlxVideo;
@ -28,6 +29,31 @@ class VideoCutscene
static var vid:FlxVideoSprite; static var vid:FlxVideoSprite;
#end #end
/**
* Called when the video is started.
*/
public static final onVideoStarted:FlxSignal = new FlxSignal();
/**
* Called if the video is paused.
*/
public static final onVideoPaused:FlxSignal = new FlxSignal();
/**
* Called if the video is resumed.
*/
public static final onVideoResumed:FlxSignal = new FlxSignal();
/**
* Called if the video is restarted. onVideoStarted is not called.
*/
public static final onVideoRestarted:FlxSignal = new FlxSignal();
/**
* Called when the video is ended or skipped.
*/
public static final onVideoEnded:FlxSignal = new FlxSignal();
/** /**
* Play a video cutscene. * Play a video cutscene.
* TODO: Currently this is hardcoded to start the countdown after the video is done. * TODO: Currently this is hardcoded to start the countdown after the video is done.
@ -94,6 +120,8 @@ class VideoCutscene
PlayState.instance.add(vid); PlayState.instance.add(vid);
PlayState.instance.refresh(); PlayState.instance.refresh();
onVideoStarted.dispatch();
} }
else else
{ {
@ -129,6 +157,8 @@ class VideoCutscene
vid.y = 0; vid.y = 0;
// vid.scale.set(0.5, 0.5); // vid.scale.set(0.5, 0.5);
}); });
onVideoStarted.dispatch();
} }
else else
{ {
@ -143,6 +173,7 @@ class VideoCutscene
if (vid != null) if (vid != null)
{ {
vid.restartVideo(); vid.restartVideo();
onVideoRestarted.dispatch();
} }
#end #end
@ -156,6 +187,8 @@ class VideoCutscene
// Resume the video if it was paused. // Resume the video if it was paused.
vid.resume(); vid.resume();
} }
onVideoRestarted.dispatch();
} }
#end #end
} }
@ -166,6 +199,7 @@ class VideoCutscene
if (vid != null) if (vid != null)
{ {
vid.pauseVideo(); vid.pauseVideo();
onVideoPaused.dispatch();
} }
#end #end
@ -173,6 +207,45 @@ class VideoCutscene
if (vid != null) if (vid != null)
{ {
vid.pause(); vid.pause();
onVideoPaused.dispatch();
}
#end
}
public static function hideVideo():Void
{
#if html5
if (vid != null)
{
vid.visible = false;
blackScreen.visible = false;
}
#end
#if hxCodec
if (vid != null)
{
vid.visible = false;
blackScreen.visible = false;
}
#end
}
public static function showVideo():Void
{
#if html5
if (vid != null)
{
vid.visible = true;
blackScreen.visible = false;
}
#end
#if hxCodec
if (vid != null)
{
vid.visible = true;
blackScreen.visible = false;
} }
#end #end
} }
@ -183,6 +256,7 @@ class VideoCutscene
if (vid != null) if (vid != null)
{ {
vid.resumeVideo(); vid.resumeVideo();
onVideoResumed.dispatch();
} }
#end #end
@ -190,6 +264,7 @@ class VideoCutscene
if (vid != null) if (vid != null)
{ {
vid.resume(); vid.resume();
onVideoResumed.dispatch();
} }
#end #end
} }
@ -240,6 +315,7 @@ class VideoCutscene
{ {
ease: FlxEase.quadInOut, ease: FlxEase.quadInOut,
onComplete: function(twn:FlxTween) { onComplete: function(twn:FlxTween) {
onVideoEnded.dispatch();
onCutsceneFinish(cutsceneType); onCutsceneFinish(cutsceneType);
} }
}); });

View file

@ -139,7 +139,16 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
for (vari in _data.playData.songVariations) for (vari in _data.playData.songVariations)
{ {
var variMeta:Null<SongMetadata> = fetchVariationMetadata(id, vari); var variMeta:Null<SongMetadata> = fetchVariationMetadata(id, vari);
if (variMeta != null) _metadata.set(variMeta.variation, variMeta); if (variMeta != null)
{
_metadata.set(variMeta.variation, variMeta);
trace(' Loaded variation: $vari');
}
else
{
FlxG.log.warn('[SONG] Failed to load variation metadata (${id}:${vari}), is the path correct?');
trace(' FAILED to load variation: $vari');
}
} }
} }
@ -374,12 +383,17 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta
public function getFirstValidVariation(?diffId:String, ?possibleVariations:Array<String>):Null<String> public function getFirstValidVariation(?diffId:String, ?possibleVariations:Array<String>):Null<String>
{ {
if (variations == null) possibleVariations = variations; if (possibleVariations == null)
{
possibleVariations = variations;
possibleVariations.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_VARIATION_LIST));
}
if (diffId == null) diffId = listDifficulties(null, possibleVariations)[0]; if (diffId == null) diffId = listDifficulties(null, possibleVariations)[0];
for (variation in variations) for (variationId in possibleVariations)
{ {
if (difficulties.exists('$diffId-$variation')) return variation; var variationSuffix = (variationId != Constants.DEFAULT_VARIATION) ? '-$variationId' : '';
if (difficulties.exists('$diffId$variationSuffix')) return variationId;
} }
return null; return null;

View file

@ -1,31 +1,35 @@
package funkin.ui.debug.anim; package funkin.ui.debug.anim;
import funkin.util.SerializerUtil;
import funkin.play.character.CharacterData;
import flixel.FlxCamera;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.addons.display.FlxGridOverlay; import flixel.addons.display.FlxGridOverlay;
import flixel.addons.ui.FlxInputText; import flixel.addons.ui.FlxInputText;
import flixel.addons.ui.FlxUIDropDownMenu; import flixel.addons.ui.FlxUIDropDownMenu;
import flixel.FlxCamera;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.graphics.frames.FlxAtlasFrames; import flixel.graphics.frames.FlxAtlasFrames;
import flixel.graphics.frames.FlxFrame; import flixel.graphics.frames.FlxFrame;
import flixel.group.FlxGroup; import flixel.group.FlxGroup;
import flixel.math.FlxPoint; import flixel.math.FlxPoint;
import flixel.text.FlxText; import flixel.text.FlxText;
import flixel.util.FlxColor; import flixel.util.FlxColor;
import funkin.util.MouseUtil;
import flixel.util.FlxSpriteUtil; import flixel.util.FlxSpriteUtil;
import flixel.util.FlxTimer; import flixel.util.FlxTimer;
import funkin.audio.FunkinSound;
import funkin.input.Cursor;
import funkin.play.character.BaseCharacter; import funkin.play.character.BaseCharacter;
import funkin.play.character.CharacterData;
import funkin.play.character.CharacterData.CharacterDataParser; import funkin.play.character.CharacterData.CharacterDataParser;
import funkin.play.character.SparrowCharacter; import funkin.play.character.SparrowCharacter;
import haxe.ui.RuntimeComponentBuilder; import funkin.ui.mainmenu.MainMenuState;
import funkin.util.MouseUtil;
import funkin.util.SerializerUtil;
import funkin.util.SortUtil;
import haxe.ui.components.DropDown; import haxe.ui.components.DropDown;
import haxe.ui.core.Component; import haxe.ui.core.Component;
import haxe.ui.core.Screen;
import haxe.ui.events.ItemEvent; import haxe.ui.events.ItemEvent;
import haxe.ui.events.UIEvent; import haxe.ui.events.UIEvent;
import funkin.ui.mainmenu.MainMenuState; import haxe.ui.RuntimeComponentBuilder;
import lime.utils.Assets as LimeAssets; import lime.utils.Assets as LimeAssets;
import openfl.Assets; import openfl.Assets;
import openfl.events.Event; import openfl.events.Event;
@ -33,13 +37,8 @@ import openfl.events.IOErrorEvent;
import openfl.geom.Rectangle; import openfl.geom.Rectangle;
import openfl.net.FileReference; import openfl.net.FileReference;
import openfl.net.URLLoader; import openfl.net.URLLoader;
import funkin.ui.mainmenu.MainMenuState;
import openfl.net.URLRequest; import openfl.net.URLRequest;
import openfl.utils.ByteArray; import openfl.utils.ByteArray;
import funkin.input.Cursor;
import funkin.play.character.CharacterData.CharacterDataParser;
import funkin.util.SortUtil;
import haxe.ui.core.Screen;
using flixel.util.FlxSpriteUtil; using flixel.util.FlxSpriteUtil;

View file

@ -4948,7 +4948,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
playbarNoteSnap.text = '1/${noteSnapQuant}'; playbarNoteSnap.text = '1/${noteSnapQuant}';
playbarDifficulty.text = '${selectedDifficulty.toTitleCase()}'; playbarDifficulty.text = '${selectedDifficulty.toTitleCase()}';
// playbarBPM.text = 'BPM: ${(Conductor.currentTimeChange?.bpm ?? 0.0)}'; playbarBPM.text = 'BPM: ${(Conductor.instance.bpm ?? 0.0)}';
} }
function handlePlayhead():Void function handlePlayhead():Void

View file

@ -1013,7 +1013,14 @@ class FreeplayState extends MusicBeatSubState
// Set the difficulty star count on the right. // Set the difficulty star count on the right.
albumRoll.setDifficultyStars(daSong?.songRating); albumRoll.setDifficultyStars(daSong?.songRating);
albumRoll.albumId = daSong?.albumId ?? Constants.DEFAULT_ALBUM_ID;
// Set the album graphic and play the animation if relevant.
var newAlbumId:String = daSong?.albumId ?? Constants.DEFAULT_ALBUM_ID;
if (albumRoll.albumId != newAlbumId)
{
albumRoll.albumId = newAlbumId;
albumRoll.playIntro();
}
} }
// Clears the cache of songs, frees up memory, they' ll have to be loaded in later tho function clearDaCache(actualSongTho:String) // Clears the cache of songs, frees up memory, they' ll have to be loaded in later tho function clearDaCache(actualSongTho:String)

View file

@ -450,7 +450,11 @@ class StoryMenuState extends MusicBeatState
*/ */
function changeDifficulty(change:Int = 0):Void function changeDifficulty(change:Int = 0):Void
{ {
var difficultyList:Array<String> = currentLevel.getDifficulties(); // "For now, NO erect in story mode" -Dave
var difficultyList:Array<String> = Constants.DEFAULT_DIFFICULTY_LIST;
// Use this line to displays all difficulties
// var difficultyList:Array<String> = currentLevel.getDifficulties();
var currentIndex:Int = difficultyList.indexOf(currentDifficultyId); var currentIndex:Int = difficultyList.indexOf(currentDifficultyId);
currentIndex += change; currentIndex += change;

View file

@ -157,6 +157,11 @@ class Constants
*/ */
public static final DEFAULT_VARIATION:String = 'default'; public static final DEFAULT_VARIATION:String = 'default';
/**
* Standard variations used by the game.
*/
public static final DEFAULT_VARIATION_LIST:Array<String> = ['default', 'erect', 'pico'];
/** /**
* The default intensity for camera zooms. * The default intensity for camera zooms.
*/ */