Allow for song specific module choices and saving/loading of song specific module choices.
This feature should require use_card, this is automatically enabled by default (this may be changed in the next commit) and has one notable bug, which is a significant FPS drop when selecting (or sometimes loading) modules on songs with 3 vocals. (This does NOT impact gameplay past song select to my knowledge) Huge thanks to somewhatlurker again for coding help and advice as well as just being a sweetie <3
This commit is contained in:
@@ -29,6 +29,9 @@ namespace TLAC::Components
|
||||
int ModuleEquipCmn3;
|
||||
int ModuleEquipCmn4;
|
||||
int ModuleEquipCmn5;
|
||||
int ActionVol;
|
||||
int ActionSlideVol;
|
||||
int UsePVEquip;
|
||||
bool ShowGreatClearBorder;
|
||||
bool ShowExcellentClearBorder;
|
||||
bool ShowRivalClearBorder;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
const std::string PLAYER_DATA_FILE_NAME = "playerdata.ini";
|
||||
static WCHAR configPath[256];
|
||||
int* headitemequip = (int*)0x0000000141804CDC;
|
||||
int customheaditemequip;
|
||||
namespace TLAC::Components
|
||||
{
|
||||
PlayerDataManager::PlayerDataManager()
|
||||
@@ -234,7 +236,7 @@ namespace TLAC::Components
|
||||
config.TryGetValue("player_name", &customPlayerData->PlayerName);
|
||||
config.TryGetValue("level_name", &customPlayerData->LevelName);
|
||||
|
||||
// ScoreSaver copies (can be improved?)
|
||||
// ScoreSaver copies & declaring non-playerdata values
|
||||
std::string utf8path = TLAC::framework::GetModuleDirectory() + "/playerdata.ini";
|
||||
MultiByteToWideChar(CP_UTF8, 0, utf8path.c_str(), -1, configPath, 256);
|
||||
|
||||
@@ -253,12 +255,16 @@ namespace TLAC::Components
|
||||
//customPlayerData->ModuleEquip3 = config.GetIntegerValue("module_equip3");
|
||||
//customPlayerData->ModuleEquip4 = config.GetIntegerValue("module_equip4");
|
||||
//customPlayerData->ModuleEquip5 = config.GetIntegerValue("module_equip5");
|
||||
customPlayerData->UsePVEquip = config.GetIntegerValue("use_pv_module_equip");
|
||||
customPlayerData->ModuleEquipCmn0 = config.GetIntegerValue("module_equip_cmn0");
|
||||
customPlayerData->ModuleEquipCmn1 = config.GetIntegerValue("module_equip_cmn1");
|
||||
customPlayerData->ModuleEquipCmn2 = config.GetIntegerValue("module_equip_cmn2");
|
||||
customPlayerData->ModuleEquipCmn3 = config.GetIntegerValue("module_equip_cmn3");
|
||||
customPlayerData->ModuleEquipCmn4 = config.GetIntegerValue("module_equip_cmn4");
|
||||
customPlayerData->ModuleEquipCmn5 = config.GetIntegerValue("module_equip_cmn5");
|
||||
customPlayerData->ActionVol = config.GetIntegerValue("act_vol");
|
||||
customPlayerData->ActionSlideVol = config.GetIntegerValue("act_slide_vol");
|
||||
customheaditemequip = config.GetIntegerValue("head_item");
|
||||
customPlayerData->ShowExcellentClearBorder = config.GetBooleanValue("border_excellent");
|
||||
customPlayerData->ShowGreatClearBorder = config.GetBooleanValue("border_great");
|
||||
customPlayerData->ShowRivalClearBorder = config.GetBooleanValue("border_rival");
|
||||
@@ -274,15 +280,18 @@ namespace TLAC::Components
|
||||
* target = value;
|
||||
};
|
||||
|
||||
// only need to run this line once on startup, otherwise cannot increase/decrease in-game
|
||||
// only need to run this line once on startup, otherwise cannot increase/decrease in-game (or use per-song settings!)
|
||||
setIfNotEqual(&playerData->vocaloid_point, customPlayerData->VocaloidPoints, 0);
|
||||
// run once to check if module setting is invalid
|
||||
setIfNotEqual(&playerData->skin_equip_cmn, customPlayerData->SkinEquip, 0);
|
||||
setIfNotEqual(&playerData->module_equip_cmn0, customPlayerData->ModuleEquipCmn0, 0);
|
||||
setIfNotEqual(&playerData->module_equip_cmn1, customPlayerData->ModuleEquipCmn1, 0);
|
||||
setIfNotEqual(&playerData->module_equip_cmn2, customPlayerData->ModuleEquipCmn2, 0);
|
||||
setIfNotEqual(&playerData->module_equip_cmn3, customPlayerData->ModuleEquipCmn3, 0);
|
||||
setIfNotEqual(&playerData->module_equip_cmn4, customPlayerData->ModuleEquipCmn4, 0);
|
||||
setIfNotEqual(&playerData->module_equip_cmn5, customPlayerData->ModuleEquipCmn5, 0);
|
||||
setIfNotEqual(headitemequip, customheaditemequip, 0);
|
||||
setIfNotEqual(&playerData->act_vol, customPlayerData->ActionVol, 100);
|
||||
setIfNotEqual(&playerData->act_slide_vol, customPlayerData->ActionSlideVol, 100);
|
||||
|
||||
std::string* mylistString;
|
||||
std::vector<std::string> mylistStringVec;
|
||||
@@ -434,11 +443,36 @@ namespace TLAC::Components
|
||||
swprintf(val, 32, L"%d", playerData->module_equip_cmn5);
|
||||
WritePrivateProfileStringW(L"playerdata", L"module_equip_cmn5", val, configPath);
|
||||
}
|
||||
if (customPlayerData->ActionVol != playerData->act_vol)
|
||||
{
|
||||
customPlayerData->ActionVol = playerData->act_vol;
|
||||
WCHAR val[32];
|
||||
swprintf(val, 32, L"%d", playerData->act_vol);
|
||||
WritePrivateProfileStringW(L"playerdata", L"act_vol", val, configPath);
|
||||
}
|
||||
if (customPlayerData->ActionSlideVol != playerData->act_slide_vol)
|
||||
{
|
||||
customPlayerData->ActionSlideVol = playerData->act_slide_vol;
|
||||
WCHAR val[32];
|
||||
swprintf(val, 32, L"%d", playerData->act_slide_vol);
|
||||
WritePrivateProfileStringW(L"playerdata", L"act_slide_vol", val, configPath);
|
||||
}
|
||||
if (playerData->use_pv_module_equip != 1)
|
||||
{
|
||||
playerData->use_pv_module_equip = 1;
|
||||
}
|
||||
if (customheaditemequip != *headitemequip)
|
||||
{
|
||||
customheaditemequip = *headitemequip;
|
||||
WCHAR val[32];
|
||||
swprintf(val, 32, L"%d", *headitemequip);
|
||||
WritePrivateProfileStringW(L"playerdata", L"head_item", val, configPath);
|
||||
}
|
||||
|
||||
|
||||
setIfNotEqual(&playerData->level, customPlayerData->LevelNum, 1);
|
||||
setIfNotEqual(&playerData->level_plate_id, customPlayerData->LevelPlateId, 0);
|
||||
setIfNotEqual(&playerData->level_plate_effect, customPlayerData->LevelPlateEffect, 0);
|
||||
setIfNotEqual(&playerData->skin_equip, customPlayerData->SkinEquip, 0);
|
||||
setIfNotEqual(&playerData->btn_se_equip, customPlayerData->BtnSeEquip, -1);
|
||||
setIfNotEqual(&playerData->slide_se_equip, customPlayerData->SlideSeEquip, -1);
|
||||
setIfNotEqual(&playerData->chainslide_se_equip, customPlayerData->ChainslideSeEquip, -1);
|
||||
|
||||
@@ -13,12 +13,15 @@ namespace TLAC::Components
|
||||
{
|
||||
WCHAR ScoreSaver::configPath[256];
|
||||
WCHAR ScoreSaver::rival_configPath[256];
|
||||
WCHAR ScoreSaver::modules_configPath[256];
|
||||
ScoreSaver::ScoreSaver()
|
||||
{
|
||||
std::string utf8path = TLAC::framework::GetModuleDirectory() + "/scores.ini";
|
||||
MultiByteToWideChar(CP_UTF8, 0, utf8path.c_str(), -1, configPath, 256);
|
||||
utf8path = TLAC::framework::GetModuleDirectory() + "/rivalscores.ini";
|
||||
MultiByteToWideChar(CP_UTF8, 0, utf8path.c_str(), -1, rival_configPath, 256);
|
||||
utf8path = TLAC::framework::GetModuleDirectory() + "/modules.ini";
|
||||
MultiByteToWideChar(CP_UTF8, 0, utf8path.c_str(), -1, modules_configPath, 256);
|
||||
}
|
||||
|
||||
ScoreSaver::~ScoreSaver()
|
||||
@@ -354,12 +357,16 @@ namespace TLAC::Components
|
||||
// update score begin and end vars from game
|
||||
FixScoreCacheAddresses(diff);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
UpdateSingleScoreCacheModulesEntry;
|
||||
}
|
||||
currentPv = pvNum;
|
||||
currentDifficulty = diff;
|
||||
currentDifficultyIsEx = diffIsEx;
|
||||
currentInsurance = insurance;
|
||||
}
|
||||
ModuleCheck(pvNum, diff, diffIsEx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -541,6 +548,73 @@ namespace TLAC::Components
|
||||
}
|
||||
}
|
||||
|
||||
void ScoreSaver::UpdateSingleScoreCacheModulesEntry(int pvNum, int diff, int exDiff)
|
||||
{
|
||||
if (pvNum < 0 || diff < 0 || exDiff < 0 || pvNum > 999 || diff > 3 || exDiff > 1)
|
||||
return;
|
||||
|
||||
|
||||
WCHAR keyBase[32]; // needs to be big enough to store pv.999
|
||||
WCHAR key[32]; // needs to be big enough to store pv.999.module5
|
||||
|
||||
const WCHAR section[] = L"modules";
|
||||
swprintf(keyBase, 32, L"pv.%03d", pvNum);
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
swprintf(key, 32, L"%ls.module%d", keyBase, i);
|
||||
int INImodule = GetPrivateProfileIntW(section, key, 0, modules_configPath);
|
||||
|
||||
if (INImodule > 0)
|
||||
{
|
||||
DivaScore* cachedScore = GetCachedScore(pvNum, diff, exDiff);
|
||||
if (cachedScore == nullptr)
|
||||
{
|
||||
ScoreCache[diff].push_back(DivaScore(pvNum, exDiff));
|
||||
cachedScore = GetCachedScore(pvNum, diff, exDiff);
|
||||
}
|
||||
if (cachedScore != nullptr)
|
||||
{
|
||||
cachedScore->per_module_equip[i] = INImodule;
|
||||
WCHAR val[32];
|
||||
swprintf(val, 32, L"%d", INImodule);
|
||||
WritePrivateProfileStringW(L"modules", key, val, modules_configPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ScoreSaver::ModuleCheck(int pvNum, int diff, int exDiff)
|
||||
{
|
||||
if (pvNum < 0 || diff < 0 || exDiff < 0 || pvNum > 999 || diff > 3 || exDiff > 1)
|
||||
return;
|
||||
|
||||
WCHAR keyBase[32]; // needs to be big enough to store pv.999
|
||||
WCHAR key[32]; // needs to be big enough to store pv.999.module5
|
||||
const WCHAR section[] = L"modules";
|
||||
swprintf(keyBase, 32, L"pv.%03d", pvNum);
|
||||
DivaScore* cachedScore = GetCachedScore(pvNum, diff, exDiff);
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
swprintf(key, 32, L"%ls.module%d", keyBase, i);
|
||||
int INImodule = GetPrivateProfileIntW(section, key, 0, modules_configPath);
|
||||
if (INImodule != cachedScore->per_module_equip[0] || INImodule != cachedScore->per_module_equip[1] || INImodule != cachedScore->per_module_equip[2] || INImodule != cachedScore->per_module_equip[3] || INImodule != cachedScore->per_module_equip[4] || INImodule != cachedScore->per_module_equip[5])
|
||||
{
|
||||
INImodule = *cachedScore->per_module_equip;
|
||||
WCHAR val[32];
|
||||
swprintf(val, 32, L"%d", cachedScore->per_module_equip[i]);
|
||||
WritePrivateProfileStringW(L"modules", key, val, modules_configPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ScoreSaver::FixScoreCacheAddresses(int diff)
|
||||
{
|
||||
// update score begin and end vars from game
|
||||
@@ -558,6 +632,7 @@ namespace TLAC::Components
|
||||
{
|
||||
UpdateSingleScoreCacheEntry(pvNum, diff, exDiff, false);
|
||||
UpdateSingleScoreCacheRivalEntry(pvNum, diff, exDiff);
|
||||
UpdateSingleScoreCacheModulesEntry(pvNum, diff, exDiff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,13 @@ namespace TLAC::Components
|
||||
{
|
||||
int pvNum;
|
||||
int exDifficulty;
|
||||
byte padding08[0xa4]; // ??? -- seems to be 6*6 ints (0x90 bytes) for modules + 5 ints (0x14 bytes) for skin and button se
|
||||
int per_module_equip[6];
|
||||
int other_module_shit[30]; // ??? -- seems to be 6*6 ints (0x90 bytes) for modules + 5 ints (0x14 bytes) for skin and button se
|
||||
int per_skin_equip;
|
||||
int per_btn_se_equip;
|
||||
int per_slide_se_equip;
|
||||
int per_chainslide_se_equip;
|
||||
int per_slidertouch_se_equip;
|
||||
int clearRank; // +0xac: clear rank
|
||||
int score; // +0xb0: score
|
||||
int percent; // +0xb4: best percent
|
||||
@@ -104,9 +110,11 @@ namespace TLAC::Components
|
||||
static void UpdateScoreCache();
|
||||
static void UpdateSingleScoreCacheEntry(int pvNum, int diff, int exDiff, bool doDefaultsReset);
|
||||
static void UpdateSingleScoreCacheRivalEntry(int pvNum, int diff, int exDiff);
|
||||
static void UpdateSingleScoreCacheModulesEntry(int pvNum, int diff, int exDiff);
|
||||
static void FixScoreCacheAddresses(int diff); // only call this from the main thread
|
||||
static DivaScore* GetCachedScore(int pvNum, int diff, int exDiff);
|
||||
static void UpdateClearCounts();
|
||||
static void ModuleCheck(int pvNum, int diff, int exDiff);
|
||||
|
||||
private:
|
||||
static bool(__stdcall* divaInitResults)(void* cls);
|
||||
@@ -118,6 +126,7 @@ namespace TLAC::Components
|
||||
|
||||
static WCHAR configPath[256];
|
||||
static WCHAR rival_configPath[256];
|
||||
static WCHAR modules_configPath[256];
|
||||
static std::thread initThread;
|
||||
|
||||
int currentPv;
|
||||
|
||||
Reference in New Issue
Block a user