mirror of
https://github.com/LostArtefacts/TRX.git
synced 2025-05-02 14:47:58 +03:00
refactor traps.c
This commit is contained in:
parent
65f0e220cd
commit
a10ed3e961
43 changed files with 1784 additions and 1563 deletions
|
@ -10,10 +10,10 @@
|
|||
#include "game/items.h"
|
||||
#include "game/lara.h"
|
||||
#include "game/lot.h"
|
||||
#include "game/moveblock.h"
|
||||
#include "game/pickup.h"
|
||||
#include "game/savegame.h"
|
||||
#include "game/traps.h"
|
||||
#include "game/traps/lava.h"
|
||||
#include "game/traps/movable_block.h"
|
||||
#include "game/vars.h"
|
||||
#include "specific/input.h"
|
||||
#include "specific/shed.h"
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef T1M_GAME_LIGHTNING_H
|
||||
#define T1M_GAME_LIGHTNING_H
|
||||
|
||||
#include "game/types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void DrawLightning(ITEM_INFO *item);
|
||||
void InitialiseLightning(int16_t item_num);
|
||||
void LightningControl(int16_t item_num);
|
||||
void LightningCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
|
||||
void InitialiseThorsHandle(int16_t item_num);
|
||||
void ThorsHandleControl(int16_t item_num);
|
||||
void ThorsHandleCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
void ThorsHeadCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
|
||||
void T1MInjectGameLightning();
|
||||
|
||||
#endif
|
70
src/game/objects/trapdoor.c
Normal file
70
src/game/objects/trapdoor.c
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include "game/objects/trapdoor.h"
|
||||
#include "game/control.h"
|
||||
#include "game/vars.h"
|
||||
|
||||
void SetupTrapDoor(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->control = TrapDoorControl;
|
||||
obj->floor = TrapDoorFloor;
|
||||
obj->ceiling = TrapDoorCeiling;
|
||||
obj->save_anim = 1;
|
||||
obj->save_flags = 1;
|
||||
}
|
||||
|
||||
void TrapDoorControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (TriggerActive(item)) {
|
||||
if (item->current_anim_state == DOOR_CLOSED) {
|
||||
item->goal_anim_state = DOOR_OPEN;
|
||||
}
|
||||
} else if (item->current_anim_state == DOOR_OPEN) {
|
||||
item->goal_anim_state = DOOR_CLOSED;
|
||||
}
|
||||
AnimateItem(item);
|
||||
}
|
||||
|
||||
void TrapDoorFloor(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height)
|
||||
{
|
||||
if (!OnTrapDoor(item, x, z)) {
|
||||
return;
|
||||
}
|
||||
if (y <= item->pos.y && item->current_anim_state == DOOR_CLOSED
|
||||
&& item->pos.y < *height) {
|
||||
*height = item->pos.y;
|
||||
}
|
||||
}
|
||||
|
||||
void TrapDoorCeiling(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height)
|
||||
{
|
||||
if (!OnTrapDoor(item, x, z)) {
|
||||
return;
|
||||
}
|
||||
if (y > item->pos.y && item->current_anim_state == DOOR_CLOSED
|
||||
&& item->pos.y > *height) {
|
||||
*height = (int16_t)item->pos.y + STEP_L;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t OnTrapDoor(ITEM_INFO *item, int32_t x, int32_t z)
|
||||
{
|
||||
x >>= WALL_SHIFT;
|
||||
z >>= WALL_SHIFT;
|
||||
int32_t tx = item->pos.x >> WALL_SHIFT;
|
||||
int32_t tz = item->pos.z >> WALL_SHIFT;
|
||||
if (item->pos.y_rot == 0 && x == tx && (z == tz || z == tz + 1)) {
|
||||
return 1;
|
||||
} else if (
|
||||
item->pos.y_rot == -PHD_180 && x == tx && (z == tz || z == tz - 1)) {
|
||||
return 1;
|
||||
} else if (
|
||||
item->pos.y_rot == PHD_90 && z == tz && (x == tx || x == tx + 1)) {
|
||||
return 1;
|
||||
} else if (
|
||||
item->pos.y_rot == -PHD_90 && z == tz && (x == tx || x == tx - 1)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
15
src/game/objects/trapdoor.h
Normal file
15
src/game/objects/trapdoor.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef T1M_GAME_OBJECTS_TRAPDOOR_H
|
||||
#define T1M_GAME_OBJECTS_TRAPDOOR_H
|
||||
|
||||
#include "game/types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void SetupTrapDoor(OBJECT_INFO *obj);
|
||||
void TrapDoorControl(int16_t item_num);
|
||||
void TrapDoorFloor(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height);
|
||||
void TrapDoorCeiling(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height);
|
||||
int32_t OnTrapDoor(ITEM_INFO *item, int32_t x, int32_t z);
|
||||
|
||||
#endif
|
|
@ -67,21 +67,6 @@ static int16_t PickUpScion4Bounds[12] = {
|
|||
0,
|
||||
};
|
||||
|
||||
static int16_t MidasBounds[12] = {
|
||||
-700,
|
||||
+700,
|
||||
+384 - 100,
|
||||
+384 + 100 + 512,
|
||||
-700,
|
||||
+700,
|
||||
-10 * PHD_DEGREE,
|
||||
+10 * PHD_DEGREE,
|
||||
-30 * PHD_DEGREE,
|
||||
+30 * PHD_DEGREE,
|
||||
-10 * PHD_DEGREE,
|
||||
+10 * PHD_DEGREE,
|
||||
};
|
||||
|
||||
static int16_t Switch1Bounds[12] = {
|
||||
-200,
|
||||
+200,
|
||||
|
@ -284,71 +269,6 @@ void PickUpScion4Collision(
|
|||
}
|
||||
}
|
||||
|
||||
void MidasCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
|
||||
if (!lara_item->gravity_status && lara_item->current_anim_state == AS_STOP
|
||||
&& lara_item->pos.x > item->pos.x - 512
|
||||
&& lara_item->pos.x < item->pos.x + 512
|
||||
&& lara_item->pos.z > item->pos.z - 512
|
||||
&& lara_item->pos.z < item->pos.z + 512) {
|
||||
lara_item->current_anim_state = AS_DIEMIDAS;
|
||||
lara_item->goal_anim_state = AS_DIEMIDAS;
|
||||
lara_item->anim_number = Objects[O_LARA_EXTRA].anim_index + 1;
|
||||
lara_item->frame_number = Anims[lara_item->anim_number].frame_base;
|
||||
lara_item->hit_points = -1;
|
||||
lara_item->gravity_status = 0;
|
||||
Lara.air = -1;
|
||||
Lara.gun_status = LGS_HANDSBUSY;
|
||||
Lara.gun_type = LGT_UNARMED;
|
||||
Camera.type = CAM_CINEMATIC;
|
||||
CineFrame = 0;
|
||||
CinematicPosition = lara_item->pos;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((InventoryChosen == -1 && !CHK_ANY(Input, IN_ACTION))
|
||||
|| Lara.gun_status != LGS_ARMLESS || lara_item->gravity_status
|
||||
|| lara_item->current_anim_state != AS_STOP) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t quadrant = (uint16_t)(lara_item->pos.y_rot + PHD_45) / PHD_90;
|
||||
switch (quadrant) {
|
||||
case DIR_NORTH:
|
||||
item->pos.y_rot = 0;
|
||||
break;
|
||||
case DIR_EAST:
|
||||
item->pos.y_rot = PHD_90;
|
||||
break;
|
||||
case DIR_SOUTH:
|
||||
item->pos.y_rot = -PHD_180;
|
||||
break;
|
||||
case DIR_WEST:
|
||||
item->pos.y_rot = -PHD_90;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!TestLaraPosition(MidasBounds, item, lara_item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (InventoryChosen == -1) {
|
||||
Display_Inventory(INV_KEYS_MODE);
|
||||
}
|
||||
|
||||
if (InventoryChosen == O_LEADBAR_OPTION) {
|
||||
Inv_RemoveItem(O_LEADBAR_OPTION);
|
||||
Inv_AddItem(O_PUZZLE_ITEM1);
|
||||
lara_item->current_anim_state = AS_USEMIDAS;
|
||||
lara_item->goal_anim_state = AS_USEMIDAS;
|
||||
lara_item->anim_number = Objects[O_LARA_EXTRA].anim_index;
|
||||
lara_item->frame_number = Anims[item->anim_number].frame_base;
|
||||
Lara.gun_status = LGS_HANDSBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
void SwitchCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
|
@ -743,7 +663,6 @@ void T1MInjectGamePickup()
|
|||
INJECT(0x00433080, PickUpCollision);
|
||||
INJECT(0x00433240, PickUpScionCollision);
|
||||
INJECT(0x004333B0, PickUpScion4Collision);
|
||||
INJECT(0x004334C0, MidasCollision);
|
||||
INJECT(0x004336F0, SwitchCollision);
|
||||
INJECT(0x00433810, SwitchCollision2);
|
||||
INJECT(0x00433900, KeyHoleCollision);
|
||||
|
|
|
@ -9,7 +9,6 @@ void PickUpScionCollision(
|
|||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
void PickUpScion4Collision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
void MidasCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
void SwitchCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
void SwitchCollision2(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
void KeyHoleCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
#include "game/ai/pod.h"
|
||||
#include "game/traps/movable_block.h"
|
||||
#include "game/traps/rolling_block.h"
|
||||
#include "game/control.h"
|
||||
#include "game/gameflow.h"
|
||||
#include "game/inv.h"
|
||||
#include "game/items.h"
|
||||
#include "game/lara.h"
|
||||
#include "game/lot.h"
|
||||
#include "game/moveblock.h"
|
||||
#include "game/pickup.h"
|
||||
#include "game/savegame.h"
|
||||
#include "game/traps.h"
|
||||
#include "game/vars.h"
|
||||
#include "game/warrior.h"
|
||||
#include "specific/shed.h"
|
||||
|
|
190
src/game/setup.c
190
src/game/setup.c
|
@ -35,16 +35,30 @@
|
|||
#include "game/inv.h"
|
||||
#include "game/items.h"
|
||||
#include "game/lara.h"
|
||||
#include "game/lightning.h"
|
||||
#include "game/lot.h"
|
||||
#include "game/moveblock.h"
|
||||
#include "game/objects.h"
|
||||
#include "game/objects/gunshot.h"
|
||||
#include "game/objects/trapdoor.h"
|
||||
#include "game/pickup.h"
|
||||
#include "game/savegame.h"
|
||||
#include "game/setup.h"
|
||||
#include "game/text.h"
|
||||
#include "game/traps.h"
|
||||
#include "game/traps/damocles_sword.h"
|
||||
#include "game/traps/dart.h"
|
||||
#include "game/traps/dart_emitter.h"
|
||||
#include "game/traps/falling_block.h"
|
||||
#include "game/traps/falling_ceiling.h"
|
||||
#include "game/traps/flame.h"
|
||||
#include "game/traps/lava.h"
|
||||
#include "game/traps/lightning_emitter.h"
|
||||
#include "game/traps/midas_touch.h"
|
||||
#include "game/traps/movable_block.h"
|
||||
#include "game/traps/pendulum.h"
|
||||
#include "game/traps/rolling_ball.h"
|
||||
#include "game/traps/rolling_block.h"
|
||||
#include "game/traps/spikes.h"
|
||||
#include "game/traps/teeth_trap.h"
|
||||
#include "game/traps/thors_hammer.h"
|
||||
#include "game/types.h"
|
||||
#include "game/vars.h"
|
||||
#include "game/warrior.h"
|
||||
|
@ -185,138 +199,31 @@ void BaddyObjects()
|
|||
|
||||
void TrapObjects()
|
||||
{
|
||||
Objects[O_FALLING_BLOCK].control = FallingBlockControl;
|
||||
Objects[O_FALLING_BLOCK].floor = FallingBlockFloor;
|
||||
Objects[O_FALLING_BLOCK].ceiling = FallingBlockCeiling;
|
||||
Objects[O_FALLING_BLOCK].save_position = 1;
|
||||
Objects[O_FALLING_BLOCK].save_anim = 1;
|
||||
Objects[O_FALLING_BLOCK].save_flags = 1;
|
||||
|
||||
Objects[O_PENDULUM].control = PendulumControl;
|
||||
Objects[O_PENDULUM].collision = TrapCollision;
|
||||
Objects[O_PENDULUM].shadow_size = UNIT_SHADOW / 2;
|
||||
Objects[O_PENDULUM].save_flags = 1;
|
||||
Objects[O_PENDULUM].save_anim = 1;
|
||||
|
||||
Objects[O_TEETH_TRAP].control = TeethTrapControl;
|
||||
Objects[O_TEETH_TRAP].collision = TrapCollision;
|
||||
Objects[O_TEETH_TRAP].save_flags = 1;
|
||||
Objects[O_TEETH_TRAP].save_anim = 1;
|
||||
|
||||
Objects[O_ROLLING_BALL].initialise = InitialiseRollingBall;
|
||||
Objects[O_ROLLING_BALL].control = RollingBallControl;
|
||||
Objects[O_ROLLING_BALL].collision = RollingBallCollision;
|
||||
Objects[O_ROLLING_BALL].save_position = 1;
|
||||
Objects[O_ROLLING_BALL].save_anim = 1;
|
||||
Objects[O_ROLLING_BALL].save_flags = 1;
|
||||
|
||||
Objects[O_SPIKES].collision = SpikeCollision;
|
||||
|
||||
Objects[O_FALLING_CEILING1].control = FallingCeilingControl;
|
||||
Objects[O_FALLING_CEILING1].collision = TrapCollision;
|
||||
Objects[O_FALLING_CEILING1].save_position = 1;
|
||||
Objects[O_FALLING_CEILING1].save_anim = 1;
|
||||
Objects[O_FALLING_CEILING1].save_flags = 1;
|
||||
|
||||
Objects[O_FALLING_CEILING2].control = FallingCeilingControl;
|
||||
Objects[O_FALLING_CEILING2].collision = TrapCollision;
|
||||
Objects[O_FALLING_CEILING2].save_position = 1;
|
||||
Objects[O_FALLING_CEILING2].save_anim = 1;
|
||||
Objects[O_FALLING_CEILING2].save_flags = 1;
|
||||
|
||||
Objects[O_DAMOCLES_SWORD].initialise = InitialiseDamoclesSword;
|
||||
Objects[O_DAMOCLES_SWORD].control = DamoclesSwordControl;
|
||||
Objects[O_DAMOCLES_SWORD].collision = DamoclesSwordCollision;
|
||||
Objects[O_DAMOCLES_SWORD].shadow_size = UNIT_SHADOW;
|
||||
Objects[O_DAMOCLES_SWORD].save_position = 1;
|
||||
Objects[O_DAMOCLES_SWORD].save_anim = 1;
|
||||
Objects[O_DAMOCLES_SWORD].save_flags = 1;
|
||||
|
||||
Objects[O_MOVABLE_BLOCK].initialise = InitialiseMovableBlock;
|
||||
Objects[O_MOVABLE_BLOCK].control = MovableBlockControl;
|
||||
Objects[O_MOVABLE_BLOCK].draw_routine = DrawMovableBlock;
|
||||
Objects[O_MOVABLE_BLOCK].collision = MovableBlockCollision;
|
||||
Objects[O_MOVABLE_BLOCK].save_position = 1;
|
||||
Objects[O_MOVABLE_BLOCK].save_anim = 1;
|
||||
Objects[O_MOVABLE_BLOCK].save_flags = 1;
|
||||
|
||||
Objects[O_MOVABLE_BLOCK2].initialise = InitialiseMovableBlock;
|
||||
Objects[O_MOVABLE_BLOCK2].control = MovableBlockControl;
|
||||
Objects[O_MOVABLE_BLOCK2].draw_routine = DrawMovableBlock;
|
||||
Objects[O_MOVABLE_BLOCK2].collision = MovableBlockCollision;
|
||||
Objects[O_MOVABLE_BLOCK2].save_position = 1;
|
||||
Objects[O_MOVABLE_BLOCK2].save_anim = 1;
|
||||
Objects[O_MOVABLE_BLOCK2].save_flags = 1;
|
||||
|
||||
Objects[O_MOVABLE_BLOCK3].initialise = InitialiseMovableBlock;
|
||||
Objects[O_MOVABLE_BLOCK3].draw_routine = DrawMovableBlock;
|
||||
Objects[O_MOVABLE_BLOCK3].control = MovableBlockControl;
|
||||
Objects[O_MOVABLE_BLOCK3].collision = MovableBlockCollision;
|
||||
Objects[O_MOVABLE_BLOCK3].save_position = 1;
|
||||
Objects[O_MOVABLE_BLOCK3].save_anim = 1;
|
||||
Objects[O_MOVABLE_BLOCK3].save_flags = 1;
|
||||
|
||||
Objects[O_MOVABLE_BLOCK4].initialise = InitialiseMovableBlock;
|
||||
Objects[O_MOVABLE_BLOCK4].control = MovableBlockControl;
|
||||
Objects[O_MOVABLE_BLOCK4].draw_routine = DrawMovableBlock;
|
||||
Objects[O_MOVABLE_BLOCK4].collision = MovableBlockCollision;
|
||||
Objects[O_MOVABLE_BLOCK4].save_position = 1;
|
||||
Objects[O_MOVABLE_BLOCK4].save_anim = 1;
|
||||
Objects[O_MOVABLE_BLOCK4].save_flags = 1;
|
||||
|
||||
Objects[O_ROLLING_BLOCK].initialise = InitialiseRollingBlock;
|
||||
Objects[O_ROLLING_BLOCK].control = RollingBlockControl;
|
||||
Objects[O_ROLLING_BLOCK].save_position = 1;
|
||||
Objects[O_ROLLING_BLOCK].save_anim = 1;
|
||||
Objects[O_ROLLING_BLOCK].save_flags = 1;
|
||||
|
||||
Objects[O_LIGHTNING_EMITTER].initialise = InitialiseLightning;
|
||||
Objects[O_LIGHTNING_EMITTER].control = LightningControl;
|
||||
Objects[O_LIGHTNING_EMITTER].draw_routine = DrawLightning;
|
||||
Objects[O_LIGHTNING_EMITTER].collision = LightningCollision;
|
||||
Objects[O_LIGHTNING_EMITTER].save_flags = 1;
|
||||
|
||||
Objects[O_THORS_HANDLE].initialise = InitialiseThorsHandle;
|
||||
Objects[O_THORS_HANDLE].control = ThorsHandleControl;
|
||||
Objects[O_THORS_HANDLE].draw_routine = DrawUnclippedItem;
|
||||
Objects[O_THORS_HANDLE].collision = ThorsHandleCollision;
|
||||
Objects[O_THORS_HANDLE].save_flags = 1;
|
||||
Objects[O_THORS_HANDLE].save_anim = 1;
|
||||
|
||||
Objects[O_THORS_HEAD].collision = ThorsHeadCollision;
|
||||
Objects[O_THORS_HEAD].draw_routine = DrawUnclippedItem;
|
||||
Objects[O_THORS_HEAD].save_flags = 1;
|
||||
Objects[O_THORS_HEAD].save_anim = 1;
|
||||
|
||||
Objects[O_MIDAS_TOUCH].collision = MidasCollision;
|
||||
Objects[O_MIDAS_TOUCH].draw_routine = DrawDummyItem;
|
||||
|
||||
Objects[O_DART_EMITTER].control = DartEmitterControl;
|
||||
|
||||
Objects[O_DARTS].collision = ObjectCollision;
|
||||
Objects[O_DARTS].control = DartsControl;
|
||||
Objects[O_DARTS].shadow_size = UNIT_SHADOW / 2;
|
||||
Objects[O_DARTS].save_flags = 1;
|
||||
|
||||
Objects[O_DART_EFFECT].control = DartEffectControl;
|
||||
Objects[O_DART_EFFECT].draw_routine = DrawSpriteItem;
|
||||
|
||||
Objects[O_FLAME_EMITTER].control = FlameEmitterControl;
|
||||
Objects[O_FLAME_EMITTER].draw_routine = DrawDummyItem;
|
||||
|
||||
Objects[O_FLAME].control = FlameControl;
|
||||
|
||||
Objects[O_LAVA_EMITTER].control = LavaEmitterControl;
|
||||
Objects[O_LAVA_EMITTER].draw_routine = DrawDummyItem;
|
||||
Objects[O_LAVA_EMITTER].collision = ObjectCollision;
|
||||
|
||||
Objects[O_LAVA].control = LavaControl;
|
||||
|
||||
Objects[O_LAVA_WEDGE].control = LavaWedgeControl;
|
||||
Objects[O_LAVA_WEDGE].collision = CreatureCollision;
|
||||
Objects[O_LAVA_WEDGE].save_position = 1;
|
||||
Objects[O_LAVA_WEDGE].save_anim = 1;
|
||||
Objects[O_LAVA_WEDGE].save_flags = 1;
|
||||
SetupFallingBlock(&Objects[O_FALLING_BLOCK]);
|
||||
SetupPendulum(&Objects[O_PENDULUM]);
|
||||
SetupTeethTrap(&Objects[O_TEETH_TRAP]);
|
||||
SetupRollingBall(&Objects[O_ROLLING_BALL]);
|
||||
SetupSpikes(&Objects[O_SPIKES]);
|
||||
SetupFallingCeilling(&Objects[O_FALLING_CEILING1]);
|
||||
SetupFallingCeilling(&Objects[O_FALLING_CEILING2]);
|
||||
SetupDamoclesSword(&Objects[O_DAMOCLES_SWORD]);
|
||||
SetupMovableBlock(&Objects[O_MOVABLE_BLOCK]);
|
||||
SetupMovableBlock(&Objects[O_MOVABLE_BLOCK2]);
|
||||
SetupMovableBlock(&Objects[O_MOVABLE_BLOCK3]);
|
||||
SetupMovableBlock(&Objects[O_MOVABLE_BLOCK4]);
|
||||
SetupRollingBlock(&Objects[O_ROLLING_BLOCK]);
|
||||
SetupLightningEmitter(&Objects[O_LIGHTNING_EMITTER]);
|
||||
SetupThorsHandle(&Objects[O_THORS_HANDLE]);
|
||||
SetupThorsHead(&Objects[O_THORS_HEAD]);
|
||||
SetupMidasTouch(&Objects[O_MIDAS_TOUCH]);
|
||||
SetupDartEmitter(&Objects[O_DART_EMITTER]);
|
||||
SetupDart(&Objects[O_DARTS]);
|
||||
SetupDartEffect(&Objects[O_DART_EFFECT]);
|
||||
SetupFlameEmitter(&Objects[O_FLAME_EMITTER]);
|
||||
SetupFlame(&Objects[O_FLAME]);
|
||||
SetupLavaEmitter(&Objects[O_LAVA_EMITTER]);
|
||||
SetupLava(&Objects[O_LAVA]);
|
||||
SetupLavaWedge(&Objects[O_LAVA_WEDGE]);
|
||||
}
|
||||
|
||||
void ObjectObjects()
|
||||
|
@ -405,17 +312,8 @@ void ObjectObjects()
|
|||
Objects[O_DOOR_TYPE8].save_anim = 1;
|
||||
Objects[O_DOOR_TYPE8].save_flags = 1;
|
||||
|
||||
Objects[O_TRAPDOOR].control = TrapDoorControl;
|
||||
Objects[O_TRAPDOOR].floor = TrapDoorFloor;
|
||||
Objects[O_TRAPDOOR].ceiling = TrapDoorCeiling;
|
||||
Objects[O_TRAPDOOR].save_anim = 1;
|
||||
Objects[O_TRAPDOOR].save_flags = 1;
|
||||
|
||||
Objects[O_TRAPDOOR2].control = TrapDoorControl;
|
||||
Objects[O_TRAPDOOR2].floor = TrapDoorFloor;
|
||||
Objects[O_TRAPDOOR2].ceiling = TrapDoorCeiling;
|
||||
Objects[O_TRAPDOOR2].save_anim = 1;
|
||||
Objects[O_TRAPDOOR2].save_flags = 1;
|
||||
SetupTrapDoor(&Objects[O_TRAPDOOR]);
|
||||
SetupTrapDoor(&Objects[O_TRAPDOOR2]);
|
||||
|
||||
Objects[O_COG_1].control = CogControl;
|
||||
Objects[O_COG_1].save_flags = 1;
|
||||
|
|
865
src/game/traps.c
865
src/game/traps.c
|
@ -1,865 +0,0 @@
|
|||
#include "3dsystem/phd_math.h"
|
||||
#include "game/collide.h"
|
||||
#include "game/control.h"
|
||||
#include "game/effects.h"
|
||||
#include "game/game.h"
|
||||
#include "game/items.h"
|
||||
#include "game/sphere.h"
|
||||
#include "game/traps.h"
|
||||
#include "game/vars.h"
|
||||
#include "specific/init.h"
|
||||
#include "util.h"
|
||||
|
||||
#define ROLLINGBALL_DAMAGE_AIR 100
|
||||
#define SPIKE_DAMAGE 15
|
||||
#define PENDULUM_DAMAGE 100
|
||||
#define TEETH_TRAP_DAMAGE 400
|
||||
#define FALLING_CEILING_DAMAGE 300
|
||||
#define DAMOCLES_SWORD_ACTIVATE_DIST ((WALL_L * 3) / 2)
|
||||
#define DAMOCLES_SWORD_DAMAGE 100
|
||||
#define FLAME_ONFIRE_DAMAGE 5
|
||||
#define FLAME_TOONEAR_DAMAGE 3
|
||||
#define LAVA_GLOB_DAMAGE 10
|
||||
#define LAVA_WEDGE_SPEED 25
|
||||
|
||||
typedef enum {
|
||||
TT_NICE = 0,
|
||||
TT_NASTY = 1,
|
||||
} TEETH_TRAP_STATE;
|
||||
|
||||
typedef enum {
|
||||
DE_IDLE = 0,
|
||||
DE_FIRE = 1,
|
||||
} DART_EMITTER_STATE;
|
||||
|
||||
static BITE_INFO Teeth1A = { -23, 0, -1718, 0 };
|
||||
static BITE_INFO Teeth1B = { 71, 0, -1718, 1 };
|
||||
static BITE_INFO Teeth2A = { -23, 10, -1718, 0 };
|
||||
static BITE_INFO Teeth2B = { 71, 10, -1718, 1 };
|
||||
static BITE_INFO Teeth3A = { -23, -10, -1718, 0 };
|
||||
static BITE_INFO Teeth3B = { 71, -10, -1718, 1 };
|
||||
|
||||
void InitialiseRollingBall(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
GAME_VECTOR *old = game_malloc(sizeof(GAME_VECTOR), GBUF_ROLLINGBALL_STUFF);
|
||||
item->data = old;
|
||||
old->x = item->pos.x;
|
||||
old->y = item->pos.y;
|
||||
old->z = item->pos.z;
|
||||
old->room_number = item->room_number;
|
||||
}
|
||||
|
||||
void RollingBallControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (item->status == IS_ACTIVE) {
|
||||
if (item->pos.y < item->floor) {
|
||||
if (!item->gravity_status) {
|
||||
item->gravity_status = 1;
|
||||
item->fall_speed = -10;
|
||||
}
|
||||
} else if (item->current_anim_state == TRAP_SET) {
|
||||
item->goal_anim_state = TRAP_ACTIVATE;
|
||||
}
|
||||
|
||||
int32_t oldx = item->pos.x;
|
||||
int32_t oldz = item->pos.z;
|
||||
AnimateItem(item);
|
||||
|
||||
int16_t room_num = item->room_number;
|
||||
FLOOR_INFO *floor =
|
||||
GetFloor(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
if (item->room_number != room_num) {
|
||||
ItemNewRoom(item_num, room_num);
|
||||
}
|
||||
|
||||
item->floor = GetHeight(floor, item->pos.x, item->pos.y, item->pos.z);
|
||||
|
||||
TestTriggers(TriggerIndex, 1);
|
||||
|
||||
if (item->pos.y >= item->floor - STEP_L) {
|
||||
item->gravity_status = 0;
|
||||
item->fall_speed = 0;
|
||||
item->pos.y = item->floor;
|
||||
}
|
||||
|
||||
int32_t x = item->pos.x
|
||||
+ (((WALL_L / 2) * phd_sin(item->pos.y_rot)) >> W2V_SHIFT);
|
||||
int32_t z = item->pos.z
|
||||
+ (((WALL_L / 2) * phd_cos(item->pos.y_rot)) >> W2V_SHIFT);
|
||||
floor = GetFloor(x, item->pos.y, z, &room_num);
|
||||
if (GetHeight(floor, x, item->pos.y, z) < item->pos.y) {
|
||||
item->status = IS_DEACTIVATED;
|
||||
item->pos.x = oldx;
|
||||
item->pos.y = item->floor;
|
||||
item->pos.z = oldz;
|
||||
item->speed = 0;
|
||||
item->fall_speed = 0;
|
||||
item->touch_bits = 0;
|
||||
}
|
||||
} else if (item->status == IS_DEACTIVATED && !TriggerActive(item)) {
|
||||
item->status = IS_NOT_ACTIVE;
|
||||
GAME_VECTOR *old = item->data;
|
||||
item->pos.x = old->x;
|
||||
item->pos.y = old->y;
|
||||
item->pos.z = old->z;
|
||||
if (item->room_number != old->room_number) {
|
||||
RemoveDrawnItem(item_num);
|
||||
ROOM_INFO *r = &RoomInfo[old->room_number];
|
||||
item->next_item = r->item_number;
|
||||
r->item_number = item_num;
|
||||
item->room_number = old->room_number;
|
||||
}
|
||||
item->current_anim_state = TRAP_SET;
|
||||
item->goal_anim_state = TRAP_SET;
|
||||
item->anim_number = Objects[item->object_number].anim_index;
|
||||
item->frame_number = Anims[item->anim_number].frame_base;
|
||||
item->current_anim_state = Anims[item->anim_number].current_anim_state;
|
||||
item->goal_anim_state = item->current_anim_state;
|
||||
item->required_anim_state = TRAP_SET;
|
||||
RemoveActiveItem(item_num);
|
||||
}
|
||||
}
|
||||
|
||||
void RollingBallCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
|
||||
if (item->status != IS_ACTIVE) {
|
||||
if (item->status != IS_INVISIBLE) {
|
||||
ObjectCollision(item_num, lara_item, coll);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TestBoundsCollide(item, lara_item, coll->radius)) {
|
||||
return;
|
||||
}
|
||||
if (!TestCollision(item, lara_item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t x, y, z, d;
|
||||
if (lara_item->gravity_status) {
|
||||
if (coll->enable_baddie_push) {
|
||||
ItemPushLara(item, lara_item, coll, coll->enable_spaz, 1);
|
||||
}
|
||||
lara_item->hit_points -= ROLLINGBALL_DAMAGE_AIR;
|
||||
x = lara_item->pos.x - item->pos.x;
|
||||
z = lara_item->pos.z - item->pos.z;
|
||||
y = (lara_item->pos.y - 350) - (item->pos.y - WALL_L / 2);
|
||||
d = phd_sqrt(SQUARE(x) + SQUARE(y) + SQUARE(z));
|
||||
if (d < WALL_L / 2) {
|
||||
d = WALL_L / 2;
|
||||
}
|
||||
x = item->pos.x + (x << WALL_SHIFT) / 2 / d;
|
||||
z = item->pos.z + (z << WALL_SHIFT) / 2 / d;
|
||||
y = item->pos.y - WALL_L / 2 + (y << WALL_SHIFT) / 2 / d;
|
||||
DoBloodSplat(x, y, z, item->speed, item->pos.y_rot, item->room_number);
|
||||
} else {
|
||||
lara_item->hit_status = 1;
|
||||
if (lara_item->hit_points > 0) {
|
||||
lara_item->hit_points = -1;
|
||||
if (lara_item->room_number != item->room_number) {
|
||||
ItemNewRoom(Lara.item_number, item->room_number);
|
||||
}
|
||||
|
||||
lara_item->pos.x_rot = 0;
|
||||
lara_item->pos.z_rot = 0;
|
||||
lara_item->pos.y_rot = item->pos.y_rot;
|
||||
|
||||
lara_item->current_anim_state = AS_SPECIAL;
|
||||
lara_item->goal_anim_state = AS_SPECIAL;
|
||||
lara_item->anim_number = AA_RBALL_DEATH;
|
||||
lara_item->frame_number = AF_RBALL_DEATH;
|
||||
|
||||
Camera.flags = FOLLOW_CENTRE;
|
||||
Camera.target_angle = 170 * PHD_DEGREE;
|
||||
Camera.target_elevation = -25 * PHD_DEGREE;
|
||||
for (int i = 0; i < 15; i++) {
|
||||
x = lara_item->pos.x + (GetRandomControl() - 0x4000) / 256;
|
||||
z = lara_item->pos.z + (GetRandomControl() - 0x4000) / 256;
|
||||
y = lara_item->pos.y - GetRandomControl() / 64;
|
||||
d = item->pos.y_rot + (GetRandomControl() - 0x4000) / 8;
|
||||
DoBloodSplat(x, y, z, item->speed * 2, d, item->room_number);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SpikeCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (lara_item->hit_points < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TestBoundsCollide(item, lara_item, coll->radius)) {
|
||||
return;
|
||||
}
|
||||
if (!TestCollision(item, lara_item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t num = GetRandomControl() / 24576;
|
||||
if (lara_item->gravity_status) {
|
||||
if (lara_item->fall_speed > 0) {
|
||||
lara_item->hit_points = -1;
|
||||
num = 20;
|
||||
}
|
||||
} else if (lara_item->speed < 30) {
|
||||
return;
|
||||
}
|
||||
|
||||
lara_item->hit_points -= SPIKE_DAMAGE;
|
||||
while (num > 0) {
|
||||
int32_t x = lara_item->pos.x + (GetRandomControl() - 0x4000) / 256;
|
||||
int32_t z = lara_item->pos.z + (GetRandomControl() - 0x4000) / 256;
|
||||
int32_t y = lara_item->pos.y - GetRandomControl() / 64;
|
||||
DoBloodSplat(x, y, z, 20, GetRandomControl(), item->room_number);
|
||||
num--;
|
||||
}
|
||||
|
||||
if (lara_item->hit_points <= 0) {
|
||||
lara_item->current_anim_state = AS_DEATH;
|
||||
lara_item->goal_anim_state = AS_DEATH;
|
||||
lara_item->anim_number = AA_SPIKE_DEATH;
|
||||
lara_item->frame_number = AF_SPIKE_DEATH;
|
||||
lara_item->pos.y = item->pos.y;
|
||||
lara_item->gravity_status = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TrapDoorControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (TriggerActive(item)) {
|
||||
if (item->current_anim_state == DOOR_CLOSED) {
|
||||
item->goal_anim_state = DOOR_OPEN;
|
||||
}
|
||||
} else if (item->current_anim_state == DOOR_OPEN) {
|
||||
item->goal_anim_state = DOOR_CLOSED;
|
||||
}
|
||||
AnimateItem(item);
|
||||
}
|
||||
|
||||
void TrapDoorFloor(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height)
|
||||
{
|
||||
if (!OnTrapDoor(item, x, z)) {
|
||||
return;
|
||||
}
|
||||
if (y <= item->pos.y && item->current_anim_state == DOOR_CLOSED
|
||||
&& item->pos.y < *height) {
|
||||
*height = item->pos.y;
|
||||
}
|
||||
}
|
||||
|
||||
void TrapDoorCeiling(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height)
|
||||
{
|
||||
if (!OnTrapDoor(item, x, z)) {
|
||||
return;
|
||||
}
|
||||
if (y > item->pos.y && item->current_anim_state == DOOR_CLOSED
|
||||
&& item->pos.y > *height) {
|
||||
*height = (int16_t)item->pos.y + STEP_L;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t OnTrapDoor(ITEM_INFO *item, int32_t x, int32_t z)
|
||||
{
|
||||
x >>= WALL_SHIFT;
|
||||
z >>= WALL_SHIFT;
|
||||
int32_t tx = item->pos.x >> WALL_SHIFT;
|
||||
int32_t tz = item->pos.z >> WALL_SHIFT;
|
||||
if (item->pos.y_rot == 0 && x == tx && (z == tz || z == tz + 1)) {
|
||||
return 1;
|
||||
} else if (
|
||||
item->pos.y_rot == -PHD_180 && x == tx && (z == tz || z == tz - 1)) {
|
||||
return 1;
|
||||
} else if (
|
||||
item->pos.y_rot == PHD_90 && z == tz && (x == tx || x == tx + 1)) {
|
||||
return 1;
|
||||
} else if (
|
||||
item->pos.y_rot == -PHD_90 && z == tz && (x == tx || x == tx - 1)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// original name: Pendulum
|
||||
void PendulumControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
|
||||
if (TriggerActive(item)) {
|
||||
if (item->current_anim_state == TRAP_SET) {
|
||||
item->goal_anim_state = TRAP_WORKING;
|
||||
}
|
||||
} else {
|
||||
if (item->current_anim_state == TRAP_WORKING) {
|
||||
item->goal_anim_state = TRAP_SET;
|
||||
}
|
||||
}
|
||||
|
||||
if (item->current_anim_state == TRAP_WORKING && item->touch_bits) {
|
||||
LaraItem->hit_points -= PENDULUM_DAMAGE;
|
||||
LaraItem->hit_status = 1;
|
||||
int32_t x = LaraItem->pos.x + (GetRandomControl() - 0x4000) / 256;
|
||||
int32_t z = LaraItem->pos.z + (GetRandomControl() - 0x4000) / 256;
|
||||
int32_t y = LaraItem->pos.y - GetRandomControl() / 44;
|
||||
int32_t d = LaraItem->pos.y_rot + (GetRandomControl() - 0x4000) / 8;
|
||||
DoBloodSplat(x, y, z, LaraItem->speed, d, LaraItem->room_number);
|
||||
}
|
||||
|
||||
FLOOR_INFO *floor =
|
||||
GetFloor(item->pos.x, item->pos.y, item->pos.z, &item->room_number);
|
||||
item->floor = GetHeight(floor, item->pos.x, item->pos.y, item->pos.z);
|
||||
|
||||
AnimateItem(item);
|
||||
}
|
||||
|
||||
// original name: FallingBlock
|
||||
void FallingBlockControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
|
||||
switch (item->current_anim_state) {
|
||||
case TRAP_SET:
|
||||
if (LaraItem->pos.y == item->pos.y - STEP_L * 2) {
|
||||
item->goal_anim_state = TRAP_ACTIVATE;
|
||||
} else {
|
||||
item->status = IS_NOT_ACTIVE;
|
||||
RemoveActiveItem(item_num);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case TRAP_ACTIVATE:
|
||||
item->goal_anim_state = TRAP_WORKING;
|
||||
break;
|
||||
|
||||
case TRAP_WORKING:
|
||||
if (item->goal_anim_state != TRAP_FINISHED) {
|
||||
item->gravity_status = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
AnimateItem(item);
|
||||
if (item->status == IS_DEACTIVATED) {
|
||||
RemoveActiveItem(item_num);
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t room_num = item->room_number;
|
||||
FLOOR_INFO *floor =
|
||||
GetFloor(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
if (item->room_number != room_num) {
|
||||
ItemNewRoom(item_num, room_num);
|
||||
}
|
||||
|
||||
item->floor = GetHeight(floor, item->pos.x, item->pos.y, item->pos.z);
|
||||
|
||||
if (item->current_anim_state == TRAP_WORKING
|
||||
&& item->pos.y >= item->floor) {
|
||||
item->goal_anim_state = TRAP_FINISHED;
|
||||
item->pos.y = item->floor;
|
||||
item->fall_speed = 0;
|
||||
item->gravity_status = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void FallingBlockFloor(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height)
|
||||
{
|
||||
if (y <= item->pos.y - STEP_L * 2
|
||||
&& (item->current_anim_state == TRAP_SET
|
||||
|| item->current_anim_state == TRAP_ACTIVATE)) {
|
||||
*height = item->pos.y - STEP_L * 2;
|
||||
}
|
||||
}
|
||||
|
||||
void FallingBlockCeiling(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height)
|
||||
{
|
||||
if (y > item->pos.y - STEP_L * 2
|
||||
&& (item->current_anim_state == TRAP_SET
|
||||
|| item->current_anim_state == TRAP_ACTIVATE)) {
|
||||
*height = item->pos.y - STEP_L;
|
||||
}
|
||||
}
|
||||
|
||||
// original name: TeethTrap
|
||||
void TeethTrapControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (TriggerActive(item)) {
|
||||
item->goal_anim_state = TT_NASTY;
|
||||
if (item->touch_bits && item->current_anim_state == TT_NASTY) {
|
||||
LaraItem->hit_points -= TEETH_TRAP_DAMAGE;
|
||||
LaraItem->hit_status = 1;
|
||||
BaddieBiteEffect(item, &Teeth1A);
|
||||
BaddieBiteEffect(item, &Teeth1B);
|
||||
BaddieBiteEffect(item, &Teeth2A);
|
||||
BaddieBiteEffect(item, &Teeth2B);
|
||||
BaddieBiteEffect(item, &Teeth3A);
|
||||
BaddieBiteEffect(item, &Teeth3B);
|
||||
}
|
||||
} else {
|
||||
item->goal_anim_state = TT_NICE;
|
||||
}
|
||||
AnimateItem(item);
|
||||
}
|
||||
|
||||
// original name: FallingCeiling
|
||||
void FallingCeilingControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (item->current_anim_state == TRAP_SET) {
|
||||
item->goal_anim_state = TRAP_ACTIVATE;
|
||||
item->gravity_status = 1;
|
||||
} else if (item->current_anim_state == TRAP_ACTIVATE && item->touch_bits) {
|
||||
LaraItem->hit_points -= FALLING_CEILING_DAMAGE;
|
||||
LaraItem->hit_status = 1;
|
||||
}
|
||||
AnimateItem(item);
|
||||
if (item->status == IS_DEACTIVATED) {
|
||||
RemoveActiveItem(item_num);
|
||||
} else if (
|
||||
item->current_anim_state == TRAP_ACTIVATE
|
||||
&& item->pos.y >= item->floor) {
|
||||
item->goal_anim_state = TRAP_WORKING;
|
||||
item->pos.y = item->floor;
|
||||
item->fall_speed = 0;
|
||||
item->gravity_status = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void InitialiseDamoclesSword(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
item->pos.y_rot = GetRandomControl();
|
||||
item->required_anim_state = (GetRandomControl() - 0x4000) / 16;
|
||||
item->fall_speed = 50;
|
||||
}
|
||||
|
||||
void DamoclesSwordControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (item->gravity_status) {
|
||||
item->pos.y_rot += item->required_anim_state;
|
||||
item->fall_speed += item->fall_speed < FASTFALL_SPEED ? GRAVITY : 1;
|
||||
item->pos.y += item->fall_speed;
|
||||
item->pos.x += item->current_anim_state;
|
||||
item->pos.z += item->goal_anim_state;
|
||||
|
||||
if (item->pos.y > item->floor) {
|
||||
SoundEffect(SFX_DAMOCLES_SWORD, &item->pos, SPM_NORMAL);
|
||||
item->pos.y = item->floor + 10;
|
||||
item->gravity_status = 0;
|
||||
item->status = IS_DEACTIVATED;
|
||||
RemoveActiveItem(item_num);
|
||||
}
|
||||
} else if (item->pos.y != item->floor) {
|
||||
item->pos.y_rot += item->required_anim_state;
|
||||
int32_t x = LaraItem->pos.x - item->pos.x;
|
||||
int32_t y = LaraItem->pos.y - item->pos.y;
|
||||
int32_t z = LaraItem->pos.z - item->pos.z;
|
||||
if (ABS(x) <= DAMOCLES_SWORD_ACTIVATE_DIST
|
||||
&& ABS(z) <= DAMOCLES_SWORD_ACTIVATE_DIST && y > 0
|
||||
&& y < WALL_L * 3) {
|
||||
item->current_anim_state = x / 32;
|
||||
item->goal_anim_state = z / 32;
|
||||
item->gravity_status = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DamoclesSwordCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (!TestBoundsCollide(item, lara_item, coll->radius)) {
|
||||
return;
|
||||
}
|
||||
if (coll->enable_baddie_push) {
|
||||
ItemPushLara(item, lara_item, coll, 0, 1);
|
||||
}
|
||||
if (item->gravity_status) {
|
||||
lara_item->hit_points -= DAMOCLES_SWORD_DAMAGE;
|
||||
int32_t x = lara_item->pos.x + (GetRandomControl() - 0x4000) / 256;
|
||||
int32_t z = lara_item->pos.z + (GetRandomControl() - 0x4000) / 256;
|
||||
int32_t y = lara_item->pos.y - GetRandomControl() / 44;
|
||||
int32_t d = lara_item->pos.y_rot + (GetRandomControl() - 0x4000) / 8;
|
||||
DoBloodSplat(x, y, z, lara_item->speed, d, lara_item->room_number);
|
||||
}
|
||||
}
|
||||
|
||||
void DartEmitterControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
|
||||
if (TriggerActive(item)) {
|
||||
if (item->current_anim_state == DE_IDLE) {
|
||||
item->goal_anim_state = DE_FIRE;
|
||||
}
|
||||
} else {
|
||||
if (item->current_anim_state == DE_FIRE) {
|
||||
item->goal_anim_state = DE_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (item->current_anim_state == DE_FIRE
|
||||
&& item->frame_number == Anims[item->anim_number].frame_base) {
|
||||
int16_t dart_item_num = CreateItem();
|
||||
if (dart_item_num != NO_ITEM) {
|
||||
ITEM_INFO *dart = &Items[dart_item_num];
|
||||
dart->object_number = O_DARTS;
|
||||
dart->room_number = item->room_number;
|
||||
dart->shade = -1;
|
||||
dart->pos.y_rot = item->pos.y_rot;
|
||||
dart->pos.y = item->pos.y - WALL_L / 2;
|
||||
|
||||
int32_t x = 0;
|
||||
int32_t z = 0;
|
||||
switch (dart->pos.y_rot) {
|
||||
case 0:
|
||||
z = -WALL_L / 2 + 100;
|
||||
break;
|
||||
case PHD_90:
|
||||
x = -WALL_L / 2 + 100;
|
||||
break;
|
||||
case -PHD_180:
|
||||
z = WALL_L / 2 - 100;
|
||||
break;
|
||||
case -PHD_90:
|
||||
x = WALL_L / 2 - 100;
|
||||
break;
|
||||
}
|
||||
|
||||
dart->pos.x = item->pos.x + x;
|
||||
dart->pos.z = item->pos.z + z;
|
||||
InitialiseItem(dart_item_num);
|
||||
AddActiveItem(dart_item_num);
|
||||
dart->status = IS_ACTIVE;
|
||||
|
||||
int16_t fx_num = CreateEffect(dart->room_number);
|
||||
if (fx_num != NO_ITEM) {
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
fx->pos = dart->pos;
|
||||
fx->speed = 0;
|
||||
fx->frame_number = 0;
|
||||
fx->counter = 0;
|
||||
fx->object_number = O_DART_EFFECT;
|
||||
SoundEffect(SFX_DARTS, &fx->pos, SPM_NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
AnimateItem(item);
|
||||
}
|
||||
|
||||
void DartsControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (item->touch_bits) {
|
||||
LaraItem->hit_points -= 50;
|
||||
LaraItem->hit_status = 1;
|
||||
DoBloodSplat(
|
||||
item->pos.x, item->pos.y, item->pos.z, LaraItem->speed,
|
||||
LaraItem->pos.y_rot, LaraItem->room_number);
|
||||
}
|
||||
AnimateItem(item);
|
||||
|
||||
int16_t room_num = item->room_number;
|
||||
FLOOR_INFO *floor =
|
||||
GetFloor(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
if (item->room_number != room_num) {
|
||||
ItemNewRoom(item_num, room_num);
|
||||
}
|
||||
|
||||
item->floor = GetHeight(floor, item->pos.x, item->pos.y, item->pos.z);
|
||||
if (item->pos.y >= item->floor) {
|
||||
KillItem(item_num);
|
||||
int16_t fx_num = CreateEffect(item->room_number);
|
||||
if (fx_num != NO_ITEM) {
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
fx->pos = item->pos;
|
||||
fx->speed = 0;
|
||||
fx->counter = 6;
|
||||
fx->frame_number = -3 * GetRandomControl() / 0x8000;
|
||||
fx->object_number = O_RICOCHET1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DartEffectControl(int16_t fx_num)
|
||||
{
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
fx->counter++;
|
||||
if (fx->counter >= 3) {
|
||||
fx->counter = 0;
|
||||
fx->frame_number--;
|
||||
if (fx->frame_number <= Objects[fx->object_number].nmeshes) {
|
||||
KillEffect(fx_num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FlameEmitterControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (TriggerActive(item)) {
|
||||
if (!item->data) {
|
||||
int16_t fx_num = CreateEffect(item->room_number);
|
||||
if (fx_num != NO_ITEM) {
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
fx->pos.x = item->pos.x;
|
||||
fx->pos.y = item->pos.y;
|
||||
fx->pos.z = item->pos.z;
|
||||
fx->frame_number = 0;
|
||||
fx->object_number = O_FLAME;
|
||||
fx->counter = 0;
|
||||
}
|
||||
item->data = (void *)(fx_num + 1);
|
||||
}
|
||||
} else if (item->data) {
|
||||
StopSoundEffect(SFX_FIRE, NULL);
|
||||
KillEffect((int16_t)(size_t)item->data - 1);
|
||||
item->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void FlameControl(int16_t fx_num)
|
||||
{
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
|
||||
fx->frame_number--;
|
||||
if (fx->frame_number <= Objects[O_FLAME].nmeshes) {
|
||||
fx->frame_number = 0;
|
||||
}
|
||||
|
||||
if (fx->counter < 0) {
|
||||
if (Lara.water_status == LWS_CHEAT) {
|
||||
fx->counter = 0;
|
||||
StopSoundEffect(SFX_FIRE, NULL);
|
||||
KillEffect(fx_num);
|
||||
}
|
||||
|
||||
fx->pos.x = 0;
|
||||
fx->pos.y = 0;
|
||||
if (fx->counter == -1) {
|
||||
fx->pos.z = -100;
|
||||
} else {
|
||||
fx->pos.z = 0;
|
||||
}
|
||||
|
||||
GetJointAbsPosition(LaraItem, (PHD_VECTOR *)&fx->pos, -1 - fx->counter);
|
||||
|
||||
int32_t y = GetWaterHeight(
|
||||
LaraItem->pos.x, LaraItem->pos.y, LaraItem->pos.z,
|
||||
LaraItem->room_number);
|
||||
|
||||
if (y != NO_HEIGHT && fx->pos.y > y) {
|
||||
fx->counter = 0;
|
||||
StopSoundEffect(SFX_FIRE, NULL);
|
||||
KillEffect(fx_num);
|
||||
} else {
|
||||
SoundEffect(SFX_FIRE, &fx->pos, SPM_NORMAL);
|
||||
LaraItem->hit_points -= FLAME_ONFIRE_DAMAGE;
|
||||
LaraItem->hit_status = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
SoundEffect(SFX_FIRE, &fx->pos, SPM_NORMAL);
|
||||
if (fx->counter) {
|
||||
fx->counter--;
|
||||
} else if (ItemNearLara(&fx->pos, 600)) {
|
||||
if (Lara.water_status == LWS_CHEAT) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t x = LaraItem->pos.x - fx->pos.x;
|
||||
int32_t z = LaraItem->pos.z - fx->pos.z;
|
||||
int32_t distance = SQUARE(x) + SQUARE(z);
|
||||
|
||||
LaraItem->hit_points -= FLAME_TOONEAR_DAMAGE;
|
||||
LaraItem->hit_status = 1;
|
||||
|
||||
if (distance < SQUARE(300)) {
|
||||
fx->counter = 100;
|
||||
|
||||
fx_num = CreateEffect(LaraItem->room_number);
|
||||
if (fx_num != NO_ITEM) {
|
||||
fx = &Effects[fx_num];
|
||||
fx->frame_number = 0;
|
||||
fx->object_number = O_FLAME;
|
||||
fx->counter = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LavaBurn(ITEM_INFO *item)
|
||||
{
|
||||
if (Lara.water_status == LWS_CHEAT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (item->hit_points < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t room_num = item->room_number;
|
||||
FLOOR_INFO *floor = GetFloor(item->pos.x, 32000, item->pos.z, &room_num);
|
||||
|
||||
if (item->floor != GetHeight(floor, item->pos.x, 32000, item->pos.z)) {
|
||||
return;
|
||||
}
|
||||
|
||||
item->hit_points = -1;
|
||||
item->hit_status = 1;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int16_t fx_num = CreateEffect(item->room_number);
|
||||
if (fx_num != NO_ITEM) {
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
fx->object_number = O_FLAME;
|
||||
fx->frame_number =
|
||||
(Objects[O_FLAME].nmeshes * GetRandomControl()) / 0x7FFF;
|
||||
fx->counter = -1 - GetRandomControl() * 24 / 0x7FFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// original name: LavaSpray
|
||||
void LavaEmitterControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
int16_t fx_num = CreateEffect(item->room_number);
|
||||
if (fx_num != NO_ITEM) {
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
fx->pos.x = item->pos.x;
|
||||
fx->pos.y = item->pos.y;
|
||||
fx->pos.z = item->pos.z;
|
||||
fx->pos.y_rot = (GetRandomControl() - 0x4000) * 2;
|
||||
fx->speed = GetRandomControl() >> 10;
|
||||
fx->fall_speed = -GetRandomControl() / 200;
|
||||
fx->frame_number = -4 * GetRandomControl() / 0x7FFF;
|
||||
fx->object_number = O_LAVA;
|
||||
SoundEffect(SFX_LAVA_FOUNTAIN, &item->pos, SPM_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
// original name: ControlLavaBlob
|
||||
void LavaControl(int16_t fx_num)
|
||||
{
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
fx->pos.z += (fx->speed * phd_cos(fx->pos.y_rot)) >> W2V_SHIFT;
|
||||
fx->pos.x += (fx->speed * phd_sin(fx->pos.y_rot)) >> W2V_SHIFT;
|
||||
fx->fall_speed += GRAVITY;
|
||||
fx->pos.y += fx->fall_speed;
|
||||
|
||||
int16_t room_num = fx->room_number;
|
||||
FLOOR_INFO *floor = GetFloor(fx->pos.x, fx->pos.y, fx->pos.z, &room_num);
|
||||
if (fx->pos.y >= GetHeight(floor, fx->pos.x, fx->pos.y, fx->pos.z)
|
||||
|| fx->pos.y < GetCeiling(floor, fx->pos.x, fx->pos.y, fx->pos.z)) {
|
||||
KillEffect(fx_num);
|
||||
} else if (ItemNearLara(&fx->pos, 200)) {
|
||||
LaraItem->hit_points -= LAVA_GLOB_DAMAGE;
|
||||
LaraItem->hit_status = 1;
|
||||
KillEffect(fx_num);
|
||||
} else if (room_num != fx->room_number) {
|
||||
EffectNewRoom(fx_num, room_num);
|
||||
}
|
||||
}
|
||||
|
||||
// original name: LavaWedge
|
||||
void LavaWedgeControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
|
||||
int16_t room_num = item->room_number;
|
||||
GetFloor(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
if (room_num != item->room_number) {
|
||||
ItemNewRoom(item_num, room_num);
|
||||
}
|
||||
|
||||
if (item->status != IS_DEACTIVATED) {
|
||||
int32_t x = item->pos.x;
|
||||
int32_t z = item->pos.z;
|
||||
|
||||
switch (item->pos.y_rot) {
|
||||
case 0:
|
||||
item->pos.z += LAVA_WEDGE_SPEED;
|
||||
z += 2 * WALL_L;
|
||||
break;
|
||||
case -PHD_180:
|
||||
item->pos.z -= LAVA_WEDGE_SPEED;
|
||||
z -= 2 * WALL_L;
|
||||
break;
|
||||
case PHD_90:
|
||||
item->pos.x += LAVA_WEDGE_SPEED;
|
||||
x += 2 * WALL_L;
|
||||
break;
|
||||
default:
|
||||
item->pos.x -= LAVA_WEDGE_SPEED;
|
||||
x -= 2 * WALL_L;
|
||||
break;
|
||||
}
|
||||
|
||||
FLOOR_INFO *floor = GetFloor(x, item->pos.y, z, &room_num);
|
||||
if (GetHeight(floor, x, item->pos.y, z) != item->pos.y) {
|
||||
item->status = IS_DEACTIVATED;
|
||||
}
|
||||
}
|
||||
|
||||
if (Lara.water_status == LWS_CHEAT) {
|
||||
item->touch_bits = 0;
|
||||
}
|
||||
|
||||
if (item->touch_bits) {
|
||||
if (LaraItem->hit_points > 0) {
|
||||
LavaBurn(LaraItem);
|
||||
}
|
||||
|
||||
Camera.item = item;
|
||||
Camera.flags = CHASE_OBJECT;
|
||||
Camera.type = CAM_FIXED;
|
||||
Camera.target_angle = -PHD_180;
|
||||
Camera.target_distance = WALL_L * 3;
|
||||
}
|
||||
}
|
||||
|
||||
void T1MInjectGameTraps()
|
||||
{
|
||||
INJECT(0x0043A010, InitialiseRollingBall);
|
||||
INJECT(0x0043A050, RollingBallControl);
|
||||
INJECT(0x0043A2B0, RollingBallCollision);
|
||||
INJECT(0x0043A520, SpikeCollision);
|
||||
INJECT(0x0043A670, TrapDoorControl);
|
||||
INJECT(0x0043A6D0, TrapDoorFloor);
|
||||
INJECT(0x0043A720, TrapDoorCeiling);
|
||||
INJECT(0x0043A770, OnTrapDoor);
|
||||
INJECT(0x0043A820, PendulumControl);
|
||||
INJECT(0x0043A970, FallingBlockControl);
|
||||
INJECT(0x0043AA70, FallingBlockFloor);
|
||||
INJECT(0x0043AAB0, FallingBlockCeiling);
|
||||
INJECT(0x0043AAF0, TeethTrapControl);
|
||||
INJECT(0x0043ABC0, FallingCeilingControl);
|
||||
INJECT(0x0043AC60, InitialiseDamoclesSword);
|
||||
INJECT(0x0043ACA0, DamoclesSwordControl);
|
||||
INJECT(0x0043ADD0, DamoclesSwordCollision);
|
||||
INJECT(0x0043AEC0, DartEmitterControl);
|
||||
INJECT(0x0043B060, DartsControl);
|
||||
INJECT(0x0043B1A0, DartEffectControl);
|
||||
INJECT(0x0043B1F0, FlameEmitterControl);
|
||||
INJECT(0x0043B2A0, FlameControl);
|
||||
INJECT(0x0043B430, LavaBurn);
|
||||
INJECT(0x0043B520, LavaEmitterControl);
|
||||
INJECT(0x0043B5F0, LavaControl);
|
||||
INJECT(0x0043B710, LavaWedgeControl);
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
#ifndef T1M_GAME_TRAPS_H
|
||||
#define T1M_GAME_TRAPS_H
|
||||
|
||||
#include "game/types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void InitialiseRollingBall(int16_t item_num);
|
||||
void RollingBallControl(int16_t item_num);
|
||||
void RollingBallCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
void SpikeCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
void TrapDoorControl(int16_t item_num);
|
||||
void TrapDoorFloor(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height);
|
||||
void TrapDoorCeiling(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height);
|
||||
int32_t OnTrapDoor(ITEM_INFO *item, int32_t x, int32_t z);
|
||||
void PendulumControl(int16_t item_num);
|
||||
void FallingBlockControl(int16_t item_num);
|
||||
void FallingBlockFloor(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height);
|
||||
void FallingBlockCeiling(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height);
|
||||
void TeethTrapControl(int16_t item_num);
|
||||
void FallingCeilingControl(int16_t item_num);
|
||||
void InitialiseDamoclesSword(int16_t item_num);
|
||||
void DamoclesSwordControl(int16_t item_num);
|
||||
void DamoclesSwordCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
void DartEmitterControl(int16_t item_num);
|
||||
void DartsControl(int16_t item_num);
|
||||
void DartEffectControl(int16_t fx_num);
|
||||
void FlameEmitterControl(int16_t item_num);
|
||||
void FlameControl(int16_t fx_num);
|
||||
void LavaBurn(ITEM_INFO *item);
|
||||
void LavaEmitterControl(int16_t item_num);
|
||||
void LavaControl(int16_t fx_num);
|
||||
void LavaWedgeControl(int16_t item_num);
|
||||
|
||||
void T1MInjectGameTraps();
|
||||
|
||||
#endif
|
80
src/game/traps/damocles_sword.c
Normal file
80
src/game/traps/damocles_sword.c
Normal file
|
@ -0,0 +1,80 @@
|
|||
#include "game/collide.h"
|
||||
#include "game/effects.h"
|
||||
#include "game/game.h"
|
||||
#include "game/items.h"
|
||||
#include "game/traps/damocles_sword.h"
|
||||
#include "game/vars.h"
|
||||
|
||||
#define DAMOCLES_SWORD_ACTIVATE_DIST ((WALL_L * 3) / 2)
|
||||
#define DAMOCLES_SWORD_DAMAGE 100
|
||||
|
||||
void SetupDamoclesSword(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->initialise = InitialiseDamoclesSword;
|
||||
obj->control = DamoclesSwordControl;
|
||||
obj->collision = DamoclesSwordCollision;
|
||||
obj->shadow_size = UNIT_SHADOW;
|
||||
obj->save_position = 1;
|
||||
obj->save_anim = 1;
|
||||
obj->save_flags = 1;
|
||||
}
|
||||
|
||||
void InitialiseDamoclesSword(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
item->pos.y_rot = GetRandomControl();
|
||||
item->required_anim_state = (GetRandomControl() - 0x4000) / 16;
|
||||
item->fall_speed = 50;
|
||||
}
|
||||
|
||||
void DamoclesSwordControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (item->gravity_status) {
|
||||
item->pos.y_rot += item->required_anim_state;
|
||||
item->fall_speed += item->fall_speed < FASTFALL_SPEED ? GRAVITY : 1;
|
||||
item->pos.y += item->fall_speed;
|
||||
item->pos.x += item->current_anim_state;
|
||||
item->pos.z += item->goal_anim_state;
|
||||
|
||||
if (item->pos.y > item->floor) {
|
||||
SoundEffect(SFX_DAMOCLES_SWORD, &item->pos, SPM_NORMAL);
|
||||
item->pos.y = item->floor + 10;
|
||||
item->gravity_status = 0;
|
||||
item->status = IS_DEACTIVATED;
|
||||
RemoveActiveItem(item_num);
|
||||
}
|
||||
} else if (item->pos.y != item->floor) {
|
||||
item->pos.y_rot += item->required_anim_state;
|
||||
int32_t x = LaraItem->pos.x - item->pos.x;
|
||||
int32_t y = LaraItem->pos.y - item->pos.y;
|
||||
int32_t z = LaraItem->pos.z - item->pos.z;
|
||||
if (ABS(x) <= DAMOCLES_SWORD_ACTIVATE_DIST
|
||||
&& ABS(z) <= DAMOCLES_SWORD_ACTIVATE_DIST && y > 0
|
||||
&& y < WALL_L * 3) {
|
||||
item->current_anim_state = x / 32;
|
||||
item->goal_anim_state = z / 32;
|
||||
item->gravity_status = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DamoclesSwordCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (!TestBoundsCollide(item, lara_item, coll->radius)) {
|
||||
return;
|
||||
}
|
||||
if (coll->enable_baddie_push) {
|
||||
ItemPushLara(item, lara_item, coll, 0, 1);
|
||||
}
|
||||
if (item->gravity_status) {
|
||||
lara_item->hit_points -= DAMOCLES_SWORD_DAMAGE;
|
||||
int32_t x = lara_item->pos.x + (GetRandomControl() - 0x4000) / 256;
|
||||
int32_t z = lara_item->pos.z + (GetRandomControl() - 0x4000) / 256;
|
||||
int32_t y = lara_item->pos.y - GetRandomControl() / 44;
|
||||
int32_t d = lara_item->pos.y_rot + (GetRandomControl() - 0x4000) / 8;
|
||||
DoBloodSplat(x, y, z, lara_item->speed, d, lara_item->room_number);
|
||||
}
|
||||
}
|
12
src/game/traps/damocles_sword.h
Normal file
12
src/game/traps/damocles_sword.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef T1M_GAME_TRAPS_DAMOCLES_SWORD_H
|
||||
#define T1M_GAME_TRAPS_DAMOCLES_SWORD_H
|
||||
|
||||
#include "game/types.h"
|
||||
|
||||
void SetupDamoclesSword(OBJECT_INFO *obj);
|
||||
void InitialiseDamoclesSword(int16_t item_num);
|
||||
void DamoclesSwordControl(int16_t item_num);
|
||||
void DamoclesSwordCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
|
||||
#endif
|
69
src/game/traps/dart.c
Normal file
69
src/game/traps/dart.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
#include "game/collide.h"
|
||||
#include "game/control.h"
|
||||
#include "game/draw.h"
|
||||
#include "game/effects.h"
|
||||
#include "game/game.h"
|
||||
#include "game/items.h"
|
||||
#include "game/traps/dart.h"
|
||||
#include "game/vars.h"
|
||||
|
||||
void SetupDart(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->collision = ObjectCollision;
|
||||
obj->control = DartsControl;
|
||||
obj->shadow_size = UNIT_SHADOW / 2;
|
||||
obj->save_flags = 1;
|
||||
}
|
||||
|
||||
void SetupDartEffect(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->control = DartEffectControl;
|
||||
obj->draw_routine = DrawSpriteItem;
|
||||
}
|
||||
|
||||
void DartsControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (item->touch_bits) {
|
||||
LaraItem->hit_points -= 50;
|
||||
LaraItem->hit_status = 1;
|
||||
DoBloodSplat(
|
||||
item->pos.x, item->pos.y, item->pos.z, LaraItem->speed,
|
||||
LaraItem->pos.y_rot, LaraItem->room_number);
|
||||
}
|
||||
AnimateItem(item);
|
||||
|
||||
int16_t room_num = item->room_number;
|
||||
FLOOR_INFO *floor =
|
||||
GetFloor(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
if (item->room_number != room_num) {
|
||||
ItemNewRoom(item_num, room_num);
|
||||
}
|
||||
|
||||
item->floor = GetHeight(floor, item->pos.x, item->pos.y, item->pos.z);
|
||||
if (item->pos.y >= item->floor) {
|
||||
KillItem(item_num);
|
||||
int16_t fx_num = CreateEffect(item->room_number);
|
||||
if (fx_num != NO_ITEM) {
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
fx->pos = item->pos;
|
||||
fx->speed = 0;
|
||||
fx->counter = 6;
|
||||
fx->frame_number = -3 * GetRandomControl() / 0x8000;
|
||||
fx->object_number = O_RICOCHET1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DartEffectControl(int16_t fx_num)
|
||||
{
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
fx->counter++;
|
||||
if (fx->counter >= 3) {
|
||||
fx->counter = 0;
|
||||
fx->frame_number--;
|
||||
if (fx->frame_number <= Objects[fx->object_number].nmeshes) {
|
||||
KillEffect(fx_num);
|
||||
}
|
||||
}
|
||||
}
|
12
src/game/traps/dart.h
Normal file
12
src/game/traps/dart.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef T1M_GAME_TRAPS_DART_H
|
||||
#define T1M_GAME_TRAPS_DART_H
|
||||
|
||||
#include "game/types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void SetupDart(OBJECT_INFO *obj);
|
||||
void SetupDartEffect(OBJECT_INFO *obj);
|
||||
void DartsControl(int16_t item_num);
|
||||
void DartEffectControl(int16_t fx_num);
|
||||
|
||||
#endif
|
73
src/game/traps/dart_emitter.c
Normal file
73
src/game/traps/dart_emitter.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
#include "game/control.h"
|
||||
#include "game/effects.h"
|
||||
#include "game/items.h"
|
||||
#include "game/traps/dart_emitter.h"
|
||||
#include "game/vars.h"
|
||||
|
||||
void SetupDartEmitter(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->control = DartEmitterControl;
|
||||
}
|
||||
|
||||
void DartEmitterControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
|
||||
if (TriggerActive(item)) {
|
||||
if (item->current_anim_state == DART_EMITTER_IDLE) {
|
||||
item->goal_anim_state = DART_EMITTER_FIRE;
|
||||
}
|
||||
} else {
|
||||
if (item->current_anim_state == DART_EMITTER_FIRE) {
|
||||
item->goal_anim_state = DART_EMITTER_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
if (item->current_anim_state == DART_EMITTER_FIRE
|
||||
&& item->frame_number == Anims[item->anim_number].frame_base) {
|
||||
int16_t dart_item_num = CreateItem();
|
||||
if (dart_item_num != NO_ITEM) {
|
||||
ITEM_INFO *dart = &Items[dart_item_num];
|
||||
dart->object_number = O_DARTS;
|
||||
dart->room_number = item->room_number;
|
||||
dart->shade = -1;
|
||||
dart->pos.y_rot = item->pos.y_rot;
|
||||
dart->pos.y = item->pos.y - WALL_L / 2;
|
||||
|
||||
int32_t x = 0;
|
||||
int32_t z = 0;
|
||||
switch (dart->pos.y_rot) {
|
||||
case 0:
|
||||
z = -WALL_L / 2 + 100;
|
||||
break;
|
||||
case PHD_90:
|
||||
x = -WALL_L / 2 + 100;
|
||||
break;
|
||||
case -PHD_180:
|
||||
z = WALL_L / 2 - 100;
|
||||
break;
|
||||
case -PHD_90:
|
||||
x = WALL_L / 2 - 100;
|
||||
break;
|
||||
}
|
||||
|
||||
dart->pos.x = item->pos.x + x;
|
||||
dart->pos.z = item->pos.z + z;
|
||||
InitialiseItem(dart_item_num);
|
||||
AddActiveItem(dart_item_num);
|
||||
dart->status = IS_ACTIVE;
|
||||
|
||||
int16_t fx_num = CreateEffect(dart->room_number);
|
||||
if (fx_num != NO_ITEM) {
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
fx->pos = dart->pos;
|
||||
fx->speed = 0;
|
||||
fx->frame_number = 0;
|
||||
fx->counter = 0;
|
||||
fx->object_number = O_DART_EFFECT;
|
||||
SoundEffect(SFX_DARTS, &fx->pos, SPM_NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
AnimateItem(item);
|
||||
}
|
15
src/game/traps/dart_emitter.h
Normal file
15
src/game/traps/dart_emitter.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef T1M_GAME_TRAPS_DART_EMITTER_H
|
||||
#define T1M_GAME_TRAPS_DART_EMITTER_H
|
||||
|
||||
#include "game/types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
DART_EMITTER_IDLE = 0,
|
||||
DART_EMITTER_FIRE = 1,
|
||||
} DART_EMITTER_STATE;
|
||||
|
||||
void SetupDartEmitter(OBJECT_INFO *obj);
|
||||
void DartEmitterControl(int16_t item_num);
|
||||
|
||||
#endif
|
85
src/game/traps/falling_block.c
Normal file
85
src/game/traps/falling_block.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
#include "game/traps/falling_block.h"
|
||||
#include "game/control.h"
|
||||
#include "game/items.h"
|
||||
#include "game/vars.h"
|
||||
|
||||
void SetupFallingBlock(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->control = FallingBlockControl;
|
||||
obj->floor = FallingBlockFloor;
|
||||
obj->ceiling = FallingBlockCeiling;
|
||||
obj->save_position = 1;
|
||||
obj->save_anim = 1;
|
||||
obj->save_flags = 1;
|
||||
}
|
||||
|
||||
// original name: FallingBlock
|
||||
void FallingBlockControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
|
||||
switch (item->current_anim_state) {
|
||||
case TRAP_SET:
|
||||
if (LaraItem->pos.y == item->pos.y - STEP_L * 2) {
|
||||
item->goal_anim_state = TRAP_ACTIVATE;
|
||||
} else {
|
||||
item->status = IS_NOT_ACTIVE;
|
||||
RemoveActiveItem(item_num);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case TRAP_ACTIVATE:
|
||||
item->goal_anim_state = TRAP_WORKING;
|
||||
break;
|
||||
|
||||
case TRAP_WORKING:
|
||||
if (item->goal_anim_state != TRAP_FINISHED) {
|
||||
item->gravity_status = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
AnimateItem(item);
|
||||
if (item->status == IS_DEACTIVATED) {
|
||||
RemoveActiveItem(item_num);
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t room_num = item->room_number;
|
||||
FLOOR_INFO *floor =
|
||||
GetFloor(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
if (item->room_number != room_num) {
|
||||
ItemNewRoom(item_num, room_num);
|
||||
}
|
||||
|
||||
item->floor = GetHeight(floor, item->pos.x, item->pos.y, item->pos.z);
|
||||
|
||||
if (item->current_anim_state == TRAP_WORKING
|
||||
&& item->pos.y >= item->floor) {
|
||||
item->goal_anim_state = TRAP_FINISHED;
|
||||
item->pos.y = item->floor;
|
||||
item->fall_speed = 0;
|
||||
item->gravity_status = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void FallingBlockFloor(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height)
|
||||
{
|
||||
if (y <= item->pos.y - STEP_L * 2
|
||||
&& (item->current_anim_state == TRAP_SET
|
||||
|| item->current_anim_state == TRAP_ACTIVATE)) {
|
||||
*height = item->pos.y - STEP_L * 2;
|
||||
}
|
||||
}
|
||||
|
||||
void FallingBlockCeiling(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height)
|
||||
{
|
||||
if (y > item->pos.y - STEP_L * 2
|
||||
&& (item->current_anim_state == TRAP_SET
|
||||
|| item->current_anim_state == TRAP_ACTIVATE)) {
|
||||
*height = item->pos.y - STEP_L;
|
||||
}
|
||||
}
|
14
src/game/traps/falling_block.h
Normal file
14
src/game/traps/falling_block.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef T1M_GAME_TRAPS_FALLING_BLOCK_H
|
||||
#define T1M_GAME_TRAPS_FALLING_BLOCK_H
|
||||
|
||||
#include "game/types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void SetupFallingBlock(OBJECT_INFO *obj);
|
||||
void FallingBlockControl(int16_t item_num);
|
||||
void FallingBlockFloor(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height);
|
||||
void FallingBlockCeiling(
|
||||
ITEM_INFO *item, int32_t x, int32_t y, int32_t z, int16_t *height);
|
||||
|
||||
#endif
|
38
src/game/traps/falling_ceiling.c
Normal file
38
src/game/traps/falling_ceiling.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
#include "game/collide.h"
|
||||
#include "game/control.h"
|
||||
#include "game/items.h"
|
||||
#include "game/traps/falling_ceiling.h"
|
||||
#include "game/vars.h"
|
||||
|
||||
void SetupFallingCeilling(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->control = FallingCeilingControl;
|
||||
obj->collision = TrapCollision;
|
||||
obj->save_position = 1;
|
||||
obj->save_anim = 1;
|
||||
obj->save_flags = 1;
|
||||
}
|
||||
|
||||
// original name: FallingCeiling
|
||||
void FallingCeilingControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (item->current_anim_state == TRAP_SET) {
|
||||
item->goal_anim_state = TRAP_ACTIVATE;
|
||||
item->gravity_status = 1;
|
||||
} else if (item->current_anim_state == TRAP_ACTIVATE && item->touch_bits) {
|
||||
LaraItem->hit_points -= FALLING_CEILING_DAMAGE;
|
||||
LaraItem->hit_status = 1;
|
||||
}
|
||||
AnimateItem(item);
|
||||
if (item->status == IS_DEACTIVATED) {
|
||||
RemoveActiveItem(item_num);
|
||||
} else if (
|
||||
item->current_anim_state == TRAP_ACTIVATE
|
||||
&& item->pos.y >= item->floor) {
|
||||
item->goal_anim_state = TRAP_WORKING;
|
||||
item->pos.y = item->floor;
|
||||
item->fall_speed = 0;
|
||||
item->gravity_status = 0;
|
||||
}
|
||||
}
|
12
src/game/traps/falling_ceiling.h
Normal file
12
src/game/traps/falling_ceiling.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef T1M_GAME_TRAPS_FALLING_CEILING_H
|
||||
#define T1M_GAME_TRAPS_FALLING_CEILING_H
|
||||
|
||||
#include "game/types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define FALLING_CEILING_DAMAGE 300
|
||||
|
||||
void SetupFallingCeilling(OBJECT_INFO *obj);
|
||||
void FallingCeilingControl(int16_t item_num);
|
||||
|
||||
#endif
|
113
src/game/traps/flame.c
Normal file
113
src/game/traps/flame.c
Normal file
|
@ -0,0 +1,113 @@
|
|||
#include "game/control.h"
|
||||
#include "game/draw.h"
|
||||
#include "game/effects.h"
|
||||
#include "game/items.h"
|
||||
#include "game/sphere.h"
|
||||
#include "game/traps/flame.h"
|
||||
#include "game/vars.h"
|
||||
|
||||
void SetupFlameEmitter(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->control = FlameEmitterControl;
|
||||
obj->draw_routine = DrawDummyItem;
|
||||
}
|
||||
|
||||
void SetupFlame(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->control = FlameControl;
|
||||
}
|
||||
|
||||
void FlameEmitterControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (TriggerActive(item)) {
|
||||
if (!item->data) {
|
||||
int16_t fx_num = CreateEffect(item->room_number);
|
||||
if (fx_num != NO_ITEM) {
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
fx->pos.x = item->pos.x;
|
||||
fx->pos.y = item->pos.y;
|
||||
fx->pos.z = item->pos.z;
|
||||
fx->frame_number = 0;
|
||||
fx->object_number = O_FLAME;
|
||||
fx->counter = 0;
|
||||
}
|
||||
item->data = (void *)(fx_num + 1);
|
||||
}
|
||||
} else if (item->data) {
|
||||
StopSoundEffect(SFX_FIRE, NULL);
|
||||
KillEffect((int16_t)(size_t)item->data - 1);
|
||||
item->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void FlameControl(int16_t fx_num)
|
||||
{
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
|
||||
fx->frame_number--;
|
||||
if (fx->frame_number <= Objects[O_FLAME].nmeshes) {
|
||||
fx->frame_number = 0;
|
||||
}
|
||||
|
||||
if (fx->counter < 0) {
|
||||
if (Lara.water_status == LWS_CHEAT) {
|
||||
fx->counter = 0;
|
||||
StopSoundEffect(SFX_FIRE, NULL);
|
||||
KillEffect(fx_num);
|
||||
}
|
||||
|
||||
fx->pos.x = 0;
|
||||
fx->pos.y = 0;
|
||||
if (fx->counter == -1) {
|
||||
fx->pos.z = -100;
|
||||
} else {
|
||||
fx->pos.z = 0;
|
||||
}
|
||||
|
||||
GetJointAbsPosition(LaraItem, (PHD_VECTOR *)&fx->pos, -1 - fx->counter);
|
||||
|
||||
int32_t y = GetWaterHeight(
|
||||
LaraItem->pos.x, LaraItem->pos.y, LaraItem->pos.z,
|
||||
LaraItem->room_number);
|
||||
|
||||
if (y != NO_HEIGHT && fx->pos.y > y) {
|
||||
fx->counter = 0;
|
||||
StopSoundEffect(SFX_FIRE, NULL);
|
||||
KillEffect(fx_num);
|
||||
} else {
|
||||
SoundEffect(SFX_FIRE, &fx->pos, SPM_NORMAL);
|
||||
LaraItem->hit_points -= FLAME_ONFIRE_DAMAGE;
|
||||
LaraItem->hit_status = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
SoundEffect(SFX_FIRE, &fx->pos, SPM_NORMAL);
|
||||
if (fx->counter) {
|
||||
fx->counter--;
|
||||
} else if (ItemNearLara(&fx->pos, 600)) {
|
||||
if (Lara.water_status == LWS_CHEAT) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t x = LaraItem->pos.x - fx->pos.x;
|
||||
int32_t z = LaraItem->pos.z - fx->pos.z;
|
||||
int32_t distance = SQUARE(x) + SQUARE(z);
|
||||
|
||||
LaraItem->hit_points -= FLAME_TOONEAR_DAMAGE;
|
||||
LaraItem->hit_status = 1;
|
||||
|
||||
if (distance < SQUARE(300)) {
|
||||
fx->counter = 100;
|
||||
|
||||
fx_num = CreateEffect(LaraItem->room_number);
|
||||
if (fx_num != NO_ITEM) {
|
||||
fx = &Effects[fx_num];
|
||||
fx->frame_number = 0;
|
||||
fx->object_number = O_FLAME;
|
||||
fx->counter = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
15
src/game/traps/flame.h
Normal file
15
src/game/traps/flame.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef T1M_GAME_TRAPS_FLAME_H
|
||||
#define T1M_GAME_TRAPS_FLAME_H
|
||||
|
||||
#include "game/types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define FLAME_ONFIRE_DAMAGE 5
|
||||
#define FLAME_TOONEAR_DAMAGE 3
|
||||
|
||||
void SetupFlameEmitter(OBJECT_INFO *obj);
|
||||
void SetupFlame(OBJECT_INFO *obj);
|
||||
void FlameEmitterControl(int16_t item_num);
|
||||
void FlameControl(int16_t fx_num);
|
||||
|
||||
#endif
|
160
src/game/traps/lava.c
Normal file
160
src/game/traps/lava.c
Normal file
|
@ -0,0 +1,160 @@
|
|||
#include "3dsystem/phd_math.h"
|
||||
#include "game/collide.h"
|
||||
#include "game/control.h"
|
||||
#include "game/draw.h"
|
||||
#include "game/effects.h"
|
||||
#include "game/game.h"
|
||||
#include "game/items.h"
|
||||
#include "game/traps/lava.h"
|
||||
#include "game/vars.h"
|
||||
|
||||
void SetupLavaEmitter(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->control = LavaEmitterControl;
|
||||
obj->draw_routine = DrawDummyItem;
|
||||
obj->collision = ObjectCollision;
|
||||
}
|
||||
|
||||
void SetupLava(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->control = LavaControl;
|
||||
}
|
||||
|
||||
void SetupLavaWedge(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->control = LavaWedgeControl;
|
||||
obj->collision = CreatureCollision;
|
||||
obj->save_position = 1;
|
||||
obj->save_anim = 1;
|
||||
obj->save_flags = 1;
|
||||
}
|
||||
|
||||
void LavaBurn(ITEM_INFO *item)
|
||||
{
|
||||
if (Lara.water_status == LWS_CHEAT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (item->hit_points < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t room_num = item->room_number;
|
||||
FLOOR_INFO *floor = GetFloor(item->pos.x, 32000, item->pos.z, &room_num);
|
||||
|
||||
if (item->floor != GetHeight(floor, item->pos.x, 32000, item->pos.z)) {
|
||||
return;
|
||||
}
|
||||
|
||||
item->hit_points = -1;
|
||||
item->hit_status = 1;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int16_t fx_num = CreateEffect(item->room_number);
|
||||
if (fx_num != NO_ITEM) {
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
fx->object_number = O_FLAME;
|
||||
fx->frame_number =
|
||||
(Objects[O_FLAME].nmeshes * GetRandomControl()) / 0x7FFF;
|
||||
fx->counter = -1 - GetRandomControl() * 24 / 0x7FFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// original name: LavaSpray
|
||||
void LavaEmitterControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
int16_t fx_num = CreateEffect(item->room_number);
|
||||
if (fx_num != NO_ITEM) {
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
fx->pos.x = item->pos.x;
|
||||
fx->pos.y = item->pos.y;
|
||||
fx->pos.z = item->pos.z;
|
||||
fx->pos.y_rot = (GetRandomControl() - 0x4000) * 2;
|
||||
fx->speed = GetRandomControl() >> 10;
|
||||
fx->fall_speed = -GetRandomControl() / 200;
|
||||
fx->frame_number = -4 * GetRandomControl() / 0x7FFF;
|
||||
fx->object_number = O_LAVA;
|
||||
SoundEffect(SFX_LAVA_FOUNTAIN, &item->pos, SPM_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
// original name: ControlLavaBlob
|
||||
void LavaControl(int16_t fx_num)
|
||||
{
|
||||
FX_INFO *fx = &Effects[fx_num];
|
||||
fx->pos.z += (fx->speed * phd_cos(fx->pos.y_rot)) >> W2V_SHIFT;
|
||||
fx->pos.x += (fx->speed * phd_sin(fx->pos.y_rot)) >> W2V_SHIFT;
|
||||
fx->fall_speed += GRAVITY;
|
||||
fx->pos.y += fx->fall_speed;
|
||||
|
||||
int16_t room_num = fx->room_number;
|
||||
FLOOR_INFO *floor = GetFloor(fx->pos.x, fx->pos.y, fx->pos.z, &room_num);
|
||||
if (fx->pos.y >= GetHeight(floor, fx->pos.x, fx->pos.y, fx->pos.z)
|
||||
|| fx->pos.y < GetCeiling(floor, fx->pos.x, fx->pos.y, fx->pos.z)) {
|
||||
KillEffect(fx_num);
|
||||
} else if (ItemNearLara(&fx->pos, 200)) {
|
||||
LaraItem->hit_points -= LAVA_GLOB_DAMAGE;
|
||||
LaraItem->hit_status = 1;
|
||||
KillEffect(fx_num);
|
||||
} else if (room_num != fx->room_number) {
|
||||
EffectNewRoom(fx_num, room_num);
|
||||
}
|
||||
}
|
||||
|
||||
// original name: LavaWedge
|
||||
void LavaWedgeControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
|
||||
int16_t room_num = item->room_number;
|
||||
GetFloor(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
if (room_num != item->room_number) {
|
||||
ItemNewRoom(item_num, room_num);
|
||||
}
|
||||
|
||||
if (item->status != IS_DEACTIVATED) {
|
||||
int32_t x = item->pos.x;
|
||||
int32_t z = item->pos.z;
|
||||
|
||||
switch (item->pos.y_rot) {
|
||||
case 0:
|
||||
item->pos.z += LAVA_WEDGE_SPEED;
|
||||
z += 2 * WALL_L;
|
||||
break;
|
||||
case -PHD_180:
|
||||
item->pos.z -= LAVA_WEDGE_SPEED;
|
||||
z -= 2 * WALL_L;
|
||||
break;
|
||||
case PHD_90:
|
||||
item->pos.x += LAVA_WEDGE_SPEED;
|
||||
x += 2 * WALL_L;
|
||||
break;
|
||||
default:
|
||||
item->pos.x -= LAVA_WEDGE_SPEED;
|
||||
x -= 2 * WALL_L;
|
||||
break;
|
||||
}
|
||||
|
||||
FLOOR_INFO *floor = GetFloor(x, item->pos.y, z, &room_num);
|
||||
if (GetHeight(floor, x, item->pos.y, z) != item->pos.y) {
|
||||
item->status = IS_DEACTIVATED;
|
||||
}
|
||||
}
|
||||
|
||||
if (Lara.water_status == LWS_CHEAT) {
|
||||
item->touch_bits = 0;
|
||||
}
|
||||
|
||||
if (item->touch_bits) {
|
||||
if (LaraItem->hit_points > 0) {
|
||||
LavaBurn(LaraItem);
|
||||
}
|
||||
|
||||
Camera.item = item;
|
||||
Camera.flags = CHASE_OBJECT;
|
||||
Camera.type = CAM_FIXED;
|
||||
Camera.target_angle = -PHD_180;
|
||||
Camera.target_distance = WALL_L * 3;
|
||||
}
|
||||
}
|
18
src/game/traps/lava.h
Normal file
18
src/game/traps/lava.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef T1M_GAME_TRAPS_LAVA_H
|
||||
#define T1M_GAME_TRAPS_LAVA_H
|
||||
|
||||
#include "game/types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define LAVA_GLOB_DAMAGE 10
|
||||
#define LAVA_WEDGE_SPEED 25
|
||||
|
||||
void SetupLavaEmitter(OBJECT_INFO *obj);
|
||||
void SetupLava(OBJECT_INFO *obj);
|
||||
void SetupLavaWedge(OBJECT_INFO *obj);
|
||||
void LavaBurn(ITEM_INFO *item);
|
||||
void LavaEmitterControl(int16_t item_num);
|
||||
void LavaControl(int16_t fx_num);
|
||||
void LavaWedgeControl(int16_t item_num);
|
||||
|
||||
#endif
|
|
@ -1,42 +1,144 @@
|
|||
#include "3dsystem/3d_gen.h"
|
||||
#include "game/collide.h"
|
||||
#include "game/const.h"
|
||||
#include "3dsystem/phd_math.h"
|
||||
#include "game/control.h"
|
||||
#include "game/draw.h"
|
||||
#include "game/effects.h"
|
||||
#include "game/game.h"
|
||||
#include "game/items.h"
|
||||
#include "game/lightning.h"
|
||||
#include "game/moveblock.h"
|
||||
#include "game/sphere.h"
|
||||
#include "game/traps/lightning_emitter.h"
|
||||
#include "game/vars.h"
|
||||
#include "specific/init.h"
|
||||
#include "specific/output.h"
|
||||
#include "util.h"
|
||||
|
||||
#define LIGHTNING_DAMAGE 400
|
||||
#define LIGHTNING_STEPS 8
|
||||
#define LIGHTNING_RND ((64 << W2V_SHIFT) / 0x8000) // = 32
|
||||
#define LIGHTNING_SHOOTS 2
|
||||
void SetupLightningEmitter(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->initialise = InitialiseLightning;
|
||||
obj->control = LightningControl;
|
||||
obj->draw_routine = DrawLightning;
|
||||
obj->collision = LightningCollision;
|
||||
obj->save_flags = 1;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int32_t onstate;
|
||||
int32_t count;
|
||||
int32_t zapped;
|
||||
int32_t notarget;
|
||||
PHD_VECTOR target;
|
||||
PHD_VECTOR main[LIGHTNING_STEPS], wibble[LIGHTNING_STEPS];
|
||||
int start[LIGHTNING_SHOOTS];
|
||||
PHD_VECTOR end[LIGHTNING_SHOOTS];
|
||||
PHD_VECTOR shoot[LIGHTNING_SHOOTS][LIGHTNING_STEPS];
|
||||
} LIGHTNING;
|
||||
void InitialiseLightning(int16_t item_num)
|
||||
{
|
||||
LIGHTNING *l = game_malloc(sizeof(LIGHTNING), 0);
|
||||
Items[item_num].data = l;
|
||||
|
||||
typedef enum {
|
||||
THS_SET = 0,
|
||||
THS_TEASE = 1,
|
||||
THS_ACTIVE = 2,
|
||||
THS_DONE = 3,
|
||||
} THOR_HAMMER_STATE;
|
||||
if (Objects[Items[item_num].object_number].nmeshes > 1) {
|
||||
Items[item_num].mesh_bits = 1;
|
||||
l->notarget = 0;
|
||||
} else {
|
||||
l->notarget = 1;
|
||||
}
|
||||
|
||||
l->onstate = 0;
|
||||
l->count = 1;
|
||||
l->zapped = 0;
|
||||
}
|
||||
|
||||
void LightningControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
LIGHTNING *l = item->data;
|
||||
|
||||
if (!TriggerActive(item)) {
|
||||
l->count = 1;
|
||||
l->onstate = 0;
|
||||
l->zapped = 0;
|
||||
|
||||
if (FlipStatus) {
|
||||
FlipMap();
|
||||
}
|
||||
|
||||
RemoveActiveItem(item_num);
|
||||
item->status = IS_NOT_ACTIVE;
|
||||
return;
|
||||
}
|
||||
|
||||
l->count--;
|
||||
if (l->count > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (l->onstate) {
|
||||
l->onstate = 0;
|
||||
l->count = 35 + (GetRandomControl() * 45) / 0x8000;
|
||||
l->zapped = 0;
|
||||
if (FlipStatus) {
|
||||
FlipMap();
|
||||
}
|
||||
} else {
|
||||
l->onstate = 1;
|
||||
l->count = 20;
|
||||
|
||||
for (int i = 0; i < LIGHTNING_STEPS; i++) {
|
||||
l->wibble[i].x = 0;
|
||||
l->wibble[i].y = 0;
|
||||
l->wibble[i].z = 0;
|
||||
}
|
||||
|
||||
int32_t radius = l->notarget ? WALL_L : WALL_L * 5 / 2;
|
||||
if (ItemNearLara(&item->pos, radius)) {
|
||||
l->target.x = LaraItem->pos.x;
|
||||
l->target.y = LaraItem->pos.y;
|
||||
l->target.z = LaraItem->pos.z;
|
||||
|
||||
LaraItem->hit_points -= LIGHTNING_DAMAGE;
|
||||
LaraItem->hit_status = 1;
|
||||
|
||||
l->zapped = 1;
|
||||
} else if (l->notarget) {
|
||||
FLOOR_INFO *floor = GetFloor(
|
||||
item->pos.x, item->pos.y, item->pos.z, &item->room_number);
|
||||
int32_t h = GetHeight(floor, item->pos.x, item->pos.y, item->pos.z);
|
||||
l->target.x = item->pos.x;
|
||||
l->target.y = h;
|
||||
l->target.z = item->pos.z;
|
||||
l->zapped = 0;
|
||||
} else {
|
||||
l->target.x = 0;
|
||||
l->target.y = 0;
|
||||
l->target.z = 0;
|
||||
GetJointAbsPosition(
|
||||
item, &l->target, 1 + (GetRandomControl() * 5) / 0x7FFF);
|
||||
l->zapped = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < LIGHTNING_SHOOTS; i++) {
|
||||
l->start[i] = GetRandomControl() * (LIGHTNING_STEPS - 1) / 0x7FFF;
|
||||
l->end[i].x = l->target.x + (GetRandomControl() * WALL_L) / 0x7FFF;
|
||||
l->end[i].y = l->target.y;
|
||||
l->end[i].z = l->target.z + (GetRandomControl() * WALL_L) / 0x7FFF;
|
||||
|
||||
for (int j = 0; j < LIGHTNING_STEPS; j++) {
|
||||
l->shoot[i][j].x = 0;
|
||||
l->shoot[i][j].y = 0;
|
||||
l->shoot[i][j].z = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!FlipStatus) {
|
||||
FlipMap();
|
||||
}
|
||||
}
|
||||
|
||||
SoundEffect(SFX_THUNDER, &item->pos, SPM_NORMAL);
|
||||
}
|
||||
|
||||
void LightningCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll)
|
||||
{
|
||||
LIGHTNING *l = Items[item_num].data;
|
||||
if (!l->zapped) {
|
||||
return;
|
||||
}
|
||||
|
||||
Lara.hit_direction = 1 + (GetRandomControl() * 4) / (PHD_180 - 1);
|
||||
Lara.hit_frame++;
|
||||
if (Lara.hit_frame > 34) {
|
||||
Lara.hit_frame = 34;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawLightning(ITEM_INFO *item)
|
||||
{
|
||||
|
@ -165,280 +267,3 @@ void DrawLightning(ITEM_INFO *item)
|
|||
|
||||
phd_PopMatrix();
|
||||
}
|
||||
|
||||
void InitialiseLightning(int16_t item_num)
|
||||
{
|
||||
LIGHTNING *l = game_malloc(sizeof(LIGHTNING), 0);
|
||||
Items[item_num].data = l;
|
||||
|
||||
if (Objects[Items[item_num].object_number].nmeshes > 1) {
|
||||
Items[item_num].mesh_bits = 1;
|
||||
l->notarget = 0;
|
||||
} else {
|
||||
l->notarget = 1;
|
||||
}
|
||||
|
||||
l->onstate = 0;
|
||||
l->count = 1;
|
||||
l->zapped = 0;
|
||||
}
|
||||
|
||||
void LightningControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
LIGHTNING *l = item->data;
|
||||
|
||||
if (!TriggerActive(item)) {
|
||||
l->count = 1;
|
||||
l->onstate = 0;
|
||||
l->zapped = 0;
|
||||
|
||||
if (FlipStatus) {
|
||||
FlipMap();
|
||||
}
|
||||
|
||||
RemoveActiveItem(item_num);
|
||||
item->status = IS_NOT_ACTIVE;
|
||||
return;
|
||||
}
|
||||
|
||||
l->count--;
|
||||
if (l->count > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (l->onstate) {
|
||||
l->onstate = 0;
|
||||
l->count = 35 + (GetRandomControl() * 45) / 0x8000;
|
||||
l->zapped = 0;
|
||||
if (FlipStatus) {
|
||||
FlipMap();
|
||||
}
|
||||
} else {
|
||||
l->onstate = 1;
|
||||
l->count = 20;
|
||||
|
||||
for (int i = 0; i < LIGHTNING_STEPS; i++) {
|
||||
l->wibble[i].x = 0;
|
||||
l->wibble[i].y = 0;
|
||||
l->wibble[i].z = 0;
|
||||
}
|
||||
|
||||
int32_t radius = l->notarget ? WALL_L : WALL_L * 5 / 2;
|
||||
if (ItemNearLara(&item->pos, radius)) {
|
||||
l->target.x = LaraItem->pos.x;
|
||||
l->target.y = LaraItem->pos.y;
|
||||
l->target.z = LaraItem->pos.z;
|
||||
|
||||
LaraItem->hit_points -= LIGHTNING_DAMAGE;
|
||||
LaraItem->hit_status = 1;
|
||||
|
||||
l->zapped = 1;
|
||||
} else if (l->notarget) {
|
||||
FLOOR_INFO *floor = GetFloor(
|
||||
item->pos.x, item->pos.y, item->pos.z, &item->room_number);
|
||||
int32_t h = GetHeight(floor, item->pos.x, item->pos.y, item->pos.z);
|
||||
l->target.x = item->pos.x;
|
||||
l->target.y = h;
|
||||
l->target.z = item->pos.z;
|
||||
l->zapped = 0;
|
||||
} else {
|
||||
l->target.x = 0;
|
||||
l->target.y = 0;
|
||||
l->target.z = 0;
|
||||
GetJointAbsPosition(
|
||||
item, &l->target, 1 + (GetRandomControl() * 5) / 0x7FFF);
|
||||
l->zapped = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < LIGHTNING_SHOOTS; i++) {
|
||||
l->start[i] = GetRandomControl() * (LIGHTNING_STEPS - 1) / 0x7FFF;
|
||||
l->end[i].x = l->target.x + (GetRandomControl() * WALL_L) / 0x7FFF;
|
||||
l->end[i].y = l->target.y;
|
||||
l->end[i].z = l->target.z + (GetRandomControl() * WALL_L) / 0x7FFF;
|
||||
|
||||
for (int j = 0; j < LIGHTNING_STEPS; j++) {
|
||||
l->shoot[i][j].x = 0;
|
||||
l->shoot[i][j].y = 0;
|
||||
l->shoot[i][j].z = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!FlipStatus) {
|
||||
FlipMap();
|
||||
}
|
||||
}
|
||||
|
||||
SoundEffect(SFX_THUNDER, &item->pos, SPM_NORMAL);
|
||||
}
|
||||
|
||||
void LightningCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll)
|
||||
{
|
||||
LIGHTNING *l = Items[item_num].data;
|
||||
if (!l->zapped) {
|
||||
return;
|
||||
}
|
||||
|
||||
Lara.hit_direction = 1 + (GetRandomControl() * 4) / (PHD_180 - 1);
|
||||
Lara.hit_frame++;
|
||||
if (Lara.hit_frame > 34) {
|
||||
Lara.hit_frame = 34;
|
||||
}
|
||||
}
|
||||
|
||||
void InitialiseThorsHandle(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *hand_item = &Items[item_num];
|
||||
int16_t head_item_num = CreateItem();
|
||||
ITEM_INFO *head_item = &Items[head_item_num];
|
||||
head_item->object_number = O_THORS_HEAD;
|
||||
head_item->room_number = hand_item->room_number;
|
||||
head_item->pos = hand_item->pos;
|
||||
head_item->shade = hand_item->shade;
|
||||
InitialiseItem(head_item_num);
|
||||
hand_item->data = head_item;
|
||||
LevelItemCount++;
|
||||
}
|
||||
|
||||
void ThorsHandleControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
|
||||
switch (item->current_anim_state) {
|
||||
case THS_SET:
|
||||
if (TriggerActive(item)) {
|
||||
item->goal_anim_state = THS_TEASE;
|
||||
} else {
|
||||
RemoveActiveItem(item_num);
|
||||
item->status = IS_NOT_ACTIVE;
|
||||
}
|
||||
break;
|
||||
|
||||
case THS_TEASE:
|
||||
if (TriggerActive(item)) {
|
||||
item->goal_anim_state = THS_ACTIVE;
|
||||
} else {
|
||||
item->goal_anim_state = THS_SET;
|
||||
}
|
||||
break;
|
||||
|
||||
case THS_ACTIVE: {
|
||||
int32_t frm = item->frame_number - Anims[item->anim_number].frame_base;
|
||||
if (frm > 30) {
|
||||
int32_t x = item->pos.x;
|
||||
int32_t z = item->pos.z;
|
||||
|
||||
switch (item->pos.y_rot) {
|
||||
case 0:
|
||||
z += WALL_L * 3;
|
||||
break;
|
||||
case PHD_90:
|
||||
x += WALL_L * 3;
|
||||
break;
|
||||
case -PHD_90:
|
||||
x -= WALL_L * 3;
|
||||
break;
|
||||
case -PHD_180:
|
||||
z -= WALL_L * 3;
|
||||
break;
|
||||
}
|
||||
|
||||
if (LaraItem->hit_points >= 0 && LaraItem->pos.x > x - 520
|
||||
&& LaraItem->pos.x < x + 520 && LaraItem->pos.z > z - 520
|
||||
&& LaraItem->pos.z < z + 520) {
|
||||
LaraItem->hit_points = -1;
|
||||
LaraItem->pos.y = item->pos.y;
|
||||
LaraItem->gravity_status = 0;
|
||||
LaraItem->current_anim_state = AS_SPECIAL;
|
||||
LaraItem->goal_anim_state = AS_SPECIAL;
|
||||
LaraItem->anim_number = AA_RBALL_DEATH;
|
||||
LaraItem->frame_number = AF_RBALL_DEATH;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case THS_DONE: {
|
||||
int32_t x = item->pos.x;
|
||||
int32_t z = item->pos.z;
|
||||
int32_t old_x = x;
|
||||
int32_t old_z = z;
|
||||
|
||||
int16_t room_num = item->room_number;
|
||||
FLOOR_INFO *floor = GetFloor(x, item->pos.y, z, &room_num);
|
||||
GetHeight(floor, x, item->pos.y, z);
|
||||
TestTriggers(TriggerIndex, 1);
|
||||
|
||||
switch (item->pos.y_rot) {
|
||||
case 0:
|
||||
z += WALL_L * 3;
|
||||
break;
|
||||
case PHD_90:
|
||||
x += WALL_L * 3;
|
||||
break;
|
||||
case -PHD_90:
|
||||
x -= WALL_L * 3;
|
||||
break;
|
||||
case -PHD_180:
|
||||
z -= WALL_L * 3;
|
||||
break;
|
||||
}
|
||||
|
||||
item->pos.x = x;
|
||||
item->pos.z = z;
|
||||
if (LaraItem->hit_points >= 0) {
|
||||
AlterFloorHeight(item, -2 * WALL_L);
|
||||
}
|
||||
item->pos.x = old_x;
|
||||
item->pos.z = old_z;
|
||||
|
||||
RemoveActiveItem(item_num);
|
||||
item->status = IS_DEACTIVATED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
AnimateItem(item);
|
||||
|
||||
ITEM_INFO *head_item = item->data;
|
||||
int32_t anim = item->anim_number - Objects[O_THORS_HANDLE].anim_index;
|
||||
int32_t frm = item->frame_number - Anims[item->anim_number].frame_base;
|
||||
head_item->anim_number = Objects[O_THORS_HEAD].anim_index + anim;
|
||||
head_item->frame_number = Anims[head_item->anim_number].frame_base + frm;
|
||||
head_item->current_anim_state = item->current_anim_state;
|
||||
}
|
||||
|
||||
void ThorsHandleCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (!TestBoundsCollide(item, lara_item, coll->radius)) {
|
||||
return;
|
||||
}
|
||||
if (coll->enable_baddie_push) {
|
||||
ItemPushLara(item, lara_item, coll, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ThorsHeadCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (!TestBoundsCollide(item, lara_item, coll->radius)) {
|
||||
return;
|
||||
}
|
||||
if (coll->enable_baddie_push && item->current_anim_state != THS_ACTIVE) {
|
||||
ItemPushLara(item, lara_item, coll, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void T1MInjectGameLightning()
|
||||
{
|
||||
INJECT(0x00429620, DrawLightning);
|
||||
INJECT(0x00429B00, InitialiseLightning);
|
||||
INJECT(0x00429B80, LightningControl);
|
||||
INJECT(0x00429E30, LightningCollision);
|
||||
|
||||
INJECT(0x00429EA0, InitialiseThorsHandle);
|
||||
INJECT(0x00429F30, ThorsHandleControl);
|
||||
INJECT(0x0042A1F0, ThorsHandleCollision);
|
||||
INJECT(0x0042A240, ThorsHeadCollision);
|
||||
}
|
30
src/game/traps/lightning_emitter.h
Normal file
30
src/game/traps/lightning_emitter.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef T1M_GAME_TRAPS_LIGHTNING_EMITTER_H
|
||||
#define T1M_GAME_TRAPS_LIGHTNING_EMITTER_H
|
||||
|
||||
#include "game/types.h"
|
||||
|
||||
#define LIGHTNING_DAMAGE 400
|
||||
#define LIGHTNING_STEPS 8
|
||||
#define LIGHTNING_RND ((64 << W2V_SHIFT) / 0x8000) // = 32
|
||||
#define LIGHTNING_SHOOTS 2
|
||||
|
||||
typedef struct {
|
||||
int32_t onstate;
|
||||
int32_t count;
|
||||
int32_t zapped;
|
||||
int32_t notarget;
|
||||
PHD_VECTOR target;
|
||||
PHD_VECTOR main[LIGHTNING_STEPS], wibble[LIGHTNING_STEPS];
|
||||
int start[LIGHTNING_SHOOTS];
|
||||
PHD_VECTOR end[LIGHTNING_SHOOTS];
|
||||
PHD_VECTOR shoot[LIGHTNING_SHOOTS][LIGHTNING_STEPS];
|
||||
} LIGHTNING;
|
||||
|
||||
void SetupLightningEmitter(OBJECT_INFO *obj);
|
||||
void InitialiseLightning(int16_t item_num);
|
||||
void LightningControl(int16_t item_num);
|
||||
void LightningCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
void DrawLightning(ITEM_INFO *item);
|
||||
|
||||
#endif
|
91
src/game/traps/midas_touch.c
Normal file
91
src/game/traps/midas_touch.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include "game/collide.h"
|
||||
#include "game/draw.h"
|
||||
#include "game/inv.h"
|
||||
#include "game/traps/midas_touch.h"
|
||||
#include "game/vars.h"
|
||||
|
||||
int16_t MidasBounds[12] = {
|
||||
-700,
|
||||
+700,
|
||||
+384 - 100,
|
||||
+384 + 100 + 512,
|
||||
-700,
|
||||
+700,
|
||||
-10 * PHD_DEGREE,
|
||||
+10 * PHD_DEGREE,
|
||||
-30 * PHD_DEGREE,
|
||||
+30 * PHD_DEGREE,
|
||||
-10 * PHD_DEGREE,
|
||||
+10 * PHD_DEGREE,
|
||||
};
|
||||
|
||||
void SetupMidasTouch(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->collision = MidasCollision;
|
||||
obj->draw_routine = DrawDummyItem;
|
||||
}
|
||||
|
||||
void MidasCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
|
||||
if (!lara_item->gravity_status && lara_item->current_anim_state == AS_STOP
|
||||
&& lara_item->pos.x > item->pos.x - 512
|
||||
&& lara_item->pos.x < item->pos.x + 512
|
||||
&& lara_item->pos.z > item->pos.z - 512
|
||||
&& lara_item->pos.z < item->pos.z + 512) {
|
||||
lara_item->current_anim_state = AS_DIEMIDAS;
|
||||
lara_item->goal_anim_state = AS_DIEMIDAS;
|
||||
lara_item->anim_number = Objects[O_LARA_EXTRA].anim_index + 1;
|
||||
lara_item->frame_number = Anims[lara_item->anim_number].frame_base;
|
||||
lara_item->hit_points = -1;
|
||||
lara_item->gravity_status = 0;
|
||||
Lara.air = -1;
|
||||
Lara.gun_status = LGS_HANDSBUSY;
|
||||
Lara.gun_type = LGT_UNARMED;
|
||||
Camera.type = CAM_CINEMATIC;
|
||||
CineFrame = 0;
|
||||
CinematicPosition = lara_item->pos;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((InventoryChosen == -1 && !CHK_ANY(Input, IN_ACTION))
|
||||
|| Lara.gun_status != LGS_ARMLESS || lara_item->gravity_status
|
||||
|| lara_item->current_anim_state != AS_STOP) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t quadrant = (uint16_t)(lara_item->pos.y_rot + PHD_45) / PHD_90;
|
||||
switch (quadrant) {
|
||||
case DIR_NORTH:
|
||||
item->pos.y_rot = 0;
|
||||
break;
|
||||
case DIR_EAST:
|
||||
item->pos.y_rot = PHD_90;
|
||||
break;
|
||||
case DIR_SOUTH:
|
||||
item->pos.y_rot = -PHD_180;
|
||||
break;
|
||||
case DIR_WEST:
|
||||
item->pos.y_rot = -PHD_90;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!TestLaraPosition(MidasBounds, item, lara_item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (InventoryChosen == -1) {
|
||||
Display_Inventory(INV_KEYS_MODE);
|
||||
}
|
||||
|
||||
if (InventoryChosen == O_LEADBAR_OPTION) {
|
||||
Inv_RemoveItem(O_LEADBAR_OPTION);
|
||||
Inv_AddItem(O_PUZZLE_ITEM1);
|
||||
lara_item->current_anim_state = AS_USEMIDAS;
|
||||
lara_item->goal_anim_state = AS_USEMIDAS;
|
||||
lara_item->anim_number = Objects[O_LARA_EXTRA].anim_index;
|
||||
lara_item->frame_number = Anims[item->anim_number].frame_base;
|
||||
Lara.gun_status = LGS_HANDSBUSY;
|
||||
}
|
||||
}
|
12
src/game/traps/midas_touch.h
Normal file
12
src/game/traps/midas_touch.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef T1M_GAME_TRAPS_MIDAS_TOUCH_H
|
||||
#define T1M_GAME_TRAPS_MIDAS_TOUCH_H
|
||||
|
||||
#include "game/types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
extern int16_t MidasBounds[12];
|
||||
|
||||
void SetupMidasTouch(OBJECT_INFO *obj);
|
||||
void MidasCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
|
||||
#endif
|
|
@ -4,30 +4,19 @@
|
|||
#include "game/effects.h"
|
||||
#include "game/items.h"
|
||||
#include "game/lara.h"
|
||||
#include "game/moveblock.h"
|
||||
#include "game/traps/movable_block.h"
|
||||
#include "game/vars.h"
|
||||
#include "util.h"
|
||||
|
||||
typedef enum {
|
||||
MBS_STILL = 1,
|
||||
MBS_PUSH = 2,
|
||||
MBS_PULL = 3,
|
||||
} MOVABLE_BLOCK_STATE;
|
||||
|
||||
static int16_t MovingBlockBounds[12] = {
|
||||
-300,
|
||||
+300,
|
||||
0,
|
||||
0,
|
||||
-WALL_L / 2 - (LARA_RAD + 80),
|
||||
-WALL_L / 2,
|
||||
-10 * PHD_DEGREE,
|
||||
+10 * PHD_DEGREE,
|
||||
-30 * PHD_DEGREE,
|
||||
+30 * PHD_DEGREE,
|
||||
-10 * PHD_DEGREE,
|
||||
+10 * PHD_DEGREE,
|
||||
};
|
||||
void SetupMovableBlock(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->initialise = InitialiseMovableBlock;
|
||||
obj->control = MovableBlockControl;
|
||||
obj->draw_routine = DrawMovableBlock;
|
||||
obj->collision = MovableBlockCollision;
|
||||
obj->save_position = 1;
|
||||
obj->save_anim = 1;
|
||||
obj->save_flags = 1;
|
||||
}
|
||||
|
||||
// original name: InitialiseMovingBlock
|
||||
void InitialiseMovableBlock(int16_t item_num)
|
||||
|
@ -178,6 +167,15 @@ void MovableBlockCollision(
|
|||
}
|
||||
}
|
||||
|
||||
void DrawMovableBlock(ITEM_INFO *item)
|
||||
{
|
||||
if (item->status == IS_ACTIVE) {
|
||||
DrawUnclippedItem(item);
|
||||
} else {
|
||||
DrawAnimatingItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t TestBlockMovable(ITEM_INFO *item, int32_t blockhite)
|
||||
{
|
||||
int16_t room_num = item->room_number;
|
||||
|
@ -313,44 +311,6 @@ int32_t TestBlockPull(ITEM_INFO *item, int32_t blockhite, uint16_t quadrant)
|
|||
return 1;
|
||||
}
|
||||
|
||||
void InitialiseRollingBlock(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
AlterFloorHeight(item, -2048);
|
||||
}
|
||||
|
||||
// original name: RollingBlock
|
||||
void RollingBlockControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (TriggerActive(item)) {
|
||||
if (item->current_anim_state == RBS_START) {
|
||||
item->goal_anim_state = RBS_END;
|
||||
AlterFloorHeight(item, 2048);
|
||||
}
|
||||
} else if (item->current_anim_state == RBS_END) {
|
||||
item->goal_anim_state = RBS_START;
|
||||
AlterFloorHeight(item, 2048);
|
||||
}
|
||||
|
||||
AnimateItem(item);
|
||||
|
||||
int16_t room_num = item->room_number;
|
||||
GetFloor(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
if (item->room_number != room_num) {
|
||||
ItemNewRoom(item_num, room_num);
|
||||
}
|
||||
|
||||
if (item->status == IS_DEACTIVATED) {
|
||||
item->status = IS_ACTIVE;
|
||||
AlterFloorHeight(item, -2048);
|
||||
item->pos.x &= -WALL_L;
|
||||
item->pos.x += WALL_L / 2;
|
||||
item->pos.z &= -WALL_L;
|
||||
item->pos.z += WALL_L / 2;
|
||||
}
|
||||
}
|
||||
|
||||
void AlterFloorHeight(ITEM_INFO *item, int32_t height)
|
||||
{
|
||||
int16_t room_num = item->room_number;
|
||||
|
@ -376,25 +336,3 @@ void AlterFloorHeight(ITEM_INFO *item, int32_t height)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawMovableBlock(ITEM_INFO *item)
|
||||
{
|
||||
if (item->status == IS_ACTIVE) {
|
||||
DrawUnclippedItem(item);
|
||||
} else {
|
||||
DrawAnimatingItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
void T1MInjectGameMoveBlock()
|
||||
{
|
||||
INJECT(0x0042B430, InitialiseMovableBlock);
|
||||
INJECT(0x0042B460, MovableBlockControl);
|
||||
INJECT(0x0042B5B0, MovableBlockCollision);
|
||||
INJECT(0x0042B7E0, TestBlockPush);
|
||||
INJECT(0x0042B940, TestBlockPull);
|
||||
INJECT(0x0042BB90, InitialiseRollingBlock);
|
||||
INJECT(0x0042BBC0, RollingBlockControl);
|
||||
INJECT(0x0042BCA0, AlterFloorHeight);
|
||||
INJECT(0x0042BD60, DrawMovableBlock);
|
||||
}
|
|
@ -1,27 +1,28 @@
|
|||
#ifndef T1M_GAME_MOVEBLOCK_H
|
||||
#define T1M_GAME_MOVEBLOCK_H
|
||||
#ifndef T1M_GAME_TRAPS_MOVABLE_BLOCK_H
|
||||
#define T1M_GAME_TRAPS_MOVABLE_BLOCK_H
|
||||
|
||||
#include "game/types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
// clang-format off
|
||||
// clang-format on
|
||||
typedef enum {
|
||||
MBS_STILL = 1,
|
||||
MBS_PUSH = 2,
|
||||
MBS_PULL = 3,
|
||||
} MOVABLE_BLOCK_STATE;
|
||||
|
||||
extern int16_t MovingBlockBounds[12];
|
||||
|
||||
void SetupMovableBlock(OBJECT_INFO *obj);
|
||||
void InitialiseMovableBlock(int16_t item_num);
|
||||
void MovableBlockControl(int16_t item_num);
|
||||
void MovableBlockCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
void DrawMovableBlock(ITEM_INFO *item);
|
||||
|
||||
int32_t TestBlockMovable(ITEM_INFO *item, int32_t blockhite);
|
||||
int32_t TestBlockPush(ITEM_INFO *item, int32_t blokhite, uint16_t quadrant);
|
||||
int32_t TestBlockPull(ITEM_INFO *item, int32_t blokhite, uint16_t quadrant);
|
||||
|
||||
void InitialiseRollingBlock(int16_t item_num);
|
||||
void RollingBlockControl(int16_t item_num);
|
||||
|
||||
void AlterFloorHeight(ITEM_INFO *item, int32_t height);
|
||||
|
||||
void DrawMovableBlock(ITEM_INFO *item);
|
||||
|
||||
void T1MInjectGameMoveBlock();
|
||||
|
||||
#endif
|
47
src/game/traps/pendulum.c
Normal file
47
src/game/traps/pendulum.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include "game/collide.h"
|
||||
#include "game/control.h"
|
||||
#include "game/effects.h"
|
||||
#include "game/game.h"
|
||||
#include "game/traps/pendulum.h"
|
||||
#include "game/vars.h"
|
||||
|
||||
void SetupPendulum(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->control = PendulumControl;
|
||||
obj->collision = TrapCollision;
|
||||
obj->shadow_size = UNIT_SHADOW / 2;
|
||||
obj->save_flags = 1;
|
||||
obj->save_anim = 1;
|
||||
}
|
||||
|
||||
// original name: Pendulum
|
||||
void PendulumControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
|
||||
if (TriggerActive(item)) {
|
||||
if (item->current_anim_state == TRAP_SET) {
|
||||
item->goal_anim_state = TRAP_WORKING;
|
||||
}
|
||||
} else {
|
||||
if (item->current_anim_state == TRAP_WORKING) {
|
||||
item->goal_anim_state = TRAP_SET;
|
||||
}
|
||||
}
|
||||
|
||||
if (item->current_anim_state == TRAP_WORKING && item->touch_bits) {
|
||||
LaraItem->hit_points -= PENDULUM_DAMAGE;
|
||||
LaraItem->hit_status = 1;
|
||||
int32_t x = LaraItem->pos.x + (GetRandomControl() - 0x4000) / 256;
|
||||
int32_t z = LaraItem->pos.z + (GetRandomControl() - 0x4000) / 256;
|
||||
int32_t y = LaraItem->pos.y - GetRandomControl() / 44;
|
||||
int32_t d = LaraItem->pos.y_rot + (GetRandomControl() - 0x4000) / 8;
|
||||
DoBloodSplat(x, y, z, LaraItem->speed, d, LaraItem->room_number);
|
||||
}
|
||||
|
||||
FLOOR_INFO *floor =
|
||||
GetFloor(item->pos.x, item->pos.y, item->pos.z, &item->room_number);
|
||||
item->floor = GetHeight(floor, item->pos.x, item->pos.y, item->pos.z);
|
||||
|
||||
AnimateItem(item);
|
||||
}
|
12
src/game/traps/pendulum.h
Normal file
12
src/game/traps/pendulum.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef T1M_GAME_TRAPS_PENDULUM_H
|
||||
#define T1M_GAME_TRAPS_PENDULUM_H
|
||||
|
||||
#include "game/types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define PENDULUM_DAMAGE 100
|
||||
|
||||
void SetupPendulum(OBJECT_INFO *obj);
|
||||
void PendulumControl(int16_t item_num);
|
||||
|
||||
#endif
|
170
src/game/traps/rolling_ball.c
Normal file
170
src/game/traps/rolling_ball.c
Normal file
|
@ -0,0 +1,170 @@
|
|||
#include "3dsystem/phd_math.h"
|
||||
#include "game/collide.h"
|
||||
#include "game/control.h"
|
||||
#include "game/effects.h"
|
||||
#include "game/game.h"
|
||||
#include "game/items.h"
|
||||
#include "game/sphere.h"
|
||||
#include "game/traps/rolling_ball.h"
|
||||
#include "game/vars.h"
|
||||
#include "specific/init.h"
|
||||
|
||||
void SetupRollingBall(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->initialise = InitialiseRollingBall;
|
||||
obj->control = RollingBallControl;
|
||||
obj->collision = RollingBallCollision;
|
||||
obj->save_position = 1;
|
||||
obj->save_anim = 1;
|
||||
obj->save_flags = 1;
|
||||
}
|
||||
|
||||
void InitialiseRollingBall(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
GAME_VECTOR *old = game_malloc(sizeof(GAME_VECTOR), GBUF_ROLLINGBALL_STUFF);
|
||||
item->data = old;
|
||||
old->x = item->pos.x;
|
||||
old->y = item->pos.y;
|
||||
old->z = item->pos.z;
|
||||
old->room_number = item->room_number;
|
||||
}
|
||||
|
||||
void RollingBallControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (item->status == IS_ACTIVE) {
|
||||
if (item->pos.y < item->floor) {
|
||||
if (!item->gravity_status) {
|
||||
item->gravity_status = 1;
|
||||
item->fall_speed = -10;
|
||||
}
|
||||
} else if (item->current_anim_state == TRAP_SET) {
|
||||
item->goal_anim_state = TRAP_ACTIVATE;
|
||||
}
|
||||
|
||||
int32_t oldx = item->pos.x;
|
||||
int32_t oldz = item->pos.z;
|
||||
AnimateItem(item);
|
||||
|
||||
int16_t room_num = item->room_number;
|
||||
FLOOR_INFO *floor =
|
||||
GetFloor(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
if (item->room_number != room_num) {
|
||||
ItemNewRoom(item_num, room_num);
|
||||
}
|
||||
|
||||
item->floor = GetHeight(floor, item->pos.x, item->pos.y, item->pos.z);
|
||||
|
||||
TestTriggers(TriggerIndex, 1);
|
||||
|
||||
if (item->pos.y >= item->floor - STEP_L) {
|
||||
item->gravity_status = 0;
|
||||
item->fall_speed = 0;
|
||||
item->pos.y = item->floor;
|
||||
}
|
||||
|
||||
int32_t x = item->pos.x
|
||||
+ (((WALL_L / 2) * phd_sin(item->pos.y_rot)) >> W2V_SHIFT);
|
||||
int32_t z = item->pos.z
|
||||
+ (((WALL_L / 2) * phd_cos(item->pos.y_rot)) >> W2V_SHIFT);
|
||||
floor = GetFloor(x, item->pos.y, z, &room_num);
|
||||
if (GetHeight(floor, x, item->pos.y, z) < item->pos.y) {
|
||||
item->status = IS_DEACTIVATED;
|
||||
item->pos.x = oldx;
|
||||
item->pos.y = item->floor;
|
||||
item->pos.z = oldz;
|
||||
item->speed = 0;
|
||||
item->fall_speed = 0;
|
||||
item->touch_bits = 0;
|
||||
}
|
||||
} else if (item->status == IS_DEACTIVATED && !TriggerActive(item)) {
|
||||
item->status = IS_NOT_ACTIVE;
|
||||
GAME_VECTOR *old = item->data;
|
||||
item->pos.x = old->x;
|
||||
item->pos.y = old->y;
|
||||
item->pos.z = old->z;
|
||||
if (item->room_number != old->room_number) {
|
||||
RemoveDrawnItem(item_num);
|
||||
ROOM_INFO *r = &RoomInfo[old->room_number];
|
||||
item->next_item = r->item_number;
|
||||
r->item_number = item_num;
|
||||
item->room_number = old->room_number;
|
||||
}
|
||||
item->current_anim_state = TRAP_SET;
|
||||
item->goal_anim_state = TRAP_SET;
|
||||
item->anim_number = Objects[item->object_number].anim_index;
|
||||
item->frame_number = Anims[item->anim_number].frame_base;
|
||||
item->current_anim_state = Anims[item->anim_number].current_anim_state;
|
||||
item->goal_anim_state = item->current_anim_state;
|
||||
item->required_anim_state = TRAP_SET;
|
||||
RemoveActiveItem(item_num);
|
||||
}
|
||||
}
|
||||
|
||||
void RollingBallCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
|
||||
if (item->status != IS_ACTIVE) {
|
||||
if (item->status != IS_INVISIBLE) {
|
||||
ObjectCollision(item_num, lara_item, coll);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TestBoundsCollide(item, lara_item, coll->radius)) {
|
||||
return;
|
||||
}
|
||||
if (!TestCollision(item, lara_item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t x, y, z, d;
|
||||
if (lara_item->gravity_status) {
|
||||
if (coll->enable_baddie_push) {
|
||||
ItemPushLara(item, lara_item, coll, coll->enable_spaz, 1);
|
||||
}
|
||||
lara_item->hit_points -= ROLLINGBALL_DAMAGE_AIR;
|
||||
x = lara_item->pos.x - item->pos.x;
|
||||
z = lara_item->pos.z - item->pos.z;
|
||||
y = (lara_item->pos.y - 350) - (item->pos.y - WALL_L / 2);
|
||||
d = phd_sqrt(SQUARE(x) + SQUARE(y) + SQUARE(z));
|
||||
if (d < WALL_L / 2) {
|
||||
d = WALL_L / 2;
|
||||
}
|
||||
x = item->pos.x + (x << WALL_SHIFT) / 2 / d;
|
||||
z = item->pos.z + (z << WALL_SHIFT) / 2 / d;
|
||||
y = item->pos.y - WALL_L / 2 + (y << WALL_SHIFT) / 2 / d;
|
||||
DoBloodSplat(x, y, z, item->speed, item->pos.y_rot, item->room_number);
|
||||
} else {
|
||||
lara_item->hit_status = 1;
|
||||
if (lara_item->hit_points > 0) {
|
||||
lara_item->hit_points = -1;
|
||||
if (lara_item->room_number != item->room_number) {
|
||||
ItemNewRoom(Lara.item_number, item->room_number);
|
||||
}
|
||||
|
||||
lara_item->pos.x_rot = 0;
|
||||
lara_item->pos.z_rot = 0;
|
||||
lara_item->pos.y_rot = item->pos.y_rot;
|
||||
|
||||
lara_item->current_anim_state = AS_SPECIAL;
|
||||
lara_item->goal_anim_state = AS_SPECIAL;
|
||||
lara_item->anim_number = AA_RBALL_DEATH;
|
||||
lara_item->frame_number = AF_RBALL_DEATH;
|
||||
|
||||
Camera.flags = FOLLOW_CENTRE;
|
||||
Camera.target_angle = 170 * PHD_DEGREE;
|
||||
Camera.target_elevation = -25 * PHD_DEGREE;
|
||||
for (int i = 0; i < 15; i++) {
|
||||
x = lara_item->pos.x + (GetRandomControl() - 0x4000) / 256;
|
||||
z = lara_item->pos.z + (GetRandomControl() - 0x4000) / 256;
|
||||
y = lara_item->pos.y - GetRandomControl() / 64;
|
||||
d = item->pos.y_rot + (GetRandomControl() - 0x4000) / 8;
|
||||
DoBloodSplat(x, y, z, item->speed * 2, d, item->room_number);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
14
src/game/traps/rolling_ball.h
Normal file
14
src/game/traps/rolling_ball.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef T1M_GAME_TRAPS_ROLLING_BALL_H
|
||||
#define T1M_GAME_TRAPS_ROLLING_BALL_H
|
||||
|
||||
#include "game/types.h"
|
||||
|
||||
#define ROLLINGBALL_DAMAGE_AIR 100
|
||||
|
||||
void SetupRollingBall(OBJECT_INFO *obj);
|
||||
void InitialiseRollingBall(int16_t item_num);
|
||||
void RollingBallControl(int16_t item_num);
|
||||
void RollingBallCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
|
||||
#endif
|
67
src/game/traps/rolling_block.c
Normal file
67
src/game/traps/rolling_block.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
#include "game/control.h"
|
||||
#include "game/items.h"
|
||||
#include "game/traps/movable_block.h"
|
||||
#include "game/traps/rolling_block.h"
|
||||
#include "game/vars.h"
|
||||
|
||||
int16_t MovingBlockBounds[12] = {
|
||||
-300,
|
||||
+300,
|
||||
0,
|
||||
0,
|
||||
-WALL_L / 2 - (LARA_RAD + 80),
|
||||
-WALL_L / 2,
|
||||
-10 * PHD_DEGREE,
|
||||
+10 * PHD_DEGREE,
|
||||
-30 * PHD_DEGREE,
|
||||
+30 * PHD_DEGREE,
|
||||
-10 * PHD_DEGREE,
|
||||
+10 * PHD_DEGREE,
|
||||
};
|
||||
|
||||
void SetupRollingBlock(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->initialise = InitialiseRollingBlock;
|
||||
obj->control = RollingBlockControl;
|
||||
obj->save_position = 1;
|
||||
obj->save_anim = 1;
|
||||
obj->save_flags = 1;
|
||||
}
|
||||
|
||||
void InitialiseRollingBlock(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
AlterFloorHeight(item, -2048);
|
||||
}
|
||||
|
||||
// original name: RollingBlock
|
||||
void RollingBlockControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (TriggerActive(item)) {
|
||||
if (item->current_anim_state == RBS_START) {
|
||||
item->goal_anim_state = RBS_END;
|
||||
AlterFloorHeight(item, 2048);
|
||||
}
|
||||
} else if (item->current_anim_state == RBS_END) {
|
||||
item->goal_anim_state = RBS_START;
|
||||
AlterFloorHeight(item, 2048);
|
||||
}
|
||||
|
||||
AnimateItem(item);
|
||||
|
||||
int16_t room_num = item->room_number;
|
||||
GetFloor(item->pos.x, item->pos.y, item->pos.z, &room_num);
|
||||
if (item->room_number != room_num) {
|
||||
ItemNewRoom(item_num, room_num);
|
||||
}
|
||||
|
||||
if (item->status == IS_DEACTIVATED) {
|
||||
item->status = IS_ACTIVE;
|
||||
AlterFloorHeight(item, -2048);
|
||||
item->pos.x &= -WALL_L;
|
||||
item->pos.x += WALL_L / 2;
|
||||
item->pos.z &= -WALL_L;
|
||||
item->pos.z += WALL_L / 2;
|
||||
}
|
||||
}
|
11
src/game/traps/rolling_block.h
Normal file
11
src/game/traps/rolling_block.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef T1M_GAME_TRAPS_ROLLING_BLOCK_H
|
||||
#define T1M_GAME_TRAPS_ROLLING_BLOCK_H
|
||||
|
||||
#include "game/types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void SetupRollingBlock(OBJECT_INFO *obj);
|
||||
void InitialiseRollingBlock(int16_t item_num);
|
||||
void RollingBlockControl(int16_t item_num);
|
||||
|
||||
#endif
|
54
src/game/traps/spikes.c
Normal file
54
src/game/traps/spikes.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include "game/collide.h"
|
||||
#include "game/effects.h"
|
||||
#include "game/game.h"
|
||||
#include "game/sphere.h"
|
||||
#include "game/traps/spikes.h"
|
||||
#include "game/vars.h"
|
||||
|
||||
void SetupSpikes(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->collision = SpikeCollision;
|
||||
}
|
||||
|
||||
void SpikeCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (lara_item->hit_points < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TestBoundsCollide(item, lara_item, coll->radius)) {
|
||||
return;
|
||||
}
|
||||
if (!TestCollision(item, lara_item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t num = GetRandomControl() / 24576;
|
||||
if (lara_item->gravity_status) {
|
||||
if (lara_item->fall_speed > 0) {
|
||||
lara_item->hit_points = -1;
|
||||
num = 20;
|
||||
}
|
||||
} else if (lara_item->speed < 30) {
|
||||
return;
|
||||
}
|
||||
|
||||
lara_item->hit_points -= SPIKE_DAMAGE;
|
||||
while (num > 0) {
|
||||
int32_t x = lara_item->pos.x + (GetRandomControl() - 0x4000) / 256;
|
||||
int32_t z = lara_item->pos.z + (GetRandomControl() - 0x4000) / 256;
|
||||
int32_t y = lara_item->pos.y - GetRandomControl() / 64;
|
||||
DoBloodSplat(x, y, z, 20, GetRandomControl(), item->room_number);
|
||||
num--;
|
||||
}
|
||||
|
||||
if (lara_item->hit_points <= 0) {
|
||||
lara_item->current_anim_state = AS_DEATH;
|
||||
lara_item->goal_anim_state = AS_DEATH;
|
||||
lara_item->anim_number = AA_SPIKE_DEATH;
|
||||
lara_item->frame_number = AF_SPIKE_DEATH;
|
||||
lara_item->pos.y = item->pos.y;
|
||||
lara_item->gravity_status = 0;
|
||||
}
|
||||
}
|
11
src/game/traps/spikes.h
Normal file
11
src/game/traps/spikes.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef T1M_GAME_TRAPS_SPIKES_H
|
||||
#define T1M_GAME_TRAPS_SPIKES_H
|
||||
|
||||
#include "game/types.h"
|
||||
|
||||
#define SPIKE_DAMAGE 15
|
||||
|
||||
void SetupSpikes(OBJECT_INFO *obj);
|
||||
void SpikeCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
|
||||
#endif
|
42
src/game/traps/teeth_trap.c
Normal file
42
src/game/traps/teeth_trap.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include "game/collide.h"
|
||||
#include "game/control.h"
|
||||
#include "game/sphere.h"
|
||||
#include "game/traps/teeth_trap.h"
|
||||
#include "game/vars.h"
|
||||
|
||||
BITE_INFO Teeth1A = { -23, 0, -1718, 0 };
|
||||
BITE_INFO Teeth1B = { 71, 0, -1718, 1 };
|
||||
BITE_INFO Teeth2A = { -23, 10, -1718, 0 };
|
||||
BITE_INFO Teeth2B = { 71, 10, -1718, 1 };
|
||||
BITE_INFO Teeth3A = { -23, -10, -1718, 0 };
|
||||
BITE_INFO Teeth3B = { 71, -10, -1718, 1 };
|
||||
|
||||
void SetupTeethTrap(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->control = TeethTrapControl;
|
||||
obj->collision = TrapCollision;
|
||||
obj->save_flags = 1;
|
||||
obj->save_anim = 1;
|
||||
}
|
||||
|
||||
// original name: TeethTrap
|
||||
void TeethTrapControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (TriggerActive(item)) {
|
||||
item->goal_anim_state = TT_NASTY;
|
||||
if (item->touch_bits && item->current_anim_state == TT_NASTY) {
|
||||
LaraItem->hit_points -= TEETH_TRAP_DAMAGE;
|
||||
LaraItem->hit_status = 1;
|
||||
BaddieBiteEffect(item, &Teeth1A);
|
||||
BaddieBiteEffect(item, &Teeth1B);
|
||||
BaddieBiteEffect(item, &Teeth2A);
|
||||
BaddieBiteEffect(item, &Teeth2B);
|
||||
BaddieBiteEffect(item, &Teeth3A);
|
||||
BaddieBiteEffect(item, &Teeth3B);
|
||||
}
|
||||
} else {
|
||||
item->goal_anim_state = TT_NICE;
|
||||
}
|
||||
AnimateItem(item);
|
||||
}
|
23
src/game/traps/teeth_trap.h
Normal file
23
src/game/traps/teeth_trap.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef T1M_GAME_TRAPS_TEETH_TRAP_H
|
||||
#define T1M_GAME_TRAPS_TEETH_TRAP_H
|
||||
|
||||
#include "game/types.h"
|
||||
|
||||
#define TEETH_TRAP_DAMAGE 400
|
||||
|
||||
typedef enum {
|
||||
TT_NICE = 0,
|
||||
TT_NASTY = 1,
|
||||
} TEETH_TRAP_STATE;
|
||||
|
||||
extern BITE_INFO Teeth1A;
|
||||
extern BITE_INFO Teeth1B;
|
||||
extern BITE_INFO Teeth2A;
|
||||
extern BITE_INFO Teeth2B;
|
||||
extern BITE_INFO Teeth3A;
|
||||
extern BITE_INFO Teeth3B;
|
||||
|
||||
void SetupTeethTrap(OBJECT_INFO *obj);
|
||||
void TeethTrapControl(int16_t item_num);
|
||||
|
||||
#endif
|
169
src/game/traps/thors_hammer.c
Normal file
169
src/game/traps/thors_hammer.c
Normal file
|
@ -0,0 +1,169 @@
|
|||
#include "game/collide.h"
|
||||
#include "game/control.h"
|
||||
#include "game/draw.h"
|
||||
#include "game/items.h"
|
||||
#include "game/traps/movable_block.h"
|
||||
#include "game/traps/thors_hammer.h"
|
||||
#include "game/vars.h"
|
||||
|
||||
void SetupThorsHandle(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->initialise = InitialiseThorsHandle;
|
||||
obj->control = ThorsHandleControl;
|
||||
obj->draw_routine = DrawUnclippedItem;
|
||||
obj->collision = ThorsHandleCollision;
|
||||
obj->save_flags = 1;
|
||||
obj->save_anim = 1;
|
||||
}
|
||||
|
||||
void SetupThorsHead(OBJECT_INFO *obj)
|
||||
{
|
||||
obj->collision = ThorsHeadCollision;
|
||||
obj->draw_routine = DrawUnclippedItem;
|
||||
obj->save_flags = 1;
|
||||
obj->save_anim = 1;
|
||||
}
|
||||
|
||||
void InitialiseThorsHandle(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *hand_item = &Items[item_num];
|
||||
int16_t head_item_num = CreateItem();
|
||||
ITEM_INFO *head_item = &Items[head_item_num];
|
||||
head_item->object_number = O_THORS_HEAD;
|
||||
head_item->room_number = hand_item->room_number;
|
||||
head_item->pos = hand_item->pos;
|
||||
head_item->shade = hand_item->shade;
|
||||
InitialiseItem(head_item_num);
|
||||
hand_item->data = head_item;
|
||||
LevelItemCount++;
|
||||
}
|
||||
|
||||
void ThorsHandleControl(int16_t item_num)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
|
||||
switch (item->current_anim_state) {
|
||||
case THS_SET:
|
||||
if (TriggerActive(item)) {
|
||||
item->goal_anim_state = THS_TEASE;
|
||||
} else {
|
||||
RemoveActiveItem(item_num);
|
||||
item->status = IS_NOT_ACTIVE;
|
||||
}
|
||||
break;
|
||||
|
||||
case THS_TEASE:
|
||||
if (TriggerActive(item)) {
|
||||
item->goal_anim_state = THS_ACTIVE;
|
||||
} else {
|
||||
item->goal_anim_state = THS_SET;
|
||||
}
|
||||
break;
|
||||
|
||||
case THS_ACTIVE: {
|
||||
int32_t frm = item->frame_number - Anims[item->anim_number].frame_base;
|
||||
if (frm > 30) {
|
||||
int32_t x = item->pos.x;
|
||||
int32_t z = item->pos.z;
|
||||
|
||||
switch (item->pos.y_rot) {
|
||||
case 0:
|
||||
z += WALL_L * 3;
|
||||
break;
|
||||
case PHD_90:
|
||||
x += WALL_L * 3;
|
||||
break;
|
||||
case -PHD_90:
|
||||
x -= WALL_L * 3;
|
||||
break;
|
||||
case -PHD_180:
|
||||
z -= WALL_L * 3;
|
||||
break;
|
||||
}
|
||||
|
||||
if (LaraItem->hit_points >= 0 && LaraItem->pos.x > x - 520
|
||||
&& LaraItem->pos.x < x + 520 && LaraItem->pos.z > z - 520
|
||||
&& LaraItem->pos.z < z + 520) {
|
||||
LaraItem->hit_points = -1;
|
||||
LaraItem->pos.y = item->pos.y;
|
||||
LaraItem->gravity_status = 0;
|
||||
LaraItem->current_anim_state = AS_SPECIAL;
|
||||
LaraItem->goal_anim_state = AS_SPECIAL;
|
||||
LaraItem->anim_number = AA_RBALL_DEATH;
|
||||
LaraItem->frame_number = AF_RBALL_DEATH;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case THS_DONE: {
|
||||
int32_t x = item->pos.x;
|
||||
int32_t z = item->pos.z;
|
||||
int32_t old_x = x;
|
||||
int32_t old_z = z;
|
||||
|
||||
int16_t room_num = item->room_number;
|
||||
FLOOR_INFO *floor = GetFloor(x, item->pos.y, z, &room_num);
|
||||
GetHeight(floor, x, item->pos.y, z);
|
||||
TestTriggers(TriggerIndex, 1);
|
||||
|
||||
switch (item->pos.y_rot) {
|
||||
case 0:
|
||||
z += WALL_L * 3;
|
||||
break;
|
||||
case PHD_90:
|
||||
x += WALL_L * 3;
|
||||
break;
|
||||
case -PHD_90:
|
||||
x -= WALL_L * 3;
|
||||
break;
|
||||
case -PHD_180:
|
||||
z -= WALL_L * 3;
|
||||
break;
|
||||
}
|
||||
|
||||
item->pos.x = x;
|
||||
item->pos.z = z;
|
||||
if (LaraItem->hit_points >= 0) {
|
||||
AlterFloorHeight(item, -2 * WALL_L);
|
||||
}
|
||||
item->pos.x = old_x;
|
||||
item->pos.z = old_z;
|
||||
|
||||
RemoveActiveItem(item_num);
|
||||
item->status = IS_DEACTIVATED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
AnimateItem(item);
|
||||
|
||||
ITEM_INFO *head_item = item->data;
|
||||
int32_t anim = item->anim_number - Objects[O_THORS_HANDLE].anim_index;
|
||||
int32_t frm = item->frame_number - Anims[item->anim_number].frame_base;
|
||||
head_item->anim_number = Objects[O_THORS_HEAD].anim_index + anim;
|
||||
head_item->frame_number = Anims[head_item->anim_number].frame_base + frm;
|
||||
head_item->current_anim_state = item->current_anim_state;
|
||||
}
|
||||
|
||||
void ThorsHandleCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (!TestBoundsCollide(item, lara_item, coll->radius)) {
|
||||
return;
|
||||
}
|
||||
if (coll->enable_baddie_push) {
|
||||
ItemPushLara(item, lara_item, coll, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ThorsHeadCollision(int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll)
|
||||
{
|
||||
ITEM_INFO *item = &Items[item_num];
|
||||
if (!TestBoundsCollide(item, lara_item, coll->radius)) {
|
||||
return;
|
||||
}
|
||||
if (coll->enable_baddie_push && item->current_anim_state != THS_ACTIVE) {
|
||||
ItemPushLara(item, lara_item, coll, 0, 1);
|
||||
}
|
||||
}
|
22
src/game/traps/thors_hammer.h
Normal file
22
src/game/traps/thors_hammer.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef T1M_GAME_TRAPS_THORS_HAMMER_H
|
||||
#define T1M_GAME_TRAPS_THORS_HAMMER_H
|
||||
|
||||
#include "game/types.h"
|
||||
|
||||
typedef enum {
|
||||
THS_SET = 0,
|
||||
THS_TEASE = 1,
|
||||
THS_ACTIVE = 2,
|
||||
THS_DONE = 3,
|
||||
} THOR_HAMMER_STATE;
|
||||
|
||||
void SetupThorsHandle(OBJECT_INFO *obj);
|
||||
void SetupThorsHead(OBJECT_INFO *obj);
|
||||
void InitialiseThorsHandle(int16_t item_num);
|
||||
void ThorsHandleControl(int16_t item_num);
|
||||
void ThorsHandleCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
void ThorsHeadCollision(
|
||||
int16_t item_num, ITEM_INFO *lara_item, COLL_INFO *coll);
|
||||
|
||||
#endif
|
|
@ -15,9 +15,7 @@
|
|||
#include "game/inv.h"
|
||||
#include "game/items.h"
|
||||
#include "game/lara.h"
|
||||
#include "game/lightning.h"
|
||||
#include "game/lot.h"
|
||||
#include "game/moveblock.h"
|
||||
#include "game/objects.h"
|
||||
#include "game/option.h"
|
||||
#include "game/pickup.h"
|
||||
|
@ -25,7 +23,6 @@
|
|||
#include "game/setup.h"
|
||||
#include "game/sphere.h"
|
||||
#include "game/text.h"
|
||||
#include "game/traps.h"
|
||||
#include "specific/display.h"
|
||||
#include "specific/file.h"
|
||||
#include "specific/frontend.h"
|
||||
|
@ -60,8 +57,6 @@ void T1MInject()
|
|||
T1MInjectGameLaraMisc();
|
||||
T1MInjectGameLaraSurf();
|
||||
T1MInjectGameLaraSwim();
|
||||
T1MInjectGameLightning();
|
||||
T1MInjectGameMoveBlock();
|
||||
T1MInjectGameObjects();
|
||||
T1MInjectGameOption();
|
||||
T1MInjectGamePickup();
|
||||
|
@ -69,7 +64,6 @@ void T1MInject()
|
|||
T1MInjectGameSetup();
|
||||
T1MInjectGameSphere();
|
||||
T1MInjectGameText();
|
||||
T1MInjectGameTraps();
|
||||
T1MInjectSpecificDisplay();
|
||||
T1MInjectSpecificFile();
|
||||
T1MInjectSpecificFrontend();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue