The current code allows up to 48 weapons. With the addition of the morgenstern 48 weapons have been reached (no, weapons will not be removed to make way for others).
Divverent, of Xonotic, Nexuiz, and Darkplaces fame, created the macro code to support 48 weapons. This was an extension of the previous 24 weapon code. When I last talked to him he said that a further extension was trivial, simply follow the pattern of the existing macro code and extend it.
The problem comes from a simple fact that I, and perhaps others, have come to realize is unbreachable: I, your host, am simply not very smart. There are many things I cannot fathom. I get by by sticking to one thing and hammering away at it untill I understand it enough. It took me four years to learn quake C sufficiently to effortlessly move around the code without frustration. Four years.
That is a long time for learning a programming language.
The code that needs to be extended resides in the common directory of the quake C source, specifically the items header file:
qcsrc/common/items.qh
The code block in question starts at line 93, but note, the code that the anthology uses starts at line 127, note the maxcount 48 (we are using two weapon sets here, we need to extend it to three to add more weapons):
define WEPSET_OP1_EE(a,b,mergeop,x) (((a)._WS1_weapons x (b)._WS1_weapons) mergeop ((a)._WS2_weapons x (b)._WS2_weapons))
define WEPSET_OP2_EE(a,b,mergeop,x,y) (((a)._WS1_weapons x (b)._WS1_weapons y (a)._WS1_weapons) mergeop ((a)._WS2_weapons x (b)._WS2_weapons y (a)._WS2_weapons))
define WEPSET_OP1_EA(a,b,mergeop,x) (((a).WS1_weapons x _WS1##b) mergeop ((a).WS2_weapons x _WS2##b))
define WEPSET_OP2_EA(a,b,mergeop,x,y) (((a).WS1_weapons x _WS1##b y (a).WS1_weapons) mergeop ((a)._WS2_weapons x _WS2##b y (a)._WS2_weapons))
define WEPSET_OP1_EW(a,b,mergeop,x) (((a)._WS1_weapons x WEPSET_BIT1(b)) mergeop ((a)._WS2_weapons x WEPSET_BIT2(b)))
define WEPSET_OP2_EW(a,b,mergeop,x,y) (((a)._WS1_weapons x WEPSET_BIT1(b) y (a)._WS1_weapons) mergeop ((a)._WS2_weapons x WEPSET_BIT2(b) y (a)._WS2_weapons))
define WEPSET_OP1_AE(a,b,mergeop,x) ((WS1##a x (b).WS1_weapons) mergeop (_WS2##a x (b)._WS2_weapons))
define WEPSET_OP2_AE(a,b,mergeop,x,y) ((WS1##a x (b).WS1_weapons y _WS1##a) mergeop (WS2##a x (b).WS2_weapons y _WS2##a))
define WEPSET_OP1_AA(a,b,mergeop,x) ((WS1##a x WS1##b) mergeop (WS2##a x WS2##b))
define WEPSET_OP2_AA(a,b,mergeop,x,y) ((WS1##a x WS1##b y WS1##a) mergeop (WS2##a x WS2##b y WS2##a))
define WEPSET_OP1_AW(a,b,mergeop,x) ((WS1##a x WEPSET_BIT1(b)) mergeop (WS2##a x WEPSET_BIT2(b)))
define WEPSET_OP2_AW(a,b,mergeop,x,y) ((WS1##a x WEPSET_BIT1(b) y WS1##a) mergeop (WS2##a x WEPSET_BIT2(b) y WS2##a))
Another file that will need to be edited is the file with the weapon reload code it seems:
near the end of string W_ThrowNewWeapon( in
(line 278 on)
qcsrc/server/cl_weapons.qc [code]
else if(doreduce)
{
for(i = 0, j = 1; i < 24; ++i, j *= 2)
{
if(wa & j)
{
ammofield = Item_CounterField(j);
//ifourweaponisloaded,giveitsloadbacktotheplayerif(self.(weapon_load[self.weapon])>0){own.ammofield+=self.(weapon_load[self.weapon]);self.(weapon_load[self.weapon])=-1;//scheduletheweaponforreloading}thisammo=min(own.ammofield,wep.ammofield);wep.ammofield=thisammo;own.ammofield-=thisammo;s=strcat(s," and ",ftos(thisammo)," ",Item_CounterFieldName(j));}}s=substring(s,5,-1);}
[/code]
the i < 24 stuff, will probably need an aditionally i < 48 if that's possile in qc for loops
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
We can't just drop in replacement, as the code has diverged. We must study the two and apply what we learn.
(The engine has diverged too, ex: more recent darkplaces engines do not support iqm as fully as older ones, complex iqm models exported by the official exporter show up invisible in modern darkplaces engine and water reflections don't seem to work right on bleeding edge DarkPlaces on intel gfx chips,so we stick with the slightly older branch of darkplaces and backport things for the source and linux compiles)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I would like to add a katana, shriukens, and a desert eagle to the game,
however more weapons slots are needed. Last time I talked to the German main
developer of Nexuiz and Xonotic he said to extend the system, when needed
was not difficult.
However it is beyond me because I am not terribly smart. I can work within
a system, but cannot surpass even the simplest of limits. That is in everything.
The programmer that originated the bitshifting weapon code is Divverent of Nexuiz
and Xonotic. He is often busy with his job and family so it is difficult to
contact him (I've only been able to maybe once a year these days).
(The bitshifting code is needed for compatability with fteqcc quake C compiler)
Other people who might be able to figure it out and how to extend the code
reside on the anynet.org irc server in #qc and #darkplaces. And on the quakenet.org
irc server on various #xonotic channels (maybe #nexuiz too). Also any channel
associated with fte quake engine might also be useful.
Could some of you, here, perhaps ask them. My scheduel is such that I and they are
rarely on at the same time so I can't communicate with them effectivly.
I very much wish to add more weapons.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The current code allows up to 48 weapons. With the addition of the morgenstern 48 weapons have been reached (no, weapons will not be removed to make way for others).
Divverent, of Xonotic, Nexuiz, and Darkplaces fame, created the macro code to support 48 weapons. This was an extension of the previous 24 weapon code. When I last talked to him he said that a further extension was trivial, simply follow the pattern of the existing macro code and extend it.
The problem comes from a simple fact that I, and perhaps others, have come to realize is unbreachable: I, your host, am simply not very smart. There are many things I cannot fathom. I get by by sticking to one thing and hammering away at it untill I understand it enough. It took me four years to learn quake C sufficiently to effortlessly move around the code without frustration. Four years.
That is a long time for learning a programming language.
The code that needs to be extended resides in the common directory of the quake C source, specifically the items header file:
qcsrc/common/items.qh
(accessable by web git if you wish here: http://chaosesqueanthology.git.sourceforge.net/git/gitweb.cgi?p=chaosesqueanthology/xonotic-data.pk3dir;a=blob_plain;f=qcsrc/common/items.qh;hb=HEAD )
The code block in question starts at line 93, but note, the code that the anthology uses starts at line 127, note the maxcount 48 (we are using two weapon sets here, we need to extend it to three to add more weapons):
[quote]
define WEP_FIRST 1
float WEP_COUNT;
float WEP_LAST;
if 0
define WEP_MAXCOUNT 24
// default storage
.float _WS_weapons;
define WEPSET_BIT(a) power2of((a) - WEP_FIRST)
define WEPSET_DECLARE_A(a) float WS##a
define WEPSET_CLEAR_E(e) ((e)._WS_weapons = 0)
define WEPSET_CLEAR_A(a) (WS##a = 0)
define WEPSET_EMPTY_E(e) ((e)._WS_weapons == 0)
define WEPSET_EMPTY_A(a) (WS##a == 0)
define WEPSET_COPY_AS(a) (WS##a = getstati(STAT_WEAPONS))
define WEPSET_ADDSTAT() addstat(STAT_WEAPONS, AS_INT, _WS_weapons)
define WEPSET_WRITE_E(dest,a) WriteInt24_t(dest, (a)._WS_weapons)
define WEPSET_WRITE_A(dest,a) WriteInt24_t(dest, WS##a)
define WEPSET_WRITE_W(dest,a) WriteInt24_t(dest, WEPSET_BIT(a))
define WEPSET_READ_E(a) (a)._WS_weapons = ReadInt24_t()
define WEPSET_READ_A(a) (WS##a) = ReadInt24_t()
define WEPSET_OP1_EE(a,b,mergeop,x) ((a)._WS_weapons x (b)._WS_weapons)
define WEPSET_OP2_EE(a,b,mergeop,x,y) ((a)._WS_weapons x (b)._WS_weapons y (a)._WS_weapons)
define WEPSET_OP1_EA(a,b,mergeop,x) ((a).WS_weapons x _WS##b)
define WEPSET_OP2_EA(a,b,mergeop,x,y) ((a).WS_weapons x _WS##b y (a)._WS_weapons)
define WEPSET_OP1_EW(a,b,mergeop,x) ((a)._WS_weapons x WEPSET_BIT(b))
define WEPSET_OP2_EW(a,b,mergeop,x,y) ((a)._WS_weapons x WEPSET_BIT(b) y (a)._WS_weapons)
define WEPSET_OP1_AE(a,b,mergeop,x) (WS##a x (b)._WS_weapons)
define WEPSET_OP2_AE(a,b,mergeop,x,y) (WS##a x (b).WS_weapons y _WS##a)
define WEPSET_OP1_AA(a,b,mergeop,x) (WS##a x WS##b)
define WEPSET_OP2_AA(a,b,mergeop,x,y) (WS##a x WS##b y WS##a)
define WEPSET_OP1_AW(a,b,mergeop,x) (WS##a x WEPSET_BIT(b))
define WEPSET_OP2_AW(a,b,mergeop,x,y) (WS##a x WEPSET_BIT(b) y WS##a)
else
define WEP_MAXCOUNT 48
define WEP_FIRST2 25
.float _WS1_weapons;
.float _WS2_weapons;
define WEPSET_BIT1(a) (((a) < WEP_FIRST2) ? power2of((a) - WEP_FIRST) : 0)
define WEPSET_BIT2(a) (((a) >= WEP_FIRST2) ? power2of((a) - WEP_FIRST2) : 0)
define WEPSET_DECLARE_A(a) float WS1##a, WS2##a
define WEPSET_CLEAR_E(e) ((e)._WS1_weapons = (e)._WS2_weapons = 0)
define WEPSET_CLEAR_A(a) ((WS1##a) = (WS2##a) = 0)
define WEPSET_EMPTY_E(e) ((e)._WS1_weapons == 0 && (e)._WS2_weapons == 0)
define WEPSET_EMPTY_A(a) ((WS1##a) == 0 && (WS2##a) == 0)
define WEPSET_COPY_AS(a) ((WS1##a) = getstati(STAT_WEAPONS), (WS2##a) = getstati(STAT_WEAPONS2))
define WEPSET_ADDSTAT() addstat(STAT_WEAPONS, AS_INT, _WS1_weapons); addstat(STAT_WEAPONS2, AS_INT, _WS2_weapons)
define WEPSET_WRITE_E(dest,a) WriteInt24_t(dest, (a)._WS1_weapons); WriteInt24_t(dest, (a)._WS2_weapons)
define WEPSET_WRITE_A(dest,a) WriteInt24_t(dest, WS1##a); WriteInt24_t(dest, WS2##a)
define WEPSET_WRITE_W(dest,a) WriteInt24_t(dest, WEPSET_BIT1(a)); WriteInt24_t(dest, WEPSET_BIT2(a))
define WEPSET_READ_E(a) (a)._WS1_weapons = ReadInt24_t(); (a)._WS2_weapons = ReadInt24_t()
define WEPSET_READ_A(a) (WS1##a) = ReadInt24_t(); (WS2##a) = ReadInt24_t()
define WEPSET_OP1_EE(a,b,mergeop,x) (((a)._WS1_weapons x (b)._WS1_weapons) mergeop ((a)._WS2_weapons x (b)._WS2_weapons))
define WEPSET_OP2_EE(a,b,mergeop,x,y) (((a)._WS1_weapons x (b)._WS1_weapons y (a)._WS1_weapons) mergeop ((a)._WS2_weapons x (b)._WS2_weapons y (a)._WS2_weapons))
define WEPSET_OP1_EA(a,b,mergeop,x) (((a).WS1_weapons x _WS1##b) mergeop ((a).WS2_weapons x _WS2##b))
define WEPSET_OP2_EA(a,b,mergeop,x,y) (((a).WS1_weapons x _WS1##b y (a).WS1_weapons) mergeop ((a)._WS2_weapons x _WS2##b y (a)._WS2_weapons))
define WEPSET_OP1_EW(a,b,mergeop,x) (((a)._WS1_weapons x WEPSET_BIT1(b)) mergeop ((a)._WS2_weapons x WEPSET_BIT2(b)))
define WEPSET_OP2_EW(a,b,mergeop,x,y) (((a)._WS1_weapons x WEPSET_BIT1(b) y (a)._WS1_weapons) mergeop ((a)._WS2_weapons x WEPSET_BIT2(b) y (a)._WS2_weapons))
define WEPSET_OP1_AE(a,b,mergeop,x) ((WS1##a x (b).WS1_weapons) mergeop (_WS2##a x (b)._WS2_weapons))
define WEPSET_OP2_AE(a,b,mergeop,x,y) ((WS1##a x (b).WS1_weapons y _WS1##a) mergeop (WS2##a x (b).WS2_weapons y _WS2##a))
define WEPSET_OP1_AA(a,b,mergeop,x) ((WS1##a x WS1##b) mergeop (WS2##a x WS2##b))
define WEPSET_OP2_AA(a,b,mergeop,x,y) ((WS1##a x WS1##b y WS1##a) mergeop (WS2##a x WS2##b y WS2##a))
define WEPSET_OP1_AW(a,b,mergeop,x) ((WS1##a x WEPSET_BIT1(b)) mergeop (WS2##a x WEPSET_BIT2(b)))
define WEPSET_OP2_AW(a,b,mergeop,x,y) ((WS1##a x WEPSET_BIT1(b) y WS1##a) mergeop (WS2##a x WEPSET_BIT2(b) y WS2##a))
endif
define XX ,
define WEPSET_COPY_EE(a,b) WEPSET_OP1_EE(a,b,XX,=)
define WEPSET_EQ_EE(a,b) WEPSET_OP1_EE(a,b,&&,==)
define WEPSET_OR_EE(a,b) WEPSET_OP1_EE(a,b,XX,|=)
define WEPSET_AND_EE(a,b) WEPSET_OP2_EE(a,b,XX,=,&)
define WEPSET_ANDNOT_EE(a,b) WEPSET_OP1_EE(a,b,XX,&~=)
define WEPSET_CONTAINS_ANY_EE(a,b) !!(WEPSET_OP1_EE(a,b,||,&))
define WEPSET_CONTAINS_ALL_EE(a,b) WEPSET_OP2_EE(b,a,&&,==,&)
define WEPSET_COPY_EA(a,b) WEPSET_OP1_EA(a,b,XX,=)
define WEPSET_EQ_EA(a,b) WEPSET_OP1_EA(a,b,&&,==)
define WEPSET_OR_EA(a,b) WEPSET_OP1_EA(a,b,XX,|=)
define WEPSET_AND_EA(a,b) WEPSET_OP2_EA(a,b,XX,=,&)
define WEPSET_ANDNOT_EA(a,b) WEPSET_OP1_EA(a,b,XX,&~=)
define WEPSET_CONTAINS_ANY_EA(a,b) !!(WEPSET_OP1_EA(a,b,||,&))
define WEPSET_CONTAINS_ALL_EA(a,b) WEPSET_OP2_EA(b,a,&&,==,&)
define WEPSET_COPY_EW(a,b) WEPSET_OP1_EW(a,b,XX,=)
define WEPSET_EQ_EW(a,b) WEPSET_OP1_EW(a,b,&&,==)
define WEPSET_OR_EW(a,b) WEPSET_OP1_EW(a,b,XX,|=)
define WEPSET_AND_EW(a,b) WEPSET_OP2_EW(a,b,XX,=,&)
define WEPSET_ANDNOT_EW(a,b) WEPSET_OP1_EW(a,b,XX,&~=)
define WEPSET_CONTAINS_EW(a,b) !!(WEPSET_OP1_EW(a,b,||,&))
define WEPSET_COPY_AE(a,b) WEPSET_OP1_AE(a,b,XX,=)
define WEPSET_EQ_AE(a,b) WEPSET_OP1_AE(a,b,&&,==)
define WEPSET_OR_AE(a,b) WEPSET_OP1_AE(a,b,XX,|=)
define WEPSET_AND_AE(a,b) WEPSET_OP2_AE(a,b,XX,=,&)
define WEPSET_ANDNOT_AE(a,b) WEPSET_OP1_AE(a,b,XX,&~=)
define WEPSET_CONTAINS_ANY_AE(a,b) !!(WEPSET_OP1_AE(a,b,||,&))
define WEPSET_CONTAINS_ALL_AE(a,b) WEPSET_OP2_AE(b,a,&&,==,&)
define WEPSET_COPY_AA(a,b) WEPSET_OP1_AA(a,b,XX,=)
define WEPSET_EQ_AA(a,b) WEPSET_OP1_AA(a,b,&&,==)
define WEPSET_OR_AA(a,b) WEPSET_OP1_AA(a,b,XX,|=)
define WEPSET_AND_AA(a,b) WEPSET_OP2_AA(a,b,XX,=,&)
define WEPSET_ANDNOT_AA(a,b) WEPSET_OP1_AA(a,b,XX,&~=)
define WEPSET_CONTAINS_ANY_AA(a,b) !!(WEPSET_OP1_AA(a,b,||,&))
define WEPSET_CONTAINS_ALL_AA(a,b) WEPSET_OP2_AA(b,a,&&,==,&)
define WEPSET_COPY_AW(a,b) WEPSET_OP1_AW(a,b,XX,=)
define WEPSET_EQ_AW(a,b) WEPSET_OP1_AW(a,b,&&,==)
define WEPSET_OR_AW(a,b) WEPSET_OP1_AW(a,b,XX,|=)
define WEPSET_AND_AW(a,b) WEPSET_OP2_AW(a,b,XX,=,&)
define WEPSET_ANDNOT_AW(a,b) WEPSET_OP1_AW(a,b,XX,&~=)
define WEPSET_CONTAINS_AW(a,b) !!(WEPSET_OP1_AW(a,b,||,&))
WEPSET_DECLARE_A(WEPBIT_ALL);
WEPSET_DECLARE_A(WEPBIT_SUPERWEAPONS);
// note: the fabs call is just there to hide "if result is constant" warning
#define REGISTER_WEAPON_2(id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname) \
float id; \
float func(float); \
void RegisterWeapons_##id() \
{ \
WEP_LAST = (id = WEP_FIRST + WEP_COUNT); \
WEPSET_OR_AW(WEPBIT_ALL, id); \
if(fabs(weapontype & WEP_FLAG_SUPERWEAPON)) \
WEPSET_OR_AW(WEPBIT_SUPERWEAPONS, id); \
++WEP_COUNT; \
register_weapon(id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname); \
} \
ACCUMULATE_FUNCTION(RegisterWeapons, RegisterWeapons_##id)
ifdef MENUQC
#define REGISTER_WEAPON(id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname) \
REGISTER_WEAPON_2(WEP_##id,w_null,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname)
else
#define REGISTER_WEAPON(id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname) \
REGISTER_WEAPON_2(WEP_##id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname)
endif
include "../server/w_all.qc"
undef REGISTER_WEAPON
ACCUMULATE_FUNCTION(RegisterWeapons, register_weapons_done)
string W_FixWeaponOrder(string order, float complete);
string W_NumberWeaponOrder(string order);
string W_NameWeaponOrder(string order);
string W_FixWeaponOrder_BuildImpulseList(string o);
string W_FixWeaponOrder_AllowIncomplete(string order);
string W_FixWeaponOrder_ForceComplete(string order);
void W_RandomWeapons(entity e, float n);
[/quote]
How? I don't know, but if you do, please tell!
Another file that will need to be edited is the file with the weapon reload code it seems:
near the end of string W_ThrowNewWeapon( in
(line 278 on)
qcsrc/server/cl_weapons.qc
[code]
else if(doreduce)
{
for(i = 0, j = 1; i < 24; ++i, j *= 2)
{
if(wa & j)
{
ammofield = Item_CounterField(j);
[/code]
the i < 24 stuff, will probably need an aditionally i < 48 if that's possile in qc for loops
http://dev.xonotic.org/issues/1968
At some point Xonotic added support for 72 weapons (though they use only about 15, so this is for mods).
We need to look at their code and add what is needed to the code we are using.
(ex: another addstat for a 3rd weaponset, probably changes to the statistics code too)
http://git.xonotic.org/?p=xonotic/xonotic-data.pk3dir.git;a=blob;f=qcsrc/common/items.qh;h=264c9ca73bd56070b6a41d69e0a359ea0f1503db;hb=HEAD;js=1
http://git.xonotic.org/?p=xonotic/xonotic-data.pk3dir.git;a=blob;f=qcsrc/common/items.qc;h=19173079fa0f1b1b198323c3d6a1b1f7c61e8b7f;hb=HEAD;js=1
VS code we are using:
http://chaosesqueanthology.git.sourceforge.net/git/gitweb.cgi?p=chaosesqueanthology/xonotic-data.pk3dir;a=blob;f=qcsrc/common/items.qh;h=7108f50b51165c656aad9f1e9b7f1c0a6a1dc757;hb=HEADp=chaosesqueanthology/xonotic-data.pk3dir;a=blob;f=qcsrc/common/items.qh;h=7108f50b51165c656aad9f1e9b7f1c0a6a1dc757;hb=HEAD
We can't just drop in replacement, as the code has diverged. We must study the two and apply what we learn.
(The engine has diverged too, ex: more recent darkplaces engines do not support iqm as fully as older ones, complex iqm models exported by the official exporter show up invisible in modern darkplaces engine and water reflections don't seem to work right on bleeding edge DarkPlaces on intel gfx chips,so we stick with the slightly older branch of darkplaces and backport things for the source and linux compiles)
I would like to add a katana, shriukens, and a desert eagle to the game,
however more weapons slots are needed. Last time I talked to the German main
developer of Nexuiz and Xonotic he said to extend the system, when needed
was not difficult.
However it is beyond me because I am not terribly smart. I can work within
a system, but cannot surpass even the simplest of limits. That is in everything.
The programmer that originated the bitshifting weapon code is Divverent of Nexuiz
and Xonotic. He is often busy with his job and family so it is difficult to
contact him (I've only been able to maybe once a year these days).
(The bitshifting code is needed for compatability with fteqcc quake C compiler)
Other people who might be able to figure it out and how to extend the code
reside on the anynet.org irc server in #qc and #darkplaces. And on the quakenet.org
irc server on various #xonotic channels (maybe #nexuiz too). Also any channel
associated with fte quake engine might also be useful.
Could some of you, here, perhaps ask them. My scheduel is such that I and they are
rarely on at the same time so I can't communicate with them effectivly.
I very much wish to add more weapons.
Divverent came through. We now have a third weaponset, and the knowlege to extend it when we need to.
The third weaponset gives us a max weapons of 72.
Just added a katana as the 49th weapon.
Sirs where to find camel porn