]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/csqcmodel.qc
a178e6c1c30324214c9c36acb3eb3d619bed4971
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / csqcmodel.qc
1 // generic CSQC model code
2
3 .vector glowmod;
4 .vector view_ofs;
5
6 #define ALLPROPERTIES \
7         PROPERTY(1, ReadCoord, WriteCoord, origin_x) \
8         PROPERTY(1, ReadCoord, WriteCoord, origin_y) \
9         PROPERTY(1, ReadCoord, WriteCoord, origin_z) \
10         PROPERTY(2, ReadAngle, WriteAngle, angles_x) \
11         PROPERTY(2, ReadAngle, WriteAngle, angles_y) \
12         PROPERTY(2, ReadAngle, WriteAngle, angles_z) \
13         PROPERTY(4, ReadShort, WriteShort, modelindex) \
14         PROPERTY(8, ReadByte, WriteByte, frame) \
15         PROPERTY(16, ReadByte, WriteByte, skin) \
16         PROPERTY(32, ReadInt24_t, WriteInt24_t, effects) \
17         PROPERTY_SCALED(64, ReadByte, WriteByte, alpha, 255, 0, 255) \
18         PROPERTY_SCALED(128, ReadByte, WriteByte, glowmod_x, 32, 0, 255) \
19         PROPERTY_SCALED(128, ReadByte, WriteByte, glowmod_y, 32, 0, 255) \
20         PROPERTY_SCALED(128, ReadByte, WriteByte, glowmod_z, 32, 0, 255) \
21         PROPERTY(256, ReadChar, WriteChar, view_ofs_z) \
22         PROPERTY(512, ReadShort, WriteShort, colormap)
23
24 #ifdef SVQC
25
26 #define PROPERTY(flag,r,w,f) \
27         .float csqcmodel_##f;
28 #define PROPERTY_SCALED(flag,r,w,f,s,mi,ma) PROPERTY(flag,r,w,f)
29         ALLPROPERTIES
30 #undef PROPERTY_SCALED
31 #undef PROPERTY
32
33 float CSQCModel_Send(entity to, float sf)
34 {
35         WriteByte(MSG_ENTITY, ENT_CLIENT_MODEL);
36         WriteShort(MSG_ENTITY, sf);
37
38 #define PROPERTY(flag,r,w,f) \
39         if(sf & flag) \
40         { \
41                 w(MSG_ENTITY, self.csqcmodel_##f); \
42         }
43 #define PROPERTY_SCALED(flag,r,w,f,s,mi,ma) PROPERTY(flag,r,w,f)
44         ALLPROPERTIES
45 #undef PROPERTY_SCALED
46 #undef PROPERTY
47
48         return TRUE;
49 }
50
51 void CSQCModel_CheckUpdate()
52 {
53         float tmp;
54 #define PROPERTY(flag,r,w,f) \
55         tmp = self.f; \
56         if(tmp != self.csqcmodel_##f) \
57         { \
58                 self.csqcmodel_##f = tmp; \
59                 self.SendFlags |= flag; \
60         }
61 #define PROPERTY_SCALED(flag,r,w,f,s,mi,ma) \
62         tmp = bound(mi, s * self.f, ma); \
63         if(tmp != self.csqcmodel_##f) \
64         { \
65                 self.csqcmodel_##f = tmp; \
66                 self.SendFlags |= flag; \
67         }
68         ALLPROPERTIES
69 #undef PROPERTY_SCALED
70 #undef PROPERTY
71 }
72
73 void CSQCModel_LinkEntity()
74 {
75         Net_LinkEntity(self, TRUE, 0, CSQCModel_Send);
76 }
77
78 #endif
79
80 #ifdef CSQC
81
82 void CSQCModel_Draw()
83 {
84         InterpolateOrigin_Do();
85 }
86
87
88 vector player_org, player_vel;
89 float player_sequence, player_pmflags;
90 float pmoveframe;
91 .float pmove_flags;
92 void Unpredict()
93 {
94         self.origin = player_org;
95         self.velocity = player_vel;
96         pmoveframe = player_sequence+1; //+1 because the recieved frame has the move already done (server side)
97         self.pmove_flags = player_pmflags;
98         if (pmoveframe < clientcommandframe-128)
99                 pmoveframe = clientcommandframe-128; // don't want to loop infinitely
100 }
101
102 void PredictTo(float endframe)
103 {
104         if(servercommandframe >= player_sequence+63)
105         {
106                 player_sequence = servercommandframe+63; // freeze laggers
107                 return;
108         }
109
110         Unpredict();
111
112         if (getstatf(STAT_HEALTH) <= 0)
113         {
114                 pmoveframe = clientcommandframe;
115                 getinputstate(pmoveframe-1);
116                 return;
117         }
118
119         while(pmoveframe < endframe)
120         {
121                 if (!getinputstate(pmoveframe))
122                 {
123                         break;
124                 }
125                 runstandardplayerphysics(self);
126
127                 pmoveframe++;
128         }
129
130         //add in anything that was applied after (for low packet rate protocols)
131         input_angles = view_angles;
132 }
133
134 entity csqcmodel_me;
135 float autocvar_chase_active;
136 float autocvar_chase_back;
137 void CSQCModel_SetCamera()
138 {
139         if(csqcmodel_me)
140         {
141                 vector org, ang;
142                 entity oldself;
143                 oldself = self;
144                 self = csqcmodel_me;
145                 PredictTo(clientcommandframe);
146                 self = oldself;
147
148                 org = csqcmodel_me.origin + csqcmodel_me.view_ofs;
149                 ang = R_SetView3fv(VF_ANGLES);
150
151                 // simulate missing engine features
152                 if(autocvar_chase_active)
153                 {
154                         float dist;
155                         vector chase_dest;
156                         dist = -autocvar_chase_back - 8;
157                         makevectors(ang);
158                         chase_dest = org + v_forward * dist;
159                         traceline(org, chase_dest, MOVE_NOMONSTERS, csqcmodel_me);
160                         org = trace_endpos + 8 * v_forward + 4 * trace_plane_normal;
161                 }
162
163                 R_SetView3fv(VF_ORIGIN, org);
164                 R_SetView3fv(VF_ANGLES, ang);
165         }
166 }
167
168 void CSQCModel_Read()
169 {
170         float sf;
171         sf = ReadShort();
172
173         if(self.entnum == player_localentnum)
174                 Unpredict();
175         else
176                 InterpolateOrigin_Undo();
177
178 #define PROPERTY(flag,r,w,f) \
179         if(sf & flag) \
180                 self.f = r();
181 #define PROPERTY_SCALED(flag,r,w,f,s,mi,ma) \
182         if(sf & flag) \
183                 self.f = r() / s;
184         ALLPROPERTIES
185 #undef PROPERTY_SCALED
186 #undef PROPERTY
187         
188         // interpolation
189         if(self.entnum == player_localentnum)
190         {
191                 vector o, v;
192                 o = self.origin;
193                 v = self.velocity;
194                 csqcmodel_me = self;
195                 PredictTo(servercommandframe + 1);
196                 player_pmflags = self.pmove_flags;
197                 player_org = o;
198                 player_vel = v;
199                 player_sequence = servercommandframe;
200                 Unpredict();
201         }
202         else
203                 InterpolateOrigin_Note();
204
205         // draw it
206         if(self.entnum <= maxclients)
207                 self.renderflags = RF_EXTERNALMODEL;
208         self.drawmask = MASK_NORMAL;
209         self.predraw = CSQCModel_Draw;
210 }
211
212 #endif