mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2025-03-23 10:29:29 +00:00
Stable, only position adjustments needed.
This commit is contained in:
parent
386e8db830
commit
3634346072
|
@ -25,6 +25,7 @@ import funkin.freeplayStuff.BGScrollingText;
|
|||
import funkin.freeplayStuff.DJBoyfriend;
|
||||
import funkin.freeplayStuff.FreeplayScore;
|
||||
import funkin.freeplayStuff.SongMenuItem;
|
||||
import funkin.play.HealthIcon;
|
||||
import lime.app.Future;
|
||||
import lime.utils.Assets;
|
||||
import funkin.shaderslmfao.AngleMask;
|
||||
|
@ -295,7 +296,7 @@ class FreeplayState extends MusicBeatSubstate
|
|||
// grpSongs.add(songText);
|
||||
|
||||
var icon:HealthIcon = new HealthIcon(songs[i].songCharacter);
|
||||
icon.sprTracker = songText;
|
||||
// icon.sprTracker = songText;
|
||||
|
||||
// using a FlxGroup is too much fuss!
|
||||
iconArray.push(icon);
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
package funkin;
|
||||
|
||||
import flixel.FlxSprite;
|
||||
import openfl.utils.Assets;
|
||||
import funkin.play.PlayState;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class HealthIcon extends FlxSprite
|
||||
{
|
||||
/**
|
||||
* Used for FreeplayState! If you use it elsewhere, prob gonna annoying
|
||||
*/
|
||||
public var sprTracker:FlxSprite;
|
||||
|
||||
public var char:String = '';
|
||||
|
||||
var isPlayer:Bool = false;
|
||||
|
||||
public function new(char:String = 'bf', isPlayer:Bool = false)
|
||||
{
|
||||
super();
|
||||
|
||||
this.isPlayer = isPlayer;
|
||||
|
||||
antialiasing = true;
|
||||
changeIcon(char);
|
||||
scrollFactor.set();
|
||||
}
|
||||
|
||||
public var isOldIcon:Bool = false;
|
||||
|
||||
public function swapOldIcon():Void
|
||||
{
|
||||
isOldIcon = !isOldIcon;
|
||||
|
||||
if (isOldIcon)
|
||||
changeIcon('bf-old');
|
||||
else
|
||||
changeIcon(PlayState.currentSong.player1);
|
||||
}
|
||||
|
||||
var pixelArrayFunny:Array<String> = CoolUtil.coolTextFile(Paths.file('images/icons/pixelIcons.txt'));
|
||||
|
||||
public function changeIcon(newChar:String):Void
|
||||
{
|
||||
if (newChar != 'bf-pixel' && newChar != 'bf-old')
|
||||
newChar = newChar.split('-')[0].trim();
|
||||
|
||||
if (!Assets.exists(Paths.image('icons/icon-' + newChar)))
|
||||
{
|
||||
FlxG.log.warn('No icon with data: $newChar : using default placeholder face instead!');
|
||||
newChar = "face";
|
||||
}
|
||||
|
||||
if (newChar != char)
|
||||
{
|
||||
if (animation.getByName(newChar) == null)
|
||||
{
|
||||
var imgSize:Int = 150;
|
||||
|
||||
if (newChar.endsWith('pixel') || pixelArrayFunny.contains(newChar))
|
||||
imgSize = 32;
|
||||
|
||||
loadGraphic(Paths.image('icons/icon-' + newChar), true, imgSize, imgSize);
|
||||
|
||||
animation.add(newChar, [0, 1], 0, false, isPlayer);
|
||||
}
|
||||
animation.play(newChar);
|
||||
char = newChar;
|
||||
|
||||
if (newChar.endsWith('pixel') || pixelArrayFunny.contains(newChar))
|
||||
antialiasing = false;
|
||||
else
|
||||
antialiasing = true;
|
||||
setGraphicSize(150);
|
||||
updateHitbox();
|
||||
}
|
||||
}
|
||||
|
||||
override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
if (sprTracker != null)
|
||||
setPosition(sprTracker.x + sprTracker.width + 10, sprTracker.y - 30);
|
||||
}
|
||||
}
|
|
@ -46,9 +46,6 @@ class MusicBeatState extends FlxUIState
|
|||
{
|
||||
super.create();
|
||||
|
||||
if (transIn != null)
|
||||
trace('reg ' + transIn.region);
|
||||
|
||||
createWatermarkText();
|
||||
}
|
||||
|
||||
|
|
|
@ -189,8 +189,11 @@ class SongLoad
|
|||
noteStuff[sectionIndex].sectionNotes[noteIndex].strumTime = arrayDipshit[0];
|
||||
noteStuff[sectionIndex].sectionNotes[noteIndex].noteData = arrayDipshit[1];
|
||||
noteStuff[sectionIndex].sectionNotes[noteIndex].sustainLength = arrayDipshit[2];
|
||||
noteStuff[sectionIndex].sectionNotes[noteIndex].altNote = arrayDipshit[3];
|
||||
if (arrayDipshit.length >= 5)
|
||||
if (arrayDipshit.length > 3)
|
||||
{
|
||||
noteStuff[sectionIndex].sectionNotes[noteIndex].altNote = arrayDipshit[3];
|
||||
}
|
||||
if (arrayDipshit.length > 4)
|
||||
{
|
||||
noteStuff[sectionIndex].sectionNotes[noteIndex].noteKind = arrayDipshit[4];
|
||||
}
|
||||
|
|
|
@ -116,8 +116,6 @@ class StoryMenuState extends MusicBeatState
|
|||
grpLocks = new FlxTypedGroup<FlxSprite>();
|
||||
add(grpLocks);
|
||||
|
||||
trace("Line 70");
|
||||
|
||||
#if discord_rpc
|
||||
// Updating Discord Rich Presence
|
||||
DiscordClient.changePresence("In the Menus", null);
|
||||
|
@ -147,8 +145,6 @@ class StoryMenuState extends MusicBeatState
|
|||
}
|
||||
}
|
||||
|
||||
trace("Line 96");
|
||||
|
||||
for (char in 0...3)
|
||||
{
|
||||
var weekCharacterThing:MenuCharacter = new MenuCharacter((FlxG.width * 0.25) * (1 + char) - 150, weekCharacters[curWeek][char]);
|
||||
|
@ -180,8 +176,6 @@ class StoryMenuState extends MusicBeatState
|
|||
difficultySelectors = new FlxGroup();
|
||||
add(difficultySelectors);
|
||||
|
||||
trace("Line 124");
|
||||
|
||||
leftArrow = new FlxSprite(grpWeekText.members[0].x + grpWeekText.members[0].width + 10, grpWeekText.members[0].y + 10);
|
||||
leftArrow.frames = ui_tex;
|
||||
leftArrow.animation.addByPrefix('idle', "arrow left");
|
||||
|
@ -206,8 +200,6 @@ class StoryMenuState extends MusicBeatState
|
|||
rightArrow.animation.play('idle');
|
||||
difficultySelectors.add(rightArrow);
|
||||
|
||||
trace("Line 150");
|
||||
|
||||
add(yellowBG);
|
||||
add(grpWeekCharacters);
|
||||
|
||||
|
@ -222,8 +214,6 @@ class StoryMenuState extends MusicBeatState
|
|||
|
||||
updateText();
|
||||
|
||||
trace("Line 165");
|
||||
|
||||
super.create();
|
||||
}
|
||||
|
||||
|
|
|
@ -189,8 +189,6 @@ class TitleState extends MusicBeatState
|
|||
gfDance.antialiasing = true;
|
||||
add(gfDance);
|
||||
|
||||
trace('MACRO TEST: ${gfDance.zIndex}');
|
||||
|
||||
// alphaShader.shader.funnyShit.input = gfDance.pixels; // old shit
|
||||
|
||||
logoBl.shader = alphaShader.shader;
|
||||
|
|
78
source/funkin/api/newgrounds/NGUnsafe.hx
Normal file
78
source/funkin/api/newgrounds/NGUnsafe.hx
Normal file
|
@ -0,0 +1,78 @@
|
|||
package funkin.api.newgrounds;
|
||||
|
||||
import flixel.util.FlxSignal;
|
||||
import flixel.util.FlxTimer;
|
||||
import lime.app.Application;
|
||||
import openfl.display.Stage;
|
||||
#if newgrounds
|
||||
import io.newgrounds.NG;
|
||||
import io.newgrounds.NGLite;
|
||||
import io.newgrounds.components.ScoreBoardComponent.Period;
|
||||
import io.newgrounds.objects.Error;
|
||||
import io.newgrounds.objects.Medal;
|
||||
import io.newgrounds.objects.Score;
|
||||
import io.newgrounds.objects.ScoreBoard;
|
||||
import io.newgrounds.objects.events.Response;
|
||||
import io.newgrounds.objects.events.Result.GetCurrentVersionResult;
|
||||
import io.newgrounds.objects.events.Result.GetVersionResult;
|
||||
#end
|
||||
|
||||
using StringTools;
|
||||
|
||||
/**
|
||||
* Contains any script functions which should be BLOCKED from use by modded scripts.
|
||||
*/
|
||||
class NGUnsafe
|
||||
{
|
||||
static public function logEvent(event:String)
|
||||
{
|
||||
#if newgrounds
|
||||
NG.core.calls.event.logEvent(event).send();
|
||||
trace('should have logged: ' + event);
|
||||
#else
|
||||
#if debug
|
||||
trace('event:$event - not logged, missing NG.io lib');
|
||||
#end
|
||||
#end
|
||||
}
|
||||
|
||||
static public function unlockMedal(id:Int)
|
||||
{
|
||||
#if newgrounds
|
||||
if (isLoggedIn)
|
||||
{
|
||||
var medal = NG.core.medals.get(id);
|
||||
if (!medal.unlocked)
|
||||
medal.sendUnlock();
|
||||
}
|
||||
#else
|
||||
#if debug
|
||||
trace('medal:$id - not unlocked, missing NG.io lib');
|
||||
#end
|
||||
#end
|
||||
}
|
||||
|
||||
static public function postScore(score:Int = 0, song:String)
|
||||
{
|
||||
#if newgrounds
|
||||
if (isLoggedIn)
|
||||
{
|
||||
for (id in NG.core.scoreBoards.keys())
|
||||
{
|
||||
var board = NG.core.scoreBoards.get(id);
|
||||
|
||||
if (song == board.name)
|
||||
{
|
||||
board.postScore(score, "Uhh meow?");
|
||||
}
|
||||
|
||||
// trace('loaded scoreboard id:$id, name:${board.name}');
|
||||
}
|
||||
}
|
||||
#else
|
||||
#if debug
|
||||
trace('Song:$song, Score:$score - not posted, missing NG.io lib');
|
||||
#end
|
||||
#end
|
||||
}
|
||||
}
|
260
source/funkin/api/newgrounds/NGUtil.hx
Normal file
260
source/funkin/api/newgrounds/NGUtil.hx
Normal file
|
@ -0,0 +1,260 @@
|
|||
package funkin.api.newgrounds;
|
||||
|
||||
import flixel.util.FlxSignal;
|
||||
import flixel.util.FlxTimer;
|
||||
import lime.app.Application;
|
||||
import openfl.display.Stage;
|
||||
#if newgrounds
|
||||
import io.newgrounds.NG;
|
||||
import io.newgrounds.NGLite;
|
||||
import io.newgrounds.components.ScoreBoardComponent.Period;
|
||||
import io.newgrounds.objects.Error;
|
||||
import io.newgrounds.objects.Medal;
|
||||
import io.newgrounds.objects.Score;
|
||||
import io.newgrounds.objects.ScoreBoard;
|
||||
import io.newgrounds.objects.events.Response;
|
||||
import io.newgrounds.objects.events.Result.GetCurrentVersionResult;
|
||||
import io.newgrounds.objects.events.Result.GetVersionResult;
|
||||
#end
|
||||
|
||||
using StringTools;
|
||||
|
||||
/**
|
||||
* Contains any script functions which should be ALLOWD for use by modded scripts.
|
||||
*/
|
||||
class NGUtil
|
||||
{
|
||||
#if newgrounds
|
||||
/**
|
||||
* True, if the saved sessionId was used in the initial login, and failed to connect.
|
||||
* Used in MainMenuState to show a popup to establish a new connection
|
||||
*/
|
||||
public static var savedSessionFailed(default, null):Bool = false;
|
||||
|
||||
public static var scoreboardsLoaded:Bool = false;
|
||||
public static var isLoggedIn(get, never):Bool;
|
||||
|
||||
inline static function get_isLoggedIn()
|
||||
{
|
||||
return NG.core != null && NG.core.loggedIn;
|
||||
}
|
||||
|
||||
public static var scoreboardArray:Array<Score> = [];
|
||||
|
||||
public static var ngDataLoaded(default, null):FlxSignal = new FlxSignal();
|
||||
public static var ngScoresLoaded(default, null):FlxSignal = new FlxSignal();
|
||||
|
||||
public static var GAME_VER:String = "";
|
||||
|
||||
static public function checkVersion(callback:String->Void)
|
||||
{
|
||||
trace('checking NG.io version');
|
||||
GAME_VER = "v" + Application.current.meta.get('version');
|
||||
|
||||
NG.core.calls.app.getCurrentVersion(GAME_VER).addDataHandler(function(response)
|
||||
{
|
||||
GAME_VER = response.result.data.currentVersion;
|
||||
trace('CURRENT NG VERSION: ' + GAME_VER);
|
||||
callback(GAME_VER);
|
||||
}).send();
|
||||
}
|
||||
|
||||
static public function init()
|
||||
{
|
||||
var api = APIStuff.API;
|
||||
if (api == null || api.length == 0)
|
||||
{
|
||||
trace("Missing Newgrounds API key, aborting connection");
|
||||
return;
|
||||
}
|
||||
trace("connecting to newgrounds");
|
||||
|
||||
#if NG_FORCE_EXPIRED_SESSION
|
||||
var sessionId:String = "fake_session_id";
|
||||
function onSessionFail(error:Error)
|
||||
{
|
||||
trace("Forcing an expired saved session. " + "To disable, comment out NG_FORCE_EXPIRED_SESSION in Project.xml");
|
||||
savedSessionFailed = true;
|
||||
}
|
||||
#else
|
||||
var sessionId:String = NGLite.getSessionId();
|
||||
if (sessionId != null)
|
||||
trace("found web session id");
|
||||
|
||||
#if (debug)
|
||||
if (sessionId == null && APIStuff.SESSION != null)
|
||||
{
|
||||
trace("using debug session id");
|
||||
sessionId = APIStuff.SESSION;
|
||||
}
|
||||
#end
|
||||
|
||||
var onSessionFail:Error->Void = null;
|
||||
if (sessionId == null && FlxG.save.data.sessionId != null)
|
||||
{
|
||||
trace("using stored session id");
|
||||
sessionId = FlxG.save.data.sessionId;
|
||||
onSessionFail = function(error) savedSessionFailed = true;
|
||||
}
|
||||
#end
|
||||
|
||||
NG.create(api, sessionId, #if NG_DEBUG true #else false #end, onSessionFail);
|
||||
|
||||
#if NG_VERBOSE
|
||||
NG.core.verbose = true;
|
||||
#end
|
||||
// Set the encryption cipher/format to RC4/Base64. AES128 and Hex are not implemented yet
|
||||
NG.core.initEncryption(APIStuff.EncKey); // Found in you NG project view
|
||||
|
||||
if (NG.core.attemptingLogin)
|
||||
{
|
||||
/* a session_id was found in the loadervars, this means the user is playing on newgrounds.com
|
||||
* and we should login shortly. lets wait for that to happen
|
||||
*/
|
||||
trace("attempting login");
|
||||
NG.core.onLogin.add(onNGLogin);
|
||||
}
|
||||
// GK: taking out auto login, adding a login button to the main menu
|
||||
// else
|
||||
// {
|
||||
// /* They are NOT playing on newgrounds.com, no session id was found. We must start one manually, if we want to.
|
||||
// * Note: This will cause a new browser window to pop up where they can log in to newgrounds
|
||||
// */
|
||||
// NG.core.requestLogin(onNGLogin);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to log in to newgrounds by requesting a new session ID, only call if no session ID was found automatically
|
||||
* @param popupLauncher The function to call to open the login url, must be inside
|
||||
* a user input event or the popup blocker will block it.
|
||||
* @param onComplete A callback with the result of the connection.
|
||||
*/
|
||||
static public function login(?popupLauncher:(Void->Void)->Void, onComplete:ConnectionResult->Void)
|
||||
{
|
||||
trace("Logging in manually");
|
||||
var onPending:Void->Void = null;
|
||||
if (popupLauncher != null)
|
||||
{
|
||||
onPending = function() popupLauncher(NG.core.openPassportUrl);
|
||||
}
|
||||
|
||||
var onSuccess:Void->Void = onNGLogin;
|
||||
var onFail:Error->Void = null;
|
||||
var onCancel:Void->Void = null;
|
||||
if (onComplete != null)
|
||||
{
|
||||
onSuccess = function()
|
||||
{
|
||||
onNGLogin();
|
||||
onComplete(Success);
|
||||
}
|
||||
onFail = function(e) onComplete(Fail(e.message));
|
||||
onCancel = function() onComplete(Cancelled);
|
||||
}
|
||||
|
||||
NG.core.requestLogin(onSuccess, onPending, onFail, onCancel);
|
||||
}
|
||||
|
||||
inline static public function cancelLogin():Void
|
||||
{
|
||||
NG.core.cancelLoginRequest();
|
||||
}
|
||||
|
||||
static function onNGLogin():Void
|
||||
{
|
||||
trace('logged in! user:${NG.core.user.name}');
|
||||
FlxG.save.data.sessionId = NG.core.sessionId;
|
||||
FlxG.save.flush();
|
||||
// Load medals then call onNGMedalFetch()
|
||||
NG.core.requestMedals(onNGMedalFetch);
|
||||
|
||||
// Load Scoreboards hten call onNGBoardsFetch()
|
||||
NG.core.requestScoreBoards(onNGBoardsFetch);
|
||||
|
||||
ngDataLoaded.dispatch();
|
||||
}
|
||||
|
||||
static public function logout()
|
||||
{
|
||||
NG.core.logOut();
|
||||
|
||||
FlxG.save.data.sessionId = null;
|
||||
FlxG.save.flush();
|
||||
}
|
||||
|
||||
// --- MEDALS
|
||||
static function onNGMedalFetch():Void
|
||||
{
|
||||
/*
|
||||
// Reading medal info
|
||||
for (id in NG.core.medals.keys())
|
||||
{
|
||||
var medal = NG.core.medals.get(id);
|
||||
trace('loaded medal id:$id, name:${medal.name}, description:${medal.description}');
|
||||
}
|
||||
|
||||
// Unlocking medals
|
||||
var unlockingMedal = NG.core.medals.get(54352);// medal ids are listed in your NG project viewer
|
||||
if (!unlockingMedal.unlocked)
|
||||
unlockingMedal.sendUnlock();
|
||||
*/
|
||||
}
|
||||
|
||||
// --- SCOREBOARDS
|
||||
static function onNGBoardsFetch():Void
|
||||
{
|
||||
/*
|
||||
// Reading medal info
|
||||
for (id in NG.core.scoreBoards.keys())
|
||||
{
|
||||
var board = NG.core.scoreBoards.get(id);
|
||||
trace('loaded scoreboard id:$id, name:${board.name}');
|
||||
}
|
||||
*/
|
||||
// var board = NG.core.scoreBoards.get(8004);// ID found in NG project view
|
||||
|
||||
// Posting a score thats OVER 9000!
|
||||
// board.postScore(FlxG.random.int(0, 1000));
|
||||
|
||||
// --- To view the scores you first need to select the range of scores you want to see ---
|
||||
|
||||
// add an update listener so we know when we get the new scores
|
||||
// board.onUpdate.add(onNGScoresFetch);
|
||||
trace("shoulda got score by NOW!");
|
||||
// board.requestScores(20);// get the best 10 scores ever logged
|
||||
// more info on scores --- http://www.newgrounds.io/help/components/#scoreboard-getscores
|
||||
}
|
||||
|
||||
static function onNGScoresFetch():Void
|
||||
{
|
||||
scoreboardsLoaded = true;
|
||||
|
||||
ngScoresLoaded.dispatch();
|
||||
/*
|
||||
for (score in NG.core.scoreBoards.get(8737).scores)
|
||||
{
|
||||
trace('score loaded user:${score.user.name}, score:${score.formatted_value}');
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
// var board = NG.core.scoreBoards.get(8004);// ID found in NG project view
|
||||
// board.postScore(HighScore.score);
|
||||
|
||||
// NGUtil.scoreboardArray = NG.core.scoreBoards.get(8004).scores;
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
enum ConnectionResult
|
||||
{
|
||||
/** Log in successful */
|
||||
Success;
|
||||
|
||||
/** Could not login */
|
||||
Fail(msg:String);
|
||||
|
||||
/** User cancelled the login */
|
||||
Cancelled;
|
||||
}
|
104
source/funkin/api/newgrounds/NgPrompt.hx
Normal file
104
source/funkin/api/newgrounds/NgPrompt.hx
Normal file
|
@ -0,0 +1,104 @@
|
|||
package funkin.api.newgrounds;
|
||||
|
||||
#if newgrounds
|
||||
import funkin.NGio;
|
||||
import funkin.ui.Prompt;
|
||||
|
||||
class NgPrompt extends Prompt
|
||||
{
|
||||
public function new(text:String, style:ButtonStyle = Yes_No)
|
||||
{
|
||||
super(text, style);
|
||||
}
|
||||
|
||||
static public function showLogin()
|
||||
{
|
||||
return showLoginPrompt(true);
|
||||
}
|
||||
|
||||
static public function showSavedSessionFailed()
|
||||
{
|
||||
return showLoginPrompt(false);
|
||||
}
|
||||
|
||||
static function showLoginPrompt(fromUi:Bool)
|
||||
{
|
||||
var prompt = new NgPrompt("Talking to server...", None);
|
||||
prompt.openCallback = NGUtil.login.bind(function popupLauncher(openPassportUrl)
|
||||
{
|
||||
var choiceMsg = fromUi ? #if web "Log in to Newgrounds?" #else null #end // User-input needed to allow popups
|
||||
: "Your session has expired.\n Please login again.";
|
||||
|
||||
if (choiceMsg != null)
|
||||
{
|
||||
prompt.setText(choiceMsg);
|
||||
prompt.setButtons(Yes_No);
|
||||
#if web
|
||||
prompt.buttons.getItem("yes").fireInstantly = true;
|
||||
#end
|
||||
prompt.onYes = function()
|
||||
{
|
||||
prompt.setText("Connecting..." #if web + "\n(check your popup blocker)" #end);
|
||||
prompt.setButtons(None);
|
||||
openPassportUrl();
|
||||
};
|
||||
prompt.onNo = function()
|
||||
{
|
||||
prompt.close();
|
||||
prompt = null;
|
||||
NGio.cancelLogin();
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
prompt.setText("Connecting...");
|
||||
openPassportUrl();
|
||||
}
|
||||
}, function onLoginComplete(result:ConnectionResult)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case Success:
|
||||
{
|
||||
prompt.setText("Login Successful");
|
||||
prompt.setButtons(Ok);
|
||||
prompt.onYes = prompt.close;
|
||||
}
|
||||
case Fail(msg):
|
||||
{
|
||||
trace("Login Error:" + msg);
|
||||
prompt.setText("Login failed");
|
||||
prompt.setButtons(Ok);
|
||||
prompt.onYes = prompt.close;
|
||||
}
|
||||
case Cancelled:
|
||||
{
|
||||
if (prompt != null)
|
||||
{
|
||||
prompt.setText("Login cancelled by user");
|
||||
prompt.setButtons(Ok);
|
||||
prompt.onYes = prompt.close;
|
||||
}
|
||||
else
|
||||
trace("Login cancelled via prompt");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return prompt;
|
||||
}
|
||||
|
||||
static public function showLogout()
|
||||
{
|
||||
var user = io.newgrounds.NG.core.user.name;
|
||||
var prompt = new NgPrompt('Log out of $user?', Yes_No);
|
||||
prompt.onYes = function()
|
||||
{
|
||||
NGio.logout();
|
||||
prompt.close();
|
||||
};
|
||||
prompt.onNo = prompt.close;
|
||||
return prompt;
|
||||
}
|
||||
}
|
||||
#end
|
9
source/funkin/api/newgrounds/README.md
Normal file
9
source/funkin/api/newgrounds/README.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
# funkin.api.newgrounds
|
||||
|
||||
This package contains two main classes:
|
||||
- `NGUtil` contains utility functions for interacting with the Newgrounds API.
|
||||
- This includes any functions which scripts should be able to use,
|
||||
such as retrieving achievement status.
|
||||
- `NGUnsafe` contains sensitive utility functions for interacting with the Newgrounds API.
|
||||
- This includes any functions which scripts should not be able to use,
|
||||
such as writing high scores or posting achievements.
|
|
@ -8,6 +8,7 @@ import funkin.audiovis.ABotVis;
|
|||
import funkin.audiovis.PolygonSpectogram;
|
||||
import funkin.audiovis.SpectogramSprite;
|
||||
import flixel.FlxSprite;
|
||||
import funkin.play.HealthIcon;
|
||||
import flixel.addons.display.FlxGridOverlay;
|
||||
import flixel.addons.transition.FlxTransitionableState;
|
||||
import flixel.addons.ui.FlxInputText;
|
||||
|
@ -705,7 +706,7 @@ class ChartingState extends MusicBeatState
|
|||
{
|
||||
if (FlxG.mouse.overlaps(leftIcon))
|
||||
{
|
||||
if (leftIcon.char == _song.player1)
|
||||
if (leftIcon.characterId == _song.player1)
|
||||
{
|
||||
p1Muted = !p1Muted;
|
||||
leftIcon.animation.curAnim.curFrame = p1Muted ? 1 : 0;
|
||||
|
@ -727,7 +728,7 @@ class ChartingState extends MusicBeatState
|
|||
// sloppy copypaste lol deal with it!
|
||||
if (FlxG.mouse.overlaps(rightIcon))
|
||||
{
|
||||
if (rightIcon.char == _song.player1)
|
||||
if (rightIcon.characterId == _song.player1)
|
||||
{
|
||||
p1Muted = !p1Muted;
|
||||
rightIcon.animation.curAnim.curFrame = p1Muted ? 1 : 0;
|
||||
|
@ -1129,16 +1130,16 @@ class ChartingState extends MusicBeatState
|
|||
{
|
||||
if (check_mustHitSection.checked)
|
||||
{
|
||||
leftIcon.changeIcon(_song.player1);
|
||||
rightIcon.changeIcon(_song.player2);
|
||||
leftIcon.characterId = (_song.player1);
|
||||
rightIcon.characterId = (_song.player2);
|
||||
|
||||
leftIcon.animation.curAnim.curFrame = p1Muted ? 1 : 0;
|
||||
rightIcon.animation.curAnim.curFrame = p2Muted ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
leftIcon.changeIcon(_song.player2);
|
||||
rightIcon.changeIcon(_song.player1);
|
||||
leftIcon.characterId = (_song.player2);
|
||||
rightIcon.characterId = (_song.player1);
|
||||
|
||||
leftIcon.animation.curAnim.curFrame = p2Muted ? 1 : 0;
|
||||
rightIcon.animation.curAnim.curFrame = p1Muted ? 1 : 0;
|
||||
|
|
|
@ -136,6 +136,8 @@ class PolymodHandler
|
|||
// Ensure script files have merge support.
|
||||
output.addType("hscript", TextFileFormat.PLAINTEXT);
|
||||
output.addType("hxs", TextFileFormat.PLAINTEXT);
|
||||
output.addType("hxc", TextFileFormat.PLAINTEXT);
|
||||
output.addType("hx", TextFileFormat.PLAINTEXT);
|
||||
|
||||
// You can specify the format of a specific file, with file extension.
|
||||
// output.addFile("data/introText.txt", TextFileFormat.LINES)
|
||||
|
@ -146,8 +148,8 @@ class PolymodHandler
|
|||
{
|
||||
return {
|
||||
assetLibraryPaths: [
|
||||
"songs" => "songs", "shared" => "", "tutorial" => "tutorial", "scripts" => "scripts", "week1" => "week1", "week2" => "week2",
|
||||
"week3" => "week3", "week4" => "week4", "week5" => "week5", "week6" => "week6", "week7" => "week7", "week8" => "week8",
|
||||
"songs" => "songs", "shared" => "", "tutorial" => "tutorial", "scripts" => "scripts", "week1" => "week1", "week2" => "week2",
|
||||
"week3" => "week3", "week4" => "week4", "week5" => "week5", "week6" => "week6", "week7" => "week7", "week8" => "week8",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
346
source/funkin/play/HealthIcon.hx
Normal file
346
source/funkin/play/HealthIcon.hx
Normal file
|
@ -0,0 +1,346 @@
|
|||
package funkin.play;
|
||||
|
||||
import funkin.play.character.CharacterData.CharacterDataParser;
|
||||
import flixel.FlxSprite;
|
||||
import openfl.utils.Assets;
|
||||
|
||||
/**
|
||||
* This is a rework of the health icon with the following changes:
|
||||
* - The health icon now owns its own state logic. It queries health and updates the sprite itself,
|
||||
* rather than relying on PlayState to command it.
|
||||
* - The health icon now supports animations.
|
||||
* - The health icon will now search for a SparrowV2 (XML) spritesheet, and use that for rendering if it can.
|
||||
* - If it can't find a spritesheet, it will the old format; a two-frame 300x150 image.
|
||||
* - If the spritesheet is found, the health icon will attempt to load and use the following animations as appropriate:
|
||||
* - `idle`, `winning`, `losing`, `toWinning`, `fromWinning`, `toLosing`, `fromLosing`
|
||||
* - The health icon is now easier to control via scripts.
|
||||
* - Set `autoUpdate` to false to prevent the health icon from changing its own animations.
|
||||
* - Once `autoUpdate` is false, you can manually call `playAnimation()` to play a specific animation.
|
||||
* - i.e. `PlayState.instance.iconP1.playAnimation("losing")`
|
||||
* - Scripts can also utilize all functionality that a normal FlxSprite would have access to, such as adding supplimental animations.
|
||||
* - i.e. `PlayState.instance.iconP1.animation.addByPrefix("jumpscare", "jumpscare", 24, false);`
|
||||
* @author MasterEric
|
||||
*/
|
||||
class HealthIcon extends FlxSprite
|
||||
{
|
||||
/**
|
||||
* The character this icon is representing.
|
||||
* Setting this variable will automatically update the graphic.
|
||||
*/
|
||||
public var characterId(default, set):String;
|
||||
|
||||
/**
|
||||
* Whether this health icon should automatically update its state based on the character's health.
|
||||
* You can set this to false if you want to manually forc
|
||||
*/
|
||||
public var autoUpdate:Bool = true;
|
||||
|
||||
/**
|
||||
* The player the health icon is attached to.
|
||||
*/
|
||||
var playerId:Int = 0;
|
||||
|
||||
/**
|
||||
* Whether the sprite is pixel art or not.
|
||||
* Calculated when loading an icon.
|
||||
*/
|
||||
var isPixel:Bool = false;
|
||||
|
||||
/**
|
||||
* At this amount of health, play the Winning animation instead of the idle.
|
||||
*/
|
||||
static final WINNING_THRESHOLD = 0.8 * 2;
|
||||
|
||||
/**
|
||||
* At this amount of health, play the Losing animation instead of the idle.
|
||||
*/
|
||||
static final LOSING_THRESHOLD = 0.2 * 2;
|
||||
|
||||
/**
|
||||
* The maximum health of the player.
|
||||
*/
|
||||
static final MAXIMUM_HEALTH = 2;
|
||||
|
||||
/**
|
||||
* The size of a non-pixel icon when using the legacy format.
|
||||
* Remember, modern icons can be any size.
|
||||
*/
|
||||
static final LEGACY_ICON_SIZE = 150;
|
||||
|
||||
/**
|
||||
* The size of a pixel icon when using the legacy format.
|
||||
* Remember, modern icons can be any size.
|
||||
*/
|
||||
static final LEGACY_PIXEL_SIZE = 32;
|
||||
|
||||
public function new(char:String = 'bf', playerId:Int = 0)
|
||||
{
|
||||
super(0, 0);
|
||||
this.playerId = playerId;
|
||||
this.scrollFactor.set();
|
||||
|
||||
this.characterId = char;
|
||||
|
||||
this.antialiasing = !isPixel;
|
||||
|
||||
this.flipX = playerId == 0;
|
||||
}
|
||||
|
||||
function set_characterId(value:String):String
|
||||
{
|
||||
if (value == characterId)
|
||||
return value;
|
||||
|
||||
characterId = value;
|
||||
loadCharacter(characterId);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Easter egg; press 9 in the PlayState to use the old player icon.
|
||||
*/
|
||||
public function toggleOldIcon():Void
|
||||
{
|
||||
if (characterId == 'bf-old')
|
||||
{
|
||||
characterId = PlayState.currentSong.player1;
|
||||
}
|
||||
else
|
||||
{
|
||||
characterId = 'bf-old';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by Flixel every frame. Includes logic to manage the currently playing animation.
|
||||
*/
|
||||
override function update(elapsed:Float):Void
|
||||
{
|
||||
super.update(elapsed);
|
||||
|
||||
if (PlayState.instance == null)
|
||||
return;
|
||||
|
||||
// Auto-update the state of the icon based on the player's health.
|
||||
if (autoUpdate)
|
||||
{
|
||||
switch (playerId)
|
||||
{
|
||||
case 0: // Boyfriend
|
||||
updateHealthIcon(PlayState.instance.health);
|
||||
case 1: // Dad
|
||||
updateHealthIcon(MAXIMUM_HEALTH - PlayState.instance.health);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateHealthIcon(health:Float)
|
||||
{
|
||||
// We want to efficiently handle animation playback
|
||||
|
||||
// Here, we use the current animation name to track the current state
|
||||
// of a simple state machine. Neat!
|
||||
|
||||
switch (getCurrentAnimation())
|
||||
{
|
||||
case IDLE:
|
||||
if (health < LOSING_THRESHOLD)
|
||||
playAnimation(TO_LOSING, LOSING);
|
||||
else if (health > WINNING_THRESHOLD)
|
||||
playAnimation(TO_WINNING, WINNING);
|
||||
else
|
||||
playAnimation(IDLE);
|
||||
case WINNING:
|
||||
if (health < WINNING_THRESHOLD)
|
||||
playAnimation(FROM_WINNING, IDLE);
|
||||
else
|
||||
playAnimation(WINNING, IDLE);
|
||||
case LOSING:
|
||||
if (health > LOSING_THRESHOLD)
|
||||
playAnimation(FROM_LOSING, IDLE);
|
||||
else
|
||||
playAnimation(LOSING, IDLE);
|
||||
case TO_LOSING:
|
||||
if (isAnimationFinished())
|
||||
playAnimation(LOSING, IDLE);
|
||||
case TO_WINNING:
|
||||
if (isAnimationFinished())
|
||||
playAnimation(WINNING, IDLE);
|
||||
case FROM_LOSING | FROM_WINNING:
|
||||
if (isAnimationFinished())
|
||||
playAnimation(IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load
|
||||
* @param charId
|
||||
*/
|
||||
function loadAnimationNew(charId:String):Void
|
||||
{
|
||||
this.animation.addByPrefix(IDLE, IDLE, 24, true);
|
||||
this.animation.addByPrefix(WINNING, WINNING, 24, true);
|
||||
this.animation.addByPrefix(LOSING, LOSING, 24, true);
|
||||
this.animation.addByPrefix(TO_WINNING, TO_WINNING, 24, true);
|
||||
this.animation.addByPrefix(TO_LOSING, TO_LOSING, 24, true);
|
||||
this.animation.addByPrefix(FROM_WINNING, FROM_WINNING, 24, true);
|
||||
this.animation.addByPrefix(FROM_LOSING, FROM_LOSING, 24, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load health icon animations using the legacy format.
|
||||
* Simply assumes two icons, one on
|
||||
* @param charId
|
||||
*/
|
||||
function loadAnimationOld(charId:String):Void
|
||||
{
|
||||
this.animation.add(IDLE, [0], 0, false, this.playerId == 0);
|
||||
this.animation.add(LOSING, [1], 0, false, this.playerId == 0);
|
||||
}
|
||||
|
||||
function correctCharacterId(charId:String):String
|
||||
{
|
||||
if (!Assets.exists(Paths.image('icons/icon-' + charId)))
|
||||
{
|
||||
FlxG.log.warn('No icon for character: $charId : using default placeholder face instead!');
|
||||
return "face";
|
||||
}
|
||||
|
||||
return charId;
|
||||
}
|
||||
|
||||
function isNewSpritesheet(charId:String):Bool
|
||||
{
|
||||
return Assets.exists(Paths.xml('icons/icon-' + characterId));
|
||||
}
|
||||
|
||||
function fetchIsPixel(charId:String):Bool
|
||||
{
|
||||
var charData = CharacterDataParser.fetchCharacterData(charId);
|
||||
if (charData == null)
|
||||
{
|
||||
FlxG.log.warn('No character data found for character: $charId');
|
||||
return false;
|
||||
}
|
||||
return charData.isPixel;
|
||||
}
|
||||
|
||||
function loadCharacter(charId:String):Void
|
||||
{
|
||||
if (correctCharacterId(charId) != charId)
|
||||
{
|
||||
characterId = correctCharacterId(charId);
|
||||
return;
|
||||
}
|
||||
|
||||
isPixel = fetchIsPixel(charId);
|
||||
|
||||
if (isNewSpritesheet(charId))
|
||||
{
|
||||
frames = Paths.getSparrowAtlas('icons/icon-$charId');
|
||||
|
||||
loadAnimationNew(charId);
|
||||
}
|
||||
else
|
||||
{
|
||||
loadGraphic(Paths.image('icons/icon-$charId'), true, isPixel ? LEGACY_PIXEL_SIZE : LEGACY_ICON_SIZE,
|
||||
isPixel ? LEGACY_PIXEL_SIZE : LEGACY_ICON_SIZE);
|
||||
|
||||
loadAnimationOld(charId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Name of the current animation being played by this health icon.
|
||||
*/
|
||||
public function getCurrentAnimation():String
|
||||
{
|
||||
if (this.animation == null || this.animation.curAnim == null)
|
||||
return "";
|
||||
return this.animation.curAnim.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether this sprite posesses the given animation.
|
||||
* Only true if the animation was successfully loaded from the XML.
|
||||
*/
|
||||
public function hasAnimation(id:String):Bool
|
||||
{
|
||||
if (this.animation == null)
|
||||
return false;
|
||||
|
||||
return this.animation.getByName(id) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether the current animation is in the finished state.
|
||||
*/
|
||||
public function isAnimationFinished():Bool
|
||||
{
|
||||
return this.animation.finished;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays the animation with the given name.
|
||||
* @param name The name of the animation to play.
|
||||
* @param fallback The fallback animation to play if the given animation is not found.
|
||||
* @param restart Whether to forcibly restart the animation if it is already playing.
|
||||
*/
|
||||
public function playAnimation(name:String, fallback:String = null, restart = false):Void
|
||||
{
|
||||
// Attempt to play the animation
|
||||
if (hasAnimation(name))
|
||||
this.animation.play(name, restart, false, 0);
|
||||
|
||||
// Play the fallback animation if the requested animation was not found
|
||||
if (fallback != null && hasAnimation(fallback))
|
||||
this.animation.play(fallback, restart, false, 0);
|
||||
|
||||
// If we don't have an animation, we're done.
|
||||
}
|
||||
}
|
||||
|
||||
enum abstract HealthIconState(String) to String from String
|
||||
{
|
||||
/**
|
||||
* Indicates the health icon is in the default animation.
|
||||
* Plays as long as health is between 20% and 80%.
|
||||
*/
|
||||
var IDLE = "idle";
|
||||
|
||||
/**
|
||||
* Indicates the health icon is playing the Winning animation.
|
||||
* Plays as long as health is above 80%.
|
||||
*/
|
||||
var WINNING = "winning";
|
||||
|
||||
/**
|
||||
* Indicates the health icon is playing the Losing animation.
|
||||
* Plays as long as health is below 20%.
|
||||
*/
|
||||
var LOSING = "losing";
|
||||
|
||||
/**
|
||||
* Indicates that the health icon is transitioning between `idle` and `winning`.
|
||||
* The next animation will play once the current animation finishes.
|
||||
*/
|
||||
var TO_WINNING = "toWinning";
|
||||
|
||||
/**
|
||||
* Indicates that the health icon is transitioning between `idle` and `losing`.
|
||||
* The next animation will play once the current animation finishes.
|
||||
*/
|
||||
var TO_LOSING = "toLosing";
|
||||
|
||||
/**
|
||||
* Indicates that the health icon is transitioning between `winning` and `idle`.
|
||||
* The next animation will play once the current animation finishes.
|
||||
*/
|
||||
var FROM_WINNING = "fromWinning";
|
||||
|
||||
/**
|
||||
* Indicates that the health icon is transitioning between `losing` and `idle`.
|
||||
* The next animation will play once the current animation finishes.
|
||||
*/
|
||||
var FROM_LOSING = "fromLosing";
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package funkin.play;
|
||||
|
||||
import funkin.play.character.BaseCharacter;
|
||||
import flixel.addons.effects.FlxTrail;
|
||||
import flixel.addons.transition.FlxTransitionableState;
|
||||
import flixel.FlxCamera;
|
||||
import flixel.FlxObject;
|
||||
|
@ -29,6 +28,7 @@ import funkin.modding.module.ModuleHandler;
|
|||
import funkin.Note;
|
||||
import funkin.play.character.CharacterData;
|
||||
import funkin.play.stage.Stage;
|
||||
import funkin.play.HealthIcon;
|
||||
import funkin.play.stage.StageData;
|
||||
import funkin.play.Strumline.StrumlineArrow;
|
||||
import funkin.play.Strumline.StrumlineStyle;
|
||||
|
@ -143,7 +143,7 @@ class PlayState extends MusicBeatState implements IHook
|
|||
* NOTE: This must be an FlxObject, not an FlxPoint, because it needs to be added to the scene.
|
||||
* Once it's added to the scene, the camera can be configured to follow it.
|
||||
*/
|
||||
public var cameraFollowPoint:FlxObject = new FlxObject(0, 0, 1, 1);
|
||||
public var cameraFollowPoint:FlxSprite = new FlxSprite(0, 0);
|
||||
|
||||
/**
|
||||
* PRIVATE INSTANCE VARIABLES
|
||||
|
@ -275,6 +275,10 @@ class PlayState extends MusicBeatState implements IHook
|
|||
|
||||
instance = this;
|
||||
|
||||
// TEMP: For testing
|
||||
cameraFollowPoint.makeGraphic(8, 8, 0xFFFF00FF);
|
||||
cameraFollowPoint.zIndex = 1000000;
|
||||
|
||||
// Reduce physics accuracy (who cares!!!) to improve animation quality.
|
||||
FlxG.fixedTimestep = false;
|
||||
|
||||
|
@ -370,11 +374,11 @@ class PlayState extends MusicBeatState implements IHook
|
|||
scoreText.scrollFactor.set();
|
||||
add(scoreText);
|
||||
|
||||
iconP1 = new HealthIcon(currentSong.player1, true);
|
||||
iconP1 = new HealthIcon(currentSong.player1, 0);
|
||||
iconP1.y = healthBar.y - (iconP1.height / 2);
|
||||
add(iconP1);
|
||||
|
||||
iconP2 = new HealthIcon(currentSong.player2, false);
|
||||
iconP2 = new HealthIcon(currentSong.player2, 1);
|
||||
iconP2.y = healthBar.y - (iconP2.height / 2);
|
||||
add(iconP2);
|
||||
|
||||
|
@ -536,51 +540,17 @@ class PlayState extends MusicBeatState implements IHook
|
|||
if (dad != null)
|
||||
{
|
||||
dad.characterType = CharacterType.DAD;
|
||||
cameraFollowPoint.setPosition(dad.getGraphicMidpoint().x, dad.getGraphicMidpoint().y);
|
||||
cameraFollowPoint.setPosition(dad.cameraFocusPoint.x, dad.cameraFocusPoint.y);
|
||||
}
|
||||
|
||||
switch (currentSong.player2)
|
||||
{
|
||||
case 'gf':
|
||||
var gfPoint:FlxPoint = currentStage.getGirlfriendPosition();
|
||||
dad.setPosition(gfPoint.x, gfPoint.y);
|
||||
|
||||
// girlfriend.visible = false;
|
||||
|
||||
if (isStoryMode)
|
||||
{
|
||||
cameraFollowPoint.x += 600;
|
||||
tweenCamIn();
|
||||
}
|
||||
case "spooky":
|
||||
dad.y += 200;
|
||||
case "monster":
|
||||
dad.y += 100;
|
||||
case 'monster-christmas':
|
||||
dad.y += 130;
|
||||
case 'dad':
|
||||
cameraFollowPoint.x += 400;
|
||||
case 'pico':
|
||||
cameraFollowPoint.x += 600;
|
||||
dad.y += 300;
|
||||
case 'parents-christmas':
|
||||
dad.x -= 500;
|
||||
case 'senpai' | 'senpai-angry':
|
||||
dad.x += 150;
|
||||
dad.y += 360;
|
||||
cameraFollowPoint.setPosition(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y);
|
||||
case 'spirit':
|
||||
dad.x -= 150;
|
||||
dad.y += 100;
|
||||
cameraFollowPoint.setPosition(dad.getGraphicMidpoint().x + 300, dad.getGraphicMidpoint().y);
|
||||
case 'tankman':
|
||||
dad.y += 180;
|
||||
}
|
||||
|
||||
if (currentSong.player1 == "pico")
|
||||
{
|
||||
dad.x -= 100;
|
||||
dad.y -= 100;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -596,11 +566,6 @@ class PlayState extends MusicBeatState implements IHook
|
|||
// REPOSITIONING PER STAGE
|
||||
switch (currentStageId)
|
||||
{
|
||||
case 'schoolEvil':
|
||||
var evilTrail = new FlxTrail(dad, null, 4, 24, 0.3, 0.069);
|
||||
// Go behind Spirit.
|
||||
evilTrail.zIndex = 190;
|
||||
add(evilTrail);
|
||||
case "tank":
|
||||
girlfriend.y += 10;
|
||||
girlfriend.x -= 30;
|
||||
|
@ -1081,7 +1046,7 @@ class PlayState extends MusicBeatState implements IHook
|
|||
FlxG.switchState(new funkin.ui.animDebugShit.DebugBoundingState());
|
||||
|
||||
if (FlxG.keys.justPressed.NINE)
|
||||
iconP1.swapOldIcon();
|
||||
iconP1.toggleOldIcon();
|
||||
|
||||
iconP1.setGraphicSize(Std.int(CoolUtil.coolLerp(iconP1.width, 150, 0.15)));
|
||||
iconP2.setGraphicSize(Std.int(CoolUtil.coolLerp(iconP2.width, 150, 0.15)));
|
||||
|
@ -1097,16 +1062,6 @@ class PlayState extends MusicBeatState implements IHook
|
|||
if (health > 2)
|
||||
health = 2;
|
||||
|
||||
if (healthBar.percent < 20)
|
||||
iconP1.animation.curAnim.curFrame = 1;
|
||||
else
|
||||
iconP1.animation.curAnim.curFrame = 0;
|
||||
|
||||
if (healthBar.percent > 80)
|
||||
iconP2.animation.curAnim.curFrame = 1;
|
||||
else
|
||||
iconP2.animation.curAnim.curFrame = 0;
|
||||
|
||||
#if debug
|
||||
if (FlxG.keys.justPressed.ONE)
|
||||
endSong();
|
||||
|
@ -1121,7 +1076,7 @@ class PlayState extends MusicBeatState implements IHook
|
|||
{
|
||||
cameraRightSide = SongLoad.getSong()[Std.int(curStep / 16)].mustHitSection;
|
||||
|
||||
cameraMovement();
|
||||
controlCamera();
|
||||
}
|
||||
|
||||
if (camZooming)
|
||||
|
@ -1195,7 +1150,7 @@ class PlayState extends MusicBeatState implements IHook
|
|||
inactiveNotes.shift();
|
||||
}
|
||||
|
||||
if (generatedMusic)
|
||||
if (generatedMusic && playerStrumline != null)
|
||||
{
|
||||
activeNotes.forEachAlive(function(daNote:Note)
|
||||
{
|
||||
|
@ -1522,57 +1477,35 @@ class PlayState extends MusicBeatState implements IHook
|
|||
comboPopUps.displayCombo(combo);
|
||||
}
|
||||
|
||||
function cameraMovement()
|
||||
function controlCamera()
|
||||
{
|
||||
if (currentStage == null)
|
||||
return;
|
||||
|
||||
if (cameraFollowPoint.x != currentStage.getDad().getMidpoint().x + 150 && !cameraRightSide)
|
||||
var isFocusedOnDad = cameraFollowPoint.x == currentStage.getDad().cameraFocusPoint.x;
|
||||
var isFocusedOnBF = cameraFollowPoint.x == currentStage.getBoyfriend().cameraFocusPoint.x;
|
||||
|
||||
if (cameraRightSide && !isFocusedOnBF)
|
||||
{
|
||||
cameraFollowPoint.setPosition(currentStage.getDad().getMidpoint().x + 150, currentStage.getDad().getMidpoint().y - 100);
|
||||
// camFollow.setPosition(lucky.getMidpoint().x - 120, lucky.getMidpoint().y + 210);
|
||||
|
||||
switch (currentStage.getDad().characterId)
|
||||
{
|
||||
case 'mom':
|
||||
cameraFollowPoint.y = currentStage.getDad().getMidpoint().y;
|
||||
case 'senpai' | 'senpai-angry':
|
||||
cameraFollowPoint.y = currentStage.getDad().getMidpoint().y - 430;
|
||||
cameraFollowPoint.x = currentStage.getDad().getMidpoint().x - 100;
|
||||
}
|
||||
|
||||
if (currentStage.getDad().characterId == 'mom')
|
||||
vocals.volume = 1;
|
||||
|
||||
if (currentSong.song.toLowerCase() == 'tutorial')
|
||||
tweenCamIn();
|
||||
}
|
||||
|
||||
if (cameraRightSide && cameraFollowPoint.x != currentStage.getBoyfriend().getMidpoint().x - 100)
|
||||
{
|
||||
cameraFollowPoint.setPosition(currentStage.getBoyfriend().getMidpoint().x - 100, currentStage.getBoyfriend().getMidpoint().y - 100);
|
||||
|
||||
switch (currentStageId)
|
||||
{
|
||||
case 'limo':
|
||||
cameraFollowPoint.x = currentStage.getBoyfriend().getMidpoint().x - 300;
|
||||
case 'mall':
|
||||
cameraFollowPoint.y = currentStage.getBoyfriend().getMidpoint().y - 200;
|
||||
case 'school' | 'schoolEvil':
|
||||
cameraFollowPoint.x = currentStage.getBoyfriend().getMidpoint().x - 200;
|
||||
cameraFollowPoint.y = currentStage.getBoyfriend().getMidpoint().y - 200;
|
||||
}
|
||||
// Focus the camera on the player.
|
||||
cameraFollowPoint.setPosition(currentStage.getBoyfriend().cameraFocusPoint.x, currentStage.getBoyfriend().cameraFocusPoint.y);
|
||||
|
||||
// TODO: Un-hardcode this.
|
||||
if (currentSong.song.toLowerCase() == 'tutorial')
|
||||
FlxTween.tween(FlxG.camera, {zoom: 1 * FlxCamera.defaultZoom}, (Conductor.stepCrochet * 4 / 1000), {ease: FlxEase.elasticInOut});
|
||||
}
|
||||
}
|
||||
else if (!cameraRightSide && !isFocusedOnDad)
|
||||
{
|
||||
// Focus the camera on the opponent.
|
||||
cameraFollowPoint.setPosition(currentStage.getDad().cameraFocusPoint.x, currentStage.getDad().cameraFocusPoint.y);
|
||||
|
||||
public var test:(PlayState) -> Void = function(instance:PlayState)
|
||||
{
|
||||
trace('test');
|
||||
trace(instance.currentStageId);
|
||||
};
|
||||
// TODO: Un-hardcode this stuff.
|
||||
if (currentStage.getDad().characterId == 'mom')
|
||||
vocals.volume = 1;
|
||||
if (currentSong.song.toLowerCase() == 'tutorial')
|
||||
tweenCamIn();
|
||||
}
|
||||
}
|
||||
|
||||
public function keyShit(test:Bool):Void
|
||||
{
|
||||
|
@ -1684,6 +1617,8 @@ class PlayState extends MusicBeatState implements IHook
|
|||
|
||||
for (keyId => isPressed in pressArray)
|
||||
{
|
||||
if (playerStrumline == null)
|
||||
continue;
|
||||
var arrow:StrumlineArrow = PlayState.instance.playerStrumline.getArrow(keyId);
|
||||
|
||||
if (isPressed && arrow.animation.curAnim.name != 'confirm')
|
||||
|
@ -2072,7 +2007,6 @@ class PlayState extends MusicBeatState implements IHook
|
|||
public function refresh()
|
||||
{
|
||||
sort(SortUtil.byZIndex, FlxSort.ASCENDING);
|
||||
trace('Stage sorted by z-index');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,14 +2,13 @@ package funkin.play;
|
|||
|
||||
import flixel.util.FlxTimer;
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.tweens.FlxTween;
|
||||
import flixel.tweens.FlxEase;
|
||||
import flixel.util.FlxColor;
|
||||
import flixel.FlxSprite;
|
||||
|
||||
/**
|
||||
* Static methods for playing cutscenes in the PlayState.
|
||||
* TODO: Softcode this shit!!!!!1!
|
||||
* TODO: Un-hardcode this shit!!!!!1!
|
||||
*/
|
||||
class VanillaCutscenes
|
||||
{
|
||||
|
@ -64,7 +63,7 @@ class VanillaCutscenes
|
|||
@:privateAccess
|
||||
PlayState.instance.startCountdown();
|
||||
@:privateAccess
|
||||
PlayState.instance.cameraMovement();
|
||||
PlayState.instance.controlCamera();
|
||||
}
|
||||
|
||||
public static function playHorrorStartCutscene()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package funkin.play.character;
|
||||
|
||||
import funkin.play.character.CharacterData.CharacterDataParser;
|
||||
import flixel.math.FlxPoint;
|
||||
import funkin.modding.events.ScriptEvent;
|
||||
import funkin.modding.events.ScriptEvent.UpdateScriptEvent;
|
||||
|
@ -40,7 +41,8 @@ class BaseCharacter extends Bopper
|
|||
final singTimeCrochet:Float;
|
||||
|
||||
/**
|
||||
* The x and y position to subtract from the stage's X value to get the character's proper rendering position.
|
||||
* Character position in stage file is at the bottom center of the character.
|
||||
* Position from stage file - character origin is at the top left corner of the character.
|
||||
*/
|
||||
public var characterOrigin(get, null):FlxPoint;
|
||||
|
||||
|
@ -48,15 +50,64 @@ class BaseCharacter extends Bopper
|
|||
{
|
||||
var xPos = (width / 2); // Horizontal center
|
||||
var yPos = (height); // Vertical bottom
|
||||
trace('Origin: ${characterId} (${xPos}, ${yPos})');
|
||||
return new FlxPoint(xPos, yPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the point the camera should focus on.
|
||||
* Should be approximately centered on the character, and should not move based on the current animation.
|
||||
*
|
||||
* Set the position of this rather than reassigning it, so that anything referencing it will not be affected.
|
||||
*/
|
||||
public var cameraFocusPoint(default, null):FlxPoint = new FlxPoint(0, 0);
|
||||
|
||||
override function set_animOffset(value:Array<Float>)
|
||||
{
|
||||
if (animOffset == null)
|
||||
animOffset = [0, 0];
|
||||
if (animOffset == value)
|
||||
return value;
|
||||
|
||||
var xDiff = animOffset[0] - value[0];
|
||||
var yDiff = animOffset[1] - value[1];
|
||||
|
||||
// Call the super function so that camera focus point is not affected.
|
||||
super.set_x(this.x + xDiff);
|
||||
super.set_y(this.y + yDiff);
|
||||
|
||||
return animOffset = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the x position changes, other than via changing the animation offset,
|
||||
* then we need to update the camera focus point.
|
||||
*/
|
||||
override function set_x(value:Float):Float
|
||||
{
|
||||
if (value == this.x)
|
||||
return value;
|
||||
|
||||
var xDiff = value - this.x;
|
||||
this.cameraFocusPoint.x += xDiff;
|
||||
|
||||
return super.set_x(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the y position changes, other than via changing the animation offset,
|
||||
* then we need to update the camera focus point.
|
||||
*/
|
||||
override function set_y(value:Float):Float
|
||||
{
|
||||
if (value == this.y)
|
||||
return value;
|
||||
|
||||
var yDiff = value - this.y;
|
||||
this.cameraFocusPoint.y += yDiff;
|
||||
|
||||
return super.set_y(value);
|
||||
}
|
||||
|
||||
public function new(id:String)
|
||||
{
|
||||
super();
|
||||
|
@ -74,6 +125,26 @@ class BaseCharacter extends Bopper
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sprite scale to the appropriate value.
|
||||
* @param scale
|
||||
*/
|
||||
function setScale(scale:Null<Float>):Void
|
||||
{
|
||||
if (scale == null)
|
||||
scale = 1.0;
|
||||
|
||||
this.scale.x = scale;
|
||||
this.scale.y = scale;
|
||||
this.updateHitbox();
|
||||
}
|
||||
|
||||
override function onCreate(event:ScriptEvent):Void
|
||||
{
|
||||
this.cameraFocusPoint = new FlxPoint(this.x + this.width / 2 + _data.cameraOffset[0], this.y + this.height / 2 + _data.cameraOffset[0]);
|
||||
super.onCreate(event);
|
||||
}
|
||||
|
||||
public override function onUpdate(event:UpdateScriptEvent):Void
|
||||
{
|
||||
super.onUpdate(event);
|
||||
|
@ -112,7 +183,7 @@ class BaseCharacter extends Bopper
|
|||
FlxG.watch.addQuick('singTimeMs-${characterId}', singTimeMs);
|
||||
if (holdTimer > singTimeMs && shouldStopSinging)
|
||||
{
|
||||
trace('holdTimer reached ${holdTimer}sec (> ${singTimeMs}), stopping sing animation');
|
||||
// trace('holdTimer reached ${holdTimer}sec (> ${singTimeMs}), stopping sing animation');
|
||||
holdTimer = 0;
|
||||
dance(true);
|
||||
}
|
||||
|
@ -229,8 +300,6 @@ class BaseCharacter extends Bopper
|
|||
{
|
||||
super.onNoteHit(event);
|
||||
|
||||
trace('HIT NOTE: ${event.note.data.dir} : ${event.note.isSustainNote}');
|
||||
|
||||
holdTimer = 0;
|
||||
|
||||
if (event.note.mustPress && characterType == BF)
|
||||
|
|
|
@ -135,7 +135,11 @@ class CharacterDataParser
|
|||
trace(' Failed to instantiate scripted character: ${charCls}');
|
||||
continue;
|
||||
}
|
||||
characterScriptedClass.set(character.characterId, charCls);
|
||||
else
|
||||
{
|
||||
trace(' Successfully instantiated scripted character: ${charCls}');
|
||||
characterScriptedClass.set(character.characterId, charCls);
|
||||
}
|
||||
}
|
||||
|
||||
trace(' Successfully loaded ${Lambda.count(characterCache)} stages.');
|
||||
|
@ -290,6 +294,7 @@ class CharacterDataParser
|
|||
static final DEFAULT_RENDERTYPE:CharacterRenderType = CharacterRenderType.SPARROW;
|
||||
static final DEFAULT_SCALE:Float = 1;
|
||||
static final DEFAULT_SCROLL:Array<Float> = [0, 0];
|
||||
static final DEFAULT_CAMERAOFFSET:Array<Float> = [0, 0];
|
||||
static final DEFAULT_STARTINGANIM:String = "idle";
|
||||
|
||||
/**
|
||||
|
@ -303,7 +308,7 @@ class CharacterDataParser
|
|||
{
|
||||
if (input == null)
|
||||
{
|
||||
trace('[CHARDATA] ERROR: Could not parse character data for "${id}".');
|
||||
// trace('[CHARDATA] ERROR: Could not parse character data for "${id}".');
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -346,6 +351,11 @@ class CharacterDataParser
|
|||
input.scale = DEFAULT_SCALE;
|
||||
}
|
||||
|
||||
if (input.cameraOffset == null)
|
||||
{
|
||||
input.cameraOffset = DEFAULT_CAMERAOFFSET;
|
||||
}
|
||||
|
||||
if (input.isPixel == null)
|
||||
{
|
||||
input.isPixel = DEFAULT_ISPIXEL;
|
||||
|
@ -451,11 +461,18 @@ typedef CharacterData =
|
|||
var assetPath:String;
|
||||
|
||||
/**
|
||||
* Either the scale of the graphic as a float, or the [w, h] scale as an array of two floats.
|
||||
* The scale of the graphic as a float.
|
||||
* Pro tip: On pixel-art levels, save the sprites small and set this value to 6 or so to save memory.
|
||||
* @default 1
|
||||
*/
|
||||
var scale:OneOfTwo<Float, Array<Float>>;
|
||||
var scale:Null<Float>;
|
||||
|
||||
/**
|
||||
* The amount to offset the camera by while focusing on this character.
|
||||
* Default value focuses on the character directly.
|
||||
* @default [0, 0]
|
||||
*/
|
||||
var cameraOffset:Array<Float>;
|
||||
|
||||
/**
|
||||
* Setting this to true disables anti-aliasing for the character.
|
||||
|
|
|
@ -41,16 +41,17 @@ class MultiSparrowCharacter extends BaseCharacter
|
|||
{
|
||||
trace('Creating MULTI SPARROW CHARACTER: ' + this.characterId);
|
||||
|
||||
buildSprite();
|
||||
|
||||
playAnimation(_data.startingAnimation);
|
||||
buildSprites();
|
||||
super.onCreate(event);
|
||||
}
|
||||
|
||||
function buildSprite()
|
||||
function buildSprites()
|
||||
{
|
||||
buildSpritesheets();
|
||||
buildAnimations();
|
||||
|
||||
playAnimation(_data.startingAnimation);
|
||||
|
||||
if (_data.isPixel)
|
||||
{
|
||||
this.antialiasing = false;
|
||||
|
@ -59,12 +60,6 @@ class MultiSparrowCharacter extends BaseCharacter
|
|||
{
|
||||
this.antialiasing = true;
|
||||
}
|
||||
|
||||
if (_data.scale != null)
|
||||
{
|
||||
this.setGraphicSize(Std.int(this.width * this.scale.x));
|
||||
this.updateHitbox();
|
||||
}
|
||||
}
|
||||
|
||||
function buildSpritesheets()
|
||||
|
@ -115,26 +110,28 @@ class MultiSparrowCharacter extends BaseCharacter
|
|||
}
|
||||
if (assetPath == null)
|
||||
{
|
||||
trace('Asset path is null, falling back to default. This is normal!');
|
||||
// trace('Asset path is null, falling back to default. This is normal!');
|
||||
loadFramesByAssetPath(_data.assetPath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.activeMember == assetPath)
|
||||
{
|
||||
trace('Already using this asset path: ${assetPath}');
|
||||
// trace('Already using this asset path: ${assetPath}');
|
||||
return;
|
||||
}
|
||||
|
||||
if (members.exists(assetPath))
|
||||
{
|
||||
// Switch to a new set of sprites.
|
||||
trace('Loading frames from asset path: ${assetPath}');
|
||||
this.frames = members.get(assetPath);
|
||||
this.activeMember = assetPath;
|
||||
this.setScale(_data.scale);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('Multi-Sparrow could not find asset path: ${assetPath}');
|
||||
trace('[WARN] MultiSparrow character ${characterId} could not find asset path: ${assetPath}');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,20 +146,18 @@ class MultiSparrowCharacter extends BaseCharacter
|
|||
}
|
||||
else
|
||||
{
|
||||
trace('Multi-Sparrow could not find animation: ${animName}');
|
||||
trace('[WARN] MultiSparrow character ${characterId} could not find animation: ${animName}');
|
||||
}
|
||||
}
|
||||
|
||||
function buildAnimations()
|
||||
{
|
||||
trace('[SPARROWCHAR] Loading ${_data.animations.length} animations for ${characterId}');
|
||||
trace('[MULTISPARROWCHAR] Loading ${_data.animations.length} animations for ${characterId}');
|
||||
|
||||
// We need to swap to the proper frame collection before adding the animations, I think?
|
||||
for (anim in _data.animations)
|
||||
{
|
||||
trace('Using frames: ${anim.name}');
|
||||
loadFramesByAnimName(anim.name);
|
||||
trace('Adding animation');
|
||||
FlxAnimationUtil.addAtlasAnimation(this, anim);
|
||||
|
||||
if (anim.offsets == null)
|
||||
|
@ -176,7 +171,7 @@ class MultiSparrowCharacter extends BaseCharacter
|
|||
}
|
||||
|
||||
var animNames = this.animation.getNameList();
|
||||
trace('[SPARROWCHAR] Successfully loaded ${animNames.length} animations for ${characterId}');
|
||||
trace('[MULTISPARROWCHAR] Successfully loaded ${animNames.length} animations for ${characterId}');
|
||||
}
|
||||
|
||||
public override function playAnimation(name:String, restart:Bool = false):Void
|
||||
|
|
|
@ -24,6 +24,8 @@ class PackerCharacter extends BaseCharacter
|
|||
loadAnimations();
|
||||
|
||||
playAnimation(_data.startingAnimation);
|
||||
|
||||
super.onCreate(event);
|
||||
}
|
||||
|
||||
function loadSpritesheet()
|
||||
|
@ -48,11 +50,7 @@ class PackerCharacter extends BaseCharacter
|
|||
this.antialiasing = true;
|
||||
}
|
||||
|
||||
if (_data.scale != null)
|
||||
{
|
||||
this.setGraphicSize(Std.int(this.width * this.scale.x));
|
||||
this.updateHitbox();
|
||||
}
|
||||
this.setScale(_data.scale);
|
||||
}
|
||||
|
||||
function loadAnimations()
|
||||
|
|
|
@ -26,6 +26,8 @@ class SparrowCharacter extends BaseCharacter
|
|||
loadAnimations();
|
||||
|
||||
playAnimation(_data.startingAnimation);
|
||||
|
||||
super.onCreate(event);
|
||||
}
|
||||
|
||||
function loadSpritesheet()
|
||||
|
@ -50,11 +52,7 @@ class SparrowCharacter extends BaseCharacter
|
|||
this.antialiasing = true;
|
||||
}
|
||||
|
||||
if (_data.scale != null)
|
||||
{
|
||||
this.setGraphicSize(Std.int(this.width * this.scale.x));
|
||||
this.updateHitbox();
|
||||
}
|
||||
this.setScale(_data.scale);
|
||||
}
|
||||
|
||||
function loadAnimations()
|
||||
|
|
|
@ -32,7 +32,7 @@ class Bopper extends FlxSprite implements IPlayStateScriptedClass
|
|||
/**
|
||||
* Offset the character's sprite by this much when playing each animation.
|
||||
*/
|
||||
public var animationOffsets:Map<String, Array<Int>> = new Map<String, Array<Int>>();
|
||||
public var animationOffsets:Map<String, Array<Float>> = new Map<String, Array<Float>>();
|
||||
|
||||
/**
|
||||
* Add a suffix to the `idle` animation (or `danceLeft` and `danceRight` animations)
|
||||
|
@ -47,23 +47,22 @@ class Bopper extends FlxSprite implements IPlayStateScriptedClass
|
|||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this value to define an additional vertical offset to this sprite's position.
|
||||
*/
|
||||
public var yOffset:Float = 0;
|
||||
private var animOffset(default, set):Array<Float> = [0, 0];
|
||||
|
||||
override function set_y(value:Float):Float
|
||||
function set_animOffset(value:Array<Float>)
|
||||
{
|
||||
this.y = this.yOffset + value;
|
||||
return this.y;
|
||||
}
|
||||
if (animOffset == null)
|
||||
animOffset = [0, 0];
|
||||
if (animOffset == value)
|
||||
return value;
|
||||
|
||||
function set_yOffset(value:Float):Float
|
||||
{
|
||||
var diff = value - this.yOffset;
|
||||
this.yOffset = value;
|
||||
this.y += diff;
|
||||
return value;
|
||||
var xDiff = animOffset[0] - value[0];
|
||||
var yDiff = animOffset[1] - value[1];
|
||||
|
||||
this.x += xDiff;
|
||||
this.y += yDiff;
|
||||
|
||||
return animOffset = value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -193,11 +192,11 @@ class Bopper extends FlxSprite implements IPlayStateScriptedClass
|
|||
var offsets = animationOffsets.get(name);
|
||||
if (offsets != null)
|
||||
{
|
||||
this.offset.set(offsets[0], offsets[1]);
|
||||
this.animOffset = offsets;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.offset.set(0, 0);
|
||||
this.animOffset = [0, 0];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -211,7 +211,6 @@ class Stage extends FlxSpriteGroup implements IHook implements IPlayStateScripte
|
|||
public function refresh()
|
||||
{
|
||||
sort(SortUtil.byZIndex, FlxSort.ASCENDING);
|
||||
trace('Stage sorted by z-index');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -242,8 +241,6 @@ class Stage extends FlxSpriteGroup implements IHook implements IPlayStateScripte
|
|||
if (character == null)
|
||||
return;
|
||||
|
||||
var debugMarker:FlxSprite = new FlxSprite(0, 0);
|
||||
|
||||
// Apply position and z-index.
|
||||
switch (charType)
|
||||
{
|
||||
|
@ -251,40 +248,24 @@ class Stage extends FlxSpriteGroup implements IHook implements IPlayStateScripte
|
|||
this.characters.set("bf", character);
|
||||
character.zIndex = _data.characters.bf.zIndex;
|
||||
// Subtracting the origin ensures characters are positioned relative to their feet.
|
||||
trace('Data: ' + _data.characters.bf.position[0] + ', ' + _data.characters.bf.position[1]);
|
||||
character.x = _data.characters.bf.position[0] - character.characterOrigin.x;
|
||||
character.y = _data.characters.bf.position[1] - character.characterOrigin.y;
|
||||
trace('Character position: ' + character.x + ', ' + character.y);
|
||||
debugMarker.x = _data.characters.bf.position[0];
|
||||
debugMarker.y = _data.characters.bf.position[1];
|
||||
trace('Debug marker position: ' + debugMarker.x + ', ' + debugMarker.y);
|
||||
case GF:
|
||||
this.characters.set("gf", character);
|
||||
character.zIndex = _data.characters.gf.zIndex;
|
||||
// Subtracting the origin ensures characters are positioned relative to their feet.
|
||||
character.x = _data.characters.gf.position[0] - character.characterOrigin.x;
|
||||
character.y = _data.characters.gf.position[1] - character.characterOrigin.y;
|
||||
debugMarker.x = _data.characters.gf.position[0];
|
||||
debugMarker.y = _data.characters.gf.position[1];
|
||||
case DAD:
|
||||
this.characters.set("dad", character);
|
||||
character.zIndex = _data.characters.dad.zIndex;
|
||||
// Subtracting the origin ensures characters are positioned relative to their feet.
|
||||
character.x = _data.characters.dad.position[0] - character.characterOrigin.x;
|
||||
character.y = _data.characters.dad.position[1] - character.characterOrigin.y;
|
||||
debugMarker.x = _data.characters.dad.position[0];
|
||||
debugMarker.y = _data.characters.dad.position[1];
|
||||
default:
|
||||
this.characters.set(character.characterId, character);
|
||||
}
|
||||
|
||||
#if debug
|
||||
// Add a DEBUG marker for the character's origin.
|
||||
debugMarker.makeGraphic(10, 10, 0xFFFF00FF);
|
||||
debugMarker.zIndex = 10000;
|
||||
this.add(debugMarker);
|
||||
#end
|
||||
|
||||
// Add the character to the scene.
|
||||
this.add(character);
|
||||
}
|
||||
|
|
|
@ -223,10 +223,9 @@ class StageDataParser
|
|||
input.cameraZoom = DEFAULT_CAMERAZOOM;
|
||||
}
|
||||
|
||||
if (input.props == null || input.props.length == 0)
|
||||
if (input.props == null)
|
||||
{
|
||||
trace('[STAGEDATA] ERROR: Could not load stage data for "$id": missing props');
|
||||
return null;
|
||||
input.props = [];
|
||||
}
|
||||
|
||||
for (inputProp in input.props)
|
||||
|
|
|
@ -4,79 +4,28 @@ import flixel.system.FlxAssets.FlxShader;
|
|||
|
||||
class BuildingShaders
|
||||
{
|
||||
public var shader(default, null):BuildingShaderLegacy;
|
||||
public var shader(default, null):BuildingShader;
|
||||
public var daAlpha:Float = 1;
|
||||
|
||||
public function new():Void
|
||||
{
|
||||
shader = new BuildingShaderLegacy();
|
||||
shader.buildingAlpha = 0;
|
||||
shader = new BuildingShader();
|
||||
shader.alphaShit.value = [0];
|
||||
}
|
||||
|
||||
public function update(elapsed:Float):Void
|
||||
{
|
||||
shader.buildingAlpha += elapsed;
|
||||
shader.alphaShit.value[0] += elapsed;
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
shader.buildingAlpha = 0;
|
||||
shader.alphaShit.value[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
class BuildingShader extends FlxRuntimeShader
|
||||
class BuildingShader extends FlxShader
|
||||
{
|
||||
public var buildingAlpha(get, set):Float;
|
||||
|
||||
function get_buildingAlpha():Float
|
||||
{
|
||||
return getFloat('alphaShit');
|
||||
}
|
||||
|
||||
function set_buildingAlpha(value:Float):Float
|
||||
{
|
||||
// Every time buildingAlpha is changed, update the property of the shader.
|
||||
setFloat('alphaShit', value);
|
||||
return value;
|
||||
}
|
||||
|
||||
static final FRAGMENT_SHADER = "
|
||||
#pragma header
|
||||
|
||||
uniform float alphaShit;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 color = flixel_texture2D(bitmap, openfl_TextureCoordv);
|
||||
|
||||
if (color.a > 0.0)
|
||||
color -= alphaShit;
|
||||
|
||||
gl_FragColor = color;
|
||||
}
|
||||
";
|
||||
|
||||
public function new()
|
||||
{
|
||||
super(FRAGMENT_SHADER, null, true);
|
||||
}
|
||||
}
|
||||
|
||||
class BuildingShaderLegacy extends FlxShader
|
||||
{
|
||||
public var buildingAlpha(get, set):Float;
|
||||
|
||||
function get_buildingAlpha():Float
|
||||
{
|
||||
return alphaShit.value[0];
|
||||
}
|
||||
|
||||
function set_buildingAlpha(value:Float):Float
|
||||
{
|
||||
// Every time buildingAlpha is changed, update the property of the shader.
|
||||
alphaShit.value = [value];
|
||||
return value;
|
||||
}
|
||||
|
||||
@:glFragmentSource('
|
||||
#pragma header
|
||||
|
||||
|
|
|
@ -157,16 +157,17 @@ class PreferencesMenu extends Page
|
|||
});
|
||||
}
|
||||
|
||||
private static function preferenceCheck(prefString:String, prefValue:Dynamic):Void
|
||||
private static function preferenceCheck(prefString:String, defaultValue:Dynamic):Void
|
||||
{
|
||||
if (preferences.get(prefString) == null)
|
||||
{
|
||||
preferences.set(prefString, prefValue);
|
||||
trace('set preference!');
|
||||
// Set the value to default.
|
||||
preferences.set(prefString, defaultValue);
|
||||
trace('Set preference to default: ${prefString} = ${defaultValue}');
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('found preference: ' + preferences.get(prefString));
|
||||
trace('Found preference: ${prefString} = ${preferences.get(prefString)}');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package funkin.ui.animDebugShit;
|
||||
|
||||
import funkin.play.character.CharacterData.CharacterDataParser;
|
||||
import funkin.play.character.SparrowCharacter;
|
||||
import flixel.addons.display.FlxGridOverlay;
|
||||
import flixel.addons.ui.FlxInputText;
|
||||
import flixel.addons.ui.FlxUIDropDownMenu;
|
||||
|
@ -392,7 +394,7 @@ class DebugBoundingState extends FlxState
|
|||
if (FlxG.keys.justPressed.RIGHT || FlxG.keys.justPressed.LEFT || FlxG.keys.justPressed.UP || FlxG.keys.justPressed.DOWN)
|
||||
{
|
||||
var animName = animDropDownMenu.selectedLabel;
|
||||
var coolValues:Array<Int> = swagChar.animationOffsets.get(animName);
|
||||
var coolValues:Array<Float> = swagChar.animationOffsets.get(animName);
|
||||
|
||||
var multiplier:Int = 5;
|
||||
|
||||
|
@ -443,7 +445,7 @@ class DebugBoundingState extends FlxState
|
|||
swagChar.destroy();
|
||||
}
|
||||
|
||||
swagChar = new BaseCharacter(char);
|
||||
swagChar = CharacterDataParser.fetchCharacter(char);
|
||||
swagChar.x = 100;
|
||||
swagChar.y = 100;
|
||||
// swagChar.debugMode = true;
|
||||
|
|
Loading…
Reference in a new issue