]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
More cleanup, make it compile now
authorSamual Lenks <samual@xonotic.org>
Mon, 10 Jun 2013 23:22:05 +0000 (19:22 -0400)
committerSamual Lenks <samual@xonotic.org>
Mon, 10 Jun 2013 23:22:05 +0000 (19:22 -0400)
14 files changed:
qcsrc/client/progs.src
qcsrc/common/explosion_equation.qc [deleted file]
qcsrc/common/explosion_equation.qh [deleted file]
qcsrc/common/items.qc [deleted file]
qcsrc/common/items.qh [deleted file]
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/common/weapons/all.qh [new file with mode: 0644]
qcsrc/common/weapons/calculations.qc [new file with mode: 0644]
qcsrc/common/weapons/calculations.qh [new file with mode: 0644]
qcsrc/common/weapons/weapons.qc [new file with mode: 0644]
qcsrc/common/weapons/weapons.qh
qcsrc/menu/progs.src
qcsrc/server/progs.src

index e409f7749bd5732e2cadf0be2af2bcf98d19a738..c12f308475eb3868fbdeccf81928de370923a8a7 100644 (file)
@@ -17,8 +17,7 @@ Defs.qc
 ../common/teams.qh
 ../common/util.qh
 ../common/counting.qh
-../common/items.qh
-../common/explosion_equation.qh
+../common/weapons/weapons.qh // TODO
 ../common/mapinfo.qh
 ../common/command/markup.qh
 ../common/command/rpn.qh
@@ -105,9 +104,7 @@ noise.qc
 ../common/command/rpn.qc
 ../common/command/generic.qc
 ../common/mapinfo.qc
-../common/items.qc
-../server/weapons/w_all.qc
-../common/explosion_equation.qc
+../common/weapons/weapons.qc // TODO
 ../common/urllib.qc
 command/cl_cmd.qc
 
diff --git a/qcsrc/common/explosion_equation.qc b/qcsrc/common/explosion_equation.qc
deleted file mode 100644 (file)
index df71154..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-float explosion_calcpush_getmultiplier(vector explosion_v, vector target_v)
-{
-       float a;
-       a  = explosion_v * (explosion_v - target_v);
-
-       if(a <= 0)
-               // target is too fast to be hittable by this
-               return 0;
-
-       a /= (explosion_v * explosion_v);
-               // we know we can divide by this, or above a would be == 0
-
-       return a;
-}
-
-#if 0
-vector explosion_calcpush(vector explosion_v, float explosion_m, vector target_v, float target_m, float elasticity)
-{
-       // solution of the equations:
-       //    v'                = v + a vp             // central hit
-       //    m*v'   + mp*vp'   = m*v + mp*vp          // conservation of momentum
-       //    m*v'^2 + mp*vp'^2 = m*v^2 + mp*vp^2      // conservation of energy (ELASTIC hit)
-       // -> a = 0                                    // case 1: did not hit
-       // -> a = 2*mp*(vp^2 - vp.v) / ((m+mp) * vp^2) // case 2: did hit
-       //                                             // non-elastic hits are somewhere between these two
-
-       // this would be physically correct, but we don't do that
-       return explosion_v * explosion_calcpush_getmultiplier(explosion_v, target_v) * (
-               (1 + elasticity) * (
-                       explosion_m
-               ) / (
-                       target_m + explosion_m
-               )
-       ); // note: this factor is at least 0, at most 2
-}
-#endif
-
-// simplified formula, tuned so that if the target has velocity 0, we get exactly the original force
-vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor)
-{
-       // if below 1, the formulas make no sense (and would cause superjumps)
-       if(speedfactor < 1)
-               return explosion_f;
-
-#if 0
-       float m;
-       // find m so that
-       //   speedfactor * (1 + e) * m / (1 + m) == 1
-       m = 1 / ((1 + 0) * speedfactor - 1);
-       vector v;
-       v = explosion_calcpush(explosion_f * speedfactor, m, target_v, 1, 0);
-       // the factor we then get is:
-       //   1
-       print(sprintf("MASS: %f\nv: %v -> %v\nENERGY BEFORE == %f + %f = %f\nENERGY AFTER >= %f\n",
-               m,
-               target_v, target_v + v,
-               target_v * target_v, m * explosion_f * speedfactor * explosion_f * speedfactor, target_v * target_v + m * explosion_f * speedfactor * explosion_f * speedfactor,
-               (target_v + v) * (target_v + v)));
-       return v;
-#endif
-       return explosion_f * explosion_calcpush_getmultiplier(explosion_f * speedfactor, target_v);
-}
diff --git a/qcsrc/common/explosion_equation.qh b/qcsrc/common/explosion_equation.qh
deleted file mode 100644 (file)
index c8630cd..0000000
+++ /dev/null
@@ -1 +0,0 @@
-vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor);
diff --git a/qcsrc/common/items.qc b/qcsrc/common/items.qc
deleted file mode 100644 (file)
index c961895..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-// WEAPON PLUGIN SYSTEM
-entity weapon_info[WEP_MAXCOUNT];
-entity dummy_weapon_info;
-
-void register_weapon(float id, float(float) func, float ammotype, float i, float weapontype, float pickupbasevalue, string modelname, string shortname, string wname)
-{
-       entity e;
-       weapon_info[id - 1] = e = spawn();
-       e.classname = "weapon_info";
-       e.weapon = id;
-       WEPSET_COPY_EW(e, id);
-       e.netname = shortname;
-       e.message = wname;
-       e.items = ammotype;
-       e.weapon_func = func;
-       e.mdl = modelname;
-       e.model = strzone(strcat("models/weapons/g_", modelname, ".md3"));
-       e.spawnflags = weapontype;
-       e.model2 = strzone(strcat("wpn-", e.mdl));
-       e.impulse = i;
-       e.bot_pickupbasevalue = pickupbasevalue;
-       if(ammotype & IT_SHELLS)
-               e.ammo_field = ammo_shells;
-       else if(ammotype & IT_NAILS)
-               e.ammo_field = ammo_nails;
-       else if(ammotype & IT_ROCKETS)
-               e.ammo_field = ammo_rockets;
-       else if(ammotype & IT_CELLS)
-               e.ammo_field = ammo_cells;
-       else if(ammotype & IT_FUEL)
-               e.ammo_field = ammo_fuel;
-       else
-               e.ammo_field = ammo_batteries;
-}
-float w_null(float dummy)
-{
-       return 0;
-}
-void register_weapons_done()
-{
-       dummy_weapon_info = spawn();
-       dummy_weapon_info.classname = "weapon_info";
-       dummy_weapon_info.weapon = 0; // you can recognize dummies by this
-       WEPSET_CLEAR_E(dummy_weapon_info);
-       dummy_weapon_info.netname = "";
-       dummy_weapon_info.message = "AOL CD Thrower";
-       dummy_weapon_info.items = 0;
-       dummy_weapon_info.weapon_func = w_null;
-       dummy_weapon_info.mdl = "";
-       dummy_weapon_info.model = "";
-       dummy_weapon_info.spawnflags = 0;
-       dummy_weapon_info.model2 = "";
-       dummy_weapon_info.impulse = -1;
-       dummy_weapon_info.bot_pickupbasevalue = 0;
-
-       float i;
-       weaponorder_byid = "";
-       for(i = WEP_MAXCOUNT; i >= 1; --i)
-               if(weapon_info[i-1])
-                       weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
-       weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
-}
-entity get_weaponinfo(float id)
-{
-       entity w;
-       if(id < WEP_FIRST || id > WEP_LAST)
-               return dummy_weapon_info;
-       w = weapon_info[id - 1];
-       if(w)
-               return w;
-       return dummy_weapon_info;
-}
-string W_FixWeaponOrder(string order, float complete)
-{
-       return fixPriorityList(order, WEP_FIRST, WEP_LAST, 230 - WEP_FIRST, complete);
-}
-string W_NameWeaponOrder_MapFunc(string s)
-{
-       entity wi;
-       if(s == "0" || stof(s))
-       {
-               wi = get_weaponinfo(stof(s));
-               if(wi != dummy_weapon_info)
-                       return wi.netname;
-       }
-       return s;
-}
-string W_NameWeaponOrder(string order)
-{
-       return mapPriorityList(order, W_NameWeaponOrder_MapFunc);
-}
-string W_NumberWeaponOrder_MapFunc(string s)
-{
-       float i;
-       if(s == "0" || stof(s))
-               return s;
-       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-               if(s == get_weaponinfo(i).netname)
-                       return ftos(i);
-       return s;
-}
-string W_NumberWeaponOrder(string order)
-{
-       return mapPriorityList(order, W_NumberWeaponOrder_MapFunc);
-}
-
-float W_FixWeaponOrder_BuildImpulseList_buf[WEP_MAXCOUNT];
-string W_FixWeaponOrder_BuildImpulseList_order;
-void W_FixWeaponOrder_BuildImpulseList_swap(float i, float j, entity pass)
-{
-       float h;
-       h = W_FixWeaponOrder_BuildImpulseList_buf[i];
-       W_FixWeaponOrder_BuildImpulseList_buf[i] = W_FixWeaponOrder_BuildImpulseList_buf[j];
-       W_FixWeaponOrder_BuildImpulseList_buf[j] = h;
-}
-float W_FixWeaponOrder_BuildImpulseList_cmp(float i, float j, entity pass)
-{
-       entity e1, e2;
-       float d;
-       e1 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[i]);
-       e2 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[j]);
-       d = mod(e1.impulse + 9, 10) - mod(e2.impulse + 9, 10);
-       if(d != 0)
-               return -d; // high impulse first!
-       return
-               strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0)
-               -
-               strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0)
-               ; // low char index first!
-}
-string W_FixWeaponOrder_BuildImpulseList(string o)
-{
-       float i;
-       W_FixWeaponOrder_BuildImpulseList_order = o;
-       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-               W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST] = i;
-       heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, world);
-       o = "";
-       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-               o = strcat(o, " ", ftos(W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST]));
-       W_FixWeaponOrder_BuildImpulseList_order = string_null;
-       return substring(o, 1, -1);
-}
-
-string W_FixWeaponOrder_AllowIncomplete(string order)
-{
-       return W_FixWeaponOrder(order, 0);
-}
-
-string W_FixWeaponOrder_ForceComplete(string order)
-{
-       if(order == "")
-               order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
-       return W_FixWeaponOrder(order, 1);
-}
-
-void W_RandomWeapons(entity e, float n)
-{
-       float i, j;
-       WEPSET_DECLARE_A(remaining);
-       WEPSET_DECLARE_A(result);
-       WEPSET_COPY_AE(remaining, e);
-       WEPSET_CLEAR_A(result);
-       for(i = 0; i < n; ++i)
-       {
-               RandomSelection_Init();
-               for(j = WEP_FIRST; j <= WEP_LAST; ++j)
-                       if(WEPSET_CONTAINS_AW(remaining, j))
-                               RandomSelection_Add(world, j, string_null, 1, 1);
-               WEPSET_OR_AW(result, RandomSelection_chosen_float);
-               WEPSET_ANDNOT_AW(remaining, RandomSelection_chosen_float);
-       }
-       WEPSET_COPY_EA(e, result);
-}
-
-string W_Name(float weaponid)
-{
-       return (get_weaponinfo(weaponid)).message;
-}
-
-float W_AmmoItemCode(float wpn)
-{
-       return (get_weaponinfo(wpn)).items & IT_AMMO;
-}
diff --git a/qcsrc/common/items.qh b/qcsrc/common/items.qh
deleted file mode 100644 (file)
index be17042..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-float BOT_PICKUP_RATING_LOW    = 2500;
-float BOT_PICKUP_RATING_MID    = 5000;
-float BOT_PICKUP_RATING_HIGH   = 10000;
-
-float WEP_TYPE_OTHER         =  0x00; // not for damaging people
-float WEP_TYPE_SPLASH        =  0x01; // splash damage
-float WEP_TYPE_HITSCAN       =  0x02; // hitscan
-float WEP_TYPEMASK            =  0x0F;
-float WEP_FLAG_CANCLIMB       =  0x10; // can be used for movement
-float WEP_FLAG_NORMAL         =  0x20; // in "most weapons" set
-float WEP_FLAG_HIDDEN         =  0x40; // hides from menu
-float WEP_FLAG_RELOADABLE     =  0x80; // can has reload
-float WEP_FLAG_SUPERWEAPON    = 0x100; // powerup timer
-float WEP_FLAG_MUTATORBLOCKED = 0x200; // hides from impulse 99 etc. (mutators are allowed to clear this flag)
-
-float  IT_UNLIMITED_WEAPON_AMMO     = 1;
-// when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
-float  IT_UNLIMITED_SUPERWEAPONS    = 2;
-// when this bit is set, superweapons don't expire. Checkpoints can give this powerup.
-float   IT_CTF_SHIELDED              = 4; // set for the flag shield
-float   IT_USING_JETPACK             = 8; // confirmation that button is pressed
-float   IT_JETPACK                   = 16; // actual item
-float   IT_FUEL_REGEN                = 32; // fuel regeneration trigger
-float   IT_SHELLS                    = 256;
-float   IT_NAILS                     = 512;
-float   IT_ROCKETS                   = 1024;
-float   IT_CELLS                     = 2048;
-float   IT_SUPERWEAPON               = 4096;
-float   IT_FUEL                      = 128;
-float   IT_STRENGTH                  = 8192;
-float   IT_INVINCIBLE                = 16384;
-float   IT_HEALTH                    = 32768;
-// union:
-       // for items:
-       float   IT_KEY1                                 = 131072;
-       float   IT_KEY2                                 = 262144;
-       // for players:
-       float   IT_RED_FLAG_TAKEN               = 32768;
-       float   IT_RED_FLAG_LOST                = 65536;
-       float   IT_RED_FLAG_CARRYING            = 98304;
-       float   IT_BLUE_FLAG_TAKEN              = 131072;
-       float   IT_BLUE_FLAG_LOST               = 262144;
-       float   IT_BLUE_FLAG_CARRYING   = 393216;
-// end
-float   IT_5HP                       = 524288;
-float   IT_25HP                      = 1048576;
-float   IT_ARMOR_SHARD               = 2097152;
-float   IT_ARMOR                     = 4194304;
-
-float   IT_AMMO                      = 3968; // IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS | IT_FUEL;
-float   IT_PICKUPMASK                = 51; // IT_FUEL_REGEN | IT_JETPACK | IT_UNLIMITED_AMMO; // strength and invincible are handled separately
-float   IT_UNLIMITED_AMMO            = 3; // IT_UNLIMITED_SUPERWEAPONS | IT_UNLIMITED_WEAPON_AMMO;
-
-float AMMO_COUNT = 4; // amount of ammo types to show in the inventory panel
-
-// variables:
-string weaponorder_byid;
-
-// functions:
-entity get_weaponinfo(float id);
-string W_FixWeaponOrder(string order, float complete);
-string W_NameWeaponOrder(string order);
-string W_NumberWeaponOrder(string order);
-
-// ammo types
-.float ammo_shells;
-.float ammo_nails;
-.float ammo_rockets;
-.float ammo_cells;
-.float ammo_fuel;
-.float ammo_batteries; // dummy
-
-// entity properties of weaponinfo:
-.float weapon; // WEP_...
-.string netname; // short name
-.string message; // human readable name
-.float items; // IT_...
-.float(float) weapon_func; // w_...
-.string mdl; // modelname without g_, v_, w_
-.string model; // full name of g_ model
-.float spawnflags; // WEPSPAWNFLAG_... combined
-.float impulse; // weapon impulse
-.float bot_pickupbasevalue; // bot weapon priority
-.string model2; // wpn- sprite name
-..float ammo_field; // main ammo field
-// also, weaponinfo ents can act as a WEPSET
-
-// dynamic weapon adding
-float w_null(float dummy);
-void register_weapon(float id, float(float) func, float ammotype, float i, float weapontype, float pickupbasevalue, string modelname, string shortname, string wname);
-void register_weapons_done();
-
-#define WEP_FIRST 1
-float WEP_COUNT;
-float WEP_LAST;
-
-#if 1
-# 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/weapons/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);
-
-string W_Name(float weaponid);
-
-float W_AmmoItemCode(float wpn);
index 480ebc9fa47aa5b07c2c4f37b5297521a19e77c6..f599c9ba1f5f19b4419c2c00bb691afe69599f89 100644 (file)
@@ -2504,199 +2504,6 @@ void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t
                queue_start.FindConnectedComponent_processing = 0;
 }
 
-
-#ifndef MENUQC
-vector cliptoplane(vector v, vector p)
-{
-       return v - (v * p) * p;
-}
-
-vector solve_cubic_pq(float p, float q)
-{
-       float D, u, v, a;
-       D = q*q/4.0 + p*p*p/27.0;
-       if(D < 0)
-       {
-               // irreducibilis
-               a = 1.0/3.0 * acos(-q/2.0 * sqrt(-27.0/(p*p*p)));
-               u = sqrt(-4.0/3.0 * p);
-               // a in range 0..pi/3
-               // cos(a)
-               // cos(a + 2pi/3)
-               // cos(a + 4pi/3)
-               return
-                       u *
-                       (
-                               '1 0 0' * cos(a + 2.0/3.0*M_PI)
-                               +
-                               '0 1 0' * cos(a + 4.0/3.0*M_PI)
-                               +
-                               '0 0 1' * cos(a)
-                       );
-       }
-       else if(D == 0)
-       {
-               // simple
-               if(p == 0)
-                       return '0 0 0';
-               u = 3*q/p;
-               v = -u/2;
-               if(u >= v)
-                       return '1 1 0' * v + '0 0 1' * u;
-               else
-                       return '0 1 1' * v + '1 0 0' * u;
-       }
-       else
-       {
-               // cardano
-               u = cbrt(-q/2.0 + sqrt(D));
-               v = cbrt(-q/2.0 - sqrt(D));
-               return '1 1 1' * (u + v);
-       }
-}
-vector solve_cubic_abcd(float a, float b, float c, float d)
-{
-       // y = 3*a*x + b
-       // x = (y - b) / 3a
-       float p, q;
-       vector v;
-       p = (9*a*c - 3*b*b);
-       q = (27*a*a*d - 9*a*b*c + 2*b*b*b);
-       v = solve_cubic_pq(p, q);
-       v = (v -  b * '1 1 1') * (1.0 / (3.0 * a));
-       if(a < 0)
-               v += '1 0 -1' * (v_z - v_x); // swap x, z
-       return v;
-}
-
-vector findperpendicular(vector v)
-{
-       vector p;
-       p_x = v_z;
-       p_y = -v_x;
-       p_z = v_y;
-       return normalize(cliptoplane(p, v));
-}
-
-vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle)
-{
-       float sigma;
-       vector v1 = '0 0 0', v2;
-       float dx, dy, r;
-       float sstyle;
-       spread *= spreadfactor; //g_weaponspreadfactor;
-       if(spread <= 0)
-               return forward;
-       sstyle = spreadstyle; //autocvar_g_projectiles_spread_style;
-       
-       if(sstyle == 0)
-       {
-               // this is the baseline for the spread value!
-               // standard deviation: sqrt(2/5)
-               // density function: sqrt(1-r^2)
-               return forward + randomvec() * spread;
-       }
-       else if(sstyle == 1)
-       {
-               // same thing, basically
-               return normalize(forward + cliptoplane(randomvec() * spread, forward));
-       }
-       else if(sstyle == 2)
-       {
-               // circle spread... has at sigma=1 a standard deviation of sqrt(1/2)
-               sigma = spread * 0.89442719099991587855; // match baseline stddev
-               v1 = findperpendicular(forward);
-               v2 = cross(forward, v1);
-               // random point on unit circle
-               dx = random() * 2 * M_PI;
-               dy = sin(dx);
-               dx = cos(dx);
-               // radius in our dist function
-               r = random();
-               r = sqrt(r);
-               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-       }
-       else if(sstyle == 3) // gauss 3d
-       {
-               sigma = spread * 0.44721359549996; // match baseline stddev
-               // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
-               v1 = forward;
-               v1_x += gsl_ran_gaussian(sigma);
-               v1_y += gsl_ran_gaussian(sigma);
-               v1_z += gsl_ran_gaussian(sigma);
-               return v1;
-       }
-       else if(sstyle == 4) // gauss 2d
-       {
-               sigma = spread * 0.44721359549996; // match baseline stddev
-               // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
-               v1_x = gsl_ran_gaussian(sigma);
-               v1_y = gsl_ran_gaussian(sigma);
-               v1_z = gsl_ran_gaussian(sigma);
-               return normalize(forward + cliptoplane(v1, forward));
-       }
-       else if(sstyle == 5) // 1-r
-       {
-               sigma = spread * 1.154700538379252; // match baseline stddev
-               v1 = findperpendicular(forward);
-               v2 = cross(forward, v1);
-               // random point on unit circle
-               dx = random() * 2 * M_PI;
-               dy = sin(dx);
-               dx = cos(dx);
-               // radius in our dist function
-               r = random();
-               r = solve_cubic_abcd(-2, 3, 0, -r) * '0 1 0';
-               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-       }
-       else if(sstyle == 6) // 1-r^2
-       {
-               sigma = spread * 1.095445115010332; // match baseline stddev
-               v1 = findperpendicular(forward);
-               v2 = cross(forward, v1);
-               // random point on unit circle
-               dx = random() * 2 * M_PI;
-               dy = sin(dx);
-               dx = cos(dx);
-               // radius in our dist function
-               r = random();
-               r = sqrt(1 - r);
-               r = sqrt(1 - r);
-               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-       }
-       else if(sstyle == 7) // (1-r) (2-r)
-       {
-               sigma = spread * 1.224744871391589; // match baseline stddev
-               v1 = findperpendicular(forward);
-               v2 = cross(forward, v1);
-               // random point on unit circle
-               dx = random() * 2 * M_PI;
-               dy = sin(dx);
-               dx = cos(dx);
-               // radius in our dist function
-               r = random();
-               r = 1 - sqrt(r);
-               r = 1 - sqrt(r);
-               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-       }
-       else
-               error("g_projectiles_spread_style must be 0 (sphere), 1 (flattened sphere), 2 (circle), 3 (gauss 3D), 4 (gauss plane), 5 (linear falloff), 6 (quadratic falloff), 7 (stronger falloff)!");
-       return '0 0 0';
-       /*
-        * how to derive falloff functions:
-        * rho(r) := (2-r) * (1-r);
-        * a : 0;
-        * b : 1;
-        * rhor(r) := r * rho(r);
-        * cr(t) := integrate(rhor(r), r, a, t);
-        * scr(t) := integrate(rhor(r) * r^2, r, a, t);
-        * variance : scr(b) / cr(b);
-        * solve(cr(r) = rand * cr(b), r), programmmode:false;
-        * sqrt(0.4 / variance), numer;
-        */
-}
-#endif
-
 #ifdef SVQC
 vector combine_to_vector(float x, float y, float z)
 {
index 27cc0ec8b5de04412365bfed2ba216ba091c8f18..993ad87f95d961c46e518addd4357c6f22fda15f 100644 (file)
@@ -346,10 +346,6 @@ typedef entity(entity cur, entity near, entity pass) findNextEntityNearFunction_
 typedef float(entity a, entity b, entity pass) isConnectedFunction_t;
 void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass);
 
-#ifndef MENUQC
-vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle);
-#endif
-
 #ifdef SVQC
 vector get_corner_position(entity box, float corner);
 #endif
diff --git a/qcsrc/common/weapons/all.qh b/qcsrc/common/weapons/all.qh
new file mode 100644 (file)
index 0000000..37458a6
--- /dev/null
@@ -0,0 +1,26 @@
+// ONLY EVER ADD NEW WEAPONS AT THE END. IF YOU REMOVE ONE, PUT THE LAST ONE ON
+// ITS PLACE. THIS IS TO AVOID UNNECESSARY RENUMBERING OF WEAPON IMPULSES.
+// IF YOU DISREGARD THIS NOTICE, I'LL KILL YOU WITH THE @!#%'N TUBA
+
+// core weapons
+#include "blaster.qc"
+#include "shockwave.qc"
+#include "machinegun.qc"
+#include "mortar.qc"
+#include "minelayer.qc"
+#include "electro.qc"
+#include "arc.qc"
+#include "crylink.qc"
+#include "nex.qc"
+#include "hagar.qc"
+#include "devastator.qc"
+
+// other weapons
+#include "porto.qc"
+#include "minstanex.qc"
+#include "hook.qc"
+#include "hlac.qc"
+#include "tuba.qc"
+#include "rifle.qc"
+#include "fireball.qc"
+#include "seeker.qc"
diff --git a/qcsrc/common/weapons/calculations.qc b/qcsrc/common/weapons/calculations.qc
new file mode 100644 (file)
index 0000000..0327943
--- /dev/null
@@ -0,0 +1,260 @@
+// =============================
+//  Explosion Force Calculation
+// =============================
+float explosion_calcpush_getmultiplier(vector explosion_v, vector target_v)
+{
+       float a;
+       a  = explosion_v * (explosion_v - target_v);
+
+       if(a <= 0)
+               // target is too fast to be hittable by this
+               return 0;
+
+       a /= (explosion_v * explosion_v);
+               // we know we can divide by this, or above a would be == 0
+
+       return a;
+}
+
+#if 0
+vector explosion_calcpush(vector explosion_v, float explosion_m, vector target_v, float target_m, float elasticity)
+{
+       // solution of the equations:
+       //    v'                = v + a vp             // central hit
+       //    m*v'   + mp*vp'   = m*v + mp*vp          // conservation of momentum
+       //    m*v'^2 + mp*vp'^2 = m*v^2 + mp*vp^2      // conservation of energy (ELASTIC hit)
+       // -> a = 0                                    // case 1: did not hit
+       // -> a = 2*mp*(vp^2 - vp.v) / ((m+mp) * vp^2) // case 2: did hit
+       //                                             // non-elastic hits are somewhere between these two
+
+       // this would be physically correct, but we don't do that
+       return explosion_v * explosion_calcpush_getmultiplier(explosion_v, target_v) * (
+               (1 + elasticity) * (
+                       explosion_m
+               ) / (
+                       target_m + explosion_m
+               )
+       ); // note: this factor is at least 0, at most 2
+}
+#endif
+
+// simplified formula, tuned so that if the target has velocity 0, we get exactly the original force
+vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor)
+{
+       // if below 1, the formulas make no sense (and would cause superjumps)
+       if(speedfactor < 1)
+               return explosion_f;
+
+#if 0
+       float m;
+       // find m so that
+       //   speedfactor * (1 + e) * m / (1 + m) == 1
+       m = 1 / ((1 + 0) * speedfactor - 1);
+       vector v;
+       v = explosion_calcpush(explosion_f * speedfactor, m, target_v, 1, 0);
+       // the factor we then get is:
+       //   1
+       print(sprintf("MASS: %f\nv: %v -> %v\nENERGY BEFORE == %f + %f = %f\nENERGY AFTER >= %f\n",
+               m,
+               target_v, target_v + v,
+               target_v * target_v, m * explosion_f * speedfactor * explosion_f * speedfactor, target_v * target_v + m * explosion_f * speedfactor * explosion_f * speedfactor,
+               (target_v + v) * (target_v + v)));
+       return v;
+#endif
+       return explosion_f * explosion_calcpush_getmultiplier(explosion_f * speedfactor, target_v);
+}
+
+
+// =========================
+//  Shot Spread Calculation
+// =========================
+
+vector cliptoplane(vector v, vector p)
+{
+       return v - (v * p) * p;
+}
+
+vector solve_cubic_pq(float p, float q)
+{
+       float D, u, v, a;
+       D = q*q/4.0 + p*p*p/27.0;
+       if(D < 0)
+       {
+               // irreducibilis
+               a = 1.0/3.0 * acos(-q/2.0 * sqrt(-27.0/(p*p*p)));
+               u = sqrt(-4.0/3.0 * p);
+               // a in range 0..pi/3
+               // cos(a)
+               // cos(a + 2pi/3)
+               // cos(a + 4pi/3)
+               return
+                       u *
+                       (
+                               '1 0 0' * cos(a + 2.0/3.0*M_PI)
+                               +
+                               '0 1 0' * cos(a + 4.0/3.0*M_PI)
+                               +
+                               '0 0 1' * cos(a)
+                       );
+       }
+       else if(D == 0)
+       {
+               // simple
+               if(p == 0)
+                       return '0 0 0';
+               u = 3*q/p;
+               v = -u/2;
+               if(u >= v)
+                       return '1 1 0' * v + '0 0 1' * u;
+               else
+                       return '0 1 1' * v + '1 0 0' * u;
+       }
+       else
+       {
+               // cardano
+               u = cbrt(-q/2.0 + sqrt(D));
+               v = cbrt(-q/2.0 - sqrt(D));
+               return '1 1 1' * (u + v);
+       }
+}
+vector solve_cubic_abcd(float a, float b, float c, float d)
+{
+       // y = 3*a*x + b
+       // x = (y - b) / 3a
+       float p, q;
+       vector v;
+       p = (9*a*c - 3*b*b);
+       q = (27*a*a*d - 9*a*b*c + 2*b*b*b);
+       v = solve_cubic_pq(p, q);
+       v = (v -  b * '1 1 1') * (1.0 / (3.0 * a));
+       if(a < 0)
+               v += '1 0 -1' * (v_z - v_x); // swap x, z
+       return v;
+}
+
+vector findperpendicular(vector v)
+{
+       vector p;
+       p_x = v_z;
+       p_y = -v_x;
+       p_z = v_y;
+       return normalize(cliptoplane(p, v));
+}
+
+vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle)
+{
+       float sigma;
+       vector v1 = '0 0 0', v2;
+       float dx, dy, r;
+       float sstyle;
+       spread *= spreadfactor; //g_weaponspreadfactor;
+       if(spread <= 0)
+               return forward;
+       sstyle = spreadstyle; //autocvar_g_projectiles_spread_style;
+       
+       if(sstyle == 0)
+       {
+               // this is the baseline for the spread value!
+               // standard deviation: sqrt(2/5)
+               // density function: sqrt(1-r^2)
+               return forward + randomvec() * spread;
+       }
+       else if(sstyle == 1)
+       {
+               // same thing, basically
+               return normalize(forward + cliptoplane(randomvec() * spread, forward));
+       }
+       else if(sstyle == 2)
+       {
+               // circle spread... has at sigma=1 a standard deviation of sqrt(1/2)
+               sigma = spread * 0.89442719099991587855; // match baseline stddev
+               v1 = findperpendicular(forward);
+               v2 = cross(forward, v1);
+               // random point on unit circle
+               dx = random() * 2 * M_PI;
+               dy = sin(dx);
+               dx = cos(dx);
+               // radius in our dist function
+               r = random();
+               r = sqrt(r);
+               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
+       }
+       else if(sstyle == 3) // gauss 3d
+       {
+               sigma = spread * 0.44721359549996; // match baseline stddev
+               // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
+               v1 = forward;
+               v1_x += gsl_ran_gaussian(sigma);
+               v1_y += gsl_ran_gaussian(sigma);
+               v1_z += gsl_ran_gaussian(sigma);
+               return v1;
+       }
+       else if(sstyle == 4) // gauss 2d
+       {
+               sigma = spread * 0.44721359549996; // match baseline stddev
+               // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
+               v1_x = gsl_ran_gaussian(sigma);
+               v1_y = gsl_ran_gaussian(sigma);
+               v1_z = gsl_ran_gaussian(sigma);
+               return normalize(forward + cliptoplane(v1, forward));
+       }
+       else if(sstyle == 5) // 1-r
+       {
+               sigma = spread * 1.154700538379252; // match baseline stddev
+               v1 = findperpendicular(forward);
+               v2 = cross(forward, v1);
+               // random point on unit circle
+               dx = random() * 2 * M_PI;
+               dy = sin(dx);
+               dx = cos(dx);
+               // radius in our dist function
+               r = random();
+               r = solve_cubic_abcd(-2, 3, 0, -r) * '0 1 0';
+               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
+       }
+       else if(sstyle == 6) // 1-r^2
+       {
+               sigma = spread * 1.095445115010332; // match baseline stddev
+               v1 = findperpendicular(forward);
+               v2 = cross(forward, v1);
+               // random point on unit circle
+               dx = random() * 2 * M_PI;
+               dy = sin(dx);
+               dx = cos(dx);
+               // radius in our dist function
+               r = random();
+               r = sqrt(1 - r);
+               r = sqrt(1 - r);
+               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
+       }
+       else if(sstyle == 7) // (1-r) (2-r)
+       {
+               sigma = spread * 1.224744871391589; // match baseline stddev
+               v1 = findperpendicular(forward);
+               v2 = cross(forward, v1);
+               // random point on unit circle
+               dx = random() * 2 * M_PI;
+               dy = sin(dx);
+               dx = cos(dx);
+               // radius in our dist function
+               r = random();
+               r = 1 - sqrt(r);
+               r = 1 - sqrt(r);
+               return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
+       }
+       else
+               error("g_projectiles_spread_style must be 0 (sphere), 1 (flattened sphere), 2 (circle), 3 (gauss 3D), 4 (gauss plane), 5 (linear falloff), 6 (quadratic falloff), 7 (stronger falloff)!");
+       return '0 0 0';
+       /*
+        * how to derive falloff functions:
+        * rho(r) := (2-r) * (1-r);
+        * a : 0;
+        * b : 1;
+        * rhor(r) := r * rho(r);
+        * cr(t) := integrate(rhor(r), r, a, t);
+        * scr(t) := integrate(rhor(r) * r^2, r, a, t);
+        * variance : scr(b) / cr(b);
+        * solve(cr(r) = rand * cr(b), r), programmmode:false;
+        * sqrt(0.4 / variance), numer;
+        */
+}
diff --git a/qcsrc/common/weapons/calculations.qh b/qcsrc/common/weapons/calculations.qh
new file mode 100644 (file)
index 0000000..9a6dd1c
--- /dev/null
@@ -0,0 +1,2 @@
+vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor);
+vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle);
diff --git a/qcsrc/common/weapons/weapons.qc b/qcsrc/common/weapons/weapons.qc
new file mode 100644 (file)
index 0000000..6d4ac36
--- /dev/null
@@ -0,0 +1,189 @@
+#ifndef MENUQC
+#include "calculations.qc"
+#endif
+#include "all.qh"
+
+// WEAPON PLUGIN SYSTEM
+entity weapon_info[WEP_MAXCOUNT];
+entity dummy_weapon_info;
+
+void register_weapon(float id, float(float) func, float ammotype, float i, float weapontype, float pickupbasevalue, string modelname, string shortname, string wname)
+{
+       entity e;
+       weapon_info[id - 1] = e = spawn();
+       e.classname = "weapon_info";
+       e.weapon = id;
+       WEPSET_COPY_EW(e, id);
+       e.netname = shortname;
+       e.message = wname;
+       e.items = ammotype;
+       e.weapon_func = func;
+       e.mdl = modelname;
+       e.model = strzone(strcat("models/weapons/g_", modelname, ".md3"));
+       e.spawnflags = weapontype;
+       e.model2 = strzone(strcat("wpn-", e.mdl));
+       e.impulse = i;
+       e.bot_pickupbasevalue = pickupbasevalue;
+       if(ammotype & IT_SHELLS)
+               e.ammo_field = ammo_shells;
+       else if(ammotype & IT_NAILS)
+               e.ammo_field = ammo_nails;
+       else if(ammotype & IT_ROCKETS)
+               e.ammo_field = ammo_rockets;
+       else if(ammotype & IT_CELLS)
+               e.ammo_field = ammo_cells;
+       else if(ammotype & IT_FUEL)
+               e.ammo_field = ammo_fuel;
+       else
+               e.ammo_field = ammo_batteries;
+}
+float w_null(float dummy)
+{
+       return 0;
+}
+void register_weapons_done()
+{
+       dummy_weapon_info = spawn();
+       dummy_weapon_info.classname = "weapon_info";
+       dummy_weapon_info.weapon = 0; // you can recognize dummies by this
+       WEPSET_CLEAR_E(dummy_weapon_info);
+       dummy_weapon_info.netname = "";
+       dummy_weapon_info.message = "AOL CD Thrower";
+       dummy_weapon_info.items = 0;
+       dummy_weapon_info.weapon_func = w_null;
+       dummy_weapon_info.mdl = "";
+       dummy_weapon_info.model = "";
+       dummy_weapon_info.spawnflags = 0;
+       dummy_weapon_info.model2 = "";
+       dummy_weapon_info.impulse = -1;
+       dummy_weapon_info.bot_pickupbasevalue = 0;
+
+       float i;
+       weaponorder_byid = "";
+       for(i = WEP_MAXCOUNT; i >= 1; --i)
+               if(weapon_info[i-1])
+                       weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
+       weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
+}
+entity get_weaponinfo(float id)
+{
+       entity w;
+       if(id < WEP_FIRST || id > WEP_LAST)
+               return dummy_weapon_info;
+       w = weapon_info[id - 1];
+       if(w)
+               return w;
+       return dummy_weapon_info;
+}
+string W_FixWeaponOrder(string order, float complete)
+{
+       return fixPriorityList(order, WEP_FIRST, WEP_LAST, 230 - WEP_FIRST, complete);
+}
+string W_NameWeaponOrder_MapFunc(string s)
+{
+       entity wi;
+       if(s == "0" || stof(s))
+       {
+               wi = get_weaponinfo(stof(s));
+               if(wi != dummy_weapon_info)
+                       return wi.netname;
+       }
+       return s;
+}
+string W_NameWeaponOrder(string order)
+{
+       return mapPriorityList(order, W_NameWeaponOrder_MapFunc);
+}
+string W_NumberWeaponOrder_MapFunc(string s)
+{
+       float i;
+       if(s == "0" || stof(s))
+               return s;
+       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+               if(s == get_weaponinfo(i).netname)
+                       return ftos(i);
+       return s;
+}
+string W_NumberWeaponOrder(string order)
+{
+       return mapPriorityList(order, W_NumberWeaponOrder_MapFunc);
+}
+
+float W_FixWeaponOrder_BuildImpulseList_buf[WEP_MAXCOUNT];
+string W_FixWeaponOrder_BuildImpulseList_order;
+void W_FixWeaponOrder_BuildImpulseList_swap(float i, float j, entity pass)
+{
+       float h;
+       h = W_FixWeaponOrder_BuildImpulseList_buf[i];
+       W_FixWeaponOrder_BuildImpulseList_buf[i] = W_FixWeaponOrder_BuildImpulseList_buf[j];
+       W_FixWeaponOrder_BuildImpulseList_buf[j] = h;
+}
+float W_FixWeaponOrder_BuildImpulseList_cmp(float i, float j, entity pass)
+{
+       entity e1, e2;
+       float d;
+       e1 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[i]);
+       e2 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[j]);
+       d = mod(e1.impulse + 9, 10) - mod(e2.impulse + 9, 10);
+       if(d != 0)
+               return -d; // high impulse first!
+       return
+               strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0)
+               -
+               strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0)
+               ; // low char index first!
+}
+string W_FixWeaponOrder_BuildImpulseList(string o)
+{
+       float i;
+       W_FixWeaponOrder_BuildImpulseList_order = o;
+       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+               W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST] = i;
+       heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, world);
+       o = "";
+       for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+               o = strcat(o, " ", ftos(W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST]));
+       W_FixWeaponOrder_BuildImpulseList_order = string_null;
+       return substring(o, 1, -1);
+}
+
+string W_FixWeaponOrder_AllowIncomplete(string order)
+{
+       return W_FixWeaponOrder(order, 0);
+}
+
+string W_FixWeaponOrder_ForceComplete(string order)
+{
+       if(order == "")
+               order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
+       return W_FixWeaponOrder(order, 1);
+}
+
+void W_RandomWeapons(entity e, float n)
+{
+       float i, j;
+       WEPSET_DECLARE_A(remaining);
+       WEPSET_DECLARE_A(result);
+       WEPSET_COPY_AE(remaining, e);
+       WEPSET_CLEAR_A(result);
+       for(i = 0; i < n; ++i)
+       {
+               RandomSelection_Init();
+               for(j = WEP_FIRST; j <= WEP_LAST; ++j)
+                       if(WEPSET_CONTAINS_AW(remaining, j))
+                               RandomSelection_Add(world, j, string_null, 1, 1);
+               WEPSET_OR_AW(result, RandomSelection_chosen_float);
+               WEPSET_ANDNOT_AW(remaining, RandomSelection_chosen_float);
+       }
+       WEPSET_COPY_EA(e, result);
+}
+
+string W_Name(float weaponid)
+{
+       return (get_weaponinfo(weaponid)).message;
+}
+
+float W_AmmoItemCode(float wpn)
+{
+       return (get_weaponinfo(wpn)).items & IT_AMMO;
+}
index beaebaf55c2e0abaddb2a7b17441a1cdbd0cc2b0..d4ccf2ba60657edc221ad22c0b468e3fe044bf86 100644 (file)
-// ONLY EVER ADD NEW WEAPONS AT THE END. IF YOU REMOVE ONE, PUT THE LAST ONE ON
-// ITS PLACE. THIS IS TO AVOID UNNECESSARY RENUMBERING OF WEAPON IMPULSES.
-// IF YOU DISREGARD THIS NOTICE, I'LL KILL YOU WITH THE @!#%'N TUBA
-
-// core weapons
-#include "blaster.qc"
-#include "shockwave.qc"
-#include "machinegun.qc"
-#include "mortar.qc"
-#include "minelayer.qc"
-#include "electro.qc"
-#include "arc.qc"
-#include "crylink.qc"
-#include "nex.qc"
-#include "hagar.qc"
-#include "devastator.qc"
-#include "porto.qc"
-#include "minstanex.qc"
-#include "hook.qc"
-#include "hlac.qc"
-#include "tuba.qc"
-#include "rifle.qc"
-#include "fireball.qc"
-#include "seeker.qc"
-
-// other weapons
+#ifndef MENUQC
+#include "calculations.qh"
+#endif
+
+float BOT_PICKUP_RATING_LOW    = 2500;
+float BOT_PICKUP_RATING_MID    = 5000;
+float BOT_PICKUP_RATING_HIGH   = 10000;
+
+float WEP_TYPE_OTHER         =  0x00; // not for damaging people
+float WEP_TYPE_SPLASH        =  0x01; // splash damage
+float WEP_TYPE_HITSCAN       =  0x02; // hitscan
+float WEP_TYPEMASK            =  0x0F;
+float WEP_FLAG_CANCLIMB       =  0x10; // can be used for movement
+float WEP_FLAG_NORMAL         =  0x20; // in "most weapons" set
+float WEP_FLAG_HIDDEN         =  0x40; // hides from menu
+float WEP_FLAG_RELOADABLE     =  0x80; // can has reload
+float WEP_FLAG_SUPERWEAPON    = 0x100; // powerup timer
+float WEP_FLAG_MUTATORBLOCKED = 0x200; // hides from impulse 99 etc. (mutators are allowed to clear this flag)
+
+float  IT_UNLIMITED_WEAPON_AMMO     = 1;
+// when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
+float  IT_UNLIMITED_SUPERWEAPONS    = 2;
+// when this bit is set, superweapons don't expire. Checkpoints can give this powerup.
+float   IT_CTF_SHIELDED              = 4; // set for the flag shield
+float   IT_USING_JETPACK             = 8; // confirmation that button is pressed
+float   IT_JETPACK                   = 16; // actual item
+float   IT_FUEL_REGEN                = 32; // fuel regeneration trigger
+float   IT_SHELLS                    = 256;
+float   IT_NAILS                     = 512;
+float   IT_ROCKETS                   = 1024;
+float   IT_CELLS                     = 2048;
+float   IT_SUPERWEAPON               = 4096;
+float   IT_FUEL                      = 128;
+float   IT_STRENGTH                  = 8192;
+float   IT_INVINCIBLE                = 16384;
+float   IT_HEALTH                    = 32768;
+// union:
+       // for items:
+       float   IT_KEY1                                 = 131072;
+       float   IT_KEY2                                 = 262144;
+       // for players:
+       float   IT_RED_FLAG_TAKEN               = 32768;
+       float   IT_RED_FLAG_LOST                = 65536;
+       float   IT_RED_FLAG_CARRYING            = 98304;
+       float   IT_BLUE_FLAG_TAKEN              = 131072;
+       float   IT_BLUE_FLAG_LOST               = 262144;
+       float   IT_BLUE_FLAG_CARRYING   = 393216;
+// end
+float   IT_5HP                       = 524288;
+float   IT_25HP                      = 1048576;
+float   IT_ARMOR_SHARD               = 2097152;
+float   IT_ARMOR                     = 4194304;
+
+float   IT_AMMO                      = 3968; // IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS | IT_FUEL;
+float   IT_PICKUPMASK                = 51; // IT_FUEL_REGEN | IT_JETPACK | IT_UNLIMITED_AMMO; // strength and invincible are handled separately
+float   IT_UNLIMITED_AMMO            = 3; // IT_UNLIMITED_SUPERWEAPONS | IT_UNLIMITED_WEAPON_AMMO;
+
+float AMMO_COUNT = 4; // amount of ammo types to show in the inventory panel
+
+// variables:
+string weaponorder_byid;
+
+// functions:
+entity get_weaponinfo(float id);
+string W_FixWeaponOrder(string order, float complete);
+string W_NameWeaponOrder(string order);
+string W_NumberWeaponOrder(string order);
+
+// ammo types
+.float ammo_shells;
+.float ammo_nails;
+.float ammo_rockets;
+.float ammo_cells;
+.float ammo_fuel;
+.float ammo_batteries; // dummy
+
+// entity properties of weaponinfo:
+.float weapon; // WEP_...
+.string netname; // short name
+.string message; // human readable name
+.float items; // IT_...
+.float(float) weapon_func; // w_...
+.string mdl; // modelname without g_, v_, w_
+.string model; // full name of g_ model
+.float spawnflags; // WEPSPAWNFLAG_... combined
+.float impulse; // weapon impulse
+.float bot_pickupbasevalue; // bot weapon priority
+.string model2; // wpn- sprite name
+..float ammo_field; // main ammo field
+// also, weaponinfo ents can act as a WEPSET
+
+
+// ===================
+//  Weapon Operations
+// ===================
+#if 1
+# 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);
+
+
+// =====================
+//  Weapon Registration
+// =====================
+
+float w_null(float dummy);
+void register_weapon(float id, float(float) func, float ammotype, float i, float weapontype, float pickupbasevalue, string modelname, string shortname, string wname);
+void register_weapons_done();
+
+#define WEP_FIRST 1
+float WEP_COUNT;
+float WEP_LAST;
+
+// 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 "all.qh"
+
+#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);
+
+string W_Name(float weaponid);
+
+float W_AmmoItemCode(float wpn);
index 36905e17ad5be250f3fd0838cb4ed118a8850928..fc21640a7179d318c7da0acbd43d8704cef72b86 100644 (file)
@@ -17,7 +17,7 @@ oo/base.h
 ../common/constants.qh
 ../common/mapinfo.qh
 ../common/campaign_common.qh
-../common/items.qh
+../common/weapons/weapons.qh // TODO
 ../common/counting.qh
 ../common/command/markup.qh
 ../common/command/rpn.qh
@@ -48,7 +48,7 @@ xonotic/util.qc
 ../common/campaign_file.qc
 ../common/campaign_setup.qc
 ../common/mapinfo.qc
-../common/items.qc
+../common/weapons/weapons.qc // TODO
 ../common/urllib.qc
 
 ../warpzonelib/mathlib.qc
index cf969eb4bbc21773769f746bc2227f55ef39cd30..fd586c3d2e5f718c658f032c4f51f85579f9afce 100644 (file)
@@ -16,8 +16,7 @@ sys-post.qh
 ../common/teams.qh
 ../common/util.qh
 ../common/counting.qh
-../common/items.qh
-../common/explosion_equation.qh
+../common/weapons/weapons.qh // TODO
 ../common/urllib.qh
 ../common/command/markup.qh
 ../common/command/rpn.qh
@@ -63,7 +62,7 @@ command/cmd.qh
 command/sv_cmd.qh
 
 accuracy.qh
-csqcprojectile.qh
+weapons/csqcprojectile.qh // TODO
 ../common/csqcmodel_settings.qh
 ../csqcmodellib/common.qh
 ../csqcmodellib/sv_model.qh
@@ -76,8 +75,8 @@ playerstats.qh
 portals.qh
 
 g_hook.qh
-weapons/w_electro.qh
-weapons/w_lightning.qh
+../common/weapons/electro.qh // TODO
+../common/weapons/arc.qh
 
 scores.qh
 
@@ -138,13 +137,13 @@ g_models.qc
 item_key.qc
 secret.qc
 
-weapons/cl_weaponsystem.qc
-weapons/w_common.qc
-
-weapons/w_all.qc
+weapons/main.qc
+weapons/common.qc
+weapons/csqcprojectile.qc // TODO
+../common/weapons/weapons.qc // TODO
 
 t_items.qc
-weapons/cl_weapons.qc
+weapons/cl_weapons.qc // TODO
 cl_impulse.qc
 
 ent_cs.qc
@@ -207,12 +206,9 @@ target_spawn.qc
 func_breakable.qc
 target_music.qc
 
-../common/items.qc
-
 
 accuracy.qc
 ../csqcmodellib/sv_model.qc
-csqcprojectile.qc
 
 playerdemo.qc
 
@@ -222,8 +218,6 @@ playerstats.qc
 
 round_handler.qc
 
-../common/explosion_equation.qc
-
 mutators/base.qc
 mutators/gamemode_assault.qc
 mutators/gamemode_arena.qc