Make GC V3 EXP boost config-driven

This commit is contained in:
2026-05-24 00:38:10 -04:00
parent e6b7ed7e24
commit f8ebc67c90
14 changed files with 2349 additions and 0 deletions
+74
View File
@@ -3688,6 +3688,79 @@ static asio::awaitable<void> dispatch_dc_v2_exp_patch(shared_ptr<Client> c) {
}
}
// Dispatch the correct GC V3 EXP table for the current episode when the
// universal GC EXP enable shim is active. This avoids EP1/EP2 patches
// overwriting each other or leaving stale episode tables in memory.
static asio::awaitable<void> dispatch_gc_v3_exp_patch(shared_ptr<Client> c) {
if (c->version() != Version::GC_V3) {
co_return;
}
if (not c->check_flag(Client::Flag::HAS_SEND_FUNCTION_CALL)) {
co_return;
}
if (not c->login || not c->login->account) {
co_return;
}
if (not c->login->account->auto_patches_enabled.count("PsoPeepsGCV3EXP_enabled")) {
co_return;
}
auto l = c->require_lobby();
if (not l->is_game()) {
co_return;
}
const char* key = nullptr;
size_t num_exp_labels = 0;
switch (l->episode) {
case Episode::EP1:
key = "PsoPeepsEP1EXP_internal";
num_exp_labels = 204;
break;
case Episode::EP2:
key = "PsoPeepsEP2EXP_internal";
num_exp_labels = 239;
break;
default:
co_return;
}
try {
auto server_state = c->require_server_state();
auto base_fn = server_state->client_functions->get(key, c->specific_version);
auto fn = make_shared<ClientFunctionIndex::Function>(*base_fn);
for (size_t z = 0; z < num_exp_labels; z++) {
string label = std::format("exp_{:03}", z);
size_t offset = fn->label_offsets.at(label);
if (offset > fn->code.size() - 4) {
throw runtime_error("GC V3 EXP label out of range");
}
uint32_t base_exp =
(static_cast<uint32_t>(static_cast<uint8_t>(fn->code[offset])) << 24) |
(static_cast<uint32_t>(static_cast<uint8_t>(fn->code[offset + 1])) << 16) |
(static_cast<uint32_t>(static_cast<uint8_t>(fn->code[offset + 2])) << 8) |
static_cast<uint32_t>(static_cast<uint8_t>(fn->code[offset + 3]));
uint64_t scaled_exp = static_cast<uint64_t>(base_exp) *
static_cast<uint64_t>(server_state->gc_v3_exp_multiplier);
if (scaled_exp > 0xFFFFFFFFULL) {
scaled_exp = 0xFFFFFFFFULL;
}
fn->code[offset] = static_cast<char>((scaled_exp >> 24) & 0xFF);
fn->code[offset + 1] = static_cast<char>((scaled_exp >> 16) & 0xFF);
fn->code[offset + 2] = static_cast<char>((scaled_exp >> 8) & 0xFF);
fn->code[offset + 3] = static_cast<char>(scaled_exp & 0xFF);
}
co_await send_function_call(c, fn);
} catch (const out_of_range&) {
c->log.warning_f("GC V3 EXP dispatcher could not find client function {}", key);
}
}
static asio::awaitable<void> on_trigger_set_event(shared_ptr<Client> c, SubcommandMessage& msg) {
auto l = c->require_lobby();
if (!l->is_game()) {
@@ -3695,6 +3768,7 @@ static asio::awaitable<void> on_trigger_set_event(shared_ptr<Client> c, Subcomma
}
co_await dispatch_dc_v2_exp_patch(c);
co_await dispatch_gc_v3_exp_patch(c);
const auto& cmd = msg.check_size_t<G_TriggerSetEvent_6x67>();
auto event_sts = l->map_state->event_states_for_id(c->version(), cmd.floor, cmd.event_id);
+1
View File
@@ -1139,6 +1139,7 @@ void ServerState::load_config_early() {
this->bb_global_exp_multiplier = this->config_json->get_float("BBGlobalEXPMultiplier", 1.0f);
this->dc_v2_exp_multiplier = std::max<int64_t>(1, this->config_json->get_int("DCV2EXPMultiplier", 1));
this->gc_v3_exp_multiplier = std::max<int64_t>(1, this->config_json->get_int("GCV3EXPMultiplier", 1));
this->exp_share_multiplier = this->config_json->get_float("BBEXPShareMultiplier", 0.5f);
this->server_global_drop_rate_multiplier = this->config_json->get_float("ServerGlobalDropRateMultiplier", 1.0f);
+1
View File
@@ -270,6 +270,7 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
QuestF960Result quest_F960_failure_results;
float bb_global_exp_multiplier = 1.0f;
int64_t dc_v2_exp_multiplier = 1;
int64_t gc_v3_exp_multiplier = 1;
float exp_share_multiplier = 0.5f;
float server_global_drop_rate_multiplier = 1.0f;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,14 @@
.meta visibility="menu"
.meta key="PsoPeepsGCV3EXP_enabled"
.meta name="GC XP"
.meta client_flag="0x0000200000000000"
.meta description="Enables server-scaled GC V3 EXP boost. Server applies the correct Episode 1 or Episode 2 table."
.versions 3OE2 3OJ5
entry_ptr:
reloc0:
.offsetof start
start:
blr