From: Rudolf Polzer Date: Wed, 21 Jul 2010 19:24:18 +0000 (+0200) Subject: mostly working code to use csqc entities for hook, electro, gauntlet (currently doesn... X-Git-Tag: xonotic-v0.1.0preview~423^2~24 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=2212005a014abddeecb44667d04392cb90200f99;p=xonotic%2Fxonotic-data.pk3dir.git mostly working code to use csqc entities for hook, electro, gauntlet (currently doesn't draw the hook end thingy properly) --- diff --git a/qcsrc/client/Main.qc b/qcsrc/client/Main.qc index ed851b9c1..dc1f5bb51 100644 --- a/qcsrc/client/Main.qc +++ b/qcsrc/client/Main.qc @@ -924,6 +924,9 @@ void(float bIsNewEntity) CSQC_Ent_Update = case ENT_CLIENT_WARPZONE: WarpZone_Read(bIsNewEntity); break; case ENT_CLIENT_WARPZONE_CAMERA: WarpZone_Camera_Read(bIsNewEntity); break; case ENT_CLIENT_TRIGGER_MUSIC: Ent_ReadTriggerMusic(); break; + case ENT_CLIENT_HOOK: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_HOOK); break; + case ENT_CLIENT_LGBEAM: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_LGBEAM); break; + case ENT_CLIENT_GAUNTLET: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_GAUNTLET); break; default: error(strcat("unknown entity type in CSQC_Ent_Update: ", ftos(self.enttype), "\n")); break; @@ -1304,10 +1307,6 @@ float CSQC_Parse_TempEntity() Net_ReadRace(); bHandled = true; break; - case TE_CSQC_BEAM: - Net_GrapplingHook(); - bHandled = true; - break; case TE_CSQC_SPAWN: Net_ReadSpawn(); bHandled = true; diff --git a/qcsrc/client/hook.qc b/qcsrc/client/hook.qc index 9f690d5bc..8aad6137c 100644 --- a/qcsrc/client/hook.qc +++ b/qcsrc/client/hook.qc @@ -1,17 +1,8 @@ -.vector HookStart; -.vector HookEnd; -.float HookKillTime; -.vector LGBeamStart; -.vector LGBeamEnd; -.float LGBeamKillTime; -.float LGBeamSound; -.float LGBeamSilent; -.vector GauntletBeamStart; -.vector GauntletBeamEnd; -.float GauntletBeamKillTime; -.float GauntletBeamSound; -.float GauntletBeamSilent; - +.float HookType; // ENT_CLIENT_* +.vector origin; +.vector velocity; +.float HookSound; +.float HookSilent; void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float alpha, float drawflag) { @@ -58,211 +49,183 @@ void Draw_GrapplingHook_trace_callback(vector start, vector hit, vector end) void Draw_GrapplingHook() { vector a, b; - string tex; + string tex, snd; vector rgb; float t; float s; vector vs; - if(time < self.HookKillTime) - { - s = cvar("cl_gunalign"); - if(s != 1 && s != 2 && s != 4) - s = 3; // default value - --s; - vs = hook_shotorigin[s]; - - if(self.sv_entnum == player_localentnum - 1) - a = view_origin + view_forward * vs_x + view_right * -vs_y + view_up * vs_z; - else - a = self.HookStart; - b = self.HookEnd; - - t = GetPlayerColorForce(self.sv_entnum); - - if(t == COLOR_TEAM1) - { - tex = "particles/hook_red"; - rgb = '1 .3 .3'; - } - else if(t == COLOR_TEAM2) - { - tex = "particles/hook_blue"; - rgb = '.3 .3 1'; - } - else if(t == COLOR_TEAM3) - { - tex = "particles/hook_yellow"; - rgb = '1 1 .3'; - } - else if(t == COLOR_TEAM4) - { - tex = "particles/hook_pink"; - rgb = '1 .3 1'; - } - else - { - tex = "particles/hook_green"; - rgb = '.3 1 .3'; - } + InterpolateOrigin_Do(); - Draw_GrapplingHook_trace_callback_tex = tex; - Draw_GrapplingHook_trace_callback_rnd = random(); - WarpZone_TraceBox_ThroughZone(a, '0 0 0', '0 0 0', b, MOVE_NOMONSTERS, world, world, Draw_GrapplingHook_trace_callback); - Draw_GrapplingHook_trace_callback_tex = string_null; + s = cvar("cl_gunalign"); + if(s != 1 && s != 2 && s != 4) + s = 3; // default value + --s; + switch(self.HookType) + { + default: + case ENT_CLIENT_HOOK: + vs = hook_shotorigin[s]; + break; + case ENT_CLIENT_LGBEAM: + vs = electro_shotorigin[s]; + break; + case ENT_CLIENT_GAUNTLET: + vs = gauntlet_shotorigin[s]; + break; } - if(time < self.LGBeamKillTime) + if((self.owner.sv_entnum == player_localentnum - 1)) { - s = cvar("cl_gunalign"); - if(s != 1 && s != 2 && s != 4) - s = 3; // default value - --s; - vs = electro_shotorigin[s]; - - if(self.sv_entnum == player_localentnum - 1) + switch(self.HookType) { - b = view_origin + view_forward * MAX_SHOT_DISTANCE; - WarpZone_TraceLine(view_origin, b, MOVE_NORMAL, world); - a = view_origin + view_forward * vs_x + view_right * -vs_y + view_up * vs_z; + default: + case ENT_CLIENT_HOOK: + a = view_origin + view_forward * vs_x + view_right * -vs_y + view_up * vs_z; + b = self.origin; + break; + case ENT_CLIENT_LGBEAM: + case ENT_CLIENT_GAUNTLET: + b = view_origin + view_forward * MAX_SHOT_DISTANCE; + WarpZone_TraceLine(view_origin, b, MOVE_NORMAL, world); + b = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); + a = view_origin + view_forward * vs_x + view_right * -vs_y + view_up * vs_z; + break; } - else + } + else + { + switch(self.HookType) { - a = self.LGBeamStart; - b = self.LGBeamEnd; + default: + case ENT_CLIENT_HOOK: + a = self.velocity; + b = self.origin; + break; + case ENT_CLIENT_LGBEAM: + case ENT_CLIENT_GAUNTLET: + a = self.origin; + b = self.velocity; + break; } + } - tex = "particles/lgbeam"; - rgb = '1 1 1'; - - Draw_GrapplingHook_trace_callback_tex = tex; - Draw_GrapplingHook_trace_callback_rnd = random(); - WarpZone_TraceBox_ThroughZone(a, '0 0 0', '0 0 0', b, MOVE_NORMAL, world, world, Draw_GrapplingHook_trace_callback); - Draw_GrapplingHook_trace_callback_tex = string_null; + t = GetPlayerColorForce(self.owner.sv_entnum); - // helps the sound - setorigin(self, a); + switch(self.HookType) + { + default: + case ENT_CLIENT_HOOK: + if(t == COLOR_TEAM1) + { + tex = "particles/hook_red"; + rgb = '1 .3 .3'; + } + else if(t == COLOR_TEAM2) + { + tex = "particles/hook_blue"; + rgb = '.3 .3 1'; + } + else if(t == COLOR_TEAM3) + { + tex = "particles/hook_yellow"; + rgb = '1 1 .3'; + } + else if(t == COLOR_TEAM4) + { + tex = "particles/hook_pink"; + rgb = '1 .3 1'; + } + else + { + tex = "particles/hook_green"; + rgb = '.3 1 .3'; + } + break; + case ENT_CLIENT_LGBEAM: + tex = "particles/lgbeam"; + rgb = '1 1 1'; + break; + case ENT_CLIENT_GAUNTLET: + tex = "particles/gauntletbeam"; + rgb = '1 1 1'; + break; } - if(time < self.GauntletBeamKillTime) + Draw_GrapplingHook_trace_callback_tex = tex; + Draw_GrapplingHook_trace_callback_rnd = random(); + WarpZone_TraceBox_ThroughZone(a, '0 0 0', '0 0 0', b, MOVE_NOMONSTERS, world, world, Draw_GrapplingHook_trace_callback); + Draw_GrapplingHook_trace_callback_tex = string_null; + + switch(self.HookType) { - s = cvar("cl_gunalign"); - if(s != 1 && s != 2 && s != 4) - s = 3; // default value - --s; - vs = gauntlet_shotorigin[s]; + default: + case ENT_CLIENT_HOOK: + self.angles = vectoangles(b - a); + break; + case ENT_CLIENT_LGBEAM: + case ENT_CLIENT_GAUNTLET: + break; + } +} - if(self.sv_entnum == player_localentnum - 1) - { - b = view_origin + view_forward * MAX_SHOT_DISTANCE; - WarpZone_TraceLine(view_origin, b, MOVE_NORMAL, world); - a = view_origin + view_forward * vs_x + view_right * -vs_y + view_up * vs_z; - } - else - { - a = self.GauntletBeamStart; - b = self.GauntletBeamEnd; - } +void Remove_GrapplingHook() +{ + sound (self, CHAN_PROJECTILE, "misc/null.wav", VOL_BASE, ATTN_NORM); +} - tex = "particles/gauntletbeam"; - rgb = '1 1 1'; +void Ent_ReadHook(float bIsNew, float type) +{ + self.HookType = type; - Draw_GrapplingHook_trace_callback_tex = tex; - Draw_GrapplingHook_trace_callback_rnd = random(); - WarpZone_TraceBox_ThroughZone(a, '0 0 0', '0 0 0', b, MOVE_NORMAL, world, world, Draw_GrapplingHook_trace_callback); - Draw_GrapplingHook_trace_callback_tex = string_null; + float sf; + sf = ReadByte(); - // helps the sound - setorigin(self, a); - } + self.HookSilent = (sf & 0x80); + self.iflags = IFLAG_VELOCITY; - if(time < self.LGBeamKillTime && !self.LGBeamSilent) - { - if(!self.LGBeamSound) - { - sound (self, CHAN_PROJECTILE, "weapons/lgbeam_fly.wav", VOL_BASE, ATTN_NORM); - self.LGBeamSound = 1; - } - } - else + InterpolateOrigin_Undo(); + + if(sf & 1) { - if(self.LGBeamSound) - { - sound (self, CHAN_PROJECTILE, "misc/null.wav", VOL_BASE, ATTN_NORM); - self.LGBeamSound = 0; - } + self.owner = playerslots[ReadByte() - 1]; } - - if(time < self.GauntletBeamKillTime && !self.GauntletBeamSilent) + if(sf & 2) { - if(!self.GauntletBeamSound) - { - sound (self, CHAN_PROJECTILE, "weapons/gauntletbeam_fly.wav", VOL_BASE, ATTN_NORM); - self.GauntletBeamSound = 1; - } + self.origin_x = ReadCoord(); + self.origin_y = ReadCoord(); + self.origin_z = ReadCoord(); + setorigin(self, self.origin); } - else + if(sf & 4) { - if(self.GauntletBeamSound) - { - sound (self, CHAN_PROJECTILE, "misc/null.wav", VOL_BASE, ATTN_NORM); - self.GauntletBeamSound = 0; - } + self.velocity_x = ReadCoord(); + self.velocity_y = ReadCoord(); + self.velocity_z = ReadCoord(); } -} - -void Net_GrapplingHook() -{ - float i, t; - vector start, end; - entity p; - - i = ReadByte(); - t = ReadByte(); - end_x = ReadCoord(); - end_y = ReadCoord(); - end_z = ReadCoord(); - start_x = ReadCoord(); - start_y = ReadCoord(); - start_z = ReadCoord(); - - if(i <= 0 || i >= 256) // not owned by a client - return; - --i; - p = playerslots[i]; - if(!p) - return; + InterpolateOrigin_Note(); - switch(t) + if(bIsNew) { - case 0: // hook beam - p.HookKillTime = time + 0.1; - p.HookStart = start; - p.HookEnd = end; - p.draw = Draw_GrapplingHook; - break; - case 1: // electro lgbeam - p.LGBeamKillTime = time + 0.1; - p.LGBeamStart = start; - p.LGBeamEnd = end; - p.LGBeamSilent = 0; - p.draw = Draw_GrapplingHook; - break; - case 2: // silent electro lgbeam - p.LGBeamKillTime = time + 0.1; - p.LGBeamStart = start; - p.LGBeamEnd = end; - p.LGBeamSilent = 1; - p.draw = Draw_GrapplingHook; - break; - case 3: // gauntlet beam - p.GauntletBeamKillTime = time + 0.1; - p.GauntletBeamStart = start; - p.GauntletBeamEnd = end; - p.GauntletBeamSilent = 0; - p.draw = Draw_GrapplingHook; - break; + self.draw = Draw_GrapplingHook; + self.entremove = Remove_GrapplingHook; + + switch(self.HookType) + { + default: + case ENT_CLIENT_HOOK: + // for the model + setmodel(self, "models/hook.md3"); + self.drawmask = MASK_NORMAL; + break; + case ENT_CLIENT_LGBEAM: + sound (self, CHAN_PROJECTILE, "weapons/lgbeam_fly.wav", VOL_BASE, ATTN_NORM); + break; + case ENT_CLIENT_GAUNTLET: + sound (self, CHAN_PROJECTILE, "weapons/gauntletbeam_fly.wav", VOL_BASE, ATTN_NORM); + break; + } } } @@ -270,4 +233,7 @@ void Hook_Precache() { precache_sound("weapons/lgbeam_fly.wav"); precache_sound("weapons/gauntletbeam_fly.wav"); + precache_model("models/hook.md3"); } + +// TODO: hook: temporarily transform self.origin for drawing the model along warpzones! diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh index e8a20f556..7a5cf3447 100644 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@ -59,7 +59,6 @@ const float TE_CSQC_ANNOUNCE = 110; const float TE_CSQC_TARGET_MUSIC = 111; const float TE_CSQC_NOTIFY = 112; const float TE_CSQC_WEAPONCOMPLAIN = 113; -const float TE_CSQC_BEAM = 114; const float TE_CSQC_CAMPINGRIFLE_SCOPE = 115; const float RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder @@ -107,6 +106,9 @@ const float ENT_CLIENT_TUBANOTE = 23; const float ENT_CLIENT_WARPZONE = 24; const float ENT_CLIENT_WARPZONE_CAMERA = 25; const float ENT_CLIENT_TRIGGER_MUSIC = 26; +const float ENT_CLIENT_HOOK = 27; +const float ENT_CLIENT_LGBEAM = 28; +const float ENT_CLIENT_GAUNTLET = 29; const float ENT_CLIENT_TURRET = 40; diff --git a/qcsrc/server/g_hook.qc b/qcsrc/server/g_hook.qc index 3ce0b310d..ce3d9b72b 100644 --- a/qcsrc/server/g_hook.qc +++ b/qcsrc/server/g_hook.qc @@ -114,6 +114,33 @@ void GrapplingHook_Stop() self.hook_length = -1; } +.vector hook_start, hook_end; +float GrapplingHookSend(entity to, float sf) +{ + WriteByte(MSG_ENTITY, ENT_CLIENT_HOOK); + sf = sf & 0x7F; + if(sound_allowed(MSG_BROADCAST, self.owner)) + sf |= 0x80; + WriteByte(MSG_ENTITY, sf); + if(sf & 1) + { + WriteByte(MSG_ENTITY, num_for_edict(self.owner)); + } + if(sf & 2) + { + WriteCoord(MSG_ENTITY, self.hook_start_x); + WriteCoord(MSG_ENTITY, self.hook_start_y); + WriteCoord(MSG_ENTITY, self.hook_start_z); + } + if(sf & 4) + { + WriteCoord(MSG_ENTITY, self.hook_end_x); + WriteCoord(MSG_ENTITY, self.hook_end_y); + WriteCoord(MSG_ENTITY, self.hook_end_z); + } + return TRUE; +} + void GrapplingHookThink() { float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch, s; @@ -243,17 +270,16 @@ void GrapplingHookThink() makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0'); myorg = WarpZone_RefSys_TransformOrigin(self, self.owner, self.origin) + v_forward * (-9); - // TODO turn into a csqc entity - WriteByte(MSG_BROADCAST, SVC_TEMPENTITY); - WriteByte(MSG_BROADCAST, TE_CSQC_BEAM); - WriteByte(MSG_BROADCAST, num_for_edict(self.owner)); - WriteByte(MSG_BROADCAST, 0); - WriteCoord(MSG_BROADCAST, myorg_x); - WriteCoord(MSG_BROADCAST, myorg_y); - WriteCoord(MSG_BROADCAST, myorg_z); - WriteCoord(MSG_BROADCAST, org_x); - WriteCoord(MSG_BROADCAST, org_y); - WriteCoord(MSG_BROADCAST, org_z); + if(myorg != self.hook_start) + { + self.SendFlags |= 2; + self.hook_start = myorg; + } + if(org != self.hook_end) + { + self.SendFlags |= 4; + self.hook_end = org; + } } void GrapplingHookTouch (void) @@ -327,7 +353,7 @@ void FireGrapplingHook (void) missile.movetype = MOVETYPE_FLY; PROJECTILE_MAKETRIGGER(missile); - setmodel (missile, "models/hook.md3"); // precision set below + //setmodel (missile, "models/hook.md3"); // precision set below setsize (missile, '-3 -3 -3', '3 3 3'); setorigin (missile, org); @@ -348,6 +374,10 @@ void FireGrapplingHook (void) missile.event_damage = GrapplingHook_Damage; missile.takedamage = DAMAGE_AIM; missile.damageforcescale = 0; + + missile.hook_start = missile.hook_end = missile.origin; + + Net_LinkEntity(missile, FALSE, 0, GrapplingHookSend); } // void GrapplingHookFrame() diff --git a/qcsrc/server/w_electro.qc b/qcsrc/server/w_electro.qc index 3a54cf386..c569b2f11 100644 --- a/qcsrc/server/w_electro.qc +++ b/qcsrc/server/w_electro.qc @@ -184,6 +184,32 @@ void W_Electro_Attack2() CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO, FALSE); // no culling, it has sound } +.vector hook_start, hook_end; +float lgbeam_send(entity to, float sf) +{ + WriteByte(MSG_ENTITY, ENT_CLIENT_LGBEAM); + sf = sf & 0x7F; + if(sound_allowed(MSG_BROADCAST, self.owner)) + sf |= 0x80; + WriteByte(MSG_ENTITY, sf); + if(sf & 1) + { + WriteByte(MSG_ENTITY, num_for_edict(self.owner)); + } + if(sf & 2) + { + WriteCoord(MSG_ENTITY, self.hook_start_x); + WriteCoord(MSG_ENTITY, self.hook_start_y); + WriteCoord(MSG_ENTITY, self.hook_start_z); + } + if(sf & 4) + { + WriteCoord(MSG_ENTITY, self.hook_end_x); + WriteCoord(MSG_ENTITY, self.hook_end_y); + WriteCoord(MSG_ENTITY, self.hook_end_z); + } + return TRUE; +} .entity lgbeam; .float prevlgfire; void lgbeam_think() @@ -226,17 +252,16 @@ void lgbeam_think() vecs = '0 0 0'; org = self.owner.origin + self.owner.view_ofs + v_forward * vecs_x + v_right * vecs_y + v_up * vecs_z; - // TODO turn into a csqc entity - WriteByte(MSG_BROADCAST, SVC_TEMPENTITY); - WriteByte(MSG_BROADCAST, TE_CSQC_BEAM); - WriteByte(MSG_BROADCAST, num_for_edict(self.owner)); - WriteByte(MSG_BROADCAST, sound_allowed(MSG_BROADCAST, self.owner) ? 1 : 2); - WriteCoord(MSG_BROADCAST, trace_endpos_x); - WriteCoord(MSG_BROADCAST, trace_endpos_y); - WriteCoord(MSG_BROADCAST, trace_endpos_z); - WriteCoord(MSG_BROADCAST, org_x); - WriteCoord(MSG_BROADCAST, org_y); - WriteCoord(MSG_BROADCAST, org_z); + if(org != self.hook_start) + { + self.SendFlags |= 2; + self.hook_start = org; + } + if(trace_endpos != self.hook_end) + { + self.SendFlags |= 4; + self.hook_end = trace_endpos; + } } // experimental lightning gun @@ -258,6 +283,7 @@ void W_Electro_Attack3 (void) beam.shot_spread = 0; beam.bot_dodge = TRUE; beam.bot_dodgerating = cvar("g_balance_electro_primary_damage"); + Net_LinkEntity(beam, FALSE, 0, lgbeam_send); oldself = self; self = beam; diff --git a/qcsrc/server/w_laser.qc b/qcsrc/server/w_laser.qc index 8633297a1..dd5e30ed8 100644 --- a/qcsrc/server/w_laser.qc +++ b/qcsrc/server/w_laser.qc @@ -101,6 +101,32 @@ void W_Laser_Attack (float issecondary) } } +.vector hook_start, hook_end; +float gauntletbeam_send(entity to, float sf) +{ + WriteByte(MSG_ENTITY, ENT_CLIENT_GAUNTLET); + sf = sf & 0x7F; + if(sound_allowed(MSG_BROADCAST, self.owner)) + sf |= 0x80; + WriteByte(MSG_ENTITY, sf); + if(sf & 1) + { + WriteByte(MSG_ENTITY, num_for_edict(self.owner)); + } + if(sf & 2) + { + WriteCoord(MSG_ENTITY, self.hook_start_x); + WriteCoord(MSG_ENTITY, self.hook_start_y); + WriteCoord(MSG_ENTITY, self.hook_start_z); + } + if(sf & 4) + { + WriteCoord(MSG_ENTITY, self.hook_end_x); + WriteCoord(MSG_ENTITY, self.hook_end_y); + WriteCoord(MSG_ENTITY, self.hook_end_z); + } + return TRUE; +} .entity gauntletbeam; .float prevgauntletfire; void gauntletbeam_think() @@ -153,17 +179,16 @@ void gauntletbeam_think() vecs = '0 0 0'; org = self.owner.origin + self.owner.view_ofs + v_forward * vecs_x + v_right * vecs_y + v_up * vecs_z; - // TODO turn into a csqc entity - WriteByte(MSG_BROADCAST, SVC_TEMPENTITY); - WriteByte(MSG_BROADCAST, TE_CSQC_BEAM); - WriteByte(MSG_BROADCAST, num_for_edict(self.owner)); - WriteByte(MSG_BROADCAST, 3); - WriteCoord(MSG_BROADCAST, trace_endpos_x); - WriteCoord(MSG_BROADCAST, trace_endpos_y); - WriteCoord(MSG_BROADCAST, trace_endpos_z); - WriteCoord(MSG_BROADCAST, org_x); - WriteCoord(MSG_BROADCAST, org_y); - WriteCoord(MSG_BROADCAST, org_z); + if(org != self.hook_start) + { + self.SendFlags |= 2; + self.hook_start = org; + } + if(trace_endpos != self.hook_end) + { + self.SendFlags |= 4; + self.hook_end = trace_endpos; + } } // experimental gauntlet @@ -186,6 +211,7 @@ void W_Laser_Attack2 (float issecondary) beam.bot_dodge = TRUE; beam.bot_dodgerating = cvar("g_balance_laser_primary_damage"); beam.cnt = issecondary; + Net_LinkEntity(beam, FALSE, 0, gauntletbeam_send); oldself = self; self = beam;