From b4d5d5249c5c9f8d7d7685e2f402f0a4d214892b Mon Sep 17 00:00:00 2001 From: saml1er Date: Tue, 14 Apr 2020 15:45:47 +0500 Subject: [PATCH 01/18] CPedPath complete --- src/control/PathFind.cpp | 218 ++++++++++++++++++++++++++++++++++++++- src/control/PathFind.h | 33 +++++- 2 files changed, 244 insertions(+), 7 deletions(-) diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index 61cd3d4e..dbfd6d0e 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -14,8 +14,6 @@ bool gbShowCarPathsLinks; CPathFind &ThePaths = *(CPathFind*)0x8F6754; -WRAPPER bool CPedPath::CalcPedRoute(uint8, CVector, CVector, CVector*, int16*, int16) { EAXJMP(0x42E680); } - #define MAX_DIST INT16_MAX-1 // object flags: @@ -28,6 +26,215 @@ CPathInfoForObject *&InfoForTilePeds = *(CPathInfoForObject**)0x8F1AE4; CTempDetachedNode *&DetachedNodesCars = *(CTempDetachedNode**)0x8E2824; CTempDetachedNode *&DetachedNodesPeds = *(CTempDetachedNode**)0x8E28A0; +bool +CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVector *pointPoses, int16 *pointsFound, int16 maxPoints) +{ + *pointsFound = 0; + CVector vecDistance = destination - position; + if (Abs(vecDistance.x) > 23.8f || Abs(vecDistance.y) > 23.8f || Abs(vecDistance.z) > 23.8f) + return false; + CVector vecPos = (position + destination) * 0.5f; + CVector vecSectorStartPos (vecPos.x - 14.0f, vecPos.y - 14.0f, vecPos.z); + CVector2D vecSectorEndPos (vecPos.x + 28.0f, vecPos.x + 28.0f); + const int16 nodeStartX = (position.x - vecSectorStartPos.x) * 1.4286f; + const int16 nodeStartY = (position.y - vecSectorStartPos.y) * 1.4286f; + const int16 nodeEndX = (destination.x - vecSectorStartPos.x) * 1.4286f; + const int16 nodeEndY = (destination.y - vecSectorStartPos.y) * 1.4286f; + if (nodeStartX == nodeEndX && nodeStartY == nodeEndY) + return false; + CPedPathNode pathNodes[40][40]; + CPedPathNode pathNodesList[416]; + for (int32 x = 0; x < 40; x++) { + for (int32 y = 0; y < 40; y++) { + pathNodes[x][y].bBlockade = false; + pathNodes[x][y].id = 0x7FFF; + pathNodes[x][y].nodeIdX = x; + pathNodes[x][y].nodeIdY = y; + } + } + CWorld::AdvanceCurrentScanCode(); + if (pathType != ROUTE_NO_BLOCKADE) { + const int32 nStartX = max(CWorld::GetSectorIndexX(vecSectorStartPos.x), 0); + const int32 nStartY = max(CWorld::GetSectorIndexY(vecSectorStartPos.y), 0); + const int32 nEndX = min(CWorld::GetSectorIndexX(vecSectorEndPos.x), NUMSECTORS_X - 1); + const int32 nEndY = min(CWorld::GetSectorIndexY(vecSectorEndPos.y), NUMSECTORS_Y - 1); + for (int32 y = nStartY; y <= nEndY; y++) { + for (int32 x = nStartX; x <= nEndX; x++) { + CSector *pSector = CWorld::GetSector(x, y); + AddBlockadeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES], pathNodes, &vecSectorStartPos); + AddBlockadeSectorList(pSector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], pathNodes, &vecSectorStartPos); + AddBlockadeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS], pathNodes, &vecSectorStartPos); + AddBlockadeSectorList(pSector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], pathNodes, &vecSectorStartPos); + } + } + } + for (int32 i = 0; i < 416; i++) { + pathNodesList[i].prev = nil; + pathNodesList[i].next = nil; + } + CPedPathNode *pStartPathNode = &pathNodes[nodeStartX][nodeStartY]; + CPedPathNode *pEndPathNode = &pathNodes[nodeEndX][nodeEndY]; + pEndPathNode->bBlockade = false; + pEndPathNode->id = 0; + pEndPathNode->prev = nil; + pEndPathNode->next = pathNodesList; + pathNodesList[0].prev = pEndPathNode; + int32 pathNodeIndex = 0; + CPedPathNode *pPreviousNode = nil; + for (; pathNodeIndex < 414; pathNodeIndex++) + { + pPreviousNode = pathNodesList[pathNodeIndex].prev; + while (pPreviousNode && pPreviousNode != pStartPathNode) { + const uint8 nodeIdX = pPreviousNode->nodeIdX; + const uint8 nodeIdY = pPreviousNode->nodeIdY; + if (nodeIdX > 0) { + AddNodeToPathList(&pathNodes[nodeIdX - 1][nodeIdY], pathNodeIndex + 5, pathNodesList); + if (nodeIdY > 0) + AddNodeToPathList(&pathNodes[nodeIdX - 1][nodeIdY - 1], pathNodeIndex + 7, pathNodesList); + if (nodeIdY < 39) + AddNodeToPathList(&pathNodes[nodeIdX - 1][nodeIdY + 1], pathNodeIndex + 7, pathNodesList); + } + if (nodeIdX < 39) { + AddNodeToPathList(&pathNodes[nodeIdX + 1][nodeIdY], pathNodeIndex + 5, pathNodesList); + if (nodeIdY > 0) + AddNodeToPathList(&pathNodes[nodeIdX + 1][nodeIdY - 1], pathNodeIndex + 7, pathNodesList); + if (nodeIdY < 39) + AddNodeToPathList(&pathNodes[nodeIdX + 1][nodeIdY + 1], pathNodeIndex + 7, pathNodesList); + } + if (nodeIdY > 0) + AddNodeToPathList(&pathNodes[nodeIdX][nodeIdY - 1], pathNodeIndex + 5, pathNodesList); + if (nodeIdY < 39) + AddNodeToPathList(&pathNodes[nodeIdX][nodeIdY + 1], pathNodeIndex + 5, pathNodesList); + pPreviousNode = pPreviousNode->prev; + if (!pPreviousNode) + break; + } + + if (pPreviousNode && pPreviousNode == pStartPathNode) + break; + } + if (pathNodeIndex == 414) + return false; + CPedPathNode *pPathNode = pStartPathNode; + for (*pointsFound = 0; pPathNode != pEndPathNode && *pointsFound < maxPoints; ++ *pointsFound) { + const uint8 nodeIdX = pPathNode->nodeIdX; + const uint8 nodeIdY = pPathNode->nodeIdY; + if (nodeIdX <= 0 || pathNodes[nodeIdX - 1][nodeIdY].id + 5 != pPathNode->id) { + if (nodeIdX >= 39 || pathNodes[nodeIdX + 1][nodeIdY].id + 5 != pPathNode->id) { + if (nodeIdY <= 0 || pathNodes[nodeIdX][nodeIdY - 1].id + 5 != pPathNode->id) { + if (nodeIdY >= 39 || pathNodes[nodeIdX][nodeIdY + 1].id + 5 != pPathNode->id) { + if (nodeIdX <= 0 || nodeIdY <= 0 || pathNodes[nodeIdX - 1][nodeIdY - 1].id + 7 != pPathNode->id) { + if (nodeIdX <= 0 || nodeIdY >= 39 || pathNodes[nodeIdX - 1][nodeIdY + 1].id + 7 != pPathNode->id) { + if (nodeIdX >= 39 || nodeIdY <= 0 || pathNodes[nodeIdX + 1][nodeIdY - 1].id + 7 != pPathNode->id) { + if (nodeIdX < 39 && nodeIdY < 39 && pathNodes[nodeIdX + 1][nodeIdY + 1].id + 7 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX + 1][nodeIdY + 1]; + } else { + pPathNode = &pathNodes[nodeIdX + 1][nodeIdY - 1]; + } + } else { + pPathNode = &pathNodes[nodeIdX - 1][nodeIdY + 1]; + } + } else { + pPathNode = &pathNodes[nodeIdX - 1][nodeIdY - 1]; + } + } else { + pPathNode = &pathNodes[nodeIdX][nodeIdY + 1]; + } + } else { + pPathNode = &pathNodes[nodeIdX][nodeIdY - 1]; + } + } + else { + pPathNode = &pathNodes[nodeIdX + 1][nodeIdY]; + } + } + else { + pPathNode = &pathNodes[nodeIdX - 1][nodeIdY]; + } + pointPoses[*pointsFound] = vecSectorStartPos; + pointPoses[*pointsFound].x += (float)pPathNode->nodeIdX * 0.7f; + pointPoses[*pointsFound].y += (float)pPathNode->nodeIdY * 0.7f; + } + return true; +} + + +void +CPedPath::AddNodeToPathList(CPedPathNode *pNodeToAdd, int16 id, CPedPathNode *pNodeList) +{ + if (!pNodeToAdd->bBlockade && id < pNodeToAdd->id) { + if (pNodeToAdd->id != 0x7FFF) + RemoveNodeFromList(pNodeToAdd); + AddNodeToList(pNodeToAdd, id, pNodeList); + } +} + +void +CPedPath::RemoveNodeFromList(CPedPathNode *pNode) +{ + pNode->next->prev = pNode->prev; + if (pNode->prev) + pNode->prev->next = pNode->next; +} + +void +CPedPath::AddNodeToList(CPedPathNode *pNode, int16 index, CPedPathNode *pList) +{ + pNode->prev = pList[index].prev; + pNode->next = &pList[index]; + if (pList[index].prev) + pList[index].prev->next = pNode; + pList[index].prev = pNode; + pNode->id = index; +} + +void +CPedPath::AddBlockadeSectorList(CPtrList& list, CPedPathNode(*pathNodes)[40], CVector *pPosition) +{ + CPtrNode* listNode = list.first; + while (listNode) { + CEntity* pEntity = (CEntity*)listNode->item; + if (pEntity->m_scanCode != CWorld::GetCurrentScanCode() && pEntity->bUsesCollision) { + pEntity->m_scanCode = CWorld::GetCurrentScanCode(); + AddBlockade(pEntity, pathNodes, pPosition); + } + listNode = listNode->next; + } +} + +void +CPedPath::AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *pPosition) +{ + const CColBox& boundingBox = pEntity->GetColModel()->boundingBox; + const float fBoundMaxY = boundingBox.max.y + 0.3f; + const float fBoundMinY = boundingBox.min.y - 0.3f; + const float fBoundMaxX = boundingBox.max.x + 0.3f; + const float fDistanceX = pPosition->x - pEntity->m_matrix.GetPosition().x; + const float fDistanceY = pPosition->y - pEntity->m_matrix.GetPosition().y; + const float fBoundRadius = pEntity->GetBoundRadius(); + CVector vecBoundCentre; + pEntity->GetBoundCentre(vecBoundCentre); + if (vecBoundCentre.x + fBoundRadius >= pPosition->x && + vecBoundCentre.y + fBoundRadius >= pPosition->y && + vecBoundCentre.x - fBoundRadius <= pPosition->x + 28.0f && + vecBoundCentre.y - fBoundRadius <= pPosition->y + 28.0f) { + for (int16 x = 0; x < 40; x++) { + const float pointX = (float)x * 0.7f + fDistanceX; + for (int16 y = 0; y < 40; y++) { + if (!pathNodes[x][y].bBlockade) { + const float pointY = (float)y * 0.7f + fDistanceY; + CVector2D point(pointX, pointY); + if (fBoundMaxX > Abs(DotProduct2D(point, pEntity->m_matrix.GetRight()))) { + float fDotProduct = DotProduct2D(point, pEntity->m_matrix.GetForward()); + if (fBoundMaxY > fDotProduct && fBoundMinY < fDotProduct) + pathNodes[x][y].bBlockade = true; + } + } + } + } + } +} + void CPathFind::Init(void) { @@ -1576,6 +1783,13 @@ CPathFind::DisplayPathData(void) } STARTPATCHES + InjectHook(0x42E680, &CPedPath::CalcPedRoute, PATCH_JUMP); + InjectHook(0x42F100, &CPedPath::AddNodeToPathList, PATCH_JUMP); + InjectHook(0x42F140, &CPedPath::RemoveNodeFromList, PATCH_JUMP); + InjectHook(0x42F160, &CPedPath::AddNodeToList, PATCH_JUMP); + InjectHook(0x42F1A0, &CPedPath::AddBlockade, PATCH_JUMP); + InjectHook(0x42F420, &CPedPath::AddBlockadeSectorList, PATCH_JUMP); + InjectHook(0x4294A0, &CPathFind::Init, PATCH_JUMP); InjectHook(0x42D580, &CPathFind::AllocatePathFindInfoMem, PATCH_JUMP); InjectHook(0x429540, &CPathFind::RegisterMapObject, PATCH_JUMP); diff --git a/src/control/PathFind.h b/src/control/PathFind.h index 81467cdf..ea88ade6 100644 --- a/src/control/PathFind.h +++ b/src/control/PathFind.h @@ -3,11 +3,7 @@ #include "Treadable.h" class CVehicle; - -class CPedPath { -public: - static bool CalcPedRoute(uint8, CVector, CVector, CVector*, int16*, int16); -}; +class CPtrList; enum { @@ -30,6 +26,33 @@ enum SWITCH_ON = 1, }; +enum +{ + ROUTE_ADD_BLOCKADE = 0, + ROUTE_NO_BLOCKADE = 1 +}; + +struct CPedPathNode +{ + bool bBlockade; + uint8 nodeIdX; + uint8 nodeIdY; + int16 id; + CPedPathNode* prev; + CPedPathNode* next; +}; +static_assert(sizeof(CPedPathNode) == 0x10, "CPedPathNode: error"); + +class CPedPath { +public: + static bool CalcPedRoute(int8 pathType, CVector position, CVector destination, CVector *pointPoses, int16 *pointsFound, int16 maxPoints); + static void AddNodeToPathList(CPedPathNode *pNodeToAdd, int16 id, CPedPathNode *pNodeList); + static void RemoveNodeFromList(CPedPathNode *pNode); + static void AddNodeToList(CPedPathNode *pNode, int16 index, CPedPathNode *pList); + static void AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *pPosition); + static void AddBlockadeSectorList(CPtrList& list, CPedPathNode(*pathNodes)[40], CVector *pPosition); +}; + struct CPathNode { CVector pos; From 8bb23ca5d4d8404c21a0e5f79f4548b86f4456a9 Mon Sep 17 00:00:00 2001 From: saml1er Date: Tue, 14 Apr 2020 16:57:28 +0500 Subject: [PATCH 02/18] Refactor CPedPath::CalcPedRoute --- src/control/PathFind.cpp | 56 ++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 36 deletions(-) diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index dbfd6d0e..f0431db9 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -36,10 +36,10 @@ CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVe CVector vecPos = (position + destination) * 0.5f; CVector vecSectorStartPos (vecPos.x - 14.0f, vecPos.y - 14.0f, vecPos.z); CVector2D vecSectorEndPos (vecPos.x + 28.0f, vecPos.x + 28.0f); - const int16 nodeStartX = (position.x - vecSectorStartPos.x) * 1.4286f; - const int16 nodeStartY = (position.y - vecSectorStartPos.y) * 1.4286f; - const int16 nodeEndX = (destination.x - vecSectorStartPos.x) * 1.4286f; - const int16 nodeEndY = (destination.y - vecSectorStartPos.y) * 1.4286f; + const int16 nodeStartX = (position.x - vecSectorStartPos.x) / 0.7f; + const int16 nodeStartY = (position.y - vecSectorStartPos.y) / 0.7f; + const int16 nodeEndX = (destination.x - vecSectorStartPos.x) / 0.7f; + const int16 nodeEndY = (destination.y - vecSectorStartPos.y) / 0.7f; if (nodeStartX == nodeEndX && nodeStartY == nodeEndY) return false; CPedPathNode pathNodes[40][40]; @@ -119,38 +119,22 @@ CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVe for (*pointsFound = 0; pPathNode != pEndPathNode && *pointsFound < maxPoints; ++ *pointsFound) { const uint8 nodeIdX = pPathNode->nodeIdX; const uint8 nodeIdY = pPathNode->nodeIdY; - if (nodeIdX <= 0 || pathNodes[nodeIdX - 1][nodeIdY].id + 5 != pPathNode->id) { - if (nodeIdX >= 39 || pathNodes[nodeIdX + 1][nodeIdY].id + 5 != pPathNode->id) { - if (nodeIdY <= 0 || pathNodes[nodeIdX][nodeIdY - 1].id + 5 != pPathNode->id) { - if (nodeIdY >= 39 || pathNodes[nodeIdX][nodeIdY + 1].id + 5 != pPathNode->id) { - if (nodeIdX <= 0 || nodeIdY <= 0 || pathNodes[nodeIdX - 1][nodeIdY - 1].id + 7 != pPathNode->id) { - if (nodeIdX <= 0 || nodeIdY >= 39 || pathNodes[nodeIdX - 1][nodeIdY + 1].id + 7 != pPathNode->id) { - if (nodeIdX >= 39 || nodeIdY <= 0 || pathNodes[nodeIdX + 1][nodeIdY - 1].id + 7 != pPathNode->id) { - if (nodeIdX < 39 && nodeIdY < 39 && pathNodes[nodeIdX + 1][nodeIdY + 1].id + 7 == pPathNode->id) - pPathNode = &pathNodes[nodeIdX + 1][nodeIdY + 1]; - } else { - pPathNode = &pathNodes[nodeIdX + 1][nodeIdY - 1]; - } - } else { - pPathNode = &pathNodes[nodeIdX - 1][nodeIdY + 1]; - } - } else { - pPathNode = &pathNodes[nodeIdX - 1][nodeIdY - 1]; - } - } else { - pPathNode = &pathNodes[nodeIdX][nodeIdY + 1]; - } - } else { - pPathNode = &pathNodes[nodeIdX][nodeIdY - 1]; - } - } - else { - pPathNode = &pathNodes[nodeIdX + 1][nodeIdY]; - } - } - else { - pPathNode = &pathNodes[nodeIdX - 1][nodeIdY]; - } + if (nodeIdX > 0 && pathNodes[nodeIdX - 1][nodeIdY].id + 5 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX - 1][nodeIdY]; + else if (nodeIdX > 39 && pathNodes[nodeIdX + 1][nodeIdY].id + 5 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX + 1][nodeIdY]; + else if (nodeIdY > 0 && pathNodes[nodeIdX][nodeIdY - 1].id + 5 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX][nodeIdY - 1]; + else if (nodeIdY > 39 && pathNodes[nodeIdX][nodeIdY + 1].id + 5 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX][nodeIdY + 1]; + else if (nodeIdX > 0 && nodeIdY > 0 && pathNodes[nodeIdX - 1][nodeIdY - 1].id + 7 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX - 1][nodeIdY - 1]; + else if (nodeIdX > 0 && nodeIdY < 39 && pathNodes[nodeIdX - 1][nodeIdY + 1].id + 7 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX - 1][nodeIdY + 1]; + else if (nodeIdX < 39 && nodeIdY > 0 && pathNodes[nodeIdX + 1][nodeIdY - 1].id + 7 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX + 1][nodeIdY - 1]; + else if (nodeIdX < 39 && nodeIdY < 39 && pathNodes[nodeIdX + 1][nodeIdY + 1].id + 7 == pPathNode->id) + pPathNode = &pathNodes[nodeIdX + 1][nodeIdY + 1]; pointPoses[*pointsFound] = vecSectorStartPos; pointPoses[*pointsFound].x += (float)pPathNode->nodeIdX * 0.7f; pointPoses[*pointsFound].y += (float)pPathNode->nodeIdY * 0.7f; From bf040c7cd1c336af160d8672324b3029f5ba7cc3 Mon Sep 17 00:00:00 2001 From: saml1er Date: Tue, 14 Apr 2020 17:05:51 +0500 Subject: [PATCH 03/18] Remove float casts --- src/control/PathFind.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index f0431db9..ea81b9b7 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -136,8 +136,8 @@ CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVe else if (nodeIdX < 39 && nodeIdY < 39 && pathNodes[nodeIdX + 1][nodeIdY + 1].id + 7 == pPathNode->id) pPathNode = &pathNodes[nodeIdX + 1][nodeIdY + 1]; pointPoses[*pointsFound] = vecSectorStartPos; - pointPoses[*pointsFound].x += (float)pPathNode->nodeIdX * 0.7f; - pointPoses[*pointsFound].y += (float)pPathNode->nodeIdY * 0.7f; + pointPoses[*pointsFound].x += pPathNode->nodeIdX * 0.7f; + pointPoses[*pointsFound].y += pPathNode->nodeIdY * 0.7f; } return true; } @@ -203,10 +203,10 @@ CPedPath::AddBlockade(CEntity *pEntity, CPedPathNode(*pathNodes)[40], CVector *p vecBoundCentre.x - fBoundRadius <= pPosition->x + 28.0f && vecBoundCentre.y - fBoundRadius <= pPosition->y + 28.0f) { for (int16 x = 0; x < 40; x++) { - const float pointX = (float)x * 0.7f + fDistanceX; + const float pointX = x * 0.7f + fDistanceX; for (int16 y = 0; y < 40; y++) { if (!pathNodes[x][y].bBlockade) { - const float pointY = (float)y * 0.7f + fDistanceY; + const float pointY = y * 0.7f + fDistanceY; CVector2D point(pointX, pointY); if (fBoundMaxX > Abs(DotProduct2D(point, pEntity->m_matrix.GetRight()))) { float fDotProduct = DotProduct2D(point, pEntity->m_matrix.GetForward()); From 6d5464b6bbf44481a56682c9a3fe8d22baf8282e Mon Sep 17 00:00:00 2001 From: saml1er Date: Tue, 14 Apr 2020 23:32:15 +0500 Subject: [PATCH 04/18] CPedPath improvements --- src/control/PathFind.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index ea81b9b7..9f45c454 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -15,6 +15,7 @@ bool gbShowCarPathsLinks; CPathFind &ThePaths = *(CPathFind*)0x8F6754; #define MAX_DIST INT16_MAX-1 +#define MIN_PED_ROUTE_DISTANCE 23.8f // object flags: // 1 UseInRoadBlock @@ -31,7 +32,7 @@ CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVe { *pointsFound = 0; CVector vecDistance = destination - position; - if (Abs(vecDistance.x) > 23.8f || Abs(vecDistance.y) > 23.8f || Abs(vecDistance.z) > 23.8f) + if (Abs(vecDistance.x) > MIN_PED_ROUTE_DISTANCE || Abs(vecDistance.y) > MIN_PED_ROUTE_DISTANCE || Abs(vecDistance.z) > MIN_PED_ROUTE_DISTANCE) return false; CVector vecPos = (position + destination) * 0.5f; CVector vecSectorStartPos (vecPos.x - 14.0f, vecPos.y - 14.0f, vecPos.z); @@ -47,7 +48,7 @@ CPedPath::CalcPedRoute(int8 pathType, CVector position, CVector destination, CVe for (int32 x = 0; x < 40; x++) { for (int32 y = 0; y < 40; y++) { pathNodes[x][y].bBlockade = false; - pathNodes[x][y].id = 0x7FFF; + pathNodes[x][y].id = INT16_MAX; pathNodes[x][y].nodeIdX = x; pathNodes[x][y].nodeIdY = y; } @@ -147,7 +148,7 @@ void CPedPath::AddNodeToPathList(CPedPathNode *pNodeToAdd, int16 id, CPedPathNode *pNodeList) { if (!pNodeToAdd->bBlockade && id < pNodeToAdd->id) { - if (pNodeToAdd->id != 0x7FFF) + if (pNodeToAdd->id != INT16_MAX) RemoveNodeFromList(pNodeToAdd); AddNodeToList(pNodeToAdd, id, pNodeList); } From db11155a49c18419e32978387c4fa124a96b7afc Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Wed, 15 Apr 2020 00:56:02 +0200 Subject: [PATCH 05/18] Collect pdb file on CI --- .appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.appveyor.yml b/.appveyor.yml index a5b44461..41ada399 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -43,3 +43,5 @@ after_build: artifacts: - path: bin/%CONFIGURATION%/re3.dll name: re3.dll +- path: bin/%CONFIGURATION%/re3.pdb + name: re3.pdb From 25841cb9b3996451213c3bf353fc1bfb8f5a5f4b Mon Sep 17 00:00:00 2001 From: Filip Gawin Date: Wed, 15 Apr 2020 00:57:45 +0200 Subject: [PATCH 06/18] Update premake5.lua --- premake5.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/premake5.lua b/premake5.lua index 4ec2eca1..173fe3e4 100644 --- a/premake5.lua +++ b/premake5.lua @@ -94,13 +94,14 @@ project "re3" filter "configurations:Debug" defines { "DEBUG" } staticruntime "on" - symbols "On" + symbols "Full" setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "plugins/") filter "configurations:Release" defines { "NDEBUG" } optimize "On" staticruntime "on" + symbols "Full" setpaths("$(GTA_III_RE_DIR)/", "gta3.exe", "plugins/") filter "configurations:ReleaseFH" From daed13485ef47d9c8992e53e1a976fba237fca50 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Wed, 15 Apr 2020 08:03:53 +0300 Subject: [PATCH 07/18] CWeapon done, ps2 cheats fix --- src/audio/AudioManager.h | 2 +- src/control/AutoPilot.cpp | 2 +- src/control/CarCtrl.cpp | 2 +- src/control/Garages.cpp | 2 +- src/core/General.h | 5 + src/core/Pad.cpp | 2 + src/core/World.cpp | 1 + src/core/World.h | 2 + src/core/main.cpp | 3 +- src/entities/Physical.cpp | 2 +- src/math/Vector.h | 7 + src/math/Vector2D.h | 7 +- src/modelinfo/ModelIndices.h | 7 + src/peds/Ped.cpp | 2 +- src/peds/Ped.h | 5 + src/peds/PlayerPed.cpp | 8 +- src/peds/PlayerPed.h | 4 +- src/render/Glass.cpp | 16 +- src/weapons/BulletInfo.cpp | 4 + src/weapons/BulletInfo.h | 7 + src/weapons/Weapon.cpp | 2237 +++++++++++++++++++++++++++++++++- src/weapons/Weapon.h | 64 +- 22 files changed, 2331 insertions(+), 60 deletions(-) diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index 910ffcaf..40aabcfc 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -117,7 +117,7 @@ enum eScriptSounds : int16 SCRIPT_SOUND_BULLET_HIT_GROUND_1 = 106, SCRIPT_SOUND_BULLET_HIT_GROUND_2 = 107, SCRIPT_SOUND_BULLET_HIT_GROUND_3 = 108, - SCRIPT_SOUND_109 = 109, + SCRIPT_SOUND_BULLET_HIT_WATER = 109, //no sound SCRIPT_SOUND_110 = 110, SCRIPT_SOUND_111 = 111, SCRIPT_SOUND_PAYPHONE_RINGING = 112, diff --git a/src/control/AutoPilot.cpp b/src/control/AutoPilot.cpp index 70099291..319cebab 100644 --- a/src/control/AutoPilot.cpp +++ b/src/control/AutoPilot.cpp @@ -35,7 +35,7 @@ void CAutoPilot::ModifySpeed(float speed) m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - (uint32)(positionBetweenNodes * m_nTimeToSpendOnCurrentCurve); #else - m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - positionBetweenNodes * m_nSpeedScaleFactor; + m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - positionBetweenNodes * m_nTimeToSpendOnCurrentCurve; #endif } diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index 3174a253..ef89965a 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -426,7 +426,7 @@ CCarCtrl::GenerateOneRandomCar() (uint32)((0.5f + positionBetweenNodes) * pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve); #else pCar->AutoPilot.m_nTimeEnteredCurve = CTimer::GetTimeInMilliseconds() - - (0.5f + positionBetweenNodes) * pCar->AutoPilot.m_nSpeedScaleFactor; + (0.5f + positionBetweenNodes) * pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve; #endif CVector directionCurrentLink(directionCurrentLinkX, directionCurrentLinkY, 0.0f); CVector directionNextLink(directionNextLinkX, directionNextLinkY, 0.0f); diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 84d49bee..48a99170 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -1082,7 +1082,7 @@ void CGarage::Update() #ifdef FIX_BUGS bool bCreatedAllCars = false; #else - bool bCraetedAllCars; + bool bCreatedAllCars; #endif switch (m_eGarageType) { case GARAGE_HIDEOUT_ONE: bCreatedAllCars = RestoreCarsForThisHideout(CGarages::aCarsInSafeHouse1); break; diff --git a/src/core/General.h b/src/core/General.h index f32846eb..77828854 100644 --- a/src/core/General.h +++ b/src/core/General.h @@ -90,6 +90,11 @@ public: return -Atan2(x / y, 1.0f); } } + + static float GetAngleBetweenPoints(float x1, float y1, float x2, float y2) + { + return RADTODEG(GetRadianAngleBetweenPoints(x1, y1, x2, y2)); + } // should return direction in 0-8 range. fits perfectly to peds' path directions. static int GetNodeHeadingFromVector(float x, float y) diff --git a/src/core/Pad.cpp b/src/core/Pad.cpp index 6efbeb8e..9d00cef7 100644 --- a/src/core/Pad.cpp +++ b/src/core/Pad.cpp @@ -642,6 +642,8 @@ void CPad::AddToCheatString(char c) { for ( int32 i = ARRAY_SIZE(CheatString) - 2; i >= 0; i-- ) CheatString[i + 1] = CheatString[i]; + + CheatString[0] = c; #define _CHEATCMP(str) strncmp(str, CheatString, sizeof(str)-1) // "4414LDRULDRU" - R2 R2 L1 R2 LEFT DOWN RIGHT UP LEFT DOWN RIGHT UP diff --git a/src/core/World.cpp b/src/core/World.cpp index d64569b3..b4ae9346 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -58,6 +58,7 @@ WRAPPER void CWorld::ClearPedsFromArea(float, float, float, float, float, float) WRAPPER void CWorld::CallOffChaseForArea(float, float, float, float) { EAXJMP(0x4B5530); } WRAPPER void CWorld::TriggerExplosion(const CVector& a1, float a2, float a3, CEntity *a4, bool a5) { EAXJMP(0x4B1140); } WRAPPER void CWorld::SetPedsOnFire(float, float, float, float, CEntity*) { EAXJMP(0x4B3D30); } +WRAPPER void CWorld::UseDetonator(CEntity *) { EAXJMP(0x4B4650); } void CWorld::Initialise() diff --git a/src/core/World.h b/src/core/World.h index 07e7889f..0ee3fdda 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -142,6 +142,8 @@ public: static void RemoveStaticObjects(); static void Process(); static void TriggerExplosion(const CVector &, float, float, CEntity*, bool); + + static void UseDetonator(CEntity *); }; extern CColPoint *gaTempSphereColPoints; diff --git a/src/core/main.cpp b/src/core/main.cpp index 93e4c71c..02f7d523 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -1557,8 +1557,9 @@ void SystemInit() // #endif - +#ifdef GTA_PS2_STUFF CPad::Initialise(); +#endif CPad::GetPad(0)->Mode = 0; CGame::frenchGame = false; diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index faa8a484..bd13ff37 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -612,7 +612,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl if(model == MI_FIRE_HYDRANT && !Bobj->bHasBeenDamaged){ CParticleObject::AddObject(POBJECT_FIRE_HYDRANT, B->GetPosition() - CVector(0.0f, 0.0f, 0.5f), true); Bobj->bHasBeenDamaged = true; - }else if(B->IsObject() && model != MI_EXPLODINGBARREL && model != MI_PETROLPUMP) + }else if(B->IsObject() && !IsExplosiveThingModel(model)) Bobj->bHasBeenDamaged = true; }else{ if(IsGlass(B->GetModelIndex())) diff --git a/src/math/Vector.h b/src/math/Vector.h index 6f544ada..9b732610 100644 --- a/src/math/Vector.h +++ b/src/math/Vector.h @@ -46,6 +46,13 @@ public: y *= invsqrt; z *= invsqrt; } + + void Normalise2D(void) { + float sq = MagnitudeSqr2D(); + float invsqrt = RecipSqrt(sq); + x *= invsqrt; + y *= invsqrt; + } const CVector &operator+=(CVector const &right) { x += right.x; diff --git a/src/math/Vector2D.h b/src/math/Vector2D.h index 1e4d698f..705ad763 100644 --- a/src/math/Vector2D.h +++ b/src/math/Vector2D.h @@ -13,13 +13,14 @@ public: void Normalise(void){ float sq = MagnitudeSqr(); - if(sq > 0.0f){ + //if(sq > 0.0f){ float invsqrt = RecipSqrt(sq); x *= invsqrt; y *= invsqrt; - }else - x = 1.0f; + //}else + // x = 1.0f; } + const CVector2D &operator+=(CVector2D const &right) { x += right.x; y += right.y; diff --git a/src/modelinfo/ModelIndices.h b/src/modelinfo/ModelIndices.h index 20d1b7f3..309fa1bb 100644 --- a/src/modelinfo/ModelIndices.h +++ b/src/modelinfo/ModelIndices.h @@ -490,3 +490,10 @@ IsPoliceVehicleModel(int16 id) id == MI_POLICE || id == MI_ENFORCER; } + +inline bool +IsExplosiveThingModel(int16 id) +{ + return id == MI_EXPLODINGBARREL || + id == MI_PETROLPUMP; +} \ No newline at end of file diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 2cd942f9..4ee31a30 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -1231,7 +1231,7 @@ CPed::Attack(void) weaponAnimAssoc->SetCurrentTime(0.0f); if (IsPlayer()) { - ((CPlayerPed*)this)->field_1376 = 0.0f; + ((CPlayerPed*)this)->m_fAttackButtonCounter = 0.0f; ((CPlayerPed*)this)->m_bHaveTargetSelected = false; } } diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 2edd5d68..ea8c4080 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -796,7 +796,12 @@ public: PedState GetPedState(void) { return m_nPedState; } void SetPedState(PedState state) { m_nPedState = state; } + bool Dead(void) { return m_nPedState == PED_DEAD; } + bool Dying(void) { return m_nPedState == PED_DIE; } bool DyingOrDead(void) { return m_nPedState == PED_DIE || m_nPedState == PED_DEAD; } + bool OnGround(void) { return m_nPedState == PED_FALL || m_nPedState == PED_DIE || m_nPedState == PED_DEAD; } + + bool Driving(void) { return m_nPedState == PED_DRIVING; } bool InVehicle(void) { return bInVehicle && m_pMyVehicle; } // True when ped is sitting/standing in vehicle, not in enter/exit state. bool EnteringCar(void) { return m_nPedState == PED_ENTER_CAR || m_nPedState == PED_CARJACK; } diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index ccc0a43a..dcd9486f 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -43,8 +43,8 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) m_fStaminaProgress = 0.0f; m_nEvadeAmount = 0; field_1367 = 0; - m_nShotDelay = 0; - field_1376 = 0.0f; + m_nHitAnimDelayTimer = 0; + m_fAttackButtonCounter = 0.0f; m_bHaveTargetSelected = false; m_bHasLockOnTarget = false; m_bCanBeDamaged = true; @@ -1024,10 +1024,10 @@ CPlayerPed::ProcessPlayerWeapon(CPad *padUsed) if (padUsed->WeaponJustDown()) { m_bHaveTargetSelected = true; } else if (!m_bHaveTargetSelected) { - field_1376 += CTimer::GetTimeStepNonClipped(); + m_fAttackButtonCounter += CTimer::GetTimeStepNonClipped(); } } else { - field_1376 = 0.0f; + m_fAttackButtonCounter = 0.0f; m_bHaveTargetSelected = false; } SetAttack(nil); diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h index c139bbbc..c6823c2d 100644 --- a/src/peds/PlayerPed.h +++ b/src/peds/PlayerPed.h @@ -20,8 +20,8 @@ public: uint8 m_nEvadeAmount; int8 field_1367; uint32 m_nSpeedTimer; - int32 m_nShotDelay; - float field_1376; // m_fAttackButtonCounter? + uint32 m_nHitAnimDelayTimer; + float m_fAttackButtonCounter; // m_fAttackButtonCounter? bool m_bHaveTargetSelected; // may have better name int8 field_1381; int8 field_1382; diff --git a/src/render/Glass.cpp b/src/render/Glass.cpp index 41d31985..46a12a6f 100644 --- a/src/render/Glass.cpp +++ b/src/render/Glass.cpp @@ -404,6 +404,7 @@ CGlass::AskForObjectToBeRenderedInGlass(CEntity *entity) void CGlass::RenderEntityInGlass(CEntity *entity) { + ASSERT(entity!=NULL); CObject *object = (CObject *)entity; if ( object->bGlassBroken ) @@ -419,7 +420,7 @@ CGlass::RenderEntityInGlass(CEntity *entity) uint8 alpha = CalcAlphaWithNormal(&fwdNorm); CColModel *col = object->GetColModel(); - + ASSERT(col!=NULL); if ( col->numTriangles >= 2 ) { CVector a = object->GetMatrix() * col->vertices[0]; @@ -523,6 +524,8 @@ CGlass::RenderEntityInGlass(CEntity *entity) int32 CGlass::CalcAlphaWithNormal(CVector *normal) { + ASSERT(normal!=NULL); + float fwdDir = 2.0f * DotProduct(*normal, TheCamera.GetForward()); float fwdDot = DotProduct(TheCamera.GetForward()-fwdDir*(*normal), CVector(0.57f, 0.57f, -0.57f)); return int32(lerp(fwdDot*fwdDot*fwdDot*fwdDot*fwdDot*fwdDot, 20.0f, 255.0f)); @@ -597,6 +600,8 @@ CGlass::RenderReflectionPolys(void) void CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, CVector point, bool explosion) { + ASSERT(entity!=NULL); + CObject *object = (CObject *)entity; if ( object->bGlassBroken ) @@ -605,7 +610,8 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, object->bGlassCracked = true; CColModel *col = object->GetColModel(); - + ASSERT(col!=NULL); + CVector a = object->GetMatrix() * col->vertices[0]; CVector b = object->GetMatrix() * col->vertices[1]; CVector c = object->GetMatrix() * col->vertices[2]; @@ -647,6 +653,8 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, void CGlass::WindowRespondsToSoftCollision(CEntity *entity, float amount) { + ASSERT(entity!=NULL); + CObject *object = (CObject *)entity; if ( amount > 50.0f && !object->bGlassCracked ) @@ -659,6 +667,8 @@ CGlass::WindowRespondsToSoftCollision(CEntity *entity, float amount) void CGlass::WasGlassHitByBullet(CEntity *entity, CVector point) { + ASSERT(entity!=NULL); + CObject *object = (CObject *)entity; if ( IsGlass(object->GetModelIndex()) ) @@ -679,6 +689,8 @@ CGlass::WasGlassHitByBullet(CEntity *entity, CVector point) void CGlass::WindowRespondsToExplosion(CEntity *entity, CVector point) { + ASSERT(entity!=NULL); + CObject *object = (CObject *)entity; CVector distToGlass = object->GetPosition() - point; diff --git a/src/weapons/BulletInfo.cpp b/src/weapons/BulletInfo.cpp index 54fa6844..81138c0f 100644 --- a/src/weapons/BulletInfo.cpp +++ b/src/weapons/BulletInfo.cpp @@ -2,4 +2,8 @@ #include "patcher.h" #include "BulletInfo.h" +WRAPPER void CBulletInfo::Initialise(void) { EAXJMP(0x558220); } +WRAPPER void CBulletInfo::Shutdown(void) { EAXJMP(0x558450); } +WRAPPER void CBulletInfo::AddBullet(CEntity *firingEntity, eWeaponType type, CVector pos, CVector velocity) { EAXJMP(0x558470); } +WRAPPER void CBulletInfo::Update(void) { EAXJMP(0x558550); } WRAPPER bool CBulletInfo::TestForSniperBullet(float x1, float x2, float y1, float y2, float z1, float z2) { EAXJMP(0x558D40); } diff --git a/src/weapons/BulletInfo.h b/src/weapons/BulletInfo.h index 3905b56d..b10ef0a1 100644 --- a/src/weapons/BulletInfo.h +++ b/src/weapons/BulletInfo.h @@ -1,7 +1,14 @@ #pragma once +class CEntity; +enum eWeaponType; + class CBulletInfo { public: + static void Initialise(void); + static void Shutdown(void); + static void AddBullet(CEntity *firingEntity, eWeaponType type, CVector pos, CVector velocity); + static void Update(void); static bool TestForSniperBullet(float x1, float x2, float y1, float y2, float z1, float z2); }; \ No newline at end of file diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 0f41264f..d4312649 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -1,23 +1,91 @@ #include "common.h" #include "patcher.h" #include "Weapon.h" -#include "Timer.h" -#include "WeaponInfo.h" +#include "AnimBlendAssociation.h" +#include "AudioManager.h" +#include "BulletInfo.h" +#include "Camera.h" +#include "Coronas.h" +#include "DMAudio.h" +#include "Explosion.h" +#include "General.h" +#include "Glass.h" +#include "Heli.h" +#include "ModelIndices.h" +#include "Object.h" +#include "Pad.h" +#include "Particle.h" #include "Ped.h" +#include "PointLights.h" +#include "Pools.h" +#include "ProjectileInfo.h" +#include "RpAnimBlend.h" +#include "ShotInfo.h" +#include "SpecialFX.h" +#include "Stats.h" +#include "TempColModels.h" +#include "Timer.h" +#include "Vehicle.h" +#include "WaterLevel.h" +#include "WeaponInfo.h" #include "World.h" -WRAPPER void CWeapon::ShutdownWeapons(void) { EAXJMP(0x55C2F0); } -WRAPPER void CWeapon::UpdateWeapons(void) { EAXJMP(0x55C310); } -WRAPPER bool CWeapon::Fire(CEntity*, CVector*) { EAXJMP(0x55C380); } -WRAPPER void CWeapon::FireFromCar(CAutomobile *car, bool left) { EAXJMP(0x55C940); } -WRAPPER void CWeapon::AddGunshell(CEntity*, CVector const&, CVector2D const&, float) { EAXJMP(0x55F770); } -WRAPPER void CWeapon::Update(int32 audioEntity) { EAXJMP(0x563A10); } -WRAPPER void CWeapon::DoTankDoomAiming(CEntity *playerVehicle, CEntity *playerPed, CVector *start, CVector *end) { EAXJMP(0x563200); } -WRAPPER void CWeapon::InitialiseWeapons(void) { EAXJMP(0x55C2D0); } -WRAPPER void FireOneInstantHitRound(CVector* shotSource, CVector* shotTarget, int32 damage) { EAXJMP(0x563B00); } +uint16 gReloadSampleTime[WEAPONTYPE_TOTAL_INVENTORY_WEAPONS] = +{ + /*UNARMED*/ 0, + /*BASEBALLBAT*/ 0, + /*COLT45*/ 250, + /*UZI*/ 400, + /*SHOTGUN*/ 650, + /*AK47*/ 300, + /*M16*/ 300, + /*SNIPERRIFLE*/ 423, + /*ROCKETLAUNCHER*/ 400, + /*FLAMETHROWER*/ 0, + /*MOLOTOV*/ 0, + /*GRENADE*/ 0, + /*DETONATOR*/ 0 +}; + +CWeaponInfo * +CWeapon::GetInfo() +{ + CWeaponInfo *info = CWeaponInfo::GetWeaponInfo(m_eWeaponType); + ASSERT(info!=NULL); + return info; +} void -CWeapon::Initialise(eWeaponType type, int ammo) +CWeapon::InitialiseWeapons(void) +{ + CWeaponInfo::Initialise(); + CShotInfo::Initialise(); + CExplosion::Initialise(); + CProjectileInfo::Initialise(); + CBulletInfo::Initialise(); +} + +void +CWeapon::ShutdownWeapons(void) +{ + CWeaponInfo::Shutdown(); + CShotInfo::Shutdown(); + CExplosion::Shutdown(); + CProjectileInfo::Shutdown(); + CBulletInfo::Shutdown(); +} + +void +CWeapon::UpdateWeapons(void) +{ + CShotInfo::Update(); + CExplosion::Update(); + CProjectileInfo::Update(); + CBulletInfo::Update(); +} + +void +CWeapon::Initialise(eWeaponType type, int32 ammo) { m_eWeaponType = type; m_eWeaponState = WEAPONSTATE_READY; @@ -30,13 +98,1872 @@ CWeapon::Initialise(eWeaponType type, int ammo) m_nTimer = 0; } +bool +CWeapon::Fire(CEntity *shooter, CVector *fireSource) +{ + ASSERT(shooter!=NULL); + + CVector fireOffset(0.0f, 0.0f, 0.6f); + CVector *source = fireSource; + + if ( !fireSource ) + source = &(shooter->GetMatrix() * fireOffset); + + if ( m_bAddRotOffset ) + { + float heading = RADTODEG(shooter->GetForward().Heading()); + float angle = DEGTORAD(heading); + (*source).x += -Sin(angle) * 0.15f; + (*source).y += Cos(angle) * 0.15f; + } + + if ( m_eWeaponState != WEAPONSTATE_READY && m_eWeaponState != WEAPONSTATE_FIRING ) + return false; + + bool fired; + + if ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE ) + { + if ( m_nAmmoInClip <= 0 ) + return false; + + switch ( m_eWeaponType ) + { + case WEAPONTYPE_SHOTGUN: + { + fired = FireShotgun(shooter, source); + + break; + } + + case WEAPONTYPE_COLT45: + case WEAPONTYPE_UZI: + case WEAPONTYPE_AK47: + { + fired = FireInstantHit(shooter, source); + + break; + } + + case WEAPONTYPE_SNIPERRIFLE: + { + fired = FireSniper(shooter); + + break; + } + + case WEAPONTYPE_M16: + { + if ( TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON && shooter == FindPlayerPed() ) + fired = FireM16_1stPerson(shooter); + else + fired = FireInstantHit(shooter, source); + + break; + } + + case WEAPONTYPE_ROCKETLAUNCHER: + { + if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != NULL ) + { + float distToTarget = (shooter->GetPosition() - ((CPed*)shooter)->m_pSeekTarget->GetPosition()).Magnitude(); + + if ( distToTarget > 8.0f || ((CPed*)shooter)->IsPlayer() ) + fired = FireProjectile(shooter, source, 0.0f); + else + fired = false; + } + else + fired = FireProjectile(shooter, source, 0.0f); + + break; + } + + case WEAPONTYPE_MOLOTOV: + case WEAPONTYPE_GRENADE: + { + if ( shooter == FindPlayerPed() ) + { + fired = FireProjectile(shooter, source, ((CPlayerPed*)shooter)->m_fAttackButtonCounter*0.0375f); + if ( m_eWeaponType == WEAPONTYPE_GRENADE ) + CStats::KgsOfExplosivesUsed++; + } + else if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != NULL ) + { + float distToTarget = (shooter->GetPosition() - ((CPed*)shooter)->m_pSeekTarget->GetPosition()).Magnitude(); + float power = clamp((distToTarget-10.0f)*0.02f, 0.2f, 1.0f); + + fired = FireProjectile(shooter, source, power); + } + else + fired = FireProjectile(shooter, source, 0.3f); + + break; + } + + case WEAPONTYPE_FLAMETHROWER: + { + fired = FireAreaEffect(shooter, source); + + break; + } + + case WEAPONTYPE_DETONATOR: + { + CWorld::UseDetonator(shooter); + m_nAmmoTotal = 1; + m_nAmmoInClip = m_nAmmoTotal; + fired = true; + + break; + } + + case WEAPONTYPE_HELICANNON: + { + if ( (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON ) + && shooter == FindPlayerPed() ) + { + fired = FireM16_1stPerson(shooter); + } + else + fired = FireInstantHit(shooter, source); + + break; + } + + default: + { + debug("Unknown weapon type, Weapon.cpp"); + break; + } + } + + if ( fired ) + { + bool isPlayer = false; + + if ( shooter->IsPed() ) + { + CPed *shooterPed = (CPed*)shooter; + + shooterPed->bIsShooting = true; + + if ( shooterPed->IsPlayer() ) + isPlayer = true; + + DMAudio.PlayOneShot(shooterPed->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); + } + + if ( m_nAmmoInClip > 0 ) m_nAmmoInClip--; + if ( m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer) ) m_nAmmoTotal--; + + if ( m_eWeaponState == WEAPONSTATE_READY && m_eWeaponType == WEAPONTYPE_FLAMETHROWER ) + DMAudio.PlayOneShot(((CPhysical*)shooter)->m_audioEntityId, SOUND_WEAPON_FLAMETHROWER_FIRE, 0.0f); + + m_eWeaponState = WEAPONSTATE_FIRING; + } + + if ( m_nAmmoInClip == 0 ) + { + if ( m_nAmmoTotal == 0 ) + return true; + + m_eWeaponState = WEAPONSTATE_RELOADING; + m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; + + if ( shooter == FindPlayerPed() ) + { + if ( CWorld::Players[CWorld::PlayerInFocus].m_bFastReload ) + m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload / 4; + } + + return true; + } + + m_nTimer = CTimer::GetTimeInMilliseconds() + 1000; + if ( shooter == FindPlayerPed() ) + CStats::RoundsFiredByPlayer++; + } + else + { + if ( m_eWeaponState != WEAPONSTATE_FIRING ) + { + m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; + m_eWeaponState = WEAPONSTATE_FIRING; + } + + FireMelee(shooter, *source); + } + + if ( m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT ) + return true; + else + return fired; +} + +bool +CWeapon::FireFromCar(CAutomobile *shooter, bool left) +{ + ASSERT(shooter!=NULL); + + if ( m_eWeaponState != WEAPONSTATE_READY && m_eWeaponState != WEAPONSTATE_FIRING ) + return false; + + if ( m_nAmmoInClip <= 0 ) + return false; + + if ( FireInstantHitFromCar(shooter, left) ) + { + DMAudio.PlayOneShot(shooter->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); + + if ( m_nAmmoInClip > 0 ) m_nAmmoInClip--; + if ( m_nAmmoTotal < 25000 && m_nAmmoTotal > 0 ) m_nAmmoTotal--; + + m_eWeaponState = WEAPONSTATE_FIRING; + + if ( m_nAmmoInClip == 0 ) + { + if ( m_nAmmoTotal == 0 ) + return true; + + m_eWeaponState = WEAPONSTATE_RELOADING; + m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; + + return true; + } + + m_nTimer = CTimer::GetTimeInMilliseconds() + 1000; + if ( shooter == FindPlayerVehicle() ) + CStats::RoundsFiredByPlayer++; + } + + return true; +} + +bool +CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) +{ + ASSERT(shooter!=NULL); + + CWeaponInfo *info = GetInfo(); + + bool anim2Playing = false; + if ( RpAnimBlendClumpGetAssociation(shooter->GetClump(), info->m_Anim2ToPlay) ) + anim2Playing = true; + + ASSERT(shooter->IsPed()); + + CPed *shooterPed = (CPed*)shooter; + + for ( int32 i = 0; i < shooterPed->m_numNearPeds; i++ ) + { + CPed *victimPed = shooterPed->m_nearPeds[i]; + ASSERT(victimPed!=NULL); + + if ( (victimPed->m_nPedType != shooterPed->m_nPedType || victimPed == shooterPed->m_pSeekTarget) + && victimPed != shooterPed->m_leader || !(CGeneral::GetRandomNumber() & 31) ) + { + bool collided = false; + + CColModel *victimPedCol = &CTempColModels::ms_colModelPed1; + if ( victimPed->OnGround() || !victimPed->IsPedHeadAbovePos(-0.3f) ) + victimPedCol = &CTempColModels::ms_colModelPedGroundHit; + + ASSERT(victimPedCol!=NULL); + + float victimPedRadius = victimPed->GetBoundRadius() + info->m_fRadius; + if ( victimPed->bUsesCollision || victimPed->Dead() || victimPed->Driving() ) + { + CVector victimPedPos = victimPed->GetPosition(); + if ( SQR(victimPedRadius) > (victimPedPos-(*fireSource)).MagnitudeSqr() ) + { + CVector collisionDist; + + int32 s = 0; + while ( s < victimPedCol->numSpheres ) + { + CColSphere *sphere = &victimPedCol->spheres[s]; + collisionDist = victimPedPos+sphere->center-(*fireSource); + + if ( SQR(sphere->radius + info->m_fRadius) > collisionDist.MagnitudeSqr() ) + { + collided = true; + break; + } + s++; + } + + if ( !(victimPed->IsPlayer() && victimPed->GetPedState() == PED_GETUP) ) + { + if ( collided ) + { + float victimPedHealth = victimPed->m_fHealth; + CVector bloodPos = fireSource + collisionDist*0.7f; + + CVector2D posOffset(shooterPed->GetPosition().x-victimPedPos.x, shooterPed->GetPosition().y-victimPedPos.y); + + int32 localDir = victimPed->GetLocalDirection(posOffset); + + bool isBat = m_eWeaponType == WEAPONTYPE_BASEBALLBAT; + + if ( !victimPed->DyingOrDead() ) + victimPed->ReactToAttack(shooterPed); + + uint8 hitLevel = HITLEVEL_HIGH; + if ( isBat && victimPed->OnGround() ) + hitLevel = HITLEVEL_GROUND; + + victimPed->StartFightDefend(localDir, hitLevel, 10); + + if ( !victimPed->DyingOrDead() ) + { + if ( shooterPed->IsPlayer() && isBat && anim2Playing ) + victimPed->InflictDamage(shooterPed, m_eWeaponType, 100.0f, PEDPIECE_TORSO, localDir); + else if ( shooterPed->IsPlayer() && ((CPlayerPed*)shooterPed)->m_bAdrenalineActive ) + victimPed->InflictDamage(shooterPed, m_eWeaponType, 3.5f*info->m_nDamage, PEDPIECE_TORSO, localDir); + else + { + if ( victimPed->IsPlayer() && isBat ) // wtf, it's not fair + victimPed->InflictDamage(shooterPed, m_eWeaponType, 2.0f*info->m_nDamage, PEDPIECE_TORSO, localDir); + else + victimPed->InflictDamage(shooterPed, m_eWeaponType, info->m_nDamage, PEDPIECE_TORSO, localDir); + } + } + + if ( CGame::nastyGame ) + { + if ( victimPed->GetIsOnScreen() ) + { + CVector dir = collisionDist * RecipSqrt(1.0f, 10.0f*collisionDist.MagnitudeSqr()); + + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + + if ( isBat ) + { + dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); + dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + + dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); + dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); + } + } + } + + if ( !victimPed->OnGround() ) + { + if ( victimPed->m_fHealth > 0.0f + && (victimPed->m_fHealth < 20.0f && victimPedHealth > 20.0f || isBat && !victimPed->IsPlayer()) ) + { + posOffset.Normalise(); + victimPed->bIsStanding = false; + victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); + + if ( isBat && victimPed->IsPlayer() ) + victimPed->SetFall(3000, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); + else + victimPed->SetFall(1500, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); + + shooterPed->m_pSeekTarget = victimPed; + shooterPed->m_pSeekTarget->RegisterReference(&shooterPed->m_pSeekTarget); + } + } + else if (victimPed->Dying() && !anim2Playing) + { + posOffset.Normalise(); + victimPed->bIsStanding = false; + victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); + } + + m_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT; + + if ( victimPed->m_nPedType == PEDTYPE_COP ) + CEventList::RegisterEvent(EVENT_ASSAULT_POLICE, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); + else + CEventList::RegisterEvent(EVENT_ASSAULT, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); + } + } + } + } + } + } + + return true; +} + +bool +CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) +{ + ASSERT(shooter!=NULL); + ASSERT(fireSource!=NULL); + + CWeaponInfo *info = GetInfo(); + + CVector source, target; + CColPoint point; + CEntity *victim = NULL; + + float heading = RADTODEG(shooter->GetForward().Heading()); + float angle = DEGTORAD(heading); + + CVector2D ahead(-Sin(angle), Cos(angle)); + ahead.Normalise(); + + CVector vel = ((CPed *)shooter)->m_vecMoveSpeed; + int32 shooterMoving = false; + if ( Abs(vel.x) > 0.0f && Abs(vel.y) > 0.0f ) + shooterMoving = true; + + if ( shooter == FindPlayerPed() ) + { + static float prev_heading = 0.0f; + prev_heading = ((CPed*)shooter)->m_fRotationCur; + } + + if ( shooter->IsPed() && ((CPed *)shooter)->m_pPointGunAt ) + { + CPed *shooterPed = (CPed *)shooter; + if ( shooterPed->m_pedIK.m_flags & CPedIK::GUN_POINTED_SUCCESSFULLY ) + { + int32 accuracy = shooterPed->m_wepAccuracy; + int32 inaccuracy = 100-accuracy; + + if ( accuracy != 100 ) + FindPlayerPed(); //what ? + + CPed *threatAttack = (CPed*)shooterPed->m_pPointGunAt; + if ( threatAttack->IsPed() ) + { + threatAttack->m_pedIK.GetComponentPosition(target, PED_MID); + threatAttack->ReactToPointGun(shooter); + } + else + target = threatAttack->GetPosition(); + + target -= *fireSource; + target *= info->m_fRange / target.Magnitude(); + target += *fireSource; + + if ( inaccuracy != 0 ) + { + target.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracy; + target.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracy; + target.z += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * inaccuracy; + } + + CWorld::bIncludeDeadPeds = true; + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + CWorld::bIncludeDeadPeds = false; + } + else + { + target.x = info->m_fRange; + target.y = 0.0f; + target.z = 0.0f; + + for (RwFrame *i = shooterPed->GetNodeFrame(PED_HANDR); i; i = RwFrameGetParent(i)) + RwV3dTransformPoints(target, target, 1, RwFrameGetMatrix(i)); + + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + } + } + else if ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam() ) + { + CVector src, trgt; + TheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, src, trgt); + + CWorld::bIncludeDeadPeds = true; + ProcessLineOfSight(src, trgt,point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + CWorld::bIncludeDeadPeds = false; + + int32 rotSpeed = 1; + if ( m_eWeaponType == WEAPONTYPE_M16 ) + rotSpeed = 4; + + CVector bulletPos; + if ( CHeli::TestBulletCollision(&src, &trgt, &bulletPos, 4) ) + { + for ( int32 i = 0; i < 16; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f, rotSpeed); + } + } + else + { + float shooterHeading = RADTODEG(shooter->GetForward().Heading()); + float shooterAngle = DEGTORAD(shooterHeading); + + CVector2D rotOffset(-Sin(shooterAngle), Cos(shooterAngle)); + rotOffset.Normalise(); + + target = *fireSource; + target.x = rotOffset.x * info->m_fRange; + target.y = rotOffset.y * info->m_fRange; + + if ( shooter->IsPed() ) + DoDoomAiming(shooter, fireSource, &target); + + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + + int32 rotSpeed = 1; + if ( m_eWeaponType == WEAPONTYPE_M16 ) + rotSpeed = 4; + + CVector bulletPos; + if ( CHeli::TestBulletCollision(fireSource, &target, &bulletPos, 4) ) + { + for ( int32 i = 0; i < 16; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f, rotSpeed); + } + } + + if ( victim && shooter->IsPed() && victim == ((CPed*)shooter)->m_leader ) + return false; + + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed *)shooter, 1000); + + if ( shooter == FindPlayerPed() ) + { + CStats::InstantHitsFiredByPlayer++; + if ( !(CTimer::GetFrameCounter() & 3) ) + MakePedsJumpAtShot((CPhysical*)shooter, fireSource, &target); + } + + switch ( m_eWeaponType ) + { + case WEAPONTYPE_AK47: + { + static uint8 counter = 0; + + if ( !(++counter & 1) ) + { + CPointLights::AddLight(CPointLights::LIGHT_POINT, + *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + + CVector gunflashPos = *fireSource; + gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.10f); + gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.08f); + gunflashPos += CVector(0.05f*ahead.x, 0.05f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); + gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + + CVector gunsmokePos = *fireSource; + float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f)); + + CVector gunshellPos = *fireSource; + gunshellPos -= CVector(0.5f*ahead.x, 0.5f*ahead.y, 0.0f); + CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); + dir.Normalise2D(); + AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.018f); + } + + break; + } + + case WEAPONTYPE_M16: + { + static uint8 counter = 0; + + if ( !(++counter & 1) ) + { + CPointLights::AddLight(CPointLights::LIGHT_POINT, + *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + + CVector gunflashPos = *fireSource; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.08f); + gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); + gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); + + gunflashPos = *fireSource; + gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); + gunflashPos.z += 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + gunflashPos.z += 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + gunflashPos.z += 0.03f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + + gunflashPos = *fireSource; + gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); + gunflashPos.z -= 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + gunflashPos.z -= 0.04f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + gunflashPos.z -= 0.03f; + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + + CVector offset = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); + offset.Normalise2D(); + + gunflashPos = *fireSource; + gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); + gunflashPos += CVector(0.06f*offset.x, 0.06f*offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + gunflashPos += CVector(0.04f*offset.x, 0.04f*offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + gunflashPos += CVector(0.03f*offset.x, 0.03f*offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + + gunflashPos = *fireSource; + gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); + gunflashPos -= CVector(0.06f*offset.x, 0.06f*offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + gunflashPos -= CVector(0.04f*offset.x, 0.04f*offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + gunflashPos -= CVector(0.03f*offset.x, 0.03f*offset.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + + CVector gunsmokePos = *fireSource; + float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f)); + + CVector gunshellPos = *fireSource; + gunshellPos -= CVector(0.65f*ahead.x, 0.65f*ahead.y, 0.0f); + CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); + dir.Normalise2D(); + AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.02f); + } + + break; + } + + case WEAPONTYPE_UZI: + { + CPointLights::AddLight(CPointLights::LIGHT_POINT, + *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + + CVector gunflashPos = *fireSource; + + if ( shooterMoving ) + gunflashPos += CVector(1.5f*vel.x, 1.5f*vel.y, 0.0f); + + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.07f); + gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.05f); + gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + gunflashPos += CVector(0.03f*ahead.x, 0.03f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + gunflashPos += CVector(0.03f*ahead.x, 0.03f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + gunflashPos += CVector(0.02f*ahead.x, 0.02f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.01f); + + CVector gunsmokePos = *fireSource; + float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f)); + + CVector gunshellPos = *fireSource; + gunshellPos -= CVector(0.2f*ahead.x, 0.2f*ahead.y, 0.0f); + CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); + dir.Normalise2D(); + AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.015f); + + break; + } + + case WEAPONTYPE_COLT45: + { + CPointLights::AddLight(CPointLights::LIGHT_POINT, + *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + + CVector gunflashPos = *fireSource; + + if ( shooterMoving ) + gunflashPos += CVector(1.5f*vel.x, 1.5f*vel.y, 0.0f); + + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); + gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + + CVector gunsmokePos = *fireSource; + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.10f, ahead.y*0.10f, 0.0f), NULL, 0.005f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.15f, ahead.y*0.15f, 0.0f), NULL, 0.015f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.20f, ahead.y*0.20f, 0.0f), NULL, 0.025f); + + CVector gunshellPos = *fireSource; + gunshellPos -= CVector(0.2f*ahead.x, 0.2f*ahead.y, 0.0f); + CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); + dir.Normalise2D(); + AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.015f); + + break; + } + } + + DoBulletImpact(shooter, victim, fireSource, &target, &point, ahead); + + return true; +} + +void +CWeapon::AddGunshell(CEntity *shooter, CVector const &source, CVector2D const &direction, float size) +{ + ASSERT(shooter!=NULL); + + if ( shooter == NULL) + return; + + CVector dir(direction.x*0.05f, direction.y*0.05f, CGeneral::GetRandomNumberInRange(0.02f, 0.08f)); + + static CVector prevEntityPosition(0.0f, 0.0f, 0.0f); + CVector entityPosition = shooter->GetPosition(); + + CVector diff = entityPosition - prevEntityPosition; + + if ( Abs(diff.x)+Abs(diff.y)+Abs(diff.z) > 1.5f ) + { + prevEntityPosition = entityPosition; + + CParticle::AddParticle(PARTICLE_GUNSHELL_FIRST, + source, dir, NULL, size, CGeneral::GetRandomNumberInRange(-20.0f, 20.0f)); + } + else + { + CParticle::AddParticle(PARTICLE_GUNSHELL, + source, dir, NULL, size, CGeneral::GetRandomNumberInRange(-20.0f, 20.0f)); + } +} + +void +CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, + CVector *source, CVector *target, CColPoint *point, CVector2D ahead) +{ + ASSERT(shooter!=NULL); + ASSERT(source!=NULL); + ASSERT(target!=NULL); + ASSERT(point!=NULL); + + CWeaponInfo *info = GetInfo(); + + if ( victim ) + { + CGlass::WasGlassHitByBullet(victim, point->point); + + CVector traceTarget = *target; + CBulletTraces::AddTrace(source, &traceTarget); + + if ( shooter != NULL ) + { + if ( shooter == FindPlayerPed() ) + { + if ( victim->IsPed() || victim->IsVehicle() ) + CStats::InstantHitsHitByPlayer++; + } + } + + if ( victim->IsPed() && ((CPed*)shooter)->m_nPedType != ((CPed*)victim)->m_nPedType || ((CPed*)shooter)->m_nPedType == PEDTYPE_PLAYER2 ) + { + CPed *victimPed = (CPed *)victim; + if ( !victimPed->OnGround() && victim != shooter ) + { + if ( victimPed->DoesLOSBulletHitPed(*point) ) + { + CVector pos = victimPed->GetPosition(); + + CVector2D posOffset(source->x-pos.x, source->y-pos.y); + int32 localDir = victimPed->GetLocalDirection(posOffset); + + victimPed->ReactToAttack(shooter); + + if ( !victimPed->IsPedInControl() || victimPed->bIsDucking ) + { + victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); + } + else + { + if ( m_eWeaponType == WEAPONTYPE_SHOTGUN || m_eWeaponType == WEAPONTYPE_HELICANNON ) + { + posOffset.Normalise(); + victimPed->bIsStanding = false; + + victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 5.0f); + victimPed->SetFall(1500, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); + + victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); + } + else + { + if ( victimPed->IsPlayer() ) + { + CPlayerPed *victimPlayer = (CPlayerPed *)victimPed; + if ( victimPlayer->m_nHitAnimDelayTimer < CTimer::GetTimeInMilliseconds() ) + { + victimPed->ClearAttackByRemovingAnim(); + + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); + ASSERT(asoc!=NULL); + + asoc->blendAmount = 0.0f; + asoc->blendDelta = 8.0f; + + if ( m_eWeaponType == WEAPONTYPE_AK47 || m_eWeaponType == WEAPONTYPE_M16 ) + victimPlayer->m_nHitAnimDelayTimer = CTimer::GetTimeInMilliseconds() + 2500; + else + victimPlayer->m_nHitAnimDelayTimer = CTimer::GetTimeInMilliseconds() + 1000; + } + } + else + { + victimPed->ClearAttackByRemovingAnim(); + + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); + ASSERT(asoc!=NULL); + + asoc->blendAmount = 0.0f; + asoc->blendDelta = 8.0f; + } + + victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); + } + } + + if ( victimPed->m_nPedType == PEDTYPE_COP ) + CEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); + else + CEventList::RegisterEvent(EVENT_SHOOT_PED, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); + + if ( CGame::nastyGame ) + { + uint8 bloodAmount = 8; + if ( m_eWeaponType == WEAPONTYPE_SHOTGUN || m_eWeaponType == WEAPONTYPE_HELICANNON ) + bloodAmount = 32; + + CVector dir = (point->point - victim->GetPosition()) * 0.01f; + dir.z = 0.01f; + + if ( victimPed->GetIsOnScreen() ) + { + for ( uint8 i = 0; i < bloodAmount; i++ ) + CParticle::AddParticle(PARTICLE_BLOOD_SMALL, point->point, dir); + } + } + } + } + else + { + if ( CGame::nastyGame ) + { + CVector dir = (point->point - victim->GetPosition()) * 0.01f; + dir.z = 0.01f; + + if ( victim->GetIsOnScreen() ) + { + for ( int32 i = 0; i < 8; i++ ) + CParticle::AddParticle(PARTICLE_BLOOD_SMALL, point->point + CVector(0.0f, 0.0f, 0.15f), dir); + } + + if ( victimPed->Dead() ) + { + CAnimBlendAssociation *asoc; + if ( RpAnimBlendClumpGetFirstAssociation(victimPed->GetClump(), ASSOC_FLAG800) ) + asoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f); + else + asoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT, 8.0f); + + if ( asoc ) + { + asoc->SetCurrentTime(0.0f); + asoc->flags |= ASSOC_RUNNING; + asoc->flags &= ~ASSOC_FADEOUTWHENDONE; + } + } + } + } + } + else + { + switch ( victim->m_type ) + { + case ENTITY_TYPE_BUILDING: + { + for ( int32 i = 0; i < 16; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); + + CVector dist = point->point - (*source); + CVector offset = dist - max(0.2f*dist.Magnitude(), 2.0f) * CVector(ahead.x, ahead.y, 0.0f); + CVector smokePos = *source + offset; + + smokePos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + smokePos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + smokePos.z += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); + + break; + } + case ENTITY_TYPE_VEHICLE: + { + ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage); + + for ( int32 i = 0; i < 16; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); + + CVector dist = point->point - (*source); + CVector offset = dist - max(0.2f*dist.Magnitude(), 0.5f) * CVector(ahead.x, ahead.y, 0.0f); + CVector smokePos = *source + offset; + + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); + + if ( shooter->IsPed() ) + { + CPed *shooterPed = (CPed *)shooter; + + if ( shooterPed->bNotAllowedToDuck ) + { + if ( shooterPed->bKindaStayInSamePlace && victim != shooterPed->m_pPointGunAt ) + { + shooterPed->bKindaStayInSamePlace = false; + shooterPed->m_duckAndCoverTimer = CTimer::GetTimeInMilliseconds() + 15000; + } + } + } + + break; + } + case ENTITY_TYPE_OBJECT: + { + for ( int32 i = 0; i < 8; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); + + CObject *victimObject = (CObject *)victim; + + if ( !victimObject->bInfiniteMass ) + { + if ( victimObject->bIsStatic && victimObject->m_fUprootLimit <= 0.0f ) + { + victimObject->bIsStatic = false; + victimObject->AddToMovingList(); + } + + if ( !victimObject->bIsStatic ) + { + CVector moveForce = point->normal*-4.0f; + victimObject->ApplyMoveForce(moveForce.x, moveForce.y, moveForce.z); + } + } + + break; + } + } + } + + switch ( victim->m_type ) + { + case ENTITY_TYPE_BUILDING: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_1, point->point); + break; + } + case ENTITY_TYPE_VEHICLE: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f); + break; + } + case ENTITY_TYPE_PED: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f); + ((CPed*)victim)->Say(SOUND_PED_BULLET_HIT); + break; + } + case ENTITY_TYPE_OBJECT: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point->point); + break; + } + case ENTITY_TYPE_DUMMY: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_3, point->point); + break; + } + } + } + else + CBulletTraces::AddTrace(source, target); + + if ( shooter == FindPlayerPed() ) + CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); + + BlowUpExplosiveThings(victim); +} + +bool +CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) +{ + ASSERT(shooter!=NULL); + ASSERT(fireSource!=NULL); + + CWeaponInfo *info = GetInfo(); + + float heading = RADTODEG(shooter->GetForward().Heading()); + float angle = DEGTORAD(heading); + + CVector2D rotOffset(-Sin(angle), Cos(angle)); + rotOffset.Normalise(); + + CVector gunflashPos = *fireSource; + gunflashPos += CVector(rotOffset.x*0.1f, rotOffset.y*0.1f, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f); + gunflashPos += CVector(rotOffset.x*0.1f, rotOffset.y*0.1f, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.15f); + gunflashPos += CVector(rotOffset.x*0.1f, rotOffset.y*0.1f, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.2f); + CParticle::AddParticle(PARTICLE_GUNFLASH, *fireSource, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f); + + CVector gunsmokePos = *fireSource; + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.10f, rotOffset.y*0.10f, 0.0f), NULL, 0.1f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.15f, rotOffset.y*0.15f, 0.0f), NULL, 0.1f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.20f, rotOffset.y*0.20f, 0.0f), NULL, 0.1f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.25f, rotOffset.y*0.25f, 0.0f), NULL, 0.1f); + + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed*)shooter, 1000); + + CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0, 0.0, 0.0), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + + float shooterAngle; + + if ( shooter->IsPed() && ((CPed*)shooter)->m_pPointGunAt != NULL ) + { + CEntity *threatAttack = ((CPed*)shooter)->m_pPointGunAt; + shooterAngle = CGeneral::GetAngleBetweenPoints(threatAttack->GetPosition().x, threatAttack->GetPosition().y, + (*fireSource).x, (*fireSource).y); + } + else + shooterAngle = RADTODEG(shooter->GetForward().Heading()); + + + for ( int32 i = 0; i < 5; i++ ) // five shoots at once + { + float shootAngle = DEGTORAD(7.5f*i + shooterAngle - 15.0f); + CVector2D shootRot(-Sin(shootAngle), Cos(shootAngle)); + + CVector source, target; + CColPoint point; + CEntity *victim; + + if ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam() ) + { + TheCamera.Find3rdPersonCamTargetVector(1.0f, *fireSource, source, target); + CVector Left = CrossProduct(TheCamera.Cams[TheCamera.ActiveCam].Front, TheCamera.Cams[TheCamera.ActiveCam].Up); + + float f = float(i - 2) * (DEGTORAD(7.5f) / 2); + target = f * Left + target - source; + target *= info->m_fRange; + target += source; + + ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + } + else + { + target = *fireSource; + target.x += shootRot.x * info->m_fRange; + target.y += shootRot.y * info->m_fRange; + + if ( shooter->IsPed() ) + { + CPed *shooterPed = (CPed *)shooter; + + if ( shooterPed->m_pPointGunAt == NULL ) + DoDoomAiming(shooter, fireSource, &target); + else + { + float distToTarget = (shooterPed->m_pPointGunAt->GetPosition() - (*fireSource)).Magnitude2D(); + target.z += info->m_fRange / distToTarget * (shooterPed->m_pPointGunAt->GetPosition().z - target.z); + } + } + + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + } + + if ( victim ) + { + CGlass::WasGlassHitByBullet(victim, point.point); + + CBulletTraces::AddTrace(fireSource, &point.point); + + if ( victim->IsPed() ) + { + CPed *victimPed = (CPed *)victim; + if ( !victimPed->OnGround() && victim != shooter && victimPed->DoesLOSBulletHitPed(point) ) + { + bool cantStandup = true; + + CVector pos = victimPed->GetPosition(); + + CVector2D posOffset((*fireSource).x-pos.x, (*fireSource).y-pos.y); + int32 localDir = victimPed->GetLocalDirection(posOffset); + + victimPed->ReactToAttack(FindPlayerPed()); + + posOffset.Normalise(); + + if ( victimPed->m_getUpTimer > (CTimer::GetTimeInMilliseconds() - 3000) ) + cantStandup = false; + + if ( victimPed->bIsStanding && cantStandup ) + { + victimPed->bIsStanding = false; + + victimPed->ApplyMoveForce(posOffset.x*-6.0f, posOffset.y*-6.0f, 5.0f); + } + else + victimPed->ApplyMoveForce(posOffset.x*-2.0f, posOffset.y*-2.0f, 0.0f); + + if ( cantStandup ) + victimPed->SetFall(1500, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); + + victimPed->InflictDamage(NULL, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point.pieceB, localDir); + + if ( victimPed->m_nPedType == PEDTYPE_COP ) + CEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); + else + CEventList::RegisterEvent(EVENT_SHOOT_PED, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); + + if ( CGame::nastyGame ) + { + uint8 bloodAmount = 8; + if ( m_eWeaponType == WEAPONTYPE_SHOTGUN ) + bloodAmount = 32; + + CVector dir = (point.point - victim->GetPosition()) * 0.01f; + dir.z = 0.01f; + + if ( victimPed->GetIsOnScreen() ) + { + for ( uint8 i = 0; i < bloodAmount; i++ ) + CParticle::AddParticle(PARTICLE_BLOOD_SMALL, point.point, dir); + } + } + } + } + else + { + switch ( victim->m_type ) + { + case ENTITY_TYPE_VEHICLE: + { + ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage); + + for ( int32 i = 0; i < 16; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal*0.05f); + + CVector dist = point.point - (*fireSource); + CVector offset = dist - max(0.2f*dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); + CVector smokePos = *fireSource + offset; + + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); + + break; + } + + case ENTITY_TYPE_BUILDING: + case ENTITY_TYPE_OBJECT: + { + for ( int32 i = 0; i < 16; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal*0.05f); + + CVector dist = point.point - (*fireSource); + CVector offset = dist - max(0.2f*dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); + CVector smokePos = *fireSource + offset; + + smokePos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + smokePos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + smokePos.z += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); + + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); + + if ( victim->IsObject() ) + { + CObject *victimObject = (CObject *)victim; + + if ( !victimObject->bInfiniteMass ) + { + if ( victimObject->bIsStatic && victimObject->m_fUprootLimit <= 0.0f ) + { + victimObject->bIsStatic = false; + victimObject->AddToMovingList(); + } + + if ( !victimObject->bIsStatic ) + { + CVector moveForce = point.normal*-5.0f; + victimObject->ApplyMoveForce(moveForce.x, moveForce.y, moveForce.z); + } + } + } + + break; + } + } + } + + switch ( victim->m_type ) + { + case ENTITY_TYPE_BUILDING: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_1, point.point); + break; + } + case ENTITY_TYPE_VEHICLE: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f); + break; + } + case ENTITY_TYPE_PED: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f); + ((CPed*)victim)->Say(SOUND_PED_BULLET_HIT); + break; + } + case ENTITY_TYPE_OBJECT: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point.point); + break; + } + case ENTITY_TYPE_DUMMY: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_3, point.point); + break; + } + } + } + else + { + CVector traceTarget = *fireSource; + traceTarget += (target - (*fireSource)) * min(info->m_fRange, 30.0f) / info->m_fRange; + CBulletTraces::AddTrace(fireSource, &traceTarget); + } + } + + if ( shooter == FindPlayerPed() ) + CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); + + return true; +} + +bool +CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power) +{ + ASSERT(shooter!=NULL); + ASSERT(fireSource!=NULL); + + CVector source, target; + + if ( m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER ) + { + source = *fireSource; + + if ( shooter->IsPed() && ((CPed*)shooter)->IsPlayer() ) + { + int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; + if (!( mode == CCam::MODE_M16_1STPERSON + || mode == CCam::MODE_SNIPER + || mode == CCam::MODE_ROCKETLAUNCHER + || mode == CCam::MODE_M16_1STPERSON_RUNABOUT + || mode == CCam::MODE_SNIPER_RUNABOUT + || mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) ) + { + return false; + } + + *fireSource += TheCamera.Cams[TheCamera.ActiveCam].Front; + } + else + *fireSource += shooter->GetForward(); + + target = *fireSource; + } + else + { + float dot = DotProduct(*fireSource-shooter->GetPosition(), shooter->GetForward()); + + if ( dot < 0.3f ) + *fireSource += (0.3f-dot) * shooter->GetForward(); + + target = *fireSource; + + if ( target.z - shooter->GetPosition().z > 0.0f ) + target += 0.6f*shooter->GetForward(); + + source = *fireSource - shooter->GetPosition(); + + source = *fireSource - DotProduct(source, shooter->GetForward()) * shooter->GetForward(); + } + + if ( !CWorld::GetIsLineOfSightClear(source, target, true, true, false, true, false, false, false) ) + { + if ( m_eWeaponType != WEAPONTYPE_GRENADE ) + CProjectileInfo::RemoveNotAdd(shooter, m_eWeaponType, *fireSource); + else + { + if ( shooter->IsPed() ) + { + source = shooter->GetPosition() - shooter->GetForward(); + source.z -= 0.4f; + + if ( !CWorld::TestSphereAgainstWorld(source, 0.5f, NULL, false, false, true, false, false, false) ) + CProjectileInfo::AddProjectile(shooter, m_eWeaponType, source, 0.0f); + else + CProjectileInfo::RemoveNotAdd(shooter, m_eWeaponType, *fireSource); + } + } + } + else + CProjectileInfo::AddProjectile(shooter, m_eWeaponType, *fireSource, power); + + return true; +} + +void +CWeapon::GenerateFlameThrowerParticles(CVector pos, CVector dir) +{ + dir *= 0.7f; + CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); + + dir *= 0.7f; + CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); + + dir *= 0.7f; + CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); + + dir *= 0.7f; + CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); + + dir *= 0.7f; + CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); +} + +bool +CWeapon::FireAreaEffect(CEntity *shooter, CVector *fireSource) +{ + ASSERT(shooter!=NULL); + ASSERT(fireSource!=NULL); + + CWeaponInfo *info = GetInfo(); + + float heading = RADTODEG(shooter->GetForward().Heading()); + + CVector source; + CVector target; + CVector dir; + + if ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam() ) + { + TheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, source, target); + float norm = (1.0f / info->m_fRange); + dir = (target - source) * norm; + } + else + { + float angle = DEGTORAD(heading); + dir = CVector(-Sin(angle)*0.5f, Cos(angle)*0.5f, 0.0f); + target = *fireSource + dir; + } + + CShotInfo::AddShot(shooter, m_eWeaponType, *fireSource, target); + CWeapon::GenerateFlameThrowerParticles(*fireSource, dir); + + return true; +} + +bool +CWeapon::FireSniper(CEntity *shooter) +{ + ASSERT(shooter!=NULL); + + int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; + if (!( mode == CCam::MODE_M16_1STPERSON + || mode == CCam::MODE_SNIPER + || mode == CCam::MODE_ROCKETLAUNCHER + || mode == CCam::MODE_M16_1STPERSON_RUNABOUT + || mode == CCam::MODE_SNIPER_RUNABOUT + || mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT) ) + { + return false; + } + +#ifndef FIX_BUGS + CWeaponInfo *info = GetInfo(); //unused +#endif + + CCam *cam = &TheCamera.Cams[TheCamera.ActiveCam]; + ASSERT(cam!=NULL); + + CVector source = cam->Source; + CVector dir = cam->Front; + + if ( DotProduct(dir, CVector(0.0f, -0.9894f, 0.145f)) > 0.997f ) + CCoronas::bSmallMoon = !CCoronas::bSmallMoon; + + dir.Normalise(); + dir *= 16.0f; + + CBulletInfo::AddBullet(shooter, m_eWeaponType, source, dir); + + if ( shooter == FindPlayerPed() ) + ++CStats::InstantHitsFiredByPlayer; + + if ( shooter == FindPlayerPed() ) + { + CPad::GetPad(0)->StartShake_Distance(240, 128, + FindPlayerPed()->GetPosition().x, + FindPlayerPed()->GetPosition().y, + FindPlayerPed()->GetPosition().z); + + CamShakeNoPos(&TheCamera, 0.2f); + } + + return true; +} + +bool +CWeapon::FireM16_1stPerson(CEntity *shooter) +{ + ASSERT(shooter!=NULL); + + int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; + + if (!( mode == CCam::MODE_M16_1STPERSON + || mode == CCam::MODE_SNIPER + || mode == CCam::MODE_ROCKETLAUNCHER + || mode == CCam::MODE_M16_1STPERSON_RUNABOUT + || mode == CCam::MODE_SNIPER_RUNABOUT + || mode == CCam::MODE_ROCKETLAUNCHER_RUNABOUT + || mode == CCam::MODE_HELICANNON_1STPERSON) ) + { + return false; + } + + CWeaponInfo *info = GetInfo(); + + CColPoint point; + CEntity *victim; + + CWorld::bIncludeCarTyres = true; + CWorld::pIgnoreEntity = shooter; + CWorld::bIncludeDeadPeds = true; + + CCam *cam = &TheCamera.Cams[TheCamera.ActiveCam]; + ASSERT(cam!=NULL); + + CVector source = cam->Source; + CVector target = cam->Front*info->m_fRange + source; + + ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + CWorld::bIncludeDeadPeds = false; + CWorld::pIgnoreEntity = NULL; + CWorld::bIncludeCarTyres = false; + + CVector2D front(cam->Front.x, cam->Front.y); + front.Normalise(); + + DoBulletImpact(shooter, victim, &source, &target, &point, front); + + CVector bulletPos; + if ( CHeli::TestBulletCollision(&source, &target, &bulletPos, 4) ) + { + for ( int32 i = 0; i < 16; i++ ) + CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f)); + } + + if ( shooter == FindPlayerPed() ) + { + CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); + + if ( m_eWeaponType == WEAPONTYPE_M16 ) + { + TheCamera.Cams[TheCamera.ActiveCam].Beta += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0003f; + TheCamera.Cams[TheCamera.ActiveCam].Alpha += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0003f; + } + else if ( m_eWeaponType == WEAPONTYPE_HELICANNON ) + { + TheCamera.Cams[TheCamera.ActiveCam].Beta += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0001f; + TheCamera.Cams[TheCamera.ActiveCam].Alpha += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0001f; + } + } + + return true; +} + +bool +CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) +{ + CWeaponInfo *info = GetInfo(); + + CVehicleModelInfo *modelInfo = shooter->GetModelInfo(); + + #define FRONTSEATPOS() (&(shooter->IsBoat() ? modelInfo->m_positions[BOAT_POS_FRONTSEAT] : modelInfo->m_positions[CAR_POS_FRONTSEAT])) + + CVector source, target; + if ( left ) + { + source = shooter->GetMatrix() * CVector(-shooter->GetColModel()->boundingBox.max.x + -0.2f, + float(CGeneral::GetRandomNumber() & 255) * 0.001f + FRONTSEATPOS()->y, + FRONTSEATPOS()->z + 0.5f); + source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; + + + target = shooter->GetMatrix() * CVector(-info->m_fRange, + FRONTSEATPOS()->y, + FRONTSEATPOS()->z + 0.5f); + } + else + { + source = shooter->GetMatrix() * CVector(shooter->GetColModel()->boundingBox.max.x + 0.2f, + float(CGeneral::GetRandomNumber() & 255) * 0.001f + FRONTSEATPOS()->y, + FRONTSEATPOS()->z + 0.5f); + source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; + + target = shooter->GetMatrix() * CVector(info->m_fRange, + FRONTSEATPOS()->y, + FRONTSEATPOS()->z + 0.5f); + } + #undef FRONTSEATPOS + + if ( TheCamera.GetLookingLRBFirstPerson() && !left ) + { + source -= 0.3f * shooter->GetForward(); + target -= 0.3f * shooter->GetForward(); + } + + target += CVector(float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f, + float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f, + float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f); + + DoDriveByAutoAiming(FindPlayerPed(), &source, &target); + + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, FindPlayerPed(), FindPlayerPed(), 1000); + + if ( !TheCamera.GetLookingLRBFirstPerson() ) + CParticle::AddParticle(PARTICLE_GUNFLASH, source, CVector(0.0f, 0.0f, 0.0f)); + else + CamShakeNoPos(&TheCamera, 0.01f); + + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_VEHICLE, shooter, FindPlayerPed(), 1000); + + CPointLights::AddLight(CPointLights::LIGHT_POINT, source, CVector(0.0f, 0.0f, 0.0f), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + + CColPoint point; + CEntity *victim; + ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); + + if ( !(CTimer::GetFrameCounter() & 3) ) + MakePedsJumpAtShot(shooter, &source, &target); + + if ( victim ) + { + CVector traceTarget = point.point; + CBulletTraces::AddTrace(&source, &traceTarget); + + if ( victim->IsPed() ) + { + CPed *victimPed = (CPed*)victim; + + if ( !victimPed->DyingOrDead() && victim != (CEntity *)shooter ) + { + CVector pos = victimPed->GetPosition(); + + CVector2D posOffset(source.x-pos.x, source.y-pos.y); + int32 localDir = victimPed->GetLocalDirection(posOffset); + + victimPed->ReactToAttack(FindPlayerPed()); + victimPed->ClearAttackByRemovingAnim(); + + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); + ASSERT(asoc!=NULL); + asoc->blendAmount = 0.0f; + asoc->blendDelta = 8.0f; + + victimPed->InflictDamage(shooter, WEAPONTYPE_UZI_DRIVEBY, 3*info->m_nDamage, (ePedPieceTypes)point.pieceB, localDir); + + pos.z += 0.8f; + + if ( victimPed->GetIsOnScreen() ) + { + if ( CGame::nastyGame ) + { + for ( int32 i = 0; i < 4; i++ ) + { + CVector dir; + dir.x = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + dir.y = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + dir.z = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + + CParticle::AddParticle(PARTICLE_BLOOD, pos, dir); + } + } + } + + if ( victimPed->m_nPedType == PEDTYPE_COP ) + CEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victimPed, FindPlayerPed(), 10000); + else + CEventList::RegisterEvent(EVENT_SHOOT_PED, EVENT_ENTITY_PED, victimPed, FindPlayerPed(), 10000); + } + } + else if ( victim->IsVehicle() ) + ((CVehicle *)victim)->InflictDamage(FindPlayerPed(), WEAPONTYPE_UZI_DRIVEBY, info->m_nDamage); + else + CGlass::WasGlassHitByBullet(victim, point.point); + + switch ( victim->m_type ) + { + case ENTITY_TYPE_BUILDING: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_1, point.point); + break; + } + case ENTITY_TYPE_VEHICLE: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f); + break; + } + case ENTITY_TYPE_PED: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f); + ((CPed*)victim)->Say(SOUND_PED_BULLET_HIT); + break; + } + case ENTITY_TYPE_OBJECT: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point.point); + break; + } + case ENTITY_TYPE_DUMMY: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_3, point.point); + break; + } + } + } + else + { + float norm = 30.0f/info->m_fRange; + CVector traceTarget = (target-source)*norm + source; + CBulletTraces::AddTrace(&source, &traceTarget); + } + + if ( shooter == FindPlayerVehicle() ) + CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerVehicle()->GetPosition().x, FindPlayerVehicle()->GetPosition().y, FindPlayerVehicle()->GetPosition().z); + + return true; +} + +void +CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) +{ + ASSERT(shooter!=NULL); + ASSERT(source!=NULL); + ASSERT(target !=NULL); + +#ifndef FIX_BUGS + CEntity entity; // unused +#endif + + CPed *shooterPed = (CPed*)shooter; + if ( shooterPed->IsPed() && shooterPed->bCrouchWhenShooting ) + return; + + int16 lastEntity; + CEntity *entities[16]; + CWorld::FindObjectsInRange(*source, (*target-*source).Magnitude(), true, &lastEntity, 15, entities, false, true, true, false, false); + + float closestEntityDist = 10000.0f; + int16 closestEntity; + + for ( int32 i = 0; i < lastEntity; i++ ) + { + CEntity *victim = entities[i]; + ASSERT(victim!=NULL); + + if ( (CEntity*)shooterPed != victim && shooterPed->CanSeeEntity(victim, DEGTORAD(22.5f)) ) + { + if ( !(victim->m_status == STATUS_TRAIN_MOVING + || victim->m_status == STATUS_TRAIN_NOT_MOVING + || victim->m_status == STATUS_HELI + || victim->m_status == STATUS_PLANE) ) + { + float distToVictim = (shooterPed->GetPosition()-victim->GetPosition()).Magnitude2D(); + float distToVictimZ = Abs(shooterPed->GetPosition().z-victim->GetPosition().z); + + if ( 1.5f*distToVictimZ < distToVictim ) + { + float entityDist = Sqrt(SQR(distToVictim) + SQR(distToVictimZ)); + + if ( entityDist < closestEntityDist ) + { + closestEntityDist = entityDist; + closestEntity = i; + } + } + } + } + } + + if ( closestEntityDist < DOOMAUTOAIMING_MAXDIST ) + { + CEntity *victim = entities[closestEntity]; + ASSERT(victim !=NULL); + + float distToTarget = (*target - *source).Magnitude2D(); + float distToSource = (victim->GetPosition() - *source).Magnitude2D(); + + float victimZ = victim->GetPosition().z + 0.3f; + if ( victim->IsPed() ) + { + if ( ((CPed*)victim)->bIsDucking ) + victimZ -= 0.8f; + } + + (*target).z = (distToTarget / distToSource) * (victimZ - (*source).z) + (*source).z; + } +} + +void +CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CVector *target) +{ + ASSERT(shooter!=NULL); + ASSERT(driver!=NULL); + ASSERT(source!=NULL); + ASSERT(target!=NULL); + +#ifndef FIX_BUGS + CEntity entity; // unused +#endif + + int16 lastEntity; + CEntity *entities[16]; + CWorld::FindObjectsInRange(*source, (*target-*source).Magnitude(), true, &lastEntity, 15, entities, false, true, false, false, false); + + float closestEntityDist = 10000.0f; + int16 closestEntity; + + float normZ = (target->z - source->z) / (*target-*source).Magnitude(); + + for ( int32 i = 0; i < lastEntity; i++ ) + { + CEntity *victim = entities[i]; + + ASSERT(victim!=NULL); + + if ( shooter != victim && driver != victim ) + { + if ( !(victim->m_status == STATUS_TRAIN_MOVING + || victim->m_status == STATUS_TRAIN_NOT_MOVING + || victim->m_status == STATUS_HELI + || victim->m_status == STATUS_PLANE) ) + { + if ( !(victim->IsVehicle() && victim->bRenderScorched) ) + { + float distToVictim = (shooter->GetPosition()-victim->GetPosition()).Magnitude2D(); + float distToVictimZ = Abs(shooter->GetPosition().z - (distToVictim*normZ + victim->GetPosition().z)); + + if ( 3.0f*distToVictimZ < distToVictim ) + { + if ( CCollision::DistToLine(source, target, + &CVector(victim->GetPosition().x, victim->GetPosition().y, 0.0f)) < victim->GetBoundRadius()*3.0f ) + { + float vehicleDist = Sqrt(SQR(distToVictim) + SQR(distToVictimZ)); + if ( vehicleDist < closestEntityDist ) + { + closestEntityDist = vehicleDist; + closestEntity = i; + } + } + } + } + } + } + } + + if ( closestEntityDist < DOOMAUTOAIMING_MAXDIST ) + { + CEntity *victim = entities[closestEntity]; + ASSERT(victim!=NULL); + + float distToTarget = (*target - *source).Magnitude2D(); + float distToSource = (victim->GetPosition() - *source).Magnitude2D(); + + (*target).z = (distToTarget / distToSource) * (0.3f + victim->GetPosition().z - (*source).z) + (*source).z; + } +} + +void +CWeapon::DoDriveByAutoAiming(CEntity *shooter, CVector *source, CVector *target) +{ + ASSERT(shooter!=NULL); + ASSERT(source!=NULL); + ASSERT(target!=NULL); + +#ifndef FIX_BUGS + CEntity entity; // unused +#endif + + CPed *shooterPed = (CPed*)shooter; + if ( shooterPed->IsPed() && shooterPed->bCrouchWhenShooting ) + return; + + int16 lastEntity; + CEntity *entities[16]; + CWorld::FindObjectsInRange(*source, (*target-*source).Magnitude(), true, &lastEntity, 15, entities, false, false, true, false, false); + + float closestEntityDist = 10000.0f; + int16 closestEntity; + + for ( int32 i = 0; i < lastEntity; i++ ) + { + CEntity *victim = entities[i]; + ASSERT(victim!=NULL); + + if ( shooter != victim ) + { + float lineDist = CCollision::DistToLine(source, target, &victim->GetPosition()); + float distToVictim = (victim->GetPosition() - shooter->GetPosition()).Magnitude(); + float pedDist = 0.15f*distToVictim + lineDist; + + if ( DotProduct((*target-*source), victim->GetPosition()-*source) > 0.0f && pedDist < closestEntityDist) + { + closestEntity = i; + closestEntityDist = pedDist; + } + } + } + + if ( closestEntityDist < DRIVEBYAUTOAIMING_MAXDIST ) + { + CEntity *victim = entities[closestEntity]; + ASSERT(victim!=NULL); + + float distToTarget = (*source - *target).Magnitude(); + float distToSource = (*source - victim->GetPosition()).Magnitude(); + *target = (distToTarget / distToSource) * (victim->GetPosition() - *source) + *source; + } +} + void CWeapon::Reload(void) { if (m_nAmmoTotal == 0) return; - CWeaponInfo *info = CWeaponInfo::GetWeaponInfo(m_eWeaponType); + CWeaponInfo *info = GetInfo(); if (m_nAmmoTotal >= info->m_nAmountofAmmunition) m_nAmmoInClip = info->m_nAmountofAmmunition; @@ -44,10 +1971,159 @@ CWeapon::Reload(void) m_nAmmoInClip = m_nAmmoTotal; } -bool -CWeapon::IsType2Handed(void) +void +CWeapon::Update(int32 audioEntity) { - return m_eWeaponType >= WEAPONTYPE_SHOTGUN && m_eWeaponType <= WEAPONTYPE_FLAMETHROWER && m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER; + switch ( m_eWeaponState ) + { + case WEAPONSTATE_MELEE_MADECONTACT: + { + m_eWeaponState = WEAPONSTATE_READY; + break; + } + + case WEAPONSTATE_FIRING: + { + if ( m_eWeaponType == WEAPONTYPE_SHOTGUN && AEHANDLE_IS_OK(audioEntity) ) + { + uint32 timePassed = m_nTimer - gReloadSampleTime[WEAPONTYPE_SHOTGUN]; + if ( CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed ) + DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); + } + + if ( CTimer::GetTimeInMilliseconds() > m_nTimer ) + { + if ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE && m_nAmmoTotal == 0 ) + m_eWeaponState = WEAPONSTATE_OUT_OF_AMMO; + else + m_eWeaponState = WEAPONSTATE_READY; + } + + break; + } + + case WEAPONSTATE_RELOADING: + { + if ( AEHANDLE_IS_OK(audioEntity) && m_eWeaponType < WEAPONTYPE_LAST_WEAPONTYPE ) + { + uint32 timePassed = m_nTimer - gReloadSampleTime[m_eWeaponType]; + if ( CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed ) + DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); + } + + if ( CTimer::GetTimeInMilliseconds() > m_nTimer ) + { + Reload(); + m_eWeaponState = WEAPONSTATE_READY; + } + + break; + } + } +} + +void +FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) +{ + ASSERT(source!=NULL); + ASSERT(target!=NULL); + + CParticle::AddParticle(PARTICLE_GUNFLASH, *source, CVector(0.0f, 0.0f, 0.0f)); + + CPointLights::AddLight(CPointLights::LIGHT_POINT, + *source, CVector(0.0f, 0.0f, 0.0f), 5.0f, + 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); + + CColPoint point; + CEntity *victim; + CWorld::ProcessLineOfSight(*source, *target, point, victim, true, true, true, true, true, true, false); + + CParticle::AddParticle(PARTICLE_HELI_ATTACK, *source, (*target) - (*source) * 0.15f); + + if ( victim ) + { + if ( victim->IsPed() ) + { + CPed *victimPed = (CPed *)victim; + if ( !victimPed->DyingOrDead() ) + { + CVector pos = victimPed->GetPosition(); + + CVector2D posOffset((*source).x-pos.x, (*source).y-pos.y); + int32 localDir = victimPed->GetLocalDirection(posOffset); + + victimPed->ClearAttackByRemovingAnim(); + + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); + ASSERT(asoc!=NULL); + asoc->blendAmount = 0.0f; + asoc->blendDelta = 8.0f; + + victimPed->InflictDamage(NULL, WEAPONTYPE_UZI, damage, (ePedPieceTypes)point.pieceB, localDir); + + pos.z += 0.8f; + + if ( victimPed->GetIsOnScreen() ) + { + if ( CGame::nastyGame ) + { + for ( int32 i = 0; i < 4; i++ ) + { + CVector dir; + dir.x = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + dir.y = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + dir.z = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); + + CParticle::AddParticle(PARTICLE_BLOOD, pos, dir); + } + } + } + } + } + else if ( victim->IsVehicle() ) + ((CVehicle *)victim)->InflictDamage(NULL, WEAPONTYPE_UZI, damage); + //BUG ? no CGlass::WasGlassHitByBullet + + switch ( victim->m_type ) + { + case ENTITY_TYPE_BUILDING: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_1, point.point); + CParticle::AddParticle(PARTICLE_SMOKE, point.point, CVector(0.0f, 0.0f, 0.01f)); + break; + } + case ENTITY_TYPE_VEHICLE: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_VEHICLE, 1.0f); + break; + } + case ENTITY_TYPE_PED: + { + DMAudio.PlayOneShot(((CPhysical*)victim)->m_audioEntityId, SOUND_WEAPON_HIT_PED, 1.0f); + ((CPed*)victim)->Say(SOUND_PED_BULLET_HIT); + break; + } + case ENTITY_TYPE_OBJECT: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_2, point.point); + break; + } + case ENTITY_TYPE_DUMMY: + { + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_GROUND_3, point.point); + break; + } + } + } + else + { + float waterLevel; + if ( CWaterLevel::GetWaterLevel((*target).x, (*target).y, (*target).z + 10.0f, &waterLevel, false) ) + { + CParticle::AddParticle(PARTICLE_BOAT_SPLASH, CVector((*target).x, (*target).y, waterLevel), CVector(0.0f, 0.0f, 0.01f)); + PlayOneShotScriptObject(SCRIPT_SOUND_BULLET_HIT_WATER, point.point); // no sound(empty) + } + } } bool @@ -57,32 +2133,75 @@ CWeapon::IsTypeMelee(void) } bool -CWeapon::HitsGround(CEntity *holder, CVector *firePos, CEntity *aimingTo) +CWeapon::IsType2Handed(void) { + return m_eWeaponType >= WEAPONTYPE_SHOTGUN && m_eWeaponType <= WEAPONTYPE_FLAMETHROWER && m_eWeaponType != WEAPONTYPE_ROCKETLAUNCHER; +} + +void +CWeapon::MakePedsJumpAtShot(CPhysical *shooter, CVector *source, CVector *target) +{ + ASSERT(shooter!=NULL); + ASSERT(source!=NULL); + ASSERT(target!=NULL); + + float minx = min(source->x, target->x) - 2.0f; + float maxx = max(source->x, target->x) + 2.0f; + float miny = min(source->y, target->y) - 2.0f; + float maxy = max(source->y, target->y) + 2.0f; + float minz = min(source->z, target->z) - 2.0f; + float maxz = max(source->z, target->z) + 2.0f; + + for ( int32 i = CPools::GetPedPool()->GetSize() - 1; i >= 0; i--) + { + CPed *ped = CPools::GetPedPool()->GetSlot(i); + + if ( ped ) + { + if ( ped->GetPosition().x > minx && ped->GetPosition().x < maxx + && ped->GetPosition().y > miny && ped->GetPosition().y < maxy + && ped->GetPosition().z > minz && ped->GetPosition().z < maxz ) + { + if ( ped != FindPlayerPed() && (uint8)(ped->m_randomSeed ^ CGeneral::GetRandomNumber()) & 31 ) + ped->SetEvasiveDive(shooter, 1); + } + } + } +} + +bool +CWeapon::HitsGround(CEntity *holder, CVector *fireSource, CEntity *aimingTo) +{ + ASSERT(holder!=NULL); + ASSERT(aimingTo!=NULL); + if (!holder->IsPed() || !((CPed*)holder)->m_pSeekTarget) return false; - CWeaponInfo *ourType = CWeaponInfo::GetWeaponInfo(m_eWeaponType); - CVector adjustedOffset = ourType->m_vecFireOffset; + CWeaponInfo *info = GetInfo(); + + CVector adjustedOffset = info->m_vecFireOffset; adjustedOffset.z += 0.6f; - CVector point1, point2; + CVector source, target; CEntity *foundEnt = nil; CColPoint foundCol; - if (firePos) - point1 = *firePos; + if (fireSource) + source = *fireSource; else - point1 = holder->GetMatrix() * adjustedOffset; + source = holder->GetMatrix() * adjustedOffset; CEntity *aimEntity = aimingTo ? aimingTo : ((CPed*)holder)->m_pSeekTarget; - point2 = aimEntity->GetPosition(); - point2.z += 0.6f; + ASSERT(aimEntity!=NULL); + + target = aimEntity->GetPosition(); + target.z += 0.6f; - CWorld::ProcessLineOfSight(point1, point2, foundCol, foundEnt, true, false, false, false, false, false, false); + CWorld::ProcessLineOfSight(source, target, foundCol, foundEnt, true, false, false, false, false, false, false); if (foundEnt && foundEnt->IsBuilding()) { // That was supposed to be Magnitude, according to leftover code in assembly - float diff = (foundCol.point.z - point1.z); + float diff = (foundCol.point.z - source.z); if (diff < 0.0f && diff > -3.0f) return true; } @@ -90,6 +2209,36 @@ CWeapon::HitsGround(CEntity *holder, CVector *firePos, CEntity *aimingTo) return false; } +void +CWeapon::BlowUpExplosiveThings(CEntity *thing) +{ + if ( thing ) + { + CObject *object = (CObject*)thing; + int32 mi = object->GetModelIndex(); + if ( IsExplosiveThingModel(mi) && !object->bHasBeenDamaged ) + { + object->bHasBeenDamaged = true; + + CExplosion::AddExplosion(object, FindPlayerPed(), EXPLOSION_BARREL, object->GetPosition()+CVector(0.0f,0.0f,0.5f), 100); + + if ( MI_EXPLODINGBARREL == mi ) + object->m_vecMoveSpeed.z += 0.75f; + else + object->m_vecMoveSpeed.z += 0.45f; + + object->m_vecMoveSpeed.x += float((CGeneral::GetRandomNumber()&255) - 128) * 0.0002f; + object->m_vecMoveSpeed.y += float((CGeneral::GetRandomNumber()&255) - 128) * 0.0002f; + + if ( object->bIsStatic ) + { + object->bIsStatic = false; + object->AddToMovingList(); + } + } + } +} + bool CWeapon::HasWeaponAmmoToBeUsed(void) { @@ -101,9 +2250,43 @@ CWeapon::HasWeaponAmmoToBeUsed(void) return m_nAmmoTotal != 0; } } + +bool +CWeapon::ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPoint &point, CEntity *&entity, eWeaponType type, CEntity *shooter, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) +{ + return CWorld::ProcessLineOfSight(point1, point2, point, entity, checkBuildings, checkVehicles, checkPeds, checkObjects, checkDummies, ignoreSeeThrough, ignoreSomeObjects); +} STARTPATCHES + + InjectHook(0x55C2D0, CWeapon::InitialiseWeapons, PATCH_JUMP); + InjectHook(0x55C2F0, CWeapon::ShutdownWeapons, PATCH_JUMP); + InjectHook(0x55C310, CWeapon::UpdateWeapons, PATCH_JUMP); InjectHook(0x55C330, &CWeapon::Initialise, PATCH_JUMP); + InjectHook(0x55C380, &CWeapon::Fire, PATCH_JUMP); + InjectHook(0x55C940, &CWeapon::FireFromCar, PATCH_JUMP); + InjectHook(0x55CA20, &CWeapon::FireMelee, PATCH_JUMP); + InjectHook(0x55D2E0, &CWeapon::FireInstantHit, PATCH_JUMP); + InjectHook(0x55F770, &CWeapon::AddGunshell, PATCH_JUMP); + InjectHook(0x55F950, &CWeapon::DoBulletImpact, PATCH_JUMP); + InjectHook(0x560620, &CWeapon::FireShotgun, PATCH_JUMP); + InjectHook(0x561900, &CWeapon::FireProjectile, PATCH_JUMP); + InjectHook(0x561C70, CWeapon::GenerateFlameThrowerParticles, PATCH_JUMP); + InjectHook(0x561E00, &CWeapon::FireAreaEffect, PATCH_JUMP); + InjectHook(0x561FE0, &CWeapon::FireSniper, PATCH_JUMP); + InjectHook(0x562180, &CWeapon::FireM16_1stPerson, PATCH_JUMP); + InjectHook(0x5624D0, &CWeapon::FireInstantHitFromCar, PATCH_JUMP); + InjectHook(0x562EB0, CWeapon::DoDoomAiming, PATCH_JUMP); + InjectHook(0x563200, CWeapon::DoTankDoomAiming, PATCH_JUMP); + InjectHook(0x563660, CWeapon::DoDriveByAutoAiming, PATCH_JUMP); InjectHook(0x5639D0, &CWeapon::Reload, PATCH_JUMP); + InjectHook(0x563A10, &CWeapon::Update, PATCH_JUMP); + InjectHook(0x563FB0, &CWeapon::IsTypeMelee, PATCH_JUMP); + InjectHook(0x563FD0, &CWeapon::IsType2Handed, PATCH_JUMP); + InjectHook(0x564680, CWeapon::MakePedsJumpAtShot, PATCH_JUMP); InjectHook(0x564890, &CWeapon::HitsGround, PATCH_JUMP); + InjectHook(0x564A60, CWeapon::BlowUpExplosiveThings, PATCH_JUMP); + InjectHook(0x564B80, &CWeapon::HasWeaponAmmoToBeUsed, PATCH_JUMP); + InjectHook(0x564C00, CWeapon::ProcessLineOfSight, PATCH_JUMP); + ENDPATCHES diff --git a/src/weapons/Weapon.h b/src/weapons/Weapon.h index 84760550..265ffddb 100644 --- a/src/weapons/Weapon.h +++ b/src/weapons/Weapon.h @@ -1,5 +1,8 @@ #pragma once +#define DRIVEBYAUTOAIMING_MAXDIST (2.5f) +#define DOOMAUTOAIMING_MAXDIST (9000.0f) + enum eWeaponType { WEAPONTYPE_UNARMED, @@ -49,7 +52,10 @@ enum eWeaponState }; class CEntity; +class CPhysical; class CAutomobile; +struct CColPoint; +class CWeaponInfo; class CWeapon { @@ -64,22 +70,50 @@ public: CWeapon() { m_bAddRotOffset = false; } + + CWeaponInfo *GetInfo(); - static void ShutdownWeapons(void); - void Initialise(eWeaponType type, int ammo); - void Update(int32 audioEntity); - void Reload(void); - bool Fire(CEntity*, CVector*); - void FireFromCar(CAutomobile *car, bool left); - void AddGunshell(CEntity*, CVector const&, CVector2D const&, float); - bool IsTypeMelee(void); - bool IsType2Handed(void); - static void DoTankDoomAiming(CEntity *playerVehicle, CEntity *playerPed, CVector *start, CVector *end); - bool HitsGround(CEntity* holder, CVector* firePos, CEntity* aimingTo); - bool HasWeaponAmmoToBeUsed(void); static void InitialiseWeapons(void); - static void UpdateWeapons(void); + static void ShutdownWeapons (void); + static void UpdateWeapons (void); + + void Initialise(eWeaponType type, int32 ammo); + + bool Fire (CEntity *shooter, CVector *fireSource); + bool FireFromCar (CAutomobile *shooter, bool left); + bool FireMelee (CEntity *shooter, CVector &fireSource); + bool FireInstantHit(CEntity *shooter, CVector *fireSource); + + void AddGunshell (CEntity *shooter, CVector const &source, CVector2D const &direction, float size); + void DoBulletImpact(CEntity *shooter, CEntity *victim, CVector *source, CVector *target, CColPoint *point, CVector2D ahead); + + bool FireShotgun (CEntity *shooter, CVector *fireSource); + bool FireProjectile(CEntity *shooter, CVector *fireSource, float power); + + static void GenerateFlameThrowerParticles(CVector pos, CVector dir); + + bool FireAreaEffect (CEntity *shooter, CVector *fireSource); + bool FireSniper (CEntity *shooter); + bool FireM16_1stPerson (CEntity *shooter); + bool FireInstantHitFromCar(CAutomobile *shooter, bool left); + + static void DoDoomAiming (CEntity *shooter, CVector *source, CVector *target); + static void DoTankDoomAiming (CEntity *shooter, CEntity *driver, CVector *source, CVector *target); + static void DoDriveByAutoAiming(CEntity *shooter, CVector *source, CVector *target); + + void Reload(void); + void Update(int32 audioEntity); + bool IsTypeMelee (void); + bool IsType2Handed(void); + + static void MakePedsJumpAtShot(CPhysical *shooter, CVector *source, CVector *target); + + bool HitsGround(CEntity *holder, CVector *fireSource, CEntity *aimingTo); + static void BlowUpExplosiveThings(CEntity *thing); + bool HasWeaponAmmoToBeUsed(void); + + static bool ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPoint &point, CEntity *&entity, eWeaponType type, CEntity *shooter, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects); }; -static_assert(sizeof(CWeapon) == 0x18, "CWeapon: error"); +VALIDATE_SIZE(CWeapon, 0x18); -void FireOneInstantHitRound(CVector* shotSource, CVector* shotTarget, int32 damage); \ No newline at end of file +void FireOneInstantHitRound(CVector *source, CVector *target, int32 damage); \ No newline at end of file From 7c13d72edc43ad0f141739937ab6238197a1db38 Mon Sep 17 00:00:00 2001 From: Fire_Head Date: Wed, 15 Apr 2020 08:13:46 +0300 Subject: [PATCH 08/18] Update Weapon.cpp --- src/weapons/Weapon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index d4312649..28031847 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -1518,7 +1518,7 @@ CWeapon::FireSniper(CEntity *shooter) CBulletInfo::AddBullet(shooter, m_eWeaponType, source, dir); if ( shooter == FindPlayerPed() ) - ++CStats::InstantHitsFiredByPlayer; + CStats::InstantHitsFiredByPlayer++; if ( shooter == FindPlayerPed() ) { From d7eee5c1307d80b64771e15458e0b1fd70898706 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 15 Apr 2020 15:26:55 +0200 Subject: [PATCH 09/18] fixed clouds and sprites --- src/render/Clouds.cpp | 2 +- src/render/Sprite.cpp | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/render/Clouds.cpp b/src/render/Clouds.cpp index 39866294..7debe3d3 100644 --- a/src/render/Clouds.cpp +++ b/src/render/Clouds.cpp @@ -233,7 +233,7 @@ CClouds::Render(void) szx*55.0f, szy*55.0f, tr, tg, tb, br, bg, bb, 0.0f, -1.0f, 1.0f/screenpos.z, - IndividualRotation/65336.0f * 2*3.14f + ms_cameraRoll, + (uint16)IndividualRotation/65336.0f * 6.28f + ms_cameraRoll, fluffyalpha); bCloudOnScreen[i] = true; }else diff --git a/src/render/Sprite.cpp b/src/render/Sprite.cpp index 8ac2315f..82754121 100644 --- a/src/render/Sprite.cpp +++ b/src/render/Sprite.cpp @@ -137,8 +137,8 @@ CSprite::RenderOneXLUSprite(float x, float y, float z, float w, float h, uint8 r void CSprite::RenderOneXLUSprite_Rotate_Aspect(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float rotation, uint8 a) { - float c = Cos(DEGTORAD(rotation)); - float s = Sin(DEGTORAD(rotation)); + float c = Cos(rotation); + float s = Sin(rotation); float xs[4]; float ys[4]; @@ -315,8 +315,8 @@ void CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float rotation, uint8 a) { m_bFlushSpriteBufferSwitchZTest = 0; - float c = Cos(DEGTORAD(rotation)); - float s = Sin(DEGTORAD(rotation)); + float c = Cos(rotation); + float s = Sin(rotation); float xs[4]; float ys[4]; @@ -367,8 +367,8 @@ void CSprite::RenderBufferedOneXLUSprite_Rotate_2Colours(float x, float y, float z, float w, float h, uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2, float cx, float cy, float recipz, float rotation, uint8 a) { m_bFlushSpriteBufferSwitchZTest = 0; - float c = Cos(DEGTORAD(rotation)); - float s = Sin(DEGTORAD(rotation)); + float c = Cos(rotation); + float s = Sin(rotation); float xs[4]; float ys[4]; @@ -398,11 +398,11 @@ CSprite::RenderBufferedOneXLUSprite_Rotate_2Colours(float x, float y, float z, f // Colour factors, cx/y is the direction in which colours change from rgb1 to rgb2 cf[0] = (cx*(-c-s) + cy*(-c+s))*0.5f + 0.5f; cf[0] = clamp(cf[0], 0.0f, 1.0f); - cf[1] = (cx*(-c-s) + cy*(-c+s))*0.5f + 0.5f; + cf[1] = (cx*(-c+s) + cy*( c+s))*0.5f + 0.5f; cf[1] = clamp(cf[1], 0.0f, 1.0f); - cf[2] = (cx*(-c-s) + cy*(-c+s))*0.5f + 0.5f; + cf[2] = (cx*( c+s) + cy*( c-s))*0.5f + 0.5f; cf[2] = clamp(cf[2], 0.0f, 1.0f); - cf[3] = (cx*(-c-s) + cy*(-c+s))*0.5f + 0.5f; + cf[3] = (cx*( c-s) + cy*(-c-s))*0.5f + 0.5f; cf[3] = clamp(cf[3], 0.0f, 1.0f); float screenz = m_f2DNearScreenZ + From eccc4a3a5b45253ad8a6bdacbfccb8a15299d334 Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 15 Apr 2020 16:17:18 +0200 Subject: [PATCH 10/18] fixed bug and weirdness in CHeli --- src/vehicles/Heli.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/vehicles/Heli.cpp b/src/vehicles/Heli.cpp index 3dc1deeb..c4cdcb02 100644 --- a/src/vehicles/Heli.cpp +++ b/src/vehicles/Heli.cpp @@ -78,6 +78,9 @@ CHeli::CHeli(int32 id, uint8 CreatedBy) m_bTestRight = true; m_fTargetOffset = 0.0f; m_fSearchLightX = m_fSearchLightY = 0.0f; + + // BUG: not in game but gets initialized to CDCDCDCD in debug + m_nLastShotTime = 0; } void @@ -590,7 +593,12 @@ CHeli::PreRender(void) break; } RwRGBA col = { r, g, b, 32 }; +#ifdef FIX_BUGS + pos.z = m_fHeliDustZ[frm]; +#else + // What the hell is the point of this? pos.z = m_fHeliDustZ[(i - (i&3))/4]; // advance every 4 iterations, why not just /4? +#endif if(pos.z > -200.0f && GetPosition().z - pos.z < 20.0f) CParticle::AddParticle(PARTICLE_HELI_DUST, pos, dir, nil, 0.0f, col); i++; From 4da1879975ef28cb7f406166d62d154d03ef47d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Wed, 15 Apr 2020 19:19:45 +0300 Subject: [PATCH 11/18] Many fixes and cleanup --- src/control/Garages.cpp | 10 ++- src/control/Script.cpp | 2 +- src/core/Collision.cpp | 5 +- src/core/Collision.h | 11 +++- src/core/Frontend.cpp | 127 ++++++++++++++++++------------------ src/core/Frontend.h | 8 ++- src/core/World.cpp | 4 +- src/core/World.h | 4 +- src/core/main.cpp | 5 +- src/entities/Physical.cpp | 6 +- src/peds/Ped.cpp | 17 ++--- src/peds/Ped.h | 10 +-- src/peds/Population.cpp | 58 ++++++++-------- src/render/Renderer.cpp | 17 ++--- src/render/Renderer.h | 16 ++--- src/vehicles/Automobile.cpp | 7 +- src/vehicles/Vehicle.cpp | 12 ++-- src/vehicles/Vehicle.h | 12 ++-- 18 files changed, 174 insertions(+), 157 deletions(-) diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index d971d453..9bd9a577 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -307,13 +307,13 @@ void CGarage::Update() CGarages::bCamShouldBeOutisde = true; } if (pVehicle) { - if (IsEntityEntirelyOutside(pVehicle, 0.0f)) + if (!IsEntityEntirelyOutside(pVehicle, 0.0f)) TheCamera.pToGarageWeAreInForHackAvoidFirstPerson = this; if (pVehicle->GetModelIndex() == MI_MRWHOOP) { if (pVehicle->IsWithinArea( m_fX1 - DISTANCE_FOR_MRWHOOP_HACK, - m_fX2 + DISTANCE_FOR_MRWHOOP_HACK, - m_fY1 - DISTANCE_FOR_MRWHOOP_HACK, + m_fY1 + DISTANCE_FOR_MRWHOOP_HACK, + m_fX2 - DISTANCE_FOR_MRWHOOP_HACK, m_fY2 + DISTANCE_FOR_MRWHOOP_HACK)) { TheCamera.pToGarageWeAreIn = this; CGarages::bCamShouldBeOutisde = true; @@ -2313,6 +2313,10 @@ void CGarages::Load(uint8* buf, uint32 size) #ifdef FIX_GARAGE_SIZE VALIDATESAVEBUF(size); #endif + + MessageEndTime = 0; + bCamShouldBeOutisde = false; + MessageStartTime = 0; } bool diff --git a/src/control/Script.cpp b/src/control/Script.cpp index ff89f0fc..7a890656 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -11358,7 +11358,7 @@ VALIDATESAVEBUF(size) void CTheScripts::ClearSpaceForMissionEntity(const CVector& pos, CEntity* pEntity) { - static CColPoint aTempColPoints[32]; + static CColPoint aTempColPoints[MAX_COLLISION_POINTS]; int16 entities = 0; CEntity* aEntities[16]; CWorld::FindObjectsKindaColliding(pos, pEntity->GetBoundRadius(), false, &entities, 16, aEntities, false, true, true, false, false); diff --git a/src/core/Collision.cpp b/src/core/Collision.cpp index c884f751..85145e86 100644 --- a/src/core/Collision.cpp +++ b/src/core/Collision.cpp @@ -31,8 +31,8 @@ enum Direction DIR_Z_NEG, }; -eLevelName &CCollision::ms_collisionInMemory = *(eLevelName*)0x8F6250; -CLinkList &CCollision::ms_colModelCache = *(CLinkList*)0x95CB58; +eLevelName CCollision::ms_collisionInMemory; +CLinkList CCollision::ms_colModelCache; void CCollision::Init(void) @@ -1355,6 +1355,7 @@ CCollision::ProcessColModels(const CMatrix &matrixA, CColModel &modelA, modelB.triangles[aTriangleIndicesB[j]], modelB.trianglePlanes[aTriangleIndicesB[j]], spherepoints[numCollisions], coldist); + if(hasCollided) numCollisions++; } diff --git a/src/core/Collision.h b/src/core/Collision.h index 1cbd1690..bdf51eb8 100644 --- a/src/core/Collision.h +++ b/src/core/Collision.h @@ -3,6 +3,13 @@ #include "templates.h" #include "Game.h" // for eLevelName +// If you spawn many tanks at once, you will see that collisions of two entity exceeds 32. +#ifdef FIX_BUGS +#define MAX_COLLISION_POINTS 64 +#else +#define MAX_COLLISION_POINTS 32 +#endif + struct CColSphere { CVector center; @@ -110,8 +117,8 @@ struct CColModel class CCollision { public: - static eLevelName &ms_collisionInMemory; - static CLinkList &ms_colModelCache; + static eLevelName ms_collisionInMemory; + static CLinkList ms_colModelCache; static void Init(void); static void Shutdown(void); diff --git a/src/core/Frontend.cpp b/src/core/Frontend.cpp index 48683abc..166ecb35 100644 --- a/src/core/Frontend.cpp +++ b/src/core/Frontend.cpp @@ -82,34 +82,34 @@ int curBottomBarOption = -1; int hoveredBottomBarOption = -1; #endif -int32 CMenuManager::OS_Language = LANG_ENGLISH; // *(int32*)0x5F2F78; -int8 CMenuManager::m_PrefsUseVibration; // = *(int8*)0x95CD92; -int8 CMenuManager::m_DisplayControllerOnFoot; // = *(int8*)0x95CD8D; -int8 CMenuManager::m_PrefsVsync = 1; // *(int8*)0x5F2E58; -int8 CMenuManager::m_PrefsVsyncDisp = 1; // *(int8*)0x5F2E5C; -int8 CMenuManager::m_PrefsFrameLimiter = 1; // *(int8*)0x5F2E60; -int8 CMenuManager::m_PrefsShowSubtitles = 1; // *(int8*)0x5F2E54; -int8 CMenuManager::m_PrefsSpeakers; // = *(int8*)0x95CD7E; -int32 CMenuManager::m_ControlMethod; // = *(int32*)0x8F5F7C; -int8 CMenuManager::m_PrefsDMA = 1; // *(int8*)0x5F2F74; -int32 CMenuManager::m_PrefsLanguage; // = *(int32*)0x941238; +int32 CMenuManager::OS_Language = LANG_ENGLISH; +int8 CMenuManager::m_PrefsUseVibration; +int8 CMenuManager::m_DisplayControllerOnFoot; +int8 CMenuManager::m_PrefsVsync = 1; +int8 CMenuManager::m_PrefsVsyncDisp = 1; +int8 CMenuManager::m_PrefsFrameLimiter = 1; +int8 CMenuManager::m_PrefsShowSubtitles = 1; +int8 CMenuManager::m_PrefsSpeakers; +int32 CMenuManager::m_ControlMethod; +int8 CMenuManager::m_PrefsDMA = 1; +int32 CMenuManager::m_PrefsLanguage; uint8 CMenuManager::m_PrefsStereoMono; // *(bool*)0x95CDB5; // unused except restore settings -bool CMenuManager::m_PrefsAllowNastyGame = true; // *(bool*)0x5F2E64; -bool CMenuManager::m_bStartUpFrontEndRequested; // = *(bool*)0x95CCF4; -bool CMenuManager::m_bShutDownFrontEndRequested; // = *(bool*)0x95CD6A; +bool CMenuManager::m_PrefsAllowNastyGame = true; +bool CMenuManager::m_bStartUpFrontEndRequested; +bool CMenuManager::m_bShutDownFrontEndRequested; -int8 CMenuManager::m_PrefsUseWideScreen; // = *(int8*)0x95CD23; -int8 CMenuManager::m_PrefsRadioStation; // = *(int8*)0x95CDA4; -int32 CMenuManager::m_PrefsBrightness = 256; // = *(int32*)0x5F2E50; -float CMenuManager::m_PrefsLOD; // = *(float*)0x8F42C4; -int8 CMenuManager::m_bFrontEnd_ReloadObrTxtGxt; // = *(int8*)0x628CFC; -int32 CMenuManager::m_PrefsMusicVolume = 102; // = *(int32*)0x5F2E4C; -int32 CMenuManager::m_PrefsSfxVolume = 102; // = *(int32*)0x5F2E48; +int8 CMenuManager::m_PrefsUseWideScreen; +int8 CMenuManager::m_PrefsRadioStation; +int32 CMenuManager::m_PrefsBrightness = 256; +float CMenuManager::m_PrefsLOD = CRenderer::ms_lodDistScale; +int8 CMenuManager::m_bFrontEnd_ReloadObrTxtGxt; +int32 CMenuManager::m_PrefsMusicVolume = 102; +int32 CMenuManager::m_PrefsSfxVolume = 102; -char CMenuManager::m_PrefsSkinFile[256] = "$$\"\""; // = (char*)0x5F2E74; +char CMenuManager::m_PrefsSkinFile[256] = "$$\"\""; -int32 CMenuManager::m_KeyPressedCode = -1; // = *(int32*)0x5F2E70; +int32 CMenuManager::m_KeyPressedCode = -1; // Originally that was PS2 option color, they forget it here and used in PrintBriefs once(but didn't use the output anyway) #ifdef PS2_LIKE_MENU @@ -119,29 +119,26 @@ const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color #endif const float menuXYpadding = MENUACTION_POS_Y; // *(float*)0x5F355C; // not original name -float MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE; //*(float*)0x5F2E40; -float MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE; //*(float*)0x5F2E44; +float MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE; +float MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE; bool holdingScrollBar; // *(bool*)0x628D59; // not original name -int32 CMenuManager::m_SelectedMap; // *(int32*)0x8E2880; -int32 CMenuManager::m_SelectedGameType; // *(int32*)0x942F88; +int32 CMenuManager::m_SelectedMap; +int32 CMenuManager::m_SelectedGameType; // Used in a hidden menu uint8 CMenuManager::m_PrefsPlayerRed = 255; uint8 CMenuManager::m_PrefsPlayerGreen = 128; uint8 CMenuManager::m_PrefsPlayerBlue; // why?? -CMenuManager FrontEndMenuManager; // = *(CMenuManager*)0x8F59D8; +CMenuManager FrontEndMenuManager; -// Move this somewhere else. -float CRenderer::ms_lodDistScale = 1.2f; // *(float*)0x5F726C; - -uint32 TimeToStopPadShaking; // = *(uint32*)0x628CF8; -char *pEditString; // = *(char**)0x628D00; -int32 *pControlEdit; // = *(int32**)0x628D08; -bool DisplayComboButtonErrMsg; // = *(bool*)0x628D14; -int32 MouseButtonJustClicked; // = *(int32*)0x628D0C; -int32 JoyButtonJustClicked; // = *(int32*)0x628D10; +uint32 TimeToStopPadShaking; +char *pEditString; +int32 *pControlEdit; +bool DisplayComboButtonErrMsg; +int32 MouseButtonJustClicked; +int32 JoyButtonJustClicked; //int32 *pControlTemp = 0; #ifndef MASTER @@ -283,6 +280,12 @@ ScaleAndCenterX(float x) } while(0) #endif +#define PREPARE_MENU_HEADER \ + CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); \ + CFont::SetRightJustifyOn(); \ + CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); \ + CFont::SetFontStyle(FONT_HEADING); + #define ProcessSlider(value, increaseAction, decreaseAction, hoverStartX, hoverEndX) \ do { \ lastActiveBarX = DisplaySlider(SCREEN_STRETCH_FROM_RIGHT(MENUSLIDER_X + columnWidth), MENU_Y(bitAboveNextItemY), MENU_Y(smallestSliderBar), MENU_Y(usableLineHeight), MENU_X(MENUSLIDER_UNK), value); \ @@ -447,8 +450,8 @@ CMenuManager::CheckCodesForControls(int typeOfControl) if (typeOfControl == KEYBOARD) { if (*pControlEdit == rsESC) { escPressed = true; - } else if (*pControlEdit > rsF3 && *pControlEdit != rsF9 && *pControlEdit != rsLWIN && - *pControlEdit != rsRWIN && *pControlEdit != rsRALT) { + } else if (*pControlEdit != rsF1 && *pControlEdit != rsF2 && *pControlEdit != rsF3 && *pControlEdit != rsF9 && + *pControlEdit != rsLWIN && *pControlEdit != rsRWIN && *pControlEdit != rsRALT) { typeToSave = KEYBOARD; if (ControlsManager.GetControllerKeyAssociatedWithAction(action, KEYBOARD) != rsNULL && *pControlEdit != ControlsManager.GetControllerKeyAssociatedWithAction(action, KEYBOARD)) { @@ -465,7 +468,10 @@ CMenuManager::CheckCodesForControls(int typeOfControl) DisplayComboButtonErrMsg = true; } - ControlsManager.ClearSettingsAssociatedWithAction(action, typeToSave); +#ifdef FIX_BUGS + if(!escPressed && !invalidKey) +#endif + ControlsManager.ClearSettingsAssociatedWithAction(action, typeToSave); if (!DisplayComboButtonErrMsg && !escPressed && !invalidKey) { if (typeOfControl == KEYBOARD) { ControlsManager.DeleteMatchingActionInitiators(action, *pControlEdit, KEYBOARD); @@ -670,6 +676,17 @@ CMenuManager::Draw() CFont::SetCentreOff(); CFont::SetJustifyOn(); CFont::SetBackGroundOnlyTextOn(); +#ifdef GTA3_1_1_PATCH + CFont::SetColor(CRGBA(235, 170, 50, FadeIn(255))); + CFont::SetRightJustifyOn(); + CFont::SetFontStyle(FONT_HEADING); + CFont::SetScale(MENU_X(0.7f), MENU_Y(0.5f)); + CFont::SetWrapx(SCREEN_WIDTH); + CFont::SetRightJustifyWrap(0.0f); + strcpy(gString, "V1.1"); + AsciiToUnicode(gString, gUString); + CFont::PrintString(SCREEN_WIDTH / 10, SCREEN_HEIGHT / 45, gUString); +#endif CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); @@ -696,17 +713,9 @@ CMenuManager::Draw() #endif if (aScreens[m_nCurrScreen].m_ScreenName[0] != '\0') { - CFont::SetRightJustifyOn(); - CFont::SetFontStyle(FONT_HEADING); -#ifdef PS2_LIKE_MENU - CFont::SetColor(CRGBA(0, 0, 0, 255)); - CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(1.3f)); - CFont::PrintString(MENU_X_RIGHT_ALIGNED(50.0f), SCREEN_SCALE_FROM_BOTTOM(75.0f), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); -#else - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); - CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); + PREPARE_MENU_HEADER CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); -#endif + // Weird place to put that. nextYToUse += 24.0f + 10.0f; } @@ -1735,11 +1744,8 @@ CMenuManager::DrawControllerSetupScreen() CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); - // Page header - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); - CFont::SetRightJustifyOn(); - CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); - CFont::SetFontStyle(FONT_HEADING); + PREPARE_MENU_HEADER + switch (m_ControlMethod) { case CONTROL_STANDARD: CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), @@ -2417,10 +2423,8 @@ CMenuManager::DrawPlayerSetupScreen() CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); CFont::SetRightJustifyWrap(SCREEN_SCALE_X(MENUACTION_WIDTH)); - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); - CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); - CFont::SetRightJustifyOn(); - CFont::SetFontStyle(FONT_HEADING); + PREPARE_MENU_HEADER + CFont::PrintString(SCREEN_SCALE_FROM_RIGHT(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get("FET_PS")); // lstrcpy's changed with strcpy @@ -3314,10 +3318,7 @@ CMenuManager::PrintStats() // ::Draw already does that. /* - CFont::SetColor(CRGBA(0, 0, 0, FadeIn(255))); - CFont::SetRightJustifyOn(); - CFont::SetFontStyle(FONT_HEADING); - CFont::SetScale(MENU_X(MENUHEADER_WIDTH), MENU_Y(MENUHEADER_HEIGHT)); + PREPARE_MENU_HEADER CFont::PrintString(MENU_X_RIGHT_ALIGNED(MENUHEADER_POS_X), SCREEN_SCALE_FROM_BOTTOM(MENUHEADER_POS_Y), TheText.Get(aScreens[m_nCurrScreen].m_ScreenName)); */ CFont::SetScale(MENU_X(MENU_TEXT_SIZE_X), MENU_Y(MENU_TEXT_SIZE_Y)); diff --git a/src/core/Frontend.h b/src/core/Frontend.h index 9064cf4e..8fe61a36 100644 --- a/src/core/Frontend.h +++ b/src/core/Frontend.h @@ -2,10 +2,16 @@ #include "Sprite2d.h" +#ifdef PS2_LIKE_MENU +#define MENUHEADER_POS_X 50.0f +#define MENUHEADER_POS_Y 75.0f +#define MENUHEADER_HEIGHT 1.3f +#else #define MENUHEADER_POS_X 35.0f #define MENUHEADER_POS_Y 93.0f -#define MENUHEADER_WIDTH 0.84f #define MENUHEADER_HEIGHT 1.6f +#endif +#define MENUHEADER_WIDTH 0.84f #define MENU_X_MARGIN 40.0f #define MENUACTION_POS_Y 60.0f diff --git a/src/core/World.cpp b/src/core/World.cpp index d64569b3..289be256 100644 --- a/src/core/World.cpp +++ b/src/core/World.cpp @@ -21,7 +21,7 @@ #include "Population.h" #include "Fire.h" -CColPoint *gaTempSphereColPoints = (CColPoint*)0x6E64C0; // [32] +CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; CPtrList *CWorld::ms_bigBuildingsList = (CPtrList*)0x6FAB60; CPtrList &CWorld::ms_listMovingEntityPtrs = *(CPtrList*)0x8F433C; @@ -29,7 +29,7 @@ CSector (*CWorld::ms_aSectors)[NUMSECTORS_X] = (CSector (*)[NUMSECTORS_Y])0x6656 uint16 &CWorld::ms_nCurrentScanCode = *(uint16*)0x95CC64; uint8 &CWorld::PlayerInFocus = *(uint8 *)0x95CD61; -CPlayerInfo (&CWorld::Players)[NUMPLAYERS] = *(CPlayerInfo (*)[NUMPLAYERS])*(uintptr*)0x9412F0; +CPlayerInfo CWorld::Players[NUMPLAYERS]; bool &CWorld::bNoMoreCollisionTorque = *(bool*)0x95CDCC; CEntity *&CWorld::pIgnoreEntity = *(CEntity**)0x8F6494; bool &CWorld::bIncludeDeadPeds = *(bool*)0x95CD8F; diff --git a/src/core/World.h b/src/core/World.h index 07e7889f..62fdc3b3 100644 --- a/src/core/World.h +++ b/src/core/World.h @@ -61,7 +61,7 @@ class CWorld public: static uint8 &PlayerInFocus; - static CPlayerInfo (&Players)[NUMPLAYERS]; + static CPlayerInfo Players[NUMPLAYERS]; static CEntity *&pIgnoreEntity; static bool &bIncludeDeadPeds; static bool &bNoMoreCollisionTorque; @@ -144,7 +144,7 @@ public: static void TriggerExplosion(const CVector &, float, float, CEntity*, bool); }; -extern CColPoint *gaTempSphereColPoints; +extern CColPoint gaTempSphereColPoints[MAX_COLLISION_POINTS]; class CPlayerPed; class CVehicle; diff --git a/src/core/main.cpp b/src/core/main.cpp index f09c2e0a..2d452f9c 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -690,14 +690,14 @@ DisplayGameDebugText() CFont::SetPropOn(); CFont::SetBackgroundOff(); CFont::SetFontStyle(FONT_BANK); - CFont::SetScale(SCREEN_STRETCH_X(0.5f), SCREEN_STRETCH_Y(0.5f)); + CFont::SetScale(SCREEN_SCALE_X(0.5f), SCREEN_SCALE_Y(0.5f)); CFont::SetCentreOff(); CFont::SetRightJustifyOff(); CFont::SetWrapx(SCREEN_WIDTH); CFont::SetJustifyOff(); CFont::SetBackGroundOnlyTextOff(); CFont::SetColor(CRGBA(255, 108, 0, 255)); - CFont::PrintString(10.0f, 10.0f, ver); + CFont::PrintString(SCREEN_SCALE_X(10.0f), SCREEN_SCALE_Y(10.0f), ver); FrameSamples++; FramesPerSecondCounter += 1000.0f / (CTimer::GetTimeStepNonClippedInSeconds() * 1000.0f); @@ -748,6 +748,7 @@ DisplayGameDebugText() AsciiToUnicode(str, ustr); + // Let's not scale those numbers, they look better that way :eyes: CFont::SetPropOff(); CFont::SetBackgroundOff(); CFont::SetScale(0.7f, 1.5f); diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index 9fc77a8c..72d6844d 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -1037,7 +1037,7 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) int numCollisions; int mostColliding; - CColPoint colpoints[32]; + CColPoint colpoints[MAX_COLLISION_POINTS]; CVector shift = { 0.0f, 0.0f, 0.0f }; bool doShift = false; CEntity *boat = nil; @@ -1187,7 +1187,7 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists) bool CPhysical::ProcessCollisionSectorList_SimpleCar(CPtrList *lists) { - static CColPoint aColPoints[32]; + static CColPoint aColPoints[MAX_COLLISION_POINTS]; float radius; CVector center; int listtype; @@ -1349,7 +1349,7 @@ collision: bool CPhysical::ProcessCollisionSectorList(CPtrList *lists) { - static CColPoint aColPoints[32]; + static CColPoint aColPoints[MAX_COLLISION_POINTS]; float radius; CVector center; CPtrList *list; diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index cee2b323..d6077ed8 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -62,7 +62,7 @@ CPed *gapTempPedList[50]; uint16 gnNumTempPedList; -CColPoint &aTempPedColPts = *(CColPoint*)0x62DB14; +CColPoint aTempPedColPts[MAX_COLLISION_POINTS]; // Corresponds to ped sounds (from SOUND_PED_DEATH to SOUND_PED_TAXI_CALL) PedAudioData CommentWaitTime[39] = { @@ -106,8 +106,6 @@ PedAudioData CommentWaitTime[39] = { {1000, 1000, 1000, 1000}, {1000, 1000, 5000, 5000}, }; -// *(CPedAudioData(*)[39]) * (uintptr*)0x5F94C4; - uint16 nPlayerInComboMove; RpClump *flyingClumpTemp; @@ -139,10 +137,9 @@ FightMove tFightMoves[NUM_FIGHTMOVES] = { {ANIM_HIT_BEHIND, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, {ANIM_FIGHT2_IDLE, 0.0f, 0.0f, 0.0f, 0.0f, HITLEVEL_NULL, 0, 0}, }; -// *(FightMove(*)[NUM_FIGHTMOVES])* (uintptr*)0x5F9844; -uint16 &CPed::nThreatReactionRangeMultiplier = *(uint16*)0x5F8C98; -uint16 &CPed::nEnterCarRangeMultiplier = *(uint16*)0x5F8C94; +uint16 CPed::nThreatReactionRangeMultiplier = 1; +uint16 CPed::nEnterCarRangeMultiplier = 1; CVector vecPedCarDoorAnimOffset; CVector vecPedCarDoorLoAnimOffset; @@ -151,9 +148,9 @@ CVector vecPedQuickDraggedOutCarAnimOffset; CVector vecPedDraggedOutCarAnimOffset; CVector vecPedTrainDoorAnimOffset; -bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44; -bool &CPed::bPedCheat2 = *(bool*)0x95CD5A; -bool &CPed::bPedCheat3 = *(bool*)0x95CD59; +bool CPed::bNastyLimbsCheat; +bool CPed::bPedCheat2; +bool CPed::bPedCheat3; CVector2D CPed::ms_vec2DFleePosition; void *CPed::operator new(size_t sz) { return CPools::GetPedPool()->New(); } @@ -4143,7 +4140,7 @@ CPed::SetGetUp(void) && ((CTimer::GetFrameCounter() + m_randomSeed % 256 + 5) % 8 || CCollision::ProcessColModels(GetMatrix(), *CModelInfo::GetModelInfo(m_modelIndex)->GetColModel(), collidingVeh->GetMatrix(), *CModelInfo::GetModelInfo(collidingVeh->m_modelIndex)->GetColModel(), - &aTempPedColPts, nil, nil) > 0)) { + aTempPedColPts, nil, nil) > 0)) { bGetUpAnimStarted = false; if (IsPlayer()) diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 2edd5d68..321d5bff 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -823,14 +823,14 @@ public: } // set by 0482:set_threat_reaction_range_multiplier opcode - static uint16 &nThreatReactionRangeMultiplier; + static uint16 nThreatReactionRangeMultiplier; // set by 0481:set_enter_car_range_multiplier opcode - static uint16 &nEnterCarRangeMultiplier; + static uint16 nEnterCarRangeMultiplier; - static bool &bNastyLimbsCheat; - static bool &bPedCheat2; - static bool &bPedCheat3; + static bool bNastyLimbsCheat; + static bool bPedCheat2; + static bool bPedCheat3; static CVector2D ms_vec2DFleePosition; #ifdef TOGGLEABLE_BETA_FEATURES diff --git a/src/peds/Population.cpp b/src/peds/Population.cpp index 6959487f..e26e2eaf 100644 --- a/src/peds/Population.cpp +++ b/src/peds/Population.cpp @@ -47,36 +47,36 @@ const RegenerationPoint aSafeZones[] = { CVector(-321.0f, -1043.0f, -13.2f), CVector(-328.0f, -1045.0f, -13.2f), CVector(-398.0f, -1044.0f, -13.5f), CVector(-390.0f, -1040.5f, -13.5f) }, { LEVEL_COMMERCIAL, LEVEL_SUBURBAN, 425.0f, 280.0f, 471.0f, 447.0f, 20.0f, 5.0f, CVector(-292.0f, -457.0f, -11.6f), CVector(-310.0f, -461.0f, -11.6f), CVector(-413.0f, -461.0f, -11.5f), CVector(-399.0f, -457.0f, -11.3f) } -}; // *(RegenerationPoint(*)[8]) * (uintptr*)0x5FA578; +}; -PedGroup CPopulation::ms_pPedGroups[NUMPEDGROUPS]; // = *(PedGroup(*)[NUMPEDGROUPS]) * (uintptr*)0x6E9248; -bool CPopulation::ms_bGivePedsWeapons; // = *(bool*)0x95CCF6; -int32 CPopulation::m_AllRandomPedsThisType = -1; // = *(int32*)0x5FA570; -float CPopulation::PedDensityMultiplier = 1.0f; // = *(float*)0x5FA56C; -uint32 CPopulation::ms_nTotalMissionPeds; // = *(uint32*)0x8F5F70; -int32 CPopulation::MaxNumberOfPedsInUse = 25; // *(int32*)0x5FA574; -uint32 CPopulation::ms_nNumCivMale; // = *(uint32*)0x8F2548; -uint32 CPopulation::ms_nNumCivFemale; // = *(uint32*)0x8F5F44; -uint32 CPopulation::ms_nNumCop; // = *(uint32*)0x885AFC; -bool CPopulation::bZoneChangeHasHappened; // = *(bool*)0x95CD79; -uint32 CPopulation::ms_nNumEmergency; // = *(uint32*)0x94071C; -int8 CPopulation::m_CountDownToPedsAtStart; // = *(int8*)0x95CD4F; -uint32 CPopulation::ms_nNumGang1; // = *(uint32*)0x8F1B1C; -uint32 CPopulation::ms_nNumGang2; // = *(uint32*)0x8F1B14; -uint32 CPopulation::ms_nTotalPeds; // = *(uint32*)0x95CB50; -uint32 CPopulation::ms_nNumGang3; // = *(uint32*)0x8F2548; -uint32 CPopulation::ms_nTotalGangPeds; // = *(uint32*)0x885AF0; -uint32 CPopulation::ms_nNumGang4; // = *(uint32*)0x8F1B2C; -uint32 CPopulation::ms_nTotalCivPeds; // = *(uint32*)0x8F2C3C; -uint32 CPopulation::ms_nNumGang5; // = *(uint32*)0x8F1B30; -uint32 CPopulation::ms_nNumDummy; // = *(uint32*)0x8F1A98; -uint32 CPopulation::ms_nNumGang6; // = *(uint32*)0x8F1B20; -uint32 CPopulation::ms_nNumGang9; // = *(uint32*)0x8F1B10; -uint32 CPopulation::ms_nNumGang7; // = *(uint32*)0x8F1B28; -uint32 CPopulation::ms_nNumGang8; // = *(uint32*)0x8F1B0C; -CVector CPopulation::RegenerationPoint_a; // = *(CVector*)0x8E2AA4; -CVector CPopulation::RegenerationPoint_b; // = *(CVector*)0x8E2A98; -CVector CPopulation::RegenerationForward; // = *(CVector*)0x8F1AD4; +PedGroup CPopulation::ms_pPedGroups[NUMPEDGROUPS]; +bool CPopulation::ms_bGivePedsWeapons; +int32 CPopulation::m_AllRandomPedsThisType = -1; +float CPopulation::PedDensityMultiplier = 1.0f; +uint32 CPopulation::ms_nTotalMissionPeds; +int32 CPopulation::MaxNumberOfPedsInUse = 25; +uint32 CPopulation::ms_nNumCivMale; +uint32 CPopulation::ms_nNumCivFemale; +uint32 CPopulation::ms_nNumCop; +bool CPopulation::bZoneChangeHasHappened; +uint32 CPopulation::ms_nNumEmergency; +int8 CPopulation::m_CountDownToPedsAtStart; +uint32 CPopulation::ms_nNumGang1; +uint32 CPopulation::ms_nNumGang2; +uint32 CPopulation::ms_nTotalPeds; +uint32 CPopulation::ms_nNumGang3; +uint32 CPopulation::ms_nTotalGangPeds; +uint32 CPopulation::ms_nNumGang4; +uint32 CPopulation::ms_nTotalCivPeds; +uint32 CPopulation::ms_nNumGang5; +uint32 CPopulation::ms_nNumDummy; +uint32 CPopulation::ms_nNumGang6; +uint32 CPopulation::ms_nNumGang9; +uint32 CPopulation::ms_nNumGang7; +uint32 CPopulation::ms_nNumGang8; +CVector CPopulation::RegenerationPoint_a; +CVector CPopulation::RegenerationPoint_b; +CVector CPopulation::RegenerationForward; void CPopulation::Initialise() diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index d7834065..7b2f90e8 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -39,16 +39,17 @@ struct EntityInfo float sort; }; -CLinkList &gSortedVehiclesAndPeds = *(CLinkList*)0x629AC0; +CLinkList gSortedVehiclesAndPeds; -int32 &CRenderer::ms_nNoOfVisibleEntities = *(int32*)0x940730; -CEntity *(&CRenderer::ms_aVisibleEntityPtrs)[NUMVISIBLEENTITIES] = *(CEntity * (*)[NUMVISIBLEENTITIES]) * (uintptr*)0x6E9920; -CEntity *(&CRenderer::ms_aInVisibleEntityPtrs)[NUMINVISIBLEENTITIES] = *(CEntity * (*)[NUMINVISIBLEENTITIES]) * (uintptr*)0x880B50; -int32 &CRenderer::ms_nNoOfInVisibleEntities = *(int32*)0x8F1B78; +int32 CRenderer::ms_nNoOfVisibleEntities; +CEntity *CRenderer::ms_aVisibleEntityPtrs[NUMVISIBLEENTITIES]; +CEntity *CRenderer::ms_aInVisibleEntityPtrs[NUMINVISIBLEENTITIES]; +int32 CRenderer::ms_nNoOfInVisibleEntities; -CVector &CRenderer::ms_vecCameraPosition = *(CVector*)0x8E2C3C; -CVehicle *&CRenderer::m_pFirstPersonVehicle = *(CVehicle**)0x885B80; -bool &CRenderer::m_loadingPriority = *(bool*)0x95CD86; +CVector CRenderer::ms_vecCameraPosition; +CVehicle *CRenderer::m_pFirstPersonVehicle; +bool CRenderer::m_loadingPriority; +float CRenderer::ms_lodDistScale = 1.2f; void CRenderer::Init(void) diff --git a/src/render/Renderer.h b/src/render/Renderer.h index 42c154ec..362741e3 100644 --- a/src/render/Renderer.h +++ b/src/render/Renderer.h @@ -20,17 +20,17 @@ class CPtrList; class CRenderer { - static int32 &ms_nNoOfVisibleEntities; - static CEntity *(&ms_aVisibleEntityPtrs)[NUMVISIBLEENTITIES]; - static int32 &ms_nNoOfInVisibleEntities; - static CEntity *(&ms_aInVisibleEntityPtrs)[NUMINVISIBLEENTITIES]; + static int32 ms_nNoOfVisibleEntities; + static CEntity *ms_aVisibleEntityPtrs[NUMVISIBLEENTITIES]; + static int32 ms_nNoOfInVisibleEntities; + static CEntity *ms_aInVisibleEntityPtrs[NUMINVISIBLEENTITIES]; - static CVector &ms_vecCameraPosition; - static CVehicle *&m_pFirstPersonVehicle; + static CVector ms_vecCameraPosition; + static CVehicle *m_pFirstPersonVehicle; public: - static float ms_lodDistScale; // defined in Frontend.cpp - static bool &m_loadingPriority; + static float ms_lodDistScale; + static bool m_loadingPriority; static void Init(void); static void Shutdown(void); diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 257c8d33..2a325b3d 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -356,7 +356,7 @@ CAutomobile::ProcessControl(void) PruneReferences(); - if(m_status == STATUS_PLAYER && CRecordDataForChase::IsRecording()) + if(m_status == STATUS_PLAYER && !CRecordDataForChase::IsRecording()) DoDriveByShootings(); } break; @@ -4206,8 +4206,7 @@ GetCurrentAtomicObjectCB(RwObject *object, void *data) return object; } -CColPoint aTempPedColPts[32]; // this name doesn't make any sense - // they probably copied it from Ped (both serves same purpose) and didn't change the name +CColPoint spherepoints[MAX_COLLISION_POINTS]; CObject* CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) @@ -4327,7 +4326,7 @@ CAutomobile::SpawnFlyingComponent(int32 component, uint32 type) if(CCollision::ProcessColModels(obj->GetMatrix(), *obj->GetColModel(), this->GetMatrix(), *this->GetColModel(), - aTempPedColPts, nil, nil) > 0) + spherepoints, nil, nil) > 0) obj->m_pCollidingEntity = this; if(bRenderScorched) diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index f47fd131..ed8f4221 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -19,12 +19,12 @@ #include "Fire.h" #include "Darkel.h" -bool &CVehicle::bWheelsOnlyCheat = *(bool *)0x95CD78; -bool &CVehicle::bAllDodosCheat = *(bool *)0x95CD75; -bool &CVehicle::bCheat3 = *(bool *)0x95CD66; -bool &CVehicle::bCheat4 = *(bool *)0x95CD65; -bool &CVehicle::bCheat5 = *(bool *)0x95CD64; -bool &CVehicle::m_bDisableMouseSteering = *(bool *)0x60252C; +bool CVehicle::bWheelsOnlyCheat; +bool CVehicle::bAllDodosCheat; +bool CVehicle::bCheat3; +bool CVehicle::bCheat4; +bool CVehicle::bCheat5; +bool CVehicle::m_bDisableMouseSteering; void *CVehicle::operator new(size_t sz) { return CPools::GetVehiclePool()->New(); } void *CVehicle::operator new(size_t sz, int handle) { return CPools::GetVehiclePool()->New(handle); } diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index f9becda0..bfc6d95d 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -277,12 +277,12 @@ public: bool IsTaxi(void) { return GetModelIndex() == MI_TAXI || GetModelIndex() == MI_CABBIE || GetModelIndex() == MI_BORGNINE; } AnimationId GetDriverAnim(void) { return IsCar() && bLowVehicle ? ANIM_CAR_LSIT : (IsBoat() && GetModelIndex() != MI_SPEEDER ? ANIM_DRIVE_BOAT : ANIM_CAR_SIT); } - static bool &bWheelsOnlyCheat; - static bool &bAllDodosCheat; - static bool &bCheat3; - static bool &bCheat4; - static bool &bCheat5; - static bool &m_bDisableMouseSteering; + static bool bWheelsOnlyCheat; + static bool bAllDodosCheat; + static bool bCheat3; + static bool bCheat4; + static bool bCheat5; + static bool m_bDisableMouseSteering; }; static_assert(sizeof(CVehicle) == 0x288, "CVehicle: error"); From 01d18e8f28d3de5b22a688fffe57ace1c98fd714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Wed, 15 Apr 2020 19:37:41 +0300 Subject: [PATCH 12/18] Readme update --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index c7d83212..53f2136a 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,6 @@ to reverse at the time, calling the original functions is acceptable. ### Unreversed / incomplete classes (at least the ones we know) ``` CBulletInfo -CPedPath CWeapon CWorld ``` From 85fe445fef1a20a0b5bc74f30bc3fd14418efb3d Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Wed, 15 Apr 2020 19:43:16 +0300 Subject: [PATCH 13/18] weapon cosmetic fix --- src/weapons/Weapon.cpp | 967 +++++++++++++++++++++-------------------- 1 file changed, 484 insertions(+), 483 deletions(-) diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 28031847..b0c9b61f 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -32,26 +32,28 @@ uint16 gReloadSampleTime[WEAPONTYPE_TOTAL_INVENTORY_WEAPONS] = { - /*UNARMED*/ 0, - /*BASEBALLBAT*/ 0, - /*COLT45*/ 250, - /*UZI*/ 400, - /*SHOTGUN*/ 650, - /*AK47*/ 300, - /*M16*/ 300, - /*SNIPERRIFLE*/ 423, - /*ROCKETLAUNCHER*/ 400, - /*FLAMETHROWER*/ 0, - /*MOLOTOV*/ 0, - /*GRENADE*/ 0, - /*DETONATOR*/ 0 + 0, // UNARMED + 0, // BASEBALLBAT + 250, // COLT45 + 400, // UZI + 650, // SHOTGUN + 300, // AK47 + 300, // M16 + 423, // SNIPERRIFLE + 400, // ROCKETLAUNCHER + 0, // FLAMETHROWER + 0, // MOLOTOV + 0, // GRENADE + 0, // DETONATOR + + 0 // WEAPONTYPE_HELICANNON }; CWeaponInfo * CWeapon::GetInfo() { CWeaponInfo *info = CWeaponInfo::GetWeaponInfo(m_eWeaponType); - ASSERT(info!=NULL); + ASSERT(info!=nil); return info; } @@ -101,14 +103,14 @@ CWeapon::Initialise(eWeaponType type, int32 ammo) bool CWeapon::Fire(CEntity *shooter, CVector *fireSource) { - ASSERT(shooter!=NULL); - + ASSERT(shooter!=nil); + CVector fireOffset(0.0f, 0.0f, 0.6f); CVector *source = fireSource; - + if ( !fireSource ) source = &(shooter->GetMatrix() * fireOffset); - + if ( m_bAddRotOffset ) { float heading = RADTODEG(shooter->GetForward().Heading()); @@ -116,58 +118,58 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) (*source).x += -Sin(angle) * 0.15f; (*source).y += Cos(angle) * 0.15f; } - + if ( m_eWeaponState != WEAPONSTATE_READY && m_eWeaponState != WEAPONSTATE_FIRING ) return false; bool fired; - + if ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE ) { if ( m_nAmmoInClip <= 0 ) return false; - + switch ( m_eWeaponType ) { case WEAPONTYPE_SHOTGUN: { fired = FireShotgun(shooter, source); - + break; } - + case WEAPONTYPE_COLT45: case WEAPONTYPE_UZI: case WEAPONTYPE_AK47: { fired = FireInstantHit(shooter, source); - + break; } - + case WEAPONTYPE_SNIPERRIFLE: { fired = FireSniper(shooter); - + break; } - + case WEAPONTYPE_M16: { if ( TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON && shooter == FindPlayerPed() ) fired = FireM16_1stPerson(shooter); else fired = FireInstantHit(shooter, source); - + break; } - + case WEAPONTYPE_ROCKETLAUNCHER: { - if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != NULL ) + if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != nil ) { float distToTarget = (shooter->GetPosition() - ((CPed*)shooter)->m_pSeekTarget->GetPosition()).Magnitude(); - + if ( distToTarget > 8.0f || ((CPed*)shooter)->IsPlayer() ) fired = FireProjectile(shooter, source, 0.0f); else @@ -175,10 +177,10 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) } else fired = FireProjectile(shooter, source, 0.0f); - + break; } - + case WEAPONTYPE_MOLOTOV: case WEAPONTYPE_GRENADE: { @@ -188,81 +190,81 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) if ( m_eWeaponType == WEAPONTYPE_GRENADE ) CStats::KgsOfExplosivesUsed++; } - else if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != NULL ) + else if ( shooter->IsPed() && ((CPed*)shooter)->m_pSeekTarget != nil ) { float distToTarget = (shooter->GetPosition() - ((CPed*)shooter)->m_pSeekTarget->GetPosition()).Magnitude(); float power = clamp((distToTarget-10.0f)*0.02f, 0.2f, 1.0f); - + fired = FireProjectile(shooter, source, power); } else fired = FireProjectile(shooter, source, 0.3f); - + break; } - + case WEAPONTYPE_FLAMETHROWER: { fired = FireAreaEffect(shooter, source); - + break; } - + case WEAPONTYPE_DETONATOR: { CWorld::UseDetonator(shooter); m_nAmmoTotal = 1; m_nAmmoInClip = m_nAmmoTotal; fired = true; - + break; } - + case WEAPONTYPE_HELICANNON: { if ( (TheCamera.PlayerWeaponMode.Mode == CCam::MODE_HELICANNON_1STPERSON || TheCamera.PlayerWeaponMode.Mode == CCam::MODE_M16_1STPERSON ) && shooter == FindPlayerPed() ) { fired = FireM16_1stPerson(shooter); - } + } else fired = FireInstantHit(shooter, source); - + break; } - + default: { debug("Unknown weapon type, Weapon.cpp"); break; } } - + if ( fired ) { bool isPlayer = false; - + if ( shooter->IsPed() ) { CPed *shooterPed = (CPed*)shooter; - + shooterPed->bIsShooting = true; - + if ( shooterPed->IsPlayer() ) isPlayer = true; - + DMAudio.PlayOneShot(shooterPed->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); } - + if ( m_nAmmoInClip > 0 ) m_nAmmoInClip--; if ( m_nAmmoTotal > 0 && (m_nAmmoTotal < 25000 || isPlayer) ) m_nAmmoTotal--; - + if ( m_eWeaponState == WEAPONSTATE_READY && m_eWeaponType == WEAPONTYPE_FLAMETHROWER ) DMAudio.PlayOneShot(((CPhysical*)shooter)->m_audioEntityId, SOUND_WEAPON_FLAMETHROWER_FIRE, 0.0f); - + m_eWeaponState = WEAPONSTATE_FIRING; } - + if ( m_nAmmoInClip == 0 ) { if ( m_nAmmoTotal == 0 ) @@ -270,16 +272,16 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) m_eWeaponState = WEAPONSTATE_RELOADING; m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; - + if ( shooter == FindPlayerPed() ) { if ( CWorld::Players[CWorld::PlayerInFocus].m_bFastReload ) m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload / 4; } - + return true; } - + m_nTimer = CTimer::GetTimeInMilliseconds() + 1000; if ( shooter == FindPlayerPed() ) CStats::RoundsFiredByPlayer++; @@ -291,10 +293,10 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; m_eWeaponState = WEAPONSTATE_FIRING; } - + FireMelee(shooter, *source); } - + if ( m_eWeaponType == WEAPONTYPE_UNARMED || m_eWeaponType == WEAPONTYPE_BASEBALLBAT ) return true; else @@ -304,23 +306,23 @@ CWeapon::Fire(CEntity *shooter, CVector *fireSource) bool CWeapon::FireFromCar(CAutomobile *shooter, bool left) { - ASSERT(shooter!=NULL); - + ASSERT(shooter!=nil); + if ( m_eWeaponState != WEAPONSTATE_READY && m_eWeaponState != WEAPONSTATE_FIRING ) return false; - + if ( m_nAmmoInClip <= 0 ) return false; - + if ( FireInstantHitFromCar(shooter, left) ) { DMAudio.PlayOneShot(shooter->m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f); - + if ( m_nAmmoInClip > 0 ) m_nAmmoInClip--; if ( m_nAmmoTotal < 25000 && m_nAmmoTotal > 0 ) m_nAmmoTotal--; - + m_eWeaponState = WEAPONSTATE_FIRING; - + if ( m_nAmmoInClip == 0 ) { if ( m_nAmmoTotal == 0 ) @@ -328,49 +330,48 @@ CWeapon::FireFromCar(CAutomobile *shooter, bool left) m_eWeaponState = WEAPONSTATE_RELOADING; m_nTimer = CTimer::GetTimeInMilliseconds() + GetInfo()->m_nReload; - + return true; } - + m_nTimer = CTimer::GetTimeInMilliseconds() + 1000; if ( shooter == FindPlayerVehicle() ) CStats::RoundsFiredByPlayer++; } - + return true; } bool CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) { - ASSERT(shooter!=NULL); - + ASSERT(shooter!=nil); + CWeaponInfo *info = GetInfo(); - + bool anim2Playing = false; if ( RpAnimBlendClumpGetAssociation(shooter->GetClump(), info->m_Anim2ToPlay) ) anim2Playing = true; - + ASSERT(shooter->IsPed()); - + CPed *shooterPed = (CPed*)shooter; - + for ( int32 i = 0; i < shooterPed->m_numNearPeds; i++ ) { CPed *victimPed = shooterPed->m_nearPeds[i]; - ASSERT(victimPed!=NULL); - + ASSERT(victimPed!=nil); + if ( (victimPed->m_nPedType != shooterPed->m_nPedType || victimPed == shooterPed->m_pSeekTarget) && victimPed != shooterPed->m_leader || !(CGeneral::GetRandomNumber() & 31) ) { bool collided = false; - + CColModel *victimPedCol = &CTempColModels::ms_colModelPed1; if ( victimPed->OnGround() || !victimPed->IsPedHeadAbovePos(-0.3f) ) victimPedCol = &CTempColModels::ms_colModelPedGroundHit; - - ASSERT(victimPedCol!=NULL); - + + float victimPedRadius = victimPed->GetBoundRadius() + info->m_fRadius; if ( victimPed->bUsesCollision || victimPed->Dead() || victimPed->Driving() ) { @@ -378,13 +379,13 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) if ( SQR(victimPedRadius) > (victimPedPos-(*fireSource)).MagnitudeSqr() ) { CVector collisionDist; - + int32 s = 0; while ( s < victimPedCol->numSpheres ) { CColSphere *sphere = &victimPedCol->spheres[s]; collisionDist = victimPedPos+sphere->center-(*fireSource); - + if ( SQR(sphere->radius + info->m_fRadius) > collisionDist.MagnitudeSqr() ) { collided = true; @@ -392,29 +393,29 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) } s++; } - + if ( !(victimPed->IsPlayer() && victimPed->GetPedState() == PED_GETUP) ) { if ( collided ) { float victimPedHealth = victimPed->m_fHealth; - CVector bloodPos = fireSource + collisionDist*0.7f; - + CVector bloodPos = fireSource + (collisionDist*0.7f); + CVector2D posOffset(shooterPed->GetPosition().x-victimPedPos.x, shooterPed->GetPosition().y-victimPedPos.y); - + int32 localDir = victimPed->GetLocalDirection(posOffset); - + bool isBat = m_eWeaponType == WEAPONTYPE_BASEBALLBAT; - + if ( !victimPed->DyingOrDead() ) victimPed->ReactToAttack(shooterPed); - + uint8 hitLevel = HITLEVEL_HIGH; if ( isBat && victimPed->OnGround() ) hitLevel = HITLEVEL_GROUND; - + victimPed->StartFightDefend(localDir, hitLevel, 10); - + if ( !victimPed->DyingOrDead() ) { if ( shooterPed->IsPlayer() && isBat && anim2Playing ) @@ -429,30 +430,30 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) victimPed->InflictDamage(shooterPed, m_eWeaponType, info->m_nDamage, PEDPIECE_TORSO, localDir); } } - + if ( CGame::nastyGame ) { if ( victimPed->GetIsOnScreen() ) { CVector dir = collisionDist * RecipSqrt(1.0f, 10.0f*collisionDist.MagnitudeSqr()); - + CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); - + if ( isBat ) { dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); - + dir.x += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); dir.y += CGeneral::GetRandomNumberInRange(-0.05f, 0.05f); CParticle::AddParticle(PARTICLE_BLOOD, bloodPos, dir); } } } - + if ( !victimPed->OnGround() ) { if ( victimPed->m_fHealth > 0.0f @@ -461,12 +462,12 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) posOffset.Normalise(); victimPed->bIsStanding = false; victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); - + if ( isBat && victimPed->IsPlayer() ) victimPed->SetFall(3000, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); else victimPed->SetFall(1500, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); - + shooterPed->m_pSeekTarget = victimPed; shooterPed->m_pSeekTarget->RegisterReference(&shooterPed->m_pSeekTarget); } @@ -477,9 +478,9 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) victimPed->bIsStanding = false; victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 3.0f); } - + m_eWeaponState = WEAPONSTATE_MELEE_MADECONTACT; - + if ( victimPed->m_nPedType == PEDTYPE_COP ) CEventList::RegisterEvent(EVENT_ASSAULT_POLICE, EVENT_ENTITY_PED, victimPed, shooterPed, 2000); else @@ -490,39 +491,39 @@ CWeapon::FireMelee(CEntity *shooter, CVector &fireSource) } } } - + return true; } bool CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) { - ASSERT(shooter!=NULL); - ASSERT(fireSource!=NULL); - + ASSERT(shooter!=nil); + ASSERT(fireSource!=nil); + CWeaponInfo *info = GetInfo(); - + CVector source, target; CColPoint point; - CEntity *victim = NULL; - + CEntity *victim = nil; + float heading = RADTODEG(shooter->GetForward().Heading()); float angle = DEGTORAD(heading); - + CVector2D ahead(-Sin(angle), Cos(angle)); ahead.Normalise(); - + CVector vel = ((CPed *)shooter)->m_vecMoveSpeed; int32 shooterMoving = false; if ( Abs(vel.x) > 0.0f && Abs(vel.y) > 0.0f ) shooterMoving = true; - + if ( shooter == FindPlayerPed() ) { static float prev_heading = 0.0f; prev_heading = ((CPed*)shooter)->m_fRotationCur; } - + if ( shooter->IsPed() && ((CPed *)shooter)->m_pPointGunAt ) { CPed *shooterPed = (CPed *)shooter; @@ -530,10 +531,10 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) { int32 accuracy = shooterPed->m_wepAccuracy; int32 inaccuracy = 100-accuracy; - + if ( accuracy != 100 ) FindPlayerPed(); //what ? - + CPed *threatAttack = (CPed*)shooterPed->m_pPointGunAt; if ( threatAttack->IsPed() ) { @@ -542,18 +543,18 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) } else target = threatAttack->GetPosition(); - + target -= *fireSource; target *= info->m_fRange / target.Magnitude(); target += *fireSource; - + if ( inaccuracy != 0 ) { target.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracy; target.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f) * inaccuracy; target.z += CGeneral::GetRandomNumberInRange(-0.1f, 0.1f) * inaccuracy; } - + CWorld::bIncludeDeadPeds = true; ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); CWorld::bIncludeDeadPeds = false; @@ -563,10 +564,10 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) target.x = info->m_fRange; target.y = 0.0f; target.z = 0.0f; - + for (RwFrame *i = shooterPed->GetNodeFrame(PED_HANDR); i; i = RwFrameGetParent(i)) RwV3dTransformPoints(target, target, 1, RwFrameGetMatrix(i)); - + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); } } @@ -574,270 +575,270 @@ CWeapon::FireInstantHit(CEntity *shooter, CVector *fireSource) { CVector src, trgt; TheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, src, trgt); - + CWorld::bIncludeDeadPeds = true; ProcessLineOfSight(src, trgt,point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); CWorld::bIncludeDeadPeds = false; - + int32 rotSpeed = 1; if ( m_eWeaponType == WEAPONTYPE_M16 ) rotSpeed = 4; - + CVector bulletPos; if ( CHeli::TestBulletCollision(&src, &trgt, &bulletPos, 4) ) { for ( int32 i = 0; i < 16; i++ ) - CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f, rotSpeed); + CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, rotSpeed); } } else { float shooterHeading = RADTODEG(shooter->GetForward().Heading()); float shooterAngle = DEGTORAD(shooterHeading); - + CVector2D rotOffset(-Sin(shooterAngle), Cos(shooterAngle)); rotOffset.Normalise(); - + target = *fireSource; target.x = rotOffset.x * info->m_fRange; target.y = rotOffset.y * info->m_fRange; - + if ( shooter->IsPed() ) DoDoomAiming(shooter, fireSource, &target); - + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); - + int32 rotSpeed = 1; if ( m_eWeaponType == WEAPONTYPE_M16 ) rotSpeed = 4; - + CVector bulletPos; if ( CHeli::TestBulletCollision(fireSource, &target, &bulletPos, 4) ) { for ( int32 i = 0; i < 16; i++ ) - CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f, rotSpeed); + CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f, rotSpeed); } } - + if ( victim && shooter->IsPed() && victim == ((CPed*)shooter)->m_leader ) return false; CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed *)shooter, 1000); - + if ( shooter == FindPlayerPed() ) { CStats::InstantHitsFiredByPlayer++; if ( !(CTimer::GetFrameCounter() & 3) ) MakePedsJumpAtShot((CPhysical*)shooter, fireSource, &target); } - + switch ( m_eWeaponType ) { case WEAPONTYPE_AK47: { static uint8 counter = 0; - + if ( !(++counter & 1) ) { CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - + CVector gunflashPos = *fireSource; gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.10f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.10f); gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.08f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.08f); gunflashPos += CVector(0.05f*ahead.x, 0.05f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); + CVector gunsmokePos = *fireSource; float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f)); - + CVector gunshellPos = *fireSource; gunshellPos -= CVector(0.5f*ahead.x, 0.5f*ahead.y, 0.0f); CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); dir.Normalise2D(); AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.018f); } - + break; } - + case WEAPONTYPE_M16: { static uint8 counter = 0; - + if ( !(++counter & 1) ) { CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - + CVector gunflashPos = *fireSource; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.08f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.08f); gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); + gunflashPos = *fireSource; gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); gunflashPos.z += 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); gunflashPos.z += 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); gunflashPos.z += 0.03f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + gunflashPos = *fireSource; gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); gunflashPos.z -= 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); gunflashPos.z -= 0.04f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); gunflashPos.z -= 0.03f; - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + CVector offset = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); offset.Normalise2D(); - + gunflashPos = *fireSource; gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); gunflashPos += CVector(0.06f*offset.x, 0.06f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); gunflashPos += CVector(0.04f*offset.x, 0.04f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); gunflashPos += CVector(0.03f*offset.x, 0.03f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + gunflashPos = *fireSource; gunflashPos += CVector(-0.1f*ahead.x, -0.1f*ahead.y, 0.0f); gunflashPos -= CVector(0.06f*offset.x, 0.06f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); gunflashPos -= CVector(0.04f*offset.x, 0.04f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); gunflashPos -= CVector(0.03f*offset.x, 0.03f*offset.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + CVector gunsmokePos = *fireSource; float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f)); - + CVector gunshellPos = *fireSource; gunshellPos -= CVector(0.65f*ahead.x, 0.65f*ahead.y, 0.0f); CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); dir.Normalise2D(); AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.02f); } - + break; } - + case WEAPONTYPE_UZI: { CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - + CVector gunflashPos = *fireSource; - + if ( shooterMoving ) gunflashPos += CVector(1.5f*vel.x, 1.5f*vel.y, 0.0f); - - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.07f); + + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.07f); gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.05f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.05f); gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); gunflashPos += CVector(0.03f*ahead.x, 0.03f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.03f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.03f); gunflashPos += CVector(0.03f*ahead.x, 0.03f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); gunflashPos += CVector(0.02f*ahead.x, 0.02f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.01f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.01f); + CVector gunsmokePos = *fireSource; float rnd = CGeneral::GetRandomNumberInRange(0.05f, 0.25f); CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*rnd, ahead.y*rnd, 0.0f)); - + CVector gunshellPos = *fireSource; gunshellPos -= CVector(0.2f*ahead.x, 0.2f*ahead.y, 0.0f); CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); dir.Normalise2D(); AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.015f); - + break; } - + case WEAPONTYPE_COLT45: { CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0f, 0.0f, 0.0f), 5.0f, 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - + CVector gunflashPos = *fireSource; - + if ( shooterMoving ) gunflashPos += CVector(1.5f*vel.x, 1.5f*vel.y, 0.0f); - - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.06f); + + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.06f); gunflashPos += CVector(0.06f*ahead.x, 0.06f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.04f); + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.04f); gunflashPos += CVector(0.04f*ahead.x, 0.04f*ahead.y, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.02f); - + CParticle::AddParticle(PARTICLE_GUNFLASH_NOANIM, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.02f); + CVector gunsmokePos = *fireSource; - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.10f, ahead.y*0.10f, 0.0f), NULL, 0.005f); - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.15f, ahead.y*0.15f, 0.0f), NULL, 0.015f); - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.20f, ahead.y*0.20f, 0.0f), NULL, 0.025f); - + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.10f, ahead.y*0.10f, 0.0f), nil, 0.005f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.15f, ahead.y*0.15f, 0.0f), nil, 0.015f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(ahead.x*0.20f, ahead.y*0.20f, 0.0f), nil, 0.025f); + CVector gunshellPos = *fireSource; gunshellPos -= CVector(0.2f*ahead.x, 0.2f*ahead.y, 0.0f); CVector dir = CrossProduct(CVector(ahead.x, ahead.y, 0.0f), CVector(0.0f, 0.0f, 5.0f)); dir.Normalise2D(); AddGunshell(shooter, gunshellPos, CVector2D(dir.x, dir.y), 0.015f); - + break; } } - + DoBulletImpact(shooter, victim, fireSource, &target, &point, ahead); - + return true; } void CWeapon::AddGunshell(CEntity *shooter, CVector const &source, CVector2D const &direction, float size) { - ASSERT(shooter!=NULL); - - if ( shooter == NULL) + ASSERT(shooter!=nil); + + if ( shooter == nil) return; - + CVector dir(direction.x*0.05f, direction.y*0.05f, CGeneral::GetRandomNumberInRange(0.02f, 0.08f)); - + static CVector prevEntityPosition(0.0f, 0.0f, 0.0f); CVector entityPosition = shooter->GetPosition(); - + CVector diff = entityPosition - prevEntityPosition; - + if ( Abs(diff.x)+Abs(diff.y)+Abs(diff.z) > 1.5f ) { prevEntityPosition = entityPosition; - + CParticle::AddParticle(PARTICLE_GUNSHELL_FIRST, - source, dir, NULL, size, CGeneral::GetRandomNumberInRange(-20.0f, 20.0f)); + source, dir, nil, size, CGeneral::GetRandomNumberInRange(-20.0f, 20.0f)); } else { CParticle::AddParticle(PARTICLE_GUNSHELL, - source, dir, NULL, size, CGeneral::GetRandomNumberInRange(-20.0f, 20.0f)); + source, dir, nil, size, CGeneral::GetRandomNumberInRange(-20.0f, 20.0f)); } } @@ -845,21 +846,21 @@ void CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, CVector *source, CVector *target, CColPoint *point, CVector2D ahead) { - ASSERT(shooter!=NULL); - ASSERT(source!=NULL); - ASSERT(target!=NULL); - ASSERT(point!=NULL); - + ASSERT(shooter!=nil); + ASSERT(source!=nil); + ASSERT(target!=nil); + ASSERT(point!=nil); + CWeaponInfo *info = GetInfo(); - + if ( victim ) { CGlass::WasGlassHitByBullet(victim, point->point); - + CVector traceTarget = *target; CBulletTraces::AddTrace(source, &traceTarget); - - if ( shooter != NULL ) + + if ( shooter != nil ) { if ( shooter == FindPlayerPed() ) { @@ -867,7 +868,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, CStats::InstantHitsHitByPlayer++; } } - + if ( victim->IsPed() && ((CPed*)shooter)->m_nPedType != ((CPed*)victim)->m_nPedType || ((CPed*)shooter)->m_nPedType == PEDTYPE_PLAYER2 ) { CPed *victimPed = (CPed *)victim; @@ -876,12 +877,12 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, if ( victimPed->DoesLOSBulletHitPed(*point) ) { CVector pos = victimPed->GetPosition(); - + CVector2D posOffset(source->x-pos.x, source->y-pos.y); int32 localDir = victimPed->GetLocalDirection(posOffset); - + victimPed->ReactToAttack(shooter); - + if ( !victimPed->IsPedInControl() || victimPed->bIsDucking ) { victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); @@ -892,10 +893,10 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, { posOffset.Normalise(); victimPed->bIsStanding = false; - + victimPed->ApplyMoveForce(posOffset.x*-5.0f, posOffset.y*-5.0f, 5.0f); victimPed->SetFall(1500, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); - + victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); } else @@ -906,13 +907,13 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, if ( victimPlayer->m_nHitAnimDelayTimer < CTimer::GetTimeInMilliseconds() ) { victimPed->ClearAttackByRemovingAnim(); - + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); - ASSERT(asoc!=NULL); - + ASSERT(asoc!=nil); + asoc->blendAmount = 0.0f; asoc->blendDelta = 8.0f; - + if ( m_eWeaponType == WEAPONTYPE_AK47 || m_eWeaponType == WEAPONTYPE_M16 ) victimPlayer->m_nHitAnimDelayTimer = CTimer::GetTimeInMilliseconds() + 2500; else @@ -922,32 +923,32 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, else { victimPed->ClearAttackByRemovingAnim(); - + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); - ASSERT(asoc!=NULL); - + ASSERT(asoc!=nil); + asoc->blendAmount = 0.0f; asoc->blendDelta = 8.0f; } - + victimPed->InflictDamage(shooter, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point->pieceB, localDir); } } - + if ( victimPed->m_nPedType == PEDTYPE_COP ) CEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); else CEventList::RegisterEvent(EVENT_SHOOT_PED, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); - + if ( CGame::nastyGame ) { uint8 bloodAmount = 8; if ( m_eWeaponType == WEAPONTYPE_SHOTGUN || m_eWeaponType == WEAPONTYPE_HELICANNON ) bloodAmount = 32; - + CVector dir = (point->point - victim->GetPosition()) * 0.01f; dir.z = 0.01f; - + if ( victimPed->GetIsOnScreen() ) { for ( uint8 i = 0; i < bloodAmount; i++ ) @@ -962,13 +963,13 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, { CVector dir = (point->point - victim->GetPosition()) * 0.01f; dir.z = 0.01f; - + if ( victim->GetIsOnScreen() ) { for ( int32 i = 0; i < 8; i++ ) CParticle::AddParticle(PARTICLE_BLOOD_SMALL, point->point + CVector(0.0f, 0.0f, 0.15f), dir); } - + if ( victimPed->Dead() ) { CAnimBlendAssociation *asoc; @@ -976,7 +977,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, asoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT_F, 8.0f); else asoc = CAnimManager::BlendAnimation(victimPed->GetClump(), ASSOCGRP_STD, ANIM_FLOOR_HIT, 8.0f); - + if ( asoc ) { asoc->SetCurrentTime(0.0f); @@ -995,36 +996,36 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, { for ( int32 i = 0; i < 16; i++ ) CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); - + CVector dist = point->point - (*source); CVector offset = dist - max(0.2f*dist.Magnitude(), 2.0f) * CVector(ahead.x, ahead.y, 0.0f); CVector smokePos = *source + offset; - + smokePos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); smokePos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); smokePos.z += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); - + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); - + break; } case ENTITY_TYPE_VEHICLE: { ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage); - + for ( int32 i = 0; i < 16; i++ ) CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); - + CVector dist = point->point - (*source); CVector offset = dist - max(0.2f*dist.Magnitude(), 0.5f) * CVector(ahead.x, ahead.y, 0.0f); CVector smokePos = *source + offset; - + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); - + if ( shooter->IsPed() ) { CPed *shooterPed = (CPed *)shooter; - + if ( shooterPed->bNotAllowedToDuck ) { if ( shooterPed->bKindaStayInSamePlace && victim != shooterPed->m_pPointGunAt ) @@ -1034,16 +1035,16 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, } } } - + break; } case ENTITY_TYPE_OBJECT: { for ( int32 i = 0; i < 8; i++ ) CParticle::AddParticle(PARTICLE_SPARK, point->point, point->normal*0.05f); - + CObject *victimObject = (CObject *)victim; - + if ( !victimObject->bInfiniteMass ) { if ( victimObject->bIsStatic && victimObject->m_fUprootLimit <= 0.0f ) @@ -1051,19 +1052,19 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, victimObject->bIsStatic = false; victimObject->AddToMovingList(); } - + if ( !victimObject->bIsStatic ) { CVector moveForce = point->normal*-4.0f; victimObject->ApplyMoveForce(moveForce.x, moveForce.y, moveForce.z); } } - + break; } } } - + switch ( victim->m_type ) { case ENTITY_TYPE_BUILDING: @@ -1096,50 +1097,50 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, } else CBulletTraces::AddTrace(source, target); - + if ( shooter == FindPlayerPed() ) CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); - + BlowUpExplosiveThings(victim); } bool CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) { - ASSERT(shooter!=NULL); - ASSERT(fireSource!=NULL); - + ASSERT(shooter!=nil); + ASSERT(fireSource!=nil); + CWeaponInfo *info = GetInfo(); - + float heading = RADTODEG(shooter->GetForward().Heading()); float angle = DEGTORAD(heading); - + CVector2D rotOffset(-Sin(angle), Cos(angle)); rotOffset.Normalise(); - + CVector gunflashPos = *fireSource; gunflashPos += CVector(rotOffset.x*0.1f, rotOffset.y*0.1f, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f); + CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f); gunflashPos += CVector(rotOffset.x*0.1f, rotOffset.y*0.1f, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.15f); + CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.15f); gunflashPos += CVector(rotOffset.x*0.1f, rotOffset.y*0.1f, 0.0f); - CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), NULL, 0.2f); - CParticle::AddParticle(PARTICLE_GUNFLASH, *fireSource, CVector(0.0f, 0.0f, 0.0f), NULL, 0.0f); - + CParticle::AddParticle(PARTICLE_GUNFLASH, gunflashPos, CVector(0.0f, 0.0f, 0.0f), nil, 0.2f); + CParticle::AddParticle(PARTICLE_GUNFLASH, *fireSource, CVector(0.0f, 0.0f, 0.0f), nil, 0.0f); + CVector gunsmokePos = *fireSource; - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.10f, rotOffset.y*0.10f, 0.0f), NULL, 0.1f); - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.15f, rotOffset.y*0.15f, 0.0f), NULL, 0.1f); - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.20f, rotOffset.y*0.20f, 0.0f), NULL, 0.1f); - CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.25f, rotOffset.y*0.25f, 0.0f), NULL, 0.1f); - + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.10f, rotOffset.y*0.10f, 0.0f), nil, 0.1f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.15f, rotOffset.y*0.15f, 0.0f), nil, 0.1f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.20f, rotOffset.y*0.20f, 0.0f), nil, 0.1f); + CParticle::AddParticle(PARTICLE_GUNSMOKE2, gunsmokePos, CVector(rotOffset.x*0.25f, rotOffset.y*0.25f, 0.0f), nil, 0.1f); + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, shooter, (CPed*)shooter, 1000); - + CPointLights::AddLight(CPointLights::LIGHT_POINT, *fireSource, CVector(0.0, 0.0, 0.0), 5.0f, 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - + float shooterAngle; - - if ( shooter->IsPed() && ((CPed*)shooter)->m_pPointGunAt != NULL ) + + if ( shooter->IsPed() && ((CPed*)shooter)->m_pPointGunAt != nil ) { CEntity *threatAttack = ((CPed*)shooter)->m_pPointGunAt; shooterAngle = CGeneral::GetAngleBetweenPoints(threatAttack->GetPosition().x, threatAttack->GetPosition().y, @@ -1147,13 +1148,13 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) } else shooterAngle = RADTODEG(shooter->GetForward().Heading()); - - + + for ( int32 i = 0; i < 5; i++ ) // five shoots at once { float shootAngle = DEGTORAD(7.5f*i + shooterAngle - 15.0f); CVector2D shootRot(-Sin(shootAngle), Cos(shootAngle)); - + CVector source, target; CColPoint point; CEntity *victim; @@ -1167,7 +1168,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) target = f * Left + target - source; target *= info->m_fRange; target += source; - + ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); } else @@ -1175,12 +1176,12 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) target = *fireSource; target.x += shootRot.x * info->m_fRange; target.y += shootRot.y * info->m_fRange; - + if ( shooter->IsPed() ) { CPed *shooterPed = (CPed *)shooter; - - if ( shooterPed->m_pPointGunAt == NULL ) + + if ( shooterPed->m_pPointGunAt == nil ) DoDoomAiming(shooter, fireSource, &target); else { @@ -1188,63 +1189,63 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) target.z += info->m_fRange / distToTarget * (shooterPed->m_pPointGunAt->GetPosition().z - target.z); } } - + ProcessLineOfSight(*fireSource, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); } - + if ( victim ) { CGlass::WasGlassHitByBullet(victim, point.point); - + CBulletTraces::AddTrace(fireSource, &point.point); - + if ( victim->IsPed() ) { CPed *victimPed = (CPed *)victim; if ( !victimPed->OnGround() && victim != shooter && victimPed->DoesLOSBulletHitPed(point) ) { bool cantStandup = true; - + CVector pos = victimPed->GetPosition(); - + CVector2D posOffset((*fireSource).x-pos.x, (*fireSource).y-pos.y); int32 localDir = victimPed->GetLocalDirection(posOffset); - + victimPed->ReactToAttack(FindPlayerPed()); - + posOffset.Normalise(); - + if ( victimPed->m_getUpTimer > (CTimer::GetTimeInMilliseconds() - 3000) ) cantStandup = false; - + if ( victimPed->bIsStanding && cantStandup ) { victimPed->bIsStanding = false; - + victimPed->ApplyMoveForce(posOffset.x*-6.0f, posOffset.y*-6.0f, 5.0f); } else victimPed->ApplyMoveForce(posOffset.x*-2.0f, posOffset.y*-2.0f, 0.0f); - + if ( cantStandup ) victimPed->SetFall(1500, AnimationId(ANIM_KO_SKID_FRONT + localDir), false); - - victimPed->InflictDamage(NULL, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point.pieceB, localDir); - + + victimPed->InflictDamage(nil, m_eWeaponType, info->m_nDamage, (ePedPieceTypes)point.pieceB, localDir); + if ( victimPed->m_nPedType == PEDTYPE_COP ) CEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); else CEventList::RegisterEvent(EVENT_SHOOT_PED, EVENT_ENTITY_PED, victim, (CPed*)shooter, 10000); - + if ( CGame::nastyGame ) { uint8 bloodAmount = 8; if ( m_eWeaponType == WEAPONTYPE_SHOTGUN ) bloodAmount = 32; - + CVector dir = (point.point - victim->GetPosition()) * 0.01f; dir.z = 0.01f; - + if ( victimPed->GetIsOnScreen() ) { for ( uint8 i = 0; i < bloodAmount; i++ ) @@ -1254,45 +1255,45 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) } } else - { + { switch ( victim->m_type ) { case ENTITY_TYPE_VEHICLE: { ((CVehicle *)victim)->InflictDamage(shooter, m_eWeaponType, info->m_nDamage); - + for ( int32 i = 0; i < 16; i++ ) CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal*0.05f); - + CVector dist = point.point - (*fireSource); CVector offset = dist - max(0.2f*dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); CVector smokePos = *fireSource + offset; - + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); - + break; } - + case ENTITY_TYPE_BUILDING: case ENTITY_TYPE_OBJECT: { for ( int32 i = 0; i < 16; i++ ) CParticle::AddParticle(PARTICLE_SPARK, point.point, point.normal*0.05f); - + CVector dist = point.point - (*fireSource); CVector offset = dist - max(0.2f*dist.Magnitude(), 2.0f) * CVector(shootRot.x, shootRot.y, 0.0f); CVector smokePos = *fireSource + offset; - + smokePos.x += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); smokePos.y += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); smokePos.z += CGeneral::GetRandomNumberInRange(-0.2f, 0.2f); - + CParticle::AddParticle(PARTICLE_BULLETHIT_SMOKE, smokePos, CVector(0.0f, 0.0f, 0.0f)); - + if ( victim->IsObject() ) { CObject *victimObject = (CObject *)victim; - + if ( !victimObject->bInfiniteMass ) { if ( victimObject->bIsStatic && victimObject->m_fUprootLimit <= 0.0f ) @@ -1300,7 +1301,7 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) victimObject->bIsStatic = false; victimObject->AddToMovingList(); } - + if ( !victimObject->bIsStatic ) { CVector moveForce = point.normal*-5.0f; @@ -1308,12 +1309,12 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) } } } - + break; } } } - + switch ( victim->m_type ) { case ENTITY_TYPE_BUILDING: @@ -1351,25 +1352,25 @@ CWeapon::FireShotgun(CEntity *shooter, CVector *fireSource) CBulletTraces::AddTrace(fireSource, &traceTarget); } } - + if ( shooter == FindPlayerPed() ) CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); - + return true; } bool CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power) { - ASSERT(shooter!=NULL); - ASSERT(fireSource!=NULL); - + ASSERT(shooter!=nil); + ASSERT(fireSource!=nil); + CVector source, target; - + if ( m_eWeaponType == WEAPONTYPE_ROCKETLAUNCHER ) { source = *fireSource; - + if ( shooter->IsPed() && ((CPed*)shooter)->IsPlayer() ) { int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; @@ -1382,31 +1383,31 @@ CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power) { return false; } - + *fireSource += TheCamera.Cams[TheCamera.ActiveCam].Front; } else *fireSource += shooter->GetForward(); - + target = *fireSource; } else { float dot = DotProduct(*fireSource-shooter->GetPosition(), shooter->GetForward()); - + if ( dot < 0.3f ) *fireSource += (0.3f-dot) * shooter->GetForward(); - + target = *fireSource; - + if ( target.z - shooter->GetPosition().z > 0.0f ) target += 0.6f*shooter->GetForward(); - + source = *fireSource - shooter->GetPosition(); source = *fireSource - DotProduct(source, shooter->GetForward()) * shooter->GetForward(); } - + if ( !CWorld::GetIsLineOfSightClear(source, target, true, true, false, true, false, false, false) ) { if ( m_eWeaponType != WEAPONTYPE_GRENADE ) @@ -1417,8 +1418,8 @@ CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power) { source = shooter->GetPosition() - shooter->GetForward(); source.z -= 0.4f; - - if ( !CWorld::TestSphereAgainstWorld(source, 0.5f, NULL, false, false, true, false, false, false) ) + + if ( !CWorld::TestSphereAgainstWorld(source, 0.5f, nil, false, false, true, false, false, false) ) CProjectileInfo::AddProjectile(shooter, m_eWeaponType, source, 0.0f); else CProjectileInfo::RemoveNotAdd(shooter, m_eWeaponType, *fireSource); @@ -1427,7 +1428,7 @@ CWeapon::FireProjectile(CEntity *shooter, CVector *fireSource, float power) } else CProjectileInfo::AddProjectile(shooter, m_eWeaponType, *fireSource, power); - + return true; } @@ -1436,16 +1437,16 @@ CWeapon::GenerateFlameThrowerParticles(CVector pos, CVector dir) { dir *= 0.7f; CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); - + dir *= 0.7f; CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); - + dir *= 0.7f; CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); - + dir *= 0.7f; CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); - + dir *= 0.7f; CParticle::AddParticle(PARTICLE_FIREBALL, pos, dir); } @@ -1453,22 +1454,22 @@ CWeapon::GenerateFlameThrowerParticles(CVector pos, CVector dir) bool CWeapon::FireAreaEffect(CEntity *shooter, CVector *fireSource) { - ASSERT(shooter!=NULL); - ASSERT(fireSource!=NULL); - + ASSERT(shooter!=nil); + ASSERT(fireSource!=nil); + CWeaponInfo *info = GetInfo(); - + float heading = RADTODEG(shooter->GetForward().Heading()); - + CVector source; CVector target; CVector dir; - + if ( shooter == FindPlayerPed() && TheCamera.Cams[0].Using3rdPersonMouseCam() ) { TheCamera.Find3rdPersonCamTargetVector(info->m_fRange, *fireSource, source, target); float norm = (1.0f / info->m_fRange); - dir = (target - source) * norm; + dir = (target - source) * norm; } else { @@ -1476,18 +1477,18 @@ CWeapon::FireAreaEffect(CEntity *shooter, CVector *fireSource) dir = CVector(-Sin(angle)*0.5f, Cos(angle)*0.5f, 0.0f); target = *fireSource + dir; } - + CShotInfo::AddShot(shooter, m_eWeaponType, *fireSource, target); CWeapon::GenerateFlameThrowerParticles(*fireSource, dir); - + return true; } bool CWeapon::FireSniper(CEntity *shooter) { - ASSERT(shooter!=NULL); - + ASSERT(shooter!=nil); + int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; if (!( mode == CCam::MODE_M16_1STPERSON || mode == CCam::MODE_SNIPER @@ -1498,28 +1499,28 @@ CWeapon::FireSniper(CEntity *shooter) { return false; } - + #ifndef FIX_BUGS CWeaponInfo *info = GetInfo(); //unused #endif CCam *cam = &TheCamera.Cams[TheCamera.ActiveCam]; - ASSERT(cam!=NULL); - + ASSERT(cam!=nil); + CVector source = cam->Source; CVector dir = cam->Front; - + if ( DotProduct(dir, CVector(0.0f, -0.9894f, 0.145f)) > 0.997f ) CCoronas::bSmallMoon = !CCoronas::bSmallMoon; - + dir.Normalise(); dir *= 16.0f; - + CBulletInfo::AddBullet(shooter, m_eWeaponType, source, dir); - + if ( shooter == FindPlayerPed() ) CStats::InstantHitsFiredByPlayer++; - + if ( shooter == FindPlayerPed() ) { CPad::GetPad(0)->StartShake_Distance(240, 128, @@ -1529,17 +1530,17 @@ CWeapon::FireSniper(CEntity *shooter) CamShakeNoPos(&TheCamera, 0.2f); } - + return true; } bool CWeapon::FireM16_1stPerson(CEntity *shooter) { - ASSERT(shooter!=NULL); - + ASSERT(shooter!=nil); + int16 mode = TheCamera.Cams[TheCamera.ActiveCam].Mode; - + if (!( mode == CCam::MODE_M16_1STPERSON || mode == CCam::MODE_SNIPER || mode == CCam::MODE_ROCKETLAUNCHER @@ -1550,30 +1551,30 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) { return false; } - + CWeaponInfo *info = GetInfo(); - + CColPoint point; CEntity *victim; - + CWorld::bIncludeCarTyres = true; CWorld::pIgnoreEntity = shooter; CWorld::bIncludeDeadPeds = true; - + CCam *cam = &TheCamera.Cams[TheCamera.ActiveCam]; - ASSERT(cam!=NULL); - + ASSERT(cam!=nil); + CVector source = cam->Source; CVector target = cam->Front*info->m_fRange + source; - + ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); CWorld::bIncludeDeadPeds = false; - CWorld::pIgnoreEntity = NULL; + CWorld::pIgnoreEntity = nil; CWorld::bIncludeCarTyres = false; - + CVector2D front(cam->Front.x, cam->Front.y); front.Normalise(); - + DoBulletImpact(shooter, victim, &source, &target, &point, front); CVector bulletPos; @@ -1582,11 +1583,11 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) for ( int32 i = 0; i < 16; i++ ) CParticle::AddParticle(PARTICLE_SPARK, bulletPos, CVector(0.0f, 0.0f, 0.0f)); } - + if ( shooter == FindPlayerPed() ) { CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerPed()->GetPosition().x, FindPlayerPed()->GetPosition().y, FindPlayerPed()->GetPosition().z); - + if ( m_eWeaponType == WEAPONTYPE_M16 ) { TheCamera.Cams[TheCamera.ActiveCam].Beta += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0003f; @@ -1598,7 +1599,7 @@ CWeapon::FireM16_1stPerson(CEntity *shooter) TheCamera.Cams[TheCamera.ActiveCam].Alpha += float((CGeneral::GetRandomNumber() & 127) - 64) * 0.0001f; } } - + return true; } @@ -1606,56 +1607,56 @@ bool CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) { CWeaponInfo *info = GetInfo(); - + CVehicleModelInfo *modelInfo = shooter->GetModelInfo(); - + #define FRONTSEATPOS() (&(shooter->IsBoat() ? modelInfo->m_positions[BOAT_POS_FRONTSEAT] : modelInfo->m_positions[CAR_POS_FRONTSEAT])) - + CVector source, target; if ( left ) { - source = shooter->GetMatrix() * CVector(-shooter->GetColModel()->boundingBox.max.x + -0.2f, + source = shooter->GetMatrix() * CVector(-shooter->GetColModel()->boundingBox.max.x + -0.2f, float(CGeneral::GetRandomNumber() & 255) * 0.001f + FRONTSEATPOS()->y, FRONTSEATPOS()->z + 0.5f); source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; - - + + target = shooter->GetMatrix() * CVector(-info->m_fRange, FRONTSEATPOS()->y, FRONTSEATPOS()->z + 0.5f); } else { - source = shooter->GetMatrix() * CVector(shooter->GetColModel()->boundingBox.max.x + 0.2f, + source = shooter->GetMatrix() * CVector(shooter->GetColModel()->boundingBox.max.x + 0.2f, float(CGeneral::GetRandomNumber() & 255) * 0.001f + FRONTSEATPOS()->y, FRONTSEATPOS()->z + 0.5f); source += CTimer::GetTimeStep() * shooter->m_vecMoveSpeed; - + target = shooter->GetMatrix() * CVector(info->m_fRange, FRONTSEATPOS()->y, FRONTSEATPOS()->z + 0.5f); } #undef FRONTSEATPOS - + if ( TheCamera.GetLookingLRBFirstPerson() && !left ) { source -= 0.3f * shooter->GetForward(); target -= 0.3f * shooter->GetForward(); } - + target += CVector(float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f, float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f, float(CGeneral::GetRandomNumber()&255)*0.01f-1.28f); - + DoDriveByAutoAiming(FindPlayerPed(), &source, &target); - + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_PED, FindPlayerPed(), FindPlayerPed(), 1000); if ( !TheCamera.GetLookingLRBFirstPerson() ) CParticle::AddParticle(PARTICLE_GUNFLASH, source, CVector(0.0f, 0.0f, 0.0f)); else CamShakeNoPos(&TheCamera, 0.01f); - + CEventList::RegisterEvent(EVENT_GUNSHOT, EVENT_ENTITY_VEHICLE, shooter, FindPlayerPed(), 1000); CPointLights::AddLight(CPointLights::LIGHT_POINT, source, CVector(0.0f, 0.0f, 0.0f), 5.0f, @@ -1664,38 +1665,38 @@ CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) CColPoint point; CEntity *victim; ProcessLineOfSight(source, target, point, victim, m_eWeaponType, shooter, true, true, true, true, true, true, false); - + if ( !(CTimer::GetFrameCounter() & 3) ) MakePedsJumpAtShot(shooter, &source, &target); - + if ( victim ) { CVector traceTarget = point.point; CBulletTraces::AddTrace(&source, &traceTarget); - + if ( victim->IsPed() ) { CPed *victimPed = (CPed*)victim; - + if ( !victimPed->DyingOrDead() && victim != (CEntity *)shooter ) { CVector pos = victimPed->GetPosition(); - + CVector2D posOffset(source.x-pos.x, source.y-pos.y); int32 localDir = victimPed->GetLocalDirection(posOffset); - + victimPed->ReactToAttack(FindPlayerPed()); victimPed->ClearAttackByRemovingAnim(); - + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); - ASSERT(asoc!=NULL); + ASSERT(asoc!=nil); asoc->blendAmount = 0.0f; asoc->blendDelta = 8.0f; - + victimPed->InflictDamage(shooter, WEAPONTYPE_UZI_DRIVEBY, 3*info->m_nDamage, (ePedPieceTypes)point.pieceB, localDir); - + pos.z += 0.8f; - + if ( victimPed->GetIsOnScreen() ) { if ( CGame::nastyGame ) @@ -1706,12 +1707,12 @@ CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) dir.x = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); dir.y = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); dir.z = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); - + CParticle::AddParticle(PARTICLE_BLOOD, pos, dir); } } } - + if ( victimPed->m_nPedType == PEDTYPE_COP ) CEventList::RegisterEvent(EVENT_SHOOT_COP, EVENT_ENTITY_PED, victimPed, FindPlayerPed(), 10000); else @@ -1722,7 +1723,7 @@ CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) ((CVehicle *)victim)->InflictDamage(FindPlayerPed(), WEAPONTYPE_UZI_DRIVEBY, info->m_nDamage); else CGlass::WasGlassHitByBullet(victim, point.point); - + switch ( victim->m_type ) { case ENTITY_TYPE_BUILDING: @@ -1759,20 +1760,20 @@ CWeapon::FireInstantHitFromCar(CAutomobile *shooter, bool left) CVector traceTarget = (target-source)*norm + source; CBulletTraces::AddTrace(&source, &traceTarget); } - + if ( shooter == FindPlayerVehicle() ) CPad::GetPad(0)->StartShake_Distance(240, 128, FindPlayerVehicle()->GetPosition().x, FindPlayerVehicle()->GetPosition().y, FindPlayerVehicle()->GetPosition().z); - + return true; } void CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) { - ASSERT(shooter!=NULL); - ASSERT(source!=NULL); - ASSERT(target !=NULL); - + ASSERT(shooter!=nil); + ASSERT(source!=nil); + ASSERT(target !=nil); + #ifndef FIX_BUGS CEntity entity; // unused #endif @@ -1780,19 +1781,19 @@ CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) CPed *shooterPed = (CPed*)shooter; if ( shooterPed->IsPed() && shooterPed->bCrouchWhenShooting ) return; - + int16 lastEntity; CEntity *entities[16]; CWorld::FindObjectsInRange(*source, (*target-*source).Magnitude(), true, &lastEntity, 15, entities, false, true, true, false, false); float closestEntityDist = 10000.0f; int16 closestEntity; - + for ( int32 i = 0; i < lastEntity; i++ ) { CEntity *victim = entities[i]; - ASSERT(victim!=NULL); - + ASSERT(victim!=nil); + if ( (CEntity*)shooterPed != victim && shooterPed->CanSeeEntity(victim, DEGTORAD(22.5f)) ) { if ( !(victim->m_status == STATUS_TRAIN_MOVING @@ -1802,11 +1803,11 @@ CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) { float distToVictim = (shooterPed->GetPosition()-victim->GetPosition()).Magnitude2D(); float distToVictimZ = Abs(shooterPed->GetPosition().z-victim->GetPosition().z); - + if ( 1.5f*distToVictimZ < distToVictim ) { float entityDist = Sqrt(SQR(distToVictim) + SQR(distToVictimZ)); - + if ( entityDist < closestEntityDist ) { closestEntityDist = entityDist; @@ -1816,22 +1817,22 @@ CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) } } } - + if ( closestEntityDist < DOOMAUTOAIMING_MAXDIST ) { CEntity *victim = entities[closestEntity]; - ASSERT(victim !=NULL); - + ASSERT(victim !=nil); + float distToTarget = (*target - *source).Magnitude2D(); float distToSource = (victim->GetPosition() - *source).Magnitude2D(); - + float victimZ = victim->GetPosition().z + 0.3f; if ( victim->IsPed() ) { if ( ((CPed*)victim)->bIsDucking ) victimZ -= 0.8f; } - + (*target).z = (distToTarget / distToSource) * (victimZ - (*source).z) + (*source).z; } } @@ -1839,11 +1840,11 @@ CWeapon::DoDoomAiming(CEntity *shooter, CVector *source, CVector *target) void CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CVector *target) { - ASSERT(shooter!=NULL); - ASSERT(driver!=NULL); - ASSERT(source!=NULL); - ASSERT(target!=NULL); - + ASSERT(shooter!=nil); + ASSERT(driver!=nil); + ASSERT(source!=nil); + ASSERT(target!=nil); + #ifndef FIX_BUGS CEntity entity; // unused #endif @@ -1854,17 +1855,17 @@ CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CV float closestEntityDist = 10000.0f; int16 closestEntity; - + float normZ = (target->z - source->z) / (*target-*source).Magnitude(); - + for ( int32 i = 0; i < lastEntity; i++ ) { CEntity *victim = entities[i]; - - ASSERT(victim!=NULL); - + + ASSERT(victim!=nil); + if ( shooter != victim && driver != victim ) - { + { if ( !(victim->m_status == STATUS_TRAIN_MOVING || victim->m_status == STATUS_TRAIN_NOT_MOVING || victim->m_status == STATUS_HELI @@ -1874,7 +1875,7 @@ CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CV { float distToVictim = (shooter->GetPosition()-victim->GetPosition()).Magnitude2D(); float distToVictimZ = Abs(shooter->GetPosition().z - (distToVictim*normZ + victim->GetPosition().z)); - + if ( 3.0f*distToVictimZ < distToVictim ) { if ( CCollision::DistToLine(source, target, @@ -1892,15 +1893,15 @@ CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CV } } } - + if ( closestEntityDist < DOOMAUTOAIMING_MAXDIST ) { CEntity *victim = entities[closestEntity]; - ASSERT(victim!=NULL); - + ASSERT(victim!=nil); + float distToTarget = (*target - *source).Magnitude2D(); float distToSource = (victim->GetPosition() - *source).Magnitude2D(); - + (*target).z = (distToTarget / distToSource) * (0.3f + victim->GetPosition().z - (*source).z) + (*source).z; } } @@ -1908,36 +1909,36 @@ CWeapon::DoTankDoomAiming(CEntity *shooter, CEntity *driver, CVector *source, CV void CWeapon::DoDriveByAutoAiming(CEntity *shooter, CVector *source, CVector *target) { - ASSERT(shooter!=NULL); - ASSERT(source!=NULL); - ASSERT(target!=NULL); - + ASSERT(shooter!=nil); + ASSERT(source!=nil); + ASSERT(target!=nil); + #ifndef FIX_BUGS CEntity entity; // unused #endif - + CPed *shooterPed = (CPed*)shooter; if ( shooterPed->IsPed() && shooterPed->bCrouchWhenShooting ) return; - + int16 lastEntity; CEntity *entities[16]; CWorld::FindObjectsInRange(*source, (*target-*source).Magnitude(), true, &lastEntity, 15, entities, false, false, true, false, false); float closestEntityDist = 10000.0f; int16 closestEntity; - + for ( int32 i = 0; i < lastEntity; i++ ) { CEntity *victim = entities[i]; - ASSERT(victim!=NULL); - + ASSERT(victim!=nil); + if ( shooter != victim ) { float lineDist = CCollision::DistToLine(source, target, &victim->GetPosition()); float distToVictim = (victim->GetPosition() - shooter->GetPosition()).Magnitude(); float pedDist = 0.15f*distToVictim + lineDist; - + if ( DotProduct((*target-*source), victim->GetPosition()-*source) > 0.0f && pedDist < closestEntityDist) { closestEntity = i; @@ -1945,12 +1946,12 @@ CWeapon::DoDriveByAutoAiming(CEntity *shooter, CVector *source, CVector *target) } } } - + if ( closestEntityDist < DRIVEBYAUTOAIMING_MAXDIST ) { CEntity *victim = entities[closestEntity]; - ASSERT(victim!=NULL); - + ASSERT(victim!=nil); + float distToTarget = (*source - *target).Magnitude(); float distToSource = (*source - victim->GetPosition()).Magnitude(); *target = (distToTarget / distToSource) * (victim->GetPosition() - *source) + *source; @@ -1981,7 +1982,7 @@ CWeapon::Update(int32 audioEntity) m_eWeaponState = WEAPONSTATE_READY; break; } - + case WEAPONSTATE_FIRING: { if ( m_eWeaponType == WEAPONTYPE_SHOTGUN && AEHANDLE_IS_OK(audioEntity) ) @@ -1990,7 +1991,7 @@ CWeapon::Update(int32 audioEntity) if ( CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed ) DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); } - + if ( CTimer::GetTimeInMilliseconds() > m_nTimer ) { if ( GetInfo()->m_eWeaponFire != WEAPON_FIRE_MELEE && m_nAmmoTotal == 0 ) @@ -1998,10 +1999,10 @@ CWeapon::Update(int32 audioEntity) else m_eWeaponState = WEAPONSTATE_READY; } - + break; } - + case WEAPONSTATE_RELOADING: { if ( AEHANDLE_IS_OK(audioEntity) && m_eWeaponType < WEAPONTYPE_LAST_WEAPONTYPE ) @@ -2010,13 +2011,13 @@ CWeapon::Update(int32 audioEntity) if ( CTimer::GetPreviousTimeInMilliseconds() < timePassed && CTimer::GetTimeInMilliseconds() >= timePassed ) DMAudio.PlayOneShot(audioEntity, SOUND_WEAPON_RELOAD, 0.0f); } - + if ( CTimer::GetTimeInMilliseconds() > m_nTimer ) { Reload(); m_eWeaponState = WEAPONSTATE_READY; } - + break; } } @@ -2025,21 +2026,21 @@ CWeapon::Update(int32 audioEntity) void FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) { - ASSERT(source!=NULL); - ASSERT(target!=NULL); - + ASSERT(source!=nil); + ASSERT(target!=nil); + CParticle::AddParticle(PARTICLE_GUNFLASH, *source, CVector(0.0f, 0.0f, 0.0f)); - + CPointLights::AddLight(CPointLights::LIGHT_POINT, *source, CVector(0.0f, 0.0f, 0.0f), 5.0f, 1.0f, 0.8f, 0.0f, CPointLights::FOG_NONE, false); - + CColPoint point; CEntity *victim; CWorld::ProcessLineOfSight(*source, *target, point, victim, true, true, true, true, true, true, false); - + CParticle::AddParticle(PARTICLE_HELI_ATTACK, *source, (*target) - (*source) * 0.15f); - + if ( victim ) { if ( victim->IsPed() ) @@ -2048,21 +2049,21 @@ FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) if ( !victimPed->DyingOrDead() ) { CVector pos = victimPed->GetPosition(); - + CVector2D posOffset((*source).x-pos.x, (*source).y-pos.y); int32 localDir = victimPed->GetLocalDirection(posOffset); - + victimPed->ClearAttackByRemovingAnim(); - + CAnimBlendAssociation *asoc = CAnimManager::AddAnimation(victimPed->GetClump(), ASSOCGRP_STD, AnimationId(ANIM_SHOT_FRONT_PARTIAL + localDir)); - ASSERT(asoc!=NULL); + ASSERT(asoc!=nil); asoc->blendAmount = 0.0f; asoc->blendDelta = 8.0f; - - victimPed->InflictDamage(NULL, WEAPONTYPE_UZI, damage, (ePedPieceTypes)point.pieceB, localDir); - + + victimPed->InflictDamage(nil, WEAPONTYPE_UZI, damage, (ePedPieceTypes)point.pieceB, localDir); + pos.z += 0.8f; - + if ( victimPed->GetIsOnScreen() ) { if ( CGame::nastyGame ) @@ -2073,7 +2074,7 @@ FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) dir.x = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); dir.y = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); dir.z = CGeneral::GetRandomNumberInRange(-0.1f, 0.1f); - + CParticle::AddParticle(PARTICLE_BLOOD, pos, dir); } } @@ -2081,9 +2082,9 @@ FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) } } else if ( victim->IsVehicle() ) - ((CVehicle *)victim)->InflictDamage(NULL, WEAPONTYPE_UZI, damage); + ((CVehicle *)victim)->InflictDamage(nil, WEAPONTYPE_UZI, damage); //BUG ? no CGlass::WasGlassHitByBullet - + switch ( victim->m_type ) { case ENTITY_TYPE_BUILDING: @@ -2141,21 +2142,21 @@ CWeapon::IsType2Handed(void) void CWeapon::MakePedsJumpAtShot(CPhysical *shooter, CVector *source, CVector *target) { - ASSERT(shooter!=NULL); - ASSERT(source!=NULL); - ASSERT(target!=NULL); - + ASSERT(shooter!=nil); + ASSERT(source!=nil); + ASSERT(target!=nil); + float minx = min(source->x, target->x) - 2.0f; float maxx = max(source->x, target->x) + 2.0f; float miny = min(source->y, target->y) - 2.0f; float maxy = max(source->y, target->y) + 2.0f; float minz = min(source->z, target->z) - 2.0f; float maxz = max(source->z, target->z) + 2.0f; - + for ( int32 i = CPools::GetPedPool()->GetSize() - 1; i >= 0; i--) { CPed *ped = CPools::GetPedPool()->GetSlot(i); - + if ( ped ) { if ( ped->GetPosition().x > minx && ped->GetPosition().x < maxx @@ -2172,14 +2173,14 @@ CWeapon::MakePedsJumpAtShot(CPhysical *shooter, CVector *source, CVector *target bool CWeapon::HitsGround(CEntity *holder, CVector *fireSource, CEntity *aimingTo) { - ASSERT(holder!=NULL); - ASSERT(aimingTo!=NULL); - + ASSERT(holder!=nil); + ASSERT(aimingTo!=nil); + if (!holder->IsPed() || !((CPed*)holder)->m_pSeekTarget) return false; CWeaponInfo *info = GetInfo(); - + CVector adjustedOffset = info->m_vecFireOffset; adjustedOffset.z += 0.6f; @@ -2193,8 +2194,8 @@ CWeapon::HitsGround(CEntity *holder, CVector *fireSource, CEntity *aimingTo) source = holder->GetMatrix() * adjustedOffset; CEntity *aimEntity = aimingTo ? aimingTo : ((CPed*)holder)->m_pSeekTarget; - ASSERT(aimEntity!=NULL); - + ASSERT(aimEntity!=nil); + target = aimEntity->GetPosition(); target.z += 0.6f; @@ -2219,17 +2220,17 @@ CWeapon::BlowUpExplosiveThings(CEntity *thing) if ( IsExplosiveThingModel(mi) && !object->bHasBeenDamaged ) { object->bHasBeenDamaged = true; - + CExplosion::AddExplosion(object, FindPlayerPed(), EXPLOSION_BARREL, object->GetPosition()+CVector(0.0f,0.0f,0.5f), 100); - + if ( MI_EXPLODINGBARREL == mi ) object->m_vecMoveSpeed.z += 0.75f; else object->m_vecMoveSpeed.z += 0.45f; - + object->m_vecMoveSpeed.x += float((CGeneral::GetRandomNumber()&255) - 128) * 0.0002f; object->m_vecMoveSpeed.y += float((CGeneral::GetRandomNumber()&255) - 128) * 0.0002f; - + if ( object->bIsStatic ) { object->bIsStatic = false; @@ -2250,7 +2251,7 @@ CWeapon::HasWeaponAmmoToBeUsed(void) return m_nAmmoTotal != 0; } } - + bool CWeapon::ProcessLineOfSight(CVector const &point1, CVector const &point2, CColPoint &point, CEntity *&entity, eWeaponType type, CEntity *shooter, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects) { From 708d247c982c7a95620723e520c718afd2058690 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Wed, 15 Apr 2020 19:53:08 +0300 Subject: [PATCH 14/18] 'fix' fix --- src/weapons/Weapon.cpp | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index b0c9b61f..fbd25f81 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -30,23 +30,22 @@ #include "WeaponInfo.h" #include "World.h" -uint16 gReloadSampleTime[WEAPONTYPE_TOTAL_INVENTORY_WEAPONS] = +uint16 gReloadSampleTime[WEAPONTYPE_LAST_WEAPONTYPE] = { - 0, // UNARMED - 0, // BASEBALLBAT - 250, // COLT45 - 400, // UZI - 650, // SHOTGUN - 300, // AK47 - 300, // M16 - 423, // SNIPERRIFLE - 400, // ROCKETLAUNCHER - 0, // FLAMETHROWER - 0, // MOLOTOV - 0, // GRENADE - 0, // DETONATOR - - 0 // WEAPONTYPE_HELICANNON + 0, // UNARMED + 0, // BASEBALLBAT + 250, // COLT45 + 400, // UZI + 650, // SHOTGUN + 300, // AK47 + 300, // M16 + 423, // SNIPERRIFLE + 400, // ROCKETLAUNCHER + 0, // FLAMETHROWER + 0, // MOLOTOV + 0, // GRENADE + 0, // DETONATOR + 0 // HELICANNON }; CWeaponInfo * From cb4e1d68e77a7fd7f17563d0522eeb2f0c39e94d Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Wed, 15 Apr 2020 20:09:51 +0300 Subject: [PATCH 15/18] glass NULL->nil --- src/render/Glass.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/render/Glass.cpp b/src/render/Glass.cpp index 46a12a6f..ac6c1728 100644 --- a/src/render/Glass.cpp +++ b/src/render/Glass.cpp @@ -404,7 +404,7 @@ CGlass::AskForObjectToBeRenderedInGlass(CEntity *entity) void CGlass::RenderEntityInGlass(CEntity *entity) { - ASSERT(entity!=NULL); + ASSERT(entity!=nil); CObject *object = (CObject *)entity; if ( object->bGlassBroken ) @@ -420,7 +420,7 @@ CGlass::RenderEntityInGlass(CEntity *entity) uint8 alpha = CalcAlphaWithNormal(&fwdNorm); CColModel *col = object->GetColModel(); - ASSERT(col!=NULL); + ASSERT(col!=nil); if ( col->numTriangles >= 2 ) { CVector a = object->GetMatrix() * col->vertices[0]; @@ -524,7 +524,7 @@ CGlass::RenderEntityInGlass(CEntity *entity) int32 CGlass::CalcAlphaWithNormal(CVector *normal) { - ASSERT(normal!=NULL); + ASSERT(normal!=nil); float fwdDir = 2.0f * DotProduct(*normal, TheCamera.GetForward()); float fwdDot = DotProduct(TheCamera.GetForward()-fwdDir*(*normal), CVector(0.57f, 0.57f, -0.57f)); @@ -600,7 +600,7 @@ CGlass::RenderReflectionPolys(void) void CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, CVector point, bool explosion) { - ASSERT(entity!=NULL); + ASSERT(entity!=nil); CObject *object = (CObject *)entity; @@ -610,7 +610,7 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, object->bGlassCracked = true; CColModel *col = object->GetColModel(); - ASSERT(col!=NULL); + ASSERT(col!=nil); CVector a = object->GetMatrix() * col->vertices[0]; CVector b = object->GetMatrix() * col->vertices[1]; @@ -653,7 +653,7 @@ CGlass::WindowRespondsToCollision(CEntity *entity, float amount, CVector speed, void CGlass::WindowRespondsToSoftCollision(CEntity *entity, float amount) { - ASSERT(entity!=NULL); + ASSERT(entity!=nil); CObject *object = (CObject *)entity; @@ -667,7 +667,7 @@ CGlass::WindowRespondsToSoftCollision(CEntity *entity, float amount) void CGlass::WasGlassHitByBullet(CEntity *entity, CVector point) { - ASSERT(entity!=NULL); + ASSERT(entity!=nil); CObject *object = (CObject *)entity; @@ -689,7 +689,7 @@ CGlass::WasGlassHitByBullet(CEntity *entity, CVector point) void CGlass::WindowRespondsToExplosion(CEntity *entity, CVector point) { - ASSERT(entity!=NULL); + ASSERT(entity!=nil); CObject *object = (CObject *)entity; From c3647ee51e05df419ebb456416cb84e7f902e581 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Wed, 15 Apr 2020 20:34:58 +0300 Subject: [PATCH 16/18] rem comment --- src/peds/PlayerPed.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h index c6823c2d..f96d8e6a 100644 --- a/src/peds/PlayerPed.h +++ b/src/peds/PlayerPed.h @@ -21,7 +21,7 @@ public: int8 field_1367; uint32 m_nSpeedTimer; uint32 m_nHitAnimDelayTimer; - float m_fAttackButtonCounter; // m_fAttackButtonCounter? + float m_fAttackButtonCounter; bool m_bHaveTargetSelected; // may have better name int8 field_1381; int8 field_1382; From a9713125dc6d7857e14da8ea50d4ac4f37e6c8db Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Wed, 15 Apr 2020 20:58:28 +0300 Subject: [PATCH 17/18] fixed uzi/ak47/m16 trace --- src/weapons/Weapon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index fbd25f81..96f86989 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -856,7 +856,7 @@ CWeapon::DoBulletImpact(CEntity *shooter, CEntity *victim, { CGlass::WasGlassHitByBullet(victim, point->point); - CVector traceTarget = *target; + CVector traceTarget = point->point; CBulletTraces::AddTrace(source, &traceTarget); if ( shooter != nil ) From 190bc696d898f77c7355a0d919add8ab4f232b15 Mon Sep 17 00:00:00 2001 From: Fire-Head Date: Wed, 15 Apr 2020 21:29:00 +0300 Subject: [PATCH 18/18] fixed crash --- src/weapons/Weapon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 96f86989..7b6b4170 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -2038,7 +2038,7 @@ FireOneInstantHitRound(CVector *source, CVector *target, int32 damage) CEntity *victim; CWorld::ProcessLineOfSight(*source, *target, point, victim, true, true, true, true, true, true, false); - CParticle::AddParticle(PARTICLE_HELI_ATTACK, *source, (*target) - (*source) * 0.15f); + CParticle::AddParticle(PARTICLE_HELI_ATTACK, *source, ((*target) - (*source)) * 0.15f); if ( victim ) {