feat(fgame): add an optional parameter to removeclass and killclass to control subclass inclusion (#863)

Subclasses are included by default.
This commit is contained in:
smallmodel authored and GitHub committed 2025-12-15 23:52:32 +01:00
1 parent e3a873b4aa
commit 9fd2fb13f1
3 files changed
+202 -63

No files matched your search

+100 -30
View File
@@ -437,13 +437,15 @@ Event EV_ScriptThread_IsAlive
"Returns true if the specified entity exists and has health > 0.",
EV_RETURN
);
// Changed in OPM
// Allow including/excluding sub-classes
Event EV_ScriptThread_KillClass
(
"killclass",
EV_CHEAT,
"sI",
"class_name except",
"Kills everything in the specified class except for the specified entity (optional)."
"sIB",
"class_name except include_subclasses",
"Kills everything in the specified class except for the specified entity (optional). Kills subclasses by default."
);
Event EV_ScriptThread_GetEntByEntnum // Added in 2.30
(
@@ -462,13 +464,15 @@ Event EV_ScriptThread_RemoveEnt
"ent_num",
"Removes the specified entity."
);
// Changed in OPM
// Allow including/excluding sub-classes
Event EV_ScriptThread_RemoveClass
(
"removeclass",
EV_CHEAT,
"sI",
"class_name except",
"Removes everything in the specified class except for the specified entity (optional)."
"sIB",
"class_name except include_subclasses",
"Removes everything in the specified class except for the specified entity (optional). Removes sub-classes by default."
);
// client/server flow control
@@ -3529,8 +3533,10 @@ void ScriptThread::KillClass(Event *ev)
{
int except;
str classname;
bool include_subclasses;
gentity_t *from;
Entity *ent;
ClassDef *c;
if (ev->NumArgs() < 1) {
throw ScriptException("No args passed in");
@@ -3539,25 +3545,56 @@ void ScriptThread::KillClass(Event *ev)
classname = ev->GetString(1);
except = 0;
if (ev->NumArgs() == 2) {
except = ev->GetInteger(1);
if (ev->NumArgs() >= 2 && !ev->IsNilAt(2)) {
// Fixed in OPM
// It was accidentally fetching the first parameter...
except = ev->GetInteger(2);
}
for (from = &g_entities[game.maxclients]; from < &g_entities[globals.num_entities]; from++) {
if (!from->inuse) {
continue;
// Added in OPM
// Check for exact class
include_subclasses = false;
if (ev->NumArgs() >= 3) {
include_subclasses = ev->GetBoolean(3);
}
c = getClass(classname);
if (include_subclasses) {
for (from = &g_entities[game.maxclients]; from < &g_entities[globals.num_entities]; from++) {
if (!from->inuse) {
continue;
}
assert(from->entity);
ent = from->entity;
if (ent->entnum == except) {
continue;
}
if (ent->inheritsFrom(c)) {
ent->Damage(world, world, ent->max_health + 25, vec_zero, vec_zero, vec_zero, 0, 0, 0);
}
}
} else {
for (from = &g_entities[game.maxclients]; from < &g_entities[globals.num_entities]; from++) {
if (!from->inuse) {
continue;
}
assert(from->entity);
assert(from->entity);
ent = from->entity;
ent = from->entity;
if (ent->entnum == except) {
continue;
}
if (ent->entnum == except) {
continue;
}
if (ent->inheritsFrom(classname.c_str())) {
ent->Damage(world, world, ent->max_health + 25, vec_zero, vec_zero, vec_zero, 0, 0, 0);
if (ent->classinfo() == c) {
ent->Damage(world, world, ent->max_health + 25, vec_zero, vec_zero, vec_zero, 0, 0, 0);
}
}
}
}
@@ -3566,8 +3603,10 @@ void ScriptThread::RemoveClass(Event *ev)
{
int except;
str classname;
bool include_subclasses;
gentity_t *from;
Entity *ent;
ClassDef *c;
if (ev->NumArgs() < 1) {
throw ScriptException("No args passed in");
@@ -3576,25 +3615,56 @@ void ScriptThread::RemoveClass(Event *ev)
classname = ev->GetString(1);
except = 0;
if (ev->NumArgs() == 2) {
except = ev->GetInteger(1);
if (ev->NumArgs() >= 2 && !ev->IsNilAt(2)) {
// Fixed in OPM
// It was accidentally fetching the first parameter...
except = ev->GetInteger(2);
}
for (from = &g_entities[game.maxclients]; from < &g_entities[globals.num_entities]; from++) {
if (!from->inuse) {
continue;
// Added in OPM
// Check for exact class
include_subclasses = false;
if (ev->NumArgs() >= 3) {
include_subclasses = ev->GetBoolean(3);
}
c = getClass(classname);
if (include_subclasses) {
for (from = &g_entities[game.maxclients]; from < &g_entities[globals.num_entities]; from++) {
if (!from->inuse) {
continue;
}
assert(from->entity);
ent = from->entity;
if (ent->entnum == except) {
continue;
}
if (ent->inheritsFrom(c)) {
ent->PostEvent(EV_Remove, 0);
}
}
} else {
for (from = &g_entities[game.maxclients]; from < &g_entities[globals.num_entities]; from++) {
if (!from->inuse) {
continue;
}
assert(from->entity);
assert(from->entity);
ent = from->entity;
ent = from->entity;
if (ent->entnum == except) {
continue;
}
if (ent->entnum == except) {
continue;
}
if (ent->inheritsFrom(classname.c_str())) {
ent->PostEvent(Event(EV_Remove), 0);
if (ent->classinfo() == c) {
ent->PostEvent(EV_Remove, 0);
}
}
}
}