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