X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fcommon%2Ft_items.qc;h=f295c1da3eaa092bf1cf4dba4d756b4338369b48;hp=af0c52e2345f76e0721e8b8732156179733ffbf8;hb=30e724fe1e818fa1a1e57250f260f7141f1f379b;hpb=646e82672a7a8b8db0be0caf5dbd062b0d04da96 diff --git a/qcsrc/common/t_items.qc b/qcsrc/common/t_items.qc index af0c52e234..f295c1da3e 100644 --- a/qcsrc/common/t_items.qc +++ b/qcsrc/common/t_items.qc @@ -22,6 +22,8 @@ #include + #include + #include "../lib/warpzone/util_server.qh" #elif defined(CSQC) #include "physics/movetypes/movetypes.qh" @@ -82,6 +84,11 @@ void ItemDraw(entity this) if(this.ItemStatus & ITS_ANIMATE2) this.avelocity = '0 -90 0'; } + + // delay is for blocking item's position for a while; + // it's a workaround for dropped weapons that receive the position + // another time right after they spawn overriding animation position + this.onground_time = time + 0.5; } } else if (autocvar_cl_animate_items) @@ -89,13 +96,15 @@ void ItemDraw(entity this) if(this.ItemStatus & ITS_ANIMATE1) { this.angles += this.avelocity * frametime; - setorigin(this, '0 0 10' + this.oldorigin + '0 0 8' * sin(time * 2)); + float fade_in = bound(0, time - this.onground_time, 1); + setorigin(this, this.oldorigin + fade_in * ('0 0 10' + '0 0 8' * sin((time - this.onground_time) * 2))); } if(this.ItemStatus & ITS_ANIMATE2) { this.angles += this.avelocity * frametime; - setorigin(this, '0 0 8' + this.oldorigin + '0 0 4' * sin(time * 3)); + float fade_in = bound(0, time - this.onground_time, 1); + setorigin(this, this.oldorigin + fade_in * ('0 0 8' + '0 0 4' * sin((time - this.onground_time) * 3))); } } @@ -183,7 +192,7 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew) if(this.ItemStatus & ITS_ALLOWFB) this.effects |= EF_FULLBRIGHT; - if(this.ItemStatus & ITS_POWERUP) + if(this.ItemStatus & ITS_GLOW) { if(this.ItemStatus & ITS_AVAILABLE) this.effects |= (EF_ADDITIVE | EF_FULLBRIGHT); @@ -386,7 +395,7 @@ bool have_pickup_item(entity this) if(autocvar_g_pickup_items == 0) return false; if(g_weaponarena) - if(this.weapons || (this.items & IT_AMMO)) // no item or ammo pickups in weaponarena + if(this.weapons || this.itemdef.instanceOfAmmo) // no item or ammo pickups in weaponarena return false; } return true; @@ -423,6 +432,7 @@ void Item_Show (entity e, float mode) { e.effects &= ~(EF_ADDITIVE | EF_STARDUST | EF_FULLBRIGHT | EF_NODEPTHTEST); e.ItemStatus &= ~ITS_STAYWEP; + entity def = e.itemdef; if (mode > 0) { // make the item look normal, and be touchable @@ -440,7 +450,6 @@ void Item_Show (entity e, float mode) e.ItemStatus &= ~ITS_AVAILABLE; } else { - entity def = e.itemdef; bool nostay = def.instanceOfWeaponPickup ? !!(def.m_weapon.weapons & WEPSET_SUPERWEAPONS) : false // no weapon-stay on superweapons || e.team // weapon stay isn't supported for teamed weapons ; @@ -463,8 +472,8 @@ void Item_Show (entity e, float mode) e.ItemStatus &= ~ITS_AVAILABLE; }} - if (e.items & ITEM_Strength.m_itemid || e.items & ITEM_Shield.m_itemid) - e.ItemStatus |= ITS_POWERUP; + if (def.m_glow) + e.ItemStatus |= ITS_GLOW; if (autocvar_g_nodepthtestitems) e.effects |= EF_NODEPTHTEST; @@ -497,13 +506,7 @@ void Item_ItemsTime_SetTimesForAllPlayers(); void Item_Respawn (entity this) { Item_Show(this, 1); - // this is ugly... - if(this.items == ITEM_Strength.m_itemid) - sound (this, CH_TRIGGER, SND_STRENGTH_RESPAWN, VOL_BASE, ATTEN_NORM); // play respawn sound - else if(this.items == ITEM_Shield.m_itemid) - sound (this, CH_TRIGGER, SND_SHIELD_RESPAWN, VOL_BASE, ATTEN_NORM); // play respawn sound - else - sound (this, CH_TRIGGER, SND_ITEMRESPAWN, VOL_BASE, ATTEN_NORM); // play respawn sound + sound(this, CH_TRIGGER, this.itemdef.m_respawnsound, VOL_BASE, ATTEN_NORM); // play respawn sound setorigin(this, this.origin); if (Item_ItemsTime_Allow(this.itemdef) || this.weapons & WEPSET_SUPERWEAPONS) @@ -863,7 +866,7 @@ LABEL(pickup) RandomSelection_Init(); IL_EACH(g_items, it.team == this.team, { - if(it.classname != "item_flag_team" && it.classname != "item_kh_key") + if(it.itemdef) // is a registered item { Item_Show(it, -1); RandomSelection_AddEnt(it, it.cnt, 0); @@ -907,7 +910,7 @@ void Item_FindTeam(entity this) RandomSelection_Init(); IL_EACH(g_items, it.team == this.team, { - if(it.classname != "item_flag_team" && it.classname != "item_kh_key") + if(it.itemdef) // is a registered item RandomSelection_AddEnt(it, it.cnt, 0); }); @@ -917,7 +920,7 @@ void Item_FindTeam(entity this) IL_EACH(g_items, it.team == this.team, { - if(it.classname != "item_flag_team" && it.classname != "item_kh_key") + if(it.itemdef) // is a registered item { if(it != e) { @@ -948,114 +951,123 @@ float generic_pickupevalfunc(entity player, entity item) {return item.bot_pickup float weapon_pickupevalfunc(entity player, entity item) { - float c; - // See if I have it already - if(item.weapons & ~player.weapons) + if(player.weapons & item.weapons) { // If I can pick it up if(!item.spawnshieldtime) - c = 0; - else if(player.ammo_cells || player.ammo_shells || player.ammo_plasma || player.ammo_nails || player.ammo_rockets) - { - // Skilled bots will grab more - c = bound(0, skill / 10, 1) * 0.5; - } - else - c = 0; + return 0; + return ammo_pickupevalfunc(player, item); } - else - c = 1; - - // If custom weapon priorities for bots is enabled rate most wanted weapons higher - if( bot_custom_weapon && c ) - { - // Find the highest position on any range - int position = -1; - for (int j = 0; j < WEP_LAST ; ++j){ - if( - bot_weapons_far[j] == item.weapon || - bot_weapons_mid[j] == item.weapon || - bot_weapons_close[j] == item.weapon - ) - { - position = j; - break; - } - } - // Rate it - if (position >= 0 ) - { - position = WEP_LAST - position; - // item.bot_pickupbasevalue is overwritten here - return (BOT_PICKUP_RATING_LOW + ( (BOT_PICKUP_RATING_HIGH - BOT_PICKUP_RATING_LOW) * (position / WEP_LAST ))) * c; - } - } + // reduce weapon value if bot already got a good arsenal + float c = 1; + int weapons_value = 0; + FOREACH(Weapons, it != WEP_Null && (player.weapons & it.m_wepset), { + weapons_value += it.bot_pickupbasevalue; + }); + c -= bound(0, weapons_value / 20000, 1) * 0.5; return item.bot_pickupbasevalue * c; } -float commodity_pickupevalfunc(entity player, entity item) +float ammo_pickupevalfunc(entity player, entity item) { - float c; - float need_shells = false, need_nails = false, need_rockets = false, need_cells = false, need_plasma = false, need_fuel = false; - c = 0; + bool need_shells = false, need_nails = false, need_rockets = false, need_cells = false, need_plasma = false, need_fuel = false; + entity wpn = NULL; + float c = 0; + float rating = 0; // Detect needed ammo - FOREACH(Weapons, it != WEP_Null, { - if(!(player.weapons & (it.m_wepset))) - continue; + if(item.itemdef.instanceOfWeaponPickup) + { + entity ammo = NULL; + if(item.ammo_shells) { need_shells = true; ammo = ITEM_Shells; } + else if(item.ammo_nails) { need_nails = true; ammo = ITEM_Bullets; } + else if(item.ammo_rockets) { need_rockets = true; ammo = ITEM_Rockets; } + else if(item.ammo_cells) { need_cells = true; ammo = ITEM_Cells; } + else if(item.ammo_plasma) { need_plasma = true; ammo = ITEM_Plasma; } + else if(item.ammo_fuel) { need_fuel = true; ammo = ITEM_JetpackFuel; } - if(it.items & ITEM_Shells.m_itemid) - need_shells = true; - else if(it.items & ITEM_Bullets.m_itemid) - need_nails = true; - else if(it.items & ITEM_Rockets.m_itemid) - need_rockets = true; - else if(it.items & ITEM_Cells.m_itemid) - need_cells = true; - else if(it.items & ITEM_Plasma.m_itemid) - need_plasma = true; - else if(it.items & ITEM_JetpackFuel.m_itemid) - need_fuel = true; - }); + if(!ammo) + return 0; + wpn = item; + rating = ammo.m_botvalue; + } + else + { + FOREACH(Weapons, it != WEP_Null, { + if(!(player.weapons & (it.m_wepset))) + continue; + + switch(it.ammo_field) + { + case ammo_shells: need_shells = true; break; + case ammo_shells: need_shells = true; break; + case ammo_nails: need_nails = true; break; + case ammo_rockets: need_rockets = true; break; + case ammo_cells: need_cells = true; break; + case ammo_plasma: need_plasma = true; break; + case ammo_fuel: need_fuel = true; break; + } + }); + rating = item.bot_pickupbasevalue; + } - // TODO: figure out if the player even has the weapon this ammo is for? - // may not affect strategy much though... - // find out how much more ammo/armor/health the player can hold if (need_shells) if (item.ammo_shells) if (player.ammo_shells < g_pickup_shells_max) - c = c + max(0, 1 - player.ammo_shells / g_pickup_shells_max); + c = item.ammo_shells / player.ammo_shells; if (need_nails) if (item.ammo_nails) if (player.ammo_nails < g_pickup_nails_max) - c = c + max(0, 1 - player.ammo_nails / g_pickup_nails_max); + c = item.ammo_nails / player.ammo_nails; if (need_rockets) if (item.ammo_rockets) if (player.ammo_rockets < g_pickup_rockets_max) - c = c + max(0, 1 - player.ammo_rockets / g_pickup_rockets_max); + c = item.ammo_rockets / player.ammo_rockets; if (need_cells) if (item.ammo_cells) if (player.ammo_cells < g_pickup_cells_max) - c = c + max(0, 1 - player.ammo_cells / g_pickup_cells_max); + c = item.ammo_cells / player.ammo_cells; if (need_plasma) if (item.ammo_plasma) if (player.ammo_plasma < g_pickup_plasma_max) - c = c + max(0, 1 - player.ammo_plasma / g_pickup_plasma_max); + c = item.ammo_plasma / player.ammo_plasma; if (need_fuel) if (item.ammo_fuel) if (player.ammo_fuel < g_pickup_fuel_max) - c = c + max(0, 1 - player.ammo_fuel / g_pickup_fuel_max); - if (item.armorvalue) + c = item.ammo_fuel / player.ammo_fuel; + + rating *= min(2, c); + if(wpn) + rating += wpn.bot_pickupbasevalue * 0.1; + return rating; +} + +.int item_group; +.int item_group_count; +float healtharmor_pickupevalfunc(entity player, entity item) +{ + float c = 0; + float rating = item.bot_pickupbasevalue; + + float itemarmor = item.armorvalue; + float itemhealth = item.health; + if(item.item_group) + { + itemarmor *= min(4, item.item_group_count); + itemhealth *= min(4, item.item_group_count); + } + if (itemarmor) if (player.armorvalue < item.max_armorvalue) - c = c + max(0, 1 - player.armorvalue / item.max_armorvalue); - if (item.health) + c = itemarmor / max(1, player.armorvalue * 2/3 + player.health * 1/3); + if (itemhealth) if (player.health < item.max_health) - c = c + max(0, 1 - player.health / item.max_health); + c = itemhealth / max(1, player.health); - return item.bot_pickupbasevalue * c; + rating *= min(2, c); + return rating; } void Item_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force) @@ -1064,6 +1076,12 @@ void Item_Damage(entity this, entity inflictor, entity attacker, float damage, i RemoveItem(this); } +void item_use(entity this, entity actor, entity trigger) +{ + // use the touch function to handle collection + gettouch(this)(this, actor); +} + void _StartItem(entity this, entity def, float defaultrespawntime, float defaultrespawntimejitter) { string itemname = def.m_name; @@ -1084,6 +1102,9 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default this.respawntimejitter = defaultrespawntimejitter; } + if(!this.pickup_anyway && def.m_pickupanyway) + this.pickup_anyway = def.m_pickupanyway(); + int itemid = def.m_itemid; this.items = itemid; int weaponid = def.instanceOfWeaponPickup ? def.m_weapon.m_id : 0; @@ -1185,6 +1206,9 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default } */ + if(this.targetname != "" && (this.spawnflags & 16)) + this.use = item_use; + if(autocvar_spawn_debug >= 2) { // why not flags & fl_item? @@ -1264,6 +1288,8 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default delete(this); return; } + + setItemGroup(this); } void StartItem(entity this, GameItem def) @@ -1276,12 +1302,58 @@ void StartItem(entity this, GameItem def) ); } +#define IS_SMALL(def) ((def.instanceOfHealth && def == ITEM_HealthSmall) || (def.instanceOfArmor && def == ITEM_ArmorSmall)) +int group_count = 1; + +void setItemGroup(entity this) +{ + if(!IS_SMALL(this.itemdef)) + return; + + FOREACH_ENTITY_RADIUS(this.origin, 120, (it != this) && IS_SMALL(it.itemdef), + { + if(!this.item_group) + { + if(!it.item_group) + { + it.item_group = group_count; + group_count++; + } + this.item_group = it.item_group; + } + else // spawning item is already part of a item_group X + { + if(!it.item_group) + it.item_group = this.item_group; + else if(it.item_group != this.item_group) // found an item near the spawning item that is part of a different item_group Y + { + int grY = it.item_group; + // move all items of item_group Y to item_group X + FOREACH_ENTITY(IS_SMALL(it.itemdef), + { + if(it.item_group == grY) + it.item_group = this.item_group; + }); + } + } + }); +} + +void setItemGroupCount() +{ + for (int k = 1; k <= group_count; k++) + { + int count = 0; + FOREACH_ENTITY(IS_SMALL(it.itemdef) && it.item_group == k, { count++; }); + if (count) + FOREACH_ENTITY(IS_SMALL(it.itemdef) && it.item_group == k, { it.item_group_count = count; }); + } +} + spawnfunc(item_rockets) { if(!this.ammo_rockets) this.ammo_rockets = g_pickup_rockets; - if(!this.pickup_anyway) - this.pickup_anyway = g_pickup_ammo_anyway; StartItem(this, ITEM_Rockets); } @@ -1299,8 +1371,6 @@ spawnfunc(item_bullets) if(!this.ammo_nails) this.ammo_nails = g_pickup_nails; - if(!this.pickup_anyway) - this.pickup_anyway = g_pickup_ammo_anyway; StartItem(this, ITEM_Bullets); } @@ -1308,8 +1378,6 @@ spawnfunc(item_cells) { if(!this.ammo_cells) this.ammo_cells = g_pickup_cells; - if(!this.pickup_anyway) - this.pickup_anyway = g_pickup_ammo_anyway; StartItem(this, ITEM_Cells); } @@ -1317,8 +1385,6 @@ spawnfunc(item_plasma) { if(!this.ammo_plasma) this.ammo_plasma = g_pickup_plasma; - if(!this.pickup_anyway) - this.pickup_anyway = g_pickup_ammo_anyway; StartItem(this, ITEM_Plasma); } @@ -1336,8 +1402,6 @@ spawnfunc(item_shells) if(!this.ammo_shells) this.ammo_shells = g_pickup_shells; - if(!this.pickup_anyway) - this.pickup_anyway = g_pickup_ammo_anyway; StartItem(this, ITEM_Shells); } @@ -1347,8 +1411,6 @@ spawnfunc(item_armor_small) this.armorvalue = g_pickup_armorsmall; if(!this.max_armorvalue) this.max_armorvalue = g_pickup_armorsmall_max; - if(!this.pickup_anyway) - this.pickup_anyway = g_pickup_armorsmall_anyway; StartItem(this, ITEM_ArmorSmall); } @@ -1358,8 +1420,6 @@ spawnfunc(item_armor_medium) this.armorvalue = g_pickup_armormedium; if(!this.max_armorvalue) this.max_armorvalue = g_pickup_armormedium_max; - if(!this.pickup_anyway) - this.pickup_anyway = g_pickup_armormedium_anyway; StartItem(this, ITEM_ArmorMedium); } @@ -1369,19 +1429,15 @@ spawnfunc(item_armor_big) this.armorvalue = g_pickup_armorbig; if(!this.max_armorvalue) this.max_armorvalue = g_pickup_armorbig_max; - if(!this.pickup_anyway) - this.pickup_anyway = g_pickup_armorbig_anyway; - StartItem(this, ITEM_ArmorLarge); + StartItem(this, ITEM_ArmorBig); } -spawnfunc(item_armor_large) +spawnfunc(item_armor_mega) { if(!this.armorvalue) - this.armorvalue = g_pickup_armorlarge; + this.armorvalue = g_pickup_armormega; if(!this.max_armorvalue) - this.max_armorvalue = g_pickup_armorlarge_max; - if(!this.pickup_anyway) - this.pickup_anyway = g_pickup_armorlarge_anyway; + this.max_armorvalue = g_pickup_armormega_max; StartItem(this, ITEM_ArmorMega); } @@ -1391,8 +1447,6 @@ spawnfunc(item_health_small) this.max_health = g_pickup_healthsmall_max; if(!this.health) this.health = g_pickup_healthsmall; - if(!this.pickup_anyway) - this.pickup_anyway = g_pickup_healthsmall_anyway; StartItem(this, ITEM_HealthSmall); } @@ -1402,20 +1456,16 @@ spawnfunc(item_health_medium) this.max_health = g_pickup_healthmedium_max; if(!this.health) this.health = g_pickup_healthmedium; - if(!this.pickup_anyway) - this.pickup_anyway = g_pickup_healthmedium_anyway; StartItem(this, ITEM_HealthMedium); } -spawnfunc(item_health_large) +spawnfunc(item_health_big) { if(!this.max_health) - this.max_health = g_pickup_healthlarge_max; + this.max_health = g_pickup_healthbig_max; if(!this.health) - this.health = g_pickup_healthlarge; - if(!this.pickup_anyway) - this.pickup_anyway = g_pickup_healthlarge_anyway; - StartItem(this, ITEM_HealthLarge); + this.health = g_pickup_healthbig; + StartItem(this, ITEM_HealthBig); } spawnfunc(item_health_mega) @@ -1424,16 +1474,16 @@ spawnfunc(item_health_mega) this.max_health = g_pickup_healthmega_max; if(!this.health) this.health = g_pickup_healthmega; - if(!this.pickup_anyway) - this.pickup_anyway = g_pickup_healthmega_anyway; StartItem(this, ITEM_HealthMega); } // support old misnamed entities spawnfunc(item_armor1) { spawnfunc_item_armor_small(this); } // FIXME: in Quake this is green armor, in Xonotic maps it is an armor shard -spawnfunc(item_armor25) { spawnfunc_item_armor_large(this); } +spawnfunc(item_armor25) { spawnfunc_item_armor_mega(this); } +spawnfunc(item_armor_large) { spawnfunc_item_armor_mega(this); } spawnfunc(item_health1) { spawnfunc_item_health_small(this); } spawnfunc(item_health25) { spawnfunc_item_health_medium(this); } +spawnfunc(item_health_large) { spawnfunc_item_health_big(this); } spawnfunc(item_health100) { spawnfunc_item_health_mega(this); } spawnfunc(item_strength) @@ -1512,6 +1562,15 @@ spawnfunc(target_items) else if(argv(j) == "fuel_regen") this.items |= ITEM_JetpackRegen.m_itemid; else { + FOREACH(Buffs, it != BUFF_Null, + { + s = Buff_UndeprecateName(argv(j)); + if(s == it.m_name) + { + this.buffs |= (it.m_itemid); + break; + } + }); FOREACH(Weapons, it != WEP_Null, { s = W_UndeprecateName(argv(j)); if(s == it.netname) @@ -1568,6 +1627,7 @@ spawnfunc(target_items) if(this.ammo_fuel != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, this.ammo_fuel), "fuel"); if(this.health != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, this.health), "health"); if(this.armorvalue != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, this.armorvalue), "armor"); + FOREACH(Buffs, it != BUFF_Null, this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, !!(this.buffs & (it.m_itemid)), it.m_name)); FOREACH(Weapons, it != WEP_Null, this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, !!(this.weapons & (it.m_wepset)), it.netname)); } this.netname = strzone(this.netname); @@ -1587,8 +1647,6 @@ spawnfunc(item_fuel) { if(!this.ammo_fuel) this.ammo_fuel = g_pickup_fuel; - if(!this.pickup_anyway) - this.pickup_anyway = g_pickup_ammo_anyway; StartItem(this, ITEM_JetpackFuel); } @@ -1645,6 +1703,35 @@ float GiveWeapon(entity e, float wpn, float op, float val) return (v0 != v1); } +bool GiveBuff(entity e, Buff thebuff, int op, int val) +{ + bool had_buff = (e.buffs & thebuff.m_itemid); + switch(op) + { + case OP_SET: + if(val > 0) + e.buffs |= thebuff.m_itemid; + else + e.buffs &= ~thebuff.m_itemid; + break; + case OP_MIN: + case OP_PLUS: + if(val > 0) + e.buffs |= thebuff.m_itemid; + break; + case OP_MAX: + if(val <= 0) + e.buffs &= ~thebuff.m_itemid; + break; + case OP_MINUS: + if(val > 0) + e.buffs &= ~thebuff.m_itemid; + break; + } + bool have_buff = (e.buffs & thebuff.m_itemid); + return (had_buff != have_buff); +} + void GiveSound(entity e, float v0, float v1, float t, Sound snd_incr, Sound snd_decr) { if(v1 == v0) @@ -1748,6 +1835,8 @@ float GiveItems(entity e, float beginarg, float endarg) got += GiveValue(e, armorvalue, op, val); case "allweapons": FOREACH(Weapons, it != WEP_Null && !(it.spawnflags & WEP_FLAG_MUTATORBLOCKED), got += GiveWeapon(e, it.m_id, op, val)); + //case "allbuffs": // all buffs makes a player god, do not want! + //FOREACH(Buffs, it != BUFF_Null, got += GiveBuff(e, it.m_itemid, op, val)); case "allammo": got += GiveValue(e, ammo_cells, op, val); got += GiveValue(e, ammo_plasma, op, val); @@ -1806,6 +1895,11 @@ float GiveItems(entity e, float beginarg, float endarg) got += GiveValue(e, ammo_fuel, op, val); break; default: + FOREACH(Buffs, it != BUFF_Null && Buff_UndeprecateName(cmd) == it.m_name, + { + got += GiveBuff(e, it, op, val); + break; + }); FOREACH(Weapons, it != WEP_Null && W_UndeprecateName(cmd) == it.netname, { got += GiveWeapon(e, it.m_id, op, val); break; @@ -1828,6 +1922,7 @@ float GiveItems(entity e, float beginarg, float endarg) }); POSTGIVE_VALUE(e, strength_finished, 1, SND_POWERUP, SND_POWEROFF); POSTGIVE_VALUE(e, invincible_finished, 1, SND_Shield, SND_POWEROFF); + //POSTGIVE_VALUE(e, superweapons_finished, 1, SND_Null, SND_Null); POSTGIVE_VALUE(e, ammo_nails, 0, SND_ITEMPICKUP, SND_Null); POSTGIVE_VALUE(e, ammo_cells, 0, SND_ITEMPICKUP, SND_Null); POSTGIVE_VALUE(e, ammo_plasma, 0, SND_ITEMPICKUP, SND_Null);