Error in Character.hx

Why is this?
This commit is contained in:
Nennneko5787 2023-03-04 10:27:19 +09:00
parent 3420b8d00a
commit 8c028d6bbe
24 changed files with 1458 additions and 248 deletions

View File

@ -61,6 +61,8 @@
<library name="week6" preload="true" />
<library name="week7" preload="true" />
<library name="weeks" preload="true" />
<library name="scripts" preload="true" />
<library name="shaders" preload="true" />
</section>
<section if="NO_PRELOAD_ALL">
@ -75,6 +77,8 @@
<library name="week6" preload="false" />
<library name="week7" preload="false" />
<library name="weeks" preload="false" />
<library name="scripts" preload="false" />
<library name="shaders" preload="false" />
</section>
<assets path="assets/songs" library="songs" exclude="*.fla|*.ogg" if="web"/>
@ -99,10 +103,12 @@
<assets path="assets/week7" library="week7" exclude="*.fla|*.mp3" unless="web"/>
<assets path="assets/weeks" library="weeks" exclude="*.fla|*.ogg" if="web"/>
<assets path="assets/weeks" library="weeks" exclude="*.fla|*.mp3" unless="web"/>
<assets path='example_mods' rename='mods' embed='false' if="desktop"/>
<assets path="assets/scripts" library="scripts" exclude="*.fla|*.ogg" if="web"/>
<assets path="assets/scripts" library="scripts" exclude="*.fla|*.mp3" unless="web"/>
<assets path="assets/shaders" library="shaders" exclude="*.fla|*.ogg" if="web"/>
<assets path="assets/shaders" library="shaders" exclude="*.fla|*.mp3" unless="web"/>
<!-- template path="example_mods" rename="mods" /> -->
<template path="example_mods" rename="mods" />
<assets path='art/readme.txt' rename='do NOT readme.txt' />
<!-- <template path='mods' /> -->
@ -126,12 +132,12 @@
<!--In case you want to use the ui package-->
<haxelib name="flixel-ui" />
<!--haxelib name="newgrounds" unless="switch"/> -->
<haxelib name="newgrounds" unless="switch"/>
<haxelib name="faxe" if='switch'/>
<haxelib name="polymod" if="desktop"/>
<haxelib name="newgrounds"/>
<haxelib name="polymod" if="desktop || mobile"/>
<haxelib name="hxcpp-debug-server" if="desktop debug"/>
<haxelib name="hxCodec" if="desktop || android" />
<haxelib name="hxCodec" if="desktop || mobile" />
<haxelib name="linc_luajit" if="desktop || mobile" />
<!-- <haxelib name="flixel-animate" /> -->
<!-- <haxelib name="spinehaxe" /> -->
@ -139,7 +145,6 @@
<haxelib name="discord_rpc" if="desktop"/> <!-- foesn't work with neko -->
<haxelib name="hxcpp-debug-server" if="desktop"/>
<!-- <haxelib name="markdown" /> -->
<!-- <haxelib name="HtmlParser" /> -->

View File

@ -42,9 +42,10 @@ Run build-Itch-WINDOWS.bat in /art/ and build.
# Credits
## Friday Night Funkin': nekoEngine2
* nennneko5787 - Programmer
* ShadowMario - The StrumNote.hx code I stole and modified from PsychEngine
* k.net(brightfyre) - Window focus & unfocus source code I stole from Indie Cross
* Leather128 - Part of the 5K+ support code stolen from LeatherEngine and part of the Mod Menu code
* ShadowMario - StrumNote.hx code, Lua code and shader code that I stole and modified from [PsychEngine](https://github.com/ShadowMario/FNF-PsychEngine).
* k.net(brightfyre) - Window focus & unfocus source code I stole from [Indie Cross](https://github.com/brightfyregit/Indie-Cross-Public)
* Leather128 - Part of the 5K+ support code stolen from [LeatherEngine](https://github.com/Leather128/LeatherEngine) and part of the Mod Menu code
* tposejank - Part of the 5K+ support code stolen from [Psych Engine With Extra Keys](https://gamebanana.com/mods/333373)
## Funkin
* ninjamuffin99 - Programmer
* PhantomArcade3K and Evilsk8r - Art

View File

@ -0,0 +1,8 @@
tutorial
week1
week2
week3
week4
week5
week6
week7

View File

@ -65,9 +65,8 @@ class ChartingState extends MusicBeatState
var curRenderedSustains:FlxTypedGroup<FlxSprite>;
var gridBG:FlxSprite;
var gridBlackLine:FlxSprite;
public static var _song:SwagSong;
var _song:SwagSong;
var typingShit:FlxInputText;
/*
@ -82,8 +81,6 @@ class ChartingState extends MusicBeatState
var leftIcon:HealthIcon;
var rightIcon:HealthIcon;
var diff:Int = 1;
override function create()
{
curSection = lastSection;
@ -105,7 +102,7 @@ class ChartingState extends MusicBeatState
leftIcon.setPosition(0, -100);
rightIcon.setPosition(gridBG.width / 2, -100);
gridBlackLine = new FlxSprite(gridBG.x + gridBG.width / 2).makeGraphic(2, Std.int(gridBG.height), FlxColor.BLACK);
var gridBlackLine:FlxSprite = new FlxSprite(gridBG.x + gridBG.width / 2).makeGraphic(2, Std.int(gridBG.height), FlxColor.BLACK);
add(gridBlackLine);
curRenderedNotes = new FlxTypedGroup<Note>();
@ -123,9 +120,7 @@ class ChartingState extends MusicBeatState
player1: 'bf',
player2: 'dad',
speed: 1,
validScore: false,
p1KeyCount: 4,
p2KeyCount: 4
validScore: false
};
}
@ -163,8 +158,8 @@ class ChartingState extends MusicBeatState
UI_box = new FlxUITabMenu(null, tabs, true);
UI_box.resize(300, 400);
UI_box.x = 0;
UI_box.y = 100;
UI_box.x = FlxG.width / 2;
UI_box.y = 20;
add(UI_box);
addSongUI();
@ -183,10 +178,6 @@ class ChartingState extends MusicBeatState
var UI_songTitle = new FlxUIInputText(10, 10, 70, _song.song, 8);
typingShit = UI_songTitle;
var stepperdiff:FlxUINumericStepper = new FlxUINumericStepper(10, 40, 1, 0, 0, 3, 2);
stepperdiff.value = diff;
stepperdiff.name = 'song_diff';
var check_voices = new FlxUICheckBox(10, 25, null, null, "Has voice track", 100);
check_voices.checked = _song.needsVoices;
// _song.needsVoices = check_voices.checked;
@ -249,15 +240,6 @@ class ChartingState extends MusicBeatState
});
player2DropDown.selectedLabel = _song.player2;
var stepperp1KeyCount:FlxUINumericStepper = new FlxUINumericStepper(10, 130, 1, 4, 1, 21, 2);
stepperp1KeyCount.value = _song.p1KeyCount;
stepperp1KeyCount.name = 'song_p1KeyCount';
var stepperp2KeyCount:FlxUINumericStepper = new FlxUINumericStepper(140, 130, 1, 4, 1, 21, 2);
stepperp2KeyCount.value = _song.p2KeyCount;
stepperp2KeyCount.name = 'song_p2KeyCount';
var tab_group_song = new FlxUI(null, UI_box);
tab_group_song.name = "Song";
tab_group_song.add(UI_songTitle);
@ -272,10 +254,6 @@ class ChartingState extends MusicBeatState
tab_group_song.add(stepperSpeed);
tab_group_song.add(player1DropDown);
tab_group_song.add(player2DropDown);
tab_group_song.add(stepperdiff);
tab_group_song.add(stepperp1KeyCount);
tab_group_song.add(stepperp2KeyCount);
UI_box.addGroup(tab_group_song);
UI_box.scrollFactor.set();
@ -347,6 +325,7 @@ class ChartingState extends MusicBeatState
}
var stepperSusLength:FlxUINumericStepper;
var stepperNoteType:FlxUINumericStepper;
function addNoteUI():Void
{
@ -357,11 +336,20 @@ class ChartingState extends MusicBeatState
stepperSusLength.value = 0;
stepperSusLength.name = 'note_susLength';
var applyLength:FlxButton = new FlxButton(100, 10, 'Apply');
var applyLength:FlxButton = new FlxButton(100, 10, 'Apply Length');
stepperNoteType = new FlxUINumericStepper(110, 10, 1, 0);
stepperNoteType.value = 0;
stepperNoteType.name = 'note_type';
var applyType:FlxButton = new FlxButton(200, 10, 'Apply NoteType');
tab_group_note.add(stepperSusLength);
tab_group_note.add(applyLength);
tab_group_note.add(stepperNoteType);
tab_group_note.add(applyType);
UI_box.addGroup(tab_group_note);
}
@ -461,19 +449,9 @@ class ChartingState extends MusicBeatState
_song.notes[curSection].bpm = nums.value;
updateGrid();
}
else if (wname == "song_p1KeyCount")
else if (wname == 'note_type')
{
_song.p1KeyCount = Std.int(nums.value);
updateGrid();
}
else if (wname == "song_p2KeyCount")
{
_song.p2KeyCount = Std.int(nums.value);
updateGrid();
}
else if (wname == "song_diff")
{
diff = Std.int(nums.value);
curSelectedNote[4] = Std.int(nums.value);
updateGrid();
}
}
@ -866,27 +844,6 @@ class ChartingState extends MusicBeatState
function updateGrid():Void
{
//Thanks For LeatherEngine
remove(gridBG);
gridBG.kill();
gridBG.destroy();
gridBG = FlxGridOverlay.create(GRID_SIZE, GRID_SIZE, GRID_SIZE * (_song.p1KeyCount + _song.p2KeyCount),
Std.int(GRID_SIZE * 10));
add(gridBG);
remove(gridBlackLine);
gridBlackLine.kill();
gridBlackLine.destroy();
gridBlackLine = new FlxSprite(gridBG.x
+ (GRID_SIZE * ((!_song.notes[curSection].mustHitSection ? _song.p1KeyCount - 1: _song.p2KeyCount)
+ 1))).makeGraphic(2, Std.int(gridBG.height), FlxColor.BLACK);
add(gridBlackLine);
if (strumLine != null)
strumLine.makeGraphic(Std.int(gridBG.width), 4);
while (curRenderedNotes.members.length > 0)
{
curRenderedNotes.remove(curRenderedNotes.members[0], true);
@ -941,8 +898,6 @@ class ChartingState extends MusicBeatState
note.x = Math.floor(daNoteInfo * GRID_SIZE);
note.y = Math.floor(getYfromStrum((daStrumTime - sectionStartTime()) % (Conductor.stepCrochet * _song.notes[curSection].lengthInSteps)));
note.rawNoteData = daNoteInfo;
curRenderedNotes.add(note);
if (daSus > 0)
@ -963,7 +918,8 @@ class ChartingState extends MusicBeatState
mustHitSection: true,
sectionNotes: [],
typeOfSection: 0,
altAnim: false
altAnim: false,
noteType: 0
};
_song.notes.push(sec);
@ -975,7 +931,7 @@ class ChartingState extends MusicBeatState
for (i in _song.notes[curSection].sectionNotes)
{
if (i.strumTime == note.strumTime && i.noteData % _song.p1KeyCount == note.noteData)
if (i.strumTime == note.strumTime && i.noteData % 4 == note.noteData)
{
curSelectedNote = _song.notes[curSection].sectionNotes[swagNum];
}
@ -991,7 +947,7 @@ class ChartingState extends MusicBeatState
{
for (i in _song.notes[curSection].sectionNotes)
{
if (i[0] == note.strumTime && i[1] == note.rawNoteData)
if (i[0] == note.strumTime && i[1] % 4 == note.noteData)
{
FlxG.log.add('FOUND EVIL NUMBER');
_song.notes[curSection].sectionNotes.remove(i);
@ -1031,7 +987,7 @@ class ChartingState extends MusicBeatState
if (FlxG.keys.pressed.CONTROL)
{
_song.notes[curSection].sectionNotes.push([noteStrum, (noteData + _song.p1KeyCount) % (_song.p1KeyCount + _song.p2KeyCount), noteSus, noteAlt]);
_song.notes[curSection].sectionNotes.push([noteStrum, (noteData + 4) % 8, noteSus, noteAlt]);
}
trace(noteStrum);
@ -1097,8 +1053,7 @@ class ChartingState extends MusicBeatState
function loadJson(song:String):Void
{
var poop:String = Highscore.formatSong(song.toLowerCase(), diff);
PlayState.SONG = Song.loadFromJson(poop, song.toLowerCase());
PlayState.SONG = Song.loadFromJson(song.toLowerCase(), song.toLowerCase());
LoadingState.loadAndSwitchState(new ChartingState());
}

View File

@ -39,8 +39,8 @@ class CoolUtil
return daList;
}
#if desktop
public static function hotTextFile(path:String):Array<String>
{
var daList:Array<String> = File.getContent(path).trim().split('\n');
@ -53,7 +53,7 @@ class CoolUtil
return daList;
}
#end
public static function numberArray(max:Int, ?min = 0):Array<Int>
{
var dumbArray:Array<Int> = [];

View File

@ -14,8 +14,8 @@ import flixel.tweens.FlxTween;
import flixel.util.FlxColor;
import lime.utils.Assets;
#if desktop
import sys.FileSystem;
import sys.io.File;
import lime.utils.AssetType;
import lime.utils.Assets;
import haxe.Json;
import haxe.format.JsonParser;
#end
@ -87,11 +87,11 @@ class FreeplayState extends MusicBeatState
}
#if desktop
var weekList:Array<String> = sys.FileSystem.readDirectory("assets/weeks/");
var weekList:Array<String> = CoolUtil.coolTextFile(Paths.txt("weeklist"));
var weekJson:String;
var weekParseJson:Dynamic;
for(i in 0...weekList.length) {
weekJson = File.getContent("assets/weeks/"+weekList[i]);
weekJson = Assets.getText(Paths.week(weekList[i]));
weekParseJson = haxe.Json.parse(weekJson);
var weekSongs:Array<String> = Reflect.getProperty(weekParseJson, "songs");
var weekid:Int = Reflect.getProperty(weekParseJson, "weekid");
@ -226,8 +226,12 @@ class FreeplayState extends MusicBeatState
}
}
var holdTime:Float = 0;
override function update(elapsed:Float)
{
var shiftMult:Int = 1;
if(FlxG.keys.pressed.SHIFT) shiftMult = 3;
super.update(elapsed);
if (FlxG.sound.music != null)
@ -250,12 +254,34 @@ class FreeplayState extends MusicBeatState
var accepted = controls.ACCEPT;
if (upP)
{
changeSelection(-1);
holdTime = 0;
}
if (downP)
{
changeSelection(1);
holdTime = 0;
}
if (FlxG.mouse.wheel != 0)
changeSelection(-Math.round(FlxG.mouse.wheel / 4));
if(controls.UI_DOWN || controls.UI_UP)
{
var checkLastHold:Int = Math.floor((holdTime - 0.5) * 10);
holdTime += elapsed;
var checkNewHold:Int = Math.floor((holdTime - 0.5) * 10);
if(holdTime > 0.5 && checkNewHold - checkLastHold > 0)
{
changeSelection((checkNewHold - checkLastHold) * (controls.UI_UP ? -shiftMult : shiftMult));
changeDiff();
}
}
if(FlxG.mouse.wheel != 0)
{
changeSelection(-shiftMult * FlxG.mouse.wheel);
changeDiff();
}
if (controls.UI_LEFT_P)
changeDiff(-1);
@ -280,7 +306,7 @@ class FreeplayState extends MusicBeatState
LoadingState.loadAndSwitchState(new PlayState());
}
if (FlxG.keys.pressed.SHIFT){
if (FlxG.keys.pressed.CONTROL){
var poop:String = Highscore.formatSong(songs[curSelected].songName.toLowerCase(), curDifficulty);
PlayState.SONG = Song.loadFromJson(poop, songs[curSelected].songName.toLowerCase());
PlayState.isStoryMode = false;

View File

@ -11,6 +11,7 @@ import ui.PreferencesMenu;
class GameOverSubstate extends MusicBeatSubstate
{
public static var instance:GameOverSubstate;
var bf:Boyfriend;
var camFollow:FlxObject;
@ -19,6 +20,7 @@ class GameOverSubstate extends MusicBeatSubstate
public function new(x:Float, y:Float)
{
instance = this;
var daStage = PlayState.curStage;
var daBf:String = '';
switch (daStage)

389
source/LuaHandler.hx Normal file
View File

@ -0,0 +1,389 @@
package;
import openfl.display.BitmapData;
#if linc_luajit
import llua.Lua;
import llua.LuaL;
import llua.State;
import llua.Convert;
#end
//import animateatlas.AtlasFrameMaker;
import flixel.FlxG;
import flixel.addons.effects.FlxTrail;
import flixel.input.keyboard.FlxKey;
import flixel.tweens.FlxTween;
import flixel.tweens.FlxEase;
import flixel.text.FlxText;
import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.math.FlxPoint;
import flixel.system.FlxSound;
import flixel.util.FlxTimer;
import flixel.FlxSprite;
import flixel.FlxCamera;
import flixel.util.FlxColor;
import flixel.FlxBasic;
import flixel.FlxObject;
import flixel.FlxSprite;
import openfl.Lib;
import openfl.display.BlendMode;
import openfl.filters.BitmapFilter;
import openfl.utils.Assets;
import flixel.math.FlxMath;
import flixel.util.FlxSave;
import flixel.addons.transition.FlxTransitionableState;
import flixel.system.FlxAssets.FlxShader;
#if (!flash && sys)
import flixel.addons.display.FlxRuntimeShader;
#end
#if sys
import sys.FileSystem;
import sys.io.File;
#end
import Type.ValueType;
import Controls;
//import DialogueBoxPsych;
#if hscript
import hscript.Parser;
import hscript.Interp;
import hscript.Expr;
#end
import ui.PreferencesMenu;
#if desktop
import Discord;
#end
using StringTools;
class LuaHandler {
public static var Function_Stop:Dynamic = "##NEKO2LUA_FUNCTIONSTOP";
public static var Function_Continue:Dynamic = "##NEKO2LUA_FUNCTIONCONTINUE";
public static var Function_StopLua:Dynamic = "##NEKO2LUA_FUNCTIONSTOPLUA";
#if linc_luajit
public var lua:State = null;
#end
public var closed:Bool = false;
public var scriptName:String = '';
#if hscript
public static var hscript:HScript = null;
#end
public function new(luafile:String)
{
var lua:State = LuaL.newstate();
LuaL.openlibs(lua);
//trace("Lua version: " + Lua.version());
//trace("LuaJIT version: " + Lua.versionJIT());
LuaL.dofile(lua, luafile);
try{
var result:Dynamic = LuaL.dofile(lua, luafile);
var resultStr:String = Lua.tostring(lua, result);
if(resultStr != null && result != 0) {
trace('Error on lua script! ' + resultStr);
#if windows
lime.app.Application.current.window.alert(resultStr, 'Error on lua script!');
#else
luaTrace('Error loading lua script: "$luafile"\n' + resultStr, true, false, FlxColor.RED);
#end
lua = null;
return;
}
} catch(e:Dynamic) {
trace(e);
return;
}
scriptName = luafile;
hscript = new HScript();
trace('lua file loaded succesfully:' + luafile);
#if linc_luajit
Lua_helper.add_callback(lua, "setLuaValue", function(variable:String, value:Dynamic) {
PlayState.instance.variables.set(variable,value);
});
Lua_helper.add_callback(lua, "getLuaValue", function(variable:String) {
return PlayState.instance.variables.get(variable);
});
Lua_helper.add_callback(lua, "setInstanceValue", function(variable:String, value:Dynamic) {
Reflect.setField(PlayState.instance, variable, value);
});
Lua_helper.add_callback(lua, "getInstanceValue", function(variable:String) {
return Reflect.field(PlayState.instance, variable);
});
Lua_helper.add_callback(lua, "runHaxeCode", function(codeToRun:String) {
var retVal:Dynamic = null;
#if hscript
hscript = new HScript();
try {
retVal = hscript.execute(codeToRun);
}
catch (e:Dynamic) {
luaTrace(scriptName + ":" + lastCalledFunction + " - " + e, false,false, FlxColor.RED);
}
#else
luaTrace("runHaxeCode: HScript isn't supported on this platform!", false, false, FlxColor.RED);
#end
if(retVal != null && !isOfTypes(retVal, [Bool, Int, Float, String, Array])) retVal = null;
return retVal;
});
Lua_helper.add_callback(lua, "debugPrint", function(text1:Dynamic = '', text2:Dynamic = '', text3:Dynamic = '', text4:Dynamic = '', text5:Dynamic = '') {
if (text1 == null) text1 = '';
if (text2 == null) text2 = '';
if (text3 == null) text3 = '';
if (text4 == null) text4 = '';
if (text5 == null) text5 = '';
luaTrace('' + text1 + text2 + text3 + text4 + text5, true, false);
});
Lua_helper.add_callback(lua, "close", function() {
closed = true;
return closed;
});
Lua_helper.add_callback(lua, "changePresence", function(details:String, state:Null<String>, ?smallImageKey:String, ?hasStartTimestamp:Bool, ?endTimestamp:Float) {
#if desktop
DiscordClient.changePresence(details, state, smallImageKey, hasStartTimestamp, endTimestamp);
#end
});
#end
}
var lastCalledFunction:String = '';
public function call(func:String, args:Array<Dynamic>):Dynamic {
#if linc_luajit
if(closed) return Function_Continue;
lastCalledFunction = func;
try {
if(lua == null) return Function_Continue;
Lua.getglobal(lua, func);
var type:Int = Lua.type(lua, -1);
if (type != Lua.LUA_TFUNCTION) {
if (type > Lua.LUA_TNIL)
luaTrace("ERROR (" + func + "): attempt to call a " + typeToString(type) + " value", false, false, FlxColor.RED);
Lua.pop(lua, 1);
return Function_Continue;
}
for (arg in args) Convert.toLua(lua, arg);
var status:Int = Lua.pcall(lua, args.length, 1, 0);
// Checks if it's not successful, then show a error.
if (status != Lua.LUA_OK) {
var error:String = getErrorMessage(status);
luaTrace("ERROR (" + func + "): " + error, false, false, FlxColor.RED);
return Function_Continue;
}
// If successful, pass and then return the result.
var result:Dynamic = cast Convert.fromLua(lua, -1);
if (result == null) result = Function_Continue;
Lua.pop(lua, 1);
return result;
}
catch (e:Dynamic) {
trace(e);
}
#end
return Function_Continue;
}
public static function isOfTypes(value:Any, types:Array<Dynamic>)
{
for (type in types)
{
if(Std.isOfType(value, type)) return true;
}
return false;
}
function typeToString(type:Int):String {
#if linc_luajit
switch(type) {
case Lua.LUA_TBOOLEAN: return "boolean";
case Lua.LUA_TNUMBER: return "number";
case Lua.LUA_TSTRING: return "string";
case Lua.LUA_TTABLE: return "table";
case Lua.LUA_TFUNCTION: return "function";
}
if (type <= Lua.LUA_TNIL) return "nil";
#end
return "unknown";
}
function getErrorMessage(status:Int):String {
#if linc_luajit
var v:String = Lua.tostring(lua, -1);
Lua.pop(lua, 1);
if (v != null) v = v.trim();
if (v == null || v == "") {
switch(status) {
case Lua.LUA_ERRRUN: return "Runtime Error";
case Lua.LUA_ERRMEM: return "Memory Allocation Error";
case Lua.LUA_ERRERR: return "Critical Error";
}
return "Unknown Error";
}
return v;
#end
return null;
}
public function set(variable:String, data:Dynamic) {
#if linc_luajit
if(lua == null) {
return;
}
Convert.toLua(lua, data);
Lua.setglobal(lua, variable);
#end
}
public function stop() {
#if linc_luajit
if(lua == null) {
return;
}
Lua.close(lua);
lua = null;
#end
}
public function luaTrace(text:String, ignoreCheck:Bool = false, deprecated:Bool = false, color:FlxColor = FlxColor.WHITE) {
#if linc_luajit
if(ignoreCheck || getBool('luaDebugMode')) {
if(deprecated && !getBool('luaDeprecatedWarnings')) {
return;
}
PlayState.instance.addTextToDebug(text, color);
trace(text);
}
#end
}
#if linc_luajit
public function getBool(variable:String) {
var result:String = null;
Lua.getglobal(lua, variable);
result = Convert.fromLua(lua, -1);
Lua.pop(lua, 1);
if(result == null) {
return false;
}
return (result == 'true');
}
#end
}
class DebugLuaText extends FlxText
{
private var disableTime:Float = 6;
public var parentGroup:FlxTypedGroup<DebugLuaText>;
public function new(text:String, parentGroup:FlxTypedGroup<DebugLuaText>, color:FlxColor) {
this.parentGroup = parentGroup;
super(10, 10, 0, text, 16);
setFormat(Paths.font("vcr.ttf"), 16, color, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
scrollFactor.set();
borderSize = 1;
}
override function update(elapsed:Float) {
super.update(elapsed);
disableTime -= elapsed;
if(disableTime < 0) disableTime = 0;
if(disableTime < 1) alpha = disableTime;
}
}
#if hscript
class HScript
{
public static var parser:Parser = new Parser();
public var interp:Interp;
public var variables(get, never):Map<String, Dynamic>;
public function get_variables()
{
return interp.variables;
}
public function new()
{
interp = new Interp();
interp.variables.set('FlxG', FlxG);
interp.variables.set('FlxSprite', FlxSprite);
interp.variables.set('FlxCamera', FlxCamera);
interp.variables.set('FlxTimer', FlxTimer);
interp.variables.set('FlxTween', FlxTween);
interp.variables.set('FlxEase', FlxEase);
interp.variables.set('PlayState', PlayState);
interp.variables.set('game', PlayState.instance);
interp.variables.set('Paths', Paths);
interp.variables.set('Conductor', Conductor);
interp.variables.set('Preference', Preference);
interp.variables.set('Character', Character);
interp.variables.set('Alphabet', Alphabet);
//interp.variables.set('CustomSubstate', CustomSubstate);
#if (!flash && sys)
interp.variables.set('FlxRuntimeShader', FlxRuntimeShader);
#end
interp.variables.set('ShaderFilter', openfl.filters.ShaderFilter);
interp.variables.set('StringTools', StringTools);
interp.variables.set('setVar', function(name:String, value:Dynamic)
{
PlayState.instance.variables.set(name, value);
});
interp.variables.set('getVar', function(name:String)
{
var result:Dynamic = null;
if(PlayState.instance.variables.exists(name)) result = PlayState.instance.variables.get(name);
return result;
});
interp.variables.set('removeVar', function(name:String)
{
if(PlayState.instance.variables.exists(name))
{
PlayState.instance.variables.remove(name);
return true;
}
return false;
});
}
public function execute(codeToRun:String):Dynamic
{
@:privateAccess
HScript.parser.line = 1;
HScript.parser.allowTypes = true;
return interp.execute(HScript.parser.parseString(codeToRun));
}
}
#end

View File

@ -144,6 +144,7 @@ class Main extends Sprite
Application.current.window.onFocusOut.add(onWindowFocusOut);
Application.current.window.onFocusIn.add(onWindowFocusIn);
#end
/*
video = new Video();
addChild(video);

View File

@ -1,48 +0,0 @@
package;
import Controls;
import flixel.FlxG;
class ManiaTools
{
private static var controls(get, never):Controls;
private static function get_controls():Controls
return PlayerSettings.player1.controls;
public static function getHoldKeysToNumber(keyCount:Int = 4):Array<Bool>
{
if (keyCount == 1) return [FlxG.keys.pressed.SPACE];
if (keyCount == 2) return [FlxG.keys.pressed.F, FlxG.keys.pressed.J];
if (keyCount == 3) return [FlxG.keys.pressed.F, FlxG.keys.pressed.SPACE, FlxG.keys.pressed.J];
if (keyCount == 4) return [controls.NOTE_LEFT, controls.NOTE_DOWN, controls.NOTE_UP, controls.NOTE_RIGHT];
if (keyCount == 5) return [FlxG.keys.pressed.D, FlxG.keys.pressed.F, FlxG.keys.pressed.SPACE, FlxG.keys.pressed.J, FlxG.keys.pressed.K];
if (keyCount == 6) return [FlxG.keys.pressed.S, FlxG.keys.pressed.D, FlxG.keys.pressed.F, FlxG.keys.pressed.J, FlxG.keys.pressed.K, FlxG.keys.pressed.L];
return [controls.NOTE_LEFT, controls.NOTE_DOWN, controls.NOTE_UP, controls.NOTE_RIGHT];
}
public static function getPressedKeysToNumber(keyCount:Int = 4):Array<Bool>
{
if (keyCount == 1) return [FlxG.keys.justPressed.SPACE];
if (keyCount == 2) return [FlxG.keys.justPressed.F, FlxG.keys.justPressed.J];
if (keyCount == 3) return [FlxG.keys.justPressed.F, FlxG.keys.justPressed.SPACE, FlxG.keys.justPressed.J];
if (keyCount == 4) return [controls.NOTE_LEFT, controls.NOTE_DOWN, controls.NOTE_UP, controls.NOTE_RIGHT];
if (keyCount == 5) return [FlxG.keys.justPressed.D, FlxG.keys.justPressed.F, FlxG.keys.justPressed.SPACE, FlxG.keys.justPressed.J, FlxG.keys.justPressed.K];
if (keyCount == 6) return [FlxG.keys.justPressed.S, FlxG.keys.justPressed.D, FlxG.keys.justPressed.F, FlxG.keys.justPressed.J, FlxG.keys.justPressed.K, FlxG.keys.justPressed.L];
return [controls.NOTE_LEFT, controls.NOTE_DOWN, controls.NOTE_UP, controls.NOTE_RIGHT];
}
public static function getReleasedKeysToNumber(keyCount:Int = 4):Array<Bool>
{
if (keyCount == 1) return [FlxG.keys.justReleased.SPACE];
if (keyCount == 2) return [FlxG.keys.justReleased.F, FlxG.keys.justReleased.J];
if (keyCount == 3) return [FlxG.keys.justReleased.F, FlxG.keys.justReleased.SPACE, FlxG.keys.justReleased.J];
if (keyCount == 4) return [controls.NOTE_LEFT, controls.NOTE_DOWN, controls.NOTE_UP, controls.NOTE_RIGHT];
if (keyCount == 5) return [FlxG.keys.justReleased.D, FlxG.keys.justReleased.F, FlxG.keys.justReleased.SPACE, FlxG.keys.justReleased.J, FlxG.keys.justReleased.K];
if (keyCount == 6) return [FlxG.keys.justReleased.S, FlxG.keys.justReleased.D, FlxG.keys.justReleased.F, FlxG.keys.justReleased.J, FlxG.keys.justReleased.K, FlxG.keys.justReleased.L];
return [controls.NOTE_LEFT, controls.NOTE_DOWN, controls.NOTE_UP, controls.NOTE_RIGHT];
}
}

View File

@ -46,8 +46,9 @@ class Note extends FlxSprite
public static var RED_NOTE:Int = 3;
public static var arrowColors:Array<Float> = [1, 1, 1, 1];
public var noteType:Int = 0;
public function new(strumTime:Float, noteData:Int, ?prevNote:Note, ?sustainNote:Bool = false)
public function new(strumTime:Float, noteData:Int, ?prevNote:Note, ?sustainNote:Bool = false, noteType:Int = 0)
{
super();
@ -63,26 +64,7 @@ class Note extends FlxSprite
this.strumTime = strumTime;
this.noteData = noteData;
if (PlayState.SONG != null){
if (mustPress)
{
scale.x = scale.x / (PlayState.SONG.p1KeyCount - 3);
scale.y = scale.y / (PlayState.SONG.p1KeyCount - 3);
}else{
scale.x = scale.x / (PlayState.SONG.p2KeyCount - 3);
scale.y = scale.y / (PlayState.SONG.p2KeyCount - 3);
}
}else{
if (mustPress)
{
scale.x = scale.x / (ChartingState._song.p1KeyCount - 3);
scale.y = scale.y / (ChartingState._song.p1KeyCount - 3);
}else{
scale.x = scale.x / (ChartingState._song.p2KeyCount - 3);
scale.y = scale.y / (ChartingState._song.p2KeyCount - 3);
}
}
this.noteType = noteType;
var daStage:String = PlayState.curStage;

View File

@ -117,6 +117,26 @@ class Paths
inline static public function video(key:String)
{
return 'assets/videos/$key';
return file('$key',"videos");
}
inline static public function week(key:String)
{
return file('$key.json',"weeks");
}
inline static public function script(key:String)
{
return file('$key',"scripts");
}
inline static public function shaders(key:String)
{
return file('$key',"shaders");
}
inline static public function filelist(type:AssetType = TEXT):Array<String>
{
return OpenFlAssets.list(type);
}
}

View File

@ -152,7 +152,6 @@ class PauseSubState extends MusicBeatSubstate
PlayState.SONG.song.toLowerCase());
PlayState.storyDifficulty = curSelected;
FlxG.resetState();
case 'Toggle Practice Mode':

View File

@ -35,6 +35,7 @@ import flixel.util.FlxColor;
import flixel.util.FlxSort;
import flixel.util.FlxStringUtil;
import flixel.util.FlxTimer;
import flixel.util.FlxSave;
import haxe.Json;
import lime.utils.Assets;
import openfl.Lib;
@ -62,8 +63,13 @@ import Discord.DiscordClient;
import lime.app.Application;
#end
#if linc_luajit
import LuaHandler;
#end
class PlayState extends MusicBeatState
{
public static var instance:PlayState;
public static var curStage:String = '';
public static var SONG:SwagSong;
public static var isStoryMode:Bool = false;
@ -111,8 +117,8 @@ class PlayState extends MusicBeatState
private var iconP1:HealthIcon;
private var iconP2:HealthIcon;
private var camHUD:FlxCamera;
private var camGame:FlxCamera;
private static var camHUD:FlxCamera;
private static var camGame:FlxCamera;
var dialogue:Array<String> = ['blah blah blah', 'coolswag'];
@ -183,8 +189,37 @@ class PlayState extends MusicBeatState
public static var isdownscroll:Bool = PreferencesMenu.getPref('downscroll');
public static var ismiddlescroll:Bool = PreferencesMenu.getPref('middlescroll');
//lua shit
//public var boyfriendMap:Map<String, Boyfriend> = new Map();
//public var dadMap:Map<String, Character> = new Map();
//public var gfMap:Map<String, Character> = new Map();
//public var modchartTweens:Map<String, FlxTween> = new Map<String, FlxTween>();
//public var modchartSprites:Map<String, ModchartSprite> = new Map<String, ModchartSprite>();
//public var modchartTimers:Map<String, FlxTimer> = new Map<String, FlxTimer>();
//public var modchartSounds:Map<String, FlxSound> = new Map<String, FlxSound>();
//public var modchartTexts:Map<String, ModchartText> = new Map<String, ModchartText>();
//public var modchartSaves:Map<String, FlxSave> = new Map<String, FlxSave>();
public var variables:Map<String, Dynamic> = new Map();
public var luaArray:Array<LuaHandler> = [];
private var luaDebugGroup:FlxTypedGroup<DebugLuaText>;
override public function create()
{
// for lua
instance = this;
//lua shit
#if linc_luajit
var luaFileList:Array<String> = Paths.filelist(openfl.utils.AssetType.SCRIPT);
for (lua in luaFileList)
{
if(lua.endsWith('.lua'))
{
luaArray.push(new LuaHandler(Paths.file(lua,openfl.utils.AssetType.SCRIPT,"default")));
}
}
#end
if (FlxG.sound.music != null)
FlxG.sound.music.stop();
@ -888,6 +923,7 @@ class PlayState extends MusicBeatState
// UI_camera.zoom = 1;
// cameras = [FlxG.cameras.list[1]];
startingSong = true;
if (isStoryMode && !seenCutscene)
@ -1510,8 +1546,8 @@ class PlayState extends MusicBeatState
inCutscene = false;
camHUD.visible = true;
generateStaticArrows(0,SONG.p1KeyCount);
generateStaticArrows(1,SONG.p2KeyCount);
generateStaticArrows(0,4);
generateStaticArrows(1,4);
talking = false;
startedCountdown = true;
@ -1647,17 +1683,18 @@ class PlayState extends MusicBeatState
var daStrumTime:Float = songNotes[0];
var gottaHitNote:Bool = section.mustHitSection;
if (songNotes[1] >= (!gottaHitNote ? SONG.p1KeyCount : SONG.p2KeyCount))
if (songNotes[1] >= 4)
gottaHitNote = !section.mustHitSection;
var oldNote:Note;
var daNoteData:Int = Std.int(songNotes[1] % (!gottaHitNote ? SONG.p1KeyCount : SONG.p2KeyCount));
var daNoteData:Int = Std.int(songNotes[1] % 4);
if (unspawnNotes.length > 0)
oldNote = unspawnNotes[Std.int(unspawnNotes.length - 1)];
else
oldNote = null;
var daNoteType:Int = Std.int(songNotes[4]);
var swagNote:Note = new Note(daStrumTime, daNoteData, oldNote);
var swagNote:Note = new Note(daStrumTime, daNoteData, oldNote, daNoteType);
swagNote.sustainLength = songNotes[2];
swagNote.altNote = songNotes[3];
swagNote.scrollFactor.set(0, 0);
@ -1671,7 +1708,7 @@ class PlayState extends MusicBeatState
{
oldNote = unspawnNotes[Std.int(unspawnNotes.length - 1)];
var sustainNote:Note = new Note(daStrumTime + (Conductor.stepCrochet * susNote) + Conductor.stepCrochet, daNoteData, oldNote, true);
var sustainNote:Note = new Note(daStrumTime + (Conductor.stepCrochet * susNote) + Conductor.stepCrochet, daNoteData, oldNote, true, daNoteType);
sustainNote.scrollFactor.set();
unspawnNotes.push(sustainNote);
@ -2148,58 +2185,7 @@ class PlayState extends MusicBeatState
if (!daNote.mustPress && daNote.wasGoodHit)
{
var time:Float = 0.15;
if(daNote.isSustainNote && !daNote.animation.curAnim.name.endsWith('end')) {
time += 0.15;
}
var spr:StrumNote = null;
spr = opponentStrums.members[daNote.noteData];
spr.animation.play('confirm', true);
if (!curStage.startsWith('school'))
{
spr.centerOffsets();
spr.offset.x -= 13;
spr.offset.y -= 13;
}
else
spr.centerOffsets();
spr.resetAnim = time;
if (SONG.song != 'Tutorial')
camZooming = true;
var altAnim:String = "";
if (SONG.notes[Math.floor(curStep / 16)] != null)
{
if (SONG.notes[Math.floor(curStep / 16)].altAnim)
altAnim = '-alt';
}
if (daNote.altNote)
altAnim = '-alt';
switch (Math.abs(daNote.noteData))
{
case 0:
dad.playAnim('singLEFT' + altAnim, true);
case 1:
dad.playAnim('singDOWN' + altAnim, true);
case 2:
dad.playAnim('singUP' + altAnim, true);
case 3:
dad.playAnim('singRIGHT' + altAnim, true);
}
dad.holdTimer = 0;
if (SONG.needsVoices)
vocals.volume = 1;
daNote.kill();
notes.remove(daNote, true);
daNote.destroy();
opponentNoteHit(daNote);
}
// WIP interpolation shit? Need to fix the pause issue
@ -2627,9 +2613,20 @@ class PlayState extends MusicBeatState
private function keyShit():Void
{
// control arrays, order L D R U
var holdArray:Array<Bool> = ManiaTools.getHoldKeysToNumber(SONG.p2KeyCount);
var pressArray:Array<Bool> = ManiaTools.getPressedKeysToNumber(SONG.p2KeyCount);
var releaseArray:Array<Bool> = ManiaTools.getReleasedKeysToNumber(SONG.p2KeyCount);
// control arrays, order L D R U
var holdArray:Array<Bool> = [controls.NOTE_LEFT, controls.NOTE_DOWN, controls.NOTE_UP, controls.NOTE_RIGHT];
var pressArray:Array<Bool> = [
controls.NOTE_LEFT_P,
controls.NOTE_DOWN_P,
controls.NOTE_UP_P,
controls.NOTE_RIGHT_P
];
var releaseArray:Array<Bool> = [
controls.NOTE_LEFT_R,
controls.NOTE_DOWN_R,
controls.NOTE_UP_R,
controls.NOTE_RIGHT_R
];
// HOLDS, check for sustain notes
if (holdArray.contains(true) && /*!boyfriend.stunned && */ generatedMusic)
@ -2805,6 +2802,66 @@ class PlayState extends MusicBeatState
noteMiss(3);
} */
function opponentNoteHit(note:Note):Void
{
var time:Float = 0.15;
if(note.isSustainNote && !note.animation.curAnim.name.endsWith('end')) {
time += 0.15;
}
var spr:StrumNote = null;
spr = opponentStrums.members[note.noteData];
spr.animation.play('confirm', true);
if (!curStage.startsWith('school'))
{
spr.centerOffsets();
spr.offset.x -= 13;
spr.offset.y -= 13;
}
else
spr.centerOffsets();
spr.resetAnim = time;
if (SONG.song != 'Tutorial')
camZooming = true;
var altAnim:String = "";
if (SONG.notes[Math.floor(curStep / 16)] != null)
{
if (SONG.notes[Math.floor(curStep / 16)].altAnim)
altAnim = '-alt';
}
if (note.altNote)
altAnim = '-alt';
switch (Math.abs(note.noteData))
{
case 0:
dad.playAnim('singLEFT' + altAnim, true);
case 1:
dad.playAnim('singDOWN' + altAnim, true);
case 2:
dad.playAnim('singUP' + altAnim, true);
case 3:
dad.playAnim('singRIGHT' + altAnim, true);
}
dad.holdTimer = 0;
if (SONG.needsVoices)
vocals.volume = 1;
callOnLuas('opponentNoteHit', [notes.members.indexOf(note), note.noteType, Math.abs(note.noteData), note.isSustainNote]);
if (!note.isSustainNote)
{
note.kill();
notes.remove(note, true);
note.destroy();
}
}
function goodNoteHit(note:Note):Void
{
if (!note.wasGoodHit)
@ -2843,6 +2900,8 @@ class PlayState extends MusicBeatState
note.wasGoodHit = true;
vocals.volume = 1;
callOnLuas('goodNoteHit', [notes.members.indexOf(note), note.noteType, Math.abs(note.noteData), note.isSustainNote]);
if (!note.isSustainNote)
{
note.kill();
@ -3104,6 +3163,9 @@ class PlayState extends MusicBeatState
{
lightningStrikeShit();
}
setOnLuas("curBeat",curBeat);
callOnLuas('onBeatHit', []);
}
var curLight:Int = 0;
@ -3152,4 +3214,49 @@ class PlayState extends MusicBeatState
#end
}
}
public function callOnLuas(event:String, args:Array<Dynamic>, ignoreStops = true, exclusions:Array<String> = null, excludeValues:Array<Dynamic> = null):Dynamic {
var returnVal = LuaHandler.Function_Continue;
#if linc_luajit
if(exclusions == null) exclusions = [];
if(excludeValues == null) excludeValues = [];
for (script in luaArray) {
if(exclusions.contains(script.scriptName))
continue;
var myValue = script.call(event, args);
if(myValue == LuaHandler.Function_StopLua && !ignoreStops)
break;
if(myValue != null && myValue != LuaHandler.Function_Continue) {
returnVal = myValue;
}
}
#end
return returnVal;
}
public function setOnLuas(variable:String, arg:Dynamic) {
#if linc_luajit
for (i in 0...luaArray.length) {
luaArray[i].set(variable, arg);
}
#end
}
public function addTextToDebug(text:String, color:FlxColor) {
#if linc_luajit
luaDebugGroup.forEachAlive(function(spr:DebugLuaText) {
spr.y += 20;
});
if(luaDebugGroup.members.length > 34) {
var blah = luaDebugGroup.members[34];
blah.destroy();
luaDebugGroup.remove(blah);
}
luaDebugGroup.insert(0, new DebugLuaText(text, luaDebugGroup, color));
#end
}
}

17
source/Preference.hx Normal file
View File

@ -0,0 +1,17 @@
package;
import ui.PreferencesMenu;
class Preference {
public static var censor_naughty = PreferencesMenu.getPref('censor-naughty');
public static var downscroll = PreferencesMenu.getPref('downscroll');
public static var middlescroll = PreferencesMenu.getPref('middlescroll');
public static var flashing_menu = PreferencesMenu.getPref('flashing-menu');
public static var camera_zoom = PreferencesMenu.getPref('camera-zoom');
public static var fps_counter = PreferencesMenu.getPref('fps-counter');
public static var auto_pause = PreferencesMenu.getPref('auto-pause');
public static var master_volume = PreferencesMenu.getPref('master-volume');
public static var ghosttapping = PreferencesMenu.getPref('ghosttapping');
public static var vcombospr = PreferencesMenu.getPref('vcombospr');
public static var shaders = PreferencesMenu.getPref('shaders');
public static var antialiasing = PreferencesMenu.getPref('antialiasing');
}

View File

@ -9,6 +9,7 @@ typedef SwagSection =
var bpm:Float;
var changeBPM:Bool;
var altAnim:Bool;
var noteType:Int;
}
class Section

View File

@ -18,9 +18,6 @@ typedef SwagSong =
var player1:String;
var player2:String;
var validScore:Bool;
var p1KeyCount:Null<Int>;
var p2KeyCount:Null<Int>;
}
class Song
@ -34,9 +31,6 @@ class Song
public var player1:String = 'bf';
public var player2:String = 'dad';
public var p1KeyCount:Int = 4;
public var p2KeyCount:Int = 4;
public function new(song, notes, bpm)
{
this.song = song;
@ -77,9 +71,6 @@ class Song
{
var swagShit:SwagSong = cast Json.parse(rawJson).song;
swagShit.validScore = true;
if (swagShit.p1KeyCount == null) swagShit.p1KeyCount = 4;
if (swagShit.p2KeyCount == null) swagShit.p2KeyCount = swagShit.p1KeyCount;
return swagShit;
}
}

View File

@ -16,8 +16,8 @@ import flixel.util.FlxColor;
import flixel.util.FlxTimer;
import lime.net.curl.CURLCode;
#if desktop
import sys.FileSystem;
import sys.io.File;
import lime.utils.Assets;
import lime.utils.AssetType;
import haxe.Json;
import haxe.format.JsonParser;
#end
@ -65,11 +65,11 @@ class StoryMenuState extends MusicBeatState
}
#if desktop
var weekList:Array<String> = sys.FileSystem.readDirectory("assets/weeks/");
var weekList:Array<String> = CoolUtil.coolTextFile(Paths.txt("weeklist"));
var weekJson:String;
var weekParseJson:Dynamic;
for(i in 0...weekList.length) {
weekJson = File.getContent("assets/weeks/"+weekList[i]);
weekJson = Assets.getText(Paths.week(weekList[i]));
weekParseJson = haxe.Json.parse(weekJson);
var weekSongs:Array<String> = Reflect.getProperty(weekParseJson, "songs");
var weekChars:Array<String> = Reflect.getProperty(weekParseJson, "weekCharacter");

View File

@ -184,14 +184,8 @@ class StrumNote extends FlxSprite
if(animation.curAnim.name == 'confirm' && !PlayState.curStage.startsWith('school')) {
centerOrigin();
centerOffsets();
//Thanks For LeatherEngine
offset.x = frameWidth / 2;
offset.y = frameHeight / 2;
var scale = keyCount;
offset.x -= 156 * scale / 2;
offset.y -= 156 * scale / 2;
offset.x -= 13;
offset.y -= 13;
}
}
}

View File

@ -74,6 +74,11 @@ class TitleState extends MusicBeatState
override public function create():Void
{
#if debug
//crash
//FlxG.log.redirectTraces = true;
#end
#if polymod
var mods:Array<String> = CoolUtil.hotTextFile("mods/modList.txt");
//Thanks For Leather Engine
@ -95,6 +100,7 @@ class TitleState extends MusicBeatState
"fonts" => "fonts",
"weeks" => "weeks",
"data" => "data",
"scripts" => "scripts",
"images" => "images",
"music" => "music",
"sounds" => "sounds",
@ -110,6 +116,7 @@ class TitleState extends MusicBeatState
}
});
FlxG.bitmap.clearCache();
Polymod.clearCache();
#end
if (!doneFlixelSplash) {
@ -200,13 +207,10 @@ class TitleState extends MusicBeatState
// netConnection.addEventListener(MouseEvent.MOUSE_DOWN, overlay_onMouseDown);
#else
/*
new FlxTimer().start(1, function(tmr:FlxTimer)
{
startIntro();
});
*/
startIntro();
#end
#if discord_rpc

View File

@ -0,0 +1,728 @@
package flixel.addons.display;
import flixel.system.FlxAssets.FlxShader;
import lime.utils.Float32Array;
import openfl.display.BitmapData;
import openfl.display.ShaderInput;
import openfl.display.ShaderParameter;
import openfl.display.ShaderParameterType;
/**
* An wrapper for Flixel/OpenFL's shaders, which takes fragment and vertex source
* in the constructor instead of using macros, so it can be provided data
* at runtime (for example, when using mods).
*
* HOW TO USE:
* 1. Create an instance of this class, passing the text of the `.frag` and `.vert` files.
* Note that you can set either of these to null (making them both null would make the shader do nothing???).
* 2. Use `flxSprite.shader = runtimeShader` to apply the shader to the sprite.
* 3. Use `runtimeShader.setFloat()`, `setBool()`, etc. to modify any uniforms.
*
* @author MasterEric
* @see https://github.com/openfl/openfl/blob/develop/src/openfl/utils/_internal/ShaderMacro.hx
* @see https://dixonary.co.uk/blog/shadertoy
*/
class FlxRuntimeShader extends FlxShader
{
#if FLX_DRAW_QUADS
// We need to add stuff from FlxGraphicsShader too!
#else
// Only stuff from openfl.display.Shader is needed
#end
// These variables got copied from openfl.display.GraphicsShader
// and from flixel.graphics.tile.FlxGraphicsShader,
// and probably won't change ever.
static final BASE_VERTEX_HEADER:String = "
#pragma version
#pragma precision
attribute float openfl_Alpha;
attribute vec4 openfl_ColorMultiplier;
attribute vec4 openfl_ColorOffset;
attribute vec4 openfl_Position;
attribute vec2 openfl_TextureCoord;
varying float openfl_Alphav;
varying vec4 openfl_ColorMultiplierv;
varying vec4 openfl_ColorOffsetv;
varying vec2 openfl_TextureCoordv;
uniform mat4 openfl_Matrix;
uniform bool openfl_HasColorTransform;
uniform vec2 openfl_TextureSize;
";
static final BASE_VERTEX_BODY:String = "
openfl_Alphav = openfl_Alpha;
openfl_TextureCoordv = openfl_TextureCoord;
if (openfl_HasColorTransform) {
openfl_ColorMultiplierv = openfl_ColorMultiplier;
openfl_ColorOffsetv = openfl_ColorOffset / 255.0;
}
gl_Position = openfl_Matrix * openfl_Position;
";
static final BASE_FRAGMENT_HEADER:String = "
#pragma version
#pragma precision
varying float openfl_Alphav;
varying vec4 openfl_ColorMultiplierv;
varying vec4 openfl_ColorOffsetv;
varying vec2 openfl_TextureCoordv;
uniform bool openfl_HasColorTransform;
uniform vec2 openfl_TextureSize;
uniform sampler2D bitmap;
"
#if FLX_DRAW_QUADS
// Add on more stuff!
+ "
uniform bool hasTransform;
uniform bool hasColorTransform;
vec4 flixel_texture2D(sampler2D bitmap, vec2 coord)
{
vec4 color = texture2D(bitmap, coord);
if (!hasTransform)
{
return color;
}
if (color.a == 0.0)
{
return vec4(0.0, 0.0, 0.0, 0.0);
}
if (!hasColorTransform)
{
return color * openfl_Alphav;
}
color = vec4(color.rgb / color.a, color.a);
mat4 colorMultiplier = mat4(0);
colorMultiplier[0][0] = openfl_ColorMultiplierv.x;
colorMultiplier[1][1] = openfl_ColorMultiplierv.y;
colorMultiplier[2][2] = openfl_ColorMultiplierv.z;
colorMultiplier[3][3] = openfl_ColorMultiplierv.w;
color = clamp(openfl_ColorOffsetv + (color * colorMultiplier), 0.0, 1.0);
if (color.a > 0.0)
{
return vec4(color.rgb * color.a * openfl_Alphav, color.a * openfl_Alphav);
}
return vec4(0.0, 0.0, 0.0, 0.0);
}
";
#else
// No additional data.
;
#end
static final BASE_FRAGMENT_BODY:String = "
vec4 color = texture2D (bitmap, openfl_TextureCoordv);
if (color.a == 0.0) {
gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0);
} else if (openfl_HasColorTransform) {
color = vec4 (color.rgb / color.a, color.a);
mat4 colorMultiplier = mat4 (0);
colorMultiplier[0][0] = openfl_ColorMultiplierv.x;
colorMultiplier[1][1] = openfl_ColorMultiplierv.y;
colorMultiplier[2][2] = openfl_ColorMultiplierv.z;
colorMultiplier[3][3] = 1.0; // openfl_ColorMultiplierv.w;
color = clamp (openfl_ColorOffsetv + (color * colorMultiplier), 0.0, 1.0);
if (color.a > 0.0) {
gl_FragColor = vec4 (color.rgb * color.a * openfl_Alphav, color.a * openfl_Alphav);
} else {
gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0);
}
} else {
gl_FragColor = color * openfl_Alphav;
}
";
#if FLX_DRAW_QUADS
static final DEFAULT_FRAGMENT_SOURCE:String = "
#pragma header
void main(void)
{
gl_FragColor = flixel_texture2D(bitmap, openfl_TextureCoordv);
}
";
#else
static final DEFAULT_FRAGMENT_SOURCE:String = "
#pragma header
void main(void) {
#pragma body
}
";
#end
#if FLX_DRAW_QUADS
static final DEFAULT_VERTEX_SOURCE:String = "
#pragma header
attribute float alpha;
attribute vec4 colorMultiplier;
attribute vec4 colorOffset;
uniform bool hasColorTransform;
void main(void)
{
#pragma body
openfl_Alphav = openfl_Alpha * alpha;
if (hasColorTransform)
{
openfl_ColorOffsetv = colorOffset / 255.0;
openfl_ColorMultiplierv = colorMultiplier;
}
}
";
#else
static final DEFAULT_VERTEX_SOURCE:String = "
#pragma header
void main(void) {
#pragma body
}
";
#end
static final PRAGMA_HEADER:String = "#pragma header";
static final PRAGMA_BODY:String = "#pragma body";
static final PRAGMA_PRECISION:String = "#pragma precision";
static final PRAGMA_VERSION:String = "#pragma version";
private var _glslVersion:Int;
/**
* Constructs a GLSL shader.
* @param fragmentSource The fragment shader source.
* @param vertexSource The vertex shader source.
* Note you also need to `initialize()` the shader MANUALLY! It can't be done automatically.
*/
public function new(fragmentSource:String = null, vertexSource:String = null, glslVersion:Int = 120):Void
{
_glslVersion = glslVersion;
if (fragmentSource == null)
{
trace('Loading default fragment source...');
glFragmentSource = processFragmentSource(DEFAULT_FRAGMENT_SOURCE);
}
else
{
trace('Loading fragment source from argument...');
glFragmentSource = processFragmentSource(fragmentSource);
}
if (vertexSource == null)
{
var s = processVertexSource(DEFAULT_VERTEX_SOURCE);
glVertexSource = s;
}
else
{
var s = processVertexSource(vertexSource);
glVertexSource = s;
}
@:privateAccess {
// This tells the shader that the glVertexSource/glFragmentSource have been updated.
__glSourceDirty = true;
// This tells the shader that the shader properties are NOT reflected on this class automatically.
__isGenerated = false;
}
super();
}
/**
* Replace the `#pragma header` and `#pragma body` with the fragment shader header and body.
*/
function processFragmentSource(input:String):String
{
var result = StringTools.replace(input, PRAGMA_HEADER, BASE_FRAGMENT_HEADER);
result = StringTools.replace(result, PRAGMA_BODY, BASE_FRAGMENT_BODY);
return result;
}
/**
* Replace the `#pragma header` and `#pragma body` with the vertex shader header and body.
*/
function processVertexSource(input:String):String
{
var result = StringTools.replace(input, PRAGMA_HEADER, BASE_VERTEX_HEADER);
result = StringTools.replace(result, PRAGMA_BODY, BASE_VERTEX_BODY);
return result;
}
function buildPrecisionHeaders():String {
return "#ifdef GL_ES
" + (precisionHint == FULL ? "#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif" : "precision lowp float;")
+ "
#endif
";
}
/**
* The parent function that initializes the shader.
* This is done to add the `#version` shader directive.
*/
private override function __initGL():Void
{
if (__glSourceDirty || __paramBool == null)
{
__glSourceDirty = false;
program = null;
__inputBitmapData = new Array();
__paramBool = new Array();
__paramFloat = new Array();
__paramInt = new Array();
__processGLData(glVertexSource, "attribute");
__processGLData(glVertexSource, "uniform");
__processGLData(glFragmentSource, "uniform");
}
@:privateAccess
if (__context != null && program == null)
{
var gl = __context.gl;
var precisionHeaders = buildPrecisionHeaders();
var versionHeader = '#version ${_glslVersion}\n';
var vertex = StringTools.replace(glVertexSource, PRAGMA_PRECISION, precisionHeaders);
vertex = StringTools.replace(vertex, PRAGMA_VERSION, versionHeader);
var fragment = StringTools.replace(glFragmentSource, PRAGMA_PRECISION, precisionHeaders);
fragment = StringTools.replace(fragment, PRAGMA_VERSION, versionHeader);
var id = vertex + fragment;
if (__context.__programs.exists(id)) {
// Use the existing program if it has been compiled.
program = __context.__programs.get(id);
} else {
// Build the program.
program = __context.createProgram(GLSL);
program.__glProgram = __createGLProgram(vertex, fragment);
__context.__programs.set(id, program);
}
if (program != null) {
glProgram = program.__glProgram;
// Map attributes for each type.
for (input in __inputBitmapData) {
if (input.__isUniform) {
input.index = gl.getUniformLocation(glProgram, input.name);
} else {
input.index = gl.getAttribLocation(glProgram, input.name);
}
}
for (parameter in __paramBool) {
if (parameter.__isUniform) {
parameter.index = gl.getUniformLocation(glProgram, parameter.name);
} else {
parameter.index = gl.getAttribLocation(glProgram, parameter.name);
}
}
for (parameter in __paramFloat) {
if (parameter.__isUniform) {
parameter.index = gl.getUniformLocation(glProgram, parameter.name);
} else {
parameter.index = gl.getAttribLocation(glProgram, parameter.name);
}
}
for (parameter in __paramInt) {
if (parameter.__isUniform) {
parameter.index = gl.getUniformLocation(glProgram, parameter.name);
} else {
parameter.index = gl.getAttribLocation(glProgram, parameter.name);
}
}
}
}
}
private var __fieldList:Array<String> = null;
private function thisHasField(name:String) {
// Reflect.hasField(this, name) is REALLY expensive so we use a cache.
if (__fieldList == null) {
__fieldList = Reflect.fields(this)
.concat(Type.getInstanceFields(Type.getClass(this)));
}
return __fieldList.indexOf(name) != -1;
}
/**
* The parent function that initializes the shader.
* This is done because some shader fields (such as `bitmap`) have to automatically propagate from the shader,
* but others may not exist or be properties rather than fields.
*/
private override function __processGLData(source:String, storageType:String):Void
{
var position;
var name;
var type;
var regex = (storageType == "uniform")
? ~/uniform ([A-Za-z0-9]+) ([A-Za-z0-9_]+)/
: ~/attribute ([A-Za-z0-9]+) ([A-Za-z0-9_]+)/;
var lastMatch = 0;
@:privateAccess
while (regex.matchSub(source, lastMatch)) {
type = regex.matched(1);
name = regex.matched(2);
if (StringTools.startsWith(name, "gl_")) {
continue;
}
var isUniform = (storageType == "uniform");
if (StringTools.startsWith(type, "sampler")) {
var input = new ShaderInput<BitmapData>();
input.name = name;
input.__isUniform = isUniform;
__inputBitmapData.push(input);
switch (name) {
case "openfl_Texture":
__texture = input;
case "bitmap":
__bitmap = input;
default:
}
Reflect.setField(__data, name, input);
if (__isGenerated && thisHasField(name)) Reflect.setProperty(this, name, input);
} else if (!Reflect.hasField(__data, name) || Reflect.field(__data, name) == null) {
var parameterType:ShaderParameterType = switch (type)
{
case "bool": BOOL;
case "double", "float": FLOAT;
case "int", "uint": INT;
case "bvec2": BOOL2;
case "bvec3": BOOL3;
case "bvec4": BOOL4;
case "ivec2", "uvec2": INT2;
case "ivec3", "uvec3": INT3;
case "ivec4", "uvec4": INT4;
case "vec2", "dvec2": FLOAT2;
case "vec3", "dvec3": FLOAT3;
case "vec4", "dvec4": FLOAT4;
case "mat2", "mat2x2": MATRIX2X2;
case "mat2x3": MATRIX2X3;
case "mat2x4": MATRIX2X4;
case "mat3x2": MATRIX3X2;
case "mat3", "mat3x3": MATRIX3X3;
case "mat3x4": MATRIX3X4;
case "mat4x2": MATRIX4X2;
case "mat4x3": MATRIX4X3;
case "mat4", "mat4x4": MATRIX4X4;
default: null;
}
var length = switch (parameterType)
{
case BOOL2, INT2, FLOAT2: 2;
case BOOL3, INT3, FLOAT3: 3;
case BOOL4, INT4, FLOAT4, MATRIX2X2: 4;
case MATRIX3X3: 9;
case MATRIX4X4: 16;
default: 1;
}
var arrayLength = switch (parameterType)
{
case MATRIX2X2: 2;
case MATRIX3X3: 3;
case MATRIX4X4: 4;
default: 1;
}
switch (parameterType)
{
case BOOL, BOOL2, BOOL3, BOOL4:
var parameter = new ShaderParameter<Bool>();
parameter.name = name;
parameter.type = parameterType;
parameter.__arrayLength = arrayLength;
parameter.__isBool = true;
parameter.__isUniform = isUniform;
parameter.__length = length;
__paramBool.push(parameter);
if (name == "openfl_HasColorTransform")
{
__hasColorTransform = parameter;
}
Reflect.setField(__data, name, parameter);
if (__isGenerated && thisHasField(name)) Reflect.setProperty(this, name, parameter);
case INT, INT2, INT3, INT4:
var parameter = new ShaderParameter<Int>();
parameter.name = name;
parameter.type = parameterType;
parameter.__arrayLength = arrayLength;
parameter.__isInt = true;
parameter.__isUniform = isUniform;
parameter.__length = length;
__paramInt.push(parameter);
Reflect.setField(__data, name, parameter);
if (__isGenerated && thisHasField(name)) Reflect.setProperty(this, name, parameter);
default:
var parameter = new ShaderParameter<Float>();
parameter.name = name;
parameter.type = parameterType;
parameter.__arrayLength = arrayLength;
#if lime
if (arrayLength > 0) parameter.__uniformMatrix = new Float32Array(arrayLength * arrayLength);
#end
parameter.__isFloat = true;
parameter.__isUniform = isUniform;
parameter.__length = length;
__paramFloat.push(parameter);
if (StringTools.startsWith(name, "openfl_"))
{
switch (name)
{
case "openfl_Alpha": __alpha = parameter;
case "openfl_ColorMultiplier": __colorMultiplier = parameter;
case "openfl_ColorOffset": __colorOffset = parameter;
case "openfl_Matrix": __matrix = parameter;
case "openfl_Position": __position = parameter;
case "openfl_TextureCoord": __textureCoord = parameter;
case "openfl_TextureSize": __textureSize = parameter;
default:
}
}
Reflect.setField(__data, name, parameter);
if (__isGenerated && thisHasField(name)) Reflect.setProperty(this, name, parameter);
}
}
position = regex.matchedPos();
lastMatch = position.pos + position.len;
}
}
/**
* Modify a float parameter of the shader.
* @param name The name of the parameter to modify.
* @param value The new value to use.
*/
public function setFloat(name:String, value:Float):Void
{
var prop:ShaderParameter<Float> = Reflect.field(this.data, name);
@:privateAccess
if (prop == null)
{
trace('[WARN] Shader float property ${name} not found.');
return;
}
prop.value = [value];
}
/**
* Modify a float array parameter of the shader.
* @param name The name of the parameter to modify.
* @param value The new value to use.
*/
public function setFloatArray(name:String, value:Array<Float>):Void
{
var prop:ShaderParameter<Float> = Reflect.field(this.data, name);
if (prop == null)
{
trace('[WARN] Shader float[] property ${name} not found.');
return;
}
prop.value = value;
}
/**
* Modify an integer parameter of the shader.
* @param name The name of the parameter to modify.
* @param value The new value to use.
*/
public function setInt(name:String, value:Int):Void
{
var prop:ShaderParameter<Int> = Reflect.field(this.data, name);
if (prop == null)
{
trace('[WARN] Shader int property ${name} not found.');
return;
}
prop.value = [value];
}
/**
* Modify an integer array parameter of the shader.
* @param name The name of the parameter to modify.
* @param value The new value to use.
*/
public function setIntArray(name:String, value:Array<Int>):Void
{
var prop:ShaderParameter<Int> = Reflect.field(this.data, name);
if (prop == null)
{
trace('[WARN] Shader int[] property ${name} not found.');
return;
}
prop.value = value;
}
/**
* Modify a boolean parameter of the shader.
* @param name The name of the parameter to modify.
* @param value The new value to use.
*/
public function setBool(name:String, value:Bool):Void
{
var prop:ShaderParameter<Bool> = Reflect.field(this.data, name);
if (prop == null)
{
trace('[WARN] Shader bool property ${name} not found.');
return;
}
prop.value = [value];
}
/**
* Modify a boolean array parameter of the shader.
* @param name The name of the parameter to modify.
* @param value The new value to use.
*/
public function setBoolArray(name:String, value:Array<Bool>):Void
{
var prop:ShaderParameter<Bool> = Reflect.field(this.data, name);
if (prop == null)
{
trace('[WARN] Shader bool[] property ${name} not found.');
return;
}
prop.value = value;
}
/**
* Set or modify a sampler2D input of the shader.
* @param name The name of the shader input to modify.
* @param value The texture to use as the sampler2D input.
*/
public function setSampler2D(name:String, value:BitmapData)
{
var prop:ShaderInput<BitmapData> = Reflect.field(this.data, name);
if(prop == null)
{
trace('[WARNING] Shader sampler2D property ${name} not found.');
return;
}
prop.input = value;
}
/**
* Retrieve a float parameter of the shader.
* @param name The name of the parameter to retrieve.
*/
public function getFloat(name:String):Null<Float>
{
var prop:ShaderParameter<Float> = Reflect.field(this.data, name);
if (prop == null || prop.value.length == 0)
{
trace('[WARN] Shader float property ${name} not found.');
return null;
}
return prop.value[0];
}
/**
* Retrieve a float array parameter of the shader.
* @param name The name of the parameter to retrieve.
*/
public function getFloatArray(name:String):Null<Array<Float>>
{
var prop:ShaderParameter<Float> = Reflect.field(this.data, name);
if (prop == null)
{
trace('[WARN] Shader float[] property ${name} not found.');
return null;
}
return prop.value;
}
/**
* Retrieve an integer parameter of the shader.
* @param name The name of the parameter to retrieve.
*/
public function getInt(name:String):Null<Int>
{
var prop:ShaderParameter<Int> = Reflect.field(this.data, name);
if (prop == null || prop.value.length == 0)
{
trace('[WARN] Shader int property ${name} not found.');
return null;
}
return prop.value[0];
}
/**
* Retrieve an integer array parameter of the shader.
* @param name The name of the parameter to retrieve.
*/
public function getIntArray(name:String):Null<Array<Int>>
{
var prop:ShaderParameter<Int> = Reflect.field(this.data, name);
if (prop == null)
{
trace('[WARN] Shader int[] property ${name} not found.');
return null;
}
return prop.value;
}
/**
* Retrieve a boolean parameter of the shader.
* @param name The name of the parameter to retrieve.
*/
public function getBool(name:String):Null<Bool>
{
var prop:ShaderParameter<Bool> = Reflect.field(this.data, name);
if (prop == null || prop.value.length == 0)
{
trace('[WARN] Shader bool property ${name} not found.');
return null;
}
return prop.value[0];
}
/**
* Retrieve a boolean array parameter of the shader.
* @param name The name of the parameter to retrieve.
*/
public function getBoolArray(name:String):Null<Array<Bool>>
{
var prop:ShaderParameter<Bool> = Reflect.field(this.data, name);
if (prop == null)
{
trace('[WARN] Shader bool[] property ${name} not found.');
return null;
}
return prop.value;
}
public function toString():String
{
return 'FlxRuntimeShader';
}
}

View File

@ -0,0 +1,22 @@
package openfl.utils;
/**
The AssetType enum lists the core set of available
asset types from the OpenFL command-line tools.
**/
@:enum abstract AssetType(String)
{
public var DATA = "DATA";
public var FONT = "FONT";
public var SHARED = "SHARED";
public var SONG = "SONGS";
public var MUSIC = "MUSIC";
public var SOUND = "SOUNDS";
public var SCRIPT = "SCRIPTS";
public var SHADER = "SHADERS";
public var WEEK = "WEEKS";
public var IMAGE = "IMAGES";
public var VIDEO = "VIDEOS";
public var MOVIE_CLIP = "MOVIE_CLIP";
public var TEXT = "TEXT";
}

View File

@ -30,7 +30,7 @@ class ModMenu extends ui.OptionsState.Page
var descriptionText:FlxText;
var descBg:FlxSprite;
public static var MOD_PATH = "./mods";
public static var MOD_PATH = "mods";
public function new():Void
{
@ -163,6 +163,8 @@ class ModMenu extends ui.OptionsState.Page
trace(i.id);
var txt:ModMenuItem = new ModMenuItem(0, 10 + (40 * loopNum), 0, i.id, 32);
txt.text = i.id;
if (enabledMods.contains(i.id))
txt.modEnabled = true;
grpMods.add(txt);
loopNum++;

View File

@ -39,6 +39,8 @@ class PreferencesMenu extends ui.OptionsState.Page
createPrefItem('Auto Pause', 'auto-pause', false);
createPrefItem('Ghost Tapping', 'ghosttapping', true);
createPrefItem('Visible Combo Sprite', 'vcombospr', false);
createPrefItem('Shaders', 'shaders', true);
createPrefItem('Antialiasing', 'antialiasing', true);
camFollow = new FlxObject(FlxG.width / 2, 0, 140, 70);
if (items != null)
@ -78,6 +80,8 @@ class PreferencesMenu extends ui.OptionsState.Page
preferenceCheck('master-volume', 1);
preferenceCheck('ghosttapping', true);
preferenceCheck('vcombospr', false);
preferenceCheck('shaders', true);
preferenceCheck('antialiasing', true);
#if muted
setPref('master-volume', 0);