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