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