1 //Camping rifle Primary mode: manually operated bolt*, Secondary: full automatic**
2 //* 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.
3 //** In fully automatic mode some of the gas is used to extract and reload the next cartrige, thus there is less power and range.
5 .float campingrifle_accumulator;
7 float W_CampingRifle_CheckMaxBullets()
10 maxbulls = cvar("g_balance_campingrifle_magazinecapacity");
13 if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
14 maxbulls = min(maxbulls, floor(self.ammo_nails / min(cvar("g_balance_campingrifle_primary_ammo"), cvar("g_balance_campingrifle_secondary_ammo"))));
15 if(self.campingrifle_bulletcounter > maxbulls || !cvar("g_balance_campingrifle_magazinecapacity"))
16 self.campingrifle_bulletcounter = maxbulls;
17 return (self.campingrifle_bulletcounter == maxbulls);
20 void W_CampingRifle_ReloadedAndReady()
23 self.campingrifle_bulletcounter = cvar("g_balance_campingrifle_magazinecapacity");
24 W_CampingRifle_CheckMaxBullets();
25 t = ATTACK_FINISHED(self) - cvar("g_balance_campingrifle_reloadtime") - 1;
26 ATTACK_FINISHED(self) = t;
30 void W_CampingRifle_Reload()
34 W_CampingRifle_CheckMaxBullets();
35 if (self.campingrifle_bulletcounter >= cvar("g_balance_campingrifle_magazinecapacity"))
38 if(self.ammo_nails < min(cvar("g_balance_campingrifle_primary_ammo"), cvar("g_balance_campingrifle_secondary_ammo")))
40 self.campingrifle_bulletcounter = -1; // reload later
44 if (self.weaponentity)
46 if (self.weaponentity.wframe == WFRAME_RELOAD)
49 // allow to switch away while reloading, but this will cause a new reload!
50 self.weaponentity.state = WS_READY;
53 sound (self, CHAN_WEAPON2, "weapons/campingrifle_reload.wav", VOL_BASE, ATTN_NORM);
55 t = max(time, ATTACK_FINISHED(self)) + cvar("g_balance_campingrifle_reloadtime") + 1;
56 ATTACK_FINISHED(self) = t;
58 weapon_thinkf(WFRAME_RELOAD, cvar("g_balance_campingrifle_reloadtime"), W_CampingRifle_ReloadedAndReady);
60 self.campingrifle_bulletcounter = -1;
63 void W_CampingRifle_CheckReloadAndReady()
66 if (self.campingrifle_bulletcounter <= 0)
67 W_CampingRifle_Reload();
72 void W_CampingRifle_FireBullet(float pSpread, float pDamage, float pHeadshotAddedDamage, float pForce, float pSpeed, float pLifetime, float pAmmo, float deathtype, float pBulletConstant)
74 if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
75 self.ammo_nails -= pAmmo;
77 if(deathtype & HITTYPE_SECONDARY)
78 W_SetupShot (self, cvar("g_antilag_bullets") && pSpeed >= cvar("g_antilag_bullets"), 2, "weapons/campingrifle_fire2.wav", cvar("g_balance_campingrifle_secondary_damage"));
80 W_SetupShot (self, cvar("g_antilag_bullets") && pSpeed >= cvar("g_antilag_bullets"), 2, "weapons/campingrifle_fire.wav", cvar("g_balance_campingrifle_primary_damage"));
82 pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 2000, 1);
84 if(self.BUTTON_ZOOM) // if zoomed, shoot from the eye
86 w_shotdir = v_forward;
87 w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward;
90 fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, EF_RED, 1, pBulletConstant);
91 endFireBallisticBullet();
93 if (cvar("g_casings") >= 2)
94 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);
96 self.campingrifle_bulletcounter = self.campingrifle_bulletcounter - 1;
97 W_CampingRifle_CheckMaxBullets();
100 void W_CampingRifle_Attack()
102 W_CampingRifle_FireBullet(cvar("g_balance_campingrifle_primary_spread"), cvar("g_balance_campingrifle_primary_damage"), cvar("g_balance_campingrifle_primary_headshotaddeddamage"), cvar("g_balance_campingrifle_primary_force"), cvar("g_balance_campingrifle_primary_speed"), cvar("g_balance_campingrifle_primary_lifetime"), cvar("g_balance_campingrifle_primary_ammo"), WEP_CAMPINGRIFLE, cvar("g_balance_campingrifle_primary_bulletconstant"));
105 void W_CampingRifle_Attack2()
107 W_CampingRifle_FireBullet(cvar("g_balance_campingrifle_secondary_spread"), cvar("g_balance_campingrifle_secondary_damage"), cvar("g_balance_campingrifle_secondary_headshotaddeddamage"), cvar("g_balance_campingrifle_secondary_force"), cvar("g_balance_campingrifle_secondary_speed"), cvar("g_balance_campingrifle_secondary_lifetime"), cvar("g_balance_campingrifle_secondary_ammo"), WEP_CAMPINGRIFLE | HITTYPE_SECONDARY, cvar("g_balance_campingrifle_secondary_bulletconstant"));
110 void spawnfunc_weapon_campingrifle (void)
112 weapon_defaultspawnfunc(WEP_CAMPINGRIFLE);
115 .float bot_secondary_campingriflemooth;
116 float w_campingrifle(float req)
121 self.BUTTON_ATCK=FALSE;
122 self.BUTTON_ATCK2=FALSE;
123 if(vlen(self.origin-self.enemy.origin) > 1000)
124 self.bot_secondary_campingriflemooth = 0;
125 if(self.bot_secondary_campingriflemooth == 0)
127 if(bot_aim(cvar("g_balance_campingrifle_primary_speed"), 0, cvar("g_balance_campingrifle_primary_lifetime"), TRUE))
129 self.BUTTON_ATCK = TRUE;
130 if(random() < 0.01) self.bot_secondary_campingriflemooth = 1;
135 if(bot_aim(cvar("g_balance_campingrifle_secondary_speed"), 0, cvar("g_balance_campingrifle_secondary_lifetime"), TRUE))
137 self.BUTTON_ATCK2 = TRUE;
138 if(random() < 0.03) self.bot_secondary_campingriflemooth = 0;
142 else if (req == WR_THINK)
144 if(self.campingrifle_bulletcounter < 0) // forced reload (e.g. because interrupted)
146 if(self.switchweapon == self.weapon)
147 if(self.weaponentity.state == WS_READY)
148 W_CampingRifle_Reload();
152 self.campingrifle_accumulator = bound(time - cvar("g_balance_campingrifle_bursttime"), self.campingrifle_accumulator, time);
153 if (self.BUTTON_ATCK)
154 if (time >= self.campingrifle_accumulator + cvar("g_balance_campingrifle_primary_burstcost"))
155 if (weapon_prepareattack(0, cvar("g_balance_campingrifle_primary_refire")))
157 W_CampingRifle_Attack();
158 weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_campingrifle_primary_animtime"), W_CampingRifle_CheckReloadAndReady);
159 self.campingrifle_accumulator += cvar("g_balance_campingrifle_primary_burstcost");
161 if (self.BUTTON_ATCK2)
162 if (time >= self.campingrifle_accumulator + cvar("g_balance_campingrifle_secondary_burstcost"))
163 if (weapon_prepareattack(1, cvar("g_balance_campingrifle_secondary_refire")))
165 W_CampingRifle_Attack2();
166 weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_campingrifle_secondary_animtime"), W_CampingRifle_CheckReloadAndReady);
167 self.campingrifle_accumulator += cvar("g_balance_campingrifle_secondary_burstcost");
171 else if (req == WR_PRECACHE)
173 precache_model ("models/weapons/g_campingrifle.md3");
174 precache_model ("models/weapons/v_campingrifle.md3");
175 precache_model ("models/weapons/h_campingrifle.dpm");
176 precache_sound ("weapons/campingrifle_reload.wav");
177 precache_sound ("weapons/campingrifle_fire.wav");
178 precache_sound ("weapons/campingrifle_fire2.wav");
180 else if (req == WR_SETUP)
182 weapon_setup(WEP_CAMPINGRIFLE);
184 full = W_CampingRifle_CheckMaxBullets();
185 if(cvar("g_balance_campingrifle_auto_reload_after_changing_weapons"))
187 self.campingrifle_bulletcounter = -1;
189 else if (req == WR_CHECKAMMO1)
190 return self.ammo_nails >= cvar("g_balance_campingrifle_primary_ammo");
191 else if (req == WR_CHECKAMMO2)
192 return self.ammo_nails >= cvar("g_balance_campingrifle_secondary_ammo");
193 else if (req == WR_SUICIDEMESSAGE)
195 if(w_deathtype & HITTYPE_SECONDARY)
196 w_deathtypestring = "shot himself automatically";
198 w_deathtypestring = "sniped himself somehow";
200 else if (req == WR_KILLMESSAGE)
202 if(w_deathtype & HITTYPE_SECONDARY)
204 if(w_deathtype & HITTYPE_BOUNCE)
205 w_deathtypestring = "failed to hide from #'s bullet hail";
207 w_deathtypestring = "died in #'s bullet hail";
211 if(w_deathtype & HITTYPE_BOUNCE)
213 // TODO special headshot message here too?
214 w_deathtypestring = "failed to hide from #'s rifle";
218 if(w_deathtype & HITTYPE_HEADSHOT)
219 w_deathtypestring = "got hit in the head by #";
221 w_deathtypestring = "was sniped by #";
225 else if (req == WR_RELOAD)
227 W_CampingRifle_Reload();
229 else if (req == WR_RESETPLAYER)
231 self.campingrifle_accumulator = time - cvar("g_balance_campingrifle_bursttime");
232 self.campingrifle_bulletcounter = cvar("g_balance_campingrifle_magazinecapacity");
233 W_CampingRifle_CheckMaxBullets();