I’ve implemented target_location functionality in my mod, and it seems to work great as long as there is only one person on each team.
Whenever another player joins the team, the previous player’s location all list as unknown, or fall back to the grid style, eg (D,1).
Here are some of my changes, as you can tell I’m sticking closely to the RTCW method.
I’ve left out all the clientside code, since the error seems to be coming from the server.
in bg_public.h, modified/added the following
#define CS_LOCATIONS ( CS_STRINGS + MAX_CSSTRINGS )
#define CS_MAX ( CS_LOCATIONS + MAX_LOCATIONS )
in g_target.c
void SP_target_location( gentity_t *self )
{
// G_Printf( S_COLOR_YELLOW "WARNING: target_location entities are now obsolete. Please remove ASAP
" );
// G_FreeEntity( self );
// jet Pilot - un-obsolete-ize this
self->think = target_location_linkup;
self->nextthink = level.time + 1000;
G_SetOrigin( self, self->s.origin );
}
also in g_target.c
// jet Pilot - derived from RTCW location code
void target_location_linkup(gentity_t *ent)
{
int i, n;
static int total = 0;
total++;
if (level.locationLinked)
{
Com_Printf("^9target_location_linkup ^3WARNING: linkup already completed. ^9(%d total locations)
", total);
return;
}
level.locationLinked = qtrue;
level.locationHead = NULL;
trap_SetConfigstring( CS_LOCATIONS, "unknown" );
for (ent = g_entities, i = 0, n = 1; i < level.num_entities; ent++, i++)
{
if (ent->classname && !Q_stricmp(ent->classname, "target_location"))
{
trap_SetConfigstring( CS_LOCATIONS + n, ent->message );
ent->health = n++;
ent->nextTrain = level.locationHead;
level.locationHead = ent;
}
}
}
in g_team.c, in the function void TeamplayInfoMessage I’ve changed the following code
Com_sprintf( entry, sizeof(entry), " %i %i %i %i %i", level.sortedClients[i], player->client->pers.teamState.location[0], player->client->pers.teamState.location[1], h, player->s.powerups);
to
// jet Pilot - send locationIndex to clients, (last on list)
Com_sprintf( entry, sizeof(entry), " %i %i %i %i %i %i", level.sortedClients[i], player->client->pers.teamState.location[0], player->client->pers.teamState.location[1], h, player->s.powerups, player->client->pers.teamState.locationIndex );
also in g_team.c,in the function CheckTeamStatus
after
ent->client->pers.teamState.location[0] = (int)ent->r.currentOrigin[0];
ent->client->pers.teamState.location[1] = (int)ent->r.currentOrigin[1];
//added
loc = Team_GetLocation( ent );
if (loc) ent->client->pers.teamState.locationIndex = loc->health;
else ent->client->pers.teamState.locationIndex = 0;
added these functions
gentity_t *Team_GetLocation(gentity_t *ent)
{
gentity_t *curLoc;
gentity_t *bestLoc = NULL;
float bestdist = 200000000;
float len;
vec3_t origin;
VectorCopy( ent->r.currentOrigin, origin );
for (curLoc = level.locationHead; curLoc; curLoc = curLoc->nextTrain)
{
VectorSubtract( ent->r.currentOrigin, curLoc->r.currentOrigin, lenVec );
len = VectorLength( lenVec );
if ( len > bestdist || !trap_InPVS( origin, curLoc->r.currentOrigin ))
{
continue;
}
bestdist = len;
bestLoc = curLoc;
}
return bestLoc;
}
qboolean Team_GetLocationMsg(gentity_t *ent, char *loc, int loclen)
{
gentity_t *curLoc;
gentity_t *bestLocLoc = NULL;
float bestdist = 200000000;
float len;
vec3_t origin;
VectorCopy( ent->r.currentOrigin, origin );
for (curLoc = level.locationHead; curLoc; curLoc = curLoc->nextTrain)
{
VectorSubtract( ent->r.currentOrigin, curLoc->r.currentOrigin, lenVec );
len = VectorLength( lenVec );
if ( len > bestdist || !trap_InPVS( origin, curLoc->r.currentOrigin ))
{
continue;
}
bestdist = len;
bestLoc = curLoc;
}
if (!bestLoc)
{
return qfalse;
}
Com_sprintf(loc, loclen, "[lon]%s[lof]", bestLoc->message);
return qtrue;
}
in g_cmds.c, in the function G_Say, I’ve modified SAY_TEAM like this
(note the fallback to the grid coordinates if target_location code fails)
case SAY_TEAM:
localize = qtrue;
G_LogPrintf( "sayteam: %s: %s
", ent->client->pers.netname, text );
if (Team_GetLocationMsg(ent, location, sizeof(location)))
{
Com_sprintf (name, sizeof(name), "[lof](%s%c%c) (%s): ", ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE, location);
}
else
{
loc = BG_GetLocationString( ent->r.currentOrigin );
Com_sprintf (name, sizeof(name), "[lof](%s%c%c) (%s): ", ent->client->pers.netname, Q_COLOR_ESCAPE, COLOR_WHITE, loc);
}
color = COLOR_CYAN;
break;
I’ve got no clue why the check works fine until another player joins the team, and it seems to work fine for that player, just not the first player. I’ve only tested it with two players so far, so I don’t know if the third player will break the 2nd as well (and so on)
Any help for anyone would be great, and if anyone who has it actually working could give me some pointers… that would be awesome.