]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/warpzonelib/server.qc
Merge branch 'master' into terencehill/centerprint_stuff
[xonotic/xonotic-data.pk3dir.git] / qcsrc / warpzonelib / server.qc
index 6e0ecb5b33811de1c266da4a90c617a84d16b2c3..29f5dc8db11aaf218354895ed5bba94f53e76397 100644 (file)
@@ -1,5 +1,6 @@
 .vector warpzone_oldorigin, warpzone_oldvelocity, warpzone_oldangles;
 .float warpzone_teleport_time;
+.entity warpzone_teleport_zone;
 
 void WarpZone_StoreProjectileData(entity e)
 {
@@ -32,6 +33,15 @@ void WarpZone_TeleportPlayer(entity teleporter, entity player, vector to, vector
        WarpZone_PostTeleportPlayer_Callback(player);
 }
 
+float WarpZone_Teleported_Send(entity to, float sf)
+{
+       WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_TELEPORTED);
+       WriteCoord(MSG_ENTITY, self.angles_x);
+       WriteCoord(MSG_ENTITY, self.angles_y);
+       WriteCoord(MSG_ENTITY, self.angles_z);
+       return TRUE;
+}
+
 float WarpZone_Teleport(entity player)
 {
        vector o0, a0, v0, o1, a1, v1;
@@ -90,6 +100,24 @@ float WarpZone_Teleport(entity player)
        WarpZone_TeleportPlayer(self, player, o1 - player.view_ofs, a1, v1);
        WarpZone_StoreProjectileData(player);
        player.warpzone_teleport_time = time;
+       player.warpzone_teleport_zone = self;
+#ifndef WARPZONE_USE_FIXANGLE
+       // instead of fixangle, send the transform to the client for smoother operation
+       player.fixangle = FALSE;
+
+       entity ts = spawn();
+       setmodel(ts, "null");
+       ts.SendEntity = WarpZone_Teleported_Send;
+       ts.SendFlags = 0xFFFFFF;
+       ts.drawonlytoclient = player;
+       ts.think = SUB_Remove;
+       ts.nextthink = time + 1;
+       ts.owner = player;
+       ts.enemy = self;
+       ts.effects = EF_NODEPTHTEST;
+       ts.classname = "warpzone_teleported";
+       ts.angles = self.warpzone_transform;
+#endif
 
        return 1;
 }
@@ -243,7 +271,13 @@ float WarpZone_CheckProjectileImpact()
        entity wz;
        wz = WarpZone_Find(self.origin + self.mins, self.origin + self.maxs);
        if(!wz)
-               return FALSE;
+               return 0;
+       if(self.warpzone_teleport_time == time)
+       {
+               // just ignore if we got teleported this frame already and now hit a wall and are in a warpzone again (this will cause a detonation)
+               // print("2 warps 1 frame\n");
+               return -1;
+       }
        o0 = self.origin;
        v0 = self.velocity;
        a0 = self.angles;
@@ -262,38 +296,40 @@ float WarpZone_CheckProjectileImpact()
        pd = WarpZone_TargetPlaneDist(wz, self.origin);
        if(pd < mpd)
        {
-               dpd = normalize(self.velocity) * self.warpzone_targetforward;
+               dpd = normalize(self.velocity) * wz.warpzone_targetforward;
                setorigin(self, self.origin + normalize(self.velocity) * ((mpd - pd) / dpd));
                if(!WarpZoneLib_MoveOutOfSolid(self))
                {
                        setorigin(self, o0);
                        self.angles = a0;
                        self.velocity = v0;
-                       return FALSE;
+                       return 0;
                }
        }
        WarpZone_RefSys_Add(self, wz);
        WarpZone_StoreProjectileData(self);
        self.warpzone_teleport_time = time;
 
-       return TRUE;
+       return +1;
 }
 float WarpZone_Projectile_Touch()
 {
+       float f;
        if(other.classname == "trigger_warpzone")
                return TRUE;
        if(WarpZone_Projectile_Touch_ImpactFilter_Callback())
                return TRUE;
-       if(WarpZone_CheckProjectileImpact())
-               return TRUE;
-       if(self.warpzone_teleport_time == time) // already got teleported this frame? no collision then please
+       if((f = WarpZone_CheckProjectileImpact()) != 0)
+               return (f > 0);
+       if(self.warpzone_teleport_time == time)
        {
+               // sequence: hit warpzone, get teleported, hit wall
+               // print("2 hits 1 frame\n");
                setorigin(self, self.warpzone_oldorigin);
                self.velocity = self.warpzone_oldvelocity;
                self.angles = self.warpzone_oldangles;
                return TRUE;
        }
-
        return FALSE;
 }
 
@@ -351,7 +387,7 @@ void WarpZoneCamera_InitStep_FindTarget()
                error("Camera with nonexisting target");
                return;
        }
-       ++warpzone_cameras_exist;
+       warpzone_cameras_exist = 1;
        WarpZone_Camera_SetUp(self, self.enemy.origin, self.enemy.angles);
        self.SendFlags = 0xFFFFFF;
 }
@@ -486,7 +522,7 @@ void WarpZone_InitStep_FinalizeTransform()
                return;
        }
 
-       ++warpzone_warpzones_exist;
+       warpzone_warpzones_exist = 1;
        WarpZone_SetUp(self, self.warpzone_origin, self.warpzone_angles, self.enemy.warpzone_origin, self.enemy.warpzone_angles);
        self.touch = WarpZone_Touch;
        self.SendFlags = 0xFFFFFF;
@@ -596,8 +632,41 @@ void WarpZone_StartFrame()
                self = e;
                WarpZones_Reconnect();
        }
-       for(e = world; (e = nextent(e)); )
-               WarpZone_StoreProjectileData(e);
+
+       if(warpzone_warpzones_exist)
+       {
+               entity oldself, oldother;
+               oldself = self;
+               oldother = other;
+               for(e = world; (e = nextent(e)); )
+               {
+                       WarpZone_StoreProjectileData(e);
+                       float f;
+                       f = clienttype(e);
+                       if(f == CLIENTTYPE_REAL)
+                       {
+                               if(e.solid != SOLID_NOT) // not spectating?
+                                       continue;
+                               if(e.movetype != MOVETYPE_NOCLIP && e.movetype != MOVETYPE_FLY) // not spectating? (this is to catch observers)
+                                       continue;
+                               self = WarpZone_Find(e.origin + e.mins, e.origin + e.maxs);
+                               if(!self)
+                                       continue;
+                               other = e;
+                               if(WarpZoneLib_ExactTrigger_Touch())
+                                       continue;
+                               WarpZone_Teleport(e); // NOT triggering targets by this!
+                       }
+                       if(f == CLIENTTYPE_NOTACLIENT)
+                       {
+                               for(; (e = nextent(e)); )
+                                       WarpZone_StoreProjectileData(e);
+                               break;
+                       }
+               }
+               self = oldself;
+               other = oldother;
+       }
 }
 
 .float warpzone_reconnecting;
@@ -644,3 +713,16 @@ void spawnfunc_target_warpzone_reconnect()
 {
        spawnfunc_trigger_warpzone_reconnect(); // both names make sense here :(
 }
+
+void WarpZone_PlayerPhysics_FixVAngle(void)
+{
+#ifndef WARPZONE_DONT_FIX_VANGLE
+       if(clienttype(self) == CLIENTTYPE_REAL)
+       if(self.v_angle_z <= 360) // if not already adjusted
+       if(time - self.ping * 0.001 < self.warpzone_teleport_time)
+       {
+               self.v_angle = WarpZone_TransformVAngles(self.warpzone_teleport_zone, self.v_angle);
+               self.v_angle_z += 720; // mark as adjusted
+       }
+#endif
+}