Merge pull request #923 from KadeDev/master

Master
This commit is contained in:
Kade M 2021-06-19 16:12:53 -07:00 committed by GitHub
commit 48e6a0597d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 2029 additions and 915 deletions

View File

@ -112,6 +112,9 @@
<haxelib name="flixel-addons" /> <haxelib name="flixel-addons" />
<haxelib name="hscript" /> <haxelib name="hscript" />
<haxelib name="actuate" />
<haxelib name="extension-webm"/> <!-- Make sure to use https://github.com/KadeDev/extension-webm/ -->
<!--In case you want to use the ui package--> <!--In case you want to use the ui package-->
<haxelib name="flixel-ui" /> <haxelib name="flixel-ui" />
<haxelib name="newgrounds"/> <haxelib name="newgrounds"/>

View File

@ -60,3 +60,9 @@ This game was made with love to Newgrounds and its community. Extra love to Tom
### Kade Engine ### Kade Engine
- [KadeDeveloper](https://twitter.com/KadeDeveloper) - Maintainer and lead programmer - [KadeDeveloper](https://twitter.com/KadeDeveloper) - Maintainer and lead programmer
- [The contributors](https://github.com/KadeDev/Kade-Engine/graphs/contributors) - [The contributors](https://github.com/KadeDev/Kade-Engine/graphs/contributors)
### Shoutouts
- [GWebDev](https://github.com/GrowtopiaFli) - Video Code
- [Rozebud](https://github.com/ThatRozebudDude) - Ideas (that I stole)
- [Puyo](https://github.com/daniel11420) - Setting up appveyor and a lot of other help

Binary file not shown.

View File

@ -26,7 +26,7 @@ hr {
<p id="HtmlIsTheWorstThingIHaveEverUsed"> <p id="HtmlIsTheWorstThingIHaveEverUsed">
<a class="headerlink" href="{{site.url}}changelogs/">Changelogs</a> <a class="headerlink" href="{{site.url}}changelogs/">Changelogs</a>
<a class="headerlink" href="{{site.url}}building">Building</a> <a class="headerlink" href="{{site.url}}building">Building</a>
<a class="headerlink" href="{{site.url}}modchart">Modcharts</a> <a class="headerlink" href="https://github.com/KadeDev/Kade-Engine/wiki/">Modchart Documentation</a>
<a class="headerlink" href="{{site.url}}guides">Guides</a> <a class="headerlink" href="{{site.url}}guides">Guides</a>
<br>&nbsp; <br>&nbsp;
<hr> <hr>

View File

@ -28,6 +28,9 @@
- `haxelib git faxe https://github.com/uhrobots/faxe` - `haxelib git faxe https://github.com/uhrobots/faxe`
- `haxelib git polymod https://github.com/larsiusprime/polymod.git` - `haxelib git polymod https://github.com/larsiusprime/polymod.git`
- `haxelib git discord_rpc https://github.com/Aidan63/linc_discord-rpc` - `haxelib git discord_rpc https://github.com/Aidan63/linc_discord-rpc`
- `haxelib install actuate`
- `haxelib git extension-webm https://github.com/KadeDev/extension-webm`
- `lime rebuild extension-webm windows`
### Windows-only dependencies (only for building *to* Windows. Building html5 on Windows does not require this) ### Windows-only dependencies (only for building *to* Windows. Building html5 on Windows does not require this)
If you are planning to build for Windows, you also need to install **Visual Studio 2019**. While installing it, *don't click on any of the options to install workloads*. Instead, go to the **individual components** tab and choose the following: If you are planning to build for Windows, you also need to install **Visual Studio 2019**. While installing it, *don't click on any of the options to install workloads*. Instead, go to the **individual components** tab and choose the following:

View File

@ -0,0 +1,16 @@
# Latest (master) changelog
Changes marked with 💖 will be listed in the short version of the changelog in `version.downloadMe`.
### Additions
- Score Screen (💖)
- Show your highest combo in the freeplay menu
- New asset loading system (💖)
- New Logo (💖)
### Changes
- Rewrote the entire hit ranking system (💖)
### Bugfixes
- NPS not showing if accuracy is disabled
- Fixed song names so they don't crash (💖)

View File

@ -1,6 +1,7 @@
# Changelogs # Changelogs
- [Latest](latest) (Contains changes that are not in a release yet) - [Latest](latest) (Contains changes that are not in a release yet)
- [1.5.3](changelog-1.5.3)
- [1.5.2](changelog-1.5.2) - [1.5.2](changelog-1.5.2)
- [1.5.1](changelog-1.5.1) - [1.5.1](changelog-1.5.1)
- [1.5.0](changelog-1.5.0) - [1.5.0](changelog-1.5.0)

View File

@ -3,10 +3,10 @@
Changes marked with 💖 will be listed in the short version of the changelog in `version.downloadMe`. Changes marked with 💖 will be listed in the short version of the changelog in `version.downloadMe`.
### Additions ### Additions
- Nothing here yet! - Nothing yet!
### Changes ### Changes
- Nothing here yet! - Nothing yet!
### Bugfixes ### Bugfixes
- Nothing here yet! - Nothing yet!

View File

@ -1,531 +1,2 @@
# Lua Modcharts ### RELOCATED
Relocated to [here](https://github.com/KadeDev/Kade-Engine/wiki/)
In the 1.4.2 release 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.
Song data is located in `assets/data/<song>/`, so the Lua file containing your scripts should be located at exactly `assets/data/<song>/modchart.lua`. (replace <song> with the name of the song. for example, `assets/data/milf/` for milf)
If the file doesn't exist, Lua code won't be ran.
## Examples
Full Example
```lua
function start (song)
print("Song: " .. song .. " @ " .. bpm .. " downscroll: " .. downscroll)
end
function update (elapsed) -- example https://twitter.com/KadeDeveloper/status/1382178179184422918
local currentBeat = (songPos / 1000)*(bpm/60)
for i=0,7 do
setActorX(_G['defaultStrum'..i..'X'] + 32 * math.sin((currentBeat + i*0.25) * math.pi), i)
setActorY(_G['defaultStrum'..i..'Y'] + 32 * math.cos((currentBeat + i*0.25) * math.pi), i)
end
end
function beatHit (beat)
-- do nothing
end
function stepHit (step)
-- do nothing
end
function keyPressed (key)
-- do nothing
end
print("Mod Chart script loaded :)")
```
Spinning Receptor Example
```lua
function update (elapsed)
for i=0,7 do
setActorAngle(getActorAngle(i) + 15, i)
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
setActorX(_G['defaultStrum'..i..'X'] + 32 * math.sin((currentBeat + i*0.25) * math.pi), i)
setActorY(_G['defaultStrum'..i..'Y'] + 32 * math.cos((currentBeat + i*0.25) * math.pi), i)
end
else
for i=0,7 do
setActorX(_G['defaultStrum'..i..'X'],i)
setActorY(_G['defaultStrum'..i..'Y'],i)
end
end
end
```
Showing/Hiding receptors/the hud
```lua
function start (song)
showOnlyStrums = true -- remove all hud elements besides notes and strums
for i=0,3 do -- fade out the first 4 receptors (the ai receptors)
tweenFadeIn(i,0,0.6)
end
end
```
Looping through all of the rendered notes
```lua
for i = 0, getRenderedNotes() do -- sets all of the rendered notes to 0 0 on the x and y axsis
setRenderedNotePos(0,0,i)
end
```
Centering BF's Side
```lua
function setDefault(id)
_G['defaultStrum'..id..'X'] = getActorX(id)
end
-- put this somewhere in a function
for i = 4, 7 do -- go to the center
tweenPosXAngle(i, _G['defaultStrum'..i..'X'] - 275,getActorAngle(i) + 360, 0.6, 'setDefault')
end
```
Jumping Arrows Example
```lua
function stepHit (step)
if step == 1 then
setActorAccelerationY(100, 4)
end
if step == 3 then
setActorAccelerationY(100, 5)
end
if step == 5 then
setActorAccelerationY(100, 6)
end
if step == 7 then
setActorAccelerationY(100, 7)
end
for i=4,7 do
if getActorY(i) >= 100 then
setActorY(100, i)
setActorVelocityY(-100, i)
end
end
end
```
### Available Hooks
Current calls to functions include,
| Name | Arguments | Description |
| :-----: | :------------: | :----------------------------------------------------------: |
| start | Song Name | Gets called when the song starts |
| update | Elapsed frames | Gets called every frame (after the song starts) |
| stepHit | Current Step | Gets called when ever a step hits (steps are in between beats, aka 4 steps are in a beat) |
| beatHit | Current Beat | Gets called when ever a beat hits |
| keyPressed | Key Pressed | Gets called when a key just got pressed (up, down, left, right, accept) |
### 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 |
| 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 |
| 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 |
| screenWidth | Int | The width of the current gamespace |
| screenHeight | Int | The height of the current gamespace |
| hudWidth | Int | The width of the hud |
| hudHeight | Int | The height of the hud |
| scrollSpeed | Int | The current scrollspeed |
| mustHit | Bool | If the current section is a must hit section |
| strumLineY | Float | The current Strum Line Y Position |
## Functions
Kade Engine exposes a lot of functions that let you modify elements in the game field.
To get started every sprite has an id, and there are some id's that are accessible without creating one.
These premade id's are the following:
| Sprite Id | Value |
| :--------: | :--------------------------------------: |
| 0-7 | Represents Receptor 0-7 |
| boyfriend | Represents the Boyfriend Actor (player1) |
| dad | Represents the Dad Actor (player2) |
| girlfriend | Represents the Girlfriend Actor |
### Sprites
##### makeSprite(string SpritePath,string SpriteId,bool DrawBehind)
Creates a sprite out of the specified image, returns the id you gave it.
*Note: Sprite Path is normally the FILE NAME so if your file is named `Image` it'll go to assets/data/songName/Image.png so don't include the extension*
### Hud/Camera
##### setHudPosition(int x, int y)
Sets the game hud's position in space.
##### getHudX()
Returns the hud's x position
##### getHudY()
Returns the hud's y position
##### setCamPosition(int x, int y)
Set's the current camera's position in space
##### getCameraX()
Returns the current camera's x position
##### getCameraY()
Returns the current camera's y position
##### setCamZoom(float zoomAmount)
Set's the current camera's zoom
##### setHudZoom(float zoomAmount)
Set's the hud's zoom
### Strumline
##### setStrumlineY(float y)
Set's the y position of the strumLine
### Actors
##### getRenderedNotes()
Returns the amount of rendered notes.
##### getRenderedNoteX(int id)
Returns the x position of the rendered note id
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### getRenderedNoteY(int id)
Returns the y position of the rendered note id
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### getRenderedNoteScaleX(int id)
Returns the scale x of the rendered note id
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### getRenderedNoteScaleY(int id)
Returns the scale y of the rendered note id
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### getRenderedNoteType(int id)
Returns the note data of an note (0-3, left, down, up, right)
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### getRenderedNoteHit(int id)
Returns whether a rendered note must be hit by the player or not
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### isSustain(int id)
Returns whether a rendered note is a sustain note or not (if they appear as the trail)
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### isParentSustain(int id)
Returns whether a rendered note's parrent is a sustain note or not (if they appear as the trail)
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### getRenderedNoteParentX(int id)
Returns the current parent x of the specified rendered note's id
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### getRenderedNoteParentY(int id)
Returns the current parent y of the specified rendered note's id
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### getRenderedNoteCalcX(int id)
Returns what the game would normally put the specified rendered note x.
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### anyNotes()
Returns true if there are rendered notes, and returns false if there are none
##### getRenderedNoteStrumtime(int id)
Returns strum time of the rendered note.
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### getRenderedNoteAlpha(int id)
Returns the alpha of the rendered note id
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### getRenderedNoteWidth(int id)
Returns the width of the specified rendered note.
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### getRenderedNoteAngle(int id)
Returns the angle of the specified rendered note.
*Note: Rendered Notes id's are special in the way that they act. 0 = closest note to any receptor, last index = the farthest away from any receptor.*
##### setRenderedNotePos(int x, int y, int id)
Set's the position of the rendered note id
*Note: Setting a Rendered Note's property will stop the note from updating it's alpha & x properties*
##### setRenderedNoteAlpha(float alpha, int id)
Set's the alpha of the rendered note id
*Note: Setting a Rendered Note's property will stop the note from updating it's alpha & x properties*
##### setRenderedNoteScale(float scale, int id)
Set's the scale of the rendered note id
*Note: Setting a Rendered Note's property will stop the note from updating it's alpha & x properties*
##### setRenderedNoteScaleX(float scale, int id) **Currently broken**
Set's the scale x of the rendered note id
*Note: Setting a Rendered Note's property will stop the note from updating it's alpha & x properties*
##### setRenderedNoteScaleY(float scale, int id) **Currently broken**
Set's the scale y of the rendered note id
*Note: Setting a Rendered Note's property will stop the note from updating it's alpha & x properties*
##### getActorX(string/int id)
Returns the x position for the sprite id
##### getActorY(string/int id)
Returns the y position for the sprite id
##### getActorScaleX(string/int id)
Returns the scale x for the sprite id
##### getActorScaleY(string/int id)
Returns the scale y for the sprite id
##### getActorAlpha(string/int id)
Returns the alpha for the sprite id
##### getActorAngle(string/int id)
Returns the angle for the sprite id
##### setActorX(int x, string/int id)
Set's the x position for the sprite id
##### setActorAccelerationX(int x, string/int id)
Sets the x acceleration for the sprite id
##### setActorDragX(int x, string/int id)
Sets the x drag for the sprite id
##### setActorVelocityX(int x, string/int id)
Sets the x velocity for the sprite id
##### setActorY(int y, string/int id)
Set's the y position for the sprite id
##### setActorAccelerationY(int y, string/int id)
Sets the y acceleration for the sprite id
##### setActorDragY(int y, string/int id)
Sets the y drag for the sprite id
##### setActorVelocityY(int y, string/int id)
Sets the y velocity for the sprite id
##### setActorAlpha(float alpha, string/int id)
Set's the alpha for the sprite id
##### setActorAngle(int alpha, string/int id)
Set's the angle for the sprite id
##### setActorScale(float scale, string/int id)
Set's the scale for the sprite id
##### setActorScaleXY(float scaleX, float scaleY, string/int id)
Set's the x and y scale for the sprite id
##### setActorFlipX(bool flip, string/int id)
Set's the x flip for the sprite id
##### setActorFlipY(bool flip, string/int id)
Set's the y flip for the sprite id
##### getActorWidth(string/int id)
Returns the width for the sprite id
##### getActorHeight(string/int id)
Returns the height for the sprite id
##### changeBoyfriendCharacter(string id)
Changes the Boyfriend sprite to another character
##### changeDadCharacter(string id)
Changes the Dad sprite to another character
##### playActorAnimation(string/int id, string anim, bool force, bool reverse)
Plays an animation on a sprite
### Tweens
*Note, On Complete functions are based by the function name (and they also well get called when the tween completes)*
##### tweenPos(string/int id, int toX, int toY, float time, string onComplete)
Smoothly tween into a x and y position
##### tweenPosXAngle(string/int id, int toX, float toAngle, float time, string onComplete)
Smoothly tween into a x position and angle
##### tweenPosYAngle(string/int id, int toY, float toAngle, float time, string onComplete)
Smoothly tween into a y position and angle
##### tweenAngle(string/int id, float toAngle, float time, string onComplete)
Smoothly tween into a angle
##### tweenFadeIn(string/int id, float toAlpha, float time, string onComplete)
Smoothly fade in to an alpha
##### tweenFadeOut(string/int id, float toAlpha, float time, string onComplete)
Smoothly fade out to an alpha
### Window & Screen
##### getWindowX()
Returns the window's x position
##### getWindowY()
Returns the window's y position
##### getScreenWidth()
Returns the width of the screen
##### getScreenHeight()
Returns the height of the screen
##### setWindowPos(int x, int y)
Sets the window's position
##### resizeWindow(int width, int height)
Resizes the window

128
source/Caching.hx Normal file
View File

@ -0,0 +1,128 @@
package;
import haxe.Exception;
import flixel.tweens.FlxEase;
import flixel.tweens.FlxTween;
import sys.FileSystem;
import sys.io.File;
import flixel.FlxG;
import flixel.FlxSprite;
import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond;
import flixel.addons.transition.FlxTransitionableState;
import flixel.addons.transition.TransitionData;
import flixel.graphics.FlxGraphic;
import flixel.graphics.frames.FlxAtlasFrames;
import flixel.math.FlxPoint;
import flixel.math.FlxRect;
import flixel.util.FlxColor;
import flixel.util.FlxTimer;
import flixel.text.FlxText;
using StringTools;
class Caching extends MusicBeatState
{
var toBeDone = 0;
var done = 0;
var text:FlxText;
var kadeLogo:FlxSprite;
override function create()
{
FlxG.mouse.visible = false;
FlxG.worldBounds.set(0,0);
text = new FlxText(FlxG.width / 2, FlxG.height / 2 + 300,0,"Loading...");
text.size = 34;
text.alignment = FlxTextAlign.CENTER;
text.alpha = 0;
kadeLogo = new FlxSprite(FlxG.width / 2, FlxG.height / 2).loadGraphic(Paths.image('KadeEngineLogo'));
kadeLogo.x -= kadeLogo.width / 2;
kadeLogo.y -= kadeLogo.height / 2 + 100;
text.y -= kadeLogo.height / 2 - 125;
text.x -= 170;
kadeLogo.setGraphicSize(Std.int(kadeLogo.width * 0.6));
kadeLogo.alpha = 0;
add(kadeLogo);
add(text);
trace('starting caching..');
sys.thread.Thread.create(() -> {
cache();
});
super.create();
}
var calledDone = false;
override function update(elapsed)
{
if (toBeDone != 0 && done != toBeDone)
{
var alpha = HelperFunctions.truncateFloat(done / toBeDone * 100,2) / 100;
kadeLogo.alpha = alpha;
text.alpha = alpha;
text.text = "Loading... (" + done + "/" + toBeDone + ")";
}
super.update(elapsed);
}
function cache()
{
var images = [];
var music = [];
trace("caching images...");
for (i in FileSystem.readDirectory(FileSystem.absolutePath("assets/shared/images/characters")))
{
if (!i.endsWith(".png"))
continue;
images.push(i);
}
trace("caching music...");
for (i in FileSystem.readDirectory(FileSystem.absolutePath("assets/songs")))
{
music.push(i);
}
toBeDone = Lambda.count(images) + Lambda.count(music);
trace("LOADING: " + toBeDone + " OBJECTS.");
for (i in images)
{
var replaced = i.replace(".png","");
FlxG.bitmap.add(Paths.image("characters/" + replaced,"shared"));
trace("cached " + replaced);
done++;
}
for (i in music)
{
FlxG.sound.cache(Paths.inst(i));
FlxG.sound.cache(Paths.voices(i));
trace("cached " + i);
done++;
}
trace("Finished caching...");
FlxG.switchState(new TitleState());
}
}

View File

@ -26,9 +26,11 @@ class FreeplayState extends MusicBeatState
var curDifficulty:Int = 1; var curDifficulty:Int = 1;
var scoreText:FlxText; var scoreText:FlxText;
var comboText:FlxText;
var diffText:FlxText; var diffText:FlxText;
var lerpScore:Int = 0; var lerpScore:Int = 0;
var intendedScore:Int = 0; var intendedScore:Int = 0;
var combo:String = '';
private var grpSongs:FlxTypedGroup<Alphabet>; private var grpSongs:FlxTypedGroup<Alphabet>;
private var curPlaying:Bool = false; private var curPlaying:Bool = false;
@ -106,6 +108,10 @@ class FreeplayState extends MusicBeatState
diffText.font = scoreText.font; diffText.font = scoreText.font;
add(diffText); add(diffText);
comboText = new FlxText(diffText.x + 100, diffText.y, 0, "", 24);
comboText.font = diffText.font;
add(comboText);
add(scoreText); add(scoreText);
changeSelection(); changeSelection();
@ -176,6 +182,7 @@ class FreeplayState extends MusicBeatState
lerpScore = intendedScore; lerpScore = intendedScore;
scoreText.text = "PERSONAL BEST:" + lerpScore; scoreText.text = "PERSONAL BEST:" + lerpScore;
comboText.text = combo + '\n';
var upP = controls.UP_P; var upP = controls.UP_P;
var downP = controls.DOWN_P; var downP = controls.DOWN_P;
@ -202,27 +209,20 @@ class FreeplayState extends MusicBeatState
if (accepted) if (accepted)
{ {
// pre lowercasing the song name (update) // adjusting the song name to be compatible
var songLowercase = StringTools.replace(songs[curSelected].songName, " ", "-").toLowerCase(); var songFormat = StringTools.replace(songs[curSelected].songName, " ", "-");
switch (songLowercase) { switch (songFormat) {
case 'dad-battle': songLowercase = 'dadbattle'; case 'Dad-Battle': songFormat = 'Dadbattle';
case 'philly-nice': songLowercase = 'philly'; case 'Philly-Nice': songFormat = 'Philly';
}
// adjusting the highscore song name to be compatible (update)
// would read original scores if we didn't change packages
var songHighscore = StringTools.replace(songs[curSelected].songName, " ", "-");
switch (songHighscore) {
case 'Dad-Battle': songHighscore = 'Dadbattle';
case 'Philly-Nice': songHighscore = 'Philly';
} }
trace(songLowercase); trace(songs[curSelected].songName);
var poop:String = Highscore.formatSong(songHighscore, curDifficulty); var poop:String = Highscore.formatSong(songFormat, curDifficulty);
trace(poop); trace(poop);
PlayState.SONG = Song.loadFromJson(poop, songLowercase); PlayState.SONG = Song.loadFromJson(poop, songs[curSelected].songName);
PlayState.isStoryMode = false; PlayState.isStoryMode = false;
PlayState.storyDifficulty = curDifficulty; PlayState.storyDifficulty = curDifficulty;
PlayState.storyWeek = songs[curSelected].week; PlayState.storyWeek = songs[curSelected].week;
@ -249,6 +249,7 @@ class FreeplayState extends MusicBeatState
#if !switch #if !switch
intendedScore = Highscore.getScore(songHighscore, curDifficulty); intendedScore = Highscore.getScore(songHighscore, curDifficulty);
combo = Highscore.getCombo(songHighscore, curDifficulty);
#end #end
switch (curDifficulty) switch (curDifficulty)
@ -290,6 +291,7 @@ class FreeplayState extends MusicBeatState
#if !switch #if !switch
intendedScore = Highscore.getScore(songHighscore, curDifficulty); intendedScore = Highscore.getScore(songHighscore, curDifficulty);
combo = Highscore.getCombo(songHighscore, curDifficulty);
// lerpScore = 0; // lerpScore = 0;
#end #end

7
source/GameDimensions.hx Normal file
View File

@ -0,0 +1,7 @@
package;
class GameDimensions
{
public static var width:Int = 1280;
public static var height:Int = 720;
}

95
source/GlobalVideo.hx Normal file
View File

@ -0,0 +1,95 @@
package;
import openfl.Lib;
class GlobalVideo
{
private static var video:VideoHandler;
private static var webm:WebmHandler;
public static var isWebm:Bool = false;
public static var isAndroid:Bool = false;
public static var daAlpha1:Float = 0.2;
public static var daAlpha2:Float = 1;
public static function setVid(vid:VideoHandler):Void
{
video = vid;
}
public static function getVid():VideoHandler
{
return video;
}
public static function setWebm(vid:WebmHandler):Void
{
webm = vid;
isWebm = true;
}
public static function getWebm():WebmHandler
{
return webm;
}
public static function get():Dynamic
{
if (isWebm)
{
return getWebm();
} else {
return getVid();
}
}
public static function calc(ind:Int):Dynamic
{
var stageWidth:Int = Lib.current.stage.stageWidth;
var stageHeight:Int = Lib.current.stage.stageHeight;
var width:Float = GameDimensions.width;
var height:Float = GameDimensions.height;
//trace("AH: " + stageWidth);
//trace(width);
var ratioX:Float = height / width;
var ratioY:Float = width / height;
var appliedWidth:Float = stageHeight * ratioY;
var appliedHeight:Float = stageWidth * ratioX;
//trace(appliedWidth);
var remainingX:Float = stageWidth - appliedWidth;
var remainingY:Float = stageHeight - appliedHeight;
remainingX = remainingX / 2;
remainingY = remainingY / 2;
appliedWidth = Std.int(appliedWidth);
appliedHeight = Std.int(appliedHeight);
if (appliedHeight > stageHeight)
{
remainingY = 0;
appliedHeight = stageHeight;
}
if (appliedWidth > stageWidth)
{
remainingX = 0;
appliedWidth = stageWidth;
}
switch(ind)
{
case 0:
return remainingX;
case 1:
return remainingY;
case 2:
return appliedWidth;
case 3:
return appliedHeight;
}
return null;
}
}

View File

@ -1,3 +1,5 @@
import flixel.math.FlxMath;
class HelperFunctions class HelperFunctions
{ {
public static function truncateFloat( number : Float, precision : Int): Float { public static function truncateFloat( number : Float, precision : Int): Float {
@ -6,4 +8,8 @@ class HelperFunctions
num = Math.round( num ) / Math.pow(10, precision); num = Math.round( num ) / Math.pow(10, precision);
return num; return num;
} }
public static function GCD(a, b) {
return b == 0 ? FlxMath.absInt(a) : GCD(b, a % b);
}
} }

View File

@ -2,12 +2,15 @@ package;
import flixel.FlxG; import flixel.FlxG;
using StringTools;
class Highscore class Highscore
{ {
#if (haxe >= "4.0.0") #if (haxe >= "4.0.0")
public static var songScores:Map<String, Int> = new Map(); public static var songScores:Map<String, Int> = new Map();
public static var songCombos:Map<String, String> = new Map();
#else #else
public static var songScores:Map<String, Int> = new Map<String, Int>(); public static var songScores:Map<String, Int> = new Map<String, Int>();
public static var songCombos:Map<String, String> = new Map<String, String>();
#end #end
@ -32,6 +35,23 @@ class Highscore
}else trace('BotPlay detected. Score saving is disabled.'); }else trace('BotPlay detected. Score saving is disabled.');
} }
public static function saveCombo(song:String, combo:String, ?diff:Int = 0):Void
{
var daSong:String = formatSong(song, diff);
var finalCombo:String = combo.split(')')[0].replace('(', '');
if(!FlxG.save.data.botplay)
{
if (songCombos.exists(daSong))
{
if (getComboInt(songCombos.get(daSong)) < getComboInt(finalCombo))
setCombo(daSong, finalCombo);
}
else
setCombo(daSong, finalCombo);
}
}
public static function saveWeekScore(week:Int = 1, score:Int = 0, ?diff:Int = 0):Void public static function saveWeekScore(week:Int = 1, score:Int = 0, ?diff:Int = 0):Void
{ {
@ -64,6 +84,14 @@ class Highscore
FlxG.save.flush(); FlxG.save.flush();
} }
static function setCombo(song:String, combo:String):Void
{
// Reminder that I don't need to format this song, it should come formatted!
songCombos.set(song, combo);
FlxG.save.data.songCombos = songCombos;
FlxG.save.flush();
}
public static function formatSong(song:String, diff:Int):String public static function formatSong(song:String, diff:Int):String
{ {
var daSong:String = song; var daSong:String = song;
@ -76,6 +104,23 @@ class Highscore
return daSong; return daSong;
} }
static function getComboInt(combo:String):Int
{
switch(combo)
{
case 'SDCB':
return 1;
case 'FC':
return 2;
case 'GFC':
return 3;
case 'MFC':
return 4;
default:
return 0;
}
}
public static function getScore(song:String, diff:Int):Int public static function getScore(song:String, diff:Int):Int
{ {
if (!songScores.exists(formatSong(song, diff))) if (!songScores.exists(formatSong(song, diff)))
@ -84,6 +129,14 @@ class Highscore
return songScores.get(formatSong(song, diff)); return songScores.get(formatSong(song, diff));
} }
public static function getCombo(song:String, diff:Int):String
{
if (!songCombos.exists(formatSong(song, diff)))
setCombo(formatSong(song, diff), '');
return songCombos.get(formatSong(song, diff));
}
public static function getWeekScore(week:Int, diff:Int):Int public static function getWeekScore(week:Int, diff:Int):Int
{ {
if (!songScores.exists(formatSong('week' + week, diff))) if (!songScores.exists(formatSong('week' + week, diff)))
@ -98,5 +151,9 @@ class Highscore
{ {
songScores = FlxG.save.data.songScores; songScores = FlxG.save.data.songScores;
} }
if (FlxG.save.data.songCombos != null)
{
songCombos = FlxG.save.data.songCombos;
}
} }
} }

250
source/HitGraph.hx Normal file
View File

@ -0,0 +1,250 @@
import openfl.display.Bitmap;
import openfl.display.BitmapData;
import openfl.text.TextFieldAutoSize;
import flixel.system.FlxAssets;
import openfl.text.TextFormat;
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFormatAlign;
import flixel.math.FlxMath;
import flixel.util.FlxColor;
import flixel.util.FlxDestroyUtil;
/**
* stolen from https://github.com/HaxeFlixel/flixel/blob/master/flixel/system/debug/stats/StatsGraph.hx
*/
class HitGraph extends Sprite
{
static inline var AXIS_COLOR:FlxColor = 0xffffff;
static inline var AXIS_ALPHA:Float = 0.5;
inline static var HISTORY_MAX:Int = 30;
public var minLabel:TextField;
public var curLabel:TextField;
public var maxLabel:TextField;
public var avgLabel:TextField;
public var minValue:Float = -(Math.floor((PlayState.rep.replay.sf / 60) * 1000) + 95);
public var maxValue:Float = Math.floor((PlayState.rep.replay.sf / 60) * 1000) + 95;
public var graphColor:FlxColor;
public var history:Array<Dynamic> = [];
public var bitmap:Bitmap;
var _axis:Shape;
var _width:Int;
var _height:Int;
var _unit:String;
var _labelWidth:Int;
var _label:String;
public function new(X:Int, Y:Int, Width:Int, Height:Int)
{
super();
x = X;
y = Y;
_width = Width;
_height = Height;
var bm = new BitmapData(Width,Height);
bm.draw(this);
bitmap = new Bitmap(bm);
_axis = new Shape();
_axis.x = _labelWidth + 10;
var ts = Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166;
var early = createTextField(10,10,FlxColor.WHITE,12);
var late = createTextField(10,_height - 20,FlxColor.WHITE,12);
early.text = "Early (" + -166 * ts + "ms)";
late.text = "Late (" + 166 * ts + "ms)";
addChild(early);
addChild(late);
addChild(_axis);
drawAxes();
}
/**
* Redraws the axes of the graph.
*/
function drawAxes():Void
{
var gfx = _axis.graphics;
gfx.clear();
gfx.lineStyle(1, AXIS_COLOR, AXIS_ALPHA);
// y-Axis
gfx.moveTo(0, 0);
gfx.lineTo(0, _height);
// x-Axis
gfx.moveTo(0, _height);
gfx.lineTo(_width, _height);
gfx.moveTo(0, _height / 2);
gfx.lineTo(_width, _height / 2);
}
public static function createTextField(X:Float = 0, Y:Float = 0, Color:FlxColor = FlxColor.WHITE, Size:Int = 12):TextField
{
return initTextField(new TextField(), X, Y, Color, Size);
}
public static function initTextField<T:TextField>(tf:T, X:Float = 0, Y:Float = 0, Color:FlxColor = FlxColor.WHITE, Size:Int = 12):T
{
tf.x = X;
tf.y = Y;
tf.multiline = false;
tf.wordWrap = false;
tf.embedFonts = true;
tf.selectable = false;
#if flash
tf.antiAliasType = AntiAliasType.NORMAL;
tf.gridFitType = GridFitType.PIXEL;
#end
tf.defaultTextFormat = new TextFormat("assets/fonts/vcr.ttf", Size, Color.to24Bit());
tf.alpha = Color.alphaFloat;
tf.autoSize = TextFieldAutoSize.LEFT;
return tf;
}
function drawJudgementLine(ms:Float):Void
{
var gfx:Graphics = graphics;
gfx.lineStyle(1, graphColor, 0.3);
var ts = Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166;
var range:Float = Math.max(maxValue - minValue, maxValue * 0.1);
var value = ((ms * ts) - minValue) / range;
var pointY = _axis.y + ((-value * _height - 1) + _height);
var graphX = _axis.x + 1;
if (ms == 45)
gfx.moveTo(graphX, _axis.y + pointY);
var graphX = _axis.x + 1;
gfx.drawRect(graphX,pointY, _width,1);
gfx.lineStyle(1, graphColor, 1);
}
/**
* Redraws the graph based on the values stored in the history.
*/
function drawGraph():Void
{
var gfx:Graphics = graphics;
gfx.clear();
gfx.lineStyle(1, graphColor, 1);
gfx.beginFill(0x00FF00);
drawJudgementLine(45);
gfx.endFill();
gfx.beginFill(0xFF0000);
drawJudgementLine(90);
gfx.endFill();
gfx.beginFill(0x8b0000);
drawJudgementLine(135);
gfx.endFill();
gfx.beginFill(0x580000);
drawJudgementLine(166);
gfx.endFill();
gfx.beginFill(0x00FF00);
drawJudgementLine(-45);
gfx.endFill();
gfx.beginFill(0xFF0000);
drawJudgementLine(-90);
gfx.endFill();
gfx.beginFill(0x8b0000);
drawJudgementLine(-135);
gfx.endFill();
gfx.beginFill(0x580000);
drawJudgementLine(-166);
gfx.endFill();
var inc:Float = _width / (PlayState.rep.replay.songNotes.length);
var range:Float = Math.max(maxValue - minValue, maxValue * 0.1);
var graphX = _axis.x + 1;
for (i in 0...history.length)
{
var value = (history[i][0] - minValue) / range;
var judge = history[i][1];
switch(judge)
{
case "sick":
gfx.beginFill(0x00FFFF);
case "good":
gfx.beginFill(0x00FF00);
case "bad":
gfx.beginFill(0xFF0000);
case "shit":
gfx.beginFill(0x8b0000);
case "miss":
gfx.beginFill(0x580000);
default:
gfx.beginFill(0xFFFFFF);
}
var pointY = (-value * _height - 1) + _height;
/*if (i == 0)
gfx.moveTo(graphX, _axis.y + pointY);*/
gfx.drawRect(graphX + (i * inc), pointY,4,4);
gfx.endFill();
}
var bm = new BitmapData(_width,_height);
bm.draw(this);
bitmap = new Bitmap(bm);
}
public function addToHistory(diff:Float, judge:String)
{
history.push([diff,judge]);
}
public function update():Void
{
drawGraph();
}
public function average():Float
{
var sum:Float = 0;
for (value in history)
sum += value;
return sum / history.length;
}
public function destroy():Void
{
_axis = FlxDestroyUtil.removeChild(this, _axis);
history = null;
}
}

View File

@ -81,6 +81,12 @@ class KadeEngineData
if (FlxG.save.data.customStrumLine == null) if (FlxG.save.data.customStrumLine == null)
FlxG.save.data.customStrumLine = 0; FlxG.save.data.customStrumLine = 0;
if (FlxG.save.data.camzoom == null)
FlxG.save.data.camzoom = true;
if (FlxG.save.data.scoreScreen == null)
FlxG.save.data.scoreScreen = true;
Conductor.recalculateTimings(); Conductor.recalculateTimings();
PlayerSettings.player1.controls.loadKeyBinds(); PlayerSettings.player1.controls.loadKeyBinds();
KeyBinds.keyCheck(); KeyBinds.keyCheck();

View File

@ -80,7 +80,7 @@ class LoadReplayState extends MusicBeatState
} }
versionShit = new FlxText(5, FlxG.height - 34, 0, "Replay Loader (ESCAPE TO GO BACK)\nNOTICE!!!! Replays are in a beta stage, and they are probably not 100% correct. expect misses and other stuff that isn't there!", 12); versionShit = new FlxText(5, FlxG.height - 34, 0, "Replay Loader (ESCAPE TO GO BACK)\nNOTICE!!!! Replays are in a beta stage, and they are probably not 100% correct. expect misses and other stuff that isn't there!\n", 12);
versionShit.scrollFactor.set(); versionShit.scrollFactor.set();
versionShit.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK); versionShit.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
add(versionShit); add(versionShit);
@ -102,7 +102,7 @@ class LoadReplayState extends MusicBeatState
for (i in 0...songs.length) for (i in 0...songs.length)
{ {
var pog:FreeplayState.SongMetadata = songs[i]; var pog:FreeplayState.SongMetadata = songs[i];
if (pog.songName.toLowerCase() == songName) if (pog.songName == songName)
week = pog.week; week = pog.week;
} }
return week; return week;
@ -148,13 +148,32 @@ class LoadReplayState extends MusicBeatState
PlayState.loadRep = true; PlayState.loadRep = true;
var poop:String = Highscore.formatSong(PlayState.rep.replay.songName.toLowerCase(), PlayState.rep.replay.songDiff); if (PlayState.rep.replay.replayGameVer == Replay.version)
{
PlayState.SONG = Song.loadFromJson(poop, PlayState.rep.replay.songName.toLowerCase()); // adjusting the song name to be compatible
PlayState.isStoryMode = false; var songFormat = StringTools.replace(PlayState.rep.replay.songName, " ", "-");
PlayState.storyDifficulty = PlayState.rep.replay.songDiff; switch (songFormat) {
PlayState.storyWeek = getWeekNumbFromSong(PlayState.rep.replay.songName); case 'Dad-Battle': songFormat = 'Dadbattle';
LoadingState.loadAndSwitchState(new PlayState()); case 'Philly-Nice': songFormat = 'Philly';
// Replay v1.0 support
case 'dad-battle': songFormat = 'Dadbattle';
case 'philly-nice': songFormat = 'Philly';
}
var poop:String = Highscore.formatSong(songFormat, PlayState.rep.replay.songDiff);
PlayState.SONG = Song.loadFromJson(poop, PlayState.rep.replay.songName);
PlayState.isStoryMode = false;
PlayState.storyDifficulty = PlayState.rep.replay.songDiff;
PlayState.storyWeek = getWeekNumbFromSong(PlayState.rep.replay.songName);
LoadingState.loadAndSwitchState(new PlayState());
}
else
{
PlayState.rep = null;
PlayState.loadRep = false;
}
} }
} }
@ -177,7 +196,7 @@ class LoadReplayState extends MusicBeatState
var rep:Replay = Replay.LoadReplay(actualNames[curSelected]); var rep:Replay = Replay.LoadReplay(actualNames[curSelected]);
poggerDetails.text = "Replay Details - \nDate Created: " + rep.replay.timestamp + "\nSong: " + rep.replay.songName + "\nReplay Version: " + (rep.replay.replayGameVer != Replay.version ? "OUTDATED" : "Latest"); poggerDetails.text = "Replay Details - \nDate Created: " + rep.replay.timestamp + "\nSong: " + rep.replay.songName + "\nReplay Version: " + rep.replay.replayGameVer + ' (' + (rep.replay.replayGameVer != Replay.version ? "OUTDATED not useable!" : "Latest") + ')\n';
// selector.y = (70 * curSelected) + 30; // selector.y = (70 * curSelected) + 30;

View File

@ -1,5 +1,7 @@
package; package;
import webm.WebmPlayer;
import openfl.display.BlendMode; import openfl.display.BlendMode;
import openfl.text.TextFormat; import openfl.text.TextFormat;
import openfl.display.Application; import openfl.display.Application;
@ -49,6 +51,8 @@ class Main extends Sprite
} }
} }
public static var webmHandler:WebmHandler;
private function init(?E:Event):Void private function init(?E:Event):Void
{ {
if (hasEventListener(Event.ADDED_TO_STAGE)) if (hasEventListener(Event.ADDED_TO_STAGE))
@ -73,10 +77,8 @@ class Main extends Sprite
gameHeight = Math.ceil(stageHeight / zoom); gameHeight = Math.ceil(stageHeight / zoom);
} }
#if !debug initialState = Caching;
initialState = TitleState;
#end
game = new FlxGame(gameWidth, gameHeight, initialState, zoom, framerate, framerate, skipSplash, startFullscreen); game = new FlxGame(gameWidth, gameHeight, initialState, zoom, framerate, framerate, skipSplash, startFullscreen);
addChild(game); addChild(game);

View File

@ -39,7 +39,7 @@ class MainMenuState extends MusicBeatState
public static var nightly:String = ""; public static var nightly:String = "";
public static var kadeEngineVer:String = "1.5.2" + nightly; public static var kadeEngineVer:String = "1.5.3" + nightly;
public static var gameVer:String = "0.2.7.1"; public static var gameVer:String = "0.2.7.1";
var magenta:FlxSprite; var magenta:FlxSprite;

View File

@ -1,6 +1,7 @@
// this file is for modchart things, this is to declutter playstate.hx // this file is for modchart things, this is to declutter playstate.hx
// Lua // Lua
import openfl.display3D.textures.VideoTexture;
import flixel.graphics.FlxGraphic; import flixel.graphics.FlxGraphic;
import flixel.graphics.frames.FlxAtlasFrames; import flixel.graphics.frames.FlxAtlasFrames;
#if windows #if windows
@ -255,11 +256,18 @@ class ModchartState
function makeAnimatedLuaSprite(spritePath:String,names:Array<String>,prefixes:Array<String>,startAnim:String, id:String) function makeAnimatedLuaSprite(spritePath:String,names:Array<String>,prefixes:Array<String>,startAnim:String, id:String)
{ {
#if sys #if sys
var data:BitmapData = BitmapData.fromFile(Sys.getCwd() + "assets/data/" + PlayState.SONG.song.toLowerCase() + '/' + spritePath + ".png"); // pre lowercasing the song name (makeAnimatedLuaSprite)
var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
switch (songLowercase) {
case 'dad-battle': songLowercase = 'dadbattle';
case 'philly-nice': songLowercase = 'philly';
}
var data:BitmapData = BitmapData.fromFile(Sys.getCwd() + "assets/data/" + songLowercase + '/' + spritePath + ".png");
var sprite:FlxSprite = new FlxSprite(0,0); var sprite:FlxSprite = new FlxSprite(0,0);
sprite.frames = FlxAtlasFrames.fromSparrow(FlxGraphic.fromBitmapData(data), Sys.getCwd() + "assets/data/" + PlayState.SONG.song.toLowerCase() + "/" + spritePath + ".xml"); sprite.frames = FlxAtlasFrames.fromSparrow(FlxGraphic.fromBitmapData(data), Sys.getCwd() + "assets/data/" + songLowercase + "/" + spritePath + ".xml");
trace(sprite.frames.frames.length); trace(sprite.frames.frames.length);
@ -282,7 +290,14 @@ class ModchartState
function makeLuaSprite(spritePath:String,toBeCalled:String, drawBehind:Bool) function makeLuaSprite(spritePath:String,toBeCalled:String, drawBehind:Bool)
{ {
#if sys #if sys
var data:BitmapData = BitmapData.fromFile(Sys.getCwd() + "assets/data/" + PlayState.SONG.song.toLowerCase() + '/' + spritePath + ".png"); // pre lowercasing the song name (makeLuaSprite)
var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
switch (songLowercase) {
case 'dad-battle': songLowercase = 'dadbattle';
case 'philly-nice': songLowercase = 'philly';
}
var data:BitmapData = BitmapData.fromFile(Sys.getCwd() + "assets/data/" + songLowercase + '/' + spritePath + ".png");
var sprite:FlxSprite = new FlxSprite(0,0); var sprite:FlxSprite = new FlxSprite(0,0);
var imgWidth:Float = FlxG.width / data.width; var imgWidth:Float = FlxG.width / data.width;
@ -345,7 +360,14 @@ class ModchartState
//shaders = new Array<LuaShader>(); //shaders = new Array<LuaShader>();
var result = LuaL.dofile(lua, Paths.lua(PlayState.SONG.song.toLowerCase() + "/modchart")); // execute le file // pre lowercasing the song name (new)
var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
switch (songLowercase) {
case 'dad-battle': songLowercase = 'dadbattle';
case 'philly-nice': songLowercase = 'philly';
}
var result = LuaL.dofile(lua, Paths.lua(songLowercase + "/modchart")); // execute le file
if (result != 0) if (result != 0)
{ {
@ -361,6 +383,8 @@ class ModchartState
setVar("scrollspeed", FlxG.save.data.scrollSpeed != 1 ? FlxG.save.data.scrollSpeed : PlayState.SONG.speed); setVar("scrollspeed", FlxG.save.data.scrollSpeed != 1 ? FlxG.save.data.scrollSpeed : PlayState.SONG.speed);
setVar("fpsCap", FlxG.save.data.fpsCap); setVar("fpsCap", FlxG.save.data.fpsCap);
setVar("downscroll", FlxG.save.data.downscroll); setVar("downscroll", FlxG.save.data.downscroll);
setVar("flashing", FlxG.save.data.flashing);
setVar("distractions", FlxG.save.data.distractions);
setVar("curStep", 0); setVar("curStep", 0);
setVar("curBeat", 0); setVar("curBeat", 0);
@ -413,10 +437,43 @@ class ModchartState
PlayState.instance.removeObject(sprite); PlayState.instance.removeObject(sprite);
return true; return true;
}); });
// hud/camera // hud/camera
Lua_helper.add_callback(lua,"initBackgroundVideo", function(videoName:String) {
trace('playing assets/videos/' + videoName + '.webm');
PlayState.instance.backgroundVideo("assets/videos/" + videoName + ".webm");
});
Lua_helper.add_callback(lua,"pauseVideo", function() {
if (!GlobalVideo.get().paused)
GlobalVideo.get().pause();
});
Lua_helper.add_callback(lua,"resumeVideo", function() {
if (GlobalVideo.get().paused)
GlobalVideo.get().pause();
});
Lua_helper.add_callback(lua,"restartVideo", function() {
GlobalVideo.get().restart();
});
Lua_helper.add_callback(lua,"getVideoSpriteX", function() {
return PlayState.instance.videoSprite.x;
});
Lua_helper.add_callback(lua,"getVideoSpriteY", function() {
return PlayState.instance.videoSprite.y;
});
Lua_helper.add_callback(lua,"setVideoSpritePos", function(x:Int,y:Int) {
PlayState.instance.videoSprite.setPosition(x,y);
});
Lua_helper.add_callback(lua,"setVideoSpriteScale", function(scale:Float) {
PlayState.instance.videoSprite.setGraphicSize(Std.int(PlayState.instance.videoSprite.width * scale));
});
Lua_helper.add_callback(lua,"setHudAngle", function (x:Float) { Lua_helper.add_callback(lua,"setHudAngle", function (x:Float) {
PlayState.instance.camHUD.angle = x; PlayState.instance.camHUD.angle = x;

View File

@ -50,7 +50,7 @@ class Note extends FlxSprite
x += 50; x += 50;
// MAKE SURE ITS DEFINITELY OFF SCREEN? // MAKE SURE ITS DEFINITELY OFF SCREEN?
y -= 2000; y -= 2000;
this.strumTime = strumTime; this.strumTime = Math.round(strumTime);
if (this.strumTime < 0 ) if (this.strumTime < 0 )
this.strumTime = 0; this.strumTime = 0;
@ -59,7 +59,14 @@ class Note extends FlxSprite
var daStage:String = PlayState.curStage; var daStage:String = PlayState.curStage;
switch (PlayState.SONG.noteStyle) //defaults if no noteStyle was found in chart
var noteTypeCheck:String = 'normal';
if (PlayState.SONG.noteStyle == null) {
switch(PlayState.storyWeek) {case 6: noteTypeCheck = 'pixel';}
} else {noteTypeCheck = PlayState.SONG.noteStyle;}
switch (noteTypeCheck)
{ {
case 'pixel': case 'pixel':
loadGraphic(Paths.image('weeb/pixelUI/arrows-pixels','week6'), true, 17, 17); loadGraphic(Paths.image('weeb/pixelUI/arrows-pixels','week6'), true, 17, 17);

View File

@ -296,8 +296,8 @@ class Judgement extends Option
override function getValue():String { override function getValue():String {
return "Safe Frames: " + Conductor.safeFrames + return "Safe Frames: " + Conductor.safeFrames +
" - SIK: " + HelperFunctions.truncateFloat(45 * Conductor.timeScale, 0) + " - SIK: " + HelperFunctions.truncateFloat(22 * Conductor.timeScale, 0) +
"ms GD: " + HelperFunctions.truncateFloat(90 * Conductor.timeScale, 0) + "ms GD: " + HelperFunctions.truncateFloat(45 * Conductor.timeScale, 0) +
"ms BD: " + HelperFunctions.truncateFloat(135 * Conductor.timeScale, 0) + "ms BD: " + HelperFunctions.truncateFloat(135 * Conductor.timeScale, 0) +
"ms SHT: " + HelperFunctions.truncateFloat(155 * Conductor.timeScale, 0) + "ms SHT: " + HelperFunctions.truncateFloat(155 * Conductor.timeScale, 0) +
"ms TOTAL: " + HelperFunctions.truncateFloat(Conductor.safeZoneOffset,0) + "ms"; "ms TOTAL: " + HelperFunctions.truncateFloat(Conductor.safeZoneOffset,0) + "ms";
@ -338,6 +338,27 @@ class FPSOption extends Option
} }
} }
class ScoreScreen extends Option
{
public function new(desc:String)
{
super();
description = desc;
}
public override function press():Bool
{
FlxG.save.data.scoreScreen = !FlxG.save.data.scoreScreen;
return true;
}
private override function updateDisplay():String
{
return (FlxG.save.data.scoreScreen ? "Show Score Screen" : "No Score Screen");
}
}
class FPSCapOption extends Option class FPSCapOption extends Option
@ -614,3 +635,23 @@ class BotPlay extends Option
private override function updateDisplay():String private override function updateDisplay():String
return "BotPlay " + (FlxG.save.data.botplay ? "on" : "off"); return "BotPlay " + (FlxG.save.data.botplay ? "on" : "off");
} }
class CamZoomOption extends Option
{
public function new(desc:String)
{
super();
description = desc;
}
public override function press():Bool
{
FlxG.save.data.camzoom = !FlxG.save.data.camzoom;
display = updateDisplay();
return true;
}
private override function updateDisplay():String
{
return "Camera Zoom " + (!FlxG.save.data.camzoom ? "off" : "on");
}
}

View File

@ -39,15 +39,14 @@ class OptionsMenu extends MusicBeatState
new CustomizeGameplay("Drag'n'Drop Gameplay Modules around to your preference") new CustomizeGameplay("Drag'n'Drop Gameplay Modules around to your preference")
]), ]),
new OptionCategory("Appearance", [ new OptionCategory("Appearance", [
#if desktop
new DistractionsAndEffectsOption("Toggle stage distractions that can hinder your gameplay."), new DistractionsAndEffectsOption("Toggle stage distractions that can hinder your gameplay."),
new CamZoomOption("Toggle the camera zoom in-game."),
#if desktop
new RainbowFPSOption("Make the FPS Counter Rainbow"), new RainbowFPSOption("Make the FPS Counter Rainbow"),
new AccuracyOption("Display accuracy information."), new AccuracyOption("Display accuracy information."),
new NPSDisplayOption("Shows your current Notes Per Second."), new NPSDisplayOption("Shows your current Notes Per Second."),
new SongPositionOption("Show the songs current position (as a bar)"), new SongPositionOption("Show the songs current position (as a bar)"),
new CpuStrums("CPU's strumline lights up when a note hits it."), new CpuStrums("CPU's strumline lights up when a note hits it."),
#else
new DistractionsAndEffectsOption("Toggle stage distractions that can hinder your gameplay.")
#end #end
]), ]),
@ -58,7 +57,8 @@ class OptionsMenu extends MusicBeatState
#end #end
new FlashingLightsOption("Toggle flashing lights that can cause epileptic seizures and strain."), new FlashingLightsOption("Toggle flashing lights that can cause epileptic seizures and strain."),
new WatermarkOption("Enable and disable all watermarks from the engine."), new WatermarkOption("Enable and disable all watermarks from the engine."),
new BotPlay("Showcase your charts and mods with autoplay.") new BotPlay("Showcase your charts and mods with autoplay."),
new ScoreScreen("Show the score screen after the end of a song")
]) ])
]; ];
@ -130,14 +130,17 @@ class OptionsMenu extends MusicBeatState
isCat = false; isCat = false;
grpControls.clear(); grpControls.clear();
for (i in 0...options.length) for (i in 0...options.length)
{ {
var controlLabel:Alphabet = new Alphabet(0, (70 * i) + 30, options[i].getName(), true, false); var controlLabel:Alphabet = new Alphabet(0, (70 * i) + 30, options[i].getName(), true, false);
controlLabel.isMenuItem = true; controlLabel.isMenuItem = true;
controlLabel.targetY = i; controlLabel.targetY = i;
grpControls.add(controlLabel); grpControls.add(controlLabel);
// DONT PUT X IN THE FIRST PARAMETER OF new ALPHABET() !! // DONT PUT X IN THE FIRST PARAMETER OF new ALPHABET() !!
} }
curSelected = 0; curSelected = 0;
changeSelection(curSelected);
} }
if (controls.UP_P) if (controls.UP_P)
changeSelection(-1); changeSelection(-1);
@ -146,7 +149,6 @@ class OptionsMenu extends MusicBeatState
if (isCat) if (isCat)
{ {
if (currentSelectedCat.getOptions()[curSelected].getAccept()) if (currentSelectedCat.getOptions()[curSelected].getAccept())
{ {
if (FlxG.keys.pressed.SHIFT) if (FlxG.keys.pressed.SHIFT)
@ -166,7 +168,6 @@ class OptionsMenu extends MusicBeatState
} }
else else
{ {
if (FlxG.keys.pressed.SHIFT) if (FlxG.keys.pressed.SHIFT)
{ {
if (FlxG.keys.justPressed.RIGHT) if (FlxG.keys.justPressed.RIGHT)
@ -179,7 +180,7 @@ class OptionsMenu extends MusicBeatState
else if (FlxG.keys.pressed.LEFT) else if (FlxG.keys.pressed.LEFT)
FlxG.save.data.offset -= 0.1; FlxG.save.data.offset -= 0.1;
versionShit.text = "Offset (Left, Right, Shift for slow): " + HelperFunctions.truncateFloat(FlxG.save.data.offset,2) + " - Description - " + currentDescription;
} }
if (currentSelectedCat.getOptions()[curSelected].getAccept()) if (currentSelectedCat.getOptions()[curSelected].getAccept())
versionShit.text = currentSelectedCat.getOptions()[curSelected].getValue() + " - Description - " + currentDescription; versionShit.text = currentSelectedCat.getOptions()[curSelected].getValue() + " - Description - " + currentDescription;
@ -189,16 +190,18 @@ class OptionsMenu extends MusicBeatState
else else
{ {
if (FlxG.keys.pressed.SHIFT) if (FlxG.keys.pressed.SHIFT)
{ {
if (FlxG.keys.justPressed.RIGHT) if (FlxG.keys.justPressed.RIGHT)
FlxG.save.data.offset += 0.1;
else if (FlxG.keys.justPressed.LEFT)
FlxG.save.data.offset -= 0.1;
}
else if (FlxG.keys.pressed.RIGHT)
FlxG.save.data.offset += 0.1; FlxG.save.data.offset += 0.1;
else if (FlxG.keys.pressed.LEFT) else if (FlxG.keys.justPressed.LEFT)
FlxG.save.data.offset -= 0.1; FlxG.save.data.offset -= 0.1;
}
else if (FlxG.keys.pressed.RIGHT)
FlxG.save.data.offset += 0.1;
else if (FlxG.keys.pressed.LEFT)
FlxG.save.data.offset -= 0.1;
versionShit.text = "Offset (Left, Right, Shift for slow): " + HelperFunctions.truncateFloat(FlxG.save.data.offset,2) + " - Description - " + currentDescription;
} }
@ -231,6 +234,8 @@ class OptionsMenu extends MusicBeatState
} }
curSelected = 0; curSelected = 0;
} }
changeSelection(curSelected);
} }
} }
FlxG.save.flush(); FlxG.save.flush();

View File

@ -33,6 +33,13 @@ class PauseSubState extends MusicBeatSubstate
{ {
super(); super();
if (PlayState.instance.useVideo)
{
menuItems.remove("Resume");
if (GlobalVideo.get().playing)
GlobalVideo.get().pause();
}
pauseMusic = new FlxSound().loadEmbedded(Paths.music('breakfast'), true, true); pauseMusic = new FlxSound().loadEmbedded(Paths.music('breakfast'), true, true);
pauseMusic.volume = 0; pauseMusic.volume = 0;
pauseMusic.play(false, FlxG.random.int(0, Std.int(pauseMusic.length / 2))); pauseMusic.play(false, FlxG.random.int(0, Std.int(pauseMusic.length / 2)));
@ -98,13 +105,23 @@ class PauseSubState extends MusicBeatSubstate
super.update(elapsed); super.update(elapsed);
if (PlayState.instance.useVideo)
menuItems.remove('Resume');
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 leftP = controls.LEFT_P;
var rightP = controls.RIGHT_P; var rightP = controls.RIGHT_P;
var accepted = controls.ACCEPT; var accepted = controls.ACCEPT;
var oldOffset:Float = 0; var oldOffset:Float = 0;
var songPath = 'assets/data/' + PlayState.SONG.song.toLowerCase() + '/';
// pre lowercasing the song name (update)
var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
switch (songLowercase) {
case 'dad-battle': songLowercase = 'dadbattle';
case 'philly-nice': songLowercase = 'philly';
}
var songPath = 'assets/data/' + songLowercase + '/';
if (upP) if (upP)
{ {
@ -180,8 +197,20 @@ class PauseSubState extends MusicBeatSubstate
case "Resume": case "Resume":
close(); close();
case "Restart Song": case "Restart Song":
if (PlayState.instance.useVideo)
{
GlobalVideo.get().stop();
PlayState.instance.remove(PlayState.instance.videoSprite);
PlayState.instance.removedVideo = true;
}
FlxG.resetState(); FlxG.resetState();
case "Exit to menu": case "Exit to menu":
if (PlayState.instance.useVideo)
{
GlobalVideo.get().stop();
PlayState.instance.remove(PlayState.instance.videoSprite);
PlayState.instance.removedVideo = true;
}
if(PlayState.loadRep) if(PlayState.loadRep)
{ {
FlxG.save.data.botplay = false; FlxG.save.data.botplay = false;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,7 @@
class PlayStateChangeables
{
public static var useDownscroll:Bool;
public static var safeFrames:Int;
public static var scrollSpeed:Float;
public static var botPlay:Bool;
}

View File

@ -5,7 +5,7 @@ class Ratings
public static function GenerateLetterRank(accuracy:Float) // generate a letter ranking public static function GenerateLetterRank(accuracy:Float) // generate a letter ranking
{ {
var ranking:String = "N/A"; var ranking:String = "N/A";
if(FlxG.save.data.botplay) if(FlxG.save.data.botplay && !PlayState.loadRep)
ranking = "BotPlay"; ranking = "BotPlay";
if (PlayState.misses == 0 && PlayState.bads == 0 && PlayState.shits == 0 && PlayState.goods == 0) // Marvelous (SICK) Full Combo if (PlayState.misses == 0 && PlayState.bads == 0 && PlayState.shits == 0 && PlayState.goods == 0) // Marvelous (SICK) Full Combo
@ -86,7 +86,7 @@ class Ratings
if (accuracy == 0) if (accuracy == 0)
ranking = "N/A"; ranking = "N/A";
else if(FlxG.save.data.botplay) else if(FlxG.save.data.botplay && !PlayState.loadRep)
ranking = "BotPlay"; ranking = "BotPlay";
return ranking; return ranking;
@ -107,35 +107,45 @@ class Ratings
// trace('Hit Info\nDifference: ' + noteDiff + '\nZone: ' + Conductor.safeZoneOffset * 1.5 + "\nTS: " + customTimeScale + "\nLate: " + 155 * customTimeScale); // trace('Hit Info\nDifference: ' + noteDiff + '\nZone: ' + Conductor.safeZoneOffset * 1.5 + "\nTS: " + customTimeScale + "\nLate: " + 155 * customTimeScale);
if (FlxG.save.data.botplay) if (FlxG.save.data.botplay && !PlayState.loadRep)
return "good"; // FUNNY return "sick"; // FUNNY
if (noteDiff > 166 * customTimeScale) // so god damn early its a miss
return "miss"; var rating = checkRating(noteDiff,customTimeScale);
if (noteDiff > 135 * customTimeScale) // way early
return "shit";
else if (noteDiff > 90 * customTimeScale) // early return rating;
return "bad"; }
else if (noteDiff > 45 * customTimeScale) // your kinda there
return "good"; public static function checkRating(ms:Float, ts:Float)
else if (noteDiff < -45 * customTimeScale) // little late {
return "good"; var rating = "miss";
else if (noteDiff < -90 * customTimeScale) // late if (ms < 166 * ts && ms > 135 * ts)
return "bad"; rating = "shit";
else if (noteDiff < -135 * customTimeScale) // late as fuck if (ms > -166 * ts && ms < -135 * ts)
return "shit"; rating = "shit";
else if (noteDiff < -166 * customTimeScale) // so god damn late its a miss if (ms < 135 * ts && ms > 90 * ts)
return "miss"; rating = "bad";
return "sick"; if (ms > -135 * ts && ms < -90 * ts)
rating = "bad";
if (ms < 90 * ts && ms > 45 * ts)
rating = "good";
if (ms > -90 * ts && ms < -45 * ts)
rating = "good";
if (ms < 45 * ts && ms > -45 * ts)
rating = "sick";
return rating;
} }
public static function CalculateRanking(score:Int,scoreDef:Int,nps:Int,maxNPS:Int,accuracy:Float):String public static function CalculateRanking(score:Int,scoreDef:Int,nps:Int,maxNPS:Int,accuracy:Float):String
{ {
return return
(FlxG.save.data.npsDisplay ? "NPS: " + nps + " (Max " + maxNPS + ")" + (!FlxG.save.data.botplay ? " | " : "") : "") + (!FlxG.save.data.botplay ? // NPS Toggle (FlxG.save.data.npsDisplay ? // NPS Toggle
"Score:" + (Conductor.safeFrames != 10 ? score + " (" + scoreDef + ")" : "" + score) + // Score "NPS: " + nps + " (Max " + maxNPS + ")" + (!PlayStateChangeables.botPlay || PlayState.loadRep ? " | " : "") : "") + // NPS
" | Combo Breaks:" + PlayState.misses + // Misses/Combo Breaks (!PlayStateChangeables.botPlay || PlayState.loadRep ? "Score:" + (Conductor.safeFrames != 10 ? score + " (" + scoreDef + ")" : "" + score) + // Score
" | Accuracy:" + (FlxG.save.data.botplay ? "N/A" : HelperFunctions.truncateFloat(accuracy, 2) + " %") + // Accuracy (FlxG.save.data.accuracyDisplay ? // Accuracy Toggle
" | " + GenerateLetterRank(accuracy) : ""); // Letter Rank " | Combo Breaks:" + PlayState.misses + // Misses/Combo Breaks
" | Accuracy:" + (PlayStateChangeables.botPlay && !PlayState.loadRep ? "N/A" : HelperFunctions.truncateFloat(accuracy, 2) + " %") + // Accuracy
" | " + GenerateLetterRank(accuracy) : "") : ""); // Letter Rank
} }
} }

View File

@ -13,79 +13,88 @@ import openfl.utils.Dictionary;
typedef ReplayJSON = typedef ReplayJSON =
{ {
public var replayGameVer:String; public var replayGameVer:String;
public var timestamp:Date; public var timestamp:Date;
public var songName:String; public var songName:String;
public var songDiff:Int; public var songDiff:Int;
public var songNotes:Array<Float>; public var songNotes:Array<Dynamic>;
public var noteSpeed:Float; public var noteSpeed:Float;
public var isDownscroll:Bool; public var isDownscroll:Bool;
public var sf:Int;
} }
class Replay class Replay
{ {
public static var version:String = "1.0"; // replay file version public static var version:String = "1.2"; // replay file version
public var path:String = ""; public var path:String = "";
public var replay:ReplayJSON; public var replay:ReplayJSON;
public function new(path:String) public function new(path:String)
{ {
this.path = path; this.path = path;
replay = { replay = {
songName: "Tutorial", songName: "No Song Found",
songDiff: 1, songDiff: 1,
noteSpeed: 1.5, noteSpeed: 1.5,
isDownscroll: false, isDownscroll: false,
songNotes: [], songNotes: [],
replayGameVer: version, replayGameVer: version,
timestamp: Date.now() timestamp: Date.now(),
}; sf: Conductor.safeFrames
} };
}
public static function LoadReplay(path:String):Replay public static function LoadReplay(path:String):Replay
{ {
var rep:Replay = new Replay(path); var rep:Replay = new Replay(path);
rep.LoadFromJSON(); rep.LoadFromJSON();
trace('basic replay data:\nSong Name: ' + rep.replay.songName + '\nSong Diff: ' + rep.replay.songDiff + '\nNotes Length: ' + rep.replay.songNotes.length); trace('basic replay data:\nSong Name: ' + rep.replay.songName + '\nSong Diff: ' + rep.replay.songDiff);
return rep; return rep;
} }
public function SaveReplay(notearray:Array<Float>) public function SaveReplay(notearray:Array<Dynamic>)
{ {
var json = { var json = {
"songName": PlayState.SONG.song.toLowerCase(), "songName": PlayState.SONG.song,
"songDiff": PlayState.storyDifficulty, "songDiff": PlayState.storyDifficulty,
"noteSpeed": (FlxG.save.data.scrollSpeed > 1 ? FlxG.save.data.scrollSpeed : PlayState.SONG.speed), "noteSpeed": (FlxG.save.data.scrollSpeed > 1 ? FlxG.save.data.scrollSpeed : PlayState.SONG.speed),
"isDownscroll": FlxG.save.data.downscroll, "isDownscroll": FlxG.save.data.downscroll,
"songNotes": notearray, "songNotes": notearray,
"timestamp": Date.now(), "timestamp": Date.now(),
"replayGameVer": version "replayGameVer": version,
}; "sf": Conductor.safeFrames
};
var data:String = Json.stringify(json); var data:String = Json.stringify(json);
var time = Date.now().getTime();
#if sys #if sys
File.saveContent("assets/replays/replay-" + PlayState.SONG.song + "-time" + Date.now().getTime() + ".kadeReplay", data); File.saveContent("assets/replays/replay-" + PlayState.SONG.song + "-time" + time + ".kadeReplay", data);
#end
}
public function LoadFromJSON() path = "replay-" + PlayState.SONG.song + "-time" + time + ".kadeReplay"; // for score screen shit
{
#if sys LoadFromJSON();
trace('loading ' + Sys.getCwd() + 'assets/replays/' + path + ' replay...'); #end
try }
{
var repl:ReplayJSON = cast Json.parse(File.getContent(Sys.getCwd() + "assets/replays/" + path)); public function LoadFromJSON()
replay = repl; {
} #if sys
catch(e) trace('loading ' + Sys.getCwd() + 'assets/replays/' + path + ' replay...');
{ try
trace('failed!\n' + e.message); {
} var repl:ReplayJSON = cast Json.parse(File.getContent(Sys.getCwd() + "assets/replays/" + path));
#end replay = repl;
} }
catch(e)
{
trace('failed!\n' + e.message);
}
#end
}
} }

250
source/ResultsScreen.hx Normal file
View File

@ -0,0 +1,250 @@
package;
import openfl.geom.Matrix;
import openfl.display.BitmapData;
import flixel.system.FlxSound;
import flixel.util.FlxAxes;
import flixel.FlxSubState;
import Options.Option;
import flixel.input.FlxInput;
import flixel.input.keyboard.FlxKey;
import flixel.FlxG;
import flixel.FlxObject;
import flixel.FlxSprite;
import flixel.effects.FlxFlicker;
import flixel.graphics.frames.FlxAtlasFrames;
import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.text.FlxText;
import flixel.tweens.FlxEase;
import flixel.tweens.FlxTween;
import flixel.util.FlxColor;
import io.newgrounds.NG;
import lime.app.Application;
import lime.utils.Assets;
import flixel.math.FlxMath;
import flixel.text.FlxText;
import flixel.input.FlxKeyManager;
using StringTools;
class ResultsScreen extends FlxSubState
{
public var background:FlxSprite;
public var text:FlxText;
public var anotherBackground:FlxSprite;
public var graph:HitGraph;
public var graphSprite:FlxSprite;
public var comboText:FlxText;
public var contText:FlxText;
public var settingsText:FlxText;
public var music:FlxSound;
public var graphData:BitmapData;
public var ranking:String;
public var accuracy:String;
override function create()
{
background = new FlxSprite(0,0).makeGraphic(FlxG.width,FlxG.height,FlxColor.BLACK);
background.scrollFactor.set();
add(background);
music = new FlxSound().loadEmbedded(Paths.music('breakfast'), true, true);
music.volume = 0;
music.play(false, FlxG.random.int(0, Std.int(music.length / 2)));
background.alpha = 0;
text = new FlxText(20,-55,0,"Song Cleared!");
text.size = 34;
text.setBorderStyle(FlxTextBorderStyle.OUTLINE,FlxColor.BLACK,4,1);
text.color = FlxColor.WHITE;
text.scrollFactor.set();
add(text);
var score = PlayState.instance.songScore;
if (PlayState.isStoryMode)
{
score = PlayState.campaignScore;
text.text = "Week Cleared!";
}
comboText = new FlxText(20,-75,0,'Judgements:\nSicks - ${PlayState.sicks}\nGoods - ${PlayState.goods}\nBads - ${PlayState.bads}\n\nCombo Breaks: ${(PlayState.isStoryMode ? PlayState.campaignMisses : PlayState.misses) + PlayState.shits}\nHighest Combo: ${PlayState.highestCombo + 1}\n\nScore: ${PlayState.instance.songScore}\nAccuracy: ${HelperFunctions.truncateFloat(PlayState.instance.accuracy,2)}%\n\n${Ratings.GenerateLetterRank(PlayState.instance.accuracy)}\n\nF1 - View replay\nF2 - Replay song
');
comboText.size = 28;
comboText.setBorderStyle(FlxTextBorderStyle.OUTLINE,FlxColor.BLACK,4,1);
comboText.color = FlxColor.WHITE;
comboText.scrollFactor.set();
add(comboText);
contText = new FlxText(FlxG.width - 475,FlxG.height + 50,0,'Press ENTER to continue.');
contText.size = 28;
contText.setBorderStyle(FlxTextBorderStyle.OUTLINE,FlxColor.BLACK,4,1);
contText.color = FlxColor.WHITE;
contText.scrollFactor.set();
add(contText);
anotherBackground = new FlxSprite(FlxG.width - 500,45).makeGraphic(450,240,FlxColor.BLACK);
anotherBackground.scrollFactor.set();
anotherBackground.alpha = 0;
add(anotherBackground);
graph = new HitGraph(FlxG.width - 500,45,495,240);
graph.alpha = 0;
graphSprite = new FlxSprite(FlxG.width - 510,45);
graphSprite.scrollFactor.set();
graphSprite.alpha = 0;
add(graphSprite);
var sicks = HelperFunctions.truncateFloat(PlayState.sicks / PlayState.goods,1);
var goods = HelperFunctions.truncateFloat(PlayState.goods / PlayState.bads,1);
if (sicks == Math.POSITIVE_INFINITY)
sicks = 0;
if (goods == Math.POSITIVE_INFINITY)
goods = 0;
var mean:Float = 0;
for (i in PlayState.rep.replay.songNotes)
{
// 0 = time
// 1 = length
// 2 = type
// 3 = diff
var diff = i[3];
var judge = Ratings.CalculateRating(diff, Math.floor((PlayState.rep.replay.sf / 60) * 1000));
mean += diff;
if (i[1] != -1)
graph.addToHistory(diff, judge);
}
graph.update();
graphSprite.makeGraphic(460,240,FlxColor.TRANSPARENT);
graphSprite.pixels.draw(graph);
mean = HelperFunctions.truncateFloat(mean / PlayState.rep.replay.songNotes.length,2);
settingsText = new FlxText(20,FlxG.height + 50,0,'SF: ${PlayState.rep.replay.sf} | Ratio (SA/GA): ${Math.round(sicks)}:1 ${Math.round(goods)}:1 | Mean: ${mean}ms | Played on ${PlayState.SONG.song} ${CoolUtil.difficultyString()}');
settingsText.size = 16;
settingsText.setBorderStyle(FlxTextBorderStyle.OUTLINE,FlxColor.BLACK,2,1);
settingsText.color = FlxColor.WHITE;
settingsText.scrollFactor.set();
add(settingsText);
FlxTween.tween(background, {alpha: 0.5},0.5);
FlxTween.tween(text, {y:20},0.5,{ease: FlxEase.expoInOut});
FlxTween.tween(comboText, {y:145},0.5,{ease: FlxEase.expoInOut});
FlxTween.tween(contText, {y:FlxG.height - 45},0.5,{ease: FlxEase.expoInOut});
FlxTween.tween(settingsText, {y:FlxG.height - 35},0.5,{ease: FlxEase.expoInOut});
FlxTween.tween(anotherBackground, {alpha: 0.6},0.5, {onUpdate: function(tween:FlxTween) {
graph.alpha = FlxMath.lerp(0,1,tween.percent);
graphSprite.alpha = FlxMath.lerp(0,1,tween.percent);
}});
cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]];
super.create();
}
var frames = 0;
override function update(elapsed:Float)
{
if (music.volume < 0.5)
music.volume += 0.01 * elapsed;
// render
if (frames != 2)
{
graphSprite.pixels.draw(graph);
frames++;
}
// keybinds
if (FlxG.keys.justPressed.ENTER)
{
music.fadeOut(0.3);
PlayState.loadRep = false;
PlayState.rep = null;
if (PlayState.isStoryMode)
{
FlxG.sound.playMusic(Paths.music('freakyMenu'));
FlxG.switchState(new MainMenuState());
}
else
FlxG.switchState(new FreeplayState());
}
if (FlxG.keys.justPressed.F1)
{
trace(PlayState.rep.path);
PlayState.rep = Replay.LoadReplay(PlayState.rep.path);
PlayState.loadRep = true;
var songFormat = StringTools.replace(PlayState.rep.replay.songName, " ", "-");
switch (songFormat) {
case 'Dad-Battle': songFormat = 'Dadbattle';
case 'Philly-Nice': songFormat = 'Philly';
// Replay v1.0 support
case 'dad-battle': songFormat = 'Dadbattle';
case 'philly-nice': songFormat = 'Philly';
}
var poop:String = Highscore.formatSong(songFormat, PlayState.rep.replay.songDiff);
music.fadeOut(0.3);
PlayState.SONG = Song.loadFromJson(poop, PlayState.rep.replay.songName);
PlayState.isStoryMode = false;
PlayState.storyDifficulty = PlayState.rep.replay.songDiff;
PlayState.storyWeek = 0;
LoadingState.loadAndSwitchState(new PlayState());
}
if (FlxG.keys.justPressed.F2 )
{
PlayState.rep = null;
PlayState.loadRep = false;
var songFormat = StringTools.replace(PlayState.SONG.song, " ", "-");
switch (songFormat) {
case 'Dad-Battle': songFormat = 'Dadbattle';
case 'Philly-Nice': songFormat = 'Philly';
case 'dad-battle': songFormat = 'Dadbattle';
case 'philly-nice': songFormat = 'Philly';
}
var poop:String = Highscore.formatSong(songFormat, PlayState.storyDifficulty);
music.fadeOut(0.3);
PlayState.SONG = Song.loadFromJson(poop, PlayState.SONG.song);
PlayState.isStoryMode = false;
PlayState.storyDifficulty = PlayState.storyDifficulty;
PlayState.storyWeek = 0;
LoadingState.loadAndSwitchState(new PlayState());
}
super.update(elapsed);
}
}

View File

@ -33,9 +33,9 @@ class Song
public var player1:String = 'bf'; public var player1:String = 'bf';
public var player2:String = 'dad'; public var player2:String = 'dad';
public var gfVersion:String = 'gf'; public var gfVersion:String = '';
public var noteStyle:String = 'normal'; public var noteStyle:String = '';
public var stage:String = 'stage'; public var stage:String = '';
public function new(song, notes, bpm) public function new(song, notes, bpm)
{ {
@ -47,8 +47,8 @@ class Song
public static function loadFromJson(jsonInput:String, ?folder:String):SwagSong public static function loadFromJson(jsonInput:String, ?folder:String):SwagSong
{ {
trace(jsonInput); trace(jsonInput);
// pre lowercasing the song name (update) // pre lowercasing the folder name
var folderLowercase = StringTools.replace(folder, " ", "-").toLowerCase(); var folderLowercase = StringTools.replace(folder, " ", "-").toLowerCase();
switch (folderLowercase) { switch (folderLowercase) {
case 'dad-battle': folderLowercase = 'dadbattle'; case 'dad-battle': folderLowercase = 'dadbattle';

View File

@ -285,19 +285,23 @@ class StoryMenuState extends MusicBeatState
PlayState.isStoryMode = true; PlayState.isStoryMode = true;
selectedWeek = true; selectedWeek = true;
var diffic = "";
switch (curDifficulty)
{
case 0:
diffic = '-easy';
case 2:
diffic = '-hard';
}
PlayState.storyDifficulty = curDifficulty; PlayState.storyDifficulty = curDifficulty;
PlayState.SONG = Song.loadFromJson(StringTools.replace(PlayState.storyPlaylist[0]," ", "-").toLowerCase() + diffic, StringTools.replace(PlayState.storyPlaylist[0]," ", "-").toLowerCase()); // adjusting the song name to be compatible
var songFormat = StringTools.replace(PlayState.storyPlaylist[0], " ", "-");
switch (songFormat) {
case 'Dad-Battle': songFormat = 'Dadbattle';
case 'Philly-Nice': songFormat = 'Philly';
}
var poop:String = Highscore.formatSong(songFormat, curDifficulty);
PlayState.sicks = 0;
PlayState.bads = 0;
PlayState.shits = 0;
PlayState.goods = 0;
PlayState.campaignMisses = 0;
PlayState.SONG = Song.loadFromJson(poop, PlayState.storyPlaylist[0]);
PlayState.storyWeek = curWeek; PlayState.storyWeek = curWeek;
PlayState.campaignScore = 0; PlayState.campaignScore = 0;
new FlxTimer().start(1, function(tmr:FlxTimer) new FlxTimer().start(1, function(tmr:FlxTimer)

195
source/VideoHandler.hx Normal file
View File

@ -0,0 +1,195 @@
//This was made by GWebDev lol btw this uses actuate
package;
import motion.Actuate;
import openfl.display.Sprite;
import openfl.events.AsyncErrorEvent;
import openfl.events.MouseEvent;
import openfl.events.NetStatusEvent;
import openfl.media.Video;
import openfl.net.NetConnection;
import openfl.net.NetStream;
import flixel.FlxG;
using StringTools;
class VideoHandler
{
public var netStream:NetStream;
public var video:Video;
public var isReady:Bool = false;
public var addOverlay:Bool = false;
public var vidPath:String = "";
public var ignoreShit:Bool = false;
public function new()
{
isReady = false;
}
public function source(?vPath:String):Void
{
if (vPath != null && vPath.length > 0)
{
vidPath = vPath;
}
}
public function init1():Void
{
isReady = false;
video = new Video();
video.visible = false;
}
public function init2():Void
{
#if web
var netConnection = new NetConnection ();
netConnection.connect (null);
netStream = new NetStream (netConnection);
netStream.client = { onMetaData: client_onMetaData };
netStream.addEventListener (AsyncErrorEvent.ASYNC_ERROR, netStream_onAsyncError);
netConnection.addEventListener (NetStatusEvent.NET_STATUS, netConnection_onNetStatus);
netConnection.addEventListener (NetStatusEvent.NET_STATUS, onPlay);
netConnection.addEventListener (NetStatusEvent.NET_STATUS, onEnd);
#end
}
public function client_onMetaData (metaData:Dynamic) {
video.attachNetStream (netStream);
video.width = FlxG.width;
video.height = FlxG.height;
}
public function netStream_onAsyncError (event:AsyncErrorEvent):Void {
trace ("Error loading video");
}
public function netConnection_onNetStatus (event:NetStatusEvent):Void {
trace (event.info.code);
}
public function play():Void
{
#if web
ignoreShit = true;
netStream.close();
init2();
netStream.play(vidPath);
ignoreShit = false;
#end
trace(vidPath);
}
public function stop():Void
{
netStream.close();
onStop();
}
public function restart():Void
{
play();
onRestart();
}
public function update(elapsed:Float):Void
{
video.x = GlobalVideo.calc(0);
video.y = GlobalVideo.calc(1);
video.width = GlobalVideo.calc(2);
video.height = GlobalVideo.calc(3);
}
public var stopped:Bool = false;
public var restarted:Bool = false;
public var played:Bool = false;
public var ended:Bool = false;
public var paused:Bool = false;
public function pause():Void
{
netStream.pause();
paused = true;
}
public function resume():Void
{
netStream.resume();
paused = false;
}
public function togglePause():Void
{
if (paused)
{
resume();
} else {
pause();
}
}
public function clearPause():Void
{
paused = false;
}
public function onStop():Void
{
if (!ignoreShit)
{
stopped = true;
}
}
public function onRestart():Void
{
restarted = true;
}
public function onPlay(event:NetStatusEvent):Void
{
if (event.info.code == "NetStream.Play.Start")
{
played = true;
}
}
public function onEnd(event:NetStatusEvent):Void
{
if (event.info.code == "NetStream.Play.Complete")
{
ended = true;
}
}
public function alpha():Void
{
video.alpha = GlobalVideo.daAlpha1;
}
public function unalpha():Void
{
video.alpha = GlobalVideo.daAlpha2;
}
public function hide():Void
{
video.visible = false;
}
public function show():Void
{
video.visible = true;
}
}

169
source/WebmHandler.hx Normal file
View File

@ -0,0 +1,169 @@
package;
import flixel.FlxG;
import openfl.display.Sprite;
#if desktop
import webm.*;
#end
class WebmHandler
{
#if desktop
public var webm:WebmPlayer;
public var vidPath:String = "";
public var io:WebmIo;
public var initialized:Bool = false;
public function new()
{
}
public function source(?vPath:String):Void
{
if (vPath != null && vPath.length > 0)
{
vidPath = vPath;
}
}
public function makePlayer():Void
{
io = new WebmIoFile(vidPath);
webm = new WebmPlayer();
webm.fuck(io, false);
webm.addEventListener(WebmEvent.PLAY, function(e) {
onPlay();
});
webm.addEventListener(WebmEvent.COMPLETE, function(e) {
onEnd();
});
webm.addEventListener(WebmEvent.STOP, function(e) {
onStop();
});
webm.addEventListener(WebmEvent.RESTART, function(e) {
onRestart();
});
webm.visible = false;
initialized = true;
}
public function updatePlayer():Void
{
io = new WebmIoFile(vidPath);
webm.fuck(io, false);
}
public function play():Void
{
if (initialized)
{
webm.play();
}
}
public function stop():Void
{
if (initialized)
{
webm.stop();
}
}
public function restart():Void
{
if (initialized)
{
webm.restart();
}
}
public function update(elapsed:Float)
{
webm.x = GlobalVideo.calc(0);
webm.y = GlobalVideo.calc(1);
webm.width = GlobalVideo.calc(2);
webm.height = GlobalVideo.calc(3);
}
public var stopped:Bool = false;
public var restarted:Bool = false;
public var played:Bool = false;
public var ended:Bool = false;
public var paused:Bool = false;
public function pause():Void
{
webm.changePlaying(false);
paused = true;
}
public function resume():Void
{
webm.changePlaying(true);
paused = false;
}
public function togglePause():Void
{
if (paused)
{
resume();
} else {
pause();
}
}
public function clearPause():Void
{
paused = false;
webm.removePause();
}
public function onStop():Void
{
stopped = true;
}
public function onRestart():Void
{
restarted = true;
}
public function onPlay():Void
{
played = true;
}
public function onEnd():Void
{
trace("IT ENDED!");
ended = true;
}
public function alpha():Void
{
webm.alpha = GlobalVideo.daAlpha1;
}
public function unalpha():Void
{
webm.alpha = GlobalVideo.daAlpha2;
}
public function hide():Void
{
webm.visible = false;
}
public function show():Void
{
webm.visible = true;
}
#else
public var webm:Sprite;
public function new()
{
trace("THIS IS ANDROID! or some shit...");
}
#end
}

View File

@ -1,11 +1,6 @@
1.5.2; 1.5.3;
- (1.5.2) Fix crashes on some songs - Score Screen
- Added toggle for ghost tapping - Rewrote the entire hit ranking system
- Officially support macOS (and add macOS requirements to docs) - Fixed song names so they don't crash
- Autoplay - New asset loading system
- Clap assist for syncing charts - New Logo
- Bring back R to reset, but now you can toggle it in the options
- You can now fully customize your keybinds
- Change how replays work + store scroll speed and direction in replays
- Opponent strumline now lights up when they hit a note, like the player's does
- Now using the new recharts from Funkin v0.2.8