bug fixes + wip new chart system
This commit is contained in:
+1
-1
@@ -1 +1 @@
|
||||
2261
|
||||
2265
|
||||
@@ -0,0 +1,172 @@
|
||||
package funkin.chart;
|
||||
|
||||
import funkin.system.Song.SwagSong;
|
||||
import haxe.Json;
|
||||
import openfl.utils.Assets;
|
||||
|
||||
class Chart {
|
||||
public static function parse(songName:String, difficulty:String = "normal"):ChartData {
|
||||
var base:ChartData = {
|
||||
strumLines: [],
|
||||
events: [],
|
||||
meta: {
|
||||
name: songName,
|
||||
bpm: 0
|
||||
},
|
||||
stage: "stage",
|
||||
codenameChart: true
|
||||
};
|
||||
var chartPath = Paths.chart(songName, difficulty);
|
||||
if (!Assets.exists(chartPath)) {
|
||||
Logs.trace('Chart for song ${songName} ($difficulty) at "$chartPath" was not found.', ERROR, RED);
|
||||
return base;
|
||||
}
|
||||
var data:Dynamic = null;
|
||||
try {
|
||||
data = Json.parse(Assets.getText(chartPath));
|
||||
} catch(e) {
|
||||
Logs.trace('Could not parse chart for song ${songName} ($difficulty): ${Std.string(e)}', ERROR, RED);
|
||||
}
|
||||
|
||||
if (Reflect.hasField(data, "codenameChart") && Reflect.field(data, "codenameChart") == true) {
|
||||
return cast data;
|
||||
} else {
|
||||
// base fnf chart parsing
|
||||
var data:SwagSong = data;
|
||||
if (Reflect.hasField(data, "song")) {
|
||||
var field:Dynamic = Reflect.field(data, "song");
|
||||
if (!(field is String))
|
||||
data = field;
|
||||
}
|
||||
|
||||
base.stage = data.stage;
|
||||
base.meta.name = data.song;
|
||||
base.meta.bpm = data.bpm;
|
||||
|
||||
base.strumLines.push({
|
||||
characters: [data.player2],
|
||||
opponent: true,
|
||||
notes: []
|
||||
});
|
||||
base.strumLines.push({
|
||||
characters: [data.player1],
|
||||
opponent: false,
|
||||
notes: []
|
||||
});
|
||||
|
||||
var camFocusedBF:Bool = false;
|
||||
var beatsPerMesure:Float = data.beatsPerMesure.getDefault(4);
|
||||
var curBPM:Float = data.bpm;
|
||||
var curTime:Float = 0;
|
||||
var curCrochet:Float = ((60 / curBPM) * 1000);
|
||||
|
||||
if (data.notes != null) for(section in data.notes) {
|
||||
if (section == null) continue; // Yoshi Engine charts crash fix
|
||||
|
||||
if (camFocusedBF != (camFocusedBF = section.mustHitSection)) {
|
||||
// TODO: auto-add event for cam movement
|
||||
base.events.push({
|
||||
time: curTime,
|
||||
type: CAM_MOVEMENT,
|
||||
params: [camFocusedBF ? 1 : 0]
|
||||
});
|
||||
}
|
||||
|
||||
if (section.sectionNotes != null) for(note in section.sectionNotes) {
|
||||
var daStrumTime:Float = note[0];
|
||||
var daNoteData:Int = Std.int(note[1] % 8);
|
||||
var daNoteType:Int = Std.int(note[1] / 8);
|
||||
var gottaHitNote:Bool = daNoteData >= 4 ? !section.mustHitSection : section.mustHitSection;
|
||||
|
||||
base.strumLines[gottaHitNote ? 1 : 0].notes.push({
|
||||
time: daStrumTime,
|
||||
id: daNoteData % 4,
|
||||
type: daNoteType,
|
||||
sustainLength: note[2]
|
||||
});
|
||||
}
|
||||
|
||||
if (section.changeBPM && section.bpm != curBPM) {
|
||||
// TODO: BPM CHANGE EVENT
|
||||
curCrochet = ((60 / section.bpm) * 1000);
|
||||
}
|
||||
|
||||
curTime += curCrochet * beatsPerMesure;
|
||||
}
|
||||
}
|
||||
return base;
|
||||
}
|
||||
}
|
||||
|
||||
typedef ChartData = {
|
||||
public var strumLines:Array<ChartStrumLine>;
|
||||
public var events:Array<ChartEvent>;
|
||||
public var meta:ChartMetaData;
|
||||
public var codenameChart:Bool;
|
||||
public var stage:String;
|
||||
}
|
||||
|
||||
typedef ChartMetaData = {
|
||||
public var name:String;
|
||||
public var bpm:Float;
|
||||
public var ?icon:String;
|
||||
public var ?color:Dynamic;
|
||||
public var ?difficulties:Array<String>;
|
||||
public var ?coopAllowed:Bool;
|
||||
public var ?opponentModeAllowed:Bool;
|
||||
}
|
||||
|
||||
typedef ChartStrumLine = {
|
||||
var characters:Array<String>;
|
||||
var opponent:Bool;
|
||||
var notes:Array<ChartNote>;
|
||||
var ?strumLinePos:Float; // 0.25 = default opponent pos, 0.75 = default boyfriend pos
|
||||
}
|
||||
|
||||
typedef ChartNote = {
|
||||
var time:Float; // time at which the note will be hit (ms)
|
||||
var id:Int; // strum id of the note
|
||||
var type:Int; // type (int) of the note
|
||||
var sustainLength:Float; // sustain length of the note (ms)
|
||||
}
|
||||
|
||||
typedef ChartEvent = {
|
||||
var time:Float;
|
||||
var type:ChartEventType;
|
||||
var params:Array<Dynamic>;
|
||||
}
|
||||
|
||||
@: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;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"meta": {
|
||||
"song": "Test",
|
||||
"bpm": 120
|
||||
},
|
||||
"strumLines": [
|
||||
{
|
||||
"characters": ["bf-pixel"],
|
||||
"opponent": true,
|
||||
"notes": [
|
||||
{
|
||||
"time": 1500,
|
||||
"id": 1,
|
||||
"type": 0,
|
||||
"sustainLength": 1500
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"characters": ["bf"],
|
||||
"opponent": false,
|
||||
"notes": [
|
||||
{
|
||||
"time": 1500,
|
||||
"id": 1,
|
||||
"type": 0,
|
||||
"sustainLength": 1500
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"events": [
|
||||
{
|
||||
"time": 1500,
|
||||
"type": -1,
|
||||
"params": ["changeShit", true, false]
|
||||
}
|
||||
],
|
||||
"codenameChart": true
|
||||
}
|
||||
@@ -29,9 +29,11 @@ import funkin.scripting.events.PlayAnimEvent.PlayAnimContext;
|
||||
using StringTools;
|
||||
|
||||
@:allow(funkin.desktop.editors.CharacterEditor)
|
||||
@:allow(funkin.game.StrumLine)
|
||||
class Character extends FunkinSprite implements IBeatReceiver implements IOffsetCompatible
|
||||
{
|
||||
private var __stunnedTime:Float = 0;
|
||||
private var __lockAnimThisFrame:Bool = false;
|
||||
public var stunned(default, set):Bool = false;
|
||||
|
||||
private function set_stunned(b:Bool) {
|
||||
@@ -206,6 +208,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
|
||||
if (__stunnedTime > 5 / 60)
|
||||
stunned = false;
|
||||
}
|
||||
__lockAnimThisFrame = false;
|
||||
}
|
||||
|
||||
private var danced:Bool = false;
|
||||
@@ -256,7 +259,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
|
||||
|
||||
public override function beatHit(curBeat:Int) {
|
||||
script.call("beatHit", [curBeat]);
|
||||
if (danceOnBeat) {
|
||||
if (danceOnBeat && !__lockAnimThisFrame) {
|
||||
tryDance();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,6 +506,8 @@ class PlayState extends MusicBeatState
|
||||
|
||||
@:dox(hide) override public function create()
|
||||
{
|
||||
// SCRIPTING & DATA INITIALISATION
|
||||
#if REGION
|
||||
instance = this;
|
||||
if (FlxG.sound.music != null) FlxG.sound.music.stop();
|
||||
|
||||
@@ -538,8 +540,10 @@ class PlayState extends MusicBeatState
|
||||
|
||||
// String for when the game is paused
|
||||
detailsPausedText = "Paused - " + detailsText;
|
||||
#end
|
||||
|
||||
|
||||
// CHARACTER INITIALISATION
|
||||
#if REGION
|
||||
// Updating Discord Rich Presence.
|
||||
dad = new Character(100, 100, SONG.player2);
|
||||
|
||||
@@ -563,8 +567,10 @@ class PlayState extends MusicBeatState
|
||||
comboGroup = new FlxSpriteGroup(FlxG.width * 0.55, (FlxG.height * 0.5) - 60);
|
||||
|
||||
boyfriend = new Character(770, 100, SONG.player1, true);
|
||||
#end
|
||||
|
||||
|
||||
// SCRIPTS & STAGE INITIALISATION
|
||||
#if REGION
|
||||
if (SONG.stage == null || SONG.stage.trim() == "") SONG.stage = "stage";
|
||||
add(stage = new Stage(SONG.stage));
|
||||
|
||||
@@ -587,17 +593,6 @@ class PlayState extends MusicBeatState
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PRECACHING
|
||||
*/
|
||||
|
||||
for(content in Paths.getFolderContent('images/game/score/', true, true))
|
||||
FlxG.bitmap.add(content);
|
||||
|
||||
/**
|
||||
* END OF PRECACHING
|
||||
*/
|
||||
|
||||
scripts.load();
|
||||
scripts.call("create");
|
||||
|
||||
@@ -610,7 +605,16 @@ class PlayState extends MusicBeatState
|
||||
|
||||
if (dad != null) add(dad);
|
||||
if (boyfriend != null) add(boyfriend);
|
||||
#end
|
||||
|
||||
// PRECACHING
|
||||
#if REGION
|
||||
for(content in Paths.getFolderContent('images/game/score/', true, true))
|
||||
FlxG.bitmap.add(content);
|
||||
#end
|
||||
|
||||
// STRUMS & NOTES INITIALISATION
|
||||
#if REGION
|
||||
strumLine = new FlxObject(0, 50, FlxG.width, 10);
|
||||
strumLine.scrollFactor.set();
|
||||
|
||||
@@ -624,7 +628,10 @@ class PlayState extends MusicBeatState
|
||||
add(splashHandler);
|
||||
|
||||
generateSong(SONG);
|
||||
#end
|
||||
|
||||
// CAMERA & HUD INITIALISATION
|
||||
#if REGION
|
||||
camFollow = new FlxObject(0, 0, 2, 2);
|
||||
camFollow.setPosition(camPos.x, camPos.y);
|
||||
add(camFollow);
|
||||
@@ -681,6 +688,7 @@ class PlayState extends MusicBeatState
|
||||
|
||||
for(e in [strumLineNotes, notes, healthBar, healthBarBG, iconP1, iconP2, scoreTxt, missesTxt, accuracyTxt])
|
||||
e.cameras = [camHUD];
|
||||
#end
|
||||
|
||||
startingSong = true;
|
||||
|
||||
@@ -1450,7 +1458,7 @@ class PlayState extends MusicBeatState
|
||||
__funcsToExec.push(function(note:Note) {
|
||||
if (__justPressed[note.strumID] && !note.isSustainNote && note.strumLineID == id && !note.wasGoodHit && note.canBeHit) {
|
||||
if (notePerStrum[note.strumID] == null) notePerStrum[note.strumID] = note;
|
||||
else if (Math.abs(notePerStrum[note.strumID].strumTime - note.strumTime) <= 2) deleteNote(note);
|
||||
else if (Math.abs(notePerStrum[note.strumID].strumTime - note.strumTime) <= 2) deleteNote(note);
|
||||
else if (note.strumTime < notePerStrum[note.strumID].strumTime) notePerStrum[note.strumID] = note;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -105,7 +105,6 @@ class StrumLine extends FlxTypedGroup<Strum> {
|
||||
add(babyArrow);
|
||||
|
||||
babyArrow.playAnim('static');
|
||||
PlayState.instance.strumLineNotes.add(babyArrow);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package funkin.menus;
|
||||
|
||||
import haxe.Json;
|
||||
import funkin.ui.FunkinText;
|
||||
import funkin.options.Options;
|
||||
import flixel.FlxG;
|
||||
@@ -108,13 +109,9 @@ class MainMenuState extends MusicBeatState
|
||||
if (FlxG.keys.justPressed.SEVEN)
|
||||
FlxG.switchState(new funkin.desktop.DesktopMain());
|
||||
if (FlxG.keys.justPressed.EIGHT) {
|
||||
var scr = new funkin.desktop.DesktopScreen();
|
||||
var camList = [for(c in FlxG.cameras.list) c];
|
||||
for(c in camList) {
|
||||
FlxG.cameras.remove(c, false);
|
||||
scr.addCamera(c);
|
||||
}
|
||||
cameras = camList;
|
||||
#if sys
|
||||
sys.io.File.saveContent("chart.json", Json.stringify(funkin.chart.Chart.parse("dadbattle", "hard")));
|
||||
#end
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,13 +30,16 @@ class FunkinRatioScaleMode extends RatioScaleMode {
|
||||
}
|
||||
|
||||
@:privateAccess {
|
||||
FlxG.width = width;
|
||||
FlxG.height = height;
|
||||
|
||||
for(c in FlxG.cameras.list) {
|
||||
c.width = width;
|
||||
c.height = height;
|
||||
if (c.width == FlxG.width && c.height == FlxG.height) {
|
||||
c.width = width;
|
||||
c.height = height;
|
||||
}
|
||||
}
|
||||
|
||||
FlxG.width = width;
|
||||
FlxG.height = height;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user