231 progress, not done, Teeth+Burst

This commit is contained in:
Niko 2023-08-06 16:55:11 -04:00
parent bb512a3286
commit 20026cf29d
15 changed files with 400 additions and 408 deletions

View File

@ -0,0 +1,34 @@
#include <common.h>
void DECOMP_RB_Burst_CollLevInst(struct ScratchpadStruct* sps,struct BSP* bspHitbox)
{
short model;
struct Instance* inst;
struct InstDef* instdef;
struct MetaDataMODEL* meta;
instdef = bspHitbox->data.hitbox.instDef;
if(instdef == NULL) return;
inst = instdef->ptrInstance;
if(inst == NULL) return;
model = instdef->modelID;
if(model < 7) return;
// check 7 and 8,
// 7: PU_FRUIT_CRATE
// 8: PU_RANDOM_CRATE (weapon box)
if (model < 9)
{
// skip nullptr checks, nullptr is not possible
meta = COLL_LevModelMeta(model);
meta->LInC(inst,sps->Union.ThBuckColl.thread,sps);
return;
}
if (model == 0x70)
RB_Teeth_OpenDoor(inst);
return;
}

View File

@ -0,0 +1,345 @@
#include <common.h>
void DECOMP_RB_Teeth_OpenDoor();
// need this cause OpenDoor can't relocate,
// feel free to remove later
void Teeth_Padding()
{
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
void DECOMP_RB_Teeth_LInB(struct Instance* inst)
{
inst->unk50 += 2;
// If in relic race
if ((sdata->gGT->gameMode1 & RELIC_RACE) != 0)
{
// enable access through a door (disable collision)
sdata->doorAccessFlags |= 1;
// Make invisible
inst->flags |= 0x80;
}
return;
}
void DECOMP_RB_Teeth_BSP_Callback(struct ScratchpadStruct* sps,struct Thread* weaponThread)
{
short model;
struct Thread* teethTh;
struct Instance* weaponInst;
struct Instance* teethInst;
int iVar5;
model = weaponThread->modelIndex;
// if not driver
if (model != 0x18)
{
if (model < 0x19)
{
// if not nitro
if (model != 6) {
return;
}
}
else
{
// if not potion or tnt
if ((model != 0x1d) && (model != 0x27)) {
return;
}
}
}
teethTh = sps->Union.ThBuckColl.thread;
weaponInst = weaponThread->inst;
teethInst = teethTh->inst;
if ((weaponInst != NULL) && (teethInst != NULL)) {
iVar5 = ((int)sps->Input1.pos[0] - weaponInst->matrix.t[0]) * (int)teethInst->matrix.m[0][2] +
((int)sps->Input1.pos[2] - weaponInst->matrix.t[2]) * (int)teethInst->matrix.m[2][2];
// catch negative value
if (iVar5 < 0) {
iVar5 = -iVar5;
}
if (0x100 < iVar5 >> 0xc) {
return;
}
}
// door is open
((struct Teeth*)teethTh->object)->direction = 1;
return;
}
void DECOMP_RB_Teeth_ThTick(struct Thread* t)
{
int iVar1;
u_int flags;
struct Teeth* teeth;
struct Instance* inst;
struct GameTracker* gGT;
gGT = sdata->gGT;
teeth = t->object;
inst = t->inst;
#define SPS \
((struct ScratchpadStruct*)0x1f800108)
// if door is not moving
if (teeth->direction == 0)
{
// if timer is zero
if (teeth->timeOpen == 0) goto LAB_800b9ff8;
// reduce timer by milliseconds
iVar1 = teeth->timeOpen - gGT->elapsedTimeMS;
// set new timer
teeth->timeOpen = iVar1;
// if timer is up
if (iVar1 < 1)
{
// play sound
// teeth closing
PlaySound3D(0x75,inst);
// timer is zero
teeth->timeOpen = 0;
// door is closing
teeth->direction = -1;
goto LAB_800b9fe8;
}
}
// if door is moving
else
{
// modify animation index by direction
inst->animFrame = inst->animFrame + teeth->direction;
iVar1 = Instance_GetNumAnimFrames(inst,0);
// if animation is not on last frame
if ((int)inst->animFrame < iVar1)
{
// if animation when backwards past beginning
if ((int)inst->animFrame < 0)
{
// set animation to beginning
inst->animFrame = 0;
// door is not moving
teeth->direction = 0;
// timer is zero
teeth->timeOpen = 0;
// remove access (enable collision)
sdata->doorAccessFlags &= 0xfffffffe;
}
}
// if animation is on last frame (or past)
else
{
// set animation to last frame
inst->animFrame = (short)iVar1 + -1;
// door is not moving (fully open)
teeth->direction = 0;
// timer, 2 seconds
teeth->timeOpen = 0x780;
}
LAB_800b9fe8:
if (teeth->timeOpen == 0) {
LAB_800b9ff8:
if (-1 < teeth->direction) goto LAB_800ba084;
}
}
// Teeth instance position
SPS->Input1.pos[0] = inst->matrix.t[0];
SPS->Input1.pos[1] = inst->matrix.t[1];
SPS->Input1.pos[2] = inst->matrix.t[2];
SPS->Input1.hitRadius = 0x300;
SPS->Input1.hitRadiusSquared = 0x90000;
SPS->Input1.modelID = 0x70;
SPS->Union.ThBuckColl.thread = t;
SPS->Union.ThBuckColl.funcCallback = DECOMP_RB_Teeth_BSP_Callback;
// If door wants to close, but Player or Mine
// is in the way, then do not force the doors to close
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[PLAYER].thread,SPS,0);
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[MINE].thread,SPS,0);
LAB_800ba084:
// if no timer exists
// (opening, closing, or full closed)
if (teeth->timeOpen == 0)
{
// make visible
flags = inst->flags & 0xffffff7f;
}
// if a timer is active
// (fully open)
else
{
// make invisible
flags = inst->flags | 0x80;
}
inst->flags = flags;
return;
}
int DECOMP_RB_Teeth_LInC(struct Instance *teethInst, struct Thread *t, struct ScratchpadStruct* sps)
{
int iVar1;
struct Thread *teethTh;
struct Teeth *teeth;
struct Driver *d;
// This is the door you can shoot in tiger temple
// If in relic race, ignore the function,
// there are no weapons to activate door anyways
if ((sdata->gGT->gameMode1 & RELIC_RACE) != 0)
return;
teethTh = teethInst->thread;
d = t->object;
if (teethTh == NULL)
{
// 0x8 = size
// 0 = no relation to param4
// 0x300 = SmallStackPool
// 0x3 = "static" thread bucket
teethTh = THREAD_BirthWithObject(0x80303, DECOMP_RB_Teeth_ThTick, 0, 0);
teethInst->thread = teethTh;
if (teethTh == NULL)
{
return 2;
}
teeth = teethTh->object;
teethTh->inst = teethInst;
// door not moving
teeth->direction = 0;
// timer is zero
teeth->timeOpen = 0;
}
teeth = teethTh->object;
// if collided object is a player
if (sps->Input1.modelID == 0x18)
{
// if driver is using mask weapon
if ((d->actionsFlagSet & 0x800000) != 0)
{
RB_Teeth_OpenDoor(teethInst);
}
return 2;
}
// If collide with something
// that is not a player
// time to close
if (teeth->timeOpen == 0)
{
iVar1 =
((int)sps->Input1.pos[0] - teethInst->matrix.t[0]) * (int)teethInst->matrix.m[0][2] +
((int)sps->Input1.pos[2] - teethInst->matrix.t[2]) * (int)teethInst->matrix.m[2][2];
if (iVar1 < 0)
{
iVar1 = -iVar1;
}
if (iVar1 >> 0xc < 0x81)
{
return 1;
}
return 2;
}
return 2;
}
void DECOMP_RB_Teeth_OpenDoor(struct Instance* inst)
{
struct Thread* teethTh = inst->thread;
// if there is no thread,
// just in case it wasn't initialized
if (teethTh == NULL)
{
// 0x8 = size
// 0 = no relation to param4
// 0x300 flag = SmallStackPool
// 0x3 = "static" thread bucket
teethTh = THREAD_BirthWithObject(0x80303,DECOMP_RB_Teeth_ThTick,0,0);
inst->thread = teethTh;
if (teethTh == NULL)
{
return;
}
teethTh->inst = inst;
((struct Teeth*)teethTh->object)->timeOpen = 0;
}
// play sound,
// teeth opening
PlaySound3D(0x75,inst);
// door is open
((struct Teeth*)teethTh->object)->direction = 1;
// enable access through a door (disable collision)
sdata->doorAccessFlags |= 1;
return;
}

View File

@ -29,8 +29,8 @@ void DECOMP_RB_CtrLetter_LInB();
void DECOMP_RB_CtrLetter_LInC();
void DECOMP_RB_Crystal_LInB();
void DECOMP_RB_Crystal_LInC();
void RB_Teeth_LInB();
void RB_Teeth_LInC();
void DECOMP_RB_Teeth_LInB();
void DECOMP_RB_Teeth_LInC();
void AH_Door_LInB();
void AH_Sign_LInB();
@ -608,7 +608,7 @@ struct Data data =
SET_MDM(0,0,0),
// 0x70 - STATIC_TEETH
SET_MDM(0,RB_Teeth_LInB,RB_Teeth_LInC),
SET_MDM(0,DECOMP_RB_Teeth_LInB,DECOMP_RB_Teeth_LInC),
// 0x71 - STATIC_STARTTEXT
SET_MDM(0,0/*RB_StartText_LInB*/,0),

View File

@ -1,49 +0,0 @@
#include <common.h>
void DECOMP_RB_Burst_CollLevInst(struct ScratchpadStruct* sps,struct BSP* bspHitbox)
{
short model;
struct InstDef* instdef;
struct Thread* meta;
struct Instance* inst;
instdef = bspHitbox->data.hitbox.instDef;
if (
// if InstDef exists
(instdef != NULL) &&
(inst = instdef->ptrInstance, inst != NULL)
)
{
model = instdef->modelID;
if (6 < model)
{
// check 7 and 8,
// 7: PU_FRUIT_CRATE
// 8: PU_RANDOM_CRATE (weapon box)
if (model < 9)
{
meta = COLL_LevModelMeta();
// if funcLevThreadsBirth is not nullptr
if ((meta != 0) && (*(code **)(meta + 8) != NULL))
{
// execute funcLevThreadsBirth, make thread for this instance
// upon collision with the instance, let it run thread->funcThCollide
(**(code **)(meta + 8))(inst,sps->Union.ThBuckColl.thread,sps);
}
}
else
{
// modelID == teeth
if (model == 0x70)
{
RB_Teeth_OpenDoor(inst);
}
}
}
}
return;
}

View File

@ -1,56 +0,0 @@
#include <common.h>
void DECOMP_RB_Teeth_BSP_Callback(struct ScratchpadStruct* sps,struct Thread* weaponThread)
{
short model;
struct Thread* teethTh;
struct Instance* weaponInst;
struct Instance* teethInst;
int iVar5;
model = weaponThread->modelIndex;
// if not driver
if (model != 0x18)
{
if (model < 0x19)
{
// if not nitro
if (model != 6) {
return;
}
}
else
{
// if not potion or tnt
if ((model != 0x1d) && (model != 0x27)) {
return;
}
}
}
teethTh = sps->Union.ThBuckColl.thread;
weaponInst = weaponThread->inst;
teethInst = teethTh->inst;
if ((weaponInst != NULL) && (teethInst != NULL)) {
iVar5 = ((int)sps->Input1.pos[0] - weaponInst->matrix.t[0]) * (int)teethInst->matrix.m[0][2] +
((int)sps->Input1.pos[2] - weaponInst->matrix.t[2]) * (int)teethInst->matrix.m[2][2];
// catch negative value
if (iVar5 < 0) {
iVar5 = -iVar5;
}
if (0x100 < iVar5 >> 0xc) {
return;
}
}
// door is open
((struct Teeth*)teethTh->object)->direction = 1;
return;
}

View File

@ -1,21 +0,0 @@
#include <common.h>
void DECOMP_RB_Teeth_LInB(undefined4 unused,struct Instance* inst)
{
// Do not make a thread for time trial, or relic.
// Time Trial will be forever closed
// Relic will be forever open
inst->unk50 += 2;
// If in relic race
if ((sdata->gGT->gameMode1 & ARCADE_MODE0) != 0)
{
// enable access through a door (disable collision)
sdata->doorAccessFlags |= 1;
// Make invisible
inst->flags |= 0x80;
}
return;
}

View File

@ -1,83 +0,0 @@
#include <common.h>
void RB_Teeth_ThTick(struct Thread *);
int DECOMP_RB_Teeth_LInC(struct Instance *teethInst, struct Thread *t, struct ScratchpadStruct* sps)
{
int iVar1;
struct Thread *teethTh;
struct Teeth *teeth;
struct Driver *d;
// This is the door you can shoot in tiger temple
// If not in relic race, ignore the function,
// there are no weapons to activate door anyways
if ((sdata->gGT->gameMode1 & ARCADE_MODE0) == 0)
return;
teethTh = teethInst->thread;
d = t->object;
if (teethTh == NULL)
{
// 0x8 = size
// 0 = no relation to param4
// 0x300 = SmallStackPool
// 0x3 = "static" thread bucket
teethTh = THREAD_BirthWithObject(0x80303, RB_Teeth_ThTick, s_teeth_800b9de8, 0);
teethInst->thread = teethTh;
if (teethTh == NULL)
{
return 2;
}
teeth = teethTh->object;
teethTh->inst = teethInst;
// door not moving
teeth->direction = 0;
// timer is zero
teeth->timeOpen = 0;
}
teeth = teethTh->object;
// if collided object is a player
if (sps->Input1.modelID == 0x18)
{
// if driver is using mask weapon
if ((d->actionsFlagSet & 0x800000) != 0)
{
RB_Teeth_OpenDoor(teethInst);
}
return 2;
}
// If collide with something
// that is not a player
// time to close
if (teeth->timeOpen == 0)
{
iVar1 =
((int)sps->Input1.pos[0] - teethInst->matrix.t[0]) * (int)teethInst->matrix.m[0][2] +
((int)sps->Input1.pos[2] - teethInst->matrix.t[2]) * (int)teethInst->matrix.m[2][2];
if (iVar1 < 0)
{
iVar1 = -iVar1;
}
if (iVar1 >> 0xc < 0x81)
{
return 1;
}
return 2;
}
return 2;
}

View File

@ -1,43 +0,0 @@
#include <common.h>
void RB_Teeth_ThTick(struct Thread*);
void DECOMP_RB_Teeth_OpenDoor(struct Instance* inst)
{
struct Thread* teethTh = inst->thread;
// if there is no thread,
// just in case it wasn't initialized
if (teethTh == NULL)
{
// 0x8 = size
// 0 = no relation to param4
// 0x300 flag = SmallStackPool
// 0x3 = "static" thread bucket
teethTh = THREAD_BirthWithObject(0x80303,RB_Teeth_ThTick,s_teeth_800b9de8,0);
inst->thread = teethTh;
if (teethTh == NULL)
{
return;
}
teethTh->inst = inst;
((struct Teeth*)teethTh->object)->timeOpen = 0;
}
// play sound,
// teeth opening
PlaySound3D(0x75,inst);
// door is open
((struct Teeth*)teethTh->object)->direction = 1;
// enable access through a door (disable collision)
sdata->doorAccessFlags |= 1;
return;
}

View File

@ -1,136 +0,0 @@
#include <common.h>
void RB_Teeth_BSP_Callback(struct ScratchpadStruct*,struct Thread*);
void DECOMP_RB_Teeth_ThTick(struct Thread* t)
{
int iVar1;
u_int flags;
struct Teeth* teeth;
struct Instance* inst;
teeth = t->object;
inst = t->inst;
#define SPS \
((struct ScratchpadStruct*)0x1f800108)
// if door is not moving
if (teeth->direction == 0)
{
// if timer is zero
if (teeth->timeOpen == 0) goto LAB_800b9ff8;
// reduce timer by milliseconds
iVar1 = teeth->timeOpen - sdata->gGT->elapsedTimeMS;
// set new timer
teeth->timeOpen = iVar1;
// if timer is up
if (iVar1 < 1)
{
// play sound
// teeth closing
PlaySound3D(0x75,inst);
// timer is zero
teeth->timeOpen = 0;
// door is closing
teeth->direction = -1;
goto LAB_800b9fe8;
}
}
// if door is moving
else
{
// modify animation index by direction
inst->animFrame = inst->animFrame + teeth->direction;
iVar1 = Instance_GetNumAnimFrames(inst,0);
// if animation is not on last frame
if ((int)inst->animFrame < iVar1)
{
// if animation when backwards past beginning
if ((int)inst->animFrame < 0)
{
// set animation to beginning
inst->animFrame = 0;
// door is not moving
teeth->direction = 0;
// timer is zero
teeth->timeOpen = 0;
// remove access (enable collision)
sdata->doorAccessFlags &= 0xfffffffe;
}
}
// if animation is on last frame (or past)
else
{
// set animation to last frame
inst->animFrame = (short)iVar1 + -1;
// door is not moving (fully open)
teeth->direction = 0;
// timer, 2 seconds
teeth->timeOpen = 0x780;
}
LAB_800b9fe8:
if (teeth->timeOpen == 0) {
LAB_800b9ff8:
if (-1 < teeth->direction) goto LAB_800ba084;
}
}
// Teeth instance position
SPS->Input1.pos[0] = inst->matrix.t[0];
SPS->Input1.pos[1] = inst->matrix.t[1];
SPS->Input1.pos[2] = inst->matrix.t[2];
SPS->Input1.hitRadius = 0x300;
SPS->Input1.hitRadiusSquared = 0x90000;
SPS->Input1.modelID = 0x70;
SPS->Union.ThBuckColl.thread = t;
SPS->Union.ThBuckColl.funcCallback = RB_Teeth_BSP_Callback;
// If door wants to close, but Player or Mine
// is in the way, then do not force the doors to close
THREAD_CollideHitboxWithBucket(sdata->gGT->threadBuckets[PLAYER],SPS,0);
THREAD_CollideHitboxWithBucket(sdata->gGT->threadBuckets[MINE],SPS,0);
LAB_800ba084:
// if no timer exists
// (opening, closing, or full closed)
if (teeth->timeOpen == 0)
{
// make visible
flags = inst->flags & 0xffffff7f;
}
// if a timer is active
// (fully open)
else
{
// make invisible
flags = inst->flags | 0x80;
}
inst->flags = flags;
return;
}

View File

@ -115,9 +115,9 @@ void DECOMP_RB_Blowup_Init(struct Instance* weaponInst)
THREAD_StartSearch_Self(&DAT_1f800108);
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[ROBOT],&DAT_1f800108,0);
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[ROBOT].thread,&DAT_1f800108,0);
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[MINE],&DAT_1f800108,0);
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[MINE].thread,&DAT_1f800108,0);
// If this is TNT
if (weaponInst->model->id != 0x27) {
@ -126,7 +126,7 @@ void DECOMP_RB_Blowup_Init(struct Instance* weaponInst)
DAT_1f800110 = 0x4000;
}
// check collision with player threads
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[PLAYER],&DAT_1f800108,0);
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[PLAYER].thread,&DAT_1f800108,0);
DAT_1f800130 = RB_Burst_CollLevInst;
return;

View File

@ -171,22 +171,22 @@ void DECOMP_RB_Burst_Init(struct Instance* inst)
// check collision with all Player thread
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[PLAYER],&DAT_1f800108,
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[PLAYER].thread,&DAT_1f800108,
// burst->driverParent(?)->instSelf->thread
*(unsigned short *)(*(int *)(*(int *)(burst + 4) + 0x1c) + 0x6c));
// check collision with all Robotcar thread
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[ROBOT],&DAT_1f800108,
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[ROBOT].thread,&DAT_1f800108,
// burst->driverParent(?)->instSelf->thread
*(unsigned short *)(*(int *)(*(int *)(burst + 4) + 0x1c) + 0x6c));
// check collision with all Mine thread
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[MINE],&DAT_1f800108,0);
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[MINE].thread,&DAT_1f800108,0);
// check collision with all Tracking thread
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[TRACKING],&DAT_1f800108,0);
THREAD_CollideHitboxWithBucket(gGT->threadBuckets[TRACKING].thread,&DAT_1f800108,0);
// RB_Burst_CollLevInst (callback for BSP collision)
DAT_1f800130 = RB_Burst_CollLevInst;

View File

@ -1,6 +1,6 @@
// 324+21+1+1+7+3+3+3+2+2+3+1+5+3+1+2+10+1+1+2+2 = 398 rewritten so far
// 325+21+1+1+7+3+3+3+2+2+3+1+5+3+1+2+10+1+1+2+4+2 = 403 rewritten so far
// 324 for every 'common' and ','
// 325 for every 'common' and ','
// additions for every file that has multiple functions,
// 21 for cheats
// most other additions for 231
@ -70,6 +70,8 @@ common, 231, RB_TNT_ThTick_ThrowOnHead, 0x0, General/231/231_020_RB_TNT_ThTick_T
common, 231, RB_Player_ToggleInvisible, 0x0, General/231/231_039_RB_Player_ToggleInvisible.c
common, 231, RB_Player_ToggleFlicker, 0x0, General/231/231_040_RB_Player_ToggleFlicker.c
common, 231, RB_Burst_CollLevInst, 0x0, General/231/231_050_RB_Burst_CollLevInst.c
common, 231, RB_Baron_ThTick, 0x0, General/231/231_054_055_RB_Baron.c
common, 231, RB_Blade_ThTick, 0x0, General/231/231_056_057_RB_Blade.c
common, 231, RB_Bubbles_RoosTubes, 0x0, General/231/231_058_RB_Bubbles_RoosTubes.c
@ -90,7 +92,7 @@ common, 231, RB_Seal_ThTick_TurnAround, 0x0, General/231/231_108_111_RB_Seal.c
common, 231, RB_Snowball_ThTick, 0x0, General/231/231_112_113_RB_Snowball.c
// skip Spider,
// skip StartText (unused)
// skip Teeth
common, 231, RB_Teeth_LInB, 0x0, General/231/231_120_124_RB_Teeth.c
common, 231, RB_Turtle_ThTick, 0x0, General/231/231_125_127_RB_Turtle.c
// 232 (incomplete)

View File

@ -2098,10 +2098,10 @@ undefined4 FUN_800ad9ac(int param_1,undefined4 param_2)
// ThreadMeta
iVar1 = FUN_8001d094(iVar3);
// if funcLevThreadsBirth is not nullptr
// if LThC is not nullptr
if ((iVar1 != 0) && (*(code **)(iVar1 + 8) != (code *)0x0))
{
// execute funcLevThreadsBirth, make thread for this instance
// execute LThC, make thread for this instance
// upon collision with the instance, let it run thread->funcThCollide
uVar2 = (**(code **)(iVar1 + 8))(iVar4,param_2,param_1);
@ -13074,8 +13074,7 @@ undefined4 FUN_800ba0c8(int param_1,int param_2,short *param_3)
// This is the door you can shoot in tiger temple
// If not in relic race, ignore the function,
// there are no weapons to activate door anyways
// Only continue if not in relic race
if ((*(uint *)PTR_DAT_8008d2ac & 0x4000000) == 0)
{
// get thread for this instance

View File

@ -100,7 +100,7 @@ struct Thread
void (*funcThCollide)(struct Thread* self);
// 0x2c
void* funcThTick;
void (*funcThTick)(struct Thread* self);
// This would be 9900C for players, or a pointer
// to a camera, etc

View File

@ -112,12 +112,12 @@ struct MetaDataMODEL
// Level Instance Birth
// callback after converting
// Lev InstDef to Lev Instance
void* LInB;
void (*LInB)(struct Instance* inst);
// Level Instance Collision
// callback after detecting
// Lev BSP hitbox collision
void* LInC;
void (*LInC)(struct Instance *i, struct Thread *t, struct ScratchpadStruct* sps);
};