]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/tturrets/system/system_damage.qc
preliminary declaration of jointtype, and make misc_follow behave as a joint if joint...
[divverent/nexuiz.git] / data / qcsrc / server / tturrets / system / system_damage.qc
1 /*
2 * Trow a turret gib
3 */
4 void turret_gib_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
5 {
6     self.velocity += vforce;
7 }
8
9 void turret_trowgib(
10     vector v_from, vector v_to, vector v_colormod,
11     string smodel,
12     float f_lifetime, float f_fadetime, float b_burn)
13 {
14     local entity gib;
15     local entity burn;
16
17     gib = spawn();
18
19     gib.classname = "turret_gib";
20     setmodel(gib,smodel);
21     setorigin(gib,v_from);
22     SUB_SetFade(gib,time + f_lifetime,2);
23
24     gib.solid              = SOLID_BBOX;
25
26     gib.movetype           = MOVETYPE_BOUNCE;
27     gib.takedamage         = DAMAGE_YES;
28     gib.event_damage       = turret_gib_damage;
29     gib.health             = -1;
30     gib.effects            = EF_LOWPRECISION;
31     gib.flags              = FL_NOTARGET;
32     gib.colormod           = v_colormod;
33     gib.velocity           = v_to;
34
35     if (b_burn)
36     {
37         burn = spawn();
38         burn.effects        = EF_LOWPRECISION;//|EF_FLAME;
39         setattachment(burn,gib,"");
40         setorigin(burn,(gib.mins + gib.maxs) * 0.5);
41         SUB_SetFade(burn,time + (f_lifetime * 0.5) ,2);
42     }
43 }
44
45 void turret_gib_boom()
46 {
47     entity gib;
48     float i;
49     string s;
50
51     for (i = 1; i < 5; i = i +1)
52     {
53         gib = spawn();
54         gib.classname = "turret_gib";
55
56         s = strcat("models/turrets/head-gib",ftos(i));
57         s = strcat(s,".md3");
58         // bprint("s:",s,"\n");
59         setmodel(gib,s);
60
61         setorigin(gib,self.origin);
62
63         SUB_SetFade(gib,time + 5,2);
64
65         gib.solid              = SOLID_BBOX;
66
67         gib.movetype           = MOVETYPE_BOUNCE;
68         gib.gravity            = 0.5;
69         gib.damageforcescale   = 2;
70         gib.takedamage         = DAMAGE_YES;
71         gib.event_damage       = turret_gib_damage;
72         gib.health             = -1;
73         gib.effects            = EF_LOWPRECISION;
74         gib.flags              = FL_NOTARGET;
75         gib.velocity           = self.velocity + (randomvec() * 700);
76         gib.avelocity          = randomvec() * 64;
77     }
78
79     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
80     WriteByte (MSG_BROADCAST, 78);
81     WriteCoord (MSG_BROADCAST, self.origin_x);
82     WriteCoord (MSG_BROADCAST, self.origin_y);
83     WriteCoord (MSG_BROADCAST, self.origin_z);
84
85     remove(self);
86 }
87
88 void turret_trowgib2(
89     vector v_from, vector v_to, vector v_colormod,
90     entity e_mimic, float boomtime)
91 {
92     entity gib;
93
94     gib = spawn();
95
96     gib.classname = "turret_gib";
97     setmodel(gib,e_mimic.model);
98     setorigin(gib,v_from);
99
100     gib.solid              = SOLID_BBOX;
101
102     gib.movetype           = MOVETYPE_BOUNCE;
103     gib.gravity            = 0.75;
104     gib.damageforcescale   = 2;
105     gib.takedamage         = DAMAGE_YES;
106     gib.event_damage       = turret_gib_damage;
107     gib.health             = -1;
108     gib.effects            = EF_LOWPRECISION;
109     gib.flags              = FL_NOTARGET;
110     gib.colormod           = v_colormod;
111     gib.velocity           = v_to;
112     gib.avelocity          = randomvec() * 32;
113     gib.think              = turret_gib_boom;
114     gib.nextthink          = boomtime;
115     //gib.effects            = EF_FLAME;
116
117
118 }
119 /*
120 * Spawn a boom, trow fake bits arround
121 * and hide the real ones.
122 */
123 void turret_stdproc_die()
124 {
125     vector org2;
126     vector t_dir;
127
128     self.deadflag           = DEAD_DEAD;
129     self.tur_head.deadflag  = self.deadflag;
130
131     sound (self, CHAN_PLAYER, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
132     org2 = self.origin + '0 0 40';
133
134 // Explotion grafix
135     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
136     WriteByte (MSG_BROADCAST, 78);
137     WriteCoord (MSG_BROADCAST, org2_x);
138     WriteCoord (MSG_BROADCAST, org2_y);
139     WriteCoord (MSG_BROADCAST, org2_z);
140
141 // Unsolidify and hide real parts
142     self.solid              = SOLID_NOT;
143     self.tur_head.solid     = self.solid;
144
145     self.alpha             = -1;
146     self.tur_head.alpha    = self.alpha;
147     self.customizeentityforclient = SUB_False;
148     self.tur_head.customizeentityforclient = SUB_False;
149
150     self.event_damage           = SUB_Null;
151     self.tur_head.event_damage  = SUB_Null;
152     self.takedamage             = DAMAGE_NO;
153     self.tur_head.takedamage    = self.takedamage;
154
155     self.effects            = 0;
156     self.tur_head.effects   = self.effects;
157     self.health             = 0;
158
159 // Trow fake parts arround
160     // base
161     if not(self.damage_flags & TFL_DMG_DEATH_NOGIBS)
162     {
163         makevectors(self.angles);
164         if (random() > 0.5)
165         {
166             turret_trowgib(self.origin, '0 0 0','1 1 1',"models/turrets/base-gib2.md3",min(self.respawntime,20),1,1);
167             t_dir = (v_up * 700) + (randomvec() * 300);
168             turret_trowgib(self.origin, t_dir,'1 1 1',"models/turrets/base-gib3.md3",min(self.respawntime,10),1,1);
169             t_dir = (v_up * 700) + (randomvec() * 300);
170             turret_trowgib(self.origin, t_dir,'1 1 1',"models/turrets/base-gib4.md3",min(self.respawntime,10),1,1);
171         }
172         else
173         {
174             turret_trowgib(self.origin, '0 0 0','1 1 1',"models/turrets/base-gib1.md3",min(self.respawntime,20),1,1);
175         }
176
177         // Blow the top part up into the air
178         turret_trowgib2( self.origin + (v_up * 50),
179                          v_up * 150 + randomvec() * 50,
180                          '0.2 0.2 0.2',
181                          self.tur_head,time + 0.5 + (random() * 0.5));
182     }
183
184 // Go boom
185     //RadiusDamage (self,self, min(self.ammo,50),min(self.ammo,50) * 0.25,250,world,min(self.ammo,50)*5,DEATH_TURRET,world);
186
187     if(self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
188     {
189         if (self.turret_diehook)
190             self.turret_diehook();
191
192         remove(self.tur_head);
193         remove(self);
194     }
195     else
196     {
197     // Setup respawn
198         self.nextthink      = time + self.respawntime;
199         //self.think          = self.turret_spawnfunc;
200         self.think          = turret_stdproc_respawn;
201         if (self.turret_diehook)
202             self.turret_diehook();
203     }
204
205 }
206
207 void turret_stdproc_respawn()
208 {
209     // Make sure all parts belong to the same team since
210     // this function doubles as "teamchange" function.
211
212     self.tur_head.team = self.team;
213
214     /*
215     COLOR_TEAM1       = 4;  // red
216     COLOR_TEAM2       = 13; // blue
217     COLOR_TEAM3       = 12; // yellow
218     COLOR_TEAM4       = 9; // pink
219     */
220
221         self.colormod = '0 0 0';
222
223         switch(self.team)
224         {
225         case COLOR_TEAM1: // Red
226             self.colormod = '1.4 0.8 0.8';
227             break;
228
229         case COLOR_TEAM2: // Blue
230             self.colormod = '0.8 0.8 1.4';
231             break;
232
233         case COLOR_TEAM3: // Yellow
234             self.colormod = '1.4 1.4 0.6';
235             break;
236
237         case COLOR_TEAM4: // Pink
238             self.colormod = '1.4 0.6 1.4';
239             break;
240         }
241
242     self.deadflag           = DEAD_NO;
243     self.tur_head.deadflag  = self.deadflag;
244     self.effects            = 0;
245     self.tur_head.effects   = self.effects;
246
247     self.solid              = SOLID_BBOX;
248     self.tur_head.solid     = self.solid;
249
250     self.alpha = 1;
251     self.tur_head.alpha     = self.alpha;
252     self.customizeentityforclient = SUB_True;
253     self.tur_head.customizeentityforclient = SUB_True;
254
255
256     self.takedamage = DAMAGE_AIM;
257     self.tur_head.takedamage    = self.takedamage;
258
259     self.event_damage           = turret_stdproc_damage;
260     self.tur_head.event_damage  = self.event_damage;
261
262     self.avelocity              = '0 0 0';
263     self.tur_head.avelocity     = self.avelocity;
264     self.tur_head.angles        = self.idle_aim;
265     self.health                 = self.tur_health;
266     self.tur_head.health         = self.tur_health;
267
268     self.enemy                  = world;
269     self.volly_counter          = self.shot_volly;
270     self.ammo                   = self.ammo_max;
271
272     self.nextthink  = time + self.ticrate;
273     self.think      = turret_think;
274
275     if (self.turret_respawnhook)
276         self.turret_respawnhook();
277
278 }
279
280 /*
281 * Standard damage proc.
282 */
283 void turret_stdproc_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
284 {
285     entity baseent;
286
287     if (self.owner)
288         baseent = self.owner;
289     else
290         baseent = self;
291
292     // Enougth allready!
293     if (self.health <= 0)
294         return;
295
296     // Inactive turrets take no damage. (hm..)
297     if not (baseent.tur_active)
298         return;
299
300     if (teamplay != 0)
301     if (self.team == attacker.team)
302     {
303         // This does not happen anymore. Re-enable if you fix that.
304         //if(attacker.flags & FL_CLIENT)
305         if(clienttype(attacker) == CLIENTTYPE_REAL)
306             sprint(attacker, "\{1}Turret tells you: I'm on your team!\n");
307
308         if(cvar("g_friendlyfire"))
309             damage = damage * cvar("g_friendlyfire");
310         else
311             return;
312     }
313
314     self.health = self.health - damage;
315
316     // thorw head slightly off aim when hit?
317     if (self.classname == "turret_head")
318         if (baseent.damage_flags & TFL_DMG_HEADSHAKE)
319         {
320             //baseent.tur_aimoff_x += (random() * damage);
321             //baseent.tur_aimoff_y += ((random()*0.75) * damage);
322             self.angles_x = self.angles_x + (-0.5 + random()) * damage;
323             self.angles_y = self.angles_y + (-0.5 + random()) * damage;
324         }
325
326     if (baseent.turrcaps_flags & TFL_TURRCAPS_MOVE)
327         baseent.velocity = baseent.velocity + vforce;
328
329     // FIXME: Better damage feedback
330     // Start burning when we have 10% or less health left
331     //if (self.health < (self.tur_health * 0.1))
332     //    self.effects = EF_FLAME;
333
334     if (self.health <= 0)
335     {
336         baseent.event_damage           = SUB_Null;
337         baseent.tur_head.event_damage  = SUB_Null;
338         baseent.takedamage             = DAMAGE_NO;
339         baseent.tur_head.takedamage    = baseent.takedamage;
340         baseent.nextthink = time;
341         baseent.think = turret_stdproc_die;
342     }
343 }