#include "../common/stats.qh"
#include "../common/teams.qh"
+#include "../common/items/all.qh"
+
#include "../common/weapons/weapons.qh"
#include "../csqcmodellib/cl_model.qh"
// needs to be done so early because of the constants they create
CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
CALL_ACCUMULATED_FUNCTION(RegisterMonsters);
+ CALL_ACCUMULATED_FUNCTION(RegisterItems);
CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
../common/urllib.qc
../common/util.qc
+../common/items/all.qc
+
../common/monsters/monsters.qc
../common/weapons/weapons.qc // TODO
--- /dev/null
+#include "item.qc"
+
+#include "item/ammo.qc"
+#include "item/buff.qc"
--- /dev/null
+#include "all.qh"
+
+#include "all.inc"
+
+void ItemTest()
+{
+ ITEMS_FOREACH(it != NULL, LAMBDA({
+ print(strcat(etos(it), "\n"));
+ ITEM_SEND(Default, it);
+ }));
+}
--- /dev/null
+#ifndef ALL_H
+#define ALL_H
+
+const int MAX_ITEMS = 23;
+entity ITEMS[MAX_ITEMS];
+
+#define ITEMS_FOREACH(pred, body) do { \
+ for (int i = 0; i < ITEM_COUNT; i++) { \
+ const entity it = ITEMS[i]; \
+ if (pred) { body } \
+ } \
+} while(0)
+
+void RegisterItems();
+void ItemTest();
+
+#ifdef CSQC
+void ReadItems()
+{
+/*
+ const int flags = read();
+ for (int i = 0; i < MAX_ITEMS; i++) {
+ if (flags & BIT(i)) {
+ self.items[i] = read();
+ }
+ }
+*/
+}
+#endif
+
+#ifdef SVQC
+void WriteItems()
+{
+
+}
+#endif
+
+#endif
--- /dev/null
+#include "item.qh"
+
+bool GameItem_respondTo(entity this, int request)
+{
+ switch (request) {
+ default: return false;
+ case ITEM_SIGNAL(Default):
+ print("Item responding\n");
+ return true;
+ }
+}
--- /dev/null
+#ifndef GAMEITEM_H
+#define GAMEITEM_H
+#include "../oo.qh"
+CLASS(GameItem, Object)
+ METHOD(GameItem, respondTo, bool(entity, int))
+ENDCLASS(GameItem)
+
+
+
+#define LAMBDA(...) { __VA_ARGS__ ; }
+
+#define ITEM_SIGNALS(_) \
+ _(Default, void, (entity it), LAMBDA({ it.respondTo(it, SIGNAL); })) \
+ /* Common item signals */
+
+#define ITEM_SIGNAL(id) __Item_Signal_##id
+
+#define ITEM_ENUM(id, ret, params, body) ITEM_SIGNAL(id) ,
+enum { ITEM_SIGNALS(ITEM_ENUM) };
+#undef ITEM_ENUM
+
+#define ITEM_SEND(id, ret, params, body) ret __Item_Send_##id params { const noref int SIGNAL = ITEM_SIGNAL(id); body }
+ITEM_SIGNALS(ITEM_SEND)
+#undef ITEM_SEND
+#define ITEM_SEND(id, ...) __Item_Send_##id(__VA_ARGS__)
+
+
+
+int ITEM_COUNT;
+#define REGISTER_ITEM(id, class, body) \
+ void RegisterItems_##id() { \
+ const noref entity this = NEW(class); \
+ ITEMS[ITEM_COUNT++] = this; \
+ body \
+ } \
+ ACCUMULATE_FUNCTION(RegisterItems, RegisterItems_##id)
+
+#endif
--- /dev/null
+#include "ammo.qh"
+
+#define REGISTER_AMMO(id) REGISTER_ITEM(id, Ammo, LAMBDA(this.ammoName = #id))
+REGISTER_AMMO(nails)
+REGISTER_AMMO(rockets)
+REGISTER_AMMO(cells)
+REGISTER_AMMO(plasma)
+REGISTER_AMMO(fuel)
+
+bool Ammo_respondTo(entity this, int request)
+{
+ switch (request) {
+ default: return false;
+ case ITEM_SIGNAL(Default):
+ print(strcat(this.ammoName, " responding\n"));
+ return true;
+ }
+}
--- /dev/null
+#ifndef AMMO_H
+#define AMMO_H
+#include "../item.qh"
+CLASS(Ammo, GameItem)
+ METHOD(Ammo, respondTo, bool(entity, int))
+ ATTRIB(Ammo, ammoName, string, string_null)
+ENDCLASS(Ammo)
+#endif
--- /dev/null
+#include "buff.qh"
+
+REGISTER_ITEM(strength, Buff, LAMBDA())
+
+bool Buff_respondTo(entity this, int request)
+{
+ switch (request) {
+ default: return false;
+ case ITEM_SIGNAL(Default):
+ print("Buff responding\n");
+ return true;
+ }
+}
--- /dev/null
+#ifndef BUFF_H
+#define BUFF_H
+#include "../item.qh"
+CLASS(Buff, GameItem)
+ METHOD(Buff, respondTo, bool(entity, int))
+ENDCLASS(Buff)
+#endif
--- /dev/null
+#ifndef OO_H
+#define OO_H
+
+#ifdef MENUQC
+ #define NULL (null_entity)
+#else
+ #define NULL (world)
+#endif
+
+.string classname;
+.string vtblname;
+.entity vtblbase;
+entity spawnVtbl(entity this, entity base)
+{
+ entity vtbl = spawn();
+ copyentity(this, vtbl);
+ vtbl.vtblname = vtbl.classname;
+ vtbl.classname = "vtbl";
+ vtbl.vtblbase = base ? base : vtbl; // Top level objects use vtbl as base
+ return vtbl;
+}
+
+entity Object_vtbl;
+entity spawnObject(entity this, entity)
+{
+ this = spawn();
+ this.classname = "Object";
+ if (!Object_vtbl) Object_vtbl = spawnVtbl(this, NULL);
+ return this;
+}
+
+// Classes have a `spawn##cname(entity, entity)` constructor
+// The parameters are used as locals for [[accumulate]]
+
+// Macro to hide this implementation detail
+#define NEW(cname) (spawn##cname(NULL, NULL))
+
+#define CLASS(cname, base) \
+entity spawn##cname(entity this, entity basevtbl) { \
+ this = NEW(base); basevtbl = base##_vtbl; \
+}
+
+#define METHOD(cname, name, prototype) \
+prototype cname##_##name; \
+.prototype name; \
+[[accumulate]] entity spawn##cname(entity this, entity basevtbl) { \
+ this.name = cname##_##name; \
+}
+
+#define ATTRIB(cname, name, type, val) \
+.type name; \
+[[accumulate]] entity spawn##cname(entity this, entity basevtbl) { \
+ this.name = val; \
+}
+
+#define ATTRIBARRAY(cname, name, type, cnt) \
+.type name[cnt];
+
+#define ENDCLASS(cname) \
+.bool instanceOf##cname; \
+entity cname##_vtbl; \
+[[last]] entity spawn##cname(entity this, entity basevtbl) { \
+ this.instanceOf##cname = true; \
+ this.classname = #cname; \
+ if (!cname##_vtbl) cname##_vtbl = spawnVtbl(this, basevtbl); \
+ return this; \
+}
+
+#define SUPER(cname) (cname##_vtbl.vtblbase)
+
+#endif
#include "oo/classes.qc"
#include "xonotic/util.qh"
+#include "../common/items/all.qh"
#include "../common/weapons/weapons.qh"
#include "../common/mapinfo.qh"
// needs to be done so early because of the constants they create
CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
+ CALL_ACCUMULATED_FUNCTION(RegisterItems);
CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
RegisterSLCategories();
#ifndef BASE_H
#define BASE_H
+#include "../../common/oo.qh"
+
#include "../../common/util.qh"
#include "../../dpdefs/keycodes.qh"
-#define NULL (null_entity)
#define world NULL
-.string classname;
-.string vtblname;
-.entity vtblbase;
-entity spawnVtbl(entity this, entity base)
-{
- entity vtbl = spawn();
- copyentity(this, vtbl);
- vtbl.vtblname = vtbl.classname;
- vtbl.classname = "vtbl";
- vtbl.vtblbase = base ? base : vtbl; // Top level objects use vtbl as base
- return vtbl;
-}
-
-entity Object_vtbl;
-entity spawnObject(entity this, entity)
-{
- this = spawn();
- this.classname = "Object";
- if (!Object_vtbl) Object_vtbl = spawnVtbl(this, null_entity);
- return this;
-}
-
-// Classes have a `spawn##cname(entity, entity)` constructor
-// The parameters are used as locals for [[accumulate]]
-
-// Macro to hide this implementation detail
-#define NEW(cname) (spawn##cname(null_entity, null_entity))
-
-#define CLASS(cname, base) \
-entity spawn##cname(entity this, entity basevtbl) { \
- this = NEW(base); basevtbl = base##_vtbl; \
-}
-
-#define METHOD(cname, name, prototype) \
-prototype cname##_##name; \
-.prototype name; \
-[[accumulate]] entity spawn##cname(entity this, entity basevtbl) { \
- this.name = cname##_##name; \
-}
-
-#define ATTRIB(cname, name, type, val) \
-.type name; \
-[[accumulate]] entity spawn##cname(entity this, entity basevtbl) { \
- this.name = val; \
-}
-
-#define ATTRIBARRAY(cname, name, type, cnt) \
-.type name[cnt];
-
-#define ENDCLASS(cname) \
-.bool instanceOf##cname; \
-entity cname##_vtbl; \
-[[last]] entity spawn##cname(entity this, entity basevtbl) { \
- this.instanceOf##cname = true; \
- this.classname = #cname; \
- if (!cname##_vtbl) cname##_vtbl = spawnVtbl(this, basevtbl); \
- return this; \
-}
-
-#define SUPER(cname) (cname##_vtbl.vtblbase)
-
-#endif
\ No newline at end of file
+#endif
../common/urllib.qc
../common/util.qc
+../common/items/all.qc
+
../common/monsters/monsters.qc
../common/weapons/weapons.qc // TODO
#include "../common/stats.qh"
#include "../common/teams.qh"
#include "../common/util.qh"
+#include "../common/items/all.qh"
#include "../common/weapons/weapons.qh"
const float LATENCY_THINKRATE = 10;
// needs to be done so early because of the constants they create
CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
CALL_ACCUMULATED_FUNCTION(RegisterMonsters);
+ CALL_ACCUMULATED_FUNCTION(RegisterItems);
CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
// needs to be done so early because of the constants they create
CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
CALL_ACCUMULATED_FUNCTION(RegisterMonsters);
+ CALL_ACCUMULATED_FUNCTION(RegisterItems);
CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
../common/test.qc
../common/urllib.qc
../common/util.qc
+
+../common/items/all.qc
+
../common/weapons/config.qc
../common/weapons/weapons.qc // TODO