X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fwarpzonelib%2Fserver.qc;h=1ec66022144fbf74bf67a1fa9196627e108cddc7;hb=a484319f89b4267fa8bbb631b060df92e2eddbaf;hp=42cc94c3af1e25b65ad044e033753bc0469305b9;hpb=0b2b94b02edc3a3af4a7eb7402fc0c46d506fd9b;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/warpzonelib/server.qc b/qcsrc/warpzonelib/server.qc index 42cc94c3a..1ec660221 100644 --- a/qcsrc/warpzonelib/server.qc +++ b/qcsrc/warpzonelib/server.qc @@ -1,5 +1,13 @@ +// for think function +.vector warpzone_save_origin; +.vector warpzone_save_angles; +.vector warpzone_save_eorigin; +.vector warpzone_save_eangles; + +// for all entities .vector warpzone_oldorigin, warpzone_oldvelocity, warpzone_oldangles; .float warpzone_teleport_time; +.entity warpzone_teleport_zone; void WarpZone_StoreProjectileData(entity e) { @@ -21,17 +29,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 +104,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 +175,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 +228,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)... @@ -341,6 +373,22 @@ void WarpZonePosition_InitStep_FindTarget() self.enemy.aiment = self; } +void WarpZoneCamera_Think(void) +{ + if(self.warpzone_save_origin != self.origin + || self.warpzone_save_angles != self.angles + || self.warpzone_save_eorigin != self.enemy.origin + || self.warpzone_save_eangles != self.enemy.angles) + { + WarpZone_Camera_SetUp(self, self.enemy.origin, self.enemy.angles); + self.warpzone_save_origin = self.origin; + self.warpzone_save_angles = self.angles; + self.warpzone_save_eorigin = self.enemy.origin; + self.warpzone_save_eangles = self.enemy.angles; + } + self.nextthink = time; +} + void WarpZoneCamera_InitStep_FindTarget() { entity e; @@ -359,9 +407,16 @@ 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; + if(self.spawnflags & 1) + { + self.think = WarpZoneCamera_Think; + self.nextthink = time; + } + else + self.nextthink = 0; } void WarpZone_InitStep_UpdateTransform() @@ -383,7 +438,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,6 +541,7 @@ void WarpZone_InitStep_FindTarget() } } +void WarpZone_Think(); void WarpZone_InitStep_FinalizeTransform() { if(!self.enemy || self.enemy.enemy != self) @@ -494,10 +550,17 @@ 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; + if(self.spawnflags & 1) + { + self.think = WarpZone_Think; + self.nextthink = time; + } + else + self.nextthink = 0; } float warpzone_initialized; @@ -525,6 +588,11 @@ void spawnfunc_trigger_warpzone(void) // the map, with another killtarget to designate its // orientation +#ifndef WARPZONE_USE_FIXANGLE + // used when teleporting + precache_model("null"); +#endif + if(!self.scale) self.scale = self.modelscale; if(!self.scale) @@ -544,7 +612,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; } @@ -588,6 +656,31 @@ void WarpZones_Reconnect() self = e; } +void WarpZone_Think() +{ + if(self.warpzone_save_origin != self.origin + || self.warpzone_save_angles != self.angles + || self.warpzone_save_eorigin != self.enemy.origin + || self.warpzone_save_eangles != self.enemy.angles) + { + entity oldself; + oldself = self; + WarpZone_InitStep_UpdateTransform(); + self = self.enemy; + WarpZone_InitStep_UpdateTransform(); + self = oldself; + WarpZone_InitStep_FinalizeTransform(); + self = self.enemy; + WarpZone_InitStep_FinalizeTransform(); + self = oldself; + self.warpzone_save_origin = self.origin; + self.warpzone_save_angles = self.angles; + self.warpzone_save_eorigin = self.enemy.origin; + self.warpzone_save_eangles = self.enemy.angles; + } + self.nextthink = time; +} + void WarpZone_StartFrame() { entity e; @@ -604,8 +697,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; @@ -652,3 +778,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 +}