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