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