]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/w_campingrifle.qc
make sure bullet counter is never > amount nails
[divverent/nexuiz.git] / data / qcsrc / server / w_campingrifle.qc
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.
4
5 float W_CampingRifle_CheckMaxBullets()
6 {
7         float maxbulls;
8         maxbulls = cvar("g_balance_campingrifle_magazinecapacity");
9         if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
10                 maxbulls = min(maxbulls, floor(self.ammo_nails / min(cvar("g_balance_campingrifle_primary_ammo"), cvar("g_balance_campingrifle_secondary_ammo"))));
11         if(self.campingrifle_bulletcounter > maxbulls)
12                 self.campingrifle_bulletcounter = maxbulls;
13         return (self.campingrifle_bulletcounter == maxbulls);
14 }
15
16 void W_Campingrifle_ReloadedAndReady()
17 {
18         float t;
19         self.campingrifle_bulletcounter = cvar("g_balance_campingrifle_magazinecapacity");
20         W_CampingRifle_CheckMaxBullets();
21         t = ATTACK_FINISHED(self) - cvar("g_balance_campingrifle_reloadtime") - 1;
22         ATTACK_FINISHED(self) = t;
23         w_ready();
24 }
25
26 void W_Campingrifle_Reload()
27 {
28         float t;
29
30         if (self.campingrifle_bulletcounter >= cvar("g_balance_campingrifle_magazinecapacity"))
31                 return;
32         
33         if (self.weaponentity)
34         {
35                 if (self.weaponentity.wframe == WFRAME_RELOAD)
36                         return;
37
38                 // allow to switch away while reloading, but this will cause a new reload!
39                 self.weaponentity.state = WS_READY;
40         }
41
42         sound (self, CHAN_WEAPON2, "weapons/campingrifle_reload.wav", VOL_BASE, ATTN_NORM);
43
44         t = max(time, ATTACK_FINISHED(self)) + cvar("g_balance_campingrifle_reloadtime") + 1;
45         ATTACK_FINISHED(self) = t;
46
47         weapon_thinkf(WFRAME_RELOAD, cvar("g_balance_campingrifle_reloadtime"), W_Campingrifle_ReloadedAndReady);
48
49         self.campingrifle_bulletcounter = -1;
50 }
51
52 void W_Campingrifle_CheckReloadAndReady()
53 {
54         w_ready();
55         if (self.campingrifle_bulletcounter <= 0)
56                 W_Campingrifle_Reload();
57         else
58                 w_ready();
59 }
60
61 void W_CampingRifle_FireBullet(float pSpread, float pDamage, float pHeadshotAddedDamage, float pForce, float pSpeed, float pLifetime, float pAmmo, float deathtype, float pBulletConstant)
62 {
63         if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
64                 self.ammo_nails -= pAmmo;
65
66         if(deathtype & HITTYPE_SECONDARY)
67                 W_SetupShot (self, cvar("g_antilag_bullets") && pSpeed >= cvar("g_antilag_bullets"), 2, "weapons/campingrifle_fire2.wav", cvar("g_balance_campingrifle_secondary_damage"));
68         else
69                 W_SetupShot (self, cvar("g_antilag_bullets") && pSpeed >= cvar("g_antilag_bullets"), 2, "weapons/campingrifle_fire.wav", cvar("g_balance_campingrifle_primary_damage"));
70
71         pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 2000, 1);
72
73         if(self.BUTTON_ZOOM) // if zoomed, shoot from the eye
74         {
75                 w_shotdir = v_forward;
76                 w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward;
77         }
78
79         fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, EF_RED, 1, pBulletConstant);
80
81         if (cvar("g_casings") >= 2)
82                 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);
83         
84         self.campingrifle_bulletcounter = self.campingrifle_bulletcounter - 1;
85 }
86
87 void W_Campingrifle_Attack()
88 {
89         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"));
90 }
91
92 void W_Campingrifle_Attack2()
93 {
94         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"));
95 }
96
97 void spawnfunc_weapon_campingrifle (void)
98 {
99         weapon_defaultspawnfunc(WEP_CAMPINGRIFLE);
100 }
101
102 .float bot_secondary_campingriflemooth;
103 float w_campingrifle(float req)
104 {
105         float full;
106         if (req == WR_AIM)
107         {
108                 self.BUTTON_ATCK=FALSE;
109                 self.BUTTON_ATCK2=FALSE;
110                 if(vlen(self.origin-self.enemy.origin) > 1000)
111                         self.bot_secondary_campingriflemooth = 0;
112                 if(self.bot_secondary_campingriflemooth == 0)
113                 {
114                         if(bot_aim(cvar("g_balance_campingrifle_primary_speed"), 0, cvar("g_balance_campingrifle_primary_lifetime"), TRUE))
115                         {
116                                 self.BUTTON_ATCK = TRUE;
117                                 if(random() < 0.01) self.bot_secondary_campingriflemooth = 1;
118                         }
119                 }
120                 else
121                 {
122                         if(bot_aim(cvar("g_balance_campingrifle_secondary_speed"), 0, cvar("g_balance_campingrifle_secondary_lifetime"), TRUE))
123                         {
124                                 self.BUTTON_ATCK2 = TRUE;
125                                 if(random() < 0.03) self.bot_secondary_campingriflemooth = 0;
126                         }
127                 }
128         }
129         else if (req == WR_THINK)
130         {
131                 if(self.campingrifle_bulletcounter < 0) // forced reload (e.g. because interrupted)
132                 {
133                         if(self.switchweapon == self.weapon)
134                         if(self.weaponentity.state == WS_READY)
135                                 W_Campingrifle_Reload();
136                 }
137                 else
138                 {
139                         if (self.BUTTON_ATCK)
140                         if (weapon_prepareattack(0, cvar("g_balance_campingrifle_primary_refire")))
141                         {
142                                 W_Campingrifle_Attack();
143                                 weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_campingrifle_primary_animtime"), W_Campingrifle_CheckReloadAndReady);
144                         }
145                         if (self.BUTTON_ATCK2)
146                         if (weapon_prepareattack(1, cvar("g_balance_campingrifle_secondary_refire")))
147                         {
148                                 W_Campingrifle_Attack2();
149                                 weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_campingrifle_secondary_animtime"), W_Campingrifle_CheckReloadAndReady);
150                         }
151                 }
152         }
153         else if (req == WR_PRECACHE)
154         {               
155                 precache_model ("models/weapons/g_campingrifle.md3");
156                 precache_model ("models/weapons/v_campingrifle.md3");
157                 precache_model ("models/weapons/h_campingrifle.dpm");
158                 precache_sound ("weapons/campingrifle_reload.wav");
159                 precache_sound ("weapons/campingrifle_fire.wav");
160                 precache_sound ("weapons/campingrifle_fire2.wav");
161         }
162         else if (req == WR_SETUP)
163         {
164                 weapon_setup(WEP_CAMPINGRIFLE);
165
166                 full = W_CampingRifle_CheckMaxBullets();
167                 if(cvar("g_balance_campingrifle_auto_reload_after_changing_weapons"))
168                         if(!full)
169                                 self.campingrifle_bulletcounter = -1;
170         }
171         else if (req == WR_CHECKAMMO1)
172                 return self.ammo_nails >= cvar("g_balance_campingrifle_primary_ammo");
173         else if (req == WR_CHECKAMMO2)
174                 return self.ammo_nails >= cvar("g_balance_campingrifle_secondary_ammo");
175         else if (req == WR_SUICIDEMESSAGE)
176         {
177                 if(w_deathtype & HITTYPE_SECONDARY)
178                         w_deathtypestring = "shot himself automatically";
179                 else
180                         w_deathtypestring = "sniped himself somehow";
181         }
182         else if (req == WR_KILLMESSAGE)
183         {
184                 if(w_deathtype & HITTYPE_SECONDARY)
185                 {
186                         if(w_deathtype & HITTYPE_BOUNCE)
187                                 w_deathtypestring = "failed to hide from #'s bullet hail";
188                         else
189                                 w_deathtypestring = "died in #'s bullet hail";
190                 }
191                 else
192                 {
193                         if(w_deathtype & HITTYPE_BOUNCE)
194                         {
195                                 // TODO special headshot message here too?
196                                 w_deathtypestring = "failed to hide from #'s rifle";
197                         }
198                         else
199                         {
200                                 if(w_deathtype & HITTYPE_HEADSHOT)
201                                         w_deathtypestring = "got hit in the head by #";
202                                 else
203                                         w_deathtypestring = "was sniped by #";
204                         }
205                 }
206         }
207         else if (req == WR_RELOAD)
208         {
209                 W_Campingrifle_Reload();
210         }
211         return TRUE;
212 };