-#include "monster/zombie.qc"
-#include "monster/spider.qc"
#include "monster/mage.qc"
-#include "monster/wyvern.qc"
#include "monster/shambler.qc"
+#include "monster/spider.qc"
+#include "monster/wyvern.qc"
+#include "monster/zombie.qc"
+#ifndef MONSTERS_ALL_C
+#define MONSTERS_ALL_C
#include "all.qh"
-#include "all.inc"
+REGISTER_MONSTER(Null, Monster) {
+ this.netname = "";
+ this.monster_name = "Monster";
+ this.monster_func = m_null;
+ this.mdl = "";
+ this.mins = '-0 -0 -0';
+ this.maxs = '0 0 0';
+ this.model = "";
+}
-// MONSTER PLUGIN SYSTEM
-entity monster_info[MON_MAXCOUNT];
-entity dummy_monster_info;
+#include "all.inc"
-void register_monster(int id, float(float) func, int monsterflags, vector min_s, vector max_s, string modelname, string shortname, string mname)
-{
- entity e;
- monster_info[id - 1] = e = spawn();
- e.classname = "monster_info";
- e.monsterid = id;
- e.netname = shortname;
- e.monster_name = mname;
- e.monster_func = func;
- e.mdl = modelname;
- e.spawnflags = monsterflags;
- e.mins = min_s;
- e.maxs = max_s;
- e.model = strzone(strcat("models/monsters/", modelname));
-}
-float m_null(float dummy) { return 0; }
-void register_monsters_done()
-{
- dummy_monster_info = spawn();
- dummy_monster_info.classname = "monster_info";
- dummy_monster_info.monsterid = 0; // you can recognize dummies by this
- dummy_monster_info.netname = "";
- dummy_monster_info.monster_name = "Monster";
- dummy_monster_info.monster_func = m_null;
- dummy_monster_info.mdl = "";
- dummy_monster_info.mins = '-0 -0 -0';
- dummy_monster_info.maxs = '0 0 0';
- dummy_monster_info.model = "";
-}
entity get_monsterinfo(int id)
{
- entity m;
- if(id < MON_FIRST || id > MON_LAST)
- return dummy_monster_info;
- m = monster_info[id - 1];
- if(m)
- return m;
- return dummy_monster_info;
+ if (id >= MON_FIRST && id <= MON_LAST)
+ {
+ entity m = monster_info[id];
+ if (m) return m;
+ }
+ return MON_Null;
}
+
+#endif
+#include "../registry.qh"
+
#ifndef MONSTERS_ALL_H
#define MONSTERS_ALL_H
+void RegisterMonsters();
+const int MON_MAXCOUNT = 24;
+entity monster_info[MON_MAXCOUNT];
+entity get_monsterinfo(float id);
+int MON_COUNT;
+const int MON_FIRST = 1;
+#define MON_LAST (MON_FIRST + MON_COUNT - 1)
+/** If you register a new monster, make sure to add it to all.inc */
+#define REGISTER_MONSTER(id, class) REGISTER(RegisterMonsters, MON, monster_info, MON_COUNT, id, class, monsterid)
+#include "monster.qh"
+#define REGISTER_MONSTER_SIMPLE(id, monsterflags, min_s, max_s, modelname, shortname, mname) \
+ REGISTER_MONSTER(id, Monster) { \
+ this.netname = shortname; \
+ this.monster_name = mname; \
+ this.mdl = modelname; \
+ this.spawnflags = monsterflags; \
+ this.mins = min_s; \
+ this.maxs = max_s; \
+ this.model = strzone(strcat("models/monsters/", modelname)); \
+ } \
+ REGISTER_INIT(MON, id)
+
#include "../util.qh"
// monster requests
const int MR_DEATH = 3; // (SERVER) called when monster dies
const int MR_PRECACHE = 4; // (BOTH) precaches models/sounds used by this monster
-// functions:
-entity get_monsterinfo(float id);
-
// special spawn flags
const int MONSTER_RESPAWN_DEATHPOINT = 16; // re-spawn where we died
const int MONSTER_TYPE_FLY = 32;
const int MON_FLAG_MELEE = 1024;
// entity properties of monsterinfo:
-.float monsterid; // MON_...
.string netname; // short name
-.string monster_name; // human readable name
-.float(float) monster_func; // m_...
.string mdl; // currently a copy of the model
.string model; // full name of model
.int spawnflags;
#define MON_ACTION(monstertype,mrequest) (get_monsterinfo(monstertype)).monster_func(mrequest)
#define M_NAME(monstertype) (get_monsterinfo(monstertype)).monster_name
-// =====================
-// Monster Registration
-// =====================
-
-float m_null(float dummy);
-void register_monster(float id, float(float) func, float monsterflags, vector min_s, vector max_s, string modelname, string shortname, string mname);
-void register_monsters_done();
-
-const int MON_MAXCOUNT = 24;
-const int MON_FIRST = 1;
-int MON_COUNT;
-int MON_LAST;
-
-#define REGISTER_MONSTER_2(id,func,monsterflags,min_s,max_s,modelname,shortname,mname) \
- int id; \
- float func(float); \
- void RegisterMonsters_##id() \
- { \
- MON_LAST = (id = MON_FIRST + MON_COUNT); \
- ++MON_COUNT; \
- register_monster(id,func,monsterflags,min_s,max_s,modelname,shortname,mname); \
- } \
- ACCUMULATE_FUNCTION(RegisterMonsters, RegisterMonsters_##id)
-#ifdef MENUQC
-#define REGISTER_MONSTER(id,func,monsterflags,min_s,max_s,modelname,shortname,mname) \
- REGISTER_MONSTER_2(MON_##id,m_null,monsterflags,min_s,max_s,modelname,shortname,mname)
-#else
-#define REGISTER_MONSTER(id,func,monsterflags,min_s,max_s,modelname,shortname,mname) \
- REGISTER_MONSTER_2(MON_##id,func,monsterflags,min_s,max_s,modelname,shortname,mname)
-#endif
-
-#include "all.inc"
-
-#undef REGISTER_MONSTER
-ACCUMULATE_FUNCTION(RegisterMonsters, register_monsters_done);
#endif
--- /dev/null
+#ifndef MONSTER_H
+#define MONSTER_H
+
+bool m_null(int) { return false; }
+
+#include "../oo.qh"
+/** If you register a new monster, make sure to add it to all.inc */
+CLASS(Monster, Object)
+ ATTRIB(Monster, monsterid, int, 0)
+ ATTRIB(Monster, classname, string, "monster_info")
+ /** human readable name */
+ ATTRIB(Monster, monster_name, string, string_null)
+ ATTRIB(Monster, monster_func, bool(int), m_null)
+ENDCLASS(Monster)
+
+#endif
-#ifdef REGISTER_MONSTER
-REGISTER_MONSTER(
+#ifndef MENUQC
+bool m_mage(int);
+#endif
+REGISTER_MONSTER_SIMPLE(
/* MON_##id */ MAGE,
-/* function */ m_mage,
/* spawnflags */ MON_FLAG_MELEE | MON_FLAG_RANGED,
/* mins,maxs */ '-36 -36 -24', '36 36 50',
/* model */ "mage.dpm",
/* netname */ "mage",
/* fullname */ _("Mage")
-);
+) {
+#ifndef MENUQC
+ this.monster_func = m_mage;
+#endif
+}
-#else
#ifdef SVQC
float autocvar_g_monster_mage_health;
float autocvar_g_monster_mage_attack_spike_damage;
{
self.classname = "monster_mage";
- if(!monster_initialize(MON_MAGE)) { remove(self); return; }
+ if(!monster_initialize(MON_MAGE.monsterid)) { remove(self); return; }
}
// compatibility with old spawns
}
#endif // CSQC
-#endif // REGISTER_MONSTER
-#ifdef REGISTER_MONSTER
-REGISTER_MONSTER(
+#ifndef MENUQC
+bool m_shambler(int);
+#endif
+REGISTER_MONSTER_SIMPLE(
/* MON_##id */ SHAMBLER,
-/* function */ m_shambler,
/* spawnflags */ MONSTER_SIZE_BROKEN | MON_FLAG_SUPERMONSTER | MON_FLAG_MELEE | MON_FLAG_RANGED,
/* mins,maxs */ '-41 -41 -31', '41 41 65',
/* model */ "shambler.mdl",
/* netname */ "shambler",
/* fullname */ _("Shambler")
-);
+) {
+#ifndef MENUQC
+ this.monster_func = m_shambler;
+#endif
+}
-#else
#ifdef SVQC
float autocvar_g_monster_shambler_health;
float autocvar_g_monster_shambler_attack_smash_damage;
{
self.classname = "monster_shambler";
- if(!monster_initialize(MON_SHAMBLER)) { remove(self); return; }
+ if(!monster_initialize(MON_SHAMBLER.monsterid)) { remove(self); return; }
}
float m_shambler(float req)
}
#endif // CSQC
-#endif // REGISTER_MONSTER
-#ifdef REGISTER_MONSTER
-REGISTER_MONSTER(
+#ifndef MENUQC
+bool m_spider(int);
+#endif
+REGISTER_MONSTER_SIMPLE(
/* MON_##id */ SPIDER,
-/* function */ m_spider,
/* spawnflags */ MON_FLAG_MELEE | MON_FLAG_RANGED,
/* mins,maxs */ '-18 -18 -25', '18 18 30',
/* model */ "spider.dpm",
/* netname */ "spider",
/* fullname */ _("Spider")
-);
+) {
+#ifndef MENUQC
+ this.monster_func = m_spider;
+#endif
+}
-#else
#ifdef SVQC
float autocvar_g_monster_spider_health;
float autocvar_g_monster_spider_attack_bite_damage;
pointparticles(particleeffectnum("electro_impact"), self.origin, '0 0 0', 1);
RadiusDamage(self, self.realowner, 0, 0, 25, world, world, 25, self.projectiledeathtype, world);
- for(e = findradius(self.origin, 25); e; e = e.chain) if(e != self) if(e.takedamage && e.deadflag == DEAD_NO) if(e.health > 0) if(e.monsterid != MON_SPIDER)
+ for(e = findradius(self.origin, 25); e; e = e.chain) if(e != self) if(e.takedamage && e.deadflag == DEAD_NO) if(e.health > 0) if(e.monsterid != MON_SPIDER.monsterid)
e.spider_slowness = time + (autocvar_g_monster_spider_attack_web_damagetime);
remove(self);
{
self.classname = "monster_spider";
- if(!monster_initialize(MON_SPIDER)) { remove(self); return; }
+ if(!monster_initialize(MON_SPIDER.monsterid)) { remove(self); return; }
}
float m_spider(float req)
}
#endif // CSQC
-#endif // REGISTER_MONSTER
-#ifdef REGISTER_MONSTER
-REGISTER_MONSTER(
+#ifndef MENUQC
+bool m_wyvern(int);
+#endif
+REGISTER_MONSTER_SIMPLE(
/* MON_##id */ WYVERN,
-/* function */ m_wyvern,
/* spawnflags */ MONSTER_TYPE_FLY | MONSTER_SIZE_BROKEN | MON_FLAG_RANGED,
/* mins,maxs */ '-20 -20 -58', '20 20 20',
/* model */ "wizard.mdl",
/* netname */ "wyvern",
/* fullname */ _("Wyvern")
-);
+) {
+#ifndef MENUQC
+ this.monster_func = m_wyvern;
+#endif
+}
-#else
#ifdef SVQC
float autocvar_g_monster_wyvern_health;
float autocvar_g_monster_wyvern_attack_fireball_damage;
{
self.classname = "monster_wyvern";
- if(!monster_initialize(MON_WYVERN)) { remove(self); return; }
+ if(!monster_initialize(MON_WYVERN.monsterid)) { remove(self); return; }
}
// compatibility with old spawns
}
#endif // CSQC
-#endif // REGISTER_MONSTER
-#ifdef REGISTER_MONSTER
-REGISTER_MONSTER(
+#ifndef MENUQC
+bool m_zombie(int);
+#endif
+REGISTER_MONSTER_SIMPLE(
/* MON_##id */ ZOMBIE,
-/* function */ m_zombie,
/* spawnflags */ MON_FLAG_MELEE,
/* mins,maxs */ '-18 -18 -25', '18 18 47',
/* model */ "zombie.dpm",
/* netname */ "zombie",
/* fullname */ _("Zombie")
-);
+) {
+#ifndef MENUQC
+ this.monster_func = m_zombie;
+#endif
+}
-#else
#ifdef SVQC
float autocvar_g_monster_zombie_health;
float autocvar_g_monster_zombie_attack_melee_damage;
{
self.classname = "monster_zombie";
- if(!monster_initialize(MON_ZOMBIE)) { remove(self); return; }
+ if(!monster_initialize(MON_ZOMBIE.monsterid)) { remove(self); return; }
}
float m_zombie(float req)
}
#endif // CSQC
-#endif // REGISTER_MONSTER
#include "../../common/teams.qh"
#include "../../common/util.qh"
-#include "../../common/monsters/all.qh"
+#include "../../common/monsters/all.qc"
#include "../../common/monsters/spawn.qh"
#include "../../common/monsters/sv_monsters.qh"
{
case "skin":
{
- if(trace_ent.monsterid != MON_MAGE)
+ if(trace_ent.monsterid != MON_MAGE.monsterid)
trace_ent.skin = stof(argv(2));
return;
}
float invasion_PickMonster(float supermonster_count)
{
if(autocvar_g_invasion_zombies_only)
- return MON_ZOMBIE;
+ return MON_ZOMBIE.monsterid;
float i;
entity mon;
void invasion_Initialize()
{
if(autocvar_g_invasion_zombies_only)
- MON_ACTION(MON_ZOMBIE, MR_PRECACHE);
+ MON_ACTION(MON_ZOMBIE.monsterid, MR_PRECACHE);
else
{
float i;
MUTATOR_HOOKFUNCTION(instagib_MonsterSpawn)
{
// always refill ammo
- if(self.monsterid == MON_MAGE)
+ if(self.monsterid == MON_MAGE.monsterid)
self.skin = 1;
return false;