]> icculus.org git repositories - divverent/nexuiz.git/blob - qcsrc/gamec/cl_weaponsystem.c
Updated powerup models
[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 void() CL_Weaponentity_Think =
11 {
12         self.nextthink = time;
13         if (self.owner.weaponentity != self)
14         {
15                 remove(self);
16                 return;
17         }
18 };
19
20 void() CL_ExteriorWeaponentity_Think =
21 {
22         self.nextthink = time;
23         if (self.owner.exteriorweaponentity != self)
24         {
25                 remove(self);
26                 return;
27         }
28         if (self.modelindex != self.owner.weaponentity.modelindex || self.dmg != self.owner.modelindex)
29         {
30                 self.modelindex = self.owner.weaponentity.modelindex;
31                 self.model = "models/weapons/w_shotgun.md3";
32                 self.dmg = self.owner.modelindex;
33                 setattachment(self, self.owner, "weapon");
34                 // if that didn't find a tag, hide the exterior weapon model
35                 if (!self.tag_index)
36                         self.model = "";
37         }
38         self.frame = self.owner.weaponentity.frame;
39         self.effects = self.owner.weaponentity.effects;
40 };
41
42 // spawning weaponentity for client
43 void() CL_SpawnWeaponentity =
44 {
45         if (self.weaponentity)
46         {
47                 w_clear();
48                 return;
49         }
50         self.weaponentity = spawn();
51         self.weaponentity.solid = SOLID_NOT;
52         self.weaponentity.owner = self;
53         self.weaponentity.weaponentity = self.weaponentity;
54         setmodel(self.weaponentity, "");
55         self.weaponentity.origin = '0 0 0';
56         self.weaponentity.angles = '0 0 0';
57         self.weaponentity.viewmodelforclient = self;
58         self.weaponentity.flags = 0;
59         self.weaponentity.think = CL_Weaponentity_Think;
60         self.weaponentity.nextthink = time;
61
62         self.exteriorweaponentity = spawn();
63         self.exteriorweaponentity.solid = SOLID_NOT;
64         self.exteriorweaponentity.exteriorweaponentity = self.exteriorweaponentity;
65         self.exteriorweaponentity.owner = self;
66         self.exteriorweaponentity.origin = '0 0 0';
67         self.exteriorweaponentity.angles = '0 0 0';
68         self.exteriorweaponentity.think = CL_ExteriorWeaponentity_Think;
69         self.exteriorweaponentity.nextthink = time;
70 };
71
72 // convertion from index (= impulse) to flag in .items
73 float(float index) weapon_translateindextoflag =
74 {
75         if (index == WEP_LASER)
76                 return IT_LASER;
77         else if (index == WEP_SHOTGUN)
78                 return IT_SHOTGUN;
79         else if (index == WEP_UZI)
80                 return IT_UZI;
81         else if (index == WEP_GRENADE_LAUNCHER)
82                 return IT_GRENADE_LAUNCHER;
83         else if (index == WEP_ELECTRO)
84                 return IT_ELECTRO;
85         else if (index == WEP_CRYLINK)
86                 return IT_CRYLINK;
87         else if (index == WEP_NEX)
88                 return IT_NEX;
89         else if (index == WEP_HAGAR)
90                 return IT_HAGAR;
91         else if (index == WEP_ROCKET_LAUNCHER)
92                 return IT_ROCKET_LAUNCHER;
93         return IT_LASER;
94 };
95
96 float(entity cl, float wpn, float andammo) client_hasweapon =
97 {
98         local float itemcode;
99         local entity oldself;
100
101         weapon_hasammo = TRUE;
102         if (wpn < WEP_FIRST || wpn > WEP_LAST)
103                 return FALSE;
104         itemcode = weapon_translateindextoflag(wpn);
105         if (cl.items & itemcode)
106         {
107                 if (andammo)
108                 {
109                         oldself = self;
110                         self = cl;
111                         weapon_action(wpn, WR_CHECKAMMO);
112                         self = oldself;
113                         if (weapon_hasammo)
114                                 return TRUE;
115                         return FALSE;
116                 }
117                 return TRUE;
118         }
119         return FALSE;
120 };
121
122 // Weapon subs
123 void() w_clear =
124 {
125         weapon_action(self.weapon, WR_CLEAR);
126         if (self.weapon != -1)
127                 self.weapon = 0;
128         if (self.weaponentity)
129         {
130                 self.weaponentity.state = WS_CLEAR;
131                 setmodel(self.weaponentity, "");
132                 self.weaponentity.effects = 0;
133         }
134 };
135
136 void() w_ready =
137 {
138         self.weaponentity.state = WS_READY;
139         weapon_action(self.weapon, WR_IDLE);
140 };
141
142 // FIXME: add qw-style client-custom weaponrating (cl_weaponrating)?
143 float(entity e) w_getbestweapon
144 {// add new weapons here
145         if (client_hasweapon(e, WEP_ROCKET_LAUNCHER, TRUE))
146                 return WEP_ROCKET_LAUNCHER;
147         else if (client_hasweapon(e, WEP_NEX, TRUE))
148                 return WEP_NEX;
149         else if (client_hasweapon(e, WEP_HAGAR, TRUE))
150                 return WEP_HAGAR;
151         else if (client_hasweapon(e, WEP_GRENADE_LAUNCHER, TRUE))
152                 return WEP_GRENADE_LAUNCHER;
153         else if (client_hasweapon(e, WEP_ELECTRO, TRUE))
154                 return WEP_ELECTRO;
155         else if (client_hasweapon(e, WEP_CRYLINK, TRUE))
156                 return WEP_CRYLINK;
157         else if (client_hasweapon(e, WEP_UZI, TRUE))
158                 return WEP_UZI;
159         else if (client_hasweapon(e, WEP_SHOTGUN, TRUE))
160                 return WEP_SHOTGUN;
161         else
162         {
163                 weapon_hasammo = TRUE;
164                 return WEP_LASER;
165         }
166 };
167
168 // Setup weapon for client (after this raise frame will be launched)
169 void(float windex, string wmodel, float hudammo) weapon_setup =
170 {
171         local string wdir, weaponmdl;
172
173         self.items = self.items - (self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS));
174         self.items = self.items | hudammo;
175
176         self.weapon = windex;
177
178         if (wmodel != "")
179         {
180                 weaponmdl = strzone(strcat("models/weapons/", wmodel));
181                 setmodel(self.weaponentity, weaponmdl);
182         }
183         // VorteX: update visible weapon
184         // CL_ViswepUpdate();
185 };
186
187 // shot direction
188 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
189 void(float x, float y, float z) weapon_shotdir =
190 {
191         makevectors(self.v_angle);
192         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;
193         self.shotdir = aim(self, 1000);
194 };
195
196 // perform weapon to attack (weaponstate and attack_finished check is here)
197 void(float() checkfunc1, float() checkfunc2, void() firefunc, float atktime) weapon_prepareattack =
198 {
199         // Change to best weapon if failed
200         if ((cvar("g_instagib") == 0) && (cvar("g_rocketarena") == 0))
201         {
202                 if (!checkfunc1())
203                 {
204                         if (!checkfunc2())
205                                 self.switchweapon = w_getbestweapon(self);
206                         return;
207                 }
208         }
209         // Don't do shot if previos attack  not finished
210                 if (time < self.attack_finished)
211                         return;
212         // Can't do shot if changing weapon
213                 if (self.weaponentity.state != WS_READY)
214                         return;
215
216         self.attack_finished = time + atktime;
217         firefunc();
218 };
219
220 // perform weapon attack
221 void(float() checkfunc1, float() checkfunc2, void() firefunc) weapon_doattack
222 {
223         // Change to best weapon if failed
224         if ((cvar("g_instagib") == 0) && (cvar("g_rocketarena") == 0))
225         {
226                 if (!checkfunc1())
227                 {
228                         if (!checkfunc2())
229                                 self.switchweapon = w_getbestweapon(self);
230                         return;
231                 }
232         }
233         self.weaponentity.state = WS_INUSE;
234         firefunc();
235         weapon_action(self.weapon, WR_UPDATECOUNTS); // update ammo now
236 };
237
238 void(entity ent, float recoil) weapon_recoil =
239 {
240         ent.punchangle = (randomvec() + '-1 0 0')*recoil;
241         ent.punchangle_z = 0; // don't want roll
242         if (recoil > 3) // push back if large recoil
243                 ent.velocity = ent.velocity - normalize(ent.shotdir)*recoil*25;
244 };
245
246 void(float fr, float t, void() func) weapon_thinkf =
247 {
248         if (fr >= 0)
249                 if (self.weaponentity != world)
250                         self.weaponentity.frame = fr;
251         // VorteX: haste can be added here
252         self.weapon_nextthink = time + t;
253         self.weapon_think = func;
254 };
255
256 void(float spd, vector org) weapon_boblayer1 =
257 {
258         // VorteX: haste can be added here
259         self.weaponentity.pos1 =org;
260         self.weaponentity.lip = spd;
261 };