2 void generic_plat_blocked()
4 if(self.dmg && other.takedamage != DAMAGE_NO) {
5 if(self.dmgtime2 < time) {
6 Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
7 self.dmgtime2 = time + self.dmgtime;
10 // Gib dead/dying stuff
11 if(other.deadflag != DEAD_NO)
12 Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
18 float STATE_BOTTOM = 1;
22 .entity trigger_field;
24 void() plat_center_touch;
25 void() plat_outside_touch;
26 void() plat_trigger_use;
30 float PLAT_LOW_TRIGGER = 1;
32 void plat_spawn_inside_trigger()
35 local vector tmin, tmax;
38 trigger.touch = plat_center_touch;
39 trigger.movetype = MOVETYPE_NONE;
40 trigger.solid = SOLID_TRIGGER;
43 tmin = self.absmin + '25 25 0';
44 tmax = self.absmax - '25 25 -8';
45 tmin_z = tmax_z - (self.pos1_z - self.pos2_z + 8);
46 if (self.spawnflags & PLAT_LOW_TRIGGER)
49 if (self.size_x <= 50)
51 tmin_x = (self.mins_x + self.maxs_x) / 2;
54 if (self.size_y <= 50)
56 tmin_y = (self.mins_y + self.maxs_y) / 2;
60 setsize (trigger, tmin, tmax);
65 sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
67 self.think = plat_go_down;
68 self.nextthink = self.ltime + 3;
71 void plat_hit_bottom()
73 sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
79 sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_NORM);
81 SUB_CalcMove (self.pos2, self.speed, plat_hit_bottom);
86 sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_NORM);
88 SUB_CalcMove (self.pos1, self.speed, plat_hit_top);
91 void plat_center_touch()
93 if not(other.iscreature)
96 if (other.health <= 0)
102 else if (self.state == 1)
103 self.nextthink = self.ltime + 1; // delay going down
106 void plat_outside_touch()
108 if not(other.iscreature)
111 if (other.health <= 0)
119 void plat_trigger_use()
122 return; // already activated
129 if((self.spawnflags & 4) && (other.takedamage != DAMAGE_NO)) { // KIll Kill Kill!!
130 Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
132 if((self.dmg) && (other.takedamage != DAMAGE_NO)) { // Shall we bite?
133 Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
134 // Gib dead/dying stuff
135 if(other.deadflag != DEAD_NO)
136 Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
141 else if (self.state == 3)
143 // when in other states, then the plat_crush event came delayed after
144 // plat state already had changed
145 // this isn't a bug per se!
153 objerror ("plat_use: not in up state");
157 .string sound1, sound2;
163 setorigin (self, self.pos1);
169 setorigin (self, self.pos2);
171 self.use = plat_trigger_use;
175 void spawnfunc_path_corner() { };
176 void spawnfunc_func_plat()
183 if (self.sounds == 0)
186 if(self.spawnflags & 4)
189 if(self.dmg && (!self.message))
190 self.message = "was squished";
191 if(self.dmg && (!self.message2))
192 self.message2 = "was squished by";
194 if (self.sounds == 1)
196 precache_sound ("plats/plat1.wav");
197 precache_sound ("plats/plat2.wav");
198 self.noise = "plats/plat1.wav";
199 self.noise1 = "plats/plat2.wav";
202 if (self.sounds == 2)
204 precache_sound ("plats/medplat1.wav");
205 precache_sound ("plats/medplat2.wav");
206 self.noise = "plats/medplat1.wav";
207 self.noise1 = "plats/medplat2.wav";
212 precache_sound (self.sound1);
213 self.noise = self.sound1;
217 precache_sound (self.sound2);
218 self.noise1 = self.sound2;
221 self.mangle = self.angles;
222 self.angles = '0 0 0';
224 self.classname = "plat";
225 if not(InitMovingBrushTrigger())
227 self.effects |= EF_LOWPRECISION;
228 setsize (self, self.mins , self.maxs);
230 self.blocked = plat_crush;
235 self.pos1 = self.origin;
236 self.pos2 = self.origin;
237 self.pos2_z = self.origin_z - self.size_z + 8;
239 plat_spawn_inside_trigger (); // the "start moving" trigger
241 self.reset = plat_reset;
250 stopsoundto(MSG_BROADCAST, self, CH_TRIGGER_SINGLE); // send this as unreliable only, as the train will resume operation shortly anyway
258 self.think = train_next;
259 self.nextthink = self.ltime + self.wait;
273 targ = find(world, targetname, self.target);
275 self.target = targ.target;
277 objerror("train_next: no next target");
278 self.wait = targ.wait;
283 SUB_CalcMove(targ.origin - self.mins, targ.speed, train_wait);
285 SUB_CalcMove(targ.origin - self.mins, self.speed, train_wait);
288 sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE);
291 void func_train_find()
294 targ = find(world, targetname, self.target);
295 self.target = targ.target;
297 objerror("func_train_find: no next target");
298 setorigin(self, targ.origin - self.mins);
299 self.nextthink = self.ltime + 1;
300 self.think = train_next;
303 /*QUAKED spawnfunc_func_train (0 .5 .8) ?
304 Ridable platform, targets spawnfunc_path_corner path to follow.
305 speed : speed the train moves (can be overridden by each spawnfunc_path_corner)
306 target : targetname of first spawnfunc_path_corner (starts here)
308 void spawnfunc_func_train()
310 if (self.noise != "")
311 precache_sound(self.noise);
314 objerror("func_train without a target");
318 if not(InitMovingBrushTrigger())
320 self.effects |= EF_LOWPRECISION;
322 // wait for targets to spawn
323 InitializeEntity(self, func_train_find, INITPRIO_SETLOCATION);
325 self.blocked = generic_plat_blocked;
326 if(self.dmg & (!self.message))
327 self.message = " was squished";
328 if(self.dmg && (!self.message2))
329 self.message2 = "was squished by";
330 if(self.dmg && (!self.dmgtime))
332 self.dmgtime2 = time;
334 // TODO make a reset function for this one
337 void func_rotating_setactive(float astate)
340 if (astate == ACTIVE_TOGGLE)
342 if(self.active == ACTIVE_ACTIVE)
343 self.active = ACTIVE_NOT;
345 self.active = ACTIVE_ACTIVE;
348 self.active = astate;
350 if(self.active == ACTIVE_NOT)
351 self.avelocity = '0 0 0';
353 self.avelocity = self.pos1;
356 /*QUAKED spawnfunc_func_rotating (0 .5 .8) ? - - X_AXIS Y_AXIS
357 Brush model that spins in place on one axis (default Z).
358 speed : speed to rotate (in degrees per second)
359 noise : path/name of looping .wav file to play.
360 dmg : Do this mutch dmg every .dmgtime intervall when blocked
364 void spawnfunc_func_rotating()
366 if (self.noise != "")
368 precache_sound(self.noise);
369 ambientsound(self.origin, self.noise, VOL_BASE, ATTN_IDLE);
372 self.active = ACTIVE_ACTIVE;
373 self.setactive = func_rotating_setactive;
377 // FIXME: test if this turns the right way, then remove this comment (negate as needed)
378 if (self.spawnflags & 4) // X (untested)
379 self.avelocity = '0 0 1' * self.speed;
380 // FIXME: test if this turns the right way, then remove this comment (negate as needed)
381 else if (self.spawnflags & 8) // Y (untested)
382 self.avelocity = '1 0 0' * self.speed;
383 // FIXME: test if this turns the right way, then remove this comment (negate as needed)
385 self.avelocity = '0 1 0' * self.speed;
387 self.pos1 = self.avelocity;
389 if(self.dmg & (!self.message))
390 self.message = " was squished";
391 if(self.dmg && (!self.message2))
392 self.message2 = "was squished by";
395 if(self.dmg && (!self.dmgtime))
398 self.dmgtime2 = time;
400 if not(InitMovingBrushTrigger())
402 // no EF_LOWPRECISION here, as rounding angles is bad
404 self.blocked = generic_plat_blocked;
406 // wait for targets to spawn
407 self.nextthink = self.ltime + 999999999;
408 self.think = SUB_Null;
410 // TODO make a reset function for this one
414 void func_bobbing_controller_think()
417 self.nextthink = time + 0.1;
419 if not (self.owner.active == ACTIVE_ACTIVE)
421 self.owner.velocity = '0 0 0';
425 // calculate sinewave using makevectors
426 makevectors((self.nextthink * self.owner.cnt + self.owner.phase * 360) * '0 1 0');
427 v = self.owner.destvec + self.owner.movedir * v_forward_y;
428 if(self.owner.classname == "func_bobbing") // don't brake stuff if the func_bobbing was killtarget'ed
429 // * 10 so it will arrive in 0.1 sec
430 self.owner.velocity = (v - self.owner.origin) * 10;
433 /*QUAKED spawnfunc_func_bobbing (0 .5 .8) ? X_AXIS Y_AXIS
434 Brush model that moves back and forth on one axis (default Z).
435 speed : how long one cycle takes in seconds (default 4)
436 height : how far the cycle moves (default 32)
437 phase : cycle timing adjustment (0-1 as a fraction of the cycle, default 0)
438 noise : path/name of looping .wav file to play.
439 dmg : Do this mutch dmg every .dmgtime intervall when blocked
442 void spawnfunc_func_bobbing()
444 local entity controller;
445 if (self.noise != "")
447 precache_sound(self.noise);
448 soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE);
454 // center of bobbing motion
455 self.destvec = self.origin;
456 // time scale to get degrees
457 self.cnt = 360 / self.speed;
459 self.active = ACTIVE_ACTIVE;
461 // damage when blocked
462 self.blocked = generic_plat_blocked;
463 if(self.dmg & (!self.message))
464 self.message = " was squished";
465 if(self.dmg && (!self.message2))
466 self.message2 = "was squished by";
467 if(self.dmg && (!self.dmgtime))
469 self.dmgtime2 = time;
472 if (self.spawnflags & 1) // X
473 self.movedir = '1 0 0' * self.height;
474 else if (self.spawnflags & 2) // Y
475 self.movedir = '0 1 0' * self.height;
477 self.movedir = '0 0 1' * self.height;
479 if not(InitMovingBrushTrigger())
482 // wait for targets to spawn
483 controller = spawn();
484 controller.classname = "func_bobbing_controller";
485 controller.owner = self;
486 controller.nextthink = time + 1;
487 controller.think = func_bobbing_controller_think;
488 self.nextthink = self.ltime + 999999999;
489 self.think = SUB_Null;
491 // Savage: Reduce bandwith, critical on e.g. nexdm02
492 self.effects |= EF_LOWPRECISION;
494 // TODO make a reset function for this one
498 void func_pendulum_controller_think()
501 self.nextthink = time + 0.1;
503 if not (self.owner.active == ACTIVE_ACTIVE)
505 self.owner.avelocity_x = 0;
509 // calculate sinewave using makevectors
510 makevectors((self.nextthink * self.owner.freq + self.owner.phase) * '0 360 0');
511 v = self.owner.speed * v_forward_y + self.cnt;
512 if(self.owner.classname == "func_pendulum") // don't brake stuff if the func_bobbing was killtarget'ed
514 // * 10 so it will arrive in 0.1 sec
515 self.owner.avelocity_z = (remainder(v - self.owner.angles_z, 360)) * 10;
519 void spawnfunc_func_pendulum()
521 local entity controller;
522 if (self.noise != "")
524 precache_sound(self.noise);
525 soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE);
528 self.active = ACTIVE_ACTIVE;
530 // keys: angle, speed, phase, noise, freq
534 // not initializing self.dmg to 2, to allow damageless pendulum
536 if(self.dmg & (!self.message))
537 self.message = " was squished";
538 if(self.dmg && (!self.message2))
539 self.message2 = "was squished by";
540 if(self.dmg && (!self.dmgtime))
542 self.dmgtime2 = time;
544 self.blocked = generic_plat_blocked;
546 self.avelocity_z = 0.0000001;
547 if not(InitMovingBrushTrigger())
552 // find pendulum length (same formula as Q3A)
553 self.freq = 1 / (M_PI * 2) * sqrt(autocvar_sv_gravity / (3 * max(8, fabs(self.mins_z))));
556 // copy initial angle
557 self.cnt = self.angles_z;
559 // wait for targets to spawn
560 controller = spawn();
561 controller.classname = "func_pendulum_controller";
562 controller.owner = self;
563 controller.nextthink = time + 1;
564 controller.think = func_pendulum_controller_think;
565 self.nextthink = self.ltime + 999999999;
566 self.think = SUB_Null;
568 //self.effects |= EF_LOWPRECISION;
570 // TODO make a reset function for this one
573 // button and multiple button
576 void() button_return;
580 self.state = STATE_TOP;
581 self.nextthink = self.ltime + self.wait;
582 self.think = button_return;
583 activator = self.enemy;
585 self.frame = 1; // use alternate textures
590 self.state = STATE_BOTTOM;
595 self.state = STATE_DOWN;
596 SUB_CalcMove (self.pos1, self.speed, button_done);
597 self.frame = 0; // use normal textures
599 self.takedamage = DAMAGE_YES; // can be shot again
603 void button_blocked()
605 // do nothing, just don't come all the way back out
611 self.health = self.max_health;
612 self.takedamage = DAMAGE_NO; // will be reset upon return
614 if (self.state == STATE_UP || self.state == STATE_TOP)
617 if (self.noise != "")
618 sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM);
620 self.state = STATE_UP;
621 SUB_CalcMove (self.pos2, self.speed, button_wait);
626 self.health = self.max_health;
627 setorigin(self, self.pos1);
628 self.frame = 0; // use normal textures
629 self.state = STATE_BOTTOM;
631 self.takedamage = DAMAGE_YES; // can be shot again
636 // if (activator.classname != "player")
638 // dprint(activator.classname);
639 // dprint(" triggered a button\n");
642 if not (self.active == ACTIVE_ACTIVE)
645 self.enemy = activator;
651 // if (activator.classname != "player")
653 // dprint(activator.classname);
654 // dprint(" touched a button\n");
658 if not(other.iscreature)
660 if(other.velocity * self.movedir < 0)
664 self.enemy = other.owner;
668 void button_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
670 if(self.spawnflags & DOOR_NOSPLASH)
671 if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
673 self.health = self.health - damage;
674 if (self.health <= 0)
676 // if (activator.classname != "player")
678 // dprint(activator.classname);
679 // dprint(" killed a button\n");
681 self.enemy = damage_attacker;
687 /*QUAKED spawnfunc_func_button (0 .5 .8) ?
688 When a button is touched, it moves some distance in the direction of it's angle, triggers all of it's targets, waits some time, then returns to it's original position where it can be triggered again.
690 "angle" determines the opening direction
691 "target" all entities with a matching targetname will be used
692 "speed" override the default 40 speed
693 "wait" override the default 1 second wait (-1 = never return)
694 "lip" override the default 4 pixel lip remaining at end of move
695 "health" if set, the button must be killed instead of touched. If set to -1, the button will fire on ANY attack, even damageless ones like the MinstaGib laser
702 void spawnfunc_func_button()
706 if not(InitMovingBrushTrigger())
708 self.effects |= EF_LOWPRECISION;
710 self.blocked = button_blocked;
711 self.use = button_use;
713 // if (self.health == 0) // all buttons are now shootable
717 self.max_health = self.health;
718 self.event_damage = button_damage;
719 self.takedamage = DAMAGE_YES;
722 self.touch = button_touch;
732 precache_sound(self.noise);
734 self.active = ACTIVE_ACTIVE;
736 self.pos1 = self.origin;
737 self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
738 self.flags |= FL_NOTARGET;
744 float DOOR_START_OPEN = 1;
745 float DOOR_DONT_LINK = 4;
746 float DOOR_TOGGLE = 32;
750 Doors are similar to buttons, but can spawn a fat trigger field around them
751 to open without a touch, and they link together to form simultanious
754 Door.owner is the master door. If there is only one door, it points to itself.
755 If multiple doors, all will point to a single one.
757 Door.enemy chains from the master door through all doors linked in the chain.
762 =============================================================================
766 =============================================================================
771 void() door_rotating_go_down;
772 void() door_rotating_go_up;
777 if((self.spawnflags & 8) && (other.takedamage != DAMAGE_NO)) { // KIll Kill Kill!!
778 Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
781 if((self.dmg) && (other.takedamage == DAMAGE_YES)) // Shall we bite?
782 Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
784 //Dont chamge direction for dead or dying stuff
785 if(other.deadflag != DEAD_NO && (other.takedamage == DAMAGE_NO)) {
788 if (self.state == STATE_DOWN)
789 if (self.classname == "door")
794 door_rotating_go_up ();
797 if (self.classname == "door")
802 door_rotating_go_down ();
806 //gib dying stuff just to make sure
807 if((self.dmg) && (other.takedamage != DAMAGE_NO)) // Shall we bite?
808 Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
812 //T_Damage (other, self, self, self.dmg, self.dmg, self.deathtype, DT_IMPACT, (self.absmin + self.absmax) * 0.5, '0 0 0', Obituary_Generic);
813 // if a door has a negative wait, it would never come back if blocked,
814 // so let it just squash the object to death real fast
815 /* if (self.wait >= 0)
817 if (self.state == STATE_DOWN)
828 if (self.noise1 != "")
829 sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
830 self.state = STATE_TOP;
831 if (self.spawnflags & DOOR_TOGGLE)
832 return; // don't come down automatically
833 if (self.classname == "door")
835 self.think = door_go_down;
838 self.think = door_rotating_go_down;
840 self.nextthink = self.ltime + self.wait;
843 void door_hit_bottom()
845 if (self.noise1 != "")
846 sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
847 self.state = STATE_BOTTOM;
852 if (self.noise2 != "")
853 sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
856 self.takedamage = DAMAGE_YES;
857 self.health = self.max_health;
860 self.state = STATE_DOWN;
861 SUB_CalcMove (self.pos1, self.speed, door_hit_bottom);
866 if (self.state == STATE_UP)
867 return; // already going up
869 if (self.state == STATE_TOP)
870 { // reset top wait time
871 self.nextthink = self.ltime + self.wait;
875 if (self.noise2 != "")
876 sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
877 self.state = STATE_UP;
878 SUB_CalcMove (self.pos2, self.speed, door_hit_top);
881 oldmessage = self.message;
884 self.message = oldmessage;
889 =============================================================================
893 =============================================================================
901 if (self.owner != self)
902 objerror ("door_fire: self.owner != self");
906 if (self.spawnflags & DOOR_TOGGLE)
908 if (self.state == STATE_UP || self.state == STATE_TOP)
913 if (self.classname == "door")
919 door_rotating_go_down ();
922 } while ( (self != starte) && (self != world) );
928 // trigger all paired doors
932 if (self.classname == "door")
937 // if the BIDIR spawnflag (==2) is set and the trigger has set trigger_reverse, reverse the opening direction
938 if ((self.spawnflags & 2) && other.trigger_reverse!=0 && self.lip!=666 && self.state == STATE_BOTTOM)
940 self.lip = 666; // self.lip is used to remember reverse opening direction for door_rotating
941 self.pos2 = '0 0 0' - self.pos2;
943 // if BIDIR_IN_DOWN (==8) is set, prevent the door from reoping during closing if it is triggered from the wrong side
944 if (!((self.spawnflags & 2) && (self.spawnflags & 8) && self.state == STATE_DOWN
945 && (((self.lip==666) && (other.trigger_reverse==0)) || ((self.lip!=666) && (other.trigger_reverse!=0)))))
947 door_rotating_go_up ();
951 } while ( (self != starte) && (self != world) );
960 //dprint("door_use (model: ");dprint(self.model);dprint(")\n");
971 void door_trigger_touch()
973 if (other.health < 1)
974 if not(other.iscreature && other.deadflag == DEAD_NO)
977 if (time < self.attack_finished_single)
980 if (self.spawnflags & (SPAWNFLAGS_GOLD_KEY | SPAWNFLAGS_SILVER_KEY)) {
981 // this door require a key
982 // only a player can have a key
983 if (other.classname != "player")
987 if (self.spawnflags & SPAWNFLAGS_GOLD_KEY)
988 if (!(other.itemkeys & KEYS_GOLD_KEY)) {
989 centerprint(other, "You don't have the gold key");
994 if (self.spawnflags & SPAWNFLAGS_SILVER_KEY)
995 if (!(other.itemkeys & KEYS_SILVER_KEY)) {
996 centerprint(other, "You don't have the silver key");
1001 self.attack_finished_single = time + 1;
1010 void door_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
1013 if(self.spawnflags & DOOR_NOSPLASH)
1014 if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
1016 self.health = self.health - damage;
1018 if (self.spawnflags & SPAWNFLAGS_GOLD_KEY || self.spawnflags & SPAWNFLAGS_SILVER_KEY) {
1019 // don't allow opening doors through damage if keys are required
1023 if (self.health <= 0)
1027 self.health = self.max_health;
1028 self.takedamage = DAMAGE_NO; // wil be reset upon return
1044 if(other.classname != "player")
1046 if (self.owner.attack_finished_single > time)
1049 self.owner.attack_finished_single = time + 2;
1051 if (!(self.owner.dmg) && (self.owner.message != ""))
1053 if (other.flags & FL_CLIENT)
1054 centerprint (other, self.owner.message);
1055 play2(other, "misc/talk.wav");
1060 void door_generic_plat_blocked()
1063 if((self.spawnflags & 8) && (other.takedamage != DAMAGE_NO)) { // KIll Kill Kill!!
1064 Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
1067 if((self.dmg) && (other.takedamage == DAMAGE_YES)) // Shall we bite?
1068 Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
1070 //Dont chamge direction for dead or dying stuff
1071 if(other.deadflag != DEAD_NO && (other.takedamage == DAMAGE_NO)) {
1074 if (self.state == STATE_DOWN)
1075 door_rotating_go_up ();
1077 door_rotating_go_down ();
1080 //gib dying stuff just to make sure
1081 if((self.dmg) && (other.takedamage != DAMAGE_NO)) // Shall we bite?
1082 Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
1086 //T_Damage (other, self, self, self.dmg, self.dmg, self.deathtype, DT_IMPACT, (self.absmin + self.absmax) * 0.5, '0 0 0', Obituary_Generic);
1087 // if a door has a negative wait, it would never come back if blocked,
1088 // so let it just squash the object to death real fast
1089 /* if (self.wait >= 0)
1091 if (self.state == STATE_DOWN)
1092 door_rotating_go_up ();
1094 door_rotating_go_down ();
1100 void door_rotating_hit_top()
1102 if (self.noise1 != "")
1103 sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
1104 self.state = STATE_TOP;
1105 if (self.spawnflags & DOOR_TOGGLE)
1106 return; // don't come down automatically
1107 self.think = door_rotating_go_down;
1108 self.nextthink = self.ltime + self.wait;
1111 void door_rotating_hit_bottom()
1113 if (self.noise1 != "")
1114 sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
1115 if (self.lip==666) // self.lip is used to remember reverse opening direction for door_rotating
1117 self.pos2 = '0 0 0' - self.pos2;
1120 self.state = STATE_BOTTOM;
1123 void door_rotating_go_down()
1125 if (self.noise2 != "")
1126 sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
1127 if (self.max_health)
1129 self.takedamage = DAMAGE_YES;
1130 self.health = self.max_health;
1133 self.state = STATE_DOWN;
1134 SUB_CalcAngleMove (self.pos1, self.speed, door_rotating_hit_bottom);
1137 void door_rotating_go_up()
1139 if (self.state == STATE_UP)
1140 return; // already going up
1142 if (self.state == STATE_TOP)
1143 { // reset top wait time
1144 self.nextthink = self.ltime + self.wait;
1147 if (self.noise2 != "")
1148 sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
1149 self.state = STATE_UP;
1150 SUB_CalcAngleMove (self.pos2, self.speed, door_rotating_hit_top);
1153 oldmessage = self.message;
1156 self.message = oldmessage;
1163 =============================================================================
1167 =============================================================================
1171 entity spawn_field(vector fmins, vector fmaxs)
1173 local entity trigger;
1174 local vector t1, t2;
1177 trigger.classname = "doortriggerfield";
1178 trigger.movetype = MOVETYPE_NONE;
1179 trigger.solid = SOLID_TRIGGER;
1180 trigger.owner = self;
1181 trigger.touch = door_trigger_touch;
1185 setsize (trigger, t1 - '60 60 8', t2 + '60 60 8');
1190 float EntitiesTouching(entity e1, entity e2)
1192 if (e1.absmin_x > e2.absmax_x)
1194 if (e1.absmin_y > e2.absmax_y)
1196 if (e1.absmin_z > e2.absmax_z)
1198 if (e1.absmax_x < e2.absmin_x)
1200 if (e1.absmax_y < e2.absmin_y)
1202 if (e1.absmax_z < e2.absmin_z)
1217 local entity t, starte;
1218 local vector cmins, cmaxs;
1221 return; // already linked by another door
1222 if (self.spawnflags & 4)
1224 self.owner = self.enemy = self;
1232 self.trigger_field = spawn_field(self.absmin, self.absmax);
1234 return; // don't want to link this door
1237 cmins = self.absmin;
1238 cmaxs = self.absmax;
1245 self.owner = starte; // master door
1248 starte.health = self.health;
1250 starte.targetname = self.targetname;
1251 if (self.message != "")
1252 starte.message = self.message;
1254 t = find(t, classname, self.classname);
1257 self.enemy = starte; // make the chain a loop
1259 // shootable, or triggered doors just needed the owner/enemy links,
1260 // they don't spawn a field
1271 self.owner.trigger_field = spawn_field(cmins, cmaxs);
1276 if (EntitiesTouching(self,t))
1279 objerror ("cross connected doors");
1284 if (t.absmin_x < cmins_x)
1285 cmins_x = t.absmin_x;
1286 if (t.absmin_y < cmins_y)
1287 cmins_y = t.absmin_y;
1288 if (t.absmin_z < cmins_z)
1289 cmins_z = t.absmin_z;
1290 if (t.absmax_x > cmaxs_x)
1291 cmaxs_x = t.absmax_x;
1292 if (t.absmax_y > cmaxs_y)
1293 cmaxs_y = t.absmax_y;
1294 if (t.absmax_z > cmaxs_z)
1295 cmaxs_z = t.absmax_z;
1302 /*QUAKED spawnfunc_func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK GOLD_KEY SILVER_KEY TOGGLE
1303 if two doors touch, they are assumed to be connected and operate as a unit.
1305 TOGGLE causes the door to wait in both the start and end states for a trigger event.
1307 START_OPEN causes the door to move to its destination when spawned, and operate in reverse. It is used to temporarily or permanently close off an area when triggered (not useful for touch or takedamage doors).
1309 GOLD_KEY causes the door to open only if the activator holds a gold key.
1311 SILVER_KEY causes the door to open only if the activator holds a silver key.
1313 "message" is printed when the door is touched if it is a trigger door and it hasn't been fired yet
1314 "angle" determines the opening direction
1315 "targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door.
1316 "health" if set, door must be shot open
1317 "speed" movement speed (100 default)
1318 "wait" wait before returning (3 default, -1 = never return)
1319 "lip" lip remaining at end of move (8 default)
1320 "dmg" damage to inflict when blocked (2 default)
1327 FIXME: only one sound set available at the time being
1331 void door_init_startopen()
1333 setorigin (self, self.pos2);
1334 self.pos2 = self.pos1;
1335 self.pos1 = self.origin;
1340 setorigin(self, self.pos1);
1341 self.velocity = '0 0 0';
1342 self.state = STATE_BOTTOM;
1343 self.think = SUB_Null;
1346 void spawnfunc_func_door()
1348 //if (!self.deathtype) // map makers can override this
1349 // self.deathtype = " got in the way";
1352 self.max_health = self.health;
1353 if not(InitMovingBrushTrigger())
1355 self.effects |= EF_LOWPRECISION;
1356 self.classname = "door";
1358 self.blocked = door_blocked;
1359 self.use = door_use;
1361 if(self.spawnflags & 8)
1364 if(self.dmg && (!self.message))
1365 self.message = "was squished";
1366 if(self.dmg && (!self.message2))
1367 self.message2 = "was squished by";
1369 if (self.sounds > 0)
1371 precache_sound ("plats/medplat1.wav");
1372 precache_sound ("plats/medplat2.wav");
1373 self.noise2 = "plats/medplat1.wav";
1374 self.noise1 = "plats/medplat2.wav";
1384 self.pos1 = self.origin;
1385 self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
1387 // DOOR_START_OPEN is to allow an entity to be lighted in the closed position
1388 // but spawn in the open position
1389 if (self.spawnflags & DOOR_START_OPEN)
1390 InitializeEntity(self, door_init_startopen, INITPRIO_SETLOCATION);
1392 self.state = STATE_BOTTOM;
1396 self.takedamage = DAMAGE_YES;
1397 self.event_damage = door_damage;
1403 self.touch = door_touch;
1405 // LinkDoors can't be done until all of the doors have been spawned, so
1406 // the sizes can be detected properly.
1407 InitializeEntity(self, LinkDoors, INITPRIO_LINKDOORS);
1409 self.reset = door_reset;
1412 /*QUAKED spawnfunc_func_door_rotating (0 .5 .8) ? START_OPEN BIDIR DOOR_DONT_LINK BIDIR_IN_DOWN x TOGGLE X_AXIS Y_AXIS
1413 if two doors touch, they are assumed to be connected and operate as a unit.
1415 TOGGLE causes the door to wait in both the start and end states for a trigger event.
1417 BIDIR makes the door work bidirectional, so that the opening direction is always away from the requestor.
1418 The usage of bidirectional doors requires two manually instantiated triggers (trigger_multiple), the one to open it in the other direction
1419 must have set trigger_reverse to 1.
1420 BIDIR_IN_DOWN will the door prevent from reopening while closing if it is triggered from the other side.
1422 START_OPEN causes the door to move to its destination when spawned, and operate in reverse. It is used to temporarily or permanently close off an area when triggered (not usefull for touch or takedamage doors).
1424 "message" is printed when the door is touched if it is a trigger door and it hasn't been fired yet
1425 "angle" determines the destination angle for opening. negative values reverse the direction.
1426 "targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door.
1427 "health" if set, door must be shot open
1428 "speed" movement speed (100 default)
1429 "wait" wait before returning (3 default, -1 = never return)
1430 "dmg" damage to inflict when blocked (2 default)
1437 FIXME: only one sound set available at the time being
1440 void door_rotating_reset()
1442 self.angles = self.pos1;
1443 self.avelocity = '0 0 0';
1444 self.state = STATE_BOTTOM;
1445 self.think = SUB_Null;
1448 void door_rotating_init_startopen()
1450 self.angles = self.movedir;
1451 self.pos2 = '0 0 0';
1452 self.pos1 = self.movedir;
1456 void spawnfunc_func_door_rotating()
1459 //if (!self.deathtype) // map makers can override this
1460 // self.deathtype = " got in the way";
1462 // I abuse "movedir" for denoting the axis for now
1463 if (self.spawnflags & 64) // X (untested)
1464 self.movedir = '0 0 1';
1465 else if (self.spawnflags & 128) // Y (untested)
1466 self.movedir = '1 0 0';
1468 self.movedir = '0 1 0';
1470 if (self.angles_y==0) self.angles_y = 90;
1472 self.movedir = self.movedir * self.angles_y;
1473 self.angles = '0 0 0';
1475 self.max_health = self.health;
1476 self.avelocity = self.movedir;
1477 if not(InitMovingBrushTrigger())
1479 self.velocity = '0 0 0';
1480 //self.effects |= EF_LOWPRECISION;
1481 self.classname = "door_rotating";
1483 self.blocked = door_blocked;
1484 self.use = door_use;
1486 if(self.spawnflags & 8)
1489 if(self.dmg && (!self.message))
1490 self.message = "was squished";
1491 if(self.dmg && (!self.message2))
1492 self.message2 = "was squished by";
1494 if (self.sounds > 0)
1496 precache_sound ("plats/medplat1.wav");
1497 precache_sound ("plats/medplat2.wav");
1498 self.noise2 = "plats/medplat1.wav";
1499 self.noise1 = "plats/medplat2.wav";
1506 self.lip = 0; // self.lip is used to remember reverse opening direction for door_rotating
1508 self.pos1 = '0 0 0';
1509 self.pos2 = self.movedir;
1511 // DOOR_START_OPEN is to allow an entity to be lighted in the closed position
1512 // but spawn in the open position
1513 if (self.spawnflags & DOOR_START_OPEN)
1514 InitializeEntity(self, door_rotating_init_startopen, INITPRIO_SETLOCATION);
1516 self.state = STATE_BOTTOM;
1520 self.takedamage = DAMAGE_YES;
1521 self.event_damage = door_damage;
1527 self.touch = door_touch;
1529 // LinkDoors can't be done until all of the doors have been spawned, so
1530 // the sizes can be detected properly.
1531 InitializeEntity(self, LinkDoors, INITPRIO_LINKDOORS);
1533 self.reset = door_rotating_reset;
1537 =============================================================================
1541 =============================================================================
1544 void() fd_secret_move1;
1545 void() fd_secret_move2;
1546 void() fd_secret_move3;
1547 void() fd_secret_move4;
1548 void() fd_secret_move5;
1549 void() fd_secret_move6;
1550 void() fd_secret_done;
1552 float SECRET_OPEN_ONCE = 1; // stays open
1553 float SECRET_1ST_LEFT = 2; // 1st move is left of arrow
1554 float SECRET_1ST_DOWN = 4; // 1st move is down from arrow
1555 float SECRET_NO_SHOOT = 8; // only opened by trigger
1556 float SECRET_YES_SHOOT = 16; // shootable even if targeted
1559 void fd_secret_use()
1562 string message_save;
1564 self.health = 10000;
1565 self.bot_attack = TRUE;
1567 // exit if still moving around...
1568 if (self.origin != self.oldorigin)
1571 message_save = self.message;
1572 self.message = ""; // no more message
1573 SUB_UseTargets(); // fire all targets / killtargets
1574 self.message = message_save;
1576 self.velocity = '0 0 0';
1578 // Make a sound, wait a little...
1580 if (self.noise1 != "")
1581 sound(self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
1582 self.nextthink = self.ltime + 0.1;
1584 temp = 1 - (self.spawnflags & SECRET_1ST_LEFT); // 1 or -1
1585 makevectors(self.mangle);
1589 if (self.spawnflags & SECRET_1ST_DOWN)
1590 self.t_width = fabs(v_up * self.size);
1592 self.t_width = fabs(v_right * self.size);
1596 self.t_length = fabs(v_forward * self.size);
1598 if (self.spawnflags & SECRET_1ST_DOWN)
1599 self.dest1 = self.origin - v_up * self.t_width;
1601 self.dest1 = self.origin + v_right * (self.t_width * temp);
1603 self.dest2 = self.dest1 + v_forward * self.t_length;
1604 SUB_CalcMove(self.dest1, self.speed, fd_secret_move1);
1605 if (self.noise2 != "")
1606 sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
1609 // Wait after first movement...
1610 void fd_secret_move1()
1612 self.nextthink = self.ltime + 1.0;
1613 self.think = fd_secret_move2;
1614 if (self.noise3 != "")
1615 sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM);
1618 // Start moving sideways w/sound...
1619 void fd_secret_move2()
1621 if (self.noise2 != "")
1622 sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
1623 SUB_CalcMove(self.dest2, self.speed, fd_secret_move3);
1626 // Wait here until time to go back...
1627 void fd_secret_move3()
1629 if (self.noise3 != "")
1630 sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM);
1631 if (!(self.spawnflags & SECRET_OPEN_ONCE))
1633 self.nextthink = self.ltime + self.wait;
1634 self.think = fd_secret_move4;
1639 void fd_secret_move4()
1641 if (self.noise2 != "")
1642 sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
1643 SUB_CalcMove(self.dest1, self.speed, fd_secret_move5);
1647 void fd_secret_move5()
1649 self.nextthink = self.ltime + 1.0;
1650 self.think = fd_secret_move6;
1651 if (self.noise3 != "")
1652 sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM);
1655 void fd_secret_move6()
1657 if (self.noise2 != "")
1658 sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
1659 SUB_CalcMove(self.oldorigin, self.speed, fd_secret_done);
1662 void fd_secret_done()
1664 if (self.spawnflags&SECRET_YES_SHOOT)
1666 self.health = 10000;
1667 self.takedamage = DAMAGE_YES;
1668 //self.th_pain = fd_secret_use;
1670 if (self.noise3 != "")
1671 sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM);
1674 void secret_blocked()
1676 if (time < self.attack_finished_single)
1678 self.attack_finished_single = time + 0.5;
1679 //T_Damage (other, self, self, self.dmg, self.dmg, self.deathtype, DT_IMPACT, (self.absmin + self.absmax) * 0.5, '0 0 0', Obituary_Generic);
1691 if not(other.iscreature)
1693 if (self.attack_finished_single > time)
1696 self.attack_finished_single = time + 2;
1700 if (other.flags & FL_CLIENT)
1701 centerprint (other, self.message);
1702 play2(other, "misc/talk.wav");
1708 if (self.spawnflags&SECRET_YES_SHOOT)
1710 self.health = 10000;
1711 self.takedamage = DAMAGE_YES;
1713 setorigin(self, self.oldorigin);
1714 self.think = SUB_Null;
1717 /*QUAKED spawnfunc_func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot
1718 Basic secret door. Slides back, then to the side. Angle determines direction.
1719 wait = # of seconds before coming back
1720 1st_left = 1st move is left of arrow
1721 1st_down = 1st move is down from arrow
1722 always_shoot = even if targeted, keep shootable
1723 t_width = override WIDTH to move back (or height if going down)
1724 t_length = override LENGTH to move sideways
1725 "dmg" damage to inflict when blocked (2 default)
1727 If a secret door has a targetname, it will only be opened by it's botton or trigger, not by damage.
1734 void spawnfunc_func_door_secret()
1736 /*if (!self.deathtype) // map makers can override this
1737 self.deathtype = " got in the way";*/
1743 self.mangle = self.angles;
1744 self.angles = '0 0 0';
1745 self.classname = "door";
1746 if not(InitMovingBrushTrigger())
1748 self.effects |= EF_LOWPRECISION;
1750 self.touch = secret_touch;
1751 self.blocked = secret_blocked;
1753 self.use = fd_secret_use;
1758 self.spawnflags |= SECRET_YES_SHOOT;
1760 if(self.spawnflags&SECRET_YES_SHOOT)
1762 self.health = 10000;
1763 self.takedamage = DAMAGE_YES;
1764 self.event_damage = fd_secret_use;
1766 self.oldorigin = self.origin;
1768 self.wait = 5; // 5 seconds before closing
1770 self.reset = secret_reset;
1774 /*QUAKED spawnfunc_func_fourier (0 .5 .8) ?
1775 Brush model that moves in a pattern of added up sine waves, can be used e.g. for circular motions.
1776 netname: list of <frequencymultiplier> <phase> <x> <y> <z> quadruples, separated by spaces; note that phase 0 represents a sine wave, and phase 0.25 a cosine wave (by default, it uses 1 0 0 0 1, to match func_bobbing's defaults
1777 speed: how long one cycle of frequency multiplier 1 in seconds (default 4)
1778 height: amplitude modifier (default 32)
1779 phase: cycle timing adjustment (0-1 as a fraction of the cycle, default 0)
1780 noise: path/name of looping .wav file to play.
1781 dmg: Do this mutch dmg every .dmgtime intervall when blocked
1785 void func_fourier_controller_think()
1790 self.nextthink = time + 0.1;
1791 if not (self.owner.active == ACTIVE_ACTIVE)
1793 self.owner.velocity = '0 0 0';
1798 n = floor((tokenize_console(self.owner.netname)) / 5);
1799 t = self.nextthink * self.owner.cnt + self.owner.phase * 360;
1801 v = self.owner.destvec;
1803 for(i = 0; i < n; ++i)
1805 makevectors((t * stof(argv(i*5)) + stof(argv(i*5+1)) * 360) * '0 1 0');
1806 v = v + ('1 0 0' * stof(argv(i*5+2)) + '0 1 0' * stof(argv(i*5+3)) + '0 0 1' * stof(argv(i*5+4))) * self.owner.height * v_forward_y;
1809 if(self.owner.classname == "func_fourier") // don't brake stuff if the func_fourier was killtarget'ed
1810 // * 10 so it will arrive in 0.1 sec
1811 self.owner.velocity = (v - self.owner.origin) * 10;
1814 void spawnfunc_func_fourier()
1816 local entity controller;
1817 if (self.noise != "")
1819 precache_sound(self.noise);
1820 soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE);
1827 self.destvec = self.origin;
1828 self.cnt = 360 / self.speed;
1830 self.blocked = generic_plat_blocked;
1831 if(self.dmg & (!self.message))
1832 self.message = " was squished";
1833 if(self.dmg && (!self.message2))
1834 self.message2 = "was squished by";
1835 if(self.dmg && (!self.dmgtime))
1836 self.dmgtime = 0.25;
1837 self.dmgtime2 = time;
1839 if(self.netname == "")
1840 self.netname = "1 0 0 0 1";
1842 if not(InitMovingBrushTrigger())
1845 self.active = ACTIVE_ACTIVE;
1847 // wait for targets to spawn
1848 controller = spawn();
1849 controller.classname = "func_fourier_controller";
1850 controller.owner = self;
1851 controller.nextthink = time + 1;
1852 controller.think = func_fourier_controller_think;
1853 self.nextthink = self.ltime + 999999999;
1854 self.think = SUB_Null;
1856 // Savage: Reduce bandwith, critical on e.g. nexdm02
1857 self.effects |= EF_LOWPRECISION;
1859 // TODO make a reset function for this one
1862 // reusing some fields havocbots declared
1863 .entity wp00, wp01, wp02, wp03;
1865 .float targetfactor, target2factor, target3factor, target4factor;
1866 .vector targetnormal, target2normal, target3normal, target4normal;
1868 vector func_vectormamamam_origin(entity o, float t)
1880 p = e.origin + t * e.velocity;
1882 v = v + (p * o.targetnormal) * o.targetnormal * o.targetfactor;
1884 v = v + (p - (p * o.targetnormal) * o.targetnormal) * o.targetfactor;
1890 p = e.origin + t * e.velocity;
1892 v = v + (p * o.target2normal) * o.target2normal * o.target2factor;
1894 v = v + (p - (p * o.target2normal) * o.target2normal) * o.target2factor;
1900 p = e.origin + t * e.velocity;
1902 v = v + (p * o.target3normal) * o.target3normal * o.target3factor;
1904 v = v + (p - (p * o.target3normal) * o.target3normal) * o.target3factor;
1910 p = e.origin + t * e.velocity;
1912 v = v + (p * o.target4normal) * o.target4normal * o.target4factor;
1914 v = v + (p - (p * o.target4normal) * o.target4normal) * o.target4factor;
1920 void func_vectormamamam_controller_think()
1922 self.nextthink = time + 0.1;
1924 if not (self.owner.active == ACTIVE_ACTIVE)
1926 self.owner.velocity = '0 0 0';
1930 if(self.owner.classname == "func_vectormamamam") // don't brake stuff if the func_vectormamamam was killtarget'ed
1931 self.owner.velocity = (self.owner.destvec + func_vectormamamam_origin(self.owner, 0.1) - self.owner.origin) * 10;
1934 void func_vectormamamam_findtarget()
1936 if(self.target != "")
1937 self.wp00 = find(world, targetname, self.target);
1939 if(self.target2 != "")
1940 self.wp01 = find(world, targetname, self.target2);
1942 if(self.target3 != "")
1943 self.wp02 = find(world, targetname, self.target3);
1945 if(self.target4 != "")
1946 self.wp03 = find(world, targetname, self.target4);
1948 if(!self.wp00 && !self.wp01 && !self.wp02 && !self.wp03)
1949 objerror("No reference entity found, so there is nothing to move. Aborting.");
1951 self.destvec = self.origin - func_vectormamamam_origin(self.owner, 0);
1953 local entity controller;
1954 controller = spawn();
1955 controller.classname = "func_vectormamamam_controller";
1956 controller.owner = self;
1957 controller.nextthink = time + 1;
1958 controller.think = func_vectormamamam_controller_think;
1961 void spawnfunc_func_vectormamamam()
1963 if (self.noise != "")
1965 precache_sound(self.noise);
1966 soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE);
1969 if(!self.targetfactor)
1970 self.targetfactor = 1;
1972 if(!self.target2factor)
1973 self.target2factor = 1;
1975 if(!self.target3factor)
1976 self.target3factor = 1;
1978 if(!self.target4factor)
1979 self.target4factor = 1;
1981 if(vlen(self.targetnormal))
1982 self.targetnormal = normalize(self.targetnormal);
1984 if(vlen(self.target2normal))
1985 self.target2normal = normalize(self.target2normal);
1987 if(vlen(self.target3normal))
1988 self.target3normal = normalize(self.target3normal);
1990 if(vlen(self.target4normal))
1991 self.target4normal = normalize(self.target4normal);
1993 self.blocked = generic_plat_blocked;
1994 if(self.dmg & (!self.message))
1995 self.message = " was squished";
1996 if(self.dmg && (!self.message2))
1997 self.message2 = "was squished by";
1998 if(self.dmg && (!self.dmgtime))
1999 self.dmgtime = 0.25;
2000 self.dmgtime2 = time;
2002 if(self.netname == "")
2003 self.netname = "1 0 0 0 1";
2005 if not(InitMovingBrushTrigger())
2008 // wait for targets to spawn
2009 self.nextthink = self.ltime + 999999999;
2010 self.think = SUB_Null;
2012 // Savage: Reduce bandwith, critical on e.g. nexdm02
2013 self.effects |= EF_LOWPRECISION;
2015 self.active = ACTIVE_ACTIVE;
2017 InitializeEntity(self, func_vectormamamam_findtarget, INITPRIO_FINDTARGET);