From: TimePath Date: Sun, 10 May 2015 09:19:51 +0000 (+1000) Subject: Initial item system setup X-Git-Tag: xonotic-v0.8.1~53^2~18 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=c11cbc96e9310e51bdcbf0f7e04f22bd4bd0d511;p=xonotic%2Fxonotic-data.pk3dir.git Initial item system setup --- diff --git a/qcsrc/client/main.qc b/qcsrc/client/main.qc index 5343c180c..ad727bf41 100644 --- a/qcsrc/client/main.qc +++ b/qcsrc/client/main.qc @@ -39,6 +39,8 @@ #include "../common/stats.qh" #include "../common/teams.qh" +#include "../common/items/all.qh" + #include "../common/weapons/weapons.qh" #include "../csqcmodellib/cl_model.qh" @@ -136,6 +138,7 @@ void CSQC_Init(void) // 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); diff --git a/qcsrc/client/progs.src b/qcsrc/client/progs.src index 36d159c75..5fbff743d 100644 --- a/qcsrc/client/progs.src +++ b/qcsrc/client/progs.src @@ -55,6 +55,8 @@ weapons/projectile.qc // TODO ../common/urllib.qc ../common/util.qc +../common/items/all.qc + ../common/monsters/monsters.qc ../common/weapons/weapons.qc // TODO diff --git a/qcsrc/common/items/all.inc b/qcsrc/common/items/all.inc new file mode 100644 index 000000000..24f795572 --- /dev/null +++ b/qcsrc/common/items/all.inc @@ -0,0 +1,4 @@ +#include "item.qc" + +#include "item/ammo.qc" +#include "item/buff.qc" diff --git a/qcsrc/common/items/all.qc b/qcsrc/common/items/all.qc new file mode 100644 index 000000000..1700ae9fb --- /dev/null +++ b/qcsrc/common/items/all.qc @@ -0,0 +1,11 @@ +#include "all.qh" + +#include "all.inc" + +void ItemTest() +{ + ITEMS_FOREACH(it != NULL, LAMBDA({ + print(strcat(etos(it), "\n")); + ITEM_SEND(Default, it); + })); +} diff --git a/qcsrc/common/items/all.qh b/qcsrc/common/items/all.qh new file mode 100644 index 000000000..74ca110ef --- /dev/null +++ b/qcsrc/common/items/all.qh @@ -0,0 +1,38 @@ +#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 diff --git a/qcsrc/common/items/item.qc b/qcsrc/common/items/item.qc new file mode 100644 index 000000000..a8cf566d7 --- /dev/null +++ b/qcsrc/common/items/item.qc @@ -0,0 +1,11 @@ +#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; + } +} diff --git a/qcsrc/common/items/item.qh b/qcsrc/common/items/item.qh new file mode 100644 index 000000000..cf2779aa0 --- /dev/null +++ b/qcsrc/common/items/item.qh @@ -0,0 +1,38 @@ +#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 diff --git a/qcsrc/common/items/item/ammo.qc b/qcsrc/common/items/item/ammo.qc new file mode 100644 index 000000000..5868eeb84 --- /dev/null +++ b/qcsrc/common/items/item/ammo.qc @@ -0,0 +1,18 @@ +#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; + } +} diff --git a/qcsrc/common/items/item/ammo.qh b/qcsrc/common/items/item/ammo.qh new file mode 100644 index 000000000..412ccc2d2 --- /dev/null +++ b/qcsrc/common/items/item/ammo.qh @@ -0,0 +1,8 @@ +#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 diff --git a/qcsrc/common/items/item/buff.qc b/qcsrc/common/items/item/buff.qc new file mode 100644 index 000000000..479df881f --- /dev/null +++ b/qcsrc/common/items/item/buff.qc @@ -0,0 +1,13 @@ +#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; + } +} diff --git a/qcsrc/common/items/item/buff.qh b/qcsrc/common/items/item/buff.qh new file mode 100644 index 000000000..6b48b1fba --- /dev/null +++ b/qcsrc/common/items/item/buff.qh @@ -0,0 +1,7 @@ +#ifndef BUFF_H +#define BUFF_H +#include "../item.qh" +CLASS(Buff, GameItem) + METHOD(Buff, respondTo, bool(entity, int)) +ENDCLASS(Buff) +#endif diff --git a/qcsrc/common/oo.qh b/qcsrc/common/oo.qh new file mode 100644 index 000000000..02f992a34 --- /dev/null +++ b/qcsrc/common/oo.qh @@ -0,0 +1,71 @@ +#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 diff --git a/qcsrc/menu/menu.qc b/qcsrc/menu/menu.qc index 669e08fe7..50183b977 100644 --- a/qcsrc/menu/menu.qc +++ b/qcsrc/menu/menu.qc @@ -2,6 +2,7 @@ #include "oo/classes.qc" #include "xonotic/util.qh" +#include "../common/items/all.qh" #include "../common/weapons/weapons.qh" #include "../common/mapinfo.qh" @@ -80,6 +81,7 @@ void m_init() // 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(); diff --git a/qcsrc/menu/oo/base.qh b/qcsrc/menu/oo/base.qh index 5c74f0d6d..28b87ab7f 100644 --- a/qcsrc/menu/oo/base.qh +++ b/qcsrc/menu/oo/base.qh @@ -1,71 +1,11 @@ #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 diff --git a/qcsrc/menu/progs.src b/qcsrc/menu/progs.src index abfb303db..124ac9db7 100644 --- a/qcsrc/menu/progs.src +++ b/qcsrc/menu/progs.src @@ -21,6 +21,8 @@ xonotic/util.qc ../common/urllib.qc ../common/util.qc +../common/items/all.qc + ../common/monsters/monsters.qc ../common/weapons/weapons.qc // TODO diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index 82a81776a..63f2db883 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -32,6 +32,7 @@ #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; @@ -556,6 +557,7 @@ void spawnfunc___init_dedicated_server(void) // 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); @@ -604,6 +606,7 @@ void spawnfunc_worldspawn (void) // 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); diff --git a/qcsrc/server/progs.src b/qcsrc/server/progs.src index 20b28a410..0455f6b6b 100644 --- a/qcsrc/server/progs.src +++ b/qcsrc/server/progs.src @@ -107,6 +107,9 @@ weapons/weaponsystem.qc ../common/test.qc ../common/urllib.qc ../common/util.qc + +../common/items/all.qc + ../common/weapons/config.qc ../common/weapons/weapons.qc // TODO