]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/w_grenadelauncher.qc
use "airshot" for in-air mortar hit
[divverent/nexuiz.git] / data / qcsrc / server / w_grenadelauncher.qc
1 void W_Grenade_Explode (void)
2 {
3         vector  org2;
4         org2 = findbetterlocation (self.origin, 12);
5         pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1);
6         sound (self, CHAN_PROJECTILE, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM);
7
8         self.event_damage = SUB_Null;
9         RadiusDamage (self, self.owner, cvar("g_balance_grenadelauncher_primary_damage"), cvar("g_balance_grenadelauncher_primary_edgedamage"), cvar("g_balance_grenadelauncher_primary_radius"), world, cvar("g_balance_grenadelauncher_primary_force"), self.projectiledeathtype, other);
10
11         if(other.takedamage == DAMAGE_AIM)
12                 if(other.classname == "player")
13                         if(IsDifferentTeam(self.owner, other))
14                                 if(IsFlying(other))
15                                         announce(self.owner, "announcer/male/airshot.ogg");
16
17         remove (self);
18 }
19
20 void W_Grenade_Explode2 (void)
21 {
22         vector  org2;
23         org2 = findbetterlocation (self.origin, 12);
24         pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1);
25         sound (self, CHAN_PROJECTILE, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM);
26
27         self.event_damage = SUB_Null;
28         RadiusDamage (self, self.owner, cvar("g_balance_grenadelauncher_secondary_damage"), cvar("g_balance_grenadelauncher_secondary_edgedamage"), cvar("g_balance_grenadelauncher_secondary_radius"), world, cvar("g_balance_grenadelauncher_secondary_force"), self.projectiledeathtype, other);
29
30         if(other.takedamage == DAMAGE_AIM)
31                 if(other.classname == "player")
32                         if(IsDifferentTeam(self.owner, other))
33                                 if(IsFlying(other))
34                                         announce(self.owner, "announcer/male/airshot.ogg");
35
36         remove (self);
37 }
38
39 void W_Grenade_Touch1 (void)
40 {
41         if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
42         {
43                 remove(self);
44                 return;
45         }
46         W_Grenade_Explode ();
47 }
48
49 void W_Grenade_Touch2 (void)
50 {
51         if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
52         {
53                 remove(self);
54                 return;
55         }
56         if (other.takedamage == DAMAGE_AIM)
57         {
58                 self.use ();
59         }
60         else
61         {
62                 float r;
63                 r = random() * 6;
64                 if(r < 1)
65                         sound (self, CHAN_PROJECTILE, "weapons/grenade_bounce1.wav", VOL_BASE, ATTN_NORM);
66                 else if(r < 2)
67                         sound (self, CHAN_PROJECTILE, "weapons/grenade_bounce2.wav", VOL_BASE, ATTN_NORM);
68                 else if(r < 3)
69                         sound (self, CHAN_PROJECTILE, "weapons/grenade_bounce3.wav", VOL_BASE, ATTN_NORM);
70                 else if(r < 4)
71                         sound (self, CHAN_PROJECTILE, "weapons/grenade_bounce4.wav", VOL_BASE, ATTN_NORM);
72                 else if(r < 5)
73                         sound (self, CHAN_PROJECTILE, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM);
74                 else
75                         sound (self, CHAN_PROJECTILE, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM);
76                 self.projectiledeathtype |= HITTYPE_BOUNCE;
77         }
78 }
79
80 void W_Grenade_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
81 {
82         self.health = self.health - damage;
83         if (self.health <= 0)
84         {
85                 self.owner = attacker;
86                 self.think ();
87         }
88 }
89
90 void W_Grenade_Attack (void)
91 {
92         local entity gren;
93
94         if not(self.items & IT_UNLIMITED_AMMO)
95                 self.ammo_rockets = self.ammo_rockets - cvar("g_balance_grenadelauncher_primary_ammo");
96         W_SetupShot (self, '25 6 -8', FALSE, 4, "weapons/grenade_fire.wav");
97         //W_SetupShot (self, '25 8 -8', FALSE, 4, "weapons/grenade_fire.wav"); // TODO: move model to the right a little
98
99         pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
100
101         gren = spawn ();
102         gren.owner = self;
103         gren.classname = "grenade";
104         gren.bot_dodge = TRUE;
105         gren.bot_dodgerating = cvar("g_balance_grenadelauncher_primary_damage");
106         gren.movetype = MOVETYPE_BOUNCE;
107         gren.solid = SOLID_BBOX;
108         gren.effects = EF_LOWPRECISION;
109         gren.modelflags = MF_TRACER2;
110         gren.projectiledeathtype = WEP_GRENADE_LAUNCHER;
111         setmodel(gren, "models/grenademodel.md3"); // precision set above
112         setsize(gren, '0 0 0', '0 0 0');
113         setorigin(gren, w_shotorg);
114
115         gren.nextthink = time + cvar("g_balance_grenadelauncher_primary_lifetime");
116         gren.think = adaptor_think2use;
117         gren.use = W_Grenade_Explode;
118         gren.touch = W_Grenade_Touch1;
119         gren.velocity = w_shotdir * cvar("g_balance_grenadelauncher_primary_speed") + v_up * cvar("g_balance_grenadelauncher_primary_speed_up");
120         W_SetupProjectileVelocity(gren);
121         gren.avelocity_x = random () * -500 - 500;
122
123         gren.angles = vectoangles (gren.velocity);
124         gren.flags = FL_PROJECTILE;
125 }
126
127 void W_Grenade_Attack2 (void)
128 {
129         local entity gren;
130
131         if not(self.items & IT_UNLIMITED_AMMO)
132                 self.ammo_rockets = self.ammo_rockets - cvar("g_balance_grenadelauncher_secondary_ammo");
133         W_SetupShot (self, '25 6 -8', FALSE, 4, "weapons/grenade_fire.wav");
134         //W_SetupShot (self, '25 8 -8', FALSE, 4, "weapons/grenade_fire.wav"); // TODO: move model to the right a little
135
136         pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
137
138         gren = spawn ();
139         gren.owner = self;
140         gren.classname = "grenade";
141         gren.bot_dodge = TRUE;
142         gren.bot_dodgerating = cvar("g_balance_grenadelauncher_secondary_damage");
143         gren.movetype = MOVETYPE_BOUNCE;
144         gren.solid = SOLID_BBOX;
145         gren.effects = EF_LOWPRECISION;
146         gren.modelflags = MF_TRACER2;
147         gren.projectiledeathtype = WEP_GRENADE_LAUNCHER | HITTYPE_SECONDARY;
148         setmodel(gren, "models/grenademodel.md3"); // precision set above
149         setsize(gren, '0 0 -3', '0 0 -3');
150         setorigin(gren, w_shotorg);
151
152         gren.nextthink = time + cvar("g_balance_grenadelauncher_secondary_lifetime");
153         gren.think = adaptor_think2use;
154         gren.use = W_Grenade_Explode2;
155         gren.touch = W_Grenade_Touch2;
156         gren.takedamage = DAMAGE_YES;
157         gren.health = cvar("g_balance_grenadelauncher_secondary_health");
158         gren.damageforcescale = 4;
159         gren.event_damage = W_Grenade_Damage;
160         gren.velocity = w_shotdir * cvar("g_balance_grenadelauncher_secondary_speed") + v_up * cvar("g_balance_grenadelauncher_secondary_speed_up");
161         W_SetupProjectileVelocity(gren);
162         gren.avelocity = '100 150 100';
163
164         gren.angles = vectoangles (gren.velocity);
165         gren.flags = FL_PROJECTILE;
166 }
167
168 void spawnfunc_weapon_grenadelauncher (void)
169 {
170         weapon_defaultspawnfunc(WEP_GRENADE_LAUNCHER);
171 }
172
173 .float bot_secondary_grenademooth;
174 float w_glauncher(float req)
175 {
176         if (req == WR_AIM)
177         {
178                 self.BUTTON_ATCK = FALSE;
179                 self.BUTTON_ATCK2 = FALSE;
180                 if (self.bot_secondary_grenademooth == 0)
181                 {
182                         if(bot_aim(cvar("g_balance_grenadelauncher_primary_speed"), cvar("g_balance_grenadelauncher_primary_speed_up"), cvar("g_balance_grenadelauncher_primary_lifetime"), TRUE))
183                         {
184                                 self.BUTTON_ATCK = TRUE;
185                                 if(random() < 0.01) self.bot_secondary_grenademooth = 1;
186                         }
187                 }
188                 else
189                 {
190                         if(bot_aim(cvar("g_balance_grenadelauncher_secondary_speed"), cvar("g_balance_grenadelauncher_secondary_speed_up"), cvar("g_balance_grenadelauncher_secondary_lifetime"), TRUE))
191                         {
192                                 self.BUTTON_ATCK2 = TRUE;
193                                 if(random() < 0.02) self.bot_secondary_grenademooth = 0;
194                         }
195                 }
196         }
197         else if (req == WR_THINK)
198         {
199                 if (self.BUTTON_ATCK)
200                 if (weapon_prepareattack(0, cvar("g_balance_grenadelauncher_primary_refire")))
201                 {
202                         W_Grenade_Attack();
203                         weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_grenadelauncher_primary_animtime"), w_ready);
204                 }
205                 if (self.BUTTON_ATCK2)
206                 if (weapon_prepareattack(1, cvar("g_balance_grenadelauncher_secondary_refire")))
207                 {
208                         W_Grenade_Attack2();
209                         weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_grenadelauncher_secondary_animtime"), w_ready);
210                 }
211         }
212         else if (req == WR_PRECACHE)
213         {
214                 precache_model ("models/grenademodel.md3");
215                 precache_model ("models/weapons/g_gl.md3");
216                 precache_model ("models/weapons/v_gl.md3");
217                 precache_model ("models/weapons/w_gl.zym");
218                 precache_sound ("weapons/grenade_bounce1.wav");
219                 precache_sound ("weapons/grenade_bounce2.wav");
220                 precache_sound ("weapons/grenade_bounce3.wav");
221                 precache_sound ("weapons/grenade_bounce4.wav");
222                 precache_sound ("weapons/grenade_bounce5.wav");
223                 precache_sound ("weapons/grenade_bounce6.wav");
224                 precache_sound ("weapons/grenade_fire.wav");
225                 precache_sound ("weapons/grenade_impact.wav");
226         }
227         else if (req == WR_SETUP)
228                 weapon_setup(WEP_GRENADE_LAUNCHER);
229         else if (req == WR_CHECKAMMO1)
230                 return self.ammo_rockets >= cvar("g_balance_grenadelauncher_primary_ammo");
231         else if (req == WR_CHECKAMMO2)
232                 return self.ammo_rockets >= cvar("g_balance_grenadelauncher_secondary_ammo");
233         else if (req == WR_SUICIDEMESSAGE)
234         {
235                 if(w_deathtype & HITTYPE_SECONDARY)
236                         w_deathtypestring = "tried out his own grenade";
237                 else
238                         w_deathtypestring = "detonated";
239         }
240         else if (req == WR_KILLMESSAGE)
241         {
242                 if(w_deathtype & HITTYPE_SPLASH)
243                         if(w_deathtype & HITTYPE_BOUNCE) // (must be secondary then)
244                                 w_deathtypestring = "didn't see #'s grenade";
245                         else // unchecked: SECONDARY
246                                 w_deathtypestring = "almost dodged #'s grenade";
247                 else // unchecked: SECONDARY, BOUNCE
248                         w_deathtypestring = "ate #'s grenade";
249         }
250         return TRUE;
251 };