Item_ScheduleRespawnIn(e, max(0, game_starttime - time) + ((e.respawntimestart) ? e.respawntimestart : ITEM_RESPAWNTIME_INITIAL(e)));
}
+void GiveRandomWeapons(entity receiver, int num_weapons, string weapon_names,
+ entity ammo_entity)
+{
+ if (num_weapons == 0)
+ {
+ return;
+ }
+ int num_potential_weapons = tokenize_console(weapon_names);
+ for (int give_attempt = 0; give_attempt < num_weapons; ++give_attempt)
+ {
+ RandomSelection_Init();
+ for (int weapon_index = 0; weapon_index < num_potential_weapons;
+ ++weapon_index)
+ {
+ string weapon = argv(weapon_index);
+ FOREACH(Weapons, it != WEP_Null,
+ {
+ // Finding a weapon which player doesn't have.
+ if (!(receiver.weapons & it.m_wepset) && (it.netname == weapon))
+ {
+ RandomSelection_AddEnt(it, 1, 1);
+ break;
+ }
+ });
+ }
+ if (RandomSelection_chosen_ent == NULL)
+ {
+ return;
+ }
+ receiver.weapons |= RandomSelection_chosen_ent.m_wepset;
+ if (RandomSelection_chosen_ent.ammo_type == RESOURCE_NONE)
+ {
+ continue;
+ }
+ if (GetResourceAmount(receiver,
+ RandomSelection_chosen_ent.ammo_type) != 0)
+ {
+ continue;
+ }
+ GiveResource(receiver, RandomSelection_chosen_ent.ammo_type,
+ GetResourceAmount(ammo_entity,
+ RandomSelection_chosen_ent.ammo_type));
+ }
+}
+
float Item_GiveAmmoTo(entity item, entity player, int resource_type, float ammomax)
{
float amount = GetResourceAmount(item, resource_type);
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 (this.classname == "droppedweapon")
+ if (Item_IsLoot(this))
{
if (ITEM_TOUCH_NEEDKILL())
{
toucher = M_ARGV(1, entity);
+ // TODO: Proper way to handle expiring and not expiring loot.
+ // Expiring loot will have strength "ticking" will it's dropped.
+ // Not expiring will not tick.
+ // OTOH, do we really need expiring loot?
if (this.classname == "droppedweapon")
{
this.strength_finished = max(0, this.strength_finished - time);
this.invincible_finished = max(0, this.invincible_finished - time);
this.superweapons_finished = max(0, this.superweapons_finished - time);
}
- entity it = this.itemdef;
- bool gave = ITEM_HANDLE(Pickup, it, this, toucher);
+ bool gave = ITEM_HANDLE(Pickup, this.itemdef, this, toucher);
if (!gave)
{
- if (this.classname == "droppedweapon")
+ if (Item_IsLoot(this))
{
// undo what we did above
this.strength_finished += time;
Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
_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);
+
+ MUTATOR_CALLHOOK(ItemTouched, this, toucher);
+ if (wasfreed(this))
+ {
+ return;
+ }
- if (this.classname == "droppedweapon")
+ if (Item_IsLoot(this))
+ {
delete(this);
- else if (this.spawnshieldtime)
+ return;
+ }
+ if (!this.spawnshieldtime)
+ {
+ return;
+ }
+ entity e;
+ if (this.team)
{
- entity e;
- if(this.team)
+ RandomSelection_Init();
+ IL_EACH(g_items, it.team == this.team,
{
- RandomSelection_Init();
- IL_EACH(g_items, it.team == this.team,
+ if (it.itemdef) // is a registered item
{
- if(it.itemdef) // is a registered item
- {
- Item_Show(it, -1);
- RandomSelection_AddEnt(it, it.cnt, 0);
- }
- });
- e = RandomSelection_chosen_ent;
- Item_Show(e, 1); // reset its state so it is visible (extra sendflags doesn't matter, this happens anyway)
- }
- else
- e = this;
- Item_ScheduleRespawn(e);
+ Item_Show(it, -1);
+ it.scheduledrespawntime = 0;
+ RandomSelection_AddEnt(it, it.cnt, 0);
+ }
+ });
+ e = RandomSelection_chosen_ent;
+ Item_Show(e, 1); // reset its state so it is visible (extra sendflags doesn't matter, this happens anyway)
}
+ else
+ e = this;
+ Item_ScheduleRespawn(e);
}
void Item_Reset(entity this)
Item_Show(this, !this.state);
setorigin(this, this.origin);
- if (this.classname != "droppedweapon")
+ if (Item_IsLoot(this))
{
- setthink(this, Item_Think);
- this.nextthink = time;
-
- if (this.waypointsprite_attached)
- WaypointSprite_Kill(this.waypointsprite_attached);
-
- if (this.itemdef.instanceOfPowerup || (this.weapons & WEPSET_SUPERWEAPONS)) // do not spawn powerups initially!
- Item_ScheduleInitialRespawn(this);
+ return;
+ }
+ setthink(this, Item_Think);
+ this.nextthink = time;
+ if (this.waypointsprite_attached)
+ {
+ WaypointSprite_Kill(this.waypointsprite_attached);
+ }
+ if (this.itemdef.instanceOfPowerup || (this.weapons & WEPSET_SUPERWEAPONS)) // do not spawn powerups initially!
+ {
+ Item_ScheduleInitialRespawn(this);
}
}
return;
}
- // is it a dropped weapon?
- if (this.classname == "droppedweapon")
+ if (Item_IsLoot(this))
{
this.reset = SUB_Remove;
- // it's a dropped weapon
set_movetype(this, MOVETYPE_TOSS);
// Savage: remove thrown items after a certain period of time ("garbage collection")
this.takedamage = DAMAGE_YES;
this.event_damage = Item_Damage;
- if(this.strength_finished || this.invincible_finished || this.superweapons_finished)
+ // TODO: Proper way to handle expiring and not expiring loot.
+ // Expiring loot will have strength "ticking" will it's dropped.
+ // Not expiring will not tick.
+ // OTOH, do we really need expiring loot?
+ if (this.strength_finished || this.invincible_finished || this.superweapons_finished)
{
// if item is worthless after a timer, have it expire then
this.nextthink = max(this.strength_finished, this.invincible_finished, this.superweapons_finished);
}
}
-spawnfunc(item_rockets)
-{
- StartItem(this, ITEM_Rockets);
-}
-
-spawnfunc(item_bullets)
-{
- if(!weaponswapping && autocvar_sv_q3acompat_machineshotgunswap &&
- (this.classname != "droppedweapon"))
- {
- weaponswapping = true;
- spawnfunc_item_shells(this);
- weaponswapping = false;
- return;
- }
-
- StartItem(this, ITEM_Bullets);
-}
-
-spawnfunc(item_cells)
-{
- StartItem(this, ITEM_Cells);
-}
-
-spawnfunc(item_plasma)
-{
- StartItem(this, ITEM_Plasma);
-}
-
-spawnfunc(item_shells)
-{
- if(!weaponswapping && autocvar_sv_q3acompat_machineshotgunswap &&
- (this.classname != "droppedweapon"))
- {
- weaponswapping = true;
- spawnfunc_item_bullets(this);
- weaponswapping = false;
- return;
- }
-
- StartItem(this, ITEM_Shells);
-}
-
-spawnfunc(item_armor_small)
-{
- StartItem(this, ITEM_ArmorSmall);
-}
-
-spawnfunc(item_armor_medium)
-{
- StartItem(this, ITEM_ArmorMedium);
-}
-
-spawnfunc(item_armor_big)
-{
- StartItem(this, ITEM_ArmorBig);
-}
-
-spawnfunc(item_armor_mega)
-{
- StartItem(this, ITEM_ArmorMega);
-}
-
-spawnfunc(item_health_small)
-{
- StartItem(this, ITEM_HealthSmall);
-}
-
-spawnfunc(item_health_medium)
-{
- StartItem(this, ITEM_HealthMedium);
-}
-
-spawnfunc(item_health_big)
-{
- StartItem(this, ITEM_HealthBig);
-}
-
-spawnfunc(item_health_mega)
-{
- 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_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)
-{
- StartItem(this, ITEM_Strength);
-}
-
-spawnfunc(item_invincible)
-{
- StartItem(this, ITEM_Shield);
-}
-
-// compatibility:
-spawnfunc(item_quad) { this.classname = "item_strength";spawnfunc_item_strength(this);}
void target_items_use(entity this, entity actor, entity trigger)
{
}
}
-spawnfunc(item_fuel)
-{
- StartItem(this, ITEM_JetpackFuel);
-}
-
-spawnfunc(item_fuel_regen)
-{
- if(start_items & ITEM_JetpackRegen.m_itemid)
- {
- spawnfunc_item_fuel(this);
- return;
- }
- StartItem(this, ITEM_JetpackRegen);
-}
-
-spawnfunc(item_jetpack)
-{
- if(start_items & ITEM_Jetpack.m_itemid)
- {
- spawnfunc_item_fuel(this);
- return;
- }
- StartItem(this, ITEM_Jetpack);
-}
-
float GiveWeapon(entity e, float wpn, float op, float val)
{
WepSet v0, v1;