]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/g_models.qc
Merge branch 'Mario/mutator_array_fix'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / g_models.qc
1 #include "g_models.qh"
2
3 #include "g_subs.qh"
4 #include <common/net_linked.qh>
5 #include "../common/triggers/subs.qh"
6 #include "../common/triggers/triggers.qh"
7
8 entityclass(BGMScript);
9 class(BGMScript) .string bgmscript;
10 class(BGMScript) .float bgmscriptattack;
11 class(BGMScript) .float bgmscriptdecay;
12 class(BGMScript) .float bgmscriptsustain;
13 class(BGMScript) .float bgmscriptrelease;
14
15 #include "../common/constants.qh"
16 #include "../lib/csqcmodel/sv_model.qh"
17
18 .float modelscale;
19
20 void g_model_setcolormaptoactivator(entity this, entity actor, entity trigger)
21 {
22         if(teamplay)
23         {
24                 if(actor.team)
25                         this.colormap = (actor.team - 1) * 0x11;
26                 else
27                         this.colormap = 0x00;
28         }
29         else
30                 this.colormap = floor(random() * 256);
31         this.colormap |= BIT(10); // RENDER_COLORMAPPED
32 }
33
34 void g_clientmodel_setcolormaptoactivator(entity this, entity actor, entity trigger)
35 {
36         g_model_setcolormaptoactivator(this, actor, trigger);
37         this.SendFlags |= (BIT(3) | BIT(0));
38 }
39
40 void g_clientmodel_use(entity this, entity actor, entity trigger)
41 {
42         if (this.antiwall_flag == 1)
43         {
44                 this.inactive = 1;
45                 this.solid = SOLID_NOT;
46         }
47         else if (this.antiwall_flag == 2)
48         {
49                 this.inactive = 0;
50                 this.solid = this.default_solid;
51         }
52         g_clientmodel_setcolormaptoactivator(this, actor, trigger);
53 }
54
55 void g_model_dropbyspawnflags(entity this)
56 {
57         if((this.spawnflags & 3) == 1) // ALIGN_ORIGIN
58         {
59                 traceline(this.origin, this.origin - '0 0 4096', MOVE_NOMONSTERS, this);
60                 setorigin(this, trace_endpos);
61         }
62         else if((this.spawnflags & 3) == 2) // ALIGN_BOTTOM
63         {
64                 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 4096', MOVE_NOMONSTERS, this);
65                 setorigin(this, trace_endpos);
66         }
67         else if((this.spawnflags & 3) == 3) // ALIGN_ORIGIN | ALIGN_BOTTOM
68         {
69                 traceline(this.origin, this.origin - '0 0 4096', MOVE_NOMONSTERS, this);
70                 setorigin(this, trace_endpos - '0 0 1' * this.mins.z);
71         }
72 }
73
74 void g_clientmodel_dropbyspawnflags(entity this)
75 {
76         vector o0;
77         o0 = this.origin;
78         g_model_dropbyspawnflags(this);
79         if(this.origin != o0)
80                 this.SendFlags |= 2;
81 }
82
83 bool g_clientmodel_genericsendentity(entity this, entity to, int sf)
84 {
85         sf = sf & 0x0F;
86         if(this.angles != '0 0 0')
87                 sf |= 0x10;
88         if(this.mins != '0 0 0' || this.maxs != '0 0 0')
89                 sf |= 0x20;
90         if(this.colormap != 0)
91                 sf |= 0x40;
92         if(this.lodmodelindex1)
93                 sf |= 0x80;
94
95         WriteHeader(MSG_ENTITY, ENT_CLIENT_WALL);
96         WriteByte(MSG_ENTITY, sf);
97
98         if(sf & BIT(0))
99         {
100                 if(sf & 0x40)
101                         WriteShort(MSG_ENTITY, this.colormap);
102                 WriteByte(MSG_ENTITY, this.skin);
103         }
104
105         if(sf & BIT(1))
106         {
107                 WriteCoord(MSG_ENTITY, this.origin.x);
108                 WriteCoord(MSG_ENTITY, this.origin.y);
109                 WriteCoord(MSG_ENTITY, this.origin.z);
110         }
111
112         if(sf & BIT(2))
113         {
114                 if(sf & 0x10)
115                 {
116                         WriteAngle(MSG_ENTITY, this.angles.x);
117                         WriteAngle(MSG_ENTITY, this.angles.y);
118                         WriteAngle(MSG_ENTITY, this.angles.z);
119                 }
120         }
121
122         if(sf & BIT(3))
123         {
124                 if(sf & 0x80)
125                 {
126                         WriteShort(MSG_ENTITY, this.lodmodelindex0);
127                         WriteShort(MSG_ENTITY, bound(0, this.loddistance1, 65535));
128                         WriteShort(MSG_ENTITY, this.lodmodelindex1);
129                         WriteShort(MSG_ENTITY, bound(0, this.loddistance2, 65535));
130                         WriteShort(MSG_ENTITY, this.lodmodelindex2);
131                 }
132                 else
133                         WriteShort(MSG_ENTITY, this.modelindex);
134                 WriteByte(MSG_ENTITY, this.solid);
135                 WriteShort(MSG_ENTITY, floor(this.scale * 256));
136                 if(sf & 0x20)
137                 {
138                         WriteCoord(MSG_ENTITY, this.mins.x);
139                         WriteCoord(MSG_ENTITY, this.mins.y);
140                         WriteCoord(MSG_ENTITY, this.mins.z);
141                         WriteCoord(MSG_ENTITY, this.maxs.x);
142                         WriteCoord(MSG_ENTITY, this.maxs.y);
143                         WriteCoord(MSG_ENTITY, this.maxs.z);
144                 }
145                 WriteString(MSG_ENTITY, this.bgmscript);
146                 if(this.bgmscript != "")
147                 {
148                         WriteByte(MSG_ENTITY, floor(this.bgmscriptattack * 64));
149                         WriteByte(MSG_ENTITY, floor(this.bgmscriptdecay * 64));
150                         WriteByte(MSG_ENTITY, floor(this.bgmscriptsustain * 255));
151                         WriteByte(MSG_ENTITY, floor(this.bgmscriptrelease * 64));
152                         WriteCoord(MSG_ENTITY, this.movedir.x);
153                         WriteCoord(MSG_ENTITY, this.movedir.y);
154                         WriteCoord(MSG_ENTITY, this.movedir.z);
155                         WriteByte(MSG_ENTITY, floor(this.lip * 255));
156                 }
157                 WriteByte(MSG_ENTITY, this.fade_start);
158                 WriteByte(MSG_ENTITY, this.fade_end);
159                 WriteByte(MSG_ENTITY, this.alpha_max);
160                 WriteByte(MSG_ENTITY, this.alpha_min);
161                 WriteByte(MSG_ENTITY, this.inactive);
162                 WriteShort(MSG_ENTITY, this.fade_vertical_offset);
163         }
164
165         return true;
166 }
167
168
169 #define G_MODEL_INIT(ent,sol) \
170         if(ent.geomtype) if(autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")) set_movetype(ent, MOVETYPE_PHYSICS); \
171         if(!ent.scale) ent.scale = ent.modelscale; \
172         SetBrushEntityModel(ent); \
173         ent.use = g_model_setcolormaptoactivator; \
174         InitializeEntity(ent, g_model_dropbyspawnflags, INITPRIO_DROPTOFLOOR); \
175         if(!ent.solid) ent.solid = (sol); else if(ent.solid < 0) ent.solid = SOLID_NOT;
176
177 #define G_CLIENTMODEL_INIT(ent,sol) \
178         if(ent.geomtype) if(autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")) set_movetype(ent, MOVETYPE_PHYSICS); \
179         if(!ent.scale) ent.scale = ent.modelscale; \
180         SetBrushEntityModel(ent); \
181         ent.use = g_clientmodel_use; \
182         InitializeEntity(ent, g_clientmodel_dropbyspawnflags, INITPRIO_DROPTOFLOOR); \
183         if(!ent.solid) ent.solid = (sol); else if(ent.solid < 0) ent.solid = SOLID_NOT; \
184         if(!ent.bgmscriptsustain) ent.bgmscriptsustain = 1; else if(ent.bgmscriptsustain < 0) ent.bgmscriptsustain = 0; \
185         Net_LinkEntity(ent, true, 0, g_clientmodel_genericsendentity); \
186         ent.default_solid = sol;
187
188 // non-solid model entities:
189 spawnfunc(misc_gamemodel)         { this.angles_x = -this.angles.x; G_MODEL_INIT      (this, SOLID_NOT) } // model entity
190 spawnfunc(misc_clientmodel)       { this.angles_x = -this.angles.x; G_CLIENTMODEL_INIT(this, SOLID_NOT) } // model entity
191 spawnfunc(misc_models)            { this.angles_x = -this.angles.x; G_MODEL_INIT      (this, SOLID_NOT) } // DEPRECATED old compat entity with confusing name, do not use
192
193 // non-solid brush entities:
194 spawnfunc(func_illusionary)       { G_MODEL_INIT      (this, SOLID_NOT) } // Q1 name (WARNING: MISPREDICTED)
195 spawnfunc(func_clientillusionary) { G_CLIENTMODEL_INIT(this, SOLID_NOT) } // brush entity
196 spawnfunc(func_static)            { G_MODEL_INIT      (this, SOLID_NOT) } // DEPRECATED old alias name from some other game
197
198 // solid brush entities
199 spawnfunc(func_wall)              { G_MODEL_INIT      (this, SOLID_BSP) } // Q1 name
200 spawnfunc(func_clientwall)        { G_CLIENTMODEL_INIT(this, SOLID_BSP) } // brush entity (WARNING: MISPREDICTED)