mirror of https://github.com/Nofated095/re-GTA.git
Merge branch 'master' into game_dev
This commit is contained in:
commit
f54c83c0b5
|
@ -33,22 +33,16 @@ to reverse at the time, calling the original functions is acceptable.
|
|||
### Unreversed / incomplete classes (at least the ones we know)
|
||||
```
|
||||
cAudioManager - WIP
|
||||
CBoat
|
||||
CBulletInfo
|
||||
CObject
|
||||
CPacManPickups
|
||||
CPedPath
|
||||
CRoadBlocks
|
||||
CWeapon
|
||||
CWorld
|
||||
GenericLoad
|
||||
```
|
||||
|
||||
The following classes have only unused or practically unused code left:
|
||||
```
|
||||
CCullZone - only mobile stuff
|
||||
CCullZones - only mobile stuff
|
||||
CFileLoader - almost done
|
||||
CSceneEdit
|
||||
```
|
||||
|
||||
|
|
|
@ -2108,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:
|
||||
|
|
|
@ -54,23 +54,6 @@ uint8 aWeaponGreens[] = { 0, 255, 128, 255, 0, 255, 128, 255, 0, 255, 255, 0, 25
|
|||
uint8 aWeaponBlues[] = { 0, 0, 255, 0, 255, 255, 0, 128, 255, 0, 255, 0, 128, 255, 0, 0 };
|
||||
float aWeaponScale[] = { 1.0f, 2.0f, 1.5f, 1.0f, 1.0f, 1.5f, 1.0f, 2.0f, 1.0f, 2.0f, 2.5f, 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
|
||||
WRAPPER void CPacManPickups::Init(void) { EAXJMP(0x432760); }
|
||||
WRAPPER void CPacManPickups::Update(void) { EAXJMP(0x432800); }
|
||||
WRAPPER void CPacManPickups::GeneratePMPickUps(CVector, float, int16, uint8) { EAXJMP(0x432AE0); }
|
||||
WRAPPER void CPacManPickups::GeneratePMPickUpsForRace(int32) { EAXJMP(0x432D50); }
|
||||
WRAPPER void CPacManPickups::GenerateOnePMPickUp(CVector) { EAXJMP(0x432F20); }
|
||||
WRAPPER void CPacManPickups::Render(void) { EAXJMP(0x432F60); }
|
||||
WRAPPER void CPacManPickups::DoCleanUpPacManStuff(void) { EAXJMP(0x433150); }
|
||||
WRAPPER void CPacManPickups::StartPacManRace(int32) { EAXJMP(0x433340); }
|
||||
WRAPPER void CPacManPickups::StartPacManRecord(void) { EAXJMP(0x433360); }
|
||||
WRAPPER uint32 CPacManPickups::QueryPowerPillsEatenInRace(void) { EAXJMP(0x4333A0); }
|
||||
WRAPPER void CPacManPickups::ResetPowerPillsEatenInRace(void) { EAXJMP(0x4333B0); }
|
||||
WRAPPER void CPacManPickups::CleanUpPacManStuff(void) { EAXJMP(0x4333C0); }
|
||||
WRAPPER void CPacManPickups::StartPacManScramble(CVector, float, int16) { EAXJMP(0x4333D0); }
|
||||
WRAPPER uint32 CPacManPickups::QueryPowerPillsCarriedByPlayer(void) { EAXJMP(0x4333F0); }
|
||||
WRAPPER void CPacManPickups::ResetPowerPillsCarriedByPlayer(void) { EAXJMP(0x433410); }
|
||||
|
||||
|
||||
void
|
||||
CPickup::RemoveKeepType()
|
||||
{
|
||||
|
@ -289,13 +272,6 @@ CPickup::Update(CPlayerPed *player, CVehicle *vehicle, int playerId)
|
|||
Remove();
|
||||
DMAudio.PlayFrontEndSound(SOUND_PICKUP_MONEY, 0);
|
||||
return true;
|
||||
//case PICKUP_IN_SHOP_OUT_OF_STOCK:
|
||||
//case PICKUP_MINE_INACTIVE:
|
||||
//case PICKUP_MINE_ARMED:
|
||||
//case PICKUP_NAUTICAL_MINE_INACTIVE:
|
||||
//case PICKUP_NAUTICAL_MINE_ARMED:
|
||||
//case PICKUP_FLOATINGPACKAGE:
|
||||
//case PICKUP_FLOATINGPACKAGE_FLOATING:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -530,14 +506,12 @@ CPickups::GenerateNewOne(CVector pos, uint32 modelIndex, uint8 type, uint32 quan
|
|||
}
|
||||
}
|
||||
|
||||
if (!bFreeFound)
|
||||
{
|
||||
if (!bFreeFound) {
|
||||
for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
|
||||
if (aPickUps[slot].m_eType == PICKUP_MONEY) break;
|
||||
}
|
||||
|
||||
if (slot >= NUMGENERALPICKUPS)
|
||||
{
|
||||
if (slot >= NUMGENERALPICKUPS) {
|
||||
for (slot = 0; slot < NUMGENERALPICKUPS; slot++) {
|
||||
if (aPickUps[slot].m_eType == PICKUP_ONCE_TIMEOUT) break;
|
||||
}
|
||||
|
@ -1021,6 +995,418 @@ INITSAVEBUF
|
|||
VALIDATESAVEBUF(*size)
|
||||
}
|
||||
|
||||
void
|
||||
CPacManPickup::Update()
|
||||
{
|
||||
if (FindPlayerVehicle() == nil) return;
|
||||
|
||||
CVehicle *veh = FindPlayerVehicle();
|
||||
|
||||
if (DistanceSqr2D(FindPlayerVehicle()->GetPosition(), m_vecPosn.x, m_vecPosn.y) < 100.0f && veh->IsSphereTouchingVehicle(m_vecPosn.x, m_vecPosn.y, m_vecPosn.z, 1.5f)) {
|
||||
switch (m_eType)
|
||||
{
|
||||
case PACMAN_SCRAMBLE:
|
||||
{
|
||||
veh->m_nPacManPickupsCarried++;
|
||||
veh->m_vecMoveSpeed *= 0.65f;
|
||||
float massMult = (veh->m_fMass + 250.0f) / veh->m_fMass;
|
||||
veh->m_fMass *= massMult;
|
||||
veh->m_fTurnMass *= massMult;
|
||||
veh->m_fForceMultiplier *= massMult;
|
||||
FindPlayerPed()->m_pWanted->m_nChaos += 10;
|
||||
FindPlayerPed()->m_pWanted->UpdateWantedLevel();
|
||||
DMAudio.PlayFrontEndSound(SOUND_PICKUP_PACMAN_PACKAGE, 0);
|
||||
break;
|
||||
}
|
||||
case PACMAN_RACE:
|
||||
CPacManPickups::PillsEatenInRace++;
|
||||
DMAudio.PlayFrontEndSound(SOUND_PICKUP_PACMAN_PILL, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m_eType = PACMAN_NONE;
|
||||
if (m_pObject != nil) {
|
||||
CWorld::Remove(m_pObject);
|
||||
delete m_pObject;
|
||||
m_pObject = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32 CollectGameState;
|
||||
int16 ThingsToCollect;
|
||||
|
||||
CPacManPickup CPacManPickups::aPMPickUps[NUMPACMANPICKUPS];
|
||||
CVector CPacManPickups::LastPickUpCoors;
|
||||
int32 CPacManPickups::PillsEatenInRace;
|
||||
bool CPacManPickups::bPMActive;
|
||||
|
||||
void
|
||||
CPacManPickups::Init()
|
||||
{
|
||||
for (int i = 0; i < NUMPACMANPICKUPS; i++)
|
||||
aPMPickUps[i].m_eType = PACMAN_NONE;
|
||||
bPMActive = false;
|
||||
}
|
||||
|
||||
void
|
||||
CPacManPickups::Update()
|
||||
{
|
||||
if (FindPlayerVehicle()) {
|
||||
float dist = Distance(FindPlayerCoors(), CVector(1072.0f, -948.0f, 14.5f));
|
||||
switch (CollectGameState) {
|
||||
case 1:
|
||||
if (dist < 10.0f) {
|
||||
ThingsToCollect -= FindPlayerVehicle()->m_nPacManPickupsCarried;
|
||||
FindPlayerVehicle()->m_nPacManPickupsCarried = 0;
|
||||
FindPlayerVehicle()->m_fMass /= FindPlayerVehicle()->m_fForceMultiplier;
|
||||
FindPlayerVehicle()->m_fTurnMass /= FindPlayerVehicle()->m_fForceMultiplier;
|
||||
FindPlayerVehicle()->m_fForceMultiplier = 1.0f;
|
||||
}
|
||||
if (ThingsToCollect <= 0) {
|
||||
CollectGameState = 2;
|
||||
ClearPMPickUps();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (dist > 11.0f)
|
||||
CollectGameState = 0;
|
||||
break;
|
||||
case 20:
|
||||
if (Distance(FindPlayerCoors(), LastPickUpCoors) > 30.0f) {
|
||||
LastPickUpCoors = FindPlayerCoors();
|
||||
printf("%f, %f, %f,\n", LastPickUpCoors.x, LastPickUpCoors.y, LastPickUpCoors.z);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bPMActive) {
|
||||
#define PACMANPICKUPS_FRAME_SPAN (4)
|
||||
for (uint32 i = (CTimer::GetFrameCounter() % PACMANPICKUPS_FRAME_SPAN) * (NUMPACMANPICKUPS / PACMANPICKUPS_FRAME_SPAN); i < ((CTimer::GetFrameCounter() % PACMANPICKUPS_FRAME_SPAN) + 1) * (NUMPACMANPICKUPS / PACMANPICKUPS_FRAME_SPAN); i++) {
|
||||
if (aPMPickUps[i].m_eType != PACMAN_NONE)
|
||||
aPMPickUps[i].Update();
|
||||
}
|
||||
#undef PACMANPICKUPS_FRAME_SPAN
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPacManPickups::GeneratePMPickUps(CVector pos, float scrambleMult, int16 count, uint8 type)
|
||||
{
|
||||
int i = 0;
|
||||
while (count > 0) {
|
||||
while (aPMPickUps[i].m_eType != PACMAN_NONE)
|
||||
i++;
|
||||
|
||||
bool bPickupCreated = false;
|
||||
while (!bPickupCreated) {
|
||||
CVector newPos = pos;
|
||||
CColPoint colPoint;
|
||||
CEntity *pRoad;
|
||||
uint16 nRand = CGeneral::GetRandomNumber();
|
||||
newPos.x += ((nRand & 0xFF) - 128) * scrambleMult / 128.0f;
|
||||
newPos.y += (((nRand >> 8) & 0xFF) - 128) * scrambleMult / 128.0f;
|
||||
newPos.z = 1000.0f;
|
||||
if (CWorld::ProcessVerticalLine(newPos, -1000.0f, colPoint, pRoad, true, false, false, false, true, false, nil) && pRoad->IsBuilding() && ((CBuilding*)pRoad)->GetIsATreadable()) {
|
||||
newPos.z = 0.7f + colPoint.point.z;
|
||||
aPMPickUps[i].m_eType = type;
|
||||
aPMPickUps[i].m_vecPosn = newPos;
|
||||
CObject *obj = new CObject(MI_BULLION, true);
|
||||
if (obj != nil) {
|
||||
obj->ObjectCreatedBy = MISSION_OBJECT;
|
||||
obj->GetPosition() = aPMPickUps[i].m_vecPosn;
|
||||
obj->SetOrientation(0.0f, 0.0f, -HALFPI);
|
||||
obj->GetMatrix().UpdateRW();
|
||||
obj->UpdateRwFrame();
|
||||
|
||||
obj->bAffectedByGravity = false;
|
||||
obj->bExplosionProof = true;
|
||||
obj->bUsesCollision = false;
|
||||
obj->bIsPickup = false;
|
||||
CWorld::Add(obj);
|
||||
}
|
||||
aPMPickUps[i].m_pObject = obj;
|
||||
bPickupCreated = true;
|
||||
}
|
||||
}
|
||||
count--;
|
||||
}
|
||||
bPMActive = true;
|
||||
}
|
||||
|
||||
// diablo porn mission pickups
|
||||
static const CVector aRacePoints1[] = {
|
||||
CVector(913.62219f, -155.13692f, 4.9699469f),
|
||||
CVector(913.92401f, -124.12943f, 4.9692569f),
|
||||
CVector(913.27899f, -93.524231f, 7.4325991f),
|
||||
CVector(912.60852f, -63.15905f, 7.4533591f),
|
||||
CVector(934.22144f, -42.049122f, 7.4511471f),
|
||||
CVector(958.88092f, -23.863735f, 7.4652338f),
|
||||
CVector(978.50812f, -0.78458798f, 5.13515f),
|
||||
CVector(1009.4175f, -2.1041219f, 2.4461579f),
|
||||
CVector(1040.6313f, -2.0793829f, 2.293175f),
|
||||
CVector(1070.7863f, -2.084095f, 2.2789791f),
|
||||
CVector(1100.5773f, -8.468729f, 5.3248072f),
|
||||
CVector(1119.9341f, -31.738031f, 7.1913071f),
|
||||
CVector(1122.1664f, -62.762737f, 7.4703908f),
|
||||
CVector(1122.814f, -93.650566f, 8.5577497f),
|
||||
CVector(1125.8253f, -124.26616f, 9.9803305f),
|
||||
CVector(1153.8727f, -135.47169f, 14.150617f),
|
||||
CVector(1184.0831f, -135.82845f, 14.973998f),
|
||||
CVector(1192.0432f, -164.57816f, 19.18627f),
|
||||
CVector(1192.7761f, -194.28871f, 24.799675f),
|
||||
CVector(1215.1527f, -215.0714f, 25.74975f),
|
||||
CVector(1245.79f, -215.39304f, 28.70726f),
|
||||
CVector(1276.2477f, -216.39485f, 33.71236f),
|
||||
CVector(1306.5535f, -216.71007f, 39.711472f),
|
||||
CVector(1335.0244f, -224.59329f, 46.474979f),
|
||||
CVector(1355.4879f, -246.27664f, 49.934841f),
|
||||
CVector(1362.6003f, -276.47064f, 49.96265f),
|
||||
CVector(1363.027f, -307.30847f, 49.969173f),
|
||||
CVector(1365.343f, -338.08609f, 49.967789f),
|
||||
CVector(1367.5957f, -368.01105f, 50.092304f),
|
||||
CVector(1368.2749f, -398.38049f, 50.061268f),
|
||||
CVector(1366.9034f, -429.98483f, 50.057545f),
|
||||
CVector(1356.8534f, -459.09259f, 50.035545f),
|
||||
CVector(1335.5819f, -481.13544f, 47.217903f),
|
||||
CVector(1306.7552f, -491.07443f, 40.202629f),
|
||||
CVector(1275.5978f, -491.33194f, 33.969223f),
|
||||
CVector(1244.702f, -491.46451f, 29.111021f),
|
||||
CVector(1213.2222f, -491.8754f, 25.771168f),
|
||||
CVector(1182.7729f, -492.19995f, 24.749964f),
|
||||
CVector(1152.6874f, -491.42221f, 21.70038f),
|
||||
CVector(1121.5352f, -491.94604f, 20.075182f),
|
||||
CVector(1090.7056f, -492.63751f, 17.585758f),
|
||||
CVector(1059.6008f, -491.65762f, 14.848632f),
|
||||
CVector(1029.113f, -489.66031f, 14.918498f),
|
||||
CVector(998.20679f, -486.78107f, 14.945688f),
|
||||
CVector(968.00555f, -484.91266f, 15.001229f),
|
||||
CVector(937.74939f, -492.09015f, 14.958629f),
|
||||
CVector(927.17352f, -520.97736f, 14.972308f),
|
||||
CVector(929.29749f, -552.08643f, 14.978855f),
|
||||
CVector(950.69525f, -574.47778f, 14.972788f),
|
||||
CVector(974.02826f, -593.56024f, 14.966445f),
|
||||
CVector(989.04779f, -620.12854f, 14.951016f),
|
||||
CVector(1014.1639f, -637.3905f, 14.966736f),
|
||||
CVector(1017.5961f, -667.3736f, 14.956415f),
|
||||
CVector(1041.9735f, -685.94391f, 15.003841f),
|
||||
CVector(1043.3064f, -716.11298f, 14.974236f),
|
||||
CVector(1043.5337f, -746.63855f, 14.96919f),
|
||||
CVector(1044.142f, -776.93823f, 14.965424f),
|
||||
CVector(1044.2657f, -807.29395f, 14.97171f),
|
||||
CVector(1017.0797f, -820.1076f, 14.975431f),
|
||||
CVector(986.23865f, -820.37103f, 14.972883f),
|
||||
CVector(956.10065f, -820.23291f, 14.981133f),
|
||||
CVector(925.86914f, -820.19049f, 14.976553f),
|
||||
CVector(897.69702f, -831.08734f, 14.962709f),
|
||||
CVector(868.06586f, -835.99237f, 14.970685f),
|
||||
CVector(836.93054f, -836.84387f, 14.965049f),
|
||||
CVector(811.63586f, -853.7915f, 15.067576f),
|
||||
CVector(811.46344f, -884.27368f, 12.247812f),
|
||||
CVector(811.60651f, -914.70959f, 9.2393751f),
|
||||
CVector(811.10425f, -945.16272f, 5.817255f),
|
||||
CVector(816.54584f, -975.64587f, 4.998558f),
|
||||
CVector(828.2951f, -1003.3685f, 5.0471172f),
|
||||
CVector(852.28839f, -1021.5963f, 4.9371028f),
|
||||
CVector(882.50067f, -1025.4459f, 5.14077f),
|
||||
CVector(912.84821f, -1026.7874f, 8.3415451f),
|
||||
CVector(943.68274f, -1026.6914f, 11.341879f),
|
||||
CVector(974.4129f, -1027.3682f, 14.410345f),
|
||||
CVector(1004.1079f, -1036.0778f, 14.92961f),
|
||||
CVector(1030.1144f, -1051.1224f, 14.850387f),
|
||||
CVector(1058.7585f, -1060.342f, 14.821624f),
|
||||
CVector(1087.7797f, -1068.3263f, 14.800561f),
|
||||
CVector(1099.8807f, -1095.656f, 11.877907f),
|
||||
CVector(1130.0005f, -1101.994f, 11.853914f),
|
||||
CVector(1160.3809f, -1101.6355f, 11.854824f),
|
||||
CVector(1191.8524f, -1102.1577f, 11.853843f),
|
||||
CVector(1223.3307f, -1102.7448f, 11.852233f),
|
||||
CVector(1253.564f, -1098.1045f, 11.853944f),
|
||||
CVector(1262.0203f, -1069.1785f, 14.8147f),
|
||||
CVector(1290.9998f, -1059.1882f, 14.816016f),
|
||||
CVector(1316.246f, -1041.0635f, 14.81109f),
|
||||
CVector(1331.7539f, -1013.835f, 14.81207f),
|
||||
CVector(1334.0579f, -983.55402f, 14.827253f),
|
||||
CVector(1323.2429f, -954.23083f, 14.954678f),
|
||||
CVector(1302.7495f, -932.21216f, 14.962917f),
|
||||
CVector(1317.418f, -905.89325f, 14.967506f),
|
||||
CVector(1337.9503f, -883.5025f, 14.969675f),
|
||||
CVector(1352.6929f, -855.96954f, 14.967854f),
|
||||
CVector(1357.2388f, -826.26971f, 14.97295f),
|
||||
CVector(1384.8668f, -812.47693f, 12.907736f),
|
||||
CVector(1410.8983f, -795.39056f, 12.052228f),
|
||||
CVector(1433.901f, -775.55811f, 11.96265f),
|
||||
CVector(1443.8615f, -746.92511f, 11.976114f),
|
||||
CVector(1457.7015f, -720.00903f, 11.971177f),
|
||||
CVector(1481.5685f, -701.30237f, 11.977908f),
|
||||
CVector(1511.4004f, -696.83295f, 11.972709f),
|
||||
CVector(1542.1796f, -695.61676f, 11.970441f),
|
||||
CVector(1570.3301f, -684.6239f, 11.969202f),
|
||||
CVector(0.0f, 0.0f, 0.0f),
|
||||
};
|
||||
|
||||
void
|
||||
CPacManPickups::GeneratePMPickUpsForRace(int32 race)
|
||||
{
|
||||
const CVector *pPos = nil;
|
||||
int i = 0;
|
||||
|
||||
if (race == 0) pPos = aRacePoints1; // there's only one available
|
||||
assert(pPos != nil);
|
||||
|
||||
while (!pPos->IsZero()) {
|
||||
while (aPMPickUps[i].m_eType != PACMAN_NONE)
|
||||
i++;
|
||||
|
||||
aPMPickUps[i].m_eType = PACMAN_RACE;
|
||||
aPMPickUps[i].m_vecPosn = *(pPos++);
|
||||
if (race == 0) {
|
||||
CObject* obj = new CObject(MI_DONKEYMAG, true);
|
||||
if (obj != nil) {
|
||||
obj->ObjectCreatedBy = MISSION_OBJECT;
|
||||
|
||||
obj->GetPosition() = aPMPickUps[i].m_vecPosn;
|
||||
obj->SetOrientation(0.0f, 0.0f, -HALFPI);
|
||||
obj->GetMatrix().UpdateRW();
|
||||
obj->UpdateRwFrame();
|
||||
|
||||
obj->bAffectedByGravity = false;
|
||||
obj->bExplosionProof = true;
|
||||
obj->bUsesCollision = false;
|
||||
obj->bIsPickup = false;
|
||||
|
||||
CWorld::Add(obj);
|
||||
}
|
||||
aPMPickUps[i].m_pObject = obj;
|
||||
} else
|
||||
aPMPickUps[i].m_pObject = nil;
|
||||
}
|
||||
bPMActive = true;
|
||||
}
|
||||
|
||||
void
|
||||
CPacManPickups::GenerateOnePMPickUp(CVector pos)
|
||||
{
|
||||
bPMActive = true;
|
||||
aPMPickUps[0].m_eType = PACMAN_RACE;
|
||||
aPMPickUps[0].m_vecPosn = pos;
|
||||
}
|
||||
|
||||
void
|
||||
CPacManPickups::Render()
|
||||
{
|
||||
if (!bPMActive) return;
|
||||
|
||||
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, FALSE);
|
||||
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
|
||||
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDONE);
|
||||
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE);
|
||||
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(gpCoronaTexture[6]));
|
||||
|
||||
RwV3d pos;
|
||||
float w, h;
|
||||
|
||||
for (int i = 0; i < NUMPACMANPICKUPS; i++) {
|
||||
switch (aPMPickUps[i].m_eType)
|
||||
{
|
||||
case PACMAN_SCRAMBLE:
|
||||
case PACMAN_RACE:
|
||||
if (CSprite::CalcScreenCoors(aPMPickUps[i].m_vecPosn, &pos, &w, &h, true) && pos.z < 100.0f) {
|
||||
if (aPMPickUps[i].m_pObject != nil) {
|
||||
aPMPickUps[i].m_pObject->GetMatrix().SetRotateZOnly((CTimer::GetTimeInMilliseconds() % 1024) * TWOPI / 1024.0f);
|
||||
aPMPickUps[i].m_pObject->GetMatrix().UpdateRW();
|
||||
aPMPickUps[i].m_pObject->UpdateRwFrame();
|
||||
}
|
||||
float fsin = Sin((CTimer::GetTimeInMilliseconds() % 1024) * 6.28f / 1024.0f); // yes, it is 6.28f when it was TWOPI just now...
|
||||
CSprite::RenderOneXLUSprite(pos.x, pos.y, pos.z, 0.8f * w * fsin, 0.8f * h, 100, 50, 5, 255, 1.0f / pos.z, 255);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
|
||||
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
|
||||
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
|
||||
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
CPacManPickups::ClearPMPickUps()
|
||||
{
|
||||
bPMActive = false;
|
||||
|
||||
for (int i = 0; i < NUMPACMANPICKUPS; i++) {
|
||||
if (aPMPickUps[i].m_pObject != nil) {
|
||||
CWorld::Remove(aPMPickUps[i].m_pObject);
|
||||
delete aPMPickUps[i].m_pObject;
|
||||
aPMPickUps[i].m_pObject = nil;
|
||||
}
|
||||
aPMPickUps[i].m_eType = PACMAN_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CPacManPickups::StartPacManRace(int32 race)
|
||||
{
|
||||
GeneratePMPickUpsForRace(race);
|
||||
PillsEatenInRace = 0;
|
||||
}
|
||||
|
||||
void
|
||||
CPacManPickups::StartPacManRecord()
|
||||
{
|
||||
CollectGameState = 20;
|
||||
LastPickUpCoors = FindPlayerCoors();
|
||||
}
|
||||
|
||||
uint32
|
||||
CPacManPickups::QueryPowerPillsEatenInRace()
|
||||
{
|
||||
return PillsEatenInRace;
|
||||
}
|
||||
|
||||
void
|
||||
CPacManPickups::ResetPowerPillsEatenInRace()
|
||||
{
|
||||
PillsEatenInRace = 0;
|
||||
}
|
||||
|
||||
void
|
||||
CPacManPickups::CleanUpPacManStuff()
|
||||
{
|
||||
ClearPMPickUps();
|
||||
}
|
||||
|
||||
void
|
||||
CPacManPickups::StartPacManScramble(CVector pos, float scrambleMult, int16 count)
|
||||
{
|
||||
GeneratePMPickUps(pos, scrambleMult, count, PACMAN_SCRAMBLE);
|
||||
}
|
||||
|
||||
uint32
|
||||
CPacManPickups::QueryPowerPillsCarriedByPlayer()
|
||||
{
|
||||
if (FindPlayerVehicle())
|
||||
return FindPlayerVehicle()->m_nPacManPickupsCarried;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
CPacManPickups::ResetPowerPillsCarriedByPlayer()
|
||||
{
|
||||
if (FindPlayerVehicle() != nil) {
|
||||
FindPlayerVehicle()->m_nPacManPickupsCarried = 0;
|
||||
FindPlayerVehicle()->m_fMass /= FindPlayerVehicle()->m_fForceMultiplier;
|
||||
FindPlayerVehicle()->m_fTurnMass /= FindPlayerVehicle()->m_fForceMultiplier;
|
||||
FindPlayerVehicle()->m_fForceMultiplier = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x430220, CPickups::Init, PATCH_JUMP);
|
||||
InjectHook(0x4303D0, CPickups::Update, PATCH_JUMP);
|
||||
|
@ -1046,4 +1432,21 @@ STARTPATCHES
|
|||
InjectHook(0x433E40, CPickups::Save, PATCH_JUMP);
|
||||
InjectHook(0x433BA0, &CPickup::GiveUsAPickUpObject, PATCH_JUMP);
|
||||
InjectHook(0x430860, &CPickup::Update, PATCH_JUMP);
|
||||
InjectHook(0x4331B0, &CPacManPickup::Update, PATCH_JUMP);
|
||||
InjectHook(0x432760, CPacManPickups::Init, PATCH_JUMP);
|
||||
InjectHook(0x432800, CPacManPickups::Update, PATCH_JUMP);
|
||||
InjectHook(0x432AE0, CPacManPickups::GeneratePMPickUps, PATCH_JUMP);
|
||||
InjectHook(0x432D50, CPacManPickups::GeneratePMPickUpsForRace, PATCH_JUMP);
|
||||
InjectHook(0x432F20, CPacManPickups::GenerateOnePMPickUp, PATCH_JUMP);
|
||||
InjectHook(0x432F60, CPacManPickups::Render, PATCH_JUMP);
|
||||
InjectHook(0x433150, CPacManPickups::ClearPMPickUps, PATCH_JUMP);
|
||||
InjectHook(0x433340, CPacManPickups::StartPacManRace, PATCH_JUMP);
|
||||
InjectHook(0x433360, CPacManPickups::StartPacManRecord, PATCH_JUMP);
|
||||
InjectHook(0x4333A0, CPacManPickups::QueryPowerPillsEatenInRace, PATCH_JUMP);
|
||||
InjectHook(0x4333B0, CPacManPickups::ResetPowerPillsEatenInRace, PATCH_JUMP);
|
||||
InjectHook(0x4333C0, CPacManPickups::CleanUpPacManStuff, PATCH_JUMP);
|
||||
InjectHook(0x4333D0, CPacManPickups::StartPacManScramble, PATCH_JUMP);
|
||||
InjectHook(0x4333F0, CPacManPickups::QueryPowerPillsCarriedByPlayer, PATCH_JUMP);
|
||||
InjectHook(0x433410, CPacManPickups::ResetPowerPillsCarriedByPlayer, PATCH_JUMP);
|
||||
|
||||
ENDPATCHES
|
||||
|
|
|
@ -102,8 +102,31 @@ 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);
|
||||
|
@ -111,11 +134,11 @@ public:
|
|||
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 ClearPMPickUps(void);
|
||||
static void CleanUpPacManStuff(void);
|
||||
static void StartPacManScramble(CVector, float, int16);
|
||||
static uint32 QueryPowerPillsCarriedByPlayer(void);
|
||||
|
|
|
@ -21,8 +21,7 @@ tGameBuffer& CRecordDataForGame::pDataBufferForFrame = *(tGameBuffer*)0x72CED0;
|
|||
void CRecordDataForGame::Init(void)
|
||||
{
|
||||
RecordingState = STATE_NONE;
|
||||
if (pDataBuffer)
|
||||
delete[] pDataBuffer;
|
||||
delete[] pDataBuffer;
|
||||
pDataBufferPointer = nil;
|
||||
pDataBuffer = nil;
|
||||
#ifndef GTA_PS2 // this stuff is not present on PS2
|
||||
|
@ -42,7 +41,7 @@ void CRecordDataForGame::Init(void)
|
|||
if (RecordingState == STATE_PLAYBACK) {
|
||||
pDataBufferPointer = new uint8[MEMORY_FOR_GAME_RECORD];
|
||||
pDataBuffer = pDataBufferPointer;
|
||||
pDataBuffer[CFileMgr::Read(FId, (char*)pDataBufferPointer, MEMORY_FOR_GAME_RECORD) + 8] = -1;
|
||||
pDataBuffer[CFileMgr::Read(FId, (char*)pDataBufferPointer, MEMORY_FOR_GAME_RECORD) + 8] = (uint8)-1;
|
||||
CFileMgr::CloseFile(FId);
|
||||
}
|
||||
#else
|
||||
|
@ -71,7 +70,7 @@ void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void)
|
|||
break;
|
||||
}
|
||||
case STATE_PLAYBACK:
|
||||
if (pDataBufferPointer[8] == -1)
|
||||
if (pDataBufferPointer[8] == (uint8)-1)
|
||||
CPad::GetPad(0)->NewState.Clear();
|
||||
else {
|
||||
tGameBuffer* pData = (tGameBuffer*)pDataBufferPointer;
|
||||
|
@ -92,7 +91,7 @@ void CRecordDataForGame::SaveOrRetrieveDataForThisFrame(void)
|
|||
|
||||
#define PROCESS_BUTTON_STATE_STORE(buf, os, ns, field, id) \
|
||||
do { \
|
||||
if (os->field != os->field){ \
|
||||
if (os->field != ns->field){ \
|
||||
*buf++ = id; \
|
||||
*buf++ = ns->field; \
|
||||
} \
|
||||
|
@ -102,7 +101,7 @@ uint8* CRecordDataForGame::PackCurrentPadValues(uint8* buf, CControllerState* os
|
|||
{
|
||||
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, LeftShoulder1, 2);
|
||||
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);
|
||||
|
@ -132,7 +131,7 @@ uint8* CRecordDataForGame::UnPackCurrentPadValues(uint8* buf, uint8 total, CCont
|
|||
switch (*buf++) {
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickX, 0);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftStickY, 1);
|
||||
PROCESS_BUTTON_STATE_RESTORE(buf, state, LeftShoulder1, 2);
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
#include "CdStream.h"
|
||||
#include "FileLoader.h"
|
||||
|
||||
WRAPPER void CFileLoader::ReloadPaths(const char *filename) { EAXJMP(0x476DB0); }
|
||||
|
||||
char CFileLoader::ms_line[256];
|
||||
|
||||
const char*
|
||||
|
@ -1198,6 +1196,165 @@ CFileLoader::LoadMapZones(const char *filename)
|
|||
debug("Finished loading IPL\n");
|
||||
}
|
||||
|
||||
void
|
||||
CFileLoader::ReloadPaths(const char *filename)
|
||||
{
|
||||
enum {
|
||||
NONE,
|
||||
PATH,
|
||||
};
|
||||
char *line;
|
||||
int section = NONE;
|
||||
int id, pathType, pathIndex = -1;
|
||||
char pathTypeStr[20];
|
||||
debug("Reloading paths from %s...\n", filename);
|
||||
|
||||
int fd = CFileMgr::OpenFile(filename, "r");
|
||||
for (line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)) {
|
||||
if (*line == '\0' || *line == '#')
|
||||
continue;
|
||||
|
||||
if (section == NONE) {
|
||||
if (strncmp(line, "path", 4) == 0) {
|
||||
section = PATH;
|
||||
ThePaths.AllocatePathFindInfoMem(4500);
|
||||
}
|
||||
} else if (strncmp(line, "end", 3) == 0) {
|
||||
section = NONE;
|
||||
} else {
|
||||
switch (section) {
|
||||
case PATH:
|
||||
if (pathIndex == -1) {
|
||||
id = LoadPathHeader(line, pathTypeStr);
|
||||
if (strncmp(pathTypeStr, "ped", 4) == 0)
|
||||
pathType = 1;
|
||||
else if (strncmp(pathTypeStr, "car", 4) == 0)
|
||||
pathType = 0;
|
||||
pathIndex = 0;
|
||||
} else {
|
||||
if (pathType == 1)
|
||||
LoadPedPathNode(line, id, pathIndex);
|
||||
else if (pathType == 0)
|
||||
LoadCarPathNode(line, id, pathIndex);
|
||||
pathIndex++;
|
||||
if (pathIndex == 12)
|
||||
pathIndex = -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
CFileMgr::CloseFile(fd);
|
||||
}
|
||||
|
||||
void
|
||||
CFileLoader::ReloadObjectTypes(const char *filename)
|
||||
{
|
||||
enum {
|
||||
NONE,
|
||||
OBJS,
|
||||
TOBJ,
|
||||
TWODFX
|
||||
};
|
||||
char *line;
|
||||
int section = NONE;
|
||||
CModelInfo::ReInit2dEffects();
|
||||
debug("Reloading object types from %s...\n", filename);
|
||||
|
||||
CFileMgr::ChangeDir("\\DATA\\MAPS\\");
|
||||
int fd = CFileMgr::OpenFile(filename, "r");
|
||||
CFileMgr::ChangeDir("\\");
|
||||
for (line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)) {
|
||||
if (*line == '\0' || *line == '#')
|
||||
continue;
|
||||
|
||||
if (section == NONE) {
|
||||
if (strncmp(line, "objs", 4) == 0) section = OBJS;
|
||||
else if (strncmp(line, "tobj", 4) == 0) section = TOBJ;
|
||||
else if (strncmp(line, "2dfx", 4) == 0) section = TWODFX;
|
||||
} else if (strncmp(line, "end", 3) == 0) {
|
||||
section = NONE;
|
||||
} else {
|
||||
switch (section) {
|
||||
case OBJS:
|
||||
case TOBJ:
|
||||
ReloadObject(line);
|
||||
break;
|
||||
case TWODFX:
|
||||
Load2dEffect(line);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
CFileMgr::CloseFile(fd);
|
||||
}
|
||||
|
||||
void
|
||||
CFileLoader::ReloadObject(const char *line)
|
||||
{
|
||||
int id, numObjs;
|
||||
char model[24], txd[24];
|
||||
float dist[3];
|
||||
uint32 flags;
|
||||
CSimpleModelInfo *mi;
|
||||
|
||||
if(sscanf(line, "%d %s %s %d", &id, model, txd, &numObjs) != 4)
|
||||
return;
|
||||
|
||||
switch(numObjs){
|
||||
case 1:
|
||||
sscanf(line, "%d %s %s %d %f %d",
|
||||
&id, model, txd, &numObjs, &dist[0], &flags);
|
||||
break;
|
||||
case 2:
|
||||
sscanf(line, "%d %s %s %d %f %f %d",
|
||||
&id, model, txd, &numObjs, &dist[0], &dist[1], &flags);
|
||||
break;
|
||||
case 3:
|
||||
sscanf(line, "%d %s %s %d %f %f %f %d",
|
||||
&id, model, txd, &numObjs, &dist[0], &dist[1], &dist[2], &flags);
|
||||
break;
|
||||
}
|
||||
|
||||
mi = (CSimpleModelInfo*) CModelInfo::GetModelInfo(id);
|
||||
if (
|
||||
#ifdef FIX_BUGS
|
||||
mi &&
|
||||
#endif
|
||||
mi->m_type == MITYPE_SIMPLE && !strcmp(mi->GetName(), model) && mi->m_numAtomics == numObjs) {
|
||||
mi->SetLodDistances(dist);
|
||||
SetModelInfoFlags(mi, flags);
|
||||
} else {
|
||||
printf("Can't reload %s\n", model);
|
||||
}
|
||||
}
|
||||
|
||||
// unused mobile function - crashes
|
||||
void
|
||||
CFileLoader::ReLoadScene(const char *filename)
|
||||
{
|
||||
char *line;
|
||||
CFileMgr::ChangeDir("\\DATA\\");
|
||||
int fd = CFileMgr::OpenFile(filename, "r");
|
||||
CFileMgr::ChangeDir("\\");
|
||||
|
||||
for (line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)) {
|
||||
if (*line == '#')
|
||||
continue;
|
||||
|
||||
if (strncmp(line, "EXIT", 9) == 0) // BUG: 9?
|
||||
break;
|
||||
|
||||
if (strncmp(line, "IDE", 3) == 0) {
|
||||
LoadObjectTypes(line + 4);
|
||||
}
|
||||
}
|
||||
CFileMgr::CloseFile(fd);
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x476290, CFileLoader::LoadLevel, PATCH_JUMP);
|
||||
|
@ -1233,4 +1390,8 @@ STARTPATCHES
|
|||
InjectHook(0x478A90, CFileLoader::LoadCullZone, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x478550, CFileLoader::LoadMapZones, PATCH_JUMP);
|
||||
|
||||
InjectHook(0x476DB0, CFileLoader::ReloadPaths, PATCH_JUMP);
|
||||
InjectHook(0x476F30, CFileLoader::ReloadObjectTypes, PATCH_JUMP);
|
||||
InjectHook(0x4772B0, CFileLoader::ReloadObject, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
|
|
|
@ -43,4 +43,7 @@ public:
|
|||
static void LoadMapZones(const char *filename);
|
||||
|
||||
static void ReloadPaths(const char *filename);
|
||||
static void ReloadObjectTypes(const char *filename);
|
||||
static void ReloadObject(const char *line);
|
||||
static void ReLoadScene(const char *filename); // unused mobile function
|
||||
};
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "Radar.h"
|
||||
#include "Stats.h"
|
||||
#include "Messages.h"
|
||||
#include "FileLoader.h"
|
||||
|
||||
#define TIDY_UP_PBP // ProcessButtonPresses
|
||||
#define MAX_VISIBLE_LIST_ROW 30
|
||||
|
@ -44,16 +45,27 @@
|
|||
#define FEET_IN_METER 3.33f
|
||||
#endif
|
||||
|
||||
#define SCROLLABLE_STATS_PAGE
|
||||
#ifdef SCROLLABLE_STATS_PAGE
|
||||
#define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS)
|
||||
#else
|
||||
#define isPlainTextScreen(screen) (screen == MENUPAGE_BRIEFS || screen == MENUPAGE_STATS)
|
||||
#endif
|
||||
|
||||
#ifdef TRIANGLE_BACK_BUTTON
|
||||
#define GetBackJustUp GetTriangleJustUp
|
||||
#define GetBackJustDown GetTriangleJustDown
|
||||
#elif defined(CIRCLE_BACK_BUTTON)
|
||||
#define GetBackJustUp GetCircleJustUp
|
||||
#define GetBackJustDown GetCircleJustDown
|
||||
#else
|
||||
#define GetBackJustUp GetSquareJustUp
|
||||
#define GetBackJustDown GetSquareJustDown
|
||||
#endif
|
||||
|
||||
#ifdef MENU_MAP
|
||||
bool CMenuManager::bMenuMapActive = false;
|
||||
bool CMenuManager::bMapMouseShownOnce = false;
|
||||
bool CMenuManager::bMapLoaded = false;
|
||||
float CMenuManager::fMapSize;
|
||||
float CMenuManager::fMapCenterY;
|
||||
float CMenuManager::fMapCenterX;
|
||||
|
@ -99,14 +111,14 @@ char *CMenuManager::m_PrefsSkinFile = (char*)0x5F2E74; //[256] "$$\"\""
|
|||
|
||||
int32 &CMenuManager::m_KeyPressedCode = *(int32*)0x5F2E70; // -1
|
||||
|
||||
// This is PS2 option color, they forget it here and used in PrintBriefs once(but didn't use the output anyway)
|
||||
#ifdef FIX_BUGS
|
||||
CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color
|
||||
// Originally that was PS2 option color, they forget it here and used in PrintBriefs once(but didn't use the output anyway)
|
||||
#ifdef PS2_LIKE_MENU
|
||||
const CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255);
|
||||
#else
|
||||
CRGBA TEXT_COLOR = CRGBA(150, 110, 30, 255);
|
||||
const CRGBA TEXT_COLOR = CRGBA(235, 170, 50, 255); // PC briefs text color
|
||||
#endif
|
||||
|
||||
float menuXYpadding = MENUACTION_POS_Y; // *(float*)0x5F355C; // never changes. not original name
|
||||
const float menuXYpadding = MENUACTION_POS_Y; // *(float*)0x5F355C; // not original name
|
||||
float MENU_TEXT_SIZE_X = SMALLTEXT_X_SCALE; //*(float*)0x5F2E40;
|
||||
float MENU_TEXT_SIZE_Y = SMALLTEXT_Y_SCALE; //*(float*)0x5F2E44;
|
||||
|
||||
|
@ -119,17 +131,17 @@ uint8 CMenuManager::m_PrefsPlayerRed = 255;
|
|||
uint8 CMenuManager::m_PrefsPlayerGreen = 128;
|
||||
uint8 CMenuManager::m_PrefsPlayerBlue; // why??
|
||||
|
||||
CMenuManager &FrontEndMenuManager = *(CMenuManager*)0x8F59D8;
|
||||
CMenuManager FrontEndMenuManager; // = *(CMenuManager*)0x8F59D8;
|
||||
|
||||
// Move this somewhere else.
|
||||
float &CRenderer::ms_lodDistScale = *(float*)0x5F726C; // 1.2
|
||||
float CRenderer::ms_lodDistScale = 1.2f; // *(float*)0x5F726C;
|
||||
|
||||
uint32 &TimeToStopPadShaking = *(uint32*)0x628CF8;
|
||||
char *&pEditString = *(char**)0x628D00;
|
||||
int32 *&pControlEdit = *(int32**)0x628D08;
|
||||
bool &DisplayComboButtonErrMsg = *(bool*)0x628D14;
|
||||
int32 &MouseButtonJustClicked = *(int32*)0x628D0C;
|
||||
int32 &JoyButtonJustClicked = *(int32*)0x628D10;
|
||||
uint32 TimeToStopPadShaking; // = *(uint32*)0x628CF8;
|
||||
char *pEditString; // = *(char**)0x628D00;
|
||||
int32 *pControlEdit; // = *(int32**)0x628D08;
|
||||
bool DisplayComboButtonErrMsg; // = *(bool*)0x628D14;
|
||||
int32 MouseButtonJustClicked; // = *(int32*)0x628D0C;
|
||||
int32 JoyButtonJustClicked; // = *(int32*)0x628D10;
|
||||
//int32 *pControlTemp = 0;
|
||||
|
||||
#ifndef MASTER
|
||||
|
@ -359,11 +371,6 @@ CMenuManager::PageDownList(bool playSoundOnSuccess)
|
|||
inline void
|
||||
CMenuManager::ThingsToDoBeforeLeavingPage()
|
||||
{
|
||||
#ifndef MASTER
|
||||
if (m_nCurrScreen == MENUPAGE_NO_MEMORY_CARD || m_nCurrScreen == MENUPAGE_MEMORY_CARD_DEBUG) {
|
||||
SaveSettings();
|
||||
}
|
||||
#endif
|
||||
if ((m_nCurrScreen == MENUPAGE_SKIN_SELECT) && strcmp(m_aSkinName, m_PrefsSkinFile) != 0) {
|
||||
CWorld::Players[0].SetPlayerSkin(m_PrefsSkinFile);
|
||||
} else if (m_nCurrScreen == MENUPAGE_SOUND_SETTINGS) {
|
||||
|
@ -719,13 +726,6 @@ CMenuManager::Draw()
|
|||
else
|
||||
str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName);
|
||||
break;
|
||||
#ifndef MASTER
|
||||
case MENUPAGE_NO_MEMORY_CARD:
|
||||
case MENUPAGE_MEMORY_CARD_DEBUG:
|
||||
CFont::SetColor(CRGBA(235, 170, 50, FadeIn(127))); // white in mobile, because all texts are white there
|
||||
str = TheText.Get(aScreens[m_nCurrScreen].m_aEntries[0].m_EntryName);
|
||||
break;
|
||||
#endif
|
||||
case MENUPAGE_SAVE_OVERWRITE_CONFIRM:
|
||||
if (Slots[m_nCurrSaveSlot + 1] == SLOT_EMPTY)
|
||||
str = TheText.Get("FESZ_QZ");
|
||||
|
@ -743,20 +743,12 @@ CMenuManager::Draw()
|
|||
break;
|
||||
}
|
||||
|
||||
#ifndef MASTER
|
||||
if (m_nCurrScreen == MENUPAGE_NO_MEMORY_CARD || m_nCurrScreen == MENUPAGE_MEMORY_CARD_DEBUG) {
|
||||
// CFont::SetWrapx(MENU_X_RIGHT_ALIGNED(MENU_X_MARGIN)); // it's always like that on PC
|
||||
CFont::PrintString(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN), MENU_Y(210.0), str);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#ifdef FIX_BUGS
|
||||
// Label is wrapped from right by StretchX(40)px, but wrapped from left by 40px. And this is only place R* didn't use StretchX in here.
|
||||
CFont::PrintString(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN), MENU_Y(menuXYpadding), str);
|
||||
// Label is wrapped from right by StretchX(40)px, but wrapped from left by 40px. And this is only place R* didn't use StretchX in here.
|
||||
CFont::PrintString(MENU_X_LEFT_ALIGNED(MENU_X_MARGIN), MENU_Y(menuXYpadding), str);
|
||||
#else
|
||||
CFont::PrintString(MENU_X_MARGIN, menuXYpadding, str);
|
||||
CFont::PrintString(MENU_X_MARGIN, menuXYpadding, str);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
CFont::SetCentreSize(SCREEN_WIDTH);
|
||||
|
@ -853,6 +845,10 @@ CMenuManager::Draw()
|
|||
break;
|
||||
}
|
||||
|
||||
#ifdef PS2_LIKE_MENU
|
||||
CFont::SetFontStyle(FONT_BANK);
|
||||
#endif
|
||||
|
||||
switch (m_nCurrScreen) {
|
||||
case MENUPAGE_CONTROLLER_PC_OLD1:
|
||||
case MENUPAGE_CONTROLLER_PC_OLD2:
|
||||
|
@ -2149,7 +2145,7 @@ CMenuManager::DrawFrontEndNormal()
|
|||
}
|
||||
|
||||
#define optionWidth MENU_X(66.0f)
|
||||
#define rawOptionHeight 20.0f
|
||||
#define rawOptionHeight 22.0f
|
||||
#define optionBottom SCREEN_SCALE_FROM_BOTTOM(20.0f)
|
||||
#define optionTop SCREEN_SCALE_FROM_BOTTOM(20.0f + rawOptionHeight)
|
||||
#define leftPadding MENU_X_LEFT_ALIGNED(90.0f)
|
||||
|
@ -3196,31 +3192,33 @@ CMenuManager::PrintBriefs()
|
|||
newColor = TEXT_COLOR;
|
||||
FilterOutColorMarkersFromString(gUString, newColor);
|
||||
|
||||
// newColor wasn't used at all! let's fix this
|
||||
#ifdef PS2_LIKE_MENU
|
||||
// This PS2 code was always here, but unused
|
||||
bool rgSame = newColor.r == TEXT_COLOR.r && newColor.g == TEXT_COLOR.g;
|
||||
bool bSame = rgSame && newColor.b == TEXT_COLOR.b;
|
||||
bool colorNotChanged = bSame
|
||||
#ifndef FIX_BUGS
|
||||
&& newColor.a == TEXT_COLOR.a
|
||||
#endif
|
||||
;
|
||||
bool colorNotChanged = bSame; /* && newColor.a == TEXT_COLOR.a; */
|
||||
|
||||
if (!colorNotChanged) {
|
||||
newColor.r /= 2;
|
||||
newColor.g /= 2;
|
||||
newColor.b /= 2;
|
||||
}
|
||||
#ifdef FIX_BUGS
|
||||
newColor.a = FadeIn(255);
|
||||
// because some colors aren't visible, due to they were made for PS2
|
||||
CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255)));
|
||||
CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); // But this is from PS2
|
||||
CFont::SetDropShadowPosition(1);
|
||||
#endif
|
||||
|
||||
#if defined(FIX_BUGS) || defined(PS2_LIKE_MENU)
|
||||
newColor.a = FadeIn(255);
|
||||
CFont::SetColor(newColor);
|
||||
#endif
|
||||
CFont::PrintString(MENU_X_LEFT_ALIGNED(50.0f), nextY, gUString);
|
||||
nextY += MENU_Y(menuXYpadding);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PS2_LIKE_MENU
|
||||
CFont::SetDropShadowPosition(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Not sure about name. Not to be confused with CPad::PrintErrorMessage
|
||||
|
@ -3337,6 +3335,7 @@ CMenuManager::Process(void)
|
|||
m_bWantToRestart = false;
|
||||
InitialiseChangedLanguageSettings();
|
||||
|
||||
// Just a hack by R* to not make game continuously resume/pause. But we it seems we can live with it.
|
||||
if (CPad::GetPad(0)->GetEscapeJustDown())
|
||||
RequestFrontEndStartUp();
|
||||
|
||||
|
@ -3662,7 +3661,7 @@ CMenuManager::ProcessButtonPresses(void)
|
|||
}
|
||||
|
||||
#ifndef TIDY_UP_PBP
|
||||
if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetSquareJustDown()) {
|
||||
if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustDown()) {
|
||||
m_bShowMouse = false;
|
||||
goBack = true;
|
||||
}
|
||||
|
@ -3741,7 +3740,7 @@ CMenuManager::ProcessButtonPresses(void)
|
|||
if (CPad::GetPad(0)->GetEnterJustDown() || CPad::GetPad(0)->GetCrossJustDown() || CPad::GetPad(0)->GetLeftMouseJustDown()) {
|
||||
optionSelected = true;
|
||||
}
|
||||
if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetSquareJustUp()) {
|
||||
if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustUp()) {
|
||||
if (m_nCurrScreen != MENUPAGE_START_MENU) {
|
||||
goBack = true;
|
||||
}
|
||||
|
@ -4009,7 +4008,7 @@ CMenuManager::ProcessButtonPresses(void)
|
|||
|
||||
}
|
||||
#ifndef TIDY_UP_PBP
|
||||
if (CPad::GetPad(0)->GetSquareJustDown()) {
|
||||
if (CPad::GetPad(0)->GetBackJustDown()) {
|
||||
if (m_nCurrScreen != MENUPAGE_START_MENU && m_nCurrScreen != MENUPAGE_PAUSE_MENU) {
|
||||
m_bShowMouse = false;
|
||||
goBack = true;
|
||||
|
@ -4050,11 +4049,11 @@ CMenuManager::ProcessButtonPresses(void)
|
|||
if (!goDown && !goUp && !optionSelected) {
|
||||
if (m_nCurrScreen != MENUPAGE_START_MENU) {
|
||||
if (isPlainTextScreen(m_nCurrScreen)) {
|
||||
if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetSquareJustUp()) {
|
||||
if (CPad::GetPad(0)->GetEscapeJustDown() || CPad::GetPad(0)->GetBackJustUp()) {
|
||||
goBack = true;
|
||||
}
|
||||
} else {
|
||||
if (CPad::GetPad(0)->GetEscapeJustDown() || (m_nCurrScreen != MENUPAGE_PAUSE_MENU && CPad::GetPad(0)->GetSquareJustDown())) {
|
||||
if (CPad::GetPad(0)->GetEscapeJustDown() || (m_nCurrScreen != MENUPAGE_PAUSE_MENU && CPad::GetPad(0)->GetBackJustDown())) {
|
||||
m_bShowMouse = false;
|
||||
goBack = true;
|
||||
}
|
||||
|
@ -4300,12 +4299,7 @@ CMenuManager::ProcessButtonPresses(void)
|
|||
} else {
|
||||
#ifdef MENU_MAP
|
||||
if (aScreens[m_nCurrScreen].m_aEntries[m_nCurrOption].m_TargetMenu == MENUPAGE_MAP) {
|
||||
fMapCenterX = SCREEN_WIDTH / 2;
|
||||
fMapCenterY = SCREEN_HEIGHT / 3;
|
||||
fMapSize = SCREEN_HEIGHT / CDraw::GetAspectRatio();
|
||||
bMapMouseShownOnce = false;
|
||||
CPad::GetPad(0)->Clear(false);
|
||||
CPad::GetPad(1)->Clear(false);
|
||||
bMapLoaded = false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -4330,8 +4324,7 @@ CMenuManager::ProcessButtonPresses(void)
|
|||
DoSettingsBeforeStartingAGame();
|
||||
break;
|
||||
case MENUACTION_RELOADIDE:
|
||||
// TODO
|
||||
// CFileLoader::ReloadObjectTypes("GTA3.IDE");
|
||||
CFileLoader::ReloadObjectTypes("GTA3.IDE");
|
||||
break;
|
||||
case MENUACTION_RELOADIPL:
|
||||
CGame::ReloadIPLs();
|
||||
|
@ -4913,8 +4906,19 @@ CMenuManager::SwitchMenuOnAndOff()
|
|||
pControlEdit = nil;
|
||||
m_bShutDownFrontEndRequested = false;
|
||||
DisplayComboButtonErrMsg = false;
|
||||
CPad::GetPad(0)->Clear(0);
|
||||
CPad::GetPad(1)->Clear(0);
|
||||
|
||||
#ifdef REGISTER_START_BUTTON
|
||||
int16 start1 = CPad::GetPad(0)->PCTempJoyState.Start, start2 = CPad::GetPad(0)->PCTempKeyState.Start,
|
||||
start3 = CPad::GetPad(0)->OldState.Start, start4 = CPad::GetPad(0)->NewState.Start;
|
||||
#endif
|
||||
CPad::GetPad(0)->Clear(false);
|
||||
CPad::GetPad(1)->Clear(false);
|
||||
#ifdef REGISTER_START_BUTTON
|
||||
CPad::GetPad(0)->PCTempJoyState.Start = start1;
|
||||
CPad::GetPad(0)->PCTempKeyState.Start = start2;
|
||||
CPad::GetPad(0)->OldState.Start = start3;
|
||||
CPad::GetPad(0)->NewState.Start = start4;
|
||||
#endif
|
||||
m_nCurrScreen = MENUPAGE_NONE;
|
||||
}
|
||||
}
|
||||
|
@ -5025,7 +5029,7 @@ CMenuManager::PrintController(void)
|
|||
CFont::SetFontStyle(FONT_BANK); // X
|
||||
|
||||
// CFont::SetScale(0.4f, 0.4f);
|
||||
CFont::SetScale(MENU_X(SMALLTEXT_X_SCALE), MENU_Y(SMALLTEXT_Y_SCALE)); // X
|
||||
CFont::SetScale(MENU_X(SMALLESTTEXT_X_SCALE), MENU_Y(SMALLESTTEXT_Y_SCALE)); // X
|
||||
|
||||
// CFont::SetColor(CRGBA(128, 128, 128, FadeIn(255)));
|
||||
CFont::SetDropColor(CRGBA(0, 0, 0, FadeIn(255))); // X
|
||||
|
@ -5219,6 +5223,8 @@ CMenuManager::PrintController(void)
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CFont::SetDropShadowPosition(0); // X
|
||||
}
|
||||
|
||||
#ifdef MENU_MAP
|
||||
|
@ -5243,6 +5249,20 @@ CMenuManager::PrintMap(void)
|
|||
bMenuMapActive = true;
|
||||
CRadar::InitFrontEndMap();
|
||||
|
||||
if (!bMapLoaded) {
|
||||
fMapCenterX = SCREEN_WIDTH / 2;
|
||||
fMapCenterY = SCREEN_HEIGHT / 3;
|
||||
fMapSize = SCREEN_HEIGHT / CDraw::GetAspectRatio();
|
||||
bMapMouseShownOnce = false;
|
||||
bMapLoaded = true;
|
||||
|
||||
// Let's wait for a frame to not toggle the waypoint
|
||||
if (CPad::GetPad(0)->NewState.Cross) {
|
||||
bMenuMapActive = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Because fMapSize is half of the map length, and map consists of 3x3 tiles.
|
||||
float halfTile = fMapSize / 3.0f;
|
||||
|
||||
|
@ -5601,6 +5621,9 @@ uint8 CMenuManager::GetNumberOfMenuOptions()
|
|||
}
|
||||
#endif
|
||||
|
||||
#undef GetBackJustUp
|
||||
#undef GetBackJustDown
|
||||
|
||||
STARTPATCHES
|
||||
for (int i = 1; i < ARRAY_SIZE(aScreens); i++)
|
||||
Patch(0x611930 + sizeof(CMenuScreen) * i, aScreens[i]);
|
||||
|
|
|
@ -196,7 +196,7 @@ enum eMenuScreen
|
|||
MENUPAGE_NEW_GAME_RELOAD = 10,
|
||||
MENUPAGE_LOAD_SLOT_CONFIRM = 11,
|
||||
MENUPAGE_DELETE_SLOT_CONFIRM = 12,
|
||||
MENUPAGE_NO_MEMORY_CARD = 13,
|
||||
MENUPAGE_NO_MEMORY_CARD = 13, // hud adjustment page in mobile
|
||||
MENUPAGE_LOADING_IN_PROGRESS = 14,
|
||||
MENUPAGE_DELETING_IN_PROGRESS = 15,
|
||||
MENUPAGE_PS2_LOAD_FAILED = 16,
|
||||
|
@ -240,7 +240,7 @@ enum eMenuScreen
|
|||
MENUPAGE_SKIN_SELECT = 54,
|
||||
MENUPAGE_KEYBOARD_CONTROLS = 55,
|
||||
MENUPAGE_MOUSE_CONTROLS = 56,
|
||||
MENUPAGE_57 = 57,
|
||||
MENUPAGE_57 = 57, // mission failed, wanna restart page in mobile
|
||||
MENUPAGE_58 = 58,
|
||||
#ifdef MENU_MAP
|
||||
MENUPAGE_MAP = 59,
|
||||
|
@ -570,6 +570,7 @@ public:
|
|||
#ifdef MENU_MAP
|
||||
static bool bMenuMapActive;
|
||||
static bool bMapMouseShownOnce;
|
||||
static bool bMapLoaded;
|
||||
static float fMapSize;
|
||||
static float fMapCenterY;
|
||||
static float fMapCenterX;
|
||||
|
@ -639,4 +640,4 @@ public:
|
|||
|
||||
static_assert(sizeof(CMenuManager) == 0x564, "CMenuManager: error");
|
||||
|
||||
extern CMenuManager &FrontEndMenuManager;
|
||||
extern CMenuManager FrontEndMenuManager;
|
||||
|
|
|
@ -128,7 +128,7 @@ const CMenuScreen aScreens[] = {
|
|||
|
||||
// MENUPAGE_NO_MEMORY_CARD = 13
|
||||
{ "FES_NOC", 1, MENUPAGE_DISABLED, MENUPAGE_DISABLED, 0, 0,
|
||||
MENUACTION_LABEL, "FEC_OFI", SAVESLOT_NONE, MENUPAGE_NONE, // only in mobile. FEC_OFI is missing
|
||||
// hud adjustment page in mobile
|
||||
},
|
||||
|
||||
// MENUPAGE_LOADING_IN_PROGRESS = 14
|
||||
|
@ -281,7 +281,6 @@ const CMenuScreen aScreens[] = {
|
|||
MENUACTION_CTRLMETHOD, "FET_CME", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC,
|
||||
MENUACTION_CHANGEMENU, "FET_RDK", SAVESLOT_NONE, MENUPAGE_KEYBOARD_CONTROLS,
|
||||
MENUACTION_CHANGEMENU, "FET_AMS", SAVESLOT_NONE, MENUPAGE_MOUSE_CONTROLS,
|
||||
|
||||
MENUACTION_RESTOREDEF, "FET_DEF", SAVESLOT_NONE, MENUPAGE_CONTROLLER_PC,
|
||||
MENUACTION_CHANGEMENU, "FEDS_TB", SAVESLOT_NONE, MENUPAGE_NONE,
|
||||
},
|
||||
|
@ -444,7 +443,7 @@ const CMenuScreen aScreens[] = {
|
|||
|
||||
// MENUPAGE_57 = 57
|
||||
{ "", 0, MENUPAGE_NONE, MENUPAGE_NONE, 0, 0,
|
||||
|
||||
// mission failed, wanna restart page in mobile
|
||||
},
|
||||
|
||||
// MENUPAGE_58 = 58
|
||||
|
|
|
@ -418,6 +418,7 @@ public:
|
|||
bool GetLeftStickXJustDown() { return !!(NewState.LeftStickX && !OldState.LeftStickX); }
|
||||
bool GetLeftStickYJustDown() { return !!(NewState.LeftStickY && !OldState.LeftStickY); }
|
||||
|
||||
bool GetTriangleJustUp() { return !!(!NewState.Triangle && OldState.Triangle); }
|
||||
bool GetCrossJustUp() { return !!(!NewState.Cross && OldState.Cross); }
|
||||
bool GetSquareJustUp() { return !!(!NewState.Square && OldState.Square); }
|
||||
bool GetDPadUpJustUp() { return !!(!NewState.DPadUp && OldState.DPadUp); }
|
||||
|
|
|
@ -183,7 +183,7 @@ INITSAVEBUF
|
|||
if (!pVehicle)
|
||||
continue;
|
||||
bool bHasPassenger = false;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
for (int j = 0; j < ARRAY_SIZE(pVehicle->pPassengers); j++) {
|
||||
if (pVehicle->pPassengers[i])
|
||||
bHasPassenger = true;
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ INITSAVEBUF
|
|||
if (!pVehicle)
|
||||
continue;
|
||||
bool bHasPassenger = false;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
for (int j = 0; j < ARRAY_SIZE(pVehicle->pPassengers); j++) {
|
||||
if (pVehicle->pPassengers[j])
|
||||
bHasPassenger = true;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,9 @@ public:
|
|||
static void Stop(void);
|
||||
static void StartUserPause(void);
|
||||
static void EndUserPause(void);
|
||||
|
||||
friend bool GenericLoad(void);
|
||||
friend bool GenericSave(int file);
|
||||
};
|
||||
|
||||
#ifdef FIX_BUGS
|
||||
|
|
|
@ -87,6 +87,7 @@ enum Config {
|
|||
NUMSCRIPTEDPICKUPS = 16,
|
||||
NUMPICKUPS = NUMGENERALPICKUPS + NUMSCRIPTEDPICKUPS,
|
||||
NUMCOLLECTEDPICKUPS = 20,
|
||||
NUMPACMANPICKUPS = 256,
|
||||
NUMEVENTS = 64,
|
||||
|
||||
NUM_CARGENS = 160,
|
||||
|
@ -192,7 +193,7 @@ enum Config {
|
|||
// Pad
|
||||
#define XINPUT
|
||||
#define KANGAROO_CHEAT
|
||||
#define REGISTER_START_BUTTON // currently only in menu sadly. resumes the game
|
||||
#define REGISTER_START_BUTTON
|
||||
|
||||
// Hud, frontend and radar
|
||||
#define ASPECT_RATIO_SCALE // Not just makes everything scale with aspect ratio, also adds support for all aspect ratios
|
||||
|
@ -200,6 +201,9 @@ enum Config {
|
|||
#define PS2_SAVE_DIALOG // PS2 style save dialog with transparent black box
|
||||
// #define PS2_LIKE_MENU // An effort to recreate PS2 menu, cycling through tabs, different bg etc.
|
||||
#define MENU_MAP // VC-like menu map. Make sure you have new menu.txd
|
||||
#define SCROLLABLE_STATS_PAGE // only draggable by mouse atm
|
||||
#define TRIANGLE_BACK_BUTTON
|
||||
// #define CIRCLE_BACK_BUTTON
|
||||
|
||||
// Script
|
||||
#define USE_DEBUG_SCRIPT_LOADER // makes game load main_freeroam.scm by default
|
||||
|
|
|
@ -151,19 +151,6 @@ SpawnCar(int id)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
LetThemFollowYou(void) {
|
||||
CPed *player = (CPed*) FindPlayerPed();
|
||||
for (int i = 0; i < player->m_numNearPeds; i++) {
|
||||
CPed *nearPed = player->m_nearPeds[i];
|
||||
if (nearPed && !nearPed->IsPlayer()) {
|
||||
nearPed->SetObjective(OBJECTIVE_FOLLOW_PED_IN_FORMATION, (void*)player);
|
||||
nearPed->m_pedFormation = (eFormation)(1 + (rand() & 7));
|
||||
nearPed->bScriptObjectiveCompleted = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
FixCar(void)
|
||||
{
|
||||
|
@ -344,6 +331,7 @@ DebugMenuPopulate(void)
|
|||
DebugMenuAddCmd("Spawn", "Spawn Dodo", [](){ SpawnCar(MI_DODO); });
|
||||
DebugMenuAddCmd("Spawn", "Spawn Rhino", [](){ SpawnCar(MI_RHINO); });
|
||||
DebugMenuAddCmd("Spawn", "Spawn Firetruck", [](){ SpawnCar(MI_FIRETRUCK); });
|
||||
DebugMenuAddCmd("Spawn", "Spawn Predator", [](){ SpawnCar(MI_PREDATOR); });
|
||||
|
||||
DebugMenuAddVarBool8("Debug", "Draw hud", (int8*)&CHud::m_Wants_To_Draw_Hud, nil);
|
||||
DebugMenuAddVarBool8("Debug", "Edit on", (int8*)&CSceneEdit::m_bEditOn, nil);
|
||||
|
@ -372,8 +360,6 @@ DebugMenuPopulate(void)
|
|||
DebugMenuAddVarBool8("Debug", "Don't render Peds", (int8*)&gbDontRenderPeds, nil);
|
||||
DebugMenuAddVarBool8("Debug", "Don't render Vehicles", (int8*)&gbDontRenderVehicles, nil);
|
||||
DebugMenuAddVarBool8("Debug", "Don't render Objects", (int8*)&gbDontRenderObjects, nil);
|
||||
|
||||
DebugMenuAddCmd("Debug", "Make peds follow you in formation", LetThemFollowYou);
|
||||
#ifdef TOGGLEABLE_BETA_FEATURES
|
||||
DebugMenuAddVarBool8("Debug", "Toggle banned particles", (int8*)&CParticle::bEnableBannedParticles, nil);
|
||||
DebugMenuAddVarBool8("Debug", "Toggle popping heads on headshot", (int8*)&CPed::bPopHeadsOnHeadshot, nil);
|
||||
|
|
|
@ -21,7 +21,7 @@ CPhysical::CPhysical(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
fForceMultiplier = 1.0f;
|
||||
m_fForceMultiplier = 1.0f;
|
||||
m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
|
||||
m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
|
||||
m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f);
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
CVector m_vecTurnSpeedAvg;
|
||||
float m_fMass;
|
||||
float m_fTurnMass; // moment of inertia
|
||||
float fForceMultiplier;
|
||||
float m_fForceMultiplier;
|
||||
float m_fAirResistance;
|
||||
float m_fElasticity;
|
||||
float m_fBuoyancy;
|
||||
|
|
|
@ -83,7 +83,7 @@ public:
|
|||
return x == right.x && y == right.y && z == right.z;
|
||||
}
|
||||
|
||||
bool IsZero(void) { return x == 0.0f && y == 0.0f && z == 0.0f; }
|
||||
bool IsZero(void) const { return x == 0.0f && y == 0.0f && z == 0.0f; }
|
||||
};
|
||||
|
||||
inline CVector operator+(const CVector &left, const CVector &right)
|
||||
|
|
|
@ -234,12 +234,6 @@ CModelInfo::RemoveColModelsFromOtherLevels(eLevelName level)
|
|||
}
|
||||
}
|
||||
|
||||
CStore<CInstance, MLOINSTANCESIZE>&
|
||||
CModelInfo::GetMloInstanceStore()
|
||||
{
|
||||
return CModelInfo::ms_mloInstanceStore;
|
||||
}
|
||||
|
||||
void
|
||||
CModelInfo::ConstructMloClumps()
|
||||
{
|
||||
|
@ -247,6 +241,17 @@ CModelInfo::ConstructMloClumps()
|
|||
ms_mloModelStore.store[i].ConstructClump();
|
||||
}
|
||||
|
||||
void
|
||||
CModelInfo::ReInit2dEffects()
|
||||
{
|
||||
ms_2dEffectStore.clear();
|
||||
|
||||
for (int i = 0; i < MODELINFOSIZE; i++) {
|
||||
if (ms_modelInfoPtrs[i])
|
||||
ms_modelInfoPtrs[i]->Init2dEffects();
|
||||
}
|
||||
}
|
||||
|
||||
STARTPATCHES
|
||||
InjectHook(0x50B310, CModelInfo::Initialise, PATCH_JUMP);
|
||||
InjectHook(0x50B5B0, CModelInfo::ShutDown, PATCH_JUMP);
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
static CVehicleModelInfo *AddVehicleModel(int id);
|
||||
|
||||
static CStore<C2dEffect, TWODFXSIZE> &Get2dEffectStore(void) { return ms_2dEffectStore; }
|
||||
static CStore<CInstance, MLOINSTANCESIZE> &GetMloInstanceStore();
|
||||
static CStore<CInstance, MLOINSTANCESIZE> &GetMloInstanceStore(void) { return ms_mloInstanceStore; }
|
||||
|
||||
static CBaseModelInfo *GetModelInfo(const char *name, int *id);
|
||||
static CBaseModelInfo *GetModelInfo(int id){
|
||||
|
@ -47,4 +47,5 @@ public:
|
|||
static bool IsBikeModel(int32 id);
|
||||
static void RemoveColModelsFromOtherLevels(eLevelName level);
|
||||
static void ConstructMloClumps();
|
||||
static void ReInit2dEffects();
|
||||
};
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "World.h"
|
||||
#include "Vehicle.h"
|
||||
#include "Automobile.h"
|
||||
#include "Boat.h"
|
||||
#include "Train.h"
|
||||
#include "Plane.h"
|
||||
#include "Heli.h"
|
||||
|
@ -80,9 +81,9 @@ RwObjectNameIdAssocation carIds[] = {
|
|||
};
|
||||
|
||||
RwObjectNameIdAssocation boatIds[] = {
|
||||
{ "boat_moving_hi", 1, VEHICLE_FLAG_COLLAPSE },
|
||||
{ "boat_rudder_hi", 3, VEHICLE_FLAG_COLLAPSE },
|
||||
{ "windscreen", 2, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_COLLAPSE },
|
||||
{ "boat_moving_hi", BOAT_MOVING, VEHICLE_FLAG_COLLAPSE },
|
||||
{ "boat_rudder_hi", BOAT_RUDDER, VEHICLE_FLAG_COLLAPSE },
|
||||
{ "windscreen", BOAT_WINDSCREEN, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_COLLAPSE },
|
||||
{ "ped_frontseat", BOAT_POS_FRONTSEAT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
|
||||
{ nil, 0, 0 }
|
||||
};
|
||||
|
|
|
@ -2733,7 +2733,6 @@ CPed::SetObjective(eObjective newObj, void *entity)
|
|||
}
|
||||
|
||||
#ifdef VC_PED_PORTS
|
||||
SetObjectiveTimer(0);
|
||||
ClearPointGunAt();
|
||||
#endif
|
||||
bObjectiveCompleted = false;
|
||||
|
|
|
@ -29,7 +29,7 @@ class CRenderer
|
|||
static CVehicle *&m_pFirstPersonVehicle;
|
||||
|
||||
public:
|
||||
static float &ms_lodDistScale; // defined in Frontend.cpp
|
||||
static float ms_lodDistScale; // defined in Frontend.cpp
|
||||
static bool &m_loadingPriority;
|
||||
|
||||
static void Init(void);
|
||||
|
|
|
@ -9,17 +9,20 @@
|
|||
#include "Clock.h"
|
||||
#include "Date.h"
|
||||
#include "FileMgr.h"
|
||||
#include "Frontend.h"
|
||||
#include "GameLogic.h"
|
||||
#include "Gangs.h"
|
||||
#include "Garages.h"
|
||||
#include "GenericGameStorage.h"
|
||||
#include "Pad.h"
|
||||
#include "Particle.h"
|
||||
#include "ParticleObject.h"
|
||||
#include "PathFind.h"
|
||||
#include "PCSave.h"
|
||||
#include "Phones.h"
|
||||
#include "Pickups.h"
|
||||
#include "PlayerPed.h"
|
||||
#include "ProjectileInfo.h"
|
||||
#include "Pools.h"
|
||||
#include "Radar.h"
|
||||
#include "Restart.h"
|
||||
|
@ -48,7 +51,6 @@ char SaveFileNameJustSaved[260];
|
|||
int (&Slots)[SLOT_COUNT+1] = *(int(*)[SLOT_COUNT+1])*(uintptr*)0x72803C;
|
||||
CDate &CompileDateAndTime = *(CDate*)0x72BCB8;
|
||||
|
||||
|
||||
bool &b_FoundRecentSavedGameWantToLoad = *(bool*)0x95CDA8;
|
||||
bool &JustLoadedDontFadeInYet = *(bool*)0x95CDB4;
|
||||
bool &StillToFadeOut = *(bool*)0x95CD99;
|
||||
|
@ -58,10 +60,26 @@ uint32 &TimeToStayFadedBeforeFadeOut = *(uint32*)0x611564;
|
|||
#define ReadDataFromBufferPointer(buf, to) memcpy(&to, buf, sizeof(to)); buf += align4bytes(sizeof(to));
|
||||
#define WriteDataToBufferPointer(buf, from) memcpy(buf, &from, sizeof(from)); buf += align4bytes(sizeof(from));
|
||||
|
||||
WRAPPER bool GenericLoad() { EAXJMP(0x590A00); }
|
||||
#define LoadSaveDataBlock()\
|
||||
do {\
|
||||
if (!ReadDataFromFile(file, (uint8 *) &size, 4))\
|
||||
return false;\
|
||||
size = align4bytes(size);\
|
||||
if (!ReadDataFromFile(file, work_buff, size))\
|
||||
return false;\
|
||||
buf = work_buff;\
|
||||
} while (0)
|
||||
|
||||
#define ReadDataFromBlock(msg,load_func)\
|
||||
do {\
|
||||
debug(msg);\
|
||||
ReadDataFromBufferPointer(buf, size);\
|
||||
load_func(buf, size);\
|
||||
size = align4bytes(size);\
|
||||
buf += size;\
|
||||
} while (0)
|
||||
|
||||
#define WRITE_BLOCK(save_func)\
|
||||
#define WriteSaveDataBlock(save_func)\
|
||||
do {\
|
||||
buf = work_buff;\
|
||||
reserved = 0;\
|
||||
|
@ -117,11 +135,11 @@ GenericSave(int file)
|
|||
WriteDataToBufferPointer(buf, CClock::ms_nGameClockMinutes);
|
||||
currPad = CPad::GetPad(0);
|
||||
WriteDataToBufferPointer(buf, currPad->Mode);
|
||||
WriteDataToBufferPointer(buf, CTimer::GetTimeInMilliseconds());
|
||||
WriteDataToBufferPointer(buf, CTimer::GetTimeScale());
|
||||
WriteDataToBufferPointer(buf, CTimer::GetTimeStep());
|
||||
WriteDataToBufferPointer(buf, CTimer::GetTimeStepNonClipped());
|
||||
WriteDataToBufferPointer(buf, CTimer::GetFrameCounter());
|
||||
WriteDataToBufferPointer(buf, CTimer::m_snTimeInMilliseconds);
|
||||
WriteDataToBufferPointer(buf, CTimer::ms_fTimeScale);
|
||||
WriteDataToBufferPointer(buf, CTimer::ms_fTimeStep);
|
||||
WriteDataToBufferPointer(buf, CTimer::ms_fTimeStepNonClipped);
|
||||
WriteDataToBufferPointer(buf, CTimer::m_FrameCounter);
|
||||
WriteDataToBufferPointer(buf, CTimeStep::ms_fTimeStep);
|
||||
WriteDataToBufferPointer(buf, CTimeStep::ms_fFramesPerUpdate);
|
||||
WriteDataToBufferPointer(buf, CTimeStep::ms_fTimeScale);
|
||||
|
@ -138,7 +156,6 @@ GenericSave(int file)
|
|||
WriteDataToBufferPointer(buf, CWeather::WeatherTypeInList);
|
||||
WriteDataToBufferPointer(buf, TheCamera.CarZoomIndicator);
|
||||
WriteDataToBufferPointer(buf, TheCamera.PedZoomIndicator);
|
||||
|
||||
assert(buf - work_buff == SIZE_OF_SIMPLEVARS);
|
||||
|
||||
// Save scripts, block is nested within the same block as simple vars for some reason
|
||||
|
@ -153,25 +170,25 @@ GenericSave(int file)
|
|||
totalSize = buf - work_buff;
|
||||
|
||||
// Save the rest
|
||||
WRITE_BLOCK(CPools::SavePedPool);
|
||||
WRITE_BLOCK(CGarages::Save);
|
||||
WRITE_BLOCK(CPools::SaveVehiclePool);
|
||||
WRITE_BLOCK(CPools::SaveObjectPool);
|
||||
WRITE_BLOCK(ThePaths.Save);
|
||||
WRITE_BLOCK(CCranes::Save);
|
||||
WRITE_BLOCK(CPickups::Save);
|
||||
WRITE_BLOCK(gPhoneInfo.Save);
|
||||
WRITE_BLOCK(CRestart::SaveAllRestartPoints);
|
||||
WRITE_BLOCK(CRadar::SaveAllRadarBlips);
|
||||
WRITE_BLOCK(CTheZones::SaveAllZones);
|
||||
WRITE_BLOCK(CGangs::SaveAllGangData);
|
||||
WRITE_BLOCK(CTheCarGenerators::SaveAllCarGenerators);
|
||||
WRITE_BLOCK(CParticleObject::SaveParticle);
|
||||
WRITE_BLOCK(cAudioScriptObject::SaveAllAudioScriptObjects);
|
||||
WRITE_BLOCK(CWorld::Players[CWorld::PlayerInFocus].SavePlayerInfo);
|
||||
WRITE_BLOCK(CStats::SaveStats);
|
||||
WRITE_BLOCK(CStreaming::MemoryCardSave);
|
||||
WRITE_BLOCK(CPedType::Save);
|
||||
WriteSaveDataBlock(CPools::SavePedPool);
|
||||
WriteSaveDataBlock(CGarages::Save);
|
||||
WriteSaveDataBlock(CPools::SaveVehiclePool);
|
||||
WriteSaveDataBlock(CPools::SaveObjectPool);
|
||||
WriteSaveDataBlock(ThePaths.Save);
|
||||
WriteSaveDataBlock(CCranes::Save);
|
||||
WriteSaveDataBlock(CPickups::Save);
|
||||
WriteSaveDataBlock(gPhoneInfo.Save);
|
||||
WriteSaveDataBlock(CRestart::SaveAllRestartPoints);
|
||||
WriteSaveDataBlock(CRadar::SaveAllRadarBlips);
|
||||
WriteSaveDataBlock(CTheZones::SaveAllZones);
|
||||
WriteSaveDataBlock(CGangs::SaveAllGangData);
|
||||
WriteSaveDataBlock(CTheCarGenerators::SaveAllCarGenerators);
|
||||
WriteSaveDataBlock(CParticleObject::SaveParticle);
|
||||
WriteSaveDataBlock(cAudioScriptObject::SaveAllAudioScriptObjects);
|
||||
WriteSaveDataBlock(CWorld::Players[CWorld::PlayerInFocus].SavePlayerInfo);
|
||||
WriteSaveDataBlock(CStats::SaveStats);
|
||||
WriteSaveDataBlock(CStreaming::MemoryCardSave);
|
||||
WriteSaveDataBlock(CPedType::Save);
|
||||
|
||||
// Write padding
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
@ -198,6 +215,115 @@ GenericSave(int file)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GenericLoad()
|
||||
{
|
||||
uint8 *buf;
|
||||
int32 file;
|
||||
uint32 size;
|
||||
|
||||
int32 saveSize;
|
||||
CPad *currPad;
|
||||
|
||||
// Load SimpleVars and Scripts
|
||||
CheckSum = 0;
|
||||
CDate(CompileDateAndTime);
|
||||
CPad::ResetCheats();
|
||||
if (!ReadInSizeofSaveFileBuffer(file, size))
|
||||
return false;
|
||||
size = align4bytes(size);
|
||||
ReadDataFromFile(file, work_buff, size);
|
||||
buf = (work_buff + 0x40);
|
||||
ReadDataFromBufferPointer(buf, saveSize);
|
||||
ReadDataFromBufferPointer(buf, CGame::currLevel);
|
||||
ReadDataFromBufferPointer(buf, TheCamera.GetPosition().x);
|
||||
ReadDataFromBufferPointer(buf, TheCamera.GetPosition().y);
|
||||
ReadDataFromBufferPointer(buf, TheCamera.GetPosition().z);
|
||||
ReadDataFromBufferPointer(buf, CClock::ms_nMillisecondsPerGameMinute);
|
||||
ReadDataFromBufferPointer(buf, CClock::ms_nLastClockTick);
|
||||
ReadDataFromBufferPointer(buf, CClock::ms_nGameClockHours);
|
||||
ReadDataFromBufferPointer(buf, CClock::ms_nGameClockMinutes);
|
||||
currPad = CPad::GetPad(0);
|
||||
ReadDataFromBufferPointer(buf, currPad->Mode);
|
||||
ReadDataFromBufferPointer(buf, CTimer::m_snTimeInMilliseconds);
|
||||
ReadDataFromBufferPointer(buf, CTimer::ms_fTimeScale);
|
||||
ReadDataFromBufferPointer(buf, CTimer::ms_fTimeStep);
|
||||
ReadDataFromBufferPointer(buf, CTimer::ms_fTimeStepNonClipped);
|
||||
ReadDataFromBufferPointer(buf, CTimer::m_FrameCounter);
|
||||
ReadDataFromBufferPointer(buf, CTimeStep::ms_fTimeStep);
|
||||
ReadDataFromBufferPointer(buf, CTimeStep::ms_fFramesPerUpdate);
|
||||
ReadDataFromBufferPointer(buf, CTimeStep::ms_fTimeScale);
|
||||
ReadDataFromBufferPointer(buf, CWeather::OldWeatherType);
|
||||
ReadDataFromBufferPointer(buf, CWeather::NewWeatherType);
|
||||
ReadDataFromBufferPointer(buf, CWeather::ForcedWeatherType);
|
||||
ReadDataFromBufferPointer(buf, CWeather::InterpolationValue);
|
||||
ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nSecond);
|
||||
ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nMinute);
|
||||
ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nHour);
|
||||
ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nDay);
|
||||
ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nMonth);
|
||||
ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nYear);
|
||||
ReadDataFromBufferPointer(buf, CWeather::WeatherTypeInList);
|
||||
ReadDataFromBufferPointer(buf, TheCamera.CarZoomIndicator);
|
||||
ReadDataFromBufferPointer(buf, TheCamera.PedZoomIndicator);
|
||||
assert(buf - work_buff == SIZE_OF_SIMPLEVARS);
|
||||
ReadDataFromBlock("Loading Scripts \n", CTheScripts::LoadAllScripts);
|
||||
|
||||
// Load the rest
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading PedPool \n", CPools::LoadPedPool);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading Garages \n", CGarages::Load);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading Vehicles \n", CPools::LoadVehiclePool);
|
||||
LoadSaveDataBlock();
|
||||
CProjectileInfo::RemoveAllProjectiles();
|
||||
CObject::DeleteAllTempObjects();
|
||||
ReadDataFromBlock("Loading Objects \n", CPools::LoadObjectPool);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading Paths \n", ThePaths.Load);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading Cranes \n", CranesLoad);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading Pickups \n", CPickups::Load);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading Phoneinfo \n", gPhoneInfo.Load);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading Restart \n", CRestart::LoadAllRestartPoints);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading Radar Blips \n", CRadar::LoadAllRadarBlips);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading Zones \n", CTheZones::LoadAllZones);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading Gang Data \n", CGangs::LoadAllGangData);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading Car Generators \n", CTheCarGenerators::LoadAllCarGenerators);
|
||||
CParticle::ReloadConfig();
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading Particles \n", CParticleObject::LoadParticle);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading AudioScript Objects \n", cAudioScriptObject::LoadAllAudioScriptObjects);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading Player Info \n", CWorld::Players[CWorld::PlayerInFocus].LoadPlayerInfo);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading Stats \n", CStats::LoadStats);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading Streaming Stuff \n", CStreaming::MemoryCardLoad);
|
||||
LoadSaveDataBlock();
|
||||
ReadDataFromBlock("Loading PedType Stuff \n", CPedType::Load);
|
||||
|
||||
DMAudio.SetMusicMasterVolume(CMenuManager::m_PrefsMusicVolume);
|
||||
DMAudio.SetEffectsMasterVolume(CMenuManager::m_PrefsSfxVolume);
|
||||
if (!CloseFile(file)) {
|
||||
PcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_CLOSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
DoGameSpecificStuffAfterSucessLoad();
|
||||
debug("Game successfully loaded \n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ReadInSizeofSaveFileBuffer(int32 &file, uint32 &size)
|
||||
{
|
||||
|
@ -411,7 +537,7 @@ align4bytes(int32 size)
|
|||
|
||||
STARTPATCHES
|
||||
InjectHook(0x58F8D0, GenericSave, PATCH_JUMP);
|
||||
//InjectHook(0x590A00, GenericLoad, PATCH_JUMP);
|
||||
InjectHook(0x590A00, GenericLoad, PATCH_JUMP);
|
||||
InjectHook(0x591910, ReadInSizeofSaveFileBuffer, PATCH_JUMP);
|
||||
InjectHook(0x591990, ReadDataFromFile, PATCH_JUMP);
|
||||
InjectHook(0x591A00, CloseFile, PATCH_JUMP);
|
||||
|
|
|
@ -667,7 +667,7 @@ CAutomobile::ProcessControl(void)
|
|||
if(!strongGrip1 && !CVehicle::bCheat3)
|
||||
gripCheat = false;
|
||||
float acceleration = pHandling->Transmission.CalculateDriveAcceleration(m_fGasPedal, m_nCurrentGear, m_fChangeGearTime, fwdSpeed, gripCheat);
|
||||
acceleration /= fForceMultiplier;
|
||||
acceleration /= m_fForceMultiplier;
|
||||
|
||||
// unused
|
||||
if(GetModelIndex() == MI_MIAMI_RCBARON ||
|
||||
|
@ -718,7 +718,7 @@ CAutomobile::ProcessControl(void)
|
|||
else
|
||||
traction = 0.004f;
|
||||
traction *= pHandling->fTractionMultiplier / 4.0f;
|
||||
traction /= fForceMultiplier;
|
||||
traction /= m_fForceMultiplier;
|
||||
if(CVehicle::bCheat3)
|
||||
traction *= 4.0f;
|
||||
|
||||
|
@ -3791,7 +3791,7 @@ CAutomobile::BlowUpCar(CEntity *culprit)
|
|||
}
|
||||
ChangeLawEnforcerState(false);
|
||||
|
||||
gFireManager.StartFire(this, culprit, 0.8f, 1); // TODO
|
||||
gFireManager.StartFire(this, culprit, 0.8f, true);
|
||||
CDarkel::RegisterCarBlownUpByPlayer(this);
|
||||
if(GetModelIndex() == MI_RCBANDIT)
|
||||
CExplosion::AddExplosion(this, culprit, EXPLOSION_CAR_QUICK, GetPosition(), 0);
|
||||
|
@ -4054,7 +4054,7 @@ CAutomobile::HasCarStoppedBecauseOfLight(void)
|
|||
if(ThePaths.m_connections[curnode->firstLink + i] == AutoPilot.m_nNextRouteNode)
|
||||
break;
|
||||
if(i < curnode->numLinks &&
|
||||
ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[curnode->firstLink + i]].trafficLightType & 3) // TODO
|
||||
ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[curnode->firstLink + i]].trafficLightType & 3)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -4064,7 +4064,7 @@ CAutomobile::HasCarStoppedBecauseOfLight(void)
|
|||
if(ThePaths.m_connections[curnode->firstLink + i] == AutoPilot.m_nPrevRouteNode)
|
||||
break;
|
||||
if(i < curnode->numLinks &&
|
||||
ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[curnode->firstLink + i]].trafficLightType & 3) // TODO
|
||||
ThePaths.m_carPathLinks[ThePaths.m_carPathConnections[curnode->firstLink + i]].trafficLightType & 3)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,25 @@
|
|||
#include "common.h"
|
||||
#include "patcher.h"
|
||||
#include "Boat.h"
|
||||
#include "General.h"
|
||||
#include "Timecycle.h"
|
||||
#include "HandlingMgr.h"
|
||||
#include "CarCtrl.h"
|
||||
#include "RwHelper.h"
|
||||
#include "ModelIndices.h"
|
||||
#include "VisibilityPlugins.h"
|
||||
#include "DMAudio.h"
|
||||
#include "Camera.h"
|
||||
#include "Darkel.h"
|
||||
#include "Explosion.h"
|
||||
#include "Particle.h"
|
||||
#include "WaterLevel.h"
|
||||
#include "Pools.h"
|
||||
#include "Floater.h"
|
||||
#include "World.h"
|
||||
#include "Pools.h"
|
||||
#include "Pad.h"
|
||||
#include "Boat.h"
|
||||
|
||||
#define INVALID_ORIENTATION (-9999.99f)
|
||||
|
||||
float &fShapeLength = *(float*)0x600E78;
|
||||
float &fShapeTime = *(float*)0x600E7C;
|
||||
|
@ -19,10 +32,6 @@ float WAKE_LIFETIME = 400.0f;
|
|||
|
||||
CBoat * (&CBoat::apFrameWakeGeneratingBoats)[4] = *(CBoat * (*)[4])*(uintptr*)0x8620E0;
|
||||
|
||||
WRAPPER void CBoat::ProcessControl() { EAXJMP(0x53EF10); }
|
||||
WRAPPER void CBoat::ProcessControlInputs(uint8) { EAXJMP(0x53EC70); }
|
||||
WRAPPER void CBoat::BlowUpCar(CEntity* ent) { EAXJMP(0x541CB0); }
|
||||
|
||||
CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner)
|
||||
{
|
||||
CVehicleModelInfo *minfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(mi);
|
||||
|
@ -47,35 +56,31 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner)
|
|||
m_fGasPedal = 0.0f;
|
||||
m_fBrakePedal = 0.0f;
|
||||
|
||||
field_288 = 0.25f;
|
||||
field_28C = 0.35f;
|
||||
field_290 = 0.7f;
|
||||
field_294 = 0.998f;
|
||||
field_298 = 0.999f;
|
||||
field_29C = 0.85f;
|
||||
field_2A0 = 0.96f;
|
||||
field_2A4 = 0.96f;
|
||||
m_fPropellerZ = 0.25f;
|
||||
m_fPropellerY = 0.35f;
|
||||
m_waterMoveDrag = CVector(0.7f, 0.998f, 0.999f);
|
||||
m_waterTurnDrag = CVector(0.85f, 0.96f, 0.96f);
|
||||
_unk2 = false;
|
||||
|
||||
m_fTurnForceZ = 7.0f;
|
||||
field_2FC = 7.0f;
|
||||
m_vecMoveForce = CVector(0.0f, 0.0f, 0.0f);
|
||||
m_fVolumeUnderWater = 7.0f;
|
||||
m_fPrevVolumeUnderWater = 7.0f;
|
||||
m_vecBuoyancePoint = CVector(0.0f, 0.0f, 0.0f);
|
||||
|
||||
field_300 = 0;
|
||||
m_bBoatFlag1 = true;
|
||||
m_bBoatFlag2 = true;
|
||||
m_nDeltaVolumeUnderWater = 0;
|
||||
bBoatInWater = true;
|
||||
bPropellerInWater = true;
|
||||
|
||||
bIsInWater = true;
|
||||
|
||||
unk1 = 0.0f;
|
||||
m_bIsAnchored = true;
|
||||
field_2C4 = -9999.99f;
|
||||
m_fOrientation = INVALID_ORIENTATION;
|
||||
bTouchingWater = true;
|
||||
field_2CC = 0.0f;
|
||||
field_2D0 = 0;
|
||||
m_fDamage = 0.0f;
|
||||
m_pSetOnFireEntity = nil;
|
||||
m_nNumWakePoints = 0;
|
||||
|
||||
for (int16 i = 0; i < 32; i++)
|
||||
for (int16 i = 0; i < ARRAY_SIZE(m_afWakePointLifeTime); i++)
|
||||
m_afWakePointLifeTime[i] = 0.0f;
|
||||
|
||||
m_nAmmoInClip = 20;
|
||||
|
@ -94,6 +99,541 @@ CBoat::GetComponentWorldPosition(int32 component, CVector &pos)
|
|||
pos = *RwMatrixGetPos(RwFrameGetLTM(m_aBoatNodes[component]));
|
||||
}
|
||||
|
||||
void
|
||||
CBoat::ProcessControl(void)
|
||||
{
|
||||
if(m_nZoneLevel > LEVEL_NONE && m_nZoneLevel != CCollision::ms_collisionInMemory)
|
||||
return;
|
||||
|
||||
bool onLand = m_fDamageImpulse > 0.0f && m_vecDamageNormal.z > 0.1f;
|
||||
|
||||
PruneWakeTrail();
|
||||
|
||||
int r, g, b;
|
||||
RwRGBA splashColor, jetColor;
|
||||
r = 114.75f*(CTimeCycle::GetAmbientRed() + 0.5f*CTimeCycle::GetDirectionalRed());
|
||||
g = 114.75f*(CTimeCycle::GetAmbientGreen() + 0.5f*CTimeCycle::GetDirectionalGreen());
|
||||
b = 114.75f*(CTimeCycle::GetAmbientBlue() + 0.5f*CTimeCycle::GetDirectionalBlue());
|
||||
r = clamp(r, 0, 255);
|
||||
g = clamp(g, 0, 255);
|
||||
b = clamp(b, 0, 255);
|
||||
splashColor.red = r;
|
||||
splashColor.green = g;
|
||||
splashColor.blue = b;
|
||||
splashColor.alpha = CGeneral::GetRandomNumberInRange(128, 150);
|
||||
|
||||
r = 242.25f*(CTimeCycle::GetAmbientRed() + 0.5f*CTimeCycle::GetDirectionalRed());
|
||||
g = 242.25f*(CTimeCycle::GetAmbientGreen() + 0.5f*CTimeCycle::GetDirectionalGreen());
|
||||
b = 242.25f*(CTimeCycle::GetAmbientBlue() + 0.5f*CTimeCycle::GetDirectionalBlue());
|
||||
r = clamp(r, 0, 255);
|
||||
g = clamp(g, 0, 255);
|
||||
b = clamp(b, 0, 255);
|
||||
jetColor.red = r;
|
||||
jetColor.green = g;
|
||||
jetColor.blue = b;
|
||||
jetColor.alpha = CGeneral::GetRandomNumberInRange(96, 128);
|
||||
|
||||
CGeneral::GetRandomNumber(); // unused
|
||||
|
||||
ProcessCarAlarm();
|
||||
|
||||
switch(m_status){
|
||||
case STATUS_PLAYER:
|
||||
m_bIsAnchored = false;
|
||||
m_fOrientation = INVALID_ORIENTATION;
|
||||
ProcessControlInputs(0);
|
||||
if(GetModelIndex() == MI_PREDATOR)
|
||||
DoFixedMachineGuns();
|
||||
break;
|
||||
case STATUS_SIMPLE:
|
||||
m_bIsAnchored = false;
|
||||
m_fOrientation = INVALID_ORIENTATION;
|
||||
CPhysical::ProcessControl();
|
||||
bBoatInWater = true;
|
||||
bPropellerInWater = true;
|
||||
bIsInWater = true;
|
||||
return;
|
||||
case STATUS_PHYSICS:
|
||||
m_bIsAnchored = false;
|
||||
m_fOrientation = INVALID_ORIENTATION;
|
||||
CCarCtrl::SteerAIBoatWithPhysics(this);
|
||||
break;
|
||||
case STATUS_ABANDONED:
|
||||
case STATUS_WRECKED:
|
||||
bBoatInWater = true;
|
||||
bPropellerInWater = true;
|
||||
bIsInWater = true;
|
||||
m_fSteerAngle = 0.0;
|
||||
bIsHandbrakeOn = false;
|
||||
m_fBrakePedal = 0.5f;
|
||||
m_fGasPedal = 0.0f;
|
||||
if((GetPosition() - CWorld::Players[CWorld::PlayerInFocus].GetPos()).Magnitude() > 150.0f){
|
||||
m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
|
||||
m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
float collisionDamage = pHandling->fCollisionDamageMultiplier * m_fDamageImpulse;
|
||||
if(collisionDamage > 25.0f && m_status != STATUS_WRECKED && m_fHealth >= 150.0f){
|
||||
float prevHealth = m_fHealth;
|
||||
if(this == FindPlayerVehicle()){
|
||||
if(bTakeLessDamage)
|
||||
m_fHealth -= (collisionDamage-25.0f)/6.0f;
|
||||
else
|
||||
m_fHealth -= (collisionDamage-25.0f)/2.0f;
|
||||
}else{
|
||||
if(collisionDamage > 60.0f && pDriver)
|
||||
pDriver->Say(SOUND_PED_CAR_COLLISION);
|
||||
if(bTakeLessDamage)
|
||||
m_fHealth -= (collisionDamage-25.0f)/12.0f;
|
||||
else
|
||||
m_fHealth -= (collisionDamage-25.0f)/4.0f;
|
||||
}
|
||||
|
||||
if(m_fHealth <= 0.0f && prevHealth > 0.0f){
|
||||
m_fHealth = 1.0f;
|
||||
m_pSetOnFireEntity = m_pDamageEntity;
|
||||
}
|
||||
}
|
||||
|
||||
// Damage particles
|
||||
if(m_fHealth <= 600.0f && m_status != STATUS_WRECKED &&
|
||||
Abs(GetPosition().x - TheCamera.GetPosition().x) < 200.0f &&
|
||||
Abs(GetPosition().y - TheCamera.GetPosition().y) < 200.0f){
|
||||
float speedSq = m_vecMoveSpeed.MagnitudeSqr();
|
||||
CVector smokeDir = 0.8f*m_vecMoveSpeed;
|
||||
CVector smokePos;
|
||||
switch(GetModelIndex()){
|
||||
case MI_SPEEDER:
|
||||
smokePos = CVector(0.4f, -2.4f, 0.8f);
|
||||
smokeDir += 0.05f*GetRight();
|
||||
smokeDir.z += 0.2f*m_vecMoveSpeed.z;
|
||||
break;
|
||||
case MI_REEFER:
|
||||
smokePos = CVector(2.0f, -1.0f, 0.5f);
|
||||
smokeDir += 0.07f*GetRight();
|
||||
break;
|
||||
case MI_PREDATOR:
|
||||
default:
|
||||
smokePos = CVector(-1.5f, -0.5f, 1.2f);
|
||||
smokeDir += -0.08f*GetRight();
|
||||
break;
|
||||
}
|
||||
|
||||
smokePos = GetMatrix() * smokePos;
|
||||
|
||||
// On fire
|
||||
if(m_fHealth < 150.0f){
|
||||
CParticle::AddParticle(PARTICLE_CARFLAME, smokePos,
|
||||
CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(2.25f/200.0f, 0.09f)),
|
||||
nil, 0.9f);
|
||||
CVector smokePos2 = smokePos;
|
||||
smokePos2.x += CGeneral::GetRandomNumberInRange(-2.25f/4.0f, 2.25f/4.0f);
|
||||
smokePos2.y += CGeneral::GetRandomNumberInRange(-2.25f/4.0f, 2.25f/4.0f);
|
||||
smokePos2.z += CGeneral::GetRandomNumberInRange(2.25f/4.0f, 2.25f);
|
||||
CParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, smokePos2, CVector(0.0f, 0.0f, 0.0f));
|
||||
|
||||
m_fDamage += CTimer::GetTimeStepInMilliseconds();
|
||||
if(m_fDamage > 5000.0f)
|
||||
BlowUpCar(m_pSetOnFireEntity);
|
||||
}
|
||||
|
||||
if(speedSq < 0.25f && (CTimer::GetFrameCounter() + m_randomSeed) & 1)
|
||||
CParticle::AddParticle(PARTICLE_ENGINE_STEAM, smokePos, smokeDir);
|
||||
if(speedSq < 0.25f && m_fHealth <= 350.0f)
|
||||
CParticle::AddParticle(PARTICLE_ENGINE_SMOKE, smokePos, 1.25f*smokeDir);
|
||||
}
|
||||
|
||||
CPhysical::ProcessControl();
|
||||
|
||||
CVector buoyanceImpulse(0.0f, 0.0f, 0.0f);
|
||||
CVector buoyancePoint(0.0f, 0.0f, 0.0f);
|
||||
if(mod_Buoyancy.ProcessBuoyancy(this, pHandling->fBuoyancy, &buoyancePoint, &buoyanceImpulse)){
|
||||
// Process boat in water
|
||||
if(0.1f * m_fMass * GRAVITY*CTimer::GetTimeStep() < buoyanceImpulse.z){
|
||||
bBoatInWater = true;
|
||||
bIsInWater = true;
|
||||
}else{
|
||||
bBoatInWater = false;
|
||||
bIsInWater = false;
|
||||
}
|
||||
|
||||
m_fVolumeUnderWater = mod_Buoyancy.m_volumeUnderWater;
|
||||
m_vecBuoyancePoint = buoyancePoint;
|
||||
ApplyMoveForce(buoyanceImpulse);
|
||||
if(!onLand)
|
||||
ApplyTurnForce(buoyanceImpulse, buoyancePoint);
|
||||
|
||||
if(!onLand && bBoatInWater && GetUp().z > 0.0f){
|
||||
float impulse;
|
||||
if(m_fGasPedal > 0.05f)
|
||||
impulse = m_vecMoveSpeed.MagnitudeSqr()*pHandling->fSuspensionForceLevel*buoyanceImpulse.z*CTimer::GetTimeStep()*0.5f*m_fGasPedal;
|
||||
else
|
||||
impulse = 0.0f;
|
||||
impulse = min(impulse, GRAVITY*pHandling->fSuspensionDampingLevel*m_fMass*CTimer::GetTimeStep());
|
||||
ApplyMoveForce(impulse*GetUp());
|
||||
ApplyTurnForce(impulse*GetUp(), buoyancePoint - pHandling->fSuspensionBias*GetForward());
|
||||
}
|
||||
|
||||
// Handle boat moving forward
|
||||
if(Abs(m_fGasPedal) > 0.05f || m_vecMoveSpeed.Magnitude() > 0.01f){
|
||||
if(bBoatInWater)
|
||||
AddWakePoint(GetPosition());
|
||||
|
||||
float steerFactor = 1.0f - DotProduct(m_vecMoveSpeed, GetForward());
|
||||
if(m_modelIndex == MI_GHOST)
|
||||
steerFactor = 1.0f - DotProduct(m_vecMoveSpeed, GetForward())*0.3f;
|
||||
if(steerFactor < 0.0f) steerFactor = 0.0f;
|
||||
|
||||
CVector propeller(0.0f, -pHandling->Dimension.y*m_fPropellerY, -pHandling->Dimension.z*m_fPropellerZ);
|
||||
propeller = Multiply3x3(GetMatrix(), propeller);
|
||||
CVector propellerWorld = GetPosition() + propeller;
|
||||
|
||||
float steerSin = Sin(-m_fSteerAngle * steerFactor);
|
||||
float steerCos = Cos(-m_fSteerAngle * steerFactor);
|
||||
float waterLevel;
|
||||
CWaterLevel::GetWaterLevel(propellerWorld, &waterLevel, true);
|
||||
if(propellerWorld.z-0.5f < waterLevel){
|
||||
float propellerDepth = waterLevel - (propellerWorld.z - 0.5f);
|
||||
if(propellerDepth > 1.0f)
|
||||
propellerDepth = 1.0f;
|
||||
else
|
||||
propellerDepth = SQR(propellerDepth);
|
||||
bPropellerInWater = true;
|
||||
|
||||
if(Abs(m_fGasPedal) > 0.05f){
|
||||
CVector forceDir = Multiply3x3(GetMatrix(), CVector(-steerSin, steerCos, -Abs(m_fSteerAngle)));
|
||||
CVector force = propellerDepth * m_fGasPedal * 40.0f * pHandling->Transmission.fEngineAcceleration * pHandling->fMass * forceDir;
|
||||
if(force.z > 0.2f)
|
||||
force.z = SQR(1.2f - force.z) + 0.2f;
|
||||
if(onLand){
|
||||
if(m_fGasPedal < 0.0f){
|
||||
force.x *= 5.0f;
|
||||
force.y *= 5.0f;
|
||||
}
|
||||
if(force.z < 0.0f)
|
||||
force.z = 0.0f;
|
||||
ApplyMoveForce(force * CTimer::GetTimeStep());
|
||||
}else{
|
||||
ApplyMoveForce(force * CTimer::GetTimeStep());
|
||||
ApplyTurnForce(force * CTimer::GetTimeStep(), propeller - pHandling->fTractionBias*GetUp());
|
||||
float rightForce = DotProduct(GetRight(), force);
|
||||
ApplyTurnForce(-rightForce*GetRight() * CTimer::GetTimeStep(), GetUp());
|
||||
}
|
||||
|
||||
// Spray some particles
|
||||
CVector jetDir = -0.04f * force;
|
||||
if(m_fGasPedal > 0.0f){
|
||||
if(m_status == STATUS_PLAYER){
|
||||
bool cameraHack = TheCamera.Cams[TheCamera.ActiveCam].Mode == CCam::MODE_TOPDOWN ||
|
||||
TheCamera.WhoIsInControlOfTheCamera == CAMCONTROL_OBBE;
|
||||
CVector sternPos = GetColModel()->boundingBox.min;
|
||||
sternPos.x = 0.0f;
|
||||
sternPos.z = 0.0f;
|
||||
sternPos = Multiply3x3(GetMatrix(), sternPos);
|
||||
|
||||
CVector jetPos = GetPosition() + sternPos;
|
||||
if(cameraHack)
|
||||
jetPos.z = 1.0f;
|
||||
else
|
||||
jetPos.z = 0.0f;
|
||||
|
||||
CVector wakePos = GetPosition() + sternPos;
|
||||
wakePos.z -= 0.65f;
|
||||
|
||||
CVector wakeDir = 0.75f * jetDir;
|
||||
|
||||
CParticle::AddParticle(PARTICLE_BOAT_THRUSTJET, jetPos, jetDir, nil, 0.0f, jetColor);
|
||||
CParticle::AddParticle(PARTICLE_CAR_SPLASH, jetPos, 0.25f * jetDir, nil, 1.0f, splashColor,
|
||||
CGeneral::GetRandomNumberInRange(0, 30),
|
||||
CGeneral::GetRandomNumberInRange(0, 90), 3);
|
||||
if(!cameraHack)
|
||||
CParticle::AddParticle(PARTICLE_BOAT_WAKE, wakePos, wakeDir, nil, 0.0f, jetColor);
|
||||
}else if((CTimer::GetFrameCounter() + m_randomSeed) & 1){
|
||||
jetDir.z = 0.018f;
|
||||
jetDir.x *= 0.01f;
|
||||
jetDir.y *= 0.01f;
|
||||
propellerWorld.z += 1.5f;
|
||||
|
||||
CParticle::AddParticle(PARTICLE_BOAT_SPLASH, propellerWorld, jetDir, nil, 1.5f, jetColor);
|
||||
CParticle::AddParticle(PARTICLE_CAR_SPLASH, propellerWorld, 0.1f * jetDir, nil, 0.5f, splashColor,
|
||||
CGeneral::GetRandomNumberInRange(0, 30),
|
||||
CGeneral::GetRandomNumberInRange(0, 90), 3);
|
||||
}
|
||||
}
|
||||
}else if(!onLand){
|
||||
float force = 50.0f*DotProduct(m_vecMoveSpeed, GetForward());
|
||||
if(force > 10.0f) force = 10.0f;
|
||||
CVector propellerForce = propellerDepth * Multiply3x3(GetMatrix(), force*CVector(-steerSin, 0.0f, 0.0f));
|
||||
ApplyMoveForce(propellerForce * CTimer::GetTimeStep()*0.5f);
|
||||
ApplyTurnForce(propellerForce * CTimer::GetTimeStep()*0.5f, propeller);
|
||||
}
|
||||
}else
|
||||
bPropellerInWater = false;
|
||||
}
|
||||
|
||||
// Slow down or push down boat as it approaches the world limits
|
||||
m_vecMoveSpeed.x = min(m_vecMoveSpeed.x, -(GetPosition().x - 1900.0f)*0.01f); // east
|
||||
m_vecMoveSpeed.x = max(m_vecMoveSpeed.x, -(GetPosition().x - -1515.0f)*0.01f); // west
|
||||
m_vecMoveSpeed.y = min(m_vecMoveSpeed.y, -(GetPosition().y - 600.0f)*0.01f); // north
|
||||
m_vecMoveSpeed.y = max(m_vecMoveSpeed.y, -(GetPosition().y - -1900.0f)*0.01f); // south
|
||||
|
||||
if(!onLand && bBoatInWater)
|
||||
ApplyWaterResistance();
|
||||
|
||||
// No idea what exactly is going on here besides drag in YZ
|
||||
float fx = Pow(m_waterTurnDrag.x, CTimer::GetTimeStep());
|
||||
float fy = Pow(m_waterTurnDrag.y, CTimer::GetTimeStep());
|
||||
float fz = Pow(m_waterTurnDrag.z, CTimer::GetTimeStep());
|
||||
m_vecTurnSpeed = Multiply3x3(m_vecTurnSpeed, GetMatrix()); // invert - to local space
|
||||
// TODO: figure this out
|
||||
float magic = 1.0f/(1000.0f * SQR(m_vecTurnSpeed.x) + 1.0f) * fx;
|
||||
m_vecTurnSpeed.y *= fy;
|
||||
m_vecTurnSpeed.z *= fz;
|
||||
float forceUp = (magic - 1.0f) * m_vecTurnSpeed.x * m_fTurnMass;
|
||||
m_vecTurnSpeed = Multiply3x3(GetMatrix(), m_vecTurnSpeed); // back to world
|
||||
CVector com = Multiply3x3(GetMatrix(), m_vecCentreOfMass);
|
||||
ApplyTurnForce(CVector(0.0f, 0.0f, forceUp), com + GetForward());
|
||||
|
||||
m_nDeltaVolumeUnderWater = (m_fVolumeUnderWater-m_fPrevVolumeUnderWater)*10000;
|
||||
|
||||
// Falling into water
|
||||
if(!onLand && bBoatInWater && GetUp().z > 0.0f && m_nDeltaVolumeUnderWater > 200){
|
||||
DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_SPLASH, m_nDeltaVolumeUnderWater);
|
||||
|
||||
float speedUp = m_vecMoveSpeed.MagnitudeSqr() * m_nDeltaVolumeUnderWater * 0.0004f;
|
||||
if(speedUp + m_vecMoveSpeed.z > pHandling->fBrakeDeceleration)
|
||||
speedUp = pHandling->fBrakeDeceleration - m_vecMoveSpeed.z;
|
||||
if(speedUp < 0.0f) speedUp = 0.0f;
|
||||
float speedFwd = DotProduct(m_vecMoveSpeed, GetForward());
|
||||
speedFwd *= -m_nDeltaVolumeUnderWater * 0.01f * pHandling->fTractionLoss;
|
||||
CVector speed = speedFwd*GetForward() + CVector(0.0f, 0.0f, speedUp);
|
||||
CVector splashImpulse = speed * m_fMass;
|
||||
ApplyMoveForce(splashImpulse);
|
||||
ApplyTurnForce(splashImpulse, buoyancePoint);
|
||||
}
|
||||
|
||||
// Spray particles on sides of boat
|
||||
if(m_nDeltaVolumeUnderWater > 75){
|
||||
float speed = m_vecMoveSpeed.Magnitude();
|
||||
float splash1Size = speed;
|
||||
float splash2Size = m_nDeltaVolumeUnderWater * 0.005f * 0.2f;
|
||||
float front = 0.9f * GetColModel()->boundingBox.max.y;
|
||||
if(splash1Size > 0.75f) splash1Size = 0.75f;
|
||||
|
||||
CVector dir, pos;
|
||||
|
||||
// right
|
||||
dir = -0.5f*m_vecMoveSpeed;
|
||||
dir.z += 0.1f*speed;
|
||||
dir += 0.5f*GetRight()*speed;
|
||||
pos = front*GetForward() + 0.5f*GetRight() + GetPosition() + m_vecBuoyancePoint;
|
||||
CWaterLevel::GetWaterLevel(pos, &pos.z, true);
|
||||
CParticle::AddParticle(PARTICLE_CAR_SPLASH, pos, 0.75f * dir, nil, splash1Size, splashColor,
|
||||
CGeneral::GetRandomNumberInRange(0, 30),
|
||||
CGeneral::GetRandomNumberInRange(0, 90), 1);
|
||||
CParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, splash2Size, jetColor);
|
||||
|
||||
// left
|
||||
dir = -0.5f*m_vecMoveSpeed;
|
||||
dir.z += 0.1f*speed;
|
||||
dir -= 0.5f*GetRight()*speed;
|
||||
pos = front*GetForward() - 0.5f*GetRight() + GetPosition() + m_vecBuoyancePoint;
|
||||
CWaterLevel::GetWaterLevel(pos, &pos.z, true);
|
||||
CParticle::AddParticle(PARTICLE_CAR_SPLASH, pos, 0.75f * dir, nil, splash1Size, splashColor,
|
||||
CGeneral::GetRandomNumberInRange(0, 30),
|
||||
CGeneral::GetRandomNumberInRange(0, 90), 1);
|
||||
CParticle::AddParticle(PARTICLE_BOAT_SPLASH, pos, dir, nil, splash2Size, jetColor);
|
||||
}
|
||||
|
||||
m_fPrevVolumeUnderWater = m_fVolumeUnderWater;
|
||||
}else{
|
||||
bBoatInWater = false;
|
||||
bIsInWater = false;
|
||||
}
|
||||
|
||||
if(m_bIsAnchored){
|
||||
m_vecMoveSpeed.x = 0.0f;
|
||||
m_vecMoveSpeed.y = 0.0f;
|
||||
|
||||
if(m_fOrientation == INVALID_ORIENTATION){
|
||||
m_fOrientation = GetForward().Heading();
|
||||
}else{
|
||||
// is this some inlined CPlaceable method?
|
||||
CVector pos = GetPosition();
|
||||
GetMatrix().RotateZ(m_fOrientation - GetForward().Heading());
|
||||
GetPosition() = pos;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessDelayedExplosion();
|
||||
}
|
||||
|
||||
void
|
||||
CBoat::ProcessControlInputs(uint8 pad)
|
||||
{
|
||||
m_nPadID = pad;
|
||||
if(m_nPadID > 3)
|
||||
m_nPadID = 3;
|
||||
|
||||
m_fBrake += (CPad::GetPad(pad)->GetBrake()/255.0f - m_fBrake)*0.1f;
|
||||
m_fBrake = clamp(m_fBrake, 0.0f, 1.0f);
|
||||
|
||||
if(m_fBrake < 0.05f){
|
||||
m_fBrake = 0.0f;
|
||||
m_fAccelerate += (CPad::GetPad(pad)->GetAccelerate()/255.0f - m_fAccelerate)*0.1f;
|
||||
m_fAccelerate = clamp(m_fAccelerate, 0.0f, 1.0f);
|
||||
}else
|
||||
m_fAccelerate = -m_fBrake*0.2f;
|
||||
|
||||
m_fSteeringLeftRight += (-CPad::GetPad(pad)->GetSteeringLeftRight()/128.0f - m_fSteeringLeftRight)*0.2f;
|
||||
m_fSteeringLeftRight = clamp(m_fSteeringLeftRight, -1.0f, 1.0f);
|
||||
|
||||
float steeringSq = m_fSteeringLeftRight < 0.0f ? -SQR(m_fSteeringLeftRight) : SQR(m_fSteeringLeftRight);
|
||||
m_fSteerAngle = pHandling->fSteeringLock * DEGTORAD(steeringSq);
|
||||
m_fGasPedal = m_fAccelerate;
|
||||
}
|
||||
|
||||
void
|
||||
CBoat::ApplyWaterResistance(void)
|
||||
{
|
||||
float fwdSpeed = DotProduct(GetMoveSpeed(), GetForward());
|
||||
// TODO: figure out how this works
|
||||
float magic = (SQR(fwdSpeed) + 0.05f) * (0.001f * SQR(m_fVolumeUnderWater) * m_fMass) + 1.0f;
|
||||
magic = Abs(magic);
|
||||
// FRAMETIME
|
||||
float fx = Pow(m_waterMoveDrag.x/magic, 0.5f*CTimer::GetTimeStep());
|
||||
float fy = Pow(m_waterMoveDrag.y/magic, 0.5f*CTimer::GetTimeStep());
|
||||
float fz = Pow(m_waterMoveDrag.z/magic, 0.5f*CTimer::GetTimeStep());
|
||||
|
||||
m_vecMoveSpeed = Multiply3x3(m_vecMoveSpeed, GetMatrix()); // invert - to local space
|
||||
m_vecMoveSpeed.x *= fx;
|
||||
m_vecMoveSpeed.y *= fy;
|
||||
m_vecMoveSpeed.z *= fz;
|
||||
float force = (fy - 1.0f) * m_vecMoveSpeed.y * m_fMass;
|
||||
m_vecMoveSpeed = Multiply3x3(GetMatrix(), m_vecMoveSpeed); // back to world
|
||||
|
||||
ApplyTurnForce(force*GetForward(), -GetUp());
|
||||
|
||||
if(m_vecMoveSpeed.z > 0.0f)
|
||||
m_vecMoveSpeed.z *= fz;
|
||||
else
|
||||
m_vecMoveSpeed.z *= (1.0f - fz)*0.5f + fz;
|
||||
}
|
||||
|
||||
RwObject*
|
||||
GetBoatAtomicObjectCB(RwObject *object, void *data)
|
||||
{
|
||||
RpAtomic *atomic = (RpAtomic*)object;
|
||||
assert(RwObjectGetType(object) == rpATOMIC);
|
||||
if(RpAtomicGetFlags(atomic) & rpATOMICRENDER)
|
||||
*(RpAtomic**)data = atomic;
|
||||
return object;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
CBoat::BlowUpCar(CEntity *culprit)
|
||||
{
|
||||
RpAtomic *atomic;
|
||||
RwFrame *frame;
|
||||
RwMatrix *matrix;
|
||||
CObject *obj;
|
||||
|
||||
if(!bCanBeDamaged)
|
||||
return;
|
||||
|
||||
// explosion pushes vehicle up
|
||||
m_vecMoveSpeed.z += 0.13f;
|
||||
m_status = STATUS_WRECKED;
|
||||
bRenderScorched = true;
|
||||
|
||||
m_fHealth = 0.0;
|
||||
m_nBombTimer = 0;
|
||||
TheCamera.CamShake(0.7f, GetPosition().x, GetPosition().y, GetPosition().z);
|
||||
|
||||
if(this == FindPlayerVehicle())
|
||||
FindPlayerPed()->m_fHealth = 0.0f; // kill player
|
||||
if(pDriver){
|
||||
CDarkel::RegisterKillByPlayer(pDriver, WEAPONTYPE_EXPLOSION);
|
||||
pDriver->SetDead();
|
||||
pDriver->FlagToDestroyWhenNextProcessed();
|
||||
}
|
||||
|
||||
bEngineOn = false;
|
||||
bLightsOn = false;
|
||||
ChangeLawEnforcerState(false);
|
||||
|
||||
CExplosion::AddExplosion(this, culprit, EXPLOSION_CAR, GetPosition(), 0);
|
||||
if(m_aBoatNodes[BOAT_MOVING] == nil)
|
||||
return;
|
||||
|
||||
// much like CAutomobile::SpawnFlyingComponent from here on
|
||||
|
||||
atomic = nil;
|
||||
RwFrameForAllObjects(m_aBoatNodes[BOAT_MOVING], GetBoatAtomicObjectCB, &atomic);
|
||||
if(atomic == nil)
|
||||
return;
|
||||
|
||||
obj = new CObject();
|
||||
if(obj == nil)
|
||||
return;
|
||||
|
||||
obj->SetModelIndexNoCreate(MI_CAR_WHEEL);
|
||||
|
||||
// object needs base model
|
||||
obj->RefModelInfo(GetModelIndex());
|
||||
|
||||
// create new atomic
|
||||
matrix = RwFrameGetLTM(m_aBoatNodes[BOAT_MOVING]);
|
||||
frame = RwFrameCreate();
|
||||
atomic = RpAtomicClone(atomic);
|
||||
*RwFrameGetMatrix(frame) = *matrix;
|
||||
RpAtomicSetFrame(atomic, frame);
|
||||
CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil);
|
||||
obj->AttachToRwObject((RwObject*)atomic);
|
||||
|
||||
// init object
|
||||
obj->m_fMass = 10.0f;
|
||||
obj->m_fTurnMass = 25.0f;
|
||||
obj->m_fAirResistance = 0.99f;
|
||||
obj->m_fElasticity = 0.1f;
|
||||
obj->m_fBuoyancy = obj->m_fMass*GRAVITY/0.75f;
|
||||
obj->ObjectCreatedBy = TEMP_OBJECT;
|
||||
obj->bIsStatic = false;
|
||||
obj->bIsPickup = false;
|
||||
|
||||
// life time
|
||||
CObject::nNoTempObjects++;
|
||||
obj->m_nEndOfLifeTime = CTimer::GetTimeInMilliseconds() + 20000;
|
||||
|
||||
obj->m_vecMoveSpeed = m_vecMoveSpeed;
|
||||
if(GetUp().z > 0.0f)
|
||||
obj->m_vecMoveSpeed.z = 0.3f;
|
||||
else
|
||||
obj->m_vecMoveSpeed.z = 0.0f;
|
||||
|
||||
obj->m_vecTurnSpeed = m_vecTurnSpeed*2.0f;
|
||||
obj->m_vecTurnSpeed.x = 0.5f;
|
||||
|
||||
// push component away from boat
|
||||
CVector dist = obj->GetPosition() - GetPosition();
|
||||
dist.Normalise();
|
||||
if(GetUp().z > 0.0f)
|
||||
dist += GetUp();
|
||||
obj->GetPosition() += GetUp();
|
||||
|
||||
CWorld::Add(obj);
|
||||
|
||||
atomic = nil;
|
||||
RwFrameForAllObjects(m_aBoatNodes[BOAT_MOVING], GetBoatAtomicObjectCB, &atomic);
|
||||
if(atomic)
|
||||
RpAtomicSetFlags(atomic, 0);
|
||||
}
|
||||
|
||||
RwIm3DVertex KeepWaterOutVertices[4];
|
||||
RwImVertexIndex KeepWaterOutIndices[6];
|
||||
|
||||
|
@ -102,8 +642,8 @@ CBoat::Render()
|
|||
{
|
||||
CMatrix matrix;
|
||||
|
||||
if (m_aBoatNodes[1] != nil) {
|
||||
matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[1]));
|
||||
if (m_aBoatNodes[BOAT_MOVING] != nil) {
|
||||
matrix.Attach(RwFrameGetMatrix(m_aBoatNodes[BOAT_MOVING]));
|
||||
|
||||
CVector pos = matrix.GetPosition();
|
||||
matrix.SetRotateZ(m_fMovingHiRotation);
|
||||
|
@ -111,7 +651,7 @@ CBoat::Render()
|
|||
|
||||
matrix.UpdateRW();
|
||||
if (CVehicle::bWheelsOnlyCheat) {
|
||||
RpAtomicRender((RpAtomic*)GetFirstObject(m_aBoatNodes[1]));
|
||||
RpAtomicRender((RpAtomic*)GetFirstObject(m_aBoatNodes[BOAT_MOVING]));
|
||||
}
|
||||
}
|
||||
m_fMovingHiRotation += 0.05f;
|
||||
|
@ -234,10 +774,9 @@ CBoat::IsVertexAffectedByWake(CVector vecVertex, CBoat *pBoat)
|
|||
void
|
||||
CBoat::SetupModelNodes()
|
||||
{
|
||||
m_aBoatNodes[0] = nil;
|
||||
m_aBoatNodes[1] = nil;
|
||||
m_aBoatNodes[2] = nil;
|
||||
m_aBoatNodes[3] = nil;
|
||||
int i;
|
||||
for(i = 0; i < ARRAY_SIZE(m_aBoatNodes); i++)
|
||||
m_aBoatNodes[i] = nil;
|
||||
CClumpModelInfo::FillFrameArray(GetClump(), m_aBoatNodes);
|
||||
}
|
||||
|
||||
|
@ -275,6 +814,43 @@ CBoat::FillBoatList()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
CBoat::PruneWakeTrail(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(m_afWakePointLifeTime); i++){
|
||||
if(m_afWakePointLifeTime[i] <= 0.0f)
|
||||
break;
|
||||
if(m_afWakePointLifeTime[i] <= CTimer::GetTimeStep()){
|
||||
m_afWakePointLifeTime[i] = 0.0f;
|
||||
break;
|
||||
}
|
||||
m_afWakePointLifeTime[i] -= CTimer::GetTimeStep();
|
||||
}
|
||||
m_nNumWakePoints = i;
|
||||
}
|
||||
|
||||
void
|
||||
CBoat::AddWakePoint(CVector point)
|
||||
{
|
||||
int i;
|
||||
if(m_afWakePointLifeTime[0] > 0.0f){
|
||||
if((CVector2D(GetPosition()) - m_avec2dWakePoints[0]).MagnitudeSqr() < SQR(1.0f)){
|
||||
for(i = min(m_nNumWakePoints, ARRAY_SIZE(m_afWakePointLifeTime)-1); i != 0; i--){
|
||||
m_avec2dWakePoints[i] = m_avec2dWakePoints[i-1];
|
||||
m_afWakePointLifeTime[i] = m_afWakePointLifeTime[i-1];
|
||||
}
|
||||
m_avec2dWakePoints[0] = point;
|
||||
m_afWakePointLifeTime[0] = 400.0f;
|
||||
}
|
||||
}else{
|
||||
m_avec2dWakePoints[0] = point;
|
||||
m_afWakePointLifeTime[0] = 400.0f;
|
||||
m_nNumWakePoints = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#include <new>
|
||||
|
||||
class CBoat_ : public CBoat
|
||||
|
@ -291,4 +867,7 @@ STARTPATCHES
|
|||
InjectHook(0x542370, CBoat::IsSectorAffectedByWake, PATCH_JUMP);
|
||||
InjectHook(0x5424A0, CBoat::IsVertexAffectedByWake, PATCH_JUMP);
|
||||
InjectHook(0x542250, CBoat::FillBoatList, PATCH_JUMP);
|
||||
InjectHook(0x542140, &CBoat::AddWakePoint, PATCH_JUMP);
|
||||
InjectHook(0x5420D0, &CBoat::PruneWakeTrail, PATCH_JUMP);
|
||||
InjectHook(0x541A30, &CBoat::ApplyWaterResistance, PATCH_JUMP);
|
||||
ENDPATCHES
|
||||
|
|
|
@ -2,47 +2,41 @@
|
|||
|
||||
#include "Vehicle.h"
|
||||
|
||||
enum eBoatNodes
|
||||
{
|
||||
BOAT_MOVING = 1,
|
||||
BOAT_RUDDER,
|
||||
BOAT_WINDSCREEN
|
||||
};
|
||||
|
||||
class CBoat : public CVehicle
|
||||
{
|
||||
public:
|
||||
// 0x288
|
||||
float field_288;
|
||||
float field_28C;
|
||||
float field_290;
|
||||
float field_294;
|
||||
float field_298;
|
||||
float field_29C;
|
||||
float field_2A0;
|
||||
float field_2A4;
|
||||
float m_fPropellerZ;
|
||||
float m_fPropellerY;
|
||||
CVector m_waterMoveDrag;
|
||||
CVector m_waterTurnDrag;
|
||||
float m_fMovingHiRotation;
|
||||
int32 _unk0;
|
||||
RwFrame *m_aBoatNodes[4];
|
||||
uint8 m_bBoatFlag1 : 1;
|
||||
uint8 m_bBoatFlag2 : 1;
|
||||
uint8 m_bBoatFlag3 : 1;
|
||||
uint8 m_bBoatFlag4 : 1;
|
||||
uint8 m_bBoatFlag5 : 1;
|
||||
uint8 m_bBoatFlag6 : 1;
|
||||
uint8 m_bBoatFlag7 : 1;
|
||||
uint8 m_bBoatFlag8 : 1;
|
||||
uint8 bBoatInWater : 1;
|
||||
uint8 bPropellerInWater : 1;
|
||||
bool m_bIsAnchored;
|
||||
char _pad0[2];
|
||||
float field_2C4;
|
||||
float m_fOrientation;
|
||||
int32 _unk1;
|
||||
float field_2CC;
|
||||
CEntity *field_2D0;
|
||||
float m_fDamage;
|
||||
CEntity *m_pSetOnFireEntity;
|
||||
bool _unk2;
|
||||
char _pad1[3];
|
||||
float m_fAccelerate;
|
||||
float m_fBrake;
|
||||
float m_fSteeringLeftRight;
|
||||
uint8 m_nPadID;
|
||||
char _pad2[3];
|
||||
int32 _unk3;
|
||||
float m_fTurnForceZ;
|
||||
CVector m_vecMoveForce;
|
||||
float field_2FC;
|
||||
uint16 field_300;
|
||||
float m_fVolumeUnderWater;
|
||||
CVector m_vecBuoyancePoint;
|
||||
float m_fPrevVolumeUnderWater;
|
||||
int16 m_nDeltaVolumeUnderWater;
|
||||
uint16 m_nNumWakePoints;
|
||||
CVector2D m_avec2dWakePoints[32];
|
||||
float m_afWakePointLifeTime[32];
|
||||
|
@ -59,7 +53,10 @@ public:
|
|||
virtual bool IsComponentPresent(int32 component) { return true; }
|
||||
virtual void BlowUpCar(CEntity *ent);
|
||||
|
||||
void ApplyWaterResistance(void);
|
||||
void SetupModelNodes();
|
||||
void PruneWakeTrail(void);
|
||||
void AddWakePoint(CVector point);
|
||||
|
||||
static CBoat *(&apFrameWakeGeneratingBoats)[4];
|
||||
|
||||
|
|
|
@ -481,6 +481,55 @@ CVehicle::InflictDamage(CEntity* damagedBy, eWeaponType weaponType, float damage
|
|||
FindPlayerPed()->SetWantedLevelNoDrop(1);
|
||||
}
|
||||
|
||||
void
|
||||
CVehicle::DoFixedMachineGuns(void)
|
||||
{
|
||||
if(CPad::GetPad(0)->GetCarGunFired() && !bGunSwitchedOff){
|
||||
if(CTimer::GetTimeInMilliseconds() > m_nGunFiringTime + 150){
|
||||
CVector source, target;
|
||||
float dx, dy, len;
|
||||
|
||||
dx = GetForward().x;
|
||||
dy = GetForward().y;
|
||||
len = Sqrt(SQR(dx) + SQR(dy));
|
||||
if(len < 0.1f) len = 0.1f;
|
||||
dx /= len;
|
||||
dy /= len;
|
||||
|
||||
m_nGunFiringTime = CTimer::GetTimeInMilliseconds();
|
||||
|
||||
source = GetMatrix() * CVector(2.0f, 2.5f, 1.0f);
|
||||
target = source + CVector(dx, dy, 0.0f)*60.0f;
|
||||
target += CVector(
|
||||
((CGeneral::GetRandomNumber()&0xFF)-128) * 0.015f,
|
||||
((CGeneral::GetRandomNumber()&0xFF)-128) * 0.015f,
|
||||
((CGeneral::GetRandomNumber()&0xFF)-128) * 0.02f);
|
||||
CWeapon::DoTankDoomAiming(this, pDriver, &source, &target);
|
||||
FireOneInstantHitRound(&source, &target, 15);
|
||||
|
||||
source = GetMatrix() * CVector(-2.0f, 2.5f, 1.0f);
|
||||
target = source + CVector(dx, dy, 0.0f)*60.0f;
|
||||
target += CVector(
|
||||
((CGeneral::GetRandomNumber()&0xFF)-128) * 0.015f,
|
||||
((CGeneral::GetRandomNumber()&0xFF)-128) * 0.015f,
|
||||
((CGeneral::GetRandomNumber()&0xFF)-128) * 0.02f);
|
||||
CWeapon::DoTankDoomAiming(this, pDriver, &source, &target);
|
||||
FireOneInstantHitRound(&source, &target, 15);
|
||||
|
||||
DMAudio.PlayOneShot(m_audioEntityId, SOUND_WEAPON_SHOT_FIRED, 0.0f);
|
||||
|
||||
m_nAmmoInClip--;
|
||||
if(m_nAmmoInClip == 0){
|
||||
m_nAmmoInClip = 20;
|
||||
m_nGunFiringTime = CTimer::GetTimeInMilliseconds() + 1400;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(CTimer::GetTimeInMilliseconds() > m_nGunFiringTime + 1400)
|
||||
m_nAmmoInClip = 20;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CVehicle::ExtinguishCarFire(void)
|
||||
{
|
||||
|
|
|
@ -270,6 +270,7 @@ public:
|
|||
bool IsSphereTouchingVehicle(float sx, float sy, float sz, float radius);
|
||||
bool ShufflePassengersToMakeSpace(void);
|
||||
void InflictDamage(CEntity *damagedBy, eWeaponType weaponType, float damage);
|
||||
void DoFixedMachineGuns(void);
|
||||
|
||||
bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1; }
|
||||
CVehicleModelInfo* GetModelInfo() { return (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()); }
|
||||
|
|
Loading…
Reference in New Issue