Server: add MapTweaks. A new feature that allows tinkerers to rewrite entity classnames under certain conditions (RFC)
This commit is contained in:
parent
c5626ce347
commit
cd3023eeba
6 changed files with 232 additions and 1 deletions
|
@ -491,6 +491,7 @@ worldspawn(void)
|
|||
lightstyle(12, "mmnnmmnnnmmnn");
|
||||
lightstyle(63, "a");
|
||||
Skill_Init();
|
||||
MapTweaks_Init();
|
||||
|
||||
precache_model("models/error.vvm");
|
||||
|
||||
|
@ -769,6 +770,9 @@ to remove in case we won't initialize it.
|
|||
void
|
||||
CheckSpawn(void() spawnfunc)
|
||||
{
|
||||
if (MapTweak_EntitySpawn(self))
|
||||
return;
|
||||
|
||||
if (spawnfunc) {
|
||||
spawnfunc();
|
||||
self._mapspawned = true;
|
||||
|
|
|
@ -12,5 +12,6 @@ vote.qc
|
|||
weapons.qc
|
||||
modelevent.qc
|
||||
mapcycle.qc
|
||||
maptweaks.qc
|
||||
entry.qc
|
||||
#endlist
|
||||
|
|
209
src/server/maptweaks.qc
Normal file
209
src/server/maptweaks.qc
Normal file
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* early maptweaks implementation (RFC)
|
||||
|
||||
design notes:
|
||||
|
||||
needed system that handles entity renaming
|
||||
or edits in an easy to understand syntax
|
||||
|
||||
replaces .ent file overrides for a lot of tasks
|
||||
and can apply rules on all relevant maps based on
|
||||
custom filters, either via serverinfo or via cvar.
|
||||
|
||||
TODO: immediately throw out things where cvar/infokey
|
||||
checks fail and don't even cache them.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
string cvarCheck;
|
||||
string serverinfoCheck;
|
||||
string itemTable;
|
||||
} mapTweak_t;
|
||||
|
||||
mapTweak_t *g_mapTweakTable;
|
||||
var int g_mapTweakCount;
|
||||
|
||||
void
|
||||
MapTweaks_Init(void)
|
||||
{
|
||||
filestream tweakFile;
|
||||
string tempString;
|
||||
string newCvar, newInfo, newItem;
|
||||
int atTweak = 0i;
|
||||
|
||||
tweakFile = fopen("scripts/maptweaks.txt", FILE_READ);
|
||||
g_mapTweakCount = 0;
|
||||
newCvar = newInfo = newItem = "";
|
||||
|
||||
/* count valid entries. */
|
||||
if (tweakFile >= 0) {
|
||||
while ((tempString = fgets(tweakFile))) {
|
||||
if (tokenize_console(tempString) == 1) {
|
||||
if (argv(0) == "}")
|
||||
g_mapTweakCount += 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
g_mapTweakTable = memalloc(sizeof(mapTweak_t) * g_mapTweakCount);
|
||||
fseek(tweakFile, 0);
|
||||
|
||||
while ((tempString = fgets(tweakFile))) {
|
||||
int segments = tokenize_console(tempString);
|
||||
if (segments == 1) {
|
||||
if (argv(0) == "}") {
|
||||
g_mapTweakTable[atTweak].cvarCheck = newCvar;
|
||||
g_mapTweakTable[atTweak].serverinfoCheck = newInfo;
|
||||
g_mapTweakTable[atTweak].itemTable = newItem;
|
||||
newCvar = newInfo = newItem = "";
|
||||
atTweak++;
|
||||
} else if (argv(0) == "{") {
|
||||
/* ??? */
|
||||
}
|
||||
} else if (segments == 4) {
|
||||
switch (argv(0)) {
|
||||
case "when-cvar":
|
||||
newCvar = strcat(newCvar, argv(1), " ", argv(2), " ", argv(3), " ");
|
||||
break;
|
||||
case "when-serverinfo":
|
||||
newInfo = strcat(newInfo, argv(1), " ", argv(2), " ", argv(3), " ");
|
||||
break;
|
||||
}
|
||||
} else if (segments == 3) {
|
||||
switch (argv(0)) {
|
||||
case "replace":
|
||||
newItem = strcat(newItem, argv(1), " ", argv(2), " ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(tweakFile);
|
||||
}
|
||||
|
||||
static bool
|
||||
MapTweak_Check(int id)
|
||||
{
|
||||
int segments = tokenize(g_mapTweakTable[id].cvarCheck);
|
||||
|
||||
/* cvars first */
|
||||
for (int i = 0; i < segments; i += 3) {
|
||||
string cvarName = argv(i);
|
||||
string checkType = argv(i + 1);
|
||||
float cvarValue = stof(argv(i + 2));
|
||||
|
||||
switch (checkType) {
|
||||
case "equals":
|
||||
if not (cvar(cvarName) == cvarValue)
|
||||
return false;
|
||||
break;
|
||||
case "less-than":
|
||||
if not (cvar(cvarName) < cvarValue)
|
||||
return false;
|
||||
break;
|
||||
case "greater-than":
|
||||
if not (cvar(cvarName) > cvarValue)
|
||||
return false;
|
||||
break;
|
||||
case "is-not":
|
||||
if not (cvar(cvarName) != cvarValue)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
segments = tokenize(g_mapTweakTable[id].serverinfoCheck);
|
||||
|
||||
/* infokeys second */
|
||||
for (int i = 0; i < segments; i += 3) {
|
||||
string infoName = argv(i);
|
||||
string checkType = argv(i + 1);
|
||||
float infoValue = stof(argv(i + 2));
|
||||
|
||||
switch (checkType) {
|
||||
case "equals":
|
||||
if not (serverkeyfloat(infoName) == infoValue)
|
||||
return false;
|
||||
break;
|
||||
case "less-than":
|
||||
if not (serverkeyfloat(infoName) < infoValue)
|
||||
return false;
|
||||
break;
|
||||
case "greater-than":
|
||||
if not (serverkeyfloat(infoName) > infoValue)
|
||||
return false;
|
||||
break;
|
||||
case "is-not":
|
||||
if not (serverkeyfloat(infoName) != infoValue)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
MapTweak_FinishSpawn(entity targetEntity, string newClassname)
|
||||
{
|
||||
entity oldSelf = self;
|
||||
self = targetEntity;
|
||||
|
||||
if (!isfunction(newClassname)) {
|
||||
self.classname = strcat("spawnfunc_", newClassname);
|
||||
} else {
|
||||
self.classname = newClassname;
|
||||
}
|
||||
|
||||
callfunction(self.classname);
|
||||
self = oldSelf;
|
||||
}
|
||||
|
||||
bool
|
||||
MapTweak_EntitySpawn(entity targetEntity)
|
||||
{
|
||||
string classCheck = targetEntity.classname;
|
||||
|
||||
if (g_mapTweakCount <= 0)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < g_mapTweakCount; i++) {
|
||||
int segments = tokenize(g_mapTweakTable[i].itemTable);
|
||||
|
||||
for (int y = 0; y < segments; y += 2) {
|
||||
string newEnt, oldEnt;
|
||||
|
||||
oldEnt = argv(y);
|
||||
newEnt = argv(y + 1);
|
||||
|
||||
if (classCheck == oldEnt) {
|
||||
if (MapTweak_Check(i) == true) {
|
||||
MapTweak_FinishSpawn(targetEntity, newEnt);
|
||||
return true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -110,7 +110,6 @@ private:
|
|||
#endif
|
||||
|
||||
PREDICTED_FLOAT(health)
|
||||
PREDICTED_FLOAT(armor)
|
||||
|
||||
PREDICTED_FLOAT_N(colormap)
|
||||
PREDICTED_FLOAT_N(gflags)
|
||||
|
|
|
@ -46,6 +46,8 @@ class NSSurfacePropEntity:NSRenderableEntity
|
|||
private:
|
||||
float m_flBurnNext;
|
||||
|
||||
PREDICTED_FLOAT(armor)
|
||||
|
||||
#ifdef SERVER
|
||||
/* fire/burning */
|
||||
entity m_eBurner;
|
||||
|
@ -126,6 +128,11 @@ public:
|
|||
/** Returns the maximum health the entity can have. */
|
||||
nonvirtual float GetMaxHealth(void);
|
||||
|
||||
/** Sets the current armor of the entity. */
|
||||
nonvirtual void SetArmor(float);
|
||||
/** Returns the current armor of the entity. */
|
||||
nonvirtual float GetArmor(void);
|
||||
|
||||
/** Returns the health the entity spawned with at map load */
|
||||
nonvirtual float GetSpawnHealth(void);
|
||||
/** Returns if the entity has prop data information set. */
|
||||
|
|
|
@ -402,6 +402,17 @@ NSSurfacePropEntity::GetSpawnHealth(void)
|
|||
return m_oldHealth;
|
||||
}
|
||||
|
||||
void
|
||||
NSSurfacePropEntity::SetArmor(float new_armor)
|
||||
{
|
||||
armor = new_armor;
|
||||
}
|
||||
float
|
||||
NSSurfacePropEntity::GetArmor(void)
|
||||
{
|
||||
return armor;
|
||||
}
|
||||
|
||||
bool
|
||||
NSSurfacePropEntity::HasPropData(void)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue