DETOUR_DECL_STATIC(bool __gcc_regcall, ParseDynamicAttributes, void *ecattr, KeyValues *kv) { DevMsg("ParseDynamicAttributes: \"%s\" \"%s\"\n", kv->GetName(), kv->GetString()); if (V_stricmp(kv->GetName(), "ExtAttr") == 0) { auto ext = reinterpret_cast<CTFBot::ExtendedAttr *>((uintptr_t)ecattr + 0x10); const char *val = kv->GetString(); if (V_stricmp(val, "AlwaysFireWeaponAlt") == 0) { DevMsg(" found: ExtAttr AlwaysFireWeaponAlt\n"); ext->TurnOn(ExtAttr::ALWAYS_FIRE_WEAPON_ALT); } else if (V_stricmp(val, "TargetStickies") == 0) { DevMsg(" found: ExtAttr TargetStickies\n"); ext->TurnOn(ExtAttr::TARGET_STICKIES); } else { Warning("TFBotSpawner: Invalid extended attribute '%s'\n", val); } DevMsg(" Got ExtAttr, returning true\n"); return true; } DevMsg(" Passing through to actual ParseDynamicAttributes\n"); return DETOUR_STATIC_CALL(ParseDynamicAttributes)(ecattr, kv); }
DETOUR_DECL_STATIC(const char *, MapEntity_ParseEntity, CBaseEntity *&pEntity, const char *pEntData, IMapEntityFilter *pFilter) { printf("MapEntity_ParseEntity: %s\n", MakeEscapedVersion(pEntData)); // PrintLineBrokenEscapedVersion(pEntData); return DETOUR_STATIC_CALL(MapEntity_ParseEntity)(pEntity, pEntData, pFilter); }
// fix env_gunfire target miss on CleanUpMap() DETOUR_DECL_STATIC2(CDetour_FindInList, bool, const char **,pStrings, const char *,pToFind) { if(strcmp(pToFind,"info_target") == 0) return false; bool ret = DETOUR_STATIC_CALL(CDetour_FindInList)(pStrings,pToFind); return ret; }
DETOUR_DECL_STATIC(const char *, MapEntity_ParseToken, const char *data, char *newToken) { auto result = DETOUR_STATIC_CALL(MapEntity_ParseToken)(data, newToken); int len1 = result - data; int len2 = strlen(newToken); Msg("MapEntity_ParseToken: %d %d %s\n", len1, len2, MakeEscapedVersion(newToken)); return result; }
DETOUR_DECL_STATIC(void, S_Play, const char *pszName, bool flush) { std::lock_guard<std::mutex> lock(m_S_Play); LOGMEM("[%12.7f] BEGIN S_Play\n", Plat_FloatTime()); { SCOPED_INCREMENT(rc_S_Play); DETOUR_STATIC_CALL(S_Play)(pszName, flush); } LOGMEM("[%12.7f] END S_Play\n\n", Plat_FloatTime()); }
DETOUR_DECL_STATIC6(SteamGameServer_InitSafeDetour, bool, uint32, unIP, uint16, usSteamPort, uint16, usGamePort, uint16, usQueryPort, EServerMode, eServerMode, const char *, pchVersionString) { bool bRet = DETOUR_STATIC_CALL(SteamGameServer_InitSafeDetour)(unIP, usSteamPort, usGamePort, usQueryPort, eServerMode, pchVersionString); /* Call to init game interfaces. */ if (g_SteamWorks.pSWGameServer != NULL && g_SteamWorks.pGSHooks != NULL) { g_SteamWorks.pGSHooks->AddHooks(g_SteamWorks.pSWGameServer->GetGameServer()); } return bRet; }
DETOUR_DECL_STATIC0(SteamAPIShutdown, void) { if (g_SteamWorks.pSWGameServer != NULL) { if (g_SteamWorks.pGSHooks != NULL) { g_SteamWorks.pGSHooks->RemoveHooks(g_SteamWorks.pSWGameServer->GetGameServer(), false); } g_SteamWorks.pSWGameServer->Reset(); } DETOUR_STATIC_CALL(SteamAPIShutdown)(); /* We're not a monster. */ }
DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientCommand(edict_t *pEntity) { const char *command = CMD_ARGV(0); // A new command is triggered, reset variable, always. CurrentItemId = 0; // Purpose is to retrieve an item id based on alias name or selected item from menu, // to be used in OnBuy* forwards. if ((ForwardOnBuyAttempt != -1 || ForwardOnBuy != -1) && command && *command) { int itemId = 0; // Handling buy via menu. if (!strcmp(command, "menuselect")) { int slot = atoi(CMD_ARGV(1)); if (slot > 0 && slot < 9) { static const int menuItemsTe[][9] = { /* Menu_Buy */ { 0, 0, 0, 0, 0, 0, CSI_PRIAMMO, CSI_SECAMMO, 0 }, /* Menu_BuyPistol */ { 0, CSI_GLOCK18, CSI_USP, CSI_P228, CSI_DEAGLE, CSI_ELITE, 0, 0, 0 }, /* Menu_BuyRifle */ { 0, CSI_GALIL, CSI_AK47, CSI_SCOUT, CSI_SG552, CSI_AWP, CSI_G3SG1, 0, 0 }, /* Menu_BuyMachineGun */ { 0, CSI_M249, 0, 0, 0, 0, 0, 0, 0 }, /* Menu_BuyShotgun */ { 0, CSI_M3, CSI_XM1014, 0, 0, 0, 0, 0, 0 }, /* Menu_BuySubMachineGun */ { 0, CSI_MAC10, CSI_MP5NAVY, CSI_UMP45, CSI_P90, 0, 0, 0, 0 }, /* Menu_BuyItem */ { 0, CSI_VEST, CSI_VESTHELM, CSI_FLASHBANG, CSI_HEGRENADE, CSI_SMOKEGRENADE, CSI_NVGS, 0, 0 } }; static const int menuItemsCt[][9] = { /* Menu_Buy */ { 0, 0, 0, 0, 0, 0, CSI_PRIAMMO, CSI_SECAMMO, 0 }, /* Menu_BuyPistol */ { 0, CSI_GLOCK18, CSI_USP, CSI_P228, CSI_DEAGLE, CSI_FIVESEVEN, 0, 0, 0 }, /* Menu_BuyRifle */ { 0, CSI_FAMAS, CSI_SCOUT, CSI_M4A1, CSI_AUG, CSI_SG550, CSI_AWP, 0, 0 }, /* Menu_BuyMachineGun */ { 0, CSI_M249, 0, 0, 0, 0, 0, 0, 0 }, /* Menu_BuyShotgun */ { 0, CSI_M3, CSI_XM1014, 0, 0, 0, 0, 0, 0 }, /* Menu_BuySubMachineGun */ { 0, CSI_TMP, CSI_MP5NAVY, CSI_UMP45, CSI_P90, 0, 0, 0, 0 }, /* Menu_BuyItem */ { 0, CSI_VEST, CSI_VESTHELM, CSI_FLASHBANG, CSI_HEGRENADE, CSI_SMOKEGRENADE, CSI_NVGS, CSI_DEFUSER, CSI_SHIELDGUN } }; int menuId = get_pdata<int>(pEdict, MenuOffset); if (menuId >= Menu_Buy && menuId <= Menu_BuyItem) { switch (get_pdata<int>(pEdict, TeamOffset)) { case TEAM_T: itemId = menuItemsTe[menuId - 4][slot]; break; // -4 because array is zero-based and Menu_Buy* constants starts from 4. case TEAM_CT:itemId = menuItemsCt[menuId - 4][slot]; break; } if (itemId) { CurrentItemId = itemId; } } } } else // Handling buy via alias { if (ItemAliasList.retrieve(command, &itemId)) { CurrentItemId = itemId; } } } int client = ENTINDEX(pEdict); if (ForwardInternalCommand != -1 && *UseBotArgs) { const char *args = *BotArgs; if (MF_ExecuteForward(ForwardInternalCommand, static_cast<cell>(client), args) > 0) { return; } } if (ForwardOnBuyAttempt != -1 && CurrentItemId && MF_IsPlayerAlive(client) && MF_ExecuteForward(ForwardOnBuyAttempt, static_cast<cell>(client), static_cast<cell>(CurrentItemId)) > 0) { return; } DETOUR_STATIC_CALL(C_ClientCommand)(pEdict); }
DETOUR_DECL_STATIC2(Cvar_DirectSet, void, struct cvar_s*, var, const char*, value) { CvarInfo* info = nullptr; if (!var || !value // Sanity checks against bogus pointers. || strcmp(var->string, value) == 0 // Make sure old and new values are different to not trigger callbacks. || !g_CvarManager.CacheLookup(var->name, &info)) // No data in cache, nothing to do. { DETOUR_STATIC_CALL(Cvar_DirectSet)(var, value); return; } if (info->bound.hasMin || info->bound.hasMax) // cvar_s doesn't have min/max mechanism, so we check things here. { float fvalue = atof(value); bool oob = false; if (info->bound.hasMin && fvalue < info->bound.minVal) { oob = true; fvalue = info->bound.minVal; } else if (info->bound.hasMax && fvalue > info->bound.maxVal) { oob = true; fvalue = info->bound.maxVal; } if (oob) // Found value out of bound, set new value and block original call. { CVAR_SET_FLOAT(var->name, fvalue); return; } } ke::AString oldValue; // We save old value since it will be likely changed after original function called. if (!info->hooks.empty()) { oldValue = var->string; } DETOUR_STATIC_CALL(Cvar_DirectSet)(var, value); if (!info->binds.empty()) { for (size_t i = 0; i < info->binds.length(); ++i) { CvarBind* bind = info->binds[i]; switch (bind->type) { case CvarBind::CvarType_Int: { *bind->varAddress = atoi(var->string); break; } case CvarBind::CvarType_Float: { float fvalue = atof(var->string); *bind->varAddress = amx_ftoc(fvalue); break; } case CvarBind::CvarType_String: { set_amxstring_simple(bind->varAddress, var->string, bind->varLength); break; } } } } if (!info->hooks.empty()) { for (size_t i = 0; i < info->hooks.length(); ++i) { CvarHook* hook = info->hooks[i]; if (hook->forward->state == AutoForward::FSTATE_OK) // Our callback can be enable/disabled by natives. { executeForwards(hook->forward->id, reinterpret_cast<cvar_t*>(var), oldValue.chars(), var->string); } } } }
DETOUR_DECL_STATIC(void, VProfRecord_StartOrStop) { DETOUR_STATIC_CALL(VProfRecord_StartOrStop)(); DETOUR_STATIC_CALL(VProfRecord_Snapshot)(); }
DETOUR_DECL_STATIC(void, MapEntity_ParseAllEntities, const char *pMapData, IMapEntityFilter *pFilter, bool bActivateEntities) { printf("MapEntity_ParseAllEntities: %s\n", MakeEscapedVersion(pMapData)); DETOUR_STATIC_CALL(MapEntity_ParseAllEntities)(pMapData, pFilter, bActivateEntities); }
DETOUR_DECL_STATIC(string_t, AllocPooledString, const char *pszValue) { ConColorMsg(Color(0xff, 0xff, 0x00, 0xff), "AllocPooledString(%s)\n", pszValue); return DETOUR_STATIC_CALL(AllocPooledString)(pszValue); }
// fix npc blood DETOUR_DECL_STATIC4(CDetour_UTIL_BloodDrips, void, const Vector &, origin, const Vector &, direction, int, color, int, amount) { IPredictionSystem::SuppressHostEvents(NULL); DETOUR_STATIC_CALL(CDetour_UTIL_BloodDrips)(origin, direction, color, amount); }