1
0
Fork 0
mirror of https://github.com/ninjamuffin99/Funkin.git synced 2025-03-23 02:19:46 +00:00

Merge branch 'master-bugs' into rewrite/master

This commit is contained in:
Cameron Taylor 2024-09-12 14:34:21 -04:00
commit 3de7047d22
13 changed files with 165 additions and 106 deletions

2
art

@ -1 +1 @@
Subproject commit e2663c1cbe029f04a98500735943f0b9465548bf
Subproject commit 0bb988c49788fd25a230b56dd9e4448838bc79c9

2
assets

@ -1 +1 @@
Subproject commit a00554b4c78d3d1da18436bc285ccbe1f4ea98f2
Subproject commit 335fac6af6b3362b1de5f233865486eaf9fbae11

View file

@ -95,7 +95,7 @@ class FlxAtlasSprite extends FlxAnimate
*/
public function hasAnimation(id:String):Bool
{
return getLabelIndex(id) != -1;
return getLabelIndex(id) != -1 || anim.symbolDictionary.exists(id);
}
/**
@ -112,6 +112,8 @@ class FlxAtlasSprite extends FlxAnimate
var looping:Bool = false;
public var ignoreExclusionPref:Array<String> = [];
/**
* Plays an animation.
* @param id A string ID of the animation to play.
@ -124,7 +126,25 @@ class FlxAtlasSprite extends FlxAnimate
public function playAnimation(id:String, restart:Bool = false, ignoreOther:Bool = false, loop:Bool = false, startFrame:Int = 0):Void
{
// Skip if not allowed to play animations.
if ((!canPlayOtherAnims && !ignoreOther)) return;
if ((!canPlayOtherAnims))
{
if (this.currentAnimation == id && restart) {}
else if (ignoreExclusionPref != null && ignoreExclusionPref.length > 0)
{
var detected:Bool = false;
for (entry in ignoreExclusionPref)
{
if (StringTools.startsWith(id, entry))
{
detected = true;
break;
}
}
if (!detected) return;
}
else
return;
}
if (anim == null) return;
@ -132,38 +152,29 @@ class FlxAtlasSprite extends FlxAnimate
if (this.currentAnimation == id && !restart)
{
if (anim.isPlaying)
{
// Skip if animation is already playing.
return;
}
else
if (!anim.isPlaying)
{
if (fr != null) anim.curFrame = fr.index + startFrame;
else
anim.curFrame = startFrame;
// Resume animation if it's paused.
anim.play('', restart, false, startFrame);
anim.resume();
}
return;
}
else
else if (!hasAnimation(id))
{
// Skip if the animation doesn't exist
if (!hasAnimation(id))
{
trace('Animation ' + id + ' not found');
return;
}
trace('Animation ' + id + ' not found');
return;
}
this.currentAnimation = id;
anim.onComplete.removeAll();
anim.onComplete.add(function() {
if (loop)
{
this.anim.play(id, restart, false, startFrame);
this.currentAnimation = id;
}
else
{
onAnimationComplete.dispatch(id);
}
_onAnimationComplete();
});
looping = loop;
@ -177,16 +188,17 @@ class FlxAtlasSprite extends FlxAnimate
if (this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null))
{
this.anim.play(id, restart, false, startFrame);
if (id == "Boyfriend DJ fist pump" || startFrame == 4) trace("PUMP COMMAND: " + anim.curFrame);
fr = null;
}
// Only call goToFrameLabel if there is a frame label with that name. This prevents annoying warnings!
if (getFrameLabelNames().indexOf(id) != -1)
{
goToFrameLabel(id);
fr = anim.getFrameLabel(id);
anim.curFrame += startFrame;
}
anim.curFrame += startFrame;
this.currentAnimation = id;
}
override public function update(elapsed:Float)
@ -284,12 +296,13 @@ class FlxAtlasSprite extends FlxAnimate
{
anim.pause();
_onAnimationComplete();
if (looping)
{
anim.curFrame = (fr != null) ? fr.index : 0;
anim.resume();
}
else
else if (fr != null && anim.curFrame != anim.length - 1)
{
anim.curFrame--;
}

View file

@ -194,6 +194,7 @@ class ResultState extends MusicBeatSubState
{
// Animation is not looped.
animation.onAnimationComplete.add((_name:String) -> {
trace("AHAHAH 2");
if (animation != null)
{
animation.anim.pause();
@ -203,9 +204,10 @@ class ResultState extends MusicBeatSubState
else if (animData.loopFrameLabel != null)
{
animation.onAnimationComplete.add((_name:String) -> {
trace("AHAHAH 2");
if (animation != null)
{
animation.playAnimation(animData.loopFrameLabel ?? ''); // unpauses this anim, since it's on PlayOnce!
animation.playAnimation(animData.loopFrameLabel ?? '', true, false, true); // unpauses this anim, since it's on PlayOnce!
}
});
}
@ -214,6 +216,7 @@ class ResultState extends MusicBeatSubState
animation.onAnimationComplete.add((_name:String) -> {
if (animation != null)
{
trace("AHAHAH");
animation.anim.curFrame = animData.loopFrame ?? 0;
animation.anim.play(); // unpauses this anim, since it's on PlayOnce!
}

View file

@ -166,6 +166,8 @@ class AnimateAtlasCharacter extends BaseCharacter
this.mainSprite = sprite;
mainSprite.ignoreExclusionPref = ["sing"];
// This forces the atlas to recalcuate its width and height
this.mainSprite.alpha = 0.0001;
this.mainSprite.draw();

View file

@ -151,6 +151,8 @@ class BaseCharacter extends Bopper
super(CharacterDataParser.DEFAULT_DANCEEVERY);
this.characterId = id;
ignoreExclusionPref = ["sing"];
_data = CharacterDataParser.fetchCharacterData(this.characterId);
if (_data == null)
{

View file

@ -260,6 +260,8 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
public var canPlayOtherAnims:Bool = true;
public var ignoreExclusionPref:Array<String> = [];
/**
* @param name The name of the animation to play.
* @param restart Whether to restart the animation if it is already playing.
@ -268,7 +270,26 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
*/
public function playAnimation(name:String, restart:Bool = false, ignoreOther:Bool = false, reversed:Bool = false):Void
{
if (!canPlayOtherAnims && !ignoreOther) return;
if ((!canPlayOtherAnims))
{
var id = name;
if (getCurrentAnimation() == id && restart) {}
else if (ignoreExclusionPref != null && ignoreExclusionPref.length > 0)
{
var detected:Bool = false;
for (entry in ignoreExclusionPref)
{
if (StringTools.startsWith(id, entry))
{
detected = true;
break;
}
}
if (!detected) return;
}
else
return;
}
var correctName = correctAnimationName(name);
if (correctName == null) return;

View file

@ -125,6 +125,7 @@ class Save
{
// Default to having seen the default character.
charactersSeen: ["bf"],
oldChar: false
},
optionsChartEditor:
@ -406,6 +407,18 @@ class Save
return data.unlocks.charactersSeen;
}
public var oldChar(get, set):Bool;
function get_oldChar():Bool
{
return data.unlocks.oldChar;
}
function set_oldChar(value:Bool):Bool
{
return data.unlocks.oldChar = value;
}
/**
* When we've seen a character unlock, add it to the list of characters seen.
* @param character
@ -1027,6 +1040,12 @@ typedef SaveDataUnlocks =
* add it to this list so that we don't show it again.
*/
var charactersSeen:Array<String>;
/**
* This is a conditional when the player enters the character state
* For the first time ever
*/
var oldChar:Bool;
}
/**

View file

@ -27,7 +27,7 @@ class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass
case "deselect":
playAnimation("deselect loop start", true, false, true);
case "slidein idle point", "cannot select", "unlock":
case "slidein idle point", "cannot select Label", "unlock":
playAnimation("idle", true, false, false);
case "idle":
trace('Waiting for onBeatHit');

View file

@ -35,55 +35,44 @@ import openfl.filters.ShaderFilter;
import funkin.util.FramesJSFLParser;
import funkin.util.FramesJSFLParser.FramesJSFLInfo;
import funkin.util.FramesJSFLParser.FramesJSFLFrame;
import funkin.graphics.FunkinSprite;
class CharSelectSubState extends MusicBeatSubState
{
var cursor:FlxSprite;
var cursorBlue:FlxSprite;
var cursorDarkBlue:FlxSprite;
var grpCursors:FlxTypedGroup<FlxSprite>;
var cursorConfirmed:FlxSprite;
var cursorDenied:FlxSprite;
var cursorX:Int = 0;
var cursorY:Int = 0;
var cursorFactor:Float = 110;
var cursorOffsetX:Float = -16;
var cursorOffsetY:Float = -48;
var cursorLocIntended:FlxPoint = new FlxPoint(0, 0);
var lerpAmnt:Float = 0.95;
var tmrFrames:Int = 60;
var currentStage:Stage;
var playerChill:CharSelectPlayer;
var playerChillOut:CharSelectPlayer;
var gfChill:CharSelectGF;
var gfChillOut:CharSelectGF;
var barthing:FlxAtlasSprite;
var dipshitBacking:FlxSprite;
var chooseDipshit:FlxSprite;
var dipshitBlur:FlxSprite;
var transitionGradient:FlxSprite;
var curChar(default, set):String = "pico";
var nametag:Nametag;
var camFollow:FlxObject;
var autoFollow:Bool = false;
var availableChars:Map<Int, String> = new Map<Int, String>();
var pressedSelect:Bool = false;
var selectTimer:FlxTimer = new FlxTimer();
var selectSound:FunkinSound;
var unlockSound:FunkinSound;
var charSelectCam:FunkinCamera;
var selectedBizz:Array<BitmapFilter> = [
@ -92,6 +81,7 @@ class CharSelectSubState extends MusicBeatSubState
];
var bopInfo:FramesJSFLInfo;
var blackScreen:FunkinSprite;
public function new()
{
@ -125,11 +115,6 @@ class CharSelectSubState extends MusicBeatSubState
override public function create():Void
{
openSubState(new IntroSubState());
subStateClosed.addOnce((_) -> {
camera.flash();
checkNewChar();
});
super.create();
bopInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/iconBopInfo/iconBopInfo.txt"));
@ -365,6 +350,20 @@ class CharSelectSubState extends MusicBeatSubState
FlxG.camera.follow(camFollow, LOCKON, 0.01);
}
});
var blackScreen = new FunkinSprite().makeSolidColor(FlxG.width * 2, FlxG.height * 2, 0xFF000000);
blackScreen.x = -(FlxG.width * 0.5);
blackScreen.y = -(FlxG.height * 0.5);
add(blackScreen);
openSubState(new IntroSubState());
subStateClosed.addOnce((_) -> {
remove(blackScreen);
if (!Save.instance.oldChar) camera.flash();
checkNewChar();
Save.instance.oldChar = true;
});
}
function checkNewChar():Void
@ -396,7 +395,6 @@ class CharSelectSubState extends MusicBeatSubState
var grpIcons:FlxSpriteGroup;
var grpXSpread(default, set):Float = 107;
var grpYSpread(default, set):Float = 127;
var nonLocks = [];
function initLocks():Void
@ -426,9 +424,9 @@ class CharSelectSubState extends MusicBeatSubState
var temp:Lock = new Lock(0, 0, i);
temp.ID = 1;
temp.onAnimationComplete.add(function(anim) {
if (anim == "unlock") playerChill.playAnimation("unlock", true);
});
// temp.onAnimationComplete.add(function(anim) {
// if (anim == "unlock") playerChill.playAnimation("unlock", true);
// });
grpIcons.add(temp);
}
@ -443,7 +441,7 @@ class CharSelectSubState extends MusicBeatSubState
{
var index = nonLocks[0];
// pressedSelect = true;
pressedSelect = true;
var copy = 3;
@ -478,7 +476,7 @@ class CharSelectSubState extends MusicBeatSubState
syncLock = lock;
// sync = true;
sync = true;
lock.onAnimationComplete.addOnce(function(_) {
syncLock = null;
@ -561,9 +559,7 @@ class CharSelectSubState extends MusicBeatSubState
}
var sync:Bool = false;
var syncLock:Lock = null;
var audioBizz:Float = 0;
function syncAudio(elapsed:Float):Void
@ -580,8 +576,6 @@ class CharSelectSubState extends MusicBeatSubState
playerChillOut.anim._tick = 0;
if (syncLock != null) syncLock.anim._tick = 0;
trace(unlockSound.time);
if ((unlockSound.time - audioBizz) >= (delay * 1000))
{
if (syncLock != null) syncLock.anim._tick = delay;
@ -738,7 +732,7 @@ class CharSelectSubState extends MusicBeatSubState
{
curChar = availableChars.get(getCurrentSelected());
if (controls.ACCEPT)
if (!pressedSelect && controls.ACCEPT)
{
cursorConfirmed.visible = true;
cursorConfirmed.x = cursor.x - 2;
@ -775,6 +769,7 @@ class CharSelectSubState extends MusicBeatSubState
FlxTween.tween(FlxG.sound.music, {pitch: 1.0, volume: 1.0}, 1, {ease: FlxEase.quartInOut});
playerChill.playAnimation("deselect");
gfChill.playAnimation("deselect");
pressedSelect = false;
FlxTween.tween(FlxG.sound.music, {pitch: 1.0}, 1,
{
ease: FlxEase.quartInOut,
@ -783,7 +778,6 @@ class CharSelectSubState extends MusicBeatSubState
gfChill.playAnimation("idle", true, false, true);
}
});
pressedSelect = false;
selectTimer.cancel();
}
}
@ -797,7 +791,7 @@ class CharSelectSubState extends MusicBeatSubState
cursorDenied.x = cursor.x - 2;
cursorDenied.y = cursor.y - 4;
playerChill.playAnimation("cannot select", true);
playerChill.playAnimation("cannot select Label", true);
cursorDenied.animation.play("idle", true);
cursorDenied.animation.finishCallback = (_) -> {
cursorDenied.visible = false;
@ -831,13 +825,9 @@ class CharSelectSubState extends MusicBeatSubState
}
var bopTimer:Float = 0;
var delay = 1 / 24;
var bopFr = 0;
var bopPlay:Bool = false;
var bopRefX:Float = 0;
var bopRefY:Float = 0;
@ -957,10 +947,10 @@ class CharSelectSubState extends MusicBeatSubState
memb.filters = selectedBizz;
memb.scale.set(2.6, 2.6);
}
if (controls.ACCEPT && memb.animation.curAnim.name == "confirm") memb.animation.play("confirm");
if (pressedSelect && controls.BACK)
if (pressedSelect && memb.animation.curAnim.name == "idle") memb.animation.play("confirm");
if (!pressedSelect && memb.animation.curAnim.name != "idle")
{
memb.animation.play("confirm", true, true);
memb.animation.play("confirm", false, true);
member.animation.finishCallback = (_) -> {
member.animation.play("idle");
member.animation.finishCallback = null;

View file

@ -8,22 +8,24 @@ import hxcodec.flixel.FlxVideoSprite;
#end
import funkin.ui.MusicBeatSubState;
import funkin.audio.FunkinSound;
import funkin.save.Save;
/**
* After about 2 minutes of inactivity on the title screen,
* the game will enter the Attract state, as a reference to physical arcade machines.
*
* In the current version, this just plays the ~~Kickstarter trailer~~ Erect teaser, but this can be changed to
* gameplay footage, a generic game trailer, or something more elaborate.
* When you first enter the character select state, it will play an introductory video opening up the lights
*/
class IntroSubState extends MusicBeatSubState
{
static final ATTRACT_VIDEO_PATH:String = Paths.stripLibrary(Paths.videos('introSelect'));
static final LIGHTS_VIDEO_PATH:String = Paths.stripLibrary(Paths.videos('introSelect'));
var introSound:FunkinSound = null;
public override function create():Void
{
if (Save.instance.oldChar)
{
onLightsEnd();
return;
}
// Pause existing music.
if (FlxG.sound.music != null)
{
@ -32,15 +34,20 @@ class IntroSubState extends MusicBeatSubState
}
#if html5
trace('Playing web video ${ATTRACT_VIDEO_PATH}');
playVideoHTML5(ATTRACT_VIDEO_PATH);
trace('Playing web video ${LIGHTS_VIDEO_PATH}');
playVideoHTML5(LIGHTS_VIDEO_PATH);
#end
#if hxCodec
trace('Playing native video ${ATTRACT_VIDEO_PATH}');
playVideoNative(ATTRACT_VIDEO_PATH);
trace('Playing native video ${LIGHTS_VIDEO_PATH}');
playVideoNative(LIGHTS_VIDEO_PATH);
#end
// Im TOO lazy to even care, so uh, yep
FlxG.camera.zoom = 0.66666666666666666666666666666667;
vid.x = -(FlxG.width - (FlxG.width * FlxG.camera.zoom));
vid.y = -((FlxG.height - (FlxG.height * FlxG.camera.zoom)) * 0.75);
introSound = new FunkinSound();
introSound.loadEmbedded(Paths.sound('CS_Lights'));
introSound.pitch = 1;
@ -64,7 +71,7 @@ class IntroSubState extends MusicBeatSubState
{
vid.zIndex = 0;
vid.finishCallback = onAttractEnd;
vid.finishCallback = onLightsEnd;
add(vid);
}
@ -88,7 +95,7 @@ class IntroSubState extends MusicBeatSubState
if (vid != null)
{
vid.zIndex = 0;
vid.bitmap.onEndReached.add(onAttractEnd);
vid.bitmap.onEndReached.add(onLightsEnd);
add(vid);
vid.play(filePath, false);
@ -104,37 +111,33 @@ class IntroSubState extends MusicBeatSubState
{
super.update(elapsed);
if (controls.ACCEPT)
{
onAttractEnd();
}
// if (!introSound.paused)
// {
// #if html5
// @:privateAccess
// vid.netStream.seek(introSound.time);
// #elseif hxCodec
// vid.bitmap.time = Std.int(introSound.time);
// #end
// }
}
/**
* When the attraction state ends (after the video ends or the user presses any button),
* switch immediately to the title screen.
* When the lights video finishes, it will close the substate
*/
function onAttractEnd():Void
function onLightsEnd():Void
{
#if html5
if (vid != null)
{
remove(vid);
}
#end
#if hxCodec
if (vid != null)
{
#if hxCodec
vid.stop();
#end
remove(vid);
vid.destroy();
vid = null;
}
#end
#if (html5 || hxCodec)
vid.destroy();
vid = null;
#end
FlxG.camera.zoom = 1;
close();
}

View file

@ -141,6 +141,7 @@ class FreeplayDJ extends FlxAtlasSprite
}
else if (getCurrentAnimation() == animPrefixB)
{
trace("Loss Intro");
var endFrame = playableCharData.getFistPumpIntroBadEndFrame();
if (endFrame > -1 && anim.curFrame >= endFrame)
{
@ -166,6 +167,7 @@ class FreeplayDJ extends FlxAtlasSprite
}
else if (getCurrentAnimation() == animPrefixB)
{
trace("Loss GYATT");
var endFrame = playableCharData.getFistPumpLoopBadEndFrame();
if (endFrame > -1 && anim.curFrame >= endFrame)
{

View file

@ -273,8 +273,11 @@ class TitleState extends MusicBeatState
}
#end
if (Save.instance.charactersSeen.contains("pico")) Save.instance.charactersSeen.remove("pico");
if (Save.instance.charactersSeen.contains("pico"))
{
Save.instance.charactersSeen.remove("pico");
Save.instance.oldChar = false;
}
Conductor.instance.update();
/* if (FlxG.onMobile)
@ -523,7 +526,8 @@ class TitleState extends MusicBeatState
remove(ngSpr);
FlxG.camera.flash(FlxColor.WHITE, initialized ? 1 : 4);
remove(credGroup);
if (credGroup != null) remove(credGroup);
skippedIntro = true;
}
}