]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/mutators/mutator/overkill/sv_overkill.qc
Random items: Added proper overkill support.
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mutators / mutator / overkill / sv_overkill.qc
1 #include "sv_overkill.qh"
2
3 #include "hmg.qh"
4 #include "rpc.qh"
5
6 string autocvar_g_overkill;
7
8 bool autocvar_g_overkill_powerups_replace;
9
10 bool autocvar_g_overkill_itemwaypoints = true;
11
12 .Weapon ok_lastwep[MAX_WEAPONSLOTS];
13
14 void ok_Initialize();
15
16 REGISTER_MUTATOR(ok, expr_evaluate(autocvar_g_overkill) && !cvar("g_instagib") && !g_nexball && cvar_string("g_mod_balance") == "Overkill")
17 {
18         MUTATOR_ONADD
19         {
20                 ok_Initialize();
21         }
22
23         MUTATOR_ONREMOVE
24         {
25                 WEP_RPC.spawnflags |= WEP_FLAG_MUTATORBLOCKED;
26                 WEP_HMG.spawnflags |= WEP_FLAG_MUTATORBLOCKED;
27         }
28 }
29
30 void W_Blaster_Attack(entity, .entity, float, float, float, float, float, float, float, float, float, float);
31 spawnfunc(weapon_hmg);
32 spawnfunc(weapon_rpc);
33
34 MUTATOR_HOOKFUNCTION(ok, Damage_Calculate, CBC_ORDER_LAST)
35 {
36         entity frag_attacker = M_ARGV(1, entity);
37         entity frag_target = M_ARGV(2, entity);
38         float frag_deathtype = M_ARGV(3, float);
39
40         if(IS_PLAYER(frag_attacker) && (IS_PLAYER(frag_target) || IS_VEHICLE(frag_target) || IS_TURRET(frag_target)))
41         if(DEATH_ISWEAPON(frag_deathtype, WEP_BLASTER))
42         {
43                 if(frag_attacker != frag_target)
44                 if(!STAT(FROZEN, frag_target))
45                 if(!IS_DEAD(frag_target))
46                 {
47                         Send_Notification(NOTIF_ONE, frag_attacker, MSG_CENTER, CENTER_SECONDARY_NODAMAGE);
48                         M_ARGV(6, vector) = '0 0 0'; // force
49                 }
50
51                 M_ARGV(4, float) = 0; // damage
52         }
53 }
54
55 void ok_DropItem(entity this, entity targ)
56 {
57         entity e = spawn();
58         e.ok_item = true;
59         Item_InitializeLoot(e, "item_armor_small", this.origin + '0 0 32',
60                 '0 0 200' + normalize(targ.origin - this.origin) * 500, 5);
61 }
62
63 MUTATOR_HOOKFUNCTION(ok, PlayerDies)
64 {
65         entity frag_attacker = M_ARGV(1, entity);
66         entity frag_target = M_ARGV(2, entity);
67
68         entity targ = ((frag_attacker) ? frag_attacker : frag_target);
69
70         ok_DropItem(frag_target, targ);
71
72         for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
73         {
74                 .entity weaponentity = weaponentities[slot];
75
76                 frag_target.ok_lastwep[slot] = frag_target.(weaponentity).m_switchweapon;
77         }
78 }
79
80 MUTATOR_HOOKFUNCTION(ok, MonsterDropItem)
81 {
82         entity mon = M_ARGV(0, entity);
83         entity olditem = M_ARGV(1, entity);
84         entity frag_attacker = M_ARGV(2, entity);
85
86         delete(olditem);
87
88         M_ARGV(1, entity) = NULL;
89
90         ok_DropItem(mon, frag_attacker);
91 }
92
93 MUTATOR_HOOKFUNCTION(ok, ForbidThrowCurrentWeapon)
94 {
95         return true;
96 }
97
98 MUTATOR_HOOKFUNCTION(ok, PlayerPreThink)
99 {
100         if(game_stopped)
101                 return;
102
103         entity player = M_ARGV(0, entity);
104
105         if(IS_DEAD(player) || !IS_PLAYER(player) || STAT(FROZEN, player))
106                 return;
107
108         if(PHYS_INPUT_BUTTON_ATCK2(player) && time >= player.jump_interval)
109         if( !forbidWeaponUse(player)
110                 || (round_handler_IsActive() && !round_handler_IsRoundStarted()) )
111         {
112                 player.jump_interval = time + WEP_CVAR_PRI(blaster, refire) * W_WeaponRateFactor(player);
113                 makevectors(player.v_angle);
114
115                 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
116                 {
117                         .entity weaponentity = weaponentities[slot];
118
119                         if(player.(weaponentity).m_weapon == WEP_Null && slot != 0)
120                                 continue;
121
122                         Weapon oldwep = player.(weaponentity).m_weapon;
123                         player.(weaponentity).m_weapon = WEP_BLASTER;
124                         W_Blaster_Attack(
125                                 player,
126                                 weaponentity,
127                                 WEP_BLASTER.m_id | HITTYPE_SECONDARY,
128                                 WEP_CVAR_SEC(vaporizer, shotangle),
129                                 WEP_CVAR_SEC(vaporizer, damage),
130                                 WEP_CVAR_SEC(vaporizer, edgedamage),
131                                 WEP_CVAR_SEC(vaporizer, radius),
132                                 WEP_CVAR_SEC(vaporizer, force),
133                                 WEP_CVAR_SEC(vaporizer, speed),
134                                 WEP_CVAR_SEC(vaporizer, spread),
135                                 WEP_CVAR_SEC(vaporizer, delay),
136                                 WEP_CVAR_SEC(vaporizer, lifetime)
137                         );
138                         player.(weaponentity).m_weapon = oldwep;
139                 }
140         }
141
142         PHYS_INPUT_BUTTON_ATCK2(player) = false;
143 }
144
145 MUTATOR_HOOKFUNCTION(ok, PlayerWeaponSelect)
146 {
147         entity player = M_ARGV(0, entity);
148
149         for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
150         {
151                 .entity weaponentity = weaponentities[slot];
152                 entity thiswep = player.(weaponentity);
153
154                 if(player.ok_lastwep[slot] && player.ok_lastwep[slot] != WEP_Null)
155                 {
156                         Weapon newwep = player.ok_lastwep[slot];
157                         if(player.ok_lastwep[slot] == WEP_HMG)
158                                 newwep = WEP_MACHINEGUN;
159                         if(player.ok_lastwep[slot] == WEP_RPC)
160                                 newwep = WEP_VORTEX;
161                         thiswep.m_switchweapon = newwep;
162                         player.ok_lastwep[slot] = WEP_Null;
163                 }
164         }
165 }
166
167 void self_spawnfunc_weapon_hmg(entity this) { spawnfunc_weapon_hmg(this); }
168 void self_spawnfunc_weapon_rpc(entity this) { spawnfunc_weapon_rpc(this); }
169
170 MUTATOR_HOOKFUNCTION(ok, OnEntityPreSpawn)
171 {
172         entity ent = M_ARGV(0, entity);
173
174         if(autocvar_g_powerups)
175         if(autocvar_g_overkill_powerups_replace)
176         {
177                 if(ent.classname == "item_strength")
178                 {
179                         entity wep = new(weapon_hmg);
180                         setorigin(wep, ent.origin);
181                         setmodel(wep, MDL_OK_HMG);
182                         wep.ok_item = true;
183                         wep.noalign = ent.noalign;
184                         wep.cnt = ent.cnt;
185                         wep.team = ent.team;
186                         wep.respawntime = g_pickup_respawntime_superweapon;
187                         wep.pickup_anyway = true;
188                         wep.spawnfunc_checked = true;
189                         setthink(wep, self_spawnfunc_weapon_hmg);
190                         wep.nextthink = time + 0.1;
191                         return true;
192                 }
193                 else if(ent.classname == "item_invincible")
194                 {
195                         entity wep = new(weapon_rpc);
196                         setorigin(wep, ent.origin);
197                         setmodel(wep, MDL_OK_RPC);
198                         wep.ok_item = true;
199                         wep.noalign = ent.noalign;
200                         wep.cnt = ent.cnt;
201                         wep.team = ent.team;
202                         wep.respawntime = g_pickup_respawntime_superweapon;
203                         wep.pickup_anyway = true;
204                         wep.spawnfunc_checked = true;
205                         setthink(wep, self_spawnfunc_weapon_rpc);
206                         wep.nextthink = time + 0.1;
207                         return true;
208                 }
209         }
210 }
211
212 bool ok_HandleItemWaypoints(entity e)
213 {
214         if(!autocvar_g_overkill_itemwaypoints)
215                 return false; // don't handle it
216
217         switch(e.itemdef)
218         {
219                 case ITEM_HealthMega: return true;
220                 case ITEM_ArmorMedium: return true;
221                 case ITEM_ArmorBig: return true;
222                 case ITEM_ArmorMega: return true;
223         }
224
225         return false;
226 }
227
228 MUTATOR_HOOKFUNCTION(ok, Item_RespawnCountdown)
229 {
230         entity item = M_ARGV(0, entity);
231         return ok_HandleItemWaypoints(item);
232 }
233
234 MUTATOR_HOOKFUNCTION(ok, Item_ScheduleRespawn)
235 {
236         entity item = M_ARGV(0, entity);
237         return ok_HandleItemWaypoints(item);
238 }
239
240 MUTATOR_HOOKFUNCTION(ok, FilterItem)
241 {
242         entity item = M_ARGV(0, entity);
243
244         if(item.ok_item)
245                 return false;
246
247         switch(item.itemdef)
248         {
249                 case ITEM_HealthMega: return autocvar_g_overkill_filter_healthmega;
250                 case ITEM_ArmorMedium: return autocvar_g_overkill_filter_armormedium;
251                 case ITEM_ArmorBig: return autocvar_g_overkill_filter_armorbig;
252                 case ITEM_ArmorMega: return autocvar_g_overkill_filter_armormega;
253         }
254
255         return true;
256 }
257
258 MUTATOR_HOOKFUNCTION(ok, SetStartItems, CBC_ORDER_LAST)
259 {
260         WepSet ok_start_items = (WEPSET(MACHINEGUN) | WEPSET(VORTEX) | WEPSET(SHOTGUN));
261
262         if(WEP_RPC.weaponstart > 0) { ok_start_items |= WEPSET(RPC); }
263         if(WEP_HMG.weaponstart > 0) { ok_start_items |= WEPSET(HMG); }
264
265         start_items |= IT_UNLIMITED_WEAPON_AMMO;
266         start_weapons = warmup_start_weapons = ok_start_items;
267 }
268
269 MUTATOR_HOOKFUNCTION(ok, SetWeaponArena)
270 {
271         // turn weapon arena off
272         M_ARGV(0, string) = "off";
273 }
274
275 MUTATOR_HOOKFUNCTION(ok, BuildMutatorsString)
276 {
277         M_ARGV(0, string) = strcat(M_ARGV(0, string), ":OK");
278 }
279
280 MUTATOR_HOOKFUNCTION(ok, BuildMutatorsPrettyString)
281 {
282         M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Overkill");
283 }
284
285 MUTATOR_HOOKFUNCTION(ok, SetModname)
286 {
287         M_ARGV(0, string) = "Overkill";
288         return true;
289 }
290
291 void ok_Initialize()
292 {
293         precache_all_playermodels("models/ok_player/*.dpm");
294
295         WEP_RPC.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
296         WEP_HMG.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
297
298         WEP_SHOTGUN.mdl = "ok_shotgun";
299         WEP_MACHINEGUN.mdl = "ok_mg";
300         WEP_VORTEX.mdl = "ok_sniper";
301 }