]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/t_plats.qc
Some random fixes and stuff (centerprints converted to notifications, less spam when...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / t_plats.qc
index 0c1bcdffb33a98a7d35627ed39cc39a7cc24eadc..d3f72b7ebc4bdad9355cf89b6462e6d10b93f2da 100644 (file)
@@ -14,11 +14,6 @@ void generic_plat_blocked()
 }
 
 
-float  STATE_TOP               = 0;
-float  STATE_BOTTOM    = 1;
-float  STATE_UP                = 2;
-float  STATE_DOWN              = 3;
-
 .entity trigger_field;
 
 void() plat_center_touch;
@@ -27,7 +22,7 @@ void() plat_trigger_use;
 void() plat_go_up;
 void() plat_go_down;
 void() plat_crush;
-float PLAT_LOW_TRIGGER = 1;
+const float PLAT_LOW_TRIGGER = 1;
 
 void plat_spawn_inside_trigger()
 {
@@ -72,7 +67,7 @@ void plat_spawn_inside_trigger()
 
 void plat_hit_top()
 {
-       sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
+       sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
        self.state = 1;
        self.think = plat_go_down;
        self.nextthink = self.ltime + 3;
@@ -80,27 +75,27 @@ void plat_hit_top()
 
 void plat_hit_bottom()
 {
-       sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
+       sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
        self.state = 2;
 }
 
 void plat_go_down()
 {
-       sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_NORM);
+       sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM);
        self.state = 3;
        SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, plat_hit_bottom);
 }
 
 void plat_go_up()
 {
-       sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_NORM);
+       sound (self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_NORM);
        self.state = 4;
        SUB_CalcMove (self.pos1, TSPEED_LINEAR, self.speed, plat_hit_top);
 }
 
 void plat_center_touch()
 {
-       if not(other.iscreature)
+       if (!other.iscreature)
                return;
 
        if (other.health <= 0)
@@ -115,7 +110,7 @@ void plat_center_touch()
 
 void plat_outside_touch()
 {
-       if not(other.iscreature)
+       if (!other.iscreature)
                return;
 
        if (other.health <= 0)
@@ -158,7 +153,7 @@ void plat_crush()
 
 void plat_use()
 {
-       self.use = SUB_Null;
+       self.use = func_null;
        if (self.state != 4)
                objerror ("plat_use: not in up state");
        plat_go_down();
@@ -227,9 +222,9 @@ void spawnfunc_func_plat()
     if(self.spawnflags & 4)
         self.dmg = 10000;
 
-    if(self.dmg && (!self.message))
+    if(self.dmg && (self.message == ""))
                self.message = "was squished";
-    if(self.dmg && (!self.message2))
+    if(self.dmg && (self.message2 == ""))
                self.message2 = "was squished by";
 
        if (self.sounds == 1)
@@ -263,7 +258,7 @@ void spawnfunc_func_plat()
        self.angles = '0 0 0';
 
        self.classname = "plat";
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
        self.effects |= EF_LOWPRECISION;
        setsize (self, self.mins , self.maxs);
@@ -341,8 +336,8 @@ void train_wait()
 
 void train_next()
 {
-       entity targ, cp;
-       vector cp_org;
+       entity targ, cp = world;
+       vector cp_org = '0 0 0';
 
        targ = find(world, targetname, self.target);
        self.target = targ.target;
@@ -353,10 +348,8 @@ void train_next()
                        cp = find(world, targetname, targ.curvetarget); // get its second target (the control point)
                        cp_org = cp.origin - self.view_ofs; // no control point found, assume a straight line to the destination
                }
-               else
-                       cp = world; // no cp
        }
-       if (!self.target)
+       if (self.target == "")
                objerror("train_next: no next target");
        self.wait = targ.wait;
        if (!self.wait)
@@ -391,7 +384,7 @@ void train_next()
        }
 
        if(self.noise != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE);
+               sound(self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE);
 }
 
 void func_train_find()
@@ -399,7 +392,7 @@ void func_train_find()
        entity targ;
        targ = find(world, targetname, self.target);
        self.target = targ.target;
-       if (!self.target)
+       if (self.target == "")
                objerror("func_train_find: no next target");
        setorigin(self, targ.origin - self.view_ofs);
        self.nextthink = self.ltime + 1;
@@ -416,11 +409,15 @@ void spawnfunc_func_train()
        if (self.noise != "")
                precache_sound(self.noise);
 
-       if (!self.target)
+       if (self.target == "")
                objerror("func_train without a target");
        if (!self.speed)
                self.speed = 100;
 
+       if (!InitMovingBrushTrigger())
+               return;
+       self.effects |= EF_LOWPRECISION;
+       
        if (self.spawnflags & 2)
        {
                self.platmovetype_turn = TRUE;
@@ -429,17 +426,13 @@ void spawnfunc_func_train()
        else
                self.view_ofs = self.mins;
 
-       if not(InitMovingBrushTrigger())
-               return;
-       self.effects |= EF_LOWPRECISION;
-
        // wait for targets to spawn
        InitializeEntity(self, func_train_find, INITPRIO_SETLOCATION);
 
        self.blocked = generic_plat_blocked;
-       if(self.dmg & (!self.message))
+       if(self.dmg && (self.message == ""))
                self.message = " was squished";
-    if(self.dmg && (!self.message2))
+    if(self.dmg && (self.message2 == ""))
                self.message2 = "was squished by";
        if(self.dmg && (!self.dmgtime))
                self.dmgtime = 0.25;
@@ -455,9 +448,9 @@ void spawnfunc_func_train()
 
 void func_rotating_setactive(float astate)
 {
-       
+
        if (astate == ACTIVE_TOGGLE)
-       {               
+       {
                if(self.active == ACTIVE_ACTIVE)
                        self.active = ACTIVE_NOT;
                else
@@ -465,8 +458,8 @@ void func_rotating_setactive(float astate)
        }
        else
                self.active = astate;
-               
-       if(self.active  == ACTIVE_NOT)          
+
+       if(self.active  == ACTIVE_NOT)
                self.avelocity = '0 0 0';
        else
                self.avelocity = self.pos1;
@@ -485,12 +478,12 @@ void spawnfunc_func_rotating()
        if (self.noise != "")
        {
                precache_sound(self.noise);
-               ambientsound(self.origin, self.noise, VOL_BASE, ATTN_IDLE);
+               ambientsound(self.origin, self.noise, VOL_BASE, ATTEN_IDLE);
        }
-       
+
        self.active = ACTIVE_ACTIVE;
        self.setactive = func_rotating_setactive;
-       
+
        if (!self.speed)
                self.speed = 100;
        // FIXME: test if this turns the right way, then remove this comment (negate as needed)
@@ -502,12 +495,12 @@ void spawnfunc_func_rotating()
        // FIXME: test if this turns the right way, then remove this comment (negate as needed)
        else // Z
                self.avelocity = '0 1 0' * self.speed;
-       
+
        self.pos1 = self.avelocity;
-    
-    if(self.dmg & (!self.message))
+
+    if(self.dmg && (self.message == ""))
         self.message = " was squished";
-    if(self.dmg && (!self.message2))
+    if(self.dmg && (self.message2 == ""))
                self.message2 = "was squished by";
 
 
@@ -516,7 +509,7 @@ void spawnfunc_func_rotating()
 
     self.dmgtime2 = time;
 
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
        // no EF_LOWPRECISION here, as rounding angles is bad
 
@@ -524,7 +517,7 @@ void spawnfunc_func_rotating()
 
        // wait for targets to spawn
        self.nextthink = self.ltime + 999999999;
-       self.think = SUB_Null;
+       self.think = SUB_NullThink; // for PushMove
 
        // TODO make a reset function for this one
 }
@@ -534,13 +527,13 @@ void func_bobbing_controller_think()
 {
        vector v;
        self.nextthink = time + 0.1;
-       
-       if not (self.owner.active == ACTIVE_ACTIVE)
+
+       if(self.owner.active != ACTIVE_ACTIVE)
        {
-               self.owner.velocity = '0 0 0';          
+               self.owner.velocity = '0 0 0';
                return;
        }
-               
+
        // calculate sinewave using makevectors
        makevectors((self.nextthink * self.owner.cnt + self.owner.phase * 360) * '0 1 0');
        v = self.owner.destvec + self.owner.movedir * v_forward_y;
@@ -564,7 +557,7 @@ void spawnfunc_func_bobbing()
        if (self.noise != "")
        {
                precache_sound(self.noise);
-               soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE);
+               soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE);
        }
        if (!self.speed)
                self.speed = 4;
@@ -579,9 +572,9 @@ void spawnfunc_func_bobbing()
 
        // damage when blocked
        self.blocked = generic_plat_blocked;
-       if(self.dmg & (!self.message))
+       if(self.dmg && (self.message == ""))
                self.message = " was squished";
-    if(self.dmg && (!self.message2))
+    if(self.dmg && (self.message2 == ""))
                self.message2 = "was squished by";
        if(self.dmg && (!self.dmgtime))
                self.dmgtime = 0.25;
@@ -595,7 +588,7 @@ void spawnfunc_func_bobbing()
        else // Z
                self.movedir = '0 0 1' * self.height;
 
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
 
        // wait for targets to spawn
@@ -605,7 +598,7 @@ void spawnfunc_func_bobbing()
        controller.nextthink = time + 1;
        controller.think = func_bobbing_controller_think;
        self.nextthink = self.ltime + 999999999;
-       self.think = SUB_Null;
+       self.think = SUB_NullThink; // for PushMove
 
        // Savage: Reduce bandwith, critical on e.g. nexdm02
        self.effects |= EF_LOWPRECISION;
@@ -619,7 +612,7 @@ void func_pendulum_controller_think()
        float v;
        self.nextthink = time + 0.1;
 
-       if not (self.owner.active == ACTIVE_ACTIVE)
+       if (!(self.owner.active == ACTIVE_ACTIVE))
        {
                self.owner.avelocity_x = 0;
                return;
@@ -641,7 +634,7 @@ void spawnfunc_func_pendulum()
        if (self.noise != "")
        {
                precache_sound(self.noise);
-               soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE);
+               soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE);
        }
 
        self.active = ACTIVE_ACTIVE;
@@ -652,9 +645,9 @@ void spawnfunc_func_pendulum()
                self.speed = 30;
        // not initializing self.dmg to 2, to allow damageless pendulum
 
-       if(self.dmg & (!self.message))
+       if(self.dmg && (self.message == ""))
                self.message = " was squished";
-       if(self.dmg && (!self.message2))
+       if(self.dmg && (self.message2 == ""))
                self.message2 = "was squished by";
        if(self.dmg && (!self.dmgtime))
                self.dmgtime = 0.25;
@@ -663,7 +656,7 @@ void spawnfunc_func_pendulum()
        self.blocked = generic_plat_blocked;
 
        self.avelocity_z = 0.0000001;
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
 
        if(!self.freq)
@@ -682,7 +675,7 @@ void spawnfunc_func_pendulum()
        controller.nextthink = time + 1;
        controller.think = func_pendulum_controller_think;
        self.nextthink = self.ltime + 999999999;
-       self.think = SUB_Null;
+       self.think = SUB_NullThink; // for PushMove
 
        //self.effects |= EF_LOWPRECISION;
 
@@ -734,7 +727,7 @@ void button_fire()
                return;
 
        if (self.noise != "")
-               sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM);
+               sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
 
        self.state = STATE_UP;
        SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, button_wait);
@@ -752,13 +745,7 @@ void button_reset()
 
 void button_use()
 {
-//     if (activator.classname != "player")
-//     {
-//             dprint(activator.classname);
-//             dprint(" triggered a button\n");
-//     }
-
-       if not (self.active == ACTIVE_ACTIVE)
+       if(self.active != ACTIVE_ACTIVE)
                return;
 
        self.enemy = activator;
@@ -767,14 +754,9 @@ void button_use()
 
 void button_touch()
 {
-//     if (activator.classname != "player")
-//     {
-//             dprint(activator.classname);
-//             dprint(" touched a button\n");
-//     }
        if (!other)
                return;
-       if not(other.iscreature)
+       if (!other.iscreature)
                return;
        if(other.velocity * self.movedir < 0)
                return;
@@ -792,11 +774,6 @@ void button_damage(entity inflictor, entity attacker, float damage, float deatht
        self.health = self.health - damage;
        if (self.health <= 0)
        {
-       //      if (activator.classname != "player")
-       //      {
-       //              dprint(activator.classname);
-       //              dprint(" killed a button\n");
-       //      }
                self.enemy = damage_attacker;
                button_fire ();
        }
@@ -822,7 +799,7 @@ void spawnfunc_func_button()
 {
        SetMovedir ();
 
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
        self.effects |= EF_LOWPRECISION;
 
@@ -860,9 +837,9 @@ void spawnfunc_func_button()
 }
 
 
-float DOOR_START_OPEN = 1;
-float DOOR_DONT_LINK = 4;
-float DOOR_TOGGLE = 32;
+const float DOOR_START_OPEN = 1;
+const float DOOR_DONT_LINK = 4;
+const float DOOR_TOGGLE = 32;
 
 /*
 
@@ -945,7 +922,7 @@ void door_blocked()
 void door_hit_top()
 {
        if (self.noise1 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
+               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
        self.state = STATE_TOP;
        if (self.spawnflags & DOOR_TOGGLE)
                return;         // don't come down automatically
@@ -962,14 +939,14 @@ void door_hit_top()
 void door_hit_bottom()
 {
        if (self.noise1 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
+               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
        self.state = STATE_BOTTOM;
 }
 
 void door_go_down()
 {
        if (self.noise2 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
+               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        if (self.max_health)
        {
                self.takedamage = DAMAGE_YES;
@@ -992,7 +969,7 @@ void door_go_up()
        }
 
        if (self.noise2 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
+               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        self.state = STATE_UP;
        SUB_CalcMove (self.pos2, TSPEED_LINEAR, self.speed, door_hit_top);
 
@@ -1015,34 +992,34 @@ ACTIVATION FUNCTIONS
 
 float door_check_keys(void) {
        local entity door;
-       
-       
+
+
        if (self.owner)
                door = self.owner;
        else
                door = self;
-       
+
        // no key needed
-       if not(door.itemkeys)
+       if (!door.itemkeys)
                return TRUE;
 
        // this door require a key
        // only a player can have a key
-       if (other.classname != "player")
+       if (!IS_PLAYER(other))
                return FALSE;
-       
+
        if (item_keys_usekey(door, other)) {
                // some keys were used
                if (other.key_door_messagetime <= time) {
                        play2(other, "misc/talk.wav");
-                       centerprint(other, strcat("You also need ", item_keys_keylist(door.itemkeys), "!"));
+                       Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_ALSONEED, item_keys_keylist(door.itemkeys));
                        other.key_door_messagetime = time + 2;
                }
        } else {
                // no keys were used
                if (other.key_door_messagetime <= time) {
                        play2(other, "misc/talk.wav");
-                       centerprint(other, strcat("You need ", item_keys_keylist(door.itemkeys), "!"));
+                       Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_NEED, item_keys_keylist(door.itemkeys));
                        other.key_door_messagetime = time + 2;
                }
        }
@@ -1050,7 +1027,7 @@ float door_check_keys(void) {
        if (door.itemkeys) {
                // door is now unlocked
                play2(other, "misc/talk.wav");
-               centerprint(other, "Door unlocked!");
+               Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_UNLOCKED);
                return TRUE;
        } else
                return FALSE;
@@ -1122,7 +1099,7 @@ void door_use()
        entity oself;
 
        //dprint("door_use (model: ");dprint(self.model);dprint(")\n");
-       
+
        if (self.owner)
        {
                oself = self;
@@ -1136,16 +1113,16 @@ void door_use()
 void door_trigger_touch()
 {
        if (other.health < 1)
-               if not(other.iscreature && other.deadflag == DEAD_NO)
+               if (!(other.iscreature && other.deadflag == DEAD_NO))
                        return;
 
        if (time < self.attack_finished_single)
                return;
-       
+
        // check if door is locked
        if (!door_check_keys())
                return;
-       
+
        self.attack_finished_single = time + 1;
 
        activator = other;
@@ -1162,12 +1139,12 @@ void door_damage(entity inflictor, entity attacker, float damage, float deathtyp
                if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
                        return;
        self.health = self.health - damage;
-       
+
        if (self.itemkeys) {
                // don't allow opening doors through damage if keys are required
                return;
        }
-       
+
        if (self.health <= 0)
        {
                oself = self;
@@ -1189,7 +1166,7 @@ Prints messages
 */
 void door_touch()
 {
-       if(other.classname != "player")
+       if (!IS_PLAYER(other))
                return;
        if (self.owner.attack_finished_single > time)
                return;
@@ -1198,7 +1175,7 @@ void door_touch()
 
        if (!(self.owner.dmg) && (self.owner.message != ""))
        {
-               if (other.flags & FL_CLIENT)
+               if (IS_CLIENT(other))
                        centerprint (other, self.owner.message);
                play2(other, "misc/talk.wav");
        }
@@ -1248,7 +1225,7 @@ void door_generic_plat_blocked()
 void door_rotating_hit_top()
 {
        if (self.noise1 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
+               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
        self.state = STATE_TOP;
        if (self.spawnflags & DOOR_TOGGLE)
                return;         // don't come down automatically
@@ -1259,7 +1236,7 @@ void door_rotating_hit_top()
 void door_rotating_hit_bottom()
 {
        if (self.noise1 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
+               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
        if (self.lip==666) // self.lip is used to remember reverse opening direction for door_rotating
        {
                self.pos2 = '0 0 0' - self.pos2;
@@ -1271,7 +1248,7 @@ void door_rotating_hit_bottom()
 void door_rotating_go_down()
 {
        if (self.noise2 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
+               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        if (self.max_health)
        {
                self.takedamage = DAMAGE_YES;
@@ -1293,7 +1270,7 @@ void door_rotating_go_up()
                return;
        }
        if (self.noise2 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
+               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        self.state = STATE_UP;
        SUB_CalcAngleMove (self.pos2, TSPEED_LINEAR, self.speed, door_rotating_hit_top);
 
@@ -1335,24 +1312,32 @@ entity spawn_field(vector fmins, vector fmaxs)
 }
 
 
-float EntitiesTouching(entity e1, entity e2)
+entity LinkDoors_nextent(entity cur, entity near, entity pass)
+{
+       while((cur = find(cur, classname, self.classname)) && ((cur.spawnflags & 4) || cur.enemy))
+       {
+       }
+       return cur;
+}
+
+float LinkDoors_isconnected(entity e1, entity e2, entity pass)
 {
-       if (e1.absmin_x > e2.absmax_x)
+       float DELTA = 4;
+       if (e1.absmin_x > e2.absmax_x + DELTA)
                return FALSE;
-       if (e1.absmin_y > e2.absmax_y)
+       if (e1.absmin_y > e2.absmax_y + DELTA)
                return FALSE;
-       if (e1.absmin_z > e2.absmax_z)
+       if (e1.absmin_z > e2.absmax_z + DELTA)
                return FALSE;
-       if (e1.absmax_x < e2.absmin_x)
+       if (e2.absmin_x > e1.absmax_x + DELTA)
                return FALSE;
-       if (e1.absmax_y < e2.absmin_y)
+       if (e2.absmin_y > e1.absmax_y + DELTA)
                return FALSE;
-       if (e1.absmax_z < e2.absmin_z)
+       if (e2.absmin_z > e1.absmax_z + DELTA)
                return FALSE;
        return TRUE;
 }
 
-
 /*
 =============
 LinkDoors
@@ -1362,7 +1347,7 @@ LinkDoors
 */
 void LinkDoors()
 {
-       entity  t, starte;
+       entity  t;
        vector  cmins, cmaxs;
 
        if (self.enemy)
@@ -1382,68 +1367,70 @@ void LinkDoors()
                return;         // don't want to link this door
        }
 
-       cmins = self.absmin;
-       cmaxs = self.absmax;
-
-       starte = self;
-       t = self;
+       FindConnectedComponent(self, enemy, LinkDoors_nextent, LinkDoors_isconnected, world);
 
-       do
+       // set owner, and make a loop of the chain
+       dprint("LinkDoors: linking doors:");
+       for(t = self; ; t = t.enemy)
        {
-               self.owner = starte;                    // master door
-
-               if (self.health)
-                       starte.health = self.health;
-               IFTARGETED
-                       starte.targetname = self.targetname;
-               if (self.message != "")
-                       starte.message = self.message;
-
-               t = find(t, classname, self.classname);
-               if (!t)
+               dprint(" ", etos(t));
+               t.owner = self;
+               if(t.enemy == world)
                {
-                       self.enemy = starte;            // make the chain a loop
-
-               // shootable, or triggered doors just needed the owner/enemy links,
-               // they don't spawn a field
-
-                       self = self.owner;
-
-                       if (self.health)
-                               return;
-                       IFTARGETED
-                               return;
-                       if (self.items)
-                               return;
+                       t.enemy = self;
+                       break;
+               }
+       }
+       dprint("\n");
 
-                       self.owner.trigger_field = spawn_field(cmins, cmaxs);
+       // collect health, targetname, message, size
+       cmins = self.absmin;
+       cmaxs = self.absmax;
+       for(t = self; ; t = t.enemy)
+       {
+               if(t.health && !self.health)
+                       self.health = t.health;
+               if((t.targetname != "") && (self.targetname == ""))
+                       self.targetname = t.targetname;
+               if((t.message != "") && (self.message == ""))
+                       self.message = t.message;
+               if (t.absmin_x < cmins_x)
+                       cmins_x = t.absmin_x;
+               if (t.absmin_y < cmins_y)
+                       cmins_y = t.absmin_y;
+               if (t.absmin_z < cmins_z)
+                       cmins_z = t.absmin_z;
+               if (t.absmax_x > cmaxs_x)
+                       cmaxs_x = t.absmax_x;
+               if (t.absmax_y > cmaxs_y)
+                       cmaxs_y = t.absmax_y;
+               if (t.absmax_z > cmaxs_z)
+                       cmaxs_z = t.absmax_z;
+               if(t.enemy == self)
+                       break;
+       }
+
+       // distribute health, targetname, message
+       for(t = self; t; t = t.enemy)
+       {
+               t.health = self.health;
+               t.targetname = self.targetname;
+               t.message = self.message;
+               if(t.enemy == self)
+                       break;
+       }
 
-                       return;
-               }
+       // shootable, or triggered doors just needed the owner/enemy links,
+       // they don't spawn a field
 
-               if (EntitiesTouching(self,t))
-               {
-                       if (t.enemy)
-                               objerror ("cross connected doors");
-
-                       self.enemy = t;
-                       self = t;
-
-                       if (t.absmin_x < cmins_x)
-                               cmins_x = t.absmin_x;
-                       if (t.absmin_y < cmins_y)
-                               cmins_y = t.absmin_y;
-                       if (t.absmin_z < cmins_z)
-                               cmins_z = t.absmin_z;
-                       if (t.absmax_x > cmaxs_x)
-                               cmaxs_x = t.absmax_x;
-                       if (t.absmax_y > cmaxs_y)
-                               cmaxs_y = t.absmax_y;
-                       if (t.absmax_z > cmaxs_z)
-                               cmaxs_z = t.absmax_z;
-               }
-       } while (1 );
+       if (self.health)
+               return;
+       IFTARGETED
+               return;
+       if (self.items)
+               return;
 
+       self.trigger_field = spawn_field(cmins, cmaxs);
 }
 
 
@@ -1488,7 +1475,8 @@ void door_reset()
        setorigin(self, self.pos1);
        self.velocity = '0 0 0';
        self.state = STATE_BOTTOM;
-       self.think = SUB_Null;
+       self.think = func_null;
+       self.nextthink = 0;
 }
 
 // spawnflags require key (for now only func_door)
@@ -1501,13 +1489,13 @@ void spawnfunc_func_door()
                self.itemkeys |= ITEM_KEY_BIT(0);
        if (self.spawnflags & SPAWNFLAGS_SILVER_KEY)
                self.itemkeys |= ITEM_KEY_BIT(1);
-               
+
        //if (!self.deathtype) // map makers can override this
        //      self.deathtype = " got in the way";
        SetMovedir ();
 
        self.max_health = self.health;
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
        self.effects |= EF_LOWPRECISION;
        self.classname = "door";
@@ -1519,9 +1507,9 @@ void spawnfunc_func_door()
        // if(self.spawnflags & 8)
        //      self.dmg = 10000;
 
-    if(self.dmg && (!self.message))
+    if(self.dmg && (self.message == ""))
                self.message = "was squished";
-    if(self.dmg && (!self.message2))
+    if(self.dmg && (self.message2 == ""))
                self.message2 = "was squished by";
 
        if (self.sounds > 0)
@@ -1600,7 +1588,8 @@ void door_rotating_reset()
        self.angles = self.pos1;
        self.avelocity = '0 0 0';
        self.state = STATE_BOTTOM;
-       self.think = SUB_Null;
+       self.think = func_null;
+       self.nextthink = 0;
 }
 
 void door_rotating_init_startopen()
@@ -1632,7 +1621,7 @@ void spawnfunc_func_door_rotating()
 
        self.max_health = self.health;
        self.avelocity = self.movedir;
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
        self.velocity = '0 0 0';
        //self.effects |= EF_LOWPRECISION;
@@ -1644,9 +1633,9 @@ void spawnfunc_func_door_rotating()
     if(self.spawnflags & 8)
         self.dmg = 10000;
 
-    if(self.dmg && (!self.message))
+    if(self.dmg && (self.message == ""))
                self.message = "was squished";
-    if(self.dmg && (!self.message2))
+    if(self.dmg && (self.message2 == ""))
                self.message2 = "was squished by";
 
     if (self.sounds > 0)
@@ -1707,12 +1696,11 @@ void() fd_secret_move5;
 void() fd_secret_move6;
 void() fd_secret_done;
 
-float SECRET_OPEN_ONCE = 1;            // stays open
-float SECRET_1ST_LEFT = 2;             // 1st move is left of arrow
-float SECRET_1ST_DOWN = 4;             // 1st move is down from arrow
-float SECRET_NO_SHOOT = 8;             // only opened by trigger
-float SECRET_YES_SHOOT = 16;   // shootable even if targeted
-
+const float SECRET_OPEN_ONCE = 1;              // stays open
+const float SECRET_1ST_LEFT = 2;               // 1st move is left of arrow
+const float SECRET_1ST_DOWN = 4;               // 1st move is down from arrow
+const float SECRET_NO_SHOOT = 8;               // only opened by trigger
+const float SECRET_YES_SHOOT = 16;     // shootable even if targeted
 
 void fd_secret_use()
 {
@@ -1736,7 +1724,7 @@ void fd_secret_use()
        // Make a sound, wait a little...
 
        if (self.noise1 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTN_NORM);
+               sound(self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
        self.nextthink = self.ltime + 0.1;
 
        temp = 1 - (self.spawnflags & SECRET_1ST_LEFT); // 1 or -1
@@ -1761,7 +1749,12 @@ void fd_secret_use()
        self.dest2 = self.dest1 + v_forward * self.t_length;
        SUB_CalcMove(self.dest1, TSPEED_LINEAR, self.speed, fd_secret_move1);
        if (self.noise2 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
+               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+}
+
+void fd_secret_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+       fd_secret_use();
 }
 
 // Wait after first movement...
@@ -1770,14 +1763,14 @@ void fd_secret_move1()
        self.nextthink = self.ltime + 1.0;
        self.think = fd_secret_move2;
        if (self.noise3 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM);
+               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
 }
 
 // Start moving sideways w/sound...
 void fd_secret_move2()
 {
        if (self.noise2 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
+               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        SUB_CalcMove(self.dest2, TSPEED_LINEAR, self.speed, fd_secret_move3);
 }
 
@@ -1785,7 +1778,7 @@ void fd_secret_move2()
 void fd_secret_move3()
 {
        if (self.noise3 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM);
+               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
        if (!(self.spawnflags & SECRET_OPEN_ONCE))
        {
                self.nextthink = self.ltime + self.wait;
@@ -1797,7 +1790,7 @@ void fd_secret_move3()
 void fd_secret_move4()
 {
        if (self.noise2 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
+               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        SUB_CalcMove(self.dest1, TSPEED_LINEAR, self.speed, fd_secret_move5);
 }
 
@@ -1807,13 +1800,13 @@ void fd_secret_move5()
        self.nextthink = self.ltime + 1.0;
        self.think = fd_secret_move6;
        if (self.noise3 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM);
+               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
 }
 
 void fd_secret_move6()
 {
        if (self.noise2 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
+               sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        SUB_CalcMove(self.oldorigin, TSPEED_LINEAR, self.speed, fd_secret_done);
 }
 
@@ -1826,7 +1819,7 @@ void fd_secret_done()
                //self.th_pain = fd_secret_use;
        }
        if (self.noise3 != "")
-               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTN_NORM);
+               sound(self, CH_TRIGGER_SINGLE, self.noise3, VOL_BASE, ATTEN_NORM);
 }
 
 void secret_blocked()
@@ -1846,7 +1839,7 @@ Prints messages
 */
 void secret_touch()
 {
-       if not(other.iscreature)
+       if (!other.iscreature)
                return;
        if (self.attack_finished_single > time)
                return;
@@ -1855,7 +1848,7 @@ void secret_touch()
 
        if (self.message)
        {
-               if (other.flags & FL_CLIENT)
+               if (IS_CLIENT(other))
                        centerprint (other, self.message);
                play2(other, "misc/talk.wav");
        }
@@ -1869,7 +1862,8 @@ void secret_reset()
                self.takedamage = DAMAGE_YES;
        }
        setorigin(self, self.oldorigin);
-       self.think = SUB_Null;
+       self.think = func_null;
+       self.nextthink = 0;
 }
 
 /*QUAKED spawnfunc_func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot
@@ -1901,7 +1895,7 @@ void spawnfunc_func_door_secret()
        self.mangle = self.angles;
        self.angles = '0 0 0';
        self.classname = "door";
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
        self.effects |= EF_LOWPRECISION;
 
@@ -1919,7 +1913,7 @@ void spawnfunc_func_door_secret()
        {
                self.health = 10000;
                self.takedamage = DAMAGE_YES;
-               self.event_damage = fd_secret_use;
+               self.event_damage = fd_secret_damage;
        }
        self.oldorigin = self.origin;
        if (!self.wait)
@@ -1946,9 +1940,9 @@ void func_fourier_controller_think()
        float n, i, t;
 
        self.nextthink = time + 0.1;
-       if not (self.owner.active == ACTIVE_ACTIVE)
+       if(self.owner.active != ACTIVE_ACTIVE)
        {
-               self.owner.velocity = '0 0 0';          
+               self.owner.velocity = '0 0 0';
                return;
        }
 
@@ -1975,7 +1969,7 @@ void spawnfunc_func_fourier()
        if (self.noise != "")
        {
                precache_sound(self.noise);
-               soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE);
+               soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE);
        }
 
        if (!self.speed)
@@ -1986,9 +1980,9 @@ void spawnfunc_func_fourier()
        self.cnt = 360 / self.speed;
 
        self.blocked = generic_plat_blocked;
-       if(self.dmg & (!self.message))
+       if(self.dmg && (self.message == ""))
                self.message = " was squished";
-    if(self.dmg && (!self.message2))
+    if(self.dmg && (self.message2 == ""))
                self.message2 = "was squished by";
        if(self.dmg && (!self.dmgtime))
                self.dmgtime = 0.25;
@@ -1997,7 +1991,7 @@ void spawnfunc_func_fourier()
        if(self.netname == "")
                self.netname = "1 0 0 0 1";
 
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
 
        self.active = ACTIVE_ACTIVE;
@@ -2009,7 +2003,7 @@ void spawnfunc_func_fourier()
        controller.nextthink = time + 1;
        controller.think = func_fourier_controller_think;
        self.nextthink = self.ltime + 999999999;
-       self.think = SUB_Null;
+       self.think = SUB_NullThink; // for PushMove
 
        // Savage: Reduce bandwith, critical on e.g. nexdm02
        self.effects |= EF_LOWPRECISION;
@@ -2079,9 +2073,9 @@ void func_vectormamamam_controller_think()
 {
        self.nextthink = time + 0.1;
 
-       if not (self.owner.active == ACTIVE_ACTIVE)
+       if(self.owner.active != ACTIVE_ACTIVE)
        {
-               self.owner.velocity = '0 0 0';          
+               self.owner.velocity = '0 0 0';
                return;
        }
 
@@ -2106,7 +2100,7 @@ void func_vectormamamam_findtarget()
        if(!self.wp00 && !self.wp01 && !self.wp02 && !self.wp03)
                objerror("No reference entity found, so there is nothing to move. Aborting.");
 
-       self.destvec = self.origin - func_vectormamamam_origin(self.owner, 0);
+       self.destvec = self.origin - func_vectormamamam_origin(self, 0);
 
        entity controller;
        controller = spawn();
@@ -2121,7 +2115,7 @@ void spawnfunc_func_vectormamamam()
        if (self.noise != "")
        {
                precache_sound(self.noise);
-               soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTN_IDLE);
+               soundto(MSG_INIT, self, CH_TRIGGER_SINGLE, self.noise, VOL_BASE, ATTEN_IDLE);
        }
 
        if(!self.targetfactor)
@@ -2149,9 +2143,9 @@ void spawnfunc_func_vectormamamam()
                self.target4normal = normalize(self.target4normal);
 
        self.blocked = generic_plat_blocked;
-       if(self.dmg & (!self.message))
+       if(self.dmg && (self.message == ""))
                self.message = " was squished";
-    if(self.dmg && (!self.message2))
+    if(self.dmg && (self.message == ""))
                self.message2 = "was squished by";
        if(self.dmg && (!self.dmgtime))
                self.dmgtime = 0.25;
@@ -2160,12 +2154,12 @@ void spawnfunc_func_vectormamamam()
        if(self.netname == "")
                self.netname = "1 0 0 0 1";
 
-       if not(InitMovingBrushTrigger())
+       if (!InitMovingBrushTrigger())
                return;
 
        // wait for targets to spawn
        self.nextthink = self.ltime + 999999999;
-       self.think = SUB_Null;
+       self.think = SUB_NullThink; // for PushMove
 
        // Savage: Reduce bandwith, critical on e.g. nexdm02
        self.effects |= EF_LOWPRECISION;
@@ -2203,7 +2197,7 @@ void conveyor_think()
 
                for(e = world; (e = findentity(e, conveyor, self)); )
                {
-                       if(e.flags & FL_CLIENT) // doing it via velocity has quite some advantages
+                       if(IS_CLIENT(e)) // doing it via velocity has quite some advantages
                                continue; // done in SV_PlayerPhysics
 
                        setorigin(e, e.origin + self.movedir * sys_frametime);