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