A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 434 lines 13 kB view raw
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}