diff --git a/MTA10/core/CChat.cpp b/MTA10/core/CChat.cpp index b21ac03518..e662766e41 100644 --- a/MTA10/core/CChat.cpp +++ b/MTA10/core/CChat.cpp @@ -46,6 +46,10 @@ CChat::CChat ( CGUI* pManager, CVector2D & vecPosition ) m_pDXFont = g_pCore->GetGraphics ()->GetFont (); m_fNativeWidth = CHAT_WIDTH; m_bCanChangeWidth = true; + m_iScrollingBack = 0; + m_fCssStyleOverrideAlpha = 0.0f; + m_fBackgroundAlpha = 0.0f; + m_fInputBackgroundAlpha = 0.f; // Background area m_pBackground = m_pManager->CreateStaticImage (); @@ -128,21 +132,15 @@ void CChat::Draw ( void ) float fLineDifference = CChat::GetFontHeight ( m_vecScale.fY ); CVector2D vecPosition ( m_vecBackgroundPosition.fX + ( 5.0f * m_vecScale.fX ), m_vecBackgroundPosition.fY + m_vecBackgroundSize.fY - ( fLineDifference * 1.25f ) ); - unsigned char ucAlpha = 0; unsigned long ulTime = GetTickCount (); - unsigned long ulLineAge = 0; - bool bShadow = ( m_Color.A == 0 || ( m_bCssStyleText && !m_bInputVisible ) ); - bool bInputShadow = ( m_InputColor.A == 0 ); + float fRcpChatLineFadeOut = 1.0f / m_ulChatLineFadeOut; + bool bShadow = ( m_Color.A * m_fBackgroundAlpha == 0.f ); + bool bInputShadow = ( m_InputColor.A * m_fInputBackgroundAlpha == 0.f ); - bool bDrawBackground = false; - if ( m_bCssStyleBackground ) - bDrawBackground = ( m_bVisible && m_bInputVisible && m_Color.A != 0 ); - else - bDrawBackground = ( m_bVisible && m_Color.A != 0 ); - - if ( bDrawBackground ) + if ( m_Color.A * m_fBackgroundAlpha > 0.f ) { // Hack to draw the background behind the text. + m_pBackground->SetAlpha ( m_fBackgroundAlpha ); m_pBackground->SetVisible ( true ); m_pBackground->Render (); m_pBackground->SetVisible ( false ); @@ -174,27 +172,16 @@ void CChat::Draw ( void ) // Loop over the circular buffer while ( m_Lines [ uiLine ].IsActive () && uiLinesDrawn < m_uiNumLines + (fabsf( m_fSmoothScroll ) > 0.1f ? 1 : 0) ) { - ucAlpha = 255; - if ( m_bCssStyleText && !m_bInputVisible ) - { - ulLineAge = ulTime - m_Lines [ uiLine ].GetCreationTime (); - if ( ulLineAge > m_ulChatLineLife ) - { - if ( ulLineAge > ( m_ulChatLineLife + m_ulChatLineFadeOut ) ) - { - ucAlpha = 0; - } - else - { - float fOver = float ( ( m_ulChatLineLife + m_ulChatLineFadeOut ) - ulLineAge ); - fOver /= ( float ) m_ulChatLineFadeOut; - ucAlpha = unsigned char ( fOver * 255.0f ); - } - } - } + // Calculate line alpha + long ulLineAge = ulTime - m_Lines [ uiLine ].GetCreationTime (); + float fLineAlpha = (long)( m_ulChatLineLife + m_ulChatLineFadeOut - ulLineAge ) * fRcpChatLineFadeOut; - if ( ucAlpha > 0 ) - m_Lines [ uiLine ].Draw ( vecPosition, ucAlpha, bShadow, RenderBounds ); + // Clamp line alpha range and combine with Css override + fLineAlpha = Clamp ( 0.0f, fLineAlpha, 1.0f ); + fLineAlpha += ( 1.0f - fLineAlpha ) * m_fCssStyleOverrideAlpha; + + if ( fLineAlpha > 0.f ) + m_Lines [ uiLine ].Draw ( vecPosition, static_cast < unsigned char >( fLineAlpha * 255.0f ), bShadow, RenderBounds ); vecPosition.fY -= fLineDifference; @@ -204,19 +191,20 @@ void CChat::Draw ( void ) break; } - if ( m_bInputVisible ) + if ( m_InputColor.A * m_fInputBackgroundAlpha > 0.f ) { - if ( m_InputColor.A != 0 ) + if ( m_pInput ) { - if ( m_pInput ) - { - // Hack to draw the input background behind the text. - m_pInput->SetVisible ( true ); - m_pInput->Render (); - m_pInput->SetVisible ( false ); - } + // Hack to draw the input background behind the text. + m_pInput->SetAlpha ( m_fInputBackgroundAlpha ); + m_pInput->SetVisible ( true ); + m_pInput->Render (); + m_pInput->SetVisible ( false ); } + } + if ( m_bInputVisible ) + { CVector2D vecPosition ( m_vecInputPosition.fX + ( 5.0f * m_vecScale.fX ), m_vecInputPosition.fY + ( fLineDifference * 0.125f ) ); m_InputLine.Draw ( vecPosition, 255, bInputShadow ); } @@ -265,6 +253,33 @@ void CChat::UpdateSmoothScroll ( float* pfPixelScroll, int *piLineScroll ) // Set return values *pfPixelScroll = fPixelScroll; *piLineScroll = iLineScroll; + + // Update 'scrolling back' flag + if ( m_uiScrollOffset != 0 ) + m_iScrollingBack = 10; + else + m_iScrollingBack = Max ( 0, m_iScrollingBack - 1 ); + + // + // Also update CssStyle override alpha + // + float fTarget = ( !m_bCssStyleText || m_bInputVisible || m_iScrollingBack ) ? 1.0f : 0.0f; + float fMaxAmount = fDeltaSeconds * 2.0f; // 0.5 seconds fade time + m_fCssStyleOverrideAlpha += Clamp ( -fMaxAmount, fTarget - m_fCssStyleOverrideAlpha, fMaxAmount ); + + // + // Also update background alpha + // + fTarget = ( !m_bCssStyleBackground || m_bInputVisible || m_iScrollingBack ) ? 1.0f : 0.0f; + fMaxAmount = fDeltaSeconds * 5.0f; // 0.2 seconds fade time + m_fBackgroundAlpha += Clamp ( -fMaxAmount, fTarget - m_fBackgroundAlpha, fMaxAmount ); + + // + // Also update input background alpha + // + fTarget = ( m_bInputVisible ) ? 1.0f : 0.0f; + fMaxAmount = fDeltaSeconds * 5.0f; // 0.2 seconds fade time + m_fInputBackgroundAlpha += Clamp ( -fMaxAmount, fTarget - m_fInputBackgroundAlpha, fMaxAmount ); } diff --git a/MTA10/core/CChat.h b/MTA10/core/CChat.h index 6aae236046..b24739b989 100644 --- a/MTA10/core/CChat.h +++ b/MTA10/core/CChat.h @@ -203,6 +203,10 @@ class CChat bool m_bVisible; bool m_bInputVisible; + int m_iScrollingBack; // Non zero if currently scrolling back + float m_fCssStyleOverrideAlpha; // For fading out 'CssStyle' effect. (When entering text or scrolling back) + float m_fBackgroundAlpha; + float m_fInputBackgroundAlpha; unsigned int m_uiNumLines; CColor m_Color; diff --git a/MTA10/core/CCommunity.cpp b/MTA10/core/CCommunity.cpp index 8d62e3b54f..e2334a2a85 100644 --- a/MTA10/core/CCommunity.cpp +++ b/MTA10/core/CCommunity.cpp @@ -125,6 +125,7 @@ void CCommunity::DoPulse ( void ) } // Check for timeout else if ( ( CClientTime::GetTime () - m_ulStartTime ) > VERIFICATION_DELAY ) { + g_pCore->ShowMessageBox ( "Error", "Services currently unavaliable", MB_BUTTON_OK | MB_ICON_ERROR ); Logout (); } } diff --git a/MTA10/core/CCommunity.h b/MTA10/core/CCommunity.h index 9535fc7458..94c045670f 100644 --- a/MTA10/core/CCommunity.h +++ b/MTA10/core/CCommunity.h @@ -18,7 +18,7 @@ typedef void (*VERIFICATIONCALLBACK) ( bool, char*, void* obj ); -#define VERIFICATION_DELAY 150000 +#define VERIFICATION_DELAY 3000 #define VERIFICATION_URL "http://dp3.community.mtasa.com/core/1.0/client.php" #define VERIFICATION_DATA_BUFFER_SIZE 1024 diff --git a/MTA10/core/CCommunityRegistration.h b/MTA10/core/CCommunityRegistration.h index c7b4a61cc1..ea8760bfe7 100644 --- a/MTA10/core/CCommunityRegistration.h +++ b/MTA10/core/CCommunityRegistration.h @@ -15,7 +15,7 @@ class CCommunityRegistration; #ifndef __CCOMMUNITYREGISTRATION_H #define __CCOMMUNITYREGISTRATION_H -#define REGISTRATION_DELAY 150000 +#define REGISTRATION_DELAY 3000 #define REGISTRATION_URL "http://dp3.community.mtasa.com/core/1.0/register.php" #define REGISTRATION_DATA_BUFFER_SIZE 100000 #define REGISTRATION_TEMP_FILE "MTA\\temp.png" diff --git a/MTA10/core/CCore.cpp b/MTA10/core/CCore.cpp index 5fd2cefe14..4a15e2e6d7 100644 --- a/MTA10/core/CCore.cpp +++ b/MTA10/core/CCore.cpp @@ -777,6 +777,13 @@ void CCore::SetCenterCursor ( bool bEnabled ) m_pSetCursorPosHook->DisableSetCursorPos (); } +bool CCore::CanDrawGUI ( void ) +{ + // Are we taking a photo with the camera? + if ( m_pGame && m_pGame->IsTakingPhoto () ) return false; + return true; +} + void CCore::CreateGame ( ) { // Create function pointer type and variable. diff --git a/MTA10/core/CCore.h b/MTA10/core/CCore.h index 8ab11dc723..068502569e 100644 --- a/MTA10/core/CCore.h +++ b/MTA10/core/CCore.h @@ -126,6 +126,7 @@ class CCore : public CCoreInterface, public CSingleton < CCore > bool IsCursorControlsToggled ( void ) { return m_bCursorToggleControls; } void HideMainMenu ( void ); void SetCenterCursor ( bool bEnabled ); + bool CanDrawGUI ( void ); // Configuration void ApplyConsoleSettings ( void ); diff --git a/MTA10/core/CCredits.cpp b/MTA10/core/CCredits.cpp index dbf99cd52a..7c64c2ad5e 100644 --- a/MTA10/core/CCredits.cpp +++ b/MTA10/core/CCredits.cpp @@ -14,126 +14,69 @@ extern CCore* g_pCore; -const char g_szCredits [] = "== The Multi Theft Auto Development Team ==\n" \ - "Cecill \"IJs\" Etheredge\n" \ - "Chris \"Cray\" McArthur\n" \ - "Christian \"ChrML\" Lundheim\n" \ - "Derek \"Slush\" Abdine\n" \ - "Ed \"eAi\" Lyons\n" \ - "Adge \"Jax\" Cutler\n" \ - "Kent \"Kent747\" Simon\n" \ - "Kevin \"Kevuwk\" Whiteside\n" \ - "Oliver \"Oli\" Brown\n" \ - "Stanislav \"lil_Toady\" Bobrov\n" - "Alberto \"ryden\" Alonso\n" \ - "\n" \ - - "== Special Thanks ==\n" \ - "Anne-Jan \"AJH\" Hak\n" \ - "Alexandru \"Rzialix\" Panait\n" \ - "Bill \"Sintax\" Blaiklock\n" \ - "Bloodymess\n" \ - "Chris \"RISO\" Hancock\n" \ - "Hans \"Blokker\" Roes\n" \ - "Headfonez\n" \ - "kktos\n" \ - "MrBump\n" \ - "ohsix\n" \ - "Pieter \"trx\" Plantenga\n" \ - "spec\n" \ - "xerox\n" \ - "Wojjie\n" \ - "\n" \ - - "== The Multi Theft Auto Website Development Team ==\n" \ - "AlienX\n" \ - "Arc_\n" \ - "driver2\n" \ - "lil_Toady\n" \ - "\n" \ - - "== The Multi Theft Auto Quality Assurance Team Managers ==\n" \ - "jhxp\n" \ - "Ransom\n" \ - "\n" \ - - "== The Multi Theft Auto Quality Assurance Team ==\n" \ - "AlienX\n" \ - "arc_\n" \ - "BB101\n" \ - "Boss\n" \ - "Brophy\n" \ - "deez\n" \ - "Dragon (Black Dragon)\n" \ - "driver2\n" \ - "erorr404\n" \ - "Fedor\n" \ - "Iggy\n" \ - "jbeta\n" \ - "Johnline\n" \ - "Joriz\n" \ - "Kcuf\n" \ - "lil_Toady\n" \ - "Lucif3r\n" \ - "MACK\n" \ - "MeanpantheR\n" \ - "nick\n" \ - "norby89\n" \ - "Outback\n" \ - "Paradox\n" \ - "RAF\n" \ - "Ratt\n" \ - "ryden\n" \ - "Scooby\n" \ - "SinnerG (TvKe)\n" \ - "Sintax\n" \ - "Slick\n" \ - "Slothman\n" \ - "Solide\n" \ - "Talidan\n" \ - "Tweak\n" \ - "Vandalite\n" \ - "x16\n" \ - "Xanarki\n" \ - "xerox\n" \ - "\n" \ - - "== Past contributors ==\n" \ - "Aeron\n" \ - "Au{R}oN\n" \ - "Bishop\n" \ - "Boro\n" \ - "Boss (Thesord)\n" \ - "Des (Marcel)\n" \ - "Dome\n" \ - "DominionSpy\n" \ - "DracoBlue\n" \ - "Dross\n" \ - "Fusion\n" \ - "Gamefreek\n" \ - "Harry\n" \ - "HAZJ\n" \ - "Hedning\n" \ - "JackC\n" \ - "Jigga\n" \ - "Kalle\n" \ - "KriS\n" \ - "MAD_BOY\n" \ - "Mif\n" \ - "Monk\n" \ - "ParoXum\n" \ - "PhatLooser\n" \ - "Prontera\n" \ - "rebel (l2ebel)\n" \ - "Samppa\n" \ - "Samurai_Ohk\n" \ - "SGB\n" \ - "TheBoas\n" \ - "Twig\n" \ - "VRocker\n" \ - "Welder\n" \ - "Zerbian\n" \ - "Zircon (Blue Zircon)\n"; +const char* g_szCredits = "== Multi Theft Auto: San Andreas v1.0 ==\n" + "\n" + + "Programming\n" + "\n" + + "Alberto \"ryden\" Alonso\n" + "Marcus \"mabako\" Bauer\n" + "Hendrik \"arc_\" van den Berge\n" + "Stanislav \"lil_Toady\" Bobrov\n" + "Dan \"Talidan\" Chowdhury\n" + "Chris \"ccw\" Cockwanger\n" + "Adge \"Jax\" Cutler\n" + "Cecill \"ijs\" Etheredge\n" + "Ed \"eAi\" Lyons\n" + "Christian \"ChrML\" Myhre Lundheim\n" + "Arushan \"aru\" Raj\n" + "Frank \"Aim\" Spijkerman\n" + "Kevin \"Kevuwk\" Whiteside\n" + "Richard \"Cazomino05\" Whitlock\n" + "\n" + + "Game Design / Scripting\n" + "\n" + + "John \"Johnline\" Borsberry\n" + "Paul \"Brophy\" Brophy\n" + "Maciej \"MACK\" Cieslak\n" + "Jacek \"jhxp\" Halas vel Lagoda\n" + "Brad \"Slothman\" Hammond\n" + "Norbert \"norby89\" Juhos\n" + "Kris \"KWKSND\" Kulchisky\n" + "Dustin \"Ransom\" Morren\n" + "\n" + + "erorr404\n" + "\n" + + "Patch contributors\n" + "\n" + + "Florian \"Flobu\" Busse\n" + "Philip \"Fenix\" Farquharson\n" + "Robin \"robhol\" Holm\n" + "Raphael \"Mr.Hankey\" Leiteritz\n" + "Adam \"50p\" Telega\n" + "\n" + + "Gamesnert\n" + "lucasc190\n" + "\n" + + "Special Thanks\n" + "\n" + + "Derek \"slush\" Abdine\n" + "Javier \"jbeta\" Beta\n" + "Oliver \"Oli\" Brown\n" + "Wojciech \"Wojjie\" Hlibowicki\n" + "Chris \"Cray\" McArthur\n" + "Hans \"Blokker\" Roes\n" + "Kent \"Kent747\" Simon\n" + "\n"; namespace CCreditsGUI { @@ -148,7 +91,7 @@ CCredits::CCredits ( void ) // Create our window CVector2D RelativeWindow = CVector2D ( fWindowX / pManager->GetResolution ().fX, fWindowY / pManager->GetResolution ().fY ); - m_pWindow = reinterpret_cast < CGUIWindow* > ( pManager->CreateWnd ( NULL, SString("MTA:SA %s %s", MTA_DM_VERSIONSTRING, MTA_DM_BUILDTYPE).c_str() ) ); + m_pWindow = reinterpret_cast < CGUIWindow* > ( pManager->CreateWnd ( NULL, SString("Multi Theft Auto: San Andreas %s %s", MTA_DM_VERSIONSTRING, MTA_DM_BUILDTYPE).c_str() ) ); m_pWindow->SetCloseButtonEnabled ( false ); m_pWindow->SetMovable ( false ); m_pWindow->SetPosition ( CVector2D ( 0.5f - RelativeWindow.fX*0.5f, 0.5f - RelativeWindow.fY*0.5f ), true ); diff --git a/MTA10/core/CDebugView.cpp b/MTA10/core/CDebugView.cpp index 459b4682aa..1c74d3c7ca 100644 --- a/MTA10/core/CDebugView.cpp +++ b/MTA10/core/CDebugView.cpp @@ -46,6 +46,10 @@ CDebugView::CDebugView ( CGUI * pManager, CVector2D & vecPosition ) : CChat () m_pDXFont = g_pCore->GetGraphics ()->GetFont (); m_fNativeWidth = DEBUGVIEW_WIDTH; m_bCanChangeWidth = false; + m_iScrollingBack = 0; + m_fCssStyleOverrideAlpha = 0.0f; + m_fBackgroundAlpha = 0.0f; + m_fInputBackgroundAlpha = 0.f; m_Color = CColor ( 0, 0, 0, 100 ); m_TextColor = DEBUGVIEW_TEXT_COLOR; unsigned long ulBackgroundColor = COLOR_ARGB ( m_Color.A, m_Color.R, m_Color.G, m_Color.B ); diff --git a/MTA10/core/CDirect3DEvents9.cpp b/MTA10/core/CDirect3DEvents9.cpp index 87361f54cd..39c6f9655f 100644 --- a/MTA10/core/CDirect3DEvents9.cpp +++ b/MTA10/core/CDirect3DEvents9.cpp @@ -98,27 +98,31 @@ void CDirect3DEvents9::OnPresent ( IDirect3DDevice9 *pDevice ) // Notify core CCore::GetSingleton ().DoPostFramePulse (); - // Create a state block. - IDirect3DStateBlock9 * pDeviceState = NULL; - pDevice->CreateStateBlock ( D3DSBT_ALL, &pDeviceState ); + // Are we allowed to draw the gui? + if ( CCore::GetSingleton ().CanDrawGUI () ) + { + // Create a state block. + IDirect3DStateBlock9 * pDeviceState = NULL; + pDevice->CreateStateBlock ( D3DSBT_ALL, &pDeviceState ); - // Draw pre-GUI primitives - CGraphics::GetSingleton ().DrawPreGUIQueue (); + // Draw pre-GUI primitives + CGraphics::GetSingleton ().DrawPreGUIQueue (); - // Draw the GUI - CLocalGUI::GetSingleton().Draw (); + // Draw the GUI + CLocalGUI::GetSingleton().Draw (); - // Draw post-GUI primitives - CGraphics::GetSingleton ().DrawPostGUIQueue (); + // Draw post-GUI primitives + CGraphics::GetSingleton ().DrawPostGUIQueue (); - // Redraw the mouse cursor so it will always be over other elements - CLocalGUI::GetSingleton().DrawMouseCursor(); + // Redraw the mouse cursor so it will always be over other elements + CLocalGUI::GetSingleton().DrawMouseCursor(); - // Restore the render states - if ( pDeviceState ) - { - pDeviceState->Apply ( ); - pDeviceState->Release ( ); + // Restore the render states + if ( pDeviceState ) + { + pDeviceState->Apply ( ); + pDeviceState->Release ( ); + } } // End the scene that we started. diff --git a/MTA10/core/CGUI.cpp b/MTA10/core/CGUI.cpp index fde452528c..80cf436b33 100644 --- a/MTA10/core/CGUI.cpp +++ b/MTA10/core/CGUI.cpp @@ -644,18 +644,22 @@ bool CLocalGUI::ProcessMessage ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lPa { case WM_KEYDOWN: { - extern CChat* g_pChat; - if ( wParam == VK_PRIOR ) { - if ( g_pChat ) - g_pChat->ScrollUp (); + if ( m_pChat ) + m_pChat->ScrollUp (); + + if ( m_pDebugView ) + m_pDebugView->ScrollUp (); } else if ( wParam == VK_NEXT ) { - if ( g_pChat ) - g_pChat->ScrollDown (); + if ( m_pChat ) + m_pChat->ScrollDown (); + + if ( m_pDebugView ) + m_pDebugView->ScrollDown (); } } } diff --git a/MTA10/core/CKeyBinds.cpp b/MTA10/core/CKeyBinds.cpp index d724d49244..e73de9b6db 100644 --- a/MTA10/core/CKeyBinds.cpp +++ b/MTA10/core/CKeyBinds.cpp @@ -230,6 +230,8 @@ CKeyBinds::CKeyBinds ( CCore* pCore ) m_bInVehicle = false; m_pChatBoxBind = NULL; m_bProcessingKeyStroke = false; + m_KeyStrokeHandler = NULL; + m_CharacterKeyHandler = NULL; } @@ -244,10 +246,16 @@ bool CKeyBinds::ProcessMessage ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lPa { bool bState; const SBindableKey * pKey = GetBindableFromMessage ( uMsg, wParam, lParam, bState ); - if ( pKey ) - { - return ProcessKeyStroke ( pKey, bState ); - } + if ( pKey ) return ProcessKeyStroke ( pKey, bState ); + + if ( uMsg == WM_CHAR ) return ProcessCharacter ( wParam ); + return false; +} + + +bool CKeyBinds::ProcessCharacter ( WPARAM wChar ) +{ + if ( m_CharacterKeyHandler && m_CharacterKeyHandler ( wChar ) ) return true; return false; } @@ -291,12 +299,15 @@ bool CKeyBinds::ProcessKeyStroke ( const SBindableKey * pKey, bool bState ) if ( pKey->iGTARelative == GTA_KEY_MSCROLLUP || pKey->iGTARelative == GTA_KEY_MSCROLLDOWN ) m_bMouseWheel = true; + // Call the key-stroke handler if we have one + if ( m_KeyStrokeHandler ) m_KeyStrokeHandler ( pKey, bState ); + // Search through binds bool bFound = false; CKeyBind* pBind = NULL; list < CKeyBind* > cloneList = *m_pList; list < CKeyBind* > ::const_iterator iter = cloneList.begin (); - for ( ; iter != cloneList.end (); iter++ ) + for ( ; iter != cloneList.end (); ++iter ) { pBind = *iter; if ( pBind->IsBeingDeleted () || !pBind->boundKey ) continue; @@ -989,8 +1000,7 @@ void CKeyBinds::CallGTAControlBind ( CGTAControlBind* pBind, bool bState ) return; // Don't allow custom track skips. Crashes for some reason. - if ( pBind->control->action == RADIO_USER_TRACK_SKIP ) - return; + if ( pBind->control->action == RADIO_USER_TRACK_SKIP ) return; // Set this binds state pBind->bState = bState; diff --git a/MTA10/core/CKeyBinds.h b/MTA10/core/CKeyBinds.h index 648be30350..ae71e1479e 100644 --- a/MTA10/core/CKeyBinds.h +++ b/MTA10/core/CKeyBinds.h @@ -30,6 +30,7 @@ class CKeyBinds: public CKeyBindsInterface bool ProcessMessage ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); protected: + bool ProcessCharacter ( WPARAM wChar ); bool ProcessKeyStroke ( const SBindableKey * pKey, bool bState ); public: @@ -108,6 +109,8 @@ class CKeyBinds: public CKeyBindsInterface bool IsKey ( const char* szKey ); char* GetKeyFromGTARelative ( int iGTAKey ); const SBindableKey* GetBindableFromMessage ( UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bState ); + inline void SetKeyStrokeHandler ( KeyStrokeHandler Handler ) { m_KeyStrokeHandler = Handler; } + inline void SetCharacterKeyHandler ( CharacterKeyHandler Handler ) { m_CharacterKeyHandler = Handler; } // Control/action funcs char* GetControlFromAction ( eControllerAction action ); @@ -152,6 +155,8 @@ class CKeyBinds: public CKeyBindsInterface bool m_bInVehicle; CCommandBind* m_pChatBoxBind; bool m_bProcessingKeyStroke; + KeyStrokeHandler m_KeyStrokeHandler; + CharacterKeyHandler m_CharacterKeyHandler; }; #endif diff --git a/MTA10/core/CMainMenu.cpp b/MTA10/core/CMainMenu.cpp index 1e7b0543e4..7f16654cb9 100644 --- a/MTA10/core/CMainMenu.cpp +++ b/MTA10/core/CMainMenu.cpp @@ -809,6 +809,9 @@ void CMainMenu::SetItemPosition ( unsigned int uiIndex, CVector2D vecPosition, b void CMainMenu::LoadMenuOptions ( void ) { + // Force all 3D scene options off + CVARS_SET ( "menu_options", 0 ); + int iMenuOptions; CVARS_GET ( "menu_options", iMenuOptions ); diff --git a/MTA10/core/CSettings.cpp b/MTA10/core/CSettings.cpp index 53459d2d66..147c026149 100644 --- a/MTA10/core/CSettings.cpp +++ b/MTA10/core/CSettings.cpp @@ -434,6 +434,13 @@ CSettings::CSettings ( void ) m_pCheckBoxMenuPostEffects->SetSize ( CVector2D ( 174.0f, 16.0f ) ); m_pCheckBoxMenuPostEffects->SetUserData ( (void*) eCheckBox::CHECKBOX_MENU_POSTEFFECTS ); + // Hide options relating to the 3D scene + m_pVideoRenderingLabel->SetVisible ( false ); + m_pCheckBoxMenuDynamic->SetVisible ( false ); + m_pCheckBoxMenuVideo->SetVisible ( false ); + m_pCheckBoxMenuPostEffects->SetVisible ( false ); + vecTemp.fY -= 72; + m_pMapRenderingLabel = reinterpret_cast < CGUILabel* > ( pManager->CreateLabel ( pTabVideo, "Map rendering options" ) ); m_pMapRenderingLabel->SetPosition ( CVector2D ( vecTemp.fX, vecTemp.fY + 40.0f ) ); m_pMapRenderingLabel->GetPosition ( vecTemp, false ); diff --git a/MTA10/game_sa/CAERadioTrackManagerSA.cpp b/MTA10/game_sa/CAERadioTrackManagerSA.cpp index a93db110e1..7203727229 100644 --- a/MTA10/game_sa/CAERadioTrackManagerSA.cpp +++ b/MTA10/game_sa/CAERadioTrackManagerSA.cpp @@ -14,13 +14,12 @@ BYTE CAERadioTrackManagerSA::GetCurrentRadioStationID() { - DEBUG_TRACE("BYTE CAERadioTrackManagerSA::GetCurrentRadioStationID()"); DWORD dwThis = ( DWORD ) m_pInterface; DWORD dwFunc = FUNC_CAERadioTrackManager_GetCurrentRadioStationID; BYTE bReturn = 0; _asm { - mov ecx, CLASS_CAERadioTrackManager + mov ecx, dwThis call dwFunc mov bReturn, al } @@ -30,7 +29,6 @@ BYTE CAERadioTrackManagerSA::GetCurrentRadioStationID() BYTE CAERadioTrackManagerSA::IsVehicleRadioActive() { - DEBUG_TRACE("BYTE CAERadioTrackManagerSA::IsVehicleRadioActive()"); DWORD dwThis = ( DWORD ) m_pInterface; DWORD dwFunc = FUNC_CAERadioTrackManager_IsVehicleRadioActive; BYTE bReturn = 0; @@ -46,7 +44,6 @@ BYTE CAERadioTrackManagerSA::IsVehicleRadioActive() char * CAERadioTrackManagerSA::GetRadioStationName(BYTE bStationID) { - DEBUG_TRACE("char * CAERadioTrackManagerSA::GetRadioStationName(BYTE bStationID)"); DWORD dwThis = ( DWORD ) m_pInterface; DWORD dwFunc = FUNC_CAERadioTrackManager_GetRadioStationName; char * cReturn = 0; @@ -64,7 +61,6 @@ char * CAERadioTrackManagerSA::GetRadioStationName(BYTE bStationID) BOOL CAERadioTrackManagerSA::IsRadioOn() { - DEBUG_TRACE("BOOL CAERadioTrackManagerSA::IsRadioOn()"); DWORD dwThis = ( DWORD ) m_pInterface; DWORD dwFunc = FUNC_CAERadioTrackManager_IsRadioOn; BYTE bReturn = 0; @@ -78,9 +74,8 @@ BOOL CAERadioTrackManagerSA::IsRadioOn() return bReturn; } -VOID CAERadioTrackManagerSA::SetBassSetting(DWORD dwBass) +void CAERadioTrackManagerSA::SetBassSetting(DWORD dwBass) { - DEBUG_TRACE("VOID CAERadioTrackManagerSA::SetBassSetting(DWORD dwBass)"); DWORD dwThis = ( DWORD ) m_pInterface; DWORD dwFunc = FUNC_CAERadioTrackManager_SetBassSetting; _asm @@ -92,9 +87,8 @@ VOID CAERadioTrackManagerSA::SetBassSetting(DWORD dwBass) } } -VOID CAERadioTrackManagerSA::Reset() +void CAERadioTrackManagerSA::Reset() { - DEBUG_TRACE("VOID CAERadioTrackManagerSA::Reset()"); DWORD dwThis = ( DWORD ) m_pInterface; DWORD dwFunc = FUNC_CAERadioTrackManager_Reset; _asm @@ -104,16 +98,15 @@ VOID CAERadioTrackManagerSA::Reset() } } -VOID CAERadioTrackManagerSA::StartRadio(BYTE bStationID, BYTE bUnknown) +void CAERadioTrackManagerSA::StartRadio(BYTE bStationID, BYTE bUnknown) { - DEBUG_TRACE("VOID CAERadioTrackManagerSA::StartRadio(BYTE bStationID, BYTE bUnknown)"); DWORD dwThis = ( DWORD ) m_pInterface; DWORD dwFunc = FUNC_CAERadioTrackManager_StartRadio; DWORD dwStationID = bStationID; DWORD dwUnknown = bUnknown; _asm { - mov ecx, CLASS_CAERadioTrackManager + mov ecx, dwThis push 0 push 0 push dwUnknown diff --git a/MTA10/game_sa/CAERadioTrackManagerSA.h b/MTA10/game_sa/CAERadioTrackManagerSA.h index 771f832e2f..d3e889c34d 100644 --- a/MTA10/game_sa/CAERadioTrackManagerSA.h +++ b/MTA10/game_sa/CAERadioTrackManagerSA.h @@ -34,15 +34,15 @@ class CAERadioTrackManagerSAInterface class CAERadioTrackManagerSA : public CAERadioTrackManager { public: - CAERadioTrackManagerSA ( CAERadioTrackManagerSAInterface * pInterface ) { m_pInterface = pInterface; } - - BYTE GetCurrentRadioStationID ( void ); - BYTE IsVehicleRadioActive ( void ); - char * GetRadioStationName ( BYTE bStationID ); - BOOL IsRadioOn ( void ); - VOID SetBassSetting ( DWORD dwBass ); - VOID Reset ( void ); - VOID StartRadio ( BYTE bStationID, BYTE bUnknown ); + CAERadioTrackManagerSA ( CAERadioTrackManagerSAInterface * pInterface ) { m_pInterface = pInterface; } + + BYTE GetCurrentRadioStationID ( void ); + BYTE IsVehicleRadioActive ( void ); + char * GetRadioStationName ( BYTE bStationID ); + BOOL IsRadioOn ( void ); + void SetBassSetting ( DWORD dwBass ); + void Reset ( void ); + void StartRadio ( BYTE bStationID, BYTE bUnknown ); private: CAERadioTrackManagerSAInterface * m_pInterface; diff --git a/MTA10/game_sa/CCameraSA.cpp b/MTA10/game_sa/CCameraSA.cpp index 7bde2e39bb..c6aba5cbb3 100644 --- a/MTA10/game_sa/CCameraSA.cpp +++ b/MTA10/game_sa/CCameraSA.cpp @@ -252,6 +252,21 @@ VOID CCameraSA::Find3rdPersonCamTargetVector ( FLOAT fDistance, CVector * vecGun } } +float CCameraSA::Find3rdPersonQuickAimPitch ( void ) +{ + DEBUG_TRACE("float CCameraSA::Find3rdPersonQuickAimPitch ( void )"); + float fReturn; + DWORD dwFunc = FUNC_Find3rdPersonQuickAimPitch; + CCameraSAInterface * cameraInterface = this->GetInterface(); + _asm + { + mov ecx, cameraInterface + call dwFunc + fstp fReturn + } + return fReturn; +} + BYTE CCameraSA::GetActiveCam() { DEBUG_TRACE("BYTE CCameraSA::GetActiveCam()"); diff --git a/MTA10/game_sa/CCameraSA.h b/MTA10/game_sa/CCameraSA.h index aa8954b2be..1d3074381f 100644 --- a/MTA10/game_sa/CCameraSA.h +++ b/MTA10/game_sa/CCameraSA.h @@ -32,6 +32,7 @@ #define FUNC_ConeCastCollisionResolve 0x51A5D0 #define FUNC_Find3rdPersonCamTargetVector 0x514970 //##SA## +#define FUNC_Find3rdPersonQuickAimPitch 0x50AD40 #define FUNC_TryToStartNewCamMode 0x467AAD #define FUNC_VectorTrackLinear 0x50D1D0 #define FUNC_GetFadingDirection 0x50ADF0 @@ -406,7 +407,8 @@ class CCameraSA : public CCamera VOID SetMatrix ( CMatrix * matrix ); VOID SetCamPositionForFixedMode ( CVector * vecPosition, CVector * vecUpOffset ); VOID Find3rdPersonCamTargetVector ( FLOAT fDistance, CVector * vecGunMuzzle, CVector * vecSource, CVector * vecTarget ); - BYTE GetActiveCam(); + float Find3rdPersonQuickAimPitch ( void ); + BYTE GetActiveCam(); CCam * GetCam(BYTE bCameraID); virtual CCam * GetCam ( CCamSAInterface* camInterface ); diff --git a/MTA10/game_sa/CEntitySA.h b/MTA10/game_sa/CEntitySA.h index 489727444b..9f98151eb8 100644 --- a/MTA10/game_sa/CEntitySA.h +++ b/MTA10/game_sa/CEntitySA.h @@ -80,14 +80,14 @@ class CReferences CEntity * pEntity; }; -class CSimpleTransformSAInterface +class CSimpleTransformSAInterface // 16 bytes { public: CVector m_translate; FLOAT m_heading; }; -class CPlaceableSAInterface +class CPlaceableSAInterface // 20 bytes { public: CSimpleTransformSAInterface m_transform; diff --git a/MTA10/game_sa/CEventDamageSA.cpp b/MTA10/game_sa/CEventDamageSA.cpp index 7f77e9aadb..ae73348911 100644 --- a/MTA10/game_sa/CEventDamageSA.cpp +++ b/MTA10/game_sa/CEventDamageSA.cpp @@ -77,9 +77,6 @@ CEntity * CEventDamageSA::GetInflictingEntity ( void ) case ENTITY_TYPE_VEHICLE: pReturn = pPools->GetVehicle ( (DWORD *)pInterface ); break; - case ENTITY_TYPE_OBJECT: - pReturn = pPools->GetObject((DWORD *)pInterface); - break; default: break; } } diff --git a/MTA10/game_sa/CExplosionManagerSA.cpp b/MTA10/game_sa/CExplosionManagerSA.cpp index 700665db23..3d9bfef9ac 100644 --- a/MTA10/game_sa/CExplosionManagerSA.cpp +++ b/MTA10/game_sa/CExplosionManagerSA.cpp @@ -113,6 +113,16 @@ CExplosion * CExplosionManagerSA::GetExplosion ( DWORD ID ) return Explosions[ID]; } +CExplosion * CExplosionManagerSA::GetExplosion ( CExplosionSAInterface * explosion ) +{ + DEBUG_TRACE("CExplosion * CExplosionManagerSA::GetExplosion ( CExplosionSAInterface * explosion )"); + for(int i = 0; i < MAX_EXPLOSIONS; i++) + { + if ( Explosions[i]->GetInterface () == explosion ) return Explosions[i]; + } + return NULL; +} + CExplosion * CExplosionManagerSA::FindFreeExplosion ( ) { DEBUG_TRACE("CExplosion * CExplosionManagerSA::FindFreeExplosion ( )"); diff --git a/MTA10/game_sa/CExplosionManagerSA.h b/MTA10/game_sa/CExplosionManagerSA.h index 706c97f272..2e3a5e9977 100644 --- a/MTA10/game_sa/CExplosionManagerSA.h +++ b/MTA10/game_sa/CExplosionManagerSA.h @@ -34,6 +34,7 @@ class CExplosionManagerSA : public CExplosionManager VOID RemoveAllExplosionsInArea ( CVector * vecPosition, FLOAT fRadius ); VOID RemoveAllExplosions ( void ); CExplosion * GetExplosion ( DWORD ID ); + CExplosion * GetExplosion ( CExplosionSAInterface * explosion ); CExplosion * FindFreeExplosion ( void ); private: diff --git a/MTA10/game_sa/CGameSA.cpp b/MTA10/game_sa/CGameSA.cpp index 509a338c58..d79ce2c932 100644 --- a/MTA10/game_sa/CGameSA.cpp +++ b/MTA10/game_sa/CGameSA.cpp @@ -99,16 +99,17 @@ CGameSA::CGameSA() this->m_pWaterManager = new CWaterManagerSA (); // Normal weapon types (WEAPONSKILL_STD) - for ( int i = 0;i < WEAPONTYPE_LAST_WEAPONTYPE;i++) - WeaponInfos[i] = new CWeaponInfoSA((CWeaponInfoSAInterface *)(ARRAY_WeaponInfo + i * CLASSSIZE_WeaponInfo), (eWeaponType)i); + for ( int i = 0; i < NUM_WeaponInfosStdSkill; i++) + WeaponInfos[i] = new CWeaponInfoSA((CWeaponInfoSAInterface *)(ARRAY_WeaponInfo + i*CLASSSIZE_WeaponInfo), (eWeaponType)(WEAPONTYPE_PISTOL + i)); + // Extra weapon types for skills (WEAPONSKILL_POOR,WEAPONSKILL_PRO,WEAPONSKILL_SPECIAL) int index; for ( int skill = 0; skill < 3 ; skill++ ) { - for ( int i = 0 ; i < NUM_WeaponInfoSkills ; i++ ) + for ( int i = 0; i < NUM_WeaponInfosOtherSkill; i++ ) { - index = WEAPONTYPE_LAST_WEAPONTYPE+(skill*NUM_WeaponInfoSkills)+i; - WeaponInfos[index] = new CWeaponInfoSA((CWeaponInfoSAInterface *)(ARRAY_WeaponInfo + index * CLASSSIZE_WeaponInfo), (eWeaponType)(i+WEAPONTYPE_PISTOL)); + index = NUM_WeaponInfosStdSkill + skill*NUM_WeaponInfosOtherSkill + i; + WeaponInfos[index] = new CWeaponInfoSA((CWeaponInfoSAInterface *)(ARRAY_WeaponInfo + index*CLASSSIZE_WeaponInfo), (eWeaponType)(WEAPONTYPE_PISTOL + i)); } } @@ -126,7 +127,7 @@ CGameSA::~CGameSA ( void ) delete reinterpret_cast < CPlayerInfoSA* > ( m_pPlayerInfo ); - for ( int i = 0; i < WEAPONTYPE_LAST_WEAPONTYPE; i++ ) + for ( int i = 0; i < NUM_WeaponInfosTotal; i++ ) { delete reinterpret_cast < CWeaponInfoSA* > ( WeaponInfos [i] ); } @@ -165,22 +166,32 @@ CGameSA::~CGameSA ( void ) delete reinterpret_cast < CAudioSA* > ( m_pAudio ); } -CWeaponInfo * CGameSA::GetWeaponInfo(eWeaponType weapon,eWeaponSkill skill) +CWeaponInfo * CGameSA::GetWeaponInfo(eWeaponType weapon, eWeaponSkill skill) { DEBUG_TRACE("CWeaponInfo * CGameSA::GetWeaponInfo(eWeaponType weapon)"); - if (weapon < WEAPONTYPE_LAST_WEAPONTYPE) + if ( (skill == WEAPONSKILL_STD && weapon >= WEAPONTYPE_UNARMED && weapon < WEAPONTYPE_LAST_WEAPONTYPE) || + (skill != WEAPONSKILL_STD && weapon >= WEAPONTYPE_PISTOL && weapon <= WEAPONTYPE_TEC9) ) { int offset = 0; switch ( skill ) { - case WEAPONSKILL_STD: offset = 0; break; - case WEAPONSKILL_POOR: offset = 25; break; - case WEAPONSKILL_PRO: offset = 36; break; - case WEAPONSKILL_SPECIAL: offset = 47; break; - default: break; + case WEAPONSKILL_STD: + offset = 0; + break; + case WEAPONSKILL_POOR: + offset = NUM_WeaponInfosStdSkill - WEAPONTYPE_PISTOL; + break; + case WEAPONSKILL_PRO: + offset = NUM_WeaponInfosStdSkill + NUM_WeaponInfosOtherSkill - WEAPONTYPE_PISTOL; + break; + case WEAPONSKILL_SPECIAL: + offset = NUM_WeaponInfosStdSkill + 2*NUM_WeaponInfosOtherSkill - WEAPONTYPE_PISTOL; + break; + default: + break; } - return WeaponInfos[weapon+offset]; + return WeaponInfos[offset + weapon]; } else return NULL; @@ -201,7 +212,7 @@ bool CGameSA::IsInForeground () return *VAR_IsForegroundWindow; } -CModelInfo * CGameSA::GetModelInfo(DWORD dwModelID ) +CModelInfo * CGameSA::GetModelInfo(DWORD dwModelID) { DEBUG_TRACE("CModelInfo * CGameSA::GetModelInfo(DWORD dwModelID )"); if (dwModelID < MODELINFO_MAX) @@ -394,6 +405,8 @@ void CGameSA::Initialize ( void ) { // Initialize garages m_pGarages->Initialize(); + + SetupSpecialCharacters (); } eGameVersion CGameSA::GetGameVersion ( void ) @@ -516,3 +529,58 @@ void CGameSA::ResetCheats () for ( it = m_Cheats.begin (); it != m_Cheats.end (); it++ ) *(it->second) = 0; } + + +bool CGameSA::IsTakingPhoto ( void ) +{ + return * ( bool * ) ( VAR_CWeapon_TakingPhoto ); +} + +void CGameSA::SetupSpecialCharacters ( void ) +{ + ModelInfo[1].MakePedModel ( "TRUTH" ); + ModelInfo[2].MakePedModel ( "MACCER" ); + //ModelInfo[190].MakePedModel ( "BARBARA" ); + //ModelInfo[191].MakePedModel ( "HELENA" ); + //ModelInfo[192].MakePedModel ( "MICHELLE" ); + //ModelInfo[193].MakePedModel ( "KATIE" ); + //ModelInfo[194].MakePedModel ( "MILLIE" ); + //ModelInfo[195].MakePedModel ( "DENISE" ); + ModelInfo[265].MakePedModel ( "TENPEN" ); + ModelInfo[266].MakePedModel ( "PULASKI" ); + ModelInfo[267].MakePedModel ( "HERN" ); + ModelInfo[268].MakePedModel ( "DWAYNE" ); + ModelInfo[269].MakePedModel ( "SMOKE" ); + ModelInfo[270].MakePedModel ( "SWEET" ); + ModelInfo[271].MakePedModel ( "RYDER" ); + ModelInfo[272].MakePedModel ( "FORELLI" ); + ModelInfo[290].MakePedModel ( "ROSE" ); + ModelInfo[291].MakePedModel ( "PAUL" ); + ModelInfo[292].MakePedModel ( "CESAR" ); + ModelInfo[293].MakePedModel ( "OGLOC" ); + ModelInfo[294].MakePedModel ( "WUZIMU" ); + ModelInfo[295].MakePedModel ( "TORINO" ); + ModelInfo[296].MakePedModel ( "JIZZY" ); + ModelInfo[297].MakePedModel ( "MADDOGG" ); + ModelInfo[298].MakePedModel ( "CAT" ); + ModelInfo[299].MakePedModel ( "CLAUDE" ); + ModelInfo[300].MakePedModel ( "RYDER2" ); + ModelInfo[301].MakePedModel ( "RYDER3" ); + ModelInfo[302].MakePedModel ( "EMMET" ); + ModelInfo[303].MakePedModel ( "ANDRE" ); + ModelInfo[304].MakePedModel ( "KENDL" ); + ModelInfo[305].MakePedModel ( "JETHRO" ); + ModelInfo[306].MakePedModel ( "ZERO" ); + ModelInfo[307].MakePedModel ( "TBONE" ); + ModelInfo[308].MakePedModel ( "SINDACO" ); + ModelInfo[309].MakePedModel ( "JANITOR" ); + ModelInfo[310].MakePedModel ( "BBTHIN" ); + ModelInfo[311].MakePedModel ( "SMOKEV" ); + /* Hot-coffee only models + ModelInfo[312].MakePedModel ( "GANGRL2" ); + ModelInfo[313].MakePedModel ( "MECGRL2" ); + ModelInfo[314].MakePedModel ( "GUNGRL2" ); + ModelInfo[315].MakePedModel ( "COPGRL2" ); + ModelInfo[316].MakePedModel ( "NURGRL2" ); + */ +} \ No newline at end of file diff --git a/MTA10/game_sa/CGameSA.h b/MTA10/game_sa/CGameSA.h index fb96774cf0..658748dcc7 100644 --- a/MTA10/game_sa/CGameSA.h +++ b/MTA10/game_sa/CGameSA.h @@ -32,8 +32,9 @@ #define ARRAY_WeaponInfo 0xC8AAB8 // ##SA## #define CLASSSIZE_WeaponInfo 112 // ##SA## -#define NUM_WeaponInfoSkills 11 -#define NUM_WeaponInfo WEAPONTYPE_LAST_WEAPONTYPE+(3*NUM_WeaponInfoSkills) // 3 sets of skill weapon infos +#define NUM_WeaponInfosStdSkill WEAPONTYPE_LAST_WEAPONTYPE +#define NUM_WeaponInfosOtherSkill 11 +#define NUM_WeaponInfosTotal (NUM_WeaponInfosStdSkill + (3*NUM_WeaponInfosOtherSkill)) // std, (poor, pro, special) #define MODELINFO_LAST_PLAYER_ID 288 // ?? #define MODELINFO_MAX 65535 @@ -47,6 +48,7 @@ #define VAR_ExtraBunnyhopEnabled 0x969161 // ##SA## #define VAR_HoveringCarsEnabled 0x969152 // ##SA## #define VAR_ExtraJumpEnabled 0x96916C // ##SA## +#define VAR_CWeapon_TakingPhoto 0xC8A7C1 #define CHEAT_HOVERINGCARS "hovercars" #define CHEAT_FLYINGCARS "aircars" @@ -58,7 +60,7 @@ class CGameSA : public CGame friend class COffsets; private: - CWeaponInfo * WeaponInfos[NUM_WeaponInfo]; + CWeaponInfo * WeaponInfos[NUM_WeaponInfosTotal]; CModelInfoSA ModelInfo[MODELINFO_MAX]; public: CGameSA(); // constructor @@ -161,6 +163,10 @@ class CGameSA : public CGame bool SetCheatEnabled ( const char* szCheatName, bool bEnable ); void ResetCheats (); + bool IsTakingPhoto ( void ); + + void SetupSpecialCharacters ( void ); + private: CPools * m_pPools; CPlayerInfo * m_pPlayerInfo; diff --git a/MTA10/game_sa/CModelInfoSA.cpp b/MTA10/game_sa/CModelInfoSA.cpp index 1ca463fb2d..314fb6c60b 100644 --- a/MTA10/game_sa/CModelInfoSA.cpp +++ b/MTA10/game_sa/CModelInfoSA.cpp @@ -41,6 +41,12 @@ CModelInfoSA::CModelInfoSA ( DWORD dwModelID ) } +CBaseModelInfoSAInterface * CModelInfoSA::GetInterface ( void ) +{ + return m_pInterface = ppModelInfo [ m_dwModelID ]; +} + + BOOL CModelInfoSA::IsBoat ( ) { DEBUG_TRACE("BOOL CModelInfoSA::IsBoat ( )"); @@ -472,6 +478,13 @@ unsigned short CModelInfoSA::GetTextureDictionaryID () return 0; } +void CModelInfoSA::SetTextureDictionaryID ( unsigned short usID ) +{ + m_pInterface = ppModelInfo [ m_dwModelID ]; + if ( m_pInterface ) + m_pInterface->usTextureDictionary = usID; +} + float CModelInfoSA::GetLODDistance () { m_pInterface = ppModelInfo [ m_dwModelID ]; @@ -603,7 +616,7 @@ void CModelInfoSA::AddRef ( bool bWaitForLoad ) if ( !IsLoaded () ) { // Request it. Wait for it to load if we're asked to. - Request ( bWaitForLoad, bWaitForLoad ); + Request ( true, bWaitForLoad ); } // Increment the references. @@ -897,3 +910,14 @@ void CModelInfoSA::SetVoice ( const char* szVoiceType, const char* szVoice ) return; SetVoice ( sVoiceType, sVoiceID ); } + + +void CModelInfoSA::MakePedModel ( char * szTexture ) +{ + // Create a new CPedModelInfo + CPedModelInfoSA pedModelInfo; + ppModelInfo [ m_dwModelID ] = ( CBaseModelInfoSAInterface * ) pedModelInfo.GetPedModelInfoInterface (); + + // Load our texture + pGame->GetStreaming ()->RequestSpecialModel ( m_dwModelID, szTexture, 0 ); +} \ No newline at end of file diff --git a/MTA10/game_sa/CModelInfoSA.h b/MTA10/game_sa/CModelInfoSA.h index 3d4b7077f9..0690d1eeda 100644 --- a/MTA10/game_sa/CModelInfoSA.h +++ b/MTA10/game_sa/CModelInfoSA.h @@ -64,6 +64,8 @@ class CPedModelInfoSAInterface; #define FUNC_CVehicleModelInfo__GetNumRemaps 0x4C86B0 #define FUNC_SetColModel 0x4C4BC0 +#define FUNC_AddPedModel 0x4c67a0 +#define VAR_CTempColModels_ModelPed1 0x968DF0 /** * \todo Fill this class with info from R* */ @@ -235,7 +237,7 @@ class CModelInfoSA : public CModelInfo CModelInfoSA ( void ); CModelInfoSA ( DWORD dwModelID ); - CBaseModelInfoSAInterface * GetInterface ( void ) { return m_pInterface; } + CBaseModelInfoSAInterface * GetInterface ( void ); CPedModelInfoSAInterface * GetPedModelInfoInterface ( void ) { return reinterpret_cast < CPedModelInfoSAInterface * > ( GetInterface () ); } BOOL IsBoat ( void ); @@ -263,6 +265,7 @@ class CModelInfoSA : public CModelInfo bool IsValid ( void ); float GetDistanceFromCentreOfMassToBaseOfModel ( void ); unsigned short GetTextureDictionaryID ( void ); + void SetTextureDictionaryID ( unsigned short usID ); float GetLODDistance ( void ); void SetLODDistance ( float fDistance ); void RestreamIPL ( void ); @@ -296,6 +299,8 @@ class CModelInfoSA : public CModelInfo inline void SetModelID ( DWORD dwModelID ) { m_dwModelID = dwModelID; } inline RwObject* GetRwObject ( void ) { return m_pInterface ? m_pInterface->pRwObject : NULL; } + + void MakePedModel ( char * szTexture ); }; #endif \ No newline at end of file diff --git a/MTA10/game_sa/CObjectSA.cpp b/MTA10/game_sa/CObjectSA.cpp index 9d9f530865..c82b577ee4 100644 --- a/MTA10/game_sa/CObjectSA.cpp +++ b/MTA10/game_sa/CObjectSA.cpp @@ -36,6 +36,7 @@ CObjectSA::CObjectSA(CObjectSAInterface * objectInterface) DEBUG_TRACE("CObjectSA::CObjectSA(CObjectSAInterface * objectInterface)"); this->SetInterface(objectInterface); m_ucAlpha = 255; + CheckForGangTag ( ); } CObjectSA::CObjectSA( DWORD dwModel ) @@ -153,6 +154,7 @@ CObjectSA::CObjectSA( DWORD dwModel ) this->internalID = pGame->GetPools ()->GetObjectRef ( (DWORD *)this->GetInterface () ); m_ucAlpha = 255; + CheckForGangTag (); } CObjectSA::~CObjectSA( ) @@ -254,4 +256,20 @@ void CObjectSA::SetModelIndex ( unsigned long ulModel ) push ulModel call dwFunc } -} \ No newline at end of file + CheckForGangTag (); +} + +void CObjectSA::CheckForGangTag ( ) +{ + switch ( GetModelIndex () ) + { + case 1524: case 1525: case 1526: case 1527: + case 1528: case 1529: case 1530: case 1531: + m_bIsAGangTag = true; + break; + default: + m_bIsAGangTag = false; + break; + } +} + diff --git a/MTA10/game_sa/CObjectSA.h b/MTA10/game_sa/CObjectSA.h index d95375d109..eacb9b5668 100644 --- a/MTA10/game_sa/CObjectSA.h +++ b/MTA10/game_sa/CObjectSA.h @@ -34,6 +34,7 @@ class CObjectSA : public virtual CObject, public virtual CPhysicalSA { private: unsigned char m_ucAlpha; + bool m_bIsAGangTag; public: CObjectSA ( CObjectSAInterface * objectInterface ); @@ -50,6 +51,10 @@ class CObjectSA : public virtual CObject, public virtual CPhysicalSA inline void SetAlpha ( unsigned char ucAlpha ) { m_ucAlpha = ucAlpha; } inline unsigned char GetAlpha ( ) { return m_ucAlpha; } + + bool IsAGangTag ( ) const { return m_bIsAGangTag; } +private: + void CheckForGangTag ( ); }; /* diff --git a/MTA10/game_sa/CPedModelInfoSA.cpp b/MTA10/game_sa/CPedModelInfoSA.cpp index 3285235858..6c08443b5a 100644 --- a/MTA10/game_sa/CPedModelInfoSA.cpp +++ b/MTA10/game_sa/CPedModelInfoSA.cpp @@ -14,6 +14,19 @@ #include "StdInc.h" +CPedModelInfoSAInterface::CPedModelInfoSAInterface ( void ) +{ + memset ( this, 0, sizeof ( CPedModelInfoSAInterface ) ); + VFTBL = ( CBaseModelInfo_SA_VTBL * ) VAR_CPedModelInfo_VTBL; + pColModel = ( CColModelSAInterface * ) VAR_CTempColModels_ModelPed1; + * ( DWORD * ) &pad = 0xFFFFFFFF; +} + +CPedModelInfoSA::CPedModelInfoSA ( void ) : CModelInfoSA () +{ + m_pPedModelInterface = new CPedModelInfoSAInterface; +} + void CPedModelInfoSA::SetMotionAnimGroup ( AssocGroupId animGroup ) { DWORD dwThis = (DWORD)m_pInterface; diff --git a/MTA10/game_sa/CPedModelInfoSA.h b/MTA10/game_sa/CPedModelInfoSA.h index d1d72c72f5..d324fc7411 100644 --- a/MTA10/game_sa/CPedModelInfoSA.h +++ b/MTA10/game_sa/CPedModelInfoSA.h @@ -21,6 +21,8 @@ class ePedStats; typedef long AssocGroupID; +#define FUNC_CPedModelInfo_Constructor 0x4c57a0 +#define VAR_CPedModelInfo_VTBL 0x85bdc0 #define FUNC_SetMotionAnimGroup 0x5b3580 // CPedModelInfo: @@ -41,10 +43,12 @@ typedef long AssocGroupID; class CPedModelInfoSAInterface : public CBaseModelInfoSAInterface { public: + CPedModelInfoSAInterface ( void ); + BYTE pad [ 4 ]; // 32 AssocGroupID motionAnimGroup; // 36 Motion anim group (AssocGroupID, long) DWORD pedType; // 40 Default ped type (long) - ePedStats * pedStats; // 44 Default ped stats (ePedStats) + DWORD pedStatsID; // 44 Default ped stats (ePedStats) BYTE bCanDriveCars; // 48 Can drive cars (byte) BYTE pad2 [ 1 ]; // 49 short pedFlags; // 50 Ped flags (short) @@ -62,9 +66,13 @@ class CPedModelInfoSAInterface : public CBaseModelInfoSAInterface class CPedModelInfoSA : public CModelInfoSA, public CPedModelInfo { public: - CPedModelInfoSAInterface * GetPedModelInfoInterface ( void ) { return reinterpret_cast < CPedModelInfoSAInterface * > ( m_pInterface ); } + CPedModelInfoSA ( void ); + CPedModelInfoSAInterface * GetPedModelInfoInterface ( void ) { return m_pPedModelInterface; } + + void SetMotionAnimGroup ( AssocGroupId animGroup ); - void SetMotionAnimGroup ( AssocGroupId animGroup ); +private: + CPedModelInfoSAInterface * m_pPedModelInterface; }; #endif \ No newline at end of file diff --git a/MTA10/game_sa/CPedSA.cpp b/MTA10/game_sa/CPedSA.cpp index 3d503fe234..152e3267fd 100644 --- a/MTA10/game_sa/CPedSA.cpp +++ b/MTA10/game_sa/CPedSA.cpp @@ -23,6 +23,8 @@ CPedSA::CPedSA ( ) : m_pPedSound ( NULL ) { DEBUG_TRACE("CPedSA::CPedSA( )"); + + memset ( this->m_pWeapons, 0, sizeof ( CWeaponSA* ) * WEAPONSLOT_MAX ); } CPedSA::CPedSA( CPedSAInterface * pPedInterface ) : @@ -31,6 +33,8 @@ CPedSA::CPedSA( CPedSAInterface * pPedInterface ) : m_pPedSound ( NULL ) { DEBUG_TRACE("CPedSA::CPedSA( CPedSAInterface * pedInterface )"); + + memset ( this->m_pWeapons, 0, sizeof ( CWeaponSA* ) * WEAPONSLOT_MAX ); } VOID CPedSA::SetInterface( CEntitySAInterface * intInterface ) @@ -42,6 +46,12 @@ CPedSA::~CPedSA ( void ) { if ( m_pPedIntelligence ) delete m_pPedIntelligence; if ( m_pPedSound ) delete m_pPedSound; + + for ( int i = 0; i < WEAPONSLOT_MAX; i++ ) + { + if ( this->m_pWeapons[i] ) + delete this->m_pWeapons[i]; + } } // used to init weapons at the moment, called by CPlayerPedSA when its been constructed diff --git a/MTA10/game_sa/CStreamingSA.cpp b/MTA10/game_sa/CStreamingSA.cpp index a1e6cdcf4e..b7311c6f27 100644 --- a/MTA10/game_sa/CStreamingSA.cpp +++ b/MTA10/game_sa/CStreamingSA.cpp @@ -22,4 +22,18 @@ void CStreamingSA::RequestAnimations ( int i, int j ) call dwFunc add esp, 0x8 } +} + + +void CStreamingSA::RequestSpecialModel ( DWORD model, const char * szTexture, DWORD channel ) +{ + DWORD dwFunc = FUNC_CStreaming_RequestSpecialModel; + _asm + { + push channel + push szTexture + push model + call dwFunc + add esp, 0xC + } } \ No newline at end of file diff --git a/MTA10/game_sa/CStreamingSA.h b/MTA10/game_sa/CStreamingSA.h index 40fc310f21..cc302bceee 100644 --- a/MTA10/game_sa/CStreamingSA.h +++ b/MTA10/game_sa/CStreamingSA.h @@ -16,12 +16,14 @@ #include #include "Common.h" -#define FUNC_CStreaming_RequestAnimations 0x407120 +#define FUNC_CStreaming_RequestAnimations 0x407120 +#define FUNC_CStreaming_RequestSpecialModel 0x409d10 class CStreamingSA : public CStreaming { public: void RequestAnimations ( int i, int j ); + void RequestSpecialModel ( DWORD model, const char * szTexture, DWORD channel ); }; #endif \ No newline at end of file diff --git a/MTA10/game_sa/CTasksSA.cpp b/MTA10/game_sa/CTasksSA.cpp index 453786461e..2eb0219543 100644 --- a/MTA10/game_sa/CTasksSA.cpp +++ b/MTA10/game_sa/CTasksSA.cpp @@ -191,7 +191,7 @@ CTaskComplexDie* CTasksSA::CreateTaskComplexDie ( const eWeaponType eMeansOfDeat } -CTaskSimpleStealthKill* CTasksSA::CreateTaskSimpleStealthKill ( bool bKiller, class CPed * pPed, const AnimationId animGroup ) +CTaskSimpleStealthKill* CTasksSA::CreateTaskSimpleStealthKill ( bool bKiller, class CPed * pPed, const AssocGroupId animGroup ) { DEBUG_TRACE("CTaskSimpleStealthKill* CTasksSA::CreateTaskSimpleStealthKill ( bool bKiller, class CPed * pPed, const AnimationId anim )"); diff --git a/MTA10/game_sa/CTasksSA.h b/MTA10/game_sa/CTasksSA.h index 6595182829..a7d66a891c 100644 --- a/MTA10/game_sa/CTasksSA.h +++ b/MTA10/game_sa/CTasksSA.h @@ -64,7 +64,7 @@ class CTasksSA : public CTasks CTaskSimpleRunNamedAnim* CreateTaskSimpleRunNamedAnim ( const char* pAnimName, const char* pAnimGroupName, const int flags, const float fBlendDelta, const int iTime = -1, const bool bDontInterrupt = false, const bool bRunInSequence = false, const bool bOffsetPed = false, const bool bHoldLastFrame = false ); CTaskComplexDie* CreateTaskComplexDie ( const eWeaponType eMeansOfDeath=WEAPONTYPE_UNARMED, const AssocGroupId animGroup=0/*ANIM_STD_PED*/, const AnimationId anim=0/*ANIM_STD_KO_FRONT*/, const float fBlendDelta=4.0f, const float fAnimSpeed=0.0f, const bool bBeingKilledByStealth=false, const bool bFallingToDeath=false, const int iFallToDeathDir=0, const bool bFallToDeathOverRailing=false ); - CTaskSimpleStealthKill* CreateTaskSimpleStealthKill ( bool bAttacker, class CPed * pPed, const AnimationId anim ); + CTaskSimpleStealthKill* CreateTaskSimpleStealthKill ( bool bAttacker, class CPed * pPed, const AssocGroupId animGroup ); CTaskComplexSunbathe* CreateTaskComplexSunbathe ( class CObject* pTowel, const bool bStartStanding ); diff --git a/MTA10/game_sa/CWeaponInfoSA.h b/MTA10/game_sa/CWeaponInfoSA.h index ab3cc210ce..91249eec4f 100644 --- a/MTA10/game_sa/CWeaponInfoSA.h +++ b/MTA10/game_sa/CWeaponInfoSA.h @@ -47,7 +47,7 @@ class CWeaponInfoSAInterface // 112 byte long class // skill settings eWeaponSkill m_SkillLevel; // what's the skill level of this weapontype - FLOAT m_nReqStatLevel; // what stat level is required for this skill level + int m_nReqStatLevel; // what stat level is required for this skill level FLOAT m_fAccuracy; // modify accuracy of weapon FLOAT m_fMoveSpeed; // how fast can move with weapon diff --git a/MTA10/game_sa/CWorldSA.cpp b/MTA10/game_sa/CWorldSA.cpp index cb5451860a..bba2358864 100644 --- a/MTA10/game_sa/CWorldSA.cpp +++ b/MTA10/game_sa/CWorldSA.cpp @@ -209,7 +209,7 @@ bool CWorldSA::ProcessLineOfSight(CVector * vecStart, CVector * vecEnd, CColPoin } } if ( colCollision ) *colCollision = pColPointSA; - else delete pColPointSA; + else pColPointSA->Destroy (); return bReturn; } diff --git a/MTA10/gui/CGUIGridList_Impl.cpp b/MTA10/gui/CGUIGridList_Impl.cpp index 9906d1ed6f..fbf2f7d2e4 100644 --- a/MTA10/gui/CGUIGridList_Impl.cpp +++ b/MTA10/gui/CGUIGridList_Impl.cpp @@ -289,6 +289,17 @@ void CGUIGridList_Impl::SetItemData ( int iRow, int hColumn, void* pData ) } +void CGUIGridList_Impl::SetItemData ( int iRow, int hColumn, const char* pszData ) +{ + // Get the current item at that offset and set the text + CGUIListItem* pItem = GetItem ( iRow, hColumn ); + if ( pItem ) + { + pItem->SetData ( pszData ); + } +} + + int CGUIGridList_Impl::SetItemText ( int iRow, int hColumn, const char* szText, bool bNumber, bool bSection, bool bFast ) { try diff --git a/MTA10/gui/CGUIGridList_Impl.h b/MTA10/gui/CGUIGridList_Impl.h index 284e26b110..63d4716bac 100644 --- a/MTA10/gui/CGUIGridList_Impl.h +++ b/MTA10/gui/CGUIGridList_Impl.h @@ -42,7 +42,8 @@ class CGUIGridList_Impl : public CGUIGridList, public CGUIElement_Impl CGUIListItem* GetItem ( int iRow, int hColumn ); char* GetItemText ( int iRow, int hColumn ); int SetItemText ( int iRow, int hColumn, const char* szText, bool bNumber = false, bool bSection = false, bool bFast = false ); - void SetItemData ( int iRow, int hColumn, void* pData ); + void SetItemData ( int iRow, int hColumn, void* pData ); + void SetItemData ( int iRow, int hColumn, const char* pszData ); void* GetItemData ( int iRow, int hColumn ); void SetHorizontalScrollBar ( bool bEnabled ); diff --git a/MTA10/gui/CGUIListItem_Impl.cpp b/MTA10/gui/CGUIListItem_Impl.cpp index 5cedc43298..010c3f453d 100644 --- a/MTA10/gui/CGUIListItem_Impl.cpp +++ b/MTA10/gui/CGUIListItem_Impl.cpp @@ -62,15 +62,30 @@ void CGUIListItem_Impl::SetFont ( const char *szFontName ) } -void CGUIListItem_Impl::SetText ( const char *Text ) +void CGUIListItem_Impl::SetText ( const char *pszText ) { CEGUI::String strText; - if ( Text ) strText.assign ( Text ); + if ( pszText ) + strText.assign ( pszText ); m_pListItem->setText ( strText ); } +void CGUIListItem_Impl::SetData ( const char* pszData ) +{ + if ( pszData ) + { + m_strData = pszData; + m_pData = (void *)m_strData.c_str (); + } + else + { + m_pData = NULL; + } +} + + void CGUIListItem_Impl::SetImage ( CGUIStaticImage* pImage ) { if ( ItemType == Type::ImageItem ) @@ -81,7 +96,7 @@ void CGUIListItem_Impl::SetImage ( CGUIStaticImage* pImage ) } -std::string CGUIListItem_Impl::GetText ( void ) +std::string CGUIListItem_Impl::GetText ( void ) const { return m_pListItem->getText ().c_str (); } @@ -92,16 +107,6 @@ CEGUI::ListboxItem* CGUIListItem_Impl::GetListItem ( void ) return m_pListItem; } -void* CGUIListItem_Impl::GetData ( void ) -{ - return m_pData; -} - -void CGUIListItem_Impl::SetData ( void* pData ) -{ - m_pData = pData; -} - bool CGUIListItem_Impl::GetSelectedState ( void ) { return m_pListItem->isSelected (); diff --git a/MTA10/gui/CGUIListItem_Impl.h b/MTA10/gui/CGUIListItem_Impl.h index b6a8790042..185c3fcc4c 100644 --- a/MTA10/gui/CGUIListItem_Impl.h +++ b/MTA10/gui/CGUIListItem_Impl.h @@ -34,11 +34,12 @@ class CGUIListItem_Impl : public CGUIListItem CGUIListItem_Impl ( const char* szText = "", unsigned int uiType = 0, CGUIStaticImage_Impl* pImage = NULL ); ~CGUIListItem_Impl ( void ); - void SetText ( const char *Text ); - std::string GetText ( void ); + std::string GetText ( void ) const; + void SetText ( const char *pszText ); - void* GetData ( void ); - void SetData ( void* pData ); + void* GetData ( void ) const { return m_pData; } + void SetData ( void* pData ) { m_pData = pData; } + void SetData ( const char* pszData ); void SetDisabled ( bool bDisabled ); void SetFont ( const char *szFontName ); @@ -53,7 +54,8 @@ class CGUIListItem_Impl : public CGUIListItem private: CEGUI::ListboxItem* m_pListItem; - void* m_pData; + void* m_pData; + std::string m_strData; }; #endif diff --git a/MTA10/loader/Main.cpp b/MTA10/loader/Main.cpp index 12790a9fc7..021a3ee189 100644 --- a/MTA10/loader/Main.cpp +++ b/MTA10/loader/Main.cpp @@ -282,7 +282,7 @@ int WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLi // Basic check for the data files { char szFileName[MAX_PATH] = {'\0'}; - _snprintf ( szFileName, MAX_PATH, "%s\\mta\\vorbis.ax", szMTASAPath ); + _snprintf ( szFileName, MAX_PATH, "%s\\mta\\cgui\\CGUI.png", szMTASAPath ); // Check if vorbis.ax exists if ( INVALID_HANDLE_VALUE == FindFirstFile ( szFileName, &fdFileInfo ) ) diff --git a/MTA10/mods/deathmatch/_Deathmatch 2008.vcproj b/MTA10/mods/deathmatch/_Deathmatch 2008.vcproj index c2a8a19ba1..53fd35cb1d 100644 --- a/MTA10/mods/deathmatch/_Deathmatch 2008.vcproj +++ b/MTA10/mods/deathmatch/_Deathmatch 2008.vcproj @@ -400,10 +400,6 @@ RelativePath=".\logic\CFoo.cpp" > - - diff --git a/MTA10/mods/deathmatch/logic/CClientGame.cpp b/MTA10/mods/deathmatch/logic/CClientGame.cpp index 8959400112..f96a463447 100644 --- a/MTA10/mods/deathmatch/logic/CClientGame.cpp +++ b/MTA10/mods/deathmatch/logic/CClientGame.cpp @@ -32,9 +32,6 @@ using std::list; // Used within this file by the packet handler to grab the this pointer of CClientGame extern CClientGame* g_pClientGame; -// Global variable holding the current interval in seconds between this frame and the previous one -extern float g_fTimeSlice = 0; - // Used by the Voice system #ifdef MTA_VOICE CVariableBuffer * CClientGame::m_pVoiceBuffer; @@ -42,7 +39,7 @@ CRITICAL_SECTION CClientGame::m_crVoice; #endif bool g_bBoundsChecker = true; -double dHack; + #define DEFAULT_GRAVITY 0.008f #define DEFAULT_GAME_SPEED 1.0f #define DEFAULT_BLUR_LEVEL 36 @@ -112,6 +109,7 @@ CClientGame::CClientGame ( bool bLocalPlay ) //Setup game glitch defaults ( false = disabled ). Remember to update these serverside if you alter them! m_Glitches [ GLITCH_QUICKRELOAD ] = false; + g_pMultiplayer->DisableQuickReload ( true ); m_Glitches [ GLITCH_FASTFIRE ] = false; m_Glitches [ GLITCH_FASTMOVE ] = false; @@ -149,6 +147,9 @@ CClientGame::CClientGame ( bool bLocalPlay ) g_pCore->GetGUI ()->SetMovedHandler ( GUI_CALLBACK ( &CClientGame::OnMove, this ) ); g_pCore->GetGUI ()->SetSizedHandler ( GUI_CALLBACK ( &CClientGame::OnSize, this ) ); + // Startup "entities from root" optimization for getElementsByType + CClientEntity::StartupEntitiesFromRoot (); + // Initialize our root entity with an invalid id, we dont know the true id until map-start m_pRootEntity = new CClientDummy ( NULL, INVALID_ELEMENT_ID, "root" ); m_pRootEntity->MakeSystemEntity (); @@ -211,7 +212,10 @@ CClientGame::CClientGame ( bool bLocalPlay ) else m_ulTimeStart = CClientTime::GetTime (); - // Register the message and the net packet handler + m_dwFrameTimeSlice = 0; + m_dwLastFrameTick = 0; + + // Register our handlers g_pMultiplayer->SetPreWeaponFireHandler ( CClientGame::PreWeaponFire ); g_pMultiplayer->SetPostWeaponFireHandler ( CClientGame::PostWeaponFire ); g_pMultiplayer->SetExplosionHandler ( CClientExplosionManager::Hook_StaticExplosionCreation ); @@ -228,8 +232,12 @@ CClientGame::CClientGame ( bool bLocalPlay ) g_pMultiplayer->SetAddAnimationHandler ( CClientGame::StaticAddAnimationHandler ); g_pMultiplayer->SetBlendAnimationHandler ( CClientGame::StaticBlendAnimationHandler ); g_pMultiplayer->SetPreHudDrawHandler ( CClientGame::StaticPreHudDrawHandler ); + g_pMultiplayer->SetBlowUpCarHandler ( CClientGame::StaticBlowUpCarHandler ); + g_pMultiplayer->SetPedOnFireHandler ( CClientGame::StaticPedOnFireHandler ); m_pProjectileManager->SetInitiateHandler ( CClientGame::StaticProjectileInitiateHandler ); g_pCore->SetMessageProcessor ( CClientGame::StaticProcessMessage ); + g_pCore->GetKeyBinds ()->SetKeyStrokeHandler ( CClientGame::StaticKeyStrokeHandler ); + g_pCore->GetKeyBinds ()->SetCharacterKeyHandler ( CClientGame::StaticCharacterKeyHandler ); g_pNet->RegisterPacketHandler ( CClientGame::StaticProcessPacket ); m_pLuaManager = new CLuaManager ( this ); @@ -361,8 +369,12 @@ CClientGame::~CClientGame ( void ) g_pMultiplayer->SetAddAnimationHandler ( NULL ); g_pMultiplayer->SetBlendAnimationHandler ( NULL ); g_pMultiplayer->SetPreHudDrawHandler ( NULL ); + g_pMultiplayer->SetBlowUpCarHandler ( NULL ); + g_pMultiplayer->SetPedOnFireHandler ( NULL ); m_pProjectileManager->SetInitiateHandler ( NULL ); g_pCore->SetMessageProcessor ( NULL ); + g_pCore->GetKeyBinds ()->SetKeyStrokeHandler ( NULL ); + g_pCore->GetKeyBinds ()->SetCharacterKeyHandler ( NULL ); g_pNet->StopNetwork (); g_pNet->RegisterPacketHandler ( NULL ); CKeyBindsInterface * pKeyBinds = g_pCore->GetKeyBinds (); @@ -651,7 +663,7 @@ void CClientGame::SendVoiceData ( const unsigned char * pData, int len ) void CClientGame::DoPulsePostFrame ( void ) -{ +{ #ifdef DEBUG_KEYSTATES // Get the controller state CControllerState cs; @@ -1609,23 +1621,9 @@ void CClientGame::UpdatePlayerWeapons ( void ) if ( pWeapon ) { + /* Send a packet to the server with info about the new weapon, + so the server stays in sync reliably */ unsigned int uiSlot = static_cast < unsigned int > ( pWeapon->GetSlot () ); - - if ( !IsGlitchEnabled ( GLITCH_QUICKRELOAD ) ) - { - CWeapon* pPreviousWeapon = m_pLocalPlayer->GetWeapon ( m_lastWeaponSlot ); - if ( pPreviousWeapon ) - { - m_wasWeaponAmmoInClip [ m_lastWeaponSlot ] = pPreviousWeapon->GetAmmoInClip(); - } - if ( m_wasWeaponAmmoInClip [ uiSlot ] > 0 ) - { - m_pLocalPlayer->GetWeapon()->SetAmmoInClip ( m_wasWeaponAmmoInClip [ uiSlot ] ); - } - } - - /* Send a packet to the server with info about the NEW weapon, - so the server stays in sync reliably */ slot.data.uiSlot = uiSlot; BitStream.Write ( &slot ); @@ -1952,6 +1950,50 @@ void CClientGame::SetAllDimensions ( unsigned short usDimension ) } +void CClientGame::StaticKeyStrokeHandler ( const SBindableKey * pKey, bool bState ) +{ + g_pClientGame->KeyStrokeHandler ( pKey, bState ); +} + + +void CClientGame::KeyStrokeHandler ( const SBindableKey * pKey, bool bState ) +{ + // Do we have a root yet? + if ( m_pRootEntity ) + { + // Call our key-stroke event + CLuaArguments Arguments; + Arguments.PushString ( pKey->szKey ); + Arguments.PushBoolean ( bState ); + m_pRootEntity->CallEvent ( "onClientKey", Arguments, false ); + } +} + + +bool CClientGame::StaticCharacterKeyHandler ( WPARAM wChar ) +{ + return g_pClientGame->CharacterKeyHandler ( wChar ); +} + + +bool CClientGame::CharacterKeyHandler ( WPARAM wChar ) +{ + // Do we have a root yet? + if ( m_pRootEntity ) + { + char szCharacter [ 2 ] = { wChar, 0 }; + + // Call our character event + CLuaArguments Arguments; + Arguments.PushString ( szCharacter ); + Arguments.PushNumber ( wChar ); + m_pRootEntity->CallEvent ( "onClientCharacter", Arguments, false ); + } + + return false; +} + + void CClientGame::StaticProcessClientKeyBind ( CKeyFunctionBind* pBind ) { g_pClientGame->ProcessClientKeyBind ( pBind ); @@ -2253,7 +2295,6 @@ void CClientGame::SetMoney ( long lMoney ) void CClientGame::AddBuiltInEvents ( void ) { - // Resource events m_Events.AddEvent ( "onClientResourceStart", "resource", NULL, false ); m_Events.AddEvent ( "onClientResourceStop", "resource", NULL, false ); @@ -2309,6 +2350,7 @@ void CClientGame::AddBuiltInEvents ( void ) //m_Events.AddEvent ( "onClientGUIKeyDown", "element", NULL, false ); m_Events.AddEvent ( "onClientGUITabSwitched", "element", NULL, false ); + // Input events m_Events.AddEvent ( "onClientDoubleClick", "button, state, screenX, screenY, worldX, worldY, worldZ, element", NULL, false ); m_Events.AddEvent ( "onClientMouseMove", "screenX, screenY", NULL, false ); m_Events.AddEvent ( "onClientMouseEnter", "screenX, screenY", NULL, false ); @@ -2316,6 +2358,8 @@ void CClientGame::AddBuiltInEvents ( void ) m_Events.AddEvent ( "onClientMouseWheel", "", NULL, false ); m_Events.AddEvent ( "onClientGUIMove", "", NULL, false ); m_Events.AddEvent ( "onClientGUISize", "", NULL, false ); + m_Events.AddEvent ( "onClientKey", "key, state", NULL, false ); + m_Events.AddEvent ( "onClientCharacter", "character", NULL, false ); // Console events m_Events.AddEvent ( "onClientConsole", "text", NULL, false ); @@ -2324,8 +2368,8 @@ void CClientGame::AddBuiltInEvents ( void ) m_Events.AddEvent ( "onClientChatMessage", "test, r, g, b", NULL, false ); // Game events + m_Events.AddEvent ( "onClientPreRender", "", NULL, false ); m_Events.AddEvent ( "onClientRender", "", NULL, false ); - m_Events.AddEvent ( "onClientWorld", "", NULL, false ); // Cursor events m_Events.AddEvent ( "onClientClick", "button, state, screenX, screenY, worldX, worldY, worldZ, gui_clicked", NULL, false ); @@ -2632,7 +2676,7 @@ void CClientGame::UpdateMimics ( void ) } // Simulate lag (or not) - if ( !m_bMimicLag || CClientTime::GetTime () >= m_ulLastMimicLag + 200 ) // TICK_RATE ) + if ( !m_bMimicLag || CClientTime::GetTime () >= m_ulLastMimicLag + 1000 ) // TICK_RATE ) { m_ulLastMimicLag = CClientTime::GetTime (); @@ -2716,7 +2760,7 @@ void CClientGame::UpdateMimics ( void ) if ( m_bMimicLag ) { - pMimic->SetTargetPosition ( vecPosition, TICK_RATE ); + pMimic->SetTargetPosition ( vecPosition ); pMimic->SetMoveSpeed ( vecMoveSpeed ); pMimic->SetControllerState ( Controller ); pMimic->SetTargetRotation ( fRotation ); @@ -2789,6 +2833,10 @@ void CClientGame::UpdateMimics ( void ) pVehicle->GetMoveSpeed ( vecMoveSpeed ); pVehicle->GetTurnSpeed ( vecTurnSpeed ); fHealth = pVehicle->GetHealth (); + unsigned short usAdjustable = pVehicle->GetAdjustablePropertyValue (); + float turretX, turretY; + pVehicle->GetTurretRotation ( turretX, turretY ); + float fLandingGear = pVehicle->GetLandingGearPosition (); if ( pMimicVehicle && pMimicVehicle->GetModel () != uiModel ) { @@ -2798,7 +2846,7 @@ void CClientGame::UpdateMimics ( void ) vecPosition.fX += ( ( float ) ( uiMimicIndex + 1 ) * 10.0f ); - if ( pMimicVehicle == NULL ) + if ( !pMimicVehicle ) { pMimicVehicle = new CDeathmatchVehicle ( m_pManager, m_pUnoccupiedVehicleSync, INVALID_ELEMENT_ID, uiModel ); pMimicVehicle->SetPosition ( vecPosition ); @@ -2815,12 +2863,13 @@ void CClientGame::UpdateMimics ( void ) m_vecLastMimicPos = vecPosition; } + static_cast < CDeathmatchVehicle * > ( pMimicVehicle )->UpdateSyncTimes (); if ( m_bMimicLag ) { - pMimicVehicle->SetTargetPosition ( vecPosition, TICK_RATE ); - pMimicVehicle->SetTargetRotation ( vecRotationDegrees, TICK_RATE ); + pMimicVehicle->SetTargetPosition ( vecPosition ); + pMimicVehicle->SetTargetRotation ( vecRotationDegrees ); pMimicVehicle->SetMoveSpeed ( vecMoveSpeed ); - pMimicVehicle->SetTurnSpeed ( vecTurnSpeed ); + pMimicVehicle->SetTurnSpeed ( vecTurnSpeed ); } else { @@ -2830,6 +2879,9 @@ void CClientGame::UpdateMimics ( void ) pMimicVehicle->SetTurnSpeed ( vecTurnSpeed ); } pMimicVehicle->SetHealth ( fHealth ); + pMimicVehicle->SetAdjustablePropertyValue ( usAdjustable ); + pMimicVehicle->SetTurretRotation ( turretX, turretY ); + pMimicVehicle->SetLandingGearPosition ( fLandingGear ); if ( pMimic->GetOccupiedVehicle () != pMimicVehicle ) pMimic->WarpIntoVehicle ( pMimicVehicle, uiSeat ); @@ -2877,7 +2929,6 @@ void CClientGame::UpdateMimics ( void ) delete pMimicVehicle; } } - dHack = CClientTime::GetTimeNano (); } } } @@ -2990,6 +3041,8 @@ void CClientGame::Event_OnIngame ( void ) pHud->DisableVitalStats ( true ); pHud->DisableAreaName ( true ); + g_pMultiplayer->DeleteAndDisableGangTags (); + // Switch off peds and traffic g_pGame->GetPathFind ()->SwitchRoadsOffInArea ( &CVector(-100000.0f, -100000.0f, -100000.0f), &CVector(100000.0f, 100000.0f, 100000.0f) ); g_pGame->GetPathFind ()->SwitchPedRoadsOffInArea ( &CVector(-100000.0f, -100000.0f, -100000.0f), &CVector(100000.0f, 100000.0f, 100000.0f) ); @@ -3127,6 +3180,16 @@ void CClientGame::StaticIdleHandler ( void ) g_pClientGame->IdleHandler (); } +void CClientGame::StaticBlowUpCarHandler ( CVehicle * pVehicle, CEntity * pResponsible ) +{ + g_pClientGame->BlowUpCarHandler ( pVehicle, pResponsible ); +} + +bool CClientGame::StaticPedOnFireHandler ( CPed * pGamePed, CFire * pFire, CExplosion * pExplosion ) +{ + return g_pClientGame->PedOnFireHandler ( pGamePed, pFire, pExplosion ); +} + void CClientGame::DrawRadarAreasHandler ( void ) { m_pRadarAreaManager->DoPulse (); @@ -3206,14 +3269,17 @@ void CClientGame::PostWorldProcessHandler ( void ) m_pManager->GetMarkerManager ()->DoPulse (); // Update frame time slice - double dTimeSeconds = GetSecondCount (); - g_fTimeSlice = Clamp ( 0.0, dTimeSeconds - m_dLastTimeSeconds, 0.1 ); - m_dLastTimeSeconds = dTimeSeconds; + DWORD dwCurrentTick = GetTickCount (); + if ( m_dwLastFrameTick ) + { + m_dwFrameTimeSlice = dwCurrentTick - m_dwLastFrameTick; - // Call onClientWorld LUA event - CLuaArguments Arguments; - Arguments.PushNumber ( g_fTimeSlice ); - m_pRootEntity->CallEvent ( "onClientWorld", Arguments, false ); + // Call onClientPreRender LUA event + CLuaArguments Arguments; + Arguments.PushNumber ( m_dwFrameTimeSlice ); + m_pRootEntity->CallEvent ( "onClientPreRender", Arguments, false ); + } + m_dwLastFrameTick = dwCurrentTick; } @@ -3254,6 +3320,69 @@ void CClientGame::PreHudDrawHandler ( void ) } +void CClientGame::BlowUpCarHandler ( CVehicle * pGameVehicle, CEntity * pGameResponsible ) +{ + // CVehicle::BlowUpCar - Called constantly for all blown CPlane's + + CClientVehicle * pVehicle = m_pManager->GetVehicleManager ()->Get ( pGameVehicle, false ); + if ( pVehicle ) + { + CClientEntity * pResponsible = m_pManager->FindEntity ( pGameResponsible ); + + // Set our vehicle to blown + pVehicle->m_bBlown = true; + + // Are we in or getting into this car? + if ( m_pLocalPlayer->GetRealOccupiedVehicle () == pVehicle ) + { + // Update our damage vars + m_ucDamageWeapon = WEAPONTYPE_EXPLOSION; + m_ucDamageBodyPiece = PED_PIECE_TORSO; + m_pDamageEntity = pResponsible; + m_ulDamageTime = CClientTime::GetTime (); + m_DamagerID = ( pResponsible ) ? pResponsible->GetID () : INVALID_ELEMENT_ID; + } + } +} + + +bool CClientGame::PedOnFireHandler ( CPed * pGamePed, CFire * pFire, CExplosion * pExplosion ) +{ + // Called when a fire or explosion sets a ped on fire (NOTE: one or the other will be NULL) + // Returning false will cancel the new fire on the ped and a call to CPlayerPed::DoStuffToGoOnFire + + CClientPlayer * pPlayer = m_pManager->GetPlayerManager ()->Get ( dynamic_cast < CPlayerPed* > ( pGamePed ), false ); + + // Grab the creating entity + CEntity * pGameCreator = NULL; + if ( pFire ) pGameCreator = pFire->GetCreator (); + else if ( pExplosion ) pGameCreator = pExplosion->GetExplosionCreator (); + + CClientEntity * pCreator = NULL; + if ( pGameCreator ) pCreator = m_pManager->FindEntity ( pGameCreator ); + + CClientPlayer * pCreatorPlayer = NULL; + if ( pCreator->GetType () == CCLIENTPLAYER ) pCreatorPlayer = static_cast < CClientPlayer * > ( pCreator ); + + // Did another player cause this? + if ( pPlayer && pCreatorPlayer && pPlayer != pCreatorPlayer ) + { + // Are we on a team? + CClientTeam * pTeam = pPlayer->GetTeam (); + if ( pTeam ) + { + // Is this friendly-fire from a team-mate? + if ( pPlayer->IsOnMyTeam ( pCreatorPlayer ) && !pTeam->GetFriendlyFire () ) + { + // Dont let us burn! + return false; + } + } + } + return true; +} + + void CClientGame::DownloadFiles ( void ) { m_pTransferBox->DoPulse (); @@ -3328,6 +3457,8 @@ bool CClientGame::DamageHandler ( CPed* pDamagePed, CEventDamage * pEvent ) { // CEventDamage::AffectsPed: This is/can be called more than once for each bit of damage (and may not actually take any more health (even if we return true)) + CClientExplosionManager * pExplosionManager = m_pManager->GetExplosionManager (); + // Grab some data from the event CEntity * pInflictor = pEvent->GetInflictingEntity (); eWeaponType weaponUsed = pEvent->GetWeaponUsed (); @@ -3352,15 +3483,14 @@ bool CClientGame::DamageHandler ( CPed* pDamagePed, CEventDamage * pEvent ) if ( pInflictor ) pInflictingEntity = m_pManager->FindEntity ( pInflictor ); // If the damage was caused by an explosion - if ( weaponUsed == WEAPONTYPE_EXPLOSION ) - { - CClientEntity * pLastExplosionCreator = m_pManager->GetExplosionManager ()->m_pLastCreator; - - // If we don't have an inflictor, look for the last explosion creator - if ( !pInflictor && pLastExplosionCreator ) pInflictingEntity = pLastExplosionCreator; - + if ( weaponUsed == WEAPONTYPE_EXPLOSION || pExplosionManager->m_bCreatingExplosion ) + { // Change the weapon used to whatever created the explosion - weaponUsed = m_pManager->GetExplosionManager ()->m_LastWeaponType; + weaponUsed = pExplosionManager->m_LastWeaponType; + + // Look for the last explosion creator + CClientEntity * pLastExplosionCreator = pExplosionManager->m_pLastCreator; + if ( pLastExplosionCreator && ( !pInflictor || pExplosionManager->m_bCreatingExplosion ) ) pInflictingEntity = pLastExplosionCreator; } // Do we have a damaged ped? @@ -4693,19 +4823,21 @@ void CClientGame::NotifyBigPacketProgress ( unsigned long ulBytesReceived, unsig m_pBigPacketTransferBox->SetInfoSingleDownload ( "", Min ( ulTotalSize, ulBytesReceived ) ); } -bool CClientGame::SetGlitchEnabled ( char cGlitch, bool bEnabled ) +bool CClientGame::SetGlitchEnabled ( unsigned char ucGlitch, bool bEnabled ) { - if ( bEnabled != m_Glitches[cGlitch] ) + if ( ucGlitch < NUM_GLITCHES && bEnabled != m_Glitches[ucGlitch] ) { - m_Glitches[cGlitch] = bEnabled; + m_Glitches[ucGlitch] = bEnabled; + if ( ucGlitch == GLITCH_QUICKRELOAD ) + g_pMultiplayer->DisableQuickReload ( !bEnabled ); return true; } return false; } -bool CClientGame::IsGlitchEnabled ( char cGlitch ) +bool CClientGame::IsGlitchEnabled ( unsigned char ucGlitch ) { - return m_Glitches[cGlitch] || false; + return ucGlitch < NUM_GLITCHES && m_Glitches[ucGlitch]; } bool CClientGame::SetCloudsEnabled ( bool bEnabled ) diff --git a/MTA10/mods/deathmatch/logic/CClientGame.h b/MTA10/mods/deathmatch/logic/CClientGame.h index e50a11b178..8d3e3ef2c4 100644 --- a/MTA10/mods/deathmatch/logic/CClientGame.h +++ b/MTA10/mods/deathmatch/logic/CClientGame.h @@ -172,6 +172,7 @@ class CClientGame GLITCH_QUICKRELOAD, GLITCH_FASTFIRE, GLITCH_FASTMOVE, + NUM_GLITCHES }; class CStoredWeaponSlot { @@ -196,6 +197,8 @@ class CClientGame void DoPulsePostFrame ( void ); void DoPulses ( void ); + DWORD GetFrameTimeSlice ( void ) { return m_dwFrameTimeSlice; } + void HandleException ( CExceptionInformation* pExceptionInformation ); static void HandleRadioNext ( CControlFunctionBind* ); static void HandleRadioPrevious ( CControlFunctionBind* ); @@ -290,12 +293,16 @@ class CClientGame void SetAllDimensions ( unsigned short usDimension ); + static void StaticKeyStrokeHandler ( const SBindableKey * pKey, bool bState ); + void KeyStrokeHandler ( const SBindableKey * pKey, bool bState ); + static bool StaticCharacterKeyHandler ( WPARAM wChar ); + bool CharacterKeyHandler ( WPARAM wChar ); + static void StaticProcessClientKeyBind ( CKeyFunctionBind* pBind ); void ProcessClientKeyBind ( CKeyFunctionBind* pBind ); static void StaticProcessClientControlBind ( CControlFunctionBind* pBind ); void ProcessClientControlBind ( CControlFunctionBind* pBind ); - static void StaticProcessServerKeyBind ( CKeyFunctionBind* pBind ); void ProcessServerKeyBind ( CKeyFunctionBind* pBind ); static void StaticProcessServerControlBind ( CControlFunctionBind* pBind ); @@ -334,8 +341,8 @@ class CClientGame inline bool GetHudAreaNameDisabled ( void ) { return m_bHudAreaNameDisabled; }; inline void SetHudAreaNameDisabled ( bool bDisabled ) { m_bHudAreaNameDisabled = bDisabled; }; - bool SetGlitchEnabled ( char cGlitch, bool bEnabled ); - bool IsGlitchEnabled ( char cGlitch ); + bool SetGlitchEnabled ( unsigned char cGlitch, bool bEnabled ); + bool IsGlitchEnabled ( unsigned char cGlitch ); bool SetCloudsEnabled ( bool bEnabled ); bool GetCloudsEnabled ( void ); @@ -344,6 +351,7 @@ class CClientGame void ChangeVehicleWeapon ( bool bNext ); void NotifyBigPacketProgress ( unsigned long ulBytesReceived, unsigned long ulTotalSize ); + bool IsDownloadingBigPacket ( ) const { return m_bReceivingBigPacket; } private: #ifdef MTA_VOICE @@ -413,6 +421,8 @@ class CClientGame static void StaticAddAnimationHandler ( RpClump * pClump, AssocGroupId animGroup, AnimationId animID ); static void StaticBlendAnimationHandler ( RpClump * pClump, AssocGroupId animGroup, AnimationId animID, float fBlendDelta ); static void StaticPreHudDrawHandler ( void ); + static void StaticBlowUpCarHandler ( CVehicle * pGameVehicle, CEntity * pResponsible ); + static bool StaticPedOnFireHandler ( CPed * pGamePed, CFire * pFire, CExplosion * pExplosion ); bool DamageHandler ( CPed* pDamagePed, CEventDamage * pEvent ); void FireHandler ( CFire* pFire ); @@ -426,6 +436,8 @@ class CClientGame void AddAnimationHandler ( RpClump * pClump, AssocGroupId animGroup, AnimationId animID ); void BlendAnimationHandler ( RpClump * pClump, AssocGroupId animGroup, AnimationId animID, float fBlendDelta ); void PreHudDrawHandler ( void ); + void BlowUpCarHandler ( CVehicle * pVehicle, CEntity * pGameResponsible ); + bool PedOnFireHandler ( CPed * pGamePed, CFire * pFire, CExplosion * pExplosion ); static bool StaticProcessMessage ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); bool ProcessMessage ( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); @@ -557,7 +569,7 @@ class CClientGame float m_fGameSpeed; long m_lMoney; - bool m_Glitches[3]; + bool m_Glitches[NUM_GLITCHES]; //Clouds Enabled bool m_bCloudsEnabled; @@ -575,7 +587,8 @@ class CClientGame unsigned long m_ulBigPacketBytesReceivedBase; CTransferBox* m_pBigPacketTransferBox; - double m_dLastTimeSeconds; + DWORD m_dwFrameTimeSlice; // how long it took (in ms) to process the current frame + DWORD m_dwLastFrameTick; // time at which the previous frame was processed #if defined (MTA_DEBUG) || defined (MTA_BETA) bool m_bShowSyncingInfo; diff --git a/MTA10/mods/deathmatch/logic/CDeathmatchObject.cpp b/MTA10/mods/deathmatch/logic/CDeathmatchObject.cpp index d396e86247..05c2cead57 100644 --- a/MTA10/mods/deathmatch/logic/CDeathmatchObject.cpp +++ b/MTA10/mods/deathmatch/logic/CDeathmatchObject.cpp @@ -20,8 +20,6 @@ extern CClientGame * g_pClientGame; CDeathmatchObject::CDeathmatchObject ( CClientManager* pManager, CMovingObjectsManager* pMovingObjectsManager, ElementID ID, unsigned short usModel ) : CClientObject ( pManager, ID, usModel ) { m_pMovingObjectsManager = pMovingObjectsManager; - m_ulStartTime = 0; - m_ulTargetTime = 0; } @@ -33,96 +31,34 @@ CDeathmatchObject::~CDeathmatchObject ( void ) void CDeathmatchObject::StartMovement ( const CVector& vecTargetPosition, const CVector& vecTargetRotation, unsigned long ulTime ) { - // More than 0 ms to move? - if ( ulTime > 0 ) - { - // Set our data - m_ulStartTime = CClientTime::GetTime (); - m_ulTargetTime = m_ulStartTime + ulTime; - GetPosition ( m_vecStartPosition ); - GetRotationRadians ( m_vecStartRotation ); - m_vecTargetPosition = vecTargetPosition; - m_vecTargetRotation = vecTargetRotation; - - // Get the start rotation between 0 and 2*pi - if ( m_vecStartRotation.fX < 0 ) - m_vecStartRotation.fX += 2.0f * PI; - else if ( m_vecStartRotation.fX >= 2*PI ) - m_vecStartRotation.fX -= 2.0f * PI; - - if ( m_vecStartRotation.fY < 0 ) - m_vecStartRotation.fY += 2.0f * PI; - else if ( m_vecStartRotation.fY >= 2*PI ) - m_vecStartRotation.fY -= 2.0f * PI; - - if ( m_vecStartRotation.fZ < 0 ) - m_vecStartRotation.fZ += 2.0f * PI; - else if ( m_vecStartRotation.fZ >= 2*PI ) - m_vecStartRotation.fZ -= 2.0f * PI; - - // Add us to the moving object's manager - m_pMovingObjectsManager->Add ( this ); - } - else - { - SetPosition ( vecTargetPosition ); - SetRotationRadians ( vecTargetRotation ); - } + GetPosition ( m_movePosition ); + GetRotationRadians ( m_moveRotation ); + NormalizeRadian ( m_moveRotation ); + m_movePosition.lerp ( vecTargetPosition, ulTime ); + m_moveRotation.lerp ( m_moveRotation + vecTargetRotation, ulTime ); + + // Add us to the moving object's manager + m_pMovingObjectsManager->Add ( this ); } void CDeathmatchObject::StopMovement ( void ) { - // Prevent it from moving in the future - m_ulStartTime = 0; - m_ulTargetTime = 0; -} - - -void CDeathmatchObject::FinishMovement ( void ) -{ - // Prevent it from moving in the future - m_ulStartTime = 0; - m_ulTargetTime = 0; - - // Set the target position/rotation (ensures accuracy) - SetPosition ( m_vecTargetPosition ); - SetRotationRadians ( m_vecStartRotation + m_vecTargetRotation ); + m_movePosition.finish (); + m_moveRotation.finish (); } void CDeathmatchObject::UpdateMovement ( void ) { - // Got a start and end time? - if ( m_ulStartTime != 0 ) + if ( !m_movePosition.finished () || !m_moveRotation.finished () ) { - // We're past our end time? - unsigned long ulCurrentTime = CClientTime::GetTime (); - if ( ulCurrentTime < m_ulTargetTime ) - { - // Grab the movement duration and the time passed as floats - float fDuration = static_cast < float > ( m_ulTargetTime - m_ulStartTime ); - float fTimePassed = static_cast < float > ( ulCurrentTime - m_ulStartTime ); - - // Grab the delta position and rotation - CVector vecDeltaPosition = m_vecTargetPosition - m_vecStartPosition; - CVector vecRotation = m_vecTargetRotation; - - // Divide it on the duration and multiply with the time passed - vecDeltaPosition /= fDuration; - vecDeltaPosition *= fTimePassed; - vecRotation /= fDuration; - vecRotation *= fTimePassed; + CVector vecPreviousPosition = m_vecPosition; + CVector vecPreviousRotation = m_vecRotation; - CVector vecPosition = m_vecStartPosition + vecDeltaPosition; + CClientObject::SetOrientation ( m_movePosition.update (), m_moveRotation.update () ); - // Plus the position with our new interpolated delta position and set it - SetOrientation ( vecPosition, m_vecStartRotation + vecRotation ); - } - else - { - FinishMovement (); - } + UpdateContactingBegin ( vecPreviousPosition, vecPreviousRotation ); } } @@ -132,6 +68,9 @@ void CDeathmatchObject::UpdateMovement ( void ) // void CDeathmatchObject::SetPosition ( const CVector& vecPosition ) { + // Don't allow if we're still moving + if ( !m_movePosition.finished () ) return; + CVector vecPreviousPosition = m_vecPosition; CVector vecPreviousRotation = m_vecRotation; @@ -148,6 +87,9 @@ void CDeathmatchObject::SetPosition ( const CVector& vecPosition ) // void CDeathmatchObject::SetRotationRadians ( const CVector& vecRotationRadians ) { + // Don't allow if we're still moving + if ( !m_moveRotation.finished () ) return; + CVector vecPreviousPosition = m_vecPosition; CVector vecPreviousRotation = m_vecRotation; @@ -164,6 +106,9 @@ void CDeathmatchObject::SetRotationRadians ( const CVector& vecRotationRadians ) // void CDeathmatchObject::SetOrientation ( const CVector& vecPosition, const CVector& vecRotationRadians ) { + // Don't allow if we're still moving + if ( !m_movePosition.finished () || !m_moveRotation.finished () ) return; + CVector vecPreviousPosition = m_vecPosition; CVector vecPreviousRotation = m_vecRotation; diff --git a/MTA10/mods/deathmatch/logic/CDeathmatchObject.h b/MTA10/mods/deathmatch/logic/CDeathmatchObject.h index 82a8cad853..5f9339e294 100644 --- a/MTA10/mods/deathmatch/logic/CDeathmatchObject.h +++ b/MTA10/mods/deathmatch/logic/CDeathmatchObject.h @@ -30,32 +30,28 @@ class CDeathmatchObject : public CClientObject void SetOrientation ( const CVector& vecPosition, const CVector& vecRotationRadians ); // CDeathmatchObject functions - inline const CVector& GetStartPosition ( void ) { return m_vecStartPosition; }; - inline const CVector& GetStartRotation ( void ) { return m_vecStartRotation; }; - inline const CVector& GetTargetPosition ( void ) { return m_vecTargetPosition; }; - inline const CVector& GetTargetRotation ( void ) { return m_vecTargetRotation; }; - inline void SetTargetRotation ( const CVector& vecRotation ) { m_vecTargetRotation = vecRotation; } - inline unsigned long GetStartTime ( void ) { return m_ulStartTime; }; - inline unsigned long GetTargetTime ( void ) { return m_ulTargetTime; }; + inline const CVector& GetStartPosition ( void ) { return m_movePosition.begin; }; + inline const CVector& GetStartRotation ( void ) { return m_moveRotation.begin; }; + inline const CVector& GetTargetPosition ( void ) { return m_movePosition.end; }; + inline const CVector& GetTargetRotation ( void ) { return m_moveRotation.end; }; + inline void SetTargetRotation ( const CVector& vecRotation ) { m_moveRotation.end = vecRotation; } + inline unsigned long GetStartTime ( void ) { return m_movePosition.beginTime; }; + inline unsigned long GetTargetTime ( void ) { return m_movePosition.endTime; }; void StartMovement ( const CVector& vecTargetPosition, const CVector& vecTargetRotation, unsigned long ulTime ); void StopMovement ( void ); - void FinishMovement ( void ); void UpdateMovement ( void ); + void UpdateContactingBegin ( const CVector& vecPreviousPosition, const CVector& vecPreviousRotation ); void UpdateContacting ( const CVector& vecCenterOfRotation, const CVector& vecFrameTranslation, const CVector& vecFrameRotation ); - inline bool IsMoving ( void ) { return m_ulStartTime != 0; }; + inline bool IsMoving ( void ) { return !m_movePosition.finished (); } protected: class CMovingObjectsManager* m_pMovingObjectsManager; - CVector m_vecStartPosition; - CVector m_vecStartRotation; - CVector m_vecTargetPosition; - CVector m_vecTargetRotation; - unsigned long m_ulStartTime; - unsigned long m_ulTargetTime; + CInterpolatedVar < CVector > m_movePosition; + CInterpolatedVar < CVector > m_moveRotation; }; #endif diff --git a/MTA10/mods/deathmatch/logic/CDeathmatchVehicle.cpp b/MTA10/mods/deathmatch/logic/CDeathmatchVehicle.cpp index d94ed10d85..a285e3cfc2 100644 --- a/MTA10/mods/deathmatch/logic/CDeathmatchVehicle.cpp +++ b/MTA10/mods/deathmatch/logic/CDeathmatchVehicle.cpp @@ -22,6 +22,8 @@ CDeathmatchVehicle::CDeathmatchVehicle ( CClientManager* pManager, CUnoccupiedVe memset ( m_ucLastPanelStates, 0, sizeof ( m_ucLastPanelStates ) ); memset ( m_ucLastLightStates, 0, sizeof ( m_ucLastLightStates ) ); m_bIsSyncing = false; + m_ulSyncFrequency = 0; + m_ulLastSyncTick = 0; SetIsSyncing ( false ); } @@ -133,3 +135,64 @@ void CDeathmatchVehicle::ResetDamageModelSync ( void ) for ( int i = 0; i < MAX_PANELS; i++ ) m_ucLastPanelStates [i] = GetPanelStatus ( i ); for ( int i = 0; i < MAX_LIGHTS; i++ ) m_ucLastLightStates [i] = GetLightStatus ( i ); } + + +void CDeathmatchVehicle::UpdateSyncTimes ( void ) +{ + unsigned long time = GetTickCount (); + m_ulSyncFrequency = time - m_ulLastSyncTick; + m_ulLastSyncTick = time; +} + + +void CDeathmatchVehicle::SetAdjustablePropertyValue ( unsigned short usValue ) +{ + if ( UseInterpolation () ) + { + if ( m_usModel == VT_HYDRA ) usValue = 5000 - usValue; + m_adjustableProperty.lerp ( usValue, m_ulSyncFrequency ); + } + else + { + CClientVehicle::SetAdjustablePropertyValue ( usValue ); + } +} + + +void CDeathmatchVehicle::SetTurretRotation ( float fHorizontal, float fVertical ) +{ + if ( UseInterpolation () ) + { + m_turretX.lerp ( fHorizontal, m_ulSyncFrequency ); + m_turretY.lerp ( fVertical, m_ulSyncFrequency ); + } + else + { + CClientVehicle::SetTurretRotation ( fHorizontal, fVertical ); + } +} + + +bool CDeathmatchVehicle::UseInterpolation ( void ) +{ + // Use smoothing if: It has a driver and it's not local and we're not syncing it or + // It has no driver and we're not syncing it. + if ( ( m_pDriver && !m_pDriver->IsLocalPlayer () && !IsSyncing () ) || + ( !m_pDriver && !IsSyncing () ) ) + { + return true; + } + return false; +} + + +void CDeathmatchVehicle::StreamedInPulse ( void ) +{ + CClientVehicle::StreamedInPulse (); + + if ( UseInterpolation () ) + { + CClientVehicle::_SetAdjustablePropertyValue ( m_adjustableProperty.update () ); + CClientVehicle::SetTurretRotation ( m_turretX.updateRotRad (), m_turretY.updateRotRad () ); + } +} \ No newline at end of file diff --git a/MTA10/mods/deathmatch/logic/CDeathmatchVehicle.h b/MTA10/mods/deathmatch/logic/CDeathmatchVehicle.h index de34cc6069..cdcb010c77 100644 --- a/MTA10/mods/deathmatch/logic/CDeathmatchVehicle.h +++ b/MTA10/mods/deathmatch/logic/CDeathmatchVehicle.h @@ -19,23 +19,39 @@ class CDeathmatchVehicle : public CClientVehicle { public: - CDeathmatchVehicle ( CClientManager* pManager, class CUnoccupiedVehicleSync* pUnoccupiedVehicleSync, ElementID ID, unsigned short usVehicleModel ); - ~CDeathmatchVehicle ( void ); + CDeathmatchVehicle ( CClientManager* pManager, class CUnoccupiedVehicleSync* pUnoccupiedVehicleSync, ElementID ID, unsigned short usVehicleModel ); + ~CDeathmatchVehicle ( void ); - inline bool IsSyncing ( void ) { return m_bIsSyncing; }; - void SetIsSyncing ( bool bIsSyncing ); + inline bool IsSyncing ( void ) { return m_bIsSyncing; }; + void SetIsSyncing ( bool bIsSyncing ); - bool SyncDamageModel ( void ); - void ResetDamageModelSync ( void ); + bool SyncDamageModel ( void ); + void ResetDamageModelSync ( void ); + + void UpdateSyncTimes ( void ); + + // Overloaded + void SetAdjustablePropertyValue ( unsigned short usValue ); + void SetTurretRotation ( float fHorizontal, float fVertical ); + +protected: + bool UseInterpolation ( void ); + void StreamedInPulse ( void ); private: - class CUnoccupiedVehicleSync* m_pUnoccupiedVehicleSync; - bool m_bIsSyncing; + class CUnoccupiedVehicleSync* m_pUnoccupiedVehicleSync; + bool m_bIsSyncing; + + unsigned char m_ucLastDoorStates [MAX_DOORS]; + unsigned char m_ucLastWheelStates [MAX_WHEELS]; + unsigned char m_ucLastPanelStates [MAX_PANELS]; + unsigned char m_ucLastLightStates [MAX_LIGHTS]; + + unsigned long m_ulLastSyncTick; + unsigned long m_ulSyncFrequency; - unsigned char m_ucLastDoorStates [MAX_DOORS]; - unsigned char m_ucLastWheelStates [MAX_WHEELS]; - unsigned char m_ucLastPanelStates [MAX_PANELS]; - unsigned char m_ucLastLightStates [MAX_LIGHTS]; + CInterpolatedVar < unsigned short > m_adjustableProperty; + CInterpolatedVar < float > m_turretX, m_turretY; }; #endif diff --git a/MTA10/mods/deathmatch/logic/CElementDeleter.cpp b/MTA10/mods/deathmatch/logic/CElementDeleter.cpp index f872f5f03c..98e28fb599 100644 --- a/MTA10/mods/deathmatch/logic/CElementDeleter.cpp +++ b/MTA10/mods/deathmatch/logic/CElementDeleter.cpp @@ -52,14 +52,14 @@ void CElementDeleter::DeleteRecursive ( class CClientEntity* pElement ) // Gather a list over children (we can't use the list as it changes) list < CClientEntity* > Children; list < CClientEntity* > ::const_iterator iterCopy = pElement->IterBegin (); - for ( ; iterCopy != pElement->IterEnd (); iterCopy++ ) + for ( ; iterCopy != pElement->IterEnd (); ++iterCopy ) { Children.push_back ( *iterCopy ); } // Call ourselves on each child of this to go as deep as possible and start deleting there list < CClientEntity* > ::const_iterator iter = Children.begin (); - for ( ; iter != Children.end (); iter++ ) + for ( ; iter != Children.end (); ++iter ) { DeleteRecursive ( *iter ); } diff --git a/MTA10/mods/deathmatch/logic/CFoo.cpp b/MTA10/mods/deathmatch/logic/CFoo.cpp index c6767cd4f8..98c110556c 100644 --- a/MTA10/mods/deathmatch/logic/CFoo.cpp +++ b/MTA10/mods/deathmatch/logic/CFoo.cpp @@ -178,7 +178,7 @@ void CFoo::Test ( const char* szString ) CVector vecT; pVehicle->GetPosition ( vecT ); vecT.fZ = fdelta; - pVehicle->SetTargetPosition ( vecT, TICK_RATE ); + pVehicle->SetTargetPosition ( vecT ); g_pCore->ChatPrintf ( "Done %f", false, fdelta ); @@ -197,7 +197,7 @@ void CFoo::Test ( const char* szString ) CVector vecT; pVehicle->GetRotationDegrees ( vecT ); vecT.fZ = atof ( szString + 7 ); - pVehicle->SetTargetRotation ( vecT, TICK_RATE ); + pVehicle->SetTargetRotation ( vecT ); g_pCore->ChatPrintf ( "Done %f", false, atof ( szString + 7 ) ); @@ -429,8 +429,8 @@ void CFoo::Test ( const char* szString ) CClientVehicle* pVehicle = pLocal->GetOccupiedVehicle (); if ( pVehicle ) { - pVehicle->SetTargetPosition ( CVector ( 0, 0, 0 ), TICK_RATE ); - pVehicle->SetTargetRotation ( CVector ( 0, 0, 0 ), TICK_RATE ); + pVehicle->SetTargetPosition ( CVector ( 0, 0, 0 ) ); + pVehicle->SetTargetRotation ( CVector ( 0, 0, 0 ) ); g_pCore->ChatPrintf ( "Done", false ); } diff --git a/MTA10/mods/deathmatch/logic/CInterpolator.cpp b/MTA10/mods/deathmatch/logic/CInterpolator.cpp deleted file mode 100644 index 0b9533a565..0000000000 --- a/MTA10/mods/deathmatch/logic/CInterpolator.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/***************************************************************************** -* -* PROJECT: Multi Theft Auto v1.0 -* LICENSE: See LICENSE in the top level directory -* FILE: mods/deathmatch/logic/CInterpolator.cpp -* PURPOSE: Interpolation calculations -* DEVELOPERS: Kent Simon <> -* Christian Myhre Lundheim <> -* Jax <> -* -* Multi Theft Auto is available from http://www.multitheftauto.com/ -* -*****************************************************************************/ - -#include - -CInterpolator::CInterpolator() -{ - return; -} - -CInterpolator::~CInterpolator() -{ - while ( !m_vecVecList.empty () ) - { - VecMap* map = m_vecVecList.back (); - m_vecVecList.pop_back (); - delete map; - } -} - - -void CInterpolator::Push(float fX, float fY, float fZ, unsigned long ulTimeStamp) -{ - VecMap* map = new VecMap; - map->m_fX = fX; - map->m_fY = fY; - map->m_fZ = fZ; - map->m_ulTimeStamp = ulTimeStamp; - m_vecVecList.insert(m_vecVecList.begin(), map); -} - - -unsigned long CInterpolator::GetOldestEntry(CVector &Vec) -{ - Vec.fX = m_vecVecList.back()->m_fX; - Vec.fY = m_vecVecList.back()->m_fY; - Vec.fZ = m_vecVecList.back()->m_fZ; - return m_vecVecList.back()->m_ulTimeStamp; -} - -bool CInterpolator::Evaluate ( unsigned long ulTime, CVector& vecResult ) -{ - if ( m_vecVecList.empty () ) - return false; - - // Time later than newest point, so use the newest point - if ( ulTime > m_vecVecList[0]->m_ulTimeStamp ) - { - vecResult.fX = m_vecVecList[0]->m_fX; - vecResult.fY = m_vecVecList[0]->m_fY; - vecResult.fZ = m_vecVecList[0]->m_fZ; - return true; - } - - // Find the two points either side and interpolate - for ( unsigned int idx = 1 ; idx < m_vecVecList.size () ; idx++ ) - { - if ( ulTime > m_vecVecList[idx]->m_ulTimeStamp ) - { - return Eval ( *m_vecVecList[idx-1], *m_vecVecList[idx], ulTime, vecResult ); - } - } - - // Time earlier than oldest point, so use the oldest point - vecResult.fX = m_vecVecList.back ()->m_fX; - vecResult.fY = m_vecVecList.back ()->m_fY; - vecResult.fZ = m_vecVecList.back ()->m_fZ; - return true; -} - -// Left should be later than Right -bool CInterpolator::Eval ( const VecMap& Left, const VecMap& Right, unsigned long ulTimeEval, CVector& vecResult ) -{ - // Check for being the same or maybe wrap around - if ( Right.m_ulTimeStamp >= Left.m_ulTimeStamp ) - { - vecResult.fX = Left.m_fX; - vecResult.fY = Left.m_fY; - vecResult.fZ = Left.m_fZ; - return true; - } - - // Find the relative position of ulTimeEval between R.m_ulTimeStamp and L.m_ulTimeStamp - float fAlpha = Unlerp ( Right.m_ulTimeStamp, ulTimeEval, Left.m_ulTimeStamp ); - - // Lerp between Right.pos and Left.pos - vecResult.fX = Lerp ( Right.m_fX, fAlpha, Left.m_fX ); - vecResult.fY = Lerp ( Right.m_fY, fAlpha, Left.m_fY ); - vecResult.fZ = Lerp ( Right.m_fZ, fAlpha, Left.m_fZ ); - return true; -} - - -void CInterpolator::Pop() -{ - if ( !m_vecVecList.empty() ) - { - VecMap* map = m_vecVecList.back (); - m_vecVecList.pop_back(); - delete map; - } -} \ No newline at end of file diff --git a/MTA10/mods/deathmatch/logic/CInterpolator.h b/MTA10/mods/deathmatch/logic/CInterpolator.h index d8f718d723..16d71da0e5 100644 --- a/MTA10/mods/deathmatch/logic/CInterpolator.h +++ b/MTA10/mods/deathmatch/logic/CInterpolator.h @@ -12,37 +12,136 @@ * *****************************************************************************/ -#ifndef __INTERPOLATOR__ -#define __INTERPOLATOR__ +#pragma once -#include #include "Utils.h" -struct VecMap -{ - unsigned long m_ulTimeStamp; - float m_fX,m_fY,m_fZ; -}; - -// the logic may seem backwards in some places, because i'm inserting at the front, so the list is -// reversed to what you'd think, like a stack +template < class T, unsigned int uiMaxElements = 64 > class CInterpolator { +protected: + struct VecMap + { + unsigned long m_ulTime; + T data; + }; + public: + CInterpolator ( ) + { + Clear (); + } + + ~CInterpolator ( ) + { + Clear (); + } + + void Push ( const T& newData, unsigned long ulTime ) + { + unsigned int uiIndex = Index ( m_uiEndIdx + 1 ); + m_nodes [ m_uiEndIdx ].data = newData; + m_nodes [ m_uiEndIdx ].m_ulTime = ulTime; + m_uiEndIdx = uiIndex; + + if ( Size () < uiMaxElements ) + ++m_uiSize; + else + m_uiStartIdx = Index ( m_uiStartIdx + 1 ); + } + + void Pop ( ) + { + if ( Size () > 0 ) + { + m_uiStartIdx = Index ( m_uiStartIdx + 1 ); + --m_uiSize; + } + } + + bool Evaluate ( unsigned long ulTime, T* output ) + { + if ( Size () == 0 ) + return false; - CInterpolator( void ); - ~CInterpolator( void ); + // Time later than newest point, so use the newest point + if ( ulTime >= m_nodes [ Index ( m_uiEndIdx - 1 ) ].m_ulTime ) + { + *output = m_nodes [ Index ( m_uiEndIdx - 1 ) ].data; + } + // Time earlier than oldest point, so use the oldest point + else if ( ulTime <= m_nodes [ m_uiStartIdx ].m_ulTime ) + { + *output = m_nodes [ m_uiStartIdx ].data; + } + else + { + // Find the two points either side and interpolate + unsigned int uiCurrent = Index ( m_uiStartIdx + 1 ); + for ( ; uiCurrent != m_uiEndIdx; uiCurrent = Index ( uiCurrent + 1 ) ) + { + if ( ulTime < m_nodes [ uiCurrent ].m_ulTime ) + return Eval ( m_nodes [ Index ( uiCurrent - 1 ) ], m_nodes [ uiCurrent ], ulTime, output ); + } + } - void Push( float fX, float fY, float fZ, unsigned long ulTimeStamp ); - bool Evaluate( unsigned long ulTime, CVector &Vec ); - void Pop(); - unsigned long GetOldestEntry(CVector &Vec); + return true; + } + + unsigned long GetOldestEntry ( T* output ) + { + if ( Size () > 0 ) + { + *output = m_nodes [ m_uiStartIdx ].data; + return m_nodes [ m_uiStartIdx ].m_ulTime; + } + else + return 0UL; + } + + unsigned int Size ( ) const + { + return m_uiSize; + } + + void Clear ( ) + { + m_uiStartIdx = 0; + m_uiEndIdx = 0; + m_uiSize = 0; + } + +protected: + virtual bool Eval ( const VecMap& Left, + const VecMap& Right, + unsigned long ulTimeEval, + T* output ) + { + // Check for being the same or maybe wrap around + if ( Left.m_ulTime >= Right.m_ulTime ) + { + *output = Right.data; + return true; + } + + // Find the relative position of ulTimeEval between R.m_ulTimeStamp and L.m_ulTimeStamp + float fAlpha = Unlerp ( Left.m_ulTime, ulTimeEval, Right.m_ulTime ); + + // Lerp between Right.pos and Left.pos + *output = Lerp ( Left.data, fAlpha, Right.data ); + return true; + } private: + unsigned int Index ( unsigned int uiIndex ) const + { + return ( uiIndex % uiMaxElements ); + } - std::vector m_vecVecList; - bool Eval ( const VecMap& Left, const VecMap& Right, unsigned long ulTimeEval, CVector& vecResult ); +private: + VecMap m_nodes [ uiMaxElements ]; + unsigned int m_uiStartIdx; + unsigned int m_uiEndIdx; + unsigned int m_uiSize; }; - -#endif \ No newline at end of file diff --git a/MTA10/mods/deathmatch/logic/CMovingObjectsManager.h b/MTA10/mods/deathmatch/logic/CMovingObjectsManager.h index 3117974c2b..95d2e7909e 100644 --- a/MTA10/mods/deathmatch/logic/CMovingObjectsManager.h +++ b/MTA10/mods/deathmatch/logic/CMovingObjectsManager.h @@ -21,7 +21,7 @@ class CMovingObjectsManager { public: - inline void Add ( CDeathmatchObject* pObject ) { m_List.push_back ( pObject ); }; + inline void Add ( CDeathmatchObject* pObject ) { if ( !ListContains ( m_List, pObject ) ) m_List.push_back ( pObject ); }; inline void Remove ( CDeathmatchObject* pObject ) { if ( !m_List.empty() ) m_List.remove ( pObject ); }; void DoPulse ( void ); diff --git a/MTA10/mods/deathmatch/logic/CNetAPI.cpp b/MTA10/mods/deathmatch/logic/CNetAPI.cpp index 404fdafca2..a6cf484da6 100644 --- a/MTA10/mods/deathmatch/logic/CNetAPI.cpp +++ b/MTA10/mods/deathmatch/logic/CNetAPI.cpp @@ -204,19 +204,14 @@ void CNetAPI::AddInterpolation ( const CVector& vecPosition ) { // Store our current position for interpolation purposes unsigned long ulCurrentTime = CClientTime::GetTime (); - m_Interpolator.Push ( vecPosition.fX, vecPosition.fY, vecPosition.fZ, ulCurrentTime ); - CVector vecTemp; - while ( m_Interpolator.GetOldestEntry ( vecTemp ) < ulCurrentTime - 2500 ) - { - m_Interpolator.Pop (); - } + m_Interpolator.Push ( vecPosition, ulCurrentTime ); } bool CNetAPI::GetInterpolation ( CVector& vecPosition, unsigned short usLatency ) { unsigned long ulInterTime = CClientTime::GetTime () - usLatency; - return m_Interpolator.Evaluate ( ulInterTime, vecPosition ); + return m_Interpolator.Evaluate ( ulInterTime, &vecPosition ); } @@ -253,7 +248,7 @@ void CNetAPI::DoPulse ( void ) m_pManager->GetPacketRecorder ()->RecordLocalData ( pPlayer ); // We should do a puresync? - if ( IsPureSyncNeeded () ) + if ( IsPureSyncNeeded () && !g_pClientGame->IsDownloadingBigPacket () ) { // Are in a vehicle? if ( pVehicle ) @@ -298,7 +293,7 @@ void CNetAPI::DoPulse ( void ) else { // We should do a keysync? - if ( IsSmallKeySyncNeeded ( pPlayer ) ) + if ( IsSmallKeySyncNeeded ( pPlayer ) && !g_pClientGame->IsDownloadingBigPacket () ) { // Send a keysync packet NetBitStreamInterface* pBitStream = g_pNet->AllocateNetBitStream (); @@ -315,7 +310,8 @@ void CNetAPI::DoPulse ( void ) } // Time to freeze because of lack of return sync? - if ( ( m_bStoredReturnSync ) && + if ( !g_pClientGame->IsDownloadingBigPacket () && + ( m_bStoredReturnSync ) && ( m_ulLastPuresyncTime != 0 ) && ( m_ulLastSyncReturnTime != 0 ) && ( ulCurrentTime <= m_ulLastPuresyncTime + 5000 ) && @@ -350,7 +346,9 @@ void CNetAPI::DoPulse ( void ) } // Display network trouble - m_pManager->GetDisplayManager ()->DrawText2D ( "*** NETWORK TROUBLE ***", CVector ( 0.30f, 0.45f, 0 ), 2.0f, 0xFFFF0000 ); + int iPosX = g_pCore->GetGraphics ()->GetViewportWidth () / 2; // Half way across + int iPosY = g_pCore->GetGraphics ()->GetViewportHeight () * 45 / 100; // 45/100 down + g_pCore->GetGraphics ()->DrawText ( iPosX, iPosY, iPosX, iPosY, COLOR_ARGB ( 255, 255, 0, 0 ), "*** NETWORK TROUBLE ***", 2.0f, 2.0f, DT_NOCLIP | DT_CENTER ); } } @@ -808,6 +806,7 @@ void CNetAPI::ReadPlayerPuresync ( CClientPlayer* pPlayer, NetBitStreamInterface if ( CWeaponNames::DoesSlotHaveAmmo ( uiSlot ) ) { + unsigned char ucCurrentWeapon = 0; float fWeaponRange = 0.01f; if ( pWeapon ) @@ -878,8 +877,8 @@ void CNetAPI::ReadPlayerPuresync ( CClientPlayer* pPlayer, NetBitStreamInterface pPlayer->GetVehicleInOutState () == VEHICLE_INOUT_GETTING_IN || pPlayer->GetVehicleInOutState () == VEHICLE_INOUT_JACKING ) { - pPlayer->SetTargetPosition ( position.data.vecPosition, TICK_RATE, pContactEntity ); - pPlayer->SetCurrentRotation ( rotation.data.fRotation ); + pPlayer->SetTargetPosition ( position.data.vecPosition, pContactEntity ); + pPlayer->SetTargetRotation ( rotation.data.fRotation ); } // Set move speed, controller state and camera rotation + duck state @@ -1061,6 +1060,7 @@ void CNetAPI::ReadVehiclePuresync ( CClientPlayer* pPlayer, CClientVehicle* pVeh unsigned short usLatency; BitStream.ReadCompressed ( usLatency ); pPlayer->SetLatency ( usLatency + g_pNet->GetPing () ); + static_cast < CDeathmatchVehicle * > ( pVehicle )->UpdateSyncTimes (); pPlayer->SetPing ( usLatency ); // Read out the keysync @@ -1072,6 +1072,7 @@ void CNetAPI::ReadVehiclePuresync ( CClientPlayer* pPlayer, CClientVehicle* pVeh { ControllerState.ButtonCircle = 0; } + pPlayer->SetControllerState ( ControllerState ); // Grab the vehicle seat the player is in. Only read out vehicle position stuff if he's the driver. unsigned int uiSeat = pPlayer->GetOccupiedVehicleSeat (); @@ -1107,8 +1108,8 @@ void CNetAPI::ReadVehiclePuresync ( CClientPlayer* pPlayer, CClientVehicle* pVeh pVehicle->SetHealth ( health.data.fValue ); // Set the target position and rotation - pVehicle->SetTargetPosition ( position.data.vecPosition, TICK_RATE ); - pVehicle->SetTargetRotation ( rotation.data.vecRotation, TICK_RATE ); + pVehicle->SetTargetPosition ( position.data.vecPosition ); + pVehicle->SetTargetRotation ( rotation.data.vecRotation ); // Apply the correct move and turnspeed pVehicle->SetMoveSpeed ( velocity.data.vecVelocity ); @@ -1229,7 +1230,6 @@ void CNetAPI::ReadVehiclePuresync ( CClientPlayer* pPlayer, CClientVehicle* pVeh pPlayer->SetCurrentWeaponSlot ( WEAPONSLOT_TYPE_UNARMED ); } - // Read out vehicle specific data if he's the driver if ( uiSeat == 0 ) { @@ -1638,7 +1638,7 @@ void CNetAPI::RPC ( eServerRPCFunctions ID, NetBitStreamInterface * pBitStream, pBitStream->ResetReadPointer (); } - g_pNet->SendPacket ( PACKET_ID_RPC, pRPCBitStream, PACKET_PRIORITY_LOW, PACKET_RELIABILITY_RELIABLE_ORDERED, packetOrdering ); + g_pNet->SendPacket ( PACKET_ID_RPC, pRPCBitStream, PACKET_PRIORITY_MEDIUM, PACKET_RELIABILITY_RELIABLE_ORDERED, packetOrdering ); g_pNet->DeallocateNetBitStream ( pRPCBitStream ); } } \ No newline at end of file diff --git a/MTA10/mods/deathmatch/logic/CNetAPI.h b/MTA10/mods/deathmatch/logic/CNetAPI.h index a2aba69289..426bb078a0 100644 --- a/MTA10/mods/deathmatch/logic/CNetAPI.h +++ b/MTA10/mods/deathmatch/logic/CNetAPI.h @@ -100,12 +100,13 @@ class CNetAPI CVector m_vecLastSentCameraPosition; CVector m_vecLastSentCameraLookAt; - CInterpolator m_Interpolator; + CInterpolator m_Interpolator; }; enum eServerRPCFunctions { PLAYER_INGAME_NOTICE, + INITIAL_DATA_STREAM, PLAYER_TARGET, PLAYER_WEAPON, KEY_BIND, diff --git a/MTA10/mods/deathmatch/logic/CPacketHandler.cpp b/MTA10/mods/deathmatch/logic/CPacketHandler.cpp index 31016a0008..edb410da81 100644 --- a/MTA10/mods/deathmatch/logic/CPacketHandler.cpp +++ b/MTA10/mods/deathmatch/logic/CPacketHandler.cpp @@ -382,6 +382,9 @@ void CPacketHandler::Packet_ServerJoined ( NetBitStreamInterface& bitStream ) // We're now joined g_pClientGame->m_Status = CClientGame::STATUS_JOINED; + // Request the on join stuff + g_pClientGame->GetNetAPI ()->RPC ( INITIAL_DATA_STREAM ); + // Call the onClientPlayerJoin event for ourselves CLuaArguments Arguments; g_pClientGame->m_pLocalPlayer->CallEvent ( "onClientPlayerJoin", Arguments, true ); @@ -1926,9 +1929,10 @@ void CPacketHandler::Packet_MapInfo ( NetBitStreamInterface& bitStream ) SFunBugsStateSync funBugs; if ( !bitStream.Read ( &funBugs ) ) return; - g_pClientGame->m_Glitches [ CClientGame::GLITCH_QUICKRELOAD ] = funBugs.data.bQuickReload; - g_pClientGame->m_Glitches [ CClientGame::GLITCH_FASTFIRE ] = funBugs.data.bFastFire; - g_pClientGame->m_Glitches [ CClientGame::GLITCH_FASTMOVE ] = funBugs.data.bFastMove; + + g_pClientGame->SetGlitchEnabled ( CClientGame::GLITCH_QUICKRELOAD, funBugs.data.bQuickReload ); + g_pClientGame->SetGlitchEnabled ( CClientGame::GLITCH_FASTFIRE, funBugs.data.bFastFire ); + g_pClientGame->SetGlitchEnabled ( CClientGame::GLITCH_FASTMOVE, funBugs.data.bFastMove ); } @@ -2257,12 +2261,16 @@ void CPacketHandler::Packet_EntityAdd ( NetBitStreamInterface& bitStream ) if ( bitStream.ReadBit ( bIsMoving ) && bIsMoving ) { unsigned long ulMoveTimeLeft; + // Needs to be CVector as we can have a value of over 2xPI here (for multiple rotations) + CVector vecRotationRadians; if ( bitStream.ReadCompressed ( ulMoveTimeLeft ) && bitStream.Read ( &position ) && - bitStream.Read ( &rotationRadians ) ) + bitStream.Read ( vecRotationRadians.fX ) && + bitStream.Read ( vecRotationRadians.fY ) && + bitStream.Read ( vecRotationRadians.fZ ) ) { pObject->StartMovement ( position.data.vecPosition, - rotationRadians.data.vecRotation, + vecRotationRadians, ulMoveTimeLeft ); } } @@ -3638,6 +3646,13 @@ void CPacketHandler::Packet_ExplosionSync ( NetBitStreamInterface& bitStream ) bCancelExplosion = !g_pClientGame->GetRootEntity ()->CallEvent ( "onClientExplosion", Arguments, false ); } + // Do our tank firing effect? (disabled through the fire key in CNetAPI) + if ( pCreator && !pCreator->IsLocalPlayer () && Type == EXP_TYPE_TANK_GRENADE ) + { + CClientVehicle * pVehicle = pCreator->GetOccupiedVehicle (); + if ( pVehicle ) pVehicle->DoTankFire (); + } + // Is it a vehicle explosion? if ( pOrigin && pOrigin->GetType () == CCLIENTVEHICLE ) { @@ -3650,7 +3665,7 @@ void CPacketHandler::Packet_ExplosionSync ( NetBitStreamInterface& bitStream ) { // Make sure the vehicle's blown CClientVehicle * pExplodingVehicle = static_cast < CClientVehicle * > ( pOrigin ); - pExplodingVehicle->Blow ( false ); + if ( !pExplodingVehicle->IsBlown () ) pExplodingVehicle->Blow ( false ); if ( !bCancelExplosion ) g_pClientGame->m_pManager->GetExplosionManager ()->Create ( EXP_TYPE_GRENADE, position.data.vecPosition, pCreator, true, -1.0f, false, WEAPONTYPE_EXPLOSION ); break; diff --git a/MTA10/mods/deathmatch/logic/CScriptKeyBinds.cpp b/MTA10/mods/deathmatch/logic/CScriptKeyBinds.cpp index 7e8da0fc62..4916370133 100644 --- a/MTA10/mods/deathmatch/logic/CScriptKeyBinds.cpp +++ b/MTA10/mods/deathmatch/logic/CScriptKeyBinds.cpp @@ -179,7 +179,7 @@ bool CScriptKeyBinds::ProcessKey ( const char* szKey, bool bHitState, eScriptKey CScriptKeyBind * pKeyBind = NULL; list < CScriptKeyBind* > cloneList = m_List; list < CScriptKeyBind* > ::iterator iter = cloneList.begin (); - for ( ; iter != cloneList.end () ; iter++ ) + for ( ; iter != cloneList.end () ; ++iter ) { pKeyBind = *iter; if ( !pKeyBind->IsBeingDeleted () && pKeyBind->GetType () == bindType ) @@ -332,7 +332,7 @@ bool CScriptKeyBinds::KeyFunctionExists ( SScriptBindableKey* pKey, CLuaMain* pL bool bFound = false; list < CScriptKeyBind* > cloneList = m_List; list < CScriptKeyBind* > ::iterator iter = cloneList.begin (); - for ( ; iter != cloneList.end () ; iter++ ) + for ( ; iter != cloneList.end () ; ++iter ) { if ( !(*iter)->IsBeingDeleted () && (*iter)->GetType () == SCRIPT_KEY_BIND_FUNCTION ) { @@ -375,7 +375,7 @@ void CScriptKeyBinds::RemoveAllKeys ( CLuaMain* pLuaMain ) continue; } } - iter++; + ++iter; } } @@ -468,7 +468,7 @@ bool CScriptKeyBinds::RemoveControlFunction ( SScriptBindableGTAControl* pContro } } } - iter++; + ++iter; } return bFound; } @@ -490,7 +490,7 @@ bool CScriptKeyBinds::ControlFunctionExists ( SScriptBindableGTAControl* pContro bool bFound = false; list < CScriptKeyBind* > cloneList = m_List; list < CScriptKeyBind* > ::iterator iter = cloneList.begin (); - for ( ; iter != cloneList.end () ;iter++ ) + for ( ; iter != cloneList.end () ; ++iter ) { if ( !(*iter)->IsBeingDeleted () && (*iter)->GetType () == SCRIPT_KEY_BIND_CONTROL_FUNCTION ) { diff --git a/MTA10/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/MTA10/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index 0c88bc8c56..e5125ae0ca 100644 --- a/MTA10/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/MTA10/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -1295,12 +1295,23 @@ bool CStaticFunctionDefinitions::GetPedCameraRotation ( CClientPed & Ped, float return true; } +bool CStaticFunctionDefinitions::GetPedWeaponMuzzlePosition ( CClientPed& Ped, CVector& vecPosition ) +{ + return Ped.GetShotData ( NULL, NULL, &vecPosition ); +} + bool CStaticFunctionDefinitions::IsPedOnFire ( CClientPed & Ped, bool & bOnFire ) { bOnFire = Ped.IsOnFire (); return true; } +bool CStaticFunctionDefinitions::IsPedInVehicle ( CClientPed & Ped, bool & bInVehicle ) +{ + bInVehicle = ( Ped.GetRealOccupiedVehicle () != NULL ); + return true; +} + char* CStaticFunctionDefinitions::GetPedSimplestTask ( CClientPed& Ped ) { CTaskManager* pTaskManager = Ped.GetTaskManager (); diff --git a/MTA10/mods/deathmatch/logic/CStaticFunctionDefinitions.h b/MTA10/mods/deathmatch/logic/CStaticFunctionDefinitions.h index c02d7dfa22..760f4e6761 100644 --- a/MTA10/mods/deathmatch/logic/CStaticFunctionDefinitions.h +++ b/MTA10/mods/deathmatch/logic/CStaticFunctionDefinitions.h @@ -127,7 +127,9 @@ class CStaticFunctionDefinitions static bool IsPedHeadless ( CClientPed& Ped, bool & bHeadless ); static bool IsPedFrozen ( CClientPed& Ped, bool & bFrozen ); static bool GetPedCameraRotation ( CClientPed& Ped, float & fRotation ); + static bool GetPedWeaponMuzzlePosition ( CClientPed& Ped, CVector& vecPosition ); static bool IsPedOnFire ( CClientPed& Ped, bool & bOnFire ); + static bool IsPedInVehicle ( CClientPed& Ped, bool & bInVehicle ); static bool SetPedWeaponSlot ( CClientEntity& Entity, int iSlot ); static bool SetPedRotation ( CClientEntity& Entity, float fRotation ); @@ -349,7 +351,7 @@ class CStaticFunctionDefinitions static inline void GUIGridListAutoSizeColumn ( CClientGUIElement& GUIElement, unsigned int uiColumn ) { static_cast < CGUIGridList* > ( GUIElement.GetCGUIElement () ) -> AutoSizeColumn ( uiColumn ); }; static void GUIGridListClear ( CClientEntity& Element ); static inline void GUIGridListSetItemText ( CClientGUIElement& GUIElement, int iRow, int iColumn, const char *szText, bool bSection, bool bNumber ) { static_cast < CGUIGridList* > ( GUIElement.GetCGUIElement () ) -> SetItemText ( iRow, iColumn, szText, bNumber, bSection ); }; - static inline void GUIGridListSetItemData ( CClientGUIElement& GUIElement, int iRow, int iColumn, const char *szData ) { static_cast < CGUIGridList* > ( GUIElement.GetCGUIElement () ) -> SetItemData ( iRow, iColumn, (void*) szData ); }; + static inline void GUIGridListSetItemData ( CClientGUIElement& GUIElement, int iRow, int iColumn, const char *szData ) { static_cast < CGUIGridList* > ( GUIElement.GetCGUIElement () ) -> SetItemData ( iRow, iColumn, szData ); }; static void GUIGridListSetSelectionMode ( CClientEntity& Element, unsigned int uiMode ); static inline void GUIGridListSetSelectedItem ( CClientGUIElement& GUIElement, int iRow, int iColumn, bool bReset ) { static_cast < CGUIGridList* > ( GUIElement.GetCGUIElement () ) -> SetSelectedItem ( iRow, iColumn, bReset ); }; diff --git a/MTA10/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp b/MTA10/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp index 8ab572ddcc..6361de6e72 100644 --- a/MTA10/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp +++ b/MTA10/mods/deathmatch/logic/CUnoccupiedVehicleSync.cpp @@ -128,6 +128,7 @@ void CUnoccupiedVehicleSync::Packet_UnoccupiedVehicleStartSync ( NetBitStreamInt CDeathmatchVehicle* pVehicle = static_cast < CDeathmatchVehicle* > ( m_pVehicleManager->Get ( ID ) ); if ( pVehicle ) { + pVehicle->UpdateSyncTimes (); // Read out and set its current state, so we start off sync'd with the server // Read out the position @@ -158,8 +159,8 @@ void CUnoccupiedVehicleSync::Packet_UnoccupiedVehicleStartSync ( NetBitStreamInt BitStream.Read ( fHealth ); // Set data for interpolation - pVehicle->SetTargetPosition ( vecPosition, TICK_RATE, false ); - pVehicle->SetTargetRotation ( vecRotationDegrees, TICK_RATE, false ); + pVehicle->SetTargetPosition ( vecPosition ); + pVehicle->SetTargetRotation ( vecRotationDegrees ); pVehicle->SetMoveSpeed ( vecMoveSpeed ); pVehicle->SetTurnSpeed ( vecTurnSpeed ); @@ -207,8 +208,8 @@ void CUnoccupiedVehicleSync::Packet_UnoccupiedVehicleSync ( NetBitStreamInterfac CClientVehicle* pVehicle = m_pVehicleManager->Get ( vehicle.data.vehicleID ); if ( pVehicle && pVehicle->CanUpdateSync ( vehicle.data.ucTimeContext ) ) { - if ( vehicle.data.bSyncPosition ) pVehicle->SetTargetPosition ( vehicle.data.vecPosition, TICK_RATE, false ); - if ( vehicle.data.bSyncRotation ) pVehicle->SetTargetRotation ( vehicle.data.vecRotation, TICK_RATE, false ); + if ( vehicle.data.bSyncPosition ) pVehicle->SetTargetPosition ( vehicle.data.vecPosition ); + if ( vehicle.data.bSyncRotation ) pVehicle->SetTargetRotation ( vehicle.data.vecRotation ); if ( vehicle.data.bSyncVelocity ) pVehicle->SetMoveSpeed ( vehicle.data.vecVelocity ); if ( vehicle.data.bSyncTurnVelocity ) pVehicle->SetTurnSpeed ( vehicle.data.vecTurnVelocity ); if ( vehicle.data.bSyncHealth ) pVehicle->SetHealth ( vehicle.data.fHealth ); diff --git a/MTA10/mods/deathmatch/logic/rpc/CWorldRPCs.cpp b/MTA10/mods/deathmatch/logic/rpc/CWorldRPCs.cpp index 2d6386309d..757df21e1a 100644 --- a/MTA10/mods/deathmatch/logic/rpc/CWorldRPCs.cpp +++ b/MTA10/mods/deathmatch/logic/rpc/CWorldRPCs.cpp @@ -204,7 +204,7 @@ void CWorldRPCs::SetGarageOpen ( NetBitStreamInterface& bitStream ) void CWorldRPCs::SetGlitchEnabled ( NetBitStreamInterface& bitStream ) { - char eGlitch; + unsigned char eGlitch; unsigned char ucIsEnabled; bitStream.Read ( eGlitch ); bitStream.Read ( ucIsEnabled ); diff --git a/MTA10/mods/shared_logic/CClientColManager.cpp b/MTA10/mods/shared_logic/CClientColManager.cpp index 29955259c5..629bbafd41 100644 --- a/MTA10/mods/shared_logic/CClientColManager.cpp +++ b/MTA10/mods/shared_logic/CClientColManager.cpp @@ -23,7 +23,7 @@ CClientColManager::~CClientColManager ( void ) void CClientColManager::DoPulse ( void ) { list < CClientColShape* > ::const_iterator iter = m_List.begin (); - for ( ; iter != m_List.end (); iter++ ) (*iter)->DoPulse (); + for ( ; iter != m_List.end (); ++iter ) (*iter)->DoPulse (); } @@ -33,7 +33,7 @@ void CClientColManager::DoHitDetection ( const CVector& vecNowPosition, float fR // Call the hit detection event on all our shapes list < CClientColShape * > cloneList = m_List; list < CClientColShape* > ::const_iterator iter = cloneList.begin (); - for ( ; iter != cloneList.end (); iter++ ) + for ( ; iter != cloneList.end (); ++iter ) { pShape = *iter; @@ -102,7 +102,7 @@ bool CClientColManager::Exists ( CClientColShape* pShape ) // Return true if it exists list < CClientColShape * > cloneList = m_List; list < CClientColShape* > ::const_iterator iter = cloneList.begin (); - for ( ; iter != cloneList.end (); iter++ ) + for ( ; iter != cloneList.end (); ++iter ) { if ( *iter == pShape ) { @@ -119,7 +119,7 @@ void CClientColManager::DeleteAll ( void ) // Delete all of them list < CClientColShape * > cloneList = m_List; list < CClientColShape* > ::const_iterator iter = cloneList.begin (); - for ( ; iter != cloneList.end (); iter++ ) + for ( ; iter != cloneList.end (); ++iter ) { delete *iter; } diff --git a/MTA10/mods/shared_logic/CClientEntity.cpp b/MTA10/mods/shared_logic/CClientEntity.cpp index 9a1895e4e7..94b5435353 100644 --- a/MTA10/mods/shared_logic/CClientEntity.cpp +++ b/MTA10/mods/shared_logic/CClientEntity.cpp @@ -11,6 +11,7 @@ * Jax <> * Kevin Whiteside * Stanislav Bobrov +* Alberto Alonso * *****************************************************************************/ @@ -56,6 +57,7 @@ CClientEntity::CClientEntity ( ElementID ID ) strncpy ( m_szTypeName, "unknown", MAX_TYPENAME_LENGTH ); m_szTypeName [MAX_TYPENAME_LENGTH] = 0; m_uiTypeHash = HashString ( m_szTypeName ); + CClientEntity::AddEntityFromRoot ( m_uiTypeHash, this ); m_szName [0] = 0; m_szName [MAX_ELEMENT_NAME_LENGTH] = 0; @@ -156,10 +158,9 @@ CClientEntity::~CClientEntity ( void ) for ( ; iterUsers != m_OriginSourceUsers.end () ; iterUsers++ ) { CClientPed* pModel = *iterUsers; - if ( pModel->m_interp.pTargetOriginSource == this ) + if ( pModel->m_pTargetOriginSource == this ) { - pModel->m_interp.pTargetOriginSource = NULL; - pModel->m_interp.bHadOriginSource = true; + pModel->m_pTargetOriginSource = NULL; } } m_OriginSourceUsers.clear (); @@ -176,13 +177,17 @@ CClientEntity::~CClientEntity ( void ) } } m_Contacts.clear (); + + CClientEntity::RemoveEntityFromRoot ( m_uiTypeHash, this ); } void CClientEntity::SetTypeName ( const char* szName ) { + CClientEntity::RemoveEntityFromRoot ( m_uiTypeHash, this ); strncpy ( m_szTypeName, szName, MAX_TYPENAME_LENGTH ); m_uiTypeHash = HashString ( szName ); + CClientEntity::AddEntityFromRoot ( m_uiTypeHash, this ); } @@ -201,16 +206,7 @@ CClientEntity* CClientEntity::SetParent ( CClientEntity* pParent ) // Remove us from previous parent's children list if ( m_pParent ) { - // Check to see if the parent is being deleted ... if so, don't bother updating them - if ( !g_pClientGame->GetElementDeleter ()->IsBeingDeleted ( m_pParent ) ) - { - // Does our parent have any children? (I hope so, or that would make this an orphan) - if ( !m_pParent->m_Children.empty () ) - { - // Jax: whats wrong with std::list::remove, instead of the above? - m_pParent->m_Children.remove ( this ); - } - } + m_pParent->m_Children.remove ( this ); } // Set the new parent @@ -938,7 +934,15 @@ void CClientEntity::FindAllChildrenByType ( const char* szType, CLuaMain* pLuaMa // Add all children of the given type to the table unsigned int uiIndex = 0; unsigned int uiTypeHash = HashString ( szType ); - FindAllChildrenByTypeIndex ( uiTypeHash, pLuaMain, uiIndex, bStreamedIn ); + + if ( this == g_pClientGame->GetRootEntity () ) + { + GetEntitiesFromRoot ( uiTypeHash, pLuaMain, bStreamedIn ); + } + else + { + FindAllChildrenByTypeIndex ( uiTypeHash, pLuaMain, uiIndex, bStreamedIn ); + } } @@ -1233,4 +1237,66 @@ RpClump * CClientEntity::GetClump ( void ) return pEntity->GetRpClump (); } return NULL; -} \ No newline at end of file +} + + +// Entities from root optimization for getElementsByType +CClientEntity::t_mapEntitiesFromRoot CClientEntity::ms_mapEntitiesFromRoot; +bool CClientEntity::ms_bEntitiesFromRootInitialized = false; + +void CClientEntity::StartupEntitiesFromRoot () +{ + if ( !ms_bEntitiesFromRootInitialized ) + { + ms_mapEntitiesFromRoot.set_deleted_key ( (unsigned int)0x00000000 ); + ms_mapEntitiesFromRoot.set_empty_key ( (unsigned int)0xFFFFFFFF ); + ms_bEntitiesFromRootInitialized = true; + } +} + +void CClientEntity::AddEntityFromRoot ( unsigned int uiTypeHash, CClientEntity* pEntity ) +{ + std::list < CClientEntity* >& listEntities = ms_mapEntitiesFromRoot [ uiTypeHash ]; + listEntities.push_front ( pEntity ); +} + +void CClientEntity::RemoveEntityFromRoot ( unsigned int uiTypeHash, CClientEntity* pEntity ) +{ + t_mapEntitiesFromRoot::iterator find = ms_mapEntitiesFromRoot.find ( uiTypeHash ); + if ( find != ms_mapEntitiesFromRoot.end () ) + { + std::list < CClientEntity* >& listEntities = find->second; + listEntities.remove ( pEntity ); + if ( listEntities.size () == 0 ) + ms_mapEntitiesFromRoot.erase ( find ); + } +} + +void CClientEntity::GetEntitiesFromRoot ( unsigned int uiTypeHash, CLuaMain* pLuaMain, bool bStreamedIn ) +{ + t_mapEntitiesFromRoot::iterator find = ms_mapEntitiesFromRoot.find ( uiTypeHash ); + if ( find != ms_mapEntitiesFromRoot.end () ) + { + std::list < CClientEntity* >& listEntities = find->second; + CClientEntity* pEntity; + lua_State* luaVM = pLuaMain->GetVirtualMachine (); + unsigned int uiIndex = 0; + + for ( std::list < CClientEntity* >::const_reverse_iterator i = listEntities.rbegin (); + i != listEntities.rend (); + ++i ) + { + pEntity = *i; + + // Only streamed in elements? + if ( !bStreamedIn || !pEntity->IsStreamingCompatibleClass() || + reinterpret_cast < CClientStreamElement* > ( pEntity )->IsStreamedIn() ) + { + // Add it to the table + lua_pushnumber ( luaVM, ++uiIndex ); + lua_pushelement ( luaVM, pEntity ); + lua_settable ( luaVM, -3 ); + } + } + } +} diff --git a/MTA10/mods/shared_logic/CClientEntity.h b/MTA10/mods/shared_logic/CClientEntity.h index 9a90054ddf..46f0ec0714 100644 --- a/MTA10/mods/shared_logic/CClientEntity.h +++ b/MTA10/mods/shared_logic/CClientEntity.h @@ -24,6 +24,7 @@ class CClientEntity; #include "CClientCommon.h" #include #include +#include class CClientManager; @@ -269,6 +270,18 @@ class CClientEntity private: static int iCount; + + // Optimization for getElementsByType starting at root +public: + static void StartupEntitiesFromRoot ( ); +private: + static void AddEntityFromRoot ( unsigned int uiTypeHash, CClientEntity* pEntity ); + static void RemoveEntityFromRoot ( unsigned int uiTypeHash, CClientEntity* pEntity ); + static void GetEntitiesFromRoot ( unsigned int uiTypeHash, CLuaMain* pLuaMain, bool bStreamedIn ); + + typedef google::dense_hash_map < unsigned int, std::list < CClientEntity* > > t_mapEntitiesFromRoot; + static t_mapEntitiesFromRoot ms_mapEntitiesFromRoot; + static bool ms_bEntitiesFromRootInitialized; }; #endif diff --git a/MTA10/mods/shared_logic/CClientExplosionManager.cpp b/MTA10/mods/shared_logic/CClientExplosionManager.cpp index 97fbb7944b..8b0fb59212 100644 --- a/MTA10/mods/shared_logic/CClientExplosionManager.cpp +++ b/MTA10/mods/shared_logic/CClientExplosionManager.cpp @@ -21,6 +21,7 @@ CClientExplosionManager::CClientExplosionManager ( CClientManager * pManager ) m_pManager = pManager; m_LastWeaponType = WEAPONTYPE_UNARMED; m_pLastCreator = NULL; + m_bCreatingExplosion = false; } @@ -140,6 +141,8 @@ CExplosion * CClientExplosionManager::Create ( eExplosionType explosionType, CVe } } + m_bCreatingExplosion = true; CExplosion * pExplosion = g_pGame->GetExplosionManager ()->AddExplosion ( NULL, pGameCreator, explosionType, vecPosition, 0, bMakeSound, fCamShake, bNoDamage ); + m_bCreatingExplosion = false; return pExplosion; } \ No newline at end of file diff --git a/MTA10/mods/shared_logic/CClientExplosionManager.h b/MTA10/mods/shared_logic/CClientExplosionManager.h index 33e462889a..41ed87a0ac 100644 --- a/MTA10/mods/shared_logic/CClientExplosionManager.h +++ b/MTA10/mods/shared_logic/CClientExplosionManager.h @@ -32,9 +32,10 @@ class CClientExplosionManager eWeaponType m_LastWeaponType; CClientEntity * m_pLastCreator; + bool m_bCreatingExplosion; private: - CClientManager * m_pManager; + CClientManager * m_pManager; }; #endif \ No newline at end of file diff --git a/MTA10/mods/shared_logic/CClientModelRequestManager.cpp b/MTA10/mods/shared_logic/CClientModelRequestManager.cpp index 5bcb3fce7a..f3a8f93e95 100644 --- a/MTA10/mods/shared_logic/CClientModelRequestManager.cpp +++ b/MTA10/mods/shared_logic/CClientModelRequestManager.cpp @@ -313,7 +313,7 @@ void CClientModelRequestManager::DoPulse ( void ) { // Cancel every entity in our cancel list list < CClientEntity* > ::iterator iter = m_CancelQueue.begin (); - for ( ; iter != m_CancelQueue.end (); iter++ ) + for ( ; iter != m_CancelQueue.end (); ++iter ) { Cancel ( *iter, false ); } diff --git a/MTA10/mods/shared_logic/CClientObjectManager.cpp b/MTA10/mods/shared_logic/CClientObjectManager.cpp index 52546fe537..dd3a1df5f4 100644 --- a/MTA10/mods/shared_logic/CClientObjectManager.cpp +++ b/MTA10/mods/shared_logic/CClientObjectManager.cpp @@ -116,7 +116,7 @@ void CClientObjectManager::DoPulse ( void ) CClientObject * pObject = NULL; // Loop through all our streamed-in objects list < CClientObject * > ::iterator iter = m_StreamedIn.begin (); - for ( ; iter != m_StreamedIn.end () ; iter++ ) + for ( ; iter != m_StreamedIn.end () ; ++iter ) { pObject = *iter; // We should have a game-object here diff --git a/MTA10/mods/shared_logic/CClientPathManager.cpp b/MTA10/mods/shared_logic/CClientPathManager.cpp index 3c909e55c7..173e4149e9 100644 --- a/MTA10/mods/shared_logic/CClientPathManager.cpp +++ b/MTA10/mods/shared_logic/CClientPathManager.cpp @@ -51,7 +51,7 @@ void CClientPathManager::DeleteAll ( void ) void CClientPathManager::DoPulse ( void ) { list < CClientPathNode* > ::const_iterator iter = m_PathNodeList.begin (); - for ( ; iter != m_PathNodeList.end () ; iter++ ) + for ( ; iter != m_PathNodeList.end () ; ++iter ) { (*iter)->DoPulse (); } diff --git a/MTA10/mods/shared_logic/CClientPed.cpp b/MTA10/mods/shared_logic/CClientPed.cpp index 0650b6b92e..8e9fdb01f3 100644 --- a/MTA10/mods/shared_logic/CClientPed.cpp +++ b/MTA10/mods/shared_logic/CClientPed.cpp @@ -94,7 +94,7 @@ void CClientPed::Init ( CClientManager* pManager, unsigned long ulModelID, bool m_pTaskManager = NULL; m_pOccupiedVehicle = NULL; m_pOccupyingVehicle = NULL; - m_uiOccupyingSeat = 0; + //m_uiOccupyingSeat = 0; m_uiOccupiedVehicleSeat = 0xFF; m_bHealthLocked = false; m_bArmorLocked = false; @@ -113,6 +113,8 @@ void CClientPed::Init ( CClientManager* pManager, unsigned long ulModelID, bool m_fTargetRotationA = 0.0f; m_fBeginCameraRotation = 0.0f; m_fTargetCameraRotation = 0.0f; + m_ulBeginPositionTime = 0; + m_ulEndPositionTime = 0; m_ulBeginTarget = 0; m_ulEndTarget = 0; m_bForceGettingIn = false; @@ -132,6 +134,8 @@ void CClientPed::Init ( CClientManager* pManager, unsigned long ulModelID, bool m_FightingStyle = STYLE_GRAB_KICK; m_MoveAnim = MOVE_PLAYER; m_ucAlpha = 255; + m_bHasTargetPosition = false; + m_pTargetOriginSource = NULL; m_fTargetRotation = 0.0f; m_bTargetAkimboUp = false; m_bIsChoking = false; @@ -156,10 +160,6 @@ void CClientPed::Init ( CClientManager* pManager, unsigned long ulModelID, bool m_bSpeechEnabled = true; m_bStealthAiming = false; m_fLighting = 0.0f; - - // Time based interpolation - m_interp.pTargetOriginSource = NULL; - m_interp.bHadOriginSource = false; m_pClothes = new CClientPlayerClothes ( this ); @@ -266,26 +266,7 @@ CClientPed::~CClientPed ( void ) m_pClothes = NULL; // Remove us from any occupied vehicle - if ( m_pOccupiedVehicle ) - { - if ( m_uiOccupiedVehicleSeat == 0 ) - m_pOccupiedVehicle->m_pDriver = NULL; - else - m_pOccupiedVehicle->m_pPassengers [ m_uiOccupiedVehicleSeat - 1 ] = NULL; - m_pOccupiedVehicle = NULL; - } - - if ( m_pOccupyingVehicle ) - { - if ( m_uiOccupyingSeat == 0 && m_pOccupyingVehicle->m_pOccupyingDriver == this ) - { - m_pOccupyingVehicle->m_pOccupyingDriver = NULL; - } - else if ( m_pOccupyingVehicle->m_pOccupyingPassengers [ m_uiOccupyingSeat - 1 ] == this ) - { - m_pOccupyingVehicle->m_pOccupyingPassengers [ m_uiOccupyingSeat - 1 ] = NULL; - } - } + CClientVehicle::UnpairPedAndVehicle ( this ); // Delete delayed sync data list < SDelayedSyncData* > ::iterator iter = m_SyncBuffer.begin (); @@ -300,10 +281,10 @@ CClientPed::~CClientPed ( void ) if ( g_pLastRebuilt == this ) g_pLastRebuilt = NULL; - if ( m_interp.pTargetOriginSource ) + if ( m_pTargetOriginSource ) { - m_interp.pTargetOriginSource->RemoveOriginSourceUser ( this ); - m_interp.pTargetOriginSource = NULL; + m_pTargetOriginSource->RemoveOriginSourceUser ( this ); + m_pTargetOriginSource = NULL; } g_pClientGame->GetPedSync()->RemovePed ( this ); @@ -433,7 +414,7 @@ void CClientPed::GetPosition ( CVector& vecPosition ) const } -void CClientPed::SetPosition ( const CVector& vecPosition, bool bResetInterpolation ) +void CClientPed::SetPosition ( const CVector& vecPosition ) { // We have a player ped? if ( m_pPlayerPed ) @@ -467,9 +448,6 @@ void CClientPed::SetPosition ( const CVector& vecPosition, bool bResetInterpolat // Update our streaming position UpdateStreamPosition ( vecPosition ); } - - if ( bResetInterpolation ) - RemoveTargetPosition (); } @@ -620,8 +598,21 @@ void CClientPed::Spawn ( const CVector& vecPosition, SetInterior ( ucInterior ); } + +void CClientPed::SetTargetPosition ( unsigned long ulDelay, const CVector& vecPosition ) +{ + m_ulBeginPositionTime = CClientTime::GetTime (); + m_ulEndPositionTime = m_ulBeginPositionTime + ulDelay; + GetMatrix ( m_Matrix ); // Test + m_vecBeginPosition = m_Matrix.vPos; + m_vecTargetPosition = vecPosition; +} + + void CClientPed::ResetInterpolation ( void ) { + m_ulBeginPositionTime = 0; + m_ulEndPositionTime = 0; m_ulBeginRotationTime = 0; m_ulEndRotationTime = 0; m_ulBeginAimTime = 0; @@ -777,6 +768,9 @@ void CClientPed::AddKeysync ( unsigned long ulDelay, const CControllerState& Con pData->bDucking = bDucking; m_SyncBuffer.push_back ( pData ); + + if ( !IsStreamedIn () ) + UpdateKeysync ( true ); } } @@ -792,6 +786,9 @@ void CClientPed::AddChangeWeapon ( unsigned long ulDelay, eWeaponSlot slot, unsi pData->usWeaponAmmo = usWeaponAmmo; m_SyncBuffer.push_back ( pData ); + + if ( !IsStreamedIn () ) + UpdateKeysync ( true ); } } @@ -806,6 +803,9 @@ void CClientPed::AddMoveSpeed ( unsigned long ulDelay, const CVector& vecMoveSpe pData->vecTarget = vecMoveSpeed; m_SyncBuffer.push_back ( pData ); + + if ( !IsStreamedIn () ) + UpdateKeysync ( true ); } } @@ -1143,7 +1143,7 @@ void CClientPed::GetOutOfVehicle ( void ) CClientVehicle* pVehicle = GetRealOccupiedVehicle (); if ( pVehicle ) { - m_pOccupyingVehicle = pVehicle; + //m_pOccupyingVehicle = pVehicle; if ( m_pPlayerPed ) { @@ -1190,7 +1190,7 @@ void CClientPed::WarpIntoVehicle ( CClientVehicle* pVehicle, unsigned int uiSeat // Eventually remove us from a previous vehicle RemoveFromVehicle (); - m_uiOccupyingSeat = uiSeat; + //m_uiOccupyingSeat = uiSeat; m_bForceGettingIn = false; m_bForceGettingOut = false; @@ -1217,9 +1217,7 @@ void CClientPed::WarpIntoVehicle ( CClientVehicle* pVehicle, unsigned int uiSeat } // Update the vehicle and us so we know we've occupied it - m_pOccupiedVehicle = pVehicle; - m_uiOccupiedVehicleSeat = 0; - pVehicle->m_pDriver = this; + CClientVehicle::SetPedOccupiedVehicle( this, pVehicle, 0 ); } else { @@ -1256,9 +1254,7 @@ void CClientPed::WarpIntoVehicle ( CClientVehicle* pVehicle, unsigned int uiSeat } // Update us so we know we've occupied it - m_pOccupiedVehicle = pVehicle; - m_uiOccupiedVehicleSeat = uiSeat; - pVehicle->m_pPassengers [uiSeat-1] = this; + CClientVehicle::SetPedOccupiedVehicle( this, pVehicle, uiSeat ); } else return; @@ -1323,20 +1319,7 @@ CClientVehicle * CClientPed::RemoveFromVehicle ( bool bIgnoreIfGettingOut ) } } - // Clear our record in the vehicle class - if ( m_uiOccupiedVehicleSeat == 0 ) - { - pVehicle->m_pDriver = NULL; - pVehicle->m_pOccupyingDriver = NULL; - } - else - { - if ( m_uiOccupiedVehicleSeat < 9 ) - { - pVehicle->m_pPassengers [m_uiOccupiedVehicleSeat - 1] = NULL; - pVehicle->m_pOccupyingPassengers [m_uiOccupiedVehicleSeat - 1] = NULL; - } - } + CClientVehicle::UnpairPedAndVehicle( this ); if ( m_bIsLocalPlayer ) { @@ -1348,9 +1331,11 @@ CClientVehicle * CClientPed::RemoveFromVehicle ( bool bIgnoreIfGettingOut ) ResetInterpolation (); // And in our class - m_pOccupiedVehicle = NULL; - m_pOccupyingVehicle = NULL; - m_uiOccupiedVehicleSeat = 0xFF; + CClientVehicle::UnpairPedAndVehicle( this ); + assert ( m_pOccupiedVehicle == NULL ); + assert ( m_pOccupyingVehicle == NULL ); + assert ( m_uiOccupiedVehicleSeat = 0xFF ); + m_bForceGettingIn = false; m_bForceGettingOut = false; @@ -1574,7 +1559,7 @@ void CClientPed::Kill ( eWeaponType weaponType, unsigned char ucBodypart, bool b if ( bStealth ) { - pTask = g_pGame->GetTasks ()->CreateTaskSimpleStealthKill ( false, m_pPlayerPed, 87 ); + pTask = g_pGame->GetTasks ()->CreateTaskSimpleStealthKill ( false, m_pPlayerPed, ANIM_GROUP_STEALTH_KN ); if ( pTask ) { pTask->SetAsPedTask ( m_pPlayerPed, TASK_PRIORITY_PRIMARY ); @@ -1609,7 +1594,7 @@ void CClientPed::StealthKill ( CClientPed * pPed ) CPlayerPed * pPlayerPed = pPed->GetGamePlayer (); if ( pPlayerPed ) { - CTask * pTask = g_pGame->GetTasks ()->CreateTaskSimpleStealthKill ( true, pPlayerPed, 87 ); + CTask * pTask = g_pGame->GetTasks ()->CreateTaskSimpleStealthKill ( true, pPlayerPed, ANIM_GROUP_STEALTH_KN ); if ( pTask ) { pTask->SetAsPedTask ( m_pPlayerPed, TASK_PRIORITY_PRIMARY ); @@ -1624,6 +1609,7 @@ void CClientPed::SetFrozen ( bool bFrozen ) if ( m_bFrozen != bFrozen ) { m_bFrozen = bFrozen; + SetStatic ( m_bFrozen ); if ( bFrozen ) { @@ -2548,7 +2534,6 @@ void CClientPed::SetTargetRotation ( float fRotation ) m_pPlayerPed->SetTargetRotation ( fRotation ); } m_fTargetRotation = fRotation; - SetCurrentRotation ( fRotation ); } void CClientPed::SetTargetRotation ( unsigned long ulDelay, float fRotation, float fCameraRotation ) @@ -2616,8 +2601,8 @@ void CClientPed::Interpolate ( void ) { // Interpolate the player rotation float fDeltaTime = float ( m_ulEndRotationTime - m_ulBeginRotationTime ); - float fDelta = m_fTargetRotationA - m_fBeginRotation; - float fCameraDelta = m_fTargetCameraRotation - m_fBeginCameraRotation; + float fDelta = GetOffsetDegrees ( m_fBeginRotation, m_fTargetRotationA ); + float fCameraDelta = GetOffsetDegrees ( m_fBeginCameraRotation, m_fTargetCameraRotation ); float fProgress = float ( ulCurrentTime - m_ulBeginRotationTime ); float fNewRotation = m_fBeginRotation + ( fDelta / fDeltaTime * fProgress ); float fNewCameraRotation = m_fBeginCameraRotation + ( fCameraDelta / fDeltaTime * fProgress ); @@ -2695,7 +2680,7 @@ void CClientPed::Interpolate ( void ) } -void CClientPed::UpdateKeysync ( void ) +void CClientPed::UpdateKeysync ( bool bCleanup ) { // TODO: we should ignore any 'old' keysyncs and set only the latest @@ -2703,7 +2688,9 @@ void CClientPed::UpdateKeysync ( void ) if ( m_SyncBuffer.size () > 0 ) { // Time to apply it? - unsigned long ulCurrentTime = CClientTime::GetTime (); + unsigned long ulCurrentTime = 0; + if ( !bCleanup ) + ulCurrentTime = CClientTime::GetTime (); // Get the sync data at the front SDelayedSyncData* pData = m_SyncBuffer.front (); @@ -2712,7 +2699,7 @@ void CClientPed::UpdateKeysync ( void ) if ( pData ) { // Check the front data's time (if this isn't valid, nothing else will be either so just leave it in the buffer) - if ( ulCurrentTime >= pData->ulTime ) + if ( bCleanup || ulCurrentTime >= pData->ulTime ) { // Loop through until one of the conditions are caught do @@ -2789,7 +2776,7 @@ void CClientPed::UpdateKeysync ( void ) m_SyncBuffer.pop_front (); } } - } while ( pData && ulCurrentTime >= pData->ulTime ); + } while ( pData && ( bCleanup || ulCurrentTime >= pData->ulTime ) ); } } } @@ -2819,16 +2806,15 @@ void CClientPed::_CreateModel ( void ) m_pManager->RestoreEntity ( this ); // Jump straight to the target position if we have one - if ( HasTargetPosition () ) + if ( m_bHasTargetPosition ) { - CVector vecPosition = m_interp.pos.vecTarget; - if ( m_interp.pTargetOriginSource ) + m_Matrix.vPos = m_vecTargetPosition; + if ( m_pTargetOriginSource ) { CVector vecOrigin; - m_interp.pTargetOriginSource->GetPosition ( vecOrigin ); - vecPosition += vecOrigin; + m_pTargetOriginSource->GetPosition ( vecOrigin ); + m_Matrix.vPos += vecOrigin; } - m_Matrix.vPos = vecPosition; } // Restore any settings @@ -2870,6 +2856,7 @@ void CClientPed::_CreateModel ( void ) SetHeadless ( m_bHeadless ); SetOnFire ( m_bIsOnFire ); SetSpeechEnabled ( m_bSpeechEnabled ); + SetStatic ( m_bFrozen ); // Rebuild the player if it's CJ. So we get the clothes. RebuildModel (); @@ -2901,7 +2888,7 @@ void CClientPed::_CreateModel ( void ) // Set the voice that corresponds to our model short sVoiceType, sVoiceID; - static_cast < CPedModelInfo * > ( m_pModelInfo )->GetVoice ( &sVoiceType, &sVoiceID ); + m_pModelInfo->GetVoice ( &sVoiceType, &sVoiceID ); SetVoice ( sVoiceType, sVoiceID ); // Tell the streamer we created the player @@ -3344,33 +3331,6 @@ bool CClientPed::PerformChecks ( void ) } -/* -void CClientPed::StartRadio ( void ) -{ - // We use this to avoid radio lags sometimes. Also make sure - // it's not already on - if ( !m_bDontChangeRadio && !m_bRadioOn ) - { - // Turn it on if we're not on channel none - if ( m_ucRadioChannel != 0 ) g_pGame->GetAudio ()->StartRadio ( m_ucRadioChannel ); - - m_bRadioOn = true; - } -} - - -void CClientPed::StopRadio ( void ) -{ - // We use this to avoid radio lags sometimes - if ( !m_bDontChangeRadio ) - { - // Stop the radio and mark it as off - g_pGame->GetAudio ()->StopRadio (); - m_bRadioOn = false; - } -} -*/ - void CClientPed::Duck ( bool bDuck ) { if ( m_pPlayerPed ) @@ -3533,9 +3493,8 @@ bool CClientPed::IsMovingGoggles ( bool & bPuttingOn ) void CClientPed::_GetIntoVehicle ( CClientVehicle* pVehicle, unsigned int uiSeat ) { - // Set our occupying vehicle to it - m_pOccupyingVehicle = pVehicle; - m_uiOccupyingSeat = uiSeat; + assert ( m_pOccupiedVehicle == NULL ); + assert ( m_pOccupyingVehicle == NULL || m_pOccupyingVehicle == pVehicle ); //Check for swimming task and warp to door. CTask* pTask = 0; @@ -3570,7 +3529,7 @@ void CClientPed::_GetIntoVehicle ( CClientVehicle* pVehicle, unsigned int uiSeat } // Tell the vehicle that we're occupying it - pVehicle->m_pOccupyingDriver = this; + CClientVehicle::SetPedOccupyingVehicle ( this, pVehicle, uiSeat ); } else { @@ -3604,7 +3563,7 @@ void CClientPed::_GetIntoVehicle ( CClientVehicle* pVehicle, unsigned int uiSeat } // Tell the vehicle we're occupying it - pVehicle->m_pOccupyingPassengers [uiSeat - 1] = this; + CClientVehicle::SetPedOccupyingVehicle ( this, pVehicle, uiSeat ); } } } @@ -3738,58 +3697,11 @@ bool CClientPed::IsClimbing ( void ) } -/* -void CClientPed::NextRadioChannel ( void ) -{ - // Is our radio on? - if ( m_bRadioOn ) SetCurrentRadioChannel ( ( m_ucRadioChannel + 1 ) % 13 ); -} - - -void CClientPed::PreviousRadioChannel ( void ) -{ - // Is our radio on? - if ( m_bRadioOn ) - { - if ( m_ucRadioChannel == 0 ) m_ucRadioChannel = 13; - - SetCurrentRadioChannel ( m_ucRadioChannel - 1 ); - } -} - - -bool CClientPed::SetCurrentRadioChannel ( unsigned char ucChannel ) -{ - // Local player? - if ( m_bIsLocalPlayer && ucChannel >= 0 && ucChannel <= 12 ) - { - if ( m_ucRadioChannel != ucChannel ) - { - CLuaArguments Arguments; - Arguments.PushNumber ( ucChannel ); - if ( !CallEvent ( "onClientPlayerRadioSwitch", Arguments, true ) ) - { - return false; - } - } - - m_ucRadioChannel = ucChannel; - - g_pGame->GetAudio ()->StartRadio ( m_ucRadioChannel ); - if ( m_ucRadioChannel == 0 ) g_pGame->GetAudio ()->StopRadio (); - - return true; - } - return false; -} -*/ - - -void CClientPed::GetShotData ( CVector * pvecOrigin, CVector * pvecTarget, CVector * pvecGunMuzzle, CVector * pvecFireOffset, float* fAimX, float* fAimY ) +bool CClientPed::GetShotData ( CVector * pvecOrigin, CVector * pvecTarget, CVector * pvecGunMuzzle, CVector * pvecFireOffset, float* fAimX, float* fAimY ) { CWeapon* pWeapon = GetWeapon ( GetCurrentWeaponSlot () ); if ( !pWeapon ) - return; + return false; unsigned char ucWeaponType = pWeapon->GetType (); CClientVehicle* pVehicle = GetRealOccupiedVehicle (); @@ -3889,6 +3801,7 @@ void CClientPed::GetShotData ( CVector * pvecOrigin, CVector * pvecTarget, CVect if ( pvecGunMuzzle ) *pvecGunMuzzle = vecGunMuzzle; if ( fAimX ) *fAimX = m_shotSyncData->m_fArmDirectionX; if ( fAimY ) *fAimY = m_shotSyncData->m_fArmDirectionY; + return true; } @@ -4308,101 +4221,120 @@ char* CClientPed::GetBodyPartName ( unsigned char ucID ) void CClientPed::GetTargetPosition ( CVector & vecPosition ) { - vecPosition = m_interp.pos.vecTarget; - if ( m_interp.pTargetOriginSource ) + vecPosition = m_vecTargetPosition; + if ( m_pTargetOriginSource ) { CVector vecTemp; - m_interp.pTargetOriginSource->GetPosition ( vecTemp ); + m_pTargetOriginSource->GetPosition ( vecTemp ); vecPosition += vecTemp; } } -void CClientPed::SetTargetPosition ( const CVector& vecPosition, unsigned long ulDelay, CClientEntity* pTargetOriginSource ) +void CClientPed::SetTargetPosition ( CVector& vecPosition, CClientEntity* pOriginSource ) { - UpdateTargetPosition (); - - // Get the origin of the position if we are in contact with anything - CVector vecOrigin; - if ( pTargetOriginSource ) - pTargetOriginSource->GetPosition ( vecOrigin ); + CVector vecTemp, vecOrigin; + GetPosition ( vecTemp ); - // Update the references to the contact entity - if ( pTargetOriginSource != m_interp.pTargetOriginSource ) - { - if ( m_interp.pTargetOriginSource ) - m_interp.pTargetOriginSource->RemoveOriginSourceUser ( this ); - if ( pTargetOriginSource ) - pTargetOriginSource->AddOriginSourceUser ( this ); - m_interp.pTargetOriginSource = pTargetOriginSource; + if ( pOriginSource ) + { + pOriginSource->GetPosition ( vecOrigin ); + vecTemp -= vecOrigin; } - if ( m_pPlayerPed ) + m_bTargetDirections [ 0 ] = ( vecTemp.fX < vecPosition.fX ); + m_bTargetDirections [ 1 ] = ( vecTemp.fY < vecPosition.fY ); + m_bTargetDirections [ 2 ] = ( vecTemp.fZ < vecPosition.fZ ); + m_vecTargetPosition = vecPosition; + m_bHasTargetPosition = true; + if ( pOriginSource != m_pTargetOriginSource ) { - // The ped is streamed in - GetPosition ( m_interp.pos.vecOrigin ); - m_interp.pos.vecOrigin -= vecOrigin; - m_interp.pos.vecTarget = vecPosition; - m_interp.vecOriginSourceLastPosition = vecOrigin; - m_interp.bHadOriginSource = false; + if ( m_pTargetOriginSource ) + m_pTargetOriginSource->RemoveOriginSourceUser ( this ); + + if ( pOriginSource ) + pOriginSource->AddOriginSourceUser ( this ); - unsigned long ulTime = CClientTime::GetTime (); - m_interp.pos.ulStartTime = ulTime; - m_interp.pos.ulFinishTime = ulTime + ulDelay; + m_pTargetOriginSource = pOriginSource; } - else + + // Jax: if we're streamed out, update our position now and don't interpolate + if ( !m_pPlayerPed ) { - // Set the position straight - SetPosition ( vecPosition + vecOrigin ); + CVector vecActualPosition = vecPosition; + if ( pOriginSource ) + { + vecActualPosition += vecOrigin; + } + SetPosition ( vecActualPosition ); } } void CClientPed::RemoveTargetPosition ( void ) { - m_interp.pos.ulFinishTime = 0; - if ( m_interp.pTargetOriginSource ) + m_bHasTargetPosition = false; + + if ( m_pTargetOriginSource ) { - m_interp.pTargetOriginSource->RemoveOriginSourceUser ( this ); - m_interp.pTargetOriginSource = NULL; + m_pTargetOriginSource->RemoveOriginSourceUser ( this ); + m_pTargetOriginSource = NULL; } } void CClientPed::UpdateTargetPosition ( void ) { - if ( HasTargetPosition () ) + if ( m_bHasTargetPosition && m_pPlayerPed ) { - CVector vecNewPosition; - unsigned long ulCurrentTime = CClientTime::GetTime (); - - // Get the origin position if there is any contact + CVector vecPosition; + GetPosition ( vecPosition ); CVector vecOrigin; - if ( m_interp.pTargetOriginSource ) - m_interp.pTargetOriginSource->GetPosition ( vecOrigin ); - else if ( m_interp.bHadOriginSource ) - vecOrigin = m_interp.vecOriginSourceLastPosition; - // Get the factor of time spent from the interpolation start - // to the current time. - float fAlpha = SharedUtil::Unlerp ( m_interp.pos.ulStartTime, - ulCurrentTime, - m_interp.pos.ulFinishTime ); + if ( m_pTargetOriginSource ) + m_pTargetOriginSource->GetPosition ( vecOrigin ); - // If the factor is bigger or equal to 1.0f, then - // we have finished interpolating. - if ( fAlpha >= 1.0f ) - { - m_interp.pos.ulFinishTime = 0; - vecNewPosition = m_interp.pos.vecTarget; - } - else + vecPosition -= vecOrigin; + + // Needs to be calced + float fTimeSlice = 1/30.f; + + CVector vecOffset = m_vecTargetPosition - vecPosition; + float fDistanceToTarget = vecOffset.Length (); + // fDistanceToTarget 0.20f to 0.00f then fSpeed = 3.0f to 15.0f + float fSpeedAlpha = UnlerpClamped ( 0, fDistanceToTarget, 0.20f ); + float fSpeed = Lerp < const float > ( 15.f, fSpeedAlpha, 3.f ); + CVector vecScale; + vecScale.fX = 1.5f * fTimeSlice * fSpeed; + vecScale.fY = 1.5f * fTimeSlice * fSpeed; + vecScale.fZ = 6.0f * fTimeSlice; + // Make sure not to overshoot + vecScale.fX = Min ( vecScale.fX, 1.f ); + vecScale.fY = Min ( vecScale.fY, 1.f ); + vecScale.fZ = Min ( vecScale.fZ, 1.f ); + vecOffset *= vecScale; + // Apply offset ignoring X and Y m_bTargetDirections + //if ( ( vecOffset.fX > 0.0f ) == m_bTargetDirections [ 0 ] ) + vecPosition.fX += vecOffset.fX; + //if ( ( vecOffset.fY > 0.0f ) == m_bTargetDirections [ 1 ] ) + vecPosition.fY += vecOffset.fY; + if ( ( vecOffset.fZ > 0.0f ) == m_bTargetDirections [ 2 ] ) + vecPosition.fZ += vecOffset.fZ; + + // Temp hack to help ensure gravity doesn't suck the ped underground - ( Maybe when level collision is streamed out and ped it not? ) + if ( CCamera* pCamera = g_pGame->GetCamera () ) { - vecNewPosition = SharedUtil::Lerp ( m_interp.pos.vecOrigin, - fAlpha, - m_interp.pos.vecTarget ); + CMatrix matCamera; + pCamera->GetMatrix ( &matCamera ); + float fDist = ( matCamera.vPos - ( vecPosition + vecOrigin ) ).Length (); + // Fix only required if ped is between 250.f and 300.f units away, possibly + if ( fDist > 230.f && fDist < 320.f ) + vecPosition.fZ = m_vecTargetPosition.fZ; } - SetPosition ( vecNewPosition + vecOrigin, false ); + + vecPosition += vecOrigin; + + SetPosition ( vecPosition ); } } @@ -4456,6 +4388,7 @@ void CClientPed::NotifyCreate ( void ) void CClientPed::NotifyDestroy ( void ) { m_pManager->GetPedManager ()->OnDestruction ( this ); + UpdateKeysync ( true ); } diff --git a/MTA10/mods/shared_logic/CClientPed.h b/MTA10/mods/shared_logic/CClientPed.h index e6986b1745..02a96e2e2c 100644 --- a/MTA10/mods/shared_logic/CClientPed.h +++ b/MTA10/mods/shared_logic/CClientPed.h @@ -122,8 +122,7 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule bool SetMatrix ( const CMatrix& Matrix ); void GetPosition ( CVector& vecPosition ) const; - void SetPosition ( const CVector& vecPosition ) { SetPosition ( vecPosition, true ); } - void SetPosition ( const CVector& vecPosition, bool bResetInterpolation ); + void SetPosition ( const CVector& vecPosition ); void SetInterior ( unsigned char ucInterior ); @@ -142,6 +141,7 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule unsigned short usModel, unsigned char ucInterior ); + void SetTargetPosition ( unsigned long ulDelay, const CVector& vecPosition ); void ResetInterpolation ( void ); float GetCurrentRotation ( void ); @@ -289,7 +289,7 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule inline CTaskManager* GetTaskManager ( void ) { return m_pTaskManager; } - void GetShotData ( CVector * pvecOrigin, CVector * pvecTarget = NULL, CVector * pvecGunMuzzle = NULL, CVector * pvecFireOffset = NULL, float* fAimX = NULL, float* fAimY = NULL ); + bool GetShotData ( CVector * pvecOrigin, CVector * pvecTarget = NULL, CVector * pvecGunMuzzle = NULL, CVector * pvecFireOffset = NULL, float* fAimX = NULL, float* fAimY = NULL ); eFightingStyle GetFightingStyle ( void ); void SetFightingStyle ( eFightingStyle style ); @@ -323,10 +323,10 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule inline unsigned char GetAlpha ( void ) { return m_ucAlpha; } void SetAlpha ( unsigned char ucAlpha ); - inline bool HasTargetPosition ( void ) { return ( m_interp.pos.ulFinishTime != 0 ); } - inline CClientEntity * GetTargetOriginSource ( void ) { return m_interp.pTargetOriginSource; } + inline bool HasTargetPosition ( void ) { return m_bHasTargetPosition; } + inline CClientEntity * GetTargetOriginSource ( void ) { return m_pTargetOriginSource; } void GetTargetPosition ( CVector & vecPosition ); - void SetTargetPosition ( const CVector& vecPosition, unsigned long ulDelay, CClientEntity* pTargetOriginSource = NULL ); + void SetTargetPosition ( CVector& vecPosition, CClientEntity* pOriginSource = NULL ); void RemoveTargetPosition ( void ); void UpdateTargetPosition ( void ); @@ -398,7 +398,7 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule void StreamedInPulse ( void ); void Interpolate ( void ); - void UpdateKeysync ( void ); + void UpdateKeysync ( bool bCleanup = false ); // Used to destroy the current game ped and create a new one in the same state. void ReCreateModel ( void ); @@ -437,7 +437,7 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule unsigned long m_ulLastOnScreenTime; CClientVehicle* m_pOccupiedVehicle; CClientVehicle* m_pOccupyingVehicle; - unsigned int m_uiOccupyingSeat; + //unsigned int m_uiOccupyingSeat; unsigned int m_uiOccupiedVehicleSeat; bool m_bForceGettingIn; bool m_bForceGettingOut; @@ -466,6 +466,9 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule float m_fTargetRotationA; float m_fBeginCameraRotation; float m_fTargetCameraRotation; + unsigned long m_ulBeginPositionTime; + unsigned long m_ulEndPositionTime; + CVector m_vecBeginPosition; unsigned long m_ulBeginTarget; unsigned long m_ulEndTarget; CVector m_vecBeginSource; @@ -500,6 +503,10 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule eMoveAnim m_MoveAnim; std::list < CClientProjectile* > m_Projectiles; unsigned char m_ucAlpha; + CVector m_vecTargetPosition; + CClientEntity* m_pTargetOriginSource; + bool m_bTargetDirections [ 3 ]; + bool m_bHasTargetPosition; float m_fTargetRotation; int m_iVehicleInOutState; bool m_bRecreatingModel; @@ -521,25 +528,6 @@ class CClientPed : public CClientStreamElement, public CAntiCheatModule bool m_bSpeechEnabled; bool m_bStealthAiming; float m_fLighting; - - // Time dependent interpolation - struct - { - struct - { - CVector vecOrigin; - CVector vecTarget; - unsigned long ulStartTime; - unsigned long ulFinishTime; - } pos; - - CClientEntity* pTargetOriginSource; - // These variables are used to track the last known position - // of the contact entity for if it's removed during the - // interpolation. - bool bHadOriginSource; - CVector vecOriginSourceLastPosition; - } m_interp; }; #endif diff --git a/MTA10/mods/shared_logic/CClientPedManager.cpp b/MTA10/mods/shared_logic/CClientPedManager.cpp index 49556aa586..12c23e6d90 100644 --- a/MTA10/mods/shared_logic/CClientPedManager.cpp +++ b/MTA10/mods/shared_logic/CClientPedManager.cpp @@ -46,7 +46,7 @@ void CClientPedManager::DoPulse ( void ) // Loop through our streamed-in peds list < CClientPed * > List = m_StreamedIn; list < CClientPed* > ::iterator iter = List.begin (); - for ( ; iter != List.end (); iter++ ) + for ( ; iter != List.end (); ++iter ) { pPed = *iter; // We should have a game ped here diff --git a/MTA10/mods/shared_logic/CClientPlayer.cpp b/MTA10/mods/shared_logic/CClientPlayer.cpp index 26f8987d9f..25029fe89c 100644 --- a/MTA10/mods/shared_logic/CClientPlayer.cpp +++ b/MTA10/mods/shared_logic/CClientPlayer.cpp @@ -292,7 +292,7 @@ void CClientPlayer::GetPretendHealthAndArmor ( float* pfHealth, float* pfArmor ) m_fPretendHealthSmoothed = fPretendHealth; // Smooth update - float fSmoothAlpha = Min ( 1.f, g_fTimeSlice * 2.f ); + float fSmoothAlpha = Min ( 1.f, g_pClientGame->GetFrameTimeSlice () * 2.f / 1000.0f ); m_fPretendHealthSmoothed = Lerp ( m_fPretendHealthSmoothed, fSmoothAlpha, fPretendHealth ); m_fPretendArmorSmoothed = Lerp ( m_fPretendArmorSmoothed, fSmoothAlpha, fPretendArmor ); diff --git a/MTA10/mods/shared_logic/CClientPlayerManager.cpp b/MTA10/mods/shared_logic/CClientPlayerManager.cpp index 9cbcfa8afa..7160adcb9b 100644 --- a/MTA10/mods/shared_logic/CClientPlayerManager.cpp +++ b/MTA10/mods/shared_logic/CClientPlayerManager.cpp @@ -36,7 +36,7 @@ void CClientPlayerManager::DoPulse ( void ) unsigned long ulCurrentTime = CClientTime::GetTime (); CClientPlayer * pPlayer = NULL; list < CClientPlayer* > ::const_iterator iter = m_Players.begin (); - for ( ; iter != m_Players.end (); iter++ ) + for ( ; iter != m_Players.end (); ++iter ) { pPlayer = *iter; if ( !pPlayer->IsLocalPlayer () ) @@ -44,7 +44,7 @@ void CClientPlayerManager::DoPulse ( void ) // Flag him with connection error if its been more than 6000 ms since last puresync and force his position unsigned long ulLastPuresyncTime = pPlayer->GetLastPuresyncTime (); bool bHasConnectionTrouble = ( ulLastPuresyncTime != 0 && ulCurrentTime >= ulLastPuresyncTime + 6000 && pPlayer->GetOccupiedVehicleSeat () == 0 ); - if ( bHasConnectionTrouble ) + if ( bHasConnectionTrouble && !g_pClientGame->IsDownloadingBigPacket () ) { pPlayer->SetHasConnectionTrouble ( true ); @@ -191,6 +191,8 @@ bool CClientPlayerManager::IsPlayerLimitReached ( void ) bool CClientPlayerManager::IsValidModel ( unsigned long ulModel ) { return ( ulModel == 0 || + ulModel == 1 || + ulModel == 2 || ulModel == 7 || ulModel >= 9 && ulModel != 208 && @@ -200,9 +202,12 @@ bool CClientPlayerManager::IsValidModel ( unsigned long ulModel ) ulModel != 74 && ulModel != 65 && ulModel != 42 && - ulModel <= 264 || + ulModel <= 272 || ulModel >= 274 && - ulModel <= 288 ); + ulModel <= 288 || + ulModel >= 290 && + ulModel <= 311 && + ulModel != 299 ); } diff --git a/MTA10/mods/shared_logic/CClientProjectileManager.cpp b/MTA10/mods/shared_logic/CClientProjectileManager.cpp index d3ccbac887..81a9f24de8 100644 --- a/MTA10/mods/shared_logic/CClientProjectileManager.cpp +++ b/MTA10/mods/shared_logic/CClientProjectileManager.cpp @@ -45,7 +45,7 @@ void CClientProjectileManager::DoPulse ( void ) CClientProjectile* pProjectile = NULL; list < CClientProjectile* > cloneList = m_List; list < CClientProjectile* > ::iterator iter = cloneList.begin (); - for ( ; iter != cloneList.end () ; iter++ ) + for ( ; iter != cloneList.end () ; ++iter ) { pProjectile = *iter; @@ -69,7 +69,7 @@ void CClientProjectileManager::RemoveAll ( void ) { list < CClientProjectile * > cloneList = m_List; list < CClientProjectile* > ::iterator iter = cloneList.begin (); - for ( ; iter != cloneList.end () ; iter++ ) + for ( ; iter != cloneList.end () ; ++iter ) { delete *iter; } diff --git a/MTA10/mods/shared_logic/CClientRadarAreaManager.cpp b/MTA10/mods/shared_logic/CClientRadarAreaManager.cpp index 5e379d64e1..8fcf2fa4da 100644 --- a/MTA10/mods/shared_logic/CClientRadarAreaManager.cpp +++ b/MTA10/mods/shared_logic/CClientRadarAreaManager.cpp @@ -99,7 +99,7 @@ void CClientRadarAreaManager::DoPulse ( bool bRender ) { // Pulse each radar area marker list < CClientRadarArea* > ::const_iterator iter = m_List.begin (); - for ( ; iter != m_List.end (); iter++ ) + for ( ; iter != m_List.end (); ++iter ) { (*iter)->DoPulse ( bRender ); } diff --git a/MTA10/mods/shared_logic/CClientRadarMarkerManager.cpp b/MTA10/mods/shared_logic/CClientRadarMarkerManager.cpp index 5ee09fa61d..dcc6ecbfa5 100644 --- a/MTA10/mods/shared_logic/CClientRadarMarkerManager.cpp +++ b/MTA10/mods/shared_logic/CClientRadarMarkerManager.cpp @@ -36,7 +36,7 @@ void CClientRadarMarkerManager::DoPulse ( void ) // Grab the camera position here (so it isn't done for every marker) m_pManager->GetCamera ()->GetPosition ( m_vecCameraPosition ); list < CClientRadarMarker* > ::iterator iter = m_Markers.begin (); - for ( ; iter != m_Markers.end (); iter++ ) + for ( ; iter != m_Markers.end (); ++iter ) { (*iter)->DoPulse (); } diff --git a/MTA10/mods/shared_logic/CClientRadio.cpp b/MTA10/mods/shared_logic/CClientRadio.cpp index 903f733950..707bbd1d09 100644 --- a/MTA10/mods/shared_logic/CClientRadio.cpp +++ b/MTA10/mods/shared_logic/CClientRadio.cpp @@ -12,17 +12,36 @@ #include "StdInc.h" #define RADIO_COLOR 0xFF106290 +#define RADIO_TUNE_COLOR 0xFF666666 #define RADIO_DROP_COLOR 0xFF000000 #define RADIO_POS_X 0.5f #define RADIO_POS_Y 0.05f #define RADIO_SCALE_X 0.8f #define RADIO_SCALE_Y 1.2f +#define CHANNEL_TUNE_TIME 1500 +#define CHANNEL_DISPLAY_TIME 2500 +#define RADIO_SOUND_TUNE 34 +#define RADIO_SOUND_STOP_TUNE 35 +#define RADIO_SOUND_SELECT 37 + +char * CClientRadio::m_ChannelNames [ NUM_RADIO_CHANNELS ] = +{ + "Police", "Playback FM", + "K Rose", "K-DST", + "Bounce FM", "SF-UR", + "Radio Los Santos", "Radio X", + "CSR 103.9", "K-Jah West", + "Master Sounds 98.3", "WCTR", + "User Track Player", "Radio Off" +}; CClientRadio::CClientRadio ( CClientManager * pManager ) { m_pManager = pManager; - m_Channel = CHANNEL_PLAYBACK_FM; - m_bIsPlaying = false; + m_PreviousChannel = m_Channel = CHANNEL_PLAYBACK_FM; + m_bPlaying = false; + m_bTuning = false; + m_bTuneForThisChannel = false; m_ulChangeTick = 0; m_bPoliceRadio = false; } @@ -30,12 +49,13 @@ CClientRadio::CClientRadio ( CClientManager * pManager ) CClientRadio::~CClientRadio ( void ) { - if ( m_bIsPlaying ) Stop (); + if ( m_bPlaying ) Stop (); } void CClientRadio::DoPulse ( void ) { + // Can we hear the radio? do we use the police radio? bool bCanHearRadio = false; CClientPlayer * pLocalPlayer = m_pManager->GetPlayerManager ()->GetLocalPlayer (); if ( pLocalPlayer ) @@ -49,6 +69,23 @@ void CClientRadio::DoPulse ( void ) } } + // Start the radio after tuning + if ( m_bPlaying && m_bTuning ) + { + // Is it time to start playing? + unsigned long ulTick = GetTickCount (); + if ( m_ulChangeTick && ulTick >= ( m_ulChangeTick + CHANNEL_TUNE_TIME ) ) + { + // Stop the tuning in + m_bTuning = false; + g_pGame->GetAudio ()->PlayFrontEndSound ( RADIO_SOUND_STOP_TUNE ); + + // Are we still turned on? + g_pGame->GetAudio ()->StartRadio ( m_Channel ); + } + } + + // If we should be playing, start the radio and vice versa if ( bCanHearRadio && !IsPlaying () ) Start (); else if ( !bCanHearRadio && IsPlaying () ) Stop (); } @@ -59,31 +96,42 @@ void CClientRadio::Render ( void ) // Are we live n kickin? if ( IsPlaying () ) { - // Only visible for 2.5secs after turning on or changing station + // Tuning takes 2.5secs and we display for another 2.5secs afterward unsigned long ulTick = GetTickCount (); - if ( m_ulChangeTick && ulTick <= ( m_ulChangeTick + 2500 ) ) - { - char * channelName = GetChannelName (); - if ( channelName ) + unsigned long ulDisplayTime = CHANNEL_DISPLAY_TIME; + if ( m_bTuneForThisChannel ) ulDisplayTime += CHANNEL_TUNE_TIME; + + // Are we still displaying? + if ( m_ulChangeTick && ulTick <= ( m_ulChangeTick + ulDisplayTime ) ) + { + // We dont display the police channel + if ( m_Channel != CHANNEL_POLICE ) { - // Position and scale correction for resolution - CVector2D vecRes = g_pCore->GetGUI ()->GetResolution (); - float fX = RADIO_POS_X * vecRes.fX, fY = RADIO_POS_Y * vecRes.fY; - float fScaleX = RADIO_SCALE_X * ( vecRes.fX / 800.0f ), fScaleY = RADIO_SCALE_Y * ( vecRes.fY / 600.0f ); - - CFont * pFont = g_pGame->GetFont (); - pFont->SetFontStyle ( 2 ); - pFont->SetJustify ( 0 ); - pFont->SetBackground ( 0, 0 ); - pFont->SetScale ( fScaleX, fScaleY ); - pFont->SetProportional ( 1 ); - pFont->SetOrientation ( 0 ); - pFont->SetRightJustifyWrap ( 0 ); - pFont->SetEdge ( 1 ); - pFont->SetDropColor ( RADIO_DROP_COLOR ); - pFont->SetColor ( RADIO_COLOR ); - pFont->PrintString ( fX, fY, channelName ); - pFont->DrawFonts (); + const char * channelName = GetChannelName (); + if ( channelName ) + { + unsigned long fontColor = ( m_bTuning ) ? RADIO_TUNE_COLOR : RADIO_COLOR; + + // Position and scale correction for resolution + CVector2D vecRes = g_pCore->GetGUI ()->GetResolution (); + float fX = RADIO_POS_X * vecRes.fX, fY = RADIO_POS_Y * vecRes.fY; + float fScaleX = RADIO_SCALE_X * ( vecRes.fX / 800.0f ), fScaleY = RADIO_SCALE_Y * ( vecRes.fY / 600.0f ); + + // Draw the radio channel name + CFont * pFont = g_pGame->GetFont (); + pFont->SetFontStyle ( 2 ); + pFont->SetJustify ( 0 ); + pFont->SetBackground ( 0, 0 ); + pFont->SetScale ( fScaleX, fScaleY ); + pFont->SetProportional ( 1 ); + pFont->SetOrientation ( 0 ); + pFont->SetRightJustifyWrap ( 0 ); + pFont->SetEdge ( 1 ); + pFont->SetDropColor ( RADIO_DROP_COLOR ); + pFont->SetColor ( fontColor ); + pFont->PrintString ( fX, fY, const_cast < char * > ( channelName ) ); + pFont->DrawFonts (); + } } } } @@ -92,24 +140,39 @@ void CClientRadio::Render ( void ) bool CClientRadio::IsPlaying ( void ) { - return m_bIsPlaying; + return m_bPlaying; } void CClientRadio::Start ( void ) { - if ( !m_bPoliceRadio && m_Channel == CHANNEL_POLICE ) m_Channel = CHANNEL_PLAYBACK_FM; + // If we have a police channel, set us to it! ..and vice versa + if ( m_bPoliceRadio && m_Channel != CHANNEL_POLICE ) + { + // Save our current channel + m_PreviousChannel = m_Channel; + m_Channel = CHANNEL_POLICE; + } + // Restore our previous channel? + else if ( !m_bPoliceRadio && m_Channel == CHANNEL_POLICE ) m_Channel = m_PreviousChannel; - g_pGame->GetAudio ()->StartRadio ( ( unsigned int ) m_Channel ); - m_bIsPlaying = true; + // Start the radio on our current channel + g_pGame->GetAudio ()->StartRadio ( m_Channel ); + m_bPlaying = true; + m_bTuning = false; + m_bTuneForThisChannel = false; m_ulChangeTick = GetTickCount (); } void CClientRadio::Stop ( void ) { + // Stop the radio g_pGame->GetAudio ()->StopRadio (); - m_bIsPlaying = false; + if ( m_bTuning ) g_pGame->GetAudio ()->PlayFrontEndSound ( RADIO_SOUND_STOP_TUNE ); + m_bPlaying = false; + m_bTuning = false; + m_bTuneForThisChannel = false; } @@ -128,39 +191,99 @@ eRadioChannel CClientRadio::GetLastChannel ( void ) void CClientRadio::SetChannel ( eRadioChannel channel ) { - m_Channel = channel; - if ( m_bIsPlaying ) + // Different channel? + if ( channel != m_Channel ) + { + CClientPlayer * pLocalPlayer = m_pManager->GetPlayerManager ()->GetLocalPlayer (); + if ( pLocalPlayer ) + { + // Call the radio switch event on the local player + CLuaArguments Arguments; + Arguments.PushNumber ( ( unsigned char ) channel ); + if ( pLocalPlayer->CallEvent ( "onClientPlayerRadioSwitch", Arguments, true ) ) + { + m_bTuning = m_bTuneForThisChannel = DoTuneForChannel ( channel ); + m_ulChangeTick = GetTickCount (); + m_Channel = channel; + + // Save our current radio status by calling StopRadio + g_pGame->GetAudio ()->StopRadio (); + + // Does this channel need to be tuned in first? + if ( m_bTuneForThisChannel ) + { + // Sound fx + g_pGame->GetAudio ()->PlayFrontEndSound ( RADIO_SOUND_TUNE ); + } + // If not select it right now + else + { + // Sound fx + g_pGame->GetAudio ()->PlayFrontEndSound ( RADIO_SOUND_STOP_TUNE ); + g_pGame->GetAudio ()->PlayFrontEndSound ( RADIO_SOUND_SELECT ); + + // Save our current radio status by calling StopRadio + g_pGame->GetAudio ()->StopRadio (); + g_pGame->GetAudio ()->StartRadio ( m_Channel ); + } + } + } + } +} + + +bool CClientRadio::CanChangeChannel ( void ) +{ + // We must be playing and not have a police a radio + if ( m_bPlaying && !m_bPoliceRadio ) return true; + return false; +} + + +const char * CClientRadio::GetChannelName ( void ) +{ + return GetChannelName ( m_Channel ); +} + + +const char * CClientRadio::GetChannelName ( eRadioChannel channel ) +{ + if ( channel < NUM_RADIO_CHANNELS ) { - g_pGame->GetAudio ()->StartRadio ( m_Channel ); - m_ulChangeTick = GetTickCount (); + return m_ChannelNames [ channel ]; } + return NULL; } -char * CClientRadio::GetChannelName ( void ) +bool CClientRadio::DoTuneForChannel ( eRadioChannel channel ) { - if ( m_Channel == CHANNEL_POLICE ) return "Police"; - return g_pGame->GetAERadioTrackManager ()->GetRadioStationName ( ( BYTE ) m_Channel ); + if ( channel == CHANNEL_RADIO_OFF || channel == CHANNEL_USER_TRACK_PLAYER ) return false; + return true; } void CClientRadio::NextChannel ( void ) { - if ( m_bIsPlaying ) + // Can we change channel now? + if ( CanChangeChannel () ) { - if ( m_Channel == GetLastChannel () ) m_Channel = GetFirstChannel (); - else m_Channel = eRadioChannel ( m_Channel + 1 ); - SetChannel ( m_Channel ); + eRadioChannel channel = m_Channel; + if ( channel == GetLastChannel () ) channel = GetFirstChannel (); + else channel = eRadioChannel ( channel + 1 ); + SetChannel ( channel ); } } void CClientRadio::PreviousChannel ( void ) { - if ( m_bIsPlaying ) + // Can we change channel now? + if ( CanChangeChannel () ) { - if ( m_Channel == GetFirstChannel () ) m_Channel = GetLastChannel (); - else m_Channel = eRadioChannel ( m_Channel - 1 ); - SetChannel ( m_Channel ); + eRadioChannel channel = m_Channel; + if ( channel == GetFirstChannel () ) channel = GetLastChannel (); + else channel = eRadioChannel ( channel - 1 ); + SetChannel ( channel ); } } \ No newline at end of file diff --git a/MTA10/mods/shared_logic/CClientRadio.h b/MTA10/mods/shared_logic/CClientRadio.h index 53fa5025ff..2c6bb96c29 100644 --- a/MTA10/mods/shared_logic/CClientRadio.h +++ b/MTA10/mods/shared_logic/CClientRadio.h @@ -32,6 +32,8 @@ enum eRadioChannel CHANNEL_RADIO_OFF, }; +#define NUM_RADIO_CHANNELS ( CHANNEL_RADIO_OFF + 1 ) + class CClientRadio { public: @@ -50,7 +52,12 @@ class CClientRadio inline eRadioChannel GetChannel ( void ) { return m_Channel; } void SetChannel ( eRadioChannel channel ); - char * GetChannelName ( void ); + bool CanChangeChannel ( void ); + + const char * GetChannelName ( void ); + const char * GetChannelName ( eRadioChannel channel ); + + bool DoTuneForChannel ( eRadioChannel channel ); void NextChannel ( void ); void PreviousChannel ( void ); @@ -58,9 +65,14 @@ class CClientRadio private: CClientManager * m_pManager; eRadioChannel m_Channel; - bool m_bIsPlaying; + eRadioChannel m_PreviousChannel; + bool m_bPlaying; + bool m_bTuning; + bool m_bTuneForThisChannel; unsigned long m_ulChangeTick; bool m_bPoliceRadio; + + static char * m_ChannelNames [ NUM_RADIO_CHANNELS ]; }; diff --git a/MTA10/mods/shared_logic/CClientSound.cpp b/MTA10/mods/shared_logic/CClientSound.cpp index cd450d0394..1eb54a3337 100644 --- a/MTA10/mods/shared_logic/CClientSound.cpp +++ b/MTA10/mods/shared_logic/CClientSound.cpp @@ -138,12 +138,12 @@ float CClientSound::GetVolume ( void ) } void CClientSound::SetVolume ( float fVolume ) -{ - m_fVolume = fVolume; +{ if ( m_pSound && !m_b3D && m_usDimension == m_pManager->GetSoundManager ()->GetDimension () ) { m_pSound->setVolume ( fVolume ); } + m_fVolume = fVolume; } void CClientSound::SetPosition ( const CVector& vecPosition ) @@ -168,15 +168,6 @@ void CClientSound::SetDimension ( unsigned short usDimension ) void CClientSound::RelateDimension ( unsigned short usDimension ) { - if ( usDimension == m_usDimension ) - { - SetVolume ( m_fVolume ); - } - else - { - m_fVolume = GetVolume (); - SetVolume ( 0.0f ); - } } void CClientSound::SetMinDistance ( float fDistance ) @@ -219,43 +210,52 @@ void CClientSound::Process3D ( CVector vecPosition, CVector vecLookAt ) if ( m_pSound ) { - // Pan - CVector vecLook = vecLookAt - vecPosition; - CVector vecSound = m_vecPosition - vecPosition; - vecLook.fZ = vecSound.fZ = 0.0f; - vecLook.Normalize (); - vecSound.Normalize (); - - vecLook.CrossProduct ( &vecSound ); - // The length of the cross product (which is simply fZ in this case) - // is equal to the sine of the angle between the vectors - float fPan = vecLook.fZ; - if ( fPan < -1.0f + SOUND_PAN_THRESHOLD ) - fPan = -1.0f + SOUND_PAN_THRESHOLD; - else if ( fPan > 1.0f - SOUND_PAN_THRESHOLD ) - fPan = 1.0f - SOUND_PAN_THRESHOLD; - - m_pSound->setPan ( fPan ); - - // Volume - float fDistance = DistanceBetweenPoints3D ( vecPosition, m_vecPosition ); - float fSilenceDistance = m_fMinDistance * 20.0f; - float fVolume = 1.0; - - if ( fDistance <= m_fMinDistance ) - { - fVolume = 1.0f; - } - else if ( fDistance >= fSilenceDistance ) - { - fVolume = 0.0f; - } - else + if ( CanWeHearSound () ) { - float fLinear = (fSilenceDistance - fDistance) / fSilenceDistance; - fVolume = sqrt ( fLinear ) * fLinear; + // Pan + CVector vecLook = vecLookAt - vecPosition; + CVector vecSound = m_vecPosition - vecPosition; + vecLook.fZ = vecSound.fZ = 0.0f; + vecLook.Normalize (); + vecSound.Normalize (); + + vecLook.CrossProduct ( &vecSound ); + // The length of the cross product (which is simply fZ in this case) + // is equal to the sine of the angle between the vectors + float fPan = vecLook.fZ; + if ( fPan < -1.0f + SOUND_PAN_THRESHOLD ) + fPan = -1.0f + SOUND_PAN_THRESHOLD; + else if ( fPan > 1.0f - SOUND_PAN_THRESHOLD ) + fPan = 1.0f - SOUND_PAN_THRESHOLD; + + m_pSound->setPan ( fPan ); + + // Volume + float fDistance = DistanceBetweenPoints3D ( vecPosition, m_vecPosition ); + float fSilenceDistance = m_fMinDistance * 20.0f; + float fVolume = 1.0; + + if ( fDistance <= m_fMinDistance ) + { + fVolume = 1.0f; + } + else if ( fDistance >= fSilenceDistance ) + { + fVolume = 0.0f; + } + else + { + float fLinear = (fSilenceDistance - fDistance) / fSilenceDistance; + fVolume = sqrt ( fLinear ) * fLinear; + } + m_pSound->setVolume ( m_fVolume * fVolume ); } - - m_pSound->setVolume ( m_fVolume * fVolume ); + else m_pSound->setVolume ( 0.0f ); } +} + + +bool CClientSound::CanWeHearSound ( void ) +{ + return ( m_fVolume > 0 && m_usDimension == m_pManager->GetSoundManager ()->GetDimension () ); } \ No newline at end of file diff --git a/MTA10/mods/shared_logic/CClientSound.h b/MTA10/mods/shared_logic/CClientSound.h index 89648d544b..5e90ad3403 100644 --- a/MTA10/mods/shared_logic/CClientSound.h +++ b/MTA10/mods/shared_logic/CClientSound.h @@ -63,6 +63,7 @@ class CClientSound : public CClientEntity void SetDimension ( unsigned short usDimension ); void RelateDimension ( unsigned short usDimension ); + bool CanWeHearSound ( void ); protected: diff --git a/MTA10/mods/shared_logic/CClientSoundManager.cpp b/MTA10/mods/shared_logic/CClientSoundManager.cpp index 3ef53deed3..018b60b308 100644 --- a/MTA10/mods/shared_logic/CClientSoundManager.cpp +++ b/MTA10/mods/shared_logic/CClientSoundManager.cpp @@ -75,7 +75,7 @@ void CClientSoundManager::DoPulse ( void ) else { list < CClientSound* > ::iterator iter = m_Sounds.begin (); - for ( ; iter != m_Sounds.end () ; iter++ ) + for ( ; iter != m_Sounds.end () ; ++iter ) { (*iter)->Process3D ( vecPosition, vecLookAt ); } diff --git a/MTA10/mods/shared_logic/CClientStreamer.cpp b/MTA10/mods/shared_logic/CClientStreamer.cpp index 6bb1510b79..c905303753 100644 --- a/MTA10/mods/shared_logic/CClientStreamer.cpp +++ b/MTA10/mods/shared_logic/CClientStreamer.cpp @@ -181,12 +181,19 @@ void CClientStreamer::ConnectRow ( CClientStreamSectorRow * pRow ) pRow->GetPosition ( fTop, fBottom ); // Connect up our row - pRow->m_pTop = FindRow ( fTop + ( ROW_SIZE / 2.0f ) ); - pRow->m_pBottom = FindRow ( fBottom - ( ROW_SIZE / 2.0f ) ); + CClientStreamSectorRow * pTop = FindRow ( fTop + ( ROW_SIZE / 2.0f ) ); + CClientStreamSectorRow * pBottom = FindRow ( fBottom - ( ROW_SIZE / 2.0f ) ); - // Connect the other rows to us - if ( pRow->m_pTop ) pRow->m_pTop->m_pBottom = pRow; - if ( pRow->m_pBottom ) pRow->m_pBottom->m_pTop = pRow; + if ( pTop && pTop != pRow ) + { + pRow->m_pTop = pTop; + pTop->m_pBottom = pRow; + } + if ( pBottom && pBottom != pRow ) + { + pRow->m_pBottom = pBottom; + pBottom->m_pTop = pRow; + } } diff --git a/MTA10/mods/shared_logic/CClientVehicle.cpp b/MTA10/mods/shared_logic/CClientVehicle.cpp index 11dc1e4888..0843ea7de2 100644 --- a/MTA10/mods/shared_logic/CClientVehicle.cpp +++ b/MTA10/mods/shared_logic/CClientVehicle.cpp @@ -117,6 +117,8 @@ CClientVehicle::CClientVehicle ( CClientManager* pManager, ElementID ID, unsigne m_bJustBlewUp = false; m_ucAlpha = 255; m_bAlphaChanged = false; + m_bHasTargetPosition = false; + m_bHasTargetRotation = false; m_bBlowNextFrame = false; m_bIsOnGround = false; m_ulIllegalTowBreakTime = 0; @@ -138,8 +140,9 @@ CClientVehicle::CClientVehicle ( CClientManager* pManager, ElementID ID, unsigne m_szLastSyncType = "none"; #endif - m_interp.rot.ulFinishTime = 0; - m_interp.pos.ulFinishTime = 0; + m_bInterpolationEnabled = false; + m_dResetInterpolationTime = 0; + ResetInterpolation (); // Check if we have landing gears @@ -177,19 +180,15 @@ CClientVehicle::~CClientVehicle ( void ) // Unreference us from the driving player model (if any) if ( m_pDriver ) { - m_pDriver->m_pOccupiedVehicle = NULL; - m_pDriver->m_pOccupyingVehicle = NULL; - m_pDriver->SetVehicleInOutState ( VEHICLE_INOUT_NONE ); + UnpairPedAndVehicle( m_pDriver, this ); } // And the occupying ones eventually if ( m_pOccupyingDriver ) { - m_pOccupyingDriver->m_pOccupiedVehicle = NULL; - m_pOccupyingDriver->m_pOccupyingVehicle = NULL; - m_pOccupyingDriver->SetVehicleInOutState ( VEHICLE_INOUT_NONE ); + UnpairPedAndVehicle( m_pOccupyingDriver, this ); } // And the passenger models @@ -198,11 +197,9 @@ CClientVehicle::~CClientVehicle ( void ) { if ( m_pPassengers [i] ) { - m_pPassengers [i]->m_pOccupiedVehicle = NULL; - m_pPassengers [i]->m_pOccupyingVehicle = NULL; m_pPassengers [i]->m_uiOccupiedVehicleSeat = 0; - m_pPassengers [i]->SetVehicleInOutState ( VEHICLE_INOUT_NONE ); + UnpairPedAndVehicle( m_pPassengers [i], this ); } } @@ -211,11 +208,9 @@ CClientVehicle::~CClientVehicle ( void ) { if ( m_pOccupyingPassengers [i] ) { - m_pOccupyingPassengers [i]->m_pOccupiedVehicle = NULL; - m_pOccupyingPassengers [i]->m_pOccupyingVehicle = NULL; m_pOccupyingPassengers [i]->m_uiOccupiedVehicleSeat = 0; - m_pOccupyingPassengers [i]->SetVehicleInOutState ( VEHICLE_INOUT_NONE ); + UnpairPedAndVehicle( m_pOccupyingPassengers [i], this ); } } @@ -325,7 +320,7 @@ void CClientVehicle::SetWas ( const CVector &vecWas ) } -void CClientVehicle::SetPosition ( const CVector& vecPosition, bool bResetInterpolation ) +void CClientVehicle::SetPosition ( const CVector& vecPosition ) { if ( m_pVehicle ) { @@ -365,8 +360,7 @@ void CClientVehicle::SetPosition ( const CVector& vecPosition, bool bResetInterp } // Reset interpolation - if ( bResetInterpolation ) - RemoveTargetPosition (); + RemoveTargetPosition (); } @@ -393,7 +387,7 @@ void CClientVehicle::GetRotationRadians ( CVector& vecRotation ) const } -void CClientVehicle::SetRotationDegrees ( const CVector& vecRotation, bool bResetInterpolation ) +void CClientVehicle::SetRotationDegrees ( const CVector& vecRotation ) { // Convert from degrees to radians CVector vecTemp; @@ -402,11 +396,11 @@ void CClientVehicle::SetRotationDegrees ( const CVector& vecRotation, bool bRese vecTemp.fZ = vecRotation.fZ * 3.1415926535897932384626433832795f / 180.0f; // Set the rotation as radians - SetRotationRadians ( vecTemp, bResetInterpolation ); + SetRotationRadians ( vecTemp ); } -void CClientVehicle::SetRotationRadians ( const CVector& vecRotation, bool bResetInterpolation ) +void CClientVehicle::SetRotationRadians ( const CVector& vecRotation ) { // Grab the matrix, apply the rotation to it and set it again // ChrML: We flip the actual rotation direction so that the rotation is consistent with @@ -417,8 +411,7 @@ void CClientVehicle::SetRotationRadians ( const CVector& vecRotation, bool bRese SetMatrix ( matTemp ); // Reset target rotatin - if ( bResetInterpolation ) - RemoveTargetRotation (); + RemoveTargetRotation (); } @@ -1187,8 +1180,7 @@ void CClientVehicle::_SetAdjustablePropertyValue ( unsigned short usValue ) m_pVehicle->SetAdjustablePropertyValue ( usValue ); // Update our collision for this adjustable? - if ( m_usModel == VT_FORKLIFT || m_usModel == VT_FIRELA || m_usModel == VT_ANDROM || - m_usModel == VT_DUMPER || m_usModel == VT_DOZER ) + if ( HasMovingCollision () ) { float fAngle = ( float ) usValue / 2499.0f; m_pVehicle->UpdateMovingCollision ( fAngle ); @@ -1198,6 +1190,14 @@ void CClientVehicle::_SetAdjustablePropertyValue ( unsigned short usValue ) m_usAdjustablePropertyValue = usValue; } + +bool CClientVehicle::HasMovingCollision ( void ) +{ + return ( m_usModel == VT_FORKLIFT || m_usModel == VT_FIRELA || m_usModel == VT_ANDROM || + m_usModel == VT_DUMPER || m_usModel == VT_DOZER || m_usModel == VT_PACKER ); +} + + unsigned char CClientVehicle::GetDoorStatus ( unsigned char ucDoor ) { if ( ucDoor < MAX_DOORS ) @@ -1589,6 +1589,8 @@ void CClientVehicle::SetFrozen ( bool bFrozen ) if ( m_bScriptFrozen && bFrozen ) { m_bIsFrozen = bFrozen; + SetStatic ( bFrozen ); + CVector vecTemp; if ( m_pVehicle ) { @@ -1606,6 +1608,7 @@ void CClientVehicle::SetFrozen ( bool bFrozen ) else if ( !m_bScriptFrozen ) { m_bIsFrozen = bFrozen; + SetStatic ( bFrozen ); if ( bFrozen ) { @@ -1623,7 +1626,7 @@ void CClientVehicle::SetFrozen ( bool bFrozen ) m_vecTurnSpeed = vecTemp; } } - } + } } @@ -1993,15 +1996,15 @@ void CClientVehicle::Create ( void ) m_pVehicle->SetStoredPointer ( this ); // Jump straight to the target position if we have one - if ( HasTargetPosition () ) + if ( m_bHasTargetPosition ) { - GetTargetPosition ( m_Matrix.vPos ); + m_Matrix.vPos = m_vecTargetPosition; } // Jump straight to the target rotation if we have one - if ( HasTargetRotation () ) + if ( m_bHasTargetRotation ) { - CVector vecTemp = m_interp.rot.vecTarget; + CVector vecTemp = m_vecTargetRotation; ConvertDegreesToRadians ( vecTemp ); g_pMultiplayer->ConvertEulerAnglesToMatrix ( m_Matrix, ( 2 * PI ) - vecTemp.fX, ( 2 * PI ) - vecTemp.fY, ( 2 * PI ) - vecTemp.fZ ); } @@ -2009,6 +2012,7 @@ void CClientVehicle::Create ( void ) // Got any settings to restore? m_pVehicle->SetMatrix ( &m_Matrix ); m_matFrozen = m_Matrix; + SetStatic ( m_bIsFrozen ); m_pVehicle->SetMoveSpeed ( &m_vecMoveSpeed ); m_pVehicle->SetTurnSpeed ( &m_vecTurnSpeed ); m_pVehicle->SetVisible ( m_bVisible ); @@ -2694,12 +2698,30 @@ void CClientVehicle::SetSmokeTrailEnabled ( bool bEnabled ) void CClientVehicle::ResetInterpolation ( void ) { - if ( HasTargetPosition () ) - SetPosition ( m_interp.pos.vecTarget ); - if ( HasTargetRotation () ) - SetRotationDegrees ( m_interp.rot.vecTarget ); - m_interp.pos.ulFinishTime = 0; - m_interp.rot.ulFinishTime = 0; + float f[3]; + double dCurrentTime = CClientTime::GetTimeNano (); + + // Reset the extrapolator with the pure matrix + f[0] = m_MatrixPure.vPos.fX; + f[1] = m_MatrixPure.vPos.fY; + f[2] = m_MatrixPure.vPos.fZ; +// m_Extrapolator.Reset ( dCurrentTime, dCurrentTime, f ); + + // Set LERP factor to 1 + m_fLERP = LERP_UNUSED; + + // Reset the source and destination quaternions + m_QuatA = m_QuatB = CQuat ( &m_MatrixPure ); + + // Turn off interpolation for the first little bit + m_bInterpolationEnabled = false; + + // Store the last reset time, so we know when to turn interpolation back on + m_dResetInterpolationTime = dCurrentTime; + +#ifdef MTA_DEBUG_INTERPOLATION + g_pCore->GetGraphics()->DrawTextTTF(300,200,332,216,0xDDDDDDDD, "RESET", 1.0f, 0); +#endif } @@ -2787,139 +2809,124 @@ void CClientVehicle::GetInitialDoorStates ( unsigned char * pucDoorStates ) } -void CClientVehicle::SetTargetPosition ( CVector& vecPosition, unsigned long ulDelay, bool bExtrapolateAfterInterpolation ) +void CClientVehicle::SetTargetPosition ( CVector& vecPosition ) { // Are we streamed in? if ( m_pVehicle ) { - UpdateTargetPosition (); -#if 0 - if ( HasTargetPosition () ) - { - // We didn't have enough time to finish the interpolation, - // so we move the vehicle directly there and start from it. - SetPosition ( m_interp.pos.vecTarget, false ); - m_interp.pos.vecOrigin = m_interp.pos.vecTarget; - } - else -#endif - GetPosition ( m_interp.pos.vecOrigin ); - m_interp.pos.vecTarget = vecPosition; - - unsigned long ulTime = CClientTime::GetTime (); - m_interp.pos.ulStartTime = ulTime; - m_interp.pos.ulFinishTime = ulTime + ulDelay; - m_interp.pos.bExtrapolateAfterInterpolation = bExtrapolateAfterInterpolation; + CVector vecTemp; + GetPosition ( vecTemp ); + m_bTargetPositionDirections [ 0 ] = ( vecTemp.fX < vecPosition.fX ); + m_bTargetPositionDirections [ 1 ] = ( vecTemp.fY < vecPosition.fY ); + m_bTargetPositionDirections [ 2 ] = ( vecTemp.fZ < vecPosition.fZ ); + m_vecTargetPosition = vecPosition; + m_bHasTargetPosition = true; } else { - // Update our position now + // Update our position now and remove any previous target we had SetPosition ( vecPosition ); + m_bHasTargetPosition = false; } } void CClientVehicle::RemoveTargetPosition ( void ) { - m_interp.pos.ulFinishTime = 0; + m_bHasTargetPosition = false; } -void CClientVehicle::SetTargetRotation ( CVector& vecRotation, unsigned long ulDelay, bool bExtrapolateAfterInterpolation ) +void CClientVehicle::SetTargetRotation ( CVector& vecRotation ) { // Are we streamed in? if ( m_pVehicle ) { - UpdateTargetRotation (); - - GetRotationDegrees ( m_interp.rot.vecOrigin ); - m_interp.rot.vecTarget = vecRotation; - - // Pre-calculate offsets - m_interp.rot.vecOffset.fX = GetOffsetDegrees ( m_interp.rot.vecOrigin.fX, m_interp.rot.vecTarget.fX ); - m_interp.rot.vecOffset.fY = GetOffsetDegrees ( m_interp.rot.vecOrigin.fY, m_interp.rot.vecTarget.fY ); - m_interp.rot.vecOffset.fZ = GetOffsetDegrees ( m_interp.rot.vecOrigin.fZ, m_interp.rot.vecTarget.fZ ); - - unsigned long ulTime = CClientTime::GetTime (); - m_interp.rot.ulStartTime = ulTime; - m_interp.rot.ulFinishTime = ulTime + ulDelay; - m_interp.rot.bExtrapolateAfterInterpolation = bExtrapolateAfterInterpolation; + // Set our target rotation + m_vecTargetRotation = vecRotation; + m_bHasTargetRotation = true; } else { - // Update our rotation now + // Update our rotation now and remove any previous target we had SetRotationDegrees ( vecRotation ); + m_bHasTargetRotation = false; } } void CClientVehicle::RemoveTargetRotation ( void ) { - m_interp.rot.ulFinishTime = 0; + m_bHasTargetRotation = false; } +float fInterpolationStrengthXY = 12; +float fInterpolationStrengthZ = 12; +float fInterpolationStrengthR = 8; + void CClientVehicle::UpdateTargetPosition ( void ) { - if ( HasTargetPosition () ) + // Do we have a position to move towards? and are we streamed in? + if ( m_bHasTargetPosition && m_pVehicle ) { - // Grab the previous position to update contact peds - CVector vecPrevPos; - GetPosition ( vecPrevPos ); - - CVector vecNewPosition; - unsigned long ulCurrentTime = CClientTime::GetTime (); - - // Get the factor of time spent from the interpolation start - // to the current time. - float fAlpha = SharedUtil::Unlerp ( m_interp.pos.ulStartTime, - ulCurrentTime, - m_interp.pos.ulFinishTime ); + // Grab the vehicle's current position + CVector vecPosition, vecPreviousPosition; + GetPosition ( vecPosition ); + vecPreviousPosition = vecPosition; + + // Grab the x, y and z distance between target and the real position + CVector vecOffset = m_vecTargetPosition - vecPosition; + + // Grab the distance to between current point and real point + float fDistance = DistanceBetweenPoints3D ( m_vecTargetPosition, vecPosition ); + + /* Incredibly slow code + // Is there anything blocking our path to the target position? + CColPoint* pColPoint = NULL; + CEntity* pEntity = NULL; + bool bCollision = g_pGame->GetWorld ()->ProcessLineOfSight ( &vecPosition, + &m_vecTargetPosition, + &pColPoint, + &pEntity, + true, false, false, true, + false, false, false, false ); + + // Destroy the colpoint or we get a leak + if ( pColPoint ) pColPoint->Destroy (); + */ - // If the factor is bigger or equal to 1.0f, then - // we have finished interpolating. - if ( !m_interp.pos.bExtrapolateAfterInterpolation && - fAlpha >= 1.0f ) + // If the distance is above our warping threshold + if ( fDistance > INTERPOLATION_WARP_THRESHOLD ) { - m_interp.pos.ulFinishTime = 0; - vecNewPosition = m_interp.pos.vecTarget; + // Warp to the target + vecPosition = m_vecTargetPosition; + if ( m_bHasTargetRotation ) + SetRotationDegrees ( m_vecTargetRotation ); } else { - vecNewPosition = SharedUtil::Lerp ( m_interp.pos.vecOrigin, - fAlpha, - m_interp.pos.vecTarget ); + // Calculate how much to interpolate and add it as long as this is the direction we're interpolating + vecOffset /= CVector ( fInterpolationStrengthXY, fInterpolationStrengthXY, fInterpolationStrengthZ ); + //if ( ( vecOffset.fX > 0.0f ) == m_bTargetPositionDirections [ 0 ] ) + vecPosition.fX += vecOffset.fX; + //if ( ( vecOffset.fY > 0.0f ) == m_bTargetPositionDirections [ 1 ] ) + vecPosition.fY += vecOffset.fY; + //if ( ( vecOffset.fZ > 0.0f ) == m_bTargetPositionDirections [ 2 ] ) + vecPosition.fZ += vecOffset.fZ; } - SetPosition ( vecNewPosition, false ); -#ifdef MTA_DEBUG - if ( g_pClientGame->IsShowingInterpolation () && - g_pClientGame->GetLocalPlayer ()->GetOccupiedVehicle () == this ) - { - // DEBUG - SString strBuffer ( "-== Vehicle interpolation ==-\n" - "vecOrigin: %f %f %f\n" - "vecTarget: %f %f %f\n" - "Position: %f %f %f\n" - "Alpha: %f\n" - "Interpolating: %s\n", - m_interp.pos.vecOrigin.fX, m_interp.pos.vecOrigin.fY, m_interp.pos.vecOrigin.fZ, - m_interp.pos.vecTarget.fX, m_interp.pos.vecTarget.fY, m_interp.pos.vecTarget.fZ, - vecNewPosition.fX, vecNewPosition.fY, vecNewPosition.fZ, - fAlpha, ( m_interp.pos.ulFinishTime == 0 ? "no" : "yes" ) ); - g_pClientGame->GetManager ()->GetDisplayManager ()->DrawText2D ( strBuffer, CVector ( 0.45f, 0.05f, 0 ), 1.0f, 0xFFBBBBFF ); - } -#endif + // Set the new position + m_pVehicle->SetPosition ( const_cast < CVector* > ( &vecPosition ) ); // Update our contact players CVector vecPlayerPosition; - CVector vecOffset; list < CClientPed * > ::iterator iter = m_Contacts.begin (); for ( ; iter != m_Contacts.end () ; iter++ ) { CClientPed * pModel = *iter; pModel->GetPosition ( vecPlayerPosition ); - vecOffset = vecPlayerPosition - vecPrevPos; - vecPlayerPosition = vecNewPosition + vecOffset; + vecOffset = vecPlayerPosition - vecPreviousPosition; + vecPlayerPosition = vecPosition + vecOffset; pModel->SetPosition ( vecPlayerPosition ); } } @@ -2929,33 +2936,42 @@ void CClientVehicle::UpdateTargetPosition ( void ) void CClientVehicle::UpdateTargetRotation ( void ) { // Do we have a rotation to move towards? and are we streamed in? - if ( HasTargetRotation () ) + if ( m_bHasTargetRotation && m_pVehicle ) { - CVector vecNewRotation; - unsigned long ulCurrentTime = CClientTime::GetTime (); + CVector vecRotation; + GetRotationDegrees ( vecRotation ); + + CVector vecOffset; + vecOffset.fX = GetOffsetDegrees ( vecRotation.fX, m_vecTargetRotation.fX ); + vecOffset.fY = GetOffsetDegrees ( vecRotation.fY, m_vecTargetRotation.fY ); + vecOffset.fZ = GetOffsetDegrees ( vecRotation.fZ, m_vecTargetRotation.fZ ); - // Get the factor of time spent from the interpolation start - // to the current time. - float fAlpha = SharedUtil::Unlerp ( m_interp.rot.ulStartTime, - ulCurrentTime, - m_interp.rot.ulFinishTime ); + vecOffset /= CVector ( fInterpolationStrengthR, fInterpolationStrengthR, fInterpolationStrengthR ); + vecRotation += vecOffset; - // If the factor is bigger or equal to 1.0f, then - // we have finished interpolating. - if ( !m_interp.rot.bExtrapolateAfterInterpolation && - fAlpha >= 1.0f ) - { - m_interp.rot.ulFinishTime = 0; - vecNewRotation = m_interp.rot.vecTarget; - } - else + SetRotationDegrees ( vecRotation ); + + CVector vecPosition; + GetPosition ( vecPosition ); + + // Update our contact players + CVector vecPlayerPosition, vecPlayerOffset, vecOffsetRadians = vecOffset; + ConvertDegreesToRadians ( vecOffsetRadians ); + CClientPed * pPed; + list < CClientPed * > ::iterator iter = m_Contacts.begin (); + for ( ; iter != m_Contacts.end () ; iter++ ) { - vecNewRotation = SharedUtil::Lerp ( CVector (), - fAlpha, - m_interp.rot.vecOffset ); - vecNewRotation += m_interp.rot.vecOrigin; - } - SetRotationDegrees ( vecNewRotation, false ); + pPed = *iter; + pPed->GetPosition ( vecPlayerPosition ); + + vecPlayerOffset = vecPlayerPosition - vecPosition; + RotateVector ( vecPlayerOffset, -vecOffsetRadians ); + vecPlayerPosition = vecPosition + vecPlayerOffset; + pPed->SetPosition ( vecPlayerPosition ); + } + + // SetRotationDegrees clears m_bHasTargetRotation, and we don't want that + m_bHasTargetRotation = true; } } @@ -3008,6 +3024,34 @@ bool CClientVehicle::HasPoliceRadio ( void ) return false; } + +void CClientVehicle::DoTankFire ( void ) +{ + if ( m_pVehicle && m_usModel == VT_RHINO ) + { + // Our turret offset + CVector vecOffset ( 0, 6.5f, 1.4f ); + + // Apply turret rotation + float turretX, turretY; + GetTurretRotation ( turretX, turretY ); + RotateVector ( vecOffset, CVector ( -turretY, 0, -turretX ) ); + + // Apply vehicle rotation + CMatrix matrix, returnMatrix; + GetMatrix ( matrix ); + AttachedMatrix ( matrix, returnMatrix, vecOffset, CVector () ); + + // Grab turret firing direction + CVector vecDirection = returnMatrix.vPos - matrix.vPos; + vecDirection.Normalize (); + + // Fiiiiiiiire! + g_pGame->GetFx ()->TriggerTankFire ( returnMatrix.vPos, vecDirection ); + } +} + + void CClientVehicle::RemoveAllProjectiles ( void ) { CClientProjectile * pProjectile = NULL; @@ -3047,4 +3091,277 @@ void CClientVehicle::SetHeadLightColor ( RGBA color ) m_pVehicle->SetHeadLightColor ( color ); } m_HeadLightColor = color; -} \ No newline at end of file +} + + +// +// Below here is basically awful. +// But there you go. +// + +#if MTA_DEBUG + #define INFO(x) g_pCore->GetConsole ()->Printf x + #define WARN(x) g_pCore->GetConsole ()->Printf x +#else + #define INFO(x) {} + #define WARN(x) {} +#endif + +std::string GetPlayerName ( CClientPed* pClientPed ) +{ + if ( !pClientPed ) + return "null"; + if ( IS_PLAYER ( pClientPed ) ) + { + CClientPlayer* pPlayer = static_cast < CClientPlayer * > ( pClientPed ); + return pPlayer->GetNick (); + } + return "ped"; +} + +// +// Make a ped become an occupied driver/passenger +// Static function +// +void CClientVehicle::SetPedOccupiedVehicle ( CClientPed* pClientPed, CClientVehicle* pVehicle, unsigned int uiSeat ) +{ + INFO (( "SetPedOccupiedVehicle:%s in vehicle:0x%08x seat:%d", GetPlayerName( pClientPed ).c_str (), pVehicle, uiSeat )); + + if ( !pClientPed || !pVehicle ) + return; + + // Clear ped from any current occupied seat in this vehicle + if ( pClientPed->m_pOccupiedVehicle == pVehicle ) + { + if ( pVehicle->m_pDriver == pClientPed ) + pVehicle->m_pDriver = NULL; + + for ( int i = 0 ; i < NUMELMS ( pVehicle->m_pPassengers ) ; i++ ) + if ( pVehicle->m_pPassengers[i] == pClientPed ) + pVehicle->m_pPassengers[i] = NULL; + } + + // Vehicle vars + if ( uiSeat == 0 ) + { + if ( pVehicle->m_pDriver && pVehicle->m_pDriver != pClientPed ) + { + WARN (( "Emergency occupied driver eject by %s on %s\n", GetPlayerName( pClientPed ).c_str (), GetPlayerName( pVehicle->m_pDriver ).c_str () )); + UnpairPedAndVehicle ( pVehicle->m_pDriver, pVehicle ); + } + pVehicle->m_pDriver = pClientPed; + } + else + { + assert ( uiSeat <= NUMELMS(pVehicle->m_pPassengers) ); + if ( pVehicle->m_pPassengers [uiSeat-1] && pVehicle->m_pPassengers [uiSeat-1] != pClientPed ) + { + WARN (( "Emergency occupied passenger eject by %s on %s\n", GetPlayerName( pClientPed ).c_str (), GetPlayerName( pVehicle->m_pPassengers [uiSeat-1] ).c_str () )); + UnpairPedAndVehicle ( pVehicle->m_pPassengers [uiSeat-1], pVehicle ); + } + pVehicle->m_pPassengers [uiSeat-1] = pClientPed; + } + + // Ped vars + pClientPed->m_pOccupiedVehicle = pVehicle; + pClientPed->m_uiOccupiedVehicleSeat = uiSeat; + + // Checks + ValidatePedAndVehiclePair ( pClientPed, pVehicle ); +} + + +// +// Make a ped become an occupying driver/passenger +// Static function +// +void CClientVehicle::SetPedOccupyingVehicle ( CClientPed* pClientPed, CClientVehicle* pVehicle, unsigned int uiSeat ) +{ + INFO (( "SetPedOccupyingVehicle:%s in vehicle:0x%08x seat:%d", GetPlayerName( pClientPed ).c_str (), pVehicle, uiSeat )); + + if ( !pClientPed || !pVehicle ) + return; + + // Clear ped from any current occupying seat in this vehicle + if ( pClientPed->m_pOccupyingVehicle == pVehicle ) + { + if ( pVehicle->m_pOccupyingDriver == pClientPed ) + pVehicle->m_pOccupyingDriver = NULL; + + for ( int i = 0 ; i < NUMELMS ( pVehicle->m_pOccupyingPassengers ) ; i++ ) + if ( pVehicle->m_pOccupyingPassengers[i] == pClientPed ) + pVehicle->m_pOccupyingPassengers[i] = NULL; + } + + // Vehicle vars + if ( uiSeat == 0 ) + { + if ( pVehicle->m_pOccupyingDriver && pVehicle->m_pOccupyingDriver != pClientPed ) + { + WARN (( "Emergency occupying driver eject by %s on %s\n", GetPlayerName( pClientPed ).c_str (), GetPlayerName( pVehicle->m_pOccupyingDriver ).c_str () )); + UnpairPedAndVehicle ( pVehicle->m_pOccupyingDriver, pVehicle ); + } + pVehicle->m_pOccupyingDriver = pClientPed; + } + else + { + assert ( uiSeat <= NUMELMS(pVehicle->m_pOccupyingPassengers) ); + if ( pVehicle->m_pOccupyingPassengers [uiSeat-1] && pVehicle->m_pOccupyingPassengers [uiSeat-1] != pClientPed ) + { + WARN (( "Emergency occupying passenger eject by %s on %s\n", GetPlayerName( pClientPed ).c_str (), GetPlayerName( pVehicle->m_pOccupyingPassengers [uiSeat-1] ).c_str () )); + UnpairPedAndVehicle ( pVehicle->m_pOccupyingPassengers [uiSeat-1], pVehicle ); + } + pVehicle->m_pOccupyingPassengers [uiSeat-1] = pClientPed; + } + + // Ped vars + pClientPed->m_pOccupyingVehicle = pVehicle; +// if ( uiSeat >= 0 && uiSeat < 8 ) +// pClientPed->m_uiOccupyingSeat = uiSeat; + + // Checks + ValidatePedAndVehiclePair ( pClientPed, pVehicle ); +} + + +// +// Check ped <> vehicle pointers +// Static function +// +void CClientVehicle::ValidatePedAndVehiclePair( CClientPed* pClientPed, CClientVehicle* pVehicle ) +{ +#if MTA_DEBUG + // Occupied + // Vehicle vars + if ( pVehicle->m_pDriver ) + assert ( pVehicle->m_pDriver->m_pOccupiedVehicle == pVehicle ); + + for ( int i = 0 ; i < NUMELMS ( pVehicle->m_pPassengers ) ; i++ ) + if ( pVehicle->m_pPassengers[i] ) + assert ( pVehicle->m_pPassengers[i]->m_pOccupiedVehicle == pVehicle ); + + // Ped vars + if ( pClientPed->m_pOccupiedVehicle ) + { + // Make sure refed once by vehicle + int iCount = 0; + if ( pClientPed->m_pOccupiedVehicle->m_pDriver == pClientPed ) + iCount++; + + for ( int i = 0 ; i < NUMELMS ( pClientPed->m_pOccupiedVehicle->m_pPassengers ) ; i++ ) + if ( pClientPed->m_pOccupiedVehicle->m_pPassengers[i] == pClientPed ) + iCount++; + + assert ( iCount == 1 ); + } + + // Occupying + // Vehicle vars + if ( pVehicle->m_pOccupyingDriver ) + assert ( pVehicle->m_pOccupyingDriver->m_pOccupyingVehicle == pVehicle ); + + for ( int i = 0 ; i < NUMELMS ( pVehicle->m_pOccupyingPassengers ) ; i++ ) + if ( pVehicle->m_pOccupyingPassengers[i] ) + assert ( pVehicle->m_pOccupyingPassengers[i]->m_pOccupyingVehicle == pVehicle ); + + // Ped vars + if ( pClientPed->m_pOccupyingVehicle ) + { + // Make sure refed once by vehicle + int iCount = 0; + if ( pClientPed->m_pOccupyingVehicle->m_pOccupyingDriver == pClientPed ) + iCount++; + + for ( int i = 0 ; i < NUMELMS ( pClientPed->m_pOccupyingVehicle->m_pOccupyingPassengers ) ; i++ ) + if ( pClientPed->m_pOccupyingVehicle->m_pOccupyingPassengers[i] == pClientPed ) + iCount++; + + assert ( iCount == 1 ); + } +#endif +} + + +// +// Make sure there is no association between a ped and a vehicle +// Static function +// +void CClientVehicle::UnpairPedAndVehicle( CClientPed* pClientPed, CClientVehicle* pVehicle ) +{ + if ( !pClientPed || !pVehicle ) + return; + + // Checks + ValidatePedAndVehiclePair ( pClientPed, pVehicle ); + + // Occupied + // Vehicle vars + if ( pVehicle->m_pDriver == pClientPed ) + { + INFO (( "UnpairPedAndVehicle: m_pDriver:%s from vehicle:0x%08x", GetPlayerName( pClientPed ).c_str (), pVehicle )); + pVehicle->m_pDriver = NULL; + } + + + for ( int i = 0 ; i < NUMELMS ( pVehicle->m_pPassengers ) ; i++ ) + if ( pVehicle->m_pPassengers[i] == pClientPed ) + { + INFO (( "UnpairPedAndVehicle: m_pPassenger:%s seat:%d from vehicle:0x%08x", GetPlayerName( pClientPed ).c_str (), i + 1, pVehicle )); + pVehicle->m_pPassengers[i] = NULL; + } + + // Ped vars + if ( pClientPed->m_pOccupiedVehicle == pVehicle ) + { + INFO (( "UnpairPedAndVehicle: pClientPed:%s from m_pOccupiedVehicle:0x%08x", GetPlayerName( pClientPed ).c_str (), pVehicle )); + pClientPed->m_pOccupiedVehicle = NULL; + pClientPed->m_uiOccupiedVehicleSeat = 0xFF; + } + + // Occupying + // Vehicle vars + if ( pVehicle->m_pOccupyingDriver == pClientPed ) + { + INFO (( "UnpairPedAndVehicle: m_pOccupyingDriver:%s from vehicle:0x%08x", GetPlayerName( pClientPed ).c_str (), pVehicle )); + pVehicle->m_pOccupyingDriver = NULL; + } + + for ( int i = 0 ; i < NUMELMS ( pVehicle->m_pOccupyingPassengers ) ; i++ ) + if ( pVehicle->m_pOccupyingPassengers[i] == pClientPed ) + { + INFO (( "UnpairPedAndVehicle: m_pOccupyingPassenger:%s seat:%d from vehicle:0x%08x", GetPlayerName( pClientPed ).c_str (), i + 1, pVehicle )); + pVehicle->m_pOccupyingPassengers[i] = NULL; + } + + // Ped vars + if ( pClientPed->m_pOccupyingVehicle == pVehicle ) + { + INFO (( "UnpairPedAndVehicle: pClientPed:%s from m_pOccupyingVehicle:0x%08x", GetPlayerName( pClientPed ).c_str (), pVehicle )); + pClientPed->m_pOccupyingVehicle = NULL; + //pClientPed->m_uiOccupyingSeat = 0xFF; + } +} + + +// +// Make sure there is no association between a ped and its vehicle +// Static function +// +void CClientVehicle::UnpairPedAndVehicle( CClientPed* pClientPed ) +{ + UnpairPedAndVehicle ( pClientPed, pClientPed->GetOccupiedVehicle () ); + UnpairPedAndVehicle ( pClientPed, pClientPed->m_pOccupyingVehicle ); + UnpairPedAndVehicle ( pClientPed, pClientPed->GetRealOccupiedVehicle () ); + + if ( pClientPed->m_pOccupiedVehicle ) + { + WARN (( "*** Unexpected m_pOccupiedVehicle:0x%08x for %s\n", pClientPed->m_pOccupiedVehicle, GetPlayerName( pClientPed ).c_str () )); + pClientPed->m_pOccupiedVehicle = NULL; + } + + if ( pClientPed->m_pOccupyingVehicle ) + { + WARN (( "*** Unexpected m_pOccupyingVehicle:0x%08x for %s\n", pClientPed->m_pOccupyingVehicle, GetPlayerName( pClientPed ).c_str () )); + pClientPed->m_pOccupyingVehicle = NULL; + } +} diff --git a/MTA10/mods/shared_logic/CClientVehicle.h b/MTA10/mods/shared_logic/CClientVehicle.h index c941cc8202..617f5a6861 100644 --- a/MTA10/mods/shared_logic/CClientVehicle.h +++ b/MTA10/mods/shared_logic/CClientVehicle.h @@ -115,18 +115,15 @@ class CClientVehicle : public CClientStreamElement inline eClientVehicleType GetVehicleType ( void ) { return m_eVehicleType; }; void GetPosition ( CVector& vecPosition ) const; - void SetPosition ( const CVector& vecPosition ) { SetPosition ( vecPosition, true ); } - void SetPosition ( const CVector& vecPosition, bool bResetInterpolation ); + void SetPosition ( const CVector& vecPosition ); void SetRoll ( const CVector& vecRoll ); void SetDirection ( const CVector& vecDir ); void SetWas ( const CVector& vecWas ); void GetRotationDegrees ( CVector& vecRotation ) const; void GetRotationRadians ( CVector& vecRotation ) const; - void SetRotationDegrees ( const CVector& vecRotation ) { SetRotationDegrees ( vecRotation, true ); } - void SetRotationDegrees ( const CVector& vecRotation, bool bResetInterpolation ); - void SetRotationRadians ( const CVector& vecRotation ) { SetRotationRadians ( vecRotation, true ); } - void SetRotationRadians ( const CVector& vecRotation, bool bResetInterpolation ); + void SetRotationDegrees ( const CVector& vecRotation ); + void SetRotationRadians ( const CVector& vecRotation ); void AttachTo ( CClientEntity * pEntity ); @@ -160,7 +157,7 @@ class CClientVehicle : public CClientStreamElement void SetColor ( unsigned char ucColor1, unsigned char ucColor2, unsigned char ucColor3, unsigned char ucColor4 ); void GetTurretRotation ( float& fHorizontal, float& fVertical ); - void SetTurretRotation ( float fHorizontal, float fVertical ); + virtual void SetTurretRotation ( float fHorizontal, float fVertical ); inline unsigned short GetModel ( void ) { return m_usModel; }; void SetModelBlocking ( unsigned short usModel, bool bLoadImmediately = false ); @@ -192,14 +189,15 @@ class CClientVehicle : public CClientStreamElement inline bool HasLandingGear ( void ) { return m_bHasLandingGear; }; float GetLandingGearPosition ( void ); - void SetLandingGearPosition ( float fPosition ); + virtual void SetLandingGearPosition ( float fPosition ); bool IsLandingGearDown ( void ); void SetLandingGearDown ( bool bLandingGearDown ); inline bool HasAdjustableProperty ( void ) { return m_bHasAdjustableProperty; }; unsigned short GetAdjustablePropertyValue ( void ); - void SetAdjustablePropertyValue ( unsigned short usValue ); -private: + virtual void SetAdjustablePropertyValue ( unsigned short usValue ); + bool HasMovingCollision ( void ); +protected: void _SetAdjustablePropertyValue ( unsigned short usValue ); public: @@ -322,24 +320,19 @@ class CClientVehicle : public CClientStreamElement void AddMatrix ( CMatrix& Matrix, double dTime, unsigned short usTickRate ); void AddVelocity ( CVector& vecVelocity ); - - - // Time dependent interpolation - inline void GetTargetPosition ( CVector& vecPosition ) { vecPosition = m_interp.pos.vecTarget; } - void SetTargetPosition ( CVector& vecPosition, unsigned long ulDelay, bool bExtrapolateAfterInterpolation = true ); + inline void GetTargetPosition ( CVector& vecPosition ) { vecPosition = m_vecTargetPosition; } + void SetTargetPosition ( CVector& vecPosition ); void RemoveTargetPosition ( void ); - inline bool HasTargetPosition ( void ) { return ( m_interp.pos.ulFinishTime != 0 ); } + inline bool HasTargetPosition ( void ) { return m_bHasTargetPosition; } - inline void GetTargetRotation ( CVector& vecRotation ) { vecRotation = m_interp.rot.vecTarget; } - void SetTargetRotation ( CVector& vecRotation, unsigned long ulDelay, bool bExtrapolateAfterInterpolation = true ); + inline void GetTargetRotation ( CVector& vecRotation ) { vecRotation = m_vecTargetRotation; } + void SetTargetRotation ( CVector& vecRotation ); void RemoveTargetRotation ( void ); - inline bool HasTargetRotation ( void ) { return ( m_interp.rot.ulFinishTime != 0 ); } + inline bool HasTargetRotation ( void ) { return m_bHasTargetRotation; } void UpdateTargetPosition ( void ); void UpdateTargetRotation ( void ); - - inline unsigned long GetIllegalTowBreakTime ( void ) { return m_ulIllegalTowBreakTime; } inline void SetIllegalTowBreakTime ( unsigned long ulTime ) { m_ulIllegalTowBreakTime = ulTime; } @@ -353,6 +346,8 @@ class CClientVehicle : public CClientStreamElement bool HasRadio ( void ); bool HasPoliceRadio ( void ); + void DoTankFire ( void ); + void ReCreate ( void ); void ModelRequestCallback ( CModelInfo* pModelInfo ); @@ -372,6 +367,12 @@ class CClientVehicle : public CClientStreamElement void RemoveAllProjectiles ( void ); + static void SetPedOccupiedVehicle ( CClientPed* pClientPed, CClientVehicle* pVehicle, unsigned int uiSeat ); + static void SetPedOccupyingVehicle ( CClientPed* pClientPed, CClientVehicle* pVehicle, unsigned int uiSeat ); + static void ValidatePedAndVehiclePair ( CClientPed* pClientPed, CClientVehicle* pVehicle ); + static void UnpairPedAndVehicle ( CClientPed* pClientPed, CClientVehicle* pVehicle ); + static void UnpairPedAndVehicle ( CClientPed* pClientPed ); + protected: void StreamIn ( bool bInstantly ); void StreamOut ( void ); @@ -381,7 +382,7 @@ class CClientVehicle : public CClientStreamElement bool DoCheckHasLandingGear ( void ); - void StreamedInPulse ( void ); + virtual void StreamedInPulse ( void ); void Dump ( FILE* pFile, bool bDumpDetails, unsigned int uiIndex ); class CClientObjectManager* m_pObjectManager; @@ -405,6 +406,10 @@ class CClientVehicle : public CClientStreamElement CMatrix m_Matrix; CMatrix m_MatrixLast; CMatrix m_MatrixPure; + CQuat m_QuatA; + CQuat m_QuatB; + CQuat m_QuatLERP; + float m_fLERP; CVector m_vecMoveSpeedInterpolate; CVector m_vecMoveSpeedMeters; CVector m_vecMoveSpeed; @@ -466,28 +471,14 @@ class CClientVehicle : public CClientStreamElement bool m_bTrainDirection; float m_fTrainSpeed; - // Time dependent interpolation - struct - { - struct - { - CVector vecOrigin; - CVector vecTarget; - unsigned long ulStartTime; - unsigned long ulFinishTime; - bool bExtrapolateAfterInterpolation; - } pos; - - struct - { - CVector vecOrigin; - CVector vecTarget; - CVector vecOffset; - unsigned long ulStartTime; - unsigned long ulFinishTime; - bool bExtrapolateAfterInterpolation; - } rot; - } m_interp; + bool m_bInterpolationEnabled; + double m_dResetInterpolationTime; + + CVector m_vecTargetPosition; + bool m_bTargetPositionDirections [ 3 ]; + bool m_bHasTargetPosition; + CVector m_vecTargetRotation; + bool m_bHasTargetRotation; unsigned long m_ulIllegalTowBreakTime; diff --git a/MTA10/mods/shared_logic/CClientVehicleManager.cpp b/MTA10/mods/shared_logic/CClientVehicleManager.cpp index c76a140d06..c2ad4d02d8 100644 --- a/MTA10/mods/shared_logic/CClientVehicleManager.cpp +++ b/MTA10/mods/shared_logic/CClientVehicleManager.cpp @@ -91,7 +91,7 @@ void CClientVehicleManager::DoPulse ( void ) // Loop through our streamed-in vehicles list < CClientVehicle * > cloneList = m_StreamedIn; list < CClientVehicle* > ::iterator iter = cloneList.begin (); - for ( ; iter != cloneList.end (); iter++ ) + for ( ; iter != cloneList.end (); ++iter ) { pVehicle = *iter; // We should have a game vehicle here diff --git a/MTA10/mods/shared_logic/CVehicleNames.cpp b/MTA10/mods/shared_logic/CVehicleNames.cpp index 175954ee17..cd05cae515 100644 --- a/MTA10/mods/shared_logic/CVehicleNames.cpp +++ b/MTA10/mods/shared_logic/CVehicleNames.cpp @@ -26,9 +26,9 @@ struct SVehicleName SVehicleName VehicleNames [611] = { {"Landstalker"}, {"Bravura"}, {"Buffalo"}, {"Linerunner"}, {"Perennial"}, {"Sentinel"}, {"Dumper"}, {"Fire Truck"}, {"Trashmaster"}, {"Stretch"}, {"Manana"}, {"Infernus"}, {"Voodoo"}, {"Pony"}, {"Mule"}, {"Cheetah"}, {"Ambulance"}, {"Leviathan"}, {"Moonbeam"}, {"Esperanto"}, {"Taxi"}, {"Washington"}, {"Bobcat"}, {"Mr. Whoopee"}, {"BF Injection"}, {"Hunter"}, {"Premier"}, {"Enforcer"}, {"Securicar"}, {"Banshee"}, -{"Predator"}, {"Bus"}, {"Rhino"}, {"Barracks"}, {"Hotknife"}, {""}, {"Previon"}, {"Coach"}, {"Cabbie"}, {"Stallion"}, -{"Rumpo"}, {"RC Bandit"}, {"Romero"}, {"Packer"}, {"Monster 1", "Monster"}, {"Admiral"}, {"Squalo"}, {"Seasparrow"}, {"Pizzaboy"}, {""}, -{""}, {"Turismo"}, {"Speeder"}, {"Reefer"}, {"Tropic"}, {"Flatbed"}, {"Yankee"}, {"Caddy"}, {"Solair"}, {"Berkley's RC Van"}, +{"Predator"}, {"Bus"}, {"Rhino"}, {"Barracks"}, {"Hotknife"}, {"Trailer 1"}, {"Previon"}, {"Coach"}, {"Cabbie"}, {"Stallion"}, +{"Rumpo"}, {"RC Bandit"}, {"Romero"}, {"Packer"}, {"Monster 1", "Monster"}, {"Admiral"}, {"Squalo"}, {"Seasparrow"}, {"Pizzaboy"}, {"Tram"}, +{"Trailer 2"}, {"Turismo"}, {"Speeder"}, {"Reefer"}, {"Tropic"}, {"Flatbed"}, {"Yankee"}, {"Caddy"}, {"Solair"}, {"Berkley's RC Van"}, {"Skimmer"}, {"PCJ-600"}, {"Faggio"}, {"Freeway"}, {"RC Baron"}, {"RC Raider"}, {"Glendale"}, {"Oceanic"}, {"Sanchez"}, {"Sparrow"}, {"Patriot"}, {"Quadbike"}, {"Coastguard"}, {"Dinghy"}, {"Hermes"}, {"Sabre"}, {"Rustler"}, {"ZR-350"}, {"Walton"}, {"Regina"}, {"Comet"}, {"BMX"}, {"Burrito"}, {"Camper"}, {"Marquis"}, {"Baggage"}, {"Dozer"}, {"Maverick"}, {"News Chopper"}, {"Rancher"}, @@ -39,12 +39,12 @@ SVehicleName VehicleNames [611] = { {"Landstalker"}, {"Bravura"}, {"Buffalo"}, { {"Forklift"}, {"Tractor"}, {"Combine Harvester"}, {"Feltzer"}, {"Remington"}, {"Slamvan"}, {"Blade"}, {"Freight"}, {"Streak"}, {"Vortex"}, {"Vincent"}, {"Bullet"}, {"Clover"}, {"Sadler"}, {"Fire Truck Ladder"}, {"Hustler"}, {"Intruder"}, {"Primo"}, {"Cargobob"}, {"Tampa"}, {"Sunrise"}, {"Merit"}, {"Utility Van"}, {"Nevada"}, {"Yosemite"}, {"Windsor"}, {"Monster 2"}, {"Monster 3"}, {"Uranus"}, {"Jester"}, -{"Sultan"}, {"Stratum"}, {"Elegy"}, {"Raindance"}, {"RC Tiger"}, {"Flash"}, {"Tahoma"}, {"Savanna"}, {"Bandito"}, {""}, -{""}, {"Kart"}, {"Mower"}, {"Dune"}, {"Sweeper"}, {"Broadway"}, {"Tornado"}, {"AT-400"}, {"DFT-30"}, {"Huntley"}, -{"Stafford"}, {"BF-400"}, {"Newsvan"}, {"Tug"}, {""}, {"Emperor"}, {"Wayfarer"}, {"Euros"}, {"Hotdog"}, {"Club"}, -{""}, {""}, {"Andromada"}, {"Dodo"}, {"RC Cam"}, {"Launch"}, {"Police LS", "Police"}, {"Police SF"}, {"Police LV"}, {"Police Ranger", "Ranger"}, -{"Picador"}, {"S.W.A.T."}, {"Alpha"}, {"Phoenix"}, {"Glendale Damaged"}, {"Sadler"}, {""}, {""}, {""}, {"Boxville Mission"}, -{""} }; +{"Sultan"}, {"Stratum"}, {"Elegy"}, {"Raindance"}, {"RC Tiger"}, {"Flash"}, {"Tahoma"}, {"Savanna"}, {"Bandito"}, {"Freight Train Flatbed"}, +{"Streak Train Trailer"}, {"Kart"}, {"Mower"}, {"Dune"}, {"Sweeper"}, {"Broadway"}, {"Tornado"}, {"AT-400"}, {"DFT-30"}, {"Huntley"}, +{"Stafford"}, {"BF-400"}, {"Newsvan"}, {"Tug"}, {"Trailer (Tanker Commando)"}, {"Emperor"}, {"Wayfarer"}, {"Euros"}, {"Hotdog"}, {"Club"}, +{"Box Freight"}, {"Trailer 3"}, {"Andromada"}, {"Dodo"}, {"RC Cam"}, {"Launch"}, {"Police LS", "Police"}, {"Police SF"}, {"Police LV"}, {"Police Ranger", "Ranger"}, +{"Picador"}, {"S.W.A.T."}, {"Alpha"}, {"Phoenix"}, {"Glendale Damaged"}, {"Sadler"}, {"Baggage Trailer (covered)"}, {"Baggage Trailer (Uncovered)"}, {"Trailer (Stairs)"}, {"Boxville Mission"}, +{"Farm Trailer"} }; SVehicleName VehicleTypes [] = { {"Automobile"}, {"Plane"}, {"Bike"}, {"Helicopter"}, {"Boat"}, {"Train"}, {"Trailer"}, {"BMX"}, {"Monster Truck"}, {"Quad"} }; diff --git a/MTA10/mods/shared_logic/Utils.h b/MTA10/mods/shared_logic/Utils.h index 7f60b75bfe..7a593da97c 100644 --- a/MTA10/mods/shared_logic/Utils.h +++ b/MTA10/mods/shared_logic/Utils.h @@ -174,6 +174,22 @@ inline float GetOffsetDegrees ( float a, float b ) c = ( 360.0f + c ); return c; } +inline float GetOffsetRadians ( float a, float b ) +{ + float c = GetOffsetDegrees ( ConvertRadiansToDegrees ( a ), ConvertRadiansToDegrees ( b ) ); + return ConvertDegreesToRadiansNoWrap ( c ); +} +inline void NormalizeRadian ( float & a ) +{ + if ( a < 0 ) a += ( 2 * PI ); + else if ( a >= ( 2 * PI ) ) a -= ( 2 * PI ); +} +inline void NormalizeRadian ( CVector & a ) +{ + NormalizeRadian ( a.fX ); + NormalizeRadian ( a.fY ); + NormalizeRadian ( a.fZ ); +} bool DoesFileExist ( const char* szFilename ); @@ -216,4 +232,51 @@ void MakeSureDirExists ( const char* szPath ); HMODULE RemoteLoadLibrary(HANDLE hProcess, const char* szLibPath); #endif +// Simple class to interpolate variables +template < class T > +class CInterpolatedVar +{ +public: + CInterpolatedVar ( void ) { begin = end = current = beginTime = endTime = 0; } + + T & operator = ( T var ) { return current = end = var; } + T operator + ( T var ) { return T ( current + var ); } + T * operator & ( void ) { return ¤t; } + operator T & ( void ) { return current; } + + void lerp ( T target, unsigned long time ) + { + update (); + begin = current; + end = target; + beginTime = GetTickCount (); + endTime = beginTime + time; + } + T & update ( void ) + { + if ( beginTime == 0 && endTime == 0 ) return current; + return current = Lerp < T > ( begin, UnlerpClamped ( beginTime, GetTickCount (), endTime ), end ); + } + T & updateRotRad ( void ) + { + return current = LerpRotationRad < T > ( begin, UnlerpClamped ( beginTime, GetTickCount (), endTime ), end ); + } + T & updateRotDeg ( void ) + { + return current = LerpRotationDeg < T > ( begin, UnlerpClamped ( beginTime, GetTickCount (), endTime ), end ); + } + T & finish ( void ) + { + endTime = GetTickCount (); + return current = end; + } + bool finished ( void ) + { + return ( GetTickCount () >= endTime && current == end ); + } + + T begin, end, current; + unsigned long beginTime, endTime; +}; + #endif diff --git a/MTA10/mods/shared_logic/lua/CLuaArgument.cpp b/MTA10/mods/shared_logic/lua/CLuaArgument.cpp index 78f605f1c2..c004b8aa47 100644 --- a/MTA10/mods/shared_logic/lua/CLuaArgument.cpp +++ b/MTA10/mods/shared_logic/lua/CLuaArgument.cpp @@ -116,6 +116,15 @@ CLuaArgument::~CLuaArgument ( void ) DeleteTableData (); } +void CLuaArgument::Clear ( void ) +{ + m_strString = ""; + DeleteTableData (); + m_iType = LUA_TNIL; + m_pTableData = NULL; + m_pLightUserData = NULL; +} + void CLuaArgument::CopyRecursive ( const CLuaArgument& Argument, std::map < CLuaArguments*, CLuaArguments* > * pKnownTables ) { // Clear the string @@ -225,20 +234,16 @@ bool CLuaArgument::CompareRecursive ( const CLuaArgument& Argument, std::set < C if ( m_pTableData->Count () != Argument.m_pTableData->Count () ) return false; - vector < CLuaArgument * > ::const_iterator iter = m_pTableData->IterBegin (); - vector < CLuaArgument * > ::const_iterator iterCompare = Argument.m_pTableData->IterBegin (); - while ( iter != m_pTableData->IterEnd () && iterCompare != Argument.m_pTableData->IterEnd () ) + for ( unsigned int i = 0; i < m_pTableData->Count (); ++i ) { if ( pKnownTables->find ( m_pTableData ) == pKnownTables->end () ) { pKnownTables->insert ( m_pTableData ); - if ( *iter != *iterCompare ) + if ( (*m_pTableData) [ i ] != (*Argument.m_pTableData) [ i ] ) return false; } - - iter++; - iterCompare++; } + return true; } case LUA_TSTRING: @@ -394,6 +399,19 @@ void CLuaArgument::Read ( CClientEntity* pElement ) m_iType = LUA_TNIL; } +void CLuaArgument::Read ( const CLuaArgument& Argument, std::map < CLuaArguments*, CLuaArguments* > * pKnownTables ) +{ + m_strString = ""; + DeleteTableData (); + CopyRecursive ( Argument, pKnownTables ); +} + +void CLuaArgument::Read ( NetBitStreamInterface& bitStream, std::vector < CLuaArguments* > * pKnownTables ) +{ + m_strString = ""; + DeleteTableData (); + ReadFromBitStream ( bitStream, pKnownTables ); +} void CLuaArgument::ReadElementID ( ElementID ID ) { diff --git a/MTA10/mods/shared_logic/lua/CLuaArgument.h b/MTA10/mods/shared_logic/lua/CLuaArgument.h index 517e6054c2..b50fd6bee1 100644 --- a/MTA10/mods/shared_logic/lua/CLuaArgument.h +++ b/MTA10/mods/shared_logic/lua/CLuaArgument.h @@ -46,12 +46,16 @@ class CLuaArgument bool operator == ( const CLuaArgument& Argument ); bool operator != ( const CLuaArgument& Argument ); + void Clear ( void ); + void Read ( lua_State* luaVM, int iArgument, std::map < const void*, CLuaArguments* > * pKnownTables = NULL ); void Read ( bool bBool ); void Read ( double dNumber ); void Read ( const char* szString ); void Read ( void* pUserData ); void Read ( CClientEntity* pElement ); + void Read ( const CLuaArgument& Argument, std::map < CLuaArguments*, CLuaArguments* > * pKnownTables = NULL ); + void Read ( NetBitStreamInterface& bitStream, std::vector < CLuaArguments* > * pKnownTables = NULL ); void ReadElementID ( ElementID ID ); void Push ( lua_State* luaVM, std::map < CLuaArguments*, int > * pKnownTables = NULL ) const; diff --git a/MTA10/mods/shared_logic/lua/CLuaArguments.cpp b/MTA10/mods/shared_logic/lua/CLuaArguments.cpp index 2fd6efdc9b..ca0e01bb6c 100644 --- a/MTA10/mods/shared_logic/lua/CLuaArguments.cpp +++ b/MTA10/mods/shared_logic/lua/CLuaArguments.cpp @@ -25,24 +25,48 @@ using namespace std; extern CClientGame* g_pClientGame; +CLuaArguments::CLuaArguments ( ) +: m_uiSize ( 0 ) +{ +} + CLuaArguments::CLuaArguments ( NetBitStreamInterface& bitStream, std::vector < CLuaArguments* > * pKnownTables ) +: m_uiSize ( 0 ) { ReadFromBitStream ( bitStream, pKnownTables ); } CLuaArguments::CLuaArguments ( const CLuaArguments& Arguments, std::map < CLuaArguments*, CLuaArguments* > * pKnownTables ) +: m_uiSize ( 0 ) { // Copy all the arguments CopyRecursive ( Arguments, pKnownTables ); } -CLuaArgument* CLuaArguments::operator [] ( const unsigned int uiPosition ) const +CLuaArgument* CLuaArguments::operator [] ( const unsigned int uiPosition ) +{ + if ( uiPosition < Count () ) + { + if ( uiPosition < MAX_EXPECTED_ARGS ) + return &( m_Arguments [ uiPosition ] ); + else + return &( m_vecArguments.at ( uiPosition - MAX_EXPECTED_ARGS ) ); + } + return NULL; +} + +const CLuaArgument* CLuaArguments::operator [] ( const unsigned int uiPosition ) const { - if ( uiPosition < m_Arguments.size () ) - return m_Arguments.at ( uiPosition ); - return NULL; + if ( uiPosition < Count () ) + { + if ( uiPosition < MAX_EXPECTED_ARGS ) + return &( m_Arguments [ uiPosition ] ); + else + return &( m_vecArguments.at ( uiPosition - MAX_EXPECTED_ARGS ) ); + } + return NULL; } @@ -70,11 +94,10 @@ void CLuaArguments::CopyRecursive ( const CLuaArguments& Arguments, std::map < C pKnownTables->insert ( std::make_pair ( (CLuaArguments *)&Arguments, (CLuaArguments *)this ) ); // Copy all the arguments - vector < CLuaArgument* > ::const_iterator iter = Arguments.m_Arguments.begin (); - for ( ; iter != Arguments.m_Arguments.end (); iter++ ) + for ( unsigned int i = 0; i < Arguments.Count (); ++i ) { - CLuaArgument* pArgument = new CLuaArgument ( **iter, pKnownTables ); - m_Arguments.push_back ( pArgument ); + CLuaArgument* pArgument = CreateNew (); + pArgument->Read ( *Arguments [ i ], pKnownTables ); } if ( bKnownTablesCreated ) @@ -92,8 +115,8 @@ void CLuaArguments::ReadArguments ( lua_State* luaVM, signed int uiIndexBegin ) while ( lua_type ( luaVM, uiIndexBegin ) != LUA_TNONE ) { // Create an argument, let it read out the argument and add it to our vector - CLuaArgument* pArgument = new CLuaArgument ( luaVM, uiIndexBegin++, &knownTables ); - m_Arguments.push_back ( pArgument ); + CLuaArgument* pArgument = CreateNew (); + pArgument->Read ( luaVM, uiIndexBegin++, &knownTables ); } } @@ -116,11 +139,11 @@ void CLuaArguments::ReadTable ( lua_State* luaVM, int iIndexBegin, std::map < co while (lua_next(luaVM, iIndexBegin) != 0) { /* uses 'key' (at index -2) and 'value' (at index -1) */ - CLuaArgument* pArgument = new CLuaArgument ( luaVM, -2, pKnownTables ); - m_Arguments.push_back ( pArgument ); // push the key first + CLuaArgument* pArgument = CreateNew (); + pArgument->Read ( luaVM, -2, pKnownTables ); // push the key first - pArgument = new CLuaArgument ( luaVM, -1, pKnownTables ); - m_Arguments.push_back ( pArgument ); // then the value + pArgument = CreateNew (); + pArgument->Read ( luaVM, -1, pKnownTables ); // then the value /* removes 'value'; keeps 'key' for next iteration */ lua_pop(luaVM, 1); @@ -132,18 +155,16 @@ void CLuaArguments::ReadTable ( lua_State* luaVM, int iIndexBegin, std::map < co void CLuaArguments::ReadArgument ( lua_State* luaVM, int iIndex ) { - CLuaArgument* pArgument = new CLuaArgument ( luaVM, iIndex ); - m_Arguments.push_back ( pArgument ); + CLuaArgument* pArgument = CreateNew (); + pArgument->Read ( luaVM, iIndex ); } void CLuaArguments::PushArguments ( lua_State* luaVM ) const { // Push all our arguments - vector < CLuaArgument* > ::const_iterator iter = m_Arguments.begin (); - for ( ; iter != m_Arguments.end (); iter++ ) - { - (*iter)->Push ( luaVM ); - } + const CLuaArguments& args = *this; + for ( unsigned int i = 0; i < Count (); ++i ) + args[ i ]->Push ( luaVM ); } void CLuaArguments::PushAsTable ( lua_State* luaVM, std::map < CLuaArguments*, int > * pKnownTables ) @@ -157,12 +178,13 @@ void CLuaArguments::PushAsTable ( lua_State* luaVM, std::map < CLuaArguments*, i lua_newtable ( luaVM ); pKnownTables->insert ( std::make_pair ( (CLuaArguments *)this, lua_gettop(luaVM) ) ); - vector < CLuaArgument* > ::const_iterator iter = m_Arguments.begin (); - for ( ; iter != m_Arguments.end () && (iter+1) != m_Arguments.end (); iter ++ ) + + CLuaArguments& args = *this; + for ( unsigned int i = 0; i < Count (); ++i ) { - (*iter)->Push ( luaVM, pKnownTables ); // index - iter++; - (*iter)->Push ( luaVM, pKnownTables ); // value + args [ i ]->Push ( luaVM, pKnownTables ); + ++i; + args [ i ]->Push ( luaVM, pKnownTables ); lua_settable ( luaVM, -3 ); } @@ -173,11 +195,10 @@ void CLuaArguments::PushAsTable ( lua_State* luaVM, std::map < CLuaArguments*, i void CLuaArguments::PushArguments ( CLuaArguments& Arguments ) { - vector < CLuaArgument* > ::const_iterator iter = Arguments.IterBegin (); - for ( ; iter != Arguments.IterEnd (); iter++ ) + for ( unsigned int i = 0; i < Arguments.Count (); ++i ) { - CLuaArgument* pArgument = new CLuaArgument ( **iter ); - m_Arguments.push_back ( pArgument ); + CLuaArgument* pArgument = CreateNew (); + pArgument->Read ( *Arguments [ i ] ); } } @@ -197,7 +218,7 @@ bool CLuaArguments::Call ( CLuaMain* pLuaMain, int iLuaFunction, CLuaArguments * // Call the function with our arguments pLuaMain->ResetInstructionCount (); - int iret = lua_pcall ( luaVM, m_Arguments.size (), LUA_MULTRET, 0 ); + int iret = lua_pcall ( luaVM, Count (), LUA_MULTRET, 0 ); if ( iret == LUA_ERRRUN || iret == LUA_ERRMEM ) { const char* szRes = lua_tostring( luaVM, -1 ); @@ -241,7 +262,7 @@ bool CLuaArguments::CallGlobal ( CLuaMain* pLuaMain, const char* szFunction, CLu // Call the function with our arguments pLuaMain->ResetInstructionCount (); - int iret = lua_pcall ( luaVM, m_Arguments.size (), LUA_MULTRET, 0 ); + int iret = lua_pcall ( luaVM, Count (), LUA_MULTRET, 0 ); if ( iret == LUA_ERRRUN || iret == LUA_ERRMEM ) { const char* szRes = lua_tostring( luaVM, -1 ); @@ -269,80 +290,71 @@ bool CLuaArguments::CallGlobal ( CLuaMain* pLuaMain, const char* szFunction, CLu CLuaArgument* CLuaArguments::PushNil ( void ) { - CLuaArgument* pArgument = new CLuaArgument; - m_Arguments.push_back ( pArgument ); - return pArgument; + return CreateNew (); } CLuaArgument* CLuaArguments::PushBoolean ( bool bBool ) { - CLuaArgument* pArgument = new CLuaArgument ( bBool ); - m_Arguments.push_back ( pArgument ); + CLuaArgument* pArgument = CreateNew (); + pArgument->Read ( bBool ); return pArgument; } CLuaArgument* CLuaArguments::PushNumber ( double dNumber ) { - CLuaArgument* pArgument = new CLuaArgument ( dNumber ); - m_Arguments.push_back ( pArgument ); + CLuaArgument* pArgument = CreateNew (); + pArgument->Read ( dNumber ); return pArgument; } CLuaArgument* CLuaArguments::PushString ( const char* szString ) { - CLuaArgument* pArgument = new CLuaArgument ( szString ); - m_Arguments.push_back ( pArgument ); + CLuaArgument* pArgument = CreateNew (); + pArgument->Read ( szString ); return pArgument; } CLuaArgument* CLuaArguments::PushUserData ( void* pUserData ) { - CLuaArgument* pArgument = new CLuaArgument ( pUserData ); - m_Arguments.push_back ( pArgument ); + CLuaArgument* pArgument = CreateNew (); + pArgument->Read ( pUserData ); return pArgument; } CLuaArgument* CLuaArguments::PushElement ( CClientEntity* pElement ) { - CLuaArgument* pArgument = new CLuaArgument ( pElement ); - m_Arguments.push_back ( pArgument ); + CLuaArgument* pArgument = CreateNew (); + pArgument->Read ( pElement ); return pArgument; } CLuaArgument* CLuaArguments::PushArgument ( CLuaArgument& Argument ) { - CLuaArgument* pArgument = new CLuaArgument ( Argument ); - m_Arguments.push_back ( pArgument ); + CLuaArgument* pArgument = CreateNew (); + pArgument->Read ( Argument ); return pArgument; } CLuaArgument* CLuaArguments::PushTable ( CLuaArguments * table ) { - CLuaArgument* pArgument = new CLuaArgument ( ); + CLuaArgument* pArgument = CreateNew (); pArgument->Read(table); - m_Arguments.push_back ( pArgument ); return pArgument; } void CLuaArguments::DeleteArguments ( void ) { - // Delete each item - vector < CLuaArgument* > ::iterator iter = m_Arguments.begin (); - for ( ; iter != m_Arguments.end (); iter++ ) - { - delete *iter; - } - // Clear the vector - m_Arguments.clear (); + m_vecArguments.clear (); + m_uiSize = 0; } @@ -361,8 +373,8 @@ bool CLuaArguments::ReadFromBitStream ( NetBitStreamInterface& bitStream, std::v pKnownTables->push_back ( this ); for ( unsigned short us = 0 ; us < usNumArgs ; us++ ) { - CLuaArgument* pArgument = new CLuaArgument ( bitStream, pKnownTables ); - m_Arguments.push_back ( pArgument ); + CLuaArgument* pArgument = CreateNew (); + pArgument->Read ( bitStream, pKnownTables ); } } @@ -384,11 +396,12 @@ bool CLuaArguments::WriteToBitStream ( NetBitStreamInterface& bitStream, std::ma bool bSuccess = true; pKnownTables->insert ( make_pair ( (CLuaArguments *)this, pKnownTables->size () ) ); - bitStream.WriteCompressed ( static_cast < unsigned short > ( m_Arguments.size () ) ); - vector < CLuaArgument* > ::const_iterator iter = m_Arguments.begin (); - for ( ; iter != m_Arguments.end () ; iter++ ) + bitStream.WriteCompressed ( static_cast < unsigned short > ( Count () ) ); + + const CLuaArguments& args = *this; + for ( unsigned int i = 0; i < Count (); ++i ) { - CLuaArgument* pArgument = *iter; + const CLuaArgument* pArgument = args [ i ]; if ( !pArgument->WriteToBitStream ( bitStream, pKnownTables ) ) { bSuccess = false; @@ -400,3 +413,24 @@ bool CLuaArguments::WriteToBitStream ( NetBitStreamInterface& bitStream, std::ma return bSuccess; } + +unsigned int CLuaArguments::Count () const +{ + return m_uiSize; +} + +CLuaArgument* CLuaArguments::CreateNew () +{ + CLuaArgument* pArgument = 0; + if ( m_uiSize < MAX_EXPECTED_ARGS ) + pArgument = &m_Arguments [ m_uiSize ]; + else + { + m_vecArguments.push_back ( CLuaArgument () ); + pArgument = &m_vecArguments.back (); + } + + ++m_uiSize; + pArgument->Clear (); + return pArgument; +} diff --git a/MTA10/mods/shared_logic/lua/CLuaArguments.h b/MTA10/mods/shared_logic/lua/CLuaArguments.h index 6ba1063435..777d92626d 100644 --- a/MTA10/mods/shared_logic/lua/CLuaArguments.h +++ b/MTA10/mods/shared_logic/lua/CLuaArguments.h @@ -31,8 +31,11 @@ class CLuaArguments; class CLuaArguments { +private: + enum { MAX_EXPECTED_ARGS = 64 }; + public: - CLuaArguments ( void ) { } + CLuaArguments ( void ); CLuaArguments ( const CLuaArguments& Arguments, std::map < CLuaArguments*, CLuaArguments* > * pKnownTables = NULL ); CLuaArguments ( NetBitStreamInterface& bitStream, std::vector < CLuaArguments* > * pKnownTables = NULL ); ~CLuaArguments ( void ) { DeleteArguments (); }; @@ -40,7 +43,8 @@ class CLuaArguments void CopyRecursive ( const CLuaArguments& Arguments, std::map < CLuaArguments*, CLuaArguments* > * pKnownTables = NULL ); const CLuaArguments& operator = ( const CLuaArguments& Arguments ); - CLuaArgument* operator [] ( const unsigned int uiPosition ) const; + CLuaArgument* operator [] ( const unsigned int uiPosition ); + const CLuaArgument* operator [] ( const unsigned int uiPosition ) const; void ReadArgument ( lua_State* luaVM, signed int uiIndex ); void ReadArguments ( lua_State* luaVM, signed int uiIndexBegin = 1 ); @@ -66,12 +70,14 @@ class CLuaArguments bool ReadFromBitStream ( NetBitStreamInterface& bitStream, std::vector < CLuaArguments* > * pKnownTables = NULL ); bool WriteToBitStream ( NetBitStreamInterface& bitStream, std::map < CLuaArguments*, unsigned long > * pKnownTables = NULL ) const; - unsigned int Count ( void ) const { return static_cast < unsigned int > ( m_Arguments.size () ); }; - std::vector < CLuaArgument* > ::const_iterator IterBegin ( void ) { return m_Arguments.begin (); }; - std::vector < CLuaArgument* > ::const_iterator IterEnd ( void ) { return m_Arguments.end (); }; + unsigned int Count ( void ) const; +private: + CLuaArgument* CreateNew (); private: - std::vector < CLuaArgument* > m_Arguments; + CLuaArgument m_Arguments [ MAX_EXPECTED_ARGS ]; + std::vector < CLuaArgument > m_vecArguments; + unsigned int m_uiSize; }; #endif diff --git a/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.Element.cpp b/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.Element.cpp index e51dead6bc..c3e11f3ef9 100644 --- a/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.Element.cpp +++ b/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.Element.cpp @@ -1331,15 +1331,18 @@ int CLuaFunctionDefs::SetElementData ( lua_State* luaVM ) // Grab the element, the element data name and the data to set CClientEntity* pEntity = lua_toelement ( luaVM, 1 ); const char* szName = lua_tostring ( luaVM, 2 ); - bool bSynchronize = true; + + // Give a warning in case the old syntax is used (elem, name, synchronize, data) + if ( lua_type ( luaVM, 3 ) == LUA_TBOOLEAN && + lua_type ( luaVM, 4 ) != LUA_TNONE && lua_type ( luaVM, 4 ) != LUA_TBOOLEAN ) + m_pScriptDebugging->LogCustom ( luaVM, "Using outdated setElementData syntax. Consult the wiki" ); + CLuaArgument Variable; - if ( lua_type ( luaVM, 3 ) == LUA_TBOOLEAN && lua_type ( luaVM, 4 ) != LUA_TNONE ) - { - bSynchronize = ( lua_toboolean ( luaVM, 3 ) ) ? true:false; - Variable.Read ( luaVM, 4 ); - } - else - Variable.Read ( luaVM, 3 ); + Variable.Read ( luaVM, 3 ); + + bool bSynchronize = true; + if ( lua_type ( luaVM, 4 ) == LUA_TBOOLEAN ) + bSynchronize = lua_toboolean ( luaVM, 4 ) ? true:false; // Valid element? if ( pEntity ) diff --git a/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.GUI.cpp b/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.GUI.cpp index d2eeb2ab36..583cdf11cb 100644 --- a/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.GUI.cpp +++ b/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.GUI.cpp @@ -1798,7 +1798,9 @@ int CLuaFunctionDefs::GUIGridListRemoveRow ( lua_State* luaVM ) int CLuaFunctionDefs::GUIGridListGetItemText ( lua_State* luaVM ) { - if ( lua_istype ( luaVM, 1, LUA_TLIGHTUSERDATA ) && lua_istype ( luaVM, 2, LUA_TNUMBER ) && lua_istype ( luaVM, 3, LUA_TNUMBER ) ) + if ( lua_istype ( luaVM, 1, LUA_TLIGHTUSERDATA ) && + lua_istype ( luaVM, 2, LUA_TNUMBER ) && + lua_istype ( luaVM, 3, LUA_TNUMBER ) ) { CClientGUIElement *pGUIElement = lua_toguielement ( luaVM, 1 ); if ( pGUIElement && IS_CGUIELEMENT_GRIDLIST ( pGUIElement ) ) @@ -1824,14 +1826,19 @@ int CLuaFunctionDefs::GUIGridListGetItemText ( lua_State* luaVM ) int CLuaFunctionDefs::GUIGridListGetItemData ( lua_State* luaVM ) { - if ( lua_istype ( luaVM, 1, LUA_TLIGHTUSERDATA ) && lua_istype ( luaVM, 2, LUA_TNUMBER ) && lua_istype ( luaVM, 3, LUA_TNUMBER ) ) + if ( lua_istype ( luaVM, 1, LUA_TLIGHTUSERDATA ) && + lua_istype ( luaVM, 2, LUA_TNUMBER ) && + lua_istype ( luaVM, 3, LUA_TNUMBER ) ) { CClientGUIElement *pGUIElement = lua_toguielement ( luaVM, 1 ); if ( pGUIElement && IS_CGUIELEMENT_GRIDLIST ( pGUIElement ) ) { - // TODO: Is this safe? Sure the data can't be something else? - const char* szData = reinterpret_cast < const char* > ( static_cast < CGUIGridList* > ( pGUIElement->GetCGUIElement () ) -> GetItemData ( static_cast < int > ( lua_tonumber ( luaVM, 2 ) ), - static_cast < int > ( lua_tonumber ( luaVM, 3 ) ) ) ); + const char* szData = reinterpret_cast < const char* > ( + static_cast < CGUIGridList* > ( pGUIElement->GetCGUIElement () ) -> GetItemData ( + static_cast < int > ( lua_tonumber ( luaVM, 2 ) ), + static_cast < int > ( lua_tonumber ( luaVM, 3 ) ) + ) + ); if ( szData ) lua_pushstring ( luaVM, szData ); else @@ -1851,8 +1858,12 @@ int CLuaFunctionDefs::GUIGridListGetItemData ( lua_State* luaVM ) int CLuaFunctionDefs::GUIGridListSetItemText ( lua_State* luaVM ) { - if ( lua_istype ( luaVM, 1, LUA_TLIGHTUSERDATA ) && lua_istype ( luaVM, 2, LUA_TNUMBER ) && lua_istype ( luaVM, 3, LUA_TNUMBER ) && - lua_istype ( luaVM, 4, LUA_TSTRING ) && lua_istype ( luaVM, 5, LUA_TBOOLEAN ) && lua_istype ( luaVM, 6, LUA_TBOOLEAN ) ) + if ( lua_istype ( luaVM, 1, LUA_TLIGHTUSERDATA ) && + lua_istype ( luaVM, 2, LUA_TNUMBER ) && + lua_istype ( luaVM, 3, LUA_TNUMBER ) && + lua_istype ( luaVM, 4, LUA_TSTRING ) && + lua_istype ( luaVM, 5, LUA_TBOOLEAN ) && + lua_istype ( luaVM, 6, LUA_TBOOLEAN ) ) { CClientGUIElement *pGUIElement = lua_toguielement ( luaVM, 1 ); if ( pGUIElement && IS_CGUIELEMENT_GRIDLIST ( pGUIElement ) ) @@ -1864,7 +1875,7 @@ int CLuaFunctionDefs::GUIGridListSetItemText ( lua_State* luaVM ) lua_tostring ( luaVM, 4 ), lua_toboolean ( luaVM, 5 ) ? true : false, lua_toboolean ( luaVM, 6 ) ? true : false - ); + ); lua_pushboolean ( luaVM, true ); return 1; @@ -1881,8 +1892,10 @@ int CLuaFunctionDefs::GUIGridListSetItemText ( lua_State* luaVM ) int CLuaFunctionDefs::GUIGridListSetItemData ( lua_State* luaVM ) { - if ( lua_istype ( luaVM, 1, LUA_TLIGHTUSERDATA ) && lua_istype ( luaVM, 2, LUA_TNUMBER ) && lua_istype ( luaVM, 3, LUA_TNUMBER ) && - lua_istype ( luaVM, 4, LUA_TSTRING ) ) + if ( lua_istype ( luaVM, 1, LUA_TLIGHTUSERDATA ) && + lua_istype ( luaVM, 2, LUA_TNUMBER ) && + lua_istype ( luaVM, 3, LUA_TNUMBER ) && + lua_istype ( luaVM, 4, LUA_TSTRING ) ) { CClientGUIElement *pGUIElement = lua_toguielement ( luaVM, 1 ); if ( pGUIElement && IS_CGUIELEMENT_GRIDLIST ( pGUIElement ) ) @@ -1892,7 +1905,7 @@ int CLuaFunctionDefs::GUIGridListSetItemData ( lua_State* luaVM ) static_cast < int > ( lua_tonumber ( luaVM, 2 ) ), static_cast < int > ( lua_tonumber ( luaVM, 3 ) ), lua_tostring ( luaVM, 4 ) - ); + ); lua_pushboolean ( luaVM, true ); return 1; diff --git a/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.Ped.cpp b/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.Ped.cpp index 1231fabe04..3fda9f81d4 100644 --- a/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.Ped.cpp +++ b/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.Ped.cpp @@ -238,6 +238,33 @@ int CLuaFunctionDefs::GetPedTotalAmmo ( lua_State* luaVM ) } +int CLuaFunctionDefs::GetPedWeaponMuzzlePosition ( lua_State* luaVM ) +{ + if ( lua_type ( luaVM, 1 ) == LUA_TLIGHTUSERDATA ) + { + CClientPed* pPed = lua_toped ( luaVM, 1 ); + if ( pPed ) + { + CVector vecMuzzlePos; + if ( CStaticFunctionDefinitions::GetPedWeaponMuzzlePosition ( *pPed, vecMuzzlePos ) ) + { + lua_pushnumber ( luaVM, vecMuzzlePos.fX ); + lua_pushnumber ( luaVM, vecMuzzlePos.fY ); + lua_pushnumber ( luaVM, vecMuzzlePos.fZ ); + return 3; + } + } + else + m_pScriptDebugging->LogBadPointer ( luaVM, "getPedWeaponMuzzlePosition", "ped", 1 ); + } + else + m_pScriptDebugging->LogBadType ( luaVM, "getPedWeaponMuzzlePosition" ); + + lua_pushboolean ( luaVM, false ); + return 1; +} + + int CLuaFunctionDefs::GetPedOccupiedVehicle ( lua_State* luaVM ) { // Correct type? @@ -644,11 +671,13 @@ int CLuaFunctionDefs::IsPedInVehicle ( lua_State* luaVM ) if ( pPed ) { // Find out whether he's in a vehicle or not - bool bInVehicle = pPed->GetOccupiedVehicle () != NULL; - - // Return that state - lua_pushboolean ( luaVM, bInVehicle ); - return 1; + bool bInVehicle; + if ( CStaticFunctionDefinitions::IsPedInVehicle ( *pPed, bInVehicle ) ) + { + // Return that state + lua_pushboolean ( luaVM, bInVehicle ); + return 1; + } } else m_pScriptDebugging->LogBadPointer ( luaVM, "isPedInVehicle", "ped", 1 ); diff --git a/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.h b/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.h index 4e6c9f9bc9..b2c4a9f3ff 100644 --- a/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.h +++ b/MTA10/mods/shared_logic/lua/CLuaFunctionDefs.h @@ -181,6 +181,7 @@ class CLuaFunctionDefs LUA_DECLARE ( GetPedWeapon ); LUA_DECLARE ( GetPedAmmoInClip ); LUA_DECLARE ( GetPedTotalAmmo ); + LUA_DECLARE ( GetPedWeaponMuzzlePosition ); LUA_DECLARE ( GetPedStat ); LUA_DECLARE ( GetPedOccupiedVehicle ); LUA_DECLARE ( GetPedArmor ); diff --git a/MTA10/mods/shared_logic/lua/CLuaManager.cpp b/MTA10/mods/shared_logic/lua/CLuaManager.cpp index f4a04c127d..6f966341d2 100644 --- a/MTA10/mods/shared_logic/lua/CLuaManager.cpp +++ b/MTA10/mods/shared_logic/lua/CLuaManager.cpp @@ -106,7 +106,7 @@ bool CLuaManager::RemoveVirtualMachine ( CLuaMain * vm ) void CLuaManager::DoPulse ( void ) { list::iterator iter = m_virtualMachines.begin (); - for ( ; iter != m_virtualMachines.end(); iter++ ) + for ( ; iter != m_virtualMachines.end(); ++iter ) { (*iter)->DoPulse (); } @@ -205,6 +205,7 @@ void CLuaManager::LoadCFunctions ( void ) CLuaCFunctions::AddFunction ( "getPlayerWeapon", CLuaFunctionDefs::GetPedWeapon ); CLuaCFunctions::AddFunction ( "getPlayerAmmoInClip", CLuaFunctionDefs::GetPedAmmoInClip ); CLuaCFunctions::AddFunction ( "getPlayerTotalAmmo", CLuaFunctionDefs::GetPedTotalAmmo ); + CLuaCFunctions::AddFunction ( "getPedWeaponMuzzlePosition", CLuaFunctionDefs::GetPedWeaponMuzzlePosition ); CLuaCFunctions::AddFunction ( "getPlayerOccupiedVehicle", CLuaFunctionDefs::GetPedOccupiedVehicle ); CLuaCFunctions::AddFunction ( "getPlayerArmor", CLuaFunctionDefs::GetPedArmor ); CLuaCFunctions::AddFunction ( "getPlayerSkin", CLuaFunctionDefs::GetElementModel ); diff --git a/MTA10/multiplayer_sa/CMultiplayerSA.cpp b/MTA10/multiplayer_sa/CMultiplayerSA.cpp index 5930b06b96..26fa776b74 100644 --- a/MTA10/multiplayer_sa/CMultiplayerSA.cpp +++ b/MTA10/multiplayer_sa/CMultiplayerSA.cpp @@ -132,8 +132,8 @@ DWORD RETURN_CWorld_SetWorldOnFire = 0x56B989; DWORD RETURN_CTaskSimplePlayerOnFire_ProcessPed = 0x6336E0; #define HOOKPOS_CFire_ProcessFire 0x53AC1A DWORD RETURN_CFire_ProcessFire = 0x53AC1F; -#define HOOKPOS_CExplosion_Update 0x7377D3 -DWORD RETURN_CExplosion_Update = 0x7377D8; +#define HOOKPOS_CExplosion_Update_TryToStartFire 0x7377D3 +DWORD RETURN_CExplosion_Update_TryToStartFire = 0x7377D8; #define HOOKPOS_CWeapon_FireAreaEffect 0x73EBFE DWORD RETURN_CWeapon_FireAreaEffect = 0x73EC03; @@ -154,6 +154,40 @@ DWORD RETURN_CAnimManager_BlendAnimation = 0x4D4617; #define HOOKPOS_CPed_GetWeaponSkill 0x5e3b60 DWORD RETURN_CPed_GetWeaponSkill = 0x5E3B68; +#define HOOKPOS_CTaskSimplePlayerOnFoot_MakeAbortable 0x68596F +DWORD RETURN_CTaskSimplePlayerOnFoot_MakeAbortable = 0x685980; + +#define HOOKPOS_CPed_AddGogglesModel 0x5E3ACB +DWORD RETURN_CPed_AddGogglesModel = 0x5E3AD4; + +#define FUNC_CWorld_Remove 0x563280 +#define FUNC_CTagManager_ShutdownForRestart 0x49CC60 +unsigned int* VAR_NumTags = (unsigned int *)0xA9AD70; +DWORD** VAR_TagInfoArray = (DWORD **)0xA9A8C0; + +// Hooks for the BlowUpCar function (CVehicle/CBmx do nothing) +#define HOOKPOS_CAutomobile_BlowUpCar 0x6b3780 +DWORD RETURN_CAutomobile_BlowUpCar = 0x6B3786; +#define HOOKPOS_CBike_BlowUpCar 0x6BEA10 +DWORD RETURN_CBike_BlowUpCar = 0x6BEA1A; +#define HOOKPOS_CHeli_BlowUpCar 0x6C6D30 +DWORD RETURN_CHeli_BlowUpCar = 0x6C6D3B; +#define HOOKPOS_CPlane_BlowUpCar 0x6CCCF0 +DWORD RETURN_CPlane_BlowUpCar = 0x6CCCFC; +#define HOOKPOS_CBoat_BlowUpCar 0x6F21C5 +DWORD RETURN_CBoat_BlowUpCar = 0x6F21CC; + +#define HOOKPOS_CFire_ProcessFire_BurnPed 0x53A897 +DWORD RETURN_CFire_ProcessFire_BurnPed = 0x53A89E; +DWORD RETURN_CANCEL_CFire_ProcessFire_BurnPed = 0x53A8C5; + +#define HOOKPOS_CExplosion_Update_SetPedsOnFire 0x73794B +DWORD RETURN_CExplosion_Update_SetPedsOnFire = 0x737951; + +#define HOOKPOS_CWorld_SetPedsOnFire 0x5657C9 +DWORD RETURN_CWorld_SetPedsOnFire = 0x5657D0; +DWORD RETURN_CANCEL_CWorld_SetPedsOnFire = 0x5657E3; + CPed* pContextSwitchedPed = 0; CVector vecCenterOfWorld; FLOAT fFalseHeading; @@ -207,6 +241,8 @@ IdleHandler * m_pIdleHandler = NULL; AddAnimationHandler* m_pAddAnimationHandler = NULL; BlendAnimationHandler* m_pBlendAnimationHandler = NULL; PreHudDrawHandler* m_pPreHudDrawHandler = NULL; +BlowUpCarHandler* m_pBlowUpCarHandler = NULL; +PedOnFireHandler* m_pPedOnFireHandler = NULL; CEntitySAInterface * dwSavedPlayerPointer = 0; CEntitySAInterface * activeEntityForStreaming = 0; // the entity that the streaming system considers active @@ -254,7 +290,7 @@ void HOOK_ApplyCarBlowHop (); void HOOK_CWorld_SetWorldOnFire (); void HOOK_CTaskSimplePlayerOnFire_ProcessPed (); void HOOK_CFire_ProcessFire (); -void HOOK_CExplosion_Update (); +void HOOK_CExplosion_Update_TryToStartFire (); void HOOK_CWeapon_FireAreaEffect (); void HOOK_CGame_Process (); void HOOK_Idle (); @@ -265,6 +301,16 @@ void HOOK_CEventHandler_ComputeKnockOffBikeResponse (); void HOOK_CAnimManager_AddAnimation (); void HOOK_CAnimManager_BlendAnimation (); void HOOK_CPed_GetWeaponSkill (); +void HOOK_CTaskSimplePlayerOnFoot_MakeAbortable (); +void HOOK_CPed_AddGogglesModel (); +void HOOK_CAutomobile_BlowUpCar (); +void HOOK_CBike_BlowUpCar (); +void HOOK_CHeli_BlowUpCar (); +void HOOK_CPlane_BlowUpCar (); +void HOOK_CBoat_BlowUpCar (); +void HOOK_CFire_ProcessFire_BurnPed (); +void HOOK_CExplosion_Update_SetPedsOnFire (); +void HOOK_CWorld_SetPedsOnFire (); void vehicle_lights_init (); @@ -366,7 +412,7 @@ void CMultiplayerSA::InitHooks() HookInstall(HOOKPOS_CWorld_SetWorldOnFire, (DWORD)HOOK_CWorld_SetWorldOnFire, 5); HookInstall(HOOKPOS_CTaskSimplePlayerOnFire_ProcessPed, (DWORD)HOOK_CTaskSimplePlayerOnFire_ProcessPed, 5); HookInstall(HOOKPOS_CFire_ProcessFire, (DWORD)HOOK_CFire_ProcessFire, 5); - HookInstall(HOOKPOS_CExplosion_Update, (DWORD)HOOK_CExplosion_Update, 5); + HookInstall(HOOKPOS_CExplosion_Update_TryToStartFire, (DWORD)HOOK_CExplosion_Update_TryToStartFire, 5); HookInstall(HOOKPOS_CWeapon_FireAreaEffect, (DWORD)HOOK_CWeapon_FireAreaEffect, 5); HookInstall(HOOKPOS_CGame_Process, (DWORD)HOOK_CGame_Process, 10 ); HookInstall(HOOKPOS_Idle, (DWORD)HOOK_Idle, 10 ); @@ -376,6 +422,16 @@ void CMultiplayerSA::InitHooks() HookInstall(HOOKPOS_CAnimManager_AddAnimation, (DWORD)HOOK_CAnimManager_AddAnimation, 10 ); HookInstall(HOOKPOS_CAnimManager_BlendAnimation, (DWORD)HOOK_CAnimManager_BlendAnimation, 7 ); HookInstall(HOOKPOS_CPed_GetWeaponSkill, (DWORD)HOOK_CPed_GetWeaponSkill, 8 ); + HookInstall(HOOKPOS_CTaskSimplePlayerOnFoot_MakeAbortable, (DWORD)HOOK_CTaskSimplePlayerOnFoot_MakeAbortable, 11 ); + HookInstall(HOOKPOS_CPed_AddGogglesModel, (DWORD)HOOK_CPed_AddGogglesModel, 6); + HookInstall(HOOKPOS_CAutomobile_BlowUpCar, (DWORD)HOOK_CAutomobile_BlowUpCar, 6 ); + HookInstall(HOOKPOS_CBike_BlowUpCar, (DWORD)HOOK_CBike_BlowUpCar, 10 ); + HookInstall(HOOKPOS_CHeli_BlowUpCar, (DWORD)HOOK_CHeli_BlowUpCar, 11 ); + HookInstall(HOOKPOS_CPlane_BlowUpCar, (DWORD)HOOK_CPlane_BlowUpCar, 12 ); + HookInstall(HOOKPOS_CBoat_BlowUpCar, (DWORD)HOOK_CBoat_BlowUpCar, 7 ); + HookInstall(HOOKPOS_CFire_ProcessFire_BurnPed, (DWORD)HOOK_CFire_ProcessFire_BurnPed, 7 ); + HookInstall(HOOKPOS_CExplosion_Update_SetPedsOnFire, (DWORD)HOOK_CExplosion_Update_SetPedsOnFire, 6 ); + HookInstall(HOOKPOS_CWorld_SetPedsOnFire, (DWORD)HOOK_CWorld_SetPedsOnFire, 7 ); HookInstallCall ( CALL_CBike_ProcessRiderAnims, (DWORD)HOOK_CBike_ProcessRiderAnims ); HookInstallCall ( CALL_Render3DStuff, (DWORD)HOOK_Render3DStuff ); @@ -899,18 +955,6 @@ void CMultiplayerSA::InitHooks() // Remove this check so that no bullets are ignored. *(BYTE *)0x73FDF9 = 0xEB; - // Disallow spraying gang tags - // Nop the whole CTagManager::IsTag function and replace its body with: - // xor eax, eax - // ret - // to make it always return false - memset ( (void *)0x49CCE0, 0x90, 74 ); - *(DWORD *)(0x49CCE0) = 0x90C3C033; - // Remove also some hardcoded and inlined checks for if it's a tag - memset ( (void *)0x53374A, 0x90, 56 ); - *(BYTE *)(0x4C4403) = 0xEB; - - // Allow turning on vehicle lights even if the engine is off memset ( (void *)0x6E1DBC, 0x90, 8 ); @@ -1110,6 +1154,14 @@ void CMultiplayerSA::DisableBirds ( bool bDisabled ) *(BYTE *)0x712330 = 0xA1; } +void CMultiplayerSA::DisableQuickReload ( bool bDisabled ) +{ + if ( bDisabled ) + *(WORD *)0x60B4F6 = 0x08EB; + else + *(WORD *)0x60B4F6 = 0x027C; +} + void CMultiplayerSA::SetCloudsEnabled ( bool bDisabled ) { //volumetric clouds @@ -1272,6 +1324,16 @@ void CMultiplayerSA::SetPreHudDrawHandler ( PreHudDrawHandler * pHandler ) m_pPreHudDrawHandler = pHandler; } +void CMultiplayerSA::SetBlowUpCarHandler ( BlowUpCarHandler * pHandler ) +{ + m_pBlowUpCarHandler = pHandler; +} + +void CMultiplayerSA::SetPedOnFireHandler ( PedOnFireHandler * pHandler ) +{ + m_pPedOnFireHandler = pHandler; +} + void CMultiplayerSA::HideRadar ( bool bHide ) { bHideRadar = bHide; @@ -2493,16 +2555,26 @@ void _declspec(naked) HOOK_CVehicle_ResetAfterRender () /** ** Objects **/ +static bool bObjectIsAGangTag = false; static void SetObjectAlpha () { bEntityHasAlpha = false; + bObjectIsAGangTag = false; if ( dwAlphaEntity ) { CObject* pObject = pGameInterface->GetPools()->GetObject ( (DWORD *)dwAlphaEntity ); if ( pObject ) { - GetAlphaAndSetNewValues ( pObject->GetAlpha () ); + if ( pObject->IsAGangTag () ) + { + // For some weird reason, gang tags don't appear unsprayed + // if we don't set their alpha to a value less than 255. + bObjectIsAGangTag = true; + GetAlphaAndSetNewValues ( SharedUtil::Min ( pObject->GetAlpha (), (unsigned char)254 ) ); + } + else + GetAlphaAndSetNewValues ( pObject->GetAlpha () ); } } } @@ -2543,7 +2615,30 @@ void _declspec(naked) HOOK_CObject_Render () mov dwCObjectRenderRet, edx mov edx, HOOK_CObject_PostRender mov [esp], edx + pushad + } + + if ( bObjectIsAGangTag ) + goto render_a_tag; + + _asm + { + popad jmp FUNC_CEntity_Render +render_a_tag: + popad + // We simulate here the header of the CEntity::Render function + // but then go straight to CTagManager::RenderTagForPC. + push ecx + push esi + mov eax, [esi+0x18] + test eax, eax + jz no_clump + mov eax, 0x534331 + jmp eax +no_clump: + mov eax, 0x5343EB + jmp eax } } @@ -3785,7 +3880,7 @@ void _declspec(naked) HOOK_CFire_ProcessFire () } } -void _declspec(naked) HOOK_CExplosion_Update () +void _declspec(naked) HOOK_CExplosion_Update_TryToStartFire () { // Set the new fire's creator to the explosion's creator _asm @@ -3797,7 +3892,7 @@ void _declspec(naked) HOOK_CExplosion_Update () mov ecx, [esi-0x18] mov [eax+0x14], ecx fail: - jmp RETURN_CExplosion_Update + jmp RETURN_CExplosion_Update_TryToStartFire } } @@ -4023,7 +4118,7 @@ bool CPed_GetWeaponSkill () CPed* pLocalPlayerPed = pGameInterface->GetPools ()->GetPedFromRef ( (DWORD)1 ); if ( pPed != pLocalPlayerPed ) { - if ( weaponSkillWeapon >= 22 && weaponSkillWeapon <= 32 ) + if ( weaponSkillWeapon >= WEAPONTYPE_PISTOL && weaponSkillWeapon <= WEAPONTYPE_TEC9 ) { CPlayerPed* playerPed = dynamic_cast < CPlayerPed* > ( pPed ); if ( playerPed ) @@ -4076,4 +4171,377 @@ void _declspec(naked) HOOK_CPed_GetWeaponSkill () jmp RETURN_CPed_GetWeaponSkill } } +} + +CPedSAInterface * pOnFootPed; +DWORD FUNC_CCamera_ClearPlayerWeaponMode = 0x50AB10; +DWORD FUNC_CWeaponEffects_ClearCrossHair = 0x742C60; +void _declspec(naked) HOOK_CTaskSimplePlayerOnFoot_MakeAbortable () +{ + /* Replaces: + call CCamera_ClearPlayerWeaponMode + mov eax, [esi+598h] + push eax + call CWeaponEffects_ClearCrossHair + */ + _asm + { + mov pOnFootPed, esi + pushad + } + if ( IsLocalPlayer ( pOnFootPed ) ) + { + _asm + { + popad + call FUNC_CCamera_ClearPlayerWeaponMode + mov eax, [esi+598h] + push eax + call FUNC_CWeaponEffects_ClearCrossHair + jmp RETURN_CTaskSimplePlayerOnFoot_MakeAbortable + } + } + else + { + _asm + { + popad + mov eax, [esi+598h] + push eax + jmp RETURN_CTaskSimplePlayerOnFoot_MakeAbortable + } + } +} + +// Actually check if the ped putting on goggles is the local player before +// applying the visual effect +bool _cdecl CPed_AddGogglesModelCheck ( void* pPedInterface ) +{ + return pGameInterface->GetPools ()->GetPed ( (DWORD *)pPedInterface ) == pGameInterface->GetPools ()->GetPedFromRef ( 1 ); +} + +void _declspec(naked) HOOK_CPed_AddGogglesModel () +{ + _asm + { + push esi + call CPed_AddGogglesModelCheck + add esp, 4 + + test al, al + jz skip + mov eax, [esp+0x10] + mov [esi+0x500], eax + mov byte ptr [eax], 1 + + skip: + jmp RETURN_CPed_AddGogglesModel + } +} + +void CMultiplayerSA::DeleteAndDisableGangTags () +{ + static bool bDisabled = false; + if ( !bDisabled ) + { + bDisabled = true; + + // Destroy all the world tags + DWORD dwFunc = FUNC_CWorld_Remove; + + for ( unsigned int i = 0; i < *VAR_NumTags; ++i ) + { + DWORD* pTagInterface = VAR_TagInfoArray [ i << 1 ]; + if ( pTagInterface ) + { + _asm + { + push pTagInterface + call dwFunc + add esp, 4 + } + } + } + + dwFunc = FUNC_CTagManager_ShutdownForRestart; + _asm call dwFunc + + // Disallow spraying gang tags + // Nop the whole CTagManager::IsTag function and replace its body with: + // xor eax, eax + // ret + // to make it always return false + memset ( (void *)0x49CCE0, 0x90, 74 ); + *(DWORD *)(0x49CCE0) = 0x90C3C033; + // Remove also some hardcoded and inlined checks for if it's a tag + memset ( (void *)0x53374A, 0x90, 56 ); + *(BYTE *)(0x4C4403) = 0xEB; + + // Force all tags to have zero tagged alpha + // + // Replaces: + // call CVisibilityPlugins::GetUserValue + // push esi + // movzx edi, al + // call CVisibilityPlugins::GetUserValue + // movzx eax, ax + // + // With: + // push esi + // xor eax, eax + // xor edi, edi + // + // No need to worry about the push esi, because at 0x49CE8E the stack is restored. + // CVisibilityPlugins::GetUserValue is a cdecl. + memset ( (void *)0x49CE58, 0x90, 5 ); + memset ( (void *)0x49CE5E, 0x90, 11 ); + *(unsigned short *)0x49CE5E = 0xC033; + *(unsigned short *)0x49CE60 = 0xFF33; + } +} + + +CVehicleSAInterface * pBlowUpCarVehicle; +CEntitySAInterface * pBlowUpCarResponsible; +void BlowUpCar () +{ + CVehicle * pVehicle = pGameInterface->GetPools ()->GetVehicle ( ( DWORD * ) pBlowUpCarVehicle ); + if ( pVehicle ) + { + CEntity * pEntity = pGameInterface->GetPools ()->GetEntity ( ( DWORD * ) pBlowUpCarResponsible ); + if ( m_pBlowUpCarHandler ) m_pBlowUpCarHandler ( pVehicle, pEntity ); + } +} + +void _declspec(naked) HOOK_CAutomobile_BlowUpCar () +{ + _asm + { + mov pBlowUpCarVehicle, ecx + mov eax, [esp+4] + mov pBlowUpCarResponsible, eax + pushad + } + + BlowUpCar (); + + _asm + { + popad + sub esp, 24h + push ebx + push ebp + push esi + jmp RETURN_CAutomobile_BlowUpCar + } +} + +void _declspec(naked) HOOK_CBike_BlowUpCar () +{ + _asm + { + mov pBlowUpCarVehicle, ecx + mov eax, [esp+4] + mov pBlowUpCarResponsible, eax + pushad + } + + BlowUpCar (); + + _asm + { + popad + push esi + mov esi, ecx + test byte ptr [esi+42Ah], 20h + jmp RETURN_CBike_BlowUpCar + } +} + +void _declspec(naked) HOOK_CHeli_BlowUpCar () +{ + _asm + { + mov pBlowUpCarVehicle, ecx + mov eax, [esp+4] + mov pBlowUpCarResponsible, eax + pushad + } + + BlowUpCar (); + + _asm + { + popad + push ebx + push esi + mov esi, ecx + test byte ptr [esi+42Ah], 20h + jmp RETURN_CHeli_BlowUpCar + } +} + +void _declspec(naked) HOOK_CPlane_BlowUpCar () +{ + _asm + { + mov pBlowUpCarVehicle, ecx + mov eax, [esp+4] + mov pBlowUpCarResponsible, eax + pushad + } + + BlowUpCar (); + + _asm + { + popad + push ebx + push ebp + push esi + mov esi, ecx + test byte ptr [esi+42Ah], 20 + jmp RETURN_CPlane_BlowUpCar + } +} + +void _declspec(naked) HOOK_CBoat_BlowUpCar () +{ + _asm + { + mov pBlowUpCarVehicle, ecx + mov eax, [esp+16] + mov pBlowUpCarResponsible, eax + pushad + } + + BlowUpCar (); + + _asm + { + popad + sub esp, 18h + push ebx + push ebp + mov ebx, ecx + jmp RETURN_CBoat_BlowUpCar + } +} + +CFireSAInterface * pOnFireFire; +CPedSAInterface * pOnFirePed; +bool CFire_ProcessFire_BurnPed () +{ + // Grab the burning ped + CPed * pPed = pGameInterface->GetPools ()->GetPed ( ( DWORD * ) pOnFirePed ); + if ( pPed ) + { + // Got a fire? + CFire * pFire = pGameInterface->GetFireManager ()->GetFire ( pOnFireFire ); + if ( pFire ) + { + // Call the handler + if ( m_pPedOnFireHandler ) return m_pPedOnFireHandler ( pPed, pFire, NULL ); + } + } + // Continue + return true; +} +DWORD FUNC_CPlayerPed_DoStuffToGoOnFire = 0x60A020; +void _declspec(naked) HOOK_CFire_ProcessFire_BurnPed () +{ + // Store the ped and fire vars + _asm + { + mov pOnFireFire, esi + mov pOnFirePed, eax + pushad + } + + // Should we continue and let the ped burn? + if ( CFire_ProcessFire_BurnPed () ) + { + _asm + { + popad + mov ecx, eax + call FUNC_CPlayerPed_DoStuffToGoOnFire + jmp RETURN_CFire_ProcessFire_BurnPed + } + } + else + { + // Skip burning + _asm + { + popad + jmp RETURN_CANCEL_CFire_ProcessFire_BurnPed + } + } + +} + +DWORD FUNC_CWorld_SetPedsOnFire = 0x565610; +CExplosionSAInterface * pUpdatingExplosion = NULL; +void _declspec(naked) HOOK_CExplosion_Update_SetPedsOnFire () +{ + // Save the CExplosion from CExplosion::Update + _asm + { + mov pUpdatingExplosion, esi + sub pUpdatingExplosion, 48 + + push edi + call FUNC_CWorld_SetPedsOnFire + jmp RETURN_CExplosion_Update_SetPedsOnFire + } +} + +CPedSAInterface * pSetPedsOnFirePed; +bool CWorld_SetPedsOnFire () +{ + // Grab the ped + CPed * pPed = pGameInterface->GetPools ()->GetPed ( ( DWORD * ) pSetPedsOnFirePed ); + if ( pPed ) + { + // Got an explosion? + CExplosion * pExplosion = pGameInterface->GetExplosionManager ()->GetExplosion ( pUpdatingExplosion ); + if ( pExplosion ) + { + // Call the handler + if ( m_pPedOnFireHandler ) return m_pPedOnFireHandler ( pPed, NULL, pExplosion ); + } + } + // Continue + return true; +} +void _declspec(naked) HOOK_CWorld_SetPedsOnFire () +{ + // Store the burning ped + _asm + { + mov pSetPedsOnFirePed, edi + pushad + } + + // Continue and let him burn? + if ( CWorld_SetPedsOnFire () ) + { + _asm + { + popad + push 2 + push 1B58h + jmp RETURN_CWorld_SetPedsOnFire + } + } + else + { + // Skip it + _asm + { + popad + jmp RETURN_CANCEL_CWorld_SetPedsOnFire + } + } } \ No newline at end of file diff --git a/MTA10/multiplayer_sa/CMultiplayerSA.h b/MTA10/multiplayer_sa/CMultiplayerSA.h index 07c659015f..4e708e691b 100644 --- a/MTA10/multiplayer_sa/CMultiplayerSA.h +++ b/MTA10/multiplayer_sa/CMultiplayerSA.h @@ -49,6 +49,9 @@ class CMultiplayerSA : public CMultiplayer void DisableEnterExitVehicleKey ( bool bDisabled ); void DisableHeatHazeEffect ( bool bDisable ); void DisableAllVehicleWeapons ( bool bDisable ); + void DisableZoneNames ( bool bDisabled ); + void DisableBirds ( bool bDisabled ); + void DisableQuickReload ( bool bDisable ); bool GetExplosionsDisabled (); void DisableExplosions ( bool bDisabled ); @@ -65,11 +68,11 @@ class CMultiplayerSA : public CMultiplayer void SetAddAnimationHandler ( AddAnimationHandler * pHandler ); void SetBlendAnimationHandler ( BlendAnimationHandler * pHandler ); void SetPreHudDrawHandler ( PreHudDrawHandler * pHandler ); + void SetBlowUpCarHandler ( BlowUpCarHandler * pHandler ); + void SetPedOnFireHandler ( PedOnFireHandler * pHandler ); void AllowMouseMovement ( bool bAllow ); void DoSoundHacksOnLostFocus ( bool bLostFocus ); - void DisableZoneNames ( bool bDisabled ); - void DisableBirds ( bool bDisabled ); void SetSkyColor ( unsigned char TopRed, unsigned char TopGreen, unsigned char TopBlue, unsigned char BottomRed, unsigned char BottomGreen, unsigned char BottomBlue ); void ResetSky (); void SetWaterColor ( float fWaterRed, float fWaterGreen, float fWaterBlue, float fWaterAlpha ); @@ -118,6 +121,7 @@ class CMultiplayerSA : public CMultiplayer void SetAkimboTargetUp ( bool bUp ) { m_bAkimboTargetUp = bUp; }; void AllowCreatedObjectsInVerticalLineTest ( bool bOn ); + void DeleteAndDisableGangTags (); CVector m_vecAkimboTarget; bool m_bAkimboTargetUp; diff --git a/MTA10/multiplayer_sa/multiplayer_shotsync.cpp b/MTA10/multiplayer_sa/multiplayer_shotsync.cpp index 507ce40b35..700556747d 100644 --- a/MTA10/multiplayer_sa/multiplayer_shotsync.cpp +++ b/MTA10/multiplayer_sa/multiplayer_shotsync.cpp @@ -147,6 +147,9 @@ VOID WriteGunDirectionDataForPed ( CPedSAInterface * pPedInterface, float * fGun // store it if ( fGunDirectionX && fGunDirectionY ) { + // Make sure our pitch is updated (fixes first-person weapons not moving) + *fGunDirectionY = pGameInterface->GetCamera ()->Find3rdPersonQuickAimPitch (); + LocalShotSyncData.m_fArmDirectionX = *fGunDirectionX; LocalShotSyncData.m_fArmDirectionY = *fGunDirectionY; } diff --git a/MTA10/sdk/core/CKeyBindsInterface.h b/MTA10/sdk/core/CKeyBindsInterface.h index 59afcf0781..e5b862701b 100644 --- a/MTA10/sdk/core/CKeyBindsInterface.h +++ b/MTA10/sdk/core/CKeyBindsInterface.h @@ -19,9 +19,12 @@ class CKeyFunctionBind; class CControlFunctionBind; +struct SBindableKey; typedef void ( *KeyFunctionBindHandler ) ( CKeyFunctionBind* pBind ); typedef void ( *ControlFunctionBindHandler ) ( CControlFunctionBind* pBind ); +typedef void ( *KeyStrokeHandler ) ( const SBindableKey * pKey, bool bState ); +typedef bool ( *CharacterKeyHandler ) ( WPARAM wChar ); enum eKeyData { @@ -197,6 +200,8 @@ class CKeyBindsInterface virtual bool IsKey ( const char* szKey ) = 0; virtual char* GetKeyFromGTARelative ( int iGTAKey ) = 0; virtual const SBindableKey* GetBindableFromMessage ( UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bState ) = 0; + virtual void SetKeyStrokeHandler ( KeyStrokeHandler Handler ) = 0; + virtual void SetCharacterKeyHandler ( CharacterKeyHandler Handler ) = 0; // Control/action funcs virtual char* GetControlFromAction ( eControllerAction action ) = 0; diff --git a/MTA10/sdk/game/CAERadioTrackManager.h b/MTA10/sdk/game/CAERadioTrackManager.h index 0de1bdf471..9b4b089f80 100644 --- a/MTA10/sdk/game/CAERadioTrackManager.h +++ b/MTA10/sdk/game/CAERadioTrackManager.h @@ -17,13 +17,13 @@ class CAERadioTrackManager { public: - virtual BYTE GetCurrentRadioStationID ( void ) = 0; - virtual BYTE IsVehicleRadioActive ( void ) = 0; - virtual char * GetRadioStationName ( BYTE bStationID ) = 0; - virtual BOOL IsRadioOn ( void ) = 0; - virtual VOID SetBassSetting ( DWORD dwBass ) = 0; - virtual VOID Reset ( void ) = 0; - virtual VOID StartRadio ( BYTE bStationID, BYTE bUnknown ) = 0; + virtual BYTE GetCurrentRadioStationID ( void ) = 0; + virtual BYTE IsVehicleRadioActive ( void ) = 0; + virtual char * GetRadioStationName ( BYTE bStationID ) = 0; + virtual BOOL IsRadioOn ( void ) = 0; + virtual void SetBassSetting ( DWORD dwBass ) = 0; + virtual void Reset ( void ) = 0; + virtual void StartRadio ( BYTE bStationID, BYTE bUnknown ) = 0; }; #endif \ No newline at end of file diff --git a/MTA10/sdk/game/CCamera.h b/MTA10/sdk/game/CCamera.h index c5569fd9d1..dec249f1d8 100644 --- a/MTA10/sdk/game/CCamera.h +++ b/MTA10/sdk/game/CCamera.h @@ -105,7 +105,8 @@ class CCamera virtual VOID SetMatrix ( CMatrix * matrix )=0; virtual VOID SetCamPositionForFixedMode ( CVector * vecPosition, CVector * vecUpOffset )=0; virtual VOID Find3rdPersonCamTargetVector ( FLOAT fDistance, CVector * vecGunMuzzle, CVector * vecSource, CVector * vecTarget )=0; - virtual BYTE GetActiveCam()=0; + virtual float Find3rdPersonQuickAimPitch ( void ) = 0; + virtual BYTE GetActiveCam()=0; virtual CCam * GetCam(BYTE bCameraID)=0; virtual VOID SetWidescreen(BOOL bWidescreen)=0; virtual BOOL GetWidescreen()=0; diff --git a/MTA10/sdk/game/CExplosionManager.h b/MTA10/sdk/game/CExplosionManager.h index 540063796d..4318b03f1e 100644 --- a/MTA10/sdk/game/CExplosionManager.h +++ b/MTA10/sdk/game/CExplosionManager.h @@ -17,6 +17,8 @@ #include "Common.h" #include "CEntity.h" +class CExplosionSAInterface; + class CExplosionManager { public: @@ -24,6 +26,7 @@ class CExplosionManager virtual VOID RemoveAllExplosionsInArea ( CVector * vecPosition, FLOAT fRadius ) = 0; virtual VOID RemoveAllExplosions ( void ) = 0; virtual CExplosion * GetExplosion ( DWORD ID ) = 0; + virtual CExplosion * GetExplosion ( CExplosionSAInterface * explosion ) = 0; virtual CExplosion * FindFreeExplosion ( void ) = 0; }; diff --git a/MTA10/sdk/game/CFireManager.h b/MTA10/sdk/game/CFireManager.h index ecb31ac0f8..921b0a1bfc 100644 --- a/MTA10/sdk/game/CFireManager.h +++ b/MTA10/sdk/game/CFireManager.h @@ -16,6 +16,7 @@ #include "CFire.h" #include "CEntity.h" +class CFireSAInterface; class CFireManager { @@ -26,6 +27,7 @@ class CFireManager virtual CFire * StartFire ( CVector & vecPosition, float fSize )=0; virtual VOID ExtinguishAllFires ( )=0; virtual CFire * GetFire ( DWORD ID )=0; + virtual CFire * GetFire ( CFireSAInterface * fire ) = 0; }; #endif \ No newline at end of file diff --git a/MTA10/sdk/game/CGame.h b/MTA10/sdk/game/CGame.h index 424ea7c661..00a481c54b 100644 --- a/MTA10/sdk/game/CGame.h +++ b/MTA10/sdk/game/CGame.h @@ -177,6 +177,8 @@ class __declspec(novtable) CGame virtual bool IsCheatEnabled ( const char* szCheatName ) = 0; virtual bool SetCheatEnabled ( const char* szCheatName, bool bEnable ) = 0; virtual void ResetCheats () = 0; + + virtual bool IsTakingPhoto ( void ) = 0; }; #endif \ No newline at end of file diff --git a/MTA10/sdk/game/CObject.h b/MTA10/sdk/game/CObject.h index 25edcad62c..26da86d19f 100644 --- a/MTA10/sdk/game/CObject.h +++ b/MTA10/sdk/game/CObject.h @@ -33,6 +33,8 @@ class CObject : public virtual CPhysical virtual void SetAlpha ( unsigned char ucAlpha ) = 0; virtual unsigned char GetAlpha ( ) = 0; + + virtual bool IsAGangTag ( ) const = 0; }; #endif \ No newline at end of file diff --git a/MTA10/sdk/game/CPedModelInfo.h b/MTA10/sdk/game/CPedModelInfo.h index de46b45a8f..997a2967b2 100644 --- a/MTA10/sdk/game/CPedModelInfo.h +++ b/MTA10/sdk/game/CPedModelInfo.h @@ -16,7 +16,7 @@ typedef unsigned long AssocGroupId; -class CPedModelInfo : public CModelInfo +class CPedModelInfo { public: virtual void SetMotionAnimGroup ( AssocGroupId animGroup ) = 0; diff --git a/MTA10/sdk/game/CStreaming.h b/MTA10/sdk/game/CStreaming.h index 474b48e17d..ec05598019 100644 --- a/MTA10/sdk/game/CStreaming.h +++ b/MTA10/sdk/game/CStreaming.h @@ -16,6 +16,7 @@ class CStreaming { public: virtual void RequestAnimations ( int i, int j ) = 0; + virtual void RequestSpecialModel ( DWORD model, const char * szTexture, DWORD channel ) = 0; }; #endif \ No newline at end of file diff --git a/MTA10/sdk/game/CTasks.h b/MTA10/sdk/game/CTasks.h index 0f496d3f8f..62a6902fde 100644 --- a/MTA10/sdk/game/CTasks.h +++ b/MTA10/sdk/game/CTasks.h @@ -58,7 +58,7 @@ class CTasks virtual CTaskSimpleRunNamedAnim * CreateTaskSimpleRunNamedAnim ( const char* pAnimName, const char* pAnimGroupName, const int flags, const float fBlendDelta, const int iTime = -1, const bool bDontInterrupt = false, const bool bRunInSequence = false, const bool bOffsetPed = false, const bool bHoldLastFrame = false )=0; virtual CTaskComplexDie * CreateTaskComplexDie ( const eWeaponType eMeansOfDeath=WEAPONTYPE_UNARMED, const AssocGroupId animGroup=0/*ANIM_STD_PED*/, const AnimationId anim=0/*ANIM_STD_KO_FRONT*/, const float fBlendDelta=4.0f, const float fAnimSpeed=0.0f, const bool bBeingKilledByStealth=false, const bool bFallingToDeath=false, const int iFallToDeathDir=0, const bool bFallToDeathOverRailing=false )=0; - virtual CTaskSimpleStealthKill * CreateTaskSimpleStealthKill ( bool bAttacker, class CPed * pPed, const AnimationId anim )=0; + virtual CTaskSimpleStealthKill * CreateTaskSimpleStealthKill ( bool bAttacker, class CPed * pPed, const AssocGroupId animGroup )=0; virtual CTaskComplexSunbathe * CreateTaskComplexSunbathe ( class CObject* pTowel, const bool bStartStanding )=0; diff --git a/MTA10/sdk/gui/CGUIGridList.h b/MTA10/sdk/gui/CGUIGridList.h index b9cb673f2f..7a4194d38a 100644 --- a/MTA10/sdk/gui/CGUIGridList.h +++ b/MTA10/sdk/gui/CGUIGridList.h @@ -57,6 +57,7 @@ class CGUIGridList : public CGUIElement virtual char* GetItemText ( int iRow, int hColumn ) = 0; virtual int SetItemText ( int iRow, int hColumn, const char* szText, bool bNumber = false, bool bSection = false, bool bFast = false ) = 0; virtual void SetItemData ( int iRow, int hColumn, void* pData ) = 0; + virtual void SetItemData ( int iRow, int hColumn, const char* pszData ) = 0; virtual void* GetItemData ( int iRow, int hColumn ) = 0; virtual void SetHorizontalScrollBar ( bool bEnabled ) = 0; diff --git a/MTA10/sdk/gui/CGUIListItem.h b/MTA10/sdk/gui/CGUIListItem.h index 9482305635..f3b3db4fe8 100644 --- a/MTA10/sdk/gui/CGUIListItem.h +++ b/MTA10/sdk/gui/CGUIListItem.h @@ -20,14 +20,15 @@ class CGUIListItem public: virtual ~CGUIListItem ( void ) {}; - virtual void SetFont ( const char *szFontName ) = 0; - virtual void SetText ( const char *Text ) = 0; - virtual std::string GetText ( void ) = 0; + virtual std::string GetText ( void ) const = 0; + virtual void SetText ( const char *pszText ) = 0; - virtual void* GetData ( void ) = 0; - virtual void SetData ( void* pData ) = 0; + virtual void* GetData ( void ) const = 0; + virtual void SetData ( void* pData ) = 0; + virtual void SetData ( const char* pszData ) = 0; virtual void SetDisabled ( bool bDisabled ) = 0; + virtual void SetFont ( const char *szFontName ) = 0; virtual void SetImage ( CGUIStaticImage* Image ) = 0; virtual bool GetSelectedState ( void ) = 0; diff --git a/MTA10/sdk/multiplayer/CMultiplayer.h b/MTA10/sdk/multiplayer/CMultiplayer.h index 55e0db96a1..a4fd74e4b1 100644 --- a/MTA10/sdk/multiplayer/CMultiplayer.h +++ b/MTA10/sdk/multiplayer/CMultiplayer.h @@ -42,6 +42,8 @@ typedef void ( IdleHandler ) ( void ); typedef void ( AddAnimationHandler ) ( RpClump * pClump, AssocGroupId animGroup, AnimationId animID ); typedef void ( BlendAnimationHandler ) ( RpClump * pClump, AssocGroupId animGroup, AnimationId animID, float fBlendDelta ); typedef void ( PreHudDrawHandler ) ( void ); +typedef void ( BlowUpCarHandler ) ( class CVehicle * pVehicle, class CEntity * pResponsible ); +typedef bool ( PedOnFireHandler ) ( class CPed * pPed, class CFire * pFire, class CExplosion * pExplosion ); /** * This class contains information used for shot syncing, one exists per player. @@ -105,6 +107,9 @@ class CMultiplayer virtual void DisablePadHandler ( bool bDisabled ) = 0; virtual void DisableHeatHazeEffect ( bool bDisable ) = 0; virtual void DisableAllVehicleWeapons ( bool bDisable ) = 0; + virtual void DisableZoneNames ( bool bDisabled ) = 0; // move to CHud + virtual void DisableBirds ( bool bDisabled ) = 0; + virtual void DisableQuickReload ( bool bDisable ) = 0; virtual bool GetExplosionsDisabled () = 0; virtual void DisableExplosions ( bool bDisabled ) = 0; @@ -121,11 +126,11 @@ class CMultiplayer virtual void SetAddAnimationHandler ( AddAnimationHandler * pHandler ) = 0; virtual void SetBlendAnimationHandler ( BlendAnimationHandler * pHandler ) = 0; virtual void SetPreHudDrawHandler ( PreHudDrawHandler * pHandler ) = 0; + virtual void SetBlowUpCarHandler ( BlowUpCarHandler * pHandler ) = 0; + virtual void SetPedOnFireHandler ( PedOnFireHandler * pHandler ) = 0; virtual void AllowMouseMovement ( bool bAllow ) = 0; virtual void DoSoundHacksOnLostFocus ( bool bLostFocus ) = 0; - virtual void DisableZoneNames ( bool bDisabled ) = 0; // move to CHud - virtual void DisableBirds ( bool bDisabled ) = 0; virtual void SetSkyColor ( unsigned char TopRed, unsigned char TopGreen, unsigned char TopBlue, unsigned char BottomRed, unsigned char BottomGreen, unsigned char BottomBlue ) = 0; virtual void ResetSky () = 0; virtual void SetWaterColor ( float fWaterRed, float fWaterGreen, float fWaterBlue, float fWaterAlpha ) = 0; @@ -176,6 +181,7 @@ class CMultiplayer virtual void SetAkimboTargetUp ( bool bUp ) = 0; virtual void AllowCreatedObjectsInVerticalLineTest ( bool bOn ) = 0; + virtual void DeleteAndDisableGangTags () = 0; }; #endif diff --git a/MTA10/version.h b/MTA10/version.h index cc193bb321..6d7eacc162 100644 --- a/MTA10/version.h +++ b/MTA10/version.h @@ -1,6 +1,6 @@ #define MTA_DM_VERSION 0x0100 #define MTA_DM_VERSIONSTRING "1.0" -#define MTA_DM_ASE_VERSION "1.0" +#define MTA_DM_ASE_VERSION "1.0.1n" #define MTA_DM_BUILDTYPE "Custom" #define MTA_DM_FULL_STRING "MTA:SA Client" -#define MTA_DM_NETCODE_VERSION 0x161 +#define MTA_DM_NETCODE_VERSION 0x165 diff --git a/MTA10_Server/mods/deathmatch/StdInc.h b/MTA10_Server/mods/deathmatch/StdInc.h index ec610da475..433b0b8823 100644 --- a/MTA10_Server/mods/deathmatch/StdInc.h +++ b/MTA10_Server/mods/deathmatch/StdInc.h @@ -8,6 +8,7 @@ #include #include +#include #include #include diff --git a/MTA10_Server/mods/deathmatch/acl.xml b/MTA10_Server/mods/deathmatch/acl.xml index 5476a3b5cd..2342ba601c 100644 --- a/MTA10_Server/mods/deathmatch/acl.xml +++ b/MTA10_Server/mods/deathmatch/acl.xml @@ -58,11 +58,17 @@ + + + + + + @@ -76,6 +82,8 @@ + + @@ -99,7 +107,7 @@ - + @@ -145,11 +153,13 @@ - + + + @@ -164,6 +174,12 @@ + + + + + + @@ -211,4 +227,4 @@ - \ No newline at end of file + diff --git a/MTA10_Server/mods/deathmatch/editor.conf b/MTA10_Server/mods/deathmatch/editor.conf index 9b055a28cc..fb6bf441ca 100644 --- a/MTA10_Server/mods/deathmatch/editor.conf +++ b/MTA10_Server/mods/deathmatch/editor.conf @@ -76,6 +76,7 @@ + diff --git a/MTA10_Server/mods/deathmatch/local.conf b/MTA10_Server/mods/deathmatch/local.conf index 332e24f62d..46f442cff9 100644 --- a/MTA10_Server/mods/deathmatch/local.conf +++ b/MTA10_Server/mods/deathmatch/local.conf @@ -75,8 +75,10 @@ + + @@ -84,6 +86,8 @@ - + + + diff --git a/MTA10_Server/mods/deathmatch/logic/CBlip.cpp b/MTA10_Server/mods/deathmatch/logic/CBlip.cpp index 241dce8505..1552b49e7e 100644 --- a/MTA10_Server/mods/deathmatch/logic/CBlip.cpp +++ b/MTA10_Server/mods/deathmatch/logic/CBlip.cpp @@ -135,11 +135,7 @@ bool CBlip::ReadSpecialData ( void ) const CVector & CBlip::GetPosition ( void ) { // Are we attached to something? - if ( m_pAttachedTo ) - { - // Update our stored position to where we should be, before returning - m_vecPosition = m_pAttachedTo->GetPosition () + m_vecAttachedPosition; - } + if ( m_pAttachedTo ) GetAttachedPosition ( m_vecPosition ); return m_vecPosition; } diff --git a/MTA10_Server/mods/deathmatch/logic/CColShape.cpp b/MTA10_Server/mods/deathmatch/logic/CColShape.cpp index bcba0de376..5bc10524c0 100644 --- a/MTA10_Server/mods/deathmatch/logic/CColShape.cpp +++ b/MTA10_Server/mods/deathmatch/logic/CColShape.cpp @@ -48,6 +48,13 @@ void CColShape::Unlink ( void ) } +const CVector & CColShape::GetPosition ( void ) +{ + if ( m_pAttachedTo ) GetAttachedPosition ( m_vecPosition ); + return m_vecPosition; +} + + void CColShape::CallHitCallback ( CElement& Element ) { // Call the callback with us as the shape if it exists diff --git a/MTA10_Server/mods/deathmatch/logic/CColShape.h b/MTA10_Server/mods/deathmatch/logic/CColShape.h index 712bae2951..dbe6b91be8 100644 --- a/MTA10_Server/mods/deathmatch/logic/CColShape.h +++ b/MTA10_Server/mods/deathmatch/logic/CColShape.h @@ -41,7 +41,7 @@ class CColShape : public CElement inline bool IsEnabled ( void ) { return m_bIsEnabled; }; inline void SetEnabled ( bool bEnabled ) { m_bIsEnabled = bEnabled; }; - virtual const CVector& GetPosition ( void ) { return m_vecPosition; }; + const CVector& GetPosition ( void ); virtual void SetPosition ( const CVector& vecPosition ) { m_vecPosition = vecPosition; }; void CallHitCallback ( CElement& Element ); diff --git a/MTA10_Server/mods/deathmatch/logic/CElement.cpp b/MTA10_Server/mods/deathmatch/logic/CElement.cpp index f4c6d6805f..ef645bb379 100644 --- a/MTA10_Server/mods/deathmatch/logic/CElement.cpp +++ b/MTA10_Server/mods/deathmatch/logic/CElement.cpp @@ -9,6 +9,7 @@ * Jax <> * Cecill Etheredge <> * lil_Toady <> +* Alberto Alonso * * Multi Theft Auto is available from http://www.multitheftauto.com/ * @@ -54,6 +55,7 @@ CElement::CElement ( CElement* pParent, CXMLNode* pNode ) } m_uiTypeHash = HashString ( m_strTypeName.c_str () ); + CElement::AddEntityFromRoot ( m_uiTypeHash, this ); // Make an event manager for us m_pEventManager = new CMapEventManager; @@ -115,13 +117,24 @@ CElement::~CElement ( void ) // Deallocate our unique ID CElementIDs::PushUniqueID ( this ); + + CElement::RemoveEntityFromRoot ( m_uiTypeHash, this ); +} + + +const CVector & CElement::GetPosition ( void ) +{ + if ( m_pAttachedTo ) GetAttachedPosition ( m_vecPosition ); + return m_vecPosition; } void CElement::SetTypeName ( std::string strTypeName ) { + CElement::RemoveEntityFromRoot ( m_uiTypeHash, this ); m_uiTypeHash = HashString ( strTypeName.c_str () ); m_strTypeName = strTypeName; + CElement::AddEntityFromRoot ( m_uiTypeHash, this ); } @@ -180,7 +193,15 @@ void CElement::FindAllChildrenByType ( const char* szType, lua_State* pLua ) // Add all children of the given type to the table unsigned int uiIndex = 0; unsigned int uiTypeHash = HashString ( szType ); - FindAllChildrenByTypeIndex ( uiTypeHash, pLua, uiIndex ); + + if ( this == g_pGame->GetMapManager ()->GetRootElement () ) + { + GetEntitiesFromRoot ( uiTypeHash, pLua ); + } + else + { + FindAllChildrenByTypeIndex ( uiTypeHash, pLua, uiIndex ); + } } @@ -1049,6 +1070,7 @@ bool CElement::IsAttachable ( void ) case CElement::OBJECT: case CElement::MARKER: case CElement::PICKUP: + case CElement::COLSHAPE: { return true; break; @@ -1070,6 +1092,7 @@ bool CElement::IsAttachToable ( void ) case CElement::OBJECT: case CElement::MARKER: case CElement::PICKUP: + case CElement::COLSHAPE: { return true; break; @@ -1080,6 +1103,31 @@ bool CElement::IsAttachToable ( void ) } +void CElement::GetAttachedPosition ( CVector & vecPosition ) +{ + if ( m_pAttachedTo ) + { + CVector vecRotation; + vecPosition = m_pAttachedTo->GetPosition (); + m_pAttachedTo->GetRotation ( vecRotation ); + + CVector vecPositionOffset = m_vecAttachedPosition; + RotateVector ( vecPositionOffset, vecRotation ); + vecPosition += vecPositionOffset; + } +} + + +void CElement::GetAttachedRotation ( CVector & vecRotation ) +{ + if ( m_pAttachedTo ) + { + m_pAttachedTo->GetRotation ( vecRotation ); + vecRotation += m_vecAttachedRotation; + } +} + + unsigned char CElement::GenerateSyncTimeContext ( void ) { // Increment the sync time index @@ -1102,3 +1150,58 @@ bool CElement::CanUpdateSync ( unsigned char ucRemote ) ucRemote == 0 || m_ucSyncTimeContext == 0 ); } + + +// Entities from root optimization for getElementsByType +CElement::t_mapEntitiesFromRoot CElement::ms_mapEntitiesFromRoot; +bool CElement::ms_bEntitiesFromRootInitialized = false; + +void CElement::StartupEntitiesFromRoot () +{ + if ( !ms_bEntitiesFromRootInitialized ) + { + ms_mapEntitiesFromRoot.set_deleted_key ( (unsigned int)0x00000000 ); + ms_mapEntitiesFromRoot.set_empty_key ( (unsigned int)0xFFFFFFFF ); + ms_bEntitiesFromRootInitialized = true; + } +} + +void CElement::AddEntityFromRoot ( unsigned int uiTypeHash, CElement* pEntity ) +{ + std::list < CElement* >& listEntities = ms_mapEntitiesFromRoot [ uiTypeHash ]; + listEntities.push_front ( pEntity ); +} + +void CElement::RemoveEntityFromRoot ( unsigned int uiTypeHash, CElement* pEntity ) +{ + t_mapEntitiesFromRoot::iterator find = ms_mapEntitiesFromRoot.find ( uiTypeHash ); + if ( find != ms_mapEntitiesFromRoot.end () ) + { + std::list < CElement* >& listEntities = find->second; + listEntities.remove ( pEntity ); + if ( listEntities.size () == 0 ) + ms_mapEntitiesFromRoot.erase ( find ); + } +} + +void CElement::GetEntitiesFromRoot ( unsigned int uiTypeHash, lua_State* pLua ) +{ + t_mapEntitiesFromRoot::iterator find = ms_mapEntitiesFromRoot.find ( uiTypeHash ); + if ( find != ms_mapEntitiesFromRoot.end () ) + { + const std::list < CElement* > & listEntities = find->second; + std::list < CElement* >::const_reverse_iterator i; + CElement* pEntity; + unsigned int uiIndex = 0; + + for ( i = listEntities.rbegin (); i != listEntities.rend (); ++i ) + { + pEntity = *i; + + // Add it to the table + lua_pushnumber ( pLua, ++uiIndex ); + lua_pushelement ( pLua, pEntity ); + lua_settable ( pLua, -3 ); + } + } +} diff --git a/MTA10_Server/mods/deathmatch/logic/CElement.h b/MTA10_Server/mods/deathmatch/logic/CElement.h index 6ab085bf28..98cf0c9ea3 100644 --- a/MTA10_Server/mods/deathmatch/logic/CElement.h +++ b/MTA10_Server/mods/deathmatch/logic/CElement.h @@ -9,6 +9,7 @@ * Jax <> * Cecill Etheredge <> * lil_Toady <> +* Alberto Alonso * * Multi Theft Auto is available from http://www.multitheftauto.com/ * @@ -87,10 +88,12 @@ class CElement inline ElementID GetID ( void ) { return m_ID; }; - virtual const CVector& GetPosition ( void ) { return m_vecPosition; }; + virtual const CVector& GetPosition ( void ); virtual const CVector& GetLastPosition ( void ) { return m_vecLastPosition; }; virtual void SetPosition ( const CVector& vecPosition ) { m_vecLastPosition = m_vecPosition; m_vecPosition = vecPosition; }; + virtual void GetRotation ( CVector & vecRotation ) { vecRotation = CVector (); } + virtual bool IsPerPlayerEntity ( void ) { return false; }; CElement* FindChild ( const char* szName, unsigned int uiIndex, bool bRecursive ); @@ -179,6 +182,8 @@ class CElement bool IsElementAttached ( CElement* pElement ); virtual bool IsAttachable ( void ); virtual bool IsAttachToable ( void ); + void GetAttachedPosition ( CVector & vecPosition ); + void GetAttachedRotation ( CVector & vecRotation ); inline CElementGroup* GetElementGroup ( void ) { return m_pElementGroup; } inline void SetElementGroup ( CElementGroup * elementGroup ){ m_pElementGroup = elementGroup; } @@ -248,6 +253,18 @@ class CElement std::list < class CPed * > m_OriginSourceUsers; unsigned char m_ucInterior; bool m_bMapCreated; + + // Optimization for getElementsByType starting at root +public: + static void StartupEntitiesFromRoot ( ); +private: + static void AddEntityFromRoot ( unsigned int uiTypeHash, CElement* pEntity ); + static void RemoveEntityFromRoot ( unsigned int uiTypeHash, CElement* pEntity ); + static void GetEntitiesFromRoot ( unsigned int uiTypeHash, lua_State* pLua ); + + typedef google::dense_hash_map < unsigned int, std::list < CElement* > > t_mapEntitiesFromRoot; + static t_mapEntitiesFromRoot ms_mapEntitiesFromRoot; + static bool ms_bEntitiesFromRootInitialized; }; #endif diff --git a/MTA10_Server/mods/deathmatch/logic/CGame.cpp b/MTA10_Server/mods/deathmatch/logic/CGame.cpp index 7c16a1aed3..f520d197e9 100644 --- a/MTA10_Server/mods/deathmatch/logic/CGame.cpp +++ b/MTA10_Server/mods/deathmatch/logic/CGame.cpp @@ -356,6 +356,9 @@ bool CGame::Start ( int iArgumentCount, char* szArguments [] ) m_pVoiceServer = NULL; #endif + // Startup the getElementsByType from root optimizations + CElement::StartupEntitiesFromRoot (); + m_pGroups = new CGroups; m_pClock = new CClock; m_pBlipManager = new CBlipManager; @@ -884,14 +887,6 @@ bool CGame::ProcessPacket ( CPacket& Packet ) void CGame::JoinPlayer ( CPlayer& Player ) { - // He's joined now - Player.SetStatus ( STATUS_JOINED ); - - // Console - char szIP [64]; - Player.GetSourceIP ( szIP ); - CLogger::LogPrintf ( "JOIN: %s joined the game (IP: %s)\n", Player.GetNick (), szIP ); - // Set the root element as his parent // NOTE: Make sure he doesn't get any entities sent to him because we're sending him soon Player.SetDoNotSendEntities ( true ); @@ -905,6 +900,17 @@ void CGame::JoinPlayer ( CPlayer& Player ) m_pMainConfig->GetHTTPDownloadType (), m_pMainConfig->GetHTTPPort (), m_pMainConfig->GetHTTPDownloadURL ().c_str () ) ); +} + +void CGame::InitialDataStream ( CPlayer& Player ) +{ + // He's joined now + Player.SetStatus ( STATUS_JOINED ); + + // Console + char szIP [64]; + Player.GetSourceIP ( szIP ); + CLogger::LogPrintf ( "JOIN: %s joined the game (IP: %s)\n", Player.GetNick (), szIP ); // Tell the other players about him CPlayerListPacket PlayerNotice; @@ -1005,7 +1011,6 @@ void CGame::JoinPlayer ( CPlayer& Player ) } } - void CGame::QuitPlayer ( CPlayer& Player, CClient::eQuitReasons Reason, bool bSayInConsole, const char* szKickReason, const char* szResponsiblePlayer ) { // Grab quit reaason @@ -1754,6 +1759,8 @@ void CGame::Packet_ExplosionSync ( CExplosionSyncPacket& Packet ) // Call the onVehicleExplode event CLuaArguments Arguments; pVehicle->CallEvent ( "onVehicleExplode", Arguments ); + //Update our engine State + pVehicle->SetEngineOn( false ); } else { @@ -2114,6 +2121,9 @@ void CGame::Packet_Vehicle_InOut ( CVehicleInOutPacket& Packet ) // The vehicle is no longer idle pVehicle->SetIdleTime ( 0 ); + //Update our engine State + pVehicle->SetEngineOn( true ); + // Tell everyone he's in (they should warp him in) CVehicleInOutPacket Reply ( ID, ucOccupiedSeat, VEHICLE_NOTIFY_IN_RETURN ); Reply.SetSourceElement ( pPlayer ); diff --git a/MTA10_Server/mods/deathmatch/logic/CGame.h b/MTA10_Server/mods/deathmatch/logic/CGame.h index 6509fda8eb..713c4af4a0 100644 --- a/MTA10_Server/mods/deathmatch/logic/CGame.h +++ b/MTA10_Server/mods/deathmatch/logic/CGame.h @@ -211,6 +211,7 @@ class CGame #endif void JoinPlayer ( CPlayer& Player ); + void InitialDataStream ( CPlayer& Player ); void QuitPlayer ( CPlayer& Player, CClient::eQuitReasons Reason = CClient::QUIT_QUIT, bool bSayInConsole = true, const char* szKickReason = "None", const char* szResponsiblePlayer = "None" ); inline class CLuaManager* GetLuaManager ( void ) { return m_pLuaManager; }; diff --git a/MTA10_Server/mods/deathmatch/logic/CKeyBinds.cpp b/MTA10_Server/mods/deathmatch/logic/CKeyBinds.cpp index 4f894e416f..a8e91c2eb7 100644 --- a/MTA10_Server/mods/deathmatch/logic/CKeyBinds.cpp +++ b/MTA10_Server/mods/deathmatch/logic/CKeyBinds.cpp @@ -202,7 +202,7 @@ bool CKeyBinds::ProcessKey ( const char* szKey, bool bHitState, eKeyBindType bin CKeyBind* pKeyBind = NULL; list < CKeyBind* > cloneList = m_List; list < CKeyBind* > ::iterator iter = cloneList.begin (); - for ( ; iter != cloneList.end () ; iter++ ) + for ( ; iter != cloneList.end () ; ++iter ) { pKeyBind = *iter; if ( !pKeyBind->IsBeingDeleted () && pKeyBind->GetType () == bindType ) @@ -323,7 +323,7 @@ bool CKeyBinds::RemoveKeyFunction ( const char* szKey, CLuaMain* pLuaMain, bool } } } - iter++; + ++iter; } return bFound; } @@ -334,7 +334,7 @@ bool CKeyBinds::KeyFunctionExists ( const char* szKey, CLuaMain* pLuaMain, bool bool bFound = false; list < CKeyBind* > cloneList = m_List; list < CKeyBind* > ::iterator iter = cloneList.begin (); - for ( ; iter != cloneList.end () ; iter++ ) + for ( ; iter != cloneList.end () ; ++iter ) { if ( (*iter)->GetType () == KEY_BIND_FUNCTION ) { @@ -381,7 +381,7 @@ void CKeyBinds::RemoveAllKeys ( CLuaMain* pLuaMain ) } } } - iter++; + ++iter; } } @@ -464,7 +464,7 @@ bool CKeyBinds::RemoveControlFunction ( const char* szControl, CLuaMain* pLuaMai } } } - iter++; + ++iter; } return bFound; } @@ -475,7 +475,7 @@ bool CKeyBinds::ControlFunctionExists ( const char* szControl, CLuaMain* pLuaMai bool bFound = false; list < CKeyBind* > cloneList = m_List; list < CKeyBind* > ::iterator iter = cloneList.begin (); - for ( ; iter != cloneList.end () ;iter++ ) + for ( ; iter != cloneList.end () ; ++iter ) { if ( (*iter)->GetType () == KEY_BIND_CONTROL_FUNCTION ) { diff --git a/MTA10_Server/mods/deathmatch/logic/CLanBroadcast.cpp b/MTA10_Server/mods/deathmatch/logic/CLanBroadcast.cpp index 8a80df9203..94ddddd26b 100644 --- a/MTA10_Server/mods/deathmatch/logic/CLanBroadcast.cpp +++ b/MTA10_Server/mods/deathmatch/logic/CLanBroadcast.cpp @@ -20,8 +20,10 @@ CLanBroadcast::CLanBroadcast ( unsigned short usServerPort ) m_SockAddr.sin_family = AF_INET; m_SockAddr.sin_port = htons ( SERVER_LIST_BROADCAST_PORT ); m_SockAddr.sin_addr.s_addr = INADDR_ANY; - - setsockopt ( m_Socket, SOL_SOCKET, SO_REUSEADDR, "1", sizeof ( "1" ) ); + + // Enable socket reusage + const int Flags = 1; + setsockopt ( m_Socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&Flags, sizeof ( Flags ) ); // Bind the socket if ( bind ( m_Socket, ( sockaddr* )&m_SockAddr, sizeof ( m_SockAddr ) ) != 0 ) @@ -35,7 +37,7 @@ CLanBroadcast::CLanBroadcast ( unsigned short usServerPort ) unsigned long ulNonBlock = 1; ioctlsocket ( m_Socket, FIONBIO, &ulNonBlock ); #else - fcntl(m_Socket, F_SETFL, O_NONBLOCK); + fcntl ( m_Socket, F_SETFL, fcntl( m_Socket, F_GETFL ) | O_NONBLOCK ); #endif // Set up the query messages diff --git a/MTA10_Server/mods/deathmatch/logic/CObject.cpp b/MTA10_Server/mods/deathmatch/logic/CObject.cpp index 528e9e083a..4140185543 100644 --- a/MTA10_Server/mods/deathmatch/logic/CObject.cpp +++ b/MTA10_Server/mods/deathmatch/logic/CObject.cpp @@ -134,11 +134,8 @@ bool CObject::ReadSpecialData ( void ) const CVector& CObject::GetPosition ( void ) { // Are we attached to something? - if ( m_pAttachedTo ) - { - m_vecPosition = m_pAttachedTo->GetPosition (); - m_vecPosition += m_vecAttachedPosition; - } + if ( m_pAttachedTo ) GetAttachedPosition ( m_vecPosition ); + // Are we moving? else if ( IsMoving () ) { @@ -189,7 +186,7 @@ void CObject::GetRotation ( CVector & vecRotation ) vecRotation = m_vecRotation; // Are we attached to something? - if ( m_pAttachedTo ) vecRotation += m_vecAttachedRotation; + if ( m_pAttachedTo ) GetAttachedRotation ( vecRotation ); // Are we moving? else if ( IsMoving () ) diff --git a/MTA10_Server/mods/deathmatch/logic/CObject.h b/MTA10_Server/mods/deathmatch/logic/CObject.h index c08f791379..ea6e4df3e9 100644 --- a/MTA10_Server/mods/deathmatch/logic/CObject.h +++ b/MTA10_Server/mods/deathmatch/logic/CObject.h @@ -47,8 +47,8 @@ class CObject : public CElement const CVector& GetPosition ( void ); void SetPosition ( const CVector& vecPosition ); - void GetRotation ( CVector & vecRotatation ); - void SetRotation ( const CVector& vecRotatation ); + void GetRotation ( CVector & vecRotation ); + void SetRotation ( const CVector& vecRotation ); bool IsMoving ( void ); void Move ( const CVector& vecPosition, const CVector& vecRotation, unsigned long ulTime ); diff --git a/MTA10_Server/mods/deathmatch/logic/CPlayer.cpp b/MTA10_Server/mods/deathmatch/logic/CPlayer.cpp index 62d1ed50ac..c7776d6a69 100644 --- a/MTA10_Server/mods/deathmatch/logic/CPlayer.cpp +++ b/MTA10_Server/mods/deathmatch/logic/CPlayer.cpp @@ -55,7 +55,7 @@ CPlayer::CPlayer ( CPlayerManager* pPlayerManager, class CScriptDebugging* pScri m_bCamFadedIn = false; SetCamFadeColor ( 0, 0, 0 ); - m_pPlayerAttacker = NULL; + m_PlayerAttackerID = INVALID_ELEMENT_ID; m_ucAttackWeapon = 0xFF; m_ucAttackBodyPart = 0xFF; @@ -203,8 +203,12 @@ void CPlayer::Send ( const CPacket& Packet, NetServerPacketOrdering packetOrderi Reliability = PACKET_RELIABILITY_UNRELIABLE; } } - NetServerPacketPriority packetPriority = PACKET_PRIORITY_HIGH; - if ( ulFlags & PACKET_LOW_PRIORITY ) + NetServerPacketPriority packetPriority = PACKET_PRIORITY_MEDIUM; + if ( ulFlags & PACKET_HIGH_PRIORITY ) + { + packetPriority = PACKET_PRIORITY_HIGH; + } + else if ( ulFlags & PACKET_LOW_PRIORITY ) { packetPriority = PACKET_PRIORITY_LOW; } @@ -346,6 +350,14 @@ void CPlayer::SetCamFadeColor ( unsigned char ucRed, unsigned char ucGreen, unsi } +void CPlayer::SetDamageInfo ( ElementID ElementID, unsigned char ucWeapon, unsigned char ucBodyPart ) +{ + m_PlayerAttackerID = ElementID; + m_ucAttackWeapon = ucWeapon; + m_ucAttackBodyPart = ucBodyPart; +} + + void CPlayer::SetTeam ( CTeam* pTeam, bool bChangeTeam ) { if ( pTeam == m_pTeam ) return; diff --git a/MTA10_Server/mods/deathmatch/logic/CPlayer.h b/MTA10_Server/mods/deathmatch/logic/CPlayer.h index 906c6efef0..ae9fe4af79 100644 --- a/MTA10_Server/mods/deathmatch/logic/CPlayer.h +++ b/MTA10_Server/mods/deathmatch/logic/CPlayer.h @@ -141,10 +141,10 @@ class CPlayer : public CPed, public CClient inline bool IsCamFadedIn ( void ) { return m_bCamFadedIn; }; inline void SetCamFadedIn ( bool bCamFadedIn ) { m_bCamFadedIn = bCamFadedIn; }; - inline void SetDamageInfo ( CElement* pElement, unsigned char ucWeapon, unsigned char ucBodyPart ) { m_pPlayerAttacker = pElement, m_ucAttackWeapon = ucWeapon, m_ucAttackBodyPart = ucBodyPart; } - inline CElement* GetPlayerAttacker ( void ) { return m_pPlayerAttacker; } - inline unsigned char GetAttackWeapon ( void ) { return m_ucAttackWeapon; } - inline unsigned char GetAttackBodyPart ( void ) { return m_ucAttackBodyPart; } + void SetDamageInfo ( ElementID ElementID, unsigned char ucWeapon, unsigned char ucBodyPart ); + ElementID GetPlayerAttacker ( void ) { return m_PlayerAttackerID; } + unsigned char GetAttackWeapon ( void ) { return m_ucAttackWeapon; } + unsigned char GetAttackBodyPart ( void ) { return m_ucAttackBodyPart; } inline CTeam* GetTeam ( void ) { return m_pTeam; } void SetTeam ( CTeam* pTeam, bool bChangeTeam = false ); @@ -247,7 +247,7 @@ class CPlayer : public CPed, public CClient unsigned long m_ulCamFadeColor; bool m_bCamFadedIn; - CElement* m_pPlayerAttacker; + ElementID m_PlayerAttackerID; unsigned char m_ucAttackWeapon; unsigned char m_ucAttackBodyPart; diff --git a/MTA10_Server/mods/deathmatch/logic/CPlayerManager.cpp b/MTA10_Server/mods/deathmatch/logic/CPlayerManager.cpp index 9790554768..7c76d397f6 100644 --- a/MTA10_Server/mods/deathmatch/logic/CPlayerManager.cpp +++ b/MTA10_Server/mods/deathmatch/logic/CPlayerManager.cpp @@ -287,6 +287,8 @@ void CPlayerManager::BroadcastOnlyJoined ( const CPacket& Packet, CPlayer* pSkip bool CPlayerManager::IsValidPlayerModel ( unsigned short usPlayerModel ) { return ( usPlayerModel == 0 || + usPlayerModel == 1 || + usPlayerModel == 2 || usPlayerModel == 7 || (usPlayerModel >= 9 && usPlayerModel != 208 && @@ -296,9 +298,12 @@ bool CPlayerManager::IsValidPlayerModel ( unsigned short usPlayerModel ) usPlayerModel != 74 && usPlayerModel != 65 && usPlayerModel != 42 && - usPlayerModel <= 264) || + usPlayerModel <= 272) || (usPlayerModel >= 274 && - usPlayerModel <= 288) ); + usPlayerModel <= 288) || + (usPlayerModel >= 290 && + usPlayerModel <= 311 && + usPlayerModel != 299) ); } diff --git a/MTA10_Server/mods/deathmatch/logic/CRPCFunctions.cpp b/MTA10_Server/mods/deathmatch/logic/CRPCFunctions.cpp index 1aa41d3e8c..79bf1bd7ec 100644 --- a/MTA10_Server/mods/deathmatch/logic/CRPCFunctions.cpp +++ b/MTA10_Server/mods/deathmatch/logic/CRPCFunctions.cpp @@ -45,6 +45,7 @@ CRPCFunctions::~CRPCFunctions ( void ) void CRPCFunctions::AddHandlers ( void ) { AddHandler ( PLAYER_INGAME_NOTICE, PlayerInGameNotice ); + AddHandler ( INITIAL_DATA_STREAM, InitialDataStream ); AddHandler ( PLAYER_TARGET, PlayerTarget ); AddHandler ( PLAYER_WEAPON, PlayerWeapon ); AddHandler ( KEY_BIND, KeyBind ); @@ -99,6 +100,20 @@ void CRPCFunctions::PlayerInGameNotice ( NetBitStreamInterface & bitStream ) } } +void CRPCFunctions::InitialDataStream ( NetBitStreamInterface & bitStream ) +{ + // Already sent initial stuff? Protocol error + if ( m_pSourcePlayer->IsJoined () ) + { + DisconnectPlayer ( g_pGame, *m_pSourcePlayer, "Protocol error: Already joined" ); + } + else + { + // Send him the initial stuff + g_pGame->InitialDataStream ( *m_pSourcePlayer ); + } +} + void CRPCFunctions::PlayerTarget ( NetBitStreamInterface & bitStream ) { diff --git a/MTA10_Server/mods/deathmatch/logic/CRPCFunctions.h b/MTA10_Server/mods/deathmatch/logic/CRPCFunctions.h index 7266eab884..416422d677 100644 --- a/MTA10_Server/mods/deathmatch/logic/CRPCFunctions.h +++ b/MTA10_Server/mods/deathmatch/logic/CRPCFunctions.h @@ -46,6 +46,7 @@ class CRPCFunctions protected: DECLARE_RPC ( PlayerInGameNotice ); + DECLARE_RPC ( InitialDataStream ); DECLARE_RPC ( PlayerTarget ); DECLARE_RPC ( PlayerWeapon ); DECLARE_RPC ( KeyBind ); @@ -60,6 +61,7 @@ class CRPCFunctions enum eRPCFunctions { PLAYER_INGAME_NOTICE, + INITIAL_DATA_STREAM, PLAYER_TARGET, PLAYER_WEAPON, KEY_BIND, diff --git a/MTA10_Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp b/MTA10_Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp index e0beff6b66..a1384b9650 100644 --- a/MTA10_Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp +++ b/MTA10_Server/mods/deathmatch/logic/CStaticFunctionDefinitions.cpp @@ -1108,22 +1108,21 @@ bool CStaticFunctionDefinitions::SetElementDimension ( CElement* pElement, unsig { assert ( pElement ); - switch ( pElement->GetType () ) + if ( pElement->GetType () == CElement::TEAM ) { - // Client side elements - case CElement::TEAM: + CTeam* pTeam = static_cast < CTeam* > ( pElement ); + list < CPlayer* > ::const_iterator iter = pTeam->PlayersBegin (); + for ( ; iter != pTeam->PlayersEnd () ; iter++ ) { - CTeam* pTeam = static_cast < CTeam* > ( pElement ); - list < CPlayer* > ::const_iterator iter = pTeam->PlayersBegin (); - for ( ; iter != pTeam->PlayersEnd () ; iter++ ) + if ( (*iter)->IsSpawned () ) { - if ( (*iter)->IsSpawned () ) - { - (*iter)->SetDimension ( usDimension ); - } + (*iter)->SetDimension ( usDimension ); } - break; } + } + + switch ( pElement->GetType () ) + { case CElement::PED: case CElement::PLAYER: { @@ -1133,6 +1132,7 @@ bool CStaticFunctionDefinitions::SetElementDimension ( CElement* pElement, unsig return false; } } + case CElement::TEAM: case CElement::COLSHAPE: case CElement::DUMMY: case CElement::VEHICLE: @@ -1508,6 +1508,11 @@ bool CStaticFunctionDefinitions::SetPlayerName ( CElement* pElement, const char* // Check that it doesn't already exist, or if it matches our current nick case-independantly (means we changed to the same nick but in a different case) if ( ( szNick && stricmp ( szNick, szName ) == 0 ) || m_pPlayerManager->Get ( szName ) == NULL ) { + // Call the event + CLuaArguments Arguments; + Arguments.PushString ( szNick ); + Arguments.PushString ( szName ); + pPlayer->CallEvent ( "onPlayerChangeNick", Arguments ); // Tell the console CLogger::LogPrintf ( "NICK: %s is now known as %s\n", szNick, szName ); @@ -3904,6 +3909,8 @@ bool CStaticFunctionDefinitions::BlowVehicle ( CElement* pElement, bool bExplode pVehicle->SetHealth ( 0.0f ); pVehicle->SetBlowTime ( ::GetTime () ); pVehicle->GenerateSyncTimeContext (); + //Update our engine State + pVehicle->SetEngineOn( false ); CBitStream BitStream; BitStream.pBitStream->Write ( pVehicle->GetID () ); @@ -7065,7 +7072,7 @@ bool CStaticFunctionDefinitions::SetGlitchEnabled ( std::string strGlitchName, b if ( g_pGame->IsGlitchEnabled ( strGlitchName ) != bEnabled ) { CBitStream BitStream; - BitStream.pBitStream->Write ( g_pGame->GetGlitchIndex(strGlitchName) ); + BitStream.pBitStream->Write ( static_cast < unsigned char > ( g_pGame->GetGlitchIndex(strGlitchName) ) ); BitStream.pBitStream->Write ( bEnabled ); m_pPlayerManager->BroadcastOnlyJoined ( CLuaPacket ( SET_GLITCH_ENABLED, *BitStream.pBitStream ) ); diff --git a/MTA10_Server/mods/deathmatch/logic/CVehicle.cpp b/MTA10_Server/mods/deathmatch/logic/CVehicle.cpp index 93ef1a7934..eafe7d9341 100644 --- a/MTA10_Server/mods/deathmatch/logic/CVehicle.cpp +++ b/MTA10_Server/mods/deathmatch/logic/CVehicle.cpp @@ -303,11 +303,7 @@ bool CVehicle::ReadSpecialData ( void ) const CVector & CVehicle::GetPosition ( void ) { // Are we attached to something? - if ( m_pAttachedTo ) - { - // Update our stored position to where we should be, before returning - m_vecPosition = m_pAttachedTo->GetPosition () + m_vecAttachedPosition; - } + if ( m_pAttachedTo ) GetAttachedPosition ( m_vecPosition ); return m_vecPosition; } @@ -327,6 +323,31 @@ void CVehicle::SetPosition ( const CVector & vecPosition ) } +void CVehicle::GetRotation ( CVector & vecRotation ) +{ + if ( m_pAttachedTo ) GetAttachedRotation ( vecRotation ); + else + { + GetRotationDegrees ( vecRotation ); + ConvertDegreesToRadians ( vecRotation ); + } +} + + +void CVehicle::GetRotationDegrees ( CVector & vecRotation ) +{ + if ( m_pAttachedTo ) GetAttachedRotation ( vecRotation ); + else vecRotation = m_vecRotationDegrees; +} + + +void CVehicle::SetRotationDegrees ( const CVector & vecRotation ) +{ + if ( m_pAttachedTo ) return; + m_vecRotationDegrees = vecRotation; +} + + void CVehicle::SetModel ( unsigned short usModel ) { if ( usModel != m_usModel ) diff --git a/MTA10_Server/mods/deathmatch/logic/CVehicle.h b/MTA10_Server/mods/deathmatch/logic/CVehicle.h index c374bd8d58..5b9d9d1f07 100644 --- a/MTA10_Server/mods/deathmatch/logic/CVehicle.h +++ b/MTA10_Server/mods/deathmatch/logic/CVehicle.h @@ -142,8 +142,9 @@ class CVehicle : public CElement const CVector& GetPosition ( void ); void SetPosition ( const CVector& vecPosition ); - inline void GetRotationDegrees ( CVector& vecRotation ) { vecRotation = m_vecRotationDegrees; }; - inline void SetRotationDegrees ( const CVector& vecRotation ) { m_vecRotationDegrees = vecRotation; }; + inline void GetRotation ( CVector& vecRotation ); + void GetRotationDegrees ( CVector& vecRotation ); + void SetRotationDegrees ( const CVector& vecRotation ); inline const CVector& GetVelocity ( void ) { return m_vecVelocity; }; inline void SetVelocity ( const CVector& vecVelocity ) { m_vecVelocity = vecVelocity; }; diff --git a/MTA10_Server/mods/deathmatch/logic/CVehicleManager.cpp b/MTA10_Server/mods/deathmatch/logic/CVehicleManager.cpp index 8ba7ae35e1..57ab443579 100644 --- a/MTA10_Server/mods/deathmatch/logic/CVehicleManager.cpp +++ b/MTA10_Server/mods/deathmatch/logic/CVehicleManager.cpp @@ -31,16 +31,17 @@ static unsigned char g_ucMaxPassengers [] = { 3, 1, 1, 1, 3, 3, 0, 1, 1, 3, 1, 1 // List over all vehicles with their special attributes #define VEHICLE_HAS_TURRENT 0x001UL //1 -#define VEHICLE_HAS_SIRENES 0x002UL //2 +#define VEHICLE_HAS_SIRENS 0x002UL //2 #define VEHICLE_HAS_LANDING_GEARS 0x004UL //4 #define VEHICLE_HAS_ADJUSTABLE_PROPERTY 0x008UL //8 #define VEHICLE_HAS_SMOKE_TRAIL 0x010UL //16 #define VEHICLE_HAS_TAXI_LIGHTS 0x020UL //32 +#define VEHICLE_HAS_SEARCH_LIGHT 0x040UL //64 unsigned long g_ulVehicleAttributes [] = { 0, 0, 0, 0, 0, 0, 8, 3, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 32, 0, 0, 2, 0, // 400-424 0, 0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, // 425-449 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 450-474 - 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 475-499 + 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 64, 0, 0, // 475-499 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 0, 0, 0, 0, 0, 4, 12, 0, 0, 2, 8, // 500-524 8, 0, 0, 2, 0, 8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, // 525-549 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 550-574 @@ -212,7 +213,7 @@ bool CVehicleManager::HasTurret ( unsigned int uiModel ) bool CVehicleManager::HasSirens ( unsigned int uiModel ) { return ( IsValidModel ( uiModel ) && - ( g_ulVehicleAttributes[ uiModel - 400 ] & VEHICLE_HAS_SIRENES ) ); + ( g_ulVehicleAttributes[ uiModel - 400 ] & VEHICLE_HAS_SIRENS ) ); } bool CVehicleManager::HasTaxiLight ( unsigned int uiModel ) diff --git a/MTA10_Server/mods/deathmatch/logic/CVehicleNames.cpp b/MTA10_Server/mods/deathmatch/logic/CVehicleNames.cpp index 935120358b..1009cfa2ce 100644 --- a/MTA10_Server/mods/deathmatch/logic/CVehicleNames.cpp +++ b/MTA10_Server/mods/deathmatch/logic/CVehicleNames.cpp @@ -21,9 +21,9 @@ char szVehicleNameEmpty [] = ""; SVehicleName VehicleNames [] = { {"Landstalker"}, {"Bravura"}, {"Buffalo"}, {"Linerunner"}, {"Perennial"}, {"Sentinel"}, {"Dumper"}, {"Fire Truck"}, {"Trashmaster"}, {"Stretch"}, {"Manana"}, {"Infernus"}, {"Voodoo"}, {"Pony"}, {"Mule"}, {"Cheetah"}, {"Ambulance"}, {"Leviathan"}, {"Moonbeam"}, {"Esperanto"}, {"Taxi"}, {"Washington"}, {"Bobcat"}, {"Mr. Whoopee"}, {"BF Injection"}, {"Hunter"}, {"Premier"}, {"Enforcer"}, {"Securicar"}, {"Banshee"}, -{"Predator"}, {"Bus"}, {"Rhino"}, {"Barracks"}, {"Hotknife"}, {""}, {"Previon"}, {"Coach"}, {"Cabbie"}, {"Stallion"}, -{"Rumpo"}, {"RC Bandit"}, {"Romero"}, {"Packer"}, {"Monster 1", "Monster"}, {"Admiral"}, {"Squalo"}, {"Seasparrow"}, {"Pizzaboy"}, {""}, -{""}, {"Turismo"}, {"Speeder"}, {"Reefer"}, {"Tropic"}, {"Flatbed"}, {"Yankee"}, {"Caddy"}, {"Solair"}, {"Berkley's RC Van"}, +{"Predator"}, {"Bus"}, {"Rhino"}, {"Barracks"}, {"Hotknife"}, {"Trailer 1"}, {"Previon"}, {"Coach"}, {"Cabbie"}, {"Stallion"}, +{"Rumpo"}, {"RC Bandit"}, {"Romero"}, {"Packer"}, {"Monster 1", "Monster"}, {"Admiral"}, {"Squalo"}, {"Seasparrow"}, {"Pizzaboy"}, {"Tram"}, +{"Trailer 2"}, {"Turismo"}, {"Speeder"}, {"Reefer"}, {"Tropic"}, {"Flatbed"}, {"Yankee"}, {"Caddy"}, {"Solair"}, {"Berkley's RC Van"}, {"Skimmer"}, {"PCJ-600"}, {"Faggio"}, {"Freeway"}, {"RC Baron"}, {"RC Raider"}, {"Glendale"}, {"Oceanic"}, {"Sanchez"}, {"Sparrow"}, {"Patriot"}, {"Quadbike"}, {"Coastguard"}, {"Dinghy"}, {"Hermes"}, {"Sabre"}, {"Rustler"}, {"ZR-350"}, {"Walton"}, {"Regina"}, {"Comet"}, {"BMX"}, {"Burrito"}, {"Camper"}, {"Marquis"}, {"Baggage"}, {"Dozer"}, {"Maverick"}, {"News Chopper"}, {"Rancher"}, @@ -34,12 +34,12 @@ SVehicleName VehicleNames [] = { {"Landstalker"}, {"Bravura"}, {"Buffalo"}, {"Li {"Forklift"}, {"Tractor"}, {"Combine Harvester"}, {"Feltzer"}, {"Remington"}, {"Slamvan"}, {"Blade"}, {"Freight"}, {"Streak"}, {"Vortex"}, {"Vincent"}, {"Bullet"}, {"Clover"}, {"Sadler"}, {"Fire Truck Ladder"}, {"Hustler"}, {"Intruder"}, {"Primo"}, {"Cargobob"}, {"Tampa"}, {"Sunrise"}, {"Merit"}, {"Utility Van"}, {"Nevada"}, {"Yosemite"}, {"Windsor"}, {"Monster 2"}, {"Monster 3"}, {"Uranus"}, {"Jester"}, -{"Sultan"}, {"Stratum"}, {"Elegy"}, {"Raindance"}, {"RC Tiger"}, {"Flash"}, {"Tahoma"}, {"Savanna"}, {"Bandito"}, {""}, -{""}, {"Kart"}, {"Mower"}, {"Dune"}, {"Sweeper"}, {"Broadway"}, {"Tornado"}, {"AT-400"}, {"DFT-30"}, {"Huntley"}, -{"Stafford"}, {"BF-400"}, {"Newsvan"}, {"Tug"}, {""}, {"Emperor"}, {"Wayfarer"}, {"Euros"}, {"Hotdog"}, {"Club"}, -{""}, {""}, {"Andromada"}, {"Dodo"}, {"RC Cam"}, {"Launch"}, {"Police LS", "Police"}, {"Police SF"}, {"Police LV"}, {"Police Ranger", "Ranger"}, -{"Picador"}, {"S.W.A.T."}, {"Alpha"}, {"Phoenix"}, {"Glendale Damaged"}, {"Sadler"}, {""}, {""}, {""}, {"Boxville Mission"}, -{""} }; +{"Sultan"}, {"Stratum"}, {"Elegy"}, {"Raindance"}, {"RC Tiger"}, {"Flash"}, {"Tahoma"}, {"Savanna"}, {"Bandito"}, {"Freight Train Flatbed"}, +{"Streak Train Trailer"}, {"Kart"}, {"Mower"}, {"Dune"}, {"Sweeper"}, {"Broadway"}, {"Tornado"}, {"AT-400"}, {"DFT-30"}, {"Huntley"}, +{"Stafford"}, {"BF-400"}, {"Newsvan"}, {"Tug"}, {"Trailer (Tanker Commando)"}, {"Emperor"}, {"Wayfarer"}, {"Euros"}, {"Hotdog"}, {"Club"}, +{"Box Freight"}, {"Trailer 3"}, {"Andromada"}, {"Dodo"}, {"RC Cam"}, {"Launch"}, {"Police LS", "Police"}, {"Police SF"}, {"Police LV"}, {"Police Ranger", "Ranger"}, +{"Picador"}, {"S.W.A.T."}, {"Alpha"}, {"Phoenix"}, {"Glendale Damaged"}, {"Sadler"}, {"Baggage Trailer (covered)"}, {"Baggage Trailer (Uncovered)"}, {"Trailer (Stairs)"}, {"Boxville Mission"}, +{"Farm Trailer"} }; bool CVehicleNames::IsValidModel ( unsigned long ulModel ) { diff --git a/MTA10_Server/mods/deathmatch/logic/Utils.cpp b/MTA10_Server/mods/deathmatch/logic/Utils.cpp index 6229272ed6..05b2cd8e93 100644 --- a/MTA10_Server/mods/deathmatch/logic/Utils.cpp +++ b/MTA10_Server/mods/deathmatch/logic/Utils.cpp @@ -450,8 +450,6 @@ bool IsValidFilePath ( const char *szDir ) return true; } -#include - unsigned int HexToInt ( const char * szHex ) { unsigned int value = 0; diff --git a/MTA10_Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp b/MTA10_Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp index 17669b3c44..f3a20ab6ef 100644 --- a/MTA10_Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp +++ b/MTA10_Server/mods/deathmatch/logic/packets/CEntityAddPacket.cpp @@ -170,11 +170,13 @@ bool CEntityAddPacket::Write ( NetBitStreamInterface& BitStream ) const position.data.vecPosition = pObject->m_moveData.vecStopPosition; BitStream.Write ( &position ); - rotationRadians.data.vecRotation = pObject->m_moveData.vecStopRotation - rotationRadians.data.vecRotation; - BitStream.Write ( &rotationRadians ); + // Needs to be CVector as we can have a value of over 2xPI here (for multiple rotations) + CVector vecRotationRadians = pObject->m_moveData.vecStopRotation - rotationRadians.data.vecRotation; + BitStream.Write ( vecRotationRadians.fX ); + BitStream.Write ( vecRotationRadians.fY ); + BitStream.Write ( vecRotationRadians.fZ ); } - break; } diff --git a/MTA10_Server/mods/deathmatch/logic/packets/CPacket.h b/MTA10_Server/mods/deathmatch/logic/packets/CPacket.h index b7ef67f146..3355221778 100644 --- a/MTA10_Server/mods/deathmatch/logic/packets/CPacket.h +++ b/MTA10_Server/mods/deathmatch/logic/packets/CPacket.h @@ -28,7 +28,8 @@ enum { PACKET_RELIABLE = 1, PACKET_SEQUENCED = 2, - PACKET_LOW_PRIORITY = 4, + PACKET_HIGH_PRIORITY = 4, + PACKET_LOW_PRIORITY = 8, }; class CPacket diff --git a/MTA10_Server/mods/deathmatch/logic/packets/CPlayerJoinCompletePacket.h b/MTA10_Server/mods/deathmatch/logic/packets/CPlayerJoinCompletePacket.h index 79de38f781..32c95beeed 100644 --- a/MTA10_Server/mods/deathmatch/logic/packets/CPlayerJoinCompletePacket.h +++ b/MTA10_Server/mods/deathmatch/logic/packets/CPlayerJoinCompletePacket.h @@ -23,20 +23,20 @@ class CPlayerJoinCompletePacket : public CPacket public: CPlayerJoinCompletePacket ( void ); CPlayerJoinCompletePacket ( ElementID PlayerID, - unsigned char ucNumberOfPlayers, - ElementID RootElementID, - eHTTPDownloadType ucHTTPDownloadType, - unsigned short usHTTPDownloadPort, - const char* szHTTPDownloadURL ); + unsigned char ucNumberOfPlayers, + ElementID RootElementID, + eHTTPDownloadType ucHTTPDownloadType, + unsigned short usHTTPDownloadPort, + const char* szHTTPDownloadURL ); inline ePacketID GetPacketID ( void ) const { return PACKET_ID_SERVER_JOINEDGAME; }; - inline unsigned long GetFlags ( void ) const { return PACKET_RELIABLE | PACKET_SEQUENCED; }; + inline unsigned long GetFlags ( void ) const { return PACKET_RELIABLE | PACKET_SEQUENCED | PACKET_HIGH_PRIORITY; }; bool Write ( NetBitStreamInterface& BitStream ) const; inline ElementID GetPlayerID ( void ) { return m_PlayerID; }; inline unsigned char GetNumberOfPlayers ( void ) { return m_ucNumberOfPlayers; }; - inline eHTTPDownloadType GetHTTPDownloadType ( void ) { return m_ucHTTPDownloadType; }; + inline eHTTPDownloadType GetHTTPDownloadType ( void ) { return m_ucHTTPDownloadType; }; inline unsigned short GetHTTPDownloadPort ( void ) { return m_usHTTPDownloadPort; }; inline const char* GetHTTPDownloadURL ( void ) { return m_szHTTPDownloadURL; }; diff --git a/MTA10_Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp b/MTA10_Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp index 45243f5cb5..d321d70317 100644 --- a/MTA10_Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp +++ b/MTA10_Server/mods/deathmatch/logic/packets/CPlayerPuresyncPacket.cpp @@ -185,14 +185,13 @@ bool CPlayerPuresyncPacket::Read ( NetBitStreamInterface& BitStream ) } // Read out damage info if changed - if ( BitStream.ReadBit () == true ) - { + bool bDamageInfo = BitStream.ReadBit (); + if ( bDamageInfo ) + { ElementID DamagerID; if ( !BitStream.ReadCompressed ( DamagerID ) ) return false; - CElement* pElement = CElementIDs::GetElement ( DamagerID ); - SWeaponTypeSync weaponType; if ( !BitStream.Read ( &weaponType ) ) return false; @@ -201,7 +200,8 @@ bool CPlayerPuresyncPacket::Read ( NetBitStreamInterface& BitStream ) if ( !BitStream.Read ( &bodyPart ) ) return false; - pSourcePlayer->SetDamageInfo ( pElement, weaponType.data.ucWeaponType, bodyPart.data.uiBodypart ); + pSourcePlayer->SetDamageInfo ( DamagerID, weaponType.data.ucWeaponType, bodyPart.data.uiBodypart ); + bDamageInfo = true; } // If we know the player's dead, make sure the health we send on is 0 @@ -213,19 +213,30 @@ bool CPlayerPuresyncPacket::Read ( NetBitStreamInterface& BitStream ) pSourcePlayer->SetHealth ( fHealth ); // Less than last packet's frame? - if ( fHealthLoss > 0 || fArmorLoss > 0 ) + if ( fHealthLoss > FLOAT_EPSILON || fArmorLoss > FLOAT_EPSILON ) { float fDamage = 0.0f; if ( fHealthLoss > 0 ) fDamage += fHealthLoss; if ( fArmorLoss > 0 ) fDamage += fArmorLoss; + CElement * pKillerElement = NULL; + unsigned char ucWeapon = 0xFF; + unsigned char ucBodyPart = 0xFF; + if ( bDamageInfo ) + { + pKillerElement = CElementIDs::GetElement ( pSourcePlayer->GetPlayerAttacker () ); + ucWeapon = pSourcePlayer->GetAttackWeapon (); + ucBodyPart = pSourcePlayer->GetAttackBodyPart (); + } + // Call the onPlayerDamage event - CLuaArguments Arguments; - CElement* pKillerElement = pSourcePlayer->GetPlayerAttacker (); + CLuaArguments Arguments; if ( pKillerElement ) Arguments.PushElement ( pKillerElement ); else Arguments.PushNil (); - Arguments.PushNumber ( pSourcePlayer->GetAttackWeapon () ); - Arguments.PushNumber ( pSourcePlayer->GetAttackBodyPart () ); + if ( ucWeapon != 0xFF ) Arguments.PushNumber ( ucWeapon ); + else Arguments.PushBoolean ( false ); + if ( ucBodyPart != 0xFF ) Arguments.PushNumber ( ucBodyPart ); + else Arguments.PushBoolean ( false ); Arguments.PushNumber ( fDamage ); pSourcePlayer->CallEvent ( "onPlayerDamage", Arguments ); diff --git a/MTA10_Server/mods/deathmatch/logic/packets/CVehiclePuresyncPacket.cpp b/MTA10_Server/mods/deathmatch/logic/packets/CVehiclePuresyncPacket.cpp index ee8d2b1cd4..53f4edf71b 100644 --- a/MTA10_Server/mods/deathmatch/logic/packets/CVehiclePuresyncPacket.cpp +++ b/MTA10_Server/mods/deathmatch/logic/packets/CVehiclePuresyncPacket.cpp @@ -254,13 +254,9 @@ bool CVehiclePuresyncPacket::Read ( NetBitStreamInterface& BitStream ) { // Call the onPlayerDamage event CLuaArguments Arguments; - CElement* pKillerElement = pSourcePlayer->GetPlayerAttacker (); - if ( pKillerElement ) - Arguments.PushElement ( pKillerElement ); - else - Arguments.PushNil (); - Arguments.PushNumber ( pSourcePlayer->GetAttackWeapon () ); - Arguments.PushNumber ( pSourcePlayer->GetAttackBodyPart () ); + Arguments.PushNil (); + Arguments.PushNumber ( 0xff ); + Arguments.PushNumber ( 0xff ); Arguments.PushNumber ( fArmorLoss ); pSourcePlayer->CallEvent ( "onPlayerDamage", Arguments ); diff --git a/MTA10_Server/mods/deathmatch/mtaserver.conf b/MTA10_Server/mods/deathmatch/mtaserver.conf index 2cadfe8df9..d9467896b2 100644 --- a/MTA10_Server/mods/deathmatch/mtaserver.conf +++ b/MTA10_Server/mods/deathmatch/mtaserver.conf @@ -75,8 +75,10 @@ + + @@ -86,4 +88,8 @@ + + + + diff --git a/MTA10_Server/sdk/MTAPlatform.cpp b/MTA10_Server/sdk/MTAPlatform.cpp index 28a4910239..ecf1378447 100644 --- a/MTA10_Server/sdk/MTAPlatform.cpp +++ b/MTA10_Server/sdk/MTAPlatform.cpp @@ -12,6 +12,10 @@ #include "StdInc.h" #include "MTAPlatform.h" +#if !defined(WIN32) +#include +#endif + // Replacement functions int mymkdir ( const char* dirname ) { diff --git a/MTA10_Server/sdk/MTAPlatform.h b/MTA10_Server/sdk/MTAPlatform.h index aa32c583c7..618a6800ed 100644 --- a/MTA10_Server/sdk/MTAPlatform.h +++ b/MTA10_Server/sdk/MTAPlatform.h @@ -63,7 +63,12 @@ extern "C" bool g_bSilent; #include #include #include - #include + #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) + #include + #else + #include + #endif + // Define functions #define MAX_PATH 255 diff --git a/MTA10_Server/version.h b/MTA10_Server/version.h index 2e82ae4071..b32dea29f6 100644 --- a/MTA10_Server/version.h +++ b/MTA10_Server/version.h @@ -1,6 +1,6 @@ #define MTA_DM_VERSION 0x0100 #define MTA_DM_VERSIONSTRING "1.0" -#define MTA_DM_ASE_VERSION "1.0" +#define MTA_DM_ASE_VERSION "1.0.1n" #define MTA_DM_BUILDTYPE "Custom" #define MTA_DM_FULL_STRING "MTA:SA Server" -#define MTA_DM_NETCODE_VERSION 0x161 \ No newline at end of file +#define MTA_DM_NETCODE_VERSION 0x165 \ No newline at end of file diff --git a/Shared/sdk/CVector.h b/Shared/sdk/CVector.h index 70b2fca22e..7f6610c995 100644 --- a/Shared/sdk/CVector.h +++ b/Shared/sdk/CVector.h @@ -42,6 +42,13 @@ class CVector this->fZ = fZ; } + CVector ( float f ) + { + this->fX = f; + this->fY = f; + this->fZ = f; + } + float Normalize ( void ) { double t = sqrt(fX*fX + fY*fY + fZ*fZ); diff --git a/Shared/sdk/SharedUtil.h b/Shared/sdk/SharedUtil.h index 5da142703d..20622cbc02 100644 --- a/Shared/sdk/SharedUtil.h +++ b/Shared/sdk/SharedUtil.h @@ -28,6 +28,13 @@ #define _vsnprintf vsnprintf #endif +// +// Macro for counting the number of elements in a static array +// +#ifndef NUMELMS // from DShow.h + #define NUMELMS(aa) (sizeof(aa)/sizeof((aa)[0])) +#endif + namespace SharedUtil { // @@ -104,6 +111,24 @@ namespace SharedUtil return static_cast < int > ( floor ( value + 0.5f ) ); } +#ifdef WIN32 + + // Lerps between two radian values depending on the weight + template< class T > + T LerpRotationRad ( T& from, float fAlpha, T& to ) + { + return GetOffsetRadians ( float ( from ), float ( to ) ) * fAlpha + from; + } + + // Lerps between two degree values depending on the weight + template< class T > + T LerpRotationDeg ( T& from, float fAlpha, T& to ) + { + return GetOffsetDegrees ( float ( from ), float ( to ) ) * fAlpha + from; + } + +#endif + // // SColor diff --git a/Shared/sdk/SharedUtil.hpp b/Shared/sdk/SharedUtil.hpp index e35fc5037a..f3b5f1b572 100644 --- a/Shared/sdk/SharedUtil.hpp +++ b/Shared/sdk/SharedUtil.hpp @@ -7,6 +7,7 @@ * Include this file once per dll. * DEVELOPERS: ccw * Alberto Alonso +* Cecill Etheredge * * Multi Theft Auto is available from http://www.multitheftauto.com/ * @@ -188,15 +189,40 @@ void SString::Split ( const SString& strDelim, std::vector < SString >& outResul // -// Emulate GetTickCount() for linux +// Cross-platform GetTickCount() implementations +// Returns the number of milliseconds since some fixed point in time. +// Wraps every 49.71 days and should always increase monotonically. // -#ifndef WIN32 +// ACHTUNG: This function should be scrapped and replaced by a cross-platform time class +// +#if defined(__APPLE__) && defined(__MACH__) + +// Apple / Darwin platforms with Mach monotonic clock support +#include +unsigned long GetTickCount ( void ) +{ + mach_timebase_info_data_t info; + + // Get the absolute time + uint64_t nAbsTime = mach_absolute_time(); + + // Get the timebase info (could be done once, statically?) + mach_timebase_info( &info ); -// Returns the number of milliseconds since some fixed point in time. -// Wraps every 49.71 days. Should not to jump backwards or forward, even if the system time is changed. + // Calculate the time in milliseconds + uint64_t nNanoTime = nAbsTime * ( info.numer / info.denom ); + return ( nNanoTime / 1000000 ); +} + +#elif !defined(WIN32) + +// BSD / Linux platforms with POSIX monotonic clock support unsigned long GetTickCount ( void ) { - // Copied from curl\lib\timeval.c + #if !defined(CLOCK_MONOTONIC) + #error "This platform does not have monotonic clock support." + #endif + /* ** clock_gettime() is granted to be increased monotonically when the ** monotonic clock is queried. Time starting point is unspecified, it @@ -218,9 +244,12 @@ unsigned long GetTickCount ( void ) else (void)gettimeofday(&now, NULL); + // ACHTUNG: Note that the above gettimeofday fallback is dangerous because it is a wall clock + // and thus not guaranteed to be monotonic. Ideally, this function should throw a fatal error + // or assertion instead of using a fallback method. + long long llMilliseconds = ( ( long long ) now.tv_sec ) * 1000 + now.tv_usec / 1000; return llMilliseconds; } - #endif