2 ===========================================================================
4 CLIENT WEAPONSYSTEM CODE
5 Bring back W_Weaponframe
7 ===========================================================================
10 void() CL_Weaponentity_Think =
12 self.nextthink = time;
13 if (self.owner.weaponentity != self)
18 self.effects = self.owner.effects;
19 self.alpha = self.owner.alpha;
22 void() CL_ExteriorWeaponentity_Think =
24 self.nextthink = time;
25 if (self.owner.exteriorweaponentity != self)
30 if (self.cnt != self.owner.weaponentity.modelindex || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag)
32 self.cnt = self.owner.weaponentity.modelindex;
33 self.dmg = self.owner.modelindex;
34 self.deadflag = self.owner.deadflag;
35 if (self.owner.deadflag) self.model = "";
36 else if (self.owner.weapon == WEP_LASER) setmodel(self, "models/weapons/v_laser.md3");
37 else if (self.owner.weapon == WEP_SHOTGUN) setmodel(self, "models/weapons/v_shotgun.md3");
38 else if (self.owner.weapon == WEP_UZI) setmodel(self, "models/weapons/v_uzi.md3");
39 else if (self.owner.weapon == WEP_GRENADE_LAUNCHER) setmodel(self, "models/weapons/v_gl.md3");
40 else if (self.owner.weapon == WEP_ELECTRO) setmodel(self, "models/weapons/v_electro.md3");
41 else if (self.owner.weapon == WEP_CRYLINK) setmodel(self, "models/weapons/v_crylink.md3");
42 else if (self.owner.weapon == WEP_NEX) setmodel(self, "models/weapons/v_nex.md3");
43 else if (self.owner.weapon == WEP_HAGAR) setmodel(self, "models/weapons/v_hagar.md3");
44 else if (self.owner.weapon == WEP_ROCKET_LAUNCHER) setmodel(self, "models/weapons/v_rl.md3");
45 setattachment(self, self.owner, "bip01 r hand");
46 // if that didn't find a tag, hide the exterior weapon model
50 self.effects = self.owner.weaponentity.effects;
53 // spawning weaponentity for client
54 void() CL_SpawnWeaponentity =
56 if (self.weaponentity)
61 self.weaponentity = spawn();
62 self.weaponentity.solid = SOLID_NOT;
63 self.weaponentity.owner = self;
64 self.weaponentity.weaponentity = self.weaponentity;
65 setmodel(self.weaponentity, "");
66 self.weaponentity.origin = '0 0 0';
67 self.weaponentity.angles = '0 0 0';
68 self.weaponentity.viewmodelforclient = self;
69 self.weaponentity.flags = 0;
70 self.weaponentity.think = CL_Weaponentity_Think;
71 self.weaponentity.nextthink = time;
73 self.exteriorweaponentity = spawn();
74 self.exteriorweaponentity.solid = SOLID_NOT;
75 self.exteriorweaponentity.exteriorweaponentity = self.exteriorweaponentity;
76 self.exteriorweaponentity.owner = self;
77 self.exteriorweaponentity.origin = '0 0 0';
78 self.exteriorweaponentity.angles = '0 0 0';
79 self.exteriorweaponentity.think = CL_ExteriorWeaponentity_Think;
80 self.exteriorweaponentity.nextthink = time;
83 // convertion from index (= impulse) to flag in .items
84 float(float index) weapon_translateindextoflag =
86 if (index == WEP_LASER)
88 else if (index == WEP_SHOTGUN)
90 else if (index == WEP_UZI)
92 else if (index == WEP_GRENADE_LAUNCHER)
93 return IT_GRENADE_LAUNCHER;
94 else if (index == WEP_ELECTRO)
96 else if (index == WEP_CRYLINK)
98 else if (index == WEP_NEX)
100 else if (index == WEP_HAGAR)
102 else if (index == WEP_ROCKET_LAUNCHER)
103 return IT_ROCKET_LAUNCHER;
107 float(entity cl, float wpn, float andammo) client_hasweapon =
109 local float itemcode;
110 local entity oldself;
112 weapon_hasammo = TRUE;
113 if (wpn < WEP_FIRST || wpn > WEP_LAST)
115 itemcode = weapon_translateindextoflag(wpn);
116 if (cl.items & itemcode)
122 weapon_action(wpn, WR_CHECKAMMO);
136 weapon_action(self.weapon, WR_CLEAR);
137 if (self.weapon != -1)
139 if (self.weaponentity)
141 self.weaponentity.state = WS_CLEAR;
142 setmodel(self.weaponentity, "");
143 self.weaponentity.effects = 0;
149 self.weaponentity.state = WS_READY;
150 weapon_action(self.weapon, WR_IDLE);
153 // FIXME: add qw-style client-custom weaponrating (cl_weaponrating)?
154 float(entity e) w_getbestweapon
155 {// add new weapons here
156 if (client_hasweapon(e, WEP_ROCKET_LAUNCHER, TRUE))
157 return WEP_ROCKET_LAUNCHER;
158 else if (client_hasweapon(e, WEP_NEX, TRUE))
160 else if (client_hasweapon(e, WEP_HAGAR, TRUE))
162 else if (client_hasweapon(e, WEP_GRENADE_LAUNCHER, TRUE))
163 return WEP_GRENADE_LAUNCHER;
164 else if (client_hasweapon(e, WEP_ELECTRO, TRUE))
166 else if (client_hasweapon(e, WEP_CRYLINK, TRUE))
168 else if (client_hasweapon(e, WEP_UZI, TRUE))
170 else if (client_hasweapon(e, WEP_SHOTGUN, TRUE))
174 weapon_hasammo = TRUE;
179 // Setup weapon for client (after this raise frame will be launched)
180 void(float windex, string wmodel, float hudammo) weapon_setup =
182 local string weaponmdl;
184 self.items = self.items - (self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS));
185 self.items = self.items | hudammo;
187 self.weapon = windex;
191 weaponmdl = strzone(strcat("models/weapons/", wmodel));
192 setmodel(self.weaponentity, weaponmdl);
194 // VorteX: update visible weapon
195 // CL_ViswepUpdate();
199 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
200 void(float x, float y, float z) weapon_shotdir =
202 makevectors(self.v_angle);
203 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;
204 self.shotdir = aim(self, 1000);
207 // perform weapon to attack (weaponstate and attack_finished check is here)
208 void(float() checkfunc1, float() checkfunc2, void() firefunc, float atktime) weapon_prepareattack =
210 // Change to best weapon if failed
211 if ((cvar("g_instagib") == 0) && (cvar("g_rocketarena") == 0))
216 self.switchweapon = w_getbestweapon(self);
220 // Don't do shot if previos attack not finished
221 if (time < self.attack_finished)
223 // Can't do shot if changing weapon
224 if (self.weaponentity.state != WS_READY)
227 self.attack_finished = time + atktime;
231 // perform weapon attack
232 void(float() checkfunc1, float() checkfunc2, void() firefunc) weapon_doattack
234 // Change to best weapon if failed
235 if ((cvar("g_instagib") == 0) && (cvar("g_rocketarena") == 0))
240 self.switchweapon = w_getbestweapon(self);
244 self.weaponentity.state = WS_INUSE;
246 weapon_action(self.weapon, WR_UPDATECOUNTS); // update ammo now
249 void(entity ent, float recoil) weapon_recoil =
251 ent.punchangle = (randomvec() + '-1 0 0')*recoil;
252 ent.punchangle_z = 0; // don't want roll
253 if (recoil > 3) // push back if large recoil
254 ent.velocity = ent.velocity - normalize(ent.shotdir)*recoil*25;
257 void(float fr, float t, void() func) weapon_thinkf =
261 if (self.weaponentity != world)
262 self.weaponentity.frame = fr;
265 if(cvar("g_runematch"))
267 if(self.runes & RUNE_SPEED)
269 if(self.runes & CURSE_SLOW)
270 t = t * cvar("g_balance_rune_speed_combo_atkrate");
272 t = t * cvar("g_balance_rune_speed_atkrate");
274 else if(self.runes & CURSE_SLOW)
276 t = t * cvar("g_balance_curse_slow_atkrate");
280 // VorteX: haste can be added here
281 self.weapon_nextthink = time + t;
282 self.weapon_think = func;
285 void(float spd, vector org) weapon_boblayer1 =
287 // VorteX: haste can be added here
288 self.weaponentity.pos1 =org;
289 self.weaponentity.lip = spd;