Beyond 48 weapons, help is needed. (Code help) (ChaosEsqueAnthology) (Xonotic Mod)

Beyond 48 weapons, help is needed. (Code help) (ChaosEsqueAnthology) (Xonotic Mod)

chaosesqueteam's picture

In the Xonotic mod, ChaosEsque Anthology (https://sourceforge.net/p/chaosesqueanthology/discussion/general/thread/... ) help on the code is needed

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=chaosesq... )

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):
```
[code]
#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);
[/code]
```

How? I don't know, but if you do, please tell!