static void aTOU_rewrite_door(ACTOR* actor, GAME_PLAY* play){
    TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor;
    
    xyz_t pos;
    Door_data_c* door_data = Common_GetPointer(structure_exit_door_data);

    if(play->fb_wipe_mode == 0){
        door_data->next_scene_id = Save_Get(scene_no);
        door_data->exit_orientation = 4;
        door_data->exit_type = 0;
        door_data->extra_data = 3;

        pos.x = light->actor_class.world.position.x;
        pos.z = light->actor_class.world.position.z - 70.0f;
        pos.y = mCoBG_GetBgY_OnlyCenter_FromWpos2(pos, 0.0f);
        door_data->exit_position.x = pos.x;
        door_data->exit_position.y = pos.y;
        door_data->exit_position.z = pos.z;
        door_data->door_actor_name = light->actor_class.npc_id;
        door_data->wipe_type = 1;
        mBGMPsComp_make_ps_wipe(0x2168);
    }
}

static int aTOU_check_door_pos(ACTOR* actor, GAME_PLAY* play){
    TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor;

    PLAYER_ACTOR* player = get_player_actor_withoutCheck(play);
    f32 diff;

    if(player != NULL){ 
        diff = (player->actor_class.world.position.z - light->actor_class.world.position.z);
        if(fabsf(player->actor_class.world.position.x - light->actor_class.world.position.x) < 20.0f && 
            diff > -65.0f && diff < 0.0f){
            if((player->actor_class.shape_info.rotation.y > -0x2000) && 
                (player->actor_class.shape_info.rotation.y < 0x2000)){
                return 1;     
            }
        } 
    }

    return 0;
}

Door_data_c aTOU_door_data = {
    SCENE_LIGHTHOUSE,
    0,
    FALSE,
    0,
    {120,0,100},
    EMPTY_NO,
    1,
    {0,0,0},
};

static void aTOU_set_bgOffset(TOUDAI_ACTOR* light, int idx){
    static mCoBG_OffsetTable_c height_table_ct[] = { { 0x64, 16, 16, 16, 16, 16, 0 },
                                            { 0x64, 16, 16, 16, 16, 16, 0 },
                                            { 0x64, 16, 16, 16, 16, 16, 0 },
                                            { 0x64, 16, 16, 16, 16, 16, 0 } };
    static mCoBG_OffsetTable_c* height_table[] = { height_table_ct, height_table_ct };
    static f32 addX[] = { -40.0f, 0.0f };
    static f32 addZ[] = { -40.0f, 0.0f }; 
    
    mCoBG_OffsetTable_c* offset;
    int i;
    xyz_t pos;

    offset  = height_table[idx]; 

    for(i = 0; i < 2; i++){
        pos.z = light->actor_class.home.position.z + addZ[i];
        pos.x = light->actor_class.home.position.x + addX[0];
        mCoBG_SetPluss5PointOffset_file(pos, *offset, "ac_toudai_move.c_inc", 184);
        offset++;
        pos.x = light->actor_class.home.position.x + addX[1];
        mCoBG_SetPluss5PointOffset_file(pos, *offset, "ac_toudai_move.c_inc", 188);
        offset++;
    }
}

static void aTOU_color_ctrl(TOUDAI_ACTOR* light) {
    f32 factor;
    int timer;

    if (light->ready_flag == 0) {
        add_calc(&light->unk2C8, 0.0f, 1.0f - sqrtf(0.7), 50.0f, 0.5f);
        add_calc(&light->unk2CC, 0.0f, 1.0f - sqrtf(0.7), 50.0f,  0.5f);
        add_calc(&light->unk2D0, 0.0f, 1.0f - sqrtf(0.9), 50.0f,  0.5f);
        return;
    }

    timer = light->current_frame - 51;
    factor = (timer < 0) ? 1.0f : -1.0f;
    timer = ABS(timer);

    if (timer == 0) {
        light->unk2C8 = 220.0f;
        light->unk2CC = 240.0f;

    } else if (timer >= 40) {
        add_calc(&light->unk2C8, 0.0f, 1.0f - sqrtf(0.7), 50.0f, 0.5f);
        add_calc(&light->unk2CC, 0.0f, 1.0f - sqrtf(0.7), 50.0f, 0.5f);

    } else if (timer < 10) {
        light->unk2C8 += (4.5f * factor);
        light->unk2CC += (7.0f * factor);

    } else if (timer < 30) {
        light->unk2C8 += (1.25f * factor);
        light->unk2CC += (2.25f * factor);

    } else {
        light->unk2C8 += (4.0f * factor);
        light->unk2CC += (0.5f * factor);
    }

    add_calc(&light->unk2D0, 255.0f, 1.0f - sqrtf(0.9), 50.0f, 0.5f);
}

static void aTOU_init(ACTOR* actor, GAME_PLAY* play){
    aTOU_setup_action(actor, 1);
}

static void aTOU_wait(ACTOR* actor, GAME_PLAY* play){
    TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor;
    int sec = Common_Get(time.now_sec);
    
    if(mSC_LightHouse_Switch_Check() != 0 && (sec >= 64800 || sec < 18000)){
            light->keyframe.frame_control.speed = 0.5f;
            light->ready_flag = TRUE; 
            aTOU_setup_action(actor, 2);
        }
}
 
static void aTOU_lighting(ACTOR* actor, GAME_PLAY* play){
    TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor;
    int sec = Common_Get(time.now_sec);
    
    if((mSC_LightHouse_Switch_Check() == 0) || ((sec < 64800) 
        && (sec >= 18000))){   
            aTOU_setup_action(actor, 3);
        }
}

static void aTOU_lightout(ACTOR* actor, GAME_PLAY* play){
    TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; 

    if(light->current_frame == 0x33){
            light->keyframe.frame_control.speed = 0.0f;
            light->ready_flag = 0; 
            aTOU_setup_action(actor, 1);
        }
}

extern cKF_Animation_R_c cKF_ba_r_obj_s_toudai;
extern cKF_Animation_R_c cKF_ba_r_obj_w_toudai;

static void aTOU_setup_action(ACTOR* actor, int action) {
    TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; 
    static cKF_Animation_R_c* ani[] = { &cKF_ba_r_obj_s_toudai, &cKF_ba_r_obj_w_toudai };
    static TOUDAI_PROC process[] = { aTOU_init, aTOU_wait, aTOU_lighting, aTOU_lightout };

    int type;
    
    if(action == 0){
        type = light->season == mTM_SEASON_WINTER;
        cKF_SkeletonInfo_R_init(&light->keyframe, light->keyframe.skeleton, ani[type], 
            1.0f, 100.0f, 51.0f, 0.0f, 0.0f, cKF_FRAMECONTROL_REPEAT, NULL);
    }

    light->proc = process[action];
    light->current_proc = action;
}

static void aTOU_actor_move(ACTOR* actor, GAME* game){
    GAME_PLAY* play = (GAME_PLAY*)game;
    TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; 

    light->keyframe_state = cKF_SkeletonInfo_R_play(&light->keyframe);
    light->current_frame = light->keyframe.frame_control.current_frame;

    if(get_player_actor_withoutCheck((GAME_PLAY*)gamePT)->get_door_label_proc(gamePT) == light){
        aTOU_rewrite_door(&light->actor_class, play);
        goto_other_scene(play, &aTOU_door_data, 0);
    }
    else{
        light->proc(actor,play);

        if((mSC_LightHouse_In_Check() != 0) && (aTOU_check_door_pos(actor,play) != 0)){
            xyz_t pos;
            pos.x = light->actor_class.world.position.x;
            pos.y = light->actor_class.world.position.y;
            pos.z = light->actor_class.world.position.z - 60.0f;
            mPlib_request_main_door_type1(game, &pos, 0, 1, light); 
        }
    } 
    aTOU_color_ctrl(light); 
}

static void aTOU_actor_init(ACTOR* actor, GAME* game){
    TOUDAI_ACTOR* light = (TOUDAI_ACTOR*)actor; 
    
    mFI_SetFG_common(0xF11E, light->actor_class.home.position, 0);
    aTOU_actor_move(actor, game);
    light->actor_class.mv_proc = aTOU_actor_move;
}
