void *SpawnSpecial::OnSpawnSpecial(ZombieClassType zombieClassType, void *vector, void *qangle)
	{
		L4D_DEBUG_LOG("ZombieManager::SpawnSpecial has been called with class %d", zombieClassType);

		cell_t result = Pl_Continue;
		cell_t overrideZombieClass = zombieClassType;
		if(g_pFwdOnSpawnSpecial)
		{
			L4D_DEBUG_LOG("L4D_OnSpawnSpecial forward has been sent out");
			g_pFwdOnSpawnSpecial->PushCellByRef(&overrideZombieClass);
			g_pFwdOnSpawnSpecial->PushArray(reinterpret_cast<cell_t*>(vector), 3);
			g_pFwdOnSpawnSpecial->PushArray(reinterpret_cast<cell_t*>(qangle), 3);
			g_pFwdOnSpawnSpecial->Execute(&result);
		}

		if(result == Pl_Handled)
		{
			L4D_DEBUG_LOG("ZombieManager::SpawnSpecial will be skipped");
			return NULL;
		}
		else if(result == Pl_Changed)
		{
			L4D_DEBUG_LOG("ZombieManager::SpawnSpecial will be called with class %d", overrideZombieClass);
			return (this->*(GetTrampoline()))(*reinterpret_cast<ZombieClassType*>(&overrideZombieClass), vector, qangle);
		}
		else
		{
			return (this->*(GetTrampoline()))(zombieClassType, vector, qangle);
		}
	}
	void *GetScriptValueString::OnGetScriptValueString(const char *key, const char *defaultValue, char *retValue, int sizeof_retValue)
	{
		L4D_DEBUG_LOG("CDirector::GetScriptValue(%s,%s,%s,%d) is about to be called", key, defaultValue, retValue, sizeof_retValue);
		
		cell_t result = Pl_Continue;

		(this->*(GetTrampoline()))(key, defaultValue, retValue, sizeof_retValue);

		L4D_DEBUG_LOG("CDirector::GetScriptValue() passed string result: %s", retValue);
		
		if(g_pFwdOnGetScriptValueString)
		{
			//L4D_DEBUG_LOG("L4D_OnGetScriptValueString() forward has been sent out");
			g_pFwdOnGetScriptValueString->PushString(key);
			defaultValue == NULL ? g_pFwdOnGetScriptValueString->PushString("") : g_pFwdOnGetScriptValueString->PushString(key);
			g_pFwdOnGetScriptValueString->PushStringEx(retValue, sizeof_retValue, SM_PARAM_STRING_COPY, SM_PARAM_COPYBACK);
			g_pFwdOnGetScriptValueString->Execute(&result);
		}

		if(result == Pl_Handled)
		{
			L4D_DEBUG_LOG("CDirector::OnGetScriptValueString will be skipped");
			return NULL;
		}
		else
		{
			return (this->*(GetTrampoline()))(key, defaultValue, retValue, sizeof_retValue);
		}
	}
	void ClearTeamScores::OnClearTeamScores(CLEAR_TEAM_SCORES_ARG)
	{
		bool b = newCampaign;

		L4D_DEBUG_LOG("CTerrorGameRules::ClearTeamScores has been called, bool=%d", b);

		cell_t result = Pl_Continue;
		if(g_pFwdOnClearTeamScores)
		{
			L4D_DEBUG_LOG("L4D_OnClearTeamScores forward has been sent out");
			g_pFwdOnClearTeamScores->PushCell(static_cast<cell_t>(b));
			g_pFwdOnClearTeamScores->Execute(&result);
		}

		if(result == Pl_Handled)
		{
			L4D_DEBUG_LOG("CTerrorGameRules::ClearTeamScores will be skipped");
			return;
		}
		else
		{
			(this->*(GetTrampoline()))(b);
			return;
		}
	}
	void ChangeFinaleStage::OnChangeFinaleStage(int finaleType, const char *key)
	{
		cell_t result = Pl_Continue;

		if(g_pFwdOnChangeFinaleStage)
		{
			L4D_DEBUG_LOG("L4D2_OnChangeFinaleStage(%d, [%s]) forward has been sent out", finaleType, key);
			g_pFwdOnChangeFinaleStage->PushCellByRef(&finaleType);

			if (key != NULL)
			{
				g_pFwdOnChangeFinaleStage->PushString(key);
			}
			else
			{
				g_pFwdOnChangeFinaleStage->PushString("");
			}
			g_pFwdOnChangeFinaleStage->Execute(&result);
		}

		if(result == Pl_Handled)
		{
			L4D_DEBUG_LOG("L4D2_OnChangeFinaleStage() will be skipped");
			return;
		}
		else
		{
			(this->*(GetTrampoline()))(finaleType, key);
			return;
		}
	}
	void EndVersusModeRound::OnEndVersusModeRound(bool countSurvivors)
	{
		L4D_DEBUG_LOG("CDirectorVersusMode::EndVersusModeRound(%s) has been called", countSurvivors ? "true" : "false");
		
		if(g_bRoundEnd) return;
		g_bRoundEnd = true;
		
		cell_t result = Pl_Continue;
		if(g_pFwdOnEndVersusModeRound)
		{
			L4D_DEBUG_LOG("L4D2_OnEndVersusModeRound forward has been sent out");
			g_pFwdOnEndVersusModeRound->PushCell(static_cast<bool>(countSurvivors));
			g_pFwdOnEndVersusModeRound->Execute(&result);
		}
		
		if(result == Pl_Handled) return;
		
		(this->*(GetTrampoline()))(countSurvivors);

		if(g_pFwdOnEndVersusModeRound_Post)
		{
			L4D_DEBUG_LOG("L4D2_OnEndVersusModeRound_Post forward has been sent out");
			g_pFwdOnEndVersusModeRound_Post->Execute(NULL);
		}
	   
		return;
	}
void PlayerSlots::Unpatch()
{
    L4D_DEBUG_LOG("PlayersSlots - Unpatching ...");

    //jl around the string "Human player limit reached (%d/%d)"
    // Windows only

#if defined PLATFORM_WINDOWS
    if(humanLimitSig)
    {
        ApplyPatch(humanLimitSig, /*offset*/0, &humanLimitRestore, /*restore*/NULL);
        L4D_DEBUG_LOG("PlayerSlots -- 'HumanPlayerLimitReached' jl(e) restored");
    }
#endif

    //jz around the string "#Valve_Reject_Server_Full"

    if(lobbyConnectSig)
    {
        ApplyPatch(lobbyConnectSig, /*offset*/0, &lobbyConnectRestore, /*restore*/NULL);
        L4D_DEBUG_LOG("PlayerSlots -- 'ConnectClientLobbyCheck' restored");
    }

    PlayerSlots::UnpatchSlotCheckOnly();
    PlayerSlots::UnpatchGetMaxHumanPlayers();
    //PlayerSlots::UnpatchGetTotalNumPlayersSupported();
}
/**
 * @brief Called when a client is authorized.
 *
 * @param client		Index of the client.
 * @param authstring	His SteamID.
 */	
void Left4Downtown::OnClientAuthorized(int client, const char *authstring)
{
	/* 
		Credits to Scott "DS" Ehlert from the SourceMod Dev Team for providing me with
		this super-easy method of selective event broadcasting. If it wasn't for him,
		I'd be stuck with a bunch of nasty code -- i.e. my initial idea of a NET_SendPacket
		vcall(bitbuffers, serializing events, casting IPs to netadr_t etc.)
		/blog
	*/
	
	if (!g_AddonsEclipse.GetBool())
	{
		L4D_DEBUG_LOG("l4d2_addons_eclipse set to 0, skipping function");
		return;
	}
	
	IGamePlayer *pPlayer = playerhelpers->GetGamePlayer(client);
	if (pPlayer->IsFakeClient())
	{
		L4D_DEBUG_LOG("Fake client %d connected, ignoring...", client);
		return;
	}
	
	cell_t result = Pl_Continue;
	if (g_pFwdOnAddonsEclipseUpdate)
	{
		g_pFwdOnAddonsEclipseUpdate->PushCell(client);
		g_pFwdOnAddonsEclipseUpdate->Execute(&result);
		
		if(result == Pl_Handled)
		{
			L4D_DEBUG_LOG("L4D2_OnAddonsEclipseUpdate(%d) will be skipped", client);
			return;
		}
		L4D_DEBUG_LOG("L4D2_OnAddonsEclipseUpdate(%d) has been sent out...", client);
	}
	
	// Getting the client event listener
	INetChannel *pNetChan = static_cast<INetChannel *>(engine->GetPlayerNetInfo(client));
	IClient *pClient = static_cast<IClient *>(pNetChan->GetMsgHandler());
	unsigned char *pBaseClient = reinterpret_cast<unsigned char *>(pClient) - 4;
	IGameEventListener2 *pClientListener = reinterpret_cast<IGameEventListener2 *>(pBaseClient);

	// Firing our event; it will tell the client to unload his addons
	IGameEvent *pEvent = gameeventmanager->CreateEvent("server_spawn");
	if (pEvent)
	{
		pEvent->SetString("address", "159.253.143.194:0");
        pEvent->SetString("mapname", STRING(gpGlobals->mapname));
		pClientListener->FireGameEvent(pEvent);
		
		L4D_DEBUG_LOG("Fired event for client %d", client);
	}

	// When done with event, must destroy it manually
	gameeventmanager->FreeEvent(pEvent);  
}
void PlayerSlots::OnMaxSlotsChanged(int max_slots)
{
    if(MaxClients == -1)
    {
        L4D_DEBUG_LOG("MaxClients -1! Disallowing slots patch");
        UpdateMaxSlots(-1);
        return;
    }

    /* no change */

    if(MaxSlots == max_slots)
        return;

    // disable

    if(max_slots < 0)
    {
        L4D_DEBUG_LOG("Disabling slots patch");
        PlayerSlots::Unpatch();
        UpdateMaxSlots(-1);
        return;
    }

#if RESTRICT_MAX_PLAYERS_BY_COMMAND_LINE
    /* dont allow slots to exceed +-maxplayers */

    int max_players = PlayerSlots::MaxPlayers;

    if(max_players >= 0 && max_slots > max_players)
    {
        L4D_DEBUG_LOG("Attempt to set slots higher than set command line value (%d max: %d)", max_slots, max_players);
        UpdateMaxSlots(MaxSlots);
        return;
    }
#endif

    // cant allow this obviously

    if(max_slots > MaxClients)
    {
        L4D_DEBUG_LOG("Attempt to set slots higher than MaxClients (%d max: %d)", max_slots, MaxClients);
        UpdateMaxSlots(MaxSlots);
        return;
    }

    //enable

    UpdateMaxSlots(max_slots);

    L4D_DEBUG_LOG("Enabling slots patch");
    PlayerSlots::Patch();
    PlayerSlots::PatchSlotCheckOnly();
    PlayerSlots::PatchGetMaxHumanPlayers();
    //PlayerSlots::PatchGetTotalNumPlayersSupported();
}
void AddonsDisabler::Unpatch()
{
    L4D_DEBUG_LOG("AddonsDisabler - Unpatching ...");

    if (vanillaModeSig)
    {
        ApplyPatch(vanillaModeSig, /*offset*/4, &vanillaModeSigRestore, /*restore*/NULL);
        L4D_DEBUG_LOG("AddonsDisabler -- 'VanillaModeOffset' restored");
    }
}
/*
	unregister all code patches, deleting every one of them
*/
void PatchManager::UnregisterAll()
{
	L4D_DEBUG_LOG("PatchManager::UnregisterAll()");

	for(PatchList::iterator iter = patchList.begin(); iter != patchList.end(); ++iter)
	{
		L4D_DEBUG_LOG("PatchManager deleted a patch");

		ICodePatch *patch = *iter;
		delete patch;
	}

	patchList.clear();
}
	/**
	 * @brief Called when the server is activated.
	 */
void Left4Downtown::OnServerActivated(int max_clients)
{
	L4D_DEBUG_LOG("Server activated with %d maxclients", max_clients);

	static bool firstTime = true;
	if(!firstTime)
	{
		L4D_DEBUG_LOG("Server activated with %d maxclients (doing nothing)", max_clients);
		return;
	}
	firstTime = false;

	PlayerSlots::MaxClients = max_clients;
	
	ConVarPublic *maxPlayersCvar = (ConVarPublic*)&g_MaxPlayers;
	maxPlayersCvar->m_bHasMax = true;
	maxPlayersCvar->m_fMaxVal = (float) max_clients;
	maxPlayersCvar->m_bHasMin  = true;
	maxPlayersCvar->m_fMinVal = (float) -1;

#if RESTRICT_MAX_PLAYERS_BY_COMMAND_LINE
	int max_players = PlayerSlots::MaxPlayers;

	if(max_players >= 0)
	{
		//dont allow it to be larger than max_clients
		max_players = max_players <= max_clients ? max_players : max_clients;

		maxPlayersCvar->m_fMaxVal = (float) max_players; 

		//if GSPs set maxplayers to the non-default value
		//we will patch the code then by default even if l4d_maxplayers is never set
		//otherwise default is -1 disabled
		if(DEFAULT_MAX_PLAYERS != max_players)
		{
			//by putting only +-maxplayers and never l4d_maxplayers, we set maxplayers +-maxplayers value
			//by specifiying l4d_maxplayers, we override the +-maxplayers value as long as its <= +-maxplayers
			g_MaxPlayers.SetValue(max_players);

			static char defaultPlayers[5];
			snprintf(defaultPlayers, sizeof(defaultPlayers), "%d", max_players);
			maxPlayersCvar->m_pszDefaultValue = defaultPlayers;
		}
	}
#endif
}
Exemple #12
0
cell_t L4D_SetSurvivorHealthBonus(IPluginContext *pContext, const cell_t *params)
{
	CBaseEntity *pPlayer;
	ENTINDEX_TO_CBASEENTITY(params[1], pPlayer);
	
	static int offset = 0;
	
	if(offset == 0)
	{
		if (!g_pGameConf->GetOffset("SurvivorHealthBonus", &offset) || !offset)
		{
			return pContext->ThrowNativeError("Could not read 'SurvivorHealthBonus' offset from GameConf");
		}
	}

	int healthbonus = params[2];
	*reinterpret_cast<int*>(reinterpret_cast<uint8_t*>(pPlayer) + offset) = healthbonus;

	L4D_DEBUG_LOG("SetSurvivorHealthBonus for %d -> %d", params[1], healthbonus);
	
	if (params[3] == 1)
	{
	
		static ICallWrapper *pWrapper = NULL;

		// Director::RestartScenario()
		if (!pWrapper)
		{
			REGISTER_NATIVE_ADDR("RecomputeTeamScores", 
				pWrapper = g_pBinTools->CreateCall(addr, CallConv_ThisCall, NULL, NULL, 0));
		}
		
		void *gamerules = *g_pGameRules;
		unsigned char vstk[sizeof(void *)];
		unsigned char *vptr = vstk;

		*(void **)vptr = gamerules;
		
		pWrapper->Execute(vstk, NULL);
		L4D_DEBUG_LOG("SetSurvivorHealthBonus Called RecomputeTeamScores");
	}
	
	
	
	return 1;
}
void PlayerSlots::UnpatchGetMaxHumanPlayers()
{
    if(getMaxHumanPlayersSig)
    {
        ApplyPatch(getMaxHumanPlayersSig, /*offset*/0, &getMaxHumanPlayersRestore, /*restore*/NULL);
        L4D_DEBUG_LOG("PlayerSlots -- 'GetMaxHumanPlayers' restored");
    }
}
void OnAddonsEclipseChanged( IConVar *var, const char *pOldValue, float flOldValue )
{
    if (AddonsDisabler::AddonsEclipse == g_AddonsEclipse.GetInt())
        return;

    AddonsDisabler::AddonsEclipse = g_AddonsEclipse.GetInt();
    L4D_DEBUG_LOG("CVAR l4d2_addons_eclipse changed to %i...", AddonsDisabler::AddonsEclipse);
    
    if (AddonsDisabler::AddonsEclipse > -1)
    {
        L4D_DEBUG_LOG("Enabling AddonsDisabler patch");
        AddonsDisabler::Patch();
    }
    else
    {
        L4D_DEBUG_LOG("Disabling AddonsDisabler patch");
        AddonsDisabler::Unpatch();
    }
}
void PlayerSlots::UnpatchSlotCheckOnly()
{
    //cmp around the string "#Valve_Reject_Server_Full"

    if(lobbyConnectSig && serverFullOffset != -1)
    {
        ApplyPatch(lobbyConnectSig, serverFullOffset, &serverFullRestore, /*restore*/NULL);
        L4D_DEBUG_LOG("PlayerSlots -- 'ValveRejectServerFullFirst' restored");
    }
}
/*
	Patch CTerrorGameRules::GetMaxHumanPlayers(void) to always return our own value

	This will cause server browsers to display our own 'max players' value (Linux only)

	On Windows overriding it does nothing at first..
	  but actually it breaks scavenge mode which is stuck in a 'scavenge versus' type mode
	  so it should NEVER BE PATCHED FOR WINDOWS EVER

	On Linux just overriding ServerPlayerCounts isn't enough (it only fixes 'status' command)
	  but overwriting GetMaxHumanPlayers works great
*/
void PlayerSlots::PatchGetMaxHumanPlayers()
{
#if !defined PLATFORM_WINDOWS

    bool firstTime = (getMaxHumanPlayersSig == NULL);

    if(firstTime)
    {
        if (!g_pGameConf->GetMemSig("GetMaxHumanPlayers", &getMaxHumanPlayersSig) || !getMaxHumanPlayersSig)
        {
            g_pSM->LogError(myself, "PlayerSlots -- Could not find 'GetMaxHumanPlayers' signature");
            return;
        }
    }

    /*
    Normally CTerrorGameRules::GetMaxHumanRules(void)
    	returns CTerrorGameRules::IsVersusMode() ? 8 : 4
    we just want it to return our own PLAYER_SLOTS_MAX always though
    */

    /*
    The trick here is just to patch the function to:

    	mov eax, PLAYER_SLOTS_MAX
    	retn

    Now it will always return our value instead of 4 or 8
    */

    patch_t getMaxHumanPlayersPatch;
    getMaxHumanPlayersPatch.bytes = OP_MOV_EAX_IMM32_SIZE + OP_RETN_SIZE;

    // mov eax, PLAYER_SLOTS_MAX
    getMaxHumanPlayersPatch.patch[0] = OP_MOV_EAX_IMM32;
    *(uint32_t*)(getMaxHumanPlayersPatch.patch+sizeof(uint8_t)) = (uint32_t)PLAYER_SLOTS_MAX;

    // retn
    getMaxHumanPlayersPatch.patch[OP_MOV_EAX_IMM32_SIZE] = OP_RETN;

    if(firstTime)
    {
        ApplyPatch(getMaxHumanPlayersSig, /*offset*/0, &getMaxHumanPlayersPatch, &getMaxHumanPlayersRestore);
    }
    else
    {
        ApplyPatch(getMaxHumanPlayersSig, /*offset*/0, &getMaxHumanPlayersPatch, /*restore*/NULL);
    }

    L4D_DEBUG_LOG("PlayerSlots -- 'GetMaxHumanPlayers' patched to MOV eax, %d; retn", PLAYER_SLOTS_MAX);

#endif
}
	void *FirstSurvivorLeftSafeArea::OnFirstSurvivorLeftSafeArea(CTerrorPlayer *p)
	{
		L4D_DEBUG_LOG("CDirector::OnFirstSurvivorLeftSafeArea has been called");

		cell_t result = Pl_Continue;
		if(g_pFwdOnFirstSurvivorLeftSafeArea)
		{
			int client;
			if(p == NULL)
			{
				/*
				quite possible the survivor is NULL
				e.g. CDirectorScavengeMode::ShouldUpdateTeamReadiness
				calls OnFirstSurvivorLeftSafeArea(NULL)
				*/
				client = 0;
			}
			else
			{
				edict_t *pEntity = gameents->BaseEntityToEdict(reinterpret_cast<CBaseEntity*>(p));
				client = IndexOfEdict(pEntity);
			}

			L4D_DEBUG_LOG("L4D_OnFirstSurvivorLeftSafeArea(%d) forward has been sent out", client);
			g_pFwdOnFirstSurvivorLeftSafeArea->PushCell(client);
			g_pFwdOnFirstSurvivorLeftSafeArea->Execute(&result);
		}

		if(result == Pl_Handled)
		{
			L4D_DEBUG_LOG("CDirector::OnFirstSurvivorLeftSafeArea will be skipped");
			return NULL;
		}
		else
		{
			g_bRoundEnd = false;
			return (this->*(GetTrampoline()))(p);
		}
	}
	void SpawnITMob::OnSpawnITMob(int amount)
	{
		L4D_DEBUG_LOG("ZombieManager::SpawnITMob(%d) has been called", amount);

		cell_t result = Pl_Continue;
		if(g_pFwdOnSpawnITMob)
		{
			L4D_DEBUG_LOG("L4D_OnSpawnITMob() forward has been sent out");
			g_pFwdOnSpawnITMob->PushCellByRef(&amount);
			g_pFwdOnSpawnITMob->Execute(&result);
		}

		if(result == Pl_Handled)
		{
			L4D_DEBUG_LOG("ZombieManager::SpawnITMob will be skipped");
			return;
		}
		else
		{
			(this->*(GetTrampoline()))(amount);
			return;
		}
	}
Exemple #19
0
	void *SpawnTank::OnSpawnTank(void *vector, void *qangle)
	{
		L4D_DEBUG_LOG("ZombieManager::SpawnTank has been called");

		cell_t result = Pl_Continue;
		if(g_pFwdOnSpawnTank)
		{
			L4D_DEBUG_LOG("L4D_OnTankSpawn forward has been sent out");
			g_pFwdOnSpawnTank->PushArray(reinterpret_cast<cell_t*>(vector), 3);
			g_pFwdOnSpawnTank->PushArray(reinterpret_cast<cell_t*>(qangle), 3);
			g_pFwdOnSpawnTank->Execute(&result);
		}

		if(result == Pl_Handled)
		{
			L4D_DEBUG_LOG("ZombieManager::SpawnTank will be skipped");
			return NULL;
		}
		else
		{
			return (this->*(GetTrampoline()))(vector, qangle);
		}
	}
	void GameRulesNetworkChanged::OnGameRulesNetworkChanged()
	{		
		L4D_DEBUG_LOG("CTerrorGameRules::GameRulesNetworkChanged has been called");
		
		cell_t result = Pl_Continue;
		if(g_pFwdOnGameRulesNetworkChanged)
		{
			L4D_DEBUG_LOG("L4D_OnGameRulesNetworkChanged forward has been sent out");
			g_pFwdOnGameRulesNetworkChanged->Execute(&result);
		}

		if(result == Pl_Handled)
		{
			L4D_DEBUG_LOG("Director::GameRulesNetworkChanged will be skipped");
			return;
		}
		else
		{		
			L4D_DEBUG_LOG("CTerrorGameRules::GameRulesNetworkChanged will be invoked");

			return (this->*(GetTrampoline()))();
		}
	}
	void RecomputeTeamScores::OnRecomputeTeamScores()
	{		
		L4D_DEBUG_LOG("CTerrorGameRules::RecomputeTeamScores has been called");
		/*
		
		//unsigned char *calloffset = *(unsigned char **)writeaddr;
		float maxflow;
		
		//-0x208694(%ebx),%ecx
		
		__asm__("mov -0xf0(%%ebx),%%eax\n\t"
				"mov (%%eax),%%eax\n\t"
				"mov 0x5a8(%%eax),%0" :"=r"(maxflow));
		//__asm__("mov -0x227040(%%ebx), %0;" :"=r"(maxflow));
		L4D_DEBUG_LOG("L4D_OnRecomputeTeamScores MaxFlow -> %.2f", maxflow);
		*/
		
		
		cell_t result = Pl_Continue;
		if(g_pFwdOnRecomputeTeamScores)
		{
			L4D_DEBUG_LOG("L4D_OnRecomputeTeamScores forward has been sent out");
			g_pFwdOnRecomputeTeamScores->Execute(&result);
		}

		if(result == Pl_Handled)
		{
			L4D_DEBUG_LOG("Director::RecomputeTeamScores will be skipped");
			return;
		}
		else
		{		
			L4D_DEBUG_LOG("CTerrorGameRules::RecomputeTeamScores will be invoked");

			return (this->*(GetTrampoline()))();
		}
	}
	void GetMissionVersusBossSpawning::OnGetMissionVersusBossSpawning(float &spawn_pos_min, float &spawn_pos_max, float &tank_chance, float &witch_chance)
	{
		L4D_DEBUG_LOG("CDirectorVersusMode::GetMissionVersusBossSpawning has been called, %f %f %f %f", spawn_pos_min, spawn_pos_max, tank_chance, witch_chance);
		
		float ov_spawn_pos_min = spawn_pos_min;
	    float ov_spawn_pos_max = spawn_pos_max;
	    float ov_tank_chance = tank_chance;
	    float ov_witch_chance = witch_chance;

		cell_t result = Pl_Continue;
		if(g_pFwdOnGetMissionVersusBossSpawning)
		{
			L4D_DEBUG_LOG("L4D_OnGetMissionVersusBossSpawning forward has been sent out");
			g_pFwdOnGetMissionVersusBossSpawning->PushFloatByRef(&ov_spawn_pos_min);
			g_pFwdOnGetMissionVersusBossSpawning->PushFloatByRef(&ov_spawn_pos_max);
			g_pFwdOnGetMissionVersusBossSpawning->PushFloatByRef(&ov_tank_chance);
			g_pFwdOnGetMissionVersusBossSpawning->PushFloatByRef(&ov_witch_chance);
			g_pFwdOnGetMissionVersusBossSpawning->Execute(&result);
		}
		switch(result)
		{
			case Pl_Changed:
				spawn_pos_min = ov_spawn_pos_min;
				spawn_pos_max = ov_spawn_pos_max;
				tank_chance = ov_tank_chance;
				witch_chance = ov_witch_chance;
			break;
			case Pl_Handled:
			break;
			case Pl_Continue:
			default:
			(this->*(GetTrampoline()))(spawn_pos_min, spawn_pos_max, tank_chance, witch_chance);
		}

	   
		return;
	}
    void *TerrorWeaponHit::OnTerrorWeaponHit(CGameTrace *trace/* a1 */, void *vector/* a2 */, bool userCall/* a3 */)
    {
        L4D_DEBUG_LOG("CTerrorWeapon::OnHit() has been called");
        cell_t result = Pl_Continue;

        int hEntity = *(int *)((unsigned char*)trace + 76);    // did the m2 trace hit anyone(i.e. an entity)
        /*  
            deadstop check: see if it's going to be versus_shove_hunter_fov_pouncing(true) or versus_shove_hunter_fov(false)
            often returns 0 when it shouldn't  - either this shit is unreliable, or the game is buggy as f**k
            probably both
        */
        int isDeadstop = *(int *)((unsigned char *)hEntity + 16024);
        int weapon = IndexOfEdict(gameents->BaseEntityToEdict(reinterpret_cast<CBaseEntity *>(this)));
        int entity = IndexOfEdict(gameents->BaseEntityToEdict(reinterpret_cast<CBaseEntity *>(hEntity)));
        CBaseHandle &weaponOwner = *(CBaseHandle *)((unsigned char *)this + 5108);  // get the weapon's owner and thus check its validity(shoves are a secondary attack of anything you're able to hold, even pills and cola)
        int client = !weaponOwner.IsValid() ? -1 : weaponOwner.GetEntryIndex();   // very simplistic and unreliable check, but meh
        /* there's another check being performed here to see if the current gamemode allows bashing... we don't need it */
        if (g_pFwdOnTerrorWeaponHit && client && entity && userCall)
        {
            g_pFwdOnTerrorWeaponHit->PushCell(client); // who shoved
            g_pFwdOnTerrorWeaponHit->PushCell(entity); // who got shoved
            g_pFwdOnTerrorWeaponHit->PushCell(weapon); // weapon that's been held while shoving
            g_pFwdOnTerrorWeaponHit->PushArray(reinterpret_cast<cell_t *>(vector), 3); // shove angles
            g_pFwdOnTerrorWeaponHit->PushCell(isDeadstop ? true : false); // reliable for high pounces only
            g_pFwdOnTerrorWeaponHit->Execute(&result);
        }

        if(result == Pl_Handled)
        {
            L4D_DEBUG_LOG("CTerrorWeapon::OnHit() will be skipped");
            return NULL;
        }
        else
        {
            return (this->*(GetTrampoline()))(trace, vector, userCall);
        }
    }
void AddonsDisabler::Patch()
{
    L4D_DEBUG_LOG("AddonsDisabler - Patching ...");
    
    bool firstTime = (vanillaModeSig == NULL);
    if (firstTime)
    {
        if (!g_pGameConf->GetMemSig("VanillaModeOffset", &vanillaModeSig) || !vanillaModeSig) 
        { 
            g_pSM->LogError(myself, "AddonsDisabler -- Could not find 'VanillaModeOffset' signature");
            return;
        } 
    }
    patch_t vanillaModePatch;
    vanillaModePatch.bytes = 3;

    // mov esi+19h -> NOP
    vanillaModePatch.patch[0] = 0x0f;
    vanillaModePatch.patch[1] = 0x1f;
    vanillaModePatch.patch[2] = 0x00;

    ApplyPatch(vanillaModeSig, /*offset*/4, &vanillaModePatch, /*restore*/firstTime ? &vanillaModeSigRestore : NULL);
    L4D_DEBUG_LOG("AddonsDisabler -- 'VanillaModeOffset' patched to NOP");
}
	int __thiscall RevivedByDefib::OnRevived(CBaseEntity *pInitiator, void *deathModel)
	{
		CBaseEntity* pTarget = reinterpret_cast<CBaseEntity*>(this);
		cell_t client = gamehelpers->EntityToBCompatRef(pTarget);

		IGamePlayer* pGamePlayer = playerhelpers->GetGamePlayer(client);
		if(pGamePlayer) {
			IPlayerInfo* pInfo = pGamePlayer->GetPlayerInfo();
			if(pInfo) {
				r_nowAlive(pInfo->GetAbsOrigin(), g_dead_players, arraysize(g_dead_players));
				L4D_DEBUG_LOG("RevivedByDefib called for: %s", pInfo->GetName());
			}
		}


		return (this->*(GetTrampoline()))(pInitiator, deathModel);
	}
Exemple #26
0
cell_t L4D_GetSurvivorHealthBonus(IPluginContext *pContext, const cell_t *params)
{
	CBaseEntity *pPlayer;
	ENTINDEX_TO_CBASEENTITY(params[1], pPlayer);
	
	static int offset = 0;
	
	if(offset == 0)
	{
		if (!g_pGameConf->GetOffset("SurvivorHealthBonus", &offset) || !offset)
		{
			return pContext->ThrowNativeError("Could not read 'SurvivorHealthBonus' offset from GameConf");
		}
	}
	
	int healthbonus = *reinterpret_cast<int*>(reinterpret_cast<uint8_t*>(pPlayer) + offset);
	L4D_DEBUG_LOG("GetSurvivorHealthBonus for %d -> %d", params[1], healthbonus);
	
	return healthbonus;
}
    void CBaseServer::OnFillServerInfo(int SVC_ServerInfo)
    {
        cell_t result = Pl_Continue;
    
        if (g_pFwdAddonsDisabler && AddonsDisabler::AddonsEclipse > 0 && vanillaModeSig)
        {
            int m_nPlayerSlot = *(int *)((unsigned char *)SVC_ServerInfo + 48);
            IClient *pClient = g_pServer->GetClient(m_nPlayerSlot);

            L4D_DEBUG_LOG("ADDONS DISABLER: Eligible client '%s' connected[%s]", pClient->GetClientName(), pClient->GetNetworkIDString());
            
            g_pFwdAddonsDisabler->PushString(pClient->GetNetworkIDString());
            g_pFwdAddonsDisabler->Execute(&result);
            
            /* uint8_t != unsigned char in terms of type */
            uint8_t disableAddons = result == Pl_Handled ? 0 : 1;
            memset((unsigned char *)SVC_ServerInfo + 25, disableAddons, sizeof(uint8_t));
        }

        (this->*(GetTrampoline()))(SVC_ServerInfo);
    }
Exemple #28
0
void InitializeValveGlobals()
{
	char *addr = NULL;
#ifdef PLATFORM_WINDOWS
	int offset;

	/* g_pGameRules */
	if (!g_pGameConfSDKTools->GetMemSig("CreateGameRulesObject", (void **)&addr) || !addr)
	{
		return;
	}
	if (!g_pGameConfSDKTools->GetOffset("g_pGameRules", &offset) || !offset)
	{
		return;
	}
	g_pGameRules = *reinterpret_cast<void ***>(addr + offset);

	/* g_pDirector */
	const char *directorConfKey = "DirectorMusicBanks_OnRoundStart";
	if (!g_pGameConf->GetMemSig(directorConfKey, (void **)&addr) || !addr)
	{
		return;
	}
	if (!g_pGameConf->GetOffset("TheDirector", &offset) || !offset)
	{
		return;
	}
	g_pDirector = *reinterpret_cast<CDirector ***>(addr + offset);
#elif defined PLATFORM_LINUX

	/* g_pGameRules */
	if (!g_pGameConfSDKTools->GetMemSig("g_pGameRules", (void **)&addr) || !addr)
	{
	    L4D_DEBUG_LOG("Couldn't find GameRules instance!");
		return;
	}
	g_pGameRules = reinterpret_cast<void **>(addr);

	/* g_pDirector */
	if (!g_pGameConf->GetMemSig("TheDirector", (void **)&addr) || !addr)
	{
	    L4D_DEBUG_LOG("Couldn't find CDirector instance!");
		return;
	}
	g_pDirector = reinterpret_cast<CDirector **>(addr);
#endif
	
	if(!g_pGameConf->GetAddress("ZombieManager", (void **)&addr))
	{
		L4D_DEBUG_LOG("TheZombieManager address not found.");
		return;
	}
	g_pZombieManager = addr;
	L4D_DEBUG_LOG("TheZombieManager found at: %p", g_pZombieManager);
	
	/* g_pWeaponInfoDatabase */
	if(!g_pGameConf->GetAddress("WeaponInfoDatabase", (void **)&addr))
	{
		L4D_DEBUG_LOG("WeaponInfoDatabase address not found.");
		return;
	}
	g_pWeaponInfoDatabase = reinterpret_cast<WeaponDatabase *>(addr);
	L4D_DEBUG_LOG("WeaponInfoDatabase found at: %p", g_pWeaponInfoDatabase);
	
	/* g_pMeleeWeaponInfoStore */
	if(!g_pGameConf->GetAddress("MeleeWeaponInfoStore", (void **)&addr))
	{
		L4D_DEBUG_LOG("MeleeWeaponInfoStore address not found.");
		return;
	}
	g_pMeleeWeaponInfoStore = reinterpret_cast<CMeleeWeaponInfoStore *>(addr);
	L4D_DEBUG_LOG("MeleeWeaponInfo Store: %p ", g_pMeleeWeaponInfoStore);
	L4D_DEBUG_LOG("MeleeWeaponInfo Store: %s ", g_pMeleeWeaponInfoStore->Name());
}
void L4D2Tools::SDK_OnAllLoaded()
{
	SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
	SM_GET_LATE_IFACE(SDKTOOLS, g_pSDKTools);

	if (!g_pBinTools || !g_pSDKTools)
	{
		L4D_DEBUG_LOG("Failed to load bintools or failed to load sdktools");
		return;
	}

	IServer *server = g_pSDKTools->GetIServer();
	L4D_DEBUG_LOG("Address of IServer is %p", server);
	//reading out server->GetName() we consistently seem to get (the same?) 
	//garbage characters. this is possibly causing a crash on windows servers
	//when a player connects. so lets not read the server name :(
	//L4D_DEBUG_LOG("Server name is %s", server->GetName());
	g_pServer = server;

	InitializeValveGlobals();
	/*
	detour the witch/spawn spawns
	*/
	//automatically will unregister/cleanup themselves when the ext is unloaded

	g_PatchManager.Register(new AutoPatch<Detours::SpawnSpecial>());
	g_PatchManager.Register(new AutoPatch<Detours::SpawnTank>());
	g_PatchManager.Register(new AutoPatch<Detours::SpawnWitch>());
	g_PatchManager.Register(new AutoPatch<Detours::SpawnWitchBride>());
	g_PatchManager.Register(new AutoPatch<Detours::FirstSurvivorLeftSafeArea>());
	g_PatchManager.Register(new AutoPatch<Detours::GetScriptValueInt>());
	g_PatchManager.Register(new AutoPatch<Detours::GetScriptValueFloat>());
	g_PatchManager.Register(new AutoPatch<Detours::GetScriptValueString>());
	g_PatchManager.Register(new AutoPatch<Detours::TryOfferingTankBot>());
	g_PatchManager.Register(new AutoPatch<Detours::MobRushStart>());
	g_PatchManager.Register(new AutoPatch<Detours::SpawnITMob>());
	g_PatchManager.Register(new AutoPatch<Detours::SpawnMob>());
	g_PatchManager.Register(new AutoPatch<Detours::GetCrouchTopSpeed>());
	g_PatchManager.Register(new AutoPatch<Detours::GetRunTopSpeed>());
	g_PatchManager.Register(new AutoPatch<Detours::GetWalkTopSpeed>());
	g_PatchManager.Register(new AutoPatch<Detours::HasConfigurableDifficulty>());
	g_PatchManager.Register(new AutoPatch<Detours::CThrowActivate>());
	g_PatchManager.Register(new AutoPatch<Detours::StartMeleeSwing>());
	g_PatchManager.Register(new AutoPatch<Detours::SendInRescueVehicle>());
	g_PatchManager.Register(new AutoPatch<Detours::ChangeFinaleStage>());
	g_PatchManager.Register(new AutoPatch<Detours::SelectSequence>());//for SelectTankAttack
	g_PatchManager.Register(new AutoPatch<Detours::Revived>());
	g_PatchManager.Register(new AutoPatch<Detours::PlayerStagger>());
	g_PatchManager.Register(new AutoPatch<Detours::HealBegin>());
	g_PatchManager.Register(new AutoPatch<Detours::UseHealingItems>());
	g_PatchManager.Register(new AutoPatch<Detours::FindScavengeItem>());
	g_PatchManager.Register(new AutoPatch<Detours::WitchAttackUpdate>());
	g_PatchManager.Register(new AutoPatch<Detours::WitchKillIncapVictim>());
	g_PatchManager.Register(new AutoPatch<Detours::WitchRetreat>());
	g_PatchManager.Register(new AutoPatch<Detours::InfectedAlertUpdate>());
	g_PatchManager.Register(new AutoPatch<Detours::InfectedAttackUpdate>());
	g_PatchManager.Register(new AutoPatch<Detours::SmokerAttackUpdate>());
	g_PatchManager.Register(new AutoPatch<Detours::BoomerAttackUpdate>());
	g_PatchManager.Register(new AutoPatch<Detours::HunterAttackUpdate>());
	g_PatchManager.Register(new AutoPatch<Detours::SpitterAttackUpdate>());
	g_PatchManager.Register(new AutoPatch<Detours::JockeyAttackUpdate>());
	g_PatchManager.Register(new AutoPatch<Detours::ChargerAttackUpdate>());
	g_PatchManager.Register(new AutoPatch<Detours::TankAttackUpdate>());
	g_PatchManager.Register(new AutoPatch<Detours::SurvivorUseObjectUpdate>());

	//new style detours that create/destroy the forwards themselves
	g_PatchManager.Register(new AutoPatch<Detours::OnEnterGhostState>());
}
void Left4Downtown::SDK_OnAllLoaded()
{
	SM_GET_LATE_IFACE(BINTOOLS, g_pBinTools);
	SM_GET_LATE_IFACE(SDKTOOLS, g_pSDKTools);

	if (!g_pBinTools || !g_pSDKTools)
	{
		L4D_DEBUG_LOG("Failed to load bintools or failed to load sdktools");
		return;
	}

	IServer *server = g_pSDKTools->GetIServer();
	L4D_DEBUG_LOG("Address of IServer is %p", server);
	//reading out server->GetName() we consistently seem to get (the same?) 
	//garbage characters. this is possibly causing a crash on windows servers
	//when a player connects. so lets not read the server name :(
	//L4D_DEBUG_LOG("Server name is %s", server->GetName());
	g_pServer = server;

	InitializeValveGlobals();

    g_AddonsEclipse.InstallChangeCallback(::OnAddonsEclipseChanged);
    AddonsDisabler::AddonsEclipse = g_AddonsEclipse.GetInt();

#ifdef USE_PLAYERSLOTS_PATCHES
	/*
		allow more than 8 players in l4d if l4d_maxplayers is not -1
		also if +maxplayers or -maxplayers is not the default value (8)
	*/
	g_MaxPlayers.InstallChangeCallback(::OnMaxPlayersChanged);

	/*
	read the +-maxplayers from command line
	*/

	/*commenting out the code below
	seems to not make it crash during connection to my NFO
	
	START HERE
	*/
	ICommandLine *cmdLine = CommandLine_Tier0();
	int maxplayers = -1;
	L4D_DEBUG_LOG("Command line is: %s", cmdLine->GetCmdLine());

	maxplayers = cmdLine->ParmValue("+maxplayers", -1);
	L4D_DEBUG_LOG("Command line +maxplayers is: %d", maxplayers);

	if(maxplayers == -1) 
	{
		maxplayers = cmdLine->ParmValue("-maxplayers", -1);
	}
	/*
	end here
	*/
	PlayerSlots::MaxPlayers = maxplayers;
#endif

	/*
	detour the witch/spawn spawns
	*/
	//automatically will unregister/cleanup themselves when the ext is unloaded

	g_PatchManager.Register(new AutoPatch<Detours::SpawnSpecial>());
	g_PatchManager.Register(new AutoPatch<Detours::SpawnTank>());
	g_PatchManager.Register(new AutoPatch<Detours::SpawnWitch>());
	g_PatchManager.Register(new AutoPatch<Detours::SpawnWitchBride>());
	g_PatchManager.Register(new AutoPatch<Detours::ClearTeamScores>());
	g_PatchManager.Register(new AutoPatch<Detours::SetCampaignScores>());

	g_PatchManager.Register(new AutoPatch<Detours::FirstSurvivorLeftSafeArea>());
	g_PatchManager.Register(new AutoPatch<Detours::GetScriptValueInt>());
	g_PatchManager.Register(new AutoPatch<Detours::GetScriptValueFloat>());
	g_PatchManager.Register(new AutoPatch<Detours::GetScriptValueString>());
	g_PatchManager.Register(new AutoPatch<Detours::TryOfferingTankBot>());
	g_PatchManager.Register(new AutoPatch<Detours::MobRushStart>());
	g_PatchManager.Register(new AutoPatch<Detours::SpawnITMob>());
	g_PatchManager.Register(new AutoPatch<Detours::SpawnMob>());
	g_PatchManager.Register(new AutoPatch<Detours::ShovedBySurvivor>());
	g_PatchManager.Register(new AutoPatch<Detours::GetCrouchTopSpeed>());
	g_PatchManager.Register(new AutoPatch<Detours::GetRunTopSpeed>());
	g_PatchManager.Register(new AutoPatch<Detours::GetWalkTopSpeed>());
	g_PatchManager.Register(new AutoPatch<Detours::HasConfigurableDifficulty>());
	g_PatchManager.Register(new AutoPatch<Detours::GetSurvivorSet>());
	g_PatchManager.Register(new AutoPatch<Detours::FastGetSurvivorSet>());
	g_PatchManager.Register(new AutoPatch<Detours::GetMissionVersusBossSpawning>());
	g_PatchManager.Register(new AutoPatch<Detours::CThrowActivate>());
	g_PatchManager.Register(new AutoPatch<Detours::StartMeleeSwing>());
	g_PatchManager.Register(new AutoPatch<Detours::UseHealingItems>());
	g_PatchManager.Register(new AutoPatch<Detours::FindScavengeItem>());
	g_PatchManager.Register(new AutoPatch<Detours::SendInRescueVehicle>());
	g_PatchManager.Register(new AutoPatch<Detours::ChangeFinaleStage>());
	g_PatchManager.Register(new AutoPatch<Detours::EndVersusModeRound>());
	g_PatchManager.Register(new AutoPatch<Detours::SelectWeightedSequence>());//for SelectTankAttack
	g_PatchManager.Register(new AutoPatch<Detours::Revived>());
    g_PatchManager.Register(new AutoPatch<Detours::WaterMove>());
	g_PatchManager.Register(new AutoPatch<Detours::PlayerStagger>());
	g_PatchManager.Register(new AutoPatch<Detours::TerrorWeaponHit>());
    g_PatchManager.Register(new AutoPatch<Detours::CTerrorGameRules>());
	g_PatchManager.Register(new AutoPatch<Detours::CBaseServer>());

	//new style detours that create/destroy the forwards themselves
	g_PatchManager.Register(new AutoPatch<Detours::IsFinale>());
	g_PatchManager.Register(new AutoPatch<Detours::OnEnterGhostState>());
	#ifdef USE_PLAYERSLOTS_PATCHES
	g_PatchManager.Register(new AutoPatch<Detours::ServerPlayerCounts>());
	#endif
}