Obj_Lightswitch (Sunswitch and Stonetower Temple flip switch) (#107)

* ObjLightswitch: fast

* ObjLightswitch: data migrated, except collider init is broke

* ObjLightswitch: nvm, collider documented

* ObjLightswitch: OK with 3 non-equiv, docs starting

* ObjLightswitch: more docs

* ObjLightswitch: some requested changes

* ObjLightswitch: requested changes

Co-authored-by: isghj8 <isghj8@gmail.com>
This commit is contained in:
Isghj
2021-05-09 19:18:57 -07:00
committed by GitHub
parent 874a75f456
commit d98e9dfb01
7 changed files with 531 additions and 48 deletions
@@ -8,8 +8,18 @@ void ObjLightswitch_Init(Actor* thisx, GlobalContext* globalCtx);
void ObjLightswitch_Destroy(Actor* thisx, GlobalContext* globalCtx);
void ObjLightswitch_Update(Actor* thisx, GlobalContext* globalCtx);
void ObjLightswitch_Draw(Actor* thisx, GlobalContext* globalCtx);
void ObjLightswitch_PlayCinema(ObjLightswitch* this, GlobalContext* globalCtx);
void ObjLightSwitch_SetupEnabled(ObjLightswitch* this);
void ObjLightSwitch_Enabled(ObjLightswitch* this, GlobalContext* globalCtx);
void ObjLightswitch_SetupIdle(ObjLightswitch* this);
void ObjLightSwitch_SetupFade(ObjLightswitch* this);
void ObjLightSwitch_Fade(ObjLightswitch* this, GlobalContext* globalCtx);
void ObjLightSwitch_SetupAsleep(ObjLightswitch* this);
void ObjLightSwitch_Asleep(ObjLightswitch* this, GlobalContext* globalCtx);
void ObjLightSwitch_SetupDisabled(ObjLightswitch* this);
void ObjLightSwitch_Disabled(ObjLightswitch* this, GlobalContext* globalCtx);
void ObjLightswitch_Idle(ObjLightswitch* this, GlobalContext* globalCtx);
/*
const ActorInit Obj_Lightswitch_InitVars = {
ACTOR_OBJ_LIGHTSWITCH,
ACTORCAT_SWITCH,
@@ -21,46 +31,471 @@ const ActorInit Obj_Lightswitch_InitVars = {
(ActorFunc)ObjLightswitch_Update,
(ActorFunc)ObjLightswitch_Draw
};
*/
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_8095FBF0.asm")
static ColliderJntSphElementInit sJntSphElementsInit[1] = {
{
{ ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x00202000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
{ 0, { { 0, 0, 0 }, 19 }, 100 },
},
};
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_8095FC94.asm")
static ColliderJntSphInit sJntSphInit = {
{ COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER | AC_TYPE_OTHER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_2, COLSHAPE_JNTSPH, },
1, sJntSphElementsInit,
};
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_8095FCEC.asm")
// different face addresses for (sleep -> waking -> awake) of light switch face
Gfx* lightswitchFaceGfx[] = {D_06000C20, D_06000420, D_06001420,};
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/ObjLightswitch_Init.asm")
Color_RGBA8 lightswitchEffectPrimColor = { 0xFF, 0xFF, 0xA0, 0xA0, };
Color_RGBA8 lightswitchEffectEnvColor = { 0xFF, 0x0, 0x0, 0x0, };
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/ObjLightswitch_Destroy.asm")
static InitChainEntry sInitChain[] = {
ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_CONTINUE),
ICHAIN_F32(uncullZoneForward, 4000, ICHAIN_CONTINUE),
ICHAIN_F32(uncullZoneScale, 200, ICHAIN_CONTINUE),
ICHAIN_F32(uncullZoneDownward, 200, ICHAIN_STOP),
};
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_8095FFF8.asm")
void ObjLightswitch_InitCollider(ObjLightswitch* this, GlobalContext* globalCtx) {
s32 pad;
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_80960014.asm")
Collider_InitJntSph(globalCtx, &this->collider);
Collider_SetJntSph(globalCtx, &this->collider, &this->actor, &sJntSphInit, &this->elements);
this->actor.colChkInfo.mass = 0xFF;
SysMatrix_SetStateRotationAndTranslation(this->actor.world.pos.x,
this->actor.world.pos.y + (this->actor.shape.yOffset * this->actor.scale.y),
this->actor.world.pos.z, &this->actor.shape);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, 1);
Collider_UpdateSpheres(0, &this->collider);
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_80960088.asm")
void ObjLightswitch_UpdateSwitchFlags(ObjLightswitch* this, GlobalContext* globalCtx, s32 set) {
if (this){}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_809600BC.asm")
if (set) {
Actor_SetSwitchFlag(globalCtx, GET_LIGHTSWITCH_SWITCHFLAG(this));
} else {
Actor_UnsetSwitchFlag(globalCtx, GET_LIGHTSWITCH_SWITCHFLAG(this));
}
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_8096012C.asm")
#if NON_EQUIVELENT
// issues: a lot of ordering issues leading up to the big effect spawn function call
// there are a lot of temps, some might have been removed that were required by accident
// however, constantly on the edge of stack oversize, so something has to go
void ObjLightswitch_SpawnEffects(ObjLightswitch* this, GlobalContext* globalCtx) {
Vec3f effectPos;
f32 sinResult;
f32 cosResult;
f32 tempResult;
f32 tempResult2; // must exist because of condition assignemt?
f32 tempResult_shorter; // tempResult - 30
f32 randomOutput;
f32 tempResult5;
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_80960148.asm")
sinResult = Math_SinS(this->actor.shape.rot.y);
cosResult = Math_CosS(this->actor.shape.rot.y);
if (this->colorAlpha >= 0x1900) {
// late rodata: 6.127451e-05f = 1 / 16320 ?
tempResult = (1.0f - ( this->colorAlpha * 6.127451e-05f)) * 400.0f;
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_80960224.asm")
if (tempResult > 60.0f) {
tempResult2 = 60.0f;
} else {
tempResult2 = tempResult;
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_80960260.asm")
tempResult = Rand_ZeroOne() * ((tempResult2 - 30.0f) + 30.0f);
tempResult_shorter = tempResult - 30.0f;
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_8096034C.asm")
if (tempResult > 30.0f) {
tempResult = 30.0f;
} else {
tempResult = 900.0f - SQ(tempResult_shorter);
if (tempResult < 100.0f) {
tempResult = 100.0f;
}
tempResult = sqrtf(tempResult);
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_80960370.asm")
tempResult5 = 2.0f * ((Rand_ZeroOne() - 0.5f) * tempResult);
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_80960424.asm")
// permuter seems to think something could be added to fix ordering here, but doesn't fix enough
//goto dummy_label_809848; dummy_label_809848: ; // minor regalloc fix
//if (cosResult){} // minor regalloc fix, but breaks some code
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_80960440.asm")
// saving fabsf result as a temp might help, but need to reduce temps
//fabsResult = fabsf(tempResult5);
//randomOutput = (Rand_ZeroOne() * 10.0f) + ((30.0f - fabsResult) * 0.5f);
//randomOutput = fabsf(tempResult5);
//randomOutput = (Rand_ZeroOne() * 10.0f) + ((30.0f - randomOutput) * 0.5f);
randomOutput = (Rand_ZeroOne() * 10.0f) + ((30.0f - fabsf(tempResult5)) * 0.5f);
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/ObjLightswitch_Update.asm")
effectPos.x = this->actor.world.pos.x + ((randomOutput * sinResult) + (tempResult5 * cosResult));
effectPos.y = this->actor.world.pos.y + tempResult_shorter + 10.0f;
effectPos.z = this->actor.world.pos.z + ((randomOutput * cosResult) - (tempResult5 * sinResult));
// weirdly, using a temp here make a big difference, but.. is that right? just one temp? prob ordering issue above
//tempResult = this->actor.world.pos.z + ((randomOutput * cosResult) - (tempResult5 * sinResult));
//effectPos.z = tempResult;
EffectSsDeadDb_Spawn(globalCtx, &effectPos, &D_801D15B0, &D_801D15B0,
&lightswitchEffectPrimColor, &lightswitchEffectEnvColor,
100, 0, 9);
}
}
#else
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/ObjLightswitch_SpawnEffects.asm")
#endif
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_809605F4.asm")
void ObjLightswitch_Init(Actor* thisx, GlobalContext* globalCtx) {
ObjLightswitch* this = THIS;
s32 pad;
u32 switchFlagResult;
s32 isTriggered;
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/func_80960880.asm")
switchFlagResult = Actor_GetSwitchFlag(globalCtx, GET_LIGHTSWITCH_SWITCHFLAG(this));
isTriggered = 0;
Actor_ProcessInitChain(&this->actor, &sInitChain);
Actor_SetHeight(&this->actor, 0.0f);
if (switchFlagResult != 0) {
if (GET_LIGHTSWITCH_TYPE(this) == LIGHTSWITCH_TYPE_FAKE) {
isTriggered = 1;
} else {
ObjLightSwitch_SetupEnabled(this);
}
} else {
ObjLightswitch_SetupIdle(this);
}
ObjLightswitch_InitCollider(this, globalCtx);
if (GET_LIGHTSWITCH_INVISIBLE(this)) {
// the stone tower exterior switch is part of the scene mesh, the actor is invisble on top
this->actor.draw = NULL;
}
if (isTriggered) {
Actor_MarkForDeath(&this->actor);
}
}
void ObjLightswitch_Destroy(Actor* thisx, GlobalContext* globalCtx) {
ObjLightswitch* this = THIS;
Collider_DestroyJntSph(globalCtx, &this->collider);
}
void ObjLightswitch_SetAction(ObjLightswitch* this, ObjLightswitchSetupFunc setupFunc, u32 setState) {
this->setupFunc = setupFunc;
this->switchFlagSetType = setState;
this->actionFunc = ObjLightswitch_PlayCinema;
}
void ObjLightswitch_PlayCinema(ObjLightswitch* this, GlobalContext* globalCtx) {
if (ActorCutscene_GetCanPlayNext(this->actor.cutscene)) {
ActorCutscene_StartAndSetUnkLinkFields(this->actor.cutscene, &this->actor);
ObjLightswitch_UpdateSwitchFlags(this, globalCtx, this->switchFlagSetType);
this->cutsceneTimer = 50;
this->setupFunc(this);
} else {
ActorCutscene_SetIntentToPlay(this->actor.cutscene);
}
}
void ObjLightswitch_SetupIdle(ObjLightswitch* this) {
this->faceState = LIGHTSWITCH_FACE_ASLEEP;
this->colorR = 0x26C0;
this->colorG = 0x1F40;
this->colorB = 0x3FC0;
this->colorAlpha = 0x3FC0;
this->actionFunc = ObjLightswitch_Idle;
}
void ObjLightswitch_Idle(ObjLightswitch* this, GlobalContext* globalCtx) {
s32 actorType = GET_LIGHTSWITCH_TYPE(this);
if (this->hitState >= 10) {
if (actorType == LIGHTSWITCH_TYPE_FAKE) {
ObjLightswitch_SetAction(this, ObjLightSwitch_SetupFade, 1);
} else {
if (actorType == LIGHTSWITCH_TYPE_FLIP) {
this->hitState = 0;
}
ObjLightswitch_SetAction(this, ObjLightSwitch_SetupAsleep, 1);
}
}
}
void ObjLightSwitch_SetupAsleep(ObjLightswitch* this) {
this->faceState = LIGHTSWITCH_FACE_ASLEEP;
this->colorShiftTimer = 0;
this->actionFunc = ObjLightSwitch_Asleep;
}
void ObjLightSwitch_Asleep(ObjLightswitch* this, GlobalContext* globalCtx) {
if (this->colorShiftTimer == 0) {
Audio_PlayActorSound2(&this->actor, 0x286F); // sfx NA_SE_EV_SUN_MARK_FLASH
}
this->colorShiftTimer++;
Math_StepToS(&this->edgeRotSpeed, -0xAA, 0xA);
this->edgeRot += this->edgeRotSpeed;
this->colorR = (this->colorShiftTimer * 0x140) + 0x26C0;
this->colorG = (this->colorShiftTimer * 0x1A0) + 0x1F40;
if (this->colorShiftTimer >= 20) {
ObjLightSwitch_SetupEnabled(this);
} else if (this->colorShiftTimer == 15) {
this->faceState = LIGHTSWITCH_FACE_WAKING;
Audio_PlayActorSound2(this, 0x2815); // sfx NA_SE_EV_FOOT_SWITCH
}
}
void ObjLightSwitch_SetupEnabled(ObjLightswitch* this) {
this->faceState = LIGHTSWITCH_FACE_FULLAWAKE;
this->colorR = 0x3FC0;
this->colorG = 0x3FC0;
this->colorB = 0x3FC0;
this->colorAlpha = 0x3FC0;
this->edgeRotSpeed = -0xAA;
this->colorShiftTimer = 0;
this->actionFunc = ObjLightSwitch_Enabled;
}
void ObjLightSwitch_Enabled(ObjLightswitch* this, GlobalContext* globalCtx) {
s32 actorType = GET_LIGHTSWITCH_TYPE(this);
if (actorType == LIGHTSWITCH_TYPE_REGULAR) {
// switch can be disabled outside of this actor by flag
if (Actor_GetSwitchFlag(globalCtx, GET_LIGHTSWITCH_SWITCHFLAG(this)) == 0) {
ObjLightSwitch_SetupDisabled(this);
}
} else if (actorType == LIGHTSWITCH_TYPE_FLIP) {
if (this->hitState >= 10) {
this->hitState = 0;
ObjLightswitch_SetAction(this, ObjLightSwitch_SetupDisabled, 0);
}
} else if (this->hitState == 0) {
if (this->colorShiftTimer >= 13) {
ObjLightswitch_UpdateSwitchFlags(this, globalCtx, 0);
ObjLightSwitch_SetupDisabled(this);
} else {
this->colorShiftTimer += 1;
}
} else {
this->colorShiftTimer = 0;
}
this->edgeRot += this->edgeRotSpeed;
}
void ObjLightSwitch_SetupDisabled(ObjLightswitch* this) {
this->colorShiftTimer = 20;
this->faceState = LIGHTSWITCH_FACE_WAKING;
this->actionFunc = ObjLightSwitch_Disabled;
}
void ObjLightSwitch_Disabled(ObjLightswitch* this, GlobalContext* globalCtx) {
this->colorShiftTimer--;
Math_StepToS(&this->edgeRotSpeed, 0, 0xA);
this->edgeRot += this->edgeRotSpeed;
this->colorR = (this->colorShiftTimer * 0x140) + 0x26C0;
this->colorG = (this->colorShiftTimer * 0x1A0) + 0x1F40;
if (this->colorShiftTimer <= 0) {
ObjLightswitch_SetupIdle(this);
} else if (this->colorShiftTimer == 15) {
this->faceState = LIGHTSWITCH_FACE_ASLEEP;
Audio_PlayActorSound2(&this->actor, 0x2815); // NA_SE_EV_FOOT_SWITCH
}
}
void ObjLightSwitch_SetupFade(ObjLightswitch* this) {
this->colorAlpha = 0x3FC0;
this->actionFunc = ObjLightSwitch_Fade;
}
void ObjLightSwitch_Fade(ObjLightswitch* this, GlobalContext* globalCtx) {
this->colorAlpha -= 0xC8;
ObjLightswitch_SpawnEffects(this, globalCtx); // spawn burning fire effect
if (this->colorAlpha < 0) {
Actor_MarkForDeath(&this->actor);
} else {
func_800B9010(&this->actor, 0x321F); // sfx NA_SE_EN_COMMON_EXTINCT_LEV "burn into ashes"
}
}
void ObjLightswitch_Update(Actor* thisx, GlobalContext* globalCtx) {
ObjLightswitch* this = THIS;
s32 pad;
if ((this->collider.base.acFlags & AC_HIT) != 0) {
// dmgFlags enum doesn't exist yet, 0x2000 is light arrows
if ((this->collider.elements->info.acHitInfo->toucher.dmgFlags & 0x2000) != 0) {
this->hitState = 10;
} else if (GET_LIGHTSWITCH_TYPE(this) == LIGHTSWITCH_TYPE_FLIP) {
if (this->hitState == 0) {
if ((this->previousACFlags & AC_HIT) == 0) {
this->hitState = 1;
}
} else if (this->hitState < 10) {
this->hitState++;
}
} else {
if (this->hitState < 10) {
this->hitState++;
}
}
} else {
this->hitState = 0;
}
// why wouldn't this be in the action func?
if ((this->cutsceneTimer > 0) && ( (s32) this->actionFunc != (s32) ObjLightswitch_PlayCinema )) {
this->cutsceneTimer--;
if (this->cutsceneTimer == 0) {
ActorCutscene_Stop(this->actor.cutscene);
}
}
this->actionFunc(this, globalCtx);
if (this->actor.update != 0) {
this->previousACFlags = this->collider.base.acFlags;
CollisionCheck_SetOC(globalCtx, &globalCtx->colCheckCtx, &this->collider);
CollisionCheck_SetAC(globalCtx, &globalCtx->colCheckCtx, &this->collider);
}
}
#if NON_EQUIVELENT
// gDPSetEnvColor parameter load order is different than the order in which the value is built
// also massive regalloc probably caused by the above
void ObjLightSwitch_DrawOpa(ObjLightswitch* this, GlobalContext* globalCtx) {
Vec3f tempPos;
Vec3s tempRot;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_8012C28C(globalCtx->state.gfxCtx);
//temp_v0->words.w1 = ((((s32) this->colorB >> 6) & 0xFF) << 8)
//| (((s32) this->colorR >> 6) << 0x18)
//| ((((s32) this->colorG >> 6) & 0xFF) << 0x10)
//| (((s32) this->colorAlpha >> 6) & 0xFF);
// load order issues with loading this in the right order for the function
gDPSetEnvColor(POLY_OPA_DISP++,
this->colorR >> 6,
this->colorG >> 6,
this->colorB >> 6,
this->colorAlpha >> 6);
gSPSegment(POLY_OPA_DISP++, 0x09, D_801AEFA0);
tempPos.x = this->actor.world.pos.x;
tempPos.y = this->actor.world.pos.y + (this->actor.shape.yOffset * this->actor.scale.y);
tempPos.z = this->actor.world.pos.z;
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(D_80960BC4[this->faceState]));
gSPDisplayList(POLY_OPA_DISP++, 0x6000260);
tempRot.x = this->actor.shape.rot.x;
tempRot.y = this->actor.shape.rot.y;
tempRot.z = this->actor.shape.rot.z + this->edgeRot;
SysMatrix_SetStateRotationAndTranslation(tempPos.z, tempPos.y, tempPos.x, &tempRot);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, 1);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, 0x6000398);
tempRot.z = this->actor.shape.rot.z - this->edgeRot;
SysMatrix_SetStateRotationAndTranslation(tempPos.z, tempPos.y, tempPos.x, &tempRot);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, 1);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, 0x6000408);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
#else
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/ObjLightSwitch_DrawOpa.asm")
#endif
#if NON_EQUIVELENT
// same issue as above
void ObjLightSwitch_DrawXlu(ObjLightswitch* this, GlobalContext* globalCtx) {
Vec3f tempPos;
Vec3s tempRot;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_8012C2DC(globalCtx->state.gfxCtx);
//temp_v0->words.w1 = ((((s32) this->colorB >> 6) & 0xFF) << 8)
//| (((s32) this->colorR >> 6) << 0x18)
//| ((((s32) this->colorG >> 6) & 0xFF) << 0x10)
//| (((s32) this->colorAlpha >> 6) & 0xFF);
gDPSetEnvColor(POLY_XLU_DISP++,
this->colorR >> 6,
this->colorG >> 6,
this->colorB >> 6,
this->colorAlpha >> 6);
gSPSegment(POLY_XLU_DISP++, 0x09, D_801AEF88);
tempPos.x = this->actor.world.pos.x;
tempPos.y = this->actor.world.pos.y + (this->actor.shape.yOffset * this->actor.scale.y);
tempPos.z = this->actor.world.pos.z;
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(D_80960BC4[this->faceState]));
gSPDisplayList(POLY_XLU_DISP++, 0x6000260);
tempRot.x = this->actor.shape.rot.x;
tempRot.y = this->actor.shape.rot.y;
tempRot.z = this->actor.shape.rot.z + this->edgeRot;
SysMatrix_SetStateRotationAndTranslation(tempPos.x, tempPos.y, tempPos.z, &tempRot);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, 1);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, 0x6000398);
tempRot.z = this->actor.shape.rot.z - this->edgeRot;
SysMatrix_SetStateRotationAndTranslation(tempPos.x, tempPos.y, tempPos.z, &tempRot);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, 1);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, 0x6000408);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
#else
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/ObjLightSwitch_DrawXlu.asm")
#endif
void ObjLightswitch_Draw(Actor* thisx, GlobalContext* globalCtx) {
ObjLightswitch* this = THIS;
s32 alpha = (this->colorAlpha >> 6) & 0xFF;
if ((GET_LIGHTSWITCH_TYPE(this) == LIGHTSWITCH_TYPE_FAKE) && (alpha > 0) && (alpha < 0xFF)) {
ObjLightSwitch_DrawXlu(this, globalCtx);
} else {
ObjLightSwitch_DrawOpa(this, globalCtx);
}
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_Obj_Lightswitch_0x8095FBF0/ObjLightswitch_Draw.asm")
@@ -3,13 +3,55 @@
#include <global.h>
typedef void (*ObjLightswitchActionFunc)(struct ObjLightswitch*, GlobalContext*);
typedef void (*ObjLightswitchSetupFunc)(struct ObjLightswitch*);
struct ObjLightswitch;
typedef struct ObjLightswitch {
/* 0x000 */ Actor actor;
/* 0x144 */ char unk_144[0x7C];
/* 0x144 */ ColliderJntSph collider;
/* 0x164 */ ColliderJntSphElement elements;
/* 0x1A4 */ ObjLightswitchActionFunc actionFunc;
/* 0x1A8 */ s16 colorR; // not RGBA8 as 4x s16 (not 4x s8)
/* 0x1AA */ s16 colorG;
/* 0x1AC */ s16 colorB;
/* 0x1AE */ s16 colorAlpha;
/* 0x1B0 */ s16 edgeRot;
/* 0x1B2 */ s16 edgeRotSpeed;
/* 0x1B4 */ s8 colorShiftTimer;
/* 0x1B5 */ s8 hitState;
/* 0x1B6 */ s8 faceState;
/* 0x1B7 */ u8 previousACFlags;
/* 0x1B8 */ ObjLightswitchSetupFunc setupFunc;
/* 0x1BC */ s8 switchFlagSetType; // 1 or 0 , for set or unset flags
/* 0x1BD */ s8 cutsceneTimer;
} ObjLightswitch; // size = 0x1C0
extern const ActorInit Obj_Lightswitch_InitVars;
extern Gfx D_06000C20[];
extern Gfx D_06000420[];
extern Gfx D_06001420[];
// opa func
extern s32 D_801AEFA0;
// xlu func
extern s32 D_801AEF88;
#define LIGHTSWITCH_FACE_ASLEEP 0
#define LIGHTSWITCH_FACE_WAKING 1
#define LIGHTSWITCH_FACE_FULLAWAKE 2
#define LIGHTSWITCH_TYPE_REGULAR 0
#define LIGHTSWITCH_TYPE_FLIP 1
#define LIGHTSWITCH_TYPE_UNK2 2
#define LIGHTSWITCH_TYPE_FAKE 3
#define GET_LIGHTSWITCH_TYPE(this) (((this)->actor.params >> 4) & 0x3)
#define GET_LIGHTSWITCH_INVISIBLE(this) (((this)->actor.params >> 3) & 1)
#define GET_LIGHTSWITCH_SWITCHFLAG(this) (((this)->actor.params >> 8) & 0x7F)
#endif // Z_OBJ_LIGHTSWITCH_H