X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fcommon%2Fweapons%2Fall.qc;h=d1bd2d7e649da0c9bdb8c32a1a80e8890ecae573;hp=f97ed6d893e4c95407f2752574a2d087681f6b41;hb=c533c16caf393c1440a10aa49d3581e280c9f4bd;hpb=2140933d4a98474446e12c00aa504cdfe0a21e9c diff --git a/qcsrc/common/weapons/all.qc b/qcsrc/common/weapons/all.qc index f97ed6d89..d1bd2d7e6 100644 --- a/qcsrc/common/weapons/all.qc +++ b/qcsrc/common/weapons/all.qc @@ -4,50 +4,51 @@ #include "all.qh" #if defined(CSQC) - #include "../../client/defs.qh" + #include #include "../constants.qh" #include "../stats.qh" - #include "../../lib/warpzone/anglestransform.qh" - #include "../../lib/warpzone/common.qh" - #include "../../lib/warpzone/client.qh" + #include + #include + #include #include "../util.qh" - #include "../buffs/all.qh" - #include "../../client/autocvars.qh" + #include #include "../deathtypes/all.qh" - #include "../../lib/csqcmodel/interpolate.qh" - #include "../movetypes/movetypes.qh" - #include "../../client/main.qh" - #include "../../lib/csqcmodel/cl_model.qh" + #include + #include "../physics/movetypes/movetypes.qh" + #include + #include #elif defined(MENUQC) #elif defined(SVQC) - #include "../../lib/warpzone/anglestransform.qh" - #include "../../lib/warpzone/common.qh" - #include "../../lib/warpzone/util_server.qh" - #include "../../lib/warpzone/server.qh" + #include + #include + #include + #include #include "../constants.qh" #include "../stats.qh" #include "../teams.qh" #include "../util.qh" - #include "../buffs/all.qh" #include "../monsters/all.qh" #include "config.qh" - #include "../../server/weapons/csqcprojectile.qh" - #include "../../server/weapons/tracing.qh" - #include "../../server/t_items.qh" - #include "../../server/autocvars.qh" - #include "../../server/constants.qh" - #include "../../server/defs.qh" - #include "../notifications.qh" + #include + #include + #include "../t_items.qh" + #include + #include + #include + #include "../notifications/all.qh" #include "../deathtypes/all.qh" - #include "../../server/mutators/all.qh" + #include #include "../mapinfo.qh" - #include "../../server/command/common.qh" - #include "../../lib/csqcmodel/sv_model.qh" - #include "../../server/portals.qh" - #include "../../server/g_hook.qh" + #include + #include + #include + #include #endif #ifndef MENUQC -#include "calculations.qc" + #include "calculations.qc" +#endif +#ifdef SVQC + #include "config.qc" #endif #define IMPLEMENTATION #include "all.inc" @@ -55,76 +56,46 @@ // WEAPON PLUGIN SYSTEM -WepSet WepSet_FromWeapon(int a) { +WepSet _WepSet_FromWeapon(int a) +{ a -= WEP_FIRST; if (Weapons_MAX > 24) - if (a >= 24) { - a -= 24; - if (Weapons_MAX > 48) - if (a >= 24) { + if (a >= 24) + { a -= 24; - return '0 0 1' * power2of(a); + if (Weapons_MAX > 48) + if (a >= 24) + { + a -= 24; + return '0 0 1' * power2of(a); + } + return '0 1 0' * power2of(a); } - return '0 1 0' * power2of(a); - } return '1 0 0' * power2of(a); } #ifdef SVQC -void WepSet_AddStat() -{ - addstat(STAT_WEAPONS, AS_INT, weapons_x); - if (Weapons_MAX > 24) - addstat(STAT_WEAPONS2, AS_INT, weapons_y); - if (Weapons_MAX > 48) - addstat(STAT_WEAPONS3, AS_INT, weapons_z); -} -void WepSet_AddStat_InMap() -{ - addstat(STAT_WEAPONSINMAP, AS_INT, weaponsinmap_x); - if (Weapons_MAX > 24) - addstat(STAT_WEAPONSINMAP2, AS_INT, weaponsinmap_y); - if (Weapons_MAX > 48) - addstat(STAT_WEAPONSINMAP3, AS_INT, weaponsinmap_z); -} -void WriteWepSet(float dst, WepSet w) -{ - if (Weapons_MAX > 48) - WriteInt72_t(dst, w); - else if (Weapons_MAX > 24) - WriteInt48_t(dst, w); - else - WriteInt24_t(dst, w.x); -} + void WriteWepSet(float dst, WepSet w) + { + if (Weapons_MAX > 48) WriteInt72_t(dst, w); + else if (Weapons_MAX > 24) WriteInt48_t(dst, w); + else WriteInt24_t(dst, w.x); + } #endif #ifdef CSQC -WepSet WepSet_GetFromStat() -{ - WepSet w = '0 0 0'; - w.x = getstati(STAT_WEAPONS); - if (Weapons_MAX > 24) - w.y = getstati(STAT_WEAPONS2); - if (Weapons_MAX > 48) - w.z = getstati(STAT_WEAPONS3); - return w; -} -WepSet WepSet_GetFromStat_InMap() -{ - WepSet w = '0 0 0'; - w_x = getstati(STAT_WEAPONSINMAP); - if (Weapons_MAX > 24) - w_y = getstati(STAT_WEAPONSINMAP2); - if (Weapons_MAX > 48) - w_z = getstati(STAT_WEAPONSINMAP3); - return w; -} -WepSet ReadWepSet() -{ - if (Weapons_MAX > 48) - return ReadInt72_t(); - if (Weapons_MAX > 24) - return ReadInt48_t(); - return ReadInt24_t() * '1 0 0'; -} + WepSet WepSet_GetFromStat() + { + return STAT(WEAPONS); + } + WepSet WepSet_GetFromStat_InMap() + { + return STAT(WEAPONSINMAP); + } + WepSet ReadWepSet() + { + if (Weapons_MAX > 48) return ReadInt72_t(); + if (Weapons_MAX > 24) return ReadInt48_t(); + return ReadInt24_t() * '1 0 0'; + } #endif string W_FixWeaponOrder(string order, float complete) @@ -133,27 +104,26 @@ string W_FixWeaponOrder(string order, float complete) } string W_NameWeaponOrder_MapFunc(string s) { - entity wi; - if(s == "0" || stof(s)) + int i = stof(s); + if (s == "0" || i) { - wi = get_weaponinfo(stof(s)); - if(wi != WEP_Null) - return wi.netname; + entity wi = Weapons_from(i); + if (wi != WEP_Null) return wi.netname; } return s; } string W_UndeprecateName(string s) { - switch ( s ) + switch (s) { - case "nex" : return "vortex"; - case "rocketlauncher" : return "devastator"; - case "laser" : return "blaster"; - case "minstanex" : return "vaporizer"; + case "nex": return "vortex"; + case "rocketlauncher": return "devastator"; + case "laser": return "blaster"; + case "minstanex": return "vaporizer"; case "grenadelauncher": return "mortar"; - case "uzi" : return "machinegun"; - default : return s; + case "uzi": return "machinegun"; + default: return s; } } string W_NameWeaponOrder(string order) @@ -162,13 +132,9 @@ string W_NameWeaponOrder(string order) } string W_NumberWeaponOrder_MapFunc(string s) { - int i; - if(s == "0" || stof(s)) - return s; + if (s == "0" || stof(s)) return s; s = W_UndeprecateName(s); - for(i = WEP_FIRST; i <= WEP_LAST; ++i) - if(s == get_weaponinfo(i).netname) - return ftos(i); + FOREACH(Weapons, it != WEP_Null && it.netname == s, return ftos(i)); return s; } string W_NumberWeaponOrder(string order) @@ -187,60 +153,62 @@ void W_FixWeaponOrder_BuildImpulseList_swap(int i, int j, entity pass) } float W_FixWeaponOrder_BuildImpulseList_cmp(int i, int 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 = (e1.impulse + 9) % 10 - (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! + int si = W_FixWeaponOrder_BuildImpulseList_buf[i]; + Weapon e1 = Weapons_from(si); + int sj = W_FixWeaponOrder_BuildImpulseList_buf[j]; + Weapon e2 = Weapons_from(sj); + int d = (e1.impulse + 9) % 10 - (e2.impulse + 9) % 10; + if (d != 0) return -d; // high impulse first! + return strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), + sprintf(" %d ", si), 0) + - + strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), + sprintf(" %d ", sj), 0) + ; // low char index first! } string W_FixWeaponOrder_BuildImpulseList(string o) { int i; W_FixWeaponOrder_BuildImpulseList_order = o; - for(i = WEP_FIRST; i <= WEP_LAST; ++i) + 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); + heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, + NULL); o = ""; - for(i = WEP_FIRST; i <= WEP_LAST; ++i) + 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) +string W_FixWeaponOrder_AllowIncomplete(entity this, string order) { return W_FixWeaponOrder(order, 0); } string W_FixWeaponOrder_ForceComplete(string order) { - if(order == "") - order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority")); + if (order == "") order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority")); return W_FixWeaponOrder(order, 1); } void W_RandomWeapons(entity e, float n) { - int i, j; + int i; WepSet remaining; WepSet result; remaining = e.weapons; result = '0 0 0'; - for(i = 0; i < n; ++i) + for (i = 0; i < n; ++i) { RandomSelection_Init(); - for(j = WEP_FIRST; j <= WEP_LAST; ++j) - if(remaining & WepSet_FromWeapon(j)) - RandomSelection_Add(world, j, string_null, 1, 1); - result |= WepSet_FromWeapon(RandomSelection_chosen_float); - remaining &= ~WepSet_FromWeapon(RandomSelection_chosen_float); + FOREACH(Weapons, it != WEP_Null, { + if (remaining & (it.m_wepset)) + RandomSelection_Add(it, 0, string_null, 1, 1); + }); + Weapon w = RandomSelection_chosen_ent; + result |= WepSet_FromWeapon(w); + remaining &= ~WepSet_FromWeapon(w); } e.weapons = result; } @@ -255,72 +223,119 @@ string GetAmmoPicture(.int ammotype) case ammo_cells: return ITEM_Cells.m_icon; case ammo_plasma: return ITEM_Plasma.m_icon; case ammo_fuel: return ITEM_JetpackFuel.m_icon; - default: return ""; // wtf, no ammo type? + default: return ""; // wtf, no ammo type? } } #ifdef CSQC -.int GetAmmoFieldFromNum(int i) -{ - switch(i) + .int GetAmmoFieldFromNum(int i) { - case 0: return ammo_shells; - case 1: return ammo_nails; - case 2: return ammo_rockets; - case 3: return ammo_cells; - case 4: return ammo_plasma; - case 5: return ammo_fuel; - default: return ammo_none; + switch (i) + { + case 0: return ammo_shells; + case 1: return ammo_nails; + case 2: return ammo_rockets; + case 3: return ammo_cells; + case 4: return ammo_plasma; + case 5: return ammo_fuel; + default: return ammo_none; + } } -} -int GetAmmoStat(.int ammotype) -{ - switch(ammotype) + int GetAmmoStat(.int ammotype) { - case ammo_shells: return STAT_SHELLS; - case ammo_nails: return STAT_NAILS; - case ammo_rockets: return STAT_ROCKETS; - case ammo_cells: return STAT_CELLS; - case ammo_plasma: return STAT_PLASMA; - case ammo_fuel: return STAT_FUEL; - default: return -1; + switch (ammotype) + { + case ammo_shells: return STAT_SHELLS; + case ammo_nails: return STAT_NAILS; + case ammo_rockets: return STAT_ROCKETS; + case ammo_cells: return STAT_CELLS; + case ammo_plasma: return STAT_PLASMA.m_id; + case ammo_fuel: return STAT_FUEL.m_id; + default: return -1; + } } -} #endif string W_Sound(string w_snd) { - #define extensions(X) X(wav) X(ogg) - #define tryext(ext) { if (fexists(strcat("sound/", output = strcat("weapons/", w_snd, "."#ext)))) break; } - string output; - do { - extensions(tryext); - #undef tryext - #undef extensions - output = strcat("weapons/", w_snd); - } while (0); - + string output = strcat("weapons/", w_snd); #ifdef SVQC - MUTATOR_CALLHOOK(WeaponSound, w_snd, output); - return weapon_sound_output; + MUTATOR_CALLHOOK(WeaponSound, w_snd, output); + return M_ARGV(1, string); #else - return output; + return output; #endif } string W_Model(string w_mdl) { string output = strcat("models/weapons/", w_mdl); -#ifdef SVQC MUTATOR_CALLHOOK(WeaponModel, w_mdl, output); - return weapon_model_output; -#else - return output; -#endif + return M_ARGV(1, string); } +#ifndef MENUQC +vector shotorg_adjustfromclient(vector vecs, float y_is_right, float algn) +{ + switch (algn) + { + default: + case 3: + // right alignment + break; + case 4: + // left + vecs.y = -vecs.y; + break; + case 1: + case 2: + // center + vecs.y = 0; + vecs.z -= 2; + break; + } + return vecs; +} + +vector shotorg_adjust_values(vector vecs, bool y_is_right, bool visual, int algn) +{ +#ifdef SVQC + string s; +#endif + if (visual) + { + vecs = shotorg_adjustfromclient(vecs, y_is_right, algn); + } #ifdef SVQC + else if (autocvar_g_shootfromeye) + { + vecs.y = vecs.z = 0; + } + else if (autocvar_g_shootfromcenter) + { + vecs.y = 0; + vecs.z -= 2; + } + else if ((s = autocvar_g_shootfromfixedorigin) != "") + { + vector v = stov(s); + if (y_is_right) v.y = -v.y; + if (v.x != 0) vecs.x = v.x; + vecs.y = v.y; + vecs.z = v.z; + } +#endif + else // just do the same as top + { + vecs = shotorg_adjustfromclient(vecs, y_is_right, algn); + } + + return vecs; +} + +#define shotorg_adjust shotorg_adjust_values + /** * supported formats: * @@ -372,12 +387,12 @@ string W_Model(string w_mdl) * call again with "" * remove the ent */ -void CL_WeaponEntity_SetModel(entity this, int slot, string name) +void CL_WeaponEntity_SetModel(entity this, string name, bool _anim) { if (name == "") { this.model = ""; - if (this.weaponchild) remove(this.weaponchild); + if (this.weaponchild) delete(this.weaponchild); this.weaponchild = NULL; this.movedir = '0 0 0'; this.spawnorigin = '0 0 0'; @@ -392,7 +407,7 @@ void CL_WeaponEntity_SetModel(entity this, int slot, string name) // if there is a child entity, hide it until we're sure we use it if (this.weaponchild) this.weaponchild.model = ""; _setmodel(this, W_Model(strcat("v_", name, ".md3"))); - int v_shot_idx; // used later + int v_shot_idx; // used later (v_shot_idx = gettagindex(this, "shot")) || (v_shot_idx = gettagindex(this, "tag_shot")); _setmodel(this, W_Model(strcat("h_", name, ".iqm"))); @@ -407,21 +422,33 @@ void CL_WeaponEntity_SetModel(entity this, int slot, string name) string t; if ((t = "weapon", gettagindex(this, t)) || (t = "tag_weapon", gettagindex(this, t))) { - if (!this.weaponchild) this.weaponchild = new(weaponchild); + if (!this.weaponchild) + { + this.weaponchild = new(weaponchild); +#ifdef CSQC + this.weaponchild.drawmask = MASK_NORMAL; + this.weaponchild.renderflags |= RF_VIEWMODEL; +#endif + } _setmodel(this.weaponchild, W_Model(strcat("v_", name, ".md3"))); + setsize(this.weaponchild, '0 0 0', '0 0 0'); setattachment(this.weaponchild, this, t); } else { - if (this.weaponchild) remove(this.weaponchild); + if (this.weaponchild) delete(this.weaponchild); this.weaponchild = NULL; } + setsize(this, '0 0 0', '0 0 0'); setorigin(this, '0 0 0'); this.angles = '0 0 0'; this.frame = 0; +#ifdef SVQC this.viewmodelforclient = NULL; - +#else + this.renderflags &= ~RF_VIEWMODEL; +#endif if (v_shot_idx) // v_ model attached to invisible h_ model { this.movedir = gettaginfo(this.weaponchild, v_shot_idx); @@ -435,29 +462,29 @@ void CL_WeaponEntity_SetModel(entity this, int slot, string name) } else { - LOG_WARNINGF("weapon model %s does not support the 'shot' tag, will display shots TOTALLY wrong\n", + LOG_WARNF("weapon model %s does not support the 'shot' tag, will display shots TOTALLY wrong", this.model); this.movedir = '0 0 0'; } } - { - int idx = 0; - // v_ model attached to invisible h_ model - if (this.weaponchild - && ((idx = gettagindex(this.weaponchild, "shell")) || (idx = gettagindex(this.weaponchild, "tag_shell")))) - { - this.spawnorigin = gettaginfo(this.weaponchild, idx); - } - else if ((idx = gettagindex(this, "shell")) || (idx = gettagindex(this, "tag_shell"))) - { - this.spawnorigin = gettaginfo(this, idx); - } - else - { - LOG_WARNINGF("weapon model %s does not support the 'shell' tag, will display casings wrong\n", - this.model); - this.spawnorigin = this.movedir; - } + { + int idx = 0; + // v_ model attached to invisible h_ model + if (this.weaponchild + && ((idx = gettagindex(this.weaponchild, "shell")) || (idx = gettagindex(this.weaponchild, "tag_shell")))) + { + this.spawnorigin = gettaginfo(this.weaponchild, idx); + } + else if ((idx = gettagindex(this, "shell")) || (idx = gettagindex(this, "tag_shell"))) + { + this.spawnorigin = gettaginfo(this, idx); + } + else + { + LOG_WARNF("weapon model %s does not support the 'shell' tag, will display casings wrong", + this.model); + this.spawnorigin = this.movedir; + } } if (v_shot_idx) { @@ -476,7 +503,7 @@ void CL_WeaponEntity_SetModel(entity this, int slot, string name) } else { - LOG_WARNINGF( + LOG_WARNF( "weapon model %s does not support the 'handle' tag " "and neither does the v_ model support the 'shot' tag, " "will display muzzle flashes TOTALLY wrong\n", @@ -485,28 +512,143 @@ void CL_WeaponEntity_SetModel(entity this, int slot, string name) } } +#ifdef SVQC this.viewmodelforclient = this.owner; +#else + this.renderflags |= RF_VIEWMODEL; +#endif } this.view_ofs = '0 0 0'; if (this.movedir.x >= 0) { + int algn = STAT(GUNALIGN, this.owner); vector v = this.movedir; - this.movedir = shotorg_adjust(v, false, false, this.owner.cvar_cl_gunalign); - this.view_ofs = shotorg_adjust(v, false, true, this.owner.cvar_cl_gunalign) - v; + this.movedir = shotorg_adjust(v, false, false, algn); + this.view_ofs = shotorg_adjust(v, false, true, algn) - v; } - this.owner.stat_shotorg = compressShotOrigin(this.movedir); - this.movedir = decompressShotOrigin(this.owner.stat_shotorg); // make them match perfectly + int compressed_shotorg = compressShotOrigin(this.movedir); + // make them match perfectly +#ifdef SVQC + this.movedir = decompressShotOrigin(this.owner.stat_shotorg = compressed_shotorg); +#else + this.movedir = decompressShotOrigin(compressed_shotorg); +#endif - this.spawnorigin += this.view_ofs; // offset the casings origin by the same amount + this.spawnorigin += this.view_ofs; // offset the casings origin by the same amount // check if an instant weapon switch occurred setorigin(this, this.view_ofs); + if (!_anim) return; // reset animstate now this.wframe = WFRAME_IDLE; setanim(this, this.anim_idle, true, false, true); } #endif +#ifndef MENUQC + +REGISTER_NET_TEMP(wframe) +#ifdef CSQC +NET_HANDLE(wframe, bool isNew) +{ + vector a; + a.x = ReadCoord(); + a.y = ReadCoord(); + a.z = ReadCoord(); + bool restartanim = ReadByte(); + anim_set(viewmodel, a, !restartanim, restartanim, restartanim); + viewmodel.state = ReadByte(); + viewmodel.weapon_nextthink = ReadFloat(); + viewmodel.alpha = ReadByte() / 255; + switch (viewmodel.state) + { + case WS_RAISE: + viewmodel.weapon_switchdelay = activeweapon.switchdelay_raise; + break; + case WS_DROP: + viewmodel.weapon_switchdelay = activeweapon.switchdelay_drop; + break; + default: + viewmodel.weapon_switchdelay = 0; + break; + } + return true; +} +#endif + +#ifdef SVQC +void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim) +{ + if (!IS_REAL_CLIENT(actor)) return; + int channel = MSG_ONE; + msg_entity = actor; + WriteHeader(channel, wframe); + WriteCoord(channel, a.x); + WriteCoord(channel, a.y); + WriteCoord(channel, a.z); + WriteByte(channel, restartanim); + WriteByte(channel, weaponentity.state); + WriteFloat(channel, weaponentity.weapon_nextthink); + WriteByte(channel, weaponentity.m_alpha * 255); +} +#endif + +REGISTER_NET_C2S(w_whereis) +#ifdef SVQC +void Weapon_whereis(Weapon this, entity cl); +NET_HANDLE(w_whereis, bool) +{ + Weapon wpn = ReadRegistered(Weapons); + if (wpn != WEP_Null) Weapon_whereis(wpn, sender); + return true; +} +#else +void w_whereis(Weapon this) +{ + int channel = MSG_C2S; + WriteHeader(channel, w_whereis); + WriteRegistered(Weapons, channel, this); +} +CLIENT_COMMAND(weapon_find, "Show spawn locations of a weapon") +{ + switch (request) + { + case CMD_REQUEST_COMMAND: + { + string s = argv(1); + if (s == "all") + { + FOREACH(Weapons, it != WEP_Null, w_whereis(it)); + return; + } + if (s == "unowned") + { + FOREACH(Weapons, it != WEP_Null && !(STAT(WEAPONS) & it.m_wepset), w_whereis(it)); + return; + } + FOREACH(Weapons, it != WEP_Null && it.netname == s, + { + w_whereis(it); + return; + }); + } + default: + { + LOG_INFOF("Incorrect parameters for ^2%s^7\n", "weapon_find"); + } + case CMD_REQUEST_USAGE: + { + LOG_INFO("\nUsage:^3 cl_cmd weapon_find weapon\n"); + LOG_INFO(" Where 'weapon' is the lowercase weapon name, 'all' or 'unowned'.\n"); + return; + } + } +} +#endif + + +#endif + #endif