mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-25 13:21:36 +00:00
ef8c96667e
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2974 fc73d0e0-1445-4013-8a0c-d673dee63da5
2348 lines
49 KiB
C
2348 lines
49 KiB
C
#include "../plugin.h"
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning(4: 4244)
|
|
#pragma warning(4: 4305)
|
|
#endif
|
|
|
|
#define DEFAULTHUDNAME "ftehud.hud"
|
|
|
|
#define MAX_ELEMENTS 128
|
|
|
|
int K_UPARROW;
|
|
int K_DOWNARROW;
|
|
int K_LEFTARROW;
|
|
int K_RIGHTARROW;
|
|
int K_ESCAPE;
|
|
int K_MOUSE1;
|
|
int K_MOUSE2;
|
|
int K_HOME;
|
|
int K_SHIFT;
|
|
int K_MWHEELDOWN;
|
|
int K_MWHEELUP;
|
|
int K_PAGEUP;
|
|
int K_PAGEDOWN;
|
|
|
|
|
|
#define MAX_CL_STATS 32
|
|
#define STAT_HEALTH 0
|
|
#define STAT_WEAPON 2
|
|
#define STAT_AMMO 3
|
|
#define STAT_ARMOR 4
|
|
#define STAT_WEAPONFRAME 5
|
|
#define STAT_SHELLS 6
|
|
#define STAT_NAILS 7
|
|
#define STAT_ROCKETS 8
|
|
#define STAT_CELLS 9
|
|
#define STAT_ACTIVEWEAPON 10
|
|
#define STAT_TOTALSECRETS 11
|
|
#define STAT_TOTALMONSTERS 12
|
|
#define STAT_SECRETS 13 // bumped on client side by svc_foundsecret
|
|
#define STAT_MONSTERS 14 // bumped by svc_killedmonster
|
|
#define STAT_ITEMS 15
|
|
|
|
// context menus
|
|
|
|
#define CONTEXT_NONE 0
|
|
#define CONTEXT_MAIN 1
|
|
#define CONTEXT_NEW_ITEM 2
|
|
#define CONTEXT_NEW_ITEM_SUB 3
|
|
|
|
//some engines can use more.
|
|
//any mod specific ones should be 31 and downwards rather than upwards.
|
|
|
|
|
|
#define IT_GUN1 (1<<0)
|
|
#define IT_GUN2 (1<<1) //the code assumes these are linear.
|
|
#define IT_GUN3 (1<<2) //be careful with strange mods.
|
|
#define IT_GUN4 (1<<3)
|
|
#define IT_GUN5 (1<<4)
|
|
#define IT_GUN6 (1<<5)
|
|
#define IT_GUN7 (1<<6)
|
|
#define IT_GUN8 (1<<7) //quake doesn't normally use this.
|
|
|
|
#define IT_AMMO1 (1<<8)
|
|
#define IT_AMMO2 (1<<9)
|
|
#define IT_AMMO3 (1<<10)
|
|
#define IT_AMMO4 (1<<11)
|
|
|
|
#define IT_GUN0 (1<<12)
|
|
|
|
#define IT_ARMOR1 (1<<13)
|
|
#define IT_ARMOR2 (1<<14)
|
|
#define IT_ARMOR3 (1<<15)
|
|
#define IT_SUPERHEALTH (1<<16)
|
|
|
|
#define IT_PUP1 (1<<17)
|
|
#define IT_PUP2 (1<<18)
|
|
#define IT_PUP3 (1<<19)
|
|
#define IT_PUP4 (1<<20)
|
|
#define IT_PUP5 (1<<21)
|
|
#define IT_PUP6 (1<<22)
|
|
|
|
#define IT_RUNE1 (1<<23)
|
|
#define IT_RUNE2 (1<<24)
|
|
#define IT_RUNE3 (1<<25)
|
|
#define IT_RUNE4 (1<<26)
|
|
|
|
//these are linear and treated the same
|
|
#define numpups 6
|
|
|
|
//the names of the cvars, as they will appear on the console
|
|
#define UI_NOSBAR "ui_defaultsbar"
|
|
#define UI_NOIBAR "ui_noibar"
|
|
#define UI_NOFLASH "ui_nosbarflash"
|
|
|
|
static char *weaponabbreviation[] = { //the postfix for the weapon anims
|
|
"shotgun", // shotgun
|
|
"sshotgun", // super shotgun
|
|
"nailgun", // nailgun
|
|
"snailgun", // super nailgun
|
|
"rlaunch", // grenade launcher
|
|
"srlaunch", // rocket launcher
|
|
"lightng" // thunderbolt
|
|
};
|
|
#define numweaps (sizeof(weaponabbreviation) / sizeof(char *))
|
|
|
|
static char *pupabbr[] = { //the postfix for the powerup anims
|
|
"key1",
|
|
"key2",
|
|
"invis",
|
|
"invul",
|
|
"suit",
|
|
"quad"
|
|
};
|
|
static char *pupabbr2[] = { //the postfix for the powerup anims
|
|
"key1",
|
|
"key2",
|
|
"invis",
|
|
"invuln",
|
|
"suit",
|
|
"quad"
|
|
};
|
|
|
|
//0 = owned, 1 selected, 2-7 flashing
|
|
static qhandle_t pic_cursor;
|
|
static qhandle_t con_chars;
|
|
static qhandle_t pic_weapon[8][numweaps];
|
|
static qhandle_t sbarback, ibarback;
|
|
|
|
//0 = owned, 1-6 flashing
|
|
static qhandle_t pic_pup[7][numpups];
|
|
static qhandle_t pic_armour[3];
|
|
static qhandle_t pic_ammo[4];
|
|
static qhandle_t pic_rune[4];
|
|
static qhandle_t pic_num[13];
|
|
static qhandle_t pic_anum[11];
|
|
|
|
//faces
|
|
static qhandle_t pic_face[5];
|
|
static qhandle_t pic_facep[5];
|
|
static qhandle_t pic_facequad;
|
|
static qhandle_t pic_faceinvis;
|
|
static qhandle_t pic_faceinvisinvuln;
|
|
static qhandle_t pic_faceinvuln;
|
|
//static qhandle_t pic_faceinvulnquad;
|
|
|
|
static int currenttime;
|
|
static int gotweapontime[numweaps];
|
|
static int gotpuptime[numpups];
|
|
|
|
float sbarminx;
|
|
float sbarminy;
|
|
float sbarscalex;
|
|
float sbarscaley;
|
|
float sbaralpha;
|
|
int sbartype;
|
|
int sbarindex;
|
|
|
|
static int hudedit;
|
|
static int typetoinsert;
|
|
|
|
enum {
|
|
DZ_BOTTOMLEFT,
|
|
DZ_BOTTOMRIGHT
|
|
};
|
|
|
|
typedef void drawelementfnc_t(void);
|
|
typedef struct {
|
|
float defaultx; //used if couldn't load a config
|
|
float defaulty;
|
|
int defaultzone;
|
|
float defaultalpha;
|
|
drawelementfnc_t *DrawElement;
|
|
int subtype;
|
|
} huddefaultelement_t;
|
|
|
|
|
|
|
|
|
|
|
|
drawelementfnc_t Hud_SBar;
|
|
drawelementfnc_t Hud_StatSmall;
|
|
drawelementfnc_t Hud_StatBig;
|
|
drawelementfnc_t Hud_ArmourPic;
|
|
drawelementfnc_t Hud_HealthPic;
|
|
drawelementfnc_t Hud_CurrentAmmoPic;
|
|
drawelementfnc_t Hud_IBar;
|
|
drawelementfnc_t Hud_Weapon;
|
|
drawelementfnc_t Hud_W_Lightning;
|
|
drawelementfnc_t Hud_Powerup;
|
|
drawelementfnc_t Hud_Rune;
|
|
drawelementfnc_t Hud_Ammo;
|
|
drawelementfnc_t Hud_ScoreCard;
|
|
drawelementfnc_t Hud_ScoreName;
|
|
drawelementfnc_t Hud_Blackness;
|
|
drawelementfnc_t Hud_TeamScore;
|
|
drawelementfnc_t Hud_TeamName;
|
|
drawelementfnc_t Hud_Tracking;
|
|
drawelementfnc_t Hud_TeamOverlay;
|
|
// TODO: more elements
|
|
// - generalized graphic elements
|
|
// - cvar controlled small and big numbers
|
|
// - alias controlled graphic elements (both +/-showscores like and alias calling?)
|
|
// - Q2-style current weapon icon
|
|
|
|
int statsremap[] =
|
|
{
|
|
STAT_HEALTH,
|
|
STAT_ARMOR,
|
|
STAT_AMMO,
|
|
STAT_SHELLS,
|
|
STAT_NAILS,
|
|
STAT_ROCKETS,
|
|
STAT_CELLS
|
|
};
|
|
|
|
struct subtypenames {
|
|
char *name;
|
|
};
|
|
typedef struct {
|
|
drawelementfnc_t *draw;
|
|
char *name;
|
|
int width, height;
|
|
int maxsubtype;
|
|
struct subtypenames subtypename[20];
|
|
} drawelement_t;
|
|
drawelement_t drawelement[] =
|
|
{
|
|
{Hud_SBar, "Status bar", 320, 24, 0},
|
|
{Hud_StatSmall, "Stat (small)", 8*3, 8, 6, {"Health", "Armour", "Ammo", "Shells", "Nails", "Rockets", "Cells"}}, // equal to sizeof(statsremap)/sizeof(statsremap[0])-1
|
|
{Hud_StatBig, "Stat (big)", 24*3, 24, 6, {"Health", "Armour", "Ammo", "Shells", "Nails", "Rockets", "Cells"}}, // equal to sizeof(statsremap)/sizeof(statsremap[0])-1
|
|
{Hud_ArmourPic, "Armor pic", 24, 24, 0},
|
|
{Hud_HealthPic, "Health pic", 24, 24, 0},
|
|
{Hud_CurrentAmmoPic, "Ammo pic", 24, 24, 0},
|
|
{Hud_IBar, "Info bar", 320, 24, 0},
|
|
{Hud_Weapon, "Weapon pic", 24, 16, 6, {"Shotgun", "Super Shotgun", "Nailgun", "Super Nailgun", "Grenade Launcher", "Rocket Launcher", "Thunderbolt"}},
|
|
{Hud_W_Lightning, "Shaft pic", 24, 16, 0},
|
|
{Hud_Powerup, "Powerup pic", 16, 16, 5, {"Key 1", "Key 2", "Ring of Invis", "Pentagram", "Biosuit", "Quad"}},
|
|
{Hud_Rune, "Rune pic", 8, 16, 3, {"Rune 1", "Rune 2", "Rune 3", "Rune 4"}},
|
|
{Hud_Ammo, "Ammo display", 42, 11, 3, {"Shells", "Spikes", "Rockets", "Cells"}},
|
|
{Hud_Blackness, "Blackness", 16, 16, 9, {"10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "100%"}},
|
|
{Hud_ScoreCard, "Scorecard", 32, 8, 15, {"Player 0", "Player 1", "Player 2", "Player 3", "Player 4", "Player 5", "Player 6", "Player 7", "Player 8", "Player 9", "Player 10", "Player 11", "Player 12", "Player 13", "Player 14", "Player 15"}},
|
|
{Hud_ScoreName, "Scorename", 128, 8, 7, {"Player 0", "Player 1", "Player 2", "Player 3", "Player 4", "Player 5", "Player 6", "Player 7"}},
|
|
{Hud_TeamScore, "TeamScore", 32, 8, 7, {"Team 0", "Team 1", "Team 2", "Team 3", "Team 4", "Team 5", "Team 6", "Team 7"}},
|
|
{Hud_TeamName, "TeamName", 128, 8, 7, {"Team 0", "Team 1", "Team 2", "Team 3", "Team 4", "Team 5", "Team 6", "Team 7"}},
|
|
{Hud_Tracking, "Tracking", 128, 8, 0},
|
|
{Hud_TeamOverlay, "Team overlay", 256, 64, 0}
|
|
};
|
|
|
|
huddefaultelement_t hedefaulttype[] = {
|
|
{
|
|
0, -24, DZ_BOTTOMLEFT,
|
|
0.3f,
|
|
Hud_SBar
|
|
},
|
|
|
|
{
|
|
0, -24, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_ArmourPic
|
|
},
|
|
{
|
|
24, -24, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_StatBig,
|
|
1
|
|
},
|
|
|
|
{
|
|
112, -24, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_HealthPic
|
|
},
|
|
{
|
|
24*6, -24, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_StatBig,
|
|
0
|
|
},
|
|
|
|
{
|
|
224, -24, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_CurrentAmmoPic
|
|
},
|
|
{
|
|
248, -24, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_StatBig,
|
|
2
|
|
},
|
|
|
|
{
|
|
0, -48, DZ_BOTTOMLEFT,
|
|
0.3f,
|
|
Hud_IBar
|
|
},
|
|
|
|
{
|
|
0, -40, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_Weapon,
|
|
0
|
|
},
|
|
{
|
|
24, -40, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_Weapon,
|
|
1
|
|
},
|
|
{
|
|
48, -40, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_Weapon,
|
|
2
|
|
},
|
|
{
|
|
72, -40, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_Weapon,
|
|
3
|
|
},
|
|
{
|
|
96, -40, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_Weapon,
|
|
4
|
|
},
|
|
{
|
|
120, -40, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_Weapon,
|
|
5
|
|
},
|
|
{
|
|
146, -40, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_W_Lightning
|
|
},
|
|
{
|
|
194, -40, DZ_BOTTOMLEFT,
|
|
0.3f,
|
|
Hud_Powerup,
|
|
0
|
|
},
|
|
{
|
|
208, -40, DZ_BOTTOMLEFT,
|
|
0.3f,
|
|
Hud_Powerup,
|
|
1
|
|
},
|
|
{
|
|
224, -40, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_Powerup,
|
|
2
|
|
},
|
|
{
|
|
240, -40, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_Powerup,
|
|
3
|
|
},
|
|
{
|
|
256, -40, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_Powerup,
|
|
4
|
|
},
|
|
{
|
|
272, -40, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_Powerup,
|
|
5
|
|
},
|
|
{
|
|
288, -40, DZ_BOTTOMLEFT,
|
|
0.3f,
|
|
Hud_Rune,
|
|
0
|
|
},
|
|
{
|
|
296, -40, DZ_BOTTOMLEFT,
|
|
0.3f,
|
|
Hud_Rune,
|
|
1
|
|
},
|
|
{
|
|
304, -40, DZ_BOTTOMLEFT,
|
|
0.3f,
|
|
Hud_Rune,
|
|
2
|
|
},
|
|
{
|
|
312, -40, DZ_BOTTOMLEFT,
|
|
0.3f,
|
|
Hud_Rune,
|
|
3
|
|
},
|
|
|
|
{
|
|
48*0+3, -48, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_Ammo,
|
|
0
|
|
},
|
|
{
|
|
48*1+3, -48, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_Ammo,
|
|
1
|
|
},
|
|
{
|
|
48*2+3, -48, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_Ammo,
|
|
2
|
|
},
|
|
{
|
|
48*3+3, -48, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_Ammo,
|
|
3
|
|
},
|
|
|
|
{
|
|
42*3, -48, DZ_BOTTOMLEFT,
|
|
1,
|
|
Hud_ScoreCard
|
|
}
|
|
};
|
|
typedef struct {
|
|
int type;
|
|
int subtype;
|
|
|
|
float x, y;
|
|
float scalex;
|
|
float scaley;
|
|
float alpha;
|
|
} hudelement_t;
|
|
hudelement_t element[MAX_ELEMENTS]; //look - Spike used a constant - that's a turn up for the books!
|
|
int numelements;
|
|
|
|
int currentitem;
|
|
int hoveritem;
|
|
qboolean mousedown, shiftdown;
|
|
float mouseofsx, mouseofsy;
|
|
qboolean context;
|
|
|
|
vec3_t player_location[32];
|
|
int player_armor[32];
|
|
int player_health[32];
|
|
unsigned int player_items[32];
|
|
char *player_nick[32] =
|
|
{
|
|
"", "", "", "", "", "", "", "",
|
|
"", "", "", "", "", "", "", "",
|
|
"", "", "", "", "", "", "", "",
|
|
"", "", "", "", "", "", "", ""
|
|
};
|
|
unsigned int player_nicklength;
|
|
|
|
void Hud_TeamOverlayUpdate(void);
|
|
|
|
/*
|
|
==================
|
|
COM_DefaultExtension
|
|
==================
|
|
*/
|
|
void COM_DefaultExtension (char *path, char *extension, int maxlen)
|
|
{
|
|
char *src;
|
|
//
|
|
// if path doesn't have a .EXT, append extension
|
|
// (extension should include the .)
|
|
//
|
|
src = path + strlen(path) - 1;
|
|
|
|
while (*src != '/' && src != path)
|
|
{
|
|
if (*src == '.')
|
|
return; // it has an extension
|
|
src--;
|
|
}
|
|
|
|
strlcpy (path+strlen(path), extension, maxlen);
|
|
}
|
|
|
|
void UI_DrawPic(qhandle_t pic, int x, int y, int width, int height)
|
|
{
|
|
Draw_Image((float)x*sbarscalex+sbarminx, (float)y*sbarscaley+sbarminy, (float)width*sbarscalex, (float)height*sbarscaley, 0, 0, 1, 1, pic);
|
|
}
|
|
void UI_DrawChar(unsigned int c, int x, int y)
|
|
{
|
|
static float size = 1.0f/16.0f;
|
|
float s1 = size * (c&15);
|
|
float t1 = size * ((c>>4)&15);
|
|
Draw_Image((float)x*sbarscalex+sbarminx, (float)y*sbarscaley+sbarminy, 8*sbarscalex, 8*sbarscaley, s1, t1, s1+size, t1+size, con_chars);
|
|
}
|
|
void UI_DrawString(char *s, int x, int y)
|
|
{
|
|
while(*s)
|
|
{
|
|
UI_DrawChar((unsigned int)*s++, x, y);
|
|
x+=8;
|
|
}
|
|
}
|
|
void UI_DrawAltString(char *s, int x, int y, qboolean shouldmask)
|
|
{
|
|
int mask = shouldmask?128:0;
|
|
while(*s)
|
|
{
|
|
UI_DrawChar((unsigned int)*s++ | mask, x, y);
|
|
x+=8;
|
|
}
|
|
}
|
|
|
|
|
|
void UI_DrawBigNumber(int num, int x, int y, qboolean red)
|
|
{
|
|
char *s;
|
|
int len;
|
|
s = va("%i", num);
|
|
|
|
|
|
len = strlen(s);
|
|
if (len < 3)
|
|
x += 24*(3-len);
|
|
else
|
|
s += len-3;
|
|
|
|
if (red)
|
|
{
|
|
while(*s)
|
|
{
|
|
if (*s == '-')
|
|
UI_DrawPic (pic_anum[10], x, y, 24, 24);
|
|
else
|
|
UI_DrawPic (pic_anum[*s-'0'], x, y, 24, 24);
|
|
s++;
|
|
x+=24;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while(*s)
|
|
{
|
|
if (*s == '-')
|
|
UI_DrawPic (pic_num[10], x, y, 24, 24);
|
|
else
|
|
UI_DrawPic (pic_num[*s-'0'], x, y, 24, 24);
|
|
s++;
|
|
x+=24;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SBar_FlushAll(void)
|
|
{
|
|
numelements = 0;
|
|
}
|
|
|
|
static int idxforfunc(drawelementfnc_t *fnc)
|
|
{
|
|
int i;
|
|
for (i = 0; i < sizeof(drawelement)/sizeof(drawelement[0]); i++)
|
|
{
|
|
if (drawelement[i].draw == fnc)
|
|
return i;
|
|
}
|
|
return -10000; //try and crash
|
|
}
|
|
|
|
void SBar_ReloadDefaults(void)
|
|
{
|
|
int i;
|
|
for (i = 0; i < sizeof(hedefaulttype)/sizeof(hedefaulttype[0]); i++)
|
|
{
|
|
if (hedefaulttype[i].defaultalpha)
|
|
{
|
|
if (numelements >= MAX_ELEMENTS)
|
|
break;
|
|
element[numelements].type = idxforfunc(hedefaulttype[i].DrawElement);
|
|
element[numelements].alpha = hedefaulttype[i].defaultalpha;
|
|
element[numelements].scalex = 1;
|
|
element[numelements].scaley = 1;
|
|
element[numelements].subtype = hedefaulttype[i].subtype;
|
|
switch(hedefaulttype[i].defaultzone)
|
|
{
|
|
case DZ_BOTTOMLEFT:
|
|
element[numelements].x = hedefaulttype[i].defaultx;
|
|
element[numelements].y = 480+hedefaulttype[i].defaulty;
|
|
break;
|
|
case DZ_BOTTOMRIGHT:
|
|
element[numelements].x = 640+hedefaulttype[i].defaultx;
|
|
element[numelements].y = 480+hedefaulttype[i].defaulty;
|
|
break;
|
|
}
|
|
numelements++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void UI_SbarInit(void)
|
|
{
|
|
int i;
|
|
int j;
|
|
|
|
//main bar (add cvars later)
|
|
ibarback = Draw_LoadImage("ibar", true);
|
|
sbarback = Draw_LoadImage("sbar", true);
|
|
|
|
con_chars = Draw_LoadImage("conchars", true);
|
|
|
|
//load images.
|
|
for (i = 0; i < 10; i++)
|
|
{
|
|
pic_num[i] = Draw_LoadImage(va("num_%i", i), true);
|
|
pic_anum[i] = Draw_LoadImage(va("anum_%i", i), true);
|
|
}
|
|
pic_num[10] = Draw_LoadImage("num_minus", true);
|
|
pic_anum[10] = Draw_LoadImage("anum_minus", true);
|
|
pic_num[11] = Draw_LoadImage("num_colon", true);
|
|
pic_num[12] = Draw_LoadImage("num_slash", true);
|
|
|
|
for (i = 0; i < numweaps; i++)
|
|
{
|
|
gotweapontime[i] = 0;
|
|
pic_weapon[0][i] = Draw_LoadImage(va("inv_%s", weaponabbreviation[i]), true);
|
|
pic_weapon[1][i] = Draw_LoadImage(va("inv2_%s", weaponabbreviation[i]), true);
|
|
for (j = 0; j < 5; j++)
|
|
{
|
|
pic_weapon[2+j][i] = Draw_LoadImage(va("inva%i_%s", j+1, weaponabbreviation[i]), true);
|
|
}
|
|
}
|
|
for (i = 0; i < numpups; i++)
|
|
{
|
|
gotpuptime[i] = 0;
|
|
pic_pup[0][i] = Draw_LoadImage(va("sb_%s", pupabbr2[i]), true);
|
|
for (j = 0; j < 5; j++)
|
|
{
|
|
pic_pup[1+j][i] = Draw_LoadImage(va("sba%i_%s", j+1, pupabbr[i]), true);
|
|
}
|
|
}
|
|
pic_cursor = Draw_LoadImage("gfx/cursor", false);
|
|
|
|
pic_armour[0] = Draw_LoadImage("sb_armor1", true);
|
|
pic_armour[1] = Draw_LoadImage("sb_armor2", true);
|
|
pic_armour[2] = Draw_LoadImage("sb_armor3", true);
|
|
|
|
pic_ammo[0] = Draw_LoadImage("sb_shells", true);
|
|
pic_ammo[1] = Draw_LoadImage("sb_nails", true);
|
|
pic_ammo[2] = Draw_LoadImage("sb_rocket", true);
|
|
pic_ammo[3] = Draw_LoadImage("sb_cells", true);
|
|
|
|
pic_rune[0] = Draw_LoadImage("sb_sigil1", true);
|
|
pic_rune[1] = Draw_LoadImage("sb_sigil2", true);
|
|
pic_rune[2] = Draw_LoadImage("sb_sigil3", true);
|
|
pic_rune[3] = Draw_LoadImage("sb_sigil4", true);
|
|
|
|
pic_face[0] = Draw_LoadImage("face1", true);
|
|
pic_face[1] = Draw_LoadImage("face2", true);
|
|
pic_face[2] = Draw_LoadImage("face3", true);
|
|
pic_face[3] = Draw_LoadImage("face4", true);
|
|
pic_face[4] = Draw_LoadImage("face5", true);
|
|
|
|
pic_facep[0] = Draw_LoadImage("face_p1", true);
|
|
pic_facep[1] = Draw_LoadImage("face_p2", true);
|
|
pic_facep[2] = Draw_LoadImage("face_p3", true);
|
|
pic_facep[3] = Draw_LoadImage("face_p4", true);
|
|
pic_facep[4] = Draw_LoadImage("face_p5", true);
|
|
|
|
pic_facequad = Draw_LoadImage("face_quad", true);
|
|
pic_faceinvis = Draw_LoadImage("face_invis", true);
|
|
pic_faceinvisinvuln = Draw_LoadImage("face_inv2", true);
|
|
pic_faceinvuln = Draw_LoadImage("face_invul2", true);
|
|
// pic_faceinvulnquad = Draw_LoadImage("face_invul1", true);
|
|
|
|
SBar_FlushAll();
|
|
SBar_ReloadDefaults();
|
|
}
|
|
|
|
unsigned int stats[MAX_CL_STATS];
|
|
|
|
void Hud_SBar(void)
|
|
{
|
|
UI_DrawPic(sbarback, 0, 0, 320, 24);
|
|
}
|
|
|
|
void Hud_ArmourPic(void)
|
|
{
|
|
if (stats[STAT_ITEMS] & IT_ARMOR3)
|
|
UI_DrawPic(pic_armour[2], 0, 0, 24, 24);
|
|
else if (stats[STAT_ITEMS] & IT_ARMOR2)
|
|
UI_DrawPic(pic_armour[1], 0, 0, 24, 24);
|
|
else if (stats[STAT_ITEMS] & IT_ARMOR1 || hudedit)
|
|
UI_DrawPic(pic_armour[0], 0, 0, 24, 24);
|
|
}
|
|
|
|
void Hud_HealthPic(void)
|
|
{
|
|
int hl;
|
|
|
|
if (stats[STAT_ITEMS] & IT_PUP3)
|
|
{ //invisability
|
|
if (stats[STAT_ITEMS] & IT_PUP4)
|
|
UI_DrawPic(pic_faceinvisinvuln, 0, 0, 24, 24);
|
|
else
|
|
UI_DrawPic(pic_faceinvis, 0, 0, 24, 24);
|
|
return;
|
|
}
|
|
|
|
if (stats[STAT_ITEMS] & IT_PUP4)
|
|
{ //invuln
|
|
// if (stats[STAT_ITEMS] & IT_PUP6)
|
|
// UI_DrawPic(pic_faceinvulnquad, 0, 0, 24, 24);
|
|
// else
|
|
UI_DrawPic(pic_faceinvuln, 0, 0, 24, 24);
|
|
return;
|
|
}
|
|
if (stats[STAT_ITEMS] & IT_PUP6)
|
|
{
|
|
UI_DrawPic(pic_facequad, 0, 0, 24, 24);
|
|
return;
|
|
}
|
|
|
|
hl = stats[STAT_HEALTH]/20;
|
|
if (hl > 4)
|
|
hl = 4;
|
|
if (hl < 0)
|
|
hl = 0;
|
|
|
|
//FIXME
|
|
// if (innpain)
|
|
// UI_DrawPic(pic_facep[4-hl], 0, 0, 24, 24);
|
|
// else
|
|
UI_DrawPic(pic_face[4-hl], 0, 0, 24, 24);
|
|
}
|
|
|
|
void Hud_StatBig(void)
|
|
{
|
|
int i = stats[statsremap[sbartype]];
|
|
|
|
UI_DrawBigNumber(i, 0, 0, i < 25);
|
|
}
|
|
|
|
void Hud_StatSmall(void)
|
|
{
|
|
int i = stats[statsremap[sbartype]];
|
|
|
|
// TODO: need some sort of options thing to change between brown/white/gold text
|
|
UI_DrawChar(i%10+18, 19, 0);
|
|
i/=10;
|
|
if (i)
|
|
UI_DrawChar(i%10+18, 11, 0);
|
|
i/=10;
|
|
if (i)
|
|
UI_DrawChar(i%10+18, 3, 0);
|
|
}
|
|
|
|
void Hud_CurrentAmmoPic(void)
|
|
{
|
|
if ((stats[STAT_ITEMS] & IT_AMMO1))
|
|
UI_DrawPic(pic_ammo[0], 0, 0, 24, 24);
|
|
else if (stats[STAT_ITEMS] & IT_AMMO2)
|
|
UI_DrawPic(pic_ammo[1], 0, 0, 24, 24);
|
|
else if (stats[STAT_ITEMS] & IT_AMMO3)
|
|
UI_DrawPic(pic_ammo[2], 0, 0, 24, 24);
|
|
else if (stats[STAT_ITEMS] & IT_AMMO4 || hudedit)
|
|
UI_DrawPic(pic_ammo[3], 0, 0, 24, 24);
|
|
}
|
|
|
|
void Hud_IBar(void)
|
|
{
|
|
UI_DrawPic(ibarback, 0, 0, 320, 24);
|
|
}
|
|
|
|
void Hud_Weapon(void)
|
|
{
|
|
int flash;
|
|
if (!(stats[STAT_ITEMS] & (IT_GUN1 << sbartype)) && !hudedit)
|
|
{
|
|
gotweapontime[sbartype] = 0;
|
|
return;
|
|
}
|
|
|
|
if (!gotweapontime[sbartype])
|
|
gotweapontime[sbartype] = currenttime;
|
|
flash = (currenttime - gotweapontime[sbartype])/100;
|
|
if (flash < 0) //errr... whoops...
|
|
flash = 0;
|
|
|
|
if (flash > 10)
|
|
{
|
|
if (stats[STAT_ACTIVEWEAPON] & (IT_GUN1 << sbartype))
|
|
flash = 1; //selected.
|
|
else
|
|
flash = 0;
|
|
}
|
|
else
|
|
flash = (flash%5) + 2;
|
|
|
|
UI_DrawPic(pic_weapon[flash][sbartype], 0, 0, 24, 16);
|
|
}
|
|
|
|
void Hud_W_HalfLightning(void) //left half only (needed due to LG icon being twice as wide)
|
|
{
|
|
int flash;
|
|
int wnum = 6;
|
|
|
|
if (!(stats[STAT_ITEMS] & (IT_GUN1 << wnum)) && !hudedit)
|
|
{
|
|
gotweapontime[wnum] = 0;
|
|
return;
|
|
}
|
|
|
|
if (!gotweapontime[wnum])
|
|
gotweapontime[wnum] = currenttime;
|
|
flash = (currenttime - gotweapontime[wnum])/100;
|
|
if (flash < 0) //errr... whoops...
|
|
flash = 0;
|
|
|
|
if (flash > 10)
|
|
{
|
|
if (stats[STAT_ACTIVEWEAPON] & (IT_GUN1 << wnum))
|
|
flash = 1; //selected.
|
|
else
|
|
flash = 0;
|
|
}
|
|
else
|
|
flash = (flash%5) + 2;
|
|
|
|
Draw_Image(sbarminx, sbarminy, (float)24*sbarscalex, (float)16*sbarscaley, 0, 0, 0.5, 1, pic_weapon[flash][wnum]);
|
|
}
|
|
void Hud_W_Lightning(void)
|
|
{
|
|
int flash;
|
|
int wnum = 6;
|
|
|
|
if (!(stats[STAT_ITEMS] & (IT_GUN1 << wnum)) && !hudedit)
|
|
{
|
|
gotweapontime[wnum] = 0;
|
|
return;
|
|
}
|
|
|
|
if (!gotweapontime[wnum])
|
|
gotweapontime[wnum] = currenttime;
|
|
flash = (currenttime - gotweapontime[wnum])/100;
|
|
if (flash < 0) //errr... whoops...
|
|
flash = 0;
|
|
|
|
if (flash > 10)
|
|
{
|
|
if (stats[STAT_ACTIVEWEAPON] & (IT_GUN1 << wnum))
|
|
flash = 1; //selected.
|
|
else
|
|
flash = 0;
|
|
}
|
|
else
|
|
flash = (flash%5) + 2;
|
|
|
|
UI_DrawPic(pic_weapon[flash][wnum], 0, 0, 48, 16);
|
|
}
|
|
|
|
void Hud_Powerup(void)
|
|
{
|
|
int flash;
|
|
if (!(stats[STAT_ITEMS] & (IT_PUP1 << sbartype)) && !hudedit)
|
|
return;
|
|
|
|
if (!gotpuptime[sbartype])
|
|
gotpuptime[sbartype] = currenttime;
|
|
flash = (currenttime - gotpuptime[sbartype])/100;
|
|
if (flash < 0) //errr... whoops...
|
|
flash = 0;
|
|
|
|
if (flash > 10)
|
|
{
|
|
flash = 0;
|
|
}
|
|
else
|
|
flash = (flash%5) + 2;
|
|
|
|
UI_DrawPic(pic_pup[flash][sbartype], 0, 0, 16, 16);
|
|
}
|
|
|
|
void Hud_Rune(void)
|
|
{
|
|
if (!(stats[STAT_ITEMS] & (IT_RUNE1 << sbartype)) && !hudedit)
|
|
return;
|
|
UI_DrawPic(pic_rune[sbartype], 0, 0, 8, 16);
|
|
}
|
|
|
|
void Hud_Ammo(void)
|
|
{
|
|
int num;
|
|
Draw_Image(sbarminx, sbarminy, (float)42*sbarscalex, (float)11*sbarscaley, (3+(sbartype*48))/320.0f, 0, (3+(sbartype*48)+42)/320.0f, 11/24.0f, ibarback);
|
|
|
|
num = stats[STAT_SHELLS+sbartype];
|
|
if (hudedit)
|
|
num = 999;
|
|
|
|
UI_DrawChar(num%10+18, 19, 0);
|
|
num/=10;
|
|
if (num)
|
|
UI_DrawChar(num%10+18, 11, 0);
|
|
num/=10;
|
|
if (num)
|
|
UI_DrawChar(num%10+18, 3, 0);
|
|
}
|
|
|
|
float pc[16][3] =
|
|
{
|
|
/*
|
|
{235, 235, 235},
|
|
{143, 111, 035},
|
|
{139, 139, 203},
|
|
{107, 107, 015},
|
|
{127, 000, 000},
|
|
{175, 103, 035},
|
|
{255, 243, 027},
|
|
{227, 179, 151},
|
|
{171, 139, 163},
|
|
{187, 115, 159},
|
|
{219, 195, 187},
|
|
{111, 131, 123},
|
|
{255, 243, 027},
|
|
{000, 000, 255},
|
|
{247, 211, 139}
|
|
*/
|
|
{0.922, 0.922, 0.922},
|
|
{0.560, 0.436, 0.137},
|
|
{0.545, 0.545, 0.796},
|
|
{0.420, 0.420, 0.059},
|
|
{0.498, 0.000, 0.000},
|
|
{0.686, 0.404, 0.137},
|
|
{1.000, 0.953, 0.106},
|
|
{0.890, 0.702, 0.592},
|
|
{0.671, 0.545, 0.639},
|
|
{0.733, 0.451, 0.624},
|
|
{0.859, 0.765, 0.733},
|
|
{0.436, 0.514, 0.482},
|
|
{1.000, 0.953, 0.106},
|
|
{0.000, 0.000, 1.000},
|
|
{0.969, 0.827, 0.545}
|
|
};
|
|
|
|
int numsortedplayers;
|
|
int trackedplayer;
|
|
int sortedplayers[32];
|
|
plugclientinfo_t players[32];
|
|
|
|
void SortPlayers(void)
|
|
{
|
|
int i, j;
|
|
int temp;
|
|
|
|
numsortedplayers = 0;
|
|
trackedplayer = -1;
|
|
for (i = 0; i < 32; i++)
|
|
{
|
|
if (GetPlayerInfo(i, &players[i])>0)
|
|
trackedplayer = i;
|
|
if (players[i].spectator)
|
|
continue;
|
|
if (*players[i].name != 0)
|
|
sortedplayers[numsortedplayers++] = i;
|
|
}
|
|
|
|
for (i = 0; i < numsortedplayers; i++)
|
|
{
|
|
for (j = i+1; j < numsortedplayers; j++)
|
|
{
|
|
if (players[sortedplayers[i]].frags < players[sortedplayers[j]].frags)
|
|
{
|
|
temp = sortedplayers[j];
|
|
sortedplayers[j] = sortedplayers[i];
|
|
sortedplayers[i] = temp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
typedef struct {
|
|
char name[8];
|
|
int frags;
|
|
int tc;
|
|
int bc;
|
|
} teams_t;
|
|
teams_t team[32];
|
|
int numsortedteams;
|
|
|
|
void SortTeams(void)
|
|
{
|
|
teams_t temp;
|
|
int i, j;
|
|
|
|
numsortedplayers = 0;
|
|
trackedplayer = -1;
|
|
for (i = 0; i < 32; i++)
|
|
{
|
|
if (GetPlayerInfo(i, &players[i])>0)
|
|
trackedplayer = i;
|
|
if (players[i].spectator)
|
|
continue;
|
|
if (*players[i].name != 0)
|
|
sortedplayers[numsortedplayers++] = i;
|
|
|
|
for (j = 0; j < numsortedteams; j++)
|
|
{
|
|
if (!strcmp(team[j].name, players[i].name))
|
|
{
|
|
team[j].frags += players[i].frags;
|
|
while(j > 0)
|
|
{
|
|
if (team[j-1].frags < team[j].frags)
|
|
{
|
|
memcpy(&temp, &team[j], sizeof(teams_t));
|
|
memcpy(&team[j], &team[j-1], sizeof(teams_t));
|
|
memcpy(&team[j-1], &temp, sizeof(teams_t));
|
|
j--;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (j == numsortedteams)
|
|
{
|
|
strlcpy(team[j].name, players[i].name, sizeof(team[j].name));
|
|
team[j].frags = players[i].frags;
|
|
team[j].tc = players[i].topcolour;
|
|
team[j].bc = players[i].bottomcolour;
|
|
numsortedteams++;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Hud_ScoreCard(void)
|
|
{
|
|
int frags, tc, bc, p;
|
|
int brackets;
|
|
char number[6];
|
|
|
|
if (hudedit)
|
|
{
|
|
frags = sbartype;
|
|
tc = 0;
|
|
bc = 0;
|
|
brackets = 1;
|
|
}
|
|
else
|
|
{
|
|
SortPlayers();
|
|
if (sbartype>=numsortedplayers)
|
|
return;
|
|
p = sortedplayers[sbartype];
|
|
bc = players[p].bottomcolour;
|
|
tc = players[p].topcolour;
|
|
frags = players[p].frags;
|
|
brackets = p==trackedplayer;
|
|
}
|
|
|
|
Draw_Colour4f(pc[tc][0], pc[tc][1], pc[tc][2], sbaralpha);
|
|
Draw_Fill(sbarminx, sbarminy, (float)32*sbarscalex, (float)4*sbarscaley);
|
|
Draw_Colour4f(pc[bc][0], pc[bc][1], pc[bc][2], sbaralpha);
|
|
Draw_Fill(sbarminx, sbarminy+4*sbarscaley, (float)32*sbarscalex, (float)4*sbarscaley);
|
|
|
|
Draw_Colour4f(1, 1, 1, sbaralpha);
|
|
if (brackets)
|
|
{
|
|
UI_DrawChar(16, 0, 0);
|
|
UI_DrawChar(17, 24, 0);
|
|
}
|
|
|
|
snprintf(number, sizeof(number), "%-3i", frags);
|
|
UI_DrawChar(number[0], 4, 0);
|
|
UI_DrawChar(number[1], 12, 0);
|
|
UI_DrawChar(number[2], 20, 0);
|
|
|
|
Draw_Colour4f(1,1,1,1);
|
|
}
|
|
void Hud_ScoreName(void)
|
|
{
|
|
int p;
|
|
char *name;
|
|
if (hudedit)
|
|
{
|
|
name = va("Player %i", sbartype);
|
|
}
|
|
else
|
|
{
|
|
SortPlayers();
|
|
if (sbartype>=numsortedplayers)
|
|
return;
|
|
p = sortedplayers[sbartype];
|
|
name = players[p].name;
|
|
}
|
|
UI_DrawString(name, 0, 0);
|
|
}
|
|
|
|
void Hud_TeamScore(void)
|
|
{
|
|
int frags, tc, bc, p;
|
|
int brackets;
|
|
char number[6];
|
|
|
|
if (hudedit)
|
|
{
|
|
frags = sbartype;
|
|
tc = 0;
|
|
bc = 0;
|
|
brackets = 1;
|
|
}
|
|
else
|
|
{
|
|
SortPlayers();
|
|
if (sbartype>=numsortedteams)
|
|
return;
|
|
p = sbartype;
|
|
bc = team[p].bc;
|
|
tc = team[p].tc;
|
|
frags = team[p].frags;
|
|
brackets = p==trackedplayer;
|
|
}
|
|
|
|
Draw_Colour4f(pc[tc][0], pc[tc][1], pc[tc][2], sbaralpha);
|
|
Draw_Fill(sbarminx, sbarminy, (float)32*sbarscalex, (float)4*sbarscaley);
|
|
Draw_Colour4f(pc[bc][0], pc[bc][1], pc[bc][2], sbaralpha);
|
|
Draw_Fill(sbarminx, sbarminy+4*sbarscaley, (float)32*sbarscalex, (float)4*sbarscaley);
|
|
|
|
Draw_Colour4f(1, 1, 1, sbaralpha);
|
|
if (brackets)
|
|
{
|
|
UI_DrawChar(16, 0, 0);
|
|
UI_DrawChar(17, 24, 0);
|
|
}
|
|
|
|
snprintf(number, sizeof(number), "%-3i", frags);
|
|
UI_DrawChar(number[0], 4, 0);
|
|
UI_DrawChar(number[1], 12, 0);
|
|
UI_DrawChar(number[2], 20, 0);
|
|
|
|
|
|
|
|
Draw_Colour4f(1,1,1,1);
|
|
}
|
|
|
|
void Hud_TeamName(void)
|
|
{
|
|
int p;
|
|
char *tname;
|
|
|
|
if (hudedit)
|
|
{
|
|
tname = va("T%-3i", sbartype);
|
|
}
|
|
else
|
|
{
|
|
SortTeams();
|
|
if (sbartype>=numsortedteams)
|
|
return;
|
|
p = sbartype;
|
|
tname = team[p].name;
|
|
}
|
|
|
|
Draw_Colour4f(1, 1, 1, sbaralpha);
|
|
|
|
if (tname[0])
|
|
{
|
|
UI_DrawChar(tname[0], 0, 0);
|
|
if (tname[1])
|
|
{
|
|
UI_DrawChar(tname[1], 8, 0);
|
|
if (tname[2])
|
|
{
|
|
UI_DrawChar(tname[2], 8, 0);
|
|
if (tname[3])
|
|
{
|
|
UI_DrawChar(tname[3], 8, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Draw_Colour4f(1,1,1,1);
|
|
}
|
|
|
|
void Hud_TeamOverlay(void)
|
|
{
|
|
static int current_player = -1;
|
|
int offset = 0;
|
|
|
|
if (hudedit)
|
|
{
|
|
UI_DrawString("UnnamedPlayer1: r999/999 rlg ra-mega", 0, 0);
|
|
UI_DrawString("UnnamedPlayer2: r999/999 rlg ra-mega", 0, 16);
|
|
UI_DrawString("UnnamedPlayer3: r999/999 rlg ra-mega", 0, 32);
|
|
}
|
|
else
|
|
{
|
|
unsigned int i;
|
|
|
|
// If the tracking has changed, flush the old teaminfo
|
|
if (current_player != players[trackedplayer].userid)
|
|
{
|
|
int j;
|
|
|
|
for (j = 0; j < 32; j++)
|
|
player_nick[j] = "";
|
|
player_nicklength = 0;
|
|
|
|
current_player = players[trackedplayer].userid;
|
|
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < 32; i++)
|
|
{
|
|
// Empty nicknames are defined as not being printed
|
|
if (player_nick[i] != "")
|
|
{
|
|
char armortype = ' ';
|
|
char* bestweap = " ";
|
|
char loc[256], str[256], spacing[64], spacing_a[64], spacing_h[64];
|
|
unsigned int j;
|
|
|
|
// More info about armortype
|
|
if (player_items[i] & IT_ARMOR3)
|
|
armortype = 'r';
|
|
else if (player_items[i] & IT_ARMOR2)
|
|
armortype = 'y';
|
|
else if (player_items[i] & IT_ARMOR1)
|
|
armortype = 'g';
|
|
|
|
// Only care about reporting weapons that have some meaning
|
|
if ((player_items[i] & (IT_GUN6 | IT_GUN7)) == (IT_GUN6 | IT_GUN7))
|
|
bestweap = "rlg ";
|
|
else if ((player_items[i] & IT_GUN7) == IT_GUN7)
|
|
bestweap = "lg ";
|
|
else if ((player_items[i] & IT_GUN6) == IT_GUN6)
|
|
bestweap = "rl ";
|
|
else if ((player_items[i] & IT_GUN5) == IT_GUN5)
|
|
bestweap = "gl ";
|
|
else if ((player_items[i] & IT_GUN4) == IT_GUN4)
|
|
bestweap = "sng ";
|
|
else if ((player_items[i] & IT_GUN2) == IT_GUN2)
|
|
bestweap = "ssg ";
|
|
|
|
GetLocationName(player_location[i], loc, sizeof(loc));
|
|
|
|
// Format spacing
|
|
|
|
// Nicknames
|
|
for (j = 0; j < (player_nicklength - strlen(player_nick[i]) + 1) && j < sizeof(spacing); j++)
|
|
spacing[j] = ' ';
|
|
spacing[j] = '\0';
|
|
|
|
// Armor
|
|
if (player_armor[i] % 10 == player_armor[i])
|
|
strlcpy(spacing_a, " ", sizeof(spacing_a)); // 0 - 9
|
|
else if (player_armor[i] % 100 == player_armor[i])
|
|
strlcpy(spacing_a, " ", sizeof(spacing_a)); // 10 - 99
|
|
else
|
|
strlcpy(spacing_a, "", sizeof(spacing_a));
|
|
|
|
// Health
|
|
if (player_health[i] % 10 == player_health[i])
|
|
strlcpy(spacing_h, " ", sizeof(spacing_h)); // 0 - 9
|
|
else if (player_health[i] % 100 == player_health[i])
|
|
strlcpy(spacing_h, " ", sizeof(spacing_h)); // 10 - 99
|
|
else
|
|
strlcpy(spacing_h, "", sizeof(spacing_h));
|
|
|
|
// TODO: Translate $5 and similar macros in loc names.
|
|
snprintf(str, sizeof(str), "%s%c%s%s%c%d%c%d %s%s%c%s%c",
|
|
player_nick[i], // player netname
|
|
':'+128, // colored colon
|
|
spacing, // spacing
|
|
spacing_a, // armor spacing
|
|
armortype, // armor type: r, y, g or none
|
|
player_armor[i], // current armor
|
|
'/'+128, // colored slash
|
|
player_health[i], // current health
|
|
spacing_h, // health spacing
|
|
bestweap, // best weapon
|
|
'\x10', // left bracket
|
|
loc, // player location
|
|
'\x11' // right bracket
|
|
);
|
|
|
|
UI_DrawString(str, 0, offset);
|
|
offset += 16;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Hud_TeamOverlayUpdate(void)
|
|
{
|
|
int user;
|
|
char str[256];
|
|
|
|
// Number in the players[] array
|
|
Cmd_Argv(1, str, sizeof(str));
|
|
user = atoi(str);
|
|
|
|
// Position in the x-axis
|
|
Cmd_Argv(2, str, sizeof(str));
|
|
player_location[user][0] = atoi(str);
|
|
|
|
// Position in the y-axis
|
|
Cmd_Argv(3, str, sizeof(str));
|
|
player_location[user][1] = atoi(str);
|
|
|
|
// Position in the z-axis
|
|
Cmd_Argv(4, str, sizeof(str));
|
|
player_location[user][2] = atoi(str);
|
|
|
|
// Player health
|
|
Cmd_Argv(5, str, sizeof(str));
|
|
player_health[user] = atoi(str);
|
|
|
|
// Player armor
|
|
Cmd_Argv(6, str, sizeof(str));
|
|
player_armor[user] = atoi(str);
|
|
|
|
// Player item bitmask
|
|
Cmd_Argv(7, str, sizeof(str));
|
|
player_items[user] = atoi(str);
|
|
|
|
// Setting this nick will make this info print
|
|
player_nick[user] = players[user].name;
|
|
|
|
// Check who has the longest nick for a better overlay format
|
|
if (strlen(player_nick[user]) > player_nicklength)
|
|
player_nicklength = strlen(player_nick[user]);
|
|
|
|
return;
|
|
}
|
|
|
|
//fixme: draw dark blobs
|
|
void Hud_Blackness(void)
|
|
{
|
|
Draw_Colour4f(0, 0, 0, (sbartype+1)/10.0f);
|
|
|
|
if (hudedit)
|
|
{
|
|
if (sbarindex == currentitem)
|
|
{
|
|
float j = ((currenttime % 1000) - 500) / 500.0f;
|
|
if (j < 0)
|
|
j = -j;
|
|
j/=3;
|
|
|
|
Draw_Colour4f(j, 0, 0, (sbartype+1)/10.0f);
|
|
}
|
|
else if (sbarindex == hoveritem)
|
|
{
|
|
Draw_Colour4f(0.0, 0.2, 0.0, (sbartype+1)/10.0f);
|
|
}
|
|
}
|
|
Draw_Fill(sbarminx, sbarminy, (float)16*sbarscalex, (float)16*sbarscaley);
|
|
Draw_Colour4f(1,1,1,1);
|
|
}
|
|
|
|
void Hud_Tracking(void)
|
|
{
|
|
qboolean flag = false;
|
|
char str[256];
|
|
|
|
if (hudedit)
|
|
{
|
|
UI_DrawString("Tracking ...", 0, 0);
|
|
return;
|
|
}
|
|
|
|
// FIXME: Need a check here to return if we are not spectating
|
|
|
|
// Print it
|
|
snprintf(str, sizeof(str), "Tracking %s", players[trackedplayer].name);
|
|
UI_DrawString(str, 0, 0);
|
|
}
|
|
|
|
void UI_DrawHandles(int *arg, int i)
|
|
{
|
|
int mt;
|
|
float vsx, vsy;
|
|
vsx = arg[3]/640.0f;
|
|
vsy = arg[4]/480.0f;
|
|
|
|
sbarminx = arg[1] + element[i].x*vsx;
|
|
sbarminy = arg[2] + element[i].y*vsy;
|
|
sbarscalex = element[i].scalex*vsx;
|
|
sbarscaley = element[i].scaley*vsy;
|
|
mt = element[i].type;
|
|
sbartype = element[i].subtype;
|
|
sbaralpha = element[i].alpha;
|
|
|
|
Draw_Colour4f(1, 0, 0, 1);
|
|
Draw_Fill(sbarminx+drawelement[mt].width*sbarscalex-((sbarscalex<0)?0:(vsx*4)), sbarminy-((sbarscaley>=0)?0:(vsy*4)), (float)4*vsx, (float)4*vsy);
|
|
|
|
Draw_Colour4f(0, 1, 0, 1);
|
|
Draw_Fill(sbarminx+drawelement[mt].width*sbarscalex-((sbarscalex<0)?0:(vsx*4)), sbarminy+drawelement[mt].height*sbarscaley-((sbarscaley<0)?0:(vsy*4)), (float)4*vsx, (float)4*vsy);
|
|
}
|
|
|
|
//draw body of sbar
|
|
//arg[0] is playernum
|
|
//arg[1]/arg[2] is x/y start of subwindow
|
|
//arg[3]/arg[4] is width/height of subwindow
|
|
int UI_StatusBar(int *arg)
|
|
{
|
|
int i;
|
|
|
|
float vsx, vsy;
|
|
|
|
if (hudedit) // don't redraw twice
|
|
return 1;
|
|
|
|
if (arg[5])
|
|
return 1;
|
|
|
|
CL_GetStats(arg[0], stats, sizeof(stats)/sizeof(int));
|
|
|
|
if (stats[STAT_HEALTH] <= 0)
|
|
return 1;
|
|
|
|
vsx = arg[3]/640.0f;
|
|
vsy = arg[4]/480.0f;
|
|
for (i = 0; i < numelements; i++)
|
|
{
|
|
sbarminx = arg[1] + element[i].x*vsx;
|
|
sbarminy = arg[2] + element[i].y*vsy;
|
|
sbarscalex = element[i].scalex*vsx;
|
|
sbarscaley = element[i].scaley*vsy;
|
|
sbartype = element[i].subtype;
|
|
sbaralpha = element[i].alpha;
|
|
drawelement[element[i].type].draw();
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int UI_StatusBarEdit(int *arg) // seperated so further improvements to editor view can be done
|
|
{
|
|
int i;
|
|
|
|
float vsx, vsy;
|
|
qboolean clrset = false;
|
|
|
|
CL_GetStats(arg[0], stats, sizeof(stats)/sizeof(int));
|
|
|
|
vsx = arg[3]/640.0f;
|
|
vsy = arg[4]/480.0f;
|
|
for (i = 0; i < numelements; i++)
|
|
{
|
|
if (i == currentitem)
|
|
{
|
|
float j = ((currenttime % 1000) - 500) / 500.0f;
|
|
if (j < 0)
|
|
j = -j;
|
|
|
|
Draw_Colour3f(1.0, j, j);
|
|
clrset = true;
|
|
}
|
|
else if (i == hoveritem)
|
|
{
|
|
Draw_Colour3f(0.0, 1.0, 0.0);
|
|
clrset = true;
|
|
}
|
|
|
|
sbarminx = arg[1] + element[i].x*vsx;
|
|
sbarminy = arg[2] + element[i].y*vsy;
|
|
sbarscalex = element[i].scalex*vsx;
|
|
sbarscaley = element[i].scaley*vsy;
|
|
sbartype = element[i].subtype;
|
|
sbaralpha = element[i].alpha;
|
|
sbarindex = i;
|
|
drawelement[element[i].type].draw();
|
|
|
|
if (clrset)
|
|
{
|
|
Draw_Colour3f(1.0, 1.0, 1.0);
|
|
clrset = false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
int UI_ScoreBoard(int *arg)
|
|
{
|
|
int i;
|
|
|
|
if (!arg[5])
|
|
return false;
|
|
|
|
sbarminx = 320;
|
|
sbarminy = 48;
|
|
sbarscalex = 1;
|
|
sbarscaley = 1;
|
|
sbaralpha = 1;
|
|
|
|
SortPlayers();
|
|
for (i = 0; i < numsortedplayers; i++)
|
|
{
|
|
sbartype = i;
|
|
Hud_ScoreCard();
|
|
UI_DrawString(players[sortedplayers[i]].name, 40, 0);
|
|
|
|
sbarminy += 16;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
*/
|
|
|
|
#define HUD_VERSION 52345
|
|
void PutFloat(float f, char sep, qhandle_t handle)
|
|
{
|
|
char *buffer;
|
|
buffer = va("%f%c", f, sep);
|
|
FS_Write(handle, buffer, strlen(buffer));
|
|
}
|
|
void PutInteger(int i, char sep, qhandle_t handle)
|
|
{
|
|
char *buffer;
|
|
buffer = va("%i%c", i, sep);
|
|
FS_Write(handle, buffer, strlen(buffer));
|
|
}
|
|
|
|
void Hud_Save(char *fname)
|
|
{
|
|
char name[256];
|
|
int i;
|
|
qhandle_t handle;
|
|
if (!fname || !*fname)
|
|
fname = DEFAULTHUDNAME;
|
|
snprintf(name, sizeof(name)-5, "huds/%s", fname);
|
|
COM_DefaultExtension(name, ".hud", sizeof(name));
|
|
if (FS_Open(name, &handle, 2)<0)
|
|
{
|
|
Con_Printf("Couldn't open %s\n", name);
|
|
return;
|
|
}
|
|
|
|
PutInteger(HUD_VERSION, '\n', handle);
|
|
PutInteger(numelements, '\n', handle);
|
|
for (i = 0; i < numelements; i++)
|
|
{
|
|
PutFloat(element[i].x, ' ', handle);
|
|
PutFloat(element[i].y, ' ', handle);
|
|
PutFloat(element[i].scalex, ' ', handle);
|
|
PutFloat(element[i].scaley, ' ', handle);
|
|
PutInteger(element[i].type, ' ', handle);
|
|
PutInteger(element[i].subtype, ' ', handle);
|
|
PutFloat(element[i].alpha, '\n', handle);
|
|
}
|
|
|
|
FS_Close(handle);
|
|
}
|
|
float GetFloat(char **f, qhandle_t handle)
|
|
{
|
|
char *ts;
|
|
while(**f <= ' ' && **f != 0)
|
|
(*f)++;
|
|
while(*f[0] == '/' && *f[1] == '/')
|
|
{
|
|
while(**f != '\n' && **f != 0)
|
|
(*f)++;
|
|
while(**f <= ' ' && **f != 0)
|
|
(*f)++;
|
|
}
|
|
ts = *f;
|
|
while (**f>' ')
|
|
(*f)++;
|
|
|
|
return (float)atof(ts);
|
|
}
|
|
int GetInteger(char **f, qhandle_t handle)
|
|
{
|
|
char *ts;
|
|
while(**f <= ' ' && **f != 0)
|
|
(*f)++;
|
|
while(*f[0] == '/' && *f[1] == '/')
|
|
{
|
|
while(**f != '\n' && **f != 0)
|
|
(*f)++;
|
|
while(**f <= ' ' && **f != 0)
|
|
(*f)++;
|
|
}
|
|
ts = *f;
|
|
while (**f>' ')
|
|
(*f)++;
|
|
|
|
return atoi(ts);
|
|
}
|
|
void Hud_Load(char *fname)
|
|
{
|
|
char file[16384];
|
|
char name[256];
|
|
char *p;
|
|
int len;
|
|
int i;
|
|
qhandle_t handle;
|
|
int ver;
|
|
|
|
float x, y, sx, sy, a;
|
|
int type, subtype;
|
|
|
|
if (!fname || !*fname)
|
|
fname = DEFAULTHUDNAME;
|
|
snprintf(name, sizeof(name)-5, "huds/%s", fname);
|
|
COM_DefaultExtension(name, ".hud", sizeof(name));
|
|
len = FS_Open(name, &handle, 1);
|
|
if (len < 0)
|
|
{
|
|
Con_Printf("Couldn't load file\n");
|
|
return;
|
|
}
|
|
if (len > 16383)
|
|
len = 16383;
|
|
FS_Read(handle, file, len);
|
|
file[len] = 0;
|
|
FS_Close(handle);
|
|
|
|
p = file;
|
|
|
|
ver = GetInteger(&p, handle);
|
|
if (ver != HUD_VERSION)
|
|
{
|
|
Con_Printf("Hud version doesn't match (%i != %i)\n", ver, HUD_VERSION);
|
|
return;
|
|
}
|
|
numelements = GetInteger(&p, handle);
|
|
if (numelements > MAX_ELEMENTS)
|
|
{
|
|
numelements = 0;
|
|
Con_Printf("Hud has too many elements\n");
|
|
return;
|
|
}
|
|
for (i = 0; i < numelements; i++)
|
|
{
|
|
x = GetFloat(&p, handle);
|
|
y = GetFloat(&p, handle);
|
|
sx = GetFloat(&p, handle);
|
|
sy = GetFloat(&p, handle);
|
|
type = GetInteger(&p, handle);
|
|
subtype = GetInteger(&p, handle);
|
|
a = GetFloat(&p, handle);
|
|
|
|
if (type<0 || type>=sizeof(drawelement)/sizeof(drawelement[0]))
|
|
{
|
|
numelements--;
|
|
i--;
|
|
continue;
|
|
}
|
|
|
|
element[i].x = x;
|
|
element[i].y = y;
|
|
element[i].scalex = sx;
|
|
element[i].scaley = sy;
|
|
element[i].alpha = a;
|
|
element[i].type = type;
|
|
element[i].subtype = subtype;
|
|
}
|
|
|
|
currentitem = -1;
|
|
}
|
|
|
|
// FindItemUnderMouse: given mouse coordinates, finds element number under mouse
|
|
// returns -1 if no element found
|
|
int FindItemUnderMouse(int mx, int my)
|
|
{
|
|
int i;
|
|
int rv;
|
|
|
|
rv = -1;
|
|
|
|
for (i = 0; i < numelements; i++)
|
|
{
|
|
if (element[i].scalex < 0)
|
|
{
|
|
if (element[i].x < mx)
|
|
continue;
|
|
if (element[i].x + element[i].scalex*drawelement[element[i].type].width > mx)
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (element[i].x > mx)
|
|
continue;
|
|
if (element[i].x + element[i].scalex*drawelement[element[i].type].width < mx)
|
|
continue;
|
|
}
|
|
if (element[i].scaley < 0)
|
|
{
|
|
if (element[i].y < my)
|
|
continue;
|
|
if (element[i].y + element[i].scaley*drawelement[element[i].type].height > my)
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if (element[i].y > my)
|
|
continue;
|
|
if (element[i].y + element[i].scaley*drawelement[element[i].type].height < my)
|
|
continue;
|
|
}
|
|
|
|
rv = i;
|
|
}
|
|
|
|
return rv; // no element found
|
|
}
|
|
|
|
void DrawContextMenu(int mx, int my)
|
|
{
|
|
int y;
|
|
Draw_Colour4f(0, 0, 0, 0.4);
|
|
Draw_Fill((mouseofsx-8)*sbarscalex, (mouseofsy-8)*sbarscaley, (float)112*sbarscalex, (float)(9*8)*sbarscaley);
|
|
Draw_Colour4f(1,1,1,1);
|
|
|
|
sbarminx = mouseofsx*sbarscalex;
|
|
sbarminy = mouseofsy*sbarscaley;
|
|
|
|
my -= mouseofsy;
|
|
my/=8;
|
|
my--;
|
|
|
|
mx -= mouseofsx;
|
|
|
|
if (mx < 0)
|
|
my = -10;
|
|
if (mx > 12*8)
|
|
my = -10;
|
|
|
|
y = 0;
|
|
UI_DrawAltString("CONTEXT MENU", 0, y, 1);
|
|
y+=8;
|
|
UI_DrawAltString("------------", 0, y, 0);
|
|
y+=8;
|
|
UI_DrawAltString("New", 0, y, (my--)==1);
|
|
y+=8;
|
|
UI_DrawAltString("Snap To Grid", 0, y, (my--)==1);
|
|
if (shiftdown)
|
|
UI_DrawAltString("X", -8, y, (my)==1);
|
|
y+=8;
|
|
UI_DrawAltString("Save", 0, y, (my--)==1);
|
|
y+=8;
|
|
UI_DrawAltString("Reload", 0, y, (my--)==1);
|
|
y+=8;
|
|
UI_DrawAltString("Defaults", 0, y, (my--)==1);
|
|
y+=8;
|
|
}
|
|
|
|
void DrawPrimaryCreationMenu(int mx, int my)
|
|
{
|
|
int i;
|
|
int y;
|
|
int numopts;
|
|
numopts = sizeof(drawelement)/sizeof(drawelement[0]);
|
|
numopts += 2;
|
|
Draw_Colour4f(0, 0, 0, 0.4);
|
|
Draw_Fill((mouseofsx-8)*sbarscalex, (mouseofsy-8)*sbarscaley, (float)(17*8)*sbarscalex, (float)((numopts+2)*8)*sbarscaley);
|
|
Draw_Colour4f(1,1,1,1);
|
|
|
|
sbarminx = mouseofsx*sbarscalex;
|
|
sbarminy = mouseofsy*sbarscaley;
|
|
|
|
my -= mouseofsy;
|
|
my/=8;
|
|
my--;
|
|
|
|
mx -= mouseofsx;
|
|
|
|
if (mx < 0)
|
|
my = -10;
|
|
if (mx > 12*8)
|
|
my = -10;
|
|
|
|
y = 0;
|
|
UI_DrawAltString("CREATE NEW ITEM", 0, y, 1);
|
|
y+=8;
|
|
UI_DrawAltString("------------", 0, y, 0);
|
|
y+=8;
|
|
|
|
|
|
for (i = 0; i < sizeof(drawelement)/sizeof(drawelement[0]); i++)
|
|
{
|
|
UI_DrawAltString(drawelement[i].name, 0, y, (my--)==1);
|
|
y+=8;
|
|
}
|
|
}
|
|
|
|
void DrawSecondaryCreationMenu(int mx, int my)
|
|
{
|
|
int i;
|
|
int y;
|
|
int numopts;
|
|
numopts = drawelement[typetoinsert].maxsubtype+1;
|
|
numopts += 2;
|
|
Draw_Colour4f(0, 0, 0, 0.4);
|
|
Draw_Fill((mouseofsx-8)*sbarscalex, (mouseofsy-8)*sbarscaley, (float)(17*8)*sbarscalex, (float)((numopts+2)*8)*sbarscaley);
|
|
Draw_Colour4f(1,1,1,1);
|
|
|
|
sbarminx = mouseofsx*sbarscalex;
|
|
sbarminy = mouseofsy*sbarscaley;
|
|
|
|
my -= mouseofsy;
|
|
my/=8;
|
|
my--;
|
|
|
|
mx -= mouseofsx;
|
|
|
|
if (mx < 0)
|
|
my = -10;
|
|
if (mx > 12*8)
|
|
my = -10;
|
|
|
|
y = 0;
|
|
UI_DrawAltString("CREATE NEW ITEM", 0, y, 1);
|
|
y+=8;
|
|
UI_DrawAltString("------------", 0, y, 0);
|
|
y+=8;
|
|
|
|
|
|
for (i = 0; i <= drawelement[typetoinsert].maxsubtype; i++)
|
|
{
|
|
UI_DrawAltString(drawelement[typetoinsert].subtypename[i].name, 0, y, (my--)==1);
|
|
y+=8;
|
|
}
|
|
}
|
|
|
|
void UI_KeyPress(int key, int mx, int my)
|
|
{
|
|
int i;
|
|
if (key == K_ESCAPE)
|
|
{
|
|
Menu_Control(0);
|
|
return;
|
|
}
|
|
|
|
if (context)
|
|
{
|
|
if (key != K_MOUSE1)
|
|
{
|
|
context = false;
|
|
return;
|
|
}
|
|
|
|
mx -= mouseofsx;
|
|
if (mx < 0)
|
|
my = -10;
|
|
if (mx > 12*8)
|
|
my = -10;
|
|
|
|
i = my - mouseofsy;
|
|
i /= 8;
|
|
|
|
if (context == 3)
|
|
{
|
|
context = false;
|
|
if ((unsigned)(i-2) > (unsigned)drawelement[typetoinsert].maxsubtype)
|
|
return;
|
|
currentitem = numelements;
|
|
numelements++;
|
|
|
|
if (typetoinsert == 12)
|
|
{
|
|
int j;
|
|
|
|
// Blackness should be sent to the back
|
|
for (j = currentitem; j > 0; j--)
|
|
{
|
|
element[j] = element[j-1];
|
|
}
|
|
|
|
currentitem = 0;
|
|
}
|
|
element[currentitem].type = typetoinsert;
|
|
element[currentitem].alpha = 1;
|
|
element[currentitem].scalex = 1;
|
|
element[currentitem].scaley = 1;
|
|
|
|
element[currentitem].x = 320;
|
|
element[currentitem].y = 240;
|
|
element[currentitem].subtype = i-2;
|
|
}
|
|
else if (context == 2)
|
|
{
|
|
typetoinsert = i-2;
|
|
if ((unsigned)typetoinsert >= sizeof(drawelement)/sizeof(drawelement[0]))
|
|
{
|
|
context = false;
|
|
return;
|
|
}
|
|
if (drawelement[typetoinsert].maxsubtype != 0)
|
|
context = 3;
|
|
else
|
|
{
|
|
context = false;
|
|
currentitem = numelements;
|
|
numelements++;
|
|
|
|
element[currentitem].type = i-2;
|
|
element[currentitem].alpha = 1;
|
|
element[currentitem].scalex = 1;
|
|
element[currentitem].scaley = 1;
|
|
|
|
element[currentitem].x = 320;
|
|
element[currentitem].y = 240;
|
|
element[currentitem].subtype = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
context = false;
|
|
switch(i)
|
|
{
|
|
case 2: //clone
|
|
if (numelements==MAX_ELEMENTS)
|
|
return; //too many
|
|
/*
|
|
memcpy(element+numelements, element+currentitem, sizeof(hudelement_t));
|
|
currentitem = numelements;
|
|
numelements++;
|
|
*/
|
|
context = 2;
|
|
break;
|
|
case 3: //snap
|
|
shiftdown ^= 1;
|
|
break;
|
|
case 4: //save
|
|
Hud_Save(NULL);
|
|
break;
|
|
case 5: //reload
|
|
Hud_Load(NULL);
|
|
break;
|
|
case 6: //defaults
|
|
SBar_FlushAll();
|
|
SBar_ReloadDefaults();
|
|
break;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (key == K_MOUSE1)
|
|
{ //figure out which one our cursor is over...
|
|
mousedown = false;
|
|
|
|
i = FindItemUnderMouse(mx, my);
|
|
if (i != -1)
|
|
{
|
|
int oldcurrent;
|
|
float big;
|
|
oldcurrent = currentitem;
|
|
currentitem = i;
|
|
|
|
mouseofsx = mx - element[i].x;
|
|
mouseofsy = my - element[i].y;
|
|
mousedown |= 1;
|
|
|
|
if (element[i].scalex < 0)
|
|
{
|
|
if (mx > element[i].x+4)
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
big = element[i].scalex*drawelement[element[i].type].width;
|
|
if (mx-element[i].x+4 < big)
|
|
return;
|
|
}
|
|
|
|
if (my < element[i].y+4)
|
|
{
|
|
if (currentitem == oldcurrent)
|
|
UI_KeyPress('d', 0, 0);
|
|
return;
|
|
}
|
|
|
|
if (element[i].scaley < 0)
|
|
{
|
|
if (my > element[i].y+4)
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
big = element[i].scaley*drawelement[element[i].type].height;
|
|
if (my-element[i].y+4 < big)
|
|
return;
|
|
}
|
|
|
|
mouseofsx = mx - element[i].scalex*drawelement[element[i].type].width;
|
|
mouseofsy = my - element[i].scaley*drawelement[element[i].type].height;
|
|
mousedown |= 2;
|
|
}
|
|
else
|
|
currentitem = -1;
|
|
}
|
|
|
|
// TODO: extra buttons
|
|
// - toggle clip to edges and clip to other controls
|
|
// - maybe toggle snap to grid instead of holding shift with mouse?
|
|
|
|
else if (key == K_MOUSE2)
|
|
{
|
|
mousedown = false; //perhaps not logically true, but it's safest this way.
|
|
context = true;
|
|
|
|
mouseofsx = mx;
|
|
mouseofsy = my;
|
|
}
|
|
else if (key == 'n')
|
|
{
|
|
currentitem++;
|
|
if (currentitem >= numelements)
|
|
currentitem = 0;
|
|
}
|
|
else if (key == 'm')
|
|
{
|
|
currentitem--;
|
|
if (currentitem < 0)
|
|
currentitem = numelements ? numelements - 1 : 0;
|
|
}
|
|
else if (key == 'i')
|
|
{
|
|
if (numelements==MAX_ELEMENTS)
|
|
return; //too many
|
|
|
|
element[numelements].scalex = 1;
|
|
element[numelements].scaley = 1;
|
|
element[numelements].alpha = 1;
|
|
numelements++;
|
|
}
|
|
else if (key == K_SHIFT)
|
|
shiftdown = true;
|
|
else if (currentitem < numelements && currentitem != -1)
|
|
{
|
|
if (key == 'd')
|
|
{
|
|
mousedown = false;
|
|
memcpy(element+currentitem, element+currentitem+1, sizeof(element[0]) * (numelements - currentitem-1));
|
|
numelements--;
|
|
currentitem = -1;
|
|
}
|
|
else if (key == 'c' || key == 'C')
|
|
{
|
|
if (numelements==MAX_ELEMENTS)
|
|
return; //too many
|
|
memcpy(element+numelements, element+currentitem, sizeof(hudelement_t));
|
|
currentitem = numelements;
|
|
numelements++;
|
|
}
|
|
else if (key == K_PAGEUP)
|
|
{ //send to back
|
|
hudelement_t temp;
|
|
|
|
memcpy(&temp, element+currentitem, sizeof(temp));
|
|
memmove(element+1, element, sizeof(hudelement_t) * (currentitem));
|
|
memcpy(element, &temp, sizeof(hudelement_t));
|
|
currentitem = 0;
|
|
}
|
|
else if (key == K_PAGEDOWN)
|
|
{ //bring to front
|
|
hudelement_t temp;
|
|
|
|
memcpy(&temp, element+currentitem, sizeof(temp));
|
|
memcpy(element+currentitem, element+currentitem+1, sizeof(element[0]) * (numelements - currentitem-1));
|
|
currentitem = numelements - 1;
|
|
memcpy(element+currentitem , &temp, sizeof(hudelement_t));
|
|
}
|
|
else if (key == 'q')
|
|
{
|
|
element[currentitem].type--;
|
|
if (element[currentitem].type < 0)
|
|
element[currentitem].type = sizeof(drawelement)/sizeof(drawelement[0])-1;
|
|
}
|
|
else if (key == 'w')
|
|
{
|
|
element[currentitem].type++;
|
|
if (element[currentitem].type >= sizeof(drawelement)/sizeof(drawelement[0]))
|
|
element[currentitem].type = 0;
|
|
}
|
|
else if (key == ',' || key == K_MWHEELUP)
|
|
{
|
|
element[currentitem].subtype--;
|
|
if (element[currentitem].subtype < 0)
|
|
element[currentitem].subtype = drawelement[element[currentitem].type].maxsubtype;
|
|
}
|
|
else if (key == '.' || key == K_MWHEELDOWN)
|
|
{
|
|
element[currentitem].subtype++;
|
|
if (element[currentitem].subtype > drawelement[element[currentitem].type].maxsubtype)
|
|
element[currentitem].subtype = 0;
|
|
}
|
|
else if (key == K_UPARROW)
|
|
{
|
|
element[currentitem].y-=shiftdown?8:1;
|
|
}
|
|
else if (key == K_DOWNARROW)
|
|
{
|
|
element[currentitem].y+=shiftdown?8:1;
|
|
}
|
|
else if (key == K_LEFTARROW)
|
|
{
|
|
element[currentitem].x-=shiftdown?8:1;
|
|
}
|
|
else if (key == K_RIGHTARROW)
|
|
{
|
|
element[currentitem].x+=shiftdown?8:1;
|
|
}
|
|
else if (key == K_HOME)
|
|
{
|
|
element[currentitem].scalex=1.0f;
|
|
element[currentitem].scaley=1.0f;
|
|
element[currentitem].alpha=1.0f;
|
|
}
|
|
else if (key == '+')
|
|
{
|
|
element[currentitem].scalex*=1.1f;
|
|
element[currentitem].scaley*=1.1f;
|
|
}
|
|
else if (key == '-')
|
|
{
|
|
element[currentitem].scalex/=1.1f;
|
|
element[currentitem].scaley/=1.1f;
|
|
}
|
|
}
|
|
}
|
|
|
|
int Plug_MenuEvent(int *args)
|
|
{
|
|
int altargs[5];
|
|
float cursorbias;
|
|
float cursorsize;
|
|
|
|
args[2]=(int)(args[2]*640.0f/vid.width);
|
|
args[3]=(int)(args[3]*480.0f/vid.height);
|
|
|
|
switch(args[0])
|
|
{
|
|
case 0: //draw
|
|
|
|
// TODO: some sort of element property display
|
|
if (context)
|
|
{
|
|
}
|
|
else if (mousedown)
|
|
{
|
|
if (mousedown & 2) //2 is 'on the scaler'
|
|
{
|
|
float w = args[2] - mouseofsx;
|
|
float h = args[3] - mouseofsy;
|
|
if (shiftdown || (mousedown & 4)) //4 is mouse2
|
|
{
|
|
w -= (int)w & 7;
|
|
h -= (int)h & 7;
|
|
}
|
|
if (w < 8 && w > -8)
|
|
w = 8;
|
|
if (h < 8 && h > -8)
|
|
h = 8;
|
|
element[currentitem].scalex = w/drawelement[element[currentitem].type].width;
|
|
element[currentitem].scaley = h/drawelement[element[currentitem].type].height;
|
|
}
|
|
else
|
|
{
|
|
element[currentitem].x = args[2] - mouseofsx;
|
|
element[currentitem].y = args[3] - mouseofsy;
|
|
if (shiftdown || (mousedown & 4)) //4 is mouse2
|
|
{
|
|
element[currentitem].x -= (int)element[currentitem].x & 7;
|
|
element[currentitem].y -= (int)element[currentitem].y & 7;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
hoveritem = FindItemUnderMouse(args[2], args[3]); // this could possibly slow some things down...
|
|
|
|
altargs[0] = 0;
|
|
altargs[1] = 0;
|
|
altargs[2] = 0;
|
|
altargs[3] = vid.width;
|
|
altargs[4] = vid.height;
|
|
if (hudedit)
|
|
UI_StatusBarEdit(altargs);
|
|
// else
|
|
// UI_StatusBar(altargs); //draw it using the same function (we're lazy)
|
|
|
|
if (currentitem >= 0)
|
|
UI_DrawHandles(altargs, currentitem);
|
|
|
|
sbarscalex = vid.width/640.0f;
|
|
sbarscaley = vid.height/480.0f;
|
|
switch (context)
|
|
{
|
|
case 1:
|
|
DrawContextMenu(args[2], args[3]);
|
|
break;
|
|
case 2:
|
|
DrawPrimaryCreationMenu(args[2], args[3]);
|
|
break;
|
|
case 3:
|
|
DrawSecondaryCreationMenu(args[2], args[3]);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
sbarminx = args[2];
|
|
sbarminy = args[3];
|
|
|
|
cursorbias = Cvar_GetFloat("cl_cursorbias");
|
|
cursorsize = Cvar_GetFloat("cl_cursorsize");
|
|
|
|
Draw_Colour4f(1,1,1,1);
|
|
Draw_Image(((float)args[2]*sbarscalex)-cursorbias, ((float)args[3]*sbarscaley)-cursorbias, (float)cursorsize*sbarscalex, (float)cursorsize*sbarscaley, 0, 0, 1, 1, pic_cursor);
|
|
break;
|
|
case 1: //keydown
|
|
UI_KeyPress(args[1], args[2], args[3]);
|
|
break;
|
|
case 2: //keyup
|
|
if (args[1] == K_MOUSE1)
|
|
mousedown = false;
|
|
else if (args[1] == K_SHIFT)
|
|
shiftdown = false;
|
|
break;
|
|
case 3: //menu closed (this is called even if we change it).
|
|
hudedit = false;
|
|
break;
|
|
case 4: //mousemove
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Plug_Tick(int *args)
|
|
{
|
|
currenttime = args[0];
|
|
return true;
|
|
}
|
|
|
|
int Plug_ExecuteCommand(int *args)
|
|
{
|
|
char cmd[256];
|
|
Cmd_Argv(0, cmd, sizeof(cmd));
|
|
if (!strcmp("sbar_edit", cmd) || !strcmp("hud_edit", cmd))
|
|
{
|
|
Menu_Control(1);
|
|
mousedown=false;
|
|
hudedit=true;
|
|
return 1;
|
|
}
|
|
if (!strcmp("sbar_save", cmd) || !strcmp("hud_save", cmd))
|
|
{
|
|
Cmd_Argv(1, cmd, sizeof(cmd));
|
|
Hud_Save(cmd);
|
|
mousedown=false;
|
|
return 1;
|
|
}
|
|
if (!strcmp("sbar_load", cmd) || !strcmp("hud_load", cmd))
|
|
{
|
|
Cmd_Argv(1, cmd, sizeof(cmd));
|
|
Hud_Load(cmd);
|
|
mousedown=false;
|
|
return 1;
|
|
}
|
|
if (!strcmp("sbar_defaults", cmd) || !strcmp("hud_defaults", cmd))
|
|
{
|
|
Cmd_Argv(1, cmd, sizeof(cmd));
|
|
SBar_FlushAll();
|
|
SBar_ReloadDefaults();
|
|
mousedown=false;
|
|
return 1;
|
|
}
|
|
// Modify a HUD element
|
|
if (!strcmp("sbar", cmd) || !strcmp("hud", cmd))
|
|
{
|
|
// FIXME: add this command
|
|
return 1;
|
|
}
|
|
// Support for KTX team overlay
|
|
if (!strcmp("tinfo", cmd))
|
|
{
|
|
Hud_TeamOverlayUpdate();
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Plug_Init(int *args)
|
|
{
|
|
if (Plug_Export("Tick", Plug_Tick) &&
|
|
Plug_Export("SbarBase", UI_StatusBar) &&
|
|
// Plug_Export("SbarOverlay", UI_ScoreBoard) &&
|
|
Plug_Export("ExecuteCommand", Plug_ExecuteCommand) &&
|
|
Plug_Export("MenuEvent", Plug_MenuEvent))
|
|
{
|
|
|
|
K_UPARROW = Key_GetKeyCode("uparrow");
|
|
K_DOWNARROW = Key_GetKeyCode("downarrow");
|
|
K_LEFTARROW = Key_GetKeyCode("leftarrow");
|
|
K_RIGHTARROW = Key_GetKeyCode("rightarrow");
|
|
K_ESCAPE = Key_GetKeyCode("escape");
|
|
K_HOME = Key_GetKeyCode("home");
|
|
K_MOUSE1 = Key_GetKeyCode("mouse1");
|
|
K_MOUSE2 = Key_GetKeyCode("mouse2");
|
|
K_MWHEELDOWN = Key_GetKeyCode("mwheeldown");
|
|
K_MWHEELUP = Key_GetKeyCode("mwheelup");
|
|
K_SHIFT = Key_GetKeyCode("shift");
|
|
K_PAGEUP = Key_GetKeyCode("pgup");
|
|
K_PAGEDOWN = Key_GetKeyCode("pgdn");
|
|
|
|
Cmd_AddCommand("hud_edit");
|
|
Cmd_AddCommand("sbar_edit");
|
|
if (BUILTINISVALID(FS_Write))
|
|
{
|
|
Cmd_AddCommand("hud_save");
|
|
Cmd_AddCommand("sbar_save");
|
|
}
|
|
if (BUILTINISVALID(FS_Read))
|
|
{
|
|
Cmd_AddCommand("hud_load");
|
|
Cmd_AddCommand("sbar_load");
|
|
}
|
|
Cmd_AddCommand("hud_defaults");
|
|
Cmd_AddCommand("sbar_defaults");
|
|
|
|
// For modifying hud elements
|
|
Cmd_AddCommand("hud");
|
|
Cmd_AddCommand("sbar");
|
|
|
|
// Teamoverlay support
|
|
Cmd_AddCommand("tinfo");
|
|
Cmd_AddText("newalias ktx_infoset \"cmd info ti 1\"\n", false);
|
|
|
|
UI_SbarInit();
|
|
|
|
if (BUILTINISVALID(FS_Read))
|
|
Hud_Load("");
|
|
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|