X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fwarpzonelib%2Fserver.qc;h=921b2ed58289df9fadff0acb3d409feca06d498f;hb=b3499b8b8d3cf35c151aa14f362fa9e777c27d97;hp=6e0ecb5b33811de1c266da4a90c617a84d16b2c3;hpb=31db6b3b90dd4b14fc6f14600718c8db01586d6a;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/warpzonelib/server.qc b/qcsrc/warpzonelib/server.qc index 6e0ecb5b3..921b2ed58 100644 --- a/qcsrc/warpzonelib/server.qc +++ b/qcsrc/warpzonelib/server.qc @@ -1,5 +1,6 @@ .vector warpzone_oldorigin, warpzone_oldvelocity, warpzone_oldangles; .float warpzone_teleport_time; +.entity warpzone_teleport_zone; void WarpZone_StoreProjectileData(entity e) { @@ -21,17 +22,23 @@ void WarpZone_TeleportPlayer(entity teleporter, entity player, vector to, vector player.fixangle = TRUE; player.velocity = to_velocity; - if(player.effects & EF_TELEPORT_BIT) - player.effects &~= EF_TELEPORT_BIT; - else - player.effects |= EF_TELEPORT_BIT; + BITXOR_ASSIGN(player.effects, EF_TELEPORT_BIT); if(player.classname == "player") - player.flags &~= FL_ONGROUND; + BITCLR_ASSIGN(player.flags, FL_ONGROUND); 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 +97,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; } @@ -143,11 +168,11 @@ float WarpZone_Send(entity to, float sendflags) // we must send this flag for clientside to match properly too f = 0; if(self.warpzone_isboxy) - f |= 1; + BITSET_ASSIGN(f, 1); if(self.warpzone_fadestart) - f |= 2; + BITSET_ASSIGN(f, 2); if(self.origin != '0 0 0') - f |= 4; + BITSET_ASSIGN(f, 4); WriteByte(MSG_ENTITY, f); // we need THESE to render the warpzone (and cull properly)... @@ -196,9 +221,9 @@ float WarpZone_Camera_Send(entity to, float sendflags) WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_CAMERA); if(self.warpzone_fadestart) - f |= 2; + BITSET_ASSIGN(f, 2); if(self.origin != '0 0 0') - f |= 4; + BITSET_ASSIGN(f, 4); WriteByte(MSG_ENTITY, f); // we need THESE to render the warpzone (and cull properly)... @@ -243,7 +268,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 +293,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 +384,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; } @@ -375,7 +408,7 @@ void WarpZone_InitStep_UpdateTransform() tex = getsurfacetexture(self, i_s); if not(tex) break; // this is beyond the last one - if(tex == "textures/common/trigger") + if(tex == "textures/common/trigger" || tex == "trigger") continue; n_t = getsurfacenumtriangles(self, i_s); for(i_t = 0; i_t < n_t; ++i_t) @@ -486,7 +519,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; @@ -536,7 +569,7 @@ void spawnfunc_trigger_warpzone(void) setsize(self, self.mins, self.maxs); self.SendEntity = WarpZone_Send; self.SendFlags = 0xFFFFFF; - self.effects |= EF_NODEPTHTEST; + BITSET_ASSIGN(self.effects, EF_NODEPTHTEST); self.warpzone_next = warpzone_first; warpzone_first = self; } @@ -596,8 +629,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 +710,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 +}