Q2 uses trigger_help for primary/secondary goal setting. A spawnflag of 1 makes it secondary, otherwise it is primary.
This is the spawn function:
g_target.c:
Code: Select all
/*QUAKED target_help (1 0 1) (-16 -16 -24) (16 16 24) help1
When fired, the "message" key becomes the current personal computer string, and the message light will be set on all clients status bars.
*/
void SP_target_help(edict_t *ent)
{
if (deathmatch->value)
{ // auto-remove for deathmatch
G_FreeEdict (ent);
return;
}
if (!ent->message)
{
gi.dprintf ("%s with no message at %s\n", ent->classname, vtos(ent->s.origin));
G_FreeEdict (ent);
return;
}
ent->use = Use_Target_Help;
}
Just before that, this is what happens when the server fires a target_help:
Code: Select all
void Use_Target_Help (edict_t *ent, edict_t *other, edict_t *activator)
{
if (ent->spawnflags & 1)
strncpy (game.helpmessage1, ent->message, sizeof(game.helpmessage2)-1);
else
strncpy (game.helpmessage2, ent->message, sizeof(game.helpmessage1)-1);
game.helpchanged++;
}
helpmessage1/2 is part of the game_locals_t struct:
g_local.h:
Code: Select all
typedef struct
{
char helpmessage1[512];
char helpmessage2[512];
int helpchanged; // flash F1 icon if non 0, play sound
// and increment only if 1, 2, or 3
gclient_t *clients; // [maxclients]
// can't store spawnpoint in level, because
// it would get overwritten by the savegame restore
char spawnpoint[512]; // needed for coop respawns
// store latched cvars here that we want to get at often
int maxclients;
int maxentities;
// cross level triggers
int serverflags;
// items
int num_items;
qboolean autosaved;
} game_locals_t;
extern game_locals_t game;
That's 512 characters. Then it's simply drawn to the HUD:
p_hud.c:
Code: Select all
/*
==================
HelpComputer
Draw help computer.
==================
*/
void HelpComputer (edict_t *ent)
{
char string[1024];
char *sk;
if (skill->value == 0)
sk = "easy";
else if (skill->value == 1)
sk = "medium";
else if (skill->value == 2)
sk = "hard";
else
sk = "hard+";
// send the layout
Com_sprintf (string, sizeof(string),
"xv 32 yv 8 picn help " // background
"xv 202 yv 12 string2 \"%s\" " // skill
"xv 0 yv 24 cstring2 \"%s\" " // level name
"xv 0 yv 54 cstring2 \"%s\" " // help 1
"xv 0 yv 110 cstring2 \"%s\" " // help 2
"xv 50 yv 164 string2 \" kills goals secrets\" "
"xv 50 yv 172 string2 \"%3i/%3i %i/%i %i/%i\" ",
sk,
level.level_name,
game.helpmessage1,
game.helpmessage2,
level.killed_monsters, level.total_monsters,
level.found_goals, level.total_goals,
level.found_secrets, level.total_secrets);
gi.WriteByte (svc_layout);
gi.WriteString (string);
gi.unicast (ent, true);
}
The layout strings there are as follows (edited out the irrelevant parts in while):
cl_scrn.c:
Code: Select all
/*
================
SCR_ExecuteLayoutString
================
*/
void SCR_ExecuteLayoutString (char *s)
{
int x, y;
int value;
char *token;
int width;
int index;
clientinfo_t *ci;
if (cls.state != ca_active || !cl.refresh_prepped)
return;
if (!s[0])
return;
x = 0;
y = 0;
width = 3;
while (s)
{
token = COM_Parse (&s);
[...]
if (!strcmp(token, "xv"))
{
token = COM_Parse (&s);
x = viddef.width/2 - 160 + atoi(token);
continue;
}
[...]
if (!strcmp(token, "yv"))
{
token = COM_Parse (&s);
y = viddef.height/2 - 120 + atoi(token);
continue;
}
[...]
if (!strcmp(token, "cstring"))
{
token = COM_Parse (&s);
DrawHUDString (token, x, y, 320, 0);
continue;
}
if (!strcmp(token, "string"))
{
token = COM_Parse (&s);
DrawString (x, y, token);
continue;
}
if (!strcmp(token, "cstring2"))
{
token = COM_Parse (&s);
DrawHUDString (token, x, y, 320,0x80);
continue;
}
if (!strcmp(token, "string2"))
{
token = COM_Parse (&s);
DrawAltString (x, y, token);
continue;
}
if (!strcmp(token, "if"))
{ // draw a number
token = COM_Parse (&s);
value = cl.frame.playerstate.stats[atoi(token)];
if (!value)
{ // skip to endif
while (s && strcmp(token, "endif") )
{
token = COM_Parse (&s);
}
}
continue;
}
}
}
I don't know whether that's helpful or not, hopefully something there can help you (you obviously can't just blindly copy that code though since there are many differences between the 2 games). edict_t is the same as gentity_t, G_FreeEdict same as G_FreeEntity, gi.* have trap_* equivalents in Q3, etc.
Here's the cource code:
http://ftp.gwdg.de/pub/misc/ftp.idsoftw ... src320.exe