From 9a84fea569421f5496c1f92728e3f39f376abe2a Mon Sep 17 00:00:00 2001 From: Samual Lenks Date: Mon, 10 Jun 2013 19:22:05 -0400 Subject: [PATCH] More cleanup, make it compile now --- qcsrc/client/progs.src | 7 +- qcsrc/common/explosion_equation.qc | 62 ---- qcsrc/common/explosion_equation.qh | 1 - qcsrc/common/items.qh | 248 --------------- qcsrc/common/util.qc | 193 ------------ qcsrc/common/util.qh | 4 - qcsrc/common/weapons/all.qh | 26 ++ qcsrc/common/weapons/calculations.qc | 260 ++++++++++++++++ qcsrc/common/weapons/calculations.qh | 2 + qcsrc/common/{items.qc => weapons/weapons.qc} | 5 + qcsrc/common/weapons/weapons.qh | 286 ++++++++++++++++-- qcsrc/menu/progs.src | 4 +- qcsrc/server/progs.src | 24 +- 13 files changed, 566 insertions(+), 556 deletions(-) delete mode 100644 qcsrc/common/explosion_equation.qc delete mode 100644 qcsrc/common/explosion_equation.qh delete mode 100644 qcsrc/common/items.qh create mode 100644 qcsrc/common/weapons/all.qh create mode 100644 qcsrc/common/weapons/calculations.qc create mode 100644 qcsrc/common/weapons/calculations.qh rename qcsrc/common/{items.qc => weapons/weapons.qc} (98%) diff --git a/qcsrc/client/progs.src b/qcsrc/client/progs.src index e409f7749..c12f30847 100644 --- a/qcsrc/client/progs.src +++ b/qcsrc/client/progs.src @@ -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 index df71154be..000000000 --- a/qcsrc/common/explosion_equation.qc +++ /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 index c8630cdb1..000000000 --- a/qcsrc/common/explosion_equation.qh +++ /dev/null @@ -1 +0,0 @@ -vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor); diff --git a/qcsrc/common/items.qh b/qcsrc/common/items.qh deleted file mode 100644 index be17042aa..000000000 --- a/qcsrc/common/items.qh +++ /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); diff --git a/qcsrc/common/util.qc b/qcsrc/common/util.qc index 480ebc9fa..f599c9ba1 100644 --- a/qcsrc/common/util.qc +++ b/qcsrc/common/util.qc @@ -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) { diff --git a/qcsrc/common/util.qh b/qcsrc/common/util.qh index 27cc0ec8b..993ad87f9 100644 --- a/qcsrc/common/util.qh +++ b/qcsrc/common/util.qh @@ -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 index 000000000..37458a6ab --- /dev/null +++ b/qcsrc/common/weapons/all.qh @@ -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 index 000000000..0327943f9 --- /dev/null +++ b/qcsrc/common/weapons/calculations.qc @@ -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 index 000000000..9a6dd1c54 --- /dev/null +++ b/qcsrc/common/weapons/calculations.qh @@ -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/items.qc b/qcsrc/common/weapons/weapons.qc similarity index 98% rename from qcsrc/common/items.qc rename to qcsrc/common/weapons/weapons.qc index c961895d9..6d4ac360b 100644 --- a/qcsrc/common/items.qc +++ b/qcsrc/common/weapons/weapons.qc @@ -1,3 +1,8 @@ +#ifndef MENUQC +#include "calculations.qc" +#endif +#include "all.qh" + // WEAPON PLUGIN SYSTEM entity weapon_info[WEP_MAXCOUNT]; entity dummy_weapon_info; diff --git a/qcsrc/common/weapons/weapons.qh b/qcsrc/common/weapons/weapons.qh index beaebaf55..d4ccf2ba6 100644 --- a/qcsrc/common/weapons/weapons.qh +++ b/qcsrc/common/weapons/weapons.qh @@ -1,26 +1,260 @@ -// 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); diff --git a/qcsrc/menu/progs.src b/qcsrc/menu/progs.src index 36905e17a..fc21640a7 100644 --- a/qcsrc/menu/progs.src +++ b/qcsrc/menu/progs.src @@ -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 diff --git a/qcsrc/server/progs.src b/qcsrc/server/progs.src index cf969eb4b..fd586c3d2 100644 --- a/qcsrc/server/progs.src +++ b/qcsrc/server/progs.src @@ -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 -- 2.39.2