Fix up translations stuff with the rereleased version of quake.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6038 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2021-08-23 06:37:21 +00:00
parent 81d5091fac
commit c2d3d3a41b
18 changed files with 424 additions and 40 deletions

View file

@ -6348,7 +6348,10 @@ static void CL_PrintStandardMessage(char *msgtext, int printlevel)
// print final chunk // print final chunk
Q_strncatz(fullmessage, msgtext, sizeof(fullmessage)); Q_strncatz(fullmessage, msgtext, sizeof(fullmessage));
Con_Printf("%s", fullmessage); if (scr_usekfont.ival)
Con_PrintFlags(fullmessage, PFS_FORCEUTF8, 0);
else
Con_Printf("%s", fullmessage);
} }
static char printtext[4096]; static char printtext[4096];

View file

@ -403,8 +403,13 @@ for a few moments
*/ */
void SCR_CenterPrint (int pnum, const char *str, qboolean skipgamecode) void SCR_CenterPrint (int pnum, const char *str, qboolean skipgamecode)
{ {
unsigned int pfl = 0;
size_t i; size_t i;
cprint_t *p; cprint_t *p;
#ifdef HAVE_LEGACY
if (scr_usekfont.ival)
pfl |= PFS_FORCEUTF8;
#endif
if (!str) if (!str)
{ {
if (cl.intermissionmode == IM_NONE) if (cl.intermissionmode == IM_NONE)
@ -545,7 +550,7 @@ void SCR_CenterPrint (int pnum, const char *str, qboolean skipgamecode)
for (;;) for (;;)
{ {
p->charcount = COM_ParseFunString(CON_WHITEMASK, str, p->string, p->stringbytes, false) - p->string; p->charcount = COM_ParseFunString(CON_WHITEMASK, str, p->string, p->stringbytes, pfl) - p->string;
if ((p->charcount+1)*sizeof(*p->string) < p->stringbytes) if ((p->charcount+1)*sizeof(*p->string) < p->stringbytes)
break; break;

View file

@ -216,7 +216,8 @@ mpic_t *QBigFontWorks(void)
if (p && R_GetShaderSizes(p, NULL, NULL, true)) if (p && R_GetShaderSizes(p, NULL, NULL, true))
return p; return p;
} }
return NULL;
return (mpic_t*)font_menu;
} }
void Draw_BigFontString(int x, int y, const char *text) void Draw_BigFontString(int x, int y, const char *text)
{ {
@ -228,6 +229,11 @@ void Draw_BigFontString(int x, int y, const char *text)
Draw_AltFunString(x, y + (20-8)/2, text); Draw_AltFunString(x, y + (20-8)/2, text);
return; return;
} }
if (p == (mpic_t*)font_menu)
{
Draw_FunStringWidthFont(font_menu, x, y, text, vid.width-x, false, false);
return;
}
{ //a hack for scaling { //a hack for scaling
p->width = 20*8; p->width = 20*8;

View file

@ -4691,7 +4691,7 @@ static void QCBUILTIN PF_checkextension (pubprogfuncs_t *prinst, struct globalva
{ {
if (QSG_Extensions[i].extensioncheck) if (QSG_Extensions[i].extensioncheck)
{ {
extcheck_t ctx = {cls.fteprotocolextensions, cls.fteprotocolextensions2}; extcheck_t ctx = {prinst->parms->user, cls.fteprotocolextensions, cls.fteprotocolextensions2};
G_FLOAT(OFS_RETURN) = QSG_Extensions[i].extensioncheck(&ctx); G_FLOAT(OFS_RETURN) = QSG_Extensions[i].extensioncheck(&ctx);
} }
else else
@ -8552,7 +8552,7 @@ void PR_CSExtensionList_f(void)
int j; int j;
const char *extname; const char *extname;
extcheck_t extcheck = {cls.fteprotocolextensions, cls.fteprotocolextensions2}; extcheck_t extcheck = {&csqc_world, cls.fteprotocolextensions, cls.fteprotocolextensions2};
#define SHOW_ACTIVEEXT 1 #define SHOW_ACTIVEEXT 1

View file

@ -326,6 +326,7 @@ extern cvar_t com_protocolversion;
extern cvar_t com_nogamedirnativecode; extern cvar_t com_nogamedirnativecode;
extern cvar_t com_parseutf8; extern cvar_t com_parseutf8;
#ifdef HAVE_LEGACY #ifdef HAVE_LEGACY
extern cvar_t scr_usekfont;
extern cvar_t ezcompat_markup; extern cvar_t ezcompat_markup;
#endif #endif
extern cvar_t sys_ticrate; extern cvar_t sys_ticrate;

View file

@ -1231,6 +1231,8 @@ void R2D_Font_Changed(void)
#endif #endif
} }
font_menu = Font_LoadFont("qfont?fmt=r", 20, 1, r_font_postprocess_outline.ival);
font_default = Font_LoadFont(gl_font.string, 8, 1, r_font_postprocess_outline.ival); font_default = Font_LoadFont(gl_font.string, 8, 1, r_font_postprocess_outline.ival);
if (!font_default && *gl_font.string) if (!font_default && *gl_font.string)
font_default = Font_LoadFont("", 8, 1, r_font_postprocess_outline.ival); font_default = Font_LoadFont("", 8, 1, r_font_postprocess_outline.ival);

View file

@ -351,6 +351,7 @@ int Font_LineWidth(conchar_t *start, conchar_t *end);
float Font_LineScaleWidth(conchar_t *start, conchar_t *end); float Font_LineScaleWidth(conchar_t *start, conchar_t *end);
void Font_LineDraw(int x, int y, conchar_t *start, conchar_t *end); void Font_LineDraw(int x, int y, conchar_t *start, conchar_t *end);
conchar_t *Font_CharAt(int x, conchar_t *start, conchar_t *end); conchar_t *Font_CharAt(int x, conchar_t *start, conchar_t *end);
extern struct font_s *font_menu;
extern struct font_s *font_default; extern struct font_s *font_default;
extern struct font_s *font_console; extern struct font_s *font_console;
extern struct font_s *font_tiny; extern struct font_s *font_tiny;

View file

@ -92,6 +92,7 @@ cvar_t host_mapname = CVARAFD("mapname", "", "host_mapname", 0, "Cvar that hol
#ifdef HAVE_LEGACY #ifdef HAVE_LEGACY
cvar_t ezcompat_markup = CVARD("ezcompat_markup", "1", "Attempt compatibility with ezquake's text markup.0: disabled.\n1: Handle markup ampersand markup.\n2: Handle chevron markup (only in echo commands, for config compat, because its just too unreliable otherwise)."); cvar_t ezcompat_markup = CVARD("ezcompat_markup", "1", "Attempt compatibility with ezquake's text markup.0: disabled.\n1: Handle markup ampersand markup.\n2: Handle chevron markup (only in echo commands, for config compat, because its just too unreliable otherwise).");
cvar_t pm_noround = CVARD("pm_noround", "0", "Disables player prediction snapping, in a way that cannot be reliably predicted but may be needed to avoid map bugs."); cvar_t pm_noround = CVARD("pm_noround", "0", "Disables player prediction snapping, in a way that cannot be reliably predicted but may be needed to avoid map bugs.");
cvar_t scr_usekfont = CVARD("scr_usekfont"/*kex*/, "0", "Exists for compat with the quake rerelease, changing the behaviour of QC's sprint/bprint/centerprint builtins.");
#endif #endif
qboolean com_modified; // set true if using non-id files qboolean com_modified; // set true if using non-id files
@ -6358,6 +6359,7 @@ void COM_Init (void)
Cvar_Register (&com_nogamedirnativecode, "Gamecode"); Cvar_Register (&com_nogamedirnativecode, "Gamecode");
Cvar_Register (&com_parseutf8, "Internationalisation"); Cvar_Register (&com_parseutf8, "Internationalisation");
#ifdef HAVE_LEGACY #ifdef HAVE_LEGACY
Cvar_Register (&scr_usekfont, NULL);
Cvar_Register (&ezcompat_markup, NULL); Cvar_Register (&ezcompat_markup, NULL);
Cvar_Register (&pm_noround, NULL); Cvar_Register (&pm_noround, NULL);
#endif #endif

View file

@ -975,6 +975,7 @@ struct po_s *PO_Create(void);
void PO_Merge(struct po_s *po, vfsfile_t *file); void PO_Merge(struct po_s *po, vfsfile_t *file);
const char *PO_GetText(struct po_s *po, const char *msg); const char *PO_GetText(struct po_s *po, const char *msg);
void PO_Close(struct po_s *po); void PO_Close(struct po_s *po);
void TL_Reformat(char *out, size_t outsize, size_t numargs, const char **arg);
// //
// log.c // log.c

View file

@ -3820,7 +3820,9 @@ void COM_Gamedir (const char *dir, const struct gamepacks *packagespaths)
/*quake requires a few settings for compatibility*/ /*quake requires a few settings for compatibility*/
#define QRPCOMPAT "set cl_cursor_scale 0.2\nset cl_cursor_bias_x 7.5\nset cl_cursor_bias_y 0.8\n" #define QRPCOMPAT "set cl_cursor_scale 0.2\nset cl_cursor_bias_x 7.5\nset cl_cursor_bias_y 0.8\n"
#define QUAKESPASMSUCKS "set mod_h2holey_bugged 1\n" #define QUAKESPASMSUCKS "set mod_h2holey_bugged 1\n"
#define QCFG "//schemes quake qw\n" "set v_gammainverted 1\nset con_stayhidden 0\nset com_parseutf8 0\nset allow_download_pakcontents 1\nset allow_download_refpackages 0\nset r_meshpitch -1\nr_sprite_backfacing 1\nset sv_bigcoords \"\"\nmap_autoopenportals 1\n" "sv_port "STRINGIFY(PORT_QWSERVER)" "STRINGIFY(PORT_NQSERVER)"\n" ZFIXHACK EZQUAKECOMPETITIVE QRPCOMPAT QUAKESPASMSUCKS #define QUAKEOVERRIDES "set v_gammainverted 1\nset con_stayhidden 0\nset allow_download_pakcontents 1\nset allow_download_refpackages 0\nset r_meshpitch -1\nr_sprite_backfacing 1\nset sv_bigcoords \"\"\nmap_autoopenportals 1\n" "sv_port "STRINGIFY(PORT_QWSERVER)" "STRINGIFY(PORT_NQSERVER)"\n" ZFIXHACK EZQUAKECOMPETITIVE QUAKESPASMSUCKS
#define QCFG "//schemes quake qw\n" QUAKEOVERRIDES "set com_parseutf8 0\n" QRPCOMPAT
#define KEXCFG "//schemes quake_r2\n" QUAKEOVERRIDES "set com_parseutf8 1\nset campaign 0\n"
/*NetQuake reconfiguration, to make certain people feel more at home...*/ /*NetQuake reconfiguration, to make certain people feel more at home...*/
#define NQCFG "//disablehomedir 1\n//mainconfig ftenq\n" QCFG "cfg_save_auto 1\nset sv_nqplayerphysics 1\nset cl_loopbackprotocol auto\ncl_sbar 1\nset plug_sbar 0\nset sv_port "STRINGIFY(PORT_NQSERVER)"\ncl_defaultport "STRINGIFY(PORT_NQSERVER)"\nset m_preset_chosen 1\nset vid_wait 1\nset cl_demoreel 1\n" #define NQCFG "//disablehomedir 1\n//mainconfig ftenq\n" QCFG "cfg_save_auto 1\nset sv_nqplayerphysics 1\nset cl_loopbackprotocol auto\ncl_sbar 1\nset plug_sbar 0\nset sv_port "STRINGIFY(PORT_NQSERVER)"\ncl_defaultport "STRINGIFY(PORT_NQSERVER)"\nset m_preset_chosen 1\nset vid_wait 1\nset cl_demoreel 1\n"
#define SPASMCFG NQCFG "fps_preset builtin_spasm\nset cl_demoreel 0\ncl_sbar 2\nset gl_load24bit 1\n" #define SPASMCFG NQCFG "fps_preset builtin_spasm\nset cl_demoreel 0\ncl_sbar 2\nset gl_load24bit 1\n"
@ -3895,6 +3897,8 @@ static const gamemode_info_t gamemode_info[] = {
//for quake, we also allow extracting all files from paks. some people think it loads faster that way or something. //for quake, we also allow extracting all files from paks. some people think it loads faster that way or something.
#ifdef HAVE_LEGACY #ifdef HAVE_LEGACY
//cmdline switch exename protocol name(dpmaster) identifying file exec dir1 dir2 dir3 dir(fte) full name //cmdline switch exename protocol name(dpmaster) identifying file exec dir1 dir2 dir3 dir(fte) full name
//use rerelease behaviours if we seem to be running from that dir.
{"-quake_rerel",NULL, "FTE-QuakeRerelease", {"QuakeEX.kpf"}, KEXCFG, {"id1", "*fte"}, "RerelQuake", UPDATEURL(Q1)},
//standard quake //standard quake
{"-quake", "q1", QUAKEPROT, {"id1/pak0.pak","id1/quake.rc"},QCFG, {"id1", "qw", "*fte"}, "Quake", UPDATEURL(Q1)}, {"-quake", "q1", QUAKEPROT, {"id1/pak0.pak","id1/quake.rc"},QCFG, {"id1", "qw", "*fte"}, "Quake", UPDATEURL(Q1)},
//alternative name, because fmf file install names are messy when a single name is used for registry install path. //alternative name, because fmf file install names are messy when a single name is used for registry install path.
@ -4468,6 +4472,19 @@ static void FS_ReloadPackFilesFlags(unsigned int reloadflags)
com_base_searchpaths = NULL; com_base_searchpaths = NULL;
gameonly_gamedir = gameonly_homedir = NULL; gameonly_gamedir = gameonly_homedir = NULL;
#if defined(HAVE_LEGACY) && defined(PACKAGE_PK3)
{
searchpathfuncs_t *pak;
vfsfile_t *vfs;
char pakname[MAX_OSPATH];
Q_snprintfz(pakname, sizeof(pakname), "%sQuakeEX.kpf", com_gamepath);
vfs = VFSOS_Open(pakname, "rb");
pak = FSZIP_LoadArchive(vfs, NULL, pakname, pakname, "");
if (pak) //logically should have SPF_EXPLICIT set, but that would give it a worse gamedir depth
FS_AddPathHandle(&oldpaths, "", pakname, pak, "", SPF_COPYPROTECTED, reloadflags);
}
#endif
i = COM_CheckParm ("-basepack"); i = COM_CheckParm ("-basepack");
while (i && i < com_argc-1) while (i && i < com_argc-1)
{ {

View file

@ -7590,6 +7590,9 @@ static qboolean check_pext2_infoblobs (extcheck_t *extcheck) {return !!(extchec
//static qboolean check_pext2_stunaware (extcheck_t *extcheck) {return !!(extcheck->pext2 & PEXT2_STUNAWARE);} //static qboolean check_pext2_stunaware (extcheck_t *extcheck) {return !!(extcheck->pext2 & PEXT2_STUNAWARE);}
static qboolean check_pext2_vrinputs (extcheck_t *extcheck) {return !!(extcheck->pext2 & PEXT2_VRINPUTS);} static qboolean check_pext2_vrinputs (extcheck_t *extcheck) {return !!(extcheck->pext2 & PEXT2_VRINPUTS);}
//rerelease stomped on things. make sure our earlier extension reports correctly.
static qboolean check_bouncemissile (extcheck_t *extcheck) {return !extcheck->world->remasterlogic/*became 'movetype_gib'*/;}
#define NOBI NULL, 0,{NULL}, #define NOBI NULL, 0,{NULL},
qc_extension_t QSG_Extensions[] = { qc_extension_t QSG_Extensions[] = {
//these don't have well-defined names... //these don't have well-defined names...
@ -7635,7 +7638,7 @@ qc_extension_t QSG_Extensions[] = {
{"DP_LIGHTSTYLE_STATICVALUE"}, {"DP_LIGHTSTYLE_STATICVALUE"},
{"DP_LITSUPPORT"}, {"DP_LITSUPPORT"},
{"DP_MONSTERWALK", NULL, 0,{NULL}, "MOVETYPE_WALK is valid on non-player entities. Note that only players receive acceleration etc in line with none/bounce/fly/noclip movetypes on the player, thus you will have to provide your own accelerations (incluing gravity) yourself."}, {"DP_MONSTERWALK", NULL, 0,{NULL}, "MOVETYPE_WALK is valid on non-player entities. Note that only players receive acceleration etc in line with none/bounce/fly/noclip movetypes on the player, thus you will have to provide your own accelerations (incluing gravity) yourself."},
{"DP_MOVETYPEBOUNCEMISSILE"}, //I added the code for hexen2 support. {"DP_MOVETYPEBOUNCEMISSILE", check_bouncemissile}, //I added the code for hexen2 support.
{"DP_MOVETYPEFOLLOW"}, {"DP_MOVETYPEFOLLOW"},
{"DP_QC_ASINACOSATANATAN2TAN", NULL, 5,{"asin", "acos", "atan", "atan2", "tan"}}, {"DP_QC_ASINACOSATANATAN2TAN", NULL, 5,{"asin", "acos", "atan", "atan2", "tan"}},
{"DP_QC_CHANGEPITCH", NULL, 1,{"changepitch"}}, {"DP_QC_CHANGEPITCH", NULL, 1,{"changepitch"}},

View file

@ -46,6 +46,7 @@ struct wedict_s
//thus this system requires various builtins to exist at specific numbers. //thus this system requires various builtins to exist at specific numbers.
//this competes against checkbuiltin(funcreference). //this competes against checkbuiltin(funcreference).
typedef struct { typedef struct {
world_t *world;
unsigned int pext1, pext2; unsigned int pext1, pext2;
} extcheck_t; } extcheck_t;
typedef struct qc_extension_s { typedef struct qc_extension_s {

View file

@ -15,9 +15,15 @@ int com_language;
char sys_language[64] = ""; char sys_language[64] = "";
static char langpath[MAX_OSPATH] = ""; static char langpath[MAX_OSPATH] = "";
struct language_s languages[MAX_LANGUAGES]; struct language_s languages[MAX_LANGUAGES];
static struct po_s *com_translations;
static void QDECL TL_LanguageChanged(struct cvar_s *var, char *oldvalue) static void QDECL TL_LanguageChanged(struct cvar_s *var, char *oldvalue)
{ {
if (com_translations)
{
PO_Close(com_translations);
com_translations = NULL;
}
com_language = TL_FindLanguage(var->string); com_language = TL_FindLanguage(var->string);
} }
@ -495,3 +501,147 @@ const char *PO_GetText(struct po_s *po, const char *msg)
return line->translated; return line->translated;
return msg; return msg;
} }
static void PO_Merge_Rerelease(struct po_s *po, const char *fmt)
{
//FOO <plat,plat> = "CString"
char line[32768];
char key[256];
char val[32768];
char *s;
vfsfile_t *file = NULL;
if (!file && *language.string) //use system locale names
file = FS_OpenVFS(va(fmt, language.string), "rb", FS_GAME);
if (!file) //make a guess
{
s = NULL;
if (language.string[0] && language.string[1] && (!language.string[2] || language.string[2] == '-' || language.string[2] == '_'))
{ //try to map the user's formal locale to the rerelease's arbitrary names (at least from the perspective of anyone who doesn't speak english).
if (!strncmp(language.string, "fr", 2))
s = "french";
else if (!strncmp(language.string, "de", 2))
s = "german";
else if (!strncmp(language.string, "it", 2))
s = "italian";
else if (!strncmp(language.string, "ru", 2))
s = "russian";
else if (!strncmp(language.string, "es", 2))
s = "spanish";
}
if (s)
file = FS_OpenVFS(va(fmt, s), "rb", FS_GAME);
}
if (!file) //fall back on misnamed american, for lack of a better default.
file = FS_OpenVFS(va(fmt, "english"), "rb", FS_GAME);
if (file)
{
*key = '$';
while(VFS_GETS(file, line, sizeof(line)))
{
s = COM_ParseOut(line, key+1, sizeof(key)-1);
s = COM_ParseOut(s, val, sizeof(val));
if (strcmp(val,"="))
continue;
s = COM_ParseCString(s, val, sizeof(val), NULL);
if (!s)
continue;
PO_AddText(po, key, val);
}
VFS_CLOSE(file);
}
}
void TL_Reformat(char *out, size_t outsize, size_t numargs, const char **arg)
{
const char *fmt;
const char *a;
size_t alen;
for (alen = 0; alen < numargs; alen++)
{
if (*arg[alen] == '$')
{
if (!com_translations)
{
char lang[64], *h;
vfsfile_t *f = NULL;
com_translations = PO_Create();
PO_Merge_Rerelease(com_translations, "localization/loc_%s.txt");
Q_strncpyz(lang, language.string, sizeof(lang));
while ((h = strchr(lang, '-')))
*h = '_'; //standardise it
if (*lang)
f = FS_OpenVFS(va("localisation/%s.po", lang), "rb", FS_GAME); //long/specific form
if (!f)
{
if ((h = strchr(lang, '_')))
{
*h = 0;
if (*lang)
f = FS_OpenVFS(va("localisation/%s.po", lang), "rb", FS_GAME); //short/general form
}
}
if (f)
PO_Merge(com_translations, f);
}
arg[alen] = PO_GetText(com_translations, arg[alen]);
}
}
fmt = (numargs>0&&arg[0])?arg[0]:"";
outsize--;
while (outsize > 0)
{
if (!*fmt)
break;
else if (*fmt == '{')
{
unsigned int index = strtoul(fmt+1, (char**)&fmt, 10)+1;
int size = 0;
if (*fmt == ',')
size = strtol(fmt+1, (char**)&fmt, 10);
if (*fmt == ':')
{ //formatting, which we don't support because its all strings.
fmt = fmt+1;
while (*fmt && *fmt != '}')
fmt++;
}
if (*fmt == '}')
fmt++;
else
break; //some formatting error
if (index >= numargs || !arg[index])
a = "";
else
a = arg[index];
alen = strlen(a);
if (alen > outsize)
alen = outsize;
if (size > 0)
{ //right aligned
if (alen > size)
alen = size;
memcpy(out, a, alen);
}
else if (size < 0)
{ //left aligned
if (alen > -size)
alen = -size;
memcpy(out, a, alen);
}
else //no alignment, no padding.
memcpy(out, a, alen);
out += alen;
outsize -= alen;
}
else
*out++ = *fmt++, outsize--;
}
*out = 0;
}

View file

@ -34,6 +34,7 @@ float Font_DrawScaleChar(float px, float py, unsigned int charflags, unsigned in
void Font_EndString(struct font_s *font); void Font_EndString(struct font_s *font);
int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int maxlines, conchar_t **starts, conchar_t **ends); int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int maxlines, conchar_t **starts, conchar_t **ends);
struct font_s *font_menu;
struct font_s *font_default; struct font_s *font_default;
struct font_s *font_console; struct font_s *font_console;
struct font_s *font_tiny; struct font_s *font_tiny;
@ -228,6 +229,7 @@ enum fontfmt_e
FMT_WINDOWS1252,//variation of latin-1 with extra glyphs FMT_WINDOWS1252,//variation of latin-1 with extra glyphs
FMT_KOI8U, //image is 16*16 koi8-u codepage. FMT_KOI8U, //image is 16*16 koi8-u codepage.
FMT_HORIZONTAL, //unicode, charcount=width/(height-2). single strip of chars, like halflife. FMT_HORIZONTAL, //unicode, charcount=width/(height-2). single strip of chars, like halflife.
FMT_RERELEASE, //fonts/foo.kfont specifies a texture and a series of glyph positions within it.
}; };
typedef struct fontface_s typedef struct fontface_s
@ -1023,6 +1025,7 @@ static struct charcache_s *Font_TryLoadGlyphRaster(font_t *f, fontface_t *qface,
{ {
safedefault: safedefault:
case FMT_AUTO: //shouldn't happen. case FMT_AUTO: //shouldn't happen.
case FMT_RERELEASE: //shouldn't happen.
case FMT_ISO88591: //all identity. case FMT_ISO88591: //all identity.
case FMT_HORIZONTAL: //erk... case FMT_HORIZONTAL: //erk...
c1tab = NULL; c1tab = NULL;
@ -1610,6 +1613,85 @@ qboolean Font_LoadHorizontalFont(struct font_s *f, int fheight, const char *font
return false; return false;
} }
qboolean Font_LoadKexFont(struct font_s *f, int fheight, const char *fontfilename)
{
vfsfile_t *kfont = FS_OpenVFS(va("fonts/%s.kfont", fontfilename), "rb", FS_GAME);
char line[256];
char val[256], *s;
struct charcache_s *c;
fontface_t *qface;
if (!kfont)
return false;
while(VFS_GETS(kfont, line, sizeof(line)))
{
s = COM_ParseOut(line, val, sizeof(val));
if (!s)
continue;
if (!strcmp(val, "texture") && (s=COM_ParseOut(s, val, sizeof(val))))
{
TEXDOWAIT(f->singletexture);
if (!TEXLOADED(f->singletexture))
f->singletexture = Image_GetTexture(val, NULL, IF_NOWORKER|IF_EXACTEXTENSION|IF_UIPIC|(r_font_linear.ival?IF_LINEAR:IF_NEAREST|IF_NOPURGE)|IF_NOPICMIP|IF_NOMIPMAP|IF_NOGAMMA|IF_NOPURGE, NULL, NULL, 0, 0, PTI_INVALID);
}
else if (*val >= '0' && *val <='9')
{
unsigned int codepoint = atoi(val);
unsigned int x, y, w, h;//, u;
if (!TEXLOADED(f->singletexture))
break;
s=COM_ParseOut(s, val, sizeof(val));
x = atoi(val);
s=COM_ParseOut(s, val, sizeof(val));
y = atoi(val);
s=COM_ParseOut(s, val, sizeof(val));
w = atoi(val);
s=COM_ParseOut(s, val, sizeof(val));
h = atoi(val);
s=COM_ParseOut(s, val, sizeof(val));
//u = atoi(val);
if (!s)
continue; //something truncated.
if (codepoint >= FONT_MAXCHARS || h<=0)
continue; //out of range.
c = Font_GetCharStore(f, codepoint);
if (codepoint != ' ')
{
y+=2;
h-=4;
}
c->advance = max(1,(f->charheight * w)/h);
c->bmw = (w * PLANEWIDTH) / f->singletexture->width;
c->bmh = (h * PLANEHEIGHT) / f->singletexture->height;
c->bmx = (x * PLANEWIDTH) / f->singletexture->width;
c->bmy = (y * PLANEHEIGHT) / f->singletexture->height;
c->left = 0;
c->nextchar = 0; //these chars are not linked in
c->texplane = BITMAPPLANE;
}
}
VFS_CLOSE(kfont);
if (!TEXLOADED(f->singletexture))
return false;
/*success!*/
qface = Z_Malloc(sizeof(*qface));
qface->flink = &faces;
qface->fnext = *qface->flink;
*qface->flink = qface;
if (qface->fnext)
qface->fnext->flink = &qface->fnext;
qface->refs++;
Q_snprintfz(qface->name, sizeof(qface->name), "fonts/%s.kfont", fontfilename);
f->face[f->faces++] = qface;
return true;
}
#ifdef AVAIL_FREETYPE #ifdef AVAIL_FREETYPE
extern cvar_t dpcompat_smallerfonts; extern cvar_t dpcompat_smallerfonts;
int Font_ChangeFTSize(fontface_t *qface, int pixelheight) int Font_ChangeFTSize(fontface_t *qface, int pixelheight)
@ -2196,6 +2278,8 @@ struct font_s *Font_LoadFont(const char *fontfilename, float vheight, float scal
fmt = FMT_KOI8U; fmt = FMT_KOI8U;
else if (*t == 'h') else if (*t == 'h')
fmt = FMT_HORIZONTAL; fmt = FMT_HORIZONTAL;
else if (*t == 'r')
fmt = FMT_RERELEASE;
} }
if (!strncmp(parms, "aspect=", 7)) if (!strncmp(parms, "aspect=", 7))
{ {
@ -2388,6 +2472,8 @@ struct font_s *Font_LoadFont(const char *fontfilename, float vheight, float scal
if (end) if (end)
*end = 0; *end = 0;
if (fmt == FMT_RERELEASE)
success = Font_LoadKexFont(f, height, start);
if (fmt == FMT_HORIZONTAL) if (fmt == FMT_HORIZONTAL)
success = Font_LoadHorizontalFont(f, height, start); success = Font_LoadHorizontalFont(f, height, start);
#ifdef AVAIL_FREETYPE #ifdef AVAIL_FREETYPE
@ -2673,6 +2759,8 @@ float Font_CharScaleHeight(void)
int Font_TabWidth(int x) int Font_TabWidth(int x)
{ {
int tabwidth = Font_CharWidth(CON_WHITEMASK, ' '); int tabwidth = Font_CharWidth(CON_WHITEMASK, ' ');
if (!tabwidth)
tabwidth = curfont->charheight;
tabwidth *= 8; tabwidth *= 8;
x++; x++;

View file

@ -3558,10 +3558,19 @@ static void *X11VID_CreateCursor(const qbyte *imagedata, int width, int height,
{ {
int nw,nh; int nw,nh;
qbyte *nd; qbyte *nd;
nw = width * scale; for(;;)
nh = height * scale; {
if (nw <= 0 || nh <= 0 || nw > 128 || nh > 128) //don't go crazy. nw = width * scale;
return NULL; nh = height * scale;
if (nw <= 0 || nh <= 0 || nw > 128 || nh > 128) //don't go crazy.
return NULL;
if (nw < 8)
scale = 8/width;
else if (nh < 8)
scale = 8/height;
else
break;
}
nd = Image_ResampleTexture(format, imagedata, width, height, NULL, nw, nh); nd = Image_ResampleTexture(format, imagedata, width, height, NULL, nw, nh);
if (!nd) if (!nd)
return NULL; //resampling of that format didn't work for some reason... return NULL; //resampling of that format didn't work for some reason...

View file

@ -2313,16 +2313,6 @@ void Q_InitProgs(enum initprogs_e flags)
#endif #endif
World_RBE_Start(&sv.world); World_RBE_Start(&sv.world);
if (sv.world.remasterlogic)
{
PR_EnableEBFSBuiltin("bprints", 23);
PR_EnableEBFSBuiltin("sprints", 24);
PR_EnableEBFSBuiltin("centerprints", 73);
PR_EnableEBFSBuiltin("finaleFinished", 79);
PR_EnableEBFSBuiltin("localsound_remaster", 80);
Con_Printf(CON_WARNING "Remastered quakec detected (this is not fool-proof), compat workarounds have been enabled\n");
}
} }
qboolean PR_QCChat(char *text, int say_type) qboolean PR_QCChat(char *text, int say_type)
@ -7237,13 +7227,13 @@ static void QCBUILTIN PF_checkextension (pubprogfuncs_t *prinst, struct globalva
if (ext->extensioncheck && clnum >= 1 && clnum <= sv.allocated_client_slots) if (ext->extensioncheck && clnum >= 1 && clnum <= sv.allocated_client_slots)
{ {
client_t *cl = &svs.clients[clnum-1]; client_t *cl = &svs.clients[clnum-1];
extcheck_t check = {cl->fteprotocolextensions, cl->fteprotocolextensions2}; extcheck_t check = {prinst->parms->user, cl->fteprotocolextensions, cl->fteprotocolextensions2};
if (!ext->extensioncheck(&check)) if (!ext->extensioncheck(&check))
return; //blocked by some setting somewhere, somehow. return; //blocked by some setting somewhere, somehow.
} }
else if (ext->extensioncheck) else if (ext->extensioncheck)
{ {
extcheck_t check = {Net_PextMask(PROTOCOL_VERSION_FTE1, false), Net_PextMask(PROTOCOL_VERSION_FTE2, false)}; extcheck_t check = {prinst->parms->user, Net_PextMask(PROTOCOL_VERSION_FTE1, false), Net_PextMask(PROTOCOL_VERSION_FTE2, false)};
if (!ext->extensioncheck(&check)) if (!ext->extensioncheck(&check))
return; //blocked by some setting somewhere, somehow. return; //blocked by some setting somewhere, somehow.
} }
@ -10732,15 +10722,100 @@ void PF_localsound_remaster(pubprogfuncs_t *prinst, struct globalvars_s *pr_glob
} }
void PF_centerprints(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void PF_centerprints(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ //TODO: send the strings to the client for localisation+reordering { //TODO: send the strings to the client for localisation+reordering
PF_centerprint(prinst, pr_globals); const char *arg[8];
int args;
char s[1024];
int entnum;
entnum = G_EDICTNUM(prinst, OFS_PARM0);
for (args = 0; args+1 < prinst->callargc; args++)
arg[args] = PR_GetStringOfs(prinst, OFS_PARM1+args*(OFS_PARM1-OFS_PARM0));
TL_Reformat(s, sizeof(s), args, arg);
PF_centerprint_Internal(entnum, false, s);
} }
void PF_sprints(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void PF_sprints(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ //TODO: send the strings to the client for localisation+reordering. {
PF_sprint(prinst, pr_globals); const char *arg[8];
int args;
char s[1024];
client_t *client;
int entnum;
int level;
#ifdef SERVER_DEMO_PLAYBACK
if (sv.demofile)
return;
#endif
entnum = G_EDICTNUM(prinst, OFS_PARM0);
if (progstype == PROG_NQ || progstype == PROG_H2)
{
level = PRINT_HIGH;
for (args = 0; args+1 < prinst->callargc; args++)
arg[args] = PR_GetStringOfs(prinst, OFS_PARM1+args*(OFS_PARM1-OFS_PARM0));
}
else
{
level = G_FLOAT(OFS_PARM1);
for (args = 0; args+2 < prinst->callargc; args++)
arg[args] = PR_GetStringOfs(prinst, OFS_PARM2+args*(OFS_PARM1-OFS_PARM0));
}
TL_Reformat(s, sizeof(s), args, arg);
if (entnum < 1 || entnum > sv.allocated_client_slots)
{
Con_TPrintf ("tried to sprint to a non-client\n");
return;
}
client = &svs.clients[entnum-1];
SV_ClientPrintf (client, level, "%s", s);
if (sv_specprint.ival & SPECPRINT_SPRINT)
{
client_t *spec;
unsigned int i;
for (i = 0, spec = svs.clients; i < sv.allocated_client_slots; i++, spec++)
{
if (spec->state != cs_spawned || !spec->spectator)
continue;
if (spec->spec_track == entnum && (spec->spec_print & SPECPRINT_SPRINT))
{
if (level < spec->messagelevel)
continue;
if (spec->controller)
SV_PrintToClient(spec->controller, level, s);
else
SV_PrintToClient(spec, level, s);
}
}
}
} }
void PF_bprints(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) void PF_bprints(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{ //TODO: send the strings to the client for localisation+reordering { //TODO: send the strings to the client for localisation+reordering
PF_bprint(prinst, pr_globals); const char *arg[8];
int args;
char formatted[1024];
int level;
if (progstype == PROG_QW)
{
level = G_FLOAT(OFS_PARM0);
for (args = 0; args+1 < prinst->callargc; args++)
arg[args] = PR_GetStringOfs(prinst, OFS_PARM1+args*(OFS_PARM1-OFS_PARM0));
}
else
{
level = PRINT_HIGH;
for (args = 0; args < prinst->callargc; args++)
arg[args] = PR_GetStringOfs(prinst, OFS_PARM0+args*(OFS_PARM1-OFS_PARM0));
}
TL_Reformat(formatted, sizeof(formatted), args, arg);
SV_BroadcastPrintf (level, "%s", formatted);
} }
#define STUB ,NULL,true #define STUB ,NULL,true
@ -12113,6 +12188,20 @@ void PR_ResetBuiltins(progstype_t type) //fix all nulls to PF_FIXME and add any
Con_Printf("Be aware that MVDSV does not follow standards. Please encourage mod developers to not require pr_imitatemvdsv to be set.\n"); Con_Printf("Be aware that MVDSV does not follow standards. Please encourage mod developers to not require pr_imitatemvdsv to be set.\n");
} }
} }
#ifdef HAVE_LEGACY
//when this cvar is set, we're assumed to be running a rerelease-compatible mod.
//obviously this might still break mods that don't include their own quake.rc (most of them), but hey... compat, right?
if (scr_usekfont.ival)
{
PR_EnableEBFSBuiltin("bprints", 23);
PR_EnableEBFSBuiltin("sprints", 24);
PR_EnableEBFSBuiltin("centerprints", 73);
PR_EnableEBFSBuiltin("finaleFinished", 79);
PR_EnableEBFSBuiltin("localsound_remaster", 80);
}
#endif
} }
void PR_SVExtensionList_f(void) void PR_SVExtensionList_f(void)
@ -12126,7 +12215,7 @@ void PR_SVExtensionList_f(void)
int num; int num;
char biissues[8192]; char biissues[8192];
extcheck_t extcheck = {Net_PextMask(PROTOCOL_VERSION_FTE1, false), Net_PextMask(PROTOCOL_VERSION_FTE2, false)}; extcheck_t extcheck = {&sv.world, Net_PextMask(PROTOCOL_VERSION_FTE1, false), Net_PextMask(PROTOCOL_VERSION_FTE2, false)};
#define SHOW_ACTIVEEXT 1 #define SHOW_ACTIVEEXT 1
#define SHOW_ACTIVEBI 2 #define SHOW_ACTIVEBI 2

View file

@ -5726,11 +5726,12 @@ void SV_InitLocal (void)
} }
#define iswhite(c) ((c) == ' ' || (unsigned char)(c) == (unsigned char)INVIS_CHAR1 || (unsigned char)(c) == (unsigned char)INVIS_CHAR2 || (unsigned char)(c) == (unsigned char)INVIS_CHAR3) #define iswhite(c) ((c) == ' ' || (unsigned char)(c) == (unsigned char)INVIS_CHAR1 || (unsigned char)(c) == (unsigned char)INVIS_CHAR2 || (unsigned char)(c) == (unsigned char)INVIS_CHAR3)
#define isinvalid(c) ((c) == ':' || (c) == '\\' || (c) == '\r' || (c) == '\n' || (unsigned char)(c) == (unsigned char)0xff || (c) == '\"') #define isinvalid(c) ((c) == ':' || (c) == '\\' || (c) == '$' || (c) == '\r' || (c) == '\n' || (unsigned char)(c) == (unsigned char)0xff || (c) == '\"')
//colon is so clients can't get confused while parsing chats //colon is so clients can't get confused while parsing chats (eg frag messages)
//255 is so fuhquake/ezquake don't end up with nameless players //255 is so fuhquake/ezquake don't end up with nameless players (and general MSG_ReadString bugs)
//" is so mods that use player names in tokenizing/frik_files don't mess up. mods are still expected to be able to cope with space. //" is so mods that use player names in tokenizing/frik_files don't mess up. mods are still expected to be able to cope with space.
//\ is blocked because it messes up our ^[NAME\player\NUM^] links, and because vanilla would hate it. //\ is blocked because it messes up our ^[NAME\player\NUM^] links, and because vanilla would hate it.
//$ is blocked because of potential internationalisation escapes.
//is allowed to shorten, out must be as long as in and min of "unnamed"+1 //is allowed to shorten, out must be as long as in and min of "unnamed"+1
void SV_FixupName(const char *in, char *out, unsigned int outlen) void SV_FixupName(const char *in, char *out, unsigned int outlen)

View file

@ -1332,6 +1332,7 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
int fl; int fl;
const float *gravitydir; const float *gravitydir;
int movetype;
WPhys_CheckVelocity (w, ent); WPhys_CheckVelocity (w, ent);
@ -1364,11 +1365,12 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
} }
// add gravity // add gravity
if (ent->v->movetype != MOVETYPE_FLY movetype = ent->v->movetype;
&& ent->v->movetype != MOVETYPE_FLY_WORLDONLY if (movetype != MOVETYPE_FLY
&& ent->v->movetype != MOVETYPE_FLYMISSILE && movetype != MOVETYPE_FLY_WORLDONLY
&& (ent->v->movetype != MOVETYPE_BOUNCEMISSILE || w->remasterlogic/*gib*/) && movetype != MOVETYPE_FLYMISSILE
&& ent->v->movetype != MOVETYPE_H2SWIM) && (movetype != MOVETYPE_BOUNCEMISSILE || w->remasterlogic/*gib*/)
&& movetype != MOVETYPE_H2SWIM)
WPhys_AddGravity (w, ent, gravitydir); WPhys_AddGravity (w, ent, gravitydir);
// move angles // move angles
@ -1407,14 +1409,17 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
VectorCopy(trace.endpos, move); VectorCopy(trace.endpos, move);
if (ent->v->movetype == MOVETYPE_BOUNCE) movetype = ent->v->movetype;
if (movetype == MOVETYPE_BOUNCEMISSILE && w->remasterlogic)
movetype = MOVETYPE_BOUNCE; //'gib'...
if (movetype == MOVETYPE_BOUNCE)
{ {
if (ent->xv->bouncefactor) if (ent->xv->bouncefactor)
backoff = 1 + ent->xv->bouncefactor; backoff = 1 + ent->xv->bouncefactor;
else else
backoff = 1.5; backoff = 1.5;
} }
else if (ent->v->movetype == MOVETYPE_BOUNCEMISSILE) else if (movetype == MOVETYPE_BOUNCEMISSILE)
{ {
if (ent->xv->bouncefactor) if (ent->xv->bouncefactor)
backoff = 1 + ent->xv->bouncefactor; backoff = 1 + ent->xv->bouncefactor;
@ -1431,7 +1436,7 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
// stop if on ground // stop if on ground
if ((-DotProduct(gravitydir, trace.plane.normal) > 0.7) && (ent->v->movetype != MOVETYPE_BOUNCEMISSILE)) if ((-DotProduct(gravitydir, trace.plane.normal) > 0.7) && (movetype != MOVETYPE_BOUNCEMISSILE))
{ {
float bouncespeed; float bouncespeed;
float bouncestop = ent->xv->bouncestop; float bouncestop = ent->xv->bouncestop;
@ -1443,7 +1448,7 @@ static void WPhys_Physics_Toss (world_t *w, wedict_t *ent)
bouncespeed = DotProduct(trace.plane.normal, ent->v->velocity); bouncespeed = DotProduct(trace.plane.normal, ent->v->velocity);
else else
bouncespeed = -DotProduct(gravitydir, ent->v->velocity); bouncespeed = -DotProduct(gravitydir, ent->v->velocity);
if (bouncespeed < bouncestop || ent->v->movetype != MOVETYPE_BOUNCE ) if (bouncespeed < bouncestop || movetype != MOVETYPE_BOUNCE )
{ {
ent->v->flags = (int)ent->v->flags | FL_ONGROUND; ent->v->flags = (int)ent->v->flags | FL_ONGROUND;
ent->v->groundentity = EDICT_TO_PROG(w->progs, trace.ent); ent->v->groundentity = EDICT_TO_PROG(w->progs, trace.ent);