1 #include "sv_overkill.qh"
3 #include "okshotgun.qh"
7 bool autocvar_g_overkill_powerups_replace;
8 bool autocvar_g_overkill_itemwaypoints = true;
9 bool autocvar_g_overkill_blaster_keepforce = false;
10 bool autocvar_g_overkill_blaster_keepdamage = false;
12 .Weapon ok_lastwep[MAX_WEAPONSLOTS];
14 /// \brief Returns a random classname of the overkill item.
15 /// \param[in] prefix Prefix of the cvars that hold probabilities.
16 /// \return Random classname of the overkill item.
17 string RandomItems_GetRandomOverkillItemClassName(string prefix)
19 RandomSelection_Init();
20 IL_EACH(g_overkill_items, !(it.spawnflags & ITEM_FLAG_MUTATORBLOCKED) &&
21 Item_IsDefinitionAllowed(it),
23 string cvar_name = sprintf("g_%s_%s_probability", prefix,
24 it.m_canonical_spawnfunc);
25 if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
27 LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
30 RandomSelection_AddString(it.m_canonical_spawnfunc, cvar(cvar_name), 1);
32 string cvar_name = sprintf("g_%s_weapon_okhmg_probability", prefix);
33 if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
35 LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
39 RandomSelection_AddString("weapon_okhmg", cvar(cvar_name), 1);
41 cvar_name = sprintf("g_%s_weapon_okrpc_probability", prefix);
42 if (!(cvar_type(cvar_name) & CVAR_TYPEFLAG_EXISTS))
44 LOG_WARNF("Random items: cvar %s doesn't exist.", cvar_name);
48 RandomSelection_AddString("weapon_okrpc", cvar(cvar_name), 1);
50 return RandomSelection_chosen_string;
54 MUTATOR_HOOKFUNCTION(ok, RandomItems_GetRandomItemClassName)
56 M_ARGV(1, string) = RandomItems_GetRandomOverkillItemClassName(
61 MUTATOR_HOOKFUNCTION(ok, Damage_Calculate, CBC_ORDER_LAST)
63 entity frag_attacker = M_ARGV(1, entity);
64 entity frag_target = M_ARGV(2, entity);
65 float frag_deathtype = M_ARGV(3, float);
67 if(IS_PLAYER(frag_attacker) && (IS_PLAYER(frag_target) || IS_VEHICLE(frag_target) || IS_TURRET(frag_target)))
68 if(DEATH_ISWEAPON(frag_deathtype, WEP_BLASTER))
70 if(frag_attacker != frag_target)
71 if(!STAT(FROZEN, frag_target))
72 if(!IS_DEAD(frag_target))
73 if(!autocvar_g_overkill_blaster_keepforce)
74 M_ARGV(6, vector) = '0 0 0'; // force
76 if(!autocvar_g_overkill_blaster_keepdamage)
77 M_ARGV(4, float) = 0; // damage
81 void ok_DropItem(entity this, entity attacker, entity e)
84 e.itemdef = ITEM_ArmorSmall;
85 e.origin = this.origin + '0 0 32';
86 e.velocity = '0 0 200' + normalize(attacker.origin - this.origin) * 500;
90 MUTATOR_HOOKFUNCTION(ok, PlayerDies)
92 entity frag_attacker = M_ARGV(1, entity);
93 entity frag_target = M_ARGV(2, entity);
95 entity attacker = ((IS_PLAYER(frag_attacker)) ? frag_attacker : frag_target);
96 entity item = spawn();
97 ok_DropItem(frag_target, attacker, item);
98 Item_Initialise(item);
100 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
102 .entity weaponentity = weaponentities[slot];
104 frag_target.ok_lastwep[slot] = frag_target.(weaponentity).m_switchweapon;
108 MUTATOR_HOOKFUNCTION(ok, MonsterDropItem)
110 entity mon = M_ARGV(0, entity);
111 entity item = M_ARGV(1, entity);
112 entity frag_attacker = M_ARGV(2, entity);
114 ok_DropItem(mon, frag_attacker, item);
117 MUTATOR_HOOKFUNCTION(ok, ForbidThrowCurrentWeapon)
122 MUTATOR_HOOKFUNCTION(ok, PlayerPreThink)
128 entity player = M_ARGV(0, entity);
129 if (!IS_PLAYER(player) || IS_DEAD(player) || STAT(FROZEN, player))
133 if (!PHYS_INPUT_BUTTON_ATCK2(player) || weaponLocked(player) ||
134 !(round_handler_IsActive() && !round_handler_IsRoundStarted()))
138 // Allow secondary blaster during countdown.
139 for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
141 .entity weaponentity = weaponentities[slot];
142 Weapon weapon = player.(weaponentity).m_weapon;
143 if (weapon == WEP_Null && slot != 0)
147 weapon.wr_think(weapon, player, weaponentity, 2);
149 PHYS_INPUT_BUTTON_ATCK2(player) = false;
152 MUTATOR_HOOKFUNCTION(ok, ForbidRandomStartWeapons)
157 MUTATOR_HOOKFUNCTION(ok, PlayerWeaponSelect)
159 entity player = M_ARGV(0, entity);
161 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
163 .entity weaponentity = weaponentities[slot];
164 entity thiswep = player.(weaponentity);
166 if(player.ok_lastwep[slot] && player.ok_lastwep[slot] != WEP_Null)
168 Weapon newwep = player.ok_lastwep[slot];
169 if(player.ok_lastwep[slot] == WEP_OVERKILL_HMG)
170 newwep = WEP_OVERKILL_MACHINEGUN;
171 if(player.ok_lastwep[slot] == WEP_OVERKILL_RPC)
172 newwep = WEP_OVERKILL_NEX;
173 thiswep.m_switchweapon = newwep;
174 player.ok_lastwep[slot] = WEP_Null;
179 bool ok_HandleItemWaypoints(entity e)
181 if(!autocvar_g_overkill_itemwaypoints)
182 return false; // don't handle it
186 case ITEM_HealthMega: return true;
187 case ITEM_ArmorMedium: return true;
188 case ITEM_ArmorBig: return true;
189 case ITEM_ArmorMega: return true;
195 MUTATOR_HOOKFUNCTION(ok, Item_RespawnCountdown)
197 entity item = M_ARGV(0, entity);
198 return ok_HandleItemWaypoints(item);
201 MUTATOR_HOOKFUNCTION(ok, Item_ScheduleRespawn)
203 entity item = M_ARGV(0, entity);
204 return ok_HandleItemWaypoints(item);
207 MUTATOR_HOOKFUNCTION(ok, FilterItem)
209 entity item = M_ARGV(0, entity);
217 case ITEM_HealthMega: return autocvar_g_overkill_filter_healthmega;
218 case ITEM_ArmorMedium: return autocvar_g_overkill_filter_armormedium;
219 case ITEM_ArmorBig: return autocvar_g_overkill_filter_armorbig;
220 case ITEM_ArmorMega: return autocvar_g_overkill_filter_armormega;
222 if (!autocvar_g_powerups || !autocvar_g_overkill_powerups_replace)
226 if (item.classname == "item_strength")
228 entity wep = spawn();
229 Item_CopyFields(item, wep);
231 wep.respawntime = g_pickup_respawntime_superweapon;
232 wep.pickup_anyway = true;
233 wep.itemdef = WEP_OVERKILL_HMG;
235 Item_Initialise(wep);
238 else if (item.classname == "item_shield")
240 entity wep = spawn();
241 Item_CopyFields(item, wep);
243 wep.respawntime = g_pickup_respawntime_superweapon;
244 wep.pickup_anyway = true;
245 wep.itemdef = WEP_OVERKILL_RPC;
247 Item_Initialise(wep);
253 MUTATOR_HOOKFUNCTION(ok, SetStartItems, CBC_ORDER_LAST)
255 WepSet ok_start_items = (WEPSET(OVERKILL_MACHINEGUN) | WEPSET(OVERKILL_NEX) | WEPSET(OVERKILL_SHOTGUN));
257 if(WEP_OVERKILL_RPC.weaponstart > 0) { ok_start_items |= WEPSET(OVERKILL_RPC); }
258 if(WEP_OVERKILL_HMG.weaponstart > 0) { ok_start_items |= WEPSET(OVERKILL_HMG); }
260 start_items |= IT_UNLIMITED_AMMO;
262 start_weapons = warmup_start_weapons = ok_start_items;
265 MUTATOR_HOOKFUNCTION(ok, SetWeaponArena)
267 // turn weapon arena off
268 M_ARGV(0, string) = "off";
271 MUTATOR_HOOKFUNCTION(ok, BuildMutatorsString)
273 M_ARGV(0, string) = strcat(M_ARGV(0, string), ":OK");
276 MUTATOR_HOOKFUNCTION(ok, BuildMutatorsPrettyString)
278 M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Overkill");
281 MUTATOR_HOOKFUNCTION(ok, SetModname)
283 M_ARGV(0, string) = "Overkill";