X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fwarpzonelib%2Fserver.qc;h=6e0ecb5b33811de1c266da4a90c617a84d16b2c3;hp=05f55f4ce8103fc5b660b3557e88eb6c644ecf1d;hb=328e88c22c6dd30e5b09da92c0cbc4db029e3955;hpb=2f0a0dcac813d09ade75cda471a28b351b1af8e0 diff --git a/qcsrc/warpzonelib/server.qc b/qcsrc/warpzonelib/server.qc index 05f55f4ce..6e0ecb5b3 100644 --- a/qcsrc/warpzonelib/server.qc +++ b/qcsrc/warpzonelib/server.qc @@ -48,7 +48,7 @@ float WarpZone_Teleport(entity player) o1 = WarpZone_TransformOrigin(self, o0); v1 = WarpZone_TransformVelocity(self, v0); - if(player.classname == "player") + if(clienttype(player) != CLIENTTYPE_NOTACLIENT) a1 = WarpZone_TransformVAngles(self, player.v_angle); else a1 = WarpZone_TransformAngles(self, a0); @@ -111,14 +111,23 @@ void WarpZone_Touch (void) e = self.enemy; if(WarpZone_Teleport(other)) { - if(self.aiment.target) - { - oldself = self; - activator = other; - self = self.aiment; - SUB_UseTargets(); - self = oldself; - } + string save1, save2; + activator = other; + + save1 = self.target; self.target = string_null; + save2 = self.target3; self.target3 = string_null; + SUB_UseTargets(); + if not(self.target) self.target = save1; + if not(self.target3) self.target3 = save2; + + oldself = self; + self = self.enemy; + save1 = self.target; self.target = string_null; + save2 = self.target2; self.target2 = string_null; + SUB_UseTargets(); + if not(self.target) self.target = save1; + if not(self.target2) self.target2 = save2; + self = oldself; } else { @@ -128,12 +137,26 @@ void WarpZone_Touch (void) float WarpZone_Send(entity to, float sendflags) { + float f; WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE); + // we must send this flag for clientside to match properly too + f = 0; + if(self.warpzone_isboxy) + f |= 1; + if(self.warpzone_fadestart) + f |= 2; + if(self.origin != '0 0 0') + f |= 4; + WriteByte(MSG_ENTITY, f); + // we need THESE to render the warpzone (and cull properly)... - WriteCoord(MSG_ENTITY, self.origin_x); - WriteCoord(MSG_ENTITY, self.origin_y); - WriteCoord(MSG_ENTITY, self.origin_z); + if(f & 4) + { + WriteCoord(MSG_ENTITY, self.origin_x); + WriteCoord(MSG_ENTITY, self.origin_y); + WriteCoord(MSG_ENTITY, self.origin_z); + } WriteShort(MSG_ENTITY, self.modelindex); WriteCoord(MSG_ENTITY, self.mins_x); @@ -158,17 +181,33 @@ float WarpZone_Send(entity to, float sendflags) WriteCoord(MSG_ENTITY, self.warpzone_targetangles_y); WriteCoord(MSG_ENTITY, self.warpzone_targetangles_z); + if(f & 2) + { + WriteShort(MSG_ENTITY, self.warpzone_fadestart); + WriteShort(MSG_ENTITY, self.warpzone_fadeend); + } + return TRUE; } float WarpZone_Camera_Send(entity to, float sendflags) { + float f; WriteByte(MSG_ENTITY, ENT_CLIENT_WARPZONE_CAMERA); + if(self.warpzone_fadestart) + f |= 2; + if(self.origin != '0 0 0') + f |= 4; + WriteByte(MSG_ENTITY, f); + // we need THESE to render the warpzone (and cull properly)... - WriteCoord(MSG_ENTITY, self.origin_x); - WriteCoord(MSG_ENTITY, self.origin_y); - WriteCoord(MSG_ENTITY, self.origin_z); + if(f & 4) + { + WriteCoord(MSG_ENTITY, self.origin_x); + WriteCoord(MSG_ENTITY, self.origin_y); + WriteCoord(MSG_ENTITY, self.origin_z); + } WriteShort(MSG_ENTITY, self.modelindex); WriteCoord(MSG_ENTITY, self.mins_x); @@ -187,6 +226,12 @@ float WarpZone_Camera_Send(entity to, float sendflags) WriteCoord(MSG_ENTITY, self.enemy.angles_y); WriteCoord(MSG_ENTITY, self.enemy.angles_z); + if(f & 2) + { + WriteShort(MSG_ENTITY, self.warpzone_fadestart); + WriteShort(MSG_ENTITY, self.warpzone_fadeend); + } + return TRUE; } @@ -210,7 +255,7 @@ float WarpZone_CheckProjectileImpact() WarpZone_TraceBox_ThroughZone(self.warpzone_oldorigin, self.mins, self.maxs, self.warpzone_oldorigin + self.warpzone_oldvelocity * frametime, MOVE_NORMAL, self, wz, WarpZone_trace_callback_t_null); // this will get us through the warpzone setorigin(self, trace_endpos); self.angles = WarpZone_TransformAngles(WarpZone_trace_transform, self.angles); - self.velocity = WarpZone_TransformVelocity(WarpZone_trace_transform, self.velocity); + self.velocity = WarpZone_TransformVelocity(WarpZone_trace_transform, self.warpzone_oldvelocity); // in case we are in our warp zone post-teleport, shift the projectile forward a bit mpd = max(vlen(self.mins), vlen(self.maxs)); @@ -262,6 +307,7 @@ void WarpZone_InitStep_FindOriginTarget() error("Warp zone with nonexisting killtarget"); return; } + self.killtarget = string_null; } } @@ -289,17 +335,25 @@ void WarpZonePosition_InitStep_FindTarget() void WarpZoneCamera_InitStep_FindTarget() { + entity e; + float i; if(self.target == "") { error("Camera with no target"); return; } - self.enemy = find(world, targetname, self.target); + self.enemy = world; + for(e = world, i = 0; (e = find(e, targetname, self.target)); ) + if(random() * ++i < 1) + self.enemy = e; if(self.enemy == world) { error("Camera with nonexisting target"); return; } + ++warpzone_cameras_exist; + WarpZone_Camera_SetUp(self, self.enemy.origin, self.enemy.angles); + self.SendFlags = 0xFFFFFF; } void WarpZone_InitStep_UpdateTransform() @@ -321,7 +375,7 @@ void WarpZone_InitStep_UpdateTransform() tex = getsurfacetexture(self, i_s); if not(tex) break; // this is beyond the last one - if(tex != "textures/common/warpzone") + if(tex == "textures/common/trigger") continue; n_t = getsurfacenumtriangles(self, i_s); for(i_t = 0; i_t < n_t; ++i_t) @@ -393,21 +447,29 @@ void WarpZone_InitStep_ClearTarget() self.enemy = world; } +entity warpzone_first; .entity warpzone_next; void WarpZone_InitStep_FindTarget() { float i; entity e, e2; + if(self.enemy) + return; + // this way only one of the two ents needs to target if(self.target != "") { + self.enemy = self; // so the if(!e.enemy) check also skips self, saves one IF + e2 = world; - for(e = world; (e = find(world, targetname, self.target)); ) + for(e = world, i = 0; (e = find(e, targetname, self.target)); ) if(!e.enemy) - if(random() * ++i < 1) - e2 = e; + if(e.classname == self.classname) // possibly non-warpzones may use the same targetname! + if(random() * ++i < 1) + e2 = e; if(!e2) { + self.enemy = world; error("Warpzone with non-existing target"); return; } @@ -424,8 +486,10 @@ void WarpZone_InitStep_FinalizeTransform() return; } + ++warpzone_warpzones_exist; WarpZone_SetUp(self, self.warpzone_origin, self.warpzone_angles, self.enemy.warpzone_origin, self.enemy.warpzone_angles); self.touch = WarpZone_Touch; + self.SendFlags = 0xFFFFFF; } float warpzone_initialized; @@ -509,6 +573,8 @@ void WarpZones_Reconnect() WarpZone_InitStep_ClearTarget(); for(self = warpzone_first; self; self = self.warpzone_next) WarpZone_InitStep_FindTarget(); + for(self = warpzone_camera_first; self; self = self.warpzone_next) + WarpZoneCamera_InitStep_FindTarget(); for(self = warpzone_first; self; self = self.warpzone_next) WarpZone_InitStep_FinalizeTransform(); self = e; @@ -525,8 +591,6 @@ void WarpZone_StartFrame() WarpZone_InitStep_FindOriginTarget(); for(self = warpzone_position_first; self; self = self.warpzone_next) WarpZonePosition_InitStep_FindTarget(); - for(self = warpzone_camera_first; self; self = self.warpzone_next) - WarpZoneCamera_InitStep_FindTarget(); for(self = warpzone_first; self; self = self.warpzone_next) WarpZone_InitStep_UpdateTransform(); self = e; @@ -536,24 +600,47 @@ void WarpZone_StartFrame() WarpZone_StoreProjectileData(e); } -void target_warpzone_reconnect_use() +.float warpzone_reconnecting; +float visible_to_some_client(entity ent) +{ + entity e; + for(e = nextent(world); clienttype(e) != CLIENTTYPE_NOTACLIENT; e = nextent(e)) + if(e.classname == "player" && clienttype(e) == CLIENTTYPE_REAL) + if(checkpvs(e.origin + e.view_ofs, ent)) + return 1; + return 0; +} +void trigger_warpzone_reconnect_use() { entity e; e = self; // NOTE: this matches for target, not targetname, but of course // targetname must be set too on the other entities for(self = warpzone_first; self; self = self.warpzone_next) - if(e.target == "" || self.target == e.target) + self.warpzone_reconnecting = ((e.target == "" || self.target == e.target) && !((e.spawnflags & 1) && (visible_to_some_client(self) || visible_to_some_client(self.enemy)))); + for(self = warpzone_camera_first; self; self = self.warpzone_next) + self.warpzone_reconnecting = ((e.target == "" || self.target == e.target) && !((e.spawnflags & 1) && visible_to_some_client(self))); + for(self = warpzone_first; self; self = self.warpzone_next) + if(self.warpzone_reconnecting) WarpZone_InitStep_ClearTarget(); for(self = warpzone_first; self; self = self.warpzone_next) - if(e.target == "" || self.target == e.target) + if(self.warpzone_reconnecting) WarpZone_InitStep_FindTarget(); + for(self = warpzone_camera_first; self; self = self.warpzone_next) + if(self.warpzone_reconnecting) + WarpZoneCamera_InitStep_FindTarget(); for(self = warpzone_first; self; self = self.warpzone_next) - if(e.target == "" || self.target == e.target || self.enemy.target == e.target) + if(self.warpzone_reconnecting || self.enemy.warpzone_reconnecting) WarpZone_InitStep_FinalizeTransform(); + self = e; +} + +void spawnfunc_trigger_warpzone_reconnect() +{ + self.use = trigger_warpzone_reconnect_use; } -void trigger_warpzone_reconnect() +void spawnfunc_target_warpzone_reconnect() { - self.use = target_warpzone_reconnect_use; + spawnfunc_trigger_warpzone_reconnect(); // both names make sense here :( }