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"))
5 //Sniper rifle Primary mode: manually operated bolt*, Secondary: full automatic**
6 //* Manually operating the bolt means that all the power of the gas is used to propell the bullet. In this mode the bolt is prevented from moving backwards in response to the firing of the bullet.
7 //** In fully automatic mode some of the gas is used to extract and reload the next cartrige, thus there is less power and range.
9 .float sniperrifle_accumulator;
11 void W_SniperRifle_Reload()
13 W_Reload(ammo_nails, 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");
16 void W_SniperRifle_FireBullet(float pSpread, float pDamage, float pHeadshotAddedDamage, float pForce, float pSpeed, float pLifetime, float pAmmo, float deathtype, float pBulletConstant)
18 // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
19 if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
21 if(autocvar_g_balance_sniperrifle_reload_ammo)
23 self.clip_load -= pAmmo;
24 self.weapon_load[WEP_SNIPERRIFLE] = self.clip_load;
27 self.ammo_nails -= pAmmo;
30 if(deathtype & HITTYPE_SECONDARY)
31 W_SetupShot (self, autocvar_g_antilag_bullets && pSpeed >= autocvar_g_antilag_bullets, 2, "weapons/campingrifle_fire2.wav", CHAN_WEAPON, autocvar_g_balance_sniperrifle_secondary_damage + autocvar_g_balance_sniperrifle_secondary_headshotaddeddamage);
33 W_SetupShot (self, autocvar_g_antilag_bullets && pSpeed >= autocvar_g_antilag_bullets, 2, "weapons/campingrifle_fire.wav", CHAN_WEAPON, autocvar_g_balance_sniperrifle_primary_damage + autocvar_g_balance_sniperrifle_primary_headshotaddeddamage);
35 pointparticles(particleeffectnum("sniperrifle_muzzleflash"), w_shotorg, w_shotdir * 2000, 1);
37 if(self.BUTTON_ZOOM) // if zoomed, shoot from the eye
39 w_shotdir = v_forward;
40 w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward;
43 if(deathtype & HITTYPE_SECONDARY)
44 fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, (autocvar_g_balance_sniperrifle_secondary_tracer ? EF_RED : EF_BLUE), 1, pBulletConstant);
46 fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, (autocvar_g_balance_sniperrifle_primary_tracer ? EF_RED : EF_BLUE), 1, pBulletConstant);
47 endFireBallisticBullet();
49 if (autocvar_g_casings >= 2)
50 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);
53 void W_SniperRifle_Attack()
55 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);
58 void W_SniperRifle_Attack2()
60 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);
63 void spawnfunc_weapon_sniperrifle (void)
65 weapon_defaultspawnfunc(WEP_SNIPERRIFLE);
68 // compatibility alias
69 void spawnfunc_weapon_campingrifle (void)
71 spawnfunc_weapon_sniperrifle();
74 .void(void) sniperrifle_bullethail_attackfunc;
75 .float sniperrifle_bullethail_frame;
76 .float sniperrifle_bullethail_animtime;
77 .float sniperrifle_bullethail_refire;
78 void W_SniperRifle_BulletHail_Continue()
82 sw = self.switchweapon; // make it not detect weapon changes as reason to abort firing
83 af = ATTACK_FINISHED(self);
84 self.switchweapon = self.weapon;
85 ATTACK_FINISHED(self) = time;
86 print(ftos(self.ammo_nails), "\n");
87 r = weapon_prepareattack(self.sniperrifle_bullethail_frame == WFRAME_FIRE2, self.sniperrifle_bullethail_refire);
88 if(self.switchweapon == self.weapon)
89 self.switchweapon = sw;
92 self.sniperrifle_bullethail_attackfunc();
93 weapon_thinkf(self.sniperrifle_bullethail_frame, self.sniperrifle_bullethail_animtime, W_SniperRifle_BulletHail_Continue);
94 print("thinkf set\n");
98 ATTACK_FINISHED(self) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time
99 print("out of ammo... ", ftos(self.weaponentity.state), "\n");
103 void W_SniperRifle_BulletHail(float mode, void(void) AttackFunc, float fr, float animtime, float refire)
105 // if we get here, we have at least one bullet to fire
110 self.sniperrifle_bullethail_attackfunc = AttackFunc;
111 self.sniperrifle_bullethail_frame = fr;
112 self.sniperrifle_bullethail_animtime = animtime;
113 self.sniperrifle_bullethail_refire = refire;
114 weapon_thinkf(fr, animtime, W_SniperRifle_BulletHail_Continue);
119 weapon_thinkf(fr, animtime, w_ready);
123 .float bot_secondary_sniperriflemooth;
124 float w_sniperrifle(float req)
130 self.BUTTON_ATCK=FALSE;
131 self.BUTTON_ATCK2=FALSE;
132 if(vlen(self.origin-self.enemy.origin) > 1000)
133 self.bot_secondary_sniperriflemooth = 0;
134 if(self.bot_secondary_sniperriflemooth == 0)
136 if(bot_aim(autocvar_g_balance_sniperrifle_primary_speed, 0, autocvar_g_balance_sniperrifle_primary_lifetime, TRUE))
138 self.BUTTON_ATCK = TRUE;
139 if(random() < 0.01) self.bot_secondary_sniperriflemooth = 1;
144 if(bot_aim(autocvar_g_balance_sniperrifle_secondary_speed, 0, autocvar_g_balance_sniperrifle_secondary_lifetime, TRUE))
146 self.BUTTON_ATCK2 = TRUE;
147 if(random() < 0.03) self.bot_secondary_sniperriflemooth = 0;
151 else if (req == WR_THINK)
153 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
154 W_SniperRifle_Reload();
157 self.sniperrifle_accumulator = bound(time - autocvar_g_balance_sniperrifle_bursttime, self.sniperrifle_accumulator, time);
158 if (self.BUTTON_ATCK)
159 if (weapon_prepareattack_check(0, autocvar_g_balance_sniperrifle_primary_refire))
160 if (time >= self.sniperrifle_accumulator + autocvar_g_balance_sniperrifle_primary_burstcost)
162 weapon_prepareattack_do(0, autocvar_g_balance_sniperrifle_primary_refire);
163 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);
164 self.sniperrifle_accumulator += autocvar_g_balance_sniperrifle_primary_burstcost;
166 if (self.BUTTON_ATCK2)
168 if (autocvar_g_balance_sniperrifle_secondary)
170 if(autocvar_g_balance_sniperrifle_secondary_reload)
171 W_SniperRifle_Reload();
174 if (weapon_prepareattack_check(1, autocvar_g_balance_sniperrifle_secondary_refire))
175 if (time >= self.sniperrifle_accumulator + autocvar_g_balance_sniperrifle_secondary_burstcost)
177 weapon_prepareattack_do(1, autocvar_g_balance_sniperrifle_secondary_refire);
178 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);
179 self.sniperrifle_accumulator += autocvar_g_balance_sniperrifle_secondary_burstcost;
186 else if (req == WR_PRECACHE)
188 precache_model ("models/weapons/g_campingrifle.md3");
189 precache_model ("models/weapons/v_campingrifle.md3");
190 precache_model ("models/weapons/h_campingrifle.iqm");
191 precache_sound ("weapons/campingrifle_fire.wav");
192 precache_sound ("weapons/campingrifle_fire2.wav");
193 precache_sound ("weapons/reload.wav");
195 else if (req == WR_SETUP)
197 weapon_setup(WEP_SNIPERRIFLE);
199 else if (req == WR_CHECKAMMO1)
201 ammo_amount = self.ammo_nails >= autocvar_g_balance_sniperrifle_primary_ammo;
202 ammo_amount += self.weapon_load[WEP_SNIPERRIFLE] >= autocvar_g_balance_sniperrifle_primary_ammo;
205 else if (req == WR_CHECKAMMO2)
207 ammo_amount = self.ammo_nails >= autocvar_g_balance_sniperrifle_secondary_ammo;
208 ammo_amount += self.weapon_load[WEP_SNIPERRIFLE] >= autocvar_g_balance_sniperrifle_secondary_ammo;
211 else if (req == WR_RESETPLAYER)
213 self.sniperrifle_accumulator = time - autocvar_g_balance_sniperrifle_bursttime;
215 else if (req == WR_RELOAD)
217 W_SniperRifle_Reload();
223 float w_sniperrifle(float req)
225 if(req == WR_IMPACTEFFECT)
228 org2 = w_org + w_backoff * 2;
229 pointparticles(particleeffectnum("machinegun_impact"), org2, w_backoff * 1000, 1);
233 sound(self, CHAN_PROJECTILE, "weapons/ric1.wav", VOL_BASE, ATTN_NORM);
234 else if(w_random < 0.4)
235 sound(self, CHAN_PROJECTILE, "weapons/ric2.wav", VOL_BASE, ATTN_NORM);
236 else if(w_random < 0.5)
237 sound(self, CHAN_PROJECTILE, "weapons/ric3.wav", VOL_BASE, ATTN_NORM);
240 else if(req == WR_PRECACHE)
242 precache_sound("weapons/ric1.wav");
243 precache_sound("weapons/ric2.wav");
244 precache_sound("weapons/ric3.wav");
246 else if (req == WR_SUICIDEMESSAGE)
248 if(w_deathtype & HITTYPE_SECONDARY)
249 w_deathtypestring = _("%s shot themself automatically");
251 w_deathtypestring = _("%s sniped themself somehow");
253 else if (req == WR_KILLMESSAGE)
255 if(w_deathtype & HITTYPE_SECONDARY)
257 if(w_deathtype & HITTYPE_BOUNCE)
258 w_deathtypestring = _("%s failed to hide from %s's bullet hail");
260 w_deathtypestring = _("%s died in %s's bullet hail");
264 if(w_deathtype & HITTYPE_BOUNCE)
266 // TODO special headshot message here too?
267 w_deathtypestring = _("%s failed to hide from %s's rifle");
271 if(w_deathtype & HITTYPE_HEADSHOT)
272 w_deathtypestring = _("%s got hit in the head by %s");
274 w_deathtypestring = _("%s was sniped by %s");