diff --git a/.gitattributes b/.gitattributes index 13519b5..2125666 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,26 +1 @@ -*.cpp text eol=crlf -*.c text eol=crlf -*.h text eol=crlf -*.inl text eol=crlf -*.rc text eol=crlf -*.rc2 text eol=crlf -*.dsp text eol=crlf -*.clw text eol=crlf -*.dsw text eol=crlf -*.sln text eol=crlf -*.vcproj text eol=crlf -*.txt text eol=crlf -*.pas text eol=crlf -*.dfm binary - -Makefile text eol=crlf -Makefile.am text eol=crlf - -archive/files/*.cfg text eol=crlf -archive/files/*.ini text eol=crlf -archive/files/*.dat text eol=crlf -archive/files/*.ide text eol=crlf -archive/files/*.bin binary -archive/files/*.txd binary -archive/files/*.png binary -archive/files/*.scm binary +* text=auto \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..f214cb1 --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +# San Andreas Multiplayer +This is an ongoing matching decompilation of the 0.3.7 version of San Andreas Multiplayer. +## Status +- [ ] **samp.exe** - Mostly decompiled. Not matching due to issues with PACKAGEINFO. +- [ ] **samp.dll** - Incomplete. +- [x] **rcon.exe** - Fully decompiled. +- [x] **samp_debug.exe** - Fully decompiled. +- [ ] **samp-server.exe** - Incomplete. +- [ ] **samp03svr** - Incomplete. +- [x] **announce.exe** - Fully decompiled. +- [ ] **announce** - System and the GCC version not have been determined. +- [ ] **samp-npc.exe** - Incomplete. +- [ ] **samp-npc** - Incomplete. + +## Building +### Requirements +- A clean virtual machine with Windows XP installed +- Microsoft Visual C++ 6.0 +- Microsoft Visual C++ 6.0 (Service Pack 6) +- Microsoft Visual Studio .NET 2003 +- Borland Delphi 7 +- (Nullsoft Scriptable Install System (NSIS) v2.46)[https://sourceforge.net/projects/nsis/files/NSIS%202/2.46/] + +Note(s): +- Make a backup of your Microsoft Visual C++ 6.0 installation before you install Service Pack 6 update. This update will overwrite your compiler binaries and alter your building results. You can find your Visual C++ 6.0 installation at `C:\Program Files\Microsoft Visual Studio`. + +### Compiling +#### Windows +TODO +#### Linux +TODO + +## Contributing +If you are interested in this decompilation project, feel free to create a pull request. diff --git a/bot/bot.vcproj b/bot/bot.vcproj index 20010e1..f9159bc 100644 --- a/bot/bot.vcproj +++ b/bot/bot.vcproj @@ -68,10 +68,15 @@ CharacterSet="2"> + + + + diff --git a/bot/net/netgame.cpp b/bot/net/netgame.cpp index af7b019..2130707 100644 --- a/bot/net/netgame.cpp +++ b/bot/net/netgame.cpp @@ -2,6 +2,7 @@ #include "../main.h" #include "../../raknet/SocketDataEncryptor.h" #include "../mathutils.h" +#include "../unnamed_1.h" #define NETGAME_VERSION 4057 @@ -27,7 +28,7 @@ typedef struct _TRAILER_SYNC_DATA // size: 54 char _gap0[54]; } TRAILER_SYNC_DATA; -char unnamed_2[63]; +INCAR_SYNC_DATA icSync; PASSENGER_SYNC_DATA unnamed_5[MAX_PLAYERS]; BOOL bPlayerSlotState[MAX_PLAYERS]; BYTE byteState; @@ -220,6 +221,47 @@ BOOL CNetGame::GetPlayerKeys(PLAYERID playerId, WORD *udAnalog, WORD *lrAnalog, } } +float CNetGame::GetPlayerFacingAngle(PLAYERID playerId) +{ + if(playerId >= MAX_PLAYERS) return 0.0f; + if(bPlayerSlotState[playerId] == FALSE) return 0.0f; + + MATRIX4X4 mat; + + if(bytePlayerState[playerId] == PLAYER_STATE_ONFOOT) + { + QuaternionToMatrix(&unnamed_3[playerId].quatRotation, &mat); + + float fZAngle = atan2(-mat.up.X, mat.up.Y) * 180.0f/PI; + + // Bound it to [0, 360) + while(fZAngle < 0.0f) + fZAngle += 360.0f; + while(fZAngle >= 360.0f) + fZAngle -= 360.0f; + + return fZAngle; + } + else if(bytePlayerState[playerId] == PLAYER_STATE_DRIVER) + { + QuaternionToMatrix(&unnamed_4[playerId].quatRotation, &mat); + + float fZAngle = atan2(-mat.up.X, mat.up.Y) * 180.0f/PI; + + // Bound it to [0, 360) + while(fZAngle < 0.0f) + fZAngle += 360.0f; + while(fZAngle >= 360.0f) + fZAngle -= 360.0f; + + return fZAngle; + } + else + { + return 0.0f; + } +} + BYTE CNetGame::GetPlayerSpecialAction(PLAYERID playerId) { if(playerId >= MAX_PLAYERS) return SPECIAL_ACTION_NONE; @@ -233,7 +275,7 @@ BYTE CNetGame::GetPlayerSpecialAction(PLAYERID playerId) } //---------------------------------------------------- -// MATCH + BOOL CNetGame::IsPlayerAdded(PLAYERID playerId) { if(playerId >= MAX_PLAYERS) return FALSE; @@ -242,6 +284,7 @@ BOOL CNetGame::IsPlayerAdded(PLAYERID playerId) } //---------------------------------------------------- + BOOL CNetGame::IsVehicleAdded(VEHICLEID VehicleID) { if(VehicleID >= MAX_VEHICLES) return FALSE; @@ -250,6 +293,7 @@ BOOL CNetGame::IsVehicleAdded(VEHICLEID VehicleID) } //---------------------------------------------------- + float CNetGame::GetDistanceFromMeToPoint(PVECTOR vecPos) { VECTOR vecMyPos; @@ -269,6 +313,7 @@ float CNetGame::GetDistanceFromMeToPoint(PVECTOR vecPos) } //---------------------------------------------------- + PVECTOR CNetGame::GetMyPos(PVECTOR Vector) { if(byteState == PLAYER_STATE_ONFOOT) @@ -292,6 +337,7 @@ PVECTOR CNetGame::GetMyPos(PVECTOR Vector) } //---------------------------------------------------- + void CNetGame::SetMyPos(PVECTOR Vector) { if(byteState == PLAYER_STATE_ONFOOT) @@ -309,6 +355,7 @@ void CNetGame::SetMyPos(PVECTOR Vector) } //---------------------------------------------------- + float CNetGame::GetMyZAngle() { MATRIX4X4 mat; @@ -343,7 +390,7 @@ float CNetGame::GetMyZAngle() } //---------------------------------------------------- -// MATCH + void CNetGame::SetMyZAngle(float fAngle) { //logprintf("CNetGame::SetMyZAngle(%f)", fAngle); @@ -428,13 +475,13 @@ void CNetGame::ShutdownForGameModeRestart() StopRecordingPlayback(); - memset(unnamed_2,0,sizeof(unnamed_2)); - memset(unnamed_3,0,sizeof(unnamed_3)); - memset(unnamed_4,0,sizeof(unnamed_4)); - memset(unnamed_5,0,sizeof(unnamed_5)); - memset(&bVehicleSlotState[0],0,sizeof(BOOL)*MAX_VEHICLES); memset(&ofSync,0,sizeof(ONFOOT_SYNC_DATA)); + memset(&icSync,0,sizeof(INCAR_SYNC_DATA)); + memset(unnamed_3, 0, sizeof(unnamed_3)); + memset(unnamed_4, 0, sizeof(unnamed_4)); + memset(unnamed_5, 0, sizeof(unnamed_5)); memset(&bPlayerSlotState[0],0,sizeof(BOOL)*MAX_PLAYERS); + memset(&bVehicleSlotState[0],0,sizeof(BOOL)*MAX_VEHICLES); memset(&bytePlayerState[0],0,sizeof(BYTE)*MAX_PLAYERS); m_bZoneNames = FALSE; @@ -496,16 +543,16 @@ void CNetGame::Init(PCHAR szHostOrIp, int iPort, m_bZoneNames = FALSE; m_bInstagib = FALSE; - memset(unnamed_2,0,sizeof(unnamed_2)); memset(&ofSync,0,sizeof(ONFOOT_SYNC_DATA)); + memset(&icSync,0,sizeof(INCAR_SYNC_DATA)); memset(unnamed_3,0,sizeof(unnamed_3)); memset(unnamed_4,0,sizeof(unnamed_4)); memset(unnamed_5,0,sizeof(unnamed_5)); - memset(&bVehicleSlotState[0],0,sizeof(BOOL)*MAX_VEHICLES); memset(&bPlayerSlotState[0],0,sizeof(BOOL)*MAX_PLAYERS); + memset(&bVehicleSlotState[0],0,sizeof(BOOL)*MAX_VEHICLES); memset(&bytePlayerState[0],0,sizeof(BYTE)*MAX_PLAYERS); field_1DE = 0; - field_1E2 = 0; + field_1E2 = NULL; field_1F2 = GetTickCount(); byteState = PLAYER_STATE_NONE; field_1FA = -1; @@ -579,6 +626,23 @@ void CNetGame::Process() UpdateNetwork(); + if(m_iGameState == GAMESTATE_CONNECTED) + { + if(m_pGameMode) m_pGameMode->Frame(fElapsedTime); + if(m_pScriptTimers) m_pScriptTimers->Process((DWORD)(fElapsedTime * 1000.0f)); + + if(bSpawned) + { + if(field_1DE) + { + + } + else + { + byteState = 1; + } + } + } // TODO: CNetGame::Process (W: 00418370 L: 080AD6A4) @@ -619,6 +683,9 @@ void CNetGame::UpdateNetwork() switch(packetIdentifier) { + case ID_UNK_12: + Packet_Unk12(pkt); + break; case ID_RSA_PUBLIC_KEY_MISMATCH: Packet_RSAPublicKeyMismatch(pkt); break; @@ -646,6 +713,12 @@ void CNetGame::UpdateNetwork() case ID_CONNECTION_REQUEST_ACCEPTED: Packet_ConnectionSucceeded(pkt); break; + case ID_PLAYER_SYNC: + Packet_PlayerSync(pkt); + break; + case ID_VEHICLE_SYNC: + Packet_VehicleSync(pkt); + break; case ID_PASSENGER_SYNC: Packet_PassengerSync(pkt); break; @@ -665,6 +738,25 @@ void CNetGame::UpdateNetwork() // PACKET HANDLERS INTERNAL //---------------------------------------------------- +void CNetGame::Packet_PlayerSync(Packet *p) +{ + RakNet::BitStream bsPlayerSync((PCHAR)p->data, p->length, false); + ONFOOT_SYNC_DATA ofSync; + BYTE bytePacketID=0; + PLAYERID playerId=0; + + if(GetGameState() != GAMESTATE_CONNECTED) return; + + memset(&ofSync,0,sizeof(ONFOOT_SYNC_DATA)); + + bsPlayerSync.Read(bytePacketID); + bsPlayerSync.Read(playerId); + + // TODO: CNetGame::Packet_PlayerSync +} + +//---------------------------------------------------- + void CNetGame::Packet_AimSync(Packet *p) { RakNet::BitStream bsAimSync((PCHAR)p->data, p->length, false); @@ -681,6 +773,13 @@ void CNetGame::Packet_AimSync(Packet *p) //---------------------------------------------------- +void CNetGame::Packet_VehicleSync(Packet *p) +{ + // TODO: CNetGame::Packet_VehicleSync +} + +//---------------------------------------------------- + void CNetGame::Packet_PassengerSync(Packet *p) { RakNet::BitStream bsPassengerSync((PCHAR)p->data, p->length, false); @@ -831,6 +930,35 @@ void CNetGame::Packet_ConnectionSucceeded(Packet *p) //---------------------------------------------------- +void CNetGame::Packet_Unk12(Packet *p) +{ + RakNet::BitStream bsRecv((PCHAR)p->data, p->length, false); + + RakNet::BitStream bsSend; + //bsSend.Write((BYTE)ID_UNK_12); + + // TODO: CNetGame::Packet_Unk12 +} + + +//---------------------------------------------------- + +void CNetGame::UpdatePlayerScoresAndPings() +{ + if(!m_pRakClient) return; + if(!m_pRakClient->IsConnected()) return; + + static DWORD dwLastUpdateTick = 0; + + if ((GetTickCount() - dwLastUpdateTick) > 3000) { + dwLastUpdateTick = GetTickCount(); + RakNet::BitStream bsParams; + m_pRakClient->RPC(RPC_UpdateScoresPingsIPs, &bsParams, HIGH_PRIORITY, RELIABLE, 0, FALSE); + } +} + +//---------------------------------------------------- + void CNetGame::ResetVehiclePool() { if(m_pVehiclePool) { @@ -872,6 +1000,56 @@ void CNetGame::SendCommand(char *szCommand) GetRakClient()->RPC(RPC_ServerCommand,&bsParams,HIGH_PRIORITY,RELIABLE,0,false); } +void CNetGame::StartRecordingPlayback(int iPlaybackType, char *szRecordName) +{ + int v5 = 0; + + if(field_1E2) + { + fclose(field_1E2); + field_1E2 = NULL; + } + + char s[MAX_PATH]; + sprintf(s, "./npcmodes/recordings/%s.rec", szRecordName); + + field_1E2 = fopen(s, "rb"); + if(!field_1E2) + { + //logprintf("NPC: Total failure. Can't open recording playback file %s.", s); + exit(1); + } + + fseek(field_1E2, 0, SEEK_END); + v5 = ftell(field_1E2); + rewind(field_1E2); + + if(v5 == 0) + { + //logprintf("NPC: Total failure. %s is a 0 length file.", s); + exit(1); + } + + int v4 = 0; + int v3 = 0; + fread(&v4, 1, sizeof(int), field_1E2); + fread(&v3, 1, sizeof(int), field_1E2); + + if(v4 != 1000) + { + //logprintf("NPC: %s is not the correct recording version for this bot.", s); + //logprintf("NPC: Trying to upgrade %s...", s); + fclose(field_1E2); + if(!UpgradeRecordFile(s, v5, iPlaybackType) ) + { + //logprintf("NPC: Fatal Error. Could not upgrade file. I'm out of options so I'm quiting."); + exit(1); + } + //logprintf("NPC: File %s was upgraded. Please restart the bot.", s); + exit(1); + } +} + void CNetGame::StopRecordingPlayback() { field_1DE = 0; diff --git a/bot/net/netgame.h b/bot/net/netgame.h index 2e033bb..8b4d04b 100644 --- a/bot/net/netgame.h +++ b/bot/net/netgame.h @@ -8,6 +8,10 @@ #define GAMESTATE_RESTARTING 5 +#define PLAYER_RECORDING_TYPE_NONE 0 +#define PLAYER_RECORDING_TYPE_DRIVER 1 +#define PLAYER_RECORDING_TYPE_ONFOOT 2 + //---------------------------------------------------- class CNetGame // size: 910 bytes @@ -23,6 +27,8 @@ private: // Packet handlers void Packet_AimSync(Packet *p); + void Packet_PlayerSync(Packet *p); + void Packet_VehicleSync(Packet *p); void Packet_PassengerSync(Packet *p); void Packet_ConnectionSucceeded(Packet *p); void Packet_RSAPublicKeyMismatch(Packet* packet); @@ -35,6 +41,7 @@ private: void Packet_ModifiedPacket(Packet* packet); void Packet_ConnectAttemptFailed(Packet* packet); void Packet_TrailerSync(Packet *p); + void Packet_Unk12(Packet *p); public: @@ -95,6 +102,7 @@ public: void Init(PCHAR szHostOrIp,int iPort,PCHAR szPlayerName,PCHAR szPass,PCHAR szNpcMode); void Process(); + void UpdatePlayerScoresAndPings(); void ResetVehiclePool(); void ResetPlayerPool(); void ShutdownForGameModeRestart(); @@ -112,6 +120,7 @@ public: BYTE GetPlayerHealth(PLAYERID playerId); BYTE GetPlayerArmour(PLAYERID playerId); BOOL GetPlayerKeys(PLAYERID playerId, WORD *udAnalog, WORD *lrAnalog, WORD *wKeys); + float GetPlayerFacingAngle(PLAYERID playerId); BYTE GetPlayerSpecialAction(PLAYERID playerId); BOOL IsPlayerAdded(PLAYERID playerId); BOOL IsVehicleAdded(VEHICLEID VehicleID); @@ -121,6 +130,7 @@ public: float GetMyZAngle(); void SetMyZAngle(float fAngle); + void StartRecordingPlayback(int iPlaybackType, char *szRecordName); void StopRecordingPlayback(); void PauseRecordingPlayback(); void ResumeRecordingPlayback(); diff --git a/bot/net/netrpc.cpp b/bot/net/netrpc.cpp index 7d1c274..b194cca 100644 --- a/bot/net/netrpc.cpp +++ b/bot/net/netrpc.cpp @@ -346,11 +346,18 @@ void RequestSpawn(RPCParameters *rpcParams) } } +//---------------------------------------------------- +// Remote client is dead. + +void Death(RPCParameters *rpcParams) +{ +} + //---------------------------------------------------- // Remote client is trying to enter vehicle gracefully. void EnterVehicle(RPCParameters *rpcParams) -{ +{ } //---------------------------------------------------- @@ -421,7 +428,7 @@ void ConnectionRejected(RPCParameters *rpcParams) if(byteRejectReason==REJECT_REASON_BAD_VERSION) { //logprintf("BOT: CONNECTION REJECTED. INCORRECT SA-MP VERSION!"); - } + } else if(byteRejectReason==REJECT_REASON_BAD_NICKNAME) { //logprintf("BOT: CONNECTION REJECTED. BAD NICKNAME!"); } @@ -459,19 +466,19 @@ void WorldTime(RPCParameters *rpcParams) //---------------------------------------------------- -void Unk5F(RPCParameters *rpcParams) +void Pickup(RPCParameters *rpcParams) { } //---------------------------------------------------- -void Unk3F(RPCParameters *rpcParams) +void DestroyPickup(RPCParameters *rpcParams) { } //---------------------------------------------------- -void Unk97(RPCParameters *rpcParams) +void DestroyWeaponPickup(RPCParameters *rpcParams) { } @@ -489,13 +496,25 @@ void Weather(RPCParameters *rpcParams) //---------------------------------------------------- -void Unk1D(RPCParameters *rpcParams) +void SetTimeEx(RPCParameters *rpcParams) { } //---------------------------------------------------- -void Unk1E(RPCParameters *rpcParams) +void ToggleClock(RPCParameters *rpcParams) +{ +} + +//---------------------------------------------------- + +void VehicleDestroy(RPCParameters *rpcParams) +{ +} + +//---------------------------------------------------- + +void ACServerProtected(RPCParameters *rpcParams) { } @@ -515,13 +534,13 @@ void RegisterRPCs(RakClientInterface * pRakClient) REGISTER_STATIC_RPC(pRakClient,ConnectionRejected); REGISTER_STATIC_RPC(pRakClient,ClientMessage); REGISTER_STATIC_RPC(pRakClient,WorldTime); - REGISTER_STATIC_RPC(pRakClient,Unk5F); - REGISTER_STATIC_RPC(pRakClient,Unk3F); - REGISTER_STATIC_RPC(pRakClient,Unk97); + REGISTER_STATIC_RPC(pRakClient,Pickup); + REGISTER_STATIC_RPC(pRakClient,DestroyPickup); + REGISTER_STATIC_RPC(pRakClient,DestroyWeaponPickup); REGISTER_STATIC_RPC(pRakClient,ScmEvent); REGISTER_STATIC_RPC(pRakClient,Weather); - REGISTER_STATIC_RPC(pRakClient,Unk1D); - REGISTER_STATIC_RPC(pRakClient,Unk1E); + REGISTER_STATIC_RPC(pRakClient,SetTimeEx); + REGISTER_STATIC_RPC(pRakClient,ToggleClock); REGISTER_STATIC_RPC(pRakClient,ServerJoin); REGISTER_STATIC_RPC(pRakClient,ServerQuit); REGISTER_STATIC_RPC(pRakClient,InitGame); @@ -551,13 +570,13 @@ void UnRegisterRPCs(RakClientInterface * pRakClient) UNREGISTER_STATIC_RPC(pRakClient,ConnectionRejected); UNREGISTER_STATIC_RPC(pRakClient,ClientMessage); UNREGISTER_STATIC_RPC(pRakClient,WorldTime); - UNREGISTER_STATIC_RPC(pRakClient,Unk5F); - UNREGISTER_STATIC_RPC(pRakClient,Unk3F); - UNREGISTER_STATIC_RPC(pRakClient,Unk97); + UNREGISTER_STATIC_RPC(pRakClient,Pickup); + UNREGISTER_STATIC_RPC(pRakClient,DestroyPickup); + UNREGISTER_STATIC_RPC(pRakClient,DestroyWeaponPickup); UNREGISTER_STATIC_RPC(pRakClient,ScmEvent); UNREGISTER_STATIC_RPC(pRakClient,Weather); - UNREGISTER_STATIC_RPC(pRakClient,Unk1D); - UNREGISTER_STATIC_RPC(pRakClient,Unk1E); + UNREGISTER_STATIC_RPC(pRakClient,SetTimeEx); + UNREGISTER_STATIC_RPC(pRakClient,ToggleClock); UNREGISTER_STATIC_RPC(pRakClient,WorldPlayerAdd); UNREGISTER_STATIC_RPC(pRakClient,WorldPlayerDeath); UNREGISTER_STATIC_RPC(pRakClient,WorldPlayerRemove); diff --git a/bot/net/playerpool.h b/bot/net/playerpool.h index 205373a..db47f24 100644 --- a/bot/net/playerpool.h +++ b/bot/net/playerpool.h @@ -19,7 +19,8 @@ public: BOOL Process(); void SetLocalPlayerName(PCHAR szName) { strcpy(m_szLocalPlayerName,szName); }; - PCHAR GetPlayerName(BYTE bytePlayerID) { return m_szPlayerNames[bytePlayerID]; }; + PCHAR GetLocalPlayerName() { return m_szLocalPlayerName; }; + PCHAR GetPlayerName(PLAYERID playerId) { return m_szPlayerNames[playerId]; }; CPlayerPool(); ~CPlayerPool(); diff --git a/bot/net/scriptrpc.cpp b/bot/net/scriptrpc.cpp index 1c21c46..0d64a44 100644 --- a/bot/net/scriptrpc.cpp +++ b/bot/net/scriptrpc.cpp @@ -27,7 +27,7 @@ void ScrUnk45(RPCParameters *rpcParams) //---------------------------------------------------- -void ScrUnk0B(RPCParameters *rpcParams) +void ScrSetPlayerName(RPCParameters *rpcParams) { } @@ -142,13 +142,13 @@ void ScrSetInterior(RPCParameters *rpcParams) //---------------------------------------------------- -void ScrUnk9D(RPCParameters *rpcParams) +void ScrSetCameraPos(RPCParameters *rpcParams) { } //---------------------------------------------------- -void ScrUnk9E(RPCParameters *rpcParams) +void ScrSetCameraLookAt(RPCParameters *rpcParams) { } @@ -178,7 +178,7 @@ void ScrUnk41(RPCParameters *rpcParams) //---------------------------------------------------- -void ScrUnkA2(RPCParameters *rpcParams) +void ScrSetCameraBehindPlayer(RPCParameters *rpcParams) { } @@ -491,7 +491,7 @@ void RegisterScriptRPCs(RakClientInterface* pRakClient) REGISTER_STATIC_RPC(pRakClient, ScrSetSpawnInfo); REGISTER_STATIC_RPC(pRakClient, ScrUnk45); REGISTER_STATIC_RPC(pRakClient, ScrUnk99); - REGISTER_STATIC_RPC(pRakClient, ScrUnk0B); + REGISTER_STATIC_RPC(pRakClient, ScrSetPlayerName); REGISTER_STATIC_RPC(pRakClient, ScrSetPlayerPos); REGISTER_STATIC_RPC(pRakClient, ScrUnk0D); REGISTER_STATIC_RPC(pRakClient, ScrUnk0E); @@ -499,13 +499,13 @@ void RegisterScriptRPCs(RakClientInterface* pRakClient) REGISTER_STATIC_RPC(pRakClient, ScrRemovePlayerFromVehicle); REGISTER_STATIC_RPC(pRakClient, ScrSetPlayerColor); REGISTER_STATIC_RPC(pRakClient, ScrDisplayGameText); - REGISTER_STATIC_RPC(pRakClient, ScrUnk9D); - REGISTER_STATIC_RPC(pRakClient, ScrUnk9E); REGISTER_STATIC_RPC(pRakClient, ScrSetInterior); + REGISTER_STATIC_RPC(pRakClient, ScrSetCameraPos); + REGISTER_STATIC_RPC(pRakClient, ScrSetCameraLookAt); REGISTER_STATIC_RPC(pRakClient, ScrUnk9F); REGISTER_STATIC_RPC(pRakClient, ScrUnkA0); REGISTER_STATIC_RPC(pRakClient, ScrUnkA1); - REGISTER_STATIC_RPC(pRakClient, ScrUnkA2); + REGISTER_STATIC_RPC(pRakClient, ScrSetCameraBehindPlayer); REGISTER_STATIC_RPC(pRakClient, ScrUnk0F); REGISTER_STATIC_RPC(pRakClient, ScrUnk10); REGISTER_STATIC_RPC(pRakClient, ScrUnk11); @@ -564,7 +564,7 @@ void UnRegisterScriptRPCs(RakClientInterface* pRakClient) { UNREGISTER_STATIC_RPC(pRakClient, ScrSetSpawnInfo); UNREGISTER_STATIC_RPC(pRakClient, ScrUnk45); - UNREGISTER_STATIC_RPC(pRakClient, ScrUnk0B); + UNREGISTER_STATIC_RPC(pRakClient, ScrSetPlayerName); UNREGISTER_STATIC_RPC(pRakClient, ScrUnk99); UNREGISTER_STATIC_RPC(pRakClient, ScrSetPlayerPos); UNREGISTER_STATIC_RPC(pRakClient, ScrUnk0D); @@ -573,13 +573,13 @@ void UnRegisterScriptRPCs(RakClientInterface* pRakClient) UNREGISTER_STATIC_RPC(pRakClient, ScrRemovePlayerFromVehicle); UNREGISTER_STATIC_RPC(pRakClient, ScrSetPlayerColor); UNREGISTER_STATIC_RPC(pRakClient, ScrDisplayGameText); - UNREGISTER_STATIC_RPC(pRakClient, ScrUnk9D); - UNREGISTER_STATIC_RPC(pRakClient, ScrUnk9E); UNREGISTER_STATIC_RPC(pRakClient, ScrSetInterior); + UNREGISTER_STATIC_RPC(pRakClient, ScrSetCameraPos); + UNREGISTER_STATIC_RPC(pRakClient, ScrSetCameraLookAt); UNREGISTER_STATIC_RPC(pRakClient, ScrUnk9F); UNREGISTER_STATIC_RPC(pRakClient, ScrUnkA0); UNREGISTER_STATIC_RPC(pRakClient, ScrUnkA1); - UNREGISTER_STATIC_RPC(pRakClient, ScrUnkA2); + UNREGISTER_STATIC_RPC(pRakClient, ScrSetCameraBehindPlayer); UNREGISTER_STATIC_RPC(pRakClient, ScrUnk0F); UNREGISTER_STATIC_RPC(pRakClient, ScrUnk10); UNREGISTER_STATIC_RPC(pRakClient, ScrUnk11); diff --git a/bot/scrcustom.cpp b/bot/scrcustom.cpp index e1891b6..ddfcfc5 100644 --- a/bot/scrcustom.cpp +++ b/bot/scrcustom.cpp @@ -3,6 +3,9 @@ #define CHECK_PARAMS(n) { if (params[0] != (n * sizeof(cell))) { logprintf("SCRIPT: Bad parameter count (Count is %d, Should be %d): ", params[0] / sizeof(cell), n); return 0; } } +char* format_amxstring(AMX *amx, cell *params, int parm, int &len); +int set_amxstring(AMX *amx,cell amx_addr,const char *source,int max); + extern CNetGame* pNetGame; //---------------------------------------------------------------------------------- @@ -93,8 +96,12 @@ static cell AMX_NATIVE_CALL n_atan2(AMX *amx, cell *params) // native StartRecordingPlayback(playbacktype, recordname[]) static cell AMX_NATIVE_CALL n_StartRecordingPlayback(AMX *amx, cell *params) { - // TODO: n_StartRecordingPlayback - return 0; + char *szRecordName; + amx_StrParam(amx, params[2], szRecordName); + if(params[1] == PLAYER_RECORDING_TYPE_DRIVER || params[1] == PLAYER_RECORDING_TYPE_ONFOOT) { + pNetGame->StartRecordingPlayback(params[1], szRecordName); + } + return 1; } // native StopRecordingPlayback() @@ -260,6 +267,18 @@ static cell AMX_NATIVE_CALL n_GetPlayerKeys(AMX *amx, cell *params) return 0; } +// native GetPlayerFacingAngle(playerid,&Float:ang); +static cell AMX_NATIVE_CALL n_GetPlayerFacingAngle(AMX *amx, cell *params) +{ + if(!pNetGame->GetPlayerPool()->GetSlotState((PLAYERID)params[1])) return 0; + + cell* cptr; + amx_GetAddr(amx, params[2], &cptr); + float fZAngle = pNetGame->GetPlayerFacingAngle((PLAYERID)params[1]); + *cptr = amx_ftoc(fZAngle); + + return 1; +} // native GetMyPos(&Float:x, &Float:y, &Float:z) static cell AMX_NATIVE_CALL n_GetMyPos(AMX *amx, cell *params) diff --git a/bot/unnamed_1.cpp b/bot/unnamed_1.cpp new file mode 100644 index 0000000..d31ba8d --- /dev/null +++ b/bot/unnamed_1.cpp @@ -0,0 +1,8 @@ + +#include "main.h" + +int UpgradeRecordFile(char *szFileName, int iFileSize, int iPlaybackType) +{ + // TODO: UpgradeRecordFile + return 0; +} diff --git a/bot/unnamed_1.h b/bot/unnamed_1.h new file mode 100644 index 0000000..714189d --- /dev/null +++ b/bot/unnamed_1.h @@ -0,0 +1,4 @@ + +#pragma once + +int UpgradeRecordFile(char *szFileName, int iFileSize, int iPlaybackType); diff --git a/exgui/ExportFavorites.dfm b/exgui/ExportFavorites.dfm index 98782d0..786daf3 100644 Binary files a/exgui/ExportFavorites.dfm and b/exgui/ExportFavorites.dfm differ diff --git a/exgui/ExportFavorites1.dfm b/exgui/ExportFavorites1.dfm new file mode 100644 index 0000000..101948a Binary files /dev/null and b/exgui/ExportFavorites1.dfm differ diff --git a/exgui/FindSort.dcu b/exgui/FindSort.dcu index d1698a2..5a8c467 100644 Binary files a/exgui/FindSort.dcu and b/exgui/FindSort.dcu differ diff --git a/exgui/GIFImage.dcu b/exgui/GIFImage.dcu index e32def8..38c456d 100644 Binary files a/exgui/GIFImage.dcu and b/exgui/GIFImage.dcu differ diff --git a/exgui/ImportFavorites.dfm b/exgui/ImportFavorites.dfm index 7abb985..dc3471e 100644 Binary files a/exgui/ImportFavorites.dfm and b/exgui/ImportFavorites.dfm differ diff --git a/exgui/Main.dfm b/exgui/Main.dfm index 180610e..12430e5 100644 Binary files a/exgui/Main.dfm and b/exgui/Main.dfm differ diff --git a/exgui/Main.pas b/exgui/Main.pas index 25887b8..8a31f4f 100644 --- a/exgui/Main.pas +++ b/exgui/Main.pas @@ -129,7 +129,6 @@ type function GetToken(TokenData: String; ItemIndex: Integer; TokenDelimiter: String): String; function GetClipBoardStr: String; procedure SetClipBoardStr(Str: String); - procedure GetGTAExe(Owner: HWND); procedure FormCreate(Sender: TObject); procedure lbServersDrawItem(Control: TWinControl; Index: Integer; @@ -170,7 +169,7 @@ type procedure AboutClick(Sender: TObject); procedure tsServerListsChange(Sender: TObject; NewTab: Integer; var AllowChange: Boolean); - procedure QueryServerInfoParse(SrcIP: String; SrcPort: Word; Buf: PAnsiChar; DataLen: Integer); + procedure QueryServerInfoParse(a2: String; a3: Word; Buf: PAnsiChar; DataLen: Integer); procedure QueryServerInfoError(SocketError: Integer); procedure QueryServerInfo(Server: String; bPing: Boolean; bInfo: Boolean; bPlayers: Boolean; bRules: Boolean); procedure ServerConnect(Server: String; Port: String; Password: String); @@ -218,10 +217,10 @@ type TServerInfo = record Address: String; - DottedAddress: String; - HasAddress: Boolean; + field_4: String; + field_8: Boolean; Port: Integer; - Tag: Word; + field_10: Word; HostName: String; Passworded: Boolean; @@ -263,14 +262,13 @@ var ServersTopIndex: Integer = -1; byte_4ED6C4: Boolean = false; dword_4EF08C: TStringList; - FavoritesChanged: Boolean; + byte_4EF090: Boolean; implementation uses ImportFavorites, ExportFavorites, ServerProperties, - RconConfig, Settings, About, Rcon, MasterUpdate, - unit_webrunform; + About, Settings, RconConfig, Rcon, unit_webrunform, MasterUpdate; {$R *.dfm} @@ -359,23 +357,22 @@ begin end; procedure sub_4E220C(a1: String); +function sub_4E2140(a1, a2: string): Integer; var - v10: String; - v9: Integer; - - function sub_4E2140(a1, a2: string): Integer; - var - v13: Integer; - begin - Result:= 0; - for v13:= (Length(a2) - Length(a1) + 1) downto 1 do begin - if Copy(a2, v13, Length(a1)) = a1 then begin - Result:= v13; - Exit; - end; + v13: Integer; +begin + Result:= 0; + for v13:= (Length(a2) - Length(a1) + 1) downto 1 do begin + if Copy(a2, v13, Length(a1)) = a1 then begin + Result:= v13; + Exit; end; end; +end; +var + v11: String; + v10: Integer; begin if (Copy(a1, 2, 1) <> ':') then begin if (Copy(a1, 3, 1) <> '\') then begin @@ -388,11 +385,11 @@ begin a1 := 'C:' + a1; end; end; - if not DirectoryExists(a1) then begin - v9:= sub_4E2140('\', a1); - v10:= Copy(a1, 1, v9 - 1); - if not DirectoryExists(v10) then - sub_4E220C(v10); + if DirectoryExists(a1) then begin + v10:= sub_4E2140('\', a1); + v11:= Copy(a1, 1, v10 - 1); + if not DirectoryExists(v11) then + sub_4E220C(v11); CreateDir(a1); end; end; @@ -520,7 +517,7 @@ var Reg: TRegistry; begin dword_4EF08C:= TStringList.Create; - FavoritesChanged:= false; + byte_4EF090:= false; Reg:= TRegistry.Create; Reg.RootKey:= HKEY_CURRENT_USER; @@ -791,9 +788,9 @@ begin end; if PingOnly then - QueryServerInfo(Servers[Idx].Address + ':' + IntToStr(Servers[Idx].Port) + '#' + IntToStr(Servers[Idx].Tag), true, false, false, false) + QueryServerInfo(Servers[Idx].Address + ':' + IntToStr(Servers[Idx].Port) + '#' + IntToStr(Servers[Idx].field_10), true, false, false, false) else - QueryServerInfo(Servers[Idx].Address + ':' + IntToStr(Servers[Idx].Port) + '#' + IntToStr(Servers[Idx].Tag), true, true, true, true); + QueryServerInfo(Servers[Idx].Address + ':' + IntToStr(Servers[Idx].Port) + '#' + IntToStr(Servers[Idx].field_10), true, true, true, true); end; procedure TfmMain.lbServersClick(Sender: TObject); @@ -846,18 +843,18 @@ var FilterList: TStringList; ItemFiltered: Boolean; Sorted: Boolean; - TrackingChanges: Boolean; + v162: Boolean; TotServers, TotSlots, TotPlayers: Integer; NewServs: TStringList; TopIndexes: Array[1..3] of Integer; - TopIndexSaved: Integer; + v157: Integer; begin if QueryQueue.Count > 0 then begin lbServers.Items.BeginUpdate; - TrackingChanges:= true; + v162:= true; end; - TopIndexSaved:= lbServers.TopIndex; + v157:= lbServers.TopIndex; NewServs:= TStringList.Create; @@ -1005,9 +1002,9 @@ begin if lbServers.ItemIndex = -1 then lbServers.ItemIndex:= 0; - if lbServers.Items.Count >= TopIndexSaved then - lbServers.TopIndex:= TopIndexSaved; - if TrackingChanges = true then + if lbServers.Items.Count >= v157 then + lbServers.TopIndex:= v157; + if v162 = true then lbServers.Items.EndUpdate; Application.ProcessMessages; end; @@ -1113,12 +1110,12 @@ begin BlockRead(ImportFile, Servers[i].RconPassword[1], Temp); Servers[i].Ping:= 9999; - Servers[i].Tag:= Random($FFFF); + Servers[i].field_10:= Random($FFFF); if Dubble then SetLength(Servers, i) else - QueryQueue.Add(Servers[i].Address + ':' + IntToStr(Servers[i].Port) + '#' + IntToStr(Servers[i].Tag)); + QueryQueue.Add(Servers[i].Address + ':' + IntToStr(Servers[i].Port) + '#' + IntToStr(Servers[i].field_10)); //QueryServerInfo(Servers[i].Address + ':' + IntToStr(Servers[i].Port), true, true, false, false); end; CloseFile(ImportFile); @@ -1261,7 +1258,7 @@ end; procedure TfmMain.AddServerClick(Sender: TObject); var Server: String; - Dummy: Boolean; + v22: Boolean; begin Server:= GetClipBoardStr; if (MasterFile <> 0) and (lbServers.ItemIndex <> -1) then begin @@ -1269,7 +1266,7 @@ begin IntToStr(Servers[StrToIntDef(lbServers.Items.Strings[lbServers.ItemIndex], 0)].Port); tsServerLists.TabIndex:= 0; - tsServerListsChange(tsServerLists, 0, Dummy); + tsServerListsChange(tsServerLists, 0, v22); end; if InputQuery('Add Server', 'Enter new server HOST:PORT...', Server) then if Server <> '' then begin @@ -1304,7 +1301,7 @@ begin //QueryServerInfo(Server, true, true, false, false); QueryQueue.Add(Server); ExportFavorites(sub_4E1DA8 + 'USERDATA.DAT', true); - FavoritesChanged:= true; + byte_4EF090:= true; end; UpdateServers; end; @@ -1324,7 +1321,7 @@ begin UpdateServers; ExportFavorites(sub_4E1DA8 + 'USERDATA.DAT', true); - FavoritesChanged:= true; + byte_4EF090:= true; end; procedure TfmMain.RefreshServerClick(Sender: TObject); @@ -1335,7 +1332,7 @@ begin Idx:= StrToInt(lbServers.Items.Strings[lbServers.ItemIndex]); if Idx >= Length(Servers) then Exit; - QueryServerInfo(Servers[Idx].Address + ':' + IntToStr(Servers[Idx].Port) + '#' + IntToStr(Servers[Idx].Tag), true, true, true, true); + QueryServerInfo(Servers[Idx].Address + ':' + IntToStr(Servers[Idx].Port) + '#' + IntToStr(Servers[Idx].field_10), true, true, true, true); end; procedure TfmMain.MasterServerUpdateClick(Sender: TObject); @@ -1401,10 +1398,10 @@ begin Servers[i].Address:= Copy(SL.Strings[i], 1, Pos(':', SL.Strings[i])-1); Servers[i].Port:= StrToIntDef(Copy(SL.Strings[i], Pos(':', SL.Strings[i])+1, 5), 7777); Servers[i].Ping:= 9999; - Servers[i].Tag:= Random($FFFF); + Servers[i].field_10:= Random(65535); //QueryServerInfo(SL.Strings[i], true, true, false, false); //Sleep(10); - QueryQueue.Add(SL.Strings[i] + '#' + IntToStr(Servers[i].Tag)); + QueryQueue.Add(SL.Strings[i] + '#' + IntToStr(Servers[i].field_10)); end; tmrQueryQueueProcess.Enabled := true; @@ -1499,9 +1496,9 @@ end; procedure TfmMain.tsServerListsChange(Sender: TObject; NewTab: Integer; var AllowChange: Boolean); begin - if (tsServerLists.TabIndex = 0) and (FavoritesChanged = True) then begin + if (tsServerLists.TabIndex = 0) and (byte_4EF090 = True) then begin ExportFavorites(sub_4E1DA8 + 'USERDATA.DAT', true); - FavoritesChanged:= False; + byte_4EF090:= False; end; QueryQueue.Clear; @@ -1542,10 +1539,10 @@ begin dword_4EF08C.Clear; end; -procedure TfmMain.QueryServerInfoParse(SrcIP: String; SrcPort: Word; Buf: PAnsiChar; DataLen: Integer); +procedure TfmMain.QueryServerInfoParse(a2: String; a3: Word; Buf: PAnsiChar; DataLen: Integer); var StrIP: String; - Tag: Word; + v144: Word; i, j, Idx: Integer; Magic: array[0..3] of char; ping: Cardinal; @@ -1557,8 +1554,8 @@ var RepaintServerList, RepaintPlayerList, RepaintRulesList: Boolean; - TempInt: Integer; - Port: Word; + v131: Integer; + v130: Word; begin @@ -1570,27 +1567,27 @@ begin StrIP:= IntToStr(Byte(Buf[4]))+'.'+IntToStr(Byte(Buf[5]))+'.'+ IntToStr(Byte(Buf[6]))+'.'+IntToStr(Byte(Buf[7])); - Move(Buf[8], Port, 2); + Move(Buf[8], v130, 2); - Tag:= SrcPort; + v144:= a3; - if SrcIP <> StrIP then Exit; + if a2 <> StrIP then Exit; Idx:= -1; for i:= 0 to Length(Servers)-1 do begin - if Servers[i].DottedAddress = '' then begin - if not Servers[i].HasAddress then begin - Servers[i].DottedAddress:= GetIPFromHost(Servers[i].Address); - Servers[i].HasAddress:= true; + if Servers[i].field_4 = '' then begin + if not Servers[i].field_8 then begin + Servers[i].field_4:= GetIPFromHost(Servers[i].Address); + Servers[i].field_8:= true; end; end; - if (Servers[i].Address = SrcIP) or (Servers[i].DottedAddress = SrcIP) then begin - if Servers[i].Port = SrcPort then begin + if (Servers[i].Address = a2) or (Servers[i].field_4 = a2) then begin + if Servers[i].Port = a3 then begin Idx:= i; break; end; end; - if (Servers[i].Address = SrcIP) and (Servers[i].Port = SrcPort) then begin + if (Servers[i].Address = a2) and (Servers[i].Port = a3) then begin Idx:= i; break; end; @@ -1601,8 +1598,7 @@ begin Exit; end; - if (Servers[i].Tag <> 0) and (Servers[i].Tag <> Port) then begin - //fmMain.Caption:= 'Invalid tag for ' + StrIP; + if (Servers[i].field_10 <> 0) and (Servers[i].field_10 <> v130) then begin Exit; end; @@ -1690,7 +1686,7 @@ begin RepaintServerList:= true; - QueryServerInfo(Servers[Idx].Address+':'+IntToStr(Servers[Idx].Port)+'#'+IntToStr(Servers[Idx].Tag), true, false, false, false); + QueryServerInfo(Servers[Idx].Address+':'+IntToStr(Servers[Idx].Port)+'#'+IntToStr(Servers[Idx].field_10), true, false, false, false); end; 'c': // Players @@ -1711,10 +1707,10 @@ begin Move(Buf[BufPos], Servers[Idx].aPlayers[i].Name[1], TempByte); Inc(BufPos, TempByte); if BufPos > DataLen then break; - Move(Buf[BufPos], TempInt, 4); - if TempInt > 1000000 then TempInt:= 1000000; - if TempInt < 0 then TempInt:= 0; - Servers[Idx].aPlayers[i].Score:= TempInt; + Move(Buf[BufPos], v131, 4); + if v131 > 1000000 then v131:= 1000000; + if v131 < 0 then v131:= 0; + Servers[Idx].aPlayers[i].Score:= v131; Inc(BufPos, 4); if BufPos > DataLen then break; end; @@ -1783,33 +1779,33 @@ var Host: String; Port: Word; - Tag: Word; + v40: Word; - ColPos, TagPos: Integer; + v39, v38: Integer; begin - Tag:= 0; + v40:= 0; if Pos(':', Server) <> 0 then begin if Pos('#', Server) <> 0 then begin - ColPos:= Pos(':', Server); - TagPos:= Pos('#', Server); + v39:= Pos(':', Server); + v38:= Pos('#', Server); - Host:= Copy(Server, 1, ColPos-1); - Port:= StrToIntDef(Copy(Server, ColPos+1, TagPos-(ColPos+1)), 7777); - Tag:= StrToIntDef(Copy(Server, TagPos+1, Length(Server)-TagPos), 0); + Host:= Copy(Server, 1, v39-1); + Port:= StrToIntDef(Copy(Server, v39+1, v38-(v39+1)), 7777); + v40:= StrToIntDef(Copy(Server, v38+1, Length(Server)-v38), 0); end else begin - ColPos:= Pos(':', Server); + v39:= Pos(':', Server); - Host:= Copy(Server, 1, ColPos-1); - Port:= StrToIntDef(Copy(Server, ColPos+1, Length(Server)-ColPos+1), 7777); + Host:= Copy(Server, 1, v39-1); + Port:= StrToIntDef(Copy(Server, v39+1, Length(Server)-v39+1), 7777); end; end else begin Host:= Server; Port:= 7777; end; - if Tag = 0 then - Tag:= Port; + if v40 = 0 then + v40:= Port; Host:= GetIPFromHost(Host); if (Length(Host) < 7) or (Length(Host) > 15) then @@ -1834,7 +1830,7 @@ begin ToAddr.sin_addr.S_addr:= inet_addr(PChar(Host)); ToLen:= SizeOf(ToAddr); - Move(Tag, Buf[8], 2); // Tag + Move(v40, Buf[8], 2); if bInfo = true then begin Buf[10]:= Byte('i'); // Info Packet Id @@ -2083,30 +2079,28 @@ procedure TfmMain.WMRecv(var Message: TMessage); var lpBuffer: Array[0..2048] of Char; BufLen: Integer; - - FromAddr: TSockAddr; - FromLen: Integer; - - SrcAddr: String; - SrcPort: Word; + v8: TSockAddr; + v13: Integer; + v12: String; + v11: Word; begin ZeroMemory(@lpBuffer, sizeof(lpBuffer)); - ZeroMemory(@FromAddr, sizeof(FromAddr)); - FromAddr.sin_family:= AF_INET; - FromLen:= SizeOf(FromAddr); + ZeroMemory(@v8, sizeof(v8)); + v8.sin_family:= AF_INET; - BufLen:= recvfrom(QuerySocket, lpBuffer, 2048, 0, FromAddr, FromLen); - SrcAddr:= inet_ntoa(FromAddr.sin_addr); - SrcPort:= htons(FromAddr.sin_port); + v13:= SizeOf(v8); + BufLen:= recvfrom(QuerySocket, lpBuffer, 2048, 0, v8, v13); + v12:= inet_ntoa(v8.sin_addr); + v11:= htons(v8.sin_port); while (BufLen > 0) do begin //OutputDebugString( PChar('[*] of size ' + IntToStr(BufLen)) ); - QueryServerInfoParse(SrcAddr,SrcPort,lpBuffer,BufLen); + QueryServerInfoParse(v12,v11,lpBuffer,BufLen); ZeroMemory(@lpBuffer, sizeof(lpBuffer)); - BufLen:= recvfrom(QuerySocket, lpBuffer, 2048, 0, FromAddr, FromLen); - SrcAddr:= inet_ntoa(FromAddr.sin_addr); - SrcPort:= htons(FromAddr.sin_port); + BufLen:= recvfrom(QuerySocket, lpBuffer, 2048, 0, v8, v13); + v12:= inet_ntoa(v8.sin_addr); + v11:= htons(v8.sin_port); end; end; @@ -2128,9 +2122,9 @@ begin QueryQueue.Free; - if (tsServerLists.TabIndex = 0) and (FavoritesChanged = True) then begin + if (tsServerLists.TabIndex = 0) and (byte_4EF090 = True) then begin ExportFavorites(sub_4E1DA8 + 'USERDATA.DAT', True); - FavoritesChanged:= False; + byte_4EF090:= False; end; Sleep(0); @@ -2139,7 +2133,7 @@ end; procedure TfmMain.FormShow(Sender: TObject); var ServFull, ServAddr, ServPort, ServPass: String; - NewServer: String; + v37: String; begin //SetProcessAffinityMask(GetCurrentProcess(),1); lbServers.DoubleBuffered:= true; @@ -2156,17 +2150,6 @@ begin ServFull:= StringReplace(ServFull, '/', '', [rfReplaceAll, rfIgnoreCase]); if Pos(':', ServFull) <> 0 then begin ServAddr:= Copy(ServFull, 0, Pos(':', ServFull)-1); - /////////////////////////////////////////////// - // - // Delphi 7 compiler bug(?) - // - // With this structure: - // ServPort:= IntToStr(StrToIntDef(Copy(ServFull, Pos(':', ServFull)+1, Length(ServFull)-Pos(':', ServFull)+1), 7777)); - // the compiler seems to gets confused and will not generate - // LStrLAsg call after Sysutils::IntToStr to set ServPort variable. - // Workaround is to break down the structure. - // - /////////////////////////////////////////////// ServPort:= Copy(ServFull, Pos(':', ServFull)+1, Length(ServFull)-Pos(':', ServFull)+1); ServPort:= IntToStr(StrToIntDef(ServPort, 7777)); end else begin @@ -2181,12 +2164,13 @@ begin end; mrYes: begin sub_4E1CEC; - NewServer:= ServAddr + ':' + ServPort; - if InputQuery('Add Server', 'Enter new server HOST:PORT...', NewServer) <> False then - if NewServer <> '' then - AddServer(NewServer); + v37:= ServAddr + ':' + ServPort; + if InputQuery('Add Server', 'Enter new server HOST:PORT...', v37) <> False then + if v37 <> '' then + AddServer(v37); end; - mrCancel: ; + mrCancel: + ; end; end else begin ServFull:= ParamStr(1); @@ -2264,14 +2248,14 @@ end; procedure TfmMain.CreateFASTDesktoplink1Click(Sender: TObject); var - Idx: Integer; + v17: Integer; begin if lbServers.ItemIndex = -1 then Exit; - Idx:= StrToInt(lbServers.Items.Strings[lbServers.ItemIndex]); - if Idx >= Length(Servers) then Exit; + v17:= StrToInt(lbServers.Items.Strings[lbServers.ItemIndex]); + if v17 >= Length(Servers) then Exit; - sub_4E1E6C(Servers[Idx].Address + ':' + IntToStr(Servers[Idx].Port), Servers[Idx].HostName); + sub_4E1E6C(Servers[v17].Address + ':' + IntToStr(Servers[v17].Port), Servers[v17].HostName); end; procedure TfmMain.FormResize(Sender: TObject); diff --git a/exgui/hh.dcu b/exgui/hh.dcu index 3b9777e..eea650f 100644 Binary files a/exgui/hh.dcu and b/exgui/hh.dcu differ diff --git a/exgui/samp.cfg b/exgui/samp.cfg index b3385c7..3b7173f 100644 --- a/exgui/samp.cfg +++ b/exgui/samp.cfg @@ -6,7 +6,7 @@ -$F- -$G+ -$H+ --$I+ +-$I- -$J- -$K- -$L+ @@ -14,8 +14,8 @@ -$N+ -$O- -$P+ --$R- -$Q+ +-$R- -$S- -$T- -$U- diff --git a/exgui/samp.dof b/exgui/samp.dof index fbb8e82..fc7e619 100644 --- a/exgui/samp.dof +++ b/exgui/samp.dof @@ -9,15 +9,15 @@ E=0 F=0 G=1 H=1 -I=1 +I=0 J=0 K=0 L=1 M=0 N=1 -O=1 +O=0 P=1 -Q=0 +Q=1 R=0 S=0 T=0 @@ -88,14 +88,14 @@ RemoteSymbols=0 MinStackSize=16384 MaxStackSize=1048576 ImageBase=4194304 -ExeDescription= +ExeDescription=San Andreas Multiplayer Server Browser [Directories] OutputDir= UnitOutputDir= PackageDLLOutputDir= PackageDCPOutputDir= SearchPath= -Packages= +Packages=vcl;rtl;vclx;indy;inet;xmlrtl;vclie;inetdbbde;inetdbxpress;dbrtl;dsnap;dsnapcon;vcldb;soaprtl;VclSmp;dbexpress;dbxcds;inetdb;bdertl;vcldbx;webdsnap;websnap;adortl;ibxpress;teeui;teedb;tee;dss;visualclx;visualdbclx;vclactnband;vclshlctrls;dclOfficeXP Conditionals= DebugSourceDirs= UsePackages=0 @@ -121,7 +121,7 @@ PreRelease=0 Special=0 Private=0 DLL=0 -Locale=1033 +Locale=3081 CodePage=1252 [Version Info Keys] CompanyName= @@ -134,3 +134,6 @@ OriginalFilename= ProductName= ProductVersion=1.0.0.0 Comments= +[HistoryLists\hlUnitAliases] +Count=1 +Item0=WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE; diff --git a/exgui/samp.res b/exgui/samp.res index 3adc036..e7561d3 100644 Binary files a/exgui/samp.res and b/exgui/samp.res differ diff --git a/exgui/unit_webrunform.dcu b/exgui/unit_webrunform.dcu index 902b156..448afe0 100644 Binary files a/exgui/unit_webrunform.dcu and b/exgui/unit_webrunform.dcu differ diff --git a/nsis/CUSTOM.ide b/nsis/CUSTOM.ide new file mode 100644 index 0000000..e69de29 diff --git a/nsis/SAMP.ide b/nsis/SAMP.ide new file mode 100644 index 0000000..9c1e3fd --- /dev/null +++ b/nsis/SAMP.ide @@ -0,0 +1,2069 @@ +# ------------------------------------------------------ +# ------------------------------------------------------ +# SA:MP IDE File +# -------------- +# Objects in this file were created and/or edited by (in alphabetical order): +# cessil, Kalcor, Matite and Micky (September 2010 to April 2015) +# +# Go to the SA:MP wiki for information about this file: +# http://wiki.sa-mp.com +# ------------------------------------------------------ +# +# IMG File Fixes in SA:MP 0.3.7: +# * Fixed the elevator COL brightness (ID:18755 - was 0 brightness) +# * Fixed the missing metal grating texture for AnimTube (ID:19901) +# * Fixed some of the draw distances (IDs:19475 to 19483 - changed from 300 to 299) +# * Fixed the flags on one of the walls (ID:19371 - changed from 2097284 to 0) +# * Fixed the wall sections COL brightness (IDs:19353 to 19465 - was 255 brightness) +# * Replaced the face COLs with box COLs on many of the wall sections (IDs:19353 to 19465) +# * Fixed the hot air balloons COL brightness (IDs:19332 to 19338 - was 0 brightness) +# * Added mine.txd from VC to fix the existing GTASA landmine that had no texture (ID:1213) +# Note: if you want a non-dynamic mine use ID:19589 +# * Fixed the deer COL brightness (ID:19315 - was 0 brightness) +# * Fixed the container COL brightness (ID:19321 - was 0 brightness) +# * Changed the flags on EnExMarker2 (ID:19197 - changed from 2097156 to 2097220) +# * Changed the flags on EnExMarker3 (ID:19198 - changed from 2097156 to 2097220) +# * Added the UFO model to old unused object ID slot (ID:18846) +# * Fixed the pumpkin COL brightness (ID:19320 - was 0 brightness) +# * Added the security keypad 2 model to old unused object ID slot (ID:19305) +# * Added the red flag model to old unused object ID slot (ID:19306) +# * Added the blue flag model to old unused object ID slot (ID:19307) +# * Added the ATM non-dynamic model to old unused object ID slot (ID:19324) +# * Updated wall001 (ID:19353) to use vertex colours so it does not respond to dynamic lighting +# * Updated wall031 (ID:19383) to use vertex colours so it does not respond to dynamic lighting +# * Updated wall047 (ID:19399) to use vertex colours so it does not respond to dynamic lighting +# * Updated wall066 (ID:19426) to use vertex colours so it does not respond to dynamic lighting +# * Updated wall085 (ID:19445) to use vertex colours so it does not respond to dynamic lighting +# * Updated SF Harry Plums building (ID:19486) to open the side doors, fix vertex colours and COL +# +# +# ------------------------------------------------------ +# The objects defined below have been added by SA:MP. +# You can replace them to define new objects +# (but they will only be visible to you). +# +# Usable object IDs are: +# * 18631 to 19999 (1369 total) reserved for SAMP.IDE +# * 11682 to 12799 (1118 total) reserved for SAMP.IDE +# * 15065 to 15999 (935 total) reserved for CUSTOM.IDE +# ------------------------------------------------------ +# +objs +# ------------------------------------------------------ +# No Model File (used internally by SA:MP - do not remove or replace this model) +18631, NoModelFile, NoModelFile, 50, 0 +# ------------------------------------------------------ +# Holding Objects +18632, FishingRod, FishingRod, 100, 0 +18633, GTASAWrench1, MatTextures, 100, 0 +18634, GTASACrowbar1, MatTextures, 100, 0 +18635, GTASAHammer1, MatTextures, 100, 0 +18636, PoliceCap1, MatTextures, 100, 2097152 +18637, PoliceShield1, MatTextures, 100, 4 +18638, HardHat1, wmycon, 100, 2097152 +18639, BlackHat1, dwmolc2, 100, 2097152 +18640, Hair1, smyst, 100, 2097152 +18641, Flashlight1, Flashlight1, 100, 0 +18642, Taser1, Taser1, 100, 0 +18643, LaserPointer1, LaserPointer1, 100, 4 +18644, Screwdriver1, MatTextures, 100, 0 +18645, MotorcycleHelmet1, MatClothes, 100, 2097152 +# ------------------------------------------------------ +# Lights +18646, PoliceLight1, MatColours, 150, 0 +18647, RedNeonTube1, MatTextures, 150, 0 +18648, BlueNeonTube1, MatTextures, 150, 0 +18649, GreenNeonTube1, MatTextures, 150, 0 +18650, YellowNeonTube1, MatTextures, 150, 0 +18651, PinkNeonTube1, MatTextures, 150, 0 +18652, WhiteNeonTube1, MatTextures, 150, 0 +18653, DiscoLightRed, Carter_block, 150, 0 +18654, DiscoLightGreen, Carter_block, 150, 0 +18655, DiscoLightBlue, Carter_block, 150, 0 +18656, LightBeamWhite, LightBeams, 200, 2097156 +18657, LightBeamRed, LightBeams, 200, 2097156 +18658, LightBeamBlue, LightBeams, 200, 2097156 +# ------------------------------------------------------ +# Spray Tags +18659, SprayTag1, SprayTags, 50, 4 +18660, SprayTag2, SprayTags, 50, 4 +18661, SprayTag3, SprayTags, 50, 4 +18662, SprayTag4, SprayTags, 50, 4 +18663, SprayTag5, SprayTags, 50, 4 +18664, SprayTag6, SprayTags, 50, 4 +18665, SprayTag7, SprayTags, 50, 4 +18666, SprayTag8, SprayTags, 50, 4 +18667, SprayTag9, SprayTags, 50, 4 +# ------------------------------------------------------ +# Particle Effects +18668, blood_heli, MatTextures, 100, 0 +18669, boat_prop, MatTextures, 100, 0 +18670, camflash, MatTextures, 100, 0 +18671, carwashspray, MatTextures, 100, 0 +18672, cementp, MatTextures, 100, 0 +18673, cigarette_smoke, MatTextures, 100, 0 +18674, cloudfast, MatTextures, 100, 0 +18675, coke_puff, MatTextures, 100, 0 +18676, coke_trail, MatTextures, 100, 0 +18677, exhale, MatTextures, 100, 0 +18678, explosion_barrel, MatTextures, 100, 0 +18679, explosion_crate, MatTextures, 100, 0 +18680, explosion_door, MatTextures, 100, 0 +18681, explosion_fuel_car, MatTextures, 100, 0 +18682, explosion_large, MatTextures, 100, 0 +18683, explosion_medium, MatTextures, 100, 0 +18684, explosion_molotov, MatTextures, 100, 0 +18685, explosion_small, MatTextures, 100, 0 +18686, explosion_tiny, MatTextures, 100, 0 +18687, extinguisher, MatTextures, 100, 0 +18688, fire, MatTextures, 150, 0 +18689, fire_bike, MatTextures, 100, 0 +18690, fire_car, MatTextures, 100, 0 +18691, fire_large, MatTextures, 100, 0 +18692, fire_med, MatTextures, 100, 0 +18693, Flame99, MatTextures, 100, 0 +18694, flamethrowerp, MatTextures, 100, 0 +18695, gunflash, MatTextures, 100, 0 +18696, gunsmoke, MatTextures, 100, 0 +18697, heli_dust, MatTextures, 100, 0 +18698, insects, MatTextures, 100, 0 +18699, jetpackp, MatTextures, 100, 0 +18700, jetthrust, MatTextures, 100, 0 +18701, molotov_flame, MatTextures, 100, 0 +18702, nitrop, MatTextures, 100, 0 +18703, overheat_car, MatTextures, 100, 0 +18704, overheat_car_elec, MatTextures, 100, 0 +18705, petrolcan, MatTextures, 100, 0 +18706, prt_blood, MatTextures, 100, 0 +18707, prt_boatsplash, MatTextures, 100, 0 +18708, prt_bubble, MatTextures, 100, 0 +18709, prt_cardebris, MatTextures, 100, 0 +18710, prt_collisionsmoke, MatTextures, 100, 0 +18711, prt_glass, MatTextures, 100, 0 +18712, prt_gunshell, MatTextures, 100, 0 +18713, prt_sand2, MatTextures, 100, 0 +18714, prt_sand, MatTextures, 100, 0 +18715, prt_smoke_huge, MatTextures, 150, 0 +18716, prt_smoke_expand, MatTextures, 100, 0 +18717, prt_spark, MatTextures, 100, 0 +18718, prt_spark_2, MatTextures, 100, 0 +18719, prt_wake, MatTextures, 100, 0 +18720, prt_watersplash, MatTextures, 100, 0 +18721, prt_wheeldirt, MatTextures, 100, 0 +18722, puke, MatTextures, 100, 0 +18723, riot_smoke, MatTextures, 100, 0 +18724, shootlight, MatTextures, 100, 0 +18725, smoke30lit, MatTextures, 100, 0 +18726, smoke30m, MatTextures, 100, 0 +18727, smoke50lit, MatTextures, 100, 0 +18728, smoke_flare, MatTextures, 100, 0 +18729, spraycanp, MatTextures, 100, 0 +18730, tank_fire, MatTextures, 100, 0 +18731, teargas99, MatTextures, 100, 0 +18732, teargasAD, MatTextures, 100, 0 +18733, tree_hit_fir, MatTextures, 100, 0 +18734, tree_hit_palm, MatTextures, 100, 0 +18735, vent2, MatTextures, 100, 0 +18736, vent, MatTextures, 100, 0 +18737, wallbust, MatTextures, 100, 0 +18738, water_fnt_tme, MatTextures, 100, 0 +18739, water_fountain, MatTextures, 100, 0 +18740, water_hydrant, MatTextures, 100, 0 +18741, water_ripples, MatTextures, 100, 0 +18742, water_speed, MatTextures, 100, 0 +18743, water_splash, MatTextures, 100, 0 +18744, water_splash_big, MatTextures, 100, 0 +18745, water_splsh_sml, MatTextures, 100, 0 +18746, water_swim, MatTextures, 100, 0 +18747, waterfall_end, MatTextures, 100, 0 +18748, WS_factorysmoke, MatTextures, 100, 0 +# ------------------------------------------------------ +# SA:MP Logos +18749, SAMPLogoSmall, MatTextures, 150, 0 +18750, SAMPLogoBig, MatTextures, 299, 0 +# ------------------------------------------------------ +# Land Masses +18751, IslandBase1, MatTextures, 299, 0 +18752, Volcano, Volcano, 299, 4 +# ------------------------------------------------------ +# Base Sections +18753, Base125mx125m1, BaseSections, 299, 2097156 +18754, Base250mx250m1, BaseSections, 299, 2097156 +# ------------------------------------------------------ +# Elevator from VC +18755, VCElevator1, VCInteriors, 50, 2097152 +18756, ElevatorDoor1, VCInteriors, 50, 0 +18757, ElevatorDoor2, VCInteriors, 50, 0 +18758, VCElevatorFront1, VCInteriors, 50, 2097152 +# ------------------------------------------------------ +# DM Cages +18759, DMCage1, DMCages, 250, 2097156 +18760, DMCage2, DMCages, 250, 2097156 +# ------------------------------------------------------ +# Racing +18761, RaceFinishLine1, MatRacing, 220, 2097156 +# ------------------------------------------------------ +# Parkour +18762, Concrete1mx1mx5m, ConcreteBits, 100, 0 +18763, Concrete3mx3mx5m, ConcreteBits, 100, 0 +18764, Concrete5mx5mx5m, ConcreteBits, 100, 0 +18765, Concrete10mx10mx5m, ConcreteBits, 100, 0 +18766, Concrete10mx1mx5m, ConcreteBits, 100, 0 +18767, ConcreteStair1, ConcreteBits, 150, 0 +# ------------------------------------------------------ +# Sky Diving Platforms +18768, SkyDivePlatform1, SkyDivePlatforms, 299, 2097152 +18769, SkyDivePlatform1a, SkyDivePlatforms, 299, 2097156 +18770, SkyDivePlatform1b, SkyDivePlatforms, 299, 0 +18771, SpiralStair1, MatStairs, 299, 0 +# ------------------------------------------------------ +# Tunnel Sections +18772, TunnelSection1, TunnelSections, 299, 4 +18773, TunnelJoinSection1, TunnelSections, 299, 4 +18774, TunnelJoinSection2, TunnelSections, 299, 4 +18775, TunnelJoinSection3, TunnelSections, 299, 4 +18776, TunnelJoinSection4, TunnelSections, 299, 4 +18777, TunnelSpiral1, TunnelSections, 299, 4 +# ------------------------------------------------------ +# Ramps +18778, RampT1, landjump, 220, 0 +18779, RampT2, MatRamps, 280, 0 +18780, RampT3, MatRamps, 280, 0 +18781, MeshRampBig, MatRamps, 220, 4 +18782, CookieRamp1, CookieRamp1, 220, 0 +18783, FunBoxTop1, MatRamps, 220, 2097284 +18784, FunBoxRamp1, MatRamps, 220, 2097284 +18785, FunBoxRamp2, MatRamps, 220, 2097284 +18786, FunBoxRamp3, MatRamps, 220, 2097284 +18787, FunBoxRamp4, MatRamps, 220, 2097284 +# ------------------------------------------------------ +# Modular Road Sections +18788, MRoad40m, cs_ebridge, 250, 0 +18789, MRoad150m, cs_ebridge, 299, 0 +18790, MRoadBend180Deg1, cs_ebridge, 250, 0 +18791, MRoadBend45Deg, cs_ebridge, 250, 0 +18792, MRoadTwist15DegL, cs_ebridge, 250, 0 +18793, MRoadTwist15DegR, cs_ebridge, 250, 0 +18794, MRoadBend15Deg1, cs_ebridge, 250, 0 +18795, MRoadBend15Deg2, cs_ebridge, 250, 0 +18796, MRoadBend15Deg3, cs_ebridge, 250, 0 +18797, MRoadBend15Deg4, cs_ebridge, 250, 0 +18798, MRoadB45T15DegL, cs_ebridge, 250, 0 +18799, MRoadB45T15DegR, cs_ebridge, 250, 0 +18800, MRoadHelix1, MRoadHelix1, 250, 0 +18801, MRoadLoop1, cs_ebridge, 250, 0 +# ------------------------------------------------------ +# Modular Bridge Sections +18802, MBridgeRamp1, cs_ebridge, 200, 0 +18803, MBridge150m1, cs_ebridge, 250, 0 +18804, MBridge150m2, cs_ebridge, 250, 0 +18805, MBridge150m3, cs_ebridge, 250, 0 +18806, MBridge150m4, cs_ebridge, 250, 0 +18807, MBridge75mHalf, cs_ebridge, 250, 0 +# ------------------------------------------------------ +# Tubes and Funnels +18808, Tube50m1, MatTextures, 299, 0 +18809, Tube50mGlass1, MatTextures, 299, 4 +18810, Tube50mBulge1, MatTextures, 299, 0 +18811, Tube50mGlassBulge1, MatTextures, 299, 4 +18812, Tube50mFunnel1, MatTextures, 299, 0 +18813, Tube50mGlassFunnel1, MatTextures, 299, 4 +18814, Tube50mFunnel2, MatTextures, 299, 0 +18815, Tube50mFunnel3, MatTextures, 299, 0 +18816, Tube50mFunnel4, MatTextures, 299, 0 +18817, Tube50mTSection1, MatTextures, 299, 0 +18818, Tube50mGlassT1, MatTextures, 299, 4 +18819, Tube50mPlus1, MatTextures, 299, 0 +18820, Tube50mGlassPlus1, MatTextures, 299, 4 +18821, Tube50m45Bend1, MatTextures, 299, 0 +18822, Tube50mGlass45Bend1, MatTextures, 299, 4 +18823, Tube50m90Bend1, MatTextures, 299, 0 +18824, Tube50mGlass90Bend1, MatTextures, 299, 4 +18825, Tube50m180Bend1, MatTextures, 299, 0 +18826, Tube50mGlass180Bend, MatTextures, 299, 4 +18827, Tube100m2, MatTextures, 299, 0 +18828, SpiralTube1, MatRamps, 299, 2097156 +18829, RTexturetube, MickyTextures, 299, 0 +18830, RTexturebridge, MickyTextures, 299, 0 +18831, RT25mBend90Tube1, MickyTextures, 299, 0 +18832, RT25mBend180Tube1, MickyTextures, 299, 0 +18833, RT50mBend45Tube1, MickyTextures, 299, 0 +18834, RT50mBend180Tube1, MickyTextures, 299, 0 +18835, RBFunnel, MickyTextures, 299, 0 +18836, RBHalfpipe, MickyTextures, 299, 0 +18837, RB25mBend90Tube, MickyTextures, 299, 0 +18838, RB25mBend180Tube, MickyTextures, 299, 0 +18839, RB50mBend45Tube, MickyTextures, 299, 0 +18840, RB50mBend90Tube, MickyTextures, 299, 0 +18841, RB50mBend180Tube, MickyTextures, 299, 0 +18842, RB50mTube, MickyTextures, 299, 0 +# ------------------------------------------------------ +# Spheres +18843, GlassSphere1, MatTextures, 299, 4 +18844, WaterUVAnimSphere1, MatTextures, 280, 4 +18845, RTexturesphere, MickyTextures, 299, 0 +# ------------------------------------------------------ +# Extracted UFO +# ------------- +18846, UFO, des_ufoinn, 299, 0 +# ------------------------------------------------------ +# More Stuff +18847, HugeHalfPipe1, glenpark7_lae, 299, 0 +18848, SamSiteNonDynamic, milbase, 150, 0 +18849, ParaDropNonDynamic, kmb_chute, 150, 0 +18850, HeliPad1, sfe_copchop, 200, 4 +# ------------------------------------------------------ +# Objects added in Beta Team IMG 1 (154 Objects) +18851, TubeToRoad1, MatTextures, 299, 0 +18852, Tube100m1, MatTextures, 299, 0 +18853, Tube100m45Bend1, MatTextures, 299, 0 +18854, Tube100m90Bend1, MatTextures, 299, 0 +18855, Tube100m180Bend1, MatTextures, 299, 0 +18856, Cage5mx5mx3m, MatTextures, 200, 4 +18857, Cage20mx20mx10m, MatTextures, 250, 4 +18858, FoamHoop1, MatRamps, 250, 0 +18859, QuarterPipe1, glenpark7_lae, 250, 0 +#18860, skyscrpunbuilt2, buildsite, 299, 0 +#18861, scaffoldlift, buildsite, 150, 0 +18862, GarbagePileRamp1, MatTextures, 250, 2097152 +18863, SnowArc1, FakeSnow1, 299, 2097156 +18864, FakeSnow1, FakeSnow1, 299, 2097156 +18865, MobilePhone1, MobilePhone1, 100, 0 +18866, MobilePhone2, MobilePhone2, 100, 0 +18867, MobilePhone3, MobilePhone3, 100, 0 +18868, MobilePhone4, MobilePhone4, 100, 0 +18869, MobilePhone5, MobilePhone5, 100, 0 +18870, MobilePhone6, MobilePhone6, 100, 0 +18871, MobilePhone7, MobilePhone7, 100, 0 +18872, MobilePhone8, MobilePhone8, 100, 0 +18873, MobilePhone9, MobilePhone9, 100, 0 +18874, MobilePhone10, MobilePhone10, 100, 0 +18875, Pager1, Pager1, 100, 0 +18876, BigGreenGloop1, gloopX, 200, 2097152 +18877, FerrisWheelBit, FerrisWheel, 299, 4 +18878, FerrisBaseBit, FerrisWheel, 299, 2097156 +18879, FerrisCageBit, FerrisWheel, 200, 0 +18880, SpeedCamera1, SpeedCamera1, 150, 0 +18881, SkyDivePlatform2, MatRacing, 299, 2097152 +18882, HugeBowl1, HugeBowls, 299, 0 +18883, HugeBowl2, HugeBowls, 299, 0 +18884, HugeBowl3, HugeBowls, 299, 4 +18885, GunVendingMachine1, GunVendingMachine1, 50, 0 +18886, ElectroMagnet1, ElectroMagnet1, 150, 0 +18887, ForceField1, ForceFields, 150, 4 +18888, ForceField2, ForceFields, 150, 4 +18889, ForceField3, ForceFields, 150, 4 +18890, Rake1, Rake1, 50, 0 +18891, Bandana1, MatClothes, 100, 2097152 +18892, Bandana2, MatClothes, 100, 2097152 +18893, Bandana3, MatClothes, 100, 2097152 +18894, Bandana4, MatClothes, 100, 2097152 +18895, Bandana5, MatClothes, 100, 2097152 +18896, Bandana6, MatClothes, 100, 2097152 +18897, Bandana7, MatClothes, 100, 2097152 +18898, Bandana8, MatClothes, 100, 2097152 +18899, Bandana9, MatClothes, 100, 2097152 +18900, Bandana10, MatClothes, 100, 2097152 +18901, Bandana11, MatClothes, 100, 2097152 +18902, Bandana12, MatClothes, 100, 2097152 +18903, Bandana13, MatClothes, 100, 2097152 +18904, Bandana14, MatClothes, 100, 2097152 +18905, Bandana15, MatClothes, 100, 2097152 +18906, Bandana16, MatClothes, 100, 2097152 +18907, Bandana17, MatClothes, 100, 2097152 +18908, Bandana18, MatClothes, 100, 2097152 +18909, Bandana19, MatClothes, 100, 2097152 +18910, Bandana20, MatClothes, 100, 2097152 +18911, Mask1, MatClothes, 100, 2097152 +18912, Mask2, MatClothes, 100, 2097152 +18913, Mask3, MatClothes, 100, 2097152 +18914, Mask4, MatClothes, 100, 2097152 +18915, Mask5, MatClothes, 100, 2097152 +18916, Mask6, MatClothes, 100, 2097152 +18917, Mask7, MatClothes, 100, 2097152 +18918, Mask8, MatClothes, 100, 2097152 +18919, Mask9, MatClothes, 100, 2097152 +18920, Mask10, MatClothes, 100, 2097152 +18921, Beret1, MatClothes, 100, 2097152 +18922, Beret2, MatClothes, 100, 2097152 +18923, Beret3, MatClothes, 100, 2097152 +18924, Beret4, MatClothes, 100, 2097152 +18925, Beret5, MatClothes, 100, 2097152 +18926, Hat1, MatClothes, 100, 2097152 +18927, Hat2, MatClothes, 100, 2097152 +18928, Hat3, MatClothes, 100, 2097152 +18929, Hat4, MatClothes, 100, 2097152 +18930, Hat5, MatClothes, 100, 2097152 +18931, Hat6, MatClothes, 100, 2097152 +18932, Hat7, MatClothes, 100, 2097152 +18933, Hat8, MatClothes, 100, 2097152 +18934, Hat9, MatClothes, 100, 2097152 +18935, Hat10, MatClothes, 100, 2097152 +18936, Helmet1, MatClothes, 100, 2097152 +18937, Helmet2, MatClothes, 100, 2097152 +18938, Helmet3, MatClothes, 100, 2097152 +18939, CapBack1, MatClothes, 100, 2097152 +18940, CapBack2, MatClothes, 100, 2097152 +18941, CapBack3, MatClothes, 100, 2097152 +18942, CapBack4, MatClothes, 100, 2097152 +18943, CapBack5, MatClothes, 100, 2097152 +18944, HatBoater1, MatClothes, 100, 2097152 +18945, HatBoater2, MatClothes, 100, 2097152 +18946, HatBoater3, MatClothes, 100, 2097152 +18947, HatBowler1, MatClothes, 100, 2097152 +18948, HatBowler2, MatClothes, 100, 2097152 +18949, HatBowler3, MatClothes, 100, 2097152 +18950, HatBowler4, MatClothes, 100, 2097152 +18951, HatBowler5, MatClothes, 100, 2097152 +18952, BoxingHelmet1, MatClothes, 100, 2097152 +18953, CapKnit1, MatClothes, 100, 2097152 +18954, CapKnit2, MatClothes, 100, 2097152 +18955, CapOverEye1, MatClothes, 100, 2097152 +18956, CapOverEye2, MatClothes, 100, 2097152 +18957, CapOverEye3, MatClothes, 100, 2097152 +18958, CapOverEye4, MatClothes, 100, 2097152 +18959, CapOverEye5, MatClothes, 100, 2097152 +18960, CapRimUp1, MatClothes, 100, 2097152 +18961, CapTrucker1, MatClothes, 100, 2097152 +18962, CowboyHat2, CowboyHats, 100, 2097152 +18963, CJElvisHead, MatClothes, 100, 2097152 +18964, SkullyCap1, MatClothes, 100, 2097152 +18965, SkullyCap2, MatClothes, 100, 2097152 +18966, SkullyCap3, MatClothes, 100, 2097152 +18967, HatMan1, MatClothes, 100, 2097152 +18968, HatMan2, MatClothes, 100, 2097152 +18969, HatMan3, MatClothes, 100, 2097152 +18970, HatTiger1, MatClothes, 100, 2097152 +18971, HatCool1, MatClothes, 100, 2097152 +18972, HatCool2, MatClothes, 100, 2097152 +18973, HatCool3, MatClothes, 100, 2097152 +18974, MaskZorro1, MatClothes, 100, 2097152 +18975, Hair2, Hair2, 100, 2097152 +18976, MotorcycleHelmet2, MatClothes, 100, 2097152 +18977, MotorcycleHelmet3, MatClothes, 100, 2097152 +18978, MotorcycleHelmet4, noncolored, 100, 2097152 +18979, MotorcycleHelmet5, MatClothes, 100, 2097152 +18980, Concrete1mx1mx25m, ConcreteBits, 150, 0 +18981, Concrete1mx25mx25m, ConcreteBits, 150, 0 +18982, Tube100m3, MatTextures, 299, 0 +18983, Tube100m4, MatTextures, 299, 0 +18984, Tube100m5, MatTextures, 299, 0 +18985, Tube100m6, MatTextures, 299, 0 +18986, TubeToPipe1, MatTextures, 299, 0 +18987, Tube25m1, MatTextures, 299, 0 +18988, Tube25mCutEnd1, MatTextures, 299, 0 +18989, Tube25m45Bend1, MatTextures, 299, 0 +18990, Tube25m90Bend1, MatTextures, 299, 0 +18991, Tube25m180Bend1, MatTextures, 299, 0 +18992, Tube10m45Bend1, MatTextures, 299, 0 +18993, Tube10m90Bend1, MatTextures, 299, 0 +18994, Tube10m180Bend1, MatTextures, 299, 0 +18995, Tube5m1, MatTextures, 299, 0 +18996, Tube5m45Bend1, MatTextures, 299, 0 +18997, Tube1m1, MatTextures, 299, 0 +18998, Tube200m1, MatTextures, 299, 0 +18999, Tube200mBendy1, MatTextures, 299, 0 +19000, Tube200mBulge1, MatTextures, 299, 0 +19001, VCWideLoop1, MatRamps, 250, 0 +19002, FireHoop1, MatRamps, 250, 0 +19003, RampT5, MatRamps, 280, 0 +19004, RoundBuilding1, RoundBuilding1, 299, 2097156 +19005, RampT4, MatRamps, 280, 0 +19006, GlassesType1, MatGlasses, 100, 2097156 +19007, GlassesType2, MatGlasses, 100, 2097156 +19008, GlassesType3, MatGlasses, 100, 2097156 +19009, GlassesType4, MatGlasses, 100, 2097156 +19010, GlassesType5, MatGlasses, 100, 2097156 +19011, GlassesType6, MatGlasses, 100, 2097156 +19012, GlassesType7, MatGlasses, 100, 2097156 +19013, GlassesType8, MatGlasses, 100, 2097156 +19014, GlassesType9, MatGlasses, 100, 2097156 +19015, GlassesType10, MatGlasses, 100, 2097156 +19016, GlassesType11, MatGlasses, 100, 2097156 +19017, GlassesType12, MatGlasses, 100, 2097156 +19018, GlassesType13, MatGlasses, 100, 2097156 +19019, GlassesType14, MatGlasses, 100, 2097156 +19020, GlassesType15, MatGlasses, 100, 2097156 +19021, GlassesType16, MatGlasses, 100, 2097156 +19022, GlassesType17, MatGlasses, 100, 2097156 +19023, GlassesType18, MatGlasses, 100, 2097156 +19024, GlassesType19, MatGlasses, 100, 2097156 +19025, GlassesType20, MatGlasses, 100, 2097156 +19026, GlassesType21, MatGlasses, 100, 2097156 +19027, GlassesType22, MatGlasses, 100, 2097156 +19028, GlassesType23, MatGlasses, 100, 2097156 +19029, GlassesType24, MatGlasses, 100, 2097156 +19030, GlassesType25, MatGlasses, 100, 2097156 +19031, GlassesType26, MatGlasses, 100, 2097156 +19032, GlassesType27, MatGlasses, 100, 2097156 +19033, GlassesType28, MatGlasses, 100, 2097156 +19034, GlassesType29, MatGlasses, 100, 2097156 +19035, GlassesType30, MatGlasses, 100, 2097156 +19036, HockeyMask1, MatHockey, 100, 2097156 +19037, HockeyMask2, MatHockey, 100, 2097156 +19038, HockeyMask3, MatHockey, 100, 2097156 +19039, WatchType1, MatWatches, 100, 2097156 +19040, WatchType2, MatWatches, 100, 2097156 +19041, WatchType3, MatWatches, 100, 2097156 +19042, WatchType4, MatWatches, 100, 2097156 +19043, WatchType5, MatWatches, 100, 2097156 +19044, WatchType6, MatWatches, 100, 2097156 +19045, WatchType7, MatWatches, 100, 2097156 +19046, WatchType8, MatWatches, 100, 2097156 +19047, WatchType9, MatWatches, 100, 2097156 +19048, WatchType10, MatWatches, 100, 2097156 +19049, WatchType11, MatWatches, 100, 2097156 +19050, WatchType12, MatWatches, 100, 2097156 +19051, WatchType13, MatWatches, 100, 2097156 +19052, WatchType14, MatWatches, 100, 2097156 +19053, WatchType15, MatWatches, 100, 2097156 +# ------------------------------------------------------ +# Objects added in RC4 (109 Objects) +19054, XmasBox1, XmasBoxes, 100, 0 +19055, XmasBox2, XmasBoxes, 100, 0 +19056, XmasBox3, XmasBoxes, 100, 0 +19057, XmasBox4, XmasBoxes, 100, 0 +19058, XmasBox5, XmasBoxes, 100, 0 +19059, XmasOrb1, XmasOrbs, 100, 0 +19060, XmasOrb2, XmasOrbs, 100, 0 +19061, XmasOrb3, XmasOrbs, 100, 0 +19062, XmasOrb4, XmasOrbs, 100, 0 +19063, XmasOrb5, XmasOrbs, 100, 0 +19064, SantaHat1, SantaHats, 100, 2097152 +19065, SantaHat2, SantaHats, 100, 2097152 +19066, SantaHat3, SantaHats, 100, 2097152 +19067, HoodyHat1, HoodyHats, 100, 2097152 +19068, HoodyHat2, HoodyHats, 100, 2097152 +19069, HoodyHat3, HoodyHats, 100, 2097152 +19070, WSDown1, WSSections, 299, 2097156 +19071, WSStraight1, WSSections, 299, 2097156 +19072, WSBend45Deg1, WSSections, 299, 2097156 +19073, WSRocky1, WSSections, 299, 2097156 +19074, Cage20mx20mx10mv2, MatTextures, 250, 4 +19075, Cage5mx5mx3mv2, MatTextures, 250, 4 +19076, XmasTree1, XmasTree1, 200, 2097156 +19077, Hair3, Hair3, 100, 2097152 +19078, TheParrot1, TheParrot, 100, 0 +19079, TheParrot2, TheParrot, 100, 0 +19080, LaserPointer2, LaserPointer2, 100, 4 +19081, LaserPointer3, LaserPointer3, 100, 4 +19082, LaserPointer4, LaserPointer4, 100, 4 +19083, LaserPointer5, LaserPointer5, 100, 4 +19084, LaserPointer6, LaserPointer6, 100, 4 +19085, EyePatch1, EyePatch1, 100, 2097152 +19086, ChainsawDildo1, sexdetail, 100, 2097152 +19087, Rope1, MatRopes, 150, 0 +19088, Rope2, MatRopes, 150, 0 +19089, Rope3, MatRopes, 150, 0 +19090, PomPomBlue, PomPoms, 100, 0 +19091, PomPomRed, PomPoms, 100, 0 +19092, PomPomGreen, PomPoms, 100, 0 +19093, HardHat2, NewHardHats, 100, 2097152 +19094, BurgerShotHat1, wfyburg, 100, 0 +19095, CowboyHat1, CowboyHats, 100, 2097152 +19096, CowboyHat3, CowboyHats, 100, 2097152 +19097, CowboyHat4, CowboyHats, 100, 2097152 +19098, CowboyHat5, CowboyHats, 100, 2097152 +19099, PoliceCap2, PoliceCaps, 100, 2097152 +19100, PoliceCap3, PoliceCaps, 100, 2097152 +19101, ArmyHelmet1, ArmyHelmets, 100, 2097152 +19102, ArmyHelmet2, ArmyHelmets, 100, 2097152 +19103, ArmyHelmet3, ArmyHelmets, 100, 2097152 +19104, ArmyHelmet4, ArmyHelmets, 100, 2097152 +19105, ArmyHelmet5, ArmyHelmets, 100, 2097152 +19106, ArmyHelmet6, ArmyHelmets, 100, 2097152 +19107, ArmyHelmet7, ArmyHelmets, 100, 2097152 +19108, ArmyHelmet8, ArmyHelmets, 100, 2097152 +19109, ArmyHelmet9, ArmyHelmets, 100, 2097152 +19110, ArmyHelmet10, ArmyHelmets, 100, 2097152 +19111, ArmyHelmet11, ArmyHelmets, 100, 2097152 +19112, ArmyHelmet12, ArmyHelmets, 100, 2097152 +19113, SillyHelmet1, SillyHelmets, 100, 2097152 +19114, SillyHelmet2, SillyHelmets, 100, 2097152 +19115, SillyHelmet3, SillyHelmets, 100, 2097152 +19116, PlainHelmet1, PlainHelmets, 100, 2097152 +19117, PlainHelmet2, PlainHelmets, 100, 2097152 +19118, PlainHelmet3, PlainHelmets, 100, 2097152 +19119, PlainHelmet4, PlainHelmets, 100, 2097152 +19120, PlainHelmet5, PlainHelmets, 100, 2097152 +19121, BollardLight1, metal, 200, 2097156 +19122, BollardLight2, metal, 200, 2097156 +19123, BollardLight3, metal, 200, 2097156 +19124, BollardLight4, metal, 200, 2097156 +19125, BollardLight5, metal, 200, 2097156 +19126, BollardLight6, metal, 200, 2097156 +19127, BollardLight7, metal, 200, 2097156 +19128, DanceFloor1, DanceFloors, 250, 0 +19129, DanceFloor2, DanceFloors, 250, 0 +19130, ArrowType1, MatArrows, 120, 0 +19131, ArrowType2, MatArrows, 120, 0 +19132, ArrowType3, MatArrows, 120, 0 +19133, ArrowType4, MatArrows, 120, 0 +19134, ArrowType5, MatArrows, 120, 0 +19135, EnExMarker1, EnExMarkers, 150, 0 +19136, Hair4, smyst2, 100, 0 +19137, CluckinBellHat1, wmybell, 100, 2097152 +19138, PoliceGlasses1, PoliceGlasses, 100, 2097152 +19139, PoliceGlasses2, PoliceGlasses, 100, 2097152 +19140, PoliceGlasses3, PoliceGlasses, 100, 2097152 +19141, SWATHelmet1, swat, 100, 2097152 +19142, SWATArmour1, swat, 100, 2097152 +19143, PinSpotLight1, PinSpotLights, 150, 0 +19144, PinSpotLight2, PinSpotLights, 150, 0 +19145, PinSpotLight3, PinSpotLights, 150, 0 +19146, PinSpotLight4, PinSpotLights, 150, 0 +19147, PinSpotLight5, PinSpotLights, 150, 0 +19148, PinSpotLight6, PinSpotLights, 150, 0 +19149, PinSpotLight7, PinSpotLights, 150, 0 +19150, PinSpotLight8, PinSpotLights, 150, 0 +19151, PinSpotLight9, PinSpotLights, 150, 0 +19152, PinSpotLight10, PinSpotLights, 150, 0 +19153, PinSpotLight11, PinSpotLights, 150, 0 +19154, PinSpotLight12, PinSpotLights, 150, 0 +19155, PinSpotLight13, PinSpotLights, 150, 0 +19156, PinSpotLight14, PinSpotLights, 150, 0 +19157, MetalLightBars1, MetalLightBars, 150, 0 +19158, MetalLightBars2, MetalLightBars, 150, 0 +19159, MirrorBall1, MirrorBall1, 150, 0 +19160, HardHat3, NewHardHats, 100, 2097152 +19161, PoliceHat1, NewPoliceHats, 100, 2097152 +19162, PoliceHat2, NewPoliceHats, 100, 2097152 +19163, GimpMask1, GimpMask1, 100, 0 +# ------------------------------------------------------ +# Objects added in RC5 (143 Objects) +19164, GTASAMap1, gtamap, 150, 0 +19165, GTASAMap2, gtamap, 150, 0 +19166, GTASAMap3, gtamap, 100, 0 +19167, GTASAMap4, gtamap, 100, 0 +19168, GTASAMap5, gtamap, 100, 0 +19169, GTASAMap6, gtamap, 100, 0 +19170, GTASAMap7, gtamap, 100, 0 +19171, GTASAMap8, gtamap, 100, 0 +19172, SAMPPicture1, SAMPPictures, 100, 0 +19173, SAMPPicture2, SAMPPictures, 100, 0 +19174, SAMPPicture3, SAMPPictures, 100, 0 +19175, SAMPPicture4, SAMPPictures, 100, 0 +19176, LSOffice1Door1, skyscrapelan2, 150, 0 +19177, MapMarkerNew1, MapMarkers, 50, 0 +19178, MapMarkerNew2, MapMarkers, 50, 0 +19179, MapMarkerNew3, MapMarkers, 50, 0 +19180, MapMarkerNew4, MapMarkers, 50, 0 +19181, MapMarkerNew5, MapMarkers, 50, 0 +19182, MapMarkerNew6, MapMarkers, 50, 0 +19183, MapMarkerNew7, MapMarkers, 50, 0 +19184, MapMarkerNew8, MapMarkers, 50, 0 +19185, MapMarkerNew9, MapMarkers, 50, 0 +19186, MapMarkerNew10, MapMarkers, 50, 0 +19187, MapMarkerNew11, MapMarkers, 50, 0 +19188, MapMarkerNew12, MapMarkers, 50, 0 +19189, MapMarkerNew13, MapMarkers, 50, 0 +19190, MapMarkerNew14, MapMarkers, 50, 0 +19191, MapMarkerNew15, MapMarkers, 50, 0 +19192, MapMarkerNew16, MapMarkers, 50, 0 +19193, MapMarkerNew17, MapMarkers, 50, 0 +19194, MapMarkerNew18, MapMarkers, 50, 0 +19195, MapMarkerNew19, MapMarkers, 50, 0 +19196, MapMarkerNew20, MapMarkers, 50, 0 +19197, EnExMarker2, EnExMarkers, 150, 2097220 +19198, EnExMarker3, EnExMarkers, 150, 2097220 +19200, PoliceHelmet1, lapdm1, 100, 2097152 +19201, MapMarker1, MapMarkers, 50, 0 +19202, MapMarker2, MapMarkers, 50, 0 +19203, MapMarker3, MapMarkers, 50, 0 +19204, MapMarker4, MapMarkers, 50, 0 +19205, MapMarker5, MapMarkers, 50, 0 +19206, MapMarker6, MapMarkers, 50, 0 +19207, MapMarker7, MapMarkers, 50, 0 +19208, MapMarker8, MapMarkers, 50, 0 +19209, MapMarker9, MapMarkers, 50, 0 +19210, MapMarker10, MapMarkers, 50, 0 +19211, MapMarker11, MapMarkers, 50, 0 +19212, MapMarker12, MapMarkers, 50, 0 +19213, MapMarker13, MapMarkers, 50, 0 +19214, MapMarker14, MapMarkers, 50, 0 +19215, MapMarker15, MapMarkers, 50, 0 +19216, MapMarker16, MapMarkers, 50, 0 +19217, MapMarker17, MapMarkers, 50, 0 +19218, MapMarker18, MapMarkers, 50, 0 +19219, MapMarker19, MapMarkers, 50, 0 +19220, MapMarker20, MapMarkers, 50, 0 +19221, MapMarker21, MapMarkers, 50, 0 +19222, MapMarker22, MapMarkers, 50, 0 +19223, MapMarker23, MapMarkers, 50, 0 +19224, MapMarker24, MapMarkers, 50, 0 +19225, MapMarker25, MapMarkers, 50, 0 +19226, MapMarker26, MapMarkers, 50, 0 +19227, MapMarker27, MapMarkers, 50, 0 +19228, MapMarker28, MapMarkers, 50, 0 +19229, MapMarker29, MapMarkers, 50, 0 +19230, MapMarker30, MapMarkers, 50, 0 +19231, MapMarker31, MapMarkers, 50, 0 +19232, MapMarker32, MapMarkers, 50, 0 +19233, MapMarker33, MapMarkers, 50, 0 +19234, MapMarker34, MapMarkers, 50, 0 +19235, MapMarker35, MapMarkers, 50, 0 +19236, MapMarker36, MapMarkers, 50, 0 +19237, MapMarker37, MapMarkers, 50, 0 +19238, MapMarker38, MapMarkers, 50, 0 +19239, MapMarker39, MapMarkers, 50, 0 +19240, MapMarker40, MapMarkers, 50, 0 +19241, MapMarker41, MapMarkers, 50, 0 +19242, MapMarker42, MapMarkers, 50, 0 +19243, MapMarker43, MapMarkers, 50, 0 +19244, MapMarker44, MapMarkers, 50, 0 +19245, MapMarker45, MapMarkers, 50, 0 +19246, MapMarker46, MapMarkers, 50, 0 +19247, MapMarker47, MapMarkers, 50, 0 +19248, MapMarker48, MapMarkers, 50, 0 +19249, MapMarker49, MapMarkers, 50, 0 +19250, MapMarker50, MapMarkers, 50, 0 +19251, MapMarker51, MapMarkers, 50, 0 +19252, MapMarker52, MapMarkers, 50, 0 +19253, MapMarker53, MapMarkers, 50, 0 +19254, MapMarker54, MapMarkers, 50, 0 +19255, MapMarker55, MapMarkers, 50, 0 +19256, MapMarker56, MapMarkers, 50, 0 +19257, MapMarker57, MapMarkers, 50, 0 +19258, MapMarker58, MapMarkers, 50, 0 +19259, MapMarker59, MapMarkers, 50, 0 +19260, MapMarker60, MapMarkers, 50, 0 +19261, MapMarker61, MapMarkers, 50, 0 +19262, MapMarker62, MapMarkers, 50, 0 +19263, MapMarker63, MapMarkers, 50, 0 +19264, MapMarker1a, MapMarkers, 50, 0 +19265, MapMarker1b, MapMarkers, 50, 0 +19266, MapMarker31a, MapMarkers, 50, 0 +19267, MapMarker31b, MapMarkers, 50, 0 +19268, MapMarker31c, MapMarkers, 50, 0 +19269, MapMarker31d, MapMarkers, 50, 0 +19270, MapMarkerFire1, MapMarkers, 50, 0 +19271, MapMarkerLight1, MapMarkers, 50, 0 +19272, DMCage3, DMCages, 250, 2097156 +19273, KeypadNonDynamic, keypad, 100, 2097152 +19274, Hair5, wmoice, 100, 2097152 +#19275, SAMPLogo2, SAMPLogos, 100, 0 +#19276, SAMPLogo3, SAMPLogos, 100, 0 +19277, LiftType1, MatLifts, 200, 4 +19278, LiftPlatform1, SkyDivePlatforms, 299, 2097156 +19279, LCSmallLight1, MatLights, 120, 0 +19280, CarRoofLight1, MatLights, 120, 0 +19281, PointLight1, MatLights, 120, 4 +19282, PointLight2, MatLights, 120, 4 +19283, PointLight3, MatLights, 120, 4 +19284, PointLight4, MatLights, 120, 4 +19285, PointLight5, MatLights, 120, 4 +19286, PointLight6, MatLights, 120, 4 +19287, PointLight7, MatLights, 120, 4 +19288, PointLight8, MatLights, 120, 4 +19289, PointLight9, MatLights, 120, 4 +19290, PointLight10, MatLights, 120, 4 +19291, PointLight11, MatLights, 120, 4 +19292, PointLight12, MatLights, 120, 4 +19293, PointLight13, MatLights, 120, 4 +19294, PointLight14, MatLights, 120, 4 +19295, PointLight15, MatLights, 120, 4 +19296, PointLight16, MatLights, 120, 4 +19297, PointLight17, MatLights, 120, 4 +19298, PointLight18, MatLights, 120, 4 +19299, PointLightMoon1, MatLights, 170, 4 +19300, blankmodel, MatTextures, 100, 0 +# ------------------------------------------------------ +# Objects added by cessil (Late 2011) +# ----------------------------------- +# Replacement sfpd interior without cell doors +19301, mp_sfpd_nocell, mp_policeSF, 100, 0 +# Cell door components that can be used in all PDs +19302, pd_jail_door01, pd_jail_door01, 299, 2097284 +19303, pd_jail_door02, pd_jail_door02, 299, 2097284 +19304, pd_jail_door_top01, pd_jail_door_top01, 299, 2097284 +# ------------------------------------------------------ +# The three objects below were missing in 0.3z and +# have been added in SA:MP 0.3.7 by Matite +# ---------------------------------------- +# This security keypad is the same as ID 2886 except it has +# a back on it so it can be used as a pickup. +# It also has no collision. +19305, sec_keypad2, keypad, 100, 0 +# This flag is the same as object ID 2993 except it is red. +19306, kmb_goflag2, goflagx2, 100, 0 +# This flag is the same as object ID 2993 except it is blue. +19307, kmb_goflag3, goflagx2, 100, 0 +# ------------------------------------------------------ +# Taxi signs which can be attached to vehicles +19308, taxi01, taxi01, 150, 0 +19309, taxi02, taxi02, 150, 0 +19310, taxi03, taxi03, 150, 0 +19311, taxi04, taxi04, 150, 0 +# Area 51 fencing as seperate objects +19312, a51fencing, a51fencing, 200, 2097156 +19313, a51fensin, a51fencing, 200, 2097156 +# Car bullhorns +19314, bullhorns01, bullhorns01, 100, 0 +# Deer +19315, deer01, deer01, 100, 0 +# Ferris wheel cage with no roof +19316, FerrisCageBit01, FerrisWheel, 200, 0 +# Guitars +19317, bassguitar01, bassguitar01, 100, 0 +19318, flyingv01, flyingv01, 100, 0 +19319, warlock01, warlock01, 100, 0 +# Pumpkin +19320, pumpkin01, pumpkin01, 100, 0 +19321, cuntainer, continX, 100, 2097152 +# LS Mall Replacement +19322, mallb_laW02, mall_law, 200, 0 +19323, lsmall_shop01, lsmall_shops, 200, 0 +# ------------------------------------------------------ +# The object below was missing in 0.3z and +# has been added in SA:MP 0.3.7 by Matite +# --------------------------------------- +# This ATM is the same as object ID 2942 except it is +# not dynamic and the texture on the back has been +# fixed. +19324, kmb_atm1_2, kmb_atmx, 100, 0 +# ------------------------------------------------------ +19325, lsmall_window01, lsmall_shops, 200, 2097220 +19326, 7_11_sign01, 7_11_posters, 100, 0 +19327, 7_11_sign02, 7_11_posters, 100, 0 +19328, 7_11_sign03, 7_11_posters, 100, 0 +19329, 7_11_sign04, 7_11_posters, 100, 0 +# Fireman hats +19330, fire_hat01, firehats, 100, 0 +19331, fire_hat02, firehats, 100, 0 +# Hot air balloons +19332, Hot_Air_Balloon01, balloon_texts, 200, 2097152 +19333, Hot_Air_Balloon02, balloon_texts, 200, 2097152 +19334, Hot_Air_Balloon03, balloon_texts, 200, 2097152 +19335, Hot_Air_Balloon04, balloon_texts, 200, 2097152 +19336, Hot_Air_Balloon05, balloon_texts, 200, 2097152 +19337, Hot_Air_Balloon06, balloon_texts, 200, 2097152 +19338, Hot_Air_Balloon07, balloon_texts, 200, 2097152 +# Coffin +19339, coffin01, coffin01, 200, 0 +# concrete slab for SF +19340, cslab01, carshow_sfse, 200, 0 +# Easter eggs +19341, easter_egg01, egg_texts, 100, 0 +19342, easter_egg02, egg_texts, 100, 0 +19343, easter_egg03, egg_texts, 100, 0 +19344, easter_egg04, egg_texts, 100, 0 +19345, easter_egg05, egg_texts, 100, 0 +# Hotdog +19346, hotdog01, hotdog01, 100, 0 +# Made by cessil 03-2012 +19347, badge01, police_things, 100, 0 +19348, cane01, classy, 100, 0 +19349, monocle01, classy, 100, 2097156 +19350, moustache01, classy, 100, 0 +19351, moustache02, classy, 100, 0 +19352, tophat01, classy, 100, 0 +# Textured wall sections +19353, wall001, all_walls, 100, 0 +19354, wall002, all_walls, 100, 0 +19355, wall003, all_walls, 100, 0 +19356, wall004, all_walls, 100, 0 +19357, wall005, all_walls, 100, 0 +19358, wall006, all_walls, 100, 0 +19359, wall007, all_walls, 100, 0 +19360, wall008, all_walls, 100, 0 +19361, wall009, all_walls, 100, 0 +19362, wall010, all_walls, 100, 0 +19363, wall011, all_walls, 100, 0 +19364, wall012, all_walls, 100, 0 +19365, wall013, all_walls, 100, 0 +19366, wall014, all_walls, 100, 0 +19367, wall015, all_walls, 100, 0 +19368, wall016, all_walls, 100, 0 +19369, wall017, all_walls, 100, 0 +19370, wall018, all_walls, 100, 0 +19371, wall019, all_walls, 100, 0 +19372, wall020, all_walls, 100, 0 +19373, wall021, all_walls, 100, 0 +19374, wall022, all_walls, 100, 0 +19375, wall023, all_walls, 100, 0 +19376, wall024, all_walls, 100, 0 +19377, wall025, all_walls, 100, 0 +19378, wall026, all_walls, 100, 0 +19379, wall027, all_walls, 100, 0 +19380, wall028, all_walls, 100, 0 +19381, wall029, all_walls, 100, 0 +19382, wall030, all_walls, 100, 0 +19383, wall031, all_walls, 100, 0 +19384, wall032, all_walls, 100, 0 +19385, wall033, all_walls, 100, 0 +19386, wall034, all_walls, 100, 0 +19387, wall035, all_walls, 100, 0 +19388, wall036, all_walls, 100, 0 +19389, wall037, all_walls, 100, 0 +19390, wall038, all_walls, 100, 0 +19391, wall039, all_walls, 100, 0 +19392, wall040, all_walls, 100, 0 +19393, wall041, all_walls, 100, 0 +19394, wall042, all_walls, 100, 0 +19395, wall043, all_walls, 100, 0 +19396, wall044, all_walls, 100, 0 +19397, wall045, all_walls, 100, 0 +19398, wall046, all_walls, 100, 0 +19399, wall047, all_walls, 100, 0 +19400, wall048, all_walls, 100, 0 +19401, wall049, all_walls, 100, 0 +19402, wall050, all_walls, 100, 0 +19403, wall051, all_walls, 100, 0 +19404, wall052, all_walls, 100, 0 +19405, wall053, all_walls, 100, 0 +19406, wall054, all_walls, 100, 0 +19407, wall055, all_walls, 100, 0 +19408, wall056, all_walls, 100, 0 +19409, wall057, all_walls, 100, 0 +19410, wall058, all_walls, 100, 0 +19411, wall059, all_walls, 100, 0 +19412, wall060, all_walls, 100, 0 +19413, wall061, all_walls, 100, 0 +19414, wall062, all_walls, 100, 0 +19415, wall063, all_walls, 100, 0 +19416, wall064, all_walls, 100, 0 +19417, wall065, all_walls, 100, 0 +19418, handcuffs01, police_things, 100, 0 +19419, police_lights01, police_things, 100, 0 +19420, police_lights02, police_things, 100, 0 +19421, headphones01, headphones, 100, 0 +19422, headphones02, headphones, 100, 0 +19423, headphones03, headphones, 100, 0 +19424, headphones04, headphones, 100, 0 +19425, speed_bump01, speed_bumps, 100, 0 +19426, wall066, all_walls, 100, 0 +19427, wall067, all_walls, 100, 0 +19428, wall068, all_walls, 100, 0 +19429, wall069, all_walls, 100, 0 +19430, wall070, all_walls, 100, 0 +19431, wall071, all_walls, 100, 0 +19432, wall072, all_walls, 100, 0 +19433, wall073, all_walls, 100, 0 +19434, wall074, all_walls, 100, 0 +19435, wall075, all_walls, 100, 0 +19436, wall076, all_walls, 100, 0 +19437, wall077, all_walls, 100, 0 +19438, wall078, all_walls, 100, 0 +19439, wall079, all_walls, 100, 0 +19440, wall080, all_walls, 100, 0 +19441, wall081, all_walls, 100, 0 +19442, wall082, all_walls, 100, 0 +19443, wall083, all_walls, 100, 0 +19444, wall084, all_walls, 100, 0 +19445, wall085, all_walls, 100, 0 +19446, wall086, all_walls, 100, 0 +19447, wall087, all_walls, 100, 0 +19448, wall088, all_walls, 100, 0 +19449, wall089, all_walls, 100, 0 +19450, wall090, all_walls, 100, 0 +19451, wall091, all_walls, 100, 0 +19452, wall092, all_walls, 100, 0 +19453, wall093, all_walls, 100, 0 +19454, wall094, all_walls, 100, 0 +19455, wall095, all_walls, 100, 0 +19456, wall096, all_walls, 100, 0 +19457, wall097, all_walls, 100, 0 +19458, wall098, all_walls, 100, 0 +19459, wall099, all_walls, 100, 0 +19460, wall100, all_walls, 100, 0 +19461, wall101, all_walls, 100, 0 +19462, wall102, all_walls, 100, 0 +19463, wall103, all_walls, 100, 0 +19464, wall104, all_walls, 100, 0 +19465, wall105, all_walls, 100, 0 +19466, window001, lsmall_shops, 100, 2097220 +19467, vehicle_barrier01, speed_bumps, 100, 0 +19468, bucket01, bucket01, 100, 2097152 +19469, scarf01, classy, 100, 2097152 +19470, forsale01, forsale01, 100, 2097152 +19471, forsale02, forsale01, 100, 2097152 +19472, gasmask01, gasmask01, 100, 0 +19473, grassplant01, grasshouse, 100, 2097156 +19474, pokertable01, kbroul1, 100, 0 +#----------------------------------------------------------------- +# Blank planes for text signs +19475, Plane001, signsurf, 299, 2097284 +19476, Plane002, signsurf, 299, 2097284 +19477, Plane003, signsurf, 299, 2097284 +19478, Plane004, signsurf, 299, 2097284 +19479, Plane005, signsurf, 299, 2097284 +19480, Plane006, signsurf, 299, 2097284 +19481, Plane007, signsurf, 299, 2097284 +19482, Plane008, signsurf, 299, 2097284 +19483, Plane009, signsurf, 299, 2097284 +#----------------------------------------------------------------- +19484, landbit01_01, bakerybit2_sfse, 200, 0 +19485, Groundbit84_SFS_01, skyscrap_sfse, 200, 0 +#----------------------------------------------------------------- +# SF Harry Plums Building +# ----------------------- +# Updated the object below in 0.3.7 (side doors now open and +# interior vertex colour fixes). +19486, SFHarryPlums1, burgalrystore_sfse, 299, 4 +#----------------------------------------------------------------- +# Non-coloured hats #1 +19487, tophat02, noncolored, 200, 0 +19488, HatBowler6, noncolored, 200, 0 +#----------------------------------------------------------------- +19489, sfhouse1, boxhses_sfsx, 200, 2097280 +19490, sfhouse1int, all_walls, 200, 128 +19491, sfhouse2, boxhses_sfsx, 200, 128 +19492, sfhouse2int, all_walls, 200, 128 +19493, sfhouse3, boxhses_sfsx, 200, 128 +19494, sfhouse3int, all_walls, 200, 128 +19495, sfhouse4, boxhses_sfsx, 200, 2097280 +19496, sfhouse4int, all_walls, 200, 128 +19497, lvhouse1, vegashse2, 200, 2097280 +19498, lvhouse1int, all_walls, 200, 128 +19499, lvhouse2, vegashse3, 200, 2097280 +19500, lvhouse2int, all_walls, 200, 128 +19501, lvhouse3, vegashse6, 200, 2097280 +19502, lvhouse3int, all_walls, 200, 128 +19503, lvhouse4, vegashse4, 200, 128 +19504, lvhouse4int, all_walls, 200, 128 +19505, lshouse1, ganghouse1_lax, 200, 128 +19506, lshouse1int, all_walls, 200, 128 +19507, lshouse2, ganghouse1_lax, 200, 128 +19508, lshouse2int, all_walls, 200, 128 +19509, lshouse3, comedhos1_la, 200, 128 +19510, lshouse3int, all_walls, 200, 128 +19511, lshouse4, glenphouse_lax, 200, 128 +19512, lshouse4int, all_walls, 200, 128 +19513, whitephone, whitephone, 100, 0 +19514, SWATHgrey, swatgrey, 100, 2097152 +19515, SWATAgrey, swatgrey, 100, 2097152 +#----------------------------------------------------------------- +# Non-coloured hair #1 +19516, Hair2_nc, noncolored, 200, 0 +19517, Hair3_nc, noncolored, 200, 0 +19518, Hair5_nc, noncolored, 200, 0 +19519, Hair1_nc, noncolored, 200, 0 +19520, pilotHat01, pilotPoliceHat, 200, 0 +19521, policeHat01, pilotPoliceHat, 200, 0 +#----------------------------------------------------------------- +#----------------------------------------------------------------- +# Objects Added by Matite in SA:MP 0.3.7 (late 2014 to early 2015) +# ---------------------------------------------------------------- +# Property Icons +# -------------- +19522, property_red, SAMPIcons, 200, 128 +19523, property_orange, SAMPIcons, 200, 128 +19524, property_yellow, SAMPIcons, 200, 128 +#----------------------------------------------------------------- +# Wedding Cake +# ------------ +19525, WeddingCake1, WeddingCake1, 100, 0 +#----------------------------------------------------------------- +# ATM Fixed (previously it was black during the night) +# ---------------------------------------------------- +19526, ATMFixed, CJ_CASINO_prop, 100, 0 +#----------------------------------------------------------------- +# Halloween Stuff +# --------------- +19527, Cauldron1, Cauldron1, 100, 0 +19528, WitchesHat1, WitchesHat1, 100, 0 +#----------------------------------------------------------------- +# Modular Island (grass, sand, concrete and roads) +# ------------------------------------------------ +19529, Plane125x125Grass1, beach_sfs, 599, 2097152 +19530, Plane125x125Sand1, beach_sfs, 599, 2097152 +19531, Plane125x125Conc1, cs_ebridge, 599, 2097152 +19532, 15x125Road1, cs_ebridge, 599, 2097152 +19533, 15x62_5Road1, cs_ebridge, 599, 2097152 +19534, 15x15RoadInters1, MatRoadInters1, 599, 2097152 +19535, 15x15RoadInters2, MatRoadInters1, 599, 2097152 +19536, Plane62_5x125Grass1, beach_sfs, 599, 2097152 +19537, Plane62_5x125Sand1, beach_sfs, 599, 2097152 +19538, Plane62_5x125Conc1, cs_ebridge, 599, 2097152 +19539, Edge62_5x62_5Grass1, beach_sfs, 599, 2097152 +19540, Edge62_5x62_5Grass2, beach_sfs, 599, 2097152 +19541, Edge62_5x15Grass1, beach_sfs, 599, 2097152 +19542, Edge62_5x125Grass1, beach_sfs, 599, 2097152 +19543, Plane62_5x15Grass1, beach_sfs, 599, 2097152 +19544, Plane62_5x15Sand1, beach_sfs, 599, 2097152 +19545, Plane62_5x15Conc1, cs_ebridge, 599, 2097152 +19546, Edge62_5x62_5Grass3, beach_sfs, 599, 2097152 +19547, Hill125x125Grass1, beach_sfs, 599, 2097152 +19548, Hill125x125Sand1, beach_sfs, 599, 2097152 +19549, Edge62_5x32_5Grass1, beach_sfs, 599, 2097152 +# The three planes below are the same as the other +# 125x125 planes above except they have some random +# lighter areas visible during the night. +19550, Plane125x125Grass2, beach_sfs, 599, 2097152 +19551, Plane125x125Sand2, beach_sfs, 599, 2097152 +19552, Plane125x125Conc2, cs_ebridge, 599, 2097152 +#----------------------------------------------------------------- +# Extracted from Skins (hats, mask, boxing gloves and backpack) +# ------------------------------------------------------------- +19553, StrawHat1, CWMOFR, 100, 2097152 +19554, Beanie1, ogloc, 100, 2097152 +19555, BoxingGloveL, vbmybox, 100, 2097152 +19556, BoxingGloveR, vbmybox, 100, 2097152 +19557, SexyMask1, wfysex, 100, 2097152 +19558, PizzaHat1, wmypizz, 100, 2097152 +19559, HikerBackpack1, wmybp, 100, 2097152 +#----------------------------------------------------------------- +# Extracted from Supermarket Items +# -------------------------------- +19560, MeatTray1, MeatTray1, 100, 0 +19561, CerealBox1, cj_ss_1, 100, 0 +19562, CerealBox2, cj_ss_1, 100, 0 +19563, JuiceBox1, cj_ss_1, 100, 0 +19564, JuiceBox2, cj_ss_1, 100, 0 +19565, IceCreamBarsBox1, cj_ss_4, 100, 0 +19566, FishFingersBox1, cj_ss_4, 100, 0 +19567, IcecreamContainer1, cj_ss_4, 100, 0 +19568, IcecreamContainer2, cj_ss_4, 100, 0 +19569, MilkCarton1, cj_ss_2, 100, 0 +19570, MilkBottle1, cj_ss_2, 100, 0 +19571, PizzaBox1, cj_ss_2, 100, 0 +19572, PisshBox1, cj_ss_1, 100, 0 +19573, BriquettesBag1, cj_ss_1, 100, 0 +#----------------------------------------------------------------- +# Fruit +# ----- +19574, Orange1, SAMPFruits, 100, 0 +19575, Apple1, SAMPFruits, 100, 0 +19576, Apple2, SAMPFruits, 100, 0 +19577, Tomato1, SAMPFruits, 100, 0 +19578, Banana1, SAMPFruits, 100, 0 +#----------------------------------------------------------------- +# Loaf of Bread +# ------------- +19579, BreadLoaf1, BreadLoaf1, 100, 0 +#----------------------------------------------------------------- +# Extracted Pepperoni Pizza +# ------------------------- +19580, Pizza1, cj_ff_acc1, 100, 0 +#----------------------------------------------------------------- +# Extracted from Marco's Bistro Kitchen +# ------------------------------------- +19581, MarcosFryingPan1, lee_kitch, 100, 0 +19582, MarcosSteak1, lee_kitch, 100, 0 +19583, MarcosKnife1, lee_kitch, 100, 0 +19584, MarcosSaucepan1, lee_kitch, 100, 0 +19585, MarcosPan1, lee_kitch, 100, 0 +19586, MarcosSpatula1, lee_kitch, 100, 4 +#----------------------------------------------------------------- +# Extracted from a Stack of Plastic Trays and Edited +# -------------------------------------------------- +19587, PlasticTray1, labins01_la, 100, 2097156 +#----------------------------------------------------------------- +# Wooden Foot Bridge +# ------------------ +19588, FootBridge1, FootBridge1, 299, 0 +#----------------------------------------------------------------- +# Extracted and Edited Rubbish Skip +# --------------------------------- +19589, RubbishSkipEmpty1, break_s_bins, 100, 0 +#----------------------------------------------------------------- +# Extracted from Woozie's Apartment +# --------------------------------- +19590, WooziesSword1, ab_wooziec, 100, 0 +19591, WooziesHandFan1, ab_wooziec, 100, 2097152 +#----------------------------------------------------------------- +# Extracted from a Stack of Baskets and Edited +# -------------------------------------------- +19592, ShopBasket1, temp_shop, 100, 2097152 +#----------------------------------------------------------------- +# SF ZomboTech Building and Lab +# ----------------------------- +# These objects can be used to replace the ZomboTech building in SF. +# The filterscript called sf_zombotech can be used to remove the +# existing GTASA map objects, replace the building, add the new lab +# building below the ground and add an elevator. +19593, ZomboTechBuilding1, bigwhitesfe, 299, 0 +19594, ZomboTechLab1, ZomboTechLab1, 299, 0 +#----------------------------------------------------------------- +# LS Apartments +# ------------- +# This object can be used to replace a block of apartments in LS. +# The filterscript called ls_apartments1 can be used to remove the +# existing GTASA map objects, replace the building and add an +# elevator. +# There is also a matching car park object (ID:19798). +19595, LSAppartments1, LSAppartments1, 299, 2097156 +#----------------------------------------------------------------- +# LS BeachSide +# ------------ +# These objects can be used to replace a block of apartments on the +# beach in LS. The filterscript called ls_beachside can be used to +# add an elevator. +# note: 19596 has been moved to model ID 6391 to replace the existing building +# 19596, LSBeachSide, LSBeachSide, 299, 2097156 +19597, LSBeachSideInsides, LSBeachSide, 125, 0 +#----------------------------------------------------------------- +# SF Building 1 +# ------------- +# These objects can be used to replace a building near the hospital +# in SF. The filterscript called sf_building1 can be used to remove +# the existing GTASA map objects and replace the building. +19598, SFBuilding1Outside, SFBuilding1, 299, 2097156 +19599, SFBuilding1Inside, SFBuilding1, 125, 0 +19600, SFBuilding1Land, SFBuilding1, 299, 0 +#----------------------------------------------------------------- +# Snow Plow +# --------- +# Attach to the front of the Barracks vehicle for best results. +19601, SnowPlow1, SnowPlow1, 150, 0 +#----------------------------------------------------------------- +# Landmine Edited +# --------------- +# Removed the red light at night and dynamic property. +19602, Landmine1, mine, 150, 0 +#----------------------------------------------------------------- +# Water Plane +# ----------- +# A 5m by 5m plane with semi-transparent water texture. +19603, WaterPlane1, ballyswater, 150, 2097156 +# A 5m x 10m plane with semi transparent and animated water texture. +19604, WaterPlane2, ballyswater, 150, 2097156 +#----------------------------------------------------------------- +# Different Coloured EnEx Markers +# ------------------------------- +# Red, Green and Blue. +19605, EnExMarker4-2, EnExMarkers, 150, 68 +19606, EnExMarker4-3, EnExMarkers, 150, 68 +19607, EnExMarker4-4, EnExMarkers, 150, 68 +#----------------------------------------------------------------- +# Stage and Music Equipment +# ------------------------- +19608, WoodenStage1, WoodenStage1, 299, 0 +19609, DrumKit1, dr_gsstudio, 100, 2097156 +19610, Microphone1, Microphone1, 100, 0 +19611, MicrophoneStand1, Microphone1, 100, 2097156 +19612, GuitarAmp1, dr_gsstudio, 100, 0 +19613, GuitarAmp2, dr_gsstudio, 100, 0 +19614, GuitarAmp3, dr_gsstudio, 100, 0 +19615, GuitarAmp4, dr_gsstudio, 100, 0 +19616, GuitarAmp5, dr_gsstudio, 100, 0 +19617, GoldRecord1, dr_gsstudio, 100, 0 +#----------------------------------------------------------------- +# Safe with Seperate Door +# ----------------------- +# You can use the MoveObject() function to make the safe door +# open and close. The safe_animated filterscript shows you an +# example of how to do it. +19618, Safe1, kbmiscfrn2, 100, 0 +19619, SafeDoor1, kbmiscfrn2, 100, 0 +#----------------------------------------------------------------- +# New Police Light Bar Model +# -------------------------- +# Uses UV animation so it works during the day too. +19620, LightBar1, LightBar1, 200, 0 +#----------------------------------------------------------------- +# Extracted from Cutscene IMG and Edited +# -------------------------------------- +19621, OilCan1, OilCan1, 100, 0 +19622, Broom1, Broom1, 100, 0 +19623, Camera1, Camera1, 100, 0 +19624, Case1, Case1, 100, 0 +19625, Ciggy1, Ciggy1, 50, 0 +19626, Spade1, Spade1, 100, 0 +19627, Wrench1, Wrench1, 100, 0 +#----------------------------------------------------------------- +# Modular Road Banked Corners +# --------------------------- +19628, MRoadBend90Banked1, cs_ebridge, 250, 5 +19629, MRoadBend90Banked2, cs_ebridge, 250, 5 +#----------------------------------------------------------------- +# 3D Fish (Bream) +# --------------- +19630, Fish1, Fish1SAMP, 100, 4 +#----------------------------------------------------------------- +# Sledge Hammer +# ------------- +19631, SledgeHammer1, SledgeHammer1, 100, 0 +#----------------------------------------------------------------- +# Burning Logs +# ------------ +19632, FireWood1, FireWood1, 100, 0 +#----------------------------------------------------------------- +# 360 Degree Ramps +# ---------------- +19633, Ramp360Degree1, landjump, 200, 0 +19634, Ramp360Degree2, landjump, 299, 0 +19635, Ramp360Degree3, landjump, 299, 0 +#----------------------------------------------------------------- +# Fruit Crates +# ------------ +# For transporting on a truck or adding to the shop shelf below. +19636, RedApplesCrate1, FruitCrates1, 100, 2097156 +19637, GreenApplesCrate1, FruitCrates1, 100, 2097156 +19638, OrangesCrate1, FruitCrates1, 100, 2097156 +19639, EmptyCrate1, FruitCrates1, 100, 0 +#----------------------------------------------------------------- +# Empty Shop Shelf +# ---------------- +# Stock it with your preferred items. Three fruit crates will fit +# side by side on the bottom shelf. +19640, EmptyShopShelf1, new_cabinets3, 100, 2097156 +#----------------------------------------------------------------- +# Wooden Fence Section +# -------------------- +19641, FenceSection1, FenceSection1, 250, 4 +#----------------------------------------------------------------- +# Half Tube Objects +# ----------------- +# The MatTubes TXD file contains different coloured textures +# (RedDirt1, GreenDirt1, BlueDirt1, YellowDirt1 and PurpleDirt1) +# that can be used to re-colour the tubes below by using the +# SetObjectMaterial or SetPlayerObjectMaterial functions. +# Re-colouring the tubes this way preserves the shading (the +# vertex colours and vertex illumination). +# +# The tubes are available in three sizes... normal (100%), +# medium (50%) and small (25%). +# ------------------------------------------ +# The tubes in this section are normal size: +19642, TubeSeg10m1, MatTubes, 299, 0 +19643, TubeSeg10m2a, MatTubes, 299, 0 +19644, TubeSeg10m2b, MatTubes, 299, 0 +19645, TubeSeg25m1, MatTubes, 299, 0 +19646, TubeHalf10m1, MatTubes, 299, 0 +19647, TubeHalf10mJoin1a, MatTubes, 299, 0 +19648, TubeHalf10mJoin1b, MatTubes, 299, 0 +19649, TubeHalf50m1, MatTubes, 299, 0 +19650, TubeFlat25x25m1, MatTubes, 299, 0 +19651, TubeHalfSpiral1a, MatTubes, 299, 0 +19652, TubeHalfSpiral1b, MatTubes, 299, 0 +19653, TubeHalfSpiral2a, MatTubes, 299, 0 +19654, TubeHalfSpiral2b, MatTubes, 299, 0 +19655, TubeHalfSpiral3a, MatTubes, 299, 0 +19656, TubeHalfSpiral3b, MatTubes, 299, 0 +19657, TubeHalfSpiral4a, MatTubes, 299, 0 +19658, TubeHalfSpiral4b, MatTubes, 299, 0 +19659, TubeHalf180Bend1a, MatTubes, 299, 0 +19660, TubeHalf180Bend1b, MatTubes, 299, 0 +19661, TubeHalf90Bend1a, MatTubes, 299, 0 +19662, TubeHalf90Bend1b, MatTubes, 299, 0 +19663, TubeHalf50mDip1, MatTubes, 299, 0 +19664, TubeHalf50mBump1, MatTubes, 299, 0 +19665, TubeHalfLoop1a, MatTubes, 299, 0 +19666, TubeHalfLoop1b, MatTubes, 299, 0 +19667, TubeHalfLoop2a, MatTubes, 299, 0 +19668, TubeHalfLoop2b, MatTubes, 299, 0 +19669, TubeHalfBowl1, MatTubes, 299, 0 +19670, TubeSupport1, dynsigns, 299, 0 +19671, TubeSupport2, dynsigns, 299, 0 +19672, TubeHalfLight1, dynsigns, 299, 0 +19673, TubeHalf5Bend1a, MatTubes, 299, 0 +19674, TubeHalf5Bend1b, MatTubes, 299, 0 +19675, TubeHalf5Bend2a, MatTubes, 299, 0 +19676, TubeHalf5Bend2b, MatTubes, 299, 0 +19677, TubeHalfTwist1a, MatTubes, 299, 0 +19678, TubeHalfTwist1b, MatTubes, 299, 0 +19679, TubeHalfTwist2a, MatTubes, 299, 0 +19680, TubeHalfTwist2b, MatTubes, 299, 0 +19681, TubeHalf45Bend1a, MatTubes, 299, 0 +19682, TubeHalf45Bend1b, MatTubes, 299, 0 +19683, TubeHalf15Bend1a, MatTubes, 299, 0 +19684, TubeHalf15Bend1b, MatTubes, 299, 0 +19685, TubeHalf15Bend2a, MatTubes, 299, 0 +19686, TubeHalf15Bend2b, MatTubes, 299, 0 +19687, TubeHalf25m1, MatTubes, 299, 0 +19688, TubeHalf45Bend3, MatTubes, 299, 0 +19689, TubeHalf45Bend4, MatTubes, 299, 0 +# ------------------------------------------ +# The tubes in this section join normal +# tubes (above) to medium tubes (below): +19690, TubeHalfNtoMJoin1a, MatTubes, 299, 0 +19691, TubeHalfNtoMJoin1b, MatTubes, 299, 0 +# ------------------------------------------ +# The tubes in this section are medium size: +19692, MTubeSeg5m1, MatTubes, 299, 0 +19693, MTubeSeg5m2a, MatTubes, 299, 0 +19694, MTubeSeg5m2b, MatTubes, 299, 0 +19695, MTubeSeg12_5m1, MatTubes, 299, 0 +19696, MTubeHalf10m1, MatTubes, 299, 0 +19697, MTubeHalf5mJoin1a, MatTubes, 299, 0 +19698, MTubeHalf5mJoin1b, MatTubes, 299, 0 +19699, MTubeHalf25m1, MatTubes, 299, 0 +19700, MTubeFlt12_5x12_5m1, MatTubes, 299, 0 +19701, MTubeHalfSpiral1a, MatTubes, 299, 0 +19702, MTubeHalfSpiral1b, MatTubes, 299, 0 +19703, MTubeHalfSpiral2a, MatTubes, 299, 0 +19704, MTubeHalfSpiral2b, MatTubes, 299, 0 +19705, MTubeHalfSpiral3a, MatTubes, 299, 0 +19706, MTubeHalfSpiral3b, MatTubes, 299, 0 +19707, MTubeHalfSpiral4a, MatTubes, 299, 0 +19708, MTubeHalfSpiral4b, MatTubes, 299, 0 +19709, MTubeHalf180Bend1a, MatTubes, 299, 0 +19710, MTubeHalf180Bend1b, MatTubes, 299, 0 +19711, MTubeHalf90Bend1a, MatTubes, 299, 0 +19712, MTubeHalf90Bend1b, MatTubes, 299, 0 +19713, MTubeHalf25mDip1, MatTubes, 299, 0 +19714, MTubeHalf25mBump1, MatTubes, 299, 0 +19715, MTubeHalfBowl1, MatTubes, 299, 0 +19716, MTubeSupport1, dynsigns, 299, 0 +19717, MTubeSupport2, dynsigns, 299, 0 +19718, MTubeHalfLight1, dynsigns, 299, 0 +19719, MTubeHalf5Bend1a, MatTubes, 299, 0 +19720, MTubeHalf5Bend1b, MatTubes, 299, 0 +19721, MTubeHalf5Bend2a, MatTubes, 299, 0 +19722, MTubeHalf5Bend2b, MatTubes, 299, 0 +19723, MTubeHalf45Bend1a, MatTubes, 299, 0 +19724, MTubeHalf45Bend1b, MatTubes, 299, 0 +19725, MTubeHalf15Bend1a, MatTubes, 299, 0 +19726, MTubeHalf15Bend1b, MatTubes, 299, 0 +19727, MTubeHalf15Bend2a, MatTubes, 299, 0 +19728, MTubeHalf15Bend2b, MatTubes, 299, 0 +19729, MTubeHalf45Bend3, MatTubes, 299, 0 +19730, MTubeHalf45Bend4, MatTubes, 299, 0 +# ------------------------------------------ +# The tubes in this section join medium +# tubes (above) to small tubes (below): +19731, TubeHalfMtoSJoin1a, MatTubes, 299, 0 +19732, TubeHalfMtoSJoin1B, MatTubes, 299, 0 +# ------------------------------------------ +# The tubes in this section are small size: +19733, STubeSeg5m1, MatTubes, 299, 0 +19734, STubeSeg5m2a, MatTubes, 299, 0 +19735, STubeSeg5m2b, MatTubes, 299, 0 +19736, STubeSeg6_25m1, MatTubes, 299, 0 +19737, STubeHalf10m1, MatTubes, 299, 0 +19738, STubeHalf5mJoin1a, MatTubes, 299, 0 +19739, STubeHalf5mJoin1b, MatTubes, 299, 0 +19740, STubeHalf12_5m1, MatTubes, 299, 0 +19741, STubeFlat6_25m1, MatTubes, 299, 0 +19742, STubeHalfSpiral1a, MatTubes, 299, 0 +19743, STubeHalfSpiral1b, MatTubes, 299, 0 +19744, STubeHalfSpiral2a, MatTubes, 299, 0 +19745, STubeHalfSpiral2b, MatTubes, 299, 0 +19746, STubeHalfSpiral3a, MatTubes, 299, 0 +19747, STubeHalfSpiral3b, MatTubes, 299, 0 +19748, STubeHalfSpiral4a, MatTubes, 299, 0 +19749, STubeHalfSpiral4b, MatTubes, 299, 0 +19750, STubeHalf180Bend1a, MatTubes, 299, 0 +19751, STubeHalf180Bend1b, MatTubes, 299, 0 +19752, STubeHalf90Bend1a, MatTubes, 299, 0 +19753, STubeHalf90Bend1b, MatTubes, 299, 0 +19754, STubeHalf12_5mDip1, MatTubes, 299, 0 +19755, STubeHalf12_5mBump1, MatTubes, 299, 0 +19756, STubeHalfBowl1, MatTubes, 299, 0 +19757, STubeSupport1, dynsigns, 299, 0 +19758, STubeSupport2, dynsigns, 299, 0 +19759, STubeHalfLight1, dynsigns, 299, 0 +19760, STubeHalf5Bend1a, MatTubes, 299, 0 +19761, STubeHalf5Bend1b, MatTubes, 299, 0 +19762, STubeHalf5Bend2a, MatTubes, 299, 0 +19763, STubeHalf5Bend2b, MatTubes, 299, 0 +19764, STubeHalf45Bend1a, MatTubes, 299, 0 +19765, STubeHalf45Bend1b, MatTubes, 299, 0 +19766, STubeHalf15Bend1a, MatTubes, 299, 0 +19767, STubeHalf15Bend1b, MatTubes, 299, 0 +19768, STubeHalf15Bend2a, MatTubes, 299, 0 +19769, STubeHalf15Bend2b, MatTubes, 299, 0 +19770, STubeHalf45Bend3, MatTubes, 299, 0 +19771, STubeHalf45Bend4, MatTubes, 299, 0 +#----------------------------------------------------------------- +# Crushed Car Cube +# ---------------- +19772, CrushedCarCube1, CrushedCarCube1, 100, 0 +# ---------------------------------------------------------------- +# Police and FBI Stuff +# -------------------- +19773, GunHolster1, MatCopStuff, 100, 0 +19774, PoliceBadge2, MatCopStuff, 100, 2097152 +19775, PoliceBadge3, MatCopStuff, 100, 2097152 +19776, FBIIDCard1, MatCopStuff, 100, 2097152 +19777, FBILogo1, MatCopStuff, 100, 2097156 +19778, InsigniaDetective1, MatPoliceInsignias, 100, 2097156 +19779, InsigniaDetective2, MatPoliceInsignias, 100, 2097156 +19780, InsigniaDetective3, MatPoliceInsignias, 100, 2097156 +19781, InsigniaSergeant1, MatPoliceInsignias, 100, 2097156 +19782, InsigniaSergeant2, MatPoliceInsignias, 100, 2097156 +19783, InsigniaPOfficer2, MatPoliceInsignias, 100, 2097156 +19784, InsigniaPOfficer3, MatPoliceInsignias, 100, 2097156 +19785, InsigniaSeniorLdOff, MatPoliceInsignias, 100, 2097156 +# ---------------------------------------------------------------- +# LCD TVs +# ------- +# Material index 1 is the LCD screen... it can be used to put +# any picture from a TXD file on the screen. +19786, LCDTVBig1, SAMPLCDTVs1, 100, 0 +19787, LCDTV1, SAMPLCDTVs1, 100, 0 +#----------------------------------------------------------------- +#----------------------------------------------------------------- +# Objects Added by Matite in SA:MP 0.3.7 RC2 +# ------------------------------------------ +# Modular Island Road Corner +# -------------------------- +# This road corner is designed to work with the other modular +# island road objects above (IDs:19529 to 19552). +19788, 15x15RoadCorner1, MatRoadInters1, 599, 2097152 +# ---------------------------------------------------------------- +# Cubes +# ----- +# The UV mapping is 1:1 per face to allow re-texturing. The 5mx5m +# and 10mx10m cubes have faces inside so a player can be within +# them. +19789, Cube1mx1m, cs_ebridge, 150, 0 +19790, Cube5mx5m, cs_ebridge, 299, 0 +19791, Cube10mx10m, cs_ebridge, 299, 0 +# ---------------------------------------------------------------- +# Normal Sized Keycard +# -------------------- +19792, SAMPKeycard1, SAMPKeycard1, 50, 0 +#----------------------------------------------------------------- +# Fire Wood Log +# ------------- +19793, FireWoodLog1, FireWood1, 100, 0 +#----------------------------------------------------------------- +# LS Prison Walls and Gates +# ------------------------- +# These objects are designed to replace the walls and gates at +# the LS Prison so you can add your own working gates. Use the +# new filterscript called ls_prisonwalls to see an example. +19794, LSPrisonWalls1, civic04_lan, 299, 128 +19795, LSPrisonGateEast, civic04_lan, 299, 128 +19796, LSPrisonGateSouth, civic04_lan, 299, 128 +#----------------------------------------------------------------- +# Police Visor Strobe +# ------------------- +# Uses UV animation so it works during the day too. +19797, PoliceVisorStrobe1, PoliceVisorStrobe1, 200, 0 +#----------------------------------------------------------------- +# LS Apartments Car Park +# ---------------------- +# This car park object can be used along with the replacement +# block of LS apartments (ID:19595). +# The filterscript called ls_apartments1 shows an example of how +# it can be used. +19798, LSACarPark1, LSACarPark1, 150, 0 +# ---------------------------------------------------------------- +# Caligulas Casino Vault Door Edited +# ---------------------------------- +# Edited to fix the pivot so it can be used with MoveObject() and +# also fixed the night vertex colours. Original object ID is 2634. +19799, CaligulasVaultDoor, all_vault, 150, 0 +#----------------------------------------------------------------- +# LS BeachSide Car Park +# --------------------- +# This car park object can be used along with the replacement +# LS BeachSide building (IDs 19596 and 19597). +# The filterscript called ls_beachside shows an example of how +# it can be used. +19800, LSBCarPark1, LSACarPark1, 150, 0 +#----------------------------------------------------------------- +# Balaclava +# --------- +19801, Balaclava1, Balaclava1, 100, 2097152 +#----------------------------------------------------------------- +# Static Door +# ----------- +# This door is the same as object ID 1502 except it is static. +# You can animate it opening and closing with the MoveObject() +# function. +19802, GenDoorINT04Static, int_doors, 50, 128 +#----------------------------------------------------------------- +# Tow Truck Lights +# ---------------- +# These lights can be used on top of the tow truck. The light +# configuration was created by Vince. +# Note that they will only be visible at night. +19803, TowTruckLights1, MatTextures, 150, 0 +#----------------------------------------------------------------- +# Padlock +# ------- +19804, Padlock1, Padlock1, 50, 0 +#----------------------------------------------------------------- +# Extracted Items +# --------------- +# This whiteboard has a transparent material overlay (index 1) +# so you can use it with the SetObjectMaterialText() or +# SetPlayerObjectMaterialText() functions +19805, Whiteboard1, Whiteboard1, 50, 2097152 +19806, Chandelier1, svbits, 50, 0 +19807, Telephone1, Telephone1, 50, 0 +19808, Keyboard1, Keyboard1, 50, 0 +19809, MetalTray1, MetalTray1, 50, 2097152 +19810, StaffOnlySign1, StaffOnlySign1, 50, 0 +19811, BurgerBox1, BurgerBox1, 50, 0 +19812, BeerKeg1, ce_breweryref, 100, 0 +19813, ElectricalOutlet1, ElectricalOutlets, 50, 0 +19814, ElectricalOutlet2, ElectricalOutlets, 50, 0 +19815, ToolBoard1, ToolBoard1, 50, 0 +19816, OxygenCylinder1, OxygenCylinder1, 50, 0 +19817, CarFixerRamp1, CarFixerRamp1, 100, 2097152 +19818, WineGlass1, lee_strip2_1, 50, 2097152 +19819, CocktailGlass1, lee_strip2_1, 50, 2097152 +19820, AlcoholBottle1, lee_strip2_1, 50, 0 +19821, AlcoholBottle2, lee_strip2_1, 50, 0 +19822, AlcoholBottle3, lee_strip2_1, 50, 0 +19823, AlcoholBottle4, lee_strip2_1, 50, 0 +19824, AlcoholBottle5, lee_strip2_1, 50, 0 +19825, SprunkClock1, SprunkClock1, 50, 0 +19826, LightSwitch1, LightSwitches, 50, 0 +19827, LightSwitch2, LightSwitches, 50, 0 +19828, LightSwitch3Off, LightSwitches, 50, 0 +19829, LightSwitch3On, LightSwitches, 50, 0 +19830, Blender1, csblender, 50, 0 +19831, Barbeque1, csbarbq, 50, 0 +19832, AmmoBox1, csammobox, 50, 0 +19833, Cow1, Cow1, 150, 0 +19834, PoliceLineTape1, PoliceLineTape1, 50, 0 +19835, CoffeeCup1, d_s, 50, 0 +#----------------------------------------------------------------- +# Objects That Use Particle.TXD +# ----------------------------- +19836, BloodPool1, particle, 50, 2097156 +19837, GrassClump1, particle, 50, 2097156 +19838, GrassClump2, particle, 50, 2097156 +19839, GrassClump3, particle, 50, 2097156 +#----------------------------------------------------------------- +# Animated Waterfalls +# ------------------- +19840, WaterFall1, vegaswaterfall, 150, 2097284 +19841, WaterFall2, vegaswaterfall, 150, 2097284 +19842, WaterFallWater1, vegaswaterfall, 150, 2097284 +#----------------------------------------------------------------- +# Metal Panels +# ------------ +19843, MetalPanel1, MetalPanels, 100, 0 +19844, MetalPanel2, MetalPanels, 100, 0 +19845, MetalPanel3, MetalPanels, 100, 0 +19846, MetalPanel4, MetalPanels, 100, 0 +#----------------------------------------------------------------- +# Leg of Ham +# ---------- +19847, LegHam1, LegHam1, 50, 0 +#----------------------------------------------------------------- +# CargoBob Platform +# ----------------- +# This platform is designed to attach to the side of the CargoBob +# helicopter using the AttachObjectToVehicle function so you can +# carry people around. +19848, CargoBobPlatform1, ab_cargo_int, 150, 0 +#----------------------------------------------------------------- +# Modular Island House 1 +# ---------------------- +# These objects are designed to work with the other modular +# island objects above (IDs:19529 to 19552). Use the new +# filterscript called modular_houses to see an example. +19849, MIHouse1Land, MIHouse1, 599, 4 +19850, MIHouse1Land2, MIHouse1, 599, 0 +19851, MIHouse1Land3, MIHouse1, 599, 0 +19852, MIHouse1Land4, MIHouse1, 599, 0 +19853, MIHouse1Land5, MIHouse1, 599, 0 +19854, MIHouse1Outside, MIHouse1, 599, 4 +19855, MIHouse1Inside, MIHouse1, 150, 0 +19856, MIHouse1IntWalls1, MIHouse1, 150, 0 +19857, MIHouse1Door1, MIHouse1, 50, 132 +19858, MIHouse1Door2, vegashse2, 50, 132 +19859, MIHouse1Door3, vegashse3, 50, 132 +19860, MIHouse1Door4, vegashse5, 50, 132 +19861, MIHouse1GarageDoor1, MIHouse1, 50, 128 +19862, MIHouse1GarageDoor2, vegashse3, 50, 128 +19863, MIHouse1GarageDoor3, vegashse5, 50, 128 +19864, MIHouse1GarageDoor4, vegashse6, 50, 128 +19865, MIFenceWood1, vegashse2, 100, 132 +19866, MIFenceBlocks1, vegashse2, 100, 128 +#----------------------------------------------------------------- +# Non-Breakable Mail Box +# ---------------------- +# This mail box is same as object ID 1478 except it is not +# dynamic (breakable) and the night vertex colours (NVC) +# have been fixed. +19867, MailBox1, break_garden, 100, 0 +#----------------------------------------------------------------- +# Non-Breakable Mesh Fences and Gate +# ---------------------------------- +# These fence sections are the same as object IDs 1411 and 1412 +# except they are not dynamic (breakable). +19868, MeshFence1, break_fen_mesh2, 100, 132 +19869, MeshFence2, break_fen_mesh2, 100, 132 +# This metal gate is the same as object ID 3036 except it is not +# dynamic (breakable). +19870, MetalGate1, ctgtxx, 100, 132 +#----------------------------------------------------------------- +#----------------------------------------------------------------- +# Objects Added by Matite in SA:MP 0.3.7 RC3 +# ------------------------------------------ +19871, CordonStand1, airp_prop, 50, 0 +19872, CarFixerRamp2, CarFixerRamp1, 100, 2097152 +19873, ToiletPaperRoll1, BathroomStuff1, 50, 0 +19874, SoapBar1, BathroomStuff1, 50, 0 +# This door is the same as object ID 2947 except it is not +# dynamic (breakable) and the pivot point has been moved. +19875, CRDoor01New, sw_doors, 50, 128 +#----------------------------------------------------------------- +# Dillimore Gas Station +# --------------------- +# Replaces object IDs 12853 and 12854 with an enterable version +# of the Dillimore Gas Station. Use the new filterscript called +# dillimore_gas to see an example. +19876, DillimoreGasExt1, cunte_gas01, 299, 2097284 +19877, DillimoreGasInt1, cunte_gas01, 100, 2097284 +#----------------------------------------------------------------- +# GTASA Skateboard +# ---------------- +# Edited to work as a normal object and added vertex colours. +19878, Skateboard1, skateboard, 100, 0 +#----------------------------------------------------------------- +# LS Wells Fargo Building +# ----------------------- +# This building is a replacement for the LS Wells Fargo building +# (object ID 4007). Use the new filterscript called ls_wellsfargo +# to see an example. +19879, WellsFargoBuild1, lanblokc, 299, 0 +19880, WellsFargoGrgDoor1, lanblokc, 100, 0 +#----------------------------------------------------------------- +# Kylie's Barn Fixed +# ------------------ +# This barn is the same as object ID 14871 except the collision +# (COL) has been fixed. Use the new filterscript called kylies_barn +# to see an example. +19881, KylieBarnFixed1, gf3, 50, 0 +#----------------------------------------------------------------- +# Marco's Steak Cooked +# -------------------- +# This steak is the same as object ID 19582 except it is cooked. +19882, MarcosSteak2, MarcosSteak2, 100, 0 +#----------------------------------------------------------------- +# Slice of Bread +# -------------- +19883, BreadSlice1, BreadSlice1, 50, 0 +#----------------------------------------------------------------- +# More Water Slide Sections +# ------------------------- +# These objects are designed to work with the old existing object +# IDs 19070 to 19073. +19884, WSBend45Deg2, WSSections, 299, 2097156 +19885, WSStraight2, WSSections, 299, 2097156 +19886, WSStraight3, WSSections, 299, 2097156 +19887, WSStart1, WSSections, 299, 2097156 +19888, WSBend45Deg3, WSSections, 299, 2097156 +19889, WSBend45Deg4, WSSections, 299, 2097156 +19890, WSStraight4, WSSections, 299, 2097156 +19891, WSTubeJoiner1, WSSections, 299, 2097156 +19892, WSRoadJoiner1, WSSections, 299, 2097156 +#----------------------------------------------------------------- +# Laptop (Old Style) +# ------------------ +# Same laptop in open and closed positions. You can change the +# screen using the SetObjectMaterial() function on index 1. +# There are three screen variations in the TXD file: +# * LaptopScreen1 = GTASA map screen (default) +# * LaptopScreen2 = Text screen +# * LaptopScreen3 = Police database screen +19893, LaptopSAMP1, LaptopSAMP1, 50, 0 +19894, LaptopSAMP2, LaptopSAMP1, 50, 0 +#----------------------------------------------------------------- +# Ladder Fire Truck Lights +# ------------------------ +# These lights can be used on top of the ladder fire truck. +# Note that they will only be visible at night. +19895, LadderFireTruckLts1, MatTextures, 150, 0 +#----------------------------------------------------------------- +# Misc Items +# ---------- +19896, CigarettePack1, CigarettePacks, 50, 0 +19897, CigarettePack2, CigarettePacks, 50, 0 +19898, OilFloorStain1, hubprops1_sfse, 50, 2097156 +19899, ToolCabinet1, hubprops2_sfse, 50, 2097152 +19900, ToolCabinet2, hubprops2_sfse, 50, 0 +# 19901 = Anim Tube ANIM object +# 19902 = EnEx Marker ANIM object +19903, MechanicComputer1, hubprops2_sfse, 50, 4 +19904, ConstructionVest1, bmyap, 100, 2097152 +#----------------------------------------------------------------- +# Area 51 (69) Buildings +# ---------------------- +# Same as the original buildings but now with an interior. +19905, A51Building1, a51_ext, 299, 0 +19906, A51Building1GrgDoor, a51_ext, 50, 0 +19907, A51Building2, a51_ext, 299, 0 +19908, A51Building2GrgDoor, a51_ext, 50, 0 +19909, A51Building3, a51_ext, 299, 0 +19910, A51Building3GrgDoor, a51_ext, 50, 0 +# The door below is designed to fit on the A51/69 Military Hangar +# (object ID 3268). It takes two doors to close the entrance. +19911, A51HangarDoor1, a51_ext, 100, 0 +#----------------------------------------------------------------- +# Metal Gate and Big Fence +# ------------------------ +# This gate is the same as object ID 980 except it has no signs +# on it and the pivot point is on the edge. +19912, SAMPMetalGate1, electricgate, 100, 4 +# Big metal fence. +19913, SAMPBigFence1, electricgate, 299, 4 +#----------------------------------------------------------------- +# Extracted from Cutscene IMG and Edited +# -------------------------------------- +19914, CutsceneBat1, csbat, 50, 0 +19915, CutsceneCooker1, cscooker, 50, 0 +19916, CutsceneFridge1, csfridge, 50, 0 +19917, CutsceneEngine1, csengine, 50, 0 +19918, CutsceneBox1, csheistbox, 50, 0 +19919, CutscenePerch1, csparrotperch, 50, 0 +19920, CutsceneRemote1, csremote, 50, 0 +19921, CutsceneToolBox1, cstoolkit, 50, 0 +#----------------------------------------------------------------- +# Modular Kitchen +# --------------- +19922, MKTable1, cswzkitch, 50, 0 +19923, MKIslandCooker1, cswzkitch, 50, 0 +19924, MKExtractionHood1, cswzkitch, 50, 0 +19925, MKWorkTop1, cswzkitch, 50, 0 +19926, MKWorkTop2, cswzkitch, 50, 0 +19927, MKWorkTop3, cswzkitch, 50, 0 +19928, MKWorkTop4, cswzkitch, 50, 0 +19929, MKWorkTop5, cswzkitch, 50, 0 +19930, MKWorkTop6, cswzkitch, 50, 0 +19931, MKWorkTop7, cswzkitch, 50, 0 +19932, MKWallOvenCabinet1, cswzkitch, 50, 0 +19933, MKWallOven1, MKWallOven1, 50, 0 +19934, MKCupboard1, cswzkitch, 50, 0 +19935, MKCupboard2, cswzkitch, 50, 0 +19936, MKCupboard3, cswzkitch, 50, 0 +19937, MKCupboard4, cswzkitch, 50, 0 +19938, MKShelf1, cswzkitch, 50, 0 +19939, MKShelf2, cswzkitch, 50, 0 +19940, MKShelf3, cswzkitch, 50, 0 +#----------------------------------------------------------------- +# Misc Items +# ---------- +19941, GoldBar1, GoldBar1, 50, 0 +19942, PoliceRadio1, PoliceRadio1, 50, 0 +19943, StonePillar1, ab_pillartemp, 150, 0 +19944, BodyBag1, des_cen, 50, 0 +#----------------------------------------------------------------- +# Checkpoints +# ----------- +19945, CPSize16Red, EnExMarkers, 299, 2097220 +19946, CPSize16Green, EnExMarkers, 299, 2097220 +19947, CPSize16Blue, EnExMarkers, 299, 2097220 +#----------------------------------------------------------------- +# Road Signs +# ---------- +# Misc road signs +19948, SAMPRoadSign1, SAMPRoadSigns, 50, 128 +19949, SAMPRoadSign2, SAMPRoadSigns, 50, 128 +19950, SAMPRoadSign3, SAMPRoadSigns, 50, 128 +19951, SAMPRoadSign4, SAMPRoadSigns, 50, 128 +19952, SAMPRoadSign5, SAMPRoadSigns, 50, 128 +19953, SAMPRoadSign6, SAMPRoadSigns, 50, 128 +19954, SAMPRoadSign7, SAMPRoadSigns, 50, 128 +19955, SAMPRoadSign8, SAMPRoadSigns, 50, 128 +19956, SAMPRoadSign9, SAMPRoadSigns, 50, 128 +19957, SAMPRoadSign10, SAMPRoadSigns, 50, 128 +19958, SAMPRoadSign11, SAMPRoadSigns, 50, 128 +19959, SAMPRoadSign12, SAMPRoadSigns, 50, 128 +19960, SAMPRoadSign13, SAMPRoadSigns, 50, 128 +19961, SAMPRoadSign14, SAMPRoadSigns, 50, 128 +19962, SAMPRoadSign15, SAMPRoadSigns, 50, 128 +19963, SAMPRoadSign16, SAMPRoadSigns, 50, 128 +19964, SAMPRoadSign17, SAMPRoadSigns, 50, 128 +19965, SAMPRoadSign18, SAMPRoadSigns, 50, 128 +19966, SAMPRoadSign19, SAMPRoadSigns, 50, 128 +19967, SAMPRoadSign20, SAMPRoadSigns, 50, 128 +19968, SAMPRoadSign21, SAMPRoadSigns, 50, 128 +19969, SAMPRoadSign22, SAMPRoadSigns, 50, 128 +19970, SAMPRoadSign23, SAMPRoadSigns, 50, 128 +19971, SAMPRoadSign24, SAMPRoadSigns, 50, 128 +19972, SAMPRoadSign25, SAMPRoadSigns, 50, 128 +19973, SAMPRoadSign26, SAMPRoadSigns, 50, 128 +19974, SAMPRoadSign27, SAMPRoadSigns, 50, 128 +19975, SAMPRoadSign28, SAMPRoadSigns, 50, 128 +19976, SAMPRoadSign29, SAMPRoadSigns, 50, 128 +19977, SAMPRoadSign30, SAMPRoadSigns, 50, 128 +19978, SAMPRoadSign31, SAMPRoadSigns, 50, 128 +19979, SAMPRoadSign32, SAMPRoadSigns, 50, 128 +# The two signs below have a transparent material overlay (index 3) +# so you can use it with the SetObjectMaterialText() or +# SetPlayerObjectMaterialText() functions +19980, SAMPRoadSign33, SAMPRoadSigns, 50, 128 +19981, SAMPRoadSign34, SAMPRoadSigns, 50, 128 +# Speed limit signs +19982, SAMPRoadSign35, SAMPRoadSigns, 50, 128 +19983, SAMPRoadSign36, SAMPRoadSigns, 50, 128 +19984, SAMPRoadSign37, SAMPRoadSigns, 50, 128 +19985, SAMPRoadSign38, SAMPRoadSigns, 50, 128 +19986, SAMPRoadSign39, SAMPRoadSigns, 50, 128 +19987, SAMPRoadSign40, SAMPRoadSigns, 50, 128 +19988, SAMPRoadSign41, SAMPRoadSigns, 50, 128 +19989, SAMPRoadSign42, SAMPRoadSigns, 50, 128 +19990, SAMPRoadSign43, SAMPRoadSigns, 50, 128 +19991, SAMPRoadSign44, SAMPRoadSigns, 50, 128 +19992, SAMPRoadSign45, SAMPRoadSigns, 50, 128 +#----------------------------------------------------------------- +# Extracted from Cutscene IMG and Edited +# -------------------------------------- +19993, CutsceneBowl1, csbowl, 50, 0 +19994, CutsceneChair1, cschair, 50, 0 +19995, CutsceneAmmoClip1, csclip, 50, 0 +19996, CutsceneFoldChair1, csfoldchair, 50, 2097152 +19997, CutsceneGrgTable1, csgrgtable, 50, 0 +19998, CutsceneLighterFl, cslighterfluid, 50, 0 +19999, CutsceneChair2, csrcrdchair, 50, 0 +#----------------------------------------------------------------- +#----------------------------------------------------------------- +# 11682 to 12799 ID Range +# ----------------------- +# Extracted and edited cutscene objects continued from above +11682, CutsceneCouch1, csmafcouch, 50, 0 +11683, CutsceneCouch2, csmafcouch, 50, 0 +11684, CutsceneCouch3, csmafcouch, 50, 0 +11685, CutsceneCouch4, csmafcouch, 50, 0 +#----------------------------------------------------------------- +# Redsands West Casino Extracted and Edited Items +# ----------------------------------------------- +11686, CBarSection1, int_casinoint3, 50, 0 +11687, CBarStool1, int_casinoint3, 50, 0 +11688, CWorkTop1, int_casinoint3, 50, 0 +11689, CBoothSeat1, int_casinoint3, 50, 0 +11690, CTable1, int_casinoint3, 50, 0 +11691, CTable2, int_casinoint3, 50, 0 +#----------------------------------------------------------------- +#----------------------------------------------------------------- +# Objects Added by Matite in SA:MP 0.3.7 RC4 +# ------------------------------------------ +# A51 Replacement Land Bit +# ------------------------ +# This object is designed to replace the land section at the +# Area 51 (69) Base (object ID 16203). Use the new filterscript +# called a51_base to see an example. +11692, A51LandBit1, a51_ext, 599, 0 +#----------------------------------------------------------------- +# Hills +# ----- +11693, Hills250x250Grass1, beach_sfs, 599, 0 +11694, Hill250x250Rocky1, des_sw, 599, 0 +11695, Hill250x250Rocky2, des_sw, 599, 0 +11696, Hill250x250Rocky3, Hill250x250Rocky3, 599, 0 +#----------------------------------------------------------------- +# Modular Rope Bridge +# ------------------- +11697, RopeBridgePart1, RopeBridge, 299, 0 +11698, RopeBridgePart2, RopeBridge, 299, 0 +#----------------------------------------------------------------- +# More Road Signs +# --------------- +# The speed limit sign below has a transparent material overlay +# (index 3) so you can use it with the SetObjectMaterialText() +# or SetPlayerObjectMaterialText() functions +11699, SAMPRoadSign46, SAMPRoadSigns, 50, 132 +11700, SAMPRoadSign47, SAMPRoadSigns, 50, 128 +#----------------------------------------------------------------- +# Ambulance Lights +# ---------------- +# First object is with lights on and second is with lights off. +11701, AmbulanceLights1, AmbulanceLights1, 150, 0 +11702, AmbulanceLights2, AmbulanceLights1, 150, 0 +#----------------------------------------------------------------- +# Magnetic Crane Object +# --------------------- +# This object is the same as object ID 1382 except GTASA will not +# automatically attach the crane cable and magnet to it. +11703, MagnoCrane_03_2, cranes_dyn2_cj, 150, 4 +#----------------------------------------------------------------- +# Extracted Items +# --------------- +11704, BDupsMask1, bdupsnew, 100, 2097152 +11705, BlackTelephone1, cuntcuts, 50, 0 +11706, SmallWasteBin1, cuntcuts, 50, 0 +11707, TowelRack1, cuntcuts, 50, 0 +11708, BrickSingle1, sw_well1, 50, 0 +11709, AbattoirSink1, ab_abbatoir01, 50, 0 +11710, FireExitSign1, eastbeach8_lae2, 75, 0 +11711, ExitSign1, eastbeach8_lae2, 75, 0 +11712, Cross1, Cross1, 50, 0 +11713, FireExtPanel1, maint1, 50, 0 +11714, MaintenanceDoors1, maint1, 50, 0 +11715, MetalFork1, gb_dirtycrock01, 50, 0 +11716, MetalKnife1, gb_dirtycrock01, 50, 0 +11717, WooziesCouch1, ab_wooziec, 50, 0 +11718, SweetsSaucepan1, SweetsStuff1, 50, 0 +11719, SweetsSaucepan2, SweetsStuff1, 50, 0 +11720, SweetsBed1, SweetsStuff1, 50, 0 +11721, Radiator1, lahss2_2int2, 50, 0 +11722, SauceBottle1, ab_trukstpb, 50, 0 +11723, SauceBottle2, ab_trukstpb, 50, 0 +11724, FireplaceSurround1, svcunthoose, 50, 0 +11725, Fireplace1, svcunthoose, 50, 0 +11726, HangingLight1, sfhosemed2, 50, 0 +11727, PaperChaseLight1, papaerchaseoffice, 50, 0 +11728, PaperChasePhone1, papaerchaseoffice, 50, 0 +11729, GymLockerClosed1, intring_gymint3, 50, 0 +11730, GymLockerOpen1, intring_gymint3, 50, 0 +11731, WHeartBed1, whore_rms, 50, 4 +11732, WHeartBath1, whore_rms, 50, 0 +11733, WRockingHorse1, whore_rms, 50, 0 +11734, WRockingChair1, whore_rms, 50, 0 +11735, WBoot1, whore_rms, 50, 0 +11736, MedicalSatchel1, paperchase_bits2, 50, 0 +11737, RockstarMat1, carter_block_2, 50, 0 +11738, MedicCase1, MedicCase1, 50, 0 +#----------------------------------------------------------------- +# Extracted from Marco's Bistro +# ----------------------------- +11739, MCake1, MarcosStuff1, 50, 0 +11740, MCake2, MarcosStuff1, 50, 0 +11741, MCake3, MarcosStuff1, 50, 0 +11742, MCakeSlice1, MarcosStuff1, 50, 0 +11743, MCoffeeMachine1, MarcosStuff1, 50, 0 +11744, MPlate1, MarcosStuff1, 50, 0 +#----------------------------------------------------------------- +# Hold All (Carry Bag) Edited +# --------------------------- +# This object is the same as ID 2919 except it is smaller and +# not dynamic. +11745, HoldAllEdited1, kmb_chute, 50, 4 +#----------------------------------------------------------------- +# Misc +# ---- +11746, DoorKey1, DoorKey1, 50, 0 +11747, Bandage1, Bandages, 50, 0 +11748, BandagePack1, Bandages, 50, 0 +#----------------------------------------------------------------- +# Cutscene Handcuffs +# ------------------ +11749, CSHandcuffs1, CSHandcuffs1, 50, 0 +# The handcuffs below are the same as above except they are folded +# in half so they can be attached to an officers belt. +11750, CSHandcuffs2, CSHandcuffs1, 50, 0 +#----------------------------------------------------------------- +# Area Boundaries +# --------------- +11751, AreaBoundary50m, EnExMarkers, 599, 2097220 +11752, AreaBoundary10m, EnExMarkers, 599, 2097220 +11753, AreaBoundary1m, EnExMarkers, 599, 2097220 +#----------------------------------------------------------------- +#----------------------------------------------------------------- +end +tobj +end +path +end +2dfx +end +#----------------------------------------------------------------- +# Animated (ANIM) Objects +# ----------------------- +# Note: You cannot have more than three ANIM objects in total +# listed below and/or in the Custom.IDE file. +#----------------------------------------------------------------- +anim +19901, AnimTube, MatTextures, AnimTube, 299, 0 +19902, EnExMarker4, EnExMarkers, EnExMarker4, 150, 68 +end +txdp +end +#----------------------------------------------------------------- +# Ped skin variants added for 0.3.7 +#----------------------------------------------------------------- +peds +300, lapdna, lapd1, COP, STAT_COP, swat, 1FFF, 0, null, 9,9, PED_TYPE_EMG,VOICE_EMG_LAPD1 ,VOICE_EMG_LAPD8 +301, sfpdna, sfpd1, COP, STAT_COP, swat, 1FFF, 0, null, 9,9, PED_TYPE_EMG,VOICE_EMG_SFPD1 ,VOICE_EMG_SFPD5 +302, lvpdna, lvpd1, COP, STAT_COP, swat, 1FFF, 0, null, 9,9, PED_TYPE_EMG,VOICE_EMG_LVPD1 ,VOICE_EMG_LVPD5 +303, lapdpc, lapdpc, COP, STAT_COP, swat, 1FFF, 0, null, 9,9, PED_TYPE_EMG,VOICE_EMG_LAPD1 ,VOICE_EMG_LAPD8 +304, lapdpd, lapdpd, COP, STAT_COP, swat, 1FFF, 0, null, 9,9, PED_TYPE_EMG,VOICE_EMG_LAPD1 ,VOICE_EMG_LAPD8 +305, lvpdpc, lvpdpc, COP, STAT_COP, swat, 1FFF, 0, null, 9,9, PED_TYPE_EMG,VOICE_EMG_LVPD1 ,VOICE_EMG_LVPD5 +306, WFYCLPD, WFYCLPD, CIVFEMALE, STAT_STREET_GIRL, woman, 1FFF,0, null,1,4,PED_TYPE_GFD,VOICE_GFD_WFYCLOT ,VOICE_GFD_WFYCLOT +307, VBFYCPD, VBFYCPD, CIVFEMALE, STAT_SUIT_GIRL, woman, 130C,0, null,3,7,PED_TYPE_GEN,VOICE_GEN_BFYCRP ,VOICE_GEN_BFYCRP +308, WFYCLEM, WFYCLEM, CIVFEMALE, STAT_STREET_GIRL, sexywoman,1983,1, null,4,6,PED_TYPE_GEN,VOICE_GEN_WFYST,VOICE_GEN_WFYST +309, WFYCLLV, WFYCLLV, CIVFEMALE, STAT_STREET_GIRL, woman, 1FFF,0, null,1,4,PED_TYPE_GFD,VOICE_GFD_WFYCLOT ,VOICE_GFD_WFYCLOT +310, csherna, csherna, COP, STAT_COP, swat, 1FFF, 0, null, 9,9, PED_TYPE_EMG,VOICE_EMG_RCOP1 ,VOICE_EMG_RCOP4 +311, dsherna, dsherna, COP, STAT_COP, swat, 1FFF, 0, null, 9,9, PED_TYPE_EMG,VOICE_EMG_RCOP1 ,VOICE_EMG_RCOP4 +end diff --git a/nsis/SAMP.img b/nsis/SAMP.img new file mode 100644 index 0000000..e94a100 Binary files /dev/null and b/nsis/SAMP.img differ diff --git a/nsis/SAMP.ipl b/nsis/SAMP.ipl new file mode 100644 index 0000000..50d1697 --- /dev/null +++ b/nsis/SAMP.ipl @@ -0,0 +1,63 @@ +# ------------------------------------------------------ +# ------------------------------------------------------ +# SA:MP IPL File +# -------------- +# This file was added to SA:MP to create some new cull +# zones for the enterable buildings. The cull zones +# prevent weather from appearing inside them. +# +# You should not need to edit this file. +# +# Cull zones in this file were created by: +# Matite (January and February 2015) +# +# Go to the SA:MP wiki for information about this file: +# http://wiki.sa-mp.com +# ------------------------------------------------------ +inst +# LS BeachSide interior object +19597, SanCliffI05_LAw2, 0, 280.29688, -1606.20313, 72.39844, 0.00000, 0.00000, 0.00000, 1.00000, -1 +# LS BeachSide carpark object +19800, SanCliffc05_LAw2, 0, 280.297, -1606.2, 22.3984, 0.00000, 0.00000, 0.00000, 1.00000, -1 +end +cull +# ---------------------------------------------------------------------------------------- +# CenterX, CenterY, CenterZ, SkewX, DistanceY, Bottom, DistanceX, SkewY, Top, Flag, 0 +# ---------------------------------------------------------------------------------------- +# LS BeachSide +287.916, -1608.9, 30.9127, 2.62643, 15.1336, 30.9127, 20.0683, -3.48285, 113.6127, 8, 0 +# ---------------------------------------------------------------------------------------- +# LS BeachSide Underground Car Park +275.75, -1621.74, 10.0, 0, 40.0, 10.0, 40.0, 0, 30.0, 8, 0 +# ---------------------------------------------------------------------------------------- +# LS Office +1803.7078, -1294.0806, 10.0, 0, 26.5, 10.0, 33.0, 0, 130.0, 8, 0 +# ---------------------------------------------------------------------------------------- +# LS Mall +1117.59, -1490.01, 10.0, 0, 77.0, 10.0, 73.0, 0, 29.0, 8, 0 +# ---------------------------------------------------------------------------------------- +# LS Apartments +1164.96, -1180.58, 15.0, 0, 21.0, 15.0, 44.0, 0, 92.0, 8, 0 +# ---------------------------------------------------------------------------------------- +# SF Building 1 +-2712.04, 859.58, 65.0, 0, 8.0, 65.0, 13.0, 0, 80.0, 8, 0 +# ---------------------------------------------------------------------------------------- +end +path +end +grge +end +enex +end +pick +end +cars +end +jump +end +tcyc +end +auzo +end +mult +end \ No newline at end of file diff --git a/nsis/SAMPCOL.img b/nsis/SAMPCOL.img new file mode 100644 index 0000000..a17d142 Binary files /dev/null and b/nsis/SAMPCOL.img differ diff --git a/nsis/bass.dll b/nsis/bass.dll new file mode 100644 index 0000000..11c58d7 Binary files /dev/null and b/nsis/bass.dll differ diff --git a/nsis/blanktex.txd b/nsis/blanktex.txd new file mode 100644 index 0000000..5e1733e Binary files /dev/null and b/nsis/blanktex.txd differ diff --git a/nsis/custom.img b/nsis/custom.img new file mode 100644 index 0000000..9bfe64e Binary files /dev/null and b/nsis/custom.img differ diff --git a/nsis/gtaweap3.ttf b/nsis/gtaweap3.ttf new file mode 100644 index 0000000..2aef91c Binary files /dev/null and b/nsis/gtaweap3.ttf differ diff --git a/nsis/mouse.png b/nsis/mouse.png new file mode 100644 index 0000000..989409a Binary files /dev/null and b/nsis/mouse.png differ diff --git a/nsis/rcon.exe b/nsis/rcon.exe new file mode 100644 index 0000000..26af77a Binary files /dev/null and b/nsis/rcon.exe differ diff --git a/nsis/samaps.txd b/nsis/samaps.txd new file mode 100644 index 0000000..ace2659 Binary files /dev/null and b/nsis/samaps.txd differ diff --git a/nsis/samp-license.txt b/nsis/samp-license.txt new file mode 100644 index 0000000..d1dde5d --- /dev/null +++ b/nsis/samp-license.txt @@ -0,0 +1,92 @@ +------------------------------------------------------------------------------------ + +The SA-MP modification for Grand Theft Auto: San Andreas (r) is a software project +aimed at extending the functionality of the Grand Theft Auto: San Andreas (r) +software for Microsoft Windows (r). + +------------------------------------------------------------------------------------ + +SA-MP CLIENT AND SERVER SOFTWARE LICENSE AGREEMENT AND ATTRIBUTIONS + + +---- LICENSE TERMS ---- + +(a) You must have a valid license to use Grand Theft Auto: San Andreas (r) PC +in order for this license to be valid. + +(b) The software contained herein is provided on an "as-is" basis without +any form of warranty. + +(c) This software may not be exploited for personal, financial or +commercial gain. + +(d) The author(s) of this software accept no liability for use/misuse of the +software. + +(e) The SA-MP software package may not be distributed, sold, rented or +leased, without written permission of the software author(s). + +(f) You may not create or distribute derivative works of the software or files +contained within the package. + +(g) You may not use this software for any illegal purposes. + +(h) The author(s) of this software retain the right to modify/revoke this license +at any time under any conditions seen appropriate by the author(s). + +(i) Ideas expressed in this software by way of coding or configuration are +property of SA-MP.com. + + +------------------------------------------------------------------------------------ + +(c) 2005-2011 SA-MP.com team. + +The SA-MP.com team is not affiliated with Rockstar Games, Rockstar North or +Take-Two Interactive Software Inc. + +Grand Theft Auto and Grand Theft Auto: San Andreas are registered trademarks of +Take-Two Interactive Software Inc. + +------------------------------------------------------------------------------------ + + +---- ATTRIBUTIONS ---- + +- This software makes use of the RakNet networking library (c) 2003 Kevin Jenkins +- This software makes use of the Pawn language (c) ITB CompuPhase, 1997-2005 +- This software makes use of the BASS audio library (c) Un4seen Developments Ltd +- This software makes use of the ttmath library (c) 2006-2009, Tomasz Sowa + +*** ttmath LIBRARY LICENSE *** + + Copyright (c) 2006-2009, Tomasz Sowa + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + Neither the name Tomasz Sowa nor the names of contributors to this + project may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. + +------------------------------------------------------------------------------------ diff --git a/nsis/samp.dll b/nsis/samp.dll new file mode 100644 index 0000000..89fa889 Binary files /dev/null and b/nsis/samp.dll differ diff --git a/nsis/samp.saa b/nsis/samp.saa new file mode 100644 index 0000000..eae9a65 Binary files /dev/null and b/nsis/samp.saa differ diff --git a/nsis/samp_debug.exe b/nsis/samp_debug.exe new file mode 100644 index 0000000..1da25d2 Binary files /dev/null and b/nsis/samp_debug.exe differ diff --git a/nsis/sampaux3.ttf b/nsis/sampaux3.ttf new file mode 100644 index 0000000..cc3735e Binary files /dev/null and b/nsis/sampaux3.ttf differ diff --git a/nsis/sampgui.png b/nsis/sampgui.png new file mode 100644 index 0000000..af4115f Binary files /dev/null and b/nsis/sampgui.png differ diff --git a/raknet/MTUSize.h b/raknet/MTUSize.h index 9af6b0d..2cf5ec7 100644 --- a/raknet/MTUSize.h +++ b/raknet/MTUSize.h @@ -33,12 +33,16 @@ #ifdef _COMPATIBILITY_1 #define DEFAULT_MTU_SIZE 1264 #else -#define DEFAULT_MTU_SIZE 1500 +#define DEFAULT_MTU_SIZE 576 #endif /// The largest value for an UDP datagram /// \sa RakPeer::SetMTUSize() -#define MAXIMUM_MTU_SIZE 1500 +#ifdef SAMPCLI +#define MAXIMUM_MTU_SIZE 1492 +#else +#define MAXIMUM_MTU_SIZE 576 +#endif #endif diff --git a/raknet/PacketPriority.h b/raknet/PacketPriority.h index e3ee020..b6c4877 100644 --- a/raknet/PacketPriority.h +++ b/raknet/PacketPriority.h @@ -32,7 +32,7 @@ enum PacketPriority /// \note Note to self: I write this with 3 bits in the stream. If I add more remember to change that enum PacketReliability { - UNRELIABLE, /// Same as regular UDP, except that it will also discard duplicate datagrams. RakNet adds (6 to 17) + 21 bits of overhead, 16 of which is used to detect duplicate packets and 6 to 17 of which is used for message length. + UNRELIABLE = 6, /// Same as regular UDP, except that it will also discard duplicate datagrams. RakNet adds (6 to 17) + 21 bits of overhead, 16 of which is used to detect duplicate packets and 6 to 17 of which is used for message length. UNRELIABLE_SEQUENCED, /// Regular UDP with a sequence counter. Out of order messages will be discarded. This adds an additional 13 bits on top what is used for UNRELIABLE. RELIABLE, /// The message is sent reliably, but not necessarily in any order. Same overhead as UNRELIABLE. RELIABLE_ORDERED, /// This message is reliable and will arrive in the order you sent it. Messages will be delayed while waiting for out of order messages. Same overhead as UNRELIABLE_SEQUENCED. diff --git a/raknet/RPCMap.h b/raknet/RPCMap.h index 6e25337..873ccf6 100644 --- a/raknet/RPCMap.h +++ b/raknet/RPCMap.h @@ -41,7 +41,6 @@ public: RPCIndex GetIndexFromFunctionName(unsigned char uniqueIdentifier); void AddIdentifierWithFunction(unsigned char uniqueIdentifier, void *functionPointer, bool isPointerToMember); protected: - DataStructures::List rpcSet; RPCNode *rpcSet[RPC_SET_SIZE]; }; diff --git a/raknet/RakNetStatistics.cpp b/raknet/RakNetStatistics.cpp index 679db45..3153b76 100644 --- a/raknet/RakNetStatistics.cpp +++ b/raknet/RakNetStatistics.cpp @@ -19,6 +19,10 @@ #include "BitStream.h" // BITS_TO_BYTES #include "GetTime.h" +RakNetTime connectionStartTimeSaved=0; +uint64_t totalBitsSentSaved=0; +uint64_t bitsReceivedSaved=0; + // Verbosity level currently supports 0 (low), 1 (medium), 2 (high) // Buffer must be hold enough to hold the output string. See the source to get an idea of how many bytes will be output void StatisticsToString( RakNetStatisticsStruct *s, char *buffer, int verbosityLevel ) @@ -29,29 +33,25 @@ void StatisticsToString( RakNetStatisticsStruct *s, char *buffer, int verbosityL return ; } - if ( verbosityLevel == 0 ) - { - // Verbosity level 0 - sprintf( buffer, - "Total bytes sent: %u\n" - "Total bytes received: %u\n" - "Packetloss: %.1f%%\n", - BITS_TO_BYTES( s->totalBitsSent ), - BITS_TO_BYTES( s->bitsReceived + s->bitsWithBadCRCReceived ), - 100.0f * ( float ) s->messagesTotalBitsResent / ( float ) s->totalBitsSent ); - } - - else if ( verbosityLevel == 1 ) + if ( verbosityLevel == 1 ) { RakNetTime time = RakNet::GetTime(); double elapsedTime; double bpsSent; double bpsReceived; - elapsedTime = (time-s->connectionStartTime) / 1000.0f; - bpsSent = (double) s->totalBitsSent / elapsedTime; - bpsReceived= (double) s->bitsReceived / elapsedTime; - // Verbosity level 1 + if ( connectionStartTimeSaved == 0 ) + connectionStartTimeSaved = s->connectionStartTime; + + elapsedTime = (time-connectionStartTimeSaved) / 1000.0f; + bpsSent = (double) ((unsigned)s->totalBitsSent-totalBitsSentSaved) / elapsedTime; + bpsReceived = (double) ((unsigned)s->bitsReceived-bitsReceivedSaved) / elapsedTime; + + totalBitsSentSaved = s->totalBitsSent; + bitsReceivedSaved = s->bitsReceived; + connectionStartTimeSaved = RakNet::GetTime(); + + // Verbosity level 1 sprintf( buffer, "Messages in Send buffer: %u\n" "Messages sent: %u\n" @@ -67,26 +67,26 @@ void StatisticsToString( RakNetStatisticsStruct *s, char *buffer, int verbosityL "Acks received: %u\n" "Duplicate acks received: %u\n" "Inst. KBits per second: %.1f\n" - "KBits per second sent:\t\t\t%.1f\n" - "KBits per second received:\t\t%.1f\n", + "KBits per second sent: %.1f\n" + "KBits per second received: %.1f\n", s->messageSendBuffer[ SYSTEM_PRIORITY ] + s->messageSendBuffer[ HIGH_PRIORITY ] + s->messageSendBuffer[ MEDIUM_PRIORITY ] + s->messageSendBuffer[ LOW_PRIORITY ], s->messagesSent[ SYSTEM_PRIORITY ] + s->messagesSent[ HIGH_PRIORITY ] + s->messagesSent[ MEDIUM_PRIORITY ] + s->messagesSent[ LOW_PRIORITY ], - BITS_TO_BYTES( s->totalBitsSent ), + ( unsigned ) BITS_TO_BYTES( s->totalBitsSent ), s->acknowlegementsSent, s->acknowlegementsPending, s->messagesOnResendQueue, s->messageResends, - BITS_TO_BYTES( s->messagesTotalBitsResent ), + ( unsigned ) BITS_TO_BYTES( s->messagesTotalBitsResent ), 100.0f * ( float ) s->messagesTotalBitsResent / ( float ) s->totalBitsSent, s->duplicateMessagesReceived + s->invalidMessagesReceived + s->messagesReceived, - BITS_TO_BYTES( s->bitsReceived + s->bitsWithBadCRCReceived ), + ( unsigned ) BITS_TO_BYTES( s->bitsReceived + s->bitsWithBadCRCReceived ), s->acknowlegementsReceived, s->duplicateAcknowlegementsReceived, s->bitsPerSecond / 1000.0, bpsSent / 1000.0, bpsReceived / 1000.0); } - else + else if ( verbosityLevel == 2 ) { RakNetTime time = RakNet::GetTime(); double elapsedTime; @@ -169,7 +169,36 @@ void StatisticsToString( RakNetStatisticsStruct *s, char *buffer, int verbosityL s->bitsPerSecond/1000.0, elapsedTime, bpsSent / 1000.0, - bpsReceived / 1000.0 - ); + bpsReceived / 1000.0); } -} + else if ( verbosityLevel == 4 ) + { + sprintf( buffer, + "Messages in Send buffer: %u\n" + "Messages sent: %u\n" + "Bytes sent: %u\n" + "Acks sent: %u\n" + "Acks in send buffer: %u\n" + "Messages waiting for ack: %u\n" + "Messages resent: %u\n" + "Bytes resent: %u\n" + "Packetloss: %.1f%%\n" + "Messages received: %u\n" + "Bytes received: %u\n" + "Acks received: %u\n" + "Duplicate acks received: %u\n", + s->messageSendBuffer[ SYSTEM_PRIORITY ] + s->messageSendBuffer[ HIGH_PRIORITY ] + s->messageSendBuffer[ MEDIUM_PRIORITY ] + s->messageSendBuffer[ LOW_PRIORITY ], + s->messagesSent[ SYSTEM_PRIORITY ] + s->messagesSent[ HIGH_PRIORITY ] + s->messagesSent[ MEDIUM_PRIORITY ] + s->messagesSent[ LOW_PRIORITY ], + ( unsigned ) BITS_TO_BYTES( s->totalBitsSent ), + s->acknowlegementsSent, + s->acknowlegementsPending, + s->messagesOnResendQueue, + s->messageResends, + ( unsigned ) BITS_TO_BYTES( s->messagesTotalBitsResent ), + 100.0f * ( float ) s->messagesTotalBitsResent / ( float ) s->totalBitsSent, + s->duplicateMessagesReceived + s->invalidMessagesReceived + s->messagesReceived, + ( unsigned ) BITS_TO_BYTES( s->bitsReceived + s->bitsWithBadCRCReceived ), + s->acknowlegementsReceived, + s->duplicateAcknowlegementsReceived); + } +} \ No newline at end of file diff --git a/raknet/RakNetStatistics.h b/raknet/RakNetStatistics.h index e24fd2a..773e778 100644 --- a/raknet/RakNetStatistics.h +++ b/raknet/RakNetStatistics.h @@ -23,20 +23,27 @@ #include "Export.h" #include "NetworkTypes.h" -/// \brief Network Statisics Usage +typedef unsigned long long uint64_t; + +/// \brief Network Statisics Usage /// -/// Store Statistics information related to network usage +/// Store Statistics information related to network usage struct RAK_DLL_EXPORT RakNetStatisticsStruct { + // TODO: RakNetStatisticsStruct + /// Number of Messages in the send Buffer (high, medium, low priority) unsigned messageSendBuffer[ NUMBER_OF_PRIORITIES ]; /// Number of messages sent (high, medium, low priority) unsigned messagesSent[ NUMBER_OF_PRIORITIES ]; + + char _gap20[16]; + /// Number of data bits used for user messages - unsigned messageDataBitsSent[ NUMBER_OF_PRIORITIES ]; + uint64_t messageDataBitsSent[ NUMBER_OF_PRIORITIES ]; /// Number of total bits used for user messages, including headers - unsigned messageTotalBitsSent[ NUMBER_OF_PRIORITIES ]; - + uint64_t messageTotalBitsSent[ NUMBER_OF_PRIORITIES ]; + /// Number of packets sent containing only acknowledgements unsigned packetsContainingOnlyAcknowlegements; /// Number of acknowledgements sent @@ -44,53 +51,53 @@ struct RAK_DLL_EXPORT RakNetStatisticsStruct /// Number of acknowledgements waiting to be sent unsigned acknowlegementsPending; /// Number of acknowledgements bits sent - unsigned acknowlegementBitsSent; - + uint64_t acknowlegementBitsSent; + /// Number of packets containing only acknowledgements and resends unsigned packetsContainingOnlyAcknowlegementsAndResends; - + /// Number of messages resent unsigned messageResends; /// Number of bits resent of actual data - unsigned messageDataBitsResent; + uint64_t messageDataBitsResent; /// Total number of bits resent, including headers - unsigned messagesTotalBitsResent; + uint64_t messagesTotalBitsResent; /// Number of messages waiting for ack (// TODO - rename this) unsigned messagesOnResendQueue; - + /// Number of messages not split for sending unsigned numberOfUnsplitMessages; /// Number of messages split for sending unsigned numberOfSplitMessages; /// Total number of splits done for sending unsigned totalSplits; - + /// Total packets sent unsigned packetsSent; - + /// Number of bits added by encryption - unsigned encryptionBitsSent; + uint64_t encryptionBitsSent; /// total bits sent - unsigned totalBitsSent; - + uint64_t totalBitsSent; + /// Number of sequenced messages arrived out of order unsigned sequencedMessagesOutOfOrder; /// Number of sequenced messages arrived in order unsigned sequencedMessagesInOrder; - + /// Number of ordered messages arrived out of order unsigned orderedMessagesOutOfOrder; /// Number of ordered messages arrived in order unsigned orderedMessagesInOrder; - + /// Packets with a good CRC received unsigned packetsReceived; /// Packets with a bad CRC received unsigned packetsWithBadCRCReceived; /// Bits with a good CRC received - unsigned bitsReceived; + uint64_t bitsReceived; /// Bits with a bad CRC received - unsigned bitsWithBadCRCReceived; + uint64_t bitsWithBadCRCReceived; /// Number of acknowledgement messages received for packets we are resending unsigned acknowlegementsReceived; /// Number of acknowledgement messages received for packets we are not resending @@ -110,7 +117,14 @@ struct RAK_DLL_EXPORT RakNetStatisticsStruct /// connection start time RakNetTime connectionStartTime; - RakNetStatisticsStruct operator +=(const RakNetStatisticsStruct& other) + RakNetTime field_110; + unsigned field_114; + unsigned field_118; + RakNetTime field_11C; + unsigned field_120; + unsigned field_124; + + void operator +=(const RakNetStatisticsStruct& other) { unsigned i; for (i=0; i < NUMBER_OF_PRIORITIES; i++) @@ -151,18 +165,9 @@ struct RAK_DLL_EXPORT RakNetStatisticsStruct duplicateMessagesReceived+=other.duplicateMessagesReceived; messagesWaitingForReassembly+=other.messagesWaitingForReassembly; internalOutputQueueSize+=other.internalOutputQueueSize; - - return *this; } }; -/// Verbosity level currently supports 0 (low), 1 (medium), 2 (high) -/// \param[in] s The Statistical information to format out -/// \param[in] buffer The buffer containing a formated report -/// \param[in] verbosityLevel -/// 0 low -/// 1 medium -/// 2 high void StatisticsToString( RakNetStatisticsStruct *s, char *buffer, int verbosityLevel ); -#endif +#endif \ No newline at end of file diff --git a/raknet/RakPeer.cpp b/raknet/RakPeer.cpp index 595a311..1bc74a5 100644 --- a/raknet/RakPeer.cpp +++ b/raknet/RakPeer.cpp @@ -46,6 +46,12 @@ #include "RouterInterface.h" #include "RakAssert.h" +#ifdef _WIN32 +#include +#else +#define OutputDebugString NULL +#endif + #if !defined ( __APPLE__ ) && !defined ( __APPLE_CC__ ) #include #endif @@ -1191,7 +1197,7 @@ bool RakPeer::RPC( char* uniqueID, const char *data, unsigned int bitLength, Pac #else sendList = new unsigned[1]; #endif - remoteSystemIndex=GetIndexFromPlayerID( playerId, false ); + remoteSystemIndex=GetIndexFromPlayerID( playerId, false ); if (remoteSystemIndex!=(unsigned)-1 && remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ASAP && remoteSystemList[remoteSystemIndex].connectMode!=RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY && @@ -1763,7 +1769,7 @@ void RakPeer::SendStaticData( const PlayerID target ) // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- void RakPeer::SetOfflinePingResponse( const char *data, const unsigned int length ) { - assert(length < 400); + //assert(length < 400); rakPeerMutexes[ offlinePingResponse_Mutex ].Lock(); offlinePingResponse.Reset(); @@ -2053,7 +2059,7 @@ void RakPeer::AdvertiseSystem( const char *host, unsigned short remotePort, cons // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- void RakPeer::SetSplitMessageProgressInterval(int interval) { - RakAssert(interval>=0); + //RakAssert(interval>=0); splitMessageProgressInterval=interval; for ( unsigned short i = 0; i < maximumNumberOfPeers; i++ ) remoteSystemList[ i ].reliabilityLayer.SetSplitMessageProgressInterval(splitMessageProgressInterval); @@ -2067,7 +2073,7 @@ void RakPeer::SetSplitMessageProgressInterval(int interval) // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- void RakPeer::SetUnreliableTimeout(RakNetTime timeoutMS) { - RakAssert(timeoutMS>=0); + //RakAssert(timeoutMS>=0); unreliableTimeout=timeoutMS; for ( unsigned short i = 0; i < maximumNumberOfPeers; i++ ) remoteSystemList[ i ].reliabilityLayer.SetUnreliableTimeout(unreliableTimeout); @@ -2408,7 +2414,7 @@ int RakPeer::GetIndexFromPlayerID( const PlayerID playerId, bool calledFromNetwo index = remoteSystemLookup.GetIndexFromKey(playerId, &objectExists); if (objectExists) { - assert(remoteSystemList[remoteSystemLookup[index].index].playerId==playerId); + //assert(remoteSystemList[remoteSystemLookup[index].index].playerId==playerId); return remoteSystemLookup[index].index; } else @@ -2774,6 +2780,12 @@ RakNetTime RakPeer::GetBestClockDifferential( const PlayerID playerId ) const return clockDifferential; } +// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +RakNetTime RakPeer::GetTimestampFromPlayerID( const PlayerID playerId, RakNetTime time ) const +{ + return time - GetBestClockDifferential(playerId); +} + // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- // Description: // Handles an RPC packet. If you get a packet with the ID ID_RPC you should pass it to this function @@ -3743,197 +3755,14 @@ void ProcessNetworkPacket( const unsigned int binaryAddress, const unsigned shor return; } - // Connecting to a system we are already connected to. - else if ((unsigned char)(data)[0] == (unsigned char) ID_CONNECTION_ATTEMPT_FAILED && length <= sizeof(unsigned char)*2) - { - // Remove the connection attempt from the buffered commands - RakPeer::RequestedConnectionStruct *rcsFirst, *rcs; - rcsFirst = rakPeer->requestedConnectionList.ReadLock(); - rcs=rcsFirst; - bool connectionAttemptCancelled=false; - while (rcs) - { - if (rcs->actionToTake==RakPeer::RequestedConnectionStruct::CONNECT && rcs->playerId==playerId) - { - connectionAttemptCancelled=true; - if (rcs==rcsFirst) - { - rakPeer->requestedConnectionList.ReadUnlock(); - rcsFirst=rakPeer->requestedConnectionList.ReadLock(); - rcs=rcsFirst; - } - else - { - // Hole in the middle - rcs->playerId=UNASSIGNED_PLAYER_ID; - rcs=rakPeer->requestedConnectionList.ReadLock(); - } - continue; - } + ID_CONNECTION_ATTEMPT_FAILED; + ID_NO_FREE_INCOMING_CONNECTIONS; + ID_CONNECTION_BANNED; - rcs=rakPeer->requestedConnectionList.ReadLock(); - } - if (rcsFirst) - rakPeer->requestedConnectionList.CancelReadLock(rcsFirst); - if (connectionAttemptCancelled) - { - // Tell user of connection attempt failed - packet=AllocPacket(sizeof( char )); - packet->data[ 0 ] = ID_CONNECTION_ATTEMPT_FAILED; // Attempted a connection and couldn't - packet->bitSize = ( sizeof( char ) * 8); - packet->playerId = playerId; - packet->playerIndex = 65535; - rakPeer->AddPacketToProducer(packet); - } - } - // We didn't check this datagram to see if it came from a connected system or not yet. - // Therefore, this datagram must be under 17 bits - otherwise it may be normal network traffic as the min size for a raknet send is 17 bits - else if ((unsigned char)(data)[0] == ID_OPEN_CONNECTION_REQUEST && length == sizeof(unsigned char)*2) - { - for (i=0; i < rakPeer->messageHandlerList.Size(); i++) - rakPeer->messageHandlerList[i]->OnDirectSocketReceive(data, length*8, playerId); - // If this guy is already connected and they initiated the connection, ignore the connection request - RakPeer::RemoteSystemStruct *rss = rakPeer->GetRemoteSystemFromPlayerID( playerId, true, true ); - if (rss==0 || rss->weInitiatedTheConnection==true) - { - // Assign new remote system - if (rss==0) - rss=rakPeer->AssignPlayerIDToRemoteSystemList(playerId, RakPeer::RemoteSystemStruct::UNVERIFIED_SENDER); - - unsigned char c[2]; - if (rss) // If this guy is already connected remote system will be 0 - c[0] = ID_OPEN_CONNECTION_REPLY; - else - c[0] = ID_NO_FREE_INCOMING_CONNECTIONS; - c[1] = 0; // Pad, some routers apparently block 1 byte packets - - unsigned i; - for (i=0; i < rakPeer->messageHandlerList.Size(); i++) - rakPeer->messageHandlerList[i]->OnDirectSocketSend((char*)&c, 16, playerId); - SocketLayer::Instance()->SendTo( rakPeer->connectionSocket, (char*)&c, 2, playerId.binaryAddress, playerId.port ); - - return; - } - else if (rss!=0) - { - // If this is an existing connection, and they are already fully connected (not in progress), reply with connection attempt failed - if (rss->connectMode==RakPeer::RemoteSystemStruct::CONNECTED || - rss->connectMode==RakPeer::RemoteSystemStruct::DISCONNECT_ASAP || - rss->connectMode==RakPeer::RemoteSystemStruct::DISCONNECT_ASAP_SILENTLY) - { - char c[2]; - c[0] = ID_CONNECTION_ATTEMPT_FAILED; - c[1] = 0; // Pad, some routers apparently block 1 byte packets - - unsigned i; - for (i=0; i < rakPeer->messageHandlerList.Size(); i++) - rakPeer->messageHandlerList[i]->OnDirectSocketSend((char*)&c, 16, playerId); - SocketLayer::Instance()->SendTo( rakPeer->connectionSocket, (char*)&c, 2, playerId.binaryAddress, playerId.port ); - } - } - - } - - // See if this datagram came from a connected system - remoteSystem = rakPeer->GetRemoteSystemFromPlayerID( playerId, true, true ); - if ( remoteSystem ) - { - if (remoteSystem->connectMode==RakPeer::RemoteSystemStruct::SET_ENCRYPTION_ON_MULTIPLE_16_BYTE_PACKET && (length%16)==0) - remoteSystem->reliabilityLayer.SetEncryptionKey( remoteSystem->AESKey ); - - // Handle regular incoming data - // HandleSocketReceiveFromConnectedPlayer is only safe to be called from the same thread as Update, which is this thread - if ( remoteSystem->reliabilityLayer.HandleSocketReceiveFromConnectedPlayer( data, length, playerId, rakPeer->messageHandlerList, rakPeer->MTUSize ) == false ) - { - // These kinds of packets may have been duplicated and incorrectly determined to be - // cheat packets. Anything else really is a cheat packet - if ( !( - ( (unsigned char)data[0] == ID_OPEN_CONNECTION_REQUEST && length <= 2 ) || - ( (unsigned char)data[0] == ID_OPEN_CONNECTION_REPLY && length <= 2 ) || - ( (unsigned char)data[0] == ID_CONNECTION_ATTEMPT_FAILED && length <= 2 ) || - ( ((unsigned char)data[0] == ID_PING_OPEN_CONNECTIONS || (unsigned char)data[0] == ID_PING || (unsigned char)data[0] == ID_PONG) && length >= sizeof(unsigned char)+sizeof(RakNetTime) ) || - ( (unsigned char)data[0] == ID_ADVERTISE_SYSTEM && lengthdata[ 0 ] = ID_MODIFIED_PACKET; - packet->bitSize = sizeof( char ) * 8; - packet->playerId = playerId; - packet->playerIndex = ( PlayerIndex ) rakPeer->GetIndexFromPlayerID( playerId, true ); - rakPeer->AddPacketToProducer(packet); - } - } - } - else - { - for (i=0; i < rakPeer->messageHandlerList.Size(); i++) - rakPeer->messageHandlerList[i]->OnDirectSocketReceive(data, length*8, playerId); - - if (length > 512) - { -#if !defined(_COMPATIBILITY_1) - // Flood attack? Unknown systems should never send more than a small amount of data. Do a short ban - rakPeer->AddToBanList(rakPeer->PlayerIDToDottedIP(playerId), 10000); -#endif - return; - } - - // These are all messages from unconnected systems. Messages here can be any size, but are never processed from connected systems. - if ( ( (unsigned char) data[ 0 ] == ID_PING_OPEN_CONNECTIONS - || (unsigned char)(data)[0] == ID_PING) && length == sizeof(unsigned char)+sizeof(RakNetTime) ) - { - if ( (unsigned char)(data)[0] == ID_PING || - rakPeer->AllowIncomingConnections() ) // Open connections with players - { -#if !defined(_COMPATIBILITY_1) - RakNet::BitStream inBitStream( (unsigned char *) data, length, false ); - inBitStream.IgnoreBits(8); - RakNetTime sendPingTime; - inBitStream.Read(sendPingTime); - - RakNet::BitStream outBitStream; - outBitStream.Write((unsigned char)ID_PONG); // Should be named ID_UNCONNECTED_PONG eventually - outBitStream.Write(sendPingTime); - //tempBitStream.Write( data, UnconnectedPingStruct_Size ); - rakPeer->rakPeerMutexes[ RakPeer::offlinePingResponse_Mutex ].Lock(); - // They are connected, so append offline ping data - outBitStream.Write( (char*)rakPeer->offlinePingResponse.GetData(), rakPeer->offlinePingResponse.GetNumberOfBytesUsed() ); - rakPeer->rakPeerMutexes[ RakPeer::offlinePingResponse_Mutex ].Unlock(); - //SocketLayer::Instance()->SendTo( connectionSocket, ( char* ) outBitStream.GetData(), outBitStream.GetNumberOfBytesUsed(), playerId.binaryAddress, playerId.port ); - - unsigned i; - for (i=0; i < rakPeer->messageHandlerList.Size(); i++) - rakPeer->messageHandlerList[i]->OnDirectSocketSend((const char*)outBitStream.GetData(), outBitStream.GetNumberOfBytesUsed(), playerId); - - SocketLayer::Instance()->SendTo( rakPeer->connectionSocket, (const char*)outBitStream.GetData(), outBitStream.GetNumberOfBytesUsed(), (char*)rakPeer->PlayerIDToDottedIP(playerId) , playerId.port ); -#endif - } - } - // UNCONNECTED MESSAGE Pong with no data. TODO - Problem - this matches a reliable send of other random data. - else if ((unsigned char) data[ 0 ] == ID_PONG && length >= sizeof(unsigned char)+sizeof(RakNetTime) && length < sizeof(unsigned char)+sizeof(RakNetTime)+MAX_OFFLINE_DATA_LENGTH) - { - packet=AllocPacket(length); - memcpy(packet->data, data, length); - packet->bitSize = length * 8; - packet->playerId = playerId; - packet->playerIndex = ( PlayerIndex ) rakPeer->GetIndexFromPlayerID( playerId, true ); - rakPeer->AddPacketToProducer(packet); - } - else if ((unsigned char) data[ 0 ] == ID_ADVERTISE_SYSTEM && length >= 2 && length < MAX_OFFLINE_DATA_LENGTH+2) - { - packet=AllocPacket(length); - memcpy(packet->data, data, length); - packet->bitSize = length * 8; - packet->playerId = playerId; - packet->playerIndex = ( PlayerIndex ) rakPeer->GetIndexFromPlayerID( playerId, true ); - rakPeer->AddPacketToProducer(packet); - } - } } // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -4452,6 +4281,7 @@ bool RakPeer::RunUpdateCycle( void ) inBitStream.IgnoreBits(8); stringCompressor->DecodeString(output, 255, &inBitStream); inBitStream.ReadCompressed(index); + //remoteSystem->rpcMap.AddIdentifierAtIndex((char*)output,index); delete [] data; } else if ( (unsigned char) data[ 0 ] == ID_REQUEST_STATIC_DATA ) diff --git a/raknet/RakPeer.h b/raknet/RakPeer.h index 2a99061..502c37f 100644 --- a/raknet/RakPeer.h +++ b/raknet/RakPeer.h @@ -471,6 +471,8 @@ public: /// \sa RakNetStatistics.h RakNetStatisticsStruct * const GetStatistics( const PlayerID playerId ); + RakNetTime GetTimestampFromPlayerID( const PlayerID playerId, RakNetTime time ) const; + // --------------------------------------------------------------------------------------------EVERYTHING AFTER THIS COMMENT IS FOR INTERNAL USE ONLY-------------------------------------------------------------------------------------------- /// \internal RPCMap *GetRPCMap( const PlayerID playerId); diff --git a/raknet/RakPeerInterface.h b/raknet/RakPeerInterface.h index 79b154d..43ddf00 100644 --- a/raknet/RakPeerInterface.h +++ b/raknet/RakPeerInterface.h @@ -462,6 +462,8 @@ public: /// \sa RakNetStatistics.h virtual RakNetStatisticsStruct * const GetStatistics( const PlayerID playerId )=0; + virtual RakNetTime GetTimestampFromPlayerID( const PlayerID playerId, RakNetTime time ) const=0; + // --------------------------------------------------------------------------------------------EVERYTHING AFTER THIS COMMENT IS FOR INTERNAL USE ONLY-------------------------------------------------------------------------------------------- /// \internal virtual RPCMap *GetRPCMap( const PlayerID playerId)=0; diff --git a/raknet/RakServer.cpp b/raknet/RakServer.cpp index 5155dbb..c091917 100644 --- a/raknet/RakServer.cpp +++ b/raknet/RakServer.cpp @@ -111,50 +111,6 @@ Packet* RakServer::Receive( void ) { Packet * packet = RakPeer::Receive(); - // This is just a regular time based update. Nowhere else good to put it - - if ( RakPeer::IsActive() && occasionalPing ) - { - RakNetTime time = RakNet::GetTime(); - - if ( time > broadcastPingsTime || ( packet && packet->data[ 0 ] == ID_RECEIVED_STATIC_DATA ) ) - { - if ( time > broadcastPingsTime ) - broadcastPingsTime = time + 30000; // Broadcast pings every 30 seconds - - unsigned i, count; - - RemoteSystemStruct *remoteSystem; - RakNet::BitStream bitStream( ( PlayerID_Size + sizeof( short ) ) * 32 + sizeof(unsigned char) ); - unsigned char typeId = ID_BROADCAST_PINGS; - - bitStream.Write( typeId ); - - //for ( i = 0, count = 0; count < 32 && i < remoteSystemListSize; i++ ) - for ( i = 0, count = 0; count < 32 && i < maximumNumberOfPeers; i++ ) - { - remoteSystem = remoteSystemList + i; - - if ( remoteSystem->playerId != UNASSIGNED_PLAYER_ID && remoteSystem->isActive) - { - bitStream.Write( remoteSystem->playerId.binaryAddress ); - bitStream.Write( remoteSystem->playerId.port ); - bitStream.Write( remoteSystem->pingAndClockDifferential[ remoteSystem->pingAndClockDifferentialWriteIndex ].pingTime ); - count++; - } - } - - if ( count > 0 ) // If we wrote anything - { - - if ( packet && packet->data[ 0 ] == ID_NEW_INCOMING_CONNECTION ) // If this was a new connection - Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, packet->playerId, false ); // Send to the new connection - else - Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, UNASSIGNED_PLAYER_ID, true ); // Send to everyone - } - } - } - // This is just a regular time based update. Nowhere else good to put it if ( RakPeer::IsActive() && synchronizedRandomInteger ) { @@ -172,17 +128,6 @@ Packet* RakServer::Receive( void ) if ( nextSeed % 2 == 0 ) // Even nextSeed--; // make odd - /* SetRandomNumberSeedStruct s; - - s.ts = ID_TIMESTAMP; - s.timeStamp = RakNet::GetTime(); - s.typeId = ID_SET_RANDOM_NUMBER_SEED; - s.seed = seed; - s.nextSeed = nextSeed; - RakNet::BitStream s_BitS( SetRandomNumberSeedStruct_Size ); - s.Serialize( s_BitS ); - */ - RakNet::BitStream outBitStream(sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned char)+sizeof(unsigned int)+sizeof(unsigned int)); outBitStream.Write((unsigned char) ID_TIMESTAMP); outBitStream.Write((unsigned int) RakNet::GetTime()); @@ -197,84 +142,6 @@ Packet* RakServer::Receive( void ) } } - if ( packet ) - { - // Intercept specific client / server feature packets. This will do an extra send and still pass on the data to the user - - if ( packet->data[ 0 ] == ID_RECEIVED_STATIC_DATA ) - { - if ( relayStaticClientData ) - { - // Relay static data to the other systems but the sender - RakNet::BitStream bitStream( packet->length + PlayerID_Size ); - unsigned char typeId = ID_REMOTE_STATIC_DATA; - bitStream.Write( typeId ); - bitStream.Write( packet->playerId.binaryAddress ); - bitStream.Write( packet->playerId.port ); - bitStream.Write( packet->playerIndex ); - bitStream.Write( ( char* ) packet->data + sizeof(unsigned char), packet->length - sizeof(unsigned char) ); - Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, packet->playerId, true ); - } - } - - else - if ( packet->data[ 0 ] == ID_DISCONNECTION_NOTIFICATION || packet->data[ 0 ] == ID_CONNECTION_LOST || packet->data[ 0 ] == ID_NEW_INCOMING_CONNECTION ) - { - // Relay the disconnection - RakNet::BitStream bitStream( packet->length + PlayerID_Size ); - unsigned char typeId; - - if ( packet->data[ 0 ] == ID_DISCONNECTION_NOTIFICATION ) - typeId = ID_REMOTE_DISCONNECTION_NOTIFICATION; - else - if ( packet->data[ 0 ] == ID_CONNECTION_LOST ) - typeId = ID_REMOTE_CONNECTION_LOST; - else - typeId = ID_REMOTE_NEW_INCOMING_CONNECTION; - - bitStream.Write( typeId ); - bitStream.Write( packet->playerId.binaryAddress ); - bitStream.Write( packet->playerId.port ); - bitStream.Write( ( unsigned short& ) packet->playerIndex ); - - Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, packet->playerId, true ); - - if ( packet->data[ 0 ] == ID_NEW_INCOMING_CONNECTION ) - { - unsigned i; - - //for ( i = 0; i < remoteSystemListSize; i++ ) - for ( i = 0; i < maximumNumberOfPeers; i++ ) - { - if ( remoteSystemList[ i ].isActive && remoteSystemList[ i ].playerId != UNASSIGNED_PLAYER_ID && packet->playerId != remoteSystemList[ i ].playerId ) - { - bitStream.Reset(); - typeId = ID_REMOTE_EXISTING_CONNECTION; - bitStream.Write( typeId ); - bitStream.Write( remoteSystemList[ i ].playerId.binaryAddress ); - bitStream.Write( remoteSystemList[ i ].playerId.port ); - bitStream.Write( ( unsigned short ) i ); - // One send to tell them of the connection - Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, packet->playerId, false ); - - if ( relayStaticClientData ) - { - bitStream.Reset(); - typeId = ID_REMOTE_STATIC_DATA; - bitStream.Write( typeId ); - bitStream.Write( remoteSystemList[ i ].playerId.binaryAddress ); - bitStream.Write( remoteSystemList[ i ].playerId.port ); - bitStream.Write( (unsigned short) i ); - bitStream.Write( ( char* ) remoteSystemList[ i ].staticData.GetData(), remoteSystemList[ i ].staticData.GetNumberOfBytesUsed() ); - // Another send to tell them of the static data - Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, packet->playerId, false ); - } - } - } - } - } - } - return packet; } @@ -397,6 +264,13 @@ bool RakServer::RPC( char* uniqueID, RakNet::BitStream *parameters, PacketPriori return RakPeer::RPC( uniqueID, parameters, priority, reliability, orderingChannel, playerId, broadcast, shiftTimestamp, networkID, replyFromTarget ); } +// SAMPSRV (adding this just as a tag for next RakNet upgrade) +bool RakServer::RPC( char* uniqueID, RakNet::BitStream *parameters, PacketPriority priority, PacketReliability reliability, char orderingChannel, PlayerID playerId, bool broadcast, bool shiftTimestamp) +{ + return RakPeer::RPC( uniqueID, parameters, priority, reliability, orderingChannel, playerId, broadcast, shiftTimestamp, UNASSIGNED_NETWORK_ID, 0 ); +} +// SAMPSRV end + void RakServer::SetTrackFrequencyTable( bool b ) { RakPeer::SetCompileFrequencyTable( b ); @@ -483,7 +357,7 @@ void RakServer::ChangeStaticClientData( const PlayerID playerChangedId, PlayerID bitStream.Write( ( char* ) remoteSystem->staticData.GetData(), remoteSystem->staticData.GetNumberOfBytesUsed() ); - Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, playerToSendToId, true ); + //Send( &bitStream, SYSTEM_PRIORITY, RELIABLE, 0, playerToSendToId, true ); } unsigned int RakServer::GetNumberOfAddresses( void ) @@ -524,9 +398,9 @@ PlayerID RakServer::GetPlayerIDFromIndex( int index ) return RakPeer::GetPlayerIDFromIndex( index ); } -void RakServer::AddToBanList( const char *IP ) +void RakServer::AddToBanList( const char *IP, RakNetTime milliseconds ) { - RakPeer::AddToBanList( IP ); + RakPeer::AddToBanList( IP, milliseconds ); } void RakServer::RemoveFromBanList( const char *IP ) diff --git a/raknet/RakServer.h b/raknet/RakServer.h index 852ec01..f480276 100644 --- a/raknet/RakServer.h +++ b/raknet/RakServer.h @@ -251,6 +251,10 @@ public: /// \return True on a successful packet send (this does not indicate the recipient performed the call), false on failure bool RPC( char* uniqueID, RakNet::BitStream *bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, PlayerID playerId, bool broadcast, bool shiftTimestamp, NetworkID networkID, RakNet::BitStream *replyFromTarget ); + // SAMPSRV (adding this just as a tag for next RakNet upgrade) + bool RPC( char* uniqueID, RakNet::BitStream *bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, PlayerID playerId, bool broadcast, bool shiftTimestamp); + // SAMPSRV end + /// Enables or disables frequency table tracking. This is required to get a frequency table, which is used in GenerateCompressionLayer() /// This value persists between connect calls and defaults to false (no frequency tracking) /// \pre You can call this at any time - however you SHOULD only call it when disconnected. Otherwise you will only trackpart of the values sent over the network. @@ -377,7 +381,7 @@ public: /// Bans an IP from connecting. Banned IPs persist between connections. /// param[in] IP Dotted IP address. Can use * as a wildcard, such as 128.0.0.* will banAll IP addresses starting with 128.0.0 - void AddToBanList( const char *IP ); + void AddToBanList( const char *IP, RakNetTime milliseconds=0 ); /// Allows a previously banned IP to connect. /// param[in] Dotted IP address. Can use * as a wildcard, such as 128.0.0.* will banAll IP addresses starting with 128.0.0 diff --git a/raknet/RakServerInterface.h b/raknet/RakServerInterface.h index 30c2946..3742a6f 100644 --- a/raknet/RakServerInterface.h +++ b/raknet/RakServerInterface.h @@ -247,6 +247,10 @@ public: /// \return True on a successful packet send (this does not indicate the recipient performed the call), false on failure virtual bool RPC( char* uniqueID, RakNet::BitStream *bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, PlayerID playerId, bool broadcast, bool shiftTimestamp, NetworkID networkID, RakNet::BitStream *replyFromTarget )=0; + // SAMPSRV (adding this just as a tag for next RakNet upgrade) + virtual bool RPC( char* uniqueID, RakNet::BitStream *bitStream, PacketPriority priority, PacketReliability reliability, char orderingChannel, PlayerID playerId, bool broadcast, bool shiftTimestamp)=0; + // SAMPSRV end + /// Enables or disables frequency table tracking. This is required to get a frequency table, which is used in GenerateCompressionLayer() /// This value persists between connect calls and defaults to false (no frequency tracking) /// \pre You can call this at any time - however you SHOULD only call it when disconnected. Otherwise you will only trackpart of the values sent over the network. @@ -373,7 +377,7 @@ public: /// Bans an IP from connecting. Banned IPs persist between connections. /// param[in] IP Dotted IP address. Can use * as a wildcard, such as 128.0.0.* will banAll IP addresses starting with 128.0.0 - virtual void AddToBanList( const char *IP )=0; + virtual void AddToBanList( const char *IP, RakNetTime milliseconds=0 )=0; /// Allows a previously banned IP to connect. /// param[in] Dotted IP address. Can use * as a wildcard, such as 128.0.0.* will banAll IP addresses starting with 128.0.0 diff --git a/raknet/ReliabilityLayer.cpp b/raknet/ReliabilityLayer.cpp index 25f152a..8652d8c 100644 --- a/raknet/ReliabilityLayer.cpp +++ b/raknet/ReliabilityLayer.cpp @@ -32,10 +32,18 @@ #include #endif +#ifdef SAMPSRV +int GetPlayerTimeout(); +#endif + static const int DEFAULT_HAS_RECEIVED_PACKET_QUEUE_SIZE=512; static const float PACKETLOSS_TOLERANCE=.02f; // What percentile packetloss we are willing to accept as background noise. static const double MINIMUM_SEND_BPS=14400.0; // Won't go below this send rate +#ifdef SAMPCLI +static const double STARTING_SEND_BPS=512000.0; // What send rate to start at. +#else static const double STARTING_SEND_BPS=28800.0; // What send rate to start at. +#endif static const float PING_MULTIPLIER_TO_RESEND=3.0; // So internet ping variation doesn't cause needless resends static const RakNetTime MIN_PING_TO_RESEND=30; // So system timer changes and CPU lag don't send needless resends static const RakNetTimeNS TIME_TO_NEW_SAMPLE=500000; // How many ns to wait before starting a new sample. This way buffers have time to overflow or relax at the new send rate, if they are indeed going to overflow. @@ -84,9 +92,13 @@ ReliabilityLayer::ReliabilityLayer() : updateBitStream( DEFAULT_MTU_SIZE ) // #ifdef _DEBUG // Wait longer to disconnect in debug so I don't get disconnected while tracing timeoutTime=30000; +#else +#ifdef SAMPSRV + timeoutTime=GetPlayerTimeout(); #else timeoutTime=10000; #endif +#endif #ifndef _RELEASE maxSendBPS=minExtraPing=extraPingVariance=0; @@ -183,6 +195,13 @@ void ReliabilityLayer::InitializeVariables( void ) memset( waitingForSequencedPacketWriteIndex, 0, NUMBER_OF_ORDERED_STREAMS * sizeof(OrderingIndexType) ); memset( &statistics, 0, sizeof( statistics ) ); statistics.connectionStartTime = RakNet::GetTime(); + statistics.field_110 = RakNet::GetTime(); + statistics.field_114 = 0; + statistics.field_118 = 0; + statistics.field_11C = RakNet::GetTime(); + statistics.field_120 = 0; + statistics.field_124 = 0; + reliabilitySizeInBits = 4; splitPacketId = 0; messageNumber = 0; availableBandwidth=0; @@ -1610,7 +1629,8 @@ int ReliabilityLayer::GetBitStreamHeaderLength( const InternalPacket *const inte // Write the PacketReliability. This is encoded in 3 bits //bitStream->WriteBits((unsigned char*)&(internalPacket->reliability), 3, true); - bitLength += 3; + //bitLength += 3; + bitLength += reliabilitySizeInBits; // If the reliability requires an ordering channel and ordering index, we Write those. if ( internalPacket->reliability == UNRELIABLE_SEQUENCED || internalPacket->reliability == RELIABLE_SEQUENCED || internalPacket->reliability == RELIABLE_ORDERED ) @@ -1684,7 +1704,7 @@ int ReliabilityLayer::WriteToBitStreamFromInternalPacket( RakNet::BitStream *bit #endif // Write the PacketReliability. This is encoded in 3 bits - bitStream->WriteBits( (const unsigned char *)&c, 3, true ); + bitStream->WriteBits( (const unsigned char *)&c, reliabilitySizeInBits, true ); // If the reliability requires an ordering channel and ordering index, we Write those. if ( internalPacket->reliability == UNRELIABLE_SEQUENCED || internalPacket->reliability == RELIABLE_SEQUENCED || internalPacket->reliability == RELIABLE_ORDERED ) @@ -1776,7 +1796,7 @@ InternalPacket* ReliabilityLayer::CreateInternalPacketFromBitStream( RakNet::Bit // Read the PacketReliability. This is encoded in 3 bits unsigned char reliability; - bitStreamSucceeded = bitStream->ReadBits( ( unsigned char* ) ( &( reliability ) ), 3 ); + bitStreamSucceeded = bitStream->ReadBits( ( unsigned char* ) ( &( reliability ) ), reliabilitySizeInBits ); internalPacket->reliability = ( const PacketReliability ) reliability; @@ -1785,7 +1805,7 @@ InternalPacket* ReliabilityLayer::CreateInternalPacketFromBitStream( RakNet::Bit // assert( bitStreamSucceeded ); #endif - if ( bitStreamSucceeded == false ) + if ( internalPacket->reliability < UNRELIABLE || bitStreamSucceeded == false ) { internalPacketPool.ReleasePointer( internalPacket ); return 0; @@ -2464,7 +2484,7 @@ void ReliabilityLayer::UpdateNextActionTime(void) //------------------------------------------------------------------------------------------------------- // Statistics //------------------------------------------------------------------------------------------------------- -RakNetStatisticsStruct * const ReliabilityLayer::GetStatistics( void ) +RakNetStatisticsStruct * const ReliabilityLayer::GetStatistics( bool includeResendListDataSize ) { unsigned i; @@ -2482,7 +2502,11 @@ RakNetStatisticsStruct * const ReliabilityLayer::GetStatistics( void ) statistics.bitsPerSecond = currentBandwidth; //statistics.lossySize = lossyWindowSize == MAXIMUM_WINDOW_SIZE + 1 ? 0 : lossyWindowSize; // statistics.lossySize=0; - statistics.messagesOnResendQueue = GetResendListDataSize(); + if (!includeResendListDataSize) + statistics.messagesOnResendQueue = GetResendListDataSize(); + else + statistics.messagesOnResendQueue = 0; + return &statistics; } diff --git a/raknet/ReliabilityLayer.h b/raknet/ReliabilityLayer.h index fa53c9c..d4213e8 100644 --- a/raknet/ReliabilityLayer.h +++ b/raknet/ReliabilityLayer.h @@ -151,7 +151,7 @@ public: /// Get Statistics /// \return A pointer to a static struct, filled out with current statistical information. - RakNetStatisticsStruct * const GetStatistics( void ); + RakNetStatisticsStruct * const GetStatistics( bool includeResendListDataSize = true ); ///Are we waiting for any data to be sent out or be processed by the player? bool IsDataWaiting(void); @@ -315,6 +315,8 @@ private: unsigned int blockWindowIncreaseUntilTime; RakNetStatisticsStruct statistics; + unsigned int reliabilitySizeInBits; + /// Memory-efficient receivedPackets algorithm: /// receivedPacketsBaseIndex is the packet number we are expecting /// Everything under receivedPacketsBaseIndex is a packet we already got diff --git a/raknet/SocketDataEncryptor.cpp b/raknet/SocketDataEncryptor.cpp new file mode 100644 index 0000000..1f8d42d --- /dev/null +++ b/raknet/SocketDataEncryptor.cpp @@ -0,0 +1,130 @@ + +#include +#include "SocketDataEncryptor.h" + +unsigned short SocketDataEncryptor::session_key = 0; + +static const unsigned char S[256] = { +#ifndef SAMPSRV + 0x27,0x69,0xFD,0x87,0x60,0x7D,0x83,0x02,0xF2,0x3F,0x71,0x99,0xA3,0x7C,0x1B,0x9D, + 0x76,0x30,0x23,0x25,0xC5,0x82,0x9B,0xEB,0x1E,0xFA,0x46,0x4F,0x98,0xC9,0x37,0x88, + 0x18,0xA2,0x68,0xD6,0xD7,0x22,0xD1,0x74,0x7A,0x79,0x2E,0xD2,0x6D,0x48,0x0F,0xB1, + 0x62,0x97,0xBC,0x8B,0x59,0x7F,0x29,0xB6,0xB9,0x61,0xBE,0xC8,0xC1,0xC6,0x40,0xEF, + 0x11,0x6A,0xA5,0xC7,0x3A,0xF4,0x4C,0x13,0x6C,0x2B,0x1C,0x54,0x56,0x55,0x53,0xA8, + 0xDC,0x9C,0x9A,0x16,0xDD,0xB0,0xF5,0x2D,0xFF,0xDE,0x8A,0x90,0xFC,0x95,0xEC,0x31, + 0x85,0xC2,0x01,0x06,0xDB,0x28,0xD8,0xEA,0xA0,0xDA,0x10,0x0E,0xF0,0x2A,0x6B,0x21, + 0xF1,0x86,0xFB,0x65,0xE1,0x6F,0xF6,0x26,0x33,0x39,0xAE,0xBF,0xD4,0xE4,0xE9,0x44, + 0x75,0x3D,0x63,0xBD,0xC0,0x7B,0x9E,0xA6,0x5C,0x1F,0xB2,0xA4,0xC4,0x8D,0xB3,0xFE, + 0x8F,0x19,0x8C,0x4D,0x5E,0x34,0xCC,0xF9,0xB5,0xF3,0xF8,0xA1,0x50,0x04,0x93,0x73, + 0xE0,0xBA,0xCB,0x45,0x35,0x1A,0x49,0x47,0x6E,0x2F,0x51,0x12,0xE2,0x4A,0x72,0x05, + 0x66,0x70,0xB8,0xCD,0x00,0xE5,0xBB,0x24,0x58,0xEE,0xB4,0x80,0x81,0x36,0xA9,0x67, + 0x5A,0x4B,0xE8,0xCA,0xCF,0x9F,0xE3,0xAC,0xAA,0x14,0x5B,0x5F,0x0A,0x3B,0x77,0x92, + 0x09,0x15,0x4E,0x94,0xAD,0x17,0x64,0x52,0xD3,0x38,0x43,0x0D,0x0C,0x07,0x3C,0x1D, + 0xAF,0xED,0xE7,0x08,0xB7,0x03,0xE6,0x8E,0xAB,0x91,0x89,0x3E,0x2C,0x96,0x42,0xD9, + 0x78,0xDF,0xD0,0x57,0x5D,0x84,0x41,0x7E,0xCE,0xF7,0x32,0xC3,0xD5,0x20,0x0B,0xA7, +#else + 0xB4,0x62,0x07,0xE5,0x9D,0xAF,0x63,0xDD,0xE3,0xD0,0xCC,0xFE,0xDC,0xDB,0x6B,0x2E, + 0x6A,0x40,0xAB,0x47,0xC9,0xD1,0x53,0xD5,0x20,0x91,0xA5,0x0E,0x4A,0xDF,0x18,0x89, + 0xFD,0x6F,0x25,0x12,0xB7,0x13,0x77,0x00,0x65,0x36,0x6D,0x49,0xEC,0x57,0x2A,0xA9, + 0x11,0x5F,0xFA,0x78,0x95,0xA4,0xBD,0x1E,0xD9,0x79,0x44,0xCD,0xDE,0x81,0xEB,0x09, + 0x3E,0xF6,0xEE,0xDA,0x7F,0xA3,0x1A,0xA7,0x2D,0xA6,0xAD,0xC1,0x46,0x93,0xD2,0x1B, + 0x9C,0xAA,0xD7,0x4E,0x4B,0x4D,0x4C,0xF3,0xB8,0x34,0xC0,0xCA,0x88,0xF4,0x94,0xCB, + 0x04,0x39,0x30,0x82,0xD6,0x73,0xB0,0xBF,0x22,0x01,0x41,0x6E,0x48,0x2C,0xA8,0x75, + 0xB1,0x0A,0xAE,0x9F,0x27,0x80,0x10,0xCE,0xF0,0x29,0x28,0x85,0x0D,0x05,0xF7,0x35, + 0xBB,0xBC,0x15,0x06,0xF5,0x60,0x71,0x03,0x1F,0xEA,0x5A,0x33,0x92,0x8D,0xE7,0x90, + 0x5B,0xE9,0xCF,0x9E,0xD3,0x5D,0xED,0x31,0x1C,0x0B,0x52,0x16,0x51,0x0F,0x86,0xC5, + 0x68,0x9B,0x21,0x0C,0x8B,0x42,0x87,0xFF,0x4F,0xBE,0xC8,0xE8,0xC7,0xD4,0x7A,0xE0, + 0x55,0x2F,0x8A,0x8E,0xBA,0x98,0x37,0xE4,0xB2,0x38,0xA1,0xB6,0x32,0x83,0x3A,0x7B, + 0x84,0x3C,0x61,0xFB,0x8C,0x14,0x3D,0x43,0x3B,0x1D,0xC3,0xA2,0x96,0xB3,0xF8,0xC4, + 0xF2,0x26,0x2B,0xD8,0x7C,0xFC,0x23,0x24,0x66,0xEF,0x69,0x64,0x50,0x54,0x59,0xF1, + 0xA0,0x74,0xAC,0xC6,0x7D,0xB5,0xE6,0xE2,0xC2,0x7E,0x67,0x17,0x5E,0xE1,0xB9,0x3F, + 0x6C,0x70,0x08,0x99,0x45,0x56,0x76,0xF9,0x9A,0x97,0x19,0x72,0x5C,0x02,0x8F,0x58, +#endif +}; + +//---------------------------------------------------- + +unsigned char SocketDataEncryptor::GetChecksum(unsigned char *data, int length) +{ + unsigned char sum = 0; + + for(int i = 0; i != length; i++) + { + sum ^= data[i] & 0xAA; + } + return sum; +} + +//---------------------------------------------------- + +void SocketDataEncryptor::Process(unsigned char key1, + unsigned char key2, + unsigned char *data, + int length) +{ + int counter = 0; + + for(int i = 0; i != length; i++) + { +#ifndef SAMPSRV + data[i] = S[data[i]]; +#endif + if(counter == 0) + { + data[i] ^= key1; + counter = 1; + } + else + { + data[i] ^= key2; + counter--; + } +#ifdef SAMPSRV + data[i] = S[data[i]]; +#endif + } +} + +//---------------------------------------------------- + +#ifndef SAMPSRV + +void SocketDataEncryptor::Encrypt(unsigned char *destination, + unsigned char *source, + int *length) +{ + unsigned char key = session_key; + + *destination = GetChecksum(source, *length); + memcpy(destination + 1, source, *length); + Process(0, key, destination + 1, *length); + ++*length; +} + +#else + +int SocketDataEncryptor::Decrypt(unsigned char *destination, + unsigned char *source, + int *length) +{ + unsigned char key = session_key; + unsigned char sum = source[0]; + + *length--; + memcpy(destination, source + 1, *length); + Process(0, key, destination, *length); + + return GetChecksum(destination, *length) == sum; +} + +#endif + +//---------------------------------------------------- + +void SocketDataEncryptor::SetKey(int key) +{ + session_key = key ^ 0xCCCC; +} + +//---------------------------------------------------- +// EOF diff --git a/raknet/SocketDataEncryptor.h b/raknet/SocketDataEncryptor.h new file mode 100644 index 0000000..499996b --- /dev/null +++ b/raknet/SocketDataEncryptor.h @@ -0,0 +1,21 @@ + +#ifndef __SOCKET_DATA_ENCRYPTOR_H +#define __SOCKET_DATA_ENCRYPTOR_H + +class SocketDataEncryptor +{ +private: + static unsigned char GetChecksum(unsigned char *data, int length); + static void Process(unsigned char key1, unsigned char key2, unsigned char *data, int length); + + static unsigned short session_key; + +public: + static void Encrypt(unsigned char *destination, unsigned char *source, int *length); + static int Decrypt(unsigned char *destination, unsigned char *source, int *length); + + static void SetKey(int key); + +}; + +#endif diff --git a/raknet/SocketLayer.cpp b/raknet/SocketLayer.cpp index a215ac4..b314194 100644 --- a/raknet/SocketLayer.cpp +++ b/raknet/SocketLayer.cpp @@ -25,6 +25,8 @@ #include #include "MTUSize.h" +#include "SocketDataEncryptor.h" + #ifdef _WIN32 #include #define COMPATIBILITY_2_RECV_FROM_FLAGS 0 @@ -48,6 +50,9 @@ typedef int socklen_t; #pragma warning( push ) #endif +unsigned char pDataBuffer[16384]; +unsigned char pDataBuffer2[16384]; // unused + bool SocketLayer::socketLayerStarted = false; #ifdef _WIN32 WSADATA SocketLayer::winsockInfo; @@ -370,6 +375,10 @@ bool SocketLayer::AssociateSocketWithCompletionPortAndRead( SOCKET readSocket, u return true; } +#ifdef SAMPSRV + int ProcessQueryPacket(unsigned int binaryAddress, unsigned short port, char *data, int length, SOCKET s); +#endif + int SocketLayer::RecvFrom( const SOCKET s, RakPeer *rakPeer, int *errorCode ) { int len; @@ -396,6 +405,7 @@ int SocketLayer::RecvFrom( const SOCKET s, RakPeer *rakPeer, int *errorCode ) // if (len>0) // printf("Got packet on port %i\n",ntohs(sa.sin_port)); + /* if ( len == 0 ) { #ifdef _DEBUG @@ -405,7 +415,7 @@ int SocketLayer::RecvFrom( const SOCKET s, RakPeer *rakPeer, int *errorCode ) *errorCode = SOCKET_ERROR; return SOCKET_ERROR; - } + }*/ if ( len != SOCKET_ERROR ) { @@ -414,8 +424,30 @@ int SocketLayer::RecvFrom( const SOCKET s, RakPeer *rakPeer, int *errorCode ) //strcpy(ip, inet_ntoa(sa.sin_addr)); //if (strcmp(ip, "0.0.0.0")==0) // strcpy(ip, "127.0.0.1"); - ProcessNetworkPacket( sa.sin_addr.s_addr, portnum, data, len, rakPeer ); + if (len > 0) + { + +#ifdef SAMPSRV + // QUERY PACKETS ARE NOT COMPRESSED + //logprintf("Raw ID: %c:%u",data[0],data[0]); + + if(ProcessQueryPacket(sa.sin_addr.s_addr, portnum,(char*)data, len, s)) { + return 1; + } + + if(!SocketDataEncryptor::Decrypt(pDataBuffer,(unsigned char *)data, &len) ) + { + *errorCode = 0; + return 1; + } + + ProcessNetworkPacket( sa.sin_addr.s_addr, portnum, (char*)pDataBuffer, len, rakPeer ); +#else + ProcessNetworkPacket( sa.sin_addr.s_addr, portnum, data, len, rakPeer ); +#endif + + } return 1; } else @@ -481,10 +513,19 @@ int SocketLayer::SendTo( SOCKET s, const char *data, int length, unsigned int bi sa.sin_addr.s_addr = binaryAddress; sa.sin_family = AF_INET; +#ifndef SAMPSRV + + SocketDataEncryptor::Encrypt(pDataBuffer, (unsigned char *)data, &length); + +#endif + do { - // TODO - use WSASendTo which is faster. +#ifndef SAMPSRV + len = sendto( s, (char *)pDataBuffer, length, 0, ( const sockaddr* ) & sa, sizeof( struct sockaddr_in ) ); +#else len = sendto( s, data, length, 0, ( const sockaddr* ) & sa, sizeof( struct sockaddr_in ) ); +#endif } while ( len == 0 ); diff --git a/saco/audiostream.cpp b/saco/audiostream.cpp index b14956f..55128c3 100644 --- a/saco/audiostream.cpp +++ b/saco/audiostream.cpp @@ -1,42 +1,117 @@ -#include "audiostream.h" +#include "main.h" -void CAudioStream::Reset() +extern CGame *pGame; + +VECTOR g_vecStreamingPos; + +//---------------------------------------------------- + +BOOL CAudioStream::Initialize() { - // TODO: CAudioStream::sub_10066480 10066480 + // TODO: CAudioStream::Initialize() + return FALSE; } -void CAudioStream::Stop() +//---------------------------------------------------- + +BOOL CAudioStream::Stop(bool bWaitForThread) { - // TODO: CAudioStream::sub_10066560 10066560 + // TODO: CAudioStream::Stop() + return FALSE; } -void CAudioStream::ConstructInfo() +//---------------------------------------------------- + +void CAudioStream::DoMeta() { - // TODO: CAudioStream::sub_100665C0 100665C0 + // TODO: CAudioStream::DoMeta } -void CAudioStream::SyncProc() +//---------------------------------------------------- + +void CALLBACK CAudioStream::MetaSync(HSYNC handle, DWORD channel, DWORD data, void *user) { - // TODO: CAudioStream::sub_100666F0 100666F0 + DoMeta(); } -void CAudioStream::Process() +//---------------------------------------------------- + +void CAudioStream::ProcessThread(PVOID v) { - // TODO: CAudioStream::sub_10066700 10066700 + // TODO: CAudioStream::ProcessThread } -void CAudioStream::Play() +//---------------------------------------------------- + +BOOL CAudioStream::Play(char *szURL, float fX, float fY, float fZ, float fDistance, bool bUsePos) { - // TODO: CAudioStream::sub_10066960 10066960 + // TODO: CAudioStream::Play + return FALSE; } -void CAudioStream::ControlGameRadio() +//---------------------------------------------------- + +void CAudioStream::HandleGameAudio() { - // TODO: CAudioStream::sub_10066A80 10066A80 + // TODO: CAudioStream::HandleGameAudio() } -void CAudioStream::DrawInfo() +//---------------------------------------------------- + +void CAudioStream::Draw() { - // TODO: CAudioStream::sub_10066AB0 10066AB0 -} \ No newline at end of file + // TODO: CAudioStream::Draw() +} + +//---------------------------------------------------- + +void FUNC_10066B90(PVECTOR in, PVECTOR out) +{ + out->X = -in->X; + out->Y = in->Z; + out->Z = in->Y; +} + +void FUNC_10066BB0(PVECTOR in, PVECTOR out) +{ + out->X = in->X; + out->Y = -in->Z; + out->Z = -in->Y; +} + +void CAudioStream::Test3D() +{ + CPlayerPed* pPlayerPed = pGame->FindPlayerPed(); + if(!pPlayerPed) return; + + CAMERA_AIM *Aim = pPlayerPed->GetCurrentAim(); + VECTOR vecResult; + VECTOR vecFront; + VECTOR vecPos; + BASS_3DVECTOR front; + BASS_3DVECTOR vel; + + vecFront.X = Aim->f1x; + vecFront.Y = Aim->f1y;; + vecFront.Z = Aim->f1z; + vecPos.X = Aim->pos1x; + vecPos.Y = Aim->pos1y; + vecPos.Z = Aim->pos1z; + + FUNC_10066BB0(&vecFront, &vecResult); + + front.x = vecResult.X; + front.y = vecResult.Y; + front.z = vecResult.Z; + + FUNC_10066B90(&vecPos, &vecResult); + + vecFront.X = vecResult.X; + vecFront.Y = vecResult.Y; + vecFront.Z = vecResult.Z; + + FUNC_10066B90(&g_vecStreamingPos, &vecResult); +} + +//---------------------------------------------------- diff --git a/saco/audiostream.h b/saco/audiostream.h index 48e54f0..b26dccd 100644 --- a/saco/audiostream.h +++ b/saco/audiostream.h @@ -1,23 +1,34 @@ #pragma once -class CAudioStream // size=1 +#include "bass.h" + +//---------------------------------------------------- + +class CAudioStream { private: - char field_0; + bool field_0; public: - CAudioStream() { field_0 = 0; } - void Reset(); - void Stop(); - void ConstructInfo(); - void SyncProc(); - void Process(); - void Play(); - void ControlGameRadio(); - void DrawInfo(); + BOOL Initialize(); + BOOL Stop(bool bWaitForThread=true); + BOOL Play(char *szURL, float fX, float fY, float fZ, float fDistance, bool bUsePos); + void HandleGameAudio(); + void Draw(); + + void Test3D(); + + static void DoMeta(); + static void CALLBACK MetaSync(HSYNC handle, DWORD channel, DWORD data, void *user); + static void ProcessThread(PVOID v); + + // Delete this: + void Process() {} }; + +//---------------------------------------------------- diff --git a/saco/bass.h b/saco/bass.h new file mode 100644 index 0000000..1aa9780 --- /dev/null +++ b/saco/bass.h @@ -0,0 +1,963 @@ +/* + BASS 2.4 C/C++ header file + Copyright (c) 1999-2013 Un4seen Developments Ltd. + + See the BASS.CHM file for more detailed documentation +*/ + +#ifndef BASS_H +#define BASS_H + +#ifdef _WIN32 +#include +typedef unsigned __int64 QWORD; +#else +#include +#define WINAPI +#define CALLBACK +typedef uint8_t BYTE; +typedef uint16_t WORD; +typedef uint32_t DWORD; +typedef uint64_t QWORD; +#ifndef __OBJC__ +typedef int BOOL; +#endif +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif +#define LOBYTE(a) (BYTE)(a) +#define HIBYTE(a) (BYTE)((a)>>8) +#define LOWORD(a) (WORD)(a) +#define HIWORD(a) (WORD)((a)>>16) +#define MAKEWORD(a,b) (WORD)(((a)&0xff)|((b)<<8)) +#define MAKELONG(a,b) (DWORD)(((a)&0xffff)|((b)<<16)) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define BASSVERSION 0x204 // API version +#define BASSVERSIONTEXT "2.4" + +#ifndef BASSDEF +#define BASSDEF(f) WINAPI f +#endif + +typedef DWORD HMUSIC; // MOD music handle +typedef DWORD HSAMPLE; // sample handle +typedef DWORD HCHANNEL; // playing sample's channel handle +typedef DWORD HSTREAM; // sample stream handle +typedef DWORD HRECORD; // recording handle +typedef DWORD HSYNC; // synchronizer handle +typedef DWORD HDSP; // DSP handle +typedef DWORD HFX; // DX8 effect handle +typedef DWORD HPLUGIN; // Plugin handle + +// Error codes returned by BASS_ErrorGetCode +#define BASS_OK 0 // all is OK +#define BASS_ERROR_MEM 1 // memory error +#define BASS_ERROR_FILEOPEN 2 // can't open the file +#define BASS_ERROR_DRIVER 3 // can't find a free/valid driver +#define BASS_ERROR_BUFLOST 4 // the sample buffer was lost +#define BASS_ERROR_HANDLE 5 // invalid handle +#define BASS_ERROR_FORMAT 6 // unsupported sample format +#define BASS_ERROR_POSITION 7 // invalid position +#define BASS_ERROR_INIT 8 // BASS_Init has not been successfully called +#define BASS_ERROR_START 9 // BASS_Start has not been successfully called +#define BASS_ERROR_ALREADY 14 // already initialized/paused/whatever +#define BASS_ERROR_NOCHAN 18 // can't get a free channel +#define BASS_ERROR_ILLTYPE 19 // an illegal type was specified +#define BASS_ERROR_ILLPARAM 20 // an illegal parameter was specified +#define BASS_ERROR_NO3D 21 // no 3D support +#define BASS_ERROR_NOEAX 22 // no EAX support +#define BASS_ERROR_DEVICE 23 // illegal device number +#define BASS_ERROR_NOPLAY 24 // not playing +#define BASS_ERROR_FREQ 25 // illegal sample rate +#define BASS_ERROR_NOTFILE 27 // the stream is not a file stream +#define BASS_ERROR_NOHW 29 // no hardware voices available +#define BASS_ERROR_EMPTY 31 // the MOD music has no sequence data +#define BASS_ERROR_NONET 32 // no internet connection could be opened +#define BASS_ERROR_CREATE 33 // couldn't create the file +#define BASS_ERROR_NOFX 34 // effects are not available +#define BASS_ERROR_NOTAVAIL 37 // requested data is not available +#define BASS_ERROR_DECODE 38 // the channel is a "decoding channel" +#define BASS_ERROR_DX 39 // a sufficient DirectX version is not installed +#define BASS_ERROR_TIMEOUT 40 // connection timedout +#define BASS_ERROR_FILEFORM 41 // unsupported file format +#define BASS_ERROR_SPEAKER 42 // unavailable speaker +#define BASS_ERROR_VERSION 43 // invalid BASS version (used by add-ons) +#define BASS_ERROR_CODEC 44 // codec is not available/supported +#define BASS_ERROR_ENDED 45 // the channel/file has ended +#define BASS_ERROR_BUSY 46 // the device is busy +#define BASS_ERROR_UNKNOWN -1 // some other mystery problem + +// BASS_SetConfig options +#define BASS_CONFIG_BUFFER 0 +#define BASS_CONFIG_UPDATEPERIOD 1 +#define BASS_CONFIG_GVOL_SAMPLE 4 +#define BASS_CONFIG_GVOL_STREAM 5 +#define BASS_CONFIG_GVOL_MUSIC 6 +#define BASS_CONFIG_CURVE_VOL 7 +#define BASS_CONFIG_CURVE_PAN 8 +#define BASS_CONFIG_FLOATDSP 9 +#define BASS_CONFIG_3DALGORITHM 10 +#define BASS_CONFIG_NET_TIMEOUT 11 +#define BASS_CONFIG_NET_BUFFER 12 +#define BASS_CONFIG_PAUSE_NOPLAY 13 +#define BASS_CONFIG_NET_PREBUF 15 +#define BASS_CONFIG_NET_PASSIVE 18 +#define BASS_CONFIG_REC_BUFFER 19 +#define BASS_CONFIG_NET_PLAYLIST 21 +#define BASS_CONFIG_MUSIC_VIRTUAL 22 +#define BASS_CONFIG_VERIFY 23 +#define BASS_CONFIG_UPDATETHREADS 24 +#define BASS_CONFIG_DEV_BUFFER 27 +#define BASS_CONFIG_VISTA_TRUEPOS 30 +#define BASS_CONFIG_IOS_MIXAUDIO 34 +#define BASS_CONFIG_DEV_DEFAULT 36 +#define BASS_CONFIG_NET_READTIMEOUT 37 +#define BASS_CONFIG_VISTA_SPEAKERS 38 +#define BASS_CONFIG_IOS_SPEAKER 39 +#define BASS_CONFIG_HANDLES 41 +#define BASS_CONFIG_UNICODE 42 +#define BASS_CONFIG_SRC 43 +#define BASS_CONFIG_SRC_SAMPLE 44 +#define BASS_CONFIG_ASYNCFILE_BUFFER 45 +#define BASS_CONFIG_OGG_PRESCAN 47 + +// BASS_SetConfigPtr options +#define BASS_CONFIG_NET_AGENT 16 +#define BASS_CONFIG_NET_PROXY 17 +#define BASS_CONFIG_IOS_NOTIFY 46 + +// BASS_Init flags +#define BASS_DEVICE_8BITS 1 // 8 bit resolution, else 16 bit +#define BASS_DEVICE_MONO 2 // mono, else stereo +#define BASS_DEVICE_3D 4 // enable 3D functionality +#define BASS_DEVICE_LATENCY 0x100 // calculate device latency (BASS_INFO struct) +#define BASS_DEVICE_CPSPEAKERS 0x400 // detect speakers via Windows control panel +#define BASS_DEVICE_SPEAKERS 0x800 // force enabling of speaker assignment +#define BASS_DEVICE_NOSPEAKER 0x1000 // ignore speaker arrangement +#define BASS_DEVICE_DMIX 0x2000 // use ALSA "dmix" plugin +#define BASS_DEVICE_FREQ 0x4000 // set device sample rate + +// DirectSound interfaces (for use with BASS_GetDSoundObject) +#define BASS_OBJECT_DS 1 // IDirectSound +#define BASS_OBJECT_DS3DL 2 // IDirectSound3DListener + +// Device info structure +typedef struct { +#ifdef _WIN32_WCE + const wchar_t *name; // description + const wchar_t *driver; // driver +#else + const char *name; // description + const char *driver; // driver +#endif + DWORD flags; +} BASS_DEVICEINFO; + +// BASS_DEVICEINFO flags +#define BASS_DEVICE_ENABLED 1 +#define BASS_DEVICE_DEFAULT 2 +#define BASS_DEVICE_INIT 4 + +typedef struct { + DWORD flags; // device capabilities (DSCAPS_xxx flags) + DWORD hwsize; // size of total device hardware memory + DWORD hwfree; // size of free device hardware memory + DWORD freesam; // number of free sample slots in the hardware + DWORD free3d; // number of free 3D sample slots in the hardware + DWORD minrate; // min sample rate supported by the hardware + DWORD maxrate; // max sample rate supported by the hardware + BOOL eax; // device supports EAX? (always FALSE if BASS_DEVICE_3D was not used) + DWORD minbuf; // recommended minimum buffer length in ms (requires BASS_DEVICE_LATENCY) + DWORD dsver; // DirectSound version + DWORD latency; // delay (in ms) before start of playback (requires BASS_DEVICE_LATENCY) + DWORD initflags; // BASS_Init "flags" parameter + DWORD speakers; // number of speakers available + DWORD freq; // current output rate +} BASS_INFO; + +// BASS_INFO flags (from DSOUND.H) +#define DSCAPS_CONTINUOUSRATE 0x00000010 // supports all sample rates between min/maxrate +#define DSCAPS_EMULDRIVER 0x00000020 // device does NOT have hardware DirectSound support +#define DSCAPS_CERTIFIED 0x00000040 // device driver has been certified by Microsoft +#define DSCAPS_SECONDARYMONO 0x00000100 // mono +#define DSCAPS_SECONDARYSTEREO 0x00000200 // stereo +#define DSCAPS_SECONDARY8BIT 0x00000400 // 8 bit +#define DSCAPS_SECONDARY16BIT 0x00000800 // 16 bit + +// Recording device info structure +typedef struct { + DWORD flags; // device capabilities (DSCCAPS_xxx flags) + DWORD formats; // supported standard formats (WAVE_FORMAT_xxx flags) + DWORD inputs; // number of inputs + BOOL singlein; // TRUE = only 1 input can be set at a time + DWORD freq; // current input rate +} BASS_RECORDINFO; + +// BASS_RECORDINFO flags (from DSOUND.H) +#define DSCCAPS_EMULDRIVER DSCAPS_EMULDRIVER // device does NOT have hardware DirectSound recording support +#define DSCCAPS_CERTIFIED DSCAPS_CERTIFIED // device driver has been certified by Microsoft + +// defines for formats field of BASS_RECORDINFO (from MMSYSTEM.H) +#ifndef WAVE_FORMAT_1M08 +#define WAVE_FORMAT_1M08 0x00000001 /* 11.025 kHz, Mono, 8-bit */ +#define WAVE_FORMAT_1S08 0x00000002 /* 11.025 kHz, Stereo, 8-bit */ +#define WAVE_FORMAT_1M16 0x00000004 /* 11.025 kHz, Mono, 16-bit */ +#define WAVE_FORMAT_1S16 0x00000008 /* 11.025 kHz, Stereo, 16-bit */ +#define WAVE_FORMAT_2M08 0x00000010 /* 22.05 kHz, Mono, 8-bit */ +#define WAVE_FORMAT_2S08 0x00000020 /* 22.05 kHz, Stereo, 8-bit */ +#define WAVE_FORMAT_2M16 0x00000040 /* 22.05 kHz, Mono, 16-bit */ +#define WAVE_FORMAT_2S16 0x00000080 /* 22.05 kHz, Stereo, 16-bit */ +#define WAVE_FORMAT_4M08 0x00000100 /* 44.1 kHz, Mono, 8-bit */ +#define WAVE_FORMAT_4S08 0x00000200 /* 44.1 kHz, Stereo, 8-bit */ +#define WAVE_FORMAT_4M16 0x00000400 /* 44.1 kHz, Mono, 16-bit */ +#define WAVE_FORMAT_4S16 0x00000800 /* 44.1 kHz, Stereo, 16-bit */ +#endif + +// Sample info structure +typedef struct { + DWORD freq; // default playback rate + float volume; // default volume (0-1) + float pan; // default pan (-1=left, 0=middle, 1=right) + DWORD flags; // BASS_SAMPLE_xxx flags + DWORD length; // length (in bytes) + DWORD max; // maximum simultaneous playbacks + DWORD origres; // original resolution bits + DWORD chans; // number of channels + DWORD mingap; // minimum gap (ms) between creating channels + DWORD mode3d; // BASS_3DMODE_xxx mode + float mindist; // minimum distance + float maxdist; // maximum distance + DWORD iangle; // angle of inside projection cone + DWORD oangle; // angle of outside projection cone + float outvol; // delta-volume outside the projection cone + DWORD vam; // voice allocation/management flags (BASS_VAM_xxx) + DWORD priority; // priority (0=lowest, 0xffffffff=highest) +} BASS_SAMPLE; + +#define BASS_SAMPLE_8BITS 1 // 8 bit +#define BASS_SAMPLE_FLOAT 256 // 32-bit floating-point +#define BASS_SAMPLE_MONO 2 // mono +#define BASS_SAMPLE_LOOP 4 // looped +#define BASS_SAMPLE_3D 8 // 3D functionality +#define BASS_SAMPLE_SOFTWARE 16 // not using hardware mixing +#define BASS_SAMPLE_MUTEMAX 32 // mute at max distance (3D only) +#define BASS_SAMPLE_VAM 64 // DX7 voice allocation & management +#define BASS_SAMPLE_FX 128 // old implementation of DX8 effects +#define BASS_SAMPLE_OVER_VOL 0x10000 // override lowest volume +#define BASS_SAMPLE_OVER_POS 0x20000 // override longest playing +#define BASS_SAMPLE_OVER_DIST 0x30000 // override furthest from listener (3D only) + +#define BASS_STREAM_PRESCAN 0x20000 // enable pin-point seeking/length (MP3/MP2/MP1) +#define BASS_MP3_SETPOS BASS_STREAM_PRESCAN +#define BASS_STREAM_AUTOFREE 0x40000 // automatically free the stream when it stop/ends +#define BASS_STREAM_RESTRATE 0x80000 // restrict the download rate of internet file streams +#define BASS_STREAM_BLOCK 0x100000 // download/play internet file stream in small blocks +#define BASS_STREAM_DECODE 0x200000 // don't play the stream, only decode (BASS_ChannelGetData) +#define BASS_STREAM_STATUS 0x800000 // give server status info (HTTP/ICY tags) in DOWNLOADPROC + +#define BASS_MUSIC_FLOAT BASS_SAMPLE_FLOAT +#define BASS_MUSIC_MONO BASS_SAMPLE_MONO +#define BASS_MUSIC_LOOP BASS_SAMPLE_LOOP +#define BASS_MUSIC_3D BASS_SAMPLE_3D +#define BASS_MUSIC_FX BASS_SAMPLE_FX +#define BASS_MUSIC_AUTOFREE BASS_STREAM_AUTOFREE +#define BASS_MUSIC_DECODE BASS_STREAM_DECODE +#define BASS_MUSIC_PRESCAN BASS_STREAM_PRESCAN // calculate playback length +#define BASS_MUSIC_CALCLEN BASS_MUSIC_PRESCAN +#define BASS_MUSIC_RAMP 0x200 // normal ramping +#define BASS_MUSIC_RAMPS 0x400 // sensitive ramping +#define BASS_MUSIC_SURROUND 0x800 // surround sound +#define BASS_MUSIC_SURROUND2 0x1000 // surround sound (mode 2) +#define BASS_MUSIC_FT2MOD 0x2000 // play .MOD as FastTracker 2 does +#define BASS_MUSIC_PT1MOD 0x4000 // play .MOD as ProTracker 1 does +#define BASS_MUSIC_NONINTER 0x10000 // non-interpolated sample mixing +#define BASS_MUSIC_SINCINTER 0x800000 // sinc interpolated sample mixing +#define BASS_MUSIC_POSRESET 0x8000 // stop all notes when moving position +#define BASS_MUSIC_POSRESETEX 0x400000 // stop all notes and reset bmp/etc when moving position +#define BASS_MUSIC_STOPBACK 0x80000 // stop the music on a backwards jump effect +#define BASS_MUSIC_NOSAMPLE 0x100000 // don't load the samples + +// Speaker assignment flags +#define BASS_SPEAKER_FRONT 0x1000000 // front speakers +#define BASS_SPEAKER_REAR 0x2000000 // rear/side speakers +#define BASS_SPEAKER_CENLFE 0x3000000 // center & LFE speakers (5.1) +#define BASS_SPEAKER_REAR2 0x4000000 // rear center speakers (7.1) +#define BASS_SPEAKER_N(n) ((n)<<24) // n'th pair of speakers (max 15) +#define BASS_SPEAKER_LEFT 0x10000000 // modifier: left +#define BASS_SPEAKER_RIGHT 0x20000000 // modifier: right +#define BASS_SPEAKER_FRONTLEFT BASS_SPEAKER_FRONT|BASS_SPEAKER_LEFT +#define BASS_SPEAKER_FRONTRIGHT BASS_SPEAKER_FRONT|BASS_SPEAKER_RIGHT +#define BASS_SPEAKER_REARLEFT BASS_SPEAKER_REAR|BASS_SPEAKER_LEFT +#define BASS_SPEAKER_REARRIGHT BASS_SPEAKER_REAR|BASS_SPEAKER_RIGHT +#define BASS_SPEAKER_CENTER BASS_SPEAKER_CENLFE|BASS_SPEAKER_LEFT +#define BASS_SPEAKER_LFE BASS_SPEAKER_CENLFE|BASS_SPEAKER_RIGHT +#define BASS_SPEAKER_REAR2LEFT BASS_SPEAKER_REAR2|BASS_SPEAKER_LEFT +#define BASS_SPEAKER_REAR2RIGHT BASS_SPEAKER_REAR2|BASS_SPEAKER_RIGHT + +#define BASS_ASYNCFILE 0x40000000 +#define BASS_UNICODE 0x80000000 + +#define BASS_RECORD_PAUSE 0x8000 // start recording paused + +// DX7 voice allocation & management flags +#define BASS_VAM_HARDWARE 1 +#define BASS_VAM_SOFTWARE 2 +#define BASS_VAM_TERM_TIME 4 +#define BASS_VAM_TERM_DIST 8 +#define BASS_VAM_TERM_PRIO 16 + +// Channel info structure +typedef struct { + DWORD freq; // default playback rate + DWORD chans; // channels + DWORD flags; // BASS_SAMPLE/STREAM/MUSIC/SPEAKER flags + DWORD ctype; // type of channel + DWORD origres; // original resolution + HPLUGIN plugin; // plugin + HSAMPLE sample; // sample + const char *filename; // filename +} BASS_CHANNELINFO; + +// BASS_CHANNELINFO types +#define BASS_CTYPE_SAMPLE 1 +#define BASS_CTYPE_RECORD 2 +#define BASS_CTYPE_STREAM 0x10000 +#define BASS_CTYPE_STREAM_OGG 0x10002 +#define BASS_CTYPE_STREAM_MP1 0x10003 +#define BASS_CTYPE_STREAM_MP2 0x10004 +#define BASS_CTYPE_STREAM_MP3 0x10005 +#define BASS_CTYPE_STREAM_AIFF 0x10006 +#define BASS_CTYPE_STREAM_CA 0x10007 +#define BASS_CTYPE_STREAM_MF 0x10008 +#define BASS_CTYPE_STREAM_WAV 0x40000 // WAVE flag, LOWORD=codec +#define BASS_CTYPE_STREAM_WAV_PCM 0x50001 +#define BASS_CTYPE_STREAM_WAV_FLOAT 0x50003 +#define BASS_CTYPE_MUSIC_MOD 0x20000 +#define BASS_CTYPE_MUSIC_MTM 0x20001 +#define BASS_CTYPE_MUSIC_S3M 0x20002 +#define BASS_CTYPE_MUSIC_XM 0x20003 +#define BASS_CTYPE_MUSIC_IT 0x20004 +#define BASS_CTYPE_MUSIC_MO3 0x00100 // MO3 flag + +typedef struct { + DWORD ctype; // channel type +#ifdef _WIN32_WCE + const wchar_t *name; // format description + const wchar_t *exts; // file extension filter (*.ext1;*.ext2;etc...) +#else + const char *name; // format description + const char *exts; // file extension filter (*.ext1;*.ext2;etc...) +#endif +} BASS_PLUGINFORM; + +typedef struct { + DWORD version; // version (same form as BASS_GetVersion) + DWORD formatc; // number of formats + const BASS_PLUGINFORM *formats; // the array of formats +} BASS_PLUGININFO; + +// 3D vector (for 3D positions/velocities/orientations) +typedef struct BASS_3DVECTOR { +#ifdef __cplusplus + BASS_3DVECTOR() {}; + BASS_3DVECTOR(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}; +#endif + float x; // +=right, -=left + float y; // +=up, -=down + float z; // +=front, -=behind +} BASS_3DVECTOR; + +// 3D channel modes +#define BASS_3DMODE_NORMAL 0 // normal 3D processing +#define BASS_3DMODE_RELATIVE 1 // position is relative to the listener +#define BASS_3DMODE_OFF 2 // no 3D processing + +// software 3D mixing algorithms (used with BASS_CONFIG_3DALGORITHM) +#define BASS_3DALG_DEFAULT 0 +#define BASS_3DALG_OFF 1 +#define BASS_3DALG_FULL 2 +#define BASS_3DALG_LIGHT 3 + +// EAX environments, use with BASS_SetEAXParameters +enum +{ + EAX_ENVIRONMENT_GENERIC, + EAX_ENVIRONMENT_PADDEDCELL, + EAX_ENVIRONMENT_ROOM, + EAX_ENVIRONMENT_BATHROOM, + EAX_ENVIRONMENT_LIVINGROOM, + EAX_ENVIRONMENT_STONEROOM, + EAX_ENVIRONMENT_AUDITORIUM, + EAX_ENVIRONMENT_CONCERTHALL, + EAX_ENVIRONMENT_CAVE, + EAX_ENVIRONMENT_ARENA, + EAX_ENVIRONMENT_HANGAR, + EAX_ENVIRONMENT_CARPETEDHALLWAY, + EAX_ENVIRONMENT_HALLWAY, + EAX_ENVIRONMENT_STONECORRIDOR, + EAX_ENVIRONMENT_ALLEY, + EAX_ENVIRONMENT_FOREST, + EAX_ENVIRONMENT_CITY, + EAX_ENVIRONMENT_MOUNTAINS, + EAX_ENVIRONMENT_QUARRY, + EAX_ENVIRONMENT_PLAIN, + EAX_ENVIRONMENT_PARKINGLOT, + EAX_ENVIRONMENT_SEWERPIPE, + EAX_ENVIRONMENT_UNDERWATER, + EAX_ENVIRONMENT_DRUGGED, + EAX_ENVIRONMENT_DIZZY, + EAX_ENVIRONMENT_PSYCHOTIC, + + EAX_ENVIRONMENT_COUNT // total number of environments +}; + +// EAX presets, usage: BASS_SetEAXParameters(EAX_PRESET_xxx) +#define EAX_PRESET_GENERIC EAX_ENVIRONMENT_GENERIC,0.5F,1.493F,0.5F +#define EAX_PRESET_PADDEDCELL EAX_ENVIRONMENT_PADDEDCELL,0.25F,0.1F,0.0F +#define EAX_PRESET_ROOM EAX_ENVIRONMENT_ROOM,0.417F,0.4F,0.666F +#define EAX_PRESET_BATHROOM EAX_ENVIRONMENT_BATHROOM,0.653F,1.499F,0.166F +#define EAX_PRESET_LIVINGROOM EAX_ENVIRONMENT_LIVINGROOM,0.208F,0.478F,0.0F +#define EAX_PRESET_STONEROOM EAX_ENVIRONMENT_STONEROOM,0.5F,2.309F,0.888F +#define EAX_PRESET_AUDITORIUM EAX_ENVIRONMENT_AUDITORIUM,0.403F,4.279F,0.5F +#define EAX_PRESET_CONCERTHALL EAX_ENVIRONMENT_CONCERTHALL,0.5F,3.961F,0.5F +#define EAX_PRESET_CAVE EAX_ENVIRONMENT_CAVE,0.5F,2.886F,1.304F +#define EAX_PRESET_ARENA EAX_ENVIRONMENT_ARENA,0.361F,7.284F,0.332F +#define EAX_PRESET_HANGAR EAX_ENVIRONMENT_HANGAR,0.5F,10.0F,0.3F +#define EAX_PRESET_CARPETEDHALLWAY EAX_ENVIRONMENT_CARPETEDHALLWAY,0.153F,0.259F,2.0F +#define EAX_PRESET_HALLWAY EAX_ENVIRONMENT_HALLWAY,0.361F,1.493F,0.0F +#define EAX_PRESET_STONECORRIDOR EAX_ENVIRONMENT_STONECORRIDOR,0.444F,2.697F,0.638F +#define EAX_PRESET_ALLEY EAX_ENVIRONMENT_ALLEY,0.25F,1.752F,0.776F +#define EAX_PRESET_FOREST EAX_ENVIRONMENT_FOREST,0.111F,3.145F,0.472F +#define EAX_PRESET_CITY EAX_ENVIRONMENT_CITY,0.111F,2.767F,0.224F +#define EAX_PRESET_MOUNTAINS EAX_ENVIRONMENT_MOUNTAINS,0.194F,7.841F,0.472F +#define EAX_PRESET_QUARRY EAX_ENVIRONMENT_QUARRY,1.0F,1.499F,0.5F +#define EAX_PRESET_PLAIN EAX_ENVIRONMENT_PLAIN,0.097F,2.767F,0.224F +#define EAX_PRESET_PARKINGLOT EAX_ENVIRONMENT_PARKINGLOT,0.208F,1.652F,1.5F +#define EAX_PRESET_SEWERPIPE EAX_ENVIRONMENT_SEWERPIPE,0.652F,2.886F,0.25F +#define EAX_PRESET_UNDERWATER EAX_ENVIRONMENT_UNDERWATER,1.0F,1.499F,0.0F +#define EAX_PRESET_DRUGGED EAX_ENVIRONMENT_DRUGGED,0.875F,8.392F,1.388F +#define EAX_PRESET_DIZZY EAX_ENVIRONMENT_DIZZY,0.139F,17.234F,0.666F +#define EAX_PRESET_PSYCHOTIC EAX_ENVIRONMENT_PSYCHOTIC,0.486F,7.563F,0.806F + +typedef DWORD (CALLBACK STREAMPROC)(HSTREAM handle, void *buffer, DWORD length, void *user); +/* User stream callback function. NOTE: A stream function should obviously be as quick +as possible, other streams (and MOD musics) can't be mixed until it's finished. +handle : The stream that needs writing +buffer : Buffer to write the samples in +length : Number of bytes to write +user : The 'user' parameter value given when calling BASS_StreamCreate +RETURN : Number of bytes written. Set the BASS_STREAMPROC_END flag to end + the stream. */ + +#define BASS_STREAMPROC_END 0x80000000 // end of user stream flag + +// special STREAMPROCs +#define STREAMPROC_DUMMY (STREAMPROC*)0 // "dummy" stream +#define STREAMPROC_PUSH (STREAMPROC*)-1 // push stream + +// BASS_StreamCreateFileUser file systems +#define STREAMFILE_NOBUFFER 0 +#define STREAMFILE_BUFFER 1 +#define STREAMFILE_BUFFERPUSH 2 + +// User file stream callback functions +typedef void (CALLBACK FILECLOSEPROC)(void *user); +typedef QWORD (CALLBACK FILELENPROC)(void *user); +typedef DWORD (CALLBACK FILEREADPROC)(void *buffer, DWORD length, void *user); +typedef BOOL (CALLBACK FILESEEKPROC)(QWORD offset, void *user); + +typedef struct { + FILECLOSEPROC *close; + FILELENPROC *length; + FILEREADPROC *read; + FILESEEKPROC *seek; +} BASS_FILEPROCS; + +// BASS_StreamPutFileData options +#define BASS_FILEDATA_END 0 // end & close the file + +// BASS_StreamGetFilePosition modes +#define BASS_FILEPOS_CURRENT 0 +#define BASS_FILEPOS_DECODE BASS_FILEPOS_CURRENT +#define BASS_FILEPOS_DOWNLOAD 1 +#define BASS_FILEPOS_END 2 +#define BASS_FILEPOS_START 3 +#define BASS_FILEPOS_CONNECTED 4 +#define BASS_FILEPOS_BUFFER 5 +#define BASS_FILEPOS_SOCKET 6 + +typedef void (CALLBACK DOWNLOADPROC)(const void *buffer, DWORD length, void *user); +/* Internet stream download callback function. +buffer : Buffer containing the downloaded data... NULL=end of download +length : Number of bytes in the buffer +user : The 'user' parameter value given when calling BASS_StreamCreateURL */ + +// BASS_ChannelSetSync types +#define BASS_SYNC_POS 0 +#define BASS_SYNC_END 2 +#define BASS_SYNC_META 4 +#define BASS_SYNC_SLIDE 5 +#define BASS_SYNC_STALL 6 +#define BASS_SYNC_DOWNLOAD 7 +#define BASS_SYNC_FREE 8 +#define BASS_SYNC_SETPOS 11 +#define BASS_SYNC_MUSICPOS 10 +#define BASS_SYNC_MUSICINST 1 +#define BASS_SYNC_MUSICFX 3 +#define BASS_SYNC_OGG_CHANGE 12 +#define BASS_SYNC_MIXTIME 0x40000000 // FLAG: sync at mixtime, else at playtime +#define BASS_SYNC_ONETIME 0x80000000 // FLAG: sync only once, else continuously + +typedef void (CALLBACK SYNCPROC)(HSYNC handle, DWORD channel, DWORD data, void *user); +/* Sync callback function. NOTE: a sync callback function should be very +quick as other syncs can't be processed until it has finished. If the sync +is a "mixtime" sync, then other streams and MOD musics can't be mixed until +it's finished either. +handle : The sync that has occured +channel: Channel that the sync occured in +data : Additional data associated with the sync's occurance +user : The 'user' parameter given when calling BASS_ChannelSetSync */ + +typedef void (CALLBACK DSPPROC)(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user); +/* DSP callback function. NOTE: A DSP function should obviously be as quick as +possible... other DSP functions, streams and MOD musics can not be processed +until it's finished. +handle : The DSP handle +channel: Channel that the DSP is being applied to +buffer : Buffer to apply the DSP to +length : Number of bytes in the buffer +user : The 'user' parameter given when calling BASS_ChannelSetDSP */ + +typedef BOOL (CALLBACK RECORDPROC)(HRECORD handle, const void *buffer, DWORD length, void *user); +/* Recording callback function. +handle : The recording handle +buffer : Buffer containing the recorded sample data +length : Number of bytes +user : The 'user' parameter value given when calling BASS_RecordStart +RETURN : TRUE = continue recording, FALSE = stop */ + +// BASS_ChannelIsActive return values +#define BASS_ACTIVE_STOPPED 0 +#define BASS_ACTIVE_PLAYING 1 +#define BASS_ACTIVE_STALLED 2 +#define BASS_ACTIVE_PAUSED 3 + +// Channel attributes +#define BASS_ATTRIB_FREQ 1 +#define BASS_ATTRIB_VOL 2 +#define BASS_ATTRIB_PAN 3 +#define BASS_ATTRIB_EAXMIX 4 +#define BASS_ATTRIB_NOBUFFER 5 +#define BASS_ATTRIB_CPU 7 +#define BASS_ATTRIB_SRC 8 +#define BASS_ATTRIB_MUSIC_AMPLIFY 0x100 +#define BASS_ATTRIB_MUSIC_PANSEP 0x101 +#define BASS_ATTRIB_MUSIC_PSCALER 0x102 +#define BASS_ATTRIB_MUSIC_BPM 0x103 +#define BASS_ATTRIB_MUSIC_SPEED 0x104 +#define BASS_ATTRIB_MUSIC_VOL_GLOBAL 0x105 +#define BASS_ATTRIB_MUSIC_VOL_CHAN 0x200 // + channel # +#define BASS_ATTRIB_MUSIC_VOL_INST 0x300 // + instrument # + +// BASS_ChannelGetData flags +#define BASS_DATA_AVAILABLE 0 // query how much data is buffered +#define BASS_DATA_FLOAT 0x40000000 // flag: return floating-point sample data +#define BASS_DATA_FFT256 0x80000000 // 256 sample FFT +#define BASS_DATA_FFT512 0x80000001 // 512 FFT +#define BASS_DATA_FFT1024 0x80000002 // 1024 FFT +#define BASS_DATA_FFT2048 0x80000003 // 2048 FFT +#define BASS_DATA_FFT4096 0x80000004 // 4096 FFT +#define BASS_DATA_FFT8192 0x80000005 // 8192 FFT +#define BASS_DATA_FFT16384 0x80000006 // 16384 FFT +#define BASS_DATA_FFT_INDIVIDUAL 0x10 // FFT flag: FFT for each channel, else all combined +#define BASS_DATA_FFT_NOWINDOW 0x20 // FFT flag: no Hanning window +#define BASS_DATA_FFT_REMOVEDC 0x40 // FFT flag: pre-remove DC bias +#define BASS_DATA_FFT_COMPLEX 0x80 // FFT flag: return complex data + +// BASS_ChannelGetTags types : what's returned +#define BASS_TAG_ID3 0 // ID3v1 tags : TAG_ID3 structure +#define BASS_TAG_ID3V2 1 // ID3v2 tags : variable length block +#define BASS_TAG_OGG 2 // OGG comments : series of null-terminated UTF-8 strings +#define BASS_TAG_HTTP 3 // HTTP headers : series of null-terminated ANSI strings +#define BASS_TAG_ICY 4 // ICY headers : series of null-terminated ANSI strings +#define BASS_TAG_META 5 // ICY metadata : ANSI string +#define BASS_TAG_APE 6 // APE tags : series of null-terminated UTF-8 strings +#define BASS_TAG_MP4 7 // MP4/iTunes metadata : series of null-terminated UTF-8 strings +#define BASS_TAG_VENDOR 9 // OGG encoder : UTF-8 string +#define BASS_TAG_LYRICS3 10 // Lyric3v2 tag : ASCII string +#define BASS_TAG_CA_CODEC 11 // CoreAudio codec info : TAG_CA_CODEC structure +#define BASS_TAG_MF 13 // Media Foundation tags : series of null-terminated UTF-8 strings +#define BASS_TAG_WAVEFORMAT 14 // WAVE format : WAVEFORMATEEX structure +#define BASS_TAG_RIFF_INFO 0x100 // RIFF "INFO" tags : series of null-terminated ANSI strings +#define BASS_TAG_RIFF_BEXT 0x101 // RIFF/BWF "bext" tags : TAG_BEXT structure +#define BASS_TAG_RIFF_CART 0x102 // RIFF/BWF "cart" tags : TAG_CART structure +#define BASS_TAG_RIFF_DISP 0x103 // RIFF "DISP" text tag : ANSI string +#define BASS_TAG_APE_BINARY 0x1000 // + index #, binary APE tag : TAG_APE_BINARY structure +#define BASS_TAG_MUSIC_NAME 0x10000 // MOD music name : ANSI string +#define BASS_TAG_MUSIC_MESSAGE 0x10001 // MOD message : ANSI string +#define BASS_TAG_MUSIC_ORDERS 0x10002 // MOD order list : BYTE array of pattern numbers +#define BASS_TAG_MUSIC_INST 0x10100 // + instrument #, MOD instrument name : ANSI string +#define BASS_TAG_MUSIC_SAMPLE 0x10300 // + sample #, MOD sample name : ANSI string + +// ID3v1 tag structure +typedef struct { + char id[3]; + char title[30]; + char artist[30]; + char album[30]; + char year[4]; + char comment[30]; + BYTE genre; +} TAG_ID3; + +// Binary APE tag structure +typedef struct { + const char *key; + const void *data; + DWORD length; +} TAG_APE_BINARY; + +// BWF "bext" tag structure +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4200) +#endif +#pragma pack(push,1) +typedef struct { + char Description[256]; // description + char Originator[32]; // name of the originator + char OriginatorReference[32]; // reference of the originator + char OriginationDate[10]; // date of creation (yyyy-mm-dd) + char OriginationTime[8]; // time of creation (hh-mm-ss) + QWORD TimeReference; // first sample count since midnight (little-endian) + WORD Version; // BWF version (little-endian) + BYTE UMID[64]; // SMPTE UMID + BYTE Reserved[190]; +#if defined(__GNUC__) && __GNUC__<3 + char CodingHistory[0]; // history +#elif 1 // change to 0 if compiler fails the following line + char CodingHistory[]; // history +#else + char CodingHistory[1]; // history +#endif +} TAG_BEXT; +#pragma pack(pop) + +// BWF "cart" tag structures +typedef struct +{ + DWORD dwUsage; // FOURCC timer usage ID + DWORD dwValue; // timer value in samples from head +} TAG_CART_TIMER; + +typedef struct +{ + char Version[4]; // version of the data structure + char Title[64]; // title of cart audio sequence + char Artist[64]; // artist or creator name + char CutID[64]; // cut number identification + char ClientID[64]; // client identification + char Category[64]; // category ID, PSA, NEWS, etc + char Classification[64]; // classification or auxiliary key + char OutCue[64]; // out cue text + char StartDate[10]; // yyyy-mm-dd + char StartTime[8]; // hh:mm:ss + char EndDate[10]; // yyyy-mm-dd + char EndTime[8]; // hh:mm:ss + char ProducerAppID[64]; // name of vendor or application + char ProducerAppVersion[64]; // version of producer application + char UserDef[64]; // user defined text + DWORD dwLevelReference; // sample value for 0 dB reference + TAG_CART_TIMER PostTimer[8]; // 8 time markers after head + char Reserved[276]; + char URL[1024]; // uniform resource locator +#if defined(__GNUC__) && __GNUC__<3 + char TagText[0]; // free form text for scripts or tags +#elif 1 // change to 0 if compiler fails the following line + char TagText[]; // free form text for scripts or tags +#else + char TagText[1]; // free form text for scripts or tags +#endif +} TAG_CART; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// CoreAudio codec info structure +typedef struct { + DWORD ftype; // file format + DWORD atype; // audio format + const char *name; // description +} TAG_CA_CODEC; + +#ifndef _WAVEFORMATEX_ +#define _WAVEFORMATEX_ +#pragma pack(push,1) +typedef struct tWAVEFORMATEX +{ + WORD wFormatTag; + WORD nChannels; + DWORD nSamplesPerSec; + DWORD nAvgBytesPerSec; + WORD nBlockAlign; + WORD wBitsPerSample; + WORD cbSize; +} WAVEFORMATEX, *PWAVEFORMATEX, *LPWAVEFORMATEX; +typedef const WAVEFORMATEX *LPCWAVEFORMATEX; +#pragma pack(pop) +#endif + +// BASS_ChannelGetLength/GetPosition/SetPosition modes +#define BASS_POS_BYTE 0 // byte position +#define BASS_POS_MUSIC_ORDER 1 // order.row position, MAKELONG(order,row) +#define BASS_POS_OGG 3 // OGG bitstream number +#define BASS_POS_DECODE 0x10000000 // flag: get the decoding (not playing) position +#define BASS_POS_DECODETO 0x20000000 // flag: decode to the position instead of seeking + +// BASS_RecordSetInput flags +#define BASS_INPUT_OFF 0x10000 +#define BASS_INPUT_ON 0x20000 + +#define BASS_INPUT_TYPE_MASK 0xff000000 +#define BASS_INPUT_TYPE_UNDEF 0x00000000 +#define BASS_INPUT_TYPE_DIGITAL 0x01000000 +#define BASS_INPUT_TYPE_LINE 0x02000000 +#define BASS_INPUT_TYPE_MIC 0x03000000 +#define BASS_INPUT_TYPE_SYNTH 0x04000000 +#define BASS_INPUT_TYPE_CD 0x05000000 +#define BASS_INPUT_TYPE_PHONE 0x06000000 +#define BASS_INPUT_TYPE_SPEAKER 0x07000000 +#define BASS_INPUT_TYPE_WAVE 0x08000000 +#define BASS_INPUT_TYPE_AUX 0x09000000 +#define BASS_INPUT_TYPE_ANALOG 0x0a000000 + +// DX8 effect types, use with BASS_ChannelSetFX +enum +{ + BASS_FX_DX8_CHORUS, + BASS_FX_DX8_COMPRESSOR, + BASS_FX_DX8_DISTORTION, + BASS_FX_DX8_ECHO, + BASS_FX_DX8_FLANGER, + BASS_FX_DX8_GARGLE, + BASS_FX_DX8_I3DL2REVERB, + BASS_FX_DX8_PARAMEQ, + BASS_FX_DX8_REVERB +}; + +typedef struct { + float fWetDryMix; + float fDepth; + float fFeedback; + float fFrequency; + DWORD lWaveform; // 0=triangle, 1=sine + float fDelay; + DWORD lPhase; // BASS_DX8_PHASE_xxx +} BASS_DX8_CHORUS; + +typedef struct { + float fGain; + float fAttack; + float fRelease; + float fThreshold; + float fRatio; + float fPredelay; +} BASS_DX8_COMPRESSOR; + +typedef struct { + float fGain; + float fEdge; + float fPostEQCenterFrequency; + float fPostEQBandwidth; + float fPreLowpassCutoff; +} BASS_DX8_DISTORTION; + +typedef struct { + float fWetDryMix; + float fFeedback; + float fLeftDelay; + float fRightDelay; + BOOL lPanDelay; +} BASS_DX8_ECHO; + +typedef struct { + float fWetDryMix; + float fDepth; + float fFeedback; + float fFrequency; + DWORD lWaveform; // 0=triangle, 1=sine + float fDelay; + DWORD lPhase; // BASS_DX8_PHASE_xxx +} BASS_DX8_FLANGER; + +typedef struct { + DWORD dwRateHz; // Rate of modulation in hz + DWORD dwWaveShape; // 0=triangle, 1=square +} BASS_DX8_GARGLE; + +typedef struct { + int lRoom; // [-10000, 0] default: -1000 mB + int lRoomHF; // [-10000, 0] default: 0 mB + float flRoomRolloffFactor; // [0.0, 10.0] default: 0.0 + float flDecayTime; // [0.1, 20.0] default: 1.49s + float flDecayHFRatio; // [0.1, 2.0] default: 0.83 + int lReflections; // [-10000, 1000] default: -2602 mB + float flReflectionsDelay; // [0.0, 0.3] default: 0.007 s + int lReverb; // [-10000, 2000] default: 200 mB + float flReverbDelay; // [0.0, 0.1] default: 0.011 s + float flDiffusion; // [0.0, 100.0] default: 100.0 % + float flDensity; // [0.0, 100.0] default: 100.0 % + float flHFReference; // [20.0, 20000.0] default: 5000.0 Hz +} BASS_DX8_I3DL2REVERB; + +typedef struct { + float fCenter; + float fBandwidth; + float fGain; +} BASS_DX8_PARAMEQ; + +typedef struct { + float fInGain; // [-96.0,0.0] default: 0.0 dB + float fReverbMix; // [-96.0,0.0] default: 0.0 db + float fReverbTime; // [0.001,3000.0] default: 1000.0 ms + float fHighFreqRTRatio; // [0.001,0.999] default: 0.001 +} BASS_DX8_REVERB; + +#define BASS_DX8_PHASE_NEG_180 0 +#define BASS_DX8_PHASE_NEG_90 1 +#define BASS_DX8_PHASE_ZERO 2 +#define BASS_DX8_PHASE_90 3 +#define BASS_DX8_PHASE_180 4 + +typedef void (CALLBACK IOSNOTIFYPROC)(DWORD status); +/* iOS notification callback function. +status : The notification (BASS_IOSNOTIFY_xxx) */ + +#define BASS_IOSNOTIFY_INTERRUPT 1 // interruption started +#define BASS_IOSNOTIFY_INTERRUPT_END 2 // interruption ended + +BOOL BASSDEF(BASS_SetConfig)(DWORD option, DWORD value); +DWORD BASSDEF(BASS_GetConfig)(DWORD option); +BOOL BASSDEF(BASS_SetConfigPtr)(DWORD option, const void *value); +void *BASSDEF(BASS_GetConfigPtr)(DWORD option); +DWORD BASSDEF(BASS_GetVersion)(); +int BASSDEF(BASS_ErrorGetCode)(); +BOOL BASSDEF(BASS_GetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info); +#if defined(_WIN32) && !defined(_WIN32_WCE) +BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, HWND win, const GUID *dsguid); +#else +BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, void *win, void *dsguid); +#endif +BOOL BASSDEF(BASS_SetDevice)(DWORD device); +DWORD BASSDEF(BASS_GetDevice)(); +BOOL BASSDEF(BASS_Free)(); +#if defined(_WIN32) && !defined(_WIN32_WCE) +void *BASSDEF(BASS_GetDSoundObject)(DWORD object); +#endif +BOOL BASSDEF(BASS_GetInfo)(BASS_INFO *info); +BOOL BASSDEF(BASS_Update)(DWORD length); +float BASSDEF(BASS_GetCPU)(); +BOOL BASSDEF(BASS_Start)(); +BOOL BASSDEF(BASS_Stop)(); +BOOL BASSDEF(BASS_Pause)(); +BOOL BASSDEF(BASS_SetVolume)(float volume); +float BASSDEF(BASS_GetVolume)(); + +HPLUGIN BASSDEF(BASS_PluginLoad)(const char *file, DWORD flags); +BOOL BASSDEF(BASS_PluginFree)(HPLUGIN handle); +const BASS_PLUGININFO *BASSDEF(BASS_PluginGetInfo)(HPLUGIN handle); + +BOOL BASSDEF(BASS_Set3DFactors)(float distf, float rollf, float doppf); +BOOL BASSDEF(BASS_Get3DFactors)(float *distf, float *rollf, float *doppf); +BOOL BASSDEF(BASS_Set3DPosition)(const BASS_3DVECTOR *pos, const BASS_3DVECTOR *vel, const BASS_3DVECTOR *front, const BASS_3DVECTOR *top); +BOOL BASSDEF(BASS_Get3DPosition)(BASS_3DVECTOR *pos, BASS_3DVECTOR *vel, BASS_3DVECTOR *front, BASS_3DVECTOR *top); +void BASSDEF(BASS_Apply3D)(); +#if defined(_WIN32) && !defined(_WIN32_WCE) +BOOL BASSDEF(BASS_SetEAXParameters)(int env, float vol, float decay, float damp); +BOOL BASSDEF(BASS_GetEAXParameters)(DWORD *env, float *vol, float *decay, float *damp); +#endif + +HMUSIC BASSDEF(BASS_MusicLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD flags, DWORD freq); +BOOL BASSDEF(BASS_MusicFree)(HMUSIC handle); + +HSAMPLE BASSDEF(BASS_SampleLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD max, DWORD flags); +HSAMPLE BASSDEF(BASS_SampleCreate)(DWORD length, DWORD freq, DWORD chans, DWORD max, DWORD flags); +BOOL BASSDEF(BASS_SampleFree)(HSAMPLE handle); +BOOL BASSDEF(BASS_SampleSetData)(HSAMPLE handle, const void *buffer); +BOOL BASSDEF(BASS_SampleGetData)(HSAMPLE handle, void *buffer); +BOOL BASSDEF(BASS_SampleGetInfo)(HSAMPLE handle, BASS_SAMPLE *info); +BOOL BASSDEF(BASS_SampleSetInfo)(HSAMPLE handle, const BASS_SAMPLE *info); +HCHANNEL BASSDEF(BASS_SampleGetChannel)(HSAMPLE handle, BOOL onlynew); +DWORD BASSDEF(BASS_SampleGetChannels)(HSAMPLE handle, HCHANNEL *channels); +BOOL BASSDEF(BASS_SampleStop)(HSAMPLE handle); + +HSTREAM BASSDEF(BASS_StreamCreate)(DWORD freq, DWORD chans, DWORD flags, STREAMPROC *proc, void *user); +HSTREAM BASSDEF(BASS_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags); +HSTREAM BASSDEF(BASS_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user); +HSTREAM BASSDEF(BASS_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *proc, void *user); +BOOL BASSDEF(BASS_StreamFree)(HSTREAM handle); +QWORD BASSDEF(BASS_StreamGetFilePosition)(HSTREAM handle, DWORD mode); +DWORD BASSDEF(BASS_StreamPutData)(HSTREAM handle, const void *buffer, DWORD length); +DWORD BASSDEF(BASS_StreamPutFileData)(HSTREAM handle, const void *buffer, DWORD length); + +BOOL BASSDEF(BASS_RecordGetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info); +BOOL BASSDEF(BASS_RecordInit)(int device); +BOOL BASSDEF(BASS_RecordSetDevice)(DWORD device); +DWORD BASSDEF(BASS_RecordGetDevice)(); +BOOL BASSDEF(BASS_RecordFree)(); +BOOL BASSDEF(BASS_RecordGetInfo)(BASS_RECORDINFO *info); +const char *BASSDEF(BASS_RecordGetInputName)(int input); +BOOL BASSDEF(BASS_RecordSetInput)(int input, DWORD flags, float volume); +DWORD BASSDEF(BASS_RecordGetInput)(int input, float *volume); +HRECORD BASSDEF(BASS_RecordStart)(DWORD freq, DWORD chans, DWORD flags, RECORDPROC *proc, void *user); + +double BASSDEF(BASS_ChannelBytes2Seconds)(DWORD handle, QWORD pos); +QWORD BASSDEF(BASS_ChannelSeconds2Bytes)(DWORD handle, double pos); +DWORD BASSDEF(BASS_ChannelGetDevice)(DWORD handle); +BOOL BASSDEF(BASS_ChannelSetDevice)(DWORD handle, DWORD device); +DWORD BASSDEF(BASS_ChannelIsActive)(DWORD handle); +BOOL BASSDEF(BASS_ChannelGetInfo)(DWORD handle, BASS_CHANNELINFO *info); +const char *BASSDEF(BASS_ChannelGetTags)(DWORD handle, DWORD tags); +DWORD BASSDEF(BASS_ChannelFlags)(DWORD handle, DWORD flags, DWORD mask); +BOOL BASSDEF(BASS_ChannelUpdate)(DWORD handle, DWORD length); +BOOL BASSDEF(BASS_ChannelLock)(DWORD handle, BOOL lock); +BOOL BASSDEF(BASS_ChannelPlay)(DWORD handle, BOOL restart); +BOOL BASSDEF(BASS_ChannelStop)(DWORD handle); +BOOL BASSDEF(BASS_ChannelPause)(DWORD handle); +BOOL BASSDEF(BASS_ChannelSetAttribute)(DWORD handle, DWORD attrib, float value); +BOOL BASSDEF(BASS_ChannelGetAttribute)(DWORD handle, DWORD attrib, float *value); +BOOL BASSDEF(BASS_ChannelSlideAttribute)(DWORD handle, DWORD attrib, float value, DWORD time); +BOOL BASSDEF(BASS_ChannelIsSliding)(DWORD handle, DWORD attrib); +BOOL BASSDEF(BASS_ChannelSet3DAttributes)(DWORD handle, int mode, float min, float max, int iangle, int oangle, float outvol); +BOOL BASSDEF(BASS_ChannelGet3DAttributes)(DWORD handle, DWORD *mode, float *min, float *max, DWORD *iangle, DWORD *oangle, float *outvol); +BOOL BASSDEF(BASS_ChannelSet3DPosition)(DWORD handle, const BASS_3DVECTOR *pos, const BASS_3DVECTOR *orient, const BASS_3DVECTOR *vel); +BOOL BASSDEF(BASS_ChannelGet3DPosition)(DWORD handle, BASS_3DVECTOR *pos, BASS_3DVECTOR *orient, BASS_3DVECTOR *vel); +QWORD BASSDEF(BASS_ChannelGetLength)(DWORD handle, DWORD mode); +BOOL BASSDEF(BASS_ChannelSetPosition)(DWORD handle, QWORD pos, DWORD mode); +QWORD BASSDEF(BASS_ChannelGetPosition)(DWORD handle, DWORD mode); +DWORD BASSDEF(BASS_ChannelGetLevel)(DWORD handle); +DWORD BASSDEF(BASS_ChannelGetData)(DWORD handle, void *buffer, DWORD length); +HSYNC BASSDEF(BASS_ChannelSetSync)(DWORD handle, DWORD type, QWORD param, SYNCPROC *proc, void *user); +BOOL BASSDEF(BASS_ChannelRemoveSync)(DWORD handle, HSYNC sync); +HDSP BASSDEF(BASS_ChannelSetDSP)(DWORD handle, DSPPROC *proc, void *user, int priority); +BOOL BASSDEF(BASS_ChannelRemoveDSP)(DWORD handle, HDSP dsp); +BOOL BASSDEF(BASS_ChannelSetLink)(DWORD handle, DWORD chan); +BOOL BASSDEF(BASS_ChannelRemoveLink)(DWORD handle, DWORD chan); +HFX BASSDEF(BASS_ChannelSetFX)(DWORD handle, DWORD type, int priority); +BOOL BASSDEF(BASS_ChannelRemoveFX)(DWORD handle, HFX fx); + +BOOL BASSDEF(BASS_FXSetParameters)(HFX handle, const void *params); +BOOL BASSDEF(BASS_FXGetParameters)(HFX handle, void *params); +BOOL BASSDEF(BASS_FXReset)(HFX handle); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/saco/bass.lib b/saco/bass.lib new file mode 100644 index 0000000..ac5ab1d Binary files /dev/null and b/saco/bass.lib differ diff --git a/saco/chatwindow.cpp b/saco/chatwindow.cpp index be99534..4c4f8bd 100644 --- a/saco/chatwindow.cpp +++ b/saco/chatwindow.cpp @@ -1,6 +1,8 @@ #include "main.h" +DWORD FUNC_100B6100(char *szString, int nMaxLen); + //---------------------------------------------------- CChatWindow::CChatWindow(IDirect3DDevice9 *pD3DDevice, CFontRender *pFontRender, CHAR *szChatLogFile) @@ -78,12 +80,84 @@ void CChatWindow::ResetDialogControls(CDXUTDialog *pGameUI) } //---------------------------------------------------- + +void CChatWindow::AddChatMessage(CHAR *szNick, DWORD dwNickColor, CHAR *szMessage) +{ + FilterInvalidChars(szMessage); + AddToChatWindowBuffer(CHAT_TYPE_CHAT,szMessage,szNick,m_dwChatTextColor,dwNickColor); +} + +//---------------------------------------------------- + +void CChatWindow::AddInfoMessage(CHAR * szFormat, ...) +{ + char tmp_buf[512]; + memset(tmp_buf,0,512); + + va_list args; + va_start(args, szFormat); + vsprintf(tmp_buf, szFormat, args); + va_end(args); + + FilterInvalidChars(tmp_buf); + AddToChatWindowBuffer(CHAT_TYPE_INFO,tmp_buf,NULL,m_dwChatInfoColor,0); +} + //---------------------------------------------------- void CChatWindow::AddDebugMessage(CHAR * szFormat, ...) { - // TODO: CChatWindow::AddDebugMessage .text:100680F0 + char tmp_buf[512]; + memset(tmp_buf,0,512); + + va_list args; + va_start(args, szFormat); + vsprintf(tmp_buf, szFormat, args); + va_end(args); + + FilterInvalidChars(tmp_buf); + AddToChatWindowBuffer(CHAT_TYPE_DEBUG,tmp_buf,NULL,m_dwChatDebugColor,0); + OutputDebugString(tmp_buf); } + +//---------------------------------------------------- + +void CChatWindow::AddClientMessage(DWORD dwColor, PCHAR szStr) +{ + dwColor = (dwColor >> 8) | 0xFF000000; // convert to ARGB + + if(strlen(szStr) > 144) return; + + FUNC_100B6100(szStr, 255); + FilterInvalidChars(szStr); + + AddToChatWindowBuffer(CHAT_TYPE_INFO,szStr,NULL,dwColor,0); +} + +//---------------------------------------------------- + +void CChatWindow::FilterInvalidChars(PCHAR szString) +{ + while(*szString) { + if(*szString > 0 && *szString < ' ') { + *szString = ' '; + } + szString++; + } +} + +//---------------------------------------------------- + +void CChatWindow::AddToChatWindowBuffer(eChatMessageType eType, + PCHAR szString, + PCHAR szNick, + DWORD dwTextColor, + DWORD dwChatColor) +{ + // TODO: CChatWindow::AddToChatWindowBuffer +} + +//---------------------------------------------------- // MATCH void CChatWindow::FUNC_10067200() { diff --git a/saco/chatwindow.h b/saco/chatwindow.h index 588fa17..31c825e 100644 --- a/saco/chatwindow.h +++ b/saco/chatwindow.h @@ -1,13 +1,28 @@ #pragma once +#define MAX_MESSAGE_LENGTH 144 +#define MAX_LINE_LENGTH MAX_MESSAGE_LENGTH / 2 #define MAX_MESSAGES 100 +enum eChatMessageType { + CHAT_TYPE_NONE=0, + CHAT_TYPE_CHAT=2, + CHAT_TYPE_INFO=4, + CHAT_TYPE_DEBUG=8, +}; #pragma pack(1) typedef struct _CHAT_WINDOW_ENTRY { - char _gap0[252]; + //char _gap0[252]; + time_t field_0; + + char _gap4[236]; + + eChatMessageType eType; + DWORD dwTextColor; + DWORD dwNickColor; } CHAT_WINDOW_ENTRY; class CChatWindow // size: 25578 @@ -27,6 +42,7 @@ private: DWORD m_dwChatInfoColor; DWORD m_dwChatDebugColor; char _gap12E[4]; + //char field_132[25200]; CHAT_WINDOW_ENTRY m_ChatWindowEntries[MAX_MESSAGES]; CFontRender *m_pFontRender; ID3DXSprite *field_63A6; @@ -44,14 +60,21 @@ private: int field_63E2; char _gap63E6[4]; + void FilterInvalidChars(PCHAR szString); + void AddToChatWindowBuffer(eChatMessageType eType,PCHAR szString, + PCHAR szNick,DWORD dwTextColor,DWORD dwChatColor); void CreateFonts(); void FUNC_10067200(); public: + CChatWindow(); + void AddChatMessage(CHAR *szNick, DWORD dwNickColor, CHAR *szMessage); + void AddInfoMessage(CHAR *szFormat, ...); void AddDebugMessage(CHAR *szFormat, ...); + void AddClientMessage(DWORD dwColor, PCHAR szStr); void ResetDialogControls(CDXUTDialog *pGameUI); diff --git a/saco/cmdprocs.cpp b/saco/cmdprocs.cpp index 0ca5640..f94c4d7 100644 --- a/saco/cmdprocs.cpp +++ b/saco/cmdprocs.cpp @@ -9,6 +9,14 @@ extern GAME_SETTINGS tSettings; extern bool bShowDebugLabels; +////////////////////////////////////////////////////// +// +// -------R E L E A S E C O M M A N D S-------- +// +// (INCLUDES SCRIPTING UTILS) +// +////////////////////////////////////////////////////// + void cmdDefaultCmdProc(PCHAR szCmd) { if(pNetGame) { @@ -18,6 +26,8 @@ void cmdDefaultCmdProc(PCHAR szCmd) } } +//---------------------------------------------------- + void cmdTestDeathWindow(PCHAR szCmd) { if(pDeathWindow) { @@ -32,6 +42,8 @@ void cmdTestDeathWindow(PCHAR szCmd) } } +//---------------------------------------------------- + void cmdCameraTargetDebug(PCHAR szCmd) { // TODO: cmdCameraTargetDebug .text:100685E0 @@ -49,7 +61,8 @@ void cmdFontSize(PCHAR szCmd) void cmdNameTagStatus(PCHAR szCmd) { - // TODO: cmdNameTagStatus .text:10068720 + if(pNetGame) + pNetGame->TogglePlayerTagStatus(); } void cmdTimestamp(PCHAR szCmd) @@ -72,11 +85,15 @@ void cmdHudScaleFix(PCHAR szCmd) // TODO: cmdHudScaleFix .text:10068870 } +//---------------------------------------------------- + void cmdMem(PCHAR szCmd) { pChatWindow->AddDebugMessage("Memory: %u",*(DWORD *)0x8A5A80); } +//---------------------------------------------------- + void cmdSetFrameLimit(PCHAR szCmd) { // TODO: cmdSetFrameLimit .text:100688D0 @@ -142,18 +159,22 @@ void cmdToggleObjectLight(PCHAR szCmd) // TODO: cmdToggleObjectLight .text:10069000 } +//---------------------------------------------------- + void cmdDebugLabels(PCHAR szCmd) { bShowDebugLabels = !bShowDebugLabels; } +//---------------------------------------------------- + void cmdRcon(PCHAR szCmd) { // TODO: cmdRcon .text:10069030 } //---------------------------------------------------- - +// MATCH void SetupCommands() { // RELEASE COMMANDS diff --git a/saco/cmdprocs.h b/saco/cmdprocs.h new file mode 100644 index 0000000..e69de29 diff --git a/saco/d3d9/common/DXUTgui.cpp b/saco/d3d9/common/DXUTgui.cpp index ecfb1c7..7353167 100644 --- a/saco/d3d9/common/DXUTgui.cpp +++ b/saco/d3d9/common/DXUTgui.cpp @@ -550,6 +550,29 @@ int CDXUTDialogResourceManager::AddFont( LPCTSTR strFaceName, LONG height, LONG } +//-------------------------------------------------------------------------------------- +int CDXUTDialogResourceManager::SetFont(UINT iFont, LPCTSTR strFaceName, LONG height, LONG weight) +{ + DXUTFontNode* pFontNode = m_FontCache.GetAt(iFont); + if( pFontNode != NULL ) + { + StringCchCopy( pFontNode->strFace, MAX_PATH, strFaceName ); + pFontNode->nHeight = height; + pFontNode->nWeight = weight; + + // If a device is available, try to create immediately + if( m_pd3dDevice ) + CreateFont( iFont ); + + return iFont; + } + else + { + return -1; + } +} + + //-------------------------------------------------------------------------------------- // MATCH HRESULT CDXUTDialog::SetFont( UINT index, LPCTSTR strFaceName, LONG height, LONG weight ) @@ -5650,7 +5673,7 @@ BOOL (APIENTRY * CDXUTIMEEditBox::_VerQueryValueA)( const LPVOID, LPSTR, LPVOID BOOL (APIENTRY * CDXUTIMEEditBox::_GetFileVersionInfoA)( LPSTR, DWORD, DWORD, LPVOID )= CDXUTIMEEditBox::Dummy_GetFileVersionInfoA; DWORD (APIENTRY * CDXUTIMEEditBox::_GetFileVersionInfoSizeA)( LPSTR, LPDWORD ) = CDXUTIMEEditBox::Dummy_GetFileVersionInfoSizeA; -DWORD dwImeWaitTick; +int nImeWaitTick; HINSTANCE CDXUTIMEEditBox::s_hDllImm32; // IMM32 DLL handle HINSTANCE CDXUTIMEEditBox::s_hDllVer; // Version DLL handle @@ -6694,7 +6717,7 @@ bool CDXUTIMEEditBox::MsgProc( UINT uMsg, WPARAM wParam, LPARAM lParam ) s_bHideCaret = false; // Hide reading window s_bShowReadingWindow = false; - dwImeWaitTick = GetTickCount(); + nImeWaitTick = GetTickCount(); break; case WM_IME_NOTIFY: @@ -7811,7 +7834,7 @@ void CDXUTIMEEditBox::Initialize() FARPROC Temp; - dwImeWaitTick = GetTickCount(); + nImeWaitTick = GetTickCount(); s_CompString.SetBufferSize( MAX_COMPSTRING_SIZE ); @@ -7906,6 +7929,18 @@ void CDXUTIMEEditBox::Uninitialize() } +//-------------------------------------------------------------------------------------- +bool CDXUTIMEEditBox::FUNC_100863E0() +{ + if(s_CandList.bShowWindow) return true; + if(s_bShowReadingWindow) return true; + + if(((int)GetTickCount() - nImeWaitTick) < 300) + return true; + return false; +} + + //-------------------------------------------------------------------------------------- // MATCH void DXUTBlendColor::Init( D3DCOLOR defaultColor, D3DCOLOR disabledColor, D3DCOLOR hiddenColor ) diff --git a/saco/d3d9/common/DXUTgui.h b/saco/d3d9/common/DXUTgui.h index a43a99f..16fbb68 100644 --- a/saco/d3d9/common/DXUTgui.h +++ b/saco/d3d9/common/DXUTgui.h @@ -327,6 +327,7 @@ public: bool MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); int AddFont( LPCTSTR strFaceName, LONG height, LONG weight ); + int SetFont(UINT iFont, LPCTSTR strFaceName, LONG height, LONG weight); int AddTexture( LPCTSTR strFilename ); DXUTFontNode* GetFontNode( int iIndex ) { return m_FontCache.GetAt( iIndex ); }; @@ -765,11 +766,12 @@ protected: bool m_bPressed; RECT m_rcButton; - bool field_76; - D3DXCOLOR field_77; + bool field_76; + D3DXCOLOR field_77; public: - void SetColor(D3DXCOLOR c) { field_76 = true; field_77 = c; }; + void SetColor(D3DXCOLOR c) { field_76 = true; field_77 = c; }; + D3DXCOLOR* GetColor() { return &field_77; }; }; @@ -1010,6 +1012,8 @@ public: virtual void RenderComposition( IDirect3DDevice9* pd3dDevice, float fElapsedTime ); virtual void RenderIndicator( IDirect3DDevice9* pd3dDevice, float fElapsedTime ); + static bool FUNC_100863E0(); + protected: static WORD GetLanguage() { return LOWORD( s_hklCurrent ); } static WORD GetPrimaryLanguage() { return PRIMARYLANGID( LOWORD( s_hklCurrent ) ); } diff --git a/saco/d3d9/d3dfont.cpp b/saco/d3d9/d3dfont.cpp new file mode 100644 index 0000000..32831a0 --- /dev/null +++ b/saco/d3d9/d3dfont.cpp @@ -0,0 +1,787 @@ +//----------------------------------------------------------------------------- +// File: D3DFont.cpp +// +// Desc: Texture-based font class +// +// Copyright (c) Microsoft Corporation. All rights reserved. +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include "include/D3DFont.h" +#include "include/DXUtil.h" + + + + +//----------------------------------------------------------------------------- +// Custom vertex types for rendering text +//----------------------------------------------------------------------------- +#define MAX_NUM_VERTICES 50*6 + +struct FONT2DVERTEX { D3DXVECTOR4 p; DWORD color; FLOAT tu, tv; }; +struct FONT3DVERTEX { D3DXVECTOR3 p; D3DXVECTOR3 n; FLOAT tu, tv; }; + +#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1) +#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1) + +inline FONT2DVERTEX InitFont2DVertex( const D3DXVECTOR4& p, D3DCOLOR color, + FLOAT tu, FLOAT tv ) +{ + FONT2DVERTEX v; v.p = p; v.color = color; v.tu = tu; v.tv = tv; + return v; +} + +inline FONT3DVERTEX InitFont3DVertex( const D3DXVECTOR3& p, const D3DXVECTOR3& n, + FLOAT tu, FLOAT tv ) +{ + FONT3DVERTEX v; v.p = p; v.n = n; v.tu = tu; v.tv = tv; + return v; +} + + + + +//----------------------------------------------------------------------------- +// Name: CD3DFont() +// Desc: Font class constructor +//----------------------------------------------------------------------------- +CD3DFont::CD3DFont( const TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags ) +{ + _tcsncpy( m_strFontName, strFontName, sizeof(m_strFontName) / sizeof(TCHAR) ); + m_strFontName[sizeof(m_strFontName) / sizeof(TCHAR) - 1] = _T('\0'); + m_dwFontHeight = dwHeight; + m_dwFontFlags = dwFlags; + m_dwSpacing = 0; + + m_pd3dDevice = NULL; + m_pTexture = NULL; + m_pVB = NULL; + + m_pStateBlockSaved = NULL; + m_pStateBlockDrawText = NULL; +} + + + + +//----------------------------------------------------------------------------- +// Name: ~CD3DFont() +// Desc: Font class destructor +//----------------------------------------------------------------------------- +CD3DFont::~CD3DFont() +{ + InvalidateDeviceObjects(); + DeleteDeviceObjects(); +} + + + + +//----------------------------------------------------------------------------- +// Name: InitDeviceObjects() +// Desc: Initializes device-dependent objects, including the vertex buffer used +// for rendering text and the texture map which stores the font image. +//----------------------------------------------------------------------------- +HRESULT CD3DFont::InitDeviceObjects( LPDIRECT3DDEVICE9 pd3dDevice ) +{ + HRESULT hr; + + // Keep a local copy of the device + m_pd3dDevice = pd3dDevice; + + // Establish the font and texture size + m_fTextScale = 1.0f; // Draw fonts into texture without scaling + + // Large fonts need larger textures + if( m_dwFontHeight > 50 ) + m_dwTexWidth = m_dwTexHeight = 2048; + else if( m_dwFontHeight > 30 ) + m_dwTexWidth = m_dwTexHeight = 1024; + else if( m_dwFontHeight > 10 ) + m_dwTexWidth = m_dwTexHeight = 512; + else + m_dwTexWidth = m_dwTexHeight = 256; + + // If requested texture is too big, use a smaller texture and smaller font, + // and scale up when rendering. + D3DCAPS9 d3dCaps; + m_pd3dDevice->GetDeviceCaps( &d3dCaps ); + + if( m_dwTexWidth > d3dCaps.MaxTextureWidth ) + { + m_fTextScale = (FLOAT)d3dCaps.MaxTextureWidth / (FLOAT)m_dwTexWidth; + m_dwTexWidth = m_dwTexHeight = d3dCaps.MaxTextureWidth; + } + + // Create a new texture for the font + hr = m_pd3dDevice->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1, + 0, D3DFMT_A4R4G4B4, + D3DPOOL_MANAGED, &m_pTexture, NULL ); + if( FAILED(hr) ) + return hr; + + // Prepare to create a bitmap + DWORD* pBitmapBits; + BITMAPINFO bmi; + ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) ); + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = (int)m_dwTexWidth; + bmi.bmiHeader.biHeight = -(int)m_dwTexHeight; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biCompression = BI_RGB; + bmi.bmiHeader.biBitCount = 32; + + // Create a DC and a bitmap for the font + HDC hDC = CreateCompatibleDC( NULL ); + HBITMAP hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS, + (void**)&pBitmapBits, NULL, 0 ); + SetMapMode( hDC, MM_TEXT ); + + // Create a font. By specifying ANTIALIASED_QUALITY, we might get an + // antialiased font, but this is not guaranteed. + INT nHeight = -MulDiv( m_dwFontHeight, + (INT)(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 ); + DWORD dwBold = (m_dwFontFlags&D3DFONT_BOLD) ? FW_BOLD : FW_NORMAL; + DWORD dwItalic = (m_dwFontFlags&D3DFONT_ITALIC) ? TRUE : FALSE; + HFONT hFont = CreateFont( nHeight, 0, 0, 0, dwBold, dwItalic, + FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, + VARIABLE_PITCH, m_strFontName ); + if( NULL==hFont ) + return E_FAIL; + + SelectObject( hDC, hbmBitmap ); + SelectObject( hDC, hFont ); + + // Set text properties + SetTextColor( hDC, RGB(255,255,255) ); + SetBkColor( hDC, 0x00000000 ); + SetTextAlign( hDC, TA_TOP ); + + // Loop through all printable character and output them to the bitmap.. + // Meanwhile, keep track of the corresponding tex coords for each character. + DWORD x = 0; + DWORD y = 0; + BYTE str[2] = _T("x"); + SIZE size; + + // Calculate the spacing between characters based on line height + GetTextExtentPoint32( hDC, TEXT(" "), 1, &size ); + x = m_dwSpacing = (DWORD) ceil(size.cy * 0.25f); + + for( DWORD c=32; c<256; c++ ) + { + str[0] = (BYTE)c; + GetTextExtentPoint32( hDC, (LPCSTR)str, 1, &size ); + + if( (DWORD)(x + size.cx + m_dwSpacing) > m_dwTexWidth ) + { + x = m_dwSpacing; + y += size.cy+1; + } + + ExtTextOut( hDC, x+0, y+0, ETO_OPAQUE, NULL, (LPCSTR)str, 1, NULL ); + + m_fTexCoords[c-32][0] = ((FLOAT)(x + 0 - m_dwSpacing))/m_dwTexWidth; + m_fTexCoords[c-32][1] = ((FLOAT)(y + 0 + 0 ))/m_dwTexHeight; + m_fTexCoords[c-32][2] = ((FLOAT)(x + size.cx + m_dwSpacing))/m_dwTexWidth; + m_fTexCoords[c-32][3] = ((FLOAT)(y + size.cy + 0 ))/m_dwTexHeight; + + x += size.cx + (2 * m_dwSpacing); + } + +#ifdef _DEBUG + + char szBuffer[1024]; + sprintf(szBuffer, "c:\\bmp-%s-%d.bmp", m_strFontName, nHeight); + + FILE *pFile = fopen(szBuffer, "wb"); + + BITMAPFILEHEADER bmfh; + int nBitsOffset = sizeof(BITMAPFILEHEADER) + bmi.bmiHeader.biSize; + LONG lImageSize = m_dwTexWidth * m_dwTexHeight * (bmi.bmiHeader.biBitCount/8); + LONG lFileSize = nBitsOffset + lImageSize; + bmfh.bfType = 'B'+('M'<<8); + bmfh.bfOffBits = nBitsOffset; + bmfh.bfSize = lFileSize; + bmfh.bfReserved1 = bmfh.bfReserved2 = 0; + //Write the bitmap file header + UINT nWrittenFileHeaderSize = fwrite(&bmfh, 1, + sizeof(BITMAPFILEHEADER), pFile); + //And then the bitmap info header + UINT nWrittenInfoHeaderSize = fwrite(&bmi.bmiHeader, + 1, sizeof(BITMAPINFOHEADER), pFile); + //Finally, write the image data itself + //-- the data represents our drawing + UINT nWrittenDIBDataSize = + fwrite(pBitmapBits, 1, lImageSize, pFile); + + fclose(pFile); + +#endif + + // Lock the surface and write the alpha values for the set pixels + D3DLOCKED_RECT d3dlr; + m_pTexture->LockRect( 0, &d3dlr, 0, 0 ); + BYTE* pDstRow = (BYTE*)d3dlr.pBits; + WORD* pDst16; + BYTE bAlpha; // 4-bit measure of pixel intensity + + for( y=0; y < m_dwTexHeight; y++ ) + { + pDst16 = (WORD*)pDstRow; + for( x=0; x < m_dwTexWidth; x++ ) + { + bAlpha = (BYTE)((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 4); + if (bAlpha > 0) + { + *pDst16++ = (WORD) ((bAlpha << 12) | 0x0fff); + } + else + { + *pDst16++ = 0x0000; + } + } + pDstRow += d3dlr.Pitch; + } + + // Done updating texture, so clean up used objects + m_pTexture->UnlockRect(0); + DeleteObject( hbmBitmap ); + DeleteDC( hDC ); + DeleteObject( hFont ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: RestoreDeviceObjects() +// Desc: +//----------------------------------------------------------------------------- +HRESULT CD3DFont::RestoreDeviceObjects() +{ + HRESULT hr; + + // Create vertex buffer for the letters + int vertexSize = max( sizeof(FONT2DVERTEX), sizeof(FONT3DVERTEX ) ); + if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( MAX_NUM_VERTICES * vertexSize, + D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0, + D3DPOOL_DEFAULT, &m_pVB, NULL ) ) ) + { + return hr; + } + + // Create the state blocks for rendering text + for( UINT which=0; which<2; which++ ) + { + m_pd3dDevice->BeginStateBlock(); + m_pd3dDevice->SetTexture( 0, m_pTexture ); + + if ( D3DFONT_ZENABLE & m_dwFontFlags ) + m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); + else + m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); + + m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); + m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); + m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); + m_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE ); + m_pd3dDevice->SetRenderState( D3DRS_ALPHAREF, 0x08 ); + m_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL ); + m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); + m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW ); + m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE, FALSE ); + m_pd3dDevice->SetRenderState( D3DRS_CLIPPING, TRUE ); + m_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, FALSE ); + m_pd3dDevice->SetRenderState( D3DRS_VERTEXBLEND, D3DVBF_DISABLE ); + m_pd3dDevice->SetRenderState( D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE ); + m_pd3dDevice->SetRenderState( D3DRS_FOGENABLE, FALSE ); + m_pd3dDevice->SetRenderState( D3DRS_COLORWRITEENABLE, + D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | + D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA ); + m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); + m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); + m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); + m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE ); + m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); + m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); + m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0 ); + m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE ); + m_pd3dDevice->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE ); + m_pd3dDevice->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE ); + m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT ); + m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT ); + m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE ); + + if( which==0 ) + m_pd3dDevice->EndStateBlock( &m_pStateBlockSaved ); + else + m_pd3dDevice->EndStateBlock( &m_pStateBlockDrawText ); + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: InvalidateDeviceObjects() +// Desc: Destroys all device-dependent objects +//----------------------------------------------------------------------------- +HRESULT CD3DFont::InvalidateDeviceObjects() +{ + SAFE_RELEASE( m_pVB ); + SAFE_RELEASE( m_pStateBlockSaved ); + SAFE_RELEASE( m_pStateBlockDrawText ); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DeleteDeviceObjects() +// Desc: Destroys all device-dependent objects +//----------------------------------------------------------------------------- +HRESULT CD3DFont::DeleteDeviceObjects() +{ + SAFE_RELEASE( m_pTexture ); + m_pd3dDevice = NULL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: GetTextExtent() +// Desc: Get the dimensions of a text string +//----------------------------------------------------------------------------- +HRESULT CD3DFont::GetTextExtent( const TCHAR* strText, SIZE* pSize ) +{ + if( NULL==strText || NULL==pSize ) + return E_FAIL; + + FLOAT fRowWidth = 0.0f; + FLOAT fRowHeight = (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight; + FLOAT fWidth = 0.0f; + FLOAT fHeight = fRowHeight; + + while( *strText ) + { + BYTE c = *(BYTE*)strText++; + + if( c == _T('\n') ) + { + fRowWidth = 0.0f; + fHeight += fRowHeight; + } + + if( (c-32) < 0 || (c-32) >= 256-32 ) + continue; + + FLOAT tx1 = m_fTexCoords[c-32][0]; + FLOAT tx2 = m_fTexCoords[c-32][2]; + + fRowWidth += (tx2-tx1)*m_dwTexWidth - 2*m_dwSpacing; + + if( fRowWidth > fWidth ) + fWidth = fRowWidth; + } + + pSize->cx = (int)fWidth; + pSize->cy = (int)fHeight; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DrawTextScaled() +// Desc: Draws scaled 2D text. Note that x and y are in viewport coordinates +// (ranging from -1 to +1). fXScale and fYScale are the size fraction +// relative to the entire viewport. For example, a fXScale of 0.25 is +// 1/8th of the screen width. This allows you to output text at a fixed +// fraction of the viewport, even if the screen or window size changes. +//----------------------------------------------------------------------------- +HRESULT CD3DFont::DrawTextScaled( FLOAT x, FLOAT y, FLOAT z, + FLOAT fXScale, FLOAT fYScale, DWORD dwColor, + const TCHAR* strText, DWORD dwFlags ) +{ + if( m_pd3dDevice == NULL ) + return E_FAIL; + + // Set up renderstate + m_pStateBlockSaved->Capture(); + m_pStateBlockDrawText->Apply(); + m_pd3dDevice->SetFVF( D3DFVF_FONT2DVERTEX ); + m_pd3dDevice->SetPixelShader( NULL ); + m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) ); + + // Set filter states + if( dwFlags & D3DFONT_FILTERED ) + { + m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); + m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); + } + + D3DVIEWPORT9 vp; + m_pd3dDevice->GetViewport( &vp ); + FLOAT fLineHeight = ( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight; + + // Center the text block in the viewport + if( dwFlags & D3DFONT_CENTERED_X ) + { + const BYTE* strTextTmp = (BYTE*)strText; + float xFinal = 0.0f; + + while( *strTextTmp ) + { + BYTE c = *strTextTmp++; + + if( c == _T('\n') ) + break; // Isn't supported. + if( (c-32) < 0 || (c-32) >= 256-32 ) + continue; + + FLOAT tx1 = m_fTexCoords[c-32][0]; + FLOAT tx2 = m_fTexCoords[c-32][2]; + + FLOAT w = (tx2-tx1)*m_dwTexWidth; + + w *= (fXScale*vp.Height)/fLineHeight; + + xFinal += w - (2 * m_dwSpacing) * (fXScale*vp.Height)/fLineHeight; + } + + x = -xFinal/vp.Width; + } + if( dwFlags & D3DFONT_CENTERED_Y ) + { + y = -fLineHeight/vp.Height; + } + + FLOAT sx = (x+1.0f)*vp.Width/2; + FLOAT sy = (y+1.0f)*vp.Height/2; + FLOAT sz = z; + FLOAT rhw = 1.0f; + + // Adjust for character spacing + sx -= m_dwSpacing * (fXScale*vp.Height)/fLineHeight; + FLOAT fStartX = sx; + + // Fill vertex buffer + FONT2DVERTEX* pVertices; + DWORD dwNumTriangles = 0L; + m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); + + while( *strText ) + { + BYTE c = *(BYTE*)strText++; + + if( c == _T('\n') ) + { + sx = fStartX; + sy += fYScale*vp.Height; + } + + if( (c-32) < 0 || (c-32) >= 256-32 ) + continue; + + FLOAT tx1 = m_fTexCoords[c-32][0]; + FLOAT ty1 = m_fTexCoords[c-32][1]; + FLOAT tx2 = m_fTexCoords[c-32][2]; + FLOAT ty2 = m_fTexCoords[c-32][3]; + + FLOAT w = (tx2-tx1)*m_dwTexWidth; + FLOAT h = (ty2-ty1)*m_dwTexHeight; + + w *= (fXScale*vp.Height)/fLineHeight; + h *= (fYScale*vp.Height)/fLineHeight; + + if( c != _T(' ') ) + { + *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx1, ty2 ); + *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 ); + *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 ); + *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx2, ty1 ); + *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,sz,rhw), dwColor, tx2, ty2 ); + *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,sz,rhw), dwColor, tx1, ty1 ); + dwNumTriangles += 2; + + if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) ) + { + // Unlock, render, and relock the vertex buffer + m_pVB->Unlock(); + m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); + m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); + dwNumTriangles = 0L; + } + } + + sx += w - (2 * m_dwSpacing) * (fXScale*vp.Height)/fLineHeight; + } + + // Unlock and render the vertex buffer + m_pVB->Unlock(); + if( dwNumTriangles > 0 ) + m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); + + // Restore the modified renderstates + m_pStateBlockSaved->Apply(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DrawText() +// Desc: Draws 2D text. Note that sx and sy are in pixels +//----------------------------------------------------------------------------- +HRESULT CD3DFont::DrawText( FLOAT sx, FLOAT sy, DWORD dwColor, + const TCHAR* strText, DWORD dwFlags ) +{ + if( m_pd3dDevice == NULL ) + return E_FAIL; + + // Setup renderstate + m_pStateBlockSaved->Capture(); + m_pStateBlockDrawText->Apply(); + m_pd3dDevice->SetFVF( D3DFVF_FONT2DVERTEX ); + m_pd3dDevice->SetPixelShader( NULL ); + m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) ); + + // Set filter states + if( dwFlags & D3DFONT_FILTERED ) + { + m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); + m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); + } + + // Center the text block in the viewport + if( dwFlags & D3DFONT_CENTERED_X ) + { + D3DVIEWPORT9 vp; + m_pd3dDevice->GetViewport( &vp ); + const BYTE* strTextTmp = (BYTE*)strText; + float xFinal = 0.0f; + + while( *strTextTmp ) + { + BYTE c = *(BYTE*)strTextTmp++; + + if( c == _T('\n') ) + break; // Isn't supported. + if( (c-32) < 0 || (c-32) >= 256-32 ) + continue; + + FLOAT tx1 = m_fTexCoords[c-32][0]; + FLOAT tx2 = m_fTexCoords[c-32][2]; + + FLOAT w = (tx2-tx1) * m_dwTexWidth / m_fTextScale; + + xFinal += w - (2 * m_dwSpacing); + } + + sx = (vp.Width-xFinal)/2.0f; + } + if( dwFlags & D3DFONT_CENTERED_Y ) + { + D3DVIEWPORT9 vp; + m_pd3dDevice->GetViewport( &vp ); + float fLineHeight = ((m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight); + sy = (vp.Height-fLineHeight)/2; + } + + // Adjust for character spacing + sx -= m_dwSpacing; + FLOAT fStartX = sx; + + // Fill vertex buffer + FONT2DVERTEX* pVertices = NULL; + DWORD dwNumTriangles = 0; + m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); + + while( *strText ) + { + BYTE c = *(BYTE*)strText++; + + if( c == _T('\n') ) + { + sx = fStartX; + sy += (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight; + } + + if( (c-32) < 0 || (c-32) >= 256-32 ) + continue; + + FLOAT tx1 = m_fTexCoords[c-32][0]; + FLOAT ty1 = m_fTexCoords[c-32][1]; + FLOAT tx2 = m_fTexCoords[c-32][2]; + FLOAT ty2 = m_fTexCoords[c-32][3]; + + FLOAT w = (tx2-tx1) * m_dwTexWidth / m_fTextScale; + FLOAT h = (ty2-ty1) * m_dwTexHeight / m_fTextScale; + + if( c != _T(' ') ) + { + *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx1, ty2 ); + *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 ); + *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 ); + *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx2, ty1 ); + *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+w-0.5f,sy+h-0.5f,0.9f,1.0f), dwColor, tx2, ty2 ); + *pVertices++ = InitFont2DVertex( D3DXVECTOR4(sx+0-0.5f,sy+0-0.5f,0.9f,1.0f), dwColor, tx1, ty1 ); + dwNumTriangles += 2; + + if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) ) + { + // Unlock, render, and relock the vertex buffer + m_pVB->Unlock(); + m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); + pVertices = NULL; + m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); + dwNumTriangles = 0L; + } + } + + sx += w - (2 * m_dwSpacing); + } + + // Unlock and render the vertex buffer + m_pVB->Unlock(); + if( dwNumTriangles > 0 ) + m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); + + // Restore the modified renderstates + m_pStateBlockSaved->Apply(); + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: Render3DText() +// Desc: Renders 3D text +//----------------------------------------------------------------------------- +HRESULT CD3DFont::Render3DText( const TCHAR* strText, DWORD dwFlags ) +{ + if( m_pd3dDevice == NULL ) + return E_FAIL; + + // Setup renderstate + m_pStateBlockSaved->Capture(); + m_pStateBlockDrawText->Apply(); + m_pd3dDevice->SetFVF( D3DFVF_FONT3DVERTEX ); + m_pd3dDevice->SetPixelShader( NULL ); + m_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(FONT3DVERTEX) ); + + // Set filter states + if( dwFlags & D3DFONT_FILTERED ) + { + m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); + m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); + } + + // Position for each text element + FLOAT x = 0.0f; + FLOAT y = 0.0f; + + // Center the text block at the origin (not the viewport) + if( dwFlags & D3DFONT_CENTERED_X ) + { + SIZE sz; + GetTextExtent( strText, &sz ); + x = -(((FLOAT)sz.cx)/10.0f)/2.0f; + } + if( dwFlags & D3DFONT_CENTERED_Y ) + { + SIZE sz; + GetTextExtent( strText, &sz ); + y = -(((FLOAT)sz.cy)/10.0f)/2.0f; + } + + // Turn off culling for two-sided text + if( dwFlags & D3DFONT_TWOSIDED ) + m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); + + // Adjust for character spacing + x -= m_dwSpacing / 10.0f; + FLOAT fStartX = x; + BYTE c; + + // Fill vertex buffer + FONT3DVERTEX* pVertices; + DWORD dwNumTriangles = 0L; + m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); + + while( (c = *(BYTE*)strText++) != 0 ) + { + if( c == '\n' ) + { + x = fStartX; + y -= (m_fTexCoords[0][3]-m_fTexCoords[0][1])*m_dwTexHeight/10.0f; + } + + if( (c-32) < 0 || (c-32) >= 256-32 ) + continue; + + FLOAT tx1 = m_fTexCoords[c-32][0]; + FLOAT ty1 = m_fTexCoords[c-32][1]; + FLOAT tx2 = m_fTexCoords[c-32][2]; + FLOAT ty2 = m_fTexCoords[c-32][3]; + + FLOAT w = (tx2-tx1) * m_dwTexWidth / ( 10.0f * m_fTextScale ); + FLOAT h = (ty2-ty1) * m_dwTexHeight / ( 10.0f * m_fTextScale ); + + if( c != _T(' ') ) + { + *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+0,0), D3DXVECTOR3(0,0,-1), tx1, ty2 ); + *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 ); + *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 ); + *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+h,0), D3DXVECTOR3(0,0,-1), tx2, ty1 ); + *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+w,y+0,0), D3DXVECTOR3(0,0,-1), tx2, ty2 ); + *pVertices++ = InitFont3DVertex( D3DXVECTOR3(x+0,y+h,0), D3DXVECTOR3(0,0,-1), tx1, ty1 ); + dwNumTriangles += 2; + + if( dwNumTriangles*3 > (MAX_NUM_VERTICES-6) ) + { + // Unlock, render, and relock the vertex buffer + m_pVB->Unlock(); + m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); + m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD ); + dwNumTriangles = 0L; + } + } + + x += w - (2 * m_dwSpacing) / 10.0f; + } + + // Unlock and render the vertex buffer + m_pVB->Unlock(); + if( dwNumTriangles > 0 ) + m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles ); + + // Restore the modified renderstates + m_pStateBlockSaved->Apply(); + + return S_OK; +} + + + + diff --git a/saco/d3d9/d3dutil.cpp b/saco/d3d9/d3dutil.cpp new file mode 100644 index 0000000..4e7c347 --- /dev/null +++ b/saco/d3d9/d3dutil.cpp @@ -0,0 +1,311 @@ +//----------------------------------------------------------------------------- +// File: D3DUtil.cpp +// +// Desc: Shortcut macros and functions for using DirectX objects +// +// Copyright (c) Microsoft Corporation. All rights reserved +//----------------------------------------------------------------------------- + +#define D3D_OVERLOADS +#include +#include "include/D3DUtil.h" + +#ifndef _T +#define _T TEXT +#endif + +//----------------------------------------------------------------------------- +// Name: D3DUtil_GetDXSDKMediaPath() +// Desc: Returns the DirectX SDK media path, as stored in the system registry +// during the SDK install. +//----------------------------------------------------------------------------- +// MATCH +const TCHAR* D3DUtil_GetDXSDKMediaPath() +{ + static TCHAR strNull[2] = _T(""); + static TCHAR strPath[MAX_PATH + 20]; + HKEY hKey; + DWORD type, size=MAX_PATH; + + // Open the appropriate registry key + LONG result = RegOpenKeyEx( HKEY_LOCAL_MACHINE, + _T("Software\\Microsoft\\DirectX SDK"), + 0, KEY_READ, &hKey ); + if( ERROR_SUCCESS != result ) + return strNull; + + result = RegQueryValueEx( hKey, _T("DX9S4SDK Samples Path"), NULL, + &type, (BYTE*)strPath, &size ); + + if( ERROR_SUCCESS != result ) + { + result = RegQueryValueEx( hKey, _T("DX81SDK Samples Path"), NULL, + &type, (BYTE*)strPath, &size ); + + if( ERROR_SUCCESS != result ) + { + result = RegQueryValueEx( hKey, _T("DX8SDK Samples Path"), NULL, + &type, (BYTE*)strPath, &size ); + + if( ERROR_SUCCESS != result ) + { + RegCloseKey( hKey ); + return strNull; + } + } + } + + RegCloseKey( hKey ); + lstrcat( strPath, _T("\\D3DIM\\Media\\") ); + + return strPath; +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_InitSurfaceDesc() +// Desc: Helper function called to build a DDSURFACEDESC2 structure, +// typically before calling CreateSurface() or GetSurfaceDesc() +//----------------------------------------------------------------------------- +// MATCH +VOID D3DUtil_InitSurfaceDesc( DDSURFACEDESC2& ddsd, DWORD dwFlags, + DWORD dwCaps ) +{ + ZeroMemory( &ddsd, sizeof(ddsd) ); + ddsd.dwSize = sizeof(ddsd); + ddsd.dwFlags = dwFlags; + ddsd.ddsCaps.dwCaps = dwCaps; + ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_InitMaterial() +// Desc: Helper function called to build a D3DMATERIAL7 structure +//----------------------------------------------------------------------------- +VOID D3DUtil_InitMaterial( D3DMATERIAL7& mtrl, FLOAT r, FLOAT g, FLOAT b, + FLOAT a ) +{ + ZeroMemory( &mtrl, sizeof(D3DMATERIAL7) ); + mtrl.dcvDiffuse.r = mtrl.dcvAmbient.r = r; + mtrl.dcvDiffuse.g = mtrl.dcvAmbient.g = g; + mtrl.dcvDiffuse.b = mtrl.dcvAmbient.b = b; + mtrl.dcvDiffuse.a = mtrl.dcvAmbient.a = a; +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_InitLight() +// Desc: Initializes a D3DLIGHT7 structure +//----------------------------------------------------------------------------- +VOID D3DUtil_InitLight( D3DLIGHT7& light, D3DLIGHTTYPE ltType, + FLOAT x, FLOAT y, FLOAT z ) +{ + ZeroMemory( &light, sizeof(D3DLIGHT7) ); + light.dltType = ltType; + light.dcvDiffuse.r = 1.0f; + light.dcvDiffuse.g = 1.0f; + light.dcvDiffuse.b = 1.0f; + light.dcvSpecular = light.dcvDiffuse; + light.dvPosition.x = light.dvDirection.x = x; + light.dvPosition.y = light.dvDirection.y = y; + light.dvPosition.z = light.dvDirection.z = z; + light.dvAttenuation0 = 1.0f; + light.dvRange = D3DLIGHT_RANGE_MAX; +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetViewMatrix() +// Desc: Given an eye point, a lookat point, and an up vector, this +// function builds a 4x4 view matrix. +//----------------------------------------------------------------------------- +// MATCH +HRESULT D3DUtil_SetViewMatrix( D3DMATRIX& mat, D3DVECTOR& vFrom, + D3DVECTOR& vAt, D3DVECTOR& vWorldUp ) +{ + // Get the z basis vector, which points straight ahead. This is the + // difference from the eyepoint to the lookat point. + D3DVECTOR vView = vAt - vFrom; + + FLOAT fLength = Magnitude( vView ); + if( fLength < 1e-6f ) + return E_INVALIDARG; + + // Normalize the z basis vector + vView /= fLength; + + // Get the dot product, and calculate the projection of the z basis + // vector onto the up vector. The projection is the y basis vector. + FLOAT fDotProduct = DotProduct( vWorldUp, vView ); + + D3DVECTOR vUp = vWorldUp - fDotProduct * vView; + + // If this vector has near-zero length because the input specified a + // bogus up vector, let's try a default up vector + if( 1e-6f > ( fLength = Magnitude( vUp ) ) ) + { + vUp = D3DVECTOR( 0.0f, 1.0f, 0.0f ) - vView.y * vView; + + // If we still have near-zero length, resort to a different axis. + if( 1e-6f > ( fLength = Magnitude( vUp ) ) ) + { + vUp = D3DVECTOR( 0.0f, 0.0f, 1.0f ) - vView.z * vView; + + if( 1e-6f > ( fLength = Magnitude( vUp ) ) ) + return E_INVALIDARG; + } + } + + // Normalize the y basis vector + vUp /= fLength; + + // The x basis vector is found simply with the cross product of the y + // and z basis vectors + D3DVECTOR vRight = CrossProduct( vUp, vView ); + + // Start building the matrix. The first three rows contains the basis + // vectors used to rotate the view to point at the lookat point + D3DUtil_SetIdentityMatrix( mat ); + mat._11 = vRight.x; mat._12 = vUp.x; mat._13 = vView.x; + mat._21 = vRight.y; mat._22 = vUp.y; mat._23 = vView.y; + mat._31 = vRight.z; mat._32 = vUp.z; mat._33 = vView.z; + + // Do the translation values (rotations are still about the eyepoint) + mat._41 = - DotProduct( vFrom, vRight ); + mat._42 = - DotProduct( vFrom, vUp ); + mat._43 = - DotProduct( vFrom, vView ); + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetProjectionMatrix() +// Desc: Sets the passed in 4x4 matrix to a perpsective projection matrix built +// from the field-of-view (fov, in y), aspect ratio, near plane (D), +// and far plane (F). Note that the projection matrix is normalized for +// element [3][4] to be 1.0. This is performed so that W-based range fog +// will work correctly. +//----------------------------------------------------------------------------- +// MATCH +HRESULT D3DUtil_SetProjectionMatrix( D3DMATRIX& mat, FLOAT fFOV, FLOAT fAspect, + FLOAT fNearPlane, FLOAT fFarPlane ) +{ + if( fabs(fFarPlane-fNearPlane) < 0.01f ) + return E_INVALIDARG; + if( fabs(sin(fFOV/2)) < 0.01f ) + return E_INVALIDARG; + + FLOAT w = fAspect * ( cosf(fFOV/2)/sinf(fFOV/2) ); + FLOAT h = 1.0f * ( cosf(fFOV/2)/sinf(fFOV/2) ); + FLOAT Q = fFarPlane / ( fFarPlane - fNearPlane ); + + ZeroMemory( &mat, sizeof(D3DMATRIX) ); + mat._11 = w; + mat._22 = h; + mat._33 = Q; + mat._34 = 1.0f; + mat._43 = -Q*fNearPlane; + + return S_OK; +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetRotateXMatrix() +// Desc: Create Rotation matrix about X axis +//----------------------------------------------------------------------------- +// MATCH +VOID D3DUtil_SetRotateXMatrix( D3DMATRIX& mat, FLOAT fRads ) +{ + D3DUtil_SetIdentityMatrix( mat ); + mat._22 = cosf( fRads ); + mat._23 = sinf( fRads ); + mat._32 = -sinf( fRads ); + mat._33 = cosf( fRads ); +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetRotateYMatrix() +// Desc: Create Rotation matrix about Y axis +//----------------------------------------------------------------------------- +// MATCH +VOID D3DUtil_SetRotateYMatrix( D3DMATRIX& mat, FLOAT fRads ) +{ + D3DUtil_SetIdentityMatrix( mat ); + mat._11 = cosf( fRads ); + mat._13 = -sinf( fRads ); + mat._31 = sinf( fRads ); + mat._33 = cosf( fRads ); +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetRotateZMatrix() +// Desc: Create Rotation matrix about Z axis +//----------------------------------------------------------------------------- +// MATCH +VOID D3DUtil_SetRotateZMatrix( D3DMATRIX& mat, FLOAT fRads ) +{ + D3DUtil_SetIdentityMatrix( mat ); + mat._11 = cosf( fRads ); + mat._12 = sinf( fRads ); + mat._21 = -sinf( fRads ); + mat._22 = cosf( fRads ); +} + + +//----------------------------------------------------------------------------- +// Name: D3DUtil_SetRotationMatrix +// Desc: Create a Rotation matrix about vector direction +//----------------------------------------------------------------------------- +// MATCH +VOID D3DUtil_SetRotationMatrix( D3DMATRIX& mat, D3DVECTOR& vDir, FLOAT fRads ) +{ + FLOAT fCos = cosf( fRads ); + FLOAT fSin = sinf( fRads ); + D3DVECTOR v = Normalize( vDir ); + + mat._11 = ( v.x * v.x ) * ( 1.0f - fCos ) + fCos; + mat._12 = ( v.x * v.y ) * ( 1.0f - fCos ) - (v.z * fSin); + mat._13 = ( v.x * v.z ) * ( 1.0f - fCos ) + (v.y * fSin); + + mat._21 = ( v.y * v.x ) * ( 1.0f - fCos ) + (v.z * fSin); + mat._22 = ( v.y * v.y ) * ( 1.0f - fCos ) + fCos ; + mat._23 = ( v.y * v.z ) * ( 1.0f - fCos ) - (v.x * fSin); + + mat._31 = ( v.z * v.x ) * ( 1.0f - fCos ) - (v.y * fSin); + mat._32 = ( v.z * v.y ) * ( 1.0f - fCos ) + (v.x * fSin); + mat._33 = ( v.z * v.z ) * ( 1.0f - fCos ) + fCos; + + mat._14 = mat._24 = mat._34 = 0.0f; + mat._41 = mat._42 = mat._43 = 0.0f; + mat._44 = 1.0f; +} + + +//----------------------------------------------------------------------------- +// Name: _DbgOut() +// Desc: Outputs a message to the debug stream +//----------------------------------------------------------------------------- +// MATCH +HRESULT _DbgOut( CHAR* strFile, DWORD dwLine, HRESULT hr, TCHAR* strMsg ) +{ + TCHAR buffer[256]; + wsprintf( buffer, _T("%hs(%ld): "), strFile, dwLine ); + OutputDebugString( buffer ); + OutputDebugString( strMsg ); + + if( hr != (HRESULT) S_OK ) + { + wsprintf( buffer, _T("(hr=%08lx)\n"), hr ); + OutputDebugString( buffer ); + } + + OutputDebugString( _T("\n") ); + + return hr; +} + diff --git a/saco/d3d9/dxutil.cpp b/saco/d3d9/dxutil.cpp new file mode 100644 index 0000000..72e1e79 --- /dev/null +++ b/saco/d3d9/dxutil.cpp @@ -0,0 +1,1381 @@ +//----------------------------------------------------------------------------- +// File: DXUtil.cpp +// +// Desc: Shortcut macros and functions for using DX objects +// +// Copyright (c) Microsoft Corporation. All rights reserved +//----------------------------------------------------------------------------- +#define STRICT +#include +#include +#include +#include +#include +#include +#include +#include "include/dxutil.h" + +#ifdef UNICODE + typedef HINSTANCE (WINAPI* LPShellExecute)(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd); +#else + typedef HINSTANCE (WINAPI* LPShellExecute)(HWND hwnd, LPCSTR lpOperation, LPCSTR lpFile, LPCSTR lpParameters, LPCSTR lpDirectory, INT nShowCmd); +#endif + +bool DXUtil_FindMediaSearchParentDirs( TCHAR* strSearchPath, int cchSearch, TCHAR* strStartAt, TCHAR* strLeafName ); +bool DXUtil_FindMediaSearchTypicalDirs( TCHAR* strSearchPath, int cchSearch, LPCTSTR strLeaf, TCHAR* strExePath, TCHAR* strExeName, TCHAR* strMediaDir ); + + +#ifndef UNDER_CE +//----------------------------------------------------------------------------- +// Name: DXUtil_GetDXSDKMediaPathCch() +// Desc: Returns the DirectX SDK media path +// cchDest is the size in TCHARs of strDest. Be careful not to +// pass in sizeof(strDest) on UNICODE builds. +//----------------------------------------------------------------------------- +HRESULT DXUtil_GetDXSDKMediaPathCch( TCHAR* strDest, int cchDest ) +{ + if( strDest == NULL || cchDest < 1 ) + return E_INVALIDARG; + + lstrcpy( strDest, TEXT("") ); + + // Open the appropriate registry key + HKEY hKey; + LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, + _T("Software\\Microsoft\\DirectX SDK"), + 0, KEY_READ, &hKey ); + if( ERROR_SUCCESS != lResult ) + return E_FAIL; + + DWORD dwType; + DWORD dwSize = cchDest * sizeof(TCHAR); + lResult = RegQueryValueEx( hKey, _T("DX9S4SDK Samples Path"), NULL, + &dwType, (BYTE*)strDest, &dwSize ); + strDest[cchDest-1] = 0; // RegQueryValueEx doesn't NULL term if buffer too small + RegCloseKey( hKey ); + + if( ERROR_SUCCESS != lResult ) + return E_FAIL; + + const TCHAR* strMedia = _T("\\Media\\"); + if( lstrlen(strDest) + lstrlen(strMedia) < cchDest ) + _tcscat( strDest, strMedia ); + else + return E_INVALIDARG; + + return S_OK; +} +#endif // !UNDER_CE + + + +#ifndef UNDER_CE +//----------------------------------------------------------------------------- +// Name: DXUtil_FindMediaFileCch() +// Desc: Trys to find the location of a SDK media file +// cchDest is the size in TCHARs of strDestPath. Be careful not to +// pass in sizeof(strDest) on UNICODE builds. +//----------------------------------------------------------------------------- +HRESULT DXUtil_FindMediaFileCch( TCHAR* strDestPath, int cchDest, LPCTSTR strFilename ) +{ + bool bFound; + TCHAR strSearchFor[MAX_PATH]; + + if( NULL==strFilename || strFilename[0] == 0 || NULL==strDestPath || cchDest < 10 ) + return E_INVALIDARG; + + // Get the DirectX SDK's media dir if the SDK is installed + TCHAR strMediaDir[MAX_PATH] = {0}; + DXUtil_GetDXSDKMediaPathCch( strMediaDir, MAX_PATH ); + + // Get the exe name, and exe path + TCHAR strExePath[MAX_PATH] = {0}; + TCHAR strExeName[MAX_PATH] = {0}; + TCHAR* strLastSlash = NULL; + GetModuleFileName( NULL, strExePath, MAX_PATH ); + strExePath[MAX_PATH-1]=0; + strLastSlash = _tcsrchr( strExePath, TEXT('\\') ); + if( strLastSlash ) + { + lstrcpyn( strExeName, &strLastSlash[1], MAX_PATH ); + + // Chop the exe name from the exe path + *strLastSlash = 0; + + // Chop the .exe from the exe name + strLastSlash = _tcsrchr( strExeName, TEXT('.') ); + if( strLastSlash ) + *strLastSlash = 0; + } + + // Typical directories: + // .\ + // ..\ + // ..\..\ + // %EXE_DIR%\ + // %EXE_DIR%\..\ + // %EXE_DIR%\..\..\ + // %EXE_DIR%\..\%EXE_NAME% + // %EXE_DIR%\..\..\%EXE_NAME% + // DXSDK media path + + // Typical directory search + bFound = DXUtil_FindMediaSearchTypicalDirs( strDestPath, cchDest, strFilename, strExePath, strExeName, strMediaDir ); + if( bFound ) + return S_OK; + + // Typical directory search again, but also look in a subdir called "\media\" + _sntprintf( strSearchFor, MAX_PATH, TEXT("media\\%s"), strFilename ); strSearchFor[MAX_PATH-1] = 0; + bFound = DXUtil_FindMediaSearchTypicalDirs( strDestPath, cchDest, strSearchFor, strExePath, strExeName, strMediaDir ); + if( bFound ) + return S_OK; + + TCHAR strLeafName[MAX_PATH] = {0}; + + // Search all parent directories starting at .\ and using strFilename as the leaf name + _tcsncpy( strLeafName, strFilename, MAX_PATH ); strLeafName[MAX_PATH-1] = 0; + bFound = DXUtil_FindMediaSearchParentDirs( strDestPath, cchDest, TEXT("."), strLeafName ); + if( bFound ) + return S_OK; + + // Search all parent directories starting at the exe's dir and using strFilename as the leaf name + bFound = DXUtil_FindMediaSearchParentDirs( strDestPath, cchDest, strExePath, strLeafName ); + if( bFound ) + return S_OK; + + // Search all parent directories starting at .\ and using "media\strFilename" as the leaf name + _sntprintf( strLeafName, MAX_PATH, TEXT("media\\%s"), strFilename ); strLeafName[MAX_PATH-1] = 0; + bFound = DXUtil_FindMediaSearchParentDirs( strDestPath, cchDest, TEXT("."), strLeafName ); + if( bFound ) + return S_OK; + + // Search all parent directories starting at the exe's dir and using "media\strFilename" as the leaf name + bFound = DXUtil_FindMediaSearchParentDirs( strDestPath, cchDest, strExePath, strLeafName ); + if( bFound ) + return S_OK; + + // On failure, return the file as the path but also return an error code + _tcsncpy( strDestPath, strFilename, cchDest ); + strDestPath[cchDest-1] = 0; + + return E_FAIL; +} + + + +//-------------------------------------------------------------------------------------- +// Search a set of typical directories +//-------------------------------------------------------------------------------------- +// MATCH +bool DXUtil_FindMediaSearchTypicalDirs( TCHAR* strSearchPath, int cchSearch, LPCTSTR strLeaf, + TCHAR* strExePath, TCHAR* strExeName, TCHAR* strMediaDir ) +{ + // Typical directories: + // .\ + // ..\ + // ..\..\ + // %EXE_DIR%\ + // %EXE_DIR%\..\ + // %EXE_DIR%\..\..\ + // %EXE_DIR%\..\%EXE_NAME% + // %EXE_DIR%\..\..\%EXE_NAME% + // DXSDK media path + + // Search in .\ + _tcsncpy( strSearchPath, strLeaf, cchSearch ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in ..\ + _sntprintf( strSearchPath, cchSearch, TEXT("..\\%s"), strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in ..\..\ + _sntprintf( strSearchPath, cchSearch, TEXT("..\\..\\%s"), strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in ..\..\ + _sntprintf( strSearchPath, cchSearch, TEXT("..\\..\\%s"), strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in the %EXE_DIR%\ + _sntprintf( strSearchPath, cchSearch, TEXT("%s\\%s"), strExePath, strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in the %EXE_DIR%\..\ + _sntprintf( strSearchPath, cchSearch, TEXT("%s\\..\\%s"), strExePath, strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in the %EXE_DIR%\..\..\ + _sntprintf( strSearchPath, cchSearch, TEXT("%s\\..\\..\\%s"), strExePath, strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in "%EXE_DIR%\..\%EXE_NAME%\". This matches the DirectX SDK layout + _sntprintf( strSearchPath, cchSearch, TEXT("%s\\..\\%s\\%s"), strExePath, strExeName, strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in "%EXE_DIR%\..\..\%EXE_NAME%\". This matches the DirectX SDK layout + _sntprintf( strSearchPath, cchSearch, TEXT("%s\\..\\..\\%s\\%s"), strExePath, strExeName, strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + // Search in DirectX SDK's media dir + _sntprintf( strSearchPath, cchSearch, TEXT("%s%s"), strMediaDir, strLeaf ); strSearchPath[cchSearch-1] = 0; + if( GetFileAttributes( strSearchPath ) != 0xFFFFFFFF ) + return true; + + return false; +} + + + +//-------------------------------------------------------------------------------------- +// Search parent directories starting at strStartAt, and appending strLeafName +// at each parent directory. It stops at the root directory. +//-------------------------------------------------------------------------------------- +// MATCH +bool DXUtil_FindMediaSearchParentDirs( TCHAR* strSearchPath, int cchSearch, TCHAR* strStartAt, TCHAR* strLeafName ) +{ + TCHAR strFullPath[MAX_PATH] = {0}; + TCHAR strFullFileName[MAX_PATH] = {0}; + TCHAR strSearch[MAX_PATH] = {0}; + TCHAR* strFilePart = NULL; + + GetFullPathName( strStartAt, MAX_PATH, strFullPath, &strFilePart ); + if( strFilePart == NULL ) + return false; + + while( strFilePart != NULL ) + { + _sntprintf( strFullFileName, MAX_PATH, TEXT("%s\\%s"), strFullPath, strLeafName ); strFullFileName[MAX_PATH-1] = 0; + if( GetFileAttributes( strFullFileName ) != 0xFFFFFFFF ) + { + _tcsncpy( strSearchPath, strFullFileName, cchSearch ); strSearchPath[cchSearch-1] = 0; + return true; + } + + _sntprintf( strSearch, MAX_PATH, TEXT("%s\\.."), strFullPath ); strSearch[MAX_PATH-1] = 0; + GetFullPathName( strSearch, MAX_PATH, strFullPath, &strFilePart ); + } + + return false; +} +#endif // !UNDER_CE + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ReadStringRegKeyCch() +// Desc: Helper function to read a registry key string +// cchDest is the size in TCHARs of strDest. Be careful not to +// pass in sizeof(strDest) on UNICODE builds. +//----------------------------------------------------------------------------- +// MATCH +HRESULT DXUtil_ReadStringRegKeyCch( HKEY hKey, LPCTSTR strRegName, TCHAR* strDest, + DWORD cchDest, LPCTSTR strDefault ) +{ + DWORD dwType; + DWORD cbDest = cchDest * sizeof(TCHAR); + + if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, + (BYTE*)strDest, &cbDest ) ) + { + _tcsncpy( strDest, strDefault, cchDest ); + strDest[cchDest-1] = 0; + return S_FALSE; + } + else + { + if( dwType != REG_SZ ) + { + _tcsncpy( strDest, strDefault, cchDest ); + strDest[cchDest-1] = 0; + return S_FALSE; + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_WriteStringRegKey() +// Desc: Helper function to write a registry key string +//----------------------------------------------------------------------------- +// MATCH +HRESULT DXUtil_WriteStringRegKey( HKEY hKey, LPCTSTR strRegName, + LPCTSTR strValue ) +{ + if( NULL == strValue ) + return E_INVALIDARG; + + DWORD cbValue = ((DWORD)_tcslen(strValue)+1) * sizeof(TCHAR); + + if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_SZ, + (BYTE*)strValue, cbValue ) ) + return E_FAIL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ReadFloatRegKey() +// Desc: Helper function to read a registry key string +//----------------------------------------------------------------------------- +// MATCH +HRESULT DXUtil_ReadFloatRegKey( HKEY hKey, LPCTSTR strRegName, FLOAT* pfDest, FLOAT fDefault ) +{ + if( NULL == pfDest ) + return E_INVALIDARG; + + TCHAR sz[256]; + float fResult; + + TCHAR strDefault[256]; + _sntprintf( strDefault, 256, TEXT("%f"), fDefault ); + strDefault[255] = 0; + + if( SUCCEEDED( DXUtil_ReadStringRegKeyCch( hKey, strRegName, sz, 256, strDefault ) ) ) + { + int nResult = _stscanf( sz, TEXT("%f"), &fResult ); + if( nResult == 1 ) + { + *pfDest = fResult; + return S_OK; + } + } + + *pfDest = fDefault; + return S_FALSE; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_WriteFloatRegKey() +// Desc: Helper function to write a registry key string +//----------------------------------------------------------------------------- +HRESULT DXUtil_WriteFloatRegKey( HKEY hKey, LPCTSTR strRegName, FLOAT fValue ) +{ + TCHAR strValue[256]; + _sntprintf( strValue, 256, TEXT("%f"), fValue ); + strValue[255] = 0; + + return DXUtil_WriteStringRegKey( hKey, strRegName, strValue ); +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ReadIntRegKey() +// Desc: Helper function to read a registry key int +//----------------------------------------------------------------------------- +HRESULT DXUtil_ReadIntRegKey( HKEY hKey, LPCTSTR strRegName, DWORD* pdwDest, + DWORD dwDefault ) +{ + DWORD dwType; + DWORD dwLength = sizeof(DWORD); + + if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, + (BYTE*)pdwDest, &dwLength ) ) + { + *pdwDest = dwDefault; + return S_FALSE; + } + else + { + if( dwType != REG_DWORD ) + { + *pdwDest = dwDefault; + return S_FALSE; + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_WriteIntRegKey() +// Desc: Helper function to write a registry key int +//----------------------------------------------------------------------------- +HRESULT DXUtil_WriteIntRegKey( HKEY hKey, LPCTSTR strRegName, DWORD dwValue ) +{ + if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_DWORD, + (BYTE*)&dwValue, sizeof(DWORD) ) ) + return E_FAIL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ReadBoolRegKey() +// Desc: Helper function to read a registry key BOOL +//----------------------------------------------------------------------------- +HRESULT DXUtil_ReadBoolRegKey( HKEY hKey, LPCTSTR strRegName, BOOL* pbDest, + BOOL bDefault ) +{ + DWORD dwType; + DWORD dwLength = sizeof(BOOL); + + if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, + (BYTE*)pbDest, &dwLength ) ) + { + *pbDest = bDefault; + return S_FALSE; + } + else + { + if( dwType != REG_DWORD ) + { + *pbDest = bDefault; + return S_FALSE; + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_WriteBoolRegKey() +// Desc: Helper function to write a registry key BOOL +//----------------------------------------------------------------------------- +HRESULT DXUtil_WriteBoolRegKey( HKEY hKey, LPCTSTR strRegName, BOOL bValue ) +{ + if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_DWORD, + (BYTE*)&bValue, sizeof(BOOL) ) ) + return E_FAIL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ReadGuidRegKey() +// Desc: Helper function to read a registry key guid +//----------------------------------------------------------------------------- +HRESULT DXUtil_ReadGuidRegKey( HKEY hKey, LPCTSTR strRegName, GUID* pGuidDest, + GUID& guidDefault ) +{ + DWORD dwType; + DWORD dwLength = sizeof(GUID); + + if( ERROR_SUCCESS != RegQueryValueEx( hKey, strRegName, 0, &dwType, + (LPBYTE) pGuidDest, &dwLength ) ) + { + *pGuidDest = guidDefault; + return S_FALSE; + } + else + { + if( dwType != REG_BINARY ) + { + *pGuidDest = guidDefault; + return S_FALSE; + } + } + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_WriteGuidRegKey() +// Desc: Helper function to write a registry key guid +//----------------------------------------------------------------------------- +HRESULT DXUtil_WriteGuidRegKey( HKEY hKey, LPCTSTR strRegName, GUID guidValue ) +{ + if( ERROR_SUCCESS != RegSetValueEx( hKey, strRegName, 0, REG_BINARY, + (BYTE*)&guidValue, sizeof(GUID) ) ) + return E_FAIL; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_Timer() +// Desc: Performs timer opertations. Use the following commands: +// TIMER_RESET - to reset the timer +// TIMER_START - to start the timer +// TIMER_STOP - to stop (or pause) the timer +// TIMER_ADVANCE - to advance the timer by 0.1 seconds +// TIMER_GETABSOLUTETIME - to get the absolute system time +// TIMER_GETAPPTIME - to get the current time +// TIMER_GETELAPSEDTIME - to get the time that elapsed between +// TIMER_GETELAPSEDTIME calls +//----------------------------------------------------------------------------- +FLOAT __stdcall DXUtil_Timer( TIMER_COMMAND command ) +{ + static BOOL m_bTimerInitialized = FALSE; + static BOOL m_bUsingQPF = FALSE; + static BOOL m_bTimerStopped = TRUE; + static LONGLONG m_llQPFTicksPerSec = 0; + + // Initialize the timer + if( FALSE == m_bTimerInitialized ) + { + m_bTimerInitialized = TRUE; + + // Use QueryPerformanceFrequency() to get frequency of timer. If QPF is + // not supported, we will timeGetTime() which returns milliseconds. + LARGE_INTEGER qwTicksPerSec; + m_bUsingQPF = QueryPerformanceFrequency( &qwTicksPerSec ); + if( m_bUsingQPF ) + m_llQPFTicksPerSec = qwTicksPerSec.QuadPart; + } + + if( m_bUsingQPF ) + { + static LONGLONG m_llStopTime = 0; + static LONGLONG m_llLastElapsedTime = 0; + static LONGLONG m_llBaseTime = 0; + double fTime; + double fElapsedTime; + LARGE_INTEGER qwTime; + + // Get either the current time or the stop time, depending + // on whether we're stopped and what command was sent + if( m_llStopTime != 0 && command != TIMER_START && command != TIMER_GETABSOLUTETIME) + qwTime.QuadPart = m_llStopTime; + else + QueryPerformanceCounter( &qwTime ); + + // Return the elapsed time + if( command == TIMER_GETELAPSEDTIME ) + { + fElapsedTime = (double) ( qwTime.QuadPart - m_llLastElapsedTime ) / (double) m_llQPFTicksPerSec; + m_llLastElapsedTime = qwTime.QuadPart; + return (FLOAT) fElapsedTime; + } + + // Return the current time + if( command == TIMER_GETAPPTIME ) + { + double fAppTime = (double) ( qwTime.QuadPart - m_llBaseTime ) / (double) m_llQPFTicksPerSec; + return (FLOAT) fAppTime; + } + + // Reset the timer + if( command == TIMER_RESET ) + { + m_llBaseTime = qwTime.QuadPart; + m_llLastElapsedTime = qwTime.QuadPart; + m_llStopTime = 0; + m_bTimerStopped = FALSE; + return 0.0f; + } + + // Start the timer + if( command == TIMER_START ) + { + if( m_bTimerStopped ) + m_llBaseTime += qwTime.QuadPart - m_llStopTime; + m_llStopTime = 0; + m_llLastElapsedTime = qwTime.QuadPart; + m_bTimerStopped = FALSE; + return 0.0f; + } + + // Stop the timer + if( command == TIMER_STOP ) + { + if( !m_bTimerStopped ) + { + m_llStopTime = qwTime.QuadPart; + m_llLastElapsedTime = qwTime.QuadPart; + m_bTimerStopped = TRUE; + } + return 0.0f; + } + + // Advance the timer by 1/10th second + if( command == TIMER_ADVANCE ) + { + m_llStopTime += m_llQPFTicksPerSec/10; + return 0.0f; + } + + if( command == TIMER_GETABSOLUTETIME ) + { + fTime = qwTime.QuadPart / (double) m_llQPFTicksPerSec; + return (FLOAT) fTime; + } + + return -1.0f; // Invalid command specified + } + else + { + // Get the time using timeGetTime() + static double m_fLastElapsedTime = 0.0; + static double m_fBaseTime = 0.0; + static double m_fStopTime = 0.0; + double fTime; + double fElapsedTime; + + // Get either the current time or the stop time, depending + // on whether we're stopped and what command was sent + if( m_fStopTime != 0.0 && command != TIMER_START && command != TIMER_GETABSOLUTETIME) + fTime = m_fStopTime; + else + fTime = GETTIMESTAMP() * 0.001; + + // Return the elapsed time + if( command == TIMER_GETELAPSEDTIME ) + { + fElapsedTime = (double) (fTime - m_fLastElapsedTime); + m_fLastElapsedTime = fTime; + return (FLOAT) fElapsedTime; + } + + // Return the current time + if( command == TIMER_GETAPPTIME ) + { + return (FLOAT) (fTime - m_fBaseTime); + } + + // Reset the timer + if( command == TIMER_RESET ) + { + m_fBaseTime = fTime; + m_fLastElapsedTime = fTime; + m_fStopTime = 0; + m_bTimerStopped = FALSE; + return 0.0f; + } + + // Start the timer + if( command == TIMER_START ) + { + if( m_bTimerStopped ) + m_fBaseTime += fTime - m_fStopTime; + m_fStopTime = 0.0f; + m_fLastElapsedTime = fTime; + m_bTimerStopped = FALSE; + return 0.0f; + } + + // Stop the timer + if( command == TIMER_STOP ) + { + if( !m_bTimerStopped ) + { + m_fStopTime = fTime; + m_fLastElapsedTime = fTime; + m_bTimerStopped = TRUE; + } + return 0.0f; + } + + // Advance the timer by 1/10th second + if( command == TIMER_ADVANCE ) + { + m_fStopTime += 0.1f; + return 0.0f; + } + + if( command == TIMER_GETABSOLUTETIME ) + { + return (FLOAT) fTime; + } + + return -1.0f; // Invalid command specified + } +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertAnsiStringToWideCch() +// Desc: This is a UNICODE conversion utility to convert a CHAR string into a +// WCHAR string. +// cchDestChar is the size in TCHARs of wstrDestination. Be careful not to +// pass in sizeof(strDest) +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertAnsiStringToWideCch( WCHAR* wstrDestination, const CHAR* strSource, + int cchDestChar ) +{ + if( wstrDestination==NULL || strSource==NULL || cchDestChar < 1 ) + return E_INVALIDARG; + + int nResult = MultiByteToWideChar( CP_ACP, 0, strSource, -1, + wstrDestination, cchDestChar ); + wstrDestination[cchDestChar-1] = 0; + + if( nResult == 0 ) + return E_FAIL; + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertWideStringToAnsi() +// Desc: This is a UNICODE conversion utility to convert a WCHAR string into a +// CHAR string. +// cchDestChar is the size in TCHARs of strDestination +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertWideStringToAnsiCch( CHAR* strDestination, const WCHAR* wstrSource, + int cchDestChar ) +{ + if( strDestination==NULL || wstrSource==NULL || cchDestChar < 1 ) + return E_INVALIDARG; + + int nResult = WideCharToMultiByte( CP_ACP, 0, wstrSource, -1, strDestination, + cchDestChar*sizeof(CHAR), NULL, NULL ); + strDestination[cchDestChar-1] = 0; + + if( nResult == 0 ) + return E_FAIL; + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertGenericStringToAnsi() +// Desc: This is a UNICODE conversion utility to convert a TCHAR string into a +// CHAR string. +// cchDestChar is the size in TCHARs of strDestination +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertGenericStringToAnsiCch( CHAR* strDestination, const TCHAR* tstrSource, + int cchDestChar ) +{ + if( strDestination==NULL || tstrSource==NULL || cchDestChar < 1 ) + return E_INVALIDARG; + +#ifdef _UNICODE + return DXUtil_ConvertWideStringToAnsiCch( strDestination, tstrSource, cchDestChar ); +#else + strncpy( strDestination, tstrSource, cchDestChar ); + strDestination[cchDestChar-1] = '\0'; + return S_OK; +#endif +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertGenericStringToWide() +// Desc: This is a UNICODE conversion utility to convert a TCHAR string into a +// WCHAR string. +// cchDestChar is the size in TCHARs of wstrDestination. Be careful not to +// pass in sizeof(strDest) +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertGenericStringToWideCch( WCHAR* wstrDestination, const TCHAR* tstrSource, + int cchDestChar ) +{ + if( wstrDestination==NULL || tstrSource==NULL || cchDestChar < 1 ) + return E_INVALIDARG; + +#ifdef _UNICODE + wcsncpy( wstrDestination, tstrSource, cchDestChar ); + wstrDestination[cchDestChar-1] = L'\0'; + return S_OK; +#else + return DXUtil_ConvertAnsiStringToWideCch( wstrDestination, tstrSource, cchDestChar ); +#endif +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertAnsiStringToGeneric() +// Desc: This is a UNICODE conversion utility to convert a CHAR string into a +// TCHAR string. +// cchDestChar is the size in TCHARs of tstrDestination. Be careful not to +// pass in sizeof(strDest) on UNICODE builds +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertAnsiStringToGenericCch( TCHAR* tstrDestination, const CHAR* strSource, + int cchDestChar ) +{ + if( tstrDestination==NULL || strSource==NULL || cchDestChar < 1 ) + return E_INVALIDARG; + +#ifdef _UNICODE + return DXUtil_ConvertAnsiStringToWideCch( tstrDestination, strSource, cchDestChar ); +#else + strncpy( tstrDestination, strSource, cchDestChar ); + tstrDestination[cchDestChar-1] = '\0'; + return S_OK; +#endif +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertAnsiStringToGeneric() +// Desc: This is a UNICODE conversion utility to convert a WCHAR string into a +// TCHAR string. +// cchDestChar is the size in TCHARs of tstrDestination. Be careful not to +// pass in sizeof(strDest) on UNICODE builds +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertWideStringToGenericCch( TCHAR* tstrDestination, const WCHAR* wstrSource, + int cchDestChar ) +{ + if( tstrDestination==NULL || wstrSource==NULL || cchDestChar < 1 ) + return E_INVALIDARG; + +#ifdef _UNICODE + wcsncpy( tstrDestination, wstrSource, cchDestChar ); + tstrDestination[cchDestChar-1] = L'\0'; + return S_OK; +#else + return DXUtil_ConvertWideStringToAnsiCch( tstrDestination, wstrSource, cchDestChar ); +#endif +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_LaunchReadme() +// Desc: Finds and opens the readme for this sample +//----------------------------------------------------------------------------- +VOID DXUtil_LaunchReadme( HWND hWnd, LPCTSTR strLoc ) +{ +#ifdef UNDER_CE + // This is not available on PocketPC + MessageBox( hWnd, TEXT("For operating instructions, please open the ") + TEXT("readme.txt file included with the project."), + TEXT("DirectX SDK Sample"), MB_ICONWARNING | MB_OK ); + + return; +#endif + + const int NUM_FILENAMES = 2; + LPCTSTR strFilenames[] = + { + TEXT("readme.htm"), + TEXT("readme.txt") + }; + + TCHAR strReadmePath[1024]; + TCHAR strExeName[MAX_PATH]; + TCHAR strExePath[MAX_PATH]; + TCHAR strSamplePath[MAX_PATH]; + TCHAR* strLastSlash = NULL; + + for( int i=0; i < NUM_FILENAMES; i++ ) + { + LPCTSTR strFilename = strFilenames[i]; + bool bSuccess = false; + bool bFound = false; + + lstrcpy( strReadmePath, TEXT("") ); + lstrcpy( strExePath, TEXT("") ); + lstrcpy( strExeName, TEXT("") ); + lstrcpy( strSamplePath, TEXT("") ); + + // If the user provided a location for the readme, check there first. + if( strLoc ) + { + HKEY hKey; + LONG lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, + _T("Software\\Microsoft\\DirectX SDK"), + 0, KEY_READ, &hKey ); + if( ERROR_SUCCESS == lResult ) + { + DWORD dwType; + DWORD dwSize = MAX_PATH * sizeof(TCHAR); + lResult = RegQueryValueEx( hKey, _T("DX9S4SDK Samples Path"), NULL, + &dwType, (BYTE*)strSamplePath, &dwSize ); + strSamplePath[MAX_PATH-1] = 0; // RegQueryValueEx doesn't NULL term if buffer too small + + if( ERROR_SUCCESS == lResult ) + { + _sntprintf( strReadmePath, 1023, TEXT("%s\\C++\\%s\\%s"), + strSamplePath, strLoc, strFilename ); + strReadmePath[1023] = 0; + + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + } + + RegCloseKey( hKey ); + } + + // Get the exe name, and exe path + GetModuleFileName( NULL, strExePath, MAX_PATH ); + strExePath[MAX_PATH-1]=0; + + strLastSlash = _tcsrchr( strExePath, TEXT('\\') ); + if( strLastSlash ) + { + _tcsncpy( strExeName, &strLastSlash[1], MAX_PATH ); + strExeName[MAX_PATH-1]=0; + + // Chop the exe name from the exe path + *strLastSlash = 0; + + // Chop the .exe from the exe name + strLastSlash = _tcsrchr( strExeName, TEXT('.') ); + if( strLastSlash ) + *strLastSlash = 0; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\..\%EXE_NAME%\". This matches the DirectX SDK layout + _tcscpy( strReadmePath, strExePath ); + + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strExeName ); + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\..\BumpMapping\%EXE_NAME%\". + _tcscpy( strReadmePath, strExePath ); + + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + lstrcat( strReadmePath, TEXT("\\BumpMapping\\") ); + lstrcat( strReadmePath, strExeName ); + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\..\EnvMapping\%EXE_NAME%\". + _tcscpy( strReadmePath, strExePath ); + + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + lstrcat( strReadmePath, TEXT("\\EnvMapping\\") ); + lstrcat( strReadmePath, strExeName ); + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\..\Meshes\%EXE_NAME%\". + _tcscpy( strReadmePath, strExePath ); + + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + lstrcat( strReadmePath, TEXT("\\Meshes\\") ); + lstrcat( strReadmePath, strExeName ); + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\..\StencilBuffer\%EXE_NAME%\". + _tcscpy( strReadmePath, strExePath ); + + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + lstrcat( strReadmePath, TEXT("\\StencilBuffer\\") ); + lstrcat( strReadmePath, strExeName ); + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\" + _tcscpy( strReadmePath, strExePath ); + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\.." + _tcscpy( strReadmePath, strExePath ); + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( !bFound ) + { + // Search in "%EXE_DIR%\..\.." + _tcscpy( strReadmePath, strExePath ); + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + strLastSlash = _tcsrchr( strReadmePath, TEXT('\\') ); + if( strLastSlash ) + *strLastSlash = 0; + lstrcat( strReadmePath, TEXT("\\") ); + lstrcat( strReadmePath, strFilename ); + if( GetFileAttributes( strReadmePath ) != 0xFFFFFFFF ) + bFound = TRUE; + } + + if( bFound ) + { + // GetProcAddress for ShellExecute, so we don't have to include shell32.lib + // in every project that uses dxutil.cpp + LPShellExecute pShellExecute = NULL; + HINSTANCE hInstShell32 = LoadLibrary(TEXT("shell32.dlTEXT(")); + if (hInstShell32 != NULL) + { + #ifdef UNICODE + pShellExecute = (LPShellExecute)GetProcAddress(hInstShell32, _TWINCE("ShellExecuteW")); + #else + pShellExecute = (LPShellExecute)GetProcAddress(hInstShell32, _TWINCE("ShellExecuteA")); + #endif + if( pShellExecute != NULL ) + { + if( pShellExecute( hWnd, TEXT("open"), strReadmePath, NULL, NULL, SW_SHOW ) > (HINSTANCE) 32 ) + bSuccess = true; + } + + FreeLibrary(hInstShell32); + } + } + + if( bSuccess ) + return; + } + + // Tell the user that the readme couldn't be opened + MessageBox( hWnd, TEXT("Could not find readme"), + TEXT("DirectX SDK Sample"), MB_ICONWARNING | MB_OK ); +} + + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_Trace() +// Desc: Outputs to the debug stream a formatted string with a variable- +// argument list. +//----------------------------------------------------------------------------- +VOID DXUtil_Trace( LPCTSTR strMsg, ... ) +{ +#if defined(DEBUG) | defined(_DEBUG) + TCHAR strBuffer[512]; + + va_list args; + va_start(args, strMsg); + _vsntprintf( strBuffer, 512, strMsg, args ); + va_end(args); + + OutputDebugString( strBuffer ); +#else + UNREFERENCED_PARAMETER(strMsg); +#endif +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertStringToGUID() +// Desc: Converts a string to a GUID +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertStringToGUID( const TCHAR* strSrc, GUID* pGuidDest ) +{ + UINT aiTmp[10]; + + if( _stscanf( strSrc, TEXT("{%8X-%4X-%4X-%2X%2X-%2X%2X%2X%2X%2X%2X}"), + &pGuidDest->Data1, + &aiTmp[0], &aiTmp[1], + &aiTmp[2], &aiTmp[3], + &aiTmp[4], &aiTmp[5], + &aiTmp[6], &aiTmp[7], + &aiTmp[8], &aiTmp[9] ) != 11 ) + { + ZeroMemory( pGuidDest, sizeof(GUID) ); + return E_FAIL; + } + else + { + pGuidDest->Data2 = (USHORT) aiTmp[0]; + pGuidDest->Data3 = (USHORT) aiTmp[1]; + pGuidDest->Data4[0] = (BYTE) aiTmp[2]; + pGuidDest->Data4[1] = (BYTE) aiTmp[3]; + pGuidDest->Data4[2] = (BYTE) aiTmp[4]; + pGuidDest->Data4[3] = (BYTE) aiTmp[5]; + pGuidDest->Data4[4] = (BYTE) aiTmp[6]; + pGuidDest->Data4[5] = (BYTE) aiTmp[7]; + pGuidDest->Data4[6] = (BYTE) aiTmp[8]; + pGuidDest->Data4[7] = (BYTE) aiTmp[9]; + return S_OK; + } +} + + + + +//----------------------------------------------------------------------------- +// Name: DXUtil_ConvertGUIDToStringCch() +// Desc: Converts a GUID to a string +// cchDestChar is the size in TCHARs of strDest. Be careful not to +// pass in sizeof(strDest) on UNICODE builds +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertGUIDToStringCch( const GUID* pGuidSrc, TCHAR* strDest, int cchDestChar ) +{ + int nResult = _sntprintf( strDest, cchDestChar, TEXT("{%0.8X-%0.4X-%0.4X-%0.2X%0.2X-%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X}"), + pGuidSrc->Data1, pGuidSrc->Data2, pGuidSrc->Data3, + pGuidSrc->Data4[0], pGuidSrc->Data4[1], + pGuidSrc->Data4[2], pGuidSrc->Data4[3], + pGuidSrc->Data4[4], pGuidSrc->Data4[5], + pGuidSrc->Data4[6], pGuidSrc->Data4[7] ); + + if( nResult < 0 ) + return E_FAIL; + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CArrayList constructor +// Desc: +//----------------------------------------------------------------------------- +CArrayList::CArrayList( ArrayListType Type, UINT BytesPerEntry ) +{ + if( Type == AL_REFERENCE ) + BytesPerEntry = sizeof(void*); + m_ArrayListType = Type; + m_pData = NULL; + m_BytesPerEntry = BytesPerEntry; + m_NumEntries = 0; + m_NumEntriesAllocated = 0; +} + + + +//----------------------------------------------------------------------------- +// Name: CArrayList destructor +// Desc: +//----------------------------------------------------------------------------- +CArrayList::~CArrayList( void ) +{ + if( m_pData != NULL ) + delete[] m_pData; +} + + + + +//----------------------------------------------------------------------------- +// Name: CArrayList::Add +// Desc: Adds pEntry to the list. +//----------------------------------------------------------------------------- +HRESULT CArrayList::Add( void* pEntry ) +{ + if( m_BytesPerEntry == 0 ) + return E_FAIL; + if( m_pData == NULL || m_NumEntries + 1 > m_NumEntriesAllocated ) + { + void* pDataNew; + UINT NumEntriesAllocatedNew; + if( m_NumEntriesAllocated == 0 ) + NumEntriesAllocatedNew = 16; + else + NumEntriesAllocatedNew = m_NumEntriesAllocated * 2; + pDataNew = new BYTE[NumEntriesAllocatedNew * m_BytesPerEntry]; + if( pDataNew == NULL ) + return E_OUTOFMEMORY; + if( m_pData != NULL ) + { + CopyMemory( pDataNew, m_pData, m_NumEntries * m_BytesPerEntry ); + delete[] m_pData; + } + m_pData = pDataNew; + m_NumEntriesAllocated = NumEntriesAllocatedNew; + } + + if( m_ArrayListType == AL_VALUE ) + CopyMemory( (BYTE*)m_pData + (m_NumEntries * m_BytesPerEntry), pEntry, m_BytesPerEntry ); + else + *(((void**)m_pData) + m_NumEntries) = pEntry; + m_NumEntries++; + + return S_OK; +} + + + + +//----------------------------------------------------------------------------- +// Name: CArrayList::Remove +// Desc: Remove the item at Entry in the list, and collapse the array. +//----------------------------------------------------------------------------- +void CArrayList::Remove( UINT Entry ) +{ + // Decrement count + m_NumEntries--; + + // Find the entry address + BYTE* pData = (BYTE*)m_pData + (Entry * m_BytesPerEntry); + + // Collapse the array + MoveMemory( pData, pData + m_BytesPerEntry, ( m_NumEntries - Entry ) * m_BytesPerEntry ); +} + + + + +//----------------------------------------------------------------------------- +// Name: CArrayList::GetPtr +// Desc: Returns a pointer to the Entry'th entry in the list. +//----------------------------------------------------------------------------- +void* CArrayList::GetPtr( UINT Entry ) +{ + if( m_ArrayListType == AL_VALUE ) + return (BYTE*)m_pData + (Entry * m_BytesPerEntry); + else + return *(((void**)m_pData) + Entry); +} + + + + +//----------------------------------------------------------------------------- +// Name: CArrayList::Contains +// Desc: Returns whether the list contains an entry identical to the +// specified entry data. +//----------------------------------------------------------------------------- +bool CArrayList::Contains( void* pEntryData ) +{ + for( UINT iEntry = 0; iEntry < m_NumEntries; iEntry++ ) + { + if( m_ArrayListType == AL_VALUE ) + { + if( memcmp( GetPtr(iEntry), pEntryData, m_BytesPerEntry ) == 0 ) + return true; + } + else + { + if( GetPtr(iEntry) == pEntryData ) + return true; + } + } + return false; +} + + + + +//----------------------------------------------------------------------------- +// Name: BYTE helper functions +// Desc: cchDestChar is the size in BYTEs of strDest. Be careful not to +// pass use sizeof() if the strDest is a string pointer. +// eg. +// TCHAR* sz = new TCHAR[100]; // sizeof(sz) == 4 +// TCHAR sz2[100]; // sizeof(sz2) == 200 +//----------------------------------------------------------------------------- +HRESULT DXUtil_ConvertAnsiStringToWideCb( WCHAR* wstrDestination, const CHAR* strSource, int cbDestChar ) +{ + return DXUtil_ConvertAnsiStringToWideCch( wstrDestination, strSource, cbDestChar / sizeof(WCHAR) ); +} + +HRESULT DXUtil_ConvertWideStringToAnsiCb( CHAR* strDestination, const WCHAR* wstrSource, int cbDestChar ) +{ + return DXUtil_ConvertWideStringToAnsiCch( strDestination, wstrSource, cbDestChar / sizeof(CHAR) ); +} + +HRESULT DXUtil_ConvertGenericStringToAnsiCb( CHAR* strDestination, const TCHAR* tstrSource, int cbDestChar ) +{ + return DXUtil_ConvertGenericStringToAnsiCch( strDestination, tstrSource, cbDestChar / sizeof(CHAR) ); +} + +HRESULT DXUtil_ConvertGenericStringToWideCb( WCHAR* wstrDestination, const TCHAR* tstrSource, int cbDestChar ) +{ + return DXUtil_ConvertGenericStringToWideCch( wstrDestination, tstrSource, cbDestChar / sizeof(WCHAR) ); +} + +HRESULT DXUtil_ConvertAnsiStringToGenericCb( TCHAR* tstrDestination, const CHAR* strSource, int cbDestChar ) +{ + return DXUtil_ConvertAnsiStringToGenericCch( tstrDestination, strSource, cbDestChar / sizeof(TCHAR) ); +} + +HRESULT DXUtil_ConvertWideStringToGenericCb( TCHAR* tstrDestination, const WCHAR* wstrSource, int cbDestChar ) +{ + return DXUtil_ConvertWideStringToGenericCch( tstrDestination, wstrSource, cbDestChar / sizeof(TCHAR) ); +} + +HRESULT DXUtil_ReadStringRegKeyCb( HKEY hKey, LPCTSTR strRegName, TCHAR* strDest, DWORD cbDest, LPCTSTR strDefault ) +{ + return DXUtil_ReadStringRegKeyCch( hKey, strRegName, strDest, cbDest / sizeof(TCHAR), strDefault ); +} + +HRESULT DXUtil_ConvertGUIDToStringCb( const GUID* pGuidSrc, TCHAR* strDest, int cbDestChar ) +{ + return DXUtil_ConvertGUIDToStringCch( pGuidSrc, strDest, cbDestChar / sizeof(TCHAR) ); +} + +#ifndef UNDER_CE +HRESULT DXUtil_GetDXSDKMediaPathCb( TCHAR* szDest, int cbDest ) +{ + return DXUtil_GetDXSDKMediaPathCch( szDest, cbDest / sizeof(TCHAR) ); +} + +HRESULT DXUtil_FindMediaFileCb( TCHAR* szDestPath, int cbDest, LPCTSTR strFilename ) +{ + return DXUtil_FindMediaFileCch( szDestPath, cbDest / sizeof(TCHAR), strFilename ); +} +#endif // !UNDER_CE diff --git a/saco/d3dhook/IDirect3DDevice9Hook.cpp b/saco/d3dhook/IDirect3DDevice9Hook.cpp index 158c04b..9b9afe1 100644 --- a/saco/d3dhook/IDirect3DDevice9Hook.cpp +++ b/saco/d3dhook/IDirect3DDevice9Hook.cpp @@ -1,6 +1,6 @@ /* - Changes found: + Changes in: IDirect3DDevice9Hook::Present IDirect3DDevice9Hook::Reset IDirect3DDevice9Hook::CreateDepthStencilSurface @@ -14,6 +14,8 @@ extern IDirect3DDevice9 *pD3DDevice; D3DXMATRIX matView, matProj, matWorld; +extern void d3d9DestroyDeviceObjects(); +extern void d3d9RestoreDeviceObjects(); //------------------------------------------- @@ -106,9 +108,25 @@ UINT __stdcall IDirect3DDevice9Hook::GetNumberOfSwapChains() HRESULT __stdcall IDirect3DDevice9Hook::Reset(D3DPRESENT_PARAMETERS* pPresentationParameters) { - // TODO: IDirect3DDevice9Hook::Reset + d3d9DestroyDeviceObjects(); - return pD3DDevice->Reset(pPresentationParameters); + /* + // Done through ALT+ENTER now + if (tSettings.bWindowedMode) { + pPresentationParameters->Windowed = 1; + pPresentationParameters->Flags = 0; + SetWindowPos(pPresentationParameters->hDeviceWindow, HWND_NOTOPMOST, 0, 0, pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight, SWP_SHOWWINDOW); + } + */ + + HRESULT hr = pD3DDevice->Reset(pPresentationParameters); + + if (SUCCEEDED(hr)) + { + d3d9RestoreDeviceObjects(); + } + + return hr; } HRESULT __stdcall IDirect3DDevice9Hook::GetBackBuffer(UINT iSwapChain, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9** ppBackBuffer) @@ -240,6 +258,7 @@ HRESULT __stdcall IDirect3DDevice9Hook::EndScene() HRESULT __stdcall IDirect3DDevice9Hook::Clear(DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) { + // +172 return pD3DDevice->Clear(Count, pRects, Flags, Color, Z, Stencil); } diff --git a/saco/events.cpp b/saco/events.cpp new file mode 100644 index 0000000..017163c --- /dev/null +++ b/saco/events.cpp @@ -0,0 +1,201 @@ + +#include "main.h" +#include "game/util.h" + +extern CNetGame *pNetGame; +extern CGame *pGame; + +#define NUDE void _declspec(naked) + +DWORD dwParams[4]; + +#define EVENT_TYPE_PAINTJOB 1 +#define EVENT_TYPE_CARCOMPONENT 2 +#define EVENT_TYPE_CARCOLOR 3 +#define EVENT_ENTEREXIT_MODSHOP 4 + +extern BOOL bFirstSpawn; + +//---------------------------------------------------------- + +void ProcessIncommingEvent(PLAYERID playerId, int iEventType, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3) +{ + CVehicle *pVehicle; + + if(!pNetGame) return; + if(bFirstSpawn) return; // Local player has never spawned. + + CVehiclePool *pVehiclePool = pNetGame->GetVehiclePool(); + CPlayerPool *pPlayerPool = pNetGame->GetPlayerPool(); + + if(!pPlayerPool) return; + if(!pVehiclePool) return; + + switch(iEventType) { + + case EVENT_TYPE_PAINTJOB: + pVehicle = pVehiclePool->GetAt(dwParam1); + if(pVehicle) pVehicle->SetPaintJob(dwParam2); + break; + + case EVENT_TYPE_CARCOMPONENT: + pVehicle = pVehiclePool->GetAt(dwParam1); + if(pVehicle) pVehicle->AddComponent(dwParam2); + break; + + case EVENT_TYPE_CARCOLOR: + pVehicle = pVehiclePool->GetAt(dwParam1); + if(pVehicle) pVehicle->SetColor(dwParam2,dwParam3); + break; + + case EVENT_ENTEREXIT_MODSHOP: + if(playerId > MAX_PLAYERS) return; + break; + } + + // TODO: ProcessIncommingEvent +} + +//---------------------------------------------------------- + +VOID ProcessOutgoingEvent(DWORD dwParam1, DWORD dwParam2, DWORD dwParam3, int iEventType) +{ + if(!pNetGame) return; + + int iVehicleID; + CVehicle *pVehicle; + VEHICLE_TYPE *pVehiclePtr; + CVehiclePool *pVehiclePool = pNetGame->GetVehiclePool(); + RakNet::BitStream bsSend; + + switch(iEventType) { + + case EVENT_TYPE_PAINTJOB: + iVehicleID = pVehiclePool->FindIDFromGtaPtr(GamePool_Vehicle_GetAt(dwParam1)); + if(iVehicleID != INVALID_VEHICLE_ID) { + bsSend.Write(iVehicleID); + bsSend.Write(dwParam2); + bsSend.Write(dwParam3); + bsSend.Write(iEventType); + pNetGame->GetRakClient()->RPC(RPC_ScmEvent,&bsSend,HIGH_PRIORITY,RELIABLE_SEQUENCED,0,false); + } + break; + + case EVENT_TYPE_CARCOMPONENT: + iVehicleID = pVehiclePool->FindIDFromGtaPtr(GamePool_Vehicle_GetAt(dwParam1)); + if(iVehicleID != INVALID_VEHICLE_ID) { + bsSend.Write(iVehicleID); + bsSend.Write(dwParam2); + bsSend.Write(dwParam3); + bsSend.Write(iEventType); + pNetGame->GetRakClient()->RPC(RPC_ScmEvent,&bsSend,HIGH_PRIORITY,RELIABLE_SEQUENCED,0,false); + } + break; + + case EVENT_TYPE_CARCOLOR: + iVehicleID = pVehiclePool->FindIDFromGtaPtr(GamePool_Vehicle_GetAt(dwParam1)); + if(iVehicleID != INVALID_VEHICLE_ID) { + bsSend.Write(iVehicleID); + bsSend.Write(dwParam2); + bsSend.Write(dwParam3); + bsSend.Write(iEventType); + pNetGame->GetRakClient()->RPC(RPC_ScmEvent,&bsSend,HIGH_PRIORITY,RELIABLE_SEQUENCED,0,false); + + pVehicle = pVehiclePool->GetAt(iVehicleID); + if(pVehicle) { + pVehicle->SetColor(dwParam2,dwParam3); + } + } + break; + + case EVENT_ENTEREXIT_MODSHOP: + iVehicleID = pVehiclePool->FindIDFromGtaPtr(GamePool_Vehicle_GetAt(dwParam1)); + pVehicle = pVehiclePool->GetAt(iVehicleID); + if(iVehicleID != INVALID_VEHICLE_ID) { + bsSend.Write(iVehicleID); + bsSend.Write(dwParam2); + bsSend.Write(dwParam3); + bsSend.Write(iEventType); + pNetGame->GetRakClient()->RPC(RPC_ScmEvent,&bsSend,HIGH_PRIORITY,RELIABLE_SEQUENCED,0,false); + + if(pVehicle) { + pVehiclePtr = pVehicle->m_pVehicle; + if(pVehiclePtr) { + if(dwParam2 == 0) { + pVehicle->SetColor(pVehiclePtr->byteColor1,pVehiclePtr->byteColor2); + pVehicle->field_71 = 0; + } else { + pVehicle->field_71 = 1; + } + } + pVehicle->SetColor(dwParam2,dwParam3); + } + } + break; + } +} + +//---------------------------------------------------------- + +NUDE SetEventCustomOpcode() +{ + _asm pushad + + _asm push 4 + _asm mov ecx, esi + _asm mov ebx, 0x464080 // CRunningScript::CollectParamaters() + _asm call ebx + + dwParams[1] = *(PDWORD)0xA43C7C; + dwParams[2] = *(PDWORD)0xA43C80; + dwParams[3] = *(PDWORD)0xA43C84; + dwParams[0] = *(PDWORD)0xA43C78; + + ProcessOutgoingEvent(dwParams[1],dwParams[2],dwParams[3],dwParams[0]); + + _asm popad + + _asm mov ebx, 0x47BF2B // return to ProcessCommands2500To2600 + _asm jmp ebx +} + +//---------------------------------------------------------- + +int IsDriving; +DWORD ScmInst; +CPlayerPed *pDriverPed; + +NUDE PlayerDriverCustomOpcode() +{ + _asm pushad + _asm mov ScmInst, esi + + IsDriving = 1; + + if(pGame) { + pDriverPed = pGame->FindPlayerPed(); + if(pDriverPed->IsInVehicle() && !pDriverPed->IsAPassenger()) { + IsDriving = 0; + } + } + + _asm push IsDriving + _asm mov ecx, ScmInst + _asm mov ebx, 0x4859D0 // CRunningScript::UpdateCompareFlag + _asm call ebx + + _asm popad + + _asm mov ebx, 0x47BF2B // return to ProcessCommands2500To2600 + _asm jmp ebx +} + +//---------------------------------------------------------- + +void InstallSCMEventsProcessor() +{ + *(DWORD *)0x47BF54 = (DWORD)SetEventCustomOpcode; // opcode 09C6 - 2502 + *(DWORD *)0x47BF88 = (DWORD)PlayerDriverCustomOpcode; // opcode 09D3 - 2515 +} + +//---------------------------------------------------------- diff --git a/saco/exceptions.cpp b/saco/exceptions.cpp index fb6dd15..ca746f5 100644 --- a/saco/exceptions.cpp +++ b/saco/exceptions.cpp @@ -27,13 +27,13 @@ int dword_10125A58=0; void DumpNetworkStateInformation(PCHAR sz) { CPlayerPool *pPlayerPool = pNetGame->GetPlayerPool(); - PLAYERID playerId=0; sz[0] = '\0'; sprintf(sz,"\r\nState Information: Ped Context: %u\r\n",*pbyteCurrentPlayer); - // TODO: DumpNetworkStateInformation 10060160 + + } //---------------------------------------------------- diff --git a/saco/game/actorped.cpp b/saco/game/actorped.cpp new file mode 100644 index 0000000..84016ce --- /dev/null +++ b/saco/game/actorped.cpp @@ -0,0 +1,229 @@ + +#include "../main.h" +#include "game.h" +#include "util.h" + +extern CGame *pGame; + +//----------------------------------------------------------- +// This is the constructor for creating new player. + +CActorPed::CActorPed(int iSkin, float fX, float fY,float fZ,float fRotation) +{ + m_pPed=0; + m_dwGTAId=0; + m_byteImmune=0; + int iCounter=0; + DWORD dwActorID=0; + + if(!pGame->IsModelLoaded(iSkin)) { + pGame->RequestModel(iSkin); + pGame->LoadRequestedModels(); + while(!pGame->IsModelLoaded(iSkin)) Sleep(1); + } + + ScriptCommand(&create_actor,5,iSkin,fX,fY,fZ-1.0f,&dwActorID); + ScriptCommand(&set_actor_z_angle,dwActorID,fRotation); + + m_dwGTAId = dwActorID; + m_pPed = GamePool_Ped_GetAt(m_dwGTAId); + m_pEntity = (ENTITY_TYPE *)m_pPed; + ScriptCommand(&set_actor_can_be_decapitated,m_dwGTAId,0); + ScriptCommand(&set_actor_dicision,m_dwGTAId,65542); +} + +//----------------------------------------------------------- + +CActorPed::~CActorPed() +{ + Destroy(); +} + +//----------------------------------------------------------- + +void CActorPed::Destroy() +{ + DWORD dwPedPtr = (DWORD)m_pPed; + + // If it points to the CPlaceable vtable it's not valid + if(!m_pPed || !GamePool_Ped_GetAt(m_dwGTAId) || m_pPed->entity.vtable == 0x863C40) + { + m_pPed = NULL; + m_pEntity = NULL; + m_dwGTAId = 0; + return; + } + + // DESTROY METHOD + _asm mov ecx, dwPedPtr + _asm mov ebx, [ecx] ; vtable + _asm push 1 + _asm call [ebx] ; destroy + + m_pPed = NULL; + m_pEntity = NULL; +} + +//----------------------------------------------------------- + +void CActorPed::ApplyAnimation( char *szAnimName, char *szAnimFile, float fT, + int opt1, int opt2, int opt3, int opt4, int iUnk ) +{ + int iWaitAnimLoad=0; + + if(!m_pPed) return; + if(!GamePool_Ped_GetAt(m_dwGTAId)) return; + + // Can't allow 'naughty' anims! + if( !stricmp(szAnimFile,"SEX") ) + return; + + if (!pGame->IsAnimationLoaded(szAnimFile)) { + pGame->RequestAnimation(szAnimFile); + while(!pGame->IsAnimationLoaded(szAnimFile)) { + Sleep(1); + iWaitAnimLoad++; + if(iWaitAnimLoad == 15) return; // we can't wait forever + } + } + + ScriptCommand(&apply_animation,m_dwGTAId,szAnimName,szAnimFile,fT,opt1,opt2,opt3,opt4,iUnk); +} + +//----------------------------------------------------------- + +DWORD dwActorPed=0; + +BOOL __declspec(naked) FlushPedIntelligence() +{ + _asm mov edx, dwActorPed + _asm mov ecx, [edx+0x47C] + _asm push 1 + _asm mov eax, 0x601640 + _asm call eax + _asm mov eax, 1 + _asm ret +} + +void CActorPed::ClearAnimations() +{ + dwActorPed = (DWORD)m_pPed; + if(dwActorPed) { + FlushPedIntelligence(); + } +} + +//----------------------------------------------------------- + +void CActorPed::SetTargetRotation(float fRotation) +{ + if(!m_pPed) return; + if(!GamePool_Ped_GetAt(m_dwGTAId)) return; + + m_pPed->fRotation2 = DegToRad(fRotation); +} + +//----------------------------------------------------------- + +float CActorPed::GetHealth() +{ + if(!m_pPed) return 0.0f; + return m_pPed->fHealth; +} + +//----------------------------------------------------------- + +void CActorPed::SetHealth(float fHealth) +{ + if(!m_pPed) return; + m_pPed->fHealth = fHealth; + + if(m_pPed->fHealth <= 0.0f) { + ScriptCommand(&kill_actor,m_dwGTAId); + } +} + +//----------------------------------------------------------- + +float CActorPed::GetArmour() +{ + if(!m_pPed) return 0.0f; + return m_pPed->fArmour; +} + +//----------------------------------------------------------- + +void CActorPed::SetArmour(float fArmour) +{ + if(!m_pPed) return; + m_pPed->fArmour = fArmour; +} + +//----------------------------------------------------------- + +DWORD CActorPed::GetStateFlags() +{ + if(!m_pPed) return 0; + return m_pPed->dwStateFlags; +} + +//----------------------------------------------------------- + +void CActorPed::SetStateFlags(DWORD dwState) +{ + if(!m_pPed) return; + m_pPed->dwStateFlags = dwState; +} + +//----------------------------------------------------------- + +BOOL CActorPed::IsDead() +{ + if(!m_pPed) return TRUE; + if(m_pPed->fHealth > 0.0f) return FALSE; + return TRUE; +} + +//----------------------------------------------------------- + +BYTE CActorPed::GetActionTrigger() +{ + return (BYTE)m_pPed->dwAction; +} + +//----------------------------------------------------------- + +void CActorPed::SetActionTrigger(BYTE byteTrigger) +{ + if(!m_pPed) return; + + m_pPed->dwAction = byteTrigger; +} + +//----------------------------------------------------------- + +BOOL CActorPed::IsInVehicle() +{ + if(!m_pPed) return FALSE; + + if(IN_VEHICLE(m_pPed)) { + return TRUE; + } + return FALSE; +} + +//----------------------------------------------------------- + +void CActorPed::ToggleImmunity(BYTE byteEnable) +{ + if(!m_pPed) return; + + m_byteImmune = byteEnable; + + if(byteEnable) + ScriptCommand(&set_actor_immunities,m_dwGTAId,1,1,1,1,1); + else + ScriptCommand(&set_actor_immunities,m_dwGTAId,0,0,0,1,0); +} + +//----------------------------------------------------------- diff --git a/saco/game/actorped.h b/saco/game/actorped.h new file mode 100644 index 0000000..37b9786 --- /dev/null +++ b/saco/game/actorped.h @@ -0,0 +1,43 @@ + +#pragma once + +//----------------------------------------------------------- + +class CActorPed : public CEntity +{ +public: + + // Constructor/Destructor. + CActorPed(int iSkin, float fPosX, float fPosY, float fPosZ, float fRotation = 0.0f); + virtual ~CActorPed(); + + void Destroy(); + + void SetTargetRotation(float fRotation); + float GetHealth(); + void SetHealth(float fHealth); + float GetArmour(); + void SetArmour(float fArmour); + DWORD GetStateFlags(); + void SetStateFlags(DWORD dwStateFlags); + BOOL IsDead(); + BYTE GetActionTrigger(); + void SetActionTrigger(BYTE byteTrigger); + BOOL IsInVehicle(); + + void ApplyAnimation(char *szAnimName, char *szAnimFile, float fT, + int opt1, int opt2, int opt3, int opt4, int iUnk); + void ClearAnimations(); + + void ToggleImmunity(BYTE byteEnable); + + PED_TYPE * GetGtaActor() { return m_pPed; }; + + PED_TYPE *m_pPed; + DWORD m_dwMarkerID; + DWORD m_dwArrow; + BYTE m_byteCreateMarker; + BYTE m_byteImmune; +}; + +//----------------------------------------------------------- diff --git a/saco/game/address.h b/saco/game/address.h index 8c5dfc2..0e458fb 100644 --- a/saco/game/address.h +++ b/saco/game/address.h @@ -22,6 +22,7 @@ #define ADDR_ENABLE_HUD 0xBA6769 +//#define ADDR_ID_FROM_ACTOR 0x451CF0 #define ADDR_ID_FROM_ACTOR 0x4442D0 #define ADDR_ACTOR_FROM_ID 0x404910 // Converts id to actor ptr #define ADDR_PED_TABLE 0xB74490 // Contains ptr to actor/ped table diff --git a/saco/game/aimstuff.cpp b/saco/game/aimstuff.cpp index afdaef8..bc8de22 100644 --- a/saco/game/aimstuff.cpp +++ b/saco/game/aimstuff.cpp @@ -232,7 +232,6 @@ void __stdcall GameResetLocalPlayerWeaponSkills() pfStats[78] = 999.0f; // m4 pfStats[79] = 999.0f; // sniper - GameStoreLocalPlayerWeaponSkills(); } diff --git a/saco/game/animlist.cpp b/saco/game/animlist.cpp index ba67271..ac48e41 100644 --- a/saco/game/animlist.cpp +++ b/saco/game/animlist.cpp @@ -1,5 +1,6 @@ #include "../main.h" +#include "../runutil.h" #include "util.h" DWORD dwAnimNameHashes[1812]; @@ -1819,6 +1820,35 @@ char szAnimNames[1812][36] = { "SAMP:FISHINGIDLE", // (1811) }; +short GetAnimIndexByName(char *szAnimLib, char *szAnimName) +{ + short j = 0; + + if(!szAnimLib || !szAnimName) return -1; + if(strlen(szAnimLib) + strlen(szAnimName) > 36) return -1; + + char szSearch[40]; + sprintf(szSearch, "%s:%s", szAnimLib, szAnimName); + Util_strupr(szSearch); + + int i = 0; + while(j != 1812) { + if(!strcmp(szSearch, szAnimNames[i])) { + return j + 1; + } + i++; + j++; + } + return -1; +} + +char *GetAnimNameByIndex(short index) +{ + if(index > 1812 || index < 1) return NULL; + + return szAnimNames[index]; +} + void InitAnimNameHashes() { char szAnimLib[32]; @@ -1840,3 +1870,15 @@ void InitAnimNameHashes() } } +short GetAnimIndexByHash(DWORD dwAnimHash) +{ + short x = 0; + + while(x != 1812) { + if(dwAnimNameHashes[x] == dwAnimHash) { + return x; + } + x++; + } + return -1; +} diff --git a/saco/game/audio.cpp b/saco/game/audio.cpp index c2914c5..39adc81 100644 --- a/saco/game/audio.cpp +++ b/saco/game/audio.cpp @@ -2,7 +2,7 @@ #include "game.h" //----------------------------------------------------------- - +// MATCH void CAudio::FUNC_100A21D0() { if(field_0 && field_0 == 1) @@ -16,7 +16,7 @@ void CAudio::FUNC_100A21D0() } //----------------------------------------------------------- - +// MATCH int CAudio::GetRadioStation() { int iRadioStation = 0; @@ -32,7 +32,7 @@ int CAudio::GetRadioStation() } //----------------------------------------------------------- - +// MATCH void CAudio::StartRadio(int iStation) { _asm push 0 @@ -43,7 +43,7 @@ void CAudio::StartRadio(int iStation) } //----------------------------------------------------------- - +// MATCH void CAudio::StopRadio() { _asm push 0 @@ -54,14 +54,14 @@ void CAudio::StopRadio() } //----------------------------------------------------------- - +// MATCH float CAudio::GetRadioVolume() { return *(float*)0xB5FCC8; } //----------------------------------------------------------- - +// MATCH void CAudio::StopOutdoorAmbienceTrack() { _asm mov ecx, 0x8AC15C @@ -70,7 +70,7 @@ void CAudio::StopOutdoorAmbienceTrack() } //----------------------------------------------------------- - +// MATCH void CAudio::SetOutdoorAmbienceTrack(int iTrack) { _asm push iTrack @@ -80,7 +80,7 @@ void CAudio::SetOutdoorAmbienceTrack(int iTrack) } //----------------------------------------------------------- - +// MATCH void CAudio::PlaySound(int iSound, float fX, float fY, float fZ) { if(iSound == 0) @@ -114,7 +114,7 @@ void CAudio::PlaySound(int iSound, float fX, float fY, float fZ) } //----------------------------------------------------------- - +// MATCH bool CAudio::IsOutdoorAmbienceTrackDisabled() { return field_4; diff --git a/saco/game/common.h b/saco/game/common.h index c85e76c..98d5d28 100644 --- a/saco/game/common.h +++ b/saco/game/common.h @@ -58,6 +58,7 @@ typedef struct _MATRIX4X4 { #define IN_VEHICLE(x) ((x->dwStateFlags & 256) >> 8) //----------------------------------------------------------- +#pragma pack(1) typedef struct _WEAPON_SLOT_TYPE { DWORD dwType; @@ -70,11 +71,24 @@ typedef struct _WEAPON_SLOT_TYPE } WEAPON_SLOT_TYPE; // MUST BE EXACTLY ALIGNED TO 28 bytes +//----------------------------------------------------------- +#pragma pack(1) typedef struct _PED_TASKS_TYPE { - char _gap0[16]; - + DWORD * pdwPed; + // Basic Tasks + DWORD * pdwDamage; + DWORD * pdwFallEnterExit; + DWORD * pdwSwimWasted; DWORD * pdwJumpJetPack; + DWORD * pdwAction; + // Extended Tasks + DWORD * pdwFighting; + DWORD * pdwCrouching; + DWORD * pdwSay; + DWORD * pdwFacialComplex; + DWORD * pdwPartialAnim; + DWORD * pdwIK; } PED_TASKS_TYPE; //----------------------------------------------------------- @@ -88,8 +102,8 @@ typedef struct _ENTITY_TYPE MATRIX4X4 *mat; // 20-24 DWORD *pdwRenderWare; // 24-28 - - char _gap1C[6]; + DWORD dwProcessingFlags; // 28-32 + char _gap20[2]; WORD nModelIndex; // 34-36 @@ -117,6 +131,7 @@ typedef struct _PED_TYPE PED_TASKS_TYPE *Tasks; // 1148-1152 DWORD dwPlayerInfoOffset; // 1152-1156 + char _gap484[124]; DWORD dwActiveVision; // 1280-1284 @@ -138,7 +153,15 @@ typedef struct _PED_TYPE float fRotation1; // 1368-1372 float fRotation2; // 1372-1376 - char _gap560[44]; + char _gap560[8]; + + DWORD pContactVehicle; // 1384 - 1388 + + char _gap56C[24]; + + DWORD pContactEntity; // 1412 - 1416 + + char _gap588[4]; DWORD pVehicle; // 1420-1424 @@ -154,6 +177,10 @@ typedef struct _PED_TYPE BYTE byteCurWeaponSlot; // 1816-1817 + char _gap719[20]; + + BYTE byteFightingStyle; // 1837-1838 + } PED_TYPE; //----------------------------------------------------------- @@ -230,7 +257,12 @@ typedef struct _VEHICLE_TYPE }; }; - char _pad5BA[162]; + char _gap5BA[142]; + + float fBikeBankingAngle1; // 1608-1612 + float fBikeBankingAngle2; // 1612-1616 + + char _gap650[12]; BYTE bBikeWheelPopped[2]; // 1628-1630 diff --git a/saco/game/debug.cpp b/saco/game/debug.cpp new file mode 100644 index 0000000..965c3a6 --- /dev/null +++ b/saco/game/debug.cpp @@ -0,0 +1,201 @@ + +#include "../main.h" +#include "keystuff.h" + +extern CChatWindow *pChatWindow; +extern CGame *pGame; + +int iGameDebugType=0; +DWORD dwDebugEntity1=0; +DWORD dwDebugEntity2=0; + +//---------------------------------------------------------- +// Switches on the debug screen for debugging raw vehicles/actors + +// MATCH +void GameDebugEntity(DWORD dwEnt1, DWORD dwEnt2, int type) +{ + iGameDebugType=type; + dwDebugEntity1=dwEnt1; + dwDebugEntity2=dwEnt2; +} + +//---------------------------------------------------------- +// Switches off any driver debug screen or sync sequence + +// MATCH +void GameDebugScreensOff() +{ + iGameDebugType=0; +} + +//---------------------------------------------------------- + +BOOL bSelVehicleInit=FALSE; +CVehicle *pVehicle=NULL; +int iSelection = 400; +GTA_CONTROLSET *pControls; +CCamera *pCam; + +void GameBuildRecreateVehicle() +{ + if(pVehicle) delete pVehicle; + + pVehicle = pGame->NewVehicle(iSelection,5.0f,5.0f,500.0f,0.0f,NULL); +} + +void GameBuildSelectVehicle() +{ + if(!bSelVehicleInit) { + pControls = GameGetInternalKeys(); + pCam = pGame->GetCamera(); + pCam->SetPosition(-4.0f,-4.0f,502.0f,0.0f,0.0f,0.0f); + pCam->LookAtPoint(5.0f,5.0f,500.0f,1); + pGame->FindPlayerPed()->TogglePlayerControllable(0); + pGame->DisplayGameText("Vehicle Select",4000,6); + GameBuildRecreateVehicle(); + bSelVehicleInit = TRUE; + } + + pGame->DisplayHud(FALSE); + + if(pVehicle && pVehicle->m_pEntity) { + VECTOR vecTurn = { 0.0f, 0.0f, 0.03f }; + VECTOR vecMove = { 0.0f, 0.0f, 0.0f }; + pVehicle->SetTurnSpeedVector(vecTurn); + pVehicle->SetMoveSpeedVector(vecMove); + + MATRIX4X4 mat; + pVehicle->GetMatrix(&mat); + mat.pos.X = 5.0f; + mat.pos.Y = 5.0f; + mat.pos.Z = 500.0f; + pVehicle->SetMatrix(mat); + } + + if(pControls->wKeys1[14] && !pControls->wKeys2[14]) { + iSelection--; + if(iSelection==538) iSelection-=2; // trains + if(iSelection==399) iSelection=611; + GameBuildRecreateVehicle(); + return; + } + + if(pControls->wKeys1[16] && !pControls->wKeys2[16]) { + iSelection++; + if(iSelection==537) iSelection+=2; // trains + if(iSelection==612) iSelection=400; + GameBuildRecreateVehicle(); + return; + } + + if(pControls->wKeys1[15] && !pControls->wKeys2[15]) { + + delete pVehicle; + pVehicle = NULL; + + pCam->SetBehindPlayer(); + GameDebugEntity(0,0,0); + + // place this vehicle near the player. + CPlayerPed *pPlayer = pGame->FindPlayerPed(); + + if(pPlayer) + { + MATRIX4X4 matPlayer; + pPlayer->GetMatrix(&matPlayer); + CHAR blank[9] = ""; + sprintf(blank, "TYPE_%d", iSelection); + CVehicle *pTestVehicle = pGame->NewVehicle(iSelection, + (matPlayer.pos.X - 5.0f), (matPlayer.pos.Y - 5.0f), + matPlayer.pos.Z+1.0f,0.0f,NULL); + + if(pTestVehicle) { + pPlayer->PutDirectlyInVehicle(pTestVehicle->m_dwGTAId,0); + } + } + + pCam->Restore(); + pCam->SetBehindPlayer(); + pGame->FindPlayerPed()->TogglePlayerControllable(1); + pGame->DisplayHud(TRUE); + bSelVehicleInit=FALSE; + + return; + } +} + +//---------------------------------------------------------- + +VECTOR vecSpawnPoint; +CObjectPool *pObjectPool=NULL; + +// MATCH +char* GetFunctionParams(char *szScriptLine) +{ + char *szParamsStart = strchr(szScriptLine, '('); + char *szParamsEnd = strchr(szScriptLine, ')'); + + if(szParamsStart && szParamsEnd) + { + strncpy(szScriptLine, szParamsStart + 1, szParamsEnd - szParamsStart - 1); + szScriptLine[szParamsEnd - szParamsStart] = 0; + return szScriptLine; + } + return NULL; +} + +void GameDebugProcessScriptLine(char *szScriptLine) +{ + if(!strncmp(szScriptLine, "CreateObject", 12)) + { + + } + else if(!strncmp(szScriptLine, "CreateVehicle", 13) || !strncmp(szScriptLine, "AddStaticVehicle", 16)) + { + + } + else if (!strncmp(szScriptLine, "SetPlayerCameraPos", 18)) + { + + } + else if(!strncmp(szScriptLine, "SetPlayerCameraLookAt", 21)) + { + + } + else if(!strncmp(szScriptLine, "RemoveBuildingForPlayer", 23)) + { + + } + else if (!strncmp(szScriptLine, "SetPlayerInterior", 17)) + { + + } +} + +void GameDebugLoadScript(char *szFileName) +{ + pGame->SetWorldTime(12, 0); + pChatWindow->AddDebugMessage("DEBUGSCRIPT: Loading %s", szFileName); + + pObjectPool = new CObjectPool(); + + FILE *pScriptFile = fopen(szFileName, "r"); + if(pScriptFile) { + while(!feof(pScriptFile)) { + char szScriptLine[257]; + fgets(szScriptLine,256,pScriptFile); + GameDebugProcessScriptLine(szScriptLine); + } + fclose(pScriptFile); + + CPlayerPed *pPlayerPed = pGame->FindPlayerPed(); + if(pPlayerPed) { + pPlayerPed->TeleportTo(vecSpawnPoint.X, vecSpawnPoint.Y, vecSpawnPoint.Z); + } + } else { + pChatWindow->AddDebugMessage("DEBUGSCRIPT: I can't open %s", szFileName); + } +} + +//---------------------------------------------------------- diff --git a/saco/game/debug.h b/saco/game/debug.h new file mode 100644 index 0000000..e69de29 diff --git a/saco/game/entity.cpp b/saco/game/entity.cpp index baf75f8..26b9f0b 100644 --- a/saco/game/entity.cpp +++ b/saco/game/entity.cpp @@ -12,7 +12,7 @@ extern CNetGame *pNetGame; extern CChatWindow *pChatWindow; //----------------------------------------------------------- - +// MATCH void CEntity::GetMatrix(PMATRIX4X4 Matrix) { if (!m_pEntity || !m_pEntity->mat) return; @@ -35,7 +35,7 @@ void CEntity::GetMatrix(PMATRIX4X4 Matrix) } //----------------------------------------------------------- - +// MATCH void CEntity::SetMatrix(MATRIX4X4 Matrix) { if (!m_pEntity || !m_pEntity->mat) return; @@ -59,32 +59,36 @@ void CEntity::SetMatrix(MATRIX4X4 Matrix) //----------------------------------------------------------- -void CEntity::FUNC_1009EC80() +void CEntity::UpdateRwMatrixAndFrame() { - if(!m_pEntity || m_pEntity->vtable == 0x863C40) return; + if(!m_pEntity) return; + if(m_pEntity->vtable == 0x863C40) return; + + if(!m_pEntity) return; DWORD dwRenderWare = (DWORD)m_pEntity->pdwRenderWare; DWORD dwMatrix = (DWORD)m_pEntity->mat; DWORD dwEntity = (DWORD)m_pEntity; - if(dwEntity && dwRenderWare && dwMatrix) - { - _asm mov edx, dwRenderWare - _asm mov eax, [edx+4] - _asm add eax, 16 - _asm push eax - _asm mov ecx, dwMatrix - _asm mov edx, 0x59AD70 - _asm call edx + if(!m_pEntity) return; + if(!m_pEntity->pdwRenderWare) return; + if(!m_pEntity->mat) return; - _asm mov ecx, dwEntity - _asm mov edx, 0x532B00 - _asm call edx - } + _asm mov edx, dwRenderWare + _asm mov eax, [edx+4] + _asm add eax, 16 + _asm push eax + _asm mov ecx, dwMatrix + _asm mov edx, 0x59AD70 ; CMatrix__UpdateRwMatrix + _asm call edx + + _asm mov ecx, dwEntity + _asm mov edx, 0x532B00 ; CEntity__UpdateRwFrame + _asm call edx } //----------------------------------------------------------- - +// MATCH void CEntity::GetMoveSpeedVector(PVECTOR Vector) { Vector->X = m_pEntity->vecMoveSpeed.X; @@ -93,7 +97,7 @@ void CEntity::GetMoveSpeedVector(PVECTOR Vector) } //----------------------------------------------------------- - +// MATCH void CEntity::SetMoveSpeedVector(VECTOR Vector) { m_pEntity->vecMoveSpeed.X = Vector.X; @@ -117,16 +121,58 @@ void CEntity::FUNC_1009ED40(float fX, float fY, float fZ) field_4[4].Y = fY; field_4[4].Z = fZ; - m_pEntity->vecMoveSpeed.X = - (field_4[0].X + field_4[1].X + field_4[2].X + field_4[3].X + field_4[4].X) * 0.2f; - m_pEntity->vecMoveSpeed.Y = - (field_4[0].Y + field_4[1].Y + field_4[2].Y + field_4[3].Y + field_4[4].Y) * 0.2f; - m_pEntity->vecMoveSpeed.Z = - (field_4[0].Z + field_4[1].Z + field_4[2].Z + field_4[3].Z + field_4[4].Z) * 0.2f; + fX = field_4[0].X; + fY = field_4[0].Y; + fZ = field_4[0].Z; + + fX += field_4[1].X; + fY += field_4[1].Y; + fZ += field_4[1].Z; + + fX += field_4[2].X; + fY += field_4[2].Y; + fZ += field_4[2].Z; + + fX += field_4[3].X; + fY += field_4[3].Y; + fZ += field_4[3].Z; + + fX += field_4[4].X; + fY += field_4[4].Y; + fZ += field_4[4].Z; + + fX *= 0.2f; + fY *= 0.2f; + fZ *= 0.2f; + + m_pEntity->vecMoveSpeed.X = fX; + m_pEntity->vecMoveSpeed.Y = fY; + m_pEntity->vecMoveSpeed.Z = fZ; + + /*fX = field_4[0].X; + fY = field_4[0].Y; + fZ = field_4[0].Z; + + fX += field_4[1].X; + fY += field_4[1].Y; + fZ += field_4[1].Z; + + fX += field_4[2].X; + fY += field_4[2].Y; + fZ += field_4[2].Z; + + float fRX = (field_4[0].X + field_4[1].X + field_4[2].X + field_4[3].X + field_4[4].X) * 0.2f; + float fRY = (field_4[0].Y + field_4[1].Y + field_4[2].Y + field_4[3].Y + field_4[4].Y) * 0.2f; + float fRZ = (field_4[0].Z + field_4[1].Z + field_4[2].Z + field_4[3].Z + field_4[4].Z) * 0.2f; + + m_pEntity->vecMoveSpeed.X = fX; + m_pEntity->vecMoveSpeed.Y = fY; + m_pEntity->vecMoveSpeed.Z = fZ; + */ } //----------------------------------------------------------- - +// MATCH void CEntity::GetTurnSpeedVector(PVECTOR Vector) { Vector->X = m_pEntity->vecTurnSpeed.X; @@ -135,7 +181,7 @@ void CEntity::GetTurnSpeedVector(PVECTOR Vector) } //----------------------------------------------------------- - +// MATCH void CEntity::SetTurnSpeedVector(VECTOR Vector) { m_pEntity->vecTurnSpeed.X = Vector.X; @@ -144,7 +190,7 @@ void CEntity::SetTurnSpeedVector(VECTOR Vector) } //----------------------------------------------------------- - +// MATCH void CEntity::ApplyTurnSpeed() { DWORD dwEnt = (DWORD)m_pEntity; @@ -156,7 +202,7 @@ void CEntity::ApplyTurnSpeed() } //----------------------------------------------------------- - +// MATCH float CEntity::GetDistanceFromCentreOfMassToBaseOfModel() { DWORD dwEnt = (DWORD)m_pEntity; @@ -173,7 +219,7 @@ float CEntity::GetDistanceFromCentreOfMassToBaseOfModel() } //----------------------------------------------------------- - +// MATCH void CEntity::GetBoundCentre(PVECTOR Vector) { DWORD dwEnt = (DWORD)m_pEntity; @@ -186,7 +232,7 @@ void CEntity::GetBoundCentre(PVECTOR Vector) } //----------------------------------------------------------- - +// MATCH void CEntity::GetBoundRect(PFRECT Rect) { DWORD dwEnt = (DWORD)m_pEntity; @@ -199,14 +245,57 @@ void CEntity::GetBoundRect(PFRECT Rect) } //----------------------------------------------------------- +// MATCH +BOOL CEntity::SetModelIndex(UINT uiModel) +{ + if(!m_pEntity) return FALSE; + BOOL bResult=FALSE; + int iCounter=0; + + if(!pGame->IsModelLoaded(uiModel) && !GetModelRwObject(uiModel)) { + pGame->RequestModel(uiModel); + pGame->LoadRequestedModels(); + while(!pGame->IsModelLoaded(uiModel)) { + Sleep(1); + iCounter++; + if(iCounter>200) { + if(pChatWindow) + pChatWindow->AddDebugMessage("Warning: Model %u wouldn't load in time!", uiModel); + return FALSE; + } + } + bResult = TRUE; + } + + DWORD dwThisEntity = (DWORD)m_pEntity; + + _asm { + mov esi, dwThisEntity + mov edi, uiModel + mov edx, [esi] + mov ecx, esi + call dword ptr [edx+32] ; destroy RW + mov eax, [esi] + mov edx, edi + push edi + mov ecx, esi + mov word ptr [esi+34], dx + call dword ptr [eax+20] ; SetModelIndex + } + + return bResult; +} + +//----------------------------------------------------------- +// MATCH UINT CEntity::GetModelIndex() { return m_pEntity->nModelIndex; } //----------------------------------------------------------- - +// MATCH void CEntity::TeleportTo(float x, float y, float z) { DWORD dwThisEntity = (DWORD)m_pEntity; @@ -229,7 +318,7 @@ void CEntity::TeleportTo(float x, float y, float z) } //----------------------------------------------------------- - +// MATCH float CEntity::GetDistanceFromLocalPlayerPed() { MATRIX4X4 matFromPlayer; @@ -262,7 +351,7 @@ float CEntity::GetDistanceFromLocalPlayerPed() } //----------------------------------------------------------- - +// MATCH float CEntity::GetDistanceFromCamera() { if(!m_pEntity || m_pEntity->vtable == 0x863C40) return 100000.0f; @@ -279,7 +368,7 @@ float CEntity::GetDistanceFromCamera() } //----------------------------------------------------------- - +// MATCH float CEntity::Get2DDistanceFromLocalPlayerPed() { MATRIX4X4 matFromPlayer; @@ -311,7 +400,7 @@ float CEntity::Get2DDistanceFromLocalPlayerPed() } //----------------------------------------------------------- - +// MATCH float CEntity::GetDistanceFromPoint(float X, float Y, float Z) { MATRIX4X4 matThis; @@ -326,7 +415,7 @@ float CEntity::GetDistanceFromPoint(float X, float Y, float Z) } //----------------------------------------------------------- - +// MATCH void CEntity::Add() { // Check for CPlaceable messup @@ -362,7 +451,7 @@ void CEntity::Add() } //----------------------------------------------------------- - +// MATCH BOOL CEntity::IsAdded() { // Check for CPlaceable messup @@ -377,7 +466,7 @@ BOOL CEntity::IsAdded() } //----------------------------------------------------------- - +// MATCH void CEntity::Remove() { // Check for CPlaceable messup @@ -402,7 +491,7 @@ void CEntity::Remove() } //----------------------------------------------------------- - +// MATCH BOOL CEntity::EnforceWorldBoundries(float fPX, float fZX, float fPY, float fNY) { MATRIX4X4 matWorld; @@ -464,7 +553,7 @@ BOOL CEntity::EnforceWorldBoundries(float fPX, float fZX, float fPY, float fNY) } //----------------------------------------------------------- - +// MATCH BOOL CEntity::HasExceededWorldBoundries(float fPX, float fZX, float fPY, float fNY) { MATRIX4X4 matWorld; @@ -489,7 +578,7 @@ BOOL CEntity::HasExceededWorldBoundries(float fPX, float fZX, float fPY, float f } //----------------------------------------------------------- - +// MATCH void CEntity::SetCollisionChecking(int iCheck) { if(!m_pEntity) return; @@ -503,7 +592,7 @@ void CEntity::SetCollisionChecking(int iCheck) } //----------------------------------------------------------- - +// MATCH BOOL CEntity::IsCollisionCheckingEnabled() { if(m_pEntity && m_pEntity->vtable != 0x863C40) @@ -514,7 +603,7 @@ BOOL CEntity::IsCollisionCheckingEnabled() } //----------------------------------------------------------- - +// MATCH void CEntity::SetGravityProcessing(int iState) { if(!m_pEntity) return; @@ -528,7 +617,7 @@ void CEntity::SetGravityProcessing(int iState) } //----------------------------------------------------------- - +// MATCH void CEntity::SetWaitingForCollision(int iState) { if(!m_pEntity) return; @@ -543,7 +632,7 @@ void CEntity::SetWaitingForCollision(int iState) } //----------------------------------------------------------- - +// MATCH void CEntity::DisableStreaming() { if(!m_pEntity) return; @@ -553,7 +642,7 @@ void CEntity::DisableStreaming() } //----------------------------------------------------------- - +// MATCH void CEntity::EnableTunnelTransition() { if(!m_pEntity) return; @@ -563,7 +652,7 @@ void CEntity::EnableTunnelTransition() } //----------------------------------------------------------- - +// MATCH void CEntity::SetApplySpeed(int iState) { if(!m_pEntity) return; @@ -592,7 +681,7 @@ void CEntity::SetApplySpeed(int iState) //----------------------------------------------------------- - +// MATCH BOOL CEntity::IsStationary() { if (!IsAdded()) return FALSE; // movespeed vectors are invalid if its not added diff --git a/saco/game/entity.h b/saco/game/entity.h index 73a49cd..e5938f8 100644 --- a/saco/game/entity.h +++ b/saco/game/entity.h @@ -1,6 +1,8 @@ #pragma once +#include "game.h" + //---------------------------------------------------------- class CEntity @@ -13,7 +15,7 @@ public: void GetMatrix(PMATRIX4X4 Matrix); void SetMatrix(MATRIX4X4 Matrix); - void FUNC_1009EC80(); + void UpdateRwMatrixAndFrame(); void GetMoveSpeedVector(PVECTOR Vector); void SetMoveSpeedVector(VECTOR Vector); void FUNC_1009ED40(float fX, float fY, float fZ); // unused @@ -24,6 +26,7 @@ public: void GetBoundCentre(PVECTOR Vector); void GetBoundRect(PFRECT Rect); // unused UINT GetModelIndex(); + BOOL SetModelIndex(UINT uiModel); void TeleportTo(float x, float y, float z); float GetDistanceFromLocalPlayerPed(); float GetDistanceFromCamera(); diff --git a/saco/game/game.cpp b/saco/game/game.cpp index 068ef0d..63053d0 100644 --- a/saco/game/game.cpp +++ b/saco/game/game.cpp @@ -1,5 +1,6 @@ #include "../main.h" +#include "game.h" #include "util.h" #include "keystuff.h" #include "aimstuff.h" @@ -18,15 +19,9 @@ DWORD dwDummyActiveMouseState; unsigned char *szGameTextMessage; HWND hWindowHandle; -int unnamed_10150340[210]; +BOOL bUsedPlayerSlots[PLAYER_PED_SLOTS]; IDirectInputDevice8 *pDirectInputMouse; -BYTE unnamed_10150688; -int unnamed_1015068C; - -float unnamed_10116718 = 2.0f; - -BOOL ApplyPreGamePatches(); bool GLOBAL_101506A4; typedef void (*DrawZone_t)(float *fPos, DWORD *dwColor, BYTE byteMenu); @@ -38,80 +33,77 @@ CGame::CGame() m_pGameAudio = new CAudio(); m_pGameCamera = new CCamera(); m_pGamePlayer = NULL; - field_4D = 0; + m_bCheckpointsEnabled = FALSE; m_bRaceCheckpointsEnabled = FALSE; m_dwRaceCheckpointHandle = NULL; field_61 = 0; field_65 = 0; field_69 = FALSE; field_6D = 0; - memset(unnamed_10150340, 0, sizeof(unnamed_10150340)); - memset(field_6E, 0, sizeof(field_6E)); + memset(bUsedPlayerSlots,0,sizeof(BOOL)*PLAYER_PED_SLOTS); + memset(m_byteKeepLoadedVehicles,0,sizeof(BYTE)*212); field_55 = 0; field_59 = 1; field_5D = 90; } -void CGame::sub_100A0010() -{ - int time = (int)RakNet::GetTime(); - if(unnamed_1015068C) - { - if((time - unnamed_1015068C) > 30) - { - unnamed_10150688++; - if(unnamed_10150688 == 5) - unnamed_10150688 = 0; - unnamed_1015068C = time; - } - *(BYTE*)0xB7356E = unnamed_10150688; - } - else - { - unnamed_1015068C = time; - } -} +//----------------------------------------------------------- -void unnamed_100A0060(float a1) -{ - *(float*)0xB7CB5C = a1; - *(float*)0xB7CB58 = a1; - unnamed_10116718 = a1 * 3.0f; -} -void CGame::sub_100A0090(int a1, int a2) -{ - if(a1 && a2 && a1 < 1000 / a2) - Sleep(1000 / a2 - a1 - 1); -} -BYTE CGame::sub_100A00C0() + +//----------------------------------------------------------- + +BYTE CGame::FindFirstFreePlayerPedSlot() { - BYTE result = 2; - while(result != 210) - { - if(!unnamed_10150340[result]) - return result; - result++; + BYTE x=2; + while(x!=PLAYER_PED_SLOTS) { + if(!bUsedPlayerSlots[x]) return x; + x++; } return 0; } -BYTE CGame::sub_100A00F0() +//----------------------------------------------------------- + + + +//----------------------------------------------------------- + +BOOL CGame::DeletePlayer(CPlayerPed *pPlayerPed) { - BYTE result = 0; - BYTE v1 = 2; - while(v1 != 210) + if(pPlayerPed) { - if(unnamed_10150340[v1] == 1) - { - result++; - } - v1++; + BYTE bytePlayerNumber = pPlayerPed->m_bytePlayerNumber; + delete pPlayerPed; + bUsedPlayerSlots[bytePlayerNumber] = FALSE; + return TRUE; } - return result; + return FALSE; } +//----------------------------------------------------------- + +CVehicle *CGame::NewVehicle(int iType, float fPosX, float fPosY, + float fPosZ, float fRotation, int a7) +{ + BOOL bKeepModelLoaded=FALSE; + + if(m_byteKeepLoadedVehicles[iType-400]) { + bKeepModelLoaded=TRUE; + } + + CVehicle *pVehicleNew = new CVehicle(iType,fPosX,fPosY,fPosZ,fRotation,bKeepModelLoaded,a7); + + if(pVehicleNew->m_pVehicle) return pVehicleNew; + return NULL; +} + +//----------------------------------------------------------- + + + + //----------------------------------------------------------- @@ -146,13 +138,14 @@ float CGame::FindGroundZForCoord(float x, float y, float z) void DIReleaseMouse() { pDirectInputMouse = *(IDirectInputDevice8**)0xC8CFA4; - //SAFE_RELEASE(pDirectInputMouse); + if(pDirectInputMouse) { pDirectInputMouse->Release(); *(IDirectInputDevice8**)0xC8CFA4 = NULL; } } + void DIInitMouse() { pDirectInputMouse = *(IDirectInputDevice8**)0xC8CFA4; @@ -165,6 +158,7 @@ void DIInitMouse() pDirectInputMouse->Acquire(); } + void DIResetMouse() { *(DWORD*)0xB73424 = 0; @@ -174,17 +168,16 @@ void DIResetMouse() _asm call edx } + void UpdatePads() { _asm mov edx, 0x541DD0 _asm call edx } + void DisableMousePositionUpdate() { - //*(DWORD*)0xB7340C = 0; - //*(DWORD*)0xB73410 = 0; - //*(DWORD*)0xB73414 = 0; memset((PVOID)0xB7340C,0,12); UnFuck(0x53F47A,4); @@ -195,6 +188,7 @@ void DisableMousePositionUpdate() *(DWORD*)0x53F4B3 = (DWORD)&dwDummyActiveMouseState; } + void RestoreMousePositionUpdate() { UnFuck(0x53F47A,4); @@ -205,6 +199,7 @@ void RestoreMousePositionUpdate() *(DWORD*)0x53F4B3 = 0xB7340C; } + void DisableMouseProcess() { UnFuck(0x53F417,5); @@ -378,73 +373,12 @@ void CGame::StartGame() //----------------------------------------------------------- - - - - - - -void CGame::sub_100A0110() +BOOL CGame::IsMenuActive() { - // TODO: CGame::sub_100A0110() .text:100A0110 + if(*(PDWORD)ADDR_MENU) return TRUE; + return FALSE; } -void CGame::sub_100A0210() -{ - // TODO: CGame::sub_100A0210() .text:100A0210 -} - -void CGame::sub_100A0250() -{ - // TODO: CGame::sub_100A0250() .text:100A0250 -} - -void CGame::sub_100A02E0() -{ - // TODO: CGame::sub_100A02E0() .text:100A02E0 (unused) -} - -void CGame::sub_100A0310() -{ - // TODO: CGame::sub_100A0310() .text:100A0310 (unused) -} - -void CGame::sub_100A0330() -{ - // TODO: CGame::sub_100A0330() .text:100A0330 -} - - - - - - - - - - - - - - - - - - - - - - - - -void CGame::sub_100A1C10() -{ - // TODO: CGame::sub_100A1C10() .text:100A1C10 -} - - - - //----------------------------------------------------------- // Return TRUE if the world has been loaded. @@ -458,14 +392,6 @@ BOOL CGame::IsGameLoaded() void CGame::RequestModel(int iModelID, int iLoadingStream) { - /* - _asm push iLoadingStream - _asm push iModelID - _asm mov edx, 0x4087E0 - _asm call edx - _asm pop edx - _asm pop edx*/ - ScriptCommand(&request_model,iModelID); } @@ -473,12 +399,6 @@ void CGame::RequestModel(int iModelID, int iLoadingStream) void CGame::LoadRequestedModels() { - /* - _asm push 0 - _asm mov edx, 0x40EA10 - _asm call edx - _asm add esp, 4*/ - ScriptCommand(&load_requested_models); } @@ -493,6 +413,13 @@ BOOL CGame::IsModelLoaded(int iModelID) //----------------------------------------------------------- +void CGame::RemoveModel(int iModelID, bool a2) +{ + // TODO: CGame::RemoveModel .text:100A09A0 +} + +//----------------------------------------------------------- + BOOL CGame::SetModelDeletable(int iModelID) { BYTE * pStreamingModelInfo = (BYTE*)(iModelID * 20); @@ -616,7 +543,7 @@ void CGame::SetFrameLimiterOn(BOOL bLimiter) BOOL CGame::IsFrameLimiterEnabled() { - if(*(PBYTE)0xBA6794) return TRUE; + if(*(BYTE*)0xBA6794) return TRUE; return FALSE; } @@ -698,14 +625,14 @@ void CGame::ToggleRadar(int iToggle) } //----------------------------------------------------------- -// MATCH + void CGame::DisplayGameText(char *szStr,int iTime,int iSize) { if(iSize > 200) return; ScriptCommand(&text_clear_all); - memset(szGameTextMessage,0,sizeof(szGameTextMessage)); // not a typo + memset(szGameTextMessage,0,sizeof(szGameTextMessage)); strncpy((char*)szGameTextMessage,szStr,512); @@ -726,6 +653,59 @@ void CGame::DisplayGameText(char *szStr,int iTime,int iSize) //----------------------------------------------------------- +void CGame::SetCheckpointInformation(VECTOR *pos, VECTOR *extent) +{ + memcpy(&m_vecCheckpointPos,pos,sizeof(VECTOR)); + memcpy(&m_vecCheckpointExtent,extent,sizeof(VECTOR)); + if(m_dwCheckpointMarker) { + DisableMarker(m_dwCheckpointMarker); + m_dwCheckpointMarker = NULL; + + DWORD dwMarkerID = 0; + ScriptCommand(&create_radar_marker_without_sphere, m_vecCheckpointPos.X, m_vecCheckpointPos.Y, m_vecCheckpointPos.Z, 0, &dwMarkerID); + ScriptCommand(&set_marker_color, dwMarkerID, 1005); + ScriptCommand(&show_on_radar, dwMarkerID, 3); + m_dwCheckpointMarker = dwMarkerID; + } +} + +//----------------------------------------------------------- + +void CGame::SetRaceCheckpointInformation(BYTE byteType, VECTOR *pos, VECTOR *next, float fSize) //VECTOR *extent) +{ + memcpy(&m_vecRaceCheckpointPos,pos,sizeof(VECTOR)); + memcpy(&m_vecRaceCheckpointNext,next,sizeof(VECTOR)); + m_fRaceCheckpointSize = fSize; + m_byteRaceType = byteType; + if(m_dwRaceCheckpointMarker) + { + DisableMarker(m_dwRaceCheckpointMarker); + m_dwRaceCheckpointMarker = NULL; + + DWORD dwMarkerID = 0; + ScriptCommand(&create_radar_marker_without_sphere, m_vecRaceCheckpointPos.X, m_vecRaceCheckpointPos.Y, m_vecRaceCheckpointPos.Z, 0, &dwMarkerID); + ScriptCommand(&set_marker_color, dwMarkerID, 1005); + ScriptCommand(&show_on_radar, dwMarkerID, 3); + m_dwRaceCheckpointMarker = dwMarkerID; + } + MakeRaceCheckpoint(); +} + +//----------------------------------------------------------- + +void CGame::MakeRaceCheckpoint() +{ + DisableRaceCheckpoint(); + + ScriptCommand(&create_racing_checkpoint, (int)m_byteRaceType, + m_vecRaceCheckpointPos.X, m_vecRaceCheckpointPos.Y, m_vecRaceCheckpointPos.Z, + m_vecRaceCheckpointNext.X, m_vecRaceCheckpointNext.Y, m_vecRaceCheckpointNext.Z, + m_fRaceCheckpointSize, &m_dwRaceCheckpointHandle); + + m_bRaceCheckpointsEnabled = true; +} + + void CGame::DisableRaceCheckpoint() { if (m_dwRaceCheckpointHandle) @@ -738,6 +718,56 @@ void CGame::DisableRaceCheckpoint() //----------------------------------------------------------- +void CGame::UpdateCheckpoints() +{ + DWORD dwMarkerID; + + if(m_bCheckpointsEnabled) { + CPlayerPed *pPlayerPed = this->FindPlayerPed(); + if(pPlayerPed) { + ScriptCommand(&is_actor_near_point_3d,pPlayerPed->m_dwGTAId, + m_vecCheckpointPos.X,m_vecCheckpointPos.Y,m_vecCheckpointPos.Z, + m_vecCheckpointExtent.X,m_vecCheckpointExtent.Y,m_vecCheckpointExtent.Z,1); + if (!m_dwCheckpointMarker) + { + dwMarkerID = 0; + ScriptCommand(&create_radar_marker_without_sphere, + m_vecCheckpointPos.X, m_vecCheckpointPos.Y, m_vecCheckpointPos.Z, 0, &dwMarkerID); + ScriptCommand(&set_marker_color, dwMarkerID, 1005); + ScriptCommand(&show_on_radar, dwMarkerID, 3); + m_dwCheckpointMarker = dwMarkerID; + } + } + } + else if(m_dwCheckpointMarker) { + DisableMarker(m_dwCheckpointMarker); + m_dwCheckpointMarker = NULL; + } + + if(m_bRaceCheckpointsEnabled) { + CPlayerPed *pPlayerPed = this->FindPlayerPed(); + if(pPlayerPed) + { + if (!m_dwRaceCheckpointMarker) + { + dwMarkerID = 0; + ScriptCommand(&create_radar_marker_without_sphere, + m_vecRaceCheckpointPos.X,m_vecRaceCheckpointPos.Y,m_vecRaceCheckpointPos.Z,0,&dwMarkerID); + ScriptCommand(&set_marker_color, dwMarkerID, 1005); + ScriptCommand(&show_on_radar, dwMarkerID, 3); + m_dwRaceCheckpointMarker = dwMarkerID; + } + } + } + else if(m_dwRaceCheckpointMarker) { + DisableMarker(m_dwRaceCheckpointMarker); + DisableRaceCheckpoint(); + m_dwRaceCheckpointMarker = NULL; + } +} + +//----------------------------------------------------------- + DWORD CGame::CreateRadarMarkerIcon(int iMarkerType, float fX, float fY, float fZ, DWORD dwColor, int iStyle) { DWORD dwMarkerID=0; @@ -816,6 +846,20 @@ void CGame::AddToLocalMoney(int iAmount) //----------------------------------------------------------- +void CGame::ResetLocalMoney() +{ + int iMoney = GetLocalMoney(); + if(!iMoney) return; + + if(iMoney < 0) { + AddToLocalMoney(abs(iMoney)); + } else { + AddToLocalMoney(-(iMoney)); + } +} + +//----------------------------------------------------------- + int CGame::GetLocalMoney() { return *(int *)0xB7CE50; @@ -921,6 +965,14 @@ const PCHAR CGame::GetWeaponName(int iWeaponID) //----------------------------------------------------------- +DWORD CGame::CreatePickup(int iModel, int iType, float fX, float fY, float fZ) +{ + // TODO: CGame::CreatePickup .text:100A11F0 + return 0; +} + +//----------------------------------------------------------- + DWORD CGame::CreateWeaponPickup(int iModel, DWORD dwAmmo, float fX, float fY, float fZ) { DWORD hnd; @@ -1030,6 +1082,24 @@ void CGame::DrawGangZone(float fPos[], DWORD dwColor) //----------------------------------------------------------- +void CGame::EnableClock(BYTE byteClock) +{ + BYTE byteClockData[] = {'%', '0', '2', 'd', ':', '%', '0', '2', 'd', 0}; + UnFuck(0x859A6C,10); + if (byteClock) + { + ToggleThePassingOfTime(1); + memcpy((PVOID)0x859A6C, byteClockData, 10); + } + else + { + ToggleThePassingOfTime(0); + memset((PVOID)0x859A6C,0,10); + } +} + +//----------------------------------------------------------- + void CGame::EnableZoneNames(BYTE byteEnable) { ScriptCommand(&enable_zone_names, byteEnable); @@ -1113,6 +1183,13 @@ int CGame::GetLoadedVehicleModelCount() //----------------------------------------------------------- +void CGame::SetRequiredVehicleModels(BYTE *ModelCounts) +{ + // TODO: CGame::SetRequiredVehicleModels .text:100A1610 +} + +//----------------------------------------------------------- + void CGame::SetTimeInMilliseconds(DWORD dwTimeInMs) { if(!field_69) { @@ -1137,6 +1214,13 @@ int CGame::GetRwObjectsCount() //----------------------------------------------------------- +void CGame::FUNC_100A1790(int a1, int a2, BOOL bIncludeVehicle, int iModelID, char a5) +{ + // TODO: CGame::FUNC_100A1790 .text:100A1790 +} + +//----------------------------------------------------------- + void CGame::RequestAnimationsAndModels() { if(!IsAnimationLoaded("PARACHUTE")) @@ -1225,3 +1309,11 @@ void CGame::DisableWeaponLockOnTarget() //----------------------------------------------------------- +void CGame::FUNC_100A1C10() +{ + int iTimeNow = (int)RakNet::GetTime(); + + // TODO: CGame::FUNC_100A1C10() .text:100A1C10 +} + +//----------------------------------------------------------- diff --git a/saco/game/game.h b/saco/game/game.h index 7c80fe1..e961a5a 100644 --- a/saco/game/game.h +++ b/saco/game/game.h @@ -3,50 +3,69 @@ #include "address.h" #include "common.h" +#include "vehicle.h" #include "playerped.h" -#include "audio.h" +#include "actorped.h" +#include "object.h" #include "camera.h" #include "scripting.h" #include "menu.h" +#include "textdraw.h" + +#include "audio.h" +#include "modelinfo.h" //----------------------------------------------------------- -class CGame // size: 322 +class CGame { private: CAudio *m_pGameAudio; CCamera *m_pGameCamera; CPlayerPed *m_pGamePlayer; - char gapC[29]; + + VECTOR m_vecRaceCheckpointPos; + VECTOR m_vecRaceCheckpointNext; + float m_fRaceCheckpointSize; + BYTE m_byteRaceType; BOOL m_bRaceCheckpointsEnabled; - char gap2D[4]; + DWORD m_dwRaceCheckpointMarker; DWORD m_dwRaceCheckpointHandle; - char gap35[24]; - int field_4D; - char gap51[4]; + + VECTOR m_vecCheckpointPos; + VECTOR m_vecCheckpointExtent; + BOOL m_bCheckpointsEnabled; + DWORD m_dwCheckpointMarker; + int field_55; int field_59; - DWORD field_5D; + int field_5D; int field_61; int field_65; BOOL field_69; char field_6D; - char field_6E[212]; + BYTE m_byteKeepLoadedVehicles[212]; public: + BYTE FindFirstFreePlayerPedSlot(); + BOOL DeletePlayer(CPlayerPed *pPlayerPed); + CVehicle *NewVehicle(int iType,float fPosX,float fPosY,float fPosZ,float fRotation,int a7); + int GetWeaponModelIDFromWeapon(int iWeaponID); BOOL IsKeyPressed(int iKeyIdentifier); float FindGroundZForCoord(float x, float y, float z); void ToggleKeyInputsDisabled(int a2, BOOL a3); void StartGame(); void InitGame(); + BOOL IsMenuActive(); BOOL IsGameLoaded(); void RequestModel(int iModelID, int iLoadingStream = 2); void LoadRequestedModels(); BOOL IsModelLoaded(int iModelID); + void RemoveModel(int iModelID, bool a2 = false); BOOL SetModelDeletable(int iModelID); void SetWorldTime(int iHour, int iMinute); @@ -69,18 +88,25 @@ public: void ToggleRadar(int iToggle); void DisplayGameText(char *szStr,int iTime,int iSize); void SetGravity(float fGravity); + void EnableClock(BYTE byteClock); void EnableZoneNames(BYTE byteEnable); void SetWantedLevel(BYTE byteLevel); void SetGameTextCount(WORD wCount); void DrawGangZone(float* fPos, DWORD dwColor); void EnableStuntBonus(bool bEnable); + void UpdateCheckpoints(); + void SetCheckpointInformation(VECTOR *pos, VECTOR *extent); + + void MakeRaceCheckpoint(); void DisableRaceCheckpoint(); + void SetRaceCheckpointInformation(BYTE byteType, VECTOR *pos, VECTOR *next, float fSize); DWORD CreateRadarMarkerIcon(int iMarkerType, float fX, float fY, float fZ, DWORD dwColor, int iStyle); void DisableMarker(DWORD dwMarkerID); void AddToLocalMoney(int iAmount); + void ResetLocalMoney(); int GetLocalMoney(); BYTE GetActiveInterior(); @@ -89,15 +115,13 @@ public: DWORD GetD3DDevice(); DWORD GetD3D() { return *(DWORD *)ADDR_ID3D9DEVICE; }; - HWND GetMainWindowHwnd() { return *(HWND *)ADDR_HWND; }; void RestartEverything(); void ProcessInputDisabling(); - //----------------------------------------------------------- - - void FUNC_10062570() { field_55++; }; + CAudio *GetAudio() { return m_pGameAudio; }; + CCamera *GetCamera() { return m_pGameCamera; }; CPlayerPed *FindPlayerPed() { if(m_pGamePlayer==NULL) m_pGamePlayer = new CPlayerPed(); @@ -106,41 +130,36 @@ public: const PCHAR GetWeaponName(int iWeaponID); + DWORD CreatePickup(int iModel, int iType, float fX, float fY, float fZ); DWORD CreateWeaponPickup(int iModel, DWORD dwAmmo, float fX, float fY, float fZ); int GetScreenWidth() { return *(int*)0xC17044; }; int GetScreenHeight() { return *(int*)0xC17048; }; + float GetHudVertScale() { return *(float *)0x859524; }; + float GetHudHorizScale() { return *(float *)0x859520; }; DWORD GetWeaponInfo(int iWeapon, int iUnk); void DisableEnterExits(); CGame(); - void sub_100A0010(); - void sub_100A0090(int a1, int a2); - BYTE sub_100A00C0(); - BYTE sub_100A00F0(); - void sub_100A0110(); - void sub_100A0210(); - void sub_100A0250(); - void sub_100A02E0(); - void sub_100A0310(); - void sub_100A0330(); - - void sub_100A1C10(); + void FUNC_10062570() { field_55++; }; void LoadScene(char* szScene); int GetMemoryUsedForStreaming(); int GetMemoryAvailableForStreaming(); int GetLoadedVehicleModelCount(); + void SetRequiredVehicleModels(BYTE *ModelCounts); void SetTimeInMilliseconds(DWORD dwTimeInMs); DWORD GetTimeInMilliseconds(); int GetRwObjectsCount(); + void FUNC_100A1790(int a1, int a2, BOOL bIncludeVehicle, int iModelID, char a5); void RequestAnimationsAndModels(); void LoadCollisionFile(char *szFileName); void LoadCullZone(char *szLine); BOOL IsUsingController(); void DisableWeaponLockOnTarget(); + void FUNC_100A1C10(); }; //----------------------------------------------------------- diff --git a/saco/game/hooks.cpp b/saco/game/hooks.cpp index 65044d5..98172a9 100644 --- a/saco/game/hooks.cpp +++ b/saco/game/hooks.cpp @@ -1,39 +1,74 @@ #include "../main.h" +#include "game.h" +#include "util.h" +#include "keystuff.h" +#include "aimstuff.h" extern int iGtaVersion; +extern CNetGame* pNetGame; +extern CGame* pGame; +extern CChatWindow *pChatWindow; extern DWORD dwGraphicsLoop; // Used for the external dll game loop. -#define NUDE void _declspec(naked) +int WINAPI exc_filter(unsigned int code, struct _EXCEPTION_POINTERS *ep, char *what); +#define NUDE void _declspec(naked) + +//----------------------------------------------------------- +// Globals which are used to avoid stack frame alteration +// inside the following hook procedures. + +GTA_CONTROLSET *pGcsKeys; + +DWORD dwFarClipHookAddr=0; +DWORD dwFarClipReturnAddr=0; + +// used generically +PED_TYPE *_pPlayer; + +BYTE byteInternalPlayer=0; +DWORD dwCurPlayerActor=0; +BYTE byteCurPlayer=0; +BYTE byteSavedCameraMode; +WORD wSavedCameraMode2; BYTE *pbyteCameraMode = (BYTE *)0xB6F1A8; BYTE *pbyteCurrentPlayer = (BYTE *)0xB7CD74; +WORD *wCameraMode2 = (WORD*)0xB6F858; +DWORD *pdwVehicleEnginePed = (DWORD *)0xB6B990; + +float fHealth; float fFarClip=1400.0f; -DWORD unnamed_101516D4; +//----------------------------------------------------------- +// currently unknown where would it be placed +DWORD GLOBAL_101516D4; +WORD wLastRendObj; +CPlayerPool *_pPlayerPool; -WORD wLastRendObj=0; +//----------------------------------------------------------- +// x86 codes to perform our unconditional jmp for detour entries. -BYTE Unk1_JmpCode[] = {0xFF,25,0xD1,0xBE,53,0x00}; -BYTE TaskEnterVehicleDriver_HookJmpCode[] = {0xFF,0x25,0xBB,0x19,0x69,0x00,0x90}; -BYTE TaskExitVehicle_HookJmpCode[] = {0xFF,0x25,0xBA,0xB8,0x63,0x00,0x90}; -BYTE RadarTranslateColor_HookJmpCode[] = {0xFF,0x25,0x79,0x4A,0x58,0x00,0x90}; -BYTE CheatProcessHook_JmpCode[] = {0xFF,0x25,0xAA,0x85,0x43,0x00,0x90}; -BYTE Unk2_JmpCode[] = {0xFF,0x25,0x33,0x14,0x42,0x00}; -BYTE Unk3_JmpCode[] = {0xFF,0x25,0x61,0x36,0x53,0x00,0x90,0x90,0x90}; -BYTE CGameShutdown_HookJmpCode[] = {0xFF,0x25,0xF1,0xC8,0x53,0x00,0x90}; -BYTE PedDamage_HookJmpCode[] = {0xFF,0x25,0xBC,0x5A,0x4B,0x00}; -BYTE Unk4_JmpCode[] = {0xFF,0x25,0x74,0x22,0x50,0x00,0x90,0x90,0x90,0x90}; -BYTE Unk5_JmpCode[] = {0xFF,0x25,0x61,0x38,0x4C,0x00}; -BYTE GetText_HookJmpCode[] = {0xFF,0x25,0x43,0x00,0x6A,0x00,0x90,0x90,0x90}; -BYTE Unk6_JmpCode[] = {0xFF,0x25,0xD8,0xFF,0x5E,0x00,0x90}; -BYTE CProjectileInfo_Update_HookJmpCode[] = {0xFF,0x25,0x1B,0x8B,0x73,0x00}; -BYTE CWeapon__Satchel__Activate_HookJmpCode[] = {0xFF,0x25,0x5B,0x88,0x73,0x00}; -BYTE Unk7_JmpCode[] = {0xFF,0x25,0x36,0xA0,0x63,0x00,0x90}; -BYTE Unk8_JmpCode[] = {0xFF,0x25,0x77,0xAB,0x5E,0x00,0x90}; -BYTE Unk9_JmpCode[] = {0xFF,0x25,0x39,0x88,0x4C,0x00,0x90,0x90}; +BYTE GameProcess_HookJmpCode[] = {0xFF,0x25,0xD1,0xBE,0x53,0x00}; //53BED1 +BYTE TaskEnterVehicleDriver_HookJmpCode[] = {0xFF,0x25,0xBB,0x19,0x69,0x00,0x90};//0x6919BB +BYTE TaskExitVehicle_HookJmpCode[] = {0xFF,0x25,0xBA,0xB8,0x63,0x00,0x90};//0x63B8BA +BYTE RadarTranslateColor_HookJmpCode[] = {0xFF,0x25,0x79,0x4A,0x58,0x00,0x90}; // 584A79 +BYTE CheatProcessHook_JmpCode[] = {0xFF,0x25,0xAA,0x85,0x43,0x00,0x90}; // 4385AA +BYTE AddVehicleHook_HookJmpCode[] = {0xFF,0x25,0x33,0x14,0x42,0x00}; // 421433 +BYTE SetFarClip_HookJmpCode[] = {0xFF,0x25,0x61,0x36,0x53,0x00,0x90,0x90,0x90}; // 533661 +BYTE CGameShutdown_HookJmpCode[] = {0xFF,0x25,0xF1,0xC8,0x53,0x00,0x90}; // 53C8F1 +BYTE PedDamage_HookJmpCode[] = {0xFF,0x25,0xBC,0x5A,0x4B,0x00}; // 4B5ABC +BYTE VehicleAudio_HookJmpCode[] = {0xFF,0x25,0x74,0x22,0x50,0x00,0x90,0x90,0x90,0x90}; // 502274 +BYTE GenTaskAlloc_HookJmpCode[] = {0xFF,0x25,0x61,0x38,0x4C,0x00}; // 4C3861 +BYTE GetText_HookJmpCode[] = {0xFF,0x25,0x43,0x00,0x6A,0x00,0x90,0x90,0x90}; // 0x6A004325 +BYTE PedSay_HookJmpCode[] = {0xFF,0x25,0xD8,0xFF,0x5E,0x00,0x90}; //5EFFD8 +BYTE CProjectileInfo_Update_HookJmpCode[] = {0xFF,0x25,0x1B,0x8B,0x73,0x00}; //00738B1B +BYTE CWeapon__Satchel__Activate_HookJmpCode[] = {0xFF,0x25,0x5B,0x88,0x73,0x00}; // 0073885B +BYTE SetColor_HookJmpCode[] = {0xFF,0x25,0x36,0xA0,0x63,0x00,0x90}; +BYTE Rand_HookJmpCode[] = {0xFF,0x25,0x77,0xAB,0x5E,0x00,0x90}; // 5EAB77 +BYTE VehicleModel_SetEnvironmentMap_JmpCode[] = {0xFF,0x25,0x39,0x88,0x4C,0x00,0x90,0x90}; // 4C8839 BYTE HOOK_7_JmpCode[] = {0xFF,0x25,0x34,0x39,0x4D,0x00,0x90,0x90,0x90,0x90}; BYTE HOOK_8_JmpCode[] = {0xFF,0x25,0x09,0x46,0x4D,0x00,0x90}; BYTE Unk10_JmpCode[] = {0xFF,0x25,0xE5,0x42,0x4D,0x00,0x90}; @@ -48,23 +83,23 @@ BYTE HOOK_60_JmpCode[] = {0xFF,0x25,0xDB,0x74,0x56,0x00}; //----------------------------------------------------------- - // TODO: HOOK_*() functions NUDE HOOK_1() {} NUDE HOOK_2() {} NUDE HOOK_3() {} NUDE HOOK_4() {} NUDE CPed_Render_Hook() {} + NUDE HOOK_7() {} NUDE HOOK_8() {} -NUDE CPlayerPed_ProcessControl_Hook() {} NUDE HOOK_10() {} NUDE TaskUseGun_Hook() {} NUDE HOOK_12() {} +NUDE CPlayerPed_ProcessCollision_Hook() {} NUDE HOOK_14() {} NUDE HOOK_15() {} NUDE AllVehicles_ProcessControl_Hook() {} -NUDE HOOK_17() {} +NUDE VehicleHorn_Hook() {} NUDE ZoneOverlay_Hook() {} NUDE PlayerWalk_Hook() {} NUDE PickUpPickup_Hook() {} @@ -115,7 +150,7 @@ NUDE HOOK_64() {} NUDE HOOK_65() {} NUDE HOOK_66() {} - +//----------------------------------------------------------- NUDE HOOK_6() { @@ -125,81 +160,126 @@ NUDE HOOK_6() _asm jmp edx } - //----------------------------------------------------------- -DWORD dwRandCaller; - -NUDE Rand_Hook() +NUDE GameProcessHook() { - _asm mov eax, [esp+0] - _asm mov dwRandCaller, eax - - /* - if(dwRandCaller > 0x73FB10 && dwRandCaller < 0x74132E) { - _asm mov eax, iSyncedRandomNumber - _asm ret - }*/ - - rand(); + _asm add esp, 190h _asm ret } //----------------------------------------------------------- -// We use a special bit (32) on dwProcFlags (+28) to indicate -// whether we should process gravity/collisions on this PlayerPed. +// A hook function that switches keys for +// CPlayerPed::ProcessControl(void) -NUDE CPlayerPed_ProcessCollision_Hook() +BYTE bytePatchPedRot[6] = { 0xD9,0x96,0x5C,0x05,0x00,0x00 }; +BYTE bytePatchPedRot2[6] = { 0xD9,0x96,0x5C,0x05,0x00,0x00 }; +BYTE bytePatchPedPos[5] = { 0xE8,0x17,0x88,0xFF,0xFF }; + +void TryProcessPedControl() { - _asm test ecx, ecx - _asm jnz ptr_is_ok + __try + { + // call the internal CPlayerPed:ProcessControl + _asm mov ecx, dwCurPlayerActor + _asm mov edx, 0x60EA90 + _asm call edx + } + __except(exc_filter(GetExceptionCode(), GetExceptionInformation(), "opcode")) + { + if(*pbyteCurrentPlayer != 0 && pNetGame) { + _pPlayerPool = pNetGame->GetPlayerPool(); + + // TODO: TryProcessPedControl() + } + } +} + +void DisablePedRotationFromCamera() +{ + // Reapply the no ped rots from Cam patch + memset((PVOID)0x6884C4,0x90,6); + + memset((PVOID)0x688200,0x90,6); +} + +void EnablePedRotationFromCamera() +{ + // Apply the original code to set ped rot from Cam + memcpy((PVOID)0x6884C4,bytePatchPedRot,6); + + memcpy((PVOID)0x688200,bytePatchPedRot2,6); +} + +void DisablePedPositionUpdate() +{ + UnFuck(0x5E92F4,5); + memset((PVOID)0x5E92F4,0x90,5); +} + +void EnablePedPositionUpdate() +{ + memcpy((PVOID)0x5E92F4,bytePatchPedPos,5); +} + +NUDE CPlayerPed_ProcessControl_Hook() +{ + _asm mov dwCurPlayerActor, ecx // store the passed actor + _asm pushad + + _pPlayer = (PED_TYPE *)dwCurPlayerActor; + byteInternalPlayer = *pbyteCurrentPlayer; // get the current internal player number + byteCurPlayer = FindPlayerNumFromPedPtr(dwCurPlayerActor); // get the ordinal of the passed actor + + if( dwCurPlayerActor && + (byteCurPlayer != 0) && + (byteInternalPlayer == 0) ) // not local player and local player's keys set. + { + // key switching + GameStoreLocalPlayerKeys(); // remember local player's keys + GameSetRemotePlayerKeys(byteCurPlayer); // set remote player's keys + + // save the internal cammode, apply the context. + byteSavedCameraMode = *pbyteCameraMode; + *pbyteCameraMode = GameGetPlayerCameraMode(byteCurPlayer); + + // save the second internal cammode, apply the context + wSavedCameraMode2 = *wCameraMode2; + *wCameraMode2 = GameGetPlayerCameraMode(byteCurPlayer); + if(*wCameraMode2 == 4) *wCameraMode2 = 0; + + // save the camera zoom factor, apply the context + GameStoreLocalPlayerCameraExtZoom(); + GameSetRemotePlayerCameraExtZoom(byteCurPlayer); + + // aim switching + GameStoreLocalPlayerAim(); + GameSetRemotePlayerAim(byteCurPlayer); + + GameStoreLocalPlayerWeaponSkills(); + GameSetRemotePlayerWeaponSkills(byteCurPlayer); + + *pbyteCurrentPlayer = byteCurPlayer; // Set the internal player to the passed actor + + fHealth = _pPlayer->fHealth; + + DisablePedPositionUpdate(); + TryProcessPedControl(); + EnablePedPositionUpdate(); + } + else // it's the local player or keys have already been set. + { + // TODO: CPlayerPed_ProcessControl_Hook() + } + + _asm popad _asm ret -ptr_is_ok: - _asm mov eax, [ecx+28] - _asm shr eax, 31 - _asm cmp eax, 1 - _asm jne do_process_cols - _asm ret // we set top bit so don't process this -do_process_cols: - _asm mov edx, 0x54DFB0 - _asm jmp edx } -//----------------------------------------------------------- -DWORD dwMat; -DWORD dwMatEffects; -DWORD dwDataParam; -NUDE VehicleModel_SetEnvironmentMapHook() -{ - _asm mov eax, [esp+4] - _asm mov dwMat, eax - _asm mov eax, [esp+8] - _asm mov dwDataParam, eax - UnFuck(0x6D64F0,1); - *(PBYTE)0x6D64F0 = 0xC3; - /* - _asm push dwMat - _asm mov edx, 0x812140 // _RpMatFXMaterialGetEffects - _asm call edx - _asm pop edx - _asm mov dwMatEffects, eax*/ - _asm push 0 - _asm push dwMat - _asm mov edx, 0x811C80 // _RpMatFXMaterialSetEffects - _asm call edx - _asm pop edx - _asm pop edx - - //pChatWindow->AddDebugMessage("SetEnvironmentMapCB(0x%X,0x%X,%d)",dwMat,dwDataParam,dwMatEffects); - - _asm mov edx, 0x4C8848 - _asm cmp [esp+8], 0FFFFh - _asm jmp edx -} //----------------------------------------------------------- @@ -306,11 +386,11 @@ void GameInstallHooks() InstallMethodHook(0x872398,(DWORD)AllVehicles_ProcessControl_Hook); // train InstallMethodHook(0x871C50,(DWORD)AllVehicles_ProcessControl_Hook); - InstallCallHook(0x501B1D,(DWORD)HOOK_17); - InstallCallHook(0x501B42,(DWORD)HOOK_17); - InstallCallHook(0x501FC2,(DWORD)HOOK_17); - InstallCallHook(0x502067,(DWORD)HOOK_17); - InstallCallHook(0x5021AE,(DWORD)HOOK_17); + InstallCallHook(0x501B1D,(DWORD)VehicleHorn_Hook); + InstallCallHook(0x501B42,(DWORD)VehicleHorn_Hook); + InstallCallHook(0x501FC2,(DWORD)VehicleHorn_Hook); + InstallCallHook(0x502067,(DWORD)VehicleHorn_Hook); + InstallCallHook(0x5021AE,(DWORD)VehicleHorn_Hook); // Radar and map hooks for gang zones InstallCallHook(0x5869BF,(DWORD)ZoneOverlay_Hook); @@ -361,12 +441,12 @@ void GameInstallHooks() if(iGtaVersion == GTASA_VERSION_USA10) { InstallHook(0x7FB020,(DWORD)HOOK_36,0x59C721,HOOK_36_JmpCode,sizeof(HOOK_36_JmpCode)); - unnamed_101516D4 = 0x7FB026; + GLOBAL_101516D4 = 0x7FB026; } else { InstallHook(0x7FB060,(DWORD)HOOK_36,0x59C721,HOOK_36_JmpCode,sizeof(HOOK_36_JmpCode)); - unnamed_101516D4 = 0x7FB066; + GLOBAL_101516D4 = 0x7FB066; } InstallCallHook(0x6D0E7E,(DWORD)HOOK_37); @@ -431,14 +511,14 @@ void GameInstallHooks() //----------------------------------------------------------- -void unnamed_100A6FF0() +void FUNC_100A6FF0() { InstallHook(0x4087EA,(DWORD)HOOK_61,0x4087D7,HOOK_61_JmpCode,sizeof(HOOK_61_JmpCode)); } //----------------------------------------------------------- -void unnamed_100A7010() +void FUNC_100A7010() { InstallCallHook(0x742495,(DWORD)HOOK_62); InstallCallHook(0x7424EC,(DWORD)HOOK_62); @@ -455,7 +535,7 @@ void unnamed_100A7010() //----------------------------------------------------------- -void unnamed_100A71C0() +void FUNC_100A71C0() { InstallCallHook(0x6D7C90,(DWORD)HOOK_66,0xE9); } diff --git a/saco/game/modelinfo.cpp b/saco/game/modelinfo.cpp new file mode 100644 index 0000000..23047cc --- /dev/null +++ b/saco/game/modelinfo.cpp @@ -0,0 +1,1514 @@ + +#include +#include "../main.h" +#include "modelinfo.h" + +extern int iGtaVersion; + +void FUNC_100A6FF0(); + +MODEL_INFO_TYPE *ModelInfoArray[65535]; +BOOL bModelInfoPathesApplied = FALSE; + +MODEL_INFO_TYPE **ModelInfoPtr = &ModelInfoArray[32767]; + +//----------------------------------------------------------- + +typedef struct _PATCH_INFO +{ + DWORD addr; + BYTE byte; +} PATCH_INFO; + +PATCH_INFO ModelInfoPtrsPatchUSA[] = +{ + { 0x40122A, 0x8B }, + { 0x403DA4, 0x8B }, + { 0x403ECC, 0x8B }, + { 0x405CDF, 0x8B }, + { 0x405E50, 0x8B }, + { 0x4063F1, 0x8B }, + { 0x406B11, 0x8B }, + { 0x407B21, 0x8B }, + { 0x407B72, 0x8B }, + { 0x407B92, 0x8B }, + { 0x4080B4, 0x8B }, + { 0x4082F4, 0x8B }, + { 0x4083A4, 0x8B }, + { 0x408894, 0x8B }, + { 0x4088A8, 0x8B }, + { 0x408903, 0x8B }, + { 0x4089CF, 0x8B }, + { 0x408CD0, 0x8B }, + { 0x408D1D, 0x8B }, + { 0x408EC0, 0x8B }, + { 0x4093F4, 0x8B }, + { 0x4097B3, 0x8B }, + { 0x4098A6, 0x8B }, + { 0x4098FC, 0x8B }, + { 0x40999E, 0x8B }, + { 0x409A4B, 0x8B }, + { 0x409C74, 0x8B }, + { 0x409CF5, 0x8B }, + { 0x409D19, 0x8B }, + { 0x409FFD, 0x8B }, + { 0x40A2B8, 0x8B }, + { 0x40A2E0, 0x8B }, + { 0x40A308, 0x8B }, + { 0x40A330, 0x8B }, + { 0x40A358, 0x8B }, + { 0x40A380, 0x8B }, + { 0x40A5B2, 0x8B }, + { 0x40A6CC, 0x8B }, + { 0x40A731, 0x8B }, + { 0x40A8E5, 0x8B }, + { 0x40AC1C, 0x8B }, + { 0x40AE8B, 0x8B }, + { 0x40BB22, 0x8B }, + { 0x40BEDD, 0x8B }, + { 0x40C04B, 0x8B }, + { 0x40C0BC, 0x8B }, + { 0x40C12A, 0x8B }, + { 0x40C300, 0x8B }, + { 0x40C4C2, 0x8B }, + { 0x40C6FE, 0x8B }, + { 0x40CD64, 0x8B }, + { 0x40CE6E, 0x8B }, + { 0x40CE83, 0x8B }, + { 0x40D05D, 0x8B }, + { 0x40E207, 0x8B }, + { 0x40E23B, 0x8B }, + { 0x41A8DE, 0x8B }, + { 0x41AA49, 0x8B }, + { 0x41AA79, 0x8B }, + { 0x41AB98, 0x8B }, + { 0x41D77E, 0x8B }, + { 0x42145A, 0x8B }, + { 0x42187B, 0x8B }, + { 0x424204, 0x8B }, + { 0x425467, 0x8B }, + { 0x425506, 0x8B }, + { 0x425B82, 0x8B }, + { 0x425BAD, 0x8B }, + { 0x425FA9, 0x8B }, + { 0x425FBE, 0x8B }, + { 0x4262BE, 0x8B }, + { 0x4262CC, 0x8B }, + { 0x426498, 0x8B }, + { 0x4264F4, 0x8B }, + { 0x426561, 0x8B }, + { 0x4265C7, 0x8B }, + { 0x426662, 0x8B }, + { 0x4266BA, 0x8B }, + { 0x426727, 0x8B }, + { 0x426790, 0x8B }, + { 0x4267F4, 0x8B }, + { 0x426806, 0x8B }, + { 0x426A2E, 0x8B }, + { 0x426C50, 0x8B }, + { 0x426D6D, 0x8B }, + { 0x42C48D, 0x8B }, + { 0x42C797, 0x8B }, + { 0x42DB81, 0x8B }, + { 0x42DC2A, 0x8B }, + { 0x42DD34, 0x8B }, + { 0x42DD97, 0x8B }, + { 0x42DDED, 0x8B }, + { 0x42ECA2, 0x8B }, + { 0x430633, 0x8B }, + { 0x430735, 0x8B }, + { 0x430947, 0x8B }, + { 0x431B46, 0x8B }, + { 0x431BD2, 0x8B }, + { 0x431F0E, 0x8B }, + { 0x436B31, 0x8B }, + { 0x436B42, 0x8B }, + { 0x43772C, 0x8B }, + { 0x43773D, 0x8B }, + { 0x437797, 0x8B }, + { 0x4377A8, 0x8B }, + { 0x4377E7, 0x8B }, + { 0x4377F8, 0x8B }, + { 0x437842, 0x8B }, + { 0x437853, 0x8B }, + { 0x43A162, 0x8B }, + { 0x43A345, 0x8B }, + { 0x43B3E3, 0x8B }, + { 0x43D546, 0x8B }, + { 0x43D7D3, 0x8B }, + { 0x43D883, 0x8B }, + { 0x43D89E, 0x8B }, + { 0x447EEB, 0x8B }, + { 0x448AF9, 0x8B }, + { 0x448EEE, 0x8B }, + { 0x449C34, 0x8B }, + { 0x44A52A, 0x8B }, + { 0x44B11E, 0x8B }, + { 0x453173, 0x8B }, + { 0x4531AE, 0x8B }, + { 0x4531E4, 0x8B }, + { 0x453220, 0x8B }, + { 0x453490, 0x8B }, + { 0x4534CB, 0x8B }, + { 0x453501, 0x8B }, + { 0x45353D, 0x8B }, + { 0x454B1E, 0x8B }, + { 0x455C0E, 0x8B }, + { 0x456802, 0x8B }, + { 0x456816, 0x8B }, + { 0x4613FD, 0x8B }, + { 0x461C2D, 0x8B }, + { 0x4624F5, 0x8B }, + { 0x4657A2, 0x8B }, + { 0x46978D, 0x8B }, + { 0x46A773, 0x8B }, + { 0x46B5F7, 0x8B }, + { 0x472950, 0x8B }, + { 0x474806, 0x8B }, + { 0x474AAD, 0x8B }, + { 0x475D91, 0x8B }, + { 0x478505, 0x8B }, + { 0x478552, 0x8B }, + { 0x4788D7, 0x8B }, + { 0x4794DF, 0x8B }, + { 0x47AEA3, 0x8B }, + { 0x47F50F, 0x8B }, + { 0x47FDC0, 0x8B }, + { 0x47FDFC, 0x8B }, + { 0x47FE52, 0x8B }, + { 0x481E29, 0x8B }, + { 0x48229F, 0x8B }, + { 0x482560, 0x8B }, + { 0x4829D6, 0x8B }, + { 0x483365, 0x8B }, + { 0x48337F, 0x8B }, + { 0x484D39, 0x8B }, + { 0x486B1D, 0x8B }, + { 0x48ACA2, 0x8B }, + { 0x494EDC, 0x8B }, + { 0x49835E, 0x8B }, + { 0x4983A6, 0x8B }, + { 0x4986FB, 0x8B }, + { 0x499A10, 0x8B }, + { 0x49B0EC, 0x8B }, + { 0x49B0F9, 0x8B }, + { 0x49DB82, 0x8B }, + { 0x4AF46B, 0x8B }, + { 0x4B313C, 0x8B }, + { 0x4B49B3, 0x8B }, + { 0x4C0C13, 0x8B }, + { 0x4C4860, 0x8B }, + { 0x4C4BED, 0x8B }, + { 0x4C5538, 0x89 }, + { 0x4C5960, 0x8B }, + { 0x4C5980, 0x8B }, + { 0x4C59C0, 0x8B }, + { 0x4C5A40, 0x8B }, + { 0x4C5A75, 0x8B }, + { 0x4C5A89, 0x8B }, + { 0x4C5AA5, 0x8B }, + { 0x4C5AB9, 0x8B }, + { 0x4C5AD5, 0x8B }, + { 0x4C5AE9, 0x8B }, + { 0x4C5B05, 0x8B }, + { 0x4C5B19, 0x8B }, + { 0x4C5B35, 0x8B }, + { 0x4C5B49, 0x8B }, + { 0x4C5B65, 0x8B }, + { 0x4C5B79, 0x8B }, + { 0x4C5B95, 0x8B }, + { 0x4C5BA9, 0x8B }, + { 0x4C5BC5, 0x8B }, + { 0x4C5BD9, 0x8B }, + { 0x4C5BF5, 0x8B }, + { 0x4C5C09, 0x8B }, + { 0x4C5C25, 0x8B }, + { 0x4C5C39, 0x8B }, + { 0x4C5C55, 0x8B }, + { 0x4C5C69, 0x8B }, + { 0x4C5C90, 0x8B }, + { 0x4C63BB, 0xBE }, + { 0x4C6642, 0x89 }, + { 0x4C6671, 0x89 }, + { 0x4C66A1, 0x89 }, + { 0x4C66D1, 0x89 }, + { 0x4C6701, 0x89 }, + { 0x4C6731, 0x89 }, + { 0x4C6761, 0x89 }, + { 0x4C6795, 0x89 }, + { 0x4C67C2, 0x89 }, + { 0x4C681A, 0xBF }, + { 0x4C85D6, 0x39 }, + { 0x4C89B8, 0x8B }, + { 0x4D3D52, 0x8B }, + { 0x4DACAE, 0x8B }, + { 0x4E4204, 0x8B }, + { 0x4E58C4, 0x8B }, + { 0x4E693A, 0x8B }, + { 0x4E6970, 0x8B }, + { 0x509CAE, 0x8B }, + { 0x50D59F, 0x8B }, + { 0x5135A2, 0x8B }, + { 0x513634, 0x8B }, + { 0x514C80, 0x8B }, + { 0x516E1A, 0x8B }, + { 0x5172F2, 0x8B }, + { 0x5180EF, 0x8B }, + { 0x51D233, 0x8B }, + { 0x52034F, 0x8B }, + { 0x532A58, 0x8B }, + { 0x532B7B, 0x8B }, + { 0x532D01, 0x8B }, + { 0x532D44, 0x8B }, + { 0x533162, 0x8B }, + { 0x533247, 0x8B }, + { 0x533389, 0x8B }, + { 0x53341D, 0x8B }, + { 0x533706, 0x8B }, + { 0x5337AA, 0x8B }, + { 0x533BFA, 0x8B }, + { 0x533D46, 0x8B }, + { 0x533F30, 0x8B }, + { 0x533F86, 0x8B }, + { 0x533FBE, 0x8B }, + { 0x533FDF, 0x8B }, + { 0x5340A5, 0x8B }, + { 0x5340D7, 0x8B }, + { 0x53412A, 0x8B }, + { 0x534254, 0x8B }, + { 0x534294, 0x8B }, + { 0x5342BD, 0x8B }, + { 0x5343FA, 0x8B }, + { 0x53441D, 0x8B }, + { 0x53443B, 0x8B }, + { 0x534449, 0x8B }, + { 0x5344D8, 0x8B }, + { 0x53454A, 0x8B }, + { 0x534568, 0x8B }, + { 0x5345F2, 0x8B }, + { 0x534FB3, 0x8B }, + { 0x535326, 0x8B }, + { 0x5354C8, 0x8B }, + { 0x535FB0, 0x8B }, + { 0x536C0B, 0x8B }, + { 0x537155, 0x8B }, + { 0x5371F6, 0x8B }, + { 0x5372D7, 0x8B }, + { 0x5373F4, 0x8B }, + { 0x537457, 0x8B }, + { 0x53748D, 0x8B }, + { 0x5380B2, 0x8B }, + { 0x538124, 0x8B }, + { 0x5383BB, 0x8B }, + { 0x5384FF, 0x8B }, + { 0x53A70D, 0x8B }, + { 0x53C449, 0x8B }, + { 0x5449C4, 0x8B }, + { 0x546680, 0x8B }, + { 0x546D28, 0x8B }, + { 0x547FDB, 0x8B }, + { 0x5483E7, 0x8B }, + { 0x54A998, 0x8B }, + { 0x54BA95, 0x8B }, + { 0x54C6C2, 0x8B }, + { 0x54C817, 0x8B }, + { 0x54D030, 0x8B }, + { 0x5537F0, 0x8B }, + { 0x553898, 0x8B }, + { 0x553A64, 0x8B }, + { 0x553B14, 0x8B }, + { 0x55423D, 0x8B }, + { 0x554463, 0x8B }, + { 0x5544BD, 0x8B }, + { 0x554663, 0x8B }, + { 0x5546B9, 0x8B }, + { 0x5546F5, 0x8B }, + { 0x5549F3, 0x8B }, + { 0x554ED8, 0x8B }, + { 0x554F39, 0x8B }, + { 0x556768, 0x8B }, + { 0x5569F7, 0x8B }, + { 0x558164, 0x8B }, + { 0x558406, 0x8B }, + { 0x5584CA, 0x8B }, + { 0x558688, 0x8B }, + { 0x5588E0, 0x8B }, + { 0x558961, 0x8B }, + { 0x5589D6, 0x8B }, + { 0x558A60, 0x8B }, + { 0x558B4E, 0x8B }, + { 0x55C011, 0x8B }, + { 0x56508C, 0x8B }, + { 0x56512C, 0x8B }, + { 0x565266, 0x8B }, + { 0x56537E, 0x8B }, + { 0x5662D2, 0x8B }, + { 0x56709E, 0x8B }, + { 0x5683CD, 0x8B }, + { 0x569999, 0x8B }, + { 0x569BB3, 0x8B }, + { 0x569BDE, 0x8B }, + { 0x569CBB, 0x8B }, + { 0x569DC6, 0x8B }, + { 0x571EAA, 0x8B }, + { 0x57206F, 0x8B }, + { 0x585EC7, 0x8B }, + { 0x58D80B, 0x8B }, + { 0x58E855, 0x8B }, + { 0x593508, 0x8B }, + { 0x594CCE, 0x8B }, + { 0x594FC0, 0x8B }, + { 0x595390, 0x8B }, + { 0x596756, 0x8B }, + { 0x59843C, 0x8B }, + { 0x5986A5, 0x8B }, + { 0x598DFC, 0x8B }, + { 0x59E7FE, 0x8B }, + { 0x59E826, 0x8B }, + { 0x59EF37, 0x8B }, + { 0x59EFB1, 0x8B }, + { 0x59F1B4, 0x8B }, + { 0x59F33B, 0x8B }, + { 0x59F6F2, 0x8B }, + { 0x59F74D, 0x8B }, + { 0x59F8AA, 0x8B }, + { 0x59F8E0, 0x8B }, + { 0x59F9B9, 0x8B }, + { 0x59FA3D, 0x8B }, + { 0x59FA53, 0x8B }, + { 0x59FB5A, 0x8B }, + { 0x5A04A2, 0x8B }, + { 0x5A06D4, 0x8B }, + { 0x5A1B84, 0x8B }, + { 0x5A1BB5, 0x8B }, + { 0x5A213D, 0x8B }, + { 0x5A2D06, 0x8B }, + { 0x5A2DEA, 0x8B }, + { 0x5A332F, 0x8B }, + { 0x5A3525, 0x8B }, + { 0x5A41C6, 0x8B }, + { 0x5A81EB, 0x8B }, + { 0x5B02D0, 0x8B }, + { 0x5B02EF, 0x8B }, + { 0x5B0610, 0x8B }, + { 0x5B062B, 0x8B }, + { 0x5B1AE5, 0x8B }, + { 0x5B1B69, 0x8B }, + { 0x5B1B7C, 0x8B }, + { 0x5B2D09, 0x8B }, + { 0x5B2F7A, 0x8B }, + { 0x5B2F9F, 0x8B }, + { 0x5B2FCA, 0x8B }, + { 0x5B2FD1, 0x8B }, + { 0x5B3088, 0x8B }, + { 0x5B30D0, 0x8B }, + { 0x5B30D7, 0x8B }, + { 0x5B50A1, 0x8B }, + { 0x5B5270, 0x8B }, + { 0x5B529D, 0x8B }, + { 0x5B52AA, 0x8B }, + { 0x5B76BD, 0x8B }, + { 0x5B8C18, 0xBF }, + { 0x5B9299, 0xBE }, + { 0x5BEC46, 0x8B }, + { 0x5C010B, 0x8B }, + { 0x5C0157, 0x8B }, + { 0x5D2A8F, 0x8B }, + { 0x5DC7F7, 0x8B }, + { 0x5DF949, 0x8B }, + { 0x5DFD98, 0x8B }, + { 0x5E255F, 0x8B }, + { 0x5E39E3, 0x8B }, + { 0x5E3A9D, 0x8B }, + { 0x5E48B2, 0x8B }, + { 0x5E5F07, 0x8B }, + { 0x5E72F2, 0x8B }, + { 0x5E8EF9, 0x8B }, + { 0x5E8F0A, 0x8B }, + { 0x5F201F, 0x8B }, + { 0x5F2F20, 0x8B }, + { 0x5F336B, 0x8B }, + { 0x5F38B2, 0x8B }, + { 0x5F39C1, 0x8B }, + { 0x5F5720, 0x8B }, + { 0x5F5733, 0x8B }, + { 0x5FCADE, 0x8B }, + { 0x5FCBB9, 0x8B }, + { 0x5FD093, 0x8B }, + { 0x5FD546, 0x8B }, + { 0x60039A, 0x8B }, + { 0x603509, 0x8B }, + { 0x605474, 0x8B }, + { 0x606A5B, 0x8B }, + { 0x609A2C, 0x8B }, + { 0x60FFB5, 0x8B }, + { 0x6100EF, 0x8B }, + { 0x610154, 0x8B }, + { 0x610738, 0x8B }, + { 0x6110C4, 0x8B }, + { 0x6110F3, 0x8B }, + { 0x611206, 0x8B }, + { 0x611454, 0x8B }, + { 0x611474, 0x8B }, + { 0x611494, 0x8B }, + { 0x611764, 0x8B }, + { 0x611794, 0x8B }, + { 0x6117B4, 0x8B }, + { 0x611CC7, 0x8B }, + { 0x611D04, 0x8B }, + { 0x611D65, 0x8B }, + { 0x611D92, 0x8B }, + { 0x611DD0, 0x8B }, + { 0x611E49, 0x8B }, + { 0x611E53, 0x8B }, + { 0x611ED4, 0x8B }, + { 0x611EEF, 0x8B }, + { 0x61235C, 0x8B }, + { 0x6123AF, 0x8B }, + { 0x61259A, 0x8B }, + { 0x612EEA, 0x8B }, + { 0x61300B, 0x8B }, + { 0x61304C, 0x8B }, + { 0x613065, 0x8B }, + { 0x61307E, 0x8B }, + { 0x613093, 0x8B }, + { 0x6130AB, 0x8B }, + { 0x6130DA, 0x8B }, + { 0x6130F3, 0x8B }, + { 0x6131F2, 0x8B }, + { 0x61321D, 0x8B }, + { 0x613227, 0x8B }, + { 0x61326D, 0x8B }, + { 0x6132B1, 0x8B }, + { 0x61331D, 0x8B }, + { 0x61333F, 0x8B }, + { 0x613B43, 0x8B }, + { 0x613B5A, 0x8B }, + { 0x613CF7, 0x8B }, + { 0x613E15, 0x8B }, + { 0x613E9B, 0x8B }, + { 0x613EED, 0x8B }, + { 0x61417E, 0x8B }, + { 0x6142E8, 0x8B }, + { 0x61451B, 0x8B }, + { 0x61454B, 0x8B }, + { 0x6145DD, 0x8B }, + { 0x6146AD, 0x8B }, + { 0x6146D5, 0x8B }, + { 0x614A90, 0x8B }, + { 0x614C6D, 0x8B }, + { 0x614CF4, 0x8B }, + { 0x614D42, 0x8B }, + { 0x614FE9, 0x8B }, + { 0x61511B, 0x8B }, + { 0x6152C3, 0x8B }, + { 0x616A9D, 0x8B }, + { 0x616AAE, 0x8B }, + { 0x616AE8, 0x8B }, + { 0x616AF9, 0x8B }, + { 0x62428B, 0x8B }, + { 0x62439A, 0x8B }, + { 0x627D2B, 0x8B }, + { 0x628A3B, 0x8B }, + { 0x6291BB, 0x8B }, + { 0x64087E, 0x8B }, + { 0x640B3B, 0x8B }, + { 0x642431, 0x8B }, + { 0x642C41, 0x8B }, + { 0x6432BF, 0x8B }, + { 0x643357, 0x8B }, + { 0x64916D, 0x8B }, + { 0x64D04D, 0x8B }, + { 0x64E74F, 0x8B }, + { 0x64FC21, 0x8B }, + { 0x6504DE, 0x8B }, + { 0x6509BC, 0x8B }, + { 0x650E09, 0x8B }, + { 0x656573, 0x8B }, + { 0x65D35A, 0x8B }, + { 0x6641B5, 0x8B }, + { 0x66477A, 0x8B }, + { 0x664BF2, 0x8B }, + { 0x66F4D1, 0x8B }, + { 0x66F92A, 0x8B }, + { 0x66F99E, 0x8B }, + { 0x66FA11, 0x8B }, + { 0x66FA85, 0x8B }, + { 0x66FAF9, 0x8B }, + { 0x66FB6D, 0x8B }, + { 0x66FBE1, 0x8B }, + { 0x66FC55, 0x8B }, + { 0x67C82F, 0x8B }, + { 0x67C83D, 0x8B }, + { 0x67D5C6, 0x8B }, + { 0x67DFCE, 0x8B }, + { 0x68D9F5, 0x8B }, + { 0x69368A, 0x8B }, + { 0x69598C, 0x8B }, + { 0x6969C5, 0x8B }, + { 0x696AF3, 0x8B }, + { 0x69912E, 0x8B }, + { 0x699268, 0x8B }, + { 0x6995EC, 0x8B }, + { 0x699701, 0x8B }, + { 0x69A77E, 0x8B }, + { 0x69B909, 0x8B }, + { 0x6A07AB, 0x8B }, + { 0x6A1577, 0x8B }, + { 0x6A26C2, 0x8B }, + { 0x6A2792, 0x8B }, + { 0x6A2871, 0x8B }, + { 0x6A2936, 0x8B }, + { 0x6A2F88, 0x8B }, + { 0x6A307F, 0x8B }, + { 0x6A3BDB, 0x8B }, + { 0x6A452A, 0x8B }, + { 0x6A4805, 0x8B }, + { 0x6A609E, 0x8B }, + { 0x6A65DD, 0x8B }, + { 0x6A7178, 0x8B }, + { 0x6A8B6E, 0x8B }, + { 0x6AA2E2, 0x8B }, + { 0x6ABD16, 0x8B }, + { 0x6AE28B, 0x8B }, + { 0x6AE2CE, 0x8B }, + { 0x6AE302, 0x8B }, + { 0x6AE332, 0x8B }, + { 0x6AE5D5, 0x8B }, + { 0x6AE60E, 0x8B }, + { 0x6AF1EA, 0x8B }, + { 0x6AF320, 0x8B }, + { 0x6AF37E, 0x8B }, + { 0x6B0581, 0x8B }, + { 0x6B0B22, 0x8B }, + { 0x6B1386, 0x8B }, + { 0x6B14B6, 0x8B }, + { 0x6B16A7, 0x8B }, + { 0x6B16EF, 0x8B }, + { 0x6B3F7D, 0x8B }, + { 0x6B4100, 0x8B }, + { 0x6B67EA, 0x8B }, + { 0x6B6965, 0x8B }, + { 0x6B804C, 0x8B }, + { 0x6B89BC, 0x8B }, + { 0x6B927D, 0x8B }, + { 0x6BBC76, 0x8B }, + { 0x6BC93C, 0x8B }, + { 0x6BD683, 0x8B }, + { 0x6BE009, 0x8B }, + { 0x6BF48A, 0x8B }, + { 0x6BF857, 0x8B }, + { 0x6C0B3F, 0x8B }, + { 0x6C1483, 0x8B }, + { 0x6C440E, 0x8B }, + { 0x6C5446, 0x8B }, + { 0x6C7E83, 0x8B }, + { 0x6C7FBC, 0x8B }, + { 0x6C8E60, 0x8B }, + { 0x6C94D5, 0x8B }, + { 0x6CE3B9, 0x8B }, + { 0x6CEAF5, 0x8B }, + { 0x6CEEA4, 0x8B }, + { 0x6CF1AA, 0x8B }, + { 0x6CFAE5, 0x8B }, + { 0x6CFD92, 0x8B }, + { 0x6D0B79, 0x8B }, + { 0x6D0C4C, 0x8B }, + { 0x6D0E49, 0x8B }, + { 0x6D0E76, 0x8B }, + { 0x6D2315, 0x8B }, + { 0x6D2B02, 0x8B }, + { 0x6D31EC, 0x8B }, + { 0x6D32DF, 0x8B }, + { 0x6D3875, 0x8B }, + { 0x6D3971, 0x8B }, + { 0x6D3A21, 0x8B }, + { 0x6D429A, 0x8B }, + { 0x6D46E9, 0x8B }, + { 0x6D5431, 0x8B }, + { 0x6D63F4, 0x8B }, + { 0x6D649D, 0x8B }, + { 0x6D64D4, 0x8B }, + { 0x6D64FE, 0x8B }, + { 0x6D6A4E, 0x8B }, + { 0x6D7ED5, 0x8B }, + { 0x6DB171, 0x8B }, + { 0x6DE2EA, 0x8B }, + { 0x6DF455, 0x8B }, + { 0x6DF936, 0x8B }, + { 0x6DF9C7, 0x8B }, + { 0x6DFA2F, 0x8B }, + { 0x6DFA3A, 0x8B }, + { 0x6DFB48, 0x8B }, + { 0x6DFB8A, 0x8B }, + { 0x6DFBFA, 0x8B }, + { 0x6E0A62, 0x8B }, + { 0x6E0E2D, 0x8B }, + { 0x6E144B, 0x8B }, + { 0x6E1607, 0x8B }, + { 0x6E17B9, 0x8B }, + { 0x6E1F35, 0x8B }, + { 0x6E22C6, 0x8B }, + { 0x6E3296, 0x8B }, + { 0x6E3312, 0x8B }, + { 0x6E3396, 0x8B }, + { 0x6F0D46, 0x8B }, + { 0x6F2987, 0x8B }, + { 0x6F2FF1, 0x8B }, + { 0x6F32EA, 0x8B }, + { 0x6F3398, 0x8B }, + { 0x6F33B2, 0x8B }, + { 0x6F3596, 0x8B }, + { 0x6F3753, 0x8B }, + { 0x6F376B, 0x8B }, + { 0x6F3990, 0x8B }, + { 0x6F6073, 0x8B }, + { 0x6F6FBB, 0x8B }, + { 0x6F7735, 0x8B }, + { 0x6F7761, 0x8B }, + { 0x6F9132, 0x8B }, + { 0x6F9380, 0x8B }, + { 0x6F9953, 0x8B }, + { 0x6FC805, 0x8B }, + { 0x7086E9, 0x8B }, + { 0x70A068, 0x8B }, + { 0x70A586, 0x8B }, + { 0x70A73C, 0x8B }, + { 0x70A8C5, 0x8B }, + { 0x711BDA, 0x8B }, + { 0x711CF6, 0x8B }, + { 0x7179E3, 0x8B }, + { 0x71AFF4, 0x8B }, + { 0x71BC64, 0x8B }, + { 0x71C0E9, 0x8B }, + { 0x71CFF8, 0x8B }, + { 0x71D032, 0x8B }, + { 0x71FB44, 0x8B }, + { 0x71FB88, 0x8B }, + { 0x71FC9A, 0x8B }, + { 0x71FD47, 0x8B }, + { 0x71FE09, 0x8B }, + { 0x71FEDA, 0x8B }, + { 0x71FFC2, 0x8B }, + { 0x73227A, 0x8B }, + { 0x732B55, 0x8B }, + { 0x736F18, 0x8B }, + { 0x738409, 0x8B }, + { 0x73A398, 0x8B }, + { 0x73A3B9, 0x8B }, + { 0x73B525, 0x8B }, + { 0x73B537, 0x8B }, + { 0x73D5D0, 0x8B }, + { 0x73EC5D, 0x8B }, + { 0x74103B, 0x8B }, + { 0x1562A35, 0x8B }, + { 0x1562B94, 0x8B }, + { 0x1564612, 0x8B }, + { 0x1564EC2, 0x8B }, + { 0x156526C, 0x8B }, + { 0x15662F5, 0x8B }, + { 0x156650D, 0x8B }, + { 0x156658A, 0x8B }, + { 0x15665C9, 0x8B }, + { 0x1566F25, 0x8B }, + { 0x15691DE, 0x8B }, + { 0x15691E5, 0x8B }, + { 0x156C247, 0x8B }, + { 0x156C275, 0x8B }, + { 0x156C5B5, 0x8B }, + { 0x156CA5D, 0x8B }, + { 0x156CAA2, 0x8B }, + { 0x156D089, 0x8B }, + { 0x156D0B6, 0x8B }, + { 0x156D0E6, 0x8B }, + { 0x1570248, 0x8B }, + { 0x1570270, 0x8B }, + { 0x1570298, 0x8B }, + { 0x15702C0, 0x8B }, + { 0x15702E8, 0x8B }, + { 0x1570310, 0x8B }, + { 0x1570404, 0x8B }, + { 0x157045D, 0x8B }, +}; + +PATCH_INFO ModelInfoPtrsPatchEU[] = +{ + { 0x40121F, 0x8B }, + { 0x403DA4, 0x8B }, + { 0x403ECC, 0x8B }, + { 0x405CDF, 0x8B }, + { 0x405E50, 0x8B }, + { 0x4063F1, 0x8B }, + { 0x406B0D, 0x8B }, + { 0x407B21, 0x8B }, + { 0x407B72, 0x8B }, + { 0x407B92, 0x8B }, + { 0x4080B4, 0x8B }, + { 0x4082F4, 0x8B }, + { 0x4083A4, 0x8B }, + { 0x408894, 0x8B }, + { 0x4088A8, 0x8B }, + { 0x408903, 0x8B }, + { 0x4089CF, 0x8B }, + { 0x408CD0, 0x8B }, + { 0x408D1D, 0x8B }, + { 0x408EC0, 0x8B }, + { 0x4093F4, 0x8B }, + { 0x4097B3, 0x8B }, + { 0x4098A6, 0x8B }, + { 0x4098FC, 0x8B }, + { 0x40999E, 0x8B }, + { 0x409A4B, 0x8B }, + { 0x409C74, 0x8B }, + { 0x409CF5, 0x8B }, + { 0x409D19, 0x8B }, + { 0x409FFD, 0x8B }, + { 0x40A2B8, 0x8B }, + { 0x40A2E0, 0x8B }, + { 0x40A308, 0x8B }, + { 0x40A330, 0x8B }, + { 0x40A358, 0x8B }, + { 0x40A380, 0x8B }, + { 0x40A5B2, 0x8B }, + { 0x40A6CC, 0x8B }, + { 0x40A731, 0x8B }, + { 0x40A8E5, 0x8B }, + { 0x40AC1C, 0x8B }, + { 0x40AE8B, 0x8B }, + { 0x40BB22, 0x8B }, + { 0x40BEDD, 0x8B }, + { 0x40C04B, 0x8B }, + { 0x40C0BC, 0x8B }, + { 0x40C12A, 0x8B }, + { 0x40C300, 0x8B }, + { 0x40C4C2, 0x8B }, + { 0x40C6FE, 0x8B }, + { 0x40CD64, 0x8B }, + { 0x40CE6E, 0x8B }, + { 0x40CE83, 0x8B }, + { 0x40D05D, 0x8B }, + { 0x40E207, 0x8B }, + { 0x40E23B, 0x8B }, + { 0x41A8DE, 0x8B }, + { 0x41AA49, 0x8B }, + { 0x41AA79, 0x8B }, + { 0x41AB98, 0x8B }, + { 0x41D77E, 0x8B }, + { 0x42145A, 0x8B }, + { 0x42187B, 0x8B }, + { 0x424204, 0x8B }, + { 0x425467, 0x8B }, + { 0x425506, 0x8B }, + { 0x425B82, 0x8B }, + { 0x425BAD, 0x8B }, + { 0x425FA9, 0x8B }, + { 0x425FBE, 0x8B }, + { 0x4262BE, 0x8B }, + { 0x4262CC, 0x8B }, + { 0x426498, 0x8B }, + { 0x4264F4, 0x8B }, + { 0x426561, 0x8B }, + { 0x4265C7, 0x8B }, + { 0x426662, 0x8B }, + { 0x4266BA, 0x8B }, + { 0x426727, 0x8B }, + { 0x426790, 0x8B }, + { 0x4267F4, 0x8B }, + { 0x426806, 0x8B }, + { 0x426A2E, 0x8B }, + { 0x426C50, 0x8B }, + { 0x426D6D, 0x8B }, + { 0x42C48D, 0x8B }, + { 0x42C797, 0x8B }, + { 0x42DB81, 0x8B }, + { 0x42DC2A, 0x8B }, + { 0x42DD34, 0x8B }, + { 0x42DD97, 0x8B }, + { 0x42DDED, 0x8B }, + { 0x42ECA2, 0x8B }, + { 0x430633, 0x8B }, + { 0x430735, 0x8B }, + { 0x430947, 0x8B }, + { 0x431B46, 0x8B }, + { 0x431BD2, 0x8B }, + { 0x431F0E, 0x8B }, + { 0x436B31, 0x8B }, + { 0x436B42, 0x8B }, + { 0x43772C, 0x8B }, + { 0x43773D, 0x8B }, + { 0x437797, 0x8B }, + { 0x4377A8, 0x8B }, + { 0x4377E7, 0x8B }, + { 0x4377F8, 0x8B }, + { 0x437842, 0x8B }, + { 0x437853, 0x8B }, + { 0x43A162, 0x8B }, + { 0x43A345, 0x8B }, + { 0x43B3E3, 0x8B }, + { 0x43D546, 0x8B }, + { 0x43D7D3, 0x8B }, + { 0x43D883, 0x8B }, + { 0x43D89E, 0x8B }, + { 0x447EEB, 0x8B }, + { 0x448AF9, 0x8B }, + { 0x448EEE, 0x8B }, + { 0x449C34, 0x8B }, + { 0x44A52A, 0x8B }, + { 0x44B11E, 0x8B }, + { 0x453173, 0x8B }, + { 0x4531AE, 0x8B }, + { 0x4531E4, 0x8B }, + { 0x453220, 0x8B }, + { 0x453490, 0x8B }, + { 0x4534CB, 0x8B }, + { 0x453501, 0x8B }, + { 0x45353D, 0x8B }, + { 0x454B1E, 0x8B }, + { 0x455C0E, 0x8B }, + { 0x456802, 0x8B }, + { 0x456816, 0x8B }, + { 0x4613FD, 0x8B }, + { 0x461C2D, 0x8B }, + { 0x4624F5, 0x8B }, + { 0x4657A2, 0x8B }, + { 0x46978D, 0x8B }, + { 0x46A773, 0x8B }, + { 0x46B5F7, 0x8B }, + { 0x472950, 0x8B }, + { 0x474806, 0x8B }, + { 0x474AAD, 0x8B }, + { 0x475D91, 0x8B }, + { 0x478505, 0x8B }, + { 0x478552, 0x8B }, + { 0x4788D7, 0x8B }, + { 0x4794DF, 0x8B }, + { 0x47AEA3, 0x8B }, + { 0x47F50F, 0x8B }, + { 0x47FDC0, 0x8B }, + { 0x47FDFC, 0x8B }, + { 0x47FE52, 0x8B }, + { 0x481E29, 0x8B }, + { 0x48229F, 0x8B }, + { 0x482560, 0x8B }, + { 0x4829D6, 0x8B }, + { 0x483365, 0x8B }, + { 0x48337F, 0x8B }, + { 0x484D39, 0x8B }, + { 0x486B1D, 0x8B }, + { 0x48ACA2, 0x8B }, + { 0x494EDC, 0x8B }, + { 0x49835E, 0x8B }, + { 0x4983A6, 0x8B }, + { 0x4986FB, 0x8B }, + { 0x499A10, 0x8B }, + { 0x49B0EC, 0x8B }, + { 0x49B0F9, 0x8B }, + { 0x49DB82, 0x8B }, + { 0x4AF46B, 0x8B }, + { 0x4B313C, 0x8B }, + { 0x4B49B3, 0x8B }, + { 0x4C0C13, 0x8B }, + { 0x4C4860, 0x8B }, + { 0x4C4BED, 0x8B }, + { 0x4C5538, 0x89 }, + { 0x4C5960, 0x8B }, + { 0x4C5980, 0x8B }, + { 0x4C59C0, 0x8B }, + { 0x4C5A40, 0x8B }, + { 0x4C5A75, 0x8B }, + { 0x4C5A89, 0x8B }, + { 0x4C5AA5, 0x8B }, + { 0x4C5AB9, 0x8B }, + { 0x4C5AD5, 0x8B }, + { 0x4C5AE9, 0x8B }, + { 0x4C5B05, 0x8B }, + { 0x4C5B19, 0x8B }, + { 0x4C5B35, 0x8B }, + { 0x4C5B49, 0x8B }, + { 0x4C5B65, 0x8B }, + { 0x4C5B79, 0x8B }, + { 0x4C5B95, 0x8B }, + { 0x4C5BA9, 0x8B }, + { 0x4C5BC5, 0x8B }, + { 0x4C5BD9, 0x8B }, + { 0x4C5BF5, 0x8B }, + { 0x4C5C09, 0x8B }, + { 0x4C5C25, 0x8B }, + { 0x4C5C39, 0x8B }, + { 0x4C5C55, 0x8B }, + { 0x4C5C69, 0x8B }, + { 0x4C5C90, 0x8B }, + { 0x4C63BB, 0xBE }, + { 0x4C6642, 0x89 }, + { 0x4C6671, 0x89 }, + { 0x4C66A1, 0x89 }, + { 0x4C66D1, 0x89 }, + { 0x4C6701, 0x89 }, + { 0x4C6731, 0x89 }, + { 0x4C6761, 0x89 }, + { 0x4C6795, 0x89 }, + { 0x4C67C2, 0x89 }, + { 0x4C681A, 0xBF }, + { 0x4C85D6, 0x39 }, + { 0x4C89B8, 0x8B }, + { 0x4D3D52, 0x8B }, + { 0x4DACAE, 0x8B }, + { 0x4E4204, 0x8B }, + { 0x4E58C4, 0x8B }, + { 0x4E693A, 0x8B }, + { 0x4E6970, 0x8B }, + { 0x509CAE, 0x8B }, + { 0x50D59F, 0x8B }, + { 0x5135A2, 0x8B }, + { 0x513634, 0x8B }, + { 0x514C80, 0x8B }, + { 0x516E1A, 0x8B }, + { 0x5172F2, 0x8B }, + { 0x5180EF, 0x8B }, + { 0x51D233, 0x8B }, + { 0x52034F, 0x8B }, + { 0x532A58, 0x8B }, + { 0x532B7B, 0x8B }, + { 0x532D01, 0x8B }, + { 0x532D44, 0x8B }, + { 0x533162, 0x8B }, + { 0x533247, 0x8B }, + { 0x533389, 0x8B }, + { 0x53341D, 0x8B }, + { 0x533706, 0x8B }, + { 0x5337AA, 0x8B }, + { 0x533BFA, 0x8B }, + { 0x533D46, 0x8B }, + { 0x533F30, 0x8B }, + { 0x533F86, 0x8B }, + { 0x533FBE, 0x8B }, + { 0x533FDF, 0x8B }, + { 0x5340A5, 0x8B }, + { 0x5340D7, 0x8B }, + { 0x53412A, 0x8B }, + { 0x534254, 0x8B }, + { 0x534294, 0x8B }, + { 0x5342BD, 0x8B }, + { 0x5343FA, 0x8B }, + { 0x53441D, 0x8B }, + { 0x53443B, 0x8B }, + { 0x534449, 0x8B }, + { 0x5344D8, 0x8B }, + { 0x53454A, 0x8B }, + { 0x534568, 0x8B }, + { 0x5345F2, 0x8B }, + { 0x534FB3, 0x8B }, + { 0x535326, 0x8B }, + { 0x5354C8, 0x8B }, + { 0x535FB0, 0x8B }, + { 0x536C0B, 0x8B }, + { 0x537155, 0x8B }, + { 0x5371F6, 0x8B }, + { 0x5372D7, 0x8B }, + { 0x5373F4, 0x8B }, + { 0x537457, 0x8B }, + { 0x53748D, 0x8B }, + { 0x5380B2, 0x8B }, + { 0x538124, 0x8B }, + { 0x5383BB, 0x8B }, + { 0x5384FF, 0x8B }, + { 0x53A70D, 0x8B }, + { 0x53C449, 0x8B }, + { 0x5449C4, 0x8B }, + { 0x546680, 0x8B }, + { 0x546D28, 0x8B }, + { 0x547FDB, 0x8B }, + { 0x5483E7, 0x8B }, + { 0x54A998, 0x8B }, + { 0x54BA95, 0x8B }, + { 0x54C6C2, 0x8B }, + { 0x54C817, 0x8B }, + { 0x54D030, 0x8B }, + { 0x5537F0, 0x8B }, + { 0x553898, 0x8B }, + { 0x553A64, 0x8B }, + { 0x553B14, 0x8B }, + { 0x55423D, 0x8B }, + { 0x554463, 0x8B }, + { 0x5544BD, 0x8B }, + { 0x554663, 0x8B }, + { 0x5546B9, 0x8B }, + { 0x5546F5, 0x8B }, + { 0x5549F3, 0x8B }, + { 0x554ED8, 0x8B }, + { 0x554F39, 0x8B }, + { 0x556768, 0x8B }, + { 0x5569F7, 0x8B }, + { 0x558164, 0x8B }, + { 0x558406, 0x8B }, + { 0x5584CA, 0x8B }, + { 0x558688, 0x8B }, + { 0x5588E0, 0x8B }, + { 0x558961, 0x8B }, + { 0x5589D6, 0x8B }, + { 0x558A60, 0x8B }, + { 0x558B4E, 0x8B }, + { 0x55C011, 0x8B }, + { 0x56508C, 0x8B }, + { 0x56512C, 0x8B }, + { 0x565266, 0x8B }, + { 0x56537E, 0x8B }, + { 0x5662D2, 0x8B }, + { 0x56709E, 0x8B }, + { 0x5683CD, 0x8B }, + { 0x569999, 0x8B }, + { 0x569BB3, 0x8B }, + { 0x569BDE, 0x8B }, + { 0x569CBB, 0x8B }, + { 0x569DC6, 0x8B }, + { 0x571EAA, 0x8B }, + { 0x57206F, 0x8B }, + { 0x585EC7, 0x8B }, + { 0x58D80B, 0x8B }, + { 0x58E855, 0x8B }, + { 0x593508, 0x8B }, + { 0x594CCE, 0x8B }, + { 0x594FC0, 0x8B }, + { 0x595390, 0x8B }, + { 0x596756, 0x8B }, + { 0x59843C, 0x8B }, + { 0x5986A5, 0x8B }, + { 0x598DFC, 0x8B }, + { 0x59E7FE, 0x8B }, + { 0x59E826, 0x8B }, + { 0x59EF37, 0x8B }, + { 0x59EFB1, 0x8B }, + { 0x59F1B4, 0x8B }, + { 0x59F33B, 0x8B }, + { 0x59F6F2, 0x8B }, + { 0x59F74D, 0x8B }, + { 0x59F8AA, 0x8B }, + { 0x59F8E0, 0x8B }, + { 0x59F9B9, 0x8B }, + { 0x59FA3D, 0x8B }, + { 0x59FA53, 0x8B }, + { 0x59FB5A, 0x8B }, + { 0x5A04A2, 0x8B }, + { 0x5A06D4, 0x8B }, + { 0x5A1B84, 0x8B }, + { 0x5A1BB5, 0x8B }, + { 0x5A213D, 0x8B }, + { 0x5A2D06, 0x8B }, + { 0x5A2DEA, 0x8B }, + { 0x5A332F, 0x8B }, + { 0x5A3525, 0x8B }, + { 0x5A41C6, 0x8B }, + { 0x5A81EB, 0x8B }, + { 0x5B02D0, 0x8B }, + { 0x5B02EF, 0x8B }, + { 0x5B0610, 0x8B }, + { 0x5B062B, 0x8B }, + { 0x5B1AE5, 0x8B }, + { 0x5B1B69, 0x8B }, + { 0x5B1B7C, 0x8B }, + { 0x5B2D09, 0x8B }, + { 0x5B2F7A, 0x8B }, + { 0x5B2F9F, 0x8B }, + { 0x5B2FCA, 0x8B }, + { 0x5B2FD1, 0x8B }, + { 0x5B3088, 0x8B }, + { 0x5B30D0, 0x8B }, + { 0x5B30D7, 0x8B }, + { 0x5B50A1, 0x8B }, + { 0x5B5270, 0x8B }, + { 0x5B529D, 0x8B }, + { 0x5B52AA, 0x8B }, + { 0x5B76BD, 0x8B }, + { 0x5B8C18, 0xBF }, + { 0x5B9299, 0xBE }, + { 0x5BEC46, 0x8B }, + { 0x5C010B, 0x8B }, + { 0x5C0157, 0x8B }, + { 0x5D2A8F, 0x8B }, + { 0x5DC7F7, 0x8B }, + { 0x5DF949, 0x8B }, + { 0x5DFD98, 0x8B }, + { 0x5E255F, 0x8B }, + { 0x5E39E3, 0x8B }, + { 0x5E3A9D, 0x8B }, + { 0x5E48B2, 0x8B }, + { 0x5E5F07, 0x8B }, + { 0x5E72F2, 0x8B }, + { 0x5E8EF9, 0x8B }, + { 0x5E8F0A, 0x8B }, + { 0x5F201F, 0x8B }, + { 0x5F2F20, 0x8B }, + { 0x5F336B, 0x8B }, + { 0x5F38B2, 0x8B }, + { 0x5F39C1, 0x8B }, + { 0x5F5720, 0x8B }, + { 0x5F5733, 0x8B }, + { 0x5FCADE, 0x8B }, + { 0x5FCBB9, 0x8B }, + { 0x5FD093, 0x8B }, + { 0x5FD546, 0x8B }, + { 0x60039A, 0x8B }, + { 0x603509, 0x8B }, + { 0x605474, 0x8B }, + { 0x606A5B, 0x8B }, + { 0x609A2C, 0x8B }, + { 0x60FFB5, 0x8B }, + { 0x6100EF, 0x8B }, + { 0x610154, 0x8B }, + { 0x610738, 0x8B }, + { 0x6110C4, 0x8B }, + { 0x6110F3, 0x8B }, + { 0x611206, 0x8B }, + { 0x611454, 0x8B }, + { 0x611474, 0x8B }, + { 0x611494, 0x8B }, + { 0x611764, 0x8B }, + { 0x611794, 0x8B }, + { 0x6117B4, 0x8B }, + { 0x611CC7, 0x8B }, + { 0x611D04, 0x8B }, + { 0x611D65, 0x8B }, + { 0x611D92, 0x8B }, + { 0x611DD0, 0x8B }, + { 0x611E49, 0x8B }, + { 0x611E53, 0x8B }, + { 0x611ED4, 0x8B }, + { 0x611EEF, 0x8B }, + { 0x61235C, 0x8B }, + { 0x6123AF, 0x8B }, + { 0x61259A, 0x8B }, + { 0x612EEA, 0x8B }, + { 0x61300B, 0x8B }, + { 0x61304C, 0x8B }, + { 0x613065, 0x8B }, + { 0x61307E, 0x8B }, + { 0x613093, 0x8B }, + { 0x6130AB, 0x8B }, + { 0x6130DA, 0x8B }, + { 0x6130F3, 0x8B }, + { 0x6131F2, 0x8B }, + { 0x61321D, 0x8B }, + { 0x613227, 0x8B }, + { 0x61326D, 0x8B }, + { 0x6132B1, 0x8B }, + { 0x61331D, 0x8B }, + { 0x61333F, 0x8B }, + { 0x613B43, 0x8B }, + { 0x613B5A, 0x8B }, + { 0x613CF7, 0x8B }, + { 0x613E15, 0x8B }, + { 0x613E9B, 0x8B }, + { 0x613EED, 0x8B }, + { 0x61417E, 0x8B }, + { 0x6142E8, 0x8B }, + { 0x61451B, 0x8B }, + { 0x61454B, 0x8B }, + { 0x6145DD, 0x8B }, + { 0x6146AD, 0x8B }, + { 0x6146D5, 0x8B }, + { 0x614A90, 0x8B }, + { 0x614C6D, 0x8B }, + { 0x614CF4, 0x8B }, + { 0x614D42, 0x8B }, + { 0x614FE9, 0x8B }, + { 0x61511B, 0x8B }, + { 0x6152C3, 0x8B }, + { 0x616A9D, 0x8B }, + { 0x616AAE, 0x8B }, + { 0x616AE8, 0x8B }, + { 0x616AF9, 0x8B }, + { 0x62428B, 0x8B }, + { 0x62439A, 0x8B }, + { 0x627D2B, 0x8B }, + { 0x628A3B, 0x8B }, + { 0x6291BB, 0x8B }, + { 0x64087E, 0x8B }, + { 0x640B3B, 0x8B }, + { 0x642431, 0x8B }, + { 0x642C41, 0x8B }, + { 0x6432BF, 0x8B }, + { 0x643357, 0x8B }, + { 0x64916D, 0x8B }, + { 0x64D04D, 0x8B }, + { 0x64E74F, 0x8B }, + { 0x64FC21, 0x8B }, + { 0x6504DE, 0x8B }, + { 0x6509BC, 0x8B }, + { 0x650E09, 0x8B }, + { 0x656573, 0x8B }, + { 0x65D35A, 0x8B }, + { 0x6641B5, 0x8B }, + { 0x66477A, 0x8B }, + { 0x664BF2, 0x8B }, + { 0x66F4D1, 0x8B }, + { 0x66F92A, 0x8B }, + { 0x66F99E, 0x8B }, + { 0x66FA11, 0x8B }, + { 0x66FA85, 0x8B }, + { 0x66FAF9, 0x8B }, + { 0x66FB6D, 0x8B }, + { 0x66FBE1, 0x8B }, + { 0x66FC55, 0x8B }, + { 0x67C82F, 0x8B }, + { 0x67C83D, 0x8B }, + { 0x67D5C6, 0x8B }, + { 0x67DFCE, 0x8B }, + { 0x68D9F5, 0x8B }, + { 0x69368A, 0x8B }, + { 0x69598C, 0x8B }, + { 0x6969C5, 0x8B }, + { 0x696AF3, 0x8B }, + { 0x69912E, 0x8B }, + { 0x699268, 0x8B }, + { 0x6995EC, 0x8B }, + { 0x699701, 0x8B }, + { 0x69A77E, 0x8B }, + { 0x69B909, 0x8B }, + { 0x6A07AB, 0x8B }, + { 0x6A1577, 0x8B }, + { 0x6A26C2, 0x8B }, + { 0x6A2792, 0x8B }, + { 0x6A2871, 0x8B }, + { 0x6A2936, 0x8B }, + { 0x6A2F88, 0x8B }, + { 0x6A307F, 0x8B }, + { 0x6A3BDB, 0x8B }, + { 0x6A452A, 0x8B }, + { 0x6A4805, 0x8B }, + { 0x6A609E, 0x8B }, + { 0x6A65DD, 0x8B }, + { 0x6A7178, 0x8B }, + { 0x6A8B6E, 0x8B }, + { 0x6AA2E2, 0x8B }, + { 0x6ABD16, 0x8B }, + { 0x6AE28B, 0x8B }, + { 0x6AE2CE, 0x8B }, + { 0x6AE302, 0x8B }, + { 0x6AE332, 0x8B }, + { 0x6AE5D5, 0x8B }, + { 0x6AE60E, 0x8B }, + { 0x6AF1EA, 0x8B }, + { 0x6AF320, 0x8B }, + { 0x6AF37E, 0x8B }, + { 0x6B0581, 0x8B }, + { 0x6B0B22, 0x8B }, + { 0x6B1386, 0x8B }, + { 0x6B14B6, 0x8B }, + { 0x6B16A7, 0x8B }, + { 0x6B16EF, 0x8B }, + { 0x6B3F7D, 0x8B }, + { 0x6B4100, 0x8B }, + { 0x6B67EA, 0x8B }, + { 0x6B6965, 0x8B }, + { 0x6B804C, 0x8B }, + { 0x6B89BC, 0x8B }, + { 0x6B927D, 0x8B }, + { 0x6BBC76, 0x8B }, + { 0x6BC93C, 0x8B }, + { 0x6BD683, 0x8B }, + { 0x6BE009, 0x8B }, + { 0x6BF48A, 0x8B }, + { 0x6BF857, 0x8B }, + { 0x6C0B3F, 0x8B }, + { 0x6C1483, 0x8B }, + { 0x6C440E, 0x8B }, + { 0x6C5446, 0x8B }, + { 0x6C7E83, 0x8B }, + { 0x6C7FBC, 0x8B }, + { 0x6C8E60, 0x8B }, + { 0x6C94D5, 0x8B }, + { 0x6CE3B9, 0x8B }, + { 0x6CEAF5, 0x8B }, + { 0x6CEEA4, 0x8B }, + { 0x6CF1AA, 0x8B }, + { 0x6CFAE5, 0x8B }, + { 0x6CFD92, 0x8B }, + { 0x6D0B79, 0x8B }, + { 0x6D0C4C, 0x8B }, + { 0x6D0E49, 0x8B }, + { 0x6D0E76, 0x8B }, + { 0x6D2315, 0x8B }, + { 0x6D2B02, 0x8B }, + { 0x6D31EC, 0x8B }, + { 0x6D32DF, 0x8B }, + { 0x6D3875, 0x8B }, + { 0x6D3971, 0x8B }, + { 0x6D3A21, 0x8B }, + { 0x6D429A, 0x8B }, + { 0x6D46E9, 0x8B }, + { 0x6D5431, 0x8B }, + { 0x6D63F4, 0x8B }, + { 0x6D649D, 0x8B }, + { 0x6D64D4, 0x8B }, + { 0x6D64FE, 0x8B }, + { 0x6D6A4E, 0x8B }, + { 0x6D7ED5, 0x8B }, + { 0x6DB171, 0x8B }, + { 0x6DE2EA, 0x8B }, + { 0x6DF455, 0x8B }, + { 0x6DF936, 0x8B }, + { 0x6DF9C7, 0x8B }, + { 0x6DFA2F, 0x8B }, + { 0x6DFA3A, 0x8B }, + { 0x6DFB48, 0x8B }, + { 0x6DFB8A, 0x8B }, + { 0x6DFBFA, 0x8B }, + { 0x6E0A62, 0x8B }, + { 0x6E0E2D, 0x8B }, + { 0x6E144B, 0x8B }, + { 0x6E1607, 0x8B }, + { 0x6E17B9, 0x8B }, + { 0x6E1F35, 0x8B }, + { 0x6E22C6, 0x8B }, + { 0x6E3296, 0x8B }, + { 0x6E3312, 0x8B }, + { 0x6E3396, 0x8B }, + { 0x6F0D46, 0x8B }, + { 0x6F2987, 0x8B }, + { 0x6F2FF1, 0x8B }, + { 0x6F32EA, 0x8B }, + { 0x6F3398, 0x8B }, + { 0x6F33B2, 0x8B }, + { 0x6F3596, 0x8B }, + { 0x6F3753, 0x8B }, + { 0x6F376B, 0x8B }, + { 0x6F3990, 0x8B }, + { 0x6F6073, 0x8B }, + { 0x6F6FBB, 0x8B }, + { 0x6F7735, 0x8B }, + { 0x6F7761, 0x8B }, + { 0x6F9132, 0x8B }, + { 0x6F9380, 0x8B }, + { 0x6F9953, 0x8B }, + { 0x6FC805, 0x8B }, + { 0x7086E9, 0x8B }, + { 0x70A068, 0x8B }, + { 0x70A586, 0x8B }, + { 0x70A73C, 0x8B }, + { 0x70A8C5, 0x8B }, + { 0x711BDA, 0x8B }, + { 0x711CF6, 0x8B }, + { 0x7179E3, 0x8B }, + { 0x71AFF4, 0x8B }, + { 0x71BC64, 0x8B }, + { 0x71C0E9, 0x8B }, + { 0x71CFF8, 0x8B }, + { 0x71D032, 0x8B }, + { 0x71FB44, 0x8B }, + { 0x71FB88, 0x8B }, + { 0x71FC9A, 0x8B }, + { 0x71FD47, 0x8B }, + { 0x71FE09, 0x8B }, + { 0x71FEDA, 0x8B }, + { 0x71FFC2, 0x8B }, + { 0x73227A, 0x8B }, + { 0x732B55, 0x8B }, + { 0x736F18, 0x8B }, + { 0x738409, 0x8B }, + { 0x73A398, 0x8B }, + { 0x73A3B9, 0x8B }, + { 0x73B525, 0x8B }, + { 0x73B537, 0x8B }, + { 0x73D5D0, 0x8B }, + { 0x73EC5D, 0x8B }, + { 0x74103B, 0x8B }, + { 0x1562A25, 0x8B }, + { 0x1562B84, 0x8B }, + { 0x1564572, 0x8B }, + { 0x1564E82, 0x8B }, + { 0x156524C, 0x8B }, + { 0x15662D5, 0x8B }, + { 0x15664FD, 0x8B }, + { 0x156657A, 0x8B }, + { 0x15665B9, 0x8B }, + { 0x1566F05, 0x8B }, + { 0x15691BE, 0x8B }, + { 0x15691C5, 0x8B }, + { 0x156C22A, 0x8B }, + { 0x156C258, 0x8B }, + { 0x156C5C5, 0x8B }, + { 0x156CA6D, 0x8B }, + { 0x156CAB2, 0x8B }, + { 0x156D0C9, 0x8B }, + { 0x156D0F6, 0x8B }, + { 0x156D126, 0x8B }, + { 0x15702D8, 0x8B }, + { 0x1570300, 0x8B }, + { 0x1570328, 0x8B }, + { 0x1570350, 0x8B }, + { 0x1570378, 0x8B }, + { 0x15703A0, 0x8B }, + { 0x1570494, 0x8B }, + { 0x15704ED, 0x8B }, +}; + +//----------------------------------------------------------- + +// MATCH +BOOL RelocateModelInfoHack() +{ + DWORD addr; + BYTE byte; + + int x=0; + while(x!=707) { + if(iGtaVersion == GTASA_VERSION_USA10) { + addr = ModelInfoPtrsPatchUSA[x].addr; + byte = ModelInfoPtrsPatchUSA[x].byte; + } else { + addr = ModelInfoPtrsPatchEU[x].addr; + byte = ModelInfoPtrsPatchEU[x].byte; + } + if(byte == *(BYTE*)addr) { + if(byte == 0x8B || byte == 0x89 || byte == 0x39) { + UnFuck(addr + 3, 4); + *(DWORD*)(addr + 3) = (DWORD)ModelInfoPtr; + } else if(byte == 0xBE || byte == 0xBF) { + UnFuck(addr + 1, 4); + *(DWORD*)(addr + 1) = (DWORD)ModelInfoPtr; + } + } + x++; + } + bModelInfoPathesApplied = TRUE; + return TRUE; +} + +//----------------------------------------------------------- + +// MATCH +BOOL InitModelInfoHack() +{ + memset(ModelInfoArray,0,sizeof(ModelInfoArray)); + memcpy(ModelInfoPtr,(void*)0xA9B0C8,80000); + RelocateModelInfoHack(); + FUNC_100A6FF0(); + return TRUE; +} + +//----------------------------------------------------------- + +// MATCH +MODEL_INFO_TYPE* __stdcall GetModelInfo(int iModelID) +{ + if(bModelInfoPathesApplied) + return ModelInfoPtr[iModelID]; + + if(iModelID < 0 || iModelID > 20000) return NULL; + + return *(MODEL_INFO_TYPE**)(4 * iModelID + 0xA9B0C8); +} + +//----------------------------------------------------------- + +// MATCH +void FreeModelInfo(int iModelID) +{ + if(ModelInfoPtr[iModelID]) + { + free(ModelInfoPtr[iModelID]); + ModelInfoPtr[iModelID] = NULL; + } +} + +//----------------------------------------------------------- diff --git a/saco/game/modelinfo.h b/saco/game/modelinfo.h new file mode 100644 index 0000000..0393546 --- /dev/null +++ b/saco/game/modelinfo.h @@ -0,0 +1,26 @@ + +#pragma once + +// size must be exactly 68 bytes +typedef struct _MODEL_INFO_TYPE { + + DWORD vtable; // 0-4 + + char _gap4[24]; + + DWORD *pdwRenderWare; // 28-32 + + char _gap20[4]; + + DWORD dwAnimType; // 36-40 + DWORD dwPedType; // 40-44 + DWORD dwStatType; // 44-48 + + char _pad30[20]; + +} MODEL_INFO_TYPE; + +BOOL RelocateModelInfoHack(); +BOOL InitModelInfoHack(); +MODEL_INFO_TYPE* __stdcall GetModelInfo(int iModelID); +void FreeModelInfo(int iModelID); // unused diff --git a/saco/game/object.cpp b/saco/game/object.cpp new file mode 100644 index 0000000..274dc17 --- /dev/null +++ b/saco/game/object.cpp @@ -0,0 +1,8 @@ + +#include "../main.h" + +CObject::CObject(int iModel, float fPosX, float fPosY, float fPosZ) +{ + + +} diff --git a/saco/game/object.h b/saco/game/object.h new file mode 100644 index 0000000..eb9d106 --- /dev/null +++ b/saco/game/object.h @@ -0,0 +1,12 @@ + +#pragma once + +#include "entity.h" + +//---------------------------------------------------- + +class CObject : public CEntity +{ +public: + CObject(int iModel, float fPosX, float fPosY, float fPosZ); +}; diff --git a/saco/game/patches.cpp b/saco/game/patches.cpp index ceb3e21..9e3e30c 100644 --- a/saco/game/patches.cpp +++ b/saco/game/patches.cpp @@ -4,6 +4,7 @@ DWORD dwSystemMemory; DWORD dwStreamingMemory; +void InstallSCMEventsProcessor(); void RelocateScanListHack(); void RelocatePedsListHack(); void RelocateBaseModelInfoHack(); @@ -440,6 +441,42 @@ void ApplyVehicleColorPatches() //---------------------------------------------------------- +void InstallGameAndGraphicsLoopHooks(); + +void ApplyDebugLevelPatches() +{ + // hack to remove motion blur in high speed vehicle + UnFuck(0x704E8A,5); + memset((PVOID)0x704E8A,0x90,5); + + // Don't go back to player anims, use the peds IDE + UnFuck(0x609A4E,6); + memset((PVOID)0x609A4E, 0x90, 6); + + InstallGameAndGraphicsLoopHooks(); + RelocateScanListHack(); + RelocatePedsListHack(); + ApplyVehicleColorPatches(); + RelocateBaseModelInfoHack(); + ApplyGameLimitPatches(); + + UnFuck(0x47BF54,4); + InstallSCMEventsProcessor(); +} + +//---------------------------------------------------------- + +BYTE pbyteTrainDelrailmentPatch[] = { + 0xB8, 0x89, 0x8F, 0x6F, 0x00, 0xFF, 0xE0 +}; + +float GLOBAL_101166F0 = 20000.0f; +float GLOBAL_101166F4 = -20000.0f; + +float GLOBAL_10116714 = 0.14f; +float GLOBAL_10116718 = 2.0f; +float GLOBAL_1011671C = 10000.0f; + extern DWORD dwFarClipHookAddr; extern DWORD dwFarClipReturnAddr; @@ -455,9 +492,331 @@ void ApplyInGamePatches() RelocateScanListHack(); RelocatePedsListHack(); // allows us to use all 300 ped model slots - + ApplyVehicleColorPatches(); RelocateBaseModelInfoHack(); + ApplyGameLimitPatches(); + UnFuck(0x4DF7E2,2); + memset((PVOID)0x4DF7E2,0x90,5); + + // VehicleStruct increase + UnFuck(0x5B8FE4,1); + *(BYTE*)0x5B8FE4 = 127; + + UnFuck(0x5720A5,5); + memset((PVOID)0x5720A5,0x90,5); + + // Remove random procedural geometry like plants/rocks etc. + UnFuck(0x53C159,5); + memset((PVOID)0x53C159,0x90,5); + + UnFuck(0x53C136,5); + memset((PVOID)0x53C136,0x90,5); + + // Automatic go-to-menu on alt+tab + if(iGtaVersion == GTASA_VERSION_USA10) { + UnFuck(0x748063, 5); + memset((PVOID)0x748063, 0x90, 5); + } else { + UnFuck(0x7480B3, 5); + memset((PVOID)0x7480B3, 0x90, 5); + } + + // No vehicle name rendering + UnFuck(0x58FBE9,5); + memset((PVOID)0x58FBE9,0x90,5); + + // No playidles anim loading. + UnFuck(0x86D1EC,1); + *(BYTE*)0x86D1EC = '\0'; + + // Prevent replays + UnFuck(0x53C090,5); + memset((PVOID)0x53C090,0x90,5); + + // NO MORE INTERIOR PEDS + UnFuck(0x440833,8); + memset((PVOID)0x440833,0x90,8); + + // caused 0x706B2E crash (This seems to be ped shadow rendering) + UnFuck(0x53EA08,10); + memset((PVOID)0x53EA08,0x90,10); + + // Make the shadows slightly darker by increasing the alpha + UnFuck(0x71162C,1); + *(PBYTE)0x71162C = 80; + + // Unknown from CPlayerPed::ProcessControl causes crash + UnFuck(0x609C08,39); + memset((PVOID)0x609C08,0x90,39); + + // FindPlayerVehicle (Always use nPlayerPed) + UnFuck(0x56E0FA,18); + memset((PVOID)0x56E0FA,0x90,18); + + // CMotorBike::ProcessControlInputs.. why oh why.. + UnFuck(0x6BC9EB,2); + memset((PVOID)0x6BC9EB,0x90,2); + + // Smallish patch to fix the drown-in-vehicle crash + UnFuck(0x4BC6C1,3); + *(BYTE*)0x4BC6C1 = 0xB0; + *(BYTE*)0x4BC6C2 = 0x00; + *(BYTE*)0x4BC6C3 = 0x90; + + // Allow all vehicles to be sprayed; + UnFuck(0x44AC75,5); + memset((PVOID)0x44AC75,0x90,5); + *(BYTE*)0x44AC75 = 0xB0; + *(BYTE*)0x44AC76 = 0x01; + + // This removes the random weapon pickups (e.g. on the hill near chilliad) + UnFuck(0x5B47B0,1); + memset((PVOID)0x5B47B0,0xC3,1); + + // Removes the FindPlayerInfoForThisPlayerPed at these locations. + UnFuck(0x5E63A6,19); + memset((PVOID)0x5E63A6,0x90,19); + + UnFuck(0x621AEA,12); + memset((PVOID)0x621AEA,0x90,12); + + UnFuck(0x62D331,11); + memset((PVOID)0x62D331,0x90,11); + + UnFuck(0x741FFF,27); + memset((PVOID)0x741FFF,0x90,27); + + // hack to remove motion blur in high speed vehicle + UnFuck(0x704E8A,5); + memset((PVOID)0x704E8A,0x90,5); + + // Respawn and Interior + UnFuck(0x4090A0,1); + *(BYTE*)0x4090A0 = 0xC3; + + // Respawn and Interior + UnFuck(0x441482,5); + memset((void*)0x441482, 0x90, 5); + + // No MessagePrint + UnFuck(0x588BE0,1); + *(BYTE*)0x588BE0 = 0xC3; + + // No IPL vehicle + UnFuck(0x53C06A,5); + memset((PVOID)0x53C06A,0x90,5); + + // SomeCarGenerator (0x41a8b3 crash) + UnFuck(0x434272,5); + memset((PVOID)0x434272,0x90,5); + + // CPlayerPed_CPlayerPed .. task system corrupts some shit + UnFuck(0x60D64D,2); + *(PBYTE)0x60D64E = 0x84; // jnz to jz + + // CPhysical Destructor (705b3b crash) + UnFuck(0x542485,11); + memset((PVOID)0x542485,0x90,11); + + // No peds kthx. (CPopulation::AddPed() nulled) + UnFuck(0x612710,3); + *(BYTE*)0x612710 = 0x33; + *(BYTE*)0x612711 = 0xC0; // xor eax, eax + *(BYTE*)0x612712 = 0xC3; // ret + + // Fuck the call to CPopulation::AddPed() for create_train off to kingdom kong + UnFuck(0x613BA7, 5); + memset((PVOID)0x613BA7, 0x90, 5); + + // Don't go back to player anims, use the peds IDE + UnFuck(0x609A4E,6); + memset((PVOID)0x609A4E, 0x90, 6); + + // Train derailment + UnFuck(0x006F8CF8, 12); + memset((PVOID)0x006F8CF8, 0x90, 5); // (Actual hook is installed in hooks.cpp) + memcpy((PVOID)(0x006F8CF8+5), pbyteTrainDelrailmentPatch, sizeof(pbyteTrainDelrailmentPatch)); + + // CarCtl::GenerateRandomCars nulled from CGame::Process (firetrucks etc) + UnFuck(0x53C1C1,5); + memset((PVOID)0x53C1C1,0x90,5); + + // (540040 bug), test ecx for 0 instead of [ecx+270] + UnFuck(0x540040,10); + // nop the first 8 bytes + memset((PVOID)0x540040,0x90,6); + *(PBYTE)0x540046 = 0x85; + *(PBYTE)0x540047 = 0xC9; // test ecx, ecx + *(PBYTE)0x540048 = 0x74; // jz + + // No wasted message + UnFuck(0x56E5AD,5); + memset((PVOID)0x56E5AD,0x90,5); + + // For the input disabling in CGame. + UnFuck(0x541DF5,5); + + // Ret at CCamera::ClearPlayerWeaponMode + UnFuck(0x609CB4,5); + memset((PVOID)0x609CB4,0x90,5); + + // PlayerInfo checks in CPlayerPed::ProcessControl + UnFuck(0x60F2C4,25); + memset((PVOID)0x60F2C4,0x90,25); + + // No Vehicle Audio Processing (done manually from the hooks) + UnFuck(0x6B18F1,5); + memset((PVOID)0x6B18F1,0x90,5); + UnFuck(0x6B9298,5); + memset((PVOID)0x6B9298,0x90,5); + UnFuck(0x6F1793,5); + memset((PVOID)0x6F1793,0x90,5); + UnFuck(0x6F86B6,5); + memset((PVOID)0x6F86B6,0x90,5); + + // camera_on_actor patch, tsk tsk R* + UnFuck(0x0047C477,1); + *(BYTE*)0x0047C477 = 0xEB; + + // CPushBike fires set on CPed patch + UnFuck(0x0053A984,2); + *(BYTE*)0x0053A984 = 0xEB; // jmp + *(BYTE*)0x0053A985 = 0x77; // +77h = 0x0053A9FD + + // Stop sniper clicking + UnFuck(0x0060F289, 8); + memset((PVOID)0x0060F289, 0x90, 8); + UnFuck(0x0060F29D, 19); + memset((PVOID)0x0060F29D, 0x90, 19); + + // Wanted level hook + UnFuck(0x58DB5F, 9); + *(BYTE*)0x58DB5F = 0xBD; + *(BYTE*)0x58DB60 = 0x00; + *(BYTE*)0x58DB61 = 0x00; + *(BYTE*)0x58DB62 = 0x00; + *(BYTE*)0x58DB63 = 0x00; + *(BYTE*)0x58DB64 = 0x90; + *(BYTE*)0x58DB65 = 0x90; + *(BYTE*)0x58DB66 = 0x90; + *(BYTE*)0x58DB67 = 0x90; + + // Remove the blue(-ish) fog in the map + UnFuck(0x00575B0E, 5); + memset((PVOID)0x00575B0E, 0x90, 5); + + // Remove the CReferences call from CTaskEnterVehicleDriver ctor + UnFuck(0x63ADC8,6); + memset((PVOID)0x63ADC8,0x90,6); + + UnFuck(0x58FC2E,30); + memset((PVOID)0x58FC2E,0x90,30); + + UnFuck(0x5E1E70,2); + *(BYTE*)0x5E1E70 = 0x33; + *(BYTE*)0x5E1E71 = 0xC0; + + UnFuck(0x6A8500,119); + memset((PVOID)0x6A8500,0xC3,119); + + UnFuck(0x593D7C,5); + memset((PVOID)0x593D7C,0x90,5); + + if(iGtaVersion == GTASA_VERSION_USA10) { + UnFuck(0x7469AF,2); + *(BYTE*)0x7469AF = 0x33; + *(BYTE*)0x7469B0 = 0xC0; + } else { + UnFuck(0x7469FF,2); + *(BYTE*)0x7469FF = 0x33; + *(BYTE*)0x746A00 = 0xC0; + } + + UnFuck(0x61E0C2,4); + *(DWORD*)0x61E0C2 = (DWORD)&GLOBAL_10116718; + + UnFuck(0x454CC9,4); + *(DWORD*)0x454CC9 = (DWORD)&GLOBAL_1011671C; + + UnFuck(0x5952A6,5); + memset((PVOID)0x5952A6,0x90,5); + + // Stop ped rotations from the camera + UnFuck(0x6884C4,6); + UnFuck(0x688200,6); + memset((PVOID)0x6884C4,0x90,6); + memset((PVOID)0x688200,0x90,6); + + UnFuck(0x570535,15); + memset((PVOID)0x570535,0x90,15); + + UnFuck(0x5E7847,17); + memset((PVOID)0x5E7847,0x90,17); + + UnFuck(0x570546,175); + memset((PVOID)0x570546,0x90,175); + + UnFuck(0x6D1874,24); + *(DWORD*)0x6D1874 = 0x6D17D5; + *(DWORD*)0x6D1878 = 0x6D17D5; + *(DWORD*)0x6D187C = 0x6D17D5; + *(DWORD*)0x6D1880 = 0x6D17D5; + *(DWORD*)0x6D1884 = 0x6D17D5; + *(DWORD*)0x6D1888 = 0x6D17D5; + + UnFuck(0x64DB49,9); + memset((PVOID)0x64DB49,0x90,9); + + UnFuck(0x64BC9F,9); + memset((PVOID)0x64BC9F,0x90,9); + + UnFuck(0x64B872,9); + memset((PVOID)0x64B872,0x90,9); + + UnFuck(0x5E7D62,5); + *(BYTE*)0x5E7D62 = 0x5E; + *(BYTE*)0x5E7D63 = 0x5D; + *(BYTE*)0x5E7D64 = 0xC2; + *(BYTE*)0x5E7D65 = 0x1C; + *(BYTE*)0x5E7D66 = 0x00; + + UnFuck(0x6348F6,4); + *(DWORD*)0x6348F6 = 0xFFFFFFFF; + UnFuck(0x634DE2,4); + *(DWORD*)0x634DE2 = 0xFFFFFFFF; + + UnFuck(0x71A220,1024); + FUNC_100AA540(); + + UnFuck(0x7361B2,4); + *(DWORD*)0x7361B2 = (DWORD)&GLOBAL_101166F4; + UnFuck(0x7361CB,4); + *(DWORD*)0x7361CB = (DWORD)&GLOBAL_101166F0; + UnFuck(0x7361E0,4); + *(DWORD*)0x7361E0 = (DWORD)&GLOBAL_101166F4; + UnFuck(0x7361F5,4); + *(DWORD*)0x7361F5 = (DWORD)&GLOBAL_101166F0; + + UnFuck(0x524582,5); + memset((PVOID)0x524582,0x90,5); + + UnFuck(0x712025,1); + *(BYTE*)0x712025 = 1; + + UnFuck(0x858B90,4); + + UnFuck(0x53BF28,5); + memset((PVOID)0x53BF28,0x90,5); + + UnFuck(0x859520,8); + UnFuck(0xC17044,8); + + UnFuck(0x4C3A5B,10); + memset((PVOID)0x4C3A5B,0x90,10); + + UnFuck(0x47BF54,4); + InstallSCMEventsProcessor(); } //---------------------------------------------------------- diff --git a/saco/game/playerped.cpp b/saco/game/playerped.cpp index 80eddd2..a308385 100644 --- a/saco/game/playerped.cpp +++ b/saco/game/playerped.cpp @@ -1,16 +1,22 @@ +#include +#include +#define _ASSERT assert + #include "../main.h" +#include "game.h" #include "util.h" #include "keystuff.h" #include "task.h" extern CGame *pGame; +extern CNetGame *pNetGame; extern BYTE *pbyteCurrentPlayer; //----------------------------------------------------------- // Used for instancing the local player. - +// MATCH CPlayerPed::CPlayerPed() { m_dwGTAId = 1; // 0x001 @@ -26,11 +32,11 @@ CPlayerPed::CPlayerPed() field_2AC = 1; m_dwArrow = 0; field_2B9 = 0; - field_2F2 = 0; - field_2D2 = 0; + m_iPissingState = 0; + m_iDanceState = 0; field_2DE = 0; field_2E2 = 0; - field_48 = 0; + m_iCellPhoneEnabled = 0; m_bGoggleState = FALSE; field_2C1 = 0; field_2C5 = 0; @@ -54,10 +60,12 @@ CPlayerPed::CPlayerPed() + + //----------------------------------------------------------- // If the game has internally destroyed the ped // during this frame, the ped pointer should become 0 - +// MATCH void CPlayerPed::ResetPointers() { m_pPed = GamePool_Ped_GetAt(m_dwGTAId); @@ -65,7 +73,7 @@ void CPlayerPed::ResetPointers() } //----------------------------------------------------------- - +// MATCH void CPlayerPed::SetInitialState() { DWORD dwPedPtr = (DWORD)m_pPed; @@ -77,7 +85,7 @@ void CPlayerPed::SetInitialState() } //----------------------------------------------------------- - +// MATCH BYTE CPlayerPed::GetSpecialKey() { GTA_CONTROLSET *pInternalKeys = GameGetInternalKeys(); @@ -92,23 +100,27 @@ BYTE CPlayerPed::GetSpecialKey() return 0; } - //----------------------------------------------------------- + + + +//----------------------------------------------------------- +// MATCH CAMERA_AIM * CPlayerPed::GetCurrentAim() { return GameGetInternalAim(); } //----------------------------------------------------------- - +// MATCH void CPlayerPed::SetCurrentAim(CAMERA_AIM *pAim) { GameStoreRemotePlayerAim(m_bytePlayerNumber, pAim); } //----------------------------------------------------------- - +// MATCH BYTE CPlayerPed::GetCurrentWeapon() { if(!m_pPed) return 0; @@ -120,7 +132,7 @@ BYTE CPlayerPed::GetCurrentWeapon() } //----------------------------------------------------------- - +// MATCH int CPlayerPed::GetCurrentVehicleID() { if(!m_pPed) return 0; @@ -129,6 +141,12 @@ int CPlayerPed::GetCurrentVehicleID() return GamePool_Vehicle_GetIndex(pVehicle); } +//----------------------------------------------------------- + + + + + //----------------------------------------------------------- void CPlayerPed::HideMarker() @@ -311,6 +329,10 @@ VEHICLE_TYPE * CPlayerPed::GetGtaVehicle() return (VEHICLE_TYPE *)m_pPed->pVehicle; } +//----------------------------------------------------------- + + + //----------------------------------------------------------- void CPlayerPed::GiveWeapon(int iWeaponID, int iAmmo) @@ -458,52 +480,197 @@ float CPlayerPed::GetDistanceFromVehicle(CVehicle *pVehicle) //----------------------------------------------------------- -WORD CPlayerPed::GetAmmo() +int CPlayerPed::GetVehicleSeatID() { - if(m_pPed) { - WEAPON_SLOT_TYPE * WeaponSlot = GetCurrentWeaponSlot(); + VEHICLE_TYPE *pVehicle; - if(!WeaponSlot) return -1; - - // Melee types always have ammo. - if( WeaponSlot->dwType <= WEAPON_CANE || - WeaponSlot->dwType == WEAPON_PARACHUTE ) return -1; - - return (WORD)WeaponSlot->dwAmmo; + if( GetActionTrigger() == ACTION_INCAR && (pVehicle = (VEHICLE_TYPE *)m_pPed->pVehicle) != 0 ) { + if(pVehicle->pDriver == m_pPed) return 0; + if(pVehicle->pPassengers[0] == m_pPed) return 1; + if(pVehicle->pPassengers[1] == m_pPed) return 2; + if(pVehicle->pPassengers[2] == m_pPed) return 3; + if(pVehicle->pPassengers[3] == m_pPed) return 4; + if(pVehicle->pPassengers[4] == m_pPed) return 5; + if(pVehicle->pPassengers[5] == m_pPed) return 6; + if(pVehicle->pPassengers[6] == m_pPed) return 7; } - return 0; + + return (-1); } //----------------------------------------------------------- -WEAPON_SLOT_TYPE * CPlayerPed::FindWeaponSlot(DWORD dwWeapon) +void CPlayerPed::PutDirectlyInVehicle(int iVehicleID, int iSeat) { - if (m_pPed) - { - BYTE i; - for (i = 0; i < 13; i++) - { - if (m_pPed->WeaponSlots[i].dwType == dwWeapon) return &m_pPed->WeaponSlots[i]; + if(!m_pPed) return; + if(!GamePool_Vehicle_GetAt(iVehicleID)) return; + if(!GamePool_Ped_GetAt(m_dwGTAId)) return; + + if(GetCurrentWeapon() == WEAPON_PARACHUTE) { + SetArmedWeapon(0, false); + } + + VEHICLE_TYPE *pVehicle = GamePool_Vehicle_GetAt(iVehicleID); + + if(pVehicle->fHealth == 0.0f) return; + + // Check to make sure internal data structure of the vehicle hasn't been deleted + // by checking if the vtbl points to CPlaceable_vtbl + if (pVehicle->entity.vtable == 0x863C40) return; + + if(GetVehicleSubtypeFromVehiclePtr(pVehicle) == VEHICLE_SUBTYPE_CAR || GetVehicleSubtypeFromVehiclePtr(pVehicle) == VEHICLE_SUBTYPE_BIKE) return; + if(iSeat > pVehicle->byteMaxPassengers) return; + + if(iSeat==0) { + if(pVehicle->pDriver && IN_VEHICLE(pVehicle->pDriver)) return; + ScriptCommand(&put_actor_in_car,m_dwGTAId,iVehicleID); + } else { + iSeat--; + ScriptCommand(&put_actor_in_car2,m_dwGTAId,iVehicleID,iSeat); + } + if(m_pPed == GamePool_FindPlayerPed() && IN_VEHICLE(m_pPed)) { + pGame->GetCamera()->SetBehindPlayer(); + } + + if(pNetGame) { + CVehiclePool* pVehiclePool = pNetGame->GetVehiclePool(); + // TODO: CPlayerPed::PutDirectlyInVehicle + } +} + +//----------------------------------------------------------- + + + + + + + + + + +//----------------------------------------------------------- +// Forceful removal + +void CPlayerPed::RemoveFromVehicleAndPutAt(float fX, float fY, float fZ) +{ + if(!GamePool_Ped_GetAt(m_dwGTAId)) return; + if(m_pPed && IN_VEHICLE(m_pPed)) { + ScriptCommand(&remove_actor_from_car_and_put_at,m_dwGTAId,fX,fY,fZ); + } +} + +//----------------------------------------------------------- + +void CPlayerPed::TogglePlayerControllable(int iControllable) +{ + MATRIX4X4 mat; + + if(!GamePool_Ped_GetAt(m_dwGTAId)) return; + + if(!iControllable) { + ScriptCommand(&toggle_player_controllable,m_bytePlayerNumber,0); + ScriptCommand(&lock_actor,m_dwGTAId,1); + } else { + ScriptCommand(&toggle_player_controllable,m_bytePlayerNumber,1); + ScriptCommand(&lock_actor,m_dwGTAId,0); + if(!IsInVehicle()) { + GetMatrix(&mat); + TeleportTo(mat.pos.X,mat.pos.Y,mat.pos.Z); } } - return NULL; } //----------------------------------------------------------- -void CPlayerPed::SetAnimationSet(PCHAR szAnim) + + + + + + +//----------------------------------------------------------- + +void CPlayerPed::HandsUp() { - if(m_pPed) { - ScriptCommand(&set_actor_animation_set,m_dwGTAId,szAnim); + if(!m_pPed || IN_VEHICLE(m_pPed)) return; + if(!IsAdded()) return; + if(!GamePool_Ped_GetAt(m_dwGTAId)) return; + ScriptCommand(&actor_task_handsup,m_dwGTAId,-2); +} + +//----------------------------------------------------------- + +BOOL CPlayerPed::HasHandsUp() +{ + if(!m_pPed || IN_VEHICLE(m_pPed)) return FALSE; + if(!IsAdded()) return FALSE; + if(!GamePool_Ped_GetAt(m_dwGTAId)) return FALSE; + if(m_pPed->Tasks->pdwJumpJetPack == NULL) return FALSE; + DWORD dwJmpVtbl = m_pPed->Tasks->pdwJumpJetPack[0]; + if(dwJmpVtbl == 0x85A29C) return TRUE; + + return FALSE; +} + +//----------------------------------------------------------- + +void CPlayerPed::HoldItem(int iObject) +{ + if(!m_pPed) return; + if(!IsAdded()) return; + if(!GamePool_Ped_GetAt(m_dwGTAId)) return; + + DWORD dwPed = (DWORD)m_pPed; + _asm push 1 + _asm push iObject + _asm mov ecx, dwPed + _asm mov ebx, 0x5E4390 + _asm call ebx +} + +//----------------------------------------------------------- + +BOOL CPlayerPed::IsJumpTask() +{ + if(m_pPed && !IN_VEHICLE(m_pPed) && m_pPed->Tasks->pdwJumpJetPack) + { + return GetTaskTypeFromTask(m_pPed->Tasks->pdwJumpJetPack) == 211; } + return FALSE; } //----------------------------------------------------------- -void CPlayerPed::SetMoney(int iAmount) +BOOL CPlayerPed::IsFightTask() { - ScriptCommand(&set_actor_money,m_dwGTAId,0); - ScriptCommand(&set_actor_money,m_dwGTAId,iAmount); + if(m_pPed && !IN_VEHICLE(m_pPed) && m_pPed->Tasks->pdwFighting) + { + return GetTaskTypeFromTask(m_pPed->Tasks->pdwFighting) == 1016; + } + return FALSE; +} + +//----------------------------------------------------------- + +BOOL CPlayerPed::IsTakeFallDamageTask() +{ + if(m_pPed && !IN_VEHICLE(m_pPed) && m_pPed->Tasks->pdwDamage) + { + return GetTaskTypeFromTask(m_pPed->Tasks->pdwDamage) == 208; + } + return FALSE; +} + +//----------------------------------------------------------- + +BOOL CPlayerPed::IsSwimTask() +{ + if(m_pPed && !IN_VEHICLE(m_pPed) && m_pPed->Tasks->pdwSwimWasted) + { + return GetTaskTypeFromTask(m_pPed->Tasks->pdwSwimWasted) == 268; + } + return FALSE; } //----------------------------------------------------------- @@ -592,3 +759,329 @@ BOOL CPlayerPed::HasGoggles() } //----------------------------------------------------------- + + + + + +//----------------------------------------------------------- + +WORD CPlayerPed::GetAmmo() +{ + if(m_pPed) { + WEAPON_SLOT_TYPE * WeaponSlot = GetCurrentWeaponSlot(); + + if(!WeaponSlot) return -1; + + // Melee types always have ammo. + if( WeaponSlot->dwType <= WEAPON_CANE || + WeaponSlot->dwType == WEAPON_PARACHUTE ) return -1; + + return (WORD)WeaponSlot->dwAmmo; + } + return 0; +} + +//----------------------------------------------------------- + + + +//----------------------------------------------------------- + +WEAPON_SLOT_TYPE * CPlayerPed::FindWeaponSlot(DWORD dwWeapon) +{ + if (m_pPed) + { + BYTE i; + for (i = 0; i < 13; i++) + { + if (m_pPed->WeaponSlots[i].dwType == dwWeapon) return &m_pPed->WeaponSlots[i]; + } + } + return NULL; +} + +//----------------------------------------------------------- + +void CPlayerPed::SetAnimationSet(PCHAR szAnim) +{ + if(m_pPed) { + ScriptCommand(&set_actor_animation_set,m_dwGTAId,szAnim); + } +} + +//----------------------------------------------------------- + +void CPlayerPed::SetMoney(int iAmount) +{ + ScriptCommand(&set_actor_money,m_dwGTAId,0); + ScriptCommand(&set_actor_money,m_dwGTAId,iAmount); +} + +//----------------------------------------------------------- + +void CPlayerPed::ApplyAnimation( char *szAnimName, char *szAnimFile, float fT, + int opt1, int opt2, int opt3, int opt4, int iUnk ) +{ + int iWaitAnimLoad=0; + + if(!m_pPed) return; + if(!GamePool_Ped_GetAt(m_dwGTAId)) return; + + // Can't allow 'naughty' anims! + if( !stricmp(szAnimFile,"SEX") ) + return; + + if (!pGame->IsAnimationLoaded(szAnimFile)) { + pGame->RequestAnimation(szAnimFile); + while(!pGame->IsAnimationLoaded(szAnimFile)) { + Sleep(1); + iWaitAnimLoad++; + if(iWaitAnimLoad == 15) return; // we can't wait forever + } + } + + ScriptCommand(&apply_animation,m_dwGTAId,szAnimName,szAnimFile,fT,opt1,opt2,opt3,opt4,iUnk); +} + +//----------------------------------------------------------- + +BOOL CPlayerPed::IsPerformingAnimation(char *szAnimName) +{ + if(m_pPed && ScriptCommand(&is_actor_performing_anim,m_dwGTAId,szAnimName)) { + return TRUE; + } + return FALSE; +} + +//----------------------------------------------------------- + + + + + + +//----------------------------------------------------------- + +ENTITY_TYPE* CPlayerPed::GetGtaContactEntity() +{ + return (ENTITY_TYPE*)m_pPed->pContactEntity; +} + +//----------------------------------------------------------- + +VEHICLE_TYPE* CPlayerPed::GetGtaContactVehicle() +{ + return (VEHICLE_TYPE*)m_pPed->pContactVehicle; +} + +//----------------------------------------------------------- + + + + + +//----------------------------------------------------------- + +char DanceStyleLibs[4][16] = {"WOP","GFUNK","RUNNINGMAN","STRIP"}; +char DanceIdleLoops[4][16] = {"DANCE_LOOP","DANCE_LOOP","DANCE_LOOP","STR_Loop_B"}; + +void CPlayerPed::StartDancing(int iStyle) +{ + if(iStyle < 0 || iStyle > 3) return; + + m_iDanceState = 1; + m_iDanceStyle = iStyle; + + if(m_bytePlayerNumber == 0) { + ApplyAnimation(DanceIdleLoops[m_iDanceStyle],DanceStyleLibs[m_iDanceStyle],16.0,1,0,0,0,-1); + } +} + +//----------------------------------------------------------- + +void CPlayerPed::StopDancing() +{ + m_iDanceState = 0; + MATRIX4X4 mat; + GetMatrix(&mat); + TeleportTo(mat.pos.X,mat.pos.Y,mat.pos.Z); +} + +//----------------------------------------------------------- + +BOOL CPlayerPed::IsDancing() +{ + if(m_iDanceState) return TRUE; + return FALSE; +} + +//----------------------------------------------------------- + + + + + + +//----------------------------------------------------------- + +void CPlayerPed::ProcessMarkers(BOOL bMarkerStreamingEnabled, float fMarkerStreamRadius, BOOL bVisible) +{ + if(!m_pPed) return; +} + +//----------------------------------------------------------- + +void CPlayerPed::ApplyCommandTask(char *szTaskName, int p1, int p2, int p3, + VECTOR *p4, int p5, float p6, int p7, int p8, int p9) +{ + DWORD dwPed = (DWORD)m_pPed; + if(!dwPed) return; + + _asm push p9 + _asm push p8 + _asm push p7 + _asm push p6 + _asm push p5 + _asm push p4 + _asm push p3 + _asm push p2 + _asm push p1 + _asm push dwPed + _asm push szTaskName + _asm mov ecx, 0xC15448 + _asm mov edx, 0x618970 + _asm call edx +} + +//----------------------------------------------------------- + +DWORD dwExt4; + +void CPlayerPed::DestroyFollowPedTask() +{ + if(!m_pPed) return; + dwExt4 = (DWORD)m_pPed->Tasks->pdwIK; + if(!dwExt4) return; + + _asm mov ecx, dwExt4 + _asm mov edx, 0x639330 + _asm push 1 + _asm call edx + + m_pPed->Tasks->pdwIK = 0; +} + +//----------------------------------------------------------- + +void CPlayerPed::ToggleCellphone(int iOn) +{ + if(!m_pPed) return; + m_iCellPhoneEnabled = iOn; + ScriptCommand(&toggle_actor_cellphone,m_dwGTAId,iOn); +} + +//----------------------------------------------------------- + +int CPlayerPed::IsCellphoneEnabled() +{ + return m_iCellPhoneEnabled; +} + +//----------------------------------------------------------- + +int CPlayerPed::GetFightingStyle() +{ + if (!m_pPed) return 0; + return m_pPed->byteFightingStyle; +} + +//----------------------------------------------------------- + +void CPlayerPed::SetFightingStyle(int iStyle) +{ + if (!m_pPed) return; + + ScriptCommand( &set_fighting_style, m_dwGTAId, iStyle, 6 ); +} + +//----------------------------------------------------------- + +void CPlayerPed::StartPissing() +{ + if(!m_pPed) return; + if(!GamePool_Ped_GetAt(m_dwGTAId)) return; + + if(m_iPissingState != 0) { + // already started + return; + } + + if (!m_bytePlayerNumber) { + ApplyAnimation("PISS_LOOP","PAULNMAC", 4.0f, 1, 0, 0, 0, -1); + } + + ScriptCommand(&attach_particle_to_actor2,"PETROLCAN",m_dwGTAId, + 0.0f, 0.58f, -0.08f, 0.0f, 0.01f, 0.0f, 1, &m_dwPissParticlesHandle); + + ScriptCommand(&make_particle_visible,m_dwPissParticlesHandle); + + m_iPissingState = 1; +} + +//----------------------------------------------------------- + +void CPlayerPed::StopPissing() +{ + if(!m_pPed) return; + if(!GamePool_Ped_GetAt(m_dwGTAId)) return; + if(!m_iPissingState) return; + + if(m_dwPissParticlesHandle) { + ScriptCommand(&destroy_particle,m_dwPissParticlesHandle); + m_dwPissParticlesHandle = 0; + } + + MATRIX4X4 mat; + GetMatrix(&mat); + TeleportTo(mat.pos.X,mat.pos.Y,mat.pos.Z); + + m_iPissingState = 0; +} + +//----------------------------------------------------------- + +int CPlayerPed::IsPissing() +{ + return m_iPissingState; +} + +//----------------------------------------------------------- + +void CPlayerPed::ProcessVehicleHorn() +{ + if(!m_pPed) return; + if(!GamePool_Ped_GetAt(m_dwGTAId)) return; + + GTA_CONTROLSET *pPlayerControls; + + if(!m_bytePlayerNumber) { + pPlayerControls = GameGetInternalKeys(); + } else { + pPlayerControls = GameGetPlayerKeys(m_bytePlayerNumber); + } + + VEHICLE_TYPE *pGtaVehicle = (VEHICLE_TYPE *)m_pPed->pVehicle; + + if(pGtaVehicle) { + if(IN_VEHICLE(m_pPed) && (pGtaVehicle->pDriver == m_pPed)) { + if(pPlayerControls->wKeys1[18]) { + pGtaVehicle->byteHorn2 = 1; + } else { + pGtaVehicle->byteHorn2 = 0; + } + } + } +} + +//----------------------------------------------------------- diff --git a/saco/game/playerped.h b/saco/game/playerped.h index f779b03..884dc53 100644 --- a/saco/game/playerped.h +++ b/saco/game/playerped.h @@ -24,6 +24,26 @@ public: CAMERA_AIM * GetCurrentAim(); void SetCurrentAim(CAMERA_AIM *pAim); + BYTE GetCameraMode() { + if(m_bytePlayerNumber) + return GameGetPlayerCameraMode(m_bytePlayerNumber); + else + return GameGetLocalPlayerCameraMode(); + }; + + void SetCameraMode(BYTE byteCamMode) { + GameSetPlayerCameraMode(byteCamMode,m_bytePlayerNumber); + }; + + void GetCameraExtendedZoom(float *pfZoom, float *pfRatio) { + *pfZoom = GameGetLocalPlayerCameraExtZoom(); + *pfRatio = GameGetLocalPlayerAspectRatio(); + } + + void SetCameraExtendedZoom(float fZoom, float fRatio) { + GameSetPlayerCameraExtZoom(m_bytePlayerNumber,fZoom,fRatio); + }; + void HideMarker(); BYTE GetCurrentWeapon(); int GetCurrentVehicleID(); @@ -38,16 +58,18 @@ public: BOOL IsInVehicle(); BYTE GetActionTrigger(); void SetActionTrigger(BYTE byteTrigger); - WORD GetAmmo(); + int GetFightingStyle(); + void SetFightingStyle(int iStyle); + float GetTargetRotation(); void SetTargetRotation(float fRotation); void ForceTargetRotation(float fRotation); void GiveWeapon(int iWeaponID, int iAmmo); - void SetArmedWeapon(int iWeaponType, bool bUnk); void ClearAllWeapons(); + void SetArmedWeapon(int iWeaponType, bool bUnk=false); void RemoveWeaponWhenEnteringVehicle(); WEAPON_SLOT_TYPE * GetCurrentWeaponSlot(); WEAPON_SLOT_TYPE * FindWeaponSlot(DWORD dwWeapon); @@ -55,9 +77,17 @@ public: void SetImmunities(BOOL bBullet, BOOL bFire, BOOL bExplosion, BOOL bDamage, BOOL bUnknown); + void PutDirectlyInVehicle(int iVehicleID, int iSeat); + void RemoveFromVehicleAndPutAt(float fX, float fY, float fZ); + BOOL IsAPassenger(); VEHICLE_TYPE * GetGtaVehicle(); + VEHICLE_TYPE * GetGtaContactVehicle(); + ENTITY_TYPE * GetGtaContactEntity(); + + int GetVehicleSeatID(); + void TogglePlayerControllable(int iControllable); float GetDistanceFromVehicle(CVehicle *pVehicle); @@ -71,12 +101,41 @@ public: void SetAnimationSet(PCHAR szAnim); void SetMoney(int iAmount); + void ApplyAnimation(char *szAnimName, char *szAnimFile, float fT, + int opt1, int opt2, int opt3, int opt4, int iUnk); + + BOOL IsPerformingAnimation(char *szAnimName); CPlayerPed(); - //char _gap0[813]; - //char _gap0[741]; - int field_48; + void ProcessVehicleHorn(); + + void StartDancing(int iStyle); + void StopDancing(); + BOOL IsDancing(); + void HandsUp(); + BOOL HasHandsUp(); + void HoldItem(int iObject); + + void ProcessMarkers(BOOL bMarkerStreamingEnabled, float fMarkerStreamRadius, BOOL bVisible); + + void ApplyCommandTask(char *szTaskName, int p1, int p2, int p3, + VECTOR *p4, int p5, float p6, int p7, int p8, int p9); + + void DestroyFollowPedTask(); + void ToggleCellphone(int iOn); + int IsCellphoneEnabled(); + + void StartPissing(); + void StopPissing(); + int IsPissing(); + + BOOL IsJumpTask(); + BOOL IsFightTask(); + BOOL IsTakeFallDamageTask(); + BOOL IsSwimTask(); + + int m_iCellPhoneEnabled; int field_4C[10]; struc_97 field_74[10]; int field_27C[10]; @@ -86,25 +145,25 @@ public: BYTE m_bytePlayerNumber; char _gap2B1[8]; int field_2B9; - char _gap2BD[4]; + DWORD m_dwPissParticlesHandle; int field_2C1; int field_2C5; int field_2C9; DWORD m_dwArrow; - char _gap2D1[1]; - int field_2D2; - char _gap2D6[8]; + char _gap2D1; + int m_iDanceState; + int m_iDanceStyle; + char _gap2DA[4]; int field_2DE; int field_2E2; BOOL m_bGoggleState; char _gap2EA[8]; - int field_2F2; + int m_iPissingState; char field_2F6; char field_2F7; char field_2F8; int field_2F9; char _gap2FD[48]; - }; //----------------------------------------------------------- diff --git a/saco/game/rwstuff.cpp b/saco/game/rwstuff.cpp index 69dc5ce..ff55cd1 100644 --- a/saco/game/rwstuff.cpp +++ b/saco/game/rwstuff.cpp @@ -443,3 +443,73 @@ void RwFrameRotate(RwFrame* frame, int axis, float angle) _asm pop edx } +void RpHAnimHierarchyUpdateMatrices(RpClump *clump) +{ + _asm push clump + _asm mov edx, 0x734A40 ; GetAnimHierarchyFromSkinClump + _asm call edx + _asm pop edx + + _asm push eax + _asm mov edx, 0x7C51D0 ; RpHAnimHierarchyUpdateMatrices + _asm call edx + _asm pop edx +} + +void RpAnimBlendClumpUpdateAnimations(RpClump *pClump, float fStep, int iOnScreen) +{ + _asm push iOnScreen + _asm push fStep + _asm push pClump + _asm mov edx, 0x4D34F0 + _asm call edx + _asm pop edx + _asm pop edx + _asm pop edx +} + +RwStream * RwStreamOpen(int iStreamType, int iAccessType, void *pData) +{ + RwStream *pResult = NULL; + DWORD dwFunc = (iGtaVersion != GTASA_VERSION_USA10) ? 0x7ECF30 : 0x7ECEF0; + + _asm push pData + _asm push iAccessType + _asm push iStreamType + _asm mov eax, dwFunc + _asm call eax + _asm mov pResult, eax + _asm pop eax + _asm pop eax + _asm pop eax + + return pResult; +} + +int RwStreamClose(RwStream *pStream, void *pData) +{ + int bResult = 0; + DWORD dwFunc = (iGtaVersion != GTASA_VERSION_USA10) ? 0x7ECE60 : 0x7ECE20; + + _asm push pData + _asm push pStream + _asm mov eax, dwFunc + _asm call eax + _asm mov bResult, eax + _asm pop eax + _asm pop eax + + return bResult; +} + +/*UINT RwStreamRead(RwStream *pStream, void *pBuffer, UINT uiLength) +{ + return ((int (__cdecl *)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD))(iGtaVersion != 1 ? 0x7ECA10 : 0x7EC9D0))( + pStream, + pBuffer, + uiLength, + iGtaVersion != 1 ? 0x7ECA10 : 0x7EC9D0, + 0); +}*/ + + diff --git a/saco/game/rwstuff.h b/saco/game/rwstuff.h index c7ca1bd..1a18326 100644 --- a/saco/game/rwstuff.h +++ b/saco/game/rwstuff.h @@ -10,6 +10,7 @@ struct RwRGBAReal { float r, g, b, a; }; struct RpAtomic { char _gap0; }; struct RwRGBA { char _gap0; }; struct RpClump { char _gap0; }; +struct RwStream { char _gap0; }; RwRaster* RwRasterCreate(int width, int height, int depth, int flags); RwTexture* RwTextureCreate(RwRaster *raster); @@ -44,3 +45,9 @@ int RpClumpDestroy(RpClump *clump); void RwCameraSetProjection(RwCamera *camera, int projection); void RwFrameTranslate(RwFrame *frame, VECTOR *v, int combine); void RwFrameRotate(RwFrame* frame, int axis, float angle); + +void RpHAnimHierarchyUpdateMatrices(RpClump *clump); +void RpAnimBlendClumpUpdateAnimations(RpClump *pClump, float fStep, int iOnScreen); +RwStream * RwStreamOpen(int iStreamType, int iAccessType, void *pData); +int RwStreamClose(RwStream *pStream, void *pData); + diff --git a/saco/game/scripting.h b/saco/game/scripting.h index f6aac63..a6bb18e 100644 --- a/saco/game/scripting.h +++ b/saco/game/scripting.h @@ -28,72 +28,156 @@ struct SCRIPT_COMMAND // Params void InitScripting(); int ScriptCommand(const SCRIPT_COMMAND* pScriptCommand, ...); // The main scripting function. See notes. +const SCRIPT_COMMAND create_arrow_above_actor = { 0x0187, "iv" }; const SCRIPT_COMMAND request_model = { 0x0247, "i" }; // (CAR_*|BIKE_*|BOAT_*|WEAPON_*|OBJECT_*) const SCRIPT_COMMAND load_requested_models = { 0x038B, "" }; // -/- +const SCRIPT_COMMAND create_car = { 0x00A5, "ifffv" }; // (CAR_*|BIKE_*|BOAT_*), x, y, z, var_car + +const SCRIPT_COMMAND create_actor = { 0x009A, "iifffv" }; // PEDTYPE_*, #MODEL, x, y, z, var_actor const SCRIPT_COMMAND fade = { 0x016A, "ii" }; // (time in ms), FADE_* const SCRIPT_COMMAND set_current_time = { 0x00C0, "ii" }; // Hours, Minutes +const SCRIPT_COMMAND create_player = { 0x0053, "vfffv" }; // 0, x, y, z, PLAYER_CHAR +const SCRIPT_COMMAND create_actor_from_player = { 0x01F5, "vv" }; // PLAYER_CHAR, PLAYER_ACTOR + +const SCRIPT_COMMAND select_interior = { 0x04BB, "i" }; // INTERIOR_* + +const SCRIPT_COMMAND destroy_car = { 0x00A6, "i" }; // var_car +const SCRIPT_COMMAND set_car_z_angle = { 0x0175, "if" }; // var_car, angle + const SCRIPT_COMMAND is_model_available = { 0x0248, "i" }; // #MODEL +const SCRIPT_COMMAND toggle_widescreen = { 0x02A3, "i" }; // widescreen(1/0) const SCRIPT_COMMAND set_camera_behind_player = { 0x0373, "" }; // -/- + +const SCRIPT_COMMAND camera_on_vehicle = { 0x0158, "iii" }; // var_car, ukn, ukn +const SCRIPT_COMMAND camera_on_actor = { 0x0159, "iii" }; // var_actor, ukn, ukn + const SCRIPT_COMMAND point_camera = { 0x0160, "fffi" }; // x, y, z, type const SCRIPT_COMMAND restore_camera_jumpcut = { 0x02EB, "" }; // -/- const SCRIPT_COMMAND set_camera_position = { 0x015F, "ffffff" }; // x, y, z, vx, vy, vz +const SCRIPT_COMMAND tie_marker_to_car = { 0x0161, "iiiv" }; // var_car, ukn, ukn, var_marker + const SCRIPT_COMMAND disable_marker = { 0x0164, "i" }; // var_marker const SCRIPT_COMMAND set_marker_color = { 0x0165, "ii" }; // var_marker, color -const SCRIPT_COMMAND enable_zone_names = { 0x09BA, "i" }; + const SCRIPT_COMMAND create_radar_marker_without_sphere = { 0x04CE, "fffiv" }; // x, y, z, marker_type, var_marker const SCRIPT_COMMAND show_on_radar = { 0x0168, "ii" }; // var_marker, size const SCRIPT_COMMAND create_icon_marker_sphere = { 0x02A7, "fffiv" }; +const SCRIPT_COMMAND is_actor_near_point_3d = { 0x00FE, "iffffffi" };// var_actor, x, y, z, rx, ry, rz, b + +const SCRIPT_COMMAND get_line_of_sight = { 0x06BD, "ffffffiiiii" }; // x1, y1, z1, x2, y2, z2, solid, vehicle, actor, obj, fx + const SCRIPT_COMMAND add_to_player_money = { 0x0109, "ii" }; // PLAYER_CHAR, money const SCRIPT_COMMAND has_car_sunk = { 0x02bf, "i" }; // CarID const SCRIPT_COMMAND is_car_wrecked = { 0x0119, "i" }; // CarID const SCRIPT_COMMAND get_ground_z = { 0x02ce, "fffv" }; // x, y, z, var_ground_z +const SCRIPT_COMMAND create_racing_checkpoint = { 0x06d5, "ifffffffv"}; // type, x, y, z, nx, ny. nz, size, $id (n=next checkpoint) +/* 0 = Street Checkpoint with arrow to the next checkpoint + 1 and 2 = Street Checkpoint + 3 and 4 = Flight Checkpoint (circle) */ const SCRIPT_COMMAND destroy_racing_checkpoint = { 0x06d6, "i" }; +const SCRIPT_COMMAND toggle_player_controllable = { 0x01B4, "ii" }; + const SCRIPT_COMMAND set_actor_armed_weapon = { 0x01b9, "ii" }; const SCRIPT_COMMAND get_actor_armed_weapon = { 0x0470, "iv" }; -const SCRIPT_COMMAND set_actor_immunities = { 0x02ab, "iiiiii" }; +const SCRIPT_COMMAND put_actor_in_car = { 0x036A, "ii" }; +const SCRIPT_COMMAND set_actor_immunities = { 0x02ab, "iiiiii" }; +const SCRIPT_COMMAND set_car_immunities = { 0x02ac, "iiiiii" }; const SCRIPT_COMMAND set_actor_can_be_decapitated = { 0x0446, "ii" }; +const SCRIPT_COMMAND create_object = { 0x0107, "ifffv" }; + +const SCRIPT_COMMAND set_object_rotation = { 0x0453, "ifff" }; const SCRIPT_COMMAND play_sound = { 0x018c, "fffi" }; +const SCRIPT_COMMAND remove_actor_from_car_and_put_at = { 0x0362, "ifff" }; +const SCRIPT_COMMAND send_actor_to_car_driverseat = { 0x05CB, "iii" }; +const SCRIPT_COMMAND send_actor_to_car_passenger = { 0x05CA, "iiii" }; +const SCRIPT_COMMAND make_actor_leave_car = { 0x05CD, "ii" }; + +const SCRIPT_COMMAND get_car_z_angle = { 0x0174, "iv" }; + +const SCRIPT_COMMAND create_train = { 0x06D8, "ifffiv" }; +const SCRIPT_COMMAND destroy_train = { 0x07bd, "i" }; + const SCRIPT_COMMAND enable_train_traffic = { 0x06d7, "i" }; const SCRIPT_COMMAND lock_car = { 0x0519, "ii" }; const SCRIPT_COMMAND put_train_at = { 0x07c7, "ifff" }; +const SCRIPT_COMMAND release_model = { 0x0249, "i" }; const SCRIPT_COMMAND get_active_interior = { 0x077e, "v" }; +const SCRIPT_COMMAND get_actor_z_angle = { 0x0172, "iv" }; const SCRIPT_COMMAND set_actor_z_angle = { 0x0173, "if" }; +const SCRIPT_COMMAND enter_passenger_driveby = { 0x0713, "iiiffffiii" }; +const SCRIPT_COMMAND lock_actor = { 0x04d7, "ii" }; const SCRIPT_COMMAND refresh_streaming_at = { 0x04E4, "ff" }; +const SCRIPT_COMMAND put_actor_in_car2 = { 0x0430, "iii" }; + +const SCRIPT_COMMAND kill_actor = { 0x0321, "i" }; const SCRIPT_COMMAND set_actor_animation_set = { 0x0245, "is" }; const SCRIPT_COMMAND request_animation = { 0x04ED, "s" }; const SCRIPT_COMMAND is_animation_loaded = { 0x04EE, "s" }; const SCRIPT_COMMAND release_animation = { 0x04EF, "s" }; - +const SCRIPT_COMMAND apply_animation = { 0x0812, "issfiiiii" }; // actor,animation,library,floatunk,bool,bool,bool,bool,int +const SCRIPT_COMMAND is_actor_performing_anim = { 0x0611, "is" }; const SCRIPT_COMMAND set_actor_weapon_droppable = { 0x087e, "ii" }; const SCRIPT_COMMAND set_actor_money = { 0x03fe, "ii" }; const SCRIPT_COMMAND text_clear_all = { 0x00be, "" }; +const SCRIPT_COMMAND set_car_hydraulics = { 0x07FF, "ii" }; //iCar, i (0=off/1=on) + +const SCRIPT_COMMAND attach_object_to_actor = { 0x069b, "iiffffff" }; + +const SCRIPT_COMMAND set_object_scaling = { 0x08d2, "if" }; + +const SCRIPT_COMMAND create_pickup = { 0x0213, "iifffv" }; const SCRIPT_COMMAND create_pickup_with_ammo = { 0x032b, "iiifffv" }; +const SCRIPT_COMMAND is_pickup_picked_up = { 0x0214, "i" }; const SCRIPT_COMMAND destroy_pickup = { 0x0215, "i" }; +const SCRIPT_COMMAND change_car_skin = { 0x06ED, "ii" }; +const SCRIPT_COMMAND add_car_component = { 0x06E7, "iiv" }; // CAR, COMPONENT, COMPONENT VAR NAME +const SCRIPT_COMMAND is_component_available = { 0x06EA, "i" }; +const SCRIPT_COMMAND request_car_component = { 0x06E9, "i" }; +const SCRIPT_COMMAND remove_component = { 0x06E8, "ii" }; + +const SCRIPT_COMMAND show_on_radar2 = { 0x018b, "ii" }; + +const SCRIPT_COMMAND find_ground_z = { 0x02CE, "fffv" }; + +const SCRIPT_COMMAND toggle_actor_cellphone = { 0x0729, "ii" }; + +const SCRIPT_COMMAND actor_task_handsup = { 0x5c4, "ii" }; + +const SCRIPT_COMMAND toggle_car_tires_vulnerable = { 0x053f, "ii" }; +const SCRIPT_COMMAND set_fighting_style = { 0x07fe, "iii" }; + const SCRIPT_COMMAND link_vehicle_to_interior = { 0x0840, "ii" }; +const SCRIPT_COMMAND destroy_object = { 0x0108, "i" }; const SCRIPT_COMMAND create_radar_marker_icon = { 0x0570, "fffiv" }; +const SCRIPT_COMMAND put_trailer_on_cab = { 0x893, "ii" }; +const SCRIPT_COMMAND detach_trailer_from_cab = { 0x7AC, "ii" }; + +const SCRIPT_COMMAND create_explosion_with_radius = { 0x0948, "fffii" }; + +const SCRIPT_COMMAND enable_zone_names = { 0x09BA, "i" }; const SCRIPT_COMMAND remove_panel = { 0x08DA, "i" }; const SCRIPT_COMMAND create_panel = { 0x08D4, "sfffiiiiv" }; @@ -103,23 +187,34 @@ const SCRIPT_COMMAND set_panel_row_enable = { 0x08D9, "iii" }; const SCRIPT_COMMAND get_panel_active_row = { 0x08D7, "iv" }; +const SCRIPT_COMMAND destroy_particle = { 0x650, "i" }; +const SCRIPT_COMMAND attach_particle_to_actor2 = { 0x066a, "siffffffiv" }; +const SCRIPT_COMMAND make_particle_visible = { 0x64c, "i" }; -const SCRIPT_COMMAND restore_camera_to_user_defined = { 0x925, "" }; -const SCRIPT_COMMAND set_camera_position_to = { 0x936, "ffffffii" }; -const SCRIPT_COMMAND point_camera_transverse_to = { 0x920, "ffffffii" }; -const SCRIPT_COMMAND lock_camera_target_point = { 0x92F, "i" }; -const SCRIPT_COMMAND lock_camera_position = { 0x930, "i" }; +const SCRIPT_COMMAND set_actor_dicision = { 0x60B, "ii" }; -const SCRIPT_COMMAND create_marker_at = { 0x2A8, "fffiv" }; +const SCRIPT_COMMAND set_player_drunk_visuals = { 0x052c, "ii" }; // player, severity (0-255) +const SCRIPT_COMMAND handling_responsiveness = { 0x03fd, "ii" }; // player, severity (0-255) +// --- -const SCRIPT_COMMAND load_wav = { 0x3CF, "ii" }; -const SCRIPT_COMMAND is_wav_loaded = { 0x3D0, "i" }; -const SCRIPT_COMMAND play_wav = { 0x3D1, "i" }; -const SCRIPT_COMMAND unload_wav = { 0x40D, "i" }; -const SCRIPT_COMMAND set_wav_at_location = { 0x3D7, "ifff" }; +const SCRIPT_COMMAND restore_camera_to_user_defined = { 0x0925, "" }; +const SCRIPT_COMMAND set_camera_position_to = { 0x0936, "ffffffii" }; +const SCRIPT_COMMAND point_camera_transverse_to = { 0x0920, "ffffffii" }; +const SCRIPT_COMMAND lock_camera_target_point = { 0x092F, "i" }; +const SCRIPT_COMMAND lock_camera_position = { 0x0930, "i" }; +const SCRIPT_COMMAND load_wav = { 0x03CF, "ii" }; +const SCRIPT_COMMAND is_wav_loaded = { 0x03D0, "i" }; +const SCRIPT_COMMAND play_wav = { 0x03D1, "i" }; +const SCRIPT_COMMAND unload_wav = { 0x040D, "i" }; +const SCRIPT_COMMAND set_wav_at_location = { 0x03D7, "ifff" }; +const SCRIPT_COMMAND create_marker_at = { 0x02A8, "fffiv" }; +const SCRIPT_COMMAND attach_object_to_car = { 0x0681, "iiffffff" }; +const SCRIPT_COMMAND is_object_attached = { 0x0685, "i" }; +const SCRIPT_COMMAND attach_object_to_object = { 0x069A, "iiffffff" }; +const SCRIPT_COMMAND task_pick_up_object = { 0x070A, "iifffiissi" }; diff --git a/saco/game/task.cpp b/saco/game/task.cpp index c0abbfa..4690a1f 100644 --- a/saco/game/task.cpp +++ b/saco/game/task.cpp @@ -396,4 +396,3 @@ CTaskKillPedOnFootArmed::CTaskKillPedOnFootArmed( int unk, int unk2, int unk3, i } //========================================================== - diff --git a/saco/game/textdraw.cpp b/saco/game/textdraw.cpp new file mode 100644 index 0000000..6337672 --- /dev/null +++ b/saco/game/textdraw.cpp @@ -0,0 +1,205 @@ + +#include "../main.h" +#include "font.h" +#include "util.h" +#include "textures.h" +extern CGame *pGame; + +DWORD unnamed_1026B568[200]; +BOOL unnamed_1026B888[200]; + +void CallRwRenderStateSet(int state, int option); + +BOOL unnamed_100B2AF0() +{ + memset(unnamed_1026B888, 0, sizeof(unnamed_1026B888)); + memset(unnamed_1026B568, 0, sizeof(unnamed_1026B568)); + return TRUE; +} + +int unnamed_100B2B20() +{ + int x=0; + while(x!=200) { + if(unnamed_1026B888[x] == FALSE) { + unnamed_1026B888[x] = TRUE; + return x; + } + x++; + } + return (-1); +} + +void unnamed_100B2B50(int iSlot) +{ + if(iSlot < 0 || iSlot >= 200) return; + + unnamed_1026B888[iSlot] = FALSE; + + if(unnamed_1026B568[iSlot]) + DestroyTexture(unnamed_1026B568[iSlot]); + unnamed_1026B568[iSlot] = 0; +} + +BOOL unnamed_100B2B90(char *a1, char *a2, bool a3) +{ + char v5[64]; + if(a3) + strcpy(v5, "SAMP\\"); + else + strcpy(v5, "models\\txd"); + + if(FindTextureSlot(a1) != -1) + return TRUE; + + int v3 = AddTextureSlot(a1); + + char v9[64]; + sprintf(v9, "%s\\%s.txd", v5, a2); + + if(IsFileOrDirectoryExists(v9)) + { + LoadTexture(v3, v9); + AddTextureRef(v3); + return TRUE; + } + return FALSE; +} + +DWORD unnamed_100B2C60(char *a1, char *a2) +{ + int v1 = FindTextureSlot(a1); + + if(v1 == -1) return 0; + + PushCurrentTexture(); + SetCurrentTexture(v1); + DWORD v4 = ReloadTexture(a2); + PopCurrentTexture(); + + return v4; +} + +void unnamed_100B2CA0(DWORD a1, int a2, int a3) +{ + if(!a1) return; + + CallRwRenderStateSet(9, 2); + + _asm push a3 + _asm push a2 + _asm mov ecx, a1 + _asm mov edx, 0x728350 + _asm call edx +} + +CTextDraw::CTextDraw(TEXT_DRAW_TRANSMIT *TextDrawTransmit, PCHAR szText) +{ + memset(&m_TextDrawData,0,sizeof(TEXT_DRAW_DATA)); + + m_TextDrawData.field_0 = TextDrawTransmit->field_1; + m_TextDrawData.field_4 = TextDrawTransmit->field_5; + m_TextDrawData.field_8 = TextDrawTransmit->field_9; + m_TextDrawData.field_C = 0; + m_TextDrawData.field_D = ((unsigned __int8)TextDrawTransmit->field_0 >> 3) & 1; + m_TextDrawData.field_E = TextDrawTransmit->field_0 & 1; + m_TextDrawData.field_F = TextDrawTransmit->field_D; + m_TextDrawData.field_13 = TextDrawTransmit->field_11; + m_TextDrawData.field_17 = TextDrawTransmit->field_15; + m_TextDrawData.field_1B = ((unsigned __int8)TextDrawTransmit->field_0 >> 4) & 1; + m_TextDrawData.field_1C = TextDrawTransmit->field_1B; + m_TextDrawData.field_20 = TextDrawTransmit->field_19; + m_TextDrawData.field_21 = TextDrawTransmit->field_1A; + m_TextDrawData.field_22 = ((unsigned __int8)TextDrawTransmit->field_0 >> 1) & 1; + m_TextDrawData.field_23 = ((unsigned __int8)TextDrawTransmit->field_0 >> 2) & 1; + m_TextDrawData.field_24 = TextDrawTransmit->field_1F; + m_TextDrawData.field_28 = TextDrawTransmit->field_21; + m_TextDrawData.field_2C = TextDrawTransmit->field_25; + m_TextDrawData.field_38 = -1; + m_TextDrawData.field_3C = -1; + m_TextDrawData.field_44 = TextDrawTransmit->field_20; + m_TextDrawData.field_45 = TextDrawTransmit->field_29; + m_TextDrawData.field_47 = TextDrawTransmit->field_2B; + m_TextDrawData.field_4B = TextDrawTransmit->field_2F; + m_TextDrawData.field_4F = TextDrawTransmit->field_33; + m_TextDrawData.field_53 = TextDrawTransmit->field_37; + m_TextDrawData.field_57 = TextDrawTransmit->field_3B; + m_TextDrawData.field_59 = TextDrawTransmit->field_3D; + field_9C0 = 0; + m_TextDrawData.field_40 = -1; + + SetText(szText); + + if(m_TextDrawData.field_24 == 4) + { + m_TextDrawData.field_40 = unnamed_100B2B20(); + FUNC_100B2CD0(); + } + + field_9BF = 0; + field_9C1 = 0; + field_9C9 = 0; + field_9C5 = 0; + field_9CD = 0; + field_9D1 = 0; + field_9D2 = 0; +} + +CTextDraw::~CTextDraw() +{ + unnamed_100B2B50(m_TextDrawData.field_40); +} + +void CTextDraw::SetText(char* szText) +{ + // TODO: CTextDraw::SetText .text:100B2F60 +} + +void CTextDraw::FUNC_100B2CD0() +{ + // TODO: CTextDraw::FUNC_100B2CD0 .text:100B2CD0 +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/saco/game/textdraw.h b/saco/game/textdraw.h new file mode 100644 index 0000000..cc379ff --- /dev/null +++ b/saco/game/textdraw.h @@ -0,0 +1,98 @@ + +#pragma once + +#define MAX_TEXT_DRAW_LINE 800 + +//----------------------------------------------------------- + +typedef struct _TEXT_DRAW_DATA +{ + int field_0; + int field_4; + int field_8; + char field_C; + char field_D; + char field_E; + int field_F; + int field_13; + int field_17; + char field_1B; + int field_1C; + char field_20; + char field_21; + char field_22; + char field_23; + int field_24; + int field_28; + int field_2C; + + char _gap30[8]; + + int field_38; + int field_3C; + int field_40; + char field_44; + short field_45; + int field_47; + int field_4B; + int field_4F; + int field_53; + short field_57; + short field_59; +} TEXT_DRAW_DATA; + +//----------------------------------------------------------- + +typedef struct _TEXT_DRAW_TRANSMIT +{ + char field_0; + int field_1; + int field_5; + int field_9; + int field_D; + int field_11; + int field_15; + char field_19; + char field_1A; + int field_1B; + char field_1F; + char field_20; + int field_21; + int field_25; + short field_29; + int field_2B; + int field_2F; + int field_33; + int field_37; + short field_3B; + short field_3D; +} TEXT_DRAW_TRANSMIT; + +//---------------------------------------------------- + +class CTextDraw +{ +private: + CHAR m_szText[MAX_TEXT_DRAW_LINE]; + + TEXT_DRAW_DATA m_TextDrawData; + + char field_9BF; + char field_9C0; + int field_9C1; + int field_9C5; + int field_9C9; + int field_9CD; + char field_9D1; + int field_9D2; + +public: + CTextDraw(TEXT_DRAW_TRANSMIT *TextDrawTransmit, PCHAR szText); + ~CTextDraw(); + + void SetText(char* szText); + + void FUNC_100B2CD0(); +}; + +//---------------------------------------------------- diff --git a/saco/game/unnamed_1.cpp b/saco/game/unnamed_1.cpp deleted file mode 100644 index 733f40e..0000000 --- a/saco/game/unnamed_1.cpp +++ /dev/null @@ -1,40 +0,0 @@ - -#include -#include - -int unnamed_1026B568[200]; -BOOL unnamed_1026B888[200]; - -BOOL unnamed_100B2AF0() -{ - memset(unnamed_1026B888, 0, sizeof(unnamed_1026B888)); - memset(unnamed_1026B568, 0, sizeof(unnamed_1026B568)); - - return TRUE; -} - -int unnamed_100B2B20() -{ - int x=0; - while(x!=200) - { - if(!unnamed_1026B888[x]) - { - unnamed_1026B888[x] = TRUE; - return x; - } - x++; - } - return (-1); -} - - - - - - - - - - - diff --git a/saco/game/util.cpp b/saco/game/util.cpp index cb4fb97..65192b2 100644 --- a/saco/game/util.cpp +++ b/saco/game/util.cpp @@ -2,8 +2,11 @@ #include #include #include "../main.h" +#include "modelinfo.h" #include +DWORD dwCameraScene = 0xC1703C; + DWORD dwPlayerPedPtrs[PLAYER_PED_SLOTS]; struct struc_96 @@ -1191,6 +1194,64 @@ OBJECT_TYPE * GamePool_GetObject() //----------------------------------------------------------- +int Game_GetValidObjectCount() +{ + int dwObjectPool = 0xB7449C; + int iPoolSize = *(int *)(*(int*)dwObjectPool + 8); + int iCount = 0; + + for(int i = 0; i < iPoolSize; i++) + { + if(*(BYTE *)(*(int*)dwObjectPool + i + 4) > 0) + iCount++; + } + + return iCount; +} + +//----------------------------------------------------------- + +int Game_GetValidTxdCount() +{ + DWORD *dwTxdPool = (DWORD *)0xC8800C; + int iPoolSize = *(int *)(*dwTxdPool + 8); + int iCount = 0; + + for(int i = 0; i < iPoolSize; i++) + { + if(*(BYTE *)(*dwTxdPool + i + 4) > 0) + iCount++; + } + + return iCount; +} + +//----------------------------------------------------------- + +bool Game_IsObjectModelValid(int iModelID) +{ + OBJECT_TYPE *pObjectPtrs = GamePool_GetObject(); + + //_asm mov eax, 0xB7449C + //_asm mov edx, [eax] +// _asm mov eax, [edx] +// _asm mov pObjectPtrs, eax + + for(int i = 0; i != 3000; i++) + { + if(pObjectPtrs && + pObjectPtrs[i].vtable != NULL && + pObjectPtrs[i].vtable != 0x863C40 && + pObjectPtrs[i].nModelIndex == iModelID) + { + return true; + } + } + return false; +} + +//----------------------------------------------------------- + void ReplaceBuildingModel(ENTITY_TYPE *pEntity, int iModelID) { _asm push iModelID @@ -1199,6 +1260,20 @@ void ReplaceBuildingModel(ENTITY_TYPE *pEntity, int iModelID) _asm call edx } +//----------------------------------------------------------- + + + + + +// TODO: sub_100B3DB0 +// TODO: sub_100B3DD0 + + + + + + //----------------------------------------------------------- int GetInvalidModelInfoCount() @@ -1354,6 +1429,83 @@ int __stdcall GameGetWeaponModelIDFromWeaponID(int iWeaponID) return -1; } +//----------------------------------------------------------- + +DWORD * GetNextTaskFromTask(DWORD *task) +{ + DWORD *ret_task=NULL; + + if(!task || *task < 0x800000 || *task > 0x900000) return NULL; + + _asm pushad + _asm mov edx, task + _asm mov ebx, [edx] + _asm mov edx, [ebx+8] + _asm mov ecx, task + _asm call edx + _asm mov ret_task, eax + _asm popad + + return ret_task; +} + +//----------------------------------------------------------- + +int GetTaskTypeFromTask(DWORD *task) +{ + int i = 0; + + if(!task || *task < 0x800000 || *task > 0x900000) return 0; + + _asm pushad + _asm mov edx, task + _asm mov ebx, [edx] + _asm mov edx, [ebx+10h] + _asm mov ecx, task + _asm call edx + _asm mov i, eax + _asm popad + + return i; +} + +//----------------------------------------------------------- + +const char* GetTaskNameFromTask(DWORD *task) +{ + return "None"; +} + +//----------------------------------------------------------- + +int Game_PedStatPrim(int model_id) +{ + /*if(model_id >= 0 && model_id <= 30000) { + MODEL_INFO_TYPE *pModelInfo = GetModelInfo(model_id); + if(!pModelInfo || pModelInfo->vtable != 0x85BDC0) { + return FALSE; + } + } + int *pStat = (int *)((*GetModelInfo(model_id)) + 40); + return *pStat;*/ + return 0; +} + +//---------------------------------------------------- + + + + + +// TODO: sub_100B4100 +// TODO: sub_100B4140 +// TODO: sub_100B4180 + + + + + + //----------------------------------------------------------- BOOL __stdcall GameIsEntityOnScreen(DWORD * pdwEnt) @@ -1368,6 +1520,16 @@ BOOL __stdcall GameIsEntityOnScreen(DWORD * pdwEnt) return bResult != FALSE; } +//----------------------------------------------------------- + + + + + + + + + //----------------------------------------------------------- void __stdcall SetRadarColor(int nIndex,DWORD dwColor) @@ -1451,6 +1613,10 @@ DWORD __stdcall CRC32FromUpcaseString(char *szString) } +DWORD *__stdcall GetModelRwObject(int iModelID) +{ + return GetModelInfo(iModelID)->pdwRenderWare; +} @@ -1465,6 +1631,22 @@ bool unnamed_100B4B50(VECTOR *vecPos) + + + + + + + + + + + + + + + + //---------------------------------------------------- @@ -1504,6 +1686,17 @@ BOOL __stdcall IsATrainPart(ENTITY_TYPE *pEntity) return FALSE; } +//---------------------------------------------------- + + + + + + + + + + //----------------------------------------------------------- float FloatDifference(float f1, float f2) @@ -1607,6 +1800,16 @@ float GetNormalisation(VECTOR *vec) return ((vec->X * vec->X) + (vec->Y * vec->Y) + (vec->Z * vec->Z)); } +//---------------------------------------------------- + + + + + + + + + //---------------------------------------------------- float DegToRad(float fDegrees) @@ -1633,6 +1836,18 @@ float InvDegToRad(float fDegrees) //---------------------------------------------------- +float InvSqrt(float x) +{ + float xhalf = 0.5f * x; + int i = *(int*)&x; + i = 0x5f3759d5 - (i >> 1); + x = *(float*)&i; + x = x*(1.5f - xhalf*x*x); + return x; +} + +//---------------------------------------------------- + bool IsNumeric(char * szString) { while(*szString) { @@ -1821,6 +2036,53 @@ void CreateCameraRaster() //---------------------------------------------------- +DWORD GLOBAL_1026DFB8; +DWORD GLOBAL_1026DFBC; + +void FUNC_100B5D20() +{ + DWORD dwCurDeviceCamera; + + _asm pushad + + CreateCameraRaster(); + + _asm mov eax, dwCameraScene + _asm mov eax, [eax] + _asm mov dwCurDeviceCamera, eax + _asm mov ds:[0xC9BCC0], eax + + _asm mov ebx, dwCurDeviceCamera + _asm mov edx, [ebx+0x60] + _asm mov GLOBAL_1026DFB8, edx + _asm mov edx, [ebx+0x64] + _asm mov GLOBAL_1026DFBC, edx + + _asm mov edx, CamFrameBuffer2 + _asm mov [ebx+0x60], edx + _asm mov edx, CamZBuffer2 + _asm mov [ebx+0x64], edx + + _asm mov edx, 0x734650 + _asm call edx + + _asm mov edx, 0x53DF40 + _asm call edx + + _asm mov edx, 0x732F30 + _asm call edx + + _asm mov ebx, dwCurDeviceCamera + _asm mov edx, GLOBAL_1026DFB8 + _asm mov [ebx+0x60], edx + _asm mov edx, GLOBAL_1026DFBC + _asm mov [ebx+0x64], edx + + _asm popad +} + +//---------------------------------------------------- + void ResetLocalPad(int unk1, int unk2) { // CPad__GetPadAt(int index) @@ -1911,7 +2173,7 @@ void RemoveColorEmbedsFromString(char *szString) *szString = 0; } -DWORD unnamed_100B6100(char *szString, int nMaxLen) +DWORD FUNC_100B6100(char *szString, int nMaxLen) { char tmp_buf[2049]; memset(tmp_buf, 0, sizeof(tmp_buf)); @@ -1963,5 +2225,11 @@ UINT GetVehicleSubtypeFromVehiclePtr(VEHICLE_TYPE *pVehicle) return 0; } +unsigned short __stdcall GetModelReferenceCount(int nModelIndex) +{ + // TODO: GetModelReferenceCount .text:100B4700 + + return 0; +} diff --git a/saco/game/util.h b/saco/game/util.h index 7c6b93f..bf60471 100644 --- a/saco/game/util.h +++ b/saco/game/util.h @@ -6,11 +6,8 @@ void ProcessLineOfSight(VECTOR *vecOrigin, VECTOR *vecLine, VECTOR *colPoint, int bCheckObjects, int bCheckDummies, int bSeeThroughStuff, int bIgnoreSomeObjectsForCamera, int bUnk1); -float GetNormalisation(VECTOR *vec); - float FloatDifference(float f1, float f2); float FloatOffset(float f1, float f2); -float NormalizeAngle(float fAngle); void __stdcall SetRadarColor(int nIndex,DWORD dwColor); @@ -33,25 +30,21 @@ void __stdcall InitPlayerPedPtrRecords(); void __stdcall SetPlayerPedPtrRecord(BYTE bytePlayer, DWORD dwPedPtr); DWORD __stdcall GetPlayerPedPtrRecord(BYTE bytePlayer); BYTE __stdcall FindPlayerNumFromPedPtr(DWORD dwPedPtr); -float __stdcall SquaredDistanceBetweenHorizontalPoints(float x1, float y1, float x2, float y2); -float DistanceBetweenHorizontalPoints(float x1, float y1, float x2, float y2); -float DistanceBetweenPoints(float x1, float y1, float z1, float x2, float y2, float z2); -float __stdcall SquaredDistanceBetweenPoints(float x1, float y1, float z1, float x2, float y2, float z2); -float __stdcall SquaredDistanceBetweenPoints(VECTOR *vec1, VECTOR *vec2); -void __stdcall _VectorNormalise(VECTOR *vec); DWORD __stdcall CRC32FromUpcaseString(char *szString); void GameResetRadarColors(); float DegToRad(float fDegrees); -float InvDegToRad(float fDegrees); +float DegToRadInv(float fDegrees); + +bool IsNumeric(char *szString); void SaveCameraRaster(char *filename); BOOL IsFileOrDirectoryExists(char * szPath); -DWORD unnamed_100B6100(char *szString, int nMaxLen); +DWORD FUNC_100B6100(char *szString, int nMaxLen); bool unnamed_100B4B50(VECTOR *vecPos); @@ -73,3 +66,10 @@ void RemoveColorEmbedsFromString(char *szString); UINT GetVehicleSubtypeFromVehiclePtr(VEHICLE_TYPE *pVehicle); +unsigned short __stdcall GetModelReferenceCount(int nModelIndex); + +DWORD * GetNextTaskFromTask(DWORD *task); +int GetTaskTypeFromTask(DWORD *task); + +DWORD *__stdcall GetModelRwObject(int iModelID); + diff --git a/saco/game/vehicle.cpp b/saco/game/vehicle.cpp index 8b10a1b..22ba7ac 100644 --- a/saco/game/vehicle.cpp +++ b/saco/game/vehicle.cpp @@ -2,6 +2,12 @@ #include "../main.h" #include "util.h" +extern CGame *pGame; +extern CNetGame *pNetGame; +extern WORD wVehicleComponentDebug; + +BOOL bDetachingVehicleTrailer; + //----------------------------------------------------------- // CONSTRUCTOR @@ -9,7 +15,78 @@ CVehicle::CVehicle(int iType, float fPosX, float fPosY, float fPosZ, float fRotation, BOOL bKeepModelLoaded, int a8) { - // TODO: CVehicle::CVehicle .text:100B88F0 + // TODO: CVehicle::CVehicle +} + +//----------------------------------------------------------- +// DESTRUCTOR + +CVehicle::~CVehicle() +{ + m_pVehicle = GamePool_Vehicle_GetAt(m_dwGTAId); + + if(m_pVehicle) { + if(m_dwMarkerID) { + ScriptCommand(&disable_marker, m_dwMarkerID); + m_dwMarkerID = 0; + } + + RemoveEveryoneFromVehicle(); + + if(m_pTrailer) { + DetachTrailer(); + m_pTrailer = NULL; + } + + FUNC_100B81F0(); + + if( m_pVehicle->entity.nModelIndex == TRAIN_PASSENGER_LOCO || + m_pVehicle->entity.nModelIndex == TRAIN_FREIGHT_LOCO ) + { + ScriptCommand(&destroy_train,m_dwGTAId); + } else { + // TODO: CVehicle::~CVehicle() + + //int nModelIndex = m_pVehicle->entity.nModelIndex; + ScriptCommand(&destroy_car,m_dwGTAId); + //pChatWindow->AddDebugMessage("VehicleModelRefs: %d",GetModelReferenceCount(nModelIndex)); + //if(!GetModelReferenceCount(nModelIndex) && !m_bKeepModelLoaded) { + // // No references and we've not been instructed to keep this + // // model loaded, so it should be safe to remove it. + // pGame->RemoveModel(nModelIndex); + //} + } + } +} + +//----------------------------------------------------------- +// Add override + +void CVehicle::Add() +{ + if (!IsAdded()) { + // Call underlying Add + CEntity::Add(); + + // Process stuff for trailers + CVehicle *pTrailer = this->GetTrailer(); + if(pTrailer) pTrailer->Add(); + } +} + +//----------------------------------------------------------- +// Remove override + +void CVehicle::Remove() +{ + if (IsAdded()) { + // Process stuff for trailers + CVehicle *pTrailer = this->GetTrailer(); + if(pTrailer) pTrailer->Remove(); + + // Call underlying Remove + CEntity::Remove(); + } } //----------------------------------------------------------- @@ -66,6 +143,25 @@ BOOL CVehicle::IsOccupied() //----------------------------------------------------------- +void CVehicle::SetInvulnerable(BOOL bInv) +{ + if(!m_pVehicle) return; + if(!GamePool_Vehicle_GetAt(m_dwGTAId)) return; + if(m_pVehicle->entity.vtable == 0x863C40) return; + + if(bInv) { + ScriptCommand(&set_car_immunities,m_dwGTAId,1,1,1,1,1); + ScriptCommand(&toggle_car_tires_vulnerable,m_dwGTAId,0); + m_bIsInvulnerable = TRUE; + } else { + ScriptCommand(&set_car_immunities,m_dwGTAId,0,0,0,0,0); + ScriptCommand(&toggle_car_tires_vulnerable,m_dwGTAId,1); + + m_bIsInvulnerable = FALSE; + } +} +//----------------------------------------------------------- + void CVehicle::SetLockedState(int iLocked) { if(!m_pVehicle) return; @@ -179,6 +275,19 @@ BOOL CVehicle::IsDriverLocalPlayer() //----------------------------------------------------------- +BOOL CVehicle::IsLocalPlayerInThisVehicle() +{ + if(m_pVehicle) { + PED_TYPE *pPed = GamePool_FindPlayerPed(); + if(pPed && IN_VEHICLE(pPed) && (DWORD)m_pVehicle == pPed->pVehicle) { + return TRUE; + } + } + return FALSE; +} + +//----------------------------------------------------------- + BOOL CVehicle::IsATrainPart() { int nModel; @@ -249,6 +358,8 @@ void CVehicle::SetAlarmState(WORD wState) void CVehicle::SetLandingGearState(eLandingGearState state) { + //if(!m_pVehicle) return; + //if(GetVehicleSubtypeFromVehiclePtr(m_pVehicle) != VEHICLE_SUBTYPE_PLANE) return; if(GetVehicleSubtype() != VEHICLE_SUBTYPE_PLANE) return; DWORD dwVehiclePtr = (DWORD)m_pVehicle; @@ -313,5 +424,681 @@ DWORD CVehicle::GetHydraThrusters() //----------------------------------------------------------- +void CVehicle::ProcessMarkers() +{ + if(!m_pVehicle) return; + + if(m_byteObjectiveVehicle) { + // SHOW ALWAYS + if(!m_bSpecialMarkerEnabled) { + if(m_dwMarkerID) { + ScriptCommand(&disable_marker, m_dwMarkerID); + m_dwMarkerID = 0; + } + ScriptCommand(&tie_marker_to_car, m_dwGTAId, 1, 3, &m_dwMarkerID); + ScriptCommand(&set_marker_color,m_dwMarkerID,1006); + ScriptCommand(&show_on_radar,m_dwMarkerID,3); + m_bSpecialMarkerEnabled = TRUE; + } + return; + } + + // Disable the special marker if it has been deactivated + if(!m_byteObjectiveVehicle && m_bSpecialMarkerEnabled) { + if(m_dwMarkerID) { + ScriptCommand(&disable_marker, m_dwMarkerID); + m_bSpecialMarkerEnabled = FALSE; + m_dwMarkerID = 0; + } + } + + // Add or remove car scanning markers. + if(GetDistanceFromLocalPlayerPed() < CSCANNER_DISTANCE && !IsOccupied()) { + // SHOW IT + if(!m_dwMarkerID) { + ScriptCommand(&tie_marker_to_car, m_dwGTAId, 1, 2, &m_dwMarkerID); + ScriptCommand(&set_marker_color,m_dwMarkerID,1004); + } + } + else if(IsOccupied() || GetDistanceFromLocalPlayerPed() >= CSCANNER_DISTANCE) { + // REMOVE IT + if(m_dwMarkerID) { + ScriptCommand(&disable_marker, m_dwMarkerID); + m_dwMarkerID = 0; + } + } +} + //----------------------------------------------------------- +void CVehicle::SetDoorState(int iState) +{ + if(iState) { + m_pVehicle->dwDoorsLocked = 2; + m_bDoorsLocked = TRUE; + } else { + m_pVehicle->dwDoorsLocked = 0; + m_bDoorsLocked = FALSE; + } +} + +//----------------------------------------------------------- + +BOOL CVehicle::UpdateLastDrivenTime() +{ + if(m_pVehicle) { + if(m_pVehicle->pDriver) { + m_bHasBeenDriven = TRUE; + m_dwTimeSinceLastDriven = GetTickCount(); + return TRUE; + } + } + return FALSE; + // Tell the system this vehicle has been used so it can reset the timer to not be based on remaining delay +} + +//----------------------------------------------------------- + +void CVehicle::SetTankRot(float X, float Y) +{ + m_pVehicle->fTankRotX = X; + m_pVehicle->fTankRotY = Y; +} + +//----------------------------------------------------------- + +float CVehicle::GetTankRotX() +{ + return m_pVehicle->fTankRotX; +} + +//----------------------------------------------------------- + +float CVehicle::GetTankRotY() +{ + return m_pVehicle->fTankRotY; +} + +//----------------------------------------------------------- + +float CVehicle::GetTrainSpeed() +{ + if(!m_pVehicle) return 0.0f; + + float fResult = m_pVehicle->fTrainSpeed; + return fResult; +} + +//----------------------------------------------------------- + +void CVehicle::SetTrainSpeed(float fSpeed) +{ + if(fSpeed > 100.0f || fSpeed < -100.0f) return; + if(!m_pVehicle) return; + + m_pVehicle->fTrainSpeed = fSpeed; +} + +//----------------------------------------------------------- + +void CVehicle::SetWheelPopped(BYTE byteFlags) +{ + if(GetVehicleSubtype() == VEHICLE_SUBTYPE_CAR) + { + if(byteFlags & 1) + m_pVehicle->bCarWheelPopped[3] = 1; + else + m_pVehicle->bCarWheelPopped[3] = 0; + + byteFlags >>= 1; + + if(byteFlags & 1) + m_pVehicle->bCarWheelPopped[2] = 1; + else + m_pVehicle->bCarWheelPopped[2] = 0; + + byteFlags >>= 1; + + if(byteFlags & 1) + m_pVehicle->bCarWheelPopped[1] = 1; + else + m_pVehicle->bCarWheelPopped[1] = 0; + + byteFlags >>= 1; + + if (byteFlags & 1) + m_pVehicle->bCarWheelPopped[0] = 1; + else + m_pVehicle->bCarWheelPopped[0] = 0; + } + else if(GetVehicleSubtype() == VEHICLE_SUBTYPE_BIKE) + { + if(byteFlags & 1) + m_pVehicle->bBikeWheelPopped[1] = 1; + else + m_pVehicle->bBikeWheelPopped[1] = 0; + + byteFlags >>= 1; + + if(byteFlags & 1) + m_pVehicle->bBikeWheelPopped[0] = 1; + else + m_pVehicle->bBikeWheelPopped[0] = 0; + } +} + +//----------------------------------------------------------- + +BYTE CVehicle::GetWheelPopped() +{ + BYTE byteRet = 0; + + if(!m_pVehicle) return 0; + + if(GetVehicleSubtype() == VEHICLE_SUBTYPE_CAR) + { + if(m_pVehicle->bCarWheelPopped[0]) byteRet |= 1; + byteRet <<= 1; + + if(m_pVehicle->bCarWheelPopped[1]) byteRet |= 1; + byteRet <<= 1; + + if(m_pVehicle->bCarWheelPopped[2]) byteRet |= 1; + byteRet <<= 1; + + if(m_pVehicle->bCarWheelPopped[3]) byteRet |= 1; + } + else if(GetVehicleSubtype() == VEHICLE_SUBTYPE_BIKE) + { + if(m_pVehicle->bBikeWheelPopped[0]) byteRet |= 1; + byteRet <<= 1; + + if(m_pVehicle->bBikeWheelPopped[1]) byteRet |= 1; + } + return byteRet; +} + +//----------------------------------------------------------- + +void CVehicle::UpdateDamageStatus(DWORD dwPanelDamage, DWORD dwDoorDamage, BYTE byteLightDamage) +{ + if(m_pVehicle && (GetVehicleSubtype() == VEHICLE_SUBTYPE_CAR || + GetVehicleSubtype() == VEHICLE_SUBTYPE_PLANE)) { + + if(!dwPanelDamage && !dwDoorDamage && !byteLightDamage) { + if(m_pVehicle->dwPanelStatus || m_pVehicle->dwDoorStatus1 || m_pVehicle->dwLightStatus) { + // The ingame car is damaged in some way although the update + // says the car should be repaired. So repair it and exit. + DWORD dwVehiclePtr = (DWORD)m_pVehicle; + _asm mov ecx, dwVehiclePtr + _asm mov edx, 0x6A3440 // CAutomobile::RepairDamageModel + _asm call edx + + return; + } + } + + m_pVehicle->dwPanelStatus = dwPanelDamage; + m_pVehicle->dwDoorStatus1 = dwDoorDamage; + m_pVehicle->dwLightStatus = (DWORD)byteLightDamage; + + DWORD dwVehiclePtr = (DWORD)m_pVehicle; + _asm mov ecx, dwVehiclePtr + _asm mov edx, 0x6B3E90 // CAutomobile::UpdateDamageModel + _asm call edx + } +} + +//----------------------------------------------------------- + +DWORD CVehicle::GetPanelDamageStatus() +{ + if(m_pVehicle && GetVehicleSubtype() == VEHICLE_SUBTYPE_CAR) { + return m_pVehicle->dwPanelStatus; + } + return 0; +} + +//----------------------------------------------------------- + +DWORD CVehicle::GetDoorDamageStatus() +{ + if(m_pVehicle && GetVehicleSubtype() == VEHICLE_SUBTYPE_CAR) { + return m_pVehicle->dwDoorStatus1; + } + return 0; +} + +//----------------------------------------------------------- + +BYTE CVehicle::GetLightDamageStatus() +{ + if(m_pVehicle && GetVehicleSubtype() == VEHICLE_SUBTYPE_CAR) { + return (BYTE)m_pVehicle->dwLightStatus; + } + return 0; +} + +//----------------------------------------------------------- + +void CVehicle::AttachTrailer() +{ + if (m_pTrailer) + ScriptCommand(&put_trailer_on_cab, m_pTrailer->m_dwGTAId, m_dwGTAId); +} + +//----------------------------------------------------------- + +void CVehicle::DetachTrailer() +{ + bDetachingVehicleTrailer = TRUE; + + if (m_pTrailer && m_pTrailer->m_dwGTAId && GamePool_Vehicle_GetAt(m_pTrailer->m_dwGTAId)) { + if(m_pTrailer->m_pVehicle) { + ScriptCommand(&detach_trailer_from_cab, m_pTrailer->m_dwGTAId, m_dwGTAId); + } + } + bDetachingVehicleTrailer = FALSE; +} + +//----------------------------------------------------------- + +void CVehicle::SetTrailer(CVehicle *pTrailer) +{ + m_pTrailer = pTrailer; +} + +//----------------------------------------------------------- + +CVehicle* CVehicle::GetTrailer() +{ + if (!m_pVehicle) return NULL; + + // Try to find associated trailer + DWORD dwTrailerGTAPtr = m_pVehicle->dwTrailer; + + if(dwTrailerGTAPtr && pNetGame) { + CVehiclePool* pVehiclePool = pNetGame->GetVehiclePool(); + VEHICLEID TrailerID = (VEHICLEID)pVehiclePool->FindIDFromGtaPtr((VEHICLE_TYPE*)dwTrailerGTAPtr); + if(TrailerID != INVALID_VEHICLE_ID && pVehiclePool->GetSlotState(TrailerID)) { + return pVehiclePool->GetAt(TrailerID); + } + } + + return NULL; +} + +//----------------------------------------------------------- + +CVehicle* CVehicle::GetTractor() +{ + if(!m_pVehicle) return NULL; + + int iSubType = GetVehicleSubtype(); + if( iSubType == VEHICLE_SUBTYPE_BIKE || + iSubType == VEHICLE_SUBTYPE_BOAT || + iSubType == VEHICLE_SUBTYPE_TRAIN || + iSubType == VEHICLE_SUBTYPE_PUSHBIKE ) { + + return NULL; + } + + // Try to find associated trailer + DWORD dwTractorGTAPtr = m_pVehicle->dwTractor; + + if(dwTractorGTAPtr && pNetGame) { + CVehiclePool* pVehiclePool = pNetGame->GetVehiclePool(); + VEHICLEID TractorID = (VEHICLEID)pVehiclePool->FindIDFromGtaPtr((VEHICLE_TYPE*)dwTractorGTAPtr); + if(TractorID != INVALID_VEHICLE_ID && pVehiclePool->GetSlotState(TractorID)) { + return pVehiclePool->GetAt(TractorID); + } + } + + return NULL; +} + +//----------------------------------------------------------- + +BOOL CVehicle::IsATrailer() +{ + if(!m_pVehicle) return FALSE; + if(!GamePool_Vehicle_GetAt(m_dwGTAId)) return FALSE; + + if( m_pVehicle->entity.nModelIndex == 435 || + m_pVehicle->entity.nModelIndex == 450 || + m_pVehicle->entity.nModelIndex == 584 || + m_pVehicle->entity.nModelIndex == 591 || + m_pVehicle->entity.nModelIndex == 606 || + m_pVehicle->entity.nModelIndex == 607 || + m_pVehicle->entity.nModelIndex == 608 || + m_pVehicle->entity.nModelIndex == 610 || + m_pVehicle->entity.nModelIndex == 611 ) + { + return TRUE; + } + + return FALSE; +} + +//----------------------------------------------------------- + +BOOL CVehicle::IsTowTruck() +{ + if(!m_pVehicle) return FALSE; + if(!GamePool_Vehicle_GetAt(m_dwGTAId)) return FALSE; + + if( m_pVehicle->entity.nModelIndex == 525 ) + { + return TRUE; + } + + return FALSE; +} + +//----------------------------------------------------------- +//441, rcbandit +//464, rcbaron +//465, rcraider +//594, rccam +//564, rctiger +//501, rcgoblin + +BOOL CVehicle::IsRCVehicle() +{ + if (!m_pVehicle) return FALSE; + if (!GamePool_Vehicle_GetAt(m_dwGTAId)) return FALSE; + + if( m_pVehicle->entity.nModelIndex == 441 || + m_pVehicle->entity.nModelIndex == 464 || + m_pVehicle->entity.nModelIndex == 465 || + m_pVehicle->entity.nModelIndex == 594 || + m_pVehicle->entity.nModelIndex == 501 || + m_pVehicle->entity.nModelIndex == 564 ) + { + return TRUE; + } + + return FALSE; +} + +//----------------------------------------------------------- + +void CVehicle::ToggleLights(BYTE bEnable) +{ + if (!m_pVehicle) return; + if (!GamePool_Vehicle_GetAt(m_dwGTAId)) return; + + if (!bEnable) { + m_pVehicle->byteMoreFlags |= 8; + m_pVehicle->byteFlags &= 0xBF; + } else { + m_pVehicle->byteMoreFlags &= ~8; + m_pVehicle->byteFlags |= 0x40; + } +} + +//----------------------------------------------------------- + +bool CVehicle::AreLightsEnabled() +{ + if (!m_pVehicle) return true; + if (!GamePool_Vehicle_GetAt(m_dwGTAId)) return true; + + if (m_pVehicle->byteMoreFlags & 8) + return true; + + return false; +} + +//----------------------------------------------------------- + +void CVehicle::RemoveEveryoneFromVehicle() +{ + if (!m_pVehicle) return; + if (!GamePool_Vehicle_GetAt(m_dwGTAId)) return; + + float fPosX = m_pVehicle->entity.mat->pos.X; + float fPosY = m_pVehicle->entity.mat->pos.Y; + float fPosZ = m_pVehicle->entity.mat->pos.Z; + + int iPlayerID = 0; + if (m_pVehicle->pDriver) { + iPlayerID = GamePool_Ped_GetIndex( m_pVehicle->pDriver ); + ScriptCommand( &remove_actor_from_car_and_put_at, iPlayerID, fPosX, fPosY, fPosZ + 2 ); + } + + for (int i = 0; i < 7; i++) { + if (m_pVehicle->pPassengers[i] != NULL) { + iPlayerID = GamePool_Ped_GetIndex( m_pVehicle->pPassengers[i] ); + ScriptCommand( &remove_actor_from_car_and_put_at, iPlayerID, fPosX, fPosY, fPosZ + 2 ); + } + } +} + +//----------------------------------------------------------- + +BOOL CVehicle::AddComponent(WORD wComponentID) +{ + if (!m_pVehicle) return FALSE; + if (!GamePool_Vehicle_GetAt(m_dwGTAId)) return FALSE; + if (GetVehicleSubtype() != VEHICLE_SUBTYPE_CAR) return FALSE; + + DWORD v; + int iWait; + + wVehicleComponentDebug = wComponentID; + + if(!ScriptCommand(&is_component_available,wComponentID)) + { + pGame->RequestModel(wComponentID); + pGame->LoadRequestedModels(); + ScriptCommand(&request_car_component,wComponentID); + + iWait = 20; + while(iWait && !ScriptCommand(&is_component_available,wComponentID)) { + Sleep(1); + iWait--; + } + } + + if(ScriptCommand(&is_component_available,wComponentID)) + { + ScriptCommand(&add_car_component,m_dwGTAId,wComponentID,&v); + return TRUE; + } + return FALSE; +} + +//----------------------------------------------------------- + +BOOL CVehicle::RemoveComponent(WORD wComponentID) +{ + if (!m_pVehicle) return FALSE; + if (!GamePool_Vehicle_GetAt(m_dwGTAId)) return FALSE; + + ScriptCommand(&remove_component,m_dwGTAId,wComponentID); + return TRUE; +} + +//----------------------------------------------------------- + +void CVehicle::SetPaintJob(BYTE bytePaintJob) +{ + if (!m_pVehicle) return; + if (!GamePool_Vehicle_GetAt(m_dwGTAId)) return; + if (GetVehicleSubtype() != VEHICLE_SUBTYPE_CAR) return; + + if(bytePaintJob <= 3) { + ScriptCommand(&change_car_skin,m_dwGTAId,bytePaintJob); + } +} + +//----------------------------------------------------------- + +BOOL CVehicle::VerifyInstance() +{ + if(GamePool_Vehicle_GetAt(m_dwGTAId)) { + return TRUE; + } + return FALSE; +} + +//----------------------------------------------------------- + +void CVehicle::FUNC_100B8150(char *a2) +{ + strncpy(field_93,a2,32); +} + +//----------------------------------------------------------- + +void CVehicle::SetRotation(float fRotation) +{ + if(GamePool_Vehicle_GetAt(m_dwGTAId)) { + ScriptCommand(&set_car_z_angle,m_dwGTAId,fRotation); + } +} + +//----------------------------------------------------------- + +void CVehicle::FUNC_100B81A0() +{ + // TODO: CVehicle::FUNC_100B81A0() .text:100B81A0 +} + +//----------------------------------------------------------- + +void CVehicle::FUNC_100B81F0() +{ + SAFE_RELEASE(field_8F); +} + +//----------------------------------------------------------- + +void CVehicle::SetEngineStatus(BOOL bOn) +{ + m_bEngineStatus = bOn; +} + +//----------------------------------------------------------- + +BOOL CVehicle::GetEngineStatus() +{ + return m_bEngineStatus; +} + +//----------------------------------------------------------- + +void CVehicle::SetLightStatus(BOOL bOn) +{ + m_bLightStatus = bOn; +} + +//----------------------------------------------------------- + +BOOL CVehicle::GetLightStatus() +{ + return m_bLightStatus; +} + +//----------------------------------------------------------- + +void CVehicle::OpenDoor(int iDoor, int iNodeIndex, float fAngle) +{ + if (GetVehicleSubtype() != VEHICLE_SUBTYPE_CAR) return; + + DWORD dwVehiclePtr = (DWORD)m_pVehicle; + BOOL bPlaySound = TRUE; + DWORD dwPedPtr = 0; + + _asm push bPlaySound + _asm push fAngle + _asm push iDoor + _asm push iNodeIndex + _asm push dwPedPtr + _asm mov ecx, dwVehiclePtr + _asm mov ebx, 0x6A6AE0 + _asm call ebx +} + +//----------------------------------------------------------- + +float CVehicle::GetBikeBankingAngle() +{ + if(m_pVehicle && GamePool_Vehicle_GetAt(m_dwGTAId)) + { + return m_pVehicle->fBikeBankingAngle1; + } + return 0.0f; +} + +//----------------------------------------------------------- + +void CVehicle::SetBikeBankingAngle(float fAngle) +{ + if(!m_pVehicle) return; + if(!GamePool_Vehicle_GetAt(m_dwGTAId)) return; + if(fAngle > 1.0f || fAngle < -1.0f) return; + + m_pVehicle->fBikeBankingAngle2 = fAngle; +} + +//----------------------------------------------------------- + +BOOL CVehicle::FUNC_100B8330() +{ + if(field_8B) return TRUE; + return FALSE; +} + +//----------------------------------------------------------- + +BYTE CVehicle::GetMaxPassengers() +{ + if(m_pVehicle && GamePool_Vehicle_GetAt(m_dwGTAId)) + { + return m_pVehicle->byteMaxPassengers; + } + return 0; +} + +//----------------------------------------------------------- + +void CVehicle::SetWindowOpenFlag(BYTE byteDoorID) +{ + if(m_pVehicle) { + DWORD dwVehiclePtr = (DWORD)m_pVehicle; + + _asm mov ecx, dwVehiclePtr + _asm xor edx, edx + _asm mov dl, byteDoorID + _asm push edx + _asm mov edx, 0x6D3080 + _asm call edx + } +} + +//----------------------------------------------------------- + +void CVehicle::ClearWindowOpenFlag(BYTE byteDoorID) +{ + if(m_pVehicle) { + DWORD dwVehiclePtr = (DWORD)m_pVehicle; + + _asm mov ecx, dwVehiclePtr + _asm xor edx, edx + _asm mov dl, byteDoorID + _asm push edx + _asm mov edx, 0x6D30B0 + _asm call edx + } +} + +//----------------------------------------------------------- + +void CVehicle::FUNC_100B8A70(BOOL a2) +{ + // TODO: CVehicle::FUNC_100B8A70 .text:100B8A70 +} + +//----------------------------------------------------------- diff --git a/saco/game/vehicle.h b/saco/game/vehicle.h index 5eda50e..95d7c59 100644 --- a/saco/game/vehicle.h +++ b/saco/game/vehicle.h @@ -4,6 +4,8 @@ #include "game.h" #include "entity.h" +#include + enum eLandingGearState { LGS_UP, @@ -15,13 +17,20 @@ enum eLandingGearState class CVehicle : public CEntity { public: - - char _gap48[4]; - + //char _gap0[184]; + CVehicle* m_pTrailer; VEHICLE_TYPE *m_pVehicle; + BOOL m_bEngineStatus; + BOOL m_bLightStatus; + BOOL m_bIsInvulnerable; - char _gap50[33]; - + char _gap5C[4]; + + BOOL m_bDoorsLocked; // Vehicle is enterable TRUE/FALSE + BYTE m_byteObjectiveVehicle; // Is this a special objective vehicle? 0/1 + BOOL m_bSpecialMarkerEnabled; + DWORD m_dwTimeSinceLastDriven; + BOOL m_bHasBeenDriven; int field_71; char _gap75[4]; @@ -30,23 +39,36 @@ public: BYTE m_byteColor2; BOOL m_bHasNewColor; - char _gap7F[57]; + BOOL m_bUnoccupiedSync; + BOOL m_bRemoteUnocSync; + BOOL m_bKeepModelLoaded; + int field_8B; + IDirect3DTexture9 *field_8F; + char field_93[33]; CVehicle( int iType, float fPosX, float fPosY, float fPosZ, float fRotation = 0.0f, BOOL bKeepModelLoaded = FALSE, int a8 = 0); + virtual ~CVehicle(); + + virtual void Add(); + virtual void Remove(); void ResetPointers(); + void ProcessMarkers(); + int m_dwMarkerID; + void SetLockedState(int iLocked); UINT GetVehicleSubtype(); float GetHealth(); void SetHealth(float fHealth); - void SetColor(BYTE byteColor1, BYTE byteColor2); - void UpdateColor(); + void SetColor(BYTE byteColor1, BYTE byteColor2); + void UpdateColor(); BOOL HasSunk(); BOOL IsWrecked(); BOOL IsDriverLocalPlayer(); + BOOL IsLocalPlayerInThisVehicle(); BOOL IsATrainPart(); BOOL HasTurret(); BOOL HasADriver(); @@ -54,6 +76,12 @@ public: void SetHydraThrusters(DWORD dwDirection); DWORD GetHydraThrusters(); + void SetTankRot(float X, float Y); + float GetTankRotX(); + float GetTankRotY(); + + float GetTrainSpeed(); + void SetTrainSpeed(float fSpeed); UINT GetPassengersMax(); @@ -62,16 +90,58 @@ public: void SetAlarmState(WORD wState); void SetLandingGearState(eLandingGearState state); eLandingGearState GetLandingGearState(); + void SetInvulnerable(BOOL bInv); void SetEngineState(BOOL bState); + void SetDoorState(int iState); + void UpdateDamageStatus(DWORD dwPanelDamage, DWORD dwDoorDamage, BYTE byteLightDamage); + DWORD GetPanelDamageStatus(); + DWORD GetDoorDamageStatus(); + BYTE GetLightDamageStatus(); void LinkToInterior(int iInterior); + void SetWheelPopped(BYTE byteFlags); + BYTE GetWheelPopped(); + void AttachTrailer(); + void DetachTrailer(); + void SetTrailer(CVehicle *pTrailer); + CVehicle* GetTrailer(); + CVehicle* GetTractor(); + BOOL IsATrailer(); + BOOL IsTowTruck(); + BOOL IsRCVehicle(); + + void ToggleLights(BYTE bEnable = 25); + bool AreLightsEnabled(); void SetHornState(BYTE byteState); BOOL IsOccupied(); + BOOL UpdateLastDrivenTime(); + void RemoveEveryoneFromVehicle(); + void SetPaintJob(BYTE bytePaintJob); + BOOL AddComponent(WORD wComponentID); + BOOL RemoveComponent(WORD wComponentID); + BOOL VerifyInstance(); + void FUNC_100B8150(char *a2); + void SetRotation(float fRotation); + void FUNC_100B81A0(); + void FUNC_100B81F0(); + void SetEngineStatus(BOOL bOn); + BOOL GetEngineStatus(); + void SetLightStatus(BOOL bOn); + BOOL GetLightStatus(); + void OpenDoor(int iDoor, int iNodeIndex, float fAngle); + float GetBikeBankingAngle(); + void SetBikeBankingAngle(float fAngle); + BOOL FUNC_100B8330(); + + BYTE GetMaxPassengers(); + void SetWindowOpenFlag(BYTE byteDoorID); + void ClearWindowOpenFlag(BYTE byteDoorID); + void FUNC_100B8A70(BOOL a2); }; //----------------------------------------------------------- diff --git a/saco/gpci.cpp b/saco/gpci.cpp new file mode 100644 index 0000000..800660d --- /dev/null +++ b/saco/gpci.cpp @@ -0,0 +1,22 @@ + +#include "main.h" +#include "fhicl-sha1.h" +#include "../ttmath/ttmath.h" + +extern CNetGame *pNetGame; + +void GenerateComputerID(char* a1, char* a2, int a3) +{ + fhicl::SHA1 sha1; + unsigned int digest[5]; + + memset(digest, 0, sizeof(digest)); + + sha1.Input(a2, strlen(a2)); + sha1.Result(digest); + + if(!pNetGame) + a3--; + + // TODO: GenerateComputerID +} diff --git a/saco/main.cpp b/saco/main.cpp index e964823..4344cb0 100644 --- a/saco/main.cpp +++ b/saco/main.cpp @@ -27,6 +27,10 @@ CUnkClass14 *pUnkClass14=0; CUnkClass15 *pUnkClass15=0; BOOL bGameInited=FALSE; +BOOL bNetworkInited=FALSE; + +BOOL bQuitGame=FALSE; +DWORD dwStartQuitTick=0; WORD wVehicleComponentDebug=0; @@ -55,6 +59,20 @@ DWORD dwGraphicsLoop=0; CFileSystem *pFileSystem=NULL; + + + + +CDXUTDialogResourceManager *pDialogResourceManager=NULL; +CDXUTDialog *pGameUI=NULL; +CDXUTDialog *pDXUTDialog1=NULL; +CDXUTDialog *pDXUTDialog2=NULL; +CDXUTDialog *pDXUTDialog3=NULL; +CDXUTDialog *pDXUTDialog4=NULL; +CDXUTDialog *pDXUTDialog5=NULL; + +IDirect3DSurface9 *pD3DMouseSurface=NULL; + // forwards BOOL SubclassGameWindow(); @@ -63,6 +81,9 @@ void TheGraphicsLoop(); LONG WINAPI exc_handler(_EXCEPTION_POINTERS* exc_inf); void FUNC_1009DD50(); +void SetupDialogResourceManager(); +void SetupGameUI(); + DWORD dwOrgRwSetState=0; DWORD dwSetStateCaller=0; DWORD dwSetStateOption=0; @@ -93,7 +114,7 @@ void LaunchMonitor(PVOID v) #define ARCHIVE_FILE "samp.saa" -BOOL WINAPI DllMain_2(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { if(DLL_PROCESS_ATTACH==fdwReason) { @@ -138,13 +159,6 @@ BOOL WINAPI DllMain_2(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) //---------------------------------------------------- -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - _asm jmp DllMain_2 -} - -//---------------------------------------------------- - PCHAR GetSAMPPath() { return szSAMPDir; @@ -351,49 +365,24 @@ void DoInitStuff() pChatWindow = new CChatWindow(pD3DDevice,pDefaultFont,szChatLogFile); pCmdWindow = new CCmdWindow(pD3DDevice); - if(tSettings.bPlayOnline) { - pDeathWindow = new CDeathWindow(pD3DDevice); - pSpawnScreen = new CSpawnScreen(pD3DDevice); - pNewPlayerTags = new CNewPlayerTags(pD3DDevice); - pScoreBoard = new CScoreBoard(pD3DDevice); - pUnkClass3 = new CUnkClass3(pD3DDevice); - pUnkClass4 = new CUnkClass4(pD3DDevice); - pUnkClass5 = new CUnkClass5(pD3DDevice); - pNetStats = new CNetStats(pD3DDevice); - pSvrNetStats = new CSvrNetStats(pD3DDevice); - pHelpDialog = new CHelpDialog(pD3DDevice); - pUnkClass8 = new CUnkClass8(); - } - pLabel = new CLabel(pD3DDevice); - pUnkClass10 = new CUnkClass10(pD3DDevice); - pUnkClass11 = new CUnkClass11(); - pUnkClass12 = new CUnkClass12(); - pUnkClass13 = new CUnkClass13(pD3DDevice); - pUnkClass14 = new CUnkClass14(pD3DDevice); - pUnkClass15 = new CUnkClass15(); - // Setting up the commands. - OutputDebugString("Setting up commands.."); - SetupCommands(); - - OutputDebugString("Hooking RwSetState.."); - HookRwRenderStateSet(); - - pGame->SetMaxStats(); - - if(tSettings.bDebug) { - } - - // TODO: DoInitStuff + // TODO: DoInitStuff() bGameInited = TRUE; return; } - - + // NET GAME INIT + if(!bNetworkInited && tSettings.bPlayOnline) { + + pNetGame = new CNetGame(tSettings.szConnectHost,atoi(tSettings.szConnectPort), + tSettings.szNickName,tSettings.szConnectPass); + + bNetworkInited = TRUE; + return; + } } //---------------------------------------------------- @@ -428,6 +417,17 @@ void TheGraphicsLoop() //---------------------------------------------------- +void QuitGame() +{ + if(pNetGame && pNetGame->GetGameState() == GAMESTATE_CONNECTED) { + pNetGame->GetRakClient()->Disconnect(500); + } + bQuitGame = TRUE; + dwStartQuitTick = GetTickCount(); +} + +//---------------------------------------------------- + void InitSettings() { PCHAR szCmdLine = GetCommandLineA(); @@ -513,6 +513,18 @@ void SetStringFromQuotedCommandLine(char *szCmdLine, char *szString) //---------------------------------------------------- +void d3d9DestroyDeviceObjects() +{ + // TOOD: d3d9DestroyDeviceObjects +} + +void d3d9RestoreDeviceObjects() +{ + // TODO: d3d9RestoreDeviceObjects +} + +//---------------------------------------------------- + float GetElapsedTime() { static BOOL bTimerInit = false; @@ -655,3 +667,130 @@ char *GetFontFace() return "Arial"; } +void SetupDialogResourceManager() +{ + pDialogResourceManager = new CDXUTDialogResourceManager(); + pDialogResourceManager->OnCreateDevice(pD3DDevice); + pDialogResourceManager->OnResetDevice(); +} + +void CALLBACK OnDialogEvent3( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext ) +{ + // TODO: OnDialogEvent3 +} + +void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext ) +{ + // TODO: OnGUIEvent +} + +void CALLBACK OnDialogEvent1( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext ) +{ + // TODO: OnDialogEvent1 +} + +void CALLBACK OnDialogEvent2( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext ) +{ + // TODO: OnDialogEvent2 +} + +void CALLBACK OnDialogEvent4( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext ) +{ + // nothing +} + +void CALLBACK OnDialogEvent5( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext ) +{ + // nothing +} + +void SetupGameUI() +{ + SAFE_DELETE(pDXUTDialog1); + SAFE_DELETE(pGameUI); + SAFE_RELEASE(pD3DMouseSurface); + SAFE_DELETE(pDXUTDialog2); + SAFE_DELETE(pDXUTDialog3); + SAFE_DELETE(pDXUTDialog4); + SAFE_DELETE(pDXUTDialog5); + + pDXUTDialog1 = new CDXUTDialog(); + pDXUTDialog1->Init(pDialogResourceManager); + pDXUTDialog1->SetCallback( OnDialogEvent1 ); + pDXUTDialog1->SetSize(640,480); + pDXUTDialog1->SetLocation(0,0); + pDXUTDialog1->SetBackgroundColors(D3DCOLOR_ARGB( 150, 10, 10, 10 )); + pDXUTDialog1->EnableMouseInput(true); + pDXUTDialog1->EnableKeyboardInput(true); + pDXUTDialog1->SetVisible(false); + if(pScoreBoard) pScoreBoard->ResetDialogControls(pDXUTDialog1); + + pGameUI = new CDXUTDialog(); + pGameUI->Init(pDialogResourceManager); + pGameUI->SetCallback( OnGUIEvent ); + pGameUI->SetLocation(0,0); + pGameUI->SetSize(pGame->GetScreenWidth(),pGame->GetScreenHeight()); + pGameUI->EnableMouseInput(true); + pGameUI->EnableKeyboardInput(true); + + pDXUTDialog2 = new CDXUTDialog(); + pDXUTDialog2->Init(pDialogResourceManager); + pDXUTDialog2->SetCallback( OnDialogEvent2 ); + pDXUTDialog2->SetLocation(0,0); + pDXUTDialog2->SetSize(310,40); + pDXUTDialog2->SetBackgroundColors(D3DCOLOR_ARGB( 150, 10, 10, 10 )); + pDXUTDialog2->EnableMouseInput(true); + pDXUTDialog2->EnableKeyboardInput(false); + pDXUTDialog2->SetVisible(false); + pDXUTDialog2->AddButton(6, "<<", 10, 5, 90, 30); + pDXUTDialog2->AddButton(5, ">>", 110, 5, 90, 30); + pDXUTDialog2->AddButton(4, "Spawn", 210, 5, 90, 30); + if(pChatWindow) pChatWindow->ResetDialogControls(pGameUI); + if(pCmdWindow) pCmdWindow->ResetDialogControls(pGameUI); + + pDXUTDialog3 = new CDXUTDialog(); + pDXUTDialog3->Init(pDialogResourceManager); + pDXUTDialog3->SetCallback(OnDialogEvent3); + pDXUTDialog3->SetLocation(0,0); + pDXUTDialog3->SetSize(600,300); + pDXUTDialog3->EnableMouseInput(true); + pDXUTDialog3->EnableKeyboardInput(true); + pDXUTDialog3->SetBackgroundColors(D3DCOLOR_ARGB( 220, 5, 5, 5 )); + pDXUTDialog3->SetVisible(false); + if(pUnkClass3) pUnkClass3->ResetDialogControls(pDXUTDialog3); + + pDXUTDialog4 = new CDXUTDialog(); + pDXUTDialog4->Init(pDialogResourceManager); + pDXUTDialog4->SetCallback(OnDialogEvent4); + pDXUTDialog4->SetLocation(0,0); + pDXUTDialog4->SetSize(500,160); + pDXUTDialog4->EnableMouseInput(true); + pDXUTDialog4->EnableKeyboardInput(true); + pDXUTDialog4->SetBackgroundColors(D3DCOLOR_ARGB( 220, 5, 5, 5 )); + pDXUTDialog4->SetVisible(false); + if(pUnkClass4) pUnkClass4->ResetDialogControls(pDXUTDialog4); + + pDXUTDialog5 = new CDXUTDialog(); + pDXUTDialog5->Init(pDialogResourceManager); + pDXUTDialog5->SetCallback(OnDialogEvent5); + pDXUTDialog5->SetLocation(0,0); + pDXUTDialog5->SetSize(500,160); + pDXUTDialog5->EnableMouseInput(true); + pDXUTDialog5->EnableKeyboardInput(false); + pDXUTDialog5->SetBackgroundColors(D3DCOLOR_ARGB( 220, 5, 5, 5 )); + pDXUTDialog5->SetVisible(false); + if(pUnkClass5) pUnkClass5->ResetDialogControls(pDXUTDialog5); + + if(!pD3DMouseSurface) + { + pD3DDevice->CreateOffscreenPlainSurface(32,32,D3DFMT_A8R8G8B8, + D3DPOOL_SYSTEMMEM,&pD3DMouseSurface,NULL); + + D3DXLoadSurfaceFromFile(pD3DMouseSurface,NULL,NULL, + "mouse.png",NULL,D3DX_FILTER_NONE,0,NULL); + + if(pD3DMouseSurface) + pD3DDevice->SetCursorProperties(0,0,pD3DMouseSurface); + } +} + diff --git a/saco/main.h b/saco/main.h index afbf6d6..185250f 100644 --- a/saco/main.h +++ b/saco/main.h @@ -7,11 +7,15 @@ #define SAFE_DELETE(p) { if (p) { delete (p); (p) = NULL; } } +#define IDC_CMDEDIT 1 + +#define MAX_PLAYER_NAME 24 #define MAX_SETTINGS_STRING 256 #define GTASA_VERSION_UNKNOWN 0 #define GTASA_VERSION_USA10 1 #define GTASA_VERSION_EU10 2 +#define CSCANNER_DISTANCE 200.0f typedef struct _GAME_SETTINGS { BOOL bDebug; @@ -29,16 +33,19 @@ typedef struct _GAME_SETTINGS { #include "d3d9/include/d3d9.h" #include "d3d9/include/d3dx9core.h" +#include "d3d9/common/dxstdafx.h" #include "game/game.h" #include "../raknet/RakClientInterface.h" #include "../raknet/RakNetworkFactory.h" +#include "../raknet/BitStream.h" #include "../raknet/PacketEnumerations.h" #include "../raknet/SAMPRPC.h" #include "../raknet/GetTime.h" #include "net/localplayer.h" #include "net/remoteplayer.h" +#include "net/netplayer.h" #include "net/netrpc.h" #include "net/actorpool.h" #include "net/playerpool.h" diff --git a/saco/mod.h b/saco/mod.h index 48353de..e43c2e6 100644 --- a/saco/mod.h +++ b/saco/mod.h @@ -1,3 +1,5 @@ #include "../archive/pkey.h" #include "../archive/skey.h" + +#define MOD_VERSION 0x01 diff --git a/saco/net/actorpool.cpp b/saco/net/actorpool.cpp index 74c6cc0..e46aeb3 100644 --- a/saco/net/actorpool.cpp +++ b/saco/net/actorpool.cpp @@ -1,16 +1,121 @@ #include "../main.h" +extern CChatWindow *pChatWindow; + //---------------------------------------------------- CActorPool::CActorPool() { for(ACTORID ActorID = 0; ActorID < MAX_ACTORS; ActorID++) { - field_FA4[ActorID] = 0; - field_4[ActorID] = 0; - field_1F44[ActorID] = 0; + m_bActorSlotState[ActorID] = FALSE; + m_pActors[ActorID] = NULL; + m_pGTAPed[ActorID] = NULL; } field_0 = 0; } //---------------------------------------------------- + +CActorPool::~CActorPool() +{ + for(ACTORID ActorID = 0; ActorID < MAX_ACTORS; ActorID++) { + Delete(ActorID); + } +} + +//---------------------------------------------------- + +BOOL CActorPool::New(NEW_ACTOR *pNewActor) +{ + if(m_pActors[pNewActor->ActorID] != NULL) { + pChatWindow->AddDebugMessage("Warning: actor %u was not deleted", pNewActor->ActorID); + Delete(pNewActor->ActorID); + } + + m_pActors[pNewActor->ActorID] = new CActorPed(pNewActor->iSkin, + pNewActor->vecPos.X,pNewActor->vecPos.Y,pNewActor->vecPos.Z, + pNewActor->fRotation); + + if(m_pActors[pNewActor->ActorID]) + { + m_pGTAPed[pNewActor->ActorID] = m_pActors[pNewActor->ActorID]->GetGtaActor(); + m_bActorSlotState[pNewActor->ActorID] = TRUE; + m_pActors[pNewActor->ActorID]->SetHealth(pNewActor->fHealth); + if(pNewActor->byteImmunity) + m_pActors[pNewActor->ActorID]->ToggleImmunity(1); + else + m_pActors[pNewActor->ActorID]->ToggleImmunity(0); + field_2EE4[pNewActor->ActorID] = 1; + field_3E84[pNewActor->ActorID] = 0; + + RecalcPoolSize(); + + return TRUE; + } + else + { + return FALSE; + } +} + +//---------------------------------------------------- + +BOOL CActorPool::Delete(ACTORID ActorID) +{ + if(!GetSlotState(ActorID) || !m_pActors[ActorID]) + { + return FALSE; + } + + m_bActorSlotState[ActorID] = FALSE; + delete m_pActors[ActorID]; + m_pActors[ActorID] = NULL; + m_pGTAPed[ActorID] = NULL; + + RecalcPoolSize(); + + return TRUE; +} + +//---------------------------------------------------- + +void CActorPool::RecalcPoolSize() +{ + int iNewIndex = 0; + int i = 0; + + do + { + if(m_bActorSlotState[i]) + iNewIndex = i; + if(m_bActorSlotState[i+1]) + iNewIndex = i+1; + if(m_bActorSlotState[i+2]) + iNewIndex = i+2; + if(m_bActorSlotState[i+3]) + iNewIndex = i+3; + if(m_bActorSlotState[i+4]) + iNewIndex = i+4; + i += 5; + } + while(i < MAX_ACTORS); + + field_0 = iNewIndex; +} + +//---------------------------------------------------- + +ACTORID CActorPool::FindIDFromGtaPtr(PED_TYPE *pGtaPed) +{ + int x=0; + + while(x<=field_0) { + if(pGtaPed == m_pGTAPed[x]) return x; + x++; + } + + return 0xFFFF; +} + +//---------------------------------------------------- diff --git a/saco/net/actorpool.h b/saco/net/actorpool.h index 3bf4197..fb950b1 100644 --- a/saco/net/actorpool.h +++ b/saco/net/actorpool.h @@ -1,21 +1,45 @@ #pragma once +#pragma pack(1) +typedef struct _NEW_ACTOR { + ACTORID ActorID; + int iSkin; + VECTOR vecPos; + float fRotation; + float fHealth; + BYTE byteImmunity; +} NEW_ACTOR; + //---------------------------------------------------- class CActorPool { private: - int field_0; - int field_4[MAX_ACTORS]; - int field_FA4[MAX_ACTORS]; - int field_1F44[MAX_ACTORS]; + int field_0; + CActorPed *m_pActors[MAX_ACTORS]; + BOOL m_bActorSlotState[MAX_ACTORS]; + PED_TYPE *m_pGTAPed[MAX_ACTORS]; // pointers to actual ingame actors. + int field_2EE4[MAX_ACTORS]; + int field_3E84[MAX_ACTORS]; - char _gap2EE4[8000]; + void RecalcPoolSize(); public: CActorPool(); + ~CActorPool(); + + BOOL New(NEW_ACTOR *pNewActor); + BOOL Delete(ACTORID ActorID); + + // Find out if the slot is inuse. + BOOL GetSlotState(ACTORID ActorID) { + if(ActorID >= MAX_ACTORS) { return FALSE; } + return m_bActorSlotState[ActorID]; + }; + + ACTORID FindIDFromGtaPtr(PED_TYPE *pGtaPed); }; //---------------------------------------------------- diff --git a/saco/net/labelpool.cpp b/saco/net/labelpool.cpp index de697a5..c59a238 100644 --- a/saco/net/labelpool.cpp +++ b/saco/net/labelpool.cpp @@ -3,9 +3,33 @@ CLabelPool::CLabelPool() { - for(WORD wLabel = 0; wLabel < MAX_LABELS; wLabel++) + for(WORD wLabelID = 0; wLabelID < MAX_LABELS; wLabelID++) { - memset(&field_0[wLabel], 0, sizeof(struc_92)); - field_E800[wLabel] = 0; + memset(&m_Labels[wLabelID], 0, sizeof(LABEL)); + m_bLabelSlotState[wLabelID] = FALSE; } } + +CLabelPool::~CLabelPool() +{ + for(WORD wLabelID = 0; wLabelID < MAX_LABELS; wLabelID++) + { + if(m_bLabelSlotState[wLabelID]) + { + Delete(wLabelID); + } + } +} + +BOOL CLabelPool::Delete(WORD wLabelID) +{ + if(wLabelID >= MAX_LABELS) return FALSE; + if(!m_bLabelSlotState[wLabelID]) return FALSE; + + if(m_Labels[wLabelID].szText) + free(m_Labels[wLabelID].szText); + memset(&m_Labels[wLabelID], 0, sizeof(LABEL)); + m_bLabelSlotState[wLabelID] = FALSE; + + return TRUE; +} diff --git a/saco/net/labelpool.h b/saco/net/labelpool.h index 6c5ce7e..51e1010 100644 --- a/saco/net/labelpool.h +++ b/saco/net/labelpool.h @@ -1,17 +1,21 @@ #pragma once -struct struc_92 +typedef struct _LABEL { - char _gap[29]; -}; + char *szText; + char _gap4[25]; +} LABEL; class CLabelPool { private: - struc_92 field_0[MAX_LABELS]; - int field_E800[MAX_LABELS]; + LABEL m_Labels[MAX_LABELS]; + BOOL m_bLabelSlotState[MAX_LABELS]; public: CLabelPool(); + ~CLabelPool(); + + BOOL Delete(WORD wLabelID); }; diff --git a/saco/net/localplayer.cpp b/saco/net/localplayer.cpp index c5b38ec..12bffd0 100644 --- a/saco/net/localplayer.cpp +++ b/saco/net/localplayer.cpp @@ -1,7 +1,16 @@ #include "../main.h" +#include "../game/util.h" extern CGame *pGame; +extern CNetGame *pNetGame; + +BOOL bFirstSpawn = TRUE; + +int iNetModeNormalOnfootSendRate = NETMODE_NORMAL_ONFOOT_SENDRATE; +int iNetModeNormalIncarSendRate = NETMODE_NORMAL_INCAR_SENDRATE; +int iNetModeFiringSendRate = NETMODE_FIRING_SENDRATE; +int iNetModeSendMultiplier = NETMODE_SEND_MULTIPLIER; //---------------------------------------------------------- @@ -15,8 +24,8 @@ CLocalPlayer::CLocalPlayer() field_2D6 = GetTickCount(); field_2F6 = 0; m_pPlayerPed = pGame->FindPlayerPed(); - field_F0 = 0; - field_F4 = 0; + m_bIsActive = FALSE; + m_bIsWasted = FALSE; field_10D = 0; field_30A = 0; field_10F = GetTickCount(); @@ -26,26 +35,26 @@ CLocalPlayer::CLocalPlayer() field_11B = field_10F; m_bIsSpectating = FALSE; field_30F = 0; - field_310 = -1; + m_SpectateID = 0xFFFFFFFF; field_306 = 0; ResetAllSyncAttributes(); - int x=0; + DWORD x=0; while(x!=13) { field_18A[x] = 0; field_197[x] = 0; x++; } - field_10C = -1; + m_byteTeam = NO_TEAM; } //---------------------------------------------------------- void CLocalPlayer::ResetAllSyncAttributes() { - field_17D = 0; + m_bHasSpawnInfo = FALSE; field_2FA = 0; field_302 = 0; field_2FE = 0; @@ -84,3 +93,117 @@ void CLocalPlayer::Say(PCHAR szText) //---------------------------------------------------------- + + +//---------------------------------------------------------- + +BOOL CLocalPlayer::Spawn() +{ + if(!m_bHasSpawnInfo) return FALSE; + + CCamera *pGameCamera; + pGameCamera = pGame->GetCamera(); + pGameCamera->Restore(); + pGameCamera->SetBehindPlayer(); + pGame->DisplayHud(TRUE); + m_pPlayerPed->TogglePlayerControllable(1); + + if(!bFirstSpawn) { + m_pPlayerPed->SetInitialState(); + } else { + bFirstSpawn = FALSE; + } + + // TODO: CLocalPlayer::Spawn + + return TRUE; +} + +//---------------------------------------------------------- + + + +//---------------------------------------------------- + +void CLocalPlayer::SetPlayerColor(DWORD dwColor) +{ + SetRadarColor(pNetGame->GetPlayerPool()->GetLocalPlayerID(),dwColor); +} + +//---------------------------------------------------- + +DWORD CLocalPlayer::GetPlayerColorAsRGBA() +{ + return TranslateColorCodeToRGBA(pNetGame->GetPlayerPool()->GetLocalPlayerID()); +} + +//---------------------------------------------------- + +DWORD CLocalPlayer::GetPlayerColorAsARGB() +{ + return (TranslateColorCodeToRGBA(pNetGame->GetPlayerPool()->GetLocalPlayerID()) >> 8) | 0xFF000000; +} + +//---------------------------------------------------- + +void CLocalPlayer::ProcessOnFootWorldBounds() +{ + if(pGame->GetActiveInterior() != 0) return; // can't enforce inside interior + + if( m_pPlayerPed->EnforceWorldBoundries( + pNetGame->field_3D5->WorldBounds[0], + pNetGame->field_3D5->WorldBounds[1], + pNetGame->field_3D5->WorldBounds[2], + pNetGame->field_3D5->WorldBounds[3]) ) + { + m_pPlayerPed->SetArmedWeapon(0); + pGame->DisplayGameText("Stay within the ~r~world boundries",1000,5); + } +} + +//---------------------------------------------------- + +void CLocalPlayer::ProcessInCarWorldBounds() +{ + CVehiclePool *pVehiclePool = pNetGame->GetVehiclePool(); + VEHICLEID VehicleID = (VEHICLEID)pVehiclePool->FindIDFromGtaPtr(m_pPlayerPed->GetGtaVehicle()); + CVehicle *pGameVehicle; + + if(pGame->GetActiveInterior() != 0) return; // can't enforce inside interior + + if(VehicleID != INVALID_VEHICLE_ID) { + pGameVehicle = pVehiclePool->GetAt(VehicleID); + if(!pGameVehicle) return; + + if( pGameVehicle->EnforceWorldBoundries( + pNetGame->field_3D5->WorldBounds[0], + pNetGame->field_3D5->WorldBounds[1], + pNetGame->field_3D5->WorldBounds[2], + pNetGame->field_3D5->WorldBounds[3]) ) + { + pGame->DisplayGameText("Stay within the ~r~world boundries",1000,5); + } + } +} + +//----------------------------------------------------- + + + + + + + + +//----------------------------------------------------------- + +void CLocalPlayer::ToggleSpectating(BOOL bToggle) +{ + // TODO: CLocalPlayer::ToggleSpectating + + m_bIsSpectating = bToggle; + m_SpectateID = 0xFFFFFFFF; +} + +//----------------------------------------------------------- + diff --git a/saco/net/localplayer.h b/saco/net/localplayer.h index f2fd620..0e2ea1f 100644 --- a/saco/net/localplayer.h +++ b/saco/net/localplayer.h @@ -14,8 +14,8 @@ public: short field_92; char field_94[68]; char field_D8[24]; - int field_F0; - int field_F4; + BOOL m_bIsActive; + BOOL m_bIsWasted; char _gapF8[2]; @@ -24,7 +24,7 @@ public: int field_100; CPlayerPed *m_pPlayerPed; BOOL m_bIsSpectating; - char field_10C; + BYTE m_byteTeam; short field_10D; DWORD field_10F; DWORD field_113; @@ -48,7 +48,7 @@ public: char _gap14B[50]; - int field_17D; + BOOL m_bHasSpawnInfo; DWORD field_181; short field_185; short field_187; @@ -80,7 +80,7 @@ public: char _gap30E; char field_30F; - int field_310; + DWORD m_SpectateID; // Vehicle or player id char _gap314[4]; @@ -92,8 +92,17 @@ public: void ResetAllSyncAttributes(); + BOOL Spawn(); + void Say(PCHAR szText); + void SetPlayerColor(DWORD dwColor); + DWORD GetPlayerColorAsRGBA(); + DWORD GetPlayerColorAsARGB(); + void ProcessOnFootWorldBounds(); + void ProcessInCarWorldBounds(); + + void ToggleSpectating(BOOL bToggle); BOOL IsSpectating() { return m_bIsSpectating; }; BOOL IsInRCMode() { return m_bInRCMode; }; diff --git a/saco/net/netgame.cpp b/saco/net/netgame.cpp index 7e17a3f..013f122 100644 --- a/saco/net/netgame.cpp +++ b/saco/net/netgame.cpp @@ -1,9 +1,17 @@ #include "../main.h" +#include "../mod.h" +#include "../buildinfo.h" #include "../../raknet/SocketDataEncryptor.h" extern CGame *pGame; extern CChatWindow *pChatWindow; +extern CConfig *pConfig; +extern CAudioStream *pAudioStream; + +void FUNC_100AABE0(); // patches.cpp + +#define NETGAME_VERSION 4057 //---------------------------------------------------- @@ -33,10 +41,17 @@ bool __stdcall HasTimestamps(Packet *p) //---------------------------------------------------- -CNetGame::CNetGame(PCHAR szHostOrIp, int iPort, +int CNetGame::GetTime() +{ + return (int)RakNet::GetTime(); +} + +//---------------------------------------------------- + +CNetGame::CNetGame(PCHAR szHostOrIp, int iPort, PCHAR szPlayerName, PCHAR szPass) { - field_3D5 = (struc_41*)calloc(1,sizeof(struc_41)); + field_3D5 = (struc_41 *)calloc(1,sizeof(struc_41)); memset(m_szHostName,0,256); memset(m_szHostOrIp,0,256); @@ -49,46 +64,75 @@ CNetGame::CNetGame(PCHAR szHostOrIp, int iPort, InitPools(); + m_pPools->pPlayerPool->SetLocalPlayerName(szPlayerName); + SocketDataEncryptor::SetKey(iPort); RegisterRPCs(m_pRakClient); RegisterScriptRPCs(m_pRakClient); // Register server-side scripting RPCs. + m_pRakClient->SetPassword(szPass); + + int i; + for (i = 0; i < 100; i++) m_dwMapIcon[i] = NULL; + + pGame->EnableClock(0); // Hide the clock by default + pGame->EnableZoneNames(0); + field_3D5->iDeathDropMoney = 0; + field_3D5->iSpawnsAvailable = 0; + field_3D5->bNameTagLOS = true; + field_3D5->byteHoldTime = 1; + field_3D5->bUseCJWalk = false; + field_3D5->bDisableEnterExits = false; + field_3D5->bZoneNames = false; + field_3D5->field_20 = 0; + field_3D5->fNameTagDrawDistance = 60.0f; + field_3D5->field_22 = 1; + field_3D5->byteWorldTime = 12; + field_3D5->byteWorldMinute = 0; + field_3D5->byteWeather = 1; + field_3D5->fGravity = (float)0.008000000; + + m_bPlayerNameTagStatus = true; + if(pConfig && pConfig->GetIntVariable("nonametagstatus")) + m_bPlayerNameTagStatus = false; + + field_232 = 0; + field_233 = 0; + m_dwLastConnectAttempt = GetTickCount(); m_iGameState = GAMESTATE_WAIT_CONNECT; + field_239 = 0; + field_3D9 = 0; - if(pChatWindow) pChatWindow->AddDebugMessage("{FFFFFF}SA-MP {B9C9BF}0.3.7-R5 {FFFFFF}Started"); - - // TODO: CNetGame::CNetGame(...) .text:1000B930 + PrintWelcomeMessage(); } //---------------------------------------------------- -void CNetGame::Process() +CNetGame::~CNetGame() { - UpdateNetwork(); - // TODO: CNetGame::Process() + m_pRakClient->Disconnect(0); + UnRegisterRPCs(m_pRakClient); + UnRegisterScriptRPCs(m_pRakClient); // Unregister server-side scripting RPCs. + RakNetworkFactory::DestroyRakClientInterface(m_pRakClient); + SAFE_DELETE(m_pPools->pPlayerPool); + SAFE_DELETE(m_pPools->pVehiclePool); + SAFE_DELETE(m_pPools->pActorPool); + SAFE_DELETE(m_pPools->pTextDrawPool); + SAFE_DELETE(m_pPools->pGangZonePool); + SAFE_DELETE(m_pPools->pLabelPool); + SAFE_DELETE(m_pPools->pPickupPool); + SAFE_DELETE(m_pPools->pObjectPool); + SAFE_DELETE(m_pPools->pMenuPool); + SAFE_DELETE(m_pPools); + SAFE_DELETE(field_3D5); } //---------------------------------------------------- -// UPDATE NETWORK -//---------------------------------------------------- - -void CNetGame::UpdateNetwork() -{ -/* Packet* pkt=NULL; - unsigned char packetIdentifier; - - while((pkt = m_pRakClient->Receive())) - { - - }*/ - - // TODO: CNetGame::UpdateNetwork() -} void CNetGame::InitPools() { - m_pPools = (NETGAME_POOLS *)calloc(1, sizeof(NETGAME_POOLS)); + m_pPools = (NETGAME_POOLS *)calloc(1,sizeof(NETGAME_POOLS)); m_pPools->pObjectPool = new CObjectPool(); m_pPools->pMenuPool = new CMenuPool(); @@ -101,9 +145,482 @@ void CNetGame::InitPools() m_pPools->pActorPool = new CActorPool(); } -DWORD CNetGame::GetTime() +//---------------------------------------------------- + +void CNetGame::ResetAllPools() { - return (DWORD)RakNet::GetTime(); + ResetVehiclePool(); + ResetActorPool(); + ResetTextDrawPool(); + ResetGangZonePool(); + ResetLabelPool(); + ResetMapIcons(); + ResetPickupPool(); + ResetObjectPool(); + ResetMenuPool(); +} + +//---------------------------------------------------- + +void CNetGame::PrintWelcomeMessage() +{ + if(pChatWindow) pChatWindow->AddDebugMessage("{FFFFFF}SA-MP {B9C9BF}" SAMP_VERSION " {FFFFFF}Started"); +} + +//---------------------------------------------------- + +void CNetGame::HandleConnectingState() +{ + if((GetTickCount() - m_dwLastConnectAttempt) > 3000) + { + if(pChatWindow) pChatWindow->AddDebugMessage("Connecting to %s:%d...",m_szHostOrIp,m_iPort); + m_pRakClient->Connect(m_szHostOrIp,m_iPort,0,0,2); + m_dwLastConnectAttempt = GetTickCount(); + SetGameState(GAMESTATE_CONNECTING); + } +} + +//---------------------------------------------------- + +void CNetGame::ShowWaitingScreen() +{ + if(pGame->FindPlayerPed()->IsInVehicle()) { + pGame->FindPlayerPed()->RemoveFromVehicleAndPutAt(1093.4f,-2036.5f,82.710602f); + } else { + pGame->FindPlayerPed()->TeleportTo(1133.0504f,-2038.4034f,69.1f); + } + pGame->GetCamera()->SetPosition(1093.0f,-2036.0f,90.0f,0.0f,0.0f,0.0f); + pGame->GetCamera()->LookAtPoint(384.0f,-1557.0f,20.0f,2); + pGame->SetWorldWeather(1); + pGame->DisplayHud(FALSE); +} + +//---------------------------------------------------- + +void CNetGame::InitGameLogic() +{ + if(field_3D5->bManualVehicleEngineAndLights) + FUNC_100AABE0(); + + field_3D5->WorldBounds[0] = 20000.0f; + field_3D5->WorldBounds[1] = -20000.0f; + field_3D5->WorldBounds[2] = 20000.0f; + field_3D5->WorldBounds[3] = -20000.0f; +} + +//---------------------------------------------------- + +float GetElapsedTime(); + +void CNetGame::Process() +{ + float fElapsedTime = GetElapsedTime(); + + UpdateNetwork(); + + if (field_3D5->byteHoldTime) { + pGame->SetWorldTime(field_3D5->byteWorldTime, field_3D5->byteWorldMinute); + } + + // KEEP THE ANIMS LOADED DURING THE NETGAME + pGame->RequestAnimationsAndModels(); + + if(GetGameState() == GAMESTATE_CONNECTED) { + + } + else { + ShowWaitingScreen(); + } + + if(GetGameState() == GAMESTATE_WAIT_CONNECT) + HandleConnectingState(); + + // TODO: CNetGame::Process() +} + +//---------------------------------------------------- +// UPDATE NETWORK +//---------------------------------------------------- + +void CNetGame::UpdateNetwork() +{ + Packet* pkt=NULL; + unsigned char packetIdentifier; + + while((pkt = m_pRakClient->Receive())) + { + packetIdentifier = GetPacketID(pkt); + + switch(packetIdentifier) + { + case ID_PLAYER_SYNC: + Packet_PlayerSync(pkt); + break; + case ID_VEHICLE_SYNC: + Packet_VehicleSync(pkt); + break; + case ID_PASSENGER_SYNC: + Packet_PassengerSync(pkt); + break; + case ID_WEAPON_SHOT_SYNC: + Packet_WeaponShotSync(pkt); + break; + case ID_AIM_SYNC: + Packet_AimSync(pkt); + break; + case ID_TRAILER_SYNC: + Packet_TrailerSync(pkt); + break; + case ID_UNOCCUPIED_SYNC: + Packet_UnoccupiedSync(pkt); + break; + case 208: + FUNC_10009F10(pkt); + break; + case 12: + FUNC_1000A100(pkt); + break; + case ID_CONNECTION_BANNED: + Packet_ConnectionBanned(pkt); + break; + case ID_RSA_PUBLIC_KEY_MISMATCH: + Packet_RSAPublicKeyMismatch(pkt); + break; + case ID_NO_FREE_INCOMING_CONNECTIONS: + Packet_NoFreeIncomingConnections(pkt); + break; + case ID_DISCONNECTION_NOTIFICATION: + Packet_DisconnectionNotification(pkt); + break; + case ID_CONNECTION_LOST: + Packet_ConnectionLost(pkt); + break; + case ID_INVALID_PASSWORD: + Packet_InvalidPassword(pkt); + break; + case ID_MODIFIED_PACKET: + Packet_ModifiedPacket(pkt); + break; + case ID_CONNECTION_ATTEMPT_FAILED: + Packet_ConnectAttemptFailed(pkt); + break; + case ID_CONNECTION_REQUEST_ACCEPTED: + Packet_ConnectionSucceeded(pkt); + break; + } + + m_pRakClient->DeallocatePacket(pkt); + } +} + +//---------------------------------------------------- +// PACKET HANDLERS INTERNAL +//---------------------------------------------------- + +void CNetGame::Packet_PlayerSync(Packet *p) +{ + // TODO: CNetGame::Packet_PlayerSync +} + +//---------------------------------------------------- + +void CNetGame::Packet_VehicleSync(Packet *p) +{ + // TODO: CNetGame::Packet_VehicleSync +} + +//---------------------------------------------------- + +void CNetGame::Packet_PassengerSync(Packet *p) +{ + // TODO: CNetGame::Packet_PassengerSync +} + +//---------------------------------------------------- + +void CNetGame::Packet_WeaponShotSync(Packet *p) +{ + // TODO: CNetGame::Packet_WeaponShotSync +} + +//---------------------------------------------------- + +void CNetGame::Packet_AimSync(Packet *p) +{ + // TODO: CNetGame::Packet_AimSync +} + +//---------------------------------------------------- + +void CNetGame::Packet_TrailerSync(Packet *p) +{ + // TODO: CNetGame::Packet_TrailerSync +} + +//---------------------------------------------------- + +void CNetGame::Packet_UnoccupiedSync(Packet *p) +{ + // TODO: CNetGame::Packet_UnoccupiedSync +} + +//---------------------------------------------------- + +void CNetGame::FUNC_10009F10(Packet *p) +{ + // TODO: CNetGame::FUNC_10009F10 +} + +//---------------------------------------------------- + +void CNetGame::FUNC_1000A100(Packet *p) +{ + // TODO: CNetGame::FUNC_1000A100 +} + +//---------------------------------------------------- + +void CNetGame::Packet_RSAPublicKeyMismatch(Packet* packet) +{ + pChatWindow->AddDebugMessage("Failed to initialize encryption."); +} + +//---------------------------------------------------- + +void CNetGame::Packet_ConnectionBanned(Packet* packet) +{ + pChatWindow->AddDebugMessage("You are banned from this server."); +} + +//---------------------------------------------------- + +void CNetGame::Packet_ConnectionRequestAccepted(Packet* packet) +{ + pChatWindow->AddDebugMessage("Server has accepted the connection."); +} + +//---------------------------------------------------- + +void CNetGame::Packet_NoFreeIncomingConnections(Packet* packet) +{ + pChatWindow->AddDebugMessage("The server is full. Retrying..."); + SetGameState(GAMESTATE_WAIT_CONNECT); +} + +//---------------------------------------------------- + +void CNetGame::Packet_DisconnectionNotification(Packet* packet) +{ + pChatWindow->AddDebugMessage("Server closed the connection."); + if(pAudioStream) + pAudioStream->Stop(); + m_pRakClient->Disconnect(2000); +} + +//---------------------------------------------------- + +void CNetGame::Packet_ConnectionLost(Packet* packet) +{ + // TODO: CNetGame::Packet_ConnectionLost +} + +//---------------------------------------------------- + +void CNetGame::Packet_InvalidPassword(Packet* packet) +{ + pChatWindow->AddDebugMessage("Wrong server password."); + m_pRakClient->Disconnect(0); +} + +//---------------------------------------------------- + +void CNetGame::Packet_ModifiedPacket(Packet* packet) +{ +#ifdef _DEBUG + char szBuffer[256]; + sprintf(szBuffer, "Packet was modified, sent by id: %d, ip: %s", + (unsigned int)packet->playerIndex, packet->playerId.ToString()); + pChatWindow->AddDebugMessage(szBuffer); + //m_pRakClient->Disconnect(0); +#endif +} + +//---------------------------------------------------- +// RST + +void CNetGame::Packet_ConnectAttemptFailed(Packet* packet) +{ + pChatWindow->AddDebugMessage("The server didn't respond. Retrying.."); + SetGameState(GAMESTATE_WAIT_CONNECT); +} + +//---------------------------------------------------- +// Connection Success + +void CNetGame::Packet_ConnectionSucceeded(Packet *p) +{ + + RakNet::BitStream bsReturnParams((PCHAR)p->data, p->length, true); + + BYTE bytePacketID=0; + unsigned int binaryAddr=0; + unsigned short port=0; + unsigned short playerId=0; + unsigned int uiChallenge=0; + + bsReturnParams.Read(bytePacketID); + bsReturnParams.Read(binaryAddr); + bsReturnParams.Read(port); + bsReturnParams.Read(playerId); + bsReturnParams.Read(uiChallenge); + + uiChallenge ^= NETGAME_VERSION; + + if(pChatWindow) { + pChatWindow->AddDebugMessage("Connected. Joining the game..."); + } + + m_iGameState = GAMESTATE_AWAIT_JOIN; + + int iVersion = NETGAME_VERSION; + BYTE byteMod = MOD_VERSION; + BYTE byteNameLen = (BYTE)strlen(GetPlayerPool()->GetLocalPlayerName()); + + RakNet::BitStream bsSend; + bsSend.Write(iVersion); + bsSend.Write(byteMod); + bsSend.Write(byteNameLen); + bsSend.Write(GetPlayerPool()->GetLocalPlayerName(),byteNameLen); + bsSend.Write(uiChallenge); + + bsSend.Write((BYTE)strlen(SAMP_VERSION)); + bsSend.Write(SAMP_VERSION,strlen(SAMP_VERSION)); + bsSend.Write(uiChallenge); + m_pRakClient->RPC(&RPC_ClientJoin,&bsSend,HIGH_PRIORITY,RELIABLE,0,false); +} + +//---------------------------------------------------- + +void CNetGame::TogglePlayerTagStatus() +{ + if(!m_bPlayerNameTagStatus) + { + pChatWindow->AddInfoMessage("NameTag Player Status: ON"); + if(pConfig) + pConfig->SetIntVariable("nonametagstatus", 0); + m_bPlayerNameTagStatus = true; + } + else + { + pChatWindow->AddInfoMessage("NameTag Player Status: OFF"); + if(pConfig) + pConfig->SetIntVariable("nonametagstatus", 1); + m_bPlayerNameTagStatus = false; + } +} + +//---------------------------------------------------- + +void CNetGame::UpdatePlayerScoresAndPings() +{ + static DWORD dwLastUpdateTick = 0; + + if ((GetTickCount() - dwLastUpdateTick) > 3000) { + dwLastUpdateTick = GetTickCount(); + RakNet::BitStream bsParams; + if(m_pRakClient) + m_pRakClient->RPC(&RPC_UpdateScoresPingsIPs, &bsParams, HIGH_PRIORITY, RELIABLE,0,false); + } +} + +//---------------------------------------------------- + +void CNetGame::ResetVehiclePool() +{ + if(m_pPools->pVehiclePool) { + delete m_pPools->pVehiclePool; + } + m_pPools->pVehiclePool = new CVehiclePool(); +} + +//---------------------------------------------------- + +void CNetGame::ResetPlayerPool() +{ + if(m_pPools->pPlayerPool) { + delete m_pPools->pPlayerPool; + } + m_pPools->pPlayerPool = new CPlayerPool(); +} + +//---------------------------------------------------- + +void CNetGame::ResetPickupPool() +{ + if(m_pPools->pPickupPool) { + delete m_pPools->pPickupPool; + } + m_pPools->pPickupPool = new CPickupPool(); +} + +//---------------------------------------------------- + +void CNetGame::ResetMenuPool() +{ + if(m_pPools->pMenuPool) { + delete m_pPools->pMenuPool; + } + m_pPools->pMenuPool = new CMenuPool(); +} + +//---------------------------------------------------- + +void CNetGame::ResetLabelPool() +{ + if(m_pPools->pLabelPool) { + delete m_pPools->pLabelPool; + } + m_pPools->pLabelPool = new CLabelPool(); +} + +//---------------------------------------------------- + +void CNetGame::ResetTextDrawPool() +{ + if(m_pPools->pTextDrawPool) { + delete m_pPools->pTextDrawPool; + } + m_pPools->pTextDrawPool = new CTextDrawPool(); +} + +//---------------------------------------------------- + +void CNetGame::ResetObjectPool() +{ + if(m_pPools->pObjectPool) { + delete m_pPools->pObjectPool; + } + m_pPools->pObjectPool = new CObjectPool(); +} + +//---------------------------------------------------- + +void CNetGame::ResetGangZonePool() +{ + if(m_pPools->pGangZonePool) { + delete m_pPools->pGangZonePool; + } + m_pPools->pGangZonePool = new CGangZonePool(); +} + +//----------------------------------------------------------- + +void CNetGame::ResetActorPool() +{ + if (m_pPools->pActorPool) { + delete m_pPools->pActorPool; + } + m_pPools->pActorPool = new CActorPool(); } //----------------------------------------------------------- diff --git a/saco/net/netgame.h b/saco/net/netgame.h index 3b00f06..4391d0a 100644 --- a/saco/net/netgame.h +++ b/saco/net/netgame.h @@ -1,79 +1,153 @@ #pragma once +#define GAMESTATE_CONNECTED 5 +#define GAMESTATE_AWAIT_JOIN 6 + +#define GAMESTATE_CONNECTING 2 #define GAMESTATE_WAIT_CONNECT 1 +#define NETMODE_NORMAL_ONFOOT_SENDRATE 30 +#define NETMODE_NORMAL_INCAR_SENDRATE 30 +#define NETMODE_FIRING_SENDRATE 30 +#define NETMODE_SEND_MULTIPLIER 2 + struct struc_41 { - char field_0; - int field_1; - char _gap5[17]; - float field_16; - char field_1A; - char _gap1B[4]; - char field_1F; - char field_20; - char field_21; - char field_22; - int field_23; - float field_27; - char _gap2B; - char field_2C; - char field_2D; - char field_2E; - char field_2F; - char _gap30[10]; + bool bUseCJWalk; + int iDeathDropMoney; + float WorldBounds[4]; + bool bAllowWeapons; + float fGravity; + bool bDisableEnterExits; + BOOL bVehicleFriendlyFire; + BYTE byteHoldTime; + char field_20; + bool bZoneNames; + char field_22; + int iSpawnsAvailable; + float fNameTagDrawDistance; + bool bManualVehicleEngineAndLights; + BYTE byteWorldTime; + BYTE byteWorldMinute; + BYTE byteWeather; + bool bNameTagLOS; + int iShowPlayerMarkers; + float fGlobalChatRadius; + bool bShowNameTags; + bool bLimitGlobalChatRadius; }; -typedef struct _NETGAME_POOLS { - CVehiclePool *pVehiclePool; - CPlayerPool *pPlayerPool; - CPickupPool *pPickupPool; - CObjectPool *pObjectPool; - CActorPool *pActorPool; - CGangZonePool *pGangZonePool; - CLabelPool *pLabelPool; - CTextDrawPool *pTextDrawPool; - CMenuPool *pMenuPool; +typedef struct _NETGAME_POOLS +{ + CVehiclePool *pVehiclePool; + CPlayerPool *pPlayerPool; + CPickupPool *pPickupPool; + CObjectPool *pObjectPool; + CActorPool *pActorPool; + CGangZonePool *pGangZonePool; + CLabelPool *pLabelPool; + CTextDrawPool *pTextDrawPool; + CMenuPool *pMenuPool; } NETGAME_POOLS; -class CNetGame // size: 994 -{ -private: +//---------------------------------------------------- +class CNetGame +{ +//private: +public: + // Should always be the first one in class (for the sake of ACGhost) RakClientInterface *m_pRakClient; + char _gap4[44]; + + char m_szHostOrIp[257]; + char m_szHostName[257]; + char field_232; + char field_233; + bool m_bPlayerNameTagStatus; + int m_iPort; + int field_239; + DWORD m_dwMapIcon[100]; + int m_iGameState; + DWORD m_dwLastConnectAttempt; + struc_41 *field_3D5; + char field_3D9; + + char _gap3DA[4]; + + NETGAME_POOLS *m_pPools; + void UpdateNetwork(); - char _gap4[44]; - char m_szHostOrIp[257]; - char m_szHostName[257]; - char field_232; - char field_233; - char field_234; - int m_iPort; - int field_239; - DWORD m_dwMapIcon[100]; - int m_iGameState; - int field_3D1; - struc_41 *field_3D5; - char field_3D9; - char _gap3DA[4]; - NETGAME_POOLS* m_pPools; + // Packet handlers + void Packet_AimSync(Packet *p); + void Packet_PlayerSync(Packet *p); + void Packet_VehicleSync(Packet *p); + void Packet_PassengerSync(Packet *p); + void Packet_UnoccupiedSync(Packet *p); + void Packet_WeaponShotSync(Packet *p); + void Packet_ConnectionSucceeded(Packet *p); + void Packet_RSAPublicKeyMismatch(Packet* packet); + void Packet_ConnectionBanned(Packet* packet); + void Packet_ConnectionRequestAccepted(Packet* packet); + void Packet_NoFreeIncomingConnections(Packet* packet); + void Packet_DisconnectionNotification(Packet* packet); + void Packet_ConnectionLost(Packet* packet); + void Packet_InvalidPassword(Packet* packet); + void Packet_ModifiedPacket(Packet* packet); + void Packet_ConnectAttemptFailed(Packet* packet); + void Packet_TrailerSync(Packet *p); + void FUNC_10009F10(Packet *p); + void FUNC_1000A100(Packet *p); public: CNetGame(PCHAR szHostOrIp,int iPort,PCHAR szPlayerName,PCHAR szPass); + ~CNetGame(); - void Process(); + void PrintWelcomeMessage(); + void HandleConnectingState(); + void ShowWaitingScreen(); void InitPools(); + void ResetAllPools(); - DWORD GetTime(); + int GetGameState() { return m_iGameState; }; + void SetGameState(int iGameState) { m_iGameState = iGameState; }; CPlayerPool * GetPlayerPool() { return m_pPools->pPlayerPool; }; + CVehiclePool * GetVehiclePool() { return m_pPools->pVehiclePool; }; + CActorPool * GetActorPool() { return m_pPools->pActorPool; }; + CPickupPool * GetPickupPool() { return m_pPools->pPickupPool; }; + CObjectPool * GetObjectPool() { return m_pPools->pObjectPool; }; + CMenuPool * GetMenuPool() { return m_pPools->pMenuPool; }; + CLabelPool * GetLabelPool() { return m_pPools->pLabelPool; }; + CTextDrawPool * GetTextDrawPool() { return m_pPools->pTextDrawPool; }; + CGangZonePool * GetGangZonePool() { return m_pPools->pGangZonePool; }; + RakClientInterface * GetRakClient() { return m_pRakClient; }; + + void InitGameLogic(); + void Process(); + + void UpdatePlayerScoresAndPings(); + void ResetVehiclePool(); + void ResetPlayerPool(); + void ResetPickupPool(); + void ResetObjectPool(); + void ResetMenuPool(); + void ResetLabelPool(); + void ResetTextDrawPool(); + void ResetGangZonePool(); + void ResetActorPool(); void ResetMapIcons(); void SetMapIcon(BYTE byteIndex, float fX, float fY, float fZ, BYTE byteIcon, DWORD dwColor, int iStyle); void DisableMapIcon(BYTE byteIndex); + + int GetTime(); + void TogglePlayerTagStatus(); }; + +//---------------------------------------------------- diff --git a/saco/net/netplayer.cpp b/saco/net/netplayer.cpp new file mode 100644 index 0000000..8889fa8 --- /dev/null +++ b/saco/net/netplayer.cpp @@ -0,0 +1,22 @@ + +#include "../main.h" + +//---------------------------------------------------- + +CNetPlayer::CNetPlayer(PCHAR szPlayerName, BOOL bIsNPC) +{ + m_bIsNPC = bIsNPC; + field_C = 0; + field_4 = 0; + m_PlayerName = szPlayerName; + m_pRemotePlayer = new CRemotePlayer(); +} + +//---------------------------------------------------- + +CNetPlayer::~CNetPlayer() +{ + SAFE_DELETE(m_pRemotePlayer); +} + +//---------------------------------------------------- diff --git a/saco/net/netplayer.h b/saco/net/netplayer.h new file mode 100644 index 0000000..a0cab8f --- /dev/null +++ b/saco/net/netplayer.h @@ -0,0 +1,23 @@ + +#pragma once + +#include + +//---------------------------------------------------- + +class CNetPlayer +{ +public: + //char _gap0[48]; + char _gap0[4]; + int field_4; + BOOL m_bIsNPC; + int field_C; + CRemotePlayer *m_pRemotePlayer; + std::string m_PlayerName; + + CNetPlayer(PCHAR szPlayerName, BOOL bIsNPC); + ~CNetPlayer(); +}; + +//---------------------------------------------------- diff --git a/saco/net/netrpc.cpp b/saco/net/netrpc.cpp index 7c98a84..e27d84b 100644 --- a/saco/net/netrpc.cpp +++ b/saco/net/netrpc.cpp @@ -1,6 +1,10 @@ #include "../main.h" +extern CGame *pGame; + +//---------------------------------------------------- + // TODO: these RPCs void Unk22(RPCParameters *rpcParams) {} void Unk24(RPCParameters *rpcParams) {} @@ -17,13 +21,12 @@ void GameModeRestart(RPCParameters *rpcParams) {} void ConnectionRejected(RPCParameters *rpcParams) {} void ClientMessage(RPCParameters *rpcParams) {} void WorldTime(RPCParameters *rpcParams) {} -void Unk5F(RPCParameters *rpcParams) {} -void Unk3F(RPCParameters *rpcParams) {} -void Unk97(RPCParameters *rpcParams) {} +void Pickup(RPCParameters *rpcParams) {} +void DestroyPickup(RPCParameters *rpcParams) {} +void DestroyWeaponPickup(RPCParameters *rpcParams) {} void ScmEvent(RPCParameters *rpcParams) {} void Weather(RPCParameters *rpcParams) {} -void Unk1D(RPCParameters *rpcParams) {} -void Unk1E(RPCParameters *rpcParams) {} +void ToggleClock(RPCParameters *rpcParams) {} void Unk3C(RPCParameters *rpcParams) {} void WorldPlayerAdd(RPCParameters *rpcParams) {} void WorldPlayerDeath(RPCParameters *rpcParams) {} @@ -51,6 +54,22 @@ void UnkAC(RPCParameters *rpcParams) {} //---------------------------------------------------- +void SetTimeEx(RPCParameters *rpcParams) +{ + PCHAR Data = reinterpret_cast(rpcParams->input); + int iBitLength = rpcParams->numberOfBitsOfData; + //PlayerID sender = rpcParams->sender; + + RakNet::BitStream bsData(Data,(iBitLength/8)+1,false); + BYTE byteHour; + BYTE byteMinute; + bsData.Read(byteHour); + bsData.Read(byteMinute); + pGame->SetWorldTime(byteHour, byteMinute); +} + +//---------------------------------------------------- + void RegisterRPCs(RakClientInterface * pRakClient) { REGISTER_STATIC_RPC(pRakClient,Unk22); @@ -68,13 +87,13 @@ void RegisterRPCs(RakClientInterface * pRakClient) REGISTER_STATIC_RPC(pRakClient,ConnectionRejected); REGISTER_STATIC_RPC(pRakClient,ClientMessage); REGISTER_STATIC_RPC(pRakClient,WorldTime); - REGISTER_STATIC_RPC(pRakClient,Unk5F); - REGISTER_STATIC_RPC(pRakClient,Unk3F); - REGISTER_STATIC_RPC(pRakClient,Unk97); + REGISTER_STATIC_RPC(pRakClient,Pickup); + REGISTER_STATIC_RPC(pRakClient,DestroyPickup); + REGISTER_STATIC_RPC(pRakClient,DestroyWeaponPickup); REGISTER_STATIC_RPC(pRakClient,ScmEvent); REGISTER_STATIC_RPC(pRakClient,Weather); - REGISTER_STATIC_RPC(pRakClient,Unk1D); - REGISTER_STATIC_RPC(pRakClient,Unk1E); + REGISTER_STATIC_RPC(pRakClient,SetTimeEx); + REGISTER_STATIC_RPC(pRakClient,ToggleClock); REGISTER_STATIC_RPC(pRakClient,Unk3C); REGISTER_STATIC_RPC(pRakClient,WorldPlayerAdd); REGISTER_STATIC_RPC(pRakClient,WorldPlayerDeath); @@ -136,13 +155,13 @@ void UnRegisterRPCs(RakClientInterface * pRakClient) UNREGISTER_STATIC_RPC(pRakClient,ConnectionRejected); UNREGISTER_STATIC_RPC(pRakClient,ClientMessage); UNREGISTER_STATIC_RPC(pRakClient,WorldTime); - UNREGISTER_STATIC_RPC(pRakClient,Unk5F); - UNREGISTER_STATIC_RPC(pRakClient,Unk3F); - UNREGISTER_STATIC_RPC(pRakClient,Unk97); + UNREGISTER_STATIC_RPC(pRakClient,Pickup); + UNREGISTER_STATIC_RPC(pRakClient,DestroyPickup); + UNREGISTER_STATIC_RPC(pRakClient,DestroyWeaponPickup); UNREGISTER_STATIC_RPC(pRakClient,ScmEvent); UNREGISTER_STATIC_RPC(pRakClient,Weather); - UNREGISTER_STATIC_RPC(pRakClient,Unk1D); - UNREGISTER_STATIC_RPC(pRakClient,Unk1E); + UNREGISTER_STATIC_RPC(pRakClient,SetTimeEx); + UNREGISTER_STATIC_RPC(pRakClient,ToggleClock); UNREGISTER_STATIC_RPC(pRakClient,EditAttachedObject); UNREGISTER_STATIC_RPC(pRakClient,EditObject); UNREGISTER_STATIC_RPC(pRakClient,SelectObject); diff --git a/saco/net/objectpool.cpp b/saco/net/objectpool.cpp index e851fcc..b8ea162 100644 --- a/saco/net/objectpool.cpp +++ b/saco/net/objectpool.cpp @@ -5,8 +5,13 @@ CObjectPool::CObjectPool() { for(WORD wObjectID = 0; wObjectID < MAX_OBJECTS; wObjectID++) { - field_4[wObjectID] = 0; - field_FA4[wObjectID] = 0; + m_bObjectSlotState[wObjectID] = FALSE; + m_pObjects[wObjectID] = NULL; } field_0 = 0; }; + +void CObjectPool::UpdatePoolSize() +{ + int iNewSize = 0; +} \ No newline at end of file diff --git a/saco/net/objectpool.h b/saco/net/objectpool.h index c0b04f7..e3dfa16 100644 --- a/saco/net/objectpool.h +++ b/saco/net/objectpool.h @@ -5,9 +5,11 @@ class CObjectPool { private: int field_0; - int field_4[MAX_OBJECTS]; - int field_FA4[MAX_OBJECTS]; + BOOL m_bObjectSlotState[MAX_OBJECTS]; + CObject *m_pObjects[MAX_OBJECTS]; + public: CObjectPool(); + void UpdatePoolSize(); }; diff --git a/saco/net/pickuppool.cpp b/saco/net/pickuppool.cpp index 2ca312d..5a463c1 100644 --- a/saco/net/pickuppool.cpp +++ b/saco/net/pickuppool.cpp @@ -3,6 +3,20 @@ //---------------------------------------------------- +/*CPickupPool::CPickupPool() +{ + memset(field_F004, 0, sizeof(field_F004)); + field_0 = 0; + for (int i = 0; i < MAX_PICKUPS; i++) + { + m_dwHnd[i] = NULL; + field_8004[i] = 0; + field_4004[i] = -1; + } +}*/ + +//---------------------------------------------------- + CPickupPool::~CPickupPool() { for(int i = 0; i < MAX_PICKUPS; i++) diff --git a/saco/net/playerpool.cpp b/saco/net/playerpool.cpp index aed84e5..f09d23c 100644 --- a/saco/net/playerpool.cpp +++ b/saco/net/playerpool.cpp @@ -6,15 +6,93 @@ CPlayerPool::CPlayerPool() { // loop through and initialize all net players to null and slot states to false - for(PLAYERID playerId = 0; playerId < MAX_PLAYERS; playerId++) { - field_1F8A[playerId] = 0; - field_2A[playerId] = 0; + PLAYERID playerId = 0; + while(playerId < MAX_PLAYERS) { + m_pPlayers[playerId] = NULL; + m_bPlayerSlotState[playerId] = FALSE; + playerId++; } m_pLocalPlayer = new CLocalPlayer(); field_0 = 0; field_22 = 0; - field_4 = 0; + m_LocalPlayerID = 0; field_2F3A = 0; } //---------------------------------------------------- + +CPlayerPool::~CPlayerPool() +{ + delete m_pLocalPlayer; + m_pLocalPlayer = NULL; + + for(PLAYERID playerId = 0; playerId < MAX_PLAYERS; playerId++) { + Delete(playerId,0); + } +} + +//---------------------------------------------------- + +BOOL CPlayerPool::New(PLAYERID playerId, PCHAR szPlayerName, BOOL bIsNPC) +{ + CNetPlayer *pNetPlayer = new CNetPlayer(szPlayerName, bIsNPC); + + if(playerId < MAX_PLAYERS && (m_pPlayers[playerId] = pNetPlayer) != NULL) + { + m_pPlayers[playerId]->m_pRemotePlayer->SetID(playerId); + // TODO: CPlayerPool::New + m_bPlayerSlotState[playerId] = TRUE; + RecalcPoolSize(); + return TRUE; + } + else + { + return FALSE; + } +} + +//---------------------------------------------------- + +BOOL CPlayerPool::Delete(PLAYERID playerId, BYTE byteReason) +{ + if(!GetSlotState(playerId) || !m_pPlayers[playerId]) + { + return FALSE; // Player already deleted or not used. + } + + if (GetLocalPlayer() && GetLocalPlayer()->IsSpectating() && GetLocalPlayer()->m_SpectateID == playerId) { + GetLocalPlayer()->ToggleSpectating(FALSE); + } + + m_bPlayerSlotState[playerId] = FALSE; + delete m_pPlayers[playerId]; + m_pPlayers[playerId] = NULL; + + RecalcPoolSize(); + + return TRUE; +} + +//---------------------------------------------------- + +void CPlayerPool::RecalcPoolSize() +{ + int iNewIndex = 0; + int i = 0; + + do + { + if(m_bPlayerSlotState[i]) + iNewIndex = i; + if(m_bPlayerSlotState[i+1]) + iNewIndex = i+1; + if(m_bPlayerSlotState[i+2]) + iNewIndex = i+2; + if(m_bPlayerSlotState[i+3]) + iNewIndex = i+3; + i += 4; + } + while(i < MAX_PLAYERS); + + field_2F3A = iNewIndex; +} diff --git a/saco/net/playerpool.h b/saco/net/playerpool.h index ac240ea..03d4fae 100644 --- a/saco/net/playerpool.h +++ b/saco/net/playerpool.h @@ -3,28 +3,59 @@ #include +#define INVALID_PLAYER_ID 0xFFFF +#define NO_TEAM 255 + //---------------------------------------------------- class CPlayerPool { private: + int field_0; - short field_4; + PLAYERID m_LocalPlayerID; std::string field_6; int field_22; CLocalPlayer *m_pLocalPlayer; - int field_2A[MAX_PLAYERS]; + BOOL m_bPlayerSlotState[MAX_PLAYERS]; char _gapFDA[4016]; - int field_1F8A[MAX_PLAYERS]; + CNetPlayer *m_pPlayers[MAX_PLAYERS]; int field_2F3A; public: + void SetLocalPlayerName(PCHAR szName) { field_6 = szName; }; + PCHAR GetLocalPlayerName() { return (PCHAR)field_6.c_str(); }; + CLocalPlayer * GetLocalPlayer() { return m_pLocalPlayer; }; + BOOL New(PLAYERID playerId, PCHAR szPlayerName, BOOL bIsNPC); + BOOL Delete(PLAYERID playerId, BYTE byteReason); + + void RecalcPoolSize(); + + void SetAt(PLAYERID playerId, CNetPlayer *pPlayer) { + if(playerId >= MAX_PLAYERS) return; + m_pPlayers[playerId] = pPlayer; + }; + + CNetPlayer* GetAt(PLAYERID playerId) { + if(playerId >= MAX_PLAYERS || m_pPlayers[playerId] == NULL) { return NULL; } + return m_pPlayers[playerId]; + }; + + // Find out if the slot is inuse. + BOOL GetSlotState(PLAYERID playerId) { + if(playerId >= MAX_PLAYERS) { return FALSE; } + return m_bPlayerSlotState[playerId]; + }; + + PLAYERID GetLocalPlayerID() { return m_LocalPlayerID; }; + CPlayerPool(); + ~CPlayerPool(); }; //---------------------------------------------------- diff --git a/saco/net/remoteplayer.cpp b/saco/net/remoteplayer.cpp index 8eb3686..f6eb267 100644 --- a/saco/net/remoteplayer.cpp +++ b/saco/net/remoteplayer.cpp @@ -12,14 +12,14 @@ CRemotePlayer::CRemotePlayer() { field_1E7 = 0; field_10A = 0; - field_1E5 = -1; - field_1DD = 0; + m_PlayerID = INVALID_PLAYER_ID; + m_pPlayerPed = NULL; field_1B8 = 0; - field_109 = -1; + field_109 = 255; field_4 = 1; field_0 = 0; field_8 = 0; - field_1F9 = 0; + m_dwMarkerID = 0; field_C = 0; field_10C = 0; field_1C1 = 0; @@ -31,6 +31,25 @@ CRemotePlayer::CRemotePlayer() //---------------------------------------------------- +CRemotePlayer::~CRemotePlayer() +{ + if(m_dwMarkerID) + { + pGame->DisableMarker(m_dwMarkerID); + m_dwMarkerID = 0; + } + + field_1E9 = 0; + + if(m_pPlayerPed) + { + pGame->DeletePlayer(m_pPlayerPed); + m_pPlayerPed = NULL; + } +} + +//---------------------------------------------------- + void CRemotePlayer::ResetAllSyncAttributes() { field_1E7 = 0; @@ -50,10 +69,10 @@ void CRemotePlayer::ResetAllSyncAttributes() memset(field_AD, 0, sizeof(field_AD)); memset(field_8E, 0, sizeof(field_8E)); memset(field_1C9, 0, sizeof(field_1C9)); - if(field_1F9) + if(m_dwMarkerID) { - pGame->DisableMarker(field_1F9); - field_1F9 = 0; + pGame->DisableMarker(m_dwMarkerID); + m_dwMarkerID = 0; } field_1E9 = 0; if(pNetGame) diff --git a/saco/net/remoteplayer.h b/saco/net/remoteplayer.h index d771347..5d94b82 100644 --- a/saco/net/remoteplayer.h +++ b/saco/net/remoteplayer.h @@ -6,7 +6,8 @@ #pragma pack(1) class CRemotePlayer { -private: +//private: +public: //char _gap0[509]; int field_0; int field_4; @@ -22,7 +23,7 @@ private: char field_8E[31]; char field_AD[24]; char field_C5[68]; - char field_109; + BYTE field_109; char field_10A; char field_10B; int field_10C; @@ -41,19 +42,24 @@ private: char field_1C9[12]; DWORD field_1D5; DWORD field_1D9; - int field_1DD; + CPlayerPed *m_pPlayerPed; int field_1E1; - short field_1E5; + PLAYERID m_PlayerID; short field_1E7; int field_1E9; int field_1ED; int field_1F1; int field_1F5; - int field_1F9; + DWORD m_dwMarkerID; //int field_1F9; public: CRemotePlayer(); + ~CRemotePlayer(); + + void SetID(PLAYERID playerId) { m_PlayerID = playerId; }; + PLAYERID GetID() { return m_PlayerID; }; + CPlayerPed * GetPlayerPed() { return m_pPlayerPed; }; void ResetAllSyncAttributes(); diff --git a/saco/net/scriptrpc.cpp b/saco/net/scriptrpc.cpp index 130ed21..d6706c8 100644 --- a/saco/net/scriptrpc.cpp +++ b/saco/net/scriptrpc.cpp @@ -1,6 +1,13 @@ #include "../main.h" +using namespace RakNet; +extern CNetGame* pNetGame; +extern CGame * pGame; + +//---------------------------------------------------- + +// TODO: These script RPCs void ScrUnkA7(RPCParameters *rpcParams) {} void ScrUnk38(RPCParameters *rpcParams) {} void ScrUnk90(RPCParameters *rpcParams) {} @@ -53,7 +60,6 @@ void ScrUnk70(RPCParameters *rpcParams) {} void ScrSetSpawnInfo(RPCParameters *rpcParams) {} void ScrUnk45(RPCParameters *rpcParams) {} void ScrUnk99(RPCParameters *rpcParams) {} -void ScrUnk0B(RPCParameters *rpcParams) {} void ScrSetPlayerPos(RPCParameters *rpcParams) {} void ScrUnk0D(RPCParameters *rpcParams) {} void ScrUnk0E(RPCParameters *rpcParams) {} @@ -61,13 +67,10 @@ void ScrPutPlayerInVehicle(RPCParameters *rpcParams) {} void ScrRemovePlayerFromVehicle(RPCParameters *rpcParams) {} void ScrSetPlayerColor(RPCParameters *rpcParams) {} void ScrDisplayGameText(RPCParameters *rpcParams) {} -void ScrUnk9D(RPCParameters *rpcParams) {} -void ScrUnk9E(RPCParameters *rpcParams) {} void ScrSetInterior(RPCParameters *rpcParams) {} void ScrUnk9F(RPCParameters *rpcParams) {} void ScrUnkA0(RPCParameters *rpcParams) {} void ScrUnkA1(RPCParameters *rpcParams) {} -void ScrUnkA2(RPCParameters *rpcParams) {} void ScrUnk0F(RPCParameters *rpcParams) {} void ScrUnk10(RPCParameters *rpcParams) {} void ScrUnk11(RPCParameters *rpcParams) {} @@ -104,6 +107,82 @@ void ScrHideMenu(RPCParameters *rpcParams) {} //---------------------------------------------------- +void ScrSetPlayerName(RPCParameters *rpcParams) +{ + PCHAR Data = reinterpret_cast(rpcParams->input); + int iBitLength = rpcParams->numberOfBitsOfData; + PlayerID sender = rpcParams->sender; + + RakNet::BitStream bsData(Data,(iBitLength/8)+1,false); + + CPlayerPool *pPlayerPool = pNetGame->GetPlayerPool(); + + PLAYERID playerId; + BYTE byteNickLen; + char szNewName[MAX_PLAYER_NAME+1]; + BYTE byteSuccess; + + bsData.Read(playerId); + bsData.Read(byteNickLen); + + if(byteNickLen > MAX_PLAYER_NAME) return; + + bsData.Read(szNewName, byteNickLen); + bsData.Read(byteSuccess); + + szNewName[byteNickLen] = '\0'; +} + +//---------------------------------------------------- + +void ScrSetCameraPos(RPCParameters *rpcParams) +{ + PCHAR Data = reinterpret_cast(rpcParams->input); + int iBitLength = rpcParams->numberOfBitsOfData; + PlayerID sender = rpcParams->sender; + + RakNet::BitStream bsData(Data,(iBitLength/8)+1,false); + VECTOR vecPos; + bsData.Read(vecPos.X); + bsData.Read(vecPos.Y); + bsData.Read(vecPos.Z); + pGame->GetCamera()->SetPosition(vecPos.X,vecPos.Y,vecPos.Z,0.0f,0.0f,0.0f); +} + +//---------------------------------------------------- + +void ScrSetCameraLookAt(RPCParameters *rpcParams) +{ + PCHAR Data = reinterpret_cast(rpcParams->input); + int iBitLength = rpcParams->numberOfBitsOfData; + PlayerID sender = rpcParams->sender; + + RakNet::BitStream bsData(Data,(iBitLength/8)+1,false); + VECTOR vecPos; + BYTE byteType; + bsData.Read(vecPos.X); + bsData.Read(vecPos.Y); + bsData.Read(vecPos.Z); + bsData.Read(byteType); + if(byteType < 1 || byteType > 2) { + byteType = 2; + } + pGame->GetCamera()->LookAtPoint(vecPos.X,vecPos.Y,vecPos.Z,byteType); +} + +//---------------------------------------------------- + +void ScrSetCameraBehindPlayer(RPCParameters *rpcParams) +{ + PCHAR Data = reinterpret_cast(rpcParams->input); + int iBitLength = rpcParams->numberOfBitsOfData; + PlayerID sender = rpcParams->sender; + + pGame->GetCamera()->SetBehindPlayer(); +} + +//---------------------------------------------------- + void RegisterScriptRPCs(RakClientInterface* pRakClient) { REGISTER_STATIC_RPC(pRakClient, ScrUnkA7); @@ -153,7 +232,7 @@ void RegisterScriptRPCs(RakClientInterface* pRakClient) REGISTER_STATIC_RPC(pRakClient, ScrSetSpawnInfo); REGISTER_STATIC_RPC(pRakClient, ScrUnk45); REGISTER_STATIC_RPC(pRakClient, ScrUnk99); - REGISTER_STATIC_RPC(pRakClient, ScrUnk0B); + REGISTER_STATIC_RPC(pRakClient, ScrSetPlayerName); REGISTER_STATIC_RPC(pRakClient, ScrSetPlayerPos); REGISTER_STATIC_RPC(pRakClient, ScrUnk0D); REGISTER_STATIC_RPC(pRakClient, ScrUnk0E); @@ -161,13 +240,13 @@ void RegisterScriptRPCs(RakClientInterface* pRakClient) REGISTER_STATIC_RPC(pRakClient, ScrRemovePlayerFromVehicle); REGISTER_STATIC_RPC(pRakClient, ScrSetPlayerColor); REGISTER_STATIC_RPC(pRakClient, ScrDisplayGameText); - REGISTER_STATIC_RPC(pRakClient, ScrUnk9D); - REGISTER_STATIC_RPC(pRakClient, ScrUnk9E); REGISTER_STATIC_RPC(pRakClient, ScrSetInterior); + REGISTER_STATIC_RPC(pRakClient, ScrSetCameraPos); + REGISTER_STATIC_RPC(pRakClient, ScrSetCameraLookAt); REGISTER_STATIC_RPC(pRakClient, ScrUnk9F); REGISTER_STATIC_RPC(pRakClient, ScrUnkA0); REGISTER_STATIC_RPC(pRakClient, ScrUnkA1); - REGISTER_STATIC_RPC(pRakClient, ScrUnkA2); + REGISTER_STATIC_RPC(pRakClient, ScrSetCameraBehindPlayer); REGISTER_STATIC_RPC(pRakClient, ScrUnk0F); REGISTER_STATIC_RPC(pRakClient, ScrUnk10); REGISTER_STATIC_RPC(pRakClient, ScrUnk11); @@ -260,7 +339,7 @@ void UnRegisterScriptRPCs(RakClientInterface* pRakClient) UNREGISTER_STATIC_RPC(pRakClient, ScrUnk2B); UNREGISTER_STATIC_RPC(pRakClient, ScrSetSpawnInfo); UNREGISTER_STATIC_RPC(pRakClient, ScrUnk45); - UNREGISTER_STATIC_RPC(pRakClient, ScrUnk0B); + UNREGISTER_STATIC_RPC(pRakClient, ScrSetPlayerName); UNREGISTER_STATIC_RPC(pRakClient, ScrUnk99); UNREGISTER_STATIC_RPC(pRakClient, ScrSetPlayerPos); UNREGISTER_STATIC_RPC(pRakClient, ScrUnk0D); @@ -269,13 +348,13 @@ void UnRegisterScriptRPCs(RakClientInterface* pRakClient) UNREGISTER_STATIC_RPC(pRakClient, ScrRemovePlayerFromVehicle); UNREGISTER_STATIC_RPC(pRakClient, ScrSetPlayerColor); UNREGISTER_STATIC_RPC(pRakClient, ScrDisplayGameText); - UNREGISTER_STATIC_RPC(pRakClient, ScrUnk9D); - UNREGISTER_STATIC_RPC(pRakClient, ScrUnk9E); UNREGISTER_STATIC_RPC(pRakClient, ScrSetInterior); + UNREGISTER_STATIC_RPC(pRakClient, ScrSetCameraPos); + UNREGISTER_STATIC_RPC(pRakClient, ScrSetCameraLookAt); UNREGISTER_STATIC_RPC(pRakClient, ScrUnk9F); UNREGISTER_STATIC_RPC(pRakClient, ScrUnkA0); UNREGISTER_STATIC_RPC(pRakClient, ScrUnkA1); - UNREGISTER_STATIC_RPC(pRakClient, ScrUnkA2); + UNREGISTER_STATIC_RPC(pRakClient, ScrSetCameraBehindPlayer); UNREGISTER_STATIC_RPC(pRakClient, ScrUnk0F); UNREGISTER_STATIC_RPC(pRakClient, ScrUnk10); UNREGISTER_STATIC_RPC(pRakClient, ScrUnk11); diff --git a/saco/net/textdrawpool.cpp b/saco/net/textdrawpool.cpp index 59e68e6..0dd5f6e 100644 --- a/saco/net/textdrawpool.cpp +++ b/saco/net/textdrawpool.cpp @@ -9,11 +9,54 @@ CTextDrawPool::CTextDrawPool() { int x=0; while(x!=MAX_TEXT_DRAWS) { - field_2400[x] = 0; - field_0[x] = 0; + m_pTextDraw[x] = NULL; + m_bSlotState[x] = FALSE; x++; } unnamed_100B2AF0(); } //---------------------------------------------------- + +CTextDrawPool::~CTextDrawPool() +{ + int x=0; + while(x != MAX_TEXT_DRAWS) { + if(m_pTextDraw[x]) { + delete m_pTextDraw[x]; + m_pTextDraw[x] = NULL; + m_bSlotState[x] = FALSE; + } + x++; + } +} + +//---------------------------------------------------- + +CTextDraw* CTextDrawPool::New(WORD wText, TEXT_DRAW_TRANSMIT *TextDrawTransmit, PCHAR szText) +{ + if(m_pTextDraw[wText]) Delete(wText); + + CTextDraw* pTextDraw = new CTextDraw(TextDrawTransmit, szText); + + if(pTextDraw) + { + m_pTextDraw[wText] = pTextDraw; + m_bSlotState[wText] = TRUE; + return pTextDraw; + } + return NULL; +} + +//---------------------------------------------------- + +void CTextDrawPool::Delete(WORD wText) +{ + if(m_pTextDraw[wText]) { + delete m_pTextDraw[wText]; + m_pTextDraw[wText] = NULL; + m_bSlotState[wText] = FALSE; + } +} + +//---------------------------------------------------- diff --git a/saco/net/textdrawpool.h b/saco/net/textdrawpool.h index 6a89a0a..4526959 100644 --- a/saco/net/textdrawpool.h +++ b/saco/net/textdrawpool.h @@ -6,10 +6,14 @@ class CTextDrawPool { private: - int field_0[MAX_TEXT_DRAWS]; - int field_2400[MAX_TEXT_DRAWS]; + BOOL m_bSlotState[MAX_TEXT_DRAWS]; + CTextDraw *m_pTextDraw[MAX_TEXT_DRAWS]; public: CTextDrawPool(); + ~CTextDrawPool(); + + CTextDraw * New(WORD wText, TEXT_DRAW_TRANSMIT *TextDrawTransmit, PCHAR szText); + void Delete(WORD wText); }; //---------------------------------------------------- diff --git a/saco/net/vehiclepool.cpp b/saco/net/vehiclepool.cpp index 1a28c23..36cdaff 100644 --- a/saco/net/vehiclepool.cpp +++ b/saco/net/vehiclepool.cpp @@ -1,5 +1,9 @@ #include "../main.h" +#include "../game/util.h" + +extern CGame *pGame; +extern CChatWindow *pChatWindow; //---------------------------------------------------- @@ -7,14 +11,196 @@ CVehiclePool::CVehiclePool() { // loop through and initialize all vehicle properties to 0 for(VEHICLEID VehicleID = 0; VehicleID < MAX_VEHICLES; VehicleID++) { - field_3074[VehicleID] = 0; - field_1134[VehicleID] = 0; - field_4FB4[VehicleID] = 0; + m_bVehicleSlotState[VehicleID] = FALSE; + m_pVehicles[VehicleID] = NULL; + m_pGTAVehicles[VehicleID] = NULL; field_9DD4[VehicleID] = GetTickCount(); } - memset(field_FA4, 0, sizeof(field_FA4)); + memset(&m_bWaitingSlotState[0],0,MAX_VEHICLE_WAITING_SLOTS * sizeof(BOOL)); field_0 = 0; field_17894 = 1; } //---------------------------------------------------- + +CVehiclePool::~CVehiclePool() +{ + for(VEHICLEID VehicleID = 0; VehicleID < MAX_VEHICLES; VehicleID++) { + Delete(VehicleID); + } +} + +//---------------------------------------------------- + +BOOL CVehiclePool::New(NEW_VEHICLE *pNewVehicle) +{ + if(m_pVehicles[pNewVehicle->VehicleId] != NULL) { + pChatWindow->AddDebugMessage("Warning: vehicle %u was not deleted",pNewVehicle->VehicleId); + Delete(pNewVehicle->VehicleId); + } + + // TODO: CVehiclePool::New .text:1001F080 + + return FALSE; +} + +//---------------------------------------------------- + +BOOL CVehiclePool::Delete(VEHICLEID VehicleID) +{ + if(!GetSlotState(VehicleID) || !m_pVehicles[VehicleID]) + { + return FALSE; // Vehicle already deleted or not used. + } + + m_bVehicleSlotState[VehicleID] = FALSE; + delete m_pVehicles[VehicleID]; + m_pVehicles[VehicleID] = NULL; + m_pGTAVehicles[VehicleID] = 0; + + // TODO: CVehiclePool::Delete .text:1001EA80 + + return TRUE; +} + +//---------------------------------------------------- + + + +//---------------------------------------------------- + +VEHICLEID CVehiclePool::FindIDFromGtaPtr(VEHICLE_TYPE * pGtaVehicle) +{ + int x=1; + + while(x<=field_0) { + if(pGtaVehicle == m_pGTAVehicles[x]) return x; + x++; + } + + return INVALID_VEHICLE_ID; +} + +//---------------------------------------------------- + +int CVehiclePool::FindGtaIDFromID(int iID) +{ + if(m_pGTAVehicles[iID]) { + return GamePool_Vehicle_GetIndex(m_pGTAVehicles[iID]); + } else { + return INVALID_VEHICLE_ID; + } +} + +//---------------------------------------------------- + +int CVehiclePool::FindGtaIDFromGtaPtr(VEHICLE_TYPE * pGtaVehicle) +{ + if(pGtaVehicle) { + return GamePool_Vehicle_GetIndex(pGtaVehicle); + } else { + return INVALID_VEHICLE_ID; + } +} + +//----------------------------------------------------------- + + +//---------------------------------------------------- + +void CVehiclePool::NotifyVehicleDeath(VEHICLEID VehicleID) +{ + { + RakNet::BitStream bsDeath; + bsDeath.Write(VehicleID); + + // CVehiclePool::NotifyVehicleDeath .text:1001F230 + } +} + +//---------------------------------------------------- + +int CVehiclePool::FindNearestToLocalPlayerPed() +{ + float fLeastDistance=10000.0f; + float fThisDistance; + VEHICLEID ClosestSoFar=INVALID_VEHICLE_ID; + + VEHICLEID x=0; + while(x <= field_0) { + if(GetSlotState(x) && m_bIsActive[x]) { + fThisDistance = m_pVehicles[x]->GetDistanceFromLocalPlayerPed(); + if(fThisDistance < fLeastDistance) { + fLeastDistance = fThisDistance; + ClosestSoFar = x; + } + } + x++; + } + + return ClosestSoFar; +} + +//---------------------------------------------------- + +void CVehiclePool::ProcessWaitingList() +{ + int x=0; + while(x!=MAX_VEHICLE_WAITING_SLOTS) { + if(m_bWaitingSlotState[x] && pGame->IsModelLoaded(m_NewVehicleWaiting[x].iVehicleType)) + { + New(&m_NewVehicleWaiting[x]); + + // TRAIN STUFF + if(m_NewVehicleWaiting[x].iVehicleType == TRAIN_FREIGHT_LOCO) { + m_NewVehicleWaiting[x].iVehicleType = TRAIN_FREIGHT; + + m_NewVehicleWaiting[x].VehicleId++; + New(&m_NewVehicleWaiting[x]); + + m_NewVehicleWaiting[x].VehicleId++; + New(&m_NewVehicleWaiting[x]); + + m_NewVehicleWaiting[x].VehicleId++; + New(&m_NewVehicleWaiting[x]); + } + + if(m_NewVehicleWaiting[x].iVehicleType == TRAIN_PASSENGER_LOCO) { + m_NewVehicleWaiting[x].iVehicleType = TRAIN_PASSENGER; + + m_NewVehicleWaiting[x].VehicleId++; + New(&m_NewVehicleWaiting[x]); + + m_NewVehicleWaiting[x].VehicleId++; + New(&m_NewVehicleWaiting[x]); + + m_NewVehicleWaiting[x].VehicleId++; + New(&m_NewVehicleWaiting[x]); + } + m_bWaitingSlotState[x] = FALSE; + } + x++; + } +} + +//---------------------------------------------------- + +void CVehiclePool::NewWhenModelLoaded(NEW_VEHICLE *pNewVehicle) +{ + // find a free slot + int x=0; + while(x!=MAX_VEHICLE_WAITING_SLOTS) { + if(m_bWaitingSlotState[x] == FALSE) break; + x++; + } + + if(x==MAX_VEHICLE_WAITING_SLOTS) { + pChatWindow->AddDebugMessage("All vehicle waiting slots are consumed!"); + return; + } + + m_bWaitingSlotState[x] = TRUE; + memcpy(&m_NewVehicleWaiting[x],pNewVehicle,sizeof(NEW_VEHICLE)); +} + +//---------------------------------------------------- diff --git a/saco/net/vehiclepool.h b/saco/net/vehiclepool.h index 2022a1f..a2111c8 100644 --- a/saco/net/vehiclepool.h +++ b/saco/net/vehiclepool.h @@ -1,29 +1,68 @@ #pragma once +#define INVALID_VEHICLE_ID 0xFFFF +#define MAX_VEHICLE_WAITING_SLOTS 100 + +#pragma pack(1) +typedef struct _NEW_VEHICLE { + //char _gap0[40]; + VEHICLEID VehicleId; + int iVehicleType; + char _gap6[34]; +} NEW_VEHICLE; + //---------------------------------------------------- class CVehiclePool { -public: +private: + + //char _gap0[96408]; int field_0; - - char _gap4[4000]; - - char field_FA4[400]; - int field_1134[MAX_VEHICLES]; - int field_3074[MAX_VEHICLES]; - int field_4FB4[MAX_VEHICLES]; - + NEW_VEHICLE m_NewVehicleWaiting[MAX_VEHICLE_WAITING_SLOTS]; + BOOL m_bWaitingSlotState[MAX_VEHICLE_WAITING_SLOTS]; + CVehicle *m_pVehicles[MAX_VEHICLES]; + BOOL m_bVehicleSlotState[MAX_VEHICLES]; + VEHICLE_TYPE *m_pGTAVehicles[MAX_VEHICLES]; char _gap6EF4[12000]; - - DWORD field_9DD4[MAX_VEHICLES]; - - char _gapBD14[48000]; - + int field_9DD4[2000]; + BOOL m_bIsActive[MAX_VEHICLES]; + char _gapDC54[40000]; int field_17894; +public: + CVehiclePool(); + ~CVehiclePool(); + + BOOL New(NEW_VEHICLE *pNewVehicle); + + BOOL Delete(VEHICLEID VehicleID); + + // Retrieve a vehicle + CVehicle* GetAt(VEHICLEID VehicleID) { + if(VehicleID >= MAX_VEHICLES || !m_bVehicleSlotState[VehicleID]) { return NULL; } + return m_pVehicles[VehicleID]; + }; + + // Find out if the slot is inuse. + BOOL GetSlotState(VEHICLEID VehicleID) { + if(VehicleID >= MAX_VEHICLES) { return FALSE; } + return m_bVehicleSlotState[VehicleID]; + }; + + VEHICLEID FindIDFromGtaPtr(VEHICLE_TYPE * pGtaVehicle); + + int FindGtaIDFromID(int iID); + int FindGtaIDFromGtaPtr(VEHICLE_TYPE * pGtaVehicle); + + void NotifyVehicleDeath(VEHICLEID VehicleID); + + int FindNearestToLocalPlayerPed(); + + void ProcessWaitingList(); + void NewWhenModelLoaded(NEW_VEHICLE *pNewVehicle); }; //---------------------------------------------------- diff --git a/saco/newplayertags.cpp b/saco/newplayertags.cpp index 3a5aa78..52e7fb1 100644 --- a/saco/newplayertags.cpp +++ b/saco/newplayertags.cpp @@ -1,6 +1,9 @@ #include "main.h" +extern CFontRender *pDefaultFont; +extern CDeathWindow *pDeathWindow; + HealthBarVertices1_s HealthBarBDRVertices1[4] = { //x y z rhw c {0.0f, 0.0f, 0.0f, 1.0f, D3DCOLOR_XRGB(0, 0, 0)}, @@ -76,6 +79,18 @@ void CNewPlayerTags::End() m_pStates->Apply(); } +void CNewPlayerTags::SpriteBegin() +{ + if(m_pSprite) + m_pSprite->Begin(D3DXSPRITE_ALPHABLEND); +} + +void CNewPlayerTags::SpriteEnd() +{ + if(m_pSprite) + m_pSprite->End(); +} + void CNewPlayerTags::DeleteDeviceObjects() { SAFE_RELEASE(m_pStates); @@ -93,6 +108,73 @@ void CNewPlayerTags::RestoreDeviceObjects() m_pDevice->CreateStateBlock(D3DSBT_ALL, &m_pStates); } +void CNewPlayerTags::FUNC_1006CDA0(D3DXVECTOR3 *pPlayerPos, char *pNameText, DWORD dwColor, float fDistanceFromLocalPlayer, bool bDrawSandGlass, int a7) +{ + // TODO: CNewPlayerTags::FUNC_1006CDA0 + + /*RECT rect, rectBack; + D3DXVECTOR3 TagPos; + D3DVIEWPORT9 Viewport; + D3DXVECTOR3 Out; + D3DXMATRIX matIdent; + + TagPos = *pPlayerPos; + TagPos.z += 0.2f + (fDistanceFromLocalPlayer * 0.0475f); + + this->m_pDevice->GetViewport(&Viewport); + + D3DXMatrixIdentity(&matIdent); + D3DXVec3Project(&Out, &TagPos, &Viewport, &matProj, &matView, &matIdent); + + if (Out.z > 1.0f) + return; + + rect.left = rect.right = (int)Out.x; + rect.top = rect.bottom = (int)Out.y; + SIZE size = pDefaultFont->MeasureText(pNameText); + rect.left -= size.cx/2; + rect.top -= size.cy - 17; + rect.right += size.cx/2; + + pDefaultFont->RenderText(this->m_pSprite,pNameText,rect,DT_NOCLIP|DT_LEFT,dwColor); + + rect.left += size.cx/2; + rect.top -= size.cy; + rect.right -= size.cx/2; + + if(!bDrawSandGlass || !pDeathWindow) + return; + + if(!pDeathWindow->field_14B) + pDeathWindow->CreateAuxFonts(); + + ID3DXFont* v12 = pDeathWindow->field_14F; + ID3DXFont* v13 = pDeathWindow->field_153; + if(!v12 || !v13) + return; + + rectBack.left = 0; + rectBack.top = 0; + rectBack.right = 0; + rectBack.bottom = 0; + + // Get the rect of the rounded square symbol character + v13->DrawText(0,"C",1,&rectBack,DT_CENTER|DT_VCENTER|DT_NOCLIP|DT_CALCRECT,0x00000000); + + rect.top += (rectBack.bottom - rectBack.top) / 2 + 17; + rect.bottom = rect.top + 2; + rect.left -= ((rectBack.right - rectBack.left) / 2) + 22; + rect.right = rect.left + 1; + + if ( a7 == 2 ) { + v13->DrawText(0,"C",1,&rect,DT_CENTER|DT_VCENTER|DT_NOCLIP,0xFF000000); + rect.top -= 2; + rect.left -= 1; + + v12->DrawText(0,"E",1,&rect,DT_CENTER|DT_VCENTER|DT_NOCLIP,0xFFE3E1E3); + }*/ +} + void CNewPlayerTags::Draw(D3DXVECTOR3* pPlayerPos, float fHealth, float fArmor, float fDistanceFromLocalPlayer) { D3DXVECTOR3 TagPos = *pPlayerPos; diff --git a/saco/newplayertags.h b/saco/newplayertags.h index 3cfa273..547a01d 100644 --- a/saco/newplayertags.h +++ b/saco/newplayertags.h @@ -23,6 +23,10 @@ public: CNewPlayerTags(IDirect3DDevice9* pDevice); ~CNewPlayerTags(); + void SpriteBegin(); + void SpriteEnd(); + void FUNC_1006CDA0(D3DXVECTOR3 *pPlayerPos, char *pNameText, DWORD dwColor, float fDistanceFromLocalPlayer, bool bDrawSandGlass, int a7); + void Begin(); void End(); void Draw(D3DXVECTOR3* pPlayerPos, float fHealth, float fArmor, float fDistanceFromLocalPlayer); diff --git a/saco/saco.vcproj b/saco/saco.vcproj index 18e26b7..e2bd9ea 100644 --- a/saco/saco.vcproj +++ b/saco/saco.vcproj @@ -24,7 +24,6 @@ MinimalRebuild="TRUE" BasicRuntimeChecks="3" RuntimeLibrary="1" - StructMemberAlignment="1" UsePrecompiledHeader="0" WarningLevel="3" Detect64BitPortabilityProblems="TRUE" @@ -33,7 +32,7 @@ Name="VCCustomBuildTool"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + @@ -317,6 +174,12 @@ + + + + @@ -337,10 +200,22 @@ + + + + + + + @@ -360,16 +235,6 @@ RelativePath=".\net\vehiclepool.h"> - - - - - - @@ -396,6 +261,12 @@ + + + @@ -408,6 +279,12 @@ + + + @@ -417,6 +294,12 @@ + + + @@ -468,6 +351,12 @@ + + + @@ -573,6 +462,12 @@ + + + @@ -591,6 +486,12 @@ + + + @@ -654,6 +555,12 @@ + + + @@ -675,6 +582,12 @@ + + + @@ -699,6 +612,12 @@ + + + @@ -711,6 +630,12 @@ + + + @@ -741,6 +666,12 @@ + + + @@ -792,6 +723,12 @@ + + + @@ -884,9 +821,221 @@ RelativePath="..\raknet\Types.h"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -972,6 +1121,12 @@ + + + @@ -1018,12 +1173,24 @@ + + + + + + @@ -1042,6 +1209,12 @@ + + + @@ -1083,6 +1256,9 @@ + + @@ -1097,6 +1273,12 @@ + + + @@ -1140,6 +1322,9 @@ + + @@ -1185,6 +1370,9 @@ + + diff --git a/saco/unkclass13.cpp b/saco/unkclass13.cpp index abf102f..f5ebb3b 100644 --- a/saco/unkclass13.cpp +++ b/saco/unkclass13.cpp @@ -41,4 +41,13 @@ void CUnkClass13::RestoreDeviceObjects() D3DXCreateRenderToSurface(m_pD3DDevice, desc.Width, desc.Height, desc.Format, TRUE, D3DFMT_D16, &m_pD3DRenderToSurface); } -} \ No newline at end of file +} + +IDirect3DTexture9* CUnkClass13::FUNC_1006D880(char *szString) +{ + //D3DXCreateTexture(); + + // TODO: CUnkClass13::FUNC_1006D880 .text:1006D880 + + return NULL; +} diff --git a/saco/unkclass13.h b/saco/unkclass13.h index 9a5887a..08f6673 100644 --- a/saco/unkclass13.h +++ b/saco/unkclass13.h @@ -17,4 +17,6 @@ public: void DeleteDeviceObjects(); void RestoreDeviceObjects(); + + IDirect3DTexture9* FUNC_1006D880(char *szString); }; diff --git a/saco/unkclass14.cpp b/saco/unkclass14.cpp index 3aa39e4..7b294d0 100644 --- a/saco/unkclass14.cpp +++ b/saco/unkclass14.cpp @@ -25,4 +25,15 @@ void CUnkClass14::RestoreDeviceObjects() { D3DXCreateSprite(m_pD3DDevice, &m_pD3DSprite1); D3DXCreateSprite(m_pD3DDevice, &m_pD3DSprite2); -} \ No newline at end of file +} + +void CUnkClass14::FUNC_100708B0() +{ + //D3DXCreateFontA(); + + //LPD3DXRENDERTOSURFACE; + //D3DXCreateRenderToSurface(); + //D3DXCreateTexture(); + //D3DXCreateFont(); + //m_pD3DDevice->Clear(Count, pRects, Flags, Color, Z, Stencil); +} diff --git a/saco/unkclass14.h b/saco/unkclass14.h index 34d0bcd..b67433a 100644 --- a/saco/unkclass14.h +++ b/saco/unkclass14.h @@ -1,6 +1,9 @@ #pragma once +#include +#include + class CUnkClass14 { private: @@ -14,4 +17,6 @@ public: void DeleteDeviceObjects(); void RestoreDeviceObjects(); + + void FUNC_100708B0(); }; diff --git a/saco/unkclass3.cpp b/saco/unkclass3.cpp index 85c13af..437e351 100644 --- a/saco/unkclass3.cpp +++ b/saco/unkclass3.cpp @@ -18,6 +18,19 @@ CUnkClass3::CUnkClass3(IDirect3DDevice9 *pD3DDevice) memset(field_89, 0, sizeof(field_89)); } +int CUnkClass3::MsgProc(UINT uMsg, DWORD wParam, DWORD lParam) +{ + if(m_pEditControl->StaticMsgProc(uMsg, wParam, lParam)) return TRUE; + return FALSE; +} + +bool CUnkClass3::FUNC_1006F4F0() +{ + if(m_pEditControl) + return m_pEditControl->FUNC_100863E0(); + return false; +} + void CUnkClass3::ResetDialogControls(CDXUTDialog *pDialog) { m_pDialog = pDialog; diff --git a/saco/unkclass3.h b/saco/unkclass3.h index 1a644ec..6d6ba81 100644 --- a/saco/unkclass3.h +++ b/saco/unkclass3.h @@ -24,5 +24,7 @@ private: public: CUnkClass3(IDirect3DDevice9 *pD3DDevice); + int MsgProc(UINT uMsg, DWORD wParam, DWORD lParam); + bool FUNC_1006F4F0(); void ResetDialogControls(CDXUTDialog *pDialog); }; diff --git a/saco/unkclass4.cpp b/saco/unkclass4.cpp index 172c744..2f5f73b 100644 --- a/saco/unkclass4.cpp +++ b/saco/unkclass4.cpp @@ -21,13 +21,25 @@ void CUnkClass4::ResetDialogControls(CDXUTDialog *pDialog) if(pDialog) { pDialog->AddSlider(30,50,10,field_14,field_18,-100,100,0); + //Color.r = 0.6f; + //Color.g = 0.6f; + //Color.b = 0.8f; + //Color.a = 1.0f;; m_pDialog->GetSlider(30)->SetColor(D3DXCOLOR(0.6f,0.6f,0.80000007f,1.0f)); int y = field_1C + 10; m_pDialog->AddSlider(32,50,y,field_14,field_18,-100,100,0); + //Color.r = 0.8f; + //Color.g = 0.6f; + //Color.b = 0.6f; + //Color.a = 1.0f;; m_pDialog->GetSlider(32)->SetColor(D3DXCOLOR(0.80000007f,0.6f,0.6f,1.0f)); m_pDialog->AddSlider(34,50,y+field_1C,field_14,field_18,-100,100,0); + //Color.r = 0.6000000f; + //Color.g = 0.8000000f; + //Color.b = 0.6f; + //Color.a = 1.0f;; m_pDialog->GetSlider(34)->SetColor(D3DXCOLOR(0.6f,0.80000007f,0.6f,1.0f)); } } diff --git a/saco/unkclass5.cpp b/saco/unkclass5.cpp index 22eb402..95d56a7 100644 --- a/saco/unkclass5.cpp +++ b/saco/unkclass5.cpp @@ -22,9 +22,15 @@ CUnkClass5::CUnkClass5(IDirect3DDevice9 *pD3DDevice) field_240 = 220; field_24C = 0; field_250 = -1; + field_254 = RakNet::GetTime(); field_25C = 0; field_258 = 0; - field_254 = RakNet::GetTime(); + +} + +void CUnkClass5::ResetDialog() +{ + // TODO: CUnkClass5::ResetDialog() } void CUnkClass5::ResetDialogControls(CDXUTDialog *pDialog) diff --git a/saco/unkclass5.h b/saco/unkclass5.h index ec3b34d..a2c7c86 100644 --- a/saco/unkclass5.h +++ b/saco/unkclass5.h @@ -33,6 +33,7 @@ private: public: CUnkClass5(IDirect3DDevice9 *pD3DDevice); + void ResetDialog(); void ResetDialogControls(CDXUTDialog *pDialog); }; diff --git a/server/console.cpp b/server/console.cpp index b75fd02..7fa2c63 100644 --- a/server/console.cpp +++ b/server/console.cpp @@ -82,12 +82,110 @@ void con_exec() } } -void con_kick() {} // TODO: con_kick W: 0048A530 L: 0809ECB0 -void con_ban() {} // TODO: con_ban W: 0048A5D0 L: 0809ED80 -void con_banip() {} // TODO: con_banip W: 0048A740 L: 0809EF40 -void con_unbanip() {} // TODO: con_unbanip W: 0048A790 L: 0809EFB0 -void con_gmx() {} // TODO: con_gmx W: 0048A7D0 L: 0809F000 -void con_changemode() {} // TODO: con_changemode W: 0048A800 L: 0809F050 +void con_kick() +{ + char* arg = strtok(NULL, ""); + if(arg) + { + CPlayerPool* pPlayerPool = pNetGame->GetPlayerPool(); + PLAYERID playerId = atoi(arg); + + if(pPlayerPool->GetSlotState(playerId)) + { + RakServerInterface* pRak = pNetGame->GetRakServer(); + PlayerID Player = pRak->GetPlayerIDFromIndex(playerId); + in_addr in; + in.s_addr = Player.binaryAddress; + logprintf("%s <#%d - %s> has been kicked.",pPlayerPool->GetPlayerName(playerId), playerId, inet_ntoa(in)); + pNetGame->KickPlayer(playerId); + } + } +} + +void con_ban() +{ + char* arg = strtok(NULL, " "); + if (arg) + { + CPlayerPool* pPlayerPool = pNetGame->GetPlayerPool(); + PLAYERID playerId = atoi(arg); + + if (pPlayerPool->GetSlotState(playerId)) + { + RakServerInterface* pRak = pNetGame->GetRakServer(); + PlayerID Player = pRak->GetPlayerIDFromIndex(playerId); + in_addr in; + in.s_addr = Player.binaryAddress; + logprintf("%s <#%d - %s> has been banned.",pPlayerPool->GetPlayerName(playerId), playerId, inet_ntoa(in)); + pNetGame->AddBan(pPlayerPool->GetPlayerName(playerId), inet_ntoa(in), "CONSOLE BAN"); + pNetGame->KickPlayer(playerId); + } + } +} + +bool IsStrIp(char* szIn) +{ + char* part; + char tmp[16]; + memcpy(&tmp, szIn, 16); + int parts = 0; + part = strtok(szIn, "."); + while (part != NULL) + { + parts++; + if (part != "*") + { + if (atoi(part) < 0 || atoi(part) > 255) return false; + } + part = strtok(NULL, "."); + } + if (parts != 4) return false; + memcpy(szIn, &tmp, 16); + return true; +} + +void con_banip() +{ + char* arg = strtok(NULL, " "); + if (arg && IsStrIp(arg)) + { + logprintf("IP %s has been banned.", arg); + pNetGame->AddBan("NONE", arg, "IP BAN"); + } +} + +void con_unbanip() +{ + char* arg = strtok(NULL, " "); + if (arg && IsStrIp(arg)) + { + pNetGame->RemoveBan(arg); + } +} + +extern BOOL bGameModeFinished; +void con_gmx() +{ + // Gets the name of the next mode to avoid standard cycling + char *szMode; + szMode = pNetGame->GetNextScriptFile(); + if (szMode != NULL && pNetGame->SetNextScriptFile(szMode)) + { + bGameModeFinished = TRUE; + } +} + +void con_changemode() +{ + char* arg = strtok(NULL, ""); + if (arg) + { + if(pNetGame->SetNextScriptFile(arg)) { + bGameModeFinished = TRUE; + } + // do nothing if we can't set the requested script. + } +} void con_cmdlist(); @@ -96,16 +194,67 @@ void con_varlist() pConsole->PrintVariableList(); } -void con_say() {} // TODO: con_say W: 0048A830 L: 0809F0A0 -void con_reloadbans() {} // TODO: con_reloadbans W: 0048A880 L: 0809F110 +void con_say() +{ + char* arg = strtok(NULL, ""); + char Message[255]; + if (arg) { + sprintf(Message, "* Admin: %.230s", arg); + pNetGame->SendClientMessageToAll(0x2587CEAA, Message); + } +} -void con_reloadlog() { +void con_reloadbans() +{ + pNetGame->LoadBanList(); +} + +void con_reloadlog() +{ LoadLogFile(); } -void con_players() {} // TODO: con_players W: 0048A8A0 L: 0809F140 -void con_gravity() {} // TODO: con_gravity W: 0048A950 L: 0809F220 -void con_weather() {} // TODO: con_weather W: 0048A980 L: 0809F260 +void con_players() +{ + RakServerInterface* pRak = pNetGame->GetRakServer(); + + if ( pRak->GetConnectedPlayers() == 0 ) // If there is no players, why continue? + return; + + CPlayerPool* pPlayerPool = pNetGame->GetPlayerPool(); + + logprintf("ID\tName\tPing\tIP"); + + for( int i = 0; i < MAX_PLAYERS; i++) + { + if ( pPlayerPool->GetSlotState(i) == TRUE) + { + PlayerID Player = pRak->GetPlayerIDFromIndex(i); + in_addr in; + in.s_addr = Player.binaryAddress; + + logprintf("%d\t%s\t%d\t%s", i, pPlayerPool->GetPlayerName(i), pRak->GetLastPing( Player ), inet_ntoa(in)); + } + } +} + +void con_gravity() +{ + char* arg = strtok(NULL, " "); + if (arg) + { + pNetGame->SetGravity((float)atof(arg)); + } +} + +void con_weather() +{ + char* arg = strtok(NULL, " "); + if (arg) + { + pNetGame->SetWeather(atoi(arg)); + } +} void con_loadfs() { diff --git a/server/format.cpp b/server/format.cpp new file mode 100644 index 0000000..80ac9f4 --- /dev/null +++ b/server/format.cpp @@ -0,0 +1,34 @@ + +#include "main.h" +#include "amx/amx.h" + +#include "format.h" + +template size_t atcprintf(char *, size_t, const cell *, AMX *, cell *, int *); + +void AddInt(int val) +{ + int signedVal; + int neg; + + signedVal = val; + neg = 0; + + if (val < 0) + { + neg = 1; + signedVal = -val; + } +} + +template +size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *params, int *param) +{ + int arg; + int args = params[0] / sizeof(cell); + int llen = maxlen; + + arg = *param; + + return 0; +} diff --git a/server/format.h b/server/format.h new file mode 100644 index 0000000..a1441a6 --- /dev/null +++ b/server/format.h @@ -0,0 +1,8 @@ +#ifndef _INCLUDE_FORMATTING_H +#define _INCLUDE_FORMATTING_H + +//Amx Templatized Cell Printf +template +size_t atcprintf(D *buffer, size_t maxlen, const S *format, AMX *amx, cell *params, int *param); + +#endif //_INCLUDE_FORMATTING_H diff --git a/server/gamemodes.cpp b/server/gamemodes.cpp index 440884e..431113e 100644 --- a/server/gamemodes.cpp +++ b/server/gamemodes.cpp @@ -138,6 +138,9 @@ void CGameMode::Frame(float fElapsedTime) if (!m_bInitialised) return; + //if (m_pScriptTimers) + //m_pScriptTimers->Process((DWORD)(fElapsedTime * 1000.0f)); + if (!m_bSleeping) return; diff --git a/server/httpclient.cpp b/server/httpclient.cpp new file mode 100644 index 0000000..d442ceb --- /dev/null +++ b/server/httpclient.cpp @@ -0,0 +1,157 @@ + +#ifdef WIN32 +# include +#else +# include +# include +# include +# include +# include +# include +# include +# include +#endif + +#include "httpclient.h" + +//---------------------------------------------------- + +CHttpClient::CHttpClient(char *a2) +{ + // TODO: CHttpClient::CHttpClient() + +// Winsock init +#ifdef WIN32 + WORD wVersionRequested; + WSADATA wsaData; + wVersionRequested = MAKEWORD(2,2); + WSAStartup(wVersionRequested,&wsaData); +#endif +} + +//---------------------------------------------------- + + +//---------------------------------------------------- + +int CHttpClient::ProcessURL(int iType, char *szURL, char *szPostData, char *szReferer) +{ + InitRequest(iType,szURL,szPostData,szReferer); + + Process(); + + return m_iError; +} + +//---------------------------------------------------- + + +//---------------------------------------------------- + +bool CHttpClient::Connect(char *szHost, int iPort) +{ + struct sockaddr_in sa; + struct hostent *hp; + + // Hostname translation + if((hp=(struct hostent *)gethostbyname(szHost)) == NULL ) { + m_iError=HTTP_ERROR_BAD_HOST; + return false; + } + + // Prepare a socket + memset(&sa,0,sizeof(sa)); + + memcpy(&sa.sin_addr,hp->h_addr,hp->h_length); + sa.sin_family = hp->h_addrtype; + sa.sin_port = htons((unsigned short)iPort); + + // TODO: CHttpClient::Connect +} + +//---------------------------------------------------- + +void CHttpClient::CloseConnection() +{ +#ifdef WIN32 + closesocket(m_iSocket); +#else + close(m_iSocket); +#endif +} + +//---------------------------------------------------- + +bool CHttpClient::Send(char *szData) +{ + if(send(m_iSocket,szData,strlen(szData),0) < 0) { + m_iError = HTTP_ERROR_CANT_WRITE; + return false; + } + return true; +} + +//---------------------------------------------------- + +int CHttpClient::Recv(char *szBuffer, int iBufferSize) +{ + return recv(m_iSocket,szBuffer,iBufferSize,0); +} + +//---------------------------------------------------- + +void CHttpClient::InitRequest(int iType, char *szURL, char *szPostData, char *szReferer) +{ + char port[129]; // port string + char *port_char; // position of ':' if any + unsigned int slash_pos; // position of first '/' numeric + char *slash_ptr; + char szUseURL[2049]={0}; // incase we have to cat something to it. + + memset(szUseURL,0,sizeof(szUseURL)); + strncpy(szUseURL,szURL,sizeof(szUseURL)-1); + + m_Request.rtype = iType; + + strncpy(m_Request.referer,szReferer,256); + + if(iType==HTTP_POST) { + strncpy(m_Request.data,szPostData,8192); + } + + // Copy hostname from URL + slash_ptr = strchr(szUseURL,'/'); + + if(!slash_ptr) { + strcat(szUseURL,"/"); + slash_ptr = strchr(szUseURL,'/'); + } + + slash_pos=(slash_ptr-szUseURL); + if(slash_pos > 256) slash_pos=256; + memcpy(m_Request.host,szUseURL,slash_pos); + m_Request.host[slash_pos]='\0'; + + // Copy the rest of the url to the file string. + strncpy(m_Request.file,strchr(szUseURL,'/'),4096); + + // Any special port used in the URL? + if((port_char=strchr(m_Request.host,':'))!=NULL) { + memset(port,0,sizeof(port)); + strncpy(port,port_char+1,128); + *port_char='\0'; + m_Request.port = atoi(port); + } + else { + m_Request.port = 80; + } +} + +//---------------------------------------------------- + +void CHttpClient::Process() +{ + // TODO: CHttpClient::Process +} + + diff --git a/server/httpclient.h b/server/httpclient.h new file mode 100644 index 0000000..dfc279e --- /dev/null +++ b/server/httpclient.h @@ -0,0 +1,51 @@ + +#define HTTP_GET 1 +#define HTTP_POST 2 +#define HTTP_HEAD 3 + +//---------------------------------------------------- + +#define HTTP_ERROR_BAD_HOST 1 +#define HTTP_ERROR_CANT_WRITE 4 + +#pragma pack(1) +typedef struct{ + unsigned short port; /* remote port */ + int rtype; /* request type */ + char host[256]; /* hostname */ + char _gap106; + char file[4096]; /* GET/POST request file */ + char _gap1107; + char data[8192]; /* POST data (if rtype HTTP_POST) */ + char _gap3108; + char referer[256]; /* http referer. */ + char _gap3209[16385]; +} HTTP_REQUEST; + +//---------------------------------------------------- + +class CHttpClient +{ +private: + + int m_iSocket; + int m_iError; + HTTP_REQUEST m_Request; + + bool Connect(char *szHost, int iPort); + void CloseConnection(); + bool Send(char *szData); + int Recv(char *szBuffer, int iBufferSize); + + void InitRequest(int iType, char *szURL, char *szPostData, char *szReferer); + + void Process(); + +public: + + int ProcessURL(int iType, char *szURL, char *szData, char *szReferer); + + CHttpClient(char *a2); +}; + +//---------------------------------------------------- diff --git a/server/main.cpp b/server/main.cpp index 81c4623..d979e61 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -17,9 +17,9 @@ int iMinConnectionTime; int iDbLogging; int iDbLogQueries; -int unnamed_3; // W: 004F5FEC L: 081AA8A4 -int unnamed_4; // W: 004F5FF0 L: 081AA8A0 unsigned int _uiRndSrvChallenge; +int unnamed_3; // TODO: rename W: 004F5FEC L: 081AA8A4 +int unnamed_4; // TODO: rename W: 004F5FF0 L: 081AA8A0 int iOnFootRate = 30; int iInCarRate = 30; @@ -429,8 +429,8 @@ int main (int argc, char** argv) } #ifdef WIN32 - SetEvent(hConsoleExecuteEvent); - WaitForSingleObject(hConsoleExecuteEvent, INFINITE); + SetEvent(hConsoleExecuteEvent); + WaitForSingleObject(hConsoleExecuteEvent, INFINITE); #endif if(RakNet::GetTime() - unnamed_4 > iConnSeedTime) diff --git a/server/main.h b/server/main.h index 52c9b17..73f1c4b 100644 --- a/server/main.h +++ b/server/main.h @@ -41,9 +41,11 @@ #include #include + #include #include #else #define SLEEP(x) { usleep(x * 1000); } + #define MAX_PATH 260 #ifndef stricmp #define stricmp strcasecmp @@ -89,9 +91,12 @@ typedef unsigned short VEHICLEID; #include "netrpc.h" #include "player.h" #include "playerpool.h" +#include "vehicle.h" #include "vehiclepool.h" #include "pickuppool.h" +#include "object.h" #include "objectpool.h" +#include "menu.h" #include "menupool.h" #include "textdrawpool.h" #include "labelpool.h" diff --git a/server/mathutils.cpp b/server/mathutils.cpp index 213281e..9ce31ea 100644 --- a/server/mathutils.cpp +++ b/server/mathutils.cpp @@ -8,7 +8,7 @@ //---------------------------------------------------- -bool unnamed_1(PVECTOR vec) +bool unnamed_func_1(PVECTOR vec) { if( vec->X <= 1.0f && vec->X >= -1.0f && vec->Y <= 1.0f && vec->Y >= -1.0f && @@ -21,7 +21,7 @@ bool unnamed_1(PVECTOR vec) //---------------------------------------------------- -bool unnamed_2(PVECTOR vec) +bool unnamed_func_2(PVECTOR vec) { if( vec->X < 20000.0f && vec->X > -20000.0f && vec->Y < 20000.0f && vec->Y > -20000.0f && @@ -34,7 +34,7 @@ bool unnamed_2(PVECTOR vec) //---------------------------------------------------- -bool unnamed_3(PVECTOR vec) +bool unnamed_func_3(PVECTOR vec) { if( vec->X < 100.0f && vec->X > -100.0f && vec->Y < 100.0f && vec->Y > -100.0f && diff --git a/server/mathutils.h b/server/mathutils.h index 28186a7..fd3d628 100644 --- a/server/mathutils.h +++ b/server/mathutils.h @@ -1,7 +1,7 @@ -bool unnamed_1(PVECTOR vec); // unused -bool unnamed_2(PVECTOR vec); -bool unnamed_3(PVECTOR vec); +bool unnamed_func_1(PVECTOR vec); // unused +bool unnamed_func_2(PVECTOR vec); +bool unnamed_func_3(PVECTOR vec); float GetLength(PVECTOR vec); void CrossProduct(PVECTOR out, PVECTOR vec1, PVECTOR vec2); // unused void Transform(PVECTOR out, PMATRIX4X4 mat, PVECTOR vec); // unused @@ -12,4 +12,3 @@ void QuaternionToMatrix(PQUATERNION quat, PMATRIX4X4 mat); float GetNormalisation(PVECTOR vec); void ToQuaternion(PVECTOR vec, PQUATERNION quat); // unused void ToEulerAngles(PQUATERNION quat, PVECTOR vec); // unused - diff --git a/server/menu.cpp b/server/menu.cpp new file mode 100644 index 0000000..ca3b37c --- /dev/null +++ b/server/menu.cpp @@ -0,0 +1,123 @@ + +#include "main.h" + +CMenu::CMenu(PCHAR pTitle, float fX, float fY, BYTE byteColumns, float fCol1Width, float fCol2Width) +{ + ResetForAll(); + for (BYTE i = 0; i < MAX_MENU_ITEMS; i++) + { + m_charItems[i][0][0] = '\0'; + m_charItems[i][1][0] = '\0'; + m_MenuInteraction.bRow[i] = TRUE; + } + m_MenuInteraction.bMenu = TRUE; + m_charHeader[0][0] = '\0'; + m_charHeader[1][0] = '\0'; + + if (strlen(pTitle) >= MAX_MENU_LINE) pTitle[MAX_MENU_LINE - 1] = '\0'; + strcpy(m_charTitle, pTitle); + + m_fXPos = fX; + m_fYPos = fY; + m_fCol1Width = fCol1Width; + m_fCol2Width = fCol2Width; + + if (byteColumns == 2) m_byteColumns = 2; + else m_byteColumns = 1; + m_byteColCount[0] = 0; + m_byteColCount[1] = 0; +} + +void CMenu::ResetForAll() +{ + for (PLAYERID i = 0; i < MAX_PLAYERS; i++) + { + m_bInitedForPlayer[i] = FALSE; + } +} + +BYTE CMenu::AddMenuItem(BYTE byteColumn, PCHAR pText) +{ + if (byteColumn >= MAX_COLUMNS) return 0xFF; + BYTE byteCount = m_byteColCount[byteColumn]; + if (byteCount >= MAX_MENU_LINE) return 0xFF; + if (strlen(pText) >= MAX_MENU_LINE) pText[MAX_MENU_LINE - 1] = '\0'; + + ResetForAll(); + strcpy(m_charItems[byteCount][byteColumn], pText); + m_byteColCount[byteColumn]++; + + return byteCount; +} + +void CMenu::SetColumnTitle(BYTE byteColumn, PCHAR pText) +{ + if (byteColumn >= MAX_COLUMNS) return; + if (strlen(pText) >= MAX_MENU_LINE) pText[MAX_MENU_LINE - 1] = '\0'; + ResetForAll(); + strcpy(m_charHeader[byteColumn], pText); +} + +void CMenu::InitForPlayer(PLAYERID playerId) +{ + if (playerId >= MAX_PLAYERS) return; + + m_bInitedForPlayer[playerId] = TRUE; + + RakNet::BitStream bsMenu; + + bsMenu.Write(m_byteMenuID); + bsMenu.Write((BOOL)(m_byteColumns == 2)); + bsMenu.Write(m_charTitle, MAX_MENU_LINE); + bsMenu.Write(m_fXPos); + bsMenu.Write(m_fYPos); + bsMenu.Write(m_fCol1Width); + if (m_byteColumns == 2) + { + bsMenu.Write(m_fCol2Width); + } + bsMenu.Write(m_MenuInteraction.bMenu); + for (BYTE i = 0; i < MAX_MENU_ITEMS; i++) + { + bsMenu.Write(m_MenuInteraction.bRow[i]); + } + bsMenu.Write(m_charHeader[0], MAX_MENU_LINE); + BYTE count = m_byteColCount[0]; + bsMenu.Write(count); + for (BYTE i = 0; i < count; i++) + { + bsMenu.Write(m_charItems[i][0], MAX_MENU_LINE); + } + if (m_byteColumns == 2) + { + bsMenu.Write(m_charHeader[1], MAX_MENU_LINE); + count = m_byteColCount[1]; + bsMenu.Write(count); + for (BYTE i = 0; i < count; i++) + { + bsMenu.Write(m_charItems[i][1], MAX_MENU_LINE); + } + } + pNetGame->SendToPlayer(RPC_ScrInitMenu, &bsMenu, playerId, 2); +} + +void CMenu::ShowForPlayer(PLAYERID playerId) +{ + if (playerId >= MAX_PLAYERS) return; + + if (!m_bInitedForPlayer[playerId]) InitForPlayer(playerId); + + // Send command to display it here + RakNet::BitStream bsMenu; + bsMenu.Write(m_byteMenuID); + pNetGame->SendToPlayer(RPC_ScrShowMenu, &bsMenu, playerId, 2); +} + +void CMenu::HideForPlayer(PLAYERID playerId) +{ + if (playerId >= MAX_PLAYERS) return; + + RakNet::BitStream bsMenu; + bsMenu.Write(m_byteMenuID); + pNetGame->SendToPlayer(RPC_ScrHideMenu, &bsMenu, playerId, 2); +} diff --git a/server/menu.h b/server/menu.h new file mode 100644 index 0000000..df3dd33 --- /dev/null +++ b/server/menu.h @@ -0,0 +1,58 @@ + +#ifndef SAMPSRV_MENU_H +#define SAMPSRV_MENU_H + +#define MAX_MENU_ITEMS 12 +#define MAX_MENU_LINE 32 +#define MAX_COLUMNS 2 + +//---------------------------------------------------- + +struct MENU_INT +{ + BOOL bMenu; + BOOL bRow[MAX_MENU_ITEMS]; + BOOL bPadding[8 - ((MAX_MENU_ITEMS + 1) % 8)]; +}; + +class CMenu +{ +private: + + BYTE m_byteMenuID; + + CHAR m_charTitle[MAX_MENU_LINE]; + CHAR m_charItems[MAX_MENU_ITEMS][MAX_COLUMNS][MAX_MENU_LINE]; + CHAR m_charHeader[MAX_COLUMNS][MAX_MENU_LINE]; + + BOOL m_bInitedForPlayer[MAX_PLAYERS]; + MENU_INT m_MenuInteraction; + + float m_fXPos; + float m_fYPos; + float m_fCol1Width; + float m_fCol2Width; + BYTE m_byteColumns; + + BYTE m_byteColCount[MAX_COLUMNS]; + +public: + + CMenu(PCHAR pTitle, float fX, float fY, BYTE byteColumns, float fCol1Width, float fCol2Width); + + BYTE AddMenuItem(BYTE byteColumn, PCHAR pText); + void SetColumnTitle(BYTE byteColumn, PCHAR pText); + + void ResetForAll(); + + void SetID(BYTE byteMenuID) { m_byteMenuID = byteMenuID; }; + + void InitForPlayer(PLAYERID playerId); + void ShowForPlayer(PLAYERID playerId); + void HideForPlayer(PLAYERID playerId); + + void DisableInteraction() { m_MenuInteraction.bMenu = FALSE; }; + void DisableRow(BYTE byteRow) { m_MenuInteraction.bRow[byteRow] = FALSE; }; +}; + +#endif // SAMPSRV_MENU_H diff --git a/server/menupool.cpp b/server/menupool.cpp index b5c813a..7afe15a 100644 --- a/server/menupool.cpp +++ b/server/menupool.cpp @@ -1,28 +1,71 @@ #include "main.h" +//---------------------------------------------------- + CMenuPool::CMenuPool() { for (BYTE byteMenuID = 0; byteMenuID < MAX_MENUS; byteMenuID++) { - field_200[byteMenuID] = 0; - field_0[byteMenuID] = 0; + m_bMenuSlotState[byteMenuID] = FALSE; + m_pMenus[byteMenuID] = NULL; } for (PLAYERID playerId = 0; playerId < MAX_PLAYERS; playerId++) { - field_400[playerId] = 255; + m_bytePlayerMenu[playerId] = 255; } } +//---------------------------------------------------- + CMenuPool::~CMenuPool() { for (BYTE byteMenuID = 0; byteMenuID < MAX_MENUS; byteMenuID++) { - if (field_0[byteMenuID]) + if (m_pMenus[byteMenuID]) { - delete field_0[byteMenuID]; - field_0[byteMenuID] = NULL; + delete m_pMenus[byteMenuID]; + m_pMenus[byteMenuID] = NULL; } } } +//---------------------------------------------------- + +BYTE CMenuPool::New(PCHAR pTitle, float fX, float fY, BYTE byteColumns, float fCol1Width, float fCol2Width) +{ + BYTE byteMenuID; + + for (byteMenuID = 1; byteMenuID < MAX_MENUS; byteMenuID++) + { + if (m_bMenuSlotState[byteMenuID] == FALSE) break; + } + if (byteMenuID == MAX_MENUS) return 0xFF; + + CMenu* pMenu = new CMenu(pTitle, fX, fY, byteColumns, fCol1Width, fCol2Width); + + if (pMenu) + { + m_bMenuSlotState[byteMenuID] = TRUE; + pMenu->SetID(byteMenuID); + m_pMenus[byteMenuID] = pMenu; + return byteMenuID; + } + return 0xFF; +} + +//---------------------------------------------------- + +BOOL CMenuPool::Delete(BYTE byteMenuID) +{ + if (m_bMenuSlotState[byteMenuID] == FALSE || !m_pMenus[byteMenuID]) + { + return FALSE; + } + m_bMenuSlotState[byteMenuID] = FALSE; + delete m_pMenus[byteMenuID]; + m_pMenus[byteMenuID] = NULL; + + return TRUE; +} + diff --git a/server/menupool.h b/server/menupool.h index 119d031..8302e90 100644 --- a/server/menupool.h +++ b/server/menupool.h @@ -2,16 +2,50 @@ #ifndef SAMPSRV_MENUPOOL_H #define SAMPSRV_MENUPOOL_H +//---------------------------------------------------- + class CMenuPool // size: WL 2024 { private: - int* field_0[128]; - int field_200[128]; - char field_400[1000]; + + CMenu *m_pMenus[MAX_MENUS]; + BOOL m_bMenuSlotState[MAX_MENUS]; + BYTE m_bytePlayerMenu[MAX_PLAYERS]; public: CMenuPool(); ~CMenuPool(); + + BYTE New(PCHAR pTitle, float fX, float fY, BYTE byteColumns, float fCol1Width, float fCol2Width); + + BOOL Delete(BYTE byteMenuID); + + // Retrieve a menu by id + CMenu* GetAt(BYTE byteMenuID) + { + if(byteMenuID > MAX_MENUS) { return NULL; } + return m_pMenus[byteMenuID]; + }; + + // Find out if the slot is inuse. + BOOL GetSlotState(BYTE byteMenuID) + { + if(byteMenuID > MAX_MENUS) { return FALSE; } + return m_bMenuSlotState[byteMenuID]; + }; + + BYTE GetPlayerMenu(PLAYERID playerId) + { + if (playerId >= MAX_PLAYERS) return 255; + return m_bytePlayerMenu[playerId]; + } + + void SetPlayerMenu(PLAYERID playerId, BYTE byteMenu) + { + if (playerId < MAX_PLAYERS && byteMenu < MAX_MENUS) m_bytePlayerMenu[playerId] = byteMenu; + } }; +//---------------------------------------------------- + #endif diff --git a/server/netgame.cpp b/server/netgame.cpp index b0e58cc..2c5ad9d 100644 --- a/server/netgame.cpp +++ b/server/netgame.cpp @@ -2,6 +2,8 @@ #include "main.h" #include "../raknet/SocketDataEncryptor.h" +float fRestartWaitTime=0.0f; + int CanFileBeOpenedForReading(char * filename); char szGameModeFile[256]; @@ -33,6 +35,13 @@ bool HasTimestamps(Packet *p) //---------------------------------------------------- +DWORD CNetGame::GetTime() +{ + return (DWORD)RakNet::GetTime(); +} + +//---------------------------------------------------- + CNetGame::CNetGame() { m_bAllowWeapons = FALSE; @@ -324,7 +333,7 @@ BOOL CNetGame::SetNextScriptFile(char *szFile) //---------------------------------------------------- -void CNetGame::Init(BOOL bFirst) +void CNetGame::Init(BOOL bFirst = false) { m_iSpawnsAvailable = 0; @@ -494,6 +503,15 @@ void CNetGame::ShutdownForGameModeRestart() //---------------------------------------------------- +void CNetGame::ReInitWhenRestarting() +{ + Init(); + + // TODO: CNetGame::ReInitWhenRestarting() +} + +//---------------------------------------------------- + #ifdef WIN32 #pragma comment(lib, "winmm.lib") @@ -588,73 +606,586 @@ void CNetGame::MasterServerAnnounce(float fElapsedTime) //---------------------------------------------------- -void CNetGame::Process() +void CNetGame::UpdateTickCounter() { - float fElapsedTime = GetElapsedTime(); - - if(m_iGameState == GAMESTATE_RUNNING) + if((GetTime() - m_iLastServerTickUpdate) >= 1000) { - if(m_pGameMode) m_pGameMode->Frame(fElapsedTime); - if(m_pScriptTimers) m_pScriptTimers->Process((DWORD)(fElapsedTime * 1000.0f)); + m_iLastServerTickUpdate = GetTime(); + m_iServerTickRate = m_iServerTickCount; + m_iServerTickCount = 0; } - else if(m_iGameState == GAMESTATE_RESTARTING) - { - - } - - // TODO: CNetGame::Process W: 00491240 L: 080AEEE0 - -/* - sub_80ABF00(this); - sub_80AECE0((int)this); - v1 = this->field_5E; - if ( v1 == 1 ) - { - if ( this->field_8 ) - sub_80D0DF0(this->field_8, v4); - if ( this->field_C ) - sub_814CD00(this->field_C, v4); - if ( this->field_14 ) - sub_80C8760(this->field_14, v4); - if ( this->field_0 ) - sub_80A5080(this->field_0, v4); - v2 = this->field_3C; - if ( v2 ) - sub_80EBAF0(v2, (signed __int64)(v4 * 1000.0)); - if ( this->field_38 ) - sub_80EA2E0(this->field_38); - } - else if ( v1 == 2 ) - { - v3 = v4 + *(float *)&dword_81CA600; - *(float *)&dword_81CA600 = v3; - if ( v3 > 12.0 ) - sub_80AE530(this); - } - if ( CConsole::GetBoolVariable(pConsole, "announce") ) - { - sub_80ABDE0((int)this, v4); - sub_80D1CA0(pPlugins); - this->field_82 = this->field_82 + v4; - } - else - { - sub_80D1CA0(pPlugins); - this->field_82 = this->field_82 + v4; - } -*/ -} - -void CNetGame::LoadBanList() -{ - // TODO: CNetGame::LoadBanList W: 48EAE0 L: 80AF1A0 + m_iServerTickCount++; } //---------------------------------------------------- -DWORD CNetGame::GetTime() +void CNetGame::Process() { - return (DWORD)RakNet::GetTime(); + float fElapsedTime = GetElapsedTime(); + + UpdateTickCounter(); + UpdateNetwork(); + + if(m_iGameState == GAMESTATE_RUNNING) + { + if(m_pPlayerPool) m_pPlayerPool->Process(fElapsedTime); + if(m_pVehiclePool) m_pVehiclePool->Process(fElapsedTime); + if(m_pObjectPool) m_pObjectPool->Process(fElapsedTime); + if(m_pGameMode) m_pGameMode->Frame(fElapsedTime); + if(m_pScriptTimers) m_pScriptTimers->Process((DWORD)(fElapsedTime * 1000.0f)); + if(m_pScriptHttps) m_pScriptHttps->Process(); + } + else if(m_iGameState == GAMESTATE_RESTARTING) + { + fRestartWaitTime += fElapsedTime; + if(fRestartWaitTime > 12.0f) // wait 12 seconds, then restart + { + ReInitWhenRestarting(); + } + } + + if (pConsole->GetBoolVariable("announce")) { + // Announce the server to the master + MasterServerAnnounce(fElapsedTime); + } + + // Execute the tick event for loaded plugins + pPlugins->DoProcessTick(); + + #ifndef WIN32 + m_dElapsedTime += (double)fElapsedTime; + #endif +} + +//---------------------------------------------------- +// UPDATE NETWORK +//---------------------------------------------------- + +void CNetGame::UpdateNetwork() +{ + Packet* p; + unsigned char packetIdentifier; + + while(p=m_pRak->Receive()) + { + packetIdentifier = GetPacketID(p); + + switch(packetIdentifier) { + + case ID_NEW_INCOMING_CONNECTION_2: + Packet_NewIncomingConnection(p); + break; + case ID_DISCONNECTION_NOTIFICATION: + Packet_DisconnectionNotification(p); + break; + case ID_CONNECTION_LOST: + Packet_ConnectionLost(p); + break; + case ID_MODIFIED_PACKET: + Packet_ModifiedPacket(p); + break; + /* + // Not in latest RakNet, so not going to support it. + case ID_REMOTE_PORT_REFUSED: + Packet_RemotePortRefused(p); + break; + */ + case ID_PLAYER_SYNC: + Packet_PlayerSync(p); + break; + case ID_VEHICLE_SYNC: + Packet_VehicleSync(p); + break; + case ID_PASSENGER_SYNC: + Packet_PassengerSync(p); + break; + case ID_SPECTATOR_SYNC: + Packet_SpectatorSync(p); + break; + case ID_WEAPON_SHOT_SYNC: + Packet_WeaponShotSync(p); + break; + case ID_AIM_SYNC: + Packet_AimSync(p); + break; + case ID_RCON_COMMAND: + Packet_InGameRcon(p); + break; + case ID_STATS_UPDATE: + Packet_StatsUpdate(p); + break; + case ID_WEAPONS_UPDATE: + Packet_WeaponsUpdate(p); + break; + case ID_TRAILER_SYNC: + Packet_TrailerSync(p); + break; + case ID_UNOCCUPIED_SYNC: + Packet_UnoccupiedSync(p); + break; + } + + m_pRak->DeallocatePacket(p); + } +} + +//---------------------------------------------------- + +void CNetGame::BroadcastData(char *szUniqueID, + RakNet::BitStream *bitStream, + PLAYERID excludedPlayer, + char orderingStream) +{ + // TODO: CNetGame::BroadcastData +} + +void CNetGame::SendToPlayer(char *szUniqueID, + RakNet::BitStream *bitStream, + PLAYERID playerId, + char orderingChannel) +{ + CPlayerPool * pPlayerPool = GetPlayerPool(); + PacketReliability reliability; + + if(!pPlayerPool) return; + + reliability = RELIABLE_ORDERED; + if(orderingChannel == 3) + reliability = RELIABLE; + + if(pPlayerPool->GetSlotState(playerId)) + { + m_pRak->RPC(szUniqueID, bitStream, HIGH_PRIORITY, reliability, orderingChannel, + m_pRak->GetPlayerIDFromIndex(playerId), false, false); + } + + // TODO: CNetGame::SendToPlayer +} + + +//---------------------------------------------------- +// PACKET HANDLERS +//---------------------------------------------------- + +void CNetGame::Packet_PlayerSync(Packet *p) +{ + CPlayer * pPlayer = GetPlayerPool()->GetAt((PLAYERID)p->playerIndex); + RakNet::BitStream bsPlayerSync((PCHAR)p->data, p->length, false); + + if(GetGameState() != GAMESTATE_RUNNING) return; + + BYTE bytePacketID=0; + ONFOOT_SYNC_DATA ofSync; + + bsPlayerSync.Read(bytePacketID); + bsPlayerSync.Read((PCHAR)&ofSync,sizeof(ONFOOT_SYNC_DATA)); + + if(pPlayer) { + // TODO: CNetGame::Packet_PlayerSync + } +} + +//---------------------------------------------------- + +void CNetGame::Packet_AimSync(Packet *p) +{ + CPlayer * pPlayer = GetPlayerPool()->GetAt((PLAYERID)p->playerIndex); + RakNet::BitStream bsPlayerSync((PCHAR)p->data, p->length, false); + + if(GetGameState() != GAMESTATE_RUNNING) return; + + BYTE bytePacketID=0; + AIM_SYNC_DATA aimSync; + + bsPlayerSync.Read(bytePacketID); + bsPlayerSync.Read((PCHAR)&aimSync,sizeof(AIM_SYNC_DATA)); + + if(pPlayer) { + pPlayer->StoreAimSyncData(&aimSync); + } +} + +//---------------------------------------------------- + +void CNetGame::Packet_VehicleSync(Packet *p) +{ + CPlayer * pPlayer = GetPlayerPool()->GetAt((PLAYERID)p->playerIndex); + RakNet::BitStream bsVehicleSync((PCHAR)p->data, p->length, false); + + if(GetGameState() != GAMESTATE_RUNNING) return; + + BYTE bytePacketID=0; + INCAR_SYNC_DATA icSync; + + bsVehicleSync.Read(bytePacketID); + bsVehicleSync.Read((PCHAR)&icSync,sizeof(INCAR_SYNC_DATA)); + + if(pPlayer) { + + } + + // TODO: CNetGame::Packet_VehicleSync +} + +//---------------------------------------------------- + +void CNetGame::Packet_PassengerSync(Packet *p) +{ + CPlayer * pPlayer = GetPlayerPool()->GetAt((PLAYERID)p->playerIndex); + RakNet::BitStream bsPassengerSync((PCHAR)p->data, p->length, false); + + if(GetGameState() != GAMESTATE_RUNNING) return; + + BYTE bytePacketID=0; + PASSENGER_SYNC_DATA psSync; + + bsPassengerSync.Read(bytePacketID); + bsPassengerSync.Read((PCHAR)&psSync,sizeof(PASSENGER_SYNC_DATA)); + + if(pPlayer) { + + } + + // TODO: CNetGame::Packet_PassengerSync +} + +//---------------------------------------------------- + +void CNetGame::Packet_SpectatorSync(Packet *p) +{ + CPlayer * pPlayer = GetPlayerPool()->GetAt((PLAYERID)p->playerIndex); + RakNet::BitStream bsSpectatorSync((PCHAR)p->data, p->length, false); + + if(GetGameState() != GAMESTATE_RUNNING) return; + + // TODO: CNetGame::Packet_SpectatorSync +} + +//---------------------------------------------------- + +void CNetGame::Packet_TrailerSync(Packet *p) +{ + CPlayer * pPlayer = GetPlayerPool()->GetAt((PLAYERID)p->playerIndex); + RakNet::BitStream bsTrailerSync((PCHAR)p->data, p->length, false); + + if(GetGameState() != GAMESTATE_RUNNING) return; + + BYTE bytePacketID=0; + TRAILER_SYNC_DATA trSync; + + bsTrailerSync.Read(bytePacketID); + bsTrailerSync.Read((PCHAR)&trSync, sizeof(TRAILER_SYNC_DATA)); + + /*if(pPlayer) { + if(unnamed_804B640(&trSync.field_1E) && unnamed_804B5D0(&trSync.field_2)) { + pPlayer->StoreTrailerFullSyncData(&trSync); + } + }*/ + // TODO: CNetGame::Packet_TrailerSync +} + +//---------------------------------------------------- + +void CNetGame::Packet_UnoccupiedSync(Packet *p) +{ + // TODO: CNetGame::Packet_UnoccupiedSync +} + +//---------------------------------------------------- + +void CNetGame::Packet_StatsUpdate(Packet *p) +{ + RakNet::BitStream bsStats((PCHAR)p->data, p->length, false); + CPlayerPool *pPlayerPool = GetPlayerPool(); + PLAYERID playerId = (PLAYERID)p->playerIndex; + int iMoney; + int iDrunkLevel; + BYTE bytePacketID; + + bsStats.Read(bytePacketID); + bsStats.Read(iMoney); + bsStats.Read(iDrunkLevel); + + if(pPlayerPool) { + if(pPlayerPool->GetSlotState(playerId)) { + pPlayerPool->SetPlayerMoney(playerId,iMoney); + pPlayerPool->SetPlayerDrunkLevel(playerId,iDrunkLevel); + } + } + + // TODO: CNetGame::Packet_StatsUpdate +} + +//---------------------------------------------------- + +void CNetGame::Packet_WeaponsUpdate(Packet *p) +{ + // TODO: CNetGame::Packet_WeaponsUpdate +} + +//---------------------------------------------------- + +void CNetGame::Packet_WeaponShotSync(Packet *p) +{ + if(GetGameState() != GAMESTATE_RUNNING) return; + + // TODO: CNetGame::Packet_WeaponShotSync +} + + + + + + + + +//---------------------------------------------------- + +void CNetGame::Packet_NewIncomingConnection(Packet* packet) +{ + if(!packet) return; + + logprintf("[connection] incoming connection: %s id: %u", + packet->playerId.ToString(), packet->playerIndex); + + if(m_pGameMode) + { + if(m_pFilterScripts) + { + m_pFilterScripts->OnIncomingConnection(packet->playerIndex, + packet->playerId.ToString(false), packet->playerId.port); + + m_pGameMode->OnIncomingConnection(packet->playerIndex, + packet->playerId.ToString(false), packet->playerId.port); + } + } +} + +//---------------------------------------------------- + +void CNetGame::Packet_DisconnectionNotification(Packet* packet) +{ + m_pPlayerPool->Delete((PLAYERID)packet->playerIndex,1); +} + +//---------------------------------------------------- + +void CNetGame::Packet_ConnectionLost(Packet* packet) +{ + m_pPlayerPool->Delete((PLAYERID)packet->playerIndex,0); +} + +//---------------------------------------------------- + +void CNetGame::Packet_ModifiedPacket(Packet* packet) +{ + logprintf("Packet was modified, sent by id: %d, ip: %s", + packet->playerIndex, packet->playerId.ToString()); +} + +//---------------------------------------------------- + +void CNetGame::Packet_RemotePortRefused(Packet* packet) +{ + logprintf("Remote Port Refused for Player: %u\n", packet->playerIndex); +} + +//---------------------------------------------------- + +void CNetGame::Packet_InGameRcon(Packet* packet) +{ + // TODO: CNetGame::Packet_InGameRcon +} + +//---------------------------------------------------- + +void CNetGame::SendClientMessageToAll(DWORD dwColor, char* szMessage, ...) +{ + va_list va; + va_start(va, szMessage); + char szBuffer[1024] = { 0 }; + vsprintf(szBuffer, szMessage, va); + va_end(va); + + RakNet::BitStream bsParams; + DWORD dwStrLen = strlen(szBuffer); + + bsParams.Write(dwColor); + bsParams.Write(dwStrLen); + bsParams.Write(szBuffer, dwStrLen); + BroadcastData(RPC_ClientMessage, &bsParams, INVALID_PLAYER_ID, 3); +} + +//---------------------------------------------------- + +void CNetGame::SetWorldTime(BYTE byteHour) +{ + RakNet::BitStream bsTime; + + m_byteWorldTime = byteHour; + bsTime.Write(m_byteWorldTime); + BroadcastData(RPC_WorldTime, &bsTime, INVALID_PLAYER_ID, 2); + + char szTime[256]; + sprintf(szTime, "%02d:%02d", m_byteWorldTime, 0); + pConsole->SetStringVariable("worldtime", szTime); +} + +//---------------------------------------------------- + +void CNetGame::SetWeather(BYTE byteWeather) +{ + RakNet::BitStream bsWeather; + m_byteWeather = byteWeather; + bsWeather.Write(m_byteWeather); + BroadcastData(RPC_Weather, &bsWeather, INVALID_PLAYER_ID, 2); + + char szWeather[128]; + sprintf(szWeather, "%d", m_byteWeather); + pConsole->SetStringVariable("weather", szWeather); +} + +//---------------------------------------------------- + +void CNetGame::SetGravity(float fGravity) +{ + m_fGravity = fGravity; + RakNet::BitStream bsGravity; + bsGravity.Write(m_fGravity); + + char szGravity[128]; + sprintf(szGravity, "%f", m_fGravity); + + pConsole->SetStringVariable("gravity", szGravity); + BroadcastData(RPC_ScrSetGravity, &bsGravity, INVALID_PLAYER_ID, 2); +} + +//---------------------------------------------------- + +void CNetGame::KickPlayer(PLAYERID kickPlayer) +{ + if(kickPlayer >= MAX_PLAYERS) return; + + // TODO: CNetGame::KickPlayer +} + +//---------------------------------------------------- + +void CNetGame::BlockIpAddress(char *ip_address, int timems) +{ + m_pRak->AddToBanList(ip_address, timems); +} + +//---------------------------------------------------- + +void CNetGame::UnBlockIpAddress(char *ip_address) +{ + m_pRak->RemoveFromBanList(ip_address); +} + +//---------------------------------------------------- + +void CNetGame::AddBan(char * nick, char * ip_mask, char * reason) +{ + const struct tm *tm; + time_t now; + now = time(NULL); + tm = localtime(&now); + char *s; + s = new char[256]; + strftime(s, 256, "[%d/%m/%y | %H:%M:%S]", tm); + + m_pRak->AddToBanList(ip_mask); + + FILE * fileBanList = fopen("samp.ban","a"); + if(!fileBanList) return; + + fprintf(fileBanList,"%s %s %s - %s\n", ip_mask, s, nick, reason); + fclose(fileBanList); + + delete [] s; +} + +//---------------------------------------------------- + +void CNetGame::RemoveBan(char* ip_mask) +{ + m_pRak->RemoveFromBanList(ip_mask); + + FILE* fileBanList = fopen("samp.ban", "r"); + FILE* fileWriteList = fopen("samp.ban.temp", "w"); + if(!fileBanList || !fileWriteList) return; + + char line[256]; + char line2[256]; + char* ip; + + while(!feof(fileBanList)) + { + if (fgets(line, 256, fileBanList)) + { + strcpy(line2, line); + ip = strtok(line, " \t"); + if (strcmp(ip_mask, ip) != 0) + { + fprintf(fileWriteList, "%s", line2); + } + } + } + fclose(fileBanList); + fclose(fileWriteList); + remove("samp.ban"); + rename("samp.ban.temp", "samp.ban"); +} + +//---------------------------------------------------- + +void CNetGame::LoadBanList() +{ + m_pRak->ClearBanList(); + + FILE * fileBanList = fopen("samp.ban","r"); + + if(!fileBanList) { + return; + } + + char tmpban_ip[256]; + + while(!feof(fileBanList)) { + if (fgets(tmpban_ip,256,fileBanList)) { + int len = strlen(tmpban_ip); + if (len > 0 && tmpban_ip[len - 1] == '\n') + tmpban_ip[len - 1] = 0; + len = strlen(tmpban_ip); + if (len > 0 && tmpban_ip[len - 1] == '\r') + tmpban_ip[len - 2] = 0; + if (tmpban_ip[0] != 0 && tmpban_ip[0] != '#') { + char *ban_ip = strtok(tmpban_ip, " \t"); + m_pRak->AddToBanList(ban_ip); + } + } + } + + logprintf(""); + logprintf("Ban list"); + logprintf("--------"); + logprintf(" Loaded: samp.ban"); + logprintf(""); + + fclose(fileBanList); +} + +//---------------------------------------------------- + +int CNetGame::AddSpawn(PLAYER_SPAWN_INFO *pSpawnInfo) +{ + if (m_iSpawnsAvailable < MAX_SPAWNS) + { + memcpy(&m_AvailableSpawns[m_iSpawnsAvailable],pSpawnInfo,sizeof(PLAYER_SPAWN_INFO)); + return m_iSpawnsAvailable++; + } + return MAX_SPAWNS; } //---------------------------------------------------- diff --git a/server/netgame.h b/server/netgame.h index 9b2ac11..85cee20 100644 --- a/server/netgame.h +++ b/server/netgame.h @@ -4,7 +4,9 @@ #define MAX_SPAWNS 319 +#define GAMESTATE_STOPPED 0 #define GAMESTATE_RUNNING 1 +#define GAMESTATE_RESTARTING 2 #define INVALID_ID 0xFFFF @@ -77,29 +79,71 @@ public: void Init(BOOL bFirst); void ShutdownForGameModeRestart(); + void ReInitWhenRestarting(); BOOL SetNextScriptFile(char *szFile); + int GetGameState() { return m_iGameState; }; CPlayerPool * GetPlayerPool() { return m_pPlayerPool; }; CVehiclePool * GetVehiclePool() { return m_pVehiclePool; }; RakServerInterface * GetRakServer() { return m_pRak; }; CGameMode * GetGameMode() { return m_pGameMode; }; CFilterScripts * GetFilterScripts() { return m_pFilterScripts; }; + CMenuPool * GetMenuPool() { return m_pMenuPool; }; CGangZonePool * GetGangZonePool() { return m_pGangZonePool; }; CActorPool * GetActorPool() { return m_pActorPool; }; + void SendClientMessageToAll(DWORD dwColor, char* szMessage, ...); void MasterServerAnnounce(float fElapsedTime); + void UpdateTickCounter(); char *GetNextScriptFile(); void LoadAllFilterscripts(); void Process(); + void BroadcastData( char *szUniqueID, + RakNet::BitStream *bitStream, + PLAYERID excludedPlayer, + char orderingStream ); + + void SendToPlayer( char *szUniqueID, + RakNet::BitStream *bitStream, + PLAYERID playerId, + char orderingChannel ); + + // Packet Handlers + void Packet_AimSync(Packet *p); + void Packet_PlayerSync(Packet *p); + void Packet_VehicleSync(Packet *p); + void Packet_PassengerSync(Packet *p); + void Packet_SpectatorSync(Packet *p); + void Packet_WeaponShotSync(Packet *p); + void Packet_NewIncomingConnection(Packet* packet); + void Packet_DisconnectionNotification(Packet* packet); + void Packet_ConnectionLost(Packet* packet); + void Packet_ModifiedPacket(Packet* packet); + void Packet_RemotePortRefused(Packet* packet); + void Packet_InGameRcon(Packet* packet); + void Packet_StatsUpdate(Packet *p); + void Packet_WeaponsUpdate(Packet *p); + void Packet_TrailerSync(Packet *p); + void Packet_UnoccupiedSync(Packet *p); + + void KickPlayer(PLAYERID kickPlayer); + void BlockIpAddress(char *ip_address, int timems); + void UnBlockIpAddress(char *ip_address); + void AddBan(char * nick, char * ip_mask, char * reason); + void RemoveBan(char * ip_mask); void LoadBanList(); // CLASS SYSTEM int m_iSpawnsAvailable; PLAYER_SPAWN_INFO m_AvailableSpawns[MAX_SPAWNS]; + int AddSpawn(PLAYER_SPAWN_INFO *pSpawnInfo); + void SetWorldTime(BYTE byteHour); + void SetWeather(BYTE byteWeather); + void SetGravity(float fGravity); const PCHAR GetWeaponName(int iWeaponID); DWORD GetTime(); diff --git a/server/object.cpp b/server/object.cpp new file mode 100644 index 0000000..e69de29 diff --git a/server/object.h b/server/object.h new file mode 100644 index 0000000..4c449a0 --- /dev/null +++ b/server/object.h @@ -0,0 +1,5 @@ + +#ifndef SAMPSRV_OBJECT_H +#define SAMPSRV_OBJECT_H + +#endif diff --git a/server/objectpool.cpp b/server/objectpool.cpp index e06cb7c..40110f0 100644 --- a/server/objectpool.cpp +++ b/server/objectpool.cpp @@ -29,6 +29,11 @@ CObjectPool::~CObjectPool() } } +void CObjectPool::Process(float fElapsedTime) +{ + // TODO: CObjectPool::Process +} + BOOL CObjectPool::Delete(WORD wObjectID) { // TODO: CObjectPool::Delete W .text:004657A0 L .text:080C89A0 diff --git a/server/objectpool.h b/server/objectpool.h index a4b9a98..3c1ba0a 100644 --- a/server/objectpool.h +++ b/server/objectpool.h @@ -18,6 +18,8 @@ public: BOOL Delete(WORD wObjectID); BOOL DeleteForPlayer(PLAYERID playerId, WORD wObjectID); + + void Process(float fElapsedTime); }; #endif diff --git a/server/player.cpp b/server/player.cpp index 4f9f72d..69d92a3 100644 --- a/server/player.cpp +++ b/server/player.cpp @@ -5,9 +5,68 @@ extern CNetGame *pNetGame; //---------------------------------------------------- -void CPlayer::Say(unsigned char * szText, BYTE byteTextLen) +CPlayer::CPlayer() { - // TODO: CPlayer::Say + m_PlayerID = INVALID_PLAYER_ID; + field_2963 = 0; + field_290D = 0; + field_295F = 0; + field_2CDA = 0; + field_2CD1 = 0; + memset(&m_aimSync,0,sizeof(AIM_SYNC_DATA)); + memset(&m_icSync,0,sizeof(INCAR_SYNC_DATA)); + memset(&m_psSync,0,sizeof(PASSENGER_SYNC_DATA)); + memset(&m_ofSync,0,sizeof(ONFOOT_SYNC_DATA)); + memset(&m_spSync,0,sizeof(SPECTATOR_SYNC_DATA)); + memset(&m_trSync,0,sizeof(TRAILER_SYNC_DATA)); + field_2C85 = 0; + ResetAllSyncAttributes(); +} + +//---------------------------------------------------- + +void CPlayer::ResetAllSyncAttributes() +{ + field_2969 = 0; + m_VehicleID = 0; + field_2B9D = 0; + field_2BA1 = 0; + field_2951 = 0; + field_2915 = 0; + field_2919 = 0; + field_291D = 0; + field_292D = 0; + field_2931 = 0; + field_2935 = 0; + field_2929 = 0; + field_2939 = 0; + field_2921 = 0; + field_2925 = 0; + field_2CB8 = 0.0f; + m_bCheckpointEnabled = FALSE; + m_bRaceCheckpointEnabled = FALSE; + m_iInteriorId = 0; + m_dwColor = 0; + field_2949 = 0; + field_294B = 0; + field_294D = 0; + m_byteState = PLAYER_STATE_NONE; + field_2CB7 = 0; + field_2C2F = 0; + field_2C30 = 4; + field_2CBC = 0; + field_2CBD = -1; + m_byteSeatID = 0; + field_28F5 = 0; + field_28F9 = 0; + field_2BDF = 0; + field_2CC1 = pNetGame->GetTime(); + + for (int i = 0; i < 13; i++) + { + m_byteSlotWeapon[i] = 0; + m_dwSlotAmmo[i] = 0; + } } //---------------------------------------------------- diff --git a/server/player.h b/server/player.h index 89864f8..7bae6e6 100644 --- a/server/player.h +++ b/server/player.h @@ -219,7 +219,9 @@ public: BYTE GetState() { return m_byteState; }; - void Say(unsigned char * szText, BYTE byteTextLength); + CPlayer(); + + void ResetAllSyncAttributes(); void SetSpawnInfo(PLAYER_SPAWN_INFO *pSpawn); @@ -234,6 +236,8 @@ public: BOOL IsInCheckpoint() { return m_bInCheckpoint; }; BOOL IsInRaceCheckpoint() { return m_bInRaceCheckpoint; }; + void StoreAimSyncData(AIM_SYNC_DATA *paimSync) {} + void Say(unsigned char * szText, BYTE byteTextLength) {} }; //---------------------------------------------------- diff --git a/server/playerpool.cpp b/server/playerpool.cpp index 708601e..445a989 100644 --- a/server/playerpool.cpp +++ b/server/playerpool.cpp @@ -25,8 +25,75 @@ CPlayerPool::~CPlayerPool() } } +//---------------------------------------------------- + +BOOL CPlayerPool::New(PLAYERID playerId, PCHAR szPlayerName, PCHAR szClientID, PCHAR szVersion, BOOL bIsNPC) +{ + if(playerId > MAX_PLAYERS) return FALSE; + if(strlen(szPlayerName) > MAX_PLAYER_NAME) return FALSE; + + m_pPlayers[playerId] = new CPlayer(); + + if(m_pPlayers[playerId]) + { + strcpy(m_szPlayerName[playerId],szPlayerName); + memset(m_szPlayerClientID[playerId],0,sizeof(m_szPlayerClientID[playerId])); + memset(m_szPlayerVersion[playerId],0,sizeof(m_szPlayerVersion[playerId])); + + if(szClientID) { + if(strlen(szClientID) >= 100) + return FALSE; + strcpy(m_szPlayerClientID[playerId],szClientID); + } + + if(szVersion) { + if(strlen(szVersion) >= 24) + return FALSE; + strcpy(m_szPlayerVersion[playerId],szVersion); + } + + m_bPlayerSlotState[playerId] = TRUE; + m_iPlayerScore[playerId] = 0; + m_iPlayerMoney[playerId] = 0; + m_bIsAnAdmin[playerId] = FALSE; + m_iVirtualWorld[playerId] = 0; + m_iPlayerDrunkLevel[playerId] = 0; + + BYTE byteIsNPC; + if(bIsNPC) { + m_bIsAnNPC[playerId] = TRUE; + byteIsNPC = 1; + } else { + m_bIsAnNPC[playerId] = FALSE; + byteIsNPC = 0; + } + + // Notify all the other players of a newcommer with + // a 'ServerJoin' join RPC + RakNet::BitStream bsSend; + bsSend.Write(playerId); + bsSend.Write((DWORD)0); + bsSend.Write(byteIsNPC); + BYTE namelen = strlen(szPlayerName); + bsSend.Write(namelen); + bsSend.Write(szPlayerName,namelen); + + return TRUE; + } + else + { + return FALSE; + } +} + BOOL CPlayerPool::Delete(PLAYERID playerId, BYTE byteReason) { // TODO: CPlayerPool::Delete W .text:00466570 L .text:080D0A90 return FALSE; } + +BOOL CPlayerPool::Process(float fElapsedTime) +{ + // TODO: CPlayerPool::Process + return TRUE; +} diff --git a/server/playerpool.h b/server/playerpool.h index e6e11af..df1c41d 100644 --- a/server/playerpool.h +++ b/server/playerpool.h @@ -2,6 +2,8 @@ #ifndef SAMPSRV_PLAYERPOOL_H #define SAMPSRV_PLAYERPOOL_H +#define INVALID_PLAYER_ID 0xFFFF + class CPlayerPool // size: WL 199024 { private: @@ -34,6 +36,8 @@ public: CPlayerPool(); ~CPlayerPool(); + BOOL Process(float fElapsedTime); + BOOL New(PLAYERID playerId, PCHAR szPlayerName, PCHAR szClientID, PCHAR szVersion, BOOL bIsNPC); BOOL Delete(PLAYERID playerId, BYTE byteReason); // Retrieve a player @@ -58,6 +62,16 @@ public: return m_szPlayerClientID[playerId]; }; + void SetPlayerMoney(PLAYERID playerId, int iMoney) { + if(playerId >= MAX_PLAYERS) return; + m_iPlayerMoney[playerId] = iMoney; + }; + + void SetPlayerDrunkLevel(PLAYERID playerId, int iLevel) { + if(playerId >= MAX_PLAYERS) return; + m_iPlayerDrunkLevel[playerId] = iLevel; + }; + void ResetPlayerScoresAndMoney() { memset(&m_iPlayerScore[0],0,sizeof(int) * MAX_PLAYERS); memset(&m_iPlayerMoney[0],0,sizeof(int) * MAX_PLAYERS); diff --git a/server/pluginkey.h b/server/pluginkey.h new file mode 100644 index 0000000..8fbe599 --- /dev/null +++ b/server/pluginkey.h @@ -0,0 +1,25 @@ + +#ifndef _PLUGINKEY_H_INCLUDED +#define _PLUGINKEY_H_INCLUDED + +#define PLUGIN_PUB_KEY_SIZE 132 +const BYTE PLUGIN_PUB_KEY[] = + {0x1, 0x0, 0x1, 0x0, 0xcb, 0xb5, 0xf6, 0x37, + 0xbf, 0x7b, 0x81, 0x8c, 0xba, 0xbb, 0xf4, 0x97, + 0xab, 0xb8, 0xb, 0x40, 0xfb, 0xb1, 0xe8, 0x87, + 0xf5, 0x7d, 0xb4, 0x7c, 0xce, 0x85, 0xbe, 0xcd, + 0x5d, 0xdb, 0x4, 0x41, 0x6a, 0xa7, 0xbf, 0x77, + 0x60, 0xac, 0xb9, 0x15, 0x2f, 0xb3, 0xbd, 0x39, + 0xcb, 0x6d, 0x2f, 0x4e, 0xb, 0x2a, 0xa1, 0xb8, + 0x28, 0x47, 0xa1, 0x7c, 0x6a, 0xc0, 0x75, 0x6e, + 0x77, 0xc2, 0xaf, 0xc6, 0x33, 0xfe, 0xc, 0x57, + 0x1, 0x3, 0xff, 0x4b, 0xcb, 0x4c, 0xd, 0x1b, + 0x63, 0x5d, 0x52, 0xac, 0x91, 0xf3, 0x91, 0x33, + 0xce, 0xca, 0x8a, 0x2f, 0x2d, 0x9b, 0xad, 0x2f, + 0xf2, 0x35, 0x9b, 0x46, 0xe2, 0x24, 0x34, 0x60, + 0x10, 0xf1, 0xcf, 0xf3, 0x2d, 0xaa, 0x4d, 0x86, + 0xe5, 0x7b, 0x60, 0x42, 0x3e, 0xd9, 0x7, 0xc0, + 0x5d, 0xf9, 0x7e, 0x3, 0x5d, 0x82, 0xb8, 0x38, + 0x89, 0x9, 0x92, 0x87}; + +#endif diff --git a/server/plugins.cpp b/server/plugins.cpp index 4157416..e25d78c 100644 --- a/server/plugins.cpp +++ b/server/plugins.cpp @@ -141,6 +141,85 @@ CPlugins::~CPlugins() //--------------------------------------- +void CPlugins::ConvertFromHex(unsigned char* pbBuffer, char* szData, unsigned int dwMaxLength) +{ + unsigned int i=0, dwTemp=0; + char szTemp[4] = {0,0,0,0}; + while(szData[i]!=0) + { + if ((i/2) >= dwMaxLength) + break; + if (szData[i+0]==0 || szData[i+1]==0) + break; + szTemp[0] = szData[i+0]; + szTemp[1] = szData[i+1]; + sscanf(szTemp, "%X", &dwTemp); + pbBuffer[i/2] = dwTemp; + i+=2; + } +} + +//--------------------------------------- + +/*bool CPlugins::VerifyPluginSignature(char* szPluginFilename) +{ + CSHA1 sha1; + sha1.HashFile(szPluginFilename); + sha1.Final(); + BYTE* pbHash = sha1.GetHash(); + + // TODO: CPlugins::VerifyPluginSignature +}*/ + +//--------------------------------------- + +bool CPlugins::IsValidForNoSign(char* szFilename) +{ + char szLCFilename[MAX_PATH]; + + int i = 0, j = 0; + for(i=strlen(szFilename)-1; i>=0; i--) + { + if (szFilename[i] == '.') + { + j=i; + } + if (szFilename[i] == '\\' || szFilename[i] == '/') + { + i++; + break; + } + } + + strcpy(szLCFilename, szFilename+i); // Get part of filename with the \ or / + szLCFilename[j-i] = 0; // Get rid of extension + + char *szNoSign = pConsole->GetStringVariable("nosign"); + char *szLCNoSign = new char[strlen(szNoSign)+1]; + strcpy(szLCNoSign, szNoSign); + + char *szTok = strtok(szLCNoSign, " "); + while(szTok) + { +#ifdef LINUX + if (strcmp(szTok, szLCFilename)==0) +#else + if (strcmpi(szTok, szLCFilename)==0) +#endif + { + delete[] szLCNoSign; + return true; + } + szTok = strtok(NULL, " "); + } + + delete[] szLCNoSign; + + return false; +} + +//--------------------------------------- + BOOL CPlugins::LoadSinglePlugin(char *szPluginPath) { // Load it diff --git a/server/plugins.h b/server/plugins.h index 9ff544e..a568cde 100644 --- a/server/plugins.h +++ b/server/plugins.h @@ -60,6 +60,9 @@ private: BOOL LoadSinglePlugin(char *szPluginPath); + void ConvertFromHex(unsigned char* pbBuffer, char* szData, unsigned int dwMaxLength); + bool IsValidForNoSign(char* szFilename); + public: CPlugins(); ~CPlugins(); diff --git a/server/query.cpp b/server/query.cpp new file mode 100644 index 0000000..c1c38c0 --- /dev/null +++ b/server/query.cpp @@ -0,0 +1,24 @@ + +#include "main.h" + +//---------------------------------------------------- + +int ProcessQueryPacket(unsigned int binaryAddress, unsigned short port, char* data, int length, SOCKET s) +{ + + + if ((length > 4) && (*(unsigned long*)(data) == 0x504D4153)) + { + if(!pNetGame || (pNetGame->GetGameState() != GAMESTATE_RUNNING)) return 0; + + if (length >= 11) + { + // TODO: ProcessQueryPacket + } + return 1; + } else { + return 0; + } +} + +//---------------------------------------------------- diff --git a/server/runutil.cpp b/server/runutil.cpp index b7d790d..e7d9f21 100644 --- a/server/runutil.cpp +++ b/server/runutil.cpp @@ -1,4 +1,271 @@ + #include +#include + +//---------------------------------------------------- + +char Util_toupper(char c) {return ((c>(char)0x60) && (c<(char)0x7b))? c-0x20:c;} + +//---------------------------------------------------- + + + + + + + +//---------------------------------------------------- + +void Util_strupr(char *string) +{ + char *p = string; + + while(*p) { + *p = Util_toupper(*p); + p++; + } +} + +//---------------------------------------------------- + +int Util_wildcmp(char *wild, char *string) +{ + char *cp, *mp; + + while((*string) && (*wild != '*')) + { + if((*wild != *string) && (*wild != '?')) + { + return 0; + } + wild++; + string++; + } + + while (*string) + { + if (*wild == '*') + { + if (!*++wild) + { + return 1; + } + mp = wild; + cp = string+1; + } + else if ((*wild == *string) || (*wild == '?')) + { + wild++; + string++; + } + else + { + wild = mp; + string = cp++; + } + } + + while (*wild == '*') + { + wild++; + } + + return !*wild; +} + +//---------------------------------------------------- + +int Util_strnicmp(const char *s1, const char *s2, size_t n) +{ + + if (n == 0) return 0; + + do + { + if (Util_toupper((unsigned char)*s1) != Util_toupper((unsigned char)*s2++)) + return (int)Util_toupper((unsigned char)*s1) - (int)Util_toupper((unsigned char)*--s2); + if (*s1++ == 0) + break; + + } while (--n != 0); + + return 0; +} + +//---------------------------------------------------- + +char *Util_strrev(char *str) +{ + char *p1, *p2; + + if (! str || ! *str) + return str; + for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2) + { + *p1 ^= *p2; + *p2 ^= *p1; + *p1 ^= *p2; + } + return str; +} + +//---------------------------------------------------- + +char * Util_itoa(int v, char *s, int r) +{ + int i,neg = 0; + char *p = s; + char *q = s; + + if (r < 0 || r > 35) { + *s = 0; + return (s); + } + if (r == 0) r = 10; + if (v == 0) { + *p++ = '0'; + *p = 0; + return (s); + } + if (v < 0) { + neg = 1; + v = -v; + } + while (v > 0) { + i = v % r; + if (i > 9) i += 7; + *p++ = '0' + i; + v /= r; + } + if (neg) *p++ = '-'; + *p-- = 0; + q = s; + while (p > q) { + i = *q; + *q++ = *p; + *p-- = i; + } + return (s); +} + +//---------------------------------------------------- + +char * Util_utoa(unsigned int v, char *s, int r) +{ + int i; + char *p = s; + char *q = s; + + if (r < 0 || r > 35) { + *s = 0; + return (s); + } + if (r == 0) r = 10; + if (v == 0) { + *p++ = '0'; + *p = 0; + return (s); + } + while (v > 0) { + i = v % r; + if (i > 9) i += 7; + *p++ = '0' + i; + v /= r; + } + *p-- = 0; + q = s; + while (p > q) { + i = *q; + *q++ = *p; + *p-- = i; + } + return (s); +} + +//---------------------------------------------------- + +char * Base64Encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + +void Util_Base64Encode( char *cpInput, char *cpOutput ) +{ +int nIdx[ 4 ]; +while ( '\0' != *cpInput ) +{ + nIdx[0] = ((*cpInput) & 0xFC)>>2; + nIdx[1] = ((*cpInput) & 0x03)<<4; + cpInput++; + if ( '\0' != *cpInput ) + { + nIdx[1] |= ((*cpInput) & 0xF0)>>4; + nIdx[2] = ((*cpInput) & 0x0F)<<2; + cpInput++; + if ( '\0' != (*cpInput) ) + { + nIdx[2] |= ((*cpInput) & 0xC0) >> 6; + nIdx[3] = (*cpInput) & 0x3F; + cpInput++; + } + else + nIdx[3] = 64; + } + else + { + nIdx[2] = 64; + nIdx[3] = 64; + } + + *(cpOutput+0) = *(Base64Encoding + nIdx[0]); + *(cpOutput+1) = *(Base64Encoding + nIdx[1]); + *(cpOutput+2) = *(Base64Encoding + nIdx[2]); + *(cpOutput+3) = *(Base64Encoding + nIdx[3]); + cpOutput += 4; +} + +*cpOutput = '\0'; + +return; +} + +//---------------------------------------------------- + +bool ContainsInvalidNickChars(char * szString) +{ + int x=0; + + while(*szString) { + if( (*szString >= '0' && *szString <= '9') || + (*szString >= 'A' && *szString <= 'Z') || + (*szString >= 'a' && *szString <= 'z') || + *szString == ']' || *szString == '[' || + *szString == '_' || *szString == '$' || + *szString == '=' || *szString == '(' || + *szString == ')' || *szString == '@' || + *szString == '.' ) { + + szString++; + } else { + return true; + } + } + return false; +} + +//---------------------------------------------------- + +int IsHexChar(char c) +{ + if( (c >= '0' && c <= '9') || + (c >= 'A' && c <= 'F') || + (c >= 'a' && c <= 'f') ) + { + return 1; + } + return 0; +} + + + + //---------------------------------------------------- diff --git a/server/runutil.h b/server/runutil.h index 8b13789..bb92028 100644 --- a/server/runutil.h +++ b/server/runutil.h @@ -1 +1,12 @@ +char Util_toupper(char c); + +void Util_strupr(char *string); +int Util_wildcmp(char *wild, char *string); +int Util_strnicmp(const char *s1, const char *s2, size_t n); +char *Util_strrev(char *str); +char * Util_itoa(int v, char *s, int r); +char * Util_utoa(unsigned int v, char *s, int r); +void Util_Base64Encode( char *cpInput, char *cpOutput ); + + diff --git a/server/scrcore.cpp b/server/scrcore.cpp index 8606615..3dd3908 100644 --- a/server/scrcore.cpp +++ b/server/scrcore.cpp @@ -164,3 +164,13 @@ int set_amxstring(AMX *amx,cell amx_addr,const char *source,int max) //---------------------------------------------------------------------------------- +char* format_amxstring(AMX *amx, cell *params, int parm, int &len) +{ + static char outbuf[4096]; + memset(outbuf,0,4096); + cell *addr = get_amxaddr(amx, params[parm++]); + len = atcprintf(outbuf, sizeof(outbuf)-1, addr, amx, params, &parm); + return outbuf; +} + +//---------------------------------------------------------------------------------- diff --git a/server/scrcustom.cpp b/server/scrcustom.cpp index e2f5988..c0f43cb 100644 --- a/server/scrcustom.cpp +++ b/server/scrcustom.cpp @@ -53,25 +53,28 @@ static cell AMX_NATIVE_CALL n_GetActorPoolSize(AMX *amx, cell *params) } //---------------------------------------------------------------------------------- - +// native print(const string[]) static cell AMX_NATIVE_CALL n_print(AMX *amx, cell *params) { // TODO: print return 0; } +// native printf(const format[], {Float,_}:...) static cell AMX_NATIVE_CALL n_printf(AMX *amx, cell *params) { // TODO: printf return 0; } +// native format(output[], len, const format[], {Float,_}:...) static cell AMX_NATIVE_CALL n_format(AMX *amx, cell *params) { // TODO: format return 0; } +// native SetTimer(funcname[], interval, repeating) static cell AMX_NATIVE_CALL n_SetTimer(AMX *amx, cell *params) { char* szFuncName; @@ -79,6 +82,7 @@ static cell AMX_NATIVE_CALL n_SetTimer(AMX *amx, cell *params) return pNetGame->GetTimers()->New(szFuncName, params[2], params[3], amx); } +// native KillTimer(timerid) static cell AMX_NATIVE_CALL n_KillTimer(AMX *amx, cell *params) { pNetGame->GetTimers()->Kill(params[1]); @@ -103,7 +107,7 @@ static cell AMX_NATIVE_CALL n_GetMaxPlayers(AMX *amx, cell *params) } //---------------------------------------------------------------------------------- - +// native SetTimerEx(funcname[], interval, repeating, const format[], {Float,_}:...) static cell AMX_NATIVE_CALL n_SetTimerEx(AMX *amx, cell *params) { if (params[0] < 4 * sizeof (cell)) @@ -147,7 +151,7 @@ static cell AMX_NATIVE_CALL n_LimitPlayerMarkerRadius(AMX *amx, cell *params) } //---------------------------------------------------------------------------------- - +// native SetWeather(weatherid) static cell AMX_NATIVE_CALL n_SetWeather(AMX *amx, cell *params) { // TODO: SetWeather @@ -160,12 +164,14 @@ static cell AMX_NATIVE_CALL n_SetPlayerWeather(AMX *amx, cell *params) return 0; } +// native CallRemoteFunction(const function[], const format[], {Float,_}:...) static cell AMX_NATIVE_CALL n_CallRemoteFunction(AMX *amx, cell *params) { // TODO: CallRemoteFunction return 0; } +// native CallLocalFunction(const function[], const format[], {Float,_}:...) static cell AMX_NATIVE_CALL n_CallLocalFunction(AMX *amx, cell *params) { // TODO: CallLocalFunction @@ -186,24 +192,28 @@ static cell AMX_NATIVE_CALL n_VectorSize(AMX *amx, cell *params) //---------------------------------------------------------------------------------- +// native Float:asin(Float:value) static cell AMX_NATIVE_CALL n_asin(AMX *amx, cell *params) { float fResult = (float)(asin(amx_ctof(params[1])) * (180.0f / PI)); return amx_ftoc(fResult); } +// native Float:acos(Float:value) static cell AMX_NATIVE_CALL n_acos(AMX *amx, cell *params) { float fResult = (float)(acos(amx_ctof(params[1])) * (180.0f / PI)); return amx_ftoc(fResult); } +// native Float:atan(Float:value) static cell AMX_NATIVE_CALL n_atan(AMX *amx, cell *params) { float fResult = (float)(atan(amx_ctof(params[1])) * (180.0f / PI)); return amx_ftoc(fResult); } +// native Float:atan2(Float:x, Float:y) static cell AMX_NATIVE_CALL n_atan2(AMX *amx, cell *params) { float fResult = (float)(atan2(amx_ctof(params[1]), amx_ctof(params[2])) * (180.0f / PI)); @@ -212,66 +222,77 @@ static cell AMX_NATIVE_CALL n_atan2(AMX *amx, cell *params) //---------------------------------------------------- +// native SHA256_PassHash(password[], salt[], ret_hash[], ret_hash_len) static cell AMX_NATIVE_CALL n_SHA256_PassHash(AMX *amx, cell *params) { // TODO: SHA256_PassHash return 0; } +// native SetSVarInt(varname[], int_value) static cell AMX_NATIVE_CALL n_SetSVarInt(AMX *amx, cell *params) { // TODO: SetSVarInt return 0; } +// native SetSVarString(varname[], string_value[]) static cell AMX_NATIVE_CALL n_SetSVarString(AMX *amx, cell *params) { // TODO: SetSVarString return 0; } +// native SetSVarFloat(varname[], Float:float_value) static cell AMX_NATIVE_CALL n_SetSVarFloat(AMX *amx, cell *params) { // TODO: SetSVarFloat return 0; } +// native GetSVarInt(varname[]) static cell AMX_NATIVE_CALL n_GetSVarInt(AMX *amx, cell *params) { // TODO: GetSVarInt return 0; } +// native GetSVarString(varname[], string_return[], len) static cell AMX_NATIVE_CALL n_GetSVarString(AMX *amx, cell *params) { // TODO: GetSVarString return 0; } +// native Float:GetSVarFloat(varname[]) static cell AMX_NATIVE_CALL n_GetSVarFloat(AMX *amx, cell *params) { // TODO: GetSVarFloat return 0; } +// native DeleteSVar(varname[]) static cell AMX_NATIVE_CALL n_DeleteSVar(AMX *amx, cell *params) { // TODO: DeleteSVar return 0; } +// native GetSVarType(varname[]) static cell AMX_NATIVE_CALL n_GetSVarType(AMX *amx, cell *params) { // TODO: GetSVarType return 0; } +// native GetSVarNameAtIndex(index, ret_varname[], ret_len) static cell AMX_NATIVE_CALL n_GetSVarNameAtIndex(AMX *amx, cell *params) { // TODO: GetSVarNameAtIndex return 0; } +// native GetSVarsUpperIndex() static cell AMX_NATIVE_CALL n_GetSVarsUpperIndex(AMX *amx, cell *params) { // TODO: GetSVarsUpperIndex @@ -307,42 +328,49 @@ static cell AMX_NATIVE_CALL n_SetTeamCount(AMX *amx, cell *params) return 0; } +// native AddPlayerClass(modelid, Float:spawn_x, Float:spawn_y, Float:spawn_z, Float:z_angle, weapon1, weapon1_ammo, weapon2, weapon2_ammo, weapon3, weapon3_ammo) static cell AMX_NATIVE_CALL n_AddPlayerClass(AMX *amx, cell *params) { // TODO: AddPlayerClass return 0; } +// native AddPlayerClassEx(teamid, modelid, Float:spawn_x, Float:spawn_y, Float:spawn_z, Float:z_angle, weapon1, weapon1_ammo, weapon2, weapon2_ammo, weapon3, weapon3_ammo) static cell AMX_NATIVE_CALL n_AddPlayerClassEx(AMX *amx, cell *params) { // TODO: AddPlayerClassEx return 0; } +// native AddStaticVehicle(modelid, Float:spawn_x, Float:spawn_y, Float:spawn_z, Float:z_angle, color1, color2) static cell AMX_NATIVE_CALL n_AddStaticVehicle(AMX *amx, cell *params) { // TODO: AddStaticVehicle return 0; } +// native AddStaticVehicleEx(modelid, Float:spawn_x, Float:spawn_y, Float:spawn_z, Float:z_angle, color1, color2, respawn_delay, addsiren=0) static cell AMX_NATIVE_CALL n_AddStaticVehicleEx(AMX *amx, cell *params) { // TODO: AddStaticVehicleEx return 0; } +// native AddStaticPickup(model, type, Float:X, Float:Y, Float:Z, virtualworld = 0) static cell AMX_NATIVE_CALL n_AddStaticPickup(AMX *amx, cell *params) { // TODO: AddStaticPickup return 0; } +// native CreatePickup(model, type, Float:X, Float:Y, Float:Z, virtualworld = 0) static cell AMX_NATIVE_CALL n_CreatePickup(AMX *amx, cell *params) { // TODO: CreatePickup return 0; } +// native DestroyPickup(pickup) static cell AMX_NATIVE_CALL n_DestroyPickup(AMX *amx, cell *params) { // TODO: DestroyPickup @@ -375,6 +403,7 @@ static cell AMX_NATIVE_CALL n_ShowPlayerMarkers(AMX *amx, cell *params) //---------------------------------------------------------------------------------- +// native SetWorldTime(hour) static cell AMX_NATIVE_CALL n_SetWorldTime(AMX *amx, cell *params) { // TODO: SetWorldTime @@ -417,6 +446,7 @@ static cell AMX_NATIVE_CALL n_AllowInteriorWeapons(AMX *amx, cell *params) //---------------------------------------------------------------------------------- +// native SetGravity(Float:gravity) static cell AMX_NATIVE_CALL n_SetGravity(AMX *amx, cell *params) { // TODO: SetGravity @@ -448,7 +478,7 @@ static cell AMX_NATIVE_CALL n_SetDeathDropAmount(AMX *amx, cell *params) } //---------------------------------------------------------------------------------- - +// native CreateExplosion(Float:X, Float:Y, Float:Z, type, Float:Radius) static cell AMX_NATIVE_CALL n_CreateExplosion(AMX *amx, cell *params) { // TODO: CreateExplosion @@ -461,6 +491,7 @@ static cell AMX_NATIVE_CALL n_CreateExplosionForPlayer(AMX *amx, cell *params) return 0; } +// static cell AMX_NATIVE_CALL n_SetDisabledWeapons(AMX *amx, cell *params) { logprintf("[warning] SetDisabledWeapons() : function is deprecated. Check weapon in OnPlayerUpdate."); @@ -497,6 +528,7 @@ static cell AMX_NATIVE_CALL n_DisableNameTagLOS(AMX *amx, cell *params) return 1; } +// native ConnectNPC(name[], script[]) static cell AMX_NATIVE_CALL n_ConnectNPC(AMX *amx, cell *params) { // TODO: ConnectNPC @@ -1029,8 +1061,15 @@ static cell AMX_NATIVE_CALL n_GetPlayerSurfingObjectID(AMX *amx, cell *params) return 0xFFFF; } +// native PutPlayerInVehicle(playerid, vehicleid, seatid) static cell AMX_NATIVE_CALL n_PutPlayerInVehicle(AMX *amx, cell *params) { + CPlayerPool *pPlayerPool = pNetGame->GetPlayerPool(); + if(!pPlayerPool) return 0; + + CVehiclePool *pVehiclePool = pNetGame->GetVehiclePool(); + if(!pVehiclePool) return 0; + // TODO: PutPlayerInVehicle return 0; } @@ -2167,9 +2206,13 @@ static cell AMX_NATIVE_CALL n_SetVehicleVirtualWorld(AMX *amx, cell *params) return 0; } +// native GetVehicleVirtualWorld(vehicleid) static cell AMX_NATIVE_CALL n_GetVehicleVirtualWorld(AMX *amx, cell *params) { - // TODO: GetVehicleVirtualWorld + if (pNetGame->GetVehiclePool()->GetSlotState((VEHICLEID)params[1])) + { + return pNetGame->GetVehiclePool()->GetVehicleVirtualWorld((VEHICLEID)params[1]); + } return 0; } @@ -2672,64 +2715,105 @@ static cell AMX_NATIVE_CALL n_IsActorInvulnerable(AMX *amx, cell *params) return 0; } +// Menus + +// native Menu:CreateMenu(const title[], columns, Float:x, Float:y, Float:col1width, Float:col2width = 0.0); static cell AMX_NATIVE_CALL n_CreateMenu(AMX *amx, cell *params) { - // TODO: CreateMenu - return 0; + CMenuPool* pMenuPool = pNetGame->GetMenuPool(); + if (!pMenuPool) return -1; + char* szMenuTitle; + amx_StrParam(amx, params[1], szMenuTitle); + BYTE menuid = pMenuPool->New(szMenuTitle, amx_ctof(params[3]), amx_ctof(params[4]), params[2], amx_ctof(params[5]), amx_ctof(params[6])); + if (menuid == 0xFF) return -1; + return menuid; } +// native DestroyMenu(Menu:menuid); static cell AMX_NATIVE_CALL n_DestroyMenu(AMX *amx, cell *params) { - // TODO: DestroyMenu + CMenuPool* pMenuPool = pNetGame->GetMenuPool(); + if (!pMenuPool) return 0; + if (pMenuPool->Delete(params[1])) return 1; return 0; } +// native AddMenuItem(Menu:menuid, column, const menutext[]); static cell AMX_NATIVE_CALL n_AddMenuItem(AMX *amx, cell *params) { - // TODO: AddMenuItem - return 0; + CMenuPool* pMenuPool = pNetGame->GetMenuPool(); + if (!pMenuPool) return 0; + char* szItemText; + amx_StrParam(amx, params[3], szItemText); + BYTE ret = pMenuPool->GetAt((BYTE)params[1])->AddMenuItem(params[2], szItemText); + if (ret == 0xFF) return -1; + return ret; } +// native SetMenuColumnHeader(Menu:menuid, column, const columnheader[]); static cell AMX_NATIVE_CALL n_SetMenuColumnHeader(AMX *amx, cell *params) { - // TODO: SetMenuColumnHeader - return 0; + CMenuPool* pMenuPool = pNetGame->GetMenuPool(); + if (!pMenuPool) return 0; + char* szItemText; + amx_StrParam(amx, params[3], szItemText); + pMenuPool->GetAt((BYTE)params[1])->SetColumnTitle(params[2], szItemText); + return 1; } +// native ShowMenuForPlayer(Menu:menuid, playerid); static cell AMX_NATIVE_CALL n_ShowMenuForPlayer(AMX *amx, cell *params) { - // TODO: ShowMenuForPlayer - return 0; + if (!pNetGame->GetPlayerPool()->GetSlotState((PLAYERID)params[2])) return 0; + CMenuPool* pMenuPool = pNetGame->GetMenuPool(); + if (!pMenuPool) return 0; + pMenuPool->GetAt((BYTE)params[1])->ShowForPlayer((PLAYERID)params[2]); + pMenuPool->SetPlayerMenu((PLAYERID)params[2], (BYTE)params[1]); + return 1; } +// native HideMenuForPlayer(Menu:menuid, playerid); static cell AMX_NATIVE_CALL n_HideMenuForPlayer(AMX *amx, cell *params) { - // TODO: HideMenuForPlayer - return 0; + if (!pNetGame->GetPlayerPool()->GetSlotState((PLAYERID)params[2])) return 0; + CMenuPool* pMenuPool = pNetGame->GetMenuPool(); + if (!pMenuPool) return 0; + pMenuPool->GetAt((BYTE)params[1])->HideForPlayer((PLAYERID)params[2]); + return 1; } +// native IsValidMenu(Menu:menuid); static cell AMX_NATIVE_CALL n_IsValidMenu(AMX *amx, cell *params) { - // TODO: IsValidMenu + CMenuPool* pMenuPool = pNetGame->GetMenuPool(); + if (pMenuPool && pMenuPool->GetSlotState(params[1])) return 1; return 0; } +// native DisableMenu(Menu:menuid); static cell AMX_NATIVE_CALL n_DisableMenu(AMX *amx, cell *params) { - // TODO: DisableMenu - return 0; + CMenuPool* pMenuPool = pNetGame->GetMenuPool(); + if (!pMenuPool) return 0; + pMenuPool->GetAt((BYTE)params[1])->DisableInteraction(); + return 1; } +// native DisableMenuRow(Menu:menuid, row); static cell AMX_NATIVE_CALL n_DisableMenuRow(AMX *amx, cell *params) { - // TODO: DisableMenuRow - return 0; + CMenuPool* pMenuPool = pNetGame->GetMenuPool(); + if (!pMenuPool) return 0; + pMenuPool->GetAt((BYTE)params[1])->DisableRow((BYTE)params[2]); + return 1; } +// native Menu:GetPlayerMenu(playerid); static cell AMX_NATIVE_CALL n_GetPlayerMenu(AMX *amx, cell *params) { - // TODO: GetPlayerMenu - return 0; + CMenuPool* pMenuPool = pNetGame->GetMenuPool(); + if (!pMenuPool) return 255; + return pMenuPool->GetPlayerMenu((PLAYERID)params[1]); } static cell AMX_NATIVE_CALL n_SetPlayerTime(AMX *amx, cell *params) @@ -2752,6 +2836,8 @@ static cell AMX_NATIVE_CALL n_GetPlayerTime(AMX *amx, cell *params) static cell AMX_NATIVE_CALL n_HTTP(AMX *amx, cell *params) { + if(!pNetGame) return 0; + // TODO: HTTP return 0; } diff --git a/server/scrhttps.cpp b/server/scrhttps.cpp index d376d01..b066789 100644 --- a/server/scrhttps.cpp +++ b/server/scrhttps.cpp @@ -12,3 +12,10 @@ CScriptHttps::CScriptHttps() } //---------------------------------------------------------------------------------- + +void CScriptHttps::Process() +{ + // TODO: CScriptHttps::Process() +} + +//---------------------------------------------------------------------------------- diff --git a/server/scrhttps.h b/server/scrhttps.h index c208ffb..61a9c70 100644 --- a/server/scrhttps.h +++ b/server/scrhttps.h @@ -9,6 +9,8 @@ private: public: CScriptHttps(); ~CScriptHttps() {}; + + void Process(); }; #endif diff --git a/server/server.sln b/server/server.sln index 79fa625..6d66d9a 100644 --- a/server/server.sln +++ b/server/server.sln @@ -1,5 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server", "server.vcproj", "{BD0C4C29-B3DF-4CAA-AFE4-F6C42A879C21}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "server", "server.vcproj", "{1FA99388-7480-4F50-A42A-A02406C91F3A}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject @@ -9,10 +9,10 @@ Global Release = Release EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution - {BD0C4C29-B3DF-4CAA-AFE4-F6C42A879C21}.Debug.ActiveCfg = Debug|Win32 - {BD0C4C29-B3DF-4CAA-AFE4-F6C42A879C21}.Debug.Build.0 = Debug|Win32 - {BD0C4C29-B3DF-4CAA-AFE4-F6C42A879C21}.Release.ActiveCfg = Release|Win32 - {BD0C4C29-B3DF-4CAA-AFE4-F6C42A879C21}.Release.Build.0 = Release|Win32 + {1FA99388-7480-4F50-A42A-A02406C91F3A}.Debug.ActiveCfg = Debug|Win32 + {1FA99388-7480-4F50-A42A-A02406C91F3A}.Debug.Build.0 = Debug|Win32 + {1FA99388-7480-4F50-A42A-A02406C91F3A}.Release.ActiveCfg = Release|Win32 + {1FA99388-7480-4F50-A42A-A02406C91F3A}.Release.Build.0 = Release|Win32 EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection diff --git a/server/server.vcproj b/server/server.vcproj index 993ae51..d159626 100644 --- a/server/server.vcproj +++ b/server/server.vcproj @@ -3,7 +3,8 @@ ProjectType="Visual C++" Version="7.10" Name="server" - ProjectGUID="{BD0C4C29-B3DF-4CAA-AFE4-F6C42A879C21}" + ProjectGUID="{1FA99388-7480-4F50-A42A-A02406C91F3A}" + RootNamespace="server" Keyword="Win32Proj"> + + @@ -740,12 +744,24 @@ + + + + + + + + @@ -764,6 +780,12 @@ + + + + @@ -782,6 +804,12 @@ + + + + @@ -806,18 +834,36 @@ + + + + + + + + + + + + @@ -827,6 +873,12 @@ + + + + diff --git a/server/signer.cpp b/server/signer.cpp new file mode 100644 index 0000000..22377a4 --- /dev/null +++ b/server/signer.cpp @@ -0,0 +1,14 @@ + +#include "signer.h" +#include "stdio.h" +#include "memory.h" + +//---------------------------------------------- + +void CSigner::SetPublicKey(unsigned char* pbKey) +{ + memcpy(&m_e, pbKey, sizeof(m_e)); + memcpy(m_n, pbKey+sizeof(m_e), sizeof(m_n)); +} + +//---------------------------------------------- diff --git a/server/signer.h b/server/signer.h new file mode 100644 index 0000000..fcfee3c --- /dev/null +++ b/server/signer.h @@ -0,0 +1,20 @@ + +#ifndef _SIGNER_H_INCLUDED +#define _SIGNER_H_INCLUDED + +#include "../raknet/RSACrypt.h" + +#define SIGNER_RSA_BIT_SIZE big::u1024 + +class CSigner +{ +private: + + big::u32 m_e; + SIGNER_RSA_BIT_SIZE m_n; + +public: + void SetPublicKey(unsigned char* pbKey); +}; + +#endif diff --git a/server/sqlite/simplearray.h b/server/sqlite/simplearray.h new file mode 100644 index 0000000..85fb88c --- /dev/null +++ b/server/sqlite/simplearray.h @@ -0,0 +1,113 @@ + +template +class SimpleArray +{ +public: + SimpleArray() : m_pData(NULL), m_nSize(0) {} + ~SimpleArray() { SetSize(0); } + + bool SetSize(unsigned int nNewSize); + + int Insert(T value); + bool Remove(unsigned int nIndex); + + // Member variables + T* m_pData; + unsigned int m_nSize; +}; + +template +bool SimpleArray::SetSize(unsigned int nNewSize) +{ + if(nNewSize == 0) + { + if(m_pData) + { + free(m_pData); + m_pData = NULL; + m_nSize = 0; + } + else + m_nSize = 0; + + return true; + } + + T* pData = (T*)realloc(m_pData, sizeof(T) * nNewSize); + if(pData) + { + m_pData = pData; + + if(m_nSize < nNewSize) + { + unsigned int nIndex = m_nSize; + do + { + m_pData[nIndex] = NULL; + nIndex++; + } + while(nIndex != nNewSize); + } + + m_nSize = nNewSize; + + return true; + } + + return false; +} + +template +int SimpleArray::Insert(T value) +{ + int nSize = (int)m_nSize; + int nIndex; + + for(nIndex = 0; nIndex != nSize; nIndex++) + { + if(m_pData[nIndex] == NULL) + break; + } + + if(nIndex >= 0) + { + m_pData[nIndex] = value; + return nIndex; + } + + if(SetSize(nSize + 1)) + { + m_pData[nSize] = value; + return nSize; + } + return -1; +} + +template +bool SimpleArray::Remove(unsigned int nIndex) +{ + int nCurrentSize = m_nSize; + int nIndex = 0; + int nNewSiye = -1; + + if(nCurrentSize == 0) + { + SetSize(0); + return; + } + + while(nIndex != nCurrentSize) + { + if(m_pData[nIndex]) + { + nNewSize = nIndex + } + nIndex++; + } + + if(nNewSize != -1) + SetSize(nNewSize + 1); + else + SetSize(0); +} + diff --git a/server/sqlite/sqlite_amx.cpp b/server/sqlite/sqlite_amx.cpp index 5198c0d..081227d 100644 --- a/server/sqlite/sqlite_amx.cpp +++ b/server/sqlite/sqlite_amx.cpp @@ -5,174 +5,200 @@ #include "../amx/amx.h" #include "sqlite3.h" +#include "simplearray.h" -// native DB:db_open(name[]); +extern iDbLogging; +void logprintf(char* format, ...); + +SimpleArray sqlite3Databases; + +// native SQLiteDB:sqlite_open(name[]); static cell AMX_NATIVE_CALL n_open(AMX* amx, cell* params) { - // TODO: n_open + char *szDBName, szPathName[260]; + int errorCode, i; + sqlite3 *sqlite=NULL; + + // Get the db filename + amx_StrParam(amx, params[1], szDBName); + + if (szDBName == NULL || szDBName == "") + { + return 0; + } + + // ensure the name doesn't start with a '/' or '\\' on win32 + if (szDBName[0] == '\\' || szDBName[0] == '/') + { + //logprintf(NATIVE_PREFIX "open - Warning: Database name can not start with %c", szDBName[0]); + return 0; + } + + // ensure there are no ".." in dbname, and no : + for(i=1; szDBName[i]!=0; i++) + { + if (szDBName[i-1] == '.' && szDBName[i] == '.') + { + //logprintf(NATIVE_PREFIX "open - Warning: Database name can not contain '..'"); + return 0; + } + } + + // ensure there are no : in the file + for(i=0; szDBName[i]!=0; i++) + { + if (szDBName[i] == ':') + { + //logprintf(NATIVE_PREFIX "open - Warning: Database name can not contain ':'"); + return 0; + } + } + + // Create the pathname string + sprintf(szPathName, "scriptfiles/%s", szDBName); + + // Open the database + errorCode = sqlite3_open(szPathName, &sqlite); + + if (errorCode != SQLITE_OK) + { + if (iDbLogging) + logprintf("[Error] Can't open sqlite database %s.", szPathName); + sqlite3_close(sqlite); + return 0; + } + + int index = sqlite3Databases.Insert(sqlite); + if(index < 0) + return 0; + return index + 1; } -// native db_close(DB:db); +// native sqlite_close(SQLiteDB:db); static cell AMX_NATIVE_CALL n_close(AMX* amx, cell* params) { // TODO: n_close return 0; } -// native DBResult:db_query(DB:db, query[]); static cell AMX_NATIVE_CALL n_query(AMX* amx, cell* params) { // TODO: n_query return 0; } -// native db_free_result(DBResult:dbresult); static cell AMX_NATIVE_CALL n_free_result(AMX* amx, cell* params) { // TODO: n_free_result return 0; } -// native db_num_rows(DBResult:dbresult); static cell AMX_NATIVE_CALL n_num_rows(AMX* amx, cell* params) { // TODO: n_num_rows return 0; } -// native db_next_row(DBResult:dbresult); static cell AMX_NATIVE_CALL n_next_row(AMX* amx, cell* params) { // TODO: n_next_row return 0; } -// native db_num_fields(DBResult:dbresult); static cell AMX_NATIVE_CALL n_num_fields(AMX* amx, cell* params) { // TODO: n_num_fields return 0; } -// native db_field_name(DBResult:dbresult, field, result[], maxlength); static cell AMX_NATIVE_CALL n_field_name(AMX* amx, cell* params) { // TODO: n_field_name return 0; } -// native db_get_field(DBResult:dbresult, field, result[], maxlength); static cell AMX_NATIVE_CALL n_get_field(AMX* amx, cell* params) { // TODO: n_get_field return 0; } -// native db_get_field_int(DBResult:result, field); static cell AMX_NATIVE_CALL n_get_field_int(AMX* amx, cell* params) { // TODO: n_get_field_int return 0; } -// native Float:db_get_field_float(DBResult:result, field); static cell AMX_NATIVE_CALL n_get_field_float(AMX* amx, cell* params) { // TODO: n_get_field_float return 0; } -// native db_get_field_assoc(DBResult:dbresult, const field[], result[], maxlength); static cell AMX_NATIVE_CALL n_get_field_assoc(AMX* amx, cell* params) { // TODO: n_get_field_assoc return 0; } -// native db_get_field_assoc_int(DBResult:result, const field[]); static cell AMX_NATIVE_CALL n_get_field_assoc_int(AMX* amx, cell* params) { // TODO: n_get_field_assoc_int return 0; } -// native Float:db_get_field_assoc_float(DBResult:result, const field[]); static cell AMX_NATIVE_CALL n_get_field_assoc_float(AMX* amx, cell* params) { // TODO: n_get_field_assoc_float return 0; } -// native db_debug_openfiles(); static cell AMX_NATIVE_CALL n_debug_openfiles(AMX* amx, cell* params) { // TODO: n_debug_openfiles return 0; } -// native db_debug_openresults(); static cell AMX_NATIVE_CALL n_debug_openresults(AMX* amx, cell* params) { // TODO: n_debug_openresults return 0; } -// native db_get_mem_handle(DB:db); static cell AMX_NATIVE_CALL n_get_mem_handle(AMX* amx, cell* params) { // TODO: n_get_mem_handle return 0; } -// native db_get_result_mem_handle(DBResult:result); static cell AMX_NATIVE_CALL n_get_result_mem_handle(AMX* amx, cell* params) { // TODO: n_get_result_mem_handle return 0; } -/* -native DB:db_open(name[]); -native db_close(DB:db); -native DBResult:db_query(DB:db, query[]); -native db_free_result(DBResult:dbresult); -native db_num_rows(DBResult:dbresult); -native db_next_row(DBResult:dbresult); -native db_num_fields(DBResult:dbresult); -native db_field_name(DBResult:dbresult, field, result[], maxlength); -native db_get_field(DBResult:dbresult, field, result[], maxlength); -native db_get_field_int(DBResult:result, field = 0); -native Float:db_get_field_float(DBResult:result, field = 0); -native db_get_field_assoc(DBResult:dbresult, const field[], result[], maxlength); -native db_get_field_assoc_int(DBResult:result, const field[]); -native Float:db_get_field_assoc_float(DBResult:result, const field[]); -native db_get_mem_handle(DB:db); -native db_get_result_mem_handle(DBResult:result); -native db_debug_openfiles(); -native db_debug_openresults(); -*/ #if defined __cplusplus extern "C" #endif AMX_NATIVE_INFO sampDb_Natives[] = { - { "db_open", n_open }, - { "db_close", n_close }, - { "db_query", n_query }, - { "db_free_result", n_free_result }, - { "db_num_rows", n_num_rows }, - { "db_next_row", n_next_row }, - { "db_num_fields", n_num_fields }, - { "db_field_name", n_field_name }, - { "db_get_field", n_get_field }, - { "db_get_field_int", n_get_field_int }, - { "db_get_field_float", n_get_field_float }, - { "db_get_field_assoc", n_get_field_assoc }, - { "db_get_field_assoc_int", n_get_field_assoc_int }, - { "db_get_field_assoc_float", n_get_field_assoc_float }, - { "db_debug_openfiles", n_debug_openfiles }, - { "db_debug_openresults", n_debug_openresults }, - { "db_get_mem_handle", n_get_mem_handle }, - { "db_get_result_mem_handle", n_get_result_mem_handle }, + { "db_open", n_open }, + { "db_close", n_close }, + { "db_query", n_query }, + { "db_free_result", n_free_result }, + { "db_num_rows", n_num_rows }, + { "db_next_row", n_next_row }, + { "db_num_fields", n_num_fields }, + { "db_field_name", n_field_name }, + { "db_get_field", n_get_field }, + { "db_get_field_int", n_get_field_int }, + { "db_get_field_float", n_get_field_float }, + { "db_get_field_assoc", n_get_field_assoc }, + { "db_get_field_assoc_int", n_get_field_assoc_int }, + { "db_get_field_assoc_float", n_get_field_assoc_float }, + { "db_debug_openfiles", n_debug_openfiles }, + { "db_debug_openresults", n_debug_openresults }, + { "db_get_mem_handle", n_get_mem_handle }, + { "db_get_result_mem_handle", n_get_result_mem_handle }, { NULL, NULL } /* terminator */ }; diff --git a/server/system.h b/server/system.h index f43c41f..b30d3fb 100644 --- a/server/system.h +++ b/server/system.h @@ -7,6 +7,23 @@ typedef struct _VECTOR { float X,Y,Z; } VECTOR, *PVECTOR; +#pragma pack(1) +typedef struct _MATRIX4X4 { + VECTOR right; + DWORD flags; + VECTOR up; + float pad_u; + VECTOR at; + float pad_a; + VECTOR pos; + float pad_p; +} MATRIX4X4, *PMATRIX4X4; + +#pragma pack(1) +typedef struct _QUATERNION { + float W,X,Y,Z; +} QUATERNION, *PQUATERNION; + typedef struct _struc_64 { int iModelID; diff --git a/server/vehicle.cpp b/server/vehicle.cpp new file mode 100644 index 0000000..9ca8ced --- /dev/null +++ b/server/vehicle.cpp @@ -0,0 +1,70 @@ + +#include "main.h" + +CVehicle::CVehicle( int iModel, VECTOR *vecPos, + float fRotation, int iColor1, + int iColor2, int iRespawnDelay) +{ + // Store the spawn info. + m_SpawnInfo.iVehicleType = iModel; + m_SpawnInfo.fRotation = fRotation; + m_SpawnInfo.vecPos.X = vecPos->X; + m_SpawnInfo.vecPos.Y = vecPos->Y; + m_SpawnInfo.vecPos.Z = vecPos->Z; + m_SpawnInfo.iColor1 = iColor1; + m_SpawnInfo.iColor2 = iColor2; + m_SpawnInfo.iRespawnDelay = iRespawnDelay; + m_SpawnInfo.iInterior = 0; + + field_0.X = vecPos->X; + field_0.Y = vecPos->Y; + field_0.Z = vecPos->Z; + + field_100 = 0; + field_105 = pNetGame->GetTime(); + + // Set the initial pos to spawn pos. + memset(&m_matWorld,0,sizeof(MATRIX4X4)); + m_matWorld.pos.X = m_SpawnInfo.vecPos.X; + m_matWorld.pos.Y = m_SpawnInfo.vecPos.Y; + m_matWorld.pos.Z = m_SpawnInfo.vecPos.Z; + + memset(field_4C, 0, sizeof(field_4C)); + memset(field_58, 0, sizeof(field_58)); + memset(&m_CarModInfo, 0,sizeof(CAR_MOD_INFO)); + m_CarModInfo.iColor0 = -1; + m_CarModInfo.iColor1 = -1; + memset(field_CE, 0, sizeof(field_CE)); + + field_7A = 1; // m_bIsActive ? + field_7E = 0; // m_bIsWasted ? + field_6A = -1; // m_byteDriverID ? + m_fHealth = 1000.0f; + + field_AA = 0; + field_F1 = -1; + field_F3 = -1; + field_F4 = -1; + field_F2 = -1; + field_EF = -1; + field_F0 = -1; + field_F5 = -1; + field_F6 = -1; + field_F7 = -1; + field_F8 = -1; + field_F9 = -1; + field_FA = -1; + field_FB = -1; + field_FC = -1; + field_FD = -1; + field_FE = -1; + field_AE = 0; + field_B2 = 0; + field_B3 = 0; + field_FF = 0; + field_66 = 0; + field_B4 = 0; + field_109 = 0; + field_10A = 0; + field_B5 = -1; +} diff --git a/server/vehicle.h b/server/vehicle.h new file mode 100644 index 0000000..f263905 --- /dev/null +++ b/server/vehicle.h @@ -0,0 +1,88 @@ + +#ifndef SAMPSRV_VEHICLE_H +#define SAMPSRV_VEHICLE_H + +#pragma pack(1) +typedef struct _VEHICLE_SPAWN_INFO +{ + int iVehicleType; + VECTOR vecPos; + float fRotation; + int iColor1; + int iColor2; + int iRespawnDelay; + int iInterior; +} VEHICLE_SPAWN_INFO; + +#pragma pack(1) +typedef struct _CAR_MOD_INFO +{ + BYTE byteCarMod[14]; + BYTE bytePaintJob; + int iColor0; + int iColor1; +} CAR_MOD_INFO; + +#pragma pack(1) +class CVehicle // size 267/0x10B +{ +public: + + //char _gap0[267]; + VECTOR field_0; + MATRIX4X4 m_matWorld; + char field_4C[12]; + char field_58[12]; + VEHICLEID m_VehicleID; + short field_66; + + char _gap68[2]; + + short field_6A; + + char _gap6C[14]; + + int field_7A; + int field_7E; + VEHICLE_SPAWN_INFO m_SpawnInfo; + //int field_A2; + float m_fHealth; + int field_AA; + int field_AE; + char field_B2; + char field_B3; + char field_B4; + short field_B5; + _CAR_MOD_INFO m_CarModInfo; + char field_CE[33]; + char field_EF; + char field_F0; + char field_F1; + char field_F2; + char field_F3; + char field_F4; + char field_F5; + char field_F6; + char field_F7; + char field_F8; + char field_F9; + char field_FA; + char field_FB; + char field_FC; + char field_FD; + char field_FE; + char field_FF; + char field_100; + + char _gap101[4]; + + int field_105; + char field_109; + char field_10A; + + CVehicle(int iModel,VECTOR *vecPos,float fRotation,int iColor1,int iColor2, int iRespawnTime); + + void SetID(VEHICLEID VehicleID) { m_VehicleID = VehicleID; }; +}; + +#endif diff --git a/server/vehiclepool.cpp b/server/vehiclepool.cpp index 496c5ea..a83b2c6 100644 --- a/server/vehiclepool.cpp +++ b/server/vehiclepool.cpp @@ -4,9 +4,9 @@ CVehiclePool::CVehiclePool() { for(VEHICLEID VehicleID = 0; VehicleID != MAX_VEHICLES; VehicleID++) { - field_2014[VehicleID] = 0; - field_3F54[VehicleID] = 0; - field_D4[VehicleID] = 0; + m_bVehicleSlotState[VehicleID] = FALSE; + m_pVehicles[VehicleID] = NULL; + m_iVirtualWorld[VehicleID] = 0; } memset(field_0,0,sizeof(field_0)); m_iPoolSize = 0; @@ -19,12 +19,50 @@ CVehiclePool::~CVehiclePool() } } +VEHICLEID CVehiclePool::New(int iVehicleType, + VECTOR * vecPos, float fRotation, + int iColor1, int iColor2, int iRespawnDelay) +{ + VEHICLEID VehicleID; + + if(iVehicleType < 400 || iVehicleType > 611) + return 0xFFFF; + + for(VehicleID=1; VehicleID != MAX_VEHICLES; VehicleID++) + { + if(m_bVehicleSlotState[VehicleID] == FALSE) break; + } + + if(VehicleID == MAX_VEHICLES) return 0xFFFF; + + m_pVehicles[VehicleID] = new CVehicle(iVehicleType,vecPos,fRotation,iColor1,iColor2,iRespawnDelay); + + if(m_pVehicles[VehicleID]) + { + // TODO: CVehiclePool::New + + m_pVehicles[VehicleID]->SetID(VehicleID); + m_bVehicleSlotState[VehicleID] = TRUE; + + return VehicleID; + } + else + { + return 0xFFFF; + } +} + BOOL CVehiclePool::Delete(VEHICLEID VehicleID) { // TODO: CVehiclePool::Delete W .text:00467700 L .text:0814CC10 return FALSE; } +void CVehiclePool::Process(float fElapsedTime) +{ + // TODO: CVehiclePool::Process +} + int CVehiclePool::GetModelCount() { int iCount=0; diff --git a/server/vehiclepool.h b/server/vehiclepool.h index ec0c2de..1207d3a 100644 --- a/server/vehiclepool.h +++ b/server/vehiclepool.h @@ -2,24 +2,40 @@ #ifndef SAMPSRV_VEHICLEPOOL_H #define SAMPSRV_VEHICLEPOOL_H -class CVehiclePool // size: WL 24216 +class CVehiclePool { private: char field_0[212]; - int field_D4[2000]; - int field_2014[2000]; - int field_3F54[2000]; + int m_iVirtualWorld[MAX_VEHICLES]; + BOOL m_bVehicleSlotState[MAX_VEHICLES]; + CVehicle *m_pVehicles[MAX_VEHICLES]; int m_iPoolSize; public: CVehiclePool(); ~CVehiclePool(); + VEHICLEID New(int iVehicleType, VECTOR * vecPos, float fRotation, int iColor1, int iColor2, int iRespawnDelay); + BOOL Delete(VEHICLEID VehicleID); + // Find out if the slot is inuse. + BOOL GetSlotState(VEHICLEID VehicleID) + { + if(VehicleID >= MAX_VEHICLES) { return FALSE; } + return m_bVehicleSlotState[VehicleID]; + }; + + void Process(float fElapsedTime); + int GetModelCount(); int GetPoolSize() { return m_iPoolSize; }; + + int GetVehicleVirtualWorld(VEHICLEID VehicleID) { + if (VehicleID >= MAX_VEHICLES) { return 0; } + return m_iVirtualWorld[VehicleID]; + }; }; #endif