diff --git a/.gitignore b/.gitignore index 15b47ac5..d2fb445f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,6 @@ assets/ignore !export/ export/* -!export/debug/windows/bin/mods/*/* \ No newline at end of file +!export/debug/windows/bin/mods/*/* +source/net/VeAPIKeys.hx +*.secret \ No newline at end of file diff --git a/README.md b/README.md index a2d2838b..1e5ca4d2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Friday Night Funkin - VMan Engine -Use the latest version of Polymod `haxelib update polymod` +Use version 1.5.2 of Polymod `haxelib set polymod 1.5.2` For mod makers: If you want new features in official vman engine, just make an [issue](https://github.com/VMan-2002/FNF-VMan-Engine/issues) (make sure you're on the latest release!) or a [pull request](https://github.com/VMan-2002/FNF-VMan-Engine/pulls) @@ -73,6 +73,8 @@ At the moment, you can optionally fix the transition bug in songs with zoomed-ou ### Compiling game NOTE: If you see any messages relating to deprecated packages, ignore them. They're just warnings that don't affect compiling +New: You must rename `source/net/VeAPIKeysPlaceholder.hx` to `source/net/VeAPIKeys.hx` before you try compiling. + Once you have all those installed, it's pretty easy to compile the game. You just need to run `lime test html5 -debug` in the root of the project to build and run the HTML5 version. (command prompt navigation guide can be found here: https://ninjamuffin99.newgrounds.com/news/post/1090480 ) To run it from your desktop (Windows, Mac, Linux) it can be a bit more involved. For Linux, you only need to open a terminal in the project directory and run `lime test linux -debug` and then run the executable file in export/release/linux/bin. For Windows, you need to install Visual Studio Community 2019. While installing VSC, don't click on any of the options to install workloads. Instead, go to the individual components tab and choose the following: * MSVC v142 - VS 2019 C++ x64/x86 build tools diff --git a/art/VE_Logo_Anim.fla b/art/VE_Logo_Anim.fla new file mode 100644 index 00000000..aa815dce Binary files /dev/null and b/art/VE_Logo_Anim.fla differ diff --git a/art/VManEngineLogo1.png b/art/VManEngineLogo1.png new file mode 100644 index 00000000..381ca6aa Binary files /dev/null and b/art/VManEngineLogo1.png differ diff --git a/art/VManEngineLogo2.png b/art/VManEngineLogo2.png new file mode 100644 index 00000000..ce70c57e Binary files /dev/null and b/art/VManEngineLogo2.png differ diff --git a/art/VMan_Engine_Logo.svg b/art/VMan_Engine_Logo.svg new file mode 100644 index 00000000..4bf5d3b1 --- /dev/null +++ b/art/VMan_Engine_Logo.svg @@ -0,0 +1 @@ +VManEngineFNF diff --git a/art/VMan_Engine_Logo_StrokeToPath.svg b/art/VMan_Engine_Logo_StrokeToPath.svg new file mode 100644 index 00000000..72157f9b --- /dev/null +++ b/art/VMan_Engine_Logo_StrokeToPath.svg @@ -0,0 +1 @@ +VManEngineFNF diff --git a/assets/preload/data/gamejoltLogin.txt b/assets/preload/data/gamejoltLogin.txt new file mode 100644 index 00000000..6faded5a --- /dev/null +++ b/assets/preload/data/gamejoltLogin.txt @@ -0,0 +1 @@ +replace ENTIRE CONTENT of this file with your gamejolt username in line 1 and your game token in line 2 | (this method is TEMPORARY.) \ No newline at end of file diff --git a/assets/preload/images/title/VE_Logo.png b/assets/preload/images/title/VE_Logo.png new file mode 100644 index 00000000..91434513 Binary files /dev/null and b/assets/preload/images/title/VE_Logo.png differ diff --git a/assets/preload/images/title/VE_Logo.xml b/assets/preload/images/title/VE_Logo.xml new file mode 100644 index 00000000..d1eda5c5 --- /dev/null +++ b/assets/preload/images/title/VE_Logo.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/preload/objects/noteskins/normal.json b/assets/preload/objects/noteskins/normal.json index f300dcdd..4ee27f93 100644 --- a/assets/preload/objects/noteskins/normal.json +++ b/assets/preload/objects/noteskins/normal.json @@ -1 +1 @@ -{"image":"normal/NOTE_assets"} \ No newline at end of file +{"image":"normal/NOTE_assets","antialias":true} \ No newline at end of file diff --git a/assets/preload/objects/noteskins/vpt_love_notes_fixed.json b/assets/preload/objects/noteskins/vpt_love_notes_fixed.json new file mode 100644 index 00000000..e9f40c1f --- /dev/null +++ b/assets/preload/objects/noteskins/vpt_love_notes_fixed.json @@ -0,0 +1,9 @@ +{"_comment":[ + + + "CONTEXT: Hardcoded fix for both-side mode in Love (Extra) in The Past Time", + "I shouldn't be doing this but whatever i'll remove this soon", + "If you want to use this in your mods, please copy this to your mod's files so that the eventual removal of these files won't break your mod" + + +],"image":"VPT_Love_Notes_Fix","arrows":{"purple":[{"name":"Scroll","anim":"left","framerate":12,"loop":true},{"name":"hold","anim":"hold","framerate":12,"loop":true},{"name":"holdend","anim":"hold","framerate":12,"loop":true},{"name":"static","anim":"strumleft","framerate":12,"loop":true},{"name":"pressed","anim":"pressleft","framerate":12,"loop":false},{"name":"confirm","anim":"pressleft","framerate":12,"loop":false}],"green":[{"name":"Scroll","anim":"up","framerate":12,"loop":true},{"name":"hold","anim":"hold","framerate":12,"loop":true},{"name":"holdend","anim":"hold","framerate":12,"loop":true},{"name":"static","anim":"strumup","framerate":12,"loop":true},{"name":"pressed","anim":"pressup","framerate":12,"loop":false},{"name":"confirm","anim":"pressup","framerate":12,"loop":false}],"blue":[{"name":"Scroll","anim":"down","framerate":12,"loop":true},{"name":"hold","anim":"hold","framerate":12,"loop":true},{"name":"holdend","anim":"hold","framerate":12,"loop":true},{"name":"static","anim":"strumdown","framerate":12,"loop":true},{"name":"pressed","anim":"pressdown","framerate":12,"loop":false},{"name":"confirm","anim":"pressdown","framerate":12,"loop":false}],"red":[{"name":"Scroll","anim":"right","framerate":12,"loop":true},{"name":"hold","anim":"hold","framerate":12,"loop":true},{"name":"holdend","anim":"hold","framerate":12,"loop":true},{"name":"static","anim":"strumright","framerate":12,"loop":true},{"name":"pressed","anim":"pressright","framerate":12,"loop":false},{"name":"confirm","anim":"pressright","framerate":12,"loop":false}],"yellow":[{"name":"Scroll","anim":"left","framerate":12,"loop":true},{"name":"hold","anim":"hold","framerate":12,"loop":true},{"name":"holdend","anim":"hold","framerate":12,"loop":true},{"name":"static","anim":"strumleft","framerate":12,"loop":true},{"name":"pressed","anim":"pressleft","framerate":12,"loop":false},{"name":"confirm","anim":"pressleft","framerate":12,"loop":false}],"darkred":[{"name":"Scroll","anim":"up","framerate":12,"loop":true},{"name":"hold","anim":"hold","framerate":12,"loop":true},{"name":"holdend","anim":"hold","framerate":12,"loop":true},{"name":"static","anim":"strumup","framerate":12,"loop":true},{"name":"pressed","anim":"pressup","framerate":12,"loop":false},{"name":"confirm","anim":"pressup","framerate":12,"loop":false}],"violet":[{"name":"Scroll","anim":"down","framerate":12,"loop":true},{"name":"hold","anim":"hold","framerate":12,"loop":true},{"name":"holdend","anim":"hold","framerate":12,"loop":true},{"name":"static","anim":"strumdown","framerate":12,"loop":true},{"name":"pressed","anim":"pressdown","framerate":12,"loop":false},{"name":"confirm","anim":"pressdown","framerate":12,"loop":false}],"dark":[{"name":"Scroll","anim":"right","framerate":12,"loop":true},{"name":"hold","anim":"hold","framerate":12,"loop":true},{"name":"holdend","anim":"hold","framerate":12,"loop":true},{"name":"static","anim":"strumright","framerate":12,"loop":true},{"name":"pressed","anim":"pressright","framerate":12,"loop":false},{"name":"confirm","anim":"pressright","framerate":12,"loop":false}],"white":[{"name":"Scroll","anim":"space","framerate":12,"loop":true},{"name":"hold","anim":"hold","framerate":12,"loop":true},{"name":"holdend","anim":"hold","framerate":12,"loop":true},{"name":"static","anim":"strumspace","framerate":12,"loop":true},{"name":"pressed","anim":"pressspace","framerate":12,"loop":false},{"name":"confirm","anim":"pressspace","framerate":12,"loop":false}],"13a":[{"name":"Scroll","anim":"trileft","framerate":12,"loop":true},{"name":"hold","anim":"hold","framerate":12,"loop":true},{"name":"holdend","anim":"hold","framerate":12,"loop":true},{"name":"static","anim":"strumtrileft","framerate":12,"loop":true},{"name":"pressed","anim":"presstrileft","framerate":12,"loop":false},{"name":"confirm","anim":"presstrileft","framerate":12,"loop":false}],"13b":[{"name":"Scroll","anim":"tridown","framerate":12,"loop":true},{"name":"hold","anim":"hold","framerate":12,"loop":true},{"name":"holdend","anim":"hold","framerate":12,"loop":true},{"name":"static","anim":"strumtridown","framerate":12,"loop":true},{"name":"pressed","anim":"presstridown","framerate":12,"loop":false},{"name":"confirm","anim":"presstridown","framerate":12,"loop":false}],"13c":[{"name":"Scroll","anim":"triup","framerate":12,"loop":true},{"name":"hold","anim":"hold","framerate":12,"loop":true},{"name":"holdend","anim":"hold","framerate":12,"loop":true},{"name":"static","anim":"strumup","framerate":12,"loop":true},{"name":"pressed","anim":"pressup","framerate":12,"loop":false},{"name":"confirm","anim":"pressup","framerate":12,"loop":false}],"13d":[{"name":"Scroll","anim":"triright","framerate":12,"loop":true},{"name":"hold","anim":"hold","framerate":12,"loop":true},{"name":"holdend","anim":"hold","framerate":12,"loop":true},{"name":"static","anim":"strumtriright","framerate":12,"loop":true},{"name":"pressed","anim":"presstriright","framerate":12,"loop":false},{"name":"confirm","anim":"presstriright","framerate":12,"loop":false}]},"antialias":true,"scale":4.5,"noteSplashImage":"VPT_Love_Notes_Fix","noteSplashScale":0} \ No newline at end of file diff --git a/assets/shared/images/VPT_Love_Notes_Fix.png b/assets/shared/images/VPT_Love_Notes_Fix.png new file mode 100644 index 00000000..15fc0f1c Binary files /dev/null and b/assets/shared/images/VPT_Love_Notes_Fix.png differ diff --git a/assets/shared/images/VPT_Love_Notes_Fix.xml b/assets/shared/images/VPT_Love_Notes_Fix.xml new file mode 100644 index 00000000..a1347400 --- /dev/null +++ b/assets/shared/images/VPT_Love_Notes_Fix.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/web_port_stuff/data/webPortMods.txt b/assets/web_port_stuff/data/webPortMods.txt new file mode 100644 index 00000000..a0ddd856 --- /dev/null +++ b/assets/web_port_stuff/data/webPortMods.txt @@ -0,0 +1,9 @@ +Friday Night Funkin +friday-night-funkin +The best rhythm game ever +FNF Cornflower Week +fnf-cornflower-week +Funny cornflower boi by VMan_2002 +Friday Night Funkbox +funny-nep-mod +Beepbox themed FNF mod by Neptendo \ No newline at end of file diff --git a/bpm gradualy.txt b/bpm gradualy.txt new file mode 100644 index 00000000..b614641e --- /dev/null +++ b/bpm gradualy.txt @@ -0,0 +1,6 @@ +First Section +Last Section +Starting Time +Ending Time +Starting BPM +Ending BPM \ No newline at end of file diff --git a/feature_todo.txt b/feature_todo.txt new file mode 100644 index 00000000..11b9b9a8 --- /dev/null +++ b/feature_todo.txt @@ -0,0 +1,15 @@ +-- feature todo (in no particular order) (feel free to add shit) -- + +note quant color +endless songs +cool chart editor stuff such as "double section" and "mirror section" +time signatures in chart editor +mod browser +multiplayer +make the html build work at some point +flashing lights mod assets + +-- things i havent made yet -- + +-- minor shit +make the GTStrum key in controls menu shaped like a guitar pick \ No newline at end of file diff --git a/source/Achievements.hx b/source/Achievements.hx index 361c1dc1..b36228a8 100644 --- a/source/Achievements.hx +++ b/source/Achievements.hx @@ -1,6 +1,7 @@ package; import ModsMenuState.ModInfo; import flixel.util.FlxSave; +import net.VeGameJolt; class Achievements { //todo: Actual custom achievements will come soon @@ -23,6 +24,7 @@ class Achievements { //"6kBothPlay", //Dunno lol "fridayNight", "calibrateDeath", + "gamejoltLinked", "modFunkboxPlay", "modRegGuitPlay", "modPastTimePlay" @@ -37,6 +39,7 @@ class Achievements { } achievementsChanged = true; achievements.push(name); + VeGameJolt.syncOneAchievement(name); return true; } @@ -62,6 +65,8 @@ class Achievements { return ["That's Epic", "Complete any song with no misses, and you hit only \"Good\" or better. (GFC, aka Good Full Combo)"]; case "anySFC": return ["Perfect Combo", "Complete any song with no misses, and you hit only \"Sick!\". (SFC, aka Sick Full Combo)"]; + case "anyMFC": + return ["Superpower", "Complete any song with no misses, and you hit only \"Marvelous!\". (MFC, aka Marvelous Full Combo)"]; case "anyWeekComplete": return ["Storytold", "Complete any week in Story Mode."]; case "anyWeekFC": @@ -84,6 +89,8 @@ class Achievements { return ["Just Like The Game", "Funk on a Friday (real time)."]; case "calibrateDeath": return checkAchievement("calibrateDeath") ? ["???", "Hidden Achievement"] : ["Out Of Time", "Die during Input Offset Calibrate."]; + case "gamejoltLinked": + return ["Jolt", "Connect your Game Jolt account."]; //hmm should i do this case "modFunkboxPlay": return ["Beepy on a Friday Night", "Complete a Story Mode week from `Friday Night Funkbox`."]; diff --git a/source/AnimationDebug.hx b/source/AnimationDebug.hx index c8f9bce5..b1b8065a 100644 --- a/source/AnimationDebug.hx +++ b/source/AnimationDebug.hx @@ -34,6 +34,7 @@ class AnimationDebug extends MusicBeatState { var healthIcon:HealthIcon; var nameTxtBox:FlxUIInputText; + var modName:String; //why does this error? //var playHint:FlxText = new FlxText(8, 8, 0, 'Use your 4K binds: ${Options.controls.get("4k").map(function(a) {return ControlsSubState.ConvertKey(a[0], true)}).join(",")} to play sing anims\nHold Shift to play miss anims instead'); @@ -70,8 +71,11 @@ class AnimationDebug extends MusicBeatState { originThing.alpha = 0.5; add(originThing); + //get char origin mod + var modNameTmp = CoolUtil.getFileOriginMod("objects/characters/" + daAnim + ".json"); + modName = modNameTmp == null ? "" : modNameTmp; // - char = new Character(xPositionThing, 0, daAnim); + char = new Character(xPositionThing, 0, daAnim, false, modName); char.debugMode = true; add(char); // @@ -108,7 +112,7 @@ class AnimationDebug extends MusicBeatState { FlxG.camera.follow(camFollow); - var animThing = Character.loadCharacterJson(daAnim, null); + var animThing = Character.loadCharacterJson(daAnim, modName); if (animThing != null && animThing.animations != null) { for (anim in animThing.animations) { fileAnims.set(anim.name, anim); @@ -173,8 +177,8 @@ class AnimationDebug extends MusicBeatState { animNoSustain: char.animNoSustain, isGirlfriend: char.isGirlfriend, substitutable: validFile ? substitutable : (char.curCharacter.startsWith("bf_") || char.curCharacter == "bf" || char.curCharacter.startsWith("gf_") || char.curCharacter == "gf"), - singTime: null, - singBeats: null + singTime: char.singTime, + singBeats: char.singBeats }; if (Options.dataStrip) { if (savedChar.substitutable != true) @@ -238,7 +242,7 @@ class AnimationDebug extends MusicBeatState { add(barSprite); add(colorBar); - healthIcon = new HealthIcon(char.healthIcon); + healthIcon = new HealthIcon(char.healthIcon, modName); healthIcon.y = colorBar.y - (healthIcon.height / 2); healthIcon.x = colorBar.x + colorBar.width + 26 - 150; add(healthIcon); diff --git a/source/Character.hx b/source/Character.hx index 518fa55f..2d1b69f9 100644 --- a/source/Character.hx +++ b/source/Character.hx @@ -4,16 +4,9 @@ import CoolUtil; import ThingThatSucks.ErrorReportSubstate; import flixel.FlxG; import flixel.FlxSprite; -import flixel.animation.FlxAnimationController; -import flixel.animation.FlxBaseAnimation; -import flixel.graphics.frames.FlxAtlasFrames; -import flixel.graphics.frames.FlxFramesCollection; -import flixel.graphics.frames.FlxImageFrame; -import flixel.input.keyboard.FlxKeyboard; import flixel.math.FlxPoint; import flixel.util.FlxColor; import flixel.util.FlxSort; -import haxe.Json; import lime.utils.Assets; using StringTools; @@ -168,7 +161,7 @@ class Character extends SpriteVManExtra { //todo: i still haven't unhardcoded these characters (gf, gf-christmas, gf-tankmen, bf-holding-gf, gf-car, gf-pixel, mom-car, monster, monster-christmas, pico-speaker, bf, bf-dead, bf-christmas, bf-car, bf-pixel, bf-pixel-dead, bf-holding-gf-dead, senpai, senpai-angry, spirit, parents-christmas, tankman) switch (curCharacter) { - case "emptyLoad" | "emptyInvisible": + case "emptyLoad" | "emptyInvisible" | "invisibleStandard": //load the minimum required stuff //todo: why doesn't this work hmmmm loadGraphic(null, true); @@ -176,8 +169,14 @@ class Character extends SpriteVManExtra { animation.add("idle", [0]); addOffset("idle", 0, 0, 0); playAnim("idle"); - if (curCharacter == "emptyInvisible") + if (curCharacter != "emptyLoad") visible = false; + if (curCharacter == "invisibleStandard") { + for (thing in ["singLEFT", "singDOWN", "singRIGHT", "singUP"]) { + animation.add(thing, [0]); + animation.add(thing + "miss", [0]); + } + } case 'gf': // GIRLFRIEND CODE AnimationDebug.imageFile = 'characters/GF_assets'; @@ -879,6 +878,8 @@ class Character extends SpriteVManExtra { } if (loadedStuff.singTime != null) { this.singTime = loadedStuff.singTime; + } else { + this.singBeats = -4; } if (loadedStuff.singBeats != null) { this.singBeats = loadedStuff.singBeats; @@ -943,6 +944,7 @@ class Character extends SpriteVManExtra { generateFlipOffsets(); if (!hasMissAnims) { + trace("generating miss anims since the character doesn't have it."); var things = new Array(); for (n in animation.getNameList()) { if (n.startsWith("sing") && !n.endsWith("miss")) @@ -1147,8 +1149,15 @@ class Character extends SpriteVManExtra { playAvailableAnim(["deathLoop" + animation.curAnim.name.substr(10), "deathLoop"]); } + var _animTimeLen:Float = 1; + + public var animTimeLen(get, never):Float; + + public function get_animTimeLen() + return _animTimeLen; + public inline function getSingTime() { - return singTime + (Conductor.crochet * singBeats * 0.001); + return (singTime != -4) ? singTime + (Conductor.crochet * singBeats * 0.001) + 0.01 : _animTimeLen; } public var danced:Bool = false; @@ -1157,7 +1166,7 @@ class Character extends SpriteVManExtra { * FOR GF DANCING SHIT */ public function dance(?anyway:Bool = false, ?force:Bool = false, ?reverse:Bool = false, ?frame:Int = 0) { - if (debugMode || moduloDances == 0 || (animation.curAnim != null && (animation.curAnim.name == 'hairBlow' || (animStartsWith('sing') && !animEndsWith("-loop") && holdTimer >= getSingTime())))) { + if (debugMode || moduloDances <= 0 || (animation.curAnim != null && (animation.curAnim.name == 'hairBlow' || (animStartsWith('sing') && !animEndsWith("-loop") && holdTimer < getSingTime())))) { return; } if (!anyway) { @@ -1198,10 +1207,23 @@ class Character extends SpriteVManExtra { misscolored = true; color = 0x999aff; } + + _animTimeLen = animation.curAnim.frames.length / animation.curAnim.frameRate; } public function set_idleAlt(value:String):String { danceType = hasAnim("danceLeft" + value); return idleAlt = value; } + + public var skipDance(get, set):Bool; + + public function set_skipDance(val:Bool) { + if (val != get_skipDance()) + moduloDances = 0 - moduloDances; + return val; + } + public function get_skipDance() { + return moduloDances <= 0; + } } diff --git a/source/CharacterAnimThing.hx b/source/CharacterAnimThing.hx new file mode 100644 index 00000000..bcb04da1 --- /dev/null +++ b/source/CharacterAnimThing.hx @@ -0,0 +1,6 @@ +import flixel.FlxSprite; +import flixel.group.FlxSpriteGroup; + +class CharacterAnimThing extends FlxTypedSpriteGroup { + +} \ No newline at end of file diff --git a/source/ChartingState.hx b/source/ChartingState.hx index 0e03a4ee..dbbb5691 100644 --- a/source/ChartingState.hx +++ b/source/ChartingState.hx @@ -570,19 +570,29 @@ class ChartingState extends MusicBeatState { //noteTypeSelect.resize(200, 20); noteTypeSelect.selectedLabel = noteTypes[0]; + inline function ensureNoteType(name:String) { + if (!curNoteTypeArr.contains(name)) { + curNoteTypeArr.push(name); + _song.usedNoteTypes = curNoteTypeArr; + } + return curNoteTypeArr.indexOf(name); + } + var allLeftType:FlxUIButton = new FlxUIButton(100, 70, Translation.getTranslation("Set All Type Left", "charteditor"), function() { + var num = ensureNoteType(curNoteType); for (thing in getSectionNotes()) { if (thing[1] < PlayState.curManiaInfo.keys) - thing[3] = curNoteType; + thing[3] = num; } updateGrid(); }); Translation.setUIObjectFont(allLeftType); var allRightType:FlxUIButton = new FlxUIButton(100, 90, Translation.getTranslation("Set All Type Right", "charteditor"), function() { + var num = ensureNoteType(curNoteType); for (thing in getSectionNotes()) { if (thing[1] >= PlayState.curManiaInfo.keys) - thing[3] = curNoteType; + thing[3] = num; } updateGrid(); }); diff --git a/source/ColorblindShader.hx b/source/ColorblindShader.hx index 15b2d635..8126aba5 100644 --- a/source/ColorblindShader.hx +++ b/source/ColorblindShader.hx @@ -2,6 +2,7 @@ import flixel.FlxG; import flixel.FlxSprite; import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; import openfl.display.Shader; +import openfl.filters.ShaderFilter; //original by doggydentures class ColorblindShader extends Shader { @@ -16,6 +17,8 @@ class ColorblindShader extends Shader { ]; public var intensity(default, set):Float; + public var valid:Bool = false; + public static var instanceFilter:Null; public function set_intensity(val:Float) { return intensity = val; @@ -23,8 +26,12 @@ class ColorblindShader extends Shader { public function new(type:String) { super(); - if (!filterList.contains(type)) + if (!filterList.contains(type)) { + instanceFilter = null; return trace("Colorblind type not found: "+type);//you're up to no good? + } + valid = true; + instanceFilter = new ShaderFilter(this); var mat = switch(type) { case "deuteranopia_correct" | "deuteranopia_simulate": "1.0, 0.0, 0.0, diff --git a/source/CoolUtil.hx b/source/CoolUtil.hx index 156a6402..fc4f188e 100644 --- a/source/CoolUtil.hx +++ b/source/CoolUtil.hx @@ -13,7 +13,6 @@ import flixel.math.FlxMath; import flixel.tweens.FlxEase; import flixel.util.FlxColor; import flixel.util.typeLimit.OneOfThree; -import flixel.util.typeLimit.OneOfTwo; import haxe.Json; import lime.utils.Assets; import openfl.display.BitmapData; @@ -634,6 +633,17 @@ class CoolUtil thing.cameras.push(camera); } } + + /** + Get mod that a file originates from. Returns `null` if the file doesn't exist or it's a vanilla file. + **/ + public static function getFileOriginMod(file:String):Null { + for (mod in ModLoad.enabledMods) { + if (FileSystem.exists('mods/${mod}/${file}')) + return mod; + } + return null; + } } class MultiStepResult { diff --git a/source/FreeplayState.hx b/source/FreeplayState.hx index 6f22a55a..83d2c223 100644 --- a/source/FreeplayState.hx +++ b/source/FreeplayState.hx @@ -322,7 +322,7 @@ class FreeplayState extends MusicBeatState { scoreFCText.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, LEFT); Translation.setObjectFont(scoreFCText, "vcr font"); - scoreAccText = new FlxText(FlxG.width, 90, FlxG.width, "99.99%", 32); + scoreAccText = new FlxText(FlxG.width, 90, FlxG.width, "99.999%", 32); scoreAccText.x -= scoreAccText.textField.textWidth + 2; scoreAccText.fieldWidth -= scoreAccText.x; // scoreAccText.autoSize = false; @@ -636,7 +636,7 @@ class FreeplayState extends MusicBeatState { return; } scoreFCText.text = Highscore.getFCFormatted(songId, curDifficulty, true); - scoreAccText.text = HudThing.trimPercent(Highscore.getAcc(songId, curDifficulty, true)); + scoreAccText.text = Std.string(FlxMath.roundDecimal(Highscore.getAcc(songId, curDifficulty, true), 3)); } #end /*if (isCornflower) { diff --git a/source/GameOverSubstate.hx b/source/GameOverSubstate.hx index 112c59d2..185fd4ba 100644 --- a/source/GameOverSubstate.hx +++ b/source/GameOverSubstate.hx @@ -130,7 +130,7 @@ class GameOverSubstate extends MusicBeatSubstate { if (!isEnding) { Scripting.runOnScripts("onAccept", ["GameOverSubstate", null, null]); isEnding = true; - bf.playAvailableAnim(['deathConfirm' + (bf.animStartsWith("deathLoop") ? bf.animation.curAnim.name.substr(9) : bf.animation.name.substr(10)), 'deathConfirm'], true); + bf.playAvailableAnim(['deathConfirm' + bf.animation.curAnim.name.substr(bf.animStartsWith("deathLoop") ? 9 : 10), 'deathConfirm'], true); FlxG.sound.music.stop(); FlxG.sound.play(Paths.music(gameOverMusicEndName)); new FlxTimer().start(0.7, function(tmr:FlxTimer) { diff --git a/source/Highscore.hx b/source/Highscore.hx index 7aabe7de..f6e2d21a 100644 --- a/source/Highscore.hx +++ b/source/Highscore.hx @@ -45,6 +45,10 @@ class Highscore var saveAcc = setAcc(daSong, PlayState.instance.songScore / (((PlayState.instance.songHits + PlayState.instance.songMisses) * 350) + PlayState.instance.possibleMoreScore)); return saveScore || saveFC || saveAcc; //return true if you got a high score } + + public static function accuracyCalc(state:PlayState) { + return state.songScore / (((state.songHits + state.songMisses) * 350) + state.possibleMoreScore); + } public static function getPlayStateFC(the:PlayState) { if (the.songMisses >= 10) diff --git a/source/Main.hx b/source/Main.hx index 212cc67c..e415983e 100644 --- a/source/Main.hx +++ b/source/Main.hx @@ -7,6 +7,8 @@ import flixel.FlxGame; import flixel.FlxState; import haxe.CallStack; import haxe.Exception; +import net.VeAPIKeys; +import net.VeGameJolt.FlxGameJolt; import openfl.Assets; import openfl.Lib; import openfl.display.FPS; @@ -16,6 +18,7 @@ import openfl.events.UncaughtErrorEvent; import render3d.Render3D.VeScene3D; import sys.io.File; import sys.io.Process; +import wackierstuff.VeFlxCamera; #if html5 import js.Browser; #end @@ -81,6 +84,9 @@ class Main extends Sprite { Achievements.LoadOptions(); Weeks.LoadOptions(); PlayState.curManiaInfo = ManiaInfo.GetManiaInfo("4k"); + new ColorblindShader(Options.colorblind); + FlxG.camera = new VeFlxCamera(); + @:privateAccess FlxGameJolt.init(Std.parseInt(VeAPIKeys.get("gj_gameid")), VeAPIKeys.get("gj_secret")); setupGame(); } diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx index ed5bc974..503e2071 100644 --- a/source/MainMenuState.hx +++ b/source/MainMenuState.hx @@ -18,6 +18,9 @@ import flixel.tweens.FlxTween; import flixel.util.FlxColor; // import io.newgrounds.NG; import lime.app.Application; +import net.VeAPIKeys; +import net.VeGameJolt.FlxGameJolt; +import net.VeGameJolt; using StringTools; #if desktop @@ -144,7 +147,7 @@ class MainMenuState extends MusicBeatState { add(vmanEngineThing); // NG.core.calls.event.logEvent('swag').send(); - if (focusOn != null) + if (focusOn != null && optionShit.contains(focusOn)) curSelected = optionShit.indexOf(focusOn); changeItem(0, false); FlxG.camera.snapToTarget(); @@ -225,6 +228,18 @@ class MainMenuState extends MusicBeatState { hillarious = new MultiWindow(1, true); } #end*/ + if (FlxG.keys.justPressed.G) { + var gamejoltUser = CoolUtil.coolTextFile("data/gamejoltLogin"); + if (gamejoltUser.length > 1) + FlxGameJolt.authUser(gamejoltUser[0], gamejoltUser[1], function(success:Bool) { + trace(success ? "Gamejolt login success" : "Gamejolt login fail"); + if (success) { + VeGameJolt.loggedIn = true; + Achievements.giveAchievement("gamejoltLinked"); + VeGameJolt.syncAchievements(); + } + }); + } if (FlxG.keys.justPressed.SEVEN) { FlxG.switchState(new OptionsMenu(new ToolsMenuSubState())); diff --git a/source/Modchart.hx b/source/Modchart.hx new file mode 100644 index 00000000..705ff049 --- /dev/null +++ b/source/Modchart.hx @@ -0,0 +1,167 @@ +package; + +import flixel.FlxG; +import flixel.FlxSprite; +import flixel.graphics.frames.FlxAtlasFrames; +import flixel.util.FlxSort; +import flixel.util.FlxTimer; +import flixel.util.typeLimit.OneOfThree; + +using StringTools; + +typedef ModchartEvent = { + time:Float, + e:Dynamic, + t:Int, + n:Array, + l:Array +} + +typedef ModchartMathEvent = { + x:String, + y:String, + xs:String, + ys:String, + r:String, + length:String +} + +typedef ModchartTweenEvent = { + x:Null, + y:Null, + xs:Null, + ys:Null, + r:Null, + length:Float, + ease:String +} + +typedef ModchartEffectEvent = { + type:String, + length:Float, + ease:String +} + +typedef ModchartSetEvent = { + x:Null, + y:Null, + s:Null, + xs:Null, + ys:Null, + r:Null +} + +typedef ModchartRelSetEvent = { + x:Null, + y:Null, + s:Null, + xs:Null, + ys:Null, + r:Null +} + +class Modchart { + var runEffects:Bool = false; + var effectStrength:Map = new Map(); + public var modchartEvents:Array; + var myState:PlayState; + public var nextNum:Int = 0; + public var nextTime:Float = -1; + + public function new(daState:PlayState) { + myState = daState; + } + + public function sort() { + modchartEvents.sort(function(a, b) { + return FlxSort.byValues(FlxSort.ASCENDING, a.time, b.time); + }); + } + + public function update() { + while (nextTime <= Conductor.songPosition) { + runEvent(modchartEvents[nextNum]); + nextNum += 1; + nextTime = modchartEvents[nextNum].time; + } + if (runEffects) { + + } + } + + //I dont know whati m doing + //this is likely a bad way of doing this + + public function runEvent(ev:Dynamic) { + switch(ev.t) { + case 0: //Math event + + case 1: //Tween event + + case 2: //Effect event + + case 3: //Set event + var evdat:ModchartSetEvent = ev.e; + doStrumStuff(ev, function(ev, l, n, strumnote) { + if (evdat.x != null) { + strumnote.x = evdat.x; + } + if (evdat.y != null) { + strumnote.y = evdat.y; + } + if (evdat.s != null) { + strumnote.scale.set(evdat.s, evdat.s); + } else { + if (evdat.xs != null) { + strumnote.scale.x = evdat.xs; + } + if (evdat.ys != null) { + strumnote.scale.y = evdat.ys; + } + } + if (evdat.r != null) { + strumnote.angle = evdat.r; + } + }); + case 4: //Set relative event + var evdat:ModchartRelSetEvent = ev.e; + doStrumStuff(ev, function(ev, l, n, strumnote) { + if (evdat.x != null) { + strumnote.x += evdat.x; + } + if (evdat.y != null) { + strumnote.y += evdat.y; + } + if (evdat.s != null) { + strumnote.scale.x += evdat.s; + strumnote.scale.y += evdat.s; + } + if (evdat.xs != null) { + strumnote.scale.x += evdat.xs; + } + if (evdat.ys != null) { + strumnote.scale.y += evdat.ys; + } + if (evdat.r != null) { + strumnote.angle += evdat.r; + } + }); + } + } + + inline function doStrumStuff(ev:Dynamic, func:(Dynamic, Int, Int, StrumNote)->Void) { + var num = 0; + var line = 0; + while(line < myState.strumLines.length) { + if (ev.l[line]) { + while(num < myState.strumLines.members[line].length) { + if (ev.n[num]) { + func(ev, line, num, myState.strumLines.members[line].members[num]); + } + num++; + } + } + line++; + } + } +} diff --git a/source/ModchartEditorState.hx b/source/ModchartEditorState.hx new file mode 100644 index 00000000..9486032b --- /dev/null +++ b/source/ModchartEditorState.hx @@ -0,0 +1,38 @@ +package; + +import flixel.FlxG; +import flixel.FlxSprite; +import flixel.graphics.frames.FlxAtlasFrames; +import flixel.util.FlxTimer; + +using StringTools; + +class ModchartEditorState extends PlayState +{ + public var unspawnNotes2:Array; + + public function new() { + super(); + } + + override function update(elapsed:Float) { + super.update(elapsed); + } + + override function generateSong(thing:String) { + super.generateSong(thing); + unspawnNotes2 = unspawnNotes.copy(); //keep notes stored so you can reverse time + } + + override function goodNoteHit(note:Note) { + super.goodNoteHit(note); + } + + override function onSpawnNote(daNote:Note) { + daNote.mustPress = false; + } + + override function endSong() { + super.endSong(); + } +} diff --git a/source/MusicBeatSubstate.hx b/source/MusicBeatSubstate.hx index a630218f..1a47ed3e 100644 --- a/source/MusicBeatSubstate.hx +++ b/source/MusicBeatSubstate.hx @@ -65,4 +65,19 @@ class MusicBeatSubstate extends FlxSubState //do literally nothing dumbass Scripting.runOnScripts("beatHit", [curBeat]); } + + /** + `top`: Open this substate on top of the topmost current substate, otherwise open it on `FlxG.state` which may not work if a substate is already active + **/ + public function openThis(?top:Bool = false) { + if (top && subState != null) { + var a = subState; + while (a.subState != null) + a = a.subState; + a.openSubState(this); + } else { + FlxG.state.openSubState(this); + } + return this; + } } diff --git a/source/Note.hx b/source/Note.hx index c02e1f64..f204f712 100644 --- a/source/Note.hx +++ b/source/Note.hx @@ -42,6 +42,9 @@ class SwagNoteSkin { public var variations:Map; public static function loadNoteSkin(name:String, modName:String) { + //todo: THIS IS A TEMPORARY HARDCODED FIX LOL + if (name == "vpt_love_notes" && modName == "vmans_past_time") + name = "vpt_love_notes_fixed"; if (Note.loadedNoteSkins.exists('${modName}:${name}')) { return Note.loadedNoteSkins.get('${modName}:${name}'); } @@ -192,6 +195,8 @@ class SwagUIStyle { uiStyle.countdownScale = uiStyleFile.countdownScale != null ? uiStyleFile.countdownScale : 1.0; if (uiStyleFile.ratings == null) uiStyle.ratings = ["sick" => uiStyleFile.sick, "good" => uiStyleFile.good, "bad" => uiStyleFile.bad, "shit" => uiStyleFile.shit, "sick-cool" => (uiStyleFile.sickcool == null ? uiStyleFile.sick : uiStyleFile.sickcool)]; + else + uiStyle.ratings = uiStyleFile.ratings; if (uiStyle.ratings.get("sick") == null) { uiStyle.ratings.set("sick", "normal/sick"); if (uiStyle.ratings.get("sick-cool") == null) diff --git a/source/Options.hx b/source/Options.hx index 7b87b077..70f87f7c 100644 --- a/source/Options.hx +++ b/source/Options.hx @@ -1,8 +1,10 @@ package; +import flixel.FlxG; import flixel.input.keyboard.FlxKey; import flixel.util.FlxSave; import openfl.Assets; import openfl.utils.AssetType; +import wackierstuff.VeFlxCamera; class Options { public static var saved:Options; @@ -102,6 +104,7 @@ class Options { public var noteSplash:Bool = true; public var hitsound:String = ""; public var hitsound_overtap:String = ""; + public static var colorblind:String = ""; //PlayState changeables public var playstate_opponentmode:Bool = false; @@ -306,4 +309,9 @@ class Options { static function get_selfAware():Bool { return _selfAware; } + + public function updateColorblind() { + new ColorblindShader(colorblind); + cast(FlxG.camera, VeFlxCamera).ve_filters.updateColorblind(); + } } \ No newline at end of file diff --git a/source/OptionsSubState.hx b/source/OptionsSubState.hx index 29aacf11..1acdfe73 100644 --- a/source/OptionsSubState.hx +++ b/source/OptionsSubState.hx @@ -48,8 +48,9 @@ class OptionsSubState extends OptionsSubStateBasic "Gameplay Changes", "Exit Without Saving", #if debug - "Options Warning Test" + "Options Warning Test", #end + "GameJolt Login" ]; } @@ -131,6 +132,10 @@ class OptionsSubState extends OptionsSubStateBasic return ["Modify hud meters"]; case "enable notesplash": return ["Enable a splashy effect when you hit \"Sick\" rating."]; + case "colorblind filter": + return ["Color filter that aids colorblind users or simulates colorblindness."]; + case "gamejolt login": + return ["Log in to your Game Jolt account."]; } return ["Unknown option.", name, 'unknownOption']; } diff --git a/source/PlayState.hx b/source/PlayState.hx index dae23f7e..6d31a2ab 100644 --- a/source/PlayState.hx +++ b/source/PlayState.hx @@ -51,6 +51,7 @@ import flixel.util.typeLimit.OneOfTwo; import haxe.Json; import haxe.ds.ArraySort; import lime.utils.Assets; +import net.VeGameJolt; import openfl.display.BlendMode; import openfl.display.GraphicsEndFill; import openfl.display.StageQuality; @@ -159,6 +160,7 @@ class PlayState extends MusicBeatState { //public var strumLineNotes = new Array(); public var strumLines:FlxTypedGroup; + public var swappedStrumline:Bool = false; public var playerStrums = new StrumLine(); public var opponentStrums = new StrumLine(); //Not the same as playerStrums and opponentStrums respectively (except when opponent mode is disabled) @@ -403,6 +405,8 @@ class PlayState extends MusicBeatState { Options.instance.playstate_opponentmode = false; if (SONG.actions.contains("noGuitarMode")) Options.instance.playstate_guitar = false; + if (SONG.actions.contains("strumlineSwap")) + swappedStrumline = !swappedStrumline; if (allowGameplayChanges && Options.instance.playstate_bothside) { var newKeys = curManiaInfo.keys * 2; var newMania = ManiaInfo.GetManiaInfo(newKeys + "k"); @@ -776,6 +780,9 @@ class PlayState extends MusicBeatState { gfVersion = 'gf-pixel'; } } + + var betweenCharArr = new Array(); + var baseCharArr = new Array(); boyfriend = new Character(770, 100, SONG.player1, currentStage.charFacing.contains(0), modName, true, true); dad = new Character(100, 100, SONG.player2, currentStage.charFacing.contains(1), modName); @@ -793,6 +800,20 @@ class PlayState extends MusicBeatState { gf.applyPositionOffset(); + (currentStage.charBetween.contains(1) ? betweenCharArr : baseCharArr).push(dad); + (currentStage.charBetween.contains(0) ? betweenCharArr : baseCharArr).push(boyfriend); + (currentStage.charBetween.contains(2) ? betweenCharArr : baseCharArr).push(gf); + + if (SONG.moreCharacters != null && SONG.moreCharacters.length != 0) { + trace('Adding ${SONG.moreCharacters.length} extra characters'); + var bullShit:Int = 3; + for (i in SONG.moreCharacters) { + var newChar = new Character(0, 0, i, currentStage.charFacing.contains(bullShit), modName); + (currentStage.charBetween.contains(bullShit) ? betweenCharArr : baseCharArr).push(newChar); + bullShit++; + } + } + var camPos:FlxPoint = new FlxPoint(dad.getGraphicMidpoint().x, dad.getGraphicMidpoint().y); switch (SONG.player2) { @@ -856,7 +877,13 @@ class PlayState extends MusicBeatState { add(evilTrail); } - add(gf); + inline function addTheGuys(arr:Array) { + while (arr.length != 0) { + add(arr.shift()); + } + } + + addTheGuys(betweenCharArr); // Shitty layering but whatev it works LOL @@ -866,17 +893,7 @@ class PlayState extends MusicBeatState { else if (curStage == 'limo') add(limo); - add(dad); - add(boyfriend); - - if (SONG.moreCharacters != null && SONG.moreCharacters.length != 0) { - trace('Adding ${SONG.moreCharacters.length} extra characters'); - var bullShit:Int = 3; - for (i in SONG.moreCharacters) { - add(new Character(0, 0, i, currentStage.charFacing.contains(bullShit), modName)); //these are automatically put into Character.activeArray, so it's ok that they're not assigned to variables here - bullShit++; - } - } + addTheGuys(baseCharArr); if (customStageCharPos != null) { for (i in 0...Character.activeArray.length) { @@ -1582,15 +1599,17 @@ class PlayState extends MusicBeatState { public function generateStaticArrows(player:Int) { var xPos:Float = 0; var scale:Float = maniaScale; + var playerSide = FlxG.width * (swappedStrumline ? 0.25 : 0.75); + var opponentSide = FlxG.width * (swappedStrumline ? 0.75 : 0.25); if (player == 1) { - xPos = isMiddlescroll ? FlxG.width / 2 : FlxG.width * 0.75; + xPos = isMiddlescroll ? FlxG.width * 0.5 : playerSide; } else { - xPos = isMiddlescroll || SONG.actions.contains("hideOpponentNotes") ? FlxG.width * 8 : FlxG.width * 0.25; + xPos = isMiddlescroll || SONG.actions.contains("hideOpponentNotes") ? FlxG.width * 8 : opponentSide; if (SONG.moreStrumLines > 0 && !isMiddlescroll) { if (!SONG.actions.contains("dontResizeStrumlines")) scale /= SONG.moreStrumLines + 1; var myNum = player == 0 ? 0.5 : player - 0.5; - xPos = (myNum * FlxG.width / 2) / (SONG.moreStrumLines + 1); + xPos = (myNum * FlxG.width * 0.5) / (SONG.moreStrumLines + 1); } } var thing:StrumLine = new StrumLine(curManiaInfo, xPos, strumLine.y, scale); @@ -2182,6 +2201,7 @@ class PlayState extends MusicBeatState { if (SONG.validScore && !(Options.instance.botplay || usedBotplay)) { #if !switch Highscore.saveScore(SONG.song, songScore, storyDifficulty); + VeGameJolt.submitScore(); #end } @@ -2218,6 +2238,9 @@ class PlayState extends MusicBeatState { Achievements.giveAchievement("anyGFC"); if (goods == 0) { Achievements.giveAchievement("anySFC"); + if (songMFC) { + Achievements.giveAchievement("anyMFC"); + } } } } diff --git a/source/Scripting.hx b/source/Scripting.hx index 99402d24..6bc5a88c 100644 --- a/source/Scripting.hx +++ b/source/Scripting.hx @@ -8,7 +8,6 @@ import CoolUtil.ScriptHelper; import Note.SwagNoteSkin; import Note.SwagNoteType; import Note.SwagUIStyle; -import flixel.FlxCamera; import flixel.FlxG; import flixel.FlxSprite; import flixel.FlxStrip; @@ -32,7 +31,6 @@ import flixel.util.FlxColor; import flixel.util.FlxTimer; import hscript.Interp; import hscript.Parser; -import openfl.system.System; import render3d.Render3D.VeFlxSprite3D; import render3d.Render3D.VeModel3D; import render3d.Render3D.VeObject3D; @@ -40,6 +38,7 @@ import render3d.Render3D.VeScene3D; import sys.FileSystem; import sys.io.File; import wackierstuff.FlxBackdropFix; +import wackierstuff.VeFlxCamera; using StringTools; @@ -98,7 +97,7 @@ class Scripting { "FlxTimer" => FlxTimer, "FlxTween" => FlxTween, "FlxEase" => FlxEase, - "FlxCamera" => FlxCamera, + "FlxCamera" => VeFlxCamera, //Modified for colorblind filter usage "FlxPoint" => FlxPoint, "FlxSound" => FlxSound, "FlxAxes" => FlxAxes, @@ -125,8 +124,11 @@ class Scripting { "VeFlxSprite3D" => VeFlxSprite3D, //retools - "MyFlxColor" => MyFlxColor//, //why cant i put FlxColor here ????????? wtf!!!!!!!!! + "MyFlxColor" => MyFlxColor,//, //why cant i put FlxColor here ????????? wtf!!!!!!!!! //"MySystem" => MySystem //im worried about security lol + + //what + "ValueAccessor" => Accessor ]; public static var gamePlatform(default, never) = @@ -585,4 +587,22 @@ class MyFlxColor { static function get_totalMemoryNumber() { return System.totalMemoryNumber; } -}*/ \ No newline at end of file +}*/ + +class Accessor { + var obj:Dynamic; + var prop:String; + /** + This class is a shortcut for `Reflect.getProperty` and `Reflect.setProperty`, using `this.get` and `this.set` respectively + **/ + public function new(obj:Dynamic, property:String) { + this.obj = obj; + prop = property; + } + + public function get() + return Reflect.getProperty(obj, prop); + + public function set(val:Dynamic) + return Reflect.setProperty(obj, prop, val); +} \ No newline at end of file diff --git a/source/ScriptingCustomState.hx b/source/ScriptingCustomState.hx index 5f0d5836..e8db88bc 100644 --- a/source/ScriptingCustomState.hx +++ b/source/ScriptingCustomState.hx @@ -1,16 +1,6 @@ package; -import Translation; import flixel.FlxG; -import flixel.FlxSprite; -import flixel.FlxSubState; -import flixel.group.FlxGroup.FlxTypedGroup; -import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup; -import flixel.math.FlxMath; -import flixel.text.FlxText; -import flixel.tweens.FlxEase; -import flixel.tweens.FlxTween; -import flixel.util.FlxColor; class ScriptingCustomState extends MusicBeatState { public static var instance:ScriptingCustomState; @@ -36,9 +26,8 @@ class ScriptingCustomState extends MusicBeatState { var script = new Scripting(path, modName, "ScriptingCustomState", function(thing:Bool) { NoSongsState.doThing("story mode", thing ? "customstate error" : "customstate", '${modName}:${path}'); }); - if (script.interp == null) { + if (script.interp == null) return; - } super.update(FlxG.elapsed); script.interp.variables.set("vmanCustomStateInstance", this); } diff --git a/source/ScriptingCustomSubstate.hx b/source/ScriptingCustomSubstate.hx new file mode 100644 index 00000000..98c6c0e8 --- /dev/null +++ b/source/ScriptingCustomSubstate.hx @@ -0,0 +1,51 @@ +package; + +import flixel.FlxG; + +class ScriptingCustomSubstate extends MusicBeatSubstate { + public static var instance:ScriptingCustomSubstate; + public var id:String; + public var modName:String; + public var path:String; + public var init:Bool = false; + + public static function cat(name:String, modName:String) { + return new ScriptingCustomSubstate('scripts/${modName}/${name}', modName); + } + + public function new(path:String, modName:String) { + super(); + id = '${modName}:${path}'; + this.modName = modName; + this.path = path; + instance = this; + } + + public override function create() { + super.create(); + var script = new Scripting(path, modName, "ScriptingCustomSubstate", function(thing:Bool) { + NoSongsState.doThing("story mode", thing ? "customstate error" : "customstate", '${modName}:${path}'); + }); + if (script.interp == null) + return; + super.update(FlxG.elapsed); + script.interp.variables.set("vmanCustomSubstateInstance", this); + } + + inline function thing(name:String, arg:Array) { + Scripting.runOnScripts(name, arg); + } + + public override function update(elapsed:Float) { + super.update(elapsed); + if (!init) { + init = true; + thing("substatePostInit", ["ScriptingCustomSubstate", id, this]); //Moving this should fix a bug where stuff can't be added in statePostInit + } + thing("update", [elapsed]); + if (controls.ACCEPT) + thing("onAccept", ["ScriptingCustomSubstate", null, null]); + if (controls.BACK) + thing("onBack", ["ScriptingCustomSubstate", null, null]); + } +} \ No newline at end of file diff --git a/source/StoryMenuState.hx b/source/StoryMenuState.hx index 31fbf6fd..1f968242 100644 --- a/source/StoryMenuState.hx +++ b/source/StoryMenuState.hx @@ -137,6 +137,8 @@ class StoryMenuState extends MusicBeatState var lock:FlxSprite = new FlxSprite(weekThing.width + 10 + weekThing.x); lock.frames = ui_tex; lock.animation.addByPrefix('lock', 'lock'); + lock.animation.addByPrefix('white', 'white lock'); + lock.animation.addByPrefix('outline', 'white outlined lock'); lock.animation.play('lock'); lock.ID = i; lock.antialiasing = true; diff --git a/source/ToolsMenuSubState.hx b/source/ToolsMenuSubState.hx index 66426224..a7947a5f 100644 --- a/source/ToolsMenuSubState.hx +++ b/source/ToolsMenuSubState.hx @@ -40,7 +40,8 @@ class ToolsMenuSubState extends OptionsSubStateBasic //"Noteskin Creator", "Clone Hero Import", "Unload Scripts", - "Documentation" + "Documentation", + "Discord Server" ]; } @@ -114,6 +115,8 @@ class ToolsMenuSubState extends OptionsSubStateBasic } } return ["Unload all currently loaded scripts.", list, "unknownOption"]; + case "discord server": + return ["A Discord Server, for VMan Engine discussion and probably more"]; } return ["Unknown option.", '', 'unknownOption']; } @@ -153,6 +156,8 @@ class ToolsMenuSubState extends OptionsSubStateBasic case "unload scripts": Scripting.clearScripts(); return true; + case "discord server": + FlxG.openURL("https://discord.gg/aYkugcADnd"); } return false; } diff --git a/source/net/GameJoltLoginState.hx b/source/net/GameJoltLoginState.hx new file mode 100644 index 00000000..c625db64 --- /dev/null +++ b/source/net/GameJoltLoginState.hx @@ -0,0 +1,2 @@ +package net; + diff --git a/source/net/VeAPIKeysPlaceholder.hx b/source/net/VeAPIKeysPlaceholder.hx new file mode 100644 index 00000000..9d6041f8 --- /dev/null +++ b/source/net/VeAPIKeysPlaceholder.hx @@ -0,0 +1,15 @@ +package net; + +/** + this version of the file is for public source code. + + to use this, rename it to "VeAPIKeys.hx" +**/ + +class VeAPIKeys { + public static final valid:Bool = false; + + static function get(name:String):Null { + return null; + } +} \ No newline at end of file diff --git a/source/net/VeGameJolt.hx b/source/net/VeGameJolt.hx new file mode 100644 index 00000000..c65ebe30 --- /dev/null +++ b/source/net/VeGameJolt.hx @@ -0,0 +1,59 @@ +package net; + +import flixel.math.FlxMath; +import sys.thread.Thread; + +using StringTools; + +typedef FlxGameJolt = flixel.addons.api.FlxGameJolt; //dont mess with this!!!!!! + +class VeGameJolt { + public static var loggedIn:Bool = false; + + static inline function canRun() { + return VeAPIKeys.valid && loggedIn; + } + + public static function submitScore() { + if (!canRun()) + return; + var song = Highscore.formatSong(PlayState.modName + ":" + PlayState.SONG.song + CoolUtil.difficultyPostfixString()) + Highscore.getModeString(false, true); + @:privateAccess var scoreboard = Std.parseInt(VeAPIKeys.get('score:' + song)); + if (scoreboard == null) { + trace("no gamejolt scoreboard for "+song); + return; + } + trace("Uploading gamejolt score for "+song); + var score = '${PlayState.instance.songScore} (${FlxMath.roundDecimal(Highscore.accuracyCalc(PlayState.instance) * 100, 3)}% / ${Highscore.getPlayStateFC(PlayState.instance)})'; + var scoreSort = CoolUtil.clamp(Highscore.accuracyCalc(PlayState.instance) * 100, 0, 200) + (Highscore.getPlayStateFCStore(PlayState.instance) * 1000); + var extras:String = [Std.string(PlayState.instance.songMisses), Std.string(PlayState.instance.songHits), Std.string(PlayState.instance.songMisses - PlayState.instance.songHittableMisses), Std.string(Highscore.getPlayStateFCStore(PlayState.instance))].join(","); + FlxGameJolt.addScore(score, scoreSort, scoreboard, false, null, extras, function(result:Map) { + /*if (result["success"] == true) + trace("Score submitted successfully") + else + trace("Score submit fail: "+Std.string(result["message"]))*/ + trace("Attempted to submit score"); + }); + } + + public static function syncAchievements() { + if (!canRun()) + return; + Thread.create(() -> { + for (thing in Achievements.achievements) { + if (syncOneAchievement(thing)) + Sys.sleep(0.2); + } + }); + } + + public static function syncOneAchievement(name:String) { + if (!Achievements.achievements.contains(name) || !canRun()) + return false; + @:privateAccess var id = VeAPIKeys.get("achievement:"+name); + if (id == null) + return false; + FlxGameJolt.addTrophy(Std.parseInt(id)); + return true; + } +} \ No newline at end of file diff --git a/source/wackierstuff/VeFlxCamera.hx b/source/wackierstuff/VeFlxCamera.hx new file mode 100644 index 00000000..2f01de83 --- /dev/null +++ b/source/wackierstuff/VeFlxCamera.hx @@ -0,0 +1,44 @@ +package wackierstuff; + +import flixel.FlxCamera; +import openfl.filters.BitmapFilter; +import openfl.filters.ShaderFilter; + +class VeFlxCameraFilters { + public var parent:VeFlxCamera; + + public function new(parent:VeFlxCamera) { + this.parent = parent; + updateColorblind(); + } + + public function updateColorblind() { + if (filterArr.length != 0) { + var topFilter = filterArr[filterArr.length - 1]; + if (Std.isOfType(topFilter, ShaderFilter) && Std.isOfType(cast(topFilter, ShaderFilter).shader, ColorblindShader)) //this if statement is a bit weird + filterArr.pop(); + } + if (Options.colorblind == "") + return; + filterArr.push(ColorblindShader.instanceFilter); + } + + public var filterArr(get, set):Array; + + function set_filterArr(value:Array):Array { + @:privateAccess return parent._filters = value; + } + + function get_filterArr():Array { + @:privateAccess return parent._filters == null ? new Array() : parent._filters; + } +} + +class VeFlxCamera extends FlxCamera { + public var ve_filters:VeFlxCameraFilters; + + public function new(?x:Int = 0, ?y:Int = 0, ?width:Int = 0, ?height:Int = 0, ?zoom:Float = 0) { + super(x, y, width, height, zoom); + ve_filters = new VeFlxCameraFilters(this); + } +} \ No newline at end of file diff --git a/version/vman_engine_changelog_upcoming.txt b/version/vman_engine_changelog_upcoming.txt index 9998ca55..11f2b7ce 100644 --- a/version/vman_engine_changelog_upcoming.txt +++ b/version/vman_engine_changelog_upcoming.txt @@ -1,8 +1,11 @@ -I didn't actually update the doc i forgor im sorry, +I didn't actually update the doc i forgor im sorry, i also didnt do it again this time Added Marvelous rating (technically.) Added "badHit" and "shouldJudge" values to note types Started adding away3d (i don't think it's ready for use tho.) Some new scripting callbacks Work on the Dialogue system -Fixed positioning of notes in piano mania \ No newline at end of file +Fixed positioning of notes in piano mania +Added GameJolt integration (currently in testing) +Temporary hardcoded fix for Love-Extra^Both crash in The Past Time (i shouldn't be doing this) +Put discord link in tools menu (7 on main menu) \ No newline at end of file