Makefile: use `-I.`
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / vehicles / vehicle / raptor_weapons.qc
1 #ifndef VEHICLE_RAPTOR_WEAPONS_H
2 #define VEHICLE_RAPTOR_WEAPONS_H
3
4 #include <common/weapons/all.qh>
5
6 CLASS(RaptorCannon, PortoLaunch)
7 /* flags     */ ATTRIB(RaptorCannon, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
8 /* impulse   */ ATTRIB(RaptorCannon, impulse, int, 3);
9 /* refname   */ ATTRIB(RaptorCannon, netname, string, "raptorcannon");
10 /* wepname   */ ATTRIB(RaptorCannon, m_name, string, _("Raptor cannon"));
11 ENDCLASS(RaptorCannon)
12 REGISTER_WEAPON(RAPTOR, NEW(RaptorCannon));
13
14 CLASS(RaptorBomb, PortoLaunch)
15 /* flags     */ ATTRIB(RaptorBomb, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
16 /* impulse   */ ATTRIB(RaptorBomb, impulse, int, 3);
17 /* refname   */ ATTRIB(RaptorBomb, netname, string, "raptorbomb");
18 /* wepname   */ ATTRIB(RaptorBomb, m_name, string, _("Raptor bomb"));
19 ENDCLASS(RaptorBomb)
20 REGISTER_WEAPON(RAPTOR_BOMB, NEW(RaptorBomb));
21
22 CLASS(RaptorFlare, PortoLaunch)
23 /* flags     */ ATTRIB(RaptorFlare, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
24 /* impulse   */ ATTRIB(RaptorFlare, impulse, int, 3);
25 /* refname   */ ATTRIB(RaptorFlare, netname, string, "raptorflare");
26 /* wepname   */ ATTRIB(RaptorFlare, m_name, string, _("Raptor flare"));
27 ENDCLASS(RaptorFlare)
28 REGISTER_WEAPON(RAPTOR_FLARE, NEW(RaptorFlare));
29
30 #endif
31
32 #ifdef IMPLEMENTATION
33
34 #ifdef SVQC
35
36 float autocvar_g_vehicle_raptor_cannon_cost;
37 float autocvar_g_vehicle_raptor_cannon_damage;
38 float autocvar_g_vehicle_raptor_cannon_radius;
39 float autocvar_g_vehicle_raptor_cannon_refire;
40 float autocvar_g_vehicle_raptor_cannon_speed;
41 float autocvar_g_vehicle_raptor_cannon_spread;
42 float autocvar_g_vehicle_raptor_cannon_force;
43
44 float autocvar_g_vehicle_raptor_bomblets;
45 float autocvar_g_vehicle_raptor_bomblet_alt;
46 float autocvar_g_vehicle_raptor_bomblet_time;
47 float autocvar_g_vehicle_raptor_bomblet_damage;
48 float autocvar_g_vehicle_raptor_bomblet_spread;
49 float autocvar_g_vehicle_raptor_bomblet_edgedamage;
50 float autocvar_g_vehicle_raptor_bomblet_radius;
51 float autocvar_g_vehicle_raptor_bomblet_force;
52 float autocvar_g_vehicle_raptor_bomblet_explode_delay;
53
54 METHOD(RaptorCannon, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire)) {
55     bool isPlayer = IS_PLAYER(actor);
56     entity player = isPlayer ? actor : actor.owner;
57     entity veh = player.vehicle;
58     // 1 [wait] 1 [wait] 2 [wait] 2 [wait] [wait]
59     float t = autocvar_g_vehicle_raptor_cannon_refire * (1 + veh.misc_bulletcounter == 4);
60     if (fire & 1)
61     if (weapon_prepareattack(thiswep, player, weaponentity, false, t)) {
62         if (isPlayer) W_SetupShot_Dir(player, v_forward, false, 0, SND(Null), CH_WEAPON_B, 0);
63         vector org = w_shotorg;
64         vector dir = w_shotdir;
65         if (veh) {
66             veh.misc_bulletcounter += 1;
67             org = (veh.misc_bulletcounter <= 2) ? gettaginfo(veh.gun1, gettagindex(veh.gun1, "fire1"))
68               : (((veh.misc_bulletcounter == 4) ? veh.misc_bulletcounter = 0 : 0), gettaginfo(veh.gun2, gettagindex(veh.gun2, "fire1")));
69             dir = v_forward;
70             veh.vehicle_energy -= autocvar_g_vehicle_raptor_cannon_cost;
71             actor.cnt = time;
72         }
73         vehicles_projectile(EFFECT_RAPTOR_MUZZLEFLASH.eent_eff_name, SND(LASERGUN_FIRE),
74                                org, normalize(dir + randomvec() * autocvar_g_vehicle_raptor_cannon_spread) * autocvar_g_vehicle_raptor_cannon_speed,
75                                autocvar_g_vehicle_raptor_cannon_damage, autocvar_g_vehicle_raptor_cannon_radius, autocvar_g_vehicle_raptor_cannon_force,  0,
76                                DEATH_VH_RAPT_CANNON.m_id, PROJECTILE_RAPTORCANNON, 0, true, true, player);
77         weapon_thinkf(player, weaponentity, WFRAME_FIRE1, 0, w_ready);
78     }
79 }
80 METHOD(RaptorCannon, wr_checkammo1, bool(RacerAttack thiswep)) {
81     SELFPARAM();
82     bool isPlayer = IS_PLAYER(self);
83     entity player = isPlayer ? self : self.owner;
84     entity veh = player.vehicle;
85     return isPlayer || veh.vehicle_energy >= autocvar_g_vehicle_raptor_cannon_cost;
86 }
87
88 float autocvar_g_vehicle_raptor_bombs_refire;
89
90 void raptor_bombdrop();
91 METHOD(RaptorBomb, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire)) {
92     bool isPlayer = IS_PLAYER(actor);
93     entity player = isPlayer ? actor : actor.owner;
94     entity veh = player.vehicle;
95     if (fire & 2)
96     if (!isPlayer || weapon_prepareattack(thiswep, player, weaponentity, true, autocvar_g_vehicle_raptor_bombs_refire)) {
97         if (veh) setself(veh);
98         raptor_bombdrop();
99         weapon_thinkf(player, weaponentity, WFRAME_FIRE2, 0, w_ready);
100     }
101 }
102
103 float autocvar_g_vehicle_raptor_flare_refire;
104 float autocvar_g_vehicle_raptor_flare_lifetime;
105 float autocvar_g_vehicle_raptor_flare_chase;
106 float autocvar_g_vehicle_raptor_flare_range;
107
108 void raptor_flare_think();
109 void raptor_flare_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force);
110 void raptor_flare_touch();
111
112 METHOD(RaptorFlare, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire)) {
113     bool isPlayer = IS_PLAYER(actor);
114     entity player = isPlayer ? actor : actor.owner;
115     entity veh = player.vehicle;
116     if (fire & 2)
117     if (!isPlayer || weapon_prepareattack(thiswep, player, weaponentity, true, autocvar_g_vehicle_raptor_flare_refire)) {
118         for(int i = 0; i < 3; ++i) {
119             entity _flare = spawn();
120             setmodel(_flare, MDL_VEH_RAPTOR_FLARE);
121             _flare.effects = EF_LOWPRECISION | EF_FLAME;
122             _flare.scale = 0.5;
123             setorigin(_flare, actor.origin - '0 0 16');
124             _flare.movetype = MOVETYPE_TOSS;
125             _flare.gravity = 0.15;
126             _flare.velocity = 0.25 * actor.velocity + (v_forward + randomvec() * 0.25)* -500;
127             _flare.think = raptor_flare_think;
128             _flare.nextthink = time;
129             _flare.owner = veh ? veh : player;
130             _flare.solid = SOLID_CORPSE;
131             _flare.takedamage = DAMAGE_YES;
132             _flare.event_damage = raptor_flare_damage;
133             _flare.health = 20;
134             _flare.tur_impacttime = time + autocvar_g_vehicle_raptor_flare_lifetime;
135             _flare.touch = raptor_flare_touch;
136         }
137         weapon_thinkf(player, weaponentity, WFRAME_FIRE2, 0, w_ready);
138     }
139 }
140
141
142 void raptor_bomblet_boom()
143 {SELFPARAM();
144     RadiusDamage (self, self.realowner, autocvar_g_vehicle_raptor_bomblet_damage,
145                                     autocvar_g_vehicle_raptor_bomblet_edgedamage,
146                                     autocvar_g_vehicle_raptor_bomblet_radius, world, world,
147                                     autocvar_g_vehicle_raptor_bomblet_force, DEATH_VH_RAPT_BOMB.m_id, world);
148     remove(self);
149 }
150
151 void raptor_bomblet_touch()
152 {SELFPARAM();
153     if(other == self.owner)
154         return;
155
156     PROJECTILE_TOUCH;
157     self.think = raptor_bomblet_boom;
158     self.nextthink = time + random() * autocvar_g_vehicle_raptor_bomblet_explode_delay;
159 }
160
161 void raptor_bomb_burst()
162 {SELFPARAM();
163     if(self.cnt > time)
164     if(autocvar_g_vehicle_raptor_bomblet_alt)
165     {
166         self.nextthink = time;
167         traceline(self.origin, self.origin + (normalize(self.velocity) * autocvar_g_vehicle_raptor_bomblet_alt), MOVE_NORMAL, self);
168         if((trace_fraction == 1.0) || (vlen(self.origin - self.owner.origin) < autocvar_g_vehicle_raptor_bomblet_radius))
169         {
170             UpdateCSQCProjectile(self);
171             return;
172         }
173     }
174
175     entity bomblet;
176     float i;
177
178     Damage_DamageInfo(self.origin, 0, 0, 0, '0 0 0', DEATH_VH_RAPT_FRAGMENT.m_id, 0, self);
179
180     for(i = 0; i < autocvar_g_vehicle_raptor_bomblets; ++i)
181     {
182         bomblet = spawn();
183         setorigin(bomblet, self.origin);
184
185         bomblet.movetype        = MOVETYPE_TOSS;
186         bomblet.touch      = raptor_bomblet_touch;
187         bomblet.think      = raptor_bomblet_boom;
188         bomblet.nextthink   = time + 5;
189         bomblet.owner      = self.owner;
190         bomblet.realowner   = self.realowner;
191         bomblet.velocity        = normalize(normalize(self.velocity) + (randomvec() * autocvar_g_vehicle_raptor_bomblet_spread)) * vlen(self.velocity);
192
193         PROJECTILE_MAKETRIGGER(bomblet);
194         CSQCProjectile(bomblet, true, PROJECTILE_RAPTORBOMBLET, true);
195     }
196
197     remove(self);
198 }
199
200 void raptor_bombdrop()
201 {SELFPARAM();
202     entity bomb_1, bomb_2;
203
204     bomb_1 = spawn();
205     bomb_2 = spawn();
206
207     vector org = gettaginfo(self, gettagindex(self, "bombmount_left"));
208     setorigin(bomb_1, org);
209     org = gettaginfo(self, gettagindex(self, "bombmount_right"));
210     setorigin(bomb_2, org);
211
212     bomb_1.movetype      = bomb_2.movetype   = MOVETYPE_BOUNCE;
213     bomb_1.velocity      = bomb_2.velocity   = self.velocity;
214     bomb_1.touch                = bomb_2.touch    = raptor_bomb_burst;
215     bomb_1.think                = bomb_2.think    = raptor_bomb_burst;
216     bomb_1.cnt            = bomb_2.cnt          = time + 10;
217
218     if(autocvar_g_vehicle_raptor_bomblet_alt)
219         bomb_1.nextthink = bomb_2.nextthink  = time;
220     else
221         bomb_1.nextthink = bomb_2.nextthink  = time + autocvar_g_vehicle_raptor_bomblet_time;
222
223     bomb_1.owner         = bomb_2.owner   = self;
224     bomb_1.realowner = bomb_2.realowner  = self.owner;
225     bomb_1.solid         = bomb_2.solid   = SOLID_BBOX;
226     bomb_1.gravity   = bomb_2.gravity   = 1;
227
228     PROJECTILE_MAKETRIGGER(bomb_1);
229     PROJECTILE_MAKETRIGGER(bomb_2);
230
231     CSQCProjectile(bomb_1, true, PROJECTILE_RAPTORBOMB, true);
232     CSQCProjectile(bomb_2, true, PROJECTILE_RAPTORBOMB, true);
233 }
234
235 void raptor_flare_touch()
236 {SELFPARAM();
237     remove(self);
238 }
239
240 void raptor_flare_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
241 {SELFPARAM();
242     self.health -= damage;
243     if(self.health <= 0)
244         remove(self);
245 }
246
247 void raptor_flare_think()
248 {SELFPARAM();
249     self.nextthink = time + 0.1;
250     entity _missile = findchainentity(enemy, self.owner);
251     while(_missile)
252     {
253         if(_missile.flags & FL_PROJECTILE)
254         if(vlen(self.origin - _missile.origin) < autocvar_g_vehicle_raptor_flare_range)
255         if(random() > autocvar_g_vehicle_raptor_flare_chase)
256             _missile.enemy = self;
257         _missile = _missile.chain;
258     }
259
260     if(self.tur_impacttime < time)
261         remove(self);
262 }
263
264 #endif
265
266 #ifdef CSQC
267
268 void RaptorCBShellfragDraw(entity this)
269 {
270     if(wasfreed(self))
271         return;
272
273     Movetype_Physics_MatchTicrate(self, autocvar_cl_gibs_ticrate, autocvar_cl_gibs_sloppy);
274     self.move_avelocity += randomvec() * 15;
275     self.renderflags = 0;
276
277     if(self.cnt < time)
278         self.alpha = bound(0, self.nextthink - time, 1);
279
280     if(self.alpha < ALPHA_MIN_VISIBLE)
281         remove(self);
282 }
283
284 void RaptorCBShellfragToss(vector _org, vector _vel, vector _ang)
285 {SELFPARAM();
286     entity sfrag;
287
288     sfrag = spawn();
289     setmodel(sfrag, MDL_VEH_RAPTOR_CB_FRAGMENT);
290     setorigin(sfrag, _org);
291
292     sfrag.move_movetype = MOVETYPE_BOUNCE;
293     sfrag.gravity = 0.15;
294     sfrag.solid = SOLID_CORPSE;
295
296     sfrag.draw = RaptorCBShellfragDraw;
297
298     sfrag.move_origin = sfrag.origin = _org;
299     sfrag.move_velocity = _vel;
300     sfrag.move_avelocity = prandomvec() * vlen(sfrag.move_velocity);
301     sfrag.angles = self.move_angles = _ang;
302
303     sfrag.move_time = time;
304     sfrag.damageforcescale = 4;
305
306     sfrag.nextthink = time + 3;
307     sfrag.cnt = time + 2;
308     sfrag.alpha = 1;
309     sfrag.drawmask = MASK_NORMAL;
310 }
311
312 #endif
313
314 #endif