plats.qc (8573B)
1 /* 2 plats.qc 3 4 platform functions 5 6 Copyright (C) 1996-1997 Id Software, Inc. 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License 10 as published by the Free Software Foundation; either version 2 11 of the License, or (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 17 See the GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to: 21 22 Free Software Foundation, Inc. 23 59 Temple Place - Suite 330 24 Boston, MA 02111-1307, USA 25 26 */ 27 28 29 void() plat_center_touch; 30 void() plat_outside_touch; 31 void() plat_trigger_use; 32 void() plat_go_up; 33 void() plat_go_down; 34 void() plat_crush; 35 float PLAT_LOW_TRIGGER = 1; 36 37 void() plat_spawn_inside_trigger = 38 { 39 local entity trigger; 40 local vector tmin, tmax; 41 42 // 43 // middle trigger 44 // 45 trigger = spawn(); 46 trigger.touch = plat_center_touch; 47 trigger.movetype = MOVETYPE_NONE; 48 trigger.solid = SOLID_TRIGGER; 49 trigger.enemy = self; 50 51 tmin = self.mins + '25 25 0'; 52 tmax = self.maxs - '25 25 -8'; 53 tmin_z = tmax_z - (self.pos1_z - self.pos2_z + 8); 54 if (self.spawnflags & PLAT_LOW_TRIGGER) 55 tmax_z = tmin_z + 8; 56 57 if (self.size_x <= 50) 58 { 59 tmin_x = (self.mins_x + self.maxs_x) / 2; 60 tmax_x = tmin_x + 1; 61 } 62 if (self.size_y <= 50) 63 { 64 tmin_y = (self.mins_y + self.maxs_y) / 2; 65 tmax_y = tmin_y + 1; 66 } 67 68 setsize (trigger, tmin, tmax); 69 }; 70 71 void() plat_hit_top = 72 { 73 sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self.noise1, 1, ATTN_NORM); 74 self.state = STATE_TOP; 75 self.think = plat_go_down; 76 self.nextthink = self.ltime + 3; 77 }; 78 79 void() plat_hit_bottom = 80 { 81 sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self.noise1, 1, ATTN_NORM); 82 self.state = STATE_BOTTOM; 83 }; 84 85 void() plat_go_down = 86 { 87 sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM); 88 self.state = STATE_DOWN; 89 SUB_CalcMove (self.pos2, self.speed, plat_hit_bottom); 90 }; 91 92 void() plat_go_up = 93 { 94 sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM); 95 self.state = STATE_UP; 96 SUB_CalcMove (self.pos1, self.speed, plat_hit_top); 97 }; 98 99 void() plat_center_touch = 100 { 101 if (other.classname != "player") 102 return; 103 104 if (other.health <= 0) 105 return; 106 107 self = self.enemy; 108 if (self.state == STATE_BOTTOM) 109 plat_go_up (); 110 else if (self.state == STATE_TOP) 111 self.nextthink = self.ltime + 1; // delay going down 112 }; 113 114 void() plat_outside_touch = 115 { 116 if (other.classname != "player") 117 return; 118 119 if (other.health <= 0) 120 return; 121 122 //dprint ("plat_outside_touch\n"); 123 self = self.enemy; 124 if (self.state == STATE_TOP) 125 plat_go_down (); 126 }; 127 128 void() plat_trigger_use = 129 { 130 if (self.think) 131 return; // allready activated 132 plat_go_down(); 133 }; 134 135 136 void() plat_crush = 137 { 138 //dprint ("plat_crush\n"); 139 140 other.deathtype = "squish"; 141 T_Damage (other, self, self, 1); 142 143 if (self.state == STATE_UP) 144 plat_go_down (); 145 else if (self.state == STATE_DOWN) 146 plat_go_up (); 147 else 148 objerror ("plat_crush: bad self.state\n"); 149 }; 150 151 void() plat_use = 152 { 153 self.use = SUB_Null; 154 if (self.state != STATE_UP) 155 objerror ("plat_use: not in up state"); 156 plat_go_down(); 157 }; 158 159 160 /*QUAKED func_plat (0 .5 .8) ? PLAT_LOW_TRIGGER 161 speed default 150 162 163 Plats are always drawn in the extended position, so they will light correctly. 164 165 If the plat is the target of another trigger or button, it will start out disabled in the extended position until it is trigger, when it will lower and become a normal plat. 166 167 If the "height" key is set, that will determine the amount the plat moves, instead of being implicitly determined by the model's height. 168 Set "sounds" to one of the following: 169 1) base fast 170 2) chain slow 171 */ 172 173 174 void() func_plat = 175 176 { 177 local entity t; 178 179 if (!self.t_length) 180 self.t_length = 80; 181 if (!self.t_width) 182 self.t_width = 10; 183 184 if (self.sounds == 0) 185 self.sounds = 2; 186 // FIX THIS TO LOAD A GENERIC PLAT SOUND 187 188 if (self.sounds == 1) 189 { 190 precache_sound ("plats/plat1.wav"); 191 precache_sound ("plats/plat2.wav"); 192 self.noise = "plats/plat1.wav"; 193 self.noise1 = "plats/plat2.wav"; 194 } 195 196 if (self.sounds == 2) 197 { 198 precache_sound ("plats/medplat1.wav"); 199 precache_sound ("plats/medplat2.wav"); 200 self.noise = "plats/medplat1.wav"; 201 self.noise1 = "plats/medplat2.wav"; 202 } 203 204 205 self.mangle = self.angles; 206 self.angles = '0 0 0'; 207 208 self.classname = "plat"; 209 self.solid = SOLID_BSP; 210 self.movetype = MOVETYPE_PUSH; 211 setorigin (self, self.origin); 212 setmodel (self, self.model); 213 setsize (self, self.mins , self.maxs); 214 215 self.blocked = plat_crush; 216 if (!self.speed) 217 self.speed = 150; 218 219 // pos1 is the top position, pos2 is the bottom 220 self.pos1 = self.origin; 221 self.pos2 = self.origin; 222 if (self.height) 223 self.pos2_z = self.origin_z - self.height; 224 else 225 self.pos2_z = self.origin_z - self.size_z + 8; 226 227 self.use = plat_trigger_use; 228 229 plat_spawn_inside_trigger (); // the "start moving" trigger 230 231 if (self.targetname) 232 { 233 self.state = STATE_UP; 234 self.use = plat_use; 235 } 236 else 237 { 238 setorigin (self, self.pos2); 239 self.state = STATE_BOTTOM; 240 } 241 }; 242 243 //============================================================================ 244 245 void() train_next; 246 void() func_train_find; 247 248 void() train_blocked = 249 { 250 if (time < self.attack_finished) 251 return; 252 self.attack_finished = time + 0.5; 253 other.deathtype = "squish"; 254 T_Damage (other, self, self, self.dmg); 255 }; 256 257 void() train_use = 258 { 259 if (self.think != func_train_find) 260 return; // already activated 261 train_next(); 262 }; 263 264 void() train_wait = 265 { 266 if (self.wait) 267 { 268 self.nextthink = self.ltime + self.wait; 269 sound (self, CHAN_NO_PHS_ADD+CHAN_VOICE, self.noise, 1, ATTN_NORM); 270 } 271 else 272 self.nextthink = self.ltime + 0.1; 273 274 self.think = train_next; 275 }; 276 277 void() train_next = 278 { 279 local entity targ; 280 281 targ = find (world, targetname, self.target); 282 self.target = targ.target; 283 if (!self.target) 284 objerror ("train_next: no next target"); 285 if (targ.wait) 286 self.wait = targ.wait; 287 else 288 self.wait = 0; 289 sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM); 290 SUB_CalcMove (targ.origin - self.mins, self.speed, train_wait); 291 }; 292 293 void() func_train_find = 294 295 { 296 local entity targ; 297 298 targ = find (world, targetname, self.target); 299 self.target = targ.target; 300 setorigin (self, targ.origin - self.mins); 301 if (!self.targetname) 302 { // not triggered, so start immediately 303 self.nextthink = self.ltime + 0.1; 304 self.think = train_next; 305 } 306 }; 307 308 /*QUAKED func_train (0 .5 .8) ? 309 Trains are moving platforms that players can ride. 310 The targets origin specifies the min point of the train at each corner. 311 The train spawns at the first target it is pointing at. 312 If the train is the target of a button or trigger, it will not begin moving until activated. 313 speed default 100 314 dmg default 2 315 sounds 316 1) ratchet metal 317 318 */ 319 void() func_train = 320 { 321 if (!self.speed) 322 self.speed = 100; 323 if (!self.target) 324 objerror ("func_train without a target"); 325 if (!self.dmg) 326 self.dmg = 2; 327 328 if (self.sounds == 0) 329 { 330 self.noise = ("misc/null.wav"); 331 precache_sound ("misc/null.wav"); 332 self.noise1 = ("misc/null.wav"); 333 precache_sound ("misc/null.wav"); 334 } 335 336 if (self.sounds == 1) 337 { 338 self.noise = ("plats/train2.wav"); 339 precache_sound ("plats/train2.wav"); 340 self.noise1 = ("plats/train1.wav"); 341 precache_sound ("plats/train1.wav"); 342 } 343 344 self.cnt = 1; 345 self.solid = SOLID_BSP; 346 self.movetype = MOVETYPE_PUSH; 347 self.blocked = train_blocked; 348 self.use = train_use; 349 self.classname = "train"; 350 351 setmodel (self, self.model); 352 setsize (self, self.mins , self.maxs); 353 setorigin (self, self.origin); 354 355 // start trains on the second frame, to make sure their targets have had 356 // a chance to spawn 357 self.nextthink = self.ltime + 0.1; 358 self.think = func_train_find; 359 }; 360 361 /*QUAKED misc_teleporttrain (0 .5 .8) (-8 -8 -8) (8 8 8) 362 This is used for the final bos 363 */ 364 void() misc_teleporttrain = 365 { 366 if (!self.speed) 367 self.speed = 100; 368 if (!self.target) 369 objerror ("func_train without a target"); 370 371 self.cnt = 1; 372 self.solid = SOLID_NOT; 373 self.movetype = MOVETYPE_PUSH; 374 self.blocked = train_blocked; 375 self.use = train_use; 376 self.avelocity = '100 200 300'; 377 378 self.noise = ("misc/null.wav"); 379 precache_sound ("misc/null.wav"); 380 self.noise1 = ("misc/null.wav"); 381 precache_sound ("misc/null.wav"); 382 383 precache_model2 ("progs/teleport.mdl"); 384 setmodel (self, "progs/teleport.mdl"); 385 setsize (self, self.mins , self.maxs); 386 setorigin (self, self.origin); 387 388 // start trains on the second frame, to make sure their targets have had 389 // a chance to spawn 390 self.nextthink = self.ltime + 0.1; 391 self.think = func_train_find; 392 }; 393