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