diff --git a/TR5Main/Game/Lara/lara.cpp b/TR5Main/Game/Lara/lara.cpp index d9691cdf9..a2999c9da 100644 --- a/TR5Main/Game/Lara/lara.cpp +++ b/TR5Main/Game/Lara/lara.cpp @@ -1,5 +1,5 @@ #include "framework.h" -#include "Lara.h" +#include "lara.h" #include "lara_basic.h" #include "lara_tests.h" #include "lara_monkey.h" @@ -49,52 +49,58 @@ ITEM_INFO* LaraItem; COLL_INFO lara_coll; byte LaraNodeUnderwater[NUM_LARA_MESHES]; +// For later. +bool EnableActionToggle; +bool EnableJumpUpAlign; +bool EnableClimbAssist; +bool EnableSafetyDrop; + function lara_control_routines[NUM_LARA_STATES + 1] = { - lara_as_walk, - lara_as_run, - lara_as_stop, - lara_as_forwardjump, + lara_as_walk_forward,//0 + lara_as_run,//1 + lara_as_stop,//2 + lara_as_jump_forward,//3 lara_void_func,//4 - lara_as_fastback,//5 - lara_as_turn_r,//6 - lara_as_turn_l,//7 + lara_as_hop_back,//5 + lara_as_turn_right,//6 + lara_as_turn_left,//7 lara_as_death,//8 - lara_as_fastfall, - lara_as_hang, - lara_as_reach, - lara_as_splat, - lara_as_tread, - lara_void_func, - lara_as_compress,//15 - lara_as_back,//16 - lara_as_swim,//17 + lara_as_freefall,//9 + lara_as_hang,//10 + lara_as_reach,//11 + lara_as_splat,//12 + lara_as_underwater_stop,//13 + lara_void_func,//14 + lara_as_jump_prepare,//15 + lara_as_walk_back,//16 + lara_as_underwater_swim,//17 lara_as_glide,//18 lara_as_null,//19 - lara_as_fastturn,//20 - lara_as_stepright,//21 - lara_as_stepleft,//22 - lara_void_func, + lara_as_turn_right_fast,//20 + lara_as_step_right,//21 + lara_as_step_left,//22 + lara_void_func,//23 lara_as_slide,//24 - lara_as_backjump,//25 - lara_as_rightjump,//26 - lara_as_leftjump,//27 - lara_as_upjump,//28 - lara_as_fallback,//29 - lara_as_hangleft,//30 - lara_as_hangright,//31 - lara_as_slideback,//32 - lara_as_surftread, - lara_as_surfswim, - lara_as_dive, - lara_as_pushblock,//36 - lara_as_pullblock,//37 - lara_as_ppready,//38 + lara_as_jump_back,//25 + lara_as_jump_right,//26 + lara_as_jump_left,//27 + lara_as_jump_up,//28 + lara_as_fall_back,//29 + lara_as_shimmy_left,//30 + lara_as_shimmy_right,//31 + lara_as_slide_back,//32 + lara_as_surftread,//33 + lara_as_surfswim,//34 + lara_as_dive,//35 + lara_as_pushable_push,//36 + lara_as_pushable_pull,//37 + lara_as_pushable_ready,//38 lara_as_pickup,//39 - lara_as_switchon,//40 - lara_as_switchoff,//41 - lara_as_usekey,//42 - lara_as_usepuzzle,//43 - lara_as_uwdeath,//44 + lara_as_switch,//40 + lara_as_switch,//41 // + lara_as_use_key,//42 + lara_as_use_puzzle,//43 + lara_as_underwater_death,//44 lara_void_func,//45 lara_as_special,//46 lara_as_surfback,//47 @@ -102,8 +108,8 @@ function lara_control_routines[NUM_LARA_STATES + 1] = { lara_as_surfright,//49 lara_void_func,//50 lara_void_func,//51 - lara_as_swandive,//52 - lara_as_fastdive,//53 + lara_as_swandive_start,//52 + lara_as_swandive_freefall,//53 lara_as_gymnast,//54 lara_as_waterout, lara_as_climbstnc, @@ -111,37 +117,37 @@ function lara_control_routines[NUM_LARA_STATES + 1] = { lara_as_climbleft, lara_as_climbend, lara_as_climbright, - lara_as_climbdown,// + lara_as_climbdown, // lara_void_func, lara_void_func, lara_void_func, lara_as_wade,//65 - lara_as_waterroll,//66 - lara_as_pickupflare,//67 + lara_as_underwater_roll_180,//66 + lara_as_pickup_flare,//67 lara_void_func,//68 lara_void_func,//69 - lara_as_deathslide,//70 - lara_as_duck,//71 + lara_as_zipline,//70 + lara_as_crouch,//71 lara_as_crouch_roll,//72 - lara_as_dash, - lara_as_dashdive, + lara_as_sprint, + lara_as_sprint_roll, lara_as_hang2, lara_as_monkeyswing, lara_as_monkeyl, lara_as_monkeyr, lara_as_monkey180, - lara_as_all4s,//80 - lara_as_crawl,//81 - lara_as_hangturnl, - lara_as_hangturnr, - lara_as_all4turnl,//84 - lara_as_all4turnr,//85 - lara_as_crawlb,//86 + lara_as_crawl_stop,//80 + lara_as_crawl_forward,//81 + lara_as_hangturnl,//82 + lara_as_hangturnr,//83 + lara_as_crawl_turn_left,//84 + lara_as_crawl_turn_right,//85 + lara_as_crawl_back,//86 lara_as_null, lara_as_null, lara_as_controlled, - lara_as_ropel, - lara_as_roper, + lara_as_rope_turn_clockwise, + lara_as_rope_turn_counter_clockwise, lara_as_controlled, lara_as_controlled, lara_as_controlled, @@ -152,34 +158,34 @@ function lara_control_routines[NUM_LARA_STATES + 1] = { lara_as_null,//99 lara_as_null,//100 lara_as_null,//101 - lara_as_poleleft,//102 - lara_as_poleright,//103 + lara_as_pole_turn_clockwise,//102 + lara_as_pole_turn_counter_clockwise,//103 lara_as_pulley,//104 - lara_as_duckl,//105 - lara_as_duckr,//106 + lara_as_crouch_turn_left,//105 + lara_as_crouch_turn_right,//106 lara_as_extcornerl,//107 lara_as_extcornerr,//108 lara_as_intcornerl,//109 lara_as_intcornerr,//110 lara_as_rope,//111 - lara_as_climbrope,//112 - lara_as_climbroped,//113 + lara_as_rope_up,//112 + lara_as_rope_down,//113 lara_as_rope,//114 lara_as_rope,//115 - lara_void_func, - lara_as_controlled, - lara_as_swimcheat, - lara_as_trpose,//119 + lara_void_func,//116 + lara_as_controlled,//117 + lara_as_swim_cheat,//118 + lara_as_tightrope_stop,//119 lara_as_null,//120 - lara_as_trwalk,//121 - lara_as_trfall,//122 - lara_as_trfall,//123 + lara_as_tightrope_walk,//121 + lara_as_tightrope_fall,//122 + lara_as_tightrope_fall,//123 lara_as_null,//124 lara_as_null,//125 - lara_as_switchon,//126 + lara_as_switch,//126 lara_as_null,//127 - lara_as_parallelbars,//128 - lara_as_pbleapoff,//129 + lara_as_swing_bar,//128 + lara_as_swing_bar_leap,//129 lara_as_null,//130 lara_as_null,//131 lara_as_null,//132 @@ -190,53 +196,60 @@ function lara_control_routines[NUM_LARA_STATES + 1] = { lara_as_null,//137 lara_as_null,//138 lara_as_hang_feet,//139 - lara_as_hang_feet_shimmyr,//140 - lara_as_hang_feet_shimmyl,//141 - lara_as_hang_feet_inRcorner,//142 - lara_as_hang_feet_inLcorner,//143 - lara_as_hang_feet_outRcorner,//144 - lara_as_hang_feet_outLcorner,//145 + lara_as_shimmy_feet_right,//140 + lara_as_shimmy_feet_left,//141 + lara_as_hang_feet_right_corner_inner,//142 + lara_as_hang_feet_left_corner_inner,//143 + lara_as_hang_feet_right_corner_outer,//144 + lara_as_hang_feet_left_corner_outer,//145 lara_as_controlledl, lara_as_null, lara_as_null, lara_as_null, - lara_as_stepoff_left, - lara_as_stepoff_right + lara_as_stepoff_left,//150 + lara_as_stepoff_right, + lara_as_steep_slide, + lara_as_steep_slide_back, + lara_as_slide_turn_180, + lara_as_jump_forward, + lara_as_turn_left_fast,//156 + lara_as_null,//157 }; + function lara_collision_routines[NUM_LARA_STATES + 1] = { - lara_col_walk, + lara_col_walk_forward, lara_col_run, lara_col_stop, - lara_col_forwardjump, + lara_col_jump_forward, lara_col_pose, - lara_col_fastback, - lara_col_turn_r, - lara_col_turn_l, + lara_col_hop_back, + lara_col_turn_right, + lara_col_turn_left, lara_col_death, - lara_col_fastfall, + lara_col_freefall, lara_col_hang, lara_col_reach, lara_col_splat, - lara_col_tread, - lara_col_land, - lara_col_compress, - lara_col_back, - lara_col_swim, + lara_col_underwater_stop, + lara_col_stop, + lara_col_jump_prepare, + lara_col_walk_back, + lara_col_underwater_swim, lara_col_glide, lara_default_col, - lara_col_fastturn, - lara_col_stepright, - lara_col_stepleft, + lara_col_turn_right_fast,//20 + lara_col_step_right, + lara_col_step_left, lara_col_roll2, lara_col_slide, - lara_col_backjump, - lara_col_rightjump, - lara_col_leftjump, - lara_col_upjump, - lara_col_fallback, - lara_col_hangleft, - lara_col_hangright, - lara_col_slideback, + lara_col_jump_back, + lara_col_jump_right, + lara_col_jump_left, + lara_col_jump_up, + lara_col_fall_back, + lara_col_shimmy_left, + lara_col_shimmy_right, + lara_col_slide_back, lara_col_surftread, lara_col_surfswim, lara_col_dive, @@ -248,7 +261,7 @@ function lara_collision_routines[NUM_LARA_STATES + 1] = { lara_default_col, lara_default_col, lara_default_col, - lara_col_uwdeath, + lara_col_underwater_death, lara_col_roll, lara_void_func, lara_col_surfback, @@ -256,8 +269,8 @@ function lara_collision_routines[NUM_LARA_STATES + 1] = { lara_col_surfright, lara_void_func, lara_void_func, - lara_col_swandive, - lara_col_fastdive, + lara_col_swandive_start, + lara_col_swandive_freefall, lara_default_col, lara_default_col, lara_col_climbstnc, @@ -270,29 +283,29 @@ function lara_collision_routines[NUM_LARA_STATES + 1] = { lara_void_func, lara_void_func, lara_col_wade, - lara_col_waterroll, + lara_col_underwater_roll_180, lara_default_col, lara_void_func, lara_void_func, lara_void_func, - lara_col_duck, + lara_col_crouch, lara_col_crouch_roll, - lara_col_dash, - lara_col_dashdive, + lara_col_sprint, + lara_col_sprint_roll, lara_col_hang2, lara_col_monkeyswing, lara_col_monkeyl, lara_col_monkeyr, lara_col_monkey180, - lara_col_all4s, - lara_col_crawl, + lara_col_crawl_stop, + lara_col_crawl_forward, lara_col_hangturnlr, lara_col_hangturnlr, - lara_col_all4turnlr, - lara_col_all4turnlr, - lara_col_crawlb, + lara_col_crawl_turn, + lara_col_crawl_turn, + lara_col_crawl_back, lara_void_func, - lara_col_crawl2hang, + lara_col_crawl_to_hang, lara_default_col, lara_void_func, lara_void_func, @@ -303,14 +316,14 @@ function lara_collision_routines[NUM_LARA_STATES + 1] = { lara_void_func, lara_void_func, lara_default_col, - lara_col_polestat, - lara_col_poleup, - lara_col_poledown, + lara_col_pole_stop, + lara_col_pole_up, + lara_col_pole_down, lara_void_func, lara_void_func, lara_default_col, - lara_col_ducklr, - lara_col_ducklr, + lara_col_crouch_turn, + lara_col_crouch_turn, lara_default_col, lara_default_col, lara_default_col, @@ -318,11 +331,11 @@ function lara_collision_routines[NUM_LARA_STATES + 1] = { lara_col_rope, lara_void_func, lara_void_func, - lara_col_ropefwd, - lara_col_ropefwd, + lara_col_rope_swing, + lara_col_rope_swing, lara_void_func, lara_void_func, - lara_col_swim, + lara_col_underwater_swim, lara_default_col, lara_default_col, lara_default_col, @@ -344,8 +357,8 @@ function lara_collision_routines[NUM_LARA_STATES + 1] = { lara_void_func, lara_void_func, lara_col_hang_feet, - lara_col_hang_feet_shimmyr, - lara_col_hang_feet_shimmyl, + lara_col_shimmy_feet_right, + lara_col_shimmy_feet_right, lara_default_col, lara_default_col, lara_default_col, @@ -354,8 +367,14 @@ function lara_collision_routines[NUM_LARA_STATES + 1] = { lara_void_func, lara_void_func, lara_void_func, + lara_default_col,//150 + lara_default_col,//151 lara_default_col, - lara_default_col + lara_default_col, + lara_default_col, + lara_default_col, + lara_col_turn_left_fast,//156 + lara_default_col,//157 }; void LaraControl(short itemNumber) // (AF) (D) @@ -375,7 +394,9 @@ void LaraControl(short itemNumber) // (AF) (D) } if (!DisableLaraControl) + { Lara.locationPad = 128; + } int oldX = LaraItem->pos.xPos; int oldY = LaraItem->pos.yPos; @@ -391,7 +412,9 @@ void LaraControl(short itemNumber) // (AF) (D) } if (item->currentAnimState != LS_SPRINT && DashTimer < 120) + { DashTimer++; + } Lara.isDucked = false; @@ -402,13 +425,19 @@ void LaraControl(short itemNumber) // (AF) (D) int hfw; if (wh != NO_HEIGHT) + { hfw = item->pos.yPos - wh; + } else + { hfw = NO_HEIGHT; + } Lara.waterSurfaceDist = -hfw; if (Lara.Vehicle == NO_ITEM) + { WadeSplash(item, wh, wd); + } short roomNumber; @@ -430,8 +459,8 @@ void LaraControl(short itemNumber) // (AF) (D) } else if (isWater & ENV_FLAG_SWAMP) { - if (item->currentAnimState == LS_SWANDIVE_START - || item->currentAnimState == LS_SWANDIVE_END) // Is Lara swan-diving? + if (item->currentAnimState == LS_SWANDIVE_START || + item->currentAnimState == LS_SWANDIVE_END) // Is Lara swan-diving? item->pos.yPos = wh + 1000; item->goalAnimState = LS_WADE_FORWARD; @@ -453,21 +482,21 @@ void LaraControl(short itemNumber) // (AF) (D) if (item->currentAnimState == LS_SWANDIVE_START) { - item->pos.xRot = -ANGLE(45); + item->pos.xRot = ANGLE(-45.0f); item->goalAnimState = LS_DIVE; AnimateLara(item); item->fallspeed *= 2; } else if (item->currentAnimState == LS_SWANDIVE_END) { - item->pos.xRot = -ANGLE(85); + item->pos.xRot = ANGLE(-85.0f); item->goalAnimState = LS_DIVE; AnimateLara(item); item->fallspeed *= 2; } else { - item->pos.xRot = -ANGLE(45); + item->pos.xRot = ANGLE(-45.0f); item->animNumber = LA_FREEFALL_DIVE; item->frameNumber = g_Level.Anims[item->animNumber].frameBase; item->currentAnimState = LS_DIVE; @@ -483,7 +512,7 @@ void LaraControl(short itemNumber) // (AF) (D) Splash(LaraItem); } - Camera.targetElevation = -ANGLE(22); + Camera.targetElevation = ANGLE(-22.0f); if (hfw >= 256) /* @ORIGINAL_BUG: checking hfw for equality with 256 results in the wade bug */ { if (hfw > 730) @@ -540,7 +569,9 @@ void LaraControl(short itemNumber) // (AF) (D) LaraItem->roomNumber; Lara.waterStatus = LW_ABOVE_WATER; if (item->currentAnimState == LS_WADE_FORWARD) + { item->goalAnimState = LS_RUN_FORWARD; + } } } @@ -711,7 +742,9 @@ void LaraControl(short itemNumber) // (AF) (D) { Lara.waterStatus = LW_ABOVE_WATER; if (item->currentAnimState == LS_WADE_FORWARD) + { item->goalAnimState = LS_RUN_FORWARD; + } } break; } @@ -722,7 +755,9 @@ void LaraControl(short itemNumber) // (AF) (D) item->hitPoints = -1; if (Lara.deathCount == 0) + { S_CDStop(); + } Lara.deathCount++; if ((LaraItem->flags & 0x100)) @@ -736,7 +771,7 @@ void LaraControl(short itemNumber) // (AF) (D) { case LW_ABOVE_WATER: case LW_WADE: - if ((g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) + if ((g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) && Lara.waterSurfaceDist < -775) { if (item->hitPoints >= 0) @@ -764,7 +799,9 @@ void LaraControl(short itemNumber) // (AF) (D) { Lara.air += 10; if (Lara.air > 1800) + { Lara.air = 1800; + } } } LaraAboveWater(item, &lara_coll); @@ -784,7 +821,9 @@ void LaraControl(short itemNumber) // (AF) (D) if (Lara.air < 0) { if (LaraDrawType == LARA_DIVESUIT && Lara.anxiety < 251) + { Lara.anxiety += 4; + } Lara.air = -1; item->hitPoints -= 5; } @@ -797,7 +836,9 @@ void LaraControl(short itemNumber) // (AF) (D) { Lara.air += 10; if (Lara.air > 1800) + { Lara.air = 1800; + } } LaraSurface(item, &lara_coll); break; @@ -830,9 +871,13 @@ void LaraAboveWater(ITEM_INFO* item, COLL_INFO* coll) //hmmmm coll->trigger = NULL; if ((TrInput & IN_LOOK) && Lara.ExtraAnim == NO_ITEM && Lara.look) + { LookLeftRight(); + } else + { ResetLook(); + } Lara.look = true; @@ -891,23 +936,36 @@ void LaraAboveWater(ITEM_INFO* item, COLL_INFO* coll) //hmmmm // Handle current Lara status lara_control_routines[item->currentAnimState](item, coll); - if (item->pos.zRot >= -ANGLE(1.0f) && item->pos.zRot <= ANGLE(1.0f)) + if (item->pos.zRot >= ANGLE(-1.0f) && item->pos.zRot <= ANGLE(1.0f)) + { item->pos.zRot = 0; - else if (item->pos.zRot < -ANGLE(1.0f)) + } + else if (item->pos.zRot < ANGLE(-1.0f)) + { item->pos.zRot += ANGLE(1.0f); + } else + { item->pos.zRot -= ANGLE(1.0f); + } - if (Lara.turnRate >= -ANGLE(2.0f) && Lara.turnRate <= ANGLE(2.0f)) + if (Lara.turnRate >= ANGLE(-2.0f) && Lara.turnRate <= ANGLE(2.0f)) + { Lara.turnRate = 0; - else if (Lara.turnRate < -ANGLE(2.0f)) + } + else if (Lara.turnRate < ANGLE(-2.0f)) + { Lara.turnRate += ANGLE(2.0f); + } else + { Lara.turnRate -= ANGLE(2.0f); + } item->pos.yRot += Lara.turnRate; + // OLD // Animate Lara - AnimateLara(item); + //AnimateLara(item); if (Lara.ExtraAnim == -1) { @@ -916,9 +974,14 @@ void LaraAboveWater(ITEM_INFO* item, COLL_INFO* coll) //hmmmm // Handle Lara collision if (Lara.Vehicle == NO_ITEM) + { lara_collision_routines[item->currentAnimState](item, coll); + } } + // Animate Lara after collision. + AnimateLara(item); + UpdateLaraRoom(item, -LARA_HITE / 2); //if (Lara.gunType == WEAPON_CROSSBOW && !LaserSight) @@ -952,9 +1015,13 @@ void LaraUnderWater(ITEM_INFO* item, COLL_INFO* coll)//4BFB4, 4C418 (F) coll->trigger = NULL; if (TrInput & IN_LOOK && Lara.look) + { LookLeftRight(); + } else + { ResetLook(); + } Lara.look = true; @@ -962,7 +1029,7 @@ void LaraUnderWater(ITEM_INFO* item, COLL_INFO* coll)//4BFB4, 4C418 (F) if (LaraDrawType == LARA_DIVESUIT) { - if (Lara.turnRate < -ANGLE(0.5)) + if (Lara.turnRate < ANGLE(-0.5)) { Lara.turnRate += ANGLE(0.5); } @@ -975,13 +1042,13 @@ void LaraUnderWater(ITEM_INFO* item, COLL_INFO* coll)//4BFB4, 4C418 (F) Lara.turnRate = 0; } } - else if (Lara.turnRate < -ANGLE(2)) + else if (Lara.turnRate < ANGLE(-2.0f)) { - Lara.turnRate += ANGLE(2); + Lara.turnRate += ANGLE(2.0f); } - else if (Lara.turnRate > ANGLE(2)) + else if (Lara.turnRate > ANGLE(2.0f)) { - Lara.turnRate -= ANGLE(2); + Lara.turnRate -= ANGLE(2.0f); } else { @@ -991,37 +1058,59 @@ void LaraUnderWater(ITEM_INFO* item, COLL_INFO* coll)//4BFB4, 4C418 (F) item->pos.yRot += Lara.turnRate; if (LaraDrawType == LARA_DIVESUIT) + { UpdateSubsuitAngles(); + } - if (item->pos.zRot < -ANGLE(2)) - item->pos.zRot += ANGLE(2); - else if (item->pos.zRot > ANGLE(2)) - item->pos.zRot -= ANGLE(2); + if (item->pos.zRot < ANGLE(-2.0f)) + { + item->pos.zRot += ANGLE(2.0f); + } + else if (item->pos.zRot > ANGLE(2.0f)) + { + item->pos.zRot -= ANGLE(2.0f); + } else + { item->pos.zRot = 0; + } - if (item->pos.xRot < -ANGLE(85)) - item->pos.xRot = -ANGLE(85); - else if (item->pos.xRot > ANGLE(85)) - item->pos.xRot = ANGLE(85); + if (item->pos.xRot < ANGLE(-85.0f)) + { + item->pos.xRot = ANGLE(-85.0f); + } + else if (item->pos.xRot > ANGLE(85.0f)) + { + item->pos.xRot = ANGLE(85.0f); + } if (LaraDrawType == LARA_DIVESUIT) { - if (item->pos.zRot > ANGLE(44)) - item->pos.zRot = ANGLE(44); - else if (item->pos.zRot < -ANGLE(44)) - item->pos.zRot = -ANGLE(44); + if (item->pos.zRot > ANGLE(44.0f)) + { + item->pos.zRot = ANGLE(44.0f); + } + else if (item->pos.zRot < ANGLE(44.0f)) + { + item->pos.zRot = ANGLE(-44.0f); + } } else { - if (item->pos.zRot > ANGLE(22)) - item->pos.zRot = ANGLE(22); - else if (item->pos.zRot < -ANGLE(22)) - item->pos.zRot = -ANGLE(22); + if (item->pos.zRot > ANGLE(22.0f)) + { + item->pos.zRot = ANGLE(22.0f); + } + else if (item->pos.zRot < ANGLE(-22.0f)) + { + item->pos.zRot = ANGLE(-22.0f); + } } if (Lara.currentActive && Lara.waterStatus != LW_FLYCHEAT) + { LaraWaterCurrent(coll); + } AnimateLara(item); @@ -1032,7 +1121,9 @@ void LaraUnderWater(ITEM_INFO* item, COLL_INFO* coll)//4BFB4, 4C418 (F) LaraBaddieCollision(item, coll); if (/*Lara.ExtraAnim == -1 &&*/ Lara.Vehicle == NO_ITEM) + { lara_collision_routines[item->currentAnimState](item, coll); + } UpdateLaraRoom(item, 0); @@ -1043,7 +1134,7 @@ void LaraUnderWater(ITEM_INFO* item, COLL_INFO* coll)//4BFB4, 4C418 (F) void LaraSurface(ITEM_INFO* item, COLL_INFO* coll)//4D684, 4DAE8 (F) { - Camera.targetElevation = -ANGLE(22); + Camera.targetElevation = ANGLE(-22.0f); coll->badPos = 32512; coll->badNeg = -128; @@ -1063,23 +1154,35 @@ void LaraSurface(ITEM_INFO* item, COLL_INFO* coll)//4D684, 4DAE8 (F) coll->trigger = NULL; if (TrInput & IN_LOOK && Lara.look) + { LookLeftRight(); + } else + { ResetLook(); + } Lara.look = true; lara_control_routines[item->currentAnimState](item, coll); - if (item->pos.zRot >= -ANGLE(2) && item->pos.zRot <= ANGLE(2)) + if (item->pos.zRot >= ANGLE(-2.0f) && item->pos.zRot <= ANGLE(2.0f)) + { item->pos.zRot = 0; + } else if (item->pos.zRot < 0) - item->pos.zRot += ANGLE(2); + { + item->pos.zRot += ANGLE(2.0f); + } else - item->pos.zRot -= ANGLE(2); + { + item->pos.zRot -= ANGLE(2.0f); + } if (Lara.currentActive && Lara.waterStatus != LW_FLYCHEAT) + { LaraWaterCurrent(coll); + } AnimateLara(item); @@ -1089,7 +1192,9 @@ void LaraSurface(ITEM_INFO* item, COLL_INFO* coll)//4D684, 4DAE8 (F) LaraBaddieCollision(item, coll); if (Lara.Vehicle == NO_ITEM) + { lara_collision_routines[item->currentAnimState](item, coll); + } UpdateLaraRoom(item, 100); @@ -1232,7 +1337,6 @@ void AnimateLara(ITEM_INFO* item) default: break; - } } } @@ -1253,10 +1357,14 @@ void AnimateLara(ITEM_INFO* item) item->gravityStatus = false; } if (item->fallspeed > 128) + { item->fallspeed >>= 1; + } item->fallspeed -= item->fallspeed >> 2; if (item->fallspeed < 4) + { item->fallspeed = 4; + } item->pos.yPos += item->fallspeed; } else @@ -1276,28 +1384,34 @@ void AnimateLara(ITEM_INFO* item) { velocity = (anim->velocity >> 1); if (anim->acceleration) + { velocity += (anim->acceleration * (item->frameNumber - anim->frameBase)) >> 2; + } } else { velocity = anim->velocity; if (anim->acceleration) + { velocity += anim->acceleration * (item->frameNumber - anim->frameBase); + } } item->speed = velocity >> 16; } if (Lara.ropePtr != -1) + { DelAlignLaraToRope(item); + } if (!Lara.isMoving) // TokyoSU: i dont know why but it's wreid, in TR3 only the 2 first line there is used and worked fine ! { item->pos.xPos += item->speed * phd_sin(item->pos.yRot + Lara.moveAngle) >> W2V_SHIFT; item->pos.zPos += item->speed * phd_cos(item->pos.yRot + Lara.moveAngle) >> W2V_SHIFT; - item->pos.xPos += lateral * phd_sin(item->pos.yRot + Lara.moveAngle + ANGLE(90)) >> W2V_SHIFT; - item->pos.zPos += lateral * phd_cos(item->pos.yRot + Lara.moveAngle + ANGLE(90)) >> W2V_SHIFT; + item->pos.xPos += lateral * phd_sin(item->pos.yRot + Lara.moveAngle + ANGLE(90.0f)) >> W2V_SHIFT; + item->pos.zPos += lateral * phd_cos(item->pos.yRot + Lara.moveAngle + ANGLE(90.0f)) >> W2V_SHIFT; } // Update matrices diff --git a/TR5Main/Game/Lara/lara.h b/TR5Main/Game/Lara/lara.h index 36a033219..abc49cd52 100644 --- a/TR5Main/Game/Lara/lara.h +++ b/TR5Main/Game/Lara/lara.h @@ -20,6 +20,12 @@ extern ITEM_INFO* LaraItem; extern COLL_INFO lara_coll; extern byte LaraNodeUnderwater[NUM_LARA_MESHES]; +// For later. +extern bool EnableActionToggle; +extern bool EnableJumpUpAlign; +extern bool EnableClimbAssist; +extern bool EnableSafetyDrop; + #define LARA_MESHES(slot, mesh) Lara.meshPtrs[mesh] = MESHES(slot, mesh) #define CHECK_LARA_MESHES(slot, mesh) Lara.meshPtrs[mesh] == MESHES(slot, mesh) #define INIT_LARA_MESHES(mesh, to, from) Lara.meshPtrs[mesh] = LARA_MESHES(to, mesh) = LARA_MESHES(from, mesh) diff --git a/TR5Main/Game/Lara/lara_basic.cpp b/TR5Main/Game/Lara/lara_basic.cpp index 5a2ad03b9..f478bdaae 100644 --- a/TR5Main/Game/Lara/lara_basic.cpp +++ b/TR5Main/Game/Lara/lara_basic.cpp @@ -11,9 +11,70 @@ #include "draw.h" #include "pickup.h" -bool DoJump = false; +bool EnableBackKeyTurn = false; + +bool EnableJump = false; + +// BASIC MOVEMENT + +// ------------------------------ +// Auxiliary Functions +// ------------------------------ + +bool TestLaraStepDown(COLL_INFO* coll) +{ + if (coll->midFloor <= STEPUP_HEIGHT && + coll->midFloor > STEP_SIZE / 2) + { + return true; + } + + return false; +} + +bool TestLaraStepUp(COLL_INFO* coll) +{ + if (coll->frontFloor >= -STEPUP_HEIGHT && + coll->frontFloor < -STEP_SIZE / 2) + { + return true; + } + + return false; +} + +// TODO: Some states can't use this function yet due to missing step up/down anims. +void DoLaraStep(ITEM_INFO* item, COLL_INFO* coll) +{ + if (TestLaraStepDown(coll)) + { + item->pos.yPos += coll->midFloor; + + item->goalAnimState = LS_STEP_DOWN; + GetChange(item, &g_Level.Anims[item->animNumber]); + } + else if (TestLaraStepUp(coll)) + { + item->pos.yPos += coll->midFloor; + + item->goalAnimState = LS_STEP_UP; + GetChange(item, &g_Level.Anims[item->animNumber]); + } + else if (abs(coll->midFloor) >= 50) + { + item->pos.yPos += 50 * GetSign(coll->midFloor); + } + else + { + item->pos.yPos += coll->midFloor; + } +} + +// ------------------------------ +// GENERAL +// Control & Collision Functions +// ------------------------------ -/*generic functions*/ void lara_void_func(ITEM_INFO* item, COLL_INFO* coll)//19928(<), 19A5C(<) (F) { return; @@ -22,12 +83,14 @@ void lara_void_func(ITEM_INFO* item, COLL_INFO* coll)//19928(<), 19A5C(<) (F) void lara_default_col(ITEM_INFO* item, COLL_INFO* coll)//1C80C(<), 1C940(<) (F) { Lara.moveAngle = 0; + coll->badPos = 384; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = 0; coll->slopesArePits = true; coll->slopesAreWalls = true; coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); } @@ -35,7 +98,7 @@ void lara_as_special(ITEM_INFO* item, COLL_INFO* coll)//1ADDC(<), 1AF10(<) (F) { Camera.flags = CF_FOLLOW_CENTER; Camera.targetAngle = ANGLE(170.0f); - Camera.targetElevation = -ANGLE(25.0f); + Camera.targetElevation = ANGLE(-25.0f); } void lara_as_null(ITEM_INFO* item, COLL_INFO* coll)//1A5DC(<), 1A710(<) (F) @@ -47,161 +110,228 @@ void lara_as_null(ITEM_INFO* item, COLL_INFO* coll)//1A5DC(<), 1A710(<) (F) void lara_as_controlled(ITEM_INFO* item, COLL_INFO* coll)//1B0FC(<), 1B230(<) (F) { Lara.look = false; + coll->enableBaddiePush = false; coll->enableSpaz = false; + if (item->frameNumber == g_Level.Anims[item->animNumber].frameEnd - 1) { Lara.gunStatus = LG_NO_ARMS; + if (UseForcedFixedCamera) + { UseForcedFixedCamera = 0; + } } } void lara_as_controlledl(ITEM_INFO* item, COLL_INFO* coll)//1B180(<), 1B2B4(<) (F) { Lara.look = false; + coll->enableBaddiePush = false; coll->enableSpaz = false; } -/*end generic functions*/ -/*-*/ -/*basic movement*/ -void lara_as_walk(ITEM_INFO* item, COLL_INFO* coll)//191B8(<), 192EC(<) (F) +// ------------------------------ +// BASIC MOVEMENT +// Control & Collision Functions +// ------------------------------ + +// State: 0 +// Collision: lara_col_walk_forward() +void lara_as_walk_forward(ITEM_INFO* item, COLL_INFO* coll)//191B8(<), 192EC(<) (F) { - /*state 0*/ - /*collision: lara_col_walk*/ + // TODO: Looking while walking. + // BUG: When looking while running Lara transitions into a walk, look mode locks. + if (item->hitPoints <= 0) { item->goalAnimState = LS_STOP; return; } - if (!Lara.isMoving) + if (Lara.isMoving) { - if (TrInput & IN_LEFT) - { - Lara.turnRate -= LARA_TURN_RATE; - if (Lara.turnRate < -ANGLE(4.0f)) - Lara.turnRate = -ANGLE(4.0f); - } - else if (TrInput & IN_RIGHT) - { - Lara.turnRate += LARA_TURN_RATE; - if (Lara.turnRate > ANGLE(4.0f)) - Lara.turnRate = ANGLE(4.0f); - } + return; + } - if (TrInput & IN_FORWARD) + // TODO: Lara refuses to turn when performing walk-to-stand anims. + if (TrInput & IN_LEFT) + { + Lara.turnRate -= LARA_TURN_RATE; + if (Lara.turnRate < ANGLE(-4.0f)) { - if (Lara.waterStatus == LW_WADE) - { - item->goalAnimState = LS_WADE_FORWARD; - } - else if (TrInput & IN_WALK) - { - item->goalAnimState = LS_WALK_FORWARD; - } - else - { - item->goalAnimState = LS_RUN_FORWARD; - } + Lara.turnRate = ANGLE(-4.0f); + } + } + else if (TrInput & IN_RIGHT) + { + Lara.turnRate += LARA_TURN_RATE; + if (Lara.turnRate > ANGLE(4.0f)) + { + Lara.turnRate = ANGLE(4.0f); + } + } + + if (TrInput & IN_FORWARD) + { + if (Lara.waterStatus == LW_WADE) + { + item->goalAnimState = LS_WADE_FORWARD; + } + else if (TrInput & IN_WALK) + { + item->goalAnimState = LS_WALK_FORWARD; } else { - item->goalAnimState = LS_STOP; + item->goalAnimState = LS_RUN_FORWARD; } + + return; } + + item->goalAnimState = LS_STOP; } -void lara_col_walk(ITEM_INFO* item, COLL_INFO* coll)//1B3E8, 1B51C (F) +// State: 0 +// State code: lara_as_walk_forward() +void lara_col_walk_forward(ITEM_INFO* item, COLL_INFO* coll)//1B3E8, 1B51C (F) { - /*state 0*/ - /*state code: lara_as_walk*/ + Lara.moveAngle = 0; + item->gravityStatus = false; item->fallspeed = 0; - Lara.moveAngle = 0; - coll->badPos = 384; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = 0; - coll->slopesAreWalls = true; coll->slopesArePits = true; coll->lavaIsPit = 1; - coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); - if (!LaraHitCeiling(item, coll) && !TestLaraVault(item, coll)) + if (TrInput & IN_LEFT) { - if (LaraDeflectEdge(item, coll)) + if (TestLaraLean(coll) && item->pos.zRot <= 0) { - item->goalAnimState = LS_SPLAT; - if (GetChange(item, &g_Level.Anims[item->animNumber])) - return; + item->pos.zRot -= LARA_LEAN_RATE; + if (item->pos.zRot < -LARA_LEAN_MAX / 2) + { + item->pos.zRot = -LARA_LEAN_MAX / 2; + } + } + } + else if (TrInput & IN_RIGHT) + { + if (TestLaraLean(coll) && item->pos.zRot >= 0) + { + item->pos.zRot += LARA_LEAN_RATE; + if (item->pos.zRot > LARA_LEAN_MAX / 2) + { + item->pos.zRot = LARA_LEAN_MAX / 2; + } + } + } - LaraCollideStop(item, coll); + if (TestLaraVault(item, coll)) + { + return; + } + + if (TestLaraHitCeiling(coll)) + { + SetLaraHitCeiling(item, coll); + return; + } + + if (TestLaraWallDeflect(coll)) + { + SetLaraWallDeflect(item, coll); + + item->goalAnimState = LS_SPLAT; + if (GetChange(item, &g_Level.Anims[item->animNumber])) + { + return; } - if (!LaraFallen(item, coll)) - { - if (coll->midFloor > STEP_SIZE / 2) - { - if (coll->frontFloor == NO_HEIGHT || coll->frontFloor <= STEP_SIZE / 2) - { - coll->midFloor = 0; - } - else - { - item->goalAnimState = LS_STEP_DOWN; - GetChange(item, &g_Level.Anims[item->animNumber]); - } - } - if (coll->midFloor >= -STEPUP_HEIGHT && coll->midFloor < -STEP_SIZE / 2) - { - if (coll->frontFloor == NO_HEIGHT || - coll->frontFloor < -STEPUP_HEIGHT || - coll->frontFloor >= -STEP_SIZE / 2) - { - coll->midFloor = 0; - } - else - { - item->goalAnimState = LS_STEP_UP; - GetChange(item, &g_Level.Anims[item->animNumber]); - } - } + LaraCollideStop(item, coll); + } - if (!TestLaraSlide(item, coll) && coll->midFloor != NO_HEIGHT) - item->pos.yPos += coll->midFloor; - } + if (abs(coll->midFloor) > 0 && abs(coll->midFloor <= STEPUP_HEIGHT)) + { + DoLaraStep(item, coll); + } + + if (TestLaraFall(coll)) + { + item->goalAnimState = LS_FALL; + item->fallspeed = 0; + item->gravityStatus = true; + + return; + } + + if (TestLaraSlide(coll)) + { + SetLaraSlide(item, coll); + return; } } +// State: 1 +// Collision: lara_col_run() void lara_as_run(ITEM_INFO* item, COLL_INFO* coll)//192EC, 19420 (F) { - /*state 1*/ - /*collision: lara_col_run*/ if (item->hitPoints <= 0) { item->goalAnimState = LS_DEATH; return; } - if (TrInput & IN_ROLL) + if (TrInput & IN_LEFT) { - item->animNumber = LA_ROLL_180_START; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase + 2; - item->currentAnimState = LS_ROLL_FORWARD; - item->goalAnimState = LS_STOP; + Lara.turnRate -= LARA_TURN_RATE; + if (Lara.turnRate < -LARA_FAST_TURN) + { + Lara.turnRate = -LARA_FAST_TURN; + } + } + else if (TrInput & IN_RIGHT) + { + Lara.turnRate += LARA_TURN_RATE; + if (Lara.turnRate > LARA_FAST_TURN) + { + Lara.turnRate = LARA_FAST_TURN; + } + } + + if (item->animNumber == LA_STAND_TO_RUN) + { + EnableJump = false; + } + else if (item->animNumber == LA_RUN && item->frameNumber == 4) + { + EnableJump = true; + } + else + { + EnableJump = true; + } + + if (TrInput & IN_JUMP && EnableJump && !item->gravityStatus) + { + item->goalAnimState = LS_JUMP_FORWARD; return; } if (TrInput & IN_SPRINT && DashTimer) { item->goalAnimState = LS_SPRINT; + return; } @@ -218,146 +348,202 @@ void lara_as_run(ITEM_INFO* item, COLL_INFO* coll)//192EC, 19420 (F) return; } - if (TrInput & IN_LEFT) + if ((TrInput & IN_ROLL || + (TrInput & IN_BACK && EnableBackKeyTurn)) + && !(TrInput & IN_JUMP)) // A slightly hacky fix to prevent unintentional rolling when JUMP and ROLL are pressed and EnableJump isn't true yet. { - Lara.turnRate -= LARA_TURN_RATE; - if (Lara.turnRate < -LARA_FAST_TURN) - Lara.turnRate = -LARA_FAST_TURN; - - if (TestLaraLean(item, coll)) - { - item->pos.zRot -= LARA_LEAN_RATE; - if (item->pos.zRot < -LARA_LEAN_MAX) - item->pos.zRot = -LARA_LEAN_MAX; - } - } - else if (TrInput & IN_RIGHT) - { - Lara.turnRate += LARA_TURN_RATE; - if (Lara.turnRate > LARA_FAST_TURN) - Lara.turnRate = LARA_FAST_TURN; - - if (TestLaraLean(item, coll)) - { - item->pos.zRot += LARA_LEAN_RATE; - if (item->pos.zRot > LARA_LEAN_MAX) - item->pos.zRot = LARA_LEAN_MAX; - } + item->goalAnimState = LS_ROLL_FORWARD; + return; } - if (item->animNumber == LA_STAND_TO_RUN) - { - DoJump = false; - } - else if (item->animNumber == LA_RUN) - { - if (item->frameNumber == 4) - DoJump = true; - } - else - { - DoJump = true; - } - - if (TrInput & IN_JUMP && DoJump && !item->gravityStatus) - { - item->goalAnimState = LS_JUMP_FORWARD; - } - else if (TrInput & IN_FORWARD) + if (TrInput & IN_FORWARD) { if (Lara.waterStatus == LW_WADE) { item->goalAnimState = LS_WADE_FORWARD; } + else if (TrInput & IN_WALK) + { + item->goalAnimState = LS_WALK_FORWARD; + } else { - if (TrInput & IN_WALK) - item->goalAnimState = LS_WALK_FORWARD; - else - item->goalAnimState = LS_RUN_FORWARD; + item->goalAnimState = LS_RUN_FORWARD; } + + return; } - else - { - item->goalAnimState = LS_STOP; - } + + item->goalAnimState = LS_STOP; } +// State: 1 +// State code: lara_col_run() void lara_col_run(ITEM_INFO* item, COLL_INFO* coll)//1B64C, 1B780 (F) { - /*state 1*/ - /*state code: lara_col_run*/ Lara.moveAngle = 0; coll->badPos = NO_BAD_POS; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = 0; - coll->slopesAreWalls = true; - coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); - if (!LaraHitCeiling(item, coll) && !TestLaraVault(item, coll)) + if (TrInput & IN_LEFT) { - if (LaraDeflectEdge(item, coll)) + if (TestLaraLean(coll)) { - item->pos.zRot = 0; - - if (TestWall(item, 256, 0, -640)) + item->pos.zRot -= LARA_LEAN_RATE; + if (item->pos.zRot < -LARA_LEAN_MAX) { - item->goalAnimState = LS_SPLAT; - if (GetChange(item, &g_Level.Anims[item->animNumber])) - { - item->currentAnimState = LS_SPLAT; - return; - } - } - - LaraCollideStop(item, coll); - } - - if (!LaraFallen(item, coll)) - { - if (coll->midFloor >= -STEPUP_HEIGHT && coll->midFloor < -STEP_SIZE / 2) - { - if (coll->frontFloor == NO_HEIGHT || coll->frontFloor < -STEPUP_HEIGHT || coll->frontFloor >= -STEP_SIZE / 2) - { - coll->midFloor = 0; - } - else - { - item->goalAnimState = LS_STEP_UP; - GetChange(item, &g_Level.Anims[item->animNumber]); - } - } - - if (!TestLaraSlide(item, coll)) - { - if (coll->midFloor < 50) - { - if (coll->midFloor != NO_HEIGHT) - item->pos.yPos += coll->midFloor; - } - else - { - item->goalAnimState = LS_STEP_DOWN; // for theoretical running stepdown anims, not in default anims - if (GetChange(item, &g_Level.Anims[item->animNumber])) - item->pos.yPos += coll->midFloor; // move Lara to midFloor - else - item->pos.yPos += 50; // do the default aligment - } + item->pos.zRot = -LARA_LEAN_MAX; } } } + else if (TrInput & IN_RIGHT) + { + if (TestLaraLean(coll)) + { + item->pos.zRot += LARA_LEAN_RATE; + if (item->pos.zRot > LARA_LEAN_MAX) + { + item->pos.zRot = LARA_LEAN_MAX; + } + } + } + + if (TestLaraVault(item, coll)) + { + return; + } + + if (TestLaraHitCeiling(coll)) + { + SetLaraHitCeiling(item, coll); + return; + } + + if (LaraDeflectEdge(item, coll)) + { + item->pos.zRot = 0; + + if (TestWall(item, 256, 0, -640)) + { + item->goalAnimState = LS_SPLAT; + if (GetChange(item, &g_Level.Anims[item->animNumber])) + { + item->currentAnimState = LS_SPLAT; + return; + } + } + + LaraCollideStop(item, coll); + } + + if (abs(coll->midFloor) > 0 && abs(coll->midFloor <= STEPUP_HEIGHT)) + { + //DoLaraStep(item, coll); // Uncomment this line and remove everything below when a step down anim is created. + + /*if (TestLaraStepDown(coll)) + { + item->pos.yPos += coll->midFloor; + + item->goalAnimState = LS_STEP_DOWN; + GetChange(item, &g_Level.Anims[item->animNumber]); + } + else */if (TestLaraStepUp(coll)) + { + item->pos.yPos += coll->midFloor; + + item->goalAnimState = LS_STEP_UP; + GetChange(item, &g_Level.Anims[item->animNumber]); + } + else if (abs(coll->midFloor) >= 50) + { + item->pos.yPos += 50 * GetSign(coll->midFloor); + } + else + { + item->pos.yPos += coll->midFloor; + } + } + + if (TestLaraFall(coll)) + { + //if (TrInput & IN_ACTION && + // EnableSafetyDrop && + // coll->midFloor >= 1024 && + // Lara.gunStatus == LG_NO_ARMS) // TODO: Also test for floor behind and static below. + //{ + // item->goalAnimState = LS_SAFE_DROP; + //} + //else + //{ + item->goalAnimState = LS_FALL; + item->fallspeed = 0; + item->gravityStatus = true; + //} + + return; + } + + // LEGACY step code. Has NO_HEIGHT checks unaccounted for above; not sure what they do exactly. -Sezz + //if (coll->midFloor >= -STEPUP_HEIGHT && coll->midFloor < -STEP_SIZE / 2) + //{ + // if (coll->frontFloor == NO_HEIGHT || coll->frontFloor < -STEPUP_HEIGHT || coll->frontFloor >= -STEP_SIZE / 2) + // { + // coll->midFloor = 0; + // } + // else + // { + // item->goalAnimState = LS_STEP_UP; + // GetChange(item, &g_Level.Anims[item->animNumber]); + // } + //} + //else + //{ + // if (coll->midFloor < 50) + // { + // if (coll->midFloor != NO_HEIGHT) + // { + // item->pos.yPos += coll->midFloor / 2; + // } + // else + // { + // item->goalAnimState = LS_STEP_DOWN; // for theoretical running stepdown anims, not in default anims + + // if (GetChange(item, &g_Level.Anims[item->animNumber])) + // { + // item->pos.yPos += coll->midFloor; // move Lara to midFloor + // } + // else + // { + // item->pos.yPos += 50; // do the default aligment + // } + // } + // } + //} + + if (TestLaraSlide(coll)) + { + SetLaraSlide(item, coll); + return; + } } +// State: 2 +// Collision: lara_col_stop() void lara_as_stop(ITEM_INFO* item, COLL_INFO* coll) { - /*state 2*/ - /*collision: lara_col_stop*/ - short fheight = NO_HEIGHT; - short rheight = NO_HEIGHT; + int fHeight = NO_HEIGHT; + int rHeight = NO_HEIGHT; + + if (item->animNumber != LA_SPRINT_TO_STAND_RIGHT && item->animNumber != LA_SPRINT_TO_STAND_LEFT) + { + StopSoundEffect(SFX_LARA_SLIPPING); + } if (item->hitPoints <= 0) { @@ -365,273 +551,365 @@ void lara_as_stop(ITEM_INFO* item, COLL_INFO* coll) return; } - if (item->animNumber != LA_SPRINT_TO_STAND_RIGHT && item->animNumber != LA_SPRINT_TO_STAND_LEFT) - StopSoundEffect(SFX_LARA_SLIPPING); - - // Handles waterskin and clockwork beetle + // Handles waterskin and clockwork beetle. if (UseSpecialItem(item)) - return; - - if (TrInput & IN_ROLL && Lara.waterStatus != LW_WADE) { - item->animNumber = LA_ROLL_180_START; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase + 2; - item->currentAnimState = LS_ROLL_FORWARD; - item->goalAnimState = LS_STOP; - return; - } - - if (TrInput & IN_DUCK - && Lara.waterStatus != LW_WADE - && item->currentAnimState == LS_STOP - && (Lara.gunStatus == LG_NO_ARMS - || Lara.gunType == WEAPON_NONE - || Lara.gunType == WEAPON_PISTOLS - || Lara.gunType == WEAPON_REVOLVER - || Lara.gunType == WEAPON_UZI - || Lara.gunType == WEAPON_FLARE)) - { - item->goalAnimState = LS_CROUCH_IDLE; return; } + // TODO: This prevents locks and looping actions, but those should be caught by each state. item->goalAnimState = LS_STOP; if (TrInput & IN_LOOK) + { LookUpDown(); + } if (TrInput & IN_FORWARD) - fheight = LaraFloorFront(item, item->pos.yRot, LARA_RAD + 4); - else if (TrInput & IN_BACK) - rheight = LaraFloorFront(item, item->pos.yRot - ANGLE(180.0f), LARA_RAD + 4); // TR3: item->pos.yRot + ANGLE(180) ? - - if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) { - if (TrInput & IN_LEFT) - item->goalAnimState = LS_TURN_LEFT_SLOW; - else if (TrInput & IN_RIGHT) - item->goalAnimState = LS_TURN_RIGHT_SLOW; + fHeight = LaraFloorFront(item, item->pos.yRot, LARA_RAD + 4); } - else + else if (TrInput & IN_BACK) { - if (TrInput & IN_LSTEP) + rHeight = LaraFloorFront(item, item->pos.yRot - ANGLE(180.0f), LARA_RAD + 4); // TR3: item->pos.yRot + ANGLE(180) ? + } + + int height, ceiling; + + if (TrInput & IN_LEFT) + { + item->goalAnimState = LS_TURN_LEFT_SLOW; + } + else if (TrInput & IN_RIGHT) + { + item->goalAnimState = LS_TURN_RIGHT_SLOW; + } + else if (TrInput & IN_LSTEP) + { + height = LaraFloorFront(item, item->pos.yRot - ANGLE(90.0f), LARA_RAD + 48); + ceiling = LaraCeilingFront(item, item->pos.yRot - ANGLE(90.0f), LARA_RAD + 48, LARA_HITE); + + if ((height < 128 && height > -128) && HeightType != BIG_SLOPE && ceiling <= 0) { - short height, ceiling; - - height = LaraFloorFront(item, item->pos.yRot - ANGLE(90.0f), LARA_RAD + 48); - ceiling = LaraCeilingFront(item, item->pos.yRot - ANGLE(90.0f), LARA_RAD + 48, LARA_HITE); - - if ((height < 128 && height > -128) && HeightType != BIG_SLOPE && ceiling <= 0) - item->goalAnimState = LS_STEP_LEFT; + item->goalAnimState = LS_STEP_LEFT; } - else if (TrInput & IN_RSTEP) - { - short height, ceiling; + } + else if (TrInput & IN_RSTEP) + { + height = LaraFloorFront(item, item->pos.yRot + ANGLE(90.0f), LARA_RAD + 48); + ceiling = LaraCeilingFront(item, item->pos.yRot + ANGLE(90.0f), LARA_RAD + 48, LARA_HITE); - height = LaraFloorFront(item, item->pos.yRot + ANGLE(90.0f), LARA_RAD + 48); - ceiling = LaraCeilingFront(item, item->pos.yRot + ANGLE(90.0f), LARA_RAD + 48, LARA_HITE); - - if ((height < 128 && height > -128) && HeightType != BIG_SLOPE && ceiling <= 0) - item->goalAnimState = LS_STEP_RIGHT; - } - else if (TrInput & IN_LEFT) + if ((height < 128 && height > -128) && HeightType != BIG_SLOPE && ceiling <= 0) { - item->goalAnimState = LS_TURN_LEFT_SLOW; - } - else if (TrInput & IN_RIGHT) - { - item->goalAnimState = LS_TURN_RIGHT_SLOW; + item->goalAnimState = LS_STEP_RIGHT; } } if (Lara.waterStatus == LW_WADE) { if (TrInput & IN_JUMP && !(g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP)) + { item->goalAnimState = LS_JUMP_PREPARE; + } if (TrInput & IN_FORWARD) { - bool wade = false; - - if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) + if ((g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP && + fHeight > -(STEPUP_HEIGHT - 1)) || + (fHeight < (STEPUP_HEIGHT - 1) && + fHeight > -(STEPUP_HEIGHT - 1))) { - if (fheight > -(STEPUP_HEIGHT - 1)) - { - lara_as_wade(item, coll); - wade = true; - } - } - else - { - if ((fheight < (STEPUP_HEIGHT - 1)) && (fheight > -(STEPUP_HEIGHT - 1))) - { - lara_as_wade(item, coll); - wade = true; - } + item->goalAnimState = LS_WADE_FORWARD; + return; } - if (!wade) + Lara.moveAngle = 0; + + coll->badPos = NO_BAD_POS; + coll->badNeg = -STEPUP_HEIGHT; + coll->badCeiling = 0; + coll->slopesAreWalls = true; + coll->radius = LARA_RAD + 2; + coll->facing = Lara.moveAngle; + + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); + + if (TestLaraVault(item, coll)) { - Lara.moveAngle = 0; - coll->badPos = NO_BAD_POS; - coll->badNeg = -STEPUP_HEIGHT; - coll->badCeiling = 0; - coll->slopesAreWalls = true; - coll->radius = LARA_RAD + 2; - coll->facing = Lara.moveAngle; - - GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); - if (TestLaraVault(item, coll)) - return; - - coll->radius = LARA_RAD; + return; } + + coll->radius = LARA_RAD; + + return; } - else if (TrInput & IN_BACK) + + if (TrInput & IN_BACK) { - if ((rheight < (STEPUP_HEIGHT - 1)) && (rheight > -(STEPUP_HEIGHT - 1))) - lara_as_back(item, coll); + if ((rHeight < (STEPUP_HEIGHT - 1)) && (rHeight > -(STEPUP_HEIGHT - 1))) + { + item->goalAnimState = LS_WALK_BACK; + } + + return; + } + + // TODO: Add failsafe which automatically crouches Lara if she unexpectedly embeds into a crawlspace. + if (TrInput & IN_DUCK && + Lara.waterStatus != LW_WADE && + (Lara.gunStatus == LG_NO_ARMS || + Lara.gunType == WEAPON_NONE || + Lara.gunType == WEAPON_PISTOLS || + Lara.gunType == WEAPON_REVOLVER || + Lara.gunType == WEAPON_UZI || + Lara.gunType == WEAPON_FLARE)) + { + item->goalAnimState = LS_CROUCH_IDLE; + return; + } + + if (TrInput & IN_ROLL && Lara.waterStatus != LW_WADE) + { + item->goalAnimState = LS_ROLL_FORWARD; + return; } } - else + else [[likely]] { if (TrInput & IN_JUMP) { item->goalAnimState = LS_JUMP_PREPARE; + return; } - else if (TrInput & IN_FORWARD) - { - short height, ceiling; - height = LaraFloorFront(item, item->pos.yRot, LARA_RAD + 4); - ceiling = LaraCeilingFront(item, item->pos.yRot, LARA_RAD + 4, LARA_HITE); + if (TrInput & IN_FORWARD) + { + int height = LaraFloorFront(item, item->pos.yRot, LARA_RAD + 4); + int ceiling = LaraCeilingFront(item, item->pos.yRot, LARA_RAD + 4, LARA_HITE); if ((HeightType == BIG_SLOPE || HeightType == DIAGONAL) && (height < 0 || ceiling > 0)) { item->goalAnimState = LS_STOP; return; } - if (TrInput & IN_WALK) - lara_as_walk(item, coll); - else - lara_as_run(item, coll); - } - else if (TrInput & IN_BACK) - { - if (TrInput & IN_WALK) + + /*if (TrInput & IN_ACTION && + EnableSafetyDrop && + LaraFloorFront(item, -item->pos.yRot, 100) <= 1024) { - if ((rheight < (STEPUP_HEIGHT - 1)) && (rheight > -(STEPUP_HEIGHT - 1)) && HeightType != BIG_SLOPE) - lara_as_back(item, coll); + item->goalAnimState = LS_SAFE_DROP; } - else if (rheight > -(STEPUP_HEIGHT - 1)) + else */if (TrInput & IN_WALK) + { + item->goalAnimState = LS_WALK_FORWARD; + } + else + { + item->goalAnimState = LS_RUN_FORWARD; + } + + return; + } + + if (TrInput & IN_BACK) + { + /*if (TrInput & IN_ACTION && LaraFloorFront(item, -item->pos.yRot, 100) < 1024 && EnableSafetyDrop) + { + item->goalAnimState = LS_SAFE_DROP; + } + else */if (TrInput & IN_WALK) + { + if ((rHeight < (STEPUP_HEIGHT - 1)) && (rHeight > -(STEPUP_HEIGHT - 1)) && HeightType != BIG_SLOPE) + { + item->goalAnimState = LS_WALK_BACK; + } + } + else if (rHeight > -(STEPUP_HEIGHT - 1)) { item->goalAnimState = LS_HOP_BACK; } + + return; + } + + //if (TrInput & IN_SPRINT) + //{ + // item->goalAnimState = LS_SPRINT; + // return; + //} + + if (TrInput & IN_DUCK && + Lara.waterStatus != LW_WADE && + (Lara.gunStatus == LG_NO_ARMS || + Lara.gunType == WEAPON_NONE || + Lara.gunType == WEAPON_PISTOLS || + Lara.gunType == WEAPON_REVOLVER || + Lara.gunType == WEAPON_UZI || + Lara.gunType == WEAPON_FLARE)) + { + item->goalAnimState = LS_CROUCH_IDLE; + return; + } + + if (TrInput & IN_ROLL && Lara.waterStatus != LW_WADE) + { + item->goalAnimState = LS_ROLL_FORWARD; + return; } } } +// State: 2 +// State code: lara_as_stop() void lara_col_stop(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - /*state 2*/ - /*state code: lara_as_stop*/ Lara.moveAngle = 0; + + item->gravityStatus = false; + item->fallspeed = 0; + coll->badPos = STEPUP_HEIGHT; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = 0; - item->gravityStatus = false; - item->fallspeed = 0; coll->slopesArePits = true; - coll->slopesAreWalls = 1; + coll->slopesAreWalls = true; coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); - if (LaraHitCeiling(item, coll)) + if (TestLaraVault(item, coll)) + { return; + } - if (LaraFallen(item, coll)) + if (TestLaraHitCeiling(coll)) + { + SetLaraHitCeiling(item, coll); return; + } + + if (TestLaraFall(coll)) + { + item->goalAnimState = LS_FALL; + item->fallspeed = 0; + item->gravityStatus = true; - if (TestLaraSlide(item, coll)) return; + } + + if (TestLaraSlide(coll)) + { + SetLaraSlide(item, coll); + return; + } ShiftItem(item, coll); #if 1 if (coll->midFloor != NO_HEIGHT) + { item->pos.yPos += coll->midFloor; + } #else if (!(g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) || coll->midFloor < 0) + { item->pos.yPos += coll->midFloor; + } else if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP && coll->midFloor) + { item->pos.yPos += SWAMP_GRAVITY; + } #endif } -void lara_as_forwardjump(ITEM_INFO* item, COLL_INFO* coll)//18A34, 18B68 (F) +// State: 3 +// Collision: lara_col_forward_jump() +void lara_as_jump_forward(ITEM_INFO* item, COLL_INFO* coll)//18A34, 18B68 (F) { - /*state 3*/ - /*collision: */ - if (item->goalAnimState == LS_SWANDIVE_START || - item->goalAnimState == LS_REACH) - item->goalAnimState = LS_JUMP_FORWARD; + //if (item->hitPoints <= 0) + //{ + // item->goalAnimState = LS_DEATH; + // return; + //} - if (item->goalAnimState != LS_DEATH && - item->goalAnimState != LS_STOP && - item->goalAnimState != LS_RUN_FORWARD) + if (item->fallspeed > LARA_FREEFALL_SPEED) { - if (Lara.gunStatus == LG_NO_ARMS && TrInput & IN_ACTION) - item->goalAnimState = LS_REACH; - - if (TrInput & IN_BACK || TrInput & IN_ROLL) - item->goalAnimState = LS_JUMP_ROLL_180; - - if (Lara.gunStatus == LG_NO_ARMS && TrInput & IN_WALK) - item->goalAnimState = LS_SWANDIVE_START; - - if (item->fallspeed > LARA_FREEFALL_SPEED) - item->goalAnimState = LS_FREEFALL; + item->goalAnimState = LS_FREEFALL; + return; } + // Petition to ban banana jumps. if (TrInput & IN_LEFT) { Lara.turnRate -= LARA_TURN_RATE; - - if (Lara.turnRate < -ANGLE(3.0f)) - Lara.turnRate = -ANGLE(3.0f); + if (Lara.turnRate < ANGLE(-3.0f)) + { + Lara.turnRate = ANGLE(-3.0f); + } } else if (TrInput & IN_RIGHT) { Lara.turnRate += LARA_TURN_RATE; - if (Lara.turnRate > ANGLE(3.0f)) + { Lara.turnRate = ANGLE(3.0f); + } } + + if (TrInput & IN_ACTION && + Lara.gunStatus == LG_NO_ARMS) + { + item->goalAnimState = LS_REACH; + return; + } + + if (TrInput & IN_WALK && + Lara.gunStatus == LG_NO_ARMS) + { + item->goalAnimState = LS_SWANDIVE_START; + return; + } + + if (TrInput & IN_ROLL || + (TrInput & IN_BACK && EnableBackKeyTurn)) + { + item->goalAnimState = LS_JUMP_ROLL_180; + return; + } + + //item->goalAnimState = LS_JUMP_FORWARD; } -void lara_col_forwardjump(ITEM_INFO* item, COLL_INFO* coll)//18B88, 18CBC (F) +// State: 3 +// State code: lara_as_forward_jump() +void lara_col_jump_forward(ITEM_INFO* item, COLL_INFO* coll)//18B88, 18CBC (F) { - /*state 3*/ - /*state code: lara_as_forwardjump*/ if (item->speed < 0) - Lara.moveAngle = ANGLE(180); + { + Lara.moveAngle = ANGLE(180.0f); + } else + { Lara.moveAngle = 0; + } coll->badPos = NO_BAD_POS; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = BAD_JUMP_CEILING; - coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); + LaraDeflectEdgeJump(item, coll); - if (item->speed < 0) + if (item->speed < 0) // ?? + { Lara.moveAngle = 0; + } if (coll->midFloor <= 0 && item->fallspeed > 0) { - if (LaraLandedBad(item, coll)) + if (LaraLandedBad(item, coll)) // ? { item->goalAnimState = LS_DEATH; } @@ -643,10 +921,14 @@ void lara_col_forwardjump(ITEM_INFO* item, COLL_INFO* coll)//18B88, 18CBC (F) } else { - if (TrInput & IN_FORWARD && !(TrInput & IN_STEPSHIFT)) + if (TrInput & IN_FORWARD && !(TrInput & IN_STEPSHIFT)) // ??? + { item->goalAnimState = LS_RUN_FORWARD; + } else + { item->goalAnimState = LS_STOP; + } } } @@ -655,144 +937,202 @@ void lara_col_forwardjump(ITEM_INFO* item, COLL_INFO* coll)//18B88, 18CBC (F) item->speed = 0; if (coll->midFloor != NO_HEIGHT) + { item->pos.yPos += coll->midFloor; + } AnimateLara(item); } } +// State: 4 +// Collision: lara_void_func() void lara_col_pose(ITEM_INFO* item, COLL_INFO* coll)//1B87C(<), 1B9B0(<) (F) { - /*state 4*/ - /*state code: lara_void_func*/ lara_col_stop(item, coll); } -void lara_as_fastback(ITEM_INFO* item, COLL_INFO* coll)//1959C(<), 196D0(<) (F) +// State: 5 +// Collision: lara_col_hop_back() +void lara_as_hop_back(ITEM_INFO* item, COLL_INFO* coll)//1959C(<), 196D0(<) (F) { - /*state: 5*/ - /*collision: lara_col_fastback*/ - item->goalAnimState = LS_STOP; if (TrInput & IN_LEFT) { Lara.turnRate -= LARA_TURN_RATE; - if (Lara.turnRate < -ANGLE(6.0f)) - Lara.turnRate = -ANGLE(6.0f); + if (Lara.turnRate < ANGLE(-6.0f)) + { + Lara.turnRate = ANGLE(-6.0f); + } } else if (TrInput & IN_RIGHT) { Lara.turnRate += LARA_TURN_RATE; if (Lara.turnRate > ANGLE(6.0f)) + { Lara.turnRate = ANGLE(6.0f); + } } + + item->goalAnimState = LS_STOP; } -void lara_col_fastback(ITEM_INFO* item, COLL_INFO* coll)//1B89C, 1B9D0 (F) +// State: 5 +// State code: lara_as_hop_back() +void lara_col_hop_back(ITEM_INFO* item, COLL_INFO* coll)//1B89C, 1B9D0 (F) { - /*state: 5*/ - /*state code: lara_as_fastback*/ + Lara.moveAngle = ANGLE(180.0f); + item->fallspeed = 0; item->gravityStatus = false; - Lara.moveAngle = ANGLE(180); - coll->slopesAreWalls = 0; coll->slopesArePits = true; - coll->badPos = NO_BAD_POS; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = 0; - coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); - if (!LaraHitCeiling(item, coll)) + if (TestLaraHitCeiling(coll)) { - if (coll->midFloor <= 200) - { - if (LaraDeflectEdge(item, coll)) - LaraCollideStop(item, coll); + SetLaraHitCeiling(item, coll); + return; + } - if (!TestLaraSlide(item, coll) && coll->midFloor != NO_HEIGHT) - item->pos.yPos += coll->midFloor; + if (TestLaraWallDeflect(coll)) + { + SetLaraWallDeflect(item, coll); + LaraCollideStop(item, coll); + } + + // TODO: Hop back step height check is unique among the land traversal states. Appropriate to make test functions have extra parameters to account for this one case? + if (abs(coll->midFloor) > 0 && abs(coll->midFloor <= 200)) + { + if (abs(coll->midFloor) >= 50) + { + item->pos.yPos += 50 * GetSign(coll->midFloor); } else { - item->fallspeed = 0; - - item->animNumber = LA_FALL_BACK; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->currentAnimState = LS_FALL_BACK; - item->goalAnimState = LS_FALL_BACK; - - item->gravityStatus = true; + item->pos.yPos += coll->midFloor; } } + + if (coll->midFloor >= 200) + { + item->goalAnimState = LS_FALL_BACK; + item->fallspeed = 0; + item->gravityStatus = true; + + return; + } + + if (TestLaraSlide(coll)) + { + SetLaraSlide(item, coll); + return; + } + + item->goalAnimState = LS_STOP; } -void lara_as_turn_r(ITEM_INFO* item, COLL_INFO* coll)//19628(<), 1975C(<) (F) +// State: 6 +// Collision: lara_col_turn_right() +void lara_as_turn_right(ITEM_INFO* item, COLL_INFO* coll)//19628(<), 1975C(<) (F) { - /*state: 6*/ - /*collision: */ if (item->hitPoints <= 0) { item->goalAnimState = LS_STOP; - return; } Lara.turnRate += LARA_TURN_RATE; - - if (Lara.gunStatus != LG_READY || Lara.waterStatus == LW_WADE) + if (Lara.waterStatus == LW_WADE || + Lara.gunStatus != LG_READY) { if (Lara.turnRate > ANGLE(4.0f)) { - if (TrInput & IN_WALK) - Lara.turnRate = ANGLE(4.0f); - else - item->goalAnimState = LS_TURN_FAST; + item->goalAnimState = LS_TURN_RIGHT_FAST; // TODO: Investigate why a 1 frame WALK input causes an early dispatch to FAST_TURN instead of SIDESTEP. } } else { - item->goalAnimState = LS_TURN_FAST; + item->goalAnimState = LS_TURN_RIGHT_FAST; } - if (!(TrInput & IN_FORWARD)) + if (TrInput & IN_JUMP) { - if (!(TrInput & IN_RIGHT)) - item->goalAnimState = LS_STOP; + item->goalAnimState = LS_JUMP_PREPARE; + return; + } + + //if (TrInput & IN_SPRINT) + //{ + // item->goalAnimState = LS_SPRINT; + // return; + //} + + if (TrInput & IN_DUCK && + Lara.waterStatus != LW_WADE && + (Lara.gunStatus == LG_NO_ARMS || + Lara.gunType == WEAPON_NONE || + Lara.gunType == WEAPON_PISTOLS || + Lara.gunType == WEAPON_REVOLVER || + Lara.gunType == WEAPON_UZI || + Lara.gunType == WEAPON_FLARE)) + { + item->goalAnimState = LS_CROUCH_IDLE; + return; + } + + if (TrInput & IN_ROLL && Lara.waterStatus != LW_WADE) + { + item->goalAnimState = LS_ROLL_FORWARD; + return; + } + + if (TrInput & IN_FORWARD) + { + if (Lara.waterStatus == LW_WADE) + { + item->goalAnimState = LS_WADE_FORWARD; + } + else if (TrInput & IN_WALK) + { + item->goalAnimState = LS_WALK_FORWARD; + } + else + { + item->goalAnimState = LS_RUN_FORWARD; + } return; } - if (Lara.waterStatus == LW_WADE) + if (!(TrInput & IN_RIGHT)) { - item->goalAnimState = LS_WADE_FORWARD; - } - else if (TrInput & IN_WALK) - { - item->goalAnimState = LS_WALK_FORWARD; - } - else - { - item->goalAnimState = LS_RUN_FORWARD; + item->goalAnimState = LS_STOP; + return; } } -void lara_col_turn_r(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +// State: 6 +// State code: lara_as_turn_r() +void lara_col_turn_right(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - /*state: 6*/ - /*state code: lara_as_turn_r*/ + Lara.moveAngle = 0; + item->fallspeed = 0; item->gravityStatus = false; - Lara.moveAngle = 0; + coll->badPos = STEPUP_HEIGHT; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = 0; coll->slopesAreWalls = 1; coll->slopesArePits = true; coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); #if 1 @@ -801,33 +1141,43 @@ void lara_col_turn_r(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) if (coll->midFloor > 100 && !(g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP)) #endif { + item->goalAnimState = LS_FALL; item->fallspeed = 0; - item->animNumber = LA_FALL_START; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->currentAnimState = LS_JUMP_FORWARD; - item->goalAnimState = LS_JUMP_FORWARD; item->gravityStatus = true; + return; } - if (TestLaraSlide(item, coll)) + if (TestLaraSlide(coll)) + { + SetLaraSlide(item, coll); return; + } + + //return; ?? #if 1 if (coll->midFloor != NO_HEIGHT) + { item->pos.yPos += coll->midFloor; + } #else if (!(g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) || coll->midFloor < 0) + { item->pos.yPos += coll->midFloor; + } else if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP && coll->midFloor) + { item->pos.yPos += SWAMP_GRAVITY; + } #endif } -void lara_as_turn_l(ITEM_INFO* item, COLL_INFO* coll)//1972C(<), 19860(<) (F) +// TODO: TURN_RIGHT_FAST is dispatched instead?! +// State: 7 +// Collision: lara_col_turn() +void lara_as_turn_left(ITEM_INFO* item, COLL_INFO* coll)//1972C(<), 19860(<) (F) { - /*state 7*/ - /*collision: lara_col_turn_l*/ if (item->hitPoints <= 0) { item->goalAnimState = LS_STOP; @@ -835,81 +1185,116 @@ void lara_as_turn_l(ITEM_INFO* item, COLL_INFO* coll)//1972C(<), 19860(<) (F) } Lara.turnRate -= LARA_TURN_RATE; - - if (Lara.gunStatus != LG_READY || Lara.waterStatus == LW_WADE) + if (Lara.waterStatus == LW_WADE || + Lara.gunStatus != LG_READY) { - if (Lara.turnRate < -ANGLE(4.0f)) + if (Lara.turnRate < ANGLE(-4.0f)) { - if (TrInput & IN_WALK) - Lara.turnRate = -ANGLE(4.0f); - else - item->goalAnimState = LS_TURN_FAST; + item->goalAnimState = LS_TURN_LEFT_FAST; } } else { - item->goalAnimState = LS_TURN_FAST; + item->goalAnimState = LS_TURN_LEFT_FAST; } - if (!(TrInput & IN_FORWARD)) + if (TrInput & IN_JUMP) { - if (!(TrInput & IN_LEFT)) - item->goalAnimState = LS_STOP; + item->goalAnimState = LS_JUMP_PREPARE; + return; + } + + //if (TrInput & IN_SPRINT) + //{ + // item->goalAnimState = LS_SPRINT; + // return; + //} + + if (TrInput & IN_DUCK && + Lara.waterStatus != LW_WADE && + (Lara.gunStatus == LG_NO_ARMS || + Lara.gunType == WEAPON_NONE || + Lara.gunType == WEAPON_PISTOLS || + Lara.gunType == WEAPON_REVOLVER || + Lara.gunType == WEAPON_UZI || + Lara.gunType == WEAPON_FLARE)) + { + item->goalAnimState = LS_CROUCH_IDLE; + return; + } + + if (TrInput & IN_ROLL && Lara.waterStatus != LW_WADE) + { + item->goalAnimState = LS_ROLL_FORWARD; + return; + } + + if (TrInput & IN_FORWARD) + { + if (Lara.waterStatus == LW_WADE) + { + item->goalAnimState = LS_WADE_FORWARD; + } + else if (TrInput & IN_WALK) + { + item->goalAnimState = LS_WALK_FORWARD; + } + else + { + item->goalAnimState = LS_RUN_FORWARD; + } return; } - if (Lara.waterStatus == LW_WADE) + if (!(TrInput & IN_LEFT)) { - item->goalAnimState = LS_WADE_FORWARD; - } - else if (TrInput & IN_WALK) - { - item->goalAnimState = LS_WALK_FORWARD; - } - else - { - item->goalAnimState = LS_RUN_FORWARD; + item->goalAnimState = LS_STOP; + return; } } -void lara_col_turn_l(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +// State: 6 +// State code: lara_as_turn_left() +void lara_col_turn_left(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - /*state 7*/ - /*state code: lara_as_turn_l*/ - lara_col_turn_r(item, coll); + lara_col_turn_right(item, coll); } +// State: 8 +// Collision: lara_col_death() void lara_as_death(ITEM_INFO* item, COLL_INFO* coll)//19830(<), 19964(<) (F) { - /*state 8*/ - /*collision: lara_col_death*/ Lara.look = false; + coll->enableBaddiePush = false; coll->enableSpaz = false; + if (BinocularRange) { BinocularRange = 0; LaserSight = 0; - AlterFOV(ANGLE(80.0f)); LaraItem->meshBits = -1; Lara.busy = false; + + AlterFOV(ANGLE(80.0f)); } } +// State: 8 +// State code: lara_as_death() void lara_col_death(ITEM_INFO* item, COLL_INFO* coll)//1BADC(<), 1BC10(<) (F) { - /*state 8*/ - /*state code: lara_as_death*/ - StopSoundEffect(SFX_LARA_FALL); - Lara.moveAngle = 0; + coll->badPos = 384; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = 0; coll->radius = 400; - coll->facing = Lara.moveAngle; + + StopSoundEffect(SFX_LARA_FALL); + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); ShiftItem(item, coll); @@ -917,31 +1302,37 @@ void lara_col_death(ITEM_INFO* item, COLL_INFO* coll)//1BADC(<), 1BC10(<) (F) Lara.air = -1; if (coll->midFloor != NO_HEIGHT) + { item->pos.yPos += coll->midFloor; + } } -void lara_as_fastfall(ITEM_INFO* item, COLL_INFO* coll)//198BC(<), 199F0(<) (F) +// State: 9 +// Collision: lara_col_freefall() +void lara_as_freefall(ITEM_INFO* item, COLL_INFO* coll)//198BC(<), 199F0(<) (F) { - /*state 9*/ - /*collision: lara_col_fastfall*/ item->speed = (item->speed * 95) / 100; if (item->fallspeed == 154) + { SoundEffect(SFX_LARA_FALL, &item->pos, 0); + } } -void lara_col_fastfall(ITEM_INFO* item, COLL_INFO* coll)//1BB88, 1BCBC (F) +// State: 9 +// State code: lara_as_freefall() +void lara_col_freefall(ITEM_INFO* item, COLL_INFO* coll)//1BB88, 1BCBC (F) { - /*state 9*/ - /*state code: lara_as_fastfall*/ item->gravityStatus = true; coll->badPos = NO_BAD_POS; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = BAD_JUMP_CEILING; - coll->facing = Lara.moveAngle; + + StopSoundEffect(SFX_LARA_FALL); + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); - LaraSlideEdgeJump(item, coll); + PerformLaraSlideEdgeJump(item, coll); if (coll->midFloor <= 0) { @@ -952,44 +1343,46 @@ void lara_col_fastfall(ITEM_INFO* item, COLL_INFO* coll)//1BB88, 1BCBC (F) else { item->goalAnimState = LS_STOP; - item->currentAnimState = LS_STOP; - item->animNumber = LA_FREEFALL_LAND; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; } - StopSoundEffect(SFX_LARA_FALL); - item->fallspeed = 0; item->gravityStatus = false; if (coll->midFloor != NO_HEIGHT) + { item->pos.yPos += coll->midFloor; + } } } +// State: 11 +// Collision: lara_col_reach() void lara_as_reach(ITEM_INFO* item, COLL_INFO* coll)//18CE0(<), 18E14(<) (F) { - /*state 11*/ - /*collision: lara_col_reach*/ Camera.targetAngle = ANGLE(85.0f); + if (item->fallspeed > LARA_FREEFALL_SPEED) + { item->goalAnimState = LS_FREEFALL; + } } +// State: 11 +// State code: lara_as_reach() void lara_col_reach(ITEM_INFO* item, COLL_INFO* coll)//18D0C, 18E40 (F) { - /*state 11*/ - /*state code: lara_as_reach*/ if (Lara.ropePtr == -1) + { item->gravityStatus = true; + } Lara.moveAngle = 0; coll->badPos = NO_BAD_POS; coll->badNeg = 0; coll->badCeiling = BAD_JUMP_CEILING; - coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); short angle; @@ -997,9 +1390,11 @@ void lara_col_reach(ITEM_INFO* item, COLL_INFO* coll)//18D0C, 18E40 (F) int edge = 0; int edgeCatch = 0; - if (TrInput & IN_ACTION && Lara.gunStatus == LG_NO_ARMS && !coll->hitStatic) + if (TrInput & IN_ACTION && + Lara.gunStatus == LG_NO_ARMS && + !coll->hitStatic) { - if (Lara.canMonkeySwing && coll->collType == CT_TOP) + if (coll->collType == CT_TOP && Lara.canMonkeySwing) { Lara.headYrot = 0; Lara.headXrot = 0; @@ -1007,6 +1402,7 @@ void lara_col_reach(ITEM_INFO* item, COLL_INFO* coll)//18D0C, 18E40 (F) Lara.torsoXrot = 0; Lara.gunStatus = LG_HANDS_BUSY; + // TODO: State dispatch. Doing it the obvious way results in a delay before the catch. item->animNumber = LA_REACH_TO_MONKEYSWING; item->frameNumber = g_Level.Anims[item->animNumber].frameBase; item->goalAnimState = LS_MONKEYSWING_IDLE; @@ -1041,7 +1437,7 @@ void lara_col_reach(ITEM_INFO* item, COLL_INFO* coll)//18D0C, 18E40 (F) if (!result) { - LaraSlideEdgeJump(item, coll); + PerformLaraSlideEdgeJump(item, coll); coll->facing = Lara.moveAngle; GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); ShiftItem(item, coll); @@ -1057,8 +1453,11 @@ void lara_col_reach(ITEM_INFO* item, COLL_INFO* coll)//18D0C, 18E40 (F) item->goalAnimState = LS_STOP; item->fallspeed = 0; item->gravityStatus = false; + if (coll->midFloor != NO_HEIGHT) + { item->pos.yPos += coll->midFloor; + } } } } @@ -1066,28 +1465,17 @@ void lara_col_reach(ITEM_INFO* item, COLL_INFO* coll)//18D0C, 18E40 (F) { if (TestHangSwingIn(item, angle)) { - /* if (TR12_OSCILLATE_HANG == true) - { - Lara.headYrot = 0; - Lara.headXrot = 0; - Lara.torsoYrot = 0; - Lara.torsoXrot = 0; - item->animNumber = LA_REACH_TO_HANG_OSCILLATE; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->currentAnimState = LS_HANG; - item->goalAnimState = LS_HANG; - } - else - { */ Lara.headYrot = 0; Lara.headXrot = 0; Lara.torsoYrot = 0; Lara.torsoXrot = 0; - item->animNumber = LA_REACH_TO_MONKEYSWING; + item->animNumber = LA_REACH_TO_HANG_OSCILLATE; item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->currentAnimState = LS_MONKEYSWING_IDLE; - item->goalAnimState = LS_MONKEYSWING_IDLE; - // } + item->currentAnimState = LS_HANG; + item->goalAnimState = LS_HANG; + item->gravityStatus = false; + item->speed = 0; + item->fallspeed = 0; } else { @@ -1132,7 +1520,6 @@ void lara_col_reach(ITEM_INFO* item, COLL_INFO* coll)//18D0C, 18E40 (F) } item->pos.yRot = angle; - item->gravityStatus = true; item->speed = 2; item->fallspeed = 1; @@ -1152,212 +1539,395 @@ void lara_col_splat(ITEM_INFO* item, COLL_INFO* coll)//1BC74(<), 1BDA8(<) (F) coll->slopesAreWalls = true; coll->slopesArePits = true; - coll->badPos = 384; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = 0; - coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); + ShiftItem(item, coll); if (coll->midFloor >= -256 && coll->midFloor <= 256) + { item->pos.yPos += coll->midFloor; + } } -void lara_col_land(ITEM_INFO* item, COLL_INFO* coll)//1BD10(<), 1BE44(<) (F) +// State: 15 +// Collision: lara_col_jump_prepare() +void lara_as_jump_prepare(ITEM_INFO* item, COLL_INFO* coll) { - /*state 14*/ - /*state code: lara_void_func*/ - lara_col_stop(item, coll); -} - -void lara_as_compress(ITEM_INFO* item, COLL_INFO* coll) -{ - /*state 15*/ - /*collision: lara_col_compress*/ if (Lara.waterStatus != LW_WADE) { + // TODO: Check ceilings as well. if (TrInput & IN_FORWARD && LaraFloorFront(item, item->pos.yRot, 256) >= -384) { item->goalAnimState = LS_JUMP_FORWARD; Lara.moveAngle = 0; } + else if (TrInput & IN_BACK && LaraFloorFront(item, item->pos.yRot - ANGLE(180.0f), 256) >= -384) + { + item->goalAnimState = LS_JUMP_BACK; + Lara.moveAngle = ANGLE(180.0f); + } else if (TrInput & IN_LEFT && LaraFloorFront(item, item->pos.yRot - ANGLE(90.0f), 256) >= -384) { item->goalAnimState = LS_JUMP_LEFT; - Lara.moveAngle = -ANGLE(90); + Lara.moveAngle = ANGLE(-90.0f); } else if (TrInput & IN_RIGHT && LaraFloorFront(item, item->pos.yRot + ANGLE(90.0f), 256) >= -384) { item->goalAnimState = LS_JUMP_RIGHT; - Lara.moveAngle = ANGLE(90); + Lara.moveAngle = ANGLE(90.0f); } - else if (TrInput & IN_BACK && LaraFloorFront(item, item->pos.yRot - ANGLE(180.0f), 256) >= -384) + else if (TrInput & IN_ROLL) { - item->goalAnimState = LS_JUMP_BACK; - Lara.moveAngle = ANGLE(180); + item->goalAnimState = LS_JUMP_ROLL_180; } + //else + //{ + // // Cancel jump preparation if the ceiling in a chosen direction is too low. + //} } if (item->fallspeed > LARA_FREEFALL_SPEED) + { item->goalAnimState = LS_FREEFALL; + } } -void lara_col_compress(ITEM_INFO* item, COLL_INFO* coll)//1BD30, 1BE64 (F) +// State: 15 +// State code: lara_as_jump_prepare() +void lara_col_jump_prepare(ITEM_INFO* item, COLL_INFO* coll)//1BD30, 1BE64 (F) { - /*state 15*/ - /*state code: lara_as_compress*/ item->fallspeed = 0; item->gravityStatus = false; coll->badPos = NO_BAD_POS; coll->badNeg = NO_HEIGHT; coll->badCeiling = 0; - coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); - if (!LaraFallen(item, coll)) + if (TestLaraFall(coll)) { - if (coll->midCeiling > -100) - { - item->animNumber = LA_STAND_SOLID; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->goalAnimState = LS_STOP; - item->currentAnimState = LS_STOP; + item->goalAnimState = LS_FALL; + item->fallspeed = 0; + item->gravityStatus = true; - item->speed = 0; - item->fallspeed = 0; - item->gravityStatus = false; + return; + } - item->pos.xPos = coll->old.x; - item->pos.yPos = coll->old.y; - item->pos.zPos = coll->old.z; - } + // G A R B A G E. + // TODO: Dispatch crouch if ceiling lowers. + if (coll->midCeiling > -100) + { + item->animNumber = LA_STAND_SOLID; // <- This anim needs to go!! + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->goalAnimState = LS_STOP; + item->currentAnimState = LS_STOP; - if (coll->midFloor > -256 && coll->midFloor < 256) - item->pos.yPos += coll->midFloor; + item->speed = 0; + item->fallspeed = 0; + item->gravityStatus = false; + + item->pos.xPos = coll->old.x; + item->pos.yPos = coll->old.y; + item->pos.zPos = coll->old.z; + } + + if (coll->midFloor > -256 && coll->midFloor < 256) + { + item->pos.yPos += coll->midFloor; } } -void lara_as_back(ITEM_INFO* item, COLL_INFO* coll)//1A4F0(<), 1A624(<) (F) +// State: 16 +// Collision: lara_col_walk_back() +void lara_as_walk_back(ITEM_INFO* item, COLL_INFO* coll)//1A4F0(<), 1A624(<) (F) { - /*state 16*/ - /*collision: lara_col_back*/ if (item->hitPoints <= 0) { item->goalAnimState = LS_STOP; return; } - if (!Lara.isMoving) + if (Lara.isMoving) { - if ((TrInput & IN_BACK) && ((TrInput & IN_WALK) || Lara.waterStatus == LW_WADE)) - item->goalAnimState = LS_WALK_BACK; - else - item->goalAnimState = LS_STOP; + return; + } - if (TrInput & IN_LEFT) + if (TrInput & IN_LEFT) + { + Lara.turnRate -= LARA_TURN_RATE; + if (Lara.turnRate < ANGLE(-4.0f)) { - Lara.turnRate -= LARA_TURN_RATE; - if (Lara.turnRate < -ANGLE(4.0f)) - Lara.turnRate = -ANGLE(4.0f); - } - else if (TrInput & IN_RIGHT) - { - Lara.turnRate += LARA_TURN_RATE; - if (Lara.turnRate > ANGLE(4.0f)) - Lara.turnRate = ANGLE(4.0f); + Lara.turnRate = ANGLE(-4.0f); } } + else if (TrInput & IN_RIGHT) + { + Lara.turnRate += LARA_TURN_RATE; + if (Lara.turnRate > ANGLE(4.0f)) + { + Lara.turnRate = ANGLE(4.0f); + } + } + + if (TrInput & IN_JUMP) + { + item->goalAnimState = LS_JUMP_PREPARE; // TODO + return; + } + + if (TrInput & IN_BACK && + (TrInput & IN_WALK || Lara.waterStatus == LW_WADE)) + { + item->goalAnimState = LS_WALK_BACK; + return; + } + + item->goalAnimState = LS_STOP; } -void lara_col_back(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +// State: 16 +// State code: lara_as_walk_back() +void lara_col_walk_back(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - /*state 16*/ - /*state code: lara_as_back*/ item->gravityStatus = false; item->fallspeed = 0; - Lara.moveAngle = ANGLE(180); + Lara.moveAngle = ANGLE(180.0f); if (Lara.waterStatus == LW_WADE) + { coll->badPos = NO_BAD_POS; + } else + { coll->badPos = STEPUP_HEIGHT; + } + coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = 0; coll->slopesArePits = true; coll->slopesAreWalls = 1; coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); if (LaraHitCeiling(item, coll)) - return; - - if (LaraDeflectEdge(item, coll)) - LaraCollideStop(item, coll); - - if (LaraFallen(item, coll)) - return; - - if (coll->midFloor > STEP_SIZE / 2 && coll->midFloor < STEPUP_HEIGHT) { - item->goalAnimState = LS_STEP_BACK_DOWN; - GetChange(item, &g_Level.Anims[item->animNumber]); + return; } - if (TestLaraSlide(item, coll)) + if (LaraDeflectEdge(item, coll)) + { + LaraCollideStop(item, coll); + } + + if (TestLaraFall(coll)) + { + item->goalAnimState = LS_FALL; + item->fallspeed = 0; + item->gravityStatus = true; + return; + } + + if (abs(coll->midFloor) > 0 && abs(coll->midFloor <= STEPUP_HEIGHT)) + { + // Like the hop back, step back is also unique. TODO: Make step test/set functions take extra parameters. + if (TestLaraStepDown(coll)) + { + item->pos.yPos += coll->midFloor; + + item->goalAnimState = LS_STEP_BACK_DOWN; + GetChange(item, &g_Level.Anims[item->animNumber]); + } + /*else if (TestLaraStepUp(coll)) + { + item->pos.yPos += coll->midFloor; + + item->goalAnimState = LS_STEP_BACK_UP; + GetChange(item, &g_Level.Anims[item->animNumber]); + }*/ + else if (abs(coll->midFloor) >= 50) + { + item->pos.yPos += 50 * GetSign(coll->midFloor); + } + else + { + item->pos.yPos += coll->midFloor; + } + } + + if (TestLaraSlide(coll)) + { + SetLaraSlide(item, coll); + return; + } #if 0 if (!(g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) || coll->midFloor < 0) + { item->pos.yPos += coll->midFloor; + } else if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP && coll->midFloor) + { item->pos.yPos += SWAMP_GRAVITY; + } #else - if (coll->midFloor != NO_HEIGHT) - item->pos.yPos += coll->midFloor; + //if (coll->midFloor != NO_HEIGHT) + //{ + // item->pos.yPos += coll->midFloor; + //} #endif } -void lara_as_fastturn(ITEM_INFO* item, COLL_INFO* coll)//1A5F8(<), 1A72C(<) (F) +// State: 20 +// Collision: lara_col_fast_turn_right() +void lara_as_turn_right_fast(ITEM_INFO* item, COLL_INFO* coll) { - /*state 20*/ - /*collision: lara_col_fastturn*/ if (item->hitPoints <= 0) { item->goalAnimState = LS_STOP; return; } - if (Lara.turnRate < 0) - { - Lara.turnRate = -LARA_FAST_TURN; + Lara.turnRate = LARA_FAST_TURN; - if (!(TrInput & IN_LEFT)) - item->goalAnimState = LS_STOP; + if (TrInput & IN_JUMP) + { + item->goalAnimState = LS_JUMP_PREPARE; + return; } - else - { - Lara.turnRate = LARA_FAST_TURN; - if (!(TrInput & IN_RIGHT)) - item->goalAnimState = LS_STOP; + if (TrInput & IN_ROLL && Lara.waterStatus != LW_WADE) + { + item->goalAnimState = LS_ROLL_FORWARD; + return; + } + + if (TrInput & IN_DUCK && + Lara.waterStatus != LW_WADE && + (Lara.gunStatus == LG_NO_ARMS || + Lara.gunType == WEAPON_NONE || + Lara.gunType == WEAPON_PISTOLS || + Lara.gunType == WEAPON_REVOLVER || + Lara.gunType == WEAPON_UZI || + Lara.gunType == WEAPON_FLARE)) + { + item->goalAnimState = LS_CROUCH_IDLE; + return; + } + + if (TrInput & IN_FORWARD) + { + if (Lara.waterStatus == LW_WADE) // Failsafe. + { + item->goalAnimState = LS_WADE_FORWARD; + } + else if (TrInput & IN_WALK) + { + item->goalAnimState = LS_WALK_FORWARD; + } + else + { + item->goalAnimState = LS_RUN_FORWARD; + } + + return; + } + + if (!(TrInput & IN_RIGHT)) + { + item->goalAnimState = LS_STOP; + return; } } -void lara_col_fastturn(ITEM_INFO* item, COLL_INFO* coll)//1A65C(<), 1A790(<) (F) +// State: 20 +// State code: lara_as_turn_right_fast() +void lara_col_turn_right_fast(ITEM_INFO* item, COLL_INFO* coll) { - /*state 20*/ - /*state code: lara_as_fastturn*/ - lara_col_stop(item, coll); + lara_col_stop(item, coll); // TODO: Investigate why collision is different to regular turn. } -void lara_as_stepright(ITEM_INFO* item, COLL_INFO* coll)//1A67C(<), 1A7B0(<) (F) +// State: 157 +// State code: lara_as_turn_left_fast() +void lara_as_turn_left_fast(ITEM_INFO* item, COLL_INFO* coll) +{ + if (item->hitPoints <= 0) + { + item->goalAnimState = LS_STOP; + return; + } + + Lara.turnRate = -LARA_FAST_TURN; + + if (TrInput & IN_JUMP) + { + item->goalAnimState = LS_JUMP_PREPARE; + return; + } + + if (TrInput & IN_ROLL && Lara.waterStatus != LW_WADE) + { + item->goalAnimState = LS_ROLL_FORWARD; + return; + } + + if (TrInput & IN_DUCK && + Lara.waterStatus != LW_WADE && + (Lara.gunStatus == LG_NO_ARMS || + Lara.gunType == WEAPON_NONE || + Lara.gunType == WEAPON_PISTOLS || + Lara.gunType == WEAPON_REVOLVER || + Lara.gunType == WEAPON_UZI || + Lara.gunType == WEAPON_FLARE)) + { + item->goalAnimState = LS_CROUCH_IDLE; + return; + } + + if (TrInput & IN_FORWARD) + { + if (Lara.waterStatus == LW_WADE) // Failsafe. + { + item->goalAnimState = LS_WADE_FORWARD; + } + else if (TrInput & IN_WALK) + { + item->goalAnimState = LS_WALK_FORWARD; + } + else + { + item->goalAnimState = LS_RUN_FORWARD; + } + + return; + } + + if (!(TrInput & IN_LEFT)) + { + item->goalAnimState = LS_STOP; + return; + } +} + +// State: 157 +// State code: lara_as_turn_left_fast() +void lara_col_turn_left_fast(ITEM_INFO* item, COLL_INFO* coll) +{ + lara_col_turn_right_fast(item, coll); +} + +// State: 21 +// Collision: lara_col_sidestep() +void lara_as_step_right(ITEM_INFO* item, COLL_INFO* coll)//1A67C(<), 1A7B0(<) (F) { - /*state 21*/ - /*collision: lara_col_stepright*/ Lara.look = false; if (item->hitPoints <= 0) @@ -1366,68 +1936,107 @@ void lara_as_stepright(ITEM_INFO* item, COLL_INFO* coll)//1A67C(<), 1A7B0(<) (F) return; } - if (!Lara.isMoving) + if (Lara.isMoving) { - if (!(TrInput & IN_RSTEP)) - { - item->goalAnimState = LS_STOP; - } + return; + } - if (TrInput & IN_LEFT) + if (TrInput & IN_LEFT) + { + Lara.turnRate -= LARA_TURN_RATE; + if (Lara.turnRate < ANGLE(-4.0f)) { - Lara.turnRate -= LARA_TURN_RATE; - if (Lara.turnRate < -ANGLE(4.0f)) - Lara.turnRate = -ANGLE(4.0f); - } - else if (TrInput & IN_RIGHT) - { - Lara.turnRate += LARA_TURN_RATE; - if (Lara.turnRate > ANGLE(4.0f)) - Lara.turnRate = ANGLE(4.0f); + Lara.turnRate = ANGLE(-4.0f); } } + else if (TrInput & IN_RIGHT) + { + Lara.turnRate += LARA_TURN_RATE; + if (Lara.turnRate > ANGLE(4.0f)) + { + Lara.turnRate = ANGLE(4.0f); + } + } + + if (TrInput & IN_RSTEP) + { + item->goalAnimState = LS_STEP_RIGHT; + return; + } + + item->goalAnimState = LS_STOP; } -void lara_col_stepright(ITEM_INFO* item, COLL_INFO* coll)//1BFB0, 1C0E4 (F) +// State: 21 +// State code: lara_as_step_right() +void lara_col_step_right(ITEM_INFO* item, COLL_INFO* coll)//1BFB0, 1C0E4 (F) { - /*state 21*/ - /*state code: lara_as_stepright*/ - if (item->currentAnimState == LS_STEP_RIGHT) - Lara.moveAngle = ANGLE(90); - else - Lara.moveAngle = -ANGLE(90); + Lara.moveAngle = ANGLE(90.0f); item->gravityStatus = false; item->fallspeed = 0; if (Lara.waterStatus == LW_WADE) + { coll->badPos = NO_BAD_POS; + } else + { coll->badPos = 128; + } coll->slopesAreWalls = true; coll->slopesArePits = true; - coll->badNeg = -128; coll->badCeiling = 0; - coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); - if (!LaraHitCeiling(item, coll)) + if (TestLaraHitCeiling(coll)) { - if (LaraDeflectEdge(item, coll)) - LaraCollideStop(item, coll); + SetLaraHitCeiling(item, coll); + return; + } - if (!LaraFallen(item, coll) && !TestLaraSlide(item, coll) && coll->midFloor != NO_HEIGHT) + if (TestLaraWallDeflect(coll)) + { + SetLaraWallDeflect(item, coll); + LaraCollideStop(item, coll); + } + + if (TestLaraFall(coll)) + { + item->goalAnimState = LS_FALL; + item->fallspeed = 0; + item->gravityStatus = true; + + return; + } + + if (abs(coll->midFloor) > 0 && coll->midFloor != NO_HEIGHT) + { + if (abs(coll->midFloor) >= 50) + { + item->pos.yPos += 50 * GetSign(coll->midFloor); + } + else + { item->pos.yPos += coll->midFloor; + } + } + + if (TestLaraSlide(coll)) + { + SetLaraSlide(item, coll); + return; } } -void lara_as_stepleft(ITEM_INFO* item, COLL_INFO* coll)//1A750(<), 1A884(<) (F) +// State: 22 +// Collision: lara_col_sidestep() +void lara_as_step_left(ITEM_INFO* item, COLL_INFO* coll)//1A750(<), 1A884(<) (F) { - /*state 22*/ - /*collision: lara_col_stepleft*/ Lara.look = false; if (item->hitPoints <= 0) @@ -1436,66 +2045,140 @@ void lara_as_stepleft(ITEM_INFO* item, COLL_INFO* coll)//1A750(<), 1A884(<) (F) return; } - if (!Lara.isMoving) + if (Lara.isMoving) { - if (!(TrInput & IN_LSTEP)) - { - item->goalAnimState = LS_STOP; - } + return; + } - if (TrInput & IN_LEFT) + if (TrInput & IN_LEFT) + { + Lara.turnRate -= LARA_TURN_RATE; + if (Lara.turnRate < -LARA_SLOW_TURN) { - Lara.turnRate -= LARA_TURN_RATE; - if (Lara.turnRate < -LARA_SLOW_TURN) - Lara.turnRate = -LARA_SLOW_TURN; + Lara.turnRate = -LARA_SLOW_TURN; } - else if (TrInput & IN_RIGHT) + } + else if (TrInput & IN_RIGHT) + { + Lara.turnRate += LARA_TURN_RATE; + if (Lara.turnRate > LARA_SLOW_TURN) { - Lara.turnRate += LARA_TURN_RATE; - if (Lara.turnRate > LARA_SLOW_TURN) - Lara.turnRate = LARA_SLOW_TURN; + Lara.turnRate = LARA_SLOW_TURN; } } + + if (TrInput & IN_LSTEP) + { + item->goalAnimState = LS_STEP_LEFT; + return; + } + + item->goalAnimState = LS_STOP; +} + +// State: 22 +// State code: lara_as_step_left() +void lara_col_step_left(ITEM_INFO* item, COLL_INFO* coll)//1BFB0, 1C0E4 (F) +{ + Lara.moveAngle = ANGLE(-90.0f); + + item->gravityStatus = false; + item->fallspeed = 0; + + if (Lara.waterStatus == LW_WADE) + { + coll->badPos = NO_BAD_POS; + } + else + { + coll->badPos = 128; + } + + coll->slopesAreWalls = true; + coll->slopesArePits = true; + coll->badNeg = -128; + coll->badCeiling = 0; + coll->facing = Lara.moveAngle; + + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); + + if (TestLaraHitCeiling(coll)) + { + SetLaraHitCeiling(item, coll); + return; + } + + if (TestLaraWallDeflect(coll)) + { + SetLaraWallDeflect(item, coll); + LaraCollideStop(item, coll); + } + + if (TestLaraFall(coll)) + { + item->goalAnimState = LS_FALL; + item->fallspeed = 0; + item->gravityStatus = true; + + return; + } + + if (abs(coll->midFloor) > 0 && coll->midFloor != NO_HEIGHT) + { + if (abs(coll->midFloor) >= 50) + { + item->pos.yPos += 50 * GetSign(coll->midFloor); + } + else + { + item->pos.yPos += coll->midFloor; + } + } + + if (TestLaraSlide(coll)) + { + SetLaraSlide(item, coll); + return; + } } -void lara_col_stepleft(ITEM_INFO* item, COLL_INFO* coll)//1C0E8(<), 1C21C(<) (F) -{ - /*state 22*/ - /*state code: lara_as_stepleft*/ - lara_col_stepright(item, coll); -} - +// State: 23 +// State code: lara_void_func() void lara_col_roll2(ITEM_INFO* item, COLL_INFO* coll)//1C384, 1C4B8 (F) { - /*state 23*/ - /*state code: lara_void_func*/ Camera.laraNode = 0; - Lara.moveAngle = ANGLE(180); + + Lara.moveAngle = ANGLE(180.0f); + + item->gravityStatus = false; + item->fallspeed = 0; coll->badPos = NO_BAD_POS; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = 0; coll->slopesAreWalls = true; - - item->gravityStatus = false; - item->fallspeed = 0; - coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); if (LaraHitCeiling(item, coll)) + { return; - if (TestLaraSlide(item, coll)) + } + + if (TestLaraSlide(coll)) + { + SetLaraSlide(item, coll); return; + } if (coll->midFloor > 200) { - item->animNumber = LA_FALL_BACK; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->currentAnimState = LS_FALL_BACK; + // TODO: not working? item->goalAnimState = LS_FALL_BACK; item->fallspeed = 0; item->gravityStatus = true; + return; } @@ -1505,78 +2188,136 @@ void lara_col_roll2(ITEM_INFO* item, COLL_INFO* coll)//1C384, 1C4B8 (F) item->pos.yPos += coll->midFloor; } -void lara_as_backjump(ITEM_INFO* item, COLL_INFO* coll)//1A854(<), 1A988(<) (F) +// State: 25 +// Cllision: lara_col_jump_back() +void lara_as_jump_back(ITEM_INFO* item, COLL_INFO* coll)//1A854(<), 1A988(<) (F) { - /*state 25*/ - /*collision: lara_col_backjump*/ Camera.targetAngle = ANGLE(135.0f); - if (item->fallspeed <= LARA_FREEFALL_SPEED) - { - if (item->goalAnimState == LS_RUN_FORWARD) - { - item->goalAnimState = LS_STOP; - } - else if ((TrInput & IN_FORWARD || TrInput & IN_ROLL) && item->goalAnimState != LS_STOP) - { - item->goalAnimState = LS_JUMP_ROLL_180; - } - } - else + Lara.look = false; + + //if (item->hitPoints <= 0) + //{ + // item->goalAnimState = LS_DEATH; + // return; + //} + + if (item->fallspeed > LARA_FREEFALL_SPEED) { item->goalAnimState = LS_FREEFALL; + return; } -} -void lara_col_backjump(ITEM_INFO* item, COLL_INFO* coll)//1C130(<), 1C264(<) (F) -{ - /*state 25*/ - /*state code: lara_as_backjump*/ - Lara.moveAngle = ANGLE(180); - lara_col_jumper(item, coll); -} - -void lara_as_rightjump(ITEM_INFO* item, COLL_INFO* coll)//1A8C4(<), 1A9F8(<) (F) -{ - /*state 26*/ - /*collision: lara_col_rightjump*/ - Lara.look = false; - if (item->fallspeed > LARA_FREEFALL_SPEED) - item->goalAnimState = LS_FREEFALL; - else if (TrInput & IN_LEFT && item->goalAnimState != LS_STOP) + if ((TrInput & IN_ROLL || + TrInput & IN_FORWARD && EnableBackKeyTurn) && + item->goalAnimState != LS_STOP) + { item->goalAnimState = LS_JUMP_ROLL_180; + return; + } + + //item->goalAnimState = LS_JUMP_BACK; } -void lara_col_rightjump(ITEM_INFO* item, COLL_INFO* coll)//1C15C(<), 1C290(<) (F) +// State: 25 +// State code: lara_as_jump_back() +void lara_col_jump_back(ITEM_INFO* item, COLL_INFO* coll)//1C130(<), 1C264(<) (F) { - /*state 26*/ - /*state code: lara_as_rightjump*/ - Lara.moveAngle = ANGLE(90); - lara_col_jumper(item, coll); + Lara.moveAngle = ANGLE(180.0f); + lara_col_jump(item, coll); } -void lara_as_leftjump(ITEM_INFO* item, COLL_INFO* coll)//1A92C(<), 1AA60(<) (F) +// State: 26 +// Collision: lara_col_jump_right() +// +void lara_as_jump_right(ITEM_INFO* item, COLL_INFO* coll)//1A8C4(<), 1A9F8(<) (F) { - /*state 27*/ - /*collision: lara_col_leftjump*/ Lara.look = false; + + //if (item->hitPoints <= 0) + //{ + // item->goalAnimState = LS_DEATH; + // return; + //} + if (item->fallspeed > LARA_FREEFALL_SPEED) + { item->goalAnimState = LS_FREEFALL; - else if (TrInput & IN_RIGHT && item->goalAnimState != LS_STOP) + return; + } + + //if (TrInput & IN_ACTION) + //{ + // item->goalAnimState = LS_REACH; + // return; + //} + + if ((TrInput & IN_ROLL || + TrInput & IN_LEFT && EnableBackKeyTurn) && + item->goalAnimState != LS_STOP) + { item->goalAnimState = LS_JUMP_ROLL_180; + return; + } + + //item->goalAnimState = LS_JUMP_RIGHT; } -void lara_col_leftjump(ITEM_INFO* item, COLL_INFO* coll)//1C188(<), 1C2BC(<) (F) +// State: 26 +// State code: lara_as_jump_right() +void lara_col_jump_right(ITEM_INFO* item, COLL_INFO* coll)//1C15C(<), 1C290(<) (F) { - /*state 27*/ - /*state code: lara_as_leftjump*/ - Lara.moveAngle = -ANGLE(90); - lara_col_jumper(item, coll); + Lara.moveAngle = ANGLE(90.0f); + lara_col_jump(item, coll); } -void lara_col_jumper(ITEM_INFO* item, COLL_INFO* coll) +// State: 27 +// Collision: lara_col_jump_left() +void lara_as_jump_left(ITEM_INFO* item, COLL_INFO* coll)//1A92C(<), 1AA60(<) (F) +{ + Lara.look = false; + + //if (item->hitPoints <= 0) + //{ + // item->goalAnimState = LS_DEATH; + // return; + //} + + if (item->fallspeed > LARA_FREEFALL_SPEED) + { + item->goalAnimState = LS_FREEFALL; + return; + } + + //if (TrInput & IN_ACTION) + //{ + // item->goalAnimState = LS_REACH; + // return; + //} + + if ((TrInput & IN_ROLL || + TrInput & IN_RIGHT && EnableBackKeyTurn) && + item->goalAnimState != LS_STOP) + { + item->goalAnimState = LS_JUMP_ROLL_180; + return; + } + + //item->goalAnimState = LS_JUMP_LEFT; +} + +// State: 27 +// State code: lara_as_jump_left() +void lara_col_jump_left(ITEM_INFO* item, COLL_INFO* coll)//1C188(<), 1C2BC(<) (F) +{ + Lara.moveAngle = ANGLE(-90.0f); + lara_col_jump(item, coll); +} + + +// States: 25, 26, 27 +// State code: none; called in lara_col_jump_back(), lara_col_jump_right(), lara_col_jump_left() +void lara_col_jump(ITEM_INFO* item, COLL_INFO* coll) { - /*states 25, 26, 27*/ - /*state code: none, but is called in lara_col_backjump, lara_col_rightjump and lara_col_leftjump*/ coll->badPos = NO_BAD_POS; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = BAD_JUMP_CEILING; @@ -1588,38 +2329,47 @@ void lara_col_jumper(ITEM_INFO* item, COLL_INFO* coll) if (item->fallspeed > 0 && coll->midFloor <= 0) { if (LaraLandedBad(item, coll)) + { item->goalAnimState = LS_DEATH; + } else + { item->goalAnimState = LS_STOP; + } item->fallspeed = 0; item->gravityStatus = 0; if (coll->midFloor != NO_HEIGHT) + { item->pos.yPos += coll->midFloor; + } } } -void lara_as_upjump(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +// State: 28 +// Collision: lara_col_jump_up() +void lara_as_jump_up(ITEM_INFO* item, COLL_INFO* coll) { - /*state 28*/ - /*collision: lara_col_upjump*/ - if (item->fallspeed > LARA_FREEFALL_SPEED) - { - item->goalAnimState = LS_FREEFALL; - } -} - -void lara_col_upjump(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) -{ - /*state 28*/ - /*state code: lara_as_upjump*/ if (item->hitPoints <= 0) { item->goalAnimState = LS_STOP; return; } + if (item->fallspeed > LARA_FREEFALL_SPEED) + { + item->goalAnimState = LS_FREEFALL; + return; + } + + item->goalAnimState = LS_JUMP_UP; +} + +// State: 28 +// State code: lara_as_jump_up() +void lara_col_jump_up(ITEM_INFO* item, COLL_INFO* coll) +{ Lara.moveAngle = 0; coll->badPos = NO_BAD_POS; @@ -1630,26 +2380,26 @@ void lara_col_upjump(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, 870); - if (TrInput & IN_ACTION && Lara.gunStatus == LG_NO_ARMS && !coll->hitStatic) + if (TrInput & IN_ACTION && + Lara.gunStatus == LG_NO_ARMS && + !coll->hitStatic) { if (Lara.canMonkeySwing && coll->collType == CT_TOP) { + Lara.gunStatus = LG_HANDS_BUSY; + item->goalAnimState = LS_MONKEYSWING_IDLE; - item->currentAnimState = LS_MONKEYSWING_IDLE; - item->animNumber = LA_JUMP_UP_TO_MONKEYSWING; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; item->gravityStatus = false; item->speed = 0; item->fallspeed = 0; - Lara.gunStatus = LG_HANDS_BUSY; - MonkeySwingSnap(item, coll); return; } - if (coll->collType == CT_FRONT && coll->midCeiling <= -STEPUP_HEIGHT) + if (coll->collType == CT_FRONT && + coll->midCeiling <= -STEPUP_HEIGHT) { int edge; int edgeCatch = LaraTestEdgeCatch(item, coll, &edge); @@ -1692,9 +2442,6 @@ void lara_col_upjump(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) } else { - item->animNumber = LA_REACH_TO_HANG; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase + 12; - item->currentAnimState = LS_HANG; item->goalAnimState = LS_HANG; } } @@ -1702,9 +2449,13 @@ void lara_col_upjump(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) bounds = GetBoundsAccurate(item); if (edgeCatch <= 0) + { item->pos.yPos = edge - bounds->Y1 + 4; + } else + { item->pos.yPos += coll->frontFloor - bounds->Y1; + } if (coll->midSplitFloor) { @@ -1741,7 +2492,9 @@ void lara_col_upjump(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) coll->collType == CT_TOP || coll->collType == CT_TOP_FRONT || coll->hitCeiling) + { item->fallspeed = 1; + } if (coll->collType == CT_NONE) { @@ -1770,77 +2523,107 @@ void lara_col_upjump(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) item->fallspeed = 0; if (coll->midFloor != NO_HEIGHT) + { item->pos.yPos += coll->midFloor; + } } } -void lara_as_fallback(ITEM_INFO* item, COLL_INFO* coll)//1959C(<), 196D0(<) (F) +// State: 29 +// Collision: lara_col_fall_back() +void lara_as_fall_back(ITEM_INFO* item, COLL_INFO* coll)//1959C(<), 196D0(<) (F) { - /*state 29*/ - /*collision: lara_col_fallback*/ if (item->fallspeed > LARA_FREEFALL_SPEED) + { item->goalAnimState = LS_FREEFALL; + return; + } - if (TrInput & IN_ACTION) - if (Lara.gunStatus == LG_NO_ARMS) - item->goalAnimState = LS_REACH; + if (TrInput & IN_ACTION && + Lara.gunStatus == LG_NO_ARMS) + { + item->goalAnimState = LS_REACH; + return; + } + + item->goalAnimState = LS_FALL_BACK; } -void lara_col_fallback(ITEM_INFO* item, COLL_INFO* coll)//1C1B4(<), 1C2E8(<) (F) +// State: 29 +// State code: lara_as_fall_back() +void lara_col_fall_back(ITEM_INFO* item, COLL_INFO* coll)//1C1B4(<), 1C2E8(<) (F) { - /*state 29*/ - /*state code: lara_as_fallback*/ - Lara.moveAngle = ANGLE(180); + Lara.moveAngle = ANGLE(180.0f); coll->badPos = NO_BAD_POS; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = BAD_JUMP_CEILING; - coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); LaraDeflectEdgeJump(item, coll); if (item->fallspeed > 0 && coll->midFloor <= 0) { if (LaraLandedBad(item, coll)) + { item->goalAnimState = LS_DEATH; + } else + { item->goalAnimState = LS_STOP; + } item->fallspeed = 0; item->gravityStatus = 0; if (coll->midFloor != NO_HEIGHT) + { item->pos.yPos += coll->midFloor; + } } } +// State: 45 +// State code: lara_void_func() void lara_col_roll(ITEM_INFO* item, COLL_INFO* coll)//1C2B0, 1C3E4 (F) { - /*state 45*/ - /*state code: lara_void_func*/ Lara.moveAngle = 0; + item->gravityStatus = false; + item->fallspeed = 0; + coll->badPos = NO_BAD_POS; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = 0; coll->slopesArePits = false; coll->slopesAreWalls = true; - - item->gravityStatus = false; - item->fallspeed = 0; - coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); if (LaraHitCeiling(item, coll)) + { return; - if (TestLaraSlide(item, coll)) - return; - if (LaraFallen(item, coll)) - return; + } - if (TrInput & IN_FORWARD && item->animNumber == LA_SWANDIVE_ROLL) + if (TestLaraSlide(coll)) + { + SetLaraSlide(item, coll); + return; + } + + if (TestLaraFall(coll)) + { + item->goalAnimState = LS_FALL; + item->fallspeed = 0; + item->gravityStatus = true; + + return; + } + + if (TrInput & IN_FORWARD && + item->animNumber == LA_SWANDIVE_ROLL) { item->goalAnimState = LS_RUN_FORWARD; } @@ -1848,30 +2631,39 @@ void lara_col_roll(ITEM_INFO* item, COLL_INFO* coll)//1C2B0, 1C3E4 (F) ShiftItem(item, coll); if (coll->midFloor != NO_HEIGHT) + { item->pos.yPos += coll->midFloor; + } } -void lara_as_swandive(ITEM_INFO* item, COLL_INFO* coll)//1AE08(<), 1AF3C(<) (F) +// State: 52 +// Collision: lara_col_swandive_start() +void lara_as_swandive_start(ITEM_INFO* item, COLL_INFO* coll)//1AE08(<), 1AF3C(<) (F) { - /*state 52*/ - /*collision: lara_col_swandive*/ coll->enableBaddiePush = true; coll->enableSpaz = false; - if (item->fallspeed > LARA_FREEFALL_SPEED && item->goalAnimState != LS_DIVE) + + if (item->fallspeed > LARA_FREEFALL_SPEED + && item->goalAnimState != LS_DIVE) + { item->goalAnimState = LS_SWANDIVE_END; + return; + } + + item->goalAnimState = LS_SWANDIVE_START; } -void lara_col_swandive(ITEM_INFO* item, COLL_INFO* coll)//1C4A0(<), 1C5D4(<) (F) +// State: 52 +// State code: lara_as_swandive_start() +void lara_col_swandive_start(ITEM_INFO* item, COLL_INFO* coll)//1C4A0(<), 1C5D4(<) (F) { - /*state 52*/ - /*state code: lara_as_swandive*/ Lara.moveAngle = 0; coll->badPos = NO_BAD_POS; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = BAD_JUMP_CEILING; - coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); LaraDeflectEdgeJump(item, coll); @@ -1882,103 +2674,110 @@ void lara_col_swandive(ITEM_INFO* item, COLL_INFO* coll)//1C4A0(<), 1C5D4(<) (F) item->gravityStatus = 0; if (coll->midFloor != NO_HEIGHT) + { item->pos.yPos += coll->midFloor; + } } } -void lara_as_fastdive(ITEM_INFO* item, COLL_INFO* coll)//1AE4C(<), 1AF80(<) (F) +// State: 53 +// Collision: lara_col_swandive_freefall() +void lara_as_swandive_freefall(ITEM_INFO* item, COLL_INFO* coll)//1AE4C(<), 1AF80(<) (F) { - /*state 53*/ - /*collision: lara_col_fastdive*/ - if (TrInput & IN_ROLL && item->goalAnimState == LS_SWANDIVE_END) - item->goalAnimState = LS_JUMP_ROLL_180; + item->speed = (item->speed * 95) / 100; + coll->enableBaddiePush = true; coll->enableSpaz = false; - item->speed = (item->speed * 95) / 100; + + if (TrInput & IN_ROLL || + (TrInput & IN_BACK && EnableBackKeyTurn)) + { + item->goalAnimState = LS_JUMP_ROLL_180; + return; + } + + item->goalAnimState = LS_SWANDIVE_END; } -void lara_col_fastdive(ITEM_INFO* item, COLL_INFO* coll)//1C558(<), 1C68C(<) (F) +// State: 53 +// State code: lara_as_swandive_freefall() +void lara_col_swandive_freefall(ITEM_INFO* item, COLL_INFO* coll)//1C558(<), 1C68C(<) (F) { - /*state 53*/ - /*state code: lara_as_fastdive*/ Lara.moveAngle = 0; coll->badPos = NO_BAD_POS; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = BAD_JUMP_CEILING; - coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); LaraDeflectEdgeJump(item, coll); if (coll->midFloor <= 0 && item->fallspeed > 0) { if (item->fallspeed <= 133) + { item->goalAnimState = LS_STOP; + } else + { item->goalAnimState = LS_DEATH; + } item->fallspeed = 0; item->gravityStatus = 0; if (coll->midFloor != NO_HEIGHT) + { item->pos.yPos += coll->midFloor; + } } } +// State: 54 +// Collision: lara_default_col() void lara_as_gymnast(ITEM_INFO* item, COLL_INFO* coll)//1AEC8(<), 1AFFC(<) (F) { - /*state 54*/ - /*collision: lara_default_col*/ coll->enableBaddiePush = false; coll->enableSpaz = false; } +// State: 65 +// Collision: lara_col_wade() void lara_as_wade(ITEM_INFO* item, COLL_INFO* coll)//1AF10, 1B044 (F) { - /*state 65*/ - /*collision: lara_col_wade*/ + Camera.targetElevation = ANGLE(-22.0f); + if (item->hitPoints <= 0) { item->goalAnimState = LS_STOP; return; } - Camera.targetElevation = -ANGLE(22.0f); - if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) { if (TrInput & IN_LEFT) { Lara.turnRate -= LARA_TURN_RATE; - if (Lara.turnRate < -(LARA_FAST_TURN >> 1)) - Lara.turnRate = -(LARA_FAST_TURN >> 1); - - if (TestLaraLean(item, coll)) + if (Lara.turnRate < -(LARA_FAST_TURN / 2)) { - item->pos.zRot -= LARA_LEAN_RATE; - if (item->pos.zRot < -(LARA_LEAN_MAX >> 1)) - item->pos.zRot = -(LARA_LEAN_MAX >> 1); + Lara.turnRate = -(LARA_FAST_TURN / 2); } } else if (TrInput & IN_RIGHT) { Lara.turnRate += LARA_TURN_RATE; - if (Lara.turnRate > (LARA_FAST_TURN >> 1)) - Lara.turnRate = (LARA_FAST_TURN >> 1); - - if (TestLaraLean(item, coll)) + if (Lara.turnRate > (LARA_FAST_TURN / 2)) { - item->pos.zRot += LARA_LEAN_RATE; - if (item->pos.zRot > (LARA_LEAN_MAX >> 1)) - item->pos.zRot = (LARA_LEAN_MAX >> 1); + Lara.turnRate = (LARA_FAST_TURN / 2); } } if (TrInput & IN_FORWARD) + { item->goalAnimState = LS_WADE_FORWARD; - else - item->goalAnimState = LS_STOP; + return; + } } else { @@ -1986,262 +2785,468 @@ void lara_as_wade(ITEM_INFO* item, COLL_INFO* coll)//1AF10, 1B044 (F) { Lara.turnRate -= LARA_TURN_RATE; if (Lara.turnRate < -LARA_FAST_TURN) - Lara.turnRate = -LARA_FAST_TURN; - - if (TestLaraLean(item, coll)) { - item->pos.zRot -= LARA_LEAN_RATE; - if (item->pos.zRot < -LARA_LEAN_MAX) - item->pos.zRot = -LARA_LEAN_MAX; + Lara.turnRate = -LARA_FAST_TURN; } } else if (TrInput & IN_RIGHT) { Lara.turnRate += LARA_TURN_RATE; if (Lara.turnRate > LARA_FAST_TURN) - Lara.turnRate = LARA_FAST_TURN; - - if (TestLaraLean(item, coll)) { - item->pos.zRot += LARA_LEAN_RATE; - if (item->pos.zRot > LARA_LEAN_MAX) - item->pos.zRot = LARA_LEAN_MAX; + Lara.turnRate = LARA_FAST_TURN; } } if (TrInput & IN_FORWARD) { if (Lara.waterStatus == LW_ABOVE_WATER) + { item->goalAnimState = LS_RUN_FORWARD; + } else + { item->goalAnimState = LS_WADE_FORWARD; - } - else - { - item->goalAnimState = LS_STOP; + } + + return; } } + + item->goalAnimState = LS_STOP; } +// State: 65 +// State code: lara_as_wade() void lara_col_wade(ITEM_INFO* item, COLL_INFO* coll) { - /*state 65*/ - /*state code: lara_as_wade*/ Lara.moveAngle = 0; coll->badPos = NO_BAD_POS; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = 0; - coll->slopesAreWalls = true; - coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); - if (LaraHitCeiling(item, coll)) - return; + if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) + { + if (TrInput & IN_LEFT) + { + if (TestLaraLean(coll)) + { + item->pos.zRot -= LARA_LEAN_RATE; + if (item->pos.zRot < -(LARA_LEAN_MAX / 2)) + { + item->pos.zRot = -(LARA_LEAN_MAX / 2); + } + } + } + else if (TrInput & IN_RIGHT) + { + if (TestLaraLean(coll)) + { + item->pos.zRot += LARA_LEAN_RATE; + if (item->pos.zRot > (LARA_LEAN_MAX / 2)) + { + item->pos.zRot = (LARA_LEAN_MAX / 2); + } + } + } + } + else + { + if (TrInput & IN_LEFT) + { + if (TestLaraLean(coll)) + { + item->pos.zRot -= LARA_LEAN_RATE; + if (item->pos.zRot < -LARA_LEAN_MAX) + { + item->pos.zRot = -LARA_LEAN_MAX; + } + } + } + else if (TrInput & IN_RIGHT) + { + if (TestLaraLean(coll)) + { + item->pos.zRot += LARA_LEAN_RATE; + if (item->pos.zRot > LARA_LEAN_MAX) + { + item->pos.zRot = LARA_LEAN_MAX; + } + } + } + } if (TestLaraVault(item, coll)) + { return; + } + + if (LaraHitCeiling(item, coll)) + { + return; + } if (LaraDeflectEdge(item, coll)) { item->pos.zRot = 0; - if ((coll->frontType == WALL || coll->frontType == SPLIT_TRI) && coll->frontFloor < -((STEP_SIZE * 5) / 2) && !(g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP)) + if ((coll->frontType == WALL || coll->frontType == SPLIT_TRI) && + coll->frontFloor < -((STEP_SIZE * 5) / 2) && + !(g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP)) { item->goalAnimState = LS_SPLAT; if (GetChange(item, &g_Level.Anims[item->animNumber])) + { return; + } } LaraCollideStop(item, coll); } - - if (coll->midFloor >= -STEPUP_HEIGHT && coll->midFloor < -STEP_SIZE / 2 && !(g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP)) + if (abs(coll->midFloor) > 0 && abs(coll->midFloor <= STEPUP_HEIGHT) && + !(g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP)) { - item->goalAnimState = LS_STEP_UP; - GetChange(item, &g_Level.Anims[item->animNumber]); + //DoLaraStep(item, coll); // Uncomment this line and remove everything below when a step down anim is created. + + /*if (TestLaraStepDown(coll)) + { + item->pos.yPos += coll->midFloor; + + item->goalAnimState = LS_STEP_DOWN; + GetChange(item, &g_Level.Anims[item->animNumber]); + } + else */if (TestLaraStepUp(coll)) + { + item->pos.yPos += coll->midFloor; + + item->goalAnimState = LS_STEP_UP; + GetChange(item, &g_Level.Anims[item->animNumber]); + } + else if (abs(coll->midFloor) >= 50) + { + item->pos.yPos += 50 * GetSign(coll->midFloor); + } + else + { + item->pos.yPos += coll->midFloor; + } } - if (coll->midFloor >= 50 && !(g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP)) + /*if (!(g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) || coll->midFloor < 0) { - item->pos.yPos += 50; - return; - } - - if (!(g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) || coll->midFloor < 0) item->pos.yPos += coll->midFloor; // Enforce to floor height.. if not a swamp room. - else if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP && coll->midFloor) + } + else */if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP && coll->midFloor) + { item->pos.yPos += SWAMP_GRAVITY; + } } -void lara_as_dash(ITEM_INFO* item, COLL_INFO* coll)//15A28, 15B5C (F) +// State: 73 +// Collision: lara_col_sprint() +void lara_as_sprint(ITEM_INFO* item, COLL_INFO* coll)//15A28, 15B5C (F) { - /*state 73*/ - /*collision: lara_col_dash*/ - if (item->hitPoints <= 0 || !DashTimer || !(TrInput & IN_SPRINT) || Lara.waterStatus == LW_WADE) + if (item->hitPoints <= 0) { - item->goalAnimState = LS_RUN_FORWARD; - return; - } - - DashTimer--; - - if (TrInput & IN_DUCK - && (Lara.gunStatus == LG_NO_ARMS - || Lara.gunType == WEAPON_NONE - || Lara.gunType == WEAPON_PISTOLS - || Lara.gunType == WEAPON_REVOLVER - || Lara.gunType == WEAPON_UZI - || Lara.gunType == WEAPON_FLARE)) - { - item->goalAnimState = LS_CROUCH_IDLE; + item->goalAnimState = LS_RUN_FORWARD; // item->goalAnimState = LS_DEATH; return; } if (TrInput & IN_LEFT) { Lara.turnRate -= LARA_TURN_RATE; - if (Lara.turnRate < -ANGLE(4.0f)) - Lara.turnRate = -ANGLE(4.0f); - - item->pos.zRot -= ANGLE(1.5f); - if (item->pos.zRot < -ANGLE(16.0f)) - item->pos.zRot = -ANGLE(16.0f); + if (Lara.turnRate < ANGLE(-4.0f)) + { + Lara.turnRate = ANGLE(-4.0f); + } } else if (TrInput & IN_RIGHT) { Lara.turnRate += LARA_TURN_RATE; if (Lara.turnRate > ANGLE(4.0f)) + { Lara.turnRate = ANGLE(4.0f); - - item->pos.zRot += ANGLE(1.5f); - if (item->pos.zRot > ANGLE(16.0f)) - item->pos.zRot = ANGLE(16.0f); - } - - if (!(TrInput & IN_JUMP) || item->gravityStatus) - { - if (TrInput & IN_FORWARD) - { - if (TrInput & IN_WALK) - item->goalAnimState = LS_WALK_FORWARD; - else - item->goalAnimState = LS_SPRINT; - } - else if (!(TrInput & IN_LEFT) && !(TrInput & IN_RIGHT)) - { - item->goalAnimState = LS_STOP; } } - else + + if (TrInput & IN_JUMP || item->gravityStatus) { - item->goalAnimState = LS_SPRINT_ROLL; + if (LaraFloorFront(item, item->pos.yRot, 1600) >= 384) // Something fun. However, the range should be probed rather than the final location. + { + item->goalAnimState = LS_SWANDIVE_START; + } + else + { + item->goalAnimState = LS_SPRINT_ROLL; + } + + return; } + + if (TrInput & IN_DUCK && + (Lara.gunStatus == LG_NO_ARMS || + Lara.gunType == WEAPON_NONE || + Lara.gunType == WEAPON_PISTOLS || + Lara.gunType == WEAPON_REVOLVER || + Lara.gunType == WEAPON_UZI || + Lara.gunType == WEAPON_FLARE)) + { + item->goalAnimState = LS_CROUCH_IDLE; + return; + } + + if (!(TrInput & IN_SPRINT) || !DashTimer || + Lara.waterStatus == LW_WADE) + { + item->goalAnimState = LS_RUN_FORWARD; + return; + } + + DashTimer--; + + if (TrInput & IN_FORWARD) + { + if (TrInput & IN_WALK) + { + item->goalAnimState = LS_WALK_FORWARD; + } + else + { + item->goalAnimState = LS_SPRINT; + } + + return; + } + + // Legacy doesn't require FORWARD to be held when sprinting. Keep original behaviour? + //if (TrInput & IN_LEFT || TrInput & IN_RIGHT) + //{ + // item->goalAnimState = LS_SPRINT; + // return; + //} + + item->goalAnimState = LS_STOP; } -void lara_col_dash(ITEM_INFO* item, COLL_INFO* coll)//15C50, 15D84 (F) +// State: 73 +// State code: lara_as_sprint() +void lara_col_sprint(ITEM_INFO* item, COLL_INFO* coll)//15C50, 15D84 (F) { - /*state 73*/ - /*state code: lara_as_dash*/ Lara.moveAngle = 0; coll->badPos = NO_BAD_POS; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = 0; - coll->slopesAreWalls = true; - coll->facing = Lara.moveAngle; - GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); - if (!LaraHitCeiling(item, coll) && !TestLaraVault(item, coll)) + if (TrInput & IN_LEFT) { - if (LaraDeflectEdge(item, coll)) + if (TestLaraLean(coll)) { - item->pos.zRot = 0; - - if (TestWall(item, 256, 0, -640)) + item->pos.zRot -= ANGLE(1.5f); + if (item->pos.zRot < ANGLE(-16.0f)) { - item->goalAnimState = LS_SPLAT; - if (GetChange(item, &g_Level.Anims[item->animNumber])) - { - item->currentAnimState = LS_SPLAT; - return; - } - } - - LaraCollideStop(item, coll); - } - - if (!LaraFallen(item, coll)) - { - if (coll->midFloor >= -STEPUP_HEIGHT && coll->midFloor < -STEP_SIZE / 2) - { - item->goalAnimState = LS_STEP_UP; - GetChange(item, &g_Level.Anims[item->animNumber]); - } - - if (!TestLaraSlide(item, coll)) - { - if (coll->midFloor < 50) - { - if (coll->midFloor != NO_HEIGHT) - item->pos.yPos += coll->midFloor; - } - else - { - item->goalAnimState = LS_STEP_DOWN; // for theoretical sprint stepdown anims, not in default anims - if (GetChange(item, &g_Level.Anims[item->animNumber])) - item->pos.yPos += coll->midFloor; // move Lara to midFloor - else - item->pos.yPos += 50; // do the default aligment - } + item->pos.zRot = ANGLE(-16.0f); } } } + else if (TrInput & IN_RIGHT) + { + item->pos.zRot += ANGLE(1.5f); + if (item->pos.zRot > ANGLE(16.0f)) + { + item->pos.zRot = ANGLE(16.0f); + } + } + + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); + + if (TestLaraVault(item, coll)) + { + return; + } + + if (TestLaraHitCeiling(coll)) + { + SetLaraHitCeiling(item, coll); + return; + } + + if (LaraDeflectEdge(item, coll)) + { + item->pos.zRot = 0; + + if (TestWall(item, 256, 0, -640)) + { + item->goalAnimState = LS_SPLAT; + if (GetChange(item, &g_Level.Anims[item->animNumber])) + { + item->currentAnimState = LS_SPLAT; + return; + } + } + + LaraCollideStop(item, coll); + } + + if (TestLaraFall(coll)) + { + item->goalAnimState = LS_FALL; + item->fallspeed = 0; + item->gravityStatus = true; + + return; + } + + // TODO: Step dispatches are the normal run step up anims. This is why Lara sprints up stairs like a dolt. + if (abs(coll->midFloor) > 0 && abs(coll->midFloor <= STEPUP_HEIGHT)) + { + /*if (TestLaraStepDown(coll)) + { + item->pos.yPos += coll->midFloor; + + item->goalAnimState = LS_STEP_DOWN; + GetChange(item, &g_Level.Anims[item->animNumber]); + } + else */if (TestLaraStepUp(coll)) + { + item->pos.yPos += coll->midFloor; + + item->goalAnimState = LS_STEP_UP; + GetChange(item, &g_Level.Anims[item->animNumber]); + } + else if (abs(coll->midFloor) >= 50) + { + item->pos.yPos += 50 * GetSign(coll->midFloor); + } + else + { + item->pos.yPos += coll->midFloor; + } + } + + if (TestLaraSlide(coll)) + { + SetLaraSlide(item, coll); + return; + } } -void lara_as_dashdive(ITEM_INFO* item, COLL_INFO* coll)//15E1C(<), 15F50(<) (F) +// State: 74 +// Collision: lara_col_sprint_roll() +void lara_as_sprint_roll(ITEM_INFO* item, COLL_INFO* coll)//15E1C(<), 15F50(<) (F) { - /*state 74*/ - /*collision: lara_col_dashdive*/ - if (item->goalAnimState != LS_DEATH && - item->goalAnimState != LS_STOP && - item->goalAnimState != LS_RUN_FORWARD && - item->fallspeed > LARA_FREEFALL_SPEED) - item->goalAnimState = LS_FREEFALL; + //if (item->hitPoints <= 0) + //{ + // item->goalAnimState = LS_DEATH; + // return; + //} + + if (TrInput & IN_LEFT) + { + Lara.turnRate -= LARA_TURN_RATE; + if (Lara.turnRate < ANGLE(-4.0f)) + { + Lara.turnRate = ANGLE(-4.0f); + } + } + else if (TrInput & IN_RIGHT) + { + Lara.turnRate += LARA_TURN_RATE; + if (Lara.turnRate > ANGLE(4.0f)) + { + Lara.turnRate = ANGLE(4.0f); + } + } + + if (TrInput & IN_FORWARD) // Not necessary... + { + item->goalAnimState = LS_RUN_FORWARD; + return; + } + + item->goalAnimState = LS_STOP; + + //LEGACY. + //if (item->goalAnimState != LS_DEATH && + // item->goalAnimState != LS_STOP && + // item->goalAnimState != LS_RUN_FORWARD && + // item->fallspeed > LARA_FREEFALL_SPEED) + //{ + // item->goalAnimState = LS_FREEFALL; // Hmm? It's not possible to go into a freefall from this state. + //} } -void lara_col_dashdive(ITEM_INFO* item, COLL_INFO* coll)//15E5C, 15F90 (F) +// State: 74 +// State code: lara_as_sprint_dive() +void lara_col_sprint_roll(ITEM_INFO* item, COLL_INFO* coll)//15E5C, 15F90 (F) { - /*state 74*/ - /*state code: lara_as_dashdive*/ - if (item->speed < 0) - Lara.moveAngle = ANGLE(180); + if (item->speed < 0) // Is this necessary?? + { + Lara.moveAngle = ANGLE(180.0f); + } else + { Lara.moveAngle = 0; + } coll->badPos = NO_BAD_POS; coll->badNeg = -256; coll->badCeiling = BAD_JUMP_CEILING; - coll->slopesAreWalls = true; - coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); LaraDeflectEdgeJump(item, coll); - if (!LaraFallen(item, coll)) + if (TrInput & IN_LEFT) { + if (TestLaraLean(coll)) + { + item->pos.zRot -= ANGLE(1.5f); + if (item->pos.zRot < ANGLE(-16.0f)) + { + item->pos.zRot = ANGLE(-16.0f); + } + } + } + else if (TrInput & IN_RIGHT) + { + item->pos.zRot += ANGLE(1.5f); + if (item->pos.zRot > ANGLE(16.0f)) + { + item->pos.zRot = ANGLE(16.0f); + } + } + + if (TestLaraFall(coll)) + { + item->goalAnimState = LS_FALL; + item->fallspeed = 0; + item->gravityStatus = true; + + return; + if (item->speed < 0) + { Lara.moveAngle = 0; + } if (coll->midFloor <= 0 && item->fallspeed > 0) { + item->gravityStatus = false; + item->fallspeed = 0; + item->pos.yPos += coll->midFloor; + item->speed = 0; + if (LaraLandedBad(item, coll)) { item->goalAnimState = LS_DEATH; @@ -2255,17 +3260,14 @@ void lara_col_dashdive(ITEM_INFO* item, COLL_INFO* coll)//15E5C, 15F90 (F) item->goalAnimState = LS_RUN_FORWARD; } - item->gravityStatus = false; - item->fallspeed = 0; - item->pos.yPos += coll->midFloor; - item->speed = 0; - AnimateLara(item); } ShiftItem(item, coll); if (coll->midFloor != NO_HEIGHT) + { item->pos.yPos += coll->midFloor; + } } } diff --git a/TR5Main/Game/Lara/lara_basic.h b/TR5Main/Game/Lara/lara_basic.h index 48b4d4c8a..d359cd79b 100644 --- a/TR5Main/Game/Lara/lara_basic.h +++ b/TR5Main/Game/Lara/lara_basic.h @@ -1,71 +1,76 @@ #pragma once #include "lara_struct.h" -/*generic functions*/ +// Auxiliary functions. +bool TestLaraStepDown(COLL_INFO* coll); +bool TestLaraStepUp(COLL_INFO* coll); +void DoLaraStep(ITEM_INFO* item, COLL_INFO* coll); + +// General control & collision functions. void lara_void_func(ITEM_INFO* item, COLL_INFO* coll); void lara_default_col(ITEM_INFO* item, COLL_INFO* coll); void lara_as_special(ITEM_INFO* item, COLL_INFO* coll); void lara_as_null(ITEM_INFO* item, COLL_INFO* coll); void lara_as_controlled(ITEM_INFO* item, COLL_INFO* coll); void lara_as_controlledl(ITEM_INFO* item, COLL_INFO* coll); -/*end generic functions*/ -/*-*/ -/*basic movement*/ -void lara_as_walk(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_walk(ITEM_INFO* item, COLL_INFO* coll); + +// Basic movement control & collision functions. +void lara_as_walk_forward(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_walk_forward(ITEM_INFO* item, COLL_INFO* coll); void lara_as_run(ITEM_INFO* item, COLL_INFO* coll); void lara_col_run(ITEM_INFO* item, COLL_INFO* coll); void lara_as_stop(ITEM_INFO* item, COLL_INFO* coll); void lara_col_stop(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_forwardjump(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_forwardjump(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_jump_forward(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_jump_forward(ITEM_INFO* item, COLL_INFO* coll); void lara_col_pose(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_fastback(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_fastback(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_turn_r(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_turn_r(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_turn_l(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_turn_l(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_hop_back(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_hop_back(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_turn_right(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_turn_right(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_turn_left(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_turn_left(ITEM_INFO* item, COLL_INFO* coll); void lara_as_death(ITEM_INFO* item, COLL_INFO* coll); void lara_col_death(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_fastfall(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_fastfall(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_freefall(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_freefall(ITEM_INFO* item, COLL_INFO* coll); void lara_as_reach(ITEM_INFO* item, COLL_INFO* coll); void lara_col_reach(ITEM_INFO* item, COLL_INFO* coll); void lara_as_splat(ITEM_INFO* item, COLL_INFO* coll); void lara_col_splat(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_land(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_compress(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_compress(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_back(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_back(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_fastturn(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_fastturn(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_stepright(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_stepright(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_stepleft(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_stepleft(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_jump_prepare(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_jump_prepare(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_walk_back(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_walk_back(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_turn_right_fast(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_turn_right_fast(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_turn_left_fast(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_turn_left_fast(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_step_right(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_step_right(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_step_left(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_step_left(ITEM_INFO* item, COLL_INFO* coll); void lara_col_roll2(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_backjump(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_backjump(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_rightjump(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_rightjump(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_leftjump(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_leftjump(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_jumper(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_upjump(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_upjump(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_fallback(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_fallback(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_jump_back(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_jump_back(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_jump_right(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_jump_right(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_jump_left(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_jump_left(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_jump(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_jump_up(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_jump_up(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_fall_back(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_fall_back(ITEM_INFO* item, COLL_INFO* coll); void lara_col_roll(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_swandive(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_swandive(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_fastdive(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_fastdive(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_swandive_start(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_swandive_start(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_swandive_freefall(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_swandive_freefall(ITEM_INFO* item, COLL_INFO* coll); void lara_as_gymnast(ITEM_INFO* item, COLL_INFO* coll); void lara_as_wade(ITEM_INFO* item, COLL_INFO* coll); void lara_col_wade(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_dash(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_dash(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_dashdive(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_dashdive(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_sprint(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_sprint(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_sprint_roll(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_sprint_roll(ITEM_INFO* item, COLL_INFO* coll); diff --git a/TR5Main/Game/Lara/lara_cheat.cpp b/TR5Main/Game/Lara/lara_cheat.cpp index fb5c249db..188553ea7 100644 --- a/TR5Main/Game/Lara/lara_cheat.cpp +++ b/TR5Main/Game/Lara/lara_cheat.cpp @@ -7,34 +7,37 @@ #include "effect2.h" #include "sound.h" - extern GameFlow* g_GameFlow; int NoCheatCounter; -void lara_as_swimcheat(ITEM_INFO* item, COLL_INFO* coll)//4C3A8, 4C80C (F) +void lara_as_swim_cheat(ITEM_INFO* item, COLL_INFO* coll)//4C3A8, 4C80C (F) { if (TrInput & IN_FORWARD) { - item->pos.xRot -= ANGLE(3); + item->pos.xRot -= ANGLE(3.0f); } else if (TrInput & IN_BACK) { - item->pos.xRot += ANGLE(3); + item->pos.xRot += ANGLE(3.0f); } if (TrInput & IN_LEFT) { Lara.turnRate -= 613; - if (Lara.turnRate < -ANGLE(6)) - Lara.turnRate = -ANGLE(6); + if (Lara.turnRate < ANGLE(-6.0f)) + { + Lara.turnRate = ANGLE(-6.0f); + } } else if (TrInput & IN_RIGHT) { Lara.turnRate += 613; - if (Lara.turnRate > ANGLE(6)) - Lara.turnRate = ANGLE(6); + if (Lara.turnRate > ANGLE(6.0f)) + { + Lara.turnRate = ANGLE(6.0f); + } } if (TrInput & IN_ACTION) @@ -44,7 +47,7 @@ void lara_as_swimcheat(ITEM_INFO* item, COLL_INFO* coll)//4C3A8, 4C80C (F) if (TrInput & IN_OPTION) { - Lara.turnRate = -ANGLE(12); + Lara.turnRate = ANGLE(-12.0f); } if (TrInput & IN_JUMP) @@ -52,14 +55,20 @@ void lara_as_swimcheat(ITEM_INFO* item, COLL_INFO* coll)//4C3A8, 4C80C (F) item->fallspeed += 16; if (item->fallspeed > 400) + { item->fallspeed = 400; + } } else { if (item->fallspeed >= 8) + { item->fallspeed -= item->fallspeed >> 3; + } else + { item->fallspeed = 0; + } } } @@ -71,10 +80,9 @@ void LaraCheatyBits() // (F) (D) { if (Lara.Vehicle == NO_ITEM) { - LaraCheatGetStuff(); - DelsGiveLaraItemsCheat(); + GiveLaraItemsCheat(); LaraItem->pos.yPos -= 128; @@ -105,7 +113,9 @@ void LaraCheatyBits() // (F) (D) } } if (NoCheatCounter) + { NoCheatCounter--; + } } void LaraCheatGetStuff() // (F) (D) @@ -115,10 +125,14 @@ void LaraCheatGetStuff() // (F) (D) Lara.NumLargeMedipacks = -1; if (Objects[ID_CROWBAR_ITEM].loaded) + { Lara.Crowbar = true; + } if (Objects[ID_LASERSIGHT_ITEM].loaded) + { Lara.Lasersight = true; + } if (Objects[ID_REVOLVER_ITEM].loaded) { @@ -198,7 +212,7 @@ void LaraCheatGetStuff() // (F) (D) g_Inventory.LoadObjects(false); } -void DelsGiveLaraItemsCheat() // (AF) (D) +void GiveLaraItemsCheat() // (AF) (D) { int i; diff --git a/TR5Main/Game/Lara/lara_cheat.h b/TR5Main/Game/Lara/lara_cheat.h index 845228de8..f1a525603 100644 --- a/TR5Main/Game/Lara/lara_cheat.h +++ b/TR5Main/Game/Lara/lara_cheat.h @@ -1,7 +1,6 @@ #pragma once - -void lara_as_swimcheat(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_swim_cheat(ITEM_INFO* item, COLL_INFO* coll); void LaraCheatyBits(); void LaraCheatGetStuff(); -void DelsGiveLaraItemsCheat(); +void GiveLaraItemsCheat(); diff --git a/TR5Main/Game/Lara/lara_climb.cpp b/TR5Main/Game/Lara/lara_climb.cpp index e5dfce32e..a340ab856 100644 --- a/TR5Main/Game/Lara/lara_climb.cpp +++ b/TR5Main/Game/Lara/lara_climb.cpp @@ -8,6 +8,12 @@ #include "level.h" #include "input.h" +// LADDER CLIMBING + +// ------------------------------ +// Auxiliary Functions +// ------------------------------ + short LeftIntRightExtTab[4] = // offset 0xA0B7C { 0x0800, 0x0100, 0x0200, 0x0400 @@ -37,25 +43,106 @@ short GetClimbTrigger(int x, int y, int z, short roomNumber) // (F) (D) return (*data & DATA_TYPE) == CLIMB_TYPE ? *data : 0; } -void lara_col_climbend(ITEM_INFO* item, COLL_INFO* coll)//46E30(<), 47294(<) (F) +bool TestLaraLetGo(ITEM_INFO* item) { - return; + if (((TrInput & IN_ACTION && !EnableActionToggle) || + (!(TrInput & IN_ACTION) && EnableActionToggle)) && // TODO: Instead, check if button has been RELEASED. + item->hitPoints > 0) + { + return false; + } + + return true; } +void SetLaraLetGo(ITEM_INFO* item, COLL_INFO* coll) +{ + item->gravityStatus = false; + item->fallspeed = 0; + + short roomNumber = item->roomNumber; + FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); + GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos); + + Lara.gunStatus = LG_NO_ARMS; + Lara.torsoYrot = 0; + Lara.torsoXrot = 0; + Lara.headYrot = 0; + Lara.headXrot = 0; + + item->goalAnimState = LS_JUMP_FORWARD; + item->currentAnimState = LS_JUMP_FORWARD; + item->animNumber = LA_FALL_START; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->speed = 2; + item->gravityStatus = true; + item->fallspeed = 1; + + coll->trigger = TriggerIndex; +} + +// TODO: delete. +int LaraCheckForLetGo(ITEM_INFO* item, COLL_INFO* coll)//45434, 45898 (F) +{ + short roomNumber = item->roomNumber; + + item->gravityStatus = false; + item->fallspeed = 0; + + GetFloorHeight(GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber), + item->pos.xPos, item->pos.yPos, item->pos.zPos); + + coll->trigger = TriggerIndex; + + if (TrInput & IN_ACTION && item->hitPoints > 0) + return 0; + + Lara.torsoYrot = 0; + Lara.torsoXrot = 0; + + Lara.headYrot = 0; + Lara.headXrot = 0; + + item->goalAnimState = LS_JUMP_FORWARD; + item->currentAnimState = LS_JUMP_FORWARD; + item->animNumber = LA_FALL_START; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + + item->speed = 2; + item->gravityStatus = true; + item->fallspeed = 1; + + Lara.gunStatus = LG_NO_ARMS; + + return 1; +} + +// ------------------------------ +// LADDER CLIMBING +// State & Collision Functions +// ------------------------------ + void lara_as_climbend(ITEM_INFO* item, COLL_INFO* coll)//46DF8(<), 4725C(<) (F) { coll->enableBaddiePush = false; coll->enableSpaz = false; Camera.flags = CF_FOLLOW_CENTER; - Camera.targetAngle = -ANGLE(45); + Camera.targetAngle = ANGLE(-45.0f); +} + +void lara_col_climbend(ITEM_INFO* item, COLL_INFO* coll)//46E30(<), 47294(<) (F) +{ + return; } void lara_col_climbdown(ITEM_INFO* item, COLL_INFO* coll)//46BD0, 47034 (F) { - if (LaraCheckForLetGo(item, coll) - || item->animNumber != LA_LADDER_DOWN) + if (TestLaraLetGo(item) || item->animNumber != LA_LADDER_DOWN) + { + SetLaraLetGo(item, coll); return; + } int frame = item->frameNumber - g_Level.Anims[LA_LADDER_DOWN].frameBase; int xShift; @@ -214,10 +301,10 @@ void lara_col_climbing(ITEM_INFO* item, COLL_INFO* coll)//469B0, 46E14 (F) void lara_as_climbing(ITEM_INFO* item, COLL_INFO* coll)//46984(<), 46DE8(<) (F) { + Camera.targetElevation = ANGLE(30.0f); + coll->enableBaddiePush = false; coll->enableSpaz = false; - - Camera.targetElevation = ANGLE(30); } void lara_col_climbright(ITEM_INFO* item, COLL_INFO* coll)//46908(<), 46D6C(<) (F) @@ -235,8 +322,8 @@ void lara_as_climbright(ITEM_INFO* item, COLL_INFO* coll)//468B8(<), 46D1C(<) (F coll->enableBaddiePush = false; coll->enableSpaz = false; - Camera.targetAngle = ANGLE(30); - Camera.targetElevation = -ANGLE(15); + Camera.targetAngle = ANGLE(30.0f); + Camera.targetElevation = ANGLE(-15.0f); if (!(TrInput & (IN_RIGHT | IN_RSTEP))) item->goalAnimState = LS_LADDER_IDLE; @@ -247,7 +334,7 @@ void lara_col_climbleft(ITEM_INFO* item, COLL_INFO* coll)//46834(<), 46C98(<) (F if (!LaraCheckForLetGo(item, coll)) { int shift = 0; - Lara.moveAngle = -ANGLE(90); + Lara.moveAngle = ANGLE(90.0f); LaraDoClimbLeftRight(item, coll, LaraTestClimbPos(item, coll->radius, -(coll->radius + 120), -512, 512, &shift), shift); } } @@ -257,8 +344,8 @@ void lara_as_climbleft(ITEM_INFO* item, COLL_INFO* coll)//467E4(<), 46C48(<) (F) coll->enableBaddiePush = false; coll->enableSpaz = false; - Camera.targetAngle = -ANGLE(30); - Camera.targetElevation = -ANGLE(15); + Camera.targetAngle = ANGLE(30.0f); + Camera.targetElevation = ANGLE(15.0f); if (!(TrInput & (IN_LEFT | IN_LSTEP))) item->goalAnimState = LS_LADDER_IDLE; @@ -277,10 +364,14 @@ void lara_col_climbstnc(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) if (!(TrInput & IN_FORWARD)) { if (!(TrInput & IN_BACK)) + { return; + } if (item->goalAnimState == LS_HANG) + { return; + } item->goalAnimState = LS_LADDER_IDLE; item->pos.yPos += 256; @@ -291,16 +382,22 @@ void lara_col_climbstnc(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) item->pos.yPos -= 256; if (!resultRight || !resultLeft || resultLeft == -2 || resultRight == -2) + { return; + } yShift = ledgeLeft; if (ledgeRight && ledgeLeft) { if (ledgeLeft < 0 != ledgeRight < 0) + { return; + } if (ledgeRight < 0 == ledgeRight < ledgeLeft) + { yShift = ledgeRight; + } } if (resultRight == 1 && resultLeft == 1) @@ -320,7 +417,9 @@ void lara_col_climbstnc(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) resultLeft = LaraTestClimbUpPos(item, coll->radius, -120 - coll->radius, &shiftLeft, &ledgeLeft); if (!resultRight || !resultLeft) + { return; + } if (resultRight >= 0 && resultLeft >= 0) { @@ -367,12 +466,16 @@ void lara_as_climbstnc(ITEM_INFO* item, COLL_INFO* coll)//463F0, 46854 (F) coll->enableSpaz = false; coll->enableBaddiePush = false; - Camera.targetElevation = -ANGLE(20); + Camera.targetElevation = ANGLE(-20.0f); if (item->animNumber == LA_LADDER_DISMOUNT_LEFT_START) - Camera.targetAngle = -ANGLE(60.0f); + { + Camera.targetAngle = ANGLE(-60.0f); + } if (item->animNumber == LA_LADDER_DISMOUNT_RIGHT_START) + { Camera.targetAngle = ANGLE(60.0f); + } if (TrInput & IN_LOOK) { @@ -382,12 +485,12 @@ void lara_as_climbstnc(ITEM_INFO* item, COLL_INFO* coll)//463F0, 46854 (F) if (TrInput & IN_LEFT || TrInput & IN_LSTEP) { item->goalAnimState = LS_LADDER_LEFT; - Lara.moveAngle = -ANGLE(90); + Lara.moveAngle = ANGLE(-90.0f); } else if (TrInput & IN_RIGHT || TrInput & IN_RSTEP) { item->goalAnimState = LS_LADDER_RIGHT; - Lara.moveAngle = ANGLE(90); + Lara.moveAngle = ANGLE(90.0f); } else if (TrInput & IN_JUMP) { @@ -405,8 +508,8 @@ void lara_as_stepoff_left(ITEM_INFO* item, COLL_INFO* coll) coll->enableBaddiePush = false; coll->enableSpaz = false; - Camera.targetAngle = -ANGLE(60.0f); - Camera.targetElevation = -ANGLE(15.0f); + Camera.targetAngle = ANGLE(-60.0f); + Camera.targetElevation = ANGLE(-15.0f); item->pos.yRot -= ANGLE(90.0f); } @@ -417,7 +520,7 @@ void lara_as_stepoff_right(ITEM_INFO* item, COLL_INFO* coll) coll->enableSpaz = false; Camera.targetAngle = ANGLE(60.0f); - Camera.targetElevation = -ANGLE(15.0f); + Camera.targetElevation = ANGLE(-15.0f); item->pos.yRot += ANGLE(90.0f); } @@ -626,7 +729,7 @@ int LaraClimbRightCornerTest(ITEM_INFO* item, COLL_INFO* coll)//45DE4, 46248 Lara.cornerX = x; item->pos.zPos = z; Lara.cornerZ = z; - item->pos.yRot += ANGLE(90); + item->pos.yRot += ANGLE(90.0f); Lara.moveAngle = 0; result = LaraTestClimbPos(item, coll->radius, coll->radius + 120, -512, 512, &shift); @@ -672,7 +775,7 @@ int LaraClimbRightCornerTest(ITEM_INFO* item, COLL_INFO* coll)//45DE4, 46248 Lara.cornerX = newX; item->pos.zPos = newZ; Lara.cornerZ = newZ; - item->pos.yRot -= ANGLE(90); + item->pos.yRot -= ANGLE(90.0f); Lara.moveAngle = 0; result = LaraTestClimbPos(item, coll->radius, coll->radius + 120, -512, 512, &shift) != 0; } @@ -724,7 +827,7 @@ int LaraClimbLeftCornerTest(ITEM_INFO* item, COLL_INFO* coll)//45ABC, 45F20 Lara.cornerX = x; item->pos.zPos = z; Lara.cornerZ = z; - item->pos.yRot -= ANGLE(90); + item->pos.yRot -= ANGLE(90.0f); Lara.moveAngle = 0; result = LaraTestClimbPos(item, coll->radius, -coll->radius - 120, -512, 512, &shift); @@ -771,7 +874,7 @@ int LaraClimbLeftCornerTest(ITEM_INFO* item, COLL_INFO* coll)//45ABC, 45F20 Lara.cornerX = newX; item->pos.zPos = newZ; Lara.cornerZ = newZ; - item->pos.yRot += ANGLE(90); + item->pos.yRot += ANGLE(90.0f); Lara.moveAngle = 0; item->itemFlags[3] = LaraTestClimbPos(item, coll->radius, -coll->radius - 120, -512, 512, &shift); result = item->itemFlags[3] != 0; @@ -792,7 +895,6 @@ int LaraClimbLeftCornerTest(ITEM_INFO* item, COLL_INFO* coll)//45ABC, 45F20 int LaraTestClimb(int x, int y, int z, int xFront, int zFront, int itemHeight, int itemRoom, int* shift)//457F0, 45C54 { - *shift = 0; int hang = 1; if (!Lara.climbStatus) @@ -986,38 +1088,3 @@ int LaraTestClimbUpPos(ITEM_INFO* item, int front, int right, int* shift, int* l return -2; } - -int LaraCheckForLetGo(ITEM_INFO* item, COLL_INFO* coll)//45434, 45898 (F) -{ - short roomNumber = item->roomNumber; - - item->gravityStatus = false; - item->fallspeed = 0; - - GetFloorHeight(GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber), - item->pos.xPos, item->pos.yPos, item->pos.zPos); - - coll->trigger = TriggerIndex; - - if (TrInput & IN_ACTION && item->hitPoints > 0) - return 0; - - Lara.torsoYrot = 0; - Lara.torsoXrot = 0; - - Lara.headYrot = 0; - Lara.headXrot = 0; - - item->goalAnimState = LS_JUMP_FORWARD; - item->currentAnimState = LS_JUMP_FORWARD; - item->animNumber = LA_FALL_START; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - - item->speed = 2; - item->gravityStatus = true; - item->fallspeed = 1; - - Lara.gunStatus = LG_NO_ARMS; - - return 1; -} diff --git a/TR5Main/Game/Lara/lara_collide.cpp b/TR5Main/Game/Lara/lara_collide.cpp index cc819b616..87ef1b3d6 100644 --- a/TR5Main/Game/Lara/lara_collide.cpp +++ b/TR5Main/Game/Lara/lara_collide.cpp @@ -4,9 +4,53 @@ #include "draw.h" #include "effect2.h" -/*this file has all the generic **collision** test functions called in lara's state code*/ +// Generic collision test functions -int LaraDeflectEdge(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +bool TestLaraWallDeflect(COLL_INFO* coll) +{ + if (coll->collType == CT_FRONT || + coll->collType == CT_TOP_FRONT || + coll->collType == CT_LEFT || + coll->collType == CT_RIGHT) + { + return true; + } + + return false; +} + +// TODO: For statics? +void SetLaraWallDeflect(ITEM_INFO* item, COLL_INFO* coll) +{ + switch (coll->collType) + { + case CT_FRONT: + case CT_TOP_FRONT: + { + ShiftItem(item, coll); + + item->goalAnimState = LS_STOP; + item->speed = 0; + item->gravityStatus = false; + break; + } + case CT_LEFT: + { + ShiftItem(item, coll); + item->pos.yRot += ANGLE(5.0f); + break; + } + case CT_RIGHT: + { + ShiftItem(item, coll); + item->pos.yRot -= ANGLE(5.0f); + break; + } + } +} + +// Legacy function. +bool LaraDeflectEdge(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { if (coll->collType == CT_FRONT || coll->collType == CT_TOP_FRONT) { @@ -16,7 +60,7 @@ int LaraDeflectEdge(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) item->speed = 0; item->gravityStatus = false; - return 1; + return true; } if (coll->collType == CT_LEFT) @@ -30,7 +74,7 @@ int LaraDeflectEdge(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) item->pos.yRot -= ANGLE(5.0f); } - return 0; + return false; } void LaraDeflectEdgeJump(ITEM_INFO* item, COLL_INFO* coll)//12904, 129B4 (F) @@ -49,7 +93,6 @@ void LaraDeflectEdgeJump(ITEM_INFO* item, COLL_INFO* coll)//12904, 129B4 (F) { item->goalAnimState = LS_GRAB_TO_FALL; item->currentAnimState = LS_GRAB_TO_FALL; - item->animNumber = LA_JUMP_UP_LAND; item->frameNumber = g_Level.Anims[LA_JUMP_UP_LAND].frameBase; } @@ -58,7 +101,6 @@ void LaraDeflectEdgeJump(ITEM_INFO* item, COLL_INFO* coll)//12904, 129B4 (F) { item->goalAnimState = LS_FREEFALL; item->currentAnimState = LS_FREEFALL; - item->animNumber = LA_JUMP_WALL_SMASH_START; item->frameNumber = g_Level.Anims[LA_JUMP_WALL_SMASH_START].frameBase + 1; } @@ -67,7 +109,9 @@ void LaraDeflectEdgeJump(ITEM_INFO* item, COLL_INFO* coll)//12904, 129B4 (F) Lara.moveAngle += ANGLE(180); if (item->fallspeed <= 0) + { item->fallspeed = 1; + } } break; @@ -96,33 +140,35 @@ void LaraDeflectEdgeJump(ITEM_INFO* item, COLL_INFO* coll)//12904, 129B4 (F) } } -int LaraDeflectEdgeDuck(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +bool TestLaraHitCeiling(COLL_INFO* coll) { - if (coll->collType == CT_FRONT || coll->collType == CT_TOP_FRONT) + if (coll->collType == CT_TOP || + coll->collType == CT_CLAMP) { - ShiftItem(item, coll); - - item->gravityStatus = false; - item->speed = 0; - - return 1; + return true; } - if (coll->collType == CT_LEFT) - { - ShiftItem(item, coll); - item->pos.yRot += ANGLE(2.0f); - } - else if (coll->collType == CT_RIGHT) - { - ShiftItem(item, coll); - item->pos.yRot -= ANGLE(2.0f); - } - - return 0; + return false; } -int LaraHitCeiling(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +// TODO: Better handling of collision with ceiling when on ground. This function should become obsolete. +void SetLaraHitCeiling(ITEM_INFO* item, COLL_INFO* coll) +{ + item->pos.xPos = coll->old.x; + item->pos.yPos = coll->old.y; + item->pos.zPos = coll->old.z; + + /*item->goalAnimState = LS_STOP; + item->currentAnimState = LS_STOP; + item->animNumber = LA_STAND_SOLID; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase;*/ + + item->speed = 0; + item->fallspeed = 0;// -item->fallspeed; +} + +// Legacy function. +bool LaraHitCeiling(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { if (coll->collType == CT_TOP || coll->collType == CT_CLAMP) { @@ -140,9 +186,9 @@ int LaraHitCeiling(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) item->fallspeed = 0; item->gravityStatus = false; - return 1; + return true; } - return 0; + return false; } void LaraCollideStop(ITEM_INFO* item, COLL_INFO* coll)//126F0(<), 127A0(<) (F) @@ -152,7 +198,8 @@ void LaraCollideStop(ITEM_INFO* item, COLL_INFO* coll)//126F0(<), 127A0(<) (F) case LS_STOP: case LS_TURN_RIGHT_SLOW: case LS_TURN_LEFT_SLOW: - case LS_TURN_FAST: + case LS_TURN_RIGHT_FAST: + case LS_TURN_LEFT_FAST: item->currentAnimState = coll->oldAnimState; item->animNumber = coll->oldAnimNumber; item->frameNumber = coll->oldFrameNumber; diff --git a/TR5Main/Game/Lara/lara_collide.h b/TR5Main/Game/Lara/lara_collide.h index 0ffacb25f..192ae3775 100644 --- a/TR5Main/Game/Lara/lara_collide.h +++ b/TR5Main/Game/Lara/lara_collide.h @@ -1,11 +1,15 @@ #pragma once #include "lara_struct.h" -int LaraDeflectEdge(ITEM_INFO* item, COLL_INFO* coll); +bool LaraDeflectEdge(ITEM_INFO* item, COLL_INFO* coll); void LaraDeflectEdgeJump(ITEM_INFO* item, COLL_INFO* coll); -int LaraDeflectEdgeDuck(ITEM_INFO* item, COLL_INFO* coll); -int LaraHitCeiling(ITEM_INFO* item, COLL_INFO* coll); +bool LaraHitCeiling(ITEM_INFO* item, COLL_INFO* coll); void LaraCollideStop(ITEM_INFO* item, COLL_INFO* coll); void SnapLaraToEdgeOfBlock(ITEM_INFO* item, COLL_INFO* coll, short angle); short GetDirOctant(int rot); void GetLaraDeadlyBounds(); + +bool TestLaraWallDeflect(COLL_INFO* coll); +void SetLaraWallDeflect(ITEM_INFO* item, COLL_INFO* coll); +bool TestLaraHitCeiling(COLL_INFO* coll); +void SetLaraHitCeiling(ITEM_INFO* item, COLL_INFO* coll); diff --git a/TR5Main/Game/Lara/lara_crawl.cpp b/TR5Main/Game/Lara/lara_crawl.cpp index 042d74290..e58b1c285 100644 --- a/TR5Main/Game/Lara/lara_crawl.cpp +++ b/TR5Main/Game/Lara/lara_crawl.cpp @@ -6,17 +6,134 @@ #include "lara_collide.h" #include "draw.h" -/*this file has all the related functions to ducking and crawling*/ +// CRAWLING & CROUCHING -/*crouch/duck start*/ -void lara_as_duck(ITEM_INFO* item, COLL_INFO* coll)//14688, 14738 (F) +// ------------------------------ +// Auxiliary Functions +// ------------------------------ + +bool TestLaraKeepCrouched(ITEM_INFO* player, COLL_INFO* coll) { - /*state 71*/ - /*collision: lara_col_duck*/ - short roomNum; + if (coll->midCeiling >= -362 || // Low ceiling. + ((TrInput & IN_FORWARD) && // Moving forward and low ceiling ahead. + TestWall(player, 512, 0, -768) && // TODO: This condition needs more specificity. There could be a thin platform above, making this fail. Maybe check for height to ceiling from location ahead? + !TestWall(player, 512, 0, -362) && + !LaraFloorFront(player, player->pos.yRot, 512) < 384) || + ((TrInput & IN_BACK) && // Moving back and low ceiling behind. + TestWall(player, -512, 0, -768) && + !TestWall(player, -512, 0, -362) && + !LaraFloorFront(player, -player->pos.yRot, 512) < 384)) + { + return true; + } - coll->enableSpaz = false; - coll->enableBaddiePush = true; + return false; +} + +bool TestLaraCrawl(ITEM_INFO* player) +{ + if (Lara.gunStatus == LG_NO_ARMS && Lara.waterStatus != LW_WADE || + Lara.waterSurfaceDist == 256 && !(Lara.waterSurfaceDist > 256) && + (player->animNumber == LA_CROUCH_IDLE || player->animNumber == LA_STAND_TO_CROUCH_END) && + !(TrInput & IN_FLARE || TrInput & IN_DRAW) && + (Lara.gunType != WEAPON_FLARE || Lara.flareAge < 900 && Lara.flareAge != 0)) + { + return true; + } + + return false; +} + +bool TestLaraCrouchTurn(ITEM_INFO* player) +{ + if (Lara.waterStatus != LW_WADE || + Lara.keepDucked) + { + return true; + } + + return false; +} + +bool TestLaraCrouchRoll(ITEM_INFO* player) +{ + if (Lara.gunStatus == LG_NO_ARMS && + Lara.waterStatus != LW_WADE || + Lara.waterSurfaceDist == 256 && + !(Lara.waterSurfaceDist > 256) && + (!(LaraFloorFront(player, player ->pos.yRot, 1024) >= 384) || // 1 block away from hole in floor. + !TestWall(player , 1024, 0, -256)) && // 1 block away from wall. + !(TrInput & IN_FLARE || TrInput & IN_DRAW) && // Avoids some flare spawning/wep stuff. + (Lara.gunType != WEAPON_FLARE || Lara.flareAge < 900 && Lara.flareAge != 0)) + { + return true; + } + + return false; +} + +bool TestLaraCrawlStepUp(ITEM_INFO* item) +{ + if (LaraFloorFront(item, item->pos.yRot, 256) == -256 && + LaraCeilingFront(item, item->pos.yRot, 256, 256) != NO_HEIGHT && + LaraCeilingFront(item, item->pos.yRot, 256, 256) <= -512) + { + return true; + } + + return false; +} + +bool TestLaraCrawlStepDown(ITEM_INFO* item) +{ + if (LaraFloorFront(item, item->pos.yRot, 256) == 256 && + LaraCeilingFront(item, item->pos.yRot, 256, 256) != NO_HEIGHT && + LaraCeilingFront(item, item->pos.yRot, 256, -256) <= -512) + { + return true; + } + + return false; +} + +// TODO: Why have a different function for crawling? I've replaced every call to this for now. Test fidelity after new collision. +void SetLaraCrawlWallDeflect(ITEM_INFO* item, COLL_INFO* coll) +{ + switch (coll->collType) + { + case CT_FRONT: + case CT_TOP_FRONT: + { + ShiftItem(item, coll); + item->gravityStatus = false; + item->speed = 0; + break; + } + case CT_LEFT: + { + ShiftItem(item, coll); + item->pos.yRot += ANGLE(3.0f); + break; + } + case CT_RIGHT: + { + ShiftItem(item, coll); + item->pos.yRot -= ANGLE(3.0f); + break; + } + } +} + +// ------------------------------ +// CROUCHING +// Control & Collision Functions +// ------------------------------ + +// State: 71 +// Collision lara_col_crouch() +void lara_as_crouch(ITEM_INFO* item, COLL_INFO* coll)//14688, 14738 (F) +{ + short roomNum = item->roomNumber; Lara.isDucked = true; @@ -26,93 +143,16 @@ void lara_as_duck(ITEM_INFO* item, COLL_INFO* coll)//14688, 14738 (F) return; } - roomNum = LaraItem->roomNumber; - - if (TrInput & IN_LOOK) - LookUpDown(); - GetFloor(LaraItem->pos.xPos, LaraItem->pos.yPos, LaraItem->pos.zPos, &roomNum); - // FOR DEBUG PURPOSES UNTIL SCRIPTING IS FINISHED- -// EnableCrouchRoll = true; - - - if ((TrInput & IN_FORWARD || TrInput & IN_BACK) - && (TrInput & IN_DUCK || Lara.keepDucked) - && Lara.gunStatus == LG_NO_ARMS - && Lara.waterStatus != LW_WADE - || Lara.waterSurfaceDist == 256 - && !(Lara.waterSurfaceDist > 256)) + if (TrInput & IN_LOOK) { - - if ((item->animNumber == LA_CROUCH_IDLE - || item->animNumber == LA_STAND_TO_CROUCH_END) - && !(TrInput & IN_FLARE || TrInput & IN_DRAW) - && (Lara.gunType != WEAPON_FLARE || Lara.flareAge < 900 && Lara.flareAge != 0)) - { - Lara.torsoYrot = 0; - Lara.torsoXrot = 0; - item->goalAnimState = LS_CRAWL_IDLE; - } - + LookUpDown(); } - else if ((TrInput & IN_SPRINT) /*crouch roll*/ - && (TrInput & IN_DUCK || Lara.keepDucked) - && Lara.gunStatus == LG_NO_ARMS - && Lara.waterStatus != LW_WADE - || Lara.waterSurfaceDist == 256 - && !(Lara.waterSurfaceDist > 256)) - // && EnableCrouchRoll == true) + + if (TrInput & IN_DUCK || Lara.keepDucked) { - if (LaraFloorFront(item, item->pos.yRot, 1024) >= 384 || //4 clicks away from holes in the floor - TestWall(item, 1024, 0, -256)) //4 clicks away from walls - return; - - if (!(TrInput & IN_FLARE || TrInput & IN_DRAW) //avoids some flare spawning/wep stuff - && (Lara.gunType != WEAPON_FLARE || Lara.flareAge < 900 && Lara.flareAge != 0)) - - { - Lara.torsoYrot = 0; - Lara.torsoXrot = 0; - item->goalAnimState = LS_CROUCH_ROLL; - } - } -} - -void lara_col_duck(ITEM_INFO* item, COLL_INFO* coll)//147C4, 148CC (F) -{ - /*state 71*/ - /*state code: lara_as_duck*/ - item->gravityStatus = false; - item->fallspeed = 0; - - Lara.moveAngle = 0; - - coll->facing = item->pos.yRot; - coll->badPos = 384; - coll->badNeg = -STEPUP_HEIGHT; - coll->badCeiling = 0; - - coll->slopesAreWalls = true; - - GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, 400); - - if (LaraFallen(item, coll)) - { - Lara.gunStatus = LG_NO_ARMS; - } - else if (!TestLaraSlide(item, coll)) - { - Lara.keepDucked = coll->midCeiling >= -362; - - ShiftItem(item, coll); - - if (coll->midFloor != NO_HEIGHT) - item->pos.yPos += coll->midFloor; - - if (TrInput & IN_DUCK && Lara.waterStatus != LW_WADE || - Lara.keepDucked || - item->animNumber != LA_CROUCH_IDLE) + if (TestLaraCrouchTurn(item)) { if (TrInput & IN_LEFT) { @@ -123,65 +163,144 @@ void lara_col_duck(ITEM_INFO* item, COLL_INFO* coll)//147C4, 148CC (F) item->goalAnimState = LS_CROUCH_TURN_RIGHT; } } - else + + if (TestLaraCrawl(item)) { - item->goalAnimState = LS_STOP; + Lara.torsoYrot = 0; // Deprecate. + Lara.torsoXrot = 0; + + // TODO: With interpolation, dispatches to crawl forward and back anims can be made directly. + if (TrInput & IN_FORWARD) + { + item->goalAnimState = LS_CRAWL_IDLE; + } + else if (TrInput & IN_BACK) + { + item->goalAnimState = LS_CRAWL_IDLE; + } + + return; } + + if (TrInput & IN_SPRINT && // TODO: Broken?? + TestLaraCrouchRoll(item)) + { + item->goalAnimState = LS_CROUCH_ROLL; + Lara.torsoYrot = 0; // Deprecate. + Lara.torsoXrot = 0; + + return; + } + } + + if (!(TrInput & IN_DUCK)) + { + item->goalAnimState = LS_STOP; + return; } } +// State: 71 +// State code: lara_as_crouch() +void lara_col_crouch(ITEM_INFO* item, COLL_INFO* coll)//147C4, 148CC (F) +{ + Lara.moveAngle = 0; + + item->gravityStatus = false; + item->fallspeed = 0; + + coll->facing = item->pos.yRot; + coll->badPos = 384; + coll->badNeg = -STEPUP_HEIGHT; + coll->badCeiling = 0; + coll->slopesAreWalls = true; + coll->enableSpaz = false; + coll->enableBaddiePush = true; + + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, 400); + + if (TestLaraKeepCrouched(item, coll)) + { + Lara.keepDucked = true; + } + else + { + Lara.keepDucked = false; + } + + if (TestLaraFall(coll)) + { + Lara.gunStatus = LG_NO_ARMS; //?? + SetLaraFall(item); + + return; + } + + if (TestLaraSlide(coll)) + { + SetLaraSlide(item, coll); + return; + } + + ShiftItem(item, coll); + + if (coll->midFloor != NO_HEIGHT) + { + item->pos.yPos += coll->midFloor; + } +} + +// State: 72 +// Collision: lara_col_crouch_roll() void lara_as_crouch_roll(ITEM_INFO* item, COLL_INFO* coll) { - /*state 72*/ - /*collision: lara_col_crouch_roll*/ - Camera.targetElevation = -ANGLE(20.0f); + Camera.targetElevation = ANGLE(-20.0f); item->goalAnimState = LS_CROUCH_IDLE; } +// State: 72 +// State code: lara_as_crouch_roll() void lara_col_crouch_roll(ITEM_INFO* item, COLL_INFO* coll) { - /*state 72*/ - /*state code: lara_as_crouch_roll*/ Lara.isDucked = true; + Lara.moveAngle = 0; + item->gravityStatus = false; item->fallspeed = 0; - Lara.moveAngle = 0; + coll->facing = item->pos.yRot; coll->badPos = STEPUP_HEIGHT; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = 0; coll->slopesAreWalls = true; coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); ShiftItem(item, coll); + if (coll->midFloor != NO_HEIGHT) + { item->pos.yPos += coll->midFloor; + } } -/*crouch/duck end*/ -/*-*/ -/*crawl start*/ -void lara_as_all4s(ITEM_INFO* item, COLL_INFO* coll)//14970, 14A78 (F) + +// ------------------------------ +// CRAWLING +// Control & Collision Functions +// ------------------------------ + +// Puke. +// State: 80 +// Collision: lara_col_crawl_stop() +void lara_as_crawl_stop(ITEM_INFO* item, COLL_INFO* coll)//14970, 14A78 (F) { - /*state 80*/ - /*collision: lara_col_all4s*/ if (item->hitPoints <= 0) { item->goalAnimState = LS_DEATH; return; } - // FOR DEBUG PURPOSES UNTIL SCRIPTING IS FINISHED -// EnableCrawlFlex1clickdown = true; -// EnableCrawlFlex1clickup = true; -// EnableCrawlFlex3clickE = true; -// EnableCrawlFlex2clickE = true; -// EnableCrawlFlex1clickE = true; - - - - - if (TrInput & IN_JUMP) { GAME_VECTOR s, d; @@ -282,41 +401,42 @@ void lara_as_all4s(ITEM_INFO* item, COLL_INFO* coll)//14970, 14A78 (F) item->goalAnimState = LS_MISC_CONTROL; item->currentAnimState = LS_MISC_CONTROL; Lara.gunStatus = LG_HANDS_BUSY; - } } - } - if ((TrInput & IN_ACTION) && (TrInput & IN_FORWARD) && item->animNumber != LA_CROUCH_TO_CRAWL_START && item->animNumber != LA_CROUCH_TO_CRAWL_CONTINUE) + // TODO: state dispatches need testing. + if ((TrInput & IN_FORWARD)/* && (TrInput & IN_FORWARD) && item->animNumber != LA_CROUCH_TO_CRAWL_START && item->animNumber != LA_CROUCH_TO_CRAWL_CONTINUE*/) { if (LaraFloorFront(item, item->pos.yRot, 256) == -256 && LaraCeilingFront(item, item->pos.yRot, 256, 256) != NO_HEIGHT && - LaraCeilingFront(item, item->pos.yRot, 256, 256) <= -512)// && -// EnableCrawlFlex1clickup == true) + LaraCeilingFront(item, item->pos.yRot, 256, 256) <= -512) { - item->animNumber = LA_CRAWL_UP_STEP; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->goalAnimState = LS_MISC_CONTROL; - item->currentAnimState = LS_MISC_CONTROL; + //item->animNumber = LA_CRAWL_UP_STEP; + //item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->goalAnimState = LS_STEP_UP; + //item->currentAnimState = LS_MISC_CONTROL; } else + { if (LaraFloorFront(item, item->pos.yRot, 256) == 256 && LaraCeilingFront(item, item->pos.yRot, 256, 256) != NO_HEIGHT && - LaraCeilingFront(item, item->pos.yRot, 256, -256) <= -512)// && -// EnableCrawlFlex1clickdown == true) + LaraCeilingFront(item, item->pos.yRot, 256, -256) <= -512) { - item->animNumber = LA_CRAWL_DOWN_STEP; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->goalAnimState = LS_MISC_CONTROL; - item->currentAnimState = LS_MISC_CONTROL; + //item->animNumber = LA_CRAWL_DOWN_STEP; + //item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->goalAnimState = LS_STEP_DOWN; + //item->currentAnimState = LS_MISC_CONTROL; } + } } Lara.gunStatus = LG_HANDS_BUSY; if (TrInput & IN_LOOK) + { LookUpDown(); + } Lara.torsoXrot = 0; Lara.torsoYrot = 0; @@ -325,9 +445,11 @@ void lara_as_all4s(ITEM_INFO* item, COLL_INFO* coll)//14970, 14A78 (F) coll->enableBaddiePush = true; if (item->animNumber == LA_CROUCH_TO_CRAWL_START) + { Lara.gunStatus = LG_HANDS_BUSY; + } - Camera.targetElevation = -ANGLE(23.0f); + Camera.targetElevation = ANGLE(-23.0f); if (g_Level.Rooms[LaraItem->roomNumber].flags & ENV_FLAG_WATER) { @@ -336,236 +458,264 @@ void lara_as_all4s(ITEM_INFO* item, COLL_INFO* coll)//14970, 14A78 (F) } } -void lara_col_all4s(ITEM_INFO* item, COLL_INFO* coll)//14B40, 14C74 (F) +// State: 80 +// State code: lara_as_crawl_stop() +void lara_col_crawl_stop(ITEM_INFO* item, COLL_INFO* coll)//14B40, 14C74 (F) { - /*state 80*/ - /*state code: lara_as_all4s*/ item->fallspeed = 0; item->gravityStatus = false; - if (item->goalAnimState != LS_CRAWL_TO_HANG) + if (item->goalAnimState == LS_CRAWL_TO_HANG) { - Lara.moveAngle = 0; - coll->facing = Lara.moveAngle; - - coll->radius = 200; - coll->badPos = 255; - coll->badNeg = -127; - coll->badCeiling = 400; - - coll->slopesAreWalls = true; - coll->slopesArePits = true; - - GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, 400); - - if (LaraFallen(item, coll)) - { - Lara.gunStatus = LG_NO_ARMS; - } - else if (!TestLaraSlide(item, coll)) - { - int slope = abs(coll->leftFloor2 - coll->rightFloor2); - - Lara.keepDucked = coll->midCeiling >= -362; - - ShiftItem(item, coll); - - if (coll->midFloor != NO_HEIGHT && coll->midFloor > -256) - item->pos.yPos += coll->midFloor; - - if (TrInput & IN_DUCK || Lara.keepDucked && - (!(TrInput & IN_FLARE) && !(TrInput & IN_DRAW) || TrInput & IN_FORWARD) && - Lara.waterStatus != LW_WADE) - { - if (item->animNumber == LA_CRAWL_IDLE || - item->animNumber == LA_CROUCH_TO_CRAWL_END || - item->animNumber == LA_CRAWL_TO_IDLE_END_RIGHT_POINTLESS || - item->animNumber == LA_CRAWL_TO_IDLE_END_LEFT_POINTLESS) - { - if (TrInput & IN_FORWARD) - { - if (abs(LaraFloorFront(item, item->pos.yRot, 256)) < 127 && HeightType != BIG_SLOPE) - item->goalAnimState = LS_CRAWL_FORWARD; - } - else if (TrInput & IN_BACK) - { - short height = LaraCeilingFront(item, item->pos.yRot, -300, 128); - short heightl = 0; - short heightr = 0; - - if (height != NO_HEIGHT && height <= 256) - { - if (TrInput & IN_ACTION) - { - int x = item->pos.xPos; - int z = item->pos.zPos; - - item->pos.xPos += 128 * phd_sin(item->pos.yRot - ANGLE(90.0f)) >> W2V_SHIFT; - item->pos.zPos += 128 * phd_cos(item->pos.yRot - ANGLE(90.0f)) >> W2V_SHIFT; - - heightl = LaraFloorFront(item, item->pos.yRot, -300); - - item->pos.xPos += 256 * phd_sin(item->pos.yRot + ANGLE(90.0f)) >> W2V_SHIFT; - item->pos.zPos += 256 * phd_cos(item->pos.yRot + ANGLE(90.0f)) >> W2V_SHIFT; - - heightr = LaraFloorFront(item, item->pos.yRot, -300); - - item->pos.xPos = x; - item->pos.zPos = z; - } - - height = LaraFloorFront(item, item->pos.yRot, -300); - - if (abs(height) >= 255 || HeightType == BIG_SLOPE) - { - if (TrInput & IN_ACTION) - { - if (height > 768 && - heightl > 768 && - heightr > 768 && - slope < 120) - { - int tmp; - ITEM_INFO* tmp1; - MESH_INFO* tmp2; - int x = item->pos.xPos; - int z = item->pos.zPos; - - item->pos.xPos -= 100 * phd_sin(coll->facing) >> W2V_SHIFT; - item->pos.zPos -= 100 * phd_cos(coll->facing) >> W2V_SHIFT; - - tmp = GetCollidedObjects(item, 100, 1, &tmp1, &tmp2, 0); - - item->pos.xPos = x; - item->pos.zPos = z; - - if (!tmp) - { - switch (GetQuadrant(item->pos.yRot)) - { - case 0: - item->pos.yRot = 0; - item->pos.zPos = (item->pos.zPos & 0xFFFFFC00) + 225; - break; - case 1: - item->pos.yRot = ANGLE(90.0f); - item->pos.xPos = (item->pos.xPos & 0xFFFFFC00) + 225; - break; - case 2: - item->pos.yRot = -ANGLE(180.0f); - item->pos.zPos = (item->pos.zPos | 0x3FF) - 225; - break; - case 3: - item->pos.yRot = -ANGLE(90.0f); - item->pos.xPos = (item->pos.xPos | 0x3FF) - 225; - break; - } - - item->goalAnimState = LS_CRAWL_TO_HANG; - } - } - } - } - else if (!(abs(height) >= 127)) - { - item->goalAnimState = LS_CRAWL_BACK; - } - } - } - else if (TrInput & IN_LEFT) - { - item->animNumber = LA_CRAWL_TURN_LEFT; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->currentAnimState = LS_CRAWL_TURN_LEFT; - item->goalAnimState = LS_CRAWL_TURN_LEFT; - } - else if (TrInput & IN_RIGHT) - { - item->animNumber = LA_CRAWL_TURN_RIGHT; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->currentAnimState = LS_CRAWL_TURN_RIGHT; - item->goalAnimState = LS_CRAWL_TURN_RIGHT; - } - } - } - else - { - item->goalAnimState = LS_CROUCH_IDLE; - } - } - } -} - -void lara_as_crawl(ITEM_INFO* item, COLL_INFO* coll)//150F4, 15228 (F) -{ - /*state 81*/ - /*collision: lara_col_crawl*/ - if (item->hitPoints <= 0 || TrInput & IN_JUMP) - { - item->goalAnimState = LS_CRAWL_IDLE; return; } - if (TrInput & IN_LOOK) - LookUpDown(); + Lara.moveAngle = 0; - Lara.torsoXrot = 0; + coll->facing = Lara.moveAngle; + coll->radius = 200; + coll->badPos = 255; + coll->badNeg = -127; + coll->badCeiling = 400; + coll->slopesAreWalls = true; + coll->slopesArePits = true; + + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, 400); + + if (TestLaraFall(coll)) + { + Lara.gunStatus = LG_NO_ARMS; + SetLaraFall(item); + + return; + } + + if (TestLaraSlide(coll)) + { + SetLaraSlide(item, coll); + return; + } + + if (TestLaraKeepCrouched(item, coll)) + { + Lara.keepDucked = true; + } + else + { + Lara.keepDucked = false; + } + + ShiftItem(item, coll); + + if (coll->midFloor != NO_HEIGHT && coll->midFloor > -256) + { + item->pos.yPos += coll->midFloor; + } + + int slope = abs(coll->leftFloor2 - coll->rightFloor2); + if (TrInput & IN_DUCK || Lara.keepDucked && + (!(TrInput & IN_FLARE) && !(TrInput & IN_DRAW) || TrInput & IN_FORWARD) && + Lara.waterStatus != LW_WADE) + { + if (item->animNumber == LA_CRAWL_IDLE || + item->animNumber == LA_CROUCH_TO_CRAWL_END || + item->animNumber == LA_CRAWL_TO_IDLE_END_RIGHT_POINTLESS || + item->animNumber == LA_CRAWL_TO_IDLE_END_LEFT_POINTLESS) + { + if (TrInput & IN_FORWARD) + { + if (abs(LaraFloorFront(item, item->pos.yRot, 256)) < 127 && HeightType != BIG_SLOPE) + { + item->goalAnimState = LS_CRAWL_FORWARD; + } + } + else if (TrInput & IN_BACK) + { + short height = LaraCeilingFront(item, item->pos.yRot, -300, 128); + short heightl = 0; + short heightr = 0; + + if (height != NO_HEIGHT && height <= 256) + { + if (TrInput & IN_ACTION) + { + int x = item->pos.xPos; + int z = item->pos.zPos; + + item->pos.xPos += 128 * phd_sin(item->pos.yRot - ANGLE(90.0f)) >> W2V_SHIFT; + item->pos.zPos += 128 * phd_cos(item->pos.yRot - ANGLE(90.0f)) >> W2V_SHIFT; + + heightl = LaraFloorFront(item, item->pos.yRot, -300); + + item->pos.xPos += 256 * phd_sin(item->pos.yRot + ANGLE(90.0f)) >> W2V_SHIFT; + item->pos.zPos += 256 * phd_cos(item->pos.yRot + ANGLE(90.0f)) >> W2V_SHIFT; + + heightr = LaraFloorFront(item, item->pos.yRot, -300); + + item->pos.xPos = x; + item->pos.zPos = z; + } + + height = LaraFloorFront(item, item->pos.yRot, -300); + + if (abs(height) >= 255 || HeightType == BIG_SLOPE) + { + if (TrInput & IN_ACTION) + { + if (height > 768 && + heightl > 768 && + heightr > 768 && + slope < 120) + { + int tmp; + ITEM_INFO* tmp1; + MESH_INFO* tmp2; + int x = item->pos.xPos; + int z = item->pos.zPos; + + item->pos.xPos -= 100 * phd_sin(coll->facing) >> W2V_SHIFT; + item->pos.zPos -= 100 * phd_cos(coll->facing) >> W2V_SHIFT; + + tmp = GetCollidedObjects(item, 100, 1, &tmp1, &tmp2, 0); + + item->pos.xPos = x; + item->pos.zPos = z; + + if (!tmp) + { + switch (GetQuadrant(item->pos.yRot)) + { + case 0: + item->pos.yRot = 0; + item->pos.zPos = (item->pos.zPos & 0xFFFFFC00) + 225; + break; + case 1: + item->pos.yRot = ANGLE(90.0f); + item->pos.xPos = (item->pos.xPos & 0xFFFFFC00) + 225; + break; + case 2: + item->pos.yRot = -ANGLE(180.0f); + item->pos.zPos = (item->pos.zPos | 0x3FF) - 225; + break; + case 3: + item->pos.yRot = -ANGLE(90.0f); + item->pos.xPos = (item->pos.xPos | 0x3FF) - 225; + break; + } + + item->goalAnimState = LS_CRAWL_TO_HANG; + } + } + } + } + else if (!(abs(height) >= 127)) + { + item->goalAnimState = LS_CRAWL_BACK; + } + } + } + else if (TrInput & IN_LEFT) + { + item->goalAnimState = LS_CRAWL_TURN_LEFT; + } + else if (TrInput & IN_RIGHT) + { + item->goalAnimState = LS_CRAWL_TURN_RIGHT; + } + } + } + else + { + item->goalAnimState = LS_CROUCH_IDLE; + } +} + +// State: 81 +// Collision: lara_col_crawl() +void lara_as_crawl_forward(ITEM_INFO* item, COLL_INFO* coll)//150F4, 15228 (F) +{ + Lara.torsoXrot = 0; // Deprecate. Lara.torsoYrot = 0; coll->enableSpaz = false; coll->enableBaddiePush = true; - Camera.targetElevation = -ANGLE(23.0f); + Camera.targetElevation = item->pos.zRot + ANGLE(-23.0f); // TODO: Test if this jives with Krys' crawl surface adaptation. - if (TrInput & IN_FORWARD - && (TrInput & IN_DUCK || Lara.keepDucked) - && Lara.waterStatus != LW_WADE) + if (item->hitPoints <= 0) { - if (TrInput & IN_LEFT) - { - Lara.turnRate -= LARA_TURN_RATE; - - if (Lara.turnRate < -ANGLE(3.0f)) - Lara.turnRate = -ANGLE(3.0f); - } - else if (TrInput & IN_RIGHT) - { - Lara.turnRate += LARA_TURN_RATE; - - if (Lara.turnRate > ANGLE(3.0f)) - Lara.turnRate = ANGLE(3.0f); - } + item->goalAnimState = LS_CRAWL_IDLE; // TODO: Interpolate into crawl death. + return; } - else + + /*if (!TestLaraCrawl(item)) { item->goalAnimState = LS_CRAWL_IDLE; + return; + }*/ + + if (TrInput & IN_LEFT) + { + Lara.turnRate -= LARA_TURN_RATE; + + if (Lara.turnRate < ANGLE(-3.0f)) + { + Lara.turnRate = ANGLE(-3.0f); + } } + else if (TrInput & IN_RIGHT) + { + Lara.turnRate += LARA_TURN_RATE; + + if (Lara.turnRate > ANGLE(3.0f)) + { + Lara.turnRate = ANGLE(3.0f); + } + } + + if (TrInput & IN_FORWARD && + (TrInput & IN_DUCK || Lara.keepDucked)) + { + item->goalAnimState = LS_CRAWL_FORWARD; + return; + } + + item->goalAnimState = LS_CRAWL_IDLE; } -void lara_col_crawl(ITEM_INFO* item, COLL_INFO* coll)//1523C, 15370 (F) +// State: 81 +// State code: lara_as_crawl_forward() +void lara_col_crawl_forward(ITEM_INFO* item, COLL_INFO* coll)//1523C, 15370 (F) { - /*state 81*/ - /*state code: lara_as_crawl*/ + Lara.moveAngle = 0; + item->gravityStatus = false; item->fallspeed = 0; - Lara.moveAngle = 0; - coll->radius = 200; - coll->badPos = 255; coll->badNeg = -127; coll->badCeiling = 400; - coll->slopesArePits = true; coll->slopesAreWalls = true; - coll->facing = Lara.moveAngle; GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, -400); - if (LaraDeflectEdgeDuck(item, coll)) + if (TestLaraKeepCrouched(item, coll)) { + Lara.keepDucked = true; + } + else + { + Lara.keepDucked = false; + } + + // TODO: Fix wall deflection causing spazz when colliding at steep angle. + if (TestLaraWallDeflect(coll)) + { + SetLaraWallDeflect(item, coll); + item->currentAnimState = LS_CRAWL_IDLE; item->goalAnimState = LS_CRAWL_IDLE; @@ -574,121 +724,177 @@ void lara_col_crawl(ITEM_INFO* item, COLL_INFO* coll)//1523C, 15370 (F) item->animNumber = LA_CRAWL_IDLE; item->frameNumber = g_Level.Anims[item->animNumber].frameBase; } - } - else if (LaraFallen(item, coll)) - { - Lara.gunStatus = LG_NO_ARMS; - } - else if (!TestLaraSlide(item, coll)) - { - ShiftItem(item, coll); - if (coll->midFloor != NO_HEIGHT && coll->midFloor > -256) - item->pos.yPos += coll->midFloor; - } -} - -void lara_as_all4turnl(ITEM_INFO* item, COLL_INFO* coll)//15390(<), 154C4(<) (F) -{ - /*state 84*/ - /*collision: lara_col_all4turnlr*/ - if (item->hitPoints <= 0) - { - item->goalAnimState = LS_CRAWL_IDLE; return; } - coll->enableSpaz = 0; - coll->enableBaddiePush = 1; + if (TestLaraFall(coll)) + { + SetLaraFall(item); + Lara.gunStatus = LG_NO_ARMS; + + return; + } + + if (TestLaraSlide(coll)) + { + SetLaraSlide(item, coll); + return; + } + + ShiftItem(item, coll); + + if (TestLaraCrawlStepUp(item)) + { + item->goalAnimState = LS_STEP_UP; + } + else if (TestLaraCrawlStepDown(item)) + { + item->goalAnimState = LS_STEP_DOWN; + } + + if (coll->midFloor != NO_HEIGHT && coll->midFloor > -256) + { + item->pos.yPos += coll->midFloor; + } +} + +// State: 84 +// Collision: lara_col_crawl_turn() +void lara_as_crawl_turn_left(ITEM_INFO* item, COLL_INFO* coll)//15390(<), 154C4(<) (F) +{ + Camera.targetElevation = ANGLE(-23.0f); Lara.torsoYrot = 0; Lara.torsoXrot = 0; - Camera.targetElevation = -ANGLE(23.0f); + item->pos.yRot -= ANGLE(1.5f); - if (!(TrInput & IN_LEFT)) - item->goalAnimState = LS_CRAWL_IDLE; -} + coll->enableSpaz = 0; + coll->enableBaddiePush = 1; -void lara_as_all4turnr(ITEM_INFO* item, COLL_INFO* coll)//15484(<), 155B8(<) (F) -{ - /*state 85*/ - /*collision: lara_col_all4turnlr*/ if (item->hitPoints <= 0) { item->goalAnimState = LS_CRAWL_IDLE; return; } - coll->enableSpaz = 0; - coll->enableBaddiePush = 1; + if (TrInput & IN_LEFT && + (TrInput & IN_DUCK || Lara.keepDucked)) + { + item->goalAnimState = LS_CRAWL_TURN_LEFT; + + return; + } + + item->goalAnimState = LS_CRAWL_IDLE; +} + +// State: 85 +// Collision: lara_col_crawl_turn() +void lara_as_crawl_turn_right(ITEM_INFO* item, COLL_INFO* coll)//15484(<), 155B8(<) (F) +{ + Camera.targetElevation = ANGLE(-23.0f); Lara.torsoYrot = 0; Lara.torsoXrot = 0; - Camera.targetElevation = -ANGLE(23.0f); + item->pos.yRot += ANGLE(1.5f); - if (!(TrInput & IN_RIGHT)) - item->goalAnimState = LS_CRAWL_IDLE; -} + coll->enableSpaz = 0; + coll->enableBaddiePush = 1; -void lara_col_all4turnlr(ITEM_INFO* item, COLL_INFO* coll)//153FC, 15530 (F) -{ - /*states 84 and 85*/ - /*state code: lara_as_all4turnl(84) and lara_as_all4turnr(85)*/ - GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, 400); - - if (!TestLaraSlide(item, coll)) - { - if (coll->midFloor != NO_HEIGHT && coll->midFloor > -256) - item->pos.yPos += coll->midFloor; - } -} - -void lara_as_crawlb(ITEM_INFO* item, COLL_INFO* coll)//154F0, 15624 (F) -{ - /*state 86*/ - /*collision: lara_col_crawlb*/ - if (item->hitPoints <= 0 || Lara.waterStatus == 4) + if (item->hitPoints <= 0) { item->goalAnimState = LS_CRAWL_IDLE; return; } - if (TrInput & IN_LOOK) - LookUpDown(); + if (TrInput & IN_RIGHT && + (TrInput & IN_DUCK || Lara.keepDucked)) + { + item->goalAnimState = LS_CRAWL_TURN_RIGHT; + + return; + } + + item->goalAnimState = LS_CRAWL_IDLE; +} + +// States: 84, 85 +// State codes: lara_as_turn_left(), lara_as_turn_right() +void lara_col_crawl_turn(ITEM_INFO* item, COLL_INFO* coll)//153FC, 15530 (F) +{ + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, 400); + + if (TestLaraSlide(coll)) + { + SetLaraSlide(item, coll); + return; + } + + if (coll->midFloor != NO_HEIGHT && coll->midFloor > -256) + { + item->pos.yPos += coll->midFloor; + } +} + +// State: 86 +// Collision: lara_col_crawl_back() +void lara_as_crawl_back(ITEM_INFO* item, COLL_INFO* coll)//154F0, 15624 (F) +{ + Lara.torsoYrot = 0; // Deprecate. + Lara.torsoXrot = 0; coll->enableSpaz = false; coll->enableBaddiePush = true; - Lara.torsoYrot = 0; - Lara.torsoXrot = 0; + Camera.targetElevation = item->pos.zRot + ANGLE(-23.0f); - Camera.targetElevation = -ANGLE(23.0f); - - if (TrInput & IN_BACK) - { - if (TrInput & IN_RIGHT) - { - Lara.turnRate -= LARA_TURN_RATE; - if (Lara.turnRate < -ANGLE(3.0f)) - Lara.turnRate = -ANGLE(3.0f); - } - else if (TrInput & IN_LEFT) - { - Lara.turnRate += LARA_TURN_RATE; - if (Lara.turnRate > ANGLE(3.0f)) - Lara.turnRate = ANGLE(3.0f); - } - } - else + if (item->hitPoints <= 0) { item->goalAnimState = LS_CRAWL_IDLE; + return; } + + //if (!TestLaraCrawl(item)) // TODO: This check doesn't work as expected. + //{ + // item->goalAnimState = LS_CRAWL_IDLE; + // return; + //} + + if (TrInput & IN_RIGHT) + { + Lara.turnRate -= LARA_TURN_RATE; + if (Lara.turnRate < ANGLE(-3.0f)) + { + Lara.turnRate = ANGLE(-3.0f); + } + } + else if (TrInput & IN_LEFT) + { + Lara.turnRate += LARA_TURN_RATE; + if (Lara.turnRate > ANGLE(3.0f)) + { + Lara.turnRate = ANGLE(3.0f); + } + } + + if (TrInput & IN_BACK && + (TrInput & IN_DUCK || Lara.keepDucked) && + Lara.waterStatus != LW_WADE) + { + item->goalAnimState = LS_CRAWL_BACK; + return; + } + + item->goalAnimState = LS_CRAWL_IDLE; } -void lara_col_crawlb(ITEM_INFO* item, COLL_INFO* coll)//15614, 15748 (F) +// State: 86 +// State code: lara_as_crawlb() +void lara_col_crawl_back(ITEM_INFO* item, COLL_INFO* coll)//15614, 15748 (F) { - /*state 86*/ - /*state code: lara_as_crawlb*/ + Lara.moveAngle = 0;// ANGLE(180); + item->gravityStatus = false; item->fallspeed = 0; @@ -698,15 +904,23 @@ void lara_col_crawlb(ITEM_INFO* item, COLL_INFO* coll)//15614, 15748 (F) coll->badCeiling = 400; coll->slopesArePits = true; coll->slopesAreWalls = true; - - Lara.moveAngle = ANGLE(180); - coll->facing = Lara.moveAngle; GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, 400); - if (LaraDeflectEdgeDuck(item, coll)) + if (TestLaraKeepCrouched(item, coll)) { + Lara.keepDucked = true; + } + else + { + Lara.keepDucked = false; + } + + if (TestLaraWallDeflect(coll)) + { + SetLaraWallDeflect(item, coll); + item->currentAnimState = LS_CRAWL_IDLE; item->goalAnimState = LS_CRAWL_IDLE; @@ -715,56 +929,95 @@ void lara_col_crawlb(ITEM_INFO* item, COLL_INFO* coll)//15614, 15748 (F) item->animNumber = LA_CRAWL_IDLE; item->frameNumber = g_Level.Anims[item->animNumber].frameBase; } + + return; } - else if (LaraFallen(item, coll)) + + if (TestLaraFall(coll)) { + SetLaraFall(item); Lara.gunStatus = LG_NO_ARMS; + + return; } - else if (!TestLaraSlide(item, coll)) + + if (TestLaraSlide(coll)) { - ShiftItem(item, coll); + SetLaraSlide(item, coll); + return; + } - if (coll->midFloor != NO_HEIGHT && coll->midFloor > -256) - item->pos.yPos += coll->midFloor; + ShiftItem(item, coll); - Lara.moveAngle = 0; + if (coll->midFloor != NO_HEIGHT && coll->midFloor > -256) + { + item->pos.yPos += coll->midFloor; } } -void lara_as_duckl(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +// State: 105 +// Collision: lara_col_turn() +void lara_as_crouch_turn_left(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - /*state 105*/ - /*collision: lara_col_ducklr*/ - coll->enableSpaz = false; - if ((TrInput & (IN_DUCK | IN_LEFT)) != (IN_DUCK | IN_LEFT) || item->hitPoints <= 0) - item->goalAnimState = LS_CROUCH_IDLE; - item->pos.yRot -= ANGLE(1.5f); -} - -void lara_as_duckr(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) -{ - /*state 106*/ - /*collision: lara_col_ducklr*/ - coll->enableSpaz = false; - if ((TrInput & (IN_DUCK | IN_LEFT)) != (IN_DUCK | IN_LEFT) || item->hitPoints <= 0) /* @ORIGINAL_BUG: the condition checks for IN_LEFT instead of IN_RIGHT */ - item->goalAnimState = LS_CROUCH_IDLE; - item->pos.yRot += ANGLE(1.5f); -} - -void lara_col_ducklr(ITEM_INFO* item, COLL_INFO* coll)//14534, 145E4 (F) -{ - /*state 105 and 106*/ - /*state code: lara_as_duckl(105) and lara_col_ducklr(106)*/ - // FIXED Lara.isDucked = true; + item->pos.yRot -= ANGLE(1.5f); + coll->enableSpaz = false; + + if (item->hitPoints <= 0) + { + item->goalAnimState = LS_CROUCH_IDLE; + return; + } + + if (TrInput & IN_LEFT && + (TrInput & IN_DUCK || Lara.keepDucked)) + { + item->goalAnimState = LS_CROUCH_TURN_LEFT; + return; + } + + item->goalAnimState = LS_CROUCH_IDLE; +} + +// State: 106 +// Collision: lara_col_turn() +void lara_as_crouch_turn_right(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +{ + Lara.isDucked = true; + item->pos.yRot += ANGLE(1.5f); + coll->enableSpaz = false; + + if (item->hitPoints <= 0) + { + item->goalAnimState = LS_CROUCH_IDLE; + return; + } + if (TrInput & IN_LOOK) + { LookUpDown(); + } + + if (TrInput & IN_RIGHT && + (TrInput & IN_DUCK || Lara.keepDucked)) + { + item->goalAnimState = LS_CROUCH_TURN_RIGHT; + return; + } + + item->goalAnimState = LS_CROUCH_IDLE; +} + +// States: 105, 106 +// State codes: lara_as_crouch_left(), lara_col_crouch_right() +void lara_col_crouch_turn(ITEM_INFO* item, COLL_INFO* coll)//14534, 145E4 (F) +{ + Lara.isDucked = true; + Lara.moveAngle = 0; item->gravityStatus = false; item->fallspeed = 0; - Lara.moveAngle = 0; - coll->facing = item->pos.yRot; coll->badPos = 384; coll->badNeg = -STEPUP_HEIGHT; @@ -773,26 +1026,38 @@ void lara_col_ducklr(ITEM_INFO* item, COLL_INFO* coll)//14534, 145E4 (F) GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, 400); - if (LaraFallen(item, coll)) + if (coll->midCeiling < -362) + { + Lara.keepDucked = false; + } + else + { + Lara.keepDucked = true; + } + + if (TestLaraFall(coll)) { Lara.gunStatus = LG_NO_ARMS; + SetLaraFall(item); + + return; } - else if (!TestLaraSlide(item, coll)) + + if (TestLaraSlide(coll)) { - if (coll->midCeiling < -362) - Lara.keepDucked = false; - else - Lara.keepDucked = true; + SetLaraSlide(item, coll); + return; + } - ShiftItem(item, coll); + ShiftItem(item, coll); - if (coll->midFloor != NO_HEIGHT) - item->pos.yPos += coll->midFloor; + if (coll->midFloor != NO_HEIGHT) + { + item->pos.yPos += coll->midFloor; } } -/*crawling end*/ -void lara_col_crawl2hang(ITEM_INFO* item, COLL_INFO* coll)//15770, 158A4 (F) +void lara_col_crawl_to_hang(ITEM_INFO* item, COLL_INFO* coll)//15770, 158A4 (F) { Camera.targetAngle = 0; Camera.targetElevation = -ANGLE(45.0f); @@ -805,19 +1070,19 @@ void lara_col_crawl2hang(ITEM_INFO* item, COLL_INFO* coll)//15770, 158A4 (F) int edgeCatch; int edge; + Lara.moveAngle = 0; + item->fallspeed = 512; item->pos.yPos += 255; coll->badPos = NO_BAD_POS; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = BAD_JUMP_CEILING; - - Lara.moveAngle = 0; coll->facing = Lara.moveAngle; GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, 870); - edgeCatch = LaraTestEdgeCatch(item, coll, &edge); + edgeCatch = LaraTestEdgeCatch(item, coll, &edge); if (edgeCatch) { if (edgeCatch >= 0 || LaraTestHangOnClimbWall(item, coll)) @@ -844,7 +1109,7 @@ void lara_col_crawl2hang(ITEM_INFO* item, COLL_INFO* coll)//15770, 158A4 (F) if (TestHangFeet(item, angle)) { item->animNumber = LA_REACH_TO_HANG; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase + 12; item->currentAnimState = LS_HANG; item->goalAnimState = LS_HANG_FEET; } diff --git a/TR5Main/Game/Lara/lara_crawl.h b/TR5Main/Game/Lara/lara_crawl.h index f3ad4d2f5..b72e0052c 100644 --- a/TR5Main/Game/Lara/lara_crawl.h +++ b/TR5Main/Game/Lara/lara_crawl.h @@ -1,25 +1,30 @@ #pragma once #include "lara_struct.h" -/*crouch/duck start*/ -void lara_as_duck(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_duck(ITEM_INFO* item, COLL_INFO* coll); +// Auxiliary functions. +bool TestLaraKeepCrouched(ITEM_INFO* player, COLL_INFO* coll); +bool TestLaraCrawl(ITEM_INFO* player); +bool TestLaraCrouchTurn(ITEM_INFO* player); +bool TestLaraCrouchRoll(ITEM_INFO* player); +void SetLaraCrawlWallDeflect(ITEM_INFO* item, COLL_INFO* coll); + +// Crouching control & collision functions. +void lara_as_crouch(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_crouch(ITEM_INFO* item, COLL_INFO* coll); void lara_as_crouch_roll(ITEM_INFO* item, COLL_INFO* coll); void lara_col_crouch_roll(ITEM_INFO* item, COLL_INFO* coll); -/*crouch/duck end*/ -/*-*/ -/*crawl start*/ -void lara_as_all4s(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_all4s(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_crawl(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_crawl(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_all4turnl(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_all4turnr(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_all4turnlr(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_crawlb(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_crawlb(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_duckl(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_duckr(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_ducklr(ITEM_INFO* item, COLL_INFO* coll); -/*crawl end*/ -void lara_col_crawl2hang(ITEM_INFO* item, COLL_INFO* coll); + +// Crawling control & collision functions. +void lara_as_crawl_stop(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_crawl_stop(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_crawl_forward(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_crawl_forward(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_crawl_turn_left(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_crawl_turn_right(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_crawl_turn(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_crawl_back(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_crawl_back(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_crouch_turn_left(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_crouch_turn_right(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_crouch_turn(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_crawl_to_hang(ITEM_INFO* item, COLL_INFO* coll); diff --git a/TR5Main/Game/Lara/lara_fire.cpp b/TR5Main/Game/Lara/lara_fire.cpp index 55c3d70c9..c253c7424 100644 --- a/TR5Main/Game/Lara/lara_fire.cpp +++ b/TR5Main/Game/Lara/lara_fire.cpp @@ -227,7 +227,8 @@ short HoldStates[] = { LS_TURN_RIGHT_SLOW, LS_TURN_LEFT_SLOW, LS_WALK_BACK, - LS_TURN_FAST, + LS_TURN_RIGHT_FAST, + LS_TURN_LEFT_FAST, LS_STEP_RIGHT, LS_STEP_LEFT, LS_PICKUP, @@ -371,19 +372,19 @@ void LaraGun() // (F) (D) || LaraItem->currentAnimState == LS_CROUCH_TURN_LEFT || LaraItem->currentAnimState == LS_CROUCH_TURN_RIGHT) && (Lara.requestGunType == WEAPON_HK - || Lara.requestGunType == WEAPON_CROSSBOW - || Lara.requestGunType == WEAPON_SHOTGUN - || Lara.requestGunType == WEAPON_HARPOON_GUN)) + || Lara.requestGunType == WEAPON_CROSSBOW + || Lara.requestGunType == WEAPON_SHOTGUN + || Lara.requestGunType == WEAPON_HARPOON_GUN)) { if (Lara.gunType == WEAPON_FLARE) Lara.requestGunType = WEAPON_FLARE; } else if (Lara.requestGunType == WEAPON_FLARE || (Lara.Vehicle == NO_ITEM - && (Lara.requestGunType == WEAPON_HARPOON_GUN - || Lara.waterStatus == LW_ABOVE_WATER - || (Lara.waterStatus == LW_WADE - && Lara.waterSurfaceDist > -Weapons[Lara.gunType].gunHeight)))) + && (Lara.requestGunType == WEAPON_HARPOON_GUN + || Lara.waterStatus == LW_ABOVE_WATER + || (Lara.waterStatus == LW_WADE + && Lara.waterSurfaceDist > -Weapons[Lara.gunType].gunHeight)))) { if (Lara.gunType == WEAPON_FLARE) { @@ -411,18 +412,18 @@ void LaraGun() // (F) (D) } else if (Lara.gunStatus == LG_READY) { - if ((TrInput & IN_DRAW) + if ((TrInput & IN_DRAW) || Lara.requestGunType != Lara.gunType) Lara.gunStatus = LG_UNDRAW_GUNS; - else if (Lara.gunType != WEAPON_HARPOON_GUN - && Lara.waterStatus != LW_ABOVE_WATER - && (Lara.waterStatus != LW_WADE - || Lara.waterSurfaceDist < -Weapons[Lara.gunType].gunHeight)) + else if (Lara.gunType != WEAPON_HARPOON_GUN + && Lara.waterStatus != LW_ABOVE_WATER + && (Lara.waterStatus != LW_WADE + || Lara.waterSurfaceDist < -Weapons[Lara.gunType].gunHeight)) Lara.gunStatus = LG_UNDRAW_GUNS; } - else if (Lara.gunStatus == LG_HANDS_BUSY - && (TrInput & IN_FLARE) - && LaraItem->currentAnimState == LS_CRAWL_IDLE + else if (Lara.gunStatus == LG_HANDS_BUSY + && (TrInput & IN_FLARE) + && LaraItem->currentAnimState == LS_CRAWL_IDLE && LaraItem->animNumber == LA_CRAWL_IDLE) { Lara.requestGunType = WEAPON_FLARE; @@ -430,154 +431,154 @@ void LaraGun() // (F) (D) switch (Lara.gunStatus) { - case LG_DRAW_GUNS: - if (Lara.gunType != WEAPON_FLARE && Lara.gunType != WEAPON_NONE) - Lara.lastGunType = Lara.gunType; + case LG_DRAW_GUNS: + if (Lara.gunType != WEAPON_FLARE && Lara.gunType != WEAPON_NONE) + Lara.lastGunType = Lara.gunType; switch (Lara.gunType) { - case WEAPON_PISTOLS: - case WEAPON_REVOLVER: - case WEAPON_UZI: - if (Camera.type != CINEMATIC_CAMERA && Camera.type != LOOK_CAMERA && Camera.type != HEAVY_CAMERA) - Camera.type = COMBAT_CAMERA; - draw_pistols(Lara.gunType); - break; + case WEAPON_PISTOLS: + case WEAPON_REVOLVER: + case WEAPON_UZI: + if (Camera.type != CINEMATIC_CAMERA && Camera.type != LOOK_CAMERA && Camera.type != HEAVY_CAMERA) + Camera.type = COMBAT_CAMERA; + draw_pistols(Lara.gunType); + break; - case WEAPON_SHOTGUN: - case WEAPON_CROSSBOW: - case WEAPON_HK: - case WEAPON_GRENADE_LAUNCHER: - case WEAPON_ROCKET_LAUNCHER: - case WEAPON_HARPOON_GUN: - if (Camera.type != CINEMATIC_CAMERA && Camera.type != LOOK_CAMERA && Camera.type != HEAVY_CAMERA) - Camera.type = COMBAT_CAMERA; - draw_shotgun(Lara.gunType); - break; + case WEAPON_SHOTGUN: + case WEAPON_CROSSBOW: + case WEAPON_HK: + case WEAPON_GRENADE_LAUNCHER: + case WEAPON_ROCKET_LAUNCHER: + case WEAPON_HARPOON_GUN: + if (Camera.type != CINEMATIC_CAMERA && Camera.type != LOOK_CAMERA && Camera.type != HEAVY_CAMERA) + Camera.type = COMBAT_CAMERA; + draw_shotgun(Lara.gunType); + break; - case WEAPON_FLARE: - draw_flare(); - break; - - default: - Lara.gunStatus = LG_NO_ARMS; - break; - } - break; - - case LG_SPECIAL: + case WEAPON_FLARE: draw_flare(); break; - case LG_UNDRAW_GUNS: + default: + Lara.gunStatus = LG_NO_ARMS; + break; + } + break; + + case LG_SPECIAL: + draw_flare(); + break; + + case LG_UNDRAW_GUNS: + Lara.meshPtrs[LM_HEAD] = Objects[ID_LARA_SKIN].meshIndex + LM_HEAD; + + switch (Lara.gunType) + { + case WEAPON_PISTOLS: + case WEAPON_REVOLVER: + case WEAPON_UZI: + undraw_pistols(Lara.gunType); + break; + + case WEAPON_SHOTGUN: + case WEAPON_CROSSBOW: + case WEAPON_HK: + case WEAPON_GRENADE_LAUNCHER: + case WEAPON_ROCKET_LAUNCHER: + case WEAPON_HARPOON_GUN: + undraw_shotgun(Lara.gunType); + break; + + case WEAPON_FLARE: + undraw_flare(); + break; + + default: + return; + } + break; + + case LG_READY: + if (!(TrInput & IN_ACTION)) Lara.meshPtrs[LM_HEAD] = Objects[ID_LARA_SKIN].meshIndex + LM_HEAD; + else + Lara.meshPtrs[LM_HEAD] = Objects[ID_LARA_SCREAM].meshIndex + LM_HEAD; - switch (Lara.gunType) + if (Camera.type != CINEMATIC_CAMERA && Camera.type != LOOK_CAMERA && Camera.type != HEAVY_CAMERA) + Camera.type = COMBAT_CAMERA; + + if (TrInput & IN_ACTION) + { + if (!*GetAmmo(Lara.gunType)) { - case WEAPON_PISTOLS: - case WEAPON_REVOLVER: - case WEAPON_UZI: - undraw_pistols(Lara.gunType); - break; - - case WEAPON_SHOTGUN: - case WEAPON_CROSSBOW: - case WEAPON_HK: - case WEAPON_GRENADE_LAUNCHER: - case WEAPON_ROCKET_LAUNCHER: - case WEAPON_HARPOON_GUN: - undraw_shotgun(Lara.gunType); - break; - - case WEAPON_FLARE: - undraw_flare(); - break; - - default: - return; + Lara.requestGunType = Objects[ID_PISTOLS_ITEM].loaded ? WEAPON_PISTOLS : WEAPON_NONE; + return; } + } + + switch (Lara.gunType) + { + case WEAPON_PISTOLS: + case WEAPON_UZI: + PistolHandler(Lara.gunType); break; - case LG_READY: - if (!(TrInput & IN_ACTION)) - Lara.meshPtrs[LM_HEAD] = Objects[ID_LARA_SKIN].meshIndex + LM_HEAD; - else - Lara.meshPtrs[LM_HEAD] = Objects[ID_LARA_SCREAM].meshIndex + LM_HEAD; - - if (Camera.type != CINEMATIC_CAMERA && Camera.type != LOOK_CAMERA && Camera.type != HEAVY_CAMERA) - Camera.type = COMBAT_CAMERA; - - if (TrInput & IN_ACTION) - { - if (!*GetAmmo(Lara.gunType)) - { - Lara.requestGunType = Objects[ID_PISTOLS_ITEM].loaded ? WEAPON_PISTOLS : WEAPON_NONE; - return; - } - } - - switch (Lara.gunType) - { - case WEAPON_PISTOLS: - case WEAPON_UZI: - PistolHandler(Lara.gunType); - break; - - case WEAPON_SHOTGUN: - case WEAPON_CROSSBOW: - case WEAPON_HK: - case WEAPON_GRENADE_LAUNCHER: - case WEAPON_ROCKET_LAUNCHER: - case WEAPON_HARPOON_GUN: - case WEAPON_REVOLVER: - RifleHandler(Lara.gunType); - break; - - default: - return; - } + case WEAPON_SHOTGUN: + case WEAPON_CROSSBOW: + case WEAPON_HK: + case WEAPON_GRENADE_LAUNCHER: + case WEAPON_ROCKET_LAUNCHER: + case WEAPON_HARPOON_GUN: + case WEAPON_REVOLVER: + RifleHandler(Lara.gunType); break; - case LG_NO_ARMS: - if (Lara.gunType == WEAPON_FLARE) + default: + return; + } + break; + + case LG_NO_ARMS: + if (Lara.gunType == WEAPON_FLARE) + { + if (Lara.Vehicle != NO_ITEM || CheckForHoldingState(LaraItem->currentAnimState)) { - if (Lara.Vehicle != NO_ITEM || CheckForHoldingState(LaraItem->currentAnimState)) + if (Lara.flareControlLeft) { - if (Lara.flareControlLeft) + if (Lara.leftArm.frameNumber) { - if (Lara.leftArm.frameNumber) - { - if (++Lara.leftArm.frameNumber == 110) - Lara.leftArm.frameNumber = 0; - } - } - else - { - Lara.leftArm.frameNumber = 95; - Lara.flareControlLeft = true; + if (++Lara.leftArm.frameNumber == 110) + Lara.leftArm.frameNumber = 0; } } else { - Lara.flareControlLeft = false; + Lara.leftArm.frameNumber = 95; + Lara.flareControlLeft = true; } + } + else + { + Lara.flareControlLeft = false; + } + DoFlareInHand(Lara.flareAge); + set_flare_arm(Lara.leftArm.frameNumber); + } + break; + + case LG_HANDS_BUSY: + if (Lara.gunType == WEAPON_FLARE) + { + if (Lara.meshPtrs[LM_LHAND] == Objects[ID_LARA_FLARE_ANIM].meshIndex + LM_LHAND) + { + Lara.flareControlLeft = (Lara.Vehicle != NO_ITEM || CheckForHoldingState(LaraItem->currentAnimState)); DoFlareInHand(Lara.flareAge); set_flare_arm(Lara.leftArm.frameNumber); } - break; - - case LG_HANDS_BUSY: - if (Lara.gunType == WEAPON_FLARE) - { - if (Lara.meshPtrs[LM_LHAND] == Objects[ID_LARA_FLARE_ANIM].meshIndex + LM_LHAND) - { - Lara.flareControlLeft = (Lara.Vehicle != NO_ITEM || CheckForHoldingState(LaraItem->currentAnimState)); - DoFlareInHand(Lara.flareAge); - set_flare_arm(Lara.leftArm.frameNumber); - } - } - break; + } + break; } } @@ -656,7 +657,7 @@ int WeaponObjectMesh(int weaponType) case WEAPON_CROSSBOW: return (Lara.Weapons[WEAPON_CROSSBOW].HasLasersight == true ? ID_LARA_CROSSBOW_LASER : ID_CROSSBOW_ANIM); - + case WEAPON_GRENADE_LAUNCHER: return ID_GRENADE_ANIM; @@ -676,7 +677,7 @@ void HitTarget(ITEM_INFO* item, GAME_VECTOR* hitPos, int damage, int flag) { CREATURE_INFO* creature = (CREATURE_INFO*)item->data; OBJECT_INFO* obj = &Objects[item->objectNumber]; - + item->hitStatus = true; if (creature != nullptr && item != LaraItem) creature->hurtByLara = true; @@ -687,16 +688,16 @@ void HitTarget(ITEM_INFO* item, GAME_VECTOR* hitPos, int damage, int flag) { switch (obj->hitEffect) { - case 1: - DoBloodSplat(hitPos->x, hitPos->y, hitPos->z, (GetRandomControl() & 3) + 3, item->pos.yRot, item->roomNumber); - break; - case 3: - TriggerRicochetSpark(hitPos, LaraItem->pos.yRot, 3, 0); - break; - case 2: - TriggerRicochetSpark(hitPos, LaraItem->pos.yRot, 3, -5); - SoundEffect(SFX_SWORD_GOD_HITMET, &item->pos, 0); - break; + case 1: + DoBloodSplat(hitPos->x, hitPos->y, hitPos->z, (GetRandomControl() & 3) + 3, item->pos.yRot, item->roomNumber); + break; + case 3: + TriggerRicochetSpark(hitPos, LaraItem->pos.yRot, 3, 0); + break; + case 2: + TriggerRicochetSpark(hitPos, LaraItem->pos.yRot, 3, -5); + SoundEffect(SFX_SWORD_GOD_HITMET, &item->pos, 0); + break; } } } @@ -731,9 +732,9 @@ FireWeaponType FireWeapon(int weaponType, ITEM_INFO* target, ITEM_INFO* src, sho rotation.zRot = 0; // Calculate ray from rotation angles - float x = sin(TO_RAD(rotation.yRot)) * cos(TO_RAD(rotation.xRot)); + float x = sin(TO_RAD(rotation.yRot)) * cos(TO_RAD(rotation.xRot)); float y = -sin(TO_RAD(rotation.xRot)); - float z = cos(TO_RAD(rotation.yRot)) * cos(TO_RAD(rotation.xRot)); + float z = cos(TO_RAD(rotation.yRot)) * cos(TO_RAD(rotation.xRot)); Vector3 direction = Vector3(x, y, z); direction.Normalize(); Vector3 source = Vector3(pos.x, pos.y, pos.z); @@ -760,7 +761,7 @@ FireWeaponType FireWeapon(int weaponType, ITEM_INFO* target, ITEM_INFO* src, sho Lara.hasFired = true; Lara.fired = true; - + GAME_VECTOR vSrc; vSrc.x = pos.x; vSrc.y = pos.y; @@ -826,10 +827,10 @@ FireWeaponType FireWeapon(int weaponType, ITEM_INFO* target, ITEM_INFO* src, sho } else {*/ - if (!GetTargetOnLOS(&vSrc, &vDest, FALSE, TRUE)) - HitTarget(target, &vDest, weapon->damage, NULL); + if (!GetTargetOnLOS(&vSrc, &vDest, FALSE, TRUE)) + HitTarget(target, &vDest, weapon->damage, NULL); //} - + return FW_MAYBEHIT; } } @@ -841,7 +842,7 @@ void find_target_point(ITEM_INFO* item, GAME_VECTOR* target) // (F) (D) bounds = (BOUNDING_BOX*)GetBestFrame(item); x = (int)(bounds->X1 + bounds->X2) / 2; - y = (int) bounds->Y1 + (bounds->Y2 - bounds->Y1) / 3; + y = (int)bounds->Y1 + (bounds->Y2 - bounds->Y1) / 3; z = (int)(bounds->Z1 + bounds->Z2) / 2; c = phd_cos(item->pos.yRot); s = phd_sin(item->pos.yRot); @@ -881,9 +882,9 @@ void LaraTargetInfo(WEAPON_INFO* weapon) // (F) (D) if (LOS(&src, &targetPoint)) { if (angles[0] >= weapon->lockAngles[0] - && angles[0] <= weapon->lockAngles[1] - && angles[1] >= weapon->lockAngles[2] - && angles[1] <= weapon->lockAngles[3]) + && angles[0] <= weapon->lockAngles[1] + && angles[1] >= weapon->lockAngles[2] + && angles[1] <= weapon->lockAngles[3]) { Lara.rightArm.lock = true; Lara.leftArm.lock = true; @@ -893,18 +894,18 @@ void LaraTargetInfo(WEAPON_INFO* weapon) // (F) (D) if (Lara.leftArm.lock) { if ((angles[0] < weapon->leftAngles[0] || - angles[0] > weapon->leftAngles[1] || - angles[1] < weapon->leftAngles[2] || - angles[1] > weapon->leftAngles[3])) + angles[0] > weapon->leftAngles[1] || + angles[1] < weapon->leftAngles[2] || + angles[1] > weapon->leftAngles[3])) Lara.leftArm.lock = false; } if (Lara.rightArm.lock) { if ((angles[0] < weapon->rightAngles[0] || - angles[0] > weapon->rightAngles[1] || - angles[1] < weapon->rightAngles[2] || - angles[1] > weapon->rightAngles[3])) + angles[0] > weapon->rightAngles[1] || + angles[1] < weapon->rightAngles[2] || + angles[1] > weapon->rightAngles[3])) Lara.rightArm.lock = false; } } @@ -933,7 +934,7 @@ bool CheckForHoldingState(int state) // (F) (D) return true; holdState++; } - + return false; } @@ -942,7 +943,7 @@ void LaraGetNewTarget(WEAPON_INFO* weapon) // (F) (D) GAME_VECTOR src, target; PHD_VECTOR muzzleOffset; int bestDistance, maxDistance, targets, slot, x, y, z, distance; - ITEM_INFO* bestItem, *item; + ITEM_INFO* bestItem, * item; short bestYrot, angle[2], match; bool flag, loop; @@ -1117,7 +1118,7 @@ void DoProperDetection(short itemNumber, int x, int y, int z, int xv, int yv, in if (y > (height + 32) && bs == 0 && (((x >> WALL_SHIFT) != (item->pos.xPos >> WALL_SHIFT)) || - ((z >> WALL_SHIFT) != (item->pos.zPos >> WALL_SHIFT)))) + ((z >> WALL_SHIFT) != (item->pos.zPos >> WALL_SHIFT)))) { // Need to know which direction the wall is. @@ -1524,7 +1525,7 @@ void DoProperDetection(short itemNumber, int x, int y, int z, int xv, int yv, in { if (y < ceiling && (((x >> WALL_SHIFT) != (item->pos.xPos >> WALL_SHIFT)) || - ((z >> WALL_SHIFT) != (item->pos.zPos >> WALL_SHIFT)))) + ((z >> WALL_SHIFT) != (item->pos.zPos >> WALL_SHIFT)))) { // Need to know which direction the wall is. @@ -1567,26 +1568,26 @@ void DoProperDetection(short itemNumber, int x, int y, int z, int xv, int yv, in HOLSTER_SLOT HolsterSlotForWeapon(LARA_WEAPON_TYPE weapon) { - switch(weapon){ - case WEAPON_PISTOLS: - return HOLSTER_SLOT::Pistols; - case WEAPON_UZI: - return HOLSTER_SLOT::Uzis; - case WEAPON_REVOLVER: - return HOLSTER_SLOT::Revolver; - case WEAPON_SHOTGUN: - return HOLSTER_SLOT::Shotgun; - case WEAPON_HK: - return HOLSTER_SLOT::HK; - case WEAPON_HARPOON_GUN: - return HOLSTER_SLOT::Harpoon; - case WEAPON_CROSSBOW: - return HOLSTER_SLOT::Crowssbow; - case WEAPON_GRENADE_LAUNCHER: - return HOLSTER_SLOT::GrenadeLauncher; - case WEAPON_ROCKET_LAUNCHER: - return HOLSTER_SLOT::RocketLauncher; - default: - return HOLSTER_SLOT::Empty; + switch (weapon) { + case WEAPON_PISTOLS: + return HOLSTER_SLOT::Pistols; + case WEAPON_UZI: + return HOLSTER_SLOT::Uzis; + case WEAPON_REVOLVER: + return HOLSTER_SLOT::Revolver; + case WEAPON_SHOTGUN: + return HOLSTER_SLOT::Shotgun; + case WEAPON_HK: + return HOLSTER_SLOT::HK; + case WEAPON_HARPOON_GUN: + return HOLSTER_SLOT::Harpoon; + case WEAPON_CROSSBOW: + return HOLSTER_SLOT::Crowssbow; + case WEAPON_GRENADE_LAUNCHER: + return HOLSTER_SLOT::GrenadeLauncher; + case WEAPON_ROCKET_LAUNCHER: + return HOLSTER_SLOT::RocketLauncher; + default: + return HOLSTER_SLOT::Empty; } } diff --git a/TR5Main/Game/Lara/lara_flare.cpp b/TR5Main/Game/Lara/lara_flare.cpp index a4a343468..308bcc2c1 100644 --- a/TR5Main/Game/Lara/lara_flare.cpp +++ b/TR5Main/Game/Lara/lara_flare.cpp @@ -12,27 +12,24 @@ #include "effect2.h" #include "chaffFX.h" - constexpr std::array FlareFlickerTable = { 0.7590,0.9880,0.8790,0.920,0.8020,0.7610,0.97878,0.8978,0.9983,0.934763,0.8485,0.762573,0.84642,0.7896,0.817634,0.923424,0.7589,0.81399,0.92834,0.9978,0.7610,0.97878,0.8978,0.9983,0.934763,0.8485,0.762573,0.74642 }; constexpr DirectX::SimpleMath::Vector3 FlareMainColor = Vector3(1,0.52947, 0.3921); constexpr std::array FlareFlickerTableLow = { 0.7590,0.1880,0.0790,0.920,0.8020,0.07610,0.197878,0.38978,0.09983,0.00934763,0.8485,0.0762573,0.84642,0.7896,0.517634,0.0923424,0.7589,0.081399,0.92834,0.01978,0.17610,0.497878,0.8978,0.69983,0.934763,0.28485,0.1762573,0.374642 }; - - -void FlareControl(short itemNumber) // (AF) (D) +void FlareControl(short itemNum) // (AF) (D) { - ITEM_INFO* item = &g_Level.Items[itemNumber]; + ITEM_INFO* item = &g_Level.Items[itemNum]; if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) { - KillItem(itemNumber); + KillItem(itemNum); return; } if (item->fallspeed) { - item->pos.xRot += ANGLE(3); - item->pos.zRot += ANGLE(5); + item->pos.xRot += ANGLE(3.0f); + item->pos.zRot += ANGLE(5.0f); } else { @@ -50,25 +47,26 @@ void FlareControl(short itemNumber) // (AF) (D) item->pos.xPos += xv; item->pos.zPos += zv; - if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_WATER) { item->fallspeed += (5 - item->fallspeed) / 2; item->speed += (5 - item->speed) / 2; } else + { item->fallspeed += 6; + } item->pos.yPos += item->fallspeed; - DoProperDetection(itemNumber, oldX, oldY, oldZ, xv, item->fallspeed, zv); + DoProperDetection(itemNum, oldX, oldY, oldZ, xv, item->fallspeed, zv); short age = (short)(item->data) & 0x7FFF; if (age >= 900) { if (!item->fallspeed && !item->speed) { - KillItem(itemNumber); + KillItem(itemNum); return; } } @@ -327,7 +325,7 @@ void CreateFlare(short objectNum, int thrown) // (F) (D) if (collided || GetFloorHeight(floor, pos.x, pos.y, pos.z) < pos.y) { flag = true; - item->pos.yRot = LaraItem->pos.yRot + ANGLE(180); + item->pos.yRot = LaraItem->pos.yRot + ANGLE(180.0f); item->pos.xPos = LaraItem->pos.xPos + (320 * phd_sin(item->pos.yRot) >> W2V_SHIFT); item->pos.zPos = LaraItem->pos.zPos + (320 * phd_cos(item->pos.yRot) >> W2V_SHIFT); item->roomNumber = LaraItem->roomNumber; @@ -335,9 +333,14 @@ void CreateFlare(short objectNum, int thrown) // (F) (D) else { if (thrown) + { item->pos.yRot = LaraItem->pos.yRot; + } else - item->pos.yRot = LaraItem->pos.yRot - ANGLE(45); + { + item->pos.yRot = LaraItem->pos.yRot - ANGLE(45.0f); + } + item->roomNumber = roomNumber; } @@ -359,14 +362,20 @@ void CreateFlare(short objectNum, int thrown) // (F) (D) } if (flag) + { item->speed >>= 1; + } if (objectNum == ID_FLARE_ITEM) { if (DoFlareLight((PHD_VECTOR*)&item->pos, Lara.flareAge)) + { item->data = (void*)(Lara.flareAge | 0x8000); + } else + { item->data = (void*)(Lara.flareAge & 0x7FFF); + } } else { @@ -393,7 +402,9 @@ void DoFlareInHand(int flare_age) // (AF) (D) GetLaraJointPosition(&pos, LM_LHAND); if (DoFlareLight(&pos, flare_age)) + { TriggerChaffEffects(flare_age); + } /* Hardcoded code */ @@ -415,7 +426,10 @@ int DoFlareLight(PHD_VECTOR* pos, int age)//49708, 49B6C (F) float random; int falloff; if (age >= 900 || age == 0) + { return 0; + } + random = frand(); x = pos->x + (random* 120); @@ -431,6 +445,7 @@ int DoFlareLight(PHD_VECTOR* pos, int age)//49708, 49B6C (F) b = FlareMainColor.z * 255; TriggerDynamicLight(x, y, z, falloff, r, g, b); + return (random < 0.9f); } else if (age < 810) @@ -442,6 +457,7 @@ int DoFlareLight(PHD_VECTOR* pos, int age)//49708, 49B6C (F) g = FlareMainColor.y * 255 * multiplier; b = FlareMainColor.z * 255 * multiplier; TriggerDynamicLight(x, y, z, falloff, r, g, b); + return (random < 0.4f); } else @@ -452,9 +468,8 @@ int DoFlareLight(PHD_VECTOR* pos, int age)//49708, 49B6C (F) r = FlareMainColor.x * 255 * multiplier; g = FlareMainColor.y * 255 * multiplier; b = FlareMainColor.z * 255 * multiplier; - TriggerDynamicLight(x, y, z, falloff, r, g, b); - return (random < .3f); - - } + TriggerDynamicLight(x, y, z, falloff, r, g, b); + return (random < .3f); + } } diff --git a/TR5Main/Game/Lara/lara_hang.cpp b/TR5Main/Game/Lara/lara_hang.cpp index 32ffa01e5..23cf201d0 100644 --- a/TR5Main/Game/Lara/lara_hang.cpp +++ b/TR5Main/Game/Lara/lara_hang.cpp @@ -3,15 +3,24 @@ #include "input.h" #include "lara_tests.h" -/*this file has all the lara_as/lara_col functions related to hanging*/ +// HANGING -/*normal hanging and shimmying*/ +// ------------------------------ +// HANGING AND SHIMMYING +// Control & Collision Functions +// ------------------------------ + +// State: 10 +// Collision: lara_col_hang() void lara_as_hang(ITEM_INFO* item, COLL_INFO* coll)//19A28, 19B5C (F) { - /*state 10*/ - /*collision: lara_col_hang*/ + Camera.targetAngle = 0; + Camera.targetElevation = ANGLE(-45.0f); Lara.isClimbing = false; + coll->enableBaddiePush = false; + coll->enableSpaz = false; + if (item->hitPoints <= 0) { item->goalAnimState = LS_STOP; @@ -19,19 +28,15 @@ void lara_as_hang(ITEM_INFO* item, COLL_INFO* coll)//19A28, 19B5C (F) } if (TrInput & IN_LOOK) + { LookUpDown(); - - coll->enableBaddiePush = false; - coll->enableSpaz = false; - - Camera.targetAngle = 0; - Camera.targetElevation = -ANGLE(45.0f); + } } +// State: 10 +// State code: lara_as_hang() void lara_col_hang(ITEM_INFO* item, COLL_INFO* coll)//19AC8, 19BFC (F) { - /*state 10*/ - /*state code: lara_as_hang*/ item->fallspeed = 0; item->gravityStatus = false; @@ -41,10 +46,9 @@ void lara_col_hang(ITEM_INFO* item, COLL_INFO* coll)//19AC8, 19BFC (F) if (TrInput & IN_LEFT || TrInput & IN_LSTEP) { - if (CanLaraHangSideways(item, coll, -ANGLE(90.0f))) + if (CanLaraHangSideways(item, coll, ANGLE(-90.0f))) { item->goalAnimState = LS_SHIMMY_LEFT; - return; } @@ -52,9 +56,13 @@ void lara_col_hang(ITEM_INFO* item, COLL_INFO* coll)//19AC8, 19BFC (F) if (flag != 0) { if (flag <= 0) + { item->goalAnimState = LS_SHIMMY_INNER_LEFT; + } else + { item->goalAnimState = LS_SHIMMY_OUTER_LEFT; + } return; } @@ -65,7 +73,6 @@ void lara_col_hang(ITEM_INFO* item, COLL_INFO* coll)//19AC8, 19BFC (F) if (CanLaraHangSideways(item, coll, ANGLE(90.0f))) { item->goalAnimState = LS_SHIMMY_RIGHT; - return; } @@ -73,9 +80,13 @@ void lara_col_hang(ITEM_INFO* item, COLL_INFO* coll)//19AC8, 19BFC (F) if (flag != 0) { if (flag <= 0) + { item->goalAnimState = LS_SHIMMY_INNER_RIGHT; + } else + { item->goalAnimState = LS_SHIMMY_OUTER_RIGHT; + } return; } @@ -174,127 +185,137 @@ void lara_col_hang(ITEM_INFO* item, COLL_INFO* coll)//19AC8, 19BFC (F) } } -void lara_as_hangleft(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +// State: 30 +// Collision: lara_col_hang_left() +void lara_as_shimmy_left(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - /*state 30*/ - /*collision: lara_col_hangleft*/ + Camera.targetAngle = 0; + Camera.targetElevation = ANGLE(-45.0f); + coll->enableBaddiePush = false; coll->enableSpaz = false; - Camera.targetAngle = 0; - Camera.targetElevation = -ANGLE(45.0f); - if (!(TrInput & (IN_LEFT | IN_LSTEP))) - item->goalAnimState = LS_HANG; -} -void lara_col_hangleft(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) + if (TrInput & IN_LEFT || TrInput & IN_LSTEP) + { + item->goalAnimState = LS_SHIMMY_LEFT; + return; + } + + item->goalAnimState = LS_HANG; +} +// State: 30 +// State code: lara_as_hang_left() +void lara_col_shimmy_left(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - /*state 30*/ - /*state code: lara_as_hangleft*/ - Lara.moveAngle = -ANGLE(90); - coll->radius = 102; /* @ORIGINAL_BUG: this value (instead of LARA_RAD) can make Lara glitch if coll->frontType is DIAGONAL or SPLIT_TRI */ + Lara.moveAngle = ANGLE(-90.0f); + coll->radius = LARA_RAD; /* @ORIGINAL_BUG: original value, 102, can make Lara glitch if coll->frontType is DIAGONAL or SPLIT_TRI */ LaraHangTest(item, coll); - Lara.moveAngle = -ANGLE(90); + Lara.moveAngle = ANGLE(-90.0f); } -void lara_as_hangright(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +// State: 31 +// Collision: lara_col_shimmy_right() +void lara_as_shimmy_right(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - /*state 31*/ - /*collision: lara_col_hangright*/ + Camera.targetAngle = 0; + Camera.targetElevation = ANGLE(-45.0f); + coll->enableBaddiePush = false; coll->enableSpaz = false; - Camera.targetAngle = 0; - Camera.targetElevation = -ANGLE(45.0f); - if (!(TrInput & (IN_RIGHT | IN_RSTEP))) - item->goalAnimState = LS_HANG; + + if (TrInput & IN_RIGHT || TrInput & IN_RSTEP) + { + item->goalAnimState = LS_SHIMMY_RIGHT; + return; + } + + item->goalAnimState = LS_HANG; } -void lara_col_hangright(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +// State: 31 +// State code: lara_as_shimmy_right() +void lara_col_shimmy_right(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - /*state 31*/ - /*state code: lara_as_hangright*/ - Lara.moveAngle = ANGLE(90); - coll->radius = 102; /* @ORIGINAL_BUG: this value (instead of LARA_RAD) can make Lara glitch if coll->frontType is DIAGONAL or SPLIT_TRI */ + Lara.moveAngle = ANGLE(90.0f); + coll->radius = LARA_RAD; /* @ORIGINAL_BUG: original value, 102, can make Lara glitch if coll->frontType is DIAGONAL or SPLIT_TRI */ LaraHangTest(item, coll); - Lara.moveAngle = ANGLE(90); + Lara.moveAngle = ANGLE(90.0f); } -/*go around corners*/ +// ------------------------------ +// SHIMMYING AROUND CORNERS +// Control & Collision Functions +// ------------------------------ +// State: 107 +// Collision: lara_default_col() void lara_as_extcornerl(ITEM_INFO* item, COLL_INFO* coll)//1A1F0(<), 1A324(<) (F) { - /*state 107*/ - /*collision: lara_default_col*/ Camera.laraNode = 8; Camera.targetElevation = ANGLE(33.0f); + SetCornerAnim(item, coll, ANGLE(90.0f), item->animNumber == LA_SHIMMY_LEFT_CORNER_OUTER_END || item->animNumber == LA_LADDER_LEFT_CORNER_OUTER_END); } +// State: 108 +// Collision: lara_default_col() void lara_as_extcornerr(ITEM_INFO* item, COLL_INFO* coll)//1A244(<), 1A378(<) (F) { - /*state 108*/ - /*collision: lara_default_col*/ Camera.laraNode = 8; Camera.targetElevation = ANGLE(33.0f); + SetCornerAnim(item, coll, -ANGLE(90.0f), item->animNumber == LA_SHIMMY_RIGHT_CORNER_OUTER_END || item->animNumber == LA_LADDER_RIGHT_CORNER_OUTER_END); } +// State: 109 +// Collision: lara_default_col() void lara_as_intcornerl(ITEM_INFO* item, COLL_INFO* coll)//1A298(<), 1A3CC(<) (F) { - /*state 109*/ - /*collision: lara_default_col*/ Camera.laraNode = 8; Camera.targetElevation = ANGLE(33.0f); + SetCornerAnim(item, coll, -ANGLE(90.0f), item->animNumber == LA_SHIMMY_LEFT_CORNER_INNER_END || item->animNumber == LA_LADDER_LEFT_CORNER_INNER_END); } +// State: 110 +// Collision: lara_default_col() void lara_as_intcornerr(ITEM_INFO* item, COLL_INFO* coll)//1A2EC(<), 1A420(<) (F) { - /*state 110*/ - /*collision: lara_default_col*/ Camera.laraNode = 8; Camera.targetElevation = ANGLE(33.0f); + SetCornerAnim(item, coll, ANGLE(90.0f), item->animNumber == LA_SHIMMY_RIGHT_CORNER_INNER_END || item->animNumber == LA_LADDER_RIGHT_CORNER_INNER_END); } -/*feet hanging and shimmying -////obviously, not all animations were made yet, we still need: +// ------------------------------ +// HANGING AND SHIMMYING BY FEET +// Control & Collision Functions +// ------------------------------ + +/*obviously, not all animations were made yet, we still need: -crouch pull up(works well, tested with placeholder anim) -corner anims(works well, tested with placeholder anims) -handstand(not tested)*/ +// State: 139 +// Collision: lara_col_hang_feet() void lara_as_hang_feet(ITEM_INFO* item, COLL_INFO* coll) { - /*state 139*/ - /*collision: lara_col_hang_feet*/ - Lara.isClimbing = false; - - if (item->hitPoints <= 0) - { - item->goalAnimState = LS_STOP; - return; - } - - if (TrInput & IN_LOOK) - LookUpDown(); - - coll->enableBaddiePush = false; - coll->enableSpaz = false; - Camera.targetAngle = 0; - Camera.targetElevation = -ANGLE(45.0f); + lara_as_hang(item, coll); } +// State: 139 +// Collision: lara_as_hang_feet() void lara_col_hang_feet(ITEM_INFO* item, COLL_INFO* coll) { - /*state 139*/ - /*state code: lara_as_hang_feet*/ item->fallspeed = 0; item->gravityStatus = false; @@ -303,7 +324,9 @@ void lara_col_hang_feet(ITEM_INFO* item, COLL_INFO* coll) LaraHangTest(item, coll); if (!(TrInput & IN_ACTION)) + { item->goalAnimState = LS_JUMP_UP; + } if (item->animNumber == LA_HANG_FEET_IDLE) { @@ -316,6 +339,7 @@ void lara_col_hang_feet(ITEM_INFO* item, COLL_INFO* coll) item->goalAnimState = LS_SHIMMY_FEET_LEFT; return; } + flag = LaraHangLeftCornerTest(item, coll); if (flag != 0) { @@ -328,7 +352,6 @@ void lara_col_hang_feet(ITEM_INFO* item, COLL_INFO* coll) } - if (TrInput & IN_RIGHT || TrInput & IN_RSTEP) { if (CanLaraHangSideways(item, coll, ANGLE(90.0f))) @@ -337,6 +360,7 @@ void lara_col_hang_feet(ITEM_INFO* item, COLL_INFO* coll) return; } + flag = LaraHangRightCornerTest(item, coll); if (flag != 0) { @@ -348,7 +372,6 @@ void lara_col_hang_feet(ITEM_INFO* item, COLL_INFO* coll) } } - TestForObjectOnLedge(item, coll); if (TrInput & IN_FORWARD) { @@ -378,6 +401,7 @@ void lara_col_hang_feet(ITEM_INFO* item, COLL_INFO* coll) } } } + if (coll->frontFloor < -650 && coll->frontFloor - coll->frontCeiling >= -256 && coll->frontFloor - coll->leftCeiling2 >= -256 && @@ -387,6 +411,7 @@ void lara_col_hang_feet(ITEM_INFO* item, COLL_INFO* coll) { item->goalAnimState = LS_HANG_TO_CRAWL; item->requiredAnimState = LS_CROUCH_IDLE; + return; } } @@ -412,97 +437,120 @@ void lara_col_hang_feet(ITEM_INFO* item, COLL_INFO* coll) }*///commenting till daniel makes anims Lara.moveAngle = 0; + LaraHangTest(item, coll); } } -void lara_as_hang_feet_shimmyr(ITEM_INFO* item, COLL_INFO* coll) +// State: 140 +// Collision: lara_col_hang_feet_shimmy_right() +void lara_as_shimmy_feet_right(ITEM_INFO* item, COLL_INFO* coll) { - /*state 140*/ - /*collision: lara_col_hang_feet_shimmyr*/ + Camera.targetAngle = 0; + Camera.targetElevation = ANGLE(-45.0f); + coll->enableBaddiePush = false; coll->enableSpaz = false; + + if (TrInput & IN_RIGHT || TrInput & IN_RSTEP) + { + item->goalAnimState = LS_SHIMMY_FEET_RIGHT; + return; + } + + item->goalAnimState = LS_HANG_FEET; +} + +// State: 140 +// State code: lara_as_hang_feet_shimmy_right() +void lara_col_shimmy_feet_right(ITEM_INFO* item, COLL_INFO* coll) +{ + lara_col_shimmy_right(item, coll); +} + +// State: 141 +// Collision: lara_as_hang_feet_shimmy_left() +void lara_as_shimmy_feet_left(ITEM_INFO* item, COLL_INFO* coll) +{ Camera.targetAngle = 0; - Camera.targetElevation = -ANGLE(45.0f); + Camera.targetElevation = ANGLE(-45.0f); - if (!(TrInput & (IN_RIGHT | IN_RSTEP))) - item->goalAnimState = LS_HANG_FEET; -} - -void lara_col_hang_feet_shimmyr(ITEM_INFO* item, COLL_INFO* coll) -{ - /*state 140*/ - /*state code: lara_as_hang_feet_shimmyr*/ - Lara.moveAngle = ANGLE(90); - coll->radius = LARA_RAD; - LaraHangTest(item, coll); - Lara.moveAngle = ANGLE(90); -} - -void lara_as_hang_feet_shimmyl(ITEM_INFO* item, COLL_INFO* coll) -{ - /*state 141*/ - /*collision: lara_col_hang_feet_shimmyl*/ coll->enableBaddiePush = false; coll->enableSpaz = false; - Camera.targetAngle = 0; - Camera.targetElevation = -ANGLE(45.0f); - if (!(TrInput & (IN_LEFT | IN_LSTEP))) - item->goalAnimState = LS_HANG_FEET; + + if (TrInput & IN_LEFT || TrInput & IN_LSTEP) + { + item->goalAnimState = LS_SHIMMY_FEET_LEFT; + return; + } + + item->goalAnimState = LS_HANG_FEET; } -void lara_col_hang_feet_shimmyl(ITEM_INFO* item, COLL_INFO* coll) +// State: 141 +// State code: lara_as_hang_feet_shimmy_left() +void lara_col_shimmy_feet_left(ITEM_INFO* item, COLL_INFO* coll) { - /*state 141*/ - /*state code: lara_as_hang_feet_shimmyl*/ - Lara.moveAngle = -ANGLE(90); - coll->radius = LARA_RAD; - LaraHangTest(item, coll); - Lara.moveAngle = -ANGLE(90); + lara_col_shimmy_left(item, coll); } -/*go around corners feet*/ +// ------------------------------ +// SHIMMYING BY FEET AROUND CORNERS +// Control & Collision Functions +// ------------------------------ -void lara_as_hang_feet_inRcorner(ITEM_INFO* item, COLL_INFO* coll) +// State 142 +// Collision: lara_default_col() +void lara_as_hang_feet_right_corner_inner(ITEM_INFO* item, COLL_INFO* coll) { - /*state 142*/ - /*collision: lara_default_col*/ Camera.laraNode = 8; Camera.targetElevation = ANGLE(33.0f); + if (item->frameNumber == g_Level.Anims[LA_SHIMMY_FEET_RIGHT_CORNER_INNER].frameEnd) // I don't like this either but it's better than adding 4 new 1 frame anims? + { SetCornerAnimFeet(item, coll, ANGLE(90.0f), item->animNumber = LA_SHIMMY_FEET_RIGHT_CORNER_INNER); + } } -void lara_as_hang_feet_inLcorner(ITEM_INFO* item, COLL_INFO* coll) +// State 143 +// Collision: lara_default_col() +void lara_as_hang_feet_left_corner_inner(ITEM_INFO* item, COLL_INFO* coll) { - /*state 143*/ - /*collision: lara_default_col*/ Camera.laraNode = 8; Camera.targetElevation = ANGLE(33.0f); + if (item->frameNumber == g_Level.Anims[LA_SHIMMY_FEET_LEFT_CORNER_INNER].frameEnd) + { SetCornerAnimFeet(item, coll, -ANGLE(90.0f), item->animNumber = LA_SHIMMY_FEET_LEFT_CORNER_INNER); + } } -void lara_as_hang_feet_outRcorner(ITEM_INFO* item, COLL_INFO* coll) +// State 144 +// Collision: lara_default_col() +void lara_as_hang_feet_right_corner_outer(ITEM_INFO* item, COLL_INFO* coll) { - /*state 144*/ - /*collision: lara_default_col*/ Camera.laraNode = 8; Camera.targetElevation = ANGLE(33.0f); + if (item->frameNumber == g_Level.Anims[LA_SHIMMY_FEET_RIGHT_CORNER_OUTER].frameEnd) + { SetCornerAnimFeet(item, coll, -ANGLE(90.0f), item->animNumber = LA_SHIMMY_FEET_RIGHT_CORNER_OUTER); + } } -void lara_as_hang_feet_outLcorner(ITEM_INFO* item, COLL_INFO* coll) +// State 145 +// Collision: lara_default_col() +void lara_as_hang_feet_left_corner_outer(ITEM_INFO* item, COLL_INFO* coll) { - /*state 145*/ - /*collision: lara_default_col*/ Camera.laraNode = 8; Camera.targetElevation = ANGLE(33.0f); + if (item->frameNumber == g_Level.Anims[LA_SHIMMY_FEET_LEFT_CORNER_OUTER].frameEnd) + { SetCornerAnimFeet(item, coll, ANGLE(90.0f), item->animNumber = LA_SHIMMY_FEET_LEFT_CORNER_OUTER); + } } diff --git a/TR5Main/Game/Lara/lara_hang.h b/TR5Main/Game/Lara/lara_hang.h index e3cc79047..9aaa6047d 100644 --- a/TR5Main/Game/Lara/lara_hang.h +++ b/TR5Main/Game/Lara/lara_hang.h @@ -1,27 +1,30 @@ #pragma once #include "lara_struct.h" -/*normal hanging and shimmying*/ +// Hanging and shimmying control & collision functions. void lara_as_hang(ITEM_INFO* item, COLL_INFO* coll); void lara_col_hang(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_hangleft(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_hangleft(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_hangright(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_hangright(ITEM_INFO* item, COLL_INFO* coll); -/*go around corners*/ +void lara_as_shimmy_left(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_shimmy_left(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_shimmy_right(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_shimmy_right(ITEM_INFO* item, COLL_INFO* coll); + +// Shimmying around corners control & collision functions. void lara_as_extcornerl(ITEM_INFO* item, COLL_INFO* coll); void lara_as_extcornerr(ITEM_INFO* item, COLL_INFO* coll); void lara_as_intcornerl(ITEM_INFO* item, COLL_INFO* coll); void lara_as_intcornerr(ITEM_INFO* item, COLL_INFO* coll); -/*feet hanging and shimmying*/ + +// Hanging and shimmying by feet control & collision functions. void lara_as_hang_feet(ITEM_INFO* item, COLL_INFO* coll); void lara_col_hang_feet(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_hang_feet_shimmyr(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_hang_feet_shimmyr(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_hang_feet_shimmyl(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_hang_feet_shimmyl(ITEM_INFO* item, COLL_INFO* coll); -/*go around corners feet*/ -void lara_as_hang_feet_inRcorner(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_hang_feet_inLcorner(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_hang_feet_outRcorner(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_hang_feet_outLcorner(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_shimmy_feet_right(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_shimmy_feet_right(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_shimmy_feet_left(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_shimmy_feet_left(ITEM_INFO* item, COLL_INFO* coll); + +// Shimmying by feet around corners control & collision functions. +void lara_as_hang_feet_right_corner_inner(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_hang_feet_left_corner_inner(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_hang_feet_right_corner_outer(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_hang_feet_left_corner_outer(ITEM_INFO* item, COLL_INFO* coll); diff --git a/TR5Main/Game/Lara/lara_initialise.cpp b/TR5Main/Game/Lara/lara_initialise.cpp index de7dbaf4a..16f2ba76f 100644 --- a/TR5Main/Game/Lara/lara_initialise.cpp +++ b/TR5Main/Game/Lara/lara_initialise.cpp @@ -149,7 +149,7 @@ void InitialiseLaraAnims(ITEM_INFO* item) // (F) (D) Lara.waterStatus = LW_ABOVE_WATER; item->goalAnimState = LS_STOP; item->currentAnimState = LS_STOP; - item->animNumber = LA_STAND_SOLID; + item->animNumber = LA_STAND_IDLE; item->frameNumber = g_Level.Anims[item->animNumber].frameBase; } } diff --git a/TR5Main/Game/Lara/lara_objects.cpp b/TR5Main/Game/Lara/lara_objects.cpp index 57c6e141a..c87d8fc15 100644 --- a/TR5Main/Game/Lara/lara_objects.cpp +++ b/TR5Main/Game/Lara/lara_objects.cpp @@ -6,73 +6,72 @@ #include "rope.h" #include "lara_tests.h" -/*This file has "all" lara_as/lara_col functions where Lara is interacting with an object.*/ +// OBJECT INTERACTION -/*pickups*/ +// ------------------------------ +// PICKUP +// Control & Collision Functions +// ------------------------------ + +// States: 39, 98 +// Collision: lara_default_col() void lara_as_pickup(ITEM_INFO* item, COLL_INFO* coll)//1AB00(<), 1AC34(<) (F) { - /*state 39, 98*/ - /*collision: lara_default_col*/ + Camera.targetAngle = ANGLE(-130.0f); + Camera.targetElevation = ANGLE(-15.0f); + Camera.targetDistance = SECTOR(1); Lara.look = false; + coll->enableBaddiePush = false; coll->enableSpaz = false; - Camera.targetAngle = -ANGLE(130.0f); - Camera.targetElevation = -ANGLE(15.0f); - Camera.targetDistance = SECTOR(1); } -void lara_as_pickupflare(ITEM_INFO* item, COLL_INFO* coll)//1AB5C(<), 1AC90(<) (F) +// State: 67 +// Collison: lara_default_col() +void lara_as_pickup_flare(ITEM_INFO* item, COLL_INFO* coll)//1AB5C(<), 1AC90(<) (F) { - /*state 67*/ - /*collison: lara_default_col*/ - Lara.look = false; - coll->enableBaddiePush = false; - coll->enableSpaz = false; Camera.targetAngle = ANGLE(130.0f); - Camera.targetElevation = -ANGLE(15.0f); + Camera.targetElevation = ANGLE(-15.0f); Camera.targetDistance = SECTOR(1); + Lara.look = false; + + coll->enableBaddiePush = false; + coll->enableSpaz = false; + if (item->frameNumber == g_Level.Anims[item->animNumber].frameEnd - 1) + { Lara.gunStatus = LG_NO_ARMS; -} -/*end pickups*/ -/*-*/ -/*switches*/ -void lara_as_switchon(ITEM_INFO* item, COLL_INFO* coll)//1ABEC(<), 1AD20(<) (F) -{ - /*states 40, 126*/ - /*collision: lara_default_col*/ - Lara.look = false; - coll->enableBaddiePush = false; - coll->enableSpaz = false; - Camera.targetAngle = ANGLE(80.0f); - Camera.targetElevation = -ANGLE(25.0f); - Camera.targetDistance = SECTOR(1); - Camera.speed = 6; + } } -void lara_as_switchoff(ITEM_INFO* item, COLL_INFO* coll)//1AC54(<), 1AD88(<) (F) +// ------------------------------ +// SWITCH +// Control & Collision Functions +// ------------------------------ + +// States: 41, 42, 126 +// Collision: lara_default_col() +void lara_as_switch(ITEM_INFO* item, COLL_INFO* coll) { - /*state 41*/ - /*collision: lara_default_col*/ - Lara.look = false; - coll->enableBaddiePush = false; - coll->enableSpaz = false; Camera.targetAngle = ANGLE(80.0f); - Camera.targetElevation = -ANGLE(25.0f); + Camera.targetElevation = ANGLE(-25.0f); Camera.targetDistance = SECTOR(1); Camera.speed = 6; + Lara.look = false; + + coll->enableBaddiePush = false; + coll->enableSpaz = false; } +// State: 95 +// State code: lara_as_controlledl() void lara_col_turnswitch(ITEM_INFO* item, COLL_INFO* coll)//1B1B4(<), 1B2E8(<) (F) { - /*state 95*/ - /*state code: lara_as_controlledl*/ if (coll->old.x != item->pos.xPos || coll->old.z != item->pos.zPos) { if (item->animNumber == LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_CONTINUE) { item->pos.yRot -= ANGLE(90.0f); - item->animNumber = LA_TURNSWITCH_PUSH_COUNTER_CLOCKWISE_END; item->frameNumber = g_Level.Anims[item->animNumber].frameBase; } @@ -80,40 +79,42 @@ void lara_col_turnswitch(ITEM_INFO* item, COLL_INFO* coll)//1B1B4(<), 1B2E8(<) ( if (item->animNumber == LA_TURNSWITCH_PUSH_CLOCKWISE_CONTINUE) { item->pos.yRot += ANGLE(90.0f); - item->animNumber = LA_TURNSWITCH_PUSH_CLOCKWISE_END; item->frameNumber = g_Level.Anims[item->animNumber].frameBase; } } } -/*end switches*/ -/*-*/ -/*puzzles and keys*/ -void lara_as_usekey(ITEM_INFO* item, COLL_INFO* coll)//1ACBC(<), 1ADF0(<) (F) + +// ------------------------------ +// PUZZLES & KEYS +// Control & Collision Functions +// ------------------------------ + +// State: 42 +// Collision: lara_default_col() +void lara_as_use_key(ITEM_INFO* item, COLL_INFO* coll)//1ACBC(<), 1ADF0(<) (F) { - /*state 42*/ - /*collision: lara_default_col*/ + Camera.targetAngle = ANGLE(-80.0f); + Camera.targetElevation = ANGLE(-25.0f); + Camera.targetDistance = SECTOR(1); Lara.look = false; + coll->enableBaddiePush = false; coll->enableSpaz = false; - Camera.targetAngle = -ANGLE(80.0f); - Camera.targetElevation = -4550; - Camera.targetDistance = SECTOR(1); } -void lara_as_usepuzzle(ITEM_INFO* item, COLL_INFO* coll)//1AD18(<), 1AE4C(<) (F) +// State: 43 +// Collision: lara_default_col() +void lara_as_use_puzzle(ITEM_INFO* item, COLL_INFO* coll)//1AD18(<), 1AE4C(<) (F) { - /*state 43*/ - /*collision: lara_default_col*/ + Camera.targetAngle = ANGLE(-80.0f); + Camera.targetElevation = ANGLE(-25.0f); + Camera.targetDistance = SECTOR(1); Lara.look = false; coll->enableBaddiePush = false; coll->enableSpaz = false; - Camera.targetAngle = -ANGLE(80.0f); - Camera.targetElevation = -ANGLE(25.0f); - Camera.targetDistance = SECTOR(1); - if (item->frameNumber == g_Level.Anims[item->animNumber].frameEnd) { if (item->itemFlags[0]) @@ -124,50 +125,62 @@ void lara_as_usepuzzle(ITEM_INFO* item, COLL_INFO* coll)//1AD18(<), 1AE4C(<) (F) } } } -/*end puzzles and keys*/ -/*-*/ -/*pushables*/ -void lara_as_pushblock(ITEM_INFO* item, COLL_INFO* coll)//1AA04(<), 1AB38(<) (F) + +// ------------------------------ +// PUSHABLE +// Control & Collision Functions +// ------------------------------ + +// State: 36 +// Collision: lara_default_col() +void lara_as_pushable_push(ITEM_INFO* item, COLL_INFO* coll)//1AA04(<), 1AB38(<) (F) { - /*state 36*/ - /*collision: lara_default_col*/ - Lara.look = false; - coll->enableBaddiePush = false; - coll->enableSpaz = false; Camera.flags = CF_FOLLOW_CENTER; Camera.targetAngle = ANGLE(90.0f); - Camera.targetElevation = -ANGLE(25.0f); -} - -void lara_as_pullblock(ITEM_INFO* item, COLL_INFO* coll)//1AA60(<), 1AB94(<) (F) -{ - /*state 37*/ - /*collision: lara_default_col*/ + Camera.targetElevation = ANGLE(-25.0f); Lara.look = false; + coll->enableBaddiePush = false; coll->enableSpaz = false; +} + +// State: 37 +// Collision: lara_default_col() +void lara_as_pushable_pull(ITEM_INFO* item, COLL_INFO* coll)//1AA60(<), 1AB94(<) (F) +{ Camera.flags = CF_FOLLOW_CENTER; Camera.targetAngle = ANGLE(35.0f); - Camera.targetElevation = -ANGLE(25.0f); -} + Camera.targetElevation = ANGLE(-25.0f); + Lara.look = false; -void lara_as_ppready(ITEM_INFO* item, COLL_INFO* coll)//1AABC(<), 1ABF0(<) (F) -{ - /*state 38*/ - /*collision: lara_default_col*/ coll->enableBaddiePush = false; coll->enableSpaz = false; - Camera.targetAngle = ANGLE(75.0f); - if (!(TrInput & IN_ACTION)) - item->goalAnimState = LS_STOP; } -/*end pushables*/ -/*-*/ -/*pulley*/ + +// State: 38 +// Collision: lara_default_col() +void lara_as_pushable_ready(ITEM_INFO* item, COLL_INFO* coll)//1AABC(<), 1ABF0(<) (F) +{ + Camera.targetAngle = ANGLE(75.0f); + + coll->enableBaddiePush = false; + coll->enableSpaz = false; + + if (!(TrInput & IN_ACTION)) + { + item->goalAnimState = LS_STOP; + } +} + +// ------------------------------ +// PULLEY +// Control & Collision Functions +// ------------------------------ + +// State: 104 +// Collision: lara_default_col() void lara_as_pulley(ITEM_INFO* item, COLL_INFO* coll)//1B288, 1B3BC (F) { - /*state 104*/ - /*collision: lara_default_col*/ ITEM_INFO* p = (ITEM_INFO*)Lara.generalPtr; Lara.look = false; @@ -206,33 +219,42 @@ void lara_as_pulley(ITEM_INFO* item, COLL_INFO* coll)//1B288, 1B3BC (F) p->itemFlags[2] = 1; if (p->itemFlags[3] >= 0) + { p->triggerFlags = abs(p->itemFlags[3]); + } else + { p->itemFlags[0] = 1; + } } } } if (item->animNumber == LA_PULLEY_RELEASE && item->frameNumber == g_Level.Anims[item->animNumber].frameEnd - 1) + { Lara.gunStatus = LG_NO_ARMS; + } } -/*end pulley*/ -/*-*/ -/*parallel bars*/ -void lara_as_parallelbars(ITEM_INFO* item, COLL_INFO* coll) + +// ------------------------------ +// SWING BAR +// Control & Collision Functions +// ------------------------------ + +// State: 128 +// Collision: lara_default_col() +void lara_as_swing_bar(ITEM_INFO* item, COLL_INFO* coll) { - /*state 128*/ - /*collision: lara_default_col*/ - if (!(TrInput & IN_ACTION)) + if (!(TrInput & IN_ACTION) || TrInput & IN_JUMP) { item->goalAnimState = LS_BARS_JUMP; } } -void lara_as_pbleapoff(ITEM_INFO* item, COLL_INFO* coll)//1D244, 1D3D8 (F) +// State: 129 +// Collision: lara_default_col() +void lara_as_swing_bar_leap(ITEM_INFO* item, COLL_INFO* coll)//1D244, 1D3D8 (F) { - /*state 129*/ - /*collision: lara_default_col*/ ITEM_INFO* pitem = (ITEM_INFO*)Lara.generalPtr; item->gravityStatus = true; @@ -241,13 +263,13 @@ void lara_as_pbleapoff(ITEM_INFO* item, COLL_INFO* coll)//1D244, 1D3D8 (F) { int dist; - if (item->pos.yRot == pitem->pos.yRot) + if (item->pos.yRot == item->pos.yRot) { - dist = pitem->triggerFlags / 100 - 2; + dist = item->triggerFlags / 100 - 2; } else { - dist = pitem->triggerFlags % 100 - 2; + dist = item->triggerFlags % 100 - 2; } item->fallspeed = -(20 * dist + 64); @@ -262,30 +284,39 @@ void lara_as_pbleapoff(ITEM_INFO* item, COLL_INFO* coll)//1D244, 1D3D8 (F) item->animNumber = LA_REACH; item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->goalAnimState = LS_REACH; item->currentAnimState = LS_REACH; } } -/*end parallel bars*/ -/*-*/ -/*tightropes*/ -void lara_as_trpose(ITEM_INFO* item, COLL_INFO* coll) -{ - /*state 119*/ - /*collision: lara_default_col*/ - if (TrInput & IN_LOOK) - LookUpDown(); - GetTighRopeFallOff(127); +// ------------------------------ +// TIGHTROPE +// Control & Collision Functions +// ------------------------------ + +// State: 119 +// Collision: lara_default_col() +void lara_as_tightrope_stop(ITEM_INFO* item, COLL_INFO* coll) +{ + if (TrInput & IN_LOOK) + { + LookUpDown(); + } + + GetTighropeFallOff(127); + if (LaraItem->currentAnimState != LS_TIGHTROPE_UNBALANCE_LEFT) { if (Lara.tightRopeFall) { if (GetRandomControl() & 1) + { item->goalAnimState = LS_TIGHTROPE_UNBALANCE_RIGHT; + } else + { item->goalAnimState = LS_TIGHTROPE_UNBALANCE_LEFT; + } } else { @@ -300,17 +331,18 @@ void lara_as_trpose(ITEM_INFO* item, COLL_INFO* coll) item->currentAnimState = LS_TIGHTROPE_TURN_180; item->animNumber = LA_TIGHTROPE_TURN_180; item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - GetTighRopeFallOff(1); + + GetTighropeFallOff(1); } } } } } -void lara_as_trwalk(ITEM_INFO* item, COLL_INFO* coll) +// State: 121 +// Collision: lara_default_col() +void lara_as_tightrope_walk(ITEM_INFO* item, COLL_INFO* coll) { - /*state 121*/ - /*collision: lara_default_col*/ if (Lara.tightRopeOnCount) { Lara.tightRopeOnCount--; @@ -328,7 +360,7 @@ void lara_as_trwalk(ITEM_INFO* item, COLL_INFO* coll) } else { - GetTighRopeFallOff(127); + GetTighropeFallOff(127); } if (LaraItem->currentAnimState != LS_TIGHTROPE_UNBALANCE_LEFT) @@ -339,60 +371,44 @@ void lara_as_trwalk(ITEM_INFO* item, COLL_INFO* coll) } if (item->goalAnimState != LS_TIGHTROPE_EXIT && - (Lara.tightRopeFall - || (TrInput & IN_BACK || TrInput & IN_ROLL || !(TrInput & IN_FORWARD)) && !Lara.tightRopeOnCount && !Lara.tightRopeOff)) + (Lara.tightRopeFall || (TrInput & IN_BACK || TrInput & IN_ROLL || !(TrInput & IN_FORWARD)) && !Lara.tightRopeOnCount && !Lara.tightRopeOff)) { item->goalAnimState = LS_TIGHTROPE_IDLE; } } } -void lara_as_trfall(ITEM_INFO* item, COLL_INFO* coll) +// States: 122, 123 +// Collision: lara_default_col() +void lara_as_tightrope_fall(ITEM_INFO* item, COLL_INFO* coll) { - /*states 122, 123*/ - /*collision: lara_default_col*/ if (item->animNumber == LA_TIGHTROPE_FALL_LEFT || item->animNumber == LA_TIGHTROPE_FALL_RIGHT) { if (item->frameNumber == g_Level.Anims[item->animNumber].frameEnd) { - PHD_VECTOR pos; - pos.x = 0; - pos.y = 0; - pos.z = 0; - - GetLaraJointPosition(&pos, LM_RFOOT); - - item->pos.xPos = pos.x; - item->pos.yPos = pos.y + 75; - item->pos.zPos = pos.z; - - item->goalAnimState = LS_FREEFALL; - item->currentAnimState = LS_FREEFALL; - - item->animNumber = LA_FREEFALL; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->fallspeed = 81; Camera.targetspeed = 16; } } else { - int undoInp, wrongInput; + int recoveryInput, wrongInput; int undoAnim, undoFrame; if (Lara.tightRopeOnCount > 0) + { Lara.tightRopeOnCount--; + } if (item->animNumber == LA_TIGHTROPE_UNBALANCE_LEFT) { - undoInp = IN_RIGHT; + recoveryInput = IN_RIGHT; wrongInput = IN_LEFT; undoAnim = LA_TIGHTROPE_RECOVER_LEFT; } else if (item->animNumber == LA_TIGHTROPE_UNBALANCE_RIGHT) { - undoInp = IN_LEFT; + recoveryInput = IN_LEFT; wrongInput = IN_RIGHT; undoAnim = LA_TIGHTROPE_RECOVER_RIGHT; } @@ -403,7 +419,7 @@ void lara_as_trfall(ITEM_INFO* item, COLL_INFO* coll) undoFrame = g_Level.Anims[item->animNumber].frameEnd + g_Level.Anims[undoAnim].frameBase - item->frameNumber; - if (TrInput & undoInp && Lara.tightRopeOnCount == 0) + if (TrInput & recoveryInput && Lara.tightRopeOnCount == 0) { item->currentAnimState = LS_TIGHTROPE_RECOVER_BALANCE; item->goalAnimState = LS_TIGHTROPE_IDLE; @@ -417,19 +433,25 @@ void lara_as_trfall(ITEM_INFO* item, COLL_INFO* coll) if (TrInput & wrongInput) { if (Lara.tightRopeOnCount < 10) + { Lara.tightRopeOnCount += (GetRandomControl() & 3) + 2; + } } } } } -/*end tightropes*/ -/*-*/ -/*ropes*/ -void lara_as_ropel(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) + +// ------------------------------ +// ROPE +// Control & Collision Functions +// ------------------------------ + +// State: 90 +// Collision: lara_void_func() +void lara_as_rope_turn_clockwise(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - /*state 90*/ - /*collision: lara_void_func*/ - if (TrInput & IN_ACTION) + if ((TrInput & IN_ACTION && !EnableActionToggle) || + (!(TrInput & IN_ACTION) && EnableActionToggle)) { if (TrInput & IN_LEFT) { @@ -439,16 +461,22 @@ void lara_as_ropel(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { item->goalAnimState = LS_ROPE_IDLE; } + + return; } - else + else if ((!(TrInput & IN_ACTION) && !EnableActionToggle) || + (TrInput & IN_ACTION && EnableActionToggle)) // How can I check for a pull button press (down, let go)? { FallFromRope(item); } } -void lara_as_roper(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +// State: 91 +// Collision: lara_void_func() +void lara_as_rope_turn_counter_clockwise(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - if (TrInput & IN_ACTION) + if ((TrInput & IN_ACTION && !EnableActionToggle) || + (!(TrInput & IN_ACTION) && EnableActionToggle)) { if (TrInput & IN_RIGHT) { @@ -459,28 +487,35 @@ void lara_as_roper(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) item->goalAnimState = LS_ROPE_IDLE; } } - else + else if ((!(TrInput & IN_ACTION) && !EnableActionToggle) || + (TrInput & IN_ACTION && EnableActionToggle)) { FallFromRope(item); } } +// States : 111, 114, 115 // What? Why 115?? +// Collison: lara_col_rope() (111), lara_col_RopeSwing() (114, 115) void lara_as_rope(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - /*states 111, 114, 115*/ - /*collison: lara_col_rope(111), lara_col_ropefwd(114, 115)*/ - if (!(TrInput & IN_ACTION)) + if ((!(TrInput & IN_ACTION) && !EnableActionToggle) || + (TrInput & IN_ACTION && EnableActionToggle)) + { FallFromRope(item); + } if (TrInput & IN_LOOK) + { LookUpDown(); + } } +// State: 111 +// State code: lara_as_rope() void lara_col_rope(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - /*state: 111*/ - /*state code: lara_as_rope*/ - if (TrInput & IN_ACTION) + if ((TrInput & IN_ACTION && !EnableActionToggle) || + (!(TrInput & IN_ACTION) && EnableActionToggle)) { UpdateRopeSwing(item); @@ -511,16 +546,17 @@ void lara_col_rope(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) item->goalAnimState = LS_ROPE_TURN_COUNTER_CLOCKWISE; } } - else + else if ((!(TrInput & IN_ACTION) && !EnableActionToggle) || + (TrInput & IN_ACTION && EnableActionToggle)) { FallFromRope(item); } } -void lara_col_ropefwd(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +// States: 114, 115 // Again, why 155? +// State code: lara_as_rope() +void lara_col_rope_swing(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - /*states 114, 115*/ - /*state code: lara_as_rope(for both)*/ Camera.targetDistance = SECTOR(2); UpdateRopeSwing(item); @@ -545,13 +581,17 @@ void lara_col_ropefwd(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { Lara.ropeFrame -= (unsigned short)Lara.ropeFrameRate; if (Lara.ropeFrame < Lara.ropeDFrame) + { Lara.ropeFrame = Lara.ropeDFrame; + } } else if (Lara.ropeFrame < Lara.ropeDFrame) { Lara.ropeFrame += (unsigned short)Lara.ropeFrameRate; if (Lara.ropeFrame > Lara.ropeDFrame) + { Lara.ropeFrame = Lara.ropeDFrame; + } } item->frameNumber = Lara.ropeFrame >> 8; @@ -563,13 +603,14 @@ void lara_col_ropefwd(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { item->animNumber = LA_JUMP_UP_TO_ROPE_END; item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->currentAnimState = LS_ROPE_IDLE; item->goalAnimState = LS_ROPE_IDLE; } if (TrInput & IN_JUMP) + { JumpOffRope(item); + } } else if (item->frameNumber == g_Level.Anims[LA_ROPE_IDLE_TO_SWING].frameBase + 15) { @@ -577,159 +618,212 @@ void lara_col_ropefwd(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) } } -void lara_as_climbrope(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +// State: 112 +// Collision: lara_void_func() +void lara_as_rope_up(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - /*state 112*/ - /*collision: lara_void_func*/ - if (TrInput & IN_ROLL) - { - FallFromRope(item); - } - else - { - Camera.targetAngle = ANGLE(30.0f); + //if (TrInput & IN_ROLL) // Stupid. + //{ + // FallFromRope(item); + //} + //else + //{ + Camera.targetAngle = ANGLE(30.0f); - if (g_Level.Anims[item->animNumber].frameEnd == item->frameNumber) - { - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - Lara.ropeSegment -= 2; - } - - if (!(TrInput & IN_FORWARD) || Lara.ropeSegment <= 4) - item->goalAnimState = LS_ROPE_IDLE; + if (g_Level.Anims[item->animNumber].frameEnd == item->frameNumber) + { + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + Lara.ropeSegment -= 2; } + + if (!(TrInput & IN_FORWARD) || Lara.ropeSegment <= 4) + { + item->goalAnimState = LS_ROPE_IDLE; + } + //} } -void lara_as_climbroped(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +// State: 113 +// Collision: lara_void_func() +void lara_as_rope_down(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { - /*state 113*/ - /*collision: lara_void_func*/ LaraClimbRope(item, coll); } -/*end ropes*/ -/*-*/ -/*poles*/ -void lara_col_polestat(ITEM_INFO* item, COLL_INFO* coll)//16DFC, 16F30 (F) + +// ------------------------------ +// POLE +// Control & Collision Functions +// ------------------------------ + +void lara_as_pole(ITEM_INFO* item, COLL_INFO* coll) { - /*state 99*/ - /*state code: lara_as_null*/ if (item->hitPoints <= 0) { item->goalAnimState = LS_FREEFALL; return; } - coll->enableSpaz = false; - coll->enableBaddiePush = false; - - if (item->animNumber == LA_POLE_IDLE) + if ((TrInput & IN_ACTION && !EnableActionToggle) || + (!(TrInput & IN_ACTION) && EnableActionToggle)) { - coll->badPos = NO_BAD_POS; - coll->badNeg = -STEPUP_HEIGHT; - coll->badCeiling = BAD_JUMP_CEILING; + item->goalAnimState = LS_POLE_IDLE; - Lara.moveAngle = 0; - - coll->facing = Lara.moveAngle; - coll->radius = 100; - coll->slopesAreWalls = true; - - GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); - - if (TrInput & IN_ACTION) + if (TrInput & IN_LEFT) { - item->goalAnimState = LS_POLE_IDLE; - - if (TrInput & IN_LEFT) - { - item->goalAnimState = LS_POLE_TURN_CLOCKWISE; - } - else if (TrInput & IN_RIGHT) - { - item->goalAnimState = LS_POLE_TURN_COUNTER_CLOCKWISE; - } - - if (TrInput & IN_LOOK) - LookUpDown(); - - if (TrInput & IN_FORWARD) - { - short roomNum = item->roomNumber; - - if (item->pos.yPos - GetCeiling(GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNum), - item->pos.xPos, item->pos.yPos, item->pos.zPos) > SECTOR(1)) - { - item->goalAnimState = LS_POLE_UP; - } - } - else if (TrInput & IN_BACK && coll->midFloor > 0) - { - item->goalAnimState = LS_POLE_DOWN; - item->itemFlags[2] = 0; - } - - if (TrInput & IN_JUMP) - item->goalAnimState = LS_JUMP_BACK; + item->goalAnimState = LS_POLE_TURN_CLOCKWISE; } - else if (coll->midFloor <= 0) + else if (TrInput & IN_RIGHT) { - item->goalAnimState = LS_STOP; + item->goalAnimState = LS_POLE_TURN_COUNTER_CLOCKWISE; } - else + + if (TrInput & IN_LOOK) { - item->pos.xPos -= (phd_sin(item->pos.yRot)) << 6 >> W2V_SHIFT; - item->pos.zPos -= (phd_cos(item->pos.yRot)) << 6 >> W2V_SHIFT; - item->goalAnimState = LS_FREEFALL; + LookUpDown(); } + + if (TrInput & IN_JUMP) + { + item->goalAnimState = LS_JUMP_BACK; + } + } + else if ((!(TrInput & IN_ACTION) && !EnableActionToggle) || + (TrInput & IN_ACTION && EnableActionToggle)) + { + item->pos.xPos -= (phd_sin(item->pos.yRot)) << 6 >> W2V_SHIFT; + item->pos.zPos -= (phd_cos(item->pos.yRot)) << 6 >> W2V_SHIFT; + item->goalAnimState = LS_FREEFALL; } } -void lara_col_poleup(ITEM_INFO* item, COLL_INFO* coll)//170D8(<), 1720C(<) (F) +// TODO: split pole up and pole down into dedicated states. +// State: 99 +// State code: lara_as_null() +void lara_col_pole_stop(ITEM_INFO* item, COLL_INFO* coll)//16DFC, 16F30 (F) { - /*state: 100*/ - /*state code: lara_as_null*/ - coll->enableBaddiePush = false; coll->enableSpaz = false; + coll->enableBaddiePush = false; - if (TrInput & IN_LOOK) - LookUpDown(); + /*if (item->animNumber == LA_POLE_IDLE) + {*/ + coll->badPos = NO_BAD_POS; + coll->badNeg = -STEPUP_HEIGHT; + coll->badCeiling = BAD_JUMP_CEILING; - if (!(TrInput & IN_ACTION) || !(TrInput & IN_FORWARD) || item->hitPoints <= 0) - item->goalAnimState = LS_POLE_IDLE; + Lara.moveAngle = 0; - short roomNumber = item->roomNumber; + coll->facing = Lara.moveAngle; + coll->radius = 100; + coll->slopesAreWalls = true; - if (item->pos.yPos - - GetCeiling(GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber), - item->pos.xPos, item->pos.yPos, item->pos.zPos) < SECTOR(1)) - item->goalAnimState = LS_POLE_IDLE; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); + + if ((TrInput & IN_ACTION && !EnableActionToggle) || + (!(TrInput & IN_ACTION) && EnableActionToggle)) + { + if (TrInput & IN_FORWARD) + { + short roomNum = item->roomNumber; + + if (item->pos.yPos - GetCeiling(GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNum), + item->pos.xPos, item->pos.yPos, item->pos.zPos) > SECTOR(1)) + { + item->goalAnimState = LS_POLE_UP; + } + } + else if (TrInput & IN_BACK && coll->midFloor > 0) + { + item->goalAnimState = LS_POLE_DOWN; + item->itemFlags[2] = 0; + } + } + else if (coll->midFloor <= 0) + { + item->goalAnimState = LS_STOP; + } + else if ((!(TrInput & IN_ACTION) && !EnableActionToggle) || + (TrInput & IN_ACTION && EnableActionToggle)) + { + item->pos.xPos -= (phd_sin(item->pos.yRot)) << 6 >> W2V_SHIFT; + item->pos.zPos -= (phd_cos(item->pos.yRot)) << 6 >> W2V_SHIFT; + item->goalAnimState = LS_FREEFALL; + } + //} } -void lara_col_poledown(ITEM_INFO* item, COLL_INFO* coll)//171A0, 172D4 (F) +void lara_as_pole_up(ITEM_INFO* item, COLL_INFO* coll) +{ + +} + +void lara_as_pole_down(ITEM_INFO* item, COLL_INFO* coll) +{ + +} + +// State: 100 +// State code: lara_as_null() +void lara_col_pole_up(ITEM_INFO* item, COLL_INFO* coll)//170D8(<), 1720C(<) (F) +{ + coll->enableBaddiePush = false; + coll->enableSpaz = false; + + if (TrInput & IN_LOOK) + { + LookUpDown(); + } + + if (TrInput & IN_LEFT) + { + item->pos.yRot += 256; + } + else if (TrInput & IN_RIGHT) + { + item->pos.yRot -= 256; + } + + if (!(TrInput & IN_ACTION) || !(TrInput & IN_FORWARD) || item->hitPoints <= 0) + { + item->goalAnimState = LS_POLE_IDLE; + } + + short roomNumber = item->roomNumber; + FLOOR_INFO* f = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); + int c = GetCeiling(f, item->pos.xPos, item->pos.yPos, item->pos.zPos); + + if (item->pos.yPos - c < SECTOR(1)) + { + item->goalAnimState = LS_POLE_IDLE; + } +} + +// State: 101 +// State code: lara_as_null() +void lara_col_pole_down(ITEM_INFO* item, COLL_INFO* coll)//171A0, 172D4 (F) { - /*state: 101*/ - /*state code: lara_as_null*/ coll->enableSpaz = false; coll->enableBaddiePush = false; if (TrInput & IN_LOOK) + { LookUpDown(); + } - if ((TrInput & (IN_BACK | IN_ACTION)) != (IN_BACK | IN_ACTION) || item->hitPoints <= 0) + if ((TrInput & (IN_ACTION | IN_BACK)) != (IN_ACTION | IN_BACK) || item->hitPoints <= 0) + { item->goalAnimState = LS_POLE_IDLE; + } coll->badPos = NO_BAD_POS; coll->badNeg = -STEPUP_HEIGHT; coll->badCeiling = 0; + coll->slopesAreWalls = true; + coll->facing = Lara.moveAngle; + coll->radius = 100; + coll->facing = Lara.moveAngle; Lara.moveAngle = 0; - coll->slopesAreWalls = true; - - coll->facing = Lara.moveAngle; - coll->radius = 100; - - coll->facing = Lara.moveAngle; GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); if (coll->midFloor < 0) @@ -768,56 +862,70 @@ void lara_col_poledown(ITEM_INFO* item, COLL_INFO* coll)//171A0, 172D4 (F) item->pos.yPos += item->itemFlags[2] >> 8; } -void lara_as_poleleft(ITEM_INFO* item, COLL_INFO* coll)//17020(<), 17154(<) (F) +// TODO: check for consistency with ropes. +// State: 102 +// Collision: lara_void_func() +void lara_as_pole_turn_clockwise(ITEM_INFO* item, COLL_INFO* coll)//17020(<), 17154(<) (F) { - /*state 102*/ - /*collision: lara_void_func*/ coll->enableBaddiePush = false; coll->enableSpaz = false; - if (!(TrInput & IN_LEFT) || !(TrInput & IN_ACTION) || (TrInput & (IN_FORWARD | IN_BACK)) || item->hitPoints <= 0) + + if (!(TrInput & IN_ACTION) || !(TrInput & IN_LEFT) || (TrInput & (IN_FORWARD | IN_BACK)) || item->hitPoints <= 0) + { item->goalAnimState = LS_POLE_IDLE; + } else + { item->pos.yRot += 256; + } } -void lara_as_poleright(ITEM_INFO* item, COLL_INFO* coll)//1707C(<), 171B0(<) (F) +// State: 103 +// Collision: lara_void_func() +void lara_as_pole_turn_counter_clockwise(ITEM_INFO* item, COLL_INFO* coll)//1707C(<), 171B0(<) (F) { - /*state: 103*/ - /*collision: lara_void_func*/ coll->enableBaddiePush = false; coll->enableSpaz = false; - if (!(TrInput & IN_RIGHT) || !(TrInput & IN_ACTION) || (TrInput & (IN_FORWARD | IN_BACK)) || item->hitPoints <= 0) + + if (!(TrInput & IN_ACTION) || !(TrInput & IN_RIGHT) || (TrInput & (IN_FORWARD | IN_BACK)) || item->hitPoints <= 0) + { item->goalAnimState = LS_POLE_IDLE; + } else + { item->pos.yRot -= 256; + } } -/*end poles*/ -/*-*/ -/*deathslide*/ -void lara_as_deathslide(ITEM_INFO* item, COLL_INFO* coll)//1B038, 1B16C (F) + +// ------------------------------ +// ZIPLINE +// Control & Collision Functions +// ------------------------------ + +// State: 70 +// Collision: lara_void_func() +void lara_as_zipline(ITEM_INFO* item, COLL_INFO* coll)//1B038, 1B16C (F) { - /*state 70*/ - /*collision: lara_void_func*/ - short roomNumber = item->roomNumber; - Camera.targetAngle = ANGLE(70.0f); - GetFloorHeight(GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber), - item->pos.xPos, item->pos.yPos, item->pos.zPos); - coll->trigger = TriggerIndex; - if (!(TrInput & IN_ACTION)) + short roomNum = item->roomNumber; + FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNum); + GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos); + + if ((!(TrInput & IN_ACTION) && !EnableActionToggle) || + (TrInput & IN_ACTION && EnableActionToggle) || + TrInput & IN_JUMP) { item->goalAnimState = LS_JUMP_FORWARD; AnimateLara(item); - - LaraItem->gravityStatus = true; - LaraItem->speed = 100; - LaraItem->fallspeed = 40; - + Lara.moveAngle = 0; + + item->gravityStatus = true; + item->speed = 100; + item->fallspeed = 40; } } -/*end deathslide*/ diff --git a/TR5Main/Game/Lara/lara_objects.h b/TR5Main/Game/Lara/lara_objects.h index 3e91d3a04..5dcb8351d 100644 --- a/TR5Main/Game/Lara/lara_objects.h +++ b/TR5Main/Game/Lara/lara_objects.h @@ -1,61 +1,50 @@ #pragma once #include "lara_struct.h" -/*pickups*/ +// Pickup control functions. void lara_as_pickup(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_pickupflare(ITEM_INFO* item, COLL_INFO* coll); -/*end pickups*/ -/*-*/ -/*switches*/ -void lara_as_switchon(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_switchoff(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_pickup_flare(ITEM_INFO* item, COLL_INFO* coll); + +// Switch control & collision functions. +void lara_as_switch(ITEM_INFO* item, COLL_INFO* coll); void lara_col_turnswitch(ITEM_INFO* item, COLL_INFO* coll); -/*end switches*/ -/*-*/ -/*puzzles and keys*/ -void lara_as_usekey(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_usepuzzle(ITEM_INFO* item, COLL_INFO* coll); -/*end puzzles and keys*/ -/*-*/ -/*pushables*/ -void lara_as_pushblock(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_pullblock(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_ppready(ITEM_INFO* item, COLL_INFO* coll); -/*end pushables*/ -/*-*/ -/*pulley*/ + +// Puzzle & key control functions. +void lara_as_use_key(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_use_puzzle(ITEM_INFO* item, COLL_INFO* coll); + +// Pushable state functions. +void lara_as_pushable_push(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_pushable_pull(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_pushable_ready(ITEM_INFO* item, COLL_INFO* coll); + +// Pulley control function. void lara_as_pulley(ITEM_INFO* item, COLL_INFO* coll); -/*end pulley*/ -/*-*/ -/*parallel bars*/ -void lara_as_parallelbars(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_pbleapoff(ITEM_INFO* item, COLL_INFO* coll); -/*end parallel bars*/ -/*-*/ -/*tightropes*/ -void lara_as_trpose(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_trwalk(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_trfall(ITEM_INFO* item, COLL_INFO* coll); -/*end tightropes*/ -/*-*/ -/*ropes*/ -void lara_as_ropel(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_roper(ITEM_INFO* item, COLL_INFO* coll); + +// Swingbar control functions. +void lara_as_swing_bar(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_swing_bar_leap(ITEM_INFO* item, COLL_INFO* coll); + +// Tightrope control functions. +void lara_as_tightrope_stop(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_tightrope_walk(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_tightrope_fall(ITEM_INFO* item, COLL_INFO* coll); + +// Rope control & collision functions. +void lara_as_rope_turn_clockwise(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_rope_turn_counter_clockwise(ITEM_INFO* item, COLL_INFO* coll); void lara_as_rope(ITEM_INFO* item, COLL_INFO* coll); void lara_col_rope(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_ropefwd(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_climbrope(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_climbroped(ITEM_INFO* item, COLL_INFO* coll); -/*end ropes*/ -/*-*/ -/*poles*/ -void lara_col_polestat(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_poleup(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_poledown(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_poleleft(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_poleright(ITEM_INFO* item, COLL_INFO* coll); -/*end poles*/ -/*-*/ -/*deathslide*/ -void lara_as_deathslide(ITEM_INFO* item, COLL_INFO* coll); -/*end deathslide*/ +void lara_col_rope_swing(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_rope_up(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_rope_down(ITEM_INFO* item, COLL_INFO* coll); + +// Pole control & collision functions. +void lara_col_pole_stop(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_pole_up(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_pole_down(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_pole_turn_clockwise(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_pole_turn_counter_clockwise(ITEM_INFO* item, COLL_INFO* coll); + +// Zipline control functions. +void lara_as_zipline(ITEM_INFO* item, COLL_INFO* coll); \ No newline at end of file diff --git a/TR5Main/Game/Lara/lara_slide.cpp b/TR5Main/Game/Lara/lara_slide.cpp index 2db64c680..a00e287b5 100644 --- a/TR5Main/Game/Lara/lara_slide.cpp +++ b/TR5Main/Game/Lara/lara_slide.cpp @@ -1,15 +1,113 @@ #include "framework.h" #include "lara.h" #include "lara_collide.h" +#include "lara_tests.h" #include "input.h" #include "sound.h" +//#include "lara_slide.h" -short OldAngle = 1; +int OldAngle = 1; // Don't care. To be deleted. -/*this file has all the related functions to sliding*/ +// For later. +bool EnableAugmentedSlide; // Adds steep sliding, slope hugging, 180 turn. +bool EnableNonCardinalSlide; // Slides Lara in true slope direction. +bool EnableSlideInterpolation; // Adapts Lara angles to slope. +bool EnableSlideSteering; // Allows player influence on slide trajectory. -/*tests and others*/ -int TestLaraSlide(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +// SLOPE SLIDING + +// ------------------------------ +// Auxiliary functions +// ------------------------------ + +bool TestLaraSlide(COLL_INFO* coll) +{ + if (abs(coll->tiltX) <= 2 && abs(coll->tiltZ) <= 2) + { + return false; + } + + return true; +} + +short GetLaraSlideDirection(COLL_INFO* coll) +{ + short laraAngle = ANGLE(0.0f); + + //if (EnableNonCardinalSlide) + //{ + // // TODO: Get true slope direction. + //} + //else + //{ + if (coll->tiltX > 2) + { + laraAngle = -ANGLE(90.0f); + } + else if (coll->tiltX < -2) + { + laraAngle = ANGLE(90.0f); + } + + if (coll->tiltZ > 2 && coll->tiltZ > abs(coll->tiltX)) + { + laraAngle = ANGLE(180.0f); + } + else if (coll->tiltZ < -2 && -coll->tiltZ > abs(coll->tiltX)) + { + laraAngle = ANGLE(0.0f); + } + //} + + return laraAngle; +} + +int GetSlopeAngle(COLL_INFO* coll) +{ + return 1; +} + +void SetLaraSlide(ITEM_INFO* item, COLL_INFO* coll) +{ + short dir = GetLaraSlideDirection(coll); + short polarity = dir - item->pos.yRot; + + ShiftItem(item, coll); + + // Slide back. + if (polarity < ANGLE(-90.0f) || polarity > ANGLE(90.0f)) + { + if (GetSlopeAngle(coll) < ANGLE(60.0f))//SLOPE_ANGLE_STEEP) + { + Lara.moveAngle = ANGLE(180); + item->goalAnimState = LS_SLIDE_BACK; + item->pos.yRot = dir + ANGLE(180.0f); + } + else + { + item->goalAnimState = LS_SLIDE_STEEP_BACK; + item->pos.yRot = dir + ANGLE(180.0f); + } + } + // Slide forward. + else + { + if (GetSlopeAngle(coll) < ANGLE(60.0f))//SLOPE_ANGLE_STEEP) + { + Lara.moveAngle = 0; + item->goalAnimState = LS_SLIDE_FORWARD; + item->pos.yRot = dir; + } + else + { + item->goalAnimState = LS_SLIDE_STEEP_FORWARD; + item->pos.yRot = dir; + } + } +} + +// LEGACY. Staying until everything is done. +int Old_TestLaraSlide(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) { if (abs(coll->tiltX) <= 2 && abs(coll->tiltZ) <= 2) return 0; @@ -59,64 +157,12 @@ int TestLaraSlide(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) return 1; } -void lara_slide_slope(ITEM_INFO* item, COLL_INFO* coll)//127BC, 1286C (F) +void PerformLaraSlide(ITEM_INFO* item, COLL_INFO* coll)//127BC, 1286C (F) { - coll->badPos = NO_BAD_POS; - coll->badNeg = -512; - coll->badCeiling = 0; - coll->facing = Lara.moveAngle; - GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); - - if (!LaraHitCeiling(item, coll)) - { - LaraDeflectEdge(item, coll); - - if (coll->midFloor <= 200) - { - TestLaraSlide(item, coll); - - item->pos.yPos += coll->midFloor; - - if (abs(coll->tiltX) <= 2 && abs(coll->tiltZ) <= 2) - { - if (TrInput & IN_FORWARD && item->currentAnimState != LS_SLIDE_BACK) - { - item->goalAnimState = LS_RUN_FORWARD; - } - else - item->goalAnimState = LS_STOP; - StopSoundEffect(SFX_LARA_SLIPPING); - } - } - else - { - if (item->currentAnimState == LS_SLIDE_FORWARD) - { - item->animNumber = LA_FALL_START; - item->frameNumber = g_Level.Anims[LA_FALL_START].frameBase; - - item->currentAnimState = LS_JUMP_FORWARD; - item->goalAnimState = LS_JUMP_FORWARD; - } - else - { - item->animNumber = LA_FALL_BACK; - item->frameNumber = g_Level.Anims[LA_FALL_BACK].frameBase; - - item->currentAnimState = LS_FALL_BACK; - item->goalAnimState = LS_FALL_BACK; - } - - StopSoundEffect(SFX_LARA_SLIPPING); - - item->gravityStatus = true; - item->fallspeed = 0; - } - } } -void LaraSlideEdgeJump(ITEM_INFO* item, COLL_INFO* coll)//12B18, 12BC8 (F) +void PerformLaraSlideEdgeJump(ITEM_INFO* item, COLL_INFO* coll)//12B18, 12BC8 (F) { ShiftItem(item, coll); @@ -150,41 +196,245 @@ void LaraSlideEdgeJump(ITEM_INFO* item, COLL_INFO* coll)//12B18, 12BC8 (F) break; } } -/*end tests and others*/ -/*-*/ -/*Lara state code*/ -void lara_as_slide(ITEM_INFO* item, COLL_INFO* coll)//1A824(<), 1A958(<) (F) + +// ------------------------------ +// SLOPE SLIDING +// Control & Collision Functions +// ------------------------------ + +// State: 24 +// Collision: lara_col_Slide() +void lara_as_slide(ITEM_INFO* player, COLL_INFO* coll)//1A824(<), 1A958(<) (F) { - /*state 24*/ - /*collision: lara_col_slide*/ - Camera.targetElevation = -ANGLE(45.0f); // FIXED - if ((TrInput & IN_JUMP) && !(TrInput & IN_BACK)) - item->goalAnimState = LS_JUMP_FORWARD; + Camera.targetElevation = player->pos.xRot - ANGLE(45.0f); + + /*if (TrInput & IN_LEFT) + { + player->pos.yRot -= ANGLE(2.0f); + + Lara.turnRate -= LARA_TURN_RATE; + if (Lara.turnRate < -LARA_FAST_TURN) + { + Lara.turnRate = -LARA_FAST_TURN; + } + + if (TestLaraLean(coll) & EnableSlideSteering) + { + player->pos.zRot -= LARA_LEAN_RATE; + if (player->pos.zRot < -LARA_LEAN_MAX) + { + player->pos.zRot = -LARA_LEAN_MAX; + } + } + } + else if (TrInput & IN_RIGHT) + { + player->pos.yRot += ANGLE(2.0f); + + Lara.turnRate += LARA_TURN_RATE; + if (Lara.turnRate > LARA_FAST_TURN) + { + Lara.turnRate = LARA_FAST_TURN; + } + + if (TestLaraLean(coll) && EnableSlideSteering) + { + player->pos.zRot += LARA_LEAN_RATE; + if (player->pos.zRot > LARA_LEAN_MAX) + { + player->pos.zRot = LARA_LEAN_MAX; + } + } + }*/ + + if ((TrInput & IN_BACK) || (TrInput & IN_DUCK)) + { + player->goalAnimState = LS_SLIDE_STEEP_FORWARD; + } + + if (TrInput & IN_JUMP) + { + player->goalAnimState = LS_JUMP_FORWARD; + } + + if (TrInput & IN_ROLL) + { + player->goalAnimState = LS_SLIDE_TURN_180; + //SetLaraSlide(item, coll); // Temp: Lara slides up the slope otherwise. + } } void lara_col_slide(ITEM_INFO* item, COLL_INFO* coll)//1C108(<), 1C23C(<) (F) { - /*state 24*/ - /*state code: lara_as_slide*/ - Lara.moveAngle = 0; - lara_slide_slope(item, coll); + Lara.moveAngle = ANGLE(0.0f); + + coll->badPos = NO_BAD_POS; + coll->badNeg = -512; + coll->badCeiling = 0; + coll->facing = Lara.moveAngle; + + if (TestLaraHitCeiling(coll)) + { + SetLaraHitCeiling(item, coll); + return; + } + + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); + + LaraDeflectEdge(item, coll); + + if (coll->midFloor <= 200) + { + item->pos.yPos += coll->midFloor; + + if (!TestLaraSlide(coll)) + { + item->goalAnimState = (TrInput & IN_FORWARD) ? LS_RUN_FORWARD : LS_STOP; + + StopSoundEffect(SFX_LARA_SLIPPING); + } + } + else + { + if (TrInput & IN_ACTION && coll->midFloor >= 1024 && EnableSafetyDrop) + { + item->goalAnimState = LS_SAFE_DROP; + } + else + { + item->goalAnimState = LS_FALL; + } + + item->gravityStatus = true; + item->fallspeed = 0; + + StopSoundEffect(SFX_LARA_SLIPPING); + } } -void lara_as_slideback(ITEM_INFO* item, COLL_INFO* coll)//1A9E0(<), 1AB14(<) (F) +// State: 32 +// Collision: lara_col_SlideBack() +void lara_as_slide_back(ITEM_INFO* item, COLL_INFO* coll)//1A9E0(<), 1AB14(<) (F) { - /*state 32*/ - /*collision: lara_col_slideback*/ - if ((TrInput & IN_JUMP) && !(TrInput & IN_FORWARD)) + Camera.targetElevation = item->pos.xRot; + + //if (TrInput & IN_FORWARD) + // item->goalAnimState = LS_SLIDE_STEEP_BACK; + + if (TrInput & IN_JUMP) + { + item->goalAnimState = LS_JUMP_BACK; + } + + /*if (TrInput & IN_ROLL) + { + item->pos.yRot += ANGLE(180.0f); + item->goalAnimState = LS_SLIDE_FORWARD; + SetLaraSlide(item, coll); + }*/ +} + +void lara_col_slide_back(ITEM_INFO* item, COLL_INFO* coll)//1C284(<), 1C3B8(<) (F) +{ + Lara.moveAngle = ANGLE(180.0f); + + coll->badPos = NO_BAD_POS; + coll->badNeg = -512; + coll->badCeiling = 0; + coll->facing = Lara.moveAngle; + + if (TestLaraHitCeiling(coll)) + { + SetLaraHitCeiling(item, coll); + return; + } + + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); + + LaraDeflectEdge(item, coll); + + if (coll->midFloor <= 200) + { + item->pos.yPos += coll->midFloor; + + if (!TestLaraSlide(coll)) + { + item->goalAnimState = LS_STOP; + StopSoundEffect(SFX_LARA_SLIPPING); + } + } + else + { + if (TrInput & IN_ACTION && coll->midFloor >= 1024 && EnableSafetyDrop) + { + item->goalAnimState = LS_SAFE_DROP; + } + else + { + item->goalAnimState = LS_FALL_BACK; + } + + item->gravityStatus = true; + item->fallspeed = 0; + + StopSoundEffect(SFX_LARA_SLIPPING); + } +} + +// TODO: Unique handling for steep slopes. Anims on the way. +void lara_as_steep_slide(ITEM_INFO* item, COLL_INFO* coll) +{ + if (item->pos.xRot >= ANGLE(60)) + { + Camera.targetElevation = ANGLE(-60.0f); + } + else + { + Camera.targetElevation = ANGLE(-45.0f); + } + + if (TrInput & IN_FORWARD) + { + item->goalAnimState = LS_SLIDE_FORWARD; + } + + if (TrInput & IN_JUMP) + { + item->goalAnimState = LS_JUMP_FORWARD; + } +} + +void lara_col_steep_slide(ITEM_INFO* item, COLL_INFO* coll) +{ + Lara.moveAngle = ANGLE(0.0f); + PerformLaraSlide(item, coll); +} + +void lara_as_steep_slide_back(ITEM_INFO* item, COLL_INFO* coll) +{ + Camera.targetElevation = ANGLE(-60.0f); + + if (TrInput & IN_BACK) + { + item->goalAnimState = LS_SLIDE_BACK; + } + + if (TrInput & IN_JUMP) { item->goalAnimState = LS_JUMP_BACK; } } -void lara_col_slideback(ITEM_INFO* item, COLL_INFO* coll)//1C284(<), 1C3B8(<) (F) +void lara_col_steep_slide_back(ITEM_INFO* item, COLL_INFO* coll) { - /*state 32*/ - /*state code: lara_as_slideback*/ - Lara.moveAngle = ANGLE(180); - lara_slide_slope(item, coll); + Lara.moveAngle = ANGLE(180.0f); + PerformLaraSlide(item, coll); } -/*end Lara state code*/ + +void lara_as_slide_turn_180(ITEM_INFO* item, COLL_INFO* coll) +{ + Lara.moveAngle = ANGLE(0.0f); +} + +// TODO: Straddling illegal slopes. +// TODO: Grabbing edge of plateau leading to steep slope. diff --git a/TR5Main/Game/Lara/lara_slide.h b/TR5Main/Game/Lara/lara_slide.h index 26621a51f..ed210b37d 100644 --- a/TR5Main/Game/Lara/lara_slide.h +++ b/TR5Main/Game/Lara/lara_slide.h @@ -1,15 +1,25 @@ #pragma once #include "lara_struct.h" -/*Tests and others*/ -int TestLaraSlide(ITEM_INFO* item, COLL_INFO* coll); -void lara_slide_slope(ITEM_INFO* item, COLL_INFO* coll); -void LaraSlideEdgeJump(ITEM_INFO* item, COLL_INFO* coll); -/*end tests and others*/ -/*-*/ -/*Lara state code*/ +#define SLOPE_ANGLE_NORMAL ANGLE(30.0f) +#define SLOPE_ANGLE_STEEP ANGLE(60.0f) + +// Auxiliary functions. +bool TestLaraSlide(COLL_INFO* coll); +float GetLaraSlideDirection(COLL_INFO* coll); +void SetLaraSlide(ITEM_INFO* item, COLL_INFO* coll); +void PerformLaraSlide(ITEM_INFO* item, COLL_INFO* coll); +void PerformLaraSlideEdgeJump(ITEM_INFO* item, COLL_INFO* coll); + +int Old_TestLaraSlide(ITEM_INFO* item, COLL_INFO* coll); + +// Sliding control & collision functions. void lara_as_slide(ITEM_INFO* item, COLL_INFO* coll); void lara_col_slide(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_slideback(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_slideback(ITEM_INFO* item, COLL_INFO* coll); -/*end Lara state code*/ +void lara_as_slide_back(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_slide_back(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_steep_slide(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_steep_slide(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_steep_slide_back(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_steep_slide_back(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_slide_turn_180(ITEM_INFO* item, COLL_INFO* coll); diff --git a/TR5Main/Game/Lara/lara_struct.h b/TR5Main/Game/Lara/lara_struct.h index 7be7c214c..9aa37601e 100644 --- a/TR5Main/Game/Lara/lara_struct.h +++ b/TR5Main/Game/Lara/lara_struct.h @@ -35,7 +35,7 @@ enum LARA_STATE LS_UNDERWATER_FORWARD = 17, LS_UNDERWATER_INERTIA = 18, LS_GRABBING = 19, - LS_TURN_FAST = 20, + LS_TURN_RIGHT_FAST = 20, LS_STEP_RIGHT = 21, LS_STEP_LEFT = 22, LS_ROLL_BACK = 23, @@ -177,6 +177,15 @@ enum LARA_STATE LS_STEP_BACK_DOWN = 149, LS_LADDER_DISMOUNT_LEFT = 150, LS_LADDER_DISMOUNT_RIGHT = 151, + + LS_SLIDE_STEEP_FORWARD = 152, + LS_SLIDE_STEEP_BACK = 153, + LS_SLIDE_TURN_180 = 154, + LS_FALL = 155, // This is needed if we are to have a fall anim dispatch from slide states, as LS_JUMP_FORWARD is already used to leap off. + LS_TURN_LEFT_FAST = 156, + LS_SAFE_DROP = 157, + /*LS_POLE_UP = 158, + LS_POLE_DOWN = 159,*/ // I broke poles, sorry. :/ I'll get to it later. -Sezz NUM_LARA_STATES }; @@ -721,6 +730,34 @@ enum LARA_ANIM LA_LADDER_DISMOUNT_RIGHT_END = 500, // Ladder dismount right (2/2) LA_ONWATER_TO_LADDER = 501, // Tread water > climb to ladder idle + // RESERVED. + LA_SLIDE_FORWARD_JUMP = 502, // Slide forward > jump forwad + LA_SLIDE_FORWARD_TURN_180 = 503, // Slide forward > slide back + LA_SLIDE_BACK_JUMP = 504, // Slide back > jump back + LA_SLIDE_BACK_TURN_180 = 505, // Slide back > slide forward + LA_SLIDE_FORWARD_TO_STEEP = 506, // Slide forward, normal > slide forward, steep + LA_SLIDE_STEEP_FORWARD_TO_NORMAL = 507, // Slide forward, steep > slide forward, normal + LA_SLIDE_STEEP_FORWARD_START = 508, // Land on slope > slide forward, steep + LA_SLIDE_STEEP_FORWARD = 509, // Slide forward, steep (looped) + LA_SLIDE_STEEP_FORWARD_END = 510, // Slide forward, steep > stand + LA_SLIDE_STEEP_FORWARD_JUMP = 511, // Slide forward > jump forward + LA_SLIDE_BACK_TO_STEEP = 512, // Slide back, normal > slide back, steep + LA_SLIDE_STEEP_BACK_TO_NORMAL = 513, // Slide back, steep > slide back, normal + LA_SLIDE_STEEP_BACK_START = 514, // Land on slope > slide forward, steep + LA_SLIDE_STEEP_BACK = 515, // Slide back, steep (looped) + LA_SLIDE_STEEP_BACK_END = 516, // Slide back, steep > stand + LA_SLIDE_STEEP_BACK_JUMP = 517, // Slide back, steep > jump forward + LA_SLIDE_FORWARD_LEDGE = 518, // Slide forward > grab ledge + LA_SLIDE_BACK_LEDGE = 519, // Slide back > grab ledge + LA_STAND_CROSS_ARMS_AFK_START = 520, // Stand idle > cross arms AFK + LA_STAND_CROSS_ARMS_AFK = 521, // Cross arms AKF (looped) + LA_STAND_CROSS_ARMS_AFK_END = 522, // Cross arms AFK > stand idle + LA_ROLL_180_ALTERNATE = 523, // Standing mid-air roll 180 + LA_SPRINT_TO_SPRINT_DIVE_LEFT = 524, // Sprint > sprint dive, left foot first + LA_SPRINT_TO_SPRINT_DIVE_RIGHT = 525, // Sprint > sprint dive, right foot first + LA_SPRINT_DIVE_TO_RUN = 526, // Sprint dive > run + LA_SPRINT_DIVE = 527, // Sprint dive, leading to swandive freefall + NUM_LARA_ANIMS }; #pragma endregion diff --git a/TR5Main/Game/Lara/lara_surface.cpp b/TR5Main/Game/Lara/lara_surface.cpp index 9188bbcc5..2c420839e 100644 --- a/TR5Main/Game/Lara/lara_surface.cpp +++ b/TR5Main/Game/Lara/lara_surface.cpp @@ -25,32 +25,34 @@ void lara_col_surftread(ITEM_INFO* item, COLL_INFO* coll) item->fallspeed = 80; Lara.waterStatus = LW_UNDERWATER; } + Lara.moveAngle = 0; LaraSurfaceCollision(item, coll); } void lara_col_surfright(ITEM_INFO* item, COLL_INFO* coll)//4DD90(<), 4E1F4(<) (F) { - Lara.moveAngle = ANGLE(90); + Lara.moveAngle = ANGLE(90.0f); LaraSurfaceCollision(item, coll); } void lara_col_surfleft(ITEM_INFO* item, COLL_INFO* coll)//4DD64(<), 4E1C8(<) (F) { - Lara.moveAngle = -ANGLE(90); + Lara.moveAngle = ANGLE(-90.0f); LaraSurfaceCollision(item, coll); } void lara_col_surfback(ITEM_INFO* item, COLL_INFO* coll)//4DD38(<), 4E19C(<) (F) { - Lara.moveAngle = ANGLE(180); + Lara.moveAngle = ANGLE(180.0f); LaraSurfaceCollision(item, coll); } void lara_col_surfswim(ITEM_INFO* item, COLL_INFO* coll)//4DCE8(<), 4E14C(<) (F) { - coll->badNeg = -384; Lara.moveAngle = 0; + coll->badNeg = -384; + LaraSurfaceCollision(item, coll); LaraTestWaterClimbOut(item, coll); LaraTestLadderClimbOut(item, coll); @@ -60,7 +62,9 @@ void lara_as_surftread(ITEM_INFO* item, COLL_INFO* coll)//4DBA0, 4E004 (F) { item->fallspeed -= 4; if (item->fallspeed < 0) + { item->fallspeed = 0; + } if (item->hitPoints <= 0) { @@ -76,11 +80,11 @@ void lara_as_surftread(ITEM_INFO* item, COLL_INFO* coll)//4DBA0, 4E004 (F) if (TrInput & IN_LEFT) { - item->pos.yRot -= ANGLE(4); + item->pos.yRot -= ANGLE(4.0f); } else if (TrInput & IN_RIGHT) { - item->pos.yRot += ANGLE(4); + item->pos.yRot += ANGLE(4.0f); } if (TrInput & IN_FORWARD) @@ -105,7 +109,9 @@ void lara_as_surftread(ITEM_INFO* item, COLL_INFO* coll)//4DBA0, 4E004 (F) { Lara.diveCount++; if (Lara.diveCount == 10) + { item->goalAnimState = LS_UNDERWATER_FORWARD; + } } else { @@ -125,11 +131,11 @@ void lara_as_surfright(ITEM_INFO* item, COLL_INFO* coll)//4DAF8, 4DF5C (F) if (TrInput & IN_LEFT) { - item->pos.yRot -= ANGLE(2); + item->pos.yRot -= ANGLE(2.0f); } else if (TrInput & IN_RIGHT) { - item->pos.yRot += ANGLE(2); + item->pos.yRot += ANGLE(2.0f); } if (!(TrInput & IN_RSTEP)) @@ -139,7 +145,9 @@ void lara_as_surfright(ITEM_INFO* item, COLL_INFO* coll)//4DAF8, 4DF5C (F) item->fallspeed += 8; if (item->fallspeed > 60) + { item->fallspeed = 60; + } } void lara_as_surfleft(ITEM_INFO* item, COLL_INFO* coll)//4DA50(<), 4DEB4(<) (F) @@ -154,11 +162,11 @@ void lara_as_surfleft(ITEM_INFO* item, COLL_INFO* coll)//4DA50(<), 4DEB4(<) (F) if (TrInput & IN_LEFT) { - item->pos.yRot -= ANGLE(2); + item->pos.yRot -= ANGLE(2.0f); } else if (TrInput & IN_RIGHT) { - item->pos.yRot += ANGLE(2); + item->pos.yRot += ANGLE(2.0f); } if (!(TrInput & IN_LSTEP)) @@ -168,7 +176,9 @@ void lara_as_surfleft(ITEM_INFO* item, COLL_INFO* coll)//4DA50(<), 4DEB4(<) (F) item->fallspeed += 8; if (item->fallspeed > 60) + { item->fallspeed = 60; + } } void lara_as_surfback(ITEM_INFO* item, COLL_INFO* coll)//4D9A8(<), 4DE0C(<) (F) @@ -183,11 +193,11 @@ void lara_as_surfback(ITEM_INFO* item, COLL_INFO* coll)//4D9A8(<), 4DE0C(<) (F) if (TrInput & IN_LEFT) { - item->pos.yRot -= ANGLE(2); + item->pos.yRot -= ANGLE(2.0f); } else if (TrInput & IN_RIGHT) { - item->pos.yRot += ANGLE(2); + item->pos.yRot += ANGLE(2.0f); } if (!(TrInput & IN_BACK)) @@ -197,7 +207,9 @@ void lara_as_surfback(ITEM_INFO* item, COLL_INFO* coll)//4D9A8(<), 4DE0C(<) (F) item->fallspeed += 8; if (item->fallspeed > 60) + { item->fallspeed = 60; + } } void lara_as_surfswim(ITEM_INFO* item, COLL_INFO* coll)//4D8E4(<), 4DD48(<) (F) @@ -220,13 +232,19 @@ void lara_as_surfswim(ITEM_INFO* item, COLL_INFO* coll)//4D8E4(<), 4DD48(<) (F) } if (!(TrInput & IN_FORWARD)) + { item->goalAnimState = LS_ONWATER_STOP; + } if (TrInput & IN_JUMP) + { item->goalAnimState = LS_ONWATER_STOP; + } item->fallspeed += 8; if (item->fallspeed > 60) + { item->fallspeed = 60; + } } void LaraSurfaceCollision(ITEM_INFO* item, COLL_INFO* coll)//4D4F0(<), 4D954(<) (F) @@ -246,11 +264,11 @@ void LaraSurfaceCollision(ITEM_INFO* item, COLL_INFO* coll)//4D4F0(<), 4D954(<) } else if (coll->collType == CT_LEFT) { - item->pos.yRot += ANGLE(5); + item->pos.yRot += ANGLE(5.0f); } else if (coll->collType == CT_RIGHT) { - item->pos.yRot -= ANGLE(5); + item->pos.yRot -= ANGLE(5.0f); } if (GetWaterHeight(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber) - item->pos.yPos > -100) @@ -272,7 +290,9 @@ void LaraSurfaceCollision(ITEM_INFO* item, COLL_INFO* coll)//4D4F0(<), 4D954(<) int LaraTestWaterClimbOut(ITEM_INFO* item, COLL_INFO* coll)//4D22C, 4D690 { if (coll->collType != CT_FRONT || !(TrInput & IN_ACTION)) + { return 0; + } // FOR DEBUG PURPOSES UNTIL SCRIPTING IS READY- EnableCrawlFlexWaterPullUp = false; @@ -280,18 +300,26 @@ int LaraTestWaterClimbOut(ITEM_INFO* item, COLL_INFO* coll)//4D22C, 4D690 if (Lara.gunStatus && (Lara.gunStatus != LG_READY || Lara.gunType != WEAPON_FLARE)) + { return 0; + } if (coll->frontCeiling > 0) + { return 0; + } if (coll->midCeiling > -384) + { return 0; + } int frontFloor = coll->frontFloor + 700; int frontCeiling = coll->frontCeiling + 700; if (frontFloor <= -512 || frontFloor > 316) + { return 0; + } short rot = item->pos.yRot; int slope = 0; @@ -304,13 +332,17 @@ int LaraTestWaterClimbOut(ITEM_INFO* item, COLL_INFO* coll)//4D22C, 4D690 else { if (abs(coll->rightFloor2 - coll->leftFloor2) >= 60) + { return 0; + } result = SnapToQuadrant(rot, 35); } if (!result) + { return 0; + } item->pos.yPos += frontFloor - 5; @@ -353,8 +385,10 @@ int LaraTestWaterClimbOut(ITEM_INFO* item, COLL_INFO* coll)//4D22C, 4D690 item->goalAnimState = LA_CROUCH_IDLE; } else + { item->animNumber = LA_ONWATER_TO_STAND_M1CLICK; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + } } else @@ -371,19 +405,17 @@ int LaraTestWaterClimbOut(ITEM_INFO* item, COLL_INFO* coll)//4D22C, 4D690 item->frameNumber = g_Level.Anims[item->animNumber].frameBase; item->goalAnimState = LS_STOP; } - - } + Lara.gunStatus = LG_HANDS_BUSY; + Lara.waterStatus = LW_ABOVE_WATER; item->currentAnimState = LS_ONWATER_EXIT; item->pos.yRot = rot; - Lara.gunStatus = LG_HANDS_BUSY; item->pos.zRot = 0; item->pos.xRot = 0; item->gravityStatus = false; item->speed = 0; item->fallspeed = 0; - Lara.waterStatus = LW_ABOVE_WATER; return 1; } @@ -442,27 +474,33 @@ int LaraTestWaterStepOut(ITEM_INFO* item, COLL_INFO* coll)//4D100, 4D564 (F) int LaraTestLadderClimbOut(ITEM_INFO* item, COLL_INFO* coll) // NEW function for water to ladder move { if (!Lara.climbStatus || coll->collType != CT_FRONT || !(TrInput & IN_ACTION)) + { return 0; + } if (Lara.gunStatus && (Lara.gunStatus != LG_READY || Lara.gunType != WEAPON_FLARE)) + { return 0; + } if (!LaraTestClimbStance(item, coll)) return 0; short rot = item->pos.yRot; - if (rot >= -ANGLE(35.0f) && rot <= ANGLE(35.0f)) + if (rot >= ANGLE(-35.0f) && rot <= ANGLE(35.0f)) rot = 0; else if (rot >= ANGLE(55.0f) && rot <= ANGLE(125.0f)) rot = ANGLE(90.0f); - else if (rot >= ANGLE(145.0f) || rot <= -ANGLE(145.0f)) + else if (rot >= ANGLE(145.0f) || rot <= ANGLE(-145.0f)) rot = ANGLE(180.0f); - else if (rot >= -ANGLE(125.0f) && rot <= -ANGLE(55.0f)) + else if (rot >= ANGLE(-125.0f) && rot <= ANGLE(-55.0f)) rot = -ANGLE(90.0f); if (rot & 0x3FFF) + { return 0; + } switch ((unsigned short)rot / ANGLE(90.0f)) { @@ -489,22 +527,23 @@ int LaraTestLadderClimbOut(ITEM_INFO* item, COLL_INFO* coll) // NEW function for item->goalAnimState = LS_LADDER_IDLE; AnimateLara(item); - item->pos.yRot = rot; Lara.gunStatus = LG_HANDS_BUSY; + Lara.waterStatus = LW_ABOVE_WATER; + item->pos.yRot = rot; item->pos.zRot = 0; item->pos.xRot = 0; item->gravityStatus = false; item->speed = 0; item->fallspeed = 0; - Lara.waterStatus = LW_ABOVE_WATER; return 1; } void lara_as_waterout(ITEM_INFO* item, COLL_INFO* coll)//1AEE4(<), 1B018(<) (F) { + Camera.flags = CF_FOLLOW_CENTER; + coll->enableBaddiePush = false; coll->enableSpaz = false; - Camera.flags = CF_FOLLOW_CENTER; } diff --git a/TR5Main/Game/Lara/lara_surface.h b/TR5Main/Game/Lara/lara_surface.h index 1072c2cf6..6e1d4012d 100644 --- a/TR5Main/Game/Lara/lara_surface.h +++ b/TR5Main/Game/Lara/lara_surface.h @@ -1,7 +1,5 @@ #pragma once - - -#include "Lara.h" +#include "lara.h" void _cdecl lara_col_surftread(ITEM_INFO* item, COLL_INFO* coll); void _cdecl lara_col_surfright(ITEM_INFO* item, COLL_INFO* coll); diff --git a/TR5Main/Game/Lara/lara_swim.cpp b/TR5Main/Game/Lara/lara_swim.cpp index d33ea5e51..a87b2d7d6 100644 --- a/TR5Main/Game/Lara/lara_swim.cpp +++ b/TR5Main/Game/Lara/lara_swim.cpp @@ -15,17 +15,15 @@ #include "sound.h" #include "GameFlowScript.h" -typedef struct SUBSUIT_INFO -{ - short XRot; - short dXRot; - short XRotVel; - short Vel[2]; - short YVel; -}; -SUBSUIT_INFO Subsuit; +SubsuitInfo Subsuit; byte SubHitCount = 0; +// SWIMMING + +// ------------------------------ +// Auxillary functions +// ------------------------------ + void LaraWaterCurrent(COLL_INFO* coll) // (F) (D) { if (Lara.currentActive) @@ -43,25 +41,41 @@ void LaraWaterCurrent(COLL_INFO* coll) // (F) (D) int shift = 0; if (abs(Lara.currentXvel) <= 16) + { shift = (abs(Lara.currentXvel) > 8) + 2; + } else + { shift = 4; + } + Lara.currentXvel -= Lara.currentXvel >> shift; if (abs(Lara.currentXvel) < 4) + { Lara.currentXvel = 0; + } if (abs(Lara.currentZvel) <= 16) + { shift = (abs(Lara.currentZvel) > 8) + 2; + } else + { shift = 4; + } + Lara.currentZvel -= Lara.currentZvel >> shift; if (abs(Lara.currentZvel) < 4) + { Lara.currentZvel = 0; + } if (!Lara.currentXvel && !Lara.currentZvel) + { return; + } } LaraItem->pos.xPos += Lara.currentXvel >> 8; @@ -75,11 +89,17 @@ void LaraWaterCurrent(COLL_INFO* coll) // (F) (D) if (coll->collType == CT_FRONT) { if (LaraItem->pos.xRot > ANGLE(35)) + { LaraItem->pos.xRot += ANGLE(1); + } else if (LaraItem->pos.xRot < -ANGLE(35)) + { LaraItem->pos.xRot -= ANGLE(1); + } else + { LaraItem->fallspeed = 0; + } } else if (coll->collType == CT_TOP) { @@ -181,190 +201,6 @@ int GetWaterDepth(int x, int y, int z, short roomNumber)//4CA38, 4CE9C } } -void lara_col_waterroll(ITEM_INFO* item, COLL_INFO* coll)//4CA18(<), 4CE7C(<) (F) -{ - LaraSwimCollision(item, coll); -} - -void lara_col_uwdeath(ITEM_INFO* item, COLL_INFO* coll)//4C980(<), 4CDE4(<) (F) -{ - item->hitPoints = -1; - Lara.air = -1; - Lara.gunStatus = LG_HANDS_BUSY; - int wh = GetWaterHeight(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber); - if (wh != NO_HEIGHT) - { - if (wh < item->pos.yPos - 100) - item->pos.yPos -= 5; - } - LaraSwimCollision(item, coll); -} - -void lara_col_dive(ITEM_INFO* item, COLL_INFO* coll)//4C960(<), 4CDC4(<) (F) -{ - LaraSwimCollision(item, coll); -} - -void lara_col_tread(ITEM_INFO* item, COLL_INFO* coll)//4C940(<), 4CDA4(<) (F) -{ - LaraSwimCollision(item, coll); -} - -void lara_col_glide(ITEM_INFO* item, COLL_INFO* coll)//4C920(<), 4CD84(<) (F) -{ - LaraSwimCollision(item, coll); -} - -void lara_col_swim(ITEM_INFO* item, COLL_INFO* coll)//4C900(<), 4CD64(<) (F) -{ - LaraSwimCollision(item, coll); -} - -void lara_as_waterroll(ITEM_INFO* item, COLL_INFO* coll)//4C8F8(<), 4CD5C(<) (F) -{ - item->fallspeed = 0; -} - -void lara_as_uwdeath(ITEM_INFO* item, COLL_INFO* coll)//4C884(<), 4CCE8(<) (F) -{ - Lara.look = 0; - - item->fallspeed -= 8; - if (item->fallspeed <= 0) - item->fallspeed = 0; - - if (item->pos.xRot < -ANGLE(2) || item->pos.xRot > ANGLE(2)) - { - if (item->pos.xRot >= 0) - item->pos.xRot -= ANGLE(2); - else - item->pos.xRot += ANGLE(2); - } - else - { - item->pos.xRot = 0; - } -} - -void lara_as_dive(ITEM_INFO* item, COLL_INFO* coll)//4C854, 4CCB8 (F) -{ - if (TrInput & IN_FORWARD) - { - item->pos.xRot -= ANGLE(1); - } -} - -void lara_as_tread(ITEM_INFO* item, COLL_INFO* coll)//4C730, 4CB94 (F) -{ - if (item->hitPoints <= 0) - { - item->goalAnimState = LS_WATER_DEATH; - return; - } - - if (TrInput & IN_ROLL && LaraDrawType != LARA_DIVESUIT) - { - item->currentAnimState = LS_UNDERWATER_ROLL; - item->animNumber = LA_UNDERWATER_ROLL_180_START; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - } - else - { - if (TrInput & IN_LOOK) - LookUpDown(); - - if (LaraDrawType == LARA_DIVESUIT) - SwimTurnSubsuit(item); - else - SwimTurn(item); - - if (TrInput & IN_JUMP) - item->goalAnimState = LS_UNDERWATER_FORWARD; - - item->fallspeed -= 6; - - if (item->fallspeed < 0) - item->fallspeed = 0; - - if (Lara.gunStatus == LG_HANDS_BUSY) - Lara.gunStatus = LG_NO_ARMS; - } -} - -void lara_as_glide(ITEM_INFO* item, COLL_INFO* coll)//4C634(<), 4CA98(<) (F) -{ - if (item->hitPoints <= 0) - { - item->goalAnimState = LS_WATER_DEATH; - return; - } - - if (TrInput & IN_ROLL) - { - if (LaraDrawType != LARA_DIVESUIT) - { - item->currentAnimState = LS_UNDERWATER_ROLL; - item->animNumber = LA_UNDERWATER_ROLL_180_START; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - return; - } - } - else if (LaraDrawType != LARA_DIVESUIT) - { - SwimTurn(item); - } - else - { - SwimTurnSubsuit(item); - } - - if (TrInput & IN_JUMP) - item->goalAnimState = LS_UNDERWATER_FORWARD; - - item->fallspeed -= 6; - if (item->fallspeed < 0) - item->fallspeed = 0; - - if (item->fallspeed <= 133) - item->goalAnimState = LS_UNDERWATER_STOP; -} - -void lara_as_swim(ITEM_INFO* item, COLL_INFO* coll)//4C548(<), 4C9AC(<) (F) -{ - if (item->hitPoints <= 0) - { - item->goalAnimState = LS_WATER_DEATH; - return; - } - - if (TrInput & IN_ROLL) - { - if (LaraDrawType != LARA_DIVESUIT) - { - item->currentAnimState = LS_UNDERWATER_ROLL; - item->animNumber = LA_UNDERWATER_ROLL_180_START; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - return; - } - } - else if (LaraDrawType != LARA_DIVESUIT) - { - SwimTurn(item); - } - else - { - SwimTurnSubsuit(item); - } - - item->fallspeed += 8; - - if (item->fallspeed > 200) - item->fallspeed = 200; - - if (!(TrInput & IN_JUMP)) - item->goalAnimState = LS_UNDERWATER_INERTIA; -} - void UpdateSubsuitAngles()//4BD20, 4C184 (F) { if (Subsuit.YVel != 0) @@ -437,7 +273,7 @@ void UpdateSubsuitAngles()//4BD20, 4C184 (F) } } -void SwimTurnSubsuit(ITEM_INFO* item)//4BBDC, 4C040 (F) +void DoLaraSubsuitSwimTurn(ITEM_INFO* item)//4BBDC, 4C040 (F) { if (item->pos.yPos < 14080) Subsuit.YVel += (14080 - item->pos.yPos) >> 4; @@ -475,30 +311,36 @@ void SwimTurnSubsuit(ITEM_INFO* item)//4BBDC, 4C040 (F) } } -void SwimTurn(ITEM_INFO* item)//4BAF4(<), 4BF58(<) (F) +void DoLaraSwimTurn(ITEM_INFO* item)//4BAF4(<), 4BF58(<) (F) { if (TrInput & IN_FORWARD) { - item->pos.xRot -= ANGLE(2); + item->pos.xRot -= ANGLE(3.5f); } else if (TrInput & IN_BACK) { - item->pos.xRot += ANGLE(2); + item->pos.xRot += ANGLE(3.0f); } if (TrInput & IN_LEFT) { - Lara.turnRate -= 409; - if (Lara.turnRate < -ANGLE(6)) - Lara.turnRate = -ANGLE(6); - item->pos.zRot -= ANGLE(3); + Lara.turnRate -= ANGLE(3.0f); + if (Lara.turnRate < ANGLE(-6.0f)) + { + Lara.turnRate = ANGLE(-6.0f); + } + + item->pos.zRot -= ANGLE(3.0f); } else if (TrInput & IN_RIGHT) { - Lara.turnRate += 409; - if (Lara.turnRate > ANGLE(6)) - Lara.turnRate = ANGLE(6); - item->pos.zRot += ANGLE(3); + Lara.turnRate += ANGLE(3.0f); + if (Lara.turnRate > ANGLE(6.0f)) + { + Lara.turnRate = ANGLE(6.0f); + } + + item->pos.zRot += ANGLE(3.0f); } } @@ -511,10 +353,10 @@ void LaraSwimCollision(ITEM_INFO* item, COLL_INFO* coll)//4B608, 4BA6C short oldYrot = item->pos.yRot; short oldZrot = item->pos.zRot; - if (item->pos.xRot < -ANGLE(90) || item->pos.xRot > ANGLE(90)) + if (item->pos.xRot < ANGLE(-90.0f) || item->pos.xRot > ANGLE(90.0f)) { - Lara.moveAngle = ANGLE(180); - coll->facing = item->pos.yRot - ANGLE(180); + Lara.moveAngle = ANGLE(180.0f); + coll->facing = item->pos.yRot - ANGLE(180.0f); } else { @@ -526,38 +368,40 @@ void LaraSwimCollision(ITEM_INFO* item, COLL_INFO* coll)//4B608, 4BA6C height = abs(height); if (height < ((LaraDrawType == LARA_DIVESUIT) << 6) + 200) + { height = ((LaraDrawType == LARA_DIVESUIT) << 6) + 200; - + } + coll->badNeg = -64; - + COLL_INFO c1; COLL_INFO c2; memcpy(&c1, coll, sizeof(COLL_INFO)); memcpy(&c2, coll, sizeof(COLL_INFO) - 2); GetCollisionInfo(coll, item->pos.xPos, height / 2 + item->pos.yPos, item->pos.zPos, item->roomNumber, height); - - c1.facing += ANGLE(45); + + c1.facing += ANGLE(45.0f); GetCollisionInfo(&c1, item->pos.xPos, height / 2 + item->pos.yPos, item->pos.zPos, item->roomNumber, height); - - c2.facing -= ANGLE(45); + + c2.facing -= ANGLE(45.0f); GetCollisionInfo(&c2, item->pos.xPos, height / 2 + item->pos.yPos, item->pos.zPos, item->roomNumber, height); - + ShiftItem(item, coll); - + int flag = 0; switch (coll->collType) { case CT_FRONT: - if (item->pos.xRot <= ANGLE(25)) + if (item->pos.xRot <= ANGLE(25.0f)) { - if (item->pos.xRot >= -ANGLE(25)) + if (item->pos.xRot >= ANGLE(-25.0f)) { - if (item->pos.xRot > ANGLE(5)) - item->pos.xRot += ANGLE(0.5); - else if (item->pos.xRot < -ANGLE(5)) - item->pos.xRot -= ANGLE(0.5); + if (item->pos.xRot > ANGLE(5.0f)) + item->pos.xRot += ANGLE(0.5f); + else if (item->pos.xRot < ANGLE(-5.0f)) + item->pos.xRot -= ANGLE(0.5f); else if (item->pos.xRot > 0) item->pos.xRot += 45; else if (item->pos.xRot < 0) @@ -602,7 +446,7 @@ void LaraSwimCollision(ITEM_INFO* item, COLL_INFO* coll)//4B608, 4BA6C if (item->pos.xRot >= -8190) { flag = 1; - item->pos.xRot -= ANGLE(1); + item->pos.xRot -= ANGLE(1.0f); } break; @@ -612,12 +456,12 @@ void LaraSwimCollision(ITEM_INFO* item, COLL_INFO* coll)//4B608, 4BA6C break; case CT_LEFT: - item->pos.yRot += ANGLE(2); + item->pos.yRot += ANGLE(2.0f); flag = 1; break; case CT_RIGHT: - item->pos.yRot -= ANGLE(2); + item->pos.yRot -= ANGLE(2.0f); flag = 1; break; @@ -633,13 +477,13 @@ void LaraSwimCollision(ITEM_INFO* item, COLL_INFO* coll)//4B608, 4BA6C if (coll->midFloor < 0 && coll->midFloor != NO_HEIGHT) { flag = 1; - item->pos.xRot += ANGLE(1); + item->pos.xRot += ANGLE(1.0f); item->pos.yPos += coll->midFloor; } if (oldX == item->pos.xPos && oldY == item->pos.yPos - && oldZ == item->pos.zPos + && oldZ == item->pos.zPos && oldXrot == item->pos.xRot && oldYrot == item->pos.yRot || flag != 1) @@ -661,23 +505,26 @@ void LaraSwimCollision(ITEM_INFO* item, COLL_INFO* coll)//4B608, 4BA6C } if (Lara.waterStatus != LW_FLYCHEAT && Lara.ExtraAnim == NO_ITEM) - LaraTestWaterDepth(item, coll); + { + TestLaraWaterDepth(item, coll); + } } -void LaraTestWaterDepth(ITEM_INFO* item, COLL_INFO* coll)//4B4F8(<), 4B95C(<) (F) +// This is a setter. +void TestLaraWaterDepth(ITEM_INFO* item, COLL_INFO* coll)//4B4F8(<), 4B95C(<) (F) { short roomNumber = item->roomNumber; FLOOR_INFO* floor = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNumber); - int wd = GetWaterDepth(item->pos.xPos, item->pos.yPos, item->pos.zPos, roomNumber); + int depth = GetWaterDepth(item->pos.xPos, item->pos.yPos, item->pos.zPos, roomNumber); - if (wd == NO_HEIGHT) + if (depth == NO_HEIGHT) { item->fallspeed = 0; item->pos.xPos = coll->old.x; item->pos.yPos = coll->old.y; item->pos.zPos = coll->old.z; } - else if (wd <= 512) + else if (depth <= 512) { item->animNumber = LA_UNDERWATER_TO_STAND; item->currentAnimState = LS_ONWATER_EXIT; @@ -691,4 +538,187 @@ void LaraTestWaterDepth(ITEM_INFO* item, COLL_INFO* coll)//4B4F8(<), 4B95C(<) (F Lara.waterStatus = LW_WADE; item->pos.yPos = GetFloorHeight(floor, item->pos.xPos, item->pos.yPos, item->pos.zPos); } -} \ No newline at end of file +} + +// ------------------------------ +// SWIMMING +// State & Collision Functions +// ------------------------------ + +void lara_as_underwater_stop(ITEM_INFO* item, COLL_INFO* coll)//4C730, 4CB94 (F) +{ + if (item->hitPoints <= 0) + { + item->goalAnimState = LS_WATER_DEATH; + return; + } + + if (TrInput & IN_ROLL && LaraDrawType != LARA_DIVESUIT) + { + //item->currentAnimState = LS_UNDERWATER_ROLL; + //item->animNumber = LA_UNDERWATER_ROLL_180_START; + //item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + + // BUG: Doesn't work when idle??? + item->goalAnimState = LS_UNDERWATER_ROLL; + return; + } + + if (TrInput & IN_LOOK) + { + LookUpDown(); + } + + if (LaraDrawType == LARA_DIVESUIT) + { + DoLaraSubsuitSwimTurn(item); + } + else + { + DoLaraSwimTurn(item); + } + + if (TrInput & IN_JUMP) + { + item->goalAnimState = LS_UNDERWATER_FORWARD; + } + + item->fallspeed -= 6; + if (item->fallspeed < 0) + { + item->fallspeed = 0; + } + + if (Lara.gunStatus == LG_HANDS_BUSY) + { + Lara.gunStatus = LG_NO_ARMS; + } +} + +void lara_col_underwater_stop(ITEM_INFO* item, COLL_INFO* coll)//4C940(<), 4CDA4(<) (F) +{ + LaraSwimCollision(item, coll); +} + +void lara_as_underwater_swim(ITEM_INFO* item, COLL_INFO* coll)//4C548(<), 4C9AC(<) (F) +{ + if (item->hitPoints <= 0) + { + item->goalAnimState = LS_WATER_DEATH; + return; + } + + if (TrInput & IN_ROLL && LaraDrawType != LARA_DIVESUIT) + { + item->goalAnimState = LS_UNDERWATER_ROLL; + return; + } + + if (LaraDrawType == LARA_DIVESUIT) + { + DoLaraSubsuitSwimTurn(item); + } + else + { + DoLaraSwimTurn(item); + } + + item->fallspeed += 8; + if (item->fallspeed > 200) + { + item->fallspeed = 200; + } + + if (!(TrInput & IN_JUMP)) + { + item->goalAnimState = LS_UNDERWATER_INERTIA; + } +} + +void lara_col_underwater_swim(ITEM_INFO* item, COLL_INFO* coll)//4C900(<), 4CD64(<) (F) +{ + LaraSwimCollision(item, coll); +} + +void lara_as_glide(ITEM_INFO* item, COLL_INFO* coll)//4C634(<), 4CA98(<) (F) +{ + lara_as_underwater_stop(item, coll); // This one has the HANDS_BUSY check which wasn't in the current function. + + if (item->fallspeed <= 133) + { + item->goalAnimState = LS_UNDERWATER_STOP; + } +} + +void lara_col_glide(ITEM_INFO* item, COLL_INFO* coll)//4C920(<), 4CD84(<) (F) +{ + LaraSwimCollision(item, coll); +} + +void lara_as_dive(ITEM_INFO* item, COLL_INFO* coll)//4C854, 4CCB8 (F) +{ + if (TrInput & IN_FORWARD) + { + item->pos.xRot -= ANGLE(1.0f); + } +} + +void lara_col_dive(ITEM_INFO* item, COLL_INFO* coll)//4C960(<), 4CDC4(<) (F) +{ + LaraSwimCollision(item, coll); +} + +void lara_as_underwater_death(ITEM_INFO* item, COLL_INFO* coll)//4C884(<), 4CCE8(<) (F) +{ + Lara.look = 0; + + item->fallspeed -= 8; + if (item->fallspeed <= 0) + { + item->fallspeed = 0; + } + + if (item->pos.xRot < -ANGLE(2.0f) || item->pos.xRot > ANGLE(2.0f)) + { + if (item->pos.xRot >= 0) + { + item->pos.xRot -= ANGLE(2.0f); + } + else + { + item->pos.xRot += ANGLE(2.0f); + } + } + else + { + item->pos.xRot = 0; + } +} + +void lara_col_underwater_death(ITEM_INFO* item, COLL_INFO* coll)//4C980(<), 4CDE4(<) (F) +{ + Lara.gunStatus = LG_HANDS_BUSY; + Lara.air = -1; + item->hitPoints = -1; + + int wh = GetWaterHeight(item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber); + if (wh != NO_HEIGHT) + { + if (wh < item->pos.yPos - 100) + { + item->pos.yPos -= 5; + } + } + + LaraSwimCollision(item, coll); +} + +void lara_as_underwater_roll_180(ITEM_INFO* item, COLL_INFO* coll)//4C8F8(<), 4CD5C(<) (F) +{ + item->fallspeed = 0; +} + +void lara_col_underwater_roll_180(ITEM_INFO* item, COLL_INFO* coll)//4CA18(<), 4CE7C(<) (F) +{ + LaraSwimCollision(item, coll); +} diff --git a/TR5Main/Game/Lara/lara_swim.h b/TR5Main/Game/Lara/lara_swim.h index 90affc330..598093d2a 100644 --- a/TR5Main/Game/Lara/lara_swim.h +++ b/TR5Main/Game/Lara/lara_swim.h @@ -1,23 +1,34 @@ #pragma once - #include "collide.h" +typedef struct SubsuitInfo +{ + short XRot; + short dXRot; + short XRotVel; + short Vel[2]; + short YVel; +}; + +// Auxillary Functions void LaraWaterCurrent(COLL_INFO* coll); int GetWaterDepth(int x, int y, int z, short roomNumber); -void lara_col_waterroll(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_uwdeath(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_dive(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_tread(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_glide(ITEM_INFO* item, COLL_INFO* coll); -void lara_col_swim(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_waterroll(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_uwdeath(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_dive(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_tread(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_glide(ITEM_INFO* item, COLL_INFO* coll); -void lara_as_swim(ITEM_INFO* item, COLL_INFO* coll); void UpdateSubsuitAngles(); -void SwimTurnSubsuit(ITEM_INFO* item); -void SwimTurn(ITEM_INFO* item); +void DoLaraSubsuitSwimTurn(ITEM_INFO* item); +void DoLaraSwimTurn(ITEM_INFO* item); void LaraSwimCollision(ITEM_INFO* item, COLL_INFO* coll); -void LaraTestWaterDepth(ITEM_INFO* item, COLL_INFO* coll); \ No newline at end of file +void TestLaraWaterDepth(ITEM_INFO* item, COLL_INFO* coll); + +// State & Collision Functions +void lara_as_underwater_stop(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_underwater_stop(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_underwater_swim(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_underwater_swim(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_glide(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_glide(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_dive(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_dive(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_underwater_death(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_underwater_death(ITEM_INFO* item, COLL_INFO* coll); +void lara_as_underwater_roll_180(ITEM_INFO* item, COLL_INFO* coll); +void lara_col_underwater_roll_180(ITEM_INFO* item, COLL_INFO* coll); diff --git a/TR5Main/Game/Lara/lara_tests.cpp b/TR5Main/Game/Lara/lara_tests.cpp index d62f51f9b..c6bf80290 100644 --- a/TR5Main/Game/Lara/lara_tests.cpp +++ b/TR5Main/Game/Lara/lara_tests.cpp @@ -1,1272 +1,1334 @@ -#include "framework.h" -#include "lara.h" -#include "lara_tests.h" -#include "input.h" -#include "draw.h" -#include "lara_climb.h" -#include "lara_collide.h" - -static short LeftClimbTab[4] = // offset 0xA0638 -{ - 0x0200, 0x0400, 0x0800, 0x0100 -}; - -static short RightClimbTab[4] = // offset 0xA0640 -{ - 0x0800, 0x0100, 0x0200, 0x0400 -}; - -//bool EnableCrawlFlex1click, EnableCrawlFlex2click, EnableCrawlFlex3click, EnableMonkeyVault; -//bool TR12_OSCILLATE_HANG, EnableFeetHang; - -/*this file has all the generic test functions called in lara's state code*/ - -int TestLaraVault(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) -{ - if (!(TrInput & IN_ACTION) || Lara.gunStatus != LG_NO_ARMS) - return 0; - -// EnableCrawlFlex1click = true; -// EnableCrawlFlex2click = true; -// EnableCrawlFlex3click = true; -// EnableMonkeyVault = true; - - if (coll->collType == CT_FRONT) - { - short angle = item->pos.yRot; - bool result; - - if (coll->midSplitFloor) - { - if (coll->frontSplitFloor != coll->midSplitFloor) - return 0; - result = SnapToDiagonal(angle, 30); - } - else - { - result = SnapToQuadrant(angle, 30); - } - - if (!result) - return 0; - - int slope = abs(coll->leftFloor2 - coll->rightFloor2) >= 60; - - if (coll->frontFloor < 0 && coll->frontFloor >= -256) - { - if (!slope && (abs(coll->frontCeiling - coll->frontFloor) < 256))// && EnableCrawlFlex1click == true) - { - item->animNumber = LA_VAULT_TO_CROUCH_1CLICK; - item->currentAnimState = LS_GRABBING; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->goalAnimState = LS_CROUCH_IDLE; - item->pos.yPos += coll->frontFloor + 256; - Lara.gunStatus = LG_HANDS_BUSY; - } - } - else if (coll->frontFloor >= -640 && coll->frontFloor <= -384) - { - if (!slope && - coll->frontFloor - coll->frontCeiling >= 0 && - coll->leftFloor2 - coll->leftCeiling2 >= 0 && - coll->rightFloor2 - coll->rightCeiling2 >= 0) - { -#if 0 - if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP && Lara.waterSurfaceDist < -768) - return 0; -#endif - - item->animNumber = LA_VAULT_TO_STAND_2CLICK_START; - item->currentAnimState = LS_GRABBING; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->goalAnimState = LS_STOP; - item->pos.yPos += coll->frontFloor + 512; - Lara.gunStatus = LG_HANDS_BUSY; - } - else if ((!slope && (abs(coll->frontCeiling - coll->frontFloor) < 256)))// && EnableCrawlFlex2click == true) - { - item->animNumber = LA_VAULT_TO_CROUCH_2CLICK; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->currentAnimState = LS_GRABBING; - item->goalAnimState = LS_CROUCH_IDLE; - item->pos.yPos += coll->frontFloor + 512; - Lara.gunStatus = LG_HANDS_BUSY; - } - else - { - return 0; - } - } - else if (coll->frontFloor >= -896 && coll->frontFloor <= -640) - { - if (!slope && - coll->frontFloor - coll->frontCeiling >= 0 && - coll->leftFloor2 - coll->leftCeiling2 >= 0 && - coll->rightFloor2 - coll->rightCeiling2 >= 0) - { -#if 0 - if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP && Lara.waterSurfaceDist < -768) - return 0; -#endif - - item->animNumber = LA_VAULT_TO_STAND_3CLICK; - item->currentAnimState = LS_GRABBING; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->goalAnimState = LS_STOP; - item->pos.yPos += coll->frontFloor + 768; - Lara.gunStatus = LG_HANDS_BUSY; - } - else if ((!slope && (abs(coll->frontCeiling - coll->frontFloor) < 256)))// && EnableCrawlFlex3click == true)) - { - item->animNumber = LA_VAULT_TO_CROUCH_3CLICK; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->currentAnimState = LS_GRABBING; - item->goalAnimState = LS_CROUCH_IDLE; - item->pos.yPos += coll->frontFloor + 768; - Lara.gunStatus = LG_HANDS_BUSY; - } - else - { - return 0; - } - } - else if (!slope && coll->frontFloor >= -1920 && coll->frontFloor <= -896) - { -#if 0 - if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) - return 0; -#endif - - item->animNumber = LA_STAND_SOLID; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->goalAnimState = LS_JUMP_UP; - item->currentAnimState = LS_STOP; - Lara.calcFallSpeed = -3 - sqrt(-9600 - 12 * coll->frontFloor); - AnimateLara(item); - } - else - { - if (!Lara.climbStatus) - return 0; - - if (coll->frontFloor > -1920 || Lara.waterStatus == LW_WADE || coll->leftFloor2 > -1920 || coll->rightFloor2 > -2048 || coll->midCeiling > -1158) - { - if ((coll->frontFloor < -1024 || coll->frontCeiling >= 506) && coll->midCeiling <= -518) - { - ShiftItem(item, coll); - - if (LaraTestClimbStance(item, coll)) - { - item->animNumber = LA_STAND_SOLID; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->goalAnimState = LS_LADDER_IDLE; - item->currentAnimState = LS_STOP; - AnimateLara(item); - item->pos.yRot = angle; - Lara.gunStatus = LG_HANDS_BUSY; - return 1; - } - } - return 0; - } - - item->animNumber = LA_STAND_SOLID; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->goalAnimState = LS_JUMP_UP; - item->currentAnimState = LS_STOP; - Lara.calcFallSpeed = -116; - AnimateLara(item); - } - - item->pos.yRot = angle; - ShiftItem(item, coll); - - if (coll->midSplitFloor) // diagonal alignment - { - Vector2 v = GetDiagonalIntersect(item->pos.xPos, item->pos.zPos, coll->midSplitFloor, LARA_RAD, item->pos.yRot); - item->pos.xPos = v.x; - item->pos.zPos = v.y; - } - else // regular aligment - { - Vector2 v = GetOrthogonalIntersect(item->pos.xPos, item->pos.zPos, LARA_RAD, item->pos.yRot); - item->pos.xPos = v.x; - item->pos.zPos = v.y; - } - return 1; - } - else// if (EnableMonkeyVault == true) - { - if (Lara.canMonkeySwing) - { - FLOOR_INFO* F; - int c, h; - short roomNum = item->roomNumber; - F = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNum); - c = GetCeiling(F, item->pos.xPos, item->pos.yPos, item->pos.zPos); - h = (c)-(item->pos.yPos); - if (h > 1792 || - h < -1792 || - abs(h) == 768) - { - return 0; - } - item->animNumber = LA_STAND_IDLE; - item->frameNumber = g_Level.Anims[LA_STAND_IDLE].frameBase; - item->goalAnimState = LS_JUMP_UP; - item->currentAnimState = LS_TEST_1; - AnimateLara(item); - return 1; - } - } -// else - return 0; -} - -int TestWall(ITEM_INFO* item, int front, int right, int down)//12550, 12600 (F) -{ - int x = item->pos.xPos; - int y = item->pos.yPos + down; - int z = item->pos.zPos; - - short angle = GetQuadrant(item->pos.yRot); - short roomNum = item->roomNumber; - - FLOOR_INFO* floor; - int h, c; - - switch (angle) - { - case NORTH: - x -= right; - break; - case EAST: - z -= right; - break; - case SOUTH: - x += right; - break; - case WEST: - z += right; - break; - default: - break; - } - - GetFloor(x, y, z, &roomNum); - - switch (angle) - { - case NORTH: - z += front; - break; - case EAST: - x += front; - break; - case SOUTH: - z -= front; - break; - case WEST: - x -= front; - break; - default: - break; - } - - floor = GetFloor(x, y, z, &roomNum); - h = GetFloorHeight(floor, x, y, z); - c = GetCeiling(floor, x, y, z); - - if (h == NO_HEIGHT) - return 1; - - if (y >= h || y <= c) - return 2; - - return 0; -} - -int LaraHangTest(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) -{ - int delta, flag, flag2, front, dfront, x, z, result; - short angle, hdif, cdif, dir; - ANIM_FRAME* frame; - - delta = 0; - flag = 0; - angle = Lara.moveAngle; - if (angle == -ANGLE(90)) - { - delta = -100; - } - else if (angle == ANGLE(90)) - { - delta = 100; - } - hdif = LaraFloorFront(item, item->pos.yRot + angle, 100); - if (hdif < 200) - flag = 1; - cdif = LaraCeilingFront(item, item->pos.yRot + angle, 100, 0); - dir = GetQuadrant(item->pos.yRot); - switch (dir) - { - case NORTH: - item->pos.zPos += 4; - break; - case EAST: - item->pos.xPos += 4; - break; - case SOUTH: - item->pos.zPos -= 4; - break; - case WEST: - item->pos.xPos -= 4; - break; - } - coll->badPos = NO_BAD_POS; - coll->badNeg = -STEPUP_HEIGHT; - coll->badCeiling = 0; - Lara.moveAngle = 0; - coll->facing = Lara.moveAngle; - GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); - result = 0; - if (Lara.climbStatus) - { - if (TrInput & IN_ACTION && item->hitPoints > 0) - { - Lara.moveAngle = angle; - if (!LaraTestHangOnClimbWall(item, coll)) - { - if (item->animNumber != LA_LADDER_TO_HANG_RIGHT && item->animNumber != LA_LADDER_TO_HANG_LEFT) - { - SnapLaraToEdgeOfBlock(item, coll, dir); - item->pos.yPos = coll->old.y; - item->currentAnimState = LS_HANG; - item->goalAnimState = LS_HANG; - item->animNumber = LA_REACH_TO_HANG; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase + 21; - } - result = 1; - } - else - { - if (item->animNumber == LA_REACH_TO_HANG && item->frameNumber == g_Level.Anims[LA_REACH_TO_HANG].frameBase + 21 && LaraTestClimbStance(item, coll)) - item->goalAnimState = LS_LADDER_IDLE; - } - } - else - { - item->animNumber = LA_FALL_START; - item->currentAnimState = LS_JUMP_FORWARD; - item->goalAnimState = LS_JUMP_FORWARD; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->pos.yPos += 256; - item->gravityStatus = true; - item->speed = 2; - item->fallspeed = 1; - Lara.gunStatus = LG_NO_ARMS; - } - } - else - { - if (TrInput & IN_ACTION && item->hitPoints > 0 && coll->frontFloor <= 0) - { - if (flag && hdif > 0 && delta > 0 == coll->leftFloor > coll->rightFloor) - flag = 0; - frame = (ANIM_FRAME*)GetBoundsAccurate(item); - front = coll->frontFloor; - dfront = coll->frontFloor - frame->boundingBox.Y1; - flag2 = 0; - x = item->pos.xPos; - z = item->pos.zPos; - switch (dir) - { - case NORTH: - x += delta; - break; - case EAST: - z -= delta; - break; - case SOUTH: - x -= delta; - break; - case WEST: - z += delta; - break; - } - Lara.moveAngle = angle; - if (256 << dir & GetClimbTrigger(x, item->pos.yPos, z, item->roomNumber)) - { - if (!LaraTestHangOnClimbWall(item, coll)) - dfront = 0; - } - else if (abs(coll->leftFloor2 - coll->rightFloor2) >= 60) - { - if (delta < 0 && coll->leftFloor2 != coll->frontFloor || delta > 0 && coll->rightFloor2 != coll->frontFloor) - flag2 = 1; - } - coll->frontFloor = front; - if (!flag2 && coll->midCeiling < 0 && coll->collType == CT_FRONT && !flag && !coll->hitStatic && cdif <= -950 && dfront >= -60 && dfront <= 60) - { - switch (dir) - { - case NORTH: - case SOUTH: - item->pos.zPos += coll->shift.z; - break; - case EAST: - case WEST: - item->pos.xPos += coll->shift.x; - break; - } - item->pos.yPos += dfront; - } - else - { - item->pos.xPos = coll->old.x; - item->pos.yPos = coll->old.y; - item->pos.zPos = coll->old.z; - if (item->currentAnimState == LS_SHIMMY_LEFT || item->currentAnimState == LS_SHIMMY_RIGHT) - { - item->currentAnimState = LS_HANG; - item->goalAnimState = LS_HANG; - item->animNumber = LA_REACH_TO_HANG; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase + 21; - } - else if (item->currentAnimState == LS_SHIMMY_FEET_LEFT || item->currentAnimState == LS_SHIMMY_FEET_RIGHT) - { - item->currentAnimState = LS_HANG_FEET; - item->goalAnimState = LS_HANG_FEET; - item->animNumber = LA_HANG_FEET_IDLE; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - } - result = 1; - } - } - else - { - item->currentAnimState = LS_JUMP_UP; - item->goalAnimState = LS_JUMP_UP; - item->animNumber = LA_JUMP_UP; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase + 9; - frame = (ANIM_FRAME*)GetBoundsAccurate(item); - item->pos.xPos += coll->shift.x; - item->pos.yPos += frame->boundingBox.Y2; - item->pos.zPos += coll->shift.z; - item->gravityStatus = true; - item->speed = 2; - item->fallspeed = 1; - Lara.gunStatus = LG_NO_ARMS; - } - } - return result; -} - -int LaraHangLeftCornerTest(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) -{ - if (item->animNumber != LA_REACH_TO_HANG && item->animNumber != LA_HANG_FEET_IDLE) - return 0; - - if (coll->hitStatic) - return 0; - - int x; - int z; - - int oldXpos = item->pos.xPos; - int oldZpos = item->pos.zPos; - short oldYrot = item->pos.yRot; - int oldFrontFloor = coll->frontFloor; - - short angle = GetQuadrant(item->pos.yRot); - if (angle != NORTH && angle != SOUTH) - { - x = item->pos.xPos ^ (item->pos.xPos ^ item->pos.zPos) & 0x3FF; - z = item->pos.zPos ^ (item->pos.xPos ^ item->pos.zPos) & 0x3FF; - } - else - { - x = (item->pos.xPos & 0xFFFFFC00) - (item->pos.zPos & 0x3FF) + SECTOR(1); - z = (item->pos.zPos & 0xFFFFFC00) - (item->pos.xPos & 0x3FF) + SECTOR(1); - } - - item->pos.xPos = x; - Lara.cornerX = x; - item->pos.zPos = z; - Lara.cornerZ = z; - item->pos.yRot -= ANGLE(90.0f); - - int result = -IsValidHangPos(item, coll); - if (result) - { - if (Lara.climbStatus) - { - if (GetClimbTrigger(x, item->pos.yPos, z, item->roomNumber) & RightClimbTab[angle]) - { - item->pos.xPos = oldXpos; - item->pos.zPos = oldZpos; - item->pos.yRot = oldYrot; - Lara.moveAngle = 0; - return result; - } - } - else - { - if (abs(oldFrontFloor - coll->frontFloor) <= 60) - { - item->pos.xPos = oldXpos; - item->pos.zPos = oldZpos; - item->pos.yRot = oldYrot; - Lara.moveAngle = 0; - return result; - } - } - } - - item->pos.xPos = oldXpos; - item->pos.zPos = oldZpos; - item->pos.yRot = oldYrot; - Lara.moveAngle = 0; - - if (LaraFloorFront(item, oldYrot - ANGLE(90.0f), 116) < 0) - return 0; - - switch (angle) - { - case NORTH: - x = ((item->pos.xPos ^ item->pos.zPos) & 0x3FF) ^ item->pos.xPos - SECTOR(1); - z = ((item->pos.xPos ^ item->pos.zPos) & 0x3FF) ^ item->pos.zPos + SECTOR(1); - break; - - case SOUTH: - x = ((item->pos.xPos ^ item->pos.zPos) & 0x3FF) ^ (item->pos.xPos + SECTOR(1)); - z = ((item->pos.xPos ^ item->pos.zPos) & 0x3FF) ^ (item->pos.zPos - SECTOR(1)); - break; - - case WEST: - x = (item->pos.xPos & 0xFFFFFC00) - (item->pos.zPos & 0x3FF); - z = (item->pos.zPos & 0xFFFFFC00) - (item->pos.xPos & 0x3FF); - break; - - default: - x = ((item->pos.xPos + SECTOR(1)) & 0xFFFFFC00) - (item->pos.zPos & 0x3FF) + SECTOR(1); - z = ((item->pos.zPos + SECTOR(1)) & 0xFFFFFC00) - (item->pos.xPos & 0x3FF) + SECTOR(1); - break; - - } - - item->pos.xPos = x; - Lara.cornerX = x; - item->pos.zPos = z; - Lara.cornerZ = z; - item->pos.yRot += ANGLE(90.0f); - - result = IsValidHangPos(item, coll); - if (!result) - { - item->pos.xPos = oldXpos; - item->pos.zPos = oldZpos; - item->pos.yRot = oldYrot; - Lara.moveAngle = 0; - return result; - } - - item->pos.xPos = oldXpos; - item->pos.zPos = oldZpos; - item->pos.yRot = oldYrot; - Lara.moveAngle = 0; - - if (!Lara.climbStatus) - { - if (abs(oldFrontFloor - coll->frontFloor) <= 60) - { - switch (angle) - { - case NORTH: - if ((oldXpos & 0x3FF) > 512) - result = 0; - break; - case EAST: - if ((oldZpos & 0x3FF) < 512) - result = 0; - break; - case SOUTH: - if ((oldXpos & 0x3FF) < 512) - result = 0; - break; - case WEST: - if ((oldZpos & 0x3FF) > 512) - result = 0; - break; - } - return result; - } - return 0; - } - - if (GetClimbTrigger(x, item->pos.yPos, z, item->roomNumber) & LeftClimbTab[angle]) - return result; - - short front = LaraFloorFront(item, item->pos.yRot, 116); - if (abs(front - coll->frontFloor) > 60) - return 0; - - if (front < -768) - return 0; - - return result; -} - -int LaraHangRightCornerTest(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) -{ - if (item->animNumber != LA_REACH_TO_HANG && item->animNumber != LA_HANG_FEET_IDLE) - return 0; - - if (coll->hitStatic) - return 0; - - int x; - int z; - - int oldXpos = item->pos.xPos; - int oldZpos = item->pos.zPos; - short oldYrot = item->pos.yRot; - int oldFrontFloor = coll->frontFloor; - - short angle = GetQuadrant(item->pos.yRot); - if (angle != NORTH && angle != SOUTH) - { - x = (item->pos.xPos & 0xFFFFFC00) - (item->pos.zPos & 0x3FF) + SECTOR(1); - z = (item->pos.zPos & 0xFFFFFC00) - (item->pos.xPos & 0x3FF) + SECTOR(1); - } - else - { - x = item->pos.xPos ^ (item->pos.xPos ^ item->pos.zPos) & 0x3FF; - z = item->pos.zPos ^ (item->pos.xPos ^ item->pos.zPos) & 0x3FF; - } - - item->pos.xPos = x; - Lara.cornerX = x; - item->pos.zPos = z; - Lara.cornerZ = z; - item->pos.yRot += ANGLE(90.0f); - - int result = -IsValidHangPos(item, coll); - if (result) - { - if (Lara.climbStatus) - { - if (GetClimbTrigger(x, item->pos.yPos, z, item->roomNumber) & LeftClimbTab[angle]) - { - item->pos.xPos = oldXpos; - item->pos.zPos = oldZpos; - item->pos.yRot = oldYrot; - Lara.moveAngle = 0; - return result; - } - } - else - { - if (abs(oldFrontFloor - coll->frontFloor) <= 60) - { - item->pos.xPos = oldXpos; - item->pos.zPos = oldZpos; - item->pos.yRot = oldYrot; - Lara.moveAngle = 0; - return result; - } - } - } - - item->pos.xPos = oldXpos; - item->pos.zPos = oldZpos; - item->pos.yRot = oldYrot; - Lara.moveAngle = 0; - - if (LaraFloorFront(item, oldYrot + ANGLE(90.0f), 116) < 0) - return 0; - - switch (angle) - { - case NORTH: - x = ((item->pos.xPos + SECTOR(1)) & 0xFFFFFC00) - (item->pos.zPos & 0x3FF) + SECTOR(1); - z = ((item->pos.zPos + SECTOR(1)) & 0xFFFFFC00) - (item->pos.xPos & 0x3FF) + SECTOR(1); - break; - - case SOUTH: - x = ((item->pos.xPos - SECTOR(1)) & 0xFFFFFC00) - (item->pos.zPos & 0x3FF) + SECTOR(1); - z = ((item->pos.zPos - SECTOR(1)) & 0xFFFFFC00) - (item->pos.xPos & 0x3FF) + SECTOR(1); - break; - - case WEST: - x = (item->pos.xPos ^ item->pos.zPos) & 0x3FF ^ (item->pos.xPos - SECTOR(1)); - z = (item->pos.xPos ^ item->pos.zPos) & 0x3FF ^ (item->pos.zPos + SECTOR(1)); - break; - - default: - x = ((item->pos.xPos ^ item->pos.zPos) & 0x3FF) ^ (item->pos.xPos + SECTOR(1)); - z = ((item->pos.xPos ^ item->pos.zPos) & 0x3FF) ^ (item->pos.zPos - SECTOR(1)); - break; - - } - - item->pos.xPos = x; - Lara.cornerX = x; - item->pos.zPos = z; - Lara.cornerZ = z; - item->pos.yRot -= ANGLE(90.0f); - - result = IsValidHangPos(item, coll); - if (!result) - { - item->pos.xPos = oldXpos; - item->pos.zPos = oldZpos; - item->pos.yRot = oldYrot; - Lara.moveAngle = 0; - return result; - } - - item->pos.xPos = oldXpos; - item->pos.zPos = oldZpos; - item->pos.yRot = oldYrot; - Lara.moveAngle = 0; - - if (!Lara.climbStatus) - { - if (abs(oldFrontFloor - coll->frontFloor) <= 60) - { - switch (angle) - { - case NORTH: - if ((oldXpos & 0x3FF) < 512) - result = 0; - break; - case EAST: - if ((oldZpos & 0x3FF) > 512) - result = 0; - break; - case SOUTH: - if ((oldXpos & 0x3FF) > 512) - result = 0; - break; - case WEST: - if ((oldZpos & 0x3FF) < 512) - result = 0; - break; - } - return result; - } - return 0; - } - - if (GetClimbTrigger(x, item->pos.yPos, z, item->roomNumber) & RightClimbTab[angle]) - return result; - - short front = LaraFloorFront(item, item->pos.yRot, 116); - if (abs(front - coll->frontFloor) > 60) - return 0; - - if (front < -768) - return 0; - - return result; -} - -int IsValidHangPos(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) -{ - if (LaraFloorFront(item, item->pos.yRot + Lara.moveAngle, 100) < 200) - return 0; - - short angle = GetQuadrant(item->pos.yRot); - switch (angle) - { - case NORTH: - item->pos.zPos += 4; - break; - case EAST: - item->pos.xPos += 4; - break; - case SOUTH: - item->pos.zPos -= 4; - break; - case WEST: - item->pos.xPos -= 4; - break; - default: - break; - } - - coll->badPos = NO_BAD_POS; - coll->badNeg = -512; - coll->badCeiling = 0; - - Lara.moveAngle = 0; - - coll->facing = Lara.moveAngle; - GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); - - if (coll->midCeiling >= 0 || coll->collType != CT_FRONT || coll->hitStatic) - return 0; - - return abs(coll->frontFloor - coll->rightFloor2) < 60; -} - -int LaraTestClimbStance(ITEM_INFO* item, COLL_INFO* coll)//11F78, 12028 -{ - int shift_r, shift_l; - - if (LaraTestClimbPos(item, coll->radius, coll->radius + 120, -700, 512, &shift_r) != 1) - return false; - - if (LaraTestClimbPos(item, coll->radius, -(coll->radius + 120), -700, 512, &shift_l) != 1) - return false; - - if (shift_r) - { - if (shift_l) - { - if (shift_r < 0 != shift_l < 0) - return false; - - if ((shift_r < 0 && shift_l < shift_r) || - (shift_r > 0 && shift_l > shift_r)) - { - item->pos.yPos += shift_l; - return true; - } - } - - item->pos.yPos += shift_r; - } - else if (shift_l) - { - item->pos.yPos += shift_l; - } - - return true; -} - -int LaraTestHangOnClimbWall(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) -{ - BOUNDING_BOX* bounds; - int shift, result; - - if (Lara.climbStatus == 0) - return 0; - - if (item->fallspeed < 0) - return 0; - - switch (GetQuadrant(item->pos.yRot)) - { - case NORTH: - case SOUTH: - item->pos.zPos += coll->shift.z; - break; - - case EAST: - case WEST: - item->pos.xPos += coll->shift.x; - break; - - default: - break; - } - - - bounds = GetBoundsAccurate(item); - - if (Lara.moveAngle) - { - short l = LaraCeilingFront(item, item->pos.yRot, 0, 0); - short r = LaraCeilingFront(item, item->pos.yRot + Lara.moveAngle, 128, 0); - - if (abs(l - r) > 60) - return 0; - } - - if (LaraTestClimbPos(item, coll->radius, coll->radius, bounds->Y1, bounds->Y2 - bounds->Y1, &shift) && - LaraTestClimbPos(item, coll->radius, -coll->radius, bounds->Y1, bounds->Y2 - bounds->Y1, &shift)) - { - result = LaraTestClimbPos(item, coll->radius, 0, bounds->Y1, bounds->Y2 - bounds->Y1, &shift); - if (result) - { - if (result != 1) - item->pos.yPos += shift; - return 1; - } - } - - return 0; -} - -int LaraTestEdgeCatch(ITEM_INFO* item, COLL_INFO* coll, int* edge) // (F) (D) -{ - - BOUNDING_BOX* bounds = GetBoundsAccurate(item); - int hdif = coll->frontFloor - bounds->Y1; - - if (hdif < 0 == hdif + item->fallspeed < 0) - { - hdif = item->pos.yPos + bounds->Y1; - - if ((hdif + item->fallspeed & 0xFFFFFF00) != (hdif & 0xFFFFFF00)) - { - if (item->fallspeed > 0) - *edge = (hdif + item->fallspeed) & 0xFFFFFF00; - else - *edge = hdif & 0xFFFFFF00; - - return -1; - } - - return 0; - } - - if (abs(coll->leftFloor2 - coll->rightFloor2) >= SLOPE_DIF) - return 0; - - return 1; -} - -int TestHangSwingIn(ITEM_INFO* item, short angle)//14104, 141B4 (F) -{ - int x = item->pos.xPos; - int y = item->pos.yPos; - int z = item->pos.zPos; - short roomNum = item->roomNumber; - FLOOR_INFO* floor; - int h, c; - - //debug till scripting be ready -// TR12_OSCILLATE_HANG = true; - - /*if (angle == ANGLE(180.0f)) - { - z -= 256; - } - else if (angle == -ANGLE(90)) - { - x -= 256; - } - else if (angle == ANGLE(90)) - { - x += 256; - } - else if (angle == ANGLE(0)) - { - z += 256; - }*/ - - z += (phd_cos(angle) * STEP_SIZE) >> W2V_SHIFT; - x += (phd_sin(angle) * STEP_SIZE) >> W2V_SHIFT; - - floor = GetFloor(x, y, z, &roomNum); - h = GetFloorHeight(floor, x, y, z); - c = GetCeiling(floor, x, y, z); - - if (h != NO_HEIGHT) - { -/* if (TR12_OSCILLATE_HANG == true) - { - if (((h - y) > 0) - && ((c - y) < -400)) - return(1); - } - else - {*/ - if (((h - y) > 0) - && ((c - y) < -400) - && ((y - 819 - c) > -72)) - return(1); -// } - } - return(0); -} - -int TestHangFeet(ITEM_INFO* item, short angle) -{ - return 0; - if (Lara.climbStatus) - return 0; - - // EnableFeetHang = true; - - -// if (!EnableFeetHang) -// return 0; - - int x = item->pos.xPos; - int y = item->pos.yPos; - int z = item->pos.zPos; - short roomNum = item->roomNumber; - FLOOR_INFO* floor; - int h, c, g, m, j; - - if (angle == ANGLE(180.0f)) - { - z -= 256; - } - else if (angle == -ANGLE(90.0f)) - { - x -= 256; - } - else if (angle == ANGLE(90.0f)) - { - x += 256; - } - else if (angle == ANGLE(0.0f)) - { - z += 256; - } - - floor = GetFloor(x, y, z, &roomNum); - h = GetFloorHeight(floor, x, y, z); - c = GetCeiling(floor, x, y, z); - g = h - y; - m = c - y; - j = y - 128 - c; - - if (item->currentAnimState == LS_CRAWL_TO_HANG) - { - if (h != NO_HEIGHT) - { - if (((g) > 0) - && ((m) < -128) - && ((j) > -72)) - return(1); - } - return(0); - } - else - { - if (h != NO_HEIGHT) - { - if (((g) > 0) - && ((m) < -128) - && ((j) > -72)) - return(0); - } - return(1); - } -} - -int CanLaraHangSideways(ITEM_INFO* item, COLL_INFO* coll, short angle)//19930, 19A64 (F) -{ - int oldx = item->pos.xPos; - int oldz = item->pos.zPos; - int x = item->pos.xPos; - int z = item->pos.zPos; - int res; - - Lara.moveAngle = angle; - - switch (GetQuadrant(item->pos.yRot + Lara.moveAngle)) - { - case 0: - z += 16; - break; - case 1: - x += 16; - break; - case 2: - z -= 16; - break; - case 3: - x -= 16; - break; - } - - item->pos.xPos = x; - item->pos.zPos = z; - - coll->old.y = item->pos.yPos; - - res = LaraHangTest(item, coll); - - item->pos.xPos = oldx; - item->pos.zPos = oldz; - - Lara.moveAngle = angle; - - return !res; -} - -void SetCornerAnim(ITEM_INFO* item, COLL_INFO* coll, short rot, short flip)//1A090, 1A1C4 (F) -{ - if (item->hitPoints <= 0) - { - item->goalAnimState = LS_JUMP_FORWARD; - item->currentAnimState = LS_JUMP_FORWARD; - item->animNumber = LA_FALL_START; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - - item->gravityStatus = true; - item->speed = 2; - item->pos.yPos += 256; - item->fallspeed = 1; - - Lara.gunStatus = LG_NO_ARMS; - - item->pos.yRot += rot / 2; - } - else if (flip) - { - if (Lara.isClimbing) - { - item->animNumber = LA_LADDER_IDLE; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->goalAnimState = LS_LADDER_IDLE; - item->currentAnimState = LS_LADDER_IDLE; - } - else - { - item->animNumber = LA_REACH_TO_HANG; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase + 21; - item->goalAnimState = LS_HANG; - item->currentAnimState = LS_HANG; - } - - coll->old.x = Lara.cornerX; - item->pos.xPos = Lara.cornerX; - - coll->old.z = Lara.cornerZ; - item->pos.zPos = Lara.cornerZ; - - item->pos.yRot += rot; - } -} - -void SetCornerAnimFeet(ITEM_INFO* item, COLL_INFO* coll, short rot, short flip) -{ - if (item->hitPoints <= 0) - { - item->goalAnimState = LS_JUMP_FORWARD; - item->currentAnimState = LS_JUMP_FORWARD; - item->animNumber = LA_FALL_START; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - - item->gravityStatus = true; - item->speed = 2; - item->pos.yPos += 256; - item->fallspeed = 1; - - Lara.gunStatus = LG_NO_ARMS; - - item->pos.yRot += rot / 2; - } - else if (flip) - { - - item->animNumber = LA_HANG_FEET_IDLE; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->goalAnimState = LS_HANG_FEET; - item->currentAnimState = LS_HANG_FEET; - - coll->old.x = Lara.cornerX; - item->pos.xPos = Lara.cornerX; - - coll->old.z = Lara.cornerZ; - item->pos.zPos = Lara.cornerZ; - - item->pos.yRot += rot; - } -} - -short LaraFloorFront(ITEM_INFO* item, short ang, int dist) // (F) (D) -{ - short room = item->roomNumber; - - int x = item->pos.xPos + ((dist * phd_sin(ang)) >> W2V_SHIFT); - int y = item->pos.yPos - 762; - int z = item->pos.zPos + ((dist * phd_cos(ang)) >> W2V_SHIFT); - - int height = GetFloorHeight(GetFloor(x, y, z, &room), x, y, z); - - if (height != NO_HEIGHT) - height -= item->pos.yPos; - - return height; -} - -short LaraCeilingFront(ITEM_INFO* item, short ang, int dist, int h) // (F) (D) -{ - short room = item->roomNumber; - - int x = item->pos.xPos + ((dist * phd_sin(ang)) >> W2V_SHIFT); - int y = item->pos.yPos - h; - int z = item->pos.zPos + ((dist * phd_cos(ang)) >> W2V_SHIFT); - - int height = GetCeiling(GetFloor(x, y, z, &room), x, y, z); - - if (height != NO_HEIGHT) - height += h - item->pos.yPos; - - return height; -} - -int LaraFallen(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) -{ - if (Lara.waterStatus == LW_WADE || coll->midFloor <= STEPUP_HEIGHT) - { - return 0; - } - - item->animNumber = LA_FALL_START; - item->currentAnimState = LS_JUMP_FORWARD; - item->goalAnimState = LS_JUMP_FORWARD; - item->frameNumber = g_Level.Anims[item->animNumber].frameBase; - item->fallspeed = 0; - item->gravityStatus = true; - return 1; -} - -int LaraLandedBad(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) -{ - int landspeed = item->fallspeed - 140; - - if (landspeed > 0) - { - if (landspeed <= 14) - { - item->hitPoints -= 1000 * SQUARE(landspeed) / 196; - return item->hitPoints <= 0; - } - else - { - item->hitPoints = -1; - return 1; - } - } - - return 0; -} - -void GetTighRopeFallOff(int regularity) -{ - if (LaraItem->hitPoints <= 0 || LaraItem->hitStatus) - { - LaraItem->goalAnimState = LS_TIGHTROPE_UNBALANCE_LEFT; - LaraItem->currentAnimState = LS_TIGHTROPE_UNBALANCE_LEFT; - LaraItem->animNumber = LA_TIGHTROPE_FALL_LEFT; - LaraItem->frameNumber = g_Level.Anims[LaraItem->animNumber].frameBase; - } - - if (!Lara.tightRopeFall && !(GetRandomControl() & regularity)) - Lara.tightRopeFall = 2 - ((GetRandomControl() & 0xF) != 0); -} - -bool TestLaraLean(ITEM_INFO* item, COLL_INFO* coll) +#include "framework.h" +#include "lara.h" +#include "lara_tests.h" +#include "input.h" +#include "draw.h" +#include "lara_climb.h" +#include "lara_collide.h" + +static short LeftClimbTab[4] = // offset 0xA0638 { - // TODO: make it more fine-tuned when new collision is done. - switch (coll->collType) + 0x0200, 0x0400, 0x0800, 0x0100 +}; + +static short RightClimbTab[4] = // offset 0xA0640 +{ + 0x0800, 0x0100, 0x0200, 0x0400 +}; + +//bool EnableCrawlFlex1click, EnableCrawlFlex2click, EnableCrawlFlex3click, EnableMonkeyVault; +//bool TR12_OSCILLATE_HANG, EnableFeetHang; + +/*this file has all the generic test functions called in lara's state code*/ + +// This function is disgusting. +int TestLaraVault(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +{ + if (!(TrInput & IN_ACTION) || Lara.gunStatus != LG_NO_ARMS) { - case CT_RIGHT: - if (TrInput & IN_RIGHT) - return false; - case CT_LEFT: - if (TrInput & IN_LEFT) - return false; + return 0; } + + // EnableCrawlFlex1click = true; + // EnableCrawlFlex2click = true; + // EnableCrawlFlex3click = true; + // EnableMonkeyVault = true; + + if (coll->collType == CT_FRONT) + { + short angle = item->pos.yRot; + bool result; + + if (coll->midSplitFloor) + { + if (coll->frontSplitFloor != coll->midSplitFloor) + return 0; + result = SnapToDiagonal(angle, 30); + } + else + { + result = SnapToQuadrant(angle, 30); + } + + if (!result) + return 0; + + int slope = abs(coll->leftFloor2 - coll->rightFloor2) >= 60; + + if (coll->frontFloor < 0 && coll->frontFloor >= -256) + { + if (!slope && (abs(coll->frontCeiling - coll->frontFloor) < 256))// && EnableCrawlFlex1click == true) + { + item->animNumber = LA_VAULT_TO_CROUCH_1CLICK; + item->currentAnimState = LS_GRABBING; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->goalAnimState = LS_CROUCH_IDLE; + item->pos.yPos += coll->frontFloor + 256; + Lara.gunStatus = LG_HANDS_BUSY; + } + } + else if (coll->frontFloor >= -640 && coll->frontFloor <= -384) + { + if (!slope && + coll->frontFloor - coll->frontCeiling >= 0 && + coll->leftFloor2 - coll->leftCeiling2 >= 0 && + coll->rightFloor2 - coll->rightCeiling2 >= 0) + { +#if 0 + if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP && Lara.waterSurfaceDist < -768) + return 0; +#endif + + item->animNumber = LA_VAULT_TO_STAND_2CLICK_START; + item->currentAnimState = LS_GRABBING; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->goalAnimState = LS_STOP; + item->pos.yPos += coll->frontFloor + 512; + Lara.gunStatus = LG_HANDS_BUSY; + } + else if ((!slope && (abs(coll->frontCeiling - coll->frontFloor) < 256)))// && EnableCrawlFlex2click == true) + { + item->animNumber = LA_VAULT_TO_CROUCH_2CLICK; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->currentAnimState = LS_GRABBING; + item->goalAnimState = LS_CROUCH_IDLE; + item->pos.yPos += coll->frontFloor + 512; + Lara.gunStatus = LG_HANDS_BUSY; + } + else + { + return 0; + } + } + else if (coll->frontFloor >= -896 && coll->frontFloor <= -640) + { + if (!slope && + coll->frontFloor - coll->frontCeiling >= 0 && + coll->leftFloor2 - coll->leftCeiling2 >= 0 && + coll->rightFloor2 - coll->rightCeiling2 >= 0) + { +#if 0 + if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP && Lara.waterSurfaceDist < -768) + return 0; +#endif + + item->animNumber = LA_VAULT_TO_STAND_3CLICK; + item->currentAnimState = LS_GRABBING; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->goalAnimState = LS_STOP; + item->pos.yPos += coll->frontFloor + 768; + Lara.gunStatus = LG_HANDS_BUSY; + } + else if ((!slope && (abs(coll->frontCeiling - coll->frontFloor) < 256)))// && EnableCrawlFlex3click == true)) + { + item->animNumber = LA_VAULT_TO_CROUCH_3CLICK; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->currentAnimState = LS_GRABBING; + item->goalAnimState = LS_CROUCH_IDLE; + item->pos.yPos += coll->frontFloor + 768; + Lara.gunStatus = LG_HANDS_BUSY; + } + else + { + return 0; + } + } + else if (!slope && coll->frontFloor >= -1920 && coll->frontFloor <= -896) + { +#if 0 + if (g_Level.Rooms[item->roomNumber].flags & ENV_FLAG_SWAMP) + return 0; +#endif + + item->animNumber = LA_STAND_SOLID; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->goalAnimState = LS_JUMP_UP; + item->currentAnimState = LS_STOP; + Lara.calcFallSpeed = -3 - sqrt(-9600 - 12 * coll->frontFloor); + AnimateLara(item); + } + else + { + if (!Lara.climbStatus) + return 0; + + if (coll->frontFloor > -1920 || Lara.waterStatus == LW_WADE || coll->leftFloor2 > -1920 || coll->rightFloor2 > -2048 || coll->midCeiling > -1158) + { + if ((coll->frontFloor < -1024 || coll->frontCeiling >= 506) && coll->midCeiling <= -518) + { + ShiftItem(item, coll); + + if (LaraTestClimbStance(item, coll)) + { + item->animNumber = LA_STAND_SOLID; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->goalAnimState = LS_LADDER_IDLE; + item->currentAnimState = LS_STOP; + AnimateLara(item); + item->pos.yRot = angle; + Lara.gunStatus = LG_HANDS_BUSY; + return 1; + } + } + return 0; + } + + item->animNumber = LA_STAND_SOLID; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->goalAnimState = LS_JUMP_UP; + item->currentAnimState = LS_STOP; + Lara.calcFallSpeed = -116; + AnimateLara(item); + } + + item->pos.yRot = angle; + ShiftItem(item, coll); + + if (coll->midSplitFloor) // diagonal alignment + { + Vector2 v = GetDiagonalIntersect(item->pos.xPos, item->pos.zPos, coll->midSplitFloor, LARA_RAD, item->pos.yRot); + item->pos.xPos = v.x; + item->pos.zPos = v.y; + } + else // regular aligment + { + Vector2 v = GetOrthogonalIntersect(item->pos.xPos, item->pos.zPos, LARA_RAD, item->pos.yRot); + item->pos.xPos = v.x; + item->pos.zPos = v.y; + } + return 1; + } + else// if (EnableMonkeyVault == true) + { + if (Lara.canMonkeySwing) + { + FLOOR_INFO* F; + int c, h; + short roomNum = item->roomNumber; + F = GetFloor(item->pos.xPos, item->pos.yPos, item->pos.zPos, &roomNum); + c = GetCeiling(F, item->pos.xPos, item->pos.yPos, item->pos.zPos); + h = (c)-(item->pos.yPos); + if (h > 1792 || + h < -1792 || + abs(h) == 768) + { + return 0; + } + item->animNumber = LA_STAND_IDLE; + item->frameNumber = g_Level.Anims[LA_STAND_IDLE].frameBase; + item->goalAnimState = LS_JUMP_UP; + item->currentAnimState = LS_TEST_1; + AnimateLara(item); + return 1; + } + } + // else + return 0; +} + +int TestWall(ITEM_INFO* item, int front, int right, int down)//12550, 12600 (F) +{ + int x = item->pos.xPos; + int y = item->pos.yPos + down; + int z = item->pos.zPos; + + short angle = GetQuadrant(item->pos.yRot); + short roomNum = item->roomNumber; + + FLOOR_INFO* floor; + int h, c; + + switch (angle) + { + case NORTH: + x -= right; + break; + case EAST: + z -= right; + break; + case SOUTH: + x += right; + break; + case WEST: + z += right; + break; + default: + break; + } + + GetFloor(x, y, z, &roomNum); + + switch (angle) + { + case NORTH: + z += front; + break; + case EAST: + x += front; + break; + case SOUTH: + z -= front; + break; + case WEST: + x -= front; + break; + default: + break; + } + + floor = GetFloor(x, y, z, &roomNum); + h = GetFloorHeight(floor, x, y, z); + c = GetCeiling(floor, x, y, z); + + if (h == NO_HEIGHT) + return 1; + + if (y >= h || y <= c) + return 2; + + return 0; +} + +bool TestLaraHang(ITEM_INFO* player, COLL_INFO* coll) +{ + if (TrInput & IN_ACTION && + Lara.climbStatus && + player->hitPoints > 0) + { + if (!LaraTestHangOnClimbWall(player, coll)) + { + int r; + } + + return true; + } + else if (TrInput & IN_ACTION && player->hitPoints > 0 && coll->frontFloor <= 0) + { + int t; + // some other garbage. + return true; + } + + return false; +} + +void SetLaraHang(ITEM_INFO* player, COLL_INFO* coll) +{ + +} + +int LaraHangTest(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +{ + int delta, flag, flag2, front, dfront, x, z, result; + short angle, hdif, cdif, dir; + ANIM_FRAME* frame; + + delta = 0; + flag = 0; + angle = Lara.moveAngle; + if (angle == -ANGLE(90)) + { + delta = -100; + } + else if (angle == ANGLE(90)) + { + delta = 100; + } + hdif = LaraFloorFront(item, item->pos.yRot + angle, 100); + if (hdif < 200) + flag = 1; + cdif = LaraCeilingFront(item, item->pos.yRot + angle, 100, 0); + dir = GetQuadrant(item->pos.yRot); + switch (dir) + { + case NORTH: + item->pos.zPos += 4; + break; + case EAST: + item->pos.xPos += 4; + break; + case SOUTH: + item->pos.zPos -= 4; + break; + case WEST: + item->pos.xPos -= 4; + break; + } + coll->badPos = NO_BAD_POS; + coll->badNeg = -STEPUP_HEIGHT; + coll->badCeiling = 0; + Lara.moveAngle = 0; + coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); + result = 0; + if (Lara.climbStatus) + { + if (TrInput & IN_ACTION && item->hitPoints > 0) + { + Lara.moveAngle = angle; + if (!LaraTestHangOnClimbWall(item, coll)) + { + if (item->animNumber != LA_LADDER_TO_HANG_RIGHT && item->animNumber != LA_LADDER_TO_HANG_LEFT) + { + SnapLaraToEdgeOfBlock(item, coll, dir); + item->pos.yPos = coll->old.y; + item->currentAnimState = LS_HANG; + item->goalAnimState = LS_HANG; + item->animNumber = LA_REACH_TO_HANG; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase + 21; + } + result = 1; + } + else + { + if (item->animNumber == LA_REACH_TO_HANG && item->frameNumber == g_Level.Anims[LA_REACH_TO_HANG].frameBase + 21 && LaraTestClimbStance(item, coll)) + item->goalAnimState = LS_LADDER_IDLE; + } + } + else + { + item->animNumber = LA_FALL_START; + item->currentAnimState = LS_JUMP_FORWARD; + item->goalAnimState = LS_JUMP_FORWARD; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->pos.yPos += 256; + item->gravityStatus = true; + item->speed = 2; + item->fallspeed = 1; + Lara.gunStatus = LG_NO_ARMS; + } + } + else + { + if (TrInput & IN_ACTION && item->hitPoints > 0 && coll->frontFloor <= 0) + { + if (flag && hdif > 0 && delta > 0 == coll->leftFloor > coll->rightFloor) + flag = 0; + frame = (ANIM_FRAME*)GetBoundsAccurate(item); + front = coll->frontFloor; + dfront = coll->frontFloor - frame->boundingBox.Y1; + flag2 = 0; + x = item->pos.xPos; + z = item->pos.zPos; + switch (dir) + { + case NORTH: + x += delta; + break; + case EAST: + z -= delta; + break; + case SOUTH: + x -= delta; + break; + case WEST: + z += delta; + break; + } + Lara.moveAngle = angle; + if (256 << dir & GetClimbTrigger(x, item->pos.yPos, z, item->roomNumber)) + { + if (!LaraTestHangOnClimbWall(item, coll)) + dfront = 0; + } + else if (abs(coll->leftFloor2 - coll->rightFloor2) >= 60) + { + if (delta < 0 && coll->leftFloor2 != coll->frontFloor || delta > 0 && coll->rightFloor2 != coll->frontFloor) + flag2 = 1; + } + coll->frontFloor = front; + if (!flag2 && coll->midCeiling < 0 && coll->collType == CT_FRONT && !flag && !coll->hitStatic && cdif <= -950 && dfront >= -60 && dfront <= 60) + { + switch (dir) + { + case NORTH: + case SOUTH: + item->pos.zPos += coll->shift.z; + break; + case EAST: + case WEST: + item->pos.xPos += coll->shift.x; + break; + } + item->pos.yPos += dfront; + } + else + { + item->pos.xPos = coll->old.x; + item->pos.yPos = coll->old.y; + item->pos.zPos = coll->old.z; + if (item->currentAnimState == LS_SHIMMY_LEFT || item->currentAnimState == LS_SHIMMY_RIGHT) + { + item->currentAnimState = LS_HANG; + item->goalAnimState = LS_HANG; + item->animNumber = LA_REACH_TO_HANG; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase + 21; + } + else if (item->currentAnimState == LS_SHIMMY_FEET_LEFT || item->currentAnimState == LS_SHIMMY_FEET_RIGHT) + { + item->currentAnimState = LS_HANG_FEET; + item->goalAnimState = LS_HANG_FEET; + item->animNumber = LA_HANG_FEET_IDLE; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + } + result = 1; + } + } + else + { + item->currentAnimState = LS_JUMP_UP; + item->goalAnimState = LS_JUMP_UP; + item->animNumber = LA_JUMP_UP; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase + 9; + frame = (ANIM_FRAME*)GetBoundsAccurate(item); + item->pos.xPos += coll->shift.x; + item->pos.yPos += frame->boundingBox.Y2; + item->pos.zPos += coll->shift.z; + item->gravityStatus = true; + item->speed = 2; + item->fallspeed = 1; + Lara.gunStatus = LG_NO_ARMS; + } + } + return result; +} + +int LaraHangLeftCornerTest(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +{ + if (item->animNumber != LA_REACH_TO_HANG && item->animNumber != LA_HANG_FEET_IDLE) + return 0; + + if (coll->hitStatic) + return 0; + + int x; + int z; + + int oldXpos = item->pos.xPos; + int oldZpos = item->pos.zPos; + short oldYrot = item->pos.yRot; + int oldFrontFloor = coll->frontFloor; + + short angle = GetQuadrant(item->pos.yRot); + if (angle != NORTH && angle != SOUTH) + { + x = item->pos.xPos ^ (item->pos.xPos ^ item->pos.zPos) & 0x3FF; + z = item->pos.zPos ^ (item->pos.xPos ^ item->pos.zPos) & 0x3FF; + } + else + { + x = (item->pos.xPos & 0xFFFFFC00) - (item->pos.zPos & 0x3FF) + SECTOR(1); + z = (item->pos.zPos & 0xFFFFFC00) - (item->pos.xPos & 0x3FF) + SECTOR(1); + } + + item->pos.xPos = x; + Lara.cornerX = x; + item->pos.zPos = z; + Lara.cornerZ = z; + item->pos.yRot -= ANGLE(90.0f); + + int result = -IsValidHangPos(item, coll); + if (result) + { + if (Lara.climbStatus) + { + if (GetClimbTrigger(x, item->pos.yPos, z, item->roomNumber) & RightClimbTab[angle]) + { + item->pos.xPos = oldXpos; + item->pos.zPos = oldZpos; + item->pos.yRot = oldYrot; + Lara.moveAngle = 0; + return result; + } + } + else + { + if (abs(oldFrontFloor - coll->frontFloor) <= 60) + { + item->pos.xPos = oldXpos; + item->pos.zPos = oldZpos; + item->pos.yRot = oldYrot; + Lara.moveAngle = 0; + return result; + } + } + } + + item->pos.xPos = oldXpos; + item->pos.zPos = oldZpos; + item->pos.yRot = oldYrot; + Lara.moveAngle = 0; + + if (LaraFloorFront(item, oldYrot - ANGLE(90.0f), 116) < 0) + return 0; + + switch (angle) + { + case NORTH: + x = ((item->pos.xPos ^ item->pos.zPos) & 0x3FF) ^ item->pos.xPos - SECTOR(1); + z = ((item->pos.xPos ^ item->pos.zPos) & 0x3FF) ^ item->pos.zPos + SECTOR(1); + break; + + case SOUTH: + x = ((item->pos.xPos ^ item->pos.zPos) & 0x3FF) ^ (item->pos.xPos + SECTOR(1)); + z = ((item->pos.xPos ^ item->pos.zPos) & 0x3FF) ^ (item->pos.zPos - SECTOR(1)); + break; + + case WEST: + x = (item->pos.xPos & 0xFFFFFC00) - (item->pos.zPos & 0x3FF); + z = (item->pos.zPos & 0xFFFFFC00) - (item->pos.xPos & 0x3FF); + break; + + default: + x = ((item->pos.xPos + SECTOR(1)) & 0xFFFFFC00) - (item->pos.zPos & 0x3FF) + SECTOR(1); + z = ((item->pos.zPos + SECTOR(1)) & 0xFFFFFC00) - (item->pos.xPos & 0x3FF) + SECTOR(1); + break; + + } + + item->pos.xPos = x; + Lara.cornerX = x; + item->pos.zPos = z; + Lara.cornerZ = z; + item->pos.yRot += ANGLE(90.0f); + + result = IsValidHangPos(item, coll); + if (!result) + { + item->pos.xPos = oldXpos; + item->pos.zPos = oldZpos; + item->pos.yRot = oldYrot; + Lara.moveAngle = 0; + return result; + } + + item->pos.xPos = oldXpos; + item->pos.zPos = oldZpos; + item->pos.yRot = oldYrot; + Lara.moveAngle = 0; + + if (!Lara.climbStatus) + { + if (abs(oldFrontFloor - coll->frontFloor) <= 60) + { + switch (angle) + { + case NORTH: + if ((oldXpos & 0x3FF) > 512) + result = 0; + break; + case EAST: + if ((oldZpos & 0x3FF) < 512) + result = 0; + break; + case SOUTH: + if ((oldXpos & 0x3FF) < 512) + result = 0; + break; + case WEST: + if ((oldZpos & 0x3FF) > 512) + result = 0; + break; + } + return result; + } + return 0; + } + + if (GetClimbTrigger(x, item->pos.yPos, z, item->roomNumber) & LeftClimbTab[angle]) + return result; + + short front = LaraFloorFront(item, item->pos.yRot, 116); + if (abs(front - coll->frontFloor) > 60) + return 0; + + if (front < -768) + return 0; + + return result; +} + +bool TestLaraHangRightCorner(ITEM_INFO* item, COLL_INFO* coll) +{ + if (item->animNumber != LA_REACH_TO_HANG && item->animNumber != LA_HANG_FEET_IDLE || + coll->hitStatic) + { + return false; + } + + return true; +} + +int LaraHangRightCornerTest(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +{ + if (item->animNumber != LA_REACH_TO_HANG && item->animNumber != LA_HANG_FEET_IDLE) + { + return 0; + } + + if (coll->hitStatic) + { + return 0; + } + + int x; + int z; + + int oldXpos = item->pos.xPos; + int oldZpos = item->pos.zPos; + short oldYrot = item->pos.yRot; + int oldFrontFloor = coll->frontFloor; + + short angle = GetQuadrant(item->pos.yRot); + if (angle != NORTH && angle != SOUTH) + { + x = (item->pos.xPos & 0xFFFFFC00) - (item->pos.zPos & 0x3FF) + SECTOR(1); + z = (item->pos.zPos & 0xFFFFFC00) - (item->pos.xPos & 0x3FF) + SECTOR(1); + } + else + { + x = item->pos.xPos ^ (item->pos.xPos ^ item->pos.zPos) & 0x3FF; + z = item->pos.zPos ^ (item->pos.xPos ^ item->pos.zPos) & 0x3FF; + } + + item->pos.xPos = x; + Lara.cornerX = x; + item->pos.zPos = z; + Lara.cornerZ = z; + item->pos.yRot += ANGLE(90.0f); + + int result = -IsValidHangPos(item, coll); + if (result) + { + if (Lara.climbStatus) + { + if (GetClimbTrigger(x, item->pos.yPos, z, item->roomNumber) & LeftClimbTab[angle]) + { + item->pos.xPos = oldXpos; + item->pos.zPos = oldZpos; + item->pos.yRot = oldYrot; + Lara.moveAngle = 0; + return result; + } + } + else + { + if (abs(oldFrontFloor - coll->frontFloor) <= 60) + { + item->pos.xPos = oldXpos; + item->pos.zPos = oldZpos; + item->pos.yRot = oldYrot; + Lara.moveAngle = 0; + return result; + } + } + } + + item->pos.xPos = oldXpos; + item->pos.zPos = oldZpos; + item->pos.yRot = oldYrot; + Lara.moveAngle = 0; + + if (LaraFloorFront(item, oldYrot + ANGLE(90.0f), 116) < 0) + return 0; + + switch (angle) + { + case NORTH: + x = ((item->pos.xPos + SECTOR(1)) & 0xFFFFFC00) - (item->pos.zPos & 0x3FF) + SECTOR(1); + z = ((item->pos.zPos + SECTOR(1)) & 0xFFFFFC00) - (item->pos.xPos & 0x3FF) + SECTOR(1); + break; + + case SOUTH: + x = ((item->pos.xPos - SECTOR(1)) & 0xFFFFFC00) - (item->pos.zPos & 0x3FF) + SECTOR(1); + z = ((item->pos.zPos - SECTOR(1)) & 0xFFFFFC00) - (item->pos.xPos & 0x3FF) + SECTOR(1); + break; + + case WEST: + x = (item->pos.xPos ^ item->pos.zPos) & 0x3FF ^ (item->pos.xPos - SECTOR(1)); + z = (item->pos.xPos ^ item->pos.zPos) & 0x3FF ^ (item->pos.zPos + SECTOR(1)); + break; + + default: + x = ((item->pos.xPos ^ item->pos.zPos) & 0x3FF) ^ (item->pos.xPos + SECTOR(1)); + z = ((item->pos.xPos ^ item->pos.zPos) & 0x3FF) ^ (item->pos.zPos - SECTOR(1)); + break; + + } + + item->pos.xPos = x; + Lara.cornerX = x; + item->pos.zPos = z; + Lara.cornerZ = z; + item->pos.yRot -= ANGLE(90.0f); + + result = IsValidHangPos(item, coll); + if (!result) + { + item->pos.xPos = oldXpos; + item->pos.zPos = oldZpos; + item->pos.yRot = oldYrot; + Lara.moveAngle = 0; + return result; + } + + item->pos.xPos = oldXpos; + item->pos.zPos = oldZpos; + item->pos.yRot = oldYrot; + Lara.moveAngle = 0; + + if (!Lara.climbStatus) + { + if (abs(oldFrontFloor - coll->frontFloor) <= 60) + { + switch (angle) + { + case NORTH: + if ((oldXpos & 0x3FF) < 512) + result = 0; + break; + case EAST: + if ((oldZpos & 0x3FF) > 512) + result = 0; + break; + case SOUTH: + if ((oldXpos & 0x3FF) > 512) + result = 0; + break; + case WEST: + if ((oldZpos & 0x3FF) < 512) + result = 0; + break; + } + return result; + } + return 0; + } + + if (GetClimbTrigger(x, item->pos.yPos, z, item->roomNumber) & RightClimbTab[angle]) + return result; + + short front = LaraFloorFront(item, item->pos.yRot, 116); + if (abs(front - coll->frontFloor) > 60) + return 0; + + if (front < -768) + return 0; + + return result; +} + +int IsValidHangPos(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +{ + if (LaraFloorFront(item, item->pos.yRot + Lara.moveAngle, 100) < 200) + return 0; + + short angle = GetQuadrant(item->pos.yRot); + switch (angle) + { + case NORTH: + item->pos.zPos += 4; + break; + case EAST: + item->pos.xPos += 4; + break; + case SOUTH: + item->pos.zPos -= 4; + break; + case WEST: + item->pos.xPos -= 4; + break; + default: + break; + } + + coll->badPos = NO_BAD_POS; + coll->badNeg = -512; + coll->badCeiling = 0; + + Lara.moveAngle = 0; + + coll->facing = Lara.moveAngle; + GetCollisionInfo(coll, item->pos.xPos, item->pos.yPos, item->pos.zPos, item->roomNumber, LARA_HITE); + + if (coll->midCeiling >= 0 || coll->collType != CT_FRONT || coll->hitStatic) + return 0; + + return abs(coll->frontFloor - coll->rightFloor2) < 60; +} + +int LaraTestClimbStance(ITEM_INFO* item, COLL_INFO* coll)//11F78, 12028 +{ + int shift_r, shift_l; + + if (LaraTestClimbPos(item, coll->radius, coll->radius + 120, -700, 512, &shift_r) != 1) + return false; + + if (LaraTestClimbPos(item, coll->radius, -(coll->radius + 120), -700, 512, &shift_l) != 1) + return false; + + if (shift_r) + { + if (shift_l) + { + if (shift_r < 0 != shift_l < 0) + return false; + + if ((shift_r < 0 && shift_l < shift_r) || + (shift_r > 0 && shift_l > shift_r)) + { + item->pos.yPos += shift_l; + return true; + } + } + + item->pos.yPos += shift_r; + } + else if (shift_l) + { + item->pos.yPos += shift_l; + } + + return true; +} + +int LaraTestHangOnClimbWall(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +{ + BOUNDING_BOX* bounds; + int shift, result; + + if (Lara.climbStatus == 0) + return 0; + + if (item->fallspeed < 0) + return 0; + + switch (GetQuadrant(item->pos.yRot)) + { + case NORTH: + case SOUTH: + item->pos.zPos += coll->shift.z; + break; + + case EAST: + case WEST: + item->pos.xPos += coll->shift.x; + break; + + default: + break; + } + + bounds = GetBoundsAccurate(item); + + if (Lara.moveAngle) + { + short l = LaraCeilingFront(item, item->pos.yRot, 0, 0); + short r = LaraCeilingFront(item, item->pos.yRot + Lara.moveAngle, 128, 0); + + if (abs(l - r) > 60) + return 0; + } + + if (LaraTestClimbPos(item, coll->radius, coll->radius, bounds->Y1, bounds->Y2 - bounds->Y1, &shift) && + LaraTestClimbPos(item, coll->radius, -coll->radius, bounds->Y1, bounds->Y2 - bounds->Y1, &shift)) + { + result = LaraTestClimbPos(item, coll->radius, 0, bounds->Y1, bounds->Y2 - bounds->Y1, &shift); + if (result) + { + if (result != 1) + item->pos.yPos += shift; + return 1; + } + } + + return 0; +} + +int LaraTestEdgeCatch(ITEM_INFO* item, COLL_INFO* coll, int* edge) // (F) (D) +{ + BOUNDING_BOX* bounds = GetBoundsAccurate(item); + int hdif = coll->frontFloor - bounds->Y1; + + if (hdif < 0 == hdif + item->fallspeed < 0) + { + hdif = item->pos.yPos + bounds->Y1; + + if ((hdif + item->fallspeed & 0xFFFFFF00) != (hdif & 0xFFFFFF00)) + { + if (item->fallspeed > 0) + *edge = (hdif + item->fallspeed) & 0xFFFFFF00; + else + *edge = hdif & 0xFFFFFF00; + + return -1; + } + + return 0; + } + + if (abs(coll->leftFloor2 - coll->rightFloor2) >= SLOPE_DIF) + return 0; + + return 1; +} + +int TestHangSwingIn(ITEM_INFO* item, short angle)//14104, 141B4 (F) +{ + int x = item->pos.xPos; + int y = item->pos.yPos; + int z = item->pos.zPos; + short roomNum = item->roomNumber; + FLOOR_INFO* floor; + int h, c; + + //debug till scripting be ready +// TR12_OSCILLATE_HANG = true; + + /*if (angle == ANGLE(180.0f)) + { + z -= 256; + } + else if (angle == -ANGLE(90)) + { + x -= 256; + } + else if (angle == ANGLE(90)) + { + x += 256; + } + else if (angle == ANGLE(0)) + { + z += 256; + }*/ + + z += (phd_cos(angle) * STEP_SIZE) >> W2V_SHIFT; + x += (phd_sin(angle) * STEP_SIZE) >> W2V_SHIFT; + + floor = GetFloor(x, y, z, &roomNum); + h = GetFloorHeight(floor, x, y, z); + c = GetCeiling(floor, x, y, z); + + if (h != NO_HEIGHT) + { + /* if (TR12_OSCILLATE_HANG == true) + { + if (((h - y) > 0) + && ((c - y) < -400)) + return(1); + } + else + {*/ + if (((h - y) > 0) + && ((c - y) < -400) + && ((y - 819 - c) > -72)) + return(1); + // } + } + return(0); +} + +int TestHangFeet(ITEM_INFO* item, short angle) +{ + return 0; + if (Lara.climbStatus) + return 0; + + // EnableFeetHang = true; + + +// if (!EnableFeetHang) +// return 0; + + int x = item->pos.xPos; + int y = item->pos.yPos; + int z = item->pos.zPos; + short roomNum = item->roomNumber; + FLOOR_INFO* floor; + int h, c, g, m, j; + + if (angle == ANGLE(180.0f)) + { + z -= 256; + } + else if (angle == -ANGLE(90.0f)) + { + x -= 256; + } + else if (angle == ANGLE(90.0f)) + { + x += 256; + } + else if (angle == ANGLE(0.0f)) + { + z += 256; + } + + floor = GetFloor(x, y, z, &roomNum); + h = GetFloorHeight(floor, x, y, z); + c = GetCeiling(floor, x, y, z); + g = h - y; + m = c - y; + j = y - 128 - c; + + if (item->currentAnimState == LS_CRAWL_TO_HANG) + { + if (h != NO_HEIGHT) + { + if (((g) > 0) + && ((m) < -128) + && ((j) > -72)) + return(1); + } + return(0); + } + else + { + if (h != NO_HEIGHT) + { + if (((g) > 0) + && ((m) < -128) + && ((j) > -72)) + return(0); + } + return(1); + } +} + +int CanLaraHangSideways(ITEM_INFO* item, COLL_INFO* coll, short angle)//19930, 19A64 (F) +{ + int oldx = item->pos.xPos; + int oldz = item->pos.zPos; + int x = item->pos.xPos; + int z = item->pos.zPos; + int res; + + Lara.moveAngle = angle; + + switch (GetQuadrant(item->pos.yRot + Lara.moveAngle)) + { + case 0: + z += 16; + break; + case 1: + x += 16; + break; + case 2: + z -= 16; + break; + case 3: + x -= 16; + break; + } + + item->pos.xPos = x; + item->pos.zPos = z; + + coll->old.y = item->pos.yPos; + + res = LaraHangTest(item, coll); + + item->pos.xPos = oldx; + item->pos.zPos = oldz; + + Lara.moveAngle = angle; + + return !res; +} + +void SetCornerAnim(ITEM_INFO* item, COLL_INFO* coll, short rot, short flip)//1A090, 1A1C4 (F) +{ + if (item->hitPoints <= 0) + { + item->goalAnimState = LS_JUMP_FORWARD; + item->currentAnimState = LS_JUMP_FORWARD; + item->animNumber = LA_FALL_START; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + + item->gravityStatus = true; + item->speed = 2; + item->pos.yPos += 256; + item->fallspeed = 1; + + Lara.gunStatus = LG_NO_ARMS; + + item->pos.yRot += rot / 2; + } + else if (flip) + { + if (Lara.isClimbing) + { + item->animNumber = LA_LADDER_IDLE; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->goalAnimState = LS_LADDER_IDLE; + item->currentAnimState = LS_LADDER_IDLE; + } + else + { + item->animNumber = LA_REACH_TO_HANG; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase + 21; + item->goalAnimState = LS_HANG; + item->currentAnimState = LS_HANG; + } + + coll->old.x = Lara.cornerX; + item->pos.xPos = Lara.cornerX; + + coll->old.z = Lara.cornerZ; + item->pos.zPos = Lara.cornerZ; + + item->pos.yRot += rot; + } +} + +void SetCornerAnimFeet(ITEM_INFO* item, COLL_INFO* coll, short rot, short flip) +{ + if (item->hitPoints <= 0) + { + item->goalAnimState = LS_JUMP_FORWARD; + item->currentAnimState = LS_JUMP_FORWARD; + item->animNumber = LA_FALL_START; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + + item->gravityStatus = true; + item->speed = 2; + item->pos.yPos += 256; + item->fallspeed = 1; + + Lara.gunStatus = LG_NO_ARMS; + + item->pos.yRot += rot / 2; + } + else if (flip) + { + + item->animNumber = LA_HANG_FEET_IDLE; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->goalAnimState = LS_HANG_FEET; + item->currentAnimState = LS_HANG_FEET; + + coll->old.x = Lara.cornerX; + item->pos.xPos = Lara.cornerX; + + coll->old.z = Lara.cornerZ; + item->pos.zPos = Lara.cornerZ; + + item->pos.yRot += rot; + } +} + +short LaraFloorFront(ITEM_INFO* item, short ang, int dist) // (F) (D) +{ + short room = item->roomNumber; + + int x = item->pos.xPos + ((dist * phd_sin(ang)) >> W2V_SHIFT); + int y = item->pos.yPos - 762; + int z = item->pos.zPos + ((dist * phd_cos(ang)) >> W2V_SHIFT); + + int height = GetFloorHeight(GetFloor(x, y, z, &room), x, y, z); + + if (height != NO_HEIGHT) + height -= item->pos.yPos; + + return height; +} + +short LaraCeilingFront(ITEM_INFO* item, short ang, int dist, int h) // (F) (D) +{ + short room = item->roomNumber; + + int x = item->pos.xPos + ((dist * phd_sin(ang)) >> W2V_SHIFT); + int y = item->pos.yPos - h; + int z = item->pos.zPos + ((dist * phd_cos(ang)) >> W2V_SHIFT); + + int height = GetCeiling(GetFloor(x, y, z, &room), x, y, z); + + if (height != NO_HEIGHT) + height += h - item->pos.yPos; + + return height; +} + +bool TestLaraFall(COLL_INFO* coll) +{ + if (coll->midFloor <= STEPUP_HEIGHT/* || + Lara.waterStatus == LW_WADE*/) // TEST: This may have been causing a floor snap bug! + { + return false; + } + + return true; +} + +// TODO: This should eventually become obsolete. Set goal states to LS_FALL. In WAD2, make links to LA_FALL_START. +void SetLaraFall(ITEM_INFO* item) +{ + item->animNumber = LA_FALL_START; + item->currentAnimState = LS_JUMP_FORWARD; + item->goalAnimState = LS_JUMP_FORWARD; + item->frameNumber = g_Level.Anims[item->animNumber].frameBase; + item->fallspeed = 0; + item->gravityStatus = true; +} + +int LaraLandedBad(ITEM_INFO* item, COLL_INFO* coll) // (F) (D) +{ + int landspeed = item->fallspeed - 140; + + if (landspeed > 0) + { + if (landspeed <= 14) + { + item->hitPoints -= 1000 * SQUARE(landspeed) / 196; + return item->hitPoints <= 0; + } + else + { + item->hitPoints = -1; + return 1; + } + } + + return 0; +} + +void GetTighropeFallOff(int regularity) +{ + if (LaraItem->hitPoints <= 0 || LaraItem->hitStatus) + { + LaraItem->goalAnimState = LS_TIGHTROPE_UNBALANCE_LEFT; + LaraItem->currentAnimState = LS_TIGHTROPE_UNBALANCE_LEFT; + LaraItem->animNumber = LA_TIGHTROPE_FALL_LEFT; + LaraItem->frameNumber = g_Level.Anims[LaraItem->animNumber].frameBase; + } + + if (!Lara.tightRopeFall && !(GetRandomControl() & regularity)) + { + Lara.tightRopeFall = 2 - ((GetRandomControl() & 0xF) != 0); + } +} + +bool TestLaraLean(COLL_INFO* coll) +{ + // TODO: fine-tune this when new collision is done. + switch (coll->collType) + { + case CT_RIGHT: + { + if (TrInput & IN_RIGHT) + { + return false; + } + } + + case CT_LEFT: + { + if (TrInput & IN_LEFT) + { + return false; + } + } + } + return true; } diff --git a/TR5Main/Game/Lara/lara_tests.h b/TR5Main/Game/Lara/lara_tests.h index 85e28dcaf..d7265f4f8 100644 --- a/TR5Main/Game/Lara/lara_tests.h +++ b/TR5Main/Game/Lara/lara_tests.h @@ -17,7 +17,10 @@ void SetCornerAnim(ITEM_INFO* item, COLL_INFO* coll, short rot, short flip); void SetCornerAnimFeet(ITEM_INFO* item, COLL_INFO* coll, short rot, short flip); short LaraFloorFront(ITEM_INFO* item, short ang, int dist); short LaraCeilingFront(ITEM_INFO* item, short ang, int dist, int h); -int LaraFallen(ITEM_INFO* item, COLL_INFO* coll); int LaraLandedBad(ITEM_INFO* l, COLL_INFO* coll); -void GetTighRopeFallOff(int Regularity); -bool TestLaraLean(ITEM_INFO* item, COLL_INFO* coll); +void GetTighropeFallOff(int Regularity); + +bool TestLaraFall(COLL_INFO* coll); +void SetLaraFall(ITEM_INFO* item); + +bool TestLaraLean(COLL_INFO* coll); diff --git a/TR5Main/Game/Lara/lara_two_guns.cpp b/TR5Main/Game/Lara/lara_two_guns.cpp index 290cfdca9..fbdf5380d 100644 --- a/TR5Main/Game/Lara/lara_two_guns.cpp +++ b/TR5Main/Game/Lara/lara_two_guns.cpp @@ -11,6 +11,7 @@ #include "input.h" #include "sound.h" #include "savegame.h" + struct PISTOL_DEF { short objectNum; @@ -19,6 +20,7 @@ struct PISTOL_DEF char draw2Anim; char recoilAnim; }; + PISTOL_DEF PistolsTable[4] = { { ID_LARA, 0, 0, 0, 0 }, diff --git a/TR5Main/Game/control.cpp b/TR5Main/Game/control.cpp index 3c51681d0..fe902cf37 100644 --- a/TR5Main/Game/control.cpp +++ b/TR5Main/Game/control.cpp @@ -2924,7 +2924,7 @@ void AnimateItem(ITEM_INFO *item) if (item->gravityStatus) { - item->fallspeed += (item->fallspeed >= 128 ? 1 : 6); + item->fallspeed += (item->fallspeed >= 128 ? 1 : 6) / 2; item->pos.yPos += item->fallspeed; } else diff --git a/TR5Main/Game/pickup.cpp b/TR5Main/Game/pickup.cpp index 95e25636f..474139321 100644 --- a/TR5Main/Game/pickup.cpp +++ b/TR5Main/Game/pickup.cpp @@ -94,19 +94,29 @@ extern Inventory g_Inventory; static bool SilencerIsEquiped() { - return Lara.Weapons[WEAPON_UZI].HasSilencer - || Lara.Weapons[WEAPON_PISTOLS].HasSilencer - || Lara.Weapons[WEAPON_SHOTGUN].HasSilencer - || Lara.Weapons[WEAPON_REVOLVER].HasSilencer - || Lara.Weapons[WEAPON_CROSSBOW].HasSilencer - || Lara.Weapons[WEAPON_HK].HasSilencer; + if (Lara.Weapons[WEAPON_UZI].HasSilencer || + Lara.Weapons[WEAPON_PISTOLS].HasSilencer || + Lara.Weapons[WEAPON_SHOTGUN].HasSilencer || + Lara.Weapons[WEAPON_REVOLVER].HasSilencer || + Lara.Weapons[WEAPON_CROSSBOW].HasSilencer || + Lara.Weapons[WEAPON_HK].HasSilencer) + { + return true; + } + + return false; } static bool LaserSightIsEquiped() { - return Lara.Weapons[WEAPON_REVOLVER].HasLasersight - || Lara.Weapons[WEAPON_CROSSBOW].HasLasersight - || Lara.Weapons[WEAPON_HK].HasLasersight; + if (Lara.Weapons[WEAPON_REVOLVER].HasLasersight || + Lara.Weapons[WEAPON_CROSSBOW].HasLasersight || + Lara.Weapons[WEAPON_HK].HasLasersight) + { + return true; + } + + return false; } void PickedUpObject(short objectNumber) @@ -502,7 +512,9 @@ void do_pickup() for (int i = 0; i < g_Level.NumItems; i++) { if (g_Level.Items[i].objectNumber == item->objectNumber) - KillItem(i); + { + KillItem(i); + } } } if (item->triggerFlags & 0xC0) @@ -533,10 +545,14 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) short triggerFlags = item->triggerFlags & 0x3F; if (triggerFlags == 5 || triggerFlags == 10) + { return; + } if (item->objectNumber == ID_FLARE_ITEM && Lara.gunType == WEAPON_FLARE) + { return; + } item->pos.yRot = l->pos.yRot; item->pos.zRot = 0; @@ -835,7 +851,10 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) if (l->currentAnimState == LS_CROUCH_IDLE) { if (item->objectNumber == ID_BURNING_TORCH_ITEM) - break; + { + break; + } + AlignLaraPosition(&PickUpPosition, item, l); if (item->objectNumber == ID_FLARE_ITEM) { @@ -852,7 +871,10 @@ void PickupCollision(short itemNum, ITEM_INFO* l, COLL_INFO* coll) if (l->currentAnimState == LS_CRAWL_IDLE) { if (item->objectNumber == ID_BURNING_TORCH_ITEM) - break; + { + break; + } + l->goalAnimState = LS_CROUCH_IDLE; Lara.generalPtr = (void*)itemNum; break; @@ -955,13 +977,20 @@ void PickupControl(short itemNum) { item->pos.yPos = item->itemFlags[0]; if (item->fallspeed <= 64) + { item->triggerFlags &= 0xC0; + } else + { item->fallspeed = -item->fallspeed >> 2; + } } if (item->roomNumber != roomNumber) + { ItemNewRoom(itemNum, roomNumber); + } + break; case 2: @@ -1007,10 +1036,14 @@ BOUNDING_BOX* FindPlinth(ITEM_INFO* item) } if (found != -1) + { return &StaticObjects[found].collisionBox; + } if (room->itemNumber == NO_ITEM) + { return NULL; + } short itemNumber = room->itemNumber; for (itemNumber = room->itemNumber; itemNumber != NO_ITEM; itemNumber = g_Level.Items[itemNumber].nextItem) @@ -1029,9 +1062,13 @@ BOUNDING_BOX* FindPlinth(ITEM_INFO* item) } if (itemNumber == NO_ITEM) + { return NULL; + } else + { return (BOUNDING_BOX*)GetBestFrame(&g_Level.Items[itemNumber]); + } } void InitialisePickup(short itemNumber) @@ -1047,7 +1084,9 @@ void InitialisePickup(short itemNumber) else { if (triggerFlags == 0 || triggerFlags == 3 || triggerFlags == 4 || triggerFlags == 7 || triggerFlags == 8 || triggerFlags == 11) + { item->pos.yPos -= bounds->Y2; + } if ((item->triggerFlags & 0x80) != 0) { @@ -1056,10 +1095,14 @@ void InitialisePickup(short itemNumber) } if (item->triggerFlags & 0x100) + { item->meshBits = 0; + } if (item->status == ITEM_INVISIBLE) + { item->flags |= 0x20; + } } } @@ -1198,7 +1241,9 @@ void SearchObjectControl(short itemNumber) objNumber = (item->objectNumber - ID_SEARCH_OBJECT1) / 2; if (item->objectNumber != ID_SEARCH_OBJECT4 || item->itemFlags[0] == 1) + { AnimateItem(item); + } frameNumber = item->frameNumber - g_Level.Anims[item->animNumber].frameBase; if (item->objectNumber == ID_SEARCH_OBJECT1) @@ -1217,16 +1262,22 @@ void SearchObjectControl(short itemNumber) else if (item->objectNumber == ID_SEARCH_OBJECT2) { if (frameNumber == 18) + { item->meshBits = 1; + } else if (frameNumber == 172) + { item->meshBits = 2; + } } else if (item->objectNumber == ID_SEARCH_OBJECT4) { item->meshBits = FlipStats[0] != 0 ? 48 : 9; if (frameNumber >= 45 && frameNumber <= 131) + { item->meshBits |= FlipStats[0] != 0 ? 4 : 2; + } if (item->itemFlags[1] != -1) { @@ -1234,9 +1285,13 @@ void SearchObjectControl(short itemNumber) if (Objects[item2->objectNumber].isPickup) { if (FlipStats[0]) + { item2->status = ITEM_NOT_ACTIVE; + } else + { item2->status = ITEM_INVISIBLE; + } } } } @@ -1287,11 +1342,12 @@ void SearchObjectControl(short itemNumber) int UseSpecialItem(ITEM_INFO* item) // to pickup.cpp? { - short selectedObject = g_Inventory.GetSelectedObject(); if (item->animNumber != LA_STAND_IDLE || Lara.gunStatus || selectedObject == NO_ITEM) - return false; + { + return false; + } if (selectedObject >= ID_WATERSKIN1_EMPTY && selectedObject <= ID_WATERSKIN2_5) { @@ -1300,9 +1356,13 @@ int UseSpecialItem(ITEM_INFO* item) // to pickup.cpp? if (selectedObject != ID_WATERSKIN1_3 && selectedObject != ID_WATERSKIN2_5) { if (selectedObject >= ID_WATERSKIN2_EMPTY) - Lara.Waterskin2.Quantity = 5; + { + Lara.Waterskin2.Quantity = 5; + } else - Lara.Waterskin1.Quantity = 3; + { + Lara.Waterskin1.Quantity = 3; + } item->animNumber = LA_WATERSKIN_FILL; } diff --git a/TR5Main/Game/trmath.cpp b/TR5Main/Game/trmath.cpp index bce83b13d..5de3f83d7 100644 --- a/TR5Main/Game/trmath.cpp +++ b/TR5Main/Game/trmath.cpp @@ -1306,6 +1306,11 @@ unsigned short atanTab[] = { 0x2000, 0x2000 }; +int GetSign(int num) +{ + return (num >= 0) ? 1 : -1; +} + // fix "improperly terminated macro invocation" // fix "expression must have integral or unscoped enum type" short ANGLE(float angle) diff --git a/TR5Main/Game/trmath.h b/TR5Main/Game/trmath.h index 40af9f5ad..97129618c 100644 --- a/TR5Main/Game/trmath.h +++ b/TR5Main/Game/trmath.h @@ -45,6 +45,9 @@ template constexpr auto MESH_BITS(T x) { return (1 << x); } + +int GetSign(int num); + short ANGLE(float angle); float TO_DEGREES(short angle); float TO_RAD(short angle); diff --git a/TR5Main/Renderer/Renderer11Lara.cpp b/TR5Main/Renderer/Renderer11Lara.cpp index b8a6fdb84..999cc50e2 100644 --- a/TR5Main/Renderer/Renderer11Lara.cpp +++ b/TR5Main/Renderer/Renderer11Lara.cpp @@ -24,7 +24,7 @@ bool shouldAnimateUpperBody(const LARA_WEAPON_TYPE& weapon) { case WEAPON_GRENADE_LAUNCHER: case WEAPON_CROSSBOW: case WEAPON_SHOTGUN: - return (LaraItem->currentAnimState == LS_STOP || LaraItem->currentAnimState == LS_TURN_FAST || LaraItem->currentAnimState == LS_TURN_LEFT_SLOW || LaraItem->currentAnimState == LS_TURN_RIGHT_SLOW); + return (LaraItem->currentAnimState == LS_STOP || LaraItem->currentAnimState == LS_TURN_LEFT_FAST || LaraItem->currentAnimState == LS_TURN_RIGHT_FAST || LaraItem->currentAnimState == LS_TURN_LEFT_SLOW || LaraItem->currentAnimState == LS_TURN_RIGHT_SLOW); break; case WEAPON_HK: { @@ -33,7 +33,7 @@ bool shouldAnimateUpperBody(const LARA_WEAPON_TYPE& weapon) { if(laraInfo.rightArm.animNumber - baseAnim == 0 || laraInfo.rightArm.animNumber - baseAnim == 2 || laraInfo.rightArm.animNumber - baseAnim == 4){ return true; } else - return (LaraItem->currentAnimState == LS_STOP || LaraItem->currentAnimState == LS_TURN_FAST || LaraItem->currentAnimState == LS_TURN_LEFT_SLOW || LaraItem->currentAnimState == LS_TURN_RIGHT_SLOW); + return (LaraItem->currentAnimState == LS_STOP || LaraItem->currentAnimState == LS_TURN_LEFT_FAST || LaraItem->currentAnimState == LS_TURN_RIGHT_FAST || LaraItem->currentAnimState == LS_TURN_LEFT_SLOW || LaraItem->currentAnimState == LS_TURN_RIGHT_SLOW); } break; default: