]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/func/pointparticles.qc
Merge branch 'TimePath/experiments/csqc_prediction' into Mario/qc_physics
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / func / pointparticles.qc
1 #ifdef SVQC
2 // NOTE: also contains func_sparks
3
4 float pointparticles_SendEntity(entity to, float fl)
5 {
6         WriteByte(MSG_ENTITY, ENT_CLIENT_POINTPARTICLES);
7
8         // optional features to save space
9         fl = fl & 0x0F;
10         if(self.spawnflags & 2)
11                 fl |= 0x10; // absolute count on toggle-on
12         if(self.movedir != '0 0 0' || self.velocity != '0 0 0')
13                 fl |= 0x20; // 4 bytes - saves CPU
14         if(self.waterlevel || self.count != 1)
15                 fl |= 0x40; // 4 bytes - obscure features almost never used
16         if(self.mins != '0 0 0' || self.maxs != '0 0 0')
17                 fl |= 0x80; // 14 bytes - saves lots of space
18
19         WriteByte(MSG_ENTITY, fl);
20         if(fl & 2)
21         {
22                 if(self.state)
23                         WriteCoord(MSG_ENTITY, self.impulse);
24                 else
25                         WriteCoord(MSG_ENTITY, 0); // off
26         }
27         if(fl & 4)
28         {
29                 WriteCoord(MSG_ENTITY, self.origin_x);
30                 WriteCoord(MSG_ENTITY, self.origin_y);
31                 WriteCoord(MSG_ENTITY, self.origin_z);
32         }
33         if(fl & 1)
34         {
35                 if(self.model != "null")
36                 {
37                         WriteShort(MSG_ENTITY, self.modelindex);
38                         if(fl & 0x80)
39                         {
40                                 WriteCoord(MSG_ENTITY, self.mins_x);
41                                 WriteCoord(MSG_ENTITY, self.mins_y);
42                                 WriteCoord(MSG_ENTITY, self.mins_z);
43                                 WriteCoord(MSG_ENTITY, self.maxs_x);
44                                 WriteCoord(MSG_ENTITY, self.maxs_y);
45                                 WriteCoord(MSG_ENTITY, self.maxs_z);
46                         }
47                 }
48                 else
49                 {
50                         WriteShort(MSG_ENTITY, 0);
51                         if(fl & 0x80)
52                         {
53                                 WriteCoord(MSG_ENTITY, self.maxs_x);
54                                 WriteCoord(MSG_ENTITY, self.maxs_y);
55                                 WriteCoord(MSG_ENTITY, self.maxs_z);
56                         }
57                 }
58                 WriteShort(MSG_ENTITY, self.cnt);
59                 if(fl & 0x20)
60                 {
61                         WriteShort(MSG_ENTITY, compressShortVector(self.velocity));
62                         WriteShort(MSG_ENTITY, compressShortVector(self.movedir));
63                 }
64                 if(fl & 0x40)
65                 {
66                         WriteShort(MSG_ENTITY, self.waterlevel * 16.0);
67                         WriteByte(MSG_ENTITY, self.count * 16.0);
68                 }
69                 WriteString(MSG_ENTITY, self.noise);
70                 if(self.noise != "")
71                 {
72                         WriteByte(MSG_ENTITY, floor(self.atten * 64));
73                         WriteByte(MSG_ENTITY, floor(self.volume * 255));
74                 }
75                 WriteString(MSG_ENTITY, self.bgmscript);
76                 if(self.bgmscript != "")
77                 {
78                         WriteByte(MSG_ENTITY, floor(self.bgmscriptattack * 64));
79                         WriteByte(MSG_ENTITY, floor(self.bgmscriptdecay * 64));
80                         WriteByte(MSG_ENTITY, floor(self.bgmscriptsustain * 255));
81                         WriteByte(MSG_ENTITY, floor(self.bgmscriptrelease * 64));
82                 }
83         }
84         return 1;
85 }
86
87 void pointparticles_use()
88 {
89         self.state = !self.state;
90         self.SendFlags |= 2;
91 }
92
93 void pointparticles_think()
94 {
95         if(self.origin != self.oldorigin)
96         {
97                 self.SendFlags |= 4;
98                 self.oldorigin = self.origin;
99         }
100         self.nextthink = time;
101 }
102
103 void pointparticles_reset()
104 {
105         if(self.spawnflags & 1)
106                 self.state = 1;
107         else
108                 self.state = 0;
109 }
110
111 void spawnfunc_func_pointparticles()
112 {
113         if(self.model != "")
114                 setmodel(self, self.model);
115         if(self.noise != "")
116                 precache_sound (self.noise);
117
118         if(!self.bgmscriptsustain)
119                 self.bgmscriptsustain = 1;
120         else if(self.bgmscriptsustain < 0)
121                 self.bgmscriptsustain = 0;
122
123         if(!self.atten)
124                 self.atten = ATTEN_NORM;
125         else if(self.atten < 0)
126                 self.atten = 0;
127         if(!self.volume)
128                 self.volume = 1;
129         if(!self.count)
130                 self.count = 1;
131         if(!self.impulse)
132                 self.impulse = 1;
133
134         if(!self.modelindex)
135         {
136                 setorigin(self, self.origin + self.mins);
137                 setsize(self, '0 0 0', self.maxs - self.mins);
138         }
139         if(!self.cnt)
140                 self.cnt = particleeffectnum(self.mdl);
141
142         Net_LinkEntity(self, (self.spawnflags & 4), 0, pointparticles_SendEntity);
143
144         IFTARGETED
145         {
146                 self.use = pointparticles_use;
147                 self.reset = pointparticles_reset;
148                 self.reset();
149         }
150         else
151                 self.state = 1;
152         self.think = pointparticles_think;
153         self.nextthink = time;
154 }
155
156 void spawnfunc_func_sparks()
157 {
158         // self.cnt is the amount of sparks that one burst will spawn
159         if(self.cnt < 1) {
160                 self.cnt = 25.0; // nice default value
161         }
162
163         // self.wait is the probability that a sparkthink will spawn a spark shower
164         // range: 0 - 1, but 0 makes little sense, so...
165         if(self.wait < 0.05) {
166                 self.wait = 0.25; // nice default value
167         }
168
169         self.count = self.cnt;
170         self.mins = '0 0 0';
171         self.maxs = '0 0 0';
172         self.velocity = '0 0 -1';
173         self.mdl = "TE_SPARK";
174         self.impulse = 10 * self.wait; // by default 2.5/sec
175         self.wait = 0;
176         self.cnt = 0; // use mdl
177
178         spawnfunc_func_pointparticles();
179 }
180 #endif