4 /// \brief Source file that contains implementation of the functions related to
5 /// creation of game items.
6 /// \copyright GNU GPLv2 or any later version.
8 #include <common/mapobjects/subs.qh>
9 #include <common/weapons/all.qh>
10 #include <server/items/items.qh>
11 #include <server/mutators/_mod.qh>
12 #include <server/weapons/spawning.qh>
13 #include <server/world.qh>
15 .bool m_isloot; ///< Holds whether item is loot.
16 /// \brief Holds whether strength, shield or superweapon timers expire while
17 /// this item is on the ground.
20 entity Item_FindDefinition(string class_name)
22 FOREACH(Items, it.m_canonical_spawnfunc == class_name,
26 FOREACH(Weapons, it.m_canonical_spawnfunc == class_name,
33 entity Item_DefinitionFromInternalName(string item_name)
35 FOREACH(Items, it.netname == item_name,
39 FOREACH(Weapons, it.netname == item_name,
46 bool Item_IsAllowed(string class_name)
48 entity definition = Item_FindDefinition(class_name);
49 if (definition == NULL)
53 return Item_IsDefinitionAllowed(definition);
56 bool Item_IsDefinitionAllowed(entity definition)
58 return !MUTATOR_CALLHOOK(FilterItemDefinition, definition);
61 entity Item_Create(string class_name, vector position, bool no_align)
63 entity item = spawn();
64 item.classname = class_name;
65 item.spawnfunc_checked = true;
66 setorigin(item, position);
67 item.noalign = no_align;
68 Item_Initialize(item, class_name);
76 void Item_Initialize(entity item, string class_name)
78 FOREACH(Weapons, it.m_canonical_spawnfunc == class_name,
80 weapon_defaultspawnfunc(item, it);
83 FOREACH(Items, it.m_canonical_spawnfunc == class_name,
88 LOG_FATALF("Item_Initialize: Invalid classname: %s", class_name);
91 entity Item_CreateLoot(string class_name, vector position, vector vel,
94 entity item = spawn();
95 if (!Item_InitializeLoot(item, class_name, position, vel, time_to_live))
102 bool Item_InitializeLoot(entity item, string class_name, vector position,
103 vector vel, float time_to_live)
105 item.classname = class_name;
106 Item_SetLoot(item, true);
108 setorigin(item, position);
109 item.pickup_anyway = true;
110 item.spawnfunc_checked = true;
111 Item_Initialize(item, class_name);
118 // StartItem sets the default .wait expiry time which is respected by Item_Think()
120 item.wait = time + time_to_live;
124 // An optimised and generic way to initialise items (loot or permanent)
125 // required field: itemdef (faster, preferred) OR classname
126 // optional fields: origin, velocity, lifetime, noalign
127 // lifetime < 0 means permanent (not loot), lifetime > 0 overrides the default
128 // permanent items only: noalign means the item is suspended (won't drop to floor)
129 bool Item_Initialise(entity item)
131 if (item.lifetime >= 0)
133 Item_SetLoot(item, true);
134 item.pickup_anyway = true; // these are ALWAYS pickable
137 if (item.itemdef) // no search required
139 if (item.itemdef.instanceOfWeapon)
140 weapon_defaultspawnfunc(item, item.itemdef);
142 StartItem(item, item.itemdef);
144 else // fall back to classname search
146 FOREACH(Weapons, it.m_canonical_spawnfunc == item.classname,
148 weapon_defaultspawnfunc(item, it);
149 goto classname_found;
151 FOREACH(Items, it.m_canonical_spawnfunc == item.classname,
154 goto classname_found;
156 LOG_FATALF("Item_Initialize: Invalid classname: %s", item.classname);
157 LABEL(classname_found)
163 // StartItem sets the default .wait expiry time which is respected by Item_Think()
164 if (item.lifetime > 0)
165 item.wait = time + item.lifetime;
167 item.spawnfunc_checked = true;
171 bool Item_IsLoot(entity item)
173 return item.m_isloot || item.classname == "droppedweapon";
176 void Item_SetLoot(entity item, bool loot)
178 item.m_isloot = loot;
181 bool Item_ShouldKeepPosition(entity item)
183 return item.noalign || (item.spawnflags & 1);
186 bool Item_IsExpiring(entity item)
188 return item.m_isexpiring;
191 void Item_SetExpiring(entity item, bool expiring)
193 item.m_isexpiring = expiring;
196 // Compatibility spawn functions
198 // in Quake this is green armor, in Xonotic maps it is an armor shard
199 SPAWNFUNC_ITEM_COND(item_armor1, autocvar_sv_mapformat_is_quake3, ITEM_ArmorSmall, ITEM_ArmorMedium)
200 SPAWNFUNC_ITEM(item_armor25, ITEM_ArmorMega) // Nexuiz used item_armor25 to spawn a Mega Armor
201 SPAWNFUNC_ITEM(item_health1, ITEM_HealthSmall)
202 SPAWNFUNC_ITEM(item_health25, ITEM_HealthMedium)
203 SPAWNFUNC_ITEM(item_health100, ITEM_HealthMega)
204 SPAWNFUNC_ITEM(item_armor_large, ITEM_ArmorMega)
205 SPAWNFUNC_ITEM(item_health_large, ITEM_HealthBig)