diff --git a/.github/ISSUE_TEMPLATE/compiling.md b/.github/ISSUE_TEMPLATE/compiling.md
index bd6f439c..4f516469 100644
--- a/.github/ISSUE_TEMPLATE/compiling.md
+++ b/.github/ISSUE_TEMPLATE/compiling.md
@@ -16,5 +16,5 @@ labels: compiling help
[ ] Mac
### Explain your issue
-##### Please check first if your issue haven't already been reported yet.
-[weed]: <> (MAKE SURE TO ADD A SCREENSHOT OF THE CRASH HANDLER, IF AVAILABLE, AND STEPS TO REPRODUCE THE BUG!)
\ No newline at end of file
+##### Please check first if your issue haven't already been reported yet, and make sure you ran the `update.bat` file before building.
+[weed]: <> (MAKE SURE TO ADD A SCREENSHOT OF THE CRASH HANDLER, IF AVAILABLE, AND STEPS TO REPRODUCE THE BUG!)
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 5463a51b..08e9b4d2 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -27,7 +27,7 @@ jobs:
cache-build-linux
- name: Installing/Updating libraries
run: |
- haxe -cp ./update -D analyzer-optimize -main Update --interp
+ haxe -cp commandline -D analyzer-optimize --run Main setup
- name: Building the game
run: |
haxelib run lime build linux
@@ -70,4 +70,4 @@ jobs:
export/release/linux/haxe/
export/release/linux/obj/
restore-keys: |
- cache-build-linux
\ No newline at end of file
+ cache-build-linux
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 772db147..65a3fa2e 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -27,7 +27,7 @@ jobs:
cache-build-mac
- name: Installing/Updating libraries
run: |
- haxe -cp ./update -D analyzer-optimize -main Update --interp
+ haxe -cp commandline -D analyzer-optimize --run Main setup
- name: Building the game
run: |
haxelib run lime build mac
@@ -70,4 +70,4 @@ jobs:
export/release/macos/haxe/
export/release/macos/obj/
restore-keys: |
- cache-build-mac
\ No newline at end of file
+ cache-build-mac
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 6088d1c2..1c93ad8c 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -27,7 +27,7 @@ jobs:
cache-build-windows
- name: Installing/Updating libraries
run: |
- haxe -cp ./update -D analyzer-optimize -main Update --interp
+ haxe -cp commandline -D analyzer-optimize --run Main setup
- name: Building the game
run: |
haxelib run lime build windows
@@ -70,4 +70,4 @@ jobs:
export/release/windows/haxe/
export/release/windows/obj/
restore-keys: |
- cache-build-windows
\ No newline at end of file
+ cache-build-windows
diff --git a/.gitignore b/.gitignore
index bee4df7e..43d2c37c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,5 @@ latest/windows/obj/
latest/windows/haxe/
.vscode/*
!.vscode/settings.json
-.haxelib/
\ No newline at end of file
+.haxelib/
+mods/Baldi's Basics in Funkin'/
\ No newline at end of file
diff --git a/README.md b/README.md
index 6c8f365c..3b8538b9 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,7 @@ Latest builds for the engine can be found in the [Actions](https://github.com/Yo
Windows
##### Tested on Windows 10 21H2
-1. Install the [latest version of Haxe](https://haxe.org/download/).
+1. Install [version 4.2.5 of Haxe](https://haxe.org/download/version/4.2.5/).
2. Download [Visual Studio Build Tools](https://aka.ms/vs/17/release/vs_BuildTools.exe)
3. Wait for the Visual Studio Installer to install
4. On the Visual Studio installer screen, go to the "Individual components" tab and only select those options:
@@ -63,7 +63,7 @@ Latest builds for the engine can be found in the [Actions](https://github.com/Yo
Linux
##### Requires testing
-1. Install the [latest version of Haxe](https://haxe.org/download/).
+1. Install [version 4.2.5 of Haxe](https://haxe.org/download/version/4.2.5/).
2. Install `g++`, if not present already.
3. Download and install [`git-scm`](https://git-scm.com/download/linux).
4. Open a terminal in the Codename Engine source folder, and run `update.sh`.
@@ -74,7 +74,7 @@ Latest builds for the engine can be found in the [Actions](https://github.com/Yo
MacOS
##### Requires testing
-1. Install the [latest version of Haxe](https://haxe.org/download/).
+1. Install [version 4.2.5 of Haxe](https://haxe.org/download/version/4.2.5/).
2. Install `Xcode` to allow C++ app building.
3. Download and install [`git-scm`](https://git-scm.com/download/mac).
4. Open a terminal in the Codename Engine source folder, and run `update.sh`.
diff --git a/assets/images/editors/charter/event-icons.png b/assets/images/editors/charter/event-icons.png
deleted file mode 100644
index fee6d3d0..00000000
Binary files a/assets/images/editors/charter/event-icons.png and /dev/null differ
diff --git a/assets/images/editors/charter/event-icons/Alt Animation Toggle.png b/assets/images/editors/charter/event-icons/Alt Animation Toggle.png
new file mode 100644
index 00000000..f2180276
Binary files /dev/null and b/assets/images/editors/charter/event-icons/Alt Animation Toggle.png differ
diff --git a/assets/images/editors/charter/event-icons/BPM Change.png b/assets/images/editors/charter/event-icons/BPM Change.png
new file mode 100644
index 00000000..a59fe83a
Binary files /dev/null and b/assets/images/editors/charter/event-icons/BPM Change.png differ
diff --git a/assets/images/editors/charter/event-icons/Camera Movement.png b/assets/images/editors/charter/event-icons/Camera Movement.png
new file mode 100644
index 00000000..c7b117f0
Binary files /dev/null and b/assets/images/editors/charter/event-icons/Camera Movement.png differ
diff --git a/assets/images/editors/charter/event-icons/HScript Call.png b/assets/images/editors/charter/event-icons/HScript Call.png
new file mode 100644
index 00000000..ab2ff5e1
Binary files /dev/null and b/assets/images/editors/charter/event-icons/HScript Call.png differ
diff --git a/assets/images/editors/charter/event-icons/Unknown.png b/assets/images/editors/charter/event-icons/Unknown.png
new file mode 100644
index 00000000..ba1116fd
Binary files /dev/null and b/assets/images/editors/charter/event-icons/Unknown.png differ
diff --git a/commandline/commands/Compiler.hx b/commandline/commands/Compiler.hx
index 24ace428..0e0eb692 100644
--- a/commandline/commands/Compiler.hx
+++ b/commandline/commands/Compiler.hx
@@ -5,13 +5,13 @@ class Compiler {
__build(args, ["test", getBuildTarget(), "-D", "TEST_BUILD"]);
}
public static function build(args:Array) {
- __build(args, ["build", "windows", "-D", "TEST_BUILD"]);
+ __build(args, ["build", getBuildTarget(), "-D", "TEST_BUILD"]);
}
public static function release(args:Array) {
- __build(args, ["build", "windows"]);
+ __build(args, ["build", getBuildTarget()]);
}
public static function testRelease(args:Array) {
- __build(args, ["test", "windows"]);
+ __build(args, ["test", getBuildTarget()]);
}
private static function __build(args:Array, arg:Array) {
diff --git a/source/funkin/backend/chart/BaseGameParser.hx b/source/funkin/backend/chart/BaseGameParser.hx
index 3c56e069..a8b31b87 100644
--- a/source/funkin/backend/chart/BaseGameParser.hx
+++ b/source/funkin/backend/chart/BaseGameParser.hx
@@ -55,7 +55,7 @@ class BaseGameParser {
if (camFocusedBF != (camFocusedBF = section.mustHitSection)) {
result.events.push({
time: curTime,
- type: CAM_MOVEMENT,
+ name: "Camera Movement",
params: [camFocusedBF ? 1 : 0]
});
}
@@ -90,7 +90,7 @@ class BaseGameParser {
result.events.push({
time: curTime,
- type: BPM_CHANGE,
+ name: "BPM Change",
params: [section.bpm]
});
}
diff --git a/source/funkin/backend/chart/Chart.hx b/source/funkin/backend/chart/Chart.hx
index 8253a7a8..e950fa9e 100644
--- a/source/funkin/backend/chart/Chart.hx
+++ b/source/funkin/backend/chart/Chart.hx
@@ -108,6 +108,22 @@ class Chart {
*/
#if REGION
if (Reflect.hasField(data, "codenameChart") && Reflect.field(data, "codenameChart") == true) {
+ // backward compat on events since its caused problems
+ var eventTypesToString:Map = [
+ -1 => "HScript Call",
+ 0 => "Unknown",
+ 1 => "Camera Movement",
+ 2 => "BPM Change",
+ 3 => "Alt Animation Toggle",
+ ];
+
+ for (event in cast(data.events, Array)) {
+ if (Reflect.hasField(event, "type")) {
+ event.name = eventTypesToString[event.type];
+ event.type = null;
+ }
+ }
+
// codename chart
base = data;
} else {
diff --git a/source/funkin/backend/chart/ChartData.hx b/source/funkin/backend/chart/ChartData.hx
index 3dd309e7..e81589e7 100644
--- a/source/funkin/backend/chart/ChartData.hx
+++ b/source/funkin/backend/chart/ChartData.hx
@@ -48,8 +48,8 @@ typedef ChartNote = {
}
typedef ChartEvent = {
+ var name:String;
var time:Float;
- var type:ChartEventType;
var params:Array;
}
@@ -67,43 +67,4 @@ abstract ChartStrumLineType(Int) from Int to Int {
* STRUMLINE IS MARKED AS ADDITIONAL - WILL BE PLAYED AS CPU EVEN IF OPPONENT MODE IS ENABLED
*/
var ADDITIONAL = 2;
-}
-@:enum
-abstract ChartEventType(Int) from Int to Int {
- /**
- * CUSTOM EVENT
- * Params:
- * - Function Name (String)
- * - Function Parameters...
- */
- var CUSTOM = -1;
- /**
- * NO EVENT, MADE FOR UNKNOWN EVENTS / EVENTS THAT CANNOT BE PARSED
- */
- var NONE = 0;
- /**
- * CAMERA MOVEMENT EVENT
- * Params:
- * - Target Strumline ID (Int)
- */
- var CAM_MOVEMENT = 1;
- /**
- * BPM CHANGE EVENT
- * Params:
- * - Target BPM (Float)
- */
- var BPM_CHANGE = 2;
- /**
- * ALT ANIM TOGGLE
- * Params:
- * - Strum Line which is going to be toggled (Int)
- * - Whenever its going to be toggled or not (Bool)
- */
- var ALT_ANIM_TOGGLE = 3;
-
- /**
- * Returns all usable event types.
- */
- public static inline function getChartEventTypes():Array
- return [CUSTOM, CAM_MOVEMENT, BPM_CHANGE, ALT_ANIM_TOGGLE];
}
\ No newline at end of file
diff --git a/source/funkin/backend/scripting/events/EventGameEvent.hx b/source/funkin/backend/scripting/events/EventGameEvent.hx
new file mode 100644
index 00000000..836e44c9
--- /dev/null
+++ b/source/funkin/backend/scripting/events/EventGameEvent.hx
@@ -0,0 +1,7 @@
+package funkin.backend.scripting.events;
+
+import funkin.backend.chart.ChartData;
+
+final class EventGameEvent extends CancellableEvent {
+ public var event:ChartEvent;
+}
\ No newline at end of file
diff --git a/source/funkin/backend/scripting/events/StrumCreationEvent.hx b/source/funkin/backend/scripting/events/StrumCreationEvent.hx
index 699f88bc..d591d958 100644
--- a/source/funkin/backend/scripting/events/StrumCreationEvent.hx
+++ b/source/funkin/backend/scripting/events/StrumCreationEvent.hx
@@ -21,6 +21,11 @@ final class StrumCreationEvent extends CancellableEvent {
*/
public var strumID:Int;
+ /**
+ * Animation prefix (`left` = `arrowLEFT`, `left press`, `left confirm`).
+ */
+ public var animPrefix:String;
+
/**
* Sprite path, in case you only want to change the sprite.
*/
diff --git a/source/funkin/backend/system/Conductor.hx b/source/funkin/backend/system/Conductor.hx
index a35f57c7..d38db2c8 100644
--- a/source/funkin/backend/system/Conductor.hx
+++ b/source/funkin/backend/system/Conductor.hx
@@ -134,7 +134,7 @@ class Conductor
var songTime:Float = 0;
var stepTime:Float = 0;
- for(e in song.events) if (e.type == BPM_CHANGE && e.params != null && e.params[0] is Float) {
+ for(e in song.events) if (e.name == "BPM Change" && e.params != null && e.params[0] is Float) {
if (e.params[0] == curBPM) continue;
var steps = (e.time - songTime) / ((60 / curBPM) * 1000 / 4);
stepTime += steps;
diff --git a/source/funkin/backend/system/MainState.hx b/source/funkin/backend/system/MainState.hx
index 0c03257b..714170f0 100644
--- a/source/funkin/backend/system/MainState.hx
+++ b/source/funkin/backend/system/MainState.hx
@@ -6,6 +6,7 @@ import sys.FileSystem;
import funkin.backend.assets.ModsFolder;
import funkin.menus.TitleState;
import funkin.menus.BetaWarningState;
+import funkin.editors.charter.EventsData;
import flixel.FlxState;
/**
@@ -42,6 +43,7 @@ class MainState extends FlxState {
Main.refreshAssets();
ModsFolder.onModSwitch.dispatch(ModsFolder.currentModFolder);
DiscordUtil.reloadJsonData();
+ EventsData.reloadEvents();
TitleState.initialized = false;
diff --git a/source/funkin/backend/system/framerate/SystemInfo.hx b/source/funkin/backend/system/framerate/SystemInfo.hx
index 3c775623..80e35e14 100644
--- a/source/funkin/backend/system/framerate/SystemInfo.hx
+++ b/source/funkin/backend/system/framerate/SystemInfo.hx
@@ -31,7 +31,7 @@ class SystemInfo extends FramerateCategory {
if (process.exitCode() == 0) cpuName = process.stdout.readAll().toString().trim().split(":")[1].trim();
#elseif linux
var process = new HiddenProcess("cat", ["/proc/cpuinfo"]);
- if (process.exitCode() != 0) return;
+ if (process.exitCode() != 0) throw 'Could not fetch CPU information';
for (line in process.stdout.readAll().toString().split("\n")) {
if (line.indexOf("model name") == 0) {
diff --git a/source/funkin/backend/utils/MemoryUtil.hx b/source/funkin/backend/utils/MemoryUtil.hx
index 47f55114..4c0c40c0 100644
--- a/source/funkin/backend/utils/MemoryUtil.hx
+++ b/source/funkin/backend/utils/MemoryUtil.hx
@@ -128,7 +128,7 @@ class MemoryUtil {
reg.match(process.stdout.readAll().toString());
if (process.exitCode() == 0) return reg.matched(1);
#elseif linux
- var process = HiddenProcess("sudo", ["dmidecode", "--type", "17"]);
+ var process = new HiddenProcess("sudo", ["dmidecode", "--type", "17"]);
if (process.exitCode() != 0) return "Unknown";
var lines = process.stdout.readAll().toString().split("\n");
for (line in lines) {
diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx
index 80759bf3..236a4d74 100644
--- a/source/funkin/editors/charter/Charter.hx
+++ b/source/funkin/editors/charter/Charter.hx
@@ -405,8 +405,11 @@ class Charter extends UIState {
var instPath:String;
public function loadSong() {
- if (__reload)
+ if (__reload) {
+ EventsData.reloadEvents();
PlayState.loadSong(__song, __diff, false, false);
+ }
+
Conductor.setupSong(PlayState.SONG);
diff --git a/source/funkin/editors/charter/CharterEvent.hx b/source/funkin/editors/charter/CharterEvent.hx
index 0d62361d..6c49081a 100644
--- a/source/funkin/editors/charter/CharterEvent.hx
+++ b/source/funkin/editors/charter/CharterEvent.hx
@@ -1,76 +1,10 @@
package funkin.editors.charter;
import funkin.backend.system.Conductor;
-import funkin.backend.chart.ChartData.ChartEventType;
import funkin.game.HealthIcon;
import funkin.backend.chart.ChartData.ChartEvent;
class CharterEvent extends UISliceSprite {
- public static function getEventInfo(id:ChartEventType):EventDefineInfo {
- return switch(id) {
- case CUSTOM:
- // hscript
- {
- name: "HScript Call",
- params: [
- {
- name: "Function name",
- type: TString,
- defValue: "myFunc"
- },
- {
- name: "Function parameters (string)",
- type: TArrayOfString,
- defValue: []
- }
- ]
- }
- case CAM_MOVEMENT:
- {
- name: "Camera Movement",
- params: [
- {
- name: "Camera Target",
- type: TStrumLine,
- defValue: 0
- }
- ]
- }
- case BPM_CHANGE:
- {
- name: "BPM Change",
- params: [
- {
- name: "Target BPM",
- type: TFloat(1),
- defValue: Conductor.bpm
- }
- ]
- }
- case ALT_ANIM_TOGGLE:
- {
- name: "Alt Animation Toggle",
- params: [
- {
- name: "Strumline",
- type: TStrumLine,
- defValue: 0
- },
- {
- name: "Enable",
- type: TBool,
- defValue: true
- }
- ]
- }
- default:
- {
- name: "Unknown",
- params: []
- }
- };
- }
-
public var events:Array;
public var step:Float;
@@ -92,17 +26,19 @@ class CharterEvent extends UISliceSprite {
}
}
- private static function generateDefaultIcon(type:Int) {
- var spr = new FlxSprite().loadGraphic(Paths.image('editors/charter/event-icons'), true, 16, 16);
- spr.frame = spr.frames.frames[type+1];
- return spr;
+ private static function generateDefaultIcon(name:String) {
+ var path:String = Paths.image('editors/charter/event-icons/$name');
+ if (!Assets.exists(path)) path = Paths.image('editors/charter/event-icons/Unknown');
+
+ var spr = new FlxSprite().loadGraphic(path);
+ return spr;
}
public static function generateEventIcon(event:ChartEvent) {
- return switch(event.type) {
+ return switch(event.name) {
default:
- generateDefaultIcon(event.type);
- case CAM_MOVEMENT:
+ generateDefaultIcon(event.name);
+ case "Camera Movement":
// custom icon for camera movement
var state = cast(FlxG.state, Charter);
if (event.params[0] != null && event.params[0] >= 0 && event.params[0] < state.strumLines.length) {
@@ -111,7 +47,7 @@ class CharterEvent extends UISliceSprite {
healthIcon.setUnstretchedGraphicSize(32, 32, false);
healthIcon;
} else
- generateDefaultIcon(event.type);
+ generateDefaultIcon(event.name);
}
}
@@ -136,28 +72,4 @@ class CharterEvent extends UISliceSprite {
x = -(bWidth = 37 + (icons.length * 22));
}
-}
-
-typedef EventDefineInfo = {
- var name:String;
- var params:Array;
-}
-typedef EventInfo = {
- > EventDefineInfo,
- var paramValues:Array;
-}
-
-typedef EventParamInfo = {
- var name:String;
- var type:EventParamType;
- var defValue:Dynamic;
-}
-
-enum EventParamType {
- TBool;
- TInt(?min:Int, ?max:Int, ?step:Float);
- TFloat(?min:Int, ?max:Int, ?step:Float, ?precision:Int);
- TString;
- TArrayOfString;
- TStrumLine;
}
\ No newline at end of file
diff --git a/source/funkin/editors/charter/CharterEventGroup.hx b/source/funkin/editors/charter/CharterEventGroup.hx
index c631a05a..90719fec 100644
--- a/source/funkin/editors/charter/CharterEventGroup.hx
+++ b/source/funkin/editors/charter/CharterEventGroup.hx
@@ -1,5 +1,3 @@
package funkin.editors.charter;
-class CharterEventGroup extends FlxTypedGroup {
-
-}
\ No newline at end of file
+class CharterEventGroup extends FlxTypedGroup {}
\ No newline at end of file
diff --git a/source/funkin/editors/charter/CharterEventScreen.hx b/source/funkin/editors/charter/CharterEventScreen.hx
index b81ee135..8fbc60bd 100644
--- a/source/funkin/editors/charter/CharterEventScreen.hx
+++ b/source/funkin/editors/charter/CharterEventScreen.hx
@@ -2,6 +2,7 @@ package funkin.editors.charter;
import funkin.backend.system.Conductor;
import flixel.group.FlxGroup;
+import funkin.editors.charter.EventsData;
class CharterEventScreen extends UISubstateWindow {
public var cam:FlxCamera;
@@ -40,11 +41,11 @@ class CharterEventScreen extends UISubstateWindow {
add(iconsPanel);
addButton = new UIButton(windowSpr.x + 1, windowSpr.y + 31, "", function() {
- openSubState(new CharterEventTypeSelection(function(eventType) {
+ openSubState(new CharterEventTypeSelection(function(eventName) {
chartEvent.events.push({
time: Conductor.getTimeForStep(chartEvent.step),
params: [],
- type: eventType
+ name: eventName
});
changeTab(chartEvent.events.length-1);
}));
@@ -105,11 +106,10 @@ class CharterEventScreen extends UISubstateWindow {
if (id >= 0 && id < chartEvent.events.length) {
curEvent = id;
var curEvent = chartEvent.events[curEvent];
- var data = CharterEvent.getEventInfo(curEvent.type);
- eventName.text = data.name;
+ eventName.text = curEvent.name;
// add new elements
var y:Float = eventName.y + eventName.height + 10;
- for(k=>param in data.params) {
+ for(k=>param in EventsData.getEventParams(curEvent.name)) {
function addLabel() {
var label:UIText = new UIText(eventName.x, y, 0, param.name);
y += label.height + 4;
@@ -121,30 +121,30 @@ class CharterEventScreen extends UISubstateWindow {
case TString:
addLabel();
var textBox:UITextBox = new UITextBox(eventName.x, y, cast value);
- y += textBox.height + 10;
+ y += textBox.height + 30;
paramsPanel.add(textBox);
paramsFields.push(textBox);
case TBool:
var checkbox = new UICheckbox(eventName.x, y, param.name, cast value);
- y += checkbox.height + 10;
+ y += checkbox.height + 8;
paramsPanel.add(checkbox);
paramsFields.push(checkbox);
case TInt(min, max, step):
addLabel();
var numericStepper = new UINumericStepper(eventName.x, y, cast value, step.getDefault(1), 0, min, max);
- y += numericStepper.height + 10;
+ y += numericStepper.height + 30;
paramsPanel.add(numericStepper);
paramsFields.push(numericStepper);
case TFloat(min, max, step, precision):
addLabel();
var numericStepper = new UINumericStepper(eventName.x, y, cast value, step.getDefault(1), precision, min, max);
- y += numericStepper.height + 10;
+ y += numericStepper.height + 30;
paramsPanel.add(numericStepper);
paramsFields.push(numericStepper);
case TStrumLine:
addLabel();
var dropdown = new UIDropDown(eventName.x, y, 320, 32, [for(k=>s in cast(FlxG.state, Charter).strumLines.members) 'Strumline #${k+1} (${s.strumLine.characters[0]})'], cast value);
- y += dropdown.height + 10;
+ y += dropdown.height + 30;
paramsPanel.add(dropdown);
paramsFields.push(dropdown);
default:
diff --git a/source/funkin/editors/charter/CharterEventTypeSelection.hx b/source/funkin/editors/charter/CharterEventTypeSelection.hx
index d04a0970..201d9600 100644
--- a/source/funkin/editors/charter/CharterEventTypeSelection.hx
+++ b/source/funkin/editors/charter/CharterEventTypeSelection.hx
@@ -1,11 +1,11 @@
package funkin.editors.charter;
-import funkin.backend.chart.ChartData.ChartEventType;
+import funkin.editors.charter.EventsData;
class CharterEventTypeSelection extends UISubstateWindow {
- var callback:ChartEventType->Void;
+ var callback:String->Void;
- public function new(callback:ChartEventType->Void) {
+ public function new(callback:String->Void) {
super();
this.callback = callback;
}
@@ -16,11 +16,10 @@ class CharterEventTypeSelection extends UISubstateWindow {
var w:Int = winWidth - 20;
var lastIndex:Int = 0;
- for(k=>eventType in ChartEventType.getChartEventTypes()) {
- var type = CharterEvent.getEventInfo(eventType);
- add(new UIButton(10, 41 + (32 * k), type.name, function() {
+ for(k=>eventName in EventsData.eventsList) {
+ add(new UIButton(10, 41 + (32 * k), eventName, function() {
close();
- callback(eventType);
+ callback(eventName);
}, w));
lastIndex = k;
diff --git a/source/funkin/editors/charter/EventsData.hx b/source/funkin/editors/charter/EventsData.hx
new file mode 100644
index 00000000..e2803c81
--- /dev/null
+++ b/source/funkin/editors/charter/EventsData.hx
@@ -0,0 +1,88 @@
+package funkin.editors.charter;
+
+import hscript.Parser;
+import hscript.Interp;
+import haxe.Json;
+import sys.io.File;
+import openfl.Assets;
+import haxe.io.Path;
+import funkin.backend.assets.Paths;
+
+using StringTools;
+
+class EventsData {
+ public static var defaultEventsList:Array = ["HScript Call", "Camera Movement", "BPM Change", "Alt Animation Toggle"];
+ public static var defaultEventsParams:Map> = [
+ "HScript Call" => [{name: "Function Name", type: TString, defValue: "myFunc"}, {name: "Function Parameters (String split with commas)", type: TString, defValue: ""}],
+ "Camera Movement" => [{name: "Camera Target", type: TStrumLine, defValue: 0}],
+ "BPM Change" => [{name: "Target BPM", type: TFloat(1), defValue: 100}],
+ "Alt Animation Toggle" => [{name: "Strumline", type: TStrumLine, defValue: 0}, {name: "Enable", type: TBool, defValue: true}],
+ ];
+
+ public static var eventsList:Array = defaultEventsList.copy();
+ public static var eventsParams:Map> = defaultEventsParams.copy();
+
+ public static function getEventParams(name:String):Array {
+ return eventsParams.exists(name) ? eventsParams.get(name) : [];
+ }
+
+ public static function reloadEvents() {
+ eventsList = defaultEventsList.copy();
+ eventsParams = defaultEventsParams.copy();
+
+ var hscriptInterp:Interp = new Interp();
+ hscriptInterp.variables.set("Bool", TBool);
+ hscriptInterp.variables.set("Int", function (?min:Int, ?max:Int, ?step:Float):EventParamType {return TInt(min, max, step);});
+ hscriptInterp.variables.set("Float", function (?min:Int, ?max:Int, ?step:Float, ?precision:Int):EventParamType {return TFloat(min, max, step, precision);});
+ hscriptInterp.variables.set("String", TString);
+ hscriptInterp.variables.set("StrumLine", TStrumLine);
+
+ var hscriptParser:Parser = new Parser();
+ hscriptParser.allowJSON = hscriptParser.allowMetadata = false;
+
+ for (file in Paths.getFolderContent('data/events/', true, BOTH)) {
+ if (Path.extension(file) != "json") continue;
+ var eventName:String = Path.withoutExtension(Path.withoutDirectory(file));
+
+ eventsList.push(eventName);
+ eventsParams.set(eventName, []);
+
+ var fileTxt:String = Assets.getText(file);
+ if (fileTxt.trim() == "") {continue;}
+
+ try {
+ var data:Dynamic = Json.parse(fileTxt);
+ if (data == null || data.params == null) continue;
+
+ var finalParams:Array = [];
+ for (paramData in cast(data.params, Array)) {
+ try {
+ 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');}
+ }
+ eventsParams.set(eventName, finalParams);
+ } catch (e) {trace('Error parsing file $file: $e');}
+ }
+
+ hscriptInterp = null; hscriptParser = null;
+ }
+}
+
+typedef EventInfo = {
+ var params:Array;
+ var paramValues:Array;
+}
+
+typedef EventParamInfo = {
+ var name:String;
+ var type:EventParamType;
+ var defValue:Dynamic;
+}
+
+enum EventParamType {
+ TBool;
+ TInt(?min:Int, ?max:Int, ?step:Float);
+ TFloat(?min:Int, ?max:Int, ?step:Float, ?precision:Int);
+ TString;
+ TStrumLine;
+}
\ No newline at end of file
diff --git a/source/funkin/game/Note.hx b/source/funkin/game/Note.hx
index 38672c56..8f0cd79f 100644
--- a/source/funkin/game/Note.hx
+++ b/source/funkin/game/Note.hx
@@ -61,7 +61,7 @@ class Note extends FlxSprite
public var strumID(get, never):Int;
private function get_strumID() {
- var id = noteData % 4;
+ var id = noteData % strumLine.members.length;
if (id < 0) id = 0;
return id;
}
diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx
index 365eb22b..250872f6 100644
--- a/source/funkin/game/PlayState.hx
+++ b/source/funkin/game/PlayState.hx
@@ -1,5 +1,6 @@
package funkin.game;
+import funkin.editors.charter.EventsData;
import funkin.backend.system.RotatingSpriteGroup;
import funkin.editors.charter.Charter;
import funkin.savedata.FunkinSave;
@@ -550,21 +551,22 @@ class PlayState extends MusicBeatState
// dadMidpoint.put();
var camPos:FlxPoint = new FlxPoint(0, 0);
-
if (!chartingMode || Options.charterEnablePlaytestScripts) {
switch(SONG.meta.name) {
// case "":
// ADD YOUR HARDCODED SCRIPTS HERE!
default:
- for(content in [
- Paths.getFolderContent('songs/${SONG.meta.name.toLowerCase()}/scripts', true, fromMods ? MODS : BOTH),
- Paths.getFolderContent('data/charts/', true, fromMods ? MODS : BOTH)]) {
- for(file in content) {
- var ext = Path.extension(file).toLowerCase();
- if (Script.scriptExtensions.contains(ext))
- scripts.add(Script.create(file));
- }
+ function addScript(file:String) {
+ var ext = Path.extension(file).toLowerCase();
+ if (Script.scriptExtensions.contains(ext))
+ scripts.add(Script.create(file));
}
+
+ for(content in [Paths.getFolderContent('songs/${SONG.meta.name.toLowerCase()}/scripts', true, fromMods ? MODS : BOTH), Paths.getFolderContent('data/charts/', true, fromMods ? MODS : BOTH)])
+ for(file in content) addScript(file);
+
+ for (file in Paths.getFolderContent('data/events/', true, fromMods ? MODS : BOTH))
+ if (EventsData.eventsList.contains(Path.withoutExtension(Path.withoutDirectory(file)))) addScript(file);
}
}
@@ -633,6 +635,12 @@ class PlayState extends MusicBeatState
// CAMERA & HUD INITIALISATION
#if REGION
+
+ if (!scripts.event("onPreGenerateStrums", new CancellableEvent()).cancelled) {
+ generateStrums();
+ scripts.call("onPostGenerateStrums");
+ }
+
for(str in strumLines)
str.generate(str.data, (chartingMode && Charter.startHere) ? Charter.startTime : null);
@@ -659,6 +667,8 @@ class PlayState extends MusicBeatState
healthBarBG.scrollFactor.set();
add(healthBarBG);
+
+
healthBar = new FlxBar(healthBarBG.x + 4, healthBarBG.y + 4, RIGHT_TO_LEFT, Std.int(healthBarBG.width - 8), Std.int(healthBarBG.height - 8), this,
'health', 0, maxHealth);
healthBar.scrollFactor.set();
@@ -782,11 +792,6 @@ class PlayState extends MusicBeatState
if (scripts.event("onStartCountdown", new CancellableEvent()).cancelled) return;
}
- if (!scripts.event("onPreGenerateStrums", new CancellableEvent()).cancelled) {
- generateStrums();
- scripts.call("onPostGenerateStrums");
- }
-
startedCountdown = true;
Conductor.songPosition = 0;
Conductor.songPosition -= Conductor.crochet * introLength;
@@ -897,7 +902,7 @@ class PlayState extends MusicBeatState
// get first camera focus
for(e in events) {
if (e.time > 10) break;
- if (e.type == CAM_MOVEMENT) {
+ if (e.name == "Camera Movement") {
executeEvent(e);
break;
}
@@ -1170,24 +1175,24 @@ class PlayState extends MusicBeatState
if (event == null) return;
if (event.params == null) return;
- switch(event.type) {
- case CUSTOM:
- if (event.params[0] is String && event.params[1] is Array) {
- scripts.call(event.params[0], event.params[1]);
+ if (scripts.event("onEvent", EventManager.get(EventGameEvent).recycle(event)).cancelled) return;
+
+ switch(event.name) {
+ case "HScript Call":
+ if (event.params[0] is String && event.params[1] is String) {
+ scripts.call(event.params[0], event.params[1].split(','));
}
- case CAM_MOVEMENT:
+ case "Camera Movement":
if (event.params[0] is Int)
curCameraTarget = event.params[0];
- case BPM_CHANGE:
- // automatically handled by conductor
- case ALT_ANIM_TOGGLE:
+ case "BPM Change": // automatically handled by conductor
+ case "Alt Animation Toggle":
if (event.params[0] is Int && event.params[1] is Bool) {
var strLine = strumLines.members[event.params[0]];
if (strLine != null)
strLine.altAnim = cast event.params[1];
}
- // todo!!!
- default:
+ case "Unknown":
}
}
diff --git a/source/funkin/game/Strum.hx b/source/funkin/game/Strum.hx
index 1e3b3d99..d4d8fe4a 100644
--- a/source/funkin/game/Strum.hx
+++ b/source/funkin/game/Strum.hx
@@ -9,16 +9,48 @@ class Strum extends FlxSprite {
public var scrollSpeed:Null = null; // custom scroll speed per strum
public var noteAngle:Null = null;
-
+
public var lastDrawCameras(default, null):Array = [];
+ public var getPressed:StrumLine->Bool = null;
+ public var getJustPressed:StrumLine->Bool = null;
+ public var getJustReleased:StrumLine->Bool = null;
+
+ public inline function __getPressed(strumLine:StrumLine):Bool {
+ return getPressed != null ? getPressed(strumLine) : switch(ID) {
+ case 0: strumLine.controls.NOTE_LEFT;
+ case 1: strumLine.controls.NOTE_DOWN;
+ case 2: strumLine.controls.NOTE_UP;
+ case 3: strumLine.controls.NOTE_RIGHT;
+ default: false;
+ }
+ }
+ public inline function __getJustPressed(strumLine:StrumLine) {
+ return getJustPressed != null ? getJustPressed(strumLine) : switch(ID) {
+ case 0: strumLine.controls.NOTE_LEFT_P;
+ case 1: strumLine.controls.NOTE_DOWN_P;
+ case 2: strumLine.controls.NOTE_UP_P;
+ case 3: strumLine.controls.NOTE_RIGHT_P;
+ default: false;
+ }
+ }
+ public inline function __getJustReleased(strumLine:StrumLine) {
+ return getJustReleased != null ? getJustReleased(strumLine) : switch(ID) {
+ case 0: strumLine.controls.NOTE_LEFT_R;
+ case 1: strumLine.controls.NOTE_DOWN_R;
+ case 2: strumLine.controls.NOTE_UP_R;
+ case 3: strumLine.controls.NOTE_RIGHT_R;
+ default: false;
+ }
+ }
+
public inline function getScrollSpeed(?note:Note):Float {
if (note != null && note.scrollSpeed != null) return note.scrollSpeed;
if (scrollSpeed != null) return scrollSpeed;
if (PlayState.instance != null) return PlayState.instance.scrollSpeed;
return 1;
}
-
+
public inline function getNotesAngle(?note:Note):Float {
if (note != null && note.noteAngle != null) return note.noteAngle;
if (noteAngle != null) return noteAngle;
@@ -44,7 +76,7 @@ class Strum extends FlxSprite {
public function updateNotePosition(daNote:Note) {
if (!daNote.exists) return;
-
+
daNote.__strumCameras = lastDrawCameras;
daNote.__strum = this;
daNote.scrollFactor.set(scrollFactor.x, scrollFactor.y);
@@ -63,7 +95,7 @@ class Strum extends FlxSprite {
var realOffset = FlxPoint.get(0, 0);
if (daNote.isSustainNote) offset.y -= N_WIDTHDIV2;
-
+
if (Std.int(daNote.__noteAngle % 360) != 0) {
var noteAngleCos = FlxMath.fastCos(daNote.__noteAngle / PIX180);
var noteAngleSin = FlxMath.fastSin(daNote.__noteAngle / PIX180);
@@ -81,9 +113,9 @@ class Strum extends FlxSprite {
realOffset.y = offset.y;
}
realOffset.y *= -1;
-
+
daNote.setPosition(x + realOffset.x, y + realOffset.y);
-
+
offset.put();
realOffset.put();
}
diff --git a/source/funkin/game/StrumLine.hx b/source/funkin/game/StrumLine.hx
index 3d959738..ca8ac584 100644
--- a/source/funkin/game/StrumLine.hx
+++ b/source/funkin/game/StrumLine.hx
@@ -187,11 +187,13 @@ class StrumLine extends FlxTypedGroup {
__justPressed.clear();
__justReleased.clear();
- __pressed.pushGroup(controls.NOTE_LEFT, controls.NOTE_DOWN, controls.NOTE_UP, controls.NOTE_RIGHT);
- __justPressed.pushGroup(controls.NOTE_LEFT_P, controls.NOTE_DOWN_P, controls.NOTE_UP_P, controls.NOTE_RIGHT_P);
- __justReleased.pushGroup(controls.NOTE_LEFT_R, controls.NOTE_DOWN_R, controls.NOTE_UP_R, controls.NOTE_RIGHT_R);
+ for(s in members) {
+ __pressed.push(s.__getPressed(this));
+ __justPressed.push(s.__getJustPressed(this));
+ __justReleased.push(s.__getJustReleased(this));
+ }
- var event = PlayState.instance.scripts.event("onKeyShit", EventManager.get(InputSystemEvent).recycle(__pressed, __justPressed, __justReleased, this, id));
+ var event = PlayState.instance.scripts.event("onInputUpdate", EventManager.get(InputSystemEvent).recycle(__pressed, __justPressed, __justReleased, this, id));
if (event.cancelled) return;
__pressed = CoolUtil.getDefault(event.pressed, []);
@@ -224,68 +226,67 @@ class StrumLine extends FlxTypedGroup {
for(e in __notePerStrum) if (e != null) PlayState.instance.goodNoteHit(this, e);
forEach(function(str:Strum) {
- str.updatePlayerInput(__pressed[str.ID], __justPressed[str.ID], __justReleased[str.ID]);
+ str.updatePlayerInput(str.__getPressed(this), str.__getJustPressed(this), str.__getJustReleased(this));
});
- PlayState.instance.scripts.call("onPostKeyShit");
+ PlayState.instance.scripts.call("onPostInputUpdate");
}
public inline function addHealth(health:Float)
PlayState.instance.health += health * (opponentSide ? -1 : 1);
- public function generateStrums(amount:Int = 4) {
+ public inline function generateStrums(amount:Int = 4) {
for (i in 0...4)
- {
- var babyArrow:Strum = new Strum((FlxG.width * strumOffset) + (Note.swagWidth * (i - 2)), PlayState.instance.strumLine.y);
- babyArrow.ID = i;
+ add(createStrum(i));
+ }
- var event = PlayState.instance.scripts.event("onStrumCreation", EventManager.get(StrumCreationEvent).recycle(babyArrow, PlayState.instance.strumLines.members.indexOf(this), i));
-
- if (!event.cancelled) {
- babyArrow.frames = Paths.getFrames(event.sprite);
- babyArrow.animation.addByPrefix('green', 'arrowUP');
- babyArrow.animation.addByPrefix('blue', 'arrowDOWN');
- babyArrow.animation.addByPrefix('purple', 'arrowLEFT');
- babyArrow.animation.addByPrefix('red', 'arrowRIGHT');
-
- babyArrow.antialiasing = true;
- babyArrow.setGraphicSize(Std.int(babyArrow.width * 0.7));
-
- switch (babyArrow.ID % 4)
- {
- case 0:
- babyArrow.animation.addByPrefix('static', 'arrowLEFT');
- babyArrow.animation.addByPrefix('pressed', 'left press', 24, false);
- babyArrow.animation.addByPrefix('confirm', 'left confirm', 24, false);
- case 1:
- babyArrow.animation.addByPrefix('static', 'arrowDOWN');
- babyArrow.animation.addByPrefix('pressed', 'down press', 24, false);
- babyArrow.animation.addByPrefix('confirm', 'down confirm', 24, false);
- case 2:
- babyArrow.animation.addByPrefix('static', 'arrowUP');
- babyArrow.animation.addByPrefix('pressed', 'up press', 24, false);
- babyArrow.animation.addByPrefix('confirm', 'up confirm', 24, false);
- case 3:
- babyArrow.animation.addByPrefix('static', 'arrowRIGHT');
- babyArrow.animation.addByPrefix('pressed', 'right press', 24, false);
- babyArrow.animation.addByPrefix('confirm', 'right confirm', 24, false);
- }
+ /**
+ * Creates a strum and returns the created strum (needs to be added manually).
+ * @param i Index of the strum
+ * @param animPrefix (Optional) Animation prefix (`left` = `arrowLEFT`, `left press`, `left confirm`).
+ */
+ public function createStrum(i:Int, ?animPrefix:String) {
+ if (animPrefix == null)
+ animPrefix = switch(i % 4) {
+ case 0: "left";
+ case 1: "down";
+ case 2: "up";
+ case 3: "right";
+ case _: "up";
}
+ var babyArrow:Strum = new Strum((FlxG.width * strumOffset) + (Note.swagWidth * (i - 2)), PlayState.instance.strumLine.y);
+ babyArrow.ID = i;
- babyArrow.cpu = cpu;
- babyArrow.updateHitbox();
- babyArrow.scrollFactor.set();
+ var event = PlayState.instance.scripts.event("onStrumCreation", EventManager.get(StrumCreationEvent).recycle(babyArrow, PlayState.instance.strumLines.members.indexOf(this), i, animPrefix));
- if (event.__doAnimation)
- {
- babyArrow.y -= 10;
- babyArrow.alpha = 0;
- FlxTween.tween(babyArrow, {y: babyArrow.y + 10, alpha: 1}, 1, {ease: FlxEase.circOut, startDelay: 0.5 + (0.2 * i)});
- }
+ if (!event.cancelled) {
+ babyArrow.frames = Paths.getFrames(event.sprite);
+ babyArrow.animation.addByPrefix('green', 'arrowUP');
+ babyArrow.animation.addByPrefix('blue', 'arrowDOWN');
+ babyArrow.animation.addByPrefix('purple', 'arrowLEFT');
+ babyArrow.animation.addByPrefix('red', 'arrowRIGHT');
- add(babyArrow);
+ babyArrow.antialiasing = true;
+ babyArrow.setGraphicSize(Std.int(babyArrow.width * 0.7));
- babyArrow.playAnim('static');
+ babyArrow.animation.addByPrefix('static', 'arrow${event.animPrefix.toUpperCase()}');
+ babyArrow.animation.addByPrefix('pressed', '${event.animPrefix} press', 24, false);
+ babyArrow.animation.addByPrefix('confirm', '${event.animPrefix} confirm', 24, false);
}
+
+ babyArrow.cpu = cpu;
+ babyArrow.updateHitbox();
+ babyArrow.scrollFactor.set();
+
+ if (event.__doAnimation)
+ {
+ babyArrow.y -= 10;
+ babyArrow.alpha = 0;
+ FlxTween.tween(babyArrow, {y: babyArrow.y + 10, alpha: 1}, 1, {ease: FlxEase.circOut, startDelay: 0.5 + (0.2 * i)});
+ }
+ babyArrow.playAnim('static');
+
+ insert(i, babyArrow);
+ return babyArrow;
}
/**