// q3map_skylight 9.32523632 3
alias skybox_nosRGB_to_sRGB "rpn $3 402.123 $4 div div $rpn_sRGB_to_linear 402.123 $4 div mul /new_skylight: $3 402.123 $4 div div $1 256 div $2 0.017453 mul sin mul add $rpn_sRGB_to_linear $3 402.123 $4 div div $rpn_sRGB_to_linear sub 256 mul $2 0.017453 mul sin div /new_sunlight:"
+set cl_orthoview 0 "enable top-down view of the map- meant to be used for radar map images (note: orthoview sets cvars temporarily, requires restart to return them to normal)"
+set cl_orthoview_nofog 1 "disable fog while in orthoview-- note, should not be enabled on ALL maps, i.e. oilrig works fine with this disabled"
+
// these settings determine how much the view is affected by movement/damage
cl_smoothviewheight 0.05 // time of the averaging to the viewheight value so that it creates a smooth transition for crouching and such. 0 for instant transition
cl_deathfade 0 // fade screen to dark red when dead, value represents how fast the fade is (higher is faster)
bind F12 screenshot
bind F4 ready
bind ALT +showaccuracy
+ alias quickmenu "cl_cmd hud quickmenu"
+ bind b quickmenu
// Gamepad defaults. Tested with Logitech Rumblepad 2, I hope similar ones works as well.
bind JOY1 "+crouch"
// Quake-Joule: 1 qJ = 1 qN * 1 qu
// Quake-Pascal: 1 qPa = 1 qN / 1 qu^2
-set g_ballistics_materialconstant 1414213562
-set g_ballistics_mindistance 16
+set g_ballistics_mindistance 2 // enable ballistics starting from 2 qu
set g_ballistics_density_player 0.50 // players are 2x as easy to pass as walls
set g_ballistics_density_corpse 0.10 // corpses are 10x as easy to pass as walls
-// unit: qJ / qu^3 (energy needed per volume unit of solid to push/burn away
-// parameter: bullet constant: mass / area in g/qu^2
-// = mass / (pi/4 * caliber^2)
-// with caliber in inches, mass in grams:
-// = 1.273239544735163 * mass / caliber^2
-// with caliber in inches, mass in grains:
-// = 0.082633246453312 * mass / caliber^2
-
-// bullet max travel distance inside solid:
-// 0.5 * v^2 * bulletconstant / g_ballistics_materialconstant
-
-// some bullet constants:
-// http://hypertextbook.com/facts/2000/ShantayArmstrong.shtml
-// second bullet: caliber .45, mass 16.2g, bullet constant 101.859163578813
-// third bullet: caliber .338, mass 16.2g, bullet constant 180.5476053421592
-// fourth bullet: caliber .25, mass 2.3g, bullet constant 46.85521524625399
-// http://en.wikipedia.org/wiki/.50_BMG
-// caliber .5, 360 grains, bullet constant 118.9918748927693
-// AK-47:
-// caliber .3, 62 grains, bullet constant 56.92512533450383
-// .3 winchester magnum:
-// caliber .3, 150 grains, bullet constant 137.7220774221867
set cl_stripcolorcodes 0 "experimental feature (notes: strips ALL color codes from messages!)"
check_unacceptable_compiler_bugs();
#ifdef WATERMARK
- print(sprintf(_("^4CSQC Build information: ^1%s\n"), WATERMARK));
+ printf(_("^4CSQC Build information: ^1%s\n"), WATERMARK);
#endif
float i;
default:
if(GetTeam(Team, false) == world)
{
- print(sprintf(_("trying to switch to unsupported team %d\n"), Team));
+ printf(_("trying to switch to unsupported team %d\n"), Team);
Team = NUM_SPECTATOR;
}
break;
default:
if(GetTeam(Team, false) == world)
{
- print(sprintf(_("trying to switch to unsupported team %d\n"), Team));
+ printf(_("trying to switch to unsupported team %d\n"), Team);
Team = NUM_SPECTATOR;
}
break;
if (HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary))
return true;
+ if (HUD_QuickMenu_InputEvent(bInputType, nPrimary, nSecondary))
+ return true;
+
if (MapVote_InputEvent(bInputType, nPrimary, nSecondary))
return true;
if(!isNew && n != self.sv_entnum)
{
//print("A CSQC entity changed its owner!\n");
- print(sprintf("A CSQC entity changed its owner! (edict: %d, classname: %s)\n", num_for_edict(self), self.classname));
+ printf("A CSQC entity changed its owner! (edict: %d, classname: %s)\n", num_for_edict(self), self.classname);
isNew = true;
Ent_Remove();
self.enttype = ENT_CLIENT_SCORES;
}
}
- //print(sprintf("Ent_ReadSpawnPoint(is_new = %d); origin = %s, team = %d, effect = %d\n", is_new, vtos(self.origin), teamnum, self.cnt));
+ //printf("Ent_ReadSpawnPoint(is_new = %d); origin = %s, team = %d, effect = %d\n", is_new, vtos(self.origin), teamnum, self.cnt);
}
void Ent_ReadSpawnEvent(float is_new)
}
}
- //print(sprintf("Ent_ReadSpawnEvent(is_new = %d); origin = %s, entnum = %d, localentnum = %d\n", is_new, vtos(self.origin), entnum, player_localentnum));
+ //printf("Ent_ReadSpawnEvent(is_new = %d); origin = %s, entnum = %d, localentnum = %d\n", is_new, vtos(self.origin), entnum, player_localentnum);
}
// CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.
t = ReadByte();
if(autocvar_developer_csqcentities)
- print(sprintf("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t));
+ printf("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t);
// set up the "time" global for received entities to be correct for interpolation purposes
savetime = time;
if(t != self.enttype || bIsNewEntity)
{
//print("A CSQC entity changed its type!\n");
- print(sprintf("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(self), self.entnum, self.enttype, t));
+ printf("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(self), self.entnum, self.enttype, t);
Ent_Remove();
clearentity(self);
bIsNewEntity = 1;
{
if(!bIsNewEntity)
{
- print(sprintf("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(self), self.entnum, t));
+ printf("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(self), self.entnum, t);
bIsNewEntity = 1;
}
}
void CSQC_Ent_Remove()
{
if(autocvar_developer_csqcentities)
- print(sprintf("CSQC_Ent_Remove() with self=%i self.entnum=%d self.enttype=%d\n", self, self.entnum, self.enttype));
+ printf("CSQC_Ent_Remove() with self=%i self.entnum=%d self.enttype=%d\n", self, self.entnum, self.enttype);
if(wasfreed(self))
{
void CSQC_Parse_StuffCmd(string strMessage)
{
if(autocvar_developer_csqcentities)
- print(sprintf("CSQC_Parse_StuffCmd(\"%s\")\n", strMessage));
+ printf("CSQC_Parse_StuffCmd(\"%s\")\n", strMessage);
localcmd(strMessage);
}
void CSQC_Parse_Print(string strMessage)
{
if(autocvar_developer_csqcentities)
- print(sprintf("CSQC_Parse_Print(\"%s\")\n", strMessage));
+ printf("CSQC_Parse_Print(\"%s\")\n", strMessage);
print(ColorTranslateRGB(strMessage));
}
void CSQC_Parse_CenterPrint(string strMessage)
{
if(autocvar_developer_csqcentities)
- print(sprintf("CSQC_Parse_CenterPrint(\"%s\")\n", strMessage));
+ printf("CSQC_Parse_CenterPrint(\"%s\")\n", strMessage);
centerprint_hud(strMessage);
}
{
// TODO somehow thwart prvm_globalset client ...
- if(forcefog != "")
- localcmd(strcat(notranslate_fogcmd1, forcefog, notranslate_fogcmd2));
+ if(autocvar_cl_orthoview && autocvar_cl_orthoview_nofog)
+ { localcmd("\nr_drawfog 0\n"); }
+ else if(forcefog != "")
+ { localcmd(strcat(notranslate_fogcmd1, forcefog, notranslate_fogcmd2)); }
}
void Gamemode_Init();
nTEID = ReadByte();
if(autocvar_developer_csqcentities)
- print(sprintf("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID));
+ printf("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID);
// NOTE: Could just do return instead of break...
switch(nTEID)
Net_ReadRace();
bHandled = true;
break;
- case TE_CSQC_ZCURVEPARTICLES:
- Net_ReadZCurveParticles();
- bHandled = true;
- break;
case TE_CSQC_NEXGUNBEAMPARTICLE:
Net_ReadNexgunBeamParticle();
bHandled = true;
return '1 0 0' * fovx + '0 1 0' * fovy;
}
+vector GetOrthoviewFOV(vector ov_worldmin, vector ov_worldmax, vector ov_mid, vector ov_org)
+{
+ float fovx, fovy;
+ float width = (ov_worldmax_x - ov_worldmin_x);
+ float height = (ov_worldmax_y - ov_worldmin_y);
+ float distance_to_middle_of_world = vlen(ov_mid - ov_org);
+ fovx = atan2(width/2, distance_to_middle_of_world) / M_PI * 360.0;
+ fovy = atan2(height/2, distance_to_middle_of_world) / M_PI * 360.0;
+ return '1 0 0' * fovx + '0 1 0' * fovy;
+}
+
// this function must match W_SetupShot!
float zoomscript_caught;
break;
}
+ vector traceorigin = getplayerorigin(player_localentnum-1) + (eZ * getstati(STAT_VIEWHEIGHT));
+
vecs = decompressShotOrigin(getstati(STAT_SHOTORG));
- traceline(view_origin, view_origin + view_forward * MAX_SHOT_DISTANCE, mv, ta);
+ traceline(traceorigin, traceorigin + view_forward * MAX_SHOT_DISTANCE, mv, ta);
trueaimpoint = trace_endpos;
- if(vlen(trueaimpoint - view_origin) < g_trueaim_minrange)
- trueaimpoint = view_origin + view_forward * g_trueaim_minrange;
+ if(vlen(trueaimpoint - traceorigin) < g_trueaim_minrange)
+ trueaimpoint = traceorigin + view_forward * g_trueaim_minrange;
if(vecs_x > 0)
vecs_y = -vecs_y;
vecs = '0 0 0';
dv = view_right * vecs_y + view_up * vecs_z;
- w_shotorg = view_origin + dv;
+ w_shotorg = traceorigin + dv;
// now move the vecs forward as much as requested if possible
tracebox(w_shotorg, mi, ma, w_shotorg + view_forward * (vecs_x + nudge), MOVE_NORMAL, ta); // FIXME this MOVE_NORMAL part will misbehave a little in csqc
// event chase camera
if(autocvar_chase_active <= 0) // greater than 0 means it's enabled manually, and this code is skipped
{
- if((spectatee_status >= 0 && (autocvar_cl_eventchase_death && is_dead)) || intermission)
+ if(((spectatee_status >= 0 && (autocvar_cl_eventchase_death && is_dead)) || intermission) && !autocvar_cl_orthoview)
{
// make special vector since we can't use view_origin (It is one frame old as of this code, it gets set later with the results this code makes.)
vector current_view_origin = (csqcplayer ? csqcplayer.origin : pmove_org);
}
// do lockview after event chase camera so that it still applies whenever necessary.
- if(autocvar_cl_lockview || (!autocvar_hud_cursormode && (autocvar__hud_configure && spectatee_status <= 0 || intermission > 1)))
+ if(autocvar_cl_lockview || (!autocvar_hud_cursormode && (autocvar__hud_configure && spectatee_status <= 0 || intermission > 1 || HUD_QuickMenu_IsOpened())))
{
setproperty(VF_ORIGIN, freeze_org);
setproperty(VF_ANGLES, freeze_ang);
WarpZone_FixView();
//WarpZone_FixPMove();
+ vector ov_org = '0 0 0';
+ vector ov_mid = '0 0 0';
+ vector ov_worldmin = '0 0 0';
+ vector ov_worldmax = '0 0 0';
+ if(autocvar_cl_orthoview)
+ {
+ ov_worldmin = mi_picmin;
+ ov_worldmax = mi_picmax;
+
+ float ov_width = (ov_worldmax_x - ov_worldmin_x);
+ float ov_height = (ov_worldmax_y - ov_worldmin_y);
+ float ov_distance = (max(vid_width, vid_height) * max(ov_width, ov_height));
+
+ ov_mid = ((ov_worldmax + ov_worldmin) * 0.5);
+ ov_org = vec3(ov_mid_x, ov_mid_y, (ov_mid_z + ov_distance));
+
+ float ov_nearest = vlen(ov_org - vec3(
+ bound(ov_worldmin_x, ov_org_x, ov_worldmax_x),
+ bound(ov_worldmin_y, ov_org_y, ov_worldmax_y),
+ bound(ov_worldmin_z, ov_org_z, ov_worldmax_z)
+ ));
+
+ float ov_furthest = 0;
+ float dist = 0;
+
+ if((dist = vlen(vec3(ov_worldmin_x, ov_worldmin_y, ov_worldmin_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
+ if((dist = vlen(vec3(ov_worldmax_x, ov_worldmin_y, ov_worldmin_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
+ if((dist = vlen(vec3(ov_worldmin_x, ov_worldmax_y, ov_worldmin_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
+ if((dist = vlen(vec3(ov_worldmin_x, ov_worldmin_y, ov_worldmax_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
+ if((dist = vlen(vec3(ov_worldmax_x, ov_worldmax_y, ov_worldmin_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
+ if((dist = vlen(vec3(ov_worldmin_x, ov_worldmax_y, ov_worldmax_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
+ if((dist = vlen(vec3(ov_worldmax_x, ov_worldmin_y, ov_worldmax_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
+ if((dist = vlen(vec3(ov_worldmax_x, ov_worldmax_y, ov_worldmax_z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
+
+ cvar_settemp("r_nearclip", ftos(ov_nearest));
+ cvar_settemp("r_farclip_base", ftos(ov_furthest));
+ cvar_settemp("r_farclip_world", "0");
+ cvar_settemp("r_novis", "1");
+ cvar_settemp("r_useportalculling", "0");
+ cvar_settemp("r_useinfinitefarclip", "0");
+
+ setproperty(VF_ORIGIN, ov_org);
+ setproperty(VF_ANGLES, '90 0 0');
+
+ #if 0
+ printf("OrthoView: org = %s, angles = %s, distance = %f, nearest = %f, furthest = %f\n",
+ vtos(ov_org),
+ vtos(getpropertyvec(VF_ANGLES)),
+ ov_distance,
+ ov_nearest,
+ ov_furthest);
+ #endif
+ }
+
// Render the Scene
view_origin = getpropertyvec(VF_ORIGIN);
view_angles = getpropertyvec(VF_ANGLES);
vid_conheight = autocvar_vid_conheight;
vid_pixelheight = autocvar_vid_pixelheight;
- setproperty(VF_FOV, GetCurrentFov(fov));
+ if(autocvar_cl_orthoview) { setproperty(VF_FOV, GetOrthoviewFOV(ov_worldmin, ov_worldmax, ov_mid, ov_org)); }
+ else { setproperty(VF_FOV, GetCurrentFov(fov)); }
// Camera for demo playback
if(camera_active)
}
}
- //print(sprintf("crosshair style: %s\n", wcross_style));
+ //printf("crosshair style: %s\n", wcross_style);
wcross_name = strcat("gfx/crosshair", wcross_style);
// MAIN CROSSHAIR COLOR DECISION
if(autocvar__hud_configure)
HUD_Panel_Mouse();
+ else if(HUD_QuickMenu_IsOpened())
+ HUD_QuickMenu_Mouse();
- if(hud && !intermission)
+ if(hud && !intermission)
{
if(hud == HUD_SPIDERBOT)
CSQC_SPIDER_HUD();
float autocvar_cl_hidewaypoints;
float autocvar_cl_lockview;
float autocvar_cl_nogibs;
+float autocvar_cl_orthoview;
+float autocvar_cl_orthoview_nofog;
float autocvar_cl_particlegibs;
float autocvar_cl_particles_oldnexbeam;
float autocvar_cl_particles_quality;
float autocvar_hud_panel_pressedkeys;
float autocvar_hud_panel_pressedkeys_aspect;
float autocvar_hud_panel_pressedkeys_attack;
+ string autocvar_hud_panel_quickmenu_file;
float autocvar_hud_panel_racetimer;
float autocvar_hud_panel_radar;
float autocvar_hud_panel_radar_foreground_alpha;
float autocvar_hud_panel_weapons_timeout_fadefgmin;
var float autocvar_hud_panel_weapons_timeout_speed_in = 0.25;
var float autocvar_hud_panel_weapons_timeout_speed_out = 0.75;
+ //float autocvar_hud_panel_quickmenu;
+ float autocvar_hud_panel_quickmenu_align;
float autocvar_hud_progressbar_alpha;
float autocvar_hud_showbinds;
float autocvar_hud_showbinds_limit;
void centerprint_generic(float new_id, string strMessage, float duration, float countdown_num)
{
- //print(sprintf("centerprint_generic(%d, '%s^7', %d, %d);\n", new_id, strMessage, duration, countdown_num));
+ //printf("centerprint_generic(%d, '%s^7', %d, %d);\n", new_id, strMessage, duration, countdown_num);
float i, j;
if(strMessage == "" && new_id == 0)
float a, sz, align, current_msg_pos_y = 0, msg_size;
vector pos;
string ts;
-
- n = -1; // if no msg will be displayed, n stays -1
+ float all_messages_expired = TRUE;
pos = panel_pos;
if (autocvar_hud_panel_centerprint_flip)
continue;
}
+ all_messages_expired = FALSE;
// fade the centerprint_hud in/out
- if(centerprint_time[j] < 0)
- a = bound(0, (time - centerprint_expire_time[j]) / max(0.0001, autocvar_hud_panel_centerprint_fade_in), 1);
- else if(centerprint_expire_time[j] - autocvar_hud_panel_centerprint_fade_out > time)
- a = bound(0, (time - (centerprint_expire_time[j] - centerprint_time[j])) / max(0.0001, autocvar_hud_panel_centerprint_fade_in), 1);
- else if(centerprint_expire_time[j] > time)
+ if(centerprint_time[j] < 0) // Expired but forced. Expire time is the fade-in time.
+ a = (time - centerprint_expire_time[j]) / max(0.0001, autocvar_hud_panel_centerprint_fade_in);
+ else if(centerprint_expire_time[j] - autocvar_hud_panel_centerprint_fade_out > time) // Regularily printed. Not fading out yet.
+ a = (time - (centerprint_expire_time[j] - centerprint_time[j])) / max(0.0001, autocvar_hud_panel_centerprint_fade_in);
+ else // Expiring soon, so fade it out.
a = (centerprint_expire_time[j] - time) / max(0.0001, autocvar_hud_panel_centerprint_fade_out);
- else
- a = 0;
+
+ if (a <= 0.5/255.0) // Guaranteed invisible - don't show.
+ continue;
+ if (a > 1)
+ a = 1;
// set the size from fading in/out before subsequent fading
sz = autocvar_hud_panel_centerprint_fade_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_minfontsize);
a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passone_minalpha, (1 - (g / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passone))), 1); // pass one: all messages after the first have half theAlpha
a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passtwo_minalpha, (1 - (g / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passtwo))), 1); // pass two: after that, gradually lower theAlpha even more for each message
}
+ a *= panel_fg_alpha;
// finally set the size based on the new theAlpha from subsequent fading
sz = sz * (autocvar_hud_panel_centerprint_fade_subsequent_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_subsequent_minfontsize));
{
if (align)
pos_x = panel_pos_x + (panel_size_x - stringwidth(ts, TRUE, fontsize)) * align;
- drawcolorcodedstring(pos + eY * 0.5 * (1 - sz) * fontsize_y, ts, fontsize, a * panel_fg_alpha, DRAWFLAG_NORMAL);
+ if (a > 0.5/255.0) // Otherwise guaranteed invisible - don't show. This is checked a second time after some multiplications with other factors were done so temporary changes of these cannot cause flicker.
+ drawcolorcodedstring(pos + eY * 0.5 * (1 - sz) * fontsize_y, ts, fontsize, a, DRAWFLAG_NORMAL);
pos_y += fontsize_y;
}
else
}
}
drawfontscale = '1 1 0';
- if (n == -1)
+ if (all_messages_expired)
{
centerprint_showing = FALSE;
reset_centerprint_messages();
}
}
+ // QuickMenu (#17)
+ //
+ // QUICKMENU_MAXLINES must be <= 10
+ #define QUICKMENU_MAXLINES 10
+ #define QUICKMENU_MAXENTRIES 256
+ string QuickMenu_Command[QUICKMENU_MAXLINES];
+ string QuickMenu_Description[QUICKMENU_MAXLINES];
+ float QuickMenu_CurrentPage;
+ float QuickMenu_IsLastPage;
+ var float QuickMenu_Buffer = -1;
+ float QuickMenu_Buffer_Size;
+ float QuickMenu_Buffer_Index;
+ string QuickMenu_CurrentSubMenu;
+ float QuickMenu_CurrentPage_FirstEntry;
+ var float QuickMenu_Entries;
+ void HUD_QuickMenu_load_entry(float i, string s, string s1)
+ {
+ //print(sprintf("^xc80 entry %d: %s, %s\n", i, s, s1));
+ if (QuickMenu_Description[i])
+ strunzone(QuickMenu_Description[i]);
+ QuickMenu_Description[i] = strzone(s);
+ if (QuickMenu_Command[i])
+ strunzone(QuickMenu_Command[i]);
+ QuickMenu_Command[i] = strzone(s1);
+ }
+ void HUD_QuickMenu_clear_entry(float i)
+ {
+ if (QuickMenu_Description[i])
+ strunzone(QuickMenu_Description[i]);
+ QuickMenu_Description[i] = string_null;
+ if (QuickMenu_Command[i])
+ strunzone(QuickMenu_Command[i]);
+ QuickMenu_Command[i] = string_null;
+ }
+
+ float HUD_QuickMenu_Buffer_Init()
+ {
+ float fh, i;
+ string s;
+ fh = fopen(autocvar_hud_panel_quickmenu_file, FILE_READ);
+ if(fh < 0)
+ {
+ print(sprintf(_("Error: Couldn't open file %s!\n"), autocvar_hud_panel_quickmenu_file));
+ return false;
+ }
+
+ QuickMenu_Buffer = buf_create();
+ if (QuickMenu_Buffer < 0)
+ {
+ fclose(fh);
+ return false;
+ }
+
+ i = 0;
+ while((s = fgets(fh)) && i < QUICKMENU_MAXENTRIES)
+ {
+ // first skip invalid entries, so we don't check them anymore
+ float argc;
+ argc = tokenize_console(s);
+ if(argc == 0 || argc > 2)
+ continue;
+
+ bufstr_set(QuickMenu_Buffer, i, s);
+ ++i;
+ }
+ QuickMenu_Buffer_Size = i;
+
+ if (QuickMenu_Buffer_Size <= 0)
+ {
+ buf_del(QuickMenu_Buffer);
+ QuickMenu_Buffer = -1;
+ }
+ fclose(fh);
+ return true;
+ }
+
+ void HUD_QuickMenu_Buffer_Close()
+ {
+ if (QuickMenu_Buffer >= 0)
+ {
+ buf_del(QuickMenu_Buffer);
+ QuickMenu_Buffer = -1;
+ QuickMenu_Buffer_Size = 0;
+ }
+ }
+
+ void HUD_QuickMenu_Close()
+ {
+ if (QuickMenu_CurrentSubMenu)
+ strunzone(QuickMenu_CurrentSubMenu);
+ QuickMenu_CurrentSubMenu = string_null;
+ float i;
+ for (i = 0; i < QUICKMENU_MAXLINES; ++i)
+ HUD_QuickMenu_clear_entry(i);
+ QuickMenu_Entries = 0;
+ hud_panel_quickmenu = 0;
+ mouseClicked = 0;
+ prevMouseClicked = 0;
+ HUD_QuickMenu_Buffer_Close();
+
+ if(autocvar_hud_cursormode)
+ if(!mv_active)
+ setcursormode(0);
+ }
+
+ // It assumes submenu open tag is already detected
+ void HUD_QuickMenu_skip_submenu(string submenu)
+ {
+ string s, z_submenu;
+ z_submenu = strzone(submenu);
+ for(++QuickMenu_Buffer_Index ; QuickMenu_Buffer_Index < QuickMenu_Buffer_Size; ++QuickMenu_Buffer_Index)
+ {
+ s = bufstr_get(QuickMenu_Buffer, QuickMenu_Buffer_Index);
+ float argc;
+ argc = tokenize_console(s);
+ if(argc == 2)
+ continue;
+ if (argv(0) == "")
+ continue;
+ if (argv(0) == z_submenu) // submenu end
+ break;
+ HUD_QuickMenu_skip_submenu(argv(0));
+ }
+ strunzone(z_submenu);
+ }
+
+ float HUD_QuickMenu_IsOpened()
+ {
+ return (QuickMenu_Entries > 0);
+ }
+
+ // new_page 0 means page 0, new_page != 0 means next page
+ float QuickMenu_Buffer_Index_Prev;
+ float HUD_QuickMenu_Page(string target_submenu, float new_page)
+ {
+ string s, z_submenu;
+
+ if (new_page == 0)
+ QuickMenu_CurrentPage = 0;
+ else
+ ++QuickMenu_CurrentPage;
+ QuickMenu_CurrentPage_FirstEntry = QuickMenu_CurrentPage * (QUICKMENU_MAXLINES - 2);
+
+ z_submenu = strzone(target_submenu);
+ if (QuickMenu_CurrentSubMenu)
+ strunzone(QuickMenu_CurrentSubMenu);
+ QuickMenu_CurrentSubMenu = strzone(z_submenu);
+
+ QuickMenu_IsLastPage = TRUE;
+ QuickMenu_Entries = 0;
+
+ QuickMenu_Buffer_Index = 0;
+ if (z_submenu != "")
+ {
+ // skip everything until the submenu open tag is found
+ for( ; QuickMenu_Buffer_Index < QuickMenu_Buffer_Size; ++QuickMenu_Buffer_Index)
+ {
+ s = bufstr_get(QuickMenu_Buffer, QuickMenu_Buffer_Index);
+ if (tokenize_console(s) == 1 && argv(0) == z_submenu)
+ {
+ // print(sprintf("^3 beginning of %s\n", z_submenu));
+ ++QuickMenu_Buffer_Index;
+ break;
+ }
+ // print(sprintf("^1 skipping %s\n", s));
+ }
+ }
+ float total = 0;
+ for( ; QuickMenu_Buffer_Index < QuickMenu_Buffer_Size; ++QuickMenu_Buffer_Index)
+ {
+ s = bufstr_get(QuickMenu_Buffer, QuickMenu_Buffer_Index);
+ float argc;
+ argc = tokenize_console(s);
+
+ if (z_submenu != "" && z_submenu == argv(0))
+ {
+ // print(sprintf("^3 end of %s\n", z_submenu));
+ break;
+ }
+
+ if (total - QuickMenu_CurrentPage_FirstEntry >= 0)
+ {
+ ++QuickMenu_Entries;
+ if(QuickMenu_Entries == QUICKMENU_MAXLINES - 2)
+ QuickMenu_Buffer_Index_Prev = QuickMenu_Buffer_Index;
+ else if(QuickMenu_Entries == QUICKMENU_MAXLINES)
+ {
+ HUD_QuickMenu_clear_entry(QUICKMENU_MAXLINES - 1);
+ QuickMenu_Buffer_Index = QuickMenu_Buffer_Index_Prev;
+ QuickMenu_IsLastPage = FALSE;
+ break;
+ }
+ }
+
+ // NOTE: entries are loaded starting from 1, not from 0
+ if (argc == 1 && argv(0) != "") // submenu
+ {
+ if (total - QuickMenu_CurrentPage_FirstEntry >= 0)
+ HUD_QuickMenu_load_entry(QuickMenu_Entries, argv(0), "");
+ HUD_QuickMenu_skip_submenu(argv(0));
+ }
+ else if (total - QuickMenu_CurrentPage_FirstEntry >= 0)
+ HUD_QuickMenu_load_entry(QuickMenu_Entries, argv(0), argv(1));
+
+ ++total;
+ }
+ strunzone(z_submenu);
+ if (QuickMenu_Entries == 0)
+ {
+ HUD_QuickMenu_Close();
+ return 0;
+ }
+ return 1;
+ }
+
+ void HUD_QuickMenu_Open()
+ {
+ if(!HUD_QuickMenu_Buffer_Init()) return;
+
+ hud_panel_quickmenu = 1;
+ if(autocvar_hud_cursormode)
+ setcursormode(1);
+ hudShiftState = 0;
+
+ HUD_QuickMenu_Page("", 0);
+ }
+
+ float HUD_QuickMenu_ActionForNumber(float num)
+ {
+ if (!QuickMenu_IsLastPage)
+ {
+ if (num < 0 || num >= QUICKMENU_MAXLINES)
+ return 0;
+ if (num == QUICKMENU_MAXLINES - 1)
+ return 0;
+ if (num == 0)
+ {
+ HUD_QuickMenu_Page(QuickMenu_CurrentSubMenu, +1);
+ return 0;
+ }
+ } else if (num <= 0 || num > QuickMenu_Entries)
+ return 0;
+
+ if (QuickMenu_Command[num] != "")
+ {
+ localcmd(strcat("\n", QuickMenu_Command[num], "\n"));
+ return 1;
+ }
+ if (QuickMenu_Description[num] != "")
+ HUD_QuickMenu_Page(QuickMenu_Description[num], 0);
+ return 0;
+ }
+
+ float HUD_QuickMenu_InputEvent(float bInputType, float nPrimary, float nSecondary)
+ {
+ // we only care for keyboard events
+ if(bInputType == 2)
+ return false;
+
+ if(!HUD_QuickMenu_IsOpened() || autocvar__hud_configure || mv_active)
+ return false;
+
+ if(bInputType == 3)
+ {
+ mousepos_x = nPrimary;
+ mousepos_y = nSecondary;
+ return true;
+ }
+
+ // allow console bind to work
+ string con_keys;
+ float keys;
+ con_keys = findkeysforcommand("toggleconsole", 0);
+ keys = tokenize(con_keys); // findkeysforcommand returns data for this
+
+ float hit_con_bind = 0, i;
+ for (i = 0; i < keys; ++i)
+ {
+ if(nPrimary == stof(argv(i)))
+ hit_con_bind = 1;
+ }
+
+ if(bInputType == 0) {
+ if(nPrimary == K_ALT) hudShiftState |= S_ALT;
+ if(nPrimary == K_CTRL) hudShiftState |= S_CTRL;
+ if(nPrimary == K_SHIFT) hudShiftState |= S_SHIFT;
+ }
+ else if(bInputType == 1) {
+ if(nPrimary == K_ALT) hudShiftState -= (hudShiftState & S_ALT);
+ if(nPrimary == K_CTRL) hudShiftState -= (hudShiftState & S_CTRL);
+ if(nPrimary == K_SHIFT) hudShiftState -= (hudShiftState & S_SHIFT);
+ }
+
+ if(nPrimary == K_ESCAPE)
+ {
+ if (bInputType == 1)
+ return true;
+ HUD_QuickMenu_Close();
+ }
+ else if(nPrimary >= '0' && nPrimary <= '9')
+ {
+ if (bInputType == 1)
+ return true;
+ HUD_QuickMenu_ActionForNumber(stof(chr2str(nPrimary)));
+ }
+ if(nPrimary == K_MOUSE1)
+ {
+ if(bInputType == 0) // key pressed
+ mouseClicked |= S_MOUSE1;
+ else if(bInputType == 1) // key released
+ mouseClicked -= (mouseClicked & S_MOUSE1);
+ }
+ else if(nPrimary == K_MOUSE2)
+ {
+ if(bInputType == 0) // key pressed
+ mouseClicked |= S_MOUSE2;
+ else if(bInputType == 1) // key released
+ mouseClicked -= (mouseClicked & S_MOUSE2);
+ }
+ else if(hit_con_bind)
+ return false;
+
+ return true;
+ }
+ void HUD_QuickMenu_Mouse()
+ {
+ if(mv_active) return;
+
+ if(!mouseClicked)
+ if(prevMouseClicked & S_MOUSE2)
+ {
+ HUD_QuickMenu_Close();
+ return;
+ }
+
+ if(!autocvar_hud_cursormode)
+ {
+ mousepos = mousepos + getmousepos() * autocvar_menu_mouse_speed;
+
+ mousepos_x = bound(0, mousepos_x, vid_conwidth);
+ mousepos_y = bound(0, mousepos_y, vid_conheight);
+ }
+
+ HUD_Panel_UpdateCvars()
+
+ if(panel_bg_padding)
+ {
+ panel_pos += '1 1 0' * panel_bg_padding;
+ panel_size -= '2 2 0' * panel_bg_padding;
+ }
+
+ float first_entry_pos, entries_height;
+ vector fontsize;
+ fontsize = '1 1 0' * (panel_size_y / QUICKMENU_MAXLINES);
+ first_entry_pos = panel_pos_y + ((QUICKMENU_MAXLINES - QuickMenu_Entries) * fontsize_y) / 2;
+ entries_height = panel_size_y - ((QUICKMENU_MAXLINES - QuickMenu_Entries) * fontsize_y);
+
+ if (mousepos_x >= panel_pos_x && mousepos_y >= first_entry_pos && mousepos_x <= panel_pos_x + panel_size_x && mousepos_y <= first_entry_pos + entries_height)
+ {
+ float entry_num;
+ entry_num = floor((mousepos_y - first_entry_pos) / fontsize_y);
+ if (QuickMenu_IsLastPage || entry_num != QUICKMENU_MAXLINES - 2)
+ {
+ panel_pos_y = first_entry_pos + entry_num * fontsize_y;
+ vector color;
+ if(mouseClicked & S_MOUSE1)
+ color = '0.5 1 0.5';
+ else if(hudShiftState & S_CTRL)
+ color = '1 1 0.3';
+ else
+ color = '1 1 1';
+ drawfill(panel_pos, eX * panel_size_x + eY * fontsize_y, color, .2, DRAWFLAG_NORMAL);
+
+ if(!mouseClicked && (prevMouseClicked & S_MOUSE1))
+ {
+ float f;
+ if (entry_num < QUICKMENU_MAXLINES - 1)
+ f = HUD_QuickMenu_ActionForNumber(entry_num + 1);
+ else
+ f = HUD_QuickMenu_ActionForNumber(0);
+ if(f && !(hudShiftState & S_CTRL))
+ HUD_QuickMenu_Close();
+ }
+ }
+ }
+
+ const vector cursorsize = '32 32 0';
+ drawpic(mousepos, strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"), cursorsize, '1 1 1', 0.8, DRAWFLAG_NORMAL);
+
+ prevMouseClicked = mouseClicked;
+ }
+ void HUD_QuickMenu_DrawEntry(vector pos, string s, vector fontsize)
+ {
+ string entry;
+ float offset;
+ entry = textShortenToWidth(s, panel_size_x, fontsize, stringwidth_colors);
+ if (autocvar_hud_panel_quickmenu_align > 0)
+ {
+ offset = (panel_size_x - stringwidth_colors(entry, fontsize)) * min(autocvar_hud_panel_quickmenu_align, 1);
+ drawcolorcodedstring(pos + eX * offset, entry, fontsize, panel_fg_alpha, DRAWFLAG_ADDITIVE);
+ }
+ else
+ drawcolorcodedstring(pos, entry, fontsize, panel_fg_alpha, DRAWFLAG_ADDITIVE);
+ }
+ void HUD_QuickMenu(void)
+ {
+ if(!autocvar__hud_configure)
+ {
+ if (hud_configure_prev && hud_configure_prev != -1)
+ HUD_QuickMenu_Close();
+
+ if(!hud_draw_maximized) return;
+ if(mv_active) return;
+ //if(!autocvar_hud_panel_quickmenu) return; // autocvar exists only for conformity with other panels
+ if(!hud_panel_quickmenu) return;
+ }
+ else
+ {
+ if(!HUD_QuickMenu_IsOpened())
+ {
+ QuickMenu_Entries = 1;
+ HUD_QuickMenu_load_entry(QuickMenu_Entries, sprintf(_("Submenu%d"), QuickMenu_Entries), "");
+ ++QuickMenu_Entries;
+ HUD_QuickMenu_load_entry(QuickMenu_Entries, sprintf(_("Submenu%d"), QuickMenu_Entries), "");
+ ++QuickMenu_Entries;
+ // although real command doesn't matter here, it must not be empty
+ // otherwise the entry is displayed like a submenu
+ for (; QuickMenu_Entries < QUICKMENU_MAXLINES - 1; ++QuickMenu_Entries)
+ HUD_QuickMenu_load_entry(QuickMenu_Entries, sprintf(_("Command%d"), QuickMenu_Entries), "-");
+ ++QuickMenu_Entries;
+ HUD_QuickMenu_clear_entry(QuickMenu_Entries);
+ QuickMenu_IsLastPage = FALSE;
+ }
+ }
+
+ HUD_Panel_UpdateCvars();
+ HUD_Panel_ApplyFadeAlpha();
+
+ HUD_Panel_DrawBg(1);
+
+ if(panel_bg_padding)
+ {
+ panel_pos += '1 1 0' * panel_bg_padding;
+ panel_size -= '2 2 0' * panel_bg_padding;
+ }
+
+ float i;
+ vector fontsize;
+ string color;
+ fontsize = '1 1 0' * (panel_size_y / QUICKMENU_MAXLINES);
+
+ if (!QuickMenu_IsLastPage)
+ {
+ color = "^5";
+ HUD_QuickMenu_DrawEntry(panel_pos + eY * (panel_size_y - fontsize_y), sprintf("%d: %s%s", 0, color, _("Continue...")), fontsize);
+ }
+ else
+ panel_pos_y += ((QUICKMENU_MAXLINES - QuickMenu_Entries) * fontsize_y) / 2;
+
+ for (i = 1; i <= QuickMenu_Entries; ++i) {
+ if (QuickMenu_Description[i] == "")
+ break;
+ if (QuickMenu_Command[i] == "")
+ color = "^4";
+ else
+ color = "^3";
+ HUD_QuickMenu_DrawEntry(panel_pos, sprintf("%d: %s%s", i, color, QuickMenu_Description[i]), fontsize);
+ panel_pos_y += fontsize_y;
+ }
+ }
+
/*
==================
Main HUD system
(panel = HUD_PANEL(RADAR)).panel_draw();
if(autocvar__con_chat_maximized)
(panel = HUD_PANEL(CHAT)).panel_draw();
+ if(hud_panel_quickmenu)
+ (panel = HUD_PANEL(QUICKMENU)).panel_draw();
if(autocvar__hud_configure)
{
float hud_draw_maximized;
float hud_panel_radar_maximized;
+ float hud_panel_quickmenu;
vector mousepos;
vector panel_click_distance; // mouse cursor distance from the top left corner of the panel (saved only upon a click)
float current_player;
+ float mv_active;
+
#define HUD_PANELS \
HUD_PANEL(WEAPONS , HUD_Weapons , weapons) \
HUD_PANEL(ENGINEINFO , HUD_EngineInfo , engineinfo) \
HUD_PANEL(INFOMESSAGES , HUD_InfoMessages , infomessages) \
HUD_PANEL(PHYSICS , HUD_Physics , physics) \
- HUD_PANEL(CENTERPRINT , HUD_CenterPrint , centerprint)
+ HUD_PANEL(CENTERPRINT , HUD_CenterPrint , centerprint) \
+ HUD_PANEL(QUICKMENU , HUD_QuickMenu , quickmenu)
#define HUD_PANEL(NAME,draw_func,name) \
float HUD_PANEL_##NAME; \
strunzone(panel.current_panel_bg); \
if(panel_bg == "")\
{\
- /*print(sprintf("^xf08 %s panel: panel_bg is empty\n", panel.panel_name));*/\
+ /*printf("^xf08 %s panel: panel_bg is empty\n", panel.panel_name);*/\
panel_bg = "0";\
}\
panel.current_panel_bg = strzone(panel_bg); \
panel_bg = panel.current_panel_bg; \
if(panel.current_panel_bg == "")\
{\
- /*print(sprintf("^xf08 %s panel: panel.current_panel_bg is empty\n", panel.panel_name));*/\
+ /*printf("^xf08 %s panel: panel.current_panel_bg is empty\n", panel.panel_name);*/\
panel_bg = "0";\
}\
panel_bg_alpha = panel.current_panel_bg_alpha; \
HUD_Write_PanelCvar_q("_fade_subsequent_minfontsize");
HUD_Write_PanelCvar_q("_fade_minfontsize");
break;
+ case HUD_PANEL_QUICKMENU:
+ HUD_Write_PanelCvar_q("_align");
+ break;
}
HUD_Write("\n");
}
HUD_Write("menu_sync\n"); // force the menu to reread the cvars, so that the dialogs are updated
- print(sprintf(_("^2Successfully exported to %s! (Note: It's saved in data/data/)\n"), filename));
+ printf(_("^2Successfully exported to %s! (Note: It's saved in data/data/)\n"), filename);
fclose(fh);
}
else
- print(sprintf(_("^1Couldn't write to %s\n"), filename));
+ printf(_("^1Couldn't write to %s\n"), filename);
}
void HUD_Configure_Exit_Force()
else
{
if (!nocomplain)
- print(sprintf("^1Error:^7 Unknown score field: '%s'\n", str));
+ printf("^1Error:^7 Unknown score field: '%s'\n", str);
continue;
}
:found
hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
hud_field[hud_num_fields] = ps_secondary;
++hud_num_fields;
- print(sprintf("fixed missing field '%s'\n", scores_label[ps_secondary]));
+ printf("fixed missing field '%s'\n", scores_label[ps_secondary]);
}
if(!have_primary)
{
hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], FALSE, hud_fontsize);
hud_field[hud_num_fields] = ps_primary;
++hud_num_fields;
- print(sprintf("fixed missing field '%s'\n", scores_label[ps_primary]));
+ printf("fixed missing field '%s'\n", scores_label[ps_primary]);
}
}
float HUD_WouldDrawScoreboard() {
if (autocvar__hud_configure)
return 0;
+ else if (HUD_QuickMenu_IsOpened())
+ return 0;
else if (scoreboard_showscores)
return 1;
else if (intermission == 1)
float get_model_parameters_fixbone;
string get_model_parameters_desc;
float get_model_parameters(string mod, float skn); // call with string_null to clear; skin -1 means mod is the filename of the txt file and is to be split
-
vector vec2(vector v);
#ifndef MENUQC
// expand multiple arguments into one argument by stripping parenthesis
#define XPD(...) __VA_ARGS__
+// Some common varargs functions. Lowercase as they match C.
+#define printf(...) print(sprintf(__VA_ARGS__))
+#define dprintf(...) dprint(sprintf(__VA_ARGS__))
+#define fprintf(file, ...) fputs(file, sprintf(__VA_ARGS__))
+#define bprintf(...) bprint(sprintf(__VA_ARGS__))
+
#ifndef MENUQC
void backtrace(string msg);
#endif