Print number of entities found in BSP file.
Add 'ambient_music' entity.
This commit is contained in:
@@ -38,9 +38,11 @@ OBJ = \
|
|||||||
monstermaker.o \
|
monstermaker.o \
|
||||||
monsters.o \
|
monsters.o \
|
||||||
monsterstate.o \
|
monsterstate.o \
|
||||||
|
music.o \
|
||||||
nodes.o \
|
nodes.o \
|
||||||
otis.o \
|
otis.o \
|
||||||
pitdrone.o \
|
pitdrone.o \
|
||||||
|
ripent.o \
|
||||||
rgrunt.o \
|
rgrunt.o \
|
||||||
scientist.o \
|
scientist.o \
|
||||||
shock.o \
|
shock.o \
|
||||||
|
|||||||
@@ -33,4 +33,18 @@ public:
|
|||||||
BOOL m_fFadeChildren;// should we make the children fadeout?
|
BOOL m_fFadeChildren;// should we make the children fadeout?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//=========================================================
|
||||||
|
// Ambient Music - Plays an mp3 music file to players.
|
||||||
|
//=========================================================
|
||||||
|
class CMAmbientMusic : public CMBaseMonster
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Spawn(void);
|
||||||
|
//void Precache(void); // accessed before entvars are valid, manual precache in monster_config.cpp
|
||||||
|
void KeyValue(KeyValueData* pkvd);
|
||||||
|
void EXPORT MusicUse(edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value);
|
||||||
|
|
||||||
|
BOOL m_fPlaying; // music is active
|
||||||
|
};
|
||||||
|
|
||||||
#endif // BASEEXTRA_H
|
#endif // BASEEXTRA_H
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ monster_type_t monster_types[]=
|
|||||||
"info_node", FALSE, // Nodes
|
"info_node", FALSE, // Nodes
|
||||||
"info_node_air", FALSE,
|
"info_node_air", FALSE,
|
||||||
"monstermaker", FALSE, // Extra entities
|
"monstermaker", FALSE, // Extra entities
|
||||||
|
"ambient_music", FALSE,
|
||||||
"", FALSE
|
"", FALSE
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -705,6 +706,7 @@ edict_t* spawn_monster(int monster_type, Vector origin, Vector angles, int spawn
|
|||||||
case 29: monsters[monster_index].pMonster = CreateClassPtr((CMStukabat *)NULL); break;
|
case 29: monsters[monster_index].pMonster = CreateClassPtr((CMStukabat *)NULL); break;
|
||||||
// Extra entities
|
// Extra entities
|
||||||
case 32: monsters[monster_index].pMonster = CreateClassPtr((CMMonsterMaker *)NULL); break;
|
case 32: monsters[monster_index].pMonster = CreateClassPtr((CMMonsterMaker *)NULL); break;
|
||||||
|
case 33: monsters[monster_index].pMonster = CreateClassPtr((CMAmbientMusic *)NULL); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (monsters[monster_index].pMonster == NULL)
|
if (monsters[monster_index].pMonster == NULL)
|
||||||
@@ -786,7 +788,7 @@ void check_respawn(void)
|
|||||||
if (spawn_monster(monster_type, origin, angles, spawnflags, keyvalue) == NULL)
|
if (spawn_monster(monster_type, origin, angles, spawnflags, keyvalue) == NULL)
|
||||||
{
|
{
|
||||||
// spawn_monster failed
|
// spawn_monster failed
|
||||||
ALERT( at_error, "Failed to spawn %s at origin %f %f %f\n", monster_types[monster_type].name, origin.x, origin.y, origin.z );
|
ALERT( at_error, "[MONSTER] Failed to spawn %s at origin %f %f %f\n", monster_types[monster_type].name, origin.x, origin.y, origin.z );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1416,6 +1418,7 @@ void mmServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
|
|||||||
|
|
||||||
// Extra entities
|
// Extra entities
|
||||||
CMMonsterMaker monstermaker; // 32
|
CMMonsterMaker monstermaker; // 32
|
||||||
|
CMAmbientMusic ambientmusic;
|
||||||
|
|
||||||
g_psv_gravity = CVAR_GET_POINTER( "sv_gravity" );
|
g_psv_gravity = CVAR_GET_POINTER( "sv_gravity" );
|
||||||
|
|
||||||
@@ -1465,6 +1468,7 @@ void mmServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
|
|||||||
case 28: rgrunt.Precache(); break;
|
case 28: rgrunt.Precache(); break;
|
||||||
case 29: stukabat.Precache(); break;
|
case 29: stukabat.Precache(); break;
|
||||||
case 32: monstermaker.Precache(); break;
|
case 32: monstermaker.Precache(); break;
|
||||||
|
//case 33: ambientmusic.Precache(); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "meta_api.h"
|
#include "meta_api.h"
|
||||||
|
|
||||||
#include "monster_plugin.h"
|
#include "monster_plugin.h"
|
||||||
|
#include "ripent.h"
|
||||||
|
|
||||||
extern cvar_t *dllapi_log;
|
extern cvar_t *dllapi_log;
|
||||||
|
|
||||||
@@ -126,6 +127,21 @@ void scan_monster_cfg(FILE *fp)
|
|||||||
monster = TRUE;
|
monster = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (strcmp(monster_types[mIndex].name, "ambient_music") == 0)
|
||||||
|
{
|
||||||
|
// TODO - Extra entities should go towards a separate counter like nodes
|
||||||
|
if (monster_spawn_count == MAX_MONSTERS)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "ERROR: can't add ambient_music, reached MAX_MONSTERS!");
|
||||||
|
badent = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
monster_spawnpoint[monster_spawn_count].monster = mIndex;
|
||||||
|
monster_types[mIndex].need_to_precache = TRUE;
|
||||||
|
monster = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (strcmp(monster_types[mIndex].name, "info_node") == 0)
|
else if (strcmp(monster_types[mIndex].name, "info_node") == 0)
|
||||||
{
|
{
|
||||||
// Normal node
|
// Normal node
|
||||||
@@ -260,7 +276,7 @@ void scan_monster_cfg(FILE *fp)
|
|||||||
{
|
{
|
||||||
if (monster)
|
if (monster)
|
||||||
{
|
{
|
||||||
// only applicable for monstermaket entity
|
// only applicable for monstermaker entity
|
||||||
if (strcmp(data[kvd_index-1].value, "monstermaker") == 0)
|
if (strcmp(data[kvd_index-1].value, "monstermaker") == 0)
|
||||||
{
|
{
|
||||||
// precache the custom model
|
// precache the custom model
|
||||||
@@ -296,6 +312,22 @@ void scan_monster_cfg(FILE *fp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (strcmp(data[i].key, "message") == 0)
|
||||||
|
{
|
||||||
|
if (monster)
|
||||||
|
{
|
||||||
|
// only applicable for ambient_music
|
||||||
|
if (strcmp(data[kvd_index - 1].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
|
else
|
||||||
{
|
{
|
||||||
// We do not know this keyvalue, but an specific entity might use it.
|
// We do not know this keyvalue, but an specific entity might use it.
|
||||||
@@ -374,36 +406,45 @@ void scan_monster_cfg(FILE *fp)
|
|||||||
bool process_monster_cfg(void)
|
bool process_monster_cfg(void)
|
||||||
{
|
{
|
||||||
char game_dir[256];
|
char game_dir[256];
|
||||||
char filename[256];
|
char BSPfilename[256];
|
||||||
|
char CFGfilename[256];
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
|
|
||||||
monster_spawn_count = 0;
|
monster_spawn_count = 0;
|
||||||
|
node_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(CFGfilename, game_dir);
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
strcat(filename, "/maps/");
|
strcat(CFGfilename, "/maps/");
|
||||||
#else
|
#else
|
||||||
strcat(filename, "\\maps\\");
|
strcat(CFGfilename, "\\maps\\");
|
||||||
#endif
|
#endif
|
||||||
strcat(filename, STRING(gpGlobals->mapname));
|
strcat(CFGfilename, STRING(gpGlobals->mapname));
|
||||||
strcat(filename, "_monster.cfg");
|
strcpy(BSPfilename, CFGfilename);
|
||||||
|
|
||||||
|
strcat(BSPfilename, ".bsp");
|
||||||
|
strcat(CFGfilename, "_monster.cfg");
|
||||||
|
|
||||||
|
LoadBSPFile(BSPfilename);
|
||||||
|
ParseEntities();
|
||||||
|
LOG_MESSAGE(PLID, "It works! LoadBSPFile: Parsed '%i' entities", num_entities);
|
||||||
|
|
||||||
// check if the map specific filename exists...
|
// check if the map specific filename exists...
|
||||||
if (access(filename, 0) == 0)
|
if (access(CFGfilename, 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'", CFGfilename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fp = fopen(filename, "r")) == NULL)
|
if ((fp = fopen(CFGfilename, "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!", CFGfilename);
|
||||||
return TRUE; // error
|
return TRUE; // error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
61
src/dlls/music.cpp
Normal file
61
src/dlls/music.cpp
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
//=========================================================
|
||||||
|
// Ambient Music - when triggered, it will play an mp3
|
||||||
|
// music file locally to players, looped or once.
|
||||||
|
//=========================================================
|
||||||
|
#include "extdll.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "cmbase.h"
|
||||||
|
#include "cmbasemonster.h"
|
||||||
|
#include "cmbaseextra.h"
|
||||||
|
|
||||||
|
// spawnflags
|
||||||
|
#define SF_MUSIC_LOOP 2 // music will loop instead of playing once.
|
||||||
|
#define SF_MUSIC_ACTIVATOR_ONLY 4 // only play to the one that activates this entity.
|
||||||
|
|
||||||
|
void CMAmbientMusic::KeyValue(KeyValueData *pkvd)
|
||||||
|
{
|
||||||
|
CMBaseMonster::KeyValue(pkvd);
|
||||||
|
}
|
||||||
|
void CMAmbientMusic::Spawn()
|
||||||
|
{
|
||||||
|
pev->solid = SOLID_NOT;
|
||||||
|
SetUse(&CMAmbientMusic::MusicUse);
|
||||||
|
pev->classname = MAKE_STRING("ambient_music");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMAmbientMusic::MusicUse(edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value)
|
||||||
|
{
|
||||||
|
// no music
|
||||||
|
if (FStringNull(pev->message))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// not a player (if not to everyone)
|
||||||
|
if (pev->spawnflags & SF_MUSIC_ACTIVATOR_ONLY && !UTIL_IsPlayer(pActivator))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (pev->spawnflags & SF_MUSIC_ACTIVATOR_ONLY)
|
||||||
|
MESSAGE_BEGIN(MSG_ALL, SVC_STUFFTEXT);
|
||||||
|
else
|
||||||
|
MESSAGE_BEGIN(MSG_ONE, SVC_STUFFTEXT, NULL, pActivator);
|
||||||
|
|
||||||
|
// triggering off
|
||||||
|
if (useType == USE_OFF || m_fPlaying && useType != USE_ON)
|
||||||
|
{
|
||||||
|
WRITE_STRING("mp3 stop\n");
|
||||||
|
m_fPlaying = FALSE;
|
||||||
|
}
|
||||||
|
else // USE_ON / USE_TOGGLE
|
||||||
|
{
|
||||||
|
char szPath[256];
|
||||||
|
|
||||||
|
if (pev->spawnflags & SF_MUSIC_LOOP)
|
||||||
|
sprintf(szPath, "mp3 loop %s\n", STRING(pev->message));
|
||||||
|
else
|
||||||
|
sprintf(szPath, "mp3 play %s\n", STRING(pev->message));
|
||||||
|
|
||||||
|
WRITE_STRING(szPath);
|
||||||
|
m_fPlaying = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
MESSAGE_END();
|
||||||
|
}
|
||||||
444
src/dlls/ripent.cpp
Normal file
444
src/dlls/ripent.cpp
Normal file
@@ -0,0 +1,444 @@
|
|||||||
|
/***
|
||||||
|
*
|
||||||
|
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||||
|
*
|
||||||
|
* This product contains software technology licensed from Id
|
||||||
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
****/
|
||||||
|
|
||||||
|
// this is a stripped down "bspfile.c" file containing only entity data similar
|
||||||
|
// to using a ripent tool to read ents from a bsp, hence the name.
|
||||||
|
// -Giegue
|
||||||
|
#include "extdll.h"
|
||||||
|
#include "ripent.h"
|
||||||
|
#include "meta_api.h"
|
||||||
|
|
||||||
|
#if defined linux
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
int entdatasize;
|
||||||
|
char dentdata[MAX_MAP_ENTSTRING];
|
||||||
|
int dentdata_checksum;
|
||||||
|
|
||||||
|
int num_entities;
|
||||||
|
entity_t entities[MAX_MAP_ENTITIES];
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
dheader_t *header;
|
||||||
|
|
||||||
|
int CopyLump(int lump, void *dest, int size)
|
||||||
|
{
|
||||||
|
int length, ofs;
|
||||||
|
|
||||||
|
length = header->lumps[lump].filelen;
|
||||||
|
ofs = header->lumps[lump].fileofs;
|
||||||
|
|
||||||
|
if (length % size)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "LoadBSPFile: odd lump size");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(dest, (byte *)header + ofs, length);
|
||||||
|
|
||||||
|
return length / size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============
|
||||||
|
LoadBSPFile
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
void LoadBSPFile(char *filename)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
//
|
||||||
|
// load the file header
|
||||||
|
//
|
||||||
|
if (LoadFile(filename, (void **)&header) == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// UNDONE: there is no need to swap it...? -Giegue
|
||||||
|
// swap the header
|
||||||
|
/*for (i = 0; i < sizeof(dheader_t) / 4; i++)
|
||||||
|
((int *)header)[i] = LittleLong(((int *)header)[i]);*/
|
||||||
|
|
||||||
|
// game will not load the BSP if it's invalid.
|
||||||
|
// so if this is called, it means something went really wrong loading it
|
||||||
|
if (header->version != BSPVERSION)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "%s is version %i, not %i", filename, header->version, BSPVERSION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
entdatasize = CopyLump(LUMP_ENTITIES, dentdata, 1);
|
||||||
|
|
||||||
|
free(header); // everything has been copied out
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
ParseEpair
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
epair_t *ParseEpair(void)
|
||||||
|
{
|
||||||
|
epair_t *e;
|
||||||
|
|
||||||
|
e = (epair_t*)malloc(sizeof(epair_t));
|
||||||
|
memset(e, 0, sizeof(epair_t));
|
||||||
|
|
||||||
|
if (strlen(token) >= MAX_KEY - 1)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "ParseEpar: token too long [strlen(token) >= MAX_KEY - 1]");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
e->key = copystring(token);
|
||||||
|
GetToken(false);
|
||||||
|
if (strlen(token) >= MAX_VALUE - 1)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "ParseEpar: token too long [strlen(token) >= MAX_VALUE - 1]");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
e->value = copystring(token);
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
ParseEntity
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
bool ParseEntity(void)
|
||||||
|
{
|
||||||
|
epair_t *e;
|
||||||
|
entity_t *mapent;
|
||||||
|
|
||||||
|
if (!GetToken(true))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (strcmp(token, "{"))
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "ParseEntity: { not found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num_entities == MAX_MAP_ENTITIES)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "num_entities == MAX_MAP_ENTITIES");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapent = &entities[num_entities];
|
||||||
|
num_entities++;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!GetToken(true))
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "ParseEntity: EOF without closing brace");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!strcmp(token, "}"))
|
||||||
|
break;
|
||||||
|
e = ParseEpair();
|
||||||
|
e->next = mapent->epairs;
|
||||||
|
mapent->epairs = e;
|
||||||
|
} while (1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
ParseEntities
|
||||||
|
|
||||||
|
Parses the dentdata string into entities
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
void ParseEntities(void)
|
||||||
|
{
|
||||||
|
num_entities = 0;
|
||||||
|
ParseFromMemory(dentdata, entdatasize);
|
||||||
|
|
||||||
|
while (ParseEntity())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --
|
||||||
|
/* MERGE cmdlib.c AND scriplib.c INTO ripent.cpp */
|
||||||
|
/* Only add needed functions. */
|
||||||
|
// --
|
||||||
|
|
||||||
|
// -- cmdlib.c --
|
||||||
|
char qdir[1024] = { '\0' };
|
||||||
|
int LoadFile(char *filename, void **bufferptr)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
int length;
|
||||||
|
void *buffer;
|
||||||
|
|
||||||
|
f = SafeOpenRead(filename);
|
||||||
|
if (f == NULL)
|
||||||
|
return -1; // error
|
||||||
|
|
||||||
|
#if defined (_WIN32)
|
||||||
|
length = filelength(fileno(f));
|
||||||
|
#else
|
||||||
|
struct stat st; stat(filename, &st);
|
||||||
|
length = st.st_size;
|
||||||
|
#endif
|
||||||
|
buffer = malloc(length + 1);
|
||||||
|
((char *)buffer)[length] = 0;
|
||||||
|
SafeRead(f, buffer, length);
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
*bufferptr = buffer;
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
int LittleLong(int l)
|
||||||
|
{
|
||||||
|
byte b1, b2, b3, b4;
|
||||||
|
|
||||||
|
b1 = l & 255;
|
||||||
|
b2 = (l >> 8) & 255;
|
||||||
|
b3 = (l >> 16) & 255;
|
||||||
|
b4 = (l >> 24) & 255;
|
||||||
|
|
||||||
|
return ((int)b1 << 24) + ((int)b2 << 16) + ((int)b3 << 8) + b4;
|
||||||
|
}
|
||||||
|
char *copystring(char *s)
|
||||||
|
{
|
||||||
|
char *b;
|
||||||
|
b = (char*)malloc(strlen(s) + 1);
|
||||||
|
strcpy(b, s);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *SafeOpenRead(char *filename)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
f = fopen(filename, "rb");
|
||||||
|
|
||||||
|
if (!f)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "Error opening %s: %s", filename, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
void SafeRead(FILE *f, void *buffer, int count)
|
||||||
|
{
|
||||||
|
if (fread(buffer, 1, count, f) != (size_t)count)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "File read failure");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
char *ExpandPath(char *path)
|
||||||
|
{
|
||||||
|
char *psz;
|
||||||
|
static char full[1024];
|
||||||
|
if (!qdir)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "ExpandPath called without qdir set");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (path[0] == '/' || path[0] == '\\' || path[1] == ':')
|
||||||
|
return path;
|
||||||
|
psz = strstr(path, qdir);
|
||||||
|
if (psz)
|
||||||
|
strcpy(full, path);
|
||||||
|
else
|
||||||
|
sprintf(full, "%s%s", qdir, path);
|
||||||
|
|
||||||
|
return full;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- scriplib.c --
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char filename[1024];
|
||||||
|
char *buffer, *script_p, *end_p;
|
||||||
|
int line;
|
||||||
|
} script_t;
|
||||||
|
|
||||||
|
#define MAX_INCLUDES 8
|
||||||
|
script_t scriptstack[MAX_INCLUDES];
|
||||||
|
script_t *script;
|
||||||
|
int scriptline;
|
||||||
|
|
||||||
|
char token[MAXTOKEN];
|
||||||
|
bool endofscript;
|
||||||
|
bool tokenready; // only true if UnGetToken was just called
|
||||||
|
|
||||||
|
void ParseFromMemory(char *buffer, int size)
|
||||||
|
{
|
||||||
|
script = scriptstack;
|
||||||
|
script++;
|
||||||
|
if (script == &scriptstack[MAX_INCLUDES])
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "script file exceeded MAX_INCLUDES");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strcpy(script->filename, "memory buffer");
|
||||||
|
|
||||||
|
script->buffer = buffer;
|
||||||
|
script->line = 1;
|
||||||
|
script->script_p = script->buffer;
|
||||||
|
script->end_p = script->buffer + size;
|
||||||
|
|
||||||
|
endofscript = false;
|
||||||
|
tokenready = false;
|
||||||
|
}
|
||||||
|
bool EndOfScript(bool crossline)
|
||||||
|
{
|
||||||
|
if (!crossline)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "Line %i is incomplete\n", scriptline);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(script->filename, "memory buffer"))
|
||||||
|
{
|
||||||
|
endofscript = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(script->buffer);
|
||||||
|
if (script == scriptstack + 1)
|
||||||
|
{
|
||||||
|
endofscript = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
script--;
|
||||||
|
scriptline = script->line;
|
||||||
|
//printf("returning to %s\n", script->filename);
|
||||||
|
return GetToken(crossline);
|
||||||
|
}
|
||||||
|
void AddScriptToStack(char *filename)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
|
||||||
|
script++;
|
||||||
|
if (script == &scriptstack[MAX_INCLUDES])
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "script file exceeded MAX_INCLUDES");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strcpy(script->filename, ExpandPath(filename));
|
||||||
|
|
||||||
|
size = LoadFile(script->filename, (void **)&script->buffer);
|
||||||
|
|
||||||
|
//printf("entering %s\n", script->filename);
|
||||||
|
|
||||||
|
script->line = 1;
|
||||||
|
|
||||||
|
script->script_p = script->buffer;
|
||||||
|
script->end_p = script->buffer + size;
|
||||||
|
}
|
||||||
|
bool GetToken(bool crossline)
|
||||||
|
{
|
||||||
|
char *token_p;
|
||||||
|
|
||||||
|
if (tokenready) // is a token allready waiting?
|
||||||
|
{
|
||||||
|
tokenready = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (script->script_p >= script->end_p)
|
||||||
|
return EndOfScript(crossline);
|
||||||
|
|
||||||
|
//
|
||||||
|
// skip space
|
||||||
|
//
|
||||||
|
skipspace:
|
||||||
|
while (*script->script_p <= 32)
|
||||||
|
{
|
||||||
|
if (script->script_p >= script->end_p)
|
||||||
|
return EndOfScript(crossline);
|
||||||
|
if (*script->script_p++ == '\n')
|
||||||
|
{
|
||||||
|
if (!crossline)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "Line %i is incomplete\n", scriptline);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
scriptline = script->line++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (script->script_p >= script->end_p)
|
||||||
|
return EndOfScript(crossline);
|
||||||
|
|
||||||
|
if (*script->script_p == ';' || *script->script_p == '#' || // semicolon and # is comment field
|
||||||
|
(*script->script_p == '/' && *((script->script_p) + 1) == '/')) // also make // a comment field
|
||||||
|
{
|
||||||
|
if (!crossline)
|
||||||
|
{
|
||||||
|
LOG_MESSAGE(PLID, "Line %i is incomplete\n", scriptline);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while (*script->script_p++ != '\n')
|
||||||
|
if (script->script_p >= script->end_p)
|
||||||
|
return EndOfScript(crossline);
|
||||||
|
goto skipspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// copy token
|
||||||
|
//
|
||||||
|
token_p = token;
|
||||||
|
|
||||||
|
if (*script->script_p == '"')
|
||||||
|
{
|
||||||
|
// quoted token
|
||||||
|
script->script_p++;
|
||||||
|
while (*script->script_p != '"')
|
||||||
|
{
|
||||||
|
*token_p++ = *script->script_p++;
|
||||||
|
if (script->script_p == script->end_p)
|
||||||
|
break;
|
||||||
|
if (token_p == &token[MAXTOKEN])
|
||||||
|
LOG_MESSAGE(PLID, "Token too large on line %i\n", scriptline);
|
||||||
|
}
|
||||||
|
script->script_p++;
|
||||||
|
}
|
||||||
|
else // regular token
|
||||||
|
while (*script->script_p > 32 && *script->script_p != ';')
|
||||||
|
{
|
||||||
|
*token_p++ = *script->script_p++;
|
||||||
|
if (script->script_p == script->end_p)
|
||||||
|
break;
|
||||||
|
if (token_p == &token[MAXTOKEN])
|
||||||
|
LOG_MESSAGE(PLID, "Token too large on line %i\n", scriptline);
|
||||||
|
}
|
||||||
|
|
||||||
|
*token_p = 0;
|
||||||
|
|
||||||
|
if (!strcmp(token, "$include"))
|
||||||
|
{
|
||||||
|
GetToken(false);
|
||||||
|
AddScriptToStack(token);
|
||||||
|
return GetToken(crossline);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
97
src/dlls/ripent.h
Normal file
97
src/dlls/ripent.h
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
/***
|
||||||
|
*
|
||||||
|
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||||
|
*
|
||||||
|
* This product contains software technology licensed from Id
|
||||||
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
****/
|
||||||
|
|
||||||
|
// this is a stripped down "bspfile.h". contains only entity data similar
|
||||||
|
// to using a ripent tool to read ents from a bsp, hence the name.
|
||||||
|
// -Giegue
|
||||||
|
#include "extdll.h"
|
||||||
|
|
||||||
|
// upper design bounds
|
||||||
|
|
||||||
|
#define MAX_MAP_ENTITIES 1024
|
||||||
|
#define MAX_MAP_ENTSTRING (128*1024)
|
||||||
|
|
||||||
|
// key / value pair sizes
|
||||||
|
|
||||||
|
#define MAX_KEY 32
|
||||||
|
#define MAX_VALUE 1024
|
||||||
|
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
#define BSPVERSION 30
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int fileofs, filelen;
|
||||||
|
} lump_t;
|
||||||
|
|
||||||
|
#define LUMP_ENTITIES 0
|
||||||
|
|
||||||
|
#define HEADER_LUMPS 15
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int version;
|
||||||
|
lump_t lumps[HEADER_LUMPS];
|
||||||
|
} dheader_t;
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
// the utilities get to be lazy and just use large static arrays
|
||||||
|
|
||||||
|
extern int entdatasize;
|
||||||
|
extern char dentdata[MAX_MAP_ENTSTRING];
|
||||||
|
|
||||||
|
void LoadBSPFile(char *filename);
|
||||||
|
|
||||||
|
//===============
|
||||||
|
|
||||||
|
typedef struct epair_s
|
||||||
|
{
|
||||||
|
struct epair_s *next;
|
||||||
|
char *key;
|
||||||
|
char *value;
|
||||||
|
} epair_t;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
vec3_t origin;
|
||||||
|
int firstbrush;
|
||||||
|
int numbrushes;
|
||||||
|
epair_t *epairs;
|
||||||
|
} entity_t;
|
||||||
|
|
||||||
|
extern int num_entities;
|
||||||
|
extern entity_t entities[MAX_MAP_ENTITIES];
|
||||||
|
|
||||||
|
void ParseEntities(void);
|
||||||
|
|
||||||
|
epair_t *ParseEpair(void);
|
||||||
|
|
||||||
|
// --
|
||||||
|
/* MERGE cmdlib.h AND scriplib.h INTO ripent.h */
|
||||||
|
/* Only add needed functions. */
|
||||||
|
// --
|
||||||
|
|
||||||
|
// -- cmdlib.h --
|
||||||
|
int LoadFile(char *filename, void **bufferptr);
|
||||||
|
int LittleLong(int l);
|
||||||
|
char *copystring(char *s);
|
||||||
|
|
||||||
|
FILE *SafeOpenRead(char *filename);
|
||||||
|
void SafeRead(FILE *f, void *buffer, int count);
|
||||||
|
char *ExpandPath(char *path); // from scripts
|
||||||
|
|
||||||
|
// -- scriplib.h --
|
||||||
|
#define MAXTOKEN 512
|
||||||
|
|
||||||
|
extern char token[MAXTOKEN];
|
||||||
|
bool GetToken(bool crossline);
|
||||||
|
void ParseFromMemory(char *buffer, int size);
|
||||||
@@ -400,6 +400,9 @@ extern DLL_GLOBAL const Vector g_vecZero;
|
|||||||
#define SVC_ROOMTYPE 37
|
#define SVC_ROOMTYPE 37
|
||||||
#define SVC_HLTV 50
|
#define SVC_HLTV 50
|
||||||
|
|
||||||
|
// Added to stuff text to the clients
|
||||||
|
#define SVC_STUFFTEXT 9 // [string] stuffed into client's console buffer
|
||||||
|
|
||||||
// prxoy director stuff
|
// prxoy director stuff
|
||||||
#define DRC_EVENT 3 // informs the dircetor about ann important game event
|
#define DRC_EVENT 3 // informs the dircetor about ann important game event
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user