Document object_obj_tokeidai and improve documentation on ovl_Obj_Tokeidai (#569)

* Document object_obj_tokeidai XML

* Change "outer ring" to "minute ring" to better describe what it is

* Rename "sun and moon disk" to "sun and moon panel"

* Preserve ordering

* Standardize on "staircase to rooftop"

* Standardize on calling it "Exterior Gear" to contrast with all the interior stuff

* Lots more documentation

* Make it more obvious that the macros refer to clock time, not regular time

* More documentation and spacing

* Better document counterweight draw

* Respond to Anghelo's and engineer's reviews

* Split tokeidai into separate files

* Revert "Split tokeidai into separate files"

This reverts commit eed1fe5ff6.
This commit is contained in:
Tom Overton 2022-01-30 12:41:21 -08:00 committed by GitHub
parent 5ebc7c0e35
commit 4543b5ade6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 270 additions and 202 deletions

View File

@ -1,59 +1,81 @@
<Root> <Root>
<!-- Contains objects related to the Clock Tower and various wall clocks. -->
<File Name="object_obj_tokeidai" Segment="6"> <File Name="object_obj_tokeidai" Segment="6">
<Texture Name="object_obj_tokeidai_TLUT_000000" OutName="tlut_000000" Format="rgba16" Width="4" Height="4" Offset="0x0" /> <Texture Name="gClockTowerClockFaceTopTLUT" OutName="clock_tower_clock_face_top_tlut" Format="rgba16" Width="4" Height="4" Offset="0x0" />
<Texture Name="object_obj_tokeidai_TLUT_000020" OutName="tlut_000020" Format="rgba16" Width="4" Height="4" Offset="0x20" /> <Texture Name="gClockTowerClockFaceBottomTLUT" OutName="clock_tower_clock_face_bottom_tlut" Format="rgba16" Width="4" Height="4" Offset="0x20" />
<Texture Name="object_obj_tokeidai_Tex_000040" OutName="tex_000040" Format="i8" Width="64" Height="64" Offset="0x40" /> <Texture Name="gClockTowerSpotlightShineTex" OutName="clock_tower_spotlight_shine" Format="i8" Width="64" Height="64" Offset="0x40" />
<Texture Name="object_obj_tokeidai_Tex_001040" OutName="tex_001040" Format="rgba16" Width="32" Height="32" Offset="0x1040" />
<Texture Name="object_obj_tokeidai_Tex_001840" OutName="tex_001840" Format="rgba16" Width="32" Height="32" Offset="0x1840" /> <!-- Generic brick texture used for multiple pieces of the Clock Tower (counterweight, unused tower wall, staircase to rooftop) -->
<Texture Name="object_obj_tokeidai_Tex_002040" OutName="tex_002040" Format="rgba16" Width="32" Height="32" Offset="0x2040" /> <Texture Name="gClockTowerBrickTex" OutName="clock_tower_bricks" Format="rgba16" Width="32" Height="32" Offset="0x1040" />
<Texture Name="object_obj_tokeidai_Tex_002840" OutName="tex_002840" Format="rgba16" Width="32" Height="32" Offset="0x2840" /> <Texture Name="gClockTowerCounterweightBeamSide1Tex" OutName="clock_tower_counterweight_beam_side1" Format="rgba16" Width="32" Height="32" Offset="0x1840" />
<Texture Name="object_obj_tokeidai_Tex_003040" OutName="tex_003040" Format="rgba16" Width="16" Height="32" Offset="0x3040" /> <Texture Name="gClockTowerCounterweightBeamSide2Tex" OutName="clock_tower_counterweight_beam_side2" Format="rgba16" Width="32" Height="32" Offset="0x2040" />
<Texture Name="object_obj_tokeidai_Tex_003440" OutName="tex_003440" Format="rgba16" Width="8" Height="32" Offset="0x3440" /> <Texture Name="gClockTowerExteriorGearFaceTex" OutName="clock_tower_exterior_gear_face" Format="rgba16" Width="32" Height="32" Offset="0x2840" />
<Texture Name="object_obj_tokeidai_Tex_003640" OutName="tex_003640" Format="rgba16" Width="16" Height="16" Offset="0x3640" /> <Texture Name="gClockTowerExteriorGearSidesAndMinuteRingBackTex" OutName="clock_tower_exterior_gear_sides_and_minute_ring_back" Format="rgba16" Width="16" Height="32" Offset="0x3040" />
<Texture Name="object_obj_tokeidai_Tex_003840" OutName="tex_003840" Format="rgba16" Width="16" Height="16" Offset="0x3840" /> <Texture Name="gClockTowerClockCenterTex" OutName="clock_tower_clock_center" Format="rgba16" Width="8" Height="32" Offset="0x3440" />
<Texture Name="object_obj_tokeidai_Tex_003A40" OutName="tex_003A40" Format="rgba16" Width="16" Height="16" Offset="0x3A40" /> <Texture Name="gClockTowerClockCenterSidesTex" OutName="clock_tower_clock_center_sides" Format="rgba16" Width="16" Height="16" Offset="0x3640" />
<Texture Name="object_obj_tokeidai_Tex_003C40" OutName="tex_003C40" Format="rgba16" Width="16" Height="32" Offset="0x3C40" /> <Texture Name="gClockTowerHandTex" OutName="clock_tower_hand" Format="rgba16" Width="16" Height="16" Offset="0x3840" />
<Texture Name="object_obj_tokeidai_Tex_004040" OutName="tex_004040" Format="rgba16" Width="16" Height="16" Offset="0x4040" /> <Texture Name="gClockTowerSunAndMoonPanelSidesTex" OutName="clock_tower_sun_and_moon_panel_sides" Format="rgba16" Width="16" Height="16" Offset="0x3A40" />
<Texture Name="object_obj_tokeidai_Tex_004240" OutName="tex_004240" Format="rgba16" Width="32" Height="16" Offset="0x4240" /> <Texture Name="gClockTowerSunAndMoonPanelMoonTex" OutName="clock_tower_sun_and_moon_panel_moon" Format="rgba16" Width="16" Height="32" Offset="0x3C40" />
<Texture Name="object_obj_tokeidai_Tex_004640" OutName="tex_004640" Format="rgba16" Width="32" Height="16" Offset="0x4640" /> <Texture Name="gClockTowerSunAndMoonPanelSunTex" OutName="clock_tower_sun_and_moon_panel_sun" Format="rgba16" Width="16" Height="16" Offset="0x4040" />
<Texture Name="object_obj_tokeidai_Tex_004A40" OutName="tex_004A40" Format="rgba16" Width="32" Height="16" Offset="0x4A40" /> <Texture Name="gClockTowerMinuteRingFace1Tex" OutName="clock_tower_minute_ring_face_1" Format="rgba16" Width="32" Height="16" Offset="0x4240" />
<Texture Name="object_obj_tokeidai_Tex_004E40" OutName="tex_004E40" Format="rgba16" Width="32" Height="16" Offset="0x4E40" /> <Texture Name="gClockTowerMinuteRingFace2Tex" OutName="clock_tower_minute_ring_face_2" Format="rgba16" Width="32" Height="16" Offset="0x4640" />
<Texture Name="object_obj_tokeidai_Tex_005240" OutName="tex_005240" Format="ci4" Width="64" Height="64" Offset="0x5240" /> <Texture Name="gClockTowerMinuteRingFace3Tex" OutName="clock_tower_minute_ring_face_3" Format="rgba16" Width="32" Height="16" Offset="0x4A40" />
<Texture Name="object_obj_tokeidai_Tex_005A40" OutName="tex_005A40" Format="ci4" Width="64" Height="64" Offset="0x5A40" /> <Texture Name="gClockTowerMinuteRingSidesTex" OutName="clock_tower_minute_ring_sides" Format="rgba16" Width="32" Height="16" Offset="0x4E40" />
<Texture Name="object_obj_tokeidai_Tex_006240" OutName="tex_006240" Format="rgba16" Width="8" Height="8" Offset="0x6240" /> <Texture Name="gClockTowerClockFaceTopTex" OutName="clock_tower_clock_face_top" Format="ci4" Width="64" Height="64" Offset="0x5240" />
<!-- <Blob Name="object_obj_tokeidai_Blob_0062C0" Size="0x1000" Offset="0x62C0" /> --> <Texture Name="gClockTowerClockFaceBottomTex" OutName="clock_tower_clock_face_bottom" Format="ci4" Width="64" Height="64" Offset="0x5A40" />
<Texture Name="object_obj_tokeidai_Tex_0072C0" OutName="tex_0072C0" Format="ia8" Width="32" Height="64" Offset="0x72C0" /> <Texture Name="gClockTowerClockFacePanelBarTex" OutName="clock_tower_clock_face_panel_bar" Format="rgba16" Width="8" Height="8" Offset="0x6240" />
<Texture Name="object_obj_tokeidai_Tex_007AC0" OutName="tex_007AC0" Format="i8" Width="32" Height="32" Offset="0x7AC0" /> <Texture Name="gClockTowerUnusedBrickTex" OutName="clock_tower_unused_bricks" Format="rgba16" Width="32" Height="32" Offset="0x62C0" />
<Texture Name="object_obj_tokeidai_Tex_007EC0" OutName="tex_007EC0" Format="i4" Width="64" Height="64" Offset="0x7EC0" /> <Texture Name="gClockTowerUnusedMaskTex" OutName="clock_tower_unused_mask" Format="i4" Width="64" Height="64" Offset="0x6AC0" />
<Texture Name="object_obj_tokeidai_Tex_0086C0" OutName="tex_0086C0" Format="i4" Width="64" Height="64" Offset="0x86C0" /> <Texture Name="gClockTowerSpotlightBeamTex" OutName="clock_tower_spotlight_beam" Format="ia8" Width="32" Height="64" Offset="0x72C0" />
<Texture Name="object_obj_tokeidai_Tex_008EC0" OutName="tex_008EC0" Format="i4" Width="64" Height="64" Offset="0x8EC0" /> <Texture Name="gClockTowerSpotlightMaskTex" OutName="clock_tower_spotlight_mask" Format="i8" Width="32" Height="32" Offset="0x7AC0" />
<DList Name="object_obj_tokeidai_DL_009A00" Offset="0x9A00" /> <Texture Name="gClockTowerCounterweightMaskTex" OutName="clock_tower_counterweight_mask" Format="i4" Width="64" Height="64" Offset="0x7EC0" />
<DList Name="object_obj_tokeidai_DL_009A08" Offset="0x9A08" /> <Texture Name="gClockTowerUnusedTowerWallMaskTex" OutName="clock_tower_unused_tower_wall_mask" Format="i4" Width="64" Height="64" Offset="0x86C0" />
<Texture Name="object_obj_tokeidai_Tex_009B48" OutName="tex_009B48" Format="rgba16" Width="32" Height="32" Offset="0x9B48" /> <Texture Name="gClockTowerStaircaseToRooftopMaskTex" OutName="clock_tower_staircase_to_rooftop_mask" Format="i4" Width="64" Height="64" Offset="0x8EC0" />
<Texture Name="object_obj_tokeidai_Tex_00A348" OutName="tex_00A348" Format="i4" Width="64" Height="64" Offset="0xA348" />
<DList Name="object_obj_tokeidai_DL_00B0C0" Offset="0xB0C0" /> <!-- Probably intended to be used as the xluDList for Clock Tower Termina Field Walls -->
<DList Name="object_obj_tokeidai_DL_00B208" Offset="0xB208" /> <DList Name="gClockTowerUnusedEmpty1DL" Offset="0x9A00" />
<TextureAnimation Name="object_obj_tokeidai_Matanimheader_00B4E4" Offset="0xB4E4" /> <DList Name="gClockTowerTerminaFieldWallsDL" Offset="0x9A08" />
<DList Name="object_obj_tokeidai_DL_00BA70" Offset="0xBA70" /> <Texture Name="gClockTowerTerminaFieldWallsBrickTex" OutName="clock_tower_termina_field_walls_brick" Format="rgba16" Width="32" Height="32" Offset="0x9B48" />
<DList Name="object_obj_tokeidai_DL_00BA78" Offset="0xBA78" /> <Texture Name="gClockTowerTerminaFieldWallsMask" OutName="clock_tower_termina_field_walls_mask" Format="i4" Width="64" Height="64" Offset="0xA348" />
<DList Name="object_obj_tokeidai_DL_00BEE0" Offset="0xBEE0" /> <DList Name="gClockTowerSpotlightDL" Offset="0xB0C0" />
<DList Name="object_obj_tokeidai_DL_00BEE8" Offset="0xBEE8" /> <DList Name="gClockTowerCounterweightDL" Offset="0xB208" />
<DList Name="object_obj_tokeidai_DL_00C360" Offset="0xC360" /> <TextureAnimation Name="gClockTowerUnusedTexAnim" Offset="0xB4E4" />
<DList Name="object_obj_tokeidai_DL_00C368" Offset="0xC368" />
<DList Name="object_obj_tokeidai_DL_00CF20" Offset="0xCF20" /> <!-- Probably intended to be used as the xluDList for Clock Tower Exterior Gear -->
<DList Name="object_obj_tokeidai_DL_00CF28" Offset="0xCF28" /> <DList Name="gClockTowerUnusedEmpty2DL" Offset="0xBA70" />
<DList Name="object_obj_tokeidai_DL_00D380" Offset="0xD380" /> <DList Name="gClockTowerExteriorGearDL" Offset="0xBA78" />
<DList Name="object_obj_tokeidai_DL_00D388" Offset="0xD388" />
<DList Name="object_obj_tokeidai_DL_00D8E0" Offset="0xD8E0" /> <!-- Probably intended to be used as the xluDList for Clock Tower Center and Hand -->
<DList Name="object_obj_tokeidai_DL_00D8E8" Offset="0xD8E8" /> <DList Name="gClockTowerUnusedEmpty3DL" Offset="0xBEE0" />
<Texture Name="object_obj_tokeidai_Tex_00DAC0" OutName="tex_00DAC0" Format="rgba16" Width="16" Height="32" Offset="0xDAC0" /> <DList Name="gClockTowerClockCenterAndHandDL" Offset="0xBEE8" />
<DList Name="object_obj_tokeidai_DL_00E810" Offset="0xE810" />
<DList Name="object_obj_tokeidai_DL_00E818" Offset="0xE818" /> <!-- Probably intended to be used as the xluDList for Clock Tower Sun and Moon Panel -->
<DList Name="object_obj_tokeidai_DL_00F510" Offset="0xF510" /> <DList Name="gClockTowerUnusedEmpty4DL" Offset="0xC360" />
<DList Name="object_obj_tokeidai_DL_00F518" Offset="0xF518" /> <DList Name="gClockTowerSunAndMoonPanelDL" Offset="0xC368" />
<Texture Name="object_obj_tokeidai_Tex_00F7F8" OutName="tex_00F7F8" Format="rgba16" Width="16" Height="32" Offset="0xF7F8" />
<Texture Name="object_obj_tokeidai_Tex_00FBF8" OutName="tex_00FBF8" Format="rgba16" Width="64" Height="32" Offset="0xFBF8" /> <!-- Probably intended to be used as the xluDList for Clock Tower Minute Ring -->
<Texture Name="object_obj_tokeidai_Tex_010BF8" OutName="tex_010BF8" Format="rgba16" Width="64" Height="32" Offset="0x10BF8" /> <DList Name="gClockTowerUnusedEmpty5DL" Offset="0xCF20" />
<Texture Name="object_obj_tokeidai_Tex_011BF8" OutName="tex_011BF8" Format="rgba16" Width="8" Height="8" Offset="0x11BF8" /> <DList Name="gClockTowerMinuteRingDL" Offset="0xCF28" />
<!-- Probably intended to be used as the xluDList for Clock Tower Unused Tower Wall -->
<DList Name="gClockTowerUnusedEmpty6DL" Offset="0xD380" />
<DList Name="gClockTowerUnusedTowerWallDL" Offset="0xD388" />
<!-- Used as the xluDList for Staircase to Rooftop -->
<DList Name="gClockTowerEmptyDL" Offset="0xD8E0" />
<DList Name="gClockTowerStaircaseToRooftopDL" Offset="0xD8E8" />
<Texture Name="gClockTowerClockFaceBackTex" OutName="clock_tower_clock_face_back" Format="rgba16" Width="16" Height="32" Offset="0xDAC0" />
<!-- Probably intended to be used as the xluDList for Clock Tower Clock Face -->
<DList Name="gClockTowerUnusedEmpty7DL" Offset="0xE810" />
<DList Name="gClockTowerClockFace" Offset="0xE818" />
<!-- Probably intended to be used as the xluDList for Wall Clock Clock Face -->
<DList Name="gClockTowerUnusedEmpty8DL" Offset="0xF510" />
<DList Name="gWallClockClockFace" Offset="0xF518" />
<Texture Name="gWallClockClockFaceBackTex" OutName="wall_clock_clock_face_back" Format="rgba16" Width="16" Height="32" Offset="0xF7F8" />
<Texture Name="gWallClockClockFaceBottomTex" OutName="wall_clock_clock_face_bottom" Format="rgba16" Width="64" Height="32" Offset="0xFBF8" />
<Texture Name="gWallClockClockFaceTopTex" OutName="wall_clock_clock_face_top" Format="rgba16" Width="64" Height="32" Offset="0x10BF8" />
<Texture Name="gWallClockClockFacePanelBarTex" OutName="wall_clock_clock_face_panel_bar" Format="rgba16" Width="8" Height="8" Offset="0x11BF8" />
</File> </File>
</Root> </Root>

View File

@ -1,17 +1,32 @@
/* /*
* File: z_obj_tokeidai.c * File: z_obj_tokeidai.c
* Overlay: ovl_Obj_Tokeidai * Overlay: ovl_Obj_Tokeidai
* Description: Components of the Clock Tower (gears, clock face, counterweight, etc). Also used for wall clocks. * Description: Components of the Clock Tower. Also used for wall clocks. The specific components are:
* - ClockFace: The decorated face of the clock that spins every hour.
* - MinuteRing: The ring around the clock face that spins every two minutes.
* - ExteriorGear: The two gears on the side of the tower that spin every two minutes.
* - SunAndMoonPanel: A panel with a sun and moon image that tells whether it is day or night.
* - Counterweight: The spinning weight on top of the tower that emits a spotlight at night.
* - StaircaseToRooftop: The staircase to tower's rooftop that opens after midnight on the Final Day.
* - TerminaFieldWalls: The walls of the Clock Tower visible from Termina Field.
* - UnusedWall: A single wall of the Clock Tower, unused in the final game.
* *
* This actor handles most of the functionality related to the Clock Tower and the various * Sometimes, the ClockFace, MinuteRing, and SunAndMoonPanel are treated as a single clock entity.
* wall clocks around Clock Town. Among its responsibilities are making the clocks correctly * This is called Clock if it applies to both the Clock Tower clock and wall clocks, and
* tell the time by spinning the various pieces and gears and controlling the spotlight that * TowerClock/WallClock, respectively, if it only applies to one of them.
* is emitted from the Clock Tower at night.
* *
* On the midnight of the Final Day, the Clock Tower opens up, and the various pieces of it * On the midnight of the Final Day, the Clock Tower opens up, and the various pieces of it
* are moved around. This actor is responsible for managing all of this movement. Additionally, * are moved around. This actor is responsible for managing all of this movement, which is handled
* if the moon crashes into Termina, this actor is responsible for making the pieces of the * via the series of action functions labeled with TowerOpening.
* Clock Tower collapse. *
* All components have at least one of these three actions:
* - Idle: The "default" action, and for some components the only action.
* The component is either completely still, or it's telling the time, depending on the component.
* - OpenedIdle: The action for certain Clock Tower components after midnight on the Final Day.
* The TowerClock, ExteriorGears, and Counterweight no longer tell time and are moved to a different position.
* Called "opened" because it corresponds to when the staircase to the tower's rooftop is opened up.
* - Collapse: The action for certain Clock Tower components when the moon crashes into Termina.
* This action is responsible for making the component fall during the moon crash cutscene.
*/ */
#include "z_obj_tokeidai.h" #include "z_obj_tokeidai.h"
@ -21,10 +36,11 @@
#define THIS ((ObjTokeidai*)thisx) #define THIS ((ObjTokeidai*)thisx)
#define GET_CURRENT_HOUR(this) ((s32)((this)->currentTime * (24.0f / 0x10000))) #define GET_CURRENT_CLOCK_HOUR(this) ((s32)((this)->clockTime * (24.0f / 0x10000)))
#define GET_CURRENT_MINUTE(this) ((s32)((this)->currentTime * (360 * 2.0f / 0x10000)) % 30) #define GET_CURRENT_CLOCK_MINUTE(this) ((s32)((this)->clockTime * (360 * 2.0f / 0x10000)) % 30)
#define GET_CLOCK_FACE_ROTATION(currentHour) ((s16)(currentHour * (0x10000 / 24.0f))) #define GET_CLOCK_FACE_ROTATION(currentClockHour) ((s16)(currentClockHour * (0x10000 / 24.0f)))
#define GET_OUTER_RING_OR_GEAR_ROTATION(currentMinute) ((s16)(currentMinute * (0x10000 * 12.0f / 360))) #define GET_MINUTE_RING_OR_EXTERIOR_GEAR_ROTATION(currentClockMinute) \
((s16)(currentClockMinute * (0x10000 * 12.0f / 360)))
void ObjTokeidai_Init(Actor* thisx, GlobalContext* globalCtx); void ObjTokeidai_Init(Actor* thisx, GlobalContext* globalCtx);
void ObjTokeidai_Destroy(Actor* thisx, GlobalContext* globalCtx); void ObjTokeidai_Destroy(Actor* thisx, GlobalContext* globalCtx);
@ -33,18 +49,18 @@ void ObjTokeidai_Draw(Actor* thisx, GlobalContext* globalCtx);
void ObjTokeidai_DoNothing(ObjTokeidai* this, GlobalContext* globalCtx); void ObjTokeidai_DoNothing(ObjTokeidai* this, GlobalContext* globalCtx);
void ObjTokeidai_TowerClock_OpenedIdle(ObjTokeidai* this, GlobalContext* globalCtx); void ObjTokeidai_TowerClock_OpenedIdle(ObjTokeidai* this, GlobalContext* globalCtx);
void ObjTokeidai_TowerGear_OpenedIdle(ObjTokeidai* this, GlobalContext* globalCtx); void ObjTokeidai_ExteriorGear_OpenedIdle(ObjTokeidai* this, GlobalContext* globalCtx);
void ObjTokeidai_Counterweight_OpenedIdle(ObjTokeidai* this, GlobalContext* globalCtx); void ObjTokeidai_Counterweight_OpenedIdle(ObjTokeidai* this, GlobalContext* globalCtx);
void ObjTokeidai_TowerClock_Idle(ObjTokeidai* this, GlobalContext* globalCtx); void ObjTokeidai_TowerClock_Idle(ObjTokeidai* this, GlobalContext* globalCtx);
void ObjTokeidai_WallClock_Idle(ObjTokeidai* this, GlobalContext* globalCtx); void ObjTokeidai_WallClock_Idle(ObjTokeidai* this, GlobalContext* globalCtx);
void ObjTokeidai_TowerGear_Idle(ObjTokeidai* this, GlobalContext* globalCtx); void ObjTokeidai_ExteriorGear_Idle(ObjTokeidai* this, GlobalContext* globalCtx);
void ObjTokeidai_Counterweight_Idle(ObjTokeidai* this, GlobalContext* globalCtx); void ObjTokeidai_Counterweight_Idle(ObjTokeidai* this, GlobalContext* globalCtx);
void ObjTokeidai_Walls_Idle(ObjTokeidai* this, GlobalContext* globalCtx); void ObjTokeidai_TerminaFieldWalls_Idle(ObjTokeidai* this, GlobalContext* globalCtx);
void ObjTokeidai_StaircaseIntoTower_Idle(ObjTokeidai* this, GlobalContext* globalCtx); void ObjTokeidai_StaircaseToRooftop_Idle(ObjTokeidai* this, GlobalContext* globalCtx);
void ObjTokeidai_SetupTowerOpening(ObjTokeidai* this); void ObjTokeidai_SetupTowerOpening(ObjTokeidai* this);
void ObjTokeidai_Clock_Draw(Actor* thisx, GlobalContext* globalCtx); void ObjTokeidai_Clock_Draw(Actor* thisx, GlobalContext* globalCtx);
void ObjTokeidai_Counterweight_Draw(Actor* thisx, GlobalContext* globalCtx); void ObjTokeidai_Counterweight_Draw(Actor* thisx, GlobalContext* globalCtx);
void ObjTokeidai_TowerGear_Draw(Actor* thisx, GlobalContext* globalCtx); void ObjTokeidai_ExteriorGear_Draw(Actor* thisx, GlobalContext* globalCtx);
const ActorInit Obj_Tokeidai_InitVars = { const ActorInit Obj_Tokeidai_InitVars = {
ACTOR_OBJ_TOKEIDAI, ACTOR_OBJ_TOKEIDAI,
@ -67,43 +83,43 @@ static InitChainEntry sInitChain[] = {
/** /**
* Returns the angle necessary to show the correct side of * Returns the angle necessary to show the correct side of
* the sun and moon disk based on the time of day. The actual * the sun and moon panel based on the time of day. The actual
* angle can differ from the target angle if the disk is in * angle can differ from the target angle if the panel is in
* the middle of rotating. * the middle of rotating.
*/ */
s32 ObjTokeidai_GetTargetSunMoonDiskRotation() { s32 ObjTokeidai_GetTargetSunMoonPanelRotation() {
if (gSaveContext.isNight) { if (gSaveContext.isNight) {
return 0x8000; return 0x8000;
} }
return 0; return 0;
} }
void ObjTokeidai_SetupClockOrGear(ObjTokeidai* this) { void ObjTokeidai_SetupClockOrExteriorGear(ObjTokeidai* this) {
s32 currentMinute = GET_CURRENT_MINUTE(this); s32 currentClockMinute = GET_CURRENT_CLOCK_MINUTE(this);
this->clockMinute = currentMinute; this->clockMinute = currentClockMinute;
this->outerRingOrGearRotation = GET_OUTER_RING_OR_GEAR_ROTATION(currentMinute); this->minuteRingOrExteriorGearRotation = GET_MINUTE_RING_OR_EXTERIOR_GEAR_ROTATION(currentClockMinute);
this->outerRingOrGearRotationalVelocity = 0x3C; this->minuteRingOrExteriorGearRotationalVelocity = 0x3C;
this->outerRingOrGearRotationTimer = 0; this->minuteRingOrExteriorGearRotationTimer = 0;
} }
void ObjTokeidai_Clock_Init(ObjTokeidai* this) { void ObjTokeidai_Clock_Init(ObjTokeidai* this) {
s32 currentHour; s32 currentClockHour;
ObjTokeidai_SetupClockOrGear(this); ObjTokeidai_SetupClockOrExteriorGear(this);
currentHour = GET_CURRENT_HOUR(this); currentClockHour = GET_CURRENT_CLOCK_HOUR(this);
this->clockHour = currentHour; this->clockHour = currentClockHour;
this->clockFaceRotation = GET_CLOCK_FACE_ROTATION(currentHour); this->clockFaceRotation = GET_CLOCK_FACE_ROTATION(currentClockHour);
this->clockFaceRotationalVelocity = 0; this->clockFaceRotationalVelocity = 0;
this->clockFaceRotationTimer = 0; this->clockFaceRotationTimer = 0;
this->sunMoonDiskRotationalVelocity = 0; this->sunMoonPanelRotationalVelocity = 0;
this->sunMoonDiskRotation = ObjTokeidai_GetTargetSunMoonDiskRotation(); this->sunMoonPanelRotation = ObjTokeidai_GetTargetSunMoonPanelRotation();
} }
void ObjTokeidai_TowerGear_Init(ObjTokeidai* this, GlobalContext* globalCtx) { void ObjTokeidai_ExteriorGear_Init(ObjTokeidai* this, GlobalContext* globalCtx) {
this->actor.draw = ObjTokeidai_TowerGear_Draw; this->actor.draw = ObjTokeidai_ExteriorGear_Draw;
this->opaDList = object_obj_tokeidai_DL_00BA78; this->opaDList = gClockTowerExteriorGearDL;
ObjTokeidai_SetupClockOrGear(this); ObjTokeidai_SetupClockOrExteriorGear(this);
if (((globalCtx->sceneNum == SCENE_CLOCKTOWER) && (gSaveContext.sceneSetupIndex == 2) && if (((globalCtx->sceneNum == SCENE_CLOCKTOWER) && (gSaveContext.sceneSetupIndex == 2) &&
(globalCtx->csCtx.unk_12 == 0)) || (globalCtx->csCtx.unk_12 == 0)) ||
@ -111,12 +127,12 @@ void ObjTokeidai_TowerGear_Init(ObjTokeidai* this, GlobalContext* globalCtx) {
(globalCtx->csCtx.unk_12 == 0))) { (globalCtx->csCtx.unk_12 == 0))) {
ObjTokeidai_SetupTowerOpening(this); ObjTokeidai_SetupTowerOpening(this);
} else if ((CURRENT_DAY == 3 && gSaveContext.time < CLOCK_TIME(6, 0)) || CURRENT_DAY >= 4) { } else if ((CURRENT_DAY == 3 && gSaveContext.time < CLOCK_TIME(6, 0)) || CURRENT_DAY >= 4) {
this->actionFunc = ObjTokeidai_TowerGear_OpenedIdle; this->actionFunc = ObjTokeidai_ExteriorGear_OpenedIdle;
this->actor.world.pos.y += this->actor.scale.y * 1900.0f; this->actor.world.pos.y += this->actor.scale.y * 1900.0f;
this->actor.shape.yOffset = 1500.0f; this->actor.shape.yOffset = 1500.0f;
gSaveContext.weekEventReg[8] |= 0x40; gSaveContext.weekEventReg[8] |= 0x40;
} else { } else {
this->actionFunc = ObjTokeidai_TowerGear_Idle; this->actionFunc = ObjTokeidai_ExteriorGear_Idle;
} }
} }
@ -133,11 +149,14 @@ void ObjTokeidai_TowerClock_Init(ObjTokeidai* this, GlobalContext* globalCtx) {
this->actor.world.pos.y += (this->actor.scale.y * 5191.0f) - 50.0f; this->actor.world.pos.y += (this->actor.scale.y * 5191.0f) - 50.0f;
this->actor.world.pos.x += Math_SinS(this->actor.world.rot.y) * this->actor.scale.z * 1791.0f; this->actor.world.pos.x += Math_SinS(this->actor.world.rot.y) * this->actor.scale.z * 1791.0f;
this->actor.world.pos.z += -Math_CosS(this->actor.world.rot.y) * this->actor.scale.z * 1791.0f; this->actor.world.pos.z += -Math_CosS(this->actor.world.rot.y) * this->actor.scale.z * 1791.0f;
this->clockFaceZTranslation = -0x140; this->clockFaceZTranslation = -0x140;
this->actor.shape.rot.x = -0x4000; this->actor.shape.rot.x = -0x4000;
this->actor.home.pos = this->actor.world.pos; this->actor.home.pos = this->actor.world.pos;
this->actor.home.pos.y -= 1178.0f; this->actor.home.pos.y -= 1178.0f;
this->actor.home.pos.z += 13.0f; this->actor.home.pos.z += 13.0f;
this->actionFunc = ObjTokeidai_TowerClock_OpenedIdle; this->actionFunc = ObjTokeidai_TowerClock_OpenedIdle;
} else { } else {
this->actionFunc = ObjTokeidai_TowerClock_Idle; this->actionFunc = ObjTokeidai_TowerClock_Idle;
@ -148,8 +167,8 @@ void ObjTokeidai_Counterweight_Init(ObjTokeidai* this, GlobalContext* globalCtx)
s32 type; s32 type;
this->actor.draw = ObjTokeidai_Counterweight_Draw; this->actor.draw = ObjTokeidai_Counterweight_Draw;
this->opaDList = object_obj_tokeidai_DL_00B208; this->opaDList = gClockTowerCounterweightDL;
this->xluDList = object_obj_tokeidai_DL_00B0C0; this->xluDList = gClockTowerSpotlightDL;
if (gSaveContext.isNight) { if (gSaveContext.isNight) {
this->spotlightIntensity = 100; this->spotlightIntensity = 100;
} else { } else {
@ -162,6 +181,7 @@ void ObjTokeidai_Counterweight_Init(ObjTokeidai* this, GlobalContext* globalCtx)
(globalCtx->csCtx.unk_12 == 0))) { (globalCtx->csCtx.unk_12 == 0))) {
this->spotlightIntensity = 0; this->spotlightIntensity = 0;
ObjTokeidai_SetupTowerOpening(this); ObjTokeidai_SetupTowerOpening(this);
if (this->actor.child == NULL) { if (this->actor.child == NULL) {
type = OBJ_TOKEIDAI_TYPE(&this->actor); type = OBJ_TOKEIDAI_TYPE(&this->actor);
if (type == OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_CLOCK_TOWN || if (type == OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_CLOCK_TOWN ||
@ -171,6 +191,7 @@ void ObjTokeidai_Counterweight_Init(ObjTokeidai* this, GlobalContext* globalCtx)
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0);
} }
} }
if (this->actor.child != NULL) { if (this->actor.child != NULL) {
if (OBJ_TOKEIDAI_TYPE(&this->actor) == OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_TERMINA_FIELD) { if (OBJ_TOKEIDAI_TYPE(&this->actor) == OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_TERMINA_FIELD) {
this->actor.child->home.rot.x = 0x384; this->actor.child->home.rot.x = 0x384;
@ -200,55 +221,65 @@ void ObjTokeidai_Init(Actor* thisx, GlobalContext* globalCtx) {
this->xRotation = 0; this->xRotation = 0;
this->yTranslation = 0; this->yTranslation = 0;
this->clockFaceZTranslation = 0; this->clockFaceZTranslation = 0;
this->currentTime = gSaveContext.time; this->clockTime = gSaveContext.time;
this->actor.home.rot.x = 0; this->actor.home.rot.x = 0;
switch (OBJ_TOKEIDAI_TYPE(&this->actor)) { switch (OBJ_TOKEIDAI_TYPE(&this->actor)) {
case OBJ_TOKEIDAI_TYPE_TOWER_GEAR_TERMINA_FIELD: case OBJ_TOKEIDAI_TYPE_EXTERIOR_GEAR_TERMINA_FIELD:
Actor_SetScale(&this->actor, 0.15f); Actor_SetScale(&this->actor, 0.15f);
ObjTokeidai_TowerGear_Init(this, globalCtx); ObjTokeidai_ExteriorGear_Init(this, globalCtx);
break; break;
case OBJ_TOKEIDAI_TYPE_TOWER_GEAR_CLOCK_TOWN:
ObjTokeidai_TowerGear_Init(this, globalCtx); case OBJ_TOKEIDAI_TYPE_EXTERIOR_GEAR_CLOCK_TOWN:
ObjTokeidai_ExteriorGear_Init(this, globalCtx);
break; break;
case OBJ_TOKEIDAI_TYPE_UNUSED_WALL: case OBJ_TOKEIDAI_TYPE_UNUSED_WALL:
this->opaDList = object_obj_tokeidai_DL_00D388; this->opaDList = gClockTowerUnusedTowerWallDL;
break; break;
case OBJ_TOKEIDAI_TYPE_TOWER_WALLS_TERMINA_FIELD: case OBJ_TOKEIDAI_TYPE_TOWER_WALLS_TERMINA_FIELD:
Actor_SetScale(&this->actor, 1.0f); Actor_SetScale(&this->actor, 1.0f);
this->opaDList = object_obj_tokeidai_DL_009A08; this->opaDList = gClockTowerTerminaFieldWallsDL;
this->actionFunc = ObjTokeidai_Walls_Idle; this->actionFunc = ObjTokeidai_TerminaFieldWalls_Idle;
break; break;
case OBJ_TOKEIDAI_TYPE_TOWER_CLOCK_TERMINA_FIELD: case OBJ_TOKEIDAI_TYPE_TOWER_CLOCK_TERMINA_FIELD:
Actor_SetScale(&this->actor, 0.15f); Actor_SetScale(&this->actor, 0.15f);
ObjTokeidai_TowerClock_Init(this, globalCtx); ObjTokeidai_TowerClock_Init(this, globalCtx);
break; break;
case OBJ_TOKEIDAI_TYPE_TOWER_CLOCK_CLOCK_TOWN: case OBJ_TOKEIDAI_TYPE_TOWER_CLOCK_CLOCK_TOWN:
ObjTokeidai_TowerClock_Init(this, globalCtx); ObjTokeidai_TowerClock_Init(this, globalCtx);
break; break;
case OBJ_TOKEIDAI_TYPE_WALL_CLOCK: case OBJ_TOKEIDAI_TYPE_WALL_CLOCK:
Actor_SetScale(&this->actor, 0.02f); Actor_SetScale(&this->actor, 0.02f);
this->actor.draw = ObjTokeidai_Clock_Draw; this->actor.draw = ObjTokeidai_Clock_Draw;
ObjTokeidai_Clock_Init(this); ObjTokeidai_Clock_Init(this);
this->actionFunc = ObjTokeidai_WallClock_Idle; this->actionFunc = ObjTokeidai_WallClock_Idle;
break; break;
case OBJ_TOKEIDAI_TYPE_SMALL_WALL_CLOCK: case OBJ_TOKEIDAI_TYPE_SMALL_WALL_CLOCK:
Actor_SetScale(&this->actor, 0.01f); Actor_SetScale(&this->actor, 0.01f);
this->actor.draw = ObjTokeidai_Clock_Draw; this->actor.draw = ObjTokeidai_Clock_Draw;
ObjTokeidai_Clock_Init(this); ObjTokeidai_Clock_Init(this);
this->actionFunc = ObjTokeidai_WallClock_Idle; this->actionFunc = ObjTokeidai_WallClock_Idle;
break; break;
case OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_TERMINA_FIELD: case OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_TERMINA_FIELD:
Actor_SetScale(&this->actor, 0.15f); Actor_SetScale(&this->actor, 0.15f);
ObjTokeidai_Counterweight_Init(this, globalCtx); ObjTokeidai_Counterweight_Init(this, globalCtx);
break; break;
case OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_CLOCK_TOWN: case OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_CLOCK_TOWN:
ObjTokeidai_Counterweight_Init(this, globalCtx); ObjTokeidai_Counterweight_Init(this, globalCtx);
break; break;
case OBJ_TOKEIDAI_TYPE_STAIRCASE_INTO_TOWER:
this->opaDList = object_obj_tokeidai_DL_00D8E8; case OBJ_TOKEIDAI_TYPE_STAIRCASE_TO_ROOFTOP:
this->xluDList = object_obj_tokeidai_DL_00D8E0; this->opaDList = gClockTowerStaircaseToRooftopDL;
this->actionFunc = ObjTokeidai_StaircaseIntoTower_Idle; this->xluDList = gClockTowerEmptyDL;
this->actionFunc = ObjTokeidai_StaircaseToRooftop_Idle;
break; break;
} }
} }
@ -257,41 +288,43 @@ void ObjTokeidai_Destroy(Actor* thisx, GlobalContext* globalCtx) {
} }
void ObjTokeidai_RotateOnMinuteChange(ObjTokeidai* this, s32 playSfx) { void ObjTokeidai_RotateOnMinuteChange(ObjTokeidai* this, s32 playSfx) {
s32 currentMinute = GET_CURRENT_MINUTE(this); s32 currentClockMinute = GET_CURRENT_CLOCK_MINUTE(this);
if (currentMinute != this->clockMinute) { if (currentClockMinute != this->clockMinute) {
if (this->outerRingOrGearRotationTimer == 8 && playSfx) { if (this->minuteRingOrExteriorGearRotationTimer == 8 && playSfx) {
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CLOCK_TOWER_SECOND_HAND); Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CLOCK_TOWER_SECOND_HAND);
} }
if (this->outerRingOrGearRotationTimer > 8) { if (this->minuteRingOrExteriorGearRotationTimer > 8) {
// This actually performs the rotation to the next minute // This actually performs the rotation to the next minute
// for the outer ring or gear. // for the minute ring or exterior gear.
this->outerRingOrGearRotationalVelocity += 0x3C; this->minuteRingOrExteriorGearRotationalVelocity += 0x3C;
this->outerRingOrGearRotation += this->outerRingOrGearRotationalVelocity; this->minuteRingOrExteriorGearRotation += this->minuteRingOrExteriorGearRotationalVelocity;
} else { } else {
// This makes the outer ring or gear wiggle in place for a bit // This makes the minute ring or exterior gear wiggle in place for a bit
// before rotating to the next position. // before rotating to the next position.
if ((this->outerRingOrGearRotationTimer & 3) == 0) { if ((this->minuteRingOrExteriorGearRotationTimer & 3) == 0) {
this->outerRingOrGearRotation += 0x5A; this->minuteRingOrExteriorGearRotation += 0x5A;
} }
if ((this->outerRingOrGearRotationTimer & 3) == 1) { if ((this->minuteRingOrExteriorGearRotationTimer & 3) == 1) {
this->outerRingOrGearRotation -= 0x5A; this->minuteRingOrExteriorGearRotation -= 0x5A;
} }
} }
this->outerRingOrGearRotationTimer++; this->minuteRingOrExteriorGearRotationTimer++;
if ((currentMinute == 15 && this->outerRingOrGearRotation < 0) ||
(currentMinute != 15 && this->outerRingOrGearRotation > GET_OUTER_RING_OR_GEAR_ROTATION(currentMinute))) { if ((currentClockMinute == 15 && this->minuteRingOrExteriorGearRotation < 0) ||
this->outerRingOrGearRotation = GET_OUTER_RING_OR_GEAR_ROTATION(currentMinute); (currentClockMinute != 15 &&
this->clockMinute = currentMinute; this->minuteRingOrExteriorGearRotation > GET_MINUTE_RING_OR_EXTERIOR_GEAR_ROTATION(currentClockMinute))) {
this->outerRingOrGearRotationalVelocity = 0x5A; this->minuteRingOrExteriorGearRotation = GET_MINUTE_RING_OR_EXTERIOR_GEAR_ROTATION(currentClockMinute);
this->outerRingOrGearRotationTimer = 0; this->clockMinute = currentClockMinute;
this->minuteRingOrExteriorGearRotationalVelocity = 0x5A;
this->minuteRingOrExteriorGearRotationTimer = 0;
} }
} }
} }
void ObjTokeidai_TowerGear_Collapse(ObjTokeidai* this, GlobalContext* globalCtx) { void ObjTokeidai_ExteriorGear_Collapse(ObjTokeidai* this, GlobalContext* globalCtx) {
if ((this->actor.bgCheckFlags & 1) || this->actor.world.pos.y < 0.0f) { if ((this->actor.bgCheckFlags & 1) || this->actor.world.pos.y < 0.0f) {
this->actionFunc = ObjTokeidai_DoNothing; this->actionFunc = ObjTokeidai_DoNothing;
} else { } else {
@ -302,9 +335,9 @@ void ObjTokeidai_TowerGear_Collapse(ObjTokeidai* this, GlobalContext* globalCtx)
} }
} }
void ObjTokeidai_TowerGear_OpenedIdle(ObjTokeidai* this, GlobalContext* globalCtx) { void ObjTokeidai_ExteriorGear_OpenedIdle(ObjTokeidai* this, GlobalContext* globalCtx) {
if (func_800EE29C(globalCtx, 0x84) && globalCtx->csCtx.npcActions[func_800EE200(globalCtx, 0x84)]->unk0 == 2) { if (func_800EE29C(globalCtx, 0x84) && globalCtx->csCtx.npcActions[func_800EE200(globalCtx, 0x84)]->unk0 == 2) {
this->actionFunc = ObjTokeidai_TowerGear_Collapse; this->actionFunc = ObjTokeidai_ExteriorGear_Collapse;
this->actor.speedXZ = this->actor.scale.y * 5.0f; this->actor.speedXZ = this->actor.scale.y * 5.0f;
this->actor.velocity.y = 0.0f; this->actor.velocity.y = 0.0f;
this->actor.terminalVelocity = this->actor.scale.y * -50.0f; this->actor.terminalVelocity = this->actor.scale.y * -50.0f;
@ -313,15 +346,15 @@ void ObjTokeidai_TowerGear_OpenedIdle(ObjTokeidai* this, GlobalContext* globalCt
} }
/** /**
* This is hard to see in the final game. This, used in conjunction * This, used in conjunction with the following function, makes the
* with the following function, makes the tower's clock slide off the * tower's clock slide off the tower and spin through the air when the moon crashes.
* tower and spin through the air when the moon crashes.
*/ */
void ObjTokeidai_TowerClock_Fall(ObjTokeidai* this, GlobalContext* globalCtx) { void ObjTokeidai_TowerClock_Fall(ObjTokeidai* this, GlobalContext* globalCtx) {
this->actor.shape.rot.x += this->fallingClockFaceRotationalVelocity; this->actor.shape.rot.x += this->fallingClockFaceRotationalVelocity;
if (this->fallingClockFaceRotationalVelocity > 0xA0) { if (this->fallingClockFaceRotationalVelocity > 0xA0) {
this->fallingClockFaceRotationalVelocity -= 5; this->fallingClockFaceRotationalVelocity -= 5;
} }
this->actor.world.pos.z += 4.0f; this->actor.world.pos.z += 4.0f;
Actor_MoveWithGravity(&this->actor); Actor_MoveWithGravity(&this->actor);
if (this->actor.world.pos.y < 0.0f) { if (this->actor.world.pos.y < 0.0f) {
@ -330,8 +363,8 @@ void ObjTokeidai_TowerClock_Fall(ObjTokeidai* this, GlobalContext* globalCtx) {
} }
/** /**
* This is hard to see in the final game. This makes the * This makes the tower's clock slide off as the moon crashes into it. It's
* tower's clock slide off as the moon crashes into it. * the tower clock's equivalent to other components' Collapse functions.
*/ */
void ObjTokeidai_TowerClock_SlideOff(ObjTokeidai* this, GlobalContext* globalCtx) { void ObjTokeidai_TowerClock_SlideOff(ObjTokeidai* this, GlobalContext* globalCtx) {
f32 cos; f32 cos;
@ -396,20 +429,15 @@ void ObjTokeidai_Counterweight_OpenedIdle(ObjTokeidai* this, GlobalContext* glob
} }
} }
/** void ObjTokeidai_TerminaFieldWalls_Collapse(ObjTokeidai* this, GlobalContext* globalCtx) {
* This is hard to see in the final game. It makes the walls of
* the clock tower tip over as the moon crashes into it, but the
* giant moon mostly obscures it.
*/
void ObjTokeidai_Walls_Collapse(ObjTokeidai* this, GlobalContext* globalCtx) {
if (this->actor.shape.rot.x < 0x4000) { if (this->actor.shape.rot.x < 0x4000) {
this->actor.shape.rot.x += 0x28; this->actor.shape.rot.x += 0x28;
} }
} }
void ObjTokeidai_Walls_Idle(ObjTokeidai* this, GlobalContext* globalCtx) { void ObjTokeidai_TerminaFieldWalls_Idle(ObjTokeidai* this, GlobalContext* globalCtx) {
if (func_800EE29C(globalCtx, 0x84) != 0 && globalCtx->csCtx.npcActions[func_800EE200(globalCtx, 0x84)]->unk0 == 1) { if (func_800EE29C(globalCtx, 0x84) != 0 && globalCtx->csCtx.npcActions[func_800EE200(globalCtx, 0x84)]->unk0 == 1) {
this->actionFunc = ObjTokeidai_Walls_Collapse; this->actionFunc = ObjTokeidai_TerminaFieldWalls_Collapse;
} }
} }
@ -480,9 +508,11 @@ void ObjTokeidai_TowerOpening_DropCounterweight(ObjTokeidai* this, GlobalContext
case 0: case 0:
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CLOCK_TOWER_BOUND_0); Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CLOCK_TOWER_BOUND_0);
break; break;
case 1: case 1:
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CLOCK_TOWER_BOUND_1); Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CLOCK_TOWER_BOUND_1);
break; break;
case 2: case 2:
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CLOCK_TOWER_BOUND_2); Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CLOCK_TOWER_BOUND_2);
break; break;
@ -565,7 +595,7 @@ void ObjTokeidai_TowerOpening_Start(ObjTokeidai* this, GlobalContext* globalCtx)
} }
/** /**
* Sets up the sequence where the Clock Tower "transforms" and opens up * Sets up the sequence where the Clock Tower opens up
* on the midnight of the Final Day. * on the midnight of the Final Day.
*/ */
void ObjTokeidai_SetupTowerOpening(ObjTokeidai* this) { void ObjTokeidai_SetupTowerOpening(ObjTokeidai* this) {
@ -580,7 +610,7 @@ void ObjTokeidai_SetupTowerOpening(ObjTokeidai* this) {
void ObjTokeidai_DoNothing(ObjTokeidai* this, GlobalContext* globalCtx) { void ObjTokeidai_DoNothing(ObjTokeidai* this, GlobalContext* globalCtx) {
} }
void ObjTokeidai_StaircaseIntoTower_Idle(ObjTokeidai* this, GlobalContext* globalCtx) { void ObjTokeidai_StaircaseToRooftop_Idle(ObjTokeidai* this, GlobalContext* globalCtx) {
if (((CURRENT_DAY == 3 && gSaveContext.time < CLOCK_TIME(6, 0)) || CURRENT_DAY >= 4) || if (((CURRENT_DAY == 3 && gSaveContext.time < CLOCK_TIME(6, 0)) || CURRENT_DAY >= 4) ||
(gSaveContext.weekEventReg[8] & 0x40)) { (gSaveContext.weekEventReg[8] & 0x40)) {
this->actor.draw = ObjTokeidai_Draw; this->actor.draw = ObjTokeidai_Draw;
@ -601,9 +631,9 @@ s32 ObjTokeidai_IsPostFirstCycleFinalHours(ObjTokeidai* this, GlobalContext* glo
} }
void ObjTokeidai_RotateOnHourChange(ObjTokeidai* this, GlobalContext* globalCtx) { void ObjTokeidai_RotateOnHourChange(ObjTokeidai* this, GlobalContext* globalCtx) {
s32 currentHour = GET_CURRENT_HOUR(this); s32 currentClockHour = GET_CURRENT_CLOCK_HOUR(this);
if (currentHour != this->clockHour) { if (currentClockHour != this->clockHour) {
if (this->clockFaceRotationTimer > 12) { if (this->clockFaceRotationTimer > 12) {
// This actually performs the rotation to the next hour // This actually performs the rotation to the next hour
// for the clock face. // for the clock face.
@ -621,32 +651,33 @@ void ObjTokeidai_RotateOnHourChange(ObjTokeidai* this, GlobalContext* globalCtx)
} }
this->clockFaceRotationTimer++; this->clockFaceRotationTimer++;
if ((currentHour == 12 && this->clockFaceRotation < 0) ||
(currentHour != 12 && this->clockFaceRotation > GET_CLOCK_FACE_ROTATION(currentHour))) { if ((currentClockHour == 12 && this->clockFaceRotation < 0) ||
this->clockFaceRotation = GET_CLOCK_FACE_ROTATION(currentHour); (currentClockHour != 12 && this->clockFaceRotation > GET_CLOCK_FACE_ROTATION(currentClockHour))) {
this->clockHour = currentHour; this->clockFaceRotation = GET_CLOCK_FACE_ROTATION(currentClockHour);
this->clockHour = currentClockHour;
this->clockFaceRotationalVelocity = 0; this->clockFaceRotationalVelocity = 0;
this->clockFaceRotationTimer = 0; this->clockFaceRotationTimer = 0;
} }
} }
// If the sun and moon disk doesn't have the target rotation (e.g., the time of day // If the sun and moon panel doesn't have the target rotation (e.g., the time of day
// just changed), rotate it until it matches the target. // just changed), rotate it until it matches the target.
if (this->sunMoonDiskRotation != ObjTokeidai_GetTargetSunMoonDiskRotation()) { if (this->sunMoonPanelRotation != ObjTokeidai_GetTargetSunMoonPanelRotation()) {
if (this->clockHour == 6) { if (this->clockHour == 6) {
this->sunMoonDiskRotationalVelocity += 0x222; this->sunMoonPanelRotationalVelocity += 0x222;
this->sunMoonDiskRotation += this->sunMoonDiskRotationalVelocity; this->sunMoonPanelRotation += this->sunMoonPanelRotationalVelocity;
if (this->sunMoonDiskRotation > 0x10000) { if (this->sunMoonPanelRotation > 0x10000) {
this->sunMoonDiskRotation = ObjTokeidai_GetTargetSunMoonDiskRotation(); this->sunMoonPanelRotation = ObjTokeidai_GetTargetSunMoonPanelRotation();
this->sunMoonDiskRotationalVelocity = 0; this->sunMoonPanelRotationalVelocity = 0;
} }
} }
if (this->clockHour == 18) { if (this->clockHour == 18) {
this->sunMoonDiskRotationalVelocity += 0x222; this->sunMoonPanelRotationalVelocity += 0x222;
this->sunMoonDiskRotation += this->sunMoonDiskRotationalVelocity; this->sunMoonPanelRotation += this->sunMoonPanelRotationalVelocity;
if (this->sunMoonDiskRotation > 0x8000) { if (this->sunMoonPanelRotation > 0x8000) {
this->sunMoonDiskRotation = ObjTokeidai_GetTargetSunMoonDiskRotation(); this->sunMoonPanelRotation = ObjTokeidai_GetTargetSunMoonPanelRotation();
this->sunMoonDiskRotationalVelocity = 0; this->sunMoonPanelRotationalVelocity = 0;
} }
} }
} }
@ -662,7 +693,7 @@ void ObjTokeidai_TowerClock_Idle(ObjTokeidai* this, GlobalContext* globalCtx) {
if (globalCtx->csCtx.state != 0) { if (globalCtx->csCtx.state != 0) {
this->actor.home.rot.x = 1; this->actor.home.rot.x = 1;
this->currentTime += 3; this->clockTime += 3;
this->actor.draw = ObjTokeidai_Clock_Draw; this->actor.draw = ObjTokeidai_Clock_Draw;
} else { } else {
if (!(globalCtx->actorCtx.unk5 & 2) && if (!(globalCtx->actorCtx.unk5 & 2) &&
@ -670,7 +701,7 @@ void ObjTokeidai_TowerClock_Idle(ObjTokeidai* this, GlobalContext* globalCtx) {
ActorCutscene_GetCurrentIndex() == -1) { ActorCutscene_GetCurrentIndex() == -1) {
this->actor.draw = NULL; this->actor.draw = NULL;
} }
this->currentTime = gSaveContext.time; this->clockTime = gSaveContext.time;
if (this->actor.home.rot.x != 0) { if (this->actor.home.rot.x != 0) {
ObjTokeidai_Clock_Init(this); ObjTokeidai_Clock_Init(this);
this->actor.home.rot.x = 0; this->actor.home.rot.x = 0;
@ -684,28 +715,28 @@ void ObjTokeidai_TowerClock_Idle(ObjTokeidai* this, GlobalContext* globalCtx) {
} }
void ObjTokeidai_WallClock_Idle(ObjTokeidai* this, GlobalContext* globalCtx) { void ObjTokeidai_WallClock_Idle(ObjTokeidai* this, GlobalContext* globalCtx) {
this->currentTime = gSaveContext.time; this->clockTime = gSaveContext.time;
ObjTokeidai_RotateOnMinuteChange(this, true); ObjTokeidai_RotateOnMinuteChange(this, true);
ObjTokeidai_RotateOnHourChange(this, globalCtx); ObjTokeidai_RotateOnHourChange(this, globalCtx);
} }
void ObjTokeidai_TowerGear_Idle(ObjTokeidai* this, GlobalContext* globalCtx) { void ObjTokeidai_ExteriorGear_Idle(ObjTokeidai* this, GlobalContext* globalCtx) {
if (ObjTokeidai_IsPostFirstCycleFinalHours(this, globalCtx)) { if (ObjTokeidai_IsPostFirstCycleFinalHours(this, globalCtx)) {
this->actor.draw = ObjTokeidai_TowerGear_Draw; this->actor.draw = ObjTokeidai_ExteriorGear_Draw;
} else { } else {
if (globalCtx->csCtx.state != 0) { if (globalCtx->csCtx.state != 0) {
this->actor.home.rot.x = 1; this->actor.home.rot.x = 1;
this->currentTime += 3; this->clockTime += 3;
this->actor.draw = ObjTokeidai_TowerGear_Draw; this->actor.draw = ObjTokeidai_ExteriorGear_Draw;
} else { } else {
if ((globalCtx->actorCtx.unk5 & 2) == 0 && if ((globalCtx->actorCtx.unk5 & 2) == 0 &&
OBJ_TOKEIDAI_TYPE(&this->actor) == OBJ_TOKEIDAI_TYPE_TOWER_GEAR_TERMINA_FIELD && OBJ_TOKEIDAI_TYPE(&this->actor) == OBJ_TOKEIDAI_TYPE_EXTERIOR_GEAR_TERMINA_FIELD &&
ActorCutscene_GetCurrentIndex() == -1) { ActorCutscene_GetCurrentIndex() == -1) {
this->actor.draw = NULL; this->actor.draw = NULL;
} }
this->currentTime = gSaveContext.time; this->clockTime = gSaveContext.time;
if (this->actor.home.rot.x != 0) { if (this->actor.home.rot.x != 0) {
ObjTokeidai_SetupClockOrGear(this); ObjTokeidai_SetupClockOrExteriorGear(this);
this->actor.home.rot.x = 0; this->actor.home.rot.x = 0;
} }
} }
@ -718,6 +749,7 @@ void ObjTokeidai_Counterweight_Idle(ObjTokeidai* this, GlobalContext* globalCtx)
if (ObjTokeidai_IsPostFirstCycleFinalHours(this, globalCtx)) { if (ObjTokeidai_IsPostFirstCycleFinalHours(this, globalCtx)) {
this->spotlightIntensity = 0; this->spotlightIntensity = 0;
if (this->actor.child == NULL) { if (this->actor.child == NULL) {
type = OBJ_TOKEIDAI_TYPE(&this->actor); type = OBJ_TOKEIDAI_TYPE(&this->actor);
if (type == OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_CLOCK_TOWN || if (type == OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_CLOCK_TOWN ||
@ -727,6 +759,7 @@ void ObjTokeidai_Counterweight_Idle(ObjTokeidai* this, GlobalContext* globalCtx)
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0);
} }
} }
if (this->actor.child != NULL) { if (this->actor.child != NULL) {
if (OBJ_TOKEIDAI_TYPE(&this->actor) == OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_TERMINA_FIELD) { if (OBJ_TOKEIDAI_TYPE(&this->actor) == OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_TERMINA_FIELD) {
this->actor.child->home.rot.x = 0x384; this->actor.child->home.rot.x = 0x384;
@ -751,6 +784,9 @@ void ObjTokeidai_Update(Actor* thisx, GlobalContext* globalCtx) {
this->actionFunc(this, globalCtx); this->actionFunc(this, globalCtx);
} }
/**
* Used for TerminaFieldWalls StaircaseToRooftop, and UnusedWall
*/
void ObjTokeidai_Draw(Actor* thisx, GlobalContext* globalCtx) { void ObjTokeidai_Draw(Actor* thisx, GlobalContext* globalCtx) {
ObjTokeidai* this = THIS; ObjTokeidai* this = THIS;
@ -761,6 +797,7 @@ void ObjTokeidai_Draw(Actor* thisx, GlobalContext* globalCtx) {
func_8012C28C(globalCtx->state.gfxCtx); func_8012C28C(globalCtx->state.gfxCtx);
gSPDisplayList(POLY_OPA_DISP++, this->opaDList); gSPDisplayList(POLY_OPA_DISP++, this->opaDList);
} }
if (this->xluDList != NULL) { if (this->xluDList != NULL) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
func_8012C2DC(globalCtx->state.gfxCtx); func_8012C2DC(globalCtx->state.gfxCtx);
@ -780,26 +817,30 @@ void ObjTokeidai_Clock_Draw(Actor* thisx, GlobalContext* globalCtx) {
Matrix_InsertTranslation(0.0f, 0.0f, -1791.0f, MTXMODE_APPLY); Matrix_InsertTranslation(0.0f, 0.0f, -1791.0f, MTXMODE_APPLY);
Matrix_InsertXRotation_s(-this->xRotation, MTXMODE_APPLY); Matrix_InsertXRotation_s(-this->xRotation, MTXMODE_APPLY);
Matrix_InsertTranslation(0.0f, 0.0f, 1791.0f, MTXMODE_APPLY); Matrix_InsertTranslation(0.0f, 0.0f, 1791.0f, MTXMODE_APPLY);
Matrix_StatePush(); Matrix_StatePush();
Matrix_InsertZRotation_s(-this->outerRingOrGearRotation, MTXMODE_APPLY); Matrix_InsertZRotation_s(-this->minuteRingOrExteriorGearRotation, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, object_obj_tokeidai_DL_00CF28); gSPDisplayList(POLY_OPA_DISP++, gClockTowerMinuteRingDL);
Matrix_StatePop(); Matrix_StatePop();
Matrix_InsertTranslation(0.0f, 0.0f, this->clockFaceZTranslation, MTXMODE_APPLY); Matrix_InsertTranslation(0.0f, 0.0f, this->clockFaceZTranslation, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, object_obj_tokeidai_DL_00BEE8); gSPDisplayList(POLY_OPA_DISP++, gClockTowerClockCenterAndHandDL);
Matrix_InsertZRotation_s(-this->clockFaceRotation * 2, MTXMODE_APPLY); Matrix_InsertZRotation_s(-this->clockFaceRotation * 2, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
if (OBJ_TOKEIDAI_TYPE(&this->actor) == OBJ_TOKEIDAI_TYPE_WALL_CLOCK || if (OBJ_TOKEIDAI_TYPE(&this->actor) == OBJ_TOKEIDAI_TYPE_WALL_CLOCK ||
OBJ_TOKEIDAI_TYPE(&this->actor) == OBJ_TOKEIDAI_TYPE_SMALL_WALL_CLOCK) { OBJ_TOKEIDAI_TYPE(&this->actor) == OBJ_TOKEIDAI_TYPE_SMALL_WALL_CLOCK) {
gSPDisplayList(POLY_OPA_DISP++, object_obj_tokeidai_DL_00F518); gSPDisplayList(POLY_OPA_DISP++, gWallClockClockFace);
} else { } else {
gSPDisplayList(POLY_OPA_DISP++, object_obj_tokeidai_DL_00E818); gSPDisplayList(POLY_OPA_DISP++, gClockTowerClockFace);
} }
Matrix_InsertTranslation(0.0f, -1112.0f, -19.6f, MTXMODE_APPLY); Matrix_InsertTranslation(0.0f, -1112.0f, -19.6f, MTXMODE_APPLY);
Matrix_RotateY((s16)this->sunMoonDiskRotation, MTXMODE_APPLY); Matrix_RotateY((s16)this->sunMoonPanelRotation, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, object_obj_tokeidai_DL_00C368); gSPDisplayList(POLY_OPA_DISP++, gClockTowerSunAndMoonPanelDL);
CLOSE_DISPS(globalCtx->state.gfxCtx); CLOSE_DISPS(globalCtx->state.gfxCtx);
} }
@ -818,11 +859,16 @@ void ObjTokeidai_Counterweight_Draw(Actor* thisx, GlobalContext* globalCtx) {
OPEN_DISPS(globalCtx->state.gfxCtx); OPEN_DISPS(globalCtx->state.gfxCtx);
// For scrolling the spotlight's mask texture down the length of the light beam.
gSPSegment(POLY_XLU_DISP++, 0x08, gSPSegment(POLY_XLU_DISP++, 0x08,
Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, 0, 0, 0x20, 0x40, 1, -gameplayFrames, 0, 0x20, 0x20)); Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, 0, 0, 0x20, 0x40, 1, -gameplayFrames, 0, 0x20, 0x20));
// Draws the counterweight
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
func_8012C28C(globalCtx->state.gfxCtx); func_8012C28C(globalCtx->state.gfxCtx);
gSPDisplayList(POLY_OPA_DISP++, this->opaDList); gSPDisplayList(POLY_OPA_DISP++, this->opaDList);
// Draws the spotlight
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
func_8012C2DC(globalCtx->state.gfxCtx); func_8012C2DC(globalCtx->state.gfxCtx);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 255, 255, 235, 180, (s32)(this->spotlightIntensity * 2.55f)); gDPSetPrimColor(POLY_XLU_DISP++, 0, 255, 255, 235, 180, (s32)(this->spotlightIntensity * 2.55f));
@ -831,7 +877,7 @@ void ObjTokeidai_Counterweight_Draw(Actor* thisx, GlobalContext* globalCtx) {
CLOSE_DISPS(globalCtx->state.gfxCtx); CLOSE_DISPS(globalCtx->state.gfxCtx);
} }
void ObjTokeidai_TowerGear_Draw(Actor* thisx, GlobalContext* globalCtx) { void ObjTokeidai_ExteriorGear_Draw(Actor* thisx, GlobalContext* globalCtx) {
ObjTokeidai* this = THIS; ObjTokeidai* this = THIS;
OPEN_DISPS(globalCtx->state.gfxCtx); OPEN_DISPS(globalCtx->state.gfxCtx);
@ -842,10 +888,10 @@ void ObjTokeidai_TowerGear_Draw(Actor* thisx, GlobalContext* globalCtx) {
Matrix_InsertXRotation_s(-this->xRotation, MTXMODE_APPLY); Matrix_InsertXRotation_s(-this->xRotation, MTXMODE_APPLY);
Matrix_RotateY(thisx->shape.rot.y, MTXMODE_APPLY); Matrix_RotateY(thisx->shape.rot.y, MTXMODE_APPLY);
Matrix_InsertTranslation(0.0f, 0.0f, 1791.0f, MTXMODE_APPLY); Matrix_InsertTranslation(0.0f, 0.0f, 1791.0f, MTXMODE_APPLY);
Matrix_InsertZRotation_s(this->outerRingOrGearRotation, MTXMODE_APPLY); Matrix_InsertZRotation_s(this->minuteRingOrExteriorGearRotation, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
func_8012C28C(globalCtx->state.gfxCtx); func_8012C28C(globalCtx->state.gfxCtx);
gSPDisplayList(POLY_OPA_DISP++, object_obj_tokeidai_DL_00BA78); gSPDisplayList(POLY_OPA_DISP++, gClockTowerExteriorGearDL);
CLOSE_DISPS(globalCtx->state.gfxCtx); CLOSE_DISPS(globalCtx->state.gfxCtx);
} }

View File

@ -6,17 +6,17 @@
#define OBJ_TOKEIDAI_TYPE(thisx) (((thisx)->params & 0xF000) >> 12) #define OBJ_TOKEIDAI_TYPE(thisx) (((thisx)->params & 0xF000) >> 12)
typedef enum { typedef enum {
/* 0 */ OBJ_TOKEIDAI_TYPE_TOWER_GEAR_CLOCK_TOWN, /* 0 */ OBJ_TOKEIDAI_TYPE_EXTERIOR_GEAR_CLOCK_TOWN,
/* 1 */ OBJ_TOKEIDAI_TYPE_UNUSED_WALL, /* 1 */ OBJ_TOKEIDAI_TYPE_UNUSED_WALL,
/* 2 */ OBJ_TOKEIDAI_TYPE_TOWER_CLOCK_CLOCK_TOWN, /* 2 */ OBJ_TOKEIDAI_TYPE_TOWER_CLOCK_CLOCK_TOWN,
/* 3 */ OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_CLOCK_TOWN, /* 3 */ OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_CLOCK_TOWN,
/* 4 */ OBJ_TOKEIDAI_TYPE_TOWER_GEAR_TERMINA_FIELD, /* 4 */ OBJ_TOKEIDAI_TYPE_EXTERIOR_GEAR_TERMINA_FIELD,
/* 5 */ OBJ_TOKEIDAI_TYPE_TOWER_CLOCK_TERMINA_FIELD, /* 5 */ OBJ_TOKEIDAI_TYPE_TOWER_CLOCK_TERMINA_FIELD,
/* 6 */ OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_TERMINA_FIELD, /* 6 */ OBJ_TOKEIDAI_TYPE_COUNTERWEIGHT_TERMINA_FIELD,
/* 8 */ OBJ_TOKEIDAI_TYPE_TOWER_WALLS_TERMINA_FIELD = 8, /* 8 */ OBJ_TOKEIDAI_TYPE_TOWER_WALLS_TERMINA_FIELD = 8,
/* 9 */ OBJ_TOKEIDAI_TYPE_WALL_CLOCK, /* 9 */ OBJ_TOKEIDAI_TYPE_WALL_CLOCK,
/* 10 */ OBJ_TOKEIDAI_TYPE_SMALL_WALL_CLOCK, /* 10 */ OBJ_TOKEIDAI_TYPE_SMALL_WALL_CLOCK,
/* 11 */ OBJ_TOKEIDAI_TYPE_STAIRCASE_INTO_TOWER, /* 11 */ OBJ_TOKEIDAI_TYPE_STAIRCASE_TO_ROOFTOP,
} ObjTokeidaiType; } ObjTokeidaiType;
struct ObjTokeidai; struct ObjTokeidai;
@ -27,9 +27,9 @@ typedef struct ObjTokeidai {
/* 0x000 */ Actor actor; /* 0x000 */ Actor actor;
/* 0x144 */ Gfx* opaDList; /* 0x144 */ Gfx* opaDList;
/* 0x148 */ Gfx* xluDList; /* 0x148 */ Gfx* xluDList;
/* 0x14C */ s16 outerRingOrGearRotation; /* 0x14C */ s16 minuteRingOrExteriorGearRotation;
/* 0x14E */ s16 outerRingOrGearRotationalVelocity; /* 0x14E */ s16 minuteRingOrExteriorGearRotationalVelocity;
/* 0x150 */ s16 outerRingOrGearRotationTimer; /* 0x150 */ s16 minuteRingOrExteriorGearRotationTimer;
/* 0x152 */ s16 clockFaceRotation; /* 0x152 */ s16 clockFaceRotation;
/* 0x154 */ union { /* 0x154 */ union {
s16 clockFaceRotationalVelocity; s16 clockFaceRotationalVelocity;
@ -44,9 +44,9 @@ typedef struct ObjTokeidai {
s16 counterweightRotationalAcceleration; s16 counterweightRotationalAcceleration;
s16 aerialClockFaceSpeed; s16 aerialClockFaceSpeed;
}; };
/* 0x158 */ s32 sunMoonDiskRotation; /* 0x158 */ s32 sunMoonPanelRotation;
/* 0x15C */ union { /* 0x15C */ union {
s16 sunMoonDiskRotationalVelocity; s16 sunMoonPanelRotationalVelocity;
s16 fallingClockFaceRotationalVelocity; s16 fallingClockFaceRotationalVelocity;
}; };
/* 0x15E */ s16 yTranslation; /* 0x15E */ s16 yTranslation;
@ -58,7 +58,7 @@ typedef struct ObjTokeidai {
s32 clockHour; s32 clockHour;
s32 spotlightIntensity; s32 spotlightIntensity;
}; };
/* 0x170 */ u16 currentTime; /* 0x170 */ u16 clockTime; // can differ from the actual time, e.g., in cutscenes
/* 0x174 */ ObjTokeidaiActionFunc actionFunc; /* 0x174 */ ObjTokeidaiActionFunc actionFunc;
} ObjTokeidai; // size = 0x178 } ObjTokeidai; // size = 0x178

View File

@ -11667,24 +11667,24 @@
0x80AB2544:("DmChar09_Update",), 0x80AB2544:("DmChar09_Update",),
0x80AB25D8:("func_80AB25D8",), 0x80AB25D8:("func_80AB25D8",),
0x80AB261C:("DmChar09_Draw",), 0x80AB261C:("DmChar09_Draw",),
0x80AB2790:("ObjTokeidai_GetTargetSunMoonDiskRotation",), 0x80AB2790:("ObjTokeidai_GetTargetSunMoonPanelRotation",),
0x80AB27B4:("ObjTokeidai_SetupClockOrGear",), 0x80AB27B4:("ObjTokeidai_SetupClockOrExteriorGear",),
0x80AB2834:("ObjTokeidai_Clock_Init",), 0x80AB2834:("ObjTokeidai_Clock_Init",),
0x80AB28C8:("ObjTokeidai_TowerGear_Init",), 0x80AB28C8:("ObjTokeidai_ExteriorGear_Init",),
0x80AB29F8:("ObjTokeidai_TowerClock_Init",), 0x80AB29F8:("ObjTokeidai_TowerClock_Init",),
0x80AB2BBC:("ObjTokeidai_Counterweight_Init",), 0x80AB2BBC:("ObjTokeidai_Counterweight_Init",),
0x80AB2DEC:("ObjTokeidai_Init",), 0x80AB2DEC:("ObjTokeidai_Init",),
0x80AB3000:("ObjTokeidai_Destroy",), 0x80AB3000:("ObjTokeidai_Destroy",),
0x80AB3010:("ObjTokeidai_RotateOnMinuteChange",), 0x80AB3010:("ObjTokeidai_RotateOnMinuteChange",),
0x80AB319C:("ObjTokeidai_TowerGear_Collapse",), 0x80AB319C:("ObjTokeidai_ExteriorGear_Collapse",),
0x80AB3240:("ObjTokeidai_TowerGear_OpenedIdle",), 0x80AB3240:("ObjTokeidai_ExteriorGear_OpenedIdle",),
0x80AB32F0:("ObjTokeidai_TowerClock_Fall",), 0x80AB32F0:("ObjTokeidai_TowerClock_Fall",),
0x80AB3370:("ObjTokeidai_TowerClock_SlideOff",), 0x80AB3370:("ObjTokeidai_TowerClock_SlideOff",),
0x80AB34CC:("ObjTokeidai_TowerClock_OpenedIdle",), 0x80AB34CC:("ObjTokeidai_TowerClock_OpenedIdle",),
0x80AB3544:("ObjTokeidai_Counterweight_Collapse",), 0x80AB3544:("ObjTokeidai_Counterweight_Collapse",),
0x80AB3598:("ObjTokeidai_Counterweight_OpenedIdle",), 0x80AB3598:("ObjTokeidai_Counterweight_OpenedIdle",),
0x80AB363C:("ObjTokeidai_Walls_Collapse",), 0x80AB363C:("ObjTokeidai_TerminaFieldWalls_Collapse",),
0x80AB365C:("ObjTokeidai_Walls_Idle",), 0x80AB365C:("ObjTokeidai_TerminaFieldWalls_Idle",),
0x80AB36C4:("ObjTokeidai_TowerTransformation_EndCutscene",), 0x80AB36C4:("ObjTokeidai_TowerTransformation_EndCutscene",),
0x80AB3808:("ObjTokeidai_TowerOpening_FinishOpening",), 0x80AB3808:("ObjTokeidai_TowerOpening_FinishOpening",),
0x80AB3880:("ObjTokeidai_TowerOpening_Wait",), 0x80AB3880:("ObjTokeidai_TowerOpening_Wait",),
@ -11694,18 +11694,18 @@
0x80AB3B34:("ObjTokeidai_TowerOpening_Start",), 0x80AB3B34:("ObjTokeidai_TowerOpening_Start",),
0x80AB3BB0:("ObjTokeidai_SetupTowerOpening",), 0x80AB3BB0:("ObjTokeidai_SetupTowerOpening",),
0x80AB3BD8:("ObjTokeidai_DoNothing",), 0x80AB3BD8:("ObjTokeidai_DoNothing",),
0x80AB3BE8:("ObjTokeidai_StaircaseIntoTower_Idle",), 0x80AB3BE8:("ObjTokeidai_StaircaseToRooftop_Idle",),
0x80AB3C50:("ObjTokeidai_IsPostFirstCycleFinalHours",), 0x80AB3C50:("ObjTokeidai_IsPostFirstCycleFinalHours",),
0x80AB3CCC:("ObjTokeidai_RotateOnHourChange",), 0x80AB3CCC:("ObjTokeidai_RotateOnHourChange",),
0x80AB3ED0:("ObjTokeidai_TowerClock_Idle",), 0x80AB3ED0:("ObjTokeidai_TowerClock_Idle",),
0x80AB4040:("ObjTokeidai_WallClock_Idle",), 0x80AB4040:("ObjTokeidai_WallClock_Idle",),
0x80AB4080:("ObjTokeidai_TowerGear_Idle",), 0x80AB4080:("ObjTokeidai_ExteriorGear_Idle",),
0x80AB4160:("ObjTokeidai_Counterweight_Idle",), 0x80AB4160:("ObjTokeidai_Counterweight_Idle",),
0x80AB4278:("ObjTokeidai_Update",), 0x80AB4278:("ObjTokeidai_Update",),
0x80AB429C:("ObjTokeidai_Draw",), 0x80AB429C:("ObjTokeidai_Draw",),
0x80AB4394:("ObjTokeidai_Clock_Draw",), 0x80AB4394:("ObjTokeidai_Clock_Draw",),
0x80AB4664:("ObjTokeidai_Counterweight_Draw",), 0x80AB4664:("ObjTokeidai_Counterweight_Draw",),
0x80AB4894:("ObjTokeidai_TowerGear_Draw",), 0x80AB4894:("ObjTokeidai_ExteriorGear_Draw",),
0x80AB4D10:("func_80AB4D10",), 0x80AB4D10:("func_80AB4D10",),
0x80AB4E34:("func_80AB4E34",), 0x80AB4E34:("func_80AB4E34",),
0x80AB4E58:("func_80AB4E58",), 0x80AB4E58:("func_80AB4E58",),