#include "t_items.qh"
-#include "items/all.qc"
+#include "items/_mod.qh"
#if defined(SVQC)
- #include "../server/bot/bot.qh"
- #include "../server/bot/waypoints.qh"
+ #include "../server/bot/api.qh"
- #include <server/mutators/all.qh>
+ #include <server/mutators/_mod.qh>
#include "../server/weapons/common.qh"
#include "../server/weapons/selection.qh"
#include "triggers/subs.qh"
#include "util.qh"
- #include <common/monsters/all.qh>
+ #include <common/monsters/_mod.qh>
- #include <common/weapons/all.qh>
+ #include <common/weapons/_all.qh>
#include "../lib/warpzone/util_server.qh"
#elif defined(CSQC)
#include "physics/movetypes/movetypes.qh"
- #include <common/weapons/all.qh>
+ #include <common/weapons/_all.qh>
#include "../lib/csqcmodel/cl_model.qh"
#include "../lib/csqcmodel/common.qh"
#endif
#ifdef CSQC
bool autocvar_cl_ghost_items_vehicle = true;
+.vector item_glowmod;
void Item_SetAlpha(entity this)
{
bool veh_hud = (hud && autocvar_cl_ghost_items_vehicle);
if(!veh_hud && (this.ItemStatus & ITS_AVAILABLE))
{
this.alpha = 1;
- this.colormod = this.glowmod = '1 1 1';
+ this.colormod = '1 1 1';
+ this.glowmod = this.item_glowmod;
}
else
{
if(this.gravity)
{
Movetype_Physics_MatchServer(this, false);
- if(this.move_flags & FL_ONGROUND)
- { // For some reason move_avelocity gets set to '0 0 0' here ...
+ if(IS_ONGROUND(this))
+ { // For some reason avelocity gets set to '0 0 0' here ...
this.oldorigin = this.origin;
this.gravity = 0;
if(autocvar_cl_animate_items)
{ // ... so reset it if animations are requested.
if(this.ItemStatus & ITS_ANIMATE1)
- this.move_avelocity = '0 180 0';
+ this.avelocity = '0 180 0';
if(this.ItemStatus & ITS_ANIMATE2)
- this.move_avelocity = '0 -90 0';
+ 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)
{
if(this.ItemStatus & ITS_ANIMATE1)
{
- this.angles += this.move_avelocity * frametime;
- setorigin(this, '0 0 10' + this.oldorigin + '0 0 8' * sin(time * 2));
+ this.angles += this.avelocity * frametime;
+ 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.move_avelocity * frametime;
- setorigin(this, '0 0 8' + this.oldorigin + '0 0 4' * sin(time * 3));
+ this.angles += this.avelocity * frametime;
+ 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)));
}
}
{
Movetype_Physics_MatchServer(this, false);
- if(this.move_flags & FL_ONGROUND)
+ if(IS_ONGROUND(this))
this.gravity = 0;
}
this.angles_x = ReadAngle();
this.angles_y = ReadAngle();
this.angles_z = ReadAngle();
- this.move_angles = this.angles;
}
if(sf & ISF_SIZE)
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);
if(sf & ISF_MODEL)
{
this.drawmask = MASK_NORMAL;
- this.move_movetype = MOVETYPE_TOSS;
+ set_movetype(this, MOVETYPE_TOSS);
+ if (isnew) IL_PUSH(g_drawables, this);
this.draw = ItemDraw;
this.solid = SOLID_TRIGGER;
- //this.move_flags |= FL_ITEM;
+ //this.flags |= FL_ITEM;
bool use_bigsize = ReadByte();
else
{
this.draw = ItemDraw;
- LOG_TRACE("Simple item requested for ", _fn, " but no model exists for it\n");
+ LOG_TRACE("Simple item requested for ", _fn, " but no model exists for it");
}
}
if(this.mdl == "")
- LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, ", tell tZork about this!\n");
+ LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, ", tell tZork about this!");
precache_model(this.mdl);
_setmodel(this, this.mdl);
}
if(sf & ISF_COLORMAP)
+ {
this.colormap = ReadShort();
+ this.item_glowmod_x = ReadByte() / 255.0;
+ this.item_glowmod_y = ReadByte() / 255.0;
+ this.item_glowmod_z = ReadByte() / 255.0;
+ }
if(sf & ISF_DROP)
{
this.gravity = 1;
this.pushable = true;
- //this.move_angles = '0 0 0';
- this.move_movetype = MOVETYPE_TOSS;
- this.move_velocity_x = ReadCoord();
- this.move_velocity_y = ReadCoord();
- this.move_velocity_z = ReadCoord();
- this.velocity = this.move_velocity;
- this.move_origin = this.oldorigin;
+ //this.angles = '0 0 0';
+ set_movetype(this, MOVETYPE_TOSS);
+ this.velocity_x = ReadCoord();
+ this.velocity_y = ReadCoord();
+ this.velocity_z = ReadCoord();
+ setorigin(this, this.oldorigin);
if(!this.move_time)
{
if(autocvar_cl_animate_items)
{
if(this.ItemStatus & ITS_ANIMATE1)
- this.move_avelocity = '0 180 0';
+ this.avelocity = '0 180 0';
if(this.ItemStatus & ITS_ANIMATE2)
- this.move_avelocity = '0 -90 0';
+ this.avelocity = '0 -90 0';
}
this.entremove = ItemRemove;
WriteShort(MSG_ENTITY, this.fade_start);
if(this.mdl == "")
- LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, "exspect a crash just aboute now\n");
+ LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, "expect a crash just about now");
WriteString(MSG_ENTITY, this.mdl);
}
if(sf & ISF_COLORMAP)
+ {
WriteShort(MSG_ENTITY, this.colormap);
+ WriteByte(MSG_ENTITY, this.glowmod.x * 255.0);
+ WriteByte(MSG_ENTITY, this.glowmod.y * 255.0);
+ WriteByte(MSG_ENTITY, this.glowmod.z * 255.0);
+ }
if(sf & ISF_DROP)
{
{
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
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
;
//setmodel(e, "null");
e.solid = SOLID_NOT;
e.colormod = '0 0 0';
- e.glowmod = e.colormod;
+ //e.glowmod = e.colormod;
e.spawnshieldtime = 1;
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;
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)
return 1;
}
-void Item_Touch(entity this)
+void Item_Touch(entity this, entity toucher)
{
// remove the item if it's currnetly in a NODROP brush or hits a NOIMPACT surface (such as sky)
{
if (ITEM_TOUCH_NEEDKILL())
{
- remove(this);
+ delete(this);
return;
}
}
- if(!(other.flags & FL_PICKUPITEMS)
- || STAT(FROZEN, other)
- || IS_DEAD(other)
+ if(!(toucher.flags & FL_PICKUPITEMS)
+ || STAT(FROZEN, toucher)
+ || IS_DEAD(toucher)
|| (this.solid != SOLID_TRIGGER)
- || (this.owner == other)
+ || (this.owner == toucher)
|| (time < this.item_spawnshieldtime)
) { return; }
- switch (MUTATOR_CALLHOOK(ItemTouch, this, other))
+ switch (MUTATOR_CALLHOOK(ItemTouch, this, toucher))
{
case MUT_ITEMTOUCH_RETURN: { return; }
- case MUT_ITEMTOUCH_PICKUP: { other = M_ARGV(1, entity); goto pickup; }
+ case MUT_ITEMTOUCH_PICKUP: { toucher = M_ARGV(1, entity); goto pickup; }
}
- other = M_ARGV(1, entity);
+ toucher = M_ARGV(1, entity);
if (this.classname == "droppedweapon")
{
this.superweapons_finished = max(0, this.superweapons_finished - time);
}
entity it = this.itemdef;
- bool gave = ITEM_HANDLE(Pickup, it, this, other);
+ bool gave = ITEM_HANDLE(Pickup, it, this, toucher);
if (!gave)
{
if (this.classname == "droppedweapon")
LABEL(pickup)
- other.last_pickup = time;
+ toucher.last_pickup = time;
Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
- _sound (other, (this.itemdef.instanceOfPowerup ? CH_TRIGGER_SINGLE : CH_TRIGGER), (this.item_pickupsound ? this.item_pickupsound : Sound_fixpath(this.item_pickupsound_ent)), VOL_BASE, ATTEN_NORM);
+ _sound (toucher, (this.itemdef.instanceOfPowerup ? CH_TRIGGER_SINGLE : CH_TRIGGER), (this.item_pickupsound ? this.item_pickupsound : Sound_fixpath(this.item_pickupsound_ent)), VOL_BASE, ATTEN_NORM);
if (this.classname == "droppedweapon")
- remove (this);
+ delete (this);
else if (this.spawnshieldtime)
{
entity e;
if(this.team)
{
RandomSelection_Init();
- for(entity head = NULL; (head = findfloat(head, team, this.team)); )
+ IL_EACH(g_items, it.team == this.team,
{
- if(head.flags & FL_ITEM)
- if(head.classname != "item_flag_team" && head.classname != "item_key_team")
+ if(it.itemdef) // is a registered item
{
- Item_Show(head, -1);
- RandomSelection_Add(head, 0, string_null, head.cnt, 0);
+ Item_Show(it, -1);
+ RandomSelection_AddEnt(it, it.cnt, 0);
}
- }
+ });
e = RandomSelection_chosen_ent;
}
if(this.effects & EF_NODRAW)
{
// marker for item team search
- LOG_TRACE("Initializing item team ", ftos(this.team), "\n");
+ LOG_TRACE("Initializing item team ", ftos(this.team));
RandomSelection_Init();
- FOREACH_ENTITY_FLOAT(team, this.team,
+ IL_EACH(g_items, it.team == this.team,
{
- if(it.flags & FL_ITEM)
- if(it.classname != "item_flag_team" && it.classname != "item_key_team")
- RandomSelection_Add(it, 0, string_null, it.cnt, 0);
+ if(it.itemdef) // is a registered item
+ RandomSelection_AddEnt(it, it.cnt, 0);
});
e = RandomSelection_chosen_ent;
e.state = 0;
Item_Show(e, 1);
- FOREACH_ENTITY_FLOAT(team, this.team,
+ IL_EACH(g_items, it.team == this.team,
{
- if(it.flags & FL_ITEM)
- if(it.classname != "item_flag_team" && it.classname != "item_key_team")
+ if(it.itemdef) // is a registered item
{
if(it != e)
{
{
if(wasfreed(this) || !this) { return; }
Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
- remove(this);
+ delete(this);
}
// pickup evaluation functions
float c;
// See if I have it already
- if(item.weapons & ~player.weapons)
+ if(!(item.weapons & ~player.weapons))
{
// If I can pick it up
if(!item.spawnshieldtime)
{
// Find the highest position on any range
int position = -1;
+ int wep_count = 0;
+ int wpn = item.weapon;
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;
- }
+ if (position == -1)
+ if (bot_weapons_far[j] == wpn || bot_weapons_mid[j] == wpn || bot_weapons_close[j] == wpn)
+ position = wep_count;
+ if (bot_weapons_far[j] > 0 || bot_weapons_mid[j] > 0 || bot_weapons_close[j] > 0)
+ wep_count++;
}
// Rate it
if (position >= 0 )
{
- position = WEP_LAST - position;
+ position = wep_count - position;
// item.bot_pickupbasevalue is overwritten here
- return (BOT_PICKUP_RATING_LOW + ( (BOT_PICKUP_RATING_HIGH - BOT_PICKUP_RATING_LOW) * (position / WEP_LAST ))) * c;
+ return (BOT_PICKUP_RATING_LOW + ( (BOT_PICKUP_RATING_HIGH - BOT_PICKUP_RATING_LOW) * (position / wep_count) )) * c;
}
}
this.weapons = WepSet_FromWeapon(Weapons_from(weaponid));
this.flags = FL_ITEM | itemflags;
+ IL_PUSH(g_items, this);
if(MUTATOR_CALLHOOK(FilterItem, this)) // error means we do not want the item
{
startitem_failed = true;
- remove(this);
+ delete(this);
return;
}
{
this.reset = SUB_Remove;
// it's a dropped weapon
- this.movetype = MOVETYPE_TOSS;
+ set_movetype(this, MOVETYPE_TOSS);
// Savage: remove thrown items after a certain period of time ("garbage collection")
setthink(this, RemoveItem);
if (trace_dpstartcontents & DPCONTENTS_NODROP)
{
startitem_failed = true;
- remove(this);
+ delete(this);
return;
}
}
if(!have_pickup_item(this))
{
startitem_failed = true;
- remove (this);
+ delete (this);
return;
}
if(this.spawnflags & 1)
this.noalign = 1;
if (this.noalign > 0)
- this.movetype = MOVETYPE_NONE;
+ set_movetype(this, MOVETYPE_NONE);
else
- this.movetype = MOVETYPE_TOSS;
+ set_movetype(this, MOVETYPE_TOSS);
// do item filtering according to game mode and other things
if (this.noalign <= 0)
{
// why not flags & fl_item?
FOREACH_ENTITY_RADIUS(this.origin, 3, it.is_item, {
LOG_TRACE("XXX Found duplicated item: ", itemname, vtos(this.origin));
- LOG_TRACE(" vs ", it.netname, vtos(it.origin), "\n");
+ LOG_TRACE(" vs ", it.netname, vtos(it.origin));
error("Mapper sucks.");
});
this.is_item = true;
this.gravity = 1;
if (!(this.spawnflags & 1024))
this.ItemStatus |= ITS_ANIMATE1;
- this.ItemStatus |= ISF_COLORMAP;
+ this.SendFlags |= ISF_COLORMAP;
}
this.state = 0;
if (MUTATOR_CALLHOOK(Item_Spawn, this))
{
startitem_failed = true;
- remove(this);
+ delete(this);
return;
}
}
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;
+ this.max_armorvalue = g_pickup_armormega_max;
if(!this.pickup_anyway)
- this.pickup_anyway = g_pickup_armorlarge_anyway;
+ this.pickup_anyway = g_pickup_armormega_anyway;
StartItem(this, ITEM_ArmorMega);
}
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;
+ this.health = g_pickup_healthbig;
if(!this.pickup_anyway)
- this.pickup_anyway = g_pickup_healthlarge_anyway;
- StartItem(this, ITEM_HealthLarge);
+ this.pickup_anyway = g_pickup_healthbig_anyway;
+ StartItem(this, ITEM_HealthBig);
}
spawnfunc(item_health_mega)
// 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)
void target_items_use(entity this, entity actor, entity trigger)
{
- other = trigger; // TODO
-
if(actor.classname == "droppedweapon")
{
- EXACTTRIGGER_TOUCH;
- remove(actor);
+ EXACTTRIGGER_TOUCH(this, trigger);
+ delete(actor);
return;
}
return;
if(trigger.solid == SOLID_TRIGGER)
{
- EXACTTRIGGER_TOUCH;
+ EXACTTRIGGER_TOUCH(this, trigger);
}
- FOREACH_ENTITY_ENT(enemy, actor,
+ IL_EACH(g_items, it.enemy == actor && it.classname == "droppedweapon",
{
- if(it.classname == "droppedweapon")
- remove(it);
+ delete(it);
});
if(GiveItems(actor, 0, tokenize_console(this.netname)))
spawnfunc(target_items)
{
- float n, i;
+ int n, j;
string s;
this.use = target_items_use;
}
else
{
- for(i = 0; i < n; ++i)
+ for(j = 0; j < n; ++j)
{
- if (argv(i) == "unlimited_ammo") this.items |= IT_UNLIMITED_AMMO;
- else if(argv(i) == "unlimited_weapon_ammo") this.items |= IT_UNLIMITED_WEAPON_AMMO;
- else if(argv(i) == "unlimited_superweapons") this.items |= IT_UNLIMITED_SUPERWEAPONS;
- else if(argv(i) == "strength") this.items |= ITEM_Strength.m_itemid;
- else if(argv(i) == "invincible") this.items |= ITEM_Shield.m_itemid;
- else if(argv(i) == "superweapons") this.items |= IT_SUPERWEAPON;
- else if(argv(i) == "jetpack") this.items |= ITEM_Jetpack.m_itemid;
- else if(argv(i) == "fuel_regen") this.items |= ITEM_JetpackRegen.m_itemid;
+ if (argv(j) == "unlimited_ammo") this.items |= IT_UNLIMITED_AMMO;
+ else if(argv(j) == "unlimited_weapon_ammo") this.items |= IT_UNLIMITED_WEAPON_AMMO;
+ else if(argv(j) == "unlimited_superweapons") this.items |= IT_UNLIMITED_SUPERWEAPONS;
+ else if(argv(j) == "strength") this.items |= ITEM_Strength.m_itemid;
+ else if(argv(j) == "invincible") this.items |= ITEM_Shield.m_itemid;
+ else if(argv(j) == "superweapons") this.items |= IT_SUPERWEAPON;
+ else if(argv(j) == "jetpack") this.items |= ITEM_Jetpack.m_itemid;
+ else if(argv(j) == "fuel_regen") this.items |= ITEM_JetpackRegen.m_itemid;
else
{
FOREACH(Weapons, it != WEP_Null, {
- s = W_UndeprecateName(argv(i));
+ s = W_UndeprecateName(argv(j));
if(s == it.netname)
{
this.weapons |= (it.m_wepset);
//print(this.netname, "\n");
n = tokenize_console(this.netname);
- for(i = 0; i < n; ++i)
+ for(j = 0; j < n; ++j)
{
- FOREACH(Weapons, it != WEP_Null && argv(i) == it.netname, {
+ FOREACH(Weapons, it != WEP_Null && W_UndeprecateName(argv(j)) == it.netname, {
it.wr_init(it);
break;
});
got += GiveValue(e, ammo_fuel, op, val);
break;
default:
- FOREACH(Weapons, it != WEP_Null && cmd == it.netname, {
+ FOREACH(Weapons, it != WEP_Null && W_UndeprecateName(cmd) == it.netname, {
got += GiveWeapon(e, it.m_id, op, val);
break;
});
});
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);