X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fw_crylink.qc;h=1bb9ad6004e7853f71acd590f9837049df3bfe7e;hb=aba5ddce2b36b71cbd7d6f0bdf39b9cae573e6b0;hp=6a77e98a882ccc2c1fb329db1b2b25b03e87fd13;hpb=f2a79cba0897fb6f6cb7ebeecb596b5547af3ddd;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/w_crylink.qc b/qcsrc/server/w_crylink.qc index 6a77e98a8..1bb9ad600 100644 --- a/qcsrc/server/w_crylink.qc +++ b/qcsrc/server/w_crylink.qc @@ -49,10 +49,20 @@ void W_Crylink_Dequeue(entity e) W_Crylink_Dequeue_Raw(e.realowner, e.queueprev, e, e.queuenext); } +void W_Crylink_Reset(void) +{ + W_Crylink_Dequeue(self); + remove(self); +} + // force projectile to explode void W_Crylink_LinkExplode (entity e, entity e2) { float a; + + if(e == e2) + return; + a = bound(0, 1 - (time - e.fade_time) * e.fade_rate, 1); if(e == e.realowner.crylink_lastgroup) @@ -63,8 +73,7 @@ void W_Crylink_LinkExplode (entity e, entity e2) else RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_primary_damage * a, autocvar_g_balance_crylink_primary_edgedamage * a, autocvar_g_balance_crylink_primary_radius, world, autocvar_g_balance_crylink_primary_force * a, e.projectiledeathtype, other); - if(e.queuenext != e2) - W_Crylink_LinkExplode(e.queuenext, e2); + W_Crylink_LinkExplode(e.queuenext, e2); e.classname = "spike_oktoremove"; remove (e); @@ -124,6 +133,7 @@ vector W_Crylink_LinkJoin(entity e, float jspeed, float jtime) p.velocity = WarpZone_RefSys_TransformVelocity(e, p, avg_velocity); UpdateCSQCProjectile(p); } + targ_origin = avg_origin + 1000000000 * normalize(avg_velocity); // HUUUUUUGE } else { @@ -215,6 +225,28 @@ void W_Crylink_LinkJoinEffect_Think() remove(self); } +float W_Crylink_Touch_WouldHitFriendly(entity projectile, float rad) +{ + entity head = WarpZone_FindRadius((projectile.origin + (projectile.mins + projectile.maxs) * 0.5), rad + MAX_DAMAGEEXTRARADIUS, FALSE); + float hit_friendly = 0; + float hit_enemy = 0; + + while(head) + { + if((head.takedamage != DAMAGE_NO) && (head.deadflag == DEAD_NO)) + { + if(IsDifferentTeam(head, projectile.realowner)) + ++hit_enemy; + else + ++hit_friendly; + } + + head = head.chain; + } + + return (hit_enemy ? FALSE : hit_friendly); +} + // NO bounce protection, as bounces are limited! void W_Crylink_Touch (void) { @@ -232,11 +264,15 @@ void W_Crylink_Touch (void) f = autocvar_g_balance_crylink_primary_bouncedamagefactor; if(a) f *= a; - if (RadiusDamage (self, self.realowner, autocvar_g_balance_crylink_primary_damage * f, autocvar_g_balance_crylink_primary_edgedamage * f, autocvar_g_balance_crylink_primary_radius, world, autocvar_g_balance_crylink_primary_force * f, self.projectiledeathtype, other) && autocvar_g_balance_crylink_primary_linkexplode) + + float totaldamage = RadiusDamage(self, self.realowner, autocvar_g_balance_crylink_primary_damage * f, autocvar_g_balance_crylink_primary_edgedamage * f, autocvar_g_balance_crylink_primary_radius, world, autocvar_g_balance_crylink_primary_force * f, self.projectiledeathtype, other); + + if(totaldamage && ((autocvar_g_balance_crylink_primary_linkexplode == 2) || ((autocvar_g_balance_crylink_primary_linkexplode == 1) && !W_Crylink_Touch_WouldHitFriendly(self, autocvar_g_balance_crylink_primary_radius)))) { if(self == self.realowner.crylink_lastgroup) self.realowner.crylink_lastgroup = world; W_Crylink_LinkExplode(self.queuenext, self); + self.classname = "spike_oktoremove"; remove (self); return; } @@ -272,11 +308,15 @@ void W_Crylink_Touch2 (void) f = autocvar_g_balance_crylink_secondary_bouncedamagefactor; if(a) f *= a; - if (RadiusDamage (self, self.realowner, autocvar_g_balance_crylink_secondary_damage * f, autocvar_g_balance_crylink_secondary_edgedamage * f, autocvar_g_balance_crylink_secondary_radius, world, autocvar_g_balance_crylink_secondary_force * f, self.projectiledeathtype, other) && autocvar_g_balance_crylink_secondary_linkexplode) + + float totaldamage = RadiusDamage(self, self.realowner, autocvar_g_balance_crylink_secondary_damage * f, autocvar_g_balance_crylink_secondary_edgedamage * f, autocvar_g_balance_crylink_secondary_radius, world, autocvar_g_balance_crylink_secondary_force * f, self.projectiledeathtype, other); + + if(totaldamage && ((autocvar_g_balance_crylink_secondary_linkexplode == 2) || ((autocvar_g_balance_crylink_secondary_linkexplode == 1) && !W_Crylink_Touch_WouldHitFriendly(self, autocvar_g_balance_crylink_secondary_radius)))) { if(self == self.realowner.crylink_lastgroup) self.realowner.crylink_lastgroup = world; W_Crylink_LinkExplode(self.queuenext, self); + self.classname = "spike_oktoremove"; remove (self); return; } @@ -304,9 +344,9 @@ void W_Crylink_Fadethink (void) void W_Crylink_Attack (void) { - local float counter, shots; - local entity proj, prevproj, firstproj; - local vector s; + float counter, shots; + entity proj, prevproj, firstproj; + vector s; vector forward, right, up; float maxdmg; @@ -324,10 +364,11 @@ void W_Crylink_Attack (void) shots = autocvar_g_balance_crylink_primary_shots; pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots); - proj = world; - while (counter < shots) + proj = prevproj = firstproj = world; + for(counter = 0; counter < shots; ++counter) { proj = spawn (); + proj.reset = W_Crylink_Reset; proj.realowner = proj.owner = self; proj.classname = "spike"; proj.bot_dodge = TRUE; @@ -396,12 +437,11 @@ void W_Crylink_Attack (void) //proj.glow_size = 20; proj.flags = FL_PROJECTILE; - + proj.missile_flags = MIF_SPLASH; + CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE); other = proj; MUTATOR_CALLHOOK(EditProjectile); - - counter = counter + 1; } if(autocvar_g_balance_crylink_primary_joinspread != 0 || autocvar_g_balance_crylink_primary_jointime != 0) { @@ -413,8 +453,10 @@ void W_Crylink_Attack (void) void W_Crylink_Attack2 (void) { - local float counter, shots; - local entity proj, prevproj, firstproj; + float counter, shots; + entity proj, prevproj, firstproj; + vector s; + vector forward, right, up; float maxdmg; W_DecreaseAmmo(ammo_cells, autocvar_g_balance_crylink_secondary_ammo, autocvar_g_balance_crylink_reload_ammo); @@ -425,13 +467,17 @@ void W_Crylink_Attack2 (void) maxdmg += autocvar_g_balance_crylink_secondary_joinexplode_damage; W_SetupShot (self, FALSE, 2, "weapons/crylink_fire2.wav", CH_WEAPON_A, maxdmg); + forward = v_forward; + right = v_right; + up = v_up; shots = autocvar_g_balance_crylink_secondary_shots; pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots); - proj = world; - while (counter < shots) + proj = prevproj = firstproj = world; + for(counter = 0; counter < shots; ++counter) { proj = spawn (); + proj.reset = W_Crylink_Reset; proj.realowner = proj.owner = self; proj.classname = "spike"; proj.bot_dodge = TRUE; @@ -464,7 +510,26 @@ void W_Crylink_Attack2 (void) setorigin (proj, w_shotorg); setsize(proj, '0 0 0', '0 0 0'); - W_SetupProjectileVelocityEx(proj, (w_shotdir + (((counter + 0.5) / shots) * 2 - 1) * v_right * autocvar_g_balance_crylink_secondary_spread * g_weaponspreadfactor), v_up, autocvar_g_balance_crylink_secondary_speed, 0, 0, 0, FALSE); + if(autocvar_g_balance_crylink_secondary_spreadtype == 1) + { + s = '0 0 0'; + if (counter == 0) + s = '0 0 0'; + else + { + makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1))); + s_y = v_forward_x; + s_z = v_forward_y; + } + s = s * autocvar_g_balance_crylink_secondary_spread * g_weaponspreadfactor; + s = w_shotdir + right * s_y + up * s_z; + } + else + { + s = (w_shotdir + (((counter + 0.5) / shots) * 2 - 1) * v_right * autocvar_g_balance_crylink_secondary_spread * g_weaponspreadfactor); + } + + W_SetupProjectileVelocityEx(proj, s, v_up, autocvar_g_balance_crylink_secondary_speed, 0, 0, 0, FALSE); proj.touch = W_Crylink_Touch2; proj.think = W_Crylink_Fadethink; if(counter == (shots - 1) / 2) @@ -488,12 +553,11 @@ void W_Crylink_Attack2 (void) //proj.glow_size = 20; proj.flags = FL_PROJECTILE; - + proj.missile_flags = MIF_SPLASH; + CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE); other = proj; MUTATOR_CALLHOOK(EditProjectile); - - counter = counter + 1; } if(autocvar_g_balance_crylink_secondary_joinspread != 0 || autocvar_g_balance_crylink_secondary_jointime != 0) { @@ -603,7 +667,7 @@ float w_crylink(float req) return TRUE; ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_primary_ammo; - ammo_amount += self.weapon_load[WEP_CRYLINK] >= autocvar_g_balance_crylink_primary_ammo; + ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= autocvar_g_balance_crylink_primary_ammo; return ammo_amount; } else if (req == WR_CHECKAMMO2) @@ -613,7 +677,7 @@ float w_crylink(float req) return TRUE; ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_secondary_ammo; - ammo_amount += self.weapon_load[WEP_CRYLINK] >= autocvar_g_balance_crylink_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= autocvar_g_balance_crylink_secondary_ammo; return ammo_amount; } else if (req == WR_RELOAD) @@ -621,7 +685,7 @@ float w_crylink(float req) W_Reload(min(autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_secondary_ammo), autocvar_g_balance_crylink_reload_ammo, autocvar_g_balance_crylink_reload_time, "weapons/reload.wav"); } return TRUE; -}; +} #endif #ifdef CSQC float w_crylink(float req)