]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/client/generator.qc
Multiple improvements to onslaught code, including CSQC generators/control points...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / generator.qc
1 float generator_precached;
2 .float count;
3
4 vector randompos(vector m1, vector m2)
5 {
6         vector v;
7         m2 = m2 - m1;
8         v_x = m2_x * random() + m1_x;
9         v_y = m2_y * random() + m1_y;
10         v_z = m2_z * random() + m1_z;
11         return  v;
12 }
13
14 void generator_precache()
15 {
16         if(generator_precached)
17                 return; // already precached
18
19         precache_model("models/onslaught/generator.md3");
20         precache_model("models/onslaught/generator_dead.md3");
21         precache_model("models/onslaught/generator_dmg1.md3");
22         precache_model("models/onslaught/generator_dmg2.md3");
23         precache_model("models/onslaught/generator_dmg3.md3");
24         precache_model("models/onslaught/generator_dmg4.md3");
25         precache_model("models/onslaught/generator_dmg5.md3");
26         precache_model("models/onslaught/generator_dmg6.md3");
27         precache_model("models/onslaught/generator_dmg7.md3");
28         precache_model("models/onslaught/generator_dmg8.md3");
29         precache_model("models/onslaught/generator_dmg9.md3");
30         precache_model("models/onslaught/generator_dead.md3");
31
32         precache_model("models/onslaught/ons_ray.md3");
33         precache_sound("onslaught/shockwave.wav");
34         precache_sound("weapons/grenade_impact.wav");
35         precache_sound("weapons/rocket_impact.wav");
36
37         precache_model("models/onslaught/gen_gib1.md3");
38         precache_model("models/onslaught/gen_gib2.md3");
39         precache_model("models/onslaught/gen_gib3.md3");
40
41         generator_precached = TRUE;
42 }
43
44 void ons_gib_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
45 {
46         self.velocity = self.velocity + vforce;
47 }
48
49 .float giblifetime;
50
51 void gib_draw_noburn()
52 {
53         if(time >= self.giblifetime)
54                 remove(self);
55 }
56
57 void gib_draw()
58 {
59         if(time >= self.move_time)
60                 return;
61
62         self.move_time = time + 0.05;
63
64         if(time > self.giblifetime)
65         {
66                 remove(self);
67                 return;
68         }
69
70         self.alpha -= 0.05;
71
72         if(self.alpha < 0.1)
73         {
74                 remove(self);
75                 return;
76         }
77
78         if(random()<0.6)
79                 pointparticles(particleeffectnum("onslaught_generator_gib_flame"), self.origin, '0 0 0', 1);
80 }
81
82 void ons_throwgib(vector v_from, vector v_to, string smodel, float f_lifetime, float b_burn)
83 {
84         entity gib;
85
86         gib = spawn();
87
88         setmodel(gib, smodel);
89         setorigin(gib, v_from);
90         gib.solid = SOLID_CORPSE;
91         gib.move_movetype = MOVETYPE_BOUNCE;
92         gib.movetype = MOVETYPE_BOUNCE;
93         gib.health = 255;
94         gib.move_velocity = v_to;
95         gib.move_origin = v_from;
96         gib.velocity = v_to;
97         gib.alpha = 1;
98         gib.move_time = time;
99         gib.drawmask = MASK_NORMAL;
100         gib.giblifetime = time + f_lifetime;
101
102         if(b_burn)
103                 gib.draw = gib_draw;
104         else
105                 gib.draw = gib_draw_noburn;
106 }
107
108 void onslaught_generator_ray_think()
109 {
110         self.nextthink = time + 0.05;
111         if(self.count > 10)
112         {
113                 self.think = SUB_Remove;
114                 return;
115         }
116
117         if(self.count > 5)
118                 self.alpha -= 0.1;
119         else
120                 self.alpha += 0.1;
121
122         self.scale += 0.2;
123         self.count +=1;
124 }
125
126 void onslaught_generator_ray_spawn(vector org)
127 {
128         entity e;
129         e = spawn();
130         setmodel(e, "models/onslaught/ons_ray.md3");
131         setorigin(e, org);
132         e.angles = randomvec() * 360;
133         e.alpha = 0;
134         e.scale = random() * 5 + 8;
135         e.think = onslaught_generator_ray_think;
136         e.nextthink = time + 0.05;
137 }
138
139 void generator_draw()
140 {
141         if(self.health > 0)
142                 return;
143
144         if(time < self.move_time)
145                 return;
146         if(self.count <= 0)
147                 return;
148
149         vector org;
150         float i;
151
152         // White shockwave
153         if(self.count==40||self.count==20)
154         {
155                 sound(self, CH_TRIGGER, "onslaught/shockwave.wav", VOL_BASE, ATTEN_NORM);
156                 pointparticles(particleeffectnum("electro_combo"), self.origin, '0 0 0', 6);
157         }
158
159         // Throw some gibs
160         if(random() < 0.3)
161         {
162                 i = random();
163                 if(i < 0.3)
164                         ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 11 + '0 0 20', "models/onslaught/gen_gib1.md3", 6, TRUE);
165                 else if(i > 0.7)
166                         ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 12 + '0 0 20', "models/onslaught/gen_gib2.md3", 6, TRUE);
167                 else
168                         ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 13 + '0 0 20', "models/onslaught/gen_gib3.md3", 6, TRUE);
169         }
170
171         // Spawn fire balls
172         for(i=0;i < 10;++i)
173         {
174                 org = self.origin + randompos('-30 -30 -30' * i + '0 0 -20', '30 30 30' * i + '0 0 20');
175                 pointparticles(particleeffectnum("onslaught_generator_gib_explode"), org, '0 0 0', 1);
176         }
177
178         // Short explosion sound + small explosion
179         if(random() < 0.25)
180         {
181                 te_explosion(self.origin);
182                 sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM);
183         }
184
185         // Particles
186         org = self.origin + randompos(self.mins + '8 8 8', self.maxs + '-8 -8 -8');
187         pointparticles(particleeffectnum("onslaught_generator_smallexplosion"), org, '0 0 0', 1);
188
189         // rays
190         if(random() > 0.25 )
191         {
192                 onslaught_generator_ray_spawn(self.origin);
193         }
194
195         // Final explosion
196         if(self.count==1)
197         {
198                 org = self.origin;
199                 te_explosion(org);
200                 pointparticles(particleeffectnum("onslaught_generator_finalexplosion"), org, '0 0 0', 1);
201                 sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
202         }
203
204         self.move_time = time + 0.05;
205
206         self.count -= 1;
207 }
208
209 .float max_health;
210 void generator_damage(float hp)
211 {
212         if(hp <= 0)
213                 setmodel(self, "models/onslaught/generator_dead.md3");
214         else if(hp < self.max_health * 0.10)
215                 setmodel(self, "models/onslaught/generator_dmg9.md3");
216         else if(hp < self.max_health * 0.20)
217                 setmodel(self, "models/onslaught/generator_dmg8.md3");
218         else if(hp < self.max_health * 0.30)
219                 setmodel(self, "models/onslaught/generator_dmg7.md3");
220         else if(hp < self.max_health * 0.40)
221                 setmodel(self, "models/onslaught/generator_dmg6.md3");
222         else if(hp < self.max_health * 0.50)
223                 setmodel(self, "models/onslaught/generator_dmg5.md3");
224         else if(hp < self.max_health * 0.60)
225                 setmodel(self, "models/onslaught/generator_dmg4.md3");
226         else if(hp < self.max_health * 0.70)
227                 setmodel(self, "models/onslaught/generator_dmg3.md3");
228         else if(hp < self.max_health * 0.80)
229                 setmodel(self, "models/onslaught/generator_dmg2.md3");
230         else if(hp < self.max_health * 0.90)
231                 setmodel(self, "models/onslaught/generator_dmg1.md3");
232         else if(hp <= self.max_health || hp >= self.max_health)
233                 setmodel(self, "models/onslaught/generator.md3");
234
235         setsize(self, GENERATOR_MIN, GENERATOR_MAX);
236 }
237
238 void generator_construct()
239 {
240         self.netname = "Generator";
241
242         setorigin(self, self.origin);
243         setmodel(self, "models/onslaught/generator.md3");
244         setsize(self, GENERATOR_MIN, GENERATOR_MAX);
245
246         self.move_movetype      = MOVETYPE_NOCLIP;
247         self.solid                      = SOLID_BBOX;
248         self.movetype           = MOVETYPE_NOCLIP;
249         self.move_origin        = self.origin;
250         self.move_time          = time;
251         self.drawmask           = MASK_NORMAL;
252         self.alpha                      = 1;
253         self.draw                       = generator_draw;
254 }
255
256 .vector glowmod;
257 void generator_changeteam()
258 {
259         if(self.team)
260         {
261                 self.glowmod = Team_ColorRGB(self.team - 1);
262                 self.teamradar_color = Team_ColorRGB(self.team - 1);
263                 self.colormap = 1024 + (self.team - 1) * 17;
264         }
265         else
266         {
267                 self.colormap = 1024;
268                 self.glowmod = '1 1 0';
269                 self.teamradar_color = '1 1 0';
270         }
271 }
272
273 void ent_generator()
274 {
275         float sf;
276         sf = ReadByte();
277
278         if(sf & GSF_SETUP)
279         {
280                 self.origin_x = ReadCoord();
281                 self.origin_y = ReadCoord();
282                 self.origin_z = ReadCoord();
283                 setorigin(self, self.origin);
284
285                 self.health = ReadByte();
286                 self.max_health = ReadByte();
287                 self.count = ReadByte();
288                 self.team = ReadByte();
289
290                 if(!self.count)
291                         self.count = 40;
292
293                 generator_changeteam();
294                 generator_precache();
295                 generator_construct();
296         }
297
298         if(sf & GSF_STATUS)
299         {
300                 float _tmp;
301                 _tmp = ReadByte();
302                 if(_tmp != self.team)
303                 {
304                         self.team = _tmp;
305                         generator_changeteam();
306                 }
307
308                 _tmp = ReadByte();
309
310                 if(_tmp != self.health)
311                         generator_damage(_tmp);
312
313                 self.health = _tmp;
314         }
315 }