Merge branch 'main' into translations-system

This commit is contained in:
Ne_Eo
2025-01-09 20:26:29 +01:00
119 changed files with 1207 additions and 416 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ class GameOverSubstate extends MusicBeatSubstate
var camFollow:FlxObject;
public static var script:String = "";
public static var script:String = Flags.DEFAULT_GAMEOVER_SCRIPT;
public var gameoverScript:Script;
public var game:PlayState = PlayState.instance; // shortcut
+7
View File
@@ -2,7 +2,14 @@ package funkin.game;
import flixel.math.FlxPoint;
/**
* Camera meant for PlayState hud, allows for flipping the camera.
**/
class HudCamera extends FlxCamera {
/**
* Whenever the camera should flip the y axis.
* Keeps the sprites not flipped, but the positions are flipped.
*/
public var downscroll:Bool = false;
//public override function update(elapsed:Float) {
// super.update(elapsed);
+1 -1
View File
@@ -75,7 +75,7 @@ class Note extends FlxSprite
public var scrollSpeed:Null<Float> = null;
public var noteAngle:Null<Float> = null;
public var noteType(get, null):String;
public var noteType(get, never):String;
@:dox(hide) public var __strumCameras:Array<FlxCamera> = null;
@:dox(hide) public var __strum:Strum = null;
+12 -2
View File
@@ -3,6 +3,10 @@ package funkin.game;
import flixel.util.FlxSort;
import funkin.backend.system.Conductor;
/**
* Group of notes, that handles updating and rendering only the visible notes.
* To only get the visible notes you gotta do `group.forEach()` or `group.forEachAlive()` instead of `group.members`.
**/
class NoteGroup extends FlxTypedGroup<Note> {
var __loopSprite:Note;
var i:Int = 0;
@@ -10,7 +14,7 @@ class NoteGroup extends FlxTypedGroup<Note> {
var __time:Float = -1.0;
/**
* How many ms it should show a note before it should be hit
* How many milliseconds it should show a note before it should be hit
**/
public var limit:Float = Flags.DEFAULT_NOTE_MS_LIMIT;
@@ -22,11 +26,17 @@ class NoteGroup extends FlxTypedGroup<Note> {
length = len;
}
/**
* Adds an array of notes to the group, and sorts them.
**/
public inline function addNotes(notes:Array<Note>) {
for(e in notes) add(e);
sortNotes();
}
/**
* Sorts the notes in the group.
**/
public inline function sortNotes() {
sort(function(i, n1, n2) {
if (n1.strumTime == n2.strumTime)
@@ -117,7 +127,7 @@ class NoteGroup extends FlxTypedGroup<Note> {
if (index < 0)
return null;
// doesnt prevent looping from breaking
// doesn't prevent looping from breaking
if (Splice && __currentlyLooping && i >= index)
i++;
+12 -8
View File
@@ -30,7 +30,7 @@ import funkin.game.SplashHandler;
import funkin.game.cutscenes.*;
import funkin.menus.*;
import funkin.menus.StoryMenuState.WeekData;
import funkin.backend.utils.FunkinSave;
import funkin.savedata.FunkinSave;
import haxe.io.Path;
using StringTools;
@@ -189,11 +189,11 @@ class PlayState extends MusicBeatState
/**
* Player strums.
*/
public var playerStrums(get, null):StrumLine;
public var playerStrums(get, set):StrumLine;
/**
* CPU strums.
*/
public var cpuStrums(get, null):StrumLine;
public var cpuStrums(get, set):StrumLine;
/**
* Shortcut to `playerStrums`.
*/
@@ -360,7 +360,7 @@ class PlayState extends MusicBeatState
/**
* Accuracy for the current week
*/
public static var campaignAccuracy(get, null):Float;
public static var campaignAccuracy(get, never):Float;
public static var campaignAccuracyTotal:Float = 0;
public static var campaignAccuracyCount:Float = 0;
@@ -423,7 +423,7 @@ class PlayState extends MusicBeatState
*/
public var events:Array<ChartEvent> = [];
/**
* Current camera target. -1 means no automatic camera targetting.
* Current camera target. -1 means no automatic camera targeting.
*/
public var curCameraTarget:Int = 0;
/**
@@ -586,8 +586,8 @@ class PlayState extends MusicBeatState
instance = this;
if (FlxG.sound.music != null) FlxG.sound.music.stop();
PauseSubState.script = "";
GameOverSubstate.script = "";
PauseSubState.script = Flags.DEFAULT_PAUSE_SCRIPT;
GameOverSubstate.script = Flags.DEFAULT_GAMEOVER_SCRIPT;
(scripts = new ScriptPack("PlayState")).setParent(this);
camGame = camera;
@@ -642,7 +642,7 @@ class PlayState extends MusicBeatState
for(folder in scriptsFolders) {
for(file in Paths.getFolderContent(folder, true, fromMods ? MODS : BOTH)) {
if (folder == 'data/charts/')
Logs.warn('data/charts/ is deprecrated and will be removed in the future. Please move script $file to songs/', DARKYELLOW, "PlayState");
Logs.warn('data/charts/ is deprecated and will be removed in the future. Please move script $file to songs/', DARKYELLOW, "PlayState");
addScript(file);
}
@@ -1949,8 +1949,12 @@ class PlayState extends MusicBeatState
}
private inline function get_cpuStrums():StrumLine
return strumLines.members[0];
private inline function set_cpuStrums(v:StrumLine):StrumLine
return strumLines.members[0] = v;
private inline function get_playerStrums():StrumLine
return strumLines.members[1];
private inline function set_playerStrums(v:StrumLine):StrumLine
return strumLines.members[1] = v;
private inline function get_gfSpeed():Int
return (strumLines.members[2] != null && strumLines.members[2].characters[0] != null) ? strumLines.members[2].characters[0].beatInterval : 1;
private inline function set_gfSpeed(v:Int):Int {
+1 -1
View File
@@ -35,7 +35,7 @@ class SplashGroup extends FlxTypedGroup<FunkinSprite> {
pregenerateSplashes(splash);
add(splash);
// immediatly draw once and put image in GPU to prevent freezes
// immediately draw once and put image in GPU to prevent freezes
// TODO: change to graphics cache
splash.drawComplex(FlxG.camera);
} catch(e:Dynamic) {
+32 -1
View File
@@ -14,6 +14,9 @@ import haxe.xml.Access;
using StringTools;
/**
* A class that handles loading a stage and putting the sprites into the state.
**/
class Stage extends FlxBasic implements IBeatReceiver {
public var stageName:String = "";
public var stageXML:Access;
@@ -26,9 +29,15 @@ class Stage extends FlxBasic implements IBeatReceiver {
private var spritesParentFolder = "";
/**
* Gets a sprite from the stage.
**/
public function getSprite(name:String)
return stageSprites[name];
/**
* Sets the sprites in the script, so you can access them by the name.
**/
public function setStagesSprites(script:Script)
for (k=>e in stageSprites) script.set(k, e);
@@ -185,7 +194,7 @@ class Stage extends FlxBasic implements IBeatReceiver {
setStagesSprites(stageScript);
// i know this for gets run twice under, but its better like this in case a script modifies the short lived ones, i dont wanna save them in an array; more dynamic like this - Nex
// i know this for gets run twice under, but its better like this in case a script modifies the short lived ones, i don't wanna save them in an array; more dynamic like this - Nex
for (info in xmlImportedScripts) if (info.importStageSprites) {
var script = info.getScript();
if (script != null) setStagesSprites(script);
@@ -210,6 +219,12 @@ class Stage extends FlxBasic implements IBeatReceiver {
prepareInfos(node);
}
/**
* Adds a character position to the stage.
* @param name The name of the character
* @param node The XML node
* @param nonXMLInfo (Optional) Non-XML information
**/
public function addCharPos(name:String, node:Access, ?nonXMLInfo:StageCharPosInfo):StageCharPos {
var charPos = new StageCharPos();
charPos.visible = charPos.active = false;
@@ -252,9 +267,21 @@ class Stage extends FlxBasic implements IBeatReceiver {
return characterPoses[name] = charPos;
}
/**
* Checks if a character is flipped or not.
* @param posName The name of the character position
* @param def The default value
**/
public inline function isCharFlipped(posName:String, def:Bool = false)
return characterPoses[posName] != null ? characterPoses[posName].flipX : def;
/**
* Applies the character stuff to the character.
* Adds the character to the stage, or inserts it into the stage.
* @param char The character
* @param posName The name of the character position
* @param id The ID of the character
**/
public function applyCharStuff(char:Character, posName:String, id:Float = 0) {
var charPos = characterPoses[char.curCharacter] != null ? characterPoses[char.curCharacter] : characterPoses[posName];
if (charPos != null) {
@@ -271,6 +298,10 @@ class Stage extends FlxBasic implements IBeatReceiver {
public function measureHit(curMeasure:Int) {}
/**
* Gets a list of stages that are available to be used.
* @param mods Whenever only the mods folder should be checked
**/
public static function getList(?mods:Bool = false):Array<String> {
var list:Array<String> = [];
for (path in Paths.getFolderContent('data/stages/', true, mods ? MODS : BOTH))
+72 -5
View File
@@ -4,6 +4,9 @@ import flixel.math.FlxPoint;
import funkin.backend.system.Conductor;
class Strum extends FlxSprite {
/**
* Extra data that can be added to the strum.
**/
public var extra:Map<String, Dynamic> = [];
/**
@@ -11,21 +14,48 @@ class Strum extends FlxSprite {
*/
public var animSuffix:String = "";
public var cpu = false; // Unused
/**
* Whenever the strum should act as a CPU strum.
* WARNING: Unused.
**/
@:dox(hide) public var cpu:Bool = false; // Unused
/**
* The last time the note/confirm animation was hit.
**/
public var lastHit:Float = -5000;
public var strumLine = null;
/**
* The strum line that this strum belongs to.
**/
public var strumLine:StrumLine;
/**
* The scroll speed of the notes.
**/
public var scrollSpeed:Null<Float> = null; // custom scroll speed per strum
/**
* The direction of the notes.
* If you don't want angle of the strum to interfere with the direction the notes are going,
* you can set noteAngle to = 0, and then you can use the angle of the strum without it affecting the direction of the notes.
**/
public var noteAngle:Null<Float> = null;
public var lastDrawCameras(default, null):Array<FlxCamera> = [];
/**
* Whenever the strum is pressed.
**/
public var getPressed:StrumLine->Bool = null;
/**
* Whenever the strum was just pressed.
**/
public var getJustPressed:StrumLine->Bool = null;
/**
* Whenever the strum was just released.
**/
public var getJustReleased:StrumLine->Bool = null;
public inline function __getPressed(strumLine:StrumLine):Bool {
@:dox(hide) 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;
@@ -34,7 +64,7 @@ class Strum extends FlxSprite {
default: false;
}
}
public inline function __getJustPressed(strumLine:StrumLine) {
@:dox(hide) 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;
@@ -43,7 +73,7 @@ class Strum extends FlxSprite {
default: false;
}
}
public inline function __getJustReleased(strumLine:StrumLine) {
@:dox(hide) 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;
@@ -53,6 +83,10 @@ class Strum extends FlxSprite {
}
}
/**
* Gets the scroll speed of the notes.
* @param note (Optional) The note
**/
public inline function getScrollSpeed(?note:Note):Float {
if (note != null && note.scrollSpeed != null) return note.scrollSpeed;
if (scrollSpeed != null) return scrollSpeed;
@@ -60,6 +94,12 @@ class Strum extends FlxSprite {
return 1;
}
/**
* Gets the angle of the notes.
* If you don't want angle of the strum to interfere with the direction the notes are going,
* you can set noteAngle to = 0, and then you can use the angle of the strum without it affecting the direction of the notes.
* @param note (Optional) The note
**/
public inline function getNotesAngle(?note:Note):Float {
if (note != null && note.noteAngle != null) return note.noteAngle;
if (noteAngle != null) return noteAngle;
@@ -83,6 +123,10 @@ class Strum extends FlxSprite {
@:noCompletion public static final PIX180:Float = 565.4866776461628; // 180 * Math.PI
@:noCompletion public static final N_WIDTHDIV2:Float = Note.swagWidth / 2;
/**
* Updates the position of a note.
* @param daNote The note
**/
public function updateNotePosition(daNote:Note) {
if (!daNote.exists) return;
@@ -130,11 +174,21 @@ class Strum extends FlxSprite {
}
}
/**
* Updates a sustain note.
* @param daNote The note
**/
public inline function updateSustain(daNote:Note) {
if (!daNote.isSustainNote) return;
daNote.updateSustain(this);
}
/**
* Updates the animation state based on the player input.
* @param pressed Whenever the player is pressing the button
* @param justPressed Whenever the player just pressed the button
* @param justReleased Whenever the player just released the button
**/
public function updatePlayerInput(pressed:Bool, justPressed:Bool, justReleased:Bool) {
switch(getAnim()) {
case "confirm":
@@ -151,16 +205,29 @@ class Strum extends FlxSprite {
}
}
/**
* Plays the confirm animation.
* @param time The time
**/
public inline function press(time:Float) {
lastHit = time;
playAnim("confirm");
}
/**
* Plays an animation.
* @param anim The animation name
* @param force Whenever the animation should be forced to play
**/
public function playAnim(anim:String, force:Bool = true) {
animation.play(anim, force);
centerOffsets();
centerOrigin();
}
/**
* Gets the current animation name.
**/
public inline function getAnim() {
return animation.name;
}
+40 -4
View File
@@ -9,6 +9,10 @@ import funkin.backend.scripting.events.note.*;
import funkin.backend.system.Conductor;
import funkin.backend.system.Controls;
/**
* Group of strums, that contains the strums and notes.
* Used in PlayState.
**/
class StrumLine extends FlxTypedGroup<Strum> {
/**
* Signal that triggers whenever a note is hit. Similar to onPlayerHit and onDadHit, except strumline specific.
@@ -71,14 +75,16 @@ class StrumLine extends FlxTypedGroup<Strum> {
*/
public var animSuffix(default, set):String = "";
/**
* TODO: Write documention about this being a variable that can help when making multi key
* TODO: Write documentation about this being a variable that can help when making multi key
*/
public var strumAnimPrefix = ["left", "down", "up", "right"];
/**
* Vocals sound (Vocals.ogg). Used for individual vocals per strumline.
*/
public var vocals:FlxSound;
/**
* Extra data that can be added to the strum line.
**/
public var extra:Map<String, Dynamic> = [];
private function get_ghostTapping() {
@@ -90,8 +96,14 @@ class StrumLine extends FlxTypedGroup<Strum> {
private inline function set_ghostTapping(b:Bool):Bool
return this.ghostTapping = b;
private var startingPos:FlxPoint = FlxPoint.get(0,0);
private var strumScale:Float = 1;
/**
* The scale of the strums.
* If called after generate, the strums wont be scaled.
* You can only change it in the Charter.
**/
public var strumScale:Float = 1;
public function new(characters:Array<Character>, startingPos:FlxPoint, strumScale:Float, cpu:Bool = false, opponentSide:Bool = true, ?controls:Controls, ?vocalPrefix:String = "") {
super();
@@ -106,6 +118,9 @@ class StrumLine extends FlxTypedGroup<Strum> {
vocals.persist = false;
}
/**
* Generates the notes for the strumline.
**/
public function generate(strumLine:ChartStrumLine, ?startTime:Float) {
// TODO: implement double generate call support if needed
@@ -153,7 +168,7 @@ class StrumLine extends FlxTypedGroup<Strum> {
if(scrollSpeed == null) if (PlayState.instance != null) scrollSpeed = PlayState.instance.scrollSpeed;
if(scrollSpeed == null) scrollSpeed = 1;
// TODO: Make this work by accounting zoom and scrollspeed changes - Nex
// TODO: Make this work by accounting zoom and scroll speed changes - Nex
/*var limit = FlxG.height / 0.45;
notes.limit = limit / scrollSpeed;
OR
@@ -171,6 +186,9 @@ class StrumLine extends FlxTypedGroup<Strum> {
notes.draw();
}
/**
* Updates the notes.
**/
public inline function updateNotes() {
__updateNote_songPos = Conductor.songPosition;
if(__updateNote_event == null) __updateNote_event = PlayState.instance.__updateNote_event;
@@ -180,6 +198,10 @@ class StrumLine extends FlxTypedGroup<Strum> {
var __updateNote_strum:Strum;
var __updateNote_songPos:Float;
var __updateNote_event:NoteUpdateEvent;
/**
* Updates a note.
* This updates the position, state, and handles the input.
**/
public function updateNote(daNote:Note) {
__updateNote_strum = members[daNote.noteData];
if (__updateNote_strum == null) return;
@@ -236,6 +258,11 @@ class StrumLine extends FlxTypedGroup<Strum> {
else if (note.strumTime < __notePerStrum[note.strumID].strumTime) __notePerStrum[note.strumID] = note;
}
}
/**
* Updates the input for the strumline, and handles the input.
* @param id The ID of the strum
**/
public function updateInput(id:Int = 0) {
updateNotes();
@@ -291,9 +318,18 @@ class StrumLine extends FlxTypedGroup<Strum> {
PlayState.instance.gameAndCharsCall("onPostInputUpdate");
}
/**
* Adds/removes health to/from the strumline.
* If the strumline is an opponent strumline, it will subtract the health, otherwise it will add the health.
* @param health The amount of health to add/remove
**/
public inline function addHealth(health:Float)
PlayState.instance.health += health * (opponentSide ? -1 : 1);
/**
* Generates strums, and adds them to the strumline.
* @param amount The amount of strums to generate (-1 for the default amount)
**/
public inline function generateStrums(amount:Int = -1) {
if(amount == -1) amount = Flags.DEFAULT_STRUM_AMOUNT;
for (i in 0...amount)
@@ -35,7 +35,7 @@ class DialogueCutscene extends ScriptedCutscene {
return curLine = val;
}
// Backwards comapt funcs - Nex
// Backwards compat funcs - Nex
public function set_dialogueScript(val:Script) return script = val;
public function get_dialogueScript() return script;
@@ -125,7 +125,7 @@ class ScriptedCutscene extends Cutscene {
}));
}
public var isVideoPlaying(get, null):Bool;
public var isVideoPlaying(get, never):Bool;
private inline function get_isVideoPlaying()
return subState is VideoCutscene;
@@ -141,7 +141,7 @@ class ScriptedCutscene extends Cutscene {
}));
}
public var isDialoguePlaying(get, null):Bool;
public var isDialoguePlaying(get, never):Bool;
private inline function get_isDialoguePlaying()
return subState is DialogueCutscene;
@@ -10,7 +10,7 @@ import haxe.xml.Access;
class DialogueBox extends FunkinSprite {
public var dialogueBoxData:Access;
public var positions:Map<String, CharPosDef> = [];
public var dialogueEnded:Bool = false; // Using text._typing is also fair but it doesnt check for eventual opening anims! - Nex
public var dialogueEnded:Bool = false; // Using text._typing is also fair but it doesn't check for eventual opening anims! - Nex
public var nextSFX:String = Paths.sound('dialogue/next');
public var defaultTextTypeSFX:Array<FlxSound>;
@@ -22,7 +22,7 @@ class DialogueBox extends FunkinSprite {
public function new(name:String) {
super();
var textTypeSFX:String = Paths.sound('dialogue/text'); // Default if xml doesnt have it - Nex
var textTypeSFX:String = Paths.sound('dialogue/text'); // Default if xml doesn't have it - Nex
dialogueBoxScript = Script.create(Paths.script('data/' + defPath + name));
dialogueBoxScript.setParent(this);