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="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-->
<haxelib name="flixel-ui" />
<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
- [KadeDeveloper](https://twitter.com/KadeDeveloper) - Maintainer and lead programmer
- [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">
<a class="headerlink" href="{{site.url}}changelogs/">Changelogs</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>
<br>&nbsp;
<hr>

View File

@ -28,6 +28,9 @@
- `haxelib git faxe https://github.com/uhrobots/faxe`
- `haxelib git polymod https://github.com/larsiusprime/polymod.git`
- `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)
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
- [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.1](changelog-1.5.1)
- [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`.
### Additions
- Nothing here yet!
- Nothing yet!
### Changes
- Nothing here yet!
- Nothing yet!
### Bugfixes
- Nothing here yet!
- Nothing yet!

View File

@ -1,531 +1,2 @@
# Lua Modcharts
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
### RELOCATED
Relocated to [here](https://github.com/KadeDev/Kade-Engine/wiki/)

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 scoreText:FlxText;
var comboText:FlxText;
var diffText:FlxText;
var lerpScore:Int = 0;
var intendedScore:Int = 0;
var combo:String = '';
private var grpSongs:FlxTypedGroup<Alphabet>;
private var curPlaying:Bool = false;
@ -106,6 +108,10 @@ class FreeplayState extends MusicBeatState
diffText.font = scoreText.font;
add(diffText);
comboText = new FlxText(diffText.x + 100, diffText.y, 0, "", 24);
comboText.font = diffText.font;
add(comboText);
add(scoreText);
changeSelection();
@ -176,6 +182,7 @@ class FreeplayState extends MusicBeatState
lerpScore = intendedScore;
scoreText.text = "PERSONAL BEST:" + lerpScore;
comboText.text = combo + '\n';
var upP = controls.UP_P;
var downP = controls.DOWN_P;
@ -202,27 +209,20 @@ class FreeplayState extends MusicBeatState
if (accepted)
{
// pre lowercasing the song name (update)
var songLowercase = StringTools.replace(songs[curSelected].songName, " ", "-").toLowerCase();
switch (songLowercase) {
case 'dad-battle': songLowercase = 'dadbattle';
case 'philly-nice': songLowercase = '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';
// adjusting the song name to be compatible
var songFormat = StringTools.replace(songs[curSelected].songName, " ", "-");
switch (songFormat) {
case 'Dad-Battle': songFormat = 'Dadbattle';
case 'Philly-Nice': songFormat = 'Philly';
}
trace(songLowercase);
trace(songs[curSelected].songName);
var poop:String = Highscore.formatSong(songHighscore, curDifficulty);
var poop:String = Highscore.formatSong(songFormat, curDifficulty);
trace(poop);
PlayState.SONG = Song.loadFromJson(poop, songLowercase);
PlayState.SONG = Song.loadFromJson(poop, songs[curSelected].songName);
PlayState.isStoryMode = false;
PlayState.storyDifficulty = curDifficulty;
PlayState.storyWeek = songs[curSelected].week;
@ -249,6 +249,7 @@ class FreeplayState extends MusicBeatState
#if !switch
intendedScore = Highscore.getScore(songHighscore, curDifficulty);
combo = Highscore.getCombo(songHighscore, curDifficulty);
#end
switch (curDifficulty)
@ -290,6 +291,7 @@ class FreeplayState extends MusicBeatState
#if !switch
intendedScore = Highscore.getScore(songHighscore, curDifficulty);
combo = Highscore.getCombo(songHighscore, curDifficulty);
// lerpScore = 0;
#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
{
public static function truncateFloat( number : Float, precision : Int): Float {
@ -6,4 +8,8 @@ class HelperFunctions
num = Math.round( num ) / Math.pow(10, precision);
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;
using StringTools;
class Highscore
{
#if (haxe >= "4.0.0")
public static var songScores:Map<String, Int> = new Map();
public static var songCombos:Map<String, String> = new Map();
#else
public static var songScores:Map<String, Int> = new Map<String, Int>();
public static var songCombos:Map<String, String> = new Map<String, String>();
#end
@ -32,6 +35,23 @@ class Highscore
}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
{
@ -64,6 +84,14 @@ class Highscore
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
{
var daSong:String = song;
@ -76,6 +104,23 @@ class Highscore
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
{
if (!songScores.exists(formatSong(song, diff)))
@ -84,6 +129,14 @@ class Highscore
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
{
if (!songScores.exists(formatSong('week' + week, diff)))
@ -98,5 +151,9 @@ class Highscore
{
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)
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();
PlayerSettings.player1.controls.loadKeyBinds();
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.setFormat("VCR OSD Mono", 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
add(versionShit);
@ -102,7 +102,7 @@ class LoadReplayState extends MusicBeatState
for (i in 0...songs.length)
{
var pog:FreeplayState.SongMetadata = songs[i];
if (pog.songName.toLowerCase() == songName)
if (pog.songName == songName)
week = pog.week;
}
return week;
@ -148,14 +148,33 @@ class LoadReplayState extends MusicBeatState
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
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);
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;
}
}
}
var isSettingControl:Bool = false;
@ -177,7 +196,7 @@ class LoadReplayState extends MusicBeatState
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;

View File

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

View File

@ -39,7 +39,7 @@ class MainMenuState extends MusicBeatState
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";
var magenta:FlxSprite;

View File

@ -1,6 +1,7 @@
// this file is for modchart things, this is to declutter playstate.hx
// Lua
import openfl.display3D.textures.VideoTexture;
import flixel.graphics.FlxGraphic;
import flixel.graphics.frames.FlxAtlasFrames;
#if windows
@ -255,11 +256,18 @@ class ModchartState
function makeAnimatedLuaSprite(spritePath:String,names:Array<String>,prefixes:Array<String>,startAnim:String, id:String)
{
#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);
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);
@ -282,7 +290,14 @@ class ModchartState
function makeLuaSprite(spritePath:String,toBeCalled:String, drawBehind:Bool)
{
#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 imgWidth:Float = FlxG.width / data.width;
@ -345,7 +360,14 @@ class ModchartState
//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)
{
@ -361,6 +383,8 @@ class ModchartState
setVar("scrollspeed", FlxG.save.data.scrollSpeed != 1 ? FlxG.save.data.scrollSpeed : PlayState.SONG.speed);
setVar("fpsCap", FlxG.save.data.fpsCap);
setVar("downscroll", FlxG.save.data.downscroll);
setVar("flashing", FlxG.save.data.flashing);
setVar("distractions", FlxG.save.data.distractions);
setVar("curStep", 0);
setVar("curBeat", 0);
@ -414,10 +438,43 @@ class ModchartState
return true;
});
// 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) {
PlayState.instance.camHUD.angle = x;
});

View File

@ -50,7 +50,7 @@ class Note extends FlxSprite
x += 50;
// MAKE SURE ITS DEFINITELY OFF SCREEN?
y -= 2000;
this.strumTime = strumTime;
this.strumTime = Math.round(strumTime);
if (this.strumTime < 0 )
this.strumTime = 0;
@ -59,7 +59,14 @@ class Note extends FlxSprite
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':
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 {
return "Safe Frames: " + Conductor.safeFrames +
" - SIK: " + HelperFunctions.truncateFloat(45 * Conductor.timeScale, 0) +
"ms GD: " + HelperFunctions.truncateFloat(90 * Conductor.timeScale, 0) +
" - SIK: " + HelperFunctions.truncateFloat(22 * Conductor.timeScale, 0) +
"ms GD: " + HelperFunctions.truncateFloat(45 * Conductor.timeScale, 0) +
"ms BD: " + HelperFunctions.truncateFloat(135 * Conductor.timeScale, 0) +
"ms SHT: " + HelperFunctions.truncateFloat(155 * Conductor.timeScale, 0) +
"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
@ -614,3 +635,23 @@ class BotPlay extends Option
private override function updateDisplay():String
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 OptionCategory("Appearance", [
#if desktop
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 AccuracyOption("Display accuracy information."),
new NPSDisplayOption("Shows your current Notes Per Second."),
new SongPositionOption("Show the songs current position (as a bar)"),
new CpuStrums("CPU's strumline lights up when a note hits it."),
#else
new DistractionsAndEffectsOption("Toggle stage distractions that can hinder your gameplay.")
#end
]),
@ -58,7 +57,8 @@ class OptionsMenu extends MusicBeatState
#end
new FlashingLightsOption("Toggle flashing lights that can cause epileptic seizures and strain."),
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")
])
];
@ -137,7 +137,10 @@ class OptionsMenu extends MusicBeatState
grpControls.add(controlLabel);
// DONT PUT X IN THE FIRST PARAMETER OF new ALPHABET() !!
}
curSelected = 0;
changeSelection(curSelected);
}
if (controls.UP_P)
changeSelection(-1);
@ -146,7 +149,6 @@ class OptionsMenu extends MusicBeatState
if (isCat)
{
if (currentSelectedCat.getOptions()[curSelected].getAccept())
{
if (FlxG.keys.pressed.SHIFT)
@ -166,7 +168,6 @@ class OptionsMenu extends MusicBeatState
}
else
{
if (FlxG.keys.pressed.SHIFT)
{
if (FlxG.keys.justPressed.RIGHT)
@ -179,7 +180,7 @@ class OptionsMenu extends MusicBeatState
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;
}
if (currentSelectedCat.getOptions()[curSelected].getAccept())
versionShit.text = currentSelectedCat.getOptions()[curSelected].getValue() + " - Description - " + currentDescription;
@ -199,6 +200,8 @@ class OptionsMenu extends MusicBeatState
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;
}
changeSelection(curSelected);
}
}
FlxG.save.flush();

View File

@ -33,6 +33,13 @@ class PauseSubState extends MusicBeatSubstate
{
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.volume = 0;
pauseMusic.play(false, FlxG.random.int(0, Std.int(pauseMusic.length / 2)));
@ -98,13 +105,23 @@ class PauseSubState extends MusicBeatSubstate
super.update(elapsed);
if (PlayState.instance.useVideo)
menuItems.remove('Resume');
var upP = controls.UP_P;
var downP = controls.DOWN_P;
var leftP = controls.LEFT_P;
var rightP = controls.RIGHT_P;
var accepted = controls.ACCEPT;
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)
{
@ -180,8 +197,20 @@ class PauseSubState extends MusicBeatSubstate
case "Resume":
close();
case "Restart Song":
if (PlayState.instance.useVideo)
{
GlobalVideo.get().stop();
PlayState.instance.remove(PlayState.instance.videoSprite);
PlayState.instance.removedVideo = true;
}
FlxG.resetState();
case "Exit to menu":
if (PlayState.instance.useVideo)
{
GlobalVideo.get().stop();
PlayState.instance.remove(PlayState.instance.videoSprite);
PlayState.instance.removedVideo = true;
}
if(PlayState.loadRep)
{
FlxG.save.data.botplay = false;

View File

@ -1,5 +1,6 @@
package;
import webm.WebmPlayer;
import flixel.input.keyboard.FlxKey;
import haxe.Exception;
import openfl.geom.Matrix;
@ -75,6 +76,7 @@ class PlayState extends MusicBeatState
public static var storyPlaylist:Array<String> = [];
public static var storyDifficulty:Int = 1;
public static var weekSong:Int = 0;
public static var weekScore:Int = 0;
public static var shits:Int = 0;
public static var bads:Int = 0;
public static var goods:Int = 0;
@ -103,6 +105,8 @@ class PlayState extends MusicBeatState
private var vocals:FlxSound;
public var originalX:Float;
public static var dad:Character;
public static var gf:Character;
public static var boyfriend:Boyfriend;
@ -128,7 +132,8 @@ class PlayState extends MusicBeatState
public var health:Float = 1; //making public because sethealth doesnt work without it
private var combo:Int = 0;
public static var misses:Int = 0;
private var accuracy:Float = 0.00;
public static var campaignMisses:Int = 0;
public var accuracy:Float = 0.00;
private var accuracyDefault:Float = 0.00;
private var totalNotesHit:Float = 0;
private var totalNotesHitDefault:Float = 0;
@ -176,7 +181,7 @@ class PlayState extends MusicBeatState
var wiggleShit:WiggleEffect = new WiggleEffect();
var talking:Bool = true;
var songScore:Int = 0;
public var songScore:Int = 0;
var songScoreDef:Int = 0;
var scoreTxt:FlxText;
var replayTxt:FlxText;
@ -206,7 +211,9 @@ class PlayState extends MusicBeatState
// BotPlay text
private var botPlayState:FlxText;
// Replay shit
private var saveNotes:Array<Float> = [];
private var saveNotes:Array<Dynamic> = [];
public static var highestCombo:Int = 0;
private var executeModchart = false;
@ -226,16 +233,25 @@ class PlayState extends MusicBeatState
if (FlxG.sound.music != null)
FlxG.sound.music.stop();
if (!isStoryMode)
{
sicks = 0;
bads = 0;
shits = 0;
goods = 0;
}
misses = 0;
repPresses = 0;
repReleases = 0;
PlayStateChangeables.useDownscroll = FlxG.save.data.downscroll;
PlayStateChangeables.safeFrames = FlxG.save.data.frames;
PlayStateChangeables.scrollSpeed = FlxG.save.data.scrollSpeed;
PlayStateChangeables.botPlay = FlxG.save.data.botplay;
// pre lowercasing the song name (create)
var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
switch (songLowercase) {
@ -243,6 +259,8 @@ class PlayState extends MusicBeatState
case 'philly-nice': songLowercase = 'philly';
}
removedVideo = false;
#if windows
executeModchart = FileSystem.exists(Paths.lua(songLowercase + "/modchart"));
#end
@ -309,12 +327,12 @@ class PlayState extends MusicBeatState
persistentDraw = true;
if (SONG == null)
SONG = Song.loadFromJson('tutorial');
SONG = Song.loadFromJson('tutorial', 'tutorial');
Conductor.mapBPMChanges(SONG);
Conductor.changeBPM(SONG.bpm);
trace('INFORMATION ABOUT WHAT U PLAYIN WIT:\nFRAMES: ' + Conductor.safeFrames + '\nZONE: ' + Conductor.safeZoneOffset + '\nTS: ' + Conductor.timeScale + '\nBotPlay : ' + FlxG.save.data.botplay);
trace('INFORMATION ABOUT WHAT U PLAYIN WIT:\nFRAMES: ' + PlayStateChangeables.safeFrames + '\nZONE: ' + Conductor.safeZoneOffset + '\nTS: ' + Conductor.timeScale + '\nBotPlay : ' + PlayStateChangeables.botPlay);
//dialogue shit
switch (songLowercase)
@ -344,7 +362,22 @@ class PlayState extends MusicBeatState
dialogue = CoolUtil.coolTextFile(Paths.txt('thorns/thornsDialogue'));
}
switch(SONG.stage)
//defaults if no stage was found in chart
var stageCheck:String = 'stage';
if (SONG.stage == null) {
switch(storyWeek)
{
case 2: stageCheck = 'halloween';
case 3: stageCheck = 'philly';
case 4: stageCheck = 'limo';
case 5: if (songLowercase == 'winter-horrorland') {stageCheck = 'mallEvil';} else {stageCheck = 'mall';}
case 6: if (songLowercase == 'thorns') {stageCheck = 'schoolEvil';} else {stageCheck = 'school';}
//i should check if its stage (but this is when none is found in chart anyway)
}
} else {stageCheck = SONG.stage;}
switch(stageCheck)
{
case 'halloween':
{
@ -723,21 +756,33 @@ class PlayState extends MusicBeatState
add(stageCurtains);
}
}
var gfVersion:String = 'gf';
switch (SONG.gfVersion)
//defaults if no gf was found in chart
var gfCheck:String = 'gf';
if (SONG.gfVersion == null) {
switch(storyWeek)
{
case 4: gfCheck = 'gf-car';
case 5: gfCheck = 'gf-christmas';
case 6: gfCheck = 'gf-pixel';
}
} else {gfCheck = SONG.gfVersion;}
var curGf:String = '';
switch (gfCheck)
{
case 'gf-car':
gfVersion = 'gf-car';
curGf = 'gf-car';
case 'gf-christmas':
gfVersion = 'gf-christmas';
curGf = 'gf-christmas';
case 'gf-pixel':
gfVersion = 'gf-pixel';
curGf = 'gf-pixel';
default:
gfVersion = 'gf';
curGf = 'gf';
}
gf = new Character(400, 130, gfVersion);
gf = new Character(400, 130, curGf);
gf.scrollFactor.set(0.95, 0.95);
dad = new Character(100, 100, SONG.player2);
@ -837,13 +882,17 @@ class PlayState extends MusicBeatState
{
FlxG.watch.addQuick('rep rpesses',repPresses);
FlxG.watch.addQuick('rep releases',repReleases);
FlxG.save.data.botplay = true;
FlxG.save.data.scrollSpeed = rep.replay.noteSpeed;
FlxG.save.data.downscroll = rep.replay.isDownscroll;
// FlxG.watch.addQuick('Queued',inputsQueued);
PlayStateChangeables.useDownscroll = rep.replay.isDownscroll;
PlayStateChangeables.safeFrames = rep.replay.sf;
PlayStateChangeables.botPlay = true;
}
trace('uh ' + PlayStateChangeables.safeFrames);
trace("SF CALC: " + Math.floor((PlayStateChangeables.safeFrames / 60) * 1000));
var doof:DialogueBox = new DialogueBox(false, dialogue);
// doof.x += 70;
// doof.y = FlxG.height * 0.5;
@ -855,7 +904,7 @@ class PlayState extends MusicBeatState
strumLine = new FlxSprite(0, 50).makeGraphic(FlxG.width, 10);
strumLine.scrollFactor.set();
if (FlxG.save.data.downscroll)
if (PlayStateChangeables.useDownscroll)
strumLine.y = FlxG.height - 165;
strumLineNotes = new FlxTypedGroup<FlxSprite>();
@ -901,7 +950,7 @@ class PlayState extends MusicBeatState
if (FlxG.save.data.songPosition) // I dont wanna talk about this code :(
{
songPosBG = new FlxSprite(0, 10).loadGraphic(Paths.image('healthBar'));
if (FlxG.save.data.downscroll)
if (PlayStateChangeables.useDownscroll)
songPosBG.y = FlxG.height * 0.9 + 45;
songPosBG.screenCenter(X);
songPosBG.scrollFactor.set();
@ -914,7 +963,7 @@ class PlayState extends MusicBeatState
add(songPosBar);
var songName = new FlxText(songPosBG.x + (songPosBG.width / 2) - 20,songPosBG.y,0,SONG.song, 16);
if (FlxG.save.data.downscroll)
if (PlayStateChangeables.useDownscroll)
songName.y -= 3;
songName.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK);
songName.scrollFactor.set();
@ -923,7 +972,7 @@ class PlayState extends MusicBeatState
}
healthBarBG = new FlxSprite(0, FlxG.height * 0.9).loadGraphic(Paths.image('healthBar'));
if (FlxG.save.data.downscroll)
if (PlayStateChangeables.useDownscroll)
healthBarBG.y = 50;
healthBarBG.screenCenter(X);
healthBarBG.scrollFactor.set();
@ -942,32 +991,38 @@ class PlayState extends MusicBeatState
kadeEngineWatermark.scrollFactor.set();
add(kadeEngineWatermark);
if (FlxG.save.data.downscroll)
if (PlayStateChangeables.useDownscroll)
kadeEngineWatermark.y = FlxG.height * 0.9 + 45;
scoreTxt = new FlxText(FlxG.width / 2 - 235, healthBarBG.y + 50, 0, "", 20);
if (!FlxG.save.data.accuracyDisplay)
scoreTxt.x = healthBarBG.x + healthBarBG.width / 2;
scoreTxt.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK);
scoreTxt.screenCenter(X);
originalX = scoreTxt.x;
scoreTxt.scrollFactor.set();
if (offsetTesting)
scoreTxt.x += 300;
if(FlxG.save.data.botplay) scoreTxt.x = FlxG.width / 2 - 20;
scoreTxt.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, FlxTextAlign.CENTER, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK);
add(scoreTxt);
replayTxt = new FlxText(healthBarBG.x + healthBarBG.width / 2 - 75, healthBarBG.y + (FlxG.save.data.downscroll ? 100 : -100), 0, "REPLAY", 20);
replayTxt = new FlxText(healthBarBG.x + healthBarBG.width / 2 - 75, healthBarBG.y + (PlayStateChangeables.useDownscroll ? 100 : -100), 0, "REPLAY", 20);
replayTxt.setFormat(Paths.font("vcr.ttf"), 42, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK);
replayTxt.borderSize = 4;
replayTxt.borderQuality = 2;
replayTxt.scrollFactor.set();
if (loadRep)
{
add(replayTxt);
}
// Literally copy-paste of the above, fu
botPlayState = new FlxText(healthBarBG.x + healthBarBG.width / 2 - 75, healthBarBG.y + (FlxG.save.data.downscroll ? 100 : -100), 0, "BOTPLAY", 20);
botPlayState = new FlxText(healthBarBG.x + healthBarBG.width / 2 - 75, healthBarBG.y + (PlayStateChangeables.useDownscroll ? 100 : -100), 0, "BOTPLAY", 20);
botPlayState.setFormat(Paths.font("vcr.ttf"), 42, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK);
botPlayState.scrollFactor.set();
if(FlxG.save.data.botplay && !loadRep) add(botPlayState);
botPlayState.borderSize = 4;
botPlayState.borderQuality = 2;
if(PlayStateChangeables.botPlay && !loadRep) add(botPlayState);
iconP1 = new HealthIcon(SONG.player1, true);
iconP1.y = healthBar.y - (iconP1.height / 2);
@ -1078,17 +1133,11 @@ class PlayState extends MusicBeatState
senpaiEvil.updateHitbox();
senpaiEvil.screenCenter();
// pre lowercasing the song name (schoolIntro)
var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
switch (songLowercase) {
case 'dad-battle': songLowercase = 'dadbattle';
case 'philly-nice': songLowercase = 'philly';
}
if (songLowercase == 'roses' || songLowercase == 'thorns')
if (StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase() == 'roses' || StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase() == 'thorns')
{
remove(black);
if (songLowercase == 'thorns')
if (StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase() == 'thorns')
{
add(red);
}
@ -1108,7 +1157,7 @@ class PlayState extends MusicBeatState
{
inCutscene = true;
if (songLowercase == 'thorns')
if (StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase() == 'thorns')
{
add(senpaiEvil);
senpaiEvil.alpha = 0;
@ -1169,10 +1218,16 @@ class PlayState extends MusicBeatState
#if windows
// pre lowercasing the song name (startCountdown)
var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
switch (songLowercase) {
case 'dad-battle': songLowercase = 'dadbattle';
case 'philly-nice': songLowercase = 'philly';
}
if (executeModchart)
{
luaModchart = ModchartState.createModchartState();
luaModchart.executeState('start',[PlayState.SONG.song]);
luaModchart.executeState('start',[songLowercase]);
}
#end
@ -1313,7 +1368,7 @@ class PlayState extends MusicBeatState
remove(songName);
songPosBG = new FlxSprite(0, 10).loadGraphic(Paths.image('healthBar'));
if (FlxG.save.data.downscroll)
if (PlayStateChangeables.useDownscroll)
songPosBG.y = FlxG.height * 0.9 + 45;
songPosBG.screenCenter(X);
songPosBG.scrollFactor.set();
@ -1327,7 +1382,7 @@ class PlayState extends MusicBeatState
add(songPosBar);
var songName = new FlxText(songPosBG.x + (songPosBG.width / 2) - 20,songPosBG.y,0,SONG.song, 16);
if (FlxG.save.data.downscroll)
if (PlayStateChangeables.useDownscroll)
songName.y -= 3;
songName.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE,FlxColor.BLACK);
songName.scrollFactor.set();
@ -1345,6 +1400,9 @@ class PlayState extends MusicBeatState
default: allowedToHeadbang = false;
}
if (useVideo)
GlobalVideo.get().resume();
#if windows
// Updating Discord Rich Presence (with Time Left)
DiscordClient.changePresence(detailsText + " " + SONG.song + " (" + storyDifficultyText + ") " + Ratings.GenerateLetterRank(accuracy), "\nAcc: " + HelperFunctions.truncateFloat(accuracy, 2) + "% | Score: " + songScore + " | Misses: " + misses , iconRPC);
@ -1381,14 +1439,15 @@ class PlayState extends MusicBeatState
var playerCounter:Int = 0;
// Per song offset check
#if windows
// pre lowercasing the song name (generateSong)
var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
switch (songLowercase) {
case 'dad-battle': songLowercase = 'dadbattle';
case 'philly-nice': songLowercase = 'philly';
}
// Per song offset check
#if windows
var songPath = 'assets/data/' + songLowercase + '/';
for(file in sys.FileSystem.readDirectory(songPath))
@ -1491,7 +1550,14 @@ class PlayState extends MusicBeatState
// FlxG.log.add(i);
var babyArrow:FlxSprite = new FlxSprite(0, strumLine.y);
switch (SONG.noteStyle)
//defaults if no noteStyle was found in chart
var noteTypeCheck:String = 'normal';
if (SONG.noteStyle == null) {
switch(storyWeek) {case 6: noteTypeCheck = 'pixel';}
} else {noteTypeCheck = SONG.noteStyle;}
switch (noteTypeCheck)
{
case 'pixel':
babyArrow.loadGraphic(Paths.image('weeb/pixelUI/arrows-pixels'), true, 17, 17);
@ -1506,16 +1572,6 @@ class PlayState extends MusicBeatState
switch (Math.abs(i))
{
case 0:
babyArrow.x += Note.swagWidth * 0;
babyArrow.animation.add('static', [0]);
babyArrow.animation.add('pressed', [4, 8], 12, false);
babyArrow.animation.add('confirm', [12, 16], 24, false);
case 1:
babyArrow.x += Note.swagWidth * 1;
babyArrow.animation.add('static', [1]);
babyArrow.animation.add('pressed', [5, 9], 12, false);
babyArrow.animation.add('confirm', [13, 17], 24, false);
case 2:
babyArrow.x += Note.swagWidth * 2;
babyArrow.animation.add('static', [2]);
@ -1526,6 +1582,16 @@ class PlayState extends MusicBeatState
babyArrow.animation.add('static', [3]);
babyArrow.animation.add('pressed', [7, 11], 12, false);
babyArrow.animation.add('confirm', [15, 19], 24, false);
case 1:
babyArrow.x += Note.swagWidth * 1;
babyArrow.animation.add('static', [1]);
babyArrow.animation.add('pressed', [5, 9], 12, false);
babyArrow.animation.add('confirm', [13, 17], 24, false);
case 0:
babyArrow.x += Note.swagWidth * 0;
babyArrow.animation.add('static', [0]);
babyArrow.animation.add('pressed', [4, 8], 12, false);
babyArrow.animation.add('confirm', [12, 16], 24, false);
}
case 'normal':
@ -1706,15 +1772,32 @@ class PlayState extends MusicBeatState
public static var songRate = 1.5;
public var stopUpdate = false;
public var removedVideo = false;
override public function update(elapsed:Float)
{
#if !debug
perfectMode = false;
#end
if (FlxG.save.data.botplay && FlxG.keys.justPressed.ONE)
if (PlayStateChangeables.botPlay && FlxG.keys.justPressed.ONE)
camHUD.visible = !camHUD.visible;
if (useVideo && GlobalVideo.get() != null && !stopUpdate)
{
if (GlobalVideo.get().ended && !removedVideo)
{
remove(videoSprite);
FlxG.stage.window.onFocusOut.remove(focusOut);
FlxG.stage.window.onFocusIn.remove(focusIn);
removedVideo = true;
}
}
#if windows
if (executeModchart && luaModchart != null && songStarted)
{
@ -1817,8 +1900,10 @@ class PlayState extends MusicBeatState
super.update(elapsed);
scoreTxt.text = Ratings.CalculateRanking(songScore,songScoreDef,nps,maxNPS,accuracy);
if (!FlxG.save.data.accuracyDisplay)
scoreTxt.text = "Score: " + songScore;
var lengthInPx = scoreTxt.textField.length * scoreTxt.frameHeight; // bad way but does more or less a better job
scoreTxt.x = (originalX - (lengthInPx / 2)) + 335;
if (FlxG.keys.justPressed.ENTER && startedCountdown && canPause)
{
@ -1838,6 +1923,14 @@ class PlayState extends MusicBeatState
if (FlxG.keys.justPressed.SEVEN)
{
if (useVideo)
{
GlobalVideo.get().stop();
remove(videoSprite);
FlxG.stage.window.onFocusOut.remove(focusOut);
FlxG.stage.window.onFocusIn.remove(focusIn);
removedVideo = true;
}
#if windows
DiscordClient.changePresence("Chart Editor", null, null, true);
#end
@ -1883,6 +1976,15 @@ class PlayState extends MusicBeatState
#if debug
if (FlxG.keys.justPressed.EIGHT)
{
if (useVideo)
{
GlobalVideo.get().stop();
remove(videoSprite);
FlxG.stage.window.onFocusOut.remove(focusOut);
FlxG.stage.window.onFocusIn.remove(focusIn);
removedVideo = true;
}
FlxG.switchState(new AnimationDebug(SONG.player2));
#if windows
if (luaModchart != null)
@ -2230,12 +2332,12 @@ class PlayState extends MusicBeatState
if (!daNote.modifiedByLua)
{
if (FlxG.save.data.downscroll)
if (PlayStateChangeables.useDownscroll)
{
if (daNote.mustPress)
daNote.y = (playerStrums.members[Math.floor(Math.abs(daNote.noteData))].y + 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2));
daNote.y = (playerStrums.members[Math.floor(Math.abs(daNote.noteData))].y + 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, 2));
else
daNote.y = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y + 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2));
daNote.y = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y + 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, 2));
if(daNote.isSustainNote)
{
// Remember = minus makes notes go up, plus makes them go down
@ -2245,7 +2347,7 @@ class PlayState extends MusicBeatState
daNote.y += daNote.height / 2;
// If not in botplay, only clip sustain notes when properly hit, botplay gets to clip it everytime
if(!FlxG.save.data.botplay)
if(!PlayStateChangeables.botPlay)
{
if((!daNote.mustPress || daNote.wasGoodHit || daNote.prevNote.wasGoodHit && !daNote.canBeHit) && daNote.y - daNote.offset.y * daNote.scale.y + daNote.height >= (strumLine.y + Note.swagWidth / 2))
{
@ -2267,14 +2369,14 @@ class PlayState extends MusicBeatState
}else
{
if (daNote.mustPress)
daNote.y = (playerStrums.members[Math.floor(Math.abs(daNote.noteData))].y - 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2));
daNote.y = (playerStrums.members[Math.floor(Math.abs(daNote.noteData))].y - 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, 2));
else
daNote.y = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y - 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(FlxG.save.data.scrollSpeed == 1 ? SONG.speed : FlxG.save.data.scrollSpeed, 2));
daNote.y = (strumLineNotes.members[Math.floor(Math.abs(daNote.noteData))].y - 0.45 * (Conductor.songPosition - daNote.strumTime) * FlxMath.roundDecimal(PlayStateChangeables.scrollSpeed == 1 ? SONG.speed : PlayStateChangeables.scrollSpeed, 2));
if(daNote.isSustainNote)
{
daNote.y -= daNote.height / 2;
if(!FlxG.save.data.botplay)
if(!PlayStateChangeables.botPlay)
{
if((!daNote.mustPress || daNote.wasGoodHit || daNote.prevNote.wasGoodHit && !daNote.canBeHit) && daNote.y + daNote.offset.y * daNote.scale.y <= (strumLine.y + Note.swagWidth / 2))
{
@ -2386,7 +2488,7 @@ class PlayState extends MusicBeatState
// WIP interpolation shit? Need to fix the pause issue
// daNote.y = (strumLine.y - (songTime - daNote.strumTime) * (0.45 * PlayState.SONG.speed));
if ((daNote.mustPress && daNote.tooLate && !FlxG.save.data.downscroll || daNote.mustPress && daNote.tooLate && FlxG.save.data.downscroll) && daNote.mustPress)
if ((daNote.mustPress && daNote.tooLate && !PlayStateChangeables.useDownscroll || daNote.mustPress && daNote.tooLate && PlayStateChangeables.useDownscroll) && daNote.mustPress)
{
if (daNote.isSustainNote && daNote.wasGoodHit)
{
@ -2394,12 +2496,28 @@ class PlayState extends MusicBeatState
notes.remove(daNote, true);
}
else
{
if (loadRep && daNote.isSustainNote)
{
// im tired and lazy this sucks I know i'm dumb
if (findByTime(daNote.strumTime) != null)
totalNotesHit += 1;
else
{
health -= 0.075;
vocals.volume = 0;
if (theFunne)
noteMiss(daNote.noteData, daNote);
}
}
else
{
health -= 0.075;
vocals.volume = 0;
if (theFunne)
noteMiss(daNote.noteData, daNote);
}
}
daNote.visible = false;
daNote.kill();
@ -2433,13 +2551,24 @@ class PlayState extends MusicBeatState
function endSong():Void
{
if (useVideo)
{
GlobalVideo.get().stop();
FlxG.stage.window.onFocusOut.remove(focusOut);
FlxG.stage.window.onFocusIn.remove(focusIn);
PlayState.instance.remove(PlayState.instance.videoSprite);
}
if (isStoryMode)
campaignMisses = misses;
if (!loadRep)
rep.SaveReplay(saveNotes);
else
{
FlxG.save.data.botplay = false;
FlxG.save.data.scrollSpeed = 1;
FlxG.save.data.downscroll = false;
PlayStateChangeables.botPlay = false;
PlayStateChangeables.scrollSpeed = 1;
PlayStateChangeables.useDownscroll = false;
}
if (FlxG.save.data.fpsCap > 290)
@ -2456,6 +2585,8 @@ class PlayState extends MusicBeatState
canPause = false;
FlxG.sound.music.volume = 0;
vocals.volume = 0;
FlxG.sound.music.pause();
vocals.pause();
if (SONG.validScore)
{
// adjusting the highscore song name to be compatible
@ -2468,6 +2599,7 @@ class PlayState extends MusicBeatState
#if !switch
Highscore.saveScore(songHighscore, Math.round(songScore), storyDifficulty);
Highscore.saveCombo(songHighscore, Ratings.GenerateLetterRank(accuracy), storyDifficulty);
#end
}
@ -2488,12 +2620,20 @@ class PlayState extends MusicBeatState
if (storyPlaylist.length <= 0)
{
FlxG.sound.playMusic(Paths.music('freakyMenu'));
transIn = FlxTransitionableState.defaultTransIn;
transOut = FlxTransitionableState.defaultTransOut;
FlxG.switchState(new StoryMenuState());
paused = true;
FlxG.sound.music.stop();
vocals.stop();
if (FlxG.save.data.scoreScreen)
openSubState(new ResultsScreen());
else
{
FlxG.sound.playMusic(Paths.music('freakyMenu'));
FlxG.switchState(new MainMenuState());
}
#if windows
if (luaModchart != null)
@ -2517,30 +2657,20 @@ class PlayState extends MusicBeatState
}
else
{
var difficulty:String = "";
if (storyDifficulty == 0)
difficulty = '-easy';
// 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';
}
if (storyDifficulty == 2)
difficulty = '-hard';
var poop:String = Highscore.formatSong(songFormat, storyDifficulty);
trace('LOADING NEXT SONG');
// pre lowercasing the next story song name
var nextSongLowercase = StringTools.replace(PlayState.storyPlaylist[0], " ", "-").toLowerCase();
switch (nextSongLowercase) {
case 'dad-battle': nextSongLowercase = 'dadbattle';
case 'philly-nice': nextSongLowercase = 'philly';
}
trace(nextSongLowercase + difficulty);
trace(poop);
// pre lowercasing the song name (endSong)
var songLowercase = StringTools.replace(PlayState.SONG.song, " ", "-").toLowerCase();
switch (songLowercase) {
case 'dad-battle': songLowercase = 'dadbattle';
case 'philly-nice': songLowercase = 'philly';
}
if (songLowercase == 'eggnog')
if (StringTools.replace(PlayState.storyPlaylist[0], " ", "-").toLowerCase() == 'eggnog')
{
var blackShit:FlxSprite = new FlxSprite(-FlxG.width * FlxG.camera.zoom,
-FlxG.height * FlxG.camera.zoom).makeGraphic(FlxG.width * 3, FlxG.height * 3, FlxColor.BLACK);
@ -2555,7 +2685,8 @@ class PlayState extends MusicBeatState
FlxTransitionableState.skipNextTransOut = true;
prevCamFollow = camFollow;
PlayState.SONG = Song.loadFromJson(nextSongLowercase + difficulty, PlayState.storyPlaylist[0]);
PlayState.SONG = Song.loadFromJson(poop, PlayState.storyPlaylist[0]);
FlxG.sound.music.stop();
LoadingState.loadAndSwitchState(new PlayState());
@ -2564,7 +2695,17 @@ class PlayState extends MusicBeatState
else
{
trace('WENT BACK TO FREEPLAY??');
FlxG.switchState(new FreeplayState());
paused = true;
FlxG.sound.music.stop();
vocals.stop();
if (FlxG.save.data.scoreScreen)
openSubState(new ResultsScreen());
else
FlxG.switchState(new PlayState());
}
}
}
@ -2580,11 +2721,10 @@ class PlayState extends MusicBeatState
private function popUpScore(daNote:Note):Void
{
var noteDiff:Float = Math.abs(Conductor.songPosition - daNote.strumTime);
var wife:Float = EtternaFunctions.wife3(noteDiff, Conductor.timeScale);
var noteDiff:Float = -(daNote.strumTime - Conductor.songPosition);
var wife:Float = EtternaFunctions.wife3(-noteDiff, Conductor.timeScale);
// boyfriend.playAnim('hey');
vocals.volume = 1;
var placement:String = Std.string(combo);
var coolText:FlxText = new FlxText(0, 0, 0, placement, 32);
@ -2679,7 +2819,10 @@ class PlayState extends MusicBeatState
rating.velocity.x -= FlxG.random.int(0, 10);
var msTiming = HelperFunctions.truncateFloat(noteDiff, 3);
if(FlxG.save.data.botplay) msTiming = 0;
if(PlayStateChangeables.botPlay && !loadRep) msTiming = 0;
if (loadRep)
msTiming = HelperFunctions.truncateFloat(findByTime(daNote.strumTime)[3], 3);
if (currentTimingShown != null)
remove(currentTimingShown);
@ -2725,7 +2868,7 @@ class PlayState extends MusicBeatState
if (currentTimingShown.alpha != 1)
currentTimingShown.alpha = 1;
if(!FlxG.save.data.botplay) add(currentTimingShown);
if(!PlayStateChangeables.botPlay || loadRep) add(currentTimingShown);
var comboSpr:FlxSprite = new FlxSprite().loadGraphic(Paths.image(pixelShitPart1 + 'combo' + pixelShitPart2));
comboSpr.screenCenter();
@ -2742,7 +2885,7 @@ class PlayState extends MusicBeatState
comboSpr.velocity.x += FlxG.random.int(1, 10);
currentTimingShown.velocity.x += comboSpr.velocity.x;
if(!FlxG.save.data.botplay) add(rating);
if(!PlayStateChangeables.botPlay || loadRep) add(rating);
if (!curStage.startsWith('school'))
{
@ -2769,6 +2912,9 @@ class PlayState extends MusicBeatState
var comboSplit:Array<String> = (combo + "").split('');
if (combo > highestCombo)
highestCombo = combo;
// make sure we have 3 digits to display (looks weird otherwise lol)
if (comboSplit.length == 1)
{
@ -2893,7 +3039,7 @@ class PlayState extends MusicBeatState
#end
// Prevent player input if botplay is on
if(FlxG.save.data.botplay)
if(PlayStateChangeables.botPlay)
{
holdArray = [false, false, false, false];
pressArray = [false, false, false, false];
@ -2953,8 +3099,6 @@ class PlayState extends MusicBeatState
}
});
trace('\nCURRENT LINE:\n' + directionsAccounted);
for (note in dumbNotes)
{
FlxG.log.add("killing dumb ass note at " + note.strumTime);
@ -3003,7 +3147,7 @@ class PlayState extends MusicBeatState
noteMiss(shit, null);
}
if(dontCheck && possibleNotes.length > 0 && FlxG.save.data.ghost && !FlxG.save.data.botplay)
if(dontCheck && possibleNotes.length > 0 && FlxG.save.data.ghost && !PlayStateChangeables.botPlay)
{
if (mashViolations > 8)
{
@ -3019,17 +3163,19 @@ class PlayState extends MusicBeatState
notes.forEachAlive(function(daNote:Note)
{
if(FlxG.save.data.downscroll && daNote.y > strumLine.y ||
!FlxG.save.data.downscroll && daNote.y < strumLine.y)
if(PlayStateChangeables.useDownscroll && daNote.y > strumLine.y ||
!PlayStateChangeables.useDownscroll && daNote.y < strumLine.y)
{
// Force good note hit regardless if it's too late to hit it or not as a fail safe
if(FlxG.save.data.botplay && daNote.canBeHit && daNote.mustPress ||
FlxG.save.data.botplay && daNote.tooLate && daNote.mustPress)
if(PlayStateChangeables.botPlay && daNote.canBeHit && daNote.mustPress ||
PlayStateChangeables.botPlay && daNote.tooLate && daNote.mustPress)
{
if(loadRep)
{
//trace('ReplayNote ' + tmpRepNote.strumtime + ' | ' + tmpRepNote.direction);
if(rep.replay.songNotes.contains(HelperFunctions.truncateFloat(daNote.strumTime, 2)))
var n = findByTime(daNote.strumTime);
trace(n);
if(n != null)
{
goodNoteHit(daNote);
boyfriend.holdTimer = daNote.sustainLength;
@ -3042,7 +3188,7 @@ class PlayState extends MusicBeatState
}
});
if (boyfriend.holdTimer > Conductor.stepCrochet * 4 * 0.001 && (!holdArray.contains(true) || FlxG.save.data.botplay))
if (boyfriend.holdTimer > Conductor.stepCrochet * 4 * 0.001 && (!holdArray.contains(true) || PlayStateChangeables.botPlay))
{
if (boyfriend.animation.curAnim.name.startsWith('sing') && !boyfriend.animation.curAnim.name.endsWith('miss'))
boyfriend.playAnim('idle');
@ -3066,6 +3212,101 @@ class PlayState extends MusicBeatState
});
}
public function findByTime(time:Float):Array<Dynamic>
{
for (i in rep.replay.songNotes)
{
//trace('checking ' + Math.round(i[0]) + ' against ' + Math.round(time));
if (i[0] == time)
return i;
}
return null;
}
public var fuckingVolume:Float = 1;
public var useVideo = false;
public static var webmHandler:WebmHandler;
public var playingDathing = false;
public var videoSprite:FlxSprite;
public function focusOut() {
if (paused)
return;
persistentUpdate = false;
persistentDraw = true;
paused = true;
if (FlxG.sound.music != null)
{
FlxG.sound.music.pause();
vocals.pause();
}
openSubState(new PauseSubState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y));
}
public function focusIn()
{
// nada
}
public function backgroundVideo(source:String) // for background videos
{
useVideo = true;
FlxG.stage.window.onFocusOut.add(focusOut);
FlxG.stage.window.onFocusIn.add(focusIn);
var ourSource:String = "assets/videos/daWeirdVid/dontDelete.webm";
WebmPlayer.SKIP_STEP_LIMIT = 90;
var str1:String = "WEBM SHIT";
webmHandler = new WebmHandler();
webmHandler.source(ourSource);
webmHandler.makePlayer();
webmHandler.webm.name = str1;
GlobalVideo.setWebm(webmHandler);
GlobalVideo.get().source(source);
GlobalVideo.get().clearPause();
if (GlobalVideo.isWebm)
{
GlobalVideo.get().updatePlayer();
}
GlobalVideo.get().show();
if (GlobalVideo.isWebm)
{
GlobalVideo.get().restart();
} else {
GlobalVideo.get().play();
}
var data = webmHandler.webm.bitmapData;
videoSprite = new FlxSprite(-470,-30).loadGraphic(data);
videoSprite.setGraphicSize(Std.int(videoSprite.width * 1.2));
remove(gf);
remove(boyfriend);
remove(dad);
add(videoSprite);
add(gf);
add(boyfriend);
add(dad);
trace('poggers');
if (!songStarted)
webmHandler.pause();
else
webmHandler.resume();
}
function noteMiss(direction:Int = 1, daNote:Note):Void
{
if (!boyfriend.stunned)
@ -3078,6 +3319,15 @@ class PlayState extends MusicBeatState
combo = 0;
misses++;
if (daNote != null)
{
if (!loadRep)
saveNotes.push([daNote.strumTime,0,direction,166 * Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166]);
}
else
if (!loadRep)
saveNotes.push([Conductor.songPosition,0,direction,166 * Math.floor((PlayState.rep.replay.sf / 60) * 1000) / 166]);
//var noteDiff:Float = Math.abs(daNote.strumTime - Conductor.songPosition);
//var wife:Float = EtternaFunctions.wife3(noteDiff, FlxG.save.data.etternaMode ? 1 : 1.7);
@ -3164,9 +3414,9 @@ class PlayState extends MusicBeatState
function noteCheck(controlArray:Array<Bool>, note:Note):Void // sorry lol
{
var noteDiff:Float = Math.abs(note.strumTime - Conductor.songPosition);
var noteDiff:Float = -(note.strumTime - Conductor.songPosition);
note.rating = Ratings.CalculateRating(noteDiff);
note.rating = Ratings.CalculateRating(noteDiff, Math.floor((PlayStateChangeables.safeFrames / 60) * 1000));
/* if (loadRep)
{
@ -3215,10 +3465,16 @@ class PlayState extends MusicBeatState
if (mashing != 0)
mashing = 0;
var noteDiff:Float = Math.abs(note.strumTime - Conductor.songPosition);
var noteDiff:Float = -(note.strumTime - Conductor.songPosition);
if(loadRep)
noteDiff = findByTime(note.strumTime)[3];
note.rating = Ratings.CalculateRating(noteDiff);
if (note.rating == "miss")
return;
// add newest note to front of notesHitArray
// the oldest notes are at the end and are removed first
if (!note.isSustainNote)
@ -3260,7 +3516,13 @@ class PlayState extends MusicBeatState
if(!loadRep && note.mustPress)
saveNotes.push(HelperFunctions.truncateFloat(note.strumTime, 2));
{
var array = [note.strumTime,note.sustainLength,note.noteData,noteDiff];
if (note.isSustainNote)
array[1] = -1;
trace('pushing ' + array[0]);
saveNotes.push(array);
}
playerStrums.forEach(function(spr:FlxSprite)
{
@ -3399,8 +3661,6 @@ class PlayState extends MusicBeatState
}
#end
// yes this updates every step.
// yes this is bad
// but i'm doing it to update misses and accuracy
@ -3423,7 +3683,7 @@ class PlayState extends MusicBeatState
if (generatedMusic)
{
notes.sort(FlxSort.byY, (FlxG.save.data.downscroll ? FlxSort.ASCENDING : FlxSort.DESCENDING));
notes.sort(FlxSort.byY, (PlayStateChangeables.useDownscroll ? FlxSort.ASCENDING : FlxSort.DESCENDING));
}
#if windows
@ -3458,6 +3718,8 @@ class PlayState extends MusicBeatState
// FlxG.log.add('change bpm' + SONG.notes[Std.int(curStep / 16)].changeBPM);
wiggleShit.update(Conductor.crochet);
if (FlxG.save.data.camzoom)
{
// HARDCODING FOR MILF ZOOMS!
if (curSong.toLowerCase() == 'milf' && curBeat >= 168 && curBeat < 200 && camZooming && FlxG.camera.zoom < 1.35)
{
@ -3471,6 +3733,8 @@ class PlayState extends MusicBeatState
camHUD.zoom += 0.03;
}
}
iconP1.setGraphicSize(Std.int(iconP1.width + 30));
iconP2.setGraphicSize(Std.int(iconP2.width + 30));

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

View File

@ -17,14 +17,15 @@ typedef ReplayJSON =
public var timestamp:Date;
public var songName:String;
public var songDiff:Int;
public var songNotes:Array<Float>;
public var songNotes:Array<Dynamic>;
public var noteSpeed:Float;
public var isDownscroll:Bool;
public var sf:Int;
}
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 replay:ReplayJSON;
@ -32,13 +33,14 @@ class Replay
{
this.path = path;
replay = {
songName: "Tutorial",
songName: "No Song Found",
songDiff: 1,
noteSpeed: 1.5,
isDownscroll: false,
songNotes: [],
replayGameVer: version,
timestamp: Date.now()
timestamp: Date.now(),
sf: Conductor.safeFrames
};
}
@ -48,27 +50,34 @@ class Replay
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;
}
public function SaveReplay(notearray:Array<Float>)
public function SaveReplay(notearray:Array<Dynamic>)
{
var json = {
"songName": PlayState.SONG.song.toLowerCase(),
"songName": PlayState.SONG.song,
"songDiff": PlayState.storyDifficulty,
"noteSpeed": (FlxG.save.data.scrollSpeed > 1 ? FlxG.save.data.scrollSpeed : PlayState.SONG.speed),
"isDownscroll": FlxG.save.data.downscroll,
"songNotes": notearray,
"timestamp": Date.now(),
"replayGameVer": version
"replayGameVer": version,
"sf": Conductor.safeFrames
};
var data:String = Json.stringify(json);
var time = Date.now().getTime();
#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);
path = "replay-" + PlayState.SONG.song + "-time" + time + ".kadeReplay"; // for score screen shit
LoadFromJSON();
#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 player2:String = 'dad';
public var gfVersion:String = 'gf';
public var noteStyle:String = 'normal';
public var stage:String = 'stage';
public var gfVersion:String = '';
public var noteStyle:String = '';
public var stage:String = '';
public function new(song, notes, bpm)
{
@ -48,7 +48,7 @@ class Song
{
trace(jsonInput);
// pre lowercasing the song name (update)
// pre lowercasing the folder name
var folderLowercase = StringTools.replace(folder, " ", "-").toLowerCase();
switch (folderLowercase) {
case 'dad-battle': folderLowercase = 'dadbattle';

View File

@ -285,19 +285,23 @@ class StoryMenuState extends MusicBeatState
PlayState.isStoryMode = true;
selectedWeek = true;
var diffic = "";
switch (curDifficulty)
{
case 0:
diffic = '-easy';
case 2:
diffic = '-hard';
}
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.campaignScore = 0;
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.2) Fix crashes on some songs
- Added toggle for ghost tapping
- Officially support macOS (and add macOS requirements to docs)
- Autoplay
- Clap assist for syncing charts
- 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
1.5.3;
- Score Screen
- Rewrote the entire hit ranking system
- Fixed song names so they don't crash
- New asset loading system
- New Logo