3 float STATE_BOTTOM = 1;
9 void() plat_center_touch;
10 void() plat_outside_touch;
11 void() plat_trigger_use;
15 float PLAT_LOW_TRIGGER = 1;
17 void() plat_spawn_inside_trigger =
20 local vector tmin, tmax;
23 trigger.touch = plat_center_touch;
24 trigger.movetype = MOVETYPE_NONE;
25 trigger.solid = SOLID_TRIGGER;
28 tmin = self.mins + '25 25 0';
29 tmax = self.maxs - '25 25 -8';
30 tmin_z = tmax_z - (self.pos1_z - self.pos2_z + 8);
31 if (self.spawnflags & PLAT_LOW_TRIGGER)
34 if (self.size_x <= 50)
36 tmin_x = (self.mins_x + self.maxs_x) / 2;
39 if (self.size_y <= 50)
41 tmin_y = (self.mins_y + self.maxs_y) / 2;
45 setsize (trigger, tmin, tmax);
50 sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
52 self.think = plat_go_down;
53 self.nextthink = self.ltime + 3;
56 void() plat_hit_bottom =
58 sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
64 sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
66 SUB_CalcMove (self.pos2, self.speed, plat_hit_bottom);
71 sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
73 SUB_CalcMove (self.pos1, self.speed, plat_hit_top);
76 void() plat_center_touch =
78 if (other.classname != "player")
81 if (other.health <= 0)
87 else if (self.state == 1)
88 self.nextthink = self.ltime + 1; // delay going down
91 void() plat_outside_touch =
93 if (other.classname != "player")
96 if (other.health <= 0)
104 void() plat_trigger_use =
107 return; // allready activated
116 else if (self.state == 3)
119 objerror ("plat_crush: bad self.state\n");
126 objerror ("plat_use: not in up state");
131 .string sound1, sound2;
140 if (self.sounds == 0)
143 if (self.sounds == 1)
145 precache_sound ("plats/plat1.wav");
146 precache_sound ("plats/plat2.wav");
147 self.noise = "plats/plat1.wav";
148 self.noise1 = "plats/plat2.wav";
151 if (self.sounds == 2)
153 precache_sound ("plats/medplat1.wav");
154 precache_sound ("plats/medplat2.wav");
155 self.noise = "plats/medplat1.wav";
156 self.noise1 = "plats/medplat2.wav";
161 precache_sound (self.sound1);
162 self.noise = self.sound1;
166 precache_sound (self.sound2);
167 self.noise1 = self.sound2;
170 self.mangle = self.angles;
171 self.angles = '0 0 0';
173 self.classname = "plat";
174 self.solid = SOLID_BSP;
175 self.movetype = MOVETYPE_PUSH;
176 setorigin (self, self.origin);
177 setmodel (self, self.model);
178 setsize (self, self.mins , self.maxs);
180 self.blocked = plat_crush;
183 self.pos1 = self.origin;
184 self.pos2 = self.origin;
185 self.pos2_z = self.origin_z - self.size_z + 8;
187 self.use = plat_trigger_use;
189 plat_spawn_inside_trigger (); // the "start moving" trigger
198 setorigin (self, self.pos2);
206 void() func_train_find;
208 void() train_blocked =
210 if (time < self.attack_finished)
212 self.attack_finished = time + 0.5;
216 if (self.think != func_train_find)
225 self.nextthink = self.ltime + self.wait;
226 sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
229 self.nextthink = self.ltime + 0.1;
231 self.think = train_next;
238 targ = find (world, targetname, self.target);
239 self.target = targ.target;
241 objerror ("train_next: no next target");
243 self.wait = targ.wait;
246 sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
247 SUB_CalcMove (targ.origin - self.mins, self.speed, train_wait);
250 void() func_train_find =
254 targ = find (world, targetname, self.target);
255 self.target = targ.target;
256 setorigin (self, targ.origin - self.mins);
257 if (!self.targetname)
258 { // not triggered, so start immediately
259 self.nextthink = self.ltime + 0.1;
260 self.think = train_next;
270 objerror ("func_train without a target");
272 if (self.sounds == 0)
274 self.noise = ("misc/null.wav");
275 precache_sound ("misc/null.wav");
276 self.noise1 = ("misc/null.wav");
277 precache_sound ("misc/null.wav");
280 if (self.sounds == 1)
282 self.noise = ("plats/train2.wav");
283 precache_sound ("plats/train2.wav");
284 self.noise1 = ("plats/train1.wav");
285 precache_sound ("plats/train1.wav");
288 self.solid = SOLID_BSP;
289 self.movetype = MOVETYPE_PUSH;
290 self.blocked = train_blocked;
291 self.use = train_use;
292 self.classname = "train";
294 setmodel (self, self.model);
295 setsize (self, self.mins , self.maxs);
296 setorigin (self, self.origin);
297 self.nextthink = self.ltime + 0.1;
298 self.think = func_train_find;
305 self.think = train_next;
306 self.nextthink = self.ltime + self.wait;
312 targ = find(world, targetname, self.target);
313 self.target = targ.target;
315 objerror("train_next: no next target");
316 self.wait = targ.wait;
320 SUB_CalcMove(targ.origin - self.mins, targ.speed, train_wait);
322 SUB_CalcMove(targ.origin - self.mins, self.speed, train_wait);
325 void() func_train_find =
328 targ = find(world, targetname, self.target);
329 self.target = targ.target;
330 setorigin(self, targ.origin - self.mins);
331 self.nextthink = self.ltime + 1;
332 self.think = train_next;
335 /*QUAKED func_train (0 .5 .8) ?
336 Ridable platform, targets path_corner path to follow.
337 speed : speed the train moves (can be overridden by each path_corner)
338 target : targetname of first path_corner (starts here)
343 objerror("func_train without a target");
347 self.solid = SOLID_BSP;
348 self.movetype = MOVETYPE_PUSH;
350 setmodel(self, self.model);
351 setsize(self, self.mins, self.maxs);
352 setorigin(self, self.origin);
354 // wait for targets to spawn
355 self.nextthink = self.ltime + 0.1;
356 self.think = func_train_find;
359 /*QUAKED func_rotating (0 .5 .8) ? - - X_AXIS Y_AXIS
360 Brush model that spins in place on one axis (default Z).
361 speed : speed to rotate (in degrees per second)
362 noise : path/name of looping .wav file to play.
364 void() func_rotating =
368 precache_sound(self.noise);
369 ambientsound(self.origin, self.noise, 1, ATTN_IDLE);
373 // FIXME: test if this turns the right way, then remove this comment (negate as needed)
374 if (self.spawnflags & 4) // X (untested)
375 self.avelocity = '0 0 1' * self.speed;
376 // FIXME: test if this turns the right way, then remove this comment (negate as needed)
377 else if (self.spawnflags & 8) // Y (untested)
378 self.avelocity = '1 0 0' * self.speed;
379 // FIXME: test if this turns the right way, then remove this comment (negate as needed)
381 self.avelocity = '0 1 0' * self.speed;
383 self.solid = SOLID_BSP;
384 self.movetype = MOVETYPE_PUSH;
386 setmodel(self, self.model);
387 setsize(self, self.mins, self.maxs);
388 setorigin(self, self.origin);
390 // wait for targets to spawn
391 self.nextthink = self.ltime + 999999999;
392 self.think = SUB_Null;
397 void() func_bobbing_controller_think =
400 self.nextthink = time + 0.1;
401 // calculate sinewave using makevectors
402 makevectors((time * self.owner.cnt + self.owner.phase) * '0 1 0');
403 v = self.owner.destvec + self.owner.movedir * v_forward_y;
404 // * 10 so it will arrive in 0.1 sec
405 self.owner.velocity = (v - self.owner.origin) * 10;
408 /*QUAKED func_bobbing (0 .5 .8) ? X_AXIS Y_AXIS
409 Brush model that moves back and forth on one axis (default Z).
410 speed : how long one cycle takes in seconds (default 4)
411 height : how far the cycle moves (default 32)
412 phase : cycle timing adjustment (0-1 as a fraction of the cycle, default 0)
413 noise : path/name of looping .wav file to play.
415 void() func_bobbing =
417 local entity controller;
420 precache_sound(self.noise);
421 ambientsound(self.origin, self.noise, 1, ATTN_IDLE);
427 // center of bobbing motion
428 self.destvec = self.origin;
429 // time scale to get degrees
430 self.cnt = 360 / self.speed;
432 if (self.spawnflags & 1) // X
433 self.movedir = '1 0 0' * self.height;
434 else if (self.spawnflags & 2) // Y
435 self.movedir = '0 1 0' * self.height;
437 self.movedir = '0 0 1' * self.height;
439 self.solid = SOLID_BSP;
440 self.movetype = MOVETYPE_PUSH;
442 setmodel(self, self.model);
443 setsize(self, self.mins, self.maxs);
444 setorigin(self, self.origin);
446 // wait for targets to spawn
447 controller = spawn();
448 controller.classname = "func_bobbing_controller";
449 controller.owner = self;
450 controller.nextthink = time + 1;
451 controller.think = func_bobbing_controller_think;
452 self.nextthink = self.ltime + 999999999;
453 self.think = SUB_Null;
455 // Savage: Reduce bandwith, critical on e.g. nexdm02
456 self.effects |= EF_LOWPRECISION;
459 // button and multiple button
462 void() button_return;
466 self.state = STATE_TOP;
467 self.nextthink = self.ltime + self.wait;
468 self.think = button_return;
469 activator = self.enemy;
471 self.frame = 1; // use alternate textures
476 self.state = STATE_BOTTOM;
479 void() button_return =
481 self.state = STATE_DOWN;
482 SUB_CalcMove (self.pos1, self.speed, button_done);
483 self.frame = 0; // use normal textures
485 self.takedamage = DAMAGE_YES; // can be shot again
489 void() button_blocked =
491 // do nothing, just don't come all the way back out
497 self.health = self.max_health;
498 self.takedamage = DAMAGE_NO; // will be reset upon return
500 if (self.state == STATE_UP || self.state == STATE_TOP)
503 if (self.noise != "")
504 sound (self, CHAN_VOICE, self.noise, 1, ATTN_NORM);
506 self.state = STATE_UP;
507 SUB_CalcMove (self.pos2, self.speed, button_wait);
513 // if (activator.classname != "player")
515 // dprint(activator.classname);
516 // dprint(" triggered a button\n");
518 self.enemy = activator;
522 void() button_touch =
524 // if (activator.classname != "player")
526 // dprint(activator.classname);
527 // dprint(" touched a button\n");
529 if (!other.classname != "player")
533 self.enemy = other.owner;
537 void(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) button_damage =
539 self.health = self.health - damage;
540 if (self.health <= 0)
542 // if (activator.classname != "player")
544 // dprint(activator.classname);
545 // dprint(" killed a button\n");
547 self.enemy = damage_attacker;
553 /*QUAKED func_button (0 .5 .8) ?
554 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.
556 "angle" determines the opening direction
557 "target" all entities with a matching targetname will be used
558 "speed" override the default 40 speed
559 "wait" override the default 1 second wait (-1 = never return)
560 "lip" override the default 4 pixel lip remaining at end of move
561 "health" if set, the button must be killed instead of touched
572 self.movetype = MOVETYPE_PUSH;
573 self.solid = SOLID_BSP;
574 setmodel (self, self.model);
576 self.blocked = button_blocked;
577 self.use = button_use;
579 // if (self.health == 0) // all buttons are now shootable
583 self.max_health = self.health;
584 self.event_damage = button_damage;
585 self.takedamage = DAMAGE_YES;
588 self.touch = button_touch;
597 self.state = STATE_BOTTOM;
599 self.pos1 = self.origin;
600 self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
604 float DOOR_START_OPEN = 1;
605 float DOOR_DONT_LINK = 4;
606 float DOOR_TOGGLE = 32;
610 Doors are similar to buttons, but can spawn a fat trigger field around them
611 to open without a touch, and they link together to form simultanious
614 Door.owner is the master door. If there is only one door, it points to itself.
615 If multiple doors, all will point to a single one.
617 Door.enemy chains from the master door through all doors linked in the chain.
622 =============================================================================
626 =============================================================================
632 void() door_blocked =
634 //T_Damage (other, self, self, self.dmg, self.dmg, self.deathtype, DT_IMPACT, (self.absmin + self.absmax) * 0.5, '0 0 0', Obituary_Generic);
636 // if a door has a negative wait, it would never come back if blocked,
637 // so let it just squash the object to death real fast
640 if (self.state == STATE_DOWN)
648 void() door_hit_top =
650 if (self.noise1 != "")
651 sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
652 self.state = STATE_TOP;
653 if (self.spawnflags & DOOR_TOGGLE)
654 return; // don't come down automatically
655 self.think = door_go_down;
656 self.nextthink = self.ltime + self.wait;
659 void() door_hit_bottom =
661 if (self.noise1 != "")
662 sound (self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
663 self.state = STATE_BOTTOM;
666 void() door_go_down =
668 if (self.noise2 != "")
669 sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
672 self.takedamage = DAMAGE_YES;
673 self.health = self.max_health;
676 self.state = STATE_DOWN;
677 SUB_CalcMove (self.pos1, self.speed, door_hit_bottom);
682 if (self.state == STATE_UP)
683 return; // allready going up
685 if (self.state == STATE_TOP)
686 { // reset top wait time
687 self.nextthink = self.ltime + self.wait;
691 if (self.noise2 != "")
692 sound (self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
693 self.state = STATE_UP;
694 SUB_CalcMove (self.pos2, self.speed, door_hit_top);
701 =============================================================================
705 =============================================================================
713 if (self.owner != self)
714 objerror ("door_fire: self.owner != self");
716 self.message = ""; // no more message
719 if (self.spawnflags & DOOR_TOGGLE)
721 if (self.state == STATE_UP || self.state == STATE_TOP)
728 } while ( (self != starte) && (self != world) );
734 // trigger all paired doors
740 } while ( (self != starte) && (self != world) );
749 //dprint("door_use (model: ");dprint(self.model);dprint(")\n");
750 self.message = ""; // door message are for touch only
752 self.owner.message = "";
754 self.enemy.message = "";
765 void() door_trigger_touch =
767 if (other.health < 1)
770 if (time < self.attack_finished)
772 self.attack_finished = time + 1;
781 void(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) door_damage =
784 self.health = self.health - damage;
785 if (self.health <= 0)
789 self.health = self.max_health;
790 self.takedamage = DAMAGE_NO; // wil be reset upon return
806 if (other.classname != "player")
808 if (self.owner.attack_finished > time)
811 self.owner.attack_finished = time + 2;
813 if (self.owner.message != "")
815 if (other.flags & FL_CLIENT)
816 centerprint (other, self.owner.message);
817 sound (other, CHAN_VOICE, "misc/talk.wav", 1, ATTN_NORM);
822 =============================================================================
826 =============================================================================
830 entity(vector fmins, vector fmaxs) spawn_field =
832 local entity trigger;
836 trigger.classname = "doortriggerfield";
837 trigger.movetype = MOVETYPE_NONE;
838 trigger.solid = SOLID_TRIGGER;
839 trigger.owner = self;
840 trigger.touch = door_trigger_touch;
844 setsize (trigger, t1 - '60 60 8', t2 + '60 60 8');
849 float (entity e1, entity e2) EntitiesTouching =
851 if (e1.mins_x > e2.maxs_x)
853 if (e1.mins_y > e2.maxs_y)
855 if (e1.mins_z > e2.maxs_z)
857 if (e1.maxs_x < e2.mins_x)
859 if (e1.maxs_y < e2.mins_y)
861 if (e1.maxs_z < e2.mins_z)
876 local entity t, starte;
877 local vector cmins, cmaxs;
880 return; // already linked by another door
881 if (self.spawnflags & 4)
883 self.owner = self.enemy = self;
884 return; // don't want to link this door
895 self.owner = starte; // master door
898 starte.health = self.health;
900 starte.targetname = self.targetname;
901 if (self.message != "")
902 starte.message = self.message;
904 t = find(t, classname, self.classname);
907 self.enemy = starte; // make the chain a loop
909 // shootable, or triggered doors just needed the owner/enemy links,
910 // they don't spawn a field
921 self.owner.trigger_field = spawn_field(cmins, cmaxs);
926 if (EntitiesTouching(self,t))
929 objerror ("cross connected doors");
934 if (t.mins_x < cmins_x)
936 if (t.mins_y < cmins_y)
938 if (t.mins_z < cmins_z)
940 if (t.maxs_x > cmaxs_x)
942 if (t.maxs_y > cmaxs_y)
944 if (t.maxs_z > cmaxs_z)
952 /*QUAKED func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK x x TOGGLE
953 if two doors touch, they are assumed to be connected and operate as a unit.
955 TOGGLE causes the door to wait in both the start and end states for a trigger event.
957 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).
959 "message" is printed when the door is touched if it is a trigger door and it hasn't been fired yet
960 "angle" determines the opening direction
961 "targetname" if set, no touch field will be spawned and a remote button or trigger field activates the door.
962 "health" if set, door must be shot open
963 "speed" movement speed (100 default)
964 "wait" wait before returning (3 default, -1 = never return)
965 "lip" lip remaining at end of move (8 default)
966 "dmg" damage to inflict when blocked (2 default)
977 //if (!self.deathtype) // map makers can override this
978 // self.deathtype = " got in the way";
981 self.max_health = self.health;
982 self.solid = SOLID_BSP;
983 self.movetype = MOVETYPE_PUSH;
984 setorigin (self, self.origin);
985 setmodel (self, self.model);
986 self.classname = "door";
988 self.blocked = door_blocked;
1000 self.pos1 = self.origin;
1001 self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
1003 // DOOR_START_OPEN is to allow an entity to be lighted in the closed position
1004 // but spawn in the open position
1005 if (self.spawnflags & DOOR_START_OPEN)
1007 setorigin (self, self.pos2);
1008 self.pos2 = self.pos1;
1009 self.pos1 = self.origin;
1012 self.state = STATE_BOTTOM;
1016 self.takedamage = DAMAGE_YES;
1017 self.event_damage = door_damage;
1023 self.touch = door_touch;
1025 // LinkDoors can't be done until all of the doors have been spawned, so
1026 // the sizes can be detected properly.
1027 self.think = LinkDoors;
1028 self.nextthink = self.ltime + 0.1;
1032 =============================================================================
1036 =============================================================================
1039 void() fd_secret_move1;
1040 void() fd_secret_move2;
1041 void() fd_secret_move3;
1042 void() fd_secret_move4;
1043 void() fd_secret_move5;
1044 void() fd_secret_move6;
1045 void() fd_secret_done;
1047 float SECRET_OPEN_ONCE = 1; // stays open
1048 float SECRET_1ST_LEFT = 2; // 1st move is left of arrow
1049 float SECRET_1ST_DOWN = 4; // 1st move is down from arrow
1050 float SECRET_NO_SHOOT = 8; // only opened by trigger
1051 float SECRET_YES_SHOOT = 16; // shootable even if targeted
1054 void () fd_secret_use =
1058 self.health = 10000;
1059 //self.havocattack = TRUE;
1061 // exit if still moving around...
1062 if (self.origin != self.oldorigin)
1065 self.message = ""; // no more message
1067 SUB_UseTargets(); // fire all targets / killtargets
1069 self.velocity = '0 0 0';
1071 // Make a sound, wait a little...
1073 if (self.noise1 != "")
1074 sound(self, CHAN_VOICE, self.noise1, 1, ATTN_NORM);
1075 self.nextthink = self.ltime + 0.1;
1077 temp = 1 - (self.spawnflags & SECRET_1ST_LEFT); // 1 or -1
1078 makevectors(self.mangle);
1082 if (self.spawnflags & SECRET_1ST_DOWN)
1083 self.t_width = fabs(v_up * self.size);
1085 self.t_width = fabs(v_right * self.size);
1089 self.t_length = fabs(v_forward * self.size);
1091 if (self.spawnflags & SECRET_1ST_DOWN)
1092 self.dest1 = self.origin - v_up * self.t_width;
1094 self.dest1 = self.origin + v_right * (self.t_width * temp);
1096 self.dest2 = self.dest1 + v_forward * self.t_length;
1097 SUB_CalcMove(self.dest1, self.speed, fd_secret_move1);
1098 if (self.noise2 != "")
1099 sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
1102 // Wait after first movement...
1103 void () fd_secret_move1 =
1105 self.nextthink = self.ltime + 1.0;
1106 self.think = fd_secret_move2;
1107 if (self.noise3 != "")
1108 sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
1111 // Start moving sideways w/sound...
1112 void () fd_secret_move2 =
1114 if (self.noise2 != "")
1115 sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
1116 SUB_CalcMove(self.dest2, self.speed, fd_secret_move3);
1119 // Wait here until time to go back...
1120 void () fd_secret_move3 =
1122 if (self.noise3 != "")
1123 sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
1124 if (!(self.spawnflags & SECRET_OPEN_ONCE))
1126 self.nextthink = self.ltime + self.wait;
1127 self.think = fd_secret_move4;
1132 void () fd_secret_move4 =
1134 if (self.noise2 != "")
1135 sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
1136 SUB_CalcMove(self.dest1, self.speed, fd_secret_move5);
1140 void () fd_secret_move5 =
1142 self.nextthink = self.ltime + 1.0;
1143 self.think = fd_secret_move6;
1144 if (self.noise3 != "")
1145 sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
1148 void () fd_secret_move6 =
1150 if (self.noise2 != "")
1151 sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM);
1152 SUB_CalcMove(self.oldorigin, self.speed, fd_secret_done);
1155 void () fd_secret_done =
1157 if (!self.targetname || self.spawnflags&SECRET_YES_SHOOT)
1159 self.health = 10000;
1160 self.takedamage = DAMAGE_YES;
1161 //self.th_pain = fd_secret_use;
1163 if (self.noise3 != "")
1164 sound(self, CHAN_VOICE, self.noise3, 1, ATTN_NORM);
1167 void () secret_blocked =
1169 if (time < self.attack_finished)
1171 self.attack_finished = time + 0.5;
1172 //T_Damage (other, self, self, self.dmg, self.dmg, self.deathtype, DT_IMPACT, (self.absmin + self.absmax) * 0.5, '0 0 0', Obituary_Generic);
1182 void() secret_touch =
1184 if (activator.classname != "player")
1186 if (self.attack_finished > time)
1189 self.attack_finished = time + 2;
1193 if (other.flags & FL_CLIENT)
1194 centerprint (other, self.message);
1195 sound (other, CHAN_BODY, "misc/talk.wav", 1, ATTN_NORM);
1200 /*QUAKED func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot
1201 Basic secret door. Slides back, then to the side. Angle determines direction.
1202 wait = # of seconds before coming back
1203 1st_left = 1st move is left of arrow
1204 1st_down = 1st move is down from arrow
1205 always_shoot = even if targeted, keep shootable
1206 t_width = override WIDTH to move back (or height if going down)
1207 t_length = override LENGTH to move sideways
1208 "dmg" damage to inflict when blocked (2 default)
1210 If a secret door has a targetname, it will only be opened by it's botton or trigger, not by damage.
1217 void () func_door_secret =
1219 /*if (!self.deathtype) // map makers can override this
1220 self.deathtype = " got in the way";*/
1226 self.mangle = self.angles;
1227 self.angles = '0 0 0';
1228 self.solid = SOLID_BSP;
1229 self.movetype = MOVETYPE_PUSH;
1230 self.classname = "door";
1231 setmodel (self, self.model);
1232 setorigin (self, self.origin);
1234 self.touch = secret_touch;
1235 self.blocked = secret_blocked;
1237 self.use = fd_secret_use;
1238 if ( !self.targetname || self.spawnflags&SECRET_YES_SHOOT)
1240 self.health = 10000;
1241 self.takedamage = DAMAGE_YES;
1242 self.event_damage = fd_secret_use;
1244 self.oldorigin = self.origin;
1246 self.wait = 5; // 5 seconds before closing