From: Mario Date: Wed, 12 Sep 2018 23:19:18 +0000 (+1000) Subject: Move item_key to mapobjects X-Git-Tag: xonotic-v0.8.5~1875 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=dba1eb2bfe3eb5fdfc8f1ef58eebab853734d27d;p=xonotic%2Fxonotic-data.pk3dir.git Move item_key to mapobjects --- diff --git a/qcsrc/common/mapobjects/misc/_mod.inc b/qcsrc/common/mapobjects/misc/_mod.inc index 498f6c521..c7f1619ad 100644 --- a/qcsrc/common/mapobjects/misc/_mod.inc +++ b/qcsrc/common/mapobjects/misc/_mod.inc @@ -2,5 +2,6 @@ #include #include #include +#include #include #include diff --git a/qcsrc/common/mapobjects/misc/_mod.qh b/qcsrc/common/mapobjects/misc/_mod.qh index 3415919f8..617db807b 100644 --- a/qcsrc/common/mapobjects/misc/_mod.qh +++ b/qcsrc/common/mapobjects/misc/_mod.qh @@ -2,5 +2,6 @@ #include #include #include +#include #include #include diff --git a/qcsrc/common/mapobjects/misc/keys.qc b/qcsrc/common/mapobjects/misc/keys.qc new file mode 100644 index 000000000..2c8574249 --- /dev/null +++ b/qcsrc/common/mapobjects/misc/keys.qc @@ -0,0 +1,292 @@ +#include "keys.qh" + +#ifdef CSQC +bool item_keys_usekey(entity l, entity p) +{ + int valid = (l.itemkeys & p.itemkeys); // TODO: itemkeys isn't networked or anything! + l.itemkeys &= ~valid; // only some of the needed keys were given + return valid != 0; +} +#endif + +#ifdef SVQC +/* +TODO: +- add an unlock sound (here to trigger_keylock and to func_door) +- display available keys on the HUD +- make more tests +- think about adding NOT_EASY/NOT_NORMAL/NOT_HARD for Q1 compatibility +- should keys have a trigger? +*/ + +bool item_keys_usekey(entity l, entity p) +{ + int valid = l.itemkeys & p.itemkeys; + + if (!valid) { + // player has none of the needed keys + return false; + } else if (l.itemkeys == valid) { + // ALL needed keys were given + l.itemkeys = 0; + return true; + } else { + // only some of the needed keys were given + l.itemkeys &= ~valid; + return true; + } +} + +string item_keys_keylist(float keylist) { + // no keys + if (!keylist) + return ""; + + // one key + if ((keylist & (keylist-1)) == 0) + return strcat("the ", item_keys_names[lowestbit(keylist)]); + + string n = ""; + int base = 0; + while (keylist) { + int l = lowestbit(keylist); + if (n) + n = strcat(n, ", the ", item_keys_names[base + l]); + else + n = strcat("the ", item_keys_names[base + l]); + + keylist = bitshift(keylist, -(l + 1)); + base+= l + 1; + } + + return n; +} + + +/* +================================ +item_key +================================ +*/ + +/** + * Key touch handler. + */ +void item_key_touch(entity this, entity toucher) +{ + if (!IS_PLAYER(toucher)) + return; + + // player already picked up this key + if (PS(toucher).itemkeys & this.itemkeys) + return; + + PS(toucher).itemkeys |= this.itemkeys; + play2(toucher, this.noise); + + centerprint(toucher, this.message); + + string oldmsg = this.message; + this.message = ""; + SUB_UseTargets(this, toucher, toucher); // TODO: should we be using toucher for the trigger here? + this.message = oldmsg; +} + +/** + * Spawn a key with given model, key code and color. + */ +void spawn_item_key(entity this) +{ + precache_model(this.model); + + if (this.spawnflags & 1) // FLOATING + this.noalign = 1; + + if (this.noalign) + set_movetype(this, MOVETYPE_NONE); + else + set_movetype(this, MOVETYPE_TOSS); + + precache_sound(this.noise); + + this.mdl = this.model; + this.effects = EF_LOWPRECISION; + _setmodel(this, this.model); + //setsize(this, '-16 -16 -24', '16 16 32'); + setorigin(this, this.origin + '0 0 32'); + setsize(this, '-16 -16 -56', '16 16 0'); + this.modelflags |= MF_ROTATE; + this.solid = SOLID_TRIGGER; + + if (!this.noalign) + { + // first nudge it off the floor a little bit to avoid math errors + setorigin(this, this.origin + '0 0 1'); + // note droptofloor returns false if stuck/or would fall too far + droptofloor(this); + } + + settouch(this, item_key_touch); +} + + +/*QUAKED item_key (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING +A key entity. +The itemkeys should contain one of the following key IDs: +1 - GOLD key - +2 - SILVER key +4 - BRONZE key +8 - RED keycard +16 - BLUE keycard +32 - GREEN keycard +Custom keys: +... - last key is 1<<23 +Keys with bigger Id than 32 don't have a default netname and model, if you use one of them, you MUST provide those. +-----------KEYS------------ +colormod: color of the key (default: '.9 .9 .9'). +itemkeys: a key Id. +message: message to print when player picks up this key. +model: custom key model to use. +netname: the display name of the key. +noise: custom sound to play when player picks up the key. +-------- SPAWNFLAGS -------- +FLOATING: the item will float in air, instead of aligning to the floor by falling +---------NOTES---------- +This is the only correct way to put keys on the map! + +itemkeys MUST always have exactly one bit set. +*/ +spawnfunc(item_key) +{ + string _netname; + vector _colormod; + + // reject this entity if more than one key was set! + if (this.itemkeys>0 && (this.itemkeys & (this.itemkeys-1)) != 0) { + objerror(this, "item_key.itemkeys must contain only 1 bit set specifying the key it represents!"); + delete(this); + return; + } + + // find default netname and colormod + switch(this.itemkeys) { + case BIT(0): + _netname = "GOLD key"; + _colormod = '1 .9 0'; + break; + + case BIT(1): + _netname = "SILVER key"; + _colormod = '.9 .9 .9'; + break; + + case BIT(2): + _netname = "BRONZE key"; + _colormod = '.6 .25 0'; + break; + + case BIT(3): + _netname = "RED keycard"; + _colormod = '.9 0 0'; + break; + + case BIT(4): + _netname = "BLUE keycard"; + _colormod = '0 0 .9'; + break; + + case BIT(5): + _netname = "GREEN keycard"; + _colormod = '0 .9 0'; + break; + + default: + _netname = "FLUFFY PINK keycard"; + _colormod = '1 1 1'; + + if (this.netname == "") { + objerror(this, "item_key doesn't have a default name for this key and a custom one was not specified!"); + delete(this); + return; + } + break; + + } + + // find default model + string _model = string_null; + if (this.itemkeys <= ITEM_KEY_BIT(2)) { + _model = "models/keys/key.md3"; + } else if (this.itemkeys >= ITEM_KEY_BIT(3) && this.itemkeys <= ITEM_KEY_BIT(5)) { + _model = "models/keys/key.md3"; // FIXME: replace it by a keycard model! + } else if (this.model == "") { + objerror(this, "item_key doesn't have a default model for this key and a custom one was not specified!"); + delete(this); + return; + } + + // set defailt netname + if (this.netname == "") + this.netname = _netname; + + // set default colormod + if (!this.colormod) + this.colormod = _colormod; + + // set default model + if (this.model == "") + this.model = _model; + + // set default pickup message + if (this.message == "") + this.message = strzone(strcat("You've picked up the ", this.netname, "!")); + + if (this.noise == "") + this.noise = strzone(SND(ITEMPICKUP)); + + // save the name for later + item_keys_names[lowestbit(this.itemkeys)] = this.netname; + + // put the key on the map + spawn_item_key(this); +} + +/*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING +SILVER key. +-----------KEYS------------ +colormod: color of the key (default: '.9 .9 .9'). +message: message to print when player picks up this key. +model: custom model to use. +noise: custom sound to play when player picks up the key. +-------- SPAWNFLAGS -------- +FLOATING: the item will float in air, instead of aligning to the floor by falling +---------NOTES---------- +Don't use this entity on new maps! Use item_key instead. +*/ +spawnfunc(item_key1) +{ + this.classname = "item_key"; + this.itemkeys = ITEM_KEY_BIT(1); + spawnfunc_item_key(this); +} + +/*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING +GOLD key. +-----------KEYS------------ +colormod: color of the key (default: '1 .9 0'). +message: message to print when player picks up this key. +model: custom model to use. +noise: custom sound to play when player picks up the key. +-------- SPAWNFLAGS -------- +FLOATING: the item will float in air, instead of aligning to the floor by falling +---------NOTES---------- +Don't use this entity on new maps! Use item_key instead. +*/ +spawnfunc(item_key2) +{ + this.classname = "item_key"; + this.itemkeys = ITEM_KEY_BIT(0); + spawnfunc_item_key(this); +} + +#endif diff --git a/qcsrc/common/mapobjects/misc/keys.qh b/qcsrc/common/mapobjects/misc/keys.qh new file mode 100644 index 000000000..50be5f8db --- /dev/null +++ b/qcsrc/common/mapobjects/misc/keys.qh @@ -0,0 +1,26 @@ +#pragma once + +/** + * Returns the bit ID of a key + */ +#define ITEM_KEY_BIT(n) ( bitshift(1, n) ) + +#define ITEM_KEY_MAX 24 + +/** + * list of key names. + */ +#ifdef SVQC +string item_keys_names[ITEM_KEY_MAX]; + +/** + * Use keys from p on l. + * Returns true if any new keys were given, false otherwise. + */ +float item_keys_usekey(entity l, entity p); + +/** + * Returns a string with a comma separated list of key names, as specified in keylist. + */ +string item_keys_keylist(float keylist); +#endif diff --git a/qcsrc/common/mapobjects/trigger/keylock.qc b/qcsrc/common/mapobjects/trigger/keylock.qc index 67db14421..f7ecd7c1f 100644 --- a/qcsrc/common/mapobjects/trigger/keylock.qc +++ b/qcsrc/common/mapobjects/trigger/keylock.qc @@ -30,7 +30,14 @@ void trigger_keylock_touch(entity this, entity toucher) // check silver key if(this.itemkeys) - key_used = item_keys_usekey(this, toucher); + { +#ifdef SVQC + entity store = PS(toucher); +#elif defined(CSQC) + entity store = toucher; +#endif + key_used = item_keys_usekey(this, store); + } if(this.itemkeys) { diff --git a/qcsrc/common/mapobjects/trigger/keylock.qh b/qcsrc/common/mapobjects/trigger/keylock.qh index 904c3fa3d..6f70f09be 100644 --- a/qcsrc/common/mapobjects/trigger/keylock.qh +++ b/qcsrc/common/mapobjects/trigger/keylock.qh @@ -1,10 +1 @@ #pragma once - -#ifdef CSQC -bool item_keys_usekey(entity l, entity p) -{ - int valid = (l.itemkeys & p.itemkeys); // TODO: itemkeys isn't networked or anything! - l.itemkeys &= ~valid; // only some of the needed keys were given - return valid != 0; -} -#endif diff --git a/qcsrc/common/mapobjects/triggers.qc b/qcsrc/common/mapobjects/triggers.qc index c7ed6643d..6a2095999 100644 --- a/qcsrc/common/mapobjects/triggers.qc +++ b/qcsrc/common/mapobjects/triggers.qc @@ -1,7 +1,4 @@ #include "triggers.qh" -#ifdef SVQC - #include -#endif void SUB_DontUseTargets(entity this, entity actor, entity trigger) { } diff --git a/qcsrc/server/_mod.inc b/qcsrc/server/_mod.inc index 429117ad0..2ec838695 100644 --- a/qcsrc/server/_mod.inc +++ b/qcsrc/server/_mod.inc @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/qcsrc/server/_mod.qh b/qcsrc/server/_mod.qh index 2bbfb7204..cc27baf12 100644 --- a/qcsrc/server/_mod.qh +++ b/qcsrc/server/_mod.qh @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/qcsrc/server/item_key.qc b/qcsrc/server/item_key.qc deleted file mode 100644 index 2bfdc49b7..000000000 --- a/qcsrc/server/item_key.qc +++ /dev/null @@ -1,287 +0,0 @@ -#include "item_key.qh" - -#include "../common/mapobjects/subs.qh" -#include -#include "../common/monsters/_mod.qh" -#include "../common/notifications/all.qh" -#include "../common/util.qh" -#include "../lib/warpzone/util_server.qh" - -/* -TODO: -- add an unlock sound (here to trigger_keylock and to func_door) -- display available keys on the HUD -- make more tests -- think about adding NOT_EASY/NOT_NORMAL/NOT_HARD for Q1 compatibility -- should keys have a trigger? -*/ - -bool item_keys_usekey(entity l, entity p) -{ - int valid = l.itemkeys & PS(p).itemkeys; - - if (!valid) { - // player has none of the needed keys - return false; - } else if (l.itemkeys == valid) { - // ALL needed keys were given - l.itemkeys = 0; - return true; - } else { - // only some of the needed keys were given - l.itemkeys &= ~valid; - return true; - } -} - -string item_keys_keylist(float keylist) { - // no keys - if (!keylist) - return ""; - - // one key - if ((keylist & (keylist-1)) == 0) - return strcat("the ", item_keys_names[lowestbit(keylist)]); - - string n = ""; - int base = 0; - while (keylist) { - int l = lowestbit(keylist); - if (n) - n = strcat(n, ", the ", item_keys_names[base + l]); - else - n = strcat("the ", item_keys_names[base + l]); - - keylist = bitshift(keylist, -(l + 1)); - base+= l + 1; - } - - return n; -} - - -/* -================================ -item_key -================================ -*/ - -/** - * Key touch handler. - */ -void item_key_touch(entity this, entity toucher) -{ - if (!IS_PLAYER(toucher)) - return; - - // player already picked up this key - if (PS(toucher).itemkeys & this.itemkeys) - return; - - PS(toucher).itemkeys |= this.itemkeys; - play2(toucher, this.noise); - - centerprint(toucher, this.message); - - string oldmsg = this.message; - this.message = ""; - SUB_UseTargets(this, toucher, toucher); // TODO: should we be using toucher for the trigger here? - this.message = oldmsg; -} - -/** - * Spawn a key with given model, key code and color. - */ -void spawn_item_key(entity this) -{ - precache_model(this.model); - - if (this.spawnflags & 1) // FLOATING - this.noalign = 1; - - if (this.noalign) - set_movetype(this, MOVETYPE_NONE); - else - set_movetype(this, MOVETYPE_TOSS); - - precache_sound(this.noise); - - this.mdl = this.model; - this.effects = EF_LOWPRECISION; - _setmodel(this, this.model); - //setsize(this, '-16 -16 -24', '16 16 32'); - setorigin(this, this.origin + '0 0 32'); - setsize(this, '-16 -16 -56', '16 16 0'); - this.modelflags |= MF_ROTATE; - this.solid = SOLID_TRIGGER; - - if (!this.noalign) - { - // first nudge it off the floor a little bit to avoid math errors - setorigin(this, this.origin + '0 0 1'); - // note droptofloor returns false if stuck/or would fall too far - droptofloor(this); - } - - settouch(this, item_key_touch); -} - - -/*QUAKED item_key (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING -A key entity. -The itemkeys should contain one of the following key IDs: -1 - GOLD key - -2 - SILVER key -4 - BRONZE key -8 - RED keycard -16 - BLUE keycard -32 - GREEN keycard -Custom keys: -... - last key is 1<<23 -Keys with bigger Id than 32 don't have a default netname and model, if you use one of them, you MUST provide those. ------------KEYS------------ -colormod: color of the key (default: '.9 .9 .9'). -itemkeys: a key Id. -message: message to print when player picks up this key. -model: custom key model to use. -netname: the display name of the key. -noise: custom sound to play when player picks up the key. --------- SPAWNFLAGS -------- -FLOATING: the item will float in air, instead of aligning to the floor by falling ----------NOTES---------- -This is the only correct way to put keys on the map! - -itemkeys MUST always have exactly one bit set. -*/ -spawnfunc(item_key) -{ - string _netname; - vector _colormod; - - // reject this entity if more than one key was set! - if (this.itemkeys>0 && (this.itemkeys & (this.itemkeys-1)) != 0) { - objerror(this, "item_key.itemkeys must contain only 1 bit set specifying the key it represents!"); - delete(this); - return; - } - - // find default netname and colormod - switch(this.itemkeys) { - case BIT(0): - _netname = "GOLD key"; - _colormod = '1 .9 0'; - break; - - case BIT(1): - _netname = "SILVER key"; - _colormod = '.9 .9 .9'; - break; - - case BIT(2): - _netname = "BRONZE key"; - _colormod = '.6 .25 0'; - break; - - case BIT(3): - _netname = "RED keycard"; - _colormod = '.9 0 0'; - break; - - case BIT(4): - _netname = "BLUE keycard"; - _colormod = '0 0 .9'; - break; - - case BIT(5): - _netname = "GREEN keycard"; - _colormod = '0 .9 0'; - break; - - default: - _netname = "FLUFFY PINK keycard"; - _colormod = '1 1 1'; - - if (this.netname == "") { - objerror(this, "item_key doesn't have a default name for this key and a custom one was not specified!"); - delete(this); - return; - } - break; - - } - - // find default model - string _model = string_null; - if (this.itemkeys <= ITEM_KEY_BIT(2)) { - _model = "models/keys/key.md3"; - } else if (this.itemkeys >= ITEM_KEY_BIT(3) && this.itemkeys <= ITEM_KEY_BIT(5)) { - _model = "models/keys/key.md3"; // FIXME: replace it by a keycard model! - } else if (this.model == "") { - objerror(this, "item_key doesn't have a default model for this key and a custom one was not specified!"); - delete(this); - return; - } - - // set defailt netname - if (this.netname == "") - this.netname = _netname; - - // set default colormod - if (!this.colormod) - this.colormod = _colormod; - - // set default model - if (this.model == "") - this.model = _model; - - // set default pickup message - if (this.message == "") - this.message = strzone(strcat("You've picked up the ", this.netname, "!")); - - if (this.noise == "") - this.noise = strzone(SND(ITEMPICKUP)); - - // save the name for later - item_keys_names[lowestbit(this.itemkeys)] = this.netname; - - // put the key on the map - spawn_item_key(this); -} - -/*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING -SILVER key. ------------KEYS------------ -colormod: color of the key (default: '.9 .9 .9'). -message: message to print when player picks up this key. -model: custom model to use. -noise: custom sound to play when player picks up the key. --------- SPAWNFLAGS -------- -FLOATING: the item will float in air, instead of aligning to the floor by falling ----------NOTES---------- -Don't use this entity on new maps! Use item_key instead. -*/ -spawnfunc(item_key1) -{ - this.classname = "item_key"; - this.itemkeys = ITEM_KEY_BIT(1); - spawnfunc_item_key(this); -} - -/*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32) FLOATING -GOLD key. ------------KEYS------------ -colormod: color of the key (default: '1 .9 0'). -message: message to print when player picks up this key. -model: custom model to use. -noise: custom sound to play when player picks up the key. --------- SPAWNFLAGS -------- -FLOATING: the item will float in air, instead of aligning to the floor by falling ----------NOTES---------- -Don't use this entity on new maps! Use item_key instead. -*/ -spawnfunc(item_key2) -{ - this.classname = "item_key"; - this.itemkeys = ITEM_KEY_BIT(0); - spawnfunc_item_key(this); -} diff --git a/qcsrc/server/item_key.qh b/qcsrc/server/item_key.qh deleted file mode 100644 index 50be5f8db..000000000 --- a/qcsrc/server/item_key.qh +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -/** - * Returns the bit ID of a key - */ -#define ITEM_KEY_BIT(n) ( bitshift(1, n) ) - -#define ITEM_KEY_MAX 24 - -/** - * list of key names. - */ -#ifdef SVQC -string item_keys_names[ITEM_KEY_MAX]; - -/** - * Use keys from p on l. - * Returns true if any new keys were given, false otherwise. - */ -float item_keys_usekey(entity l, entity p); - -/** - * Returns a string with a comma separated list of key names, as specified in keylist. - */ -string item_keys_keylist(float keylist); -#endif