4 void nade_timer_think()
6 self.skin = 8 - (self.owner.wait - time) / (autocvar_g_nades_nade_lifetime / 10);
8 if(!self.owner || wasfreed(self.owner))
13 void nade_burn_spawn(entity _nade)
17 switch(_nade.realowner.team)
19 case NUM_TEAM_1: p = PROJECTILE_NADE_RED_BURN; break;
20 case NUM_TEAM_2: p = PROJECTILE_NADE_BLUE_BURN; break;
21 case NUM_TEAM_3: p = PROJECTILE_NADE_YELLOW_BURN; break;
22 case NUM_TEAM_4: p = PROJECTILE_NADE_PINK_BURN; break;
23 default: p = PROJECTILE_NADE_BURN; break;
26 CSQCProjectile(_nade, TRUE, p, TRUE);
29 void nade_spawn(entity _nade)
32 entity timer = spawn();
33 setmodel(timer, "models/ok_nade_counter/ok_nade_counter.md3");
34 setattachment(timer, _nade, "");
35 timer.classname = "nade_timer";
36 timer.colormap = _nade.colormap;
37 timer.glowmod = _nade.glowmod;
38 timer.think = nade_timer_think;
39 timer.nextthink = time;
40 timer.wait = _nade.wait;
44 switch(_nade.realowner.team)
46 case NUM_TEAM_1: p = PROJECTILE_NADE_RED; break;
47 case NUM_TEAM_2: p = PROJECTILE_NADE_BLUE; break;
48 case NUM_TEAM_3: p = PROJECTILE_NADE_YELLOW; break;
49 case NUM_TEAM_4: p = PROJECTILE_NADE_PINK; break;
50 default: p = PROJECTILE_NADE; break;
53 CSQCProjectile(_nade, TRUE, p, TRUE);
57 void nade_boom() // TODO: DamageInfo
61 switch(self.realowner.team)
63 case NUM_TEAM_1: expef = "nade_red_explode"; break;
64 case NUM_TEAM_2: expef = "nade_blue_explode"; break;
65 case NUM_TEAM_3: expef = "nade_yellow_explode"; break;
66 case NUM_TEAM_4: expef = "nade_pink_explode"; break;
67 default: expef = "nade_explode"; break;
70 sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTN_NORM);
71 sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
72 pointparticles(particleeffectnum(expef), self.origin + '0 0 1', '0 0 0', 1);
74 self.takedamage = DAMAGE_NO;
75 RadiusDamage(self, self.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
76 autocvar_g_nades_nade_radius, self, autocvar_g_nades_nade_force, self.projectiledeathtype, self.enemy);
84 setsize(self, '-2 -2 -2', '2 2 2');
85 UpdateCSQCProjectile(self);
86 if(self.health == autocvar_g_nades_nade_health)
88 spamsound(self, CH_SHOTS, strcat("weapons/grenade_bounce", ftos(1 + rint(random() * 5)), ".wav"), VOL_BASE, ATTN_NORM);
98 sound(self, CH_SHOTS_SINGLE, "overkill/grenadebip.ogg", VOL_BASE, 0.5 *(ATTN_LARGE + ATTN_MAX));
99 self.think = nade_boom;
100 self.nextthink = max(self.wait, time);
103 void nade_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
105 if(DEATH_ISWEAPON(deathtype, WEP_LASER))
108 if(DEATH_ISWEAPON(deathtype, WEP_NEX) || DEATH_ISWEAPON(deathtype, WEP_MINSTANEX))
111 damage = autocvar_g_nades_nade_health * 0.55;
114 if(DEATH_ISWEAPON(deathtype, WEP_UZI))
115 damage = autocvar_g_nades_nade_health * 0.1;
117 if(DEATH_ISWEAPON(deathtype, WEP_SHOTGUN))
118 damage = autocvar_g_nades_nade_health * 1.1;
120 self.velocity += force;
125 if(self.health == autocvar_g_nades_nade_health)
127 sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, 0.5 *(ATTN_LARGE + ATTN_MAX));
128 self.nextthink = max(time + autocvar_g_nades_nade_lifetime, time);
129 self.think = nade_beep;
132 self.health -= damage;
133 self.realowner = attacker;
136 W_PrepareExplosionByDamage(attacker, nade_boom);
138 nade_burn_spawn(self);
141 void toss_nade(entity e, vector _velocity, float _time)
143 entity _nade = e.nade;
146 Kill_Notification(NOTIF_ONE_ONLY, e, MSG_CENTER_CPID, CPID_NADES);
148 setorigin(_nade, gettaginfo(_nade, gettagindex(_nade, "Object001")));
149 setattachment(_nade, world, "");
150 PROJECTILE_MAKETRIGGER(_nade);
151 setsize(_nade, '-16 -16 -16', '16 16 16');
152 _nade.movetype = MOVETYPE_BOUNCE;
155 _nade.velocity = '0 0 -10';
156 else if(autocvar_g_nades_nade_newton_style == 1)
157 _nade.velocity = e.velocity + _velocity;
158 else if(autocvar_g_nades_nade_newton_style == 2)
159 _nade.velocity = _velocity;
161 _nade.velocity = W_CalculateProjectileVelocity(e.velocity, _velocity, FALSE);
163 _nade.solid = SOLID_BBOX;
164 _nade.touch = nade_touch;
165 _nade.health = autocvar_g_nades_nade_health;
166 _nade.takedamage = DAMAGE_YES;
167 _nade.event_damage = nade_damage;
168 _nade.teleportable = TRUE;
174 _nade.think = nade_boom;
175 _nade.nextthink = _time;
178 e.nade_refire = time + autocvar_g_nades_nade_refire;
187 setmodel(self.nade, "models/weapons/h_ok_grenade.iqm");
188 setattachment(self.nade, self.weaponentity, "");
189 self.nade.classname = "nade";
190 self.nade.realowner = self;
191 self.nade.colormap = self.colormap;
192 self.nade.glowmod = self.glowmod;
193 self.nade.wait = time + autocvar_g_nades_nade_lifetime;
194 self.nade.cnt = time;
195 self.nade.think = nade_beep;
196 self.nade.nextthink = max(self.nade.wait - 3, time);
197 self.nade.projectiledeathtype = DEATH_NADE;
208 if not(autocvar_g_nades)
209 return FALSE; // allow turning them off mid match
211 if(forbidWeaponUse())
214 if not(IS_PLAYER(self))
220 MUTATOR_HOOKFUNCTION(nades_ForbidThrowing)
222 if(!g_weaponarena || !g_minstagib)
223 return FALSE; // TODO: fix this to support all modes that don't disable weapon dropping
230 if(self.nade_refire < time)
232 Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_NADE_THROW);
234 self.nade_refire = time + autocvar_g_nades_nade_refire;
239 if(time - self.nade.cnt >= 1)
241 makevectors(self.v_angle);
242 float _force = time - self.nade.cnt;
243 _force /= autocvar_g_nades_nade_lifetime;
244 _force = autocvar_g_nades_nade_minforce + (_force * (autocvar_g_nades_nade_maxforce - autocvar_g_nades_nade_minforce));
245 toss_nade(self, (v_forward * 0.75 + v_up * 0.2 + v_right * 0.05) * _force, 0);
252 MUTATOR_HOOKFUNCTION(nades_VehicleEnter)
255 toss_nade(other, '0 0 100', max(other.nade.wait, time + 0.05));
260 MUTATOR_HOOKFUNCTION(nades_PlayerPreThink)
262 float key_pressed = ((g_grappling_hook) ? self.button16 : self.BUTTON_HOOK);
265 if(self.nade.wait - 0.1 <= time)
266 toss_nade(self, '0 0 0', time + 0.05);
269 if(self.nade_refire < time)
276 else if(time - self.nade.cnt >= 1)
280 makevectors(self.v_angle);
281 float _force = time - self.nade.cnt;
282 _force /= autocvar_g_nades_nade_lifetime;
283 _force = autocvar_g_nades_nade_minforce + (_force * (autocvar_g_nades_nade_maxforce - autocvar_g_nades_nade_minforce));
284 toss_nade(self, (v_forward * 0.7 + v_up * 0.2 + v_right * 0.1) * _force, 0);
292 MUTATOR_HOOKFUNCTION(nades_PlayerSpawn)
294 if(autocvar_g_nades_spawn)
295 self.nade_refire = time + autocvar_g_spawnshieldtime;
297 self.nade_refire = time + autocvar_g_nades_nade_refire;
302 MUTATOR_HOOKFUNCTION(nades_PlayerDies)
305 toss_nade(self, '0 0 100', max(self.nade.wait, time + 0.05));
310 MUTATOR_HOOKFUNCTION(nades_BuildMutatorsString)
312 ret_string = strcat(ret_string, ":Nades");
316 MUTATOR_HOOKFUNCTION(nades_BuildMutatorsPrettyString)
318 ret_string = strcat(ret_string, ", Nades");
322 MUTATOR_DEFINITION(mutator_nades)
324 MUTATOR_HOOK(ForbidThrowCurrentWeapon, nades_ForbidThrowing, CBC_ORDER_ANY);
325 MUTATOR_HOOK(VehicleEnter, nades_VehicleEnter, CBC_ORDER_ANY);
326 MUTATOR_HOOK(PlayerPreThink, nades_PlayerPreThink, CBC_ORDER_ANY);
327 MUTATOR_HOOK(PlayerSpawn, nades_PlayerSpawn, CBC_ORDER_ANY);
328 MUTATOR_HOOK(PlayerDies, nades_PlayerDies, CBC_ORDER_ANY);
329 MUTATOR_HOOK(BuildMutatorsString, nades_BuildMutatorsString, CBC_ORDER_ANY);
330 MUTATOR_HOOK(BuildMutatorsPrettyString, nades_BuildMutatorsPrettyString, CBC_ORDER_ANY);
334 precache_model("models/ok_nade_counter/ok_nade_counter.md3");
336 precache_model("models/weapons/h_ok_grenade.iqm");
337 precache_model("models/weapons/v_ok_grenade.md3");
338 precache_sound("weapons/rocket_impact.wav");
339 precache_sound("weapons/grenade_bounce1.wav");
340 precache_sound("weapons/grenade_bounce2.wav");
341 precache_sound("weapons/grenade_bounce3.wav");
342 precache_sound("weapons/grenade_bounce4.wav");
343 precache_sound("weapons/grenade_bounce5.wav");
344 precache_sound("weapons/grenade_bounce6.wav");
345 precache_sound("overkill/grenadebip.ogg");