pointparticles: negative "impulse" is particles per 64^3 cube, instead of absolute...
[divverent/nexuiz.git] / data / qcsrc / client / particles.qc
1 vector PointInBrush_vec;
2 float PointInBrush_Recurse()
3 {
4         float s;
5         entity se;
6         float f;
7
8         traceline(PointInBrush_vec, PointInBrush_vec, 0, world);
9         if not(trace_ent)
10                 return 0;
11         if(trace_ent == self)
12                 return 1;
13
14         se = trace_ent;
15         s = se.solid;
16         se.solid = SOLID_NOT;
17         f = PointInBrush_Recurse();
18         se.solid = s;
19
20         return f;
21 }
22 float PointInBrush(entity brush, vector point)
23 {
24         float f, s;
25
26         if not(self.modelindex)
27                 return 1;
28
29         s = self.solid;
30         self.solid = SOLID_BSP;
31         PointInBrush_vec = point;
32         f = PointInBrush_Recurse();
33         self.solid = s;
34
35         return f;
36 }
37
38 .float cnt; // effect number
39 .vector velocity; // particle velocity
40 .float waterlevel; // direction jitter
41 .float count; // count multiplier
42 .float glow_color; // palette color
43 .float impulse; // density
44 .string noise; // sound
45 .float absolute;
46
47 void Draw_PointParticles()
48 {
49         float n, i, fail;
50         vector p;
51         vector sz;
52         vector o;
53         o = self.origin;
54         sz = self.maxs - self.mins;
55         n = self.impulse * drawframetime;
56         fail = 0;
57         for(i = random(); i <= n && fail <= 64*n; ++i)
58         {
59                 p = o + self.mins;
60                 p_x += random() * sz_x;
61                 p_y += random() * sz_y;
62                 p_z += random() * sz_z;
63                 if(PointInBrush(self, p))
64                 {
65                         pointparticles(self.cnt, p, self.velocity + randomvec() * self.waterlevel, self.count, self.glow_color);
66                         if(self.noise != "")
67                         {
68                                 self.origin = p;
69                                 sound(self, CHAN_AUTO, self.noise, 1, ATTN_NORM);
70                         }
71                 }
72                 else if(self.absolute)
73                 {
74                         ++fail;
75                         --i;
76                 }
77         }
78         self.origin = o;
79 }
80
81 void Ent_PointParticles()
82 {
83         self.modelindex = ReadShort();
84         self.origin_x = ReadCoord();
85         self.origin_y = ReadCoord();
86         self.origin_z = ReadCoord();
87         self.maxs_x = ReadCoord();
88         self.maxs_y = ReadCoord();
89         self.maxs_z = ReadCoord();
90         self.cnt = ReadShort(); // effect number
91         self.impulse = ReadCoord(); // density (<0: point, >0: volume)
92         if(self.impulse == 0)
93                 self.impulse = 1; // one per sec
94         self.velocity_x = ReadCoord();
95         self.velocity_y = ReadCoord();
96         self.velocity_z = ReadCoord();
97         self.waterlevel = ReadCoord();
98         self.count = ReadCoord();
99         self.glow_color = ReadByte();
100         if(self.noise)
101                 strunzone(self.noise);
102         self.noise = strzone(ReadString());
103
104         self.absolute = (self.impulse >= 0);
105         if(!self.absolute)
106                 self.impulse *= -self.maxs_x * self.maxs_y * self.maxs_z / 262144; // relative: particles per 64^3 cube
107
108         self.mins    = -0.5 * self.maxs;
109         self.maxs    =  0.5 * self.maxs;
110         self.origin  = self.origin - self.mins;
111
112         setorigin(self, self.origin);
113         setsize(self, self.mins, self.maxs);
114         self.solid = SOLID_NOT;
115         self.draw = Draw_PointParticles;
116 }