]> icculus.org git repositories - divverent/nexuiz.git/blob - qcsrc/gamec/cl_weaponsystem.c
Some changes to the grenade launcher and shotgun that weren't my changes
[divverent/nexuiz.git] / qcsrc / gamec / cl_weaponsystem.c
1 /*
2 ===========================================================================
3
4   CLIENT WEAPONSYSTEM CODE
5   Bring back W_Weaponframe
6
7 ===========================================================================
8 */ 
9
10 // spawning weaponentity for client
11 void() CL_SpawnWeaponentity =
12 {
13         if (self.weaponentity)
14         {
15                 w_clear();
16                 return;
17         }
18         self.weaponentity = spawn();
19         self.weaponentity.solid = SOLID_NOT;
20         self.weaponentity.owner = self;
21         self.weaponentity.weaponentity = self.weaponentity;
22         setmodel(self.weaponentity, "");
23         self.weaponentity.origin = '0 0 0';
24         self.weaponentity.angles = '0 0 0';
25         self.weaponentity.viewmodelforclient = self;
26         self.weaponentity.flags = 0;
27 };
28
29 // convertion from index (= impulse) to flag in .items
30 float(float index) weapon_translateindextoflag =
31 {
32         if (index == WEP_LASER) 
33                 return IT_LASER;
34         else if (index == WEP_SHOTGUN) 
35                 return IT_SHOTGUN;
36         else if (index == WEP_UZI) 
37                 return IT_UZI;
38         else if (index == WEP_GRENADE_LAUNCHER) 
39                 return IT_GRENADE_LAUNCHER;
40         else if (index == WEP_ELECTRO)
41                 return IT_ELECTRO;
42         else if (index == WEP_CRYLINK) 
43                 return IT_CRYLINK;
44         else if (index == WEP_NEX) 
45                 return IT_NEX;
46         else if (index == WEP_HAGAR) 
47                 return IT_HAGAR;
48         else if (index == WEP_ROCKET_LAUNCHER)
49                 return IT_ROCKET_LAUNCHER;
50 };
51
52 float(entity cl, float wpn, float andammo) client_hasweapon =
53 {
54         local float itemcode;
55
56         itemcode = weapon_translateindextoflag(wpn);
57         if (cl.items & itemcode)
58         {
59                 if (andammo)
60                 {
61                         weapon_action(wpn, WR_CHECKAMMO);
62                         if (weapon_hasammo)
63                                 return TRUE;
64                         return FALSE;
65                 }
66                 return TRUE;
67         }
68         return FALSE;
69 };
70
71 // Weapon subs
72 void() w_clear =
73 {
74         weapon_action(self.weapon, WR_CLEAR); 
75         if (self.weapon != -1)
76                 self.weapon = 0;
77         self.weaponentity.state = WS_CLEAR;
78         setmodel(self.weaponentity, "");
79         self.weaponentity.effects = 0;
80 };
81
82 void() w_ready =
83 {
84         self.weaponentity.state = WS_READY;
85         weapon_action(self.weapon, WR_IDLE); 
86 };
87
88 // FIXME: add qw-style client-custom weaponrating (cl_weaponrating)?
89 void() w_bestweapon
90 {// add new weapons here
91         weapon_hasammo = TRUE;
92         if (client_hasweapon(self, WEP_ROCKET_LAUNCHER, TRUE))
93                 self.switchweapon = WEP_ROCKET_LAUNCHER;
94         else if (client_hasweapon(self, WEP_NEX, TRUE))
95                 self.switchweapon = WEP_NEX;
96         else if (client_hasweapon(self, WEP_HAGAR, TRUE))
97                 self.switchweapon = WEP_HAGAR;
98         else if (client_hasweapon(self, WEP_GRENADE_LAUNCHER, TRUE))
99                 self.switchweapon = WEP_GRENADE_LAUNCHER;
100         else if (client_hasweapon(self, WEP_ELECTRO, TRUE))
101                 self.switchweapon = WEP_ELECTRO;
102         else if (client_hasweapon(self, WEP_CRYLINK, TRUE))
103                 self.switchweapon = WEP_CRYLINK;
104         else if (client_hasweapon(self, WEP_UZI, TRUE))
105                 self.switchweapon = WEP_UZI;
106         else if (client_hasweapon(self, WEP_SHOTGUN, TRUE))
107                 self.switchweapon = WEP_SHOTGUN;
108         else
109                 self.switchweapon = WEP_LASER;
110 };
111
112 // Setup weapon for client (after this raise frame will be launched)
113 void(float windex, string wmodel, float hudammo) weapon_setup =
114 {
115         local string wdir, weaponmdl;
116
117         self.items = self.items - (self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS));
118         self.items = self.items | hudammo;
119
120         self.weapon = windex;
121
122         if (wmodel != "")
123         {
124                 weaponmdl = strzone(strcat("models/weapons/", wmodel));
125                 setmodel(self.weaponentity, weaponmdl);
126         }
127         // VorteX: update visible weapon
128         // CL_ViswepUpdate();
129 };
130
131 // shot direction
132 float WEAPON_MAXRELX = 14; // if more, shot can be spawned after wall surface (in empty worldspace) or inside other entity if client stands close to it
133 void(float x, float y, float z) weapon_shotdir =
134 {
135         makevectors(self.v_angle);
136         self.shotorg  = self.origin + self.view_ofs + v_forward*bound(0, x, WEAPON_MAXRELX) + v_right*(y + self.weaponentity.view_ofs_y) + v_up*z;
137         self.shotdir = aim(self, 1000);
138 };
139
140 // perform weapon to attack (weaponstate and attack_finished check is here)
141 void(float() checkfunc1, float() checkfunc2, void() firefunc, float atktime) weapon_prepareattack =
142 {
143         // Change to best weapon if failed
144         if (!(game & GAME_INSTAGIB) && !(game & GAME_ROCKET_ARENA))
145         {
146                 if (!checkfunc1())
147                 {
148                         if (!checkfunc2())
149                                 w_bestweapon();
150                         return;
151                 }
152         }
153         // Don't do shot if previos attack  not finished
154         if (!(game & GAME_INSANE))
155                 if (time < self.attack_finished)            
156                         return; 
157         // Can't do shot if changing weapon
158         if (!(game & GAME_INSANE))
159                 if (self.weaponentity.state != WS_READY)        
160                         return;
161
162         self.attack_finished = time + atktime;
163         firefunc();
164 };
165
166 // perform weapon attack
167 void(float() checkfunc1, float() checkfunc2, void() firefunc) weapon_doattack
168 {
169         // Change to best weapon if failed
170         if (!(game & GAME_INSTAGIB) && !(game & GAME_ROCKET_ARENA))
171         {
172                 if (!checkfunc1())
173                 {
174                         if (!checkfunc2())
175                                 w_bestweapon();
176                         return;
177                 }
178         }
179         self.weaponentity.state = WS_INUSE;
180         firefunc();
181         weapon_action(self.weapon, WR_UPDATECOUNTS); // update ammo now
182 };
183
184 void(entity ent, float recoil) weapon_recoil =
185 {
186         ent.punchangle = (randomvec() + '-1 0 0')*recoil;
187         ent.punchangle_z = 0; // don't want roll
188         if (recoil > 3) // push back if large recoil
189                 ent.velocity = ent.velocity - normalize(ent.shotdir)*recoil*25;
190 };
191
192 void(float fr, float t, void() func) weapon_thinkf =
193 {
194         if (fr >= 0)
195                 if (self.weaponentity != world)
196                         self.weaponentity.frame = fr;
197         // VorteX: haste can be added here
198         self.weapon_nextthink = time + t;
199         self.weapon_think = func;
200 };
201
202 void(float spd, vector org) weapon_boblayer1 =
203 {
204         // VorteX: haste can be added here
205         self.weaponentity.pos1 =org;
206         self.weaponentity.lip = spd;
207 };