Make GC V3 EXP boost config-driven
This commit is contained in:
@@ -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) {
|
static asio::awaitable<void> on_trigger_set_event(shared_ptr<Client> c, SubcommandMessage& msg) {
|
||||||
auto l = c->require_lobby();
|
auto l = c->require_lobby();
|
||||||
if (!l->is_game()) {
|
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_dc_v2_exp_patch(c);
|
||||||
|
co_await dispatch_gc_v3_exp_patch(c);
|
||||||
|
|
||||||
const auto& cmd = msg.check_size_t<G_TriggerSetEvent_6x67>();
|
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);
|
auto event_sts = l->map_state->event_states_for_id(c->version(), cmd.floor, cmd.event_id);
|
||||||
|
|||||||
@@ -1139,6 +1139,7 @@ void ServerState::load_config_early() {
|
|||||||
|
|
||||||
this->bb_global_exp_multiplier = this->config_json->get_float("BBGlobalEXPMultiplier", 1.0f);
|
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->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->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);
|
this->server_global_drop_rate_multiplier = this->config_json->get_float("ServerGlobalDropRateMultiplier", 1.0f);
|
||||||
|
|
||||||
|
|||||||
@@ -270,6 +270,7 @@ struct ServerState : public std::enable_shared_from_this<ServerState> {
|
|||||||
QuestF960Result quest_F960_failure_results;
|
QuestF960Result quest_F960_failure_results;
|
||||||
float bb_global_exp_multiplier = 1.0f;
|
float bb_global_exp_multiplier = 1.0f;
|
||||||
int64_t dc_v2_exp_multiplier = 1;
|
int64_t dc_v2_exp_multiplier = 1;
|
||||||
|
int64_t gc_v3_exp_multiplier = 1;
|
||||||
float exp_share_multiplier = 0.5f;
|
float exp_share_multiplier = 0.5f;
|
||||||
float server_global_drop_rate_multiplier = 1.0f;
|
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
|
||||||
Reference in New Issue
Block a user