mirror of
https://github.com/halpz/re3.git
synced 2025-06-29 17:26:21 +00:00
Merge branch 'master' into MoreLanguages
# Conflicts: # src/core/Frontend.cpp # src/render/Font.cpp # src/render/Hud.cpp # src/render/Hud.h # src/text/Messages.cpp # src/text/Text.cpp
This commit is contained in:
@ -12,17 +12,17 @@ void CAutoPilot::ModifySpeed(float speed)
|
||||
float positionBetweenNodes = (float)(CTimer::GetTimeInMilliseconds() - m_nTimeEnteredCurve) / m_nTimeToSpendOnCurrentCurve;
|
||||
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo];
|
||||
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[m_nNextPathNodeInfo];
|
||||
float currentPathLinkForwardX = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dirX;
|
||||
float currentPathLinkForwardY = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dirY;
|
||||
float nextPathLinkForwardX = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dirX;
|
||||
float nextPathLinkForwardY = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dirY;
|
||||
float currentPathLinkForwardX = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dir.x;
|
||||
float currentPathLinkForwardY = m_nCurrentDirection * ThePaths.m_carPathLinks[m_nCurrentPathNodeInfo].dir.y;
|
||||
float nextPathLinkForwardX = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dir.x;
|
||||
float nextPathLinkForwardY = m_nNextDirection * ThePaths.m_carPathLinks[m_nNextPathNodeInfo].dir.y;
|
||||
CVector positionOnCurrentLinkIncludingLane(
|
||||
pCurrentLink->posX + ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardY,
|
||||
pCurrentLink->posY - ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardX,
|
||||
pCurrentLink->pos.x + ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardY,
|
||||
pCurrentLink->pos.y - ((m_nCurrentLane + 0.5f) * LANE_WIDTH) * currentPathLinkForwardX,
|
||||
0.0f);
|
||||
CVector positionOnNextLinkIncludingLane(
|
||||
pNextLink->posX + ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardY,
|
||||
pNextLink->posY - ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardX,
|
||||
pNextLink->pos.x + ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardY,
|
||||
pNextLink->pos.y - ((m_nNextLane + 0.5f) * LANE_WIDTH) * nextPathLinkForwardX,
|
||||
0.0f);
|
||||
m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
|
||||
&positionOnCurrentLinkIncludingLane,
|
||||
|
@ -90,7 +90,7 @@ uint32 (&aCarsToKeepTime)[MAX_CARS_TO_KEEP] = *(uint32(*)[MAX_CARS_TO_KEEP])*(ui
|
||||
void
|
||||
CCarCtrl::GenerateRandomCars()
|
||||
{
|
||||
if (CCutsceneMgr::IsCutsceneProcessing())
|
||||
if (CCutsceneMgr::IsRunning())
|
||||
return;
|
||||
if (NumRandomCars < 30){
|
||||
if (CountDownToCarsAtStart == 0){
|
||||
@ -393,25 +393,25 @@ CCarCtrl::GenerateOneRandomCar()
|
||||
pCar->GetRight() = CVector(forwardY, -forwardX, 0.0f);
|
||||
pCar->GetUp() = CVector(0.0f, 0.0f, 1.0f);
|
||||
|
||||
float currentPathLinkForwardX = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dirX;
|
||||
float currentPathLinkForwardY = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dirY;
|
||||
float nextPathLinkForwardX = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dirX;
|
||||
float nextPathLinkForwardY = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dirY;
|
||||
float currentPathLinkForwardX = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dir.x;
|
||||
float currentPathLinkForwardY = pCar->AutoPilot.m_nCurrentDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo].dir.y;
|
||||
float nextPathLinkForwardX = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dir.x;
|
||||
float nextPathLinkForwardY = pCar->AutoPilot.m_nNextDirection * ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo].dir.y;
|
||||
|
||||
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nCurrentPathNodeInfo];
|
||||
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pCar->AutoPilot.m_nNextPathNodeInfo];
|
||||
CVector positionOnCurrentLinkIncludingLane(
|
||||
pCurrentLink->posX + ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
|
||||
pCurrentLink->posY - ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
|
||||
pCurrentLink->pos.x + ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
|
||||
pCurrentLink->pos.y - ((pCar->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
|
||||
0.0f);
|
||||
CVector positionOnNextLinkIncludingLane(
|
||||
pNextLink->posX + ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
|
||||
pNextLink->posY - ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
|
||||
pNextLink->pos.x + ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
|
||||
pNextLink->pos.y - ((pCar->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
|
||||
0.0f);
|
||||
float directionCurrentLinkX = pCurrentLink->dirX * pCar->AutoPilot.m_nCurrentDirection;
|
||||
float directionCurrentLinkY = pCurrentLink->dirY * pCar->AutoPilot.m_nCurrentDirection;
|
||||
float directionNextLinkX = pNextLink->dirX * pCar->AutoPilot.m_nNextDirection;
|
||||
float directionNextLinkY = pNextLink->dirY * pCar->AutoPilot.m_nNextDirection;
|
||||
float directionCurrentLinkX = pCurrentLink->dir.x * pCar->AutoPilot.m_nCurrentDirection;
|
||||
float directionCurrentLinkY = pCurrentLink->dir.y * pCar->AutoPilot.m_nCurrentDirection;
|
||||
float directionNextLinkX = pNextLink->dir.x * pCar->AutoPilot.m_nNextDirection;
|
||||
float directionNextLinkY = pNextLink->dir.y * pCar->AutoPilot.m_nNextDirection;
|
||||
/* We want to make a path between two links that may not have the same forward directions a curve. */
|
||||
pCar->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
|
||||
&positionOnCurrentLinkIncludingLane,
|
||||
@ -763,17 +763,17 @@ CCarCtrl::UpdateCarOnRails(CVehicle* pVehicle)
|
||||
return;
|
||||
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
|
||||
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
|
||||
float currentPathLinkForwardX = pCurrentLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float currentPathLinkForwardY = pCurrentLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float nextPathLinkForwardX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection;
|
||||
float nextPathLinkForwardY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection;
|
||||
float currentPathLinkForwardX = pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float currentPathLinkForwardY = pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
|
||||
float nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
|
||||
CVector positionOnCurrentLinkIncludingLane(
|
||||
pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
|
||||
pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
|
||||
pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
|
||||
pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
|
||||
0.0f);
|
||||
CVector positionOnNextLinkIncludingLane(
|
||||
pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
|
||||
pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
|
||||
pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
|
||||
pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
|
||||
0.0f);
|
||||
CVector directionCurrentLink(currentPathLinkForwardX, currentPathLinkForwardY, 0.0f);
|
||||
CVector directionNextLink(nextPathLinkForwardX, nextPathLinkForwardY, 0.0f);
|
||||
@ -1553,8 +1553,8 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
|
||||
pVehicle->AutoPilot.m_nNextDirection = -1;
|
||||
lanesOnNextNode = pNextLink->numRightLanes;
|
||||
}
|
||||
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirX;
|
||||
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirX;
|
||||
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x;
|
||||
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x;
|
||||
if (lanesOnNextNode >= 0){
|
||||
if ((CGeneral::GetRandomNumber() & 0x600) == 0){
|
||||
/* 25% chance vehicle will try to switch lane */
|
||||
@ -1574,17 +1574,17 @@ void CCarCtrl::PickNextNodeRandomly(CVehicle* pVehicle)
|
||||
if (pVehicle->AutoPilot.m_bStayInFastLane)
|
||||
pVehicle->AutoPilot.m_nNextLane = 0;
|
||||
CVector positionOnCurrentLinkIncludingLane(
|
||||
pCurLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH), /* ...what about Y? */
|
||||
pCurLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
|
||||
pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH), /* ...what about Y? */
|
||||
pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
|
||||
0.0f);
|
||||
CVector positionOnNextLinkIncludingLane(
|
||||
pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH),
|
||||
pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
|
||||
pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH),
|
||||
pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
|
||||
0.0f);
|
||||
float directionCurrentLinkX = pCurLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float directionCurrentLinkY = pCurLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float directionNextLinkX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection;
|
||||
float directionNextLinkY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection;
|
||||
float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
|
||||
float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
|
||||
/* We want to make a path between two links that may not have the same forward directions a curve. */
|
||||
pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
|
||||
&positionOnCurrentLinkIncludingLane,
|
||||
@ -1725,10 +1725,10 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
|
||||
pVehicle->AutoPilot.m_nNextDirection = -1;
|
||||
lanesOnNextNode = pNextLink->numRightLanes;
|
||||
}
|
||||
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirX;
|
||||
float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirY;
|
||||
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirX;
|
||||
float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirY;
|
||||
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x;
|
||||
float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.y;
|
||||
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x;
|
||||
float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.y;
|
||||
if (lanesOnNextNode >= 0) {
|
||||
CVector2D dist = pNextPathNode->pos - pCurNode->pos;
|
||||
if (dist.MagnitudeSqr() >= SQR(7.0f)){
|
||||
@ -1755,17 +1755,17 @@ void CCarCtrl::PickNextNodeToChaseCar(CVehicle* pVehicle, float targetX, float t
|
||||
if (pVehicle->AutoPilot.m_bStayInFastLane)
|
||||
pVehicle->AutoPilot.m_nNextLane = 0;
|
||||
CVector positionOnCurrentLinkIncludingLane(
|
||||
pCurLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
|
||||
pCurLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
|
||||
pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
|
||||
pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
|
||||
0.0f);
|
||||
CVector positionOnNextLinkIncludingLane(
|
||||
pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
|
||||
pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
|
||||
pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
|
||||
pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
|
||||
0.0f);
|
||||
float directionCurrentLinkX = pCurLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float directionCurrentLinkY = pCurLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float directionNextLinkX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection;
|
||||
float directionNextLinkY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection;
|
||||
float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
|
||||
float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
|
||||
/* We want to make a path between two links that may not have the same forward directions a curve. */
|
||||
pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
|
||||
&positionOnCurrentLinkIncludingLane,
|
||||
@ -1814,10 +1814,10 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)
|
||||
pVehicle->AutoPilot.m_nNextDirection = -1;
|
||||
lanesOnNextNode = pNextLink->numRightLanes;
|
||||
}
|
||||
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirX;
|
||||
float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dirY;
|
||||
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirX;
|
||||
float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dirY;
|
||||
float currentPathLinkForwardX = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.x;
|
||||
float currentPathLinkForwardY = pVehicle->AutoPilot.m_nCurrentDirection * pCurLink->dir.y;
|
||||
float nextPathLinkForwardX = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.x;
|
||||
float nextPathLinkForwardY = pVehicle->AutoPilot.m_nNextDirection * pNextLink->dir.y;
|
||||
if (lanesOnNextNode >= 0) {
|
||||
CVector2D dist = pNextPathNode->pos - pCurNode->pos;
|
||||
if (dist.MagnitudeSqr() >= SQR(7.0f) && (CGeneral::GetRandomNumber() & 0x600) == 0) {
|
||||
@ -1835,17 +1835,17 @@ bool CCarCtrl::PickNextNodeToFollowPath(CVehicle* pVehicle)
|
||||
if (pVehicle->AutoPilot.m_bStayInFastLane)
|
||||
pVehicle->AutoPilot.m_nNextLane = 0;
|
||||
CVector positionOnCurrentLinkIncludingLane(
|
||||
pCurLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
|
||||
pCurLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
|
||||
pCurLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardY,
|
||||
pCurLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForwardX,
|
||||
0.0f);
|
||||
CVector positionOnNextLinkIncludingLane(
|
||||
pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
|
||||
pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
|
||||
pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
|
||||
pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX,
|
||||
0.0f);
|
||||
float directionCurrentLinkX = pCurLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float directionCurrentLinkY = pCurLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float directionNextLinkX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection;
|
||||
float directionNextLinkY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection;
|
||||
float directionCurrentLinkX = pCurLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float directionCurrentLinkY = pCurLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
float directionNextLinkX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
|
||||
float directionNextLinkY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
|
||||
/* We want to make a path between two links that may not have the same forward directions a curve. */
|
||||
pVehicle->AutoPilot.m_nTimeToSpendOnCurrentCurve = CCurves::CalcSpeedScaleFactor(
|
||||
&positionOnCurrentLinkIncludingLane,
|
||||
@ -2192,16 +2192,16 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
|
||||
forward.Normalise();
|
||||
CCarPathLink* pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
|
||||
CCarPathLink* pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
|
||||
CVector2D currentPathLinkForward(pCurrentLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection,
|
||||
pCurrentLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection);
|
||||
float nextPathLinkForwardX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection;
|
||||
float nextPathLinkForwardY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection;
|
||||
CVector2D currentPathLinkForward(pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection,
|
||||
pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection);
|
||||
float nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
|
||||
float nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
|
||||
CVector2D positionOnCurrentLinkIncludingLane(
|
||||
pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y,
|
||||
pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x);
|
||||
pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y,
|
||||
pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x);
|
||||
CVector2D positionOnNextLinkIncludingLane(
|
||||
pNextLink->posX + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
|
||||
pNextLink->posY - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX);
|
||||
pNextLink->pos.x + ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardY,
|
||||
pNextLink->pos.y - ((pVehicle->AutoPilot.m_nNextLane + pNextLink->OneWayLaneOffset()) * LANE_WIDTH) * nextPathLinkForwardX);
|
||||
CVector2D distanceToNextNode = (CVector2D)pVehicle->GetPosition() - positionOnCurrentLinkIncludingLane;
|
||||
float scalarDistanceToNextNode = distanceToNextNode.Magnitude();
|
||||
CVector2D distanceBetweenNodes = positionOnNextLinkIncludingLane - positionOnCurrentLinkIncludingLane;
|
||||
@ -2230,16 +2230,16 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
|
||||
}
|
||||
pCurrentLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nCurrentPathNodeInfo];
|
||||
scalarDistanceToNextNode = CVector2D(
|
||||
pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y - pVehicle->GetPosition().x,
|
||||
pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x - pVehicle->GetPosition().y).Magnitude();
|
||||
pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y - pVehicle->GetPosition().x,
|
||||
pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x - pVehicle->GetPosition().y).Magnitude();
|
||||
pNextLink = &ThePaths.m_carPathLinks[pVehicle->AutoPilot.m_nNextPathNodeInfo];
|
||||
currentPathLinkForward.x = pCurrentLink->dirX * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
currentPathLinkForward.y = pCurrentLink->dirY * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
nextPathLinkForwardX = pNextLink->dirX * pVehicle->AutoPilot.m_nNextDirection;
|
||||
nextPathLinkForwardY = pNextLink->dirY * pVehicle->AutoPilot.m_nNextDirection;
|
||||
currentPathLinkForward.x = pCurrentLink->dir.x * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
currentPathLinkForward.y = pCurrentLink->dir.y * pVehicle->AutoPilot.m_nCurrentDirection;
|
||||
nextPathLinkForwardX = pNextLink->dir.x * pVehicle->AutoPilot.m_nNextDirection;
|
||||
nextPathLinkForwardY = pNextLink->dir.y * pVehicle->AutoPilot.m_nNextDirection;
|
||||
}
|
||||
positionOnCurrentLinkIncludingLane.x = pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y;
|
||||
positionOnCurrentLinkIncludingLane.y = pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x;
|
||||
positionOnCurrentLinkIncludingLane.x = pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y;
|
||||
positionOnCurrentLinkIncludingLane.y = pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x;
|
||||
CVector2D projectedPosition = positionOnCurrentLinkIncludingLane - currentPathLinkForward * scalarDistanceToNextNode * 0.4f;
|
||||
if (scalarDistanceToNextNode > DISTANCE_TO_NEXT_NODE_TO_CONSIDER_SLOWING_DOWN){
|
||||
projectedPosition.x = positionOnCurrentLinkIncludingLane.x;
|
||||
@ -2281,8 +2281,8 @@ void CCarCtrl::SteerAICarWithPhysicsFollowPath(CVehicle* pVehicle, float* pSwerv
|
||||
CCarAI::CarHasReasonToStop(pVehicle);
|
||||
speedStyleMultiplier = 0.0f;
|
||||
}
|
||||
CVector2D trajectory(pCurrentLink->posX + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y,
|
||||
pCurrentLink->posY - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x);
|
||||
CVector2D trajectory(pCurrentLink->pos.x + ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.y,
|
||||
pCurrentLink->pos.y - ((pVehicle->AutoPilot.m_nCurrentLane + pCurrentLink->OneWayLaneOffset()) * LANE_WIDTH) * currentPathLinkForward.x);
|
||||
trajectory -= pVehicle->GetPosition();
|
||||
float speedAngleMultiplier = FindSpeedMultiplier(
|
||||
CGeneral::GetATanOfXY(trajectory.x, trajectory.y) - angleForward,
|
||||
|
@ -1,312 +0,0 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "CarGen.h"
|
||||
|
||||
#include "Automobile.h"
|
||||
#include "Boat.h"
|
||||
#include "Camera.h"
|
||||
#include "CarCtrl.h"
|
||||
#include "CutsceneMgr.h"
|
||||
#include "General.h"
|
||||
#include "Pools.h"
|
||||
#include "Streaming.h"
|
||||
#include "Timer.h"
|
||||
#include "Vehicle.h"
|
||||
#include "World.h"
|
||||
|
||||
uint8 &CTheCarGenerators::ProcessCounter = *(uint8*)0x95CDAF;
|
||||
uint32 &CTheCarGenerators::NumOfCarGenerators = *(uint32*)0x8E2C1C;
|
||||
CCarGenerator (&CTheCarGenerators::CarGeneratorArray)[NUM_CARGENS] = *(CCarGenerator(*)[NUM_CARGENS])*(uintptr*)0x87CB18;
|
||||
uint8 &CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter = *(uint8*)0x95CDC6;
|
||||
uint32 &CTheCarGenerators::CurrentActiveCount = *(uint32*)0x8F2C5C;
|
||||
|
||||
void CCarGenerator::SwitchOff()
|
||||
{
|
||||
m_nUsesRemaining = 0;
|
||||
--CTheCarGenerators::CurrentActiveCount;
|
||||
}
|
||||
|
||||
void CCarGenerator::SwitchOn()
|
||||
{
|
||||
m_nUsesRemaining = -1;
|
||||
m_nTimer = CalcNextGen();
|
||||
++CTheCarGenerators::CurrentActiveCount;
|
||||
}
|
||||
|
||||
uint32 CCarGenerator::CalcNextGen()
|
||||
{
|
||||
return CTimer::GetTimeInMilliseconds() + 4;
|
||||
}
|
||||
|
||||
void CCarGenerator::DoInternalProcessing()
|
||||
{
|
||||
if (CheckForBlockage()) {
|
||||
m_nTimer += 4;
|
||||
if (m_nUsesRemaining == 0)
|
||||
--CTheCarGenerators::CurrentActiveCount;
|
||||
return;
|
||||
}
|
||||
if (CCarCtrl::NumParkedCars >= 10)
|
||||
return;
|
||||
CStreaming::RequestModel(m_nModelIndex, STREAMFLAGS_DEPENDENCY);
|
||||
if (!CStreaming::HasModelLoaded(m_nModelIndex))
|
||||
return;
|
||||
if (CModelInfo::IsBoatModel(m_nModelIndex)){
|
||||
CBoat* pBoat = new CBoat(m_nModelIndex, PARKED_VEHICLE);
|
||||
pBoat->bIsStatic = false;
|
||||
pBoat->bEngineOn = false;
|
||||
CVector pos = m_vecPos;
|
||||
if (pos.z <= -100.0f)
|
||||
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
|
||||
pos.z += pBoat->GetDistanceFromCentreOfMassToBaseOfModel();
|
||||
pBoat->GetPosition() = pos;
|
||||
pBoat->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle));
|
||||
pBoat->m_status = STATUS_ABANDONED;
|
||||
pBoat->m_nDoorLock = CARLOCK_UNLOCKED;
|
||||
CWorld::Add(pBoat);
|
||||
if (CGeneral::GetRandomNumberInRange(0, 100) < m_nAlarm)
|
||||
pBoat->m_nAlarmState = -1;
|
||||
if (CGeneral::GetRandomNumberInRange(0, 100) < m_nDoorlock)
|
||||
pBoat->m_nDoorLock = CARLOCK_LOCKED;
|
||||
if (m_nColor1 != -1 && m_nColor2){
|
||||
pBoat->m_currentColour1 = m_nColor1;
|
||||
pBoat->m_currentColour2 = m_nColor2;
|
||||
}
|
||||
m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pBoat);
|
||||
}else{
|
||||
bool groundFound = false;
|
||||
CVector pos = m_vecPos;
|
||||
if (pos.z > -100.0f){
|
||||
pos.z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, pos.z, &groundFound);
|
||||
}else{
|
||||
CColPoint cp;
|
||||
CEntity* pEntity;
|
||||
groundFound = CWorld::ProcessVerticalLine(CVector(pos.x, pos.y, 1000.0f), -1000.0f,
|
||||
cp, pEntity, true, false, false, false, false, false, nil);
|
||||
if (groundFound)
|
||||
pos.z = cp.point.z;
|
||||
}
|
||||
if (!groundFound) {
|
||||
debug("CCarGenerator::DoInternalProcessing - can't find ground z for new car x = %f y = %f \n", m_vecPos.x, m_vecPos.y);
|
||||
}else{
|
||||
CAutomobile* pCar = new CAutomobile(m_nModelIndex, PARKED_VEHICLE);
|
||||
pCar->bIsStatic = false;
|
||||
pCar->bEngineOn = false;
|
||||
pos.z += pCar->GetDistanceFromCentreOfMassToBaseOfModel();
|
||||
pCar->GetPosition() = pos;
|
||||
pCar->SetOrientation(0.0f, 0.0f, DEGTORAD(m_fAngle));
|
||||
pCar->m_status = STATUS_ABANDONED;
|
||||
pCar->bLightsOn = false;
|
||||
pCar->m_nDoorLock = CARLOCK_UNLOCKED;
|
||||
CWorld::Add(pCar);
|
||||
if (CGeneral::GetRandomNumberInRange(0, 100) < m_nAlarm)
|
||||
pCar->m_nAlarmState = -1;
|
||||
if (CGeneral::GetRandomNumberInRange(0, 100) < m_nDoorlock)
|
||||
pCar->m_nDoorLock = CARLOCK_LOCKED;
|
||||
if (m_nColor1 != -1 && m_nColor2) {
|
||||
pCar->m_currentColour1 = m_nColor1;
|
||||
pCar->m_currentColour2 = m_nColor2;
|
||||
}
|
||||
m_nVehicleHandle = CPools::GetVehiclePool()->GetIndex(pCar);
|
||||
}
|
||||
}
|
||||
if (m_nUsesRemaining < -1) /* I don't think this is a correct comparasion */
|
||||
--m_nUsesRemaining;
|
||||
m_nTimer = CalcNextGen();
|
||||
if (m_nUsesRemaining == 0)
|
||||
--CTheCarGenerators::CurrentActiveCount;
|
||||
}
|
||||
|
||||
void CCarGenerator::Process()
|
||||
{
|
||||
if (m_nVehicleHandle == -1 &&
|
||||
(CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter || CTimer::GetTimeInMilliseconds() >= m_nTimer) &&
|
||||
m_nUsesRemaining != 0 && CheckIfWithinRangeOfAnyPlayer())
|
||||
DoInternalProcessing();
|
||||
if (m_nVehicleHandle == -1)
|
||||
return;
|
||||
CVehicle* pVehicle = CPools::GetVehiclePool()->GetAt(m_nVehicleHandle);
|
||||
if (!pVehicle){
|
||||
m_nVehicleHandle = -1;
|
||||
return;
|
||||
}
|
||||
if (pVehicle->m_status != STATUS_PLAYER)
|
||||
return;
|
||||
m_nTimer += 60000;
|
||||
m_nVehicleHandle = -1;
|
||||
m_bIsBlocking = true;
|
||||
pVehicle->bExtendedRange = false;
|
||||
}
|
||||
|
||||
void CCarGenerator::Setup(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay)
|
||||
{
|
||||
CMatrix m1, m2, m3; /* Unused but present on stack, so I'll leave them. */
|
||||
m_vecPos = CVector(x, y, z);
|
||||
m_fAngle = angle;
|
||||
m_nModelIndex = mi;
|
||||
m_nColor1 = color1;
|
||||
m_nColor2 = color2;
|
||||
m_bForceSpawn = force;
|
||||
m_nAlarm = alarm;
|
||||
m_nDoorlock = lock;
|
||||
m_nMinDelay = min_delay;
|
||||
m_nMaxDelay = max_delay;
|
||||
m_nVehicleHandle = -1;
|
||||
m_nTimer = CTimer::GetTimeInMilliseconds() + 1;
|
||||
m_nUsesRemaining = 0;
|
||||
m_bIsBlocking = false;
|
||||
m_vecInf = CModelInfo::GetModelInfo(m_nModelIndex)->GetColModel()->boundingBox.min;
|
||||
m_vecSup = CModelInfo::GetModelInfo(m_nModelIndex)->GetColModel()->boundingBox.max;
|
||||
m_fSize = max(m_vecInf.Magnitude(), m_vecSup.Magnitude());
|
||||
}
|
||||
|
||||
bool CCarGenerator::CheckForBlockage()
|
||||
{
|
||||
int16 entities;
|
||||
CWorld::FindObjectsKindaColliding(CVector(m_vecPos), m_fSize, 1, &entities, 2, nil, false, true, true, false, false);
|
||||
return entities > 0;
|
||||
}
|
||||
|
||||
bool CCarGenerator::CheckIfWithinRangeOfAnyPlayer()
|
||||
{
|
||||
CVector2D direction = FindPlayerCentreOfWorld(CWorld::PlayerInFocus) - m_vecPos;
|
||||
float distance = direction.Magnitude();
|
||||
float farclip = 120.0f * TheCamera.GenerationDistMultiplier;
|
||||
float nearclip = farclip - 20.0f;
|
||||
if (distance >= farclip){
|
||||
if (m_bIsBlocking)
|
||||
m_bIsBlocking = false;
|
||||
return false;
|
||||
}
|
||||
if (CTheCarGenerators::GenerateEvenIfPlayerIsCloseCounter)
|
||||
return true;
|
||||
if (m_bIsBlocking)
|
||||
return false;
|
||||
if (distance < nearclip)
|
||||
return false;
|
||||
return DotProduct2D(direction, FindPlayerSpeed()) <= 0;
|
||||
}
|
||||
|
||||
void CCarGenerator::Save(uint8 *&buffer)
|
||||
{
|
||||
WriteSaveBuf(buffer, m_nModelIndex);
|
||||
WriteSaveBuf(buffer, m_vecPos);
|
||||
WriteSaveBuf(buffer, m_fAngle);
|
||||
WriteSaveBuf(buffer, m_nColor1);
|
||||
WriteSaveBuf(buffer, m_nColor2);
|
||||
WriteSaveBuf(buffer, m_bForceSpawn);
|
||||
WriteSaveBuf(buffer, m_nAlarm);
|
||||
WriteSaveBuf(buffer, m_nDoorlock);
|
||||
WriteSaveBuf(buffer, (uint8)0);
|
||||
WriteSaveBuf(buffer, m_nMinDelay);
|
||||
WriteSaveBuf(buffer, m_nMaxDelay);
|
||||
WriteSaveBuf(buffer, m_nTimer);
|
||||
WriteSaveBuf(buffer, m_nVehicleHandle);
|
||||
WriteSaveBuf(buffer, m_nUsesRemaining);
|
||||
WriteSaveBuf(buffer, m_bIsBlocking);
|
||||
WriteSaveBuf(buffer, (uint8)0);
|
||||
WriteSaveBuf(buffer, m_vecInf);
|
||||
WriteSaveBuf(buffer, m_vecSup);
|
||||
WriteSaveBuf(buffer, m_fSize);
|
||||
|
||||
// or
|
||||
//WriteSaveBuf(buffer, *this);
|
||||
|
||||
}
|
||||
|
||||
void CCarGenerator::Load(uint8 *&buffer)
|
||||
{
|
||||
m_nModelIndex = ReadSaveBuf<uint32>(buffer);
|
||||
m_vecPos = ReadSaveBuf<CVector>(buffer);
|
||||
m_fAngle = ReadSaveBuf<float>(buffer);
|
||||
m_nColor1 = ReadSaveBuf<int16>(buffer);
|
||||
m_nColor2 = ReadSaveBuf<int16>(buffer);
|
||||
m_bForceSpawn = ReadSaveBuf<uint8>(buffer);
|
||||
m_nAlarm = ReadSaveBuf<uint8>(buffer);
|
||||
m_nDoorlock = ReadSaveBuf<uint8>(buffer);
|
||||
ReadSaveBuf<uint8>(buffer);
|
||||
m_nMinDelay = ReadSaveBuf<uint16>(buffer);
|
||||
m_nMaxDelay = ReadSaveBuf<uint16>(buffer);
|
||||
m_nTimer = ReadSaveBuf<uint32>(buffer);
|
||||
m_nVehicleHandle = ReadSaveBuf<int32>(buffer);
|
||||
m_nUsesRemaining = ReadSaveBuf<uint16>(buffer);
|
||||
m_bIsBlocking = ReadSaveBuf<bool>(buffer);
|
||||
ReadSaveBuf<uint8>(buffer);
|
||||
m_vecInf = ReadSaveBuf<CVector>(buffer);
|
||||
m_vecSup = ReadSaveBuf<CVector>(buffer);
|
||||
m_fSize = ReadSaveBuf<float>(buffer);
|
||||
|
||||
// or
|
||||
//*this = ReadSaveBuf<CCarGenerator>(buffer);
|
||||
}
|
||||
|
||||
void CTheCarGenerators::Process()
|
||||
{
|
||||
if (FindPlayerTrain() || CCutsceneMgr::IsRunning())
|
||||
return;
|
||||
if (++CTheCarGenerators::ProcessCounter == 4)
|
||||
CTheCarGenerators::ProcessCounter = 0;
|
||||
for (uint32 i = ProcessCounter; i < NumOfCarGenerators; i += 4)
|
||||
CTheCarGenerators::CarGeneratorArray[i].Process();
|
||||
if (GenerateEvenIfPlayerIsCloseCounter)
|
||||
GenerateEvenIfPlayerIsCloseCounter--;
|
||||
}
|
||||
|
||||
int32 CTheCarGenerators::CreateCarGenerator(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay)
|
||||
{
|
||||
CarGeneratorArray[NumOfCarGenerators].Setup(x, y, z, angle, mi, color1, color2, force, alarm, lock, min_delay, max_delay);
|
||||
return NumOfCarGenerators++;
|
||||
}
|
||||
|
||||
void CTheCarGenerators::Init()
|
||||
{
|
||||
GenerateEvenIfPlayerIsCloseCounter = 0;
|
||||
NumOfCarGenerators = 0;
|
||||
ProcessCounter = 0;
|
||||
CurrentActiveCount = 0;
|
||||
}
|
||||
|
||||
void CTheCarGenerators::SaveAllCarGenerators(uint8 *buffer, uint32 *size)
|
||||
{
|
||||
*size = 20 + sizeof(CarGeneratorArray) + SAVE_HEADER_SIZE;
|
||||
INITSAVEBUF
|
||||
WriteSaveHeader(buffer, 'C','G','N','\0', *size - SAVE_HEADER_SIZE);
|
||||
|
||||
WriteSaveBuf(buffer, 12); /* what is this? */
|
||||
WriteSaveBuf(buffer, NumOfCarGenerators);
|
||||
WriteSaveBuf(buffer, CurrentActiveCount);
|
||||
WriteSaveBuf(buffer, ProcessCounter);
|
||||
WriteSaveBuf(buffer, GenerateEvenIfPlayerIsCloseCounter);
|
||||
WriteSaveBuf(buffer, (int16)0);
|
||||
WriteSaveBuf(buffer, sizeof(CarGeneratorArray));
|
||||
for (int i = 0; i < NUM_CARGENS; i++){
|
||||
CarGeneratorArray[i].Save(buffer);
|
||||
}
|
||||
VALIDATESAVEBUF(*size)
|
||||
}
|
||||
|
||||
void CTheCarGenerators::LoadAllCarGenerators(uint8* buffer, uint32 size)
|
||||
{
|
||||
Init();
|
||||
INITSAVEBUF
|
||||
assert(size == 20 + sizeof(CarGeneratorArray) + SAVE_HEADER_SIZE);
|
||||
CheckSaveHeader(buffer, 'C','G','N','\0', size - SAVE_HEADER_SIZE);
|
||||
ReadSaveBuf<uint32>(buffer);
|
||||
NumOfCarGenerators = ReadSaveBuf<uint32>(buffer);
|
||||
CurrentActiveCount = ReadSaveBuf<uint32>(buffer);
|
||||
ProcessCounter = ReadSaveBuf<uint8>(buffer);
|
||||
GenerateEvenIfPlayerIsCloseCounter = ReadSaveBuf<uint8>(buffer);
|
||||
ReadSaveBuf<int16>(buffer);
|
||||
assert(ReadSaveBuf<uint32>(buffer) == sizeof(CarGeneratorArray));
|
||||
for (int i = 0; i < NUM_CARGENS; i++) {
|
||||
CarGeneratorArray[i].Load(buffer);
|
||||
}
|
||||
VALIDATESAVEBUF(size)
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x543020, CTheCarGenerators::Init, PATCH_JUMP);
|
||||
InjectHook(0x542F40, CTheCarGenerators::Process, PATCH_JUMP);
|
||||
InjectHook(0x543050, CTheCarGenerators::SaveAllCarGenerators, PATCH_JUMP);
|
||||
InjectHook(0x5431E0, CTheCarGenerators::LoadAllCarGenerators, PATCH_JUMP);
|
||||
ENDPATCHES
|
@ -1,56 +0,0 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
#include "config.h"
|
||||
|
||||
enum {
|
||||
CARGEN_MAXACTUALLIMIT = 100
|
||||
};
|
||||
|
||||
class CCarGenerator
|
||||
{
|
||||
int32 m_nModelIndex;
|
||||
CVector m_vecPos;
|
||||
float m_fAngle;
|
||||
int16 m_nColor1;
|
||||
int16 m_nColor2;
|
||||
uint8 m_bForceSpawn;
|
||||
uint8 m_nAlarm;
|
||||
uint8 m_nDoorlock;
|
||||
int16 m_nMinDelay;
|
||||
int16 m_nMaxDelay;
|
||||
uint32 m_nTimer;
|
||||
int32 m_nVehicleHandle;
|
||||
uint16 m_nUsesRemaining;
|
||||
bool m_bIsBlocking;
|
||||
CVector m_vecInf;
|
||||
CVector m_vecSup;
|
||||
float m_fSize;
|
||||
public:
|
||||
void SwitchOff();
|
||||
void SwitchOn();
|
||||
uint32 CalcNextGen();
|
||||
void DoInternalProcessing();
|
||||
void Process();
|
||||
void Setup(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay);
|
||||
bool CheckForBlockage();
|
||||
bool CheckIfWithinRangeOfAnyPlayer();
|
||||
void Save(uint8*&);
|
||||
void Load(uint8*&);
|
||||
void SetUsesRemaining(uint16 uses) { m_nUsesRemaining = uses; }
|
||||
};
|
||||
|
||||
class CTheCarGenerators
|
||||
{
|
||||
public:
|
||||
static uint8 &ProcessCounter;
|
||||
static uint32 &NumOfCarGenerators;
|
||||
static CCarGenerator (&CarGeneratorArray)[NUM_CARGENS];
|
||||
static uint8 &GenerateEvenIfPlayerIsCloseCounter;
|
||||
static uint32 &CurrentActiveCount;
|
||||
|
||||
static void Process();
|
||||
static int32 CreateCarGenerator(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay);
|
||||
static void Init();
|
||||
static void SaveAllCarGenerators(uint8 *, uint32 *);
|
||||
static void LoadAllCarGenerators(uint8 *, uint32);
|
||||
};
|
@ -1,14 +0,0 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Cranes.h"
|
||||
|
||||
WRAPPER bool CCranes::IsThisCarBeingTargettedByAnyCrane(CVehicle*) { EAXJMP(0x5451E0); }
|
||||
WRAPPER bool CCranes::IsThisCarBeingCarriedByAnyCrane(CVehicle*) { EAXJMP(0x545190); }
|
||||
WRAPPER bool CCranes::IsThisCarPickedUp(float, float, CVehicle*) { EAXJMP(0x543940); }
|
||||
WRAPPER bool CCranes::HaveAllCarsBeenCollectedByMilitaryCrane() { EAXJMP(0x544BE0); }
|
||||
WRAPPER void CCranes::ActivateCrane(float, float, float, float, float, float, float, float, bool, bool, float, float) { EAXJMP(0x543650); }
|
||||
WRAPPER void CCranes::DeActivateCrane(float, float) { EAXJMP(0x543890); }
|
||||
WRAPPER void CCranes::InitCranes(void) { EAXJMP(0x543360); }
|
||||
WRAPPER void CCranes::UpdateCranes(void) { EAXJMP(0x5439E0); }
|
||||
WRAPPER void CCranes::Save(uint8*, uint32*) { EAXJMP(0x545210); }
|
||||
WRAPPER void CranesLoad(uint8*, uint32) { EAXJMP(0x5454d0); }
|
@ -1,61 +0,0 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
|
||||
class CVehicle;
|
||||
class CEntity;
|
||||
class CObject;
|
||||
|
||||
class CCrane
|
||||
{
|
||||
public:
|
||||
CEntity *m_pObject;
|
||||
CObject *m_pMagnet;
|
||||
int m_nAudioEntity;
|
||||
float m_fPickupX1;
|
||||
float m_fPickupX2;
|
||||
float m_fPickupY1;
|
||||
float m_fPickupY2;
|
||||
CVector m_vecDropoffTarget;
|
||||
float m_fDropoffHeading;
|
||||
float m_fPickupAngle;
|
||||
float m_fDropoffAngle;
|
||||
float m_fPickupDistance;
|
||||
float m_fDropoffDistance;
|
||||
float m_fAngle;
|
||||
float m_fDistance;
|
||||
float m_fHeight;
|
||||
float m_fHookOffset;
|
||||
float m_fHookHeight;
|
||||
CVector m_vecHookInitPos;
|
||||
CVector m_vecHookCurPos;
|
||||
float m_fHookVelocityX;
|
||||
float m_fHookVelocityY;
|
||||
CVehicle *m_pVehiclePickedUp;
|
||||
int m_nUpdateTimer;
|
||||
char m_bCraneActive;
|
||||
char m_bCraneStatus;
|
||||
char m_bVehiclesCollected;
|
||||
char m_bIsCrusher;
|
||||
char m_bIsMilitaryCrane;
|
||||
char field_125;
|
||||
char m_bNotMilitaryCrane;
|
||||
char gap_127[1];
|
||||
};
|
||||
|
||||
static_assert(sizeof(CCrane) == 128, "CCrane: error");
|
||||
|
||||
class CCranes
|
||||
{
|
||||
public:
|
||||
static bool IsThisCarBeingTargettedByAnyCrane(CVehicle*);
|
||||
static bool IsThisCarBeingCarriedByAnyCrane(CVehicle*);
|
||||
static bool IsThisCarPickedUp(float, float, CVehicle*);
|
||||
static bool HaveAllCarsBeenCollectedByMilitaryCrane();
|
||||
static void ActivateCrane(float, float, float, float, float, float, float, float, bool, bool, float, float);
|
||||
static void DeActivateCrane(float, float);
|
||||
static void InitCranes(void);
|
||||
static void UpdateCranes(void);
|
||||
static void Save(uint8*, uint32*);
|
||||
};
|
||||
|
||||
void CranesLoad(uint8*, uint32); // is this really outside CCranes?
|
@ -1,294 +1,294 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "GameLogic.h"
|
||||
#include "Clock.h"
|
||||
#include "Stats.h"
|
||||
#include "Pickups.h"
|
||||
#include "Timer.h"
|
||||
#include "Streaming.h"
|
||||
#include "CutsceneMgr.h"
|
||||
#include "World.h"
|
||||
#include "PlayerPed.h"
|
||||
#include "Wanted.h"
|
||||
#include "Camera.h"
|
||||
#include "Messages.h"
|
||||
#include "CarCtrl.h"
|
||||
#include "Restart.h"
|
||||
#include "Pad.h"
|
||||
#include "References.h"
|
||||
#include "Fire.h"
|
||||
#include "Script.h"
|
||||
#include "Garages.h"
|
||||
|
||||
uint8 CGameLogic::ActivePlayers; // 0x95CD5E
|
||||
|
||||
void
|
||||
CGameLogic::InitAtStartOfGame()
|
||||
{
|
||||
ActivePlayers = 1;
|
||||
}
|
||||
|
||||
void
|
||||
CGameLogic::PassTime(uint32 time)
|
||||
{
|
||||
int32 minutes, hours, days;
|
||||
|
||||
minutes = time + CClock::GetMinutes();
|
||||
hours = CClock::GetHours();
|
||||
|
||||
for (; minutes >= 60; minutes -= 60)
|
||||
hours++;
|
||||
|
||||
if (hours > 23) {
|
||||
days = CStats::DaysPassed;
|
||||
for (; hours >= 24; hours -= 24)
|
||||
days++;
|
||||
CStats::DaysPassed = days;
|
||||
}
|
||||
|
||||
CClock::SetGameClock(hours, minutes);
|
||||
CPickups::PassTime(time * 1000);
|
||||
}
|
||||
|
||||
void
|
||||
CGameLogic::SortOutStreamingAndMemory(const CVector &pos)
|
||||
{
|
||||
CTimer::Stop();
|
||||
CStreaming::FlushRequestList();
|
||||
CStreaming::DeleteRwObjectsAfterDeath(pos);
|
||||
CStreaming::RemoveUnusedModelsInLoadedList();
|
||||
CGame::DrasticTidyUpMemory(true);
|
||||
CStreaming::LoadScene(pos);
|
||||
CTimer::Update();
|
||||
}
|
||||
|
||||
void
|
||||
CGameLogic::Update()
|
||||
{
|
||||
CVector vecRestartPos;
|
||||
float fRestartFloat;
|
||||
|
||||
if (CCutsceneMgr::IsCutsceneProcessing()) return;
|
||||
|
||||
CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus];
|
||||
switch (pPlayerInfo.m_WBState) {
|
||||
case WBSTATE_PLAYING:
|
||||
if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) {
|
||||
pPlayerInfo.m_pPed->ClearAdrenaline();
|
||||
pPlayerInfo.KillPlayer();
|
||||
}
|
||||
if (pPlayerInfo.m_pPed->m_nPedState == PED_ARRESTED) {
|
||||
pPlayerInfo.m_pPed->ClearAdrenaline();
|
||||
pPlayerInfo.ArrestPlayer();
|
||||
}
|
||||
break;
|
||||
case WBSTATE_WASTED:
|
||||
if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
|
||||
TheCamera.SetFadeColour(200, 200, 200);
|
||||
TheCamera.Fade(2.0f, FADE_OUT);
|
||||
}
|
||||
|
||||
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
|
||||
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
|
||||
if (pPlayerInfo.m_bGetOutOfHospitalFree) {
|
||||
pPlayerInfo.m_bGetOutOfHospitalFree = false;
|
||||
} else {
|
||||
pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - 1000);
|
||||
pPlayerInfo.m_pPed->ClearWeapons();
|
||||
}
|
||||
|
||||
if (pPlayerInfo.m_pPed->bInVehicle) {
|
||||
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
|
||||
if (pVehicle != nil) {
|
||||
if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
|
||||
pVehicle->pDriver = nil;
|
||||
if (pVehicle->m_status != STATUS_WRECKED)
|
||||
pVehicle->m_status = STATUS_ABANDONED;
|
||||
} else
|
||||
pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
|
||||
}
|
||||
}
|
||||
CEventList::Initialise();
|
||||
CMessages::ClearMessages();
|
||||
CCarCtrl::ClearInterestingVehicleList();
|
||||
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
|
||||
CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
|
||||
CRestart::OverrideHospitalLevel = LEVEL_NONE;
|
||||
CRestart::OverridePoliceStationLevel = LEVEL_NONE;
|
||||
PassTime(720);
|
||||
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
|
||||
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
|
||||
TheCamera.m_fCamShakeForce = 0.0f;
|
||||
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
|
||||
CPad::GetPad(0)->StopShaking(0);
|
||||
CReferences::RemoveReferencesToPlayer();
|
||||
CCarCtrl::CountDownToCarsAtStart = 2;
|
||||
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
|
||||
if (CRestart::bFadeInAfterNextDeath) {
|
||||
TheCamera.SetFadeColour(200, 200, 200);
|
||||
TheCamera.Fade(4.0f, FADE_IN);
|
||||
} else CRestart::bFadeInAfterNextDeath = true;
|
||||
}
|
||||
break;
|
||||
case WBSTATE_BUSTED:
|
||||
if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
|
||||
TheCamera.SetFadeColour(0, 0, 0);
|
||||
TheCamera.Fade(2.0f, FADE_OUT);
|
||||
}
|
||||
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
|
||||
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
|
||||
int takeMoney;
|
||||
|
||||
switch (pPlayerInfo.m_pPed->m_pWanted->m_nWantedLevel) {
|
||||
case 0:
|
||||
case 1:
|
||||
takeMoney = 100;
|
||||
break;
|
||||
case 2:
|
||||
takeMoney = 200;
|
||||
break;
|
||||
case 3:
|
||||
takeMoney = 400;
|
||||
break;
|
||||
case 4:
|
||||
takeMoney = 600;
|
||||
break;
|
||||
case 5:
|
||||
takeMoney = 900;
|
||||
break;
|
||||
case 6:
|
||||
takeMoney = 1500;
|
||||
break;
|
||||
}
|
||||
if (pPlayerInfo.m_bGetOutOfJailFree) {
|
||||
pPlayerInfo.m_bGetOutOfJailFree = false;
|
||||
} else {
|
||||
pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - takeMoney);
|
||||
pPlayerInfo.m_pPed->ClearWeapons();
|
||||
}
|
||||
|
||||
if (pPlayerInfo.m_pPed->bInVehicle) {
|
||||
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
|
||||
if (pVehicle != nil) {
|
||||
if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
|
||||
pVehicle->pDriver = nil;
|
||||
if (pVehicle->m_status != STATUS_WRECKED)
|
||||
pVehicle->m_status = STATUS_ABANDONED;
|
||||
}
|
||||
else
|
||||
pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
|
||||
}
|
||||
}
|
||||
CEventList::Initialise();
|
||||
CMessages::ClearMessages();
|
||||
CCarCtrl::ClearInterestingVehicleList();
|
||||
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
|
||||
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
|
||||
CRestart::OverrideHospitalLevel = LEVEL_NONE;
|
||||
CRestart::OverridePoliceStationLevel = LEVEL_NONE;
|
||||
PassTime(720);
|
||||
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
|
||||
pPlayerInfo.m_pPed->ClearWeapons();
|
||||
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
|
||||
TheCamera.m_fCamShakeForce = 0.0f;
|
||||
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
|
||||
CPad::GetPad(0)->StopShaking(0);
|
||||
CReferences::RemoveReferencesToPlayer();
|
||||
CCarCtrl::CountDownToCarsAtStart = 2;
|
||||
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
|
||||
if (CRestart::bFadeInAfterNextArrest) {
|
||||
TheCamera.SetFadeColour(0, 0, 0);
|
||||
TheCamera.Fade(4.0f, FADE_IN);
|
||||
} else CRestart::bFadeInAfterNextArrest = true;
|
||||
}
|
||||
break;
|
||||
case WBSTATE_FAILED_CRITICAL_MISSION:
|
||||
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800 && CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800) {
|
||||
TheCamera.SetFadeColour(0, 0, 0);
|
||||
TheCamera.Fade(2.0f, FADE_OUT);
|
||||
}
|
||||
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
|
||||
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
|
||||
if (pPlayerInfo.m_pPed->bInVehicle) {
|
||||
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
|
||||
if (pVehicle != nil) {
|
||||
if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
|
||||
pVehicle->pDriver = nil;
|
||||
if (pVehicle->m_status != STATUS_WRECKED)
|
||||
pVehicle->m_status = STATUS_ABANDONED;
|
||||
} else
|
||||
pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
|
||||
}
|
||||
}
|
||||
CEventList::Initialise();
|
||||
CMessages::ClearMessages();
|
||||
CCarCtrl::ClearInterestingVehicleList();
|
||||
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
|
||||
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
|
||||
CRestart::OverridePoliceStationLevel = LEVEL_NONE;
|
||||
CRestart::OverrideHospitalLevel = LEVEL_NONE;
|
||||
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
|
||||
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
|
||||
TheCamera.m_fCamShakeForce = 0.0f;
|
||||
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
|
||||
CPad::GetPad(0)->StopShaking(0);
|
||||
CReferences::RemoveReferencesToPlayer();
|
||||
CCarCtrl::CountDownToCarsAtStart = 2;
|
||||
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
|
||||
TheCamera.SetFadeColour(0, 0, 0);
|
||||
TheCamera.Fade(4.0f, FADE_IN);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle)
|
||||
{
|
||||
pPlayerPed->m_fHealth = 100.0f;
|
||||
pPlayerPed->m_fArmour = 0.0f;
|
||||
pPlayerPed->bIsVisible = true;
|
||||
pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0;
|
||||
pPlayerPed->bDoBloodyFootprints = false;
|
||||
pPlayerPed->ClearAdrenaline();
|
||||
pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;
|
||||
if (pPlayerPed->m_pFire)
|
||||
pPlayerPed->m_pFire->Extinguish();
|
||||
pPlayerPed->bInVehicle = false;
|
||||
pPlayerPed->m_pMyVehicle = nil;
|
||||
pPlayerPed->m_pVehicleAnim = nil;
|
||||
pPlayerPed->m_pWanted->Reset();
|
||||
pPlayerPed->RestartNonPartialAnims();
|
||||
pPlayerPed->GetPlayerInfoForThisPlayerPed()->MakePlayerSafe(false);
|
||||
pPlayerPed->bRemoveFromWorld = false;
|
||||
pPlayerPed->ClearWeaponTarget();
|
||||
pPlayerPed->SetInitialState();
|
||||
CCarCtrl::ClearInterestingVehicleList();
|
||||
|
||||
pos.z += 1.0f;
|
||||
pPlayerPed->Teleport(pos);
|
||||
pPlayerPed->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f));
|
||||
|
||||
pPlayerPed->m_fRotationCur = DEGTORAD(angle);
|
||||
pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur;
|
||||
pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur);
|
||||
CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed);
|
||||
CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1);
|
||||
pPlayerPed->RestoreHeadingRate();
|
||||
TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
|
||||
CReferences::RemoveReferencesToPlayer();
|
||||
CGarages::PlayerArrestedOrDied();
|
||||
CStats::CheckPointReachedUnsuccessfully();
|
||||
CWorld::Remove(pPlayerPed);
|
||||
CWorld::Add(pPlayerPed);
|
||||
}
|
||||
|
||||
#include "GameLogic.h"
|
||||
#include "Clock.h"
|
||||
#include "Stats.h"
|
||||
#include "Pickups.h"
|
||||
#include "Timer.h"
|
||||
#include "Streaming.h"
|
||||
#include "CutsceneMgr.h"
|
||||
#include "World.h"
|
||||
#include "PlayerPed.h"
|
||||
#include "Wanted.h"
|
||||
#include "Camera.h"
|
||||
#include "Messages.h"
|
||||
#include "CarCtrl.h"
|
||||
#include "Restart.h"
|
||||
#include "Pad.h"
|
||||
#include "References.h"
|
||||
#include "Fire.h"
|
||||
#include "Script.h"
|
||||
#include "Garages.h"
|
||||
|
||||
uint8 CGameLogic::ActivePlayers; // 0x95CD5E
|
||||
|
||||
void
|
||||
CGameLogic::InitAtStartOfGame()
|
||||
{
|
||||
ActivePlayers = 1;
|
||||
}
|
||||
|
||||
void
|
||||
CGameLogic::PassTime(uint32 time)
|
||||
{
|
||||
int32 minutes, hours, days;
|
||||
|
||||
minutes = time + CClock::GetMinutes();
|
||||
hours = CClock::GetHours();
|
||||
|
||||
for (; minutes >= 60; minutes -= 60)
|
||||
hours++;
|
||||
|
||||
if (hours > 23) {
|
||||
days = CStats::DaysPassed;
|
||||
for (; hours >= 24; hours -= 24)
|
||||
days++;
|
||||
CStats::DaysPassed = days;
|
||||
}
|
||||
|
||||
CClock::SetGameClock(hours, minutes);
|
||||
CPickups::PassTime(time * 1000);
|
||||
}
|
||||
|
||||
void
|
||||
CGameLogic::SortOutStreamingAndMemory(const CVector &pos)
|
||||
{
|
||||
CTimer::Stop();
|
||||
CStreaming::FlushRequestList();
|
||||
CStreaming::DeleteRwObjectsAfterDeath(pos);
|
||||
CStreaming::RemoveUnusedModelsInLoadedList();
|
||||
CGame::DrasticTidyUpMemory(true);
|
||||
CStreaming::LoadScene(pos);
|
||||
CTimer::Update();
|
||||
}
|
||||
|
||||
void
|
||||
CGameLogic::Update()
|
||||
{
|
||||
CVector vecRestartPos;
|
||||
float fRestartFloat;
|
||||
|
||||
if (CCutsceneMgr::IsCutsceneProcessing()) return;
|
||||
|
||||
CPlayerInfo &pPlayerInfo = CWorld::Players[CWorld::PlayerInFocus];
|
||||
switch (pPlayerInfo.m_WBState) {
|
||||
case WBSTATE_PLAYING:
|
||||
if (pPlayerInfo.m_pPed->m_nPedState == PED_DEAD) {
|
||||
pPlayerInfo.m_pPed->ClearAdrenaline();
|
||||
pPlayerInfo.KillPlayer();
|
||||
}
|
||||
if (pPlayerInfo.m_pPed->m_nPedState == PED_ARRESTED) {
|
||||
pPlayerInfo.m_pPed->ClearAdrenaline();
|
||||
pPlayerInfo.ArrestPlayer();
|
||||
}
|
||||
break;
|
||||
case WBSTATE_WASTED:
|
||||
if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
|
||||
TheCamera.SetFadeColour(200, 200, 200);
|
||||
TheCamera.Fade(2.0f, FADE_OUT);
|
||||
}
|
||||
|
||||
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
|
||||
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
|
||||
if (pPlayerInfo.m_bGetOutOfHospitalFree) {
|
||||
pPlayerInfo.m_bGetOutOfHospitalFree = false;
|
||||
} else {
|
||||
pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - 1000);
|
||||
pPlayerInfo.m_pPed->ClearWeapons();
|
||||
}
|
||||
|
||||
if (pPlayerInfo.m_pPed->bInVehicle) {
|
||||
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
|
||||
if (pVehicle != nil) {
|
||||
if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
|
||||
pVehicle->pDriver = nil;
|
||||
if (pVehicle->m_status != STATUS_WRECKED)
|
||||
pVehicle->m_status = STATUS_ABANDONED;
|
||||
} else
|
||||
pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
|
||||
}
|
||||
}
|
||||
CEventList::Initialise();
|
||||
CMessages::ClearMessages();
|
||||
CCarCtrl::ClearInterestingVehicleList();
|
||||
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
|
||||
CRestart::FindClosestHospitalRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
|
||||
CRestart::OverrideHospitalLevel = LEVEL_NONE;
|
||||
CRestart::OverridePoliceStationLevel = LEVEL_NONE;
|
||||
PassTime(720);
|
||||
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
|
||||
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
|
||||
TheCamera.m_fCamShakeForce = 0.0f;
|
||||
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
|
||||
CPad::GetPad(0)->StopShaking(0);
|
||||
CReferences::RemoveReferencesToPlayer();
|
||||
CCarCtrl::CountDownToCarsAtStart = 2;
|
||||
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
|
||||
if (CRestart::bFadeInAfterNextDeath) {
|
||||
TheCamera.SetFadeColour(200, 200, 200);
|
||||
TheCamera.Fade(4.0f, FADE_IN);
|
||||
} else CRestart::bFadeInAfterNextDeath = true;
|
||||
}
|
||||
break;
|
||||
case WBSTATE_BUSTED:
|
||||
if ((CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800) && (CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800)) {
|
||||
TheCamera.SetFadeColour(0, 0, 0);
|
||||
TheCamera.Fade(2.0f, FADE_OUT);
|
||||
}
|
||||
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
|
||||
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
|
||||
int takeMoney;
|
||||
|
||||
switch (pPlayerInfo.m_pPed->m_pWanted->m_nWantedLevel) {
|
||||
case 0:
|
||||
case 1:
|
||||
takeMoney = 100;
|
||||
break;
|
||||
case 2:
|
||||
takeMoney = 200;
|
||||
break;
|
||||
case 3:
|
||||
takeMoney = 400;
|
||||
break;
|
||||
case 4:
|
||||
takeMoney = 600;
|
||||
break;
|
||||
case 5:
|
||||
takeMoney = 900;
|
||||
break;
|
||||
case 6:
|
||||
takeMoney = 1500;
|
||||
break;
|
||||
}
|
||||
if (pPlayerInfo.m_bGetOutOfJailFree) {
|
||||
pPlayerInfo.m_bGetOutOfJailFree = false;
|
||||
} else {
|
||||
pPlayerInfo.m_nMoney = max(0, pPlayerInfo.m_nMoney - takeMoney);
|
||||
pPlayerInfo.m_pPed->ClearWeapons();
|
||||
}
|
||||
|
||||
if (pPlayerInfo.m_pPed->bInVehicle) {
|
||||
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
|
||||
if (pVehicle != nil) {
|
||||
if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
|
||||
pVehicle->pDriver = nil;
|
||||
if (pVehicle->m_status != STATUS_WRECKED)
|
||||
pVehicle->m_status = STATUS_ABANDONED;
|
||||
}
|
||||
else
|
||||
pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
|
||||
}
|
||||
}
|
||||
CEventList::Initialise();
|
||||
CMessages::ClearMessages();
|
||||
CCarCtrl::ClearInterestingVehicleList();
|
||||
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
|
||||
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
|
||||
CRestart::OverrideHospitalLevel = LEVEL_NONE;
|
||||
CRestart::OverridePoliceStationLevel = LEVEL_NONE;
|
||||
PassTime(720);
|
||||
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
|
||||
pPlayerInfo.m_pPed->ClearWeapons();
|
||||
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
|
||||
TheCamera.m_fCamShakeForce = 0.0f;
|
||||
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
|
||||
CPad::GetPad(0)->StopShaking(0);
|
||||
CReferences::RemoveReferencesToPlayer();
|
||||
CCarCtrl::CountDownToCarsAtStart = 2;
|
||||
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
|
||||
if (CRestart::bFadeInAfterNextArrest) {
|
||||
TheCamera.SetFadeColour(0, 0, 0);
|
||||
TheCamera.Fade(4.0f, FADE_IN);
|
||||
} else CRestart::bFadeInAfterNextArrest = true;
|
||||
}
|
||||
break;
|
||||
case WBSTATE_FAILED_CRITICAL_MISSION:
|
||||
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime > 0x800 && CTimer::GetPreviousTimeInMilliseconds() - pPlayerInfo.m_nWBTime <= 0x800) {
|
||||
TheCamera.SetFadeColour(0, 0, 0);
|
||||
TheCamera.Fade(2.0f, FADE_OUT);
|
||||
}
|
||||
if (CTimer::GetTimeInMilliseconds() - pPlayerInfo.m_nWBTime >= 0x1000) {
|
||||
pPlayerInfo.m_WBState = WBSTATE_PLAYING;
|
||||
if (pPlayerInfo.m_pPed->bInVehicle) {
|
||||
CVehicle *pVehicle = pPlayerInfo.m_pPed->m_pMyVehicle;
|
||||
if (pVehicle != nil) {
|
||||
if (pVehicle->pDriver == pPlayerInfo.m_pPed) {
|
||||
pVehicle->pDriver = nil;
|
||||
if (pVehicle->m_status != STATUS_WRECKED)
|
||||
pVehicle->m_status = STATUS_ABANDONED;
|
||||
} else
|
||||
pVehicle->RemovePassenger(pPlayerInfo.m_pPed);
|
||||
}
|
||||
}
|
||||
CEventList::Initialise();
|
||||
CMessages::ClearMessages();
|
||||
CCarCtrl::ClearInterestingVehicleList();
|
||||
CWorld::ClearExcitingStuffFromArea(pPlayerInfo.GetPos(), 4000.0f, 1);
|
||||
CRestart::FindClosestPoliceRestartPoint(pPlayerInfo.GetPos(), &vecRestartPos, &fRestartFloat);
|
||||
CRestart::OverridePoliceStationLevel = LEVEL_NONE;
|
||||
CRestart::OverrideHospitalLevel = LEVEL_NONE;
|
||||
RestorePlayerStuffDuringResurrection(pPlayerInfo.m_pPed, vecRestartPos, fRestartFloat);
|
||||
SortOutStreamingAndMemory(pPlayerInfo.GetPos());
|
||||
TheCamera.m_fCamShakeForce = 0.0f;
|
||||
TheCamera.SetMotionBlur(0, 0, 0, 0, MBLUR_NONE);
|
||||
CPad::GetPad(0)->StopShaking(0);
|
||||
CReferences::RemoveReferencesToPlayer();
|
||||
CCarCtrl::CountDownToCarsAtStart = 2;
|
||||
CPad::GetPad(CWorld::PlayerInFocus)->DisablePlayerControls = PLAYERCONTROL_ENABLED;
|
||||
TheCamera.SetFadeColour(0, 0, 0);
|
||||
TheCamera.Fade(4.0f, FADE_IN);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CGameLogic::RestorePlayerStuffDuringResurrection(CPlayerPed *pPlayerPed, CVector pos, float angle)
|
||||
{
|
||||
pPlayerPed->m_fHealth = 100.0f;
|
||||
pPlayerPed->m_fArmour = 0.0f;
|
||||
pPlayerPed->bIsVisible = true;
|
||||
pPlayerPed->m_bloodyFootprintCountOrDeathTime = 0;
|
||||
pPlayerPed->bDoBloodyFootprints = false;
|
||||
pPlayerPed->ClearAdrenaline();
|
||||
pPlayerPed->m_fCurrentStamina = pPlayerPed->m_fMaxStamina;
|
||||
if (pPlayerPed->m_pFire)
|
||||
pPlayerPed->m_pFire->Extinguish();
|
||||
pPlayerPed->bInVehicle = false;
|
||||
pPlayerPed->m_pMyVehicle = nil;
|
||||
pPlayerPed->m_pVehicleAnim = nil;
|
||||
pPlayerPed->m_pWanted->Reset();
|
||||
pPlayerPed->RestartNonPartialAnims();
|
||||
pPlayerPed->GetPlayerInfoForThisPlayerPed()->MakePlayerSafe(false);
|
||||
pPlayerPed->bRemoveFromWorld = false;
|
||||
pPlayerPed->ClearWeaponTarget();
|
||||
pPlayerPed->SetInitialState();
|
||||
CCarCtrl::ClearInterestingVehicleList();
|
||||
|
||||
pos.z += 1.0f;
|
||||
pPlayerPed->Teleport(pos);
|
||||
pPlayerPed->SetMoveSpeed(CVector(0.0f, 0.0f, 0.0f));
|
||||
|
||||
pPlayerPed->m_fRotationCur = DEGTORAD(angle);
|
||||
pPlayerPed->m_fRotationDest = pPlayerPed->m_fRotationCur;
|
||||
pPlayerPed->SetHeading(pPlayerPed->m_fRotationCur);
|
||||
CTheScripts::ClearSpaceForMissionEntity(pos, pPlayerPed);
|
||||
CWorld::ClearExcitingStuffFromArea(pos, 4000.0, 1);
|
||||
pPlayerPed->RestoreHeadingRate();
|
||||
TheCamera.SetCameraDirectlyInFrontForFollowPed_CamOnAString();
|
||||
CReferences::RemoveReferencesToPlayer();
|
||||
CGarages::PlayerArrestedOrDied();
|
||||
CStats::CheckPointReachedUnsuccessfully();
|
||||
CWorld::Remove(pPlayerPed);
|
||||
CWorld::Add(pPlayerPed);
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4213F0, &CGameLogic::InitAtStartOfGame, PATCH_JUMP);
|
||||
InjectHook(0x421C00, &CGameLogic::PassTime, PATCH_JUMP);
|
||||
InjectHook(0x421A20, &CGameLogic::SortOutStreamingAndMemory, PATCH_JUMP);
|
||||
InjectHook(0x421400, &CGameLogic::Update, PATCH_JUMP);
|
||||
InjectHook(0x421A60, &CGameLogic::RestorePlayerStuffDuringResurrection, PATCH_JUMP);
|
||||
InjectHook(0x421A60, &CGameLogic::RestorePlayerStuffDuringResurrection, PATCH_JUMP);
|
||||
ENDPATCHES
|
@ -1,13 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
class CGameLogic
|
||||
{
|
||||
public:
|
||||
static void InitAtStartOfGame();
|
||||
static void PassTime(uint32 time);
|
||||
static void SortOutStreamingAndMemory(const CVector &pos);
|
||||
static void Update();
|
||||
static void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle);
|
||||
|
||||
static uint8 ActivePlayers;
|
||||
#pragma once
|
||||
|
||||
class CGameLogic
|
||||
{
|
||||
public:
|
||||
static void InitAtStartOfGame();
|
||||
static void PassTime(uint32 time);
|
||||
static void SortOutStreamingAndMemory(const CVector &pos);
|
||||
static void Update();
|
||||
static void RestorePlayerStuffDuringResurrection(class CPlayerPed *pPlayerPed, CVector pos, float angle);
|
||||
|
||||
static uint8 ActivePlayers;
|
||||
};
|
@ -1,89 +0,0 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "ModelIndices.h"
|
||||
#include "Gangs.h"
|
||||
#include "Weapon.h"
|
||||
|
||||
//CGangInfo(&CGangs::Gang)[NUM_GANGS] = *(CGangInfo(*)[NUM_GANGS])*(uintptr*)0x6EDF78;
|
||||
CGangInfo CGangs::Gang[NUM_GANGS];
|
||||
|
||||
CGangInfo::CGangInfo() :
|
||||
m_nVehicleMI(MI_BUS),
|
||||
m_nPedModelOverride(-1),
|
||||
m_Weapon1(WEAPONTYPE_UNARMED),
|
||||
m_Weapon2(WEAPONTYPE_UNARMED)
|
||||
{}
|
||||
|
||||
void CGangs::Initialise(void)
|
||||
{
|
||||
Gang[GANG_MAFIA].m_nVehicleMI = MI_MAFIA;
|
||||
Gang[GANG_TRIAD].m_nVehicleMI = MI_BELLYUP;
|
||||
Gang[GANG_DIABLOS].m_nVehicleMI = MI_DIABLOS;
|
||||
Gang[GANG_YAKUZA].m_nVehicleMI = MI_YAKUZA;
|
||||
Gang[GANG_YARDIE].m_nVehicleMI = MI_YARDIE;
|
||||
Gang[GANG_COLUMB].m_nVehicleMI = MI_COLUMB;
|
||||
Gang[GANG_HOODS].m_nVehicleMI = MI_HOODS;
|
||||
Gang[GANG_7].m_nVehicleMI = -1;
|
||||
Gang[GANG_8].m_nVehicleMI = -1;
|
||||
#ifdef FIX_BUGS
|
||||
for (int i = 0; i < NUM_GANGS; i++)
|
||||
Gang[i].m_nPedModelOverride = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void CGangs::SetGangVehicleModel(int16 gang, int32 model)
|
||||
{
|
||||
GetGangInfo(gang)->m_nVehicleMI = model;
|
||||
}
|
||||
|
||||
void CGangs::SetGangWeapons(int16 gang, int32 weapon1, int32 weapon2)
|
||||
{
|
||||
CGangInfo *gi = GetGangInfo(gang);
|
||||
gi->m_Weapon1 = weapon1;
|
||||
gi->m_Weapon2 = weapon2;
|
||||
}
|
||||
|
||||
void CGangs::SetGangPedModelOverride(int16 gang, int8 ovrd)
|
||||
{
|
||||
GetGangInfo(gang)->m_nPedModelOverride = ovrd;
|
||||
}
|
||||
|
||||
int8 CGangs::GetGangPedModelOverride(int16 gang)
|
||||
{
|
||||
return GetGangInfo(gang)->m_nPedModelOverride;
|
||||
}
|
||||
|
||||
void CGangs::SaveAllGangData(uint8 *buf, uint32 *size)
|
||||
{
|
||||
INITSAVEBUF
|
||||
|
||||
*size = SAVE_HEADER_SIZE + sizeof(Gang);
|
||||
WriteSaveHeader(buf, 'G','N','G','\0', *size - SAVE_HEADER_SIZE);
|
||||
for (int i = 0; i < NUM_GANGS; i++)
|
||||
WriteSaveBuf(buf, Gang[i]);
|
||||
|
||||
VALIDATESAVEBUF(*size);
|
||||
}
|
||||
|
||||
void CGangs::LoadAllGangData(uint8 *buf, uint32 size)
|
||||
{
|
||||
Initialise();
|
||||
|
||||
INITSAVEBUF
|
||||
// original: SkipSaveBuf(buf, SAVE_HEADER_SIZE);
|
||||
CheckSaveHeader(buf, 'G','N','G','\0', size - SAVE_HEADER_SIZE);
|
||||
|
||||
for (int i = 0; i < NUM_GANGS; i++)
|
||||
Gang[i] = ReadSaveBuf<CGangInfo>(buf);
|
||||
VALIDATESAVEBUF(size);
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4C3FB0, CGangs::Initialise, PATCH_JUMP);
|
||||
InjectHook(0x4C4010, CGangs::SetGangVehicleModel, PATCH_JUMP);
|
||||
InjectHook(0x4C4030, CGangs::SetGangWeapons, PATCH_JUMP);
|
||||
InjectHook(0x4C4050, CGangs::SetGangPedModelOverride, PATCH_JUMP);
|
||||
InjectHook(0x4C4070, CGangs::GetGangPedModelOverride, PATCH_JUMP);
|
||||
InjectHook(0x4C4080, CGangs::SaveAllGangData, PATCH_JUMP);
|
||||
InjectHook(0x4C4100, CGangs::LoadAllGangData, PATCH_JUMP);
|
||||
ENDPATCHES
|
@ -1,44 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
struct CGangInfo
|
||||
{
|
||||
int32 m_nVehicleMI;
|
||||
int8 m_nPedModelOverride;
|
||||
int32 m_Weapon1;
|
||||
int32 m_Weapon2;
|
||||
|
||||
CGangInfo();
|
||||
};
|
||||
|
||||
static_assert(sizeof(CGangInfo) == 0x10, "CGangInfo: error");
|
||||
|
||||
enum {
|
||||
GANG_MAFIA = 0,
|
||||
GANG_TRIAD,
|
||||
GANG_DIABLOS,
|
||||
GANG_YAKUZA,
|
||||
GANG_YARDIE,
|
||||
GANG_COLUMB,
|
||||
GANG_HOODS,
|
||||
GANG_7,
|
||||
GANG_8,
|
||||
NUM_GANGS
|
||||
};
|
||||
|
||||
class CGangs
|
||||
{
|
||||
public:
|
||||
static void Initialise(void);
|
||||
static void SetGangVehicleModel(int16, int32);
|
||||
static void SetGangWeapons(int16, int32, int32);
|
||||
static void SetGangPedModelOverride(int16, int8);
|
||||
static int8 GetGangPedModelOverride(int16);
|
||||
static void SaveAllGangData(uint8 *, uint32 *);
|
||||
static void LoadAllGangData(uint8 *, uint32);
|
||||
|
||||
static int32 GetGangVehicleModel(int16 gang) { return Gang[gang].m_nVehicleMI; }
|
||||
static CGangInfo *GetGangInfo(int16 gang) { return &Gang[gang]; }
|
||||
|
||||
private:
|
||||
static CGangInfo Gang[NUM_GANGS];
|
||||
};
|
@ -126,7 +126,6 @@ uint32& CGarages::MessageEndTime = *(uint32*)0x8F597C;
|
||||
uint32& CGarages::NumGarages = *(uint32*)0x8F29F4;
|
||||
bool& CGarages::PlayerInGarage = *(bool*)0x95CD83;
|
||||
int32& CGarages::PoliceCarsCollected = *(int32*)0x941444;
|
||||
uint32& CGarages::GarageToBeTidied = *(uint32*)0x623570;
|
||||
CStoredCar(&CGarages::aCarsInSafeHouse1)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA210;
|
||||
CStoredCar(&CGarages::aCarsInSafeHouse2)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA300;
|
||||
CStoredCar(&CGarages::aCarsInSafeHouse3)[NUM_GARAGE_STORED_CARS] = *(CStoredCar(*)[NUM_GARAGE_STORED_CARS]) * (uintptr*)0x6FA3F0;
|
||||
@ -322,6 +321,9 @@ void CGarage::Update()
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (m_bDeactivated && m_eGarageState == GS_FULLYCLOSED)
|
||||
@ -408,11 +410,11 @@ void CGarage::Update()
|
||||
if (!((CAutomobile*)(FindPlayerVehicle()))->bFixedColour) {
|
||||
uint8 colour1, colour2;
|
||||
uint16 attempt;
|
||||
((CVehicleModelInfo*)CModelInfo::GetModelInfo(FindPlayerVehicle()->GetModelIndex()))->ChooseVehicleColour(colour1, colour2);
|
||||
FindPlayerVehicle()->GetModelInfo()->ChooseVehicleColour(colour1, colour2);
|
||||
for (attempt = 0; attempt < 10; attempt++) {
|
||||
if (colour1 != FindPlayerVehicle()->m_currentColour1 || colour2 != FindPlayerVehicle()->m_currentColour2)
|
||||
break;
|
||||
((CVehicleModelInfo*)CModelInfo::GetModelInfo(FindPlayerVehicle()->GetModelIndex()))->ChooseVehicleColour(colour1, colour2);
|
||||
FindPlayerVehicle()->GetModelInfo()->ChooseVehicleColour(colour1, colour2);
|
||||
}
|
||||
bChangedColour = (attempt < 10);
|
||||
FindPlayerVehicle()->m_currentColour1 = colour1;
|
||||
@ -490,7 +492,7 @@ void CGarage::Update()
|
||||
break;
|
||||
}
|
||||
if (!CGarages::BombsAreFree && CWorld::Players[CWorld::PlayerInFocus].m_nMoney < BOMB_PRICE) {
|
||||
CGarages::TriggerMessage("GA_4", -1, 4000, -1); // "Car bombs are $1000 each"
|
||||
CGarages::TriggerMessage("GA_4", -1, 4000, -1); // "Car bombs are $1000 each" - weird that the price is hardcoded in message
|
||||
m_eGarageState = GS_OPENEDCONTAINSCAR;
|
||||
DMAudio.PlayFrontEndSound(SOUND_GARAGE_NO_MONEY, 1);
|
||||
break;
|
||||
@ -524,7 +526,7 @@ void CGarage::Update()
|
||||
((CAutomobile*)(FindPlayerVehicle()))->m_pBombRigger = FindPlayerPed();
|
||||
if (m_eGarageType == GARAGE_BOMBSHOP3)
|
||||
CGarages::GivePlayerDetonator();
|
||||
CStats::KgOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB;
|
||||
CStats::KgsOfExplosivesUsed += KGS_OF_EXPLOSIVES_IN_BOMB;
|
||||
}
|
||||
switch (m_eGarageType) {
|
||||
case GARAGE_BOMBSHOP1:
|
||||
@ -1184,7 +1186,7 @@ bool CGarage::IsEntityEntirelyInside(CEntity * pEntity)
|
||||
if (pEntity->GetPosition().x < m_fX1 || pEntity->GetPosition().x > m_fX2 ||
|
||||
pEntity->GetPosition().y < m_fY1 || pEntity->GetPosition().y > m_fY2)
|
||||
return false;
|
||||
CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel();
|
||||
CColModel* pColModel = pEntity->GetColModel();
|
||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
|
||||
float radius = pColModel->spheres[i].radius;
|
||||
@ -1201,7 +1203,7 @@ bool CGarage::IsEntityEntirelyInside3D(CEntity * pEntity, float fMargin)
|
||||
pEntity->GetPosition().y < m_fY1 - fMargin || pEntity->GetPosition().y > m_fY2 + fMargin ||
|
||||
pEntity->GetPosition().z < m_fZ1 - fMargin || pEntity->GetPosition().z > m_fZ2 + fMargin)
|
||||
return false;
|
||||
CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel();
|
||||
CColModel* pColModel = pEntity->GetColModel();
|
||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
|
||||
float radius = pColModel->spheres[i].radius;
|
||||
@ -1218,7 +1220,7 @@ bool CGarage::IsEntityEntirelyOutside(CEntity * pEntity, float fMargin)
|
||||
if (pEntity->GetPosition().x > m_fX1 - fMargin && pEntity->GetPosition().x < m_fX2 + fMargin &&
|
||||
pEntity->GetPosition().y > m_fY1 - fMargin && pEntity->GetPosition().y < m_fY2 + fMargin)
|
||||
return false;
|
||||
CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel();
|
||||
CColModel* pColModel = pEntity->GetColModel();
|
||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
|
||||
float radius = pColModel->spheres[i].radius;
|
||||
@ -1250,7 +1252,7 @@ bool CGarage::IsEntityTouching3D(CEntity * pEntity)
|
||||
pEntity->GetPosition().y - radius < m_fY1 || pEntity->GetPosition().y + radius > m_fY2 ||
|
||||
pEntity->GetPosition().z - radius < m_fZ1 || pEntity->GetPosition().z + radius > m_fZ2)
|
||||
return false;
|
||||
CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel();
|
||||
CColModel* pColModel = pEntity->GetColModel();
|
||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
|
||||
radius = pColModel->spheres[i].radius;
|
||||
@ -1264,7 +1266,7 @@ bool CGarage::IsEntityTouching3D(CEntity * pEntity)
|
||||
|
||||
bool CGarage::EntityHasASphereWayOutsideGarage(CEntity * pEntity, float fMargin)
|
||||
{
|
||||
CColModel* pColModel = CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel();
|
||||
CColModel* pColModel = pEntity->GetColModel();
|
||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||
CVector pos = pEntity->GetMatrix() * pColModel->spheres[i].center;
|
||||
float radius = pColModel->spheres[i].radius;
|
||||
@ -1285,7 +1287,7 @@ bool CGarage::IsAnyOtherCarTouchingGarage(CVehicle * pException)
|
||||
continue;
|
||||
if (!IsEntityTouching3D(pVehicle))
|
||||
continue;
|
||||
CColModel* pColModel = CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel();
|
||||
CColModel* pColModel = pVehicle->GetColModel();
|
||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
|
||||
float radius = pColModel->spheres[i].radius;
|
||||
@ -1307,7 +1309,7 @@ bool CGarage::IsAnyOtherPedTouchingGarage(CPed * pException)
|
||||
continue;
|
||||
if (!IsEntityTouching3D(pPed))
|
||||
continue;
|
||||
CColModel* pColModel = CModelInfo::GetModelInfo(pPed->GetModelIndex())->GetColModel();
|
||||
CColModel* pColModel = pException->GetColModel();
|
||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||
CVector pos = pPed->GetMatrix() * pColModel->spheres[i].center;
|
||||
float radius = pColModel->spheres[i].radius;
|
||||
@ -1329,7 +1331,7 @@ bool CGarage::IsAnyCarBlockingDoor()
|
||||
continue;
|
||||
if (!IsEntityTouching3D(pVehicle))
|
||||
continue;
|
||||
CColModel* pColModel = CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel();
|
||||
CColModel* pColModel = pVehicle->GetColModel();
|
||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
|
||||
float radius = pColModel->spheres[i].radius;
|
||||
@ -1677,7 +1679,7 @@ float CGarage::CalcDistToGarageRectangleSquared(float X, float Y)
|
||||
else
|
||||
distX = 0.0f;
|
||||
if (Y < m_fY1)
|
||||
distY = m_fY1 - X;
|
||||
distY = m_fY1 - Y;
|
||||
else if (Y > m_fY2)
|
||||
distY = Y - m_fY2;
|
||||
else
|
||||
@ -1698,8 +1700,8 @@ float CGarage::CalcSmallestDistToGarageDoorSquared(float X, float Y)
|
||||
|
||||
void CGarage::FindDoorsEntities()
|
||||
{
|
||||
m_pDoor1 = false;
|
||||
m_pDoor2 = false;
|
||||
m_pDoor1 = nil;
|
||||
m_pDoor2 = nil;
|
||||
int xstart = max(0, CWorld::GetSectorIndexX(m_fX1));
|
||||
int xend = min(NUMSECTORS_X - 1, CWorld::GetSectorIndexX(m_fX2));
|
||||
int ystart = max(0, CWorld::GetSectorIndexY(m_fY1));
|
||||
@ -1992,7 +1994,7 @@ void CGarage::TidyUpGarageClose()
|
||||
continue;
|
||||
bool bRemove = false;
|
||||
if (m_eGarageState != GS_FULLYCLOSED) {
|
||||
CColModel* pColModel = CModelInfo::GetModelInfo(pVehicle->GetModelIndex())->GetColModel();
|
||||
CColModel* pColModel = pVehicle->GetColModel();
|
||||
for (int i = 0; i < pColModel->numSpheres; i++) {
|
||||
CVector pos = pVehicle->GetMatrix() * pColModel->spheres[i].center;
|
||||
float radius = pColModel->spheres[i].radius;
|
||||
@ -2106,7 +2108,7 @@ void CGarages::CloseHideOutGaragesBeforeSave()
|
||||
aGarages[i].m_eGarageType != GARAGE_HIDEOUT_THREE)
|
||||
continue;
|
||||
if (aGarages[i].m_eGarageState != GS_FULLYCLOSED &&
|
||||
aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE || !aGarages[i].IsAnyCarBlockingDoor()) {
|
||||
(aGarages[i].m_eGarageType != GARAGE_HIDEOUT_ONE || !aGarages[i].IsAnyCarBlockingDoor())) {
|
||||
aGarages[i].m_eGarageState = GS_FULLYCLOSED;
|
||||
switch (aGarages[i].m_eGarageType) {
|
||||
case GARAGE_HIDEOUT_ONE:
|
||||
@ -2227,6 +2229,7 @@ void CGarages::SetAllDoorsBackToOriginalHeight()
|
||||
void CGarages::Save(uint8 * buf, uint32 * size)
|
||||
{
|
||||
#ifdef FIX_GARAGE_SIZE
|
||||
INITSAVEBUF
|
||||
*size = (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage));
|
||||
#else
|
||||
* size = 5484;
|
||||
@ -2248,6 +2251,9 @@ void CGarages::Save(uint8 * buf, uint32 * size)
|
||||
}
|
||||
for (int i = 0; i < NUM_GARAGES; i++)
|
||||
WriteSaveBuf(buf, aGarages[i]);
|
||||
#ifdef FIX_GARAGE_SIZE
|
||||
VALIDATESAVEBUF(*size);
|
||||
#endif
|
||||
}
|
||||
|
||||
CStoredCar::CStoredCar(const CStoredCar & other)
|
||||
@ -2271,6 +2277,7 @@ CStoredCar::CStoredCar(const CStoredCar & other)
|
||||
void CGarages::Load(uint8* buf, uint32 size)
|
||||
{
|
||||
#ifdef FIX_GARAGE_SIZE
|
||||
INITSAVEBUF
|
||||
assert(size == (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage));
|
||||
#else
|
||||
assert(size == 5484);
|
||||
@ -2303,6 +2310,9 @@ void CGarages::Load(uint8* buf, uint32 size)
|
||||
else
|
||||
aGarages[i].UpdateDoorsHeight();
|
||||
}
|
||||
#ifdef FIX_GARAGE_SIZE
|
||||
VALIDATESAVEBUF(size);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2345,8 +2355,7 @@ CGarages::IsModelIndexADoor(uint32 id)
|
||||
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x426B20, CGarages::TriggerMessage, PATCH_JUMP); // CCrane::Update, CCrane::FindCarInSectorList
|
||||
InjectHook(0x427AB0, CGarages::IsPointInAGarageCameraZone, PATCH_JUMP); // CCamera::CamControl
|
||||
InjectHook(0x427BC0, CGarages::CameraShouldBeOutside, PATCH_JUMP); // CCamera::CamControl
|
||||
InjectHook(0x428940, CGarages::Load, PATCH_JUMP); // GenericLoad
|
||||
ENDPATCHES
|
||||
ENDPATCHES
|
||||
|
@ -194,7 +194,6 @@ class CGarages
|
||||
static uint32 &NumGarages;
|
||||
static bool &PlayerInGarage;
|
||||
static int32 &PoliceCarsCollected;
|
||||
static uint32 &GarageToBeTidied;
|
||||
static CGarage(&aGarages)[NUM_GARAGES];
|
||||
static CStoredCar(&aCarsInSafeHouse1)[NUM_GARAGE_STORED_CARS];
|
||||
static CStoredCar(&aCarsInSafeHouse2)[NUM_GARAGE_STORED_CARS];
|
||||
|
@ -1,49 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
enum
|
||||
{
|
||||
COUNTER_DISPLAY_NUMBER,
|
||||
COUNTER_DISPLAY_BAR,
|
||||
};
|
||||
|
||||
class COnscreenTimerEntry
|
||||
{
|
||||
public:
|
||||
uint32 m_nTimerOffset;
|
||||
uint32 m_nCounterOffset;
|
||||
char m_aTimerText[10];
|
||||
char m_aCounterText[10];
|
||||
uint16 m_nType;
|
||||
char m_bCounterBuffer[42];
|
||||
char m_bTimerBuffer[42];
|
||||
bool m_bTimerProcessed;
|
||||
bool m_bCounterProcessed;
|
||||
|
||||
void Process();
|
||||
bool ProcessForDisplay();
|
||||
|
||||
void ProcessForDisplayClock();
|
||||
void ProcessForDisplayCounter();
|
||||
};
|
||||
|
||||
static_assert(sizeof(COnscreenTimerEntry) == 0x74, "COnscreenTimerEntry: error");
|
||||
|
||||
class COnscreenTimer
|
||||
{
|
||||
public:
|
||||
COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES];
|
||||
bool m_bProcessed;
|
||||
bool m_bDisabled;
|
||||
|
||||
void Init();
|
||||
void Process();
|
||||
void ProcessForDisplay();
|
||||
|
||||
void ClearCounter(uint32 offset);
|
||||
void ClearClock(uint32 offset);
|
||||
|
||||
void AddCounter(uint32 offset, uint16 type, char* text);
|
||||
void AddClock(uint32 offset, char* text);
|
||||
};
|
||||
|
||||
#pragma once
|
||||
|
||||
enum
|
||||
{
|
||||
COUNTER_DISPLAY_NUMBER,
|
||||
COUNTER_DISPLAY_BAR,
|
||||
};
|
||||
|
||||
class COnscreenTimerEntry
|
||||
{
|
||||
public:
|
||||
uint32 m_nTimerOffset;
|
||||
uint32 m_nCounterOffset;
|
||||
char m_aTimerText[10];
|
||||
char m_aCounterText[10];
|
||||
uint16 m_nType;
|
||||
char m_bCounterBuffer[42];
|
||||
char m_bTimerBuffer[42];
|
||||
bool m_bTimerProcessed;
|
||||
bool m_bCounterProcessed;
|
||||
|
||||
void Process();
|
||||
bool ProcessForDisplay();
|
||||
|
||||
void ProcessForDisplayClock();
|
||||
void ProcessForDisplayCounter();
|
||||
};
|
||||
|
||||
static_assert(sizeof(COnscreenTimerEntry) == 0x74, "COnscreenTimerEntry: error");
|
||||
|
||||
class COnscreenTimer
|
||||
{
|
||||
public:
|
||||
COnscreenTimerEntry m_sEntries[NUMONSCREENTIMERENTRIES];
|
||||
bool m_bProcessed;
|
||||
bool m_bDisabled;
|
||||
|
||||
void Init();
|
||||
void Process();
|
||||
void ProcessForDisplay();
|
||||
|
||||
void ClearCounter(uint32 offset);
|
||||
void ClearClock(uint32 offset);
|
||||
|
||||
void AddCounter(uint32 offset, uint16 type, char* text);
|
||||
void AddClock(uint32 offset, char* text);
|
||||
};
|
||||
|
||||
static_assert(sizeof(COnscreenTimer) == 0x78, "COnscreenTimer: error");
|
@ -5,8 +5,13 @@
|
||||
#include "Camera.h"
|
||||
#include "Vehicle.h"
|
||||
#include "World.h"
|
||||
#include "Lines.h" // for debug
|
||||
#include "PathFind.h"
|
||||
|
||||
bool gbShowPedPaths;
|
||||
bool gbShowCarPaths;
|
||||
bool gbShowCarPathsLinks;
|
||||
|
||||
CPathFind &ThePaths = *(CPathFind*)0x8F6754;
|
||||
|
||||
WRAPPER bool CPedPath::CalcPedRoute(uint8, CVector, CVector, CVector*, int16*, int16) { EAXJMP(0x42E680); }
|
||||
@ -466,20 +471,20 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
|
||||
// IMPROVE: use a goto here
|
||||
// Find existing car path link
|
||||
for(k = 0; k < m_numCarPathLinks; k++){
|
||||
if(m_carPathLinks[k].dirX == tempnodes[j].dirX &&
|
||||
m_carPathLinks[k].dirY == tempnodes[j].dirY &&
|
||||
m_carPathLinks[k].posX == tempnodes[j].pos.x &&
|
||||
m_carPathLinks[k].posY == tempnodes[j].pos.y){
|
||||
if(m_carPathLinks[k].dir.x == tempnodes[j].dirX &&
|
||||
m_carPathLinks[k].dir.y == tempnodes[j].dirY &&
|
||||
m_carPathLinks[k].pos.x == tempnodes[j].pos.x &&
|
||||
m_carPathLinks[k].pos.y == tempnodes[j].pos.y){
|
||||
m_carPathConnections[m_numConnections] = k;
|
||||
k = m_numCarPathLinks;
|
||||
}
|
||||
}
|
||||
// k is m_numCarPathLinks+1 if we found one
|
||||
if(k == m_numCarPathLinks){
|
||||
m_carPathLinks[m_numCarPathLinks].dirX = tempnodes[j].dirX;
|
||||
m_carPathLinks[m_numCarPathLinks].dirY = tempnodes[j].dirY;
|
||||
m_carPathLinks[m_numCarPathLinks].posX = tempnodes[j].pos.x;
|
||||
m_carPathLinks[m_numCarPathLinks].posY = tempnodes[j].pos.y;
|
||||
m_carPathLinks[m_numCarPathLinks].dir.x = tempnodes[j].dirX;
|
||||
m_carPathLinks[m_numCarPathLinks].dir.y = tempnodes[j].dirY;
|
||||
m_carPathLinks[m_numCarPathLinks].pos.x = tempnodes[j].pos.x;
|
||||
m_carPathLinks[m_numCarPathLinks].pos.y = tempnodes[j].pos.y;
|
||||
m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i;
|
||||
m_carPathLinks[m_numCarPathLinks].numLeftLanes = tempnodes[j].numLeftLanes;
|
||||
m_carPathLinks[m_numCarPathLinks].numRightLanes = tempnodes[j].numRightLanes;
|
||||
@ -529,20 +534,20 @@ CPathFind::PreparePathDataForType(uint8 type, CTempNode *tempnodes, CPathInfoFor
|
||||
// IMPROVE: use a goto here
|
||||
// Find existing car path link
|
||||
for(k = 0; k < m_numCarPathLinks; k++){
|
||||
if(m_carPathLinks[k].dirX == dx &&
|
||||
m_carPathLinks[k].dirY == dy &&
|
||||
m_carPathLinks[k].posX == posx &&
|
||||
m_carPathLinks[k].posY == posy){
|
||||
if(m_carPathLinks[k].dir.x == dx &&
|
||||
m_carPathLinks[k].dir.y == dy &&
|
||||
m_carPathLinks[k].pos.x == posx &&
|
||||
m_carPathLinks[k].pos.y == posy){
|
||||
m_carPathConnections[m_numConnections] = k;
|
||||
k = m_numCarPathLinks;
|
||||
}
|
||||
}
|
||||
// k is m_numCarPathLinks+1 if we found one
|
||||
if(k == m_numCarPathLinks){
|
||||
m_carPathLinks[m_numCarPathLinks].dirX = dx;
|
||||
m_carPathLinks[m_numCarPathLinks].dirY = dy;
|
||||
m_carPathLinks[m_numCarPathLinks].posX = posx;
|
||||
m_carPathLinks[m_numCarPathLinks].posY = posy;
|
||||
m_carPathLinks[m_numCarPathLinks].dir.x = dx;
|
||||
m_carPathLinks[m_numCarPathLinks].dir.y = dy;
|
||||
m_carPathLinks[m_numCarPathLinks].pos.x = posx;
|
||||
m_carPathLinks[m_numCarPathLinks].pos.y = posy;
|
||||
m_carPathLinks[m_numCarPathLinks].pathNodeIndex = i;
|
||||
m_carPathLinks[m_numCarPathLinks].numLeftLanes = -1;
|
||||
m_carPathLinks[m_numCarPathLinks].numRightLanes = -1;
|
||||
@ -760,8 +765,8 @@ CPathFind::SetLinksBridgeLights(float x1, float x2, float y1, float y2, bool ena
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < m_numCarPathLinks; i++)
|
||||
if(x1 < m_carPathLinks[i].posX && m_carPathLinks[i].posX < x2 &&
|
||||
y1 < m_carPathLinks[i].posY && m_carPathLinks[i].posY < y2)
|
||||
if(x1 < m_carPathLinks[i].pos.x && m_carPathLinks[i].pos.x < x2 &&
|
||||
y1 < m_carPathLinks[i].pos.y && m_carPathLinks[i].pos.y < y2)
|
||||
m_carPathLinks[i].bBridgeLights = enable;
|
||||
}
|
||||
|
||||
@ -1444,6 +1449,132 @@ CPathFind::Load(uint8 *buf, uint32 size)
|
||||
m_pathNodes[i].bBetweenLevels = false;
|
||||
}
|
||||
|
||||
void
|
||||
CPathFind::DisplayPathData(void)
|
||||
{
|
||||
// Not the function from mobm_carPathLinksile but my own!
|
||||
|
||||
int i, j, k;
|
||||
// Draw 50 units around camera
|
||||
CVector pos = TheCamera.GetPosition();
|
||||
const float maxDist = 50.0f;
|
||||
|
||||
// Render car path nodes
|
||||
if(gbShowCarPaths)
|
||||
for(i = 0; i < m_numCarPathNodes; i++){
|
||||
if((m_pathNodes[i].pos - pos).MagnitudeSqr() > SQR(maxDist))
|
||||
continue;
|
||||
|
||||
CVector n1 = m_pathNodes[i].pos;
|
||||
n1.z += 0.3f;
|
||||
|
||||
// Draw node itself
|
||||
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
|
||||
n1.x, n1.y, n1.z + 1.0f,
|
||||
0xFFFFFFFF, 0xFFFFFFFF);
|
||||
|
||||
for(j = 0; j < m_pathNodes[i].numLinks; j++){
|
||||
k = m_connections[m_pathNodes[i].firstLink + j];
|
||||
CVector n2 = m_pathNodes[k].pos;
|
||||
n2.z += 0.3f;
|
||||
// Draw links to neighbours
|
||||
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
|
||||
n2.x, n2.y, n2.z,
|
||||
0xFFFFFFFF, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
// Render car path nodes
|
||||
if(gbShowCarPathsLinks)
|
||||
for(i = 0; i < m_numCarPathLinks; i++){
|
||||
CVector2D n1_2d = m_carPathLinks[i].pos;
|
||||
if((n1_2d - pos).MagnitudeSqr() > SQR(maxDist))
|
||||
continue;
|
||||
|
||||
int ni = m_carPathLinks[i].pathNodeIndex;
|
||||
CVector pn1 = m_pathNodes[ni].pos;
|
||||
pn1.z += 0.3f;
|
||||
CVector n1(n1_2d.x, n1_2d.y, pn1.z);
|
||||
n1.z += 0.3f;
|
||||
|
||||
// Draw car node itself
|
||||
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
|
||||
n1.x, n1.y, n1.z + 1.0f,
|
||||
0xFFFFFFFF, 0xFFFFFFFF);
|
||||
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z + 0.5f,
|
||||
n1.x+m_carPathLinks[i].dir.x, n1.y+m_carPathLinks[i].dir.y, n1.z + 0.5f,
|
||||
0xFFFFFFFF, 0xFFFFFFFF);
|
||||
|
||||
// Draw connection to car path node
|
||||
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
|
||||
pn1.x, pn1.y, pn1.z,
|
||||
0xFF0000FF, 0xFFFFFFFF);
|
||||
|
||||
// traffic light type
|
||||
uint32 col = 0xFF;
|
||||
if((m_carPathLinks[i].trafficLightType&0x7F) == 1)
|
||||
col += 0xFF000000;
|
||||
if((m_carPathLinks[i].trafficLightType&0x7F) == 2)
|
||||
col += 0x00FF0000;
|
||||
if(m_carPathLinks[i].trafficLightType & 0x80)
|
||||
col += 0x0000FF00;
|
||||
CLines::RenderLineWithClipping(n1.x+0.2f, n1.y, n1.z,
|
||||
n1.x+0.2f, n1.y, n1.z + 1.0f,
|
||||
col, col);
|
||||
|
||||
for(j = 0; j < m_pathNodes[ni].numLinks; j++){
|
||||
k = m_carPathConnections[m_pathNodes[ni].firstLink + j];
|
||||
CVector2D n2_2d = m_carPathLinks[k].pos;
|
||||
int nk = m_carPathLinks[k].pathNodeIndex;
|
||||
CVector pn2 = m_pathNodes[nk].pos;
|
||||
pn2.z += 0.3f;
|
||||
CVector n2(n2_2d.x, n2_2d.y, pn2.z);
|
||||
n2.z += 0.3f;
|
||||
|
||||
// Draw links to neighbours
|
||||
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
|
||||
n2.x, n2.y, n2.z,
|
||||
0xFF00FFFF, 0xFF00FFFF);
|
||||
}
|
||||
}
|
||||
|
||||
// Render ped path nodes
|
||||
if(gbShowPedPaths)
|
||||
for(i = m_numCarPathNodes; i < m_numPathNodes; i++){
|
||||
if((m_pathNodes[i].pos - pos).MagnitudeSqr() > SQR(maxDist))
|
||||
continue;
|
||||
|
||||
CVector n1 = m_pathNodes[i].pos;
|
||||
n1.z += 0.3f;
|
||||
|
||||
// Draw node itself
|
||||
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
|
||||
n1.x, n1.y, n1.z + 1.0f,
|
||||
0xFFFFFFFF, 0xFFFFFFFF);
|
||||
|
||||
for(j = 0; j < m_pathNodes[i].numLinks; j++){
|
||||
k = m_connections[m_pathNodes[i].firstLink + j];
|
||||
CVector n2 = m_pathNodes[k].pos;
|
||||
n2.z += 0.3f;
|
||||
// Draw links to neighbours
|
||||
CLines::RenderLineWithClipping(n1.x, n1.y, n1.z,
|
||||
n2.x, n2.y, n2.z,
|
||||
0xFFFFFFFF, 0xFFFFFFFF);
|
||||
|
||||
// Draw connection flags
|
||||
CVector mid = (n1+n2)/2.0f;
|
||||
uint32 col = 0xFF;
|
||||
if(m_connectionFlags[m_pathNodes[i].firstLink + j].bCrossesRoad)
|
||||
col += 0x00FF0000;
|
||||
if(m_connectionFlags[m_pathNodes[i].firstLink + j].bTrafficLight)
|
||||
col += 0xFF000000;
|
||||
CLines::RenderLineWithClipping(mid.x, mid.y, mid.z,
|
||||
mid.x, mid.y, mid.z + 1.0f,
|
||||
col, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x4294A0, &CPathFind::Init, PATCH_JUMP);
|
||||
InjectHook(0x42D580, &CPathFind::AllocatePathFindInfoMem, PATCH_JUMP);
|
||||
|
@ -84,10 +84,8 @@ union CConnectionFlags
|
||||
|
||||
struct CCarPathLink
|
||||
{
|
||||
float posX;
|
||||
float posY;
|
||||
float dirX;
|
||||
float dirY;
|
||||
CVector2D pos;
|
||||
CVector2D dir;
|
||||
int16 pathNodeIndex;
|
||||
int8 numLeftLanes;
|
||||
int8 numRightLanes;
|
||||
@ -208,7 +206,13 @@ public:
|
||||
bool TestCoorsCloseness(CVector target, uint8 type, CVector start);
|
||||
void Save(uint8 *buf, uint32 *size);
|
||||
void Load(uint8 *buf, uint32 size);
|
||||
|
||||
void DisplayPathData(void);
|
||||
};
|
||||
static_assert(sizeof(CPathFind) == 0x49bf4, "CPathFind: error");
|
||||
|
||||
extern CPathFind &ThePaths;
|
||||
|
||||
extern bool gbShowPedPaths;
|
||||
extern bool gbShowCarPaths;
|
||||
extern bool gbShowCarPathsLinks;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,124 +1,147 @@
|
||||
#pragma once
|
||||
#include "Weapon.h"
|
||||
|
||||
enum ePickupType : uint8
|
||||
{
|
||||
PICKUP_NONE = 0,
|
||||
PICKUP_IN_SHOP,
|
||||
PICKUP_ON_STREET,
|
||||
PICKUP_ONCE,
|
||||
PICKUP_ONCE_TIMEOUT,
|
||||
PICKUP_COLLECTABLE1,
|
||||
PICKUP_IN_SHOP_OUT_OF_STOCK,
|
||||
PICKUP_MONEY,
|
||||
PICKUP_MINE_INACTIVE,
|
||||
PICKUP_MINE_ARMED,
|
||||
PICKUP_NAUTICAL_MINE_INACTIVE,
|
||||
PICKUP_NAUTICAL_MINE_ARMED,
|
||||
PICKUP_FLOATINGPACKAGE,
|
||||
PICKUP_FLOATINGPACKAGE_FLOATING,
|
||||
PICKUP_ON_STREET_SLOW,
|
||||
PICKUP_NUMOFTYPES
|
||||
};
|
||||
|
||||
class CEntity;
|
||||
class CObject;
|
||||
class CVehicle;
|
||||
class CPlayerPed;
|
||||
|
||||
class CPickup
|
||||
{
|
||||
public:
|
||||
ePickupType m_eType;
|
||||
bool m_bRemoved;
|
||||
uint16 m_nQuantity;
|
||||
CObject *m_pObject;
|
||||
uint32 m_nTimer;
|
||||
int16 m_eModelIndex;
|
||||
uint16 m_nIndex;
|
||||
CVector m_vecPos;
|
||||
|
||||
CObject *GiveUsAPickUpObject(int32 handle);
|
||||
bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);
|
||||
private:
|
||||
bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }
|
||||
inline bool CanBePickedUp(CPlayerPed *player);
|
||||
void RemoveKeepType();
|
||||
void Remove();
|
||||
};
|
||||
|
||||
static_assert(sizeof(CPickup) == 0x1C, "CPickup: error");
|
||||
|
||||
struct tPickupMessage
|
||||
{
|
||||
CVector2D m_pos;
|
||||
eWeaponType m_weaponType;
|
||||
CVector2D m_dist;
|
||||
CRGBA m_color;
|
||||
uint8 m_bOutOfStock : 1;
|
||||
uint8 m_quantity;
|
||||
};
|
||||
|
||||
class CPickups
|
||||
{
|
||||
static int32 aPickUpsCollected[NUMCOLLECTEDPICKUPS];
|
||||
static int16 CollectedPickUpIndex;
|
||||
static int16 NumMessages;
|
||||
static tPickupMessage aMessages[NUMPICKUPMESSAGES];
|
||||
public:
|
||||
static void Init();
|
||||
static void Update();
|
||||
static void RenderPickUpText();
|
||||
static void DoCollectableEffects(CEntity *ent);
|
||||
static void DoMoneyEffects(CEntity *ent);
|
||||
static void DoMineEffects(CEntity *ent);
|
||||
static void DoPickUpEffects(CEntity *ent);
|
||||
static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity);
|
||||
static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity);
|
||||
static void RemovePickUp(int32 pickupIndex);
|
||||
static void RemoveAllFloatingPickups();
|
||||
static void AddToCollectedPickupsArray(int32 index);
|
||||
static bool IsPickUpPickedUp(int32 pickupId);
|
||||
static int32 ModelForWeapon(eWeaponType weaponType);
|
||||
static enum eWeaponType WeaponForModel(int32 model);
|
||||
static int32 FindColourIndexForWeaponMI(int32 model);
|
||||
static int32 GetActualPickupIndex(int32 index);
|
||||
static int32 GetNewUniquePickupIndex(int32 slot);
|
||||
static void PassTime(uint32 time);
|
||||
static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex);
|
||||
static void Load(uint8 *buf, uint32 size);
|
||||
static void Save(uint8 *buf, uint32 *size);
|
||||
|
||||
static CPickup(&aPickUps)[NUMPICKUPS];
|
||||
|
||||
// unused
|
||||
static bool &bPickUpcamActivated;
|
||||
static CVehicle *&pPlayerVehicle;
|
||||
static CVector &StaticCamCoors;
|
||||
static uint32 &StaticCamStartTime;
|
||||
};
|
||||
|
||||
extern uint16 AmmoForWeapon[20];
|
||||
extern uint16 AmmoForWeapon_OnStreet[20];
|
||||
extern uint16 CostOfWeapon[20];
|
||||
|
||||
class CPacManPickups
|
||||
{
|
||||
public:
|
||||
static void Init(void);
|
||||
static void Update(void);
|
||||
static void GeneratePMPickUps(CVector, float, int16, uint8);
|
||||
static void GeneratePMPickUpsForRace(int32);
|
||||
static void GenerateOnePMPickUp(CVector);
|
||||
static void Render(void);
|
||||
static void DoCleanUpPacManStuff(void);
|
||||
static void StartPacManRace(int32);
|
||||
static void StartPacManRecord(void);
|
||||
static uint32 QueryPowerPillsEatenInRace(void);
|
||||
static void ResetPowerPillsEatenInRace(void);
|
||||
static void CleanUpPacManStuff(void);
|
||||
static void StartPacManScramble(CVector, float, int16);
|
||||
static uint32 QueryPowerPillsCarriedByPlayer(void);
|
||||
static void ResetPowerPillsCarriedByPlayer(void);
|
||||
|
||||
};
|
||||
#pragma once
|
||||
#include "Weapon.h"
|
||||
|
||||
enum ePickupType : uint8
|
||||
{
|
||||
PICKUP_NONE = 0,
|
||||
PICKUP_IN_SHOP,
|
||||
PICKUP_ON_STREET,
|
||||
PICKUP_ONCE,
|
||||
PICKUP_ONCE_TIMEOUT,
|
||||
PICKUP_COLLECTABLE1,
|
||||
PICKUP_IN_SHOP_OUT_OF_STOCK,
|
||||
PICKUP_MONEY,
|
||||
PICKUP_MINE_INACTIVE,
|
||||
PICKUP_MINE_ARMED,
|
||||
PICKUP_NAUTICAL_MINE_INACTIVE,
|
||||
PICKUP_NAUTICAL_MINE_ARMED,
|
||||
PICKUP_FLOATINGPACKAGE,
|
||||
PICKUP_FLOATINGPACKAGE_FLOATING,
|
||||
PICKUP_ON_STREET_SLOW,
|
||||
PICKUP_NUMOFTYPES
|
||||
};
|
||||
|
||||
class CEntity;
|
||||
class CObject;
|
||||
class CVehicle;
|
||||
class CPlayerPed;
|
||||
|
||||
class CPickup
|
||||
{
|
||||
public:
|
||||
ePickupType m_eType;
|
||||
bool m_bRemoved;
|
||||
uint16 m_nQuantity;
|
||||
CObject *m_pObject;
|
||||
uint32 m_nTimer;
|
||||
int16 m_eModelIndex;
|
||||
uint16 m_nIndex;
|
||||
CVector m_vecPos;
|
||||
|
||||
CObject *GiveUsAPickUpObject(int32 handle);
|
||||
bool Update(CPlayerPed *player, CVehicle *vehicle, int playerId);
|
||||
private:
|
||||
bool IsMine() { return m_eType >= PICKUP_MINE_INACTIVE && m_eType <= PICKUP_FLOATINGPACKAGE_FLOATING; }
|
||||
inline bool CanBePickedUp(CPlayerPed *player);
|
||||
void RemoveKeepType();
|
||||
void Remove();
|
||||
};
|
||||
|
||||
static_assert(sizeof(CPickup) == 0x1C, "CPickup: error");
|
||||
|
||||
struct tPickupMessage
|
||||
{
|
||||
CVector2D m_pos;
|
||||
eWeaponType m_weaponType;
|
||||
CVector2D m_dist;
|
||||
CRGBA m_color;
|
||||
uint8 m_bOutOfStock : 1;
|
||||
uint8 m_quantity;
|
||||
};
|
||||
|
||||
class CPickups
|
||||
{
|
||||
static int32 aPickUpsCollected[NUMCOLLECTEDPICKUPS];
|
||||
static int16 CollectedPickUpIndex;
|
||||
static int16 NumMessages;
|
||||
static tPickupMessage aMessages[NUMPICKUPMESSAGES];
|
||||
public:
|
||||
static void Init();
|
||||
static void Update();
|
||||
static void RenderPickUpText();
|
||||
static void DoCollectableEffects(CEntity *ent);
|
||||
static void DoMoneyEffects(CEntity *ent);
|
||||
static void DoMineEffects(CEntity *ent);
|
||||
static void DoPickUpEffects(CEntity *ent);
|
||||
static int32 GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quantity);
|
||||
static int32 GenerateNewOne_WeaponType(CVector pos, eWeaponType weaponType, uint8 type, uint32 quantity);
|
||||
static void RemovePickUp(int32 pickupIndex);
|
||||
static void RemoveAllFloatingPickups();
|
||||
static void AddToCollectedPickupsArray(int32 index);
|
||||
static bool IsPickUpPickedUp(int32 pickupId);
|
||||
static int32 ModelForWeapon(eWeaponType weaponType);
|
||||
static enum eWeaponType WeaponForModel(int32 model);
|
||||
static int32 FindColourIndexForWeaponMI(int32 model);
|
||||
static int32 GetActualPickupIndex(int32 index);
|
||||
static int32 GetNewUniquePickupIndex(int32 slot);
|
||||
static void PassTime(uint32 time);
|
||||
static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex);
|
||||
static void Load(uint8 *buf, uint32 size);
|
||||
static void Save(uint8 *buf, uint32 *size);
|
||||
|
||||
static CPickup(&aPickUps)[NUMPICKUPS];
|
||||
|
||||
// unused
|
||||
static bool &bPickUpcamActivated;
|
||||
static CVehicle *&pPlayerVehicle;
|
||||
static CVector &StaticCamCoors;
|
||||
static uint32 &StaticCamStartTime;
|
||||
};
|
||||
|
||||
extern uint16 AmmoForWeapon[20];
|
||||
extern uint16 AmmoForWeapon_OnStreet[20];
|
||||
extern uint16 CostOfWeapon[20];
|
||||
|
||||
enum ePacmanPickupType
|
||||
{
|
||||
PACMAN_NONE,
|
||||
PACMAN_SCRAMBLE,
|
||||
PACMAN_RACE,
|
||||
};
|
||||
|
||||
class CPacManPickup
|
||||
{
|
||||
public:
|
||||
CVector m_vecPosn;
|
||||
CObject *m_pObject;
|
||||
uint8 m_eType;
|
||||
|
||||
void Update();
|
||||
};
|
||||
|
||||
class CPacManPickups
|
||||
{
|
||||
friend CPacManPickup;
|
||||
|
||||
static CPacManPickup aPMPickUps[NUMPACMANPICKUPS];
|
||||
static CVector LastPickUpCoors;
|
||||
static int PillsEatenInRace;
|
||||
static bool bPMActive;
|
||||
public:
|
||||
static void Init(void);
|
||||
static void Update(void);
|
||||
static void GeneratePMPickUps(CVector, float, int16, uint8);
|
||||
static void GeneratePMPickUpsForRace(int32);
|
||||
static void GenerateOnePMPickUp(CVector);
|
||||
static void Render(void);
|
||||
static void StartPacManRace(int32);
|
||||
static void StartPacManRecord(void);
|
||||
static uint32 QueryPowerPillsEatenInRace(void);
|
||||
static void ResetPowerPillsEatenInRace(void);
|
||||
static void ClearPMPickUps(void);
|
||||
static void CleanUpPacManStuff(void);
|
||||
static void StartPacManScramble(CVector, float, int16);
|
||||
static uint32 QueryPowerPillsCarriedByPlayer(void);
|
||||
static void ResetPowerPillsCarriedByPlayer(void);
|
||||
|
||||
};
|
||||
|
@ -1,22 +1,22 @@
|
||||
#include "common.h"
|
||||
#include "PowerPoints.h"
|
||||
|
||||
// Some cut beta feature
|
||||
|
||||
void CPowerPoint::Update()
|
||||
{}
|
||||
|
||||
void CPowerPoints::Init()
|
||||
{}
|
||||
|
||||
void CPowerPoints::Update()
|
||||
{}
|
||||
|
||||
void CPowerPoints::GenerateNewOne(float, float, float, float, float, float, uint8)
|
||||
{}
|
||||
|
||||
void CPowerPoints::Save(uint8**, uint32*)
|
||||
{}
|
||||
|
||||
void CPowerPoints::Load(uint8*, uint32)
|
||||
#include "common.h"
|
||||
#include "PowerPoints.h"
|
||||
|
||||
// Some cut beta feature
|
||||
|
||||
void CPowerPoint::Update()
|
||||
{}
|
||||
|
||||
void CPowerPoints::Init()
|
||||
{}
|
||||
|
||||
void CPowerPoints::Update()
|
||||
{}
|
||||
|
||||
void CPowerPoints::GenerateNewOne(float, float, float, float, float, float, uint8)
|
||||
{}
|
||||
|
||||
void CPowerPoints::Save(uint8**, uint32*)
|
||||
{}
|
||||
|
||||
void CPowerPoints::Load(uint8*, uint32)
|
||||
{}
|
@ -1,26 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
enum
|
||||
{
|
||||
POWERPOINT_NONE = 0,
|
||||
POWERPOINT_HEALTH,
|
||||
POWERPOINT_HIDEOUT_INDUSTRIAL,
|
||||
POWERPOINT_HIDEOUT_COMMERCIAL,
|
||||
POWERPOINT_HIDEOUT_SUBURBAN
|
||||
};
|
||||
|
||||
class CPowerPoint
|
||||
{
|
||||
public:
|
||||
void Update();
|
||||
};
|
||||
|
||||
class CPowerPoints
|
||||
{
|
||||
public:
|
||||
static void Init();
|
||||
static void Update();
|
||||
static void GenerateNewOne(float, float, float, float, float, float, uint8);
|
||||
static void Save(uint8**, uint32*);
|
||||
static void Load(uint8*, uint32);
|
||||
#pragma once
|
||||
|
||||
enum
|
||||
{
|
||||
POWERPOINT_NONE = 0,
|
||||
POWERPOINT_HEALTH,
|
||||
POWERPOINT_HIDEOUT_INDUSTRIAL,
|
||||
POWERPOINT_HIDEOUT_COMMERCIAL,
|
||||
POWERPOINT_HIDEOUT_SUBURBAN
|
||||
};
|
||||
|
||||
class CPowerPoint
|
||||
{
|
||||
public:
|
||||
void Update();
|
||||
};
|
||||
|
||||
class CPowerPoints
|
||||
{
|
||||
public:
|
||||
static void Init();
|
||||
static void Update();
|
||||
static void GenerateNewOne(float, float, float, float, float, float, uint8);
|
||||
static void Save(uint8**, uint32*);
|
||||
static void Load(uint8*, uint32);
|
||||
};
|
@ -2,18 +2,522 @@
|
||||
#include "patcher.h"
|
||||
#include "Record.h"
|
||||
|
||||
#include "FileMgr.h"
|
||||
#include "Pad.h"
|
||||
#include "Pools.h"
|
||||
#include "Streaming.h"
|
||||
#include "Timer.h"
|
||||
#include "VehicleModelInfo.h"
|
||||
#include "World.h"
|
||||
|
||||
uint16 &CRecordDataForGame::RecordingState = *(uint16*)0x95CC24;
|
||||
uint8*& CRecordDataForGame::pDataBuffer = *(uint8**)0x8F1B70;
|
||||
uint8*& CRecordDataForGame::pDataBufferPointer = *(uint8**)0x8F1AB0;
|
||||
int& CRecordDataForGame::FId = *(int*)0x885BA4;
|
||||
tGameBuffer& CRecordDataForGame::pDataBufferForFrame = *(tGameBuffer*)0x72CED0;
|
||||
|
||||
uint8 &CRecordDataForChase::Status = *(uint8*)0x95CDCE;
|
||||
#define MEMORY_FOR_GAME_RECORD (150000)
|
||||
|
||||
WRAPPER void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void) { EAXJMP(0x4341F0); }
|
||||
WRAPPER void CRecordDataForGame::Init(void) { EAXJMP(0x4340F0); }
|
||||
void CRecordDataForGame::Init(void)
|
||||
{
|
||||
RecordingState = STATE_NONE;
|
||||
delete[] pDataBuffer;
|
||||
pDataBufferPointer = nil;
|
||||
pDataBuffer = nil;
|
||||
#ifndef GTA_PS2 // this stuff is not present on PS2
|
||||
FId = CFileMgr::OpenFile("playback.dat", "r");
|
||||
if (FId <= 0) {
|
||||
if ((FId = CFileMgr::OpenFile("record.dat", "r")) <= 0)
|
||||
RecordingState = STATE_NONE;
|
||||
else {
|
||||
CFileMgr::CloseFile(FId);
|
||||
FId = CFileMgr::OpenFileForWriting("record.dat");
|
||||
RecordingState = STATE_RECORD;
|
||||
}
|
||||
}
|
||||
else {
|
||||
RecordingState = STATE_PLAYBACK;
|
||||
}
|
||||
if (RecordingState == STATE_PLAYBACK) {
|
||||
pDataBufferPointer = new uint8[MEMORY_FOR_GAME_RECORD];
|
||||
pDataBuffer = pDataBufferPointer;
|
||||
pDataBuffer[CFileMgr::Read(FId, (char*)pDataBufferPointer, MEMORY_FOR_GAME_RECORD) + 8] = (uint8)-1;
|
||||
CFileMgr::CloseFile(FId);
|
||||
}
|
||||
#else
|
||||
RecordingState = STATE_NONE; // second time to make sure
|
||||
#endif
|
||||
}
|
||||
|
||||
void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void)
|
||||
{
|
||||
switch (RecordingState) {
|
||||
case STATE_RECORD:
|
||||
{
|
||||
pDataBufferForFrame.m_fTimeStep = CTimer::GetTimeStep();
|
||||
pDataBufferForFrame.m_nTimeInMilliseconds = CTimer::GetTimeInMilliseconds();
|
||||
pDataBufferForFrame.m_nSizeOfPads[0] = 0;
|
||||
pDataBufferForFrame.m_nSizeOfPads[1] = 0;
|
||||
pDataBufferForFrame.m_nChecksum = CalcGameChecksum();
|
||||
uint8* pController1 = PackCurrentPadValues(pDataBufferForFrame.m_ControllerBuffer, &CPad::GetPad(0)->OldState, &CPad::GetPad(0)->NewState);
|
||||
pDataBufferForFrame.m_nSizeOfPads[0] = (pController1 - pDataBufferForFrame.m_ControllerBuffer) / 2;
|
||||
uint8* pController2 = PackCurrentPadValues(pController1, &CPad::GetPad(1)->OldState, &CPad::GetPad(1)->NewState);
|
||||
pDataBufferForFrame.m_nSizeOfPads[1] = (pController2 - pController1) / 2;
|
||||
uint8* pEndPtr = pController2;
|
||||
if ((pDataBufferForFrame.m_nSizeOfPads[0] + pDataBufferForFrame.m_nSizeOfPads[1]) & 1)
|
||||
pEndPtr += 2;
|
||||
CFileMgr::Write(FId, (char*)&pDataBufferForFrame, pEndPtr - (uint8*)&pDataBufferForFrame);
|
||||
break;
|
||||
}
|
||||
case STATE_PLAYBACK:
|
||||
if (pDataBufferPointer[8] == (uint8)-1)
|
||||
CPad::GetPad(0)->NewState.Clear();
|
||||
else {
|
||||
tGameBuffer* pData = (tGameBuffer*)pDataBufferPointer;
|
||||
CTimer::SetTimeInMilliseconds(pData->m_nTimeInMilliseconds);
|
||||
CTimer::SetTimeStep(pData->m_fTimeStep);
|
||||
uint8 size1 = pData->m_nSizeOfPads[0];
|
||||
uint8 size2 = pData->m_nSizeOfPads[1];
|
||||
pDataBufferPointer = (uint8*)&pData->m_ControllerBuffer;
|
||||
pDataBufferPointer = UnPackCurrentPadValues(pDataBufferPointer, size1, &CPad::GetPad(0)->NewState);
|
||||
pDataBufferPointer = UnPackCurrentPadValues(pDataBufferPointer, size2, &CPad::GetPad(1)->NewState);
|
||||
if ((size1 + size2) & 1)
|
||||
pDataBufferPointer += 2;
|
||||
if (pData->m_nChecksum != CalcGameChecksum())
|
||||
printf("Playback out of sync\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define PROCESS_BUTTON_STATE_STORE(buf, os, ns, field, id) \
|
||||
do { \
|
||||
if (os->field != ns->field){ \
|
||||
*buf++ = id; \
|
||||
*buf++ = ns->field; \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
uint8* CRecordDataForGame::PackCurrentPadValues(uint8* buf, CControllerState* os, CControllerState* ns)
|
||||
{
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickX, 0);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftStickY, 1);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightStickX, 2);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightStickY, 3);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder1, 4);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShoulder2, 5);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShoulder1, 6);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShoulder2, 7);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadUp, 8);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadDown, 9);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadLeft, 10);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, DPadRight, 11);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, Start, 12);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, Select, 13);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, Square, 14);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, Triangle, 15);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, Cross, 16);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, Circle, 17);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, LeftShock, 18);
|
||||
PROCESS_BUTTON_STATE_STORE(buf, os, ns, RightShock, 19);
|
||||
return buf;
|
||||
}
|
||||
#undef PROCESS_BUTTON_STATE_STORE
|
||||
|
||||
#define PROCESS_BUTTON_STATE_RESTORE(buf, state, field, id) case id: state->field = *buf++; break;
|
||||
|
||||
uint8* CRecordDataForGame::UnPackCurrentPadValues(uint8* buf, uint8 total, CControllerState* state)
|
||||
{
|
||||
for (uint8 i = 0; i < total; i++) {
|
||||
switch (*buf++) {
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickX, 0);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickY, 1);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, RightStickX, 2);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, RightStickY, 3);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder1, 4);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder2, 5);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShoulder1, 6);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShoulder2, 7);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadUp, 8);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadDown, 9);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadLeft, 10);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, DPadRight, 11);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, Start, 12);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, Select, 13);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, Square, 14);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, Triangle, 15);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, Cross, 16);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, Circle, 17);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShock, 18);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, RightShock, 19);
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
#undef PROCESS_BUTTON_STATE_RESTORE
|
||||
|
||||
uint16 CRecordDataForGame::CalcGameChecksum(void)
|
||||
{
|
||||
uint32 checksum = 0;
|
||||
int i = CPools::GetPedPool()->GetSize();
|
||||
while (i--) {
|
||||
CPed* pPed = CPools::GetPedPool()->GetSlot(i);
|
||||
if (!pPed)
|
||||
continue;
|
||||
checksum ^= pPed->GetModelIndex() ^ *(uint32*)&pPed->GetPosition().z ^ *(uint32*)&pPed->GetPosition().y ^ *(uint32*)&pPed->GetPosition().x;
|
||||
}
|
||||
i = CPools::GetVehiclePool()->GetSize();
|
||||
while (i--) {
|
||||
CVehicle* pVehicle = CPools::GetVehiclePool()->GetSlot(i);
|
||||
if (!pVehicle)
|
||||
continue;
|
||||
checksum ^= pVehicle->GetModelIndex() ^ *(uint32*)&pVehicle->GetPosition().z ^ *(uint32*)&pVehicle->GetPosition().y ^ *(uint32*)&pVehicle->GetPosition().x;
|
||||
}
|
||||
return checksum ^ checksum >> 16;
|
||||
}
|
||||
|
||||
uint8& CRecordDataForChase::Status = *(uint8*)0x95CDCE;
|
||||
int& CRecordDataForChase::PositionChanges = *(int*)0x8F59C8;
|
||||
uint8& CRecordDataForChase::CurrentCar = *(uint8*)0x95CDC9;
|
||||
CAutomobile* (&CRecordDataForChase::pChaseCars)[NUM_CHASE_CARS] = *(CAutomobile * (*)[NUM_CHASE_CARS])*(uintptr*)0x6F46A8;
|
||||
uint32& CRecordDataForChase::AnimStartTime = *(uint32*)0x8F1AEC;
|
||||
float& CRecordDataForChase::AnimTime = *(float*)0x880F88;
|
||||
CCarStateEachFrame* (&CRecordDataForChase::pBaseMemForCar)[NUM_CHASE_CARS] = *(CCarStateEachFrame * (*)[NUM_CHASE_CARS])*(uintptr*)0x70EA18;
|
||||
float& CRecordDataForChase::TimeMultiplier = *(float*)0x8E2A94;
|
||||
int& CRecordDataForChase::FId2 = *(int*)0x8E2C18;
|
||||
|
||||
#define CHASE_SCENE_LENGTH_IN_SECONDS (80)
|
||||
#define CHASE_SCENE_FRAMES_PER_SECOND (15) // skipping every second frame
|
||||
#define CHASE_SCENE_FRAMES_IN_RECORDING (CHASE_SCENE_LENGTH_IN_SECONDS * CHASE_SCENE_FRAMES_PER_SECOND)
|
||||
#define CHASE_SCENE_LENGTH_IN_FRAMES (CHASE_SCENE_FRAMES_IN_RECORDING * 2)
|
||||
|
||||
void CRecordDataForChase::Init(void)
|
||||
{
|
||||
Status = STATE_NONE;
|
||||
PositionChanges = 0;
|
||||
CurrentCar = 0;
|
||||
for (int i = 0; i < NUM_CHASE_CARS; i++)
|
||||
pChaseCars[i] = nil;
|
||||
AnimStartTime = 0;
|
||||
}
|
||||
|
||||
void CRecordDataForChase::SaveOrRetrieveDataForThisFrame(void)
|
||||
{
|
||||
switch (Status) {
|
||||
case STATE_NONE:
|
||||
return;
|
||||
case STATE_RECORD:
|
||||
{
|
||||
if ((CTimer::GetFrameCounter() & 1) == 0)
|
||||
StoreInfoForCar(pChaseCars[CurrentCar], &pBaseMemForCar[CurrentCar][CTimer::GetFrameCounter() / 2]);
|
||||
if (CTimer::GetFrameCounter() < CHASE_SCENE_LENGTH_IN_FRAMES * 2)
|
||||
return;
|
||||
CFileMgr::SetDir("data\\paths");
|
||||
sprintf(gString, "chase%d.dat", CurrentCar);
|
||||
int fid = CFileMgr::OpenFileForWriting(gString);
|
||||
uint32 fs = CHASE_SCENE_LENGTH_IN_FRAMES * sizeof(CCarStateEachFrame);
|
||||
printf("FileSize:%d\n", fs);
|
||||
CFileMgr::Write(fid, (char*)pBaseMemForCar[CurrentCar], fs);
|
||||
CFileMgr::CloseFile(fid);
|
||||
CFileMgr::SetDir("");
|
||||
sprintf(gString, "car%d.max", CurrentCar);
|
||||
int fid2 = CFileMgr::OpenFileForWriting(gString);
|
||||
for (int i = 0; i < CHASE_SCENE_FRAMES_IN_RECORDING; i++) {
|
||||
// WTF? Was it ever used?
|
||||
#ifdef FIX_BUGS
|
||||
CCarStateEachFrame* pState = pBaseMemForCar[CurrentCar];
|
||||
#else
|
||||
CCarStateEachFrame* pState = (CCarStateEachFrame*)pChaseCars[CurrentCar];
|
||||
#endif
|
||||
CVector right = CVector(pState->rightX, pState->rightY, pState->rightZ) / INT8_MAX;
|
||||
CVector forward = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / INT8_MAX;
|
||||
CVector up = CrossProduct(right, forward);
|
||||
sprintf(gString, "%f %f %f\n", pState->pos.x, pState->pos.y, pState->pos.z);
|
||||
CFileMgr::Write(fid2, gString, strlen(gString) - 1);
|
||||
sprintf(gString, "%f %f %f\n", right.x, right.y, right.z);
|
||||
CFileMgr::Write(fid2, gString, strlen(gString) - 1);
|
||||
sprintf(gString, "%f %f %f\n", forward.x, forward.y, forward.z);
|
||||
CFileMgr::Write(fid2, gString, strlen(gString) - 1);
|
||||
sprintf(gString, "%f %f %f\n", up.x, up.y, up.z);
|
||||
CFileMgr::Write(fid2, gString, strlen(gString) - 1);
|
||||
}
|
||||
CFileMgr::CloseFile(fid2);
|
||||
}
|
||||
case STATE_PLAYBACK:
|
||||
case STATE_PLAYBACK_BEFORE_RECORDING:
|
||||
case STATE_PLAYBACK_INIT:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct tCoors {
|
||||
CVector pos;
|
||||
float angle;
|
||||
};
|
||||
|
||||
// I guess developer was filling this with actual data before running the game
|
||||
tCoors NewCoorsForRecordedCars[7];
|
||||
|
||||
void CRecordDataForChase::SaveOrRetrieveCarPositions(void)
|
||||
{
|
||||
switch (Status) {
|
||||
case STATE_NONE:
|
||||
return;
|
||||
case STATE_RECORD:
|
||||
case STATE_PLAYBACK_BEFORE_RECORDING:
|
||||
for (int i = 0; i < NUM_CHASE_CARS; i++) {
|
||||
if (i != CurrentCar && CTimer::GetFrameCounter()) {
|
||||
RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][CTimer::GetFrameCounter() / 2], false);
|
||||
pChaseCars[i]->GetMatrix().UpdateRW();
|
||||
pChaseCars[i]->UpdateRwFrame();
|
||||
}
|
||||
}
|
||||
if (Status == STATE_PLAYBACK_BEFORE_RECORDING && CTimer::GetFrameCounter()) {
|
||||
RestoreInfoForCar(pChaseCars[CurrentCar], &pBaseMemForCar[CurrentCar][CTimer::GetFrameCounter() / 2], false);
|
||||
pChaseCars[CurrentCar]->GetMatrix().UpdateRW();
|
||||
pChaseCars[CurrentCar]->UpdateRwFrame();
|
||||
}
|
||||
if (CPad::GetPad(0)->GetLeftShockJustDown() && CPad::GetPad(0)->GetRightShockJustDown()) {
|
||||
if (!CPad::GetPad(0)->GetRightShockJustDown()) {
|
||||
pChaseCars[CurrentCar]->GetPosition() = NewCoorsForRecordedCars[PositionChanges].pos;
|
||||
pChaseCars[CurrentCar]->SetMoveSpeed(0.0f, 0.0f, 0.0f);
|
||||
pChaseCars[CurrentCar]->GetMatrix().SetRotateZOnly(DEGTORAD(NewCoorsForRecordedCars[PositionChanges].angle));
|
||||
++PositionChanges;
|
||||
}
|
||||
if (Status == STATE_PLAYBACK_BEFORE_RECORDING) {
|
||||
Status = STATE_RECORD;
|
||||
pChaseCars[CurrentCar]->m_status = STATUS_PLAYER;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATE_PLAYBACK_INIT:
|
||||
Status = STATE_PLAYBACK;
|
||||
break;
|
||||
case STATE_PLAYBACK:
|
||||
{
|
||||
TimeMultiplier += CTimer::GetTimeStepNonClippedInSeconds();
|
||||
float EndOfFrameTime = CHASE_SCENE_FRAMES_PER_SECOND * min(CHASE_SCENE_LENGTH_IN_SECONDS, TimeMultiplier);
|
||||
for (int i = 0; i < NUM_CHASE_CARS; i++) {
|
||||
if (!pBaseMemForCar[i])
|
||||
continue;
|
||||
if (!pChaseCars[i])
|
||||
continue;
|
||||
if (EndOfFrameTime < CHASE_SCENE_FRAMES_IN_RECORDING - 1) {
|
||||
int FlooredEOFTime = EndOfFrameTime;
|
||||
RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][FlooredEOFTime], false);
|
||||
CMatrix tmp;
|
||||
float dp = EndOfFrameTime - FlooredEOFTime;
|
||||
RestoreInfoForMatrix(tmp, &pBaseMemForCar[i][FlooredEOFTime + 1]);
|
||||
pChaseCars[i]->GetRight() += (tmp.GetRight() - pChaseCars[i]->GetRight()) * dp;
|
||||
pChaseCars[i]->GetForward() += (tmp.GetForward() - pChaseCars[i]->GetForward()) * dp;
|
||||
pChaseCars[i]->GetUp() += (tmp.GetUp() - pChaseCars[i]->GetUp()) * dp;
|
||||
pChaseCars[i]->GetPosition() += (tmp.GetPosition() - pChaseCars[i]->GetPosition()) * dp;
|
||||
}
|
||||
else{
|
||||
RestoreInfoForCar(pChaseCars[i], &pBaseMemForCar[i][CHASE_SCENE_FRAMES_IN_RECORDING - 1], true);
|
||||
if (i == 0)
|
||||
pChaseCars[i]->GetPosition().z += 0.2f;
|
||||
}
|
||||
pChaseCars[i]->GetMatrix().UpdateRW();
|
||||
pChaseCars[i]->UpdateRwFrame();
|
||||
pChaseCars[i]->RemoveAndAdd();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CRecordDataForChase::StoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* pState)
|
||||
{
|
||||
pState->rightX = INT8_MAX * pCar->GetRight().x;
|
||||
pState->rightY = INT8_MAX * pCar->GetRight().y;
|
||||
pState->rightZ = INT8_MAX * pCar->GetRight().z;
|
||||
pState->forwardX = INT8_MAX * pCar->GetForward().x;
|
||||
pState->forwardY = INT8_MAX * pCar->GetForward().y;
|
||||
pState->forwardZ = INT8_MAX * pCar->GetForward().z;
|
||||
pState->pos = pCar->GetPosition();
|
||||
pState->velX = 0.5f * INT16_MAX * pCar->GetMoveSpeed().x;
|
||||
pState->velY = 0.5f * INT16_MAX * pCar->GetMoveSpeed().y;
|
||||
pState->velZ = 0.5f * INT16_MAX * pCar->GetMoveSpeed().z;
|
||||
pState->wheel = 20 * pCar->m_fSteerAngle;
|
||||
pState->gas = 100 * pCar->m_fGasPedal;
|
||||
pState->brake = 100 * pCar->m_fBrakePedal;
|
||||
pState->handbrake = pCar->bIsHandbrakeOn;
|
||||
}
|
||||
|
||||
void CRecordDataForChase::RestoreInfoForMatrix(CMatrix& matrix, CCarStateEachFrame* pState)
|
||||
{
|
||||
matrix.GetRight() = CVector(pState->rightX, pState->rightY, pState->rightZ) / INT8_MAX;
|
||||
matrix.GetForward() = CVector(pState->forwardX, pState->forwardY, pState->forwardZ) / INT8_MAX;
|
||||
matrix.GetUp() = CrossProduct(matrix.GetRight(), matrix.GetForward());
|
||||
matrix.GetPosition() = pState->pos;
|
||||
}
|
||||
|
||||
void CRecordDataForChase::RestoreInfoForCar(CAutomobile* pCar, CCarStateEachFrame* pState, bool stop)
|
||||
{
|
||||
CVector oldPos = pCar->GetPosition();
|
||||
RestoreInfoForMatrix(pCar->GetMatrix(), pState);
|
||||
pCar->SetMoveSpeed(CVector(pState->velX, pState->velY, pState->velZ) / INT16_MAX / 0.5f);
|
||||
pCar->SetTurnSpeed(0.0f, 0.0f, 0.0f);
|
||||
pCar->m_fSteerAngle = pState->wheel / 20.0f;
|
||||
pCar->m_fGasPedal = pState->gas / 100.0f;
|
||||
pCar->m_fBrakePedal = pState->brake / 100.0f;
|
||||
pCar->bIsHandbrakeOn = pState->handbrake;
|
||||
if ((oldPos - pCar->GetPosition()).Magnitude() > 15.0f) {
|
||||
if (pCar == pChaseCars[14]) {
|
||||
pCar->m_currentColour1 = 58;
|
||||
pCar->m_currentColour2 = 1;
|
||||
}
|
||||
else
|
||||
pCar->GetModelInfo()->ChooseVehicleColour(pCar->m_currentColour1, pCar->m_currentColour2);
|
||||
}
|
||||
pCar->m_fHealth = min(pCar->m_fHealth, 500.0f);
|
||||
if (stop) {
|
||||
pCar->m_fGasPedal = 0.0f;
|
||||
pCar->m_fBrakePedal = 0.0f;
|
||||
pCar->SetMoveSpeed(0.0f, 0.0f, 0.0f);
|
||||
pCar->bIsHandbrakeOn = false;
|
||||
}
|
||||
}
|
||||
|
||||
void CRecordDataForChase::ProcessControlCars(void)
|
||||
{
|
||||
if (Status != STATE_PLAYBACK)
|
||||
return;
|
||||
for (int i = 0; i < NUM_CHASE_CARS; i++) {
|
||||
if (pChaseCars[i])
|
||||
pChaseCars[i]->ProcessControl();
|
||||
}
|
||||
}
|
||||
|
||||
#if (defined(GTA_PS2) || defined(FIX_BUGS))
|
||||
bool CRecordDataForChase::ShouldThisPadBeLeftAlone(uint8 pad)
|
||||
{
|
||||
// may be wrong
|
||||
if (Status == STATE_NONE || Status == STATE_PLAYBACK)
|
||||
return false;
|
||||
return pad != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void CRecordDataForChase::GiveUsACar(int32 mi, CVector pos, float angle, CAutomobile** ppCar, uint8 colour1, uint8 colour2)
|
||||
{
|
||||
CStreaming::RequestModel(mi, STREAMFLAGS_DEPENDENCY);
|
||||
CStreaming::LoadAllRequestedModels(false);
|
||||
if (!CStreaming::HasModelLoaded(mi))
|
||||
return;
|
||||
CAutomobile* pCar = new CAutomobile(mi, MISSION_VEHICLE);
|
||||
pCar->GetPosition() = pos;
|
||||
pCar->m_status = STATUS_PLAYER_PLAYBACKFROMBUFFER;
|
||||
pCar->GetMatrix().SetRotateZOnly(DEGTORAD(angle));
|
||||
pCar->pDriver = nil;
|
||||
pCar->m_currentColour1 = colour1;
|
||||
pCar->m_currentColour2 = colour2;
|
||||
CWorld::Add(pCar);
|
||||
*ppCar = pCar;
|
||||
}
|
||||
|
||||
void RemoveUnusedCollision(void)
|
||||
{
|
||||
static const char* dontDeleteArray[] = {
|
||||
"rd_SrRoad2A50", "rd_SrRoad2A20", "rd_CrossRda1w22", "rd_CrossRda1rw22",
|
||||
"road_broadway02", "road_broadway01", "com_21way5", "com_21way50",
|
||||
"cm1waycrosscom", "com_21way20", "com_21way10", "road_broadway04",
|
||||
"com_rvroads52", "com_roadsrv", "com_roadkb23", "com_roadkb22"
|
||||
};
|
||||
for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++)
|
||||
CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_NONE;
|
||||
CModelInfo::RemoveColModelsFromOtherLevels(LEVEL_NONE);
|
||||
for (int i = 0; i < ARRAY_SIZE(dontDeleteArray); i++)
|
||||
CModelInfo::GetModelInfo(dontDeleteArray[i], nil)->GetColModel()->level = LEVEL_COMMERCIAL;
|
||||
}
|
||||
|
||||
void CRecordDataForChase::StartChaseScene(float startTime)
|
||||
{
|
||||
char filename[28];
|
||||
SetUpCarsForChaseScene();
|
||||
Status = STATE_PLAYBACK;
|
||||
AnimTime = startTime;
|
||||
AnimStartTime = CTimer::GetTimeInMilliseconds();
|
||||
RemoveUnusedCollision();
|
||||
CStreaming::RemoveIslandsNotUsed(LEVEL_SUBURBAN);
|
||||
CGame::TidyUpMemory(true, true);
|
||||
CStreaming::ImGonnaUseStreamingMemory();
|
||||
CFileMgr::SetDir("data\\paths");
|
||||
for (int i = 0; i < NUM_CHASE_CARS; i++) {
|
||||
if (!pChaseCars[i]) {
|
||||
pBaseMemForCar[i] = nil;
|
||||
continue;
|
||||
}
|
||||
sprintf(filename, "chase%d.dat", i);
|
||||
FId2 = CFileMgr::OpenFile(filename, "rb");
|
||||
if (FId2 <= 0) {
|
||||
pBaseMemForCar[i] = nil;
|
||||
continue;
|
||||
}
|
||||
pBaseMemForCar[i] = new CCarStateEachFrame[CHASE_SCENE_FRAMES_IN_RECORDING];
|
||||
for (int j = 0; j < CHASE_SCENE_FRAMES_IN_RECORDING; j++) {
|
||||
CFileMgr::Read(FId2, (char*)&pBaseMemForCar[i][j], sizeof(CCarStateEachFrame));
|
||||
CFileMgr::Seek(FId2, sizeof(CCarStateEachFrame), 1);
|
||||
}
|
||||
CFileMgr::CloseFile(FId2);
|
||||
}
|
||||
CFileMgr::SetDir("");
|
||||
CStreaming::IHaveUsedStreamingMemory();
|
||||
TimeMultiplier = 0.0f;
|
||||
}
|
||||
|
||||
void CRecordDataForChase::CleanUpChaseScene(void)
|
||||
{
|
||||
if (Status != STATE_PLAYBACK_INIT && Status != STATE_PLAYBACK)
|
||||
return;
|
||||
Status = STATE_NONE;
|
||||
CleanUpCarsForChaseScene();
|
||||
for (int i = 0; i < NUM_CHASE_CARS; i++) {
|
||||
if (pBaseMemForCar[i]) {
|
||||
delete[] pBaseMemForCar[i];
|
||||
pBaseMemForCar[i] = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CRecordDataForChase::SetUpCarsForChaseScene(void)
|
||||
{
|
||||
GiveUsACar(MI_POLICE, CVector(273.54221f, -1167.1907f, 24.880601f), 63.0f, &pChaseCars[0], 2, 1);
|
||||
GiveUsACar(MI_ENFORCER, CVector(231.1783f, -1388.8322f, 25.978201f), 90.0f, &pChaseCars[1], 2, 1);
|
||||
GiveUsACar(MI_TAXI, CVector(184.3156f, -1473.251f, 25.978201f), 0.0f, &pChaseCars[4], 6, 6);
|
||||
GiveUsACar(MI_CHEETAH, CVector(173.8868f, -1377.6514f, 25.978201f), 0.0f, &pChaseCars[6], 4, 5);
|
||||
GiveUsACar(MI_STINGER, CVector(102.5946f, -943.93628f, 25.9781f), 270.0f, &pChaseCars[7], 53, 53);
|
||||
GiveUsACar(MI_CHEETAH, CVector(-177.7157f, -862.18652f, 25.978201f), 155.0f, &pChaseCars[10], 41, 1);
|
||||
GiveUsACar(MI_STINGER, CVector(-170.56979f, -889.02362f, 25.978201f), 154.0f, &pChaseCars[11], 10, 10);
|
||||
GiveUsACar(MI_KURUMA, CVector(402.60809f, -917.49628f, 37.381001f), 90.0f, &pChaseCars[14], 34, 1);
|
||||
GiveUsACar(MI_TAXI, CVector(-33.496201f, -938.4563f, 25.9781f), 266.0f, &pChaseCars[16], 6, 6);
|
||||
GiveUsACar(MI_KURUMA, CVector(49.363098f, -987.60498f, 25.9781f), 0.0f, &pChaseCars[18], 51, 1);
|
||||
GiveUsACar(MI_TAXI, CVector(179.0049f, -1154.6686f, 25.9781f), 0.0f, &pChaseCars[19], 6, 76);
|
||||
GiveUsACar(MI_RUMPO, CVector(-28.9762f, -1031.3367f, 25.990601f), 242.0f, &pChaseCars[2], 1, 75);
|
||||
GiveUsACar(MI_PATRIOT, CVector(114.1564f, -796.69379f, 24.978201f), 180.0f, &pChaseCars[3], 0, 0);
|
||||
}
|
||||
|
||||
void CRecordDataForChase::CleanUpCarsForChaseScene(void)
|
||||
{
|
||||
for (int i = 0; i < NUM_CHASE_CARS; i++)
|
||||
RemoveCarFromChase(i);
|
||||
}
|
||||
|
||||
void CRecordDataForChase::RemoveCarFromChase(int32 i)
|
||||
{
|
||||
if (!pChaseCars[i])
|
||||
return;
|
||||
CWorld::Remove(pChaseCars[i]);
|
||||
delete pChaseCars[i];
|
||||
pChaseCars[i] = nil;
|
||||
}
|
||||
|
||||
CVehicle* CRecordDataForChase::TurnChaseCarIntoScriptCar(int32 i)
|
||||
{
|
||||
CVehicle* pVehicle = pChaseCars[i];
|
||||
pChaseCars[i] = nil;
|
||||
pVehicle->m_status = STATUS_PHYSICS;
|
||||
return pVehicle;
|
||||
}
|
||||
|
||||
WRAPPER void CRecordDataForChase::SaveOrRetrieveDataForThisFrame(void) { EAXJMP(0x4347F0); }
|
||||
WRAPPER void CRecordDataForChase::ProcessControlCars(void) { EAXJMP(0x435540); }
|
||||
WRAPPER void CRecordDataForChase::SaveOrRetrieveCarPositions(void) { EAXJMP(0x434B20); }
|
||||
WRAPPER void CRecordDataForChase::StartChaseScene(float) { EAXJMP(0x435690); }
|
||||
WRAPPER void CRecordDataForChase::CleanUpChaseScene() { EAXJMP(0x4357C0); }
|
||||
WRAPPER void CRecordDataForChase::RemoveCarFromChase(int32) { EAXJMP(0x435BC0); }
|
||||
WRAPPER CVehicle* CRecordDataForChase::TurnChaseCarIntoScriptCar(int32) { EAXJMP(0x435C00); }
|
||||
WRAPPER void CRecordDataForChase::Init(void) { EAXJMP(0x434780); }
|
||||
|
@ -1,34 +1,106 @@
|
||||
#pragma once
|
||||
|
||||
class CAutomobile;
|
||||
class CVehicle;
|
||||
class CControllerState;
|
||||
|
||||
enum {
|
||||
RECORDSTATE_0,
|
||||
RECORDSTATE_1,
|
||||
RECORDSTATE_2,
|
||||
class CCarStateEachFrame
|
||||
{
|
||||
public:
|
||||
int16 velX;
|
||||
int16 velY;
|
||||
int16 velZ;
|
||||
int8 rightX;
|
||||
int8 rightY;
|
||||
int8 rightZ;
|
||||
int8 forwardX;
|
||||
int8 forwardY;
|
||||
int8 forwardZ;
|
||||
int8 wheel;
|
||||
uint8 gas;
|
||||
uint8 brake;
|
||||
bool handbrake;
|
||||
CVector pos;
|
||||
};
|
||||
|
||||
extern char* gString;
|
||||
|
||||
class CRecordDataForChase
|
||||
{
|
||||
public:
|
||||
enum {
|
||||
NUM_CHASE_CARS = 20
|
||||
};
|
||||
enum {
|
||||
STATE_NONE = 0,
|
||||
STATE_RECORD = 1,
|
||||
STATE_PLAYBACK_INIT = 2,
|
||||
STATE_PLAYBACK = 3,
|
||||
STATE_PLAYBACK_BEFORE_RECORDING = 4
|
||||
};
|
||||
static uint8 &Status;
|
||||
static int &PositionChanges;
|
||||
static uint8 &CurrentCar;
|
||||
static CAutomobile*(&pChaseCars)[NUM_CHASE_CARS];
|
||||
static float &AnimTime;
|
||||
static uint32 &AnimStartTime;
|
||||
static CCarStateEachFrame* (&pBaseMemForCar)[NUM_CHASE_CARS];
|
||||
static float &TimeMultiplier;
|
||||
static int &FId2;
|
||||
public:
|
||||
|
||||
static bool IsRecording(void) { return Status == STATE_RECORD; }
|
||||
|
||||
static void Init(void);
|
||||
static void SaveOrRetrieveDataForThisFrame(void);
|
||||
static void ProcessControlCars(void);
|
||||
static void SaveOrRetrieveCarPositions(void);
|
||||
static void StoreInfoForCar(CAutomobile*, CCarStateEachFrame*);
|
||||
static void RestoreInfoForMatrix(CMatrix&, CCarStateEachFrame*);
|
||||
static void RestoreInfoForCar(CAutomobile*, CCarStateEachFrame*, bool);
|
||||
static void ProcessControlCars(void);
|
||||
#if (defined(GTA_PS2) || defined(FIX_BUGS))
|
||||
static bool ShouldThisPadBeLeftAlone(uint8 pad);
|
||||
#endif
|
||||
static void GiveUsACar(int32, CVector, float, CAutomobile**, uint8, uint8);
|
||||
static void StartChaseScene(float);
|
||||
static void CleanUpChaseScene();
|
||||
static void CleanUpChaseScene(void);
|
||||
static void SetUpCarsForChaseScene(void);
|
||||
static void CleanUpCarsForChaseScene(void);
|
||||
static void RemoveCarFromChase(int32);
|
||||
static CVehicle* TurnChaseCarIntoScriptCar(int32);
|
||||
static void Init(void);
|
||||
|
||||
};
|
||||
|
||||
struct tGameBuffer
|
||||
{
|
||||
float m_fTimeStep;
|
||||
uint32 m_nTimeInMilliseconds;
|
||||
uint8 m_nSizeOfPads[2];
|
||||
uint16 m_nChecksum;
|
||||
uint8 m_ControllerBuffer[116];
|
||||
};
|
||||
|
||||
class CRecordDataForGame
|
||||
{
|
||||
enum {
|
||||
STATE_NONE = 0,
|
||||
STATE_RECORD = 1,
|
||||
STATE_PLAYBACK = 2,
|
||||
};
|
||||
static uint16& RecordingState;
|
||||
static uint8* &pDataBuffer;
|
||||
static uint8* &pDataBufferPointer;
|
||||
static int &FId;
|
||||
static tGameBuffer &pDataBufferForFrame;
|
||||
|
||||
public:
|
||||
static uint16 &RecordingState;
|
||||
static bool IsRecording() { return RecordingState == STATE_RECORD; }
|
||||
static bool IsPlayingBack() { return RecordingState == STATE_PLAYBACK; }
|
||||
|
||||
static void SaveOrRetrieveDataForThisFrame(void);
|
||||
static void Init(void);
|
||||
|
||||
private:
|
||||
static uint16 CalcGameChecksum(void);
|
||||
static uint8* PackCurrentPadValues(uint8*, CControllerState*, CControllerState*);
|
||||
static uint8* UnPackCurrentPadValues(uint8*, uint8, CControllerState*);
|
||||
};
|
||||
|
@ -1107,7 +1107,7 @@ void CReplay::TriggerPlayback(uint8 cam_mode, float cam_x, float cam_y, float ca
|
||||
CStreaming::LoadScene(ff_coord);
|
||||
}
|
||||
if (cam_mode == REPLAYCAMMODE_ASSTORED)
|
||||
TheCamera.CarZoomIndicator = 5.0f;
|
||||
TheCamera.CarZoomIndicator = CAM_ZOOM_CINEMATIC;
|
||||
}
|
||||
|
||||
void CReplay::StoreStuffInMem(void)
|
||||
@ -1129,8 +1129,8 @@ void CReplay::StoreStuffInMem(void)
|
||||
pEmptyReferences = CReferences::pEmptyList;
|
||||
pStoredCam = new uint8[sizeof(CCamera)];
|
||||
memcpy(pStoredCam, &TheCamera, sizeof(CCamera));
|
||||
pRadarBlips = new uint8[sizeof(CBlip) * NUMRADARBLIPS];
|
||||
memcpy(pRadarBlips, CRadar::ms_RadarTrace, NUMRADARBLIPS * sizeof(CBlip));
|
||||
pRadarBlips = new uint8[sizeof(sRadarTrace) * NUMRADARBLIPS];
|
||||
memcpy(pRadarBlips, CRadar::ms_RadarTrace, NUMRADARBLIPS * sizeof(sRadarTrace));
|
||||
PlayerWanted = *FindPlayerPed()->m_pWanted;
|
||||
PlayerInfo = CWorld::Players[0];
|
||||
Time1 = CTimer::GetTimeInMilliseconds();
|
||||
@ -1179,7 +1179,7 @@ void CReplay::RestoreStuffFromMem(void)
|
||||
memcpy(&TheCamera, pStoredCam, sizeof(CCamera));
|
||||
delete[] pStoredCam;
|
||||
pStoredCam = nil;
|
||||
memcpy(CRadar::ms_RadarTrace, pRadarBlips, sizeof(CBlip) * NUMRADARBLIPS);
|
||||
memcpy(CRadar::ms_RadarTrace, pRadarBlips, sizeof(sRadarTrace) * NUMRADARBLIPS);
|
||||
delete[] pRadarBlips;
|
||||
pRadarBlips = nil;
|
||||
FindPlayerPed()->m_pWanted = new CWanted(PlayerWanted);
|
||||
|
@ -21,234 +21,234 @@ CVector(&CRestart::PoliceRestartPoints)[NUM_RESTART_POINTS] = *(CVector(*)[NUM_R
|
||||
float(&CRestart::PoliceRestartHeadings)[NUM_RESTART_POINTS] = *(float(*)[NUM_RESTART_POINTS])*(uintptr*)0x6F1D20;
|
||||
uint16 &CRestart::NumberOfPoliceRestarts = *(uint16*)0x95CC44;
|
||||
|
||||
void
|
||||
CRestart::Initialise()
|
||||
{
|
||||
OverridePoliceStationLevel = LEVEL_NONE;
|
||||
OverrideHospitalLevel = LEVEL_NONE;
|
||||
bFadeInAfterNextArrest = true;
|
||||
bFadeInAfterNextDeath = true;
|
||||
OverrideHeading = 0.0f;
|
||||
OverridePosition = CVector(0.0f, 0.0f, 0.0f);
|
||||
bOverrideRestart = false;
|
||||
NumberOfPoliceRestarts = 0;
|
||||
NumberOfHospitalRestarts = 0;
|
||||
|
||||
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
|
||||
HospitalRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
|
||||
HospitalRestartHeadings[i] = 0.0f;
|
||||
PoliceRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
|
||||
PoliceRestartHeadings[i] = 0.0f;
|
||||
}
|
||||
void
|
||||
CRestart::Initialise()
|
||||
{
|
||||
OverridePoliceStationLevel = LEVEL_NONE;
|
||||
OverrideHospitalLevel = LEVEL_NONE;
|
||||
bFadeInAfterNextArrest = true;
|
||||
bFadeInAfterNextDeath = true;
|
||||
OverrideHeading = 0.0f;
|
||||
OverridePosition = CVector(0.0f, 0.0f, 0.0f);
|
||||
bOverrideRestart = false;
|
||||
NumberOfPoliceRestarts = 0;
|
||||
NumberOfHospitalRestarts = 0;
|
||||
|
||||
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
|
||||
HospitalRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
|
||||
HospitalRestartHeadings[i] = 0.0f;
|
||||
PoliceRestartPoints[i] = CVector(0.0f, 0.0f, 0.0f);
|
||||
PoliceRestartHeadings[i] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CRestart::AddHospitalRestartPoint(const CVector &pos, float heading)
|
||||
{
|
||||
HospitalRestartPoints[NumberOfHospitalRestarts] = pos;
|
||||
HospitalRestartHeadings[NumberOfHospitalRestarts++] = heading;
|
||||
void
|
||||
CRestart::AddHospitalRestartPoint(const CVector &pos, float heading)
|
||||
{
|
||||
HospitalRestartPoints[NumberOfHospitalRestarts] = pos;
|
||||
HospitalRestartHeadings[NumberOfHospitalRestarts++] = heading;
|
||||
}
|
||||
|
||||
void
|
||||
CRestart::AddPoliceRestartPoint(const CVector &pos, float heading)
|
||||
{
|
||||
PoliceRestartPoints[NumberOfPoliceRestarts] = pos;
|
||||
PoliceRestartHeadings[NumberOfPoliceRestarts++] = heading;
|
||||
void
|
||||
CRestart::AddPoliceRestartPoint(const CVector &pos, float heading)
|
||||
{
|
||||
PoliceRestartPoints[NumberOfPoliceRestarts] = pos;
|
||||
PoliceRestartHeadings[NumberOfPoliceRestarts++] = heading;
|
||||
}
|
||||
|
||||
void
|
||||
CRestart::OverrideNextRestart(const CVector &pos, float heading)
|
||||
{
|
||||
bOverrideRestart = true;
|
||||
OverridePosition = pos;
|
||||
OverrideHeading = heading;
|
||||
void
|
||||
CRestart::OverrideNextRestart(const CVector &pos, float heading)
|
||||
{
|
||||
bOverrideRestart = true;
|
||||
OverridePosition = pos;
|
||||
OverrideHeading = heading;
|
||||
}
|
||||
|
||||
void
|
||||
CRestart::CancelOverrideRestart()
|
||||
{
|
||||
bOverrideRestart = false;
|
||||
void
|
||||
CRestart::CancelOverrideRestart()
|
||||
{
|
||||
bOverrideRestart = false;
|
||||
}
|
||||
|
||||
void
|
||||
CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
|
||||
{
|
||||
if (bOverrideRestart) {
|
||||
*outPos = OverridePosition;
|
||||
*outHeading = OverrideHeading;
|
||||
CancelOverrideRestart();
|
||||
return;
|
||||
}
|
||||
|
||||
eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
|
||||
float fMinDist = 16000000.0f;
|
||||
int closestPoint = NUM_RESTART_POINTS;
|
||||
|
||||
// find closest point on this level
|
||||
for (int i = 0; i < NumberOfHospitalRestarts; i++) {
|
||||
if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) {
|
||||
float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
|
||||
if (fMinDist >= dist) {
|
||||
fMinDist = dist;
|
||||
closestPoint = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we didn't find anything, find closest point on any level
|
||||
if (closestPoint == NUM_RESTART_POINTS) {
|
||||
for (int i = 0; i < NumberOfHospitalRestarts; i++) {
|
||||
float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
|
||||
if (fMinDist >= dist) {
|
||||
fMinDist = dist;
|
||||
closestPoint = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we still didn't find anything, find closest path node
|
||||
if (closestPoint == NUM_RESTART_POINTS) {
|
||||
*outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
|
||||
*outHeading = 0.0f;
|
||||
printf("Couldn't find a hospital restart zone near the player %f %f %f->%f %f %f\n", pos.x, pos.y, pos.z, outPos->x, outPos->y, outPos->z);
|
||||
} else {
|
||||
*outPos = HospitalRestartPoints[closestPoint];
|
||||
*outHeading = HospitalRestartHeadings[closestPoint];
|
||||
}
|
||||
void
|
||||
CRestart::FindClosestHospitalRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
|
||||
{
|
||||
if (bOverrideRestart) {
|
||||
*outPos = OverridePosition;
|
||||
*outHeading = OverrideHeading;
|
||||
CancelOverrideRestart();
|
||||
return;
|
||||
}
|
||||
|
||||
eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
|
||||
float fMinDist = 16000000.0f;
|
||||
int closestPoint = NUM_RESTART_POINTS;
|
||||
|
||||
// find closest point on this level
|
||||
for (int i = 0; i < NumberOfHospitalRestarts; i++) {
|
||||
if (CTheZones::FindZoneForPoint(HospitalRestartPoints[i]) == (OverrideHospitalLevel != LEVEL_NONE ? OverrideHospitalLevel : curlevel)) {
|
||||
float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
|
||||
if (fMinDist >= dist) {
|
||||
fMinDist = dist;
|
||||
closestPoint = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we didn't find anything, find closest point on any level
|
||||
if (closestPoint == NUM_RESTART_POINTS) {
|
||||
for (int i = 0; i < NumberOfHospitalRestarts; i++) {
|
||||
float dist = (pos - HospitalRestartPoints[i]).MagnitudeSqr();
|
||||
if (fMinDist >= dist) {
|
||||
fMinDist = dist;
|
||||
closestPoint = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we still didn't find anything, find closest path node
|
||||
if (closestPoint == NUM_RESTART_POINTS) {
|
||||
*outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
|
||||
*outHeading = 0.0f;
|
||||
printf("Couldn't find a hospital restart zone near the player %f %f %f->%f %f %f\n", pos.x, pos.y, pos.z, outPos->x, outPos->y, outPos->z);
|
||||
} else {
|
||||
*outPos = HospitalRestartPoints[closestPoint];
|
||||
*outHeading = HospitalRestartHeadings[closestPoint];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
|
||||
{
|
||||
if (bOverrideRestart) {
|
||||
*outPos = OverridePosition;
|
||||
*outHeading = OverrideHeading;
|
||||
CancelOverrideRestart();
|
||||
return;
|
||||
}
|
||||
|
||||
eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
|
||||
float fMinDist = 16000000.0f;
|
||||
int closestPoint = NUM_RESTART_POINTS;
|
||||
|
||||
// find closest point on this level
|
||||
for (int i = 0; i < NumberOfPoliceRestarts; i++) {
|
||||
if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) {
|
||||
float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
|
||||
if (fMinDist >= dist) {
|
||||
fMinDist = dist;
|
||||
closestPoint = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we didn't find anything, find closest point on any level
|
||||
if (closestPoint == NUM_RESTART_POINTS) {
|
||||
for (int i = 0; i < NumberOfPoliceRestarts; i++) {
|
||||
float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
|
||||
if (fMinDist >= dist) {
|
||||
fMinDist = dist;
|
||||
closestPoint = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we still didn't find anything, find closest path node
|
||||
if (closestPoint == NUM_RESTART_POINTS) {
|
||||
printf("Couldn't find a police restart zone near the player\n");
|
||||
*outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
|
||||
*outHeading = 0.0f;
|
||||
} else {
|
||||
*outPos = PoliceRestartPoints[closestPoint];
|
||||
*outHeading = PoliceRestartHeadings[closestPoint];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CRestart::LoadAllRestartPoints(uint8 *buf, uint32 size)
|
||||
{
|
||||
Initialise();
|
||||
|
||||
INITSAVEBUF
|
||||
CheckSaveHeader(buf, 'R','S','T','\0', size - SAVE_HEADER_SIZE);
|
||||
|
||||
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
|
||||
HospitalRestartPoints[i] = ReadSaveBuf<CVector>(buf);
|
||||
HospitalRestartHeadings[i] = ReadSaveBuf<float>(buf);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
|
||||
PoliceRestartPoints[i] = ReadSaveBuf<CVector>(buf);
|
||||
PoliceRestartHeadings[i] = ReadSaveBuf<float>(buf);
|
||||
}
|
||||
|
||||
NumberOfHospitalRestarts = ReadSaveBuf<uint16>(buf);
|
||||
NumberOfPoliceRestarts = ReadSaveBuf<uint16>(buf);
|
||||
bOverrideRestart = ReadSaveBuf<bool>(buf);
|
||||
|
||||
// skip something unused
|
||||
ReadSaveBuf<uint8>(buf);
|
||||
ReadSaveBuf<uint16>(buf);
|
||||
|
||||
OverridePosition = ReadSaveBuf<CVector>(buf);
|
||||
OverrideHeading = ReadSaveBuf<float>(buf);
|
||||
bFadeInAfterNextDeath = ReadSaveBuf<bool>(buf);
|
||||
bFadeInAfterNextArrest = ReadSaveBuf<bool>(buf);
|
||||
OverrideHospitalLevel = ReadSaveBuf<uint8>(buf);
|
||||
OverridePoliceStationLevel = ReadSaveBuf<uint8>(buf);
|
||||
VALIDATESAVEBUF(size);
|
||||
}
|
||||
|
||||
void
|
||||
CRestart::SaveAllRestartPoints(uint8 *buf, uint32 *size)
|
||||
{
|
||||
*size = SAVE_HEADER_SIZE
|
||||
+ sizeof(HospitalRestartPoints)
|
||||
+ sizeof(HospitalRestartHeadings)
|
||||
+ sizeof(PoliceRestartPoints)
|
||||
+ sizeof(PoliceRestartHeadings)
|
||||
+ sizeof(NumberOfHospitalRestarts)
|
||||
+ sizeof(NumberOfPoliceRestarts)
|
||||
+ sizeof(bOverrideRestart)
|
||||
+ sizeof(uint8)
|
||||
+ sizeof(uint16)
|
||||
+ sizeof(OverridePosition)
|
||||
+ sizeof(OverrideHeading)
|
||||
+ sizeof(bFadeInAfterNextDeath)
|
||||
+ sizeof(bFadeInAfterNextArrest)
|
||||
+ sizeof(OverrideHospitalLevel)
|
||||
+ sizeof(OverridePoliceStationLevel); // == 292
|
||||
|
||||
INITSAVEBUF
|
||||
WriteSaveHeader(buf, 'R','S','T','\0', *size - SAVE_HEADER_SIZE);
|
||||
|
||||
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
|
||||
WriteSaveBuf(buf, HospitalRestartPoints[i]);
|
||||
WriteSaveBuf(buf, HospitalRestartHeadings[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
|
||||
WriteSaveBuf(buf, PoliceRestartPoints[i]);
|
||||
WriteSaveBuf(buf, PoliceRestartHeadings[i]);
|
||||
}
|
||||
|
||||
WriteSaveBuf(buf, NumberOfHospitalRestarts);
|
||||
WriteSaveBuf(buf, NumberOfPoliceRestarts);
|
||||
WriteSaveBuf(buf, bOverrideRestart);
|
||||
|
||||
WriteSaveBuf(buf, (uint8)0);
|
||||
WriteSaveBuf(buf, (uint16)0);
|
||||
|
||||
WriteSaveBuf(buf, OverridePosition);
|
||||
WriteSaveBuf(buf, OverrideHeading);
|
||||
WriteSaveBuf(buf, bFadeInAfterNextDeath);
|
||||
WriteSaveBuf(buf, bFadeInAfterNextArrest);
|
||||
WriteSaveBuf(buf, OverrideHospitalLevel);
|
||||
WriteSaveBuf(buf, OverridePoliceStationLevel);
|
||||
VALIDATESAVEBUF(*size);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CRestart::FindClosestPoliceRestartPoint(const CVector &pos, CVector *outPos, float *outHeading)
|
||||
{
|
||||
if (bOverrideRestart) {
|
||||
*outPos = OverridePosition;
|
||||
*outHeading = OverrideHeading;
|
||||
CancelOverrideRestart();
|
||||
return;
|
||||
}
|
||||
|
||||
eLevelName curlevel = CTheZones::FindZoneForPoint(pos);
|
||||
float fMinDist = 16000000.0f;
|
||||
int closestPoint = NUM_RESTART_POINTS;
|
||||
|
||||
// find closest point on this level
|
||||
for (int i = 0; i < NumberOfPoliceRestarts; i++) {
|
||||
if (CTheZones::FindZoneForPoint(PoliceRestartPoints[i]) == (OverridePoliceStationLevel != LEVEL_NONE ? OverridePoliceStationLevel : curlevel)) {
|
||||
float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
|
||||
if (fMinDist >= dist) {
|
||||
fMinDist = dist;
|
||||
closestPoint = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we didn't find anything, find closest point on any level
|
||||
if (closestPoint == NUM_RESTART_POINTS) {
|
||||
for (int i = 0; i < NumberOfPoliceRestarts; i++) {
|
||||
float dist = (pos - PoliceRestartPoints[i]).MagnitudeSqr();
|
||||
if (fMinDist >= dist) {
|
||||
fMinDist = dist;
|
||||
closestPoint = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we still didn't find anything, find closest path node
|
||||
if (closestPoint == NUM_RESTART_POINTS) {
|
||||
printf("Couldn't find a police restart zone near the player\n");
|
||||
*outPos = ThePaths.m_pathNodes[ThePaths.FindNodeClosestToCoors(pos, PATH_PED, 999999.9f)].pos;
|
||||
*outHeading = 0.0f;
|
||||
} else {
|
||||
*outPos = PoliceRestartPoints[closestPoint];
|
||||
*outHeading = PoliceRestartHeadings[closestPoint];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CRestart::LoadAllRestartPoints(uint8 *buf, uint32 size)
|
||||
{
|
||||
Initialise();
|
||||
|
||||
INITSAVEBUF
|
||||
CheckSaveHeader(buf, 'R','S','T','\0', size - SAVE_HEADER_SIZE);
|
||||
|
||||
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
|
||||
HospitalRestartPoints[i] = ReadSaveBuf<CVector>(buf);
|
||||
HospitalRestartHeadings[i] = ReadSaveBuf<float>(buf);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
|
||||
PoliceRestartPoints[i] = ReadSaveBuf<CVector>(buf);
|
||||
PoliceRestartHeadings[i] = ReadSaveBuf<float>(buf);
|
||||
}
|
||||
|
||||
NumberOfHospitalRestarts = ReadSaveBuf<uint16>(buf);
|
||||
NumberOfPoliceRestarts = ReadSaveBuf<uint16>(buf);
|
||||
bOverrideRestart = ReadSaveBuf<bool>(buf);
|
||||
|
||||
// skip something unused
|
||||
ReadSaveBuf<uint8>(buf);
|
||||
ReadSaveBuf<uint16>(buf);
|
||||
|
||||
OverridePosition = ReadSaveBuf<CVector>(buf);
|
||||
OverrideHeading = ReadSaveBuf<float>(buf);
|
||||
bFadeInAfterNextDeath = ReadSaveBuf<bool>(buf);
|
||||
bFadeInAfterNextArrest = ReadSaveBuf<bool>(buf);
|
||||
OverrideHospitalLevel = ReadSaveBuf<uint8>(buf);
|
||||
OverridePoliceStationLevel = ReadSaveBuf<uint8>(buf);
|
||||
VALIDATESAVEBUF(size);
|
||||
}
|
||||
|
||||
void
|
||||
CRestart::SaveAllRestartPoints(uint8 *buf, uint32 *size)
|
||||
{
|
||||
*size = SAVE_HEADER_SIZE
|
||||
+ sizeof(HospitalRestartPoints)
|
||||
+ sizeof(HospitalRestartHeadings)
|
||||
+ sizeof(PoliceRestartPoints)
|
||||
+ sizeof(PoliceRestartHeadings)
|
||||
+ sizeof(NumberOfHospitalRestarts)
|
||||
+ sizeof(NumberOfPoliceRestarts)
|
||||
+ sizeof(bOverrideRestart)
|
||||
+ sizeof(uint8)
|
||||
+ sizeof(uint16)
|
||||
+ sizeof(OverridePosition)
|
||||
+ sizeof(OverrideHeading)
|
||||
+ sizeof(bFadeInAfterNextDeath)
|
||||
+ sizeof(bFadeInAfterNextArrest)
|
||||
+ sizeof(OverrideHospitalLevel)
|
||||
+ sizeof(OverridePoliceStationLevel); // == 292
|
||||
|
||||
INITSAVEBUF
|
||||
WriteSaveHeader(buf, 'R','S','T','\0', *size - SAVE_HEADER_SIZE);
|
||||
|
||||
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
|
||||
WriteSaveBuf(buf, HospitalRestartPoints[i]);
|
||||
WriteSaveBuf(buf, HospitalRestartHeadings[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUM_RESTART_POINTS; i++) {
|
||||
WriteSaveBuf(buf, PoliceRestartPoints[i]);
|
||||
WriteSaveBuf(buf, PoliceRestartHeadings[i]);
|
||||
}
|
||||
|
||||
WriteSaveBuf(buf, NumberOfHospitalRestarts);
|
||||
WriteSaveBuf(buf, NumberOfPoliceRestarts);
|
||||
WriteSaveBuf(buf, bOverrideRestart);
|
||||
|
||||
WriteSaveBuf(buf, (uint8)0);
|
||||
WriteSaveBuf(buf, (uint16)0);
|
||||
|
||||
WriteSaveBuf(buf, OverridePosition);
|
||||
WriteSaveBuf(buf, OverrideHeading);
|
||||
WriteSaveBuf(buf, bFadeInAfterNextDeath);
|
||||
WriteSaveBuf(buf, bFadeInAfterNextArrest);
|
||||
WriteSaveBuf(buf, OverrideHospitalLevel);
|
||||
WriteSaveBuf(buf, OverridePoliceStationLevel);
|
||||
VALIDATESAVEBUF(*size);
|
||||
}
|
||||
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x435E20, &CRestart::Initialise, PATCH_JUMP);
|
||||
InjectHook(0x436100, &CRestart::AddHospitalRestartPoint, PATCH_JUMP);
|
||||
@ -258,5 +258,5 @@ STARTPATCHES
|
||||
InjectHook(0x4361A0, &CRestart::FindClosestHospitalRestartPoint, PATCH_JUMP);
|
||||
InjectHook(0x436450, &CRestart::FindClosestPoliceRestartPoint, PATCH_JUMP);
|
||||
InjectHook(0x436B20, &CRestart::LoadAllRestartPoints, PATCH_JUMP);
|
||||
InjectHook(0x436700, &CRestart::SaveAllRestartPoints, PATCH_JUMP);
|
||||
InjectHook(0x436700, &CRestart::SaveAllRestartPoints, PATCH_JUMP);
|
||||
ENDPATCHES
|
@ -2,36 +2,202 @@
|
||||
#include "patcher.h"
|
||||
#include "RoadBlocks.h"
|
||||
#include "PathFind.h"
|
||||
#include "ModelIndices.h"
|
||||
#include "Streaming.h"
|
||||
#include "World.h"
|
||||
#include "PedPlacement.h"
|
||||
#include "Automobile.h"
|
||||
#include "CopPed.h"
|
||||
#include "VisibilityPlugins.h"
|
||||
#include "PlayerPed.h"
|
||||
#include "Wanted.h"
|
||||
#include "Camera.h"
|
||||
#include "CarCtrl.h"
|
||||
#include "General.h"
|
||||
|
||||
int16 &CRoadBlocks::NumRoadBlocks = *(int16*)0x95CC34;
|
||||
int16 (&CRoadBlocks::RoadBlockObjects)[NUMROADBLOCKS] = *(int16(*)[NUMROADBLOCKS]) * (uintptr*)0x72B3A8;
|
||||
bool (&CRoadBlocks::InOrOut)[NUMROADBLOCKS] = *(bool(*)[NUMROADBLOCKS]) * (uintptr*)0x733810;
|
||||
|
||||
WRAPPER void CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle*, int32, int16) { EAXJMP(0x4376A0); }
|
||||
WRAPPER void CRoadBlocks::GenerateRoadBlocks(void) { EAXJMP(0x436FA0); }
|
||||
|
||||
void
|
||||
CRoadBlocks::Init(void)
|
||||
{
|
||||
NumRoadBlocks = 0;
|
||||
for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) {
|
||||
if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) {
|
||||
if (NumRoadBlocks < 600) {
|
||||
InOrOut[NumRoadBlocks] = true;
|
||||
RoadBlockObjects[NumRoadBlocks] = objId;
|
||||
NumRoadBlocks++;
|
||||
} else {
|
||||
NumRoadBlocks = 0;
|
||||
for (int objId = 0; objId < ThePaths.m_numMapObjects; objId++) {
|
||||
if (ThePaths.m_objectFlags[objId] & UseInRoadBlock) {
|
||||
if (NumRoadBlocks < NUMROADBLOCKS) {
|
||||
InOrOut[NumRoadBlocks] = true;
|
||||
RoadBlockObjects[NumRoadBlocks] = objId;
|
||||
NumRoadBlocks++;
|
||||
} else {
|
||||
#ifndef MASTER
|
||||
printf("Not enough room for the potential roadblocks\n");
|
||||
printf("Not enough room for the potential roadblocks\n");
|
||||
#endif
|
||||
// FIX: Don't iterate loop after NUMROADBLOCKS
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// FIX: Don't iterate loop after NUMROADBLOCKS
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
CRoadBlocks::GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode)
|
||||
{
|
||||
static const CVector vecRoadBlockOffets[6] = { {-1.5, 1.8f, 0.0f}, {-1.5f, -1.8f, 0.0f}, {1.5f, 1.8f, 0.0f},
|
||||
{1.5f, -1.8f, 0.0f}, {-1.5f, 0.0f, 0.0f}, {1.5, 0.0, 0.0} };
|
||||
CEntity* pEntityToAttack = (CEntity*)FindPlayerVehicle();
|
||||
if (!pEntityToAttack)
|
||||
pEntityToAttack = (CEntity*)FindPlayerPed();
|
||||
CColModel* pPoliceColModel = CModelInfo::GetModelInfo(MI_POLICE)->GetColModel();
|
||||
float fRadius = pVehicle->GetBoundRadius() / pPoliceColModel->boundingSphere.radius;
|
||||
for (int32 i = 0; i < 2; i++) {
|
||||
const int32 roadBlockIndex = i + 2 * roadBlockType;
|
||||
CVector posForZ = pVehicle->m_matrix * (fRadius * vecRoadBlockOffets[roadBlockIndex]);
|
||||
int32 modelInfoId = MI_COP;
|
||||
eCopType copType = COP_STREET;
|
||||
switch (pVehicle->GetModelIndex())
|
||||
{
|
||||
case MI_FBICAR:
|
||||
modelInfoId = MI_FBI;
|
||||
copType = COP_FBI;
|
||||
break;
|
||||
case MI_ENFORCER:
|
||||
modelInfoId = MI_SWAT;
|
||||
copType = COP_SWAT;
|
||||
break;
|
||||
case MI_BARRACKS:
|
||||
modelInfoId = MI_ARMY;
|
||||
copType = COP_ARMY;
|
||||
break;
|
||||
}
|
||||
if (!CStreaming::HasModelLoaded(modelInfoId))
|
||||
copType = COP_STREET;
|
||||
CCopPed* pCopPed = new CCopPed(copType);
|
||||
if (copType == COP_STREET)
|
||||
pCopPed->SetCurrentWeapon(WEAPONTYPE_COLT45);
|
||||
CPedPlacement::FindZCoorForPed(&posForZ);
|
||||
pCopPed->m_matrix.GetPosition() = posForZ;
|
||||
CVector vecSavedPos = pCopPed->m_matrix.GetPosition();
|
||||
pCopPed->m_matrix.SetRotate(0.0f, 0.0f, -HALFPI);
|
||||
pCopPed->m_matrix.GetPosition() += vecSavedPos;
|
||||
pCopPed->m_bIsDisabledCop = true;
|
||||
pCopPed->SetIdle();
|
||||
pCopPed->bKindaStayInSamePlace = true;
|
||||
pCopPed->bNotAllowedToDuck = false;
|
||||
pCopPed->m_wRoadblockNode = roadBlockNode;
|
||||
pCopPed->bCrouchWhenShooting = roadBlockType != 2;
|
||||
if (pEntityToAttack) {
|
||||
pCopPed->m_pPointGunAt = pEntityToAttack;
|
||||
pEntityToAttack->RegisterReference(&pCopPed->m_pPointGunAt);
|
||||
pCopPed->SetAttack(pEntityToAttack);
|
||||
}
|
||||
pCopPed->m_pMyVehicle = pVehicle;
|
||||
pVehicle->RegisterReference((CEntity**)&pCopPed->m_pMyVehicle);
|
||||
pCopPed->bCullExtraFarAway = true;
|
||||
CVisibilityPlugins::SetClumpAlpha(pCopPed->GetClump(), 0);
|
||||
CWorld::Add(pCopPed);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CRoadBlocks::GenerateRoadBlocks(void)
|
||||
{
|
||||
CMatrix offsetMatrix;
|
||||
uint32 frame = CTimer::GetFrameCounter() & 0xF;
|
||||
int16 nRoadblockNode = (int16)(NUMROADBLOCKS * frame) / 16;
|
||||
const int16 maxRoadBlocks = (int16)(NUMROADBLOCKS * (frame + 1)) / 16;
|
||||
int16 numRoadBlocks = CRoadBlocks::NumRoadBlocks;
|
||||
if (CRoadBlocks::NumRoadBlocks >= maxRoadBlocks)
|
||||
numRoadBlocks = maxRoadBlocks;
|
||||
for (; nRoadblockNode < numRoadBlocks; nRoadblockNode++) {
|
||||
CTreadable *mapObject = ThePaths.m_mapObjects[CRoadBlocks::RoadBlockObjects[nRoadblockNode]];
|
||||
CVector2D vecDistance = FindPlayerCoors() - mapObject->GetPosition();
|
||||
if (vecDistance.x > -80.0f && vecDistance.x < 80.0f &&
|
||||
vecDistance.y > -80.0f && vecDistance.y < 80.0f &&
|
||||
vecDistance.Magnitude() < 80.0f) {
|
||||
if (!CRoadBlocks::InOrOut[nRoadblockNode]) {
|
||||
CRoadBlocks::InOrOut[nRoadblockNode] = true;
|
||||
if (FindPlayerVehicle() && (CGeneral::GetRandomNumber() & 0x7F) < FindPlayerPed()->m_pWanted->m_RoadblockDensity) {
|
||||
CWanted *pPlayerWanted = FindPlayerPed()->m_pWanted;
|
||||
float fMapObjectRadius = 2.0f * mapObject->GetColModel()->boundingBox.max.x;
|
||||
int32 vehicleId = MI_POLICE;
|
||||
if (pPlayerWanted->AreArmyRequired())
|
||||
vehicleId = MI_BARRACKS;
|
||||
else if (pPlayerWanted->AreFbiRequired())
|
||||
vehicleId = MI_FBICAR;
|
||||
else if (pPlayerWanted->AreSwatRequired())
|
||||
vehicleId = MI_ENFORCER;
|
||||
if (!CStreaming::HasModelLoaded(vehicleId))
|
||||
vehicleId = MI_POLICE;
|
||||
CColModel *pVehicleColModel = CModelInfo::GetModelInfo(vehicleId)->GetColModel();
|
||||
float fModelRadius = 2.0f * pVehicleColModel->boundingSphere.radius + 0.25f;
|
||||
int16 radius = (int16)(fMapObjectRadius / fModelRadius);
|
||||
if (radius > 0 && radius < 6) {
|
||||
CVector2D vecDistanceToCamera = TheCamera.GetPosition() - mapObject->m_matrix.GetPosition();
|
||||
float fDotProduct = DotProduct2D(vecDistanceToCamera, mapObject->m_matrix.GetUp());
|
||||
float fOffset = 0.5f * fModelRadius * (float)(radius - 1);
|
||||
for (int16 i = 0; i < radius; i++) {
|
||||
uint8 nRoadblockType = fDotProduct < 0.0f;
|
||||
if (CGeneral::GetRandomNumber() & 1) {
|
||||
offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f + HALFPI);
|
||||
}
|
||||
else {
|
||||
nRoadblockType = !nRoadblockType;
|
||||
offsetMatrix.SetRotateZ(((CGeneral::GetRandomNumber() & 0xFF) - 128.0f) * 0.003f - HALFPI);
|
||||
}
|
||||
if (ThePaths.m_objectFlags[CRoadBlocks::RoadBlockObjects[nRoadblockNode]] & ObjectEastWest)
|
||||
offsetMatrix.GetPosition() = CVector(0.0f, -fOffset, 0.6f);
|
||||
else
|
||||
offsetMatrix.GetPosition() = CVector(-fOffset, 0.0f, 0.6f);
|
||||
CMatrix vehicleMatrix = mapObject->m_matrix * offsetMatrix;
|
||||
float fModelRadius = CModelInfo::GetModelInfo(vehicleId)->GetColModel()->boundingSphere.radius - 0.25f;
|
||||
int16 colliding = 0;
|
||||
CWorld::FindObjectsKindaColliding(vehicleMatrix.GetPosition(), fModelRadius, 0, &colliding, 2, nil, false, true, true, false, false);
|
||||
if (!colliding) {
|
||||
CAutomobile *pVehicle = new CAutomobile(vehicleId, RANDOM_VEHICLE);
|
||||
pVehicle->m_status = STATUS_ABANDONED;
|
||||
// pVehicle->GetHeightAboveRoad(); // called but return value is ignored?
|
||||
vehicleMatrix.GetPosition().z += fModelRadius - 0.6f;
|
||||
pVehicle->m_matrix = vehicleMatrix;
|
||||
pVehicle->PlaceOnRoadProperly();
|
||||
pVehicle->bIsStatic = false;
|
||||
pVehicle->m_matrix.UpdateRW();
|
||||
pVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
|
||||
CCarCtrl::JoinCarWithRoadSystem(pVehicle);
|
||||
pVehicle->bIsLocked = false;
|
||||
pVehicle->AutoPilot.m_nCarMission = MISSION_NONE;
|
||||
pVehicle->AutoPilot.m_nTempAction = TEMPACT_NONE;
|
||||
pVehicle->AutoPilot.m_nCurrentLane = 0;
|
||||
pVehicle->AutoPilot.m_nNextLane = 0;
|
||||
pVehicle->AutoPilot.m_fMaxTrafficSpeed = 0.0f;
|
||||
pVehicle->AutoPilot.m_nCruiseSpeed = 0.0f;
|
||||
pVehicle->bExtendedRange = true;
|
||||
if (pVehicle->UsesSiren(pVehicle->GetModelIndex()) && CGeneral::GetRandomNumber() & 1)
|
||||
pVehicle->m_bSirenOrAlarm = true;
|
||||
if (pVehicle->m_matrix.GetForward().z > 0.94f) {
|
||||
CVisibilityPlugins::SetClumpAlpha(pVehicle->GetClump(), 0);
|
||||
CWorld::Add(pVehicle);
|
||||
pVehicle->bCreateRoadBlockPeds = true;
|
||||
pVehicle->m_nRoadblockType = nRoadblockType;
|
||||
pVehicle->m_nRoadblockNode = nRoadblockNode;
|
||||
}
|
||||
else {
|
||||
delete pVehicle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
CRoadBlocks::InOrOut[nRoadblockNode] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x436F50, &CRoadBlocks::Init, PATCH_JUMP);
|
||||
InjectHook(0x4376A0, &CRoadBlocks::GenerateRoadBlockCopsForCar, PATCH_JUMP);
|
||||
InjectHook(0x436FA0, &CRoadBlocks::GenerateRoadBlocks, PATCH_JUMP);
|
||||
ENDPATCHES
|
@ -11,6 +11,6 @@ public:
|
||||
static bool (&InOrOut)[NUMROADBLOCKS];
|
||||
|
||||
static void Init(void);
|
||||
static void GenerateRoadBlockCopsForCar(CVehicle*, int32, int16);
|
||||
static void GenerateRoadBlockCopsForCar(CVehicle* pVehicle, int32 roadBlockType, int16 roadBlockNode);
|
||||
static void GenerateRoadBlocks(void);
|
||||
};
|
||||
|
@ -91,10 +91,10 @@ uint8 (&CTheScripts::ScriptSpace)[SIZE_SCRIPT_SPACE] = *(uint8(*)[SIZE_SCRIPT_SP
|
||||
CRunningScript(&CTheScripts::ScriptsArray)[MAX_NUM_SCRIPTS] = *(CRunningScript(*)[MAX_NUM_SCRIPTS])*(uintptr*)0x6F5C08;
|
||||
int32(&CTheScripts::BaseBriefIdForContact)[MAX_NUM_CONTACTS] = *(int32(*)[MAX_NUM_CONTACTS])*(uintptr*)0x880200;
|
||||
int32(&CTheScripts::OnAMissionForContactFlag)[MAX_NUM_CONTACTS] = *(int32(*)[MAX_NUM_CONTACTS])*(uintptr*)0x8622F0;
|
||||
CTextLine (&CTheScripts::IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES] = *(CTextLine (*)[MAX_NUM_INTRO_TEXT_LINES])*(uintptr*)0x70EA68;
|
||||
CScriptRectangle (&CTheScripts::IntroRectangles)[MAX_NUM_INTRO_RECTANGLES] = *(CScriptRectangle (*)[MAX_NUM_INTRO_RECTANGLES])*(uintptr*)0x72D108;
|
||||
intro_text_line (&CTheScripts::IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES] = *(intro_text_line (*)[MAX_NUM_INTRO_TEXT_LINES])*(uintptr*)0x70EA68;
|
||||
intro_script_rectangle (&CTheScripts::IntroRectangles)[MAX_NUM_INTRO_RECTANGLES] = *(intro_script_rectangle (*)[MAX_NUM_INTRO_RECTANGLES])*(uintptr*)0x72D108;
|
||||
CSprite2d (&CTheScripts::ScriptSprites)[MAX_NUM_SCRIPT_SRPITES] = *(CSprite2d(*)[MAX_NUM_SCRIPT_SRPITES])*(uintptr*)0x72B090;
|
||||
CScriptSphere(&CTheScripts::ScriptSphereArray)[MAX_NUM_SCRIPT_SPHERES] = *(CScriptSphere(*)[MAX_NUM_SCRIPT_SPHERES])*(uintptr*)0x727D60;
|
||||
script_sphere_struct(&CTheScripts::ScriptSphereArray)[MAX_NUM_SCRIPT_SPHERES] = *(script_sphere_struct(*)[MAX_NUM_SCRIPT_SPHERES])*(uintptr*)0x727D60;
|
||||
tCollectiveData(&CTheScripts::CollectiveArray)[MAX_NUM_COLLECTIVES] = *(tCollectiveData(*)[MAX_NUM_COLLECTIVES])*(uintptr*)0x6FA008;
|
||||
tUsedObject(&CTheScripts::UsedObjectArray)[MAX_NUM_USED_OBJECTS] = *(tUsedObject(*)[MAX_NUM_USED_OBJECTS])*(uintptr*)0x6E69C8;
|
||||
int32(&CTheScripts::MultiScriptArray)[MAX_NUM_MISSION_SCRIPTS] = *(int32(*)[MAX_NUM_MISSION_SCRIPTS])*(uintptr*)0x6F0558;
|
||||
@ -313,7 +313,7 @@ bool CUpsideDownCarCheck::HasCarBeenUpsideDownForAWhile(int32 id)
|
||||
return false;
|
||||
}
|
||||
|
||||
void CStuckCarCheckEntry::Reset()
|
||||
void stuck_car_data::Reset()
|
||||
{
|
||||
m_nVehicleIndex = -1;
|
||||
m_vecPos = CVector(-5000.0f, -5000.0f, -5000.0f);
|
||||
@ -2229,6 +2229,7 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
|
||||
if (pos.z <= -100)
|
||||
pos.z = CWorld::FindGroundZForCoord(pos.x, pos.y);
|
||||
UpdateCompareFlag(TheCamera.IsSphereVisible(pos, *(float*)&ScriptParams[3]));
|
||||
return 0;
|
||||
}
|
||||
case COMMAND_DEBUG_ON:
|
||||
CTheScripts::DbgFlag = true;
|
||||
@ -7116,7 +7117,7 @@ int8 CRunningScript::ProcessCommands800To899(int32 command)
|
||||
case COMMAND_CLOSE_GARAGE:
|
||||
{
|
||||
CollectParameters(&m_nIp, 1);
|
||||
CGarages::CloseGarage(ScriptParams[1]);
|
||||
CGarages::CloseGarage(ScriptParams[0]);
|
||||
return 0;
|
||||
}
|
||||
case COMMAND_WARP_CHAR_FROM_CAR_TO_COORD:
|
||||
@ -7657,13 +7658,13 @@ int8 CRunningScript::ProcessCommands900To999(int32 command)
|
||||
assert(pObject);
|
||||
if (ScriptParams[1]) {
|
||||
if (pObject->bIsStatic) {
|
||||
pObject->bIsStatic = true;
|
||||
pObject->bIsStatic = false;
|
||||
pObject->AddToMovingList();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!pObject->bIsStatic) {
|
||||
pObject->bIsStatic = false;
|
||||
pObject->bIsStatic = true;
|
||||
pObject->RemoveFromMovingList();
|
||||
}
|
||||
}
|
||||
@ -8441,7 +8442,7 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
|
||||
CPlayerInfo* pPlayerInfo = &CWorld::Players[ScriptParams[0]];
|
||||
CPad::GetPad(ScriptParams[0])->DisablePlayerControls |= PLAYERCONTROL_DISABLED_80;
|
||||
pPlayerInfo->MakePlayerSafe(true);
|
||||
CCutsceneMgr::SetRunning(true);
|
||||
CCutsceneMgr::StartCutsceneProcessing();
|
||||
return 0;
|
||||
}
|
||||
case COMMAND_USE_TEXT_COMMANDS:
|
||||
@ -9140,7 +9141,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
|
||||
assert(pVehicle);
|
||||
assert(pVehicle->m_vehType == VEHICLE_TYPE_CAR);
|
||||
CAutomobile* pCar = (CAutomobile*)pVehicle;
|
||||
pCar->bTakeLessDamage = ScriptParams[1];
|
||||
pCar->bMoreResistantToDamage = ScriptParams[1];
|
||||
return 0;
|
||||
}
|
||||
case COMMAND_SET_JAMES_CAR_ON_PATH_TO_PLAYER:
|
||||
@ -9152,6 +9153,7 @@ int8 CRunningScript::ProcessCommands1100To1199(int32 command)
|
||||
return 0;
|
||||
}
|
||||
case COMMAND_LOAD_END_OF_GAME_TUNE:
|
||||
DMAudio.ChangeMusicMode(MUSICMODE_CUTSCENE);
|
||||
printf("Start preload end of game audio\n");
|
||||
DMAudio.PreloadCutSceneMusic(STREAMED_SOUND_GAME_COMPLETED);
|
||||
printf("End preload end of game audio\n");
|
||||
@ -11037,6 +11039,7 @@ void CRunningScript::DoDeatharrestCheck()
|
||||
int contactFlagOffset = CTheScripts::OnAMissionForContactFlag[contact];
|
||||
if (contactFlagOffset && CTheScripts::ScriptSpace[contactFlagOffset] == 1) {
|
||||
messageId += CTheScripts::BaseBriefIdForContact[contact];
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
@ -11331,6 +11334,7 @@ INITSAVEBUF
|
||||
break;
|
||||
case 4:
|
||||
InvisibilitySettingArray[i] = CPools::GetDummyPool()->GetSlot(handle - 1);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
@ -11369,15 +11373,15 @@ void CTheScripts::ClearSpaceForMissionEntity(const CVector& pos, CEntity* pEntit
|
||||
continue;
|
||||
CEntity* pFound = aEntities[i];
|
||||
int cols;
|
||||
if (CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel()->numLines <= 0)
|
||||
cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(),
|
||||
pFound->GetMatrix(), *CModelInfo::GetModelInfo(pFound->GetModelIndex())->GetColModel(), aTempColPoints, nil, nil);
|
||||
if (pEntity->GetColModel()->numLines <= 0)
|
||||
cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(),
|
||||
pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints, nil, nil);
|
||||
else {
|
||||
float lines[4];
|
||||
lines[0] = lines[1] = lines[2] = lines[3] = 1.0f;
|
||||
CColPoint tmp;
|
||||
cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *CModelInfo::GetModelInfo(pEntity->GetModelIndex())->GetColModel(),
|
||||
pFound->GetMatrix(), *CModelInfo::GetModelInfo(pFound->GetModelIndex())->GetColModel(), aTempColPoints, &tmp, lines);
|
||||
CColPoint tmp[4];
|
||||
cols = CCollision::ProcessColModels(pEntity->GetMatrix(), *pEntity->GetColModel(),
|
||||
pFound->GetMatrix(), *pFound->GetColModel(), aTempColPoints,tmp, lines);
|
||||
}
|
||||
if (cols <= 0)
|
||||
continue;
|
||||
|
@ -15,22 +15,25 @@ class CRunningScript;
|
||||
|
||||
#define KEY_LENGTH_IN_SCRIPT 8
|
||||
|
||||
struct CScriptRectangle
|
||||
struct intro_script_rectangle
|
||||
{
|
||||
int8 m_bIsUsed;
|
||||
bool m_bIsUsed;
|
||||
bool m_bBeforeFade;
|
||||
int16 m_nTextureId;
|
||||
CRect m_sRect;
|
||||
CRGBA m_sColor;
|
||||
|
||||
intro_script_rectangle() { }
|
||||
~intro_script_rectangle() { }
|
||||
};
|
||||
|
||||
static_assert(sizeof(CScriptRectangle) == 0x18, "Script.h: error");
|
||||
static_assert(sizeof(intro_script_rectangle) == 0x18, "Script.h: error");
|
||||
|
||||
enum {
|
||||
SCRIPT_TEXT_MAX_LENGTH = 500
|
||||
};
|
||||
|
||||
struct CTextLine
|
||||
struct intro_text_line
|
||||
{
|
||||
float m_fScaleX;
|
||||
float m_fScaleY;
|
||||
@ -50,6 +53,9 @@ struct CTextLine
|
||||
float m_fAtY;
|
||||
wchar m_Text[SCRIPT_TEXT_MAX_LENGTH];
|
||||
|
||||
intro_text_line() { }
|
||||
~intro_text_line() { }
|
||||
|
||||
void Reset()
|
||||
{
|
||||
m_fScaleX = 0.48f;
|
||||
@ -72,15 +78,17 @@ struct CTextLine
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(CTextLine) == 0x414, "Script.h: error");
|
||||
static_assert(sizeof(intro_text_line) == 0x414, "Script.h: error");
|
||||
|
||||
struct CScriptSphere
|
||||
struct script_sphere_struct
|
||||
{
|
||||
bool m_bInUse;
|
||||
uint16 m_Index;
|
||||
uint32 m_Id;
|
||||
CVector m_vecCenter;
|
||||
float m_fRadius;
|
||||
|
||||
script_sphere_struct() { }
|
||||
};
|
||||
|
||||
struct CStoredLine
|
||||
@ -145,7 +153,7 @@ public:
|
||||
bool HasCarBeenUpsideDownForAWhile(int32);
|
||||
};
|
||||
|
||||
struct CStuckCarCheckEntry
|
||||
struct stuck_car_data
|
||||
{
|
||||
int32 m_nVehicleIndex;
|
||||
CVector m_vecPos;
|
||||
@ -154,12 +162,13 @@ struct CStuckCarCheckEntry
|
||||
uint32 m_nStuckTime;
|
||||
bool m_bStuck;
|
||||
|
||||
stuck_car_data() { }
|
||||
inline void Reset();
|
||||
};
|
||||
|
||||
class CStuckCarCheck
|
||||
{
|
||||
CStuckCarCheckEntry m_sCars[MAX_STUCK_CAR_CHECKS];
|
||||
stuck_car_data m_sCars[MAX_STUCK_CAR_CHECKS];
|
||||
|
||||
public:
|
||||
void Init();
|
||||
@ -235,10 +244,10 @@ class CTheScripts
|
||||
static CRunningScript(&ScriptsArray)[MAX_NUM_SCRIPTS];
|
||||
static int32(&BaseBriefIdForContact)[MAX_NUM_CONTACTS];
|
||||
static int32(&OnAMissionForContactFlag)[MAX_NUM_CONTACTS];
|
||||
static CTextLine(&IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES];
|
||||
static CScriptRectangle(&IntroRectangles)[MAX_NUM_INTRO_RECTANGLES];
|
||||
static intro_text_line(&IntroTextLines)[MAX_NUM_INTRO_TEXT_LINES];
|
||||
static intro_script_rectangle(&IntroRectangles)[MAX_NUM_INTRO_RECTANGLES];
|
||||
static CSprite2d(&ScriptSprites)[MAX_NUM_SCRIPT_SRPITES];
|
||||
static CScriptSphere(&ScriptSphereArray)[MAX_NUM_SCRIPT_SPHERES];
|
||||
static script_sphere_struct(&ScriptSphereArray)[MAX_NUM_SCRIPT_SPHERES];
|
||||
static tCollectiveData(&CollectiveArray)[MAX_NUM_COLLECTIVES];
|
||||
static tUsedObject(&UsedObjectArray)[MAX_NUM_USED_OBJECTS];
|
||||
static int32(&MultiScriptArray)[MAX_NUM_MISSION_SCRIPTS];
|
||||
|
@ -1,23 +1,335 @@
|
||||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "TrafficLights.h"
|
||||
#include "General.h"
|
||||
#include "Camera.h"
|
||||
#include "World.h"
|
||||
#include "PathFind.h"
|
||||
#include "Timer.h"
|
||||
#include "Clock.h"
|
||||
#include "Weather.h"
|
||||
#include "Timecycle.h"
|
||||
#include "Pointlights.h"
|
||||
#include "Shadows.h"
|
||||
#include "Coronas.h"
|
||||
#include "SpecialFX.h"
|
||||
#include "Vehicle.h"
|
||||
#include "TrafficLights.h"
|
||||
|
||||
WRAPPER void CTrafficLights::DisplayActualLight(CEntity *ent) { EAXJMP(0x455800); }
|
||||
WRAPPER void CTrafficLights::ScanForLightsOnMap(void) { EAXJMP(0x454F40); }
|
||||
WRAPPER bool CTrafficLights::ShouldCarStopForLight(CVehicle*, bool) { EAXJMP(0x455350); }
|
||||
WRAPPER bool CTrafficLights::ShouldCarStopForBridge(CVehicle*) { EAXJMP(0x456460); }
|
||||
// TODO: figure out the meaning of this
|
||||
enum { SOME_FLAG = 0x80 };
|
||||
|
||||
void
|
||||
CTrafficLights::DisplayActualLight(CEntity *ent)
|
||||
{
|
||||
if(ent->GetUp().z < 0.96f || ent->bRenderDamaged)
|
||||
return;
|
||||
|
||||
int phase;
|
||||
if(FindTrafficLightType(ent) == 1)
|
||||
phase = LightForCars1();
|
||||
else
|
||||
phase = LightForCars2();
|
||||
|
||||
int i;
|
||||
CBaseModelInfo *mi = CModelInfo::GetModelInfo(ent->GetModelIndex());
|
||||
float x = mi->Get2dEffect(0)->pos.x;
|
||||
float yMin = mi->Get2dEffect(0)->pos.y;
|
||||
float yMax = mi->Get2dEffect(0)->pos.y;
|
||||
float zMin = mi->Get2dEffect(0)->pos.z;
|
||||
float zMax = mi->Get2dEffect(0)->pos.z;
|
||||
for(i = 1; i < 6; i++){
|
||||
assert(mi->Get2dEffect(i));
|
||||
yMin = min(yMin, mi->Get2dEffect(i)->pos.y);
|
||||
yMax = max(yMax, mi->Get2dEffect(i)->pos.y);
|
||||
zMin = min(zMin, mi->Get2dEffect(i)->pos.z);
|
||||
zMax = max(zMax, mi->Get2dEffect(i)->pos.z);
|
||||
}
|
||||
|
||||
CVector pos1, pos2;
|
||||
uint8 r, g;
|
||||
int id;
|
||||
switch(phase){
|
||||
case CAR_LIGHTS_GREEN:
|
||||
r = 0;
|
||||
g = 255;
|
||||
pos1 = ent->GetMatrix() * CVector(x, yMax, zMin);
|
||||
pos2 = ent->GetMatrix() * CVector(x, yMin, zMin);
|
||||
id = 0;
|
||||
break;
|
||||
case CAR_LIGHTS_YELLOW:
|
||||
r = 255;
|
||||
g = 128;
|
||||
pos1 = ent->GetMatrix() * CVector(x, yMax, (zMin+zMax)/2.0f);
|
||||
pos2 = ent->GetMatrix() * CVector(x, yMin, (zMin+zMax)/2.0f);
|
||||
id = 1;
|
||||
break;
|
||||
case CAR_LIGHTS_RED:
|
||||
default:
|
||||
r = 255;
|
||||
g = 0;
|
||||
pos1 = ent->GetMatrix() * CVector(x, yMax, zMax);
|
||||
pos2 = ent->GetMatrix() * CVector(x, yMin, zMax);
|
||||
id = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if(CClock::GetHours() > 19 || CClock::GetHours() < 6 || CWeather::Foggyness > 0.05f)
|
||||
CPointLights::AddLight(CPointLights::LIGHT_POINT,
|
||||
pos1, CVector(0.0f, 0.0f, 0.0f), 8.0f,
|
||||
r/255.0f, g/255.0f, 0/255.0f, CPointLights::FOG_NORMAL, true);
|
||||
|
||||
CShadows::StoreStaticShadow((uintptr)ent,
|
||||
SHADOWTYPE_ADDITIVE, gpShadowExplosionTex, &pos1,
|
||||
8.0f, 0.0f, 0.0f, -8.0f, 128,
|
||||
r*CTimeCycle::GetLightOnGroundBrightness()/8.0f,
|
||||
g*CTimeCycle::GetLightOnGroundBrightness()/8.0f,
|
||||
0*CTimeCycle::GetLightOnGroundBrightness()/8.0f,
|
||||
12.0f, 1.0f, 40.0f, false, 0.0f);
|
||||
|
||||
if(DotProduct(TheCamera.GetForward(), ent->GetForward()) < 0.0f)
|
||||
CCoronas::RegisterCorona((uintptr)ent + id,
|
||||
r*CTimeCycle::GetSpriteBrightness()*0.7f,
|
||||
g*CTimeCycle::GetSpriteBrightness()*0.7f,
|
||||
0*CTimeCycle::GetSpriteBrightness()*0.7f,
|
||||
255,
|
||||
pos1, 1.75f*CTimeCycle::GetSpriteSize(), 50.0f,
|
||||
CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
|
||||
CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
|
||||
else
|
||||
CCoronas::RegisterCorona((uintptr)ent + id + 3,
|
||||
r*CTimeCycle::GetSpriteBrightness()*0.7f,
|
||||
g*CTimeCycle::GetSpriteBrightness()*0.7f,
|
||||
0*CTimeCycle::GetSpriteBrightness()*0.7f,
|
||||
255,
|
||||
pos2, 1.75f*CTimeCycle::GetSpriteSize(), 50.0f,
|
||||
CCoronas::TYPE_STAR, CCoronas::FLARE_NONE, CCoronas::REFLECTION_ON,
|
||||
CCoronas::LOSCHECK_OFF, CCoronas::STREAK_OFF, 0.0f);
|
||||
|
||||
CBrightLights::RegisterOne(pos1, ent->GetUp(), ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);
|
||||
CBrightLights::RegisterOne(pos2, ent->GetUp(), -ent->GetRight(), CVector(0.0f, 0.0f, 0.0f), id + BRIGHTLIGHT_TRAFFIC_GREEN);
|
||||
|
||||
static const float top = -0.127f;
|
||||
static const float bot = -0.539f;
|
||||
static const float mid = bot + (top-bot)/3.0f;
|
||||
static const float left = 1.256f;
|
||||
static const float right = 0.706f;
|
||||
phase = CTrafficLights::LightForPeds();
|
||||
if(phase == PED_LIGHTS_DONT_WALK){
|
||||
CVector p0(2.7f, right, top);
|
||||
CVector p1(2.7f, left, top);
|
||||
CVector p2(2.7f, right, mid);
|
||||
CVector p3(2.7f, left, mid);
|
||||
CShinyTexts::RegisterOne(ent->GetMatrix()*p0, ent->GetMatrix()*p1, ent->GetMatrix()*p2, ent->GetMatrix()*p3,
|
||||
1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
|
||||
SHINYTEXT_WALK, 255, 0, 0, 60.0f);
|
||||
}else if(phase == PED_LIGHTS_WALK || CTimer::GetTimeInMilliseconds() & 0x100){
|
||||
CVector p0(2.7f, right, mid);
|
||||
CVector p1(2.7f, left, mid);
|
||||
CVector p2(2.7f, right, bot);
|
||||
CVector p3(2.7f, left, bot);
|
||||
CShinyTexts::RegisterOne(ent->GetMatrix()*p0, ent->GetMatrix()*p1, ent->GetMatrix()*p2, ent->GetMatrix()*p3,
|
||||
1.0f, 0.5f, 0.0f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f,
|
||||
SHINYTEXT_WALK, 255, 255, 255, 60.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CTrafficLights::ScanForLightsOnMap(void)
|
||||
{
|
||||
int x, y;
|
||||
int i, j, l;
|
||||
CPtrNode *node;
|
||||
|
||||
for(x = 0; x < NUMSECTORS_X; x++)
|
||||
for(y = 0; y < NUMSECTORS_Y; y++){
|
||||
CPtrList &list = CWorld::GetSector(x, y)->m_lists[ENTITYLIST_DUMMIES];
|
||||
for(node = list.first; node; node = node->next){
|
||||
CEntity *light = (CEntity*)node->item;
|
||||
if(light->GetModelIndex() != MI_TRAFFICLIGHTS)
|
||||
continue;
|
||||
|
||||
// Check cars
|
||||
for(i = 0; i < ThePaths.m_numCarPathLinks; i++){
|
||||
CVector2D dist = ThePaths.m_carPathLinks[i].pos - light->GetPosition();
|
||||
float dotY = Abs(DotProduct2D(dist, light->GetForward())); // forward is direction of car light
|
||||
float dotX = DotProduct2D(dist, light->GetRight()); // towards base of light
|
||||
// it has to be on the correct side of the node and also not very far away
|
||||
if(dotX < 0.0f && dotX > -15.0f && dotY < 3.0f){
|
||||
float dz = ThePaths.m_pathNodes[ThePaths.m_carPathLinks[i].pathNodeIndex].pos.z -
|
||||
light->GetPosition().z;
|
||||
if(dz < 15.0f){
|
||||
ThePaths.m_carPathLinks[i].trafficLightType = FindTrafficLightType(light);
|
||||
// Find two neighbour nodes of this one
|
||||
int n1 = -1;
|
||||
int n2 = -1;
|
||||
for(j = 0; j < ThePaths.m_numPathNodes; j++)
|
||||
for(l = 0; l < ThePaths.m_pathNodes[j].numLinks; l++)
|
||||
if(ThePaths.m_carPathConnections[ThePaths.m_pathNodes[j].firstLink + l] == i){
|
||||
if(n1 == -1)
|
||||
n1 = j;
|
||||
else
|
||||
n2 = j;
|
||||
}
|
||||
// What's going on here?
|
||||
if(ThePaths.m_pathNodes[n1].numLinks <= ThePaths.m_pathNodes[n2].numLinks)
|
||||
n1 = n2;
|
||||
if(ThePaths.m_carPathLinks[i].pathNodeIndex != n1)
|
||||
ThePaths.m_carPathLinks[i].trafficLightType |= SOME_FLAG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check peds
|
||||
for(i = ThePaths.m_numCarPathNodes; i < ThePaths.m_numPathNodes; i++){
|
||||
float dist1, dist2;
|
||||
dist1 = Abs(ThePaths.m_pathNodes[i].pos.x - light->GetPosition().x) +
|
||||
Abs(ThePaths.m_pathNodes[i].pos.y - light->GetPosition().y);
|
||||
if(dist1 < 50.0f){
|
||||
for(l = 0; l < ThePaths.m_pathNodes[i].numLinks; l++){
|
||||
j = ThePaths.m_pathNodes[i].firstLink + l;
|
||||
if(ThePaths.m_connectionFlags[j].bCrossesRoad){
|
||||
dist2 = Abs(ThePaths.m_pathNodes[j].pos.x - light->GetPosition().x) +
|
||||
Abs(ThePaths.m_pathNodes[j].pos.y - light->GetPosition().y);
|
||||
if(dist1 < 15.0f || dist2 < 15.0f)
|
||||
ThePaths.m_connectionFlags[j].bTrafficLight = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CTrafficLights::ShouldCarStopForLight(CVehicle *vehicle, bool alwaysStop)
|
||||
{
|
||||
int node, type;
|
||||
|
||||
node = vehicle->AutoPilot.m_nNextPathNodeInfo;
|
||||
type = ThePaths.m_carPathLinks[node].trafficLightType;
|
||||
if(type){
|
||||
if((type & SOME_FLAG || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nNextRouteNode) &&
|
||||
(!(type & SOME_FLAG) || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nNextRouteNode))
|
||||
if(alwaysStop ||
|
||||
(type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||
|
||||
(type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){
|
||||
float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos,
|
||||
ThePaths.m_carPathLinks[node].dir);
|
||||
if(vehicle->AutoPilot.m_nNextDirection == -1){
|
||||
if(dist > 0.0f && dist < 8.0f)
|
||||
return true;
|
||||
}else{
|
||||
if(dist < 0.0f && dist > -8.0f)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node = vehicle->AutoPilot.m_nCurrentPathNodeInfo;
|
||||
type = ThePaths.m_carPathLinks[node].trafficLightType;
|
||||
if(type){
|
||||
if((type & SOME_FLAG || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nCurrentRouteNode) &&
|
||||
(!(type & SOME_FLAG) || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nCurrentRouteNode))
|
||||
if(alwaysStop ||
|
||||
(type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||
|
||||
(type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){
|
||||
float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos,
|
||||
ThePaths.m_carPathLinks[node].dir);
|
||||
if(vehicle->AutoPilot.m_nCurrentDirection == -1){
|
||||
if(dist > 0.0f && dist < 8.0f)
|
||||
return true;
|
||||
}else{
|
||||
if(dist < 0.0f && dist > -8.0f)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(vehicle->m_status == STATUS_PHYSICS){
|
||||
node = vehicle->AutoPilot.m_nPreviousPathNodeInfo;
|
||||
type = ThePaths.m_carPathLinks[node].trafficLightType;
|
||||
if(type){
|
||||
if((type & SOME_FLAG || ThePaths.m_carPathLinks[node].pathNodeIndex == vehicle->AutoPilot.m_nPrevRouteNode) &&
|
||||
(!(type & SOME_FLAG) || ThePaths.m_carPathLinks[node].pathNodeIndex != vehicle->AutoPilot.m_nPrevRouteNode))
|
||||
if(alwaysStop ||
|
||||
(type&~SOME_FLAG) == 1 && LightForCars1() != CAR_LIGHTS_GREEN ||
|
||||
(type&~SOME_FLAG) == 2 && LightForCars2() != CAR_LIGHTS_GREEN){
|
||||
float dist = DotProduct2D(CVector2D(vehicle->GetPosition()) - ThePaths.m_carPathLinks[node].pos,
|
||||
ThePaths.m_carPathLinks[node].dir);
|
||||
if(vehicle->AutoPilot.m_nPreviousDirection == -1){
|
||||
if(dist > 0.0f && dist < 6.0f)
|
||||
return true;
|
||||
}else{
|
||||
if(dist < 0.0f && dist > -6.0f)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
CTrafficLights::ShouldCarStopForBridge(CVehicle *vehicle)
|
||||
{
|
||||
return ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nNextPathNodeInfo].bBridgeLights &&
|
||||
!ThePaths.m_carPathLinks[vehicle->AutoPilot.m_nCurrentPathNodeInfo].bBridgeLights;
|
||||
}
|
||||
|
||||
int
|
||||
CTrafficLights::FindTrafficLightType(CEntity *light)
|
||||
{
|
||||
float orientation = RADTODEG(CGeneral::GetATanOfXY(light->GetForward().x, light->GetForward().y));
|
||||
if((orientation > 60.0f && orientation < 60.0f + 90.0f) ||
|
||||
(orientation > 240.0f && orientation < 240.0f + 90.0f))
|
||||
return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
uint8
|
||||
CTrafficLights::LightForPeds(void)
|
||||
{
|
||||
uint32 period = CTimer::GetTimeInMilliseconds() & 0x3FFF; // Equals to % 16384
|
||||
uint32 period = CTimer::GetTimeInMilliseconds() % 16384;
|
||||
|
||||
if (period >= 15384)
|
||||
return PED_LIGHTS_WALK_BLINK;
|
||||
else if (period >= 12000)
|
||||
if(period < 12000)
|
||||
return PED_LIGHTS_DONT_WALK;
|
||||
else if(period < 16384 - 1000)
|
||||
return PED_LIGHTS_WALK;
|
||||
else
|
||||
return PED_LIGHTS_DONT_WALK;
|
||||
}
|
||||
return PED_LIGHTS_WALK_BLINK;
|
||||
}
|
||||
|
||||
uint8
|
||||
CTrafficLights::LightForCars1(void)
|
||||
{
|
||||
uint32 period = CTimer::GetTimeInMilliseconds() % 16384;
|
||||
|
||||
if(period < 5000)
|
||||
return CAR_LIGHTS_GREEN;
|
||||
else if(period < 5000 + 1000)
|
||||
return CAR_LIGHTS_YELLOW;
|
||||
else
|
||||
return CAR_LIGHTS_RED;
|
||||
}
|
||||
|
||||
uint8
|
||||
CTrafficLights::LightForCars2(void)
|
||||
{
|
||||
uint32 period = CTimer::GetTimeInMilliseconds() % 16384;
|
||||
|
||||
if(period < 6000)
|
||||
return CAR_LIGHTS_RED;
|
||||
else if(period < 12000 - 1000)
|
||||
return CAR_LIGHTS_GREEN;
|
||||
else if(period < 12000)
|
||||
return CAR_LIGHTS_YELLOW;
|
||||
else
|
||||
return CAR_LIGHTS_RED;
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x455760, &CTrafficLights::LightForCars1, PATCH_JUMP);
|
||||
InjectHook(0x455790, &CTrafficLights::LightForCars2, PATCH_JUMP);
|
||||
InjectHook(0x4557D0, &CTrafficLights::LightForPeds, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
|
@ -7,6 +7,10 @@ enum {
|
||||
PED_LIGHTS_WALK,
|
||||
PED_LIGHTS_WALK_BLINK,
|
||||
PED_LIGHTS_DONT_WALK,
|
||||
|
||||
CAR_LIGHTS_GREEN = 0,
|
||||
CAR_LIGHTS_YELLOW,
|
||||
CAR_LIGHTS_RED
|
||||
};
|
||||
|
||||
class CTrafficLights
|
||||
@ -14,7 +18,10 @@ class CTrafficLights
|
||||
public:
|
||||
static void DisplayActualLight(CEntity *ent);
|
||||
static void ScanForLightsOnMap(void);
|
||||
static int FindTrafficLightType(CEntity *light);
|
||||
static uint8 LightForPeds(void);
|
||||
static uint8 LightForCars1(void);
|
||||
static uint8 LightForCars2(void);
|
||||
static bool ShouldCarStopForLight(CVehicle*, bool);
|
||||
static bool ShouldCarStopForBridge(CVehicle*);
|
||||
};
|
||||
|
Reference in New Issue
Block a user