fix director_cut cheat + easter egg stats

closes #60 #42 #47
This commit is contained in:
m 2024-01-21 12:45:42 -06:00
parent 8105fc0480
commit 5abecf9fad
2 changed files with 248 additions and 194 deletions

View File

@ -472,20 +472,6 @@ namespace command
game::Com_GameMode_SetDesiredGameMode(game::GAME_MODE_CP); game::Com_GameMode_SetDesiredGameMode(game::GAME_MODE_CP);
}); });
add("director_cut", [](const params& params)
{
if (params.size() == 2)
{
const auto value = static_cast<int>(atoi(params.get(1)));
utils::hook::set<int>(0x5ECB830_b, value);
}
else
{
const auto command = params.get(0);
console::error("Incorrect number of arguments for \"%s\".\n", command);
}
});
add_sv("god", [](const int client_num, const params_sv&) add_sv("god", [](const int client_num, const params_sv&)
{ {
if (!game::shared::cheats_ok(client_num, true)) if (!game::shared::cheats_ok(client_num, true))

View File

@ -14,17 +14,103 @@
namespace stats namespace stats
{ {
void unlock_stats() namespace
{
utils::hook::detour is_item_unlocked_hook;
utils::hook::detour is_item_unlocked_hook2;
utils::hook::detour item_quantity_hook;
bool is_item_unlocked_stub(__int64 a1, int a2, const char* unlock_table, unsigned __int8* value)
{
if (dvars::cg_unlockall_items && dvars::cg_unlockall_items->current.enabled)
{
return true;
}
return is_item_unlocked_hook.invoke<bool>(a1, a2, unlock_table, value);
}
bool is_item_unlocked_stub2(__int64 a1, int a2, const char* unlock_table, unsigned __int8* value)
{
if (dvars::cg_unlockall_items && dvars::cg_unlockall_items->current.enabled)
{
return true;
}
return is_item_unlocked_hook2.invoke<bool>(a1, a2, unlock_table, value);
}
int item_quantity_stub(__int64 a1, int a2, int id)
{
auto result = item_quantity_hook.invoke<int>(a1, a2, id);
// 30000 crashes
if (id != 30000 && dvars::cg_unlockall_loot && dvars::cg_unlockall_loot->current.enabled)
{
return 1;
}
return result;
}
void com_ddl_print_state(const game::DDLState* state, const game::DDLContext* context)
{
if (game::DDL_StateIsLeaf(state))
{
const auto type = game::DDL_GetType(state);
const auto value = game::DDL_GetValue(state, context);
switch (type)
{
case game::DDL_BYTE_TYPE:
case game::DDL_SHORT_TYPE:
case game::DDL_UINT_TYPE:
case game::DDL_INT_TYPE:
console::info("%d\n", value.intValue);
break;
case game::DDL_UINT64_TYPE:
console::info("%zu\n", value.uint64Value);
break;
case game::DDL_FLOAT_TYPE:
console::info("%f\n", value.floatValue);
break;
case game::DDL_STRING_TYPE:
console::info("%s\n", value.stringPtr);
break;
case game::DDL_ENUM_TYPE:
console::info("%s\n", game::DDL_Lookup_GetEnumString(state, value.intValue));
break;
default:
console::info("Unknown type (%d).\n", type);
break;
}
}
else
{
console::info("non leaf node named \"%s\"\n", state->member->name);
}
}
bool can_run_command()
{ {
if (game::CL_IsGameClientActive(0)) if (game::CL_IsGameClientActive(0))
{ {
console::info("Not allowed while ingame."); console::error("Not allowed while ingame.");
return; return false;
} }
if (game::Com_GameMode_GetActiveGameMode() != game::GAME_MODE_MP && game::Com_GameMode_GetActiveGameMode() != game::GAME_MODE_CP) if (game::Com_GameMode_GetActiveGameMode() != game::GAME_MODE_MP && game::Com_GameMode_GetActiveGameMode() != game::GAME_MODE_CP)
{ {
console::info("Must be in multiplayer or coop."); console::error("Must be in multiplayer or coop.");
return false;
}
return true;
}
void unlock_stats()
{
if (!can_run_command())
{
return; return;
} }
@ -192,82 +278,60 @@ namespace stats
command::execute(utils::string::va("setCoopPlayerData meritProgress %s %d", challenge, max_progress), true); command::execute(utils::string::va("setCoopPlayerData meritProgress %s %d", challenge, max_progress), true);
} }
} }
command::execute("uploadstats", true); // needed to update stats i think
console::debug("unlocked all normal stats!\n");
} }
namespace void unlock_stats_ee()
{ {
utils::hook::detour is_item_unlocked_hook; if (!can_run_command())
utils::hook::detour is_item_unlocked_hook2;
utils::hook::detour item_quantity_hook;
bool is_item_unlocked_stub(__int64 a1, int a2, const char* unlock_table, unsigned __int8* value)
{ {
if (dvars::cg_unlockall_items && dvars::cg_unlockall_items->current.enabled) return;
{
return true;
} }
return is_item_unlocked_hook.invoke<bool>(a1, a2, unlock_table, value); // soul keys (secret characters)
command::execute("setCoopPlayerData haveSoulKeys any_soul_key 1", true); // useless stat?
command::execute("setCoopPlayerData haveSoulKeys soul_key_1 1", true);
command::execute("setCoopPlayerData haveSoulKeys soul_key_2 1", true);
command::execute("setCoopPlayerData haveSoulKeys soul_key_3 1", true);
command::execute("setCoopPlayerData haveSoulKeys soul_key_4 1", true);
command::execute("setCoopPlayerData haveSoulKeys soul_key_5 1", true);
// secret character 5 on cp_zmb
command::execute("setCoopPlayerData meritState mt_dlc4_troll2 1", true); // Conditions.HasBeatenMeph
command::execute("setCoopPlayerData meritState mt_dc_camo 1", true);
// lobby songs unlocked
command::execute("setCoopPlayerData hasSongsUnlocked any_song 1", true);
for (int index = 1; index < 11; index++)
{
command::execute(utils::string::va("setCoopPlayerData hasSongsUnlocked song_%d 1", index), true);
} }
bool is_item_unlocked_stub2(__int64 a1, int a2, const char* unlock_table, unsigned __int8* value) command::execute("uploadstats", true); // needed to update stats i think
{ console::debug("unlocked all easter egg stats!\n");
if (dvars::cg_unlockall_items && dvars::cg_unlockall_items->current.enabled)
{
return true;
} }
return is_item_unlocked_hook2.invoke<bool>(a1, a2, unlock_table, value); void director_cut(const command::params& params)
{
if (!can_run_command())
{
return;
} }
int item_quantity_stub(__int64 a1, int a2, int id) if (params.size() < 2)
{ {
auto result = item_quantity_hook.invoke<int>(a1, a2, id); console::info("usage: \"/director_cut 0/1\"\n");
return;
// 30000 crashes
if (id != 30000 && dvars::cg_unlockall_loot && dvars::cg_unlockall_loot->current.enabled)
{
return 1;
} }
return result; const auto is_enabled = params.get(1);
} command::execute(utils::string::va("setCoopPlayerData dc %s", is_enabled), true);
command::execute(utils::string::va("setCoopPlayerData dc_available %s", is_enabled), true);
void com_ddl_print_state(const game::DDLState* state, const game::DDLContext* context) command::execute("uploadstats", true); // needed to update stats i think
{ console::debug("directors cut set to %s\n", is_enabled);
if (game::DDL_StateIsLeaf(state))
{
const auto type = game::DDL_GetType(state);
const auto value = game::DDL_GetValue(state, context);
switch (type)
{
case game::DDL_BYTE_TYPE:
case game::DDL_SHORT_TYPE:
case game::DDL_UINT_TYPE:
case game::DDL_INT_TYPE:
console::info("%d\n", value.intValue);
break;
case game::DDL_UINT64_TYPE:
console::info("%zu\n", value.uint64Value);
break;
case game::DDL_FLOAT_TYPE:
console::info("%f\n", value.floatValue);
break;
case game::DDL_STRING_TYPE:
console::info("%s\n", value.stringPtr);
break;
case game::DDL_ENUM_TYPE:
console::info("%s\n", game::DDL_Lookup_GetEnumString(state, value.intValue));
break;
default:
console::info("Unknown type (%d).\n", type);
break;
}
}
else
{
console::info("non leaf node named \"%s\"\n", state->member->name);
}
} }
} }
@ -282,6 +346,10 @@ namespace stats
} }
command::add("unlockstats", unlock_stats); command::add("unlockstats", unlock_stats);
command::add("unlockall", unlock_stats);
command::add("unlockstatsEE", unlock_stats_ee);
command::add("unlockallEE", unlock_stats_ee);
command::add("director_cut", director_cut);
// register dvars // register dvars
scheduler::once([]() scheduler::once([]()