int CLuaPedDefs::GetPedWeapon ( lua_State* luaVM ) { CPed* pPed; unsigned char ucSlot; CScriptArgReader argStream ( luaVM ); argStream.ReadUserData ( pPed ); argStream.ReadNumber ( ucSlot, 0xFF ); if ( !argStream.HasErrors () ) { if ( ucSlot == 0xFF ) ucSlot = pPed->GetWeaponSlot (); CWeapon* pWeapon = pPed->GetWeapon ( ucSlot ); if ( pWeapon ) { unsigned char ucWeapon = pWeapon->ucType; lua_pushnumber ( luaVM, ucWeapon ); return 1; } } else m_pScriptDebugging->LogCustom ( luaVM, argStream.GetFullErrorMessage () ); // Failed lua_pushboolean ( luaVM, false ); return 1; }
CClientProjectile* CClientProjectileManager::Create(CClientEntity* pCreator, eWeaponType eWeapon, CVector& vecOrigin, float fForce, CVector* target, CClientEntity* pTargetEntity) { m_bCreating = true; m_pLastCreated = NULL; CEntity* pGameCreator = pCreator->GetGameEntity(); CEntity* pGameTargetEntity = NULL; if (pTargetEntity) pGameTargetEntity = pTargetEntity->GetGameEntity(); if (pGameCreator) { // Peds and players if (pCreator->GetType() == CCLIENTPED || pCreator->GetType() == CCLIENTPLAYER) { CPed* pPed = dynamic_cast<CPed*>(pGameCreator); if (pPed) pPed->AddProjectile(eWeapon, vecOrigin, fForce, target, pGameTargetEntity); } // Vehicles else if (pCreator->GetType() == CCLIENTVEHICLE) { CVehicle* pVehicle = dynamic_cast<CVehicle*>(pGameCreator); if (pVehicle) pVehicle->AddProjectile(eWeapon, vecOrigin, fForce, target, pGameTargetEntity); } } m_bCreating = false; return m_pLastCreated; }
int CLuaPedDefs::GetPedTotalAmmo ( lua_State* luaVM ) { CPed* pPed; unsigned char ucSlot = 0; CScriptArgReader argStream ( luaVM ); argStream.ReadUserData ( pPed ); if ( !argStream.HasErrors () ) argStream.ReadNumber ( ucSlot, pPed->GetWeaponSlot () ); if ( !argStream.HasErrors () ) { CWeapon* pWeapon = pPed->GetWeapon ( ucSlot ); if ( pWeapon ) { lua_pushnumber ( luaVM, pWeapon->usAmmo ); return 1; } } else m_pScriptDebugging->LogCustom ( luaVM, argStream.GetFullErrorMessage () ); lua_pushboolean ( luaVM, false ); return 1; }
//////////////////////////////////////////////////// // // CMouseControl::ProcessMouseMove // // Process a windows mouse movement message and turn it into control // //////////////////////////////////////////////////// bool CMouseControl::ProcessMouseMove ( UINT uMsg, WPARAM wParam, LPARAM lParam ) { if ( uMsg != WM_MOUSEMOVE ) return false; if ( g_pCore->GetGame ()->GetSystemState () != 9 ) return false; // HACK: Grab our local player, and check his vehicle CPed* pPed = g_pCore->GetGame ()->GetPools ()->GetPedFromRef ( (DWORD)1 ); if ( !pPed ) return false; CVehicle* pVehicle = pPed->GetVehicle (); if ( !pVehicle ) return false; CModelInfo* pModelInfo = g_pCore->GetGame ()->GetModelInfo( pVehicle->GetModelIndex() ); bool bVar; CVARS_GET ( "fly_with_mouse", bVar ); if ( pModelInfo->IsPlane() || pModelInfo->IsHeli() && !bVar ) // Are we in a plane, but not have mouse flight enabled? return false; CVARS_GET ( "steer_with_mouse", bVar ); if ( !bVar ) // Are we in another type of vehicle, but not have mouse steering enabled? return false; // Let's calculate our mouse movement directions CVector2D resolution = g_pCore->GetGUI()->GetResolution(); int iX = LOWORD ( lParam ), iY = HIWORD ( lParam ); float fX = (iX - resolution.fX*0.5f)/resolution.fX; fX *= MOUSE_CONTROL_MULTIPLIER; float fMouseSensitivity = g_pCore->GetGame ( )->GetSettings()->GetMouseSensitivity (); fX *= fMouseSensitivity; m_usLeftStickX += fX*128; m_usLeftStickX = Clamp < const short > ( -128, m_usLeftStickX, 128 ); // Only process Y input if we're in a vehicle that requires it if ( pModelInfo->IsPlane() || pModelInfo->IsHeli() || pModelInfo->IsBike() || pModelInfo->IsBmx() || pModelInfo->IsQuadBike() ) { float fY = (resolution.fY*0.5f - iY)/resolution.fY; fY *= MOUSE_CONTROL_MULTIPLIER; fY *= fMouseSensitivity; CVARS_GET ( "invert_mouse", bVar ); fY = bVar ? -fY : fY; m_usLeftStickY += fY*128; m_usLeftStickY = Clamp < const short > ( -128, m_usLeftStickY, 128 ); } return true; }
static void Event_BulletImpact ( void ) { if ( m_pBulletImpactHandler ) { CPed * pInitiator = m_pools->GetPed ( (DWORD *)pBulletImpactInitiator ); if ( pInitiator ) { CEntity* pVictim = m_pools->GetEntity ( (DWORD *)pBulletImpactVictim ); if ( IsLocalPlayer ( pInitiator ) ) { // Correct weapon range if local player float fRange = pInitiator->GetCurrentWeaponRange (); CVector vecDir = *pBulletImpactEndPosition - *pBulletImpactStartPosition; float fLength = vecDir.Length (); if ( fRange < fLength ) { vecDir.Normalize (); *pBulletImpactEndPosition = *pBulletImpactStartPosition + vecDir * fRange; } // These two will be the same when shooting without aiming, so correct them if ( vecLastLocalPlayerBulletStart == vecLastLocalPlayerBulletEnd ) { vecLastLocalPlayerBulletStart = *pBulletImpactStartPosition; vecLastLocalPlayerBulletEnd = *pBulletImpactEndPosition; } m_pBulletImpactHandler ( pInitiator, pVictim, &vecLastLocalPlayerBulletStart, &vecLastLocalPlayerBulletEnd ); } else { // Correct start postion if remote player CRemoteDataStorageSA * data = CRemoteDataSA::GetRemoteDataStorage ( pBulletImpactInitiator ); if ( data ) { if ( data->ProcessPlayerWeapon () ) { if ( data->m_shotSyncData.m_bRemoteBulletSyncVectorsValid ) { *pBulletImpactStartPosition = data->m_shotSyncData.m_vecRemoteBulletSyncStart; data->m_shotSyncData.m_bRemoteBulletSyncVectorsValid = false; // Ensure weapon fire event gets the correct vectors data->m_shotSyncData.m_vecShotOrigin = data->m_shotSyncData.m_vecRemoteBulletSyncStart; data->m_shotSyncData.m_vecShotTarget = data->m_shotSyncData.m_vecRemoteBulletSyncEnd; } else *pBulletImpactStartPosition = data->m_shotSyncData.m_vecShotOrigin; } } m_pBulletImpactHandler ( pInitiator, pVictim, pBulletImpactStartPosition, pBulletImpactEndPosition ); } } vecSavedBulletImpactEndPosition = *pBulletImpactEndPosition; // Saved for vehicle damage event parameters } }
PlayerWeapon() { static int keyPressTime = 0; Events::gameProcessEvent += [] { CPed *playa = FindPlayerPed(); if (playa && KeyPressed(VK_TAB) && CTimer::m_snTimeInMilliseconds - keyPressTime > 500) { keyPressTime = CTimer::m_snTimeInMilliseconds; CStreaming::RequestModel(MODEL_M4, 2); CStreaming::LoadAllRequestedModels(false); playa->GiveWeapon(WEAPON_M4, 10, true); playa->SetCurrentWeapon(WEAPON_M4); CStreaming::SetModelIsDeletable(MODEL_M4); } }; }
CPed* CPedManager::Create ( unsigned short usModel, CElement* pParent, CXMLNode* pNode ) { // Create the ped CPed* pPed = new CPed ( this, pParent, pNode, usModel ); // Invalid ped id? if ( pPed->GetID () == INVALID_ELEMENT_ID ) { delete pPed; return NULL; } // Return the created ped return pPed; }
int CLuaPedDefs::IsPedDucked ( lua_State* luaVM ) { CPed* pPed; CScriptArgReader argStream ( luaVM ); argStream.ReadUserData ( pPed ); if ( !argStream.HasErrors () ) { lua_pushboolean ( luaVM, pPed->IsDucked () ); return 1; } else m_pScriptDebugging->LogCustom ( luaVM, argStream.GetFullErrorMessage () ); lua_pushboolean ( luaVM, false ); return 1; }
void CRPCFunctions::RequestStealthKill ( NetBitStreamInterface & bitStream ) { ElementID ID; bitStream.ReadCompressed ( ID ); CElement * pElement = CElementIDs::GetElement ( ID ); if ( pElement ) { int elementType = pElement->GetType (); if ( elementType == CElement::PLAYER || elementType == CElement::PED ) { CPed * pTarget = static_cast < CPed * > ( pElement ); // Are they both alive? if ( !m_pSourcePlayer->IsDead () && !pTarget->IsDead () ) { //Do we have any record of the killer currently having a knife? if ( m_pSourcePlayer->GetWeaponType( 1 ) == 4 ) { // Are they close enough? if ( DistanceBetweenPoints3D ( m_pSourcePlayer->GetPosition (), pTarget->GetPosition () ) <= STEALTH_KILL_RANGE ) { CLuaArguments Arguments; Arguments.PushElement ( pTarget ); if ( m_pSourcePlayer->CallEvent ( "onPlayerStealthKill", Arguments, false ) ) { // Start the stealth kill CStaticFunctionDefinitions::KillPed ( pTarget, m_pSourcePlayer, 4 /*WEAPONTYPE_KNIFE*/, 9/*BODYPART_HEAD*/, true ); } } } else { //You shouldn't be able to get here without cheating to get a knife. if ( !g_pGame->GetConfig ()->IsDisableAC ( "2" ) ) { CStaticFunctionDefinitions::KickPlayer ( m_pSourcePlayer, NULL, "AC #2: You were kicked from the game" ); } } } } } }
////////////////////////////////////////////////////////////////////////////////////////// // // CVehicle::BurstTyre // (Used for CAutomobile and CBike hooks) // // Called when an inflated vehicle tyre is hit by a bullet // ////////////////////////////////////////////////////////////////////////////////////////// bool OnMY_CVehicle_BurstTyre( CVehicleSAInterface* pVehicle, uchar ucTyre ) { if ( m_pVehicleDamageHandler ) { eWeaponType weaponType = WEAPONTYPE_INVALID; // Discover weapon if possible CPed* pInitiator = pGameInterface->GetPools()->GetPed ( (DWORD *)pBulletImpactInitiator ); if ( pInitiator ) { CWeapon* pWeapon = pInitiator->GetWeapon ( pInitiator->GetCurrentWeaponSlot () ); if ( pWeapon ) weaponType = pWeapon->GetType (); } if ( !m_pVehicleDamageHandler( pVehicle, 0, pBulletImpactInitiator, weaponType, vecSavedBulletImpactEndPosition, ucTyre ) ) return false; } return true; }
CPed* CPedManager::CreateFromXML ( CElement* pParent, CXMLNode& Node, CLuaMain* pLuaMain, CEvents* pEvents ) { // Create the Ped CPed* pPed = new CPed ( this, pParent, &Node, 400 ); // Verify the Ped id and load the data from xml if ( pPed->GetID () == INVALID_ELEMENT_ID || !pPed->LoadFromCustomData ( pLuaMain, pEvents ) ) { delete pPed; return NULL; } // Make sure hes alive (leave to scripts?) pPed->SetIsDead ( false ); pPed->SetSpawned ( true ); pPed->SetHealth ( 100.0f ); // Return the created Ped return pPed; }
int cheat_panic ( void ) { traceLastFunc( "cheat_panic()" ); static int pstate_map = 0, // m0d's map pstate_d3dtext_hud = 0, // hud bar pstate_actor_hp_nSP = 0, // "Extra actor invincibility" patch (invulnerable single player enemies) pstate_actor_hp_SP = 0, // "Extra actor invincibility2" patch (no problems in SP) pstate_vehicle_hp = 0, // vehicle hp patch pstate_generic_menu = 0, // m0d's menu pstate_infnos = 0, // infinite NOS pstate_ini[INI_PATCHES_MAX], pstate_dummy_aligner; // this should all be a structure, static = DOING IT WRONG int i; // sa-mp related static int pstate_chat = 0, // chat pstate_deathlist = 0; // deathlist if ( KEY_PRESSED(set.key_panic) ) { // toggle panic cheat_state->_generic.cheat_panic_enabled ^= 1; if ( cheat_state->_generic.cheat_panic_enabled ) { struct actor_info *actor_info = actor_info_get( ACTOR_SELF, ACTOR_ALIVE ); if ( actor_info ) { actor_info->flags &= ~ACTOR_FLAGS_INVULNERABLE; actor_info->weapon_slot = 0; } // remove infinite NOS pstate_infnos = cheat_state->vehicle.infNOS_toggle_on; cheat_state->vehicle.infNOS_toggle_on = false; patcher_remove( &patch_vehicle_inf_NOS ); if ( pPedSelf->GetVehicle() ) { CVehicle *pVehicleSelf = pPedSelf->GetVehicle(); CVehicle *pVehicleTemp = NULL; for ( pVehicleTemp = pVehicleSelf; pVehicleTemp != NULL; pVehicleTemp = pVehicleTemp->GetTowedVehicle() ) { pVehicleTemp->SetGravity( &CVector(0.0, 0.0, -1.0) ); pVehicleTemp->SetCanBeDamaged( true ); if ( !set.trailer_support ) break; } // remove inf NOS if ( pstate_infnos ) { pVehicleSelf->RemoveVehicleUpgrade( 1010 ); //pVehicleSelf->AddVehicleUpgrade( 1010 ); } // reset overrideLights, pstate not needed, will be reactivated on demand if ( set.enable_car_lights_at_day_time ) pVehicleSelf->SetOverrideLights( 0 ); } // hud bar, this should probably become a cheat_state pstate_d3dtext_hud = set.d3dtext_hud; set.d3dtext_hud = 0; // m0d's map pstate_map = cheat_state->_generic.map; cheat_state->_generic.map = 0; // m0d's menu pstate_generic_menu = cheat_state->_generic.menu; cheat_state->_generic.menu = 0; // remove "Extra actor invincibility" patch pstate_actor_hp_nSP = patch_actor_hp_extraInv.installed; patcher_remove( &patch_actor_hp_extraInv ); pstate_actor_hp_SP = patch_actor_hp.installed; patcher_remove( &patch_actor_hp ); // remove vehicle hp patch pstate_vehicle_hp = patch_vehicle_hp.installed; patcher_remove( &patch_vehicle_hp ); // just call with null vehicle info to disable cheat_handle_vehicle_fly( NULL, 0.0f ); for ( i = 0; i < INI_PATCHES_MAX; i++ ) { // added to not remove volatile patches if ( !set.patch[i].has_volatile ) { pstate_ini[i] = set.patch[i].installed; patcher_remove( &set.patch[i] ); } } // turn off kill & chat if ( g_DeathList != NULL ) { pstate_deathlist = g_DeathList->iEnabled; g_DeathList->iEnabled = 1; } if ( g_Chat != NULL ) { pstate_chat = g_Chat->iChatWindowMode; g_Chat->iChatWindowMode = 2; } } else { // restore infinite NOS if ( pstate_infnos ) { cheat_state->vehicle.infNOS_toggle_on = true; patcher_install( &patch_vehicle_inf_NOS ); } // vehicle stuff CPed *pPedSelf = pPools->GetPedFromRef( CPOOLS_PED_SELF_REF ); if ( pPedSelf->GetVehicle() ) { CVehicle *pVehicleSelf = pPedSelf->GetVehicle(); // restore inf NOS if ( pstate_infnos ) { pVehicleSelf->AddVehicleUpgrade( 1010 ); } } // restore "Extra actor invincibility" patch if ( pstate_actor_hp_nSP ) patcher_install( &patch_actor_hp_extraInv ); if ( pstate_actor_hp_SP ) patcher_install( &patch_actor_hp ); // restore vehicle hp patch if ( pstate_vehicle_hp ) patcher_install( &patch_vehicle_hp ); // restore some cheat_states set.d3dtext_hud = pstate_d3dtext_hud; cheat_state->_generic.map = pstate_map; cheat_state->_generic.menu = pstate_generic_menu; // restore patches for ( i = 0; i < INI_PATCHES_MAX; i++ ) { if ( pstate_ini[i] ) patcher_install( &set.patch[i] ); } // restore kill & chat if ( g_DeathList != NULL ) { g_DeathList->iEnabled = pstate_deathlist; } if ( g_Chat != NULL ) { g_Chat->iChatWindowMode = pstate_chat; } // clear cheat state text cheat_state_text( NULL ); } } return cheat_state->_generic.cheat_panic_enabled; }
void CMapManager::SpawnPlayer ( CPlayer& Player, const CVector& vecPosition, float fRotation, unsigned short usModel, unsigned char ucInterior, unsigned short usDimension, CTeam* pTeam ) { // Don't force them off their team if the spawnpoint doesn't have one if ( pTeam == NULL ) pTeam = Player.GetTeam (); ElementID TeamID = ( pTeam ) ? pTeam->GetID () : INVALID_ELEMENT_ID; // Change the time context to avoid old sync packets arriving causing players // to slide from previous location to the new one. unsigned char ucTimeContext = Player.GenerateSyncTimeContext (); // Tell everyone where he spawns m_pPlayerManager->BroadcastOnlyJoined ( CPlayerSpawnPacket ( Player.GetID (), vecPosition, fRotation, usModel, ucInterior, usDimension, TeamID, ucTimeContext ) ); // Remove him from any occupied vehicle CVehicle* pVehicle = Player.GetOccupiedVehicle (); if ( pVehicle ) { pVehicle->SetOccupant ( NULL, Player.GetOccupiedVehicleSeat () ); Player.SetOccupiedVehicle ( NULL, 0 ); } // If this guy was jacking someone, make sure its aborted pVehicle = Player.GetJackingVehicle (); if ( pVehicle ) { if ( Player.GetVehicleAction () == CPlayer::VEHICLEACTION_JACKING ) { CPed * pOccupant = pVehicle->GetOccupant ( 0 ); if ( pOccupant ) { pOccupant->SetVehicleAction ( CPlayer::VEHICLEACTION_NONE ); // Tell everyone CVehicleInOutPacket Reply ( pVehicle->GetID (), 0, CGame::VEHICLE_NOTIFY_JACK_RETURN, pOccupant->GetID (), Player.GetID () ); Reply.SetSourceElement ( &Player ); m_pPlayerManager->BroadcastOnlyJoined ( Reply ); } } if ( pVehicle->GetJackingPlayer () == &Player ) pVehicle->SetJackingPlayer ( NULL ); } // Update the player data Player.SetSpawned ( true ); Player.SetHealth ( Player.GetMaxHealth () ); Player.SetIsDead ( false ); Player.SetWearingGoggles ( false ); Player.SetHasJetPack ( false ); Player.SetPosition ( vecPosition ); Player.SetRotation ( fRotation ); Player.SetModel ( usModel ); Player.SetVehicleAction ( CPlayer::VEHICLEACTION_NONE ); Player.SetTeam ( pTeam, true ); Player.SetInterior ( ucInterior ); Player.SetDimension ( usDimension ); Player.AttachTo ( NULL ); // Call onPlayerSpawn CLuaArguments OnPlayerSpawnArguments; OnPlayerSpawnArguments.PushNumber ( vecPosition.fX ); OnPlayerSpawnArguments.PushNumber ( vecPosition.fY ); OnPlayerSpawnArguments.PushNumber ( vecPosition.fZ ); OnPlayerSpawnArguments.PushNumber ( fRotation ); OnPlayerSpawnArguments.PushElement ( pTeam ); OnPlayerSpawnArguments.PushNumber ( usModel ); OnPlayerSpawnArguments.PushNumber ( ucInterior ); OnPlayerSpawnArguments.PushNumber ( usDimension ); Player.CallEvent ( "onPlayerSpawn", OnPlayerSpawnArguments ); }
CPlayer::~CPlayer ( void ) { // Make sure the script debugger doesn't reference us SetScriptDebugLevel ( 0 ); if ( m_pCamera ) { // Remove the camera from its targets FollowingCameras list if ( m_pCamera->GetTarget () ) m_pCamera->GetTarget ()->m_FollowingCameras.remove ( m_pCamera ); delete m_pCamera; m_pCamera = NULL; } // Make sure nobody's syncing us RemoveAllSyncingVehicles (); RemoveAllSyncingPeds (); RemoveAllSyncingObjects (); // Delete the player text manager delete m_pPlayerTextManager; // Destroy our nick if ( m_szNametagText ) { delete [] m_szNametagText; m_szNametagText = NULL; } SetTeam ( NULL, true ); delete m_pPad; delete m_pKeyBinds; CSimControl::RemoveSimPlayer ( this ); // Unparent us (CElement's unparenting will crash because of the incomplete vtable at that point) m_bDoNotSendEntities = true; SetParentObject ( NULL ); // Do this if ( m_pJackingVehicle ) { if ( m_uiVehicleAction == VEHICLEACTION_JACKING ) { CPed * pOccupant = m_pJackingVehicle->GetOccupant ( 0 ); if ( pOccupant ) { m_pJackingVehicle->SetOccupant ( NULL, 0 ); pOccupant->SetOccupiedVehicle ( NULL, 0 ); pOccupant->SetVehicleAction ( VEHICLEACTION_NONE ); } } if ( m_pJackingVehicle->GetJackingPlayer () == this ) m_pJackingVehicle->SetJackingPlayer ( NULL ); } CElementRefManager::RemoveElementRefs ( ELEMENT_REF_DEBUG ( this, "CPlayer" ), &m_pTeam, NULL ); CElementRefManager::RemoveElementListRef ( ELEMENT_REF_DEBUG ( this, "CPlayer m_lstBroadcastList" ), &m_lstBroadcastList ); CElementRefManager::RemoveElementListRef ( ELEMENT_REF_DEBUG ( this, "CPlayer m_lstIgnoredList" ), &m_lstIgnoredList ); delete m_pPlayerStatsPacket; // Unlink from manager Unlink (); }
bool CEntityAddPacket::Write ( NetBitStreamInterface& BitStream ) const { SPositionSync position ( false ); // Check that we have any entities if ( m_Entities.size () > 0 ) { // Write the number of entities unsigned int NumElements = m_Entities.size (); BitStream.WriteCompressed ( NumElements ); // For each entity ... CVector vecTemp; vector < CElement* > ::const_iterator iter = m_Entities.begin (); for ( ; iter != m_Entities.end (); iter++ ) { // Entity id CElement* pElement = *iter; BitStream.Write ( pElement->GetID () ); // Entity type id unsigned char ucEntityTypeID = static_cast < unsigned char > ( pElement->GetType () ); BitStream.Write ( ucEntityTypeID ); // Entity parent CElement* pParent = pElement->GetParentEntity (); ElementID ParentID = INVALID_ELEMENT_ID; if ( pParent ) ParentID = pParent->GetID (); BitStream.Write ( ParentID ); // Entity interior BitStream.Write ( pElement->GetInterior () ); // Entity dimension BitStream.WriteCompressed ( pElement->GetDimension () ); // Entity attached to CElement* pElementAttachedTo = pElement->GetAttachedToElement (); if ( pElementAttachedTo ) { BitStream.WriteBit ( true ); BitStream.Write ( pElementAttachedTo->GetID () ); // Attached position and rotation SPositionSync attachedPosition ( false ); SRotationDegreesSync attachedRotation ( false ); pElement->GetAttachedOffsets ( attachedPosition.data.vecPosition, attachedRotation.data.vecRotation ); BitStream.Write ( &attachedPosition ); BitStream.Write ( &attachedRotation ); } else BitStream.WriteBit ( false ); // Entity collisions enabled bool bCollisionsEnabled = true; switch ( pElement->GetType() ) { case CElement::VEHICLE: { CVehicle* pVehicle = static_cast < CVehicle* > ( pElement ); bCollisionsEnabled = pVehicle->GetCollisionEnabled ( ); break; } case CElement::OBJECT: { CObject* pObject = static_cast < CObject* > ( pElement ); bCollisionsEnabled = pObject->GetCollisionEnabled ( ); break; } case CElement::PED: case CElement::PLAYER: { CPed* pPed = static_cast < CPed* > ( pElement ); bCollisionsEnabled = pPed->GetCollisionEnabled ( ); break; } } BitStream.WriteBit ( bCollisionsEnabled ); // Write custom data CCustomData* pCustomData = pElement->GetCustomDataPointer (); assert ( pCustomData ); BitStream.WriteCompressed ( pCustomData->CountOnlySynchronized () ); map < string, SCustomData > :: const_iterator iter = pCustomData->IterBegin (); for ( ; iter != pCustomData->IterEnd (); iter++ ) { const char* szName = iter->first.c_str (); const CLuaArgument* pArgument = &iter->second.Variable; bool bSynchronized = iter->second.bSynchronized; if ( bSynchronized ) { unsigned char ucNameLength = static_cast < unsigned char > ( strlen ( szName ) ); BitStream.Write ( ucNameLength ); BitStream.Write ( szName, ucNameLength ); pArgument->WriteToBitStream ( BitStream ); } } // Grab its name char szEmpty [1]; szEmpty [0] = 0; const char* szName = pElement->GetName ().c_str (); if ( !szName ) szName = szEmpty; // Write the name. It can be empty. unsigned short usNameLength = static_cast < unsigned short > ( strlen ( szName ) ); BitStream.WriteCompressed ( usNameLength ); if ( usNameLength > 0 ) { BitStream.Write ( const_cast < char * > ( szName ), usNameLength ); } // Write the sync time context BitStream.Write ( pElement->GetSyncTimeContext () ); // Write the rest depending on the type switch ( ucEntityTypeID ) { case CElement::OBJECT: { CObject* pObject = static_cast < CObject* > ( pElement ); // Position position.data.vecPosition = pObject->GetPosition (); BitStream.Write ( &position ); // Rotation SRotationRadiansSync rotationRadians ( false ); pObject->GetRotation ( rotationRadians.data.vecRotation ); BitStream.Write ( &rotationRadians ); // Object id BitStream.WriteCompressed ( pObject->GetModel () ); // Alpha SEntityAlphaSync alpha; alpha.data.ucAlpha = pObject->GetAlpha (); BitStream.Write ( &alpha ); // Double sided bool bIsDoubleSided = pObject->IsDoubleSided (); BitStream.WriteBit ( bIsDoubleSided ); // Moving const CPositionRotationAnimation* pMoveAnimation = pObject->GetMoveAnimation (); if ( pMoveAnimation ) { BitStream.WriteBit ( true ); pMoveAnimation->ToBitStream ( BitStream, true ); } else { BitStream.WriteBit ( false ); } // Scale float fScale = pObject->GetScale (); BitStream.Write ( fScale ); // Static bool bStatic = pObject->IsStatic (); BitStream.WriteBit ( bStatic ); // Health SObjectHealthSync health; health.data.fValue = pObject->GetHealth (); BitStream.Write ( &health ); break; } case CElement::PICKUP: { CPickup* pPickup = static_cast < CPickup* > ( pElement ); // Position position.data.vecPosition = pPickup->GetPosition (); BitStream.Write ( &position ); // Grab the model and write it unsigned short usModel = pPickup->GetModel (); BitStream.WriteCompressed ( usModel ); // Write if it's visible bool bVisible = pPickup->IsVisible (); BitStream.WriteBit ( bVisible ); // Write the type SPickupTypeSync pickupType; pickupType.data.ucType = pPickup->GetPickupType (); BitStream.Write ( &pickupType ); switch ( pPickup->GetPickupType () ) { case CPickup::ARMOR: { SPlayerArmorSync armor; armor.data.fValue = pPickup->GetAmount (); BitStream.Write ( &armor ); break; } case CPickup::HEALTH: { SPlayerHealthSync health; health.data.fValue = pPickup->GetAmount (); BitStream.Write ( &health ); break; } case CPickup::WEAPON: { SWeaponTypeSync weaponType; weaponType.data.ucWeaponType = pPickup->GetWeaponType (); BitStream.Write ( &weaponType ); SWeaponAmmoSync ammo ( weaponType.data.ucWeaponType, true, false ); ammo.data.usTotalAmmo = pPickup->GetAmmo (); BitStream.Write ( &ammo ); break; } default: break; } break; } case CElement::VEHICLE: { CVehicle* pVehicle = static_cast < CVehicle* > ( pElement ); // Write the vehicle position and rotation position.data.vecPosition = pVehicle->GetPosition (); SRotationDegreesSync rotationDegrees ( false ); pVehicle->GetRotationDegrees ( rotationDegrees.data.vecRotation ); // Write it BitStream.Write ( &position ); BitStream.Write ( &rotationDegrees ); // Vehicle id as a char // I'm assuming the "-400" is for adjustment so that all car values can // fit into a char? Why doesn't someone document this? // // --slush BitStream.Write ( static_cast < unsigned char > ( pVehicle->GetModel () - 400 ) ); // Health SVehicleHealthSync health; health.data.fValue = pVehicle->GetHealth (); BitStream.Write ( &health ); // Color CVehicleColor& vehColor = pVehicle->GetColor (); uchar ucNumColors = vehColor.GetNumColorsUsed () - 1; BitStream.WriteBits ( &ucNumColors, 2 ); for ( uint i = 0 ; i <= ucNumColors ; i++ ) { SColor RGBColor = vehColor.GetRGBColor ( i ); BitStream.Write ( RGBColor.R ); BitStream.Write ( RGBColor.G ); BitStream.Write ( RGBColor.B ); } // Paintjob SPaintjobSync paintjob; paintjob.data.ucPaintjob = pVehicle->GetPaintjob (); BitStream.Write ( &paintjob ); // Write the damage model SVehicleDamageSync damage ( true, true, true, true, false ); memcpy ( damage.data.ucDoorStates, pVehicle->m_ucDoorStates, MAX_DOORS ); memcpy ( damage.data.ucWheelStates, pVehicle->m_ucWheelStates, MAX_WHEELS ); memcpy ( damage.data.ucPanelStates, pVehicle->m_ucPanelStates, MAX_PANELS ); memcpy ( damage.data.ucLightStates, pVehicle->m_ucLightStates, MAX_LIGHTS ); BitStream.Write ( &damage ); // If the vehicle has a turret, send its position too unsigned short usModel = pVehicle->GetModel (); if ( CVehicleManager::HasTurret ( usModel ) ) { SVehicleTurretSync specific; specific.data.fTurretX = pVehicle->GetTurretPositionX (); specific.data.fTurretY = pVehicle->GetTurretPositionY (); BitStream.Write ( &specific ); } // If the vehicle has an adjustable property send its value if ( CVehicleManager::HasAdjustableProperty ( usModel ) ) { BitStream.WriteCompressed ( pVehicle->GetAdjustableProperty () ); } // If the vehicle has doors, sync their open angle ratios. if ( CVehicleManager::HasDoors ( usModel ) ) { SDoorOpenRatioSync door; for ( unsigned char i = 0; i < 6; ++i ) { door.data.fRatio = pVehicle->GetDoorOpenRatio ( i ); BitStream.Write ( &door ); } } // Write all the upgrades CVehicleUpgrades* pUpgrades = pVehicle->GetUpgrades (); unsigned char ucNumUpgrades = pUpgrades->Count (); unsigned short* usSlotStates = pUpgrades->GetSlotStates (); BitStream.Write ( ucNumUpgrades ); if ( ucNumUpgrades > 0 ) { unsigned char ucSlot = 0; for ( ; ucSlot < VEHICLE_UPGRADE_SLOTS ; ucSlot++ ) { unsigned short usUpgrade = usSlotStates [ ucSlot ]; /* * This is another retarded modification in an attempt to save * a byte. We're apparently subtracting 1000 so we can store the * information in a single byte instead of two. This only gives us * a maximum of 256 vehicle slots. * * --slush * -- ChrML: Ehm, GTA only has 17 upgrade slots... This is a valid optimization. */ if ( usUpgrade ) BitStream.Write ( static_cast < unsigned char > ( usSlotStates [ ucSlot ] - 1000 ) ); } } // Get the vehicle's reg plate as 8 bytes of chars with the not used bytes // nulled. const char* cszRegPlate = pVehicle->GetRegPlate (); BitStream.Write ( cszRegPlate, 8 ); // Light override SOverrideLightsSync overrideLights; overrideLights.data.ucOverride = pVehicle->GetOverrideLights (); BitStream.Write ( &overrideLights ); // Grab various vehicle flags BitStream.WriteBit ( pVehicle->IsLandingGearDown () ); BitStream.WriteBit ( pVehicle->IsSirenActive () ); BitStream.WriteBit ( pVehicle->IsFuelTankExplodable () ); BitStream.WriteBit ( pVehicle->IsEngineOn () ); BitStream.WriteBit ( pVehicle->IsLocked () ); BitStream.WriteBit ( pVehicle->AreDoorsUndamageable () ); BitStream.WriteBit ( pVehicle->IsDamageProof () ); BitStream.WriteBit ( pVehicle->IsFrozen () ); BitStream.WriteBit ( pVehicle->IsDerailed () ); BitStream.WriteBit ( pVehicle->IsDerailable () ); BitStream.WriteBit ( pVehicle->GetTrainDirection () ); BitStream.WriteBit ( pVehicle->IsTaxiLightOn () ); // Write alpha SEntityAlphaSync alpha; alpha.data.ucAlpha = pVehicle->GetAlpha (); BitStream.Write ( &alpha ); // Write headlight color SColor color = pVehicle->GetHeadLightColor (); if ( color.R != 255 || color.G != 255 || color.B != 255 ) { BitStream.WriteBit ( true ); BitStream.Write ( color.R ); BitStream.Write ( color.G ); BitStream.Write ( color.B ); } else BitStream.WriteBit ( false ); // Write handling if ( g_pGame->GetHandlingManager()->HasModelHandlingChanged ( static_cast < eVehicleTypes > ( pVehicle->GetModel() ) ) || pVehicle->HasHandlingChanged() ) { BitStream.WriteBit ( true ); SVehicleHandlingSync handling; CHandlingEntry* pEntry = pVehicle->GetHandlingData (); handling.data.fMass = pEntry->GetMass (); handling.data.fTurnMass = pEntry->GetTurnMass (); handling.data.fDragCoeff = pEntry->GetDragCoeff (); handling.data.vecCenterOfMass = pEntry->GetCenterOfMass (); handling.data.ucPercentSubmerged = pEntry->GetPercentSubmerged (); handling.data.fTractionMultiplier = pEntry->GetTractionMultiplier (); handling.data.ucDriveType = pEntry->GetCarDriveType (); handling.data.ucEngineType = pEntry->GetCarEngineType (); handling.data.ucNumberOfGears = pEntry->GetNumberOfGears (); handling.data.fEngineAcceleration = pEntry->GetEngineAcceleration (); handling.data.fEngineInertia = pEntry->GetEngineInertia (); handling.data.fMaxVelocity = pEntry->GetMaxVelocity (); handling.data.fBrakeDeceleration = pEntry->GetBrakeDeceleration (); handling.data.fBrakeBias = pEntry->GetBrakeBias (); handling.data.bABS = pEntry->GetABS (); handling.data.fSteeringLock = pEntry->GetSteeringLock (); handling.data.fTractionLoss = pEntry->GetTractionLoss (); handling.data.fTractionBias = pEntry->GetTractionBias (); handling.data.fSuspensionForceLevel = pEntry->GetSuspensionForceLevel (); handling.data.fSuspensionDamping = pEntry->GetSuspensionDamping (); handling.data.fSuspensionHighSpdDamping = pEntry->GetSuspensionHighSpeedDamping (); handling.data.fSuspensionUpperLimit = pEntry->GetSuspensionUpperLimit (); handling.data.fSuspensionLowerLimit = pEntry->GetSuspensionLowerLimit (); handling.data.fSuspensionFrontRearBias = pEntry->GetSuspensionFrontRearBias (); handling.data.fSuspensionAntiDiveMultiplier = pEntry->GetSuspensionAntiDiveMultiplier (); handling.data.fCollisionDamageMultiplier = pEntry->GetCollisionDamageMultiplier (); handling.data.uiModelFlags = pEntry->GetModelFlags (); handling.data.uiHandlingFlags = pEntry->GetHandlingFlags (); handling.data.fSeatOffsetDistance = pEntry->GetSeatOffsetDistance (); //handling.data.uiMonetary = pEntry->GetMonetary (); //handling.data.ucHeadLight = pEntry->GetHeadLight (); //handling.data.ucTailLight = pEntry->GetTailLight (); handling.data.ucAnimGroup = pEntry->GetAnimGroup (); BitStream.Write ( &handling ); } else BitStream.WriteBit ( false ); break; } case CElement::MARKER: { CMarker* pMarker = static_cast < CMarker* > ( pElement ); // Position position.data.vecPosition = pMarker->GetPosition (); BitStream.Write ( &position ); // Type SMarkerTypeSync markerType; markerType.data.ucType = pMarker->GetMarkerType (); BitStream.Write ( &markerType ); // Size float fSize = pMarker->GetSize (); BitStream.Write ( fSize ); // Colour SColorSync color; color = pMarker->GetColor (); BitStream.Write ( &color ); // Write the target position vector eventually if ( markerType.data.ucType == CMarker::TYPE_CHECKPOINT || markerType.data.ucType == CMarker::TYPE_RING ) { if ( pMarker->HasTarget () ) { BitStream.WriteBit ( true ); position.data.vecPosition = pMarker->GetTarget (); BitStream.Write ( &position ); } else BitStream.WriteBit ( false ); } break; } case CElement::BLIP: { CBlip* pBlip = static_cast < CBlip* > ( pElement ); // Grab the blip position position.data.vecPosition = pBlip->GetPosition (); BitStream.Write ( &position ); // Write the ordering id BitStream.WriteCompressed ( pBlip->m_sOrdering ); // Write the visible distance SIntegerSync < unsigned short, 14 > visibleDistance ( pBlip->m_usVisibleDistance ); BitStream.Write ( &visibleDistance ); // Write the icon SIntegerSync < unsigned char, 6 > icon ( pBlip->m_ucIcon ); BitStream.Write ( &icon ); if ( pBlip->m_ucIcon == 0 ) { // Write the size SIntegerSync < unsigned char, 5 > size ( pBlip->m_ucSize ); BitStream.Write ( &size ); // Write the color SColorSync color; color = pBlip->GetColor (); BitStream.Write ( &color ); } break; } case CElement::RADAR_AREA: { CRadarArea* pArea = static_cast < CRadarArea* > ( pElement ); // Write the position SPosition2DSync position2D ( false ); position2D.data.vecPosition = pArea->GetPosition (); BitStream.Write ( &position2D ); // Write the size SPosition2DSync size2D ( false ); size2D.data.vecPosition = pArea->GetSize (); BitStream.Write ( &size2D ); // And the color SColor color = pArea->GetColor (); BitStream.Write ( color.R ); BitStream.Write ( color.G ); BitStream.Write ( color.B ); BitStream.Write ( color.A ); // Write whether it is flashing bool bIsFlashing = pArea->IsFlashing (); BitStream.WriteBit ( bIsFlashing ); break; } case CElement::WORLD_MESH: { /* CWorldMesh* pMesh = static_cast < CWorldMesh* > ( pElement ); // Write the name char* szName = pMesh->GetName (); unsigned short usNameLength = static_cast < unsigned short > ( strlen ( szName ) ); BitStream.Write ( usNameLength ); BitStream.Write ( szName, static_cast < int > ( usNameLength ) ); // Write the position and rotation CVector vecTemp = pMesh->GetPosition (); BitStream.Write ( vecTemp.fX ); BitStream.Write ( vecTemp.fY ); BitStream.Write ( vecTemp.fZ ); vecTemp = pMesh->GetRotation (); BitStream.Write ( vecTemp.fX ); BitStream.Write ( vecTemp.fY ); BitStream.Write ( vecTemp.fZ ); */ break; } case CElement::TEAM: { CTeam* pTeam = static_cast < CTeam* > ( pElement ); // Write the name char* szTeamName = pTeam->GetTeamName (); unsigned short usNameLength = static_cast < unsigned short > ( strlen ( szTeamName ) ); unsigned char ucRed, ucGreen, ucBlue; pTeam->GetColor ( ucRed, ucGreen, ucBlue ); bool bFriendlyFire = pTeam->GetFriendlyFire (); BitStream.WriteCompressed ( usNameLength ); BitStream.Write ( szTeamName, usNameLength ); BitStream.Write ( ucRed ); BitStream.Write ( ucGreen ); BitStream.Write ( ucBlue ); BitStream.WriteBit ( bFriendlyFire ); break; } case CElement::PED: { CPed* pPed = static_cast < CPed* > ( pElement ); // position position.data.vecPosition = pPed->GetPosition (); BitStream.Write ( &position ); // model unsigned short usModel = pPed->GetModel (); BitStream.WriteCompressed ( usModel ); // rotation SPedRotationSync pedRotation; pedRotation.data.fRotation = pPed->GetRotation (); BitStream.Write ( &pedRotation ); // health SPlayerHealthSync health; health.data.fValue = pPed->GetHealth (); BitStream.Write ( &health ); // Armor SPlayerArmorSync armor; armor.data.fValue = pPed->GetArmor (); BitStream.Write ( &armor ); // vehicle CVehicle * pVehicle = pPed->GetOccupiedVehicle (); if ( pVehicle ) { BitStream.WriteBit ( true ); BitStream.Write ( pVehicle->GetID () ); SOccupiedSeatSync seat; seat.data.ucSeat = pPed->GetOccupiedVehicleSeat (); BitStream.Write ( &seat ); } else BitStream.WriteBit ( false ); // flags BitStream.WriteBit ( pPed->HasJetPack () ); BitStream.WriteBit ( pPed->IsSyncable () ); BitStream.WriteBit ( pPed->IsHeadless () ); BitStream.WriteBit ( pPed->IsFrozen () ); // alpha SEntityAlphaSync alpha; alpha.data.ucAlpha = pPed->GetAlpha (); BitStream.Write ( &alpha ); // clothes unsigned char ucNumClothes = 0; CPlayerClothes* pClothes = pPed->GetClothes ( ); for ( unsigned char ucType = 0 ; ucType < PLAYER_CLOTHING_SLOTS ; ucType++ ) { SPlayerClothing* pClothing = pClothes->GetClothing ( ucType ); if ( pClothing ) { ucNumClothes++; } } BitStream.Write ( ucNumClothes ); for ( unsigned char ucType = 0 ; ucType < PLAYER_CLOTHING_SLOTS ; ucType++ ) { SPlayerClothing* pClothing = pClothes->GetClothing ( ucType ); if ( pClothing ) { unsigned char ucTextureLength = strlen ( pClothing->szTexture ); unsigned char ucModelLength = strlen ( pClothing->szModel ); BitStream.Write ( ucTextureLength ); BitStream.Write ( pClothing->szTexture, ucTextureLength ); BitStream.Write ( ucModelLength ); BitStream.Write ( pClothing->szModel, ucModelLength ); BitStream.Write ( ucType ); } } break; } case CElement::DUMMY: { CDummy* pDummy = static_cast < CDummy* > ( pElement ); // Type Name const char* szTypeName = pDummy->GetTypeName ().c_str (); unsigned short usTypeNameLength = static_cast < unsigned short > ( strlen ( szTypeName ) ); BitStream.WriteCompressed ( usTypeNameLength ); BitStream.Write ( const_cast < char* > ( szTypeName ), usTypeNameLength ); // Position position.data.vecPosition = pDummy->GetPosition(); if ( position.data.vecPosition != CVector ( 0.0f, 0.0f, 0.0f ) ) { BitStream.WriteBit ( true ); BitStream.Write ( &position ); } else BitStream.WriteBit ( false ); break; } case CElement::PLAYER: { break; } case CElement::SCRIPTFILE: { // No extra data break; } case CElement::COLSHAPE: { CColShape* pColShape = static_cast < CColShape* > ( pElement ); if ( !pColShape->GetParentEntity () ) { // Jax: i'm pretty sure this is f*****g up our packet somehow.. // all valid col-shapes should have a parent! assert ( false ); } // Type SColshapeTypeSync colType; colType.data.ucType = static_cast < unsigned char > ( pColShape->GetShapeType () ); BitStream.Write ( &colType ); // Position position.data.vecPosition = pColShape->GetPosition (); BitStream.Write ( &position ); // Enabled BitStream.WriteBit ( pColShape->IsEnabled () ); // Auto Call Event BitStream.WriteBit ( pColShape->GetAutoCallEvent () ); switch ( pColShape->GetShapeType () ) { case COLSHAPE_CIRCLE: { BitStream.Write ( static_cast < CColCircle* > ( pColShape )->GetRadius () ); break; } case COLSHAPE_CUBOID: { SPositionSync size ( false ); size.data.vecPosition = static_cast < CColCuboid* > ( pColShape )->GetSize (); BitStream.Write ( &size ); break; } case COLSHAPE_SPHERE: { BitStream.Write ( static_cast < CColSphere* > ( pColShape )->GetRadius () ); break; } case COLSHAPE_RECTANGLE: { SPosition2DSync size ( false ); size.data.vecPosition = static_cast < CColRectangle* > ( pColShape )->GetSize (); BitStream.Write ( &size ); break; } case COLSHAPE_TUBE: { BitStream.Write ( static_cast < CColTube* > ( pColShape )->GetRadius () ); BitStream.Write ( static_cast < CColTube* > ( pColShape )->GetHeight () ); break; } case COLSHAPE_POLYGON: { CColPolygon* pPolygon = static_cast < CColPolygon* > ( pColShape ); BitStream.WriteCompressed ( pPolygon->CountPoints() ); std::vector < CVector2D > ::const_iterator iter = pPolygon->IterBegin(); for ( ; iter != pPolygon->IterEnd () ; iter++ ) { SPosition2DSync vertex ( false ); vertex.data.vecPosition = *iter; BitStream.Write ( &vertex ); } break; } default: break; } break; } case CElement::WATER: { CWater* pWater = static_cast < CWater* > ( pElement ); unsigned char ucNumVertices = (unsigned char)pWater->GetNumVertices (); BitStream.Write ( ucNumVertices ); CVector vecVertex; for ( int i = 0; i < ucNumVertices; i++ ) { pWater->GetVertex ( i, vecVertex ); BitStream.Write ( (short)vecVertex.fX ); BitStream.Write ( (short)vecVertex.fY ); BitStream.Write ( vecVertex.fZ ); } break; } default: { assert ( 0 ); CLogger::LogPrintf ( "not sending this element - id: %i\n", pElement->GetType () ); } } } // Success return true; } return false; }
void CPedSync::Packet_PedSync ( CPedSyncPacket& Packet ) { // Grab the player CPlayer* pPlayer = Packet.GetSourcePlayer (); if ( pPlayer && pPlayer->IsJoined () ) { // Apply the data for each ped in the packet vector < CPedSyncPacket::SyncData* > ::const_iterator iter = Packet.IterBegin (); for ( ; iter != Packet.IterEnd (); iter++ ) { CPedSyncPacket::SyncData* pData = *iter; // Grab the ped this packet is for CElement* pPedElement = CElementIDs::GetElement ( pData->Model ); if ( pPedElement && IS_PED ( pPedElement ) ) { // Convert to a CPed CPed* pPed = static_cast < CPed* > ( pPedElement ); // Is the player syncing this ped? // this packet if the time context matches. if ( pPed->GetSyncer () == pPlayer && pPed->CanUpdateSync ( pData->ucSyncTimeContext ) ) { // Apply the data to the ped if ( pData->ucFlags & 0x01 ) { pPed->SetPosition ( pData->vecPosition ); g_pGame->GetColManager()->DoHitDetection ( pPed->GetLastPosition (), pPed->GetPosition (), 0.0f, pPed ); } if ( pData->ucFlags & 0x02 ) pPed->SetRotation ( pData->fRotation ); if ( pData->ucFlags & 0x04 ) pPed->SetVelocity ( pData->vecVelocity ); if ( pData->ucFlags & 0x08 ) { // Less health than last time? float fPreviousHealth = pPed->GetHealth (); pPed->SetHealth ( pData->fHealth ); if ( pData->fHealth < fPreviousHealth ) { // Grab the delta health float fDeltaHealth = fPreviousHealth - pData->fHealth; if ( fDeltaHealth > 0.0f ) { // Call the onPedDamage event CLuaArguments Arguments; Arguments.PushNumber ( fDeltaHealth ); pPed->CallEvent ( "onPedDamage", Arguments ); } } } if ( pData->ucFlags & 0x10 ) pPed->SetArmor ( pData->fArmor ); // Send this sync pData->bSend = true; } } } // Tell everyone m_pPlayerManager->BroadcastOnlyJoined ( Packet, pPlayer ); } }