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