]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/tturrets/system/system_damage.qc
72bfaec2b931c581bc3fdfdeb40bf17e20b61f69
[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     gib.movetype           = MOVETYPE_BOUNCE;
26     gib.takedamage         = DAMAGE_YES;
27     gib.event_damage       = turret_gib_damage;
28     gib.health             = -1;
29     gib.effects            = EF_LOWPRECISION;
30     gib.flags              = FL_NOTARGET;
31     gib.colormod           = v_colormod;
32     gib.velocity           = v_to;
33
34     if (b_burn)
35     {
36         burn = spawn();
37         burn.effects        = EF_LOWPRECISION;//|EF_FLAME;
38         setattachment(burn,gib,"");
39         setorigin(burn,(gib.mins + gib.maxs) * 0.5);
40         SUB_SetFade(burn,time + (f_lifetime * 0.5), 2);
41     }
42 }
43
44 void turret_gib_boom()
45 {
46     entity gib;
47     float i;
48     string s;
49
50     for (i = 1; i < 5; i = i +1)
51     {
52         gib = spawn();
53         gib.classname = "turret_gib";
54
55         s = strcat("models/turrets/head-gib",ftos(i));
56         s = strcat(s,".md3");
57         setmodel(gib, s);
58
59         setorigin(gib,self.origin);
60
61         SUB_SetFade(gib,time + 5,2);
62
63         gib.solid              = SOLID_BBOX;
64         gib.movetype           = MOVETYPE_BOUNCE;
65         gib.gravity            = 0.5;
66         gib.damageforcescale   = 2;
67         gib.takedamage         = DAMAGE_YES;
68         gib.event_damage       = turret_gib_damage;
69         gib.health             = -1;
70         gib.effects            = EF_LOWPRECISION;
71         gib.flags              = FL_NOTARGET;
72         gib.velocity           = self.velocity + (randomvec() * 700);
73         gib.avelocity          = randomvec() * 64;
74     }
75
76     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
77     WriteByte (MSG_BROADCAST, 78);
78     WriteCoord (MSG_BROADCAST, self.origin_x);
79     WriteCoord (MSG_BROADCAST, self.origin_y);
80     WriteCoord (MSG_BROADCAST, self.origin_z);
81
82     remove(self);
83 }
84
85 void turret_trowgib2(
86     vector v_from, vector v_to, vector v_colormod,
87     entity e_mimic, float boomtime)
88 {
89     entity gib;
90
91     gib = spawn();
92
93     gib.classname = "turret_gib";
94     setmodel(gib,e_mimic.model);
95     setorigin(gib,v_from);
96
97     gib.solid              = SOLID_BBOX;
98
99     gib.movetype           = MOVETYPE_BOUNCE;
100     gib.gravity            = 0.75;
101     gib.damageforcescale   = 2;
102     gib.takedamage         = DAMAGE_YES;
103     gib.event_damage       = turret_gib_damage;
104     gib.health             = -1;
105     gib.effects            = EF_LOWPRECISION;
106     gib.flags              = FL_NOTARGET;
107     gib.colormod           = v_colormod;
108     gib.velocity           = v_to;
109     gib.avelocity          = randomvec() * 32;
110     gib.think              = turret_gib_boom;
111     gib.nextthink          = boomtime;
112     //gib.effects            = EF_FLAME;
113
114
115 }
116 /*
117 * Spawn a boom, trow fake bits arround
118 * and hide the real ones.
119 */
120 void turret_stdproc_die()
121 {
122     vector org2;
123     vector t_dir;
124
125     self.deadflag           = DEAD_DEAD;
126     self.tur_head.deadflag  = self.deadflag;
127     
128     sound (self, CHAN_PLAYER, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
129     org2 = self.origin + '0 0 40';
130
131 // Explotion grafix
132     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
133     WriteByte (MSG_BROADCAST, 78);
134     WriteCoord (MSG_BROADCAST, org2_x);
135     WriteCoord (MSG_BROADCAST, org2_y);
136     WriteCoord (MSG_BROADCAST, org2_z);
137
138 // Unsolidify and hide real parts
139     self.solid              = SOLID_NOT;
140     self.tur_head.solid     = self.solid;
141
142     self.event_damage           = SUB_Null;
143     self.takedamage             = DAMAGE_NO;
144
145     self.effects            = EF_NODRAW;
146     self.health             = 0;
147
148 // Trow fake parts arround
149     // base
150     if not(self.damage_flags & TFL_DMG_DEATH_NOGIBS)
151     {
152         makevectors(self.angles);
153         if (random() > 0.5)
154         {
155             turret_trowgib(self.origin, '0 0 0', '1 1 1', "models/turrets/base-gib2.md3", min(self.respawntime, 20), 1, 1);
156             
157             t_dir = (v_up * 700) + (randomvec() * 300);            
158             turret_trowgib(self.origin, t_dir, '1 1 1', "models/turrets/base-gib3.md3", min(self.respawntime, 10), 1, 1);
159             
160             t_dir = (v_up * 700) + (randomvec() * 300);
161             turret_trowgib(self.origin, t_dir, '1 1 1', "models/turrets/base-gib4.md3", min(self.respawntime, 10), 1, 1);
162         }
163         else
164         {
165             turret_trowgib(self.origin, '0 0 0', '1 1 1', "models/turrets/base-gib1.md3", min(self.respawntime, 20), 1, 1);
166         }
167
168         // Blow the top part up into the air
169         turret_trowgib2( self.origin + (v_up * 50), v_up * 150 + randomvec() * 50, '0.2 0.2 0.2', self.tur_head,time + 0.5 + (random() * 0.5));
170     }
171
172 // Go boom
173     //RadiusDamage (self,self, min(self.ammo,50),min(self.ammo,50) * 0.25,250,world,min(self.ammo,50)*5,DEATH_TURRET,world);
174
175     if(self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
176     {
177         if (self.turret_diehook)
178             self.turret_diehook();
179
180         remove(self.tur_head);
181         remove(self);
182     }
183     else
184     {
185                 // Setup respawn
186         self.nextthink      = time + self.respawntime;
187         self.think          = turret_stdproc_respawn;
188         
189         if (self.turret_diehook)
190             self.turret_diehook();
191     }
192 }
193
194 void turret_stdproc_respawn()
195 {
196     // Make sure all parts belong to the same team since
197     // this function doubles as "teamchange" function.
198
199     self.tur_head.team  = self.team;
200
201     self.effects             &~= EF_NODRAW;
202     self.deadflag           = DEAD_NO;
203     self.effects            = EF_LOWPRECISION;
204     self.solid              = SOLID_BBOX;
205     
206     self.takedamage                     = DAMAGE_AIM;
207     self.event_damage           = turret_stdproc_damage;
208
209     self.avelocity              = '0 0 0';
210     self.tur_head.avelocity     = self.avelocity;
211     self.tur_head.angles        = self.idle_aim;
212     self.health                 = self.tur_health;
213
214     self.enemy                  = world;
215     self.volly_counter          = self.shot_volly;
216     self.ammo                   = self.ammo_max;
217
218     self.nextthink  = time + self.ticrate;
219     
220     self.SendFlags  = TNSF_FULL_UPDATE;
221     self.think      = turret_link;  // CSQC?
222
223     if (self.turret_respawnhook)
224         self.turret_respawnhook();
225
226 }
227
228 /*
229 * Standard damage proc.
230 */
231 void turret_stdproc_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
232 {
233
234     // Enougth allready!
235     if (self.health <= 0)
236         return;
237
238     // Inactive turrets take no damage. (hm..)
239     if not (self.tur_active)
240         return;
241
242     if (teamplay)
243     if (self.team == attacker.team)
244     {
245         // This does not happen anymore. Re-enable if you fix that.
246         if(clienttype(attacker) == CLIENTTYPE_REAL)
247             sprint(attacker, "\{1}Turret tells you: I'm on your team!\n");
248
249         if(autocvar_g_friendlyfire)
250             damage = damage * autocvar_g_friendlyfire;
251         else
252             return;
253     }
254
255     self.health = self.health - damage;
256
257     // thorw head slightly off aim when hit?
258     if (self.damage_flags & TFL_DMG_HEADSHAKE)
259     {
260         self.tur_head.angles_x = self.tur_head.angles_x + (-0.5 + random()) * damage;
261         self.tur_head.angles_y = self.tur_head.angles_y + (-0.5 + random()) * damage;
262         
263         self.SendFlags  |= TNSF_ANG;
264
265     }
266
267     if (self.turrcaps_flags & TFL_TURRCAPS_MOVE)
268         self.velocity = self.velocity + vforce;
269
270     // FIXME: Better damage feedback?
271     
272     if (self.health <= 0)
273     {
274         self.event_damage           = SUB_Null;
275         self.tur_head.event_damage  = SUB_Null;
276         self.takedamage             = DAMAGE_NO;
277         self.nextthink = time;
278         self.think = turret_stdproc_die;
279     }
280     
281     // CSQC
282     self.SendFlags  |= TNSF_STATUS;
283
284 }