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=44e696aece4e632077fa2519e3e1cfa14e6b2086;hb=328e88c22c6dd30e5b09da92c0cbc4db029e3955;hpb=0e7ed909bffb4ff21f0c68d163edfc17487e380a diff --git a/qcsrc/warpzonelib/server.qc b/qcsrc/warpzonelib/server.qc index 44e696aec..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)); @@ -252,10 +297,8 @@ float WarpZone_Projectile_Touch() return FALSE; } -void WarpZone_InitStep_FindTarget() +void WarpZone_InitStep_FindOriginTarget() { - entity e; - if(self.killtarget != "") { self.aiment = find(world, targetname, self.killtarget); @@ -264,24 +307,12 @@ void WarpZone_InitStep_FindTarget() error("Warp zone with nonexisting killtarget"); return; } - } - - // this way only one of the two ents needs to target - if(self.target != "") - { - e = find(world, targetname, self.target); - if(e) - { - self.enemy = e; - self.enemy.enemy = self; - } + self.killtarget = string_null; } } void WarpZonePosition_InitStep_FindTarget() { - entity e; - if(self.target == "") { error("Warp zone position with no target"); @@ -305,18 +336,24 @@ 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() @@ -327,12 +364,6 @@ void WarpZone_InitStep_UpdateTransform() float i_s, i_t, n_t; string tex; - if(!self.enemy || self.enemy.enemy != self) - { - error("Invalid warp zone detected. Killed."); - return; - } - org = self.origin; if(org == '0 0 0') org = 0.5 * (self.mins + self.maxs); @@ -344,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) @@ -408,10 +439,57 @@ void WarpZone_InitStep_UpdateTransform() self.warpzone_origin = org; self.warpzone_angles = ang; } + +void WarpZone_InitStep_ClearTarget() +{ + if(self.enemy) + self.enemy.enemy = world; + 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, i = 0; (e = find(e, targetname, self.target)); ) + if(!e.enemy) + 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; + } + self.enemy = e2; + e2.enemy = self; + } +} + void WarpZone_InitStep_FinalizeTransform() { + if(!self.enemy || self.enemy.enemy != self) + { + error("Invalid warp zone detected. Killed."); + 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; @@ -487,6 +565,21 @@ void spawnfunc_func_camera(void) self.warpzone_next = warpzone_camera_first; warpzone_camera_first = self; } +void WarpZones_Reconnect() +{ + entity e; + e = self; + for(self = warpzone_first; self; self = self.warpzone_next) + 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; +} + void WarpZone_StartFrame() { entity e; @@ -495,17 +588,59 @@ void WarpZone_StartFrame() warpzone_initialized = 1; e = self; for(self = warpzone_first; self; self = self.warpzone_next) - WarpZone_InitStep_FindTarget(); + 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(); - for(self = warpzone_first; self; self = self.warpzone_next) - WarpZone_InitStep_FinalizeTransform(); self = e; + WarpZones_Reconnect(); } for(e = world; (e = nextent(e)); ) WarpZone_StoreProjectileData(e); } + +.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) + 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(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(self.warpzone_reconnecting || self.enemy.warpzone_reconnecting) + WarpZone_InitStep_FinalizeTransform(); + self = e; +} + +void spawnfunc_trigger_warpzone_reconnect() +{ + self.use = trigger_warpzone_reconnect_use; +} + +void spawnfunc_target_warpzone_reconnect() +{ + spawnfunc_trigger_warpzone_reconnect(); // both names make sense here :( +}