MCPcopy Create free account
hub / github.com/assaultcube/AC / mmcollide

Function mmcollide

source/src/physics.cpp:134–194  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

132static int cornersurface = 0;
133
134bool mmcollide(physent *d, float &hi, float &lo) // collide with a mapmodel
135{
136 const float eyeheight = d->eyeheight, SQRT2HALF = SQRT2 / 2.0f;
137 const float playerheight = eyeheight + d->aboveeye;
138 if(editmode) clentstats.firstclip = 0;
139 for(int i = clentstats.firstclip; i < ents.length(); i++)
140 {
141 entity &e = ents[i];
142 if (e.type==CLIP || (e.type == PLCLIP && (d->type == ENT_BOT || d->type == ENT_PLAYER || (d->type == ENT_BOUNCE && ((bounceent *)d)->plclipped))))
143 {
144 bool hitarea = false;
145 switch(e.attr7 & 3)
146 {
147 default: // classic unrotated clip, possibly tilted
148 hitarea = (fabs(e.x - d->o.x) - (float(e.attr2) / ENTSCALE5 + d->radius) < 1e-5) && (fabs(e.y - d->o.y) - (float(e.attr3) / ENTSCALE5 + d->radius) < 1e-5); // fix PLCLIP-step-up bug where e.g. 2.1<=2.1 was FALSE [sic!]
149 break;
150 case 3: // clip rotated 45°
151 {
152 float rx = (e.x - d->o.x) * SQRT2HALF, ry = (e.y - d->o.y) * SQRT2HALF, rr = d->radius * SQRT2; // rotate player instead of clip (adjust player radius to compensate)
153 float a1 = fabs(rx - ry) - float(e.attr3) / ENTSCALE5 - rr, a2 = fabs(rx + ry) - float(e.attr2) / ENTSCALE5 - rr;
154 if(a1 < 0 && a2 < 0)
155 {
156 float a3 = a1 + a2 + rr;
157 if(a3 < 0) hitarea = true;
158 if(a3 < -1e-2 && (a3 < -rr || a1 * a2 < 0.42f)) cornersurface = a1 > a2 ? 1 : 2;
159 }
160 break;
161 }
162 }
163 if(hitarea)
164 {
165 float cz = float(S(e.x, e.y)->floor + float(e.attr1) / ENTSCALE10), ch = float(e.attr4) / ENTSCALE5;
166 if(e.attr6) switch(e.attr7 & 3)
167 { // incredibly ugly solution - but it only applies on the one tilted clip we stand on
168 case 1: cz += (floor(0.5f + clamp(d->o.x - e.x + d->radius * (e.attr6 > 0 ? 1 : -1), -float(e.attr2) / ENTSCALE5, float(e.attr2) / ENTSCALE5))) * float(e.attr6) / (4 * ENTSCALE10); break; // tilt x
169 case 2: cz += (floor(0.5f + clamp(d->o.y - e.y + d->radius * (e.attr6 > 0 ? 1 : -1), -float(e.attr3) / ENTSCALE5, float(e.attr3) / ENTSCALE5))) * float(e.attr6) / (4 * ENTSCALE10); break; // tilt y
170 }
171 const float dz = d->o.z - d->eyeheight;
172 if(dz < cz - 0.42) { if(cz<hi) hi = cz; }
173 else if(cz+ch>lo) lo = cz+ch;
174 if(hi-lo < playerheight) return true;
175 if(dz + (d->type != ENT_BOUNCE ? 1.26 : 0) > cz + ch || dz + playerheight < cz) cornersurface = 0;
176 }
177 }
178 else if(e.type==MAPMODEL)
179 {
180 mapmodelinfo *mmi = getmminfo(e.attr2);
181 if(!mmi || !mmi->h) continue;
182 const float r = mmi->rad + d->radius;
183 if(fabs(e.x-d->o.x)<r && fabs(e.y-d->o.y)<r)
184 {
185 const float mmz = float(S(e.x, e.y)->floor + mmi->zoff + float(e.attr3) / ENTSCALE5);
186 const float dz = d->o.z-eyeheight;
187 if(dz < mmz - 0.42) { if(mmz < hi) hi = mmz; }
188 else if(mmz + mmi->h > lo) lo = mmz + mmi->h;
189 if(hi-lo < playerheight) return true;
190 }
191 }

Callers 1

collideFunction · 0.85

Calls 2

getmminfoFunction · 0.85
lengthMethod · 0.45

Tested by

no test coverage detected