Merge branch 'main' into base-fnf-port-remake

This commit is contained in:
⍚~Nex
2024-09-14 16:19:13 +02:00
29 changed files with 129 additions and 96 deletions
+2 -2
View File
@@ -38,12 +38,12 @@ jobs:
- name: Tar files
run: tar -zcvf CodenameEngine.tar.gz -C export/release/linux/bin .
- name: Uploading artifact (entire build)
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: Codename Engine
path: CodenameEngine.tar.gz
# - name: Uploading artifact (executable)
# uses: actions/upload-artifact@v2
# uses: actions/upload-artifact@v4
# with:
# name: Update-Linux
# path: export/release/linux/bin/CodenameEngine
+2 -2
View File
@@ -35,12 +35,12 @@ jobs:
- name: Tar files
run: tar -zcvf CodenameEngine.tar.gz -C export/release/macos/bin .
- name: Uploading artifact (entire build)
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: Codename Engine
path: CodenameEngine.tar.gz
# - name: Uploading artifact (executable)
# uses: actions/upload-artifact@v2
# uses: actions/upload-artifact@v4
# with:
# name: Update-Mac
# path: export/release/macos/bin/CodenameEngine
+2 -2
View File
@@ -33,12 +33,12 @@ jobs:
run: |
haxelib run lime build windows
- name: Uploading artifact (entire build)
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: Codename Engine
path: export/release/windows/bin
# - name: Uploading artifact (executable)
# uses: actions/upload-artifact@v2
# uses: actions/upload-artifact@v4
# with:
# name: Update-Windows
# path: export/release/windows/bin/CodenameEngine.exe
+1 -1
View File
@@ -35,7 +35,7 @@ Shoutout to the people who stuck with us throughout the alpha and supported us!
- ### New Features
- Opponent & Co-op modes
- New volume change SFX (no more loud flixel beep, customizable)
- New FPS counter allowing you to see advanced info by pressing F3.
- New FPS counter allowing you to see advanced info by pressing F3 (infos can be selected and copied too when in advanced).
- (Windows) FNF is no longer blurry on 125-150% DPI
- FNF auto fixes audio on state change when you plug in/out your headphones.
- FNF auto applies dark titlebar
+1 -1
View File
@@ -17,7 +17,7 @@ _**QOL = Quality of Life**_
- Usage of [flxanimate](https://github.com/Dot-Stuff/flxanimate) on big sprites, such as Girlfriend to save memory.
- You can further optimize it on certain stages by enabling `Low Memory Mode` in `Options > Appearance`.
- New volume change SFX (no more loud flixel beep, customizable)
- New FPS counter allowing you to see advanced info by pressing F3.
- New FPS counter allowing you to see advanced info by pressing F3 (infos can be selected and copied too when in advanced).
- Simple but advanced modding system (press TAB on main menu)
- **Windows only:**
- (Windows) FNF is no longer blurry on 125-150% DPI
+4 -2
View File
@@ -163,16 +163,18 @@ function postUpdate(elapsed) {
if (enableCameraHacks) {
for(p in strumLines)
p.notes.forEach(function(n) {
if(n.isSustainNote) return; // hacky fix for hold
n.y -= n.y % daPixelZoom;
n.x -= n.x % daPixelZoom;
});
}
var zoom = 1 / daPixelZoom / Math.min(FlxG.scaleMode.scale.x, FlxG.scaleMode.scale.y);
for(e in pixellyCameras) {
if (!e.exists) continue;
e.zoom = 1 / daPixelZoom / Math.min(FlxG.scaleMode.scale.x, FlxG.scaleMode.scale.y);
e.zoom = zoom;
}
for(e in pixellyShaders) {
e.pixelZoom = 1 / daPixelZoom / Math.min(FlxG.scaleMode.scale.x, FlxG.scaleMode.scale.y);
e.pixelZoom = zoom;
}
}
+2 -1
View File
@@ -73,7 +73,8 @@ function confText(text) {
}
function destroy() {
FlxG.cameras.remove(pauseCam);
if(FlxG.cameras.list.contains(pauseCam))
FlxG.cameras.remove(pauseCam);
}
var canDoShit = true;
+1
View File
@@ -1,3 +1,4 @@
//
import funkin.game.PlayState;
// phillyTrain is automatically added by Stage.hx
+6 -6
View File
@@ -18,17 +18,17 @@ void main() {
return;
vec4 color = getColor(camPos);
float fsteps = steps;
for(float inside = 1.0; inside < stepsInside+1.0; inside++) {
float fsteps = float(steps);
for(float inside = 1.0; inside < float(stepsInside)+1.0; inside++) {
for(int i = 0; i < steps; i++) {
float fi = i;
float fi = float(i);
color += getColor(camPos + vec2(
strength * (inside / stepsInside) * cos(fi / fsteps * (PI * 2.0)),
strength * (inside / stepsInside) * sin(fi / fsteps * (PI * 2.0))
strength * (inside / float(stepsInside)) * cos(fi / fsteps * (PI * 2.0)),
strength * (inside / float(stepsInside)) * sin(fi / fsteps * (PI * 2.0))
));
}
}
color /= steps * stepsInside;
color /= vec4(steps * stepsInside);
gl_FragColor = color;
}
+3
View File
@@ -153,6 +153,8 @@
<!-- Comment this out to disable dark mode windows -->
<define name="DARK_MODE_WINDOW"/>
<haxedef name="analyzer-optimize" />
<haxedef name="VIDEO_CUTSCENES" if="VIDEO_CUTSCENES" />
<haxedef name="UPDATE_CHECKING" if="UPDATE_CHECKING" />
<haxedef name="DISCORD_RPC" if="DISCORD_RPC" />
@@ -200,6 +202,7 @@
<haxedef name="HXCPP_CHECK_POINTER" if="release" />
<haxedef name="HXCPP_STACK_LINE" if="release" />
<haxedef name="HXCPP_DEBUG_LINK" if="release" />
<haxedef name="HXCPP_CATCH_SEGV" />
<haxedef name="hscriptPos" /> <!-- for logging -->
</project>
+7 -2
View File
@@ -103,7 +103,7 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
if (!debugMode && isAnimFinished()) {
var name = getAnimName() + '-loop';
if (hasAnimation(name))
playAnim(name, false, lastAnimContext);
playAnim(name, null, lastAnimContext);
}
}
@@ -296,11 +296,16 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
#if REGION
public var lastAnimContext:PlayAnimContext = DANCE;
public function playAnim(AnimName:String, Force:Bool = false, Context:PlayAnimContext = NONE, Reversed:Bool = false, Frame:Int = 0):Void
public function playAnim(AnimName:String, ?Force:Null<Bool>, Context:PlayAnimContext = NONE, Reversed:Bool = false, Frame:Int = 0):Void
{
if (AnimName == null)
return;
if (Force == null) {
var anim = animDatas.get(AnimName);
Force = anim != null && anim.forced;
}
if (animateAtlas != null)
{
@:privateAccess
+24 -7
View File
@@ -69,7 +69,11 @@ class EventsData {
hscriptInterp.variables.set("String", TString);
hscriptInterp.variables.set("StrumLine", TStrumLine);
hscriptInterp.variables.set("ColorWheel", TColorWheel);
hscriptInterp.variables.set("DropDown", Reflect.makeVarArgs((args) -> {return args.length > 0 ? TDropDown([for (arg in args) Std.string(arg)]) : TDropDown(["null"]);}));
hscriptInterp.variables.set("DropDown", Reflect.makeVarArgs(function(args:Array<Dynamic>):EventParamType {
var flatArgs = CoolUtil.deepFlatten(args);
if(flatArgs.length == 0) return TDropDown(["null"]);
return TDropDown([for (arg in flatArgs) Std.string(arg)]);
}));
hscriptInterp.variables.set("Character", TCharacter);
hscriptInterp.variables.set("Stage", TStage);
@@ -77,11 +81,12 @@ class EventsData {
hscriptParser.allowJSON = hscriptParser.allowMetadata = false;
for (file in Paths.getFolderContent('data/events/', true, BOTH)) {
if (Path.extension(file) != "json" && Path.extension(file) != "pack") continue;
var eventName:String = Path.withoutExtension(Path.withoutDirectory(file));
var ext = Path.extension(file);
if (ext != "json" && ext != "pack") continue;
var eventName:String = CoolUtil.getFilename(file);
var fileTxt:String = Assets.getText(file);
if (Path.extension(file) == "pack") {
if (ext == "pack") {
var arr = fileTxt.split("________PACKSEP________");
eventName = Path.withoutExtension(arr[0]);
fileTxt = arr[2];
@@ -93,13 +98,17 @@ class EventsData {
eventsParams.set(eventName, []);
try {
var data:Dynamic = Json.parse(fileTxt);
var data:EventInfoFile = cast Json.parse(fileTxt);
if (data == null || data.params == null) continue;
var finalParams:Array<EventParamInfo> = [];
for (paramData in cast(data.params, Array<Dynamic>)) {
for (paramData in data.params) {
try {
finalParams.push({name: paramData.name, type: hscriptInterp.expr(hscriptParser.parseString(paramData.type)), defValue: paramData.defaultValue});
finalParams.push({
name: paramData.name,
type: hscriptInterp.expr(hscriptParser.parseString(paramData.type)),
defValue: paramData.defaultValue
});
} catch (e) {trace('Error parsing event param ${paramData.name} - ${eventName}: $e'); finalParams.push(null);}
}
eventsParams.set(eventName, finalParams);
@@ -110,6 +119,14 @@ class EventsData {
}
}
typedef EventInfoFile = {
var params:Array<{
var name:String;
var type:String;
var defaultValue:Dynamic;
}>;
}
typedef EventInfo = {
var params:Array<EventParamInfo>;
var paramValues:Array<Dynamic>;
@@ -26,7 +26,7 @@ final class DirectionAnimEvent extends CancellableEvent {
**/
public var frame:Int;
/**
Force the animation to replay even if it's already playing.
Force the animation to replay even if it's already playing (if it's null it will be forced based on the sprite's data xml, if it has one).
**/
public var force:Bool = true;
public var force:Null<Bool>;
}
@@ -100,9 +100,9 @@ final class NoteHitEvent extends CancellableEvent {
*/
public var ratingAntialiasing:Bool = true;
/**
* Whenever the animation should be forced to play.
* Whenever the animation should be forced to play (if it's null it will be forced based on the sprite's data xml, if it has one).
*/
public var forceAnim:Bool = true;
public var forceAnim:Null<Bool> = true;
/**
* Prevents the default sing animation from being played.
@@ -29,9 +29,9 @@ final class NoteMissEvent extends CancellableEvent {
public var gfSadAnim:String;
public var forceGfAnim:Bool;
/**
* Whenever the animation should be forced to play.
* Whenever the animation should be forced to play (if it's null it will be forced based on the sprite's data xml, if it has one).
*/
public var forceAnim:Bool;
public var forceAnim:Null<Bool>;
/**
* Suffix of the animation. "miss" for miss notes, "-alt" for alt notes, "" for normal ones.
*/
@@ -7,9 +7,9 @@ final class PlayAnimEvent extends CancellableEvent {
public var animName:String;
/**
Whenever the animation will be forced or not.
Whenever the animation will be forced or not (if it's null it will be forced based on the sprite's data xml, if it has one).
**/
public var force:Bool;
public var force:Null<Bool>;
/**
Whenever the animation will play in reverse or not
@@ -125,9 +125,16 @@ class Framerate extends Sprite {
bgSprite.scaleX = width;
bgSprite.scaleY = height;
var y:Float = height + 4;
var selectable = debugMode == 2;
{ // idk i tried to make it more lookable:sob: - Nex
memoryCounter.memoryText.selectable = memoryCounter.memoryPeakText.selectable =
fpsCounter.fpsNum.selectable = fpsCounter.fpsLabel.selectable =
#if SHOW_BUILD_ON_FPS codenameBuildField.selectable = #end selectable;
}
var y:Float = height + 4;
for(c in categories) {
c.title.selectable = c.text.selectable = selectable;
c.alpha = debugAlpha;
c.x = FlxMath.lerp(-c.width - offset.x, 0, debugAlpha);
c.y = y;
@@ -29,6 +29,7 @@ class FramerateCategory extends Sprite {
label.x = 0;
label.y = 0;
label.defaultTextFormat = new TextFormat(Framerate.fontName, label == this.title ? 18 : 12, -1);
label.selectable = false;
addChild(label);
}
this.title.text = title;
@@ -1,28 +1,17 @@
package funkin.backend.system.framerate;
import haxe.ds.Vector;
import openfl.display.Sprite;
import openfl.text.TextField;
import openfl.text.TextFormat;
inline final FRAME_TIME_HISTORY = 20;
class FramerateCounter extends Sprite {
public var fpsNum:TextField;
public var fpsLabel:TextField;
public var fpsHistoryIndex:Int = 0;
public var fpsHistory:Vector<Float>;
public var lastFPS:Float = 0;
public function new() {
super();
fpsHistory = new Vector(FRAME_TIME_HISTORY);
// Initialize to 60 FPS, so that the initial estimation until we get enough data is always reasonable.
for(i in 0...FRAME_TIME_HISTORY) {
fpsHistory[i] = 1000.0 / 60.0;
}
fpsNum = new TextField();
fpsLabel = new TextField();
@@ -33,6 +22,7 @@ class FramerateCounter extends Sprite {
label.text = "FPS";
label.multiline = label.wordWrap = false;
label.defaultTextFormat = new TextFormat(Framerate.fontName, label == fpsNum ? 18 : 12, -1);
label.selectable = false;
addChild(label);
}
}
@@ -43,20 +33,8 @@ class FramerateCounter extends Sprite {
if (alpha <= 0.05) return;
super.__enterFrame(t);
// todo use gpu time
fpsHistory[fpsHistoryIndex] = FlxG.elapsed * 1000;
fpsHistoryIndex = (fpsHistoryIndex + 1) % FRAME_TIME_HISTORY;
// Calculate average CPU time.
// Code based on Godot's FPS counter.
var cpuTime = 0.0;
for(i in 0...FRAME_TIME_HISTORY) {
cpuTime += fpsHistory[i];
}
cpuTime /= FRAME_TIME_HISTORY;
cpuTime = Math.max(0.01, cpuTime); // Prevent unrealistically low values.
fpsNum.text = Std.string(Math.floor(1000.0 / cpuTime));
lastFPS = CoolUtil.fpsLerp(lastFPS, FlxG.elapsed == 0 ? 0 : (1 / FlxG.elapsed), 0.25);
fpsNum.text = Std.string(Math.floor(lastFPS));
fpsLabel.x = fpsNum.x + fpsNum.width;
fpsLabel.y = (fpsNum.y + fpsNum.height) - fpsLabel.height;
}
@@ -24,6 +24,7 @@ class MemoryCounter extends Sprite {
label.text = "FPS";
label.multiline = label.wordWrap = false;
label.defaultTextFormat = new TextFormat(Framerate.fontName, 12, -1);
label.selectable = false;
addChild(label);
}
memoryPeakText.alpha = 0.5;
+14 -1
View File
@@ -721,7 +721,7 @@ class CoolUtil
*/
@:noUsing public static inline function openURL(url:String) {
#if linux
Sys.command('/usr/bin/xdg-open', [url, "&"]);
Sys.command('/usr/bin/xdg-open', [url]);
#else
FlxG.openURL(url);
#end
@@ -906,6 +906,19 @@ class CoolUtil
return result.join(seperator);
}
public static function deepFlatten(arr:Array<Dynamic>, ?result:Array<Dynamic>):Array<Dynamic> {
if(arr == null) return [];
if(result == null) result = [];
for (e in arr) {
if (Std.isOfType(e, Array)) {
deepFlatten(e, result);
} else {
result.push(e);
}
}
return result;
}
}
/**
@@ -32,8 +32,8 @@ class FunkinParentDisabler extends FlxBasic {
FlxTimer.globalManager._timers = [];
// cameras
__cameras = [for(c in FlxG.cameras.list) if (c.active) c];
for(c in __cameras) c.active = false;
__cameras = [for(c in FlxG.cameras.list) if (!c.paused) c];
for(c in __cameras) c.paused = true;
// sounds
__sounds = [for(s in FlxG.sound.list) if (s.playing) s];
@@ -41,9 +41,6 @@ class FunkinParentDisabler extends FlxBasic {
}
}
public override function update(elapsed:Float) {
@:privateAccess for(c in __cameras) c.updateFlashSpritePosition();
}
public override function draw() {}
public function reset() {
@@ -63,7 +60,7 @@ class FunkinParentDisabler extends FlxBasic {
for(t in __tweens) FlxTween.globalManager._tweens.push(t);
for(t in __timers) FlxTimer.globalManager._timers.push(t);
}
for(c in __cameras) c.active = true;
for(c in __cameras) c.paused = false;
for(s in __sounds) s.play();
}
}
+11 -8
View File
@@ -4,6 +4,7 @@ import flixel.util.FlxColor;
import flixel.util.typeLimit.OneOfTwo;
import funkin.backend.FunkinSprite.XMLAnimType;
import funkin.backend.FunkinSprite;
import funkin.game.Character;
import funkin.backend.system.ErrorCode;
import funkin.backend.system.interfaces.IOffsetCompatible;
import haxe.xml.Access;
@@ -172,8 +173,7 @@ class XMLUtil {
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)
indices: [for(i in 0...spr.frames.frames.length) i]
});
}
}
@@ -199,8 +199,7 @@ class XMLUtil {
animType: animType,
x: 0,
y: 0,
indices: [],
forced: false,
indices: []
};
if (anim.has.name) animData.name = anim.att.name;
@@ -256,24 +255,28 @@ class XMLUtil {
if (sprite is FunkinSprite) {
var xmlSpr = cast(sprite, FunkinSprite);
var name = animData.name;
switch(animData.animType) {
case BEAT:
xmlSpr.beatAnims.push({
name: animData.name,
forced: animData.forced.getDefault(false)
name: name,
forced: animData.forced.getDefault(defaultForcedCheck(name, xmlSpr))
});
case LOOP:
xmlSpr.playAnim(animData.name, animData.forced.getDefault(false));
xmlSpr.playAnim(name, animData.forced.getDefault(defaultForcedCheck(name, xmlSpr)));
default:
// nothing
}
xmlSpr.animDatas.set(animData.name, animData);
xmlSpr.animDatas.set(name, animData);
}
return OK;
}
return MISSING_PROPERTY;
}
public static inline function defaultForcedCheck(animName:String, sprite:FunkinSprite):Bool
return sprite is Character && (animName.startsWith("idle") || animName.startsWith("danceLeft") || animName.startsWith("danceRight")) ? false : sprite.spriteAnimType == BEAT;
public static inline function fixXMLText(text:String) {
var v:String;
return [for(l in text.split("\n")) if ((v = l.trim()) != "") v].join("\n");
@@ -98,11 +98,7 @@ class SongCreationScreen extends UISubstateWindow {
voicesExplorer.uiElement = audioPlayer;
});
songDataGroup.add(voicesExplorer);
voicesUIText = addLabelOn(voicesExplorer, "Vocal Audio File");
voicesUIText.applyMarkup(
"Vocal Audio File $* Required$",
[new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFAD1212), "$")]);
addLabelOn(voicesExplorer, "Vocal Audio File");
var menuTitle:UIText;
menuDataGroup.add(menuTitle = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, "Menus Data (Freeplay/Story)", 28));
+3 -2
View File
@@ -235,7 +235,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
/**
* Like `playSingAnimUnsafe` but checks if the character has the animation with the suffix part, otherwise it plays the animation without the suffix part.
*/
public function playSingAnim(direction:Int, suffix:String = "", Context:PlayAnimContext = SING, Force:Bool = true, Reversed:Bool = false, Frame:Int = 0)
public function playSingAnim(direction:Int, suffix:String = "", Context:PlayAnimContext = SING, ?Force:Null<Bool> = null, Reversed:Bool = false, Frame:Int = 0)
{
var event = EventManager.get(DirectionAnimEvent).recycle(getSingAnim(direction, suffix), direction, suffix, Context, Reversed, Frame, Force);
script.call("onPlaySingAnim", [event]);
@@ -252,7 +252,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
playAnim(event.animName, event.force, event.context, event.reversed, event.frame);
}
public override function playAnim(AnimName:String, Force:Bool = false, Context:PlayAnimContext = NONE, Reversed:Bool = false, Frame:Int = 0) {
public override function playAnim(AnimName:String, ?Force:Bool, Context:PlayAnimContext = NONE, Reversed:Bool = false, Frame:Int = 0) {
var event = EventManager.get(PlayAnimEvent).recycle(AnimName, Force, Reversed, Frame, Context);
script.call("onPlayAnim", [event]);
if (event.cancelled) return;
@@ -323,6 +323,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
public inline function buildCharacter(xml:Access) {
this.xml = xml; // Modders wassup :D
sprite = curCharacter;
spriteAnimType = BEAT;
if (xml.x.exists("isPlayer")) playerOffsets = (xml.x.get("isPlayer") == "true");
if (xml.x.exists("x")) globalOffset.x = Std.parseFloat(xml.x.get("x"));
+7 -5
View File
@@ -675,10 +675,12 @@ class PlayState extends MusicBeatState
chars.push(char);
}
var strOffset:Float = strumLine.strumLinePos == null ? (strumLine.type == 1 ? 0.75 : 0.25) : strumLine.strumLinePos;
var startingPos:FlxPoint = strumLine.strumPos == null ?
FlxPoint.get((FlxG.width * strOffset) - ((Note.swagWidth * (strumLine.strumScale == null ? 1 : strumLine.strumScale)) * 2), this.strumLine.y) :
FlxPoint.get(strumLine.strumPos[0] == 0 ? ((FlxG.width * strOffset) - ((Note.swagWidth * (strumLine.strumScale == null ? 1 : strumLine.strumScale)) * 2)) : strumLine.strumPos[0], strumLine.strumPos[1]);
var strOffset:Float = strumLine.strumLinePos != null ? strumLine.strumLinePos : (strumLine.type == 1 ? 0.75 : 0.25);
var strScale:Float = strumLine.strumScale != null ? strumLine.strumScale : 1;
var strXPos:Float = (FlxG.width * strOffset) - (Note.swagWidth * strScale * 2);
var startingPos:FlxPoint = strumLine.strumPos != null ?
FlxPoint.get(strumLine.strumPos[0] == 0 ? strXPos : strumLine.strumPos[0], strumLine.strumPos[1]) :
FlxPoint.get(strXPos, this.strumLine.y);
var strLine = new StrumLine(chars,
startingPos,
strumLine.strumScale == null ? 1 : strumLine.strumScale,
@@ -1954,7 +1956,7 @@ class PlayState extends MusicBeatState
}
}
class ComboRating {
final class ComboRating {
public var percent:Float;
public var rating:String;
public var color:FlxColor;
+6 -1
View File
@@ -152,7 +152,12 @@ class StrumLine extends FlxTypedGroup<Strum> {
var scrollSpeed = strumLine.scrollSpeed;
if(scrollSpeed == null) if (PlayState.instance != null) scrollSpeed = PlayState.instance.scrollSpeed;
if(scrollSpeed == null) scrollSpeed = 1;
notes.limit = Constants.DEFAULT_NOTE_MS_LIMIT / scrollSpeed;
// TODO: Make this work by accounting zoom and scrollspeed changes - Nex
/*var limit = FlxG.height / 0.45;
notes.limit = limit / scrollSpeed;
OR
notes.limit = Constants.DEFAULT_NOTE_MS_LIMIT / scrollSpeed;*/
}
public override function update(elapsed:Float) {
@@ -97,7 +97,7 @@ class DialogueBox extends FunkinSprite {
dialogueBoxScript.call("postCreate");
}
public override function playAnim(AnimName:String, Force:Bool = false, Context:PlayAnimContext = NONE, Reversed:Bool = false, Frame:Int = 0) {
public override function playAnim(AnimName:String, ?Force:Bool, Context:PlayAnimContext = NONE, Reversed:Bool = false, Frame:Int = 0) {
var event = EventManager.get(PlayAnimEvent).recycle(AnimName, Force, Reversed, Frame, Context);
dialogueBoxScript.call("onPlayAnim", [event]);
if(event.cancelled) return;
@@ -62,7 +62,7 @@ class DialogueCharacter extends FunkinSprite {
dialogueCharScript.call("postCreate");
}
public override function playAnim(AnimName:String, Force:Bool = false, Context:PlayAnimContext = NONE, Reversed:Bool = false, Frame:Int = 0) {
public override function playAnim(AnimName:String, ?Force:Bool, Context:PlayAnimContext = NONE, Reversed:Bool = false, Frame:Int = 0) {
var event = EventManager.get(PlayAnimEvent).recycle(AnimName, Force, Reversed, Frame, Context);
dialogueCharScript.call("playAnim", [event]);
if(event.cancelled) return;