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_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
244 if (client_hasweapon(e, WEP_ROCKET_LAUNCHER, TRUE))
245 return WEP_ROCKET_LAUNCHER;
246 else if (client_hasweapon(e, WEP_NEX, TRUE))
248 else if (client_hasweapon(e, WEP_HAGAR, TRUE))
250 else if (client_hasweapon(e, WEP_GRENADE_LAUNCHER, TRUE))
251 return WEP_GRENADE_LAUNCHER;
252 else if (client_hasweapon(e, WEP_ELECTRO, TRUE))
254 else if (client_hasweapon(e, WEP_CRYLINK, TRUE))
256 else if (client_hasweapon(e, WEP_UZI, TRUE))
258 else if (client_hasweapon(e, WEP_SHOTGUN, TRUE))
260 else if (client_hasweapon(e, WEP_LASER, FALSE))
266 // Setup weapon for client (after this raise frame will be launched)
267 void(float windex, string wmodel, float hudammo) weapon_setup =
269 local string weaponmdl;
271 self.items = self.items - (self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS));
272 self.items = self.items | hudammo;
274 self.weapon = windex;
278 weaponmdl = strzone(strcat("models/weapons/", wmodel));
279 setmodel(self.weaponentity, weaponmdl);
281 // VorteX: update visible weapon
282 // CL_ViswepUpdate();
286 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
287 void(float x, float y, float z) weapon_shotdir =
289 makevectors(self.v_angle);
290 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;
291 self.shotdir = aim(self, 1000);
294 // perform weapon to attack (weaponstate and attack_finished check is here)
295 void(float() checkfunc1, float() checkfunc2, void() firefunc, float atktime) weapon_prepareattack =
300 self.switchweapon = w_getbestweapon(self);
303 // Don't do shot if previos attack not finished
304 if (time < self.attack_finished)
306 // Can't do shot if changing weapon
307 if (self.weaponentity.state != WS_READY)
310 self.attack_finished = time + atktime;
314 // perform weapon attack
315 void(float() checkfunc1, float() checkfunc2, void() firefunc) weapon_doattack
320 self.switchweapon = w_getbestweapon(self);
323 self.weaponentity.state = WS_INUSE;
325 weapon_action(self.weapon, WR_UPDATECOUNTS); // update ammo now
328 void(entity ent, float recoil) weapon_recoil =
330 ent.punchangle = (randomvec() + '-1 0 0')*recoil;
331 ent.punchangle_z = 0; // don't want roll
332 if (recoil > 3) // push back if large recoil
333 ent.velocity = ent.velocity - normalize(ent.shotdir)*recoil*25;
336 void(float fr, float t, void() func) weapon_thinkf =
340 if (self.weaponentity != world)
341 self.weaponentity.frame = fr;
344 if(cvar("g_runematch"))
346 if(self.runes & RUNE_SPEED)
348 if(self.runes & CURSE_SLOW)
349 t = t * cvar("g_balance_rune_speed_combo_atkrate");
351 t = t * cvar("g_balance_rune_speed_atkrate");
353 else if(self.runes & CURSE_SLOW)
355 t = t * cvar("g_balance_curse_slow_atkrate");
359 // VorteX: haste can be added here
360 self.weapon_nextthink = time + t;
361 self.weapon_think = func;
364 void(float spd, vector org) weapon_boblayer1 =
366 // VorteX: haste can be added here
367 self.weaponentity.pos1 =org;
368 self.weaponentity.lip = spd;