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