]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/triggers/func/door.qc
Merge branch 'master' into Mario/use1
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / func / door.qc
index 3b831a237cdc5e93a0e8019a8a311bec457bf867..0546b2eae009f83316d4b83448dc8aa09bcad15e 100644 (file)
@@ -26,28 +26,28 @@ void() door_rotating_go_down;
 void() door_rotating_go_up;
 
 void door_blocked()
-{
-       if((self.spawnflags & 8) 
+{SELFPARAM();
+       if((self.spawnflags & 8)
 #ifdef SVQC
                && (other.takedamage != DAMAGE_NO)
 #elif defined(CSQC)
-               && !PHYS_DEAD(other)
+               && !IS_DEAD(other)
 #endif
        )
        { // KIll Kill Kill!!
 #ifdef SVQC
-               Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+               Damage (other, self, self, 10000, DEATH_HURTTRIGGER.m_id, other.origin, '0 0 0');
 #endif
        }
        else
        {
 #ifdef SVQC
                if((self.dmg) && (other.takedamage == DAMAGE_YES))    // Shall we bite?
-                       Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+                       Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER.m_id, other.origin, '0 0 0');
 #endif
 
                 // don't change direction for dead or dying stuff
-               if(PHYS_DEAD(other)
+               if(IS_DEAD(other)
 #ifdef SVQC
                        && (other.takedamage == DAMAGE_NO)
 #endif
@@ -78,40 +78,40 @@ void door_blocked()
                {
                        //gib dying stuff just to make sure
                        if((self.dmg) && (other.takedamage != DAMAGE_NO))    // Shall we bite?
-                               Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+                               Damage (other, self, self, 10000, DEATH_HURTTRIGGER.m_id, other.origin, '0 0 0');
                }
 #endif
        }
 }
 
 void door_hit_top()
-{
+{SELFPARAM();
        if (self.noise1 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_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
        if (self.classname == "door")
        {
-               self.think = door_go_down;
+               self.SUB_THINK = door_go_down;
        } else
        {
-               self.think = door_rotating_go_down;
+               self.SUB_THINK = door_rotating_go_down;
        }
-       trigger_setnextthink(self, self.ltime + self.wait);
+       self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
 }
 
 void door_hit_bottom()
-{
+{SELFPARAM();
        if (self.noise1 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
+               _sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_NORM);
        self.state = STATE_BOTTOM;
 }
 
 void door_go_down()
-{
+{SELFPARAM();
        if (self.noise2 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+               _sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        if (self.max_health)
        {
                self.takedamage = DAMAGE_YES;
@@ -123,25 +123,25 @@ void door_go_down()
 }
 
 void door_go_up()
-{
+{SELFPARAM();
        if (self.state == STATE_UP)
                return;         // already going up
 
        if (self.state == STATE_TOP)
        {       // reset top wait time
-               trigger_setnextthink(self, self.ltime + self.wait);
+               self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
                return;
        }
 
        if (self.noise2 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_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);
 
        string oldmessage;
        oldmessage = self.message;
        self.message = "";
-       SUB_UseTargets();
+       SUB_UseTargets(self, NULL, NULL);
        self.message = oldmessage;
 }
 
@@ -154,76 +154,67 @@ ACTIVATION FUNCTIONS
 =============================================================================
 */
 
-float door_check_keys(void)
+bool door_check_keys(entity door, entity player)
 {
-       local entity door;
-
-
-       if (self.owner)
-               door = self.owner;
-       else
-               door = self;
+       if(door.owner)
+               door = door.owner;
 
        // no key needed
-       if (!door.itemkeys)
+       if(!door.itemkeys)
                return true;
 
        // this door require a key
        // only a player can have a key
-       if (!IS_PLAYER(other))
+       if(!IS_PLAYER(player))
                return false;
 
-#ifdef SVQC
-       if (item_keys_usekey(door, other))
-       {
-               // some keys were used
-               if (other.key_door_messagetime <= time)
-               {
+       int valid = (door.itemkeys & player.itemkeys);
+       door.itemkeys &= ~valid; // only some of the needed keys were given
 
-                       play2(other, "misc/talk.wav");
-                       Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_ALSONEED, item_keys_keylist(door.itemkeys));
-                       other.key_door_messagetime = time + 2;
-               }
+       if(!door.itemkeys)
+       {
+#ifdef SVQC
+               play2(player, SND(TALK));
+               Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_DOOR_UNLOCKED);
+#endif
+               return true;
        }
-       else
+
+       if(!valid)
        {
-               // no keys were used
-               if (other.key_door_messagetime <= time)
+#ifdef SVQC
+               if(player.key_door_messagetime <= time)
                {
-                       play2(other, "misc/talk.wav");
-                       Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_LOCKED_NEED, item_keys_keylist(door.itemkeys));
-
-                       other.key_door_messagetime = time + 2;
+                       play2(player, door.noise3);
+                       Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_DOOR_LOCKED_NEED, item_keys_keylist(door.itemkeys));
+                       player.key_door_messagetime = time + 2;
                }
-       }
 #endif
+               return false;
+       }
 
-       if (door.itemkeys)
-       {
+       // door needs keys the player doesn't have
 #ifdef SVQC
-               // door is now unlocked
-               play2(other, "misc/talk.wav");
-               Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_DOOR_UNLOCKED);
-#endif
-               return true;
+       if(player.key_door_messagetime <= time)
+       {
+               play2(player, door.noise3);
+               Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_DOOR_LOCKED_ALSONEED, item_keys_keylist(door.itemkeys));
+               player.key_door_messagetime = time + 2;
        }
-       else
-               return false;
+#endif
+
+       return false;
 }
 
-void door_fire()
+void door_fire(entity this, entity actor, entity trigger)
 {
-       entity  oself;
-       entity  starte;
-
-       if (self.owner != self)
-               objerror ("door_fire: self.owner != self");
-
-       oself = self;
+       entity starte;
+       if (this.owner != this)
+               objerror ("door_fire: this.owner != this");
 
-       if (self.spawnflags & DOOR_TOGGLE)
+       if (this.spawnflags & DOOR_TOGGLE)
        {
-               if (self.state == STATE_UP || self.state == STATE_TOP)
+               if (this.state == STATE_UP || this.state == STATE_TOP)
                {
                        starte = self;
                        do
@@ -236,9 +227,9 @@ void door_fire()
                                {
                                        door_rotating_go_down ();
                                }
-                               self = self.enemy;
+                               setself(self.enemy);
                        } while ( (self != starte) && (self != world) );
-                       self = oself;
+                       setself(this);
                        return;
                }
        }
@@ -265,51 +256,41 @@ void door_fire()
                                door_rotating_go_up ();
                        }
                }
-               self = self.enemy;
+               setself(self.enemy);
        } while ( (self != starte) && (self != world) );
-       self = oself;
+       setself(this);
 }
 
-void door_use()
+void door_use(entity this, entity actor, entity trigger)
 {
-       entity oself;
-
        //dprint("door_use (model: ");dprint(self.model);dprint(")\n");
 
-       if (self.owner)
-       {
-               oself = self;
-               self = self.owner;
-               door_fire ();
-               self = oself;
-       }
+       if (this.owner)
+               WITHSELF(this.owner, door_fire(this.owner, actor, trigger));
 }
 
-void door_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void door_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {
-       entity oself;
-       if(self.spawnflags & DOOR_NOSPLASH)
+       if(this.spawnflags & DOOR_NOSPLASH)
                if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
                        return;
-       self.health = self.health - damage;
+       this.health = this.health - damage;
 
-       if (self.itemkeys)
+       if (this.itemkeys)
        {
                // don't allow opening doors through damage if keys are required
                return;
        }
 
-       if (self.health <= 0)
+       if (this.health <= 0)
        {
-               oself = self;
-               self = self.owner;
-               self.health = self.max_health;
-               self.takedamage = DAMAGE_NO;    // wil be reset upon return
-               door_use ();
-               self = oself;
+               this.owner.health = this.owner.max_health;
+               this.owner.takedamage = DAMAGE_NO;      // wil be reset upon return
+               door_use(this.owner, NULL, NULL);
        }
 }
 
+.float door_finished;
 
 /*
 ================
@@ -320,30 +301,30 @@ Prints messages
 */
 
 void door_touch()
-{
+{SELFPARAM();
        if (!IS_PLAYER(other))
                return;
-       if (self.owner.attack_finished_single > time)
+       if (self.owner.door_finished > time)
                return;
 
-       self.owner.attack_finished_single = time + 2;
+       self.owner.door_finished = time + 2;
 
 #ifdef SVQC
        if (!(self.owner.dmg) && (self.owner.message != ""))
        {
                if (IS_CLIENT(other))
                        centerprint(other, self.owner.message);
-               play2(other, "misc/talk.wav");
+               play2(other, self.owner.noise);
        }
 #endif
 }
 
 void door_generic_plat_blocked()
-{
+{SELFPARAM();
 
        if((self.spawnflags & 8) && (other.takedamage != DAMAGE_NO)) { // KIll Kill Kill!!
 #ifdef SVQC
-               Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+               Damage (other, self, self, 10000, DEATH_HURTTRIGGER.m_id, other.origin, '0 0 0');
 #endif
        }
        else
@@ -351,11 +332,11 @@ void door_generic_plat_blocked()
 
 #ifdef SVQC
                if((self.dmg) && (other.takedamage == DAMAGE_YES))    // Shall we bite?
-                       Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+                       Damage (other, self, self, self.dmg, DEATH_HURTTRIGGER.m_id, other.origin, '0 0 0');
 #endif
 
                 //Dont chamge direction for dead or dying stuff
-               if(PHYS_DEAD(other) && (other.takedamage == DAMAGE_NO))
+               if(IS_DEAD(other) && (other.takedamage == DAMAGE_NO))
                {
                        if (self.wait >= 0)
                        {
@@ -370,27 +351,27 @@ void door_generic_plat_blocked()
                {
                        //gib dying stuff just to make sure
                        if((self.dmg) && (other.takedamage != DAMAGE_NO))    // Shall we bite?
-                               Damage (other, self, self, 10000, DEATH_HURTTRIGGER, other.origin, '0 0 0');
+                               Damage (other, self, self, 10000, DEATH_HURTTRIGGER.m_id, other.origin, '0 0 0');
                }
 #endif
        }
 }
 
 void door_rotating_hit_top()
-{
+{SELFPARAM();
        if (self.noise1 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_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
-       self.think = door_rotating_go_down;
-       self.nextthink = self.ltime + self.wait;
+       self.SUB_THINK = door_rotating_go_down;
+       self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
 }
 
 void door_rotating_hit_bottom()
-{
+{SELFPARAM();
        if (self.noise1 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise1, VOL_BASE, ATTEN_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;
@@ -400,9 +381,9 @@ void door_rotating_hit_bottom()
 }
 
 void door_rotating_go_down()
-{
+{SELFPARAM();
        if (self.noise2 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
+               _sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_NORM);
        if (self.max_health)
        {
                self.takedamage = DAMAGE_YES;
@@ -414,24 +395,24 @@ void door_rotating_go_down()
 }
 
 void door_rotating_go_up()
-{
+{SELFPARAM();
        if (self.state == STATE_UP)
                return;         // already going up
 
        if (self.state == STATE_TOP)
        {       // reset top wait time
-               trigger_setnextthink(self, self.ltime + self.wait);
+               self.SUB_NEXTTHINK = self.SUB_LTIME + self.wait;
                return;
        }
        if (self.noise2 != "")
-               sound (self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTEN_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);
 
        string oldmessage;
        oldmessage = self.message;
        self.message = "";
-       SUB_UseTargets();
+       SUB_UseTargets(self, NULL, other); // TODO: is other needed here?
        self.message = oldmessage;
 }
 
@@ -445,101 +426,48 @@ Spawned if a door lacks a real activator
 */
 
 void door_trigger_touch()
-{
+{SELFPARAM();
        if (other.health < 1)
 #ifdef SVQC
-               if (!(other.iscreature && !PHYS_DEAD(other)))
+               if (!((other.iscreature || (other.flags & FL_PROJECTILE)) && !IS_DEAD(other)))
 #elif defined(CSQC)
-               if(!((IS_CLIENT(other) || other.classname == "csqcprojectile") && !PHYS_DEAD(other)))
+               if(!((IS_CLIENT(other) || other.classname == "csqcprojectile") && !IS_DEAD(other)))
 #endif
                        return;
 
-       if (time < self.attack_finished_single)
+       if (time < self.door_finished)
                return;
 
        // check if door is locked
-       if (!door_check_keys())
+       if (!door_check_keys(self, other))
                return;
 
-       self.attack_finished_single = time + 1;
-
-       activator = other;
-
-       self = self.owner;
-       door_use ();
-}
-
-#ifdef SVQC
-
-float door_trigger_send(entity to, float sf)
-{
-       WriteByte(MSG_ENTITY, ENT_CLIENT_DOOR_TRIGGER);
+       self.door_finished = time + 1;
 
-       WriteShort(MSG_ENTITY, num_for_edict(self.owner));
-       WriteCoord(MSG_ENTITY, self.origin_x);
-       WriteCoord(MSG_ENTITY, self.origin_y);
-       WriteCoord(MSG_ENTITY, self.origin_z);
-
-       WriteCoord(MSG_ENTITY, self.mins_x);
-       WriteCoord(MSG_ENTITY, self.mins_y);
-       WriteCoord(MSG_ENTITY, self.mins_z);
-       WriteCoord(MSG_ENTITY, self.maxs_x);
-       WriteCoord(MSG_ENTITY, self.maxs_y);
-       WriteCoord(MSG_ENTITY, self.maxs_z);
-
-       return true;
+       door_use(this.owner, other, NULL);
 }
 
-void door_trigger_link(entity trig)
-{
-       Net_LinkEntity(trig, false, 0, door_trigger_send);
-}
-
-void spawn_field(vector fmins, vector fmaxs)
-{
+void door_spawnfield(vector fmins, vector fmaxs)
+{SELFPARAM();
        entity  trigger;
        vector  t1 = fmins, t2 = fmaxs;
 
-       trigger = spawn();
-       trigger.classname = "doortriggerfield";
+       trigger = new(doortriggerfield);
        trigger.movetype = MOVETYPE_NONE;
        trigger.solid = SOLID_TRIGGER;
        trigger.owner = self;
+#ifdef SVQC
        trigger.touch = door_trigger_touch;
+#elif defined(CSQC)
+       trigger.trigger_touch = door_trigger_touch;
+       trigger.draw = trigger_draw_generic;
+       trigger.drawmask = MASK_NORMAL;
+#endif
 
        setsize (trigger, t1 - '60 60 8', t2 + '60 60 8');
-       door_trigger_link(trigger);
 }
 
-#elif defined(CSQC)
-
-void ent_door_trigger()
-{
-       float entnum = ReadShort();
-       self.origin_x = ReadCoord();
-       self.origin_y = ReadCoord();
-       self.origin_z = ReadCoord();
-       setorigin(self, self.origin);
-       self.mins_x = ReadCoord();
-       self.mins_y = ReadCoord();
-       self.mins_z = ReadCoord();
-       self.maxs_x = ReadCoord();
-       self.maxs_y = ReadCoord();
-       self.maxs_z = ReadCoord();
-       setsize(self, self.mins, self.maxs);
-
-       self.owner = findfloat(world, sv_entnum, entnum); // if owner doesn't exist, it shouldn't matter much
-       self.classname = "doortriggerfield";
-       self.movetype = MOVETYPE_NONE;
-       self.solid = SOLID_TRIGGER;
-       self.trigger_touch = door_trigger_touch;
-       self.draw = trigger_draw_generic;
-       self.drawmask = MASK_NORMAL;
-       self.move_time = time;
-}
 
-#endif
-#ifdef SVQC
 /*
 =============
 LinkDoors
@@ -549,7 +477,7 @@ LinkDoors
 */
 
 entity LinkDoors_nextent(entity cur, entity near, entity pass)
-{
+{SELFPARAM();
        while((cur = find(cur, classname, self.classname)) && ((cur.spawnflags & 4) || cur.enemy))
        {
        }
@@ -569,13 +497,17 @@ bool LinkDoors_isconnected(entity e1, entity e2, entity pass)
        return true;
 }
 
+#ifdef SVQC
 void door_link();
-void LinkDoors()
+#endif
+void LinkDoors(entity this)
 {
        entity  t;
        vector  cmins, cmaxs;
 
+#ifdef SVQC
        door_link();
+#endif
 
        if (self.enemy)
                return;         // already linked by another door
@@ -589,7 +521,8 @@ void LinkDoors()
                        return;
                if (self.items)
                        return;
-               spawn_field(self.absmin, self.absmax);
+
+               door_spawnfield(self.absmin, self.absmax);
 
                return;         // don't want to link this door
        }
@@ -597,10 +530,10 @@ void LinkDoors()
        FindConnectedComponent(self, enemy, LinkDoors_nextent, LinkDoors_isconnected, world);
 
        // set owner, and make a loop of the chain
-       dprint("LinkDoors: linking doors:");
+       LOG_TRACE("LinkDoors: linking doors:");
        for(t = self; ; t = t.enemy)
        {
-               dprint(" ", etos(t));
+               LOG_TRACE(" ", etos(t));
                t.owner = self;
                if(t.enemy == world)
                {
@@ -608,7 +541,7 @@ void LinkDoors()
                        break;
                }
        }
-       dprint("\n");
+       LOG_TRACE("\n");
 
        // collect health, targetname, message, size
        cmins = self.absmin;
@@ -657,10 +590,12 @@ void LinkDoors()
        if (self.items)
                return;
 
-       spawn_field(cmins, cmaxs);
+       door_spawnfield(cmins, cmaxs);
 }
 
+REGISTER_NET_LINKED(ENT_CLIENT_DOOR)
 
+#ifdef SVQC
 /*QUAKED spawnfunc_func_door (0 .5 .8) ? START_OPEN x DOOR_DONT_LINK GOLD_KEY SILVER_KEY TOGGLE
 if two doors touch, they are assumed to be connected and operate as a unit.
 
@@ -691,40 +626,18 @@ FIXME: only one sound set available at the time being
 */
 
 float door_send(entity to, float sf)
-{
-       WriteByte(MSG_ENTITY, ENT_CLIENT_DOOR);
+{SELFPARAM();
+       WriteHeader(MSG_ENTITY, ENT_CLIENT_DOOR);
        WriteByte(MSG_ENTITY, sf);
 
        if(sf & SF_TRIGGER_INIT)
        {
                WriteString(MSG_ENTITY, self.classname);
                WriteByte(MSG_ENTITY, self.spawnflags);
-               WriteShort(MSG_ENTITY, ((self.owner == self || !self.owner) ? -1 : num_for_edict(self.owner)));
-               WriteShort(MSG_ENTITY, ((self.enemy == self || !self.enemy) ? -1 : num_for_edict(self.enemy)));
-               WriteShort(MSG_ENTITY, num_for_edict(self));
-
-               WriteByte(MSG_ENTITY, self.scale);
-
-               WriteCoord(MSG_ENTITY, self.origin_x);
-               WriteCoord(MSG_ENTITY, self.origin_y);
-               WriteCoord(MSG_ENTITY, self.origin_z);
 
                WriteString(MSG_ENTITY, self.model);
 
-               WriteCoord(MSG_ENTITY, self.mins_x);
-               WriteCoord(MSG_ENTITY, self.mins_y);
-               WriteCoord(MSG_ENTITY, self.mins_z);
-               WriteCoord(MSG_ENTITY, self.maxs_x);
-               WriteCoord(MSG_ENTITY, self.maxs_y);
-               WriteCoord(MSG_ENTITY, self.maxs_z);
-
-               WriteCoord(MSG_ENTITY, self.movedir_x);
-               WriteCoord(MSG_ENTITY, self.movedir_y);
-               WriteCoord(MSG_ENTITY, self.movedir_z);
-
-               WriteAngle(MSG_ENTITY, self.angles_x);
-               WriteAngle(MSG_ENTITY, self.angles_y);
-               WriteAngle(MSG_ENTITY, self.angles_z);
+               trigger_common_write(self, true);
 
                WriteCoord(MSG_ENTITY, self.pos1_x);
                WriteCoord(MSG_ENTITY, self.pos1_y);
@@ -741,7 +654,7 @@ float door_send(entity to, float sf)
                WriteShort(MSG_ENTITY, self.speed);
                WriteByte(MSG_ENTITY, self.lip);
                WriteByte(MSG_ENTITY, self.state);
-               WriteCoord(MSG_ENTITY, self.ltime);
+               WriteCoord(MSG_ENTITY, self.SUB_LTIME);
        }
 
        if(sf & SF_TRIGGER_RESET)
@@ -769,38 +682,39 @@ float door_send(entity to, float sf)
 void door_link()
 {
        // set size now, as everything is loaded
-       FixSize(self);
-       Net_LinkEntity(self, false, 0, door_send);
+       //FixSize(self);
+       //Net_LinkEntity(self, false, 0, door_send);
 }
+#endif
 
-void door_init_startopen()
+void door_init_startopen(entity this)
 {
-       setorigin (self, self.pos2);
+       SUB_SETORIGIN(self, self.pos2);
        self.pos2 = self.pos1;
        self.pos1 = self.origin;
 
+#ifdef SVQC
        self.SendFlags |= SF_TRIGGER_UPDATE;
-}
-
 #endif
+}
 
-void door_reset()
+void door_reset(entity this)
 {
-       setorigin(self, self.pos1);
-       self.velocity = '0 0 0';
-       self.state = STATE_BOTTOM;
-       self.think = func_null;
-       self.nextthink = 0;
+       SUB_SETORIGIN(this, this.pos1);
+       this.SUB_VELOCITY = '0 0 0';
+       this.state = STATE_BOTTOM;
+       this.SUB_THINK = func_null;
+       this.SUB_NEXTTHINK = 0;
 
 #ifdef SVQC
-       self.SendFlags |= SF_TRIGGER_RESET;
+       this.SendFlags |= SF_TRIGGER_RESET;
 #endif
 }
 
 #ifdef SVQC
 
 // spawnflags require key (for now only func_door)
-void spawnfunc_func_door()
+spawnfunc(func_door)
 {
        // Quake 1 keys compatibility
        if (self.spawnflags & SPAWNFLAGS_GOLD_KEY)
@@ -808,7 +722,7 @@ void spawnfunc_func_door()
        if (self.spawnflags & SPAWNFLAGS_SILVER_KEY)
                self.itemkeys |= ITEM_KEY_BIT(1);
 
-       SetMovedir ();
+       SetMovedir(self);
 
        self.max_health = self.health;
        if (!InitMovingBrushTrigger())
@@ -816,8 +730,15 @@ void spawnfunc_func_door()
        self.effects |= EF_LOWPRECISION;
        self.classname = "door";
 
+       if(self.noise == "")
+               self.noise = "misc/talk.wav";
+       if(self.noise3 == "")
+               self.noise3 = "misc/talk.wav";
+       precache_sound(self.noise);
+       precache_sound(self.noise3);
+
        self.blocked = door_blocked;
-       self.use = door_use;
+       self.use1 = door_use;
 
        if(self.dmg && (self.message == ""))
                self.message = "was squished";
@@ -839,9 +760,12 @@ void spawnfunc_func_door()
        if (!self.lip)
                self.lip = 8;
 
-       self.pos1 = self.origin;
+       self.pos1 = self.SUB_ORIGIN;
        self.pos2 = self.pos1 + self.movedir*(fabs(self.movedir*self.size) - self.lip);
 
+       if(self.spawnflags & DOOR_NONSOLID)
+               self.solid = SOLID_NOT;
+
 // DOOR_START_OPEN is to allow an entity to be lighted in the closed position
 // but spawn in the open position
        if (self.spawnflags & DOOR_START_OPEN)
@@ -869,95 +793,90 @@ void spawnfunc_func_door()
 
 #elif defined(CSQC)
 
-void ent_door()
+void door_draw(entity this)
+{
+       Movetype_Physics_NoMatchServer(this);
+
+       trigger_draw_generic(this);
+}
+
+NET_HANDLE(ENT_CLIENT_DOOR, bool isnew)
 {
        float sf = ReadByte();
 
        if(sf & SF_TRIGGER_INIT)
        {
-               self.classname = strzone(ReadString());
-               self.spawnflags = ReadByte();
-               float myowner = ReadShort();
-               float myenemy = ReadShort();
-               self.sv_entnum = ReadShort();
-
-               self.scale = ReadByte();
-
-               self.origin_x = ReadCoord();
-               self.origin_y = ReadCoord();
-               self.origin_z = ReadCoord();
-               setorigin(self, self.origin);
-
-               self.mdl = strzone(ReadString());
-               setmodel(self, self.mdl);
-
-               self.mins_x = ReadCoord();
-               self.mins_y = ReadCoord();
-               self.mins_z = ReadCoord();
-               self.maxs_x = ReadCoord();
-               self.maxs_y = ReadCoord();
-               self.maxs_z = ReadCoord();
-               setsize(self, self.mins, self.maxs);
-
-               self.movedir_x = ReadCoord();
-               self.movedir_y = ReadCoord();
-               self.movedir_z = ReadCoord();
-
-               self.angles_x = ReadAngle();
-               self.angles_y = ReadAngle();
-               self.angles_z = ReadAngle();
-
-               self.pos1_x = ReadCoord();
-               self.pos1_y = ReadCoord();
-               self.pos1_z = ReadCoord();
-               self.pos2_x = ReadCoord();
-               self.pos2_y = ReadCoord();
-               self.pos2_z = ReadCoord();
-
-               self.size_x = ReadCoord();
-               self.size_y = ReadCoord();
-               self.size_z = ReadCoord();
-
-               self.wait = ReadShort();
-               self.speed = ReadShort();
-               self.lip = ReadByte();
-               self.state = ReadByte();
-               self.ltime = ReadCoord();
-
-               self.movetype = MOVETYPE_PUSH;
-               self.solid = SOLID_BSP;
-               self.trigger_touch = door_touch;
-               self.draw = trigger_draw_generic;
-               self.drawmask = MASK_NORMAL;
-               self.move_time = time;
-               self.use = door_use;
-               self.blocked = door_blocked;
-
-               print(ftos(self.entnum), " ", ftos(self.sv_entnum), "\n");
-
-               self.owner = ((myowner == -1) ? self : findfloat(world, sv_entnum, myowner));
-               self.enemy = ((myenemy == -1) ? self : findfloat(world, sv_entnum, myenemy));
+               this.classname = strzone(ReadString());
+               this.spawnflags = ReadByte();
+
+               this.mdl = strzone(ReadString());
+               _setmodel(this, this.mdl);
+
+               trigger_common_read(true);
+
+               vector v;
+
+               v.x = ReadCoord();
+               v.y = ReadCoord();
+               v.z = ReadCoord();
+               this.pos1 = v;
+
+               v.x = ReadCoord();
+               v.y = ReadCoord();
+               v.z = ReadCoord();
+               this.pos2 = v;
+
+               v.x = ReadCoord();
+               v.y = ReadCoord();
+               v.z = ReadCoord();
+               this.size = v;
+
+               this.wait = ReadShort();
+               this.speed = ReadShort();
+               this.lip = ReadByte();
+               this.state = ReadByte();
+               this.SUB_LTIME = ReadCoord();
+
+               this.solid = SOLID_BSP;
+               this.movetype = MOVETYPE_PUSH;
+               this.trigger_touch = door_touch;
+               this.draw = door_draw;
+               this.drawmask = MASK_NORMAL;
+               this.use1 = door_use;
+
+               LinkDoors(this);
+
+               if(this.spawnflags & DOOR_START_OPEN)
+                       door_init_startopen(this);
+
+               this.move_time = time;
+               this.move_origin = this.origin;
+               this.move_movetype = MOVETYPE_PUSH;
+               this.move_angles = this.angles;
+               this.move_blocked = door_blocked;
        }
 
        if(sf & SF_TRIGGER_RESET)
        {
-               door_reset();
+               door_reset(this);
        }
 
        if(sf & SF_TRIGGER_UPDATE)
        {
-               self.origin_x = ReadCoord();
-               self.origin_y = ReadCoord();
-               self.origin_z = ReadCoord();
-               setorigin(self, self.origin);
-
-               self.pos1_x = ReadCoord();
-               self.pos1_y = ReadCoord();
-               self.pos1_z = ReadCoord();
-               self.pos2_x = ReadCoord();
-               self.pos2_y = ReadCoord();
-               self.pos2_z = ReadCoord();
+               this.origin_x = ReadCoord();
+               this.origin_y = ReadCoord();
+               this.origin_z = ReadCoord();
+               setorigin(this, this.origin);
+               this.move_origin = this.origin;
+
+               this.pos1_x = ReadCoord();
+               this.pos1_y = ReadCoord();
+               this.pos1_z = ReadCoord();
+               this.pos2_x = ReadCoord();
+               this.pos2_y = ReadCoord();
+               this.pos2_z = ReadCoord();
        }
+       return true;
 }
 
 #endif