]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/func_breakable.qc
clean up the func_breakable mess a bit; TODO merge it with assault's
[divverent/nexuiz.git] / data / qcsrc / server / func_breakable.qc
1 // TODO add assault's colormodding to this, make assault redirect to this one
2 // TODO add the fields this uses to the entities.def when done
3
4 .string mdl_dead; // or "" to hide when broken
5 .string debris; // space separated list of debris models
6 // other fields:
7 //   mdl = particle effect name
8 //   count = particle effect multiplier
9 //   targetname = target to trigger to unbreak the model
10 //   target = targets to trigger when broken
11 // notes:
12 //   for mdl_dead to work, origin must be set (using a common/origin brush).
13 //   Otherwise mdl_dead will be displayed at the map origin, and nobody would
14 //   want that!
15
16 .vector mins_save, maxs_save;
17
18 void func_breakable_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
19
20 //
21 // func_breakable
22 // - basically func_assault_destructible for general gameplay use
23 //
24 void LaunchDebris (string debrisname) =
25 {
26         local   entity dbr;
27
28         dbr = spawn();
29         dbr.origin = self.origin + self.absmin
30                    + '1 0 0' * random() * (self.absmax_x - self.absmin_x)
31                    + '0 1 0' * random() * (self.absmax_y - self.absmin_y)
32                    + '0 0 1' * random() * (self.absmax_z - self.absmin_z);
33         setmodel (dbr, debrisname );
34         dbr.movetype = MOVETYPE_BOUNCE;
35         dbr.solid = SOLID_NOT;
36         // TODO parametrize this
37         dbr.velocity_x = 70 * crandom();
38         dbr.velocity_y = 70 * crandom();
39         dbr.velocity_z = 140 + 70 * random();
40         dbr.avelocity_x = random()*600;
41         dbr.avelocity_y = random()*600;
42         dbr.avelocity_z = random()*600;
43         SUB_SetFade(dbr, time + 1 + random() * 5, 1);
44 };
45
46 void func_breakable_make_destroyed()
47 {
48         if(self.mdl_dead == "")
49         {
50                 self.model = "";
51                 self.solid = SOLID_NOT;
52         }
53         else
54         {
55                 setmodel(self, self.mdl_dead);
56                 self.solid = SOLID_BSP;
57         }
58         self.health = self.max_health;
59         self.takedamage = DAMAGE_NO;
60         self.event_damage = SUB_Null;
61         self.state = 1;
62         setsize(self, '0 0 0', '0 0 0');
63 }
64
65 void func_breakable_restore()
66 {
67         setmodel(self, self.mdl);
68         self.solid = SOLID_BSP;
69         self.health = self.max_health;
70         self.takedamage = DAMAGE_AIM;
71         self.event_damage = func_breakable_damage;
72         self.state = 0;
73         setsize(self, self.mins_save, self.maxs_save);
74 }
75
76 void func_breakable_destroy() {
77         float n, i;
78
79         func_breakable_make_destroyed();
80
81         // now throw around the debris
82         n = tokenize_sane(self.debris);
83         for(i = 0; i < n; ++i)
84                 LaunchDebris(argv(i));
85
86         if(self.cnt)
87                 pointparticles(self.cnt, self.absmin * 0.5 + self.absmax * 0.5, '0 0 0', self.count);
88
89         SUB_UseTargets();
90 }
91
92 void func_breakable_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
93 {
94         if(self.state == 1)
95                 return;
96         self.health = self.health - damage;
97         if(self.health < 0)
98         {
99                 activator = attacker;
100                 func_breakable_destroy();
101         }
102 }
103
104 // destructible walls that can be used to trigger target_objective_decrease
105 void spawnfunc_func_breakable() {
106         float n, i;
107         if(!self.health)
108                 self.health = 100;
109         self.max_health = self.health;
110
111         if(self.mdl != "")
112                 self.cnt = particleeffectnum(self.mdl);
113         if(self.count == 0)
114                 self.count = 1;
115
116         self.mdl = self.model;
117         SetBrushEntityModel();
118         self.mins_save = self.mins;
119         self.maxs_save = self.mins;
120
121         self.use = func_breakable_restore;
122
123         // precache all the models
124         if (self.mdl_dead)
125                 precache_model(self.mdl_dead);
126         n = tokenize_sane(self.debris);
127         for(i = 0; i < n; ++i)
128                 precache_model(argv(i));
129
130         self.event_damage = func_breakable_damage;
131
132         if(self.state)
133                 func_breakable_make_destroyed();
134         else
135                 func_breakable_restore();
136 }