Add more stuff from the OG game and more PART 1 (#228)
* senpai fucking dies * final flash fadeout * made cutscene not play on restart * winter horrorland + fixes * fix for pixel perfect shader * trail + fixes * better + shaking last update about it, i swear * never fucking mind + repacks + accuracy * more fixes + chromatic aberration * i hate how pixel shader fucks everything up * aberration in the cutscene & its cool twitch * camera beats when twitching * tank stuff pt1 now the cutscenes look 99% like og (still gotta freeze the stage animated sprites n stuff) PS: Deleting the lipSycn function in ugh and guns cutscenes cause its not needed + sometimes breaks the animations so lets just leave it in stress only like it was in og * week 5 completed + retrocompatibility with altanim now chrima parents work * philly train * gameplay shaders option better adding it now * tank stuff pt2 * blue balled text (death counter) * winter horrorland better rework WIP colored vignette usable by everyone (you can change its color, amount and strength) wip cuz i wanna edit the amount/strength based on the zoom, i'll do later, now i dont have time gotta do christmas irl stuff yay * winter horrorland better rework completed * seen cutscene variable finally * even better cutscenes * oops * tank stuff pt3 * tank stuff pt4 WIP running tanks Co-Authored-By: Ne_Eo <NeeEoo@users.noreply.github.com> * tankstuff pt4.5 imma check tmr why do some tankmen spawn too much up * tank stuff pt4.75 * dumb * tank stuff pt 4.9 * type on xml sprite type fix and more Co-Authored-By: Ne_Eo <NeeEoo@users.noreply.github.com> --------- Co-authored-by: Ne_Eo <NeeEoo@users.noreply.github.com> Co-authored-by: lunarcleint <88809950+lunarcleint@users.noreply.github.com>
This commit is contained in:
co-authored by
Ne_Eo
lunarcleint
parent
a71a02ea94
commit
6e23da8e86
@@ -1,5 +1,6 @@
|
||||
package funkin.backend;
|
||||
|
||||
import funkin.backend.utils.XMLUtil.BeatAnim;
|
||||
import funkin.backend.utils.XMLUtil.AnimData;
|
||||
import funkin.backend.utils.XMLUtil.IXMLEvents;
|
||||
import flixel.system.FlxAssets.FlxGraphicAsset;
|
||||
@@ -34,13 +35,17 @@ abstract XMLAnimType(Int)
|
||||
class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements IOffsetCompatible implements IXMLEvents
|
||||
{
|
||||
public var spriteAnimType:XMLAnimType = NONE;
|
||||
public var beatAnims:Array<String> = [];
|
||||
public var beatAnims:Array<BeatAnim> = [];
|
||||
public var name:String;
|
||||
public var zoomFactor:Float = 1;
|
||||
public var initialZoom:Float = 1;
|
||||
public var debugMode:Bool = false;
|
||||
public var animDatas:Map<String, AnimData> = [];
|
||||
|
||||
public var beatInterval:Int = 1;
|
||||
public var beatOffset:Int = 0;
|
||||
public var skipNegativeBeats:Bool = false;
|
||||
|
||||
public var animateAtlas:FlxAnimate;
|
||||
@:noCompletion public var atlasPlayingAnim:String;
|
||||
@:noCompletion public var atlasPath:String;
|
||||
@@ -108,13 +113,16 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
||||
moves = true;
|
||||
}
|
||||
|
||||
private var countedBeat = 0;
|
||||
public function beatHit(curBeat:Int)
|
||||
{
|
||||
if (beatAnims.length > 0)
|
||||
if (beatAnims.length > 0 && (curBeat + beatOffset) % beatInterval == 0)
|
||||
{
|
||||
var anim = beatAnims[FlxMath.wrap(curBeat, 0, beatAnims.length - 1)];
|
||||
if (anim != null && anim != "null" && anim != "none")
|
||||
playAnim(anim);
|
||||
if(skipNegativeBeats && curBeat < 0) return;
|
||||
// TODO: find a solution without countedBeat
|
||||
var anim = beatAnims[FlxMath.wrap(countedBeat++, 0, beatAnims.length - 1)];
|
||||
if (anim.name != null && anim.name != "null" && anim.name != "none")
|
||||
playAnim(anim.name, anim.forced);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ class BaseGameParser {
|
||||
result.meta.needsVoices = data.needsVoices.getDefault(true);
|
||||
|
||||
var camFocusedBF:Bool = false;
|
||||
var altAnims:Bool = false;
|
||||
var beatsPerMesure:Float = data.beatsPerMesure.getDefault(4);
|
||||
var curBPM:Float = data.bpm;
|
||||
var curTime:Float = 0;
|
||||
@@ -60,6 +61,15 @@ class BaseGameParser {
|
||||
});
|
||||
}
|
||||
|
||||
if (section.altAnim == null) section.altAnim = false;
|
||||
if (altAnims != (altAnims = section.altAnim)) {
|
||||
result.events.push({
|
||||
time: curTime,
|
||||
name: "Alt Animation Toggle",
|
||||
params: [0, altAnims]
|
||||
});
|
||||
}
|
||||
|
||||
if (section.sectionNotes != null) for(note in section.sectionNotes) {
|
||||
if (note[1] < 0) continue;
|
||||
|
||||
@@ -129,6 +139,6 @@ typedef SwagSection =
|
||||
var mustHitSection:Bool;
|
||||
var bpm:Float;
|
||||
var changeBPM:Bool;
|
||||
var altAnim:Bool;
|
||||
var altAnim:Null<Bool>;
|
||||
@:optional var camTarget:Null<Float>;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class ScriptsMacro {
|
||||
"flixel.addons.plugin", "flixel.addons.text", "flixel.addons.tile", "flixel.addons.transition",
|
||||
"flixel.addons.util",
|
||||
// OTHER LIBRARIES & STUFF
|
||||
"away3d", "flx3d",
|
||||
#if THREE_D_SUPPORT "away3d", "flx3d", #end
|
||||
#if VIDEO_CUTSCENES "hxvlc.flixel", "hxvlc.openfl", #end
|
||||
// BASE HAXE
|
||||
"DateTools", "EReg", "Lambda", "StringBuf", "haxe.crypto", "haxe.display", "haxe.exceptions", "haxe.extern", "scripting"
|
||||
|
||||
@@ -28,6 +28,16 @@ class CoolUtil
|
||||
public static function getLastExceptionStack():String {
|
||||
return CallStack.toString(CallStack.exceptionStack());
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns `v` if not null
|
||||
* @param v The value
|
||||
* @return A bool value
|
||||
*/
|
||||
public static inline function isNotNull(v:Null<Dynamic>):Bool {
|
||||
return v != null && !isNaN(v);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns `v` if not null, `defaultValue` otherwise.
|
||||
* @param v The value
|
||||
|
||||
@@ -21,7 +21,7 @@ class XMLUtil {
|
||||
*/
|
||||
public static function applyXMLProperty(object:Dynamic, property:Access):ErrorCode {
|
||||
if (!property.has.name || !property.has.type || !property.has.value) {
|
||||
Logs.trace('Failed to apply XML property: XML Element misses name, type, or value attributes.', WARNING);
|
||||
Logs.trace('Failed to apply XML property: XML Element is missing name, type, or value attributes.', WARNING);
|
||||
return MISSING_PROPERTY;
|
||||
}
|
||||
|
||||
@@ -72,54 +72,86 @@ class XMLUtil {
|
||||
|
||||
spr.loadSprite(Paths.image('$parentFolder${node.getAtt("sprite")}', null, true));
|
||||
|
||||
if (spr.frames != null && spr.frames.frames != null) {
|
||||
spr.animation.add("idle", [for(i in 0...spr.frames.frames.length) i], 24, true);
|
||||
spr.animation.play("idle");
|
||||
spr.spriteAnimType = defaultAnimType;
|
||||
if (node.has.type) {
|
||||
spr.spriteAnimType = XMLAnimType.fromString(node.att.type, spr.spriteAnimType);
|
||||
}
|
||||
|
||||
spr.spriteAnimType = defaultAnimType;
|
||||
if (node.has.type)
|
||||
spr.spriteAnimType = XMLAnimType.fromString(node.att.type, spr.spriteAnimType);
|
||||
|
||||
var x:Null<Float> = node.has.x ? Std.parseFloat(node.att.x) : null;
|
||||
var y:Null<Float> = node.has.y ? Std.parseFloat(node.att.y) : null;
|
||||
if (x != null) spr.x = x;
|
||||
if (y != null) spr.y = y;
|
||||
if(node.has.x) {
|
||||
var x:Null<Float> = Std.parseFloat(node.att.x);
|
||||
if (x.isNotNull()) spr.x = x;
|
||||
}
|
||||
if(node.has.y) {
|
||||
var y:Null<Float> = Std.parseFloat(node.att.y);
|
||||
if (y.isNotNull()) spr.y = y;
|
||||
}
|
||||
if (node.has.scroll) {
|
||||
var scroll:Null<Float> = Std.parseFloat(node.att.scroll);
|
||||
if (scroll != null) spr.scrollFactor.set(scroll, scroll);
|
||||
if (scroll.isNotNull()) spr.scrollFactor.set(scroll, scroll);
|
||||
} else {
|
||||
if (node.has.scrollx) {
|
||||
var scroll:Null<Float> = Std.parseFloat(node.att.scrollx);
|
||||
if (scroll != null) spr.scrollFactor.x = scroll;
|
||||
if (scroll.isNotNull()) spr.scrollFactor.x = scroll;
|
||||
}
|
||||
if (node.has.scrolly) {
|
||||
var scroll:Null<Float> = Std.parseFloat(node.att.scrolly);
|
||||
if (scroll != null) spr.scrollFactor.y = scroll;
|
||||
if (scroll.isNotNull()) spr.scrollFactor.y = scroll;
|
||||
}
|
||||
}
|
||||
if (node.has.skewx) {
|
||||
var skew:Null<Float> = Std.parseFloat(node.att.skewx);
|
||||
if (skew != null) spr.skew.x = skew;
|
||||
if (skew.isNotNull()) spr.skew.x = skew;
|
||||
}
|
||||
if (node.has.skewy) {
|
||||
var skew:Null<Float> = Std.parseFloat(node.att.skewy);
|
||||
if (skew != null) spr.skew.y = skew;
|
||||
if (skew.isNotNull()) spr.skew.y = skew;
|
||||
}
|
||||
if (node.has.antialiasing) spr.antialiasing = node.att.antialiasing == "true";
|
||||
if (node.has.scale) {
|
||||
var scale:Null<Float> = Std.parseFloat(node.att.scale);
|
||||
if (scale != null) spr.scale.set(scale, scale);
|
||||
if (scale.isNotNull()) spr.scale.set(scale, scale);
|
||||
}
|
||||
if (node.has.scalex) {
|
||||
var scale:Null<Float> = Std.parseFloat(node.att.scalex);
|
||||
if (scale.isNotNull()) spr.scale.x = scale;
|
||||
}
|
||||
if (node.has.scaley) {
|
||||
var scale:Null<Float> = Std.parseFloat(node.att.scaley);
|
||||
if (scale.isNotNull()) spr.scale.y = scale;
|
||||
}
|
||||
if (node.has.updateHitbox && node.att.updateHitbox == "true") spr.updateHitbox();
|
||||
|
||||
spr.zoomFactor = Std.parseFloat(node.getAtt("zoomfactor")).getDefault(spr.zoomFactor);
|
||||
if(node.has.zoomfactor)
|
||||
spr.zoomFactor = Std.parseFloat(node.getAtt("zoomfactor")).getDefault(spr.zoomFactor);
|
||||
|
||||
if (node.has.alpha)
|
||||
spr.alpha = Std.parseFloat(node.getAtt("alpha")).getDefault(spr.alpha);
|
||||
|
||||
for(anim in node.nodes.anim)
|
||||
addXMLAnimation(spr, anim);
|
||||
if (node.has.playOnCountdown)
|
||||
spr.skipNegativeBeats = node.att.playOnCountdown == "true";
|
||||
if (node.has.beatInterval)
|
||||
spr.beatInterval = Std.parseInt(node.att.beatInterval);
|
||||
if (node.has.beatOffset)
|
||||
spr.beatOffset = Std.parseInt(node.att.beatOffset);
|
||||
|
||||
if(node.hasNode.anim) {
|
||||
for(anim in node.nodes.anim)
|
||||
addXMLAnimation(spr, anim);
|
||||
} else {
|
||||
if (spr.frames != null && spr.frames.frames != null) {
|
||||
addAnimToSprite(spr, {
|
||||
name: "idle",
|
||||
anim: null,
|
||||
fps: 24,
|
||||
loop: spr.spriteAnimType == LOOP,
|
||||
animType: spr.spriteAnimType,
|
||||
x: 0,
|
||||
y: 0,
|
||||
indices: [for(i in 0...spr.frames.frames.length) i],
|
||||
forced: (node.has.forced && node.att.forced == "true") || (!node.has.forced && spr.spriteAnimType == BEAT)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return spr;
|
||||
}
|
||||
@@ -133,16 +165,18 @@ class XMLUtil {
|
||||
animType: animType,
|
||||
x: 0,
|
||||
y: 0,
|
||||
indices: []
|
||||
indices: [],
|
||||
forced: false,
|
||||
};
|
||||
|
||||
if (anim.has.name) animData.name = anim.att.name;
|
||||
if (anim.has.type) animData.animType = XMLAnimType.fromString(anim.att.type, animData.animType);
|
||||
if (anim.has.anim) animData.anim = anim.att.anim;
|
||||
if (anim.has.fps) animData.fps = Std.parseFloat(anim.att.fps);
|
||||
if (anim.has.x) animData.x = Std.parseFloat(anim.att.x);
|
||||
if (anim.has.y) animData.y = Std.parseFloat(anim.att.y);
|
||||
if (anim.has.fps) animData.fps = Std.parseFloat(anim.att.fps).getDefault(animData.fps);
|
||||
if (anim.has.x) animData.x = Std.parseFloat(anim.att.x).getDefault(animData.x);
|
||||
if (anim.has.y) animData.y = Std.parseFloat(anim.att.y).getDefault(animData.y);
|
||||
if (anim.has.loop) animData.loop = anim.att.loop == "true";
|
||||
if (anim.has.forced) animData.forced = anim.att.forced == "true";
|
||||
if (anim.has.indices) {
|
||||
var indicesSplit = anim.att.indices.split(",");
|
||||
for(indice in indicesSplit) {
|
||||
@@ -161,24 +195,30 @@ class XMLUtil {
|
||||
*/
|
||||
public static function addXMLAnimation(sprite:FlxSprite, anim:Access, loop:Bool = false):ErrorCode {
|
||||
var animType:XMLAnimType = NONE;
|
||||
if (sprite is FunkinSprite)
|
||||
if (sprite is FunkinSprite) {
|
||||
animType = cast(sprite, FunkinSprite).spriteAnimType;
|
||||
}
|
||||
|
||||
return addAnimToSprite(sprite, extractAnimFromXML(anim, animType, loop));
|
||||
}
|
||||
|
||||
public static function addAnimToSprite(sprite:FlxSprite, animData:AnimData):ErrorCode {
|
||||
if (animData.name != null && animData.anim != null) {
|
||||
if (animData.name != null) {
|
||||
if (animData.fps <= 0 #if web || animData.fps == null #end) animData.fps = 24;
|
||||
|
||||
if (sprite is FunkinSprite && cast(sprite, FunkinSprite).animateAtlas != null) {
|
||||
var animateAnim = cast(sprite, FunkinSprite).animateAtlas.anim;
|
||||
if(animData.anim == null)
|
||||
return MISSING_PROPERTY;
|
||||
|
||||
if (animData.indices.length > 0)
|
||||
animateAnim.addBySymbolIndices(animData.name, animData.anim, animData.indices, animData.fps, animData.loop);
|
||||
else
|
||||
animateAnim.addBySymbol(animData.name, animData.anim, animData.fps, animData.loop);
|
||||
} else {
|
||||
if (animData.indices.length > 0)
|
||||
if (animData.anim == null && animData.indices.length > 0)
|
||||
sprite.animation.add(animData.name, animData.indices, animData.fps, animData.loop);
|
||||
else if (animData.indices.length > 0)
|
||||
sprite.animation.addByIndices(animData.name, animData.anim, animData.indices, "", animData.fps, animData.loop);
|
||||
else
|
||||
sprite.animation.addByPrefix(animData.name, animData.anim, animData.fps, animData.loop);
|
||||
@@ -191,9 +231,12 @@ class XMLUtil {
|
||||
var xmlSpr = cast(sprite, FunkinSprite);
|
||||
switch(animData.animType) {
|
||||
case BEAT:
|
||||
xmlSpr.beatAnims.push(animData.name);
|
||||
xmlSpr.beatAnims.push({
|
||||
name: animData.name,
|
||||
forced: animData.forced.getDefault(false)
|
||||
});
|
||||
case LOOP:
|
||||
xmlSpr.animation.play(animData.name);
|
||||
xmlSpr.animation.play(animData.name, animData.forced.getDefault(false));
|
||||
default:
|
||||
// nothing
|
||||
}
|
||||
@@ -219,6 +262,12 @@ typedef AnimData = {
|
||||
var y:Float;
|
||||
var indices:Array<Int>;
|
||||
var animType:XMLAnimType;
|
||||
var ?forced:Bool;
|
||||
}
|
||||
|
||||
typedef BeatAnim = {
|
||||
var name:String;
|
||||
var forced:Bool;
|
||||
}
|
||||
|
||||
interface IXMLEvents {
|
||||
|
||||
@@ -69,6 +69,7 @@ class GameOverSubstate extends MusicBeatSubstate
|
||||
|
||||
if (controls.BACK)
|
||||
{
|
||||
PlayState.resetSongInfos();
|
||||
if (FlxG.sound.music != null)
|
||||
FlxG.sound.music.stop();
|
||||
FlxG.sound.music = null;
|
||||
|
||||
@@ -75,7 +75,7 @@ class PlayState extends MusicBeatState
|
||||
*/
|
||||
public static var opponentMode:Bool = false;
|
||||
/**
|
||||
// * Whenever the song has been started with co-op mode on.
|
||||
* Whenever the song has been started with co-op mode on.
|
||||
*/
|
||||
public static var coopMode:Bool = false;
|
||||
|
||||
@@ -89,6 +89,10 @@ class PlayState extends MusicBeatState
|
||||
*/
|
||||
public var strumLines:FlxTypedGroup<StrumLine> = new FlxTypedGroup<StrumLine>();
|
||||
|
||||
/**
|
||||
* Death counter on current week (or song if from freeplay).
|
||||
*/
|
||||
public static var deathCounter:Int = 0;
|
||||
/**
|
||||
* Game Over Song. (assets/music/gameOver.ogg)
|
||||
*/
|
||||
@@ -361,11 +365,14 @@ class PlayState extends MusicBeatState
|
||||
* Whenever the game is currently in a cutscene or not.
|
||||
*/
|
||||
public var inCutscene:Bool = false;
|
||||
|
||||
/**
|
||||
* Whenever the game should play the cutscenes. Defaults to whenever the game is currently in Story Mode or not.
|
||||
*/
|
||||
public var playCutscenes:Bool = isStoryMode;
|
||||
/**
|
||||
* Whenever the game has already played a specific cutscene for the current song. Check `startCutscene` for more details.
|
||||
*/
|
||||
public static var seenCutscene:Bool = false;
|
||||
/**
|
||||
* Cutscene script path.
|
||||
*/
|
||||
@@ -443,6 +450,7 @@ class PlayState extends MusicBeatState
|
||||
public var hitWindow:Float = Options.hitWindow; // is calculated in create(), is safeFrames in milliseconds
|
||||
|
||||
@:noCompletion @:dox(hide) private var _startCountdownCalled:Bool = false;
|
||||
@:noCompletion @:dox(hide) private var _endSongCalled:Bool = false;
|
||||
|
||||
@:dox(hide)
|
||||
var __vocalOffsetViolation:Float = 0;
|
||||
@@ -739,11 +747,15 @@ class PlayState extends MusicBeatState
|
||||
}
|
||||
|
||||
@:dox(hide) public override function createPost() {
|
||||
startCutscene("", cutscene);
|
||||
startCutscene("", cutscene, null, true);
|
||||
super.createPost();
|
||||
|
||||
updateDiscordPresence();
|
||||
|
||||
// Make icons appear in the correct spot during cutscenes
|
||||
healthBar.update(0);
|
||||
updateIconPositions();
|
||||
|
||||
__updateNote_event = EventManager.get(NoteUpdateEvent);
|
||||
|
||||
scripts.call("postCreate");
|
||||
@@ -761,10 +773,15 @@ class PlayState extends MusicBeatState
|
||||
* @param prefix Custom prefix. Using `midsong-` will require you to for example rename your video cutscene to `songs/song/midsong-cutscene.mp4` instead of `songs/song/cutscene.mp4`
|
||||
* @param cutsceneScriptPath Optional: Custom script path.
|
||||
* @param callback Callback called after the cutscene ended. If equals to `null`, `startCountdown` will be called.
|
||||
* @param checkSeen Bool that by default is false, if true and `seenCutscene` is also true, it won't play the cutscene but directly call `callback` (PS: `seenCutscene` becomes true if the cutscene gets played and `checkSeen` was true)
|
||||
*/
|
||||
public function startCutscene(prefix:String = "", ?cutsceneScriptPath:String, ?callback:Void->Void) {
|
||||
if (callback == null)
|
||||
callback = startCountdown;
|
||||
public function startCutscene(prefix:String = "", ?cutsceneScriptPath:String, ?callback:Void->Void, checkSeen:Bool = false) {
|
||||
if (callback == null) callback = startCountdown;
|
||||
if (checkSeen && seenCutscene) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
if (cutsceneScriptPath == null)
|
||||
cutsceneScriptPath = Paths.script('songs/${SONG.meta.name.toLowerCase()}/${prefix}cutscene');
|
||||
|
||||
@@ -774,28 +791,25 @@ class PlayState extends MusicBeatState
|
||||
var videoCutsceneAlt = Paths.file('songs/${PlayState.SONG.meta.name.toLowerCase()}/${prefix}cutscene.mp4');
|
||||
var dialogue = Paths.file('songs/${PlayState.SONG.meta.name.toLowerCase()}/${prefix}dialogue.xml');
|
||||
persistentUpdate = true;
|
||||
var toCall:Void->Void = function() {
|
||||
if(checkSeen) seenCutscene = true;
|
||||
callback();
|
||||
}
|
||||
|
||||
if (cutsceneScriptPath != null && Assets.exists(cutsceneScriptPath)) {
|
||||
openSubState(new ScriptedCutscene(cutsceneScriptPath, function() {
|
||||
callback();
|
||||
}));
|
||||
openSubState(new ScriptedCutscene(cutsceneScriptPath, toCall));
|
||||
} else if (Assets.exists(dialogue)) {
|
||||
MusicBeatState.skipTransIn = true;
|
||||
openSubState(new DialogueCutscene(dialogue, function() {
|
||||
callback();
|
||||
}));
|
||||
openSubState(new DialogueCutscene(dialogue, toCall));
|
||||
} else if (Assets.exists(videoCutsceneAlt)) {
|
||||
MusicBeatState.skipTransIn = true;
|
||||
persistentUpdate = false;
|
||||
openSubState(new VideoCutscene(videoCutsceneAlt, function() {
|
||||
callback();
|
||||
}));
|
||||
openSubState(new VideoCutscene(videoCutsceneAlt, toCall));
|
||||
persistentDraw = false;
|
||||
} else if (Assets.exists(videoCutscene)) {
|
||||
MusicBeatState.skipTransIn = true;
|
||||
persistentUpdate = false;
|
||||
openSubState(new VideoCutscene(videoCutscene, function() {
|
||||
callback();
|
||||
}));
|
||||
openSubState(new VideoCutscene(videoCutscene, toCall));
|
||||
persistentDraw = false;
|
||||
} else
|
||||
callback();
|
||||
@@ -850,6 +864,7 @@ class PlayState extends MusicBeatState
|
||||
sprite.scale.set(event.scale, event.scale);
|
||||
sprite.updateHitbox();
|
||||
sprite.screenCenter();
|
||||
sprite.antialiasing = event.antialiasing;
|
||||
add(sprite);
|
||||
tween = FlxTween.tween(sprite, {y: sprite.y + 100, alpha: 0}, Conductor.crochet / 1000, {
|
||||
ease: FlxEase.cubeInOut,
|
||||
@@ -913,6 +928,11 @@ class PlayState extends MusicBeatState
|
||||
Note.__customNoteTypeExists = [];
|
||||
}
|
||||
|
||||
public static function resetSongInfos() {
|
||||
deathCounter = 0;
|
||||
seenCutscene = false;
|
||||
}
|
||||
|
||||
@:dox(hide) private function generateSong(?songData:ChartData):Void
|
||||
{
|
||||
if (songData == null) songData = SONG;
|
||||
@@ -1074,6 +1094,18 @@ class PlayState extends MusicBeatState
|
||||
updateDiscordPresence();
|
||||
}
|
||||
|
||||
function updateIconPositions() {
|
||||
var iconOffset:Int = 26;
|
||||
|
||||
iconP1.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 1, 0)) - iconOffset);
|
||||
iconP2.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 1, 0))) - (iconP2.width - iconOffset);
|
||||
|
||||
health = FlxMath.bound(health, 0, maxHealth);
|
||||
|
||||
iconP1.health = healthBar.percent / 100;
|
||||
iconP2.health = 1 - (healthBar.percent / 100);
|
||||
}
|
||||
|
||||
@:dox(hide)
|
||||
override public function update(elapsed:Float)
|
||||
{
|
||||
@@ -1119,15 +1151,7 @@ class PlayState extends MusicBeatState
|
||||
iconP1.updateHitbox();
|
||||
iconP2.updateHitbox();
|
||||
|
||||
var iconOffset:Int = 26;
|
||||
|
||||
iconP1.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 1, 0)) - iconOffset);
|
||||
iconP2.x = healthBar.x + (healthBar.width * (FlxMath.remapToRange(healthBar.percent, 0, 100, 1, 0))) - (iconP2.width - iconOffset);
|
||||
|
||||
health = FlxMath.bound(health, 0, maxHealth);
|
||||
|
||||
iconP1.health = healthBar.percent / 100;
|
||||
iconP2.health = 1 - (healthBar.percent / 100);
|
||||
updateIconPositions();
|
||||
|
||||
if (startingSong)
|
||||
{
|
||||
@@ -1260,6 +1284,7 @@ class PlayState extends MusicBeatState
|
||||
if (FlxG.sound.music != null)
|
||||
FlxG.sound.music.stop();
|
||||
|
||||
deathCounter++;
|
||||
openSubState(new GameOverSubstate(character == null ? 0 : character.x, character == null ? 0 : character.y, deathCharID, character != null ? character.isPlayer : true, gameOverSong, lossSFX, retrySFX));
|
||||
}
|
||||
|
||||
@@ -1268,12 +1293,17 @@ class PlayState extends MusicBeatState
|
||||
*/
|
||||
public function endSong():Void
|
||||
{
|
||||
scripts.call("onSongEnd");
|
||||
canPause = false;
|
||||
inst.volume = 0;
|
||||
vocals.volume = 0;
|
||||
inst.pause();
|
||||
vocals.pause();
|
||||
if (!_endSongCalled) {
|
||||
_endSongCalled = true;
|
||||
|
||||
canPause = false;
|
||||
inst.volume = 0;
|
||||
vocals.volume = 0;
|
||||
inst.pause();
|
||||
vocals.pause();
|
||||
|
||||
if (scripts.event("onSongEnd", new CancellableEvent()).cancelled) return;
|
||||
}
|
||||
|
||||
if (validScore)
|
||||
{
|
||||
@@ -1289,6 +1319,7 @@ class PlayState extends MusicBeatState
|
||||
}
|
||||
|
||||
startCutscene("end-", endCutscene, nextSong);
|
||||
resetSongInfos();
|
||||
}
|
||||
|
||||
private static inline function getSongChanges():Array<HighscoreChange> {
|
||||
|
||||
@@ -77,7 +77,7 @@ class Stage extends FlxBasic implements IBeatReceiver {
|
||||
case "sprite" | "spr" | "sparrow":
|
||||
if (!node.has.sprite || !node.has.name) continue;
|
||||
|
||||
var spr = XMLUtil.createSpriteFromXML(node, spritesParentFolder, BEAT);
|
||||
var spr = XMLUtil.createSpriteFromXML(node, spritesParentFolder, LOOP);
|
||||
|
||||
if (!node.has.zoomfactor && PlayState.instance != null)
|
||||
spr.initialZoom = PlayState.instance.defaultCamZoom;
|
||||
@@ -89,8 +89,8 @@ class Stage extends FlxBasic implements IBeatReceiver {
|
||||
if ( !node.has.name || !node.has.width || !node.has.height) continue;
|
||||
|
||||
var spr = new FlxSprite(
|
||||
(node.has.x) ? Std.parseFloat(node.att.x) : 0,
|
||||
(node.has.y) ? Std.parseFloat(node.att.y) : 0
|
||||
(node.has.x) ? Std.parseFloat(node.att.x).getDefault(0) : 0,
|
||||
(node.has.y) ? Std.parseFloat(node.att.y).getDefault(0) : 0
|
||||
);
|
||||
|
||||
(node.name == "solid" ? spr.makeSolid : spr.makeGraphic)(
|
||||
|
||||
@@ -23,7 +23,7 @@ class ScriptedCutscene extends Cutscene {
|
||||
|
||||
public override function create() {
|
||||
super.create();
|
||||
trace("fuck");
|
||||
trace("fuck you");
|
||||
script.call("create");
|
||||
if (Std.isOfType(script, DummyScript)) {
|
||||
Logs.trace('Could not find script for scripted cutscene at ${scriptPath}', ERROR, RED);
|
||||
|
||||
@@ -61,6 +61,7 @@ class GitarooPause extends MusicBeatState
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayState.resetSongInfos();
|
||||
FlxG.switchState(new MainMenuState());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,15 +71,17 @@ class PauseSubState extends MusicBeatSubstate
|
||||
add(bg);
|
||||
|
||||
var levelInfo:FlxText = new FlxText(20, 15, 0, PlayState.SONG.meta.displayName, 32);
|
||||
var levelDifficulty:FlxText = new FlxText(20, 15 + 32, 0, PlayState.difficulty.toUpperCase(), 32);
|
||||
var multiplayerText:FlxText = new FlxText(20, 15 + 32 + 32, 0, PlayState.opponentMode ? 'OPPONENT MODE' : (PlayState.coopMode ? 'CO-OP MODE' : ''), 32);
|
||||
var levelDifficulty:FlxText = new FlxText(20, 15, 0, PlayState.difficulty.toUpperCase(), 32);
|
||||
var deathCounter:FlxText = new FlxText(20, 15, 0, "Blue balled: " + PlayState.deathCounter, 32);
|
||||
var multiplayerText:FlxText = new FlxText(20, 15, 0, PlayState.opponentMode ? 'OPPONENT MODE' : (PlayState.coopMode ? 'CO-OP MODE' : ''), 32);
|
||||
|
||||
for(k=>label in [levelInfo, levelDifficulty, multiplayerText]) {
|
||||
for(k=>label in [levelInfo, levelDifficulty, deathCounter, multiplayerText]) {
|
||||
label.scrollFactor.set();
|
||||
label.setFormat(Paths.font('vcr.ttf'), 32);
|
||||
label.updateHitbox();
|
||||
label.alpha = 0;
|
||||
label.x = FlxG.width - (label.width + 20);
|
||||
label.y = 15 + (32 * k);
|
||||
FlxTween.tween(label, {alpha: 1, y: label.y + 5}, 0.4, {ease: FlxEase.quartInOut, startDelay: 0.3 * (k+1)});
|
||||
add(label);
|
||||
}
|
||||
@@ -155,6 +157,7 @@ class PauseSubState extends MusicBeatSubstate
|
||||
case "Exit to charter":
|
||||
FlxG.switchState(new funkin.editors.charter.Charter(PlayState.SONG.meta.name, PlayState.difficulty, false));
|
||||
case "Exit to menu":
|
||||
PlayState.resetSongInfos();
|
||||
CoolUtil.playMenuSong();
|
||||
FlxG.switchState(PlayState.isStoryMode ? new StoryMenuState() : new FreeplayState());
|
||||
}
|
||||
|
||||
@@ -25,14 +25,15 @@ class CreditsCodename extends funkin.options.OptionsScreen {
|
||||
|
||||
public function checkUpdate():Bool {
|
||||
var curTime:Float = Date.now().getTime();
|
||||
if(Options.lastUpdated != null && curTime < Options.lastUpdated + 120000) return false; // Fuck you Github rate limits - Nex_isDumb
|
||||
if(Options.lastUpdated != null && curTime < Options.lastUpdated + 120000) return false; // Fuck you Github rate limits
|
||||
Options.lastUpdated = curTime;
|
||||
|
||||
error = false;
|
||||
//Main.execAsync(function() {
|
||||
var idk = GitHub.getContributors("FNF-CNE-Devs", "CodenameEngine", function(e) {
|
||||
error = true;
|
||||
var errMsg:String = 'Error while trying to download contributors list:\n${CoolUtil.removeIP(e.message)}';
|
||||
var errMsg:String = ~/\d+.\d+.\d+.\d+/.replace(e.message, "[Your IP]"); // Removing sensitive stuff
|
||||
errMsg = 'Error while trying to download contributors list:\n$errMsg';
|
||||
|
||||
Logs.traceColored([Logs.logText(errMsg.replace('\n', ' '), RED)], ERROR);
|
||||
funkin.backend.utils.NativeAPI.showMessageBox("Codename Engine Warning", errMsg, MSG_WARNING);
|
||||
|
||||
@@ -27,6 +27,7 @@ class Options
|
||||
public static var antialiasing:Bool = true;
|
||||
public static var volume:Float = 1;
|
||||
public static var week6PixelPerfect:Bool = true;
|
||||
public static var gameplayShaders:Bool = true;
|
||||
public static var colorHealthBar:Bool = true;
|
||||
public static var lowMemoryMode:Bool = false;
|
||||
public static var betaUpdates:Bool = false;
|
||||
@@ -54,7 +55,9 @@ class Options
|
||||
public static var contributors:Array<funkin.backend.system.github.GitHubContributor> = [];
|
||||
public static var lastUpdated:Null<Float>;
|
||||
|
||||
// CHARTER
|
||||
/**
|
||||
* CHARTER
|
||||
*/
|
||||
public static var charterMetronomeEnabled:Bool = false;
|
||||
public static var charterShowSections:Bool = true;
|
||||
public static var charterShowBeats:Bool = true;
|
||||
|
||||
@@ -23,6 +23,10 @@ class AppearanceOptions extends OptionsScreen {
|
||||
"Pixel Perfect Effect",
|
||||
"If checked, Week 6 will have a pixel perfect effect to it enabled, aligning every pixel on the screen.",
|
||||
"week6PixelPerfect"));
|
||||
add(new Checkbox(
|
||||
"Gameplay Shaders",
|
||||
"If unchecked, gameplay shaders (visual effects like Thorns's Chromatic Aberration) wont be loaded; this may be helpful on weak devices.",
|
||||
"gameplayShaders"));
|
||||
add(new Checkbox(
|
||||
"Flashing Menu",
|
||||
"If unchecked, will disable menu flashing when you select an option in the Main Menu, and other flashs will be slower",
|
||||
|
||||
Reference in New Issue
Block a user