Merge remote-tracking branch 'upstream/main'
This commit is contained in:
@@ -18,7 +18,7 @@ class Socket implements IFlxDestroyable {
|
||||
|
||||
public function read():String {
|
||||
try {
|
||||
return this.socket.input.readUntil(('\n').charCodeAt(0)).replace("\\n", "\n");
|
||||
return this.socket.input.readUntil('\n'.code).replace("\\n", "\n");
|
||||
} catch(e) {
|
||||
|
||||
}
|
||||
|
||||
@@ -980,6 +980,124 @@ class CoolUtil
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public inline static function parsePropertyString(fieldPath:String):Array<OneOfTwo<String, Int>> {
|
||||
return FlxTween.parseFieldString(fieldPath);
|
||||
}
|
||||
|
||||
public static function stringifyFieldsPath(fields:Array<OneOfTwo<String, Int>>):String {
|
||||
var str = new StringBuf();
|
||||
var first = true;
|
||||
for (field in fields) {
|
||||
if (Type.typeof(field) == TInt) {
|
||||
str.add('[${field}]');
|
||||
} else {
|
||||
if (!first)
|
||||
str.add('.');
|
||||
str.add(field);
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
public static function parseProperty(target:Dynamic, fields:OneOfTwo<String, Array<OneOfTwo<String, Int>>>):Dynamic {
|
||||
var fields:Array<OneOfTwo<String, Int>> = {
|
||||
if((fields is String)) CoolUtil.parsePropertyString(fields);
|
||||
else fields;
|
||||
}
|
||||
|
||||
var field = CoolUtil.last(fields);
|
||||
for (i in 0...fields.length - 1) {
|
||||
var component = fields[i];
|
||||
if (Type.typeof(component) == TInt) {
|
||||
if ((target is Array)) {
|
||||
var index:Int = cast component;
|
||||
var arr:Array<Dynamic> = cast target;
|
||||
target = arr[index];
|
||||
}
|
||||
} else { // TClass(String)
|
||||
target = Reflect.getProperty(target, component);
|
||||
}
|
||||
if (!Reflect.isObject(target) && !(target is Array))
|
||||
throw 'The object does not have the property "$component" in "${stringifyFieldsPath(fields)}"';
|
||||
}
|
||||
return new PropertyInfo(target, field);
|
||||
}
|
||||
|
||||
public static function cloneProperty(toTarget:Dynamic, fields:OneOfTwo<String, Array<OneOfTwo<String, Int>>>, fromTarget:Dynamic):Dynamic {
|
||||
var fields:Array<OneOfTwo<String, Int>> = {
|
||||
if((fields is String)) CoolUtil.parsePropertyString(fields);
|
||||
else fields;
|
||||
}
|
||||
|
||||
var toProperty = CoolUtil.parseProperty(toTarget, fields);
|
||||
var fromProperty = CoolUtil.parseProperty(fromTarget, fields);
|
||||
|
||||
return toProperty.setValue(fromProperty.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
class PropertyInfo {
|
||||
public var object:Dynamic;
|
||||
public var field:OneOfTwo<String, Int>;
|
||||
public var typeOfField:Type.ValueType;
|
||||
#if hscript_improved
|
||||
public var isCustom:Bool = false;
|
||||
public var custom:hscript.IHScriptCustomBehaviour;
|
||||
#end
|
||||
|
||||
public function new(object:Dynamic, field:OneOfTwo<String, Int>) {
|
||||
this.object = object;
|
||||
this.field = field;
|
||||
#if hscript_improved
|
||||
if (object is hscript.IHScriptCustomBehaviour)
|
||||
{
|
||||
isCustom = true;
|
||||
custom = cast object;
|
||||
}
|
||||
#end
|
||||
|
||||
typeOfField = Type.typeof(field);
|
||||
}
|
||||
|
||||
public function getValue():Dynamic
|
||||
{
|
||||
if (typeOfField == TInt)
|
||||
{
|
||||
var index:Int = cast field;
|
||||
var arr:Array<Dynamic> = cast object;
|
||||
return arr[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
#if hscript_improved
|
||||
if (isCustom)
|
||||
return custom.hget(field);
|
||||
else
|
||||
#end
|
||||
return Reflect.getProperty(object, field);
|
||||
}
|
||||
}
|
||||
|
||||
public function setValue(value:Dynamic):Void
|
||||
{
|
||||
if (typeOfField == TInt)
|
||||
{
|
||||
var index:Int = cast field;
|
||||
var arr:Array<Dynamic> = cast object;
|
||||
arr[index] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if hscript_improved
|
||||
if (isCustom)
|
||||
custom.hset(field, value);
|
||||
else
|
||||
#end
|
||||
Reflect.setProperty(object, field, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -135,12 +135,12 @@ class ZipUtil {
|
||||
if (prog == null) prog = new ZipProgress();
|
||||
|
||||
try {
|
||||
var curPath:Array<String> = ['$path'];
|
||||
var curPath:Array<String> = [path];
|
||||
var destPath:Array<String> = [];
|
||||
if (prefix != "") {
|
||||
prefix = prefix.replace("\\", "/");
|
||||
while(prefix.charAt(0) == "/") prefix = prefix.substr(1);
|
||||
while(prefix.charAt(prefix.length-1) == "/") prefix = prefix.substr(0, prefix.length-1);
|
||||
while(prefix.charCodeAt(0) == "/".code) prefix = prefix.substr(1);
|
||||
while(prefix.charCodeAt(prefix.length-1) == "/".code) prefix = prefix.substr(0, prefix.length-1);
|
||||
destPath.push(prefix);
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ class ZipUtil {
|
||||
} else {
|
||||
// is file, put it in the list
|
||||
var zipPath = '$zipPath/$e';
|
||||
while(zipPath.charAt(0) == "/") zipPath = zipPath.substr(1);
|
||||
while(zipPath.charCodeAt(0) == "/".code) zipPath = zipPath.substr(1);
|
||||
files.push(new StrNameLabel('$path/$e', zipPath));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,29 +101,8 @@ class GameOverSubstate extends MusicBeatSubstate
|
||||
if (__cancelDefault)
|
||||
return;
|
||||
|
||||
if (controls.ACCEPT)
|
||||
{
|
||||
endBullshit();
|
||||
}
|
||||
|
||||
if (controls.BACK)
|
||||
{
|
||||
if (PlayState.chartingMode && Charter.undos.unsaved)
|
||||
game.saveWarn(false);
|
||||
else {
|
||||
if (Charter.instance != null) Charter.instance.__clearStatics();
|
||||
|
||||
if (FlxG.sound.music != null)
|
||||
FlxG.sound.music.stop();
|
||||
FlxG.sound.music = null;
|
||||
|
||||
if (PlayState.isStoryMode)
|
||||
FlxG.switchState(new StoryMenuState());
|
||||
else
|
||||
FlxG.switchState(new FreeplayState());
|
||||
}
|
||||
|
||||
}
|
||||
if (controls.ACCEPT) endBullshit();
|
||||
if (controls.BACK) exit();
|
||||
|
||||
if (!isEnding && ((!lossSFX.playing) || (character.getAnimName() == "firstDeath" && character.isAnimFinished())) && (FlxG.sound.music == null || !FlxG.sound.music.playing))
|
||||
{
|
||||
@@ -192,6 +171,25 @@ class GameOverSubstate extends MusicBeatSubstate
|
||||
});
|
||||
}
|
||||
|
||||
function exit()
|
||||
{
|
||||
var event = new CancellableEvent();
|
||||
gameoverScript.call('onReturnToMenu', [event]);
|
||||
|
||||
if (event.cancelled)
|
||||
return;
|
||||
|
||||
if (PlayState.chartingMode && Charter.undos.unsaved) game.saveWarn(false);
|
||||
else {
|
||||
if (Charter.instance != null) Charter.instance.__clearStatics();
|
||||
|
||||
if (FlxG.sound.music != null) FlxG.sound.music.stop();
|
||||
FlxG.sound.music = null;
|
||||
|
||||
FlxG.switchState(PlayState.isStoryMode ? new StoryMenuState() : new FreeplayState());
|
||||
}
|
||||
}
|
||||
|
||||
override function destroy()
|
||||
{
|
||||
gameoverScript.call("destroy");
|
||||
|
||||
@@ -75,6 +75,11 @@ class Note extends FlxSprite
|
||||
public var scrollSpeed:Null<Float> = null;
|
||||
public var noteAngle:Null<Float> = null;
|
||||
|
||||
public var copyStrumAngle:Bool = true;
|
||||
public var updateNotesPosX:Bool = true;
|
||||
public var updateNotesPosY:Bool = true;
|
||||
public var updateFlipY:Bool = true;
|
||||
|
||||
public var noteType(get, never):String;
|
||||
|
||||
@:dox(hide) public var __strumCameras:Array<FlxCamera> = null;
|
||||
@@ -211,7 +216,7 @@ class Note extends FlxSprite
|
||||
|
||||
override function drawComplex(camera:FlxCamera) {
|
||||
var downscrollCam = (camera is HudCamera ? ({var _:HudCamera=cast camera;_;}).downscroll : false);
|
||||
flipY = (isSustainNote && flipSustain) && (downscrollCam != (__strum != null && __strum.getScrollSpeed(this) < 0));
|
||||
if (updateFlipY) flipY = (isSustainNote && flipSustain) && (downscrollCam != (__strum != null && __strum.getScrollSpeed(this) < 0));
|
||||
if (downscrollCam) {
|
||||
frameOffset.y += __notePosFrameOffset.y * 2;
|
||||
super.drawComplex(camera);
|
||||
|
||||
@@ -710,7 +710,7 @@ class PlayState extends MusicBeatState
|
||||
case 2: "girlfriend";
|
||||
}) : strumLine.position;
|
||||
if (strumLine.characters != null) for(k=>charName in strumLine.characters) {
|
||||
var char = new Character(0, 0, charName, stage.isCharFlipped(charPosName, strumLine.type == 1));
|
||||
var char = new Character(0, 0, charName, stage.isCharFlipped(stage.characterPoses[charName] != null ? charName : charPosName, strumLine.type == 1));
|
||||
stage.applyCharStuff(char, charPosName, k);
|
||||
chars.push(char);
|
||||
}
|
||||
@@ -1312,9 +1312,6 @@ class PlayState extends MusicBeatState
|
||||
|
||||
updateRatingStuff();
|
||||
|
||||
if (controls.PAUSE && startedCountdown && canPause)
|
||||
pauseGame();
|
||||
|
||||
if (canAccessDebugMenus) {
|
||||
if (chartingMode && FlxG.keys.justPressed.SEVEN) {
|
||||
FlxG.switchState(new funkin.editors.charter.Charter(SONG.meta.name, difficulty, false));
|
||||
@@ -1357,6 +1354,9 @@ class PlayState extends MusicBeatState
|
||||
while(events.length > 0 && events.last().time <= Conductor.songPosition)
|
||||
executeEvent(events.pop());
|
||||
|
||||
if (controls.PAUSE && startedCountdown && canPause)
|
||||
pauseGame();
|
||||
|
||||
if (generatedMusic)
|
||||
moveCamera();
|
||||
|
||||
@@ -1442,7 +1442,27 @@ class PlayState extends MusicBeatState
|
||||
|
||||
switch(event.name) {
|
||||
case "HScript Call":
|
||||
scripts.call(event.params[0], event.params[1].split(','));
|
||||
var scriptPacks:Array<ScriptPack> = [scripts, stateScripts];
|
||||
for (strLine in strumLines.members) for (char in strLine.characters) scriptPacks.push(char.scripts);
|
||||
var args:Array<String> = event.params[1].split(',');
|
||||
|
||||
for (pack in scriptPacks) {
|
||||
pack.call(event.params[0], args);
|
||||
//public functions
|
||||
if (pack.publicVariables.exists(event.params[0])) {
|
||||
var func = pack.publicVariables.get(event.params[0]);
|
||||
if (func != null && Reflect.isFunction(func))
|
||||
Reflect.callMethod(null, func, args);
|
||||
}
|
||||
}
|
||||
|
||||
//static functions
|
||||
if (Script.staticVariables.exists(event.params[0])) {
|
||||
var func = Script.staticVariables.get(event.params[0]);
|
||||
if (func != null && Reflect.isFunction(func))
|
||||
Reflect.callMethod(null, func, args);
|
||||
}
|
||||
|
||||
case "Camera Movement":
|
||||
var tween = eventsTween.get("cameraMovement");
|
||||
if (tween != null) tween.cancel();
|
||||
|
||||
+58
-32
@@ -42,6 +42,18 @@ class Strum extends FlxSprite {
|
||||
|
||||
public var lastDrawCameras(default, null):Array<FlxCamera> = [];
|
||||
|
||||
// Copy fields
|
||||
public var copyStrumCamera:Bool = true;
|
||||
public var copyStrumScrollX:Bool = true;
|
||||
public var copyStrumScrollY:Bool = true;
|
||||
public var copyStrumAngle:Bool = true;
|
||||
public var updateNotesPosX:Bool = true;
|
||||
public var updateNotesPosY:Bool = true;
|
||||
public var extraCopyFields(default, set):Array<String> = [];
|
||||
|
||||
private inline function set_extraCopyFields(val:Array<String>)
|
||||
return extraCopyFields = val == null ? [] : val;
|
||||
|
||||
/**
|
||||
* Whenever the strum is pressed.
|
||||
**/
|
||||
@@ -130,47 +142,61 @@ 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);
|
||||
daNote.__noteAngle = getNotesAngle(daNote);
|
||||
daNote.angle = daNote.isSustainNote ? daNote.__noteAngle : angle;
|
||||
if (copyStrumCamera) daNote.__strumCameras = lastDrawCameras;
|
||||
if (copyStrumScrollX) daNote.scrollFactor.x = scrollFactor.x;
|
||||
if (copyStrumScrollY) daNote.scrollFactor.y = scrollFactor.y;
|
||||
if (copyStrumAngle && daNote.copyStrumAngle) {
|
||||
daNote.__noteAngle = getNotesAngle(daNote);
|
||||
daNote.angle = daNote.isSustainNote ? daNote.__noteAngle : angle;
|
||||
}
|
||||
|
||||
updateNotePos(daNote);
|
||||
for (field in extraCopyFields)
|
||||
CoolUtil.cloneProperty(daNote, field, this); // TODO: make this cached to reduce the reflection calls - Neo
|
||||
}
|
||||
|
||||
private inline function updateNotePos(daNote:Note) {
|
||||
if (daNote.strumRelativePos) {
|
||||
daNote.setPosition((this.width - daNote.width) / 2, (daNote.strumTime - Conductor.songPosition) * (0.45 * CoolUtil.quantize(getScrollSpeed(daNote), 100)));
|
||||
if (daNote.isSustainNote) daNote.y += N_WIDTHDIV2;
|
||||
} else {
|
||||
var offset = FlxPoint.get(0, (Conductor.songPosition - daNote.strumTime) * (0.45 * CoolUtil.quantize(getScrollSpeed(daNote), 100)));
|
||||
var realOffset = FlxPoint.get(0, 0);
|
||||
var shouldX = updateNotesPosX && daNote.updateNotesPosX;
|
||||
var shouldY = updateNotesPosY && daNote.updateNotesPosY;
|
||||
|
||||
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);
|
||||
|
||||
var aOffset:FlxPoint = FlxPoint.get(
|
||||
(daNote.origin.x / daNote.scale.x) - daNote.offset.x,
|
||||
(daNote.origin.y / daNote.scale.y) - daNote.offset.y
|
||||
);
|
||||
realOffset.x = -aOffset.x + (noteAngleCos * (offset.x + aOffset.x)) + (noteAngleSin * (offset.y + aOffset.y));
|
||||
realOffset.y = -aOffset.y + (noteAngleSin * (offset.x + aOffset.x)) + (noteAngleCos * (offset.y + aOffset.y));
|
||||
|
||||
aOffset.put();
|
||||
if (shouldX || shouldY) {
|
||||
if (daNote.strumRelativePos) {
|
||||
if (shouldX) daNote.x = (this.width - daNote.width) / 2;
|
||||
if (shouldY) {
|
||||
daNote.y = (daNote.strumTime - Conductor.songPosition) * (0.45 * CoolUtil.quantize(getScrollSpeed(daNote), 100));
|
||||
if (daNote.isSustainNote) daNote.y += N_WIDTHDIV2;
|
||||
}
|
||||
} else {
|
||||
realOffset.x = offset.x;
|
||||
realOffset.y = offset.y;
|
||||
var offset = FlxPoint.get(0, (Conductor.songPosition - daNote.strumTime) * (0.45 * CoolUtil.quantize(getScrollSpeed(daNote), 100)));
|
||||
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);
|
||||
|
||||
var aOffset:FlxPoint = FlxPoint.get(
|
||||
(daNote.origin.x / daNote.scale.x) - daNote.offset.x,
|
||||
(daNote.origin.y / daNote.scale.y) - daNote.offset.y
|
||||
);
|
||||
realOffset.x = -aOffset.x + (noteAngleCos * (offset.x + aOffset.x)) + (noteAngleSin * (offset.y + aOffset.y));
|
||||
realOffset.y = -aOffset.y + (noteAngleSin * (offset.x + aOffset.x)) + (noteAngleCos * (offset.y + aOffset.y));
|
||||
|
||||
aOffset.put();
|
||||
} else {
|
||||
realOffset.x = offset.x;
|
||||
realOffset.y = offset.y;
|
||||
}
|
||||
realOffset.y *= -1;
|
||||
|
||||
if (shouldX) daNote.x = x + realOffset.x;
|
||||
if (shouldY) daNote.y = y + realOffset.y;
|
||||
|
||||
offset.put();
|
||||
realOffset.put();
|
||||
}
|
||||
realOffset.y *= -1;
|
||||
|
||||
daNote.setPosition(x + realOffset.x, y + realOffset.y);
|
||||
|
||||
offset.put();
|
||||
realOffset.put();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -347,8 +347,10 @@ class StrumLine extends FlxTypedGroup<Strum> {
|
||||
* 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`).
|
||||
* @param spritePath (Optional) The sprite's graphic path if you don't want the default one.
|
||||
* @param playIntroAnimation (Optional) Whenever the intro animation should be played, by default might be `true` under certain conditions.
|
||||
*/
|
||||
public function createStrum(i:Int, ?animPrefix:String) {
|
||||
public function createStrum(i:Int, ?animPrefix:String, ?spritePath:String, ?playIntroAnimation:Bool) {
|
||||
if (animPrefix == null)
|
||||
animPrefix = strumAnimPrefix[i % strumAnimPrefix.length];
|
||||
var babyArrow:Strum = new Strum(startingPos.x + ((Note.swagWidth * strumScale) * i), startingPos.y);
|
||||
@@ -359,7 +361,8 @@ class StrumLine extends FlxTypedGroup<Strum> {
|
||||
babyArrow.scrollSpeed = data.scrollSpeed;
|
||||
|
||||
var event = EventManager.get(StrumCreationEvent).recycle(babyArrow, PlayState.instance.strumLines.members.indexOf(this), i, animPrefix);
|
||||
event.__doAnimation = !MusicBeatState.skipTransIn && (PlayState.instance != null ? PlayState.instance.introLength > 0 : true);
|
||||
event.__doAnimation = playIntroAnimation == null ? (!MusicBeatState.skipTransIn && (PlayState.instance != null ? PlayState.instance.introLength > 0 : true)) : playIntroAnimation;
|
||||
if (spritePath != null) event.sprite = spritePath;
|
||||
if (PlayState.instance != null) event = PlayState.instance.gameAndCharsEvent("onStrumCreation", event);
|
||||
|
||||
if (!event.cancelled) {
|
||||
|
||||
@@ -92,7 +92,7 @@ class DialogueCutscene extends ScriptedCutscene {
|
||||
callback: node.getAtt('callback'),
|
||||
changeDefAnim: node.getAtt('changeDefAnim'),
|
||||
speed: Std.parseFloat(node.getAtt("speed")).getDefault(0.05),
|
||||
musicVolume: node.has.musicVolume ? (volume = Std.parseFloat(node.att.speed).getDefault(0.8)) : null,
|
||||
musicVolume: node.has.musicVolume ? (volume = Std.parseFloat(node.att.musicVolume).getDefault(0.8)) : null,
|
||||
changeMusic: node.has.changeMusic ? FlxG.sound.load(Paths.music(node.att.changeMusic), volume, true) : null,
|
||||
playSound: node.has.playSound ? FlxG.sound.load(Paths.sound(node.att.playSound)) : null,
|
||||
nextSound: node.has.nextSound ? FlxG.sound.load(Paths.sound(node.att.nextSound)) : null,
|
||||
|
||||
Reference in New Issue
Block a user