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