/*****************************************************************************
*
* PROJECT: Multi Theft Auto v1.0
* LICENSE: See LICENSE in the top level directory
* FILE: multiplayer_sa/CPopulationSA.cpp
* PURPOSE: Ped world population class
* DEVELOPERS: Ed Lyons <eai@opencoding.net>
* Christian Myhre Lundheim <>
* Cecill Etheredge <ijsf@gmx.net>
*
* Multi Theft Auto is available from http://w...content-available-to-author-only...o.com/
*
*****************************************************************************/
#include "StdInc.h"
using std::list;
CPedSAInterface * pPedStorage;
CVehicleSAInterface * pVehicleStorage;
CObjectSAInterface * pObjectStorage;
CPopulationSA * pSingleton;
DWORD pedVtable;
VOID HOOK_EndOf_CPopulation__Add();
VOID HOOK_CPopulation__RemovePed();
VOID HOOK_CVehicle__Add();
VOID HOOK_CVehicle__Remove();
VOID HOOK_CObject__Add();
VOID HOOK_CObject__Remove();
CivilianAddHandler * m_pCivilianAddHandler;
CivilianRemoveHandler * m_pCivilianRemoveHandler;
VehicleAddHandler * m_pVehicleAddHandler;
VehicleRemoveHandler * m_pVehicleRemoveHandler;
ObjectAddHandler * m_pObjectAddHandler;
ObjectRemoveHandler * m_pObjectRemoveHandler;
CPopulationSA::CPopulationSA()
{
dwPedCount = 0;
dwVehicleCount = 0;
dwObjectCount = 0;
HookInstall(HOOKPOS_EndOf_CPopulation__Add, (DWORD)HOOK_EndOf_CPopulation__Add, 6);
HookInstall(HOOKPOS_CPopulation__RemovePed, (DWORD)HOOK_CPopulation__RemovePed, 6);
#if HOOKPOS_CVehicle__Add != 0x00000000
HookInstall(HOOKPOS_CVehicle__Add, (DWORD)HOOK_CVehicle__Add, 6);
#endif
#if HOOKPOS_CVehicle__Remove != 0x00000000
HookInstall(HOOKPOS_CVehicle__Remove, (DWORD)HOOK_CVehicle__Remove, 6);
#endif
#if HOOKPOS_CObject__Add != 0x00000000
HookInstall(HOOKPOS_CObject__Add, (DWORD)HOOK_CObject__Add, 6);
#endif
#if HOOKPOS_CObject__Remove != 0x00000000
HookInstall(HOOKPOS_CObject__Remove, (DWORD)HOOK_CObject__Remove, 6);
#endif
pSingleton = this;
m_pCivilianRemoveHandler = NULL;
m_pCivilianAddHandler = NULL;
m_pObjectAddHandler = NULL;
m_pObjectRemoveHandler = NULL;
m_pVehicleAddHandler = NULL;
m_pVehicleRemoveHandler = NULL;
}
VOID CPopulationSA::AddPed ( CCivilianPed * ped )
{
CCivilianPedSA* pPedSA = dynamic_cast < CCivilianPedSA* > ( ped );
if ( !pPedSA ) return;
CEntitySAInterface* pPedSAInterface = pPedSA->GetInterface ();
list < CCivilianPedSA* > ::iterator iter;
for ( iter = peds.begin (); iter != peds.end (); ++iter )
{
if ( (*iter)->GetInterface() == pPedSAInterface )
{
return;
}
}
peds.push_back ( pPedSA );
dwPedCount ++;
}
VOID CPopulationSA::AddVehicle(CVehicle * vehicle)
{
CVehicleSA* pVehicleSA = dynamic_cast < CVehicleSA* > (vehicle);
if (!pVehicleSA) return;
CEntitySAInterface* pVehicleSAInterface = pVehicleSA->GetInterface();
list < CVehicleSA* > ::iterator iter;
for (iter = vehicles.begin(); iter != vehicles.end(); ++iter)
{
if ((*iter)->GetInterface() == pVehicleSAInterface)
{
return;
}
}
vehicles.push_back(pVehicleSA);
dwVehicleCount++;
}
VOID CPopulationSA::AddObject(CObject * object)
{
CObjectSA* pObjectSA = dynamic_cast < CObjectSA* > (object);
if (!pObjectSA) return;
CEntitySAInterface* pObjectSAInterface = pObjectSA->GetInterface();
list < CObjectSA* > ::iterator iter;
for (iter = objects.begin(); iter != objects.end(); ++iter)
{
if ((*iter)->GetInterface() == pObjectSAInterface)
{
return;
}
}
objects.push_back(pObjectSA);
dwObjectCount++;
}
VOID CPopulationSA::AddPed ( CPedSAInterface * ped )
{
list < CCivilianPedSA* > ::iterator iter;
for ( iter = peds.begin (); iter != peds.end (); ++iter )
{
if ( (*iter)->GetInterface() == ped )
{
return;
}
}
//_asm int 3
CCivilianPedSA * pedSA = dynamic_cast < CCivilianPedSA* > ( pGameInterface->GetPools()->AddCivilianPed((DWORD *)ped ) );
if ( !pedSA ) return;
//char szDebug[255] = {'\0'};
DWORD dwPedInterface = (DWORD)pedSA->GetInterface();
//sprintf ( szDebug, "Civ ped added (%d) (0x%X -> 0x%X)\n", dwPedCount+1, ped, dwPedInterface);
//OutputDebugString ( szDebug );
if ( m_pCivilianAddHandler )
m_pCivilianAddHandler ( pedSA );
peds.push_back (pedSA);
dwPedCount ++;
}
VOID CPopulationSA::AddVehicle(CVehicleSAInterface * vehicle)
{
list < CVehicleSA* > ::iterator iter;
for (iter = vehicles.begin(); iter != vehicles.end(); ++iter)
{
if ((*iter)->GetInterface() == vehicle)
{
return;
}
}
//_asm int 3
CVehicleSA * vehicleSA = dynamic_cast < CVehicleSA* > (pGameInterface->GetPools()->AddVehicle((DWORD *)vehicle));
if (!vehicleSA) return;
//char szDebug[255] = { '\0' };
DWORD dwVehicleInterface = (DWORD)vehicleSA->GetInterface();
//sprintf(szDebug, "Vehicle added (%d) (0x%X -> 0x%X)\n", dwVehicleCount + 1, vehicle, dwVehicleInterface);
//OutputDebugString ( szDebug );
if (m_pVehicleAddHandler)
m_pVehicleAddHandler(vehicleSA);
vehicles.push_back(vehicleSA);
dwVehicleCount++;
}
VOID CPopulationSA::AddObject(CObjectSAInterface * object)
{
list < CObjectSA* > ::iterator iter;
for (iter = objects.begin(); iter != objects.end(); ++iter)
{
if ((*iter)->GetInterface() == object)
{
return;
}
}
//_asm int 3
CObjectSA * ObjectSA = dynamic_cast < CObjectSA* > (pGameInterface->GetPools()->AddBuilding(object->m_nModelIndex));
if (!ObjectSA) return;
//char szDebug[255] = { '\0' };
DWORD dwObjectInterface = (DWORD)ObjectSA->GetInterface();
//sprintf(szDebug, "Object added (%d) (0x%X -> 0x%X)\n", dwObjectCount + 1, object, dwObjectInterface);
//OutputDebugString ( szDebug );
if (m_pObjectAddHandler)
m_pObjectAddHandler(ObjectSA);
objects.push_back(ObjectSA);
dwObjectCount++;
}
VOID CPopulationSA::RemovePed ( CCivilianPed * ped )
{
if ( !ped ) return;
CCivilianPedSA* pPedSA = dynamic_cast < CCivilianPedSA* > ( ped );
if ( !pPedSA ) return;
ped->SetDoNotRemoveFromGameWhenDeleted ( true );
pGameInterface->GetPools()->RemovePed ( (CPed*)ped );
if ( !peds.empty () ) peds.remove ( pPedSA );
dwPedCount--;
}
VOID CPopulationSA::RemoveVehicle(CVehicle * vehicle)
{
if (!vehicle) return;
CVehicleSA* pVehicleSA = dynamic_cast < CVehicleSA* > (vehicle);
if (!pVehicleSA) return;
vehicle->SetDoNotRemoveFromGameWhenDeleted(true);
pGameInterface->GetPools()->RemoveVehicle((CVehicle*)vehicle);
if (!vehicles.empty()) vehicles.remove(pVehicleSA);
dwVehicleCount--;
}
VOID CPopulationSA::RemoveObject(CObject * object)
{
if (!object) return;
CObjectSA* pObjectSA = dynamic_cast < CObjectSA* > (object);
if (!pObjectSA) return;
object->SetDoNotRemoveFromGameWhenDeleted(true);
pGameInterface->GetPools()->RemoveObject((CObject*)object);
if (!objects.empty()) objects.remove(pObjectSA);
dwObjectCount--;
}
VOID CPopulationSA::RemovePed ( CPedSAInterface * ped )
{
list < CCivilianPedSA* > ::iterator iter;
for ( iter = peds.begin (); iter != peds.end (); ++iter )
{
if ( (*iter)->GetInterface() == ped )
{
//char szDebug[255] = {'\0'};
//sprintf ( szDebug, "Civ ped removed (%d)\n", dwPedCount - 1);
pGameInterface->GetPools()->RemovePed ( (CPed *)(CCivilianPed *)(*iter), false );
//OutputDebugString ( szDebug );
if ( m_pCivilianRemoveHandler )
m_pCivilianRemoveHandler ( (*iter) );
peds.erase ( iter );
dwPedCount--;
return;
}
}
//OutputDebugString ( "Tried to remove Civ Ped, but Civ Ped not found!\n" );
}
VOID CPopulationSA::RemoveVehicle(CVehicleSAInterface * vehicle)
{
list < CVehicleSA* > ::iterator iter;
for (iter = vehicles.begin(); iter != vehicles.end(); ++iter)
{
if ((*iter)->GetInterface() == vehicle)
{
//char szDebug[255] = {'\0'};
//sprintf ( szDebug, "Civ ped removed (%d)\n", dwPedCount - 1);
pGameInterface->GetPools()->RemoveVehicle((CVehicle*)(*iter), false);
//OutputDebugString ( szDebug );
if (m_pVehicleRemoveHandler)
m_pVehicleRemoveHandler((*iter));
vehicles.erase(iter);
dwVehicleCount--;
return;
}
}
//OutputDebugString ( "Tried to remove Civ Ped, but Civ Ped not found!\n" );
}
VOID CPopulationSA::RemoveObject(CObjectSAInterface * object)
{
list < CObjectSA* > ::iterator iter;
for (iter = objects.begin(); iter != objects.end(); ++iter)
{
if ((*iter)->GetInterface() == object)
{
//char szDebug[255] = {'\0'};
//sprintf ( szDebug, "Civ ped removed (%d)\n", dwPedCount - 1);
pGameInterface->GetPools()->RemoveObject((CObject*)(*iter), false);
//OutputDebugString ( szDebug );
if (m_pObjectRemoveHandler)
m_pObjectRemoveHandler((*iter));
objects.erase(iter);
dwObjectCount--;
return;
}
}
//OutputDebugString ( "Tried to remove Civ Ped, but Civ Ped not found!\n" );
}
DWORD CPopulationSA::GetPedCount ( )
{
return dwPedCount;
}
DWORD CPopulationSA::GetVehicleCount()
{
return dwVehicleCount;
}
DWORD CPopulationSA::GetObjectCount()
{
return dwObjectCount;
}
CCivilianPed * CPopulationSA::GetFirstPed ()
{
if ( peds.size () > 0 )
{
pedIter = peds.begin ();
return *peds.begin ();
}
else
{
return NULL;
}
}
CVehicle * CPopulationSA::GetFirstVehicle()
{
if (vehicles.size() > 0)
{
vehIter = vehicles.begin();
return *vehicles.begin();
}
else
{
return NULL;
}
}
CObject * CPopulationSA::GetFirstObject()
{
if (objects.size() > 0)
{
objectIter = objects.begin();
return *objects.begin();
}
else
{
return NULL;
}
}
CCivilianPed * CPopulationSA::GetNextPed ()
{
++( pedIter );
if ( pedIter != peds.end () )
{
return *pedIter;
}
else
{
return NULL;
}
}
CVehicle * CPopulationSA::GetNextVehicle()
{
++(vehIter);
if (vehIter != vehicles.end())
{
return *vehIter;
}
else
{
return NULL;
}
}
CObject * CPopulationSA::GetNextObject()
{
++(objectIter);
if (objectIter != objects.end())
{
return *objectIter;
}
else
{
return NULL;
}
}
void CPopulationSA::SetCivilianAddHandler ( CivilianAddHandler * pCivilianAddHandler )
{
m_pCivilianAddHandler = pCivilianAddHandler;
}
void CPopulationSA::SetCivilianRemoveHandler ( CivilianRemoveHandler * pCivilianRemoveHandler )
{
m_pCivilianRemoveHandler = pCivilianRemoveHandler;
}
void CPopulationSA::SetObjectAddHandler(ObjectAddHandler * pObjectAddHandler)
{
m_pObjectAddHandler = pObjectAddHandler;
}
void CPopulationSA::SetObjectRemoveHandler(ObjectRemoveHandler * pObjectRemoveHandler)
{
m_pObjectRemoveHandler = pObjectRemoveHandler;
}
void CPopulationSA::SetVehicleAddHandler(VehicleAddHandler * pVehicleAddHandler)
{
m_pVehicleAddHandler = pVehicleAddHandler;
}
void CPopulationSA::SetVehicleRemoveHandler(VehicleRemoveHandler * pVehicleRemoveHandler)
{
m_pVehicleRemoveHandler = pVehicleRemoveHandler;
}
VOID _declspec(naked) HOOK_EndOf_CPopulation__Add()
{
_asm
{
mov pPedStorage, eax
pushad
}
pSingleton->AddPed ( pPedStorage );
_asm
{
popad
add esp, 0x3C
retn
}
}
VOID _declspec(naked) HOOK_CPopulation__RemovePed()
{
/*
00610F20 /$ 56 PUSH ESI
00610F21 |. 8B7424 08 MOV ESI,DWORD PTR SS:[ESP+8]
00610F25 |. 56 PUSH ESI
*/
_asm
{
push esi
mov esi, [esp+8]
push esi
mov pPedStorage, esi
mov ecx, [esi]
mov pedVtable, ecx
pushad
}
if ( pedVtable == VTBL_CPlayerPed )
{
_asm
{
popad
pop esi
pop esi
retn
}
}
pSingleton->RemovePed(pPedStorage);
_asm
{
popad
mov ecx, HOOKPOS_CPopulation__RemovePed
add ecx, 6
jmp ecx
}
}
//I really just copied the ASM code, probably will crash
VOID _declspec(naked) HOOK_CVehicle__Add()
{
_asm
{
mov pVehicleStorage, eax
pushad
}
pSingleton->AddVehicle(pVehicleStorage);
_asm
{
popad
add esp, 0x3C
retn
}
}
VOID _declspec(naked) HOOK_CVehicle__Remove()
{
#pragma warning ("Put ASM shit here just like in HOOK_EndOf_CPopulation__Add() to make it work")
pSingleton->RemoveVehicle(pVehicleStorage);
}
VOID _declspec(naked) HOOK_CObject__Add()
{
_asm
{
mov pObjectStorage, eax
pushad
}
pSingleton->AddObject(pObjectStorage);
_asm
{
popad
add esp, 0x3C
retn
}
}
VOID _declspec(naked) HOOK_CObject__Remove()
{
pSingleton->RemoveObject(pObjectStorage);
}