Commit 1bb02b20 authored by TimePath's avatar TimePath

Re-use generic registry code for monsters

parent c4775145
#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
......@@ -9,9 +33,6 @@ const int MR_THINK = 2; // (SERVER) logic to run every frame
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;
......@@ -22,10 +43,7 @@ const int MON_FLAG_RANGED = 512; // monster shoots projectiles
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;
......@@ -35,39 +53,4 @@ const int MON_FLAG_MELEE = 1024;
#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
#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;
......@@ -337,7 +341,7 @@ void spawnfunc_monster_mage()
{
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
......@@ -420,4 +424,3 @@ float m_mage(float req)
}
#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;
......@@ -197,7 +201,7 @@ void spawnfunc_monster_shambler()
{
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)
......@@ -252,4 +256,3 @@ 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;
......@@ -37,7 +41,7 @@ void spider_web_explode()
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);
......@@ -119,7 +123,7 @@ void spawnfunc_monster_spider()
{
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)
......@@ -174,4 +178,3 @@ 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;
......@@ -96,7 +100,7 @@ void spawnfunc_monster_wyvern()
{
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
......@@ -155,4 +159,3 @@ float m_wyvern(float req)
}
#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;
......@@ -130,7 +134,7 @@ void spawnfunc_monster_zombie()
{
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)
......@@ -193,4 +197,3 @@ float m_zombie(float req)
}
#endif // CSQC
#endif // REGISTER_MONSTER
......@@ -26,7 +26,7 @@
#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"
......@@ -239,7 +239,7 @@ void ClientCommand_mobedit(float request, float argc)
{
case "skin":
{
if(trace_ent.monsterid != MON_MAGE)
if(trace_ent.monsterid != MON_MAGE.monsterid)
trace_ent.skin = stof(argv(2));
return;
}
......
......@@ -20,7 +20,7 @@ void spawnfunc_invasion_spawnpoint()
float invasion_PickMonster(float supermonster_count)
{
if(autocvar_g_invasion_zombies_only)
return MON_ZOMBIE;
return MON_ZOMBIE.monsterid;
float i;
entity mon;
......@@ -431,7 +431,7 @@ void invasion_DelayedInit() // Do this check with a delay so we can wait for tea
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;
......
......@@ -124,7 +124,7 @@ MUTATOR_HOOKFUNCTION(instagib_MonsterLoot)
MUTATOR_HOOKFUNCTION(instagib_MonsterSpawn)
{
// always refill ammo
if(self.monsterid == MON_MAGE)
if(self.monsterid == MON_MAGE.monsterid)
self.skin = 1;
return false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment