LabelId C3DLabelManager::Add(const String& text, const CVector3& vecPosition, DWORD dwColor, bool bVisible, float fStreamingDistance) { for(LabelId i = 0; i < MAX_3D_LABELS; i++) { if(!DoesExist(i)) { m_Labels[i] = new C3DLabel(i, text, vecPosition, dwColor, bVisible, fStreamingDistance); m_Labels[i]->SetText(text); m_Labels[i]->SetPosition(vecPosition); m_Labels[i]->SetVisible(true); CBitStream bsSend; bsSend.WriteCompressed(i); bsSend.Write(m_Labels[i]->GetText()); bsSend.Write(m_Labels[i]->GetPosition()); bsSend.Write(m_Labels[i]->GetColor()); bsSend.Write(m_Labels[i]->GetStreamingDistance()); bsSend.Write(m_Labels[i]->GetDimension()); bsSend.WriteBit(m_Labels[i]->IsVisible()); g_pNetworkManager->RPC(RPC_New3DLabel, &bsSend, PRIORITY_HIGH, RELIABILITY_RELIABLE_ORDERED, INVALID_ENTITY_ID, true); return i; } } return MAX_3D_LABELS; /* INVALID ID */ }
void CVehicle::SetComponentState(unsigned char ucSlot, bool bOn) { if(ucSlot >= 0 && ucSlot <= 8) { if(m_bComponents[ucSlot] != bOn) { m_bComponents[ucSlot] = bOn; CBitStream bsSend; bsSend.Write(m_vehicleId); for(int i = 0; i < 9; ++ i) bsSend.WriteBit(m_bComponents[i]); g_pNetworkManager->RPC(RPC_ScriptingSetVehicleComponents, &bsSend, PRIORITY_HIGH, RELIABILITY_RELIABLE_ORDERED, INVALID_ENTITY_ID, true); } } }
void C3DLabelManager::HandleClientJoin(EntityId playerId) { for(LabelId i = 0; i < MAX_3D_LABELS; i++) { if(DoesExist(i)) { CBitStream bsSend; bsSend.WriteCompressed(i); bsSend.Write(m_Labels[i]->GetText()); bsSend.Write(m_Labels[i]->GetPosition()); bsSend.Write(m_Labels[i]->GetColor()); bsSend.Write(m_Labels[i]->GetStreamingDistance()); bsSend.Write(m_Labels[i]->GetDimension()); bsSend.WriteBit(m_Labels[i]->IsVisible()); g_pNetworkManager->RPC(RPC_New3DLabel, &bsSend, PRIORITY_HIGH, RELIABILITY_RELIABLE_ORDERED, playerId, false); } } }
void CServerRPCHandler::VehicleEnterExit(CBitStream * pBitStream, CPlayerSocket senderSocket) { CLogFile::Printf("Got VehicleEnterExit RPC from player %d", senderSocket.playerId); // Ensure we have a valid bitstream if(!pBitStream) { CLogFile::Printf("Warning: Invalid bitstream for VehicleEnterExit RPC"); return; } // Get the player pointer CPlayer * pPlayer = g_pServer->GetPlayerManager()->Get(senderSocket.playerId); // Is the player pointer valid? if(pPlayer) { // Read the vehicle entry/exit type BYTE byteVehicleEntryExitType; if(!pBitStream->Read(byteVehicleEntryExitType)) return; // Read the vehicle id EntityId vehicleId; if(!pBitStream->ReadCompressed(vehicleId)) return; // Get the vehicle CVehicle * pVehicle = g_pServer->GetVehicleManager()->Get(vehicleId); // Does the vehicle not exist? if(!pVehicle) return; // Is this an entry request? if(byteVehicleEntryExitType == VEHICLE_ENTRY_REQUEST) { // Read the seat id BYTE byteSeatId; if(!pBitStream->Read(byteSeatId)) return; // Get the reply CSquirrelArguments arguments; arguments.push(vehicleId); arguments.push(byteSeatId); bool bReply = pPlayer->CallEvent("vehicleEntryRequest", &arguments); // Reply to the vehicle entry request CBitStream bitStream; bitStream.WriteCompressed(senderSocket.playerId); bitStream.WriteBit(bReply); // Was the reply ok? if(bReply) { bitStream.Write((BYTE)VEHICLE_ENTRY_RETURN); bitStream.Write(vehicleId); bitStream.Write(byteSeatId); g_pServer->GetNetworkManager()->RPC(RPC_VEHICLE_ENTER_EXIT, &bitStream, PRIORITY_HIGH, RELIABILITY_RELIABLE, INVALID_ENTITY_ID, true); } } // Is this an entry cancellation? if(byteVehicleEntryExitType == VEHICLE_ENTRY_CANCELLED) { // Read the seat id BYTE byteSeatId; if(!pBitStream->Read(byteSeatId)) return; // Call the event CSquirrelArguments arguments; arguments.push(vehicleId); arguments.push(byteSeatId); pPlayer->CallEvent("vehicleEntryCancelled", &arguments); CBitStream bitStream; bitStream.WriteCompressed(senderSocket.playerId); bitStream.WriteBit(true); bitStream.Write((BYTE)VEHICLE_ENTRY_CANCELLED); bitStream.Write(vehicleId); g_pServer->GetNetworkManager()->RPC(RPC_VEHICLE_ENTER_EXIT, &bitStream, PRIORITY_HIGH, RELIABILITY_RELIABLE, senderSocket.playerId, true); } // Is this an entry completion? else if(byteVehicleEntryExitType == VEHICLE_ENTRY_COMPLETE) { // Read the seat id BYTE byteSeatId; if(!pBitStream->Read(byteSeatId)) return; // Call the event CSquirrelArguments arguments; arguments.push(vehicleId); arguments.push(byteSeatId); pPlayer->CallEvent("vehicleEntryComplete", &arguments); // Set the player vehicle and seat id pPlayer->SetVehicle(pVehicle); pPlayer->SetVehicleSeatId(byteSeatId); // Set the vehicle occupant pVehicle->SetOccupant(byteSeatId, pPlayer); } // Is this an exit request? else if(byteVehicleEntryExitType == VEHICLE_EXIT_REQUEST) { // Get the reply CSquirrelArguments arguments; arguments.push(vehicleId); bool bReply = pPlayer->CallEvent("vehicleExitRequest", &arguments); // Reply to the vehicle exit request CBitStream bitStream; bitStream.WriteCompressed(senderSocket.playerId); bitStream.WriteBit(bReply); // Was the reply ok? if(bReply) { bitStream.Write((BYTE)VEHICLE_EXIT_RETURN); bitStream.Write(vehicleId); g_pServer->GetNetworkManager()->RPC(RPC_VEHICLE_ENTER_EXIT, &bitStream, PRIORITY_HIGH, RELIABILITY_RELIABLE, INVALID_ENTITY_ID, true); } } // Is this an exit completion? else if(byteVehicleEntryExitType == VEHICLE_EXIT_COMPLETE) { // Call the event CSquirrelArguments arguments; arguments.push(vehicleId); arguments.push(pPlayer->GetVehicleSeatId()); pPlayer->CallEvent("vehicleExitComplete", &arguments); // Reset the vehicle occupant pVehicle->SetOccupant(pPlayer->GetVehicleSeatId(), NULL); // Reset the player vehicle and seat id pPlayer->SetVehicle(NULL); pPlayer->SetVehicleSeatId(0); } // Is this a forceful exit? else if(byteVehicleEntryExitType == VEHICLE_EXIT_FORCEFUL) { // Call the event CSquirrelArguments arguments; arguments.push(vehicleId); arguments.push(pPlayer->GetVehicleSeatId()); pPlayer->CallEvent("vehicleForcefulExit", &arguments); // Reset the vehicle occupant pVehicle->SetOccupant(pPlayer->GetVehicleSeatId(), NULL); // Reset the player vehicle and seat id pPlayer->SetVehicle(NULL); pPlayer->SetVehicleSeatId(0); } } }
void CServerRPCHandler::VehicleEnterExit(CBitStream * pBitStream, CPlayerSocket * pSenderSocket) { // Ensure we have a valid bit stream if(!pBitStream) return; EntityId playerId; if(!pBitStream->ReadCompressed(playerId)) return; // Check the host if(playerId != pSenderSocket->GetPlayerId()) return; // Get the player pointer CPlayer * pPlayer = g_pPlayerManager->GetAt(playerId); // Is the player pointer valid? if(pPlayer) { // Read the vehicle entry/exit type BYTE byteVehicleEntryExitType; if(!pBitStream->Read(byteVehicleEntryExitType)) return; // Read the vehicle id EntityId vehicleId; if(!pBitStream->ReadCompressed(vehicleId)) return; // Get the vehicle CVehicle * pVehicle = g_pVehicleManager->GetAt(vehicleId); // Does the vehicle not exist? if(!pVehicle) return; // Is this an entry request? if(byteVehicleEntryExitType == VEHICLE_ENTRY_REQUEST) { // Read the seat id BYTE byteSeatId; if(!pBitStream->Read(byteSeatId)) return; bool bReply = true; // Is the vehicle fully locked? if(pVehicle->GetLocked() == 1) bReply = false; else { // Get the reply CSquirrelArguments arguments; arguments.push(playerId); arguments.push(vehicleId); arguments.push(byteSeatId); bReply = (g_pEvents->Call("vehicleEntryRequest", &arguments).GetInteger() == 1); } // Reply to the vehicle entry request CBitStream bitStream; bitStream.WriteCompressed(playerId); bitStream.WriteBit(bReply); //-Was the reply ok? if(bReply) { bitStream.Write((BYTE)VEHICLE_ENTRY_RETURN); bitStream.Write(vehicleId); bitStream.Write(byteSeatId); // Set the player state pPlayer->SetState(STATE_TYPE_ENTERVEHICLE); } g_pNetworkManager->RPC(RPC_VehicleEnterExit, &bitStream, PRIORITY_HIGH, RELIABILITY_RELIABLE, INVALID_ENTITY_ID, true); } // Is this an entry cancellation? if(byteVehicleEntryExitType == VEHICLE_ENTRY_CANCELLED) { // Read the seat id BYTE byteSeatId; if(!pBitStream->Read(byteSeatId)) return; // Call the event CSquirrelArguments arguments; arguments.push(playerId); arguments.push(vehicleId); arguments.push(byteSeatId); g_pEvents->Call("vehicleEntryCancelled", &arguments); CBitStream bitStream; bitStream.WriteCompressed(playerId); bitStream.WriteBit(true); bitStream.Write((BYTE)VEHICLE_ENTRY_CANCELLED); bitStream.Write(vehicleId); g_pNetworkManager->RPC(RPC_VehicleEnterExit, &bitStream, PRIORITY_HIGH, RELIABILITY_RELIABLE, pSenderSocket->playerId, true); // Set the player state pPlayer->SetState(STATE_TYPE_ONFOOT); } // Is this an entry completion? else if(byteVehicleEntryExitType == VEHICLE_ENTRY_COMPLETE) { // Read the seat id BYTE byteSeatId; if(!pBitStream->Read(byteSeatId)) return; // Call the event CSquirrelArguments arguments; arguments.push(playerId); arguments.push(vehicleId); arguments.push(byteSeatId); g_pEvents->Call("vehicleEntryComplete", &arguments); // Set the player vehicle and seat id pPlayer->SetVehicle(pVehicle); pPlayer->SetVehicleSeatId(byteSeatId); // Set the vehicle occupant pVehicle->SetOccupant(byteSeatId, pPlayer); // Set the player state pPlayer->SetState(STATE_TYPE_INVEHICLE); } // Is this an exit request? else if(byteVehicleEntryExitType == VEHICLE_EXIT_REQUEST) { // Get the reply CSquirrelArguments arguments; arguments.push(playerId); arguments.push(vehicleId); arguments.push(pPlayer->GetVehicleSeatId()); bool bReply = (g_pEvents->Call("vehicleExitRequest", &arguments).GetInteger() == 1); // Reply to the vehicle exit request CBitStream bitStream; bitStream.WriteCompressed(playerId); bitStream.WriteBit(bReply); // Was the reply ok? if(bReply) { bitStream.Write((BYTE)VEHICLE_EXIT_RETURN); bitStream.Write(vehicleId); // Set the player state pPlayer->SetState(STATE_TYPE_EXITVEHICLE); } g_pNetworkManager->RPC(RPC_VehicleEnterExit, &bitStream, PRIORITY_HIGH, RELIABILITY_RELIABLE, INVALID_ENTITY_ID, true); } // Is this an exit completion? else if(byteVehicleEntryExitType == VEHICLE_EXIT_COMPLETE) { // Call the event CSquirrelArguments arguments; arguments.push(playerId); arguments.push(vehicleId); arguments.push(pPlayer->GetVehicleSeatId()); g_pEvents->Call("vehicleExitComplete", &arguments); // Reset the vehicle occupant pVehicle->SetOccupant(pPlayer->GetVehicleSeatId(), NULL); // Reset the player vehicle and seat id pPlayer->SetVehicle(NULL); pPlayer->SetVehicleSeatId(0); // Set the player state pPlayer->SetState(STATE_TYPE_ONFOOT); } // Is this a forceful exit? else if(byteVehicleEntryExitType == VEHICLE_EXIT_FORCEFUL) { // Call the event CSquirrelArguments arguments; arguments.push(playerId); arguments.push(vehicleId); arguments.push(pPlayer->GetVehicleSeatId()); g_pEvents->Call("vehicleForcefulExit", &arguments); // Reset the vehicle occupant pVehicle->SetOccupant(pPlayer->GetVehicleSeatId(), NULL); // Reset the player vehicle and seat id pPlayer->SetVehicle(NULL); pPlayer->SetVehicleSeatId(0); // Set the player state pPlayer->SetState(STATE_TYPE_ONFOOT); } } }
void CServerRPCHandler::PlayerConnect(CBitStream * pBitStream, CPlayerSocket * pSenderSocket) { // Ensure we have a valid bit stream if(!pBitStream) return; // Read packet data EntityId playerId = pSenderSocket->playerId; int iVersion; pBitStream->Read(iVersion); String strName; pBitStream->Read(strName); CheckGTAFiles pCheckFiles; bool bGameFilesModded = false; pBitStream->Read((char *)&pCheckFiles, sizeof(CheckGTAFiles)); if(pCheckFiles.bGTAFileChecksum || pCheckFiles.bHandleFileChanged) { if(CVAR_GET_BOOL("checkGTAFiles")) CLogFile::Printf("[FileCheckSum] Warning, detected modded GTA IV files at player %s", strName.Get()); bGameFilesModded = true; } // Apply serial and ip String strIP = pSenderSocket->GetAddress(true); String strSerial = pSenderSocket->GetSerial(); // Setup our reply packet CBitStream bsSend; // Check for matching network versions if(iVersion != NETWORK_VERSION) { bsSend.Write(REFUSE_REASON_INVALID_VERSION); g_pNetworkManager->RPC(RPC_ConnectionRefused, &bsSend, PRIORITY_HIGH, RELIABILITY_RELIABLE, playerId, false); CLogFile::Printf("[Connect] Authorization for %s (%s) failed (Invalid version (Client: %x, Server: %x))!", strIP.Get(), strName.Get(), iVersion, NETWORK_VERSION); return; } // Check that their name is valid if(strName.IsEmpty() || strName.GetLength() > MAX_NAME_LENGTH) { bsSend.Write(REFUSE_REASON_NAME_INVALID); g_pNetworkManager->RPC(RPC_ConnectionRefused, &bsSend, PRIORITY_HIGH, RELIABILITY_RELIABLE, playerId, false); CLogFile::Printf("[Connect] Authorization for %s (%s) failed (name invalid).", strIP.Get(), strName.Get()); return; } // Check that their name is not already in use if(g_pPlayerManager->IsNameInUse(strName)) { bsSend.Write(REFUSE_REASON_NAME_IN_USE); g_pNetworkManager->RPC(RPC_ConnectionRefused, &bsSend, PRIORITY_HIGH, RELIABILITY_RELIABLE, playerId, false); CLogFile::Printf("[Connect] Authorization for %s (%s) failed (name in use).", strIP.Get(), strName.Get()); return; } CSquirrelArguments nameCheckArguments; nameCheckArguments.push(playerId); nameCheckArguments.push(strName); if(g_pEvents->Call("playerNameCheck", &nameCheckArguments).GetInteger() != 1) { bsSend.Write(REFUSE_REASON_NAME_INVALID); g_pNetworkManager->RPC(RPC_ConnectionRefused, &bsSend, PRIORITY_HIGH, RELIABILITY_RELIABLE, playerId, false); CLogFile::Printf("[Connect] Authorization for %s (%s) failed (name invalid).", strIP.Get(), strName.Get()); return; } // Call the playerAuth event, and process the return value CSquirrelArguments playerAuthArguments; playerAuthArguments.push(playerId); playerAuthArguments.push(strName); playerAuthArguments.push(strIP); playerAuthArguments.push(strSerial); playerAuthArguments.push(bGameFilesModded); if(g_pEvents->Call("playerAuth", &playerAuthArguments).GetInteger() != 1) { bsSend.Write(REFUSE_REASON_ABORTED_BY_SCRIPT); g_pNetworkManager->RPC(RPC_ConnectionRefused, &bsSend, PRIORITY_HIGH, RELIABILITY_RELIABLE, playerId, false); CLogFile::Printf("[Connect] Authorization for %s (%s) failed (aborted by script).", strIP.Get(), strName.Get()); return; } CLogFile::Printf("[Connect] Authorization for %s (%s) complete.", strIP.Get(), strName.Get()); // Setup the player g_pPlayerManager->Add(playerId, strName); CPlayer * pPlayer = g_pPlayerManager->GetAt(playerId); // Check player creation if(!pPlayer) { CLogFile::Printf("[Connect] Failed to create player instance for %s.", strName.Get()); return; } // Apply files pPlayer->SetFileCheck(pCheckFiles); // Let the vehicle manager handle the client join g_pVehicleManager->HandleClientJoin(playerId); // Let the player manager handle the client join g_pPlayerManager->HandleClientJoin(playerId); // Let the object manager handle the client join g_pObjectManager->HandleClientJoin(playerId); // Let the fire manager handle the client join g_pObjectManager->HandleClientJoinFire(playerId); // Let the blip manager handle the client join g_pBlipManager->HandleClientJoin(playerId); // Let the checkpoint manager handle the client join g_pCheckpointManager->HandleClientJoin(playerId); // Let the pickup manager handle the client join g_pPickupManager->HandleClientJoin(playerId); // Let the actor manager handle the client join g_pActorManager->HandleClientJoin(playerId); g_p3DLabelManager->HandleClientJoin(playerId); // Construct the reply bit stream bsSend.Write(playerId); bsSend.Write(CVAR_GET_STRING("hostname")); bsSend.WriteBit(CVAR_GET_BOOL("paynspray")); bsSend.WriteBit(CVAR_GET_BOOL("autoaim")); bsSend.Write(pPlayer->GetColor()); bsSend.Write(CVAR_GET_STRING("httpserver")); bsSend.Write((unsigned short)CVAR_GET_INTEGER("httpport")); bsSend.Write((unsigned char)CVAR_GET_INTEGER("weather")); bsSend.WriteBit(CVAR_GET_BOOL("guinametags")); bsSend.WriteBit(CVAR_GET_BOOL("vehicledamage")); bsSend.WriteBit(CVAR_GET_BOOL("vehiclewaterdeath")); bsSend.WriteBit(CVAR_GET_BOOL("headmovement")); bsSend.Write(CVAR_GET_INTEGER("maxplayers")); // Time unsigned char ucHour = 0, ucMinute = 0; g_pTime->GetTime(&ucHour, &ucMinute); bsSend.Write((unsigned char)(ucHour + (24 * (1 + g_pTime->GetDayOfWeek())))); bsSend.Write(ucMinute); if(g_pTime->GetMinuteDuration() != CTime::DEFAULT_MINUTE_DURATION) { bsSend.Write1(); bsSend.Write(g_pTime->GetMinuteDuration()); } else bsSend.Write0(); // Traffic Lights bsSend.Write((unsigned char)g_pTrafficLights->GetSetState()); bsSend.Write(g_pTrafficLights->GetTimeThisCylce()); if(g_pTrafficLights->GetSetState() != CTrafficLights::TRAFFIC_LIGHT_STATE_DISABLED_DISABLED) { if(g_pTrafficLights->IsLocked()) bsSend.Write1(); else bsSend.Write0(); if(!g_pTrafficLights->IsUsingDefaultDurations()) { bsSend.Write1(); if(g_pTrafficLights->GetSetState() >= CTrafficLights::TRAFFIC_LIGHT_STATE_FLASHING_FLASHING) bsSend.Write(g_pTrafficLights->GetYellowDuration()); else { bsSend.Write(g_pTrafficLights->GetGreenDuration()); bsSend.Write(g_pTrafficLights->GetYellowDuration()); bsSend.Write(g_pTrafficLights->GetRedDuration()); } } else bsSend.Write0(); } // Send the joined game RPC g_pNetworkManager->RPC(RPC_JoinedGame, &bsSend, PRIORITY_HIGH, RELIABILITY_RELIABLE_ORDERED, playerId, false); // Inform the resource file manager of the client join g_pClientResourceFileManager->HandleClientJoin(playerId); // Inform the script file manager of the client join g_pClientScriptFileManager->HandleClientJoin(playerId); CLogFile::Printf("[Join] %s (%d) is joining the game.", strName.Get(), playerId); CSquirrelArguments playerConnectArguments; playerConnectArguments.push(playerId); playerConnectArguments.push(strName); g_pEvents->Call("playerConnect", &playerConnectArguments); }
void CVehicle::SpawnForPlayer(EntityId playerId) { CBitStream bsSend; bsSend.WriteCompressed(m_vehicleId); bsSend.Write(m_iModelId); bsSend.Write(m_uiHealth); bsSend.Write(m_fPetrolTankHealth); bsSend.Write(m_vecPosition); if(!m_vecRotation.IsEmpty()) { bsSend.Write1(); bsSend.Write(m_vecRotation); } else bsSend.Write0(); if(!m_vecTurnSpeed.IsEmpty()) { bsSend.Write1(); bsSend.Write(m_vecTurnSpeed); } else bsSend.Write0(); if(!m_vecMoveSpeed.IsEmpty()) { bsSend.Write1(); bsSend.Write(m_vecMoveSpeed); } else bsSend.Write0(); bsSend.Write(m_iRespawnDelay); bsSend.Write((char *)m_byteColors, sizeof(m_byteColors)); bsSend.Write(m_fDirtLevel); for(int i = 0; i < 4; ++ i) bsSend.WriteBit(m_bIndicatorState[i]); for(int i = 0; i < 9; ++ i) bsSend.WriteBit(m_bComponents[i]); bsSend.Write(m_iHornDuration); bsSend.Write(m_bSirenState); bsSend.Write(m_iLocked); bsSend.Write(m_bEngineStatus); bsSend.Write(m_bLights); for(int i = 0; i < 6; i++) bsSend.Write(m_fDoor[i]); for(int i = 0; i < 4; i++) bsSend.Write(m_bWindow[i]); bsSend.Write(m_bTaxiLight); bsSend.Write(m_bGpsState); if(m_ucVariation != 0) { bsSend.Write1(); bsSend.Write(m_ucVariation); } else bsSend.Write0(); g_pNetworkManager->RPC(RPC_NewVehicle, &bsSend, PRIORITY_HIGH, RELIABILITY_RELIABLE_ORDERED, playerId, false); // Mark vehicle as actor vehicle bsSend.Reset(); bsSend.Write(m_vehicleId); bsSend.Write(m_bActorVehicle); g_pNetworkManager->RPC(RPC_ScriptingMarkVehicleAsActorVehicle, &bsSend, PRIORITY_HIGH, RELIABILITY_RELIABLE_ORDERED, playerId, false); SetColors(m_byteColors[0],m_byteColors[1],m_byteColors[2],m_byteColors[3]); }
void CVehicle::ResetComponents(bool bNotify) { memset(&m_bComponents, 0, sizeof(m_bComponents)); // Make sure some default components are added (they can be removed) switch(m_iModelId) { case 4: // Benson case 51: // Mule case 85: // Steed case 104: // Yankee m_bComponents[0] = true; // missing half of it otherwise, could chose anything from 0 on break; case 6: // Blista case 26: // Faction case 76: // Ruiner case 87: // Stratum m_bComponents[1] = true; // Roof window break; case 13: // Cabby m_bComponents[5] = true; // Taxi sign break; case 35: // Futo m_bComponents[0] = true; // driver seat break; case 52: // Noose case 63: // Police case 64: // Police 2 m_bComponents[0] = true; // Sirens break; case 89: // Sultan m_bComponents[1] = true; // Air vent break; case 92: // Taxi case 93: // Taxi 2 m_bComponents[4] = true; // Taxi sign break; case 98: // Vigero (trashed) m_bComponents[2] = true; break; case 105: // Freeway case 109: // PCJ m_bComponents[0] = true; // Tank m_bComponents[6] = true; // Exhaust break; case 108: // NRG m_bComponents[3] = true; // Body m_bComponents[7] = true; // Exhaust break; case 112: // Annihilator case 113: // Maverick case 114: // Police Maverick case 115: // Heli-Tours Maverick m_bComponents[0] = true; // Rotor blades break; case 123: // Tropic m_bComponents[4] = true; break; } if(bNotify) { CBitStream bsSend; bsSend.Write(m_vehicleId); for(int i = 0; i < 9; ++ i) bsSend.WriteBit(m_bComponents[i]); g_pNetworkManager->RPC(RPC_ScriptingSetVehicleComponents, &bsSend, PRIORITY_HIGH, RELIABILITY_RELIABLE_ORDERED, INVALID_ENTITY_ID, true); } }