1 2/*QUAKED info_null (0 0.5 0) (-4 -4 -4) (4 4 4) 3Used as a positional target for spotlights, etc. 4*/ 5void() info_null = 6{ 7 remove(self); 8}; 9 10/*QUAKED info_notnull (0 0.5 0) (-4 -4 -4) (4 4 4) 11Used as a positional target for lightning. 12*/ 13void() info_notnull = 14{ 15}; 16 17//============================================================================ 18 19float START_OFF = 1; 20 21void() light_use = 22{ 23 if (self.spawnflags & START_OFF) 24 { 25 lightstyle(self.style, "m"); 26 self.spawnflags = self.spawnflags - START_OFF; 27 } 28 else 29 { 30 lightstyle(self.style, "a"); 31 self.spawnflags = self.spawnflags + START_OFF; 32 } 33}; 34 35/*QUAKED light (0 1 0) (-8 -8 -8) (8 8 8) START_OFF 36Non-displayed light. 37Default light value is 300 38Default style is 0 39If targeted, it will toggle between on or off. 40*/ 41void() light = 42{ 43 if (!self.targetname) 44 { // inert light 45 remove(self); 46 return; 47 } 48 49 if (self.style >= 32) 50 { 51 self.use = light_use; 52 if (self.spawnflags & START_OFF) 53 lightstyle(self.style, "a"); 54 else 55 lightstyle(self.style, "m"); 56 } 57}; 58 59/*QUAKED light_fluoro (0 1 0) (-8 -8 -8) (8 8 8) START_OFF 60Non-displayed light. 61Default light value is 300 62Default style is 0 63If targeted, it will toggle between on or off. 64Makes steady fluorescent humming sound 65*/ 66void() light_fluoro = 67{ 68 if (self.style >= 32) 69 { 70 self.use = light_use; 71 if (self.spawnflags & START_OFF) 72 lightstyle(self.style, "a"); 73 else 74 lightstyle(self.style, "m"); 75 } 76 77 precache_sound ("ambience/fl_hum1.wav"); 78 ambientsound (self.origin, "ambience/fl_hum1.wav", 0.5, ATTN_STATIC); 79}; 80 81/*QUAKED light_fluorospark (0 1 0) (-8 -8 -8) (8 8 8) 82Non-displayed light. 83Default light value is 300 84Default style is 10 85Makes sparking, broken fluorescent sound 86*/ 87void() light_fluorospark = 88{ 89 if (!self.style) 90 self.style = 10; 91 92 precache_sound ("ambience/buzz1.wav"); 93 ambientsound (self.origin, "ambience/buzz1.wav", 0.5, ATTN_STATIC); 94}; 95 96/*QUAKED light_globe (0 1 0) (-8 -8 -8) (8 8 8) 97Sphere globe light. 98Default light value is 300 99Default style is 0 100*/ 101void() light_globe = 102{ 103 precache_model ("progs/s_light.spr"); 104 setmodel (self, "progs/s_light.spr"); 105 makestatic (self); 106}; 107 108void() FireAmbient = 109{ 110 precache_sound ("ambience/fire1.wav"); 111// attenuate fast 112 ambientsound (self.origin, "ambience/fire1.wav", 0.5, ATTN_STATIC); 113}; 114 115/*QUAKED light_torch_small_walltorch (0 .5 0) (-10 -10 -20) (10 10 20) 116Short wall torch 117Default light value is 200 118Default style is 0 119*/ 120void() light_torch_small_walltorch = 121{ 122 precache_model ("progs/flame.mdl"); 123 setmodel (self, "progs/flame.mdl"); 124 FireAmbient (); 125 makestatic (self); 126}; 127 128/*QUAKED light_flame_large_yellow (0 1 0) (-10 -10 -12) (12 12 18) 129Large yellow flame ball 130*/ 131void() light_flame_large_yellow = 132{ 133 precache_model ("progs/flame2.mdl"); 134 setmodel (self, "progs/flame2.mdl"); 135 self.frame = 1; 136 FireAmbient (); 137 makestatic (self); 138}; 139 140/*QUAKED light_flame_small_yellow (0 1 0) (-8 -8 -8) (8 8 8) START_OFF 141Small yellow flame ball 142*/ 143void() light_flame_small_yellow = 144{ 145 precache_model ("progs/flame2.mdl"); 146 setmodel (self, "progs/flame2.mdl"); 147 FireAmbient (); 148 makestatic (self); 149}; 150 151/*QUAKED light_flame_small_white (0 1 0) (-10 -10 -40) (10 10 40) START_OFF 152Small white flame ball 153*/ 154void() light_flame_small_white = 155{ 156 precache_model ("progs/flame2.mdl"); 157 setmodel (self, "progs/flame2.mdl"); 158 FireAmbient (); 159 makestatic (self); 160}; 161 162//============================================================================ 163 164 165/*QUAKED misc_fireball (0 .5 .8) (-8 -8 -8) (8 8 8) 166Lava Balls 167*/ 168 169void() fire_fly; 170void() fire_touch; 171void() misc_fireball = 172{ 173 174 precache_model ("progs/lavaball.mdl"); 175 self.classname = "fireball"; 176 self.nextthink = time + (random() * 5); 177 self.think = fire_fly; 178 if (!self.speed) 179 self.speed == 1000; 180}; 181 182void() fire_fly = 183{ 184local entity fireball; 185 186 fireball = spawn(); 187 fireball.solid = SOLID_TRIGGER; 188 fireball.movetype = MOVETYPE_TOSS; 189 fireball.velocity = '0 0 1000'; 190 fireball.velocity_x = (random() * 100) - 50; 191 fireball.velocity_y = (random() * 100) - 50; 192 fireball.velocity_z = self.speed + (random() * 200); 193 fireball.classname = "fireball"; 194 setmodel (fireball, "progs/lavaball.mdl"); 195 setsize (fireball, '0 0 0', '0 0 0'); 196 setorigin (fireball, self.origin); 197 fireball.nextthink = time + 5; 198 fireball.think = SUB_Remove; 199 fireball.touch = fire_touch; 200 201 self.nextthink = time + (random() * 5) + 3; 202 self.think = fire_fly; 203}; 204 205 206void() fire_touch = 207{ 208 T_Damage (other, self, self, 20); 209 remove(self); 210}; 211 212//============================================================================ 213 214 215void() barrel_explode = 216{ 217 self.takedamage = DAMAGE_NO; 218 self.classname = "explo_box"; 219 // did say self.owner 220 T_RadiusDamage (self, self, 160, world, ""); 221 WriteByte (MSG_MULTICAST, SVC_TEMPENTITY); 222 WriteByte (MSG_MULTICAST, TE_EXPLOSION); 223 WriteCoord (MSG_MULTICAST, self.origin_x); 224 WriteCoord (MSG_MULTICAST, self.origin_y); 225 WriteCoord (MSG_MULTICAST, self.origin_z+32); 226 multicast (self.origin, MULTICAST_PHS); 227 remove (self); 228}; 229 230 231 232/*QUAKED misc_explobox (0 .5 .8) (0 0 0) (32 32 64) 233TESTING THING 234*/ 235 236void() misc_explobox = 237{ 238 local float oldz; 239 240 self.solid = SOLID_BBOX; 241 self.movetype = MOVETYPE_NONE; 242 precache_model ("maps/b_explob.bsp"); 243 setmodel (self, "maps/b_explob.bsp"); 244 setsize (self, '0 0 0', '32 32 64'); 245 precache_sound ("weapons/r_exp3.wav"); 246 self.health = 20; 247 self.th_die = barrel_explode; 248 self.takedamage = DAMAGE_AIM; 249 250 self.origin_z = self.origin_z + 2; 251 oldz = self.origin_z; 252 droptofloor(); 253 if (oldz - self.origin_z > 250) 254 { 255 dprint ("item fell out of level at "); 256 dprint (vtos(self.origin)); 257 dprint ("\n"); 258 remove(self); 259 } 260}; 261 262 263 264 265/*QUAKED misc_explobox2 (0 .5 .8) (0 0 0) (32 32 64) 266Smaller exploding box, REGISTERED ONLY 267*/ 268 269void() misc_explobox2 = 270{ 271 local float oldz; 272 273 self.solid = SOLID_BBOX; 274 self.movetype = MOVETYPE_NONE; 275 precache_model2 ("maps/b_exbox2.bsp"); 276 setmodel (self, "maps/b_exbox2.bsp"); 277 setsize (self, '0 0 0', '32 32 32'); 278 precache_sound ("weapons/r_exp3.wav"); 279 self.health = 20; 280 self.th_die = barrel_explode; 281 self.takedamage = DAMAGE_AIM; 282 283 self.origin_z = self.origin_z + 2; 284 oldz = self.origin_z; 285 droptofloor(); 286 if (oldz - self.origin_z > 250) 287 { 288 dprint ("item fell out of level at "); 289 dprint (vtos(self.origin)); 290 dprint ("\n"); 291 remove(self); 292 } 293}; 294 295//============================================================================ 296 297float SPAWNFLAG_SUPERSPIKE = 1; 298float SPAWNFLAG_LASER = 2; 299 300void() Laser_Touch = 301{ 302 local vector org; 303 304 if (other == self.owner) 305 return; // don't explode on owner 306 307 if (pointcontents(self.origin) == CONTENT_SKY) 308 { 309 remove(self); 310 return; 311 } 312 313 sound (self, CHAN_WEAPON, "enforcer/enfstop.wav", 1, ATTN_STATIC); 314 org = self.origin - 8*normalize(self.velocity); 315 316 if (other.health) 317 { 318 SpawnBlood (org, 15); 319 other.deathtype = "laser"; 320 T_Damage (other, self, self.owner, 15); 321 } 322 else 323 { 324 WriteByte (MSG_MULTICAST, SVC_TEMPENTITY); 325 WriteByte (MSG_MULTICAST, TE_GUNSHOT); 326 WriteByte (MSG_MULTICAST, 5); 327 WriteCoord (MSG_MULTICAST, org_x); 328 WriteCoord (MSG_MULTICAST, org_y); 329 WriteCoord (MSG_MULTICAST, org_z); 330 multicast (org, MULTICAST_PVS); 331 } 332 333 remove(self); 334}; 335 336void(vector org, vector vec) LaunchLaser = 337{ 338 local vector vec; 339 340 if (self.classname == "monster_enforcer") 341 sound (self, CHAN_WEAPON, "enforcer/enfire.wav", 1, ATTN_NORM); 342 343 vec = normalize(vec); 344 345 newmis = spawn(); 346 newmis.owner = self; 347 newmis.movetype = MOVETYPE_FLY; 348 newmis.solid = SOLID_BBOX; 349 newmis.effects = EF_DIMLIGHT; 350 351 setmodel (newmis, "progs/laser.mdl"); 352 setsize (newmis, '0 0 0', '0 0 0'); 353 354 setorigin (newmis, org); 355 356 newmis.velocity = vec * 600; 357 newmis.angles = vectoangles(newmis.velocity); 358 359 newmis.nextthink = time + 5; 360 newmis.think = SUB_Remove; 361 newmis.touch = Laser_Touch; 362}; 363 364void() spikeshooter_use = 365{ 366 if (self.spawnflags & SPAWNFLAG_LASER) 367 { 368 sound (self, CHAN_VOICE, "enforcer/enfire.wav", 1, ATTN_NORM); 369 LaunchLaser (self.origin, self.movedir); 370 } 371 else 372 { 373 sound (self, CHAN_VOICE, "weapons/spike2.wav", 1, ATTN_NORM); 374 launch_spike (self.origin, self.movedir); 375 newmis.velocity = self.movedir * 500; 376 if (self.spawnflags & SPAWNFLAG_SUPERSPIKE) 377 newmis.touch = superspike_touch; 378 } 379}; 380 381void() shooter_think = 382{ 383 spikeshooter_use (); 384 self.nextthink = time + self.wait; 385 newmis.velocity = self.movedir * 500; 386}; 387 388 389/*QUAKED trap_spikeshooter (0 .5 .8) (-8 -8 -8) (8 8 8) superspike laser 390When triggered, fires a spike in the direction set in QuakeEd. 391Laser is only for REGISTERED. 392*/ 393 394void() trap_spikeshooter = 395{ 396 SetMovedir (); 397 self.use = spikeshooter_use; 398 if (self.spawnflags & SPAWNFLAG_LASER) 399 { 400 precache_model2 ("progs/laser.mdl"); 401 402 precache_sound2 ("enforcer/enfire.wav"); 403 precache_sound2 ("enforcer/enfstop.wav"); 404 } 405 else 406 precache_sound ("weapons/spike2.wav"); 407}; 408 409 410/*QUAKED trap_shooter (0 .5 .8) (-8 -8 -8) (8 8 8) superspike laser 411Continuously fires spikes. 412"wait" time between spike (1.0 default) 413"nextthink" delay before firing first spike, so multiple shooters can be stagered. 414*/ 415void() trap_shooter = 416{ 417 trap_spikeshooter (); 418 419 if (self.wait == 0) 420 self.wait = 1; 421 self.nextthink = self.nextthink + self.wait + self.ltime; 422 self.think = shooter_think; 423}; 424 425 426 427/* 428=============================================================================== 429 430 431=============================================================================== 432*/ 433 434 435void() make_bubbles; 436void() bubble_remove; 437void() bubble_bob; 438 439/*QUAKED air_bubbles (0 .5 .8) (-8 -8 -8) (8 8 8) 440 441testing air bubbles 442*/ 443 444void() air_bubbles = 445{ 446 remove (self); 447}; 448 449void() make_bubbles = 450{ 451local entity bubble; 452 453 bubble = spawn(); 454 setmodel (bubble, "progs/s_bubble.spr"); 455 setorigin (bubble, self.origin); 456 bubble.movetype = MOVETYPE_NOCLIP; 457 bubble.solid = SOLID_NOT; 458 bubble.velocity = '0 0 15'; 459 bubble.nextthink = time + 0.5; 460 bubble.think = bubble_bob; 461 bubble.touch = bubble_remove; 462 bubble.classname = "bubble"; 463 bubble.frame = 0; 464 bubble.cnt = 0; 465 setsize (bubble, '-8 -8 -8', '8 8 8'); 466 self.nextthink = time + random() + 0.5; 467 self.think = make_bubbles; 468}; 469 470void() bubble_split = 471{ 472local entity bubble; 473 bubble = spawn(); 474 setmodel (bubble, "progs/s_bubble.spr"); 475 setorigin (bubble, self.origin); 476 bubble.movetype = MOVETYPE_NOCLIP; 477 bubble.solid = SOLID_NOT; 478 bubble.velocity = self.velocity; 479 bubble.nextthink = time + 0.5; 480 bubble.think = bubble_bob; 481 bubble.touch = bubble_remove; 482 bubble.classname = "bubble"; 483 bubble.frame = 1; 484 bubble.cnt = 10; 485 setsize (bubble, '-8 -8 -8', '8 8 8'); 486 self.frame = 1; 487 self.cnt = 10; 488 if (self.waterlevel != 3) 489 remove (self); 490}; 491 492void() bubble_remove = 493{ 494 if (other.classname == self.classname) 495 { 496// dprint ("bump"); 497 return; 498 } 499 remove(self); 500}; 501 502void() bubble_bob = 503{ 504local float rnd1, rnd2, rnd3; 505local vector vtmp1, modi; 506 507 self.cnt = self.cnt + 1; 508 if (self.cnt == 4) 509 bubble_split(); 510 if (self.cnt == 20) 511 remove(self); 512 513 rnd1 = self.velocity_x + (-10 + (random() * 20)); 514 rnd2 = self.velocity_y + (-10 + (random() * 20)); 515 rnd3 = self.velocity_z + 10 + random() * 10; 516 517 if (rnd1 > 10) 518 rnd1 = 5; 519 if (rnd1 < -10) 520 rnd1 = -5; 521 522 if (rnd2 > 10) 523 rnd2 = 5; 524 if (rnd2 < -10) 525 rnd2 = -5; 526 527 if (rnd3 < 10) 528 rnd3 = 15; 529 if (rnd3 > 30) 530 rnd3 = 25; 531 532 self.velocity_x = rnd1; 533 self.velocity_y = rnd2; 534 self.velocity_z = rnd3; 535 536 self.nextthink = time + 0.5; 537 self.think = bubble_bob; 538}; 539 540/*~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~> 541~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~<~>~*/ 542 543/*QUAKED viewthing (0 .5 .8) (-8 -8 -8) (8 8 8) 544 545Just for the debugging level. Don't use 546*/ 547 548void() viewthing = 549 550{ 551 self.movetype = MOVETYPE_NONE; 552 self.solid = SOLID_NOT; 553 precache_model ("progs/player.mdl"); 554 setmodel (self, "progs/player.mdl"); 555}; 556 557 558/* 559============================================================================== 560 561SIMPLE BMODELS 562 563============================================================================== 564*/ 565 566void() func_wall_use = 567{ // change to alternate textures 568 self.frame = 1 - self.frame; 569}; 570 571/*QUAKED func_wall (0 .5 .8) ? 572This is just a solid wall if not inhibitted 573*/ 574void() func_wall = 575{ 576 self.angles = '0 0 0'; 577 self.movetype = MOVETYPE_PUSH; // so it doesn't get pushed by anything 578 self.solid = SOLID_BSP; 579 self.use = func_wall_use; 580 setmodel (self, self.model); 581}; 582 583 584/*QUAKED func_illusionary (0 .5 .8) ? 585A simple entity that looks solid but lets you walk through it. 586*/ 587void() func_illusionary = 588 589{ 590 self.angles = '0 0 0'; 591 self.movetype = MOVETYPE_NONE; 592 self.solid = SOLID_NOT; 593 setmodel (self, self.model); 594 makestatic (); 595}; 596 597/*QUAKED func_episodegate (0 .5 .8) ? E1 E2 E3 E4 598This bmodel will appear if the episode has allready been completed, so players can't reenter it. 599*/ 600void() func_episodegate = 601 602{ 603 if (!(serverflags & self.spawnflags)) 604 return; // can still enter episode 605 606 self.angles = '0 0 0'; 607 self.movetype = MOVETYPE_PUSH; // so it doesn't get pushed by anything 608 self.solid = SOLID_BSP; 609 self.use = func_wall_use; 610 setmodel (self, self.model); 611}; 612 613/*QUAKED func_bossgate (0 .5 .8) ? 614This bmodel appears unless players have all of the episode sigils. 615*/ 616void() func_bossgate = 617 618{ 619 if ( (serverflags & 15) == 15) 620 return; // all episodes completed 621 self.angles = '0 0 0'; 622 self.movetype = MOVETYPE_PUSH; // so it doesn't get pushed by anything 623 self.solid = SOLID_BSP; 624 self.use = func_wall_use; 625 setmodel (self, self.model); 626}; 627 628//============================================================================ 629/*QUAKED ambient_suck_wind (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) 630*/ 631void() ambient_suck_wind = 632{ 633 precache_sound ("ambience/suck1.wav"); 634 ambientsound (self.origin, "ambience/suck1.wav", 1, ATTN_STATIC); 635}; 636 637/*QUAKED ambient_drone (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) 638*/ 639void() ambient_drone = 640{ 641 precache_sound ("ambience/drone6.wav"); 642 ambientsound (self.origin, "ambience/drone6.wav", 0.5, ATTN_STATIC); 643}; 644 645/*QUAKED ambient_flouro_buzz (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) 646*/ 647void() ambient_flouro_buzz = 648{ 649 precache_sound ("ambience/buzz1.wav"); 650 ambientsound (self.origin, "ambience/buzz1.wav", 1, ATTN_STATIC); 651}; 652/*QUAKED ambient_drip (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) 653*/ 654void() ambient_drip = 655{ 656 precache_sound ("ambience/drip1.wav"); 657 ambientsound (self.origin, "ambience/drip1.wav", 0.5, ATTN_STATIC); 658}; 659/*QUAKED ambient_comp_hum (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) 660*/ 661void() ambient_comp_hum = 662{ 663 precache_sound ("ambience/comp1.wav"); 664 ambientsound (self.origin, "ambience/comp1.wav", 1, ATTN_STATIC); 665}; 666/*QUAKED ambient_thunder (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) 667*/ 668void() ambient_thunder = 669{ 670 precache_sound ("ambience/thunder1.wav"); 671 ambientsound (self.origin, "ambience/thunder1.wav", 0.5, ATTN_STATIC); 672}; 673/*QUAKED ambient_light_buzz (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) 674*/ 675void() ambient_light_buzz = 676{ 677 precache_sound ("ambience/fl_hum1.wav"); 678 ambientsound (self.origin, "ambience/fl_hum1.wav", 0.5, ATTN_STATIC); 679}; 680/*QUAKED ambient_swamp1 (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) 681*/ 682void() ambient_swamp1 = 683{ 684 precache_sound ("ambience/swamp1.wav"); 685 ambientsound (self.origin, "ambience/swamp1.wav", 0.5, ATTN_STATIC); 686}; 687/*QUAKED ambient_swamp2 (0.3 0.1 0.6) (-10 -10 -8) (10 10 8) 688*/ 689void() ambient_swamp2 = 690{ 691 precache_sound ("ambience/swamp2.wav"); 692 ambientsound (self.origin, "ambience/swamp2.wav", 0.5, ATTN_STATIC); 693}; 694 695//============================================================================ 696 697void() noise_think = 698{ 699 self.nextthink = time + 0.5; 700 sound (self, 1, "enforcer/enfire.wav", 1, ATTN_NORM); 701 sound (self, 2, "enforcer/enfstop.wav", 1, ATTN_NORM); 702 sound (self, 3, "enforcer/sight1.wav", 1, ATTN_NORM); 703 sound (self, 4, "enforcer/sight2.wav", 1, ATTN_NORM); 704 sound (self, 5, "enforcer/sight3.wav", 1, ATTN_NORM); 705 sound (self, 6, "enforcer/sight4.wav", 1, ATTN_NORM); 706 sound (self, 7, "enforcer/pain1.wav", 1, ATTN_NORM); 707}; 708 709/*QUAKED misc_noisemaker (1 0.5 0) (-10 -10 -10) (10 10 10) 710 711For optimzation testing, starts a lot of sounds. 712*/ 713 714void() misc_noisemaker = 715 716{ 717 precache_sound2 ("enforcer/enfire.wav"); 718 precache_sound2 ("enforcer/enfstop.wav"); 719 precache_sound2 ("enforcer/sight1.wav"); 720 precache_sound2 ("enforcer/sight2.wav"); 721 precache_sound2 ("enforcer/sight3.wav"); 722 precache_sound2 ("enforcer/sight4.wav"); 723 precache_sound2 ("enforcer/pain1.wav"); 724 precache_sound2 ("enforcer/pain2.wav"); 725 precache_sound2 ("enforcer/death1.wav"); 726 precache_sound2 ("enforcer/idle1.wav"); 727 728 self.nextthink = time + 0.1 + random(); 729 self.think = noise_think; 730}; 731