From: Samual Lenks Date: Mon, 10 Jun 2013 23:57:20 +0000 (-0400) Subject: More cleanup... X-Git-Tag: xonotic-v0.8.0~152^2~398 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=2fb9674d8313959ff2dcf50ac8a293569464db01;p=xonotic%2Fxonotic-data.pk3dir.git More cleanup... --- diff --git a/qcsrc/client/projectile.qc b/qcsrc/client/projectile.qc deleted file mode 100644 index fb4fdd5ef..000000000 --- a/qcsrc/client/projectile.qc +++ /dev/null @@ -1,470 +0,0 @@ -.vector iorigin1, iorigin2; -.float spawntime; -.vector trail_oldorigin; -.float trail_oldtime; -.float fade_time, fade_rate; - -void SUB_Stop() -{ - self.move_velocity = self.move_avelocity = '0 0 0'; - self.move_movetype = MOVETYPE_NONE; -} - -.float alphamod; -.float count; // set if clientside projectile -.float cnt; // sound index -.float gravity; -.float snd_looping; -.float silent; - -void Projectile_ResetTrail(vector to) -{ - self.trail_oldorigin = to; - self.trail_oldtime = time; -} - -void Projectile_DrawTrail(vector to) -{ - vector from; - float t0; - - from = self.trail_oldorigin; - t0 = self.trail_oldtime; - self.trail_oldorigin = to; - self.trail_oldtime = time; - - // force the effect even for stationary firemine - if(self.cnt == PROJECTILE_FIREMINE) - if(from == to) - from_z += 1; - - if (self.traileffect) - { - particles_alphamin = particles_alphamax = sqrt(self.alpha); - boxparticles(self.traileffect, self, from, to, self.velocity, self.velocity, sqrt(self.alpha), PARTICLES_USEALPHA); - } -} - -void Projectile_Draw() -{ - vector rot; - vector trailorigin; - float f; - float drawn; - float t; - float a; - - f = self.move_flags; - - if(self.count & 0x80) - { - //self.move_flags &~= FL_ONGROUND; - if(self.move_movetype == MOVETYPE_NONE || self.move_movetype == MOVETYPE_FLY) - Movetype_Physics_NoMatchServer(); - // the trivial movetypes do not have to match the - // server's ticrate as they are ticrate independent - // NOTE: this assumption is only true if MOVETYPE_FLY - // projectiles detonate on impact. If they continue - // moving, we might still be ticrate dependent. - else - Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy); - if(!(self.move_flags & FL_ONGROUND)) - if(self.velocity != '0 0 0') - self.move_angles = self.angles = vectoangles(self.velocity); - } - else - { - InterpolateOrigin_Do(); - } - - if(self.count & 0x80) - { - drawn = (time >= self.spawntime - 0.02); - t = max(time, self.spawntime); - } - else - { - drawn = (self.iflags & IFLAG_VALID); - t = time; - } - - if(!(f & FL_ONGROUND)) - { - rot = '0 0 0'; - switch(self.cnt) - { - /* - case PROJECTILE_GRENADE: - rot = '-2000 0 0'; // forward - break; - */ - case PROJECTILE_GRENADE_BOUNCING: - rot = '0 -1000 0'; // sideways - break; - case PROJECTILE_HOOKBOMB: - rot = '1000 0 0'; // forward - break; - default: - break; - } - self.angles = AnglesTransform_ToAngles(AnglesTransform_Multiply(AnglesTransform_FromAngles(self.angles), rot * (t - self.spawntime))); - } - - vector ang; - ang = self.angles; - ang_x = -ang_x; - makevectors(ang); - - a = 1 - (time - self.fade_time) * self.fade_rate; - self.alpha = bound(0, self.alphamod * a, 1); - if(self.alpha <= 0) - drawn = 0; - self.renderflags = 0; - - trailorigin = self.origin; - switch(self.cnt) - { - case PROJECTILE_GRENADE: - case PROJECTILE_GRENADE_BOUNCING: - trailorigin += v_right * 1 + v_forward * -10; - break; - default: - break; - } - if(drawn) - Projectile_DrawTrail(trailorigin); - else - Projectile_ResetTrail(trailorigin); - - self.drawmask = 0; - - if(!drawn) - return; - - switch(self.cnt) - { - case PROJECTILE_BULLET_GLOWING: - case PROJECTILE_BULLET_GLOWING_TRACER: - adddynamiclight(self.origin, 50 * a, '1 1 0'); - break; - default: - break; - } - - self.drawmask = MASK_NORMAL; -} - -void loopsound(entity e, float ch, string samp, float vol, float attn) -{ - if(self.silent) - return; - - sound(e, ch, samp, vol, attn); - e.snd_looping = ch; -} - -void Ent_RemoveProjectile() -{ - if(self.count & 0x80) - { - tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 0.05, MOVE_NORMAL, self); - Projectile_DrawTrail(trace_endpos); - } -} - -void Ent_Projectile() -{ - float f; - - // projectile properties: - // kind (interpolated, or clientside) - // - // modelindex - // origin - // scale - // if clientside: - // velocity - // gravity - // soundindex (hardcoded list) - // effects - // - // projectiles don't send angles, because they always follow the velocity - - f = ReadByte(); - self.count = (f & 0x80); - self.iflags = (self.iflags & IFLAG_INTERNALMASK) | IFLAG_AUTOANGLES | IFLAG_ANGLES | IFLAG_ORIGIN; - self.solid = SOLID_TRIGGER; - //self.effects = EF_NOMODELFLAGS; - - // this should make collisions with bmodels more exact, but it leads to - // projectiles no longer being able to lie on a bmodel - self.move_nomonsters = MOVE_WORLDONLY; - if(f & 0x40) - self.move_flags |= FL_ONGROUND; - else - self.move_flags &~= FL_ONGROUND; - - if(!self.move_time) - { - // for some unknown reason, we don't need to care for - // sv_gameplayfix_delayprojectiles here. - self.move_time = time; - self.spawntime = time; - } - else - self.move_time = max(self.move_time, time); - - if(!(self.count & 0x80)) - InterpolateOrigin_Undo(); - - if(f & 1) - { - self.origin_x = ReadCoord(); - self.origin_y = ReadCoord(); - self.origin_z = ReadCoord(); - setorigin(self, self.origin); - if(self.count & 0x80) - { - self.velocity_x = ReadCoord(); - self.velocity_y = ReadCoord(); - self.velocity_z = ReadCoord(); - if(f & 0x10) - self.gravity = ReadCoord(); - else - self.gravity = 0; // none - self.move_origin = self.origin; - self.move_velocity = self.velocity; - } - - if(time == self.spawntime || (self.count & 0x80) || (f & 0x08)) - { - self.trail_oldorigin = self.origin; - if(!(self.count & 0x80)) - InterpolateOrigin_Reset(); - } - - if(f & 0x20) - { - self.fade_time = time + ReadByte() * ticrate; - self.fade_rate = 1 / (ReadByte() * ticrate); - } - else - { - self.fade_time = 0; - self.fade_rate = 0; - } - } - - if(f & 2) - { - self.cnt = ReadByte(); - - self.silent = (self.cnt & 0x80); - self.cnt = (self.cnt & 0x7F); - - self.scale = 1; - self.traileffect = 0; - switch(self.cnt) - { - case PROJECTILE_ELECTRO: setmodel(self, "models/ebomb.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; - case PROJECTILE_ROCKET: setmodel(self, "models/rocket.md3");self.traileffect = particleeffectnum("TR_ROCKET"); self.scale = 2; break; - case PROJECTILE_BULLET: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_bullet"); break; - case PROJECTILE_BULLET_GLOWING: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_rifle_weak"); break; - case PROJECTILE_BULLET_GLOWING_TRACER: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_rifle"); break; - case PROJECTILE_CRYLINK: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break; - case PROJECTILE_CRYLINK_BOUNCING: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break; - case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; - case PROJECTILE_GRENADE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break; - case PROJECTILE_GRENADE_BOUNCING: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break; - case PROJECTILE_MINE: setmodel(self, "models/mine.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break; - case PROJECTILE_LASER: setmodel(self, "models/laser.mdl");self.traileffect = particleeffectnum(""); break; - case PROJECTILE_HLAC: setmodel(self, "models/hlac_bullet.md3");self.traileffect = particleeffectnum(""); break; - case PROJECTILE_PORTO_RED: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break; - case PROJECTILE_PORTO_BLUE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break; - case PROJECTILE_HOOKBOMB: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_KNIGHTSPIKE"); break; - case PROJECTILE_HAGAR: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break; - case PROJECTILE_HAGAR_BOUNCING: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break; - case PROJECTILE_FIREBALL: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("fireball"); break; // particle effect is good enough - case PROJECTILE_FIREMINE: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("firemine"); break; // particle effect is good enough - case PROJECTILE_TAG: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum("TR_ROCKET"); break; - case PROJECTILE_FLAC: setmodel(self, "models/hagarmissile.mdl"); self.scale = 0.4; self.traileffect = particleeffectnum("TR_SEEKER"); break; - case PROJECTILE_SEEKER: setmodel(self, "models/tagrocket.md3"); self.traileffect = particleeffectnum("TR_SEEKER"); break; - - case PROJECTILE_RAPTORBOMB: setmodel(self, "models/vehicles/clusterbomb.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break; - case PROJECTILE_RAPTORBOMBLET: setmodel(self, "models/vehicles/bomblet.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break; - case PROJECTILE_RAPTORCANNON: setmodel(self, "models/plasmatrail.mdl"); self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break; - - case PROJECTILE_SPIDERROCKET: setmodel(self, "models/vehicles/rocket02.md3"); self.traileffect = particleeffectnum("spiderbot_rocket_thrust"); break; - case PROJECTILE_WAKIROCKET: setmodel(self, "models/vehicles/rocket01.md3"); self.traileffect = particleeffectnum("wakizashi_rocket_thrust"); break; - case PROJECTILE_WAKICANNON: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum(""); break; - - case PROJECTILE_BUMBLE_GUN: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; - case PROJECTILE_BUMBLE_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; - - default: - error("Received invalid CSQC projectile, can't work with this!"); - break; - } - - self.mins = '0 0 0'; - self.maxs = '0 0 0'; - self.colormod = '0 0 0'; - self.move_touch = SUB_Stop; - self.move_movetype = MOVETYPE_TOSS; - self.alphamod = 1; - - switch(self.cnt) - { - case PROJECTILE_ELECTRO: - // only new engines support sound moving with object - loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTN_NORM); - self.mins = '0 0 -4'; - self.maxs = '0 0 -4'; - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - self.move_bounce_factor = g_balance_electro_secondary_bouncefactor; - self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop; - break; - case PROJECTILE_ROCKET: - loopsound(self, CH_SHOTS_SINGLE, "weapons/rocket_fly.wav", VOL_BASE, ATTN_NORM); - self.mins = '-3 -3 -3'; - self.maxs = '3 3 3'; - break; - case PROJECTILE_GRENADE: - self.mins = '-3 -3 -3'; - self.maxs = '3 3 3'; - break; - case PROJECTILE_GRENADE_BOUNCING: - self.mins = '-3 -3 -3'; - self.maxs = '3 3 3'; - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - self.move_bounce_factor = g_balance_grenadelauncher_bouncefactor; - self.move_bounce_stopspeed = g_balance_grenadelauncher_bouncestop; - break; - case PROJECTILE_MINE: - self.mins = '-4 -4 -4'; - self.maxs = '4 4 4'; - break; - case PROJECTILE_PORTO_RED: - self.colormod = '2 1 1'; - self.alphamod = 0.5; - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - break; - case PROJECTILE_PORTO_BLUE: - self.colormod = '1 1 2'; - self.alphamod = 0.5; - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - break; - case PROJECTILE_HAGAR_BOUNCING: - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - break; - case PROJECTILE_CRYLINK_BOUNCING: - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - break; - case PROJECTILE_FIREBALL: - loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly2.wav", VOL_BASE, ATTN_NORM); - self.mins = '-16 -16 -16'; - self.maxs = '16 16 16'; - break; - case PROJECTILE_FIREMINE: - loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly.wav", VOL_BASE, ATTN_NORM); - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - self.mins = '-4 -4 -4'; - self.maxs = '4 4 4'; - break; - case PROJECTILE_TAG: - self.mins = '-2 -2 -2'; - self.maxs = '2 2 2'; - break; - case PROJECTILE_FLAC: - self.mins = '-2 -2 -2'; - self.maxs = '2 2 2'; - break; - case PROJECTILE_SEEKER: - loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM); - self.mins = '-4 -4 -4'; - self.maxs = '4 4 4'; - break; - case PROJECTILE_RAPTORBOMB: - self.mins = '-3 -3 -3'; - self.maxs = '3 3 3'; - break; - case PROJECTILE_RAPTORBOMBLET: - break; - case PROJECTILE_RAPTORCANNON: - break; - case PROJECTILE_SPIDERROCKET: - loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM); - break; - case PROJECTILE_WAKIROCKET: - loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM); - break; - /* - case PROJECTILE_WAKICANNON: - break; - case PROJECTILE_BUMBLE_GUN: - // only new engines support sound moving with object - loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTN_NORM); - self.mins = '0 0 -4'; - self.maxs = '0 0 -4'; - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - self.move_bounce_factor = g_balance_electro_secondary_bouncefactor; - self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop; - break; - */ - default: - break; - } - setsize(self, self.mins, self.maxs); - } - - if(self.gravity) - { - if(self.move_movetype == MOVETYPE_FLY) - self.move_movetype = MOVETYPE_TOSS; - if(self.move_movetype == MOVETYPE_BOUNCEMISSILE) - self.move_movetype = MOVETYPE_BOUNCE; - } - else - { - if(self.move_movetype == MOVETYPE_TOSS) - self.move_movetype = MOVETYPE_FLY; - if(self.move_movetype == MOVETYPE_BOUNCE) - self.move_movetype = MOVETYPE_BOUNCEMISSILE; - } - - if(!(self.count & 0x80)) - InterpolateOrigin_Note(); - - self.draw = Projectile_Draw; - self.entremove = Ent_RemoveProjectile; -} - -void Projectile_Precache() -{ - precache_model("models/ebomb.mdl"); - precache_model("models/elaser.mdl"); - precache_model("models/grenademodel.md3"); - precache_model("models/mine.md3"); - precache_model("models/hagarmissile.mdl"); - precache_model("models/hlac_bullet.md3"); - precache_model("models/laser.mdl"); - precache_model("models/plasmatrail.mdl"); - precache_model("models/rocket.md3"); - precache_model("models/tagrocket.md3"); - precache_model("models/tracer.mdl"); - - precache_sound("weapons/electro_fly.wav"); - precache_sound("weapons/rocket_fly.wav"); - precache_sound("weapons/fireball_fly.wav"); - precache_sound("weapons/fireball_fly2.wav"); - precache_sound("weapons/tag_rocket_fly.wav"); - -} diff --git a/qcsrc/client/projectile.qh b/qcsrc/client/projectile.qh deleted file mode 100644 index 70c8ba0df..000000000 --- a/qcsrc/client/projectile.qh +++ /dev/null @@ -1,3 +0,0 @@ -.float traileffect; -void Projectile_ResetTrail(vector to); -void Projectile_DrawTrail(vector to); diff --git a/qcsrc/client/weapons/projectile.qc b/qcsrc/client/weapons/projectile.qc new file mode 100644 index 000000000..fb4fdd5ef --- /dev/null +++ b/qcsrc/client/weapons/projectile.qc @@ -0,0 +1,470 @@ +.vector iorigin1, iorigin2; +.float spawntime; +.vector trail_oldorigin; +.float trail_oldtime; +.float fade_time, fade_rate; + +void SUB_Stop() +{ + self.move_velocity = self.move_avelocity = '0 0 0'; + self.move_movetype = MOVETYPE_NONE; +} + +.float alphamod; +.float count; // set if clientside projectile +.float cnt; // sound index +.float gravity; +.float snd_looping; +.float silent; + +void Projectile_ResetTrail(vector to) +{ + self.trail_oldorigin = to; + self.trail_oldtime = time; +} + +void Projectile_DrawTrail(vector to) +{ + vector from; + float t0; + + from = self.trail_oldorigin; + t0 = self.trail_oldtime; + self.trail_oldorigin = to; + self.trail_oldtime = time; + + // force the effect even for stationary firemine + if(self.cnt == PROJECTILE_FIREMINE) + if(from == to) + from_z += 1; + + if (self.traileffect) + { + particles_alphamin = particles_alphamax = sqrt(self.alpha); + boxparticles(self.traileffect, self, from, to, self.velocity, self.velocity, sqrt(self.alpha), PARTICLES_USEALPHA); + } +} + +void Projectile_Draw() +{ + vector rot; + vector trailorigin; + float f; + float drawn; + float t; + float a; + + f = self.move_flags; + + if(self.count & 0x80) + { + //self.move_flags &~= FL_ONGROUND; + if(self.move_movetype == MOVETYPE_NONE || self.move_movetype == MOVETYPE_FLY) + Movetype_Physics_NoMatchServer(); + // the trivial movetypes do not have to match the + // server's ticrate as they are ticrate independent + // NOTE: this assumption is only true if MOVETYPE_FLY + // projectiles detonate on impact. If they continue + // moving, we might still be ticrate dependent. + else + Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy); + if(!(self.move_flags & FL_ONGROUND)) + if(self.velocity != '0 0 0') + self.move_angles = self.angles = vectoangles(self.velocity); + } + else + { + InterpolateOrigin_Do(); + } + + if(self.count & 0x80) + { + drawn = (time >= self.spawntime - 0.02); + t = max(time, self.spawntime); + } + else + { + drawn = (self.iflags & IFLAG_VALID); + t = time; + } + + if(!(f & FL_ONGROUND)) + { + rot = '0 0 0'; + switch(self.cnt) + { + /* + case PROJECTILE_GRENADE: + rot = '-2000 0 0'; // forward + break; + */ + case PROJECTILE_GRENADE_BOUNCING: + rot = '0 -1000 0'; // sideways + break; + case PROJECTILE_HOOKBOMB: + rot = '1000 0 0'; // forward + break; + default: + break; + } + self.angles = AnglesTransform_ToAngles(AnglesTransform_Multiply(AnglesTransform_FromAngles(self.angles), rot * (t - self.spawntime))); + } + + vector ang; + ang = self.angles; + ang_x = -ang_x; + makevectors(ang); + + a = 1 - (time - self.fade_time) * self.fade_rate; + self.alpha = bound(0, self.alphamod * a, 1); + if(self.alpha <= 0) + drawn = 0; + self.renderflags = 0; + + trailorigin = self.origin; + switch(self.cnt) + { + case PROJECTILE_GRENADE: + case PROJECTILE_GRENADE_BOUNCING: + trailorigin += v_right * 1 + v_forward * -10; + break; + default: + break; + } + if(drawn) + Projectile_DrawTrail(trailorigin); + else + Projectile_ResetTrail(trailorigin); + + self.drawmask = 0; + + if(!drawn) + return; + + switch(self.cnt) + { + case PROJECTILE_BULLET_GLOWING: + case PROJECTILE_BULLET_GLOWING_TRACER: + adddynamiclight(self.origin, 50 * a, '1 1 0'); + break; + default: + break; + } + + self.drawmask = MASK_NORMAL; +} + +void loopsound(entity e, float ch, string samp, float vol, float attn) +{ + if(self.silent) + return; + + sound(e, ch, samp, vol, attn); + e.snd_looping = ch; +} + +void Ent_RemoveProjectile() +{ + if(self.count & 0x80) + { + tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 0.05, MOVE_NORMAL, self); + Projectile_DrawTrail(trace_endpos); + } +} + +void Ent_Projectile() +{ + float f; + + // projectile properties: + // kind (interpolated, or clientside) + // + // modelindex + // origin + // scale + // if clientside: + // velocity + // gravity + // soundindex (hardcoded list) + // effects + // + // projectiles don't send angles, because they always follow the velocity + + f = ReadByte(); + self.count = (f & 0x80); + self.iflags = (self.iflags & IFLAG_INTERNALMASK) | IFLAG_AUTOANGLES | IFLAG_ANGLES | IFLAG_ORIGIN; + self.solid = SOLID_TRIGGER; + //self.effects = EF_NOMODELFLAGS; + + // this should make collisions with bmodels more exact, but it leads to + // projectiles no longer being able to lie on a bmodel + self.move_nomonsters = MOVE_WORLDONLY; + if(f & 0x40) + self.move_flags |= FL_ONGROUND; + else + self.move_flags &~= FL_ONGROUND; + + if(!self.move_time) + { + // for some unknown reason, we don't need to care for + // sv_gameplayfix_delayprojectiles here. + self.move_time = time; + self.spawntime = time; + } + else + self.move_time = max(self.move_time, time); + + if(!(self.count & 0x80)) + InterpolateOrigin_Undo(); + + if(f & 1) + { + self.origin_x = ReadCoord(); + self.origin_y = ReadCoord(); + self.origin_z = ReadCoord(); + setorigin(self, self.origin); + if(self.count & 0x80) + { + self.velocity_x = ReadCoord(); + self.velocity_y = ReadCoord(); + self.velocity_z = ReadCoord(); + if(f & 0x10) + self.gravity = ReadCoord(); + else + self.gravity = 0; // none + self.move_origin = self.origin; + self.move_velocity = self.velocity; + } + + if(time == self.spawntime || (self.count & 0x80) || (f & 0x08)) + { + self.trail_oldorigin = self.origin; + if(!(self.count & 0x80)) + InterpolateOrigin_Reset(); + } + + if(f & 0x20) + { + self.fade_time = time + ReadByte() * ticrate; + self.fade_rate = 1 / (ReadByte() * ticrate); + } + else + { + self.fade_time = 0; + self.fade_rate = 0; + } + } + + if(f & 2) + { + self.cnt = ReadByte(); + + self.silent = (self.cnt & 0x80); + self.cnt = (self.cnt & 0x7F); + + self.scale = 1; + self.traileffect = 0; + switch(self.cnt) + { + case PROJECTILE_ELECTRO: setmodel(self, "models/ebomb.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; + case PROJECTILE_ROCKET: setmodel(self, "models/rocket.md3");self.traileffect = particleeffectnum("TR_ROCKET"); self.scale = 2; break; + case PROJECTILE_BULLET: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_bullet"); break; + case PROJECTILE_BULLET_GLOWING: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_rifle_weak"); break; + case PROJECTILE_BULLET_GLOWING_TRACER: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_rifle"); break; + case PROJECTILE_CRYLINK: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break; + case PROJECTILE_CRYLINK_BOUNCING: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break; + case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; + case PROJECTILE_GRENADE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break; + case PROJECTILE_GRENADE_BOUNCING: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break; + case PROJECTILE_MINE: setmodel(self, "models/mine.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break; + case PROJECTILE_LASER: setmodel(self, "models/laser.mdl");self.traileffect = particleeffectnum(""); break; + case PROJECTILE_HLAC: setmodel(self, "models/hlac_bullet.md3");self.traileffect = particleeffectnum(""); break; + case PROJECTILE_PORTO_RED: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break; + case PROJECTILE_PORTO_BLUE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break; + case PROJECTILE_HOOKBOMB: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_KNIGHTSPIKE"); break; + case PROJECTILE_HAGAR: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break; + case PROJECTILE_HAGAR_BOUNCING: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break; + case PROJECTILE_FIREBALL: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("fireball"); break; // particle effect is good enough + case PROJECTILE_FIREMINE: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("firemine"); break; // particle effect is good enough + case PROJECTILE_TAG: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum("TR_ROCKET"); break; + case PROJECTILE_FLAC: setmodel(self, "models/hagarmissile.mdl"); self.scale = 0.4; self.traileffect = particleeffectnum("TR_SEEKER"); break; + case PROJECTILE_SEEKER: setmodel(self, "models/tagrocket.md3"); self.traileffect = particleeffectnum("TR_SEEKER"); break; + + case PROJECTILE_RAPTORBOMB: setmodel(self, "models/vehicles/clusterbomb.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break; + case PROJECTILE_RAPTORBOMBLET: setmodel(self, "models/vehicles/bomblet.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break; + case PROJECTILE_RAPTORCANNON: setmodel(self, "models/plasmatrail.mdl"); self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break; + + case PROJECTILE_SPIDERROCKET: setmodel(self, "models/vehicles/rocket02.md3"); self.traileffect = particleeffectnum("spiderbot_rocket_thrust"); break; + case PROJECTILE_WAKIROCKET: setmodel(self, "models/vehicles/rocket01.md3"); self.traileffect = particleeffectnum("wakizashi_rocket_thrust"); break; + case PROJECTILE_WAKICANNON: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum(""); break; + + case PROJECTILE_BUMBLE_GUN: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; + case PROJECTILE_BUMBLE_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; + + default: + error("Received invalid CSQC projectile, can't work with this!"); + break; + } + + self.mins = '0 0 0'; + self.maxs = '0 0 0'; + self.colormod = '0 0 0'; + self.move_touch = SUB_Stop; + self.move_movetype = MOVETYPE_TOSS; + self.alphamod = 1; + + switch(self.cnt) + { + case PROJECTILE_ELECTRO: + // only new engines support sound moving with object + loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTN_NORM); + self.mins = '0 0 -4'; + self.maxs = '0 0 -4'; + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + self.move_bounce_factor = g_balance_electro_secondary_bouncefactor; + self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop; + break; + case PROJECTILE_ROCKET: + loopsound(self, CH_SHOTS_SINGLE, "weapons/rocket_fly.wav", VOL_BASE, ATTN_NORM); + self.mins = '-3 -3 -3'; + self.maxs = '3 3 3'; + break; + case PROJECTILE_GRENADE: + self.mins = '-3 -3 -3'; + self.maxs = '3 3 3'; + break; + case PROJECTILE_GRENADE_BOUNCING: + self.mins = '-3 -3 -3'; + self.maxs = '3 3 3'; + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + self.move_bounce_factor = g_balance_grenadelauncher_bouncefactor; + self.move_bounce_stopspeed = g_balance_grenadelauncher_bouncestop; + break; + case PROJECTILE_MINE: + self.mins = '-4 -4 -4'; + self.maxs = '4 4 4'; + break; + case PROJECTILE_PORTO_RED: + self.colormod = '2 1 1'; + self.alphamod = 0.5; + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + break; + case PROJECTILE_PORTO_BLUE: + self.colormod = '1 1 2'; + self.alphamod = 0.5; + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + break; + case PROJECTILE_HAGAR_BOUNCING: + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + break; + case PROJECTILE_CRYLINK_BOUNCING: + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + break; + case PROJECTILE_FIREBALL: + loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly2.wav", VOL_BASE, ATTN_NORM); + self.mins = '-16 -16 -16'; + self.maxs = '16 16 16'; + break; + case PROJECTILE_FIREMINE: + loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly.wav", VOL_BASE, ATTN_NORM); + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + self.mins = '-4 -4 -4'; + self.maxs = '4 4 4'; + break; + case PROJECTILE_TAG: + self.mins = '-2 -2 -2'; + self.maxs = '2 2 2'; + break; + case PROJECTILE_FLAC: + self.mins = '-2 -2 -2'; + self.maxs = '2 2 2'; + break; + case PROJECTILE_SEEKER: + loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM); + self.mins = '-4 -4 -4'; + self.maxs = '4 4 4'; + break; + case PROJECTILE_RAPTORBOMB: + self.mins = '-3 -3 -3'; + self.maxs = '3 3 3'; + break; + case PROJECTILE_RAPTORBOMBLET: + break; + case PROJECTILE_RAPTORCANNON: + break; + case PROJECTILE_SPIDERROCKET: + loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM); + break; + case PROJECTILE_WAKIROCKET: + loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM); + break; + /* + case PROJECTILE_WAKICANNON: + break; + case PROJECTILE_BUMBLE_GUN: + // only new engines support sound moving with object + loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTN_NORM); + self.mins = '0 0 -4'; + self.maxs = '0 0 -4'; + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + self.move_bounce_factor = g_balance_electro_secondary_bouncefactor; + self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop; + break; + */ + default: + break; + } + setsize(self, self.mins, self.maxs); + } + + if(self.gravity) + { + if(self.move_movetype == MOVETYPE_FLY) + self.move_movetype = MOVETYPE_TOSS; + if(self.move_movetype == MOVETYPE_BOUNCEMISSILE) + self.move_movetype = MOVETYPE_BOUNCE; + } + else + { + if(self.move_movetype == MOVETYPE_TOSS) + self.move_movetype = MOVETYPE_FLY; + if(self.move_movetype == MOVETYPE_BOUNCE) + self.move_movetype = MOVETYPE_BOUNCEMISSILE; + } + + if(!(self.count & 0x80)) + InterpolateOrigin_Note(); + + self.draw = Projectile_Draw; + self.entremove = Ent_RemoveProjectile; +} + +void Projectile_Precache() +{ + precache_model("models/ebomb.mdl"); + precache_model("models/elaser.mdl"); + precache_model("models/grenademodel.md3"); + precache_model("models/mine.md3"); + precache_model("models/hagarmissile.mdl"); + precache_model("models/hlac_bullet.md3"); + precache_model("models/laser.mdl"); + precache_model("models/plasmatrail.mdl"); + precache_model("models/rocket.md3"); + precache_model("models/tagrocket.md3"); + precache_model("models/tracer.mdl"); + + precache_sound("weapons/electro_fly.wav"); + precache_sound("weapons/rocket_fly.wav"); + precache_sound("weapons/fireball_fly.wav"); + precache_sound("weapons/fireball_fly2.wav"); + precache_sound("weapons/tag_rocket_fly.wav"); + +} diff --git a/qcsrc/client/weapons/projectile.qh b/qcsrc/client/weapons/projectile.qh new file mode 100644 index 000000000..70c8ba0df --- /dev/null +++ b/qcsrc/client/weapons/projectile.qh @@ -0,0 +1,3 @@ +.float traileffect; +void Projectile_ResetTrail(vector to); +void Projectile_DrawTrail(vector to); diff --git a/qcsrc/common/weapons/calculations.qc b/qcsrc/common/weapons/calculations.qc index 0327943f9..183a5e5ed 100644 --- a/qcsrc/common/weapons/calculations.qc +++ b/qcsrc/common/weapons/calculations.qc @@ -1,6 +1,7 @@ // ============================= // Explosion Force Calculation // ============================= + float explosion_calcpush_getmultiplier(vector explosion_v, vector target_v) { float a; diff --git a/qcsrc/server/accuracy.qc b/qcsrc/server/accuracy.qc deleted file mode 100644 index 3c737f6e6..000000000 --- a/qcsrc/server/accuracy.qc +++ /dev/null @@ -1,125 +0,0 @@ -.float accuracy_hit[WEP_MAXCOUNT]; -.float accuracy_fired[WEP_MAXCOUNT]; -.float accuracy_cnt_hit[WEP_MAXCOUNT]; -.float accuracy_cnt_fired[WEP_MAXCOUNT]; - -float accuracy_byte(float n, float d) -{ - //print(sprintf("accuracy: %d / %d\n", n, d)); - if(n <= 0) - return 0; - if(n > d) - return 255; - return 1 + rint(n * 100.0 / d); -} - -float accuracy_send(entity to, float sf) -{ - float w, f; - entity a; - WriteByte(MSG_ENTITY, ENT_CLIENT_ACCURACY); - - a = self.owner; - if(IS_SPEC(a)) - a = a.enemy; - a = a.accuracy; - - if(to != a.owner) - if not(self.owner.cvar_cl_accuracy_data_share && autocvar_sv_accuracy_data_share) - sf = 0; - // note: zero sendflags can never be sent... so we can use that to say that we send no accuracy! - WriteInt24_t(MSG_ENTITY, sf); - if(sf == 0) - return TRUE; - // note: we know that client and server agree about SendFlags... - for(w = 0, f = 1; w <= WEP_LAST - WEP_FIRST; ++w) - { - if(sf & f) - WriteByte(MSG_ENTITY, accuracy_byte(self.(accuracy_hit[w]), self.(accuracy_fired[w]))); - if(f == 0x800000) - f = 1; - else - f *= 2; - } - return TRUE; -} - -// init/free -void accuracy_init(entity e) -{ - e.accuracy = spawn(); - e.accuracy.owner = e; - e.accuracy.classname = "accuracy"; - e.accuracy.drawonlytoclient = e; - Net_LinkEntity(e.accuracy, FALSE, 0, accuracy_send); -} - -void accuracy_free(entity e) -{ - remove(e.accuracy); -} - -// force a resend of a player's accuracy stats -void accuracy_resend(entity e) -{ - e.accuracy.SendFlags = 0xFFFFFF; -} - -// update accuracy stats -.float hit_time; -.float fired_time; - -void accuracy_add(entity e, float w, float fired, float hit) -{ - entity a; - float b; - if(IS_INDEPENDENT_PLAYER(e)) - return; - a = e.accuracy; - if(!a || !(hit || fired)) - return; - w -= WEP_FIRST; - b = accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w])); - if(hit) - a.(accuracy_hit[w]) += hit; - if(fired) - a.(accuracy_fired[w]) += fired; - - if(hit && a.hit_time != time) // only run this once per frame - { - a.(accuracy_cnt_hit[w]) += 1; - a.hit_time = time; - } - - if(fired && a.fired_time != time) // only run this once per frame - { - a.(accuracy_cnt_fired[w]) += 1; - a.fired_time = time; - } - - if(b == accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w]))) - return; - w = pow(2, mod(w, 24)); - a.SendFlags |= w; - FOR_EACH_CLIENT(a) - if(IS_SPEC(a)) - if(a.enemy == e) - a.SendFlags |= w; -} - -float accuracy_isgooddamage(entity attacker, entity targ) -{ - if(!inWarmupStage) - if(IS_CLIENT(targ)) - if(targ.deadflag == DEAD_NO) - if(IsDifferentTeam(attacker, targ)) - return TRUE; - return FALSE; -} - -float accuracy_canbegooddamage(entity attacker) -{ - if(!inWarmupStage) - return TRUE; - return FALSE; -} diff --git a/qcsrc/server/accuracy.qh b/qcsrc/server/accuracy.qh deleted file mode 100644 index 90dbb663d..000000000 --- a/qcsrc/server/accuracy.qh +++ /dev/null @@ -1,15 +0,0 @@ -.float cvar_cl_accuracy_data_share; - -// init/free -void accuracy_init(entity e); -void accuracy_free(entity e); - -// force a resend of a player's accuracy stats -void accuracy_resend(entity e); - -// update accuracy stats -void accuracy_add(entity e, float w, float fired, float hit); - -// helper -float accuracy_isgooddamage(entity attacker, entity targ); -float accuracy_canbegooddamage(entity attacker); diff --git a/qcsrc/server/weapons/accuracy.qc b/qcsrc/server/weapons/accuracy.qc new file mode 100644 index 000000000..3c737f6e6 --- /dev/null +++ b/qcsrc/server/weapons/accuracy.qc @@ -0,0 +1,125 @@ +.float accuracy_hit[WEP_MAXCOUNT]; +.float accuracy_fired[WEP_MAXCOUNT]; +.float accuracy_cnt_hit[WEP_MAXCOUNT]; +.float accuracy_cnt_fired[WEP_MAXCOUNT]; + +float accuracy_byte(float n, float d) +{ + //print(sprintf("accuracy: %d / %d\n", n, d)); + if(n <= 0) + return 0; + if(n > d) + return 255; + return 1 + rint(n * 100.0 / d); +} + +float accuracy_send(entity to, float sf) +{ + float w, f; + entity a; + WriteByte(MSG_ENTITY, ENT_CLIENT_ACCURACY); + + a = self.owner; + if(IS_SPEC(a)) + a = a.enemy; + a = a.accuracy; + + if(to != a.owner) + if not(self.owner.cvar_cl_accuracy_data_share && autocvar_sv_accuracy_data_share) + sf = 0; + // note: zero sendflags can never be sent... so we can use that to say that we send no accuracy! + WriteInt24_t(MSG_ENTITY, sf); + if(sf == 0) + return TRUE; + // note: we know that client and server agree about SendFlags... + for(w = 0, f = 1; w <= WEP_LAST - WEP_FIRST; ++w) + { + if(sf & f) + WriteByte(MSG_ENTITY, accuracy_byte(self.(accuracy_hit[w]), self.(accuracy_fired[w]))); + if(f == 0x800000) + f = 1; + else + f *= 2; + } + return TRUE; +} + +// init/free +void accuracy_init(entity e) +{ + e.accuracy = spawn(); + e.accuracy.owner = e; + e.accuracy.classname = "accuracy"; + e.accuracy.drawonlytoclient = e; + Net_LinkEntity(e.accuracy, FALSE, 0, accuracy_send); +} + +void accuracy_free(entity e) +{ + remove(e.accuracy); +} + +// force a resend of a player's accuracy stats +void accuracy_resend(entity e) +{ + e.accuracy.SendFlags = 0xFFFFFF; +} + +// update accuracy stats +.float hit_time; +.float fired_time; + +void accuracy_add(entity e, float w, float fired, float hit) +{ + entity a; + float b; + if(IS_INDEPENDENT_PLAYER(e)) + return; + a = e.accuracy; + if(!a || !(hit || fired)) + return; + w -= WEP_FIRST; + b = accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w])); + if(hit) + a.(accuracy_hit[w]) += hit; + if(fired) + a.(accuracy_fired[w]) += fired; + + if(hit && a.hit_time != time) // only run this once per frame + { + a.(accuracy_cnt_hit[w]) += 1; + a.hit_time = time; + } + + if(fired && a.fired_time != time) // only run this once per frame + { + a.(accuracy_cnt_fired[w]) += 1; + a.fired_time = time; + } + + if(b == accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w]))) + return; + w = pow(2, mod(w, 24)); + a.SendFlags |= w; + FOR_EACH_CLIENT(a) + if(IS_SPEC(a)) + if(a.enemy == e) + a.SendFlags |= w; +} + +float accuracy_isgooddamage(entity attacker, entity targ) +{ + if(!inWarmupStage) + if(IS_CLIENT(targ)) + if(targ.deadflag == DEAD_NO) + if(IsDifferentTeam(attacker, targ)) + return TRUE; + return FALSE; +} + +float accuracy_canbegooddamage(entity attacker) +{ + if(!inWarmupStage) + return TRUE; + return FALSE; +} diff --git a/qcsrc/server/weapons/accuracy.qh b/qcsrc/server/weapons/accuracy.qh new file mode 100644 index 000000000..90dbb663d --- /dev/null +++ b/qcsrc/server/weapons/accuracy.qh @@ -0,0 +1,15 @@ +.float cvar_cl_accuracy_data_share; + +// init/free +void accuracy_init(entity e); +void accuracy_free(entity e); + +// force a resend of a player's accuracy stats +void accuracy_resend(entity e); + +// update accuracy stats +void accuracy_add(entity e, float w, float fired, float hit); + +// helper +float accuracy_isgooddamage(entity attacker, entity targ); +float accuracy_canbegooddamage(entity attacker);