Fix crash if Num_walls=0
[btb/d2x.git] / main / effects.c
1 /* $Id: effects.c,v 1.6 2004-08-28 23:17:45 schaffner Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Special effects, such as rotating fans, electrical walls, and
18  * other cool animations.
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <conf.h>
24 #endif
25
26 #ifdef RCS
27 static char rcsid[] = "$Id: effects.c,v 1.6 2004-08-28 23:17:45 schaffner Exp $";
28 #endif
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stdarg.h>
33 #include <string.h>
34
35 #include "gr.h"
36 #include "inferno.h"
37 #include "game.h"
38 #include "vclip.h"
39 #include "effects.h"
40 #include "bm.h"
41 #include "mono.h"
42 #include "u_mem.h"
43 #include "textures.h"
44 #include "cntrlcen.h"
45 #include "error.h"
46
47 int Num_effects;
48 eclip Effects[MAX_EFFECTS];
49
50 void init_special_effects()
51 {
52         int i;
53
54         for (i=0;i<Num_effects;i++)
55                 Effects[i].time_left = Effects[i].vc.frame_time;
56 }
57
58 void reset_special_effects()
59 {
60         int i;
61
62         for (i=0;i<Num_effects;i++) {
63                 Effects[i].segnum = -1;                                 //clear any active one-shots
64                 Effects[i].flags &= ~(EF_STOPPED|EF_ONE_SHOT);          //restart any stopped effects
65
66                 //reset bitmap, which could have been changed by a crit_clip
67                 if (Effects[i].changing_wall_texture != -1)
68                         Textures[Effects[i].changing_wall_texture] = Effects[i].vc.frames[Effects[i].frame_count];
69
70                 if (Effects[i].changing_object_texture != -1)
71                         ObjBitmaps[Effects[i].changing_object_texture] = Effects[i].vc.frames[Effects[i].frame_count];
72
73         }
74 }
75
76 void do_special_effects()
77 {
78         int i;
79         eclip *ec;
80
81         for (i=0,ec=Effects;i<Num_effects;i++,ec++) {
82
83                 if ((Effects[i].changing_wall_texture == -1) && (Effects[i].changing_object_texture==-1) )
84                         continue;
85
86                 if (ec->flags & EF_STOPPED)
87                         continue;
88
89                 ec->time_left -= FrameTime;
90
91                 while (ec->time_left < 0) {
92
93                         ec->time_left += ec->vc.frame_time;
94                         
95                         ec->frame_count++;
96                         if (ec->frame_count >= ec->vc.num_frames) {
97                                 if (ec->flags & EF_ONE_SHOT) {
98                                         Assert(ec->segnum!=-1);
99                                         Assert(ec->sidenum>=0 && ec->sidenum<6);
100                                         Assert(ec->dest_bm_num!=0 && Segments[ec->segnum].sides[ec->sidenum].tmap_num2!=0);
101                                         Segments[ec->segnum].sides[ec->sidenum].tmap_num2 = ec->dest_bm_num | (Segments[ec->segnum].sides[ec->sidenum].tmap_num2&0xc000);               //replace with destoyed
102                                         ec->flags &= ~EF_ONE_SHOT;
103                                         ec->segnum = -1;                //done with this
104                                 }
105
106                                 ec->frame_count = 0;
107                         }
108                 }
109
110                 if (ec->flags & EF_CRITICAL)
111                         continue;
112
113                 if (ec->crit_clip!=-1 && Control_center_destroyed) {
114                         int n = ec->crit_clip;
115
116                         //*ec->bm_ptr = &GameBitmaps[Effects[n].vc.frames[Effects[n].frame_count].index];
117                         if (ec->changing_wall_texture != -1)
118                                 Textures[ec->changing_wall_texture] = Effects[n].vc.frames[Effects[n].frame_count];
119
120                         if (ec->changing_object_texture != -1)
121                                 ObjBitmaps[ec->changing_object_texture] = Effects[n].vc.frames[Effects[n].frame_count];
122
123                 }
124                 else    {
125                         // *ec->bm_ptr = &GameBitmaps[ec->vc.frames[ec->frame_count].index];
126                         if (ec->changing_wall_texture != -1)
127                                 Textures[ec->changing_wall_texture] = ec->vc.frames[ec->frame_count];
128         
129                         if (ec->changing_object_texture != -1)
130                                 ObjBitmaps[ec->changing_object_texture] = ec->vc.frames[ec->frame_count];
131                 }
132
133         }
134 }
135
136 void restore_effect_bitmap_icons()
137 {
138         int i;
139         
140         for (i=0;i<Num_effects;i++)
141                 if (! (Effects[i].flags & EF_CRITICAL)) {
142                         if (Effects[i].changing_wall_texture != -1)
143                                 Textures[Effects[i].changing_wall_texture] = Effects[i].vc.frames[0];
144         
145                         if (Effects[i].changing_object_texture != -1)
146                                 ObjBitmaps[Effects[i].changing_object_texture] = Effects[i].vc.frames[0];
147                 }
148                         //if (Effects[i].bm_ptr != -1)
149                         //      *Effects[i].bm_ptr = &GameBitmaps[Effects[i].vc.frames[0].index];
150 }
151
152 //stop an effect from animating.  Show first frame.
153 void stop_effect(int effect_num)
154 {
155         eclip *ec = &Effects[effect_num];
156         
157         //Assert(ec->bm_ptr != -1);
158
159         ec->flags |= EF_STOPPED;
160
161         ec->frame_count = 0;
162         //*ec->bm_ptr = &GameBitmaps[ec->vc.frames[0].index];
163
164         if (ec->changing_wall_texture != -1)
165                 Textures[ec->changing_wall_texture] = ec->vc.frames[0];
166         
167         if (ec->changing_object_texture != -1)
168                 ObjBitmaps[ec->changing_object_texture] = ec->vc.frames[0];
169
170 }
171
172 //restart a stopped effect
173 void restart_effect(int effect_num)
174 {
175         Effects[effect_num].flags &= ~EF_STOPPED;
176
177         //Assert(Effects[effect_num].bm_ptr != -1);
178 }
179
180 #ifndef FAST_FILE_IO
181 /*
182  * reads n eclip structs from a CFILE
183  */
184 int eclip_read_n(eclip *ec, int n, CFILE *fp)
185 {
186         int i;
187
188         for (i = 0; i < n; i++) {
189                 vclip_read_n(&ec[i].vc, 1, fp);
190                 ec[i].time_left = cfile_read_fix(fp);
191                 ec[i].frame_count = cfile_read_int(fp);
192                 ec[i].changing_wall_texture = cfile_read_short(fp);
193                 ec[i].changing_object_texture = cfile_read_short(fp);
194                 ec[i].flags = cfile_read_int(fp);
195                 ec[i].crit_clip = cfile_read_int(fp);
196                 ec[i].dest_bm_num = cfile_read_int(fp);
197                 ec[i].dest_vclip = cfile_read_int(fp);
198                 ec[i].dest_eclip = cfile_read_int(fp);
199                 ec[i].dest_size = cfile_read_fix(fp);
200                 ec[i].sound_num = cfile_read_int(fp);
201                 ec[i].segnum = cfile_read_int(fp);
202                 ec[i].sidenum = cfile_read_int(fp);
203         }
204         return i;
205 }
206 #endif