2024-08-10 12:07:54 -04:00
|
|
|
#include "global.h"
|
|
|
|
|
#include "GameplayAssist.h"
|
|
|
|
|
#include "GamePreferences.h"
|
|
|
|
|
#include "GameState.h"
|
|
|
|
|
#include "Player.h"
|
|
|
|
|
#include "PlayerState.h"
|
|
|
|
|
#include "ScreenDimensions.h"
|
|
|
|
|
#include "Style.h"
|
|
|
|
|
#include "EditModePlayerManager.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void EditModePlayerManager::AddPlayers(const NoteData& note_data) {
|
2025-01-23 11:45:45 -05:00
|
|
|
FOREACH_EnabledPlayer(pn) {
|
|
|
|
|
// In case of a routine chart, both players are actually seen as
|
|
|
|
|
// enabled. This isn't desired, since the playerState and inputs in
|
|
|
|
|
// routine charts eventually collapse down only to P1.
|
|
|
|
|
if ((GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StyleType == StyleType_TwoPlayersSharedSides) && pn != PLAYER_1) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2024-08-10 12:07:54 -04:00
|
|
|
players_[pn] = std::make_shared<PlayerPlus>();
|
|
|
|
|
|
|
|
|
|
PlayerPlus& player = *players_[pn];
|
|
|
|
|
player->Init("Player", GAMESTATE->m_pPlayerState[pn], nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
|
|
|
|
|
player.Load(note_data);
|
|
|
|
|
|
|
|
|
|
player->CacheAllUsedNoteSkins();
|
|
|
|
|
GAMESTATE->m_pPlayerState[pn]->m_PlayerController = PC_HUMAN;
|
|
|
|
|
player->SetY(SCREEN_CENTER_Y);
|
|
|
|
|
player->SetZoom(SCREEN_HEIGHT / 480);
|
|
|
|
|
StyleType style_type = GAMESTATE->GetCurrentStyle(pn)->m_StyleType;
|
2024-09-23 16:12:04 -04:00
|
|
|
if (center_) {
|
|
|
|
|
// Use the doubles style positioning for centering.
|
|
|
|
|
style_type = StyleType_OnePlayerTwoSides;
|
|
|
|
|
}
|
2024-08-10 12:07:54 -04:00
|
|
|
player->SetX(THEME->GetMetricF("ScreenGameplay", ssprintf("PlayerP%d%sX", pn + 1, StyleTypeToString(style_type).c_str())));
|
|
|
|
|
|
2024-09-30 16:19:38 -04:00
|
|
|
// Initial state is to hide the notefield.
|
|
|
|
|
player->SetVisible(false);
|
|
|
|
|
}
|
2024-08-10 12:07:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void EditModePlayerManager::AddPlayersToActorFrame(ActorFrame& frame) {
|
|
|
|
|
for (auto& player : players_) {
|
|
|
|
|
frame.AddChild(*player.second);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void EditModePlayerManager::ReloadNoteData(const NoteData& note_data) {
|
|
|
|
|
for (auto& player : players_) {
|
|
|
|
|
player.second->Load(note_data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void EditModePlayerManager::SetVisible(bool visible) {
|
2024-09-30 16:19:38 -04:00
|
|
|
// If this is a routine chart, only set visibility of PLAYER_1.
|
|
|
|
|
if (GAMESTATE->GetCurrentStyle(PLAYER_1)->m_StyleType ==
|
|
|
|
|
StyleType::StyleType_TwoPlayersSharedSides) {
|
|
|
|
|
(*players_[PLAYER_1])->SetVisible(visible);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-10 12:07:54 -04:00
|
|
|
for (auto& player : players_) {
|
|
|
|
|
(*player.second)->SetVisible(visible);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool EditModePlayerManager::HandleGameplayInput(const InputEventPlus& input, const GameButtonType& gbt) {
|
2024-09-30 16:19:38 -04:00
|
|
|
PlayerNumber pn = input.pn;
|
|
|
|
|
|
|
|
|
|
// Redirect Player2's inputs to P1's notefield in case of Routine charts.
|
|
|
|
|
if (GAMESTATE->GetCurrentStyle(GAMESTATE->GetMasterPlayerNumber())->m_StyleType == StyleType_TwoPlayersSharedSides) {
|
|
|
|
|
pn = PLAYER_1;
|
|
|
|
|
}
|
|
|
|
|
if (gbt == GameButtonType_Step && GAMESTATE->IsPlayerEnabled(pn)) {
|
|
|
|
|
if (GAMESTATE->m_pPlayerState[pn]->m_PlayerController == PC_AUTOPLAY) {
|
2024-08-10 12:07:54 -04:00
|
|
|
return false;
|
|
|
|
|
}
|
2024-09-30 16:19:38 -04:00
|
|
|
const int iCol = GAMESTATE->GetCurrentStyle(pn)->GameInputToColumn(input.GameI);
|
2024-08-10 12:07:54 -04:00
|
|
|
if (iCol != -1) {
|
2024-09-30 16:19:38 -04:00
|
|
|
(*players_[pn])->Step(iCol, -1, input.DeviceI.ts, false, input.type == IET_RELEASE);
|
2024-08-10 12:07:54 -04:00
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EditModePlayerManager::SetupAutoplay() {
|
|
|
|
|
for (auto& player : players_) {
|
|
|
|
|
if (GAMESTATE->m_pPlayerState[player.first]->m_PlayerOptions.GetCurrent().m_fPlayerAutoPlay != 0) {
|
|
|
|
|
GAMESTATE->m_pPlayerState[player.first]->m_PlayerController = PC_AUTOPLAY;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
GAMESTATE->m_pPlayerState[player.first]->m_PlayerController = GamePreferences::m_AutoPlay;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EditModePlayerManager::CacheAllUsedNoteSkins() {
|
|
|
|
|
for (auto& player : players_) {
|
|
|
|
|
(*player.second)->CacheAllUsedNoteSkins();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void EditModePlayerManager::PlayTicks(GameplayAssist& gameplay_assist) {
|
|
|
|
|
for (auto& player : players_) {
|
|
|
|
|
// Edit mode does not support 2p practicing different steps, so
|
|
|
|
|
// enabling one set of ticks is fine.
|
|
|
|
|
gameplay_assist.PlayTicks((*player.second)->GetNoteData(), (*player.second)->GetPlayerState());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|