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