#include #include "functions.h" #include "variables.h" #include "prop.h" extern void actor_predrawMethod(Actor *); extern void actor_postdrawMethod(ActorMarker *); extern f32 randf (void); extern BKModelBin *chvilegame_get_grumblie_model(ActorMarker *marker); enum chyumblie_state_e{ YUMBLIE_STATE_1_UNDER_GROUND = 1, YUMBLIE_STATE_2_APPEAR, YUMBLIE_STATE_3_ABOVE_GROUND, YUMBLIE_STATE_4_DISAPPEAR, YUMBLIE_STATE_5_BEING_EATEN }; typedef struct chyumblie_s{ f32 unk0; u8 unk4; u8 pad7[3]; f32 unk8; //wait_timer ActorMarker *game_marker; } ActorLocal_Yumblie; void chyumblie_set_state(Actor*, enum chyumblie_state_e); void chyumblie_update(Actor *); Actor *chyumblie_draw(ActorMarker *this, Gfx **gfx, Mtx** mtx, Vtx **vtx); /* .data */ ActorInfo D_80390A40 = {MARKER_C7_YUMBLIE, ACTOR_139_YUMBLIE, ASSET_3F6_MODEL_YUMBLIE, 0x00, NULL, chyumblie_update, NULL, chyumblie_draw, 0, 0, 0.0f, 0 }; /* .code */ bool func_8038B160(Actor *this){ ActorLocal_Yumblie *local; s32 temp_v0; local = (ActorLocal_Yumblie *)&this->local; temp_v0 = func_8038A9E0(local->game_marker); if ((temp_v0 == 1) || (temp_v0 == 4)) return FALSE; if ((temp_v0 == 2) || (temp_v0 == 5)) return (0.7 <= randf ()) ? TRUE : FALSE; return (randf () >= 0.5)? TRUE : FALSE; } void chyumblie_set_state(Actor* this, enum chyumblie_state_e next_state){ ActorLocal_Yumblie *s0; s0 = (ActorLocal_Yumblie *)&this->local; s0->unk8 = 0; if(next_state == 1){ s0->unk8 = randf2(1.0f, 10.0f); } if(next_state == 2){ this->yaw = randf2(0.0f, 360.0f); s0->unk4 = func_8038B160(this); chvilegame_new_piece(s0->game_marker, this->marker, this->position, s0->unk4); skeletalAnim_set(this->unk148, (s0->unk4)? ASSET_128_ANIM_GRUMBLIE_APPEAR : ASSET_125_ANIM_YUMBLIE_APPEAR, 0.0f, 1.5f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); } if(next_state == 3){ s0->unk8 = randf2(5.0f, 10.0f); skeletalAnim_set(this->unk148, (s0->unk4)? ASSET_12A_ANIM_GRUMBLIE_IDLE : ASSET_127_ANIM_YUMBLIE_IDLE, 0.1f, randf2(0.5f, 1.0f)); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_1_LOOP); if(s0->unk4){ func_8030E6A4(SFX_C4_TWINKLY_MUNCHER_GRR,randf2(1.0f, 1.2), 30000); }else{ func_8030E878(SFX_C3_HEGH,randf2(1.0f, 1.2), 30000, this->position, 500.0f, 3000.0f); } } if(next_state == 4){ chvilegame_remove_piece(s0->game_marker, this->marker); skeletalAnim_set(this->unk148, (s0->unk4)? ASSET_129_ANIM_GRUMBLIE_HIDE : ASSET_126_ANIM_YUMBLIE_HIDE, 0.1f, 0.5f); skeletalAnim_setBehavior(this->unk148, SKELETAL_ANIM_2_ONCE); } if(next_state == 5){ s0->unk8 = randf2(10.0f, 20.0f); chvilegame_remove_piece(s0->game_marker, this->marker); func_8030E878((s0->unk4)? SFX_C4_TWINKLY_MUNCHER_GRR: SFX_C3_HEGH, 1.4f, 32000, this->position, 500.0f, 3000.0f); } this->state = next_state; } bool chyumblie_is_edible(ActorMarker * arg0){ volatile Actor* actPtr; actPtr = marker_getActor(arg0); return (actPtr->state >= 2) && (actPtr->state < 5); } Actor *chyumblie_draw(ActorMarker *this, Gfx **gfx, Mtx** mtx, Vtx **vtx){ Actor *thisActor; ActorLocal_Yumblie *sp40; f32 sp44[3]; f32 sp38[3]; thisActor = marker_getActor(this); sp40 = (ActorLocal_Yumblie *)&thisActor->local; if ( thisActor->state < 2 || thisActor->state > 4){ thisActor->marker->unk14_21 = 0; return thisActor; } modelRender_preDraw((GenFunction_1) actor_predrawMethod, (s32)thisActor); modelRender_postDraw((GenFunction_1) actor_postdrawMethod, (s32)this); sp44[0] = thisActor->position_x; sp44[1] = thisActor->position_y + sp40->unk0*75.0f; sp44[2] = thisActor->position_z; sp38[0] = thisActor->pitch; sp38[1] = thisActor->yaw; sp38[2] = thisActor->roll; if(sp40->unk4 && sp40->game_marker){ modelRender_draw(gfx, mtx, sp44, sp38, 1.0f, NULL, chvilegame_get_grumblie_model(sp40->game_marker)); } else{ modelRender_draw(gfx, mtx, sp44, sp38, 1.0f, NULL, marker_loadModelBin(this)); } return thisActor; } bool func_8038B684(ActorMarker * arg0){ Actor* actPtr = marker_getActor(arg0); if( actPtr->state < 5){ chyumblie_set_state(actPtr, YUMBLIE_STATE_5_BEING_EATEN); return TRUE; } return FALSE; } void chyumblie_update(Actor *this){ ActorLocal_Yumblie *s0; f32 sp50; f32 sp4C; f32 sp48; s32 pad44; f32 tmp; s0 = (ActorLocal_Yumblie *)&this->local; sp4C = time_getDelta(); if(!this->volatile_initialized){ this->volatile_initialized = TRUE; s0->unk0 = 0.0f; s0->unk4 = 0; s0->game_marker = NULL; chyumblie_set_state(this, YUMBLIE_STATE_1_UNDER_GROUND); return; } if(s0->game_marker == NULL){ s0->game_marker = actorArray_findClosestActorFromActorId(this->position, ACTOR_138_VILE_GAME_CTRL, -1, &sp48)->marker; } sp50 = skeletalAnim_getProgress(this->unk148); if(this->state == YUMBLIE_STATE_1_UNDER_GROUND){ if(ml_timer_update(&s0->unk8, sp4C)){ if(mapSpecificFlags_get(6) && (12 > chvilegame_get_piece_count(s0->game_marker))){ chyumblie_set_state(this, YUMBLIE_STATE_2_APPEAR); } else{ chyumblie_set_state(this, YUMBLIE_STATE_1_UNDER_GROUND); } } } if(this->state == YUMBLIE_STATE_2_APPEAR){ tmp = s0->unk0; if(s0->unk4){ if(sp50 <= 0.3){ s0->unk0 = sp50/0.3; } }else{ if(sp50 <= 0.6){ s0->unk0 = sp50/0.6; } } if((tmp < 0.5) && (0.5 <= s0->unk0)){ func_8030E878(SFX_C5_TWINKLY_POP, randf2(1.0f, 1.2f), 30000, this->position, 500.0f, 3000.0f); } if( 0 < skeletalAnim_getLoopCount(this->unk148)){ s0->unk0 = 1.0f; chyumblie_set_state(this,YUMBLIE_STATE_3_ABOVE_GROUND); } } if(this->state == YUMBLIE_STATE_3_ABOVE_GROUND){ if( ml_timer_update(&s0->unk8,sp4C) || !mapSpecificFlags_get(6) ){ chyumblie_set_state(this,YUMBLIE_STATE_4_DISAPPEAR); } } if(this->state == YUMBLIE_STATE_4_DISAPPEAR){ if(sp50 >= 0.25 ) s0->unk0 -= 2.0f*(f64)sp4C; if(0.0f >= s0->unk0){ s0->unk0 = 0.0f; chyumblie_set_state(this,YUMBLIE_STATE_1_UNDER_GROUND); } } if(this->state == YUMBLIE_STATE_5_BEING_EATEN){ if( ml_timer_update(&s0->unk8,sp4C)){ chyumblie_set_state(this,YUMBLIE_STATE_1_UNDER_GROUND); } } }