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 | // seg007:0000 |
||
| 24 | void __pascal far process_trobs() { |
||
| 25 | word need_delete; |
||
| 26 | word index; |
||
| 27 | word new_index; |
||
| 28 | need_delete = 0; |
||
| 29 | if (trobs_count == 0) return; |
||
| 30 | for (index = 0; index < trobs_count; ++index) { |
||
| 31 | trob = trobs[index]; |
||
| 32 | animate_tile(); |
||
| 33 | trobs[index].type = trob.type; |
||
| 34 | if (trob.type < 0) { |
||
| 35 | need_delete = 1; |
||
| 36 | } |
||
| 37 | } |
||
| 38 | if (need_delete) { |
||
| 39 | for (index = new_index = 0; index < trobs_count; ++index) { |
||
| 40 | if (trobs[index].type >= 0) { |
||
| 41 | trobs[new_index++] = trobs[index]; |
||
| 42 | } |
||
| 43 | } |
||
| 44 | trobs_count = new_index; |
||
| 45 | } |
||
| 46 | } |
||
| 47 | |||
| 48 | // seg007:00AF |
||
| 49 | void __pascal far animate_tile() { |
||
| 50 | get_room_address(trob.room); |
||
| 51 | switch (get_curr_tile(trob.tilepos)) { |
||
| 52 | case tiles_19_torch: |
||
| 53 | case tiles_30_torch_with_debris: |
||
| 54 | animate_torch(); |
||
| 55 | break; |
||
| 56 | case tiles_6_closer: |
||
| 57 | case tiles_15_opener: |
||
| 58 | animate_button(); |
||
| 59 | break; |
||
| 60 | case tiles_2_spike: |
||
| 61 | animate_spike(); |
||
| 62 | break; |
||
| 63 | case tiles_11_loose: |
||
| 64 | animate_loose(); |
||
| 65 | break; |
||
| 66 | case tiles_0_empty: |
||
| 67 | animate_empty(); |
||
| 68 | break; |
||
| 69 | case tiles_18_chomper: |
||
| 70 | animate_chomper(); |
||
| 71 | break; |
||
| 72 | case tiles_4_gate: |
||
| 73 | animate_door(); |
||
| 74 | break; |
||
| 75 | case tiles_16_level_door_left: |
||
| 76 | animate_leveldoor(); |
||
| 77 | break; |
||
| 78 | case tiles_10_potion: |
||
| 79 | animate_potion(); |
||
| 80 | break; |
||
| 81 | case tiles_22_sword: |
||
| 82 | animate_sword(); |
||
| 83 | break; |
||
| 84 | default: |
||
| 85 | trob.type = -1; |
||
| 86 | break; |
||
| 87 | } |
||
| 88 | curr_room_modif[trob.tilepos] = curr_modifier; |
||
| 89 | } |
||
| 90 | |||
| 91 | // seg007:0166 |
||
| 92 | short __pascal far is_trob_in_drawn_room() { |
||
| 93 | if (trob.room != drawn_room) { |
||
| 94 | trob.type = -1; |
||
| 95 | return 0; |
||
| 96 | } else { |
||
| 97 | return 1; |
||
| 98 | } |
||
| 99 | } |
||
| 100 | |||
| 101 | // seg007:017E |
||
| 102 | void __pascal far set_redraw_anim_right() { |
||
| 103 | set_redraw_anim(get_trob_right_pos_in_drawn_room(), 1); |
||
| 104 | } |
||
| 105 | |||
| 106 | // seg007:018C |
||
| 107 | void __pascal far set_redraw_anim_curr() { |
||
| 108 | set_redraw_anim(get_trob_pos_in_drawn_room(), 1); |
||
| 109 | } |
||
| 110 | |||
| 111 | // seg007:019A |
||
| 112 | void __pascal far redraw_at_trob() { |
||
| 113 | word tilepos; |
||
| 114 | redraw_height = 63; |
||
| 115 | tilepos = get_trob_pos_in_drawn_room(); |
||
| 116 | set_redraw_full(tilepos, 1); |
||
| 117 | set_wipe(tilepos, 1); |
||
| 118 | } |
||
| 119 | |||
| 120 | // seg007:01C5 |
||
| 121 | void __pascal far redraw_21h() { |
||
| 122 | redraw_height = 0x21; |
||
| 123 | redraw_tile_height(); |
||
| 124 | } |
||
| 125 | |||
| 126 | // seg007:01D0 |
||
| 127 | void __pascal far redraw_11h() { |
||
| 128 | redraw_height = 0x11; |
||
| 129 | redraw_tile_height(); |
||
| 130 | } |
||
| 131 | |||
| 132 | // seg007:01DB |
||
| 133 | void __pascal far redraw_20h() { |
||
| 134 | redraw_height = 0x20; |
||
| 135 | redraw_tile_height(); |
||
| 136 | } |
||
| 137 | |||
| 138 | // seg007:01E6 |
||
| 139 | void __pascal far draw_trob() { |
||
| 140 | word var_2; |
||
| 141 | var_2 = get_trob_right_pos_in_drawn_room(); |
||
| 142 | set_redraw_anim(var_2, 1); |
||
| 143 | set_redraw_fore(var_2, 1); |
||
| 144 | set_redraw_anim(get_trob_right_above_pos_in_drawn_room(), 1); |
||
| 145 | } |
||
| 146 | |||
| 147 | // seg007:0218 |
||
| 148 | void __pascal far redraw_tile_height() { |
||
| 149 | short tilepos; |
||
| 150 | tilepos = get_trob_pos_in_drawn_room(); |
||
| 151 | set_redraw_full(tilepos, 1); |
||
| 152 | set_wipe(tilepos, 1); |
||
| 153 | tilepos = get_trob_right_pos_in_drawn_room(); |
||
| 154 | set_redraw_full(tilepos, 1); |
||
| 155 | set_wipe(tilepos, 1); |
||
| 156 | } |
||
| 157 | |||
| 158 | // seg007:0258 |
||
| 159 | short __pascal far get_trob_pos_in_drawn_room() { |
||
| 160 | short tilepos; |
||
| 161 | tilepos = trob.tilepos; |
||
| 162 | if (trob.room == room_A) { |
||
| 163 | if (tilepos >= 20 && tilepos < 30) { |
||
| 164 | // 20..29 -> -1..-10 |
||
| 165 | tilepos = 19 - tilepos; |
||
| 166 | } else { |
||
| 167 | tilepos = 30; |
||
| 168 | } |
||
| 169 | } else { |
||
| 170 | if (trob.room != drawn_room) { |
||
| 171 | tilepos = 30; |
||
| 172 | } |
||
| 173 | } |
||
| 174 | return tilepos; |
||
| 175 | } |
||
| 176 | |||
| 177 | // seg007:029D |
||
| 178 | short __pascal far get_trob_right_pos_in_drawn_room() { |
||
| 179 | word tilepos; |
||
| 180 | tilepos = trob.tilepos; |
||
| 181 | if (trob.room == drawn_room) { |
||
| 182 | if (tilepos % 10 != 9) { |
||
| 183 | ++tilepos; |
||
| 184 | } else { |
||
| 185 | tilepos = 30; |
||
| 186 | } |
||
| 187 | } else if (trob.room == room_L) { |
||
| 188 | if (tilepos % 10 == 9) { |
||
| 189 | tilepos -= 9; |
||
| 190 | } else { |
||
| 191 | tilepos = 30; |
||
| 192 | } |
||
| 193 | } else if (trob.room == room_A) { |
||
| 194 | if (tilepos >= 20 && tilepos < 29) { |
||
| 195 | // 20..28 -> -2..-10 |
||
| 196 | tilepos = 18 - tilepos; |
||
| 197 | } else { |
||
| 198 | tilepos = 30; |
||
| 199 | } |
||
| 200 | } else if (trob.room == room_AL && tilepos == 29) { |
||
| 201 | tilepos = -1; |
||
| 202 | } else { |
||
| 203 | tilepos = 30; |
||
| 204 | } |
||
| 205 | return tilepos; |
||
| 206 | } |
||
| 207 | |||
| 208 | // seg007:032C |
||
| 209 | short __pascal far get_trob_right_above_pos_in_drawn_room() { |
||
| 210 | word tilepos; |
||
| 211 | tilepos = trob.tilepos; |
||
| 212 | if (trob.room == drawn_room) { |
||
| 213 | if (tilepos % 10 != 9) { |
||
| 214 | if (tilepos < 10) { |
||
| 215 | // 0..8 -> -2..-10 |
||
| 216 | tilepos = -(tilepos + 2); |
||
| 217 | } else { |
||
| 218 | tilepos -= 9; |
||
| 219 | } |
||
| 220 | } else { |
||
| 221 | tilepos = 30; |
||
| 222 | } |
||
| 223 | } else if (trob.room == room_L) { |
||
| 224 | if (tilepos == 9) { |
||
| 225 | tilepos = -1; |
||
| 226 | } else { |
||
| 227 | if (tilepos % 10 == 9) { |
||
| 228 | tilepos -= 19; |
||
| 229 | } else { |
||
| 230 | tilepos = 30; |
||
| 231 | } |
||
| 232 | } |
||
| 233 | } else if (trob.room == room_B) { |
||
| 234 | if (tilepos < 9) { |
||
| 235 | tilepos += 21; |
||
| 236 | } else { |
||
| 237 | tilepos = 30; |
||
| 238 | } |
||
| 239 | } else if (trob.room == room_BL && tilepos == 9) { |
||
| 240 | tilepos = 20; |
||
| 241 | } else { |
||
| 242 | tilepos = 30; |
||
| 243 | } |
||
| 244 | return tilepos; |
||
| 245 | } |
||
| 246 | |||
| 247 | // seg007:03CF |
||
| 248 | void __pascal far animate_torch() { |
||
| 249 | if (is_trob_in_drawn_room()) { |
||
| 250 | curr_modifier = get_torch_frame(curr_modifier); |
||
| 251 | set_redraw_anim_right(); |
||
| 252 | } |
||
| 253 | } |
||
| 254 | |||
| 255 | // seg007:03E9 |
||
| 256 | void __pascal far animate_potion() { |
||
| 257 | word type; |
||
| 258 | if (trob.type >= 0 && is_trob_in_drawn_room()) { |
||
| 259 | type = curr_modifier & 0xF8; |
||
| 260 | curr_modifier = bubble_next_frame(curr_modifier & 0x07) | type; |
||
| 261 | set_redraw_anim_curr(); |
||
| 262 | } |
||
| 263 | } |
||
| 264 | |||
| 265 | // seg007:0425 |
||
| 266 | void __pascal far animate_sword() { |
||
| 267 | if (is_trob_in_drawn_room()) { |
||
| 268 | --curr_modifier; |
||
| 269 | if (curr_modifier == 0) { |
||
| 270 | curr_modifier = (prandom(255) & 0x3F) + 0x28; |
||
| 271 | } |
||
| 272 | set_redraw_anim_curr(); |
||
| 273 | } |
||
| 274 | } |
||
| 275 | |||
| 276 | // seg007:0448 |
||
| 277 | void __pascal far animate_chomper() { |
||
| 278 | word blood; |
||
| 279 | word frame; |
||
| 280 | if (trob.type >= 0) { |
||
| 281 | blood = curr_modifier & 0x80; |
||
| 282 | frame = (curr_modifier & 0x7F) + 1; |
||
| 283 | if (frame > 15) { |
||
| 284 | frame = 1; |
||
| 285 | } |
||
| 286 | curr_modifier = blood | frame; |
||
| 287 | if (frame == 2) { |
||
| 288 | play_sound(sound_47_chomper); // chomper |
||
| 289 | } |
||
| 290 | // If either: |
||
| 291 | // - Kid left this room |
||
| 292 | // - Kid left this row |
||
| 293 | // - Kid died but not in this chomper |
||
| 294 | // and chomper is past frame 6 |
||
| 295 | // then stop. |
||
| 296 | if ((trob.room != drawn_room || trob.tilepos / 10 != Kid.curr_row || |
||
| 297 | (Kid.alive >= 0 && blood == 0)) && (curr_modifier & 0x7F) >= 6 |
||
| 298 | ) { |
||
| 299 | trob.type = -1; |
||
| 300 | } |
||
| 301 | } |
||
| 302 | if ((curr_modifier & 0x7F) < 6) { |
||
| 303 | redraw_at_trob(); |
||
| 304 | } |
||
| 305 | } |
||
| 306 | |||
| 307 | // seg007:04D3 |
||
| 308 | void __pascal far animate_spike() { |
||
| 309 | if (trob.type >= 0) { |
||
| 310 | // 0xFF means a disabled spike. |
||
| 311 | if (curr_modifier == 0xFF) return; |
||
| 312 | if (curr_modifier & 0x80) { |
||
| 313 | --curr_modifier; |
||
| 314 | if (curr_modifier & 0x7F) return; |
||
| 315 | curr_modifier = 6; |
||
| 316 | } else { |
||
| 317 | ++curr_modifier; |
||
| 318 | if (curr_modifier == 5) { |
||
| 319 | curr_modifier = 0x8F; |
||
| 320 | } else if (curr_modifier == 9) { |
||
| 321 | curr_modifier = 0; |
||
| 322 | trob.type = -1; |
||
| 323 | } |
||
| 324 | } |
||
| 325 | } |
||
| 326 | redraw_21h(); |
||
| 327 | } |
||
| 328 | |||
| 329 | // data:27B2 |
||
| 330 | const byte gate_close_speeds[] = {0, 0, 0, 20, 40, 60, 80, 100, 120}; |
||
| 331 | // data:27C0 |
||
| 332 | const byte door_delta[] = {-1, 4, 4}; |
||
| 333 | // seg007:0522 |
||
| 334 | void __pascal far animate_door() { |
||
| 335 | /* |
||
| 336 | Possible values of anim_type: |
||
| 337 | 0: closing |
||
| 338 | 1: open |
||
| 339 | 2: permanent open |
||
| 340 | 3,4,5,6,7,8: fast closing with speeds 20,40,60,80,100,120 /4 pixel/frame |
||
| 341 | */ |
||
| 342 | sbyte anim_type; |
||
| 343 | anim_type = trob.type; |
||
| 344 | if (anim_type >= 0) { |
||
| 345 | if (anim_type >= 3) { |
||
| 346 | // closing fast |
||
| 347 | if (anim_type < 8) { |
||
| 348 | ++anim_type; |
||
| 349 | trob.type = anim_type; |
||
| 350 | } |
||
| 351 | short new_mod = curr_modifier - gate_close_speeds[anim_type]; |
||
| 352 | curr_modifier = new_mod; |
||
| 353 | //if ((sbyte)curr_modifier < 0) { |
||
| 354 | if (new_mod < 0) { |
||
| 355 | //if ((curr_modifier -= gate_close_speeds[anim_type]) < 0) { |
||
| 356 | curr_modifier = 0; |
||
| 357 | trob.type = -1; |
||
| 358 | play_sound(sound_6_gate_closing_fast); // gate closing fast |
||
| 359 | } |
||
| 360 | } else { |
||
| 361 | if (curr_modifier != 0xFF) { |
||
| 362 | // 0xFF means permanently open. |
||
| 363 | curr_modifier += door_delta[anim_type]; |
||
| 364 | if (anim_type == 0) { |
||
| 365 | // closing |
||
| 366 | if (curr_modifier != 0) { |
||
| 367 | if (curr_modifier < 188) { |
||
| 368 | if ((curr_modifier & 3) == 3) { |
||
| 369 | play_door_sound_if_visible(sound_4_gate_closing); // gate closing |
||
| 370 | } |
||
| 371 | } |
||
| 372 | } else { |
||
| 373 | gate_stop(); |
||
| 374 | } |
||
| 375 | } else { |
||
| 376 | // opening |
||
| 377 | if (curr_modifier < 188) { |
||
| 378 | if ((curr_modifier & 7) == 0) { |
||
| 379 | play_sound(sound_5_gate_opening); // gate opening |
||
| 380 | } |
||
| 381 | } else { |
||
| 382 | // stop |
||
| 383 | if (anim_type < 2) { |
||
| 384 | // after regular open |
||
| 385 | curr_modifier = 238; |
||
| 386 | trob.type = 0; // closing |
||
| 387 | play_sound(sound_7_gate_stop); // gate stop (after opening) |
||
| 388 | } else { |
||
| 389 | // after permanent open |
||
| 390 | curr_modifier = 0xFF; // keep open |
||
| 391 | gate_stop(); |
||
| 392 | } |
||
| 393 | } |
||
| 394 | } |
||
| 395 | } else { |
||
| 396 | gate_stop(); |
||
| 397 | } |
||
| 398 | } |
||
| 399 | } |
||
| 400 | draw_trob(); |
||
| 401 | } |
||
| 402 | |||
| 403 | // seg007:05E3 |
||
| 404 | void __pascal far gate_stop() { |
||
| 405 | trob.type = -1; |
||
| 406 | play_door_sound_if_visible(sound_7_gate_stop); // gate stop (after closing) |
||
| 407 | } |
||
| 408 | |||
| 409 | // data:27B8 |
||
| 410 | const byte leveldoor_close_speeds[] = {0, 5, 17, 99, 0}; |
||
| 411 | // seg007:05F1 |
||
| 412 | void __pascal far animate_leveldoor() { |
||
| 413 | /* |
||
| 414 | Possible values of trob_type: |
||
| 415 | 0: open |
||
| 416 | 1: open (with button) |
||
| 417 | 2: open |
||
| 418 | 3,4,5,6: fast closing with speeds 0,5,17,99 pixel/frame |
||
| 419 | */ |
||
| 420 | word trob_type; |
||
| 421 | trob_type = trob.type; |
||
| 422 | if (trob.type >= 0) { |
||
| 423 | if (trob_type >= 3) { |
||
| 424 | // closing |
||
| 425 | ++trob.type; |
||
| 426 | curr_modifier -= leveldoor_close_speeds[trob.type - 3]; |
||
| 427 | if ((sbyte)curr_modifier < 0) { |
||
| 428 | curr_modifier = 0; |
||
| 429 | trob.type = -1; |
||
| 430 | play_sound(sound_14_leveldoor_closing); // level door closing |
||
| 431 | } else { |
||
| 432 | if (trob.type == 4 && |
||
| 433 | (sound_flags & sfDigi) |
||
| 434 | ) { |
||
| 435 | sound_interruptible[sound_15_leveldoor_sliding] = 1; |
||
| 436 | play_sound(sound_15_leveldoor_sliding); // level door sliding (closing) |
||
| 437 | } |
||
| 438 | } |
||
| 439 | } else { |
||
| 440 | // opening |
||
| 441 | ++curr_modifier; |
||
| 442 | if (curr_modifier >= 43) { |
||
| 443 | trob.type = -1; |
||
| 444 | #ifdef FIX_FEATHER_INTERRUPTED_BY_LEVELDOOR |
||
| 445 | if (!(fix_feather_interrupted_by_leveldoor && is_feather_fall)) |
||
| 446 | #endif |
||
| 447 | stop_sounds(); |
||
| 448 | if (leveldoor_open == 0 || leveldoor_open == 2) { |
||
| 449 | leveldoor_open = 1; |
||
| 450 | if (current_level == 4) { |
||
| 451 | // Special event: place mirror |
||
| 452 | get_tile(4, 4, 0); |
||
| 453 | curr_room_tiles[curr_tilepos] = tiles_13_mirror; |
||
| 454 | } |
||
| 455 | } |
||
| 456 | } else { |
||
| 457 | sound_interruptible[15] = 0; |
||
| 458 | play_sound(sound_15_leveldoor_sliding); // level door sliding (opening) |
||
| 459 | } |
||
| 460 | } |
||
| 461 | } |
||
| 462 | set_redraw_anim_right(); |
||
| 463 | } |
||
| 464 | |||
| 465 | // seg007:06AD |
||
| 466 | short __pascal far bubble_next_frame(short curr) { |
||
| 467 | short next; |
||
| 468 | next = curr + 1; |
||
| 469 | if (next >= 8) next = 1; |
||
| 470 | return next; |
||
| 471 | } |
||
| 472 | |||
| 473 | // seg007:06CD |
||
| 474 | short __pascal far get_torch_frame(short curr) { |
||
| 475 | short next; |
||
| 476 | next = prandom(255); |
||
| 477 | if (next != curr) { |
||
| 478 | if (next < 9) { |
||
| 479 | return next; |
||
| 480 | } else { |
||
| 481 | next = curr; |
||
| 482 | } |
||
| 483 | } |
||
| 484 | ++next; |
||
| 485 | if (next >= 9) next = 0; |
||
| 486 | return next; |
||
| 487 | } |
||
| 488 | |||
| 489 | // seg007:070A |
||
| 490 | void __pascal far set_redraw_anim(short tilepos, byte frames) { |
||
| 491 | if (tilepos < 30) { |
||
| 492 | if (tilepos < 0) { |
||
| 493 | ++tilepos; |
||
| 494 | redraw_frames_above[-tilepos] = frames; |
||
| 495 | // or simply: ~tilepos |
||
| 496 | } else { |
||
| 497 | redraw_frames_anim[tilepos] = frames; |
||
| 498 | } |
||
| 499 | } |
||
| 500 | } |
||
| 501 | |||
| 502 | // seg007:0738 |
||
| 503 | void __pascal far set_redraw2(short tilepos, byte frames) { |
||
| 504 | if (tilepos < 30) { |
||
| 505 | if (tilepos < 0) { |
||
| 506 | // trying to draw a mob at a negative tilepos, in the range -1 .. -10 |
||
| 507 | // used e.g. when the kid is climbing up to the room above |
||
| 508 | // however, loose tiles falling out of the room end up with a negative tilepos {-2 .. -11} ! |
||
| 509 | tilepos = (-tilepos) - 1; |
||
| 510 | if (tilepos > 9) tilepos = 9; // prevent array index out of bounds! |
||
| 511 | redraw_frames_above[tilepos] = frames; |
||
| 512 | } else { |
||
| 513 | redraw_frames2[tilepos] = frames; |
||
| 514 | } |
||
| 515 | } |
||
| 516 | } |
||
| 517 | |||
| 518 | // seg007:0766 |
||
| 519 | void __pascal far set_redraw_floor_overlay(short tilepos, byte frames) { |
||
| 520 | if (tilepos < 30) { |
||
| 521 | if (tilepos < 0) { |
||
| 522 | ++tilepos; |
||
| 523 | redraw_frames_above[-tilepos] = frames; |
||
| 524 | // or simply: ~tilepos |
||
| 525 | } else { |
||
| 526 | redraw_frames_floor_overlay[tilepos] = frames; |
||
| 527 | } |
||
| 528 | } |
||
| 529 | } |
||
| 530 | |||
| 531 | // seg007:0794 |
||
| 532 | void __pascal far set_redraw_full(short tilepos, byte frames) { |
||
| 533 | if (tilepos < 30) { |
||
| 534 | if (tilepos < 0) { |
||
| 535 | ++tilepos; |
||
| 536 | redraw_frames_above[-tilepos] = frames; |
||
| 537 | // or simply: ~tilepos |
||
| 538 | } else { |
||
| 539 | redraw_frames_full[tilepos] = frames; |
||
| 540 | } |
||
| 541 | } |
||
| 542 | } |
||
| 543 | |||
| 544 | // seg007:07C2 |
||
| 545 | void __pascal far set_redraw_fore(short tilepos, byte frames) { |
||
| 546 | if (tilepos < 30 && tilepos >= 0) { |
||
| 547 | redraw_frames_fore[tilepos] = frames; |
||
| 548 | } |
||
| 549 | } |
||
| 550 | |||
| 551 | // seg007:07DF |
||
| 552 | void __pascal far set_wipe(short tilepos, byte frames) { |
||
| 553 | if (tilepos < 30 && tilepos >= 0) { |
||
| 554 | if (wipe_frames[tilepos] != 0) { |
||
| 555 | redraw_height = MAX(wipe_heights[tilepos], redraw_height); |
||
| 556 | } |
||
| 557 | wipe_heights[tilepos] = redraw_height; |
||
| 558 | wipe_frames[tilepos] = frames; |
||
| 559 | } |
||
| 560 | } |
||
| 561 | |||
| 562 | // seg007:081E |
||
| 563 | void __pascal far start_anim_torch(short room,short tilepos) { |
||
| 564 | curr_room_modif[tilepos] = prandom(8); |
||
| 565 | add_trob(room, tilepos, 1); |
||
| 566 | } |
||
| 567 | |||
| 568 | // seg007:0847 |
||
| 569 | void __pascal far start_anim_potion(short room,short tilepos) { |
||
| 570 | curr_room_modif[tilepos] &= 0xF8; |
||
| 571 | curr_room_modif[tilepos] |= prandom(6) + 1; |
||
| 572 | add_trob(room, tilepos, 1); |
||
| 573 | } |
||
| 574 | |||
| 575 | // seg007:087C |
||
| 576 | void __pascal far start_anim_sword(short room,short tilepos) { |
||
| 577 | curr_room_modif[tilepos] = prandom(0xFF) & 0x1F; |
||
| 578 | add_trob(room, tilepos, 1); |
||
| 579 | } |
||
| 580 | |||
| 581 | // seg007:08A7 |
||
| 582 | void __pascal far start_anim_chomper(short room,short tilepos, byte modifier) { |
||
| 583 | short old_modifier; |
||
| 584 | old_modifier = curr_room_modif[tilepos]; |
||
| 585 | if (old_modifier == 0 || old_modifier >= 6) { |
||
| 586 | curr_room_modif[tilepos] = modifier; |
||
| 587 | add_trob(room, tilepos, 1); |
||
| 588 | } |
||
| 589 | } |
||
| 590 | |||
| 591 | // seg007:08E3 |
||
| 592 | void __pascal far start_anim_spike(short room,short tilepos) { |
||
| 593 | sbyte old_modifier; |
||
| 594 | old_modifier = curr_room_modif[tilepos]; |
||
| 595 | if (old_modifier <= 0) { |
||
| 596 | if (old_modifier == 0) { |
||
| 597 | add_trob(room, tilepos, 1); |
||
| 598 | play_sound(sound_49_spikes); // spikes |
||
| 599 | } else { |
||
| 600 | // 0xFF means a disabled spike. |
||
| 601 | if (old_modifier != (sbyte)0xFF) { |
||
| 602 | curr_room_modif[tilepos] = 0x8F; |
||
| 603 | } |
||
| 604 | } |
||
| 605 | } |
||
| 606 | } |
||
| 607 | |||
| 608 | // seg007:092C |
||
| 609 | short __pascal far trigger_gate(short room,short tilepos,short button_type) { |
||
| 610 | byte modifier; |
||
| 611 | modifier = curr_room_modif[tilepos]; |
||
| 612 | if (button_type == tiles_15_opener) { |
||
| 613 | // If the gate is permanently open, don't to anything. |
||
| 614 | if (modifier == 0xFF) return -1; |
||
| 615 | if (modifier >= 188) { // if it's already open |
||
| 616 | curr_room_modif[tilepos] = 238; // keep it open for a while |
||
| 617 | return -1; |
||
| 618 | } |
||
| 619 | curr_room_modif[tilepos] = (modifier + 3) & 0xFC; |
||
| 620 | return 1; // regular open |
||
| 621 | } else if (button_type == tiles_14_debris) { |
||
| 622 | // If it's not fully open: |
||
| 623 | if (modifier < 188) return 2; // permanent open |
||
| 624 | curr_room_modif[tilepos] = 0xFF; // keep open |
||
| 625 | return -1; |
||
| 626 | } else { |
||
| 627 | if (modifier != 0) { |
||
| 628 | return 3; // close fast |
||
| 629 | } else { |
||
| 630 | // already closed |
||
| 631 | return -1; |
||
| 632 | } |
||
| 633 | } |
||
| 634 | } |
||
| 635 | |||
| 636 | // seg007:0999 |
||
| 637 | short __pascal far trigger_1(short target_type,short room,short tilepos,short button_type) { |
||
| 638 | short result; |
||
| 639 | result = -1; |
||
| 640 | if (target_type == tiles_4_gate) { |
||
| 641 | result = trigger_gate(room, tilepos, button_type); |
||
| 642 | } else if (target_type == tiles_16_level_door_left) { |
||
| 643 | if (curr_room_modif[tilepos] != 0) { |
||
| 644 | result = -1; |
||
| 645 | } else { |
||
| 646 | result = 1; |
||
| 647 | } |
||
| 648 | } else if (allow_triggering_any_tile) { //allow_triggering_any_tile hack |
||
| 649 | result = 1; |
||
| 650 | } |
||
| 651 | return result; |
||
| 652 | } |
||
| 653 | |||
| 654 | // seg007:09E5 |
||
| 655 | void __pascal far do_trigger_list(short index,short button_type) { |
||
| 656 | word room; |
||
| 657 | word tilepos; |
||
| 658 | byte target_type; |
||
| 659 | sbyte trigger_result; |
||
| 660 | // while (doorlink1_ad[index] != -1) { // these can't be equal! |
||
| 661 | while (1) { // Same as the above but just a little faster and no compiler warning. |
||
| 662 | room = get_doorlink_room(index); |
||
| 663 | get_room_address(room); |
||
| 664 | tilepos = get_doorlink_tile(index); |
||
| 665 | target_type = curr_room_tiles[tilepos] & 0x1F; |
||
| 666 | trigger_result = trigger_1(target_type, room, tilepos, button_type); |
||
| 667 | if (trigger_result >= 0) { |
||
| 668 | add_trob(room, tilepos, trigger_result); |
||
| 669 | } |
||
| 670 | if (get_doorlink_next(index++) == 0) break; |
||
| 671 | } |
||
| 672 | } |
||
| 673 | |||
| 674 | // seg007:0A5A |
||
| 675 | void __pascal far add_trob(byte room,byte tilepos,sbyte type) { |
||
| 676 | short found; |
||
| 677 | if (trobs_count >= 30) { |
||
| 678 | show_dialog("Trobs Overflow"); |
||
| 679 | return /*0*/; // added |
||
| 680 | } |
||
| 681 | trob.room = room; |
||
| 682 | trob.tilepos = tilepos; |
||
| 683 | trob.type = type; |
||
| 684 | found = find_trob(); |
||
| 685 | if (found == -1) { |
||
| 686 | // add new |
||
| 687 | if (trobs_count == 30) return; |
||
| 688 | trobs[trobs_count++] = trob; |
||
| 689 | } else { |
||
| 690 | // change existing |
||
| 691 | trobs[found].type = trob.type; |
||
| 692 | } |
||
| 693 | } |
||
| 694 | |||
| 695 | // seg007:0ACA |
||
| 696 | short __pascal far find_trob() { |
||
| 697 | short index; |
||
| 698 | for (index = 0; index < trobs_count; ++index) { |
||
| 699 | if (trobs[index].tilepos == trob.tilepos && |
||
| 700 | trobs[index].room == trob.room) return index; |
||
| 701 | } |
||
| 702 | return -1; |
||
| 703 | } |
||
| 704 | |||
| 705 | // seg007:0B0A |
||
| 706 | void __pascal far clear_tile_wipes() { |
||
| 707 | memset_near(redraw_frames_full, 0, sizeof(redraw_frames_full)); |
||
| 708 | memset_near(wipe_frames, 0, sizeof(wipe_frames)); |
||
| 709 | memset_near(wipe_heights, 0, sizeof(wipe_heights)); |
||
| 710 | memset_near(redraw_frames_anim, 0, sizeof(redraw_frames_anim)); |
||
| 711 | memset_near(redraw_frames_fore, 0, sizeof(redraw_frames_fore)); |
||
| 712 | memset_near(redraw_frames2, 0, sizeof(redraw_frames2)); |
||
| 713 | memset_near(redraw_frames_floor_overlay, 0, sizeof(redraw_frames_floor_overlay)); |
||
| 714 | memset_near(tile_object_redraw, 0, sizeof(tile_object_redraw)); |
||
| 715 | memset_near(redraw_frames_above, 0, sizeof(redraw_frames_above)); |
||
| 716 | } |
||
| 717 | |||
| 718 | // seg007:0BB6 |
||
| 719 | short __pascal far get_doorlink_timer(short index) { |
||
| 720 | return doorlink2_ad[index] & 0x1F; |
||
| 721 | } |
||
| 722 | |||
| 723 | // seg007:0BCD |
||
| 724 | short __pascal far set_doorlink_timer(short index,byte value) { |
||
| 725 | doorlink2_ad[index] &= 0xE0; |
||
| 726 | doorlink2_ad[index] |= value & 0x1F; |
||
| 727 | return doorlink2_ad[index]; |
||
| 728 | } |
||
| 729 | |||
| 730 | // seg007:0BF2 |
||
| 731 | short __pascal far get_doorlink_tile(short index) { |
||
| 732 | return doorlink1_ad[index] & 0x1F; |
||
| 733 | } |
||
| 734 | |||
| 735 | // seg007:0C09 |
||
| 736 | short __pascal far get_doorlink_next(short index) { |
||
| 737 | return !(doorlink1_ad[index] & 0x80); |
||
| 738 | } |
||
| 739 | |||
| 740 | // seg007:0C26 |
||
| 741 | short __pascal far get_doorlink_room(short index) { |
||
| 742 | return |
||
| 743 | ((doorlink1_ad[index] & 0x60) >> 5) + |
||
| 744 | ((doorlink2_ad[index] & 0xE0) >> 3); |
||
| 745 | } |
||
| 746 | |||
| 747 | // seg007:0C53 |
||
| 748 | void __pascal far trigger_button(int playsound,int button_type,int modifier) { |
||
| 749 | sbyte link_timer; |
||
| 750 | get_curr_tile(curr_tilepos); |
||
| 751 | if (button_type == 0) { |
||
| 752 | // 0 means currently selected |
||
| 753 | button_type = curr_tile; |
||
| 754 | } |
||
| 755 | if (modifier == -1) { |
||
| 756 | // -1 means currently selected |
||
| 757 | modifier = curr_modifier; |
||
| 758 | } |
||
| 759 | link_timer = get_doorlink_timer(modifier); |
||
| 760 | // is the event jammed? |
||
| 761 | if (link_timer != 0x1F) { |
||
| 762 | set_doorlink_timer(modifier, 5); |
||
| 763 | if (link_timer < 2) { |
||
| 764 | add_trob(curr_room, curr_tilepos, 1); |
||
| 765 | redraw_11h(); |
||
| 766 | is_guard_notice = 1; |
||
| 767 | if (playsound) { |
||
| 768 | play_sound(sound_3_button_pressed); // button pressed |
||
| 769 | } |
||
| 770 | } |
||
| 771 | do_trigger_list(modifier, button_type); |
||
| 772 | } |
||
| 773 | } |
||
| 774 | |||
| 775 | // seg007:0CD9 |
||
| 776 | void __pascal far died_on_button() { |
||
| 777 | word button_type; |
||
| 778 | word modifier; |
||
| 779 | button_type = get_curr_tile(curr_tilepos); |
||
| 780 | modifier = curr_modifier; |
||
| 781 | if (curr_tile == tiles_15_opener) { |
||
| 782 | curr_room_tiles[curr_tilepos] = tiles_1_floor; |
||
| 783 | curr_room_modif[curr_tilepos] = 0; |
||
| 784 | button_type = tiles_14_debris; // force permanent open |
||
| 785 | } else { |
||
| 786 | curr_room_tiles[curr_tilepos] = tiles_5_stuck; |
||
| 787 | } |
||
| 788 | trigger_button(1, button_type, modifier); |
||
| 789 | } |
||
| 790 | |||
| 791 | // seg007:0D3A |
||
| 792 | void __pascal far animate_button() { |
||
| 793 | word var_2; |
||
| 794 | if (trob.type >= 0) { |
||
| 795 | set_doorlink_timer(curr_modifier, var_2 = get_doorlink_timer(curr_modifier) - 1); |
||
| 796 | if (var_2 < 2) { |
||
| 797 | trob.type = -1; |
||
| 798 | redraw_11h(); |
||
| 799 | } |
||
| 800 | } |
||
| 801 | } |
||
| 802 | |||
| 803 | // seg007:0D72 |
||
| 804 | void __pascal far start_level_door(short room,short tilepos) { |
||
| 805 | curr_room_modif[tilepos] = 43; // start fully open |
||
| 806 | add_trob(room, tilepos, 3); |
||
| 807 | } |
||
| 808 | |||
| 809 | // seg007:0D93 |
||
| 810 | void __pascal far animate_empty() { |
||
| 811 | trob.type = -1; |
||
| 812 | redraw_20h(); |
||
| 813 | } |
||
| 814 | |||
| 815 | // data:2284 |
||
| 816 | const word y_loose_land[] = {2, 65, 128, 191, 254}; |
||
| 817 | // seg007:0D9D |
||
| 818 | void __pascal far animate_loose() { |
||
| 819 | word room; |
||
| 820 | word row; |
||
| 821 | word tilepos; |
||
| 822 | short anim_type; |
||
| 823 | anim_type = trob.type; |
||
| 824 | if (anim_type >= 0) { |
||
| 825 | ++curr_modifier; |
||
| 826 | if (curr_modifier & 0x80) { |
||
| 827 | // just shaking |
||
| 828 | // don't shake on level 13 |
||
| 829 | if (current_level == 13) return; |
||
| 830 | if (curr_modifier >= 0x84) { |
||
| 831 | curr_modifier = 0; |
||
| 832 | trob.type = -1; |
||
| 833 | } |
||
| 834 | loose_shake(!curr_modifier); |
||
| 835 | } else { |
||
| 836 | // something is on the floor |
||
| 837 | // should it fall already? |
||
| 838 | if (curr_modifier >= 11) { |
||
| 839 | curr_modifier = remove_loose(room = trob.room, tilepos = trob.tilepos); |
||
| 840 | trob.type = -1; |
||
| 841 | curmob.xh = (tilepos % 10) << 2; |
||
| 842 | row = tilepos / 10; |
||
| 843 | curmob.y = y_loose_land[row + 1]; |
||
| 844 | curmob.room = room; |
||
| 845 | curmob.speed = 0; |
||
| 846 | curmob.type = 0; |
||
| 847 | curmob.row = row; |
||
| 848 | add_mob(); |
||
| 849 | } else { |
||
| 850 | loose_shake(0); |
||
| 851 | } |
||
| 852 | } |
||
| 853 | } |
||
| 854 | redraw_20h(); |
||
| 855 | } |
||
| 856 | |||
| 857 | // data:2734 |
||
| 858 | const byte loose_sound[] = {0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0}; |
||
| 859 | // seg007:0E55 |
||
| 860 | void __pascal far loose_shake(int arg_0) { |
||
| 861 | word sound_id; |
||
| 862 | if (arg_0 || loose_sound[curr_modifier & 0x7F]) { |
||
| 863 | do { |
||
| 864 | // Sounds 20,21,22: loose floor shaking |
||
| 865 | sound_id = prandom(2) + sound_20_loose_shake_1; |
||
| 866 | } while(sound_id == last_loose_sound); |
||
| 867 | if (sound_flags & sfDigi) { |
||
| 868 | last_loose_sound = sound_id; |
||
| 869 | // random sample rate (10500..11500) |
||
| 870 | //sound_pointers[sound_id]->samplerate = prandom(1000) + 10500; |
||
| 871 | } |
||
| 872 | play_sound(sound_id); |
||
| 873 | } |
||
| 874 | } |
||
| 875 | |||
| 876 | // seg007:0EB8 |
||
| 877 | int __pascal far remove_loose(int room, int tilepos) { |
||
| 878 | curr_room_tiles[tilepos] = tiles_0_empty; |
||
| 879 | // note: the level type is used to determine the modifier of the empty space left behind |
||
| 880 | return tbl_level_type[current_level]; |
||
| 881 | } |
||
| 882 | |||
| 883 | // seg007:0ED5 |
||
| 884 | void __pascal far make_loose_fall(byte modifier) { |
||
| 885 | // is it a "solid" loose floor? |
||
| 886 | if ((curr_room_tiles[curr_tilepos] & 0x20) == 0) { |
||
| 887 | if ((sbyte)curr_room_modif[curr_tilepos] <= 0) { |
||
| 888 | curr_room_modif[curr_tilepos] = modifier; |
||
| 889 | add_trob(curr_room, curr_tilepos, 0); |
||
| 890 | redraw_20h(); |
||
| 891 | } |
||
| 892 | } |
||
| 893 | } |
||
| 894 | |||
| 895 | // seg007:0F13 |
||
| 896 | void __pascal far start_chompers() { |
||
| 897 | short timing; |
||
| 898 | short modifier; |
||
| 899 | short tilepos; |
||
| 900 | short column; |
||
| 901 | timing = 15; |
||
| 902 | if ((byte)Char.curr_row < 3) { |
||
| 903 | get_room_address(Char.room); |
||
| 904 | for (column = 0, tilepos = tbl_line[Char.curr_row]; |
||
| 905 | column < 10; ++column, ++tilepos |
||
| 906 | ){ |
||
| 907 | if (get_curr_tile(tilepos) == tiles_18_chomper) { |
||
| 908 | modifier = curr_modifier & 0x7F; |
||
| 909 | if (modifier == 0 || modifier >= 6) { |
||
| 910 | start_anim_chomper(Char.room, tilepos, timing | (curr_modifier & 0x80)); |
||
| 911 | timing = next_chomper_timing(timing); |
||
| 912 | } |
||
| 913 | } |
||
| 914 | } |
||
| 915 | } |
||
| 916 | } |
||
| 917 | |||
| 918 | // seg007:0F9A |
||
| 919 | int __pascal far next_chomper_timing(byte timing) { |
||
| 920 | // 15,12,9,6,13,10,7,14,11,8,repeat |
||
| 921 | timing -= 3; |
||
| 922 | if (timing < 6) { |
||
| 923 | timing += 10; |
||
| 924 | } |
||
| 925 | return timing; |
||
| 926 | } |
||
| 927 | |||
| 928 | // seg007:0FB4 |
||
| 929 | void __pascal far loose_make_shake() { |
||
| 930 | if (curr_room_modif[curr_tilepos] == 0 && current_level != 13) { |
||
| 931 | curr_room_modif[curr_tilepos] = 0x80; |
||
| 932 | add_trob(curr_room, curr_tilepos, 1); |
||
| 933 | } |
||
| 934 | } |
||
| 935 | |||
| 936 | // seg007:0FE0 |
||
| 937 | void __pascal far do_knock(int room,int tile_row) { |
||
| 938 | short tile_col; |
||
| 939 | for (tile_col = 0; tile_col < 10; ++tile_col) { |
||
| 940 | if (get_tile(room, tile_col, tile_row) == tiles_11_loose) { |
||
| 941 | loose_make_shake(); |
||
| 942 | } |
||
| 943 | } |
||
| 944 | } |
||
| 945 | |||
| 946 | // seg007:1010 |
||
| 947 | void __pascal far add_mob() { |
||
| 948 | if (mobs_count >= 14) { |
||
| 949 | show_dialog("Mobs Overflow"); |
||
| 950 | return /*0*/; // added |
||
| 951 | } |
||
| 952 | mobs[mobs_count++] = curmob; |
||
| 953 | } |
||
| 954 | |||
| 955 | // seg007:1041 |
||
| 956 | short __pascal far get_curr_tile(short tilepos) { |
||
| 957 | curr_modifier = curr_room_modif[tilepos]; |
||
| 958 | return curr_tile = curr_room_tiles[tilepos] & 0x1F; |
||
| 959 | } |
||
| 960 | |||
| 961 | // data:43DC |
||
| 962 | word curmob_index; |
||
| 963 | |||
| 964 | // seg007:1063 |
||
| 965 | void __pascal far do_mobs() { |
||
| 966 | short n_mobs; |
||
| 967 | short index; |
||
| 968 | short new_index; |
||
| 969 | n_mobs = mobs_count; |
||
| 970 | for (curmob_index = 0; n_mobs > curmob_index; ++curmob_index) { |
||
| 971 | curmob = mobs[curmob_index]; |
||
| 972 | move_mob(); |
||
| 973 | check_loose_fall_on_kid(); |
||
| 974 | mobs[curmob_index] = curmob; |
||
| 975 | } |
||
| 976 | new_index = 0; |
||
| 977 | for (index = 0; index < mobs_count; ++index) { |
||
| 978 | if (mobs[index].speed != -1) { |
||
| 979 | mobs[new_index++] = mobs[index]; |
||
| 980 | } |
||
| 981 | } |
||
| 982 | mobs_count = new_index; |
||
| 983 | } |
||
| 984 | |||
| 985 | // seg007:110F |
||
| 986 | void __pascal far move_mob() { |
||
| 987 | if (curmob.type == 0) { |
||
| 988 | move_loose(); |
||
| 989 | } |
||
| 990 | if (curmob.speed <= 0) { |
||
| 991 | ++curmob.speed; |
||
| 992 | } |
||
| 993 | } |
||
| 994 | |||
| 995 | // data:227A |
||
| 996 | const short y_something[] = {-1, 62, 125, 188, 25}; |
||
| 997 | // data:594A |
||
| 998 | word curr_tile_temp; |
||
| 999 | // seg007:1126 |
||
| 1000 | void __pascal far move_loose() { |
||
| 1001 | if (curmob.speed < 0) return; |
||
| 1002 | if (curmob.speed < 29) curmob.speed += 3; |
||
| 1003 | curmob.y += curmob.speed; |
||
| 1004 | if (curmob.room == 0) { |
||
| 1005 | if (curmob.y < 210) { |
||
| 1006 | return; |
||
| 1007 | } else { |
||
| 1008 | curmob.speed = -2; |
||
| 1009 | return; |
||
| 1010 | } |
||
| 1011 | } |
||
| 1012 | if (curmob.y < 226 && y_something[curmob.row + 1] <= curmob.y) { |
||
| 1013 | // fell into a different row |
||
| 1014 | curr_tile_temp = get_tile(curmob.room, curmob.xh >> 2, curmob.row); |
||
| 1015 | if (curr_tile_temp == tiles_11_loose) { |
||
| 1016 | loose_fall(); |
||
| 1017 | } |
||
| 1018 | if (curr_tile_temp == tiles_0_empty || |
||
| 1019 | curr_tile_temp == tiles_11_loose |
||
| 1020 | ) { |
||
| 1021 | mob_down_a_row(); |
||
| 1022 | return; |
||
| 1023 | } |
||
| 1024 | play_sound(sound_2_tile_crashing); // tile crashing |
||
| 1025 | do_knock(curmob.room, curmob.row); |
||
| 1026 | curmob.y = y_something[curmob.row + 1]; |
||
| 1027 | curmob.speed = -2; |
||
| 1028 | loose_land(); |
||
| 1029 | } |
||
| 1030 | } |
||
| 1031 | |||
| 1032 | // seg007:11E8 |
||
| 1033 | void __pascal far loose_land() { |
||
| 1034 | short button_type; |
||
| 1035 | short tiletype; |
||
| 1036 | button_type = 0; |
||
| 1037 | tiletype = get_tile(curmob.room, curmob.xh >> 2, curmob.row); |
||
| 1038 | switch (tiletype) { |
||
| 1039 | case tiles_15_opener: |
||
| 1040 | curr_room_tiles[curr_tilepos] = tiles_14_debris; |
||
| 1041 | button_type = tiles_14_debris; |
||
| 1042 | // fallthrough! |
||
| 1043 | case tiles_6_closer: |
||
| 1044 | trigger_button(1, button_type, -1); |
||
| 1045 | tiletype = get_tile(curmob.room, curmob.xh >> 2, curmob.row); |
||
| 1046 | // fallthrough! |
||
| 1047 | case tiles_1_floor: |
||
| 1048 | case tiles_2_spike: |
||
| 1049 | case tiles_10_potion: |
||
| 1050 | case tiles_19_torch: |
||
| 1051 | case tiles_30_torch_with_debris: |
||
| 1052 | if (tiletype == tiles_19_torch || |
||
| 1053 | tiletype == tiles_30_torch_with_debris |
||
| 1054 | ) { |
||
| 1055 | curr_room_tiles[curr_tilepos] = tiles_30_torch_with_debris; |
||
| 1056 | } else { |
||
| 1057 | curr_room_tiles[curr_tilepos] = tiles_14_debris; |
||
| 1058 | } |
||
| 1059 | redraw_at_cur_mob(); |
||
| 1060 | if (tile_col != 0) { |
||
| 1061 | set_redraw_full(curr_tilepos - 1, 1); |
||
| 1062 | } |
||
| 1063 | } |
||
| 1064 | } |
||
| 1065 | |||
| 1066 | // seg007:12CB |
||
| 1067 | void __pascal far loose_fall() { |
||
| 1068 | curr_room_modif[curr_tilepos] = remove_loose(curr_room, curr_tilepos); |
||
| 1069 | curmob.speed >>= 1; |
||
| 1070 | mobs[curmob_index] = curmob; |
||
| 1071 | curmob.y += 6; |
||
| 1072 | mob_down_a_row(); |
||
| 1073 | add_mob(); |
||
| 1074 | curmob = mobs[curmob_index]; |
||
| 1075 | redraw_at_cur_mob(); |
||
| 1076 | } |
||
| 1077 | |||
| 1078 | // seg007:132C |
||
| 1079 | void __pascal far redraw_at_cur_mob() { |
||
| 1080 | if (curmob.room == drawn_room) { |
||
| 1081 | redraw_height = 0x20; |
||
| 1082 | set_redraw_full(curr_tilepos, 1); |
||
| 1083 | set_wipe(curr_tilepos, 1); |
||
| 1084 | // Redraw tile to the right only if it's in the same room. |
||
| 1085 | if ((curr_tilepos % 10) + 1 < 10) { // changed |
||
| 1086 | set_redraw_full(curr_tilepos + 1, 1); |
||
| 1087 | set_wipe(curr_tilepos + 1, 1); |
||
| 1088 | } |
||
| 1089 | } |
||
| 1090 | } |
||
| 1091 | |||
| 1092 | // seg007:1387 |
||
| 1093 | void __pascal far mob_down_a_row() { |
||
| 1094 | ++curmob.row; |
||
| 1095 | if (curmob.row >= 3) { |
||
| 1096 | curmob.y -= 192; |
||
| 1097 | curmob.row = 0; |
||
| 1098 | curmob.room = level.roomlinks[curmob.room - 1].down; |
||
| 1099 | } |
||
| 1100 | } |
||
| 1101 | |||
| 1102 | // seg007:13AE |
||
| 1103 | void __pascal far draw_mobs() { |
||
| 1104 | short index; |
||
| 1105 | for (index = 0; index < mobs_count; ++index) { |
||
| 1106 | curmob = mobs[index]; |
||
| 1107 | draw_mob(); |
||
| 1108 | } |
||
| 1109 | } |
||
| 1110 | |||
| 1111 | // seg007:13E5 |
||
| 1112 | void __pascal far draw_mob() { |
||
| 1113 | short tile_row; |
||
| 1114 | short ypos; |
||
| 1115 | short top_row; |
||
| 1116 | short tilepos; |
||
| 1117 | short tile_col; |
||
| 1118 | ypos = curmob.y; |
||
| 1119 | if (curmob.room == drawn_room) { |
||
| 1120 | if (curmob.y >= 210) return; |
||
| 1121 | } else if (curmob.room == room_B) { |
||
| 1122 | if (ABS(ypos) >= 18) return; |
||
| 1123 | curmob.y += 192; |
||
| 1124 | ypos = curmob.y; |
||
| 1125 | } else if (curmob.room == room_A) { |
||
| 1126 | if (curmob.y < 174) return; |
||
| 1127 | ypos = curmob.y - 189; |
||
| 1128 | } else { |
||
| 1129 | return; |
||
| 1130 | } |
||
| 1131 | tile_col = curmob.xh >> 2; |
||
| 1132 | tile_row = y_to_row_mod4(ypos); |
||
| 1133 | obj_tilepos = get_tilepos_nominus(tile_col, tile_row); |
||
| 1134 | ++tile_col; |
||
| 1135 | tilepos = get_tilepos(tile_col, tile_row); |
||
| 1136 | set_redraw2(tilepos, 1); |
||
| 1137 | set_redraw_fore(tilepos, 1); |
||
| 1138 | top_row = y_to_row_mod4(ypos - 18); |
||
| 1139 | if (top_row != tile_row) { |
||
| 1140 | tilepos = get_tilepos(tile_col, top_row); |
||
| 1141 | set_redraw2(tilepos, 1); |
||
| 1142 | set_redraw_fore(tilepos, 1); |
||
| 1143 | } |
||
| 1144 | add_mob_to_objtable(ypos); |
||
| 1145 | } |
||
| 1146 | |||
| 1147 | // seg007:14DE |
||
| 1148 | void __pascal far add_mob_to_objtable(int ypos) { |
||
| 1149 | word index; |
||
| 1150 | objtable_type* curr_obj; |
||
| 1151 | index = objtable_count++; |
||
| 1152 | curr_obj = &objtable[index]; |
||
| 1153 | curr_obj->obj_type = curmob.type | 0x80; |
||
| 1154 | curr_obj->xh = curmob.xh; |
||
| 1155 | curr_obj->xl = 0; |
||
| 1156 | curr_obj->y = ypos; |
||
| 1157 | curr_obj->chtab_id = id_chtab_6_environment; |
||
| 1158 | curr_obj->id = 10; |
||
| 1159 | curr_obj->clip.top = 0; |
||
| 1160 | curr_obj->clip.left = 0; |
||
| 1161 | curr_obj->clip.right = 40; |
||
| 1162 | mark_obj_tile_redraw(index); |
||
| 1163 | } |
||
| 1164 | |||
| 1165 | // seg007:153E |
||
| 1166 | void __pascal far sub_9A8E() { |
||
| 1167 | // This function is not used. |
||
| 1168 | method_1_blit_rect(onscreen_surface_, offscreen_surface, &rect_top, &rect_top, 0); |
||
| 1169 | } |
||
| 1170 | |||
| 1171 | // seg007:1556 |
||
| 1172 | int __pascal far is_spike_harmful() { |
||
| 1173 | sbyte modifier; |
||
| 1174 | modifier = curr_room_modif[curr_tilepos]; |
||
| 1175 | if (modifier == 0 || modifier == -1) { |
||
| 1176 | return 0; |
||
| 1177 | } else if (modifier < 0) { |
||
| 1178 | return 1; |
||
| 1179 | } else if (modifier < 5) { |
||
| 1180 | return 2; |
||
| 1181 | } else { |
||
| 1182 | return 0; |
||
| 1183 | } |
||
| 1184 | } |
||
| 1185 | |||
| 1186 | // seg007:1591 |
||
| 1187 | void __pascal far check_loose_fall_on_kid() { |
||
| 1188 | loadkid(); |
||
| 1189 | if (Char.room == curmob.room && |
||
| 1190 | Char.curr_col == curmob.xh >> 2 && |
||
| 1191 | curmob.y < Char.y && |
||
| 1192 | Char.y - 30 < curmob.y |
||
| 1193 | ) { |
||
| 1194 | fell_on_your_head(); |
||
| 1195 | savekid(); |
||
| 1196 | } |
||
| 1197 | } |
||
| 1198 | |||
| 1199 | // seg007:15D3 |
||
| 1200 | void __pascal far fell_on_your_head() { |
||
| 1201 | short frame; |
||
| 1202 | short action; |
||
| 1203 | frame = Char.frame; |
||
| 1204 | action = Char.action; |
||
| 1205 | // loose floors hurt you in frames 5..14 (running) only on level 13 |
||
| 1206 | if ( |
||
| 1207 | (current_level == 13 || (frame < frame_5_start_run || frame >= 15)) && |
||
| 1208 | (action < actions_2_hang_climb || action == actions_7_turn) |
||
| 1209 | ) { |
||
| 1210 | Char.y = y_land[Char.curr_row + 1]; |
||
| 1211 | if (take_hp(1)) { |
||
| 1212 | seqtbl_offset_char(seq_22_crushed); // dead (because of loose floor) |
||
| 1213 | if (frame == frame_177_spiked) { // spiked |
||
| 1214 | Char.x = char_dx_forward(-12); |
||
| 1215 | } |
||
| 1216 | } else { |
||
| 1217 | if (frame != frame_109_crouch) { // crouching |
||
| 1218 | if (get_tile_behind_char() == 0) { |
||
| 1219 | Char.x = char_dx_forward(-2); |
||
| 1220 | } |
||
| 1221 | seqtbl_offset_char(seq_52_loose_floor_fell_on_kid); // loose floor fell on Kid |
||
| 1222 | } |
||
| 1223 | } |
||
| 1224 | } |
||
| 1225 | } |
||
| 1226 | |||
| 1227 | // seg007:1669 |
||
| 1228 | void __pascal far play_door_sound_if_visible(int sound_id) { |
||
| 1229 | word has_sound; |
||
| 1230 | word tilepos; |
||
| 1231 | word gate_room; |
||
| 1232 | tilepos = trob.tilepos; |
||
| 1233 | gate_room = trob.room; |
||
| 1234 | has_sound = 0; |
||
| 1235 | |||
| 1236 | #ifdef FIX_GATE_SOUNDS |
||
| 1237 | sbyte has_sound_condition; |
||
| 1238 | if (fix_gate_sounds) |
||
| 1239 | has_sound_condition = (gate_room == room_L && tilepos % 10 == 9) || |
||
| 1240 | (gate_room == drawn_room && tilepos % 10 != 9); |
||
| 1241 | else |
||
| 1242 | has_sound_condition = gate_room == room_L ? tilepos % 10 == 9 : |
||
| 1243 | (gate_room == drawn_room && tilepos % 10 != 9); |
||
| 1244 | #define GATE_SOUND_CONDITION has_sound_condition |
||
| 1245 | #else |
||
| 1246 | #define GATE_SOUND_CONDITION gate_room == room_L ? tilepos % 10 == 9 : \ |
||
| 1247 | (gate_room == drawn_room && tilepos % 10 != 9) |
||
| 1248 | #endif |
||
| 1249 | // Special event: sound of closing gates |
||
| 1250 | if ((current_level == 3 && gate_room == 2) || GATE_SOUND_CONDITION) { |
||
| 1251 | has_sound = 1; |
||
| 1252 | } |
||
| 1253 | if (has_sound) { |
||
| 1254 | play_sound(sound_id); |
||
| 1255 | } |
||
| 1256 | } |