]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/w_grenadelauncher.qc
move airshot and electrobitch to a place where they should actually work
[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         if(other.takedamage == DAMAGE_AIM)
9                 if(other.classname == "player")
10                         if(IsDifferentTeam(self.owner, other))
11                                 if(IsFlying(other))
12                                         announce(self.owner, "announcer/male/airshot.ogg");
13
14         self.event_damage = SUB_Null;
15         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);
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                 W_PrepareExplosionByDamage(attacker, self.think);
86         }
87 }
88
89 void W_Grenade_Attack (void)
90 {
91         local entity gren;
92
93         if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
94                 self.ammo_rockets = self.ammo_rockets - cvar("g_balance_grenadelauncher_primary_ammo");
95         W_SetupShot (self, '25 6 -8', FALSE, 4, "weapons/grenade_fire.wav");
96         //W_SetupShot (self, '25 8 -8', FALSE, 4, "weapons/grenade_fire.wav"); // TODO: move model to the right a little
97
98         pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
99
100         gren = spawn ();
101         gren.owner = self;
102         gren.classname = "grenade";
103         gren.bot_dodge = TRUE;
104         gren.bot_dodgerating = cvar("g_balance_grenadelauncher_primary_damage");
105         gren.movetype = MOVETYPE_BOUNCE;
106         gren.solid = SOLID_BBOX;
107         gren.effects = EF_LOWPRECISION;
108         gren.modelflags = MF_TRACER2;
109         gren.projectiledeathtype = WEP_GRENADE_LAUNCHER;
110         setmodel(gren, "models/grenademodel.md3"); // precision set above
111         setsize(gren, '0 0 0', '0 0 0');
112         setorigin(gren, w_shotorg);
113
114         gren.nextthink = time + cvar("g_balance_grenadelauncher_primary_lifetime");
115         gren.think = adaptor_think2use;
116         gren.use = W_Grenade_Explode;
117         gren.touch = W_Grenade_Touch1;
118         gren.velocity = w_shotdir * cvar("g_balance_grenadelauncher_primary_speed") + v_up * cvar("g_balance_grenadelauncher_primary_speed_up");
119         W_SetupProjectileVelocity(gren);
120         gren.avelocity_x = random () * -500 - 500;
121
122         gren.angles = vectoangles (gren.velocity);
123         gren.flags = FL_PROJECTILE;
124 }
125
126 void W_Grenade_Attack2 (void)
127 {
128         local entity gren;
129
130         if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
131                 self.ammo_rockets = self.ammo_rockets - cvar("g_balance_grenadelauncher_secondary_ammo");
132         W_SetupShot (self, '25 6 -8', FALSE, 4, "weapons/grenade_fire.wav");
133         //W_SetupShot (self, '25 8 -8', FALSE, 4, "weapons/grenade_fire.wav"); // TODO: move model to the right a little
134
135         pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
136
137         gren = spawn ();
138         gren.owner = self;
139         gren.classname = "grenade";
140         gren.bot_dodge = TRUE;
141         gren.bot_dodgerating = cvar("g_balance_grenadelauncher_secondary_damage");
142         gren.movetype = MOVETYPE_BOUNCE;
143         gren.solid = SOLID_BBOX;
144         gren.effects = EF_LOWPRECISION;
145         gren.modelflags = MF_TRACER2;
146         gren.projectiledeathtype = WEP_GRENADE_LAUNCHER | HITTYPE_SECONDARY;
147         setmodel(gren, "models/grenademodel.md3"); // precision set above
148         setsize(gren, '0 0 -3', '0 0 -3');
149         setorigin(gren, w_shotorg);
150
151         gren.nextthink = time + cvar("g_balance_grenadelauncher_secondary_lifetime");
152         gren.think = adaptor_think2use;
153         gren.use = W_Grenade_Explode2;
154         gren.touch = W_Grenade_Touch2;
155         gren.takedamage = DAMAGE_YES;
156         gren.health = cvar("g_balance_grenadelauncher_secondary_health");
157         gren.damageforcescale = 4;
158         gren.event_damage = W_Grenade_Damage;
159         gren.velocity = w_shotdir * cvar("g_balance_grenadelauncher_secondary_speed") + v_up * cvar("g_balance_grenadelauncher_secondary_speed_up");
160         W_SetupProjectileVelocity(gren);
161         gren.avelocity = '100 150 100';
162
163         gren.angles = vectoangles (gren.velocity);
164         gren.flags = FL_PROJECTILE;
165 }
166
167 void spawnfunc_weapon_grenadelauncher (void)
168 {
169         weapon_defaultspawnfunc(WEP_GRENADE_LAUNCHER);
170 }
171
172 .float bot_secondary_grenademooth;
173 float w_glauncher(float req)
174 {
175         if (req == WR_AIM)
176         {
177                 self.BUTTON_ATCK = FALSE;
178                 self.BUTTON_ATCK2 = FALSE;
179                 if (self.bot_secondary_grenademooth == 0)
180                 {
181                         if(bot_aim(cvar("g_balance_grenadelauncher_primary_speed"), cvar("g_balance_grenadelauncher_primary_speed_up"), cvar("g_balance_grenadelauncher_primary_lifetime"), TRUE))
182                         {
183                                 self.BUTTON_ATCK = TRUE;
184                                 if(random() < 0.01) self.bot_secondary_grenademooth = 1;
185                         }
186                 }
187                 else
188                 {
189                         if(bot_aim(cvar("g_balance_grenadelauncher_secondary_speed"), cvar("g_balance_grenadelauncher_secondary_speed_up"), cvar("g_balance_grenadelauncher_secondary_lifetime"), TRUE))
190                         {
191                                 self.BUTTON_ATCK2 = TRUE;
192                                 if(random() < 0.02) self.bot_secondary_grenademooth = 0;
193                         }
194                 }
195         }
196         else if (req == WR_THINK)
197         {
198                 if (self.BUTTON_ATCK)
199                 if (weapon_prepareattack(0, cvar("g_balance_grenadelauncher_primary_refire")))
200                 {
201                         W_Grenade_Attack();
202                         weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_grenadelauncher_primary_animtime"), w_ready);
203                 }
204                 if (self.BUTTON_ATCK2)
205                 if (weapon_prepareattack(1, cvar("g_balance_grenadelauncher_secondary_refire")))
206                 {
207                         W_Grenade_Attack2();
208                         weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_grenadelauncher_secondary_animtime"), w_ready);
209                 }
210         }
211         else if (req == WR_PRECACHE)
212         {
213                 precache_model ("models/grenademodel.md3");
214                 precache_model ("models/weapons/g_gl.md3");
215                 precache_model ("models/weapons/v_gl.md3");
216                 precache_model ("models/weapons/w_gl.zym");
217                 precache_sound ("weapons/grenade_bounce1.wav");
218                 precache_sound ("weapons/grenade_bounce2.wav");
219                 precache_sound ("weapons/grenade_bounce3.wav");
220                 precache_sound ("weapons/grenade_bounce4.wav");
221                 precache_sound ("weapons/grenade_bounce5.wav");
222                 precache_sound ("weapons/grenade_bounce6.wav");
223                 precache_sound ("weapons/grenade_fire.wav");
224                 precache_sound ("weapons/grenade_impact.wav");
225         }
226         else if (req == WR_SETUP)
227                 weapon_setup(WEP_GRENADE_LAUNCHER);
228         else if (req == WR_CHECKAMMO1)
229                 return self.ammo_rockets >= cvar("g_balance_grenadelauncher_primary_ammo");
230         else if (req == WR_CHECKAMMO2)
231                 return self.ammo_rockets >= cvar("g_balance_grenadelauncher_secondary_ammo");
232         else if (req == WR_SUICIDEMESSAGE)
233         {
234                 if(w_deathtype & HITTYPE_SECONDARY)
235                         w_deathtypestring = "tried out his own grenade";
236                 else
237                         w_deathtypestring = "detonated";
238         }
239         else if (req == WR_KILLMESSAGE)
240         {
241                 if(w_deathtype & HITTYPE_SPLASH)
242                         if(w_deathtype & HITTYPE_BOUNCE) // (must be secondary then)
243                                 w_deathtypestring = "didn't see #'s grenade";
244                         else // unchecked: SECONDARY
245                                 w_deathtypestring = "almost dodged #'s grenade";
246                 else // unchecked: SECONDARY, BOUNCE
247                         w_deathtypestring = "ate #'s grenade";
248         }
249         return TRUE;
250 };