2 ===========================================================================
4 CLIENT WEAPONSYSTEM CODE
5 Bring back W_Weaponframe
7 ===========================================================================
9 // definitions (move this part to defs after finishing of weapon system)
12 void(float wpn, float wrequest) weapon_action;
14 // VorteX: standalone think for weapons, so normal think on weaponentity can be reserved by weaponflashes which needs update even player dies)
15 .float weapon_nextthink;
17 .vector shotdir, shotorg;
18 float weapon_hasammo; // sets by WR_CHECKAMMO request
20 // weapon states (self.weaponentity.state)
21 float WS_CLEAR = 0; // no weapon selected
22 float WS_RAISE = 1; // raise frame
23 float WS_DROP = 2; // deselecting frame
24 float WS_INUSE = 3; // fire state
25 float WS_READY = 4; // idle frame
28 float WR_SETUP = 1; // setup weapon data
29 float WR_UPDATECOUNTS = 2; // update ammo display
30 float WR_IDLE = 3; // idle frame
31 float WR_DROP = 4; // deselect frame
32 float WR_RAISE = 5; // select frame
33 float WR_FIRE1 = 6; // primary fire frame
34 float WR_FIRE2 = 7; // secondary fire
35 float WR_FIRE3 = 8; // third fire
36 float WR_CHECKAMMO = 9; // checks ammo for weapon
37 float WR_CLEAR = 10; // runs afted deselecting frames, remove weapon parts (if presented). This useful for quake3-style chaingun
40 float WEP_LASER = 1; // float IT_LASER = 4096;
41 float WEP_SHOTGUN = 2; // float IT_SHOTGUN = 1;
42 float WEP_UZI = 3; // float IT_UZI = 2;
43 float WEP_GRENADE_LAUNCHER = 4; // float IT_GRENADE_LAUNCHER = 4;
44 float WEP_ELECTRO = 5; // float IT_ELECTRO = 8;
45 float WEP_CRYLINK = 6; // float IT_CRYLINK = 16;
46 float WEP_NEX = 7; // float IT_NEX = 32;
47 float WEP_HAGAR = 8; // float IT_HAGAR = 64;
48 float WEP_ROCKET_LAUNCHER = 9; // float IT_ROCKET_LAUNCHER = 128;
50 // For weapon cycling commands
54 // spawning weaponentity for client
55 void() CL_SpawnWeaponentity =
57 if (self.weaponentity)
62 self.weaponentity = spawn();
63 self.weaponentity.solid = SOLID_NOT;
64 self.weaponentity.owner = self;
65 self.weaponentity.weaponentity = self.weaponentity;
66 setmodel(self.weaponentity, "");
67 self.weaponentity.origin = '0 0 0';
68 self.weaponentity.angles = '0 0 0';
69 self.weaponentity.viewmodelforclient = self;
70 self.weaponentity.flags = 0;
73 // convertion from index (= impulse) to flag in .items
74 float(float index) weapon_translateindextoflag =
76 if (index == WEP_LASER)
78 else if (index == WEP_SHOTGUN)
80 else if (index == WEP_UZI)
82 else if (index == WEP_GRENADE_LAUNCHER)
83 return IT_GRENADE_LAUNCHER;
84 else if (index == WEP_ELECTRO)
86 else if (index == WEP_CRYLINK)
88 else if (index == WEP_NEX)
90 else if (index == WEP_HAGAR)
92 else if (index == WEP_ROCKET_LAUNCHER)
93 return IT_ROCKET_LAUNCHER;
96 float(entity cl, float wpn, float andammo) client_hasweapon =
100 itemcode = weapon_translateindextoflag(wpn);
101 if (cl.items & itemcode)
105 weapon_action(wpn, WR_CHECKAMMO);
118 weapon_action(self.weapon, WR_CLEAR);
119 if (self.weapon != -1)
121 self.weaponentity.state = WS_CLEAR;
122 setmodel(self.weaponentity, "");
123 self.weaponentity.effects = 0;
128 self.weaponentity.state = WS_READY;
129 weapon_action(self.weapon, WR_IDLE);
132 // FIXME: add qw-style client-custom weaponrating (cl_weaponrating)?
134 {// add new weapons here
135 weapon_hasammo = TRUE;
136 if (client_hasweapon(self, WEP_ROCKET_LAUNCHER, TRUE))
137 self.switchweapon = WEP_ROCKET_LAUNCHER;
138 else if (client_hasweapon(self, WEP_NEX, TRUE))
139 self.switchweapon = WEP_NEX;
140 else if (client_hasweapon(self, WEP_HAGAR, TRUE))
141 self.switchweapon = WEP_HAGAR;
142 else if (client_hasweapon(self, WEP_GRENADE_LAUNCHER, TRUE))
143 self.switchweapon = WEP_GRENADE_LAUNCHER;
144 else if (client_hasweapon(self, WEP_ELECTRO, TRUE))
145 self.switchweapon = WEP_ELECTRO;
146 else if (client_hasweapon(self, WEP_CRYLINK, TRUE))
147 self.switchweapon = WEP_CRYLINK;
148 else if (client_hasweapon(self, WEP_UZI, TRUE))
149 self.switchweapon = WEP_UZI;
150 else if (client_hasweapon(self, WEP_SHOTGUN, TRUE))
151 self.switchweapon = WEP_SHOTGUN;
153 self.switchweapon = WEP_LASER;
156 // Setup weapon for client (after this raise frame will be launched)
157 void(float windex, string wmodel, float hudammo) weapon_setup =
159 local string wdir, weaponmdl;
161 self.items = self.items - (self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS));
162 self.items = self.items | hudammo;
164 self.weapon = windex;
168 weaponmdl = strzone(strcat("models/weapons/", wmodel));
169 setmodel(self.weaponentity, weaponmdl);
171 // VorteX: update visible weapon
172 // CL_ViswepUpdate();
176 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
177 void(float x, float y, float z) weapon_shotdir =
179 makevectors(self.v_angle);
180 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;
181 self.shotdir = aim(self, 1000);
184 // perform weapon to attack (weaponstate and attack_finished check is here)
185 void(float() checkfunc1, float() checkfunc2, void() firefunc, float atktime) weapon_prepareattack =
187 // Change to best weapon if failed
188 if (!(game & GAME_INSTAGIB) && !(game & GAME_ROCKET_ARENA))
197 // Don't do shot if previos attack not finished
198 if (!(game & GAME_INSANE))
199 if (time < self.attack_finished)
201 // Can't do shot if changing weapon
202 if (!(game & GAME_INSANE))
203 if (self.weaponentity.state != WS_READY)
206 self.attack_finished = time + atktime;
210 // perform weapon attack
211 void(float() checkfunc1, float() checkfunc2, void() firefunc) weapon_doattack
213 // Change to best weapon if failed
214 if (!(game & GAME_INSTAGIB) && !(game & GAME_ROCKET_ARENA))
223 self.weaponentity.state = WS_INUSE;
225 weapon_action(self.weapon, WR_UPDATECOUNTS); // update ammo now
228 void(entity ent, float recoil) weapon_recoil =
230 ent.punchangle = (randomvec() + '-1 0 0')*recoil;
231 ent.punchangle_z = 0; // don't want roll
232 if (recoil > 3) // push back if large recoil
233 ent.velocity = ent.velocity - normalize(ent.shotdir)*recoil*25;
236 void(float fr, float t, void() func) weapon_thinkf =
239 if (self.weaponentity != world)
240 self.weaponentity.frame = fr;
241 // VorteX: haste can be added here
242 self.weapon_nextthink = time + t;
243 self.weapon_think = func;
246 void(float spd, vector org) weapon_boblayer1 =
248 // VorteX: haste can be added here
249 self.weaponentity.pos1 =org;
250 self.weaponentity.lip = spd;