summaryrefslogtreecommitdiff
path: root/apps/plugins/doom/p_plats.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/doom/p_plats.c')
-rw-r--r--apps/plugins/doom/p_plats.c434
1 files changed, 434 insertions, 0 deletions
diff --git a/apps/plugins/doom/p_plats.c b/apps/plugins/doom/p_plats.c
new file mode 100644
index 0000000000..4a5c28bb88
--- /dev/null
+++ b/apps/plugins/doom/p_plats.c
@@ -0,0 +1,434 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Plats (i.e. elevator platforms) code, raising/lowering.
29 *
30 *-----------------------------------------------------------------------------*/
31
32#include "doomstat.h"
33#include "m_random.h"
34#include "r_main.h"
35#include "p_spec.h"
36#include "p_tick.h"
37#include "s_sound.h"
38#include "sounds.h"
39#include "rockmacros.h"
40platlist_t *activeplats; // killough 2/14/98: made global again
41
42//
43// T_PlatRaise()
44//
45// Action routine to move a plat up and down
46//
47// Passed a plat structure containing all pertinent information about the move
48// No return
49//
50// jff 02/08/98 all cases with labels beginning with gen added to support
51// generalized line type behaviors.
52
53void T_PlatRaise(plat_t* plat)
54{
55 result_e res;
56
57 // handle plat moving, up, down, waiting, or in stasis,
58 switch(plat->status)
59 {
60 case up: // plat moving up
61 res = T_MovePlane(plat->sector,plat->speed,plat->high,plat->crush,0,1);
62
63 // if a pure raise type, make the plat moving sound
64 if (plat->type == raiseAndChange
65 || plat->type == raiseToNearestAndChange)
66 {
67 if (!(leveltime&7))
68 S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_stnmov);
69 }
70
71 // if encountered an obstacle, and not a crush type, reverse direction
72 if (res == crushed && (!plat->crush))
73 {
74 plat->count = plat->wait;
75 plat->status = down;
76 S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_pstart);
77 }
78 else // else handle reaching end of up stroke
79 {
80 if (res == pastdest) // end of stroke
81 {
82 // if not an instant toggle type, wait, make plat stop sound
83 if (plat->type!=toggleUpDn)
84 {
85 plat->count = plat->wait;
86 plat->status = waiting;
87 S_StartSound((mobj_t *)&plat->sector->soundorg, sfx_pstop);
88 }
89 else // else go into stasis awaiting next toggle activation
90 {
91 plat->oldstatus = plat->status;//jff 3/14/98 after action wait
92 plat->status = in_stasis; //for reactivation of toggle
93 }
94
95 // lift types and pure raise types are done at end of up stroke
96 // only the perpetual type waits then goes back up
97 switch(plat->type)
98 {
99 case blazeDWUS:
100 case downWaitUpStay:
101 case raiseAndChange:
102 case raiseToNearestAndChange:
103 case genLift:
104 P_RemoveActivePlat(plat); // killough
105 default:
106 break;
107 }
108 }
109 }
110 break;
111
112 case down: // plat moving down
113 res = T_MovePlane(plat->sector,plat->speed,plat->low,false,0,-1);
114
115 // handle reaching end of down stroke
116 if (res == pastdest)
117 {
118 // if not an instant toggle, start waiting, make plat stop sound
119 if (plat->type!=toggleUpDn) //jff 3/14/98 toggle up down
120 { // is silent, instant, no waiting
121 plat->count = plat->wait;
122 plat->status = waiting;
123 S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_pstop);
124 }
125 else // instant toggles go into stasis awaiting next activation
126 {
127 plat->oldstatus = plat->status;//jff 3/14/98 after action wait
128 plat->status = in_stasis; //for reactivation of toggle
129 }
130
131 //jff 1/26/98 remove the plat if it bounced so it can be tried again
132 //only affects plats that raise and bounce
133 //killough 1/31/98: relax compatibility to demo_compatibility
134
135 // remove the plat if its a pure raise type
136 if (!comp[comp_floors])
137 {
138 switch(plat->type)
139 {
140 case raiseAndChange:
141 case raiseToNearestAndChange:
142 P_RemoveActivePlat(plat);
143 default:
144 break;
145 }
146 }
147 }
148 break;
149
150 case waiting: // plat is waiting
151 if (!--plat->count) // downcount and check for delay elapsed
152 {
153 if (plat->sector->floorheight == plat->low)
154 plat->status = up; // if at bottom, start up
155 else
156 plat->status = down; // if at top, start down
157
158 // make plat start sound
159 S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_pstart);
160 }
161 break; //jff 1/27/98 don't pickup code added later to in_stasis
162
163 case in_stasis: // do nothing if in stasis
164 break;
165 }
166}
167
168
169//
170// EV_DoPlat
171//
172// Handle Plat linedef types
173//
174// Passed the linedef that activated the plat, the type of plat action,
175// and for some plat types, an amount to raise
176// Returns true if a thinker is started, or restarted from stasis
177//
178int EV_DoPlat
179( line_t* line,
180 plattype_e type,
181 int amount )
182{
183 plat_t* plat;
184 int secnum;
185 int rtn;
186 sector_t* sec;
187
188 secnum = -1;
189 rtn = 0;
190
191
192 // Activate all <type> plats that are in_stasis
193 switch(type)
194 {
195 case perpetualRaise:
196 P_ActivateInStasis(line->tag);
197 break;
198
199 case toggleUpDn:
200 P_ActivateInStasis(line->tag);
201 rtn=1;
202 break;
203
204 default:
205 break;
206 }
207
208 // act on all sectors tagged the same as the activating linedef
209 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
210 {
211 sec = &sectors[secnum];
212
213 // don't start a second floor function if already moving
214 if (P_SectorActive(floor_special,sec)) //jff 2/23/98 multiple thinkers
215 continue;
216
217 // Create a thinker
218 rtn = 1;
219 plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0);
220 P_AddThinker(&plat->thinker);
221
222 plat->type = type;
223 plat->sector = sec;
224 plat->sector->floordata = plat; //jff 2/23/98 multiple thinkers
225 plat->thinker.function = T_PlatRaise;
226 plat->crush = false;
227 plat->tag = line->tag;
228
229 //jff 1/26/98 Avoid raise plat bouncing a head off a ceiling and then
230 //going down forever -- default low to plat height when triggered
231 plat->low = sec->floorheight;
232
233 // set up plat according to type
234 switch(type)
235 {
236 case raiseToNearestAndChange:
237 plat->speed = PLATSPEED/2;
238 sec->floorpic = sides[line->sidenum[0]].sector->floorpic;
239 plat->high = P_FindNextHighestFloor(sec,sec->floorheight);
240 plat->wait = 0;
241 plat->status = up;
242 sec->special = 0;
243 //jff 3/14/98 clear old field as well
244 sec->oldspecial = 0;
245
246 S_StartSound((mobj_t *)&sec->soundorg,sfx_stnmov);
247 break;
248
249 case raiseAndChange:
250 plat->speed = PLATSPEED/2;
251 sec->floorpic = sides[line->sidenum[0]].sector->floorpic;
252 plat->high = sec->floorheight + amount*FRACUNIT;
253 plat->wait = 0;
254 plat->status = up;
255
256 S_StartSound((mobj_t *)&sec->soundorg,sfx_stnmov);
257 break;
258
259 case downWaitUpStay:
260 plat->speed = PLATSPEED * 4;
261 plat->low = P_FindLowestFloorSurrounding(sec);
262
263 if (plat->low > sec->floorheight)
264 plat->low = sec->floorheight;
265
266 plat->high = sec->floorheight;
267 plat->wait = 35*PLATWAIT;
268 plat->status = down;
269 S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart);
270 break;
271
272 case blazeDWUS:
273 plat->speed = PLATSPEED * 8;
274 plat->low = P_FindLowestFloorSurrounding(sec);
275
276 if (plat->low > sec->floorheight)
277 plat->low = sec->floorheight;
278
279 plat->high = sec->floorheight;
280 plat->wait = 35*PLATWAIT;
281 plat->status = down;
282 S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart);
283 break;
284
285 case perpetualRaise:
286 plat->speed = PLATSPEED;
287 plat->low = P_FindLowestFloorSurrounding(sec);
288
289 if (plat->low > sec->floorheight)
290 plat->low = sec->floorheight;
291
292 plat->high = P_FindHighestFloorSurrounding(sec);
293
294 if (plat->high < sec->floorheight)
295 plat->high = sec->floorheight;
296
297 plat->wait = 35*PLATWAIT;
298 plat->status = P_Random(pr_plats)&1;
299
300 S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart);
301 break;
302
303 case toggleUpDn: //jff 3/14/98 add new type to support instant toggle
304 plat->speed = PLATSPEED; //not used
305 plat->wait = 35*PLATWAIT; //not used
306 plat->crush = true; //jff 3/14/98 crush anything in the way
307
308 // set up toggling between ceiling, floor inclusive
309 plat->low = sec->ceilingheight;
310 plat->high = sec->floorheight;
311 plat->status = down;
312 break;
313
314 default:
315 break;
316 }
317 P_AddActivePlat(plat); // add plat to list of active plats
318 }
319 return rtn;
320}
321
322// The following were all rewritten by Lee Killough
323// to use the new structure which places no limits
324// on active plats. It also avoids spending as much
325// time searching for active plats. Previously a
326// fixed-size array was used, with NULL indicating
327// empty entries, while now a doubly-linked list
328// is used.
329
330//
331// P_ActivateInStasis()
332//
333// Activate a plat that has been put in stasis
334// (stopped perpetual floor, instant floor/ceil toggle)
335//
336// Passed the tag of the plat that should be reactivated
337// Returns nothing
338//
339void P_ActivateInStasis(int tag)
340{
341 platlist_t *pl;
342 for (pl=activeplats; pl; pl=pl->next) // search the active plats
343 {
344 plat_t *plat = pl->plat; // for one in stasis with right tag
345 if (plat->tag == tag && plat->status == in_stasis)
346 {
347 if (plat->type==toggleUpDn) //jff 3/14/98 reactivate toggle type
348 plat->status = plat->oldstatus==up? down : up;
349 else
350 plat->status = plat->oldstatus;
351 plat->thinker.function = T_PlatRaise;
352 }
353 }
354}
355
356//
357// EV_StopPlat()
358//
359// Handler for "stop perpetual floor" linedef type
360//
361// Passed the linedef that stopped the plat
362// Returns true if a plat was put in stasis
363//
364// jff 2/12/98 added int return value, fixed return
365//
366int EV_StopPlat(line_t* line)
367{
368 platlist_t *pl;
369 for (pl=activeplats; pl; pl=pl->next) // search the active plats
370 {
371 plat_t *plat = pl->plat; // for one with the tag not in stasis
372 if (plat->status != in_stasis && plat->tag == line->tag)
373 {
374 plat->oldstatus = plat->status; // put it in stasis
375 plat->status = in_stasis;
376 plat->thinker.function = NULL;
377 }
378 }
379 return 1;
380}
381
382//
383// P_AddActivePlat()
384//
385// Add a plat to the head of the active plat list
386//
387// Passed a pointer to the plat to add
388// Returns nothing
389//
390void P_AddActivePlat(plat_t* plat)
391{
392 platlist_t *list = malloc(sizeof *list);
393 list->plat = plat;
394 plat->list = list;
395 if ((list->next = activeplats))
396 list->next->prev = &list->next;
397 list->prev = &activeplats;
398 activeplats = list;
399}
400
401//
402// P_RemoveActivePlat()
403//
404// Remove a plat from the active plat list
405//
406// Passed a pointer to the plat to remove
407// Returns nothing
408//
409void P_RemoveActivePlat(plat_t* plat)
410{
411 platlist_t *list = plat->list;
412 plat->sector->floordata = NULL; //jff 2/23/98 multiple thinkers
413 P_RemoveThinker(&plat->thinker);
414 if ((*list->prev = list->next))
415 list->next->prev = list->prev;
416 free(list);
417}
418
419//
420// P_RemoveAllActivePlats()
421//
422// Remove all plats from the active plat list
423//
424// Passed nothing, returns nothing
425//
426void P_RemoveAllActivePlats(void)
427{
428 while (activeplats)
429 {
430 platlist_t *next = activeplats->next;
431 free(activeplats);
432 activeplats = next;
433 }
434}