78 LOG_TRACE(
"^1WARNING!^7 this.mdl is unset for item ", this.
classname,
"expect a crash just about now");
117 if(!this.
itemdef.instanceOfPowerup)
124 if(
STAT(WEAPONS,
this) || this.
itemdef.instanceOfAmmo)
140 e.spawnshieldtime = 1;
148 e.spawnshieldtime = 1;
153 bool nostay = def.instanceOfWeaponPickup ? !!(def.m_weapon.m_wepset &
WEPSET_SUPERWEAPONS) :
false
162 e.spawnshieldtime = 0;
168 e.spawnshieldtime = 1;
188 setorigin(e, e.origin);
212 if (this.
itemdef.instanceOfPowerup)
274 if (wi != WEP_Null) {
275 entity wp =
WaypointSprite_Spawn(WP_Weapon, 0, 0,
this,
'0 0 64',
NULL, 0,
this,
waypointsprite_attached,
true, RADARICON_Weapon);
276 wp.wp_extra = wi.m_id;
283 entity wp =
WaypointSprite_Spawn(WP_Item, 0, 0,
this,
'0 0 64',
NULL, 0,
this,
waypointsprite_attached,
true, RADARICON_Item);
284 wp.wp_extra = ii.m_id;
334 e.item_respawncounter = 0;
340 e.scheduledrespawntime =
time + t;
352AUTOCVAR(g_pickup_respawntime_scaling_reciprocal,
float, 0.0,
"multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `reciprocal` (with `offset` and `linear` set to \\\"0\\\") can be used to achieve a constant number of items spawned *per player*");
353AUTOCVAR(g_pickup_respawntime_scaling_offset,
float, 0.0,
"multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `offset` offsets the curve left or right (NOTE: results are not intuitive and it is recommend to plot the respawn time and the number of items per player to see what's happening)");
354AUTOCVAR(g_pickup_respawntime_scaling_linear,
float, 1.0,
"multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `linear` can be used to simply scale the respawn time linearly");
358 float r = autocvar_g_pickup_respawntime_scaling_reciprocal;
359 float o = autocvar_g_pickup_respawntime_scaling_offset;
360 float l = autocvar_g_pickup_respawntime_scaling_linear;
362 if (r == 0 && l == 1) {
363 return normal_respawntime;
379 return normal_respawntime * (r / (
players + o) + l);
381 return normal_respawntime;
387 if(e.respawntime > 0)
395 float respawn_in = adjusted_respawntime +
crandom() * e.respawntimejitter;
402AUTOCVAR(g_pickup_respawntime_initial_random,
int, 1,
403 "for items that don't start spawned; \\\"0\\\" = spawn after their normal respawntime, \\\"1\\\" = spawn after `random * respawntime` with the *same* random, \\\"2\\\" = same as 1 but each item has separate random");
410 if (autocvar_g_pickup_respawntime_initial_random == 0)
413 spawn_in = e.respawntime +
random() * e.respawntimejitter;
418 if (autocvar_g_pickup_respawntime_initial_random == 1)
420 static float shared_random = 0;
423 if (!shared_random ||
floor(
time) > shared_random)
443 if (num_weapons == 0)
448 for (
int give_attempt = 0; give_attempt < num_weapons; ++give_attempt)
451 for (
int weapon_index = 0; weapon_index < num_potential_weapons;
458 if (!(
STAT(WEAPONS, receiver) & it.m_wepset) && (it.netname ==
weapon))
492 float player_amount =
GetResource(player, res_type);
493 if (item.spawnshieldtime)
495 if ((player_amount >= ammomax) && (item.pickup_anyway <= 0))
500 ammomax =
min(amount, ammomax);
501 if(player_amount >= ammomax)
517 WriteHeader(MSG_ONE, TE_CSQC_WEAPONPICKUP);
518 WriteRegistered(Weapons, MSG_ONE, wep);
525 int _switchweapon = 0;
530 bool use_cts_autoswitch = (
g_cts && item.itemdef.instanceOfWeaponPickup && (
CS_CVAR(player).cvar_cl_autoswitch_cts != -1));
531 if (
CS_CVAR(player).cvar_cl_autoswitch && !use_cts_autoswitch)
536 if (player.(weaponentity).m_weapon != WEP_Null || slot == 0)
538 if (player.(weaponentity).m_switchweapon ==
w_getbestweapon(player, weaponentity))
539 _switchweapon |=
BIT(slot);
542 _switchweapon |=
BIT(slot);
546 bool pickedup =
false;
547 pickedup |=
Item_GiveAmmoTo(item, player, RES_HEALTH, item.max_health);
554 if (item.itemdef.instanceOfWeaponPickup)
557 w =
STAT(WEAPONS, item);
558 wp = w &
~STAT(WEAPONS, player);
560 if (wp || (item.spawnshieldtime && item.pickup_anyway > 0))
564 if(w & (it.m_wepset))
567 if(wp & (it.m_wepset))
572 if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
573 W_DropEvent(wr_pickup, player, it.m_id, item, weaponentity);
581 if (item.itemdef.instanceOfPowerup)
583 if ((item.itemdef == ITEM_FuelRegen) && !(player.items &
IT_FUEL_REGEN))
585 else if ((item.itemdef == ITEM_Jetpack) && !(player.items &
IT_JETPACK))
598 if (item.strength_finished)
603 t += item.strength_finished;
605 t =
max(t,
time + item.strength_finished);
608 if (item.invincible_finished)
613 t += item.invincible_finished;
615 t =
max(t,
time + item.invincible_finished);
618 if (item.speed_finished)
623 t += item.speed_finished;
625 t =
max(t,
time + item.speed_finished);
628 if (item.invisibility_finished)
633 t += item.invisibility_finished;
635 t =
max(t,
time + item.invisibility_finished);
638 if (item.superweapons_finished)
652 if(use_cts_autoswitch)
655 if(
CS_CVAR(player).cvar_cl_autoswitch_cts == 1)
662 if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
668 else if(_switchweapon)
674 if(_switchweapon &
BIT(slot))
677 if(player.(weaponentity).m_switchweapon != best_wep)
771 it.scheduledrespawntime = 0;
772 RandomSelection_AddEnt(it, it.cnt, 0);
823 RandomSelection_AddEnt(it, it.cnt, 0);
837 if (it.waypointsprite_attached)
838 WaypointSprite_Kill(it.waypointsprite_attached);
846 it.effects &= ~EF_NOGUNBOB;
853 setorigin(to, this.
origin);
858 to.spawnfunc_checked =
true;
867 if(wasfreed(
this) || !
this) {
return; }
890 if(
STAT(WEAPONS, player) &
STAT(WEAPONS, item))
893 if(!item.spawnshieldtime)
900 int weapons_value = 0;
902 weapons_value += it.bot_pickupbasevalue;
904 c -=
bound(0, weapons_value / 20000, 1) * 0.5;
906 return item.bot_pickupbasevalue * c;
917 if(item.itemdef.instanceOfWeaponPickup)
919 entity res = item.itemdef.m_weapon.ammo_type;
927 rating =
ammo.m_botvalue;
932 if(!(
STAT(WEAPONS, player) & (it.m_wepset)))
934 if(it.ammo_type == RES_NONE)
939 item_resource = it.ammo_type;
943 rating = item.bot_pickupbasevalue;
946 float noammorating = 0.5;
953 rating += wpn.bot_pickupbasevalue * 0.1;
960 float rating = item.bot_pickupbasevalue;
967 itemarmor *=
min(4, item.item_group_count);
968 itemhealth *=
min(4, item.item_group_count);
974 if (itemhealth && (
GetResource(player, RES_HEALTH) < item.max_health))
997 int old_status = this.
active;
1003 if(this.
active != old_status)
1009 if (def.m_spawnfunc_hookreplace)
1010 def = def.m_spawnfunc_hookreplace(def,
this);
1012 if (def.m_canonical_spawnfunc !=
"")
1013 this.
classname = def.m_canonical_spawnfunc;
1019 def.m_iteminit(def,
this);
1022 this.
items = def.m_itemid;
1023 this.
weapon = def.instanceOfWeaponPickup ? def.m_weapon.m_id : 0;
1060 setsize (
this, this.
pos1 = def.m_mins,
this.pos2 = def.m_maxs);
1089 nudgeoutofsolid_OrFallback(
this);
1111 if (def.m_respawntime)
1114 LOG_WARNF(
"Default respawntime for a %s is unavailable from its itemdef", this.
classname);
1119 if(this.
angles !=
'0 0 0')
1128 if(t) this.
team = crc16(
false, t);
1134 setorigin(
this, this.
origin);
1165 error(
"Mapper sucks.");
1172 if ( def.instanceOfPowerup
1173 || def.instanceOfWeaponPickup
1174 || (def.instanceOfHealth && def != ITEM_HealthSmall)
1175 || (def.instanceOfArmor && def != ITEM_ArmorSmall)
1180 this.
target =
"###item###";
1189 this.bot_pickupevalfunc = def.m_pickupevalfunc;
1197 this.
skin = def.m_skin;
1200 if(def.instanceOfPowerup)
1207 if(def.instanceOfWeaponPickup)
1229 Net_LinkEntity(
this, !(def.instanceOfPowerup || def.instanceOfHealth || def.instanceOfArmor), 0,
ItemSend);
1248#define IS_SMALL(def) ((def.instanceOfHealth && def == ITEM_HealthSmall) || (def.instanceOfArmor && def == ITEM_ArmorSmall))
1265 if (!head.item_group)
1274 if (!head.item_group)
1276 else if (head.item_group !=
this.item_group)
1278 int grY = head.item_group;
1301 v0 = (
STAT(WEAPONS, e) & s);
1306 STAT(WEAPONS, e) |= s;
1308 STAT(WEAPONS, e) &= ~s;
1313 STAT(WEAPONS, e) |= s;
1317 STAT(WEAPONS, e) &= ~s;
1321 STAT(WEAPONS, e) &= ~s;
1324 v1 = (
STAT(WEAPONS, e) & s);
1335 new_buff_time =
time + val;
1338 new_buff_time =
max(new_buff_time,
time + val);
1341 new_buff_time =
min(new_buff_time,
time + val);
1344 new_buff_time += val;
1347 new_buff_time -= val;
1350 if(new_buff_time <=
time)
1361 return (had_buff != have_buff);
1370 if(snd_decr !=
NULL)
1373 else if(v0 >= v0 + t)
1375 if(snd_incr !=
NULL)
1380void GiveRot(
entity e,
float v0,
float v1, .
float rotfield,
float rottime, .
float regenfield,
float regentime)
1383 e.(rotfield) =
max(e.(rotfield),
time + rottime);
1385 e.(regenfield) =
max(e.(regenfield),
time + regentime);
1394 case OP_SET: new_val = val;
break;
1395 case OP_MIN: new_val =
max(v0, val);
break;
1396 case OP_MAX: new_val =
min(v0, val);
break;
1397 case OP_PLUS: new_val = v0 + val;
break;
1398 case OP_MINUS: new_val = v0 - val;
break;
1399 default:
return false;
1411 new_eff_time =
time + val;
1414 new_eff_time =
max(new_eff_time,
time + val);
1417 new_eff_time =
min(new_eff_time,
time + val);
1420 new_eff_time += val;
1423 new_eff_time -= val;
1426 if(new_eff_time <=
time)
1434 return (had_eff != have_eff);
1439 float got, i, val, op;
1447 int _switchweapon = 0;
1449 bool use_cts_autoswitch = (
g_cts && (
CS_CVAR(e).cvar_cl_autoswitch_cts != -1));
1450 if(
CS_CVAR(e).cvar_cl_autoswitch && !use_cts_autoswitch)
1455 if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
1456 if(e.(weaponentity).m_switchweapon ==
w_getbestweapon(e, weaponentity))
1457 _switchweapon |=
BIT(slot);
1476 Weapon last_wep = WEP_Null;
1477 for(i = beginarg; i < endarg; ++i)
1505 got +=
GiveBit(e,
items, ITEM_FuelRegen.m_itemid, op, val);
1509 got +=
GiveBit(e,
items, ITEM_Jetpack.m_itemid, op, val);
1524 case "unlimited_ammo":
1528 case "unlimited_weapon_ammo":
1531 case "unlimited_superweapons":
1535 got +=
GiveBit(e,
items, ITEM_Jetpack.m_itemid, op, val);
1538 got +=
GiveBit(e,
items, ITEM_FuelRegen.m_itemid, op, val);
1550 case "invisibility":
1553 case "superweapons":
1581 got += GiveBuff(e, it, op, val);
1585 got += GiveWeapon(e, it.m_id, op, val);
1586 if(use_cts_autoswitch && CS_CVAR(e).cvar_cl_autoswitch_cts == 1)
1587 if(val > 0 && (op == OP_SET || op == OP_PLUS || op == OP_MIN))
1603 if(!(save_weapons & (it.m_wepset)))
1604 if(
STAT(WEAPONS, e) & (it.m_wepset))
1629 if(use_cts_autoswitch)
1632 if(last_wep != WEP_Null)
1633 if(
CS_CVAR(e).cvar_cl_autoswitch_cts == 1)
1639 if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
1651 if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
1653 _switchweapon |=
BIT(slot);
1655 if(_switchweapon &
BIT(slot))
1658 if(e.(weaponentity).m_switchweapon != best_wep)
void waypoint_spawnforitem(entity e)
#define MUTATOR_CALLHOOK(id,...)
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
ERASEABLE bool GiveBit(entity e,.int fld, int bit, int op, int val)
float bot_pickupbasevalue
string Buff_CompatName(string buffname)
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
void TakeResourceWithLimit(entity receiver, Resource res_type, float amount, float limit)
Takes an entity some resource but not less than a limit.
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
int autocvar_g_pickup_rockets_max
int autocvar_g_pickup_fuel_max
int autocvar_g_pickup_shells_max
int autocvar_g_pickup_cells_max
int autocvar_g_pickup_nails_max
const float IT_UPDATE_INTERVAL
const int IT_UNLIMITED_AMMO
const int IT_UNLIMITED_SUPERWEAPONS
float invincible_finished
@ ITEM_FLAG_MUTATORBLOCKED
#define ITEM_HANDLE(signal,...)
const float IT_DESPAWNFX_TIME
#define setmodel(this, m)
vector weaponsInMap
all the weapons actually spawned in the map, does not include filtered items
const int INITPRIO_FINDTARGET
const float SOLID_TRIGGER
float trace_dpstartcontents
const float EF_FULLBRIGHT
const float EF_NODEPTHTEST
void W_SwitchWeapon_Force(Player this, Weapon w,.entity weaponentity)
WriteString(chan, ent.netname)
WriteByte(chan, ent.angles.y/DEC_FACTOR)
SetResourceExplicit(ent, RES_ARMOR, ReadByte() *DEC_FACTOR)) ENTCS_PROP(NAME
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define IL_EACH(this, cond, body)
float invisibility_finished
#define ITEM_IS_LOOT(item)
Returns whether the item is loot.
#define ITEM_IS_EXPIRING(item)
Returns whether the item is expiring (i.e.
#define ITEM_SHOULD_KEEP_POSITION(item)
Returns whether item should keep its position or be dropped to the ground.
#define FOREACH(list, cond, body)
void SUB_UseTargets(entity this, entity actor, entity trigger)
#define WriteHeader(to, id)
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
entity WarpZone_SearchInRadius(vector org, float rad, float nomonsters, WarpZone_FindRadius_cond_callback_t cb)
Modified findradius aware of warpzones, that only includes entities that meet the "cb" criteria.
#define WarpZone_FindRadius(org, radius)
Modified findradius aware of warpzones.
noref entity WarpZone_SearchInRadius_otherent
Free to use in the callback.
void set_movetype(entity this, int mt)
@ STATUSEFFECT_REMOVE_CLEAR
Effect is being forcibly removed without calling any additional mechanics.
@ STATUSEFFECT_REMOVE_NORMAL
Effect is being removed by a function, calls regular removal mechanics.
void Send_Notification(NOTIF broadcast, entity client, MSG net_type, Notification net_name,...count)
ERASEABLE void RandomSelection_Init()
#define RandomSelection_AddEnt(e, weight, priority)
entity RandomSelection_chosen_ent
#define crandom()
Returns a random number between -1.0 and 1.0.
#define REGISTRY_GET(id, i)
#define AVAILABLE_TEAMS
Number of teams that exist currently.
bool client_hasweapon(entity this, Weapon wpn,.entity weaponentity, float andammo, bool complain)
#define w_getbestweapon(ent, wepent)
float pauserotfuel_finished
float pauseregen_finished
float pauserothealth_finished
float pauserotarmor_finished
float generic_pickupevalfunc(entity player, entity item)
bool Item_ItemsTime_SpectatorOnly(GameItem it)
float ammo_pickupevalfunc(entity player, entity item)
float Item_ItemsTime_UpdateTime(entity e, float t)
void GiveRot(entity e, float v0, float v1,.float rotfield, float rottime,.float regenfield, float regentime)
float adjust_respawntime(float normal_respawntime)
Adjust respawn time according to the number of players.
void Item_ScheduleRespawn(entity e)
void Item_ItemsTime_SetTimesForAllPlayers()
void Item_CopyFields(entity this, entity to)
bool GiveStatusEffect(entity e, StatusEffect this, int op, float val)
bool GiveBuff(entity e, Buff thebuff, int op, int val)
bool ItemSend(entity this, entity to, int sf)
void Item_RespawnThink(entity this)
void Item_NotifyWeapon(entity player, entity wep)
bool Item_GiveAmmoTo(entity item, entity player, Resource res_type, float ammomax)
void Item_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
void ItemUpdate(entity this)
void StartItem(entity this, entity def)
void Item_ScheduleInitialRespawn(entity e)
void Item_ScheduleRespawnIn(entity e, float t)
void UpdateItemAfterTeleport(entity this)
void RemoveItem(entity this)
float weapon_pickupevalfunc(entity player, entity item)
bool setItemGroup_cond(entity e)
float GiveWeapon(entity e, float wpn, float op, float val)
void Item_Think(entity this)
void Item_RespawnCountdown(entity this)
void Item_Show(entity e, int mode)
void setItemGroup(entity this)
void item_use(entity this, entity actor, entity trigger)
void Item_ItemsTime_SetTime(entity e, float t)
void Item_FindTeam(entity this)
float GiveItems(entity e, float beginarg, float endarg)
bool have_pickup_item(entity this)
bool Item_ItemsTime_Allow(GameItem it)
void Item_Reset(entity this)
bool GiveResourceValue(entity e, Resource res_type, int op, int val)
float healtharmor_pickupevalfunc(entity player, entity item)
void item_setactive(entity this, int act)
void GiveSound(entity e, float v0, float v1, float t, Sound snd_incr, Sound snd_decr)
void GiveRandomWeapons(entity receiver, int num_weapons, string weapon_names, entity ammo_entity)
Give several random weapons and ammo to the entity.
bool Item_GiveTo(entity item, entity player)
void Item_Respawn(entity this)
void Item_Touch(entity this, entity toucher)
float autocvar_g_balance_superweapons_time
entity item_pickupsound_ent
int autocvar_g_pickup_items
float item_respawncounter
#define ITEM_TOUCH_NEEDKILL()
#define ITEM_DAMAGE_NEEDKILL(dt)
#define POSTGIVE_WEAPON(e, b, snd_incr, snd_decr)
float autocvar_sv_simple_items
#define PREGIVE_WEAPONS(e)
#define POSTGIVE_RESOURCE(e, f, t, snd_incr, snd_decr)
bool autocvar_g_fullbrightitems
#define PREGIVE_STATUSEFFECT(e, f)
float superweapons_finished
const float ITEM_RESPAWN_TICKS
#define PREGIVE_RESOURCE(e, f)
float autocvar_g_items_maxdist
bool autocvar_g_nodepthtestitems
#define POSTGIVE_STATUSEFFECT(e, f, snd_incr, snd_decr)
float item_spawnshieldtime
#define POSTGIVE_RES_ROT(e, f, t, rotfield, rottime, regenfield, regentime, snd_incr, snd_decr)
#define POSTGIVE_BIT(e, f, b, snd_incr, snd_decr)
float autocvar_g_items_dropped_lifetime
string GetField_fullspawndata(entity e, string fieldname, bool vfspath)
Retrieves the value of a map entity field from fullspawndata.
float autocvar_sys_ticrate
void W_GiveWeapon(entity e, int wep)
const int CH_TRIGGER_SINGLE
#define Sound_fixpath(this)
#define _sound(e, c, s, v, a)
#define sound(e, c, s, v, a)
void soundto(int _dest, entity e, int chan, string samp, float vol, float _atten, float _pitch)
void StatusEffects_remove(StatusEffect this, entity actor, int removal_type)
float StatusEffects_gettime(StatusEffect this, entity actor)
bool StatusEffects_active(StatusEffect this, entity actor)
void StatusEffects_apply(StatusEffect this, entity actor, float eff_time, int eff_flags)
void StatusEffects_update(entity e)
float buff_Available(entity buff)
void buff_RemoveAll(entity actor, int removal_type)
void powerups_DropItem_Think(entity this)
bool autocvar_g_powerups_stack
void GiveResource(entity receiver, Resource res_type, float amount)
Gives an entity some resource.
float GetResourceLimit(entity e, Resource res_type)
Returns the maximum amount of the given resource.
void GiveResourceWithLimit(entity receiver, Resource res_type, float amount, float limit)
Gives an entity some resource but not more than a limit.
float autocvar_g_balance_pause_fuel_regen
float autocvar_g_balance_pause_armor_rot
float autocvar_g_balance_pause_health_rot
float autocvar_g_balance_pause_health_regen
float autocvar_g_balance_pause_fuel_rot
void TeamBalance_Destroy(entity balance)
Destroy the team balance entity.
int TeamBalance_GetNumberOfPlayers(entity balance, int index)
Returns the number of players (both humans and bots) in a team.
void TeamBalance_GetTeamCounts(entity balance, entity ignore)
Counts the number of players and various other information about each team.
entity TeamBalance_CheckAllowedTeams(entity for_whom)
Checks whether the player can join teams according to global configuration and mutator settings.
bool TeamBalance_IsTeamAllowed(entity balance, int index)
Returns whether the team change to the specified team is allowed.
#define IS_REAL_CLIENT(v)
#define FOREACH_CLIENT(cond, body)
void WaypointSprite_Kill(entity wp)
void WaypointSprite_Ping(entity e)
entity WaypointSprite_Spawn(entity spr, float _lifetime, float maxdistance, entity ref, vector ofs, entity showto, float t, entity own,.entity ownfield, float hideable, entity icon)
void WaypointSprite_UpdateBuildFinished(entity e, float f)
void WaypointSprite_UpdateRule(entity e, float t, float r)
entity waypointsprite_attached
const int SPRITERULE_SPECTATOR
entity GetAmmoItem(Resource ammotype)
WepSet WEPSET_SUPERWEAPONS
#define WepSet_FromWeapon(it)
const int MAX_WEAPONSLOTS
entity weaponentities[MAX_WEAPONSLOTS]
const int WEP_FLAG_MUTATORBLOCKED
const int WEP_FLAG_HIDDEN
void W_DropEvent(.void(Weapon, entity actor,.entity) event, entity player, int weapon_type, entity weapon_item,.entity weaponentity)
void DropToFloor_QC_DelayedInit(entity this)
void InitializeEntity(entity e, void(entity this) func, int order)