1 /***************************************************************************
2     Collision & Crash Code.
3 
4     There are two types of collision: Scenery & Traffic.
5 
6     1/ Traffic: The Ferrari will spin after a collision.
7     2/ Scenery: There are three types of scenery collision:
8        - Low speed bump. Car rises slightly in the air and stalls.
9        - Mid speed spin. Car spins and slides after collision.
10        - High speed flip. If slightly slower, car rolls into screen.
11          Otherwise, grows towards screen and vanishes
12 
13     Known Issues With Original Code:
14     - Passenger sprites flicker if they land moving in the water on Stage 1
15 
16     The Ferrari sprite is used differently by the crash code.
17     As there's only one of them, I've rolled the additional variables into
18     this class.
19 
20     Copyright Chris White.
21     See license.txt for more details.
22 ***************************************************************************/
23 
24 #pragma once
25 
26 #include "outrun.hpp"
27 
28 class OCrash
29 {
30 public:
31     // Reference to sprite used by crash code
32     oentry* spr_ferrari;
33     oentry* spr_shadow;
34     oentry* spr_pass1;
35     oentry* spr_pass1s;
36     oentry* spr_pass2;
37     oentry* spr_pass2s;
38 
39     // Default value to reset skid counter to on collision
40     const static uint8_t SKID_RESET = 20;
41 
42     // Maximum value to allow skid reset to be set to during collision
43     const static uint8_t SKID_MAX = 30;
44 
45     // Amount to adjust car x position by when skidding
46     const static uint8_t SKID_X_ADJ = 24;
47 
48     //Crash State [Investigate Further]
49     //
50     // 0 = No crash
51     // 1 = Collision with object. Init Spin if medium speed collision.
52     // 2 = Flip Car.
53     // 3 = Slide Car. Trigger Smoke Cloud.
54     // 4 = Horizontally Flip Car. Trigger Smoke Cloud.
55     // 5 = SPIN: Remove Smoke From Spin. Girl Points Finger.
56     //     FLIP: Flip Animation Done.
57     // 6 = Pan Camera To Track Centre
58     // 7 = Camera Repositioned. Ready For Restart
59     //
60     // (Note that hitting another vehicle and skidding does not affect the crash state)
61     int8_t crash_state;
62 
63     // Skid Counter. Set On Collision With Another Vehicle Only.
64     //
65     // If positive, skid to the left.
66     // If negative, skid to the right.
67     int16_t skid_counter;
68     int16_t skid_counter_bak;
69 
70     // Spin Control 1 - SPIN only
71     //
72     // 0 = No Spin
73     // 1 = Init Spin Car
74     // 2 = Spin In Progress
75     uint8_t spin_control1;
76 
77     uint8_t spin_control2;
78 
79     // Increments on a per collision basis (Follows on from collision_sprite being set)
80     //
81     // Used to cycle passenger animations after a crash
82     //
83     // coll_count1 != coll_count2 = Crash Subroutines Not Enabled
84     // coll_count1 == coll_count2 = Crash Subroutines Enabled
85     int16_t coll_count1;
86     int16_t coll_count2;
87 
88     // Counter that increments per-frame during a crash scenario
89     int16_t crash_counter;
90 
91     // Denotes the spin/flip number following the crash.
92     //
93     // 0 = No crash has taken place yet
94     // 1 = Crash has taken place this level
95     // 2 = Crash. First Spin/Flip.
96     // 3 = Crash. Second Spin/Flip.
97     // 4 = Crash. Third Spin/Flip.
98     int16_t crash_spin_count;
99 
100     // Crash Sprite Z Position
101     int16_t crash_z;
102 
103     OCrash(void);
104     ~OCrash(void);
105     void init(oentry* f, oentry* s, oentry* p1, oentry* p1s, oentry* p2, oentry* p2s);
106     bool is_flip();
107     void enable();
108     void clear_crash_state();
109     void tick();
110 
111 private:
112 
113     // This is the rolled Ferrari sprite, which is configured differently for
114     // the crash code.
115     // The offsets indicate the original offsets in memory.
116 
117     //+1E [Word] Spins/Flips Remaining
118     int16_t spinflipcount1;
119     //+22 [Word] Crash Spin/Flip Count Copy
120     int16_t spinflipcount2;
121     //+24 [Word] Crash Slide Value (After Spin/Flip etc.)
122     int16_t slide;
123     //+26 [Word] Frame (actually an index into the Sprite format below)
124     int16_t frame;
125     //+28 [Long] Address of animation sequence (frame address, palette info etc.)
126     uint32_t addr;
127     //+2C [Word] Camera Pan X Target (for repositioning after crash)
128     int16_t camera_x_target;
129     //+2E [Word] Camera Pan Increment
130     int16_t camera_xinc;
131     //+30 [Word] Index into movement lookup table (to set y position of car during low speed bump)
132     int16_t lookup_index;
133     //+32 [Word] Frame to restore car to after bump routine
134     int16_t frame_restore;
135     //+34 [Word] Used as a shift value to change y position during shunt
136     int16_t shift;
137     //+36 [Word] Flip Only: 0 = Fast Crash. 1 = Slow Crash.
138     int16_t crash_speed;
139     //+38 [Word] Crash Z Increment (How much to change Crash Z Per Tick)
140     int16_t crash_zinc;
141     //+3A [Word] 0 = RHS, 1 = LHS?
142     int16_t crash_side;
143 
144     // Passenger Frame to use during spin
145     int16_t spin_pass_frame;
146 
147     int8_t crash_type;
148     enum { CRASH_BUMP = 0, CRASH_SPIN = 1, CRASH_FLIP = 2 };
149 
150     // Delay counter after crash.
151     // Show animation (e.g. girl pointing finger, before car is repositioned)
152     int16_t crash_delay;
153 
154     void do_crash();
155     void spin_switch(const uint16_t);
156     void crash_switch();
157 
158     void init_collision();
159     void do_collision();
160     void end_collision();
161 
162     void do_bump();
163     void do_car_flip();
164     void init_finger(uint32_t);
165     void trigger_smoke();
166     void post_flip_anim();
167     void pan_camera();
168 
169     void init_spin1();
170     void init_spin2();
171     void collide_slow();
172     void collide_med();
173     void collide_fast();
174 
175     void done(oentry*);
176 
177     void do_shadow(oentry*, oentry*);
178 
179     // Pointers to functions for crash code
180     void (OCrash::*function_pass1)(oentry*);
181     void (OCrash::*function_pass2)(oentry*);
182 
183     void do_crash_passengers(oentry*);
184     void flip_start(oentry*);
185 
186     void crash_pass1(oentry*);
187     void crash_pass2(oentry*);
188     void crash_pass_flip(oentry*);
189 
190     void pass_flip(oentry*);
191     void pass_situp(oentry*);
192     void pass_turnhead(oentry*);
193 };
194 
195 extern OCrash ocrash;