1
0
Fork 0
forked from fte/fteqw

Add _some_ support for the rerelease's waypoints.

This commit is contained in:
Shpoike 2024-11-08 11:51:36 +00:00
parent 9bc9700506
commit 777b4b1fd9
2 changed files with 226 additions and 49 deletions

View file

@ -7714,7 +7714,10 @@ void CSQC_Shutdown(void)
csqc_world.progs = csqcprogs = NULL;
}
else
{
PR_Route_Shutdown (&csqc_world);
World_Destroy(&csqc_world);
}
Cmd_RemoveCommands(CS_ConsoleCommand_f);

View file

@ -660,6 +660,10 @@ struct waypointnetwork_s
int node;
float linkcost;//might be much lower in the case of teleports, or expensive if someone wanted it to be a lower priority link.
int linkflags; //LF_*
struct wphint_s
{
vec3_t pos[3];
} *hints;
} *neighbour;
size_t neighbours;
} waypoints[1];
@ -675,7 +679,7 @@ void WayNet_Done(struct waypointnetwork_s *net)
static qboolean WayNet_TokenizeLine(char **linestart)
{
char *end = *linestart;
if (!*end)
if (!end || !*end)
{ //clear it out...
Cmd_TokenizeString("", false, false);
return false;
@ -697,65 +701,221 @@ static struct waypointnetwork_s *WayNet_Begin(void **ctxptr, model_t *worldmodel
struct waypointnetwork_s *net = *ctxptr;
if (!net)
{
char *wf = NULL, *l, *e;
int numwaypoints, maxlinks, numlinks;
struct wpneighbour_s *nextlink;
char *wf = NULL;
qofs_t fsize = 0;
if (!worldmodel)
return NULL;
if (!wf && !strncmp(worldmodel->name, "maps/", 5))
{
char n[MAX_QPATH];
COM_StripExtension(worldmodel->name+5, n, sizeof(n));
wf = FS_MallocFile(va("data/%s.way", n), FS_GAME, NULL);
wf = FS_MallocFile(va("data/%s.way", n), FS_GAME, &fsize);
if (!wf)
wf = FS_MallocFile(va("bots/navigation/%s.nav", n), FS_GAME, &fsize);
}
if (!wf)
wf = FS_MallocFile(va("%s.way", worldmodel->name), FS_GAME, NULL);
if (!wf)
return NULL;
wf = FS_MallocFile(va("%s.way", worldmodel->name), FS_GAME, &fsize);
l = wf;
//read the number of waypoints
WayNet_TokenizeLine(&l);
numwaypoints = atoi(Cmd_Argv(0));
//count lines and guess the link count.
for (e = l, maxlinks=0; *e; e++)
if (*e == '\n')
maxlinks++;
maxlinks -= numwaypoints;
net = Z_Malloc(sizeof(*net)-sizeof(net->waypoints) + (numwaypoints*sizeof(struct waypoint_s)) + (maxlinks*sizeof(struct wpneighbour_s)));
net->refs = 1;
net->worldmodel = worldmodel;
*ctxptr = net;
if (wf && fsize >= 8 && (
(wf[0] == 'N' && wf[1] == 'A' && wf[2] == 'V' && wf[3] == '2' && (wf[4]|(wf[5]<<8)|(wf[6]<<8)|(wf[7]<<8)) >= 12 && (wf[4]|(wf[5]<<8)|(wf[6]<<8)|(wf[7]<<8)) <= 17) //q1e
||(wf[0] == 'N' && wf[1] == 'A' && wf[2] == 'V' && wf[3] == '3' && (wf[4]|(wf[5]<<8)|(wf[6]<<8)|(wf[7]<<8)) >= 2 && (wf[4]|(wf[5]<<8)|(wf[6]<<8)|(wf[7]<<8)) <= 6) //q2e
))
{ //rerelease's format(s)
sizebuf_t sb = {wf, fsize, fsize};
qboolean error = false;
unsigned int u;
unsigned int ver, numnodes, numlinks, numhints, numents;
struct wphint_s *hints;
struct wpneighbour_s *links;
nextlink = (struct wpneighbour_s*)(net->waypoints+numwaypoints);
MSG_BeginReading(&sb, msg_nullnetprim);
/*magic(already checked)*/MSG_ReadLong();
ver = MSG_ReadLong();
if (wf[3] == '3') ver |= 0x80000000; //convert from q2 to q1 version numbers...
numnodes = MSG_ReadLong();
numlinks = MSG_ReadLong();
numhints = MSG_ReadLong();
if (ver >= 16)
/*some sort of scale?*/MSG_ReadFloat();
while (WayNet_TokenizeLine(&l) && net->numwaypoints < numwaypoints)
{
if (!Cmd_Argc())
continue; //a comment line?
net->waypoints[net->numwaypoints].org[0] = atof(Cmd_Argv(0));
net->waypoints[net->numwaypoints].org[1] = atof(Cmd_Argv(1));
net->waypoints[net->numwaypoints].org[2] = atof(Cmd_Argv(2));
net->waypoints[net->numwaypoints].radius = atof(Cmd_Argv(3));
numlinks = bound(0, atoi(Cmd_Argv(4)), maxlinks);
net = Z_Malloc(sizeof(*net)-sizeof(net->waypoints) + (numnodes*sizeof(struct waypoint_s)) + (numlinks*sizeof(struct wpneighbour_s)) + (numhints*sizeof(struct wphint_s)));
net->numwaypoints = numnodes;
//make sure the links are valid, and clamp to avoid problems (even if we're then going to mis-parse.
net->waypoints[net->numwaypoints].neighbour = nextlink;
while (numlinks-- > 0 && WayNet_TokenizeLine(&l))
links = (struct wpneighbour_s*)(net->waypoints+numnodes);
hints = (struct wphint_s*)(links+numlinks);
for (u = 0; u < numnodes && !error; u++)
{
unsigned short flags = MSG_ReadShort(); //some sort of conditional info
unsigned short nodelinks = MSG_ReadShort();
unsigned short firstlink = MSG_ReadShort();
unsigned short radius = MSG_ReadShort();
(void)flags;
net->waypoints[u].neighbours = nodelinks;
net->waypoints[u].neighbour = links + firstlink;
net->waypoints[u].radius = radius;
if (net->waypoints[u].neighbour+net->waypoints[u].neighbours > &links[numlinks])
error = true;
}
for (u = 0; u < numnodes; u++)
{ //positions are split for some reason
net->waypoints[u].org[0] = MSG_ReadFloat();
net->waypoints[u].org[1] = MSG_ReadFloat();
net->waypoints[u].org[2] = MSG_ReadFloat()+24; //rerelease waypoints are aligned to the ground.
}
for (u = 0; u < numlinks; u++)
{
unsigned short peernode = MSG_ReadShort();
unsigned short type = MSG_ReadShort(); //0=normal, 1=
unsigned short hint = MSG_ReadShort(); //can be ~0
links[u].linkcost = 16;
links[u].linkflags = 1u<<type;
links[u].node = peernode;
links[u].hints = NULL;
if (hint < numhints)
links[u].hints = hints+hint;
else if (hint != 0xffff)
error = true;
if (links[u].node >= numnodes)
error = true;
}
for (u = 0; u < numhints; u++)
{
hints[u].pos[0][0] = MSG_ReadFloat();
hints[u].pos[0][1] = MSG_ReadFloat();
hints[u].pos[0][2] = MSG_ReadFloat();
hints[u].pos[1][0] = MSG_ReadFloat();
hints[u].pos[1][1] = MSG_ReadFloat();
hints[u].pos[1][2] = MSG_ReadFloat();
hints[u].pos[2][0] = MSG_ReadFloat();
hints[u].pos[2][1] = MSG_ReadFloat();
hints[u].pos[2][2] = MSG_ReadFloat();
if (ver >= 0x80000006)
{
/*hints[u].pos[3][0] =*/ MSG_ReadFloat();
/*hints[u].pos[3][1] =*/ MSG_ReadFloat();
/*hints[u].pos[3][2] =*/ MSG_ReadFloat();
}
}
numents = MSG_ReadLong(); //grr
for (u = 0; u < numents; u++)
{
unsigned short link = MSG_ReadShort();
if (link >= numlinks)
error = true; //err?.. probably we don't really care, but for the sake of sanity lets bail.
/*mins = */MSG_ReadFloat();
MSG_ReadFloat();
MSG_ReadFloat();
/*maxs = */MSG_ReadFloat();
MSG_ReadFloat();
MSG_ReadFloat();
if (ver <= 13) //FIXME: true for 12, verify v13
;
else if (ver == 14)
{
/*targ*/MSG_ReadLong();
/*class*/MSG_ReadLong();
}
else if (ver >= 15)
/*entnum*/MSG_ReadLong();
}
for (u = 0; u < numnodes && !error; u++)
{ //compute costs (no reading here)
size_t v;
for (v = 0; v < net->waypoints[u].neighbours; v++)
{
vec3_t move;
VectorSubtract(net->waypoints[net->waypoints[u].neighbour[v].node].org, net->waypoints[u].org, move);
net->waypoints[u].neighbour[v].linkcost = sqrt(DotProduct(move,move));
}
}
if(msg_badread)
error = true;
MSG_ReadByte();
if (!msg_badread)
error = true; //should have taken us over the end. there's trailing junk here.
if (error)
{ //some sort of corrupt
Z_Free(net);
net = NULL;
}
}
else if (wf)
{ //our qc-friendly format (predates remaster)
//read the number of waypoints
char *l=wf, *e;
int numwaypoints, maxlinks, numlinks;
struct wpneighbour_s *nextlink;
WayNet_TokenizeLine(&l);
numwaypoints = atoi(Cmd_Argv(0));
//count lines and guess the link count.
for (e = l, maxlinks=0; *e; e++)
if (*e == '\n')
maxlinks++;
maxlinks -= numwaypoints;
net = Z_Malloc(sizeof(*net)-sizeof(net->waypoints) + (numwaypoints*sizeof(struct waypoint_s)) + (maxlinks*sizeof(struct wpneighbour_s)));
net->worldmodel = worldmodel;
nextlink = (struct wpneighbour_s*)(net->waypoints+numwaypoints);
while (WayNet_TokenizeLine(&l) && net->numwaypoints < numwaypoints)
{
if (!Cmd_Argc())
continue; //a comment line?
nextlink[net->waypoints[net->numwaypoints].neighbours].node = atoi(Cmd_Argv(0));
nextlink[net->waypoints[net->numwaypoints].neighbours].linkcost = atof(Cmd_Argv(1));
nextlink[net->waypoints[net->numwaypoints].neighbours++].linkflags = atoi(Cmd_Argv(2));
net->waypoints[net->numwaypoints].org[0] = atof(Cmd_Argv(0));
net->waypoints[net->numwaypoints].org[1] = atof(Cmd_Argv(1));
net->waypoints[net->numwaypoints].org[2] = atof(Cmd_Argv(2));
net->waypoints[net->numwaypoints].radius = atof(Cmd_Argv(3));
numlinks = bound(0, atoi(Cmd_Argv(4)), maxlinks);
//make sure the links are valid, and clamp to avoid problems (even if we're then going to mis-parse.
net->waypoints[net->numwaypoints].neighbour = nextlink;
while (numlinks-- > 0 && WayNet_TokenizeLine(&l))
{
if (!Cmd_Argc())
continue; //a comment line?
nextlink[net->waypoints[net->numwaypoints].neighbours].node = atoi(Cmd_Argv(0));
nextlink[net->waypoints[net->numwaypoints].neighbours].linkcost = atof(Cmd_Argv(1));
nextlink[net->waypoints[net->numwaypoints].neighbours++].linkflags = atoi(Cmd_Argv(2));
}
maxlinks -= net->waypoints[net->numwaypoints].neighbours;
nextlink += net->waypoints[net->numwaypoints++].neighbours;
}
maxlinks -= net->waypoints[net->numwaypoints].neighbours;
nextlink += net->waypoints[net->numwaypoints++].neighbours;
}
BZ_Free(wf);
}
if (!*ctxptr)
{ //no network yet.
if (!net)
{ //don't spam reload attempts.
if (!worldmodel)
return NULL;
net = Z_Malloc(sizeof(*net)-sizeof(net->waypoints));
net->numwaypoints = 0;
}
net->worldmodel = worldmodel;
//link to the world state
net->refs = 1;
*ctxptr = net;
}
net->refs++;
return net;
}
@ -841,10 +1001,13 @@ void Route_Calculated(void *ctx, void *data, size_t a, size_t b)
if (!route->callback)
{
BZ_Free(route->waynet->displaynode);
route->waynet->displaynode = BZ_Malloc(sizeof(struct resultnodes_s) * route->numresultnodes);
route->waynet->displaynodes = route->numresultnodes;
memcpy(route->waynet->displaynode, route->resultnodes, sizeof(struct resultnodes_s) * route->numresultnodes);
if (route->waynet)
{
BZ_Free(route->waynet->displaynode);
route->waynet->displaynode = BZ_Malloc(sizeof(struct resultnodes_s) * route->numresultnodes);
route->waynet->displaynodes = route->numresultnodes;
memcpy(route->waynet->displaynode, route->resultnodes, sizeof(struct resultnodes_s) * route->numresultnodes);
}
}
else if (route->callback && route->world->spawncount == route->spawncount/* && route->spawnid == route->ed->xv->uniquespawnid*/)
{
@ -1130,6 +1293,11 @@ void QCBUILTIN PF_route_calculate (pubprogfuncs_t *prinst, struct globalvars_s *
VectorCopy(end, route->end);
route->waynet = WayNet_Begin(&route->world->waypoints, route->world->worldmodel);
if (!route->waynet)
{
Z_Free(route);
return;
}
//tracelines use some sequence info to avoid retracing the same brush multiple times.
// this means that we can't reliably trace on worker threads (would break the main thread occasionally).
@ -1153,7 +1321,12 @@ static void Route_Visualise_f(void)
VectorCopy(r_refdef.vieworg, route->start);
VectorCopy(targ, route->end);
route->waynet = WayNet_Begin(&route->world->waypoints, route->world->worldmodel);
route->waynet = WayNet_Begin(&route->world->waypoints, cl.worldmodel);
if (!route->waynet)
{
Z_Free(route);
return;
}
//tracelines use some sequence info to avoid retracing the same brush multiple times.
// this means that we can't reliably trace on worker threads (would break the main thread occasionally).
@ -1173,7 +1346,7 @@ void PR_Route_Visualise (void)
struct waypointnetwork_s *wn;
size_t u;
wn = (w && (w->waypoints || route_shownodes.ival))?WayNet_Begin(&w->waypoints, w->worldmodel):NULL;
wn = (w && (w->waypoints || route_shownodes.ival))?WayNet_Begin(&w->waypoints, cl.worldmodel):NULL;
if (wn)
{
if (route_shownodes.ival)
@ -1205,6 +1378,7 @@ void PR_Route_Visualise (void)
float radius;
vec3_t dir;
//should probably use a different colour for the node you're inside.
int nearest = WayNet_FindNearestNode(wn, r_origin);
for (u = 0; u < wn->numwaypoints; u++)
{
mat[3] = wn->waypoints[u].org[0];
@ -1216,9 +1390,9 @@ void PR_Route_Visualise (void)
VectorSubtract(wn->waypoints[u].org, r_refdef.vieworg, dir);
if (DotProduct(dir,dir) < radius*radius)
CLQ1_AddOrientedSphere(shader_in, radius, mat, 0.0, 0.1, 0, 1);
CLQ1_AddOrientedSphere(shader_in, radius, mat, 0.0, 0.1, (nearest==u)?0.2:0.0, 1);
else
CLQ1_AddOrientedSphere(shader_out, radius, mat, 0.2, 0.0, 0, 1);
CLQ1_AddOrientedSphere(shader_out, radius, mat, 0.2, 0.0, (nearest==u)?0.2:0.0, 1);
}
for (u = 0; u < wn->numwaypoints; u++)
{
@ -1226,7 +1400,7 @@ void PR_Route_Visualise (void)
for (n = 0; n < wn->waypoints[u].neighbours; n++)
{
struct waypoint_s *r = wn->waypoints + wn->waypoints[u].neighbour[n].node;
CLQ1_DrawLine(shader_out, wn->waypoints[u].org, r->org, 0, 0, 1, 1);
CLQ1_DrawLine(shader_out, wn->waypoints[u].org, r->org, 0, 0, (nearest==u)?1:0.2, 1);
}
}
}