void CTaskSimpleChokingSA::UpdateChoke ( CPed* pPed, CPed* pAttacker, bool bIsTearGas ) { // Get game interfaces CPedSA* pPedSA = dynamic_cast < CPedSA* > ( pPed ); if ( !pPedSA ) return; CPedSAInterface* pPedInterface = pPedSA->GetPedInterface (); CPedSAInterface* pAttackerInterface = NULL; if ( pAttacker ) { CPedSA* pAttackerSA = dynamic_cast < CPedSA* > ( pAttacker ); if ( pAttackerSA ) pAttackerInterface = pAttackerSA->GetPedInterface (); } // Call the func DWORD dwThisInterface = (DWORD)this->GetInterface(); DWORD dwFunc = FUNC_CTaskSimpleChoking__UpdateChoke; _asm { mov ecx, dwThisInterface push bIsTearGas push pAttackerInterface push pPedInterface call dwFunc } }
/** * \todo Handle pEvent correctly to convert it */ bool CTaskSA::MakeAbortable(CPed* pPed, const int iPriority, const CEvent* pEvent) { DEBUG_TRACE("bool CTaskSA::MakeAbortable(CPed* pPed, const int iPriority, const CEvent* pEvent)"); CPedSA* pPedSA = dynamic_cast<CPedSA*>(pPed); if (!pPedSA) return false; DWORD dwPedInterface = (DWORD)pPedSA->GetInterface(); DWORD dwThisInterface = (DWORD)this->GetInterface(); DWORD dwFunc = this->GetInterface()->VTBL->MakeAbortable; bool bReturn = 0; if (dwFunc != 0x82263A && dwFunc) // 82263A = purecall { _asm { mov ecx, dwThisInterface push pEvent push iPriority push dwPedInterface call dwFunc mov bReturn, al } } return bReturn; }
VOID ReturnContextToLocalPlayer() { if ( bNotInLocalContext ) { // Grab the remote data storage for the player we context switched to CPlayerPed* pContextSwitchedPlayerPed = dynamic_cast < CPlayerPed* > ( pContextSwitchedPed ); if ( pContextSwitchedPlayerPed ) { CRemoteDataStorageSA * data = CRemoteDataSA::GetRemoteDataStorage ( pContextSwitchedPlayerPed ); if ( data ) { // Store any changes the game has made to the pad CPad* pLocalPad = pGameInterface->GetPad (); CPadSAInterface* pLocalPadInterface = ( (CPadSA*) pLocalPad )->GetInterface (); memcpy ( &data->m_pad, pLocalPadInterface, sizeof ( CPadSAInterface ) ); } } pGameInterface->GetPad()->Restore(); *(float *)VAR_CameraRotation = fLocalPlayerCameraRotation; bNotInLocalContext = false; CPed* pLocalPlayerPed = pGameInterface->GetPools ()->GetPedFromRef ( (DWORD)1 ); // the player CPedSA* pLocalPlayerPedSA = dynamic_cast < CPedSA* > ( pLocalPlayerPed ); if ( pLocalPlayerPedSA ) { CEntitySAInterface * ped = pLocalPlayerPedSA->GetInterface(); *(DWORD *)0xB7CD98 = (DWORD)ped; } PostContextSwitch(); if ( m_pPostContextSwitchHandler ) { m_pPostContextSwitchHandler (); } } else { // Store any changes to the local-players stats? if ( !bLocalStatsStatic ) { memcpy ( &localStatsData.StatTypesFloat, (void *)0xb79380, sizeof(float) * MAX_FLOAT_STATS ); memcpy ( &localStatsData.StatTypesInt, (void *)0xb79000, sizeof(int) * MAX_INT_STATS ); memcpy ( &localStatsData.StatReactionValue, (void *)0xb78f10, sizeof(float) * MAX_REACTION_STATS ); } } // radio change on startup hack //0050237C 90 NOP memset((void *)0x50237C, 0x90, 5); memset((void *)0x5023A3, 0x90, 5); // We need to set this back, even if its the local player pGameInterface->SetGravity ( fGlobalGravity ); }
void CPoolsSA::RemovePed ( CPed* pPed, bool bDelete ) { DEBUG_TRACE("void CPoolsSA::RemovePed ( CPed* pPed, bool bDelete )"); assert ( NULL != pPed ); CPedSA* pPedSA = dynamic_cast < CPedSA* > ( pPed ); if ( pPedSA ) { RemovePed ( pPedSA->GetArrayID (), bDelete ); } }
DWORD CPoolsSA::GetPedRef ( CPed* pPed ) { DEBUG_TRACE("DWORD CPoolsSA::GetPedRef ( CPed* pPed )"); DWORD dwRef = 0; CPedSA* pPedSA = dynamic_cast < CPedSA * > ( pPed ); if ( pPedSA ) { CPedSAInterface* pInterface = pPedSA->GetPedInterface (); DWORD dwFunc = FUNC_GetPedRef; _asm { push pInterface call dwFunc add esp, 0x4 mov dwRef, eax } } return dwRef; }
bool CCarEnterExitSA::GetNearestCarDoor ( CPed * pPed, CVehicle * pVehicle, CVector * pVector, int * pDoor ) { DWORD dwFunc = FUNC_GetNearestCarDoor; bool bReturn = false; CPedSA* pPedSA = dynamic_cast < CPedSA* > ( pPed ); CVehicleSA* pVehicleSA = dynamic_cast < CVehicleSA* > ( pVehicle ); if ( pPedSA && pVehicleSA ) { CPedSAInterface * pPedInterface = pPedSA->GetPedInterface (); CVehicleSAInterface * pVehicleInterface = pVehicleSA->GetVehicleInterface (); _asm { push pDoor push pVector push pVehicleInterface push pPedInterface call dwFunc add esp, 0x10 mov bReturn, al } }
CTaskSimpleChokingSA::CTaskSimpleChokingSA ( CPed* pAttacker, bool bIsTearGas ) { CPedSA* pAttackerSA = dynamic_cast < CPedSA* > ( pAttacker ); DWORD dwFunc = FUNC_CTaskSimpleChoking__Constructor; DWORD dwIsTearGas = bIsTearGas; // Grab the GTA class for the attacker if any CPedSAInterface* pAttackerInterface = NULL; if ( pAttackerSA ) pAttackerInterface = pAttackerSA->GetPedInterface (); this->CreateTaskInterface ( sizeof ( CTaskSimpleChokingSAInterface ) ); DWORD dwThisInterface = (DWORD)this->GetInterface(); _asm { mov ecx, dwThisInterface push ebx push bIsTearGas push pAttackerInterface call dwFunc pop ebx } }
CTask* CTaskComplexSA::ControlSubTask(CPed* pPed) { DEBUG_TRACE("CTask * CTaskComplexSA::ControlSubTask(CPed* pPed)"); CPedSA* pPedSA = dynamic_cast<CPedSA*>(pPed); if (!pPedSA) return NULL; DWORD dwPedInterface = (DWORD)pPedSA->GetInterface(); DWORD dwThisInterface = (DWORD)this->GetInterface(); DWORD dwFunc = ((TaskComplexVTBL*)this->GetInterface()->VTBL)->ControlSubTask; DWORD dwReturn = 0; if (dwFunc != 0x82263A && dwFunc) { _asm { mov ecx, dwThisInterface push dwPedInterface call dwFunc mov dwReturn, eax } } return ((CTaskManagementSystemSA*)pGame->GetTaskManagementSystem())->GetTask((CTaskSAInterface*)dwReturn); }
bool CTaskSimpleSA::SetPedPosition(CPed* pPed) { DEBUG_TRACE("bool CTaskSimpleSA::SetPedPosition(CPed* pPed)"); CPedSA* pPedSA = dynamic_cast<CPedSA*>(pPed); if (!pPedSA) return false; DWORD dwPedInterface = (DWORD)pPedSA->GetInterface(); DWORD dwThisInterface = (DWORD)this->GetInterface(); DWORD dwFunc = ((TaskSimpleVTBL*)this->GetInterface()->VTBL)->SetPedPosition; bool bReturn = 0; if (dwFunc != 0x82263A && dwFunc) { _asm { mov ecx, dwThisInterface push dwPedInterface call dwFunc mov bReturn, al } } return bReturn; }
void SwitchContext ( CPed* thePed ) { if ( thePed == NULL ) return; pContextSwitchedPed = thePed; // Are we not already in another context? if ( !bNotInLocalContext ) { // Grab the local ped and the local pad CPed* pLocalPlayerPed = pGameInterface->GetPools ()->GetPedFromRef ( (DWORD)1 ); // the player CPad* pLocalPad = pGameInterface->GetPad (); CPadSAInterface* pLocalPadInterface = ( (CPadSA*) pLocalPad )->GetInterface (); // We're not switching to local player if ( thePed != pLocalPlayerPed ) { // Store the local pad pLocalPad->Store (); // store a copy of the local pad internally // Grab the remote data storage for the player we're context switching to CPlayerPed* thePlayerPed = dynamic_cast < CPlayerPed* > ( thePed ); if ( thePlayerPed ) { CRemoteDataStorageSA * data = CRemoteDataSA::GetRemoteDataStorage ( thePlayerPed ); if ( data ) { // We want the player to be seen as in targeting mode if they are right clicking and with weapons eWeaponType currentWeapon = thePed->GetWeapon(thePed->GetCurrentWeaponSlot())->GetType(); CControllerState * cs = data->CurrentControllerState(); if ( cs->RightShoulder1 != 0 && ( currentWeapon == WEAPONTYPE_SNIPERRIFLE || currentWeapon == WEAPONTYPE_ROCKETLAUNCHER || currentWeapon == WEAPONTYPE_ROCKETLAUNCHER_HS || currentWeapon == WEAPONTYPE_CAMERA ) ) { b1stPersonWeaponModeHackInPlace = true; // make the CCamera::Using1stPersonWeaponMode function return true *(BYTE *)0x50BFF0 = 0xB0; // MOV AL, 1 *(BYTE *)0x50BFF1 = 0x01; *(BYTE *)0x50BFF2 = 0xC3; // RETN } // Change the local player's pad to the remote player's memcpy ( pLocalPadInterface, &data->m_pad, sizeof ( CPadSAInterface ) ); // this is to fix the horn/siren pLocalPad->SetHornHistoryValue ( ( cs->ShockButtonL == 255 ) ); // disables the impatient actions on remote players (which cause desync) pLocalPad->SetLastTimeTouched ( pGameInterface->GetSystemTime () ); // this is to make movement work correctly fLocalPlayerCameraRotation = *(float *)VAR_CameraRotation; *(float *)VAR_CameraRotation = data->m_fCameraRotation; // Change the gravity to the remote player's pGameInterface->SetGravity ( data->m_fGravity ); // Disable mouselook for remote players (so the mouse doesn't affect them) // Only disable mouselook if they're not holding a 1st-person weapon // And if they're not under-water bool bDisableMouseLook = true; CWeapon* pWeapon = thePed->GetWeapon ( thePed->GetCurrentWeaponSlot () ); if ( pWeapon ) { eWeaponType weaponType = pWeapon->GetType (); switch ( weaponType ) { case WEAPONTYPE_SNIPERRIFLE: case WEAPONTYPE_ROCKETLAUNCHER: case WEAPONTYPE_ROCKETLAUNCHER_HS: bDisableMouseLook = false; } } bMouseLookEnabled = *(bool *)0xB6EC2E; if ( bDisableMouseLook ) *(bool *)0xB6EC2E = false; // Disable the goggles bInfraredVisionEnabled = *(bool *)0xC402B9; *(bool *)0xC402B9 = false; bNightVisionEnabled = *(bool *)0xC402B8; *(bool *)0xC402B8 = false; // Remove the code making players cough on fire extinguisher and teargas memset ( (void*) 0x4C03F0, 0x90, 3 ); memset ( (void*) 0x4C03F8, 0x90, 7 ); // Prevent it calling ClearWeaponTarget for remote players *(BYTE *)0x609C80 = 0xC3; // Prevent rockets firing oddly //*(BYTE *)0x73811C = 0x90; //*(BYTE *)0x73811D = 0xE9; // This is so weapon clicks and similar don't play for us when done remotly *(BYTE *)0x60F273 = 0xEB; *(BYTE *)0x60F260 = 0x90; *(BYTE *)0x60F261 = 0x90; // Prevent CCamera::SetNewPlayerWeaponMode being called *(BYTE *)0x50BFB0 = 0xC2; // RETN 0xC *(BYTE *)0x50BFB1 = 0x0C; *(BYTE *)0x50BFB2 = 0x00; // Prevent it calling CCamera::ClearPlayerWeaponMode for remote players *(BYTE *)0x50AB10 = 0xC3; // Prevent it marking targets of remote players *(BYTE *)0x742BF0 = 0xC3; // this is to prevent shooting players following the local camera *(BYTE *)0x687099 = 0xEB; // Prevent the game making remote player's weapons get switched by the local player's *(BYTE *)0x60D850 = 0xC2; *(BYTE *)0x60D851 = 0x04; *(BYTE *)0x60D852 = 0x00; // Change the local player's stats to the remote player's if ( data ) { memcpy ( (void *)0xb79380, data->m_stats.StatTypesFloat, sizeof(float) * MAX_FLOAT_STATS ); memcpy ( (void *)0xb79000, data->m_stats.StatTypesInt, sizeof(int) * MAX_INT_STATS ); memcpy ( (void *)0xb78f10, data->m_stats.StatReactionValue, sizeof(float) * MAX_REACTION_STATS ); } /* // ChrML: Force as high stats as we can go before screwing up. Players can't have different // stats or guns don't work. We can't have dual guns either due to some screwups. // Dual gun screwup: Sync code needs update and the gun pointing up needs to. float* pfStats = (float*) 0xb79380; pfStats [ 69 ] = 500.0f; pfStats [ 70 ] = 999.0f; pfStats [ 71 ] = 999.0f; pfStats [ 72 ] = 999.0f; pfStats [ 73 ] = 500.0f; pfStats [ 74 ] = 999.0f; pfStats [ 75 ] = 500.0f; pfStats [ 76 ] = 999.0f; pfStats [ 77 ] = 999.0f; pfStats [ 78 ] = 999.0f; pfStats [ 79 ] = 999.0f; */ CPedSA* thePedSA = dynamic_cast < CPedSA* > ( thePed ); if ( thePedSA ) { CEntitySAInterface * ped = thePedSA->GetInterface(); *(DWORD *)0xB7CD98 = (DWORD)ped; } // Remember that we're not in the local player's context any more (for switching back) bNotInLocalContext = true; // Call the pre-context switch handler we might have if ( m_pPreContextSwitchHandler ) { CPlayerPed* pPlayerPed = dynamic_cast < CPlayerPed* > ( thePed ); if ( pPlayerPed ) m_pPreContextSwitchHandler ( pPlayerPed ); } } } } else { // Set the local players gravity pGameInterface->SetGravity ( fLocalPlayerGravity ); if ( bCustomCameraRotation ) *(float *)VAR_CameraRotation = fLocalPlayerCameraRotation; } } }
void CPoolsSA::RemovePed ( unsigned long ulID, bool bDelete ) { DEBUG_TRACE("void CPoolsSA::RemovePed ( unsigned long ulID, bool bDelete )"); static bool bIsDeletingPedAlready = false; // to prevent delete being called twice if ( !bIsDeletingPedAlready ) { bIsDeletingPedAlready = true; CPedSA* pPedSA = m_pedPool.array [ ulID ]; assert ( NULL != pPedSA ); // Pop the element to remove from the pool array if ( ulID != m_pedPool.ulCount - 1 ) { // We are removing an intermediate position of // the array. Move the last element to the just // deleted element position to not allow empty // spaces on it. m_pedPool.array [ ulID ] = m_pedPool.array [ m_pedPool.ulCount - 1 ]; m_pedPool.array [ ulID ]->SetArrayID ( ulID ); } m_pedPool.array [ m_pedPool.ulCount - 1 ] = NULL; // Unlink the element to remove from the pool map pedPool_t::mapType::iterator iter = m_pedPool.map.find ( pPedSA->GetPedInterface () ); if ( iter != m_pedPool.map.end () ) { m_pedPool.map.erase ( iter ); } // Delete the element from memory switch ( pPedSA->GetType () ) { case PLAYER_PED: { CPlayerPedSA* pPlayerPed = dynamic_cast < CPlayerPedSA* > ( pPedSA ); if ( pPlayerPed ) { if ( ! bDelete ) pPlayerPed->SetDoNotRemoveFromGameWhenDeleted ( true ); } delete pPlayerPed; break; } default: { CCivilianPedSA* pCivPed = dynamic_cast < CCivilianPedSA* > ( pPedSA ); if ( pCivPed ) { if ( ! bDelete ) pCivPed->SetDoNotRemoveFromGameWhenDeleted ( true ); } delete pCivPed; } } // Decrease the count of elements in the pool --m_pedPool.ulCount; bIsDeletingPedAlready = false; } }