Merge branch 'divVerent/simpler-clipped-rectangle' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mapobjects / func / rainsnow.qc
1 #include "rainsnow.qh"
2 REGISTER_NET_LINKED(ENT_CLIENT_RAINSNOW)
3
4 #ifdef SVQC
5 bool rainsnow_SendEntity(entity this, entity to, float sf)
6 {
7         vector myorg = this.origin + this.mins;
8         vector mysize = this.maxs - this.mins;
9         WriteHeader(MSG_ENTITY, ENT_CLIENT_RAINSNOW);
10         WriteByte(MSG_ENTITY, this.state);
11         WriteVector(MSG_ENTITY, myorg);
12         WriteVector(MSG_ENTITY, mysize);
13         WriteShort(MSG_ENTITY, compressShortVector(this.dest));
14         WriteShort(MSG_ENTITY, this.count);
15         WriteByte(MSG_ENTITY, this.cnt);
16         WriteShort(MSG_ENTITY, bound(0, this.fade_end, 65535));
17         return true;
18 }
19
20 /*QUAKED spawnfunc_func_rain (0 .5 .8) ?
21 This is an invisible area like a trigger, which rain falls inside of.
22
23 Keys:
24 "velocity"
25  falling direction (should be something like '0 0 -700', use the X and Y velocity for wind)
26 "cnt"
27  sets color of rain (default 12 - white)
28 "count"
29  adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
30 */
31 spawnfunc(func_rain)
32 {
33         this.dest = this.velocity;
34         this.velocity = '0 0 0';
35         if (!this.dest)
36                 this.dest = '0 0 -700';
37         this.angles = '0 0 0';
38         set_movetype(this, MOVETYPE_NONE);
39         this.solid = SOLID_NOT;
40         SetBrushEntityModel(this, true);
41         if (!this.cnt)
42         {
43                 this.cnt = 12;
44         }
45         if (!this.count)
46                 this.count = 2000;
47         // relative to absolute particle count
48         //this.count = 0.1 * this.count * (this.size_x / 1024) * (this.size_y / 1024);
49         if (this.count < 1)
50                 this.count = 1;
51         if(this.count > 65535)
52                 this.count = 65535;
53
54         this.state = RAINSNOW_RAIN;
55
56         Net_LinkEntity(this, false, 0, rainsnow_SendEntity);
57 }
58
59
60 /*QUAKED spawnfunc_func_snow (0 .5 .8) ?
61 This is an invisible area like a trigger, which snow falls inside of.
62
63 Keys:
64 "velocity"
65  falling direction (should be something like '0 0 -300', use the X and Y velocity for wind)
66 "cnt"
67  sets color of rain (default 12 - white)
68 "count"
69  adjusts density, this many particles fall every second for a 1024x1024 area, default is 2000
70 */
71 spawnfunc(func_snow)
72 {
73         this.dest = this.velocity;
74         this.velocity = '0 0 0';
75         if (!this.dest)
76                 this.dest = '0 0 -300';
77         this.angles = '0 0 0';
78         set_movetype(this, MOVETYPE_NONE);
79         this.solid = SOLID_NOT;
80         SetBrushEntityModel(this, true);
81         if (!this.cnt)
82         {
83                 this.cnt = 12;
84         }
85         if (!this.count)
86                 this.count = 2000;
87         // relative to absolute particle count
88         //this.count = 0.1 * this.count * (this.size_x / 1024) * (this.size_y / 1024);
89         if (this.count < 1)
90                 this.count = 1;
91         if(this.count > 65535)
92                 this.count = 65535;
93
94         this.state = RAINSNOW_SNOW;
95
96         Net_LinkEntity(this, false, 0, rainsnow_SendEntity);
97 }
98 #elif defined(CSQC)
99 float autocvar_cl_rainsnow_maxdrawdist = 1000;
100
101 void Draw_RainSnow(entity this)
102 {
103         float drawdist = ((this.fade_end) ? this.fade_end : autocvar_cl_rainsnow_maxdrawdist);
104         vector maxdist = '1 1 1' * drawdist;
105
106         vector effbox_min = vec_to_max(view_origin - maxdist, this.origin + this.mins);
107         vector effbox_max = vec_to_min(view_origin + maxdist, this.origin + this.maxs);
108
109         vector mysize = effbox_max - effbox_min;
110         float mycount = bound(1, 0.1 * this.count * (mysize.x / 1024) * (mysize.y / 1024), 65535);
111
112         if(boxesoverlap(view_origin - maxdist, view_origin + maxdist, this.absmin, this.absmax)) // optimisation: don't render any rain if the player is outside the view distance
113         {
114                 if(this.state == RAINSNOW_RAIN)
115                 te_particlerain(effbox_min, effbox_max, this.velocity, floor(mycount * drawframetime + random()), this.glow_color);
116         else
117                 te_particlesnow(effbox_min, effbox_max, this.velocity, floor(mycount * drawframetime + random()), this.glow_color);
118         }
119 }
120
121 NET_HANDLE(ENT_CLIENT_RAINSNOW, bool isnew)
122 {
123         this.state = ReadByte(); // Rain, Snow, or Whatever
124         this.origin = ReadVector();
125         this.maxs = ReadVector();
126         this.velocity = decompressShortVector(ReadShort());
127         this.count = ReadShort();
128         this.glow_color = ReadByte(); // color
129         this.fade_end = ReadShort();
130
131         return = true;
132
133         this.mins    = -0.5 * this.maxs;
134         this.maxs    =  0.5 * this.maxs;
135         this.origin  = this.origin - this.mins;
136
137         setorigin(this, this.origin);
138         setsize(this, this.mins, this.maxs);
139         this.solid = SOLID_NOT;
140         if (isnew) IL_PUSH(g_drawables, this);
141         this.draw = Draw_RainSnow;
142 }
143 #endif