]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/client/particles.qc
workaround: traceline appears to not hit SOLID_BSP csqc entities, no idea why
[divverent/nexuiz.git] / data / qcsrc / client / particles.qc
1 #ifdef POINTINBRUSH_WORKS
2 vector PointInBrush_vec;
3 entity PointInBrush_brush;
4 entity PointInBrush_allmask;
5 .float dphitcontentsmask;
6 float PointInBrush_Recurse()
7 {
8         float s;
9         entity se;
10         float f;
11
12         traceline(PointInBrush_vec, PointInBrush_vec, 0, world);
13         if not(trace_ent)
14                 return 0;
15         if(trace_ent == PointInBrush_brush)
16                 return 1;
17
18         se = trace_ent;
19         s = se.solid;
20         se.solid = SOLID_NOT;
21         f = PointInBrush_Recurse();
22         se.solid = s;
23
24         return f;
25 }
26 float PointInBrush(entity brush, vector point)
27 {
28         float f, s;
29
30         if not(brush.modelindex)
31                 return 1;
32
33         s = brush.solid;
34         brush.solid = SOLID_BSP;
35         PointInBrush_vec = point;
36         PointInBrush_brush = brush;
37         f = PointInBrush_Recurse();
38         brush.solid = s;
39
40         return f;
41 }
42 #endif
43
44 .float cnt; // effect number
45 .vector velocity; // particle velocity
46 .float waterlevel; // direction jitter
47 .float count; // count multiplier
48 .float glow_color; // palette color
49 .float impulse; // density
50 .string noise; // sound
51 .float absolute;
52 .vector movedir; // trace direction
53
54 void Draw_PointParticles()
55 {
56         float n, i, fail;
57         vector p;
58         vector sz;
59         vector o;
60         o = self.origin;
61         sz = self.maxs - self.mins;
62         n = self.impulse * drawframetime;
63         fail = 0;
64         for(i = random(); i <= n && fail <= 64*n; ++i)
65         {
66                 p = o + self.mins;
67                 p_x += random() * sz_x;
68                 p_y += random() * sz_y;
69                 p_z += random() * sz_z;
70 #ifdef POINTINBRUSH_WORKS
71                 if(PointInBrush(self, p))
72 #endif
73                 {
74                         if(self.movedir != '0 0 0')
75                         {
76                                 traceline(p, p + normalize(self.movedir) * 4096, 0, world);
77                                 p = trace_endpos;
78                                 pointparticles(self.cnt, p, trace_plane_normal * vlen(self.movedir) + self.velocity + randomvec() * self.waterlevel, self.count, self.glow_color);
79                         }
80                         else
81                                 pointparticles(self.cnt, p, self.velocity + randomvec() * self.waterlevel, self.count, self.glow_color);
82                         if(self.noise != "")
83                         {
84                                 self.origin = p;
85                                 sound(self, CHAN_AUTO, self.noise, 1, ATTN_NORM);
86                         }
87                 }
88 #ifdef POINTINBRUSH_WORKS
89                 else if(self.absolute)
90                 {
91                         ++fail;
92                         --i;
93                 }
94 #endif
95         }
96         self.origin = o;
97 }
98
99 void Ent_PointParticles()
100 {
101         float f;
102         f = ReadByte();
103         if(f & 2)
104         {
105                 self.impulse = ReadCoord(); // density (<0: point, >0: volume)
106                 if(self.impulse == 0)
107                         self.impulse = 1; // one per sec
108                 self.absolute = (self.impulse >= 0);
109                 if(!self.absolute)
110                         self.impulse *= -self.maxs_x * self.maxs_y * self.maxs_z / 262144; // relative: particles per 64^3 cube
111         }
112         if(f & 1)
113         {
114                 self.modelindex = ReadShort();
115                 self.origin_x = ReadCoord();
116                 self.origin_y = ReadCoord();
117                 self.origin_z = ReadCoord();
118                 self.maxs_x = ReadCoord();
119                 self.maxs_y = ReadCoord();
120                 self.maxs_z = ReadCoord();
121
122                 self.mins    = -0.5 * self.maxs;
123                 self.maxs    =  0.5 * self.maxs;
124                 self.origin  = self.origin - self.mins;
125
126                 self.cnt = ReadShort(); // effect number
127
128                 self.velocity = decompressShortVector(ReadShort());
129                 self.movedir = decompressShortVector(ReadShort());
130                 self.waterlevel = ReadCoord();
131                 self.count = ReadCoord();
132                 self.glow_color = ReadByte();
133                 if(self.noise)
134                         strunzone(self.noise);
135                 self.noise = strzone(ReadString());
136         }
137
138         setorigin(self, self.origin);
139         setsize(self, self.mins, self.maxs);
140         self.solid = SOLID_NOT;
141         self.draw = Draw_PointParticles;
142 }
143
144 void Ent_PointParticles_Remove()
145 {
146         if(self.noise)
147                 strunzone(self.noise);
148         self.noise = string_null;
149 }
150
151 void Draw_Rain()
152 {
153     te_particlerain(self.origin + self.mins, self.origin + self.maxs, self.velocity, self.count * drawframetime, self.glow_color);
154 }
155
156 void Draw_Snow()
157 {
158     te_particlesnow(self.origin + self.mins, self.origin + self.maxs, self.velocity, self.count * drawframetime, self.glow_color);
159 }
160
161 void Ent_RainOrSnow()
162 {
163         self.impulse = ReadByte(); // Rain, Snow, or Whatever
164         self.origin_x = ReadCoord();
165         self.origin_y = ReadCoord();
166         self.origin_z = ReadCoord();
167         self.maxs_x = ReadCoord();
168         self.maxs_y = ReadCoord();
169         self.maxs_z = ReadCoord();
170         self.velocity = decompressShortVector(ReadShort());
171         self.count = ReadShort() * 10;
172         self.glow_color = ReadByte(); // color
173
174         self.mins    = -0.5 * self.maxs;
175         self.maxs    =  0.5 * self.maxs;
176         self.origin  = self.origin - self.mins;
177
178         setorigin(self, self.origin);
179         setsize(self, self.mins, self.maxs);
180         self.solid = SOLID_NOT;
181         if(self.impulse)
182                 self.draw = Draw_Rain;
183         else
184                 self.draw = Draw_Snow;
185 }