#include "newobjects.h" #include "../Game/anim.h" #include "../Game/Box.h" #include "../Game/items.h" #include "../Game/lot.h" #include "../Game/control.h" #include "../Game/people.h" #include "../Game/effects.h" #include "../Game/effect2.h" #include "../Game/draw.h" #include "../Game/sphere.h" #include "../Game/inventory.h" #include "../Game/collide.h" #include "../Game/draw.h" short StargateBounds[24] = { 0xFE00, 0x0200, 0xFC00, 0xFC80, 0xFFA0, 0x0060, 0xFE00, 0x0200, 0xFF80, 0x0000, 0xFFA0, 0x0060, 0xFE00, 0xFE80, 0xFC00, 0x0000, 0xFFA0, 0x0060, 0x0180, 0x0200, 0xFC00, 0x0000, 0xFFA0, 0x0060 }; BITE_INFO sentryGunBite = { 0, 0, 0, 8 }; void FourBladesControl(short itemNum) { ITEM_INFO* item = &Items[itemNum]; if (!TriggerActive(item)) { item->frameNumber = Anims[item->animNumber].frameBase; item->itemFlags[0] = 0; } else { short frameNumber = item->frameNumber - Anims[item->animNumber].frameBase; if (frameNumber <= 5 || frameNumber >= 58 || frameNumber >= 8 && frameNumber <= 54) item->itemFlags[0] = 0; else { if (frameNumber >= 6 && frameNumber <= 7) { item->itemFlags[3] = 20; item->itemFlags[0] = 30; } else { if (frameNumber >= 55 && frameNumber <= 57) { item->itemFlags[3] = 200; item->itemFlags[0] = 30; } } } AnimateItem(item); } } void BirdBladeControl(short itemNum) { ITEM_INFO* item = &Items[itemNum]; item->itemFlags[3] = 100; if (!TriggerActive(item)) { item->frameNumber = Anims[item->animNumber].frameBase; item->itemFlags[0] = 0; } else { short frameNumber = item->frameNumber - Anims[item->animNumber].frameBase; if (frameNumber <= 14 || frameNumber >= 31) item->itemFlags[0] = 0; else item->itemFlags[0] = 6; AnimateItem(item); } } void CatwalkBlaldeControl(short itemNum) { ITEM_INFO* item = &Items[itemNum]; if (!TriggerActive(item)) { item->frameNumber = Anims[item->animNumber].frameBase; item->itemFlags[0] = 0; } else { short frameNumber = item->frameNumber - Anims[item->animNumber].frameBase; if (item->frameNumber == Anims[item->animNumber].frameEnd || frameNumber < 38) item->itemFlags[3] = 0; else item->itemFlags[3] = 100; AnimateItem(item); } } void PlinthBladeControl(short itemNum) { ITEM_INFO* item = &Items[itemNum]; if (!TriggerActive(item)) { item->frameNumber = Anims[item->animNumber].frameBase; } else { short frameNumber = item->frameNumber - Anims[item->animNumber].frameBase; if (item->frameNumber == Anims[item->animNumber].frameEnd) item->itemFlags[3] = 0; else item->itemFlags[3] = 200; AnimateItem(item); } } void InitialiseSethBlade(short itemNum) { ITEM_INFO* item = &Items[itemNum]; item->animNumber = Objects[ID_SETH_BLADE].animIndex + 1; item->goalAnimState = 2; item->currentAnimState = 2; item->frameNumber = Anims[item->animNumber].frameBase; item->itemFlags[2] = abs(item->triggerFlags); } void SethBladeControl(short itemNum) { ITEM_INFO* item = &Items[itemNum]; item->itemFlags[0] = 0; if (TriggerActive(item)) { if (item->currentAnimState == 2) { if (item->itemFlags[2] > 1) { item->itemFlags[2]--; } else if (item->itemFlags[2] == 1) { item->goalAnimState = 1; item->itemFlags[2] = 0; } else if (!item->itemFlags[2]) { if (item->triggerFlags > 0) { item->itemFlags[2] = item->triggerFlags; } } } else { short frameNumber = item->frameNumber - Anims[item->animNumber].frameBase; if (item->frameNumber != Anims[item->animNumber].frameBase && frameNumber <= 6) { item->itemFlags[0] = -1; item->itemFlags[3] = 1000; } else if (frameNumber >= 7 && frameNumber <= 15) { item->itemFlags[0] = 448; item->itemFlags[3] = 1000; } else { item->itemFlags[0] = 0; item->itemFlags[3] = 1000; } } AnimateItem(item); } } void ChainControl(short itemNum) { ITEM_INFO* item = &Items[itemNum]; if (item->triggerFlags) { item->itemFlags[2] = 1; item->itemFlags[3] = 75; if (TriggerActive(item)) { item->itemFlags[0] = 30846; AnimateItem(item); return; } } else { item->itemFlags[3] = 25; if (TriggerActive(item)) { item->itemFlags[0] = 1920; AnimateItem(item); return; } } item->itemFlags[0] = 0; } void PloughControl(short itemNum) { ITEM_INFO* item = &Items[itemNum]; item->itemFlags[3] = 50; if (TriggerActive(item)) { item->itemFlags[0] = 258048; AnimateItem(item); } else { item->itemFlags[0] = 0; } } void CogControl(short itemNum) { ITEM_INFO* item = &Items[itemNum]; if (TriggerActive(item)) { item->status = ITEM_ACTIVE; // *(_DWORD *)&item->gap4C[5526] = *(_DWORD *)&item->gap4C[5526] & 0xFFFFFFFB | 2; AnimateItem(item); if (item->triggerFlags == 666) { PHD_VECTOR pos; GetJointAbsPosition(item, &pos, 0); SoundEffect(65, (PHD_3DPOS *)&pos, 0); if (item->frameNumber == Anims[item->animNumber].frameEnd) item->flags &= 0xC1; } } else if (item->triggerFlags == 2) { item->status |= ITEM_INVISIBLE; } } void SpikeballControl(short itemNum) { ITEM_INFO* item = &Items[itemNum]; if (TriggerActive(item)) { short frameNumber = item->frameNumber - Anims[item->animNumber].frameBase; if ((frameNumber <= 14 || frameNumber >= 24) && (frameNumber < 138 || frameNumber > 140)) { if (frameNumber < 141) item->itemFlags[0] = 0; else { item->itemFlags[3] = 50; item->itemFlags[0] = 0x7FF800; } } else { item->itemFlags[3] = 150; item->itemFlags[0] = 0x7FF800; } AnimateItem(item); } else { item->frameNumber = Anims[item->animNumber].frameBase; item->itemFlags[0] = 0; } } void StargateControl(short itemNum) { ITEM_INFO* item = &Items[itemNum]; item->itemFlags[3] = 50; if (TriggerActive(item)) { SoundEffect(SFX_TR4_STARGATE_SWIRL_ID23, &item->pos, 0); item->itemFlags[0] = 57521664; AnimateItem(item); } else item->itemFlags[0] = 0; } void StargateCollision(short itemNum, ITEM_INFO* l, COLL_INFO* c) { ITEM_INFO* item = &Items[itemNum]; if (item->status == ITEM_INVISIBLE) return; if (TestBoundsCollide(item, l, c->radius)) { for (int i = 0; i < 8; i++) { GlobalCollisionBounds.X1 = StargateBounds[3 * i + 0]; GlobalCollisionBounds.Y1 = StargateBounds[3 * i + 1]; GlobalCollisionBounds.Z1 = StargateBounds[3 * i + 2]; if (TestWithGlobalCollisionBounds(item, l, c)) ItemPushLara(item, l, c, 0, 2); } int result = TestCollision(item, l); if (result) { result &= item->itemFlags[0]; int flags = item->itemFlags[0]; if (result) { int j = 0; do { if (result & 1) { GlobalCollisionBounds.X1 = SphereList[j].x - SphereList[j].r - item->pos.xPos; GlobalCollisionBounds.Y1 = SphereList[j].y - SphereList[j].r - item->pos.yPos; GlobalCollisionBounds.Z1 = SphereList[j].z - SphereList[j].r - item->pos.zPos; GlobalCollisionBounds.X2 = SphereList[j].x + SphereList[j].r - item->pos.xPos; GlobalCollisionBounds.Y2 = SphereList[j].y + SphereList[j].r - item->pos.yPos; GlobalCollisionBounds.Z2 = SphereList[j].z + SphereList[j].r - item->pos.zPos; int oldX = LaraItem->pos.xPos; int oldY = LaraItem->pos.yPos; int oldZ = LaraItem->pos.zPos; if (ItemPushLara(item, l, c, flags & 1, 2)) { if ((flags & 1) && (oldX != LaraItem->pos.xPos || oldY != LaraItem->pos.yPos || oldZ != LaraItem->pos.zPos) && TriggerActive(item)) { DoBloodSplat((GetRandomControl() & 0x3F) + l->pos.xPos - 32, (GetRandomControl() & 0x1F) + SphereList[j].y - 16, (GetRandomControl() & 0x3F) + l->pos.zPos - 32, (GetRandomControl() & 3) + 2, 2 * GetRandomControl(), l->roomNumber); LaraItem->hitPoints -= 100; } } } result >>= 1; j++; flags >>= 1; } while (result); } } } } void ControlSpikyWall(short itemNum) { ITEM_INFO* item = &Items[itemNum]; /* Move wall */ if (TriggerActive(item) && item->status != ITEM_DEACTIVATED) { int x = item->pos.xPos + SIN(item->pos.yRot) >> WALL_SHIFT; int z = item->pos.zPos + COS(item->pos.yRot) >> WALL_SHIFT; short roomNumber = item->roomNumber; FLOOR_INFO* floor = GetFloor(x, item->pos.yPos, z, &roomNumber); if (GetFloorHeight(floor, x, item->pos.yPos, z) != item->pos.yPos) { item->status = ITEM_DEACTIVATED; StopSoundEffect(SFX_ROLLING_BALL); } else { item->pos.xPos = x; item->pos.zPos = z; if (roomNumber != item->roomNumber) ItemNewRoom(itemNum, roomNumber); SoundEffect(SFX_ROLLING_BALL, &item->pos, 0); } } if (item->touchBits) { LaraItem->hitPoints -= 15; LaraItem->hitStatus = true; DoLotsOfBlood(LaraItem->pos.xPos, LaraItem->pos.yPos - 512, LaraItem->pos.zPos, 4, item->pos.yRot, LaraItem->roomNumber, 3); item->touchBits = 0; SoundEffect(56, &item->pos, 0); } } void InitialiseSpinningBlade(short item_number) { ITEM_INFO* item = &Items[item_number]; item->animNumber = Objects[item->objectNumber].animIndex + 3; item->frameNumber = Anims[item->animNumber].frameBase; item->currentAnimState = 1; } void SpinningBlade(short item_number) { bool spinning = false; ITEM_INFO* item = &Items[item_number]; if (item->currentAnimState == 2) { if (item->goalAnimState != 1) { int x = item->pos.xPos + (WALL_SIZE * 3 / 2 * SIN(item->pos.yRot) >> W2V_SHIFT); int z = item->pos.zPos + (WALL_SIZE * 3 / 2 * COS(item->pos.yRot) >> W2V_SHIFT); short roomNumber = item->roomNumber; FLOOR_INFO* floor = GetFloor(x, item->pos.yPos, z, &roomNumber); int height = GetFloorHeight(floor, x, item->pos.yPos, z); if (height == NO_HEIGHT) item->goalAnimState = 1; } spinning = true; if (item->touchBits) { LaraItem->hitStatus = true; LaraItem->hitPoints -= 100; DoLotsOfBlood(LaraItem->pos.xPos, LaraItem->pos.yPos - STEP_SIZE * 2, LaraItem->pos.zPos, (short)(item->speed * 2), LaraItem->pos.yRot, LaraItem->roomNumber, 2); } SoundEffect(231, &item->pos, 0); } else { if (TriggerActive(item)) item->goalAnimState = 2; spinning = false; } AnimateItem(item); short roomNumber = item->roomNumber; FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); item->floor = item->pos.yPos = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos); if (roomNumber != item->roomNumber) ItemNewRoom(item_number, roomNumber); if (spinning && item->currentAnimState == 1) item->pos.yRot += -ANGLE(180); } void InitialiseKillerStatue(short item_number) { ITEM_INFO* item = &Items[item_number]; item->animNumber = Objects[item->objectNumber].animIndex + 3; item->frameNumber = Anims[item->animNumber].frameBase; item->currentAnimState = 1; } void KillerStatueControl(short item_number) { ITEM_INFO *item; int x, y, z; short d; item = &Items[item_number]; if (TriggerActive(item) && item->currentAnimState == 1) item->goalAnimState = 2; else item->goalAnimState = 1; if ((item->touchBits & 0x80) && item->currentAnimState == 2) { LaraItem->hitStatus = 1; LaraItem->hitPoints -= 20; int x = LaraItem->pos.xPos + (GetRandomControl() - 16384) / 256; int z = LaraItem->pos.zPos + (GetRandomControl() - 16384) / 256; int y = LaraItem->pos.yPos - GetRandomControl() / 44; int d = (GetRandomControl() - 16384) / 8 + LaraItem->pos.yRot; DoBloodSplat(x, y, z, LaraItem->speed, d, LaraItem->roomNumber); } AnimateItem(item); } void SpringBoardControl(short item_number) { ITEM_INFO* item = &Items[item_number]; if (item->currentAnimState == 0 && LaraItem->pos.yPos == item->pos.yPos && (LaraItem->pos.xPos >> WALL_SHIFT) == (item->pos.xPos >> WALL_SHIFT) && (LaraItem->pos.zPos >> WALL_SHIFT) == (item->pos.zPos >> WALL_SHIFT)) { if (LaraItem->hitPoints <= 0) return; if (LaraItem->currentAnimState == STATE_LARA_WALK_BACK || LaraItem->currentAnimState == STATE_LARA_RUN_BACK) LaraItem->speed = -LaraItem->speed; LaraItem->fallspeed = -240; LaraItem->gravityStatus = true; LaraItem->animNumber = ANIMATION_LARA_FREE_FALL_FORWARD; LaraItem->frameNumber = GF2(ID_LARA, ANIMATION_LARA_FREE_FALL_FORWARD, 0); LaraItem->currentAnimState = STATE_LARA_JUMP_FORWARD; LaraItem->goalAnimState = STATE_LARA_JUMP_FORWARD; item->goalAnimState = 1; } AnimateItem(item); } void InitialiseSlicerDicer(short itemNum) { ITEM_INFO* item = &Items[itemNum]; int dx = SIN(item->pos.yRot + ANGLE(90)) >> 5; int dz = COS(item->pos.yRot + ANGLE(90)) >> 5; item->pos.xPos += dx; item->pos.zPos += dz; item->itemFlags[0] = item->pos.xPos >> 8; item->itemFlags[1] = (item->pos.yPos - 4608) >> 8; item->itemFlags[2] = item->pos.zPos >> 8; item->itemFlags[3] = 50; } void SlicerDicerControl(short itemNum) { ITEM_INFO* item = &Items[itemNum]; SoundEffect(SFX_TR4_METAL_SCRAPE_LOOP_2_ID20, &item->pos, 0); SoundEffect(SFX_TR4_METAL_SCRAPE_LOOP_1_ID12, &item->pos, 0); int factor = (9 * COS(item->triggerFlags) << 9 >> W2V_SHIFT) * COS(item->pos.yRot) >> W2V_SHIFT; item->pos.xPos = (item->itemFlags[0] << 8) + factor; item->pos.yPos = (item->itemFlags[1] << 8) - 4608 * SIN(item->triggerFlags); item->pos.zPos = (item->itemFlags[2] << 8) + factor; item->triggerFlags += 170; short roomNumber = item->roomNumber; GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); if (item->roomNumber != roomNumber) ItemNewRoom(itemNum, roomNumber); AnimateItem(item); } void BladeCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) { ITEM_INFO* item = &Items[itemNum]; if (item->status == ITEM_INVISIBLE) return; if (item->itemFlags[3]) // Check this { if (TestBoundsCollide(item, l, coll->radius)) { int oldX = LaraItem->pos.xPos; int oldY = LaraItem->pos.yPos; int oldZ = LaraItem->pos.zPos; int dx = 0; int dy = 0; int dz = 0; if (ItemPushLara(item, l, coll, 1, 1)) { LaraItem->hitPoints -= item->itemFlags[3]; dx = oldX - LaraItem->pos.xPos; dy = oldY - LaraItem->pos.yPos; dz = oldZ - LaraItem->pos.zPos; if ((dx || dy || dz) && TriggerActive(item)) { DoBloodSplat((GetRandomControl() & 0x3F) + l->pos.xPos - 32, l->pos.yPos - (GetRandomControl() & 0x1FF) - 256, (GetRandomControl() & 0x3F) + l->pos.zPos - 32, (GetRandomControl() & 3) + (item->itemFlags[3] >> 5) + 2, 2 * GetRandomControl(), l->roomNumber); } if (!coll->enableBaddiePush) { LaraItem->pos.xPos += dx; LaraItem->pos.yPos += dy; LaraItem->pos.zPos += dz; } } } } } void InitialiseMine(short itemNum) { ITEM_INFO* item = &Items[itemNum]; if (item->triggerFlags) item->meshBits = 0; } void MineControl(short itemNum) { ITEM_INFO* item = &Items[itemNum]; int num = GetSpheres(item, SphereList, true); if (item->itemFlags[0] >= 150) { SoundEffect(SFX_EXPLOSION1, &item->pos, 0); SoundEffect(SFX_EXPLOSION2, &item->pos, 0); SoundEffect(SFX_EXPLOSION1, &item->pos, 0x1800004); if (num > 0) { SPHERE* sphere = &SphereList[0]; for (int i = 0; i < num; i++) { if (i >= 7 && i != 9) { TriggerExplosionSparks(sphere->x, sphere->y, sphere->z, 3, -2, 0, -item->roomNumber); TriggerExplosionSparks(sphere->x, sphere->y, sphere->z, 3, -1, 0, -item->roomNumber); TriggerShockwave((PHD_3DPOS*)sphere, 19922992, (GetRandomControl() & 0x1F) + 112, 545284096, 2048, 0); } sphere++; } for (int i = 0; i < num; i++) ExplodeItemNode(item, i, 0, -128); } FlashFadeR = 255; FlashFadeG = 192; FlashFadeB = 64; FlashFader = 32; short currentItemNumber = Rooms[item->roomNumber].itemNumber; // Make the sentry gun explode? while (currentItemNumber != NO_ITEM) { ITEM_INFO* currentItem = &Items[currentItemNumber]; if (currentItem->objectNumber == ID_SENTRY_GUN) currentItem->meshBits &= ~0x40; currentItemNumber = currentItem->nextItem; } KillItem(itemNum); } else { item->itemFlags[0]++; int something = 4 * item->itemFlags[0]; if (something > 255) something = 0; for (int i = 0; i < num; i++) { SPHERE* sphere = &SphereList[i]; if (i == 0 || i > 5) AddFire(sphere->x, sphere->y, sphere->z, 2, item->roomNumber, something); sphere++; } SoundEffect(SFX_LOOP_FOR_SMALL_FIRES, &item->pos, 0); } } void MineCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) { ITEM_INFO* item = &Items[itemNum]; if (item->triggerFlags && !item->itemFlags[3]) { if (l->animNumber != 432 || l->frameNumber < Anims[item->animNumber].frameBase + 57) { if (TestBoundsCollide(item, l, 512)) { TriggerExplosionSparks(item->pos.xPos, item->pos.yPos, item->pos.zPos, 3, -2, 0, item->roomNumber); for (int i = 0; i < 2; i++) TriggerExplosionSparks(item->pos.xPos, item->pos.yPos, item->pos.zPos, 3, -1, 0, item->roomNumber); item->meshBits = 1; ExplodeItemNode(item, 0, 0, 128); KillItem(itemNum); l->animNumber = 438; l->frameNumber = Anims[item->animNumber].frameBase; l->currentAnimState = 8; l->speed = 0; SoundEffect(SFX_TR4_MINE_EXPLOSION_OVERLAY_ID103, &item->pos, 0); } } else { for (int i = 0; i < LevelItems; i++) { ITEM_INFO* currentItem = &Items[i]; // Explode other mines if (currentItem->objectNumber == ID_MINE && currentItem->status != ITEM_INVISIBLE && !currentItem->triggerFlags) { TriggerExplosionSparks( currentItem->pos.xPos, currentItem->pos.yPos, currentItem->pos.zPos, 3, -2, 0, currentItem->roomNumber); for (int j = 0; j < 2; j++) TriggerExplosionSparks( currentItem->pos.xPos, currentItem->pos.yPos, currentItem->pos.zPos, 3, -1, 0, currentItem->roomNumber); currentItem->meshBits = 1; ExplodeItemNode(currentItem, 0, 0, -32); KillItem(i); if (!(GetRandomControl() & 3)) SoundEffect(SFX_TR4_MINE_EXPLOSION_OVERLAY_ID103, ¤tItem->pos, 0); currentItem->status = ITEM_INVISIBLE; } } } } } void InitialiseSentryGun(short itemNum) { ITEM_INFO* item = &Items[itemNum]; ClearItem(itemNum); item->itemFlags[0] = 0; item->itemFlags[1] = 768; item->itemFlags[2] = 0; } void SentryGunControl(short itemNum) { ITEM_INFO* item = &Items[itemNum]; if (!CreatureActive(itemNum)) return; CREATURE_INFO* creature = (CREATURE_INFO*)item->data; AI_INFO info; int c = 0; if (creature) { // Flags set by the ID_MINE object? if (item->meshBits & 0x40) { if (item->itemFlags[0]) { PHD_VECTOR pos; pos.x = sentryGunBite.x; pos.y = sentryGunBite.y; pos.z = sentryGunBite.z; GetJointAbsPosition(item, &pos, sentryGunBite.meshNum); TriggerDynamicLight(pos.x, pos.y, pos.z, 4 * item->itemFlags[0] + 12, 24, 16, 4); item->itemFlags[0]--; } if (item->itemFlags[0] & 1) item->meshBits |= 0x100; else item->meshBits &= ~0x100; if (item->triggerFlags == 0) { item->pos.yPos -= 512; CreatureAIInfo(item, &info); item->pos.yPos += 512; int deltaAngle = info.angle - creature->jointRotation[0]; //printf("Angle: %d\n", (int)TR_ANGLE_TO_DEGREES(info.angle)); info.ahead = true; if (deltaAngle <= -ANGLE(90) || deltaAngle >= ANGLE(90)) info.ahead = false; if (Targetable(item, &info)) { if (info.distance < SQUARE(9 * WALL_SIZE)) { if (!ObjectInInventory(ID_PUZZLE_ITEM5) && !item->itemFlags[0]) { if (info.distance <= SQUARE(2048)) { // Throw fire SentryGunThrowFire(item); c = 4 * rcossin_tbl[(GlobalCounter & 0x1F) << 11 >> 3] >> 2; } else { // Shot to Lara with bullets c = 0; item->itemFlags[0] = 2; ShotLara(item, &info, &sentryGunBite, creature->jointRotation[0], 5); SoundEffect(SFX_TR4_AUTOGUNS_ID358, &item->pos, 0); item->itemFlags[2] += 256; if (item->itemFlags[2] > 6144) { item->itemFlags[2] = 6144; } } } deltaAngle = c + info.angle - creature->jointRotation[0]; if (deltaAngle <= ANGLE(10)) { if (deltaAngle < -ANGLE(10)) { deltaAngle = -ANGLE(10); } } else { deltaAngle = ANGLE(10); } creature->jointRotation[0] += deltaAngle; CreatureJoint(item, 1, -info.xAngle); } } item->itemFlags[2] -= 32; if (item->itemFlags[2] < 0) { item->itemFlags[2] = 0; } creature->jointRotation[3] += item->itemFlags[2]; creature->jointRotation[2] += item->itemFlags[1]; if (creature->jointRotation[2] > ANGLE(90) || creature->jointRotation[2] < -ANGLE(90)) { item->itemFlags[1] = -item->itemFlags[1]; } } else { // Stuck sentry gun CreatureJoint(item, 0, (GetRandomControl() & 0x7FF) - 1024); CreatureJoint(item, 1, ANGLE(45)); CreatureJoint(item, 2, (GetRandomControl() & 0x3FFF) - ANGLE(45)); } } else { ExplodingDeath(itemNum, -1, 257); DisableBaddieAI(itemNum); KillItem(itemNum); item->flags |= 1u; item->status = ITEM_DEACTIVATED; RemoveAllItemsInRoom(item->roomNumber, ID_SMOKE_EMITTER_BLACK); TriggerExplosionSparks(item->pos.xPos, item->pos.yPos - 768, item->pos.zPos, 3, -2, 0, item->roomNumber); for (int i = 0; i < 2; i++) TriggerExplosionSparks(item->pos.xPos, item->pos.yPos - 768, item->pos.zPos, 3, -1, 0, item->roomNumber); SoundEffect(SFX_EXPLOSION1, &item->pos, 25165828); SoundEffect(SFX_EXPLOSION2, &item->pos, 0); } } } void SentryGunThrowFire(ITEM_INFO* item) { for (int i = 0; i < 3; i++) { SPARKS* spark = &Sparks[GetFreeSpark()]; spark->on = 1; spark->sR = (GetRandomControl() & 0x1F) + 48; spark->sG = 48; spark->sB = 255; spark->dR = (GetRandomControl() & 0x3F) - 64; spark->dG = (GetRandomControl() & 0x3F) + -128; spark->dB = 32; spark->colFadeSpeed = 12; spark->fadeToBlack = 8; spark->transType = 2; spark->life = spark->sLife = (GetRandomControl() & 0x1F) + 16; PHD_VECTOR pos1; pos1.x = -140; pos1.y = -30; pos1.z = -4; GetJointAbsPosition(item, &pos1, 7); spark->x = (GetRandomControl() & 0x1F) + pos1.x - 16; spark->y = (GetRandomControl() & 0x1F) + pos1.y - 16; spark->z = (GetRandomControl() & 0x1F) + pos1.z - 16; PHD_VECTOR pos2; pos2.x = -280; pos2.y = -30; pos2.z = -4; GetJointAbsPosition(item, &pos2, 7); int v = (GetRandomControl() & 0x3F) + 192; spark->xVel = v * (pos2.x - pos1.x) / 10; spark->yVel = v * (pos2.y - pos1.y) / 10; spark->zVel = v * (pos2.z - pos1.z) / 10; spark->friction = 85; spark->gravity = -16 - (GetRandomControl() & 0x1F); spark->maxYvel = 0; spark->flags = 538; if ((GlobalCounter & 1) != 0) { v = 255; spark->flags = 539; } spark->scalar = 3; spark->dSize = v * ((GetRandomControl() & 7) + 60) >> 8; spark->sSize = spark->dSize >> 4; spark->size = spark->dSize >> 4; } } void InitialiseBurningFloor(short itemNum) { Items[itemNum].requiredAnimState = 127; } void BurningFloorControl(short itemNum) { } void ControlSpikyCeiling(short itemNumber) { ITEM_INFO* item = &Items[itemNumber]; if (TriggerActive(item) && item->status != ITEM_DEACTIVATED) { int y = item->pos.yPos + ((item->itemFlags[0] == 1) ? 10 : 5); short roomNumber = item->roomNumber; FLOOR_INFO* floor = GetFloor(item->pos.xPos, y, item->pos.zPos, &roomNumber); if (GetFloorHeight(floor, item->pos.xPos, y, item->pos.zPos) < y + 1024) { item->status = ITEM_DEACTIVATED; StopSoundEffect(147); } else { item->pos.yPos = y; if (roomNumber != item->roomNumber) ItemNewRoom(itemNumber, roomNumber); SoundEffect(147, &item->pos, 0); } } if (item->touchBits) { LaraItem->hitPoints -= 20; LaraItem->hitStatus = true; DoLotsOfBlood(LaraItem->pos.xPos, item->pos.yPos + 768, LaraItem->pos.zPos, 4, item->pos.yRot, LaraItem->roomNumber, 3); item->touchBits = 0; SoundEffect(56, &item->pos, 0); } if (TriggerActive(item) && item->status != ITEM_DEACTIVATED && item->itemFlags[0] == 1) AnimateItem(item); }