A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 471 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 * Ceiling aninmation (lowering, crushing, raising) 29 * 30 *-----------------------------------------------------------------------------*/ 31 32#include "doomstat.h" 33#include "r_main.h" 34#include "p_spec.h" 35#include "p_tick.h" 36#include "s_sound.h" 37#include "sounds.h" 38#include "z_zone.h" 39#include "doomdef.h" 40#define PU_LEVSPEC 51 // a special thinker in a level 41#include "rockmacros.h" 42 43// the list of ceilings moving currently, including crushers 44ceilinglist_t *activeceilings; 45 46///////////////////////////////////////////////////////////////// 47// 48// Ceiling action routine and linedef type handler 49// 50///////////////////////////////////////////////////////////////// 51 52// 53// T_MoveCeiling 54// 55// Action routine that moves ceilings. Called once per tick. 56// 57// Passed a ceiling_t structure that contains all the info about the move. 58// see P_SPEC.H for fields. No return. 59// 60// jff 02/08/98 all cases with labels beginning with gen added to support 61// generalized line type behaviors. 62// 63void T_MoveCeiling (ceiling_t* ceiling) 64{ 65 result_e res; 66 67 switch(ceiling->direction) 68 { 69 case 0: 70 // If ceiling in stasis, do nothing 71 break; 72 73 case 1: 74 // Ceiling is moving up 75 res = T_MovePlane 76 ( 77 ceiling->sector, 78 ceiling->speed, 79 ceiling->topheight, 80 false, 81 1, 82 ceiling->direction 83 ); 84 85 // if not a silent crusher, make moving sound 86 if (!(leveltime&7)) 87 { 88 switch(ceiling->type) 89 { 90 case silentCrushAndRaise: 91 case genSilentCrusher: 92 break; 93 default: 94 S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov); 95 break; 96 } 97 } 98 99 // handle reaching destination height 100 if (res == pastdest) 101 { 102 switch(ceiling->type) 103 { 104 // plain movers are just removed 105 case raiseToHighest: 106 case genCeiling: 107 P_RemoveActiveCeiling(ceiling); 108 break; 109 110 // movers with texture change, change the texture then get removed 111 case genCeilingChgT: 112 case genCeilingChg0: 113 ceiling->sector->special = ceiling->newspecial; 114 //jff 3/14/98 transfer old special field as well 115 ceiling->sector->oldspecial = ceiling->oldspecial; 116 case genCeilingChg: 117 ceiling->sector->ceilingpic = ceiling->texture; 118 P_RemoveActiveCeiling(ceiling); 119 break; 120 121 // crushers reverse direction at the top 122 case silentCrushAndRaise: 123 S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_pstop); 124 /* fallthrough */ 125 case genSilentCrusher: 126 case genCrusher: 127 case fastCrushAndRaise: 128 case crushAndRaise: 129 ceiling->direction = -1; 130 break; 131 132 default: 133 break; 134 } 135 } 136 break; 137 138 case -1: 139 // Ceiling moving down 140 res = T_MovePlane 141 ( 142 ceiling->sector, 143 ceiling->speed, 144 ceiling->bottomheight, 145 ceiling->crush, 146 1, 147 ceiling->direction 148 ); 149 150 // if not silent crusher type make moving sound 151 if (!(leveltime&7)) 152 { 153 switch(ceiling->type) 154 { 155 case silentCrushAndRaise: 156 case genSilentCrusher: 157 break; 158 default: 159 S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov); 160 } 161 } 162 163 // handle reaching destination height 164 if (res == pastdest) 165 { 166 switch(ceiling->type) 167 { 168 // 02/09/98 jff change slow crushers' speed back to normal 169 // start back up 170 case genSilentCrusher: 171 case genCrusher: 172 if (ceiling->oldspeed<CEILSPEED*3) 173 ceiling->speed = ceiling->oldspeed; 174 ceiling->direction = 1; //jff 2/22/98 make it go back up! 175 break; 176 177 // make platform stop at bottom of all crusher strokes 178 // except generalized ones, reset speed, start back up 179 case silentCrushAndRaise: 180 S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_pstop); 181 /* fallthrough */ 182 case crushAndRaise: 183 ceiling->speed = CEILSPEED; 184 /* fallthrough */ 185 case fastCrushAndRaise: 186 ceiling->direction = 1; 187 break; 188 189 // in the case of ceiling mover/changer, change the texture 190 // then remove the active ceiling 191 case genCeilingChgT: 192 case genCeilingChg0: 193 ceiling->sector->special = ceiling->newspecial; 194 //jff add to fix bug in special transfers from changes 195 ceiling->sector->oldspecial = ceiling->oldspecial; 196 case genCeilingChg: 197 ceiling->sector->ceilingpic = ceiling->texture; 198 P_RemoveActiveCeiling(ceiling); 199 break; 200 201 // all other case, just remove the active ceiling 202 case lowerAndCrush: 203 case lowerToFloor: 204 case lowerToLowest: 205 case lowerToMaxFloor: 206 case genCeiling: 207 P_RemoveActiveCeiling(ceiling); 208 break; 209 210 default: 211 break; 212 } 213 } 214 else // ( res != pastdest ) 215 { 216 // handle the crusher encountering an obstacle 217 if (res == crushed) 218 { 219 switch(ceiling->type) 220 { 221 //jff 02/08/98 slow down slow crushers on obstacle 222 case genCrusher: 223 case genSilentCrusher: 224 if (ceiling->oldspeed < CEILSPEED*3) 225 ceiling->speed = CEILSPEED / 8; 226 break; 227 case silentCrushAndRaise: 228 case crushAndRaise: 229 case lowerAndCrush: 230 ceiling->speed = CEILSPEED / 8; 231 break; 232 233 default: 234 break; 235 } 236 } 237 } 238 break; 239 } 240} 241 242 243// 244// EV_DoCeiling 245// 246// Move a ceiling up/down or start a crusher 247// 248// Passed the linedef activating the function and the type of function desired 249// returns true if a thinker started 250// 251int EV_DoCeiling 252( line_t* line, 253 ceiling_e type ) 254{ 255 int secnum; 256 int rtn; 257 sector_t* sec; 258 ceiling_t* ceiling; 259 260 secnum = -1; 261 rtn = 0; 262 263 // Reactivate in-stasis ceilings...for certain types. 264 // This restarts a crusher after it has been stopped 265 switch(type) 266 { 267 case fastCrushAndRaise: 268 case silentCrushAndRaise: 269 case crushAndRaise: 270 //jff 4/5/98 return if activated 271 rtn = P_ActivateInStasisCeiling(line); 272 default: 273 break; 274 } 275 276 // affects all sectors with the same tag as the linedef 277 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 278 { 279 sec = &sectors[secnum]; 280 281 // if ceiling already moving, don't start a second function on it 282 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98 283 continue; 284 285 // create a new ceiling thinker 286 rtn = 1; 287 ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); 288 P_AddThinker (&ceiling->thinker); 289 sec->ceilingdata = ceiling; //jff 2/22/98 290 ceiling->thinker.function = T_MoveCeiling; 291 ceiling->sector = sec; 292 ceiling->crush = false; 293 294 // setup ceiling structure according to type of function 295 switch(type) 296 { 297 case fastCrushAndRaise: 298 ceiling->crush = true; 299 ceiling->topheight = sec->ceilingheight; 300 ceiling->bottomheight = sec->floorheight + (8*FRACUNIT); 301 ceiling->direction = -1; 302 ceiling->speed = CEILSPEED * 2; 303 break; 304 305 case silentCrushAndRaise: 306 case crushAndRaise: 307 ceiling->crush = true; 308 ceiling->topheight = sec->ceilingheight; 309 case lowerAndCrush: 310 case lowerToFloor: 311 ceiling->bottomheight = sec->floorheight; 312 if (type != lowerToFloor) 313 ceiling->bottomheight += 8*FRACUNIT; 314 ceiling->direction = -1; 315 ceiling->speed = CEILSPEED; 316 break; 317 318 case raiseToHighest: 319 ceiling->topheight = P_FindHighestCeilingSurrounding(sec); 320 ceiling->direction = 1; 321 ceiling->speed = CEILSPEED; 322 break; 323 324 case lowerToLowest: 325 ceiling->bottomheight = P_FindLowestCeilingSurrounding(sec); 326 ceiling->direction = -1; 327 ceiling->speed = CEILSPEED; 328 break; 329 330 case lowerToMaxFloor: 331 ceiling->bottomheight = P_FindHighestFloorSurrounding(sec); 332 ceiling->direction = -1; 333 ceiling->speed = CEILSPEED; 334 break; 335 336 default: 337 break; 338 } 339 340 // add the ceiling to the active list 341 ceiling->tag = sec->tag; 342 ceiling->type = type; 343 P_AddActiveCeiling(ceiling); 344 } 345 return rtn; 346} 347 348////////////////////////////////////////////////////////////////////// 349// 350// Active ceiling list primitives 351// 352///////////////////////////////////////////////////////////////////// 353 354// jff 2/22/98 - modified Lee's plat code to work for ceilings 355// 356// The following were all rewritten by Lee Killough 357// to use the new structure which places no limits 358// on active ceilings. It also avoids spending as much 359// time searching for active ceilings. Previously a 360// fixed-size array was used, with NULL indicating 361// empty entries, while now a doubly-linked list 362// is used. 363 364// 365// P_ActivateInStasisCeiling() 366// 367// Reactivates all stopped crushers with the right tag 368// 369// Passed the line reactivating the crusher 370// Returns true if a ceiling reactivated 371// 372//jff 4/5/98 return if activated 373int P_ActivateInStasisCeiling(line_t *line) 374{ 375 ceilinglist_t *cl; 376 int rtn=0; 377 378 for (cl=activeceilings; cl; cl=cl->next) 379 { 380 ceiling_t *ceiling = cl->ceiling; 381 if (ceiling->tag == line->tag && ceiling->direction == 0) 382 { 383 ceiling->direction = ceiling->olddirection; 384 ceiling->thinker.function = T_MoveCeiling; 385 //jff 4/5/98 return if activated 386 rtn=1; 387 } 388 } 389 return rtn; 390} 391 392// 393// EV_CeilingCrushStop() 394// 395// Stops all active ceilings with the right tag 396// 397// Passed the linedef stopping the ceilings 398// Returns true if a ceiling put in stasis 399// 400int EV_CeilingCrushStop(line_t* line) 401{ 402 int rtn=0; 403 404 ceilinglist_t *cl; 405 for (cl=activeceilings; cl; cl=cl->next) 406 { 407 ceiling_t *ceiling = cl->ceiling; 408 if (ceiling->direction != 0 && ceiling->tag == line->tag) 409 { 410 ceiling->olddirection = ceiling->direction; 411 ceiling->direction = 0; 412 ceiling->thinker.function = NULL; 413 rtn=1; 414 } 415 } 416 return rtn; 417} 418 419// 420// P_AddActiveCeiling() 421// 422// Adds a ceiling to the head of the list of active ceilings 423// 424// Passed the ceiling motion structure 425// Returns nothing 426// 427void P_AddActiveCeiling(ceiling_t* ceiling) 428{ 429 ceilinglist_t *list = malloc(sizeof *list); 430 list->ceiling = ceiling; 431 ceiling->list = list; 432 if ((list->next = activeceilings)) 433 list->next->prev = &list->next; 434 list->prev = &activeceilings; 435 activeceilings = list; 436} 437 438// 439// P_RemoveActiveCeiling() 440// 441// Removes a ceiling from the list of active ceilings 442// 443// Passed the ceiling motion structure 444// Returns nothing 445// 446void P_RemoveActiveCeiling(ceiling_t* ceiling) 447{ 448 ceilinglist_t *list = ceiling->list; 449 ceiling->sector->ceilingdata = NULL; //jff 2/22/98 450 P_RemoveThinker(&ceiling->thinker); 451 if ((*list->prev = list->next)) 452 list->next->prev = list->prev; 453 free(list); 454} 455 456// 457// P_RemoveAllActiveCeilings() 458// 459// Removes all ceilings from the active ceiling list 460// 461// Passed nothing, returns nothing 462// 463void P_RemoveAllActiveCeilings(void) 464{ 465 while (activeceilings) 466 { 467 ceilinglist_t *next = activeceilings->next; 468 free(activeceilings); 469 activeceilings = next; 470 } 471}