Subversion Repositories Games.Prince of Persia

Rev

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:3D1A
24
sbyte distance_mirror;
25
 
26
// seg003:0000
27
void __pascal far init_game(int level) {
28
        if(offscreen_surface) {
29
                free_surface(offscreen_surface); // missing in original
30
                offscreen_surface = NULL;
31
        }
32
        offscreen_surface = make_offscreen_buffer(&rect_top);
33
        load_kid_sprite();
34
        text_time_remaining = 0;
35
        text_time_total = 0;
36
        is_show_time = 0;
37
        checkpoint = 0;
38
        upside_down = 0; // N.B. upside_down is also reset in set_start_pos()
39
        resurrect_time = 0;
40
        if (!dont_reset_time) {
41
                rem_min = start_minutes_left;   // 60
42
                rem_tick = start_ticks_left;    // 719
43
                hitp_beg_lev = start_hitp;      // 3
44
        }
45
        need_level1_music = (level == 1);
46
        play_level(level);
47
}
48
 
49
// seg003:005C
50
void __pascal far play_level(int level_number) {
51
        cutscene_ptr_type cutscene_func;
52
#ifdef USE_COPYPROT
53
        if (enable_copyprot && level_number == copyprot_level) {
54
                level_number = 15;
55
        }
56
#endif
57
        for (;;) {
58
                if (demo_mode && level_number > 2) {
59
                        start_level = -1;
60
                        need_quotes = 1;
61
                        start_game();
62
                }
63
                if (level_number != current_level) {
64
                        if (level_number <0 || level_number >15) {
65
                                printf("Tried to load cutscene for level %d, not in 0..15\n", level_number);
66
                                quit(1);
67
                        }
68
                        cutscene_func = tbl_cutscenes[level_number];
69
                        if (cutscene_func != NULL
70
 
71
                                #ifdef USE_REPLAY
72
                                && !(recording || replaying)
73
                                #endif
74
#ifdef USE_SCREENSHOT
75
                                && !want_auto_screenshot()
76
#endif
77
                                        ) {
78
                                load_intro(level_number > 2, cutscene_func, 1);
79
                        }
80
                }
81
                if (level_number != current_level) {
82
                        load_lev_spr(level_number);
83
                }
84
                load_level();
85
                pos_guards();
86
                clear_coll_rooms();
87
                clear_saved_ctrl();
88
                drawn_room = 0;
89
                mobs_count = 0;
90
                trobs_count = 0;
91
                next_sound = -1;
92
                holding_sword = 0;
93
                grab_timer = 0;
94
                can_guard_see_kid = 0;
95
                united_with_shadow = 0;
96
                flash_time = 0;
97
                leveldoor_open = 0;
98
                demo_index = 0;
99
                demo_time = 0;
100
                guardhp_curr = 0;
101
                hitp_delta = 0;
102
                Guard.charid = charid_2_guard;
103
                Guard.direction = dir_56_none;
104
                do_startpos();
105
                have_sword = (level_number != 1);
106
                find_start_level_door();
107
                // busy waiting?
108
                while (check_sound_playing() && !do_paused()) idle();
109
                stop_sounds();
110
                #ifdef USE_REPLAY
111
                if (replaying) replay_restore_level();
112
                if (skipping_replay) {
113
                        if (replay_seek_target == replay_seek_0_next_room ||
114
                                replay_seek_target == replay_seek_1_next_level
115
                        )
116
                                skipping_replay = 0; // resume replay from here
117
                }
118
                #endif
119
                draw_level_first();
120
                show_copyprot(0);
121
                level_number = play_level_2();
122
                // hacked...
123
#ifdef USE_COPYPROT
124
                if (enable_copyprot && level_number == copyprot_level && !demo_mode) {
125
                        level_number = 15;
126
                } else {
127
                        if (level_number == 16) {
128
                                level_number = copyprot_level;
129
                                copyprot_level = -1;
130
                        }
131
                }
132
#endif
133
                free_peels();
134
        }
135
}
136
 
137
// seg003:01A3
138
void __pascal far do_startpos() {
139
        word x;
140
        // Special event: start at checkpoint
141
        if (current_level == 3 && checkpoint) {
142
                level.start_dir = dir_FF_left;
143
                level.start_room = 2;
144
                level.start_pos = 6;
145
                // Special event: remove loose floor
146
                get_tile(7, 4, 0);
147
                curr_room_tiles[curr_tilepos] = tiles_0_empty;
148
        }
149
        next_room = Char.room = level.start_room;
150
        x = level.start_pos;
151
        Char.curr_col = x % 10;
152
        Char.curr_row = x / 10;
153
        Char.x = x_bump[Char.curr_col + 5] + 14;
154
        // Start in the opposite direction (and turn into the correct one).
155
        Char.direction = ~ level.start_dir;
156
        if (seamless == 0) {
157
                if (current_level != 0) {
158
                        x = hitp_beg_lev;
159
                } else {
160
                        // HP on demo level
161
                        x = 4;
162
                }
163
                hitp_max = hitp_curr = x;
164
        }
165
        if (current_level == 1) {
166
                // Special event: press button + falling entry
167
                get_tile(5, 2, 0);
168
                trigger_button(0, 0, -1);
169
                seqtbl_offset_char(seq_7_fall); // fall
170
        } else if (current_level == 13) {
171
                // Special event: running entry
172
                seqtbl_offset_char(seq_84_run); // run
173
        } else {
174
                seqtbl_offset_char(seq_5_turn); // turn
175
        }
176
        set_start_pos();
177
}
178
 
179
// seg003:028A
180
void __pascal far set_start_pos() {
181
        Char.y = y_land[Char.curr_row + 1];
182
        Char.alive = -1;
183
        Char.charid = charid_0_kid;
184
        is_screaming = 0;
185
        knock = 0;
186
        upside_down = start_upside_down; // 0
187
        is_feather_fall = 0;
188
        Char.fall_y = 0;
189
        Char.fall_x = 0;
190
        offguard = 0;
191
        Char.sword = sword_0_sheathed;
192
        droppedout = 0;
193
        play_seq();
194
        if (current_level == 7 && Char.room == 17) {
195
                // Special event: level 7 falling entry
196
                // level 7, room 17: show room below
197
                goto_other_room(3);
198
        }
199
        savekid();
200
}
201
 
202
// seg003:02E6
203
void __pascal far find_start_level_door() {
204
        short tilepos;
205
        get_room_address(Kid.room);
206
        for (tilepos = 0; tilepos < 30; ++tilepos) {
207
                if ((curr_room_tiles[tilepos] & 0x1F) == tiles_16_level_door_left) {
208
                        start_level_door(Kid.room, tilepos);
209
                }
210
        }
211
}
212
 
213
// seg003:0326
214
void __pascal far draw_level_first() {
215
        screen_updates_suspended = 1;
216
 
217
        next_room = Kid.room;
218
        check_the_end();
219
        if (tbl_level_type[current_level]) {
220
                gen_palace_wall_colors();
221
        }
222
        draw_rect(&screen_rect, 0);
223
        show_level();
224
        redraw_screen(0);
225
        draw_kid_hp(hitp_curr, hitp_max);
226
 
227
        screen_updates_suspended = 0;
228
        request_screen_update();
229
 
230
#ifdef USE_SCREENSHOT
231
        auto_screenshot();
232
#endif
233
 
234
        // Busy waiting!
235
        start_timer(timer_1, 5);
236
        do_simple_wait(1);
237
}
238
 
239
// seg003:037B
240
void __pascal far redraw_screen(int drawing_different_room) {
241
        //remove_flash();
242
        if (drawing_different_room) {
243
                draw_rect(&rect_top, 0);
244
        }
245
 
246
        different_room = 0;
247
        if (is_blind_mode) {
248
                draw_rect(&rect_top, 0);
249
        } else {
250
                if (curr_guard_color) {
251
                        // Moved *before* drawings.
252
                        set_chtab_palette(chtab_addrs[id_chtab_5_guard], &guard_palettes[0x30 * curr_guard_color - 0x30], 0x10);
253
                }
254
                need_drects = 0;
255
                redraw_room();
256
#ifdef USE_LIGHTING
257
        redraw_lighting();
258
#endif
259
                if (is_keyboard_mode) {
260
                        clear_kbd_buf();
261
                }
262
                is_blind_mode = 1;
263
                draw_tables();
264
                if (is_keyboard_mode) {
265
                        clear_kbd_buf();
266
                }
267
#ifdef USE_COPYPROT
268
                if (current_level == 15) {
269
                        // letters on potions level
270
                        current_target_surface = offscreen_surface;
271
                        short var_2;
272
                        for (var_2 = 0; var_2 < 14; ++var_2) {
273
                                if (copyprot_room[var_2] == drawn_room) {
274
                                        set_curr_pos((copyprot_tile[var_2] % 10 << 5) + 24, copyprot_tile[var_2] / 10 * 63 + 38);
275
                                        draw_text_character(copyprot_letter[cplevel_entr[var_2]]);
276
                                }
277
                        }
278
                        current_target_surface = onscreen_surface_;
279
                }
280
#endif
281
                is_blind_mode = 0;
282
                memset_near(table_counts, 0, sizeof(table_counts));
283
                draw_moving();
284
                draw_tables();
285
                if (is_keyboard_mode) {
286
                        clear_kbd_buf();
287
                }
288
                need_drects = 1;
289
                if (curr_guard_color) {
290
                        //set_pal_arr(0x80, 0x10, &guard_palettes[0x30 * curr_guard_color - 0x30], 1);
291
                }
292
                if (upside_down) {
293
                        flip_screen(offscreen_surface);
294
                }
295
                copy_screen_rect(&rect_top);
296
                if (upside_down) {
297
                        flip_screen(offscreen_surface);
298
                }
299
                if (is_keyboard_mode) {
300
                        clear_kbd_buf();
301
                }
302
        }
303
        exit_room_timer = 2;
304
 
305
}
306
 
307
// seg003:04F8
308
// Returns a level number:
309
// - The current level if it was restarted.
310
// - The next level if the level was completed.
311
int __pascal far play_level_2() {
312
        while (1) { // main loop
313
#ifdef USE_QUICKSAVE
314
                check_quick_op();
315
#endif
316
 
317
#ifdef USE_REPLAY
318
                if (need_replay_cycle) replay_cycle();
319
#endif
320
 
321
                if (Kid.sword == sword_2_drawn) {
322
                        // speed when fighting (smaller is faster)
323
                        start_timer(timer_1, 6);
324
                } else {
325
                        // speed when not fighting (smaller is faster)
326
                        start_timer(timer_1, 5);
327
                }
328
                guardhp_delta = 0;
329
                hitp_delta = 0;
330
                timers();
331
                play_frame();
332
 
333
#ifdef USE_REPLAY
334
                // At the exact "end of level" frame, preserve the seed to ensure reproducibility,
335
                // regardless of how long the sound is still playing *after* this frame (torch animation modifies the seed!)
336
                if (keep_last_seed == 1) {
337
                        preserved_seed = random_seed;
338
                        keep_last_seed = -1; // disable repeat
339
                }
340
#endif
341
 
342
                if (is_restart_level) {
343
                        is_restart_level = 0;
344
                        return current_level;
345
                } else {
346
                        if (next_level == current_level || check_sound_playing()) {
347
                                screen_updates_suspended = 1;
348
                                draw_game_frame();
349
                                if (flash_if_hurt()) {
350
                                        screen_updates_suspended = 0;
351
                                        request_screen_update(); // display the flash
352
                                        delay_ticks(2);          // and add a short delay
353
                                }
354
                                screen_updates_suspended = 0;
355
                                remove_flash_if_hurt();
356
 
357
                                #ifdef USE_DEBUG_CHEATS
358
                                if (debug_cheats_enabled && is_timer_displayed) {
359
                                        char timer_text[16];
360
                                        if (rem_min < 0) {
361
                                                snprintf(timer_text, 16, "%02d:%02d:%02d", -(rem_min + 1), (719 - rem_tick) / 12, (719 - rem_tick) % 12);
362
                                        } else {
363
                                                snprintf(timer_text, 16, "%02d:%02d:%02d", rem_min - 1, rem_tick / 12, rem_tick % 12);
364
                                        }
365
                                        screen_updates_suspended = 1;
366
                                        draw_rect(&timer_rect, color_0_black);
367
                                        show_text(&timer_rect, -1, -1, timer_text);
368
                                        screen_updates_suspended = 0;
369
                                }
370
                                #endif
371
 
372
                                request_screen_update(); // request screen update manually
373
                                do_simple_wait(1);
374
                        } else {
375
                                stop_sounds();
376
                                hitp_beg_lev = hitp_max;
377
                                checkpoint = 0;
378
 
379
                                #ifdef USE_REPLAY
380
                                if (keep_last_seed == -1) {
381
                                        random_seed = preserved_seed; // Ensure reproducibility in the next level.
382
                                        keep_last_seed = 0;
383
                                }
384
                                #endif
385
 
386
                                return next_level;
387
                        }
388
                }
389
        }
390
}
391
 
392
// seg003:0576
393
void __pascal far redraw_at_char() {
394
        short x_top_row;
395
        short tile_col;
396
        short tile_row;
397
        short x_col_left;
398
        short x_col_right;
399
        if (Char.sword >= sword_2_drawn) {
400
                // If char is holding sword, it makes redraw-area bigger.
401
                if (Char.direction >= dir_0_right) {
402
                        if (++char_col_right > 9) char_col_right = 9;
403
                        // char_col_right = MIN(char_col_right + 1, 9);
404
                } else {
405
                        if (--char_col_left < 0) char_col_left = 0;
406
                        // char_col_left = MAX(char_col_left - 1, 0);
407
                }
408
        }
409
        if (Char.charid == charid_0_kid) {
410
                x_top_row = MIN(char_top_row, prev_char_top_row);
411
                x_col_right = MAX(char_col_right, prev_char_col_right);
412
                x_col_left = MIN(char_col_left, prev_char_col_left);
413
        } else {
414
                x_top_row = char_top_row;
415
                x_col_right = char_col_right;
416
                x_col_left = char_col_left;
417
        }
418
        for (tile_row = x_top_row; tile_row <= char_bottom_row; ++tile_row) {
419
                for (tile_col = x_col_left; tile_col <= x_col_right; ++tile_col) {
420
                        set_redraw_fore(get_tilepos(tile_col, tile_row), 1);
421
                }
422
        }
423
        if (Char.charid == charid_0_kid) {
424
                prev_char_top_row = char_top_row;
425
                prev_char_col_right = char_col_right;
426
                prev_char_col_left = char_col_left;
427
        }
428
}
429
 
430
// seg003:0645
431
void __pascal far redraw_at_char2() {
432
        short char_action;
433
        short char_frame;
434
        void __pascal (* redraw_func)(short, byte);
435
        char_action = Char.action;
436
        char_frame = Char.frame;
437
        redraw_func = &set_redraw2;
438
        // frames 78..80: grab
439
        if (char_frame < frame_78_jumphang || char_frame >= frame_80_jumphang) {
440
                // frames 135..149: climb up
441
                if (char_frame >= frame_137_climbing_3 && char_frame < frame_145_climbing_11) {
442
                        redraw_func = &set_redraw_floor_overlay;
443
                } else {
444
                        // frames 102..106: fall
445
                        if (char_action != actions_2_hang_climb && char_action != actions_3_in_midair &&
446
                                        char_action != actions_4_in_freefall && char_action != actions_6_hang_straight &&
447
                                        (char_action != actions_5_bumped || char_frame < frame_102_start_fall_1 || char_frame > frame_106_fall)) {
448
                                return;
449
                        }
450
                }
451
        }
452
        for (tile_col = char_col_right; tile_col >= char_col_left; --tile_col) {
453
                if (char_action != 2) {
454
                        redraw_func(get_tilepos(tile_col, char_bottom_row), 1);
455
                }
456
                if (char_top_row != char_bottom_row) {
457
                        redraw_func(get_tilepos(tile_col, char_top_row), 1);
458
                }
459
        }
460
}
461
 
462
// seg003:0706
463
void __pascal far check_knock() {
464
        if (knock) {
465
                do_knock(Char.room, Char.curr_row - (knock>0));
466
                knock = 0;
467
        }
468
}
469
 
470
// seg003:0735
471
void __pascal far timers() {
472
        if (united_with_shadow > 0) {
473
                --united_with_shadow;
474
                if (united_with_shadow == 0) {
475
                        --united_with_shadow;
476
                }
477
        }
478
        if (guard_notice_timer > 0) {
479
                --guard_notice_timer;
480
        }
481
        if (resurrect_time > 0) {
482
                --resurrect_time;
483
        }
484
        if (is_feather_fall && !check_sound_playing()) {
485
#ifdef USE_REPLAY
486
                if (recording) special_move = MOVE_EFFECT_END;
487
                if (!replaying) // during replays, feather effect gets cancelled in do_replay_move()
488
#endif
489
                is_feather_fall = 0;
490
        }
491
        // Special event: mouse
492
        if (current_level == 8 && Char.room == 16 && leveldoor_open) {
493
                ++leveldoor_open;
494
                // time before mouse comes: 150/12=12.5 seconds
495
                if (leveldoor_open == 150) {
496
                        do_mouse();
497
                }
498
        }
499
}
500
 
501
// seg003:0798
502
void __pascal far check_mirror() {
503
        word clip_top;
504
        if (jumped_through_mirror == -1) {
505
                jump_through_mirror();
506
        } else {
507
                if (get_tile_at_char() == tiles_13_mirror) {
508
                        loadkid();
509
                        load_frame();
510
                        check_mirror_image();
511
                        if (distance_mirror >= 0) {
512
                                load_frame_to_obj();
513
                                reset_obj_clip();
514
                                clip_top = y_clip[Char.curr_row + 1];
515
                                if (clip_top < obj_y) {
516
                                        obj_clip_top = clip_top;
517
                                        obj_clip_left = (Char.curr_col << 5) + 9;
518
                                        add_objtable(4); // mirror image
519
                                }
520
                        }
521
                }
522
        }
523
}
524
 
525
// seg003:080A
526
void __pascal far jump_through_mirror() {
527
        loadkid();
528
        load_frame();
529
        check_mirror_image();
530
        jumped_through_mirror = 0;
531
        Char.charid = charid_1_shadow;
532
        play_sound(sound_45_jump_through_mirror); // jump through mirror
533
        saveshad();
534
        guardhp_max = guardhp_curr = hitp_max;
535
        hitp_curr = 1;
536
        draw_kid_hp(1, hitp_max);
537
        draw_guard_hp(guardhp_curr, guardhp_max);
538
}
539
 
540
// seg003:085B
541
void __pascal far check_mirror_image() {
542
        short distance;
543
        short xpos;
544
        xpos = x_bump[Char.curr_col + 5] + 10;
545
        distance = distance_to_edge_weight();
546
        if (Char.direction >= dir_0_right) {
547
                distance = (~distance) + 14;
548
        }
549
        distance_mirror = distance - 2;
550
        Char.x = (xpos << 1) - Char.x;
551
        Char.direction = ~Char.direction;
552
}
553
 
554
// seg003:08AA
555
void __pascal far bump_into_opponent() {
556
        // This is called from play_kid_frame, so char=Kid, Opp=Guard
557
        short distance;
558
        if (can_guard_see_kid >= 2 &&
559
                Char.sword == sword_0_sheathed && // Kid must not be in fighting pose
560
                Opp.sword != sword_0_sheathed && // but Guard must
561
                Opp.action < 2 &&
562
                Char.direction != Opp.direction // must be facing toward each other
563
        ) {
564
                distance = char_opp_dist();
565
                if (ABS(distance) <= 15) {
566
 
567
                        #ifdef FIX_PAINLESS_FALL_ON_GUARD
568
                        if (fix_painless_fall_on_guard) {
569
                                if (Char.fall_y >= 33) return; // don't bump; dead
570
                                else if (Char.fall_y >= 22) { // medium land
571
                                        take_hp(1);
572
                                        play_sound(sound_16_medium_land);
573
                                }
574
                        }
575
                        #endif
576
 
577
                        Char.y = y_land[Char.curr_row + 1];
578
                        Char.fall_y = 0;
579
                        seqtbl_offset_char(seq_47_bump); // bump into opponent
580
                        play_seq();
581
                }
582
        }
583
}
584
 
585
// seg003:0913
586
void __pascal far pos_guards() {
587
        short guard_tile;
588
        short room1;
589
        for (room1 = 0; room1 < 24; ++room1) {
590
                guard_tile = level.guards_tile[room1];
591
                if (guard_tile < 30) {
592
                        level.guards_x[room1] = x_bump[guard_tile % 10 + 5] + 14;
593
                        level.guards_seq_hi[room1] = 0;
594
                }
595
        }
596
}
597
 
598
// seg003:0959
599
void __pascal far check_can_guard_see_kid() {
600
/*
601
Possible results in can_guard_see_kid:
602
0: Guard can't see Kid
603
1: Guard can see Kid, but won't come
604
2: Guard can see Kid, and will come
605
*/
606
        short kid_frame;
607
        short left_pos;
608
        short temp;
609
        short right_pos;
610
        kid_frame = Kid.frame;
611
        if (Guard.charid == charid_24_mouse) {
612
                return;
613
        }
614
        if ((Guard.charid != charid_1_shadow || current_level == 12) &&
615
                // frames 217..228: going up on stairs
616
                kid_frame != 0 && (kid_frame < frame_219_exit_stairs_3 || kid_frame >= 229) &&
617
                Guard.direction != dir_56_none && Kid.alive < 0 && Guard.alive < 0 && Kid.room == Guard.room && Kid.curr_row == Guard.curr_row
618
        ) {
619
                can_guard_see_kid = 2;
620
                left_pos = x_bump[Kid.curr_col + 5] + 7;
621
                right_pos = x_bump[Guard.curr_col + 5] + 7;
622
                if (left_pos > right_pos) {
623
                        temp = left_pos;
624
                        left_pos = right_pos;
625
                        right_pos = temp;
626
                }
627
                // A chomper is on the left side of a tile, so it doesn't count.
628
                if (get_tile_at_kid(left_pos) == tiles_18_chomper) {
629
                        left_pos += 14;
630
                }
631
                // A gate is on the right side of a tile, so it doesn't count.
632
                if (get_tile_at_kid(right_pos) == tiles_4_gate) {
633
                        right_pos -= 14;
634
                }
635
                if (right_pos >= left_pos) {
636
                        while (left_pos <= right_pos) {
637
                                // Can't see through these tiles.
638
                                if (get_tile_at_kid(left_pos) == tiles_20_wall ||
639
                                        curr_tile2 == tiles_7_doortop_with_floor ||
640
                                        curr_tile2 == tiles_12_doortop
641
                                ) {
642
                                        can_guard_see_kid = 0; return;
643
                                }
644
                                // Can see through these, but won't go through them.
645
                                if (curr_tile2 == tiles_11_loose ||
646
                                        curr_tile2 == tiles_18_chomper ||
647
                                        (curr_tile2 == tiles_4_gate && curr_room_modif[curr_tilepos] < 112) ||
648
                                        !tile_is_floor(curr_tile2)
649
                                ) {
650
                                        can_guard_see_kid = 1;
651
                                }
652
                                left_pos += 14;
653
                        }
654
                }
655
        } else {
656
                can_guard_see_kid = 0;
657
        }
658
}
659
 
660
// seg003:0A99
661
byte __pascal far get_tile_at_kid(int xpos) {
662
        return get_tile(Kid.room, get_tile_div_mod_m7(xpos), Kid.curr_row);
663
}
664
 
665
// seg003:0ABA
666
void __pascal far do_mouse() {
667
        loadkid();
668
        Char.charid = charid_24_mouse;
669
        Char.x = 200;
670
        Char.curr_row = 0;
671
        Char.y = y_land[Char.curr_row + 1];
672
        Char.alive = -1;
673
        Char.direction = dir_FF_left;
674
        guardhp_curr = 1;
675
        seqtbl_offset_char(seq_105_mouse_forward); // mouse forward
676
        play_seq();
677
        saveshad();
678
}
679
 
680
// seg003:0AFC
681
int __pascal far flash_if_hurt() {
682
        if (flash_time != 0) {
683
                do_flash_no_delay(flash_color); // don't add delay to the flash
684
                return 1;
685
        } else if (hitp_delta < 0) {
686
                if (is_joyst_mode && enable_controller_rumble && sdl_haptic != NULL) {
687
                        SDL_HapticRumblePlay(sdl_haptic, 1.0, 100); // rumble at full strength for 100 milliseconds
688
                }
689
                do_flash_no_delay(color_12_brightred); // red
690
                return 1;
691
        }
692
        return 0; // not flashed
693
}
694
 
695
// seg003:0B1A
696
void __pascal far remove_flash_if_hurt() {
697
        if (flash_time != 0) {
698
                --flash_time;
699
        } else {
700
                if (hitp_delta >= 0) return;
701
        }
702
        remove_flash();
703
}