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