2 ===========================================================================
4 CLIENT WEAPONSYSTEM CODE
5 Bring back W_Weaponframe
7 ===========================================================================
10 vector() W_TrueAim = {
12 traceline(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_homing_missile"))
41 //if(self.owner.weapon == WEP_ELECTRO && cvar("g_homing_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.exteriorweaponentity != self)
114 if (self.cnt != self.owner.weaponentity.modelindex || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag)
116 self.cnt = self.owner.weaponentity.modelindex;
117 self.dmg = self.owner.modelindex;
118 self.deadflag = self.owner.deadflag;
119 if (self.owner.deadflag) return;
120 else if (self.owner.weapon == WEP_LASER) setmodel(self, "models/weapons/v_laser.md3");
121 else if (self.owner.weapon == WEP_SHOTGUN) setmodel(self, "models/weapons/v_shotgun.md3");
122 else if (self.owner.weapon == WEP_UZI) setmodel(self, "models/weapons/v_uzi.md3");
123 else if (self.owner.weapon == WEP_GRENADE_LAUNCHER) setmodel(self, "models/weapons/v_gl.md3");
124 else if (self.owner.weapon == WEP_ELECTRO) setmodel(self, "models/weapons/v_electro.md3");
125 else if (self.owner.weapon == WEP_CRYLINK) setmodel(self, "models/weapons/v_crylink.md3");
126 else if (self.owner.weapon == WEP_NEX) setmodel(self, "models/weapons/v_nex.md3");
127 else if (self.owner.weapon == WEP_HAGAR) setmodel(self, "models/weapons/v_hagar.md3");
128 else if (self.owner.weapon == WEP_ROCKET_LAUNCHER) setmodel(self, "models/weapons/v_rl.md3");
129 setattachment(self, self.owner, "bip01 r hand");
130 // if that didn't find a tag, hide the exterior weapon model
134 self.effects = self.owner.weaponentity.effects;
137 // spawning weaponentity for client
138 void() CL_SpawnWeaponentity =
140 if (self.weaponentity)
145 self.weaponentity = spawn();
146 self.weaponentity.solid = SOLID_NOT;
147 self.weaponentity.owner = self;
148 self.weaponentity.weaponentity = self.weaponentity;
149 setmodel(self.weaponentity, "");
150 self.weaponentity.origin = '0 0 0';
151 self.weaponentity.angles = '0 0 0';
152 self.weaponentity.viewmodelforclient = self;
153 self.weaponentity.flags = 0;
154 self.weaponentity.think = CL_Weaponentity_Think;
155 self.weaponentity.nextthink = time;
157 self.exteriorweaponentity = spawn();
158 self.exteriorweaponentity.solid = SOLID_NOT;
159 self.exteriorweaponentity.exteriorweaponentity = self.exteriorweaponentity;
160 self.exteriorweaponentity.owner = self;
161 self.exteriorweaponentity.origin = '0 0 0';
162 self.exteriorweaponentity.angles = '0 0 0';
163 self.exteriorweaponentity.think = CL_ExteriorWeaponentity_Think;
164 self.exteriorweaponentity.nextthink = time;
167 // convertion from index (= impulse) to flag in .items
168 float(float index) weapon_translateindextoflag =
170 if (index == WEP_LASER)
172 else if (index == WEP_SHOTGUN)
174 else if (index == WEP_UZI)
176 else if (index == WEP_GRENADE_LAUNCHER)
177 return IT_GRENADE_LAUNCHER;
178 else if (index == WEP_ELECTRO)
180 else if (index == WEP_CRYLINK)
182 else if (index == WEP_NEX)
184 else if (index == WEP_HAGAR)
186 else if (index == WEP_ROCKET_LAUNCHER)
187 return IT_ROCKET_LAUNCHER;
188 else if (index == WEP_LASER)
194 float(entity cl, float wpn, float andammo) client_hasweapon =
196 local float itemcode;
197 local entity oldself;
199 weapon_hasammo = TRUE;
200 if (wpn < WEP_FIRST || wpn > WEP_LAST)
202 itemcode = weapon_translateindextoflag(wpn);
203 if (cl.items & itemcode)
209 weapon_action(wpn, WR_CHECKAMMO);
223 weapon_action(self.weapon, WR_CLEAR);
224 if (self.weapon != -1)
226 if (self.weaponentity)
228 self.weaponentity.state = WS_CLEAR;
229 setmodel(self.weaponentity, "");
230 self.weaponentity.effects = 0;
236 self.weaponentity.state = WS_READY;
237 weapon_action(self.weapon, WR_IDLE);
240 // FIXME: add qw-style client-custom weaponrating (cl_weaponrating)?
241 float(entity e) w_getbestweapon
242 {// add new weapons here
243 if (client_hasweapon(e, WEP_ROCKET_LAUNCHER, TRUE))
244 return WEP_ROCKET_LAUNCHER;
245 else if (client_hasweapon(e, WEP_NEX, TRUE))
247 else if (client_hasweapon(e, WEP_HAGAR, TRUE))
249 else if (client_hasweapon(e, WEP_GRENADE_LAUNCHER, TRUE))
250 return WEP_GRENADE_LAUNCHER;
251 else if (client_hasweapon(e, WEP_ELECTRO, TRUE))
253 else if (client_hasweapon(e, WEP_CRYLINK, TRUE))
255 else if (client_hasweapon(e, WEP_UZI, TRUE))
257 else if (client_hasweapon(e, WEP_SHOTGUN, TRUE))
259 else if (client_hasweapon(e, WEP_LASER, FALSE))
265 // Setup weapon for client (after this raise frame will be launched)
266 void(float windex, string wmodel, float hudammo) weapon_setup =
268 local string weaponmdl;
270 self.items = self.items - (self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS));
271 self.items = self.items | hudammo;
273 self.weapon = windex;
277 weaponmdl = strzone(strcat("models/weapons/", wmodel));
278 setmodel(self.weaponentity, weaponmdl);
280 // VorteX: update visible weapon
281 // CL_ViswepUpdate();
285 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
286 void(float x, float y, float z) weapon_shotdir =
288 makevectors(self.v_angle);
289 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;
290 self.shotdir = aim(self, 1000);
293 // perform weapon to attack (weaponstate and attack_finished check is here)
294 void(float() checkfunc1, float() checkfunc2, void() firefunc, float atktime) weapon_prepareattack =
299 self.switchweapon = w_getbestweapon(self);
302 // Don't do shot if previos attack not finished
303 if (time < self.attack_finished)
305 // Can't do shot if changing weapon
306 if (self.weaponentity.state != WS_READY)
309 self.attack_finished = time + atktime;
313 // perform weapon attack
314 void(float() checkfunc1, float() checkfunc2, void() firefunc) weapon_doattack
319 self.switchweapon = w_getbestweapon(self);
322 self.weaponentity.state = WS_INUSE;
324 weapon_action(self.weapon, WR_UPDATECOUNTS); // update ammo now
327 void(entity ent, float recoil) weapon_recoil =
329 ent.punchangle = (randomvec() + '-1 0 0')*recoil;
330 ent.punchangle_z = 0; // don't want roll
331 if (recoil > 3) // push back if large recoil
332 ent.velocity = ent.velocity - normalize(ent.shotdir)*recoil*25;
335 void(float fr, float t, void() func) weapon_thinkf =
339 if (self.weaponentity != world)
340 self.weaponentity.frame = fr;
343 if(cvar("g_runematch"))
345 if(self.runes & RUNE_SPEED)
347 if(self.runes & CURSE_SLOW)
348 t = t * cvar("g_balance_rune_speed_combo_atkrate");
350 t = t * cvar("g_balance_rune_speed_atkrate");
352 else if(self.runes & CURSE_SLOW)
354 t = t * cvar("g_balance_curse_slow_atkrate");
358 // VorteX: haste can be added here
359 self.weapon_nextthink = time + t;
360 self.weapon_think = func;
363 void(float spd, vector org) weapon_boblayer1 =
365 // VorteX: haste can be added here
366 self.weaponentity.pos1 =org;
367 self.weaponentity.lip = spd;