From 22460c5aa0d092a8b4e346af19976cbcb8819bc6 Mon Sep 17 00:00:00 2001 From: Marco Cawthorne Date: Fri, 17 Nov 2023 18:58:24 -0800 Subject: [PATCH] BotLib: new commands - 'offset [vector]', 'flipx', 'flipy', 'flipz', 'merge [filename.way]', 'loadpb [podbotwaypoint.pwf]', 'loadrich [jumbot.jrf]', 'loadfb [foxbot.fwp]' Also make the bots use the soundDef when pressing '+use'. --- src/botlib/bot.qc | 2 +- src/botlib/include.src | 1 + src/botlib/way.qc | 76 ++++-- src/botlib/way_convert.qc | 502 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 565 insertions(+), 16 deletions(-) create mode 100644 src/botlib/way_convert.qc diff --git a/src/botlib/bot.qc b/src/botlib/bot.qc index 992e910f..d71468ed 100644 --- a/src/botlib/bot.qc +++ b/src/botlib/bot.qc @@ -92,7 +92,7 @@ bot::UseButton(void) } bestButton.Trigger(this, TRIG_TOGGLE); - sound(this, CHAN_ITEM, "common/wpn_select.wav", 0.25, ATTN_IDLE); + StartSoundDef("Player.WeaponSelected", CHAN_ITEM, false); } void diff --git a/src/botlib/include.src b/src/botlib/include.src index 05767451..14361923 100644 --- a/src/botlib/include.src +++ b/src/botlib/include.src @@ -7,5 +7,6 @@ bot_chat.qc bot_combat.qc route.qc way.qc +way_convert.qc cmd.qc #endlist diff --git a/src/botlib/way.qc b/src/botlib/way.qc index 8016aa33..bdf7d7b4 100644 --- a/src/botlib/way.qc +++ b/src/botlib/way.qc @@ -27,14 +27,14 @@ typedef struct waypoint_s int m_numNeighbours; } waypoint_t; -static waypoint_t *g_pWaypoints; -static int g_iWaypoints; +waypoint_t *g_pWaypoints; +int g_iWaypoints; static int g_waylink_status; var int g_way1 = -1; var int g_way2 = -1; -static void +void Way_WipeWaypoints(void) { for (int i = 0; i < g_iWaypoints; i++) { @@ -45,7 +45,7 @@ Way_WipeWaypoints(void) g_iWaypoints = 0; } -static void +void Way_LinkNodes(waypoint_t *wp, waypoint_t *w2) { int w2n = w2 - g_pWaypoints; @@ -103,7 +103,7 @@ Way_UnlinkNodes(waypoint_t *wp, waypoint_t *w2) } } -static void +void Way_AutoLink(int wpidx) { for (int i = 0i; i < g_iWaypoints; i++) { @@ -518,21 +518,34 @@ Way_SaveFile(string filename) } void -Way_ReadFile(string strFile) +Way_ReadFile(string strFile, bool flush) { - float file = fopen(strFile, FILE_READ); + int startId = 0i; + int offSet = 0i; + + filestream file = fopen(strFile, FILE_READ); if (file < 0) { print("Way_ReadFile: unable to open ", strFile, "\n"); return; } - Way_WipeWaypoints(); - + /* read the number of waypoints */ tokenize(fgets(file)); - g_iWaypoints = stoi(argv(0)); - g_pWaypoints = memalloc(sizeof(*g_pWaypoints) * g_iWaypoints); - for (int i = 0i; i < g_iWaypoints; i++) { + if (flush) { + Way_WipeWaypoints(); + g_iWaypoints = stoi(argv(0)); + g_pWaypoints = memalloc(sizeof(*g_pWaypoints) * g_iWaypoints); + } else { + int oldSize = g_iWaypoints; + int newSize = g_iWaypoints + stoi(argv(0)); + g_pWaypoints = (waypoint_t *)memrealloc(g_pWaypoints, sizeof(waypoint_t), oldSize, newSize); + g_iWaypoints = newSize; + startId = oldSize; + offSet = oldSize; + } + + for (int i = startId; i < g_iWaypoints; i++) { tokenize(fgets(file)); g_pWaypoints[i].m_vecOrigin[0] = stof(argv(0)); g_pWaypoints[i].m_vecOrigin[1] = stof(argv(1)); @@ -543,7 +556,7 @@ Way_ReadFile(string strFile) for (int j = 0i; j < g_pWaypoints[i].m_numNeighbours; j++) { tokenize(fgets(file)); - g_pWaypoints[i].m_pNeighbour[j].m_iNode = stoi(argv(0)); + g_pWaypoints[i].m_pNeighbour[j].m_iNode = offSet + stoi(argv(0)); g_pWaypoints[i].m_pNeighbour[j].m_flCost = stof(argv(1)); g_pWaypoints[i].m_pNeighbour[j].m_iFlags = stoi(argv(2)); } @@ -551,7 +564,6 @@ Way_ReadFile(string strFile) fclose(file); } - void Way_ConnectOne(void) { @@ -725,6 +737,9 @@ Way_DrawDebugInfo(void) } } +void Way_ReadFBFile(string, bool); +void Way_ReadPBFile(string, bool); +void Way_ReadJumbotFile(string, bool); void Way_Cmd(void) { @@ -780,6 +795,25 @@ Way_Cmd(void) g_pWaypoints[i].m_flRadius = autocvar_nav_radius; } break; + case "offset": + for (int i = 0i; i < g_iWaypoints; i++) { + g_pWaypoints[i].m_vecOrigin += stov(argv(2)); + } + break; + case "flipx": + for (int i = 0i; i < g_iWaypoints; i++) { + g_pWaypoints[i].m_vecOrigin[0] *= -1; + } + case "flipy": + for (int i = 0i; i < g_iWaypoints; i++) { + g_pWaypoints[i].m_vecOrigin[1] *= -1; + } + break; + case "flipz": + for (int i = 0i; i < g_iWaypoints; i++) { + g_pWaypoints[i].m_vecOrigin[2] *= -1; + } + break; case "linkjump": Way_FlagJump(); break; @@ -821,7 +855,19 @@ Way_Cmd(void) Way_SaveFile(argv(2)); break; case "load": - Way_ReadFile(argv(2)); + Way_ReadFile(argv(2), true); + break; + case "merge": + Way_ReadFile(argv(2), false); + break; + case "loadpb": + Way_ReadPBFile(argv(2), true); + break; + case "loadrich": + Way_ReadJumbotFile(argv(2), true); + break; + case "loadfb": + Way_ReadFBFile(argv(2), true); break; } } diff --git a/src/botlib/way_convert.qc b/src/botlib/way_convert.qc new file mode 100644 index 00000000..69e03b91 --- /dev/null +++ b/src/botlib/way_convert.qc @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2016-2022 Vera Visions LLC. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +typedef struct +{ + /* 8 bytes */ + int type1; + int type2; + + int versionNumber; + int extraFlags; + int numNodes; + + /* 32 bytes */ + int mapname1; + int mapname2; + int mapname3; + int mapname4; + int mapname5; + int mapname6; + int mapname7; + int mapname8; +} fb_header; + +#define FBFL_TEAM1 0x00000001 +#define FBFL_TEAM2 0x00000002 +#define FBFL_TEAMSPECIFIC 0x00000004 +#define FBFL_CROUCH 0x00000008 +#define FBFL_LADDER 0x00000010 +#define FBFL_LIFT 0x00000020 +#define FBFL_WALK 0x00000040 +#define FBFL_HEALTH 0x00000080 +#define FBFL_ARMOR 0x00000100 +#define FBFL_AMMO 0x00000200 +#define FBFL_SNIPER 0x00000400 +#define FBFL_GOALITEM 0x00000800 +#define FBFL_GOAL 0x00001000 +#define FBFL_SENTRY 0x00002000 +#define FBFL_AIMING 0x00004000 +#define FBFL_JUMP 0x00008000 +#define FBFL_DETPACKSEAL 0x00010000 +#define FBFL_PATHCHECK 0x00020000 +#define FBFL_UNUSED1 0x00040000 +#define FBFL_UNUSED2 0x00080000 +#define FBFL_UNUSED3 0x00100000 +#define FBFL_UNUSED4 0x00200000 +#define FBFL_UNUSED5 0x00400000 +#define ITEM_UNUSED6 0x00800000 +#define FBFL_PIPETRAP 0x01000000 +#define FBFL_DETPACKCLEAR 0x02000000 +#define FBFL_TELEENTER 0x04000000 +#define FBFL_CONCJUMP 0x08000000 +#define FBFL_SENTRY_180 0x10000000 +#define FBFL_DEFEND 0x20000000 +#define FBFL_TELEEXIT 0x40000000 +#define FBFL_DELETED 0x80000000 + +int +Way_FBFlagsToNC(int inputFlags) +{ + int outFlags = 0i; + + if (inputFlags & FBFL_JUMP) + outFlags |= LF_JUMP; + + if (inputFlags & FBFL_WALK) + outFlags |= LF_WALK; + + if (inputFlags & FBFL_CROUCH) + outFlags |= LF_CROUCH; + + if (inputFlags & FBFL_AIMING) + outFlags |= LF_AIM; + + if (inputFlags & FBFL_LADDER) + outFlags |= LF_AIM; + + return outFlags; +} + +/* Reads a FB waypoint file. + +These are binary files and contain a lot of type sizes that we don't +have access to in QC. So we cannot just fread() into a struct. + +The only flag between nodes is seemingly JUMP (1), however the +individual nodes themselves have defining info flags too including +ones for using buttons and ladders. Ideally we'd want to re-interpret +those into linkflags. + */ +void +Way_ReadFBFile(string strFile, bool flush) +{ + int startId = 0i; + int offSet = 0i; + fb_header fbHeader; + int *nodeFlags; + + filestream file = fopen(strFile, FILE_READ); + if (file < 0) { + print("Way_ReadFile: unable to open ", strFile, "\n"); + return; + } + + fread(file, (void*)&fbHeader, sizeof(fb_header)); + + if (flush) { + Way_WipeWaypoints(); + g_iWaypoints = fbHeader.numNodes; + g_pWaypoints = memalloc(sizeof(*g_pWaypoints) * g_iWaypoints); + } else { + int oldSize = g_iWaypoints; + int newSize = g_iWaypoints + fbHeader.numNodes; + g_pWaypoints = (waypoint_t *)memrealloc(g_pWaypoints, sizeof(waypoint_t), oldSize, newSize); + g_iWaypoints = newSize; + startId = oldSize; + offSet = oldSize; + } + + print(sprintf("FB Waypoints Version %i, %i nodes\n", fbHeader.versionNumber, fbHeader.numNodes)); + + nodeFlags = (int *)memalloc(sizeof(int) * fbHeader.numNodes); + + /* create the nodes */ + for (int i = startId; i < g_iWaypoints; i++) { + int iData = 0i; + float flData = 0.0f; + + fread(file, (void*)&nodeFlags[i], 4); /* flags */ + fread(file, (void*)&iData, 4); /* script flags, should be 1 byte but it's padded. */ + + fread(file, (void*)&flData, 4); /* origin x */ + g_pWaypoints[i].m_vecOrigin[0] = flData; + fread(file, (void*)&flData, 4); /* origin y */ + g_pWaypoints[i].m_vecOrigin[1] = flData; + fread(file, (void*)&flData, 4); /* origin z */ + g_pWaypoints[i].m_vecOrigin[2] = flData; + } + + /* create the links */ + for (int i = startId; i < g_iWaypoints; i++) { + int iData = 0i; + fread(file, (void*)&iData, 2); /* neighbour count */ + //print(sprintf("%i neighbours\n", iData)); + + g_pWaypoints[i].m_numNeighbours = iData; + g_pWaypoints[i].m_pNeighbour = memalloc(sizeof(*g_pWaypoints[i].m_pNeighbour) * g_pWaypoints[i].m_numNeighbours); + + for (int j = 0i; j < g_pWaypoints[i].m_numNeighbours; j++) { + fread(file, (void*)&iData, 2); /* neighbour index */ + g_pWaypoints[i].m_pNeighbour[j].m_iNode = offSet + iData; + g_pWaypoints[i].m_pNeighbour[j].m_flCost = -1; + g_pWaypoints[i].m_pNeighbour[j].m_iFlags = Way_FBFlagsToNC(nodeFlags[offSet + iData]); + } + } + + memfree(nodeFlags); + fclose(file); +} + +typedef struct +{ + /* 8 bytes */ + int type1; + int type2; + int versionNumber; + int numNodes; + /* 32 bytes */ + int mapname1; + int mapname2; + int mapname3; + int mapname4; + int mapname5; + int mapname6; + int mapname7; + int mapname8; + /* 32 bytes */ + int author1; + int author2; + int author3; + int author4; + int author5; + int author6; + int author7; + int author8; +} pb_header; + +#define PBFL_USEBUTTON 0x00000001i +#define PBFL_ELEVATOR 0x00000002i +#define PBFL_CROUCH 0x00000004i +#define PBFL_CROSSING 0x00000008i +#define PBFL_GOAL 0x00000010i +#define PBFL_LADDER 0x00000020i +#define PBFL_RESCUE 0x00000040i +#define PBFL_CAMP 0x00000080i + +int +Way_PBFlagsToNC(int inputFlags) +{ + int outFlags = 0i; + + if (inputFlags & 1) + outFlags |= LF_JUMP; + + return outFlags; +} + +/* Reads a PB version 5, 6, 7 file. + +These are binary files and contain a lot of type sizes that we don't +have access to in QC. So we cannot just fread() into a struct. + +The only flag between nodes is seemingly JUMP (1), however the +individual nodes themselves have defining info flags too including +ones for using buttons and ladders. Ideally we'd want to re-interpret +those into linkflags. + */ +void +Way_ReadPBFile(string strFile, bool flush) +{ + int startId = 0i; + int offSet = 0i; + pb_header pbHeader; + + filestream file = fopen(strFile, FILE_READ); + if (file < 0) { + print("Way_ReadFile: unable to open ", strFile, "\n"); + return; + } + + fread(file, (void*)&pbHeader, sizeof(pb_header)); + + if (flush) { + Way_WipeWaypoints(); + g_iWaypoints = pbHeader.numNodes; + g_pWaypoints = memalloc(sizeof(*g_pWaypoints) * g_iWaypoints); + } else { + int oldSize = g_iWaypoints; + int newSize = g_iWaypoints + pbHeader.numNodes; + g_pWaypoints = (waypoint_t *)memrealloc(g_pWaypoints, sizeof(waypoint_t), oldSize, newSize); + g_iWaypoints = newSize; + startId = oldSize; + offSet = oldSize; + } + + print(sprintf("PB Waypoints Version %i, %i nodes\n", pbHeader.versionNumber, pbHeader.numNodes)); + + for (int i = startId; i < g_iWaypoints; i++) { + int neighbours = 0i; + int index[8]; + float cost[8]; + int nFlags[8]; + int iData = 0i; + float flData = 0.0f; + + /* make them all invalid */ + for (int n = 0i; n < 8i; n++) { + index[n] = 65535; + } + + if (pbHeader.versionNumber == 7) { + fread(file, (void*)&iData, 4); /* number */ + fread(file, (void*)&iData, 4); /* flags */ + fread(file, (void*)&flData, 4); /* origin x */ + g_pWaypoints[i].m_vecOrigin[0] = flData; + fread(file, (void*)&flData, 4); /* origin y */ + g_pWaypoints[i].m_vecOrigin[1] = flData; + fread(file, (void*)&flData, 4); /* origin z */ + g_pWaypoints[i].m_vecOrigin[2] = flData; + fread(file, (void*)&flData, 4); /* radius */ + g_pWaypoints[i].m_flRadius = flData; + fread(file, (void*)&flData, 4); /* camp start x */ + fread(file, (void*)&flData, 4); /* camp start y */ + fread(file, (void*)&flData, 4); /* camp end x */ + fread(file, (void*)&flData, 4); /* camp end y */ + fread(file, (void*)&index[0], 2); /* index 1 */ + fread(file, (void*)&index[1], 2); /* index 2 */ + fread(file, (void*)&index[2], 2); /* index 3 */ + fread(file, (void*)&index[3], 2); /* index 4 */ + fread(file, (void*)&index[4], 2); /* index 5 */ + fread(file, (void*)&index[5], 2); /* index 6 */ + fread(file, (void*)&index[6], 2); /* index 7 */ + fread(file, (void*)&index[7], 2); /* index 8 */ + fread(file, (void*)&nFlags[0], 2); /* nFlags 1 */ + fread(file, (void*)&nFlags[1], 2); /* nFlags 2 */ + fread(file, (void*)&nFlags[2], 2); /* nFlags 3 */ + fread(file, (void*)&nFlags[3], 2); /* nFlags 4 */ + fread(file, (void*)&nFlags[4], 2); /* nFlags 5 */ + fread(file, (void*)&nFlags[5], 2); /* nFlags 6 */ + fread(file, (void*)&nFlags[6], 2); /* nFlags 7 */ + fread(file, (void*)&nFlags[7], 2); /* nFlags 8 */ + fread(file, (void*)&flData, 4); /* velocity 1 x */ + fread(file, (void*)&flData, 4); /* velocity 1 y */ + fread(file, (void*)&flData, 4); /* velocity 1 z */ + fread(file, (void*)&flData, 4); /* velocity 2 x */ + fread(file, (void*)&flData, 4); /* velocity 2 y */ + fread(file, (void*)&flData, 4); /* velocity 2 z */ + fread(file, (void*)&flData, 4); /* velocity 3 x */ + fread(file, (void*)&flData, 4); /* velocity 3 y */ + fread(file, (void*)&flData, 4); /* velocity 3 z */ + fread(file, (void*)&flData, 4); /* velocity 4 x */ + fread(file, (void*)&flData, 4); /* velocity 4 y */ + fread(file, (void*)&flData, 4); /* velocity 4 z */ + fread(file, (void*)&flData, 4); /* velocity 5 x */ + fread(file, (void*)&flData, 4); /* velocity 5 y */ + fread(file, (void*)&flData, 4); /* velocity 5 z */ + fread(file, (void*)&flData, 4); /* velocity 6 x */ + fread(file, (void*)&flData, 4); /* velocity 6 y */ + fread(file, (void*)&flData, 4); /* velocity 6 z */ + fread(file, (void*)&flData, 4); /* velocity 7 x */ + fread(file, (void*)&flData, 4); /* velocity 7 y */ + fread(file, (void*)&flData, 4); /* velocity 7 z */ + fread(file, (void*)&flData, 4); /* velocity 8 x */ + fread(file, (void*)&flData, 4); /* velocity 8 y */ + fread(file, (void*)&flData, 4); /* velocity 8 z */ + fread(file, (void*)&iData, 4); /* distance 1 */ + cost[0] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 2 */ + cost[1] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 3 */ + cost[2] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 4 */ + cost[3] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 5 */ + cost[4] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 6 */ + cost[5] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 7 */ + cost[6] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 8 */ + cost[7] = (float)iData; + fread(file, (void*)&iData, 4); /* pointer */ + } else if (pbHeader.versionNumber == 6) { + fread(file, (void*)&iData, 4); /* number */ + fread(file, (void*)&iData, 4); /* flags */ + fread(file, (void*)&flData, 4); /* origin x */ + g_pWaypoints[i].m_vecOrigin[0] = flData; + fread(file, (void*)&flData, 4); /* origin y */ + g_pWaypoints[i].m_vecOrigin[1] = flData; + fread(file, (void*)&flData, 4); /* origin z */ + g_pWaypoints[i].m_vecOrigin[2] = flData; + fread(file, (void*)&flData, 4); /* radius */ + g_pWaypoints[i].m_flRadius = flData; + fread(file, (void*)&flData, 4); /* camp start x */ + fread(file, (void*)&flData, 4); /* camp start y */ + fread(file, (void*)&flData, 4); /* camp end x */ + fread(file, (void*)&flData, 4); /* camp end y */ + fread(file, (void*)&index[0], 2); /* index 1 */ + fread(file, (void*)&index[1], 2); /* index 2 */ + fread(file, (void*)&index[2], 2); /* index 3 */ + fread(file, (void*)&index[3], 2); /* index 4 */ + fread(file, (void*)&index[4], 2); /* index 5 */ + fread(file, (void*)&index[5], 2); /* index 6 */ + fread(file, (void*)&index[6], 2); /* index 7 */ + fread(file, (void*)&index[7], 2); /* index 8 */ + fread(file, (void*)&iData, 4); /* distance 1 */ + cost[0] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 2 */ + cost[1] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 3 */ + cost[2] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 4 */ + cost[3] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 5 */ + cost[4] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 6 */ + cost[5] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 7 */ + cost[6] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 8 */ + cost[7] = (float)iData; + fread(file, (void*)&iData, 4); /* pointer */ + } else if (pbHeader.versionNumber == 5) { + fread(file, (void*)&iData, 4); /* number */ + fread(file, (void*)&iData, 4); /* flags */ + fread(file, (void*)&flData, 4); /* origin x */ + g_pWaypoints[i].m_vecOrigin[0] = flData; + fread(file, (void*)&flData, 4); /* origin y */ + g_pWaypoints[i].m_vecOrigin[1] = flData; + fread(file, (void*)&flData, 4); /* origin z */ + g_pWaypoints[i].m_vecOrigin[2] = flData; + fread(file, (void*)&flData, 4); /* radius */ + g_pWaypoints[i].m_flRadius = flData; + fread(file, (void*)&flData, 4); /* camp start x */ + fread(file, (void*)&flData, 4); /* camp start y */ + fread(file, (void*)&flData, 4); /* camp end x */ + fread(file, (void*)&flData, 4); /* camp end y */ + fread(file, (void*)&index[0], 2); /* index 1 */ + fread(file, (void*)&index[1], 2); /* index 2 */ + fread(file, (void*)&index[2], 2); /* index 3 */ + fread(file, (void*)&index[3], 2); /* index 4 */ + fread(file, (void*)&iData, 4); /* distance 1 */ + cost[0] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 2 */ + cost[1] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 3 */ + cost[2] = (float)iData; + fread(file, (void*)&iData, 4); /* distance 4 */ + cost[3] = (float)iData; + fread(file, (void*)&iData, 4); /* pointer */ + } + + /* check for valid neighbours */ + for (int n = 0i; n < 8i; n++) { + if (index[n] != 65535) /* -1 */ + neighbours++; + } + + g_pWaypoints[i].m_numNeighbours = neighbours; + g_pWaypoints[i].m_pNeighbour = memalloc(sizeof(*g_pWaypoints[i].m_pNeighbour) * g_pWaypoints[i].m_numNeighbours); + + for (int j = 0i; j < g_pWaypoints[i].m_numNeighbours; j++) { + g_pWaypoints[i].m_pNeighbour[j].m_iNode = offSet + index[j]; + g_pWaypoints[i].m_pNeighbour[j].m_flCost = cost[j]; + g_pWaypoints[i].m_pNeighbour[j].m_iFlags = Way_PBFlagsToNC(nFlags[j]); + } + } + fclose(file); +} + + + +/* Reads a Jumbot file. + +Plaintext that's simple to parse, however does not store any node +connections. That's because Jumbot was specific to Half-Life and +the AI was smart enough to know how to navigate using only those +helper points. + +We count all lines until we hit the end character '$' and then parse +each line - which contains the info: [id] [flag] ([position]) + +We then link those in linear order. There's probably better ways of +doing that so that'll be an area of research. +*/ +void +Way_ReadJumbotFile(string strFile, bool flush) +{ + int startId = 0i; + int offSet = 0i; + int nodeCount = 0i; + string line; + + filestream file = fopen(strFile, FILE_READ); + if (file < 0) { + print("Way_ReadFile: unable to open ", strFile, "\n"); + return; + } + + /* read the number of waypoints */ + while ((line = fgets(file))) { + if (line != "$") { + nodeCount++; + } + } + fseek(file, 0); + + print(sprintf("Jumpbot Waypoints Version %i, %i nodes\n", 1i, nodeCount)); + + if (flush) { + Way_WipeWaypoints(); + g_iWaypoints = nodeCount; + g_pWaypoints = memalloc(sizeof(*g_pWaypoints) * g_iWaypoints); + } else { + int oldSize = g_iWaypoints; + int newSize = g_iWaypoints + nodeCount; + g_pWaypoints = (waypoint_t *)memrealloc(g_pWaypoints, sizeof(waypoint_t), oldSize, newSize); + g_iWaypoints = newSize; + startId = oldSize; + offSet = oldSize; + } + + for (int i = startId; i < g_iWaypoints; i++) { + float length = strlen(argv(5)); + line = fgets(file); + tokenize(line); + g_pWaypoints[i].m_vecOrigin[0] = stof(argv(3)); + g_pWaypoints[i].m_vecOrigin[1] = stof(argv(4)); + g_pWaypoints[i].m_vecOrigin[2] = stof(argv(5)); + g_pWaypoints[i].m_flRadius = 32.0f; + + if (i > startId) { + Way_LinkNodes(&g_pWaypoints[i], &g_pWaypoints[i-1]); + Way_LinkNodes(&g_pWaypoints[i-1], &g_pWaypoints[i]); + } + } + + fclose(file); +} \ No newline at end of file