Reworked configs to use a more elegant key->value format.

This commit is contained in:
Julian
2020-02-27 19:30:02 -03:00
parent cc33d0efeb
commit b22f0d1e89
3 changed files with 324 additions and 412 deletions

View File

@@ -1,5 +1,9 @@
// //
// botman's monster - MetaMOD plugin // Monster Mod is a modification based on Botman's original "Monster" plugin.
// The "forgotten" modification was made by Rick90.
// This is an attempt to recreate the plugin so it does not become lost again.
//
// Recreated by Giegue.
// //
// dllapi.cpp // dllapi.cpp
// //
@@ -101,20 +105,23 @@ DLL_DECALLIST gDecals[] = {
monster_type_t monster_types[]= monster_type_t monster_types[]=
{ {
"agrunt", FALSE, // These are just names. But to keep it consistent
"apache", FALSE, // with the new KVD format, ensure these are exactly
"barney", FALSE, // like an actual, entity classname.
"bigmomma", FALSE, "monster_alien_grunt", FALSE,
"bullsquid", FALSE, "monster_apache", FALSE,
"controller", FALSE, "monster_barney", FALSE,
"hassassin", FALSE, "monster_bigmomma", FALSE,
"headcrab", FALSE, "monster_bullsquid", FALSE,
"hgrunt", FALSE, "monster_alien_controller", FALSE,
"houndeye", FALSE, "monster_hassassin", FALSE,
"islave", FALSE, "monster_headcrab", FALSE,
"scientist", FALSE, "monster_human_grunt", FALSE,
"snark", FALSE, "monster_houndeye", FALSE,
"zombie", FALSE, "monster_alien_slave", FALSE,
"monster_scientist", FALSE,
"monster_snark", FALSE,
"monster_zombie", FALSE,
"", FALSE "", FALSE
}; };
@@ -320,7 +327,7 @@ void check_monster_dead(void)
} }
bool spawn_monster(int monster_type, Vector origin, float angle, int respawn_index) bool spawn_monster(int monster_type, Vector origin, Vector angles, int respawn_index)
{ {
int monster_index; int monster_index;
edict_t *monster_pent; edict_t *monster_pent;
@@ -399,8 +406,12 @@ bool spawn_monster(int monster_type, Vector origin, float angle, int respawn_ind
monsters[monster_index].monster_index = (*g_engfuncs.pfnIndexOfEdict)(monster_pent); monsters[monster_index].monster_index = (*g_engfuncs.pfnIndexOfEdict)(monster_pent);
monster_pent->v.origin = origin; monster_pent->v.origin = origin;
monster_pent->v.angles.y = angle; monster_pent->v.angles = angles;
// Since the entity is now linked to the class above,
// it's pev->classname should be, theorically, safe to edit.
// The pev->classname is set in the monster's Spawn() function.
//monster_pent->v.classname = MAKE_STRING("monster_zombie");
monsters[monster_index].pMonster->Spawn(); monsters[monster_index].pMonster->Spawn();
monster_pent->v.spawnflags = SF_MONSTER_FADECORPSE; monster_pent->v.spawnflags = SF_MONSTER_FADECORPSE;
@@ -412,10 +423,9 @@ bool spawn_monster(int monster_type, Vector origin, float angle, int respawn_ind
void check_respawn(void) void check_respawn(void)
{ {
int type_index;
int monster_type; int monster_type;
Vector origin; Vector origin;
float angle; Vector angles;
if (!monster_spawn->value) if (!monster_spawn->value)
return; // monster_spawn is turned off, retry again later return; // monster_spawn is turned off, retry again later
@@ -427,20 +437,13 @@ void check_respawn(void)
{ {
monster_spawnpoint[index].need_to_respawn = FALSE; monster_spawnpoint[index].need_to_respawn = FALSE;
type_index = RANDOM_LONG(0, monster_spawnpoint[index].monster_count-1); monster_type = monster_spawnpoint[index].monster;
monster_type = monster_spawnpoint[index].monster[type_index];
origin = monster_spawnpoint[index].origin; origin = monster_spawnpoint[index].origin;
angle = monster_spawnpoint[index].angle_min; angles = monster_spawnpoint[index].angles;
if (angle != monster_spawnpoint[index].angle_max) if (spawn_monster(monster_type, origin, angles, index))
{
angle = RANDOM_FLOAT(angle, monster_spawnpoint[index].angle_max);
}
if (spawn_monster(monster_type, origin, angle, index))
{ {
// spawn_monster failed, retry again after delay... // spawn_monster failed, retry again after delay...
monster_spawnpoint[index].need_to_respawn = TRUE; monster_spawnpoint[index].need_to_respawn = TRUE;
@@ -573,7 +576,7 @@ void MonsterCommand(void)
Vector origin = pPlayer->v.origin; Vector origin = pPlayer->v.origin;
Vector view_angle = pPlayer->v.v_angle; Vector view_angle = pPlayer->v.v_angle;
Vector v_src, v_dest; Vector v_src, v_dest;
float monster_angle; Vector monster_angle;
// try to determine the best place to spawn the monster... // try to determine the best place to spawn the monster...
@@ -596,11 +599,11 @@ void MonsterCommand(void)
if (tr.flFraction < 1.0) // hit something? if (tr.flFraction < 1.0) // hit something?
{ {
monster_angle = view_angle.y + 180.0f; // face the player monster_angle.y = view_angle.y + 180.0f; // face the player
if (monster_angle > 360) if (monster_angle.y > 360)
monster_angle -= 360; monster_angle.y -= 360;
if (monster_angle < 0) if (monster_angle.y < 0)
monster_angle += 360; monster_angle.y += 360;
spawn_monster(monster_type, v_src, monster_angle, -1); spawn_monster(monster_type, v_src, monster_angle, -1);
@@ -624,11 +627,11 @@ void MonsterCommand(void)
if (tr.flFraction < 1.0) // hit something? if (tr.flFraction < 1.0) // hit something?
{ {
monster_angle = view_angle.y - 135.0f; // face the player monster_angle.y = view_angle.y - 135.0f; // face the player
if (monster_angle > 360) if (monster_angle.y > 360)
monster_angle -= 360; monster_angle.y -= 360;
if (monster_angle < 0) if (monster_angle.y < 0)
monster_angle += 360; monster_angle.y += 360;
spawn_monster(monster_type, v_src, monster_angle, -1); spawn_monster(monster_type, v_src, monster_angle, -1);
@@ -652,11 +655,11 @@ void MonsterCommand(void)
if (tr.flFraction < 1.0) // hit something? if (tr.flFraction < 1.0) // hit something?
{ {
monster_angle = view_angle.y + 135.0f; // face the player monster_angle.y = view_angle.y + 135.0f; // face the player
if (monster_angle > 360) if (monster_angle.y > 360)
monster_angle -= 360; monster_angle.y -= 360;
if (monster_angle < 0) if (monster_angle.y < 0)
monster_angle += 360; monster_angle.y += 360;
spawn_monster(monster_type, v_src, monster_angle, -1); spawn_monster(monster_type, v_src, monster_angle, -1);
@@ -679,11 +682,11 @@ void MonsterCommand(void)
if (tr.flFraction < 1.0) // hit something? if (tr.flFraction < 1.0) // hit something?
{ {
monster_angle = view_angle.y + 90.0f; // face the player monster_angle.y = view_angle.y + 90.0f; // face the player
if (monster_angle > 360) if (monster_angle.y > 360)
monster_angle -= 360; monster_angle.y -= 360;
if (monster_angle < 0) if (monster_angle.y < 0)
monster_angle += 360; monster_angle.y += 360;
spawn_monster(monster_type, v_src, monster_angle, -1); spawn_monster(monster_type, v_src, monster_angle, -1);
@@ -706,11 +709,11 @@ void MonsterCommand(void)
if (tr.flFraction < 1.0) // hit something? if (tr.flFraction < 1.0) // hit something?
{ {
monster_angle = view_angle.y - 90.0f; // face the player monster_angle.y = view_angle.y - 90.0f; // face the player
if (monster_angle > 360) if (monster_angle.y > 360)
monster_angle -= 360; monster_angle.y -= 360;
if (monster_angle < 0) if (monster_angle.y < 0)
monster_angle += 360; monster_angle.y += 360;
spawn_monster(monster_type, v_src, monster_angle, -1); spawn_monster(monster_type, v_src, monster_angle, -1);
@@ -733,11 +736,11 @@ void MonsterCommand(void)
if (tr.flFraction < 1.0) // hit something? if (tr.flFraction < 1.0) // hit something?
{ {
monster_angle = view_angle.y; // face the player monster_angle.y = view_angle.y; // face the player
if (monster_angle > 360) if (monster_angle.y > 360)
monster_angle -= 360; monster_angle.y -= 360;
if (monster_angle < 0) if (monster_angle.y < 0)
monster_angle += 360; monster_angle.y += 360;
spawn_monster(monster_type, v_src, monster_angle, -1); spawn_monster(monster_type, v_src, monster_angle, -1);
@@ -850,9 +853,14 @@ void mmDispatchThink( edict_t *pent )
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);
} }
// HACKHACK -- this is a hack to keep the node graph entity from "touching" things (like triggers)
// while it builds the graph
BOOL gTouchDisabled = FALSE;
void mmDispatchTouch( edict_t *pentTouched, edict_t *pentOther ) void mmDispatchTouch( edict_t *pentTouched, edict_t *pentOther )
{ {
if (gTouchDisabled)
RETURN_META(MRES_SUPERCEDE);
for (int index=0; index < monster_ents_used; index++) for (int index=0; index < monster_ents_used; index++)
{ {
if ((pentTouched != NULL) && (pentTouched == monsters[index].monster_pent)) if ((pentTouched != NULL) && (pentTouched == monsters[index].monster_pent))

View File

@@ -22,397 +22,305 @@ extern int monster_spawn_count;
bool get_input(FILE *fp, char *input) bool get_input(FILE *fp, char *input)
{ {
char line[1024]; char line[1024];
int len, pos; int len, pos;
while (!feof(fp)) while (!feof(fp))
{ {
if (fgets(line, 1023, fp) != NULL) if (fgets(line, 1023, fp) != NULL)
{ {
len = strlen(line); len = strlen(line);
if (len == 0) if (len == 0)
continue; // skip any null lines continue; // skip any null lines
// remove any trailing newline, carriage return or whitespace... // remove any trailing newline, carriage return or whitespace...
while ((line[len-1] == '\n') || (line[len-1] == '\r') || while ((line[len-1] == '\n') || (line[len-1] == '\r') || isspace(line[len-1]))
isspace(line[len-1])) {
{ line[len-1] = 0;
line[len-1] = 0; len--;
len--; if (len == 0)
if (len == 0) break;
break; }
}
pos = 0; pos = 0;
while (isspace(line[pos])) while (isspace(line[pos]))
pos++; // skip leading blanks pos++; // skip leading blanks
if ((line[pos] == '/') && (line[pos+1] == '/')) if ((line[pos] == '/') && (line[pos+1] == '/'))
continue; // skip comment lines continue; // skip comment lines
if (line[pos] == 0) if (line[pos] == 0)
continue; // skip empty lines continue; // skip empty lines
strcpy(input, &line[pos]); strcpy(input, &line[pos]);
return TRUE; return TRUE;
} }
} }
return FALSE; // no input found return FALSE; // no input found
} }
struct pKVD
bool scan_monster_cfg(FILE *fp)
{ {
char input[1024]; char key[33];
bool origin, angle, delay, angle_min, angle_max, monster; char value[33];
float x, y, z; };
void scan_monster_cfg(FILE *fp)
while (get_input(fp, input)) {
{ // Let's make a full rework of this. -Giegue
if (monster_spawn_count == MAX_MONSTERS) char input[1024];
continue; // skip if max monster spawn count reached float x, y, z;
if (input[0] == '{') while (get_input(fp, input))
{ {
origin = angle = delay = angle_min = angle_max = monster = FALSE; if (input[0] == '{')
{
monster_spawnpoint[monster_spawn_count].monster_count = 0; // Proper start, initialize entity creation
// Temporary variables to store entity data
while (get_input(fp, input)) pKVD *data = (pKVD*)malloc(32*sizeof(*data)); // Entities should not have more than 32 keyvalues
{ int kvd_index = 0;
if (input[0] == '}') while (get_input(fp, input))
break; {
// It's the end of the entity structure?
if (strncmp(input, "origin/", 7) == 0) if (input[0] == '}')
{ {
if (origin) // Done. Let's process the keyvalues.
{ for (int i = 0; i < kvd_index; i++)
//META_CONS("[MONSTER] ERROR: origin found twice: %s", input); {
LOG_MESSAGE(PLID, "ERROR: origin found twice: %s", input); float x, y, z;
return TRUE; // error // Any unknown keyvalue is ignored.
} // Any duplicate keyvalue is overwritten.
if (sscanf(&input[7], "%f %f %f", &x, &y, &z) != 3)
{ if (strcmp(data[i].key, "origin") == 0)
//META_CONS("[MONSTER] ERROR: invalid origin: %s", input); {
LOG_MESSAGE(PLID, "ERROR: invalid origin: %s", input); if (sscanf(data[i].value, "%f %f %f", &x, &y, &z) != 3)
return TRUE; // error {
} LOG_MESSAGE(PLID, "ERROR: invalid origin: %s", input); // print conflictive line
origin = TRUE;
monster_spawnpoint[monster_spawn_count].origin[0] = x; // reset origin to g_vecZero
monster_spawnpoint[monster_spawn_count].origin[1] = y; LOG_MESSAGE(PLID, "ERROR: entity will spawn at 0 0 0");
monster_spawnpoint[monster_spawn_count].origin[2] = z; x = y = z = 0;
} }
else if (strncmp(input, "delay/", 6) == 0) monster_spawnpoint[monster_spawn_count].origin[0] = x;
{ monster_spawnpoint[monster_spawn_count].origin[1] = y;
if (delay) monster_spawnpoint[monster_spawn_count].origin[2] = z;
{ }
//META_CONS("[MONSTER] ERROR: delay found twice: %s", input); else if (strcmp(data[i].key, "delay") == 0)
LOG_MESSAGE(PLID, "ERROR: delay found twice: %s", input); {
return TRUE; // error // ToDo: Remove this keyvalue.
} // Monsters spawned directly should not respawn.
if (sscanf(&input[6], "%f", &x) != 1) if (sscanf(data[i].value, "%f", &x) != 1)
{ {
//META_CONS("[MONSTER] ERROR: invalid delay: %s", input); LOG_MESSAGE(PLID, "ERROR: invalid delay: %s", input); // print conflictive line
LOG_MESSAGE(PLID, "ERROR: invalid delay: %s", input);
return TRUE; // error // default to 30 seconds
} LOG_MESSAGE(PLID, "ERROR: entity respawn frequency will be set to 30 seconds");
delay = TRUE; x = 30;
monster_spawnpoint[monster_spawn_count].delay = x; }
} monster_spawnpoint[monster_spawn_count].delay = x;
else if (strncmp(input, "angle/", 6) == 0) }
{ else if (strcmp(data[i].key, "angles") == 0)
if (angle) {
{ if (sscanf(data[i].value, "%f %f %f", &x, &y, &z) != 3)
//META_CONS("[MONSTER] ERROR: angle found twice: %s", input); {
LOG_MESSAGE(PLID, "ERROR: angle found twice: %s", input); LOG_MESSAGE(PLID, "ERROR: invalid angles: %s", input); // print conflictive line
return TRUE; // error
} // reset angles to g_vecZero
if (angle_min || angle_max) LOG_MESSAGE(PLID, "ERROR: entity angles will be set to 0 0 0");
{ x = y = z = 0;
//META_CONS("[MONSTER] ERROR: you can't specify angle AND angle_min or angle_max: %s", input); }
LOG_MESSAGE(PLID, "ERROR: you can't specify angle AND angle_min or angle_max: %s", input); monster_spawnpoint[monster_spawn_count].angles[0] = x;
return TRUE; // error monster_spawnpoint[monster_spawn_count].angles[1] = y;
} monster_spawnpoint[monster_spawn_count].angles[2] = z;
if (sscanf(&input[6], "%f", &x) != 1) }
{ else if (strcmp(data[i].key, "classname") == 0)
//META_CONS("[MONSTER] ERROR: invalid angle: %s", input); {
LOG_MESSAGE(PLID, "ERROR: invalid angle: %s", input); int mIndex;
return TRUE; // error for (mIndex = 0; monster_types[mIndex].name[0]; mIndex++)
} {
angle = TRUE; if (strcmp(data[i].value, monster_types[mIndex].name) == 0)
monster_spawnpoint[monster_spawn_count].angle_min = x; {
monster_spawnpoint[monster_spawn_count].angle_max = x; monster_spawnpoint[monster_spawn_count].monster = mIndex;
} monster_types[mIndex].need_to_precache = TRUE;
else if (strncmp(input, "angle_min/", 10) == 0) break;
{ }
if (angle_min) }
{ if (monster_types[mIndex].name[0] == 0)
//META_CONS("[MONSTER] ERROR: angle_min found twice: %s", input); {
LOG_MESSAGE(PLID, "ERROR: angle_min found twice: %s", input); LOG_MESSAGE(PLID, "ERROR: unknown classname: %s", input); // print conflictive line
return TRUE; // error LOG_MESSAGE(PLID, "ERROR: nothing will spawn here!");
} }
if (angle) }
{ }
//META_CONS("[MONSTER] ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
LOG_MESSAGE(PLID, "ERROR: you can't specify angle AND angle_min or angle_max: %s", input); // Init monster
return TRUE; // error monster_spawnpoint[monster_spawn_count].respawn_time = gpGlobals->time + 0.1; // spawn (nearly) right away
} monster_spawnpoint[monster_spawn_count].need_to_respawn = TRUE;
if (sscanf(&input[10], "%f", &x) != 1)
{ // Log on? Print all the entities that were added
//META_CONS("[MONSTER] ERROR: invalid angle_min: %s", input); if (dllapi_log->value)
LOG_MESSAGE(PLID, "ERROR: invalid angle_min: %s", input); {
return TRUE; // error // Classname only, or we will flood the server!
} // No, I'm not making this idiotproof. Classname should be the last KVD entry on an entity!
angle_min = TRUE; LOG_CONSOLE(PLID, "[DEBUG] Added entity: %s", data[kvd_index-1].value);
monster_spawnpoint[monster_spawn_count].angle_min = x; }
}
else if (strncmp(input, "angle_max/", 10) == 0) monster_spawn_count++;
{ free( data );
if (angle_max) break;
{ }
//META_CONS("[MONSTER] ERROR: angle_max found twice: %s", input);
LOG_MESSAGE(PLID, "ERROR: angle_max found twice: %s", input); // Bruteforce to remove quotes
return TRUE; // error char parse[66] = {0};
} int skip = 0;
if (angle) for (int i = 0; i < strlen(input); i++)
{ {
//META_CONS("[MONSTER] ERROR: you can't specify angle AND angle_min or angle_max: %s", input); if (input[i] == '"')
LOG_MESSAGE(PLID, "ERROR: you can't specify angle AND angle_min or angle_max: %s", input); {
return TRUE; // error skip++;
} continue;
if (sscanf(&input[10], "%f", &x) != 1) }
{ parse[i-skip] = input[i];
//META_CONS("[MONSTER] ERROR: invalid angle_max: %s", input); }
LOG_MESSAGE(PLID, "ERROR: invalid angle_max: %s", input); parse[strlen(parse)] = '\0';
return TRUE; // error
} // Copy all keyvalues to the tempvar
angle_max = TRUE; // Key
monster_spawnpoint[monster_spawn_count].angle_max = x; char *copy = strtok(parse, " ");
} strcpy(data[kvd_index].key, copy);
else if (strncmp(input, "monster/", 8) == 0)
{ // Value
int index; copy = strtok(NULL, " ");
int count = monster_spawnpoint[monster_spawn_count].monster_count; strcpy(data[kvd_index].value, "");
if (count < MAX_MONSTER_COUNT) while (copy != NULL)
{ {
for (index=0; monster_types[index].name[0]; index++) // If the value is a vector, append necessary whitespaces
{ strcat(data[kvd_index].value, copy);
if (strcmp(&input[8], monster_types[index].name) == 0) copy = strtok(NULL, " ");
{ if (copy != NULL)
monster_spawnpoint[monster_spawn_count].monster[count] = index; strcat(data[kvd_index].value, " ");
monster_spawnpoint[monster_spawn_count].monster_count++; }
monster_types[index].need_to_precache = TRUE; // Next KVD
break; kvd_index++;
} }
} }
if (monster_types[index].name[0] == 0) }
{
//META_CONS("[MONSTER] ERROR: invalid monster name: %s", input);
LOG_MESSAGE(PLID, "ERROR: invalid monster name: %s", input);
return TRUE;
}
}
monster = TRUE;
}
else
{
//META_CONS("[MONSTER] ERROR: unknown command: %s", input);
LOG_MESSAGE(PLID, "ERROR: unknown command: %s", input);
return TRUE; // error occurred
}
}
// check for all necessary fields here...
if (!origin)
{
//META_CONS("[MONSTER] ERROR: you didn't specify an origin!");
LOG_MESSAGE(PLID, "ERROR: you didn't specify an origin!");
return TRUE;
}
if (angle_min && !angle_max)
{
//META_CONS("[MONSTER] ERROR: you specified angle_min but didn't specify angle_max!");
LOG_MESSAGE(PLID, "ERROR: you specified angle_min but didn't specify angle_max!");
return TRUE;
}
if (angle_max && !angle_min)
{
//META_CONS("[MONSTER] ERROR: you specified angle_max but didn't specify angle_min!");
LOG_MESSAGE(PLID, "ERROR: you specified angle_max but didn't specify angle_min!");
return TRUE;
}
if (!monster)
{
//META_CONS("[MONSTER] ERROR: No monster key found!");
LOG_MESSAGE(PLID, "ERROR: No monster key found!");
return TRUE;
}
if (!delay)
monster_spawnpoint[monster_spawn_count].delay = 30; // 30 second default delay
if (monster_spawnpoint[monster_spawn_count].delay < 1)
monster_spawnpoint[monster_spawn_count].delay = 1; // no negative or zero delay
if (!angle && !angle_min && !angle_max) // no angle specified, use 0-359 as default
{
monster_spawnpoint[monster_spawn_count].angle_min = 0;
monster_spawnpoint[monster_spawn_count].angle_max = 359;
}
if (monster_spawnpoint[monster_spawn_count].angle_min < 0)
monster_spawnpoint[monster_spawn_count].angle_min = 0; // no negative angles
if (monster_spawnpoint[monster_spawn_count].angle_max > 359)
monster_spawnpoint[monster_spawn_count].angle_max = 359; // no angle > 359 degrees
monster_spawnpoint[monster_spawn_count].respawn_time = gpGlobals->time + RANDOM_FLOAT(10.0, 20.0);
monster_spawnpoint[monster_spawn_count].need_to_respawn = TRUE;
if (dllapi_log->value)
{
char name_monsters[256];
LOG_MESSAGE(PLID, "Added monster spawn at: %7.2f %7.2f %7.2f",
monster_spawnpoint[monster_spawn_count].origin.x,
monster_spawnpoint[monster_spawn_count].origin.y,
monster_spawnpoint[monster_spawn_count].origin.z);
LOG_MESSAGE(PLID, " with delay = %7.2f, angle_min = %7.2f, angle_max = %7.2f",
monster_spawnpoint[monster_spawn_count].delay,
monster_spawnpoint[monster_spawn_count].angle_min,
monster_spawnpoint[monster_spawn_count].angle_max);
name_monsters[0] = 0;
for (int i = 0; i < monster_spawnpoint[monster_spawn_count].monster_count; i++)
{
strcat(name_monsters, monster_types[monster_spawnpoint[monster_spawn_count].monster[i]].name);
strcat(name_monsters, " ");
}
LOG_MESSAGE(PLID, " monsters = %s", name_monsters);
}
monster_spawn_count++;
}
}
return FALSE;
} }
void process_monster_cfg(void)
bool process_monster_cfg(void)
{ {
char game_dir[256]; char game_dir[256];
char filename[256]; char filename[256];
FILE *fp = NULL; FILE *fp = NULL;
bool status = FALSE; // no error bool status = FALSE; // no error
monster_spawn_count = 0; monster_spawn_count = 0;
// find the directory name of the currently running MOD... // find the directory name of the currently running MOD...
(*g_engfuncs.pfnGetGameDir)(game_dir); (*g_engfuncs.pfnGetGameDir)(game_dir);
strcpy(filename, game_dir); strcpy(filename, game_dir);
#ifdef __linux__ #ifdef __linux__
strcat(filename, "/maps/"); strcat(filename, "/maps/");
#else #else
strcat(filename, "\\maps\\"); strcat(filename, "\\maps\\");
#endif #endif
strcat(filename, STRING(gpGlobals->mapname)); strcat(filename, STRING(gpGlobals->mapname));
strcat(filename, "_monster.cfg"); strcat(filename, "_monster.cfg");
// check if the map specific filename exists... // check if the map specific filename exists...
if (access(filename, 0) == 0) if (access(filename, 0) == 0)
{ {
if (dllapi_log->value) if (dllapi_log->value)
{ {
//META_CONS("[MONSTER] Processing config file=%s", filename); //META_CONS("[MONSTER] Processing config file=%s", filename);
LOG_MESSAGE(PLID, "Processing config file=%s", filename); LOG_MESSAGE(PLID, "Processing config file=%s", filename);
} }
if ((fp = fopen(filename, "r")) == NULL) if ((fp = fopen(filename, "r")) == NULL)
{ {
//META_CONS("[MONSTER] ERROR: Could not open \"%s\"!", filename); //META_CONS("[MONSTER] ERROR: Could not open \"%s\"!", filename);
LOG_MESSAGE(PLID, "ERROR: Could not open \"%s\" file!", filename); LOG_MESSAGE(PLID, "ERROR: Could not open \"%s\" file!", filename);
return TRUE; // return bad status return;
} }
status = scan_monster_cfg(fp); scan_monster_cfg(fp);
fclose(fp); fclose(fp);
} }
return status; return;
} }
bool scan_monster_precache_cfg(FILE *fp) bool scan_monster_precache_cfg(FILE *fp)
{ {
char input[1024]; char input[1024];
bool found; bool found;
while (get_input(fp, input)) while (get_input(fp, input))
{ {
found = FALSE; found = FALSE;
for (int index=0; monster_types[index].name[0]; index++) for (int index=0; monster_types[index].name[0]; index++)
{ {
if (strcmp(input, monster_types[index].name) == 0) if (strcmp(input, monster_types[index].name) == 0)
{ {
monster_types[index].need_to_precache = TRUE; monster_types[index].need_to_precache = TRUE;
found = TRUE; found = TRUE;
break; break;
} }
} }
if (found == FALSE) if (found == FALSE)
{ {
//META_CONS("[MONSTER] ERROR: invalid precache monster name: %s", input); //META_CONS("[MONSTER] ERROR: invalid precache monster name: %s", input);
LOG_MESSAGE(PLID, "ERROR: invalid precache monster name: %s", input); LOG_MESSAGE(PLID, "ERROR: invalid precache monster name: %s", input);
} }
} }
return FALSE; return FALSE;
} }
bool process_monster_precache_cfg(void) bool process_monster_precache_cfg(void)
{ {
char game_dir[256]; char game_dir[256];
char filename[256]; char filename[256];
FILE *fp = NULL; FILE *fp = NULL;
bool status = FALSE; // no error bool status = FALSE; // no error
// find the directory name of the currently running MOD... // find the directory name of the currently running MOD...
(*g_engfuncs.pfnGetGameDir)(game_dir); (*g_engfuncs.pfnGetGameDir)(game_dir);
strcpy(filename, game_dir); strcpy(filename, game_dir);
strcat(filename, "/monster_precache.cfg"); strcat(filename, "/monster_precache.cfg");
// check if the map specific filename exists... // check if the map specific filename exists...
if (access(filename, 0) == 0) if (access(filename, 0) == 0)
{ {
if (dllapi_log->value) if (dllapi_log->value)
{ {
//META_CONS("[MONSTER] Processing config file=%s", filename); //META_CONS("[MONSTER] Processing config file=%s", filename);
LOG_MESSAGE(PLID, "Processing config file=%s", filename); LOG_MESSAGE(PLID, "Processing config file=%s", filename);
} }
if ((fp = fopen(filename, "r")) == NULL) if ((fp = fopen(filename, "r")) == NULL)
{ {
//META_CONS("[MONSTER] ERROR: Could not open \"%s\"!", filename); //META_CONS("[MONSTER] ERROR: Could not open \"%s\"!", filename);
LOG_MESSAGE(PLID, "ERROR: Could not open \"%s\" file!", filename); LOG_MESSAGE(PLID, "ERROR: Could not open \"%s\" file!", filename);
return TRUE; // return bad status return TRUE; // return bad status
} }
status = scan_monster_precache_cfg(fp); status = scan_monster_precache_cfg(fp);
fclose(fp); fclose(fp);
} }
return status; return status;
} }

View File

@@ -28,15 +28,11 @@ typedef struct
extern monster_t monsters[MAX_MONSTER_ENTS]; extern monster_t monsters[MAX_MONSTER_ENTS];
#define MAX_MONSTER_COUNT 20
typedef struct { typedef struct {
Vector origin; Vector origin;
float angle_min, angle_max; Vector angles;
float delay; float delay;
unsigned char monster[MAX_MONSTER_COUNT]; unsigned char monster;
int monster_count;
float respawn_time; float respawn_time;
bool need_to_respawn; bool need_to_respawn;
} monster_spawnpoint_t; } monster_spawnpoint_t;