2 ===========================================================================
4 CLIENT WEAPONSYSTEM CODE
5 Bring back W_Weaponframe
7 ===========================================================================
10 vector() W_TrueAim = {
12 traceline_hitcorpse(self,self.origin + self.view_ofs,self.origin + self.view_ofs + v_forward * 4096,FALSE,self);
14 if ((self.weapon == WEP_NEX || self.weapon == WEP_SHOTGUN || self.weapon == WEP_UZI) && cvar("g_antilag"))
16 // if aiming at a player and the original trace won't hit that player
17 // anymore, try aiming at the player's new position
19 if(self.cursor_trace_ent)
20 if(self.cursor_trace_ent.takedamage)
21 if(trace_ent != self.cursor_trace_ent) {
22 return self.cursor_trace_ent.origin;
30 void LaserTarget_Think()
37 // list of weapons that will use the laser, and the options that enable it
38 if(self.owner.laser_on && self.owner.weapon == WEP_ROCKET_LAUNCHER && cvar("g_laserguided_missile"))
41 //if(self.owner.weapon == WEP_ELECTRO && cvar("g_laserguided_electro"))
46 // if a laser-enabled weapon isn't selected, delete any existing laser and quit
49 // rocket launcher isn't selected, so no laser target.
50 if(self.lasertarget != world)
52 remove(self.lasertarget);
53 self.lasertarget = world;
60 // we don't have a lasertarget entity, so spawn one
61 //bprint("create laser target\n");
62 e = self.lasertarget = spawn();
63 e.owner = self.owner; // Its owner is my owner
64 e.classname = "laser_target";
65 e.movetype = MOVETYPE_NOCLIP; // don't touch things
66 setmodel(e, "models/laser_dot.mdl"); // what it looks like
67 e.scale = 1.25; // make it larger
68 e.alpha = 0.25; // transparency
69 e.colormod = '255 0 0' * (1/255) * 8; // change colors
70 e.effects = EF_FULLBRIGHT;
71 // make it dynamically glow
72 // you should avoid over-using this, as it can slow down the player's computer.
73 e.glow_color = 251; // red color
79 // move the laser dot to where the player is looking
81 makevectors(self.owner.v_angle); // set v_forward etc to the direction the player is looking
82 offset = '0 0 26' + v_right*3;
83 traceline(self.owner.origin + offset, self.owner.origin + offset + v_forward * 2048, FALSE, self); // trace forward until you hit something, like a player or wall
84 setorigin(e, trace_endpos + v_forward*8); // move me to where the traceline ended
85 if(trace_plane_normal != '0 0 0')
86 e.angles = vectoangles(trace_plane_normal);
88 e.angles = vectoangles(v_forward);
91 void() CL_Weaponentity_Think =
93 self.nextthink = time;
94 if (self.owner.weaponentity != self)
99 self.effects = self.owner.effects;
100 self.alpha = self.owner.alpha;
102 // create or update the lasertarget entity
106 void() CL_ExteriorWeaponentity_Think =
108 self.nextthink = time;
109 if(self.owner.deadflag != DEAD_NO)
114 if (self.owner.exteriorweaponentity != self)
119 if (self.cnt != self.owner.weaponentity.modelindex || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag)
121 self.cnt = self.owner.weaponentity.modelindex;
122 self.dmg = self.owner.modelindex;
123 self.deadflag = self.owner.deadflag;
124 if (self.owner.deadflag) return;
125 else if (self.owner.weapon == WEP_LASER) setmodel(self, "models/weapons/v_laser.md3");
126 else if (self.owner.weapon == WEP_SHOTGUN) setmodel(self, "models/weapons/v_shotgun.md3");
127 else if (self.owner.weapon == WEP_UZI) setmodel(self, "models/weapons/v_uzi.md3");
128 else if (self.owner.weapon == WEP_GRENADE_LAUNCHER) setmodel(self, "models/weapons/v_gl.md3");
129 else if (self.owner.weapon == WEP_ELECTRO) setmodel(self, "models/weapons/v_electro.md3");
130 else if (self.owner.weapon == WEP_CRYLINK) setmodel(self, "models/weapons/v_crylink.md3");
131 else if (self.owner.weapon == WEP_NEX) setmodel(self, "models/weapons/v_nex.md3");
132 else if (self.owner.weapon == WEP_HAGAR) setmodel(self, "models/weapons/v_hagar.md3");
133 else if (self.owner.weapon == WEP_ROCKET_LAUNCHER) setmodel(self, "models/weapons/v_rl.md3");
134 setattachment(self, self.owner, "bip01 r hand");
135 // if that didn't find a tag, hide the exterior weapon model
139 self.effects = self.owner.weaponentity.effects;
142 // spawning weaponentity for client
143 void() CL_SpawnWeaponentity =
145 if (self.weaponentity)
150 self.weaponentity = spawn();
151 self.weaponentity.solid = SOLID_NOT;
152 self.weaponentity.owner = self;
153 self.weaponentity.weaponentity = self.weaponentity;
154 setmodel(self.weaponentity, "");
155 self.weaponentity.origin = '0 0 0';
156 self.weaponentity.angles = '0 0 0';
157 self.weaponentity.viewmodelforclient = self;
158 self.weaponentity.flags = 0;
159 self.weaponentity.think = CL_Weaponentity_Think;
160 self.weaponentity.nextthink = time;
162 self.exteriorweaponentity = spawn();
163 self.exteriorweaponentity.solid = SOLID_NOT;
164 self.exteriorweaponentity.exteriorweaponentity = self.exteriorweaponentity;
165 self.exteriorweaponentity.owner = self;
166 self.exteriorweaponentity.origin = '0 0 0';
167 self.exteriorweaponentity.angles = '0 0 0';
168 self.exteriorweaponentity.think = CL_ExteriorWeaponentity_Think;
169 self.exteriorweaponentity.nextthink = time;
172 // convertion from index (= impulse) to flag in .items
173 float(float index) weapon_translateindextoflag =
175 if (index == WEP_LASER)
177 else if (index == WEP_SHOTGUN)
179 else if (index == WEP_UZI)
181 else if (index == WEP_GRENADE_LAUNCHER)
182 return IT_GRENADE_LAUNCHER;
183 else if (index == WEP_ELECTRO)
185 else if (index == WEP_CRYLINK)
187 else if (index == WEP_NEX)
189 else if (index == WEP_HAGAR)
191 else if (index == WEP_ROCKET_LAUNCHER)
192 return IT_ROCKET_LAUNCHER;
193 else if (index == WEP_LASER)
199 float(entity cl, float wpn, float andammo) client_hasweapon =
201 local float itemcode;
202 local entity oldself;
204 weapon_hasammo = TRUE;
205 if (wpn < WEP_FIRST || wpn > WEP_LAST)
207 itemcode = weapon_translateindextoflag(wpn);
208 if (cl.items & itemcode)
214 weapon_action(wpn, WR_CHECKAMMO);
228 weapon_action(self.weapon, WR_CLEAR);
229 if (self.weapon != -1)
231 if (self.weaponentity)
233 self.weaponentity.state = WS_CLEAR;
234 setmodel(self.weaponentity, "");
235 self.weaponentity.effects = 0;
241 self.weaponentity.state = WS_READY;
242 weapon_action(self.weapon, WR_IDLE);
245 // FIXME: add qw-style client-custom weaponrating (cl_weaponrating)?
246 float(entity e) w_getbestweapon
247 {// add new weapons here
248 if (client_hasweapon(e, WEP_ROCKET_LAUNCHER, TRUE))
249 return WEP_ROCKET_LAUNCHER;
250 else if (client_hasweapon(e, WEP_NEX, TRUE))
252 else if (client_hasweapon(e, WEP_HAGAR, TRUE))
254 else if (client_hasweapon(e, WEP_GRENADE_LAUNCHER, TRUE))
255 return WEP_GRENADE_LAUNCHER;
256 else if (client_hasweapon(e, WEP_ELECTRO, TRUE))
258 else if (client_hasweapon(e, WEP_CRYLINK, TRUE))
260 else if (client_hasweapon(e, WEP_UZI, TRUE))
262 else if (client_hasweapon(e, WEP_SHOTGUN, TRUE))
264 else if (client_hasweapon(e, WEP_LASER, FALSE))
270 // Setup weapon for client (after this raise frame will be launched)
271 void(float windex, string wmodel, float hudammo) weapon_setup =
273 local string weaponmdl;
275 self.items = self.items - (self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS));
276 self.items = self.items | hudammo;
278 self.weapon = windex;
282 weaponmdl = strzone(strcat("models/weapons/", wmodel));
283 setmodel(self.weaponentity, weaponmdl);
285 // VorteX: update visible weapon
286 // CL_ViswepUpdate();
290 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
291 void(float x, float y, float z) weapon_shotdir =
293 makevectors(self.v_angle);
294 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;
295 self.shotdir = aim(self, 1000);
298 // perform weapon to attack (weaponstate and attack_finished check is here)
299 void(float() checkfunc1, float() checkfunc2, void() firefunc, float atktime) weapon_prepareattack =
305 self.switchweapon = w_getbestweapon(self);
306 if (self.switchweapon != self.weapon)
307 self.cnt = self.weapon;
311 // Don't do shot if previos attack not finished
312 if (time < self.attack_finished)
314 // Can't do shot if changing weapon
315 if (self.weaponentity.state != WS_READY)
318 self.attack_finished = time + atktime;
322 // perform weapon attack
323 void(float() checkfunc1, float() checkfunc2, void() firefunc) weapon_doattack
329 self.switchweapon = w_getbestweapon(self);
330 if (self.switchweapon != self.weapon)
331 self.cnt = self.weapon;
335 self.weaponentity.state = WS_INUSE;
337 if (cvar("g_norecoil"))
338 self.punchangle = '0 0 0';
339 weapon_action(self.weapon, WR_UPDATECOUNTS); // update ammo now
342 void(entity ent, float recoil) weapon_recoil =
344 ent.punchangle = (randomvec() + '-1 0 0')*recoil;
345 ent.punchangle_z = 0; // don't want roll
346 if (recoil > 3) // push back if large recoil
347 ent.velocity = ent.velocity - normalize(ent.shotdir)*recoil*25;
350 void(float fr, float t, void() func) weapon_thinkf =
354 if (self.weaponentity != world)
355 self.weaponentity.frame = fr;
358 if(cvar("g_runematch"))
360 if(self.runes & RUNE_SPEED)
362 if(self.runes & CURSE_SLOW)
363 t = t * cvar("g_balance_rune_speed_combo_atkrate");
365 t = t * cvar("g_balance_rune_speed_atkrate");
367 else if(self.runes & CURSE_SLOW)
369 t = t * cvar("g_balance_curse_slow_atkrate");
373 // VorteX: haste can be added here
374 self.weapon_nextthink = time + t;
375 self.weapon_think = func;
378 void(float spd, vector org) weapon_boblayer1 =
380 // VorteX: haste can be added here
381 self.weaponentity.pos1 =org;
382 self.weaponentity.lip = spd;