mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-28 23:31:57 +00:00
game: Add remaster translation support
This commit is contained in:
parent
51d092660b
commit
1f0e67621c
11 changed files with 254 additions and 7 deletions
1
Makefile
1
Makefile
|
@ -963,6 +963,7 @@ GAME_OBJS_ = \
|
|||
src/game/g_sphere.o \
|
||||
src/game/g_svcmds.o \
|
||||
src/game/g_target.o \
|
||||
src/game/g_translate.o \
|
||||
src/game/g_trigger.o \
|
||||
src/game/g_turret.o \
|
||||
src/game/g_utils.o \
|
||||
|
|
|
@ -2618,7 +2618,7 @@ door_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */,
|
|||
|
||||
self->touch_debounce_time = level.time + 5.0;
|
||||
|
||||
gi.centerprintf(other, "%s", self->message);
|
||||
gi.centerprintf(other, "%s", LocalizationMessage(self->message));
|
||||
gi.sound(other, CHAN_AUTO, gi.soundindex("misc/talk1.wav"), 1, ATTN_NORM, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -228,7 +228,7 @@ secret_touch(edict_t *self, edict_t *other, cplane_t *plane /* unused */, csurfa
|
|||
|
||||
if (self->message)
|
||||
{
|
||||
gi.centerprintf(other, self->message);
|
||||
gi.centerprintf(other, LocalizationMessage(self->message));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -865,8 +865,8 @@ SP_worldspawn(edict_t *ent)
|
|||
/* make some data visible to the server */
|
||||
if (ent->message && ent->message[0])
|
||||
{
|
||||
gi.configstring(CS_NAME, ent->message);
|
||||
Q_strlcpy(level.level_name, ent->message, sizeof(level.level_name));
|
||||
Q_strlcpy(level.level_name, LocalizationMessage(ent->message), sizeof(level.level_name));
|
||||
gi.configstring(CS_NAME, level.level_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
218
src/game/g_translate.c
Normal file
218
src/game/g_translate.c
Normal file
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* Copyright (C) 1997-2001 Id Software, Inc.
|
||||
* Copyright (c) ZeniMax Media Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* =======================================================================
|
||||
*
|
||||
* Localization logic.
|
||||
*
|
||||
* =======================================================================
|
||||
*/
|
||||
|
||||
#include "header/local.h"
|
||||
|
||||
localmessages_t *localmessages = NULL;
|
||||
int nlocalmessages = 0;
|
||||
|
||||
static int
|
||||
LocalizationSort(const void *p1, const void *p2)
|
||||
{
|
||||
localmessages_t *msg1, *msg2;
|
||||
|
||||
msg1 = (localmessages_t*)p1;
|
||||
msg2 = (localmessages_t*)p2;
|
||||
return Q_stricmp(msg1->key, msg2->key);
|
||||
}
|
||||
|
||||
void
|
||||
LocalizationInit(void)
|
||||
{
|
||||
byte *raw = NULL;
|
||||
int len;
|
||||
|
||||
localmessages = NULL;
|
||||
nlocalmessages = 0;
|
||||
|
||||
/* load the file */
|
||||
len = gi.FS_LoadFile("localization/loc_english.txt", (void **)&raw);
|
||||
if (len > 1)
|
||||
{
|
||||
char *buf, *curr;
|
||||
int i;
|
||||
|
||||
buf = malloc(len + 1);
|
||||
memcpy(buf, raw, len);
|
||||
buf[len] = 0;
|
||||
|
||||
/* get lines count */
|
||||
curr = buf;
|
||||
while(*curr)
|
||||
{
|
||||
size_t linesize = 0;
|
||||
|
||||
linesize = strcspn(curr, "\n\r");
|
||||
if (*curr && strncmp(curr, "//", 2) &&
|
||||
*curr != '\n' && *curr != '\r')
|
||||
{
|
||||
nlocalmessages ++;
|
||||
}
|
||||
curr += linesize;
|
||||
if (curr >= (buf + len))
|
||||
{
|
||||
break;
|
||||
}
|
||||
/* skip our endline */
|
||||
curr++;
|
||||
}
|
||||
|
||||
if (nlocalmessages)
|
||||
{
|
||||
localmessages = gi.TagMalloc(nlocalmessages * sizeof(*localmessages), TAG_GAME);
|
||||
memset(localmessages, 0, nlocalmessages * sizeof(*localmessages));
|
||||
}
|
||||
|
||||
/* parse lines */
|
||||
curr = buf;
|
||||
i = 0;
|
||||
while(*curr)
|
||||
{
|
||||
size_t linesize = 0;
|
||||
|
||||
if (i == nlocalmessages)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
linesize = strcspn(curr, "\n\r");
|
||||
curr[linesize] = 0;
|
||||
if (*curr && strncmp(curr, "//", 2) &&
|
||||
*curr != '\n' && *curr != '\r')
|
||||
{
|
||||
char *sign;
|
||||
|
||||
sign = strchr(curr, '=');
|
||||
/* clean up end of key */
|
||||
if (sign)
|
||||
{
|
||||
char *signend;
|
||||
|
||||
signend = sign - 1;
|
||||
while ((*signend == ' ' || *signend == '\t') &&
|
||||
(signend > curr))
|
||||
{
|
||||
*signend = 0;
|
||||
/* go back */
|
||||
signend --;
|
||||
}
|
||||
*sign = 0;
|
||||
sign ++;
|
||||
}
|
||||
|
||||
/* skip value prefix */
|
||||
if (sign && *sign)
|
||||
{
|
||||
size_t valueskip;
|
||||
|
||||
valueskip = strcspn(sign, " \t");
|
||||
sign += valueskip;
|
||||
if (*sign)
|
||||
{
|
||||
sign++;
|
||||
}
|
||||
}
|
||||
|
||||
/* start real value */
|
||||
if (sign && *sign == '"')
|
||||
{
|
||||
char *currend;
|
||||
|
||||
sign ++;
|
||||
|
||||
currend = sign;
|
||||
while (*currend && *currend != '"')
|
||||
{
|
||||
if (*currend == '\\')
|
||||
{
|
||||
/* escaped */
|
||||
*currend = ' ';
|
||||
currend++;
|
||||
if (*currend == 'n')
|
||||
{
|
||||
/* new line */
|
||||
*currend = '\n';
|
||||
}
|
||||
}
|
||||
currend++;
|
||||
}
|
||||
|
||||
if (*currend == '"')
|
||||
{
|
||||
/* mark as end of string */
|
||||
*currend = 0;
|
||||
}
|
||||
|
||||
localmessages[i].key = gi.TagMalloc(strlen(curr) + 2, TAG_GAME);
|
||||
localmessages[i].key[0] = '$';
|
||||
strcpy(localmessages[i].key + 1, curr);
|
||||
localmessages[i].value = gi.TagMalloc(strlen(sign) + 1, TAG_GAME);
|
||||
strcpy(localmessages[i].value, sign);
|
||||
i ++;
|
||||
}
|
||||
}
|
||||
curr += linesize;
|
||||
if (curr >= (buf + len))
|
||||
{
|
||||
break;
|
||||
}
|
||||
/* skip our endline */
|
||||
curr++;
|
||||
}
|
||||
|
||||
nlocalmessages = i;
|
||||
/* sort messages */
|
||||
qsort(localmessages, nlocalmessages, sizeof(localmessages_t), LocalizationSort);
|
||||
|
||||
gi.FS_FreeFile(raw);
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
LocalizationMessage(const char *message)
|
||||
{
|
||||
if (!message || !localmessages || !nlocalmessages)
|
||||
{
|
||||
return message;
|
||||
}
|
||||
|
||||
if (message[0] == '$')
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nlocalmessages; i++)
|
||||
{
|
||||
if (!strcmp(localmessages[i].key, message))
|
||||
{
|
||||
return localmessages[i].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
|
@ -321,7 +321,7 @@ G_UseTargets(edict_t *ent, edict_t *activator)
|
|||
/* print the message */
|
||||
if (activator && (ent->message) && !(activator->svflags & SVF_MONSTER))
|
||||
{
|
||||
gi.centerprintf(activator, "%s", ent->message);
|
||||
gi.centerprintf(activator, "%s", LocalizationMessage(ent->message));
|
||||
|
||||
if (ent->noise_index)
|
||||
{
|
||||
|
|
|
@ -189,6 +189,15 @@ typedef struct
|
|||
void (*AddCommandString)(const char *text);
|
||||
|
||||
void (*DebugGraph)(float value, int color);
|
||||
|
||||
/* Extended to classic Quake2 API.
|
||||
files will be memory mapped read only
|
||||
the returned buffer may be part of a larger pak file,
|
||||
or a discrete file from anywhere in the quake search path
|
||||
a -1 return means the file does not exist
|
||||
NULL can be passed for buf to just determine existance */
|
||||
int (*FS_LoadFile) (const char *name, void **buf);
|
||||
void (*FS_FreeFile) (void *buf);
|
||||
} game_import_t;
|
||||
|
||||
/* functions exported by the game subsystem */
|
||||
|
|
|
@ -994,6 +994,18 @@ void SV_AddGravity(edict_t *ent);
|
|||
void SaveClientData(void);
|
||||
void EndDMLevel(void);
|
||||
|
||||
/* g_translate.c */
|
||||
typedef struct
|
||||
{
|
||||
char *key;
|
||||
char *value;
|
||||
} localmessages_t;
|
||||
|
||||
extern localmessages_t *localmessages;
|
||||
extern int nlocalmessages;
|
||||
void LocalizationInit(void);
|
||||
const char* LocalizationMessage(const char *message);
|
||||
|
||||
/* g_chase.c */
|
||||
void UpdateChaseCam(edict_t *ent);
|
||||
void ChaseNext(edict_t *ent);
|
||||
|
|
|
@ -421,8 +421,8 @@ HelpComputerMessage(edict_t *ent)
|
|||
"xv 50 yv 172 string2 \"%3i/%3i %i/%i %i/%i\" ",
|
||||
sk,
|
||||
level.level_name,
|
||||
game.helpmessage1,
|
||||
game.helpmessage2,
|
||||
LocalizationMessage(game.helpmessage1),
|
||||
LocalizationMessage(game.helpmessage2),
|
||||
level.killed_monsters, level.total_monsters,
|
||||
level.found_goals, level.total_goals,
|
||||
level.found_secrets, level.total_secrets);
|
||||
|
|
|
@ -264,6 +264,9 @@ InitGame(void)
|
|||
g_quick_weap = gi.cvar("g_quick_weap", "1", CVAR_ARCHIVE);
|
||||
g_swap_speed = gi.cvar("g_swap_speed", "1", 0);
|
||||
|
||||
/* initilize localization */
|
||||
LocalizationInit();
|
||||
|
||||
/* items */
|
||||
InitItems();
|
||||
|
||||
|
|
|
@ -453,6 +453,10 @@ SV_InitGameProgs(void)
|
|||
import.SetAreaPortalState = CM_SetAreaPortalState;
|
||||
import.AreasConnected = CM_AreasConnected;
|
||||
|
||||
/* Extension to classic Quake2 API */
|
||||
import.FS_LoadFile = FS_LoadFile;
|
||||
import.FS_FreeFile = FS_FreeFile;
|
||||
|
||||
ge = (game_export_t *)Sys_GetGameAPI(&import);
|
||||
|
||||
if (!ge)
|
||||
|
|
Loading…
Reference in a new issue