#include "all.qh" #include "../_all.qh" #include "../../common/movetypes/movetypes.qh" #include "../prandom.qh" #include "../scoreboard.qh" #include "../t_items.qh" #include "../../common/buffs.qh" #include "../../common/constants.qh" #include "../../common/movetypes/movetypes.qh" #include "../../common/stats.qh" #include "../../common/util.qh" #include "../../csqcmodellib/cl_model.qh" .float cnt; const string vCROSS_BURST = "gfx/vehicles/crosshair_burst.tga"; const string vCROSS_DROP = "gfx/vehicles/crosshair_drop.tga"; const string vCROSS_GUIDE = "gfx/vehicles/crosshair_guide.tga"; const string vCROSS_HEAL = "gfx/vehicles/crosshair_heal.tga"; const string vCROSS_HINT = "gfx/vehicles/crosshair_hint.tga"; const string vCROSS_LOCK = "gfx/vehicles/crosshair_lock.tga"; const string vCROSS_RAIN = "gfx/vehicles/crosshair_rain.tga"; const int SBRM_FIRST = 1; const int SBRM_VOLLY = 1; const int SBRM_GUIDE = 2; const int SBRM_ARTILLERY = 3; const int SBRM_LAST = 3; const int RSM_FIRST = 1; const int RSM_BOMB = 1; const int RSM_FLARE = 2; const int RSM_LAST = 2; const int MAX_AXH = 4; entity AuxiliaryXhairs[MAX_AXH]; entityclass(AuxiliaryXhair); class(AuxiliaryXhair) .string axh_image; class(AuxiliaryXhair) .float axh_fadetime; class(AuxiliaryXhair) .float axh_drawflag; entity dropmark; float alarm1time; float alarm2time; int weapon2mode; void AuxiliaryXhair_Draw2D() { if (scoreboard_showscores) return; vector size = draw_getimagesize(self.axh_image) * autocvar_cl_vehicles_crosshair_size; vector pos = project_3d_to_2d(self.move_origin) - 0.5 * size; if (!(pos.z < 0 || pos.x < 0 || pos.y < 0 || pos.x > vid_conwidth || pos.y > vid_conheight)) { pos.z = 0; size.z = 0; drawpic(pos, self.axh_image, size, self.colormod, autocvar_crosshair_alpha * self.alpha, self.axh_drawflag); } if(time - self.cnt > self.axh_fadetime) self.draw2d = func_null; } void Net_AuXair2(bool bIsNew) { int axh_id = bound(0, ReadByte(), MAX_AXH); entity axh = AuxiliaryXhairs[axh_id]; if(axh == world || wasfreed(axh)) // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?) { axh = spawn(); axh.draw2d = func_null; axh.drawmask = MASK_NORMAL; axh.axh_drawflag = DRAWFLAG_ADDITIVE; axh.axh_fadetime = 0.1; axh.axh_image = vCROSS_HINT; axh.alpha = 1; AuxiliaryXhairs[axh_id] = axh; } axh.move_origin_x = ReadCoord(); axh.move_origin_y = ReadCoord(); axh.move_origin_z = ReadCoord(); axh.colormod_x = ReadByte() / 255; axh.colormod_y = ReadByte() / 255; axh.colormod_z = ReadByte() / 255; axh.cnt = time; axh.draw2d = AuxiliaryXhair_Draw2D; } void Net_VehicleSetup() { int hud_id = ReadByte(); // Weapon update? if(hud_id > HUD_VEHICLE_LAST) { weapon2mode = hud_id - HUD_VEHICLE_LAST; return; } // hud_id == 0 means we exited a vehicle, so stop alarm sound/s if(hud_id == 0) { sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE); sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE); return; } hud_id = bound(HUD_VEHICLE_FIRST, hud_id, HUD_VEHICLE_LAST); // Init auxiliary crosshairs int i; for(i = 0; i < MAX_AXH; ++i) { entity axh = AuxiliaryXhairs[i]; if(axh != world && !wasfreed(axh)) // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?) remove(axh); axh = spawn(); axh.draw2d = func_null; axh.drawmask = MASK_NORMAL; axh.axh_drawflag = DRAWFLAG_NORMAL; axh.axh_fadetime = 0.1; axh.axh_image = vCROSS_HINT; axh.alpha = 1; AuxiliaryXhairs[i] = axh; } switch(hud_id) { case HUD_SPIDERBOT: AuxiliaryXhairs[0].axh_image = vCROSS_HINT; // Minigun1 AuxiliaryXhairs[1].axh_image = vCROSS_HINT; // Minigun2 break; case HUD_WAKIZASHI: AuxiliaryXhairs[0].axh_image = vCROSS_LOCK; // Rocket break; case HUD_RAPTOR: AuxiliaryXhairs[1].axh_image = vCROSS_LOCK; break; case HUD_BUMBLEBEE: AuxiliaryXhairs[0].axh_image = vCROSS_LOCK; // Raygun-locked AuxiliaryXhairs[1].axh_image = vCROSS_BURST; // Gunner1 AuxiliaryXhairs[2].axh_image = vCROSS_BURST; // Gunner2 break; case HUD_BUMBLEBEE_GUN: AuxiliaryXhairs[0].axh_image = vCROSS_BURST; // Plasma cannons AuxiliaryXhairs[1].axh_image = vCROSS_BURST; // Raygun break; } } void Vehicles_drawHUD( string vehicle, string vehicleWeapon1, string vehicleWeapon2, string iconAmmo1, vector colorAmmo1, string iconAmmo2, vector colorAmmo2, string crosshair) { if(autocvar_r_letterbox) return; if(scoreboard_showscores) return; // Initialize vector hudSize = '0 0 0'; vector hudPos = '0 0 0'; vector tmpSize = '0 0 0'; vector tmpPos = '0 0 0'; float hudAlpha = autocvar_hud_panel_fg_alpha; float barAlpha = autocvar_hud_progressbar_alpha * hudAlpha; float blinkValue = 0.55 + sin(time * 7) * 0.45; float health = getstati(STAT_VEHICLESTAT_HEALTH) * 0.01; float shield = getstati(STAT_VEHICLESTAT_SHIELD) * 0.01; float energy = getstati(STAT_VEHICLESTAT_ENERGY) * 0.01; float ammo1 = getstati(STAT_VEHICLESTAT_AMMO1) * 0.01; float reload1 = getstati(STAT_VEHICLESTAT_RELOAD1) * 0.01; float ammo2 = getstati(STAT_VEHICLESTAT_AMMO2) * 0.01; float reload2 = getstati(STAT_VEHICLESTAT_RELOAD2) * 0.01; // HACK to deal with the inconcistent use of the vehicle stats ammo1 = (ammo1) ? ammo1 : energy; // Frame string frame = strcat(hud_skin_path, "/vehicle_frame"); if (precache_pic(frame) == "") frame = "gfx/hud/default/vehicle_frame"; hudSize = draw_getimagesize(frame) * autocvar_cl_vehicles_hudscale; hudPos.x = (vid_conwidth - hudSize.x) / 2; hudPos.y = vid_conheight - hudSize.y; if(teamplay && autocvar_hud_panel_bg_color_team) drawpic(hudPos, frame, hudSize, myteamcolors * autocvar_hud_panel_bg_color_team, autocvar_hud_panel_bg_alpha, DRAWFLAG_NORMAL); else drawpic(hudPos, frame, hudSize, autocvar_hud_panel_bg_color, autocvar_hud_panel_bg_alpha, DRAWFLAG_NORMAL); // Model tmpSize.x = hudSize.x / 3; tmpSize.y = hudSize.y; tmpPos.x = hudPos.x + hudSize.x / 3; tmpPos.y = hudPos.y; if(health < 0.25) drawpic_skin(tmpPos, vehicle, tmpSize, '1 0 0' + '0 1 1' * blinkValue, hudAlpha, DRAWFLAG_NORMAL); else drawpic_skin(tmpPos, vehicle, tmpSize, '1 1 1' * health + '1 0 0' * (1 - health), hudAlpha, DRAWFLAG_NORMAL); if(vehicleWeapon1) drawpic_skin(tmpPos, vehicleWeapon1, tmpSize, '1 1 1' * ammo1 + '1 0 0' * (1 - ammo1), hudAlpha, DRAWFLAG_NORMAL); if(vehicleWeapon2) drawpic_skin(tmpPos, vehicleWeapon2, tmpSize, '1 1 1' * ammo2 + '1 0 0' * (1 - ammo2), hudAlpha, DRAWFLAG_NORMAL); drawpic_skin(tmpPos, "vehicle_shield", tmpSize, '1 1 1' * shield + '1 0 0' * (1 - shield), hudAlpha * shield, DRAWFLAG_NORMAL); // Health bar tmpSize.y = hudSize.y / 2; tmpPos.x = hudPos.x + hudSize.x * (32/768); tmpPos.y = hudPos.y; drawsetcliparea(tmpPos.x + (tmpSize.x * (1 - health)), tmpPos.y, tmpSize.x, tmpSize.y); drawpic_skin(tmpPos, "vehicle_bar_northwest", tmpSize, autocvar_hud_progressbar_health_color, barAlpha, DRAWFLAG_NORMAL); // Shield bar tmpPos.y = hudPos.y + hudSize.y / 2; drawsetcliparea(tmpPos.x + (tmpSize.x * (1 - shield)), tmpPos.y, tmpSize.x, tmpSize.y); drawpic_skin(tmpPos, "vehicle_bar_southwest", tmpSize, autocvar_hud_progressbar_armor_color, barAlpha, DRAWFLAG_NORMAL); // Ammo1 bar tmpPos.x = hudPos.x + hudSize.x * (480/768); tmpPos.y = hudPos.y; if(ammo1) drawsetcliparea(tmpPos.x, tmpPos.y, tmpSize.x * ammo1, tmpSize.y); else drawsetcliparea(tmpPos.x, tmpPos.y, tmpSize.x * reload1, tmpSize.y); drawpic_skin(tmpPos, "vehicle_bar_northeast", tmpSize, colorAmmo1, barAlpha, DRAWFLAG_NORMAL); // Ammo2 bar tmpPos.y = hudPos.y + hudSize.y / 2; if(ammo2) drawsetcliparea(tmpPos.x, tmpPos.y, tmpSize.x * ammo2, tmpSize.y); else drawsetcliparea(tmpPos.x, tmpPos.y, tmpSize.x * reload2, tmpSize.y); drawpic_skin(tmpPos, "vehicle_bar_southeast", tmpSize, colorAmmo2, barAlpha, DRAWFLAG_NORMAL); drawresetcliparea(); // Health icon tmpSize.x = hudSize.x * (80/768); tmpSize.y = hudSize.y * (80/256); tmpPos.x = hudPos.x + hudSize.x * (64/768); tmpPos.y = hudPos.y + hudSize.y * (48/256); if(health < 0.25) { if(alarm1time < time) { alarm1time = time + 2; sound(self, CH_PAIN_SINGLE, "vehicles/alarm.wav", VOL_BASEVOICE, ATTEN_NONE); } drawpic_skin(tmpPos, "vehicle_icon_health", tmpSize, '1 1 1', hudAlpha * blinkValue, DRAWFLAG_NORMAL); } else { if(alarm1time) { sound(self, CH_PAIN_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE); alarm1time = 0; } drawpic_skin(tmpPos, "vehicle_icon_health", tmpSize, '1 1 1', hudAlpha, DRAWFLAG_NORMAL); } // Shield icon tmpPos.y = hudPos.y + hudSize.y / 2; if(shield < 0.25) { if(alarm2time < time) { alarm2time = time + 1; sound(self, CH_TRIGGER_SINGLE, "vehicles/alarm_shield.wav", VOL_BASEVOICE, ATTEN_NONE); } drawpic_skin(tmpPos, "vehicle_icon_shield", tmpSize, '1 1 1', hudAlpha * blinkValue, DRAWFLAG_NORMAL); } else { if(alarm2time) { sound(self, CH_TRIGGER_SINGLE, "misc/null.wav", VOL_BASEVOICE, ATTEN_NONE); alarm2time = 0; } drawpic_skin(tmpPos, "vehicle_icon_shield", tmpSize, '1 1 1', hudAlpha, DRAWFLAG_NORMAL); } // Ammo1 icon tmpPos.x = hudPos.x + hudSize.x * (624/768); tmpPos.y = hudPos.y + hudSize.y * (48/256); if(iconAmmo1) { if(ammo1) drawpic_skin(tmpPos, iconAmmo1, tmpSize, '1 1 1', hudAlpha, DRAWFLAG_NORMAL); else drawpic_skin(tmpPos, iconAmmo1, tmpSize, '1 1 1', hudAlpha * 0.2, DRAWFLAG_NORMAL); } // Ammo2 icon tmpPos.y = hudPos.y + hudSize.y / 2; if(iconAmmo2) { if(ammo2) drawpic_skin(tmpPos, iconAmmo2, tmpSize, '1 1 1', hudAlpha, DRAWFLAG_NORMAL); else drawpic_skin(tmpPos, iconAmmo2, tmpSize, '1 1 1', hudAlpha * 0.2, DRAWFLAG_NORMAL); } // Bumblebee gunner crosshairs if(hud == HUD_BUMBLEBEE) { tmpSize = '1 1 1' * hud_fontsize; tmpPos.x = hudPos.x + hudSize.x * (520/768); if(!AuxiliaryXhairs[1].draw2d) { tmpPos.y = hudPos.y + hudSize.y * (96/256) - tmpSize.y; drawstring(tmpPos, _("No right gunner!"), tmpSize, '1 1 1', hudAlpha * blinkValue, DRAWFLAG_NORMAL); } if(!AuxiliaryXhairs[2].draw2d) { tmpPos.y = hudPos.y + hudSize.y * (160/256); drawstring(tmpPos, _("No left gunner!"), tmpSize, '1 1 1', hudAlpha * blinkValue, DRAWFLAG_NORMAL); } } // Raptor bomb crosshair if(hud == HUD_RAPTOR && weapon2mode != RSM_FLARE) { vector where; if(!dropmark) { dropmark = spawn(); dropmark.owner = self; dropmark.gravity = 1; } if(reload2 == 1) { setorigin(dropmark, pmove_org); dropmark.velocity = pmove_vel; tracetoss(dropmark, self); where = project_3d_to_2d(trace_endpos); setorigin(dropmark, trace_endpos); tmpSize = draw_getimagesize(vCROSS_DROP) * autocvar_cl_vehicles_crosshair_size; if (!(where.z < 0 || where.x < 0 || where.y < 0 || where.x > vid_conwidth || where.y > vid_conheight)) { where.x -= tmpSize.x * 0.5; where.y -= tmpSize.y * 0.5; where.z = 0; drawpic(where, vCROSS_DROP, tmpSize, '0 1 0', autocvar_crosshair_alpha * 0.9, DRAWFLAG_ADDITIVE); drawpic(where, vCROSS_DROP, tmpSize, '0 1 0', autocvar_crosshair_alpha * 0.6, DRAWFLAG_NORMAL); // Ensure visibility against bright bg } dropmark.cnt = time + 5; } else { if(dropmark.cnt > time) { where = project_3d_to_2d(dropmark.origin); tmpSize = draw_getimagesize(vCROSS_DROP) * autocvar_cl_vehicles_crosshair_size * 1.25; if (!(where.z < 0 || where.x < 0 || where.y < 0 || where.x > vid_conwidth || where.y > vid_conheight)) { where.x -= tmpSize.x * 0.5; where.y -= tmpSize.y * 0.5; where.z = 0; drawpic(where, vCROSS_DROP, tmpSize, '1 0 0', autocvar_crosshair_alpha * 0.9, DRAWFLAG_ADDITIVE); drawpic(where, vCROSS_DROP, tmpSize, '1 0 0', autocvar_crosshair_alpha * 0.6, DRAWFLAG_NORMAL); // Ensure visibility against bright bg } } } } // Crosshair if(crosshair) { tmpSize = draw_getimagesize(crosshair) * autocvar_cl_vehicles_crosshair_size; tmpPos.x = (vid_conwidth - tmpSize.x) / 2; tmpPos.y = (vid_conheight - tmpSize.y) / 2; drawpic(tmpPos, crosshair, tmpSize, '1 1 1', autocvar_crosshair_alpha, DRAWFLAG_NORMAL); } } void CSQC_BUMBLE_HUD() { Vehicles_drawHUD("vehicle_bumble", "vehicle_bumble_weapon1", "vehicle_bumble_weapon2", "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color, "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color, vCROSS_HEAL); } void CSQC_BUMBLE_GUN_HUD() { Vehicles_drawHUD("vehicle_gunner", "vehicle_gunner_weapon1", string_null, "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color, string_null, '0 0 0', string_null); } void CSQC_SPIDER_HUD() { string crosshair; switch(weapon2mode) { case SBRM_VOLLY: crosshair = vCROSS_BURST; break; case SBRM_GUIDE: crosshair = vCROSS_GUIDE; break; case SBRM_ARTILLERY: crosshair = vCROSS_RAIN; break; default: crosshair = vCROSS_BURST; } Vehicles_drawHUD("vehicle_spider", "vehicle_spider_weapon1", "vehicle_spider_weapon2", "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color, "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color, crosshair); } void CSQC_RAPTOR_HUD() { string crosshair; switch(weapon2mode) { case RSM_FLARE: crosshair = vCROSS_RAIN; break; case RSM_BOMB: crosshair = vCROSS_BURST; break; default: crosshair = vCROSS_BURST; } Vehicles_drawHUD("vehicle_raptor", "vehicle_raptor_weapon1", "vehicle_raptor_weapon2", "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color, "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color, crosshair); } void CSQC_WAKIZASHI_HUD() { Vehicles_drawHUD("vehicle_racer", "vehicle_racer_weapon1", "vehicle_racer_weapon2", "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color, "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color, vCROSS_GUIDE); } void Vehicles_Precache() { precache_model("models/vehicles/bomblet.md3"); precache_model("models/vehicles/clusterbomb.md3"); precache_model("models/vehicles/clusterbomb_fragment.md3"); precache_model("models/vehicles/rocket01.md3"); precache_model("models/vehicles/rocket02.md3"); precache_sound("vehicles/alarm.wav"); precache_sound("vehicles/alarm_shield.wav"); } void RaptorCBShellfragDraw() { if(wasfreed(self)) return; Movetype_Physics_MatchTicrate(autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy); self.move_avelocity += randomvec() * 15; self.renderflags = 0; if(self.cnt < time) self.alpha = bound(0, self.nextthink - time, 1); if(self.alpha < ALPHA_MIN_VISIBLE) remove(self); } void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang) { entity sfrag; sfrag = spawn(); setmodel(sfrag, "models/vehicles/clusterbomb_fragment.md3"); setorigin(sfrag, _org); sfrag.move_movetype = MOVETYPE_BOUNCE; sfrag.gravity = 0.15; sfrag.solid = SOLID_CORPSE; sfrag.draw = RaptorCBShellfragDraw; sfrag.move_origin = sfrag.origin = _org; sfrag.move_velocity = _vel; sfrag.move_avelocity = prandomvec() * vlen(sfrag.move_velocity); sfrag.angles = self.move_angles = _ang; sfrag.move_time = time; sfrag.damageforcescale = 4; sfrag.nextthink = time + 3; sfrag.cnt = time + 2; sfrag.alpha = 1; sfrag.drawmask = MASK_NORMAL; }