Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 1 | pmbaty | 1 | /* |
| 2 | SDLPoP, a port/conversion of the DOS game Prince of Persia. |
||
| 3 | Copyright (C) 2013-2018 Dávid Nagy |
||
| 4 | |||
| 5 | This program is free software: you can redistribute it and/or modify |
||
| 6 | it under the terms of the GNU General Public License as published by |
||
| 7 | the Free Software Foundation, either version 3 of the License, or |
||
| 8 | (at your option) any later version. |
||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, |
||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
| 13 | GNU General Public License for more details. |
||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License |
||
| 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
| 17 | |||
| 18 | The authors of this program may be contacted at http://forum.princed.org |
||
| 19 | */ |
||
| 20 | |||
| 21 | #include "common.h" |
||
| 22 | |||
| 23 | // data:0E32 |
||
| 24 | const word strikeprob [] = { 61,100, 61, 61, 61, 40,100,220, 0, 48, 32, 48}; |
||
| 25 | // data:0E4A |
||
| 26 | const word restrikeprob[] = { 0, 0, 0, 5, 5,175, 16, 8, 0,255,255,150}; |
||
| 27 | // data:0E62 |
||
| 28 | const word blockprob [] = { 0,150,150,200,200,255,200,250, 0,255,255,255}; |
||
| 29 | // data:0E7A |
||
| 30 | const word impblockprob[] = { 0, 61, 61,100,100,145,100,250, 0,145,255,175}; |
||
| 31 | // data:0E92 |
||
| 32 | const word advprob [] = {255,200,200,200,255,255,200, 0, 0,255,100,100}; |
||
| 33 | // data:0EAA |
||
| 34 | const word refractimer [] = { 16, 16, 16, 16, 8, 8, 8, 8, 0, 8, 0, 0}; |
||
| 35 | // data:0EC2 |
||
| 36 | const word extrastrength[] = {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}; |
||
| 37 | |||
| 38 | // seg002:0000 |
||
| 39 | void __pascal far do_init_shad(const byte *source,int seq_index) { |
||
| 40 | memcpy_near(&Char, source, 7); |
||
| 41 | seqtbl_offset_char(seq_index); |
||
| 42 | Char.charid = charid_1_shadow; |
||
| 43 | demo_time = 0; |
||
| 44 | guard_skill = 3; |
||
| 45 | guardhp_delta = guardhp_curr = guardhp_max = 4; |
||
| 46 | saveshad(); |
||
| 47 | } |
||
| 48 | |||
| 49 | // seg002:0044 |
||
| 50 | void __pascal far get_guard_hp() { |
||
| 51 | guardhp_delta = guardhp_curr = guardhp_max = extrastrength[guard_skill] + tbl_guard_hp[current_level]; |
||
| 52 | } |
||
| 53 | |||
| 54 | // data:0EEA |
||
| 55 | const byte init_shad_6[] = {0x0F, 0x51, 0x76, 0, 0, 1, 0, 0}; |
||
| 56 | // data:0EF2 |
||
| 57 | const byte init_shad_5[] = {0x0F, 0x37, 0x37, 0, 0xFF, 0, 0, 0}; |
||
| 58 | // data:0EFA |
||
| 59 | const byte init_shad_12[] = {0x0F, 0x51, 0xE8, 0, 0, 0, 0, 0}; |
||
| 60 | |||
| 61 | // seg002:0064 |
||
| 62 | void __pascal far check_shadow() { |
||
| 63 | offguard = 0; |
||
| 64 | if (current_level == 12) { |
||
| 65 | // Special event: level 12 shadow |
||
| 66 | if (!united_with_shadow && drawn_room == 15) { |
||
| 67 | Char.room = drawn_room; |
||
| 68 | if (get_tile(15, 1, 0) == tiles_22_sword) { |
||
| 69 | return; |
||
| 70 | } |
||
| 71 | shadow_initialized = 0; |
||
| 72 | do_init_shad(/*&*/init_shad_12, 7 /*fall*/); |
||
| 73 | return; |
||
| 74 | } |
||
| 75 | } else if (current_level == 6) { |
||
| 76 | // Special event: level 6 shadow |
||
| 77 | Char.room = drawn_room; |
||
| 78 | if (Char.room == 1) { |
||
| 79 | if (leveldoor_open != 0x4D) { |
||
| 80 | play_sound(sound_25_presentation); // presentation (level 6 shadow) |
||
| 81 | leveldoor_open = 0x4D; |
||
| 82 | } |
||
| 83 | do_init_shad(/*&*/init_shad_6, 2 /*stand*/); |
||
| 84 | return; |
||
| 85 | } |
||
| 86 | } else if (current_level == 5) { |
||
| 87 | // Special event: level 5 shadow |
||
| 88 | Char.room = drawn_room; |
||
| 89 | if (Char.room == 24) { |
||
| 90 | if (get_tile(24, 3, 0) != tiles_10_potion) { |
||
| 91 | return; |
||
| 92 | } |
||
| 93 | do_init_shad(/*&*/init_shad_5, 2 /*stand*/); |
||
| 94 | return; |
||
| 95 | } |
||
| 96 | } |
||
| 97 | enter_guard(); |
||
| 98 | } |
||
| 99 | |||
| 100 | // seg002:0112 |
||
| 101 | void __pascal far enter_guard() { |
||
| 102 | word room_minus_1; |
||
| 103 | word guard_tile; |
||
| 104 | word frame; |
||
| 105 | byte seq_hi; |
||
| 106 | // arrays are indexed 0..23 instead of 1..24 |
||
| 107 | room_minus_1 = drawn_room - 1; |
||
| 108 | frame = Char.frame; // hm? |
||
| 109 | guard_tile = level.guards_tile[room_minus_1]; |
||
| 110 | |||
| 111 | #ifndef FIX_OFFSCREEN_GUARDS_DISAPPEARING |
||
| 112 | if (guard_tile >= 30) return; |
||
| 113 | #else |
||
| 114 | if (guard_tile >= 30) { |
||
| 115 | if (!fix_offscreen_guards_disappearing) return; |
||
| 116 | |||
| 117 | // try to see if there are offscreen guards in the left and right rooms that might be visible from this room |
||
| 118 | word left_guard_tile = 31; |
||
| 119 | word right_guard_tile = 31; |
||
| 120 | if (room_L > 0) left_guard_tile = level.guards_tile[room_L-1]; |
||
| 121 | if (room_R > 0) right_guard_tile = level.guards_tile[room_R-1]; |
||
| 122 | |||
| 123 | int other_guard_x; |
||
| 124 | sbyte other_guard_dir; |
||
| 125 | int delta_x; |
||
| 126 | int other_room_minus_1; |
||
| 127 | if (right_guard_tile >= 0 && right_guard_tile < 30) { |
||
| 128 | other_room_minus_1 = room_R - 1; |
||
| 129 | other_guard_x = level.guards_x[other_room_minus_1]; |
||
| 130 | other_guard_dir = level.guards_dir[other_room_minus_1]; |
||
| 131 | // left edge of the guard matters |
||
| 132 | if (other_guard_dir == dir_0_right) other_guard_x -= 9; // only retrieve a guard if they will be visible |
||
| 133 | if (other_guard_dir == dir_FF_left) other_guard_x += 1; // getting these right was mostly trial and error |
||
| 134 | // only retrieve offscreen guards |
||
| 135 | if (!(other_guard_x < 58 + 4)) return; |
||
| 136 | delta_x = 140; // guard leaves to the left |
||
| 137 | guard_tile = right_guard_tile; |
||
| 138 | } |
||
| 139 | else if (left_guard_tile >= 0 && left_guard_tile < 30) { |
||
| 140 | other_room_minus_1 = room_L - 1; |
||
| 141 | other_guard_x = level.guards_x[other_room_minus_1]; |
||
| 142 | other_guard_dir = level.guards_dir[other_room_minus_1]; |
||
| 143 | // right edge of the guard matters |
||
| 144 | if (other_guard_dir == dir_0_right) other_guard_x -= 9; |
||
| 145 | if (other_guard_dir == dir_FF_left) other_guard_x += 1; |
||
| 146 | // only retrieve offscreen guards |
||
| 147 | if (!(other_guard_x > 190 - 4)) return; |
||
| 148 | delta_x = -140; // guard leaves to the right |
||
| 149 | guard_tile = left_guard_tile; |
||
| 150 | } |
||
| 151 | else return; |
||
| 152 | |||
| 153 | // retrieve guard from adjacent room |
||
| 154 | level.guards_x[room_minus_1] = level.guards_x[other_room_minus_1] + delta_x; |
||
| 155 | level.guards_color[room_minus_1] = level.guards_color[other_room_minus_1]; |
||
| 156 | level.guards_dir[room_minus_1] = level.guards_dir[other_room_minus_1]; |
||
| 157 | level.guards_seq_hi[room_minus_1] = level.guards_seq_hi[other_room_minus_1]; |
||
| 158 | level.guards_seq_lo[room_minus_1] = level.guards_seq_lo[other_room_minus_1]; |
||
| 159 | level.guards_skill[room_minus_1] = level.guards_skill[other_room_minus_1]; |
||
| 160 | |||
| 161 | level.guards_tile[other_room_minus_1] = 0xFF; |
||
| 162 | level.guards_seq_hi[other_room_minus_1] = 0; |
||
| 163 | } |
||
| 164 | #endif |
||
| 165 | |||
| 166 | Char.room = drawn_room; |
||
| 167 | Char.curr_row = guard_tile / 10; |
||
| 168 | Char.y = y_land[Char.curr_row + 1]; |
||
| 169 | Char.x = level.guards_x[room_minus_1]; |
||
| 170 | Char.curr_col = get_tile_div_mod_m7(Char.x); |
||
| 171 | Char.direction = level.guards_dir[room_minus_1]; |
||
| 172 | // only regular guards have different colors (and only on VGA) |
||
| 173 | if (graphics_mode == gmMcgaVga && tbl_guard_type[current_level] == 0) { |
||
| 174 | curr_guard_color = level.guards_color[room_minus_1]; |
||
| 175 | } else { |
||
| 176 | curr_guard_color = 0; |
||
| 177 | } |
||
| 178 | |||
| 179 | #ifdef REMEMBER_GUARD_HP |
||
| 180 | int remembered_hp = (curr_guard_color & 0xF0) >> 4; |
||
| 181 | #endif |
||
| 182 | curr_guard_color &= 0x0F; // added; only least significant 4 bits are used for guard color |
||
| 183 | |||
| 184 | // level 3 has skeletons with infinite lives |
||
| 185 | if (current_level == 3) { |
||
| 186 | Char.charid = charid_4_skeleton; |
||
| 187 | } else { |
||
| 188 | Char.charid = charid_2_guard; |
||
| 189 | } |
||
| 190 | seq_hi = level.guards_seq_hi[room_minus_1]; |
||
| 191 | if (seq_hi == 0) { |
||
| 192 | if (Char.charid == charid_4_skeleton) { |
||
| 193 | Char.sword = sword_2_drawn; |
||
| 194 | seqtbl_offset_char(seq_63_guard_stand_active); // stand active (when entering room) (skeleton) |
||
| 195 | } else { |
||
| 196 | Char.sword = sword_0_sheathed; |
||
| 197 | seqtbl_offset_char(seq_77_guard_stand_inactive); // stand inactive (when entering room) |
||
| 198 | } |
||
| 199 | } else { |
||
| 200 | Char.curr_seq = level.guards_seq_lo[room_minus_1] + (seq_hi << 8); |
||
| 201 | } |
||
| 202 | play_seq(); |
||
| 203 | guard_skill = level.guards_skill[room_minus_1]; |
||
| 204 | if (guard_skill >= 12) { |
||
| 205 | guard_skill = 3; |
||
| 206 | } |
||
| 207 | frame = Char.frame; |
||
| 208 | if (frame == frame_185_dead || frame == frame_177_spiked || frame == frame_178_chomped) { |
||
| 209 | Char.alive = 1; |
||
| 210 | draw_guard_hp(0, guardhp_curr); |
||
| 211 | guardhp_curr = 0; |
||
| 212 | } else { |
||
| 213 | Char.alive = -1; |
||
| 214 | justblocked = 0; |
||
| 215 | guard_refrac = 0; |
||
| 216 | is_guard_notice = 0; |
||
| 217 | get_guard_hp(); |
||
| 218 | #ifdef REMEMBER_GUARD_HP |
||
| 219 | if (enable_remember_guard_hp && remembered_hp > 0) |
||
| 220 | guardhp_delta = guardhp_curr = (word) remembered_hp; |
||
| 221 | #endif |
||
| 222 | } |
||
| 223 | Char.fall_y = 0; |
||
| 224 | Char.fall_x = 0; |
||
| 225 | Char.action = actions_1_run_jump; |
||
| 226 | saveshad(); |
||
| 227 | } |
||
| 228 | |||
| 229 | // seg002:0269 |
||
| 230 | void __pascal far check_guard_fallout() { |
||
| 231 | if (Guard.direction == dir_56_none || Guard.y < 211) { |
||
| 232 | return; |
||
| 233 | } |
||
| 234 | if (Guard.charid == charid_1_shadow) { |
||
| 235 | if (Guard.action != actions_4_in_freefall) { |
||
| 236 | return; |
||
| 237 | } |
||
| 238 | loadshad(); |
||
| 239 | clear_char(); |
||
| 240 | saveshad(); |
||
| 241 | } else if (Guard.charid == charid_4_skeleton && |
||
| 242 | (Guard.room = level.roomlinks[Guard.room - 1].down) == 3) { |
||
| 243 | // if skeleton falls down into room 3 |
||
| 244 | Guard.x = 133; |
||
| 245 | Guard.curr_row = 1; |
||
| 246 | Guard.direction = dir_0_right; |
||
| 247 | Guard.alive = -1; |
||
| 248 | leave_guard(); |
||
| 249 | } else { |
||
| 250 | on_guard_killed(); |
||
| 251 | level.guards_tile[drawn_room - 1] = -1; |
||
| 252 | Guard.direction = dir_56_none; |
||
| 253 | draw_guard_hp(0, guardhp_curr); |
||
| 254 | guardhp_curr = 0; |
||
| 255 | } |
||
| 256 | } |
||
| 257 | |||
| 258 | // seg002:02F5 |
||
| 259 | void __pascal far leave_guard() { |
||
| 260 | word room_minus_1; |
||
| 261 | if (Guard.direction == dir_56_none || Guard.charid == charid_1_shadow || Guard.charid == charid_24_mouse) { |
||
| 262 | return; |
||
| 263 | } |
||
| 264 | // arrays are indexed 0..23 instead of 1..24 |
||
| 265 | room_minus_1 = Guard.room - 1; |
||
| 266 | level.guards_tile[room_minus_1] = get_tilepos(0, Guard.curr_row); |
||
| 267 | |||
| 268 | level.guards_color[room_minus_1] = curr_guard_color & 0x0F; // restriction to 4 bits added |
||
| 269 | #ifdef REMEMBER_GUARD_HP |
||
| 270 | if (enable_remember_guard_hp && guardhp_curr < 16) // can remember 1..15 hp |
||
| 271 | level.guards_color[room_minus_1] |= (guardhp_curr << 4); |
||
| 272 | #endif |
||
| 273 | |||
| 274 | level.guards_x[room_minus_1] = Guard.x; |
||
| 275 | level.guards_dir[room_minus_1] = Guard.direction; |
||
| 276 | level.guards_skill[room_minus_1] = guard_skill; |
||
| 277 | if (Guard.alive < 0) { |
||
| 278 | level.guards_seq_hi[room_minus_1] = 0; |
||
| 279 | } else { |
||
| 280 | level.guards_seq_lo[room_minus_1] = Guard.curr_seq; |
||
| 281 | level.guards_seq_hi[room_minus_1] = Guard.curr_seq >> 8; |
||
| 282 | } |
||
| 283 | Guard.direction = dir_56_none; |
||
| 284 | draw_guard_hp(0, guardhp_curr); |
||
| 285 | guardhp_curr = 0; |
||
| 286 | } |
||
| 287 | |||
| 288 | // seg002:039E |
||
| 289 | void __pascal far follow_guard() { |
||
| 290 | level.guards_tile[Kid.room - 1] = 0xFF; |
||
| 291 | level.guards_tile[Guard.room - 1] = 0xFF; |
||
| 292 | loadshad(); |
||
| 293 | goto_other_room(roomleave_result); |
||
| 294 | saveshad(); |
||
| 295 | } |
||
| 296 | |||
| 297 | // seg002:03C7 |
||
| 298 | void __pascal far exit_room() { |
||
| 299 | word leave; |
||
| 300 | word kid_room_m1; |
||
| 301 | leave = 0; |
||
| 302 | if (exit_room_timer != 0) { |
||
| 303 | --exit_room_timer; |
||
| 304 | return; |
||
| 305 | } |
||
| 306 | loadkid(); |
||
| 307 | load_frame_to_obj(); |
||
| 308 | set_char_collision(); |
||
| 309 | roomleave_result = leave_room(); |
||
| 310 | if (roomleave_result < 0) { |
||
| 311 | return; |
||
| 312 | } |
||
| 313 | savekid(); |
||
| 314 | next_room = Char.room; |
||
| 315 | if (Guard.direction == dir_56_none) return; |
||
| 316 | if (Guard.alive < 0 && Guard.sword == sword_2_drawn) { |
||
| 317 | kid_room_m1 = Kid.room - 1; |
||
| 318 | if (level.guards_tile[kid_room_m1] >= 30 || |
||
| 319 | level.guards_seq_hi[kid_room_m1] != 0 |
||
| 320 | ) { |
||
| 321 | if (roomleave_result == 0) { |
||
| 322 | // left |
||
| 323 | if (Guard.x >= 91) leave = 1; |
||
| 324 | #ifdef FIX_GUARD_FOLLOWING_THROUGH_CLOSED_GATES |
||
| 325 | else if (fix_guard_following_through_closed_gates && can_guard_see_kid != 2 && |
||
| 326 | Kid.sword != sword_2_drawn) { |
||
| 327 | leave = 1; |
||
| 328 | } |
||
| 329 | #endif |
||
| 330 | } else if (roomleave_result == 1) { |
||
| 331 | // right |
||
| 332 | if (Guard.x < 165) leave = 1; |
||
| 333 | #ifdef FIX_GUARD_FOLLOWING_THROUGH_CLOSED_GATES |
||
| 334 | else if (fix_guard_following_through_closed_gates && can_guard_see_kid != 2 && |
||
| 335 | Kid.sword != sword_2_drawn) { |
||
| 336 | leave = 1; |
||
| 337 | } |
||
| 338 | #endif |
||
| 339 | } else if (roomleave_result == 2) { |
||
| 340 | // up |
||
| 341 | if (Guard.curr_row >= 0) leave = 1; |
||
| 342 | } else { |
||
| 343 | // down |
||
| 344 | if (Guard.curr_row < 3) leave = 1; |
||
| 345 | } |
||
| 346 | } else { |
||
| 347 | leave = 1; |
||
| 348 | } |
||
| 349 | } else { |
||
| 350 | leave = 1; |
||
| 351 | } |
||
| 352 | if (leave) { |
||
| 353 | leave_guard(); |
||
| 354 | } else { |
||
| 355 | follow_guard(); |
||
| 356 | } |
||
| 357 | } |
||
| 358 | |||
| 359 | // seg002:0486 |
||
| 360 | int __pascal far goto_other_room(short direction) { |
||
| 361 | short opposite_dir; |
||
| 362 | Char.room = ((byte*)&level.roomlinks[Char.room - 1])[direction]; |
||
| 363 | if (direction == 0) { |
||
| 364 | // left |
||
| 365 | Char.x += 140; |
||
| 366 | opposite_dir = 1; |
||
| 367 | } else if (direction == 1) { |
||
| 368 | // right |
||
| 369 | Char.x -= 140; |
||
| 370 | opposite_dir = 0; |
||
| 371 | } else if (direction == 2) { |
||
| 372 | // up |
||
| 373 | Char.y += 189; |
||
| 374 | Char.curr_row = y_to_row_mod4(Char.y); |
||
| 375 | opposite_dir = 3; |
||
| 376 | } else { |
||
| 377 | // down |
||
| 378 | Char.y -= 189; |
||
| 379 | Char.curr_row = y_to_row_mod4(Char.y); |
||
| 380 | opposite_dir = 2; |
||
| 381 | } |
||
| 382 | return opposite_dir; |
||
| 383 | } |
||
| 384 | |||
| 385 | // seg002:0504 |
||
| 386 | short __pascal far leave_room() { |
||
| 387 | short frame; |
||
| 388 | word action; |
||
| 389 | short chary; |
||
| 390 | short leave_dir; |
||
| 391 | chary = Char.y; |
||
| 392 | action = Char.action; |
||
| 393 | frame = Char.frame; |
||
| 394 | if (action != actions_5_bumped && |
||
| 395 | action != actions_4_in_freefall && |
||
| 396 | action != actions_3_in_midair && |
||
| 397 | (sbyte)chary < 10 && (sbyte)chary > -16 |
||
| 398 | ) { |
||
| 399 | leave_dir = 2; // up |
||
| 400 | } else if (chary >= 211) { |
||
| 401 | leave_dir = 3; // down |
||
| 402 | } else if ( |
||
| 403 | // frames 135..149: climb up |
||
| 404 | (frame >= frame_135_climbing_1 && frame < 150) || |
||
| 405 | // frames 110..119: standing up from crouch |
||
| 406 | (frame >= frame_110_stand_up_from_crouch_1 && frame < 120) || |
||
| 407 | // frames 150..162: with sword |
||
| 408 | (frame >= frame_150_parry && frame < 163 |
||
| 409 | |||
| 410 | #ifdef FIX_RETREAT_WITHOUT_LEAVING_ROOM |
||
| 411 | // By repeatedly pressing 'back' in a swordfight, you can retreat out of a room without the room changing. (Trick 35) |
||
| 412 | |||
| 413 | // The game waits for a 'legal frame' (e.g. frame_170_stand_with_sword) until leaving is possible; |
||
| 414 | // However, this frame is never reached if you press 'back' in the correct pattern! |
||
| 415 | |||
| 416 | // Solution: also allow the room to be changed on frame_157_walk_with_sword |
||
| 417 | // Note that this means that the delay for leaving rooms in a swordfight becomes noticably shorter. |
||
| 418 | |||
| 419 | && (frame != frame_157_walk_with_sword || !fix_retreat_without_leaving_room) |
||
| 420 | #endif |
||
| 421 | |||
| 422 | ) || |
||
| 423 | // frames 166..168: with sword |
||
| 424 | (frame >= frame_166_stand_inactive && frame < 169) || |
||
| 425 | action == actions_7_turn // turn |
||
| 426 | ) { |
||
| 427 | return -1; |
||
| 428 | } else if (Char.direction != dir_0_right) { |
||
| 429 | // looking left |
||
| 430 | if (char_x_left <= 54) { |
||
| 431 | leave_dir = 0; // left |
||
| 432 | } else if (char_x_left >= 198) { |
||
| 433 | leave_dir = 1; // right |
||
| 434 | } else { |
||
| 435 | return -1; |
||
| 436 | } |
||
| 437 | } else { |
||
| 438 | // looking right |
||
| 439 | get_tile(Char.room, 9, Char.curr_row); |
||
| 440 | if (curr_tile2 != tiles_7_doortop_with_floor && |
||
| 441 | curr_tile2 != tiles_12_doortop && |
||
| 442 | char_x_right >= 201 |
||
| 443 | ) { |
||
| 444 | leave_dir = 1; // right |
||
| 445 | } else if (char_x_right <= 57) { |
||
| 446 | leave_dir = 0; // left |
||
| 447 | } else { |
||
| 448 | return -1; |
||
| 449 | } |
||
| 450 | } |
||
| 451 | switch (leave_dir) { |
||
| 452 | case 0: // left |
||
| 453 | play_mirr_mus(); |
||
| 454 | level3_set_chkp(); |
||
| 455 | Jaffar_exit(); |
||
| 456 | break; |
||
| 457 | case 1: // right |
||
| 458 | sword_disappears(); |
||
| 459 | meet_Jaffar(); |
||
| 460 | break; |
||
| 461 | //case 2: // up |
||
| 462 | case 3: // down |
||
| 463 | // Special event: falling exit |
||
| 464 | if (current_level == 6 && Char.room == 1) { |
||
| 465 | return -2; |
||
| 466 | } |
||
| 467 | break; |
||
| 468 | } |
||
| 469 | goto_other_room(leave_dir); |
||
| 470 | #ifdef USE_REPLAY |
||
| 471 | if (skipping_replay && replay_seek_target == replay_seek_0_next_room) skipping_replay = 0; |
||
| 472 | #endif |
||
| 473 | return leave_dir; |
||
| 474 | } |
||
| 475 | |||
| 476 | // seg002:0643 |
||
| 477 | void __pascal far Jaffar_exit() { |
||
| 478 | if (leveldoor_open == 2) { |
||
| 479 | get_tile(24, 0, 0); |
||
| 480 | trigger_button(0, 0, -1); |
||
| 481 | } |
||
| 482 | } |
||
| 483 | |||
| 484 | // seg002:0665 |
||
| 485 | void __pascal far level3_set_chkp() { |
||
| 486 | // Special event: set checkpoint |
||
| 487 | if (current_level == 3 && Char.room == 7) { |
||
| 488 | checkpoint = 1; |
||
| 489 | hitp_beg_lev = hitp_max; |
||
| 490 | } |
||
| 491 | } |
||
| 492 | |||
| 493 | // seg002:0680 |
||
| 494 | void __pascal far sword_disappears() { |
||
| 495 | // Special event: sword disappears |
||
| 496 | if (current_level == 12 && Char.room == 18) { |
||
| 497 | get_tile(15, 1, 0); |
||
| 498 | curr_room_tiles[curr_tilepos] = tiles_1_floor; |
||
| 499 | curr_room_modif[curr_tilepos] = 0; // added, a nonzero modifier may show fake tiles |
||
| 500 | } |
||
| 501 | } |
||
| 502 | |||
| 503 | // seg002:06AE |
||
| 504 | void __pascal far meet_Jaffar() { |
||
| 505 | // Special event: play music |
||
| 506 | if (current_level == 13 && leveldoor_open == 0 && Char.room == 3) { |
||
| 507 | play_sound(sound_29_meet_Jaffar); // meet Jaffar |
||
| 508 | // Special event: Jaffar waits a bit (28/12=2.33 seconds) |
||
| 509 | guard_notice_timer = 28; |
||
| 510 | } |
||
| 511 | } |
||
| 512 | |||
| 513 | // seg002:06D3 |
||
| 514 | void __pascal far play_mirr_mus() { |
||
| 515 | // Special event: mirror music |
||
| 516 | if ( |
||
| 517 | leveldoor_open != 0 && |
||
| 518 | leveldoor_open != 0x4D && // was the music played already? |
||
| 519 | current_level == 4 && |
||
| 520 | Char.curr_row == 0 && |
||
| 521 | Char.room == 11 |
||
| 522 | ) { |
||
| 523 | play_sound(sound_25_presentation); // presentation (level 4 mirror) |
||
| 524 | leveldoor_open = 0x4D; |
||
| 525 | } |
||
| 526 | } |
||
| 527 | |||
| 528 | // seg002:0706 |
||
| 529 | void __pascal far move_0_nothing() { |
||
| 530 | control_shift = 0; |
||
| 531 | control_y = 0; |
||
| 532 | control_x = 0; |
||
| 533 | control_shift2 = 0; |
||
| 534 | control_down = 0; |
||
| 535 | control_up = 0; |
||
| 536 | control_backward = 0; |
||
| 537 | control_forward = 0; |
||
| 538 | } |
||
| 539 | |||
| 540 | // seg002:0721 |
||
| 541 | void __pascal far move_1_forward() { |
||
| 542 | control_x = -1; |
||
| 543 | control_forward = -1; |
||
| 544 | } |
||
| 545 | |||
| 546 | // seg002:072A |
||
| 547 | void __pascal far move_2_backward() { |
||
| 548 | control_backward = -1; |
||
| 549 | control_x = 1; |
||
| 550 | } |
||
| 551 | |||
| 552 | // seg002:0735 |
||
| 553 | void __pascal far move_3_up() { |
||
| 554 | control_y = -1; |
||
| 555 | control_up = -1; |
||
| 556 | } |
||
| 557 | |||
| 558 | // seg002:073E |
||
| 559 | void __pascal far move_4_down() { |
||
| 560 | control_down = -1; |
||
| 561 | control_y = 1; |
||
| 562 | } |
||
| 563 | |||
| 564 | // seg002:0749 |
||
| 565 | void __pascal far move_up_back() { |
||
| 566 | control_up = -1; |
||
| 567 | move_2_backward(); |
||
| 568 | } |
||
| 569 | |||
| 570 | // seg002:0753 |
||
| 571 | void __pascal far move_down_back() { |
||
| 572 | control_down = -1; |
||
| 573 | move_2_backward(); |
||
| 574 | } |
||
| 575 | |||
| 576 | // seg002:075D |
||
| 577 | void __pascal far move_down_forw() { |
||
| 578 | control_down = -1; |
||
| 579 | move_1_forward(); |
||
| 580 | } |
||
| 581 | |||
| 582 | // seg002:0767 |
||
| 583 | void __pascal far move_6_shift() { |
||
| 584 | control_shift = -1; |
||
| 585 | control_shift2 = -1; |
||
| 586 | } |
||
| 587 | |||
| 588 | // seg002:0770 |
||
| 589 | void __pascal far move_7() { |
||
| 590 | control_shift = 0; |
||
| 591 | } |
||
| 592 | |||
| 593 | // seg002:0776 |
||
| 594 | void __pascal far autocontrol_opponent() { |
||
| 595 | word charid; |
||
| 596 | move_0_nothing(); |
||
| 597 | charid = Char.charid; |
||
| 598 | if (charid == charid_0_kid) { |
||
| 599 | autocontrol_kid(); |
||
| 600 | } else { |
||
| 601 | if (justblocked) --justblocked; |
||
| 602 | if (kid_sword_strike) --kid_sword_strike; |
||
| 603 | if (guard_refrac) --guard_refrac; |
||
| 604 | if (charid == charid_24_mouse) { |
||
| 605 | autocontrol_mouse(); |
||
| 606 | } else if (charid == charid_4_skeleton) { |
||
| 607 | autocontrol_skeleton(); |
||
| 608 | } else if (charid == charid_1_shadow) { |
||
| 609 | autocontrol_shadow(); |
||
| 610 | } else if (current_level == 13) { |
||
| 611 | autocontrol_Jaffar(); |
||
| 612 | } else { |
||
| 613 | autocontrol_guard(); |
||
| 614 | } |
||
| 615 | } |
||
| 616 | } |
||
| 617 | |||
| 618 | // seg002:07EB |
||
| 619 | void __pascal far autocontrol_mouse() { |
||
| 620 | if (Char.direction == dir_56_none) { |
||
| 621 | return; |
||
| 622 | } |
||
| 623 | if (Char.action == actions_0_stand) { |
||
| 624 | if (Char.x >= 200) { |
||
| 625 | clear_char(); |
||
| 626 | } |
||
| 627 | } else { |
||
| 628 | if (Char.x < 166) { |
||
| 629 | seqtbl_offset_char(seq_107_mouse_stand_up_and_go); // mouse |
||
| 630 | play_seq(); |
||
| 631 | } |
||
| 632 | } |
||
| 633 | } |
||
| 634 | |||
| 635 | // seg002:081D |
||
| 636 | void __pascal far autocontrol_shadow() { |
||
| 637 | if (current_level == 4) { |
||
| 638 | autocontrol_shadow_level4(); |
||
| 639 | } else if (current_level == 5) { |
||
| 640 | autocontrol_shadow_level5(); |
||
| 641 | } else if (current_level == 6) { |
||
| 642 | autocontrol_shadow_level6(); |
||
| 643 | } else if (current_level == 12) { |
||
| 644 | autocontrol_shadow_level12(); |
||
| 645 | } |
||
| 646 | } |
||
| 647 | |||
| 648 | // seg002:0850 |
||
| 649 | void __pascal far autocontrol_skeleton() { |
||
| 650 | Char.sword = sword_2_drawn; |
||
| 651 | autocontrol_guard(); |
||
| 652 | } |
||
| 653 | |||
| 654 | // seg002:085A |
||
| 655 | void __pascal far autocontrol_Jaffar() { |
||
| 656 | autocontrol_guard(); |
||
| 657 | } |
||
| 658 | |||
| 659 | // seg002:085F |
||
| 660 | void __pascal far autocontrol_kid() { |
||
| 661 | autocontrol_guard(); |
||
| 662 | } |
||
| 663 | |||
| 664 | // seg002:0864 |
||
| 665 | void __pascal far autocontrol_guard() { |
||
| 666 | if (Char.sword < sword_2_drawn) { |
||
| 667 | autocontrol_guard_inactive(); |
||
| 668 | } else { |
||
| 669 | autocontrol_guard_active(); |
||
| 670 | } |
||
| 671 | } |
||
| 672 | |||
| 673 | // seg002:0876 |
||
| 674 | void __pascal far autocontrol_guard_inactive() { |
||
| 675 | short distance; |
||
| 676 | if (Kid.alive >= 0) return; |
||
| 677 | distance = char_opp_dist(); |
||
| 678 | if (Opp.curr_row != Char.curr_row || (word)distance < (word)-8) { |
||
| 679 | // If Kid made a sound ... |
||
| 680 | if (is_guard_notice) { |
||
| 681 | is_guard_notice = 0; |
||
| 682 | if (distance < 0) { |
||
| 683 | // ... and Kid is behind Guard, Guard turns around. |
||
| 684 | if ((word)distance < (word)-4) { |
||
| 685 | move_4_down(); |
||
| 686 | } |
||
| 687 | return; |
||
| 688 | } |
||
| 689 | } else if (distance < 0) { |
||
| 690 | return; |
||
| 691 | } |
||
| 692 | } |
||
| 693 | if (can_guard_see_kid) { |
||
| 694 | // If Guard can see Kid, Guard moves to fighting pose. |
||
| 695 | if (current_level != 13 || guard_notice_timer == 0) { |
||
| 696 | move_down_forw(); |
||
| 697 | } |
||
| 698 | } |
||
| 699 | } |
||
| 700 | |||
| 701 | // seg002:08DC |
||
| 702 | void __pascal far autocontrol_guard_active() { |
||
| 703 | short opp_frame; |
||
| 704 | short char_frame; |
||
| 705 | short distance; |
||
| 706 | char_frame = Char.frame; |
||
| 707 | if (char_frame != frame_166_stand_inactive && char_frame >= 150 && can_guard_see_kid != 1) { |
||
| 708 | if (can_guard_see_kid == 0) { |
||
| 709 | if (droppedout != 0) { |
||
| 710 | guard_follows_kid_down(); |
||
| 711 | //return; |
||
| 712 | } else if (Char.charid != charid_4_skeleton) { |
||
| 713 | move_down_back(); |
||
| 714 | } |
||
| 715 | //return; |
||
| 716 | } else { // can_guard_see_kid == 2 |
||
| 717 | opp_frame = Opp.frame; |
||
| 718 | distance = char_opp_dist(); |
||
| 719 | if (distance >= 12 && |
||
| 720 | // frames 102..117: falling and landing |
||
| 721 | opp_frame >= frame_102_start_fall_1 && opp_frame < frame_118_stand_up_from_crouch_9 && |
||
| 722 | Opp.action == actions_5_bumped |
||
| 723 | ) { |
||
| 724 | return; |
||
| 725 | } |
||
| 726 | if (distance < 35) { |
||
| 727 | if ((Char.sword < sword_2_drawn && distance < 8) || distance < 12) { |
||
| 728 | if (Char.direction == Opp.direction) { |
||
| 729 | // turn around |
||
| 730 | move_2_backward(); |
||
| 731 | //return; |
||
| 732 | } else { |
||
| 733 | move_1_forward(); |
||
| 734 | //return; |
||
| 735 | } |
||
| 736 | } else { |
||
| 737 | autocontrol_guard_kid_in_sight(distance); |
||
| 738 | //return; |
||
| 739 | } |
||
| 740 | } else { |
||
| 741 | if (guard_refrac != 0) return; |
||
| 742 | if (Char.direction != Opp.direction) { |
||
| 743 | // frames 7..14: running |
||
| 744 | // frames 34..43: run-jump |
||
| 745 | if (opp_frame >= frame_7_run && opp_frame < 15) { |
||
| 746 | if (distance < 40) move_6_shift(); |
||
| 747 | return; |
||
| 748 | } else if (opp_frame >= frame_34_start_run_jump_1 && opp_frame < 44) { |
||
| 749 | if (distance < 50) move_6_shift(); |
||
| 750 | return; |
||
| 751 | //return; |
||
| 752 | } |
||
| 753 | } |
||
| 754 | autocontrol_guard_kid_far(); |
||
| 755 | } |
||
| 756 | //... |
||
| 757 | } |
||
| 758 | //... |
||
| 759 | } |
||
| 760 | } |
||
| 761 | |||
| 762 | // seg002:09CB |
||
| 763 | void __pascal far autocontrol_guard_kid_far() { |
||
| 764 | if (tile_is_floor(get_tile_infrontof_char()) || |
||
| 765 | tile_is_floor(get_tile_infrontof2_char())) { |
||
| 766 | move_1_forward(); |
||
| 767 | } else { |
||
| 768 | move_2_backward(); |
||
| 769 | } |
||
| 770 | } |
||
| 771 | |||
| 772 | // seg002:09F8 |
||
| 773 | void __pascal far guard_follows_kid_down() { |
||
| 774 | // This is called from autocontrol_guard_active, so char=Guard, Opp=Kid |
||
| 775 | word opp_action; |
||
| 776 | opp_action = Opp.action; |
||
| 777 | if (opp_action == actions_2_hang_climb || opp_action == actions_6_hang_straight) { |
||
| 778 | return; |
||
| 779 | } |
||
| 780 | if (// there is wall in front of Guard |
||
| 781 | wall_type(get_tile_infrontof_char()) != 0 || |
||
| 782 | (! tile_is_floor(curr_tile2) && ( |
||
| 783 | (get_tile(curr_room, tile_col, ++tile_row) == tiles_2_spike || |
||
| 784 | // Guard would fall on loose floor |
||
| 785 | curr_tile2 == tiles_11_loose || |
||
| 786 | // ... or wall (?) |
||
| 787 | wall_type(curr_tile2) != 0 || |
||
| 788 | // ... or into a chasm |
||
| 789 | ! tile_is_floor(curr_tile2)) || |
||
| 790 | // ... or Kid is not below |
||
| 791 | Char.curr_row + 1 != Opp.curr_row |
||
| 792 | )) |
||
| 793 | ) { |
||
| 794 | // don't follow |
||
| 795 | droppedout = 0; |
||
| 796 | move_2_backward(); |
||
| 797 | } else { |
||
| 798 | // follow |
||
| 799 | move_1_forward(); |
||
| 800 | } |
||
| 801 | } |
||
| 802 | |||
| 803 | // seg002:0A93 |
||
| 804 | void __pascal far autocontrol_guard_kid_in_sight(short distance) { |
||
| 805 | if (Opp.sword == sword_2_drawn) { |
||
| 806 | autocontrol_guard_kid_armed(distance); |
||
| 807 | } else if (guard_refrac == 0) { |
||
| 808 | if (distance < 29) { |
||
| 809 | move_6_shift(); |
||
| 810 | } else { |
||
| 811 | move_1_forward(); |
||
| 812 | } |
||
| 813 | } |
||
| 814 | } |
||
| 815 | |||
| 816 | // seg002:0AC1 |
||
| 817 | void __pascal far autocontrol_guard_kid_armed(short distance) { |
||
| 818 | if (distance < 10 || distance >= 29) { |
||
| 819 | guard_advance(); |
||
| 820 | } else { |
||
| 821 | guard_block(); |
||
| 822 | if (guard_refrac == 0) { |
||
| 823 | if (distance < 12 || distance >= 29) { |
||
| 824 | guard_advance(); |
||
| 825 | } else { |
||
| 826 | guard_strike(); |
||
| 827 | } |
||
| 828 | } |
||
| 829 | } |
||
| 830 | } |
||
| 831 | |||
| 832 | // seg002:0AF5 |
||
| 833 | void __pascal far guard_advance() { |
||
| 834 | if (guard_skill == 0 || kid_sword_strike == 0) { |
||
| 835 | if (advprob[guard_skill] > prandom(255)) { |
||
| 836 | move_1_forward(); |
||
| 837 | } |
||
| 838 | } |
||
| 839 | } |
||
| 840 | |||
| 841 | // seg002:0B1D |
||
| 842 | void __pascal far guard_block() { |
||
| 843 | word opp_frame; |
||
| 844 | opp_frame = Opp.frame; |
||
| 845 | if (opp_frame == frame_152_strike_2 || opp_frame == frame_153_strike_3 || opp_frame == frame_162_block_to_strike) { |
||
| 846 | if (justblocked != 0) { |
||
| 847 | if (impblockprob[guard_skill] > prandom(255)) { |
||
| 848 | move_3_up(); |
||
| 849 | } |
||
| 850 | } else { |
||
| 851 | if (blockprob[guard_skill] > prandom(255)) { |
||
| 852 | move_3_up(); |
||
| 853 | } |
||
| 854 | } |
||
| 855 | } |
||
| 856 | } |
||
| 857 | |||
| 858 | // seg002:0B73 |
||
| 859 | void __pascal far guard_strike() { |
||
| 860 | word opp_frame; |
||
| 861 | word char_frame; |
||
| 862 | opp_frame = Opp.frame; |
||
| 863 | if (opp_frame == frame_169_begin_block || opp_frame == frame_151_strike_1) return; |
||
| 864 | char_frame = Char.frame; |
||
| 865 | if (char_frame == frame_161_parry || char_frame == frame_150_parry) { |
||
| 866 | if (restrikeprob[guard_skill] > prandom(255)) { |
||
| 867 | move_6_shift(); |
||
| 868 | } |
||
| 869 | } else { |
||
| 870 | if (strikeprob[guard_skill] > prandom(255)) { |
||
| 871 | move_6_shift(); |
||
| 872 | } |
||
| 873 | } |
||
| 874 | } |
||
| 875 | |||
| 876 | // seg002:0BCD |
||
| 877 | void __pascal far hurt_by_sword() { |
||
| 878 | short distance; |
||
| 879 | if (Char.alive >= 0) return; |
||
| 880 | if (Char.sword != sword_2_drawn) { |
||
| 881 | // Being hurt when not in fighting pose means death. |
||
| 882 | take_hp(100); |
||
| 883 | seqtbl_offset_char(seq_85_stabbed_to_death); // dying (stabbed unarmed) |
||
| 884 | loc_4276: |
||
| 885 | if (get_tile_behind_char() != 0 || |
||
| 886 | (distance = distance_to_edge_weight()) < 4 |
||
| 887 | ) { |
||
| 888 | seqtbl_offset_char(seq_85_stabbed_to_death); // dying (stabbed) |
||
| 889 | if (Char.charid != charid_0_kid && |
||
| 890 | Char.direction < dir_0_right && // looking left |
||
| 891 | (curr_tile2 == tiles_4_gate || get_tile_at_char() == tiles_4_gate) |
||
| 892 | ) { |
||
| 893 | Char.x = x_bump[tile_col - (curr_tile2 != tiles_4_gate) + 5] + 7; |
||
| 894 | Char.x = char_dx_forward(10); |
||
| 895 | } |
||
| 896 | Char.y = y_land[Char.curr_row + 1]; |
||
| 897 | Char.fall_y = 0; |
||
| 898 | } else { |
||
| 899 | Char.x = char_dx_forward(distance - 20); |
||
| 900 | load_fram_det_col(); |
||
| 901 | inc_curr_row(); |
||
| 902 | seqtbl_offset_char(seq_81_kid_pushed_off_ledge); // Kid/Guard is killed and pushed off the ledge |
||
| 903 | } |
||
| 904 | } else { |
||
| 905 | // You can't hurt skeletons |
||
| 906 | if (Char.charid != charid_4_skeleton) { |
||
| 907 | if (take_hp(1)) goto loc_4276; |
||
| 908 | } |
||
| 909 | seqtbl_offset_char(seq_74_hit_by_sword); // being hit with sword |
||
| 910 | Char.y = y_land[Char.curr_row + 1]; |
||
| 911 | Char.fall_y = 0; |
||
| 912 | } |
||
| 913 | // sound 13: Kid hurt (by sword), sound 12: Guard hurt (by sword) |
||
| 914 | play_sound(Char.charid == charid_0_kid ? sound_13_kid_hurt : sound_12_guard_hurt); |
||
| 915 | play_seq(); |
||
| 916 | } |
||
| 917 | |||
| 918 | // seg002:0CD4 |
||
| 919 | void __pascal far check_sword_hurt() { |
||
| 920 | if (Guard.action == actions_99_hurt) { |
||
| 921 | if (Kid.action == actions_99_hurt) { |
||
| 922 | Kid.action = actions_1_run_jump; |
||
| 923 | } |
||
| 924 | loadshad(); |
||
| 925 | hurt_by_sword(); |
||
| 926 | saveshad(); |
||
| 927 | guard_refrac = refractimer[guard_skill]; |
||
| 928 | } else { |
||
| 929 | if (Kid.action == actions_99_hurt) { |
||
| 930 | loadkid(); |
||
| 931 | hurt_by_sword(); |
||
| 932 | savekid(); |
||
| 933 | } |
||
| 934 | } |
||
| 935 | } |
||
| 936 | |||
| 937 | // seg002:0D1A |
||
| 938 | void __pascal far check_sword_hurting() { |
||
| 939 | short kid_frame; |
||
| 940 | kid_frame = Kid.frame; |
||
| 941 | // frames 217..228: go up on stairs |
||
| 942 | if (kid_frame != 0 && (kid_frame < frame_219_exit_stairs_3 || kid_frame >= 229)) { |
||
| 943 | loadshad_and_opp(); |
||
| 944 | check_hurting(); |
||
| 945 | saveshad_and_opp(); |
||
| 946 | loadkid_and_opp(); |
||
| 947 | check_hurting(); |
||
| 948 | savekid_and_opp(); |
||
| 949 | } |
||
| 950 | } |
||
| 951 | |||
| 952 | // seg002:0D56 |
||
| 953 | void __pascal far check_hurting() { |
||
| 954 | short opp_frame, char_frame, distance, min_hurt_range; |
||
| 955 | if (Char.sword != sword_2_drawn) return; |
||
| 956 | if (Char.curr_row != Opp.curr_row) return; |
||
| 957 | char_frame = Char.frame; |
||
| 958 | // frames 153..154: poking with sword |
||
| 959 | if (char_frame != frame_153_strike_3 && char_frame != frame_154_poking) return; |
||
| 960 | // If char is poking ... |
||
| 961 | distance = char_opp_dist(); |
||
| 962 | opp_frame = Opp.frame; |
||
| 963 | // frames 161 and 150: parrying |
||
| 964 | if (distance < 0 || distance >= 29 || |
||
| 965 | (opp_frame != frame_161_parry && opp_frame != frame_150_parry) |
||
| 966 | ) { |
||
| 967 | // ... and Opp is not parrying |
||
| 968 | // frame 154: poking |
||
| 969 | if (Char.frame == frame_154_poking) { |
||
| 970 | if (Opp.sword < sword_2_drawn) { |
||
| 971 | min_hurt_range = 8; |
||
| 972 | } else { |
||
| 973 | min_hurt_range = 12; |
||
| 974 | } |
||
| 975 | distance = char_opp_dist(); |
||
| 976 | if (distance >= min_hurt_range && distance < 29) { |
||
| 977 | Opp.action = actions_99_hurt; |
||
| 978 | } |
||
| 979 | } |
||
| 980 | } else { |
||
| 981 | Opp.frame = frame_161_parry; |
||
| 982 | if (Char.charid != charid_0_kid) { |
||
| 983 | justblocked = 4; |
||
| 984 | } |
||
| 985 | seqtbl_offset_char(seq_69_attack_was_parried); // attack was parried |
||
| 986 | play_seq(); |
||
| 987 | } |
||
| 988 | // frame 154: poking |
||
| 989 | // frame 161: parrying |
||
| 990 | if (Char.frame == frame_154_poking && Opp.frame != frame_161_parry && Opp.action != actions_99_hurt) { |
||
| 991 | play_sound(sound_11_sword_moving); // sword moving |
||
| 992 | } |
||
| 993 | } |
||
| 994 | |||
| 995 | // seg002:0E1F |
||
| 996 | void __pascal far check_skel() { |
||
| 997 | // Special event: skeleton wakes |
||
| 998 | if (current_level == 3 && |
||
| 999 | Guard.direction == dir_56_none && |
||
| 1000 | drawn_room == 1 && |
||
| 1001 | leveldoor_open != 0 && |
||
| 1002 | (Kid.curr_col == 2 || Kid.curr_col == 3) |
||
| 1003 | ) { |
||
| 1004 | get_tile(drawn_room, 5, 1); |
||
| 1005 | if (curr_tile2 == tiles_21_skeleton) { |
||
| 1006 | // erase skeleton |
||
| 1007 | curr_room_tiles[curr_tilepos] = tiles_1_floor; |
||
| 1008 | redraw_height = 24; |
||
| 1009 | set_redraw_full(curr_tilepos, 1); |
||
| 1010 | set_wipe(curr_tilepos, 1); |
||
| 1011 | ++curr_tilepos; |
||
| 1012 | set_redraw_full(curr_tilepos, 1); |
||
| 1013 | set_wipe(curr_tilepos, 1); |
||
| 1014 | Char.room = drawn_room; |
||
| 1015 | Char.curr_row = 1; |
||
| 1016 | Char.y = y_land[Char.curr_row + 1]; |
||
| 1017 | Char.curr_col = 5; |
||
| 1018 | Char.x = x_bump[Char.curr_col + 5] + 14; |
||
| 1019 | Char.direction = dir_FF_left; |
||
| 1020 | seqtbl_offset_char(seq_88_skel_wake_up); // skel wake up |
||
| 1021 | play_seq(); |
||
| 1022 | play_sound(sound_44_skel_alive); // skel alive |
||
| 1023 | guard_skill = 2; |
||
| 1024 | Char.alive = -1; |
||
| 1025 | guardhp_max = guardhp_curr = 3; |
||
| 1026 | Char.fall_x = Char.fall_y = 0; |
||
| 1027 | is_guard_notice = guard_refrac = 0; |
||
| 1028 | Char.sword = sword_2_drawn; |
||
| 1029 | Char.charid = charid_4_skeleton; |
||
| 1030 | saveshad(); |
||
| 1031 | } |
||
| 1032 | } |
||
| 1033 | } |
||
| 1034 | |||
| 1035 | // seg002:0F3F |
||
| 1036 | void __pascal far do_auto_moves(const auto_move_type *moves_ptr) { |
||
| 1037 | short demoindex; |
||
| 1038 | short curr_move; |
||
| 1039 | if (demo_time >= 0xFE) return; |
||
| 1040 | ++demo_time; |
||
| 1041 | demoindex = demo_index; |
||
| 1042 | if (moves_ptr[demoindex].time <= demo_time) { |
||
| 1043 | ++demo_index; |
||
| 1044 | } else { |
||
| 1045 | demoindex = demo_index - 1; |
||
| 1046 | } |
||
| 1047 | curr_move = moves_ptr[demoindex].move; |
||
| 1048 | switch (curr_move) { |
||
| 1049 | case -1: |
||
| 1050 | break; |
||
| 1051 | case 0: |
||
| 1052 | move_0_nothing(); |
||
| 1053 | break; |
||
| 1054 | case 1: |
||
| 1055 | move_1_forward(); |
||
| 1056 | break; |
||
| 1057 | case 2: |
||
| 1058 | move_2_backward(); |
||
| 1059 | break; |
||
| 1060 | case 3: |
||
| 1061 | move_3_up(); |
||
| 1062 | break; |
||
| 1063 | case 4: |
||
| 1064 | move_4_down(); |
||
| 1065 | break; |
||
| 1066 | case 5: |
||
| 1067 | move_3_up(); |
||
| 1068 | move_1_forward(); |
||
| 1069 | break; |
||
| 1070 | case 6: |
||
| 1071 | move_6_shift(); |
||
| 1072 | break; |
||
| 1073 | case 7: |
||
| 1074 | move_7(); |
||
| 1075 | break; |
||
| 1076 | } |
||
| 1077 | } |
||
| 1078 | |||
| 1079 | // seg002:1000 |
||
| 1080 | void __pascal far autocontrol_shadow_level4() { |
||
| 1081 | if (Char.room == 4) { |
||
| 1082 | if (Char.x < 80) { |
||
| 1083 | clear_char(); |
||
| 1084 | } else { |
||
| 1085 | move_1_forward(); |
||
| 1086 | } |
||
| 1087 | } |
||
| 1088 | } |
||
| 1089 | |||
| 1090 | // data:0F02 |
||
| 1091 | const auto_move_type shad_drink_move[] = { |
||
| 1092 | {0x00, 0}, |
||
| 1093 | {0x01, 1}, |
||
| 1094 | {0x0E, 0}, |
||
| 1095 | {0x12, 6}, |
||
| 1096 | {0x1D, 7}, |
||
| 1097 | {0x2D, 2}, |
||
| 1098 | {0x31, 1}, |
||
| 1099 | {0xFF,-2}, |
||
| 1100 | }; |
||
| 1101 | |||
| 1102 | // seg002:101A |
||
| 1103 | void __pascal far autocontrol_shadow_level5() { |
||
| 1104 | if (Char.room == 24) { |
||
| 1105 | if (demo_time == 0) { |
||
| 1106 | get_tile(24, 1, 0); |
||
| 1107 | // is the door open? |
||
| 1108 | if (curr_room_modif[curr_tilepos] < 80) return; |
||
| 1109 | demo_index = 0; |
||
| 1110 | } |
||
| 1111 | do_auto_moves(shad_drink_move); |
||
| 1112 | if (Char.x < 15) { |
||
| 1113 | clear_char(); |
||
| 1114 | } |
||
| 1115 | } |
||
| 1116 | } |
||
| 1117 | |||
| 1118 | // seg002:1064 |
||
| 1119 | void __pascal far autocontrol_shadow_level6() { |
||
| 1120 | if (Char.room == 1 && |
||
| 1121 | Kid.frame == frame_43_running_jump_4 && // a frame in run-jump |
||
| 1122 | Kid.x < 128 |
||
| 1123 | ) { |
||
| 1124 | move_6_shift(); |
||
| 1125 | move_1_forward(); |
||
| 1126 | } |
||
| 1127 | } |
||
| 1128 | |||
| 1129 | // seg002:1082 |
||
| 1130 | void __pascal far autocontrol_shadow_level12() { |
||
| 1131 | short opp_frame; |
||
| 1132 | short xdiff; |
||
| 1133 | if (Char.room == 15 && shadow_initialized == 0) { |
||
| 1134 | if (Opp.x >= 150) { |
||
| 1135 | do_init_shad(/*&*/init_shad_12, 7 /*fall*/); |
||
| 1136 | return; |
||
| 1137 | } |
||
| 1138 | shadow_initialized = 1; |
||
| 1139 | } |
||
| 1140 | if (Char.sword >= sword_2_drawn) { |
||
| 1141 | // if the Kid puts his sword away, the shadow does the same, |
||
| 1142 | // but only if the shadow was already hurt (?) |
||
| 1143 | if (offguard == 0 || guard_refrac == 0) { |
||
| 1144 | autocontrol_guard_active(); |
||
| 1145 | } else { |
||
| 1146 | move_4_down(); |
||
| 1147 | } |
||
| 1148 | return; |
||
| 1149 | } |
||
| 1150 | if (Opp.sword >= sword_2_drawn || offguard == 0) { |
||
| 1151 | xdiff = 0x7000; // bugfix/workaround |
||
| 1152 | // This behavior matches the DOS version but not the Apple II source. |
||
| 1153 | if (can_guard_see_kid < 2 || (xdiff = char_opp_dist()) >= 90) { |
||
| 1154 | if (xdiff < 0) { |
||
| 1155 | move_2_backward(); |
||
| 1156 | } |
||
| 1157 | return; |
||
| 1158 | } |
||
| 1159 | // Shadow draws his sword |
||
| 1160 | if (Char.frame == 15) { |
||
| 1161 | move_down_forw(); |
||
| 1162 | } |
||
| 1163 | return; |
||
| 1164 | } |
||
| 1165 | if (char_opp_dist() < 10) { |
||
| 1166 | // unite with the shadow |
||
| 1167 | flash_color = color_15_brightwhite; // white |
||
| 1168 | flash_time = 18; |
||
| 1169 | // get an extra HP for uniting the shadow |
||
| 1170 | add_life(); |
||
| 1171 | // time of Kid-shadow flash |
||
| 1172 | united_with_shadow = 42; |
||
| 1173 | // put the Kid where the shadow was |
||
| 1174 | Char.charid = charid_0_kid; |
||
| 1175 | savekid(); |
||
| 1176 | // remove the shadow |
||
| 1177 | clear_char(); |
||
| 1178 | return; |
||
| 1179 | } |
||
| 1180 | if (can_guard_see_kid == 2) { |
||
| 1181 | // If Kid runs to shadow, shadow runs to Kid. |
||
| 1182 | opp_frame = Opp.frame; |
||
| 1183 | // frames 1..14: running |
||
| 1184 | // frames 121..132: stepping |
||
| 1185 | if ((opp_frame >= frame_3_start_run && opp_frame < frame_15_stand) || |
||
| 1186 | (opp_frame >= frame_127_stepping_7 && opp_frame < 133) |
||
| 1187 | ) { |
||
| 1188 | move_1_forward(); |
||
| 1189 | } |
||
| 1190 | } |
||
| 1191 | } |