]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/doom/p_ceilng.c
games/doom: display correct message on medkit pickup when health low (thanks qu7uux)
[plan9front.git] / sys / src / games / doom / p_ceilng.c
1 // Emacs style mode select   -*- C++ -*- 
2 //-----------------------------------------------------------------------------
3 //
4 // $Id:$
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 //
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
11 //
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15 // for more details.
16 //
17 // $Log:$
18 //
19 // DESCRIPTION:  Ceiling aninmation (lowering, crushing, raising)
20 //
21 //-----------------------------------------------------------------------------
22
23 static const char
24 rcsid[] = "$Id: p_ceilng.c,v 1.4 1997/02/03 16:47:53 b1 Exp $";
25
26
27 #include "z_zone.h"
28 #include "doomdef.h"
29 #include "p_local.h"
30
31 #include "s_sound.h"
32
33 // State.
34 #include "doomstat.h"
35 #include "r_state.h"
36
37 // Data.
38 #include "sounds.h"
39
40 //
41 // CEILINGS
42 //
43
44
45 ceiling_t*      activeceilings[MAXCEILINGS];
46
47
48 //
49 // T_MoveCeiling
50 //
51
52 void T_MoveCeiling (void *_ceiling, void*)
53 {
54     ceiling_t *ceiling = (ceiling_t *)_ceiling;
55     result_e    res;
56         
57     switch(ceiling->direction)
58     {
59       case 0:
60         // IN STASIS
61         break;
62       case 1:
63         // UP
64         res = T_MovePlane(ceiling->sector,
65                           ceiling->speed,
66                           ceiling->topheight,
67                           false,1,ceiling->direction);
68         
69         if (!(leveltime&7))
70         {
71             switch(ceiling->type)
72             {
73               case silentCrushAndRaise:
74                 break;
75               default:
76                 S_StartSound((mobj_t *)&ceiling->sector->soundorg,
77                              sfx_stnmov);
78                 // ?
79                 break;
80             }
81         }
82         
83         if (res == pastdest)
84         {
85             switch(ceiling->type)
86             {
87               case raiseToHighest:
88                 P_RemoveActiveCeiling(ceiling);
89                 break;
90                 
91               case silentCrushAndRaise:
92                 S_StartSound((mobj_t *)&ceiling->sector->soundorg,
93                              sfx_pstop);
94               case fastCrushAndRaise:
95               case crushAndRaise:
96                 ceiling->direction = -1;
97                 break;
98                 
99               default:
100                 break;
101             }
102             
103         }
104         break;
105         
106       case -1:
107         // DOWN
108         res = T_MovePlane(ceiling->sector,
109                           ceiling->speed,
110                           ceiling->bottomheight,
111                           ceiling->crush,1,ceiling->direction);
112         
113         if (!(leveltime&7))
114         {
115             switch(ceiling->type)
116             {
117               case silentCrushAndRaise: break;
118               default:
119                 S_StartSound((mobj_t *)&ceiling->sector->soundorg,
120                              sfx_stnmov);
121             }
122         }
123         
124         if (res == pastdest)
125         {
126             switch(ceiling->type)
127             {
128               case silentCrushAndRaise:
129                 S_StartSound((mobj_t *)&ceiling->sector->soundorg,
130                              sfx_pstop);
131               case crushAndRaise:
132                 ceiling->speed = CEILSPEED;
133               case fastCrushAndRaise:
134                 ceiling->direction = 1;
135                 break;
136
137               case lowerAndCrush:
138               case lowerToFloor:
139                 P_RemoveActiveCeiling(ceiling);
140                 break;
141
142               default:
143                 break;
144             }
145         }
146         else // ( res != pastdest )
147         {
148             if (res == crushed)
149             {
150                 switch(ceiling->type)
151                 {
152                   case silentCrushAndRaise:
153                   case crushAndRaise:
154                   case lowerAndCrush:
155                     ceiling->speed = CEILSPEED / 8;
156                     break;
157
158                   default:
159                     break;
160                 }
161             }
162         }
163         break;
164     }
165 }
166
167
168 //
169 // EV_DoCeiling
170 // Move a ceiling up/down and all around!
171 //
172 int
173 EV_DoCeiling
174 ( line_t*       line,
175   ceiling_e     type )
176 {
177     int         secnum;
178     int         rtn;
179     sector_t*   sec;
180     ceiling_t*  ceiling;
181         
182     secnum = -1;
183     rtn = 0;
184     
185     //  Reactivate in-stasis ceilings...for certain types.
186     switch(type)
187     {
188       case fastCrushAndRaise:
189       case silentCrushAndRaise:
190       case crushAndRaise:
191         P_ActivateInStasisCeiling(line);
192       default:
193         break;
194     }
195         
196     while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
197     {
198         sec = &sectors[secnum];
199         if (sec->specialdata)
200             continue;
201         
202         // new door thinker
203         rtn = 1;
204         ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
205         P_AddThinker (&ceiling->thinker);
206         sec->specialdata = ceiling;
207         ceiling->thinker.function = T_MoveCeiling;
208         ceiling->sector = sec;
209         ceiling->crush = false;
210         
211         switch(type)
212         {
213           case fastCrushAndRaise:
214             ceiling->crush = true;
215             ceiling->topheight = sec->ceilingheight;
216             ceiling->bottomheight = sec->floorheight + (8*FRACUNIT);
217             ceiling->direction = -1;
218             ceiling->speed = CEILSPEED * 2;
219             break;
220
221           case silentCrushAndRaise:
222           case crushAndRaise:
223             ceiling->crush = true;
224             ceiling->topheight = sec->ceilingheight;
225           case lowerAndCrush:
226           case lowerToFloor:
227             ceiling->bottomheight = sec->floorheight;
228             if (type != lowerToFloor)
229                 ceiling->bottomheight += 8*FRACUNIT;
230             ceiling->direction = -1;
231             ceiling->speed = CEILSPEED;
232             break;
233
234           case raiseToHighest:
235             ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
236             ceiling->direction = 1;
237             ceiling->speed = CEILSPEED;
238             break;
239         }
240                 
241         ceiling->tag = sec->tag;
242         ceiling->type = type;
243         P_AddActiveCeiling(ceiling);
244     }
245     return rtn;
246 }
247
248
249 //
250 // Add an active ceiling
251 //
252 void P_AddActiveCeiling(ceiling_t* c)
253 {
254     int         i;
255     
256     for (i = 0; i < MAXCEILINGS;i++)
257     {
258         if (activeceilings[i] == NULL)
259         {
260             activeceilings[i] = c;
261             return;
262         }
263     }
264 }
265
266
267
268 //
269 // Remove a ceiling's thinker
270 //
271 void P_RemoveActiveCeiling(ceiling_t* c)
272 {
273     int         i;
274         
275     for (i = 0;i < MAXCEILINGS;i++)
276     {
277         if (activeceilings[i] == c)
278         {
279             activeceilings[i]->sector->specialdata = NULL;
280             P_RemoveThinker (&activeceilings[i]->thinker);
281             activeceilings[i] = NULL;
282             break;
283         }
284     }
285 }
286
287
288
289 //
290 // Restart a ceiling that's in-stasis
291 //
292 void P_ActivateInStasisCeiling(line_t* line)
293 {
294     int         i;
295         
296     for (i = 0;i < MAXCEILINGS;i++)
297     {
298         if (activeceilings[i]
299             && (activeceilings[i]->tag == line->tag)
300             && (activeceilings[i]->direction == 0))
301         {
302             activeceilings[i]->direction = activeceilings[i]->olddirection;
303             activeceilings[i]->thinker.function = T_MoveCeiling;
304         }
305     }
306 }
307
308
309
310 //
311 // EV_CeilingCrushStop
312 // Stop a ceiling from crushing!
313 //
314 int     EV_CeilingCrushStop(line_t      *line)
315 {
316     int         i;
317     int         rtn;
318         
319     rtn = 0;
320     for (i = 0;i < MAXCEILINGS;i++)
321     {
322         if (activeceilings[i]
323             && (activeceilings[i]->tag == line->tag)
324             && (activeceilings[i]->direction != 0))
325         {
326             activeceilings[i]->olddirection = activeceilings[i]->direction;
327             activeceilings[i]->thinker.function = (actionf_t)NULL;
328             activeceilings[i]->direction = 0;           // in-stasis
329             rtn = 1;
330         }
331     }
332     
333
334     return rtn;
335 }