p_plats.cpp (7464B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. 23 24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. 25 26 =========================================================================== 27 */ 28 29 #include "Precompiled.h" 30 #include "globaldata.h" 31 32 33 #include "i_system.h" 34 #include "z_zone.h" 35 #include "m_random.h" 36 37 #include "doomdef.h" 38 #include "p_local.h" 39 40 #include "s_sound.h" 41 42 // State. 43 #include "doomstat.h" 44 #include "r_state.h" 45 46 // Data. 47 #include "sounds.h" 48 49 50 51 52 53 // 54 // Move a plat up and down 55 // 56 void T_PlatRaise(plat_t* plat) 57 { 58 result_e res; 59 60 switch(plat->status) 61 { 62 case up: 63 res = T_MovePlane(plat->sector, 64 plat->speed, 65 plat->high, 66 plat->crush,0,1); 67 68 if (plat->type == raiseAndChange 69 || plat->type == raiseToNearestAndChange) 70 { 71 if (!(::g->leveltime&7)) 72 S_StartSound( &plat->sector->soundorg, 73 sfx_stnmov); 74 } 75 76 77 if (res == crushed && (!plat->crush)) 78 { 79 plat->count = plat->wait; 80 plat->status = down; 81 S_StartSound( &plat->sector->soundorg, 82 sfx_pstart); 83 } 84 else 85 { 86 if (res == pastdest) 87 { 88 plat->count = plat->wait; 89 plat->status = waiting; 90 S_StartSound( &plat->sector->soundorg, 91 sfx_pstop); 92 93 switch(plat->type) 94 { 95 case blazeDWUS: 96 case downWaitUpStay: 97 P_RemoveActivePlat(plat); 98 break; 99 100 case raiseAndChange: 101 case raiseToNearestAndChange: 102 P_RemoveActivePlat(plat); 103 break; 104 105 default: 106 break; 107 } 108 } 109 } 110 break; 111 112 case down: 113 res = T_MovePlane(plat->sector,plat->speed,plat->low,false,0,-1); 114 115 if (res == pastdest) 116 { 117 plat->count = plat->wait; 118 plat->status = waiting; 119 S_StartSound( &plat->sector->soundorg,sfx_pstop); 120 } 121 break; 122 123 case waiting: 124 if (!--plat->count) 125 { 126 if (plat->sector->floorheight == plat->low) 127 plat->status = up; 128 else 129 plat->status = down; 130 S_StartSound( &plat->sector->soundorg,sfx_pstart); 131 } 132 case in_stasis: 133 break; 134 } 135 } 136 137 138 // 139 // Do Platforms 140 // "amount" is only used for SOME platforms. 141 // 142 int 143 EV_DoPlat 144 ( line_t* line, 145 plattype_e type, 146 int amount ) 147 { 148 plat_t* plat; 149 int secnum; 150 int rtn; 151 sector_t* sec; 152 153 secnum = -1; 154 rtn = 0; 155 156 157 // Activate all <type> plats that are in_stasis 158 switch(type) 159 { 160 case perpetualRaise: 161 P_ActivateInStasis(line->tag); 162 break; 163 164 default: 165 break; 166 } 167 168 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) 169 { 170 sec = &::g->sectors[secnum]; 171 172 if (sec->specialdata) 173 continue; 174 175 // Find lowest & highest floors around sector 176 rtn = 1; 177 plat = (plat_t*)DoomLib::Z_Malloc( sizeof(*plat), PU_LEVEL, 0); 178 P_AddThinker(&plat->thinker); 179 180 plat->type = type; 181 plat->sector = sec; 182 plat->sector->specialdata = plat; 183 plat->thinker.function.acp1 = (actionf_p1) T_PlatRaise; 184 plat->crush = false; 185 plat->tag = line->tag; 186 187 switch(type) 188 { 189 case raiseToNearestAndChange: 190 plat->speed = PLATSPEED/2; 191 sec->floorpic = ::g->sides[line->sidenum[0]].sector->floorpic; 192 plat->high = P_FindNextHighestFloor(sec,sec->floorheight); 193 plat->wait = 0; 194 plat->status = up; 195 // NO MORE DAMAGE, IF APPLICABLE 196 sec->special = 0; 197 198 S_StartSound( &sec->soundorg,sfx_stnmov); 199 break; 200 201 case raiseAndChange: 202 plat->speed = PLATSPEED/2; 203 sec->floorpic = ::g->sides[line->sidenum[0]].sector->floorpic; 204 plat->high = sec->floorheight + amount*FRACUNIT; 205 plat->wait = 0; 206 plat->status = up; 207 208 S_StartSound( &sec->soundorg,sfx_stnmov); 209 break; 210 211 case downWaitUpStay: 212 plat->speed = PLATSPEED * 4; 213 plat->low = P_FindLowestFloorSurrounding(sec); 214 215 if (plat->low > sec->floorheight) 216 plat->low = sec->floorheight; 217 218 plat->high = sec->floorheight; 219 plat->wait = TICRATE*PLATWAIT; 220 plat->status = down; 221 S_StartSound( &sec->soundorg,sfx_pstart); 222 break; 223 224 case blazeDWUS: 225 plat->speed = PLATSPEED * 8; 226 plat->low = P_FindLowestFloorSurrounding(sec); 227 228 if (plat->low > sec->floorheight) 229 plat->low = sec->floorheight; 230 231 plat->high = sec->floorheight; 232 plat->wait = TICRATE*PLATWAIT; 233 plat->status = down; 234 S_StartSound( &sec->soundorg,sfx_pstart); 235 break; 236 237 case perpetualRaise: 238 plat->speed = PLATSPEED; 239 plat->low = P_FindLowestFloorSurrounding(sec); 240 241 if (plat->low > sec->floorheight) 242 plat->low = sec->floorheight; 243 244 plat->high = P_FindHighestFloorSurrounding(sec); 245 246 if (plat->high < sec->floorheight) 247 plat->high = sec->floorheight; 248 249 plat->wait = TICRATE*PLATWAIT; 250 plat->status = (plat_e)(P_Random()&1); 251 252 S_StartSound( &sec->soundorg,sfx_pstart); 253 break; 254 } 255 P_AddActivePlat(plat); 256 } 257 return rtn; 258 } 259 260 261 262 void P_ActivateInStasis(int tag) 263 { 264 int i; 265 266 for (i = 0;i < MAXPLATS;i++) 267 if (::g->activeplats[i] 268 && (::g->activeplats[i])->tag == tag 269 && (::g->activeplats[i])->status == in_stasis) 270 { 271 (::g->activeplats[i])->status = (::g->activeplats[i])->oldstatus; 272 (::g->activeplats[i])->thinker.function.acp1 273 = (actionf_p1) T_PlatRaise; 274 } 275 } 276 277 void EV_StopPlat(line_t* line) 278 { 279 int j; 280 281 for (j = 0;j < MAXPLATS;j++) 282 if (::g->activeplats[j] 283 && ((::g->activeplats[j])->status != in_stasis) 284 && ((::g->activeplats[j])->tag == line->tag)) 285 { 286 (::g->activeplats[j])->oldstatus = (::g->activeplats[j])->status; 287 (::g->activeplats[j])->status = in_stasis; 288 (::g->activeplats[j])->thinker.function.acv = (actionf_v)NULL; 289 } 290 } 291 292 void P_AddActivePlat(plat_t* plat) 293 { 294 int i; 295 296 for (i = 0;i < MAXPLATS;i++) 297 if (::g->activeplats[i] == NULL) 298 { 299 ::g->activeplats[i] = plat; 300 return; 301 } 302 I_Error ("P_AddActivePlat: no more plats!"); 303 } 304 305 void P_RemoveActivePlat(plat_t* plat) 306 { 307 int i; 308 for (i = 0;i < MAXPLATS;i++) 309 if (plat == ::g->activeplats[i]) 310 { 311 (::g->activeplats[i])->sector->specialdata = NULL; 312 P_RemoveThinker(&(::g->activeplats[i])->thinker); 313 ::g->activeplats[i] = NULL; 314 315 return; 316 } 317 I_Error ("P_RemoveActivePlat: can't find plat!"); 318 } 319