#include "../newobjects.h" #include "../../Game/lara.h" #include "../../Game/inventory.h" #include "../../Game/effect2.h" #include "../../Game/collide.h" #include "../../Game/effects.h" #include "../../Game/lara1gun.h" #include "../../Game/items.h" #include "../../Game/sphere.h" #include "../../Game/laraflar.h" #include using namespace std; #define JF_FALLING 0x40 #define JF_DEAD 0x80 #define JEEP_GETOFF_DISTANCE 512 #define JEEP_UNDO_TURN 91 #define JEEP_SLIP 100 #define JEEP_SLIP_SIDE 128 #define JEEP_MAX_SPEED 0x8000 #define JEEP_MAX_BACK 0x4000 #define JEEP_STATE_LARA_STOP 0 #define JEEP_STATE_LARA_GETON 9 #define JEEP_STATE_LARA_GETOFF 10 #define JEEP_STATE_LARA_JEEPDEATH 16 #define JEEP_IN_ACCELERATE (IN_ACTION) #define JEEP_IN_BRAKE (IN_JUMP) #define JEEP_IN_DISMOUNT (IN_JUMP|IN_LEFT) #define JEEP_IN_HANDBRAKE (IN_DASH|IN_DUCK) //bool QuadHandbrakeStarting; //bool QuadCanHandbrakeStart; char JeepSmokeStart; bool JeepNoGetOff; extern LaraExtraInfo g_LaraExtra; extern Inventory* g_Inventory; int TestJeepHeight(ITEM_INFO* item, int dz, int dx, PHD_VECTOR* pos) { pos->y = item->pos.yPos - (dz * SIN(item->pos.xRot) >> W2V_SHIFT) + (dx * SIN(item->pos.zRot) >> W2V_SHIFT); int c = COS(item->pos.yRot); int s = SIN(item->pos.yRot); pos->z = item->pos.zPos + ((dz * c - dx * s) >> W2V_SHIFT); pos->x = item->pos.xPos + ((dz * s + dx * c) >> W2V_SHIFT); short roomNumber = item->roomNumber; FLOOR_INFO* floor = GetFloor(pos->x, pos->y, pos->z, &roomNumber); int ceiling = GetCeiling(floor, pos->x, pos->y, pos->z); if (pos->y < ceiling || ceiling == NO_HEIGHT) return NO_HEIGHT; return GetFloorHeight(floor, pos->x, pos->y, pos->z); } int DoJeepShift(ITEM_INFO* jeep, PHD_VECTOR* pos, PHD_VECTOR* old) { int x = pos->x >> WALL_SHIFT; int z = pos->z >> WALL_SHIFT; int oldX = old->x >> WALL_SHIFT; int oldZ = old->z >> WALL_SHIFT; int shiftX = pos->x & (WALL_SIZE - 1); int shiftZ = pos->z & (WALL_SIZE - 1); if (x == oldX) { if (z == oldZ) { jeep->pos.zPos += (old->z - pos->z); jeep->pos.xPos += (old->x - pos->x); } else if (z > oldZ) { jeep->pos.zPos -= shiftZ + 1; return (pos->x - jeep->pos.xPos); } else { jeep->pos.zPos += WALL_SIZE - shiftZ; return (jeep->pos.xPos - pos->x); } } else if (z == oldZ) { if (x > oldX) { jeep->pos.xPos -= shiftX + 1; return (jeep->pos.zPos - pos->z); } else { jeep->pos.xPos += WALL_SIZE - shiftX; return (pos->z - jeep->pos.zPos); } } else { x = 0; z = 0; short roomNumber = jeep->roomNumber; FLOOR_INFO* floor = GetFloor(old->x, pos->y, pos->z, &roomNumber); int height = GetFloorHeight(floor, old->x, pos->y, pos->z); if (height < old->y - STEP_SIZE) { if (pos->z > old->z) z = -shiftZ - 1; else z = WALL_SIZE - shiftZ; } roomNumber = jeep->roomNumber; floor = GetFloor(pos->x, pos->y, old->z, &roomNumber); height = GetFloorHeight(floor, pos->x, pos->y, old->z); if (height < old->y - STEP_SIZE) { if (pos->x > old->x) x = -shiftX - 1; else x = WALL_SIZE - shiftX; } if (x && z) { jeep->pos.zPos += z; jeep->pos.xPos += x; } else if (z) { jeep->pos.zPos += z; if (z > 0) return (jeep->pos.xPos - pos->x); else return (pos->x - jeep->pos.xPos); } else if (x) { jeep->pos.xPos += x; if (x > 0) return (pos->z - jeep->pos.zPos); else return (jeep->pos.zPos - pos->z); } else { jeep->pos.zPos += (old->z - pos->z); jeep->pos.xPos += (old->x - pos->x); } } return 0; } int DoJeepDynamics(int height, int speed, int* y, int flags) { int result = 0; if (height <= *y) { if (flags) { result = speed; } else { int temp = height - *y; if (temp < -80) { temp = -80; } result = ((temp - speed) >> 4) + speed; if (*y > height) { *y = height; } } } else { *y += speed; if (*y <= height - 32) { if (flags) { result = flags + (flags >> 1) + speed; } else { result = speed + GRAVITY; } } else { *y = height; if (speed > 150) { LaraItem->hitPoints += 150 - speed; } result = 0; } } return result; } int JeepCanGetOff() { ITEM_INFO* item = &Items[g_LaraExtra.Vehicle]; short angle = item->pos.yRot + 0x4000; int x = item->pos.xPos - (JEEP_GETOFF_DISTANCE * SIN(angle) >> W2V_SHIFT); int y = item->pos.yPos; int z = item->pos.zPos - (JEEP_GETOFF_DISTANCE * COS(angle) >> W2V_SHIFT); short roomNumber = item->roomNumber; FLOOR_INFO* floor = GetFloor(x, y, z, &roomNumber); int height = GetFloorHeight(floor, x, y, z); if ((HeightType == BIG_SLOPE) || (HeightType == DIAGONAL) || (height == NO_HEIGHT)) return 0; if (abs(height - item->pos.yPos) > WALL_SIZE / 2) return 0; int ceiling = GetCeiling(floor, x, y, z); if ((ceiling - item->pos.yPos > -LARA_HITE) || (height - ceiling < LARA_HITE)) return 0; return 1; } void TriggerJeepExhaustSmoke(int x, int y, int z, short angle, short speed, int moving) { SPARKS* spark = &Sparks[GetFreeSpark()]; spark->dR = 16; spark->dG = 16; spark->on = 1; spark->sR = 0; spark->sG = 0; spark->sB = 0; spark->dB = 32; if (moving) { spark->dR = (spark->dR * speed) >> 5; spark->dG = (spark->dG * speed) >> 5; spark->dB = (spark->dB * speed) >> 5; } spark->colFadeSpeed = 4; spark->fadeToBlack = 4; spark->life = spark->sLife = (GetRandomControl() & 3) - (speed >> 12) + 20;; if (spark->life < 9) { spark->life = 9; spark->sLife = 9; } spark->transType = 2; spark->x = (GetRandomControl() & 0xF) + x - 8; spark->y = (GetRandomControl() & 0xF) + y - 8; spark->z = (GetRandomControl() & 0xF) + z - 8; spark->xVel = speed * SIN(angle) >> (W2V_SHIFT + 2); spark->yVel = -8 - (GetRandomControl() & 7); spark->zVel = speed * COS(angle) >> (W2V_SHIFT + 2); spark->friction = 4; if (GetRandomControl() & 1) { spark->flags = 538; spark->rotAng = GetRandomControl() & 0xFFF; if (GetRandomControl() & 1) { spark->rotAdd = -24 - (GetRandomControl() & 7); } else { spark->rotAdd = (GetRandomControl() & 7) + 24; } } else { spark->flags = 522; } spark->scalar = 1; spark->gravity = -4 - (GetRandomControl() & 3); spark->maxYvel = -8 - (GetRandomControl() & 7); spark->dSize = (GetRandomControl() & 7) + (speed >> 7) + 32; spark->sSize = spark->dSize >> 1; spark->size = spark->dSize >> 1; } void InitialiseJeep(short itemNum) { ITEM_INFO* item = &Items[itemNum]; JEEP_INFO* jeep = (JEEP_INFO*)GameMalloc(sizeof(JEEP_INFO)); item->data = jeep; jeep->velocity = 0; jeep->revs = 0; jeep->jeepTurn = 0; jeep->fallSpeed = 0; jeep->extraRotation = 0; jeep->momentumAngle = item->pos.yPos; jeep->pitch = 0; jeep->flags = 0; jeep->unknown2 = 0; jeep->rot1 = 0; jeep->rot2 = 0; jeep->rot3 = 0; jeep->rot4 = 0; item->meshBits = 114687; } int JeepCheckGetOff() { if (LaraItem->currentAnimState == 10) { if (LaraItem->frameNumber == Anims[LaraItem->animNumber].frameEnd) { LaraItem->pos.yRot += ANGLE(90); LaraItem->animNumber = ANIMATION_LARA_STAY_SOLID; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; LaraItem->goalAnimState = STATE_LARA_STOP; LaraItem->currentAnimState = STATE_LARA_STOP; LaraItem->pos.xPos -= JEEP_GETOFF_DISTANCE * SIN(LaraItem->pos.yRot) >> W2V_SHIFT; LaraItem->pos.zPos -= JEEP_GETOFF_DISTANCE * COS(LaraItem->pos.yRot) >> W2V_SHIFT; LaraItem->pos.xRot = 0; LaraItem->pos.zRot = 0; g_LaraExtra.Vehicle = NO_ITEM; Lara.gunStatus = LG_NO_ARMS; CurrentAtmosphere = 110; IsAtmospherePlaying = true; S_CDPlay(110, 1); return false; } } return true; } int GetOnJeep(int itemNumber) { ITEM_INFO* item = &Items[itemNumber]; if (!(TrInput & IN_ACTION) && g_Inventory->GetSelectedObject() != ID_PUZZLE_ITEM1) { return 0; } if (item->flags & 0x100) { return 0; } if (Lara.gunStatus) { return 0; } if (LaraItem->currentAnimState != STATE_LARA_STOP) { return 0; } if (LaraItem->animNumber != ANIMATION_LARA_STAY_IDLE) { return 0; } if (LaraItem->gravityStatus) { return 0; } if (abs(item->pos.yPos - LaraItem->pos.yPos) >= 256) { return 0; } if (!TestBoundsCollide(item, LaraItem, 100)) { return 0; } _int16 roomNumber = item->roomNumber; FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); if (GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos) < -32000) return 0; short angle = ATAN(item->pos.zPos - LaraItem->pos.zPos, item->pos.xPos - LaraItem->pos.xPos); angle -= item->pos.yRot; if ((angle > -ANGLE(45)) && (angle < ANGLE(135))) { int tempAngle = LaraItem->pos.yRot - item->pos.yRot; if (tempAngle > ANGLE(45) && tempAngle < ANGLE(135)) { if (g_Inventory->GetSelectedObject() == ID_PUZZLE_ITEM1) { g_Inventory->SetSelectedObject(NO_ITEM); return 1; } else { if (g_Inventory->IsObjectPresentInInventory(ID_PUZZLE_ITEM1)) g_Inventory->SetEnterObject(ID_PUZZLE_ITEM1); return 0; } } else return 0; } else { int tempAngle = LaraItem->pos.yRot - item->pos.yRot; if (tempAngle > ANGLE(225) && tempAngle < ANGLE(315)) { if (g_Inventory->GetSelectedObject() == ID_PUZZLE_ITEM1) { g_Inventory->SetSelectedObject(NO_ITEM); return 1; } else { if (g_Inventory->IsObjectPresentInInventory(ID_PUZZLE_ITEM1)) g_Inventory->SetEnterObject(ID_PUZZLE_ITEM1); return 0; } } else return 0; } return 0; } int GetJeepCollisionAnim(ITEM_INFO* item, PHD_VECTOR* p) { p->x = item->pos.xPos - p->x; p->z = item->pos.zPos - p->z; if (p->x || p->z) { int c = COS(item->pos.yRot); int s = SIN(item->pos.yRot); int front = ((p->z * c) + (p->x * s)) >> W2V_SHIFT; int side = (-(p->z * s) + (p->x * c)) >> W2V_SHIFT; if (abs(front) > abs(side)) { return (front > 0) + 13; } else { return (side <= 0) + 11; } } return 0; } void JeepBaddieCollision(ITEM_INFO* jeep) { vector roomsList; short* door, numDoors; roomsList.push_back(jeep->roomNumber); door = Rooms[jeep->roomNumber].door; if (door) { numDoors = *door; door++; for (int i = 0; i < numDoors; i++) { roomsList.push_back(*door); door += 16; } } for (int i = 0; i < roomsList.size(); i++) { short itemNum = Rooms[roomsList[i]].itemNumber; while (itemNum != NO_ITEM) { ITEM_INFO* item = &Items[itemNum]; if (item->collidable && item->status != ITEM_INVISIBLE && item != LaraItem && item != jeep) { if (item->objectNumber == ID_ENEMY_JEEP) { Unk_0080DE1A = 0; Unk_0080DDE8 = 400; Unk_0080DE24 = Unk_0080DE24 & 0xFFDF | 0x10; //ObjectCollision(item, jeep, ) } else { OBJECT_INFO* object = &Objects[item->objectNumber]; if (object->collision && object->intelligent || item->objectNumber == ID_ROLLINGBALL) { int x = jeep->pos.xPos - item->pos.xPos; int y = jeep->pos.yPos - item->pos.yPos; int z = jeep->pos.zPos - item->pos.zPos; if (x > -2048 && x < 2048 && z > -2048 && z < 2048 && y > -2048 && y < 2048) { if (item->objectNumber == ID_ROLLINGBALL) { if (TestBoundsCollide(item, LaraItem, 100)) { if (LaraItem->hitPoints > 0) { DoLotsOfBlood(LaraItem->pos.xPos, LaraItem->pos.yPos - 512, LaraItem->pos.zPos, GetRandomControl() & 3, LaraItem->pos.yRot, LaraItem->roomNumber, 5); item->hitPoints -= 8; } } } else { if (TestBoundsCollide(item, jeep, 550)) { DoLotsOfBlood(item->pos.xPos, jeep->pos.yPos - STEP_SIZE, item->pos.zPos, GetRandomControl() & 3, jeep->pos.yRot, item->roomNumber, 3); item->hitPoints = 0; } } } } } } itemNum = item->nextItem; } } } void JeepExplode(ITEM_INFO* item) { if (Rooms[item->roomNumber].flags & ENV_FLAG_WATER) { TriggerUnderwaterExplosion(item); } else { TriggerExplosionSparks(item->pos.xPos, item->pos.yPos, item->pos.zPos, 3, -2, 0, item->roomNumber); for (int i = 0; i < 3; i++) { TriggerExplosionSparks(item->pos.xPos, item->pos.yPos, item->pos.zPos, 3, -1, 0, item->roomNumber); } } ExplodingDeath(g_LaraExtra.Vehicle, -1, 256); KillItem(g_LaraExtra.Vehicle); item->status = ITEM_DEACTIVATED; SoundEffect(SFX_EXPLOSION1, 0, 0); SoundEffect(SFX_EXPLOSION2, 0, 0); g_LaraExtra.Vehicle = NO_ITEM; } int JeepDynamics(ITEM_INFO* item) { JEEP_INFO* jeep = (JEEP_INFO*)item->data; PHD_VECTOR f_old, b_old, mm_old, mt_old, mb_old; int hf_old = TestJeepHeight(item, 550, -256, &f_old); int hb_old = TestJeepHeight(item, 550, 256,&b_old); int hmm_old = TestJeepHeight(item, -600, -256, &mm_old); int hmt_old = TestJeepHeight(item, -600, 256, &mt_old); int hmb_old = TestJeepHeight(item, -600, 0, (PHD_VECTOR*)&mb_old); PHD_VECTOR oldPos; oldPos.x = item->pos.xPos; oldPos.y = item->pos.yPos; oldPos.z = item->pos.zPos; if (mm_old.y > hmm_old) mm_old.y = hmm_old; if (mt_old.y > hmt_old) mt_old.y = hmt_old; if (f_old.y > hf_old) f_old.y = hf_old; if (b_old.y > hb_old) b_old.y = hb_old; if (mb_old.y > hmb_old) mb_old.y = hmb_old; short rot = 0; if (oldPos.y <= item->floor - 8 ) { if (jeep->jeepTurn < -91) jeep->jeepTurn += 91; else if (jeep->jeepTurn > 91) jeep->jeepTurn -= 91; else jeep->jeepTurn = 0; item->pos.yRot += jeep->jeepTurn + jeep->extraRotation; jeep->momentumAngle += (item->pos.yRot - jeep->momentumAngle) >> 5; } else { short rot2 = 0; short momentum = 0; if (jeep->jeepTurn < -ANGLE(1)) jeep->jeepTurn += ANGLE(1); else if (jeep->jeepTurn > ANGLE(1)) jeep->jeepTurn -= ANGLE(1); else jeep->jeepTurn = 0; item->pos.yRot += jeep->jeepTurn + jeep->extraRotation; rot = item->pos.yRot - jeep->momentumAngle; momentum = 728 - (3 * jeep->velocity >> 11); if (!(TrInput & IN_ACTION) && jeep->velocity > 0) momentum -= momentum >> 2; if (rot >= -273) { if (rot <= 273) jeep->momentumAngle = item->pos.yRot; else { if (rot > 13650) { item->pos.yPos -= 41; item->fallspeed = -6 - (GetRandomControl() & 3); jeep->jeepTurn = 0; jeep->velocity -= jeep->velocity >> 3; } if (rot <= 16380) jeep->momentumAngle += momentum; else jeep->momentumAngle = item->pos.yRot - 16380; } } else { if (rot < -13650) { item->pos.yPos -= 41; item->fallspeed = -6 - (GetRandomControl() & 3); jeep->jeepTurn = 0; jeep->velocity -= jeep->velocity >> 3; } if (rot >= -16380) jeep->momentumAngle -= momentum; else jeep->momentumAngle = item->pos.yRot + 16380; } } short roomNumber = item->roomNumber; FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); int height = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos); short speed; if (item->pos.yPos < height) speed = item->speed; else speed = item->speed * COS(item->pos.xRot) >> W2V_SHIFT; item->pos.xPos += (speed * SIN(jeep->momentumAngle)) >> W2V_SHIFT; item->pos.zPos += (speed * COS(jeep->momentumAngle)) >> W2V_SHIFT; int slip = 0; if (item->pos.yPos >= height) { slip = JEEP_SLIP * SIN(item->pos.xRot) >> W2V_SHIFT; if (abs(slip) > 16) { JeepNoGetOff = 1; if (slip >= 0) slip = jeep->velocity - (SQUARE(slip - 16) >> 1); else slip = (SQUARE(slip + 16) >> 1) + jeep->velocity; jeep->velocity = slip; } slip = JEEP_SLIP_SIDE * SIN(item->pos.zRot) >> W2V_SHIFT; if (abs(slip) > JEEP_SLIP_SIDE / 4) { JeepNoGetOff = 1; if (slip >= 0) { item->pos.xPos += (slip - 24) * SIN(item->pos.yRot + ANGLE(90)) >> W2V_SHIFT; item->pos.zPos += (slip - 24) * COS(item->pos.yRot + ANGLE(90)) >> W2V_SHIFT; } else { item->pos.xPos += (slip - 24) * SIN(item->pos.yRot - ANGLE(90)) >> W2V_SHIFT; item->pos.zPos += (slip - 24) * COS(item->pos.yRot - ANGLE(90)) >> W2V_SHIFT; } } } if (jeep->velocity > JEEP_MAX_SPEED) jeep->velocity = JEEP_MAX_SPEED; else if (jeep->velocity < -JEEP_MAX_BACK) jeep->velocity = -JEEP_MAX_BACK; PHD_VECTOR movedPos; movedPos.x = item->pos.xPos; movedPos.z = item->pos.zPos; if (!(item->flags & ONESHOT)) { JeepBaddieCollision(item); // v37 = sub_467850(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, 512); } PHD_VECTOR f, b, mm, mt, mb; int rot1 = 0; int rot2 = 0; int hf = TestJeepHeight(item, 550, -256, (PHD_VECTOR*)&f); if (hf < f_old.y - STEP_SIZE) rot1 = abs(4 * DoJeepShift(item, &f, &f_old)); int hmm = TestJeepHeight(item, -600, -256, (PHD_VECTOR*)&mm); if (hmm < mm_old.y - STEP_SIZE) { if (rot) rot1 += abs(4 * DoJeepShift(item, &mm, &mm_old)); else rot1 = -abs(4 * DoJeepShift(item, &mm, &mm_old)); } int hb = TestJeepHeight(item, 550, 256, (PHD_VECTOR*)&b); if (hb < b_old.y - STEP_SIZE) rot2 = -abs(4 * DoJeepShift(item, &b, &b_old)); int hmb = TestJeepHeight(item, -600, 0, (PHD_VECTOR*)&mb); if (hmb < mb_old.y - STEP_SIZE) DoJeepShift(item, &mb, &mb_old); int hmt = TestJeepHeight(item, -600, 256, (PHD_VECTOR*)&mt); if (hmt < mt_old.y - STEP_SIZE) { if (rot2) rot2 -= abs(4 * DoJeepShift(item, &mt, &mt_old)); else rot2 = abs(4 * DoJeepShift(item, &mt, &mt_old)); } if (!rot1) rot1 = rot2; roomNumber = item->roomNumber; floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); if (GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos) < item->pos.yPos - STEP_SIZE) DoJeepShift(item, (PHD_VECTOR*)&item->pos, &oldPos); if (!jeep->velocity) rot1 = 0; jeep->extraRotation = rot1; /*jeep->unknown0 += rot1 >> 1; if (abs(jeep->unknown0) < 2) jeep->unknown0 = 0; if (abs(jeep->unknown0 - jeep->extraRotation) >= 4) jeep->extraRotation += ((jeep->unknown0 - jeep->extraRotation) >> 2); else jeep->extraRotation = jeep->unknown0; */ int newspeed = 0; int collide = GetJeepCollisionAnim(item, &movedPos); if (collide) { newspeed = ((item->pos.zPos - oldPos.z) * COS(jeep->momentumAngle) + (item->pos.xPos - oldPos.x) * SIN(jeep->momentumAngle)) >> W2V_SHIFT; newspeed <<= 8; if ((&Items[g_LaraExtra.Vehicle] == item) && (jeep->velocity == JEEP_MAX_SPEED) && (newspeed < (JEEP_MAX_SPEED - 10))) { LaraItem->hitPoints -= (JEEP_MAX_SPEED - newspeed) >> 7; LaraItem->hitStatus = true; } if (jeep->velocity > 0 && newspeed < jeep->velocity) jeep->velocity = (newspeed < 0) ? 0 : newspeed; else if (jeep->velocity < 0 && newspeed > jeep->velocity) jeep->velocity = (newspeed > 0) ? 0 : newspeed; if (jeep->velocity < JEEP_MAX_BACK) jeep->velocity = JEEP_MAX_BACK; } return collide; } int JeepUserControl(ITEM_INFO* item, int height, int* pitch) { if (LaraItem->currentAnimState == 10 || LaraItem->goalAnimState == 10) TrInput = 0; JEEP_INFO* jeep = (JEEP_INFO*)item->data; if (jeep->revs <= 16) jeep->revs = 0; else { jeep->velocity += jeep->revs >> 4; jeep->revs -= (jeep->revs >> 3); } int rot1 = 0; int rot2 = 0; if (item->pos.yPos >= height - STEP_SIZE) { if (!jeep->velocity) { if (TrInput & IN_LOOK) LookUpDown(); } if (abs(jeep->velocity) <= JEEP_MAX_SPEED / 2) { rot1 = (int)ANGLE(5) * abs(jeep->velocity) >> W2V_SHIFT; rot2 = (60 * abs(jeep->velocity) >> W2V_SHIFT) + ANGLE(1); } else { rot1 = ANGLE(5); rot2 = 242; } if (jeep->velocity < 0) { if (TrInput & (IN_RIGHT | IN_RSTEP)) { jeep->jeepTurn -= rot2; if (jeep->jeepTurn < -rot1) jeep->jeepTurn = -rot1; } else if (TrInput & (IN_LEFT | IN_LSTEP)) { jeep->jeepTurn += rot2; if (jeep->jeepTurn > rot1) jeep->jeepTurn = rot1; } } else if (jeep->velocity > 0) { if (TrInput & (IN_RIGHT | IN_RSTEP)) { jeep->jeepTurn += rot2; if (jeep->jeepTurn > rot1) jeep->jeepTurn = rot1; } else if (TrInput & (IN_LEFT | IN_LSTEP)) { jeep->jeepTurn -= rot2; if (jeep->jeepTurn < -rot1) jeep->jeepTurn = -rot1; } } // Break/reverse if (TrInput & JEEP_IN_BRAKE) { if (jeep->velocity < 0) { jeep->velocity += 768; if (jeep->velocity > 0) jeep->velocity = 0; } else if (jeep->velocity > 0) { jeep->velocity -= 768; if (jeep->velocity < 0) jeep->velocity = 0; } } // Accelerate else if (TrInput & JEEP_IN_ACCELERATE) { if (jeep->unknown2) { if (jeep->unknown2 == 1 && jeep->velocity > -JEEP_MAX_BACK) { jeep->velocity -= (abs(-JEEP_MAX_BACK - jeep->velocity) >> 3) - 2; } } else { if (jeep->velocity < JEEP_MAX_SPEED) { if (jeep->velocity < 0x4000) jeep->velocity += 8 + ((0x4000 + 0x800 - jeep->velocity) >> 3); else if (jeep->velocity < 0x7000) jeep->velocity += 4 + ((0x7000 + 0x800 - jeep->velocity) >> 4); else if (jeep->velocity < JEEP_MAX_SPEED) jeep->velocity += 2 + ((JEEP_MAX_SPEED - jeep->velocity) >> 3); } else jeep->velocity = JEEP_MAX_SPEED; } jeep->velocity -= abs(item->pos.yRot - jeep->momentumAngle) >> 6; } else if (jeep->velocity > 256) { jeep->velocity -= 256; } else if (jeep->velocity < -256) { jeep->velocity += 256; } else { jeep->velocity = 0; } item->speed = jeep->velocity >> 8; if (jeep->engineRevs > 0xC000) { jeep->engineRevs = (GetRandomControl() & 0x1FF) + 48896; } int revs = jeep->velocity; if (jeep->velocity < 0) { revs >>= 1; } jeep->engineRevs += (abs(revs) - jeep->engineRevs) >> 3; } if (TrInput & JEEP_IN_BRAKE) { PHD_VECTOR pos; pos.x = 0; pos.y = -144; pos.z = -1024; GetJointAbsPosition(item, &pos, 11); TriggerDynamicLight(pos.x, pos.y, pos.z, 10, 64, 0, 0); item->meshBits = 163839; } else { item->meshBits = 114687; } *pitch = jeep->engineRevs; return 1; } void AnimateJeep(ITEM_INFO* item, int collide, int dead) { JEEP_INFO* jeep = (JEEP_INFO*)item->data; if (item->pos.yPos != item->floor && LaraItem->currentAnimState != 11 && LaraItem->currentAnimState != 12 && !dead) { if (jeep->unknown2 == 1) LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 20; else LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 6; LaraItem->currentAnimState = 11; LaraItem->goalAnimState = 11; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; } else if (collide) { if (LaraItem->currentAnimState != 4 && LaraItem->currentAnimState != 5 && LaraItem->currentAnimState != 2 && LaraItem->currentAnimState != 3 && LaraItem->currentAnimState != 11 && jeep->velocity > JEEP_MAX_SPEED / 3 && !dead) { switch (collide) { case 13: LaraItem->goalAnimState = LaraItem->currentAnimState = 4; LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 11; break; case 14: LaraItem->goalAnimState = LaraItem->currentAnimState = 5; LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 10; break; case 11: LaraItem->goalAnimState = LaraItem->currentAnimState = 2; LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 12; break; default: LaraItem->goalAnimState = LaraItem->currentAnimState = 3; LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 13; break; } LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; } } else { switch (LaraItem->currentAnimState) { case 0: if (dead) LaraItem->goalAnimState = 16; else { if (((TrInput & JEEP_IN_DISMOUNT) == JEEP_IN_DISMOUNT) && !jeep->velocity && !JeepNoGetOff) { if (JeepCanGetOff()) LaraItem->goalAnimState = 10; break; } if (!(DbInput & 0x800)) { if (!(DbInput & 0x40000000)) { if ((TrInput & JEEP_IN_ACCELERATE) && !(TrInput & JEEP_IN_BRAKE)) { LaraItem->goalAnimState = 1; break; } else if (TrInput & (IN_LEFT | IN_LSTEP)) { LaraItem->goalAnimState = 7; } else if (TrInput & (IN_RIGHT | IN_RSTEP)) { LaraItem->goalAnimState = 8; } } else if (jeep->unknown2 < 1) { jeep->unknown2++; if (jeep->unknown2 == 1) LaraItem->goalAnimState = 17; } } else { if (jeep->unknown2) jeep->unknown2--; } } break; case 1: if (dead) LaraItem->goalAnimState = 0; else { if (jeep->velocity & 0xFFFFFF00 || TrInput & (JEEP_IN_ACCELERATE | JEEP_IN_BRAKE)) { if (TrInput & JEEP_IN_BRAKE) { if (jeep->velocity <= 21844) LaraItem->goalAnimState = 0; else LaraItem->goalAnimState = 6; } else { if (TrInput & (IN_LEFT | IN_LSTEP)) { LaraItem->goalAnimState = 7; } else if (TrInput & (IN_RIGHT | IN_RSTEP)) { LaraItem->goalAnimState = 8; } } } else { LaraItem->goalAnimState = 0; } } break; case 2: case 3: case 4: case 5: if (dead) { LaraItem->goalAnimState = 0; } else if (TrInput & (JEEP_IN_ACCELERATE | JEEP_IN_BRAKE)) { LaraItem->goalAnimState = 1; } break; case 6: if (dead) { LaraItem->goalAnimState = 0; } else if (jeep->velocity & 0xFFFFFF00) { if (TrInput & (IN_LEFT | IN_LSTEP)) { LaraItem->goalAnimState = 7; } else if (TrInput & (IN_RIGHT | IN_RSTEP)) { LaraItem->goalAnimState = 8; } } else { LaraItem->goalAnimState = 0; } break; case 7: if (dead) { LaraItem->goalAnimState = 0; } else if ((DbInput & 0x80u) == 0) { if (DbInput & 0x40000000) { if (jeep->unknown2 < 1) { jeep->unknown2++; if (jeep->unknown2 == 1) { LaraItem->goalAnimState = 15; LaraItem->currentAnimState = 15; LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 40; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; break; } } } else if (TrInput & (IN_RIGHT | IN_RSTEP)) { LaraItem->goalAnimState = 1; } else if (TrInput & (IN_LEFT | IN_LSTEP)) { LaraItem->goalAnimState = 7; } else if (jeep->velocity) { LaraItem->goalAnimState = 1; } else { LaraItem->goalAnimState = 0; } } else { if (jeep->unknown2) { jeep->unknown2--; } } if (LaraItem->animNumber == Objects[ID_LARA_JEEP_ANIMS].animIndex + 4 && !jeep->velocity) { LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 32; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase + 14; } if (LaraItem->animNumber == Objects[ID_LARA_JEEP_ANIMS].animIndex + 32) { if (jeep->velocity) { LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 4; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; } } break; case 8: if (dead) { LaraItem->goalAnimState = 0; } if ((DbInput & 0x80u) == 0) { if (DbInput & 0x40000000) { if (jeep->unknown2 < 1) { jeep->unknown2++; if (jeep->unknown2 == 1) { LaraItem->goalAnimState = 14; LaraItem->currentAnimState = 14; LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 41; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; break; } } } else if (TrInput & (IN_LEFT | IN_LSTEP)) { LaraItem->goalAnimState = 1; } else if (TrInput & (IN_RIGHT | IN_RSTEP)) { LaraItem->goalAnimState = 8; } else if (jeep->velocity) { LaraItem->goalAnimState = 1; } else { LaraItem->goalAnimState = 0; } } else { if (jeep->unknown2) { jeep->unknown2--; } } if (LaraItem->animNumber == Objects[ID_LARA_JEEP_ANIMS].animIndex + 16 && !jeep->velocity) { LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 33; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase + 14; } if (LaraItem->animNumber == Objects[ID_LARA_JEEP_ANIMS].animIndex + 33) { if (jeep->velocity) { LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 16; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; } } break; case 11: if (item->pos.yPos == item->floor) { LaraItem->goalAnimState = 12; } else if (item->fallspeed > 300) { jeep->flags |= 0x40u; } break; case 13: if (dead) { LaraItem->goalAnimState = 17; } else if (abs(jeep->velocity) & 0xFFFFFF00) { if (TrInput & (IN_LEFT | IN_LSTEP)) { LaraItem->goalAnimState = 15; } else if (TrInput & (IN_RIGHT | IN_RSTEP)) { LaraItem->goalAnimState = 14; } } else { LaraItem->goalAnimState = 17; } break; case 14: if (dead) { LaraItem->goalAnimState = 17; } else if ((DbInput & 0x80u) == 0) { if (DbInput & 0x40000000) { if (jeep->unknown2 < 1) { jeep->unknown2++; } } else if (TrInput & (IN_RIGHT | IN_RSTEP)) { LaraItem->goalAnimState = 14; } else { LaraItem->goalAnimState = 13; } } else { if (jeep->unknown2) { jeep->unknown2--; if (!jeep->unknown2) { LaraItem->goalAnimState = 8; LaraItem->currentAnimState = 8; LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 44; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; break; } } } if (LaraItem->animNumber == Objects[ID_LARA_JEEP_ANIMS].animIndex + 30 && !jeep->velocity) { LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 37; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase + 14; } if (LaraItem->animNumber == Objects[ID_LARA_JEEP_ANIMS].animIndex + 37) { if (jeep->velocity) { LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 30; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; } } break; case 15: if (dead) { LaraItem->goalAnimState = 17; } else if ((DbInput & 0x80u) == 0) { if (DbInput & 0x40000000) { if (jeep->unknown2 < 1) { jeep->unknown2++; } } else if (TrInput & (IN_LEFT | IN_LSTEP)) { LaraItem->goalAnimState = 15; } else { LaraItem->goalAnimState = 13; } if (LaraItem->animNumber == Objects[ID_LARA_JEEP_ANIMS].animIndex + 27 && !jeep->velocity) { LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 36; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase + 14; } if (LaraItem->animNumber == Objects[ID_LARA_JEEP_ANIMS].animIndex + 36) { if (jeep->velocity) { LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 27; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; } } break; } else if (!jeep->unknown2 || (--jeep->unknown2 != 0)) { if (LaraItem->animNumber == Objects[ID_LARA_JEEP_ANIMS].animIndex + 27 && !jeep->velocity) { LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 36; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase + 14; } if (LaraItem->animNumber == Objects[ID_LARA_JEEP_ANIMS].animIndex + 36) { if (jeep->velocity) { LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 27; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; } } break; } LaraItem->goalAnimState = 7; LaraItem->currentAnimState = 7; LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 44; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; break; case 17: if (dead) { LaraItem->goalAnimState = 0; } if ((TrInput & JEEP_IN_DISMOUNT) != JEEP_IN_DISMOUNT || jeep->velocity || JeepNoGetOff) { if ((DbInput & 0x80u) == 0) { if (DbInput & 0x40000000) { if (jeep->unknown2 < 1) { jeep->unknown2++; } } else if (!(TrInput & JEEP_IN_ACCELERATE) || TrInput & JEEP_IN_BRAKE) { if (TrInput & (IN_LEFT | IN_LSTEP)) { LaraItem->goalAnimState = 15; } else if (TrInput & (IN_LEFT | IN_LSTEP)) { LaraItem->goalAnimState = 14; } } else { LaraItem->goalAnimState = 13; } } else { if (jeep->unknown2) { jeep->unknown2--; if (!jeep->unknown2) { LaraItem->goalAnimState = 0; } } } } else { if (JeepCanGetOff()) { LaraItem->goalAnimState = 10; } } break; default: break; } } if (Rooms[item->roomNumber].flags & ENV_FLAG_WATER) { LaraItem->goalAnimState = 11; LaraItem->hitPoints = 0; JeepExplode(item); } } void JeepCollision(short itemNumber, ITEM_INFO* l, COLL_INFO* coll) { if (l->hitPoints > 0 && g_LaraExtra.Vehicle == NO_ITEM) { ITEM_INFO* item = &Items[itemNumber]; if (GetOnJeep(itemNumber)) { g_LaraExtra.Vehicle = itemNumber; if (Lara.gunType == WEAPON_FLARE) { CreateFlare(ID_FLARE_ITEM, 0); undraw_flare_meshes(); Lara.flareControlLeft = 0; Lara.requestGunType = LG_NO_ARMS; Lara.gunType = LG_NO_ARMS; } Lara.gunStatus = LG_HANDS_BUSY; /*v4 = *(_WORD*)(Rooms + 148 * (signed short)v3->roomNumber + 72); // Enable ENEMY_JEEP if (v4 != -1) { while (1) { v5 = Items + 5622 * v4; if (*(_WORD*)(Items + 5622 * v4 + 12) == 34) { break; } v4 = *(_WORD*)(v5 + 26); if (v4 == -1) { goto LABEL_11; } } EnableBaddieAI(v4, 1); *(_DWORD*)(v5 + 5610) = *(_DWORD*)(v5 + 5610) & 0xFFFFFFFB | 2; AddActiveItem(v4); }*/ short ang = ATAN(item->pos.zPos - LaraItem->pos.zPos, item->pos.xPos - LaraItem->pos.xPos); ang -= item->pos.yRot; if ((ang > -(ONE_DEGREE * 45)) && (ang < (ONE_DEGREE * 135))) { LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 18; } else { LaraItem->animNumber = Objects[ID_LARA_JEEP_ANIMS].animIndex + 9; } LaraItem->goalAnimState = 9; LaraItem->currentAnimState = 9; LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; item->hitPoints = 1; LaraItem->pos.xPos = item->pos.xPos; LaraItem->pos.yPos = item->pos.yPos; LaraItem->pos.zPos = item->pos.zPos; LaraItem->pos.yRot = item->pos.yRot; Lara.headXrot = Lara.headYrot = 0; Lara.torsoXrot = Lara.torsoYrot = 0; Lara.hitDirection = -1; AnimateItem(l); int anim = LaraItem->animNumber; JEEP_INFO* jeep = (JEEP_INFO*)item->data; jeep->revs = 0; jeep->unknown2 = 0; item->flags |= 0x20; CurrentAtmosphere = 98; IsAtmospherePlaying = 1; S_CDPlay(98, 1); } else { ObjectCollision(itemNumber, l, coll); } } } int JeepControl() { ITEM_INFO* item = &Items[g_LaraExtra.Vehicle]; JEEP_INFO* jeep = (JEEP_INFO*)item->data; int drive = -1; bool dead = 0; int collide = JeepDynamics(item); short roomNumber = item->roomNumber; FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); GAME_VECTOR oldPos; oldPos.x = item->pos.xPos; oldPos.y = item->pos.yPos; oldPos.z = item->pos.zPos; int height = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos); int ceiling = GetCeiling(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos); PHD_VECTOR fl, fr, bc; int hfl = TestJeepHeight(item, 550, -256, &fl); int hfr = TestJeepHeight(item, 550, 256, &fr); int hbc = TestJeepHeight(item, -600, 0, &bc); roomNumber = item->roomNumber; floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); height = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos); TestTriggers(TriggerIndex, 1, 0); TestTriggers(TriggerIndex, 0, 0); if (LaraItem->hitPoints <= 0) { dead = true; TrInput &= ~(IN_LEFT | IN_RIGHT | IN_BACK | IN_FORWARD); } int pitch = 0; if (jeep->flags) { collide = 0; } else if (LaraItem->currentAnimState == 9) { drive = -1; collide = 0; } else { drive = JeepUserControl(item, height, &pitch); } if (jeep->velocity || jeep->revs) { jeep->pitch = pitch; if (pitch >= -32768) { if (pitch > 40960) { jeep->pitch = 40960; } } else { jeep->pitch = -32768; } SoundEffect(155, &item->pos, (jeep->pitch << 8) + 16777220); } else { if (drive != -1) { SoundEffect(153, &item->pos, 0); } jeep->pitch = 0; } item->floor = height; short rotAdd = jeep->velocity >> 2; jeep->rot1 -= rotAdd; jeep->rot2 -= rotAdd; jeep->rot3 -= rotAdd; jeep->rot4 -= rotAdd; int oldY = item->pos.yPos; item->fallspeed = DoJeepDynamics(height, item->fallspeed, &item->pos.yPos, 0); height = (fl.y + fr.y) >> 1; short xRot; short zRot; if (bc.y >= hbc) { if (height >= (hfl + hfr) >> 1) xRot = ATAN(1100, hbc - height); else xRot = ATAN(550, hbc - item->pos.yPos); } else { if (height >= (hfl + hfr) >> 1) { xRot = ATAN(550, item->pos.yPos - height); } else { xRot = -ATAN(137, oldY - item->pos.yPos); if (jeep->velocity < 0) xRot = -xRot; } } item->pos.xRot += (xRot - item->pos.xRot) >> 2; item->pos.zRot += (ATAN(256, height - fl.y) - item->pos.zRot) >> 2; if (!(jeep->flags & JF_DEAD)) { if (roomNumber != item->roomNumber) { ItemNewRoom(g_LaraExtra.Vehicle, roomNumber); ItemNewRoom(Lara.itemNumber, roomNumber); } LaraItem->pos.xPos = item->pos.xPos; LaraItem->pos.yPos = item->pos.yPos; LaraItem->pos.zPos = item->pos.zPos; LaraItem->pos.xRot = item->pos.xRot; LaraItem->pos.yRot = item->pos.yRot; LaraItem->pos.zRot = item->pos.zRot; int jeepAnim = Objects[ID_JEEP].animIndex; int laraAnim = LaraItem->animNumber; int extraAnim = Objects[ID_LARA_JEEP_ANIMS].animIndex; AnimateJeep(item, collide, dead); AnimateItem(LaraItem); item->animNumber = Objects[ID_JEEP].animIndex + LaraItem->animNumber - Objects[ID_LARA_JEEP_ANIMS].animIndex; item->frameNumber = Anims[item->animNumber].frameBase + (LaraItem->frameNumber - Anims[LaraItem->animNumber].frameBase); jeepAnim = Objects[ID_JEEP].animIndex; laraAnim = LaraItem->animNumber; extraAnim = Objects[ID_LARA_JEEP_ANIMS].animIndex; Camera.targetElevation = -ANGLE(30); Camera.targetDistance = 2 * WALL_SIZE; if (jeep->unknown2) { if (jeep->unknown2 == 1) jeep->fallSpeed += (32578 - jeep->fallSpeed) >> 3; } else { jeep->fallSpeed -= jeep->fallSpeed >> 3; } Camera.targetAngle = jeep->fallSpeed; if (jeep->flags & JF_FALLING && item->pos.yPos == item->floor) { LaraItem->meshBits = 0; LaraItem->hitPoints = 0; LaraItem->flags |= ONESHOT; JeepExplode(item); return 0; } } if (LaraItem->currentAnimState == 9 || LaraItem->currentAnimState == 10) { JeepSmokeStart = 0; } else { short speed = 0; short angle = 0; PHD_VECTOR pos; pos.x = 80; pos.y = 0; pos.z = -500; GetJointAbsPosition(item, &pos, 11); if (item->speed <= 32) { if (JeepSmokeStart >= 16) { if (GetRandomControl() & 3) speed = 0; else speed = ((GetRandomControl() & 0xF) + GetRandomControl() & 0x10) << 6; } else { speed = ((GetRandomControl() & 7) + GetRandomControl() & 0x10 + 2 * JeepSmokeStart) << 6; JeepSmokeStart++; } TriggerJeepExhaustSmoke(pos.x, pos.y, pos.z, item->pos.yRot + -32768, speed, 0); } else if (item->speed < 64) { TriggerJeepExhaustSmoke(pos.x, pos.y, pos.z, item->pos.yRot - 32768, 64 - item->speed, 1); } } return JeepCheckGetOff(); }