X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fserver%2Fw_crylink.qc;fp=qcsrc%2Fserver%2Fw_crylink.qc;h=f3d9a6cbf97881aeccc07f77e8a97107047b40ae;hp=bf65d03b8f071ebfe3cd4ada1cdb8c6a52aed827;hb=ff35e838d3cfa0162951d604d213e48aeb771e80;hpb=994e2e010d2ca496b8fb6bdafcd0b6824d97e20f diff --git a/qcsrc/server/w_crylink.qc b/qcsrc/server/w_crylink.qc index bf65d03b8f..f3d9a6cbf9 100644 --- a/qcsrc/server/w_crylink.qc +++ b/qcsrc/server/w_crylink.qc @@ -52,6 +52,8 @@ vector W_Crylink_LinkJoin(entity e, float joinspeed) float avg_dist, n; entity p; + w_crylink_linkjoin_time = 0; + avg_origin = e.origin; avg_velocity = e.velocity; n = 1; @@ -64,13 +66,16 @@ vector W_Crylink_LinkJoin(entity e, float joinspeed) avg_origin *= (1.0 / n); avg_velocity *= (1.0 / n); + if(n < 2) + return avg_origin; // nothing to do + // yes, mathematically we can do this in ONE step, but beware of 32bit floats... avg_dist = pow(vlen(e.origin - avg_origin), 2); for(p = e; (p = p.queuenext) != e; ) avg_dist += pow(vlen(e.origin - avg_origin), 2); avg_dist *= (1.0 / n); + avg_dist = sqrt(avg_dist); - w_crylink_linkjoin_time = 0; if(avg_dist == 0) return avg_origin; // no change needed @@ -115,6 +120,32 @@ vector W_Crylink_LinkJoin(entity e, float joinspeed) return targ_origin; } +void W_Crylink_LinkJoinEffect_Think() +{ + // is there at least 2 projectiles very close? + entity e, p; + float n; + e = self.owner.crylink_lastgroup; + n = 0; + if(e) + { + if(vlen(e.origin - self.origin) < vlen(e.velocity) * frametime) + ++n; + for(p = e; (p = p.queuenext) != e; ) + { + if(vlen(p.origin - self.origin) < vlen(p.velocity) * frametime) + ++n; + } + if(n >= 2) + { + // they seem to touch... + // TODO make a specific particle effect for this + pointparticles(particleeffectnum("crylink_linkjoin"), self.origin, '0 0 0', 1); + } + } + remove(self); +} + // NO bounce protection, as bounces are limited! void W_Crylink_Touch (void) { @@ -142,14 +173,21 @@ void W_Crylink_Touch (void) f = cvar("g_balance_crylink_primary_bouncedamagefactor"); if(a) f *= a; - if (RadiusDamage (self, self.realowner, cvar("g_balance_crylink_primary_damage") * f, cvar("g_balance_crylink_primary_edgedamage") * f, cvar("g_balance_crylink_primary_radius"), world, cvar("g_balance_crylink_primary_force") * f, self.projectiledeathtype, other) || finalhit) + if (RadiusDamage (self, self.realowner, cvar("g_balance_crylink_primary_damage") * f, cvar("g_balance_crylink_primary_edgedamage") * f, cvar("g_balance_crylink_primary_radius"), world, cvar("g_balance_crylink_primary_force") * f, self.projectiledeathtype, other)) { W_Crylink_LinkExplode(self.queuenext, self); remove (self); return; } + else if(finalhit) + { + // just unlink + W_Crylink_Dequeue(self); + remove(self); + return; + } self.cnt = self.cnt - 1; - // self.angles = vectoangles(self.velocity); // csqc + self.angles = vectoangles(self.velocity); self.owner = world; self.projectiledeathtype |= HITTYPE_BOUNCE; // commented out as it causes a little hitch... @@ -197,7 +235,7 @@ void W_Crylink_Touch2 (void) return; } self.cnt = self.cnt - 1; - // self.angles = vectoangles(self.velocity); // csqc + self.angles = vectoangles(self.velocity); self.owner = world; self.projectiledeathtype |= HITTYPE_BOUNCE; // commented out as it causes a little hitch... @@ -213,9 +251,10 @@ void W_Crylink_Fadethink (void) void W_Crylink_Attack (void) { - float counter, shots; - entity proj, prevproj, firstproj; - vector forward, right, up, s; + local float counter, shots; + local entity proj, prevproj, firstproj; + local vector s; + vector forward, right, up; if not(self.items & IT_UNLIMITED_WEAPON_AMMO) self.ammo_cells = self.ammo_cells - cvar("g_balance_crylink_primary_ammo"); @@ -231,7 +270,6 @@ void W_Crylink_Attack (void) while (counter < shots) { proj = spawn (); - proj.crylink_waitrelease = time; // keep track of when each projectile was spawned proj.realowner = proj.owner = self; proj.classname = "spike"; proj.bot_dodge = TRUE; @@ -281,12 +319,6 @@ void W_Crylink_Attack (void) self.fade_rate = 1 / cvar("g_balance_crylink_primary_middle_fadetime"); proj.nextthink = time + cvar("g_balance_crylink_primary_middle_lifetime") + cvar("g_balance_crylink_primary_middle_fadetime"); } - else if(counter <= 3) - { - proj.fade_time = time + cvar("g_balance_crylink_primary_star_lifetime"); - self.fade_rate = 1 / cvar("g_balance_crylink_primary_star_fadetime"); - proj.nextthink = time + cvar("g_balance_crylink_primary_star_lifetime") + cvar("g_balance_crylink_primary_star_fadetime"); - } else { proj.fade_time = time + cvar("g_balance_crylink_primary_other_lifetime"); @@ -294,9 +326,10 @@ void W_Crylink_Attack (void) proj.nextthink = time + cvar("g_balance_crylink_primary_other_lifetime") + cvar("g_balance_crylink_primary_other_fadetime"); } proj.cnt = cvar("g_balance_crylink_primary_bounces"); - //proj.scale = 1 + 1 * proj.cnt; - //proj.angles = vectoangles (proj.velocity); // csqc + + proj.angles = vectoangles (proj.velocity); + //proj.glow_size = 20; proj.flags = FL_PROJECTILE; @@ -326,7 +359,6 @@ void W_Crylink_Attack2 (void) while (counter < shots) { proj = spawn (); - proj.crylink_waitrelease = time; // keep track of when each projectile was spawned proj.realowner = proj.owner = self; proj.classname = "spike"; proj.bot_dodge = TRUE; @@ -373,7 +405,7 @@ void W_Crylink_Attack2 (void) proj.cnt = cvar("g_balance_crylink_secondary_bounces"); //proj.scale = 1 + 1 * proj.cnt; - // proj.angles = vectoangles (proj.velocity); // csqc + proj.angles = vectoangles (proj.velocity); //proj.glow_size = 20; @@ -406,22 +438,18 @@ float w_crylink(float req) { if (self.BUTTON_ATCK) { - if(self.crylink_lastgroup == world) - self.crylink_waitrelease = 0; - if (!self.crylink_waitrelease) if (weapon_prepareattack(0, cvar("g_balance_crylink_primary_refire"))) { W_Crylink_Attack(); weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_crylink_primary_animtime"), w_ready); if(cvar("g_balance_crylink_primary_joinspeed") != 0) - self.crylink_waitrelease = 1; // time + 0.01; + self.crylink_waitrelease = 1; } - - } else if(self.BUTTON_ATCK2 && cvar("g_balance_crylink_secondary")) { + if (!self.crylink_waitrelease) if (weapon_prepareattack(1, cvar("g_balance_crylink_secondary_refire"))) { W_Crylink_Attack2(); @@ -431,33 +459,38 @@ float w_crylink(float req) } } else - { - if (self.crylink_waitrelease) + { + if (self.crylink_waitrelease) { // fired and released now! if(self.crylink_lastgroup) - { - // Click and hold fire - if (time - self.crylink_lastgroup.crylink_waitrelease > 0.1) + { + vector pos; + if(self.crylink_waitrelease == 1) { - //dprint("HoldFire:", ftos(time - self.crylink_lastgroup.crylink_waitrelease), "\nTimer is ", ftos(self.crylink_lastgroup.crylink_waitrelease),"\n"); - W_Crylink_LinkJoin(self.crylink_lastgroup, cvar("g_balance_crylink_primary_joinspeed")); - // 'splode @ join, if timing is just right, you get the target with the join-explode splash first, then the individual projectile's damage. - - if(w_crylink_linkjoin_time > 0) - { - self.crylink_lastgroup.think = W_Crylink_Touch; - self.crylink_lastgroup.nextthink = w_crylink_linkjoin_time + time; - } + pos = W_Crylink_LinkJoin(self.crylink_lastgroup, cvar("g_balance_crylink_primary_joinspeed")); } - else // tap fire + else { - dprint("TapFire:", ftos(time - self.crylink_lastgroup.crylink_waitrelease), "\nTimer is ", ftos(self.crylink_lastgroup.crylink_waitrelease),"\n"); + pos = W_Crylink_LinkJoin(self.crylink_lastgroup, cvar("g_balance_crylink_secondary_joinspeed")); } + + entity linkjoineffect; + linkjoineffect = spawn(); + linkjoineffect.classname = "linkjoineffect"; + linkjoineffect.think = W_Crylink_LinkJoinEffect_Think; + linkjoineffect.nextthink = time + w_crylink_linkjoin_time; + linkjoineffect.owner = self; + setorigin(linkjoineffect, pos); } - self.crylink_waitrelease = 0; - } + if(!w_crylink(WR_CHECKAMMO1) && !w_crylink(WR_CHECKAMMO2)) + { + // ran out of ammo! + self.cnt = WEP_CRYLINK; + self.switchweapon = w_getbestweapon(self); + } + } } } else if (req == WR_PRECACHE) @@ -467,13 +500,24 @@ float w_crylink(float req) precache_model ("models/weapons/h_crylink.iqm"); precache_sound ("weapons/crylink_fire.wav"); precache_sound ("weapons/crylink_fire2.wav"); + precache_sound ("weapons/crylink_linkjoin.wav"); } else if (req == WR_SETUP) weapon_setup(WEP_CRYLINK); else if (req == WR_CHECKAMMO1) + { + // don't "run out of ammo" and switch weapons while waiting for release + if(self.crylink_lastgroup && self.crylink_waitrelease) + return TRUE; return self.ammo_cells >= cvar("g_balance_crylink_primary_ammo"); + } else if (req == WR_CHECKAMMO2) + { + // don't "run out of ammo" and switch weapons while waiting for release + if(self.crylink_lastgroup && self.crylink_waitrelease) + return TRUE; return self.ammo_cells >= cvar("g_balance_crylink_secondary_ammo"); + } return TRUE; }; #endif @@ -518,4 +562,4 @@ float w_crylink(float req) return TRUE; } #endif -#endif +#endif \ No newline at end of file