2 REGISTER_WEAPON(SNIPERRIFLE, w_sniperrifle, IT_NAILS, 7, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN, BOT_PICKUP_RATING_MID, "campingrifle", "sniperrifle", _("Sniper Rifle"))
6 .float sniperrifle_accumulator;
8 void W_SniperRifle_FireBullet(float pSpread, float pDamage, float pHeadshotAddedDamage, float pForce, float pSpeed, float pLifetime, float pAmmo, float deathtype, float pBulletConstant, float pTracer, float pShots, string pSound)
12 W_DecreaseAmmo(ammo_nails, pAmmo, autocvar_g_balance_sniperrifle_reload_ammo);
14 W_SetupShot (self, autocvar_g_antilag_bullets && pSpeed >= autocvar_g_antilag_bullets, 2, pSound, CHAN_WEAPON, (pDamage + pHeadshotAddedDamage) * pShots);
16 pointparticles(particleeffectnum("sniperrifle_muzzleflash"), w_shotorg, w_shotdir * 2000, 1);
18 if(self.BUTTON_ZOOM | self.BUTTON_ZOOMSCRIPT) // if zoomed, shoot from the eye
20 w_shotdir = v_forward;
21 w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward;
24 for(i = 0; i < pShots; ++i)
25 fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, (pTracer ? EF_RED : EF_BLUE), 1, pBulletConstant);
26 endFireBallisticBullet();
28 if (autocvar_g_casings >= 2)
29 SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
32 void W_SniperRifle_Attack()
34 W_SniperRifle_FireBullet(autocvar_g_balance_sniperrifle_primary_spread, autocvar_g_balance_sniperrifle_primary_damage, autocvar_g_balance_sniperrifle_primary_headshotaddeddamage, autocvar_g_balance_sniperrifle_primary_force, autocvar_g_balance_sniperrifle_primary_speed, autocvar_g_balance_sniperrifle_primary_lifetime, autocvar_g_balance_sniperrifle_primary_ammo, WEP_SNIPERRIFLE, autocvar_g_balance_sniperrifle_primary_bulletconstant, autocvar_g_balance_sniperrifle_primary_tracer, autocvar_g_balance_sniperrifle_primary_shots, "weapons/campingrifle_fire.wav");
37 void W_SniperRifle_Attack2()
39 W_SniperRifle_FireBullet(autocvar_g_balance_sniperrifle_secondary_spread, autocvar_g_balance_sniperrifle_secondary_damage, autocvar_g_balance_sniperrifle_secondary_headshotaddeddamage, autocvar_g_balance_sniperrifle_secondary_force, autocvar_g_balance_sniperrifle_secondary_speed, autocvar_g_balance_sniperrifle_secondary_lifetime, autocvar_g_balance_sniperrifle_secondary_ammo, WEP_SNIPERRIFLE | HITTYPE_SECONDARY, autocvar_g_balance_sniperrifle_secondary_bulletconstant, autocvar_g_balance_sniperrifle_secondary_tracer, autocvar_g_balance_sniperrifle_secondary_shots, "weapons/campingrifle_fire2.wav");
42 void spawnfunc_weapon_sniperrifle (void)
44 weapon_defaultspawnfunc(WEP_SNIPERRIFLE);
47 // compatibility alias
48 void spawnfunc_weapon_campingrifle (void)
50 spawnfunc_weapon_sniperrifle();
53 .void(void) sniperrifle_bullethail_attackfunc;
54 .float sniperrifle_bullethail_frame;
55 .float sniperrifle_bullethail_animtime;
56 .float sniperrifle_bullethail_refire;
57 void W_SniperRifle_BulletHail_Continue()
61 sw = self.switchweapon; // make it not detect weapon changes as reason to abort firing
62 af = ATTACK_FINISHED(self);
63 self.switchweapon = self.weapon;
64 ATTACK_FINISHED(self) = time;
65 print(ftos(self.ammo_nails), "\n");
66 r = weapon_prepareattack(self.sniperrifle_bullethail_frame == WFRAME_FIRE2, self.sniperrifle_bullethail_refire);
67 if(self.switchweapon == self.weapon)
68 self.switchweapon = sw;
71 self.sniperrifle_bullethail_attackfunc();
72 weapon_thinkf(self.sniperrifle_bullethail_frame, self.sniperrifle_bullethail_animtime, W_SniperRifle_BulletHail_Continue);
73 print("thinkf set\n");
77 ATTACK_FINISHED(self) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time
78 print("out of ammo... ", ftos(self.weaponentity.state), "\n");
82 void W_SniperRifle_BulletHail(float mode, void(void) AttackFunc, float fr, float animtime, float refire)
84 // if we get here, we have at least one bullet to fire
89 self.sniperrifle_bullethail_attackfunc = AttackFunc;
90 self.sniperrifle_bullethail_frame = fr;
91 self.sniperrifle_bullethail_animtime = animtime;
92 self.sniperrifle_bullethail_refire = refire;
93 weapon_thinkf(fr, animtime, W_SniperRifle_BulletHail_Continue);
98 weapon_thinkf(fr, animtime, w_ready);
102 .float bot_secondary_sniperriflemooth;
103 float w_sniperrifle(float req)
109 self.BUTTON_ATCK=FALSE;
110 self.BUTTON_ATCK2=FALSE;
111 if(vlen(self.origin-self.enemy.origin) > 1000)
112 self.bot_secondary_sniperriflemooth = 0;
113 if(self.bot_secondary_sniperriflemooth == 0)
115 if(bot_aim(autocvar_g_balance_sniperrifle_primary_speed, 0, autocvar_g_balance_sniperrifle_primary_lifetime, TRUE))
117 self.BUTTON_ATCK = TRUE;
118 if(random() < 0.01) self.bot_secondary_sniperriflemooth = 1;
123 if(bot_aim(autocvar_g_balance_sniperrifle_secondary_speed, 0, autocvar_g_balance_sniperrifle_secondary_lifetime, TRUE))
125 self.BUTTON_ATCK2 = TRUE;
126 if(random() < 0.03) self.bot_secondary_sniperriflemooth = 0;
130 else if (req == WR_THINK)
132 if(autocvar_g_balance_sniperrifle_reload_ammo && self.clip_load < min(autocvar_g_balance_sniperrifle_primary_ammo, autocvar_g_balance_sniperrifle_secondary_ammo)) // forced reload
133 weapon_action(self.weapon, WR_RELOAD);
136 self.sniperrifle_accumulator = bound(time - autocvar_g_balance_sniperrifle_bursttime, self.sniperrifle_accumulator, time);
137 if (self.BUTTON_ATCK)
138 if (weapon_prepareattack_check(0, autocvar_g_balance_sniperrifle_primary_refire))
139 if (time >= self.sniperrifle_accumulator + autocvar_g_balance_sniperrifle_primary_burstcost)
141 weapon_prepareattack_do(0, autocvar_g_balance_sniperrifle_primary_refire);
142 W_SniperRifle_BulletHail(autocvar_g_balance_sniperrifle_primary_bullethail, W_SniperRifle_Attack, WFRAME_FIRE1, autocvar_g_balance_sniperrifle_primary_animtime, autocvar_g_balance_sniperrifle_primary_refire);
143 self.sniperrifle_accumulator += autocvar_g_balance_sniperrifle_primary_burstcost;
145 if (self.BUTTON_ATCK2)
147 if (autocvar_g_balance_sniperrifle_secondary)
149 if(autocvar_g_balance_sniperrifle_secondary_reload)
150 weapon_action(self.weapon, WR_RELOAD);
153 if (weapon_prepareattack_check(1, autocvar_g_balance_sniperrifle_secondary_refire))
154 if (time >= self.sniperrifle_accumulator + autocvar_g_balance_sniperrifle_secondary_burstcost)
156 weapon_prepareattack_do(1, autocvar_g_balance_sniperrifle_secondary_refire);
157 W_SniperRifle_BulletHail(autocvar_g_balance_sniperrifle_secondary_bullethail, W_SniperRifle_Attack2, WFRAME_FIRE2, autocvar_g_balance_sniperrifle_secondary_animtime, autocvar_g_balance_sniperrifle_primary_refire);
158 self.sniperrifle_accumulator += autocvar_g_balance_sniperrifle_secondary_burstcost;
165 else if (req == WR_PRECACHE)
167 precache_model ("models/weapons/g_campingrifle.md3");
168 precache_model ("models/weapons/v_campingrifle.md3");
169 precache_model ("models/weapons/h_campingrifle.iqm");
170 precache_sound ("weapons/campingrifle_fire.wav");
171 precache_sound ("weapons/campingrifle_fire2.wav");
172 //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
174 else if (req == WR_SETUP)
176 weapon_setup(WEP_SNIPERRIFLE);
177 self.current_ammo = ammo_nails;
179 else if (req == WR_CHECKAMMO1)
181 ammo_amount = self.ammo_nails >= autocvar_g_balance_sniperrifle_primary_ammo;
182 ammo_amount += self.weapon_load[WEP_SNIPERRIFLE] >= autocvar_g_balance_sniperrifle_primary_ammo;
185 else if (req == WR_CHECKAMMO2)
187 ammo_amount = self.ammo_nails >= autocvar_g_balance_sniperrifle_secondary_ammo;
188 ammo_amount += self.weapon_load[WEP_SNIPERRIFLE] >= autocvar_g_balance_sniperrifle_secondary_ammo;
191 else if (req == WR_RESETPLAYER)
193 self.sniperrifle_accumulator = time - autocvar_g_balance_sniperrifle_bursttime;
195 else if (req == WR_RELOAD)
197 W_Reload(min(autocvar_g_balance_sniperrifle_primary_ammo, autocvar_g_balance_sniperrifle_secondary_ammo), autocvar_g_balance_sniperrifle_reload_ammo, autocvar_g_balance_sniperrifle_reload_time, "weapons/reload.wav");
203 float w_sniperrifle(float req)
205 if(req == WR_IMPACTEFFECT)
208 org2 = w_org + w_backoff * 2;
209 pointparticles(particleeffectnum("machinegun_impact"), org2, w_backoff * 1000, 1);
213 sound(self, CHAN_PROJECTILE, "weapons/ric1.wav", VOL_BASE, ATTN_NORM);
214 else if(w_random < 0.4)
215 sound(self, CHAN_PROJECTILE, "weapons/ric2.wav", VOL_BASE, ATTN_NORM);
216 else if(w_random < 0.5)
217 sound(self, CHAN_PROJECTILE, "weapons/ric3.wav", VOL_BASE, ATTN_NORM);
220 else if(req == WR_PRECACHE)
222 precache_sound("weapons/ric1.wav");
223 precache_sound("weapons/ric2.wav");
224 precache_sound("weapons/ric3.wav");
226 else if (req == WR_SUICIDEMESSAGE)
228 if(w_deathtype & HITTYPE_SECONDARY)
229 w_deathtypestring = _("%s shot themself automatically");
231 w_deathtypestring = _("%s sniped themself somehow");
233 else if (req == WR_KILLMESSAGE)
235 if(w_deathtype & HITTYPE_SECONDARY)
237 if(w_deathtype & HITTYPE_BOUNCE)
238 w_deathtypestring = _("%s failed to hide from %s's bullet hail");
240 w_deathtypestring = _("%s died in %s's bullet hail");
244 if(w_deathtype & HITTYPE_BOUNCE)
246 // TODO special headshot message here too?
247 w_deathtypestring = _("%s failed to hide from %s's rifle");
251 if(w_deathtype & HITTYPE_HEADSHOT)
252 w_deathtypestring = _("%s got hit in the head by %s");
254 w_deathtypestring = _("%s was sniped by %s");