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