]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc
Merge branch 'master' into Mario/qcphysics
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / vehicles / vehicle / spiderbot_weapons.qc
1 #include "spiderbot_weapons.qh"
2
3 #ifdef SVQC
4
5 void spiderbot_rocket_artillery(entity this)
6 {
7     this.nextthink = time;
8     UpdateCSQCProjectile(this);
9 }
10
11 void spiderbot_rocket_unguided(entity this)
12 {
13     vector newdir, olddir;
14
15     this.nextthink  = time;
16
17     olddir = normalize(this.velocity);
18     newdir = normalize(this.pos1 - this.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
19     this.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
20
21     UpdateCSQCProjectile(this);
22
23     if (IS_DEAD(this.owner) || this.cnt < time || vdist(this.pos1 - this.origin, <, 16))
24         this.use(this, NULL, NULL);
25 }
26
27 void spiderbot_rocket_guided(entity this)
28 {
29     vector newdir, olddir;
30
31     this.nextthink  = time;
32
33     if(!this.realowner.vehicle)
34         setthink(this, spiderbot_rocket_unguided);
35
36     crosshair_trace(this.realowner);
37     olddir = normalize(this.velocity);
38     newdir = normalize(trace_endpos - this.origin) + randomvec() * autocvar_g_vehicle_spiderbot_rocket_noise;
39     this.velocity = normalize(olddir + newdir * autocvar_g_vehicle_spiderbot_rocket_turnrate) * autocvar_g_vehicle_spiderbot_rocket_speed;
40
41     UpdateCSQCProjectile(this);
42
43     if (IS_DEAD(this.owner) || this.cnt < time)
44         this.use(this, NULL, NULL);
45 }
46
47 void spiderbot_guide_release(entity this)
48 {
49     bool donetrace = false;
50     IL_EACH(g_projectiles, it.realowner == this.owner && getthink(it) == spiderbot_rocket_guided,
51     {
52         if(!donetrace) // something exists, let's trace!
53         {
54             donetrace = true;
55             crosshair_trace(this.owner);
56         }
57
58         it.pos1 = trace_endpos;
59         setthink(it, spiderbot_rocket_unguided);
60     });
61 }
62
63 float spiberbot_calcartillery_flighttime;
64 vector spiberbot_calcartillery(vector org, vector tgt, float ht)
65 {
66     float grav, sdist, zdist, vs, vz, jumpheight;
67     vector sdir;
68
69     grav  = autocvar_sv_gravity;
70     zdist = tgt_z - org_z;
71     sdist = vlen(tgt - org - zdist * '0 0 1');
72     sdir  = normalize(tgt - org - zdist * '0 0 1');
73
74     // how high do we need to go?
75     jumpheight = fabs(ht);
76     if(zdist > 0)
77         jumpheight = jumpheight + zdist;
78
79     // push so high...
80     vz = sqrt(2 * grav * jumpheight); // NOTE: sqrt(positive)!
81
82     // we start with downwards velocity only if it's a downjump and the jump apex should be outside the jump!
83     if(ht < 0)
84         if(zdist < 0)
85             vz = -vz;
86
87     vector solution;
88     solution = solve_quadratic(0.5 * grav, -vz, zdist); // equation "z(ti) = zdist"
89     // ALWAYS solvable because jumpheight >= zdist
90     if(!solution_z)
91         solution_y = solution_x; // just in case it is not solvable due to roundoff errors, assume two equal solutions at their center (this is mainly for the usual case with ht == 0)
92     if(zdist == 0)
93         solution_x = solution_y; // solution_x is 0 in this case, so don't use it, but rather use solution_y (which will be sqrt(0.5 * jumpheight / grav), actually)
94
95     if(zdist < 0)
96     {
97         // down-jump
98         if(ht < 0)
99         {
100             // almost straight line type
101             // jump apex is before the jump
102             // we must take the larger one
103             spiberbot_calcartillery_flighttime = solution_y;
104         }
105         else
106         {
107             // regular jump
108             // jump apex is during the jump
109             // we must take the larger one too
110             spiberbot_calcartillery_flighttime = solution_y;
111         }
112     }
113     else
114     {
115         // up-jump
116         if(ht < 0)
117         {
118             // almost straight line type
119             // jump apex is after the jump
120             // we must take the smaller one
121             spiberbot_calcartillery_flighttime = solution_x;
122         }
123         else
124         {
125             // regular jump
126             // jump apex is during the jump
127             // we must take the larger one
128             spiberbot_calcartillery_flighttime = solution_y;
129         }
130     }
131     vs = sdist / spiberbot_calcartillery_flighttime;
132
133     // finally calculate the velocity
134     return sdir * vs + '0 0 1' * vz;
135 }
136
137 void spiderbot_rocket_do(entity this)
138 {
139     vector v;
140     entity rocket = NULL;
141
142     if (this.wait != -10)
143     {
144         if (PHYS_INPUT_BUTTON_ATCK2(this.owner) && STAT(VEHICLESTAT_W2MODE, this) == SBRM_GUIDE)
145         {
146             if (this.wait == 1)
147             if (this.tur_head.frame == 9 || this.tur_head.frame == 1)
148             {
149                 if(this.gun2.cnt < time && this.tur_head.frame == 9)
150                     this.tur_head.frame = 1;
151
152                 return;
153             }
154             this.wait = 1;
155         }
156         else
157         {
158             if(this.wait)
159                 spiderbot_guide_release(this);
160
161             this.wait = 0;
162         }
163     }
164
165     if(this.gun2.cnt > time)
166         return;
167
168     if (this.tur_head.frame >= 9)
169     {
170         this.tur_head.frame = 1;
171         this.wait = 0;
172     }
173
174     if(this.wait != -10)
175     if(!PHYS_INPUT_BUTTON_ATCK2(this.owner))
176         return;
177
178     if(weaponLocked(this.owner) || weaponUseForbidden(this.owner))
179         return;
180
181     v = gettaginfo(this.tur_head,gettagindex(this.tur_head,"tag_fire"));
182
183     switch(STAT(VEHICLESTAT_W2MODE, this))
184     {
185         case SBRM_VOLLY:
186             rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH, SND_ROCKET_FIRE,
187                                    v, normalize(randomvec() * autocvar_g_vehicle_spiderbot_rocket_spread + v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
188                                    autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
189                                    DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, this.owner);
190             crosshair_trace(this.owner);
191             float _dist = (random() * autocvar_g_vehicle_spiderbot_rocket_radius) + vlen(v - trace_endpos);
192             _dist -= (random() * autocvar_g_vehicle_spiderbot_rocket_radius) ;
193             rocket.nextthink  = time + (_dist / autocvar_g_vehicle_spiderbot_rocket_speed);
194             setthink(rocket, vehicles_projectile_explode_think);
195
196             if(PHYS_INPUT_BUTTON_ATCK2(this.owner) && this.tur_head.frame == 1)
197                 this.wait = -10;
198             break;
199         case SBRM_GUIDE:
200             rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH, SND_ROCKET_FIRE,
201                                    v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
202                                    autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
203                                    DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, false, this.owner);
204             crosshair_trace(this.owner);
205             rocket.pos1    = trace_endpos;
206             rocket.nextthink  = time;
207             setthink(rocket, spiderbot_rocket_guided);
208
209
210         break;
211         case SBRM_ARTILLERY:
212             rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH, SND_ROCKET_FIRE,
213                                    v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
214                                    autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
215                                    DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, this.owner);
216
217             crosshair_trace(this.owner);
218
219             rocket.pos1    = trace_endpos + randomvec() * (0.75 * autocvar_g_vehicle_spiderbot_rocket_radius);
220             rocket.pos1_z          = trace_endpos_z;
221
222             traceline(v, v + '0 0 1' * max_shot_distance, MOVE_WORLDONLY, this);
223             float h1 = 0.75 * vlen(v - trace_endpos);
224
225             //v = trace_endpos;
226             traceline(v , rocket.pos1 + '0 0 1' * max_shot_distance, MOVE_WORLDONLY, this);
227             float h2 = 0.75 * vlen(rocket.pos1 - v);
228
229             rocket.velocity  = spiberbot_calcartillery(v, rocket.pos1, ((h1 < h2) ? h1 : h2));
230             set_movetype(rocket, MOVETYPE_TOSS);
231             rocket.gravity   = 1;
232             //setthink(rocket, spiderbot_rocket_artillery);
233         break;
234     }
235     rocket.classname  = "spiderbot_rocket";
236
237     rocket.cnt = time + autocvar_g_vehicle_spiderbot_rocket_lifetime;
238
239     this.tur_head.frame += 1;
240     if (this.tur_head.frame == 9)
241         this.attack_finished_single[0] = autocvar_g_vehicle_spiderbot_rocket_reload;
242     else
243         this.attack_finished_single[0] = ((STAT(VEHICLESTAT_W2MODE, this) ==  SBRM_VOLLY) ? autocvar_g_vehicle_spiderbot_rocket_refire2 : autocvar_g_vehicle_spiderbot_rocket_refire);
244
245     this.gun2.cnt = time + this.attack_finished_single[0];
246 }
247
248 #endif