amgus
amgus
This commit is contained in:
commit
4c47464a2e
123
ModCharts.md
Normal file
123
ModCharts.md
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# Kade Engine Lua Mod Chart Documentation
|
||||||
|
|
||||||
|
In the latest version of Kade Engine we introduced Mod Charts. Mod Charts are a way of changing gameplay without hard coded values, this is achieved by using the Lua Scripting language to create script files that run during runtime.
|
||||||
|
|
||||||
|
All files **are located in** `assets/data/song/modchart.lua`
|
||||||
|
|
||||||
|
Lua code will only be ran if that file exists.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
Full Example
|
||||||
|
|
||||||
|
```lua
|
||||||
|
function start (song)
|
||||||
|
print("Song: " .. song .. " @ " .. bpm .. " donwscroll: " .. downscroll)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function update (elapsed) -- example https://twitter.com/KadeDeveloper/status/1382178179184422918
|
||||||
|
local currentBeat = (songPos / 1000)*(bpm/60)
|
||||||
|
for i=0,7 do
|
||||||
|
_G['strum'..i..'X'] = _G['defaultStrum'..i..'X'] + 32 * math.sin((currentBeat + i*0.25) * math.pi)
|
||||||
|
_G['strum'..i..'Y'] = _G['defaultStrum'..i..'Y'] + 32 * math.cos((currentBeat + i*0.25) * math.pi)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function beatHit (beat)
|
||||||
|
-- do nothing
|
||||||
|
end
|
||||||
|
|
||||||
|
function stepHit (step)
|
||||||
|
-- do nothing
|
||||||
|
end
|
||||||
|
|
||||||
|
print("Mod Chart script loaded :)")
|
||||||
|
```
|
||||||
|
|
||||||
|
Spinning Receptor Example
|
||||||
|
|
||||||
|
```lua
|
||||||
|
function update (elapsed)
|
||||||
|
for i=0,7 do
|
||||||
|
_G['strum'..i..'Angle'] = _G['strum'..i..'Angle'] + 15
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Spinning Hud Example
|
||||||
|
|
||||||
|
```lua
|
||||||
|
function update (elapsed)
|
||||||
|
camHudAngle = camHudAngle + 0.005
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Spin at a specific part of the song
|
||||||
|
|
||||||
|
```lua
|
||||||
|
function update (elapsed)
|
||||||
|
if curStep >= 352 and curStep < 400 then
|
||||||
|
local currentBeat = (songPos / 1000)*(bpm/60)
|
||||||
|
for i=0,7 do
|
||||||
|
_G['strum'..i..'X'] = _G['defaultStrum'..i..'X'] + 32 * math.sin((currentBeat + i*0.25) * math.pi)
|
||||||
|
_G['strum'..i..'Y'] = _G['defaultStrum'..i..'Y'] + 32 * math.cos((currentBeat + i*0.25) * math.pi)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
_G['strum'..i..'X'] = _G['defaultStrum'..i..'X']
|
||||||
|
_G['strum'..i..'Y'] = _G['defaultStrum'..i..'Y']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Showing/Hiding receptors/the hud
|
||||||
|
|
||||||
|
```lua
|
||||||
|
function start (song)
|
||||||
|
showOnlyStrums = true -- remove all hud elements besides notes and strums
|
||||||
|
_G['strumLine1Visible'] = false -- remove the first line of strums (the ai notes)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Available Hooks
|
||||||
|
|
||||||
|
Current calls to functions include,
|
||||||
|
|
||||||
|
| Name | Arguments | Description |
|
||||||
|
| :-----: | :------------: | :----------------------------------------------------------: |
|
||||||
|
| start | Song Name | Get's called when the song starts |
|
||||||
|
| update | Elapsed frames | Get's called every frame (after the song starts) |
|
||||||
|
| stepHit | Current Step | Get's called when ever a step hits (steps are in between beats, aka 4 steps are in a beat) |
|
||||||
|
| beatHit | Current Beat | Get's called when ever a beat hits |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Global Variables
|
||||||
|
|
||||||
|
Kade Engine provides a list of global variables to be used in the lua scripting interface.
|
||||||
|
|
||||||
|
| G Name | Type | Description |
|
||||||
|
| :------------------: | :---: | :----------------------------------------------------------: |
|
||||||
|
| bpm | Float | The current BPM of the song |
|
||||||
|
| fpsCap | Int | The current FPS Cap (set by the player) |
|
||||||
|
| downscroll | Bool | Whether the player is in downscroll or not |
|
||||||
|
| hudZoom | Float | The amount of zoom the Hud should be zoomed in/out |
|
||||||
|
| cameraZoom | Float | The amount of zoom the Main Camera should be zoomed in/out |
|
||||||
|
| cameraAngle | Float | The angle that the Main Camera should be rotated |
|
||||||
|
| camHudAngle | Float | The angle that the Hud should be rotated |
|
||||||
|
| followXOffset | Float | The x offset to be added when the camera moves between a character |
|
||||||
|
| followYOffset | Float | The y offset to be added when the camera moves between a character |
|
||||||
|
| showOnlyStrums | Bool | Whether to show the Hud and Strums or only the Strums |
|
||||||
|
| strumLine1Visible | Bool | Whether to show the first strum line or not |
|
||||||
|
| strumLine2Visible | Bool | Whether to show the secondstrum line or not |
|
||||||
|
| strum0-7X | Float | (0-7 is strum0,strum1,strum2,etc) get/set the X coordinate for the strum |
|
||||||
|
| strum0-7Y | Float | (0-7 is strum0,strum1,strum2,etc) get/set the Y coordinate for the strum |
|
||||||
|
| strum0-7Angle | Float | (0-7 is strum0,strum1,strum2,etc) get/set the Angle for the strum |
|
||||||
|
| defaultStrum0-7X | Float | (0-7 is strum0,strum1,strum2,etc) get the default X coordinate for the strum |
|
||||||
|
| defaultStrum0-7Y | Float | (0-7 is strum0,strum1,strum2,etc) get the default Y coordinate for the strum |
|
||||||
|
| defaultStrum0-7Angle | Float | (0-7 is strum0,strum1,strum2,etc) get the default Angle for the strum |
|
||||||
|
|
@ -55,7 +55,7 @@ class FreeplayState extends MusicBeatState
|
|||||||
|
|
||||||
#if windows
|
#if windows
|
||||||
// Updating Discord Rich Presence
|
// Updating Discord Rich Presence
|
||||||
DiscordClient.changePresence("In the Menus", null);
|
DiscordClient.changePresence("In the Freeplay Menu", null);
|
||||||
#end
|
#end
|
||||||
|
|
||||||
var isDebug:Bool = false;
|
var isDebug:Bool = false;
|
||||||
|
@ -21,6 +21,9 @@ class PauseSubState extends MusicBeatSubstate
|
|||||||
var curSelected:Int = 0;
|
var curSelected:Int = 0;
|
||||||
|
|
||||||
var pauseMusic:FlxSound;
|
var pauseMusic:FlxSound;
|
||||||
|
var perSongOffset:FlxText;
|
||||||
|
|
||||||
|
var offsetChanged:Bool = false;
|
||||||
|
|
||||||
public function new(x:Float, y:Float)
|
public function new(x:Float, y:Float)
|
||||||
{
|
{
|
||||||
@ -63,6 +66,10 @@ class PauseSubState extends MusicBeatSubstate
|
|||||||
|
|
||||||
grpMenuShit = new FlxTypedGroup<Alphabet>();
|
grpMenuShit = new FlxTypedGroup<Alphabet>();
|
||||||
add(grpMenuShit);
|
add(grpMenuShit);
|
||||||
|
perSongOffset = new FlxText(5, FlxG.height - 18, 0, "Additive Offset (Left, Right): " + PlayState.songOffset + " - Description - " + 'Adds value to global offset, per song.', 12);
|
||||||
|
perSongOffset.scrollFactor.set();
|
||||||
|
perSongOffset.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
|
||||||
|
add(perSongOffset);
|
||||||
|
|
||||||
for (i in 0...menuItems.length)
|
for (i in 0...menuItems.length)
|
||||||
{
|
{
|
||||||
@ -86,15 +93,71 @@ class PauseSubState extends MusicBeatSubstate
|
|||||||
|
|
||||||
var upP = controls.UP_P;
|
var upP = controls.UP_P;
|
||||||
var downP = controls.DOWN_P;
|
var downP = controls.DOWN_P;
|
||||||
|
var leftP = controls.LEFT_P;
|
||||||
|
var rightP = controls.RIGHT_P;
|
||||||
var accepted = controls.ACCEPT;
|
var accepted = controls.ACCEPT;
|
||||||
|
var oldOffset:Float = 0;
|
||||||
|
var songPath = 'assets/data/' + PlayState.SONG.song.toLowerCase() + '/';
|
||||||
|
|
||||||
if (upP)
|
if (upP)
|
||||||
{
|
{
|
||||||
changeSelection(-1);
|
changeSelection(-1);
|
||||||
}
|
|
||||||
if (downP)
|
}else if (downP)
|
||||||
{
|
{
|
||||||
changeSelection(1);
|
changeSelection(1);
|
||||||
|
}else if (leftP)
|
||||||
|
{
|
||||||
|
oldOffset = PlayState.songOffset;
|
||||||
|
PlayState.songOffset -= 1;
|
||||||
|
sys.FileSystem.rename(songPath + oldOffset + '.offset', songPath + PlayState.songOffset + '.offset');
|
||||||
|
perSongOffset.text = "Additive Offset (Left, Right): " + PlayState.songOffset + " - Description - " + 'Adds value to global offset, per song.';
|
||||||
|
|
||||||
|
// Prevent loop from happening every single time the offset changes
|
||||||
|
if(!offsetChanged)
|
||||||
|
{
|
||||||
|
grpMenuShit.clear();
|
||||||
|
|
||||||
|
menuItems = ['Restart Song', 'Exit to menu'];
|
||||||
|
|
||||||
|
for (i in 0...menuItems.length)
|
||||||
|
{
|
||||||
|
var songText:Alphabet = new Alphabet(0, (70 * i) + 30, menuItems[i], true, false);
|
||||||
|
songText.isMenuItem = true;
|
||||||
|
songText.targetY = i;
|
||||||
|
grpMenuShit.add(songText);
|
||||||
|
}
|
||||||
|
|
||||||
|
changeSelection();
|
||||||
|
|
||||||
|
cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]];
|
||||||
|
offsetChanged = true;
|
||||||
|
}
|
||||||
|
}else if (rightP)
|
||||||
|
{
|
||||||
|
oldOffset = PlayState.songOffset;
|
||||||
|
PlayState.songOffset += 1;
|
||||||
|
sys.FileSystem.rename(songPath + oldOffset + '.offset', songPath + PlayState.songOffset + '.offset');
|
||||||
|
perSongOffset.text = "Additive Offset (Left, Right): " + PlayState.songOffset + " - Description - " + 'Adds value to global offset, per song.';
|
||||||
|
if(!offsetChanged)
|
||||||
|
{
|
||||||
|
grpMenuShit.clear();
|
||||||
|
|
||||||
|
menuItems = ['Restart Song', 'Exit to menu'];
|
||||||
|
|
||||||
|
for (i in 0...menuItems.length)
|
||||||
|
{
|
||||||
|
var songText:Alphabet = new Alphabet(0, (70 * i) + 30, menuItems[i], true, false);
|
||||||
|
songText.isMenuItem = true;
|
||||||
|
songText.targetY = i;
|
||||||
|
grpMenuShit.add(songText);
|
||||||
|
}
|
||||||
|
|
||||||
|
changeSelection();
|
||||||
|
|
||||||
|
cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]];
|
||||||
|
offsetChanged = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accepted)
|
if (accepted)
|
||||||
|
@ -39,6 +39,7 @@ import lime.utils.Assets;
|
|||||||
import openfl.display.BlendMode;
|
import openfl.display.BlendMode;
|
||||||
import openfl.display.StageQuality;
|
import openfl.display.StageQuality;
|
||||||
import openfl.filters.ShaderFilter;
|
import openfl.filters.ShaderFilter;
|
||||||
|
import Sys;
|
||||||
|
|
||||||
#if windows
|
#if windows
|
||||||
import Discord.DiscordClient;
|
import Discord.DiscordClient;
|
||||||
@ -180,6 +181,8 @@ class PlayState extends MusicBeatState
|
|||||||
|
|
||||||
// Will decide if she's even allowed to headbang at all depending on the song
|
// Will decide if she's even allowed to headbang at all depending on the song
|
||||||
private var allowedToHeadbang:Bool = false;
|
private var allowedToHeadbang:Bool = false;
|
||||||
|
// Per song additive offset
|
||||||
|
public static var songOffset:Float = 0;
|
||||||
|
|
||||||
override public function create()
|
override public function create()
|
||||||
{
|
{
|
||||||
@ -1226,6 +1229,24 @@ class PlayState extends MusicBeatState
|
|||||||
|
|
||||||
var playerCounter:Int = 0;
|
var playerCounter:Int = 0;
|
||||||
|
|
||||||
|
// Per song offset check
|
||||||
|
var songPath = 'assets/data/' + PlayState.SONG.song.toLowerCase() + '/';
|
||||||
|
for(file in sys.FileSystem.readDirectory(songPath))
|
||||||
|
{
|
||||||
|
var path = haxe.io.Path.join([songPath, file]);
|
||||||
|
if(!sys.FileSystem.isDirectory(path))
|
||||||
|
{
|
||||||
|
if(path.endsWith('.offset'))
|
||||||
|
{
|
||||||
|
trace('Found offset file: ' + path);
|
||||||
|
songOffset = Std.parseFloat(file.substring(0, file.indexOf('.off')));
|
||||||
|
break;
|
||||||
|
}else {
|
||||||
|
trace('Offset file not found. Creating one @: ' + songPath);
|
||||||
|
sys.io.File.saveContent(songPath + songOffset + '.offset', '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
var daBeats:Int = 0; // Not exactly representative of 'daBeats' lol, just how much it has looped
|
var daBeats:Int = 0; // Not exactly representative of 'daBeats' lol, just how much it has looped
|
||||||
for (section in noteData)
|
for (section in noteData)
|
||||||
{
|
{
|
||||||
@ -1233,7 +1254,7 @@ class PlayState extends MusicBeatState
|
|||||||
|
|
||||||
for (songNotes in section.sectionNotes)
|
for (songNotes in section.sectionNotes)
|
||||||
{
|
{
|
||||||
var daStrumTime:Float = songNotes[0] + FlxG.save.data.offset;
|
var daStrumTime:Float = songNotes[0] + FlxG.save.data.offset + songOffset;
|
||||||
if (daStrumTime < 0)
|
if (daStrumTime < 0)
|
||||||
daStrumTime = 0;
|
daStrumTime = 0;
|
||||||
var daNoteData:Int = Std.int(songNotes[1] % 4);
|
var daNoteData:Int = Std.int(songNotes[1] % 4);
|
||||||
@ -3249,4 +3270,4 @@ class PlayState extends MusicBeatState
|
|||||||
}
|
}
|
||||||
|
|
||||||
var curLight:Int = 0;
|
var curLight:Int = 0;
|
||||||
}
|
}
|
@ -76,7 +76,7 @@ class StoryMenuState extends MusicBeatState
|
|||||||
{
|
{
|
||||||
#if windows
|
#if windows
|
||||||
// Updating Discord Rich Presence
|
// Updating Discord Rich Presence
|
||||||
DiscordClient.changePresence("In the Menus", null);
|
DiscordClient.changePresence("In the Story Mode Menu", null);
|
||||||
#end
|
#end
|
||||||
|
|
||||||
transIn = FlxTransitionableState.defaultTransIn;
|
transIn = FlxTransitionableState.defaultTransIn;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user