package funkin.backend.chart; import funkin.backend.chart.ChartData.ChartMetaData; // These new structures are kinda a mess to port, i love and hate them at the same time; why the hell are every difficulty in the same file??? - Nex class BaseGameParser { public static function parseChart(data:Dynamic, metaData:Dynamic, events:Dynamic, result:ChartData) { // base fnf chart parsing var data:Array = data; var metadata:SwagMetadata = metaData; var events:Array = events; result.stage = metadata.playData.stage; var p2isGF:Bool = false; result.strumLines.push({ characters: [metadata.playData.characters.player], type: 1, position: "boyfriend", notes: [], vocalsSuffix: "-Player" }); result.strumLines.push({ characters: [metadata.playData.characters.opponent], type: 0, position: (p2isGF = metadata.playData.characters.opponent.startsWith("gf")) ? "girlfriend" : "dad", notes: [], vocalsSuffix: "-Opponent" }); var gfName = metadata.playData.characters.girlfriend; if (!p2isGF && gfName != "none") { result.strumLines.push({ characters: [gfName], type: 2, position: "girlfriend", notes: [], visible: false, }); } var firstTimeChange = metadata.timeChanges[0]; result.meta.bpm = firstTimeChange.bpm; result.meta.needsVoices = true; for (note in data) { var daNoteType:Null = null; if (note.k != null) daNoteType = Chart.addNoteType(result, note.k); var daNoteData:Int = Std.int(note.d % 8); var isMustHit:Bool = Math.floor(daNoteData / 4) == 0; result.strumLines[isMustHit ? 0 : 1].notes.push({ time: note.t, id: daNoteData % 4, type: daNoteType, sLen: note.l }); } for (event in events) { switch (event.e) { case "FocusCamera": result.events.push({ time: event.t, name: "Camera Movement", params: [event.v.char] }); } } /*var camFocusedBF:Bool = false; var altAnims:Bool = false; var beatsPerMeasure:Float = data.beatsPerMeasure.getDefault(Flags.DEFAULT_BEATS_PER_MEASURE); var curBPM:Float = firstTimeChange.bpm; var curTime:Float = 0; var curCrochet:Float = ((60 / curBPM) * 1000); if (data.notes != null) for(section in data.notes) { if (section == null) { curTime += curCrochet * beatsPerMeasure; continue; // Yoshi Engine charts crash fix } if (camFocusedBF != (camFocusedBF = section.mustHitSection)) { result.events.push({ time: curTime, name: "Camera Movement", params: [camFocusedBF ? 1 : 0] }); } if (section.altAnim == null) section.altAnim = false; if (altAnims != (altAnims = section.altAnim)) { result.events.push({ time: curTime, name: "Alt Animation Toggle", params: [altAnims, false, 0] }); } if (section.sectionNotes != null) for(note in section.sectionNotes) { if (note[1] < 0) continue; 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; if (note.length > 2) { if (note[3] is Int && data.noteTypes != null) daNoteType = Chart.addNoteType(result, data.noteTypes[Std.int(note[3])-1]); else if (note[3] is String) daNoteType = Chart.addNoteType(result, note[3]); } else { if(data.noteTypes != null) daNoteType = Chart.addNoteType(result, data.noteTypes[daNoteType-1]); } result.strumLines[gottaHitNote ? 1 : 0].notes.push({ time: daStrumTime, id: daNoteData % 4, type: daNoteType, sLen: note[2] }); } if (section.changeBPM && section.bpm != curBPM) { curCrochet = ((60 / (curBPM = section.bpm)) * 1000); result.events.push({ time: curTime, name: "BPM Change", params: [section.bpm] }); } curTime += curCrochet * beatsPerMeasure; }*/ } public static function parseMeta(data:Dynamic, result:ChartMetaData) { var data:SwagMetadata = data; result.name = data.songName; result.artist = data.artist; result.customValues = {}; result.customValues.timeChanges = data.timeChanges; var firstTimeChange:SwagTimeChange = data.timeChanges[0]; result.bpm = firstTimeChange.bpm; result.beatsPerMeasure = firstTimeChange.b != null ? firstTimeChange.b : Flags.DEFAULT_BEATS_PER_MEASURE; result.difficulties = data.playData.difficulties.concat(data.playData.songVariations); Reflect.deleteField(data.playData, "difficulties"); for (field in Reflect.fields(data.playData)) Reflect.setProperty(result.customValues, field, Reflect.getProperty(data.playData, field)); } public static function encodeMeta(meta:ChartMetaData, ?chart:ChartData):SwagMetadata { var addVars:Dynamic = meta.customValues; var defStage:String = addVars.stage != null ? addVars.stage : Flags.DEFAULT_STAGE; var defChars:SwagCharactersList = addVars.characters != null ? addVars.characters : {player: Flags.DEFAULT_CHARACTER, girlfriend: Flags.DEFAULT_GIRLFRIEND, opponent: Flags.DEFAULT_OPPONENT, playerVocals: [], opponentVocals: [], instrumental: '', altInstrumentals: []}; var defTimeCh:Array; if (addVars.timeChanges != null && addVars.timeChanges.length > 0) { defTimeCh = addVars.timeChanges; defTimeCh[0].bpm = meta.bpm; } else defTimeCh = [{bpm: meta.bpm, t: -1}]; if (chart != null) { defStage = chart.stage; var done:Array = [false, false, false]; for (strumLine in chart.strumLines) switch (strumLine.type) { case OPPONENT: if (!done[0]) { done[0] = true; defChars.opponent = strumLine.characters.getDefault([defChars.opponent])[0]; } case PLAYER: if (!done[1]) { done[1] = true; defChars.player = strumLine.characters.getDefault([defChars.player])[0]; } case ADDITIONAL: if (!done[3]) { done[3] = true; defChars.girlfriend = strumLine.characters.getDefault([defChars.girlfriend])[0]; } } } var result:SwagMetadata = { songName: meta.name, timeFormat: MILLISECONDS, artist: meta.artist, timeChanges: defTimeCh, looped: false, generatedBy: 'Basegame Chart Importer (Codename Engine)', version: Flags.BASEGAME_SONG_METADATA_VERSION, playData: { stage: defStage, characters: defChars, songVariations: addVars.songVariations != null ? [for (i in 0...addVars.songVariations.length) {meta.difficulties.remove(addVars.songVariations[i]); addVars.songVariations[i];}] : [], difficulties: meta.difficulties, noteStyle: addVars.noteStyle != null ? addVars.noteStyle : Flags.BASEGAME_DEFAULT_NOTE_STYLE, album: addVars.album != null ? addVars.album : Flags.BASEGAME_DEFAULT_ALBUM_ID, previewStart: addVars.previewStart != null ? addVars.previewStart : Flags.BASEGAME_DEFAULT_PREVIEW_START, previewEnd: addVars.previewEnd != null ? addVars.previewEnd : Flags.BASEGAME_DEFAULT_PREVIEW_END }, }; return result; return null; } public static function encodeChart(chart:ChartData):NewSwagSong { // TO DO return null; } } // METADATA STRUCTURES typedef SwagMetadata = { var timeFormat:SwagTimeFormat; var artist:String; var songName:String; var playData:SwagPlayData; var timeChanges:Array; var generatedBy:String; var looped:Bool; var version:String; var ?divisions:Int; var ?offsets:SwagSongOffsets; } enum abstract SwagTimeFormat(String) from String to String { var TICKS = 'ticks'; var FLOAT = 'float'; var MILLISECONDS = 'ms'; } typedef SwagTimeChange = { var ?d:Int; // Time Signature Den var ?n:Int; // Time Signature Num var t:Int; // Time Stamp var ?b:Int; // Beat Time var ?bt:Array; // Beat Tuplets var bpm:Float; } typedef SwagPlayData = { var album:String; var previewStart:Float; var previewEnd:Float; var stage:String; var characters:SwagCharactersList; var songVariations:Array; var difficulties:Array; var noteStyle:String; } typedef SwagCharactersList = { var player:String; var girlfriend:String; var opponent:String; var instrumental:String; var altInstrumentals:Array; var opponentVocals:Array; var playerVocals:Array; } typedef SwagSongOffsets = { var ?instrumental:Float; var ?altInstrumentals:Dynamic; var ?vocals:Dynamic; } // CHART STRUCTURE typedef NewSwagSong = { var version:String; var scrollSpeed:Dynamic; // Map var events:Array; var notes:Dynamic; // Map> var generatedBy:String; } typedef SwagEvent = { var t:Float; // Time var e:String; // Event Kind var v:Dynamic; // Value (Map) } typedef SwagNote = { var t:Float; // Time var d:Int; // Data var l:Float; // Length var k:String; // Kind }