4 #include "../movetypes.qh"
5 #include "../movetypes.qh"
6 #include "../prandom.qh"
7 #include "../scoreboard.qh"
8 #include "../t_items.qh"
10 #include "../../common/buffs.qh"
11 #include "../../common/constants.qh"
12 #include "../../common/stats.qh"
13 #include "../../common/util.qh"
15 #include "../../csqcmodellib/cl_model.qh"
19 const string vNULL = "gfx/vehicles/null.tga";
20 const string vFRAME = "gfx/vehicles/frame.tga";
22 const string vMODEL_SHIELD = "gfx/vehicles/vh-shield.tga";
23 const string vMODEL_BUMBLE = "gfx/vehicles/bumb.tga";
24 const string vMODEL_BUMBLE_WEAPON1 = "gfx/vehicles/bumb_lgun.tga";
25 const string vMODEL_BUMBLE_WEAPON2 = "gfx/vehicles/bumb_rgun.tga";
26 const string vMODEL_GUNNER = "gfx/vehicles/bumb_side.tga";
27 const string vMODEL_GUNNER_WEAPON1 = "gfx/vehicles/bumb_side_gun.tga";
28 const string vMODEL_RAPTOR = "gfx/vehicles/raptor.tga";
29 const string vMODEL_RAPTOR_WEAPON1 = "gfx/vehicles/raptor_guns.tga";
30 const string vMODEL_RAPTOR_WEAPON2 = "gfx/vehicles/raptor_bombs.tga";
31 const string vMODEL_SPIDER = "gfx/vehicles/sbot.tga";
32 const string vMODEL_SPIDER_WEAPON1 = "gfx/vehicles/sbot_mguns.tga";
33 const string vMODEL_SPIDER_WEAPON2 = "gfx/vehicles/sbot_rpods.tga";
34 const string vMODEL_RACER = "gfx/vehicles/waki.tga";
35 const string vMODEL_RACER_WEAPON1 = "gfx/vehicles/waki_guns.tga";
36 const string vMODEL_RACER_WEAPON2 = "gfx/vehicles/waki_rockets.tga";
38 const string vBAR_HEALTH = "gfx/vehicles/bar_up_left.tga";
39 const string vBAR_SHIELD = "gfx/vehicles/bar_dwn_left.tga";
40 const string vBAR_AMMO1 = "gfx/vehicles/bar_up_right.tga";
41 const string vBAR_AMMO2 = "gfx/vehicles/bar_dwn_right.tga";
43 const string vICON_HEALTH = "gfx/vehicles/health.tga";
44 const string vICON_SHIELD = "gfx/vehicles/shield.tga";
45 const string vICON_AMMO1 = "gfx/vehicles/bullets.tga";
46 const string vICON_AMMO2 = "gfx/vehicles/rocket.tga";
48 const string vCROSS_AIM = "gfx/vehicles/axh-special1.tga";
49 const string vCROSS_DROP = "gfx/vehicles/axh-dropcross.tga";
50 const string vCROSS_HEAL = "gfx/vehicles/axh-cross.tga";
51 const string vCROSS_HINT = "gfx/vehicles/axh-ring.tga";
52 const string vCROSS_LOCK = "gfx/vehicles/axh-bracket.tga";
53 const string vCROSS_TAG = "gfx/vehicles/axh-tag.tga";
55 const int SBRM_FIRST = 1;
56 const int SBRM_VOLLY = 1;
57 const int SBRM_GUIDE = 2;
58 const int SBRM_ARTILLERY = 3;
59 const int SBRM_LAST = 3;
61 const int RSM_FIRST = 1;
62 const int RSM_BOMB = 1;
63 const int RSM_FLARE = 2;
64 const int RSM_LAST = 2;
66 const int MAX_AXH = 4;
67 entity AuxiliaryXhairs[MAX_AXH];
68 entityclass(AuxiliaryXhair);
69 class(AuxiliaryXhair) .string axh_image;
70 class(AuxiliaryXhair) .float axh_fadetime;
71 class(AuxiliaryXhair) .float axh_drawflag;
80 void AuxiliaryXhair_Draw2D()
82 if (scoreboard_showscores)
85 vector size = draw_getimagesize(self.axh_image) * autocvar_cl_vehicles_crosshair_size;
86 vector pos = project_3d_to_2d(self.move_origin) - 0.5 * size;
88 if (!(pos.z < 0 || pos.x < 0 || pos.y < 0 || pos.x > vid_conwidth || pos.y > vid_conheight))
92 drawpic(pos, self.axh_image, size, self.colormod, self.alpha, self.axh_drawflag);
95 if(time - self.cnt > self.axh_fadetime)
96 self.draw2d = func_null;
99 void Net_AuXair2(bool bIsNew)
101 int axh_id = bound(0, ReadByte(), MAX_AXH);
102 entity axh = AuxiliaryXhairs[axh_id];
104 if(axh == world || wasfreed(axh)) // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?)
107 axh.draw2d = func_null;
108 axh.drawmask = MASK_NORMAL;
109 axh.axh_drawflag = DRAWFLAG_ADDITIVE;
110 axh.axh_fadetime = 0.1;
111 axh.axh_image = vCROSS_HINT;
114 AuxiliaryXhairs[axh_id] = axh;
117 axh.move_origin_x = ReadCoord();
118 axh.move_origin_y = ReadCoord();
119 axh.move_origin_z = ReadCoord();
120 axh.colormod_x = ReadByte() / 255;
121 axh.colormod_y = ReadByte() / 255;
122 axh.colormod_z = ReadByte() / 255;
124 axh.draw2d = AuxiliaryXhair_Draw2D;
127 void Net_VehicleSetup()
129 int hud_id = ReadByte();
132 if(hud_id > HUD_VEHICLE_LAST)
134 weapon2mode = hud_id - HUD_VEHICLE_LAST;
138 // hud_id == 0 means we exited a vehicle, so stop alarm sound/s
141 sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
142 sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
146 hud_id = bound(HUD_VEHICLE_FIRST, hud_id, HUD_VEHICLE_LAST);
148 // Init auxiliary crosshairs
150 for(i = 0; i < MAX_AXH; ++i)
152 entity axh = AuxiliaryXhairs[i];
154 if(axh != world && !wasfreed(axh)) // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?)
158 axh.draw2d = func_null;
159 axh.drawmask = MASK_NORMAL;
160 axh.axh_drawflag = DRAWFLAG_NORMAL;
161 axh.axh_fadetime = 0.1;
162 axh.axh_image = vCROSS_HINT;
164 AuxiliaryXhairs[i] = axh;
170 AuxiliaryXhairs[0].axh_image = vCROSS_HINT; // Minigun1
171 AuxiliaryXhairs[1].axh_image = vCROSS_HINT; // Minigun2
175 AuxiliaryXhairs[0].axh_image = vCROSS_LOCK; // Rocket
179 AuxiliaryXhairs[1].axh_image = vCROSS_LOCK;
183 AuxiliaryXhairs[0].axh_image = vCROSS_LOCK; // Raygun-locked
184 AuxiliaryXhairs[1].axh_image = vCROSS_TAG; // Gunner1
185 AuxiliaryXhairs[2].axh_image = vCROSS_TAG; // Gunner2
188 case HUD_BUMBLEBEE_GUN:
189 AuxiliaryXhairs[0].axh_image = vCROSS_LOCK; // Plasma cannons
190 AuxiliaryXhairs[1].axh_image = vCROSS_LOCK; // Raygun
195 void Vehicles_drawHUD(
202 bool shouldDrawBumbleGunnerCrosshair,
203 bool shouldDrawRaptorBombCrosshair)
205 if(autocvar_r_letterbox)
208 if(scoreboard_showscores)
212 vector hudSize = '0 0 0';
213 vector hudPos = '0 0 0';
214 vector tmpSize = '0 0 0';
215 vector tmpPos = '0 0 0';
217 float blinkValue = 0.55 + sin(time * 7) * 0.45;
219 float health = getstati(STAT_VEHICLESTAT_HEALTH) * 0.01;
220 float shield = getstati(STAT_VEHICLESTAT_SHIELD) * 0.01;
221 float energy = getstati(STAT_VEHICLESTAT_ENERGY) * 0.01;
222 float ammo1 = getstati(STAT_VEHICLESTAT_AMMO1) * 0.01;
223 float reload1 = getstati(STAT_VEHICLESTAT_RELOAD1) * 0.01;
224 float ammo2 = getstati(STAT_VEHICLESTAT_AMMO2) * 0.01;
225 float reload2 = getstati(STAT_VEHICLESTAT_RELOAD2) * 0.01;
227 // HACK to deal with the inconcistent use of the vehicle stats
228 ammo1 = (ammo1) ? ammo1 : energy;
231 hudSize = draw_getimagesize(vFRAME) * autocvar_cl_vehicles_hudscale;
232 hudPos.x = (vid_conwidth - hudSize.x) / 2;
233 hudPos.y = vid_conheight - hudSize.y;
235 drawpic(hudPos, vFRAME, hudSize, '1 1 1', autocvar_cl_vehicles_hudalpha, DRAWFLAG_NORMAL);
238 tmpSize.x = hudSize.x / 3;
239 tmpSize.y = hudSize.y;
240 tmpPos.x = hudPos.x + hudSize.x / 3;
244 drawpic(tmpPos, modelBase, tmpSize, '1 0 0' + '0 1 1' * blinkValue, 1, DRAWFLAG_NORMAL);
246 drawpic(tmpPos, modelBase, tmpSize, '1 1 1' * health + '1 0 0' * (1 - health), 1, DRAWFLAG_NORMAL);
248 drawpic(tmpPos, modelWeapon1, tmpSize, '1 1 1' * ammo1 + '1 0 0' * (1 - ammo1), 1, DRAWFLAG_NORMAL);
249 drawpic(tmpPos, modelWeapon2, tmpSize, '1 1 1' * ammo2 + '1 0 0' * (1 - ammo2), 1, DRAWFLAG_NORMAL);
250 drawpic(tmpPos, vMODEL_SHIELD, tmpSize, '1 1 1' * shield + '1 0 0' * (1 - shield), shield, DRAWFLAG_NORMAL);
253 tmpSize.y = hudSize.y / 2;
254 tmpPos.x = hudPos.x + hudSize.x * (32/768);
257 drawsetcliparea(tmpPos.x + (tmpSize.x * (1 - health)), tmpPos.y, tmpSize.x, tmpSize.y);
258 drawpic(tmpPos, vBAR_HEALTH, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
261 tmpPos.y = hudPos.y + hudSize.y / 2;
263 drawsetcliparea(tmpPos.x + (tmpSize.x * (1 - shield)), tmpPos.y, tmpSize.x, tmpSize.y);
264 drawpic(tmpPos, vBAR_SHIELD, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
267 tmpPos.x = hudPos.x + hudSize.x * (480/768);
271 drawsetcliparea(tmpPos.x, tmpPos.y, tmpSize.x * ammo1, tmpSize.y);
273 drawsetcliparea(tmpPos.x, tmpPos.y, tmpSize.x * reload1, tmpSize.y);
275 drawpic(tmpPos, vBAR_AMMO1, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
278 tmpPos.y = hudPos.y + hudSize.y / 2;
281 drawsetcliparea(tmpPos.x, tmpPos.y, tmpSize.x * ammo2, tmpSize.y);
283 drawsetcliparea(tmpPos.x, tmpPos.y, tmpSize.x * reload2, tmpSize.y);
285 drawpic(tmpPos, vBAR_AMMO2, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
289 tmpSize.x = hudSize.x * (80/768);
290 tmpSize.y = hudSize.y * (80/256);
291 tmpPos.x = hudPos.x + hudSize.x * (56/768);
292 tmpPos.y = hudPos.y + hudSize.y * (48/256);
296 if(alarm1time < time)
298 alarm1time = time + 2;
299 sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTEN_NONE);
301 drawpic(tmpPos, vICON_HEALTH, tmpSize, '1 1 1', blinkValue, DRAWFLAG_NORMAL);
307 sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
310 drawpic(tmpPos, vICON_HEALTH, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
314 tmpPos.y = hudPos.y + hudSize.y / 2;
318 if(alarm2time < time)
320 alarm2time = time + 1;
321 sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTEN_NONE);
323 drawpic(tmpPos, vICON_SHIELD, tmpSize, '1 1 1', blinkValue, DRAWFLAG_NORMAL);
329 sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE);
332 drawpic(tmpPos, vICON_SHIELD, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
336 tmpPos.x = hudPos.x + hudSize.x * (632/768);
337 tmpPos.y = hudPos.y + hudSize.y * (48/256);
340 drawpic(tmpPos, iconAmmo1, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
342 drawpic(tmpPos, iconAmmo1, tmpSize, '1 1 1', 0.2, DRAWFLAG_NORMAL);
345 tmpPos.y = hudPos.y + hudSize.y / 2;
348 drawpic(tmpPos, iconAmmo2, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
350 drawpic(tmpPos, iconAmmo2, tmpSize, '1 1 1', 0.2, DRAWFLAG_NORMAL);
353 tmpSize = draw_getimagesize(crosshair) * autocvar_cl_vehicles_crosshair_size;
354 tmpPos.x = (vid_conwidth - tmpSize.x) / 2;
355 tmpPos.y = (vid_conheight - tmpSize.y) / 2;
357 drawpic(tmpPos, crosshair, tmpSize, '1 1 1', 1, DRAWFLAG_NORMAL);
359 // Bumblebee gunner crosshairs
360 if(shouldDrawBumbleGunnerCrosshair)
362 tmpSize = '1 1 1' * hud_fontsize;
363 tmpPos.x = hudPos.x + hudSize.x * (520/768);
365 if(!AuxiliaryXhairs[1].draw2d)
367 tmpPos.y = hudPos.y + hudSize.y * (96/256) - tmpSize.y;
368 drawstring(tmpPos, _("No right gunner!"), tmpSize, '1 1 1', blinkValue, DRAWFLAG_NORMAL);
371 if(!AuxiliaryXhairs[2].draw2d)
373 tmpPos.y = hudPos.y + hudSize.y * (160/256);
374 drawstring(tmpPos, _("No left gunner!"), tmpSize, '1 1 1', blinkValue, DRAWFLAG_NORMAL);
378 // Raptor bomb crosshair
379 if(shouldDrawRaptorBombCrosshair && weapon2mode != RSM_FLARE)
386 dropmark.owner = self;
387 dropmark.gravity = 1;
392 setorigin(dropmark, pmove_org);
393 dropmark.velocity = pmove_vel;
394 tracetoss(dropmark, self);
396 where = project_3d_to_2d(trace_endpos);
398 setorigin(dropmark, trace_endpos);
399 tmpSize = draw_getimagesize(vCROSS_DROP) * autocvar_cl_vehicles_crosshair_size;
401 if (!(where.z < 0 || where.x < 0 || where.y < 0 || where.x > vid_conwidth || where.y > vid_conheight))
403 where.x -= tmpSize.x * 0.5;
404 where.y -= tmpSize.y * 0.5;
406 drawpic(where, vCROSS_DROP, tmpSize, '0 1 0', 0.9, DRAWFLAG_ADDITIVE);
407 drawpic(where, vCROSS_DROP, tmpSize, '0 1 0', 0.6, DRAWFLAG_NORMAL); // Ensure visibility against bright bg
409 dropmark.cnt = time + 5;
413 if(dropmark.cnt > time)
415 where = project_3d_to_2d(dropmark.origin);
416 tmpSize = draw_getimagesize(vCROSS_DROP) * autocvar_cl_vehicles_crosshair_size * 1.25;
418 if (!(where.z < 0 || where.x < 0 || where.y < 0 || where.x > vid_conwidth || where.y > vid_conheight))
420 where.x -= tmpSize.x * 0.5;
421 where.y -= tmpSize.y * 0.5;
423 drawpic(where, vCROSS_DROP, tmpSize, '1 0 0', 0.9, DRAWFLAG_ADDITIVE);
424 drawpic(where, vCROSS_DROP, tmpSize, '1 0 0', 0.6, DRAWFLAG_NORMAL); // Ensure visibility against bright bg
431 void CSQC_BUMBLE_HUD()
433 Vehicles_drawHUD(vMODEL_BUMBLE, vMODEL_BUMBLE_WEAPON1, vMODEL_BUMBLE_WEAPON2, vICON_AMMO1, vICON_AMMO1, vCROSS_HEAL, TRUE, FALSE);
436 void CSQC_BUMBLE_GUN_HUD()
438 Vehicles_drawHUD(vMODEL_GUNNER, vMODEL_GUNNER_WEAPON1, vNULL, vICON_AMMO1, vNULL, vNULL, TRUE, FALSE);
441 void CSQC_SPIDER_HUD()
447 case SBRM_VOLLY: crosshair = vCROSS_LOCK; break;
448 case SBRM_GUIDE: crosshair = vCROSS_AIM; break;
449 default: crosshair = vCROSS_TAG;
452 Vehicles_drawHUD(vMODEL_SPIDER, vMODEL_SPIDER_WEAPON1, vMODEL_SPIDER_WEAPON2, vICON_AMMO1, vICON_AMMO2, crosshair, FALSE, FALSE);
455 void CSQC_RAPTOR_HUD()
461 case RSM_FLARE: crosshair = vCROSS_LOCK; break;
462 default: crosshair = vCROSS_AIM;
465 Vehicles_drawHUD(vMODEL_RAPTOR, vMODEL_RAPTOR_WEAPON1, vMODEL_RAPTOR_WEAPON2, vICON_AMMO1, vICON_AMMO2, crosshair, FALSE, TRUE);
468 void CSQC_WAKIZASHI_HUD()
470 Vehicles_drawHUD(vMODEL_RACER, vMODEL_RACER_WEAPON1, vMODEL_RACER_WEAPON2, vICON_AMMO1, vICON_AMMO2, vCROSS_AIM, FALSE, FALSE);
473 void Vehicles_Precache()
475 precache_model("models/vehicles/bomblet.md3");
476 precache_model("models/vehicles/clusterbomb.md3");
477 precache_model("models/vehicles/clusterbomb_fragment.md3");
478 precache_model("models/vehicles/rocket01.md3");
479 precache_model("models/vehicles/rocket02.md3");
481 precache_sound("vehicles/alarm.wav");
482 precache_sound("vehicles/alarm_shield.wav");
485 void RaptorCBShellfragDraw()
490 Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
491 self.move_avelocity += randomvec() * 15;
492 self.renderflags = 0;
495 self.alpha = bound(0, self.nextthink - time, 1);
497 if(self.alpha < ALPHA_MIN_VISIBLE)
501 void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang)
506 setmodel(sfrag, "models/vehicles/clusterbomb_fragment.md3");
507 setorigin(sfrag, _org);
509 sfrag.move_movetype = MOVETYPE_BOUNCE;
510 sfrag.gravity = 0.15;
511 sfrag.solid = SOLID_CORPSE;
513 sfrag.draw = RaptorCBShellfragDraw;
515 sfrag.move_origin = sfrag.origin = _org;
516 sfrag.move_velocity = _vel;
517 sfrag.move_avelocity = prandomvec() * vlen(sfrag.move_velocity);
518 sfrag.angles = self.move_angles = _ang;
520 sfrag.move_time = time;
521 sfrag.damageforcescale = 4;
523 sfrag.nextthink = time + 3;
524 sfrag.cnt = time + 2;
526 sfrag.drawmask = MASK_NORMAL;