]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/mutators/mutator/nades/nades.qh
Merge branch 'z411/bai-server' into LegendaryGuard/bai_mod
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mutators / mutator / nades / nades.qh
1 #pragma once
2
3 #include <common/teams.qh>
4
5 #ifdef SVQC
6 bool autocvar_g_nades;
7 bool autocvar_g_nades_override_dropweapon = true;
8 vector autocvar_g_nades_throw_offset;
9 bool autocvar_g_nades_spawn;
10 int autocvar_g_nades_spawn_count;
11 bool autocvar_g_nades_client_select;
12 bool autocvar_g_nades_pickup = true;
13 float autocvar_g_nades_pickup_time = 2;
14 float autocvar_g_nades_nade_lifetime;
15 float autocvar_g_nades_nade_minforce;
16 float autocvar_g_nades_nade_maxforce;
17 float autocvar_g_nades_nade_health;
18 float autocvar_g_nades_nade_refire;
19 float autocvar_g_nades_nade_damage;
20 float autocvar_g_nades_nade_edgedamage;
21 float autocvar_g_nades_nade_radius;
22 float autocvar_g_nades_nade_force;
23 int autocvar_g_nades_nade_newton_style;
24 int autocvar_g_nades_napalm_ball_count;
25 float autocvar_g_nades_napalm_ball_spread;
26 float autocvar_g_nades_napalm_ball_damage;
27 float autocvar_g_nades_napalm_ball_damageforcescale;
28 float autocvar_g_nades_napalm_ball_lifetime;
29 float autocvar_g_nades_napalm_ball_radius;
30 bool autocvar_g_nades_napalm_blast;
31 float autocvar_g_nades_napalm_fountain_lifetime;
32 float autocvar_g_nades_napalm_fountain_delay;
33 float autocvar_g_nades_napalm_fountain_radius;
34 float autocvar_g_nades_napalm_fountain_damage;
35 float autocvar_g_nades_napalm_fountain_edgedamage;
36 float autocvar_g_nades_napalm_burntime;
37 bool autocvar_g_nades_napalm_selfdamage;
38 int autocvar_g_nades_nade_type;
39 int autocvar_g_nades_bonus_type;
40 bool autocvar_g_nades_bonus;
41 bool autocvar_g_nades_bonus_onstrength;
42 bool autocvar_g_nades_bonus_client_select;
43 bool autocvar_g_nades_bonus_only;
44 int autocvar_g_nades_bonus_max;
45 int autocvar_g_nades_bonus_score_max;
46 int autocvar_g_nades_bonus_score_time;
47 int autocvar_g_nades_bonus_score_time_flagcarrier;
48 int autocvar_g_nades_bonus_score_minor;
49 int autocvar_g_nades_bonus_score_low;
50 int autocvar_g_nades_bonus_score_high;
51 int autocvar_g_nades_bonus_score_medium;
52 int autocvar_g_nades_bonus_score_spree;
53 float autocvar_g_nades_ice_freeze_time;
54 float autocvar_g_nades_ice_health;
55 bool autocvar_g_nades_ice_explode;
56 bool autocvar_g_nades_ice_teamcheck;
57 float autocvar_g_nades_heal_time;
58 float autocvar_g_nades_heal_rate;
59 float autocvar_g_nades_heal_friend;
60 float autocvar_g_nades_heal_foe;
61 float autocvar_g_nades_entrap_strength = 0.01;
62 float autocvar_g_nades_entrap_speed = 0.5;
63 float autocvar_g_nades_entrap_radius = 500;
64 float autocvar_g_nades_entrap_time = 10;
65 float autocvar_g_nades_veil_time = 8;
66 float autocvar_g_nades_veil_radius = 300;
67 float autocvar_g_nades_armorize_time = 5; //LegendGuard adds new nade cvars 11-02-2021
68 float autocvar_g_nades_armorize_rate = 30;
69 float autocvar_g_nades_armorize_friend = 1;
70 float autocvar_g_nades_armorize_foe = -2;
71 float autocvar_g_nades_ammo_time = 5; //LegendGuard adds new nade cvars 13-02-2021
72 float autocvar_g_nades_ammo_rate = 30;
73 float autocvar_g_nades_ammo_friend = 1;
74 float autocvar_g_nades_ammo_foe = -2;
75 float autocvar_g_nades_dark_damage = 25; //LegendGuard adds new nade cvars 08-02-2021
76 float autocvar_g_nades_dark_time = 13;
77 float autocvar_g_nades_dark_radius = 700;
78 string autocvar_g_nades_pokenade_monster_type;
79 float autocvar_g_nades_pokenade_monster_lifetime;
80 #endif
81
82 // use slots 70-100
83 const int PROJECTILE_NADE = 71;
84 const int PROJECTILE_NADE_BURN = 72;
85 const int PROJECTILE_NADE_NAPALM = 73;
86 const int PROJECTILE_NADE_NAPALM_BURN = 74;
87 const int PROJECTILE_NAPALM_FOUNTAIN = 75;
88 const int PROJECTILE_NADE_ICE = 76;
89 const int PROJECTILE_NADE_ICE_BURN = 77;
90 const int PROJECTILE_NADE_TRANSLOCATE = 78;
91 const int PROJECTILE_NADE_SPAWN = 79;
92 const int PROJECTILE_NADE_HEAL = 80;
93 const int PROJECTILE_NADE_HEAL_BURN = 81;
94 const int PROJECTILE_NADE_MONSTER = 82;
95 const int PROJECTILE_NADE_MONSTER_BURN = 83;
96 const int PROJECTILE_NADE_ENTRAP = 84;
97 const int PROJECTILE_NADE_ENTRAP_BURN = 85;
98 const int PROJECTILE_NADE_VEIL = 86;
99 const int PROJECTILE_NADE_VEIL_BURN = 87;
100 const int PROJECTILE_NADE_ARMORIZE = 88; //LegendGuard adds new nade MACROS 11-02-2021
101 const int PROJECTILE_NADE_ARMORIZE_BURN = 89;
102 const int PROJECTILE_NADE_AMMO = 90; //LegendGuard adds new nade MACROS 13-02-2021
103 const int PROJECTILE_NADE_AMMO_BURN = 91;
104 const int PROJECTILE_NADE_DARK = 92; //LegendGuard adds new nade MACROS 08-02-2021
105 const int PROJECTILE_NADE_DARK_BURN = 93;
106
107 REGISTRY(Nades, BITS(4))
108 REGISTER_REGISTRY(Nades)
109 REGISTRY_CHECK(Nades)
110
111 #define REGISTER_NADE(id) REGISTER(Nades, NADE_TYPE, id, m_id, NEW(Nade))
112
113 CLASS(Nade, Object)
114     ATTRIB(Nade, m_id, int, 0);
115     ATTRIB(Nade, m_color, vector, '0 0 0');
116     ATTRIB(Nade, m_name, string, _("Grenade"));
117     ATTRIB(Nade, m_icon, string, "nade_normal");
118     ATTRIB(Nade, m_alpha, float, 1);
119     ATTRIBARRAY(Nade, m_projectile, int, 2);
120     ATTRIBARRAY(Nade, m_trail, entity, 2);
121     METHOD(Nade, display, void(entity this, void(string name, string icon) returns)) {
122         returns(this.m_name, sprintf("/gfx/hud/%s/%s", cvar_string("menu_skin"), this.m_icon));
123     }
124 ENDCLASS(Nade)
125
126 REGISTER_NADE(Null);
127 REGISTRY_DEFINE_GET(Nades, NADE_TYPE_Null)
128
129 Nade Nade_FromProjectile(int proj)
130 {
131     FOREACH(Nades, true, {
132         for (int j = 0; j < 2; j++)
133         {
134             if (it.m_projectile[j] == proj) return it;
135         }
136     });
137     return NADE_TYPE_Null;
138 }
139
140 #ifdef GAMEQC
141 #include "effects.inc"
142 #endif
143
144 #include "nades.inc"
145
146 .float orb_lifetime;
147 .float orb_radius;
148
149 #ifdef SVQC
150
151 .entity nade;
152 .entity fake_nade;
153 .float nade_refire;
154 .float nade_special_time;
155 .string pokenade_type;
156 .entity nade_damage_target;
157 .float cvar_cl_nade_type;
158 .string cvar_cl_pokenade_type;
159 .float toss_time;
160 .float nade_show_particles;
161 .float nade_veil_prevalpha;
162 .float nade_dark_prevalpha; //LegendGuard adds new nade .variable 08-02-2021
163
164 bool orb_send(entity this, entity to, int sf);
165
166 // Remove nades that are being thrown
167 void nades_Clear(entity player);
168
169 // Give a bonus grenade to a player
170 void nades_GiveBonus(entity player, float score);
171
172 /**
173  * called to adjust nade damage and force on hit
174  */
175 #define EV_Nade_Damage(i, o) \
176     /** nade */   i(entity, MUTATOR_ARGV_0_entity) \
177         /** weapon */ i(entity, MUTATOR_ARGV_1_entity) \
178     /** force */  i(vector, MUTATOR_ARGV_2_vector) \
179     /**/          o(vector, MUTATOR_ARGV_2_vector) \
180         /** damage */ i(float,  MUTATOR_ARGV_3_float) \
181     /**/          o(float,  MUTATOR_ARGV_3_float) \
182     /**/
183 MUTATOR_HOOKABLE(Nade_Damage, EV_Nade_Damage);
184
185 #endif
186
187 REGISTER_NET_TEMP(TE_CSQC_DARKBLINKING); //LegendGuard registers dark blinking nade feature 09-02-2021
188
189 #ifdef CSQC
190 float cvar_cl_nade_type;
191 string cvar_cl_pokenade_type;
192 //LegendGuard sets variables for dark nade 09-02-2021
193 float autocvar_hud_panel_darkradar_maximised_zoom_scale = 1;
194 float dark_appeartime;
195 float dark_fadetime;
196 /***************************************************************/
197 void HUD_DarkBlinking()
198 {
199         // vectors for top right, bottom right, bottom and bottom left corners
200         //vector topright = vec2(vid_conwidth, 0);
201         //vector bottom = vec2(vid_conwidth / 2, vid_conheight);
202         vector bottomright = vec2(vid_conwidth, vid_conheight);
203         //vector bottomleft = vec2(0, vid_conheight);
204
205         /*
206         drawfill function parameters (qcsrc/dpdefs/menudefs.qc):
207         float drawfill(vector position, vector size, vector rgb, float alpha, float flag)
208         */
209         drawfill('0 0 0', bottomright, '0.23 0 0.23', 0.98, DRAWFLAG_NORMAL);
210 }
211
212 #elif defined(SVQC)
213 void DarkBlinking(entity e)
214 {
215         if(e == NULL)
216                 return;
217
218         int accepted = VerifyClientEntity(e, true, false);
219
220         if(accepted > 0) 
221         {
222                 msg_entity = e;
223                 WriteHeader(MSG_ONE, TE_CSQC_DARKBLINKING);
224         }
225 }
226 #endif
227
228 #ifdef CSQC
229 const int MAX_QUADRATIC2 = 25;
230 vector quadratic2_slots[MAX_QUADRATIC2];
231 vector quadratic2_dirs[MAX_QUADRATIC2];
232 const float QUADRATIC2_SPEED = 150;
233 const float QUADRATIC2_TURNSPEED = 0.35;
234 const float QUADRATIC2_SIZE = 24;
235 const float QUADRATIC2_CHANCE = 0.35;
236 float quadratic2_spawntime, quadratic2_fadetime;
237 bool quadratic2;
238 void HUD_Quadratic2()
239 {
240         for(int j = MAX_QUADRATIC2 - 1; j >= 0; --j)
241         {
242                 vector slot = quadratic2_slots[j];
243                 vector dirs = quadratic2_dirs[j];
244                 float oldz = slot.z;
245                 if(slot)
246                         slot += quadratic2_dirs[j] * QUADRATIC2_SPEED * frametime;
247                 slot.z = oldz;
248                 //if(slot.z)
249                         //slot.z = sin(QUADRATIC2_TURNSPEED * M_PI * time);
250                 if(slot.y > vid_conheight || slot.x > vid_conwidth)
251                         slot = '0 0 0';
252
253                 if(slot == '0 0 0')
254                 {
255                         if(time > quadratic2_spawntime && random() <= QUADRATIC2_CHANCE) // low chance to spawn!
256                         {
257                                 slot.x = bound(0, (random() * vid_conwidth + 1), vid_conwidth);
258                                 slot.y = bound(0, (random() * vid_conheight + 1), vid_conheight);
259                                 slot.z = 0;
260                                 dirs = vec2(randomvec());
261                                 quadratic2_spawntime = time + bound(0.05, random() * 0.5, 0.4); // prevent spawning another one for this amount of time!
262                         }
263                 }
264                 else
265                 {
266                         vector splash_size = vec2(QUADRATIC2_SIZE, QUADRATIC2_SIZE);
267                         if(time > dirs.z)
268                         {
269                                 if(random() <= 0.05)
270                                         slot.z = -1;
271                                 else
272                                         slot.z = floor(random() * 9) + 1;
273                                 dirs.z = time + QUADRATIC2_TURNSPEED;
274                         }
275                         string chosen_number = ((slot.z == -1) ? "NOOB" : ftos(rint(slot.z)));
276                         draw_beginBoldFont();
277                         drawcolorcodedstring(vec2(slot), chosen_number, splash_size, 0.95, DRAWFLAG_NORMAL);
278                         draw_endBoldFont();
279                 }
280
281                 quadratic2_slots[j] = slot;
282                 quadratic2_dirs[j] = dirs;
283         }
284 }
285
286 bool darkblink;
287
288 STATIC_INIT_LATE(cl_darkblink_override)
289 {
290         localcmd("\nalias solve_quadratic2 \"cl_cmd solve_quadratic2 ${* ?}\"\n");
291 }
292
293 REGISTER_MUTATOR(cl_darkblink, true);
294
295 MUTATOR_HOOKFUNCTION(cl_darkblink, DrawScoreboard)
296 {
297         return darkblink;
298 }
299
300 MUTATOR_HOOKFUNCTION(cl_darkblink, HUD_Draw_overlay)
301 {
302         if(!darkblink && !quadratic2)
303                 return false;
304
305         if(time <= dark_fadetime && autocvar_hud_panel_darkradar_maximised_zoom_scale == 1)
306         {
307                 HUD_DarkBlinking();
308                 return false;
309         }
310         else
311                 darkblink = false;
312
313         if(time <= quadratic2_fadetime)
314         {
315                 HUD_Quadratic2();
316                 // don't return true, we want regular HUD effects!
317         }
318         else
319                 quadratic2 = false;
320
321         return false;
322 }
323
324 MUTATOR_HOOKFUNCTION(cl_darkblink, CSQC_ConsoleCommand)
325 {
326         if(MUTATOR_RETURNVALUE) // command was already handled?
327                 return;
328
329         string cmd_name = M_ARGV(0, string);
330         //int cmd_argc = M_ARGV(2, int);
331
332         if(cmd_name == "solve_quadratic2")
333         {
334                 quadratic2 = true;
335                 quadratic2_fadetime = time + 5;
336                 return true;
337         }
338 }
339
340 NET_HANDLE(TE_CSQC_DARKBLINKING, bool isNew)
341 {
342         return = true;
343
344         if(darkblink)
345                 return;
346
347         localcmd("play2 sound/misc/blind\n");
348         darkblink = true;
349         dark_appeartime = time;
350         dark_fadetime = time + 9;
351 }
352 #endif
353 /***************************************************************/
354 #ifdef CSQC
355 bool Projectile_isnade(int proj); // TODO: remove
356
357 void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expand_time); // TODO: mutator
358 #endif