Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rubberduckycooly
GitHub Repository: rubberduckycooly/Sonic-1-2-2013-Decompilation
Path: blob/main/RSDKv4/Collision.cpp
817 views
1
#include "RetroEngine.hpp"
2
3
int collisionLeft = 0;
4
int collisionTop = 0;
5
int collisionRight = 0;
6
int collisionBottom = 0;
7
8
int collisionTolerance = 0;
9
10
CollisionSensor sensors[RETRO_REV00 ? 6 : 7];
11
12
#if !RETRO_USE_ORIGINAL_CODE
13
byte showHitboxes = 0;
14
15
int debugHitboxCount = 0;
16
DebugHitboxInfo debugHitboxList[DEBUG_HITBOX_COUNT];
17
18
int AddDebugHitbox(byte type, Entity *entity, int left, int top, int right, int bottom)
19
{
20
int i = 0;
21
for (; i < debugHitboxCount; ++i) {
22
if (debugHitboxList[i].left == left && debugHitboxList[i].top == top && debugHitboxList[i].right == right
23
&& debugHitboxList[i].bottom == bottom
24
&& (entity && debugHitboxList[i].xpos == entity->xpos && debugHitboxList[i].ypos == entity->ypos
25
&& debugHitboxList[i].entity == entity)) {
26
return i;
27
}
28
}
29
30
if (i < DEBUG_HITBOX_COUNT) {
31
debugHitboxList[i].type = type;
32
debugHitboxList[i].entity = entity;
33
debugHitboxList[i].collision = 0;
34
debugHitboxList[i].left = left;
35
debugHitboxList[i].top = top;
36
debugHitboxList[i].right = right;
37
debugHitboxList[i].bottom = bottom;
38
debugHitboxList[i].xpos = entity ? entity->xpos : 0;
39
debugHitboxList[i].ypos = entity ? entity->ypos : 0;
40
41
int id = debugHitboxCount;
42
debugHitboxCount++;
43
return id;
44
}
45
46
return -1;
47
}
48
#endif
49
50
inline Hitbox *GetHitbox(Entity *entity)
51
{
52
AnimationFile *thisAnim = objectScriptList[entity->type].animFile;
53
return &hitboxList[thisAnim->hitboxListOffset
54
+ animFrames[animationList[thisAnim->aniListOffset + entity->animation].frameListOffset + entity->frame].hitboxID];
55
}
56
57
void FindFloorPosition(Entity *player, CollisionSensor *sensor, int startY)
58
{
59
int c = 0;
60
int angle = sensor->angle;
61
int tsm1 = (TILE_SIZE - 1);
62
for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {
63
if (!sensor->collided) {
64
int XPos = sensor->xpos >> 16;
65
int chunkX = XPos >> 7;
66
int tileX = (XPos & 0x7F) >> 4;
67
int YPos = (sensor->ypos >> 16) - TILE_SIZE + i;
68
int chunkY = YPos >> 7;
69
int tileY = (YPos & 0x7F) >> 4;
70
if (XPos > -1 && YPos > -1) {
71
int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;
72
tile += tileX + (tileY << 3);
73
int tileIndex = tiles128x128.tileIndex[tile];
74
if (tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_LRB
75
&& tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_NONE) {
76
switch (tiles128x128.direction[tile]) {
77
case FLIP_NONE: {
78
c = (XPos & tsm1) + (tileIndex << 4);
79
if (collisionMasks[player->collisionPlane].floorMasks[c] >= 0x40)
80
break;
81
82
sensor->ypos = collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);
83
sensor->collided = true;
84
sensor->angle = collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF;
85
break;
86
}
87
case FLIP_X: {
88
c = tsm1 - (XPos & tsm1) + (tileIndex << 4);
89
if (collisionMasks[player->collisionPlane].floorMasks[c] >= 0x40)
90
break;
91
92
sensor->ypos = collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);
93
sensor->collided = true;
94
sensor->angle = 0x100 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF);
95
break;
96
}
97
case FLIP_Y: {
98
c = (XPos & 15) + (tileIndex << 4);
99
if (collisionMasks[player->collisionPlane].roofMasks[c] <= -0x40)
100
break;
101
102
sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);
103
sensor->collided = true;
104
sensor->angle = (byte)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24));
105
break;
106
}
107
case FLIP_XY: {
108
c = tsm1 - (XPos & tsm1) + (tileIndex << 4);
109
if (collisionMasks[player->collisionPlane].roofMasks[c] <= -0x40)
110
break;
111
112
sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);
113
sensor->collided = true;
114
sensor->angle = 0x100 - (byte)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24));
115
break;
116
}
117
}
118
}
119
120
if (sensor->collided) {
121
if (sensor->angle < 0)
122
sensor->angle += 0x100;
123
124
if (sensor->angle >= 0x100)
125
sensor->angle -= 0x100;
126
127
if ((abs(sensor->angle - angle) > 0x20) && (abs(sensor->angle - 0x100 - angle) > 0x20)
128
&& (abs(sensor->angle + 0x100 - angle) > 0x20)) {
129
sensor->ypos = startY << 16;
130
sensor->collided = false;
131
sensor->angle = angle;
132
i = TILE_SIZE * 3;
133
}
134
else if (sensor->ypos - startY > collisionTolerance || sensor->ypos - startY < -collisionTolerance) {
135
sensor->ypos = startY << 16;
136
sensor->collided = false;
137
}
138
}
139
}
140
}
141
}
142
}
143
void FindLWallPosition(Entity *player, CollisionSensor *sensor, int startX)
144
{
145
int c = 0;
146
int angle = sensor->angle;
147
int tsm1 = (TILE_SIZE - 1);
148
for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {
149
if (!sensor->collided) {
150
int XPos = (sensor->xpos >> 16) - TILE_SIZE + i;
151
int chunkX = XPos >> 7;
152
int tileX = (XPos & 0x7F) >> 4;
153
int YPos = sensor->ypos >> 16;
154
int chunkY = YPos >> 7;
155
int tileY = (YPos & 0x7F) >> 4;
156
if (XPos > -1 && YPos > -1) {
157
int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;
158
tile = tile + tileX + (tileY << 3);
159
int tileIndex = tiles128x128.tileIndex[tile];
160
if (tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {
161
switch (tiles128x128.direction[tile]) {
162
case FLIP_NONE: {
163
c = (YPos & tsm1) + (tileIndex << 4);
164
if (collisionMasks[player->collisionPlane].lWallMasks[c] >= 0x40)
165
break;
166
167
sensor->xpos = collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
168
sensor->collided = true;
169
sensor->angle = ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF00) >> 8);
170
break;
171
}
172
case FLIP_X: {
173
c = (YPos & tsm1) + (tileIndex << 4);
174
if (collisionMasks[player->collisionPlane].rWallMasks[c] <= -0x40)
175
break;
176
177
sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
178
sensor->collided = true;
179
sensor->angle = 0x100 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF0000) >> 16);
180
break;
181
}
182
case FLIP_Y: {
183
c = tsm1 - (YPos & tsm1) + (tileIndex << 4);
184
if (collisionMasks[player->collisionPlane].lWallMasks[c] >= 0x40)
185
break;
186
187
sensor->xpos = collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
188
sensor->collided = true;
189
sensor->angle = (byte)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF00) >> 8));
190
break;
191
}
192
case FLIP_XY: {
193
c = tsm1 - (YPos & tsm1) + (tileIndex << 4);
194
if (collisionMasks[player->collisionPlane].rWallMasks[c] <= -0x40)
195
break;
196
197
sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
198
sensor->collided = true;
199
sensor->angle = 0x100 - (byte)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF0000) >> 16));
200
break;
201
}
202
}
203
}
204
if (sensor->collided) {
205
if (sensor->angle < 0)
206
sensor->angle += 0x100;
207
208
if (sensor->angle >= 0x100)
209
sensor->angle -= 0x100;
210
211
if (abs(angle - sensor->angle) > 0x20) {
212
sensor->xpos = startX << 16;
213
sensor->collided = false;
214
sensor->angle = angle;
215
i = TILE_SIZE * 3;
216
}
217
else if (sensor->xpos - startX > collisionTolerance || sensor->xpos - startX < -collisionTolerance) {
218
sensor->xpos = startX << 16;
219
sensor->collided = false;
220
}
221
}
222
}
223
}
224
}
225
}
226
void FindRoofPosition(Entity *player, CollisionSensor *sensor, int startY)
227
{
228
int c = 0;
229
int angle = sensor->angle;
230
int tsm1 = (TILE_SIZE - 1);
231
for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {
232
if (!sensor->collided) {
233
int XPos = sensor->xpos >> 16;
234
int chunkX = XPos >> 7;
235
int tileX = (XPos & 0x7F) >> 4;
236
int YPos = (sensor->ypos >> 16) + TILE_SIZE - i;
237
int chunkY = YPos >> 7;
238
int tileY = (YPos & 0x7F) >> 4;
239
if (XPos > -1 && YPos > -1) {
240
int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;
241
tile = tile + tileX + (tileY << 3);
242
int tileIndex = tiles128x128.tileIndex[tile];
243
if (tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {
244
switch (tiles128x128.direction[tile]) {
245
case FLIP_NONE: {
246
c = (XPos & tsm1) + (tileIndex << 4);
247
if (collisionMasks[player->collisionPlane].roofMasks[c] <= -0x40)
248
break;
249
250
sensor->ypos = collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);
251
sensor->collided = true;
252
sensor->angle = (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24;
253
break;
254
}
255
case FLIP_X: {
256
c = tsm1 - (XPos & tsm1) + (tileIndex << 4);
257
if (collisionMasks[player->collisionPlane].roofMasks[c] <= -0x40)
258
break;
259
260
sensor->ypos = collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);
261
sensor->collided = true;
262
sensor->angle = 0x100 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24);
263
break;
264
}
265
case FLIP_Y: {
266
c = (XPos & tsm1) + (tileIndex << 4);
267
if (collisionMasks[player->collisionPlane].floorMasks[c] >= 0x40)
268
break;
269
270
sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);
271
sensor->collided = true;
272
sensor->angle = (byte)(0x180 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF));
273
break;
274
}
275
case FLIP_XY: {
276
c = tsm1 - (XPos & tsm1) + (tileIndex << 4);
277
if (collisionMasks[player->collisionPlane].floorMasks[c] >= 0x40)
278
break;
279
280
sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);
281
sensor->collided = true;
282
sensor->angle = 0x100 - (byte)(0x180 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF));
283
break;
284
}
285
}
286
}
287
288
if (sensor->collided) {
289
if (sensor->angle < 0)
290
sensor->angle += 0x100;
291
292
if (sensor->angle >= 0x100)
293
sensor->angle -= 0x100;
294
295
if (abs(sensor->angle - angle) <= 0x20) {
296
if (sensor->ypos - startY > collisionTolerance || sensor->ypos - startY < -collisionTolerance) {
297
sensor->ypos = startY << 16;
298
sensor->collided = false;
299
}
300
}
301
else {
302
sensor->ypos = startY << 16;
303
sensor->collided = false;
304
sensor->angle = angle;
305
i = TILE_SIZE * 3;
306
}
307
}
308
}
309
}
310
}
311
}
312
void FindRWallPosition(Entity *player, CollisionSensor *sensor, int startX)
313
{
314
int c;
315
int angle = sensor->angle;
316
int tsm1 = (TILE_SIZE - 1);
317
for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {
318
if (!sensor->collided) {
319
int XPos = (sensor->xpos >> 16) + TILE_SIZE - i;
320
int chunkX = XPos >> 7;
321
int tileX = (XPos & 0x7F) >> 4;
322
int YPos = sensor->ypos >> 16;
323
int chunkY = YPos >> 7;
324
int tileY = (YPos & 0x7F) >> 4;
325
if (XPos > -1 && YPos > -1) {
326
int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;
327
tile = tile + tileX + (tileY << 3);
328
int tileIndex = tiles128x128.tileIndex[tile];
329
if (tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {
330
switch (tiles128x128.direction[tile]) {
331
case FLIP_NONE: {
332
c = (YPos & tsm1) + (tileIndex << 4);
333
if (collisionMasks[player->collisionPlane].rWallMasks[c] <= -0x40)
334
break;
335
336
sensor->xpos = collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
337
sensor->collided = true;
338
sensor->angle = (byte)((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF0000) >> 16);
339
break;
340
}
341
case FLIP_X: {
342
c = (YPos & tsm1) + (tileIndex << 4);
343
if (collisionMasks[player->collisionPlane].lWallMasks[c] >= 0x40)
344
break;
345
346
sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
347
sensor->collided = true;
348
sensor->angle = 0x100 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF00) >> 8);
349
break;
350
}
351
case FLIP_Y: {
352
c = tsm1 - (YPos & tsm1) + (tileIndex << 4);
353
if (collisionMasks[player->collisionPlane].rWallMasks[c] <= -0x40)
354
break;
355
356
sensor->xpos = collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
357
sensor->collided = true;
358
sensor->angle = (byte)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF0000) >> 16));
359
break;
360
}
361
case FLIP_XY: {
362
c = tsm1 - (YPos & tsm1) + (tileIndex << 4);
363
if (collisionMasks[player->collisionPlane].lWallMasks[c] >= 0x40)
364
break;
365
366
sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
367
sensor->collided = true;
368
sensor->angle = 0x100 - (byte)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF00) >> 8));
369
break;
370
}
371
}
372
}
373
if (sensor->collided) {
374
if (sensor->angle < 0)
375
sensor->angle += 0x100;
376
377
if (sensor->angle >= 0x100)
378
sensor->angle -= 0x100;
379
380
if (abs(sensor->angle - angle) > 0x20) {
381
sensor->xpos = startX << 16;
382
sensor->collided = false;
383
sensor->angle = angle;
384
i = TILE_SIZE * 3;
385
}
386
else if (sensor->xpos - startX > collisionTolerance || sensor->xpos - startX < -collisionTolerance) {
387
sensor->xpos = startX << 16;
388
sensor->collided = false;
389
}
390
}
391
}
392
}
393
}
394
}
395
396
void FloorCollision(Entity *player, CollisionSensor *sensor)
397
{
398
int c;
399
int startY = sensor->ypos >> 16;
400
int tsm1 = (TILE_SIZE - 1);
401
for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {
402
if (!sensor->collided) {
403
int XPos = sensor->xpos >> 16;
404
int chunkX = XPos >> 7;
405
int tileX = (XPos & 0x7F) >> 4;
406
int YPos = (sensor->ypos >> 16) - TILE_SIZE + i;
407
int chunkY = YPos >> 7;
408
int tileY = (YPos & 0x7F) >> 4;
409
if (XPos > -1 && YPos > -1) {
410
int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;
411
tile += tileX + (tileY << 3);
412
int tileIndex = tiles128x128.tileIndex[tile];
413
if (tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_LRB
414
&& tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_NONE) {
415
switch (tiles128x128.direction[tile]) {
416
case FLIP_NONE: {
417
c = (XPos & tsm1) + (tileIndex << 4);
418
if ((YPos & tsm1) <= collisionMasks[player->collisionPlane].floorMasks[c] - TILE_SIZE + i
419
|| collisionMasks[player->collisionPlane].floorMasks[c] >= tsm1)
420
break;
421
422
sensor->ypos = collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);
423
sensor->collided = true;
424
sensor->angle = collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF;
425
break;
426
}
427
case FLIP_X: {
428
c = tsm1 - (XPos & tsm1) + (tileIndex << 4);
429
if ((YPos & tsm1) <= collisionMasks[player->collisionPlane].floorMasks[c] - TILE_SIZE + i
430
|| collisionMasks[player->collisionPlane].floorMasks[c] >= tsm1)
431
break;
432
433
sensor->ypos = collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);
434
sensor->collided = true;
435
sensor->angle = 0x100 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF);
436
break;
437
}
438
case FLIP_Y: {
439
c = (XPos & tsm1) + (tileIndex << 4);
440
if ((YPos & tsm1) <= tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] - TILE_SIZE + i)
441
break;
442
443
sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);
444
sensor->collided = true;
445
byte cAngle = (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24;
446
sensor->angle = (byte)(0x180 - cAngle);
447
break;
448
}
449
case FLIP_XY: {
450
c = tsm1 - (XPos & tsm1) + (tileIndex << 4);
451
if ((YPos & tsm1) <= tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] - TILE_SIZE + i)
452
break;
453
454
sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);
455
sensor->collided = true;
456
sensor->angle = 0x100 - (byte)(0x180 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24));
457
break;
458
}
459
}
460
}
461
462
if (sensor->collided) {
463
if (sensor->angle < 0)
464
sensor->angle += 0x100;
465
466
if (sensor->angle >= 0x100)
467
sensor->angle -= 0x100;
468
469
if (sensor->ypos - startY > (TILE_SIZE - 2)) {
470
sensor->ypos = startY << 16;
471
sensor->collided = false;
472
}
473
else if (sensor->ypos - startY < -(TILE_SIZE + 1)) {
474
sensor->ypos = startY << 16;
475
sensor->collided = false;
476
}
477
}
478
}
479
}
480
}
481
}
482
void LWallCollision(Entity *player, CollisionSensor *sensor)
483
{
484
int c;
485
int startX = sensor->xpos >> 16;
486
int tsm1 = (TILE_SIZE - 1);
487
for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {
488
if (!sensor->collided) {
489
int XPos = (sensor->xpos >> 16) - TILE_SIZE + i;
490
int chunkX = XPos >> 7;
491
int tileX = (XPos & 0x7F) >> 4;
492
int YPos = sensor->ypos >> 16;
493
int chunkY = YPos >> 7;
494
int tileY = (YPos & 0x7F) >> 4;
495
if (XPos > -1 && YPos > -1) {
496
int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;
497
tile += tileX + (tileY << 3);
498
int tileIndex = tiles128x128.tileIndex[tile];
499
if (tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_TOP
500
&& tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {
501
switch (tiles128x128.direction[tile]) {
502
case FLIP_NONE: {
503
c = (YPos & tsm1) + (tileIndex << 4);
504
if ((XPos & tsm1) <= collisionMasks[player->collisionPlane].lWallMasks[c] - TILE_SIZE + i)
505
break;
506
507
sensor->xpos = collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
508
sensor->collided = true;
509
break;
510
}
511
case FLIP_X: {
512
c = (YPos & tsm1) + (tileIndex << 4);
513
if ((XPos & tsm1) <= tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] - TILE_SIZE + i)
514
break;
515
516
sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
517
sensor->collided = true;
518
break;
519
}
520
case FLIP_Y: {
521
c = tsm1 - (YPos & tsm1) + (tileIndex << 4);
522
if ((XPos & tsm1) <= collisionMasks[player->collisionPlane].lWallMasks[c] - TILE_SIZE + i)
523
break;
524
525
sensor->xpos = collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
526
sensor->collided = true;
527
break;
528
}
529
case FLIP_XY: {
530
c = tsm1 - (YPos & tsm1) + (tileIndex << 4);
531
if ((XPos & tsm1) <= tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] - TILE_SIZE + i)
532
break;
533
534
sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
535
sensor->collided = true;
536
break;
537
}
538
}
539
}
540
541
if (sensor->collided) {
542
if (sensor->xpos - startX > tsm1) {
543
sensor->xpos = startX << 16;
544
sensor->collided = false;
545
}
546
else if (sensor->xpos - startX < -tsm1) {
547
sensor->xpos = startX << 16;
548
sensor->collided = false;
549
}
550
}
551
}
552
}
553
}
554
}
555
void RoofCollision(Entity *player, CollisionSensor *sensor)
556
{
557
int c;
558
int startY = sensor->ypos >> 16;
559
int tsm1 = (TILE_SIZE - 1);
560
for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {
561
if (!sensor->collided) {
562
int XPos = sensor->xpos >> 16;
563
int chunkX = XPos >> 7;
564
int tileX = (XPos & 0x7F) >> 4;
565
int YPos = (sensor->ypos >> 16) + TILE_SIZE - i;
566
int chunkY = YPos >> 7;
567
int tileY = (YPos & 0x7F) >> 4;
568
if (XPos > -1 && YPos > -1) {
569
int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;
570
tile += tileX + (tileY << 3);
571
int tileIndex = tiles128x128.tileIndex[tile];
572
if (tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_TOP
573
&& tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {
574
switch (tiles128x128.direction[tile]) {
575
case FLIP_NONE: {
576
c = (XPos & tsm1) + (tileIndex << 4);
577
if ((YPos & tsm1) >= collisionMasks[player->collisionPlane].roofMasks[c] + TILE_SIZE - i)
578
break;
579
580
sensor->ypos = collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);
581
sensor->collided = true;
582
sensor->angle = ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24);
583
break;
584
}
585
case FLIP_X: {
586
c = tsm1 - (XPos & tsm1) + (tileIndex << 4);
587
if ((YPos & tsm1) >= collisionMasks[player->collisionPlane].roofMasks[c] + TILE_SIZE - i)
588
break;
589
590
sensor->ypos = collisionMasks[player->collisionPlane].roofMasks[c] + (chunkY << 7) + (tileY << 4);
591
sensor->collided = true;
592
sensor->angle = 0x100 - ((collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF000000) >> 24);
593
break;
594
}
595
case FLIP_Y: {
596
c = (XPos & tsm1) + (tileIndex << 4);
597
if ((YPos & tsm1) >= tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + TILE_SIZE - i)
598
break;
599
600
sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);
601
sensor->collided = true;
602
sensor->angle = 0x180 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF);
603
break;
604
}
605
case FLIP_XY: {
606
c = tsm1 - (XPos & tsm1) + (tileIndex << 4);
607
if ((YPos & tsm1) >= tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + TILE_SIZE - i)
608
break;
609
610
sensor->ypos = tsm1 - collisionMasks[player->collisionPlane].floorMasks[c] + (chunkY << 7) + (tileY << 4);
611
sensor->collided = true;
612
sensor->angle = 0x100 - (byte)(0x180 - (collisionMasks[player->collisionPlane].angles[tileIndex] & 0xFF));
613
break;
614
}
615
}
616
}
617
618
if (sensor->collided) {
619
if (sensor->angle < 0)
620
sensor->angle += 0x100;
621
622
if (sensor->angle >= 0x100)
623
sensor->angle -= 0x100;
624
625
if (sensor->ypos - startY > (tsm1 - 1)) {
626
sensor->ypos = startY << 16;
627
sensor->collided = false;
628
}
629
else if (sensor->ypos - startY < -(tsm1 - 1)) {
630
sensor->ypos = startY << 16;
631
sensor->collided = false;
632
}
633
}
634
}
635
}
636
}
637
}
638
void RWallCollision(Entity *player, CollisionSensor *sensor)
639
{
640
int c;
641
int startX = sensor->xpos >> 16;
642
int tsm1 = (TILE_SIZE - 1);
643
for (int i = 0; i < TILE_SIZE * 3; i += TILE_SIZE) {
644
if (!sensor->collided) {
645
int XPos = (sensor->xpos >> 16) + TILE_SIZE - i;
646
int chunkX = XPos >> 7;
647
int tileX = (XPos & 0x7F) >> 4;
648
int YPos = sensor->ypos >> 16;
649
int chunkY = YPos >> 7;
650
int tileY = (YPos & 0x7F) >> 4;
651
if (XPos > -1 && YPos > -1) {
652
int tile = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;
653
tile += tileX + (tileY << 3);
654
int tileIndex = tiles128x128.tileIndex[tile];
655
if (tiles128x128.collisionFlags[player->collisionPlane][tile] != SOLID_TOP
656
&& tiles128x128.collisionFlags[player->collisionPlane][tile] < SOLID_NONE) {
657
switch (tiles128x128.direction[tile]) {
658
case FLIP_NONE: {
659
c = (YPos & tsm1) + (tileIndex << 4);
660
if ((XPos & tsm1) >= collisionMasks[player->collisionPlane].rWallMasks[c] + TILE_SIZE - i)
661
break;
662
663
sensor->xpos = collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
664
sensor->collided = true;
665
break;
666
}
667
case FLIP_X: {
668
c = (YPos & tsm1) + (tileIndex << 4);
669
if ((XPos & tsm1) >= tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + TILE_SIZE - i)
670
break;
671
672
sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
673
sensor->collided = true;
674
break;
675
}
676
case FLIP_Y: {
677
c = tsm1 - (YPos & tsm1) + (tileIndex << 4);
678
if ((XPos & tsm1) >= collisionMasks[player->collisionPlane].rWallMasks[c] + TILE_SIZE - i)
679
break;
680
681
sensor->xpos = collisionMasks[player->collisionPlane].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
682
sensor->collided = true;
683
break;
684
}
685
case FLIP_XY: {
686
c = tsm1 - (YPos & tsm1) + (tileIndex << 4);
687
if ((XPos & tsm1) >= tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + TILE_SIZE - i)
688
break;
689
690
sensor->xpos = tsm1 - collisionMasks[player->collisionPlane].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
691
sensor->collided = true;
692
break;
693
}
694
}
695
}
696
697
if (sensor->collided) {
698
if (sensor->xpos - startX > tsm1) {
699
sensor->xpos = startX << 16;
700
sensor->collided = false;
701
}
702
else if (sensor->xpos - startX < -tsm1) {
703
sensor->xpos = startX << 16;
704
sensor->collided = false;
705
}
706
}
707
}
708
}
709
}
710
}
711
712
void ProcessAirCollision(Entity *entity)
713
{
714
Hitbox *playerHitbox = GetHitbox(entity);
715
collisionLeft = playerHitbox->left[0];
716
collisionTop = playerHitbox->top[0];
717
collisionRight = playerHitbox->right[0];
718
collisionBottom = playerHitbox->bottom[0];
719
720
byte movingDown = 0;
721
byte movingUp = 0;
722
byte movingLeft = 0;
723
byte movingRight = 0;
724
725
if (entity->xvel < 0) {
726
movingRight = 0;
727
}
728
else {
729
movingRight = 1;
730
sensors[0].ypos = entity->ypos + 0x40000;
731
sensors[0].collided = false;
732
sensors[0].xpos = entity->xpos + (collisionRight << 16);
733
}
734
if (entity->xvel > 0) {
735
movingLeft = 0;
736
}
737
else {
738
movingLeft = 1;
739
sensors[1].ypos = entity->ypos + 0x40000;
740
sensors[1].collided = false;
741
sensors[1].xpos = entity->xpos + ((collisionLeft - 1) << 16);
742
}
743
sensors[2].xpos = entity->xpos + (playerHitbox->left[1] << 16);
744
sensors[3].xpos = entity->xpos + (playerHitbox->right[1] << 16);
745
sensors[2].collided = false;
746
sensors[3].collided = false;
747
sensors[4].xpos = sensors[2].xpos;
748
sensors[5].xpos = sensors[3].xpos;
749
sensors[4].collided = false;
750
sensors[5].collided = false;
751
if (entity->yvel < 0) {
752
movingDown = 0;
753
}
754
else {
755
movingDown = 1;
756
sensors[2].ypos = entity->ypos + (collisionBottom << 16);
757
sensors[3].ypos = entity->ypos + (collisionBottom << 16);
758
}
759
760
if (abs(entity->xvel) > 0x10000 || entity->yvel < 0) {
761
movingUp = 1;
762
sensors[4].ypos = entity->ypos + ((collisionTop - 1) << 16);
763
sensors[5].ypos = entity->ypos + ((collisionTop - 1) << 16);
764
}
765
766
int cnt = (abs(entity->xvel) <= abs(entity->yvel) ? (abs(entity->yvel) >> 19) + 1 : (abs(entity->xvel) >> 19) + 1);
767
int XVel = entity->xvel / cnt;
768
int YVel = entity->yvel / cnt;
769
int XVel2 = entity->xvel - XVel * (cnt - 1);
770
int YVel2 = entity->yvel - YVel * (cnt - 1);
771
while (cnt > 0) {
772
if (cnt < 2) {
773
XVel = XVel2;
774
YVel = YVel2;
775
}
776
cnt--;
777
778
if (movingRight == 1) {
779
sensors[0].xpos += XVel;
780
sensors[0].ypos += YVel;
781
LWallCollision(entity, &sensors[0]);
782
if (sensors[0].collided) {
783
movingRight = 2;
784
}
785
else if (entity->xvel < 0x20000) {
786
sensors[0].ypos -= 0x80000;
787
LWallCollision(entity, &sensors[0]);
788
if (sensors[0].collided)
789
movingRight = 2;
790
sensors[0].ypos += 0x80000;
791
}
792
}
793
794
if (movingLeft == 1) {
795
sensors[1].xpos += XVel;
796
sensors[1].ypos += YVel;
797
RWallCollision(entity, &sensors[1]);
798
if (sensors[1].collided) {
799
movingLeft = 2;
800
}
801
else if (entity->xvel > -0x20000) {
802
sensors[1].ypos -= 0x80000;
803
RWallCollision(entity, &sensors[1]);
804
if (sensors[1].collided)
805
movingLeft = 2;
806
sensors[1].ypos += 0x80000;
807
}
808
}
809
810
if (movingRight == 2) {
811
entity->xvel = 0;
812
entity->speed = 0;
813
entity->xpos = (sensors[0].xpos - collisionRight) << 16;
814
sensors[2].xpos = entity->xpos + ((collisionLeft + 1) << 16);
815
sensors[3].xpos = entity->xpos + ((collisionRight - 2) << 16);
816
sensors[4].xpos = sensors[2].xpos;
817
sensors[5].xpos = sensors[3].xpos;
818
XVel = 0;
819
XVel2 = 0;
820
movingRight = 3;
821
}
822
823
if (movingLeft == 2) {
824
entity->xvel = 0;
825
entity->speed = 0;
826
entity->xpos = (sensors[1].xpos - collisionLeft + 1) << 16;
827
sensors[2].xpos = entity->xpos + ((collisionLeft + 1) << 16);
828
sensors[3].xpos = entity->xpos + ((collisionRight - 2) << 16);
829
sensors[4].xpos = sensors[2].xpos;
830
sensors[5].xpos = sensors[3].xpos;
831
XVel = 0;
832
XVel2 = 0;
833
movingLeft = 3;
834
}
835
836
if (movingDown == 1) {
837
for (int i = 2; i < 4; i++) {
838
if (!sensors[i].collided) {
839
sensors[i].xpos += XVel;
840
sensors[i].ypos += YVel;
841
FloorCollision(entity, &sensors[i]);
842
}
843
}
844
if (sensors[2].collided || sensors[3].collided) {
845
movingDown = 2;
846
cnt = 0;
847
}
848
}
849
850
if (movingUp == 1) {
851
for (int i = 4; i < 6; i++) {
852
if (!sensors[i].collided) {
853
sensors[i].xpos += XVel;
854
sensors[i].ypos += YVel;
855
RoofCollision(entity, &sensors[i]);
856
}
857
}
858
if (sensors[4].collided || sensors[5].collided) {
859
movingUp = 2;
860
cnt = 0;
861
}
862
}
863
}
864
865
if (movingRight < 2 && movingLeft < 2)
866
entity->xpos = entity->xpos + entity->xvel;
867
868
if (movingUp < 2 && movingDown < 2) {
869
entity->ypos = entity->ypos + entity->yvel;
870
return;
871
}
872
873
if (movingDown == 2) {
874
entity->gravity = 0;
875
if (sensors[2].collided && sensors[3].collided) {
876
if (sensors[2].ypos >= sensors[3].ypos) {
877
entity->ypos = (sensors[3].ypos - collisionBottom) << 16;
878
entity->angle = sensors[3].angle;
879
}
880
else {
881
entity->ypos = (sensors[2].ypos - collisionBottom) << 16;
882
entity->angle = sensors[2].angle;
883
}
884
}
885
else if (sensors[2].collided == 1) {
886
entity->ypos = (sensors[2].ypos - collisionBottom) << 16;
887
entity->angle = sensors[2].angle;
888
}
889
else if (sensors[3].collided == 1) {
890
entity->ypos = (sensors[3].ypos - collisionBottom) << 16;
891
entity->angle = sensors[3].angle;
892
}
893
if (entity->angle > 0xA0 && entity->angle < 0xE0 && entity->collisionMode != CMODE_LWALL) {
894
entity->collisionMode = CMODE_LWALL;
895
entity->xpos -= 0x40000;
896
}
897
if (entity->angle > 0x20 && entity->angle < 0x60 && entity->collisionMode != CMODE_RWALL) {
898
entity->collisionMode = CMODE_RWALL;
899
entity->xpos += 0x40000;
900
}
901
if (entity->angle < 0x20 || entity->angle > 0xE0) {
902
entity->controlLock = 0;
903
}
904
entity->rotation = entity->angle << 1;
905
906
int speed = 0;
907
if (entity->down) {
908
if (entity->angle < 128) {
909
if (entity->angle < 16) {
910
speed = entity->xvel;
911
}
912
else if (entity->angle >= 32) {
913
speed = (abs(entity->xvel) <= abs(entity->yvel) ? entity->yvel + entity->yvel / 12 : entity->xvel);
914
}
915
else {
916
speed = (abs(entity->xvel) <= abs(entity->yvel >> 1) ? (entity->yvel + entity->yvel / 12) >> 1 : entity->xvel);
917
}
918
}
919
else if (entity->angle > 240) {
920
speed = entity->xvel;
921
}
922
else if (entity->angle <= 224) {
923
speed = (abs(entity->xvel) <= abs(entity->yvel) ? -(entity->yvel + entity->yvel / 12) : entity->xvel);
924
}
925
else {
926
speed = (abs(entity->xvel) <= abs(entity->yvel >> 1) ? -((entity->yvel + entity->yvel / 12) >> 1) : entity->xvel);
927
}
928
}
929
else if (entity->angle < 0x80) {
930
if (entity->angle < 0x10) {
931
speed = entity->xvel;
932
}
933
else if (entity->angle >= 0x20) {
934
speed = (abs(entity->xvel) <= abs(entity->yvel) ? entity->yvel : entity->xvel);
935
}
936
else {
937
speed = (abs(entity->xvel) <= abs(entity->yvel >> 1) ? entity->yvel >> 1 : entity->xvel);
938
}
939
}
940
else if (entity->angle > 0xF0) {
941
speed = entity->xvel;
942
}
943
else if (entity->angle <= 0xE0) {
944
speed = (abs(entity->xvel) <= abs(entity->yvel) ? -entity->yvel : entity->xvel);
945
}
946
else {
947
speed = (abs(entity->xvel) <= abs(entity->yvel >> 1) ? -(entity->yvel >> 1) : entity->xvel);
948
}
949
950
if (speed < -0x180000)
951
speed = -0x180000;
952
if (speed > 0x180000)
953
speed = 0x180000;
954
entity->speed = speed;
955
entity->yvel = 0;
956
scriptEng.checkResult = 1;
957
}
958
959
if (movingUp == 2) {
960
int sensorAngle = 0;
961
if (sensors[4].collided && sensors[5].collided) {
962
if (sensors[4].ypos <= sensors[5].ypos) {
963
entity->ypos = (sensors[5].ypos - collisionTop + 1) << 16;
964
sensorAngle = sensors[5].angle;
965
}
966
else {
967
entity->ypos = (sensors[4].ypos - collisionTop + 1) << 16;
968
sensorAngle = sensors[4].angle;
969
}
970
}
971
else if (sensors[4].collided) {
972
entity->ypos = (sensors[4].ypos - collisionTop + 1) << 16;
973
sensorAngle = sensors[4].angle;
974
}
975
else if (sensors[5].collided) {
976
entity->ypos = (sensors[5].ypos - collisionTop + 1) << 16;
977
sensorAngle = sensors[5].angle;
978
}
979
sensorAngle &= 0xFF;
980
981
int angle = ArcTanLookup(entity->xvel, entity->yvel);
982
if (sensorAngle > 0x40 && sensorAngle < 0x62 && angle > 0xA0 && angle < 0xC2) {
983
entity->gravity = 0;
984
entity->angle = sensorAngle;
985
entity->rotation = entity->angle << 1;
986
entity->collisionMode = CMODE_RWALL;
987
entity->xpos += 0x40000;
988
entity->ypos -= 0x20000;
989
if (entity->angle <= 0x60)
990
entity->speed = entity->yvel;
991
else
992
entity->speed = entity->yvel >> 1;
993
}
994
if (sensorAngle > 0x9E && sensorAngle < 0xC0 && angle > 0xBE && angle < 0xE0) {
995
entity->gravity = 0;
996
entity->angle = sensorAngle;
997
entity->rotation = entity->angle << 1;
998
entity->collisionMode = CMODE_LWALL;
999
entity->xpos -= 0x40000;
1000
entity->ypos -= 0x20000;
1001
if (entity->angle >= 0xA0)
1002
entity->speed = -entity->yvel;
1003
else
1004
entity->speed = -entity->yvel >> 1;
1005
}
1006
if (entity->yvel < 0)
1007
entity->yvel = 0;
1008
scriptEng.checkResult = 2;
1009
}
1010
}
1011
void ProcessPathGrip(Entity *entity)
1012
{
1013
int cosValue256;
1014
int sinValue256;
1015
sensors[4].xpos = entity->xpos;
1016
sensors[4].ypos = entity->ypos;
1017
for (int i = 0; i < (RETRO_REV00 ? 6 : 7); ++i) {
1018
sensors[i].angle = entity->angle;
1019
sensors[i].collided = false;
1020
}
1021
SetPathGripSensors(entity);
1022
int absSpeed = abs(entity->speed);
1023
int checkDist = absSpeed >> 18;
1024
absSpeed &= 0x3FFFF;
1025
byte cMode = entity->collisionMode;
1026
1027
while (checkDist > -1) {
1028
if (checkDist >= 1) {
1029
cosValue256 = cos256LookupTable[entity->angle] << 10;
1030
sinValue256 = sin256LookupTable[entity->angle] << 10;
1031
checkDist--;
1032
}
1033
else {
1034
cosValue256 = absSpeed * cos256LookupTable[entity->angle] >> 8;
1035
sinValue256 = absSpeed * sin256LookupTable[entity->angle] >> 8;
1036
checkDist = -1;
1037
}
1038
1039
if (entity->speed < 0) {
1040
cosValue256 = -cosValue256;
1041
sinValue256 = -sinValue256;
1042
}
1043
1044
sensors[0].collided = false;
1045
sensors[1].collided = false;
1046
sensors[2].collided = false;
1047
#if !RETRO_REV00
1048
sensors[5].collided = false;
1049
sensors[6].collided = false;
1050
#endif
1051
sensors[4].xpos += cosValue256;
1052
sensors[4].ypos += sinValue256;
1053
int tileDistance = -1;
1054
1055
switch (entity->collisionMode) {
1056
case CMODE_FLOOR: {
1057
sensors[3].xpos += cosValue256;
1058
sensors[3].ypos += sinValue256;
1059
1060
if (entity->speed > 0) {
1061
LWallCollision(entity, &sensors[3]);
1062
if (sensors[3].collided) {
1063
sensors[2].xpos = (sensors[3].xpos - 2) << 16;
1064
}
1065
}
1066
1067
if (entity->speed < 0) {
1068
RWallCollision(entity, &sensors[3]);
1069
if (sensors[3].collided) {
1070
sensors[0].xpos = (sensors[3].xpos + 2) << 16;
1071
}
1072
}
1073
1074
if (sensors[3].collided) {
1075
cosValue256 = 0;
1076
checkDist = -1;
1077
}
1078
1079
for (int i = 0; i < 3; i++) {
1080
sensors[i].xpos += cosValue256;
1081
sensors[i].ypos += sinValue256;
1082
FindFloorPosition(entity, &sensors[i], sensors[i].ypos >> 16);
1083
}
1084
1085
#if !RETRO_REV00
1086
for (int i = 5; i < 7; i++) {
1087
sensors[i].xpos += cosValue256;
1088
sensors[i].ypos += sinValue256;
1089
FindFloorPosition(entity, &sensors[i], sensors[i].ypos >> 16);
1090
}
1091
#endif
1092
1093
tileDistance = -1;
1094
for (int i = 0; i < 3; i++) {
1095
if (tileDistance > -1) {
1096
if (sensors[i].collided) {
1097
if (sensors[i].ypos < sensors[tileDistance].ypos)
1098
tileDistance = i;
1099
1100
if (sensors[i].ypos == sensors[tileDistance].ypos && (sensors[i].angle < 0x08 || sensors[i].angle > 0xF8))
1101
tileDistance = i;
1102
}
1103
}
1104
else if (sensors[i].collided)
1105
tileDistance = i;
1106
}
1107
1108
if (tileDistance <= -1) {
1109
checkDist = -1;
1110
}
1111
else {
1112
sensors[0].ypos = sensors[tileDistance].ypos << 16;
1113
sensors[0].angle = sensors[tileDistance].angle;
1114
sensors[1].ypos = sensors[0].ypos;
1115
sensors[1].angle = sensors[0].angle;
1116
sensors[2].ypos = sensors[0].ypos;
1117
sensors[2].angle = sensors[0].angle;
1118
sensors[3].ypos = sensors[0].ypos - 0x40000;
1119
sensors[3].angle = sensors[0].angle;
1120
sensors[4].xpos = sensors[1].xpos;
1121
sensors[4].ypos = sensors[0].ypos - (collisionBottom << 16);
1122
}
1123
1124
if (sensors[0].angle < 0xDE && sensors[0].angle > 0x80)
1125
entity->collisionMode = CMODE_LWALL;
1126
if (sensors[0].angle > 0x22 && sensors[0].angle < 0x80)
1127
entity->collisionMode = CMODE_RWALL;
1128
break;
1129
}
1130
case CMODE_LWALL: {
1131
sensors[3].xpos += cosValue256;
1132
sensors[3].ypos += sinValue256;
1133
1134
if (entity->speed > 0)
1135
RoofCollision(entity, &sensors[3]);
1136
1137
if (entity->speed < 0)
1138
FloorCollision(entity, &sensors[3]);
1139
1140
if (sensors[3].collided) {
1141
sinValue256 = 0;
1142
checkDist = -1;
1143
}
1144
for (int i = 0; i < 3; i++) {
1145
sensors[i].xpos += cosValue256;
1146
sensors[i].ypos += sinValue256;
1147
FindLWallPosition(entity, &sensors[i], sensors[i].xpos >> 16);
1148
}
1149
1150
tileDistance = -1;
1151
for (int i = 0; i < 3; i++) {
1152
if (tileDistance > -1) {
1153
if (sensors[i].xpos < sensors[tileDistance].xpos && sensors[i].collided) {
1154
tileDistance = i;
1155
}
1156
}
1157
else if (sensors[i].collided) {
1158
tileDistance = i;
1159
}
1160
}
1161
1162
if (tileDistance <= -1) {
1163
checkDist = -1;
1164
}
1165
else {
1166
sensors[0].xpos = sensors[tileDistance].xpos << 16;
1167
sensors[0].angle = sensors[tileDistance].angle;
1168
sensors[1].xpos = sensors[0].xpos;
1169
sensors[1].angle = sensors[0].angle;
1170
sensors[2].xpos = sensors[0].xpos;
1171
sensors[2].angle = sensors[0].angle;
1172
sensors[4].ypos = sensors[1].ypos;
1173
sensors[4].xpos = sensors[1].xpos - (collisionRight << 16);
1174
}
1175
1176
if (sensors[0].angle > 0xE2)
1177
entity->collisionMode = CMODE_FLOOR;
1178
if (sensors[0].angle < 0x9E)
1179
entity->collisionMode = CMODE_ROOF;
1180
break;
1181
break;
1182
}
1183
case CMODE_ROOF: {
1184
sensors[3].xpos += cosValue256;
1185
sensors[3].ypos += sinValue256;
1186
1187
if (entity->speed > 0)
1188
RWallCollision(entity, &sensors[3]);
1189
1190
if (entity->speed < 0)
1191
LWallCollision(entity, &sensors[3]);
1192
1193
if (sensors[3].collided) {
1194
cosValue256 = 0;
1195
checkDist = -1;
1196
}
1197
for (int i = 0; i < 3; i++) {
1198
sensors[i].xpos += cosValue256;
1199
sensors[i].ypos += sinValue256;
1200
FindRoofPosition(entity, &sensors[i], sensors[i].ypos >> 16);
1201
}
1202
1203
tileDistance = -1;
1204
for (int i = 0; i < 3; i++) {
1205
if (tileDistance > -1) {
1206
if (sensors[i].ypos > sensors[tileDistance].ypos && sensors[i].collided) {
1207
tileDistance = i;
1208
}
1209
}
1210
else if (sensors[i].collided) {
1211
tileDistance = i;
1212
}
1213
}
1214
1215
if (tileDistance <= -1) {
1216
checkDist = -1;
1217
}
1218
else {
1219
sensors[0].ypos = sensors[tileDistance].ypos << 16;
1220
sensors[0].angle = sensors[tileDistance].angle;
1221
sensors[1].ypos = sensors[0].ypos;
1222
sensors[1].angle = sensors[0].angle;
1223
sensors[2].ypos = sensors[0].ypos;
1224
sensors[2].angle = sensors[0].angle;
1225
sensors[3].ypos = sensors[0].ypos + 0x40000;
1226
sensors[3].angle = sensors[0].angle;
1227
sensors[4].xpos = sensors[1].xpos;
1228
sensors[4].ypos = sensors[0].ypos - ((collisionTop - 1) << 16);
1229
}
1230
1231
if (sensors[0].angle > 0xA2)
1232
entity->collisionMode = CMODE_LWALL;
1233
if (sensors[0].angle < 0x5E)
1234
entity->collisionMode = CMODE_RWALL;
1235
break;
1236
}
1237
case CMODE_RWALL: {
1238
sensors[3].xpos += cosValue256;
1239
sensors[3].ypos += sinValue256;
1240
1241
if (entity->speed > 0)
1242
FloorCollision(entity, &sensors[3]);
1243
1244
if (entity->speed < 0)
1245
RoofCollision(entity, &sensors[3]);
1246
1247
if (sensors[3].collided) {
1248
sinValue256 = 0;
1249
checkDist = -1;
1250
}
1251
for (int i = 0; i < 3; i++) {
1252
sensors[i].xpos += cosValue256;
1253
sensors[i].ypos += sinValue256;
1254
FindRWallPosition(entity, &sensors[i], sensors[i].xpos >> 16);
1255
}
1256
1257
tileDistance = -1;
1258
for (int i = 0; i < 3; i++) {
1259
if (tileDistance > -1) {
1260
if (sensors[i].xpos > sensors[tileDistance].xpos && sensors[i].collided) {
1261
tileDistance = i;
1262
}
1263
}
1264
else if (sensors[i].collided) {
1265
tileDistance = i;
1266
}
1267
}
1268
1269
if (tileDistance <= -1) {
1270
checkDist = -1;
1271
}
1272
else {
1273
sensors[0].xpos = sensors[tileDistance].xpos << 16;
1274
sensors[0].angle = sensors[tileDistance].angle;
1275
sensors[1].xpos = sensors[0].xpos;
1276
sensors[1].angle = sensors[0].angle;
1277
sensors[2].xpos = sensors[0].xpos;
1278
sensors[2].angle = sensors[0].angle;
1279
sensors[4].ypos = sensors[1].ypos;
1280
sensors[4].xpos = sensors[1].xpos - ((collisionLeft - 1) << 16);
1281
}
1282
1283
if (sensors[0].angle < 0x1E)
1284
entity->collisionMode = CMODE_FLOOR;
1285
if (sensors[0].angle > 0x62)
1286
entity->collisionMode = CMODE_ROOF;
1287
break;
1288
}
1289
}
1290
if (tileDistance != -1)
1291
entity->angle = sensors[0].angle;
1292
1293
if (!sensors[3].collided)
1294
SetPathGripSensors(entity);
1295
else
1296
checkDist = -2;
1297
}
1298
1299
switch (cMode) {
1300
case CMODE_FLOOR: {
1301
if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {
1302
entity->angle = sensors[0].angle;
1303
entity->rotation = entity->angle << 1;
1304
entity->floorSensors[0] = sensors[0].collided;
1305
entity->floorSensors[1] = sensors[1].collided;
1306
entity->floorSensors[2] = sensors[2].collided;
1307
#if !RETRO_REV00
1308
entity->floorSensors[3] = sensors[5].collided;
1309
entity->floorSensors[4] = sensors[6].collided;
1310
#endif
1311
if (!sensors[3].collided) {
1312
entity->pushing = 0;
1313
entity->xpos = sensors[4].xpos;
1314
}
1315
else {
1316
if (entity->speed > 0)
1317
entity->xpos = (sensors[3].xpos - collisionRight) << 16;
1318
1319
if (entity->speed < 0)
1320
entity->xpos = (sensors[3].xpos - collisionLeft + 1) << 16;
1321
1322
entity->speed = 0;
1323
if ((entity->left || entity->right) && entity->pushing < 2)
1324
entity->pushing++;
1325
}
1326
entity->ypos = sensors[4].ypos;
1327
}
1328
else {
1329
entity->gravity = 1;
1330
entity->collisionMode = CMODE_FLOOR;
1331
entity->xvel = cos256LookupTable[entity->angle] * entity->speed >> 8;
1332
entity->yvel = sin256LookupTable[entity->angle] * entity->speed >> 8;
1333
if (entity->yvel < -0x100000)
1334
entity->yvel = -0x100000;
1335
1336
if (entity->yvel > 0x100000)
1337
entity->yvel = 0x100000;
1338
1339
entity->speed = entity->xvel;
1340
entity->angle = 0;
1341
if (!sensors[3].collided) {
1342
entity->pushing = 0;
1343
entity->xpos += entity->xvel;
1344
}
1345
else {
1346
if (entity->speed > 0)
1347
entity->xpos = (sensors[3].xpos - collisionRight) << 16;
1348
if (entity->speed < 0)
1349
entity->xpos = (sensors[3].xpos - collisionLeft + 1) << 16;
1350
1351
entity->speed = 0;
1352
if ((entity->left || entity->right) && entity->pushing < 2)
1353
entity->pushing++;
1354
}
1355
entity->ypos += entity->yvel;
1356
}
1357
break;
1358
}
1359
case CMODE_LWALL: {
1360
if (!sensors[0].collided && !sensors[1].collided && !sensors[2].collided) {
1361
entity->gravity = 1;
1362
entity->collisionMode = CMODE_FLOOR;
1363
entity->xvel = cos256LookupTable[entity->angle] * entity->speed >> 8;
1364
entity->yvel = sin256LookupTable[entity->angle] * entity->speed >> 8;
1365
if (entity->yvel < -0x100000) {
1366
entity->yvel = -0x100000;
1367
}
1368
if (entity->yvel > 0x100000) {
1369
entity->yvel = 0x100000;
1370
}
1371
entity->speed = entity->xvel;
1372
entity->angle = 0;
1373
}
1374
else if (entity->speed >= 0x28000 || entity->speed <= -0x28000 || entity->controlLock != 0) {
1375
entity->angle = sensors[0].angle;
1376
entity->rotation = entity->angle << 1;
1377
}
1378
else {
1379
entity->gravity = 1;
1380
entity->angle = 0;
1381
entity->collisionMode = CMODE_FLOOR;
1382
entity->speed = entity->xvel;
1383
entity->controlLock = 30;
1384
}
1385
if (!sensors[3].collided) {
1386
entity->ypos = sensors[4].ypos;
1387
}
1388
else {
1389
if (entity->speed > 0)
1390
entity->ypos = (sensors[3].ypos - collisionTop) << 16;
1391
1392
if (entity->speed < 0)
1393
entity->ypos = (sensors[3].ypos - collisionBottom) << 16;
1394
1395
entity->speed = 0;
1396
}
1397
entity->xpos = sensors[4].xpos;
1398
break;
1399
}
1400
case CMODE_ROOF: {
1401
if (!sensors[0].collided && !sensors[1].collided && !sensors[2].collided) {
1402
entity->gravity = 1;
1403
entity->collisionMode = CMODE_FLOOR;
1404
entity->xvel = cos256LookupTable[entity->angle] * entity->speed >> 8;
1405
entity->yvel = sin256LookupTable[entity->angle] * entity->speed >> 8;
1406
entity->floorSensors[0] = false;
1407
entity->floorSensors[1] = false;
1408
entity->floorSensors[2] = false;
1409
if (entity->yvel < -0x100000)
1410
entity->yvel = -0x100000;
1411
1412
if (entity->yvel > 0x100000)
1413
entity->yvel = 0x100000;
1414
1415
entity->angle = 0;
1416
entity->speed = entity->xvel;
1417
if (!sensors[3].collided) {
1418
entity->xpos = entity->xpos + entity->xvel;
1419
}
1420
else {
1421
if (entity->speed > 0)
1422
entity->xpos = (sensors[3].xpos - collisionRight) << 16;
1423
1424
if (entity->speed < 0)
1425
entity->xpos = (sensors[3].xpos - collisionLeft + 1) << 16;
1426
1427
entity->speed = 0;
1428
}
1429
}
1430
else if (entity->speed <= -0x28000 || entity->speed >= 0x28000) {
1431
entity->angle = sensors[0].angle;
1432
entity->rotation = entity->angle << 1;
1433
if (!sensors[3].collided) {
1434
entity->xpos = sensors[4].xpos;
1435
}
1436
else {
1437
if (entity->speed < 0)
1438
entity->xpos = (sensors[3].xpos - collisionRight) << 16;
1439
1440
if (entity->speed > 0)
1441
entity->xpos = (sensors[3].xpos - collisionLeft + 1) << 16;
1442
entity->speed = 0;
1443
}
1444
}
1445
else {
1446
entity->gravity = 1;
1447
entity->angle = 0;
1448
entity->collisionMode = CMODE_FLOOR;
1449
entity->speed = entity->xvel;
1450
entity->floorSensors[0] = false;
1451
entity->floorSensors[1] = false;
1452
entity->floorSensors[2] = false;
1453
if (!sensors[3].collided) {
1454
entity->xpos = entity->xpos + entity->xvel;
1455
}
1456
else {
1457
if (entity->speed > 0)
1458
entity->xpos = (sensors[3].xpos - collisionRight) << 16;
1459
1460
if (entity->speed < 0)
1461
entity->xpos = (sensors[3].xpos - collisionLeft + 1) << 16;
1462
entity->speed = 0;
1463
}
1464
}
1465
entity->ypos = sensors[4].ypos;
1466
break;
1467
}
1468
case CMODE_RWALL: {
1469
if (!sensors[0].collided && !sensors[1].collided && !sensors[2].collided) {
1470
entity->gravity = 1;
1471
entity->collisionMode = CMODE_FLOOR;
1472
entity->xvel = cos256LookupTable[entity->angle] * entity->speed >> 8;
1473
entity->yvel = sin256LookupTable[entity->angle] * entity->speed >> 8;
1474
if (entity->yvel < -0x100000)
1475
entity->yvel = -0x100000;
1476
1477
if (entity->yvel > 0x100000)
1478
entity->yvel = 0x100000;
1479
1480
entity->speed = entity->xvel;
1481
entity->angle = 0;
1482
}
1483
else if (entity->speed <= -0x28000 || entity->speed >= 0x28000 || entity->controlLock != 0) {
1484
entity->angle = sensors[0].angle;
1485
entity->rotation = entity->angle << 1;
1486
}
1487
else {
1488
entity->gravity = 1;
1489
entity->angle = 0;
1490
entity->collisionMode = CMODE_FLOOR;
1491
entity->speed = entity->xvel;
1492
entity->controlLock = 30;
1493
}
1494
if (!sensors[3].collided) {
1495
entity->ypos = sensors[4].ypos;
1496
}
1497
else {
1498
if (entity->speed > 0)
1499
entity->ypos = (sensors[3].ypos - collisionBottom) << 16;
1500
1501
if (entity->speed < 0)
1502
entity->ypos = (sensors[3].ypos - collisionTop + 1) << 16;
1503
1504
entity->speed = 0;
1505
}
1506
entity->xpos = sensors[4].xpos;
1507
break;
1508
}
1509
default: break;
1510
}
1511
}
1512
1513
void SetPathGripSensors(Entity *player)
1514
{
1515
Hitbox *playerHitbox = GetHitbox(player);
1516
1517
switch (player->collisionMode) {
1518
case CMODE_FLOOR: {
1519
collisionLeft = playerHitbox->left[0];
1520
collisionTop = playerHitbox->top[0];
1521
collisionRight = playerHitbox->right[0];
1522
collisionBottom = playerHitbox->bottom[0];
1523
sensors[0].ypos = sensors[4].ypos + (collisionBottom << 16);
1524
sensors[1].ypos = sensors[0].ypos;
1525
sensors[2].ypos = sensors[0].ypos;
1526
sensors[3].ypos = sensors[4].ypos + 0x40000;
1527
#if !RETRO_REV00
1528
sensors[5].ypos = sensors[0].ypos;
1529
sensors[6].ypos = sensors[0].ypos;
1530
#endif
1531
1532
sensors[0].xpos = sensors[4].xpos + ((playerHitbox->left[1] - 1) << 16);
1533
sensors[1].xpos = sensors[4].xpos;
1534
sensors[2].xpos = sensors[4].xpos + (playerHitbox->right[1] << 16);
1535
#if !RETRO_REV00
1536
sensors[5].xpos = sensors[4].xpos + (playerHitbox->left[1] << 15);
1537
sensors[6].xpos = sensors[4].xpos + (playerHitbox->right[1] << 15);
1538
#endif
1539
if (player->speed > 0) {
1540
sensors[3].xpos = sensors[4].xpos + ((collisionRight + 1) << 16);
1541
}
1542
else {
1543
sensors[3].xpos = sensors[4].xpos + ((collisionLeft - 1) << 16);
1544
}
1545
return;
1546
}
1547
case CMODE_LWALL: {
1548
collisionLeft = playerHitbox->left[2];
1549
collisionTop = playerHitbox->top[2];
1550
collisionRight = playerHitbox->right[2];
1551
collisionBottom = playerHitbox->bottom[2];
1552
sensors[0].xpos = sensors[4].xpos + (collisionRight << 16);
1553
sensors[1].xpos = sensors[0].xpos;
1554
sensors[2].xpos = sensors[0].xpos;
1555
sensors[3].xpos = sensors[4].xpos + 0x40000;
1556
sensors[0].ypos = sensors[4].ypos + ((playerHitbox->top[3] - 1) << 16);
1557
sensors[1].ypos = sensors[4].ypos;
1558
sensors[2].ypos = sensors[4].ypos + (playerHitbox->bottom[3] << 16);
1559
if (player->speed > 0) {
1560
sensors[3].ypos = sensors[4].ypos + (collisionTop << 16);
1561
}
1562
else {
1563
sensors[3].ypos = sensors[4].ypos + ((collisionBottom - 1) << 16);
1564
}
1565
return;
1566
}
1567
case CMODE_ROOF: {
1568
collisionLeft = playerHitbox->left[4];
1569
collisionTop = playerHitbox->top[4];
1570
collisionRight = playerHitbox->right[4];
1571
collisionBottom = playerHitbox->bottom[4];
1572
sensors[0].ypos = sensors[4].ypos + ((collisionTop - 1) << 16);
1573
sensors[1].ypos = sensors[0].ypos;
1574
sensors[2].ypos = sensors[0].ypos;
1575
sensors[3].ypos = sensors[4].ypos - 0x40000;
1576
sensors[0].xpos = sensors[4].xpos + ((playerHitbox->left[5] - 1) << 16);
1577
sensors[1].xpos = sensors[4].xpos;
1578
sensors[2].xpos = sensors[4].xpos + (playerHitbox->right[5] << 16);
1579
if (player->speed < 0) {
1580
sensors[3].xpos = sensors[4].xpos + ((collisionRight + 1) << 16);
1581
}
1582
else {
1583
sensors[3].xpos = sensors[4].xpos + ((collisionLeft - 1) << 16);
1584
}
1585
return;
1586
}
1587
case CMODE_RWALL: {
1588
collisionLeft = playerHitbox->left[6];
1589
collisionTop = playerHitbox->top[6];
1590
collisionRight = playerHitbox->right[6];
1591
collisionBottom = playerHitbox->bottom[6];
1592
sensors[0].xpos = sensors[4].xpos + ((collisionLeft - 1) << 16);
1593
sensors[1].xpos = sensors[0].xpos;
1594
sensors[2].xpos = sensors[0].xpos;
1595
sensors[3].xpos = sensors[4].xpos - 0x40000;
1596
sensors[0].ypos = sensors[4].ypos + ((playerHitbox->top[7] - 1) << 16);
1597
sensors[1].ypos = sensors[4].ypos;
1598
sensors[2].ypos = sensors[4].ypos + (playerHitbox->bottom[7] << 16);
1599
if (player->speed > 0) {
1600
sensors[3].ypos = sensors[4].ypos + (collisionBottom << 16);
1601
}
1602
else {
1603
sensors[3].ypos = sensors[4].ypos + ((collisionTop - 1) << 16);
1604
}
1605
return;
1606
}
1607
default: return;
1608
}
1609
}
1610
1611
void ProcessTileCollisions(Entity *player)
1612
{
1613
player->floorSensors[0] = false;
1614
player->floorSensors[1] = false;
1615
player->floorSensors[2] = false;
1616
#if !RETRO_REV00
1617
player->floorSensors[3] = false;
1618
player->floorSensors[4] = false;
1619
#endif
1620
scriptEng.checkResult = false;
1621
1622
collisionTolerance = 15;
1623
if (player->speed < 0x60000)
1624
collisionTolerance = (sbyte)player->angle == 0 ? 8 : 15;
1625
1626
if (player->gravity == 1)
1627
ProcessAirCollision(player);
1628
else
1629
ProcessPathGrip(player);
1630
}
1631
1632
void ObjectFloorCollision(int xOffset, int yOffset, int cPath)
1633
{
1634
scriptEng.checkResult = false;
1635
Entity *entity = &objectEntityList[objectEntityPos];
1636
int c = 0;
1637
int XPos = (entity->xpos >> 16) + xOffset;
1638
int YPos = (entity->ypos >> 16) + yOffset;
1639
if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7) {
1640
int chunkX = XPos >> 7;
1641
int tileX = (XPos & 0x7F) >> 4;
1642
int chunkY = YPos >> 7;
1643
int tileY = (YPos & 0x7F) >> 4;
1644
int chunk = (stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6) + tileX + (tileY << 3);
1645
int tileIndex = tiles128x128.tileIndex[chunk];
1646
if (tiles128x128.collisionFlags[cPath][chunk] != SOLID_LRB && tiles128x128.collisionFlags[cPath][chunk] != SOLID_NONE) {
1647
switch (tiles128x128.direction[chunk]) {
1648
case 0: {
1649
c = (XPos & 15) + (tileIndex << 4);
1650
if ((YPos & 15) <= collisionMasks[cPath].floorMasks[c]) {
1651
break;
1652
}
1653
YPos = collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);
1654
scriptEng.checkResult = true;
1655
break;
1656
}
1657
case 1: {
1658
c = 15 - (XPos & 15) + (tileIndex << 4);
1659
if ((YPos & 15) <= collisionMasks[cPath].floorMasks[c]) {
1660
break;
1661
}
1662
YPos = collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);
1663
scriptEng.checkResult = true;
1664
break;
1665
}
1666
case 2: {
1667
c = (XPos & 15) + (tileIndex << 4);
1668
if ((YPos & 15) <= 15 - collisionMasks[cPath].roofMasks[c]) {
1669
break;
1670
}
1671
YPos = 15 - collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);
1672
scriptEng.checkResult = true;
1673
break;
1674
}
1675
case 3: {
1676
c = 15 - (XPos & 15) + (tileIndex << 4);
1677
if ((YPos & 15) <= 15 - collisionMasks[cPath].roofMasks[c]) {
1678
break;
1679
}
1680
YPos = 15 - collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);
1681
scriptEng.checkResult = true;
1682
break;
1683
}
1684
}
1685
}
1686
if (scriptEng.checkResult) {
1687
entity->ypos = (YPos - yOffset) << 16;
1688
}
1689
}
1690
}
1691
void ObjectLWallCollision(int xOffset, int yOffset, int cPath)
1692
{
1693
int c;
1694
scriptEng.checkResult = false;
1695
Entity *entity = &objectEntityList[objectEntityPos];
1696
int XPos = (entity->xpos >> 16) + xOffset;
1697
int YPos = (entity->ypos >> 16) + yOffset;
1698
if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7) {
1699
int chunkX = XPos >> 7;
1700
int tileX = (XPos & 0x7F) >> 4;
1701
int chunkY = YPos >> 7;
1702
int tileY = (YPos & 0x7F) >> 4;
1703
int chunk = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;
1704
chunk = chunk + tileX + (tileY << 3);
1705
int tileIndex = tiles128x128.tileIndex[chunk];
1706
if (tiles128x128.collisionFlags[cPath][chunk] != SOLID_TOP && tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {
1707
switch (tiles128x128.direction[chunk]) {
1708
case 0: {
1709
c = (YPos & 15) + (tileIndex << 4);
1710
if ((XPos & 15) <= collisionMasks[cPath].lWallMasks[c]) {
1711
break;
1712
}
1713
XPos = collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
1714
scriptEng.checkResult = true;
1715
break;
1716
}
1717
case 1: {
1718
c = (YPos & 15) + (tileIndex << 4);
1719
if ((XPos & 15) <= 15 - collisionMasks[cPath].rWallMasks[c]) {
1720
break;
1721
}
1722
XPos = 15 - collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
1723
scriptEng.checkResult = true;
1724
break;
1725
}
1726
case 2: {
1727
c = 15 - (YPos & 15) + (tileIndex << 4);
1728
if ((XPos & 15) <= collisionMasks[cPath].lWallMasks[c]) {
1729
break;
1730
}
1731
XPos = collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
1732
scriptEng.checkResult = true;
1733
break;
1734
}
1735
case 3: {
1736
c = 15 - (YPos & 15) + (tileIndex << 4);
1737
if ((XPos & 15) <= 15 - collisionMasks[cPath].rWallMasks[c]) {
1738
break;
1739
}
1740
XPos = 15 - collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
1741
scriptEng.checkResult = true;
1742
break;
1743
}
1744
}
1745
}
1746
if (scriptEng.checkResult) {
1747
entity->xpos = (XPos - xOffset) << 16;
1748
}
1749
}
1750
}
1751
void ObjectRoofCollision(int xOffset, int yOffset, int cPath)
1752
{
1753
int c;
1754
scriptEng.checkResult = false;
1755
Entity *entity = &objectEntityList[objectEntityPos];
1756
int XPos = (entity->xpos >> 16) + xOffset;
1757
int YPos = (entity->ypos >> 16) + yOffset;
1758
if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7) {
1759
int chunkX = XPos >> 7;
1760
int tileX = (XPos & 0x7F) >> 4;
1761
int chunkY = YPos >> 7;
1762
int tileY = (YPos & 0x7F) >> 4;
1763
int chunk = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;
1764
chunk = chunk + tileX + (tileY << 3);
1765
int tileIndex = tiles128x128.tileIndex[chunk];
1766
if (tiles128x128.collisionFlags[cPath][chunk] != SOLID_TOP && tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {
1767
switch (tiles128x128.direction[chunk]) {
1768
case 0: {
1769
c = (XPos & 15) + (tileIndex << 4);
1770
if ((YPos & 15) >= collisionMasks[cPath].roofMasks[c]) {
1771
break;
1772
}
1773
YPos = collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);
1774
scriptEng.checkResult = true;
1775
break;
1776
}
1777
case 1: {
1778
c = 15 - (XPos & 15) + (tileIndex << 4);
1779
if ((YPos & 15) >= collisionMasks[cPath].roofMasks[c]) {
1780
break;
1781
}
1782
YPos = collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);
1783
scriptEng.checkResult = true;
1784
break;
1785
}
1786
case 2: {
1787
c = (XPos & 15) + (tileIndex << 4);
1788
if ((YPos & 15) >= 15 - collisionMasks[cPath].floorMasks[c]) {
1789
break;
1790
}
1791
YPos = 15 - collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);
1792
scriptEng.checkResult = true;
1793
break;
1794
}
1795
case 3: {
1796
c = 15 - (XPos & 15) + (tileIndex << 4);
1797
if ((YPos & 15) >= 15 - collisionMasks[cPath].floorMasks[c]) {
1798
break;
1799
}
1800
YPos = 15 - collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);
1801
scriptEng.checkResult = true;
1802
break;
1803
}
1804
}
1805
}
1806
if (scriptEng.checkResult) {
1807
entity->ypos = (YPos - yOffset) << 16;
1808
}
1809
}
1810
}
1811
void ObjectRWallCollision(int xOffset, int yOffset, int cPath)
1812
{
1813
int c;
1814
scriptEng.checkResult = false;
1815
Entity *entity = &objectEntityList[objectEntityPos];
1816
int XPos = (entity->xpos >> 16) + xOffset;
1817
int YPos = (entity->ypos >> 16) + yOffset;
1818
if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7) {
1819
int chunkX = XPos >> 7;
1820
int tileX = (XPos & 0x7F) >> 4;
1821
int chunkY = YPos >> 7;
1822
int tileY = (YPos & 0x7F) >> 4;
1823
int chunk = stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6;
1824
chunk = chunk + tileX + (tileY << 3);
1825
int tileIndex = tiles128x128.tileIndex[chunk];
1826
if (tiles128x128.collisionFlags[cPath][chunk] != SOLID_TOP && tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {
1827
switch (tiles128x128.direction[chunk]) {
1828
case 0: {
1829
c = (YPos & 15) + (tileIndex << 4);
1830
if ((XPos & 15) >= collisionMasks[cPath].rWallMasks[c]) {
1831
break;
1832
}
1833
XPos = collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
1834
scriptEng.checkResult = true;
1835
break;
1836
}
1837
case 1: {
1838
c = (YPos & 15) + (tileIndex << 4);
1839
if ((XPos & 15) >= 15 - collisionMasks[cPath].lWallMasks[c]) {
1840
break;
1841
}
1842
XPos = 15 - collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
1843
scriptEng.checkResult = true;
1844
break;
1845
}
1846
case 2: {
1847
c = 15 - (YPos & 15) + (tileIndex << 4);
1848
if ((XPos & 15) >= collisionMasks[cPath].rWallMasks[c]) {
1849
break;
1850
}
1851
XPos = collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
1852
scriptEng.checkResult = true;
1853
break;
1854
}
1855
case 3: {
1856
c = 15 - (YPos & 15) + (tileIndex << 4);
1857
if ((XPos & 15) >= 15 - collisionMasks[cPath].lWallMasks[c]) {
1858
break;
1859
}
1860
XPos = 15 - collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
1861
scriptEng.checkResult = true;
1862
break;
1863
}
1864
}
1865
}
1866
if (scriptEng.checkResult) {
1867
entity->xpos = (XPos - xOffset) << 16;
1868
}
1869
}
1870
}
1871
1872
void ObjectFloorGrip(int xOffset, int yOffset, int cPath)
1873
{
1874
int c;
1875
scriptEng.checkResult = false;
1876
Entity *entity = &objectEntityList[objectEntityPos];
1877
int XPos = (entity->xpos >> 16) + xOffset;
1878
int YPos = (entity->ypos >> 16) + yOffset;
1879
int chunkX = YPos;
1880
YPos = YPos - 16;
1881
for (int i = 3; i > 0; i--) {
1882
if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7 && !scriptEng.checkResult) {
1883
int chunkX = XPos >> 7;
1884
int tileX = (XPos & 0x7F) >> 4;
1885
int chunkY = YPos >> 7;
1886
int tileY = (YPos & 0x7F) >> 4;
1887
int chunk = (stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6) + tileX + (tileY << 3);
1888
int tileIndex = tiles128x128.tileIndex[chunk];
1889
if (tiles128x128.collisionFlags[cPath][chunk] != SOLID_LRB && tiles128x128.collisionFlags[cPath][chunk] != SOLID_NONE) {
1890
switch (tiles128x128.direction[chunk]) {
1891
case 0: {
1892
c = (XPos & 15) + (tileIndex << 4);
1893
if (collisionMasks[cPath].floorMasks[c] >= 64) {
1894
break;
1895
}
1896
entity->ypos = collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);
1897
scriptEng.checkResult = true;
1898
break;
1899
}
1900
case 1: {
1901
c = 15 - (XPos & 15) + (tileIndex << 4);
1902
if (collisionMasks[cPath].floorMasks[c] >= 64) {
1903
break;
1904
}
1905
entity->ypos = collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);
1906
scriptEng.checkResult = true;
1907
break;
1908
}
1909
case 2: {
1910
c = (XPos & 15) + (tileIndex << 4);
1911
if (collisionMasks[cPath].roofMasks[c] <= -64) {
1912
break;
1913
}
1914
entity->ypos = 15 - collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);
1915
scriptEng.checkResult = true;
1916
break;
1917
}
1918
case 3: {
1919
c = 15 - (XPos & 15) + (tileIndex << 4);
1920
if (collisionMasks[cPath].roofMasks[c] <= -64) {
1921
break;
1922
}
1923
entity->ypos = 15 - collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);
1924
scriptEng.checkResult = true;
1925
break;
1926
}
1927
}
1928
}
1929
}
1930
YPos += 16;
1931
}
1932
1933
if (scriptEng.checkResult) {
1934
if (abs(entity->ypos - chunkX) < 16) {
1935
entity->ypos = (entity->ypos - yOffset) << 16;
1936
return;
1937
}
1938
entity->ypos = (chunkX - yOffset) << 16;
1939
scriptEng.checkResult = false;
1940
}
1941
}
1942
void ObjectLWallGrip(int xOffset, int yOffset, int cPath)
1943
{
1944
int c;
1945
scriptEng.checkResult = false;
1946
Entity *entity = &objectEntityList[objectEntityPos];
1947
int XPos = (entity->xpos >> 16) + xOffset;
1948
int YPos = (entity->ypos >> 16) + yOffset;
1949
int startX = XPos;
1950
XPos = XPos - 16;
1951
for (int i = 3; i > 0; i--) {
1952
if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7 && !scriptEng.checkResult) {
1953
int chunkX = XPos >> 7;
1954
int tileX = (XPos & 0x7F) >> 4;
1955
int chunkY = YPos >> 7;
1956
int tileY = (YPos & 0x7F) >> 4;
1957
int chunk = (stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6) + tileX + (tileY << 3);
1958
int tileIndex = tiles128x128.tileIndex[chunk];
1959
if (tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {
1960
switch (tiles128x128.direction[chunk]) {
1961
case 0: {
1962
c = (YPos & 15) + (tileIndex << 4);
1963
if (collisionMasks[cPath].lWallMasks[c] >= 64) {
1964
break;
1965
}
1966
entity->xpos = collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
1967
scriptEng.checkResult = true;
1968
break;
1969
}
1970
case 1: {
1971
c = (YPos & 15) + (tileIndex << 4);
1972
if (collisionMasks[cPath].rWallMasks[c] <= -64) {
1973
break;
1974
}
1975
entity->xpos = 15 - collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
1976
scriptEng.checkResult = true;
1977
break;
1978
}
1979
case 2: {
1980
c = 15 - (YPos & 15) + (tileIndex << 4);
1981
if (collisionMasks[cPath].lWallMasks[c] >= 64) {
1982
break;
1983
}
1984
entity->xpos = collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
1985
scriptEng.checkResult = true;
1986
break;
1987
}
1988
case 3: {
1989
c = 15 - (YPos & 15) + (tileIndex << 4);
1990
if (collisionMasks[cPath].rWallMasks[c] <= -64) {
1991
break;
1992
}
1993
entity->xpos = 15 - collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
1994
scriptEng.checkResult = true;
1995
break;
1996
}
1997
}
1998
}
1999
}
2000
XPos += 16;
2001
}
2002
if (scriptEng.checkResult) {
2003
if (abs(entity->xpos - startX) < 16) {
2004
entity->xpos = (entity->xpos - xOffset) << 16;
2005
return;
2006
}
2007
entity->xpos = (startX - xOffset) << 16;
2008
scriptEng.checkResult = false;
2009
}
2010
}
2011
void ObjectRoofGrip(int xOffset, int yOffset, int cPath)
2012
{
2013
int c;
2014
scriptEng.checkResult = false;
2015
Entity *entity = &objectEntityList[objectEntityPos];
2016
int XPos = (entity->xpos >> 16) + xOffset;
2017
int YPos = (entity->ypos >> 16) + yOffset;
2018
int startY = YPos;
2019
YPos = YPos + 16;
2020
for (int i = 3; i > 0; i--) {
2021
if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7 && !scriptEng.checkResult) {
2022
int chunkX = XPos >> 7;
2023
int tileX = (XPos & 0x7F) >> 4;
2024
int chunkY = YPos >> 7;
2025
int tileY = (YPos & 0x7F) >> 4;
2026
int chunk = (stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6) + tileX + (tileY << 3);
2027
int tileIndex = tiles128x128.tileIndex[chunk];
2028
if (tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {
2029
switch (tiles128x128.direction[chunk]) {
2030
case 0: {
2031
c = (XPos & 15) + (tileIndex << 4);
2032
if (collisionMasks[cPath].roofMasks[c] <= -64) {
2033
break;
2034
}
2035
entity->ypos = collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);
2036
scriptEng.checkResult = true;
2037
break;
2038
}
2039
case 1: {
2040
c = 15 - (XPos & 15) + (tileIndex << 4);
2041
if (collisionMasks[cPath].roofMasks[c] <= -64) {
2042
break;
2043
}
2044
entity->ypos = collisionMasks[cPath].roofMasks[c] + (chunkY << 7) + (tileY << 4);
2045
scriptEng.checkResult = true;
2046
break;
2047
}
2048
case 2: {
2049
c = (XPos & 15) + (tileIndex << 4);
2050
if (collisionMasks[cPath].floorMasks[c] >= 64) {
2051
break;
2052
}
2053
entity->ypos = 15 - collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);
2054
scriptEng.checkResult = true;
2055
break;
2056
}
2057
case 3: {
2058
c = 15 - (XPos & 15) + (tileIndex << 4);
2059
if (collisionMasks[cPath].floorMasks[c] >= 64) {
2060
break;
2061
}
2062
entity->ypos = 15 - collisionMasks[cPath].floorMasks[c] + (chunkY << 7) + (tileY << 4);
2063
scriptEng.checkResult = true;
2064
break;
2065
}
2066
}
2067
}
2068
}
2069
YPos -= 16;
2070
}
2071
if (scriptEng.checkResult) {
2072
if (abs(entity->ypos - startY) < 16) {
2073
entity->ypos = (entity->ypos - yOffset) << 16;
2074
return;
2075
}
2076
entity->ypos = (startY - yOffset) << 16;
2077
scriptEng.checkResult = false;
2078
}
2079
}
2080
void ObjectRWallGrip(int xOffset, int yOffset, int cPath)
2081
{
2082
int c;
2083
scriptEng.checkResult = false;
2084
Entity *entity = &objectEntityList[objectEntityPos];
2085
int XPos = (entity->xpos >> 16) + xOffset;
2086
int YPos = (entity->ypos >> 16) + yOffset;
2087
int startX = XPos;
2088
XPos = XPos + 16;
2089
for (int i = 3; i > 0; i--) {
2090
if (XPos > 0 && XPos < stageLayouts[0].xsize << 7 && YPos > 0 && YPos < stageLayouts[0].ysize << 7 && !scriptEng.checkResult) {
2091
int chunkX = XPos >> 7;
2092
int tileX = (XPos & 0x7F) >> 4;
2093
int chunkY = YPos >> 7;
2094
int tileY = (YPos & 0x7F) >> 4;
2095
int chunk = (stageLayouts[0].tiles[chunkX + (chunkY << 8)] << 6) + tileX + (tileY << 3);
2096
int tileIndex = tiles128x128.tileIndex[chunk];
2097
if (tiles128x128.collisionFlags[cPath][chunk] < SOLID_NONE) {
2098
switch (tiles128x128.direction[chunk]) {
2099
case 0: {
2100
c = (YPos & 15) + (tileIndex << 4);
2101
if (collisionMasks[cPath].rWallMasks[c] <= -64) {
2102
break;
2103
}
2104
entity->xpos = collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
2105
scriptEng.checkResult = true;
2106
break;
2107
}
2108
case 1: {
2109
c = (YPos & 15) + (tileIndex << 4);
2110
if (collisionMasks[cPath].lWallMasks[c] >= 64) {
2111
break;
2112
}
2113
entity->xpos = 15 - collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
2114
scriptEng.checkResult = true;
2115
break;
2116
}
2117
case 2: {
2118
c = 15 - (YPos & 15) + (tileIndex << 4);
2119
if (collisionMasks[cPath].rWallMasks[c] <= -64) {
2120
break;
2121
}
2122
entity->xpos = collisionMasks[cPath].rWallMasks[c] + (chunkX << 7) + (tileX << 4);
2123
scriptEng.checkResult = true;
2124
break;
2125
}
2126
case 3: {
2127
c = 15 - (YPos & 15) + (tileIndex << 4);
2128
if (collisionMasks[cPath].lWallMasks[c] >= 64) {
2129
break;
2130
}
2131
entity->xpos = 15 - collisionMasks[cPath].lWallMasks[c] + (chunkX << 7) + (tileX << 4);
2132
scriptEng.checkResult = true;
2133
break;
2134
}
2135
}
2136
}
2137
}
2138
XPos -= 16;
2139
}
2140
if (scriptEng.checkResult) {
2141
if (abs(entity->xpos - startX) < 16) {
2142
entity->xpos = (entity->xpos - xOffset) << 16;
2143
return;
2144
}
2145
entity->xpos = (startX - xOffset) << 16;
2146
scriptEng.checkResult = false;
2147
}
2148
}
2149
#if RETRO_REV03
2150
void ObjectLEntityGrip(int xOffset, int yOffset, int cPath)
2151
{
2152
scriptEng.checkResult = false;
2153
Entity *entity = &objectEntityList[objectEntityPos];
2154
int mBlockID = entity->values[44];
2155
int XPos = (entity->xpos >> 16) + xOffset - 16;
2156
int YPos = (entity->ypos >> 16) + yOffset;
2157
int check = 0;
2158
if (mBlockID > 0 && objectTypeGroupList[mBlockID].listSize > 0) {
2159
TypeGroupList *mBlockGroupList = &objectTypeGroupList[mBlockID];
2160
for (int i = 0; i < objectTypeGroupList[mBlockID].listSize; i++) {
2161
short entRef = mBlockGroupList->entityRefs[i];
2162
Entity *otherEntity = &objectEntityList[entRef];
2163
int XPos2 = otherEntity->xpos >> 16;
2164
int YPos2 = otherEntity->ypos >> 16;
2165
if (((((XPos2 - 16) <= XPos) && (XPos <= (XPos2 + 16))) && ((YPos2 - 16) <= YPos)) && (YPos <= (YPos2 + 16))) {
2166
entity->xpos = otherEntity->xpos - (xOffset << 16) - 0x100000;
2167
if (otherEntity->values[0] == 0) {
2168
check = 2;
2169
scriptEng.checkResult = check;
2170
}
2171
else {
2172
scriptEng.checkResult = check;
2173
if (check != 2) {
2174
check = 1;
2175
scriptEng.checkResult = check;
2176
}
2177
}
2178
}
2179
if ((((XPos2 - 16) <= (XPos + 16) && ((XPos + 16) <= (XPos2 + 16))) && (YPos2 - 16) <= YPos) && (YPos <= (YPos2 + 16))) {
2180
entity->xpos = otherEntity->xpos - (xOffset << 16) - 0x100000;
2181
if (otherEntity->values[0] == 0) {
2182
check = 2;
2183
scriptEng.checkResult = check;
2184
}
2185
else {
2186
scriptEng.checkResult = check;
2187
if (check != 2) {
2188
scriptEng.checkResult = check;
2189
}
2190
}
2191
}
2192
2193
if (((XPos2 <= (XPos + 32)) && ((XPos + 32) <= (XPos2 + 16))) && (((YPos2 - 16) <= YPos && YPos <= (YPos2 + 16)))) {
2194
entity->xpos = otherEntity->xpos - (xOffset << 16) - 0x100000;
2195
if (otherEntity->values[0] == 0) {
2196
check = 2;
2197
scriptEng.checkResult = check;
2198
}
2199
else {
2200
scriptEng.checkResult = check;
2201
if (check != 2) {
2202
check = 1;
2203
scriptEng.checkResult = check;
2204
}
2205
}
2206
}
2207
2208
if (check != 0) {
2209
return;
2210
}
2211
}
2212
}
2213
ObjectLWallGrip(xOffset, yOffset, cPath);
2214
}
2215
void ObjectREntityGrip(int xOffset, int yOffset, int cPath)
2216
{
2217
scriptEng.checkResult = false;
2218
Entity *entity = &objectEntityList[objectEntityPos];
2219
int mBlockID = entity->values[44];
2220
int XPos = (entity->xpos >> 16) + xOffset + 16;
2221
int YPos = (entity->ypos >> 16) + yOffset;
2222
int check = 0;
2223
if (mBlockID > 0 && objectTypeGroupList[mBlockID].listSize > 0) {
2224
TypeGroupList *mBlockGroupList = &objectTypeGroupList[mBlockID];
2225
for (int i = 0; i < objectTypeGroupList[mBlockID].listSize; i++) {
2226
short entRef = mBlockGroupList->entityRefs[i];
2227
Entity *otherEntity = &objectEntityList[entRef];
2228
int XPos2 = otherEntity->xpos >> 16;
2229
int YPos2 = otherEntity->ypos >> 16;
2230
if (((((XPos2 - 16) <= XPos) && (XPos <= (XPos2 + 16))) && ((YPos2 - 16) <= YPos)) && (YPos <= (YPos2 + 16))) {
2231
entity->xpos = otherEntity->xpos + ((16 - xOffset) << 16);
2232
if (otherEntity->values[0] == 0) {
2233
check = 2;
2234
scriptEng.checkResult = check;
2235
}
2236
else {
2237
scriptEng.checkResult = check;
2238
if (check != 2) {
2239
check = 1;
2240
scriptEng.checkResult = check;
2241
}
2242
}
2243
}
2244
if ((((XPos2 - 16) <= (XPos + 16) && ((XPos - 16) <= (XPos2 + 16))) && (YPos2 - 16) <= YPos) && (YPos <= (YPos2 + 16))) {
2245
entity->xpos = otherEntity->xpos + ((16 - xOffset) << 16);
2246
if (otherEntity->values[0] == 0) {
2247
check = 2;
2248
scriptEng.checkResult = check;
2249
}
2250
else {
2251
scriptEng.checkResult = check;
2252
if (check != 2) {
2253
scriptEng.checkResult = check;
2254
}
2255
}
2256
}
2257
2258
if (((XPos2 <= (XPos - 32)) && ((XPos - 32) <= (XPos2 + 16))) && (((YPos2 - 16) <= YPos && YPos <= (YPos2 + 16)))) {
2259
entity->xpos = otherEntity->xpos + ((16 - xOffset) << 16);
2260
if (otherEntity->values[0] == 0) {
2261
check = 2;
2262
scriptEng.checkResult = check;
2263
}
2264
else {
2265
scriptEng.checkResult = check;
2266
if (check != 2) {
2267
check = 1;
2268
scriptEng.checkResult = check;
2269
}
2270
}
2271
}
2272
2273
if (check != 0) {
2274
return;
2275
}
2276
}
2277
}
2278
ObjectRWallGrip(xOffset, yOffset, cPath);
2279
}
2280
#endif
2281
void TouchCollision(Entity *thisEntity, int thisLeft, int thisTop, int thisRight, int thisBottom, Entity *otherEntity, int otherLeft, int otherTop,
2282
int otherRight, int otherBottom)
2283
{
2284
Hitbox *thisHitbox = GetHitbox(thisEntity);
2285
Hitbox *otherHitbox = GetHitbox(otherEntity);
2286
2287
if (thisLeft == C_BOX)
2288
thisLeft = thisHitbox->left[0];
2289
2290
if (thisTop == C_BOX)
2291
thisTop = thisHitbox->top[0];
2292
2293
if (thisRight == C_BOX)
2294
thisRight = thisHitbox->right[0];
2295
2296
if (thisBottom == C_BOX)
2297
thisBottom = thisHitbox->bottom[0];
2298
2299
if (otherLeft == C_BOX)
2300
otherLeft = otherHitbox->left[0];
2301
2302
if (otherTop == C_BOX)
2303
otherTop = otherHitbox->top[0];
2304
2305
if (otherRight == C_BOX)
2306
otherRight = otherHitbox->right[0];
2307
2308
if (otherBottom == C_BOX)
2309
otherBottom = otherHitbox->bottom[0];
2310
2311
#if !RETRO_USE_ORIGINAL_CODE
2312
int thisHitboxID = 0;
2313
int otherHitboxID = 0;
2314
if (showHitboxes) {
2315
thisHitboxID = AddDebugHitbox(H_TYPE_TOUCH, thisEntity, thisLeft, thisTop, thisRight, thisBottom);
2316
otherHitboxID = AddDebugHitbox(H_TYPE_TOUCH, otherEntity, otherLeft, otherTop, otherRight, otherBottom);
2317
}
2318
#endif
2319
2320
thisLeft += thisEntity->xpos >> 16;
2321
thisTop += thisEntity->ypos >> 16;
2322
thisRight += thisEntity->xpos >> 16;
2323
thisBottom += thisEntity->ypos >> 16;
2324
2325
otherLeft += otherEntity->xpos >> 16;
2326
otherTop += otherEntity->ypos >> 16;
2327
otherRight += otherEntity->xpos >> 16;
2328
otherBottom += otherEntity->ypos >> 16;
2329
2330
scriptEng.checkResult = otherRight > thisLeft && otherLeft < thisRight && otherBottom > thisTop && otherTop < thisBottom;
2331
2332
#if !RETRO_USE_ORIGINAL_CODE
2333
if (showHitboxes) {
2334
if (thisHitboxID >= 0 && scriptEng.checkResult)
2335
debugHitboxList[thisHitboxID].collision |= 1;
2336
if (otherHitboxID >= 0 && scriptEng.checkResult)
2337
debugHitboxList[otherHitboxID].collision |= 1;
2338
}
2339
#endif
2340
}
2341
void BoxCollision(Entity *thisEntity, int thisLeft, int thisTop, int thisRight, int thisBottom, Entity *otherEntity, int otherLeft, int otherTop,
2342
int otherRight, int otherBottom)
2343
{
2344
Hitbox *thisHitbox = GetHitbox(thisEntity);
2345
Hitbox *otherHitbox = GetHitbox(otherEntity);
2346
2347
if (thisLeft == C_BOX)
2348
thisLeft = thisHitbox->left[0];
2349
2350
if (thisTop == C_BOX)
2351
thisTop = thisHitbox->top[0];
2352
2353
if (thisRight == C_BOX)
2354
thisRight = thisHitbox->right[0];
2355
2356
if (thisBottom == C_BOX)
2357
thisBottom = thisHitbox->bottom[0];
2358
2359
if (otherLeft == C_BOX)
2360
otherLeft = otherHitbox->left[0];
2361
2362
if (otherTop == C_BOX)
2363
otherTop = otherHitbox->top[0];
2364
2365
if (otherRight == C_BOX)
2366
otherRight = otherHitbox->right[0];
2367
2368
if (otherBottom == C_BOX)
2369
otherBottom = otherHitbox->bottom[0];
2370
2371
#if !RETRO_USE_ORIGINAL_CODE
2372
int thisHitboxID = 0;
2373
int otherHitboxID = 0;
2374
if (showHitboxes) {
2375
thisHitboxID = AddDebugHitbox(H_TYPE_BOX, thisEntity, thisLeft, thisTop, thisRight, thisBottom);
2376
otherHitboxID = AddDebugHitbox(H_TYPE_BOX, otherEntity, otherLeft, otherTop, otherRight, otherBottom);
2377
}
2378
#endif
2379
2380
thisLeft += thisEntity->xpos >> 16;
2381
thisTop += thisEntity->ypos >> 16;
2382
thisRight += thisEntity->xpos >> 16;
2383
thisBottom += thisEntity->ypos >> 16;
2384
2385
thisLeft <<= 16;
2386
thisTop <<= 16;
2387
thisRight <<= 16;
2388
thisBottom <<= 16;
2389
2390
otherLeft <<= 16;
2391
otherTop <<= 16;
2392
otherRight <<= 16;
2393
otherBottom <<= 16;
2394
2395
scriptEng.checkResult = 0;
2396
2397
int rx = otherEntity->xpos >> 16 << 16;
2398
int ry = otherEntity->ypos >> 16 << 16;
2399
2400
int xDif = otherEntity->xpos - thisRight;
2401
if (thisEntity->xpos > otherEntity->xpos)
2402
xDif = thisLeft - otherEntity->xpos;
2403
int yDif = thisTop - otherEntity->ypos;
2404
if (thisEntity->ypos <= otherEntity->ypos)
2405
yDif = otherEntity->ypos - thisBottom;
2406
2407
if (xDif <= yDif && abs(otherEntity->xvel) >> 1 <= abs(otherEntity->yvel)) {
2408
sensors[0].collided = false;
2409
sensors[1].collided = false;
2410
sensors[2].collided = false;
2411
sensors[3].collided = false;
2412
sensors[4].collided = false;
2413
sensors[0].xpos = rx + otherLeft + 0x20000;
2414
sensors[1].xpos = rx;
2415
sensors[2].xpos = rx + otherRight - 0x20000;
2416
sensors[3].xpos = (sensors[0].xpos + rx) >> 1;
2417
sensors[4].xpos = (sensors[2].xpos + rx) >> 1;
2418
2419
sensors[0].ypos = ry + otherBottom;
2420
2421
if (otherEntity->yvel >= 0) {
2422
for (int i = 0; i < (RETRO_REV00 ? 3 : 5); ++i) {
2423
if (thisLeft < sensors[i].xpos && thisRight > sensors[i].xpos && thisTop <= sensors[0].ypos
2424
&& thisTop > otherEntity->ypos - otherEntity->yvel) {
2425
sensors[i].collided = true;
2426
otherEntity->floorSensors[i] = true;
2427
}
2428
}
2429
}
2430
2431
if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {
2432
if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {
2433
otherEntity->xvel = 0;
2434
otherEntity->speed = 0;
2435
}
2436
otherEntity->ypos = thisTop - otherBottom;
2437
otherEntity->gravity = 0;
2438
otherEntity->yvel = 0;
2439
otherEntity->angle = 0;
2440
otherEntity->rotation = 0;
2441
otherEntity->controlLock = 0;
2442
scriptEng.checkResult = 1;
2443
}
2444
else {
2445
sensors[0].collided = false;
2446
sensors[1].collided = false;
2447
sensors[0].xpos = rx + otherLeft + 0x20000;
2448
sensors[1].xpos = rx + otherRight - 0x20000;
2449
2450
sensors[0].ypos = ry + otherTop;
2451
2452
for (int i = 0; i < 2; ++i) {
2453
if (thisLeft < sensors[1].xpos && thisRight > sensors[0].xpos && thisBottom > sensors[0].ypos
2454
&& thisBottom < otherEntity->ypos - otherEntity->yvel) {
2455
sensors[i].collided = true;
2456
}
2457
}
2458
2459
if (sensors[1].collided || sensors[0].collided) {
2460
if (otherEntity->gravity == 1)
2461
otherEntity->ypos = thisBottom - otherTop;
2462
2463
if (otherEntity->yvel <= 0)
2464
otherEntity->yvel = 0;
2465
scriptEng.checkResult = 4;
2466
}
2467
else {
2468
sensors[0].collided = false;
2469
sensors[1].collided = false;
2470
sensors[0].xpos = rx + otherRight;
2471
2472
sensors[0].ypos = ry + otherTop + 0x20000;
2473
sensors[1].ypos = ry + otherBottom - 0x20000;
2474
for (int i = 0; i < 2; ++i) {
2475
if (thisLeft <= sensors[0].xpos && thisLeft > otherEntity->xpos - otherEntity->xvel && thisTop < sensors[1].ypos
2476
&& thisBottom > sensors[0].ypos) {
2477
sensors[i].collided = true;
2478
}
2479
}
2480
2481
if (sensors[1].collided || sensors[0].collided) {
2482
otherEntity->xpos = thisLeft - otherRight;
2483
if (otherEntity->xvel > 0) {
2484
if (!otherEntity->direction)
2485
otherEntity->pushing = 2;
2486
2487
otherEntity->xvel = 0;
2488
if (otherEntity->collisionMode || !otherEntity->left)
2489
otherEntity->speed = 0;
2490
else
2491
otherEntity->speed = -0x8000;
2492
}
2493
scriptEng.checkResult = 2;
2494
}
2495
else {
2496
sensors[0].collided = false;
2497
sensors[1].collided = false;
2498
sensors[0].xpos = rx + otherLeft;
2499
2500
sensors[0].ypos = ry + otherTop + 0x20000;
2501
sensors[1].ypos = ry + otherBottom - 0x20000;
2502
for (int i = 0; i < 2; ++i) {
2503
if (thisRight > sensors[0].xpos && thisRight < otherEntity->xpos - otherEntity->xvel && thisTop < sensors[1].ypos
2504
&& thisBottom > sensors[0].ypos) {
2505
sensors[i].collided = true;
2506
}
2507
}
2508
2509
if (sensors[1].collided || sensors[0].collided) {
2510
otherEntity->xpos = thisRight - otherLeft;
2511
if (otherEntity->xvel < 0) {
2512
if (otherEntity->direction == FLIP_X)
2513
otherEntity->pushing = 2;
2514
2515
if (otherEntity->xvel < -0x10000)
2516
otherEntity->xpos += 0x8000;
2517
2518
otherEntity->xvel = 0;
2519
if (otherEntity->collisionMode || !otherEntity->right)
2520
otherEntity->speed = 0;
2521
else
2522
otherEntity->speed = 0x8000;
2523
}
2524
scriptEng.checkResult = 3;
2525
}
2526
}
2527
}
2528
}
2529
}
2530
else {
2531
sensors[0].collided = false;
2532
sensors[1].collided = false;
2533
sensors[0].xpos = rx + otherRight;
2534
2535
sensors[0].ypos = ry + otherTop + 0x20000;
2536
sensors[1].ypos = ry + otherBottom - 0x20000;
2537
for (int i = 0; i < 2; ++i) {
2538
if (thisLeft <= sensors[0].xpos && thisLeft > otherEntity->xpos - otherEntity->xvel && thisTop < sensors[1].ypos
2539
&& thisBottom > sensors[0].ypos) {
2540
sensors[i].collided = true;
2541
}
2542
}
2543
if (sensors[1].collided || sensors[0].collided) {
2544
otherEntity->xpos = thisLeft - otherRight;
2545
if (otherEntity->xvel > 0) {
2546
if (!otherEntity->direction)
2547
otherEntity->pushing = 2;
2548
2549
otherEntity->xvel = 0;
2550
if (otherEntity->collisionMode || !otherEntity->left)
2551
otherEntity->speed = 0;
2552
else
2553
otherEntity->speed = -0x8000;
2554
}
2555
scriptEng.checkResult = 2;
2556
}
2557
else {
2558
sensors[0].collided = false;
2559
sensors[1].collided = false;
2560
sensors[0].xpos = rx + otherLeft;
2561
2562
sensors[0].ypos = ry + otherTop + 0x20000;
2563
sensors[1].ypos = ry + otherBottom - 0x20000;
2564
for (int i = 0; i < 2; ++i) {
2565
if (thisRight > sensors[0].xpos && thisRight < otherEntity->xpos - otherEntity->xvel && thisTop < sensors[1].ypos
2566
&& thisBottom > sensors[0].ypos) {
2567
sensors[i].collided = true;
2568
}
2569
}
2570
2571
if (sensors[0].collided || sensors[1].collided) {
2572
otherEntity->xpos = thisRight - otherLeft;
2573
if (otherEntity->xvel < 0) {
2574
if (otherEntity->direction == FLIP_X)
2575
otherEntity->pushing = 2;
2576
2577
if (otherEntity->xvel < -0x10000)
2578
otherEntity->xpos += 0x8000;
2579
2580
otherEntity->xvel = 0;
2581
if (otherEntity->collisionMode || !otherEntity->right)
2582
otherEntity->speed = 0;
2583
else
2584
otherEntity->speed = 0x8000;
2585
}
2586
scriptEng.checkResult = 3;
2587
}
2588
else {
2589
sensors[0].collided = false;
2590
sensors[1].collided = false;
2591
sensors[2].collided = false;
2592
sensors[3].collided = false;
2593
sensors[4].collided = false;
2594
sensors[0].xpos = rx + otherLeft + 0x20000;
2595
sensors[1].xpos = rx;
2596
sensors[2].xpos = rx + otherRight - 0x20000;
2597
sensors[3].xpos = (sensors[0].xpos + rx) >> 1;
2598
sensors[4].xpos = (sensors[2].xpos + rx) >> 1;
2599
2600
sensors[0].ypos = ry + otherBottom;
2601
if (otherEntity->yvel >= 0) {
2602
for (int i = 0; i < (RETRO_REV00 ? 3 : 5); ++i) {
2603
if (thisLeft < sensors[i].xpos && thisRight > sensors[i].xpos && thisTop <= sensors[0].ypos
2604
&& thisTop > otherEntity->ypos - otherEntity->yvel) {
2605
sensors[i].collided = true;
2606
otherEntity->floorSensors[i] = true;
2607
}
2608
}
2609
}
2610
if (sensors[2].collided || sensors[1].collided || sensors[0].collided) {
2611
if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {
2612
otherEntity->xvel = 0;
2613
otherEntity->speed = 0;
2614
}
2615
otherEntity->ypos = thisTop - otherBottom;
2616
otherEntity->gravity = 0;
2617
otherEntity->yvel = 0;
2618
otherEntity->angle = 0;
2619
otherEntity->rotation = 0;
2620
otherEntity->controlLock = 0;
2621
scriptEng.checkResult = 1;
2622
}
2623
else {
2624
sensors[0].collided = false;
2625
sensors[1].collided = false;
2626
sensors[0].xpos = rx + otherLeft + 0x20000;
2627
sensors[1].xpos = rx + otherRight - 0x20000;
2628
sensors[0].ypos = ry + otherTop;
2629
2630
for (int i = 0; i < 2; ++i) {
2631
if (thisLeft < sensors[1].xpos && thisRight > sensors[0].xpos && thisBottom > sensors[0].ypos
2632
&& thisBottom < otherEntity->ypos - otherEntity->yvel) {
2633
sensors[i].collided = true;
2634
}
2635
}
2636
2637
if (sensors[1].collided || sensors[0].collided) {
2638
if (otherEntity->gravity == 1)
2639
otherEntity->ypos = thisBottom - otherTop;
2640
2641
if (otherEntity->yvel <= 0)
2642
otherEntity->yvel = 0;
2643
scriptEng.checkResult = 4;
2644
}
2645
}
2646
}
2647
}
2648
}
2649
2650
#if !RETRO_USE_ORIGINAL_CODE
2651
if (showHitboxes) {
2652
if (thisHitboxID >= 0 && scriptEng.checkResult)
2653
debugHitboxList[thisHitboxID].collision |= 1 << (scriptEng.checkResult - 1);
2654
if (otherHitboxID >= 0 && scriptEng.checkResult)
2655
debugHitboxList[otherHitboxID].collision |= 1 << (4 - scriptEng.checkResult);
2656
}
2657
#endif
2658
}
2659
void BoxCollision2(Entity *thisEntity, int thisLeft, int thisTop, int thisRight, int thisBottom, Entity *otherEntity, int otherLeft, int otherTop,
2660
int otherRight, int otherBottom)
2661
{
2662
Hitbox *thisHitbox = GetHitbox(thisEntity);
2663
Hitbox *otherHitbox = GetHitbox(otherEntity);
2664
2665
if (thisLeft == C_BOX)
2666
thisLeft = thisHitbox->left[0];
2667
2668
if (thisTop == C_BOX)
2669
thisTop = thisHitbox->top[0];
2670
2671
if (thisRight == C_BOX)
2672
thisRight = thisHitbox->right[0];
2673
2674
if (thisBottom == C_BOX)
2675
thisBottom = thisHitbox->bottom[0];
2676
2677
if (otherLeft == C_BOX)
2678
otherLeft = otherHitbox->left[0];
2679
2680
if (otherTop == C_BOX)
2681
otherTop = otherHitbox->top[0];
2682
2683
if (otherRight == C_BOX)
2684
otherRight = otherHitbox->right[0];
2685
2686
if (otherBottom == C_BOX)
2687
otherBottom = otherHitbox->bottom[0];
2688
2689
#if !RETRO_USE_ORIGINAL_CODE
2690
int thisHitboxID = 0;
2691
int otherHitboxID = 0;
2692
if (showHitboxes) {
2693
thisHitboxID = AddDebugHitbox(H_TYPE_BOX, thisEntity, thisLeft, thisTop, thisRight, thisBottom);
2694
otherHitboxID = AddDebugHitbox(H_TYPE_BOX, otherEntity, otherLeft, otherTop, otherRight, otherBottom);
2695
}
2696
#endif
2697
2698
thisLeft += thisEntity->xpos >> 16;
2699
thisTop += thisEntity->ypos >> 16;
2700
thisRight += thisEntity->xpos >> 16;
2701
thisBottom += thisEntity->ypos >> 16;
2702
2703
thisLeft <<= 16;
2704
thisTop <<= 16;
2705
thisRight <<= 16;
2706
thisBottom <<= 16;
2707
2708
otherLeft <<= 16;
2709
otherTop <<= 16;
2710
otherRight <<= 16;
2711
otherBottom <<= 16;
2712
2713
scriptEng.checkResult = 0;
2714
2715
int rx = otherEntity->xpos >> 16 << 16;
2716
int ry = otherEntity->ypos >> 16 << 16;
2717
2718
int xDif = thisLeft - rx;
2719
if (thisEntity->xpos <= rx)
2720
xDif = rx - thisRight;
2721
int yDif = thisTop - ry;
2722
if (thisEntity->ypos <= ry)
2723
yDif = ry - thisBottom;
2724
2725
if (xDif <= yDif) {
2726
sensors[0].collided = false;
2727
sensors[1].collided = false;
2728
sensors[2].collided = false;
2729
sensors[0].xpos = rx + otherLeft + 0x20000;
2730
sensors[1].xpos = rx;
2731
sensors[2].xpos = rx + otherRight - 0x20000;
2732
2733
sensors[0].ypos = ry + otherBottom;
2734
2735
if (otherEntity->yvel >= 0) {
2736
// this should prolly be using all 5 sensors, but this was barely used in S2 so it was prolly forgotten about
2737
for (int i = 0; i < 3; ++i) {
2738
if (thisLeft < sensors[i].xpos && thisRight > sensors[i].xpos && thisTop <= sensors[0].ypos && thisEntity->ypos > sensors[0].ypos) {
2739
sensors[i].collided = true;
2740
otherEntity->floorSensors[i] = true;
2741
}
2742
}
2743
}
2744
2745
if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {
2746
if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {
2747
otherEntity->xvel = 0;
2748
otherEntity->speed = 0;
2749
}
2750
otherEntity->ypos = thisTop - otherBottom;
2751
otherEntity->gravity = 0;
2752
otherEntity->yvel = 0;
2753
otherEntity->angle = 0;
2754
otherEntity->rotation = 0;
2755
otherEntity->controlLock = 0;
2756
scriptEng.checkResult = 1;
2757
}
2758
else {
2759
sensors[0].collided = false;
2760
sensors[1].collided = false;
2761
sensors[0].xpos = rx + otherLeft + 0x20000;
2762
sensors[1].xpos = rx + otherRight - 0x20000;
2763
2764
sensors[0].ypos = ry + otherTop;
2765
2766
for (int i = 0; i < 2; ++i) {
2767
if (thisLeft < sensors[1].xpos && thisRight > sensors[0].xpos && thisBottom > sensors[0].ypos && thisEntity->ypos < sensors[0].ypos) {
2768
sensors[i].collided = true;
2769
}
2770
}
2771
2772
if (sensors[1].collided || sensors[0].collided) {
2773
if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {
2774
otherEntity->xvel = 0;
2775
otherEntity->speed = 0;
2776
}
2777
2778
otherEntity->ypos = thisBottom - otherTop;
2779
if (otherEntity->yvel < 0)
2780
otherEntity->yvel = 0;
2781
scriptEng.checkResult = 4;
2782
}
2783
else {
2784
sensors[0].collided = false;
2785
sensors[1].collided = false;
2786
sensors[0].xpos = rx + otherRight;
2787
2788
sensors[0].ypos = ry + otherTop + 0x20000;
2789
sensors[1].ypos = ry + otherBottom - 0x20000;
2790
for (int i = 0; i < 2; ++i) {
2791
if (thisLeft <= sensors[0].xpos && thisEntity->xpos > sensors[0].xpos && thisTop < sensors[1].ypos
2792
&& thisBottom > sensors[0].ypos) {
2793
sensors[i].collided = true;
2794
}
2795
}
2796
2797
if (sensors[1].collided || sensors[0].collided) {
2798
otherEntity->xpos = thisLeft - otherRight;
2799
if (otherEntity->xvel > 0) {
2800
if (!otherEntity->direction)
2801
otherEntity->pushing = 2;
2802
2803
otherEntity->xvel = 0;
2804
otherEntity->speed = 0;
2805
}
2806
scriptEng.checkResult = 2;
2807
}
2808
else {
2809
sensors[0].collided = false;
2810
sensors[1].collided = false;
2811
sensors[0].xpos = rx + otherLeft;
2812
2813
sensors[0].ypos = ry + otherTop + 0x20000;
2814
sensors[1].ypos = ry + otherBottom - 0x20000;
2815
for (int i = 0; i < 2; ++i) {
2816
if (thisRight > sensors[0].xpos && thisEntity->xpos < sensors[0].xpos && thisTop < sensors[1].ypos
2817
&& thisBottom > sensors[0].ypos) {
2818
sensors[i].collided = true;
2819
}
2820
}
2821
2822
if (sensors[1].collided || sensors[0].collided) {
2823
otherEntity->xpos = thisRight - otherLeft;
2824
if (otherEntity->xvel < 0) {
2825
if (otherEntity->direction == FLIP_X)
2826
otherEntity->pushing = 2;
2827
2828
if (otherEntity->xvel < -0x10000)
2829
otherEntity->xpos += 0x8000;
2830
2831
otherEntity->xvel = 0;
2832
otherEntity->speed = 0;
2833
}
2834
scriptEng.checkResult = 3;
2835
}
2836
}
2837
}
2838
}
2839
}
2840
else {
2841
sensors[0].collided = false;
2842
sensors[1].collided = false;
2843
sensors[0].xpos = rx + otherRight;
2844
2845
sensors[0].ypos = ry + otherTop + 0x20000;
2846
sensors[1].ypos = ry + otherBottom - 0x20000;
2847
for (int i = 0; i < 2; ++i) {
2848
if (thisLeft <= sensors[0].xpos && thisEntity->xpos > sensors[0].xpos && thisTop < sensors[1].ypos && thisBottom > sensors[0].ypos) {
2849
sensors[i].collided = true;
2850
}
2851
}
2852
if (sensors[1].collided || sensors[0].collided) {
2853
otherEntity->xpos = thisLeft - otherRight;
2854
if (otherEntity->xvel > 0) {
2855
if (!otherEntity->direction)
2856
otherEntity->pushing = 2;
2857
2858
otherEntity->xvel = 0;
2859
otherEntity->speed = 0;
2860
}
2861
scriptEng.checkResult = 2;
2862
}
2863
else {
2864
sensors[0].collided = false;
2865
sensors[1].collided = false;
2866
sensors[0].xpos = rx + otherLeft;
2867
2868
sensors[0].ypos = ry + otherTop + 0x20000;
2869
sensors[1].ypos = ry + otherBottom - 0x20000;
2870
for (int i = 0; i < 2; ++i) {
2871
if (thisRight > sensors[0].xpos && thisEntity->xpos < sensors[0].xpos && thisTop < sensors[1].ypos && thisBottom > sensors[0].ypos) {
2872
sensors[i].collided = true;
2873
}
2874
}
2875
2876
if (sensors[0].collided || sensors[1].collided) {
2877
otherEntity->xpos = thisRight - otherLeft;
2878
if (otherEntity->xvel < 0) {
2879
if (otherEntity->direction == FLIP_X)
2880
otherEntity->pushing = 2;
2881
2882
if (otherEntity->xvel < -0x10000)
2883
otherEntity->xpos += 0x8000;
2884
2885
otherEntity->xvel = 0;
2886
otherEntity->speed = 0;
2887
}
2888
scriptEng.checkResult = 3;
2889
}
2890
else {
2891
sensors[0].collided = false;
2892
sensors[1].collided = false;
2893
sensors[2].collided = false;
2894
sensors[0].xpos = rx + otherLeft + 0x20000;
2895
sensors[1].xpos = rx;
2896
sensors[2].xpos = rx + otherRight - 0x20000;
2897
2898
sensors[0].ypos = ry + otherBottom;
2899
if (otherEntity->yvel >= 0) {
2900
for (int i = 0; i < 3; ++i) {
2901
if (thisLeft < sensors[i].xpos && thisRight > sensors[i].xpos && thisTop <= sensors[0].ypos
2902
&& thisEntity->ypos > sensors[0].ypos) {
2903
sensors[i].collided = true;
2904
otherEntity->floorSensors[i] = true;
2905
}
2906
}
2907
}
2908
2909
if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {
2910
if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {
2911
otherEntity->xvel = 0;
2912
otherEntity->speed = 0;
2913
}
2914
otherEntity->ypos = thisTop - otherBottom;
2915
otherEntity->gravity = 0;
2916
otherEntity->yvel = 0;
2917
otherEntity->angle = 0;
2918
otherEntity->rotation = 0;
2919
otherEntity->controlLock = 0;
2920
scriptEng.checkResult = 1;
2921
}
2922
else {
2923
sensors[0].collided = false;
2924
sensors[1].collided = false;
2925
sensors[0].xpos = rx + otherLeft + 0x20000;
2926
sensors[1].xpos = rx + otherRight - 0x20000;
2927
2928
sensors[0].ypos = ry + otherTop;
2929
2930
for (int i = 0; i < 2; ++i) {
2931
if (thisLeft < sensors[1].xpos && thisRight > sensors[0].xpos && thisBottom > sensors[0].ypos
2932
&& thisEntity->ypos < sensors[0].ypos) {
2933
sensors[i].collided = true;
2934
}
2935
}
2936
2937
if (sensors[1].collided || sensors[0].collided) {
2938
if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {
2939
otherEntity->xvel = 0;
2940
otherEntity->speed = 0;
2941
}
2942
2943
otherEntity->ypos = thisBottom - otherTop;
2944
2945
if (otherEntity->yvel < 0)
2946
otherEntity->yvel = 0;
2947
scriptEng.checkResult = 4;
2948
}
2949
}
2950
}
2951
}
2952
}
2953
2954
#if !RETRO_USE_ORIGINAL_CODE
2955
if (showHitboxes) {
2956
if (thisHitboxID >= 0 && scriptEng.checkResult)
2957
debugHitboxList[thisHitboxID].collision |= 1 << (scriptEng.checkResult - 1);
2958
if (otherHitboxID >= 0 && scriptEng.checkResult)
2959
debugHitboxList[otherHitboxID].collision |= 1 << (4 - scriptEng.checkResult);
2960
}
2961
#endif
2962
}
2963
void PlatformCollision(Entity *thisEntity, int thisLeft, int thisTop, int thisRight, int thisBottom, Entity *otherEntity, int otherLeft, int otherTop,
2964
int otherRight, int otherBottom)
2965
{
2966
scriptEng.checkResult = false;
2967
2968
Hitbox *thisHitbox = GetHitbox(thisEntity);
2969
Hitbox *otherHitbox = GetHitbox(otherEntity);
2970
2971
if (thisLeft == C_BOX)
2972
thisLeft = thisHitbox->left[0];
2973
2974
if (thisTop == C_BOX)
2975
thisTop = thisHitbox->top[0];
2976
2977
if (thisRight == C_BOX)
2978
thisRight = thisHitbox->right[0];
2979
2980
if (thisBottom == C_BOX)
2981
thisBottom = thisHitbox->bottom[0];
2982
2983
if (otherLeft == C_BOX)
2984
otherLeft = otherHitbox->left[0];
2985
2986
if (otherTop == C_BOX)
2987
otherTop = otherHitbox->top[0];
2988
2989
if (otherRight == C_BOX)
2990
otherRight = otherHitbox->right[0];
2991
2992
if (otherBottom == C_BOX)
2993
otherBottom = otherHitbox->bottom[0];
2994
2995
#if !RETRO_USE_ORIGINAL_CODE
2996
int thisHitboxID = 0;
2997
int otherHitboxID = 0;
2998
if (showHitboxes) {
2999
thisHitboxID = AddDebugHitbox(H_TYPE_PLAT, thisEntity, thisLeft, thisTop, thisRight, thisBottom);
3000
otherHitboxID = AddDebugHitbox(H_TYPE_PLAT, otherEntity, otherLeft, otherTop, otherRight, otherBottom);
3001
}
3002
#endif
3003
3004
thisLeft += thisEntity->xpos >> 16;
3005
thisTop += thisEntity->ypos >> 16;
3006
thisRight += thisEntity->xpos >> 16;
3007
thisBottom += thisEntity->ypos >> 16;
3008
3009
thisLeft <<= 16;
3010
thisTop <<= 16;
3011
thisRight <<= 16;
3012
thisBottom <<= 16;
3013
3014
sensors[0].collided = false;
3015
sensors[1].collided = false;
3016
sensors[2].collided = false;
3017
3018
int rx = otherEntity->xpos >> 16 << 16;
3019
int ry = otherEntity->ypos >> 16 << 16;
3020
3021
sensors[0].xpos = rx + (otherLeft << 16);
3022
sensors[1].xpos = rx;
3023
sensors[2].xpos = rx + (otherRight << 16);
3024
sensors[3].xpos = (rx + sensors[0].xpos) >> 1;
3025
sensors[4].xpos = (sensors[2].xpos + rx) >> 1;
3026
3027
sensors[0].ypos = (otherBottom << 16) + ry;
3028
3029
for (int i = 0; i < (RETRO_REV00 ? 3 : 5); ++i) {
3030
if (thisLeft < sensors[i].xpos && thisRight > sensors[i].xpos && thisTop - 1 <= sensors[0].ypos && thisBottom > sensors[0].ypos
3031
&& otherEntity->yvel >= 0) {
3032
sensors[i].collided = true;
3033
otherEntity->floorSensors[i] = true;
3034
}
3035
}
3036
3037
if (sensors[0].collided || sensors[1].collided || sensors[2].collided) {
3038
if (!otherEntity->gravity && (otherEntity->collisionMode == CMODE_RWALL || otherEntity->collisionMode == CMODE_LWALL)) {
3039
otherEntity->xvel = 0;
3040
otherEntity->speed = 0;
3041
}
3042
otherEntity->ypos = thisTop - (otherBottom << 16);
3043
otherEntity->gravity = 0;
3044
otherEntity->yvel = 0;
3045
otherEntity->angle = 0;
3046
otherEntity->rotation = 0;
3047
otherEntity->controlLock = 0;
3048
scriptEng.checkResult = true;
3049
}
3050
3051
#if !RETRO_USE_ORIGINAL_CODE
3052
if (showHitboxes) {
3053
if (thisHitboxID >= 0 && scriptEng.checkResult)
3054
debugHitboxList[thisHitboxID].collision |= 1 << 0;
3055
if (otherHitboxID >= 0 && scriptEng.checkResult)
3056
debugHitboxList[otherHitboxID].collision |= 1 << 3;
3057
}
3058
#endif
3059
}
3060
3061