Read entities within the BSP itself.
NOT YET COMPLETE, HIGHLY UNSTABLE! Disabled by default, prone to crashing under Windows. Set CVar "monster_entity_config" to 0 (or 2) to enable reading from BSP.
This commit is contained in:
@@ -165,8 +165,6 @@ There are probably more issues that aren't listed here, I'll attempt to fix them
|
|||||||
Attempting to recreate everything in one go is a daunting task.
|
Attempting to recreate everything in one go is a daunting task.
|
||||||
Let it be known that the original 2002 source code will NOT compile on today's compilers, and does NOT contain all the necessary files for compilation. The preliminary was to rewrite and provide as many files or lines of code to ensure it can compile again, and be usable on an actual HLDS installation.
|
Let it be known that the original 2002 source code will NOT compile on today's compilers, and does NOT contain all the necessary files for compilation. The preliminary was to rewrite and provide as many files or lines of code to ensure it can compile again, and be usable on an actual HLDS installation.
|
||||||
|
|
||||||
The original Visual C++ 6.0 DSP file exists in the repository but neither the file nor the code has been updated to newer formats. Don't expect it to compile on modern Visual Studio versions.
|
|
||||||
|
|
||||||
Current milestones are separated by "Tiers", which are as follows:
|
Current milestones are separated by "Tiers", which are as follows:
|
||||||
|
|
||||||
### Tier 0
|
### Tier 0
|
||||||
@@ -206,6 +204,7 @@ Current milestones are separated by "Tiers", which are as follows:
|
|||||||
- Add configurations to change AI behaviour.
|
- Add configurations to change AI behaviour.
|
||||||
- Optimize code and enhance the AI.
|
- Optimize code and enhance the AI.
|
||||||
- Create "tool" entities for easier map customization.
|
- Create "tool" entities for easier map customization.
|
||||||
|
- Do more fixes not covered in Tier 4.
|
||||||
|
|
||||||
|
|
||||||
What will the future hold after all Tiers has been completed?
|
What will the future hold after all Tiers has been completed?
|
||||||
|
|||||||
@@ -724,6 +724,9 @@ edict_t* spawn_monster(int monster_type, Vector origin, Vector angles, int spawn
|
|||||||
monster_pent->v.origin = origin;
|
monster_pent->v.origin = origin;
|
||||||
monster_pent->v.angles = angles;
|
monster_pent->v.angles = angles;
|
||||||
|
|
||||||
|
// Pass spawnflags first if no keyvalue data exists for it
|
||||||
|
monster_pent->v.spawnflags = spawnflags;
|
||||||
|
|
||||||
// Keyvalue data
|
// Keyvalue data
|
||||||
if (keyvalue != NULL)
|
if (keyvalue != NULL)
|
||||||
{
|
{
|
||||||
@@ -738,8 +741,6 @@ edict_t* spawn_monster(int monster_type, Vector origin, Vector angles, int spawn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
monster_pent->v.spawnflags = spawnflags;
|
|
||||||
|
|
||||||
monsters[monster_index].pMonster->Spawn();
|
monsters[monster_index].pMonster->Spawn();
|
||||||
|
|
||||||
// Only modify starting spawnflags for monsters, not for entities!
|
// Only modify starting spawnflags for monsters, not for entities!
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ cvar_t init_monster_show_info = {"monster_show_info", "1", FCVAR_EXTDLL, 0, NULL
|
|||||||
cvar_t *monster_show_info = NULL;
|
cvar_t *monster_show_info = NULL;
|
||||||
cvar_t init_monster_turn_coeficient = {"monster_turn_coeficient", "1.75", FCVAR_EXTDLL, 0, NULL};
|
cvar_t init_monster_turn_coeficient = {"monster_turn_coeficient", "1.75", FCVAR_EXTDLL, 0, NULL};
|
||||||
cvar_t *monster_turn_coeficient = NULL;
|
cvar_t *monster_turn_coeficient = NULL;
|
||||||
|
cvar_t init_monster_entity_config = {"monster_entity_config", "1", FCVAR_EXTDLL, 0, NULL};
|
||||||
|
cvar_t *monster_entity_config = NULL;
|
||||||
|
|
||||||
|
|
||||||
// Metamod requesting info about this plugin:
|
// Metamod requesting info about this plugin:
|
||||||
@@ -151,6 +153,9 @@ C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, m
|
|||||||
CVAR_REGISTER(&init_monster_turn_coeficient);
|
CVAR_REGISTER(&init_monster_turn_coeficient);
|
||||||
monster_turn_coeficient = CVAR_GET_POINTER("monster_turn_coeficient");
|
monster_turn_coeficient = CVAR_GET_POINTER("monster_turn_coeficient");
|
||||||
|
|
||||||
|
CVAR_REGISTER(&init_monster_entity_config);
|
||||||
|
monster_entity_config = CVAR_GET_POINTER("monster_entity_config");
|
||||||
|
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include "ripent.h"
|
#include "ripent.h"
|
||||||
|
|
||||||
extern cvar_t *dllapi_log;
|
extern cvar_t *dllapi_log;
|
||||||
|
extern cvar_t *monster_entity_config;
|
||||||
|
|
||||||
extern monster_type_t monster_types[];
|
extern monster_type_t monster_types[];
|
||||||
extern int monster_spawn_count;
|
extern int monster_spawn_count;
|
||||||
@@ -403,6 +404,314 @@ void scan_monster_cfg(FILE *fp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scan_monster_bsp(void)
|
||||||
|
{
|
||||||
|
// TODO: code duplication galore! optimize this for T5 milestone. -Giegue
|
||||||
|
epair_t *kv_pair;
|
||||||
|
pKVD data[MAX_KEYVALUES];
|
||||||
|
|
||||||
|
int kvd_index;
|
||||||
|
int duplicate_ent;
|
||||||
|
bool use_monstermod;
|
||||||
|
|
||||||
|
int classname_kvdI, mIndex;
|
||||||
|
float x, y, z;
|
||||||
|
bool badent, monster, node;
|
||||||
|
|
||||||
|
// go through all entities
|
||||||
|
for (int ent = 1; ent < num_entities; ent++)
|
||||||
|
{
|
||||||
|
kv_pair = entities[ent].epairs;
|
||||||
|
|
||||||
|
kvd_index = 0;
|
||||||
|
duplicate_ent = 0;
|
||||||
|
use_monstermod = true;
|
||||||
|
|
||||||
|
classname_kvdI = 0;
|
||||||
|
badent = monster = node = false;
|
||||||
|
|
||||||
|
// examine all keys
|
||||||
|
while (kv_pair != NULL)
|
||||||
|
{
|
||||||
|
if (strcmp(kv_pair->key, "classname") == 0)
|
||||||
|
{
|
||||||
|
// the entity we are trying to spawn could already exist within the game
|
||||||
|
// use the engine's CREATE_NAMED_ENTITY to see if it's valid or not
|
||||||
|
//
|
||||||
|
// if it is valid, this entity already exists and we should ignore it
|
||||||
|
edict_t *existsGAME = CREATE_NAMED_ENTITY( MAKE_STRING( kv_pair->value ) );
|
||||||
|
if ( !FNullEnt( existsGAME ) )
|
||||||
|
{
|
||||||
|
for (mIndex = 0; monster_types[mIndex].name[0]; mIndex++)
|
||||||
|
{
|
||||||
|
if (strcmp(kv_pair->value, monster_types[mIndex].name) == 0)
|
||||||
|
{
|
||||||
|
// the entity exists BOTH in the game and monstermod!
|
||||||
|
// keep track of it
|
||||||
|
duplicate_ent = ent;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UTIL_Remove( existsGAME ); // get rid of the temporary entity
|
||||||
|
use_monstermod = false; // use game entity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (duplicate_ent && strcmp(kv_pair->key, "use_monstermod") == 0)
|
||||||
|
{
|
||||||
|
if (atoi(kv_pair->value) == 1)
|
||||||
|
{
|
||||||
|
// EXPLICITY requested to use the monstermod entity
|
||||||
|
use_monstermod = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(data[kvd_index].key, kv_pair->key);
|
||||||
|
strcpy(data[kvd_index].value, kv_pair->value);
|
||||||
|
|
||||||
|
kvd_index++;
|
||||||
|
kv_pair = kv_pair->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// spawn a monstermod entity?
|
||||||
|
if (use_monstermod)
|
||||||
|
{
|
||||||
|
// find classname keyvalue
|
||||||
|
for (int i = 0; i < kvd_index; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(data[i].key, "classname") == 0)
|
||||||
|
{
|
||||||
|
for (mIndex = 0; monster_types[mIndex].name[0]; mIndex++)
|
||||||
|
{
|
||||||
|
if (strcmp(data[i].value, monster_types[mIndex].name) == 0)
|
||||||
|
{
|
||||||
|
// Match found, check if it's a node
|
||||||
|
if (strcmp(monster_types[mIndex].name, "info_node") == 0)
|
||||||
|
{
|
||||||
|
// Normal node
|
||||||
|
if (node_spawn_count == MAX_NODES)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "ERROR: can't add node, reached MAX_NODES!");
|
||||||
|
badent = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
node = true;
|
||||||
|
}
|
||||||
|
else if (strcmp(monster_types[mIndex].name, "info_node_air") == 0)
|
||||||
|
{
|
||||||
|
// Aerial node
|
||||||
|
if (node_spawn_count == MAX_NODES)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "ERROR: can't add node, reached MAX_NODES!");
|
||||||
|
badent = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node_spawnpoint[node_spawn_count].is_air_node = true;
|
||||||
|
node = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Assume it's a monster and add it to the list
|
||||||
|
// (Extra entities are built as CMBaseMonster)
|
||||||
|
if (monster_spawn_count == MAX_MONSTERS)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "ERROR: can't add entity, reached MAX_MONSTERS!");
|
||||||
|
badent = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
monster_spawnpoint[monster_spawn_count].monster = mIndex;
|
||||||
|
monster_types[mIndex].need_to_precache = true;
|
||||||
|
monster = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
classname_kvdI = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (monster_types[mIndex].name[0] == 0)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "unknown classname: %s", data[i].value);
|
||||||
|
badent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!badent)
|
||||||
|
{
|
||||||
|
// Make room for entity-specific keyvalues.
|
||||||
|
if (monster)
|
||||||
|
{
|
||||||
|
// Can I use malloc/calloc again or you are going to crash cuz you feel like it? >.>
|
||||||
|
monster_spawnpoint[monster_spawn_count].keyvalue = (pKVD*)calloc(MAX_KEYVALUES, sizeof(*monster_spawnpoint[monster_spawn_count].keyvalue));
|
||||||
|
}
|
||||||
|
|
||||||
|
// process entity keyvalues
|
||||||
|
for (int i = 0; i < kvd_index; i++)
|
||||||
|
{
|
||||||
|
// duplicates are overwritten
|
||||||
|
if (strcmp(data[i].key, "origin") == 0)
|
||||||
|
{
|
||||||
|
if (sscanf(data[i].value, "%f %f %f", &x, &y, &z) != 3)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "ERROR: invalid origin: %s", data[i].value); // print conflictive line
|
||||||
|
|
||||||
|
// reset origin to g_vecZero
|
||||||
|
LOG_MESSAGE(PLID, "ERROR: entity will spawn at 0 0 0");
|
||||||
|
x = y = z = 0;
|
||||||
|
}
|
||||||
|
if (monster)
|
||||||
|
{
|
||||||
|
monster_spawnpoint[monster_spawn_count].origin[0] = x;
|
||||||
|
monster_spawnpoint[monster_spawn_count].origin[1] = y;
|
||||||
|
monster_spawnpoint[monster_spawn_count].origin[2] = z;
|
||||||
|
}
|
||||||
|
else if (node)
|
||||||
|
{
|
||||||
|
node_spawnpoint[node_spawn_count].origin[0] = x;
|
||||||
|
node_spawnpoint[node_spawn_count].origin[1] = y;
|
||||||
|
node_spawnpoint[node_spawn_count].origin[2] = z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(data[i].key, "angles") == 0)
|
||||||
|
{
|
||||||
|
if (monster)
|
||||||
|
{
|
||||||
|
if (sscanf(data[i].value, "%f %f %f", &x, &y, &z) != 3)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "ERROR: invalid angles: %s", data[i].value); // print conflictive line
|
||||||
|
|
||||||
|
// reset angles to g_vecZero
|
||||||
|
LOG_MESSAGE(PLID, "ERROR: entity angles will be set to 0 0 0");
|
||||||
|
x = y = z = 0;
|
||||||
|
}
|
||||||
|
monster_spawnpoint[monster_spawn_count].angles[0] = x;
|
||||||
|
monster_spawnpoint[monster_spawn_count].angles[1] = y;
|
||||||
|
monster_spawnpoint[monster_spawn_count].angles[2] = z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(data[i].key, "spawnflags") == 0)
|
||||||
|
{
|
||||||
|
if (monster)
|
||||||
|
{
|
||||||
|
if (sscanf(data[i].value, "%f", &x) != 1)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "ERROR: invalid spawnflags: %s", data[i].value); // print conflictive line
|
||||||
|
|
||||||
|
// default to no spawnflags
|
||||||
|
LOG_MESSAGE(PLID, "ERROR: entity spawnflags will be set to none (0)");
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
monster_spawnpoint[monster_spawn_count].spawnflags = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(data[i].key, "model") == 0)
|
||||||
|
{
|
||||||
|
if (monster)
|
||||||
|
{
|
||||||
|
// only applicable for normal monsters
|
||||||
|
if (strcmp(data[classname_kvdI].value, "monstermaker") != 0)
|
||||||
|
{
|
||||||
|
// precache the custom model here
|
||||||
|
PRECACHE_MODEL( data[i].value );
|
||||||
|
|
||||||
|
// the entity will need the keyvalue
|
||||||
|
strcpy(monster_spawnpoint[monster_spawn_count].keyvalue[i].key, data[i].key);
|
||||||
|
strcpy(monster_spawnpoint[monster_spawn_count].keyvalue[i].value, data[i].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(data[i].key, "new_model") == 0)
|
||||||
|
{
|
||||||
|
if (monster)
|
||||||
|
{
|
||||||
|
// only applicable for monstermaker entity
|
||||||
|
if (strcmp(data[classname_kvdI].value, "monstermaker") == 0)
|
||||||
|
{
|
||||||
|
// precache the custom model
|
||||||
|
PRECACHE_MODEL( data[i].value );
|
||||||
|
|
||||||
|
// the entity will need the keyvalue as well
|
||||||
|
strcpy(monster_spawnpoint[monster_spawn_count].keyvalue[i].key, data[i].key);
|
||||||
|
strcpy(monster_spawnpoint[monster_spawn_count].keyvalue[i].value, data[i].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(data[i].key, "monstertype") == 0)
|
||||||
|
{
|
||||||
|
if (monster)
|
||||||
|
{
|
||||||
|
// this keyvalue is only valid for monstermaker entity
|
||||||
|
if (strcmp(data[classname_kvdI].value, "monstermaker") == 0)
|
||||||
|
{
|
||||||
|
// process the entity precache here
|
||||||
|
for (mIndex = 0; monster_types[mIndex].name[0]; mIndex++)
|
||||||
|
{
|
||||||
|
if (strcmp(data[i].value, monster_types[mIndex].name) == 0)
|
||||||
|
{
|
||||||
|
monster_types[mIndex].need_to_precache = TRUE;
|
||||||
|
break; // only one monster at a time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pass the keyvalue to the entity
|
||||||
|
strcpy(monster_spawnpoint[monster_spawn_count].keyvalue[i].key, data[i].key);
|
||||||
|
strcpy(monster_spawnpoint[monster_spawn_count].keyvalue[i].value, data[i].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strcmp(data[i].key, "message") == 0)
|
||||||
|
{
|
||||||
|
if (monster)
|
||||||
|
{
|
||||||
|
// only applicable for ambient_music
|
||||||
|
if (strcmp(data[classname_kvdI].value, "ambient_music") == 0)
|
||||||
|
{
|
||||||
|
// precache the sound here
|
||||||
|
PRECACHE_GENERIC(data[i].value);
|
||||||
|
|
||||||
|
// the entity will need the keyvalue
|
||||||
|
strcpy(monster_spawnpoint[monster_spawn_count].keyvalue[i].key, data[i].key);
|
||||||
|
strcpy(monster_spawnpoint[monster_spawn_count].keyvalue[i].value, data[i].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We do not know this keyvalue, but an specific entity might use it.
|
||||||
|
// Save it for later
|
||||||
|
if (monster)
|
||||||
|
{
|
||||||
|
strcpy(monster_spawnpoint[monster_spawn_count].keyvalue[i].key, data[i].key);
|
||||||
|
strcpy(monster_spawnpoint[monster_spawn_count].keyvalue[i].value, data[i].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (monster)
|
||||||
|
{
|
||||||
|
// Spawn right away
|
||||||
|
monster_spawnpoint[monster_spawn_count].need_to_respawn = TRUE;
|
||||||
|
monster_spawn_count++;
|
||||||
|
}
|
||||||
|
else if (node)
|
||||||
|
{
|
||||||
|
// Increase node count
|
||||||
|
node_spawn_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log on? Print all the entities that were added
|
||||||
|
if (dllapi_log->value)
|
||||||
|
{
|
||||||
|
// Classname only, or we will flood the server!
|
||||||
|
LOG_CONSOLE(PLID, "[DEBUG] Added entity: %s", data[classname_kvdI].value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool process_monster_cfg(void)
|
bool process_monster_cfg(void)
|
||||||
{
|
{
|
||||||
char game_dir[256];
|
char game_dir[256];
|
||||||
@@ -428,29 +737,46 @@ bool process_monster_cfg(void)
|
|||||||
strcat(BSPfilename, ".bsp");
|
strcat(BSPfilename, ".bsp");
|
||||||
strcat(CFGfilename, "_monster.cfg");
|
strcat(CFGfilename, "_monster.cfg");
|
||||||
|
|
||||||
LoadBSPFile(BSPfilename);
|
// process config files?
|
||||||
ParseEntities();
|
// -1 = don't process monster config, dynamic spawns only
|
||||||
LOG_MESSAGE(PLID, "It works! LoadBSPFile: Parsed '%i' entities", num_entities);
|
// 0 = read entities from BSP file
|
||||||
|
// 1 = read entities from CFG file
|
||||||
// check if the map specific filename exists...
|
// 2 = read entities from both, BSP first, then CFG file
|
||||||
if (access(CFGfilename, 0) == 0)
|
if (monster_entity_config->value >= 0)
|
||||||
{
|
{
|
||||||
if (dllapi_log->value)
|
// read from bsp? (mode 0 or 2)
|
||||||
|
if (monster_entity_config->value != 1)
|
||||||
{
|
{
|
||||||
//META_CONS("[MONSTER] Processing config file=%s", filename);
|
LoadBSPFile(BSPfilename);
|
||||||
LOG_MESSAGE(PLID, "Processing config file '%s'", CFGfilename);
|
ParseEntities();
|
||||||
|
|
||||||
|
scan_monster_bsp();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fp = fopen(CFGfilename, "r")) == NULL)
|
// read from cfg? (mode 1 or 2)
|
||||||
|
if (monster_entity_config->value > 0)
|
||||||
{
|
{
|
||||||
//META_CONS("[MONSTER] ERROR: Could not open \"%s\"!", filename);
|
// check if the map specific filename exists...
|
||||||
LOG_MESSAGE(PLID, "ERROR: Could not open \"%s\" file!", CFGfilename);
|
if (access(CFGfilename, 0) == 0)
|
||||||
return TRUE; // error
|
{
|
||||||
|
if (dllapi_log->value)
|
||||||
|
{
|
||||||
|
//META_CONS("[MONSTER] Processing config file=%s", filename);
|
||||||
|
LOG_MESSAGE(PLID, "Processing config file '%s'", CFGfilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fp = fopen(CFGfilename, "r")) == NULL)
|
||||||
|
{
|
||||||
|
//META_CONS("[MONSTER] ERROR: Could not open \"%s\"!", filename);
|
||||||
|
LOG_MESSAGE(PLID, "ERROR: Could not open \"%s\" file!", CFGfilename);
|
||||||
|
return TRUE; // error
|
||||||
|
}
|
||||||
|
|
||||||
|
scan_monster_cfg(fp);
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scan_monster_cfg(fp);
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE; // all ok
|
return FALSE; // all ok
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
int entdatasize;
|
int entdatasize;
|
||||||
char dentdata[MAX_MAP_ENTSTRING];
|
char dentdata[MAX_MAP_ENTSTRING];
|
||||||
int dentdata_checksum;
|
|
||||||
|
|
||||||
int num_entities;
|
int num_entities;
|
||||||
entity_t entities[MAX_MAP_ENTITIES];
|
entity_t entities[MAX_MAP_ENTITIES];
|
||||||
@@ -57,7 +56,13 @@ LoadBSPFile
|
|||||||
*/
|
*/
|
||||||
void LoadBSPFile(char *filename)
|
void LoadBSPFile(char *filename)
|
||||||
{
|
{
|
||||||
int i;
|
//int i;
|
||||||
|
|
||||||
|
// reset these values
|
||||||
|
entdatasize = 0;
|
||||||
|
num_entities = 0;
|
||||||
|
memset(dentdata, 0, sizeof(dentdata));
|
||||||
|
memset(entities, 0, sizeof(entities));
|
||||||
|
|
||||||
//
|
//
|
||||||
// load the file header
|
// load the file header
|
||||||
|
|||||||
Reference in New Issue
Block a user