diff --git a/TR2_progress.txt b/TR2_progress.txt index 7b8410a..5f05083 100644 --- a/TR2_progress.txt +++ b/TR2_progress.txt @@ -121,7 +121,7 @@ x function is unused / included in another function 0x0040C8F0: * EagleControl game/boat.cpp -0x0040CB10: InitialiseBoat +0x0040CB10: * InitialiseBoat 0x0040CB50: BoatCheckGeton 0x0040CCC0: BoatCollision 0x0040CE20: TestWaterHeight @@ -131,12 +131,12 @@ x function is unused / included in another function 0x0040D2C0: BoatDynamics 0x0040D7A0: BoatUserControl 0x0040D930: BoatAnimation -0x0040DAA0: BoatControl +0x0040DAA0: * BoatControl 0x0040E0D0: + GondolaControl game/box.cpp 0x0040E190: * InitialiseCreature -0x0040E1C0: CreatureActive +0x0040E1C0: * CreatureActive 0x0040E210: * CreatureAIInfo 0x0040E470: SearchLOT 0x0040E670: UpdateLOT @@ -159,7 +159,7 @@ x function is unused / included in another function 0x00410090: * CreatureEffect 0x004100F0: CreatureVault 0x00410230: + CreatureKill -0x004103A0: GetBaddieTarget +0x004103A0: + GetBaddieTarget game/camera.cpp 0x00410580: + InitialiseCamera @@ -189,48 +189,48 @@ x function is unused / included in another function 0x00412680: * InGameCinematicCamera game/collide.cpp -0x004128D0: GetCollisionInfo -0x00412F90: FindGridShift +0x004128D0: * GetCollisionInfo +0x00412F90: + FindGridShift 0x00412FC0: + CollideStaticObjects 0x004133B0: + GetNearByRooms 0x00413480: + GetNewRoom -0x004134E0: ShiftItem -0x00413520: * UpdateLaraRoom -0x00413580: GetTiltType -0x00413620: LaraBaddieCollision -0x004137C0: EffectSpaz -0x00413840: * CreatureCollision -0x004138C0: * ObjectCollision -0x00413920: DoorCollision -0x004139A0: TrapCollision -0x00413A10: ItemPushLara -0x00413D20: TestBoundsCollide -0x00413DF0: TestLaraPosition -0x00413F30: AlignLaraPosition -0x00414070: MoveLaraPosition -0x00414200: Move3DPosTo3DPos +0x004134E0: + ShiftItem +0x00413520: + UpdateLaraRoom +0x00413580: + GetTiltType +0x00413620: + LaraBaddieCollision +0x004137C0: + EffectSpaz +0x00413840: + CreatureCollision +0x004138C0: + ObjectCollision +0x00413920: + DoorCollision +0x004139A0: + TrapCollision +0x00413A10: + ItemPushLara +0x00413D20: + TestBoundsCollide +0x00413DF0: + TestLaraPosition +0x00413F30: + AlignLaraPosition +0x00414070: + MoveLaraPosition +0x00414200: + Move3DPosTo3DPos game/control.cpp 0x00414370: + ControlPhase 0x004146C0: * AnimateItem -0x00414A30: GetChange -0x00414AE0: TranslateItem +0x00414A30: * GetChange +0x00414AE0: * TranslateItem 0x00414B40: * GetFloor 0x00414CE0: * GetWaterHeight 0x00414E50: * GetHeight -0x004150D0: RefreshCamera +0x004150D0: * RefreshCamera 0x004151C0: * TestTriggers 0x004158A0: * TriggerActive 0x00415900: * GetCeiling -0x00415B60: GetDoor +0x00415B60: * GetDoor 0x00415BB0: * LOS -0x00415C50: zLOS -0x00415F40: xLOS -0x00416230: ClipTarget -0x00416310: ObjectOnLOS +0x00415C50: * zLOS +0x00415F40: * xLOS +0x00416230: * ClipTarget +0x00416310: * ObjectOnLOS 0x00416610: * FlipMap -0x004166D0: RemoveRoomFlipItems -0x00416770: AddRoomFlipItems +0x004166D0: * RemoveRoomFlipItems +0x00416770: * AddRoomFlipItems 0x004167D0: + TriggerCDTrack 0x00416800: + TriggerNormalCDTrack @@ -250,7 +250,7 @@ x function is unused / included in another function 0x004174E0: * TigerControl game/dragon.cpp -0x00417780: ControlTwinkle +0x00417780: * ControlTwinkle 0x00417900: CreateBartoliLight 0x004179E0: DragonFire 0x00417A90: * DragonCollision @@ -261,8 +261,8 @@ x function is unused / included in another function 0x00418670: * DinoControl game/draw.cpp -0x00418920: * DrawPhaseCinematic -0x00418960: * DrawPhaseGame +0x00418920: + DrawPhaseCinematic +0x00418960: + DrawPhaseGame 0x004189A0: + DrawRooms 0x00418C50: + GetRoomBounds 0x00418E20: + SetRoomBounds @@ -273,27 +273,27 @@ x function is unused / included in another function 0x004199C0: + DrawSpriteItem ----------: + DrawDummyItem 0x00419A50: + DrawAnimatingItem -0x00419DD0: * DrawLara +0x00419DD0: + DrawLara 0x0041AB00: + DrawLaraInt -0x0041B6F0: * InitInterpolate -0x0041B730: * phd_PopMatrix_I -0x0041B760: * phd_PushMatrix_I -0x0041B790: * phd_RotY_I -0x0041B7D0: * phd_RotX_I -0x0041B810: * phd_RotZ_I -0x0041B850: * phd_TranslateRel_I -0x0041B8A0: * phd_TranslateRel_ID -0x0041B8F0: * phd_RotYXZ_I -0x0041B940: * phd_RotYXZsuperpack_I +0x0041B6F0: + InitInterpolate +0x0041B730: + phd_PopMatrix_I +0x0041B760: + phd_PushMatrix_I +0x0041B790: + phd_RotY_I +0x0041B7D0: + phd_RotX_I +0x0041B810: + phd_RotZ_I +0x0041B850: + phd_TranslateRel_I +0x0041B8A0: + phd_TranslateRel_ID +0x0041B8F0: + phd_RotYXZ_I +0x0041B940: + phd_RotYXZsuperpack_I 0x0041B980: + phd_RotYXZsuperpack 0x0041BA30: + phd_PutPolygons_I -0x0041BA60: * InterpolateMatrix -0x0041BC10: * InterpolateArmMatrix +0x0041BA60: + InterpolateMatrix +0x0041BC10: + InterpolateArmMatrix 0x0041BD10: + DrawGunFlash 0x0041BE80: * CalculateObjectLighting -0x0041BF70: * GetFrames -0x0041C010: * GetBoundsAccurate -0x0041C090: * GetBestFrame +0x0041BF70: + GetFrames +0x0041C010: + GetBoundsAccurate +0x0041C090: + GetBestFrame 0x0041C0D0: + AddDynamicLight game/eel.cpp @@ -668,7 +668,7 @@ x function is unused / included in another function 0x0042ECB0: * CheckForHoldingState 0x0042ECF0: * InitialiseNewWeapon 0x0042EE30: * LaraTargetInfo -0x0042EFD0: * LaraGetNewTarget +0x0042EFD0: + LaraGetNewTarget 0x0042F1F0: * find_target_point 0x0042F2A0: * AimWeapon 0x0042F370: * FireWeapon @@ -691,14 +691,14 @@ x function is unused / included in another function game/laramisc.cpp 0x00430380: + LaraControl -0x00430A10: * AnimateLara +0x00430A10: + AnimateLara 0x00430D10: + UseItem 0x00430ED0: + LaraCheatGetStuff 0x00430F90: + ControlLaraExtra 0x00430FB0: + InitialiseLaraLoad -0x00430FE0: * InitialiseLara +0x00430FE0: + InitialiseLara 0x004312A0: + InitialiseLaraInventory -0x00431610: * LaraInitialiseMeshes +0x00431610: + LaraInitialiseMeshes game/larasurf.cpp 0x00431710: * LaraSurface @@ -737,75 +737,75 @@ x function is unused / included in another function 0x00432920: LaraWaterCurrent game/lot.cpp -0x00432B10: InitialiseLOTarray -0x00432B70: * DisableBaddieAI -0x00432BC0: * EnableBaddieAI -0x00432D70: InitialiseSlot -0x00432F80: CreateZone -0x00433040: ClearLOT +0x00432B10: + InitialiseLOTarray +0x00432B70: + DisableBaddieAI +0x00432BC0: + EnableBaddieAI +0x00432D70: + InitialiseSlot +0x00432F80: * CreateZone +0x00433040: * ClearLOT game/missile.cpp 0x00433090: + ControlMissile 0x00433360: ShootAtLara 0x00433410: * ExplodingDeath -0x004337A0: ControlBodyPart +0x004337A0: * ControlBodyPart game/moveblock.cpp -0x004339A0: InitialiseMovingBlock +0x004339A0: * InitialiseMovingBlock 0x004339D0: * MovableBlock -0x00433B20: MovableBlockCollision +0x00433B20: * MovableBlockCollision 0x00433D80: TestBlockMovable 0x00433DD0: TestBlockPush 0x00433F20: TestBlockPull 0x00434160: * AlterFloorHeight -0x00434220: DrawMovableBlock +0x00434220: * DrawMovableBlock 0x00434250: * DrawUnclippedItem game/objects.cpp -0x004342C0: EarthQuake -0x004343A0: ControlCutShotgun -0x004343E0: InitialiseFinalLevel -0x004344B0: FinalLevelCounter -0x004346C0: MiniCopterControl -0x004347A0: InitialiseDyingMonk -0x00434820: DyingMonk -0x004348B0: ControlGongBonger -0x00434970: DeathSlideCollision -0x00434A30: ControlDeathSlide -0x00434CC0: BigBowlControl -0x00434DB0: BellControl -0x00434E30: InitialiseWindow +0x004342C0: * EarthQuake +0x004343A0: * ControlCutShotgun +0x004343E0: * InitialiseFinalLevel +0x004344B0: * FinalLevelCounter +0x004346C0: * MiniCopterControl +0x004347A0: * InitialiseDyingMonk +0x00434820: * DyingMonk +0x004348B0: * ControlGongBonger +0x00434970: * DeathSlideCollision +0x00434A30: * ControlDeathSlide +0x00434CC0: * BigBowlControl +0x00434DB0: * BellControl +0x00434E30: * InitialiseWindow 0x00434EB0: * SmashWindow -0x00434F80: WindowControl -0x00435020: SmashIceControl -0x00435100: ShutThatDoor -0x00435150: OpenThatDoor -0x00435190: InitialiseDoor -0x00435570: DoorControl -0x00435640: OnDrawBridge -0x00435700: DrawBridgeFloor -0x00435740: DrawBridgeCeiling -0x00435780: DrawBridgeCollision -0x004357B0: InitialiseLift -0x004357F0: LiftControl -0x004358D0: LiftFloorCeiling -0x00435A50: LiftFloor -0x00435A90: LiftCeiling -0x00435AD0: BridgeFlatFloor -0x00435AF0: BridgeFlatCeiling -0x00435B10: GetOffset -0x00435B50: BridgeTilt1Floor -0x00435B80: BridgeTilt1Ceiling -0x00435BC0: BridgeTilt2Floor -0x00435BF0: BridgeTilt2Ceiling -0x00435C30: CopterControl -0x00435D40: GeneralControl -0x00435E20: DetonatorControl +0x00434F80: * WindowControl +0x00435020: * SmashIceControl +0x00435100: + ShutThatDoor +0x00435150: + OpenThatDoor +0x00435190: * InitialiseDoor +0x00435570: + DoorControl +0x00435640: * OnDrawBridge +0x00435700: * DrawBridgeFloor +0x00435740: * DrawBridgeCeiling +0x00435780: * DrawBridgeCollision +0x004357B0: * InitialiseLift +0x004357F0: * LiftControl +0x004358D0: * LiftFloorCeiling +0x00435A50: * LiftFloor +0x00435A90: * LiftCeiling +0x00435AD0: * BridgeFlatFloor +0x00435AF0: * BridgeFlatCeiling +0x00435B10: * GetOffset +0x00435B50: * BridgeTilt1Floor +0x00435B80: * BridgeTilt1Ceiling +0x00435BC0: * BridgeTilt2Floor +0x00435BF0: * BridgeTilt2Ceiling +0x00435C30: * CopterControl +0x00435D40: + GeneralControl +0x00435E20: * DetonatorControl game/people.cpp 0x00435EB0: Targetable -0x00435F40: ControlGlow -0x00435F80: ControlGunShot +0x00435F40: * ControlGlow +0x00435F80: * ControlGunShot 0x00435FD0: + GunShot 0x00436040: + GunHit 0x00436100: GunMiss @@ -822,16 +822,16 @@ x function is unused / included in another function game/pickup.cpp 0x00437F20: * PickUpCollision -0x004383A0: SwitchCollision -0x004385B0: SwitchCollision2 -0x004386B0: DetonatorCollision -0x004388F0: KeyHoleCollision +0x004383A0: * SwitchCollision +0x004385B0: * SwitchCollision2 +0x004386B0: * DetonatorCollision +0x004388F0: * KeyHoleCollision 0x00438B30: * PuzzleHoleCollision -0x00438DF0: SwitchControl +0x00438DF0: * SwitchControl 0x00438E30: SwitchTrigger 0x00438EF0: KeyTrigger 0x00438F30: PickupTrigger -0x00438F70: SecretControl +0x00438F70: * SecretControl game/rat.cpp 0x00438FA0: * MouseControl @@ -847,14 +847,14 @@ x function is unused / included in another function 0x0043A2F0: + ReadSG game/setup.cpp -0x0043A330: * InitialiseLevel -0x0043A490: InitialiseGameFlags +0x0043A330: + InitialiseLevel +0x0043A490: * InitialiseGameFlags 0x0043A500: + InitialiseLevelFlags 0x0043A530: + BaddyObjects -0x0043B570: * TrapObjects +0x0043B570: + TrapObjects 0x0043BB70: * ObjectObjects 0x0043C7C0: + InitialiseObjects -0x0043C830: GetCarriedItems +0x0043C830: * GetCarriedItems game/shark.cpp 0x0043C900: * JellyControl @@ -864,7 +864,7 @@ x function is unused / included in another function game/skidoo.cpp 0x0043CEE0: * InitialiseSkidoo 0x0043CF20: SkidooCheckGeton -0x0043D010: SkidooCollision +0x0043D010: * SkidooCollision 0x0043D110: SkidooBaddieCollision 0x0043D310: TestHeight 0x0043D3D0: DoShift @@ -878,7 +878,7 @@ x function is unused / included in another function 0x0043E2D0: + SkidooExplode 0x0043E350: SkidooCheckGetOff 0x0043E590: + SkidooGuns -0x0043E6B0: SkidooControl +0x0043E6B0: * SkidooControl 0x0043EB10: + DrawSkidoo 0x0043EDF0: * InitialiseSkidman 0x0043EE80: * SkidManControl @@ -894,10 +894,10 @@ x function is unused / included in another function 0x0043FA30: + SOUND_Init game/sphere.cpp -0x0043FA60: TestCollision -0x0043FB90: GetSpheres -0x0043FE70: * GetJointAbsPosition -0x00440010: * BaddieBiteEffect +0x0043FA60: * TestCollision +0x0043FB90: * GetSpheres +0x0043FE70: + GetJointAbsPosition +0x00440010: + BaddieBiteEffect game/spider.cpp 0x00440070: SpiderLeap @@ -932,26 +932,26 @@ x function is unused / included in another function 0x004411C0: + ControlSpikeWall 0x00441300: + ControlCeilingSpikes 0x00441420: + HookControl -0x004414B0: PropellerControl +0x004414B0: * PropellerControl 0x00441640: + SpinningBlade 0x004417C0: + IcicleControl 0x004418C0: + InitialiseBlade 0x00441900: + BladeControl 0x004419A0: + InitialiseKillerStatue 0x004419F0: + KillerStatueControl -0x00441B00: SpringBoardControl -0x00441BE0: InitialiseRollingBall -0x00441C20: RollingBallControl -0x00441F70: RollingBallCollision -0x004421C0: SpikeCollision -0x00442320: TrapDoorControl -0x00442370: TrapDoorFloor -0x004423B0: TrapDoorCeiling -0x004423F0: OnTrapDoor +0x00441B00: * SpringBoardControl +0x00441BE0: * InitialiseRollingBall +0x00441C20: * RollingBallControl +0x00441F70: * RollingBallCollision +0x004421C0: * SpikeCollision +0x00442320: * TrapDoorControl +0x00442370: * TrapDoorFloor +0x004423B0: * TrapDoorCeiling +0x004423F0: * OnTrapDoor 0x004424A0: + Pendulum -0x004425B0: FallingBlock -0x004426C0: FallingBlockFloor -0x00442700: FallingBlockCeiling +0x004425B0: * FallingBlock +0x004426C0: * FallingBlockFloor +0x00442700: * FallingBlockCeiling 0x00442750: + TeethTrap 0x00442810: + FallingCeiling 0x004428F0: + DartEmitterControl @@ -961,8 +961,8 @@ x function is unused / included in another function 0x00442C70: + FlameControl 0x00442DE0: + LaraBurn 0x00442E30: + LavaBurn -0x00442F20: LavaSpray -0x00442FF0: ControlLavaBlob +0x00442F20: * LavaSpray +0x00442FF0: * ControlLavaBlob game/yeti.cpp 0x00443100: * GiantYetiControl @@ -1406,7 +1406,7 @@ x function is unused / included in another function 0x00456680: + UpdateTicks 0x004566C0: + TIME_Init 0x00456720: + Sync -0x00456780: + LoadResource +0x00456780: + UT_LoadResource // NOTE: Previous name was LoadResource but utils.h have UT_ in front. 0x004567C0: + UT_InitAccurateTimer 0x00456820: + UT_Microseconds 0x00456870: + UT_CenterWindow diff --git a/configs/TR2Main.json b/configs/TR2Main.json index 3b15fd9..43e5fa0 100644 --- a/configs/TR2Main.json +++ b/configs/TR2Main.json @@ -31,6 +31,10 @@ " boots. It is used for alternative sound effects of Lara's steps. ", " The parameter can be true or false. Default value is false. ", " ", + " - 'bridgelightfix' is used to fix the drawbridge that create a ", + " dynamic light when triggered. (minisub is not affected) ", + " Default is true. ", + " ", " - 'semitransparent' is used for semitransparency parameters. ", " It can contain: 'animtex', 'objects', 'statics', 'rooms' ", " ", @@ -91,6 +95,7 @@ "default": { "comment": "Default settings for all levels", "watercolor": "80FFFF", + "bridgelightfix": true, "semitransparent": { "animtex": "auto", "objects": [{ diff --git a/game/boat.h b/game/boat.h index 59b7a6c..34eadff 100644 --- a/game/boat.h +++ b/game/boat.h @@ -27,9 +27,9 @@ /* * Function list */ -// 0x0040CB10: InitialiseBoat +#define InitialiseBoat ((void(__cdecl*)(__int16)) 0x0040CB10) // 0x0040CB50: BoatCheckGeton -// 0x0040CCC0: BoatCollision +#define BoatCollision ((void(__cdecl*)(__int16,ITEM_INFO*,COLL_INFO*)) 0x0040CCC0) // 0x0040CE20: TestWaterHeight // 0x0040CF20: DoBoatShift @@ -39,7 +39,7 @@ void __cdecl DoWakeEffect(ITEM_INFO *item); // 0x0040D0F0 // 0x0040D2C0: BoatDynamics // 0x0040D7A0: BoatUserControl // 0x0040D930: BoatAnimation -// 0x0040DAA0: BoatControl +#define BoatControl ((void(__cdecl*)(__int16)) 0x0040DAA0) void __cdecl GondolaControl(__int16 itemID); // 0x0040E0D0 diff --git a/game/box.cpp b/game/box.cpp index 69d3580..548fc10 100644 --- a/game/box.cpp +++ b/game/box.cpp @@ -21,12 +21,100 @@ #include "global/precompiled.h" #include "game/box.h" +#include "3dsystem/phd_math.h" #include "game/control.h" #include "game/items.h" #include "game/lot.h" #include "game/missile.h" +#include "specific/game.h" #include "global/vars.h" +/*void __cdecl InitialiseCreature(__int16 itemID) { + ITEM_INFO *item = &Items[itemID]; + item->pos.rotY += (GetRandomControl() - PHD_90) >> 1; + item->collidable = 1; + item->data = NULL; +} + +BOOL __cdecl CreatureActive(__int16 itemID) { + ITEM_INFO *item = &Items[itemID]; + + if (CHK_ANY(item->status, ITEM_INVISIBLE)) { + BOOL isActive = EnableBaddieAI(itemID, FALSE); + if (isActive) { + item->status = ITEM_ACTIVE; + return TRUE; + } + } + + return CHK_ANY(item->status, ITEM_ACTIVE); +} + +void __cdecl CreatureAIInfo(ITEM_INFO *item, AI_INFO *ai) { + CREATURE_INFO *creature = (CREATURE_INFO*)item->data; + if (creature == NULL) { + return; + } + + ITEM_INFO *enemy = NULL; + __int16 *zone = NULL; + + switch (item->objectID) { + case ID_BANDIT1: + case ID_BANDIT2: + GetBaddieTarget(creature->item_num, 0); + break; + case ID_MONK1: + case ID_MONK2: + GetBaddieTarget(creature->item_num, 1); + break; + default: + creature->enemy = LaraItem; + break; + } + + enemy = creature->enemy; + if (enemy == NULL) { + enemy = LaraItem; + } + + if (creature->LOT.fly != 0) { + zone = FlyZones[FlipStatus]; + } else { + zone = GroundZones[2 * (creature->LOT.step >> 8) + FlipStatus]; + } + + ROOM_INFO *roomSource = &RoomInfo[item->roomNumber]; + item->boxNumber = roomSource->floor[((item->pos.z - roomSource->z) >> WALL_SHIFT) + roomSource->xSize * ((item->pos.x - roomSource->x) >> WALL_SHIFT)].box; + ai->zone_number = zone[item->boxNumber]; + + ROOM_INFO *roomTarget = &RoomInfo[enemy->roomNumber]; + enemy->boxNumber = roomTarget->floor[((enemy->pos.z - roomTarget->z) >> WALL_SHIFT) + roomTarget->xSize * ((enemy->pos.x - roomTarget->x) >> WALL_SHIFT)].box; + ai->enemy_zone = zone[enemy->boxNumber]; + + if ( CHK_ANY(Boxes[enemy->boxNumber].overlapIndex, creature->LOT.block_mask) || creature->LOT.node[item->boxNumber].search_number == (creature->LOT.search_number | 0x8000) ) { + ai->enemy_zone |= 0x4000; + } + + OBJECT_INFO *obj = &Objects[item->objectID]; + int x = enemy->pos.x - ((obj->pivotLength * phd_cos(item->pos.rotY)) >> W2V_SHIFT) - item->pos.x; + int z = enemy->pos.z - ((obj->pivotLength * phd_sin(item->pos.rotY)) >> W2V_SHIFT) - item->pos.z; + int angle = phd_atan(z, x); + if (creature->enemy != NULL) { + ai->distance = SQR(x) + SQR(z); + } else { + ai->distance = 0x7FFFFFFF; + } + ai->angle = angle - item->pos.rotY; + ai->enemy_facing = angle - enemy->pos.rotY + PHD_180; + ai->ahead = angle > -PHD_90 && angle < PHD_90; + if (ai->ahead && enemy->hitPoints >= 0 && ABS(item->pos.y - enemy->pos.y) < 384) { + ai->bite = 1; + } else { + ai->bite = 0; + } +}*/ + void __cdecl CreatureDie(__int16 itemID, BOOL explode) { ITEM_INFO *item = &Items[itemID]; item->collidable = 0; @@ -94,6 +182,73 @@ void __cdecl CreatureKill(ITEM_INFO *item, int killAnim, int killState, int lara Camera.pos.roomNumber = LaraItem->roomNumber; } +void __cdecl GetBaddieTarget(__int16 itemNum, int flags) { + ITEM_INFO *item = &Items[itemNum], *target = NULL, *bestItem = NULL; + CREATURE_INFO *creature = (CREATURE_INFO*)item->data, *creatureFound = NULL; + int bestDistance = 0x7FFFFFFF, distance = 0; + int x, y, z; + + for (int i = 0; i < MAXIMUM_CREATURE_SLOTS; i++) { + creatureFound = &ActiveCreatures[i]; + if (creatureFound->item_num == -1 || creatureFound->item_num == itemNum) + continue; + target = &Items[creatureFound->item_num]; + switch (flags) { + case 1: // MONK + if (target->objectID != ID_BANDIT1 && target->objectID != ID_BANDIT2) + continue; + break; + case 0: // BANDIT (Mercenary) + if (target->objectID != ID_MONK1 && target->objectID != ID_MONK2) + continue; + break; + default: + continue; + } + x = (target->pos.x - item->pos.x) >> 6; + y = (target->pos.y - item->pos.y) >> 6; + z = (target->pos.z - item->pos.z) >> 6; + distance = SQR(z) + SQR(y) + SQR(x); + if (distance < bestDistance) { + bestItem = target; + bestDistance = distance; + } + } + + if (bestItem == NULL) { + if (flags == 0 || MonksAttackLara) { + creature->enemy = LaraItem; + } else { + creature->enemy = NULL; + } + return; + } + + if (flags == 0 || MonksAttackLara) { + x = (LaraItem->pos.x - item->pos.x) >> 6; + y = (LaraItem->pos.y - item->pos.y) >> 6; + z = (LaraItem->pos.z - item->pos.z) >> 6; + distance = SQR(z) + SQR(y) + SQR(x); + if (distance < bestDistance) { + bestItem = LaraItem; + bestDistance = distance; + } + } + + target = creature->enemy; + if (target != NULL && target->status == ITEM_ACTIVE) { + x = (target->pos.x - item->pos.x) >> 6; + y = (target->pos.y - item->pos.y) >> 6; + z = (target->pos.z - item->pos.z) >> 6; + distance = SQR(z) + SQR(y) + SQR(x); + if (distance < (bestDistance + 0x400000)) { + creature->enemy = bestItem; + } + } else { + creature->enemy = bestItem; + } +} + /* * Inject function */ @@ -125,6 +280,5 @@ void Inject_Box() { // INJECT(0x004100F0, CreatureVault); INJECT(0x00410230, CreatureKill); - -// INJECT(0x004103A0, GetBaddieTarget); + INJECT(0x004103A0, GetBaddieTarget); } diff --git a/game/box.h b/game/box.h index 5baf9fa..6128c4a 100644 --- a/game/box.h +++ b/game/box.h @@ -27,11 +27,10 @@ /* * Function list */ -#define InitialiseCreature ((void(__cdecl*)(__int16)) 0x0040E190) - -// 0x0040E1C0: CreatureActive -#define CreatureAIInfo ((void(__cdecl*)(ITEM_INFO *, AI_INFO *)) 0x0040E210) +#define InitialiseCreature ((void(__cdecl*)(__int16)) 0x0040E190) +#define CreatureActive ((BOOL(__cdecl*)(__int16)) 0x0040E1C0) +#define CreatureAIInfo ((void(__cdecl*)(ITEM_INFO*,AI_INFO*)) 0x0040E210) // 0x0040E470: SearchLOT // 0x0040E670: UpdateLOT @@ -40,7 +39,7 @@ // 0x0040E880: EscapeBox // 0x0040E930: ValidBox -#define CreatureMood ((void(__cdecl*)(ITEM_INFO *, AI_INFO *, BOOL)) 0x0040E9E0) +#define CreatureMood ((void(__cdecl*)(ITEM_INFO*, AI_INFO*, BOOL)) 0x0040E9E0) // 0x0040EE50: CalculateTarget // 0x0040F2B0: CreatureCreature @@ -62,7 +61,7 @@ void __cdecl CreatureDie(__int16 itemID, BOOL explode); // 0x0040F440 // 0x004100F0: CreatureVault void __cdecl CreatureKill(ITEM_INFO *item, int killAnim, int killState, int laraKillState); // 0x00410230 - -// 0x004103A0: GetBaddieTarget +// NOTE: 1 = Monk, 0 = Bandit +void __cdecl GetBaddieTarget(__int16 itemNum, int flags); // 0x004103A0 #endif // BOX_H_INCLUDED diff --git a/game/cinema.cpp b/game/cinema.cpp index 69e46c0..d171f5f 100644 --- a/game/cinema.cpp +++ b/game/cinema.cpp @@ -51,6 +51,16 @@ int __cdecl StartCinematic(int levelID) { return 2; } + // NOTE: fix lara hair waving in air, + // Caused by the cheat fly mode being not reset when cutscene is played ! + if (Lara.water_status == LWS_Cheat) { + Lara.water_status = LWS_AboveWater; + LaraItem->currentAnimState = AS_STOP; + LaraItem->goalAnimState = AS_STOP; + LaraItem->animNumber = 11; + LaraItem->frameNumber = Anims[LaraItem->animNumber].frameBase; + } + InitCinematicRooms(); InitialisePlayer1(Lara.item_number); Camera.targetAngle = CineTargetAngle; diff --git a/game/collide.cpp b/game/collide.cpp index 3599420..53b7a5e 100644 --- a/game/collide.cpp +++ b/game/collide.cpp @@ -21,9 +21,29 @@ #include "global/precompiled.h" #include "game/collide.h" +#include "3dsystem/3d_gen.h" +#include "3dsystem/phd_math.h" +#include "game/draw.h" +#include "game/items.h" #include "game/control.h" +#include "game/sound.h" +#include "game/sphere.h" #include "global/vars.h" +int __cdecl FindGridShift(int src, int dest) { + int srcShift = src >> WALL_SHIFT; + int destShift = dest >> WALL_SHIFT; + if (srcShift == destShift) { + return 0; + } + src &= 1023; + if (destShift <= srcShift) { + return -1 - src; + } else { + return 1025 - src; + } +} + int __cdecl CollideStaticObjects(COLL_INFO *coll, int x, int y, int z, __int16 roomID, int hite) { int rxMin = x - coll->radius; int rxMax = x + coll->radius; @@ -191,30 +211,471 @@ void __cdecl GetNewRoom(int x, int y, int z, __int16 roomID) { DrawRoomsArray[DrawRoomsCount++] = roomID; } +void __cdecl ShiftItem(ITEM_INFO *item, COLL_INFO *coll) { + item->pos.x += coll->shift.x; + item->pos.y += coll->shift.y; + item->pos.z += coll->shift.z; + coll->shift.z = 0; + coll->shift.y = 0; + coll->shift.x = 0; +} + +void __cdecl UpdateLaraRoom(ITEM_INFO *item, int height) { + FLOOR_INFO *floor; + int x, y, z; + __int16 roomID; + + x = item->pos.x; + y = item->pos.y + height; + z = item->pos.z; + roomID = item->roomNumber; + floor = GetFloor(x, y, z, &roomID); + item->floor = GetHeight(floor, x, y, z); + if (item->roomNumber != roomID) { + ItemNewRoom(Lara.item_number, roomID); + } +} + +__int16 __cdecl GetTiltType(FLOOR_INFO *floor, int x, int y, int z) { + __int16 *data; + BYTE i; + + for (i = floor->pitRoom; i != 255; i = floor->pitRoom) { + floor = &RoomInfo[i].floor[((z - RoomInfo[i].z) >> WALL_SHIFT) + RoomInfo[i].xSize * ((x - RoomInfo[i].x) >> WALL_SHIFT)]; + } + if (floor->index == 0) { + return 0; + } + data = &FloorData[floor->index]; + if (y + 512 >= floor->floor << 8 && *(BYTE*)data == 2) { + return data[1]; + } else { + return 0; + } +} + +void __cdecl LaraBaddieCollision(ITEM_INFO *laraitem, COLL_INFO *coll) { +#define ROOM_ARRAY_COUNT 20 + DOOR_INFOS *doors; + ITEM_INFO *item; + OBJECT_INFO *obj; + int x, y, z; + __int16 roomArray[ROOM_ARRAY_COUNT]; + __int16 roomCount; + __int16 itemID; + __int16 i; + + laraitem->hit_status = 0; + Lara.hit_direction = -1; + if (laraitem->hitPoints <= 0) { + return; + } + + roomArray[0] = laraitem->roomNumber; + roomCount = 1; + doors = RoomInfo[laraitem->roomNumber].doors; + if (doors) { + for (i = 0; i < doors->wCount; i++) { + if (i > (ROOM_ARRAY_COUNT - 1)) { // check if i > roomArray size, to avoid overflow ! + break; + } + roomArray[roomCount++] = doors->door[i].room; + } + } + + if (roomCount > 0) { + for (i = 0; i < roomCount; i++) { + itemID = RoomInfo[roomArray[i]].itemNumber; + while (itemID != -1) + { + item = &Items[itemID]; + if (item->collidable && item->status != ITEM_INVISIBLE) { + obj = &Objects[item->objectID]; + if (obj->collision) { + x = laraitem->pos.x - item->pos.x; + y = laraitem->pos.y - item->pos.y; + z = laraitem->pos.z - item->pos.z; + if (x > -4096 && x < 4096 + && y > -4096 && y < 4096 + && z > -4096 && z < 4096) { + obj->collision(itemID, laraitem, coll); + } + } + } + itemID = item->nextItem; + } + } + } + + if (Lara.spaz_effect_count != 0) + EffectSpaz(laraitem, coll); // NOTE: coll is not used ! + if (Lara.hit_direction == -1) + Lara.hit_frame = 0; + InventoryChosen = -1; +} + +void __cdecl EffectSpaz(ITEM_INFO *laraitem, COLL_INFO *coll) { + Lara.hit_direction = (UINT16)(laraitem->pos.rotY + PHD_180 - phd_atan(Lara.spaz_effect->pos.z - laraitem->pos.z, Lara.spaz_effect->pos.x - laraitem->pos.x) + PHD_90) >> W2V_SHIFT; + if (!Lara.hit_frame) { + PlaySoundEffect(31, &laraitem->pos, 0); + } + if (++Lara.hit_frame > 34) { + Lara.hit_frame = 34; + } + --Lara.spaz_effect_count; +} + +void __cdecl CreatureCollision(__int16 itemID, ITEM_INFO *laraitem, COLL_INFO *coll) { + ITEM_INFO *item = &Items[itemID]; + if (TestBoundsCollide(item, laraitem, coll->radius)) { + if (TestCollision(item, laraitem)) { + if (coll->enableBaddiePush && Lara.water_status != LWS_Underwater) { // NOTE: original checked "(Lara.water_status == 0) != 2" but it's always true ! + ItemPushLara(item, laraitem, coll, coll->enableSpaz, FALSE); + } + } + } +} + +void __cdecl ObjectCollision(__int16 itemID, ITEM_INFO *laraitem, COLL_INFO *coll) { + ITEM_INFO *item = &Items[itemID]; + if (TestBoundsCollide(item, laraitem, coll->radius)) { + if (TestCollision(item, laraitem)) { + if (coll->enableBaddiePush) { + ItemPushLara(item, laraitem, coll, FALSE, TRUE); + } + } + } +} + +void __cdecl DoorCollision(__int16 itemID, ITEM_INFO *laraitem, COLL_INFO *coll) { + ITEM_INFO *item = &Items[itemID]; + if (TestBoundsCollide(item, laraitem, coll->radius)) { + if (TestCollision(item, laraitem)) { + if (coll->enableBaddiePush) { + if (item->currentAnimState == item->goalAnimState) { + ItemPushLara(item, laraitem, coll, FALSE, TRUE); + } else { + ItemPushLara(item, laraitem, coll, coll->enableSpaz, TRUE); + } + } + } + } +} + +void __cdecl TrapCollision(__int16 itemID, ITEM_INFO *laraitem, COLL_INFO *coll) { + ITEM_INFO *item = &Items[itemID]; + if (item->status == ITEM_ACTIVE) { + if (TestBoundsCollide(item, laraitem, coll->radius)) { + TestCollision(item, laraitem); + } + } else if (item->status != ITEM_INVISIBLE) { + ObjectCollision(itemID, laraitem, coll); + } +} + +void __cdecl ItemPushLara(ITEM_INFO *item, ITEM_INFO *laraitem, COLL_INFO *coll, BOOL spazon, BOOL bigpush) { + int x, z, rx, rz; + int l, r, t, b; + int bndMin, bndMax; + int radius; + __int16 *bounds; + __int16 c, s; + __int16 minx, maxx, minz, maxz; + __int16 oldFacing; + + x = laraitem->pos.x - item->pos.x; + z = laraitem->pos.z - item->pos.z; + s = phd_sin(item->pos.rotY); + c = phd_cos(item->pos.rotY); + rx = (x * c - z * s) >> W2V_SHIFT; + rz = (x * s + z * c) >> W2V_SHIFT; + bounds = GetBestFrame(item); + minx = bounds[0]; + maxx = bounds[1]; + minz = bounds[4]; + maxz = bounds[5]; + + if (bigpush) { + radius = coll->radius; + maxx += radius; + minz -= radius; + maxz += radius; + minx -= radius; + } + + if (rx >= minx && rx <= maxx && rz >= minz && rz <= maxz) { + l = rx - minx; + r = maxx - rx; + t = maxz - rz; + b = rz - minz; + + if (r <= l && r <= t && r <= b) { + rx += r; + } else if (l <= r && l <= t && l <= b) { + rx -= l; + } else if (t <= r && t <= l && t <= b) { + rz += t; + } else { + rz -= b; + } + + laraitem->pos.x = item->pos.x + ((rz * s + rx * c) >> W2V_SHIFT); + laraitem->pos.z = item->pos.z + ((rz * c - rx * s) >> W2V_SHIFT); + + bndMin = (bounds[1] + bounds[0]) / 2; + bndMax = (bounds[5] + bounds[4]) / 2; + rx -= (bndMax * s + bndMin * c) >> W2V_SHIFT; + rz -= (bndMax * c - bndMin * s) >> W2V_SHIFT; + + if (spazon && bounds[3] - bounds[2] > 256) { + Lara.hit_direction = (UINT16)(laraitem->pos.rotY + PHD_180 - phd_atan(rz, rx) + PHD_90) >> W2V_SHIFT; + if (!Lara.hit_frame) { + PlaySoundEffect(31, &laraitem->pos, 0); + } + if (++Lara.hit_frame > 34) { + Lara.hit_frame = 34; + } + } + + x = coll->old.x; + z = coll->old.z; + oldFacing = coll->facing; + coll->badPos = -NO_HEIGHT; + coll->badNeg = -384; + coll->badCeiling = 0; + coll->facing = phd_atan(laraitem->pos.z - z, laraitem->pos.x - x); + GetCollisionInfo(coll, laraitem->pos.x, laraitem->pos.y, laraitem->pos.z, laraitem->roomNumber, 762); + coll->facing = oldFacing; + if (coll->collType == 0) { + coll->old.x = laraitem->pos.x; + coll->old.y = laraitem->pos.y; + coll->old.z = laraitem->pos.z; + UpdateLaraRoom(laraitem, -10); + } else { + laraitem->pos.x = coll->old.x; + laraitem->pos.z = coll->old.z; + } + } +} + +BOOL __cdecl TestBoundsCollide(ITEM_INFO *item, ITEM_INFO *laraitem, int radius) { + __int16 *boundItem; + __int16 *boundLara; + int x, z, s, c; + int rx, rz; + + boundItem = GetBestFrame(item); + boundLara = GetBestFrame(laraitem); + + if (item->pos.y + boundItem[3] > item->pos.y + boundLara[2] && item->pos.y + boundItem[2] < item->pos.y + boundLara[3]) { + c = phd_cos(item->pos.rotY); + s = phd_sin(item->pos.rotY); + x = laraitem->pos.x - item->pos.x; + z = laraitem->pos.z - item->pos.z; + rx = (c * x - s * z) >> W2V_SHIFT; + rz = (s * x + c * z) >> W2V_SHIFT; + if (rx >= boundItem[0] - radius && + rx <= radius + boundItem[1] && + rz >= boundItem[4] - radius && + rz <= radius + boundItem[5]) { + return TRUE; + } + } + + return FALSE; +} + +BOOL __cdecl TestLaraPosition(__int16 *bounds, ITEM_INFO *item, ITEM_INFO *laraitem) { + int x, y, z; + int xBound, yBound, zBound; + __int16 yRot, xRot, zRot; + + xRot = laraitem->pos.rotX - item->pos.rotX; + yRot = laraitem->pos.rotY - item->pos.rotY; + zRot = laraitem->pos.rotZ - item->pos.rotZ; + + if (xRot < bounds[6]) { + return FALSE; + } + if (xRot > bounds[7]) { + return FALSE; + } + if (yRot < bounds[8]) { + return FALSE; + } + if (yRot > bounds[9]) { + return FALSE; + } + if (zRot < bounds[10]) { + return FALSE; + } + if (zRot > bounds[11]) { + return FALSE; + } + + x = laraitem->pos.x - item->pos.x; + y = laraitem->pos.y - item->pos.y; + z = laraitem->pos.z - item->pos.z; + + phd_PushUnitMatrix(); + phd_RotYXZ(item->pos.rotY, item->pos.rotX, item->pos.rotZ); + xBound = (x * PhdMatrixPtr->_00 + y * PhdMatrixPtr->_10 + z * PhdMatrixPtr->_20) >> W2V_SHIFT; + yBound = (x * PhdMatrixPtr->_01 + y * PhdMatrixPtr->_11 + z * PhdMatrixPtr->_21) >> W2V_SHIFT; + zBound = (x * PhdMatrixPtr->_02 + y * PhdMatrixPtr->_12 + z * PhdMatrixPtr->_22) >> W2V_SHIFT; + phd_PopMatrix(); + + return xBound >= bounds[0] + && xBound <= bounds[1] + && yBound >= bounds[2] + && yBound <= bounds[3] + && zBound >= bounds[4] + && zBound <= bounds[5]; +} + +void __cdecl AlignLaraPosition(PHD_VECTOR *pos, ITEM_INFO *item, ITEM_INFO *laraitem) { + FLOOR_INFO *floor; + int x, y, z; + int height, ceiling; + __int16 roomID; + + laraitem->pos.rotX = item->pos.rotX; + laraitem->pos.rotY = item->pos.rotY; + laraitem->pos.rotZ = item->pos.rotZ; + + phd_PushUnitMatrix(); + phd_RotYXZ(item->pos.rotY, item->pos.rotX, item->pos.rotZ); + x = item->pos.x + ((pos->x * PhdMatrixPtr->_00 + pos->y * PhdMatrixPtr->_01 + pos->z * PhdMatrixPtr->_02) >> W2V_SHIFT); + y = item->pos.y + ((pos->x * PhdMatrixPtr->_10 + pos->y * PhdMatrixPtr->_11 + pos->z * PhdMatrixPtr->_12) >> W2V_SHIFT); + z = item->pos.z + ((pos->x * PhdMatrixPtr->_20 + pos->y * PhdMatrixPtr->_21 + pos->z * PhdMatrixPtr->_22) >> W2V_SHIFT); + phd_PopMatrix(); + + roomID = laraitem->roomNumber; + floor = GetFloor(x, y, z, &roomID); + height = GetHeight(floor, x, y, z); + ceiling = GetCeiling(floor, x, y, z); + + if (ABS(height - laraitem->pos.y) <= 256 && ABS(ceiling - laraitem->pos.y) >= 762) { + laraitem->pos.x = x; + laraitem->pos.y = y; + laraitem->pos.z = z; + } +} + +BOOL __cdecl MoveLaraPosition(PHD_VECTOR *pos, ITEM_INFO *item, ITEM_INFO *laraitem) { + PHD_3DPOS newpos; + FLOOR_INFO *floor; + int height, distance; + int xDist, yDist, zDist; + __int16 roomID; + + newpos.rotX = item->pos.rotX; + newpos.rotY = item->pos.rotY; + newpos.rotZ = item->pos.rotZ; + + phd_PushUnitMatrix(); + phd_RotYXZ(item->pos.rotY, item->pos.rotX, item->pos.rotZ); + newpos.x = item->pos.x + ((pos->x * PhdMatrixPtr->_00 + pos->y * PhdMatrixPtr->_01 + pos->z * PhdMatrixPtr->_02) >> W2V_SHIFT); + newpos.y = item->pos.y + ((pos->x * PhdMatrixPtr->_10 + pos->y * PhdMatrixPtr->_11 + pos->z * PhdMatrixPtr->_12) >> W2V_SHIFT); + newpos.z = item->pos.z + ((pos->x * PhdMatrixPtr->_20 + pos->y * PhdMatrixPtr->_21 + pos->z * PhdMatrixPtr->_22) >> W2V_SHIFT); + phd_PopMatrix(); + + if (item->objectID != ID_FLARE_ITEM) { + return Move3DPosTo3DPos(&laraitem->pos, &newpos, 16, 364); + } + + roomID = laraitem->roomNumber; + floor = GetFloor(newpos.x, newpos.y, newpos.z, &roomID); + height = GetHeight(floor, newpos.x, newpos.y, newpos.z); + + if (ABS(height - laraitem->pos.y) > 512) { + return FALSE; + } + + zDist = SQR(newpos.z - laraitem->pos.z); + yDist = SQR(newpos.y - laraitem->pos.y); + xDist = SQR(newpos.x - laraitem->pos.x); + distance = phd_sqrt(zDist + yDist + xDist); + return distance < 128 || Move3DPosTo3DPos(&laraitem->pos, &newpos, 16, 364); +} + +BOOL __cdecl Move3DPosTo3DPos(PHD_3DPOS *src, PHD_3DPOS *dest, int velocity, __int16 angleAdder) { + int x, y, z, distance; + __int16 xRot, yRot, zRot; + + x = dest->x - src->x; + y = dest->y - src->y; + z = dest->z - src->z; + distance = phd_sqrt(SQR(z) + SQR(y) + SQR(x)); + if (velocity < distance) { + src->x += velocity * x / distance; + src->y += velocity * y / distance; + src->z += velocity * z / distance; + } else { + src->x = dest->x; + src->y = dest->y; + src->z = dest->z; + } + + xRot = dest->rotX - src->rotX; + yRot = dest->rotY - src->rotY; + zRot = dest->rotZ - src->rotZ; + if (xRot <= angleAdder) { + if (xRot >= -angleAdder) { + src->rotX = dest->rotX; + } else { + src->rotX -= angleAdder; + } + } else { + src->rotX += angleAdder; + } + if (yRot <= angleAdder) { + if (yRot >= -angleAdder) { + src->rotY = dest->rotY; + } else { + src->rotY -= angleAdder; + } + } else { + src->rotY += angleAdder; + } + if (zRot <= angleAdder) { + if (zRot >= -angleAdder) { + src->rotZ = dest->rotZ; + } else { + src->rotZ -= angleAdder; + } + } else { + src->rotZ += angleAdder; + } + return src->x == dest->x + && src->y == dest->y + && src->z == dest->z + && src->rotX == dest->rotX + && src->rotY == dest->rotY + && src->rotZ == dest->rotZ; +} + /* * Inject function */ void Inject_Collide() { // INJECT(0x004128D0, GetCollisionInfo); -// INJECT(0x00412F90, FindGridShift); - + INJECT(0x00412F90, FindGridShift); INJECT(0x00412FC0, CollideStaticObjects); INJECT(0x004133B0, GetNearByRooms); INJECT(0x00413480, GetNewRoom); - -// INJECT(0x004134E0, ShiftItem); -// INJECT(0x00413520, UpdateLaraRoom); -// INJECT(0x00413580, GetTiltType); -// INJECT(0x00413620, LaraBaddieCollision); -// INJECT(0x004137C0, EffectSpaz); -// INJECT(0x00413840, CreatureCollision); -// INJECT(0x004138C0, ObjectCollision); -// INJECT(0x00413920, DoorCollision); -// INJECT(0x004139A0, TrapCollision); -// INJECT(0x00413A10, ItemPushLara); -// INJECT(0x00413D20, TestBoundsCollide); -// INJECT(0x00413DF0, TestLaraPosition); -// INJECT(0x00413F30, AlignLaraPosition); -// INJECT(0x00414070, MoveLaraPosition); -// INJECT(0x00414200, Move3DPosTo3DPos); + INJECT(0x004134E0, ShiftItem); + INJECT(0x00413520, UpdateLaraRoom); + INJECT(0x00413580, GetTiltType); + INJECT(0x00413620, LaraBaddieCollision); + INJECT(0x004137C0, EffectSpaz); + INJECT(0x00413840, CreatureCollision); + INJECT(0x004138C0, ObjectCollision); + INJECT(0x00413920, DoorCollision); + INJECT(0x004139A0, TrapCollision); + INJECT(0x00413A10, ItemPushLara); + INJECT(0x00413D20, TestBoundsCollide); + INJECT(0x00413DF0, TestLaraPosition); + INJECT(0x00413F30, AlignLaraPosition); + INJECT(0x00414070, MoveLaraPosition); + INJECT(0x00414200, Move3DPosTo3DPos); } diff --git a/game/collide.h b/game/collide.h index 9d53b79..0bfd553 100644 --- a/game/collide.h +++ b/game/collide.h @@ -27,31 +27,25 @@ /* * Function list */ -// 0x004128D0: GetCollisionInfo -// 0x00412F90: FindGridShift - +#define GetCollisionInfo ((void(__cdecl*)(COLL_INFO*, int, int, int, __int16, int)) 0x004128D0) +int __cdecl FindGridShift(int src, int dest); // 0x00412F90 int __cdecl CollideStaticObjects(COLL_INFO *coll, int x, int y, int z, __int16 roomID, int hite); // 0x00412FC0 void __cdecl GetNearByRooms(int x, int y, int z, int r, int h, __int16 roomID); // 0x004133B0 void __cdecl GetNewRoom(int x, int y, int z, __int16 roomID); // 0x00413480 - -// 0x004134E0: ShiftItem - -#define UpdateLaraRoom ((void(__cdecl*)(ITEM_INFO*, int)) 0x00413520) - -// 0x00413580: GetTiltType -// 0x00413620: LaraBaddieCollision -// 0x004137C0: EffectSpaz - -#define CreatureCollision ((void(__cdecl*)(__int16, ITEM_INFO *, COLL_INFO *)) 0x00413840) -#define ObjectCollision ((void(__cdecl*)(__int16, ITEM_INFO *, COLL_INFO *)) 0x004138C0) - -// 0x00413920: DoorCollision -// 0x004139A0: TrapCollision -// 0x00413A10: ItemPushLara -// 0x00413D20: TestBoundsCollide -// 0x00413DF0: TestLaraPosition -// 0x00413F30: AlignLaraPosition -// 0x00414070: MoveLaraPosition -// 0x00414200: Move3DPosTo3DPos +void __cdecl ShiftItem(ITEM_INFO *item, COLL_INFO *coll); // 0x004134E0 +void __cdecl UpdateLaraRoom(ITEM_INFO *item, int height); // 0x00413520 +__int16 __cdecl GetTiltType(FLOOR_INFO *floor, int x, int y, int z); // 0x00413580 +void __cdecl LaraBaddieCollision(ITEM_INFO *laraitem, COLL_INFO *coll); // 0x00413620 +void __cdecl EffectSpaz(ITEM_INFO *laraitem, COLL_INFO *coll); // 0x004137C0 +void __cdecl CreatureCollision(__int16 itemID, ITEM_INFO *laraitem, COLL_INFO *coll); // 0x00413840 +void __cdecl ObjectCollision(__int16 itemID, ITEM_INFO *laraitem, COLL_INFO *coll); // 0x004138C0 +void __cdecl DoorCollision(__int16 itemID, ITEM_INFO *laraitem, COLL_INFO *coll); // 0x00413920 +void __cdecl TrapCollision(__int16 itemID, ITEM_INFO *laraitem, COLL_INFO *coll); // 0x004139A0 +void __cdecl ItemPushLara(ITEM_INFO *item, ITEM_INFO *laraitem, COLL_INFO *coll, BOOL spazon, BOOL bigpush); // 0x00413A10 +BOOL __cdecl TestBoundsCollide(ITEM_INFO *item, ITEM_INFO *laraitem, int radius); // 0x00413D20 +BOOL __cdecl TestLaraPosition(__int16 *bounds, ITEM_INFO *item, ITEM_INFO *laraitem); // 0x00413DF0 +void __cdecl AlignLaraPosition(PHD_VECTOR *pos, ITEM_INFO *item, ITEM_INFO *laraitem); // 0x00413F30 +BOOL __cdecl MoveLaraPosition(PHD_VECTOR *pos, ITEM_INFO *item, ITEM_INFO *laraitem); // 0x00414070 +BOOL __cdecl Move3DPosTo3DPos(PHD_3DPOS *src, PHD_3DPOS *dest, int velocity, __int16 angleAdder); // 0x00414200 #endif // COLLIDE_H_INCLUDED diff --git a/game/control.h b/game/control.h index 8d91dd6..5f93622 100644 --- a/game/control.h +++ b/game/control.h @@ -28,36 +28,25 @@ * Function list */ int __cdecl ControlPhase(int nTicks, BOOL demoMode); - #define AnimateItem ((void(__cdecl*)(ITEM_INFO*)) 0x004146C0) - -// 0x00414A30: GetChange -// 0x00414AE0: TranslateItem - +#define GetChange ((int(__cdecl*)(ITEM_INFO*,ANIM_STRUCT*)) 0x00414A30) +#define TranslateItem ((void(__cdecl*)(ITEM_INFO*,int,int,int)) 0x00414AE0) #define GetFloor ((FLOOR_INFO*(__cdecl*)(int, int, int, __int16*)) 0x00414B40) #define GetWaterHeight ((int(__cdecl*)(int, int, int, __int16)) 0x00414CE0) #define GetHeight ((int(__cdecl*)(FLOOR_INFO*, int, int, int)) 0x00414E50) - -// 0x004150D0: RefreshCamera - +#define RefreshCamera ((void(__cdecl*)(int,__int16*)) 0x004150D0) #define TestTriggers ((void(__cdecl*)(__int16*, BOOL)) 0x004151C0) #define TriggerActive ((int(__cdecl*)(ITEM_INFO*)) 0x004158A0) #define GetCeiling ((int(__cdecl*)(FLOOR_INFO*, int, int, int)) 0x00415900) - -// 0x00415B60: GetDoor - +#define GetDoor ((__int16(__cdecl*)(FLOOR_INFO*)) 0x00415B60) #define LOS ((int(__cdecl*)(GAME_VECTOR*, GAME_VECTOR*)) 0x00415BB0) - -// 0x00415C50: zLOS -// 0x00415F40: xLOS -// 0x00416230: ClipTarget -// 0x00416310: ObjectOnLOS - +#define zLOS ((int(__cdecl*)(GAME_VECTOR*, GAME_VECTOR*)) 0x00415C50) +#define xLOS ((int(__cdecl*)(GAME_VECTOR*, GAME_VECTOR*)) 0x00415F40) +#define ClipTarget ((int(__cdecl*)(GAME_VECTOR*, GAME_VECTOR*, FLOOR_INFO*)) 0x00416230) +#define ObjectOnLOS ((int(__cdecl*)(GAME_VECTOR*, GAME_VECTOR*)) 0x00416310) #define FlipMap ((void(__cdecl*)(void)) 0x00416610) - -// 0x004166D0: RemoveRoomFlipItems -// 0x00416770: AddRoomFlipItems - +#define RemoveRoomFlipItems ((void(__cdecl*)(ROOM_INFO*)) 0x004166D0) +#define AddRoomFlipItems ((void(__cdecl*)(ROOM_INFO*)) 0x00416770) void __cdecl TriggerCDTrack(__int16 value, UINT16 flags, __int16 type); // 0x004167D0 void __cdecl TriggerNormalCDTrack(__int16 value, UINT16 flags, __int16 type); // 0x00416800; diff --git a/game/dragon.h b/game/dragon.h index 1dcabe4..6f8e7f9 100644 --- a/game/dragon.h +++ b/game/dragon.h @@ -27,10 +27,9 @@ /* * Function list */ -// 0x00417780: ControlTwinkle +#define ControlTwinkle ((void(__cdecl*)(__int16)) 0x00417780) // 0x00417900: CreateBartoliLight // 0x004179E0: DragonFire - #define DragonCollision ((void(__cdecl*)(__int16, ITEM_INFO *, COLL_INFO *)) 0x00417A90) #define DragonBones ((void(__cdecl*)(__int16)) 0x00417D80) #define DragonControl ((void(__cdecl*)(__int16)) 0x00417E60) diff --git a/game/draw.cpp b/game/draw.cpp index 3c5e307..1f5f135 100644 --- a/game/draw.cpp +++ b/game/draw.cpp @@ -24,6 +24,7 @@ #include "3dsystem/3d_gen.h" #include "3dsystem/scalespr.h" #include "game/hair.h" +#include "game/health.h" #include "specific/game.h" #include "specific/output.h" #include "global/vars.h" @@ -44,6 +45,24 @@ void ResetGoldenLaraAlpha() { } #endif // FEATURE_VIDEOFX_IMPROVED +int __cdecl DrawPhaseCinematic() { + UnderwaterCamera = FALSE; + DrawRooms(Camera.pos.roomNumber); + S_OutputPolyList(); + Camera.numberFrames = S_DumpScreen(); + S_AnimateTextures(Camera.numberFrames); + return Camera.numberFrames; +} + +int __cdecl DrawPhaseGame() { + DrawRooms(Camera.pos.roomNumber); + DrawGameInfo(TRUE); + S_OutputPolyList(); + Camera.numberFrames = S_DumpScreen(); + S_AnimateTextures(Camera.numberFrames); + return Camera.numberFrames; +} + void __cdecl DrawRooms(__int16 currentRoom) { ROOM_INFO *room = &RoomInfo[currentRoom]; @@ -655,6 +674,308 @@ void __cdecl DrawAnimatingItem(ITEM_INFO *item) { phd_PopMatrix(); } +void __cdecl DrawLara(ITEM_INFO *laraitem) { + PHD_MATRIX hairMatrix, weaponMatrix; + OBJECT_INFO *obj; + int gunType; + int frac, rate, clip; + int currentState; + int oldBottom, oldTop, oldLeft, oldRight; + int interpolation; + int *bones; + UINT16 *rot1, *rot2, *rot1copy; + __int16 *framesPtr[2]; + __int16 *animFramePtr; + __int16 *frame; + + oldBottom = PhdWinBottom; + oldTop = PhdWinTop; + oldLeft = PhdWinLeft; + oldRight = PhdWinRight; + PhdWinBottom = PhdWinMaxY; + PhdWinTop = 0; + PhdWinLeft = 0; + PhdWinRight = PhdWinMaxX; + + if (Lara.hit_direction < 0) { + frac = GetFrames(laraitem, framesPtr, &rate); + if (frac) { + DrawLaraInt(laraitem, framesPtr[0], framesPtr[1], frac, rate); + PhdWinBottom = oldBottom; + PhdWinTop = oldTop; + PhdWinLeft = oldLeft; + PhdWinRight = oldRight; + return; + } + } + + if (Lara.hit_direction < 0) { + frame = framesPtr[0]; + } else { + switch (Lara.hit_direction) { + case 1: + animFramePtr = Anims[127].framePtr; + interpolation = Anims[127].interpolation; + break; + case 2: + animFramePtr = Anims[126].framePtr; + interpolation = Anims[126].interpolation; + break; + case 3: + animFramePtr = Anims[128].framePtr; + interpolation = Anims[128].interpolation; + break; + default: + animFramePtr = Anims[125].framePtr; + interpolation = Anims[125].interpolation; + break; + } + frame = &animFramePtr[Lara.hit_frame * (interpolation >> 8)]; + } + + obj = &Objects[laraitem->objectID]; + if (Lara.skidoo == -1) { + S_PrintShadow(obj->shadowSize, frame, laraitem); + } + + // save hair matrix position + memcpy(&hairMatrix, PhdMatrixPtr, sizeof(hairMatrix)); + + phd_PushMatrix(); + phd_TranslateAbs(laraitem->pos.x, laraitem->pos.y, laraitem->pos.z); + phd_RotYXZ(laraitem->pos.rotY, laraitem->pos.rotX, laraitem->pos.rotZ); + clip = S_GetObjectBounds(frame); + if (clip) { + bones = &AnimBones[obj->boneIndex]; + rot1 = (UINT16 *)frame + 9; + rot1copy = rot1; + + phd_PushMatrix(); + CalculateObjectLighting(laraitem, frame); + phd_TranslateRel(frame[6], frame[7], frame[8]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[0], clip); + + phd_PushMatrix(); + phd_TranslateRel(bones[1], bones[2], bones[3]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[1], clip); + phd_TranslateRel(bones[5], bones[6], bones[7]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[2], clip); + phd_TranslateRel(bones[9], bones[10], bones[11]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[3], clip); + phd_PopMatrix(); + + phd_PushMatrix(); + phd_TranslateRel(bones[13], bones[14], bones[15]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[4], clip); + phd_TranslateRel(bones[17], bones[18], bones[19]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[5], clip); + phd_TranslateRel(bones[21], bones[22], bones[23]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[6], clip); + phd_PopMatrix(); + + phd_TranslateRel(bones[25], bones[26], bones[27]); + currentState = Items[Lara.weapon_item].currentAnimState; + if (Lara.weapon_item != -1 && Lara.gun_type == LGT_M16 && (currentState == 0 || currentState == 2 || currentState == 4)) { + rot1 = (UINT16*)Lara.right_arm.frame_base + Lara.right_arm.frame_number * (Anims[Lara.right_arm.anim_number].interpolation >> 8) + 9; + phd_RotYXZsuperpack(&rot1, 7); + } else { + phd_RotYXZsuperpack(&rot1, 0); + } + phd_RotYXZ(Lara.torso_y_rot, Lara.torso_x_rot, Lara.torso_z_rot); + phd_PutPolygons(Lara.mesh_ptrs[7], clip); + + phd_PushMatrix(); + phd_TranslateRel(bones[53], bones[54], bones[55]); + rot1copy = rot1; + phd_RotYXZsuperpack(&rot1, 6); + rot1 = rot1copy; + phd_RotYXZ(Lara.head_y_rot, Lara.head_x_rot, Lara.head_z_rot); + phd_PutPolygons(Lara.mesh_ptrs[14], clip); + // restore hair matrix position + memcpy(PhdMatrixPtr, &hairMatrix, sizeof(PHD_MATRIX)); + DrawHair(); + phd_PopMatrix(); + + if (Lara.back_gun) { + phd_PushMatrix(); + obj = &Objects[Lara.back_gun]; + phd_TranslateRel(AnimBones[obj->boneIndex + 53], AnimBones[obj->boneIndex + 54], AnimBones[obj->boneIndex + 55]); + rot2 = (UINT16*)Objects[Lara.back_gun].frameBase + 9; + phd_RotYXZsuperpack(&rot2, 14); + phd_PutPolygons(MeshPtr[obj->meshIndex + 14], clip); + phd_PopMatrix(); + } + + if (Lara.gun_status == LGS_Ready || Lara.gun_status == LGS_Special || Lara.gun_status == LGS_Draw || Lara.gun_status == LGS_Undraw) { + gunType = Lara.gun_type; + } else { + gunType = LGT_Unarmed; + } + + switch (gunType) { + case LGT_Unarmed: + case LGT_Flare: + phd_PushMatrix(); + phd_TranslateRel(bones[29], bones[30], bones[31]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[8], clip); + + phd_TranslateRel(bones[33], bones[34], bones[35]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[9], clip); + + phd_TranslateRel(bones[37], bones[38], bones[39]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[10], clip); + phd_PopMatrix(); + + phd_PushMatrix(); + phd_TranslateRel(bones[41], bones[42], bones[43]); + if (Lara.flare_control_left) { + rot1 = (UINT16*)Lara.left_arm.frame_base + (Lara.left_arm.frame_number - Anims[Lara.left_arm.anim_number].frameBase) * (Anims[Lara.left_arm.anim_number].interpolation >> 8) + 9; + phd_RotYXZsuperpack(&rot1, 11); + } else { + phd_RotYXZsuperpack(&rot1, 0); + } + phd_PutPolygons(Lara.mesh_ptrs[11], clip); + + phd_TranslateRel(bones[45], bones[46], bones[47]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[12], clip); + + phd_TranslateRel(bones[49], bones[50], bones[51]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[13], clip); + if (Lara.gun_type == LGT_Flare && Lara.left_arm.flash_gun) { + DrawGunFlash(LGT_Flare, clip); + } + phd_PopMatrix(); + break; + case LGT_Pistols: + case LGT_Magnums: + case LGT_Uzis: + phd_PushMatrix(); + phd_TranslateRel(bones[29], bones[30], bones[31]); + PhdMatrixPtr->_00 = PhdMatrixPtr[-2]._00; + PhdMatrixPtr->_01 = PhdMatrixPtr[-2]._01; + PhdMatrixPtr->_02 = PhdMatrixPtr[-2]._02; + PhdMatrixPtr->_10 = PhdMatrixPtr[-2]._10; + PhdMatrixPtr->_11 = PhdMatrixPtr[-2]._11; + PhdMatrixPtr->_12 = PhdMatrixPtr[-2]._12; + PhdMatrixPtr->_20 = PhdMatrixPtr[-2]._20; + PhdMatrixPtr->_21 = PhdMatrixPtr[-2]._21; + PhdMatrixPtr->_22 = PhdMatrixPtr[-2]._22; + phd_RotYXZ(Lara.right_arm.y_rot, Lara.right_arm.x_rot, Lara.right_arm.z_rot); + rot1 = (UINT16*)Lara.right_arm.frame_base + (Lara.right_arm.frame_number - Anims[Lara.right_arm.anim_number].frameBase) * (Anims[Lara.right_arm.anim_number].interpolation >> 8) + 9; + phd_RotYXZsuperpack(&rot1, 8); + phd_PutPolygons(Lara.mesh_ptrs[8], clip); + + phd_TranslateRel(bones[33], bones[34], bones[35]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[9], clip); + + phd_TranslateRel(bones[37], bones[38], bones[39]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[10], clip); + if (Lara.right_arm.flash_gun) { + memcpy(&weaponMatrix, PhdMatrixPtr, sizeof(PHD_MATRIX)); + } + phd_PopMatrix(); + + phd_PushMatrix(); + phd_TranslateRel(bones[41], bones[42], bones[43]); + PhdMatrixPtr->_00 = PhdMatrixPtr[-2]._00; + PhdMatrixPtr->_01 = PhdMatrixPtr[-2]._01; + PhdMatrixPtr->_02 = PhdMatrixPtr[-2]._02; + PhdMatrixPtr->_10 = PhdMatrixPtr[-2]._10; + PhdMatrixPtr->_11 = PhdMatrixPtr[-2]._11; + PhdMatrixPtr->_12 = PhdMatrixPtr[-2]._12; + PhdMatrixPtr->_20 = PhdMatrixPtr[-2]._20; + PhdMatrixPtr->_21 = PhdMatrixPtr[-2]._21; + PhdMatrixPtr->_22 = PhdMatrixPtr[-2]._22; + phd_RotYXZ(Lara.left_arm.y_rot, Lara.left_arm.x_rot, Lara.left_arm.z_rot); + rot1 = (UINT16*)Lara.left_arm.frame_base + (Lara.left_arm.frame_number - Anims[Lara.left_arm.anim_number].frameBase) * (Anims[Lara.left_arm.anim_number].interpolation >> 8) + 9; + phd_RotYXZsuperpack(&rot1, 11); + phd_PutPolygons(Lara.mesh_ptrs[11], clip); + + phd_TranslateRel(bones[45], bones[46], bones[47]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[12], clip); + + phd_TranslateRel(bones[49], bones[50], bones[51]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[13], clip); + + if (Lara.left_arm.flash_gun) { + DrawGunFlash(gunType, 0); + } + if (Lara.right_arm.flash_gun) { + memcpy(PhdMatrixPtr, &weaponMatrix, sizeof(PHD_MATRIX)); + DrawGunFlash(gunType, clip); + } + phd_PopMatrix(); + break; + case LGT_Shotgun: + case LGT_M16: + case LGT_Grenade: + case LGT_Harpoon: + phd_PushMatrix(); + phd_TranslateRel(bones[29], bones[30], bones[31]); + rot1 = (UINT16*)Lara.right_arm.frame_base + Lara.right_arm.frame_number * (Anims[Lara.right_arm.anim_number].interpolation >> 8) + 9; + phd_RotYXZsuperpack(&rot1, 8); + phd_PutPolygons(Lara.mesh_ptrs[8], clip); + + phd_TranslateRel(bones[33], bones[34], bones[35]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[9], clip); + + phd_TranslateRel(bones[37], bones[38], bones[39]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[10], clip); + if (Lara.right_arm.flash_gun) { + memcpy(&weaponMatrix, PhdMatrixPtr, sizeof(PHD_MATRIX)); + } + phd_PopMatrix(); + + phd_PushMatrix(); + phd_TranslateRel(bones[41], bones[42], bones[43]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[11], clip); + + phd_TranslateRel(bones[45], bones[46], bones[47]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[12], clip); + + phd_TranslateRel(bones[49], bones[50], bones[51]); + phd_RotYXZsuperpack(&rot1, 0); + phd_PutPolygons(Lara.mesh_ptrs[13], clip); + + if (Lara.right_arm.flash_gun) { + memcpy(PhdMatrixPtr, &weaponMatrix, sizeof(PHD_MATRIX)); + DrawGunFlash(gunType, clip); + } + phd_PopMatrix(); + break; + default: + break; + } + phd_PopMatrix(); + } + + phd_PopMatrix(); + PhdWinBottom = oldBottom; + PhdWinTop = oldTop; + PhdWinLeft = oldLeft; + PhdWinRight = oldRight; +} + void __cdecl DrawLaraInt(ITEM_INFO *item, __int16 *frame1, __int16 *frame2, int frac, int rate) { PHD_MATRIX matrix; UINT16 *rot1, *rot2, *rot1copy, *rot2copy; @@ -894,6 +1215,87 @@ void __cdecl DrawLaraInt(ITEM_INFO *item, __int16 *frame1, __int16 *frame2, int phd_PopMatrix(); } +void __cdecl InitInterpolate(int frac, int rate) { + IMRate = rate; + IMFrac = frac; + IMPtr = IMStack; + memcpy(IMStack, PhdMatrixPtr, sizeof(PHD_MATRIX)); +} + +void __cdecl phd_PopMatrix_I() { + phd_PopMatrix(); + --IMPtr; +} + +void __cdecl phd_PushMatrix_I() { + phd_PushMatrix(); + memcpy(&IMPtr[1], &IMPtr[0], sizeof(PHD_MATRIX)); + ++IMPtr; +} + +void __cdecl phd_RotY_I(__int16 angle) { + PHD_MATRIX *oldMatrix; + phd_RotY(angle); + oldMatrix = PhdMatrixPtr; + PhdMatrixPtr = IMPtr; + phd_RotY(angle); + PhdMatrixPtr = oldMatrix; +} + +void __cdecl phd_RotX_I(__int16 angle) { + PHD_MATRIX *oldMatrix; + phd_RotX(angle); + oldMatrix = PhdMatrixPtr; + PhdMatrixPtr = IMPtr; + phd_RotX(angle); + PhdMatrixPtr = oldMatrix; +} + +void __cdecl phd_RotZ_I(__int16 angle) { + PHD_MATRIX *oldMatrix; + phd_RotZ(angle); + oldMatrix = PhdMatrixPtr; + PhdMatrixPtr = IMPtr; + phd_RotZ(angle); + PhdMatrixPtr = oldMatrix; +} + +void __cdecl phd_TranslateRel_I(int x, int y, int z) { + PHD_MATRIX *oldMatrix; + phd_TranslateRel(x, y, z); + oldMatrix = PhdMatrixPtr; + PhdMatrixPtr = IMPtr; + phd_TranslateRel(x, y, z); + PhdMatrixPtr = oldMatrix; +} + +void __cdecl phd_TranslateRel_ID(int x1, int y1, int z1, int x2, int y2, int z2) { + PHD_MATRIX *oldMatrix; + phd_TranslateRel(x1, y1, z1); + oldMatrix = PhdMatrixPtr; + PhdMatrixPtr = IMPtr; + phd_TranslateRel(x2, y2, z2); + PhdMatrixPtr = oldMatrix; +} + +void __cdecl phd_RotYXZ_I(__int16 y, __int16 x, __int16 z) { + PHD_MATRIX *oldMatrix; + phd_RotYXZ(y, x, z); + oldMatrix = PhdMatrixPtr; + PhdMatrixPtr = IMPtr; + phd_RotYXZ(y, x, z); + PhdMatrixPtr = oldMatrix; +} + +void __cdecl phd_RotYXZsuperpack_I(UINT16 **pptr1, UINT16 **pptr2, int index) { + PHD_MATRIX *oldMatrix; + phd_RotYXZsuperpack(pptr1, index); + oldMatrix = PhdMatrixPtr; + PhdMatrixPtr = IMPtr; + phd_RotYXZsuperpack(pptr2, index); + PhdMatrixPtr = oldMatrix; +} + void __cdecl phd_RotYXZsuperpack(UINT16 **pptr, int index) { for( int i = 0; i < index; ++i ) { if( (**pptr >> 14) == 0 ) @@ -929,6 +1331,62 @@ void __cdecl phd_PutPolygons_I(__int16 *ptrObj, int clip) { phd_PopMatrix(); } +void __cdecl InterpolateMatrix() { + if (IMRate == 2) { + PhdMatrixPtr->_00 = (PhdMatrixPtr->_00 + IMPtr->_00) >> 1; + PhdMatrixPtr->_01 = (PhdMatrixPtr->_01 + IMPtr->_01) >> 1; + PhdMatrixPtr->_02 = (PhdMatrixPtr->_02 + IMPtr->_02) >> 1; + PhdMatrixPtr->_03 = (PhdMatrixPtr->_03 + IMPtr->_03) >> 1; + + PhdMatrixPtr->_10 = (PhdMatrixPtr->_10 + IMPtr->_10) >> 1; + PhdMatrixPtr->_11 = (PhdMatrixPtr->_11 + IMPtr->_11) >> 1; + PhdMatrixPtr->_12 = (PhdMatrixPtr->_12 + IMPtr->_12) >> 1; + PhdMatrixPtr->_13 = (PhdMatrixPtr->_13 + IMPtr->_13) >> 1; + + PhdMatrixPtr->_20 = (PhdMatrixPtr->_20 + IMPtr->_20) >> 1; + PhdMatrixPtr->_21 = (PhdMatrixPtr->_21 + IMPtr->_21) >> 1; + PhdMatrixPtr->_22 = (PhdMatrixPtr->_22 + IMPtr->_22) >> 1; + PhdMatrixPtr->_23 = (PhdMatrixPtr->_23 + IMPtr->_23) >> 1; + } else { + PhdMatrixPtr->_00 += IMFrac * (IMPtr->_00 - PhdMatrixPtr->_00) / IMRate; + PhdMatrixPtr->_01 += IMFrac * (IMPtr->_01 - PhdMatrixPtr->_01) / IMRate; + PhdMatrixPtr->_02 += IMFrac * (IMPtr->_02 - PhdMatrixPtr->_02) / IMRate; + PhdMatrixPtr->_03 += IMFrac * (IMPtr->_03 - PhdMatrixPtr->_03) / IMRate; + + PhdMatrixPtr->_10 += IMFrac * (IMPtr->_10 - PhdMatrixPtr->_10) / IMRate; + PhdMatrixPtr->_11 += IMFrac * (IMPtr->_11 - PhdMatrixPtr->_11) / IMRate; + PhdMatrixPtr->_12 += IMFrac * (IMPtr->_12 - PhdMatrixPtr->_12) / IMRate; + PhdMatrixPtr->_13 += IMFrac * (IMPtr->_13 - PhdMatrixPtr->_13) / IMRate; + + PhdMatrixPtr->_20 += IMFrac * (IMPtr->_20 - PhdMatrixPtr->_20) / IMRate; + PhdMatrixPtr->_21 += IMFrac * (IMPtr->_21 - PhdMatrixPtr->_21) / IMRate; + PhdMatrixPtr->_22 += IMFrac * (IMPtr->_22 - PhdMatrixPtr->_22) / IMRate; + PhdMatrixPtr->_23 += IMFrac * (IMPtr->_23 - PhdMatrixPtr->_23) / IMRate; + } +} + +void __cdecl InterpolateArmMatrix() { + PhdMatrixPtr->_00 = PhdMatrixPtr[-2]._00; + PhdMatrixPtr->_01 = PhdMatrixPtr[-2]._01; + PhdMatrixPtr->_02 = PhdMatrixPtr[-2]._02; + PhdMatrixPtr->_10 = PhdMatrixPtr[-2]._10; + PhdMatrixPtr->_11 = PhdMatrixPtr[-2]._11; + PhdMatrixPtr->_12 = PhdMatrixPtr[-2]._12; + PhdMatrixPtr->_20 = PhdMatrixPtr[-2]._20; + PhdMatrixPtr->_21 = PhdMatrixPtr[-2]._21; + PhdMatrixPtr->_22 = PhdMatrixPtr[-2]._22; + + if (IMRate == 2) { + PhdMatrixPtr->_03 = (IMPtr->_03 + PhdMatrixPtr->_03) / 2; + PhdMatrixPtr->_13 = (IMPtr->_13 + PhdMatrixPtr->_13) / 2; + PhdMatrixPtr->_23 = (IMPtr->_23 + PhdMatrixPtr->_23) / 2; + } else { + PhdMatrixPtr->_03 += IMFrac * (IMPtr->_03 - PhdMatrixPtr->_03) / IMRate; + PhdMatrixPtr->_13 += IMFrac * (IMPtr->_13 - PhdMatrixPtr->_13) / IMRate; + PhdMatrixPtr->_23 += IMFrac * (IMPtr->_23 - PhdMatrixPtr->_23) / IMRate; + } +} + void __cdecl DrawGunFlash(int weapon, int clip) { __int16 light; int len; @@ -994,6 +1452,52 @@ void __cdecl DrawGunFlash(int weapon, int clip) { #endif // FEATURE_VIDEOFX_IMPROVED } +int __cdecl GetFrames(ITEM_INFO *item, __int16 **frames, int *rate) { + ANIM_STRUCT *anim; + int interopLow, interop; + int frameCurrent; + + anim = &Anims[item->animNumber]; + frames[0] = frames[1] = anim->framePtr; + interopLow = LOBYTE(anim->interpolation); + *rate = interopLow; + frameCurrent = item->frameNumber - anim->frameBase; + frames[0] += frameCurrent / interopLow * (anim->interpolation >> 8); + frames[1] = &frames[0][anim->interpolation >> 8]; + if (!(frameCurrent % interopLow)) { + return 0; + } + interop = interopLow * (frameCurrent / interopLow + 1); + if (interop > anim->frameEnd) { + *rate = anim->frameEnd + interopLow - interop; + } + return frameCurrent % interopLow; +} + +__int16 *__cdecl GetBoundsAccurate(ITEM_INFO *item) { + int rate, frac; + __int16 *frames[2]; + + frac = GetFrames(item, frames, &rate); + if (!frac) { + return frames[0]; + } + for (int i = 0; i < 6; i++, frames[0]++, frames[1]++) { + InterpolateBounds[i] = *frames[0] + frac * (*frames[1] - *frames[0]) / rate; + } + return InterpolateBounds; +} + +__int16 *__cdecl GetBestFrame(ITEM_INFO *item) { + int frac, rate; + __int16 *frames[2]; + frac = GetFrames(item, frames, &rate); + if (frac > rate / 2) { + return frames[1]; + } + return frames[0]; +} + void __cdecl AddDynamicLight(int x, int y, int z, int intensity, int falloff) { int idx = ( DynamicLightCount < ARRAY_SIZE(DynamicLights) ) ? DynamicLightCount++ : 0; DynamicLights[idx].x = x; @@ -1007,8 +1511,8 @@ void __cdecl AddDynamicLight(int x, int y, int z, int intensity, int falloff) { * Inject function */ void Inject_Draw() { -// INJECT(0x00418920, DrawPhaseCinematic); -// INJECT(0x00418960, DrawPhaseGame); + INJECT(0x00418920, DrawPhaseCinematic); + INJECT(0x00418960, DrawPhaseGame); INJECT(0x004189A0, DrawRooms); INJECT(0x00418C50, GetRoomBounds); @@ -1022,33 +1526,33 @@ void Inject_Draw() { // INJECT(----------, DrawDummyItem); INJECT(0x00419A50, DrawAnimatingItem); -// INJECT(0x00419DD0, DrawLara); + INJECT(0x00419DD0, DrawLara); INJECT(0x0041AB00, DrawLaraInt); -// INJECT(0x0041B6F0, InitInterpolate); -// INJECT(0x0041B730, phd_PopMatrix_I); -// INJECT(0x0041B760, phd_PushMatrix_I); -// INJECT(0x0041B790, phd_RotY_I); -// INJECT(0x0041B7D0, phd_RotX_I); -// INJECT(0x0041B810, phd_RotZ_I); -// INJECT(0x0041B850, phd_TranslateRel_I); -// INJECT(0x0041B8A0, phd_TranslateRel_ID); -// INJECT(0x0041B8F0, phd_RotYXZ_I); -// INJECT(0x0041B940, phd_RotYXZsuperpack_I); + INJECT(0x0041B6F0, InitInterpolate); + INJECT(0x0041B730, phd_PopMatrix_I); + INJECT(0x0041B760, phd_PushMatrix_I); + INJECT(0x0041B790, phd_RotY_I); + INJECT(0x0041B7D0, phd_RotX_I); + INJECT(0x0041B810, phd_RotZ_I); + INJECT(0x0041B850, phd_TranslateRel_I); + INJECT(0x0041B8A0, phd_TranslateRel_ID); + INJECT(0x0041B8F0, phd_RotYXZ_I); + INJECT(0x0041B940, phd_RotYXZsuperpack_I); INJECT(0x0041B980, phd_RotYXZsuperpack); INJECT(0x0041BA30, phd_PutPolygons_I); -// INJECT(0x0041BA60, InterpolateMatrix); -// INJECT(0x0041BC10, InterpolateArmMatrix); + INJECT(0x0041BA60, InterpolateMatrix); + INJECT(0x0041BC10, InterpolateArmMatrix); INJECT(0x0041BD10, DrawGunFlash); // INJECT(0x0041BE80, CalculateObjectLighting); -// INJECT(0x0041BF70, GetFrames); -// INJECT(0x0041C010, GetBoundsAccurate); -// INJECT(0x0041C090, GetBestFrame); + INJECT(0x0041BF70, GetFrames); + INJECT(0x0041C010, GetBoundsAccurate); + INJECT(0x0041C090, GetBestFrame); INJECT(0x0041C0D0, AddDynamicLight); } diff --git a/game/draw.h b/game/draw.h index f007824..27e37c9 100644 --- a/game/draw.h +++ b/game/draw.h @@ -27,8 +27,8 @@ /* * Function list */ -#define DrawPhaseCinematic ((int(__cdecl*)(void)) 0x00418920) -#define DrawPhaseGame ((int(__cdecl*)(void)) 0x00418960) +int __cdecl DrawPhaseCinematic(); // 0x00418920 +int __cdecl DrawPhaseGame(); // 0x00418960 void __cdecl DrawRooms(__int16 currentRoom); // 0x004189A0 void __cdecl GetRoomBounds(); // 0x00418C50 @@ -41,33 +41,32 @@ void __cdecl DrawSpriteItem(ITEM_INFO *item); // 0x004199C0 void __cdecl DrawDummyItem(ITEM_INFO *item); void __cdecl DrawAnimatingItem(ITEM_INFO *item); // 0x00419A50 -#define DrawLara ((void(__cdecl*)(ITEM_INFO*)) 0x00419DD0) +void __cdecl DrawLara(ITEM_INFO *laraitem); // 0x00419DD0 void __cdecl DrawLaraInt(ITEM_INFO *item, __int16 *frame1, __int16 *frame2, int frac, int rate); -#define InitInterpolate ((void(__cdecl*)(int, int)) 0x0041B6F0) -#define phd_PopMatrix_I ((void(__cdecl*)(void)) 0x0041B730) -#define phd_PushMatrix_I ((void(__cdecl*)(void)) 0x0041B760) -#define phd_RotY_I ((void(__cdecl*)(__int16)) 0x0041B790) -#define phd_RotX_I ((void(__cdecl*)(__int16)) 0x0041B7D0) -#define phd_RotZ_I ((void(__cdecl*)(__int16)) 0x0041B810) -#define phd_TranslateRel_I ((void(__cdecl*)(int, int, int)) 0x0041B850) -#define phd_TranslateRel_ID ((void(__cdecl*)(int, int, int, int, int, int)) 0x0041B8A0) -#define phd_RotYXZ_I ((void(__cdecl*)(int, int, int)) 0x0041B8F0) -#define phd_RotYXZsuperpack_I ((void(__cdecl*)(UINT16**, UINT16**, int)) 0x0041B940) - +void __cdecl InitInterpolate(int frac, int rate); // 0x0041B6F0 +void __cdecl phd_PopMatrix_I(); // 0x0041B730 +void __cdecl phd_PushMatrix_I(); // 0x0041B760 +void __cdecl phd_RotY_I(__int16 angle); // 0x0041B790 +void __cdecl phd_RotX_I(__int16 angle); // 0x0041B7D0 +void __cdecl phd_RotZ_I(__int16 angle); // 0x0041B810 +void __cdecl phd_TranslateRel_I(int x, int y, int z); // 0x0041B850 +void __cdecl phd_TranslateRel_ID(int x1, int y1, int z1, int x2, int y2, int z2); // 0x0041B8A0 +void __cdecl phd_RotYXZ_I(__int16 y, __int16 x, __int16 z); // 0x0041B8F0 +void __cdecl phd_RotYXZsuperpack_I(UINT16 **pptr1, UINT16 **pptr2, int index); // 0x0041B940 void __cdecl phd_RotYXZsuperpack(UINT16 **pptr, int index); // 0x0041B980 void __cdecl phd_PutPolygons_I(__int16 *ptrObj, int clip); // 0x0041BA30 -#define InterpolateMatrix ((void(__cdecl*)(void)) 0x0041BA60) -#define InterpolateArmMatrix ((void(__cdecl*)(void)) 0x0041BC10) +void __cdecl InterpolateMatrix(); // 0x0041BA60 +void __cdecl InterpolateArmMatrix(); // 0x0041BC10 void __cdecl DrawGunFlash(int weapon, int clip); #define CalculateObjectLighting ((void(__cdecl*)(ITEM_INFO*, __int16*)) 0x0041BE80) -#define GetFrames ((int(__cdecl*)(ITEM_INFO*, __int16**, int*)) 0x0041BF70) -#define GetBoundsAccurate ((__int16*(__cdecl*)(ITEM_INFO*)) 0x0041C010) -#define GetBestFrame ((__int16*(__cdecl*)(ITEM_INFO*)) 0x0041C090) +int __cdecl GetFrames(ITEM_INFO *item, __int16 **frames, int *rate); // 0x0041BF70 +__int16 *__cdecl GetBoundsAccurate(ITEM_INFO *item); // 0x0041C010 +__int16 *__cdecl GetBestFrame(ITEM_INFO *item); // 0x0041C090 void __cdecl AddDynamicLight(int x, int y, int z, int intensity, int falloff); // 0x0041C0D0 diff --git a/game/effects.h b/game/effects.h index 72e1ee8..c78856b 100644 --- a/game/effects.h +++ b/game/effects.h @@ -71,10 +71,8 @@ void __cdecl lara_hands_free(ITEM_INFO *item); // 0x0041D760 void __cdecl flip_map_effect(ITEM_INFO *item); // 0x0041D770 void __cdecl draw_right_gun(ITEM_INFO *item); // 0x0041D780 void __cdecl draw_left_gun(ITEM_INFO *item); // 0x0041D7D0 - // ----------: shoot_right_gun // ----------: shoot_left_gun - void __cdecl swap_meshes_with_meshswap1(ITEM_INFO *item); // 0x0041D820 void __cdecl swap_meshes_with_meshswap2(ITEM_INFO *item); // 0x0041D890 void __cdecl swap_meshes_with_meshswap3(ITEM_INFO *item); // 0x0041D900 diff --git a/game/items.h b/game/items.h index ddc757b..87439b5 100644 --- a/game/items.h +++ b/game/items.h @@ -28,21 +28,14 @@ * Function list */ void __cdecl InitialiseItemArray(int itemCount); // 0x00426CD0 - #define KillItem ((void(__cdecl*)(__int16)) 0x00426D30) #define CreateItem ((__int16(__cdecl*)(void)) 0x00426E50) - void __cdecl InitialiseItem(__int16 itemIndex); // 0x00426E90 - #define RemoveActiveItem ((void(__cdecl*)(__int16)) 0x00427050) #define RemoveDrawnItem ((void(__cdecl*)(__int16)) 0x004270E0) - void __cdecl AddActiveItem(__int16 itemIndex); // 0x00427150 - #define ItemNewRoom ((void(__cdecl*)(__int16, __int16)) 0x004271B0) - int __cdecl GlobalItemReplace(int oldItemID, int newItemID); // 0x00427250 - #define InitialiseFXArray ((void(__cdecl*)(void)) 0x004272D0) #define CreateEffect ((__int16(__cdecl*)(__int16)) 0x00427300) #define KillEffect ((void(__cdecl*)(__int16)) 0x00427370) diff --git a/game/lara.h b/game/lara.h index c3bdb97..ca31e99 100644 --- a/game/lara.h +++ b/game/lara.h @@ -29,9 +29,9 @@ */ #define LaraAboveWater ((void(__cdecl*)(ITEM_INFO*, COLL_INFO*)) 0x00427560) -// 0x00427700: LookUpDown -// 0x00427770: LookLeftRight -// 0x004277F0: ResetLook +#define LookUpDown ((void(__cdecl*)(void)) 0x00427700) +#define LookLeftRight ((void(__cdecl*)(void)) 0x00427770) +#define ResetLook ((void(__cdecl*)(void)) 0x004277F0) // 0x00427880: lara_as_walk // 0x00427910: lara_as_run // 0x00427A60: lara_as_stop diff --git a/game/lara1gun.h b/game/lara1gun.h index 744a175..dd31e2b 100644 --- a/game/lara1gun.h +++ b/game/lara1gun.h @@ -36,7 +36,7 @@ void __cdecl FireShotgun(); // 0x0042BE70 void __cdecl FireM16(BOOL isRunning); // 0x0042BF70 void __cdecl FireHarpoon(); // 0x0042BFF0 -// 0x0042C180: ControlHarpoonBolt +#define ControlHarpoonBolt ((void(__cdecl*)(__int16)) 0x0042C180) void __cdecl FireRocket(); // 0x0042C4D0 void __cdecl ControlRocket(__int16 itemID); // 0x0042C5C0 diff --git a/game/larafire.cpp b/game/larafire.cpp index 3a8b884..deed1d0 100644 --- a/game/larafire.cpp +++ b/game/larafire.cpp @@ -21,9 +21,68 @@ #include "global/precompiled.h" #include "game/larafire.h" +#include "3dsystem/3d_gen.h" +#include "game/control.h" +#include "game/lot.h" #include "global/vars.h" +void __cdecl LaraGetNewTarget(WEAPON_INFO* weapon) { + GAME_VECTOR start, target; + CREATURE_INFO *creature = NULL; + ITEM_INFO *bestItem = NULL, *item = NULL; + int distance; + int bestDistance = 0x7FFFFFFF; + int maxDistance = weapon->targetDist; + int sqrMaxDistance = SQR(maxDistance); + int x, y, z; + VECTOR_ANGLES angles; + __int16 bestYRot = 0x7FFF, yRot; + start.x = LaraItem->pos.x; + start.y = LaraItem->pos.y - 650; + start.z = LaraItem->pos.z; + start.roomNumber = LaraItem->roomNumber; + + for (int i = 0; i < MAXIMUM_CREATURE_SLOTS; i++) { + creature = &ActiveCreatures[i]; + if (creature->item_num != -1 && creature->item_num != Lara.item_number) { + item = &Items[creature->item_num]; + if (item->hitPoints <= 0) + continue; + x = item->pos.x - start.x; + y = item->pos.y - start.y; + z = item->pos.z - start.z; + if ((ABS(x) > maxDistance) || + (ABS(y) > maxDistance) || + (ABS(z) > maxDistance)) + continue; + distance = SQR(z) + SQR(y) + SQR(x); + if (distance < sqrMaxDistance) { + find_target_point(item, &target); + + if (LOS(&start, &target)) { + phd_GetVectorAngles(target.x - start.x, target.y - start.y, target.z - start.z, &angles); + angles.yaw -= LaraItem->pos.rotY + Lara.torso_y_rot; + angles.pitch -= LaraItem->pos.rotX + Lara.torso_x_rot; + if (angles.yaw >= weapon->lockAngles[0] && + angles.yaw <= weapon->lockAngles[1] && + angles.pitch >= weapon->lockAngles[2] && + angles.pitch <= weapon->lockAngles[3]) { + yRot = ABS(angles.yaw); + if (yRot < (bestYRot + 2730) && distance < bestDistance) { + bestDistance = distance; + bestYRot = yRot; + bestItem = item; + } + } + } + } + } + } + + Lara.target = bestItem; + LaraTargetInfo(weapon); +} /* * Inject function @@ -33,11 +92,11 @@ void Inject_LaraFire() { // INJECT(0x0042ECB0, CheckForHoldingState); // INJECT(0x0042ECF0, InitialiseNewWeapon); // INJECT(0x0042EE30, LaraTargetInfo); -// INJECT(0x0042EFD0, LaraGetNewTarget); + INJECT(0x0042EFD0, LaraGetNewTarget); // INJECT(0x0042F1F0, find_target_point); // INJECT(0x0042F2A0, AimWeapon); // INJECT(0x0042F370, FireWeapon); // INJECT(0x0042F6E0, HitTarget); // INJECT(0x0042F780, SmashItem); // INJECT(0x0042F7E0, WeaponObject); -} \ No newline at end of file +} diff --git a/game/larafire.h b/game/larafire.h index 9d5cce3..32de751 100644 --- a/game/larafire.h +++ b/game/larafire.h @@ -31,7 +31,7 @@ #define CheckForHoldingState ((int(__cdecl*)(int)) 0x0042ECB0) #define InitialiseNewWeapon ((void(__cdecl*)(void)) 0x0042ECF0) #define LaraTargetInfo ((void(__cdecl*)(WEAPON_INFO*)) 0x0042EE30) -#define LaraGetNewTarget ((void(__cdecl*)(WEAPON_INFO*)) 0x0042EFD0) +void __cdecl LaraGetNewTarget(WEAPON_INFO* weapon); // 0x0042EFD0 #define find_target_point ((void(__cdecl*)(ITEM_INFO*,GAME_VECTOR*)) 0x0042F1F0) #define AimWeapon ((void(__cdecl*)(WEAPON_INFO*,LARA_ARM*)) 0x0042F2A0) #define FireWeapon ((int(__cdecl*)(int,ITEM_INFO*,ITEM_INFO*,__int16*)) 0x0042F370) diff --git a/game/laraflare.h b/game/laraflare.h index 67011b3..b508bcf 100644 --- a/game/laraflare.h +++ b/game/laraflare.h @@ -39,6 +39,6 @@ void __cdecl DrawFlareInAir(ITEM_INFO *item); // 0x00430090: draw_flare_meshes // 0x004300B0: undraw_flare_meshes // 0x004300D0: ready_flare -// 0x00430110: FlareControl +#define FlareControl ((void(__cdecl*)(__int16)) 0x00430110) #endif // LARA_FLARE_H_INCLUDED diff --git a/game/laramisc.cpp b/game/laramisc.cpp index 67e802b..952be23 100644 --- a/game/laramisc.cpp +++ b/game/laramisc.cpp @@ -320,6 +320,111 @@ void __cdecl LaraControl(__int16 itemID) { Lara.last_pos.z = item->pos.z; } +void __cdecl AnimateLara(ITEM_INFO* item) { + ANIM_STRUCT *anim; + int waterSurfDist; + int velocity; + __int16 *command, soundType; + bool notLand, notWater; + + ++item->frameNumber; + anim = &Anims[item->animNumber]; + if (anim->numberChanges > 0 && GetChange(item, anim)) { + anim = &Anims[item->animNumber]; + item->currentAnimState = anim->currentAnimState; + } + + if (item->frameNumber > anim->frameEnd) { + command = &AnimCommands[anim->commandIndex]; + for (__int16 i = anim->numberCommands; i > 0; i--) { + switch (*command++) { + case 1: + TranslateItem(item, command[0], command[1], command[2]); + command += 3; + break; + case 2: + item->fallSpeed = command[0]; + item->speed = command[1]; + item->gravity = TRUE; + if (Lara.calc_fallspeed) { + item->fallSpeed = Lara.calc_fallspeed; + Lara.calc_fallspeed = 0; + } + command += 2; + break; + case 3: + if (Lara.gun_status != LGS_Special) + Lara.gun_status = LGS_Armless; + break; + case 5: + case 6: + command += 2; + break; + } + } + item->animNumber = anim->jumpAnimNum; + item->frameNumber = anim->jumpFrameNum; + anim = &Anims[anim->jumpAnimNum]; + item->currentAnimState = anim->currentAnimState; + } + + command = &AnimCommands[anim->commandIndex]; + for (__int16 i = anim->numberCommands; i > 0; i--) { + switch (*command++) { + case 1: + command += 3; + continue; + case 2: + break; + case 5: + if (item->frameNumber != command[0]) { + break; + } + waterSurfDist = Lara.water_surface_dist; + soundType = command[1] & 0xC000; // LAND or WATER + notLand = soundType != 0x4000 || (waterSurfDist < 0 && waterSurfDist != NO_HEIGHT); + notWater = soundType != (__int16)0x8000 || waterSurfDist >= 0 || waterSurfDist == NO_HEIGHT; + if (soundType && notLand && notWater) { + break; + } + PlaySoundEffect(command[1] & 0x3FFF, &item->pos, SFX_ALWAYS); + break; + case 6: + if (item->frameNumber != command[0]) { + break; + } + waterSurfDist = Lara.water_surface_dist; + soundType = command[1] & 0xC000; // LAND or WATER + notLand = soundType != 0x4000 || (waterSurfDist < 0 && waterSurfDist != NO_HEIGHT); + notWater = soundType != (__int16)0x8000 || (waterSurfDist >= 0 || waterSurfDist == NO_HEIGHT); + if (soundType != 0 && notLand && notWater) { + break; + } + EffectFunctions[command[1] & 0x3FFF](item); + break; + default: + continue; + } + command += 2; + } + + if (item->gravity) { + velocity = anim->velocity + anim->acceleration * (item->frameNumber - anim->frameBase - 1); + item->speed -= velocity >> 16; + item->speed += (anim->acceleration + velocity) >> 16; + item->fallSpeed += item->fallSpeed >= 128 ? 1 : 6; + item->pos.y += item->fallSpeed; + } else { + velocity = anim->velocity; + if (anim->acceleration) + velocity += anim->acceleration * (item->frameNumber - anim->frameBase); + item->speed = velocity >> 16; + } + + item->pos.x += (item->speed * phd_sin(Lara.move_angle)) >> W2V_SHIFT; + item->pos.z += (item->speed * phd_cos(Lara.move_angle)) >> W2V_SHIFT; +} + void __cdecl UseItem(__int16 itemID) { if( itemID <= ID_NONE || itemID >= ID_NUMBER_OBJECTS ) return; @@ -492,6 +597,96 @@ void __cdecl InitialiseLaraLoad(__int16 itemID) { LaraItem = &Items[itemID]; } +void __cdecl InitialiseLara(GF_LEVEL_TYPE type) { + ITEM_INFO *item = LaraItem; + LARA_INFO *lara = &Lara; + + item->data = lara; + item->collidable = FALSE; + item->hitPoints = 1000; + + lara->hit_direction = -1; + lara->skidoo = -1; + lara->weapon_item = -1; + lara->calc_fallspeed = 0; + lara->climb_status = 0; + lara->pose_count = 0; + lara->hit_frame = 0; + lara->air = 1800; + lara->dive_count = 0; + lara->death_count = 0; + lara->current_active = 0; + lara->spaz_effect_count = 0; + lara->flare_age = 0; + lara->flare_frame = 0; + lara->flare_control_left = FALSE; + lara->flare_control_right = FALSE; + lara->burn = FALSE; + lara->CanMonkeySwing = FALSE; + lara->extra_anim = 0; + lara->keep_ducked = FALSE; + lara->look = TRUE; + lara->back_gun = 0; + lara->water_surface_dist = 100; + lara->last_pos.x = item->pos.x; + lara->last_pos.y = item->pos.y; + lara->last_pos.z = item->pos.z; + lara->spaz_effect = 0; + lara->mesh_effects = 0; + lara->target = 0; + lara->turn_rate = 0; + lara->move_angle = 0; + lara->head_z_rot = 0; + lara->head_y_rot = 0; + lara->head_x_rot = 0; + lara->torso_z_rot = 0; + lara->torso_y_rot = 0; + lara->torso_x_rot = 0; + lara->right_arm.flash_gun = 0; + lara->left_arm.flash_gun = 0; + lara->right_arm.lock = FALSE; + lara->left_arm.lock = FALSE; + lara->creature = NULL; + + if (type == GFL_NORMAL && GF_LaraStartAnim) { + lara->gun_status = LGS_HandBusy; + lara->water_status = LWS_AboveWater; + lara->extra_anim = TRUE; + item->animNumber = Objects[ID_LARA_EXTRA].animIndex; + item->frameNumber = Anims[item->animNumber].frameBase; + item->currentAnimState = EXTRA_BREATH; + item->goalAnimState = GF_LaraStartAnim; + AnimateLara(item); + Camera.type = CAM_Cinematic; + CineFrameIdx = 0; + CinematicPos = item->pos; + } else if CHK_ANY(RoomInfo[item->roomNumber].flags, ROOM_UNDERWATER) { + lara->gun_status = LGS_Armless; + item->animNumber = 108; + item->frameNumber = Anims[108].frameBase; + item->goalAnimState = AS_TREAD; + item->currentAnimState = AS_TREAD; + item->fallSpeed = 0; + } else { + lara->gun_status = LGS_Armless; + item->animNumber = 11; + item->frameNumber = Anims[11].frameBase; + item->goalAnimState = AS_STOP; + item->currentAnimState = AS_STOP; + } + + if (type == GFL_CUTSCENE) { + lara->gun_status = LGS_Armless; + for (UINT32 i = 0; i < ARRAY_SIZE(lara->mesh_ptrs); i++) { + lara->mesh_ptrs[i] = MeshPtr[Objects[ID_LARA].meshIndex + i]; + } + lara->mesh_ptrs[1] = MeshPtr[Objects[ID_LARA_PISTOLS].meshIndex + 1]; + lara->mesh_ptrs[4] = MeshPtr[Objects[ID_LARA_PISTOLS].meshIndex + 4]; + } else { + InitialiseLaraInventory(CurrentLevel); + } +} + void __cdecl InitialiseLaraInventory(int levelID) { int i; START_INFO *start = &SaveGame.start[levelID]; @@ -691,22 +886,76 @@ void __cdecl InitialiseLaraInventory(int levelID) { InitialiseNewWeapon(); } +void __cdecl LaraInitialiseMeshes(int levelID) { + START_INFO *start = &SaveGame.start[levelID]; + + for (UINT32 i = 0; i < ARRAY_SIZE(Lara.mesh_ptrs); i++) { + Lara.mesh_ptrs[i] = MeshPtr[Objects[ID_LARA].meshIndex + i]; + } + + // fill the weapon holster + switch (start->gunType) { + case LGT_Pistols: + Lara.mesh_ptrs[1] = MeshPtr[Objects[ID_LARA_PISTOLS].meshIndex + 1]; + Lara.mesh_ptrs[4] = MeshPtr[Objects[ID_LARA_PISTOLS].meshIndex + 4]; + break; + case LGT_Uzis: + Lara.mesh_ptrs[1] = MeshPtr[Objects[ID_LARA_UZIS].meshIndex + 1]; + Lara.mesh_ptrs[4] = MeshPtr[Objects[ID_LARA_UZIS].meshIndex + 4]; + break; + case LGT_Magnums: + Lara.mesh_ptrs[1] = MeshPtr[Objects[ID_LARA_MAGNUMS].meshIndex + 1]; + Lara.mesh_ptrs[4] = MeshPtr[Objects[ID_LARA_MAGNUMS].meshIndex + 4]; + break; + case LGT_Unarmed: + default: + break; + } + + // if you start with the flare, assign the mesh in the hand + if (start->gunType == LGT_Flare) { + Lara.mesh_ptrs[13] = MeshPtr[Objects[ID_LARA_FLARE].meshIndex + 13]; + } + + // check for back gun now ! + switch (start->gunType) { + case LGT_M16: + Lara.back_gun = ID_LARA_M16; + return; + case LGT_Shotgun: + Lara.back_gun = ID_LARA_SHOTGUN; + return; + case LGT_Grenade: + Lara.back_gun = ID_LARA_GRENADE; + return; + case LGT_Harpoon: + Lara.back_gun = ID_LARA_HARPOON; + return; + } + + // if there is no back gun on start and if there is one in inventory, assign it ! + if (start->has_shotgun) { + Lara.back_gun = ID_LARA_SHOTGUN; + } else if (start->has_m16) { + Lara.back_gun = ID_LARA_M16; + } else if (start->has_grenade) { + Lara.back_gun = ID_LARA_GRENADE; + } else if (start->has_harpoon) { + Lara.back_gun = ID_LARA_HARPOON; + } +} + /* * Inject function */ void Inject_LaraMisc() { INJECT(0x00430380, LaraControl); - -// INJECT(0x00430A10, AnimateLara); - + INJECT(0x00430A10, AnimateLara); INJECT(0x00430D10, UseItem); INJECT(0x00430ED0, LaraCheatGetStuff); INJECT(0x00430F90, ControlLaraExtra); INJECT(0x00430FB0, InitialiseLaraLoad); - -// INJECT(0x00430FE0, InitialiseLara); - + INJECT(0x00430FE0, InitialiseLara); INJECT(0x004312A0, InitialiseLaraInventory); - -// INJECT(0x00431610, LaraInitialiseMeshes); + INJECT(0x00431610, LaraInitialiseMeshes); } diff --git a/game/laramisc.h b/game/laramisc.h index 2e2ea09..2a06d87 100644 --- a/game/laramisc.h +++ b/game/laramisc.h @@ -28,18 +28,13 @@ * Function list */ void __cdecl LaraControl(__int16 itemID); - -#define AnimateLara ((void(__cdecl*)(ITEM_INFO*)) 0x00430A10) - +void __cdecl AnimateLara(ITEM_INFO* item); // 0x00430A10 void __cdecl UseItem(__int16 itemID); // 0x00430D10 void __cdecl LaraCheatGetStuff(); // 0x00430ED0 void __cdecl ControlLaraExtra(__int16 itemID); // 0x00430F90 void __cdecl InitialiseLaraLoad(__int16 itemID); // 0x00430FB0 - -#define InitialiseLara ((void(__cdecl*)(int)) 0x00430FE0) - +void __cdecl InitialiseLara(GF_LEVEL_TYPE type); // 0x00430FE0 void __cdecl InitialiseLaraInventory(int levelID); // 0x004312A0 - -#define LaraInitialiseMeshes ((void(__cdecl*)(int)) 0x00431610) +void __cdecl LaraInitialiseMeshes(int levelID); // 0x00431610 #endif // LARAMISC_H_INCLUDED diff --git a/game/laraswim.cpp b/game/laraswim.cpp index d9bfeca..b6e3eae 100644 --- a/game/laraswim.cpp +++ b/game/laraswim.cpp @@ -21,8 +21,142 @@ #include "global/precompiled.h" #include "game/laraswim.h" +#include "3dsystem/phd_math.h" +#include "game/control.h" +#include "game/collide.h" +#include "game/items.h" +#include "game/lara.h" +#include "game/larafire.h" +#include "game/laramisc.h" +#include "game/objects.h" #include "global/vars.h" +#ifdef FEATURE_CHEAT +static int OpenDoorsCheatCooldown = 0; +// NOTE: this come from Tomb1Main (Door Cheat) +void DoorOpenNearest(int rangeClick) { + int max_dist = SQR((1024 * rangeClick) >> 8); + for (int itemID = 0; itemID < LevelItemCount; itemID++) { + ITEM_INFO *item = &Items[itemID]; + int dx = (item->pos.x - LaraItem->pos.x) >> 8; + int dy = (item->pos.y - LaraItem->pos.y) >> 8; + int dz = (item->pos.z - LaraItem->pos.z) >> 8; + int dist = SQR(dx) + SQR(dy) + SQR(dz); + if (dist > max_dist) { + continue; + } + if ((item->objectID < ID_DOOR_TYPE1 + || item->objectID > ID_DOOR_TYPE8) + && item->objectID != ID_TRAPDOOR_TYPE1 + && item->objectID != ID_TRAPDOOR_TYPE2 + && item->objectID != ID_TRAPDOOR_TYPE3) { + continue; + } + if (!item->active) { + AddActiveItem(itemID); + item->flags |= IFL_CODEBITS; + } else if CHK_ANY(item->flags, IFL_CODEBITS) { + item->flags &= ~IFL_CODEBITS; + } else { + item->flags |= IFL_CODEBITS; + } + item->timer = 0; + item->touchBits = 0; + } +} +#endif + +void __cdecl LaraUnderWater(ITEM_INFO *item, COLL_INFO *coll) { + int s, c; + + coll->badPos = -NO_HEIGHT; + coll->badNeg = -400; + coll->badCeiling = 400; + coll->old.x = item->pos.x; + coll->old.y = item->pos.y; + coll->old.z = item->pos.z; + coll->radius = 300; + coll->trigger = 0; + coll->slopesAreWalls = 0; + coll->slopesArePits = 0; + coll->lavaIsPit = 0; + coll->enableSpaz = 0; + coll->enableBaddiePush = 1; + + if (CHK_ANY(InputStatus, IN_LOOK) && Lara.look) { + LookLeftRight(); + } else { + ResetLook(); + } + + Lara.look = TRUE; + if (Lara.extra_anim) { + ExtraFunctions[item->currentAnimState](item, coll); + } else { + LaraControlFunctions[item->currentAnimState](item, coll); + } + + if (item->pos.rotZ < -364 || item->pos.rotZ > 364) { + if (item->pos.rotZ >= 0) { + item->pos.rotZ -= 364; + } else { + item->pos.rotZ += 364; + } + } else { + item->pos.rotZ = 0; + } + + CLAMP(item->pos.rotX, -15470, 15470) + CLAMP(item->pos.rotZ, -4004, 4004) + + if (Lara.turn_rate < -364 || Lara.turn_rate > 364) { + if (Lara.turn_rate >= 0) { + Lara.turn_rate -= 364; + } else { + Lara.turn_rate += 364; + } + } else { + Lara.turn_rate = 0; + } + + item->pos.rotY += Lara.turn_rate; + if (Lara.current_active && Lara.water_status != LWS_Cheat) { + LaraWaterCurrent(coll); + } + AnimateLara(item); + + c = (item->fallSpeed * phd_cos(item->pos.rotY)) >> 16; + s = (item->fallSpeed * phd_sin(item->pos.rotY)) >> 16; + item->pos.y -= (item->fallSpeed * phd_sin(item->pos.rotX)) >> 16; + item->pos.x += (phd_cos(item->pos.rotX) * s) >> W2V_SHIFT; + item->pos.z += (phd_cos(item->pos.rotX) * c) >> W2V_SHIFT; + + if (Lara.water_status != LWS_Cheat && Lara.extra_anim == 0) { + LaraBaddieCollision(item, coll); + } + + if (Lara.extra_anim == 0) { + LaraCollisionFunctions[item->currentAnimState](item, coll); + } + +#ifdef FEATURE_CHEAT + // NOTE: this come from Tomb1Main (Door Cheat) + // Press Draw key to open any near door ! + if (Lara.water_status == LWS_Cheat) { + if (OpenDoorsCheatCooldown) { + OpenDoorsCheatCooldown--; + } else if CHK_ANY(InputStatus, IN_DRAW) { + OpenDoorsCheatCooldown = FRAMES_PER_SECOND; + DoorOpenNearest(5); + } + } +#endif // FEATURE_CHEAT + + UpdateLaraRoom(item, 0); + LaraGun(); + TestTriggers(coll->trigger, FALSE); +} + void __cdecl SwimTurn(ITEM_INFO *item) { if( CHK_ANY(InputStatus, IN_FORWARD) ) { item->pos.rotX -= 2*PHD_DEGREE; @@ -73,7 +207,7 @@ void __cdecl lara_as_swim(ITEM_INFO *item, COLL_INFO *coll) { * Inject function */ void Inject_LaraSwim() { -// INJECT(0x00432000, LaraUnderWater); + INJECT(0x00432000, LaraUnderWater); INJECT(0x00432230, SwimTurn); INJECT(0x004322C0, lara_as_swim); diff --git a/game/laraswim.h b/game/laraswim.h index 5a04c43..0ff1664 100644 --- a/game/laraswim.h +++ b/game/laraswim.h @@ -27,7 +27,7 @@ /* * Function list */ -#define LaraUnderWater ((void(__cdecl*)(ITEM_INFO*, COLL_INFO*)) 0x00432000) +void __cdecl LaraUnderWater(ITEM_INFO *item, COLL_INFO *coll); // 0x00432000 void __cdecl SwimTurn(ITEM_INFO *item); // 0x00432230 void __cdecl lara_as_swim(ITEM_INFO *item, COLL_INFO *coll); // 0x004322C0 @@ -48,6 +48,6 @@ void __cdecl lara_as_swim(ITEM_INFO *item, COLL_INFO *coll); // 0x004322C0 // 0x004326F0: LaraTestWaterDepth // 0x004327C0: LaraSwimCollision -// 0x00432920: LaraWaterCurrent +#define LaraWaterCurrent ((void(__cdecl*)(COLL_INFO*)) 0x00432920) #endif // LARA_SWIM_H_INCLUDED diff --git a/game/lot.cpp b/game/lot.cpp index 0a411f2..67ec371 100644 --- a/game/lot.cpp +++ b/game/lot.cpp @@ -21,18 +21,177 @@ #include "global/precompiled.h" #include "game/lot.h" +#include "specific/init.h" #include "global/vars.h" +#ifdef FEATURE_GOLD +extern bool IsGold(); +#endif +void __cdecl InitialiseLOTarray() { + ActiveCreatures = (CREATURE_INFO*)game_malloc(MAXIMUM_CREATURE_SLOTS * sizeof(CREATURE_INFO), GBUF_CreatureData); + for (int i = 0; i < MAXIMUM_CREATURE_SLOTS; i++) { + CREATURE_INFO *creature = &ActiveCreatures[i]; + creature->item_num = -1; + creature->LOT.node = (BOX_NODE*)game_malloc(sizeof(BOX_NODE) * BoxesCount, GBUF_CreatureLOT); + } + ActiveCreaturesUsed = 0; +} + +void __cdecl DisableBaddieAI(__int16 itemNum) { + CREATURE_INFO *creature = NULL; + ITEM_INFO *item = &Items[itemNum]; + + if (itemNum == Lara.item_number) { + creature = Lara.creature; + Lara.creature = NULL; + } else { + creature = (CREATURE_INFO*)item->data; + item->data = NULL; + } + + if (creature != NULL) { + creature->item_num = -1; + ActiveCreaturesUsed--; + } +} + +BOOL __cdecl EnableBaddieAI(__int16 itemNum, BOOL always) { + if (itemNum == Lara.item_number && Lara.creature != NULL) + return TRUE; + + ITEM_INFO *item = &Items[itemNum]; + if (item->data != NULL) + return TRUE; + + CREATURE_INFO *creature = NULL; + if (ActiveCreaturesUsed >= MAXIMUM_CREATURE_SLOTS) { + int x, y, z; + int distance, bestdistance, slot = -1; + if (!always) { + item = &Items[itemNum]; + x = (item->pos.x - Camera.pos.x) >> 8; + y = (item->pos.y - Camera.pos.y) >> 8; + z = (item->pos.z - Camera.pos.z) >> 8; + bestdistance = SQR(x) + SQR(y) + SQR(z); + } else { + bestdistance = 0; + } + + for (int i = 0; i < MAXIMUM_CREATURE_SLOTS; i++) { + item = &Items[ActiveCreatures[i].item_num]; + x = (item->pos.x - Camera.pos.x) >> 8; + y = (item->pos.y - Camera.pos.y) >> 8; + z = (item->pos.z - Camera.pos.z) >> 8; + distance = SQR(x) + SQR(y) + SQR(z); + if (distance > bestdistance) { + bestdistance = distance; + slot = i; + } + } + + if (slot >= 0 && slot < MAXIMUM_CREATURE_SLOTS) { + creature = &ActiveCreatures[slot]; + item = &Items[creature->item_num]; + item->status = ITEM_INVISIBLE; + DisableBaddieAI(creature->item_num); + InitialiseSlot(itemNum, slot); + return TRUE; + } + } else { + for (int i = 0; i < MAXIMUM_CREATURE_SLOTS; i++) { + creature = &ActiveCreatures[i]; + if (creature->item_num == -1) { + InitialiseSlot(itemNum, i); + return TRUE; + } + } + } + + return FALSE; +} + +void __cdecl InitialiseSlot(__int16 itemNum, int creatureNum) { + CREATURE_INFO *creature = &ActiveCreatures[creatureNum]; + ITEM_INFO *item = &Items[itemNum]; + + if (itemNum == Lara.item_number) + Lara.creature = creature; + else + item->data = creature; + creature->item_num = itemNum; + creature->mood = MOOD_BORED; + creature->neck_rotation = 0; + creature->head_rotation = 0; + creature->maximum_turn = PHD_DEGREE; + creature->flags = 0; + creature->enemy = NULL; + creature->LOT.step = 256; + creature->LOT.drop = -512; + creature->LOT.block_mask = 0x8000; + creature->LOT.fly = 0; + + switch (item->objectID) { + case ID_LARA: + creature->LOT.step = 20480; + creature->LOT.drop = -20480; + creature->LOT.fly = 256; + break; + case ID_SHARK: + case ID_BARRACUDA: + case ID_DIVER: + case ID_JELLY: + case ID_CROW: + case ID_EAGLE: + creature->LOT.step = 20480; + creature->LOT.drop = -20480; + creature->LOT.fly = 16; + if (item->objectID == ID_SHARK) + creature->LOT.block_mask = 0x8000; + break; + case ID_WORKER3: + case ID_WORKER4: + case ID_YETI: + creature->LOT.step = 1024; + creature->LOT.drop = -1024; + break; +#ifdef FEATURE_GOLD + case ID_SPIDER_or_WOLF: // NOTE: don't include wolf since he not climb ! + if (!IsGold()) { + creature->LOT.step = 512; + creature->LOT.drop = -1024; + } + break; + case ID_SKIDOO_ARMED: + creature->LOT.step = 512; + creature->LOT.drop = -1024; + break; +#else + case ID_SPIDER_or_WOLF: + case ID_SKIDOO_ARMED: + creature->LOT.step = 512; + creature->LOT.drop = -1024; + break; +#endif + case ID_DINO: + creature->LOT.block_mask = 0x8000; + break; + } + + ClearLOT(&creature->LOT); + if (itemNum != Lara.item_number) + CreateZone(item); + ActiveCreaturesUsed++; +} /* * Inject function */ void Inject_Lot() { -// INJECT(0x00432B10, InitialiseLOTarray); -// INJECT(0x00432B70, DisableBaddieAI); -// INJECT(0x00432BC0, EnableBaddieAI); -// INJECT(0x00432D70, InitialiseSlot); + INJECT(0x00432B10, InitialiseLOTarray); + INJECT(0x00432B70, DisableBaddieAI); + INJECT(0x00432BC0, EnableBaddieAI); + INJECT(0x00432D70, InitialiseSlot); // INJECT(0x00432F80, CreateZone); // INJECT(0x00433040, ClearLOT); } diff --git a/game/lot.h b/game/lot.h index 01f17d9..702960c 100644 --- a/game/lot.h +++ b/game/lot.h @@ -24,16 +24,17 @@ #include "global/types.h" +#define MAXIMUM_CREATURE_SLOTS 16 + /* * Function list */ -// 0x00432B10: InitialiseLOTarray - -#define DisableBaddieAI ((void(__cdecl*)(__int16)) 0x00432B70) -#define EnableBaddieAI ((int(__cdecl*)(__int16, BOOL)) 0x00432BC0) -// 0x00432D70: InitialiseSlot -// 0x00432F80: CreateZone -// 0x00433040: ClearLOT +void __cdecl InitialiseLOTarray(); // 0x00432B10 +void __cdecl DisableBaddieAI(__int16 itemNum); // 0x00432B70 +BOOL __cdecl EnableBaddieAI(__int16 itemNum, BOOL always); // 0x00432BC0 +void __cdecl InitialiseSlot(__int16 itemNum, int creatureNum); // 0x00432D70 +#define CreateZone ((void(__cdecl*)(ITEM_INFO*)) 0x00432F80) +#define ClearLOT ((void(__cdecl*)(LOT_INFO*)) 0x00433040) #endif // LOT_H_INCLUDED diff --git a/game/missile.h b/game/missile.h index b2863b5..7030d58 100644 --- a/game/missile.h +++ b/game/missile.h @@ -27,13 +27,9 @@ /* * Function list */ - void __cdecl ControlMissile(__int16 fxID); // 0x00433090 - // 0x00433360: ShootAtLara - #define ExplodingDeath ((BOOL(__cdecl*)(__int16, DWORD, __int16)) 0x00433410) - -// 0x004337A0: ControlBodyPart +#define ControlBodyPart ((void(__cdecl*)(__int16)) 0x004337A0) #endif // MISSILE_H_INCLUDED diff --git a/game/moveblock.h b/game/moveblock.h index 0b8acff..74cbae2 100644 --- a/game/moveblock.h +++ b/game/moveblock.h @@ -27,19 +27,14 @@ /* * Function list */ -// 0x004339A0: InitialiseMovingBlock - +#define InitialiseMovingBlock ((void(__cdecl*)(__int16)) 0x004339A0) #define MovableBlock ((void(__cdecl*)(__int16)) 0x004339D0) - -// 0x00433B20: MovableBlockCollision +#define MovableBlockCollision ((void(__cdecl*)(__int16,ITEM_INFO*,COLL_INFO*)) 0x00433B20) // 0x00433D80: TestBlockMovable // 0x00433DD0: TestBlockPush // 0x00433F20: TestBlockPull - -#define AlterFloorHeight ((void(__cdecl*)(ITEM_INFO *, int)) 0x00434160) - -// 0x00434220: DrawMovableBlock - -#define DrawUnclippedItem ((void(__cdecl*)(ITEM_INFO *)) 0x00434250) +#define AlterFloorHeight ((void(__cdecl*)(ITEM_INFO*, int)) 0x00434160) +#define DrawMovableBlock ((void(__cdecl*)(ITEM_INFO*)) 0x00434220) +#define DrawUnclippedItem ((void(__cdecl*)(ITEM_INFO*)) 0x00434250) #endif // MOVE_BLOCK_H_INCLUDED diff --git a/game/objects.cpp b/game/objects.cpp index 46577a9..0c91bbf 100644 --- a/game/objects.cpp +++ b/game/objects.cpp @@ -21,9 +21,98 @@ #include "global/precompiled.h" #include "game/objects.h" +#include "game/control.h" +#include "game/draw.h" +#include "game/items.h" +#include "game/sphere.h" #include "global/vars.h" +#if defined(FEATURE_MOD_CONFIG) +#include "modding/mod_utils.h" +#endif // !FEATURE_MOD_CONFIG +void __cdecl ShutThatDoor(DOORPOS_DATA *door) { + FLOOR_INFO* floor = door->floor; + if (floor != NULL) { + floor->index = 0; + floor->ceiling = -127; + floor->floor = -127; + floor->box = -1; + floor->skyRoom = -1; + floor->pitRoom = -1; + if (door->box != -1) { + Boxes[door->box].overlapIndex |= 0x40; // BLOCKED + } + } +} + +void __cdecl OpenThatDoor(DOORPOS_DATA *door) { + if (door->floor) { + *door->floor = door->data; + if (door->box != -1) { + Boxes[door->box].overlapIndex &= ~0x40; // UNBLOCKED + } + } +} + +void __cdecl DoorControl(__int16 itemID) { + ITEM_INFO *item = &Items[itemID]; + DOOR_DATA *data = (DOOR_DATA*)item->data; + + if (TriggerActive(item)) { + if (item->currentAnimState) { + OpenThatDoor(&data->d1); + OpenThatDoor(&data->d2); + OpenThatDoor(&data->d1flip); + OpenThatDoor(&data->d2flip); + } else { + item->goalAnimState = 1; + } + } + else if (item->currentAnimState == 1) { + item->goalAnimState = 0; + } else { + ShutThatDoor(&data->d1); + ShutThatDoor(&data->d2); + ShutThatDoor(&data->d1flip); + ShutThatDoor(&data->d2flip); + } + AnimateItem(item); +} + +void __cdecl GeneralControl(__int16 itemID) { + ITEM_INFO *item; + PHD_VECTOR pos; + __int16 roomID; + + item = &Items[itemID]; + if (TriggerActive(item)) { + item->goalAnimState = 1; // NOTE: open + } else { + item->goalAnimState = 0; // NOTE: close + } + + AnimateItem(item); + + roomID = item->roomNumber; + GetFloor(item->pos.x, item->pos.y, item->pos.z, &roomID); + if (roomID != item->roomNumber) { + ItemNewRoom(item->roomNumber, roomID); + } + + if (item->status == ITEM_DISABLED) { + RemoveActiveItem(itemID); + item->flags |= IFL_INVISIBLE; + } +#if defined(FEATURE_MOD_CONFIG) + if (IsModBridgeLightFix() && item->objectID != ID_GENERAL) return; +#endif // !FEATURE_MOD_CONFIG + pos.x = 3000; + pos.y = 720; + pos.z = 0; + GetJointAbsPosition(item, &pos, 0); + AddDynamicLight(pos.x, pos.y, pos.z, 14, 11); +} /* * Inject function @@ -45,10 +134,10 @@ void Inject_Objects() { // INJECT(0x00434EB0, SmashWindow); // INJECT(0x00434F80, WindowControl); // INJECT(0x00435020, SmashIceControl); -// INJECT(0x00435100, ShutThatDoor); -// INJECT(0x00435150, OpenThatDoor); + INJECT(0x00435100, ShutThatDoor); + INJECT(0x00435150, OpenThatDoor); // INJECT(0x00435190, InitialiseDoor); -// INJECT(0x00435570, DoorControl); + INJECT(0x00435570, DoorControl); // INJECT(0x00435640, OnDrawBridge); // INJECT(0x00435700, DrawBridgeFloor); // INJECT(0x00435740, DrawBridgeCeiling); @@ -66,6 +155,6 @@ void Inject_Objects() { // INJECT(0x00435BC0, BridgeTilt2Floor); // INJECT(0x00435BF0, BridgeTilt2Ceiling); // INJECT(0x00435C30, CopterControl); -// INJECT(0x00435D40, GeneralControl); + INJECT(0x00435D40, GeneralControl); // INJECT(0x00435E20, DetonatorControl); } diff --git a/game/objects.h b/game/objects.h index 096b944..2464e53 100644 --- a/game/objects.h +++ b/game/objects.h @@ -27,46 +27,44 @@ /* * Function list */ -// 0x004342C0: EarthQuake -// 0x004343A0: ControlCutShotgun -// 0x004343E0: InitialiseFinalLevel -// 0x004344B0: FinalLevelCounter -// 0x004346C0: MiniCopterControl -// 0x004347A0: InitialiseDyingMonk -// 0x00434820: DyingMonk -// 0x004348B0: ControlGongBonger -// 0x00434970: DeathSlideCollision -// 0x00434A30: ControlDeathSlide -// 0x00434CC0: BigBowlControl -// 0x00434DB0: BellControl -// 0x00434E30: InitialiseWindow - +#define EarthQuake ((void(__cdecl*)(__int16)) 0x004342C0) +#define ControlCutShotgun ((void(__cdecl*)(__int16)) 0x004343A0) +#define InitialiseFinalLevel ((void(__cdecl*)()) 0x004343E0) +#define FinalLevelCounter ((void(__cdecl*)(__int16)) 0x004344B0) +#define MiniCopterControl ((void(__cdecl*)(__int16)) 0x004346C0) +#define InitialiseDyingMonk ((void(__cdecl*)(__int16)) 0x004347A0) +#define DyingMonk ((void(__cdecl*)(__int16)) 0x00434820) +#define ControlGongBonger ((void(__cdecl*)(__int16)) 0x004348B0) +#define DeathSlideCollision ((void(__cdecl*)(__int16,ITEM_INFO*,COLL_INFO*)) 0x00434970) +#define ControlDeathSlide ((void(__cdecl*)(__int16)) 0x00434A30) +#define BigBowlControl ((void(__cdecl*)(__int16)) 0x00434CC0) +#define BellControl ((void(__cdecl*)(__int16)) 0x00434DB0) +#define InitialiseWindow ((void(__cdecl*)(__int16)) 0x00434E30) #define SmashWindow ((void(__cdecl*)(__int16)) 0x00434EB0) - -// 0x00434F80: WindowControl -// 0x00435020: SmashIceControl -// 0x00435100: ShutThatDoor -// 0x00435150: OpenThatDoor -// 0x00435190: InitialiseDoor -// 0x00435570: DoorControl -// 0x00435640: OnDrawBridge -// 0x00435700: DrawBridgeFloor -// 0x00435740: DrawBridgeCeiling -// 0x00435780: DrawBridgeCollision -// 0x004357B0: InitialiseLift -// 0x004357F0: LiftControl -// 0x004358D0: LiftFloorCeiling -// 0x00435A50: LiftFloor -// 0x00435A90: LiftCeiling -// 0x00435AD0: BridgeFlatFloor -// 0x00435AF0: BridgeFlatCeiling -// 0x00435B10: GetOffset -// 0x00435B50: BridgeTilt1Floor -// 0x00435B80: BridgeTilt1Ceiling -// 0x00435BC0: BridgeTilt2Floor -// 0x00435BF0: BridgeTilt2Ceiling -// 0x00435C30: CopterControl -// 0x00435D40: GeneralControl -// 0x00435E20: DetonatorControl +#define WindowControl ((void(__cdecl*)(__int16)) 0x00434F80) +#define SmashIceControl ((void(__cdecl*)(__int16)) 0x00435020) +void __cdecl ShutThatDoor(DOORPOS_DATA* door); // 0x00435100 +void __cdecl OpenThatDoor(DOORPOS_DATA* door); // 0x00435150 +#define InitialiseDoor ((void(__cdecl*)(__int16)) 0x00435190) +void __cdecl DoorControl(__int16 itemID); // 0x00435570 +#define OnDrawBridge ((BOOL(__cdecl*)(ITEM_INFO*,int,int)) 0x00435640) +#define DrawBridgeFloor ((void(__cdecl*)(ITEM_INFO*,int,int,int,__int16*)) 0x00435700) +#define DrawBridgeCeiling ((void(__cdecl*)(ITEM_INFO*,int,int,int,__int16*)) 0x00435740) +#define DrawBridgeCollision ((void(__cdecl*)(__int16,ITEM_INFO*,COLL_INFO*)) 0x00435780) +#define InitialiseLift ((void(__cdecl*)(__int16)) 0x004357B0) +#define LiftControl ((void(__cdecl*)(__int16)) 0x004357F0) +#define LiftFloorCeiling ((void(__cdecl*)(ITEM_INFO*,int,int,int,int*,int*)) 0x004358D0) +#define LiftFloor ((void(__cdecl*)(ITEM_INFO*,int,int,int,__int16*)) 0x00435A50) +#define LiftCeiling ((void(__cdecl*)(ITEM_INFO*,int,int,int,__int16*)) 0x00435A90) +#define BridgeFlatFloor ((void(__cdecl*)(ITEM_INFO*,int,int,int,__int16*)) 0x00435AD0) +#define BridgeFlatCeiling ((void(__cdecl*)(ITEM_INFO*,int,int,int,__int16*)) 0x00435AF0) +#define GetOffset ((int(__cdecl*)(ITEM_INFO*,int,int)) 0x00435B10) +#define BridgeTilt1Floor ((void(__cdecl*)(ITEM_INFO*,int,int,int,__int16*)) 0x00435B50) +#define BridgeTilt1Ceiling ((void(__cdecl*)(ITEM_INFO*,int,int,int,__int16*)) 0x00435B80) +#define BridgeTilt2Floor ((void(__cdecl*)(ITEM_INFO*,int,int,int,__int16*)) 0x00435BC0) +#define BridgeTilt2Ceiling ((void(__cdecl*)(ITEM_INFO*,int,int,int,__int16*)) 0x00435BF0) +#define CopterControl ((void(__cdecl*)(__int16)) 0x00435C30) +void __cdecl GeneralControl(__int16 itemID); // 0x00435D40 +#define DetonatorControl ((void(__cdecl*)(__int16)) 0x00435E20) #endif // OBJECTS_H_INCLUDED diff --git a/game/people.h b/game/people.h index 1d41dad..7bd4961 100644 --- a/game/people.h +++ b/game/people.h @@ -28,8 +28,8 @@ * Function list */ // 0x00435EB0: Targetable -// 0x00435F40: ControlGlow -// 0x00435F80: ControlGunShot +#define ControlGlow ((void(__cdecl*)(__int16)) 0x00435F40) +#define ControlGunShot ((void(__cdecl*)(__int16)) 0x00435F80) __int16 __cdecl GunShot(int x, int y, int z, __int16 speed, __int16 rotY, __int16 roomNumber); // 0x00435FD0 __int16 __cdecl GunHit(int x, int y, int z, __int16 speed, __int16 rotY, __int16 roomNumber); // 0x00436040 diff --git a/game/pickup.h b/game/pickup.h index 1f5aa0d..a5b21a8 100644 --- a/game/pickup.h +++ b/game/pickup.h @@ -28,19 +28,16 @@ * Function list */ -#define PickUpCollision ((void(__cdecl*)(__int16, ITEM_INFO *, COLL_INFO *)) 0x00437F20) - -// 0x004383A0: SwitchCollision -// 0x004385B0: SwitchCollision2 -// 0x004386B0: DetonatorCollision -// 0x004388F0: KeyHoleCollision - -#define PuzzleHoleCollision ((void(__cdecl*)(__int16, ITEM_INFO *, COLL_INFO *)) 0x00438B30) - -// 0x00438DF0: SwitchControl +#define PickUpCollision ((void(__cdecl*)(__int16,ITEM_INFO*,COLL_INFO*)) 0x00437F20) +#define SwitchCollision ((void(__cdecl*)(__int16,ITEM_INFO*,COLL_INFO*)) 0x004383A0) +#define SwitchCollision2 ((void(__cdecl*)(__int16,ITEM_INFO*,COLL_INFO*)) 0x004385B0) +#define DetonatorCollision ((void(__cdecl*)(__int16,ITEM_INFO*,COLL_INFO*)) 0x004386B0) +#define KeyHoleCollision ((void(__cdecl*)(__int16,ITEM_INFO*,COLL_INFO*)) 0x004388F0) +#define PuzzleHoleCollision ((void(__cdecl*)(__int16,ITEM_INFO*,COLL_INFO*)) 0x00438B30) +#define SwitchControl ((void(__cdecl*)(__int16)) 0x00438DF0) // 0x00438E30: SwitchTrigger // 0x00438EF0: KeyTrigger // 0x00438F30: PickupTrigger -// 0x00438F70: SecretControl +#define SecretControl ((void(__cdecl*)(__int16)) 0x00438F70) #endif // PICKUP_H_INCLUDED diff --git a/game/savegame.cpp b/game/savegame.cpp index 056bd39..397b54d 100644 --- a/game/savegame.cpp +++ b/game/savegame.cpp @@ -137,8 +137,12 @@ void __cdecl ModifyStartInfo(int levelIdx) { break; } - // Bonus game activated and level is not Assault + // Bonus game activated and level is not Assault give all weapons or else if cheat enabled, give it by default. +#ifdef _DEBUG + if( (SaveGame.bonusFlag && levelIdx != 0) || CHK_ANY(GF_GameFlow.flags, GFF_DozyCheatEnabled) ) { +#else if( SaveGame.bonusFlag && levelIdx != 0 ) { +#endif // !_DEBUG start->available = 1; // make level available start->has_pistols = 1; // Lara has all weapons start->has_magnums = 1; @@ -156,6 +160,8 @@ void __cdecl ModifyStartInfo(int levelIdx) { start->grenadeAmmo = 10001; start->harpoonAmmo = 10001; + start->smallMedipacks = 255; + start->largeMedipacks = 255; start->flares = 255; } } diff --git a/game/setup.cpp b/game/setup.cpp index 7ee1236..14e7357 100644 --- a/game/setup.cpp +++ b/game/setup.cpp @@ -23,23 +23,44 @@ #include "game/setup.h" #include "game/bear.h" #include "game/bird.h" +#include "game/boat.h" #include "game/collide.h" +#include "game/cinema.h" #include "game/diver.h" #include "game/dog.h" #include "game/dragon.h" #include "game/draw.h" #include "game/eel.h" +#include "game/effects.h" #include "game/enemies.h" +#include "game/gameflow.h" #include "game/hair.h" +#include "game/health.h" +#include "game/items.h" +#include "game/invfunc.h" +#include "game/lara1gun.h" +#include "game/laraflare.h" #include "game/laramisc.h" +#include "game/lot.h" #include "game/moveblock.h" +#include "game/missile.h" +#include "game/objects.h" #include "game/people.h" +#include "game/pickup.h" #include "game/rat.h" +#include "game/savegame.h" #include "game/shark.h" #include "game/skidoo.h" #include "game/spider.h" +#include "game/sound.h" +#include "game/traps.h" +#include "game/text.h" #include "game/wolf.h" #include "game/yeti.h" +#include "specific/file.h" +#include "specific/init.h" +#include "specific/output.h" +#include "specific/sndpc.h" #include "specific/winmain.h" #include "global/vars.h" @@ -47,33 +68,97 @@ extern bool IsGold(); #endif -void __cdecl InitialiseLevelFlags() { - memset(&SaveGame.statistics, 0, sizeof(STATISTICS_INFO)); +// NOTE: Create simple pickup item (2D) +// Set isSecret if it's a secret pickup (Example: Dragon Item) +static void SetPickup(GAME_OBJECT_ID objectID, bool isSecret = false) { + OBJECT_INFO* obj = &Objects[objectID]; + obj->drawRoutine = DrawSpriteItem; + obj->collision = PickUpCollision; + obj->save_position = TRUE; + obj->save_flags = TRUE; + if (isSecret) { + obj->control = SecretControl; + } } -void __cdecl InitialiseObjects() { - for( int i = 0; i < ID_NUMBER_OBJECTS; ++i ) { - Objects[i].intelligent = 0; - Objects[i].save_position = 0; - Objects[i].save_hitpoints = 0; - Objects[i].save_flags = 0; - Objects[i].save_anim = 0; - Objects[i].water_creature = 0; - Objects[i].initialise = NULL; - Objects[i].collision = NULL; - Objects[i].control = NULL; - Objects[i].drawRoutine = DrawAnimatingItem; - Objects[i].ceiling = NULL; - Objects[i].floor = NULL; - Objects[i].pivotLength = 0; - Objects[i].radius = 10; - Objects[i].shadowSize = 0; - Objects[i].hitPoints = HP_DONT_TARGET; +BOOL __cdecl InitialiseLevel(int levelID, GF_LEVEL_TYPE levelType) { + BOOL isLoaded = FALSE; + if (levelType != GFL_TITLE && levelType != GFL_CUTSCENE) { + CurrentLevel = levelID; } - BaddyObjects(); - TrapObjects(); - ObjectObjects(); - InitialiseHair(); + IsDemoLevelType = levelType == GFL_DEMO; + InitialiseGameFlags(); + Lara.item_number = -1; + IsTitleLoaded = FALSE; + if (levelType != GFL_TITLE) { + if (levelType == GFL_SAVED || levelType != GFL_CUTSCENE) { + isLoaded = S_LoadLevelFile(GF_LevelFilesStringTable[levelID], levelID, levelType); + } else { + isLoaded = S_LoadLevelFile(GF_CutsFilesStringTable[levelID], levelID, GFL_CUTSCENE); + } + } else { + isLoaded = S_LoadLevelFile(GF_TitleFilesStringTable[0], levelID, GFL_TITLE); + } + + if (isLoaded) { + if (Lara.item_number != -1) { + InitialiseLara(levelType); + } + if (levelType == GFL_NORMAL || levelType == GFL_SAVED || levelType == GFL_DEMO) { + GetCarriedItems(); + } + Effects = (FX_INFO*)game_malloc(sizeof(FX_INFO) * 100, GBUF_EffectsArray); + InitialiseFXArray(); + InitialiseLOTarray(); + InitColours(); + T_InitPrint(); + InitialisePickUpDisplay(); + S_InitialiseScreen(levelType); + HealthBarTimer = 100; + SOUND_Stop(); + + if (levelType == GFL_SAVED) { + ExtractSaveGameInfo(); + } else if (levelType == GFL_NORMAL) { + GF_ModifyInventory(CurrentLevel, FALSE); + } + + if (Objects[ID_FINAL_LEVEL_COUNTER].loaded) { + InitialiseFinalLevel(); + } + + if (levelType == GFL_NORMAL || levelType == GFL_SAVED || levelType == GFL_DEMO) { + if (TrackIDs[0] != 0) { + S_CDPlay(TrackIDs[0], TRUE); + } + } + + IsAssaultTimerActive = FALSE; + IsAssaultTimerDisplay = FALSE; + Camera.underwater = FALSE; + isLoaded = TRUE; + } + + return isLoaded; +} + +void __cdecl InitialiseGameFlags() { + FlipStatus = 0; + ZeroMemory(FlipMaps, sizeof(FlipMaps)); + ZeroMemory(CD_Flags, sizeof(CD_Flags)); + for (int i = 0; i < ID_NUMBER_OBJECTS; i++) { + Objects[i].loaded = FALSE; + } + SunsetTimer = 0; + AmmoTextInfo = NULL; + IsLevelComplete = FALSE; + FlipEffect = -1; + MinesDetonated = FALSE; + IsMonkAngry = FALSE; +} + +void __cdecl InitialiseLevelFlags() { + memset(&SaveGame.statistics, 0, sizeof(STATISTICS_INFO)); } void __cdecl BaddyObjects() { @@ -701,20 +786,586 @@ void __cdecl BaddyObjects() { } } +void __cdecl TrapObjects() { + OBJECT_INFO *obj; + int i; + + obj = &Objects[ID_GONDOLA]; + obj->collision = ObjectCollision; + obj->control = GondolaControl; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_SPIKE_WALL]; + obj->collision = ObjectCollision; + obj->control = ControlSpikeWall; + obj->save_position = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_CEILING_SPIKES]; + obj->collision = TrapCollision; + obj->control = ControlCeilingSpikes; + obj->save_position = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_COPTER]; + obj->control = CopterControl; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_MINI_COPTER]; + obj->control = MiniCopterControl; + obj->save_flags = TRUE; + obj->save_position = TRUE; + + obj = &Objects[ID_HOOK]; + obj->collision = CreatureCollision; + obj->control = HookControl; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_GENERAL]; + obj->collision = ObjectCollision; + obj->control = GeneralControl; + obj->water_creature = TRUE; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_DYING_MONK]; + obj->initialise = InitialiseDyingMonk; + obj->collision = ObjectCollision; + obj->control = DyingMonk; + obj->save_flags = TRUE; + + obj = &Objects[ID_MINE]; + obj->collision = ObjectCollision; + obj->control = MineControl; + obj->save_flags = TRUE; + + obj = &Objects[ID_DEATH_SLIDE]; + obj->initialise = InitialiseRollingBall; + obj->collision = DeathSlideCollision; + obj->control = ControlDeathSlide; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + obj->save_position = TRUE; + + obj = &Objects[ID_PROPELLER1]; + obj->collision = TrapCollision; + obj->control = PropellerControl; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_PROPELLER2]; + obj->collision = ObjectCollision; + obj->control = PropellerControl; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_PROPELLER3]; + obj->collision = TrapCollision; + obj->control = PropellerControl; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + obj->water_creature = TRUE; + + obj = &Objects[ID_PROPELLER4]; + obj->collision = ObjectCollision; + obj->control = PropellerControl; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_SPINNING_BLADE]; + obj->initialise = InitialiseKillerStatue; + obj->control = SpinningBlade; + obj->collision = ObjectCollision; + obj->save_position = TRUE; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_KILLER_STATUE]; + obj->initialise = InitialiseKillerStatue; + obj->control = KillerStatueControl; + obj->collision = TrapCollision; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + for (i = 0; i < 3; i++) { + obj = &Objects[ID_FALLING_BLOCK1 + i]; + obj->control = FallingBlock; + obj->ceiling = FallingBlockCeiling; + obj->floor = FallingBlockFloor; + obj->save_position = TRUE; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + } + + obj = &Objects[ID_ICICLE]; + obj->collision = TrapCollision; + obj->control = IcicleControl; + obj->save_position = TRUE; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_BLADE]; + obj->initialise = InitialiseBlade; + obj->control = BladeControl; + obj->collision = TrapCollision; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_SPRING_BOARD]; + obj->control = SpringBoardControl; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_PENDULUM1]; + obj->collision = ObjectCollision; + obj->control = Pendulum; + obj->shadowSize = 128; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_PENDULUM2]; + obj->collision = ObjectCollision; + obj->control = Pendulum; + obj->shadowSize = 128; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_TEETH_TRAP]; + obj->collision = TrapCollision; + obj->control = TeethTrap; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_FALLING_CEILING]; + obj->collision = TrapCollision; + obj->control = FallingCeiling; + obj->save_position = TRUE; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + for (i = 0; i < 3; i++) { + obj = &Objects[ID_ROLLING_BALL1 + i]; + obj->initialise = InitialiseRollingBall; + obj->collision = RollingBallCollision; + obj->control = RollingBallControl; + obj->save_position = TRUE; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + } + + for (i = 0; i < 4; i++) { + obj = &Objects[ID_MOVABLE_BLOCK1 + i]; + obj->initialise = InitialiseMovingBlock; + obj->collision = MovableBlockCollision; + obj->control = MovableBlock; + obj->drawRoutine = DrawMovableBlock; + obj->save_position = TRUE; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + } + + obj = &Objects[ID_SPIKES]; + obj->collision = SpikeCollision; + + obj = &Objects[ID_DARTS]; + obj->control = DartsControl; + obj->collision = ObjectCollision; + obj->shadowSize = 128; + + obj = &Objects[ID_DART_EMITTER]; + obj->control = DartEmitterControl; + obj->save_flags = TRUE; + + obj = &Objects[ID_DART_EFFECT]; + obj->control = DartEffectControl; + obj->drawRoutine = DrawSpriteItem; + obj->semi_transparent = TRUE; + + obj = &Objects[ID_FLAME]; + obj->control = FlameControl; + obj->semi_transparent = TRUE; + + obj = &Objects[ID_FLAME_EMITTER]; + obj->control = FlameEmitterControl; + obj->drawRoutine = DrawDummyItem; + obj->save_flags = TRUE; + + obj = &Objects[ID_LAVA]; + obj->control = ControlLavaBlob; + obj->semi_transparent = TRUE; + + obj = &Objects[ID_LAVA_EMITTER]; + obj->control = LavaSpray; + obj->collision = ObjectCollision; + obj->drawRoutine = DrawDummyItem; + obj->save_flags = TRUE; +} + +void __cdecl ObjectObjects() { + OBJECT_INFO* obj; + int i; + + obj = &Objects[ID_CAMERA_TARGET]; + obj->drawRoutine = DrawDummyItem; + + obj = &Objects[ID_ROCKET]; + obj->control = ControlRocket; + obj->save_position = TRUE; + + obj = &Objects[ID_HARPOON_BOLT]; + obj->control = ControlHarpoonBolt; + obj->save_position = TRUE; + + obj = &Objects[ID_MISSILE_KNIFE]; + obj->control = ControlMissile; + obj->save_position = TRUE; + + obj = &Objects[ID_MISSILE_HARPOON]; + obj->control = ControlMissile; + obj->save_position = TRUE; + + for (i = 0; i < 3; i++) { + obj = &Objects[ID_SPHERE_OF_DOOM1 + i]; + obj->control = SphereOfDoom; + obj->drawRoutine = DrawSphereOfDoom; + obj->collision = SphereOfDoomCollision; + if (i < 2) { + obj->semi_transparent = TRUE; + } + obj->save_flags = TRUE; + obj->save_position = TRUE; + } + + obj = &Objects[ID_BIG_BOWL]; + obj->control = BigBowlControl; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_BELL]; + obj->control = BellControl; + obj->collision = ObjectCollision; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_SKIDOO_FAST]; + obj->initialise = InitialiseSkidoo; + obj->collision = SkidooCollision; + obj->drawRoutine = DrawSkidoo; + obj->save_position = TRUE; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_BOAT]; + obj->initialise = InitialiseBoat; + obj->control = BoatControl; + obj->collision = BoatCollision; + obj->save_position = TRUE; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_FLARE_ITEM]; + obj->control = FlareControl; + obj->collision = PickUpCollision; + obj->drawRoutine = DrawFlareInAir; + obj->save_position = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_WINDOW1]; + obj->initialise = InitialiseWindow; + obj->control = WindowControl; + obj->collision = ObjectCollision; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_WINDOW2]; + obj->initialise = InitialiseWindow; + obj->control = SmashIceControl; + obj->collision = ObjectCollision; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_LIFT]; + obj->initialise = InitialiseLift; + obj->control = LiftControl; + obj->floor = LiftFloor; + obj->ceiling = LiftCeiling; + obj->save_position = TRUE; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_BRIDGE_FLAT]; + obj->floor = BridgeFlatFloor; + obj->ceiling = BridgeFlatCeiling; + + obj = &Objects[ID_BRIDGE_TILT1]; + obj->floor = BridgeTilt1Floor; + obj->ceiling = BridgeTilt1Ceiling; + + obj = &Objects[ID_BRIDGE_TILT2]; + obj->floor = BridgeTilt2Floor; + obj->ceiling = BridgeTilt2Ceiling; + + obj = &Objects[ID_DRAW_BRIDGE]; + if (obj->loaded) { + obj->control = GeneralControl; + obj->collision = DrawBridgeCollision; + obj->floor = DrawBridgeFloor; + obj->ceiling = DrawBridgeCeiling; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + } + + for (i = 0; i < 5; i++) { + obj = &Objects[ID_SWITCH_TYPE1 + i]; + obj->control = SwitchControl; + obj->collision = i < 4 ? SwitchCollision : SwitchCollision2; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + } + + for (i = 0; i < 8; i++) { + obj = &Objects[ID_DOOR_TYPE1 + i]; + obj->initialise = InitialiseDoor; + obj->control = DoorControl; + obj->collision = DoorCollision; + obj->drawRoutine = DrawUnclippedItem; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + } + + for (i = 0; i < 2; i++) { + obj = &Objects[ID_TRAPDOOR_TYPE1 + i]; + obj->control = TrapDoorControl; + obj->ceiling = TrapDoorCeiling; + obj->floor = TrapDoorFloor; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + } + + SetPickup(ID_PICKUP_ITEM1); + SetPickup(ID_PICKUP_ITEM2); + SetPickup(ID_KEY_ITEM1); + SetPickup(ID_KEY_ITEM2); + SetPickup(ID_KEY_ITEM3); + SetPickup(ID_KEY_ITEM4); + SetPickup(ID_PUZZLE_ITEM1); + SetPickup(ID_PUZZLE_ITEM2); + SetPickup(ID_PUZZLE_ITEM3); + SetPickup(ID_PUZZLE_ITEM4); + SetPickup(ID_SECRET1, true); + SetPickup(ID_SECRET2, true); + SetPickup(ID_SECRET3, true); + SetPickup(ID_PISTOL_ITEM); + SetPickup(ID_SHOTGUN_ITEM); + SetPickup(ID_MAGNUM_ITEM); + SetPickup(ID_UZI_ITEM); + SetPickup(ID_M16_ITEM); + SetPickup(ID_HARPOON_ITEM); + SetPickup(ID_GRENADE_ITEM); + SetPickup(ID_PISTOL_AMMO_ITEM); + SetPickup(ID_SHOTGUN_AMMO_ITEM); + SetPickup(ID_MAGNUM_AMMO_ITEM); + SetPickup(ID_UZI_AMMO_ITEM); + SetPickup(ID_M16_AMMO_ITEM); + SetPickup(ID_HARPOON_AMMO_ITEM); + SetPickup(ID_GRENADE_AMMO_ITEM); + SetPickup(ID_FLARES_ITEM); + SetPickup(ID_SMALL_MEDIPACK_ITEM); + SetPickup(ID_LARGE_MEDIPACK_ITEM); + + obj = &Objects[ID_GONG_BONGER]; + obj->control = ControlGongBonger; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + for (i = 0; i < 4; i++) { + obj = &Objects[ID_KEY_HOLE1 + i]; + obj->collision = KeyHoleCollision; + obj->save_flags = TRUE; + } + + for (i = 0; i < 4; i++) { + obj = &Objects[ID_PUZZLE_HOLE1 + i]; + obj->collision = PuzzleHoleCollision; + obj->save_flags = TRUE; + } + + for (i = 0; i < 4; i++) { + obj = &Objects[ID_PUZZLE_DONE1 + i]; + obj->save_flags = TRUE; + } + + obj = &Objects[ID_DETONATOR1]; + obj->collision = DetonatorCollision; + + obj = &Objects[ID_DETONATOR2]; + obj->collision = DetonatorCollision; + obj->control = DetonatorControl; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_ALARM_SOUND]; + obj->control = ControlAlarmSound; + obj->save_flags = TRUE; + + obj = &Objects[ID_LARA_ALARM]; + obj->control = ControlLaraAlarm; + obj->drawRoutine = DrawDummyItem; + obj->save_flags = TRUE; + + for (i = 0; i < 10; i++) { + obj = &Objects[ID_PLAYER1 + i]; + obj->initialise = InitialiseGenPlayer; + obj->control = ControlCinematicPlayer; + obj->hitPoints = 1; + } + + obj = &Objects[ID_BLOOD]; + obj->control = ControlBlood1; + obj->semi_transparent = TRUE; + + obj = &Objects[ID_BUBBLES]; + obj->control = ControlBubble1; + + obj = &Objects[ID_EXPLOSION]; + obj->control = ControlExplosion1; + obj->semi_transparent = TRUE; + + obj = &Objects[ID_MISSILE_FLAME]; + obj->control = ControlMissile; + obj->semi_transparent = TRUE; + + obj = &Objects[ID_RICOCHET]; + obj->control = ControlRichochet1; + + obj = &Objects[ID_TWINKLE]; + obj->control = ControlTwinkle; + + obj = &Objects[ID_SPLASH]; + obj->control = ControlSplash1; + obj->semi_transparent = TRUE; + + obj = &Objects[ID_SNOW_SPRITE]; + obj->control = ControlSnowSprite; + + obj = &Objects[ID_WATER_SPRITE]; + obj->control = ControlWaterSprite; + obj->semi_transparent = TRUE; + + obj = &Objects[ID_WATERFALL]; + obj->control = WaterFall; + obj->drawRoutine = DrawDummyItem; + + obj = &Objects[ID_BODY_PART]; + obj->nMeshes = 0; + obj->control = ControlBodyPart; + obj->loaded = TRUE; + + obj = &Objects[ID_GUN_FLASH]; + obj->control = ControlGunShot; + + obj = &Objects[ID_GLOW]; + obj->control = ControlGlow; + + obj = &Objects[ID_HOT_LIQUID]; + obj->control = ControlHotLiquid; + obj->semi_transparent = TRUE; + + for (i = 0; i < 2; i++) { + obj = &Objects[ID_BIRD_TWEETER1 + i]; + obj->control = ControlBirdTweeter; + obj->drawRoutine = DrawDummyItem; + } + + obj = &Objects[ID_DING_DONG]; + obj->control = ControlDingDong; + obj->drawRoutine = DrawDummyItem; + + obj = &Objects[ID_CLOCK_CHIMES]; + obj->control = ControlClockChimes; + obj->drawRoutine = DrawDummyItem; + obj->save_flags = TRUE; + + obj = &Objects[ID_FINAL_LEVEL_COUNTER]; + obj->control = FinalLevelCounter; + obj->drawRoutine = DrawDummyItem; + obj->save_flags = TRUE; + + obj = &Objects[ID_CUT_SHOTGUN]; + obj->control = ControlCutShotgun; + obj->save_anim = TRUE; + obj->save_flags = TRUE; + + obj = &Objects[ID_EARTHQUAKE]; + obj->control = EarthQuake; + obj->drawRoutine = DrawDummyItem; + obj->save_flags = TRUE; +} + +void __cdecl InitialiseObjects() { + for( int i = 0; i < ID_NUMBER_OBJECTS; ++i ) { + Objects[i].intelligent = FALSE; + Objects[i].save_position = FALSE; + Objects[i].save_hitpoints = FALSE; + Objects[i].save_flags = FALSE; + Objects[i].save_anim = FALSE; + Objects[i].water_creature = FALSE; + Objects[i].initialise = NULL; + Objects[i].collision = NULL; + Objects[i].control = NULL; + Objects[i].drawRoutine = DrawAnimatingItem; + Objects[i].ceiling = NULL; + Objects[i].floor = NULL; + Objects[i].pivotLength = 0; + Objects[i].radius = 10; + Objects[i].shadowSize = 0; + Objects[i].hitPoints = HP_DONT_TARGET; + } + BaddyObjects(); + TrapObjects(); + ObjectObjects(); + InitialiseHair(); +} + +void __cdecl GetCarriedItems() { + ITEM_INFO *item, *pickup; + int i; + + for (i = 0, item = Items; i < LevelItemCount; i++, item++) { + if (Objects[item->objectID].intelligent) { + item->carriedItem = -1; + __int16 pickupID = RoomInfo[item->roomNumber].itemNumber; + while (pickupID != -1) + { + pickup = &Items[pickupID]; + if (pickup->pos.x == item->pos.x + && pickup->pos.y == item->pos.y + && pickup->pos.z == item->pos.z + && Objects[pickup->objectID].collision == PickUpCollision) { + pickup->carriedItem = item->carriedItem; + item->carriedItem = pickupID; + RemoveDrawnItem(pickupID); + pickup->roomNumber = 255; + } + pickupID = pickup->nextItem; + } + } + } +} + /* * Inject function */ void Inject_Setup() { -// INJECT(0x0043A330, InitialiseLevel); -// INJECT(0x0043A490, InitialiseGameFlags); - + INJECT(0x0043A330, InitialiseLevel); + INJECT(0x0043A490, InitialiseGameFlags); INJECT(0x0043A500, InitialiseLevelFlags); INJECT(0x0043A530, BaddyObjects); - -// INJECT(0x0043B570, TrapObjects); -// INJECT(0x0043BB70, ObjectObjects); - + INJECT(0x0043B570, TrapObjects); + INJECT(0x0043BB70, ObjectObjects); INJECT(0x0043C7C0, InitialiseObjects); - -// INJECT(0x0043C830, GetCarriedItems); + INJECT(0x0043C830, GetCarriedItems); } diff --git a/game/setup.h b/game/setup.h index 6831604..29a8910 100644 --- a/game/setup.h +++ b/game/setup.h @@ -27,18 +27,13 @@ /* * Function list */ -#define InitialiseLevel ((BOOL(__cdecl*)(int,int)) 0x0043A330) - -// 0x0043A490: InitialiseGameFlags - +BOOL __cdecl InitialiseLevel(int levelID, GF_LEVEL_TYPE levelType); // 0x0043A330 +void __cdecl InitialiseGameFlags(); // 0x0043A490 void __cdecl InitialiseLevelFlags(); // 0x0043A500 void __cdecl BaddyObjects(); // 0x0043A530 - -#define TrapObjects ((void(__cdecl*)(void)) 0x0043B570) -#define ObjectObjects ((void(__cdecl*)(void)) 0x0043BB70) - +void __cdecl TrapObjects(); // 0x0043B570 +void __cdecl ObjectObjects(); // 0x0043BB70 void __cdecl InitialiseObjects(); // 0x0043C7C0 - -// 0x0043C830: GetCarriedItems +void __cdecl GetCarriedItems(); // 0x0043C830 #endif // SETUP_H_INCLUDED diff --git a/game/skidoo.h b/game/skidoo.h index 3a95247..16a23f2 100644 --- a/game/skidoo.h +++ b/game/skidoo.h @@ -29,8 +29,8 @@ */ #define InitialiseSkidoo ((void(__cdecl*)(__int16)) 0x0043CEE0) -// 0x0043CF20: SkidooCheckGeton -// 0x0043D010: SkidooCollision +// 0x0043CF20: SkidooCheckGetOn +#define SkidooCollision ((void(__cdecl*)(__int16,ITEM_INFO*,COLL_INFO*)) 0x0043D010) // 0x0043D110: SkidooBaddieCollision // 0x0043D310: TestHeight // 0x0043D3D0: DoShift @@ -50,7 +50,7 @@ void __cdecl SkidooExplode(ITEM_INFO *item); // 0x0043E2D0 void __cdecl SkidooGuns(); // 0x0043E590 -// 0x0043E6B0: SkidooControl +#define SkidooControl ((void(__cdcel*)(__int16)) 0x0043E6B0) void __cdecl DrawSkidoo(ITEM_INFO *item); @@ -59,6 +59,6 @@ void __cdecl DrawSkidoo(ITEM_INFO *item); // 0x0043F280: SkidmanPush -#define SkidmanCollision ((void(__cdecl*)(__int16, ITEM_INFO *, COLL_INFO *)) 0x0043F3A0) +#define SkidmanCollision ((void(__cdecl*)(__int16,ITEM_INFO*,COLL_INFO*)) 0x0043F3A0) #endif // SKIDOO_H_INCLUDED diff --git a/game/sound.h b/game/sound.h index c409403..130946c 100644 --- a/game/sound.h +++ b/game/sound.h @@ -28,12 +28,10 @@ * Function list */ int __cdecl GetRealTrack(int trackID); // 0x0043F430 - #define PlaySoundEffect ((void(__cdecl*)(DWORD, PHD_3DPOS *, DWORD)) 0x0043F470) #define StopSoundEffect ((void(__cdecl*)(int)) 0x0043F910) #define SOUND_EndScene ((void(__cdecl*)(void)) 0x0043F970) #define SOUND_Stop ((void(__cdecl*)(void)) 0x0043FA00) - void __cdecl SOUND_Init(); // 0x0043FA30 #endif // SOUND_H_INCLUDED diff --git a/game/sphere.cpp b/game/sphere.cpp index d5b0b4a..5fb0419 100644 --- a/game/sphere.cpp +++ b/game/sphere.cpp @@ -21,9 +21,72 @@ #include "global/precompiled.h" #include "game/sphere.h" +#include "3dsystem/3d_gen.h" +#include "game/draw.h" +#include "game/effects.h" #include "global/vars.h" +void __cdecl GetJointAbsPosition(ITEM_INFO *item, PHD_VECTOR *pos, int joint) { + OBJECT_INFO *obj; + int *bones, flags; + UINT16 *rotation; + __int16 *frame, *rot; + + obj = &Objects[item->objectID]; + bones = &AnimBones[obj->boneIndex]; + frame = GetBestFrame(item); + rot = (__int16*)item->data; + + phd_PushUnitMatrix(); + PhdMatrixPtr->_03 = 0; + PhdMatrixPtr->_13 = 0; + PhdMatrixPtr->_23 = 0; + phd_RotYXZ(item->pos.rotY, item->pos.rotX, item->pos.rotZ); + phd_TranslateRel(frame[6], frame[7], frame[8]); + rotation = (UINT16*)frame + 9; + phd_RotYXZsuperpack(&rotation, 0); + + for (int i = 0; i < joint; i++, bones += 4) { + flags = bones[0]; + if (flags & 1) { + phd_PopMatrix(); + } + if (flags & 2) { + phd_PushMatrix(); + } + + phd_TranslateRel(bones[1], bones[2], bones[3]); + phd_RotYXZsuperpack(&rotation, 0); + + if (flags & 0x1C) { + if (flags & 8) { + phd_RotY(*(rot++)); + } + if (flags & 4) { + phd_RotX(*(rot++)); + } + if (flags & 0x10) { + phd_RotZ(*(rot++)); + } + } + } + + phd_TranslateRel(pos->x, pos->y, pos->z); + pos->x = (PhdMatrixPtr->_03 >> W2V_SHIFT) + item->pos.x; + pos->y = (PhdMatrixPtr->_13 >> W2V_SHIFT) + item->pos.y; + pos->z = (PhdMatrixPtr->_23 >> W2V_SHIFT) + item->pos.z; + phd_PopMatrix(); +} + +void __cdecl BaddieBiteEffect(ITEM_INFO *item, BITE_INFO *bite) { + PHD_VECTOR pos; + pos.x = bite->x; + pos.y = bite->y; + pos.z = bite->z; + GetJointAbsPosition(item, &pos, bite->meshIndex); + DoBloodSplat(pos.x, pos.y, pos.z, item->speed, item->pos.rotY, item->roomNumber); +} /* * Inject function @@ -31,6 +94,6 @@ void Inject_Sphere() { // INJECT(0x0043FA60, TestCollision); // INJECT(0x0043FB90, GetSpheres); -// INJECT(0x0043FE70, GetJointAbsPosition); -// INJECT(0x00440010, BaddieBiteEffect); + INJECT(0x0043FE70, GetJointAbsPosition); + INJECT(0x00440010, BaddieBiteEffect); } diff --git a/game/sphere.h b/game/sphere.h index fc8431a..9ff7a46 100644 --- a/game/sphere.h +++ b/game/sphere.h @@ -27,10 +27,9 @@ /* * Function list */ -// 0x0043FA60: TestCollision +#define TestCollision ((BOOL(__cdecl*)(ITEM_INFO*, ITEM_INFO*)) 0x0043FA60) // 0x0043FB90: GetSpheres - -#define GetJointAbsPosition ((void(__cdecl*)(ITEM_INFO*, PHD_VECTOR*, int)) 0x0043FE70) -#define BaddieBiteEffect ((void(__cdecl*)(ITEM_INFO*,BITE_INFO*)) 0x00440010) +void __cdecl GetJointAbsPosition(ITEM_INFO *item, PHD_VECTOR *pos, int joint); // 0x0043FE70 +void __cdecl BaddieBiteEffect(ITEM_INFO *item, BITE_INFO *bite); // 0x00440010 #endif // SPHERE_H_INCLUDED diff --git a/game/traps.h b/game/traps.h index ce29eba..5308ed9 100644 --- a/game/traps.h +++ b/game/traps.h @@ -32,32 +32,26 @@ void __cdecl MineControl(__int16 mineID); // 0x00440FC0 void __cdecl ControlSpikeWall(__int16 itemID); // 0x004411C0 void __cdecl ControlCeilingSpikes(__int16 itemID); // 0x00441300 void __cdecl HookControl(__int16 itemID); // 0x00441420 - -// 0x004414B0: PropellerControl - +#define PropellerControl ((void(__cdecl*)(__int16)) 0x004414B0) void __cdecl SpinningBlade(__int16 itemID); // 0x00441640 void __cdecl IcicleControl(__int16 itemID); // 0x004417C0 void __cdecl InitialiseBlade(__int16 itemID); // 0x004418C0 void __cdecl BladeControl(__int16 itemID); // 0x00441900 void __cdecl InitialiseKillerStatue(__int16 itemID); // 0x004419A0 void __cdecl KillerStatueControl(__int16 itemID); // 0x004419F0 - -// 0x00441B00: SpringBoardControl -// 0x00441BE0: InitialiseRollingBall -// 0x00441C20: RollingBallControl -// 0x00441F70: RollingBallCollision -// 0x004421C0: SpikeCollision -// 0x00442320: TrapDoorControl -// 0x00442370: TrapDoorFloor -// 0x004423B0: TrapDoorCeiling -// 0x004423F0: OnTrapDoor - +#define SpringBoardControl ((void(__cdecl*)(__int16)) 0x00441B00) +#define InitialiseRollingBall ((void(__cdecl*)(__int16)) 0x00441BE0) +#define RollingBallControl ((void(__cdecl*)(__int16)) 0x00441C20) +#define RollingBallCollision ((void(__cdecl*)(__int16,ITEM_INFO*,COLL_INFO*)) 0x00441F70) +#define SpikeCollision ((void(__cdecl*)(__int16,ITEM_INFO*,COLL_INFO*)) 0x004421C0) +#define TrapDoorControl ((void(__cdecl*)(__int16)) 0x00442320) +#define TrapDoorFloor ((void(__cdecl*)(ITEM_INFO*,int,int,int,__int16*)) 0x00442370) +#define TrapDoorCeiling ((void(__cdecl*)(ITEM_INFO*,int,int,int,__int16*)) 0x004423B0) +#define OnTrapDoor ((int(__cdecl*)(ITEM_INFO*,int,int)) 0x004423F0) void __cdecl Pendulum(__int16 itemID); // 0x004424A0 - -// 0x004425B0: FallingBlock -// 0x004426C0: FallingBlockFloor -// 0x00442700: FallingBlockCeiling - +#define FallingBlock ((void(__cdecl*)(__int16)) 0x004425B0) +#define FallingBlockFloor ((void(__cdecl*)(ITEM_INFO*,int,int,int,__int16*)) 0x004426C0) +#define FallingBlockCeiling ((void(__cdecl*)(ITEM_INFO*,int,int,int,__int16*)) 0x00442700) void __cdecl TeethTrap(__int16 itemID); // 0x00442750 void __cdecl FallingCeiling(__int16 itemID); // 0x00442810 void __cdecl DartEmitterControl(__int16 itemID); // 0x004428F0 @@ -67,8 +61,7 @@ void __cdecl FlameEmitterControl(__int16 item_id); // 0x00442BE0 void __cdecl FlameControl(__int16 fx_id); // 0x00442C70 void __cdecl LaraBurn(); // 0x00442DE0 void __cdecl LavaBurn(ITEM_INFO *item); // 0x00442E30 - -// 0x00442F20: LavaSpray -// 0x00442FF0: ControlLavaBlob +#define LavaSpray ((void(__cdecl*)(__int16)) 0x00442F20) +#define ControlLavaBlob ((void(__cdecl*)(__int16)) 0x00442FF0) #endif // TRAPS_H_INCLUDED diff --git a/global/types.h b/global/types.h index 47f91ee..193e27e 100644 --- a/global/types.h +++ b/global/types.h @@ -1783,7 +1783,12 @@ typedef struct CollInfo_t { char zTilt; char hitByBaddie; char hitStatic; - UINT16 flags; + UINT16 slopesAreWalls : 2; + UINT16 slopesArePits : 1; + UINT16 lavaIsPit : 1; + UINT16 enableBaddiePush : 1; + UINT16 enableSpaz : 1; + UINT16 hitCeiling : 1; } COLL_INFO; typedef struct ObjectInfo_t { @@ -1835,9 +1840,9 @@ typedef struct DoorInfos_t { typedef struct FloorInfo_t { __int16 index; __int16 box; - char pitRoom; + BYTE pitRoom; char floor; - char skyRoom; + BYTE skyRoom; char ceiling; } FLOOR_INFO; @@ -1861,6 +1866,19 @@ typedef struct MeshInfo_t { __int16 staticNumber; } MESH_INFO; +typedef struct DoorPosData_t { + FLOOR_INFO* floor; + FLOOR_INFO data; + __int16 box; +} DOORPOS_DATA; + +typedef struct DoorData_t { + DOORPOS_DATA d1; + DOORPOS_DATA d1flip; + DOORPOS_DATA d2; + DOORPOS_DATA d2flip; +} DOOR_DATA; + typedef struct RoomInfo_t { __int16 *data; DOOR_INFOS *doors; diff --git a/global/vars.h b/global/vars.h index e575962..507542f 100644 --- a/global/vars.h +++ b/global/vars.h @@ -57,7 +57,11 @@ #define ins_objectG4 (*(__int16*(__cdecl **)(__int16*,int,SORTTYPE)) 0x004BCAF8) #define ins_objectG3 (*(__int16*(__cdecl **)(__int16*,int,SORTTYPE)) 0x004BCB40) -#define SfxFunctions (*(void(__cdecl *(*)[32])(ITEM_INFO*)) 0x004641F8) +#define SfxFunctions (*(void(__cdecl *(*)[32])(ITEM_INFO*)) 0x004641F8) +#define EffectFunctions (*(void(__cdecl *(*)[32])(ITEM_INFO*)) 0x004641F8) +#define ExtraFunctions (*(void(__cdecl *(*)[11])(ITEM_INFO*,COLL_INFO*)) 0x00465DF0) +#define LaraControlFunctions (*(void(__cdecl *(*)[71])(ITEM_INFO*,COLL_INFO*)) 0x00465CD0) +#define LaraCollisionFunctions (*(void(__cdecl *(*)[71])(ITEM_INFO*,COLL_INFO*)) 0x00465E20) // Initialized variables #define PerspectiveDistance VAR_I_(0x00464060, DWORD, 0x3000000) @@ -394,7 +398,7 @@ extern APP_SETTINGS SavedAppSettings; #define AnimChanges VAR_U_(0x0052617C, CHANGE_STRUCT*) #define RoomCount VAR_U_(0x00526180, __int16) #define RoomInfo VAR_U_(0x0052618C, ROOM_INFO*) -#define UnderwaterCamera VAR_U_(0x00526190, int) +#define UnderwaterCamera VAR_U_(0x00526190, BOOL) #define SunsetTimer VAR_U_(0x00526194, DWORD) #define OutsideRight VAR_U_(0x00526198, int) #define OutsideTop VAR_U_(0x005261AC, int) @@ -406,12 +410,21 @@ extern APP_SETTINGS SavedAppSettings; #define IsCinematicLoaded VAR_U_(0x005262F4, __int16) #define CineFramesCount VAR_U_(0x005262F6, __int16) #define CineFrames VAR_U_(0x005262F8, CINE_FRAME_INFO*) +#define CinematicPos VAR_U_(0x00526300, PHD_3DPOS) #define CineLevelID VAR_U_(0x00526312, __int16) #define CineFrameIdx VAR_U_(0x00526314, __int16) #define Camera VAR_U_(0x00526320, CAMERA_INFO) #define Overlaps VAR_U_(0x005263C8, UINT16*) #define Boxes VAR_U_(0x005263CC, BOX_INFO*) #define BoxesCount VAR_U_(0x005263D0, DWORD) +#define IMRate VAR_U_(0x00526184, int) +#define IMFrac VAR_U_(0x005258F0, int) +#define IMPtr VAR_U_(0x00526188, PHD_MATRIX*) +#define IMStack ARRAY_(0x005252C0, PHD_MATRIX, [32]) +#define InterpolateBounds ARRAY_(0x005261A0, __int16, [6]) +#define ActiveCreatures VAR_U_(0x005206C0, CREATURE_INFO*) +#define ActiveCreaturesUsed VAR_U_(0x004D7C40, int) +#define MonksAttackLara VAR_U_(0x004D77D8, BOOL) // Initialized arrays #define TrackIDs ARRAY_(0x004642F0, __int16, [16]) /* = {2, 0}; */ diff --git a/modding/mod_utils.cpp b/modding/mod_utils.cpp index a90370e..ef57a30 100644 --- a/modding/mod_utils.cpp +++ b/modding/mod_utils.cpp @@ -44,6 +44,7 @@ typedef struct { typedef struct { bool isLoaded; bool isBarefoot; + bool isBridgeLightFix; char loadingPix[256]; DWORD waterColor; SEMITRANS_CONFIG semitrans; @@ -168,6 +169,10 @@ bool IsModBarefoot() { return ModConfig.isBarefoot; } +bool IsModBridgeLightFix() { + return ModConfig.isBridgeLightFix; +} + const char *GetModLoadingPix() { return *ModConfig.loadingPix ? ModConfig.loadingPix : NULL; } @@ -414,6 +419,10 @@ static bool ParseLevelConfiguration(json_value *root) { if( field ) { ModConfig.isBarefoot = field->u.boolean; } + field = GetJsonField(root, json_boolean, "bridgelightfix", NULL); + if( field ) { + ModConfig.isBridgeLightFix = field->u.boolean; + } ParseSemitransConfiguration(GetJsonField(root, json_object, "semitransparent", NULL)); ParseReflectConfiguration(GetJsonField(root, json_object, "reflective", NULL)); return true; diff --git a/modding/mod_utils.h b/modding/mod_utils.h index 920f37d..4ed717b 100644 --- a/modding/mod_utils.h +++ b/modding/mod_utils.h @@ -56,6 +56,7 @@ bool EnumeratePolys(__int16 *ptrObj, bool isRoomMesh, ENUM_POLYS_CB callback, PO #ifdef FEATURE_MOD_CONFIG bool IsModConfigLoaded(); bool IsModBarefoot(); +bool IsModBridgeLightFix(); const char *GetModLoadingPix(); DWORD GetModWaterColor(); bool IsModSemitransConfigLoaded(); diff --git a/modding/xinput_ex.cpp b/modding/xinput_ex.cpp index 0949e6e..8a51016 100644 --- a/modding/xinput_ex.cpp +++ b/modding/xinput_ex.cpp @@ -27,7 +27,7 @@ // Imports from xinput*.dll static HMODULE hXInput = NULL; -static void (WINAPI *_XInputEnable)(WINBOOL) = NULL; +static void (WINAPI *_XInputEnable)(BOOL) = NULL; static DWORD (WINAPI *_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*) = NULL; static DWORD (WINAPI *_XInputSetState)(DWORD, XINPUT_VIBRATION*) = NULL; static DWORD (WINAPI *_XInputGetState)(DWORD, XINPUT_STATE*) = NULL; diff --git a/specific/game.cpp b/specific/game.cpp index 1581c12..b751a41 100644 --- a/specific/game.cpp +++ b/specific/game.cpp @@ -402,7 +402,7 @@ void __cdecl DisplayCredits() { S_UnloadLevelFile(); TempVideoAdjust(HiRes, 1.0); // NOTE: this line was not in the original code - if( !InitialiseLevel(0, 0) ) // init title level + if( !InitialiseLevel(0, GFL_TITLE) ) // init title level return; memcpy(palette, GamePalette8, sizeof(GamePalette8)); diff --git a/specific/init_input.cpp b/specific/init_input.cpp index a9d5f2e..e0d0e04 100644 --- a/specific/init_input.cpp +++ b/specific/init_input.cpp @@ -164,7 +164,7 @@ bool IsJoyVibrationSupported() { return true; } if( XInputIndex >= 0 ) { - return( XInputCaps.Vibration.wLeftMotorSpeed || XInputCaps.Vibration.wLeftMotorSpeed ); + return( XInputCaps.Vibration.wLeftMotorSpeed || XInputCaps.Vibration.wRightMotorSpeed ); } return false; } @@ -459,7 +459,11 @@ bool __cdecl DInputEnumDevices(JOYSTICK_LIST *joystickList) { } RawInputEnumerate(RawInputCallBack, (LPVOID)joystickList); #endif // FEATURE_INPUT_IMPROVED +#if DIRECTINPUT_VERSION >= 0x800 + return SUCCEEDED(DInput->EnumDevices(DI8DEVTYPE_JOYSTICK, DInputEnumDevicesCallback, (LPVOID)joystickList, DIEDFL_ATTACHEDONLY)); +#else return SUCCEEDED(DInput->EnumDevices(DIDEVTYPE_JOYSTICK, DInputEnumDevicesCallback, (LPVOID)joystickList, DIEDFL_ATTACHEDONLY)); +#endif } BOOL CALLBACK DInputEnumDevicesCallback(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) { diff --git a/specific/smain.cpp b/specific/smain.cpp index aa4cb85..7b36fa1 100644 --- a/specific/smain.cpp +++ b/specific/smain.cpp @@ -288,7 +288,7 @@ __int16 __cdecl TitleSequence() { NoInputCounter = 0; if( !IsTitleLoaded ) { - if( !InitialiseLevel(0, 0) ) + if( !InitialiseLevel(0, GFL_TITLE) ) return GF_EXIT_GAME; IsTitleLoaded = TRUE; }