Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Nikolay Korolev 2019-07-27 21:28:42 +03:00
commit d62225968b
13 changed files with 612 additions and 174 deletions

View File

@ -2430,7 +2430,7 @@ int8 CRunningScript::ProcessCommandsFrom200To299(int32 command)
{ {
CollectParameters(&m_nIp, 2); CollectParameters(&m_nIp, 2);
bool value = GetPadState(ScriptParams[0], ScriptParams[1]) != 0; bool value = GetPadState(ScriptParams[0], ScriptParams[1]) != 0;
if (CGame::playingIntro && ScriptParams[0] && ScriptParams[1] == 12){ /* pad1, start */ if (CGame::playingIntro && ScriptParams[0] == 0 && ScriptParams[1] == 12){ /* pad1, start */
if (CPad::GetPad(0)->GetLeftMouseJustDown() || if (CPad::GetPad(0)->GetLeftMouseJustDown() ||
CPad::GetPad(0)->GetPadEnterJustDown() || CPad::GetPad(0)->GetPadEnterJustDown() ||
CPad::GetPad(0)->GetCharJustDown(' ')) CPad::GetPad(0)->GetCharJustDown(' '))
@ -3169,4 +3169,4 @@ InjectHook(0x439000, &CTheScripts::StartNewScript, PATCH_JUMP);
InjectHook(0x439040, &CTheScripts::Process, PATCH_JUMP); InjectHook(0x439040, &CTheScripts::Process, PATCH_JUMP);
InjectHook(0x439400, &CTheScripts::StartTestScript, PATCH_JUMP); InjectHook(0x439400, &CTheScripts::StartTestScript, PATCH_JUMP);
InjectHook(0x439410, &CTheScripts::IsPlayerOnAMission, PATCH_JUMP); InjectHook(0x439410, &CTheScripts::IsPlayerOnAMission, PATCH_JUMP);
ENDPATCHES ENDPATCHES

View File

@ -150,6 +150,18 @@ FixCar(void)
((CAutomobile*)veh)->Fix(); ((CAutomobile*)veh)->Fix();
} }
static int engineStatus;
static void
SetEngineStatus(void)
{
CVehicle *veh = FindPlayerVehicle();
if(veh == nil)
return;
if(!veh->IsCar())
return;
((CAutomobile*)veh)->Damage.SetEngineStatus(engineStatus);
}
static void static void
ToggleComedy(void) ToggleComedy(void)
{ {
@ -300,7 +312,8 @@ DebugMenuPopulate(void)
DebugMenuAddCmd("Spawn", "Spawn Rhino", [](){ SpawnCar(MI_RHINO); }); DebugMenuAddCmd("Spawn", "Spawn Rhino", [](){ SpawnCar(MI_RHINO); });
DebugMenuAddCmd("Spawn", "Spawn Firetruck", [](){ SpawnCar(MI_FIRETRUCK); }); DebugMenuAddCmd("Spawn", "Spawn Firetruck", [](){ SpawnCar(MI_FIRETRUCK); });
DebugMenuAddVar("Debug", "Engine Status", &engineStatus, nil, 1, 0, 226, nil);
DebugMenuAddCmd("Debug", "Set Engine Status", SetEngineStatus);
DebugMenuAddCmd("Debug", "Fix Car", FixCar); DebugMenuAddCmd("Debug", "Fix Car", FixCar);
DebugMenuAddCmd("Debug", "Toggle Comedy Controls", ToggleComedy); DebugMenuAddCmd("Debug", "Toggle Comedy Controls", ToggleComedy);
DebugMenuAddCmd("Debug", "Place Car on Road", PlaceOnRoad); DebugMenuAddCmd("Debug", "Place Car on Road", PlaceOnRoad);

View File

@ -125,6 +125,24 @@ public:
m_matrix.pos.y = 0.0f; m_matrix.pos.y = 0.0f;
m_matrix.pos.z = 0.0f; m_matrix.pos.z = 0.0f;
} }
void Scale(float scale)
{
// GTA treats this as 4x4 floats
m_matrix.right.x *= scale;
m_matrix.right.y *= scale;
m_matrix.right.z *= scale;
m_matrix.up.x *= scale;
m_matrix.up.y *= scale;
m_matrix.up.z *= scale;
m_matrix.at.x *= scale;
m_matrix.at.y *= scale;
m_matrix.at.z *= scale;
m_matrix.pos.x *= scale;
m_matrix.pos.y *= scale;
m_matrix.pos.z *= scale;
m_matrix.flags = 0;
}
void SetRotateXOnly(float angle){ void SetRotateXOnly(float angle){
float c = Cos(angle); float c = Cos(angle);
@ -192,40 +210,10 @@ public:
m_matrix.pos.y = 0.0f; m_matrix.pos.y = 0.0f;
m_matrix.pos.z = 0.0f; m_matrix.pos.z = 0.0f;
} }
void SetRotate(float xAngle, float yAngle, float zAngle) { void SetRotate(float xAngle, float yAngle, float zAngle);
float cX = Cos(xAngle); void Rotate(float x, float y, float z);
float sX = Sin(xAngle);
float cY = Cos(yAngle);
float sY = Sin(yAngle);
float cZ = Cos(zAngle);
float sZ = Sin(zAngle);
m_matrix.right.x = cZ * cY - (sZ * sX) * sY; void Reorthogonalise(void);
m_matrix.right.y = (cZ * sX) * sY + sZ * cY;
m_matrix.right.z = -cX * sY;
m_matrix.up.x = -sZ * cX;
m_matrix.up.y = cZ * cX;
m_matrix.up.z = sX;
m_matrix.at.x = (sZ * sX) * cY + cZ * sY;
m_matrix.at.y = sZ * sY - (cZ * sX) * cY;
m_matrix.at.z = cX * cY;
m_matrix.pos.x = 0.0f;
m_matrix.pos.y = 0.0f;
m_matrix.pos.z = 0.0f;
}
void Reorthogonalise(void){
CVector &r = GetRight();
CVector &f = GetForward();
CVector &u = GetUp();
u = CrossProduct(r, f);
u.Normalise();
r = CrossProduct(f, u);
r.Normalise();
f = CrossProduct(u, r);
}
void CopyOnlyMatrix(CMatrix *other){ void CopyOnlyMatrix(CMatrix *other){
m_matrix = other->m_matrix; m_matrix = other->m_matrix;
} }
@ -245,35 +233,13 @@ public:
} }
}; };
inline CMatrix&
Invert(const CMatrix &src, CMatrix &dst) CMatrix &Invert(const CMatrix &src, CMatrix &dst);
{ CVector operator*(const CMatrix &mat, const CVector &vec);
// GTA handles this as a raw 4x4 orthonormal matrix CMatrix operator*(const CMatrix &m1, const CMatrix &m2);
// and trashes the RW flags, let's not do that CVector MultiplyInverse(const CMatrix &mat, const CVector &vec);
// actual copy of librw code: CVector Multiply3x3(const CMatrix &mat, const CVector &vec);
RwMatrix *d = &dst.m_matrix; CVector Multiply3x3(const CVector &vec, const CMatrix &mat);
const RwMatrix *s = &src.m_matrix;
d->right.x = s->right.x;
d->right.y = s->up.x;
d->right.z = s->at.x;
d->up.x = s->right.y;
d->up.y = s->up.y;
d->up.z = s->at.y;
d->at.x = s->right.z;
d->at.y = s->up.z;
d->at.z = s->at.z;
d->pos.x = -(s->pos.x*s->right.x +
s->pos.y*s->right.y +
s->pos.z*s->right.z);
d->pos.y = -(s->pos.x*s->up.x +
s->pos.y*s->up.y +
s->pos.z*s->up.z);
d->pos.z = -(s->pos.x*s->at.x +
s->pos.y*s->at.y +
s->pos.z*s->at.z);
d->flags = rwMATRIXTYPEORTHONORMAL;
return dst;
}
inline CMatrix inline CMatrix
Invert(const CMatrix &matrix) Invert(const CMatrix &matrix)
@ -282,64 +248,6 @@ Invert(const CMatrix &matrix)
return Invert(matrix, inv); return Invert(matrix, inv);
} }
inline CVector
operator*(const CMatrix &mat, const CVector &vec)
{
return CVector(
mat.m_matrix.right.x * vec.x + mat.m_matrix.up.x * vec.y + mat.m_matrix.at.x * vec.z + mat.m_matrix.pos.x,
mat.m_matrix.right.y * vec.x + mat.m_matrix.up.y * vec.y + mat.m_matrix.at.y * vec.z + mat.m_matrix.pos.y,
mat.m_matrix.right.z * vec.x + mat.m_matrix.up.z * vec.y + mat.m_matrix.at.z * vec.z + mat.m_matrix.pos.z);
}
inline CMatrix
operator*(const CMatrix &m1, const CMatrix &m2)
{
CMatrix out;
RwMatrix *dst = &out.m_matrix;
const RwMatrix *src1 = &m1.m_matrix;
const RwMatrix *src2 = &m2.m_matrix;
dst->right.x = src1->right.x*src2->right.x + src1->up.x*src2->right.y + src1->at.x*src2->right.z;
dst->right.y = src1->right.y*src2->right.x + src1->up.y*src2->right.y + src1->at.y*src2->right.z;
dst->right.z = src1->right.z*src2->right.x + src1->up.z*src2->right.y + src1->at.z*src2->right.z;
dst->up.x = src1->right.x*src2->up.x + src1->up.x*src2->up.y + src1->at.x*src2->up.z;
dst->up.y = src1->right.y*src2->up.x + src1->up.y*src2->up.y + src1->at.y*src2->up.z;
dst->up.z = src1->right.z*src2->up.x + src1->up.z*src2->up.y + src1->at.z*src2->up.z;
dst->at.x = src1->right.x*src2->at.x + src1->up.x*src2->at.y + src1->at.x*src2->at.z;
dst->at.y = src1->right.y*src2->at.x + src1->up.y*src2->at.y + src1->at.y*src2->at.z;
dst->at.z = src1->right.z*src2->at.x + src1->up.z*src2->at.y + src1->at.z*src2->at.z;
dst->pos.x = src1->right.x*src2->pos.x + src1->up.x*src2->pos.y + src1->at.x*src2->pos.z + src1->pos.x;
dst->pos.y = src1->right.y*src2->pos.x + src1->up.y*src2->pos.y + src1->at.y*src2->pos.z + src1->pos.y;
dst->pos.z = src1->right.z*src2->pos.x + src1->up.z*src2->pos.y + src1->at.z*src2->pos.z + src1->pos.z;
return out;
}
inline CVector
MultiplyInverse(const CMatrix &mat, const CVector &vec)
{
CVector v(vec.x - mat.m_matrix.pos.x, vec.y - mat.m_matrix.pos.y, vec.z - mat.m_matrix.pos.z);
return CVector(
mat.m_matrix.right.x * v.x + mat.m_matrix.right.y * v.y + mat.m_matrix.right.z * v.z,
mat.m_matrix.up.x * v.x + mat.m_matrix.up.y * v.y + mat.m_matrix.up.z * v.z,
mat.m_matrix.at.x * v.x + mat.m_matrix.at.y * v.y + mat.m_matrix.at.z * v.z);
}
inline CVector
Multiply3x3(const CMatrix &mat, const CVector &vec)
{
return CVector(
mat.m_matrix.right.x * vec.x + mat.m_matrix.up.x * vec.y + mat.m_matrix.at.x * vec.z,
mat.m_matrix.right.y * vec.x + mat.m_matrix.up.y * vec.y + mat.m_matrix.at.y * vec.z,
mat.m_matrix.right.z * vec.x + mat.m_matrix.up.z * vec.y + mat.m_matrix.at.z * vec.z);
}
inline CVector
Multiply3x3(const CVector &vec, const CMatrix &mat)
{
return CVector(
mat.m_matrix.right.x * vec.x + mat.m_matrix.right.y * vec.y + mat.m_matrix.right.z * vec.z,
mat.m_matrix.up.x * vec.x + mat.m_matrix.up.y * vec.y + mat.m_matrix.up.z * vec.z,
mat.m_matrix.at.x * vec.x + mat.m_matrix.at.y * vec.y + mat.m_matrix.at.z * vec.z);
}
class CCompressedMatrixNotAligned class CCompressedMatrixNotAligned
{ {

View File

@ -4,6 +4,145 @@
// TODO: move more stuff into here // TODO: move more stuff into here
void
CMatrix::SetRotate(float xAngle, float yAngle, float zAngle)
{
float cX = Cos(xAngle);
float sX = Sin(xAngle);
float cY = Cos(yAngle);
float sY = Sin(yAngle);
float cZ = Cos(zAngle);
float sZ = Sin(zAngle);
m_matrix.right.x = cZ * cY - (sZ * sX) * sY;
m_matrix.right.y = (cZ * sX) * sY + sZ * cY;
m_matrix.right.z = -cX * sY;
m_matrix.up.x = -sZ * cX;
m_matrix.up.y = cZ * cX;
m_matrix.up.z = sX;
m_matrix.at.x = (sZ * sX) * cY + cZ * sY;
m_matrix.at.y = sZ * sY - (cZ * sX) * cY;
m_matrix.at.z = cX * cY;
m_matrix.pos.x = 0.0f;
m_matrix.pos.y = 0.0f;
m_matrix.pos.z = 0.0f;
}
void
CMatrix::Rotate(float x, float y, float z)
{
// TODO? do this directly without creating another matrix
CMatrix rot;
rot.SetRotate(x, y, z);
*this = rot * *this;
}
void
CMatrix::Reorthogonalise(void)
{
CVector &r = GetRight();
CVector &f = GetForward();
CVector &u = GetUp();
u = CrossProduct(r, f);
u.Normalise();
r = CrossProduct(f, u);
r.Normalise();
f = CrossProduct(u, r);
}
CMatrix&
Invert(const CMatrix &src, CMatrix &dst)
{
// GTA handles this as a raw 4x4 orthonormal matrix
// and trashes the RW flags, let's not do that
// actual copy of librw code:
RwMatrix *d = &dst.m_matrix;
const RwMatrix *s = &src.m_matrix;
d->right.x = s->right.x;
d->right.y = s->up.x;
d->right.z = s->at.x;
d->up.x = s->right.y;
d->up.y = s->up.y;
d->up.z = s->at.y;
d->at.x = s->right.z;
d->at.y = s->up.z;
d->at.z = s->at.z;
d->pos.x = -(s->pos.x*s->right.x +
s->pos.y*s->right.y +
s->pos.z*s->right.z);
d->pos.y = -(s->pos.x*s->up.x +
s->pos.y*s->up.y +
s->pos.z*s->up.z);
d->pos.z = -(s->pos.x*s->at.x +
s->pos.y*s->at.y +
s->pos.z*s->at.z);
d->flags = rwMATRIXTYPEORTHONORMAL;
return dst;
}
CVector
operator*(const CMatrix &mat, const CVector &vec)
{
return CVector(
mat.m_matrix.right.x * vec.x + mat.m_matrix.up.x * vec.y + mat.m_matrix.at.x * vec.z + mat.m_matrix.pos.x,
mat.m_matrix.right.y * vec.x + mat.m_matrix.up.y * vec.y + mat.m_matrix.at.y * vec.z + mat.m_matrix.pos.y,
mat.m_matrix.right.z * vec.x + mat.m_matrix.up.z * vec.y + mat.m_matrix.at.z * vec.z + mat.m_matrix.pos.z);
}
CMatrix
operator*(const CMatrix &m1, const CMatrix &m2)
{
CMatrix out;
RwMatrix *dst = &out.m_matrix;
const RwMatrix *src1 = &m1.m_matrix;
const RwMatrix *src2 = &m2.m_matrix;
dst->right.x = src1->right.x*src2->right.x + src1->up.x*src2->right.y + src1->at.x*src2->right.z;
dst->right.y = src1->right.y*src2->right.x + src1->up.y*src2->right.y + src1->at.y*src2->right.z;
dst->right.z = src1->right.z*src2->right.x + src1->up.z*src2->right.y + src1->at.z*src2->right.z;
dst->up.x = src1->right.x*src2->up.x + src1->up.x*src2->up.y + src1->at.x*src2->up.z;
dst->up.y = src1->right.y*src2->up.x + src1->up.y*src2->up.y + src1->at.y*src2->up.z;
dst->up.z = src1->right.z*src2->up.x + src1->up.z*src2->up.y + src1->at.z*src2->up.z;
dst->at.x = src1->right.x*src2->at.x + src1->up.x*src2->at.y + src1->at.x*src2->at.z;
dst->at.y = src1->right.y*src2->at.x + src1->up.y*src2->at.y + src1->at.y*src2->at.z;
dst->at.z = src1->right.z*src2->at.x + src1->up.z*src2->at.y + src1->at.z*src2->at.z;
dst->pos.x = src1->right.x*src2->pos.x + src1->up.x*src2->pos.y + src1->at.x*src2->pos.z + src1->pos.x;
dst->pos.y = src1->right.y*src2->pos.x + src1->up.y*src2->pos.y + src1->at.y*src2->pos.z + src1->pos.y;
dst->pos.z = src1->right.z*src2->pos.x + src1->up.z*src2->pos.y + src1->at.z*src2->pos.z + src1->pos.z;
return out;
}
CVector
MultiplyInverse(const CMatrix &mat, const CVector &vec)
{
CVector v(vec.x - mat.m_matrix.pos.x, vec.y - mat.m_matrix.pos.y, vec.z - mat.m_matrix.pos.z);
return CVector(
mat.m_matrix.right.x * v.x + mat.m_matrix.right.y * v.y + mat.m_matrix.right.z * v.z,
mat.m_matrix.up.x * v.x + mat.m_matrix.up.y * v.y + mat.m_matrix.up.z * v.z,
mat.m_matrix.at.x * v.x + mat.m_matrix.at.y * v.y + mat.m_matrix.at.z * v.z);
}
CVector
Multiply3x3(const CMatrix &mat, const CVector &vec)
{
return CVector(
mat.m_matrix.right.x * vec.x + mat.m_matrix.up.x * vec.y + mat.m_matrix.at.x * vec.z,
mat.m_matrix.right.y * vec.x + mat.m_matrix.up.y * vec.y + mat.m_matrix.at.y * vec.z,
mat.m_matrix.right.z * vec.x + mat.m_matrix.up.z * vec.y + mat.m_matrix.at.z * vec.z);
}
CVector
Multiply3x3(const CVector &vec, const CMatrix &mat)
{
return CVector(
mat.m_matrix.right.x * vec.x + mat.m_matrix.right.y * vec.y + mat.m_matrix.right.z * vec.z,
mat.m_matrix.up.x * vec.x + mat.m_matrix.up.y * vec.y + mat.m_matrix.up.z * vec.z,
mat.m_matrix.at.x * vec.x + mat.m_matrix.at.y * vec.y + mat.m_matrix.at.z * vec.z);
}
void void
CQuaternion::Slerp(const CQuaternion &q1, const CQuaternion &q2, float theta, float invSin, float t) CQuaternion::Slerp(const CQuaternion &q1, const CQuaternion &q2, float theta, float invSin, float t)
{ {

View File

@ -79,7 +79,7 @@ RwObjectNameIdAssocation boatIds[] = {
{ "boat_moving_hi", 1, VEHICLE_FLAG_COLLAPSE }, { "boat_moving_hi", 1, VEHICLE_FLAG_COLLAPSE },
{ "boat_rudder_hi", 3, VEHICLE_FLAG_COLLAPSE }, { "boat_rudder_hi", 3, VEHICLE_FLAG_COLLAPSE },
{ "windscreen", 2, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_COLLAPSE }, { "windscreen", 2, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_COLLAPSE },
{ "ped_frontseat", 0, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, { "ped_frontseat", BOAT_POS_FRONTSEAT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID },
{ nil, 0, 0 } { nil, 0, 0 }
}; };

View File

@ -47,9 +47,6 @@ enum {
}; };
enum { enum {
VEHICLE_DUMMY_BOAT_RUDDER = 0,
VEHICLE_DUMMY_FRONT_SEATS = 2,
VEHICLE_DUMMY_REAR_SEATS = 3,
NUM_VEHICLE_POSITIONS = 10 NUM_VEHICLE_POSITIONS = 10
}; };

View File

@ -1456,8 +1456,8 @@ CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg)
ped->m_ped_flagI4 = false; ped->m_ped_flagI4 = false;
} }
void CVector
CPed::GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float seatPosMult) CPed::GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float seatPosMult)
{ {
CVehicleModelInfo *vehModel; CVehicleModelInfo *vehModel;
CVector vehDoorPos; CVector vehDoorPos;
@ -1465,7 +1465,7 @@ CPed::GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enter
float seatOffset; float seatOffset;
vehModel = (CVehicleModelInfo*) CModelInfo::GetModelInfo(veh->m_modelIndex); vehModel = (CVehicleModelInfo*) CModelInfo::GetModelInfo(veh->m_modelIndex);
if (veh->bIsVan && (enterType == CAR_DOOR_LR || enterType == CAR_DOOR_RR)) { if (veh->bIsVan && (component == CAR_DOOR_LR || component == CAR_DOOR_RR)) {
seatOffset = 0.0f; seatOffset = 0.0f;
vehDoorOffset = offsetToOpenVanDoor; vehDoorOffset = offsetToOpenVanDoor;
} else { } else {
@ -1477,63 +1477,63 @@ CPed::GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enter
} }
} }
switch (enterType) { switch (component) {
case CAR_DOOR_RF: case CAR_DOOR_RF:
if (vehModel->m_vehicleType == VEHICLE_TYPE_BOAT) if (vehModel->m_vehicleType == VEHICLE_TYPE_BOAT)
vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_BOAT_RUDDER]; vehDoorPos = vehModel->m_positions[BOAT_POS_FRONTSEAT];
else else
vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_FRONT_SEATS]; vehDoorPos = vehModel->m_positions[CAR_POS_FRONTSEAT];
vehDoorPos.x += seatOffset; vehDoorPos.x += seatOffset;
vehDoorOffset.x = -vehDoorOffset.x; vehDoorOffset.x = -vehDoorOffset.x;
break; break;
case CAR_DOOR_RR: case CAR_DOOR_RR:
vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_REAR_SEATS]; vehDoorPos = vehModel->m_positions[CAR_POS_FRONTSEAT];
vehDoorPos.x += seatOffset; vehDoorPos.x += seatOffset;
vehDoorOffset.x = -vehDoorOffset.x; vehDoorOffset.x = -vehDoorOffset.x;
break; break;
case CAR_DOOR_LF: case CAR_DOOR_LF:
if (vehModel->m_vehicleType == VEHICLE_TYPE_BOAT) if (vehModel->m_vehicleType == VEHICLE_TYPE_BOAT)
vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_BOAT_RUDDER]; vehDoorPos = vehModel->m_positions[BOAT_POS_FRONTSEAT];
else else
vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_FRONT_SEATS]; vehDoorPos = vehModel->m_positions[CAR_POS_FRONTSEAT];
vehDoorPos.x = -(vehDoorPos.x + seatOffset); vehDoorPos.x = -(vehDoorPos.x + seatOffset);
break; break;
case CAR_DOOR_LR: case CAR_DOOR_LR:
vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_REAR_SEATS]; vehDoorPos = vehModel->m_positions[BOAT_POS_FRONTSEAT];
vehDoorPos.x = -(vehDoorPos.x + seatOffset); vehDoorPos.x = -(vehDoorPos.x + seatOffset);
break; break;
default: default:
if (vehModel->m_vehicleType == VEHICLE_TYPE_BOAT) if (vehModel->m_vehicleType == VEHICLE_TYPE_BOAT)
vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_BOAT_RUDDER]; vehDoorPos = vehModel->m_positions[BOAT_POS_FRONTSEAT];
else else
vehDoorPos = vehModel->m_positions[VEHICLE_DUMMY_FRONT_SEATS]; vehDoorPos = vehModel->m_positions[CAR_POS_FRONTSEAT];
vehDoorOffset = CVector(0.0f, 0.0f, 0.0f); vehDoorOffset = CVector(0.0f, 0.0f, 0.0f);
} }
*output = vehDoorPos - vehDoorOffset; return vehDoorPos - vehDoorOffset;
} }
// This function was mostly duplicate of GetLocalPositionToOpenCarDoor, so I've used it. // This function was mostly duplicate of GetLocalPositionToOpenCarDoor, so I've used it.
void CVector
CPed::GetPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType) CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component)
{ {
CVector localPos; CVector localPos;
CVector vehDoorPos; CVector vehDoorPos;
GetLocalPositionToOpenCarDoor(&localPos, veh, enterType, 1.0f); localPos = GetLocalPositionToOpenCarDoor(veh, component, 1.0f);
vehDoorPos = Multiply3x3(veh->GetMatrix(), localPos) + veh->GetPosition(); vehDoorPos = Multiply3x3(veh->GetMatrix(), localPos) + veh->GetPosition();
/* /*
// Not used. // Not used.
CVector localVehDoorOffset; CVector localVehDoorOffset;
if (veh->bIsVan && (enterType == VEHICLE_ENTER_REAR_LEFT || enterType == VEHICLE_ENTER_REAR_RIGHT)) { if (veh->bIsVan && (component == VEHICLE_ENTER_REAR_LEFT || component == VEHICLE_ENTER_REAR_RIGHT)) {
localVehDoorOffset = offsetToOpenVanDoor; localVehDoorOffset = offsetToOpenVanDoor;
} else { } else {
if (veh->bIsLow) { if (veh->bIsLow) {
@ -1545,19 +1545,18 @@ CPed::GetPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType)
vehDoorPosWithoutOffset = Multiply3x3(veh->GetMatrix(), localPos + localVehDoorOffset) + veh->GetPosition(); vehDoorPosWithoutOffset = Multiply3x3(veh->GetMatrix(), localPos + localVehDoorOffset) + veh->GetPosition();
*/ */
*output = vehDoorPos; return vehDoorPos;
} }
void CVector
CPed::GetPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float offset) CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset)
{ {
CVector doorPos; CVector doorPos;
CMatrix vehMat(veh->GetMatrix()); CMatrix vehMat(veh->GetMatrix());
GetLocalPositionToOpenCarDoor(output, veh, enterType, offset); doorPos = Multiply3x3(vehMat, GetLocalPositionToOpenCarDoor(veh, component, offset));
doorPos = Multiply3x3(vehMat, *output);
*output = veh->GetPosition() + doorPos; return veh->GetPosition() + doorPos;
} }
void void
@ -1678,7 +1677,7 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase)
if (phase == LINE_UP_TO_CAR_2) { if (phase == LINE_UP_TO_CAR_2) {
neededPos = GetPosition(); neededPos = GetPosition();
} else { } else {
GetPositionToOpenCarDoor(&neededPos, veh, m_vehEnterType, seatPosMult); neededPos = GetPositionToOpenCarDoor(veh, m_vehEnterType, seatPosMult);
} }
CVector autoZPos = neededPos; CVector autoZPos = neededPos;
@ -1776,11 +1775,9 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase)
// It will be all 0 after rotate. // It will be all 0 after rotate.
GetPosition() = neededPos; GetPosition() = neededPos;
} else { } else {
CVector output;
CMatrix vehDoorMat(veh->GetMatrix()); CMatrix vehDoorMat(veh->GetMatrix());
GetLocalPositionToOpenCarDoor(&output, veh, m_vehEnterType, 0.0f); vehDoorMat.GetPosition() += Multiply3x3(vehDoorMat, GetLocalPositionToOpenCarDoor(veh, m_vehEnterType, 0.0f));
vehDoorMat.GetPosition() += Multiply3x3(vehDoorMat, output);
GetMatrix() = vehDoorMat; GetMatrix() = vehDoorMat;
} }
@ -4822,8 +4819,8 @@ STARTPATCHES
InjectHook(0x4CF000, &CPed::PedSetDraggedOutCarCB, PATCH_JUMP); InjectHook(0x4CF000, &CPed::PedSetDraggedOutCarCB, PATCH_JUMP);
InjectHook(0x4C5D80, &CPed::RestartNonPartialAnims, PATCH_JUMP); InjectHook(0x4C5D80, &CPed::RestartNonPartialAnims, PATCH_JUMP);
InjectHook(0x4E4730, &CPed::GetLocalPositionToOpenCarDoor, PATCH_JUMP); InjectHook(0x4E4730, &CPed::GetLocalPositionToOpenCarDoor, PATCH_JUMP);
InjectHook(0x4E4660, (void (*)(CVector*, CVehicle*, uint32, float)) CPed::GetPositionToOpenCarDoor, PATCH_JUMP); InjectHook(0x4E4660, (CVector (*)(CVehicle*, uint32, float)) CPed::GetPositionToOpenCarDoor, PATCH_JUMP);
InjectHook(0x4E1A30, (void (*)(CVector*, CVehicle*, uint32)) CPed::GetPositionToOpenCarDoor, PATCH_JUMP); InjectHook(0x4E1A30, (CVector (*)(CVehicle*, uint32)) CPed::GetPositionToOpenCarDoor, PATCH_JUMP);
InjectHook(0x4DF940, &CPed::LineUpPedWithCar, PATCH_JUMP); InjectHook(0x4DF940, &CPed::LineUpPedWithCar, PATCH_JUMP);
InjectHook(0x4CC6C0, &CPed::PlayFootSteps, PATCH_JUMP); InjectHook(0x4CC6C0, &CPed::PlayFootSteps, PATCH_JUMP);
InjectHook(0x4C5350, &CPed::BuildPedLists, PATCH_JUMP); InjectHook(0x4C5350, &CPed::BuildPedLists, PATCH_JUMP);

View File

@ -558,9 +558,9 @@ public:
void SetFall(int, AnimationId, uint8); void SetFall(int, AnimationId, uint8);
// Static methods // Static methods
static void GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float offset); static CVector GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset);
static void GetPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float seatPosMult); static CVector GetPositionToOpenCarDoor(CVehicle *veh, uint32 component, float seatPosMult);
static void GetPositionToOpenCarDoor(CVector* output, CVehicle* veh, uint32 enterType); static CVector GetPositionToOpenCarDoor(CVehicle* veh, uint32 component);
// Callbacks // Callbacks
static RwObject *SetPedAtomicVisibilityCB(RwObject *object, void *data); static RwObject *SetPedAtomicVisibilityCB(RwObject *object, void *data);

View File

@ -20,6 +20,7 @@
#include "Floater.h" #include "Floater.h"
#include "World.h" #include "World.h"
#include "SurfaceTable.h" #include "SurfaceTable.h"
#include "Weather.h"
#include "HandlingMgr.h" #include "HandlingMgr.h"
#include "Record.h" #include "Record.h"
#include "Remote.h" #include "Remote.h"
@ -167,7 +168,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy)
m_fCarGunLR = 0.0f; m_fCarGunLR = 0.0f;
m_fCarGunUD = 0.05f; m_fCarGunUD = 0.05f;
m_fWindScreenRotation = 0.0f; m_fPropellerRotation = 0.0f;
m_weaponDoorTimerLeft = 0.0f; m_weaponDoorTimerLeft = 0.0f;
m_weaponDoorTimerRight = m_weaponDoorTimerLeft; m_weaponDoorTimerRight = m_weaponDoorTimerLeft;
@ -206,7 +207,7 @@ CAutomobile::ProcessControl(void)
int i; int i;
CColModel *colModel; CColModel *colModel;
if(bUseSpecialColModel) if(bUsingSpecialColModel)
colModel = &CWorld::Players[CWorld::PlayerInFocus].m_ColModel; colModel = &CWorld::Players[CWorld::PlayerInFocus].m_ColModel;
else else
colModel = GetColModel(); colModel = GetColModel();
@ -1202,8 +1203,216 @@ CAutomobile::Teleport(CVector pos)
} }
WRAPPER void CAutomobile::PreRender(void) { EAXJMP(0x535B40); } WRAPPER void CAutomobile::PreRender(void) { EAXJMP(0x535B40); }
WRAPPER void CAutomobile::Render(void) { EAXJMP(0x539EA0); }
void
CAutomobile::Render(void)
{
int i;
CMatrix mat;
CVector pos;
CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
if(GetModelIndex() == MI_RHINO && m_aCarNodes[CAR_BONNET]){
// Rhino has no bonnet...what are we doing here?
CMatrix m;
CVector p;
m.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_BONNET]));
p = m.GetPosition();
m.SetRotateZ(m_fCarGunLR);
m.Translate(p);
m.UpdateRW();
}
CVector contactPoints[4]; // relative to model
CVector contactSpeeds[4]; // speed at contact points
CVector frontWheelFwd = Multiply3x3(GetMatrix(), CVector(-Sin(m_fSteerAngle), Cos(m_fSteerAngle), 0.0f));
CVector rearWheelFwd = GetForward();
for(i = 0; i < 4; i++){
contactPoints[i] = m_aWheelColPoints[i].point - GetPosition();
contactSpeeds[i] = GetSpeed(contactPoints[i]);
if(i == CARWHEEL_FRONT_LEFT || i == CARWHEEL_FRONT_RIGHT)
m_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], frontWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale);
else
m_aWheelSpeed[i] = ProcessWheelRotation(m_aWheelState[i], rearWheelFwd, contactSpeeds[i], 0.5f*mi->m_wheelScale);
m_aWheelRotation[i] += m_aWheelSpeed[i];
}
// Rear right wheel
mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RB]));
pos.x = mat.GetPosition().x;
pos.y = mat.GetPosition().y;
pos.z = m_aWheelPosition[CARWHEEL_REAR_RIGHT];
if(Damage.GetWheelStatus(CARWHEEL_REAR_RIGHT) == WHEEL_STATUS_BURST)
mat.SetRotate(m_aWheelRotation[CARWHEEL_REAR_RIGHT], 0.0f, 0.3f*Sin(m_aWheelRotation[CARWHEEL_REAR_RIGHT]));
else
mat.SetRotateX(m_aWheelRotation[CARWHEEL_REAR_RIGHT]);
mat.Scale(mi->m_wheelScale);
mat.Translate(pos);
mat.UpdateRW();
if(CVehicle::bWheelsOnlyCheat)
RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RB]));
// Rear left wheel
mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LB]));
pos.x = mat.GetPosition().x;
pos.y = mat.GetPosition().y;
pos.z = m_aWheelPosition[CARWHEEL_REAR_LEFT];
if(Damage.GetWheelStatus(CARWHEEL_REAR_LEFT) == WHEEL_STATUS_BURST)
mat.SetRotate(-m_aWheelRotation[CARWHEEL_REAR_LEFT], 0.0f, PI+0.3f*Sin(-m_aWheelRotation[CARWHEEL_REAR_LEFT]));
else
mat.SetRotate(-m_aWheelRotation[CARWHEEL_REAR_LEFT], 0.0f, PI);
mat.Scale(mi->m_wheelScale);
mat.Translate(pos);
mat.UpdateRW();
if(CVehicle::bWheelsOnlyCheat)
RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LB]));
// Mid right wheel
if(m_aCarNodes[CAR_WHEEL_RM]){
mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RM]));
pos.x = mat.GetPosition().x;
pos.y = mat.GetPosition().y;
pos.z = m_aWheelPosition[CARWHEEL_REAR_RIGHT];
if(Damage.GetWheelStatus(CARWHEEL_REAR_RIGHT) == WHEEL_STATUS_BURST)
mat.SetRotate(m_aWheelRotation[CARWHEEL_REAR_RIGHT], 0.0f, 0.3f*Sin(m_aWheelRotation[CARWHEEL_REAR_RIGHT]));
else
mat.SetRotateX(m_aWheelRotation[CARWHEEL_REAR_RIGHT]);
mat.Scale(mi->m_wheelScale);
mat.Translate(pos);
mat.UpdateRW();
if(CVehicle::bWheelsOnlyCheat)
RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RM]));
}
// Mid left wheel
if(m_aCarNodes[CAR_WHEEL_LM]){
mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LM]));
pos.x = mat.GetPosition().x;
pos.y = mat.GetPosition().y;
pos.z = m_aWheelPosition[CARWHEEL_REAR_LEFT];
if(Damage.GetWheelStatus(CARWHEEL_REAR_LEFT) == WHEEL_STATUS_BURST)
mat.SetRotate(-m_aWheelRotation[CARWHEEL_REAR_LEFT], 0.0f, PI+0.3f*Sin(-m_aWheelRotation[CARWHEEL_REAR_LEFT]));
else
mat.SetRotate(-m_aWheelRotation[CARWHEEL_REAR_LEFT], 0.0f, PI);
mat.Scale(mi->m_wheelScale);
mat.Translate(pos);
mat.UpdateRW();
if(CVehicle::bWheelsOnlyCheat)
RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LM]));
}
if(GetModelIndex() == MI_DODO){
// Front wheel
mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));
pos.x = mat.GetPosition().x;
pos.y = mat.GetPosition().y;
pos.z = m_aWheelPosition[CARWHEEL_FRONT_RIGHT];
if(Damage.GetWheelStatus(CARWHEEL_FRONT_RIGHT) == WHEEL_STATUS_BURST)
mat.SetRotate(m_aWheelRotation[CARWHEEL_FRONT_RIGHT], 0.0f, m_fSteerAngle+0.3f*Sin(m_aWheelRotation[CARWHEEL_FRONT_RIGHT]));
else
mat.SetRotate(m_aWheelRotation[CARWHEEL_FRONT_RIGHT], 0.0f, m_fSteerAngle);
mat.Scale(mi->m_wheelScale);
mat.Translate(pos);
mat.UpdateRW();
if(CVehicle::bWheelsOnlyCheat)
RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]));
// Rotate propeller
if(m_aCarNodes[CAR_WINDSCREEN]){
mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WINDSCREEN]));
pos = mat.GetPosition();
mat.SetRotateY(m_fPropellerRotation);
mat.Translate(pos);
mat.UpdateRW();
m_fPropellerRotation += m_fGasPedal != 0.0f ? TWOPI/13.0f : TWOPI/26.0f;
if(m_fPropellerRotation > TWOPI)
m_fPropellerRotation -= TWOPI;
}
// Rudder
if(Damage.GetDoorStatus(DOOR_BOOT) != DOOR_STATUS_MISSING && m_aCarNodes[CAR_BOOT]){
mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_BOOT]));
pos = mat.GetPosition();
mat.SetRotate(0.0f, 0.0f, -m_fSteerAngle);
mat.Rotate(0.0f, Sin(m_fSteerAngle)*DEGTORAD(22.0f), 0.0f);
mat.Translate(pos);
mat.UpdateRW();
}
ProcessSwingingDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT);
ProcessSwingingDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT);
}else if(GetModelIndex() == MI_RHINO){
// Front right wheel
mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));
pos.x = mat.GetPosition().x;
pos.y = mat.GetPosition().y;
pos.z = m_aWheelPosition[CARWHEEL_FRONT_RIGHT];
// no damaged wheels or steering
mat.SetRotate(m_aWheelRotation[CARWHEEL_FRONT_RIGHT], 0.0f, 0.0f);
mat.Scale(mi->m_wheelScale);
mat.Translate(pos);
mat.UpdateRW();
if(CVehicle::bWheelsOnlyCheat)
RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]));
// Front left wheel
mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));
pos.x = mat.GetPosition().x;
pos.y = mat.GetPosition().y;
pos.z = m_aWheelPosition[CARWHEEL_FRONT_LEFT];
// no damaged wheels or steering
mat.SetRotate(-m_aWheelRotation[CARWHEEL_FRONT_LEFT], 0.0f, PI);
mat.Scale(mi->m_wheelScale);
mat.Translate(pos);
mat.UpdateRW();
if(CVehicle::bWheelsOnlyCheat)
RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]));
}else{
// Front right wheel
mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_RF]));
pos.x = mat.GetPosition().x;
pos.y = mat.GetPosition().y;
pos.z = m_aWheelPosition[CARWHEEL_FRONT_RIGHT];
if(Damage.GetWheelStatus(CARWHEEL_FRONT_RIGHT) == WHEEL_STATUS_BURST)
mat.SetRotate(m_aWheelRotation[CARWHEEL_FRONT_RIGHT], 0.0f, m_fSteerAngle+0.3f*Sin(m_aWheelRotation[CARWHEEL_FRONT_RIGHT]));
else
mat.SetRotate(m_aWheelRotation[CARWHEEL_FRONT_RIGHT], 0.0f, m_fSteerAngle);
mat.Scale(mi->m_wheelScale);
mat.Translate(pos);
mat.UpdateRW();
if(CVehicle::bWheelsOnlyCheat)
RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_RF]));
// Front left wheel
mat.Attach(RwFrameGetMatrix(m_aCarNodes[CAR_WHEEL_LF]));
pos.x = mat.GetPosition().x;
pos.y = mat.GetPosition().y;
pos.z = m_aWheelPosition[CARWHEEL_FRONT_LEFT];
if(Damage.GetWheelStatus(CARWHEEL_FRONT_LEFT) == WHEEL_STATUS_BURST)
mat.SetRotate(-m_aWheelRotation[CARWHEEL_FRONT_LEFT], 0.0f, PI+m_fSteerAngle+0.3f*Sin(-m_aWheelRotation[CARWHEEL_FRONT_LEFT]));
else
mat.SetRotate(-m_aWheelRotation[CARWHEEL_FRONT_LEFT], 0.0f, PI+m_fSteerAngle);
mat.Scale(mi->m_wheelScale);
mat.Translate(pos);
mat.UpdateRW();
if(CVehicle::bWheelsOnlyCheat)
RpAtomicRender((RpAtomic*)GetFirstObject(m_aCarNodes[CAR_WHEEL_LF]));
ProcessSwingingDoor(CAR_DOOR_LF, DOOR_FRONT_LEFT);
ProcessSwingingDoor(CAR_DOOR_RF, DOOR_FRONT_RIGHT);
ProcessSwingingDoor(CAR_DOOR_LR, DOOR_REAR_LEFT);
ProcessSwingingDoor(CAR_DOOR_RR, DOOR_REAR_RIGHT);
ProcessSwingingDoor(CAR_BONNET, DOOR_BONNET);
ProcessSwingingDoor(CAR_BOOT, DOOR_BOOT);
mi->SetVehicleColour(m_currentColour1, m_currentColour2);
}
if(!CVehicle::bWheelsOnlyCheat)
CEntity::Render();
}
int32 int32
CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints) CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
@ -1214,7 +1423,7 @@ CAutomobile::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
if(m_status != STATUS_SIMPLE) if(m_status != STATUS_SIMPLE)
bVehicleColProcessed = true; bVehicleColProcessed = true;
if(bUseSpecialColModel) if(bUsingSpecialColModel)
colModel = &CWorld::Players[CWorld::PlayerInFocus].m_ColModel; colModel = &CWorld::Players[CWorld::PlayerInFocus].m_ColModel;
else else
colModel = GetColModel(); colModel = GetColModel();
@ -1596,7 +1805,7 @@ CAutomobile::HydraulicControl(void)
if(m_status != STATUS_PLAYER){ if(m_status != STATUS_PLAYER){
// reset hydraulics for non-player cars // reset hydraulics for non-player cars
if(!bUseSpecialColModel) if(!bUsingSpecialColModel)
return; return;
if(specialColModel != nil) // this is always true if(specialColModel != nil) // this is always true
for(i = 0; i < 4; i++) for(i = 0; i < 4; i++)
@ -1616,7 +1825,7 @@ CAutomobile::HydraulicControl(void)
if(playerInfo->m_pVehicleEx == this) if(playerInfo->m_pVehicleEx == this)
playerInfo->m_pVehicleEx = nil; playerInfo->m_pVehicleEx = nil;
bUseSpecialColModel = false; bUsingSpecialColModel = false;
m_hydraulicState = 0; m_hydraulicState = 0;
return; return;
} }
@ -1630,14 +1839,14 @@ CAutomobile::HydraulicControl(void)
float extendedLowerLimit = normalLowerLimit - 0.2f; float extendedLowerLimit = normalLowerLimit - 0.2f;
float extendedSpringLength = extendedUpperLimit - extendedLowerLimit; float extendedSpringLength = extendedUpperLimit - extendedLowerLimit;
if(!bUseSpecialColModel){ if(!bUsingSpecialColModel){
// Init special col model // Init special col model
if(playerInfo->m_pVehicleEx && playerInfo->m_pVehicleEx == this) if(playerInfo->m_pVehicleEx && playerInfo->m_pVehicleEx == this)
playerInfo->m_pVehicleEx->bUseSpecialColModel = false; playerInfo->m_pVehicleEx->bUsingSpecialColModel = false;
playerInfo->m_pVehicleEx = this; playerInfo->m_pVehicleEx = this;
playerInfo->m_ColModel = *normalColModel; playerInfo->m_ColModel = *normalColModel;
bUseSpecialColModel = true; bUsingSpecialColModel = true;
specialColModel = &playerInfo->m_ColModel; specialColModel = &playerInfo->m_ColModel;
if(m_fVelocityChangeForAudio > 0.1f) if(m_fVelocityChangeForAudio > 0.1f)
@ -2466,6 +2675,110 @@ CAutomobile::dmgDrawCarCollidingParticles(const CVector &pos, float amount)
CGeneral::GetRandomNumberInRange(0.0f, 4.0f)); CGeneral::GetRandomNumberInRange(0.0f, 4.0f));
} }
void
CAutomobile::AddDamagedVehicleParticles(void)
{
if(this == FindPlayerVehicle() && TheCamera.GetLookingForwardFirstPerson())
return;
uint8 engineStatus = Damage.GetEngineStatus();
if(engineStatus < ENGINE_STATUS_STEAM1)
return;
float fwdSpeed = DotProduct(m_vecMoveSpeed, GetForward()) * 180.0f;
CVector direction = 0.5f*m_vecMoveSpeed;
CVector damagePos = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->m_positions[CAR_POS_HEADLIGHTS];
switch(Damage.GetDoorStatus(DOOR_BONNET)){
case DOOR_STATUS_OK:
case DOOR_STATUS_SMASHED:
// Bonnet is still there, smoke comes out at the edge
damagePos += vecDAMAGE_ENGINE_POS_SMALL;
break;
case DOOR_STATUS_SWINGING:
case DOOR_STATUS_MISSING:
// Bonnet is gone, smoke comes out at the engine
damagePos += vecDAMAGE_ENGINE_POS_BIG;
break;
}
if(GetModelIndex() == MI_BFINJECT)
damagePos = CVector(0.3f, -1.5f, -0.1f);
damagePos = GetMatrix()*damagePos;
damagePos.z += 0.15f;
if(engineStatus < ENGINE_STATUS_STEAM2){
if(fwdSpeed < 90.0f){
direction.z += 0.05f;
CParticle::AddParticle(PARTICLE_ENGINE_STEAM, damagePos, direction, nil, 0.1f);
}
}else if(engineStatus < ENGINE_STATUS_SMOKE){
if(fwdSpeed < 90.0f)
CParticle::AddParticle(PARTICLE_ENGINE_STEAM, damagePos, direction, nil, 0.0f);
}else if(engineStatus < ENGINE_STATUS_ON_FIRE){
if(fwdSpeed < 90.0f){
CParticle::AddParticle(PARTICLE_ENGINE_STEAM, damagePos, direction, nil, 0.0f);
CParticle::AddParticle(PARTICLE_ENGINE_SMOKE, damagePos, 0.3f*direction, nil, 0.0f);
}
}else if(m_fHealth > 250.0f){
if(fwdSpeed < 90.0f)
CParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, damagePos, 0.2f*direction, nil, 0.0f);
}
}
void
CAutomobile::AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed)
{
int i;
CVector dir;
static RwRGBA grassCol = { 8, 24, 8, 255 };
static RwRGBA dirtCol = { 64, 64, 64, 255 };
static RwRGBA dirttrackCol = { 64, 32, 16, 255 };
static RwRGBA waterCol = { 48, 48, 64, 0 };
if(!belowEffectSpeed)
return;
switch(colpoint->surfaceB){
case SURFACE_GRASS:
dir.x = -0.05f*m_vecMoveSpeed.x;
dir.y = -0.05f*m_vecMoveSpeed.y;
for(i = 0; i < 4; i++){
dir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.06f);
CParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil,
CGeneral::GetRandomNumberInRange(0.02f, 0.1f), grassCol);
}
break;
case SURFACE_DIRT:
dir.x = -0.05f*m_vecMoveSpeed.x;
dir.y = -0.05f*m_vecMoveSpeed.y;
for(i = 0; i < 4; i++){
dir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.06f);
CParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil,
CGeneral::GetRandomNumberInRange(0.02f, 0.06f), dirtCol);
}
break;
case SURFACE_DIRTTRACK:
dir.x = -0.05f*m_vecMoveSpeed.x;
dir.y = -0.05f*m_vecMoveSpeed.y;
for(i = 0; i < 4; i++){
dir.z = CGeneral::GetRandomNumberInRange(0.03f, 0.06f);
CParticle::AddParticle(PARTICLE_WHEEL_DIRT, colpoint->point, dir, nil,
CGeneral::GetRandomNumberInRange(0.02f, 0.06f), dirttrackCol);
}
break;
default:
// Is this even visible?
if(CWeather::WetRoads > 0.01f && CTimer::GetFrameCounter() & 1)
CParticle::AddParticle(PARTICLE_WATERSPRAY,
colpoint->point + CVector(0.0f, 0.0f, 0.25f+0.25f),
CVector(0.0f, 0.0f, 1.0f), nil,
CGeneral::GetRandomNumberInRange(0.1f, 0.5f), waterCol);
break;
}
}
void void
CAutomobile::GetComponentWorldPosition(int32 component, CVector &pos) CAutomobile::GetComponentWorldPosition(int32 component, CVector &pos)
{ {
@ -2824,7 +3137,64 @@ CAutomobile::BurstTyre(uint8 wheel)
} }
} }
WRAPPER bool CAutomobile::IsRoomForPedToLeaveCar(uint32, CVector *) { EAXJMP(0x53C5B0); } bool
CAutomobile::IsRoomForPedToLeaveCar(uint32 component, CVector *doorOffset)
{
CColPoint colpoint;
CEntity *ent;
colpoint.point = CVector(0.0f, 0.0f, 0.0f);
CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex());
CVector seatPos;
switch(component){
case CAR_DOOR_RF:
seatPos = mi->m_positions[IsBoat() ? BOAT_POS_FRONTSEAT : CAR_POS_FRONTSEAT];
break;
case CAR_DOOR_LF:
seatPos = mi->m_positions[IsBoat() ? BOAT_POS_FRONTSEAT : CAR_POS_FRONTSEAT];
seatPos.x = -seatPos.x;
break;
case CAR_DOOR_RR:
seatPos = mi->m_positions[CAR_POS_BACKSEAT];
break;
case CAR_DOOR_LR:
seatPos = mi->m_positions[CAR_POS_BACKSEAT];
seatPos.x = -seatPos.x;
break;
}
seatPos = GetMatrix() * seatPos;
CVector doorPos = CPed::GetPositionToOpenCarDoor(this, component);
if(doorOffset){
CVector off = *doorOffset;
if(component == CAR_DOOR_RF || component == CAR_DOOR_RR)
off.x = -off.x;
doorPos += Multiply3x3(GetMatrix(), off);
}
if(GetUp().z < 0.0f){
seatPos.z += 0.5f;
doorPos.z += 0.5f;
}
CVector dist = doorPos - seatPos;
float length = dist.Magnitude();
CVector pedPos = seatPos + dist*((length+0.6f)/length);
if(!CWorld::GetIsLineOfSightClear(seatPos, pedPos, true, false, false, true, false, false))
return false;
if(CWorld::TestSphereAgainstWorld(doorPos, 0.6f, this, true, true, false, true, false, false))
return false;
if(CWorld::ProcessVerticalLine(doorPos, 1000.0f, colpoint, ent, true, false, false, true, false, false, nil))
if(colpoint.point.z > doorPos.z && colpoint.point.z < doorPos.z + 0.6f)
return false;
float upperZ = colpoint.point.z;
if(!CWorld::ProcessVerticalLine(doorPos, -1000.0f, colpoint, ent, true, false, false, true, false, false, nil))
return false;
if(upperZ != 0.0f && upperZ < colpoint.point.z)
return false;
return true;
}
float float
CAutomobile::GetHeightAboveRoad(void) CAutomobile::GetHeightAboveRoad(void)
@ -3438,6 +3808,7 @@ STARTPATCHES
InjectHook(0x52D190, &CAutomobile_::SetModelIndex_, PATCH_JUMP); InjectHook(0x52D190, &CAutomobile_::SetModelIndex_, PATCH_JUMP);
InjectHook(0x531470, &CAutomobile_::ProcessControl_, PATCH_JUMP); InjectHook(0x531470, &CAutomobile_::ProcessControl_, PATCH_JUMP);
InjectHook(0x535180, &CAutomobile_::Teleport_, PATCH_JUMP); InjectHook(0x535180, &CAutomobile_::Teleport_, PATCH_JUMP);
InjectHook(0x539EA0, &CAutomobile_::Render_, PATCH_JUMP);
InjectHook(0x53B270, &CAutomobile_::ProcessEntityCollision_, PATCH_JUMP); InjectHook(0x53B270, &CAutomobile_::ProcessEntityCollision_, PATCH_JUMP);
InjectHook(0x53B660, &CAutomobile_::ProcessControlInputs_, PATCH_JUMP); InjectHook(0x53B660, &CAutomobile_::ProcessControlInputs_, PATCH_JUMP);
InjectHook(0x52E5F0, &CAutomobile_::GetComponentWorldPosition_, PATCH_JUMP); InjectHook(0x52E5F0, &CAutomobile_::GetComponentWorldPosition_, PATCH_JUMP);
@ -3452,10 +3823,13 @@ STARTPATCHES
InjectHook(0x53BC60, &CAutomobile_::BlowUpCar_, PATCH_JUMP); InjectHook(0x53BC60, &CAutomobile_::BlowUpCar_, PATCH_JUMP);
InjectHook(0x53BF70, &CAutomobile_::SetUpWheelColModel_, PATCH_JUMP); InjectHook(0x53BF70, &CAutomobile_::SetUpWheelColModel_, PATCH_JUMP);
InjectHook(0x53C0E0, &CAutomobile_::BurstTyre_, PATCH_JUMP); InjectHook(0x53C0E0, &CAutomobile_::BurstTyre_, PATCH_JUMP);
InjectHook(0x53C5B0, &CAutomobile_::IsRoomForPedToLeaveCar_, PATCH_JUMP);
InjectHook(0x437690, &CAutomobile_::GetHeightAboveRoad_, PATCH_JUMP); InjectHook(0x437690, &CAutomobile_::GetHeightAboveRoad_, PATCH_JUMP);
InjectHook(0x53C450, &CAutomobile_::PlayCarHorn_, PATCH_JUMP); InjectHook(0x53C450, &CAutomobile_::PlayCarHorn_, PATCH_JUMP);
InjectHook(0x53E090, &CAutomobile::PlaceOnRoadProperly, PATCH_JUMP); InjectHook(0x53E090, &CAutomobile::PlaceOnRoadProperly, PATCH_JUMP);
InjectHook(0x52F030, &CAutomobile::dmgDrawCarCollidingParticles, PATCH_JUMP); InjectHook(0x52F030, &CAutomobile::dmgDrawCarCollidingParticles, PATCH_JUMP);
InjectHook(0x535450, &CAutomobile::AddDamagedVehicleParticles, PATCH_JUMP);
InjectHook(0x5357D0, &CAutomobile::AddWheelDirtAndWater, PATCH_JUMP);
InjectHook(0x5353A0, &CAutomobile::ResetSuspension, PATCH_JUMP); InjectHook(0x5353A0, &CAutomobile::ResetSuspension, PATCH_JUMP);
InjectHook(0x52D210, &CAutomobile::SetupSuspensionLines, PATCH_JUMP); InjectHook(0x52D210, &CAutomobile::SetupSuspensionLines, PATCH_JUMP);
InjectHook(0x53E000, &CAutomobile::BlowUpCarsInPath, PATCH_JUMP); InjectHook(0x53E000, &CAutomobile::BlowUpCarsInPath, PATCH_JUMP);

View File

@ -71,7 +71,7 @@ public:
float m_weaponDoorTimerRight; float m_weaponDoorTimerRight;
float m_fCarGunLR; float m_fCarGunLR;
float m_fCarGunUD; float m_fCarGunUD;
float m_fWindScreenRotation; float m_fPropellerRotation;
uint8 stuff4[4]; uint8 stuff4[4];
uint8 m_nWheelsOnGround; uint8 m_nWheelsOnGround;
uint8 m_nDriveWheelsOnGround; uint8 m_nDriveWheelsOnGround;
@ -108,7 +108,7 @@ public:
void BlowUpCar(CEntity *ent); void BlowUpCar(CEntity *ent);
bool SetUpWheelColModel(CColModel *colModel); bool SetUpWheelColModel(CColModel *colModel);
void BurstTyre(uint8 tyre); void BurstTyre(uint8 tyre);
bool IsRoomForPedToLeaveCar(uint32, CVector *); bool IsRoomForPedToLeaveCar(uint32 component, CVector *doorOffset);
float GetHeightAboveRoad(void); float GetHeightAboveRoad(void);
void PlayCarHorn(void); void PlayCarHorn(void);
@ -122,6 +122,8 @@ public:
int32 RcbanditCheck1CarWheels(CPtrList &list); int32 RcbanditCheck1CarWheels(CPtrList &list);
void PlaceOnRoadProperly(void); void PlaceOnRoadProperly(void);
void dmgDrawCarCollidingParticles(const CVector &pos, float amount); void dmgDrawCarCollidingParticles(const CVector &pos, float amount);
void AddDamagedVehicleParticles(void);
void AddWheelDirtAndWater(CColPoint *colpoint, uint32 belowEffectSpeed);
void PlayHornIfNecessary(void); void PlayHornIfNecessary(void);
void ResetSuspension(void); void ResetSuspension(void);
void SetupSuspensionLines(void); void SetupSuspensionLines(void);

View File

@ -6,6 +6,9 @@
enum eEngineStatus enum eEngineStatus
{ {
ENGINE_STATUS_STEAM1 = 100,
ENGINE_STATUS_STEAM2 = 150,
ENGINE_STATUS_SMOKE = 200,
ENGINE_STATUS_ON_FIRE = 225 ENGINE_STATUS_ON_FIRE = 225
}; };

View File

@ -70,7 +70,7 @@ CVehicle::CVehicle(uint8 CreatedBy)
bHasBeenOwnedByPlayer = false; bHasBeenOwnedByPlayer = false;
m_veh_flagC20 = false; m_veh_flagC20 = false;
bCanBeDamaged = true; bCanBeDamaged = true;
bUseSpecialColModel = false; bUsingSpecialColModel = false;
m_veh_flagD1 = false; m_veh_flagD1 = false;
m_veh_flagD2 = false; m_veh_flagD2 = false;
m_nGunFiringTime = 0; m_nGunFiringTime = 0;

View File

@ -59,6 +59,11 @@ enum
CAR_POS_EXHAUST = 9, CAR_POS_EXHAUST = 9,
}; };
enum
{
BOAT_POS_FRONTSEAT
};
enum eDoors enum eDoors
{ {
DOOR_BONNET = 0, DOOR_BONNET = 0,
@ -186,7 +191,7 @@ public:
uint8 m_veh_flagC10 : 1; uint8 m_veh_flagC10 : 1;
uint8 m_veh_flagC20 : 1; uint8 m_veh_flagC20 : 1;
uint8 bCanBeDamaged : 1; // Set to FALSE during cut scenes to avoid explosions uint8 bCanBeDamaged : 1; // Set to FALSE during cut scenes to avoid explosions
uint8 bUseSpecialColModel : 1; uint8 bUsingSpecialColModel : 1;// Is player vehicle using special collision model, stored in player strucure
uint8 m_veh_flagD1 : 1; uint8 m_veh_flagD1 : 1;
uint8 m_veh_flagD2 : 1; uint8 m_veh_flagD2 : 1;
@ -253,7 +258,7 @@ public:
virtual void BlowUpCar(CEntity *ent) {} virtual void BlowUpCar(CEntity *ent) {}
virtual bool SetUpWheelColModel(CColModel *colModel) { return false; } virtual bool SetUpWheelColModel(CColModel *colModel) { return false; }
virtual void BurstTyre(uint8 tyre) {} virtual void BurstTyre(uint8 tyre) {}
virtual bool IsRoomForPedToLeaveCar(uint32, CVector *) { return false;} virtual bool IsRoomForPedToLeaveCar(uint32 component, CVector *forcedDoorPos) { return false;}
virtual float GetHeightAboveRoad(void); virtual float GetHeightAboveRoad(void);
virtual void PlayCarHorn(void) {} virtual void PlayCarHorn(void) {}