]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/tturrets/system/system_damage.qc
Add remaxim to the credits file, for using his sound from opengameart. I'm not sure...
[xonotic/xonotic-data.pk3dir.git] / 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.takedamage             = DAMAGE_NO;
152
153     self.effects            = 0;
154     self.tur_head.effects   = self.effects;
155     self.health             = 0;
156
157 // Trow fake parts arround
158     // base
159     if not(self.damage_flags & TFL_DMG_DEATH_NOGIBS)
160     {
161         makevectors(self.angles);
162         if (random() > 0.5)
163         {
164             turret_trowgib(self.origin, '0 0 0','1 1 1',"models/turrets/base-gib2.md3",min(self.respawntime,20),1,1);
165             t_dir = (v_up * 700) + (randomvec() * 300);
166             turret_trowgib(self.origin, t_dir,'1 1 1',"models/turrets/base-gib3.md3",min(self.respawntime,10),1,1);
167             t_dir = (v_up * 700) + (randomvec() * 300);
168             turret_trowgib(self.origin, t_dir,'1 1 1',"models/turrets/base-gib4.md3",min(self.respawntime,10),1,1);
169         }
170         else
171         {
172             turret_trowgib(self.origin, '0 0 0','1 1 1',"models/turrets/base-gib1.md3",min(self.respawntime,20),1,1);
173         }
174
175         // Blow the top part up into the air
176         turret_trowgib2( self.origin + (v_up * 50),
177                          v_up * 150 + randomvec() * 50,
178                          '0.2 0.2 0.2',
179                          self.tur_head,time + 0.5 + (random() * 0.5));
180     }
181
182 // Go boom
183     //RadiusDamage (self,self, min(self.ammo,50),min(self.ammo,50) * 0.25,250,world,min(self.ammo,50)*5,DEATH_TURRET,world);
184
185     if(self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
186     {
187         if (self.turret_diehook)
188             self.turret_diehook();
189
190         remove(self.tur_head);
191         remove(self);
192     }
193     else
194     {
195     // Setup respawn
196         self.nextthink      = time + self.respawntime;
197         //self.think          = self.turret_spawnfunc;
198         self.think          = turret_stdproc_respawn;
199         if (self.turret_diehook)
200             self.turret_diehook();
201     }
202
203 }
204
205 void turret_stdproc_respawn()
206 {
207     // Make sure all parts belong to the same team since
208     // this function doubles as "teamchange" function.
209
210     self.tur_head.team = self.team;
211
212     /*
213     COLOR_TEAM1       = 4;  // red
214     COLOR_TEAM2       = 13; // blue
215     COLOR_TEAM3       = 12; // yellow
216     COLOR_TEAM4       = 9; // pink
217     */
218
219         self.colormod = '0 0 0';
220
221         switch(self.team)
222         {
223         case COLOR_TEAM1: // Red
224             self.colormod = '1.4 0.8 0.8';
225             break;
226
227         case COLOR_TEAM2: // Blue
228             self.colormod = '0.8 0.8 1.4';
229             break;
230
231         case COLOR_TEAM3: // Yellow
232             self.colormod = '1.4 1.4 0.6';
233             break;
234
235         case COLOR_TEAM4: // Pink
236             self.colormod = '1.4 0.6 1.4';
237             break;
238         }
239
240     self.deadflag           = DEAD_NO;
241     self.effects            = 0;
242     self.tur_head.effects   = self.effects;
243
244     self.solid              = SOLID_BBOX;
245
246     self.alpha = 1;
247     self.tur_head.alpha     = self.alpha;
248     self.customizeentityforclient = SUB_True;
249     self.tur_head.customizeentityforclient = SUB_True;
250
251     self.takedamage = DAMAGE_AIM;
252     self.event_damage           = turret_stdproc_damage;
253
254     self.avelocity              = '0 0 0';
255     self.tur_head.avelocity     = self.avelocity;
256     self.tur_head.angles        = self.idle_aim;
257     self.health                 = self.tur_health;
258
259     self.enemy                  = world;
260     self.volly_counter          = self.shot_volly;
261     self.ammo                   = self.ammo_max;
262
263     self.nextthink  = time + self.ticrate;
264     self.think      = turret_think;
265
266     if (self.turret_respawnhook)
267         self.turret_respawnhook();
268
269 }
270
271 /*
272 * Standard damage proc.
273 */
274 void turret_stdproc_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
275 {
276
277     // Enougth allready!
278     if (self.health <= 0)
279         return;
280
281     // Inactive turrets take no damage. (hm..)
282     if not (self.tur_active)
283         return;
284
285     if (teamplay != 0)
286     if (self.team == attacker.team)
287     {
288         // This does not happen anymore. Re-enable if you fix that.
289         if(clienttype(attacker) == CLIENTTYPE_REAL)
290             sprint(attacker, "\{1}Turret tells you: I'm on your team!\n");
291
292         if(cvar("g_friendlyfire"))
293             damage = damage * cvar("g_friendlyfire");
294         else
295             return;
296     }
297
298     self.health = self.health - damage;
299
300     // thorw head slightly off aim when hit?
301     if (self.damage_flags & TFL_DMG_HEADSHAKE)
302     {
303         //baseent.tur_aimoff_x += (random() * damage);
304         //baseent.tur_aimoff_y += ((random()*0.75) * damage);
305         self.tur_head.angles_x = self.tur_head.angles_x + (-0.5 + random()) * damage;
306         self.tur_head.angles_y = self.tur_head.angles_y + (-0.5 + random()) * damage;
307     }
308
309     if (self.turrcaps_flags & TFL_TURRCAPS_MOVE)
310         self.velocity = self.velocity + vforce;
311
312     // FIXME: Better damage feedback
313     // Start burning when we have 10% or less health left
314     //if (self.health < (self.tur_health * 0.1))
315     //    self.effects = EF_FLAME;
316
317     if (self.health <= 0)
318     {
319         self.event_damage           = SUB_Null;
320         self.tur_head.event_damage  = SUB_Null;
321         self.takedamage             = DAMAGE_NO;
322         self.nextthink = time;
323         self.think = turret_stdproc_die;
324     }
325 }