(untested) make rain and snow client side entities
[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 .vector movedir; // trace direction
47
48 void Draw_PointParticles()
49 {
50         float n, i, fail;
51         vector p;
52         vector sz;
53         vector o;
54         o = self.origin;
55         sz = self.maxs - self.mins;
56         n = self.impulse * drawframetime;
57         fail = 0;
58         for(i = random(); i <= n && fail <= 64*n; ++i)
59         {
60                 p = o + self.mins;
61                 p_x += random() * sz_x;
62                 p_y += random() * sz_y;
63                 p_z += random() * sz_z;
64                 if(PointInBrush(self, p))
65                 {
66                         if(self.movedir != '0 0 0')
67                         {
68                                 traceline(p, p + normalize(self.movedir) * 4096, 0, world);
69                                 p = trace_endpos;
70                                 pointparticles(self.cnt, p, trace_plane_normal * vlen(self.movedir) + self.velocity + randomvec() * self.waterlevel, self.count, self.glow_color);
71                         }
72                         else
73                                 pointparticles(self.cnt, p, self.velocity + randomvec() * self.waterlevel, self.count, self.glow_color);
74                         if(self.noise != "")
75                         {
76                                 self.origin = p;
77                                 sound(self, CHAN_AUTO, self.noise, 1, ATTN_NORM);
78                         }
79                 }
80                 else if(self.absolute)
81                 {
82                         ++fail;
83                         --i;
84                 }
85         }
86         self.origin = o;
87 }
88
89 void Ent_PointParticles()
90 {
91         self.modelindex = ReadShort();
92         self.origin_x = ReadCoord();
93         self.origin_y = ReadCoord();
94         self.origin_z = ReadCoord();
95         self.maxs_x = ReadCoord();
96         self.maxs_y = ReadCoord();
97         self.maxs_z = ReadCoord();
98         self.cnt = ReadShort(); // effect number
99         self.impulse = ReadCoord(); // density (<0: point, >0: volume)
100         if(self.impulse == 0)
101                 self.impulse = 1; // one per sec
102         self.velocity = decompressShortVector(ReadShort());
103         self.movedir = decompressShortVector(ReadShort());
104         self.waterlevel = ReadCoord();
105         self.count = ReadCoord();
106         self.glow_color = ReadByte();
107         if(self.noise)
108                 strunzone(self.noise);
109         self.noise = strzone(ReadString());
110
111         self.absolute = (self.impulse >= 0);
112         if(!self.absolute)
113                 self.impulse *= -self.maxs_x * self.maxs_y * self.maxs_z / 262144; // relative: particles per 64^3 cube
114
115         self.mins    = -0.5 * self.maxs;
116         self.maxs    =  0.5 * self.maxs;
117         self.origin  = self.origin - self.mins;
118
119         setorigin(self, self.origin);
120         setsize(self, self.mins, self.maxs);
121         self.solid = SOLID_NOT;
122         self.draw = Draw_PointParticles;
123 }
124
125 void Draw_Rain()
126 {
127     te_particlerain(self.origin + self.mins, self.origin + self.maxs, self.velocity, self.count * drawframetime, self.glow_color);
128 }
129
130 void Draw_Snow()
131 {
132     te_particlesnow(self.origin + self.mins, self.origin + self.maxs, self.velocity, self.count * drawframetime, self.glow_color);
133 }
134
135 void Ent_RainOrSnow()
136 {
137         self.impulse = ReadByte(); // Rain, Snow, or Whatever
138         self.origin_x = ReadCoord();
139         self.origin_y = ReadCoord();
140         self.origin_z = ReadCoord();
141         self.maxs_x = ReadCoord();
142         self.maxs_y = ReadCoord();
143         self.maxs_z = ReadCoord();
144         self.velocity = decompressShortVector(ReadShort());
145         self.count = ReadShort() * 10;
146         self.glow_color = ReadByte(); // color
147
148         self.mins    = -0.5 * self.maxs;
149         self.maxs    =  0.5 * self.maxs;
150         self.origin  = self.origin - self.mins;
151
152         setorigin(self, self.origin);
153         setsize(self, self.mins, self.maxs);
154         self.solid = SOLID_NOT;
155         if(self.impulse)
156                 self.draw = Draw_Rain;
157         else
158                 self.draw = Draw_Snow;
159 }