diff --git a/config/rel_slices.yml b/config/rel_slices.yml index d518201c..c6df974f 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -25,6 +25,10 @@ m_actor_dlftbls.c: .text: [0x8037619C, 0x803761BC] .data: [0x8064D628, 0x8064F4E8] .bss: [0x8125A828, 0x8125A830] +m_actor_shadow.c: + .text: [0x803761BC, 0x80377114] + .rodata: [0x80641328, 0x80641388] + .data: [0x8064F4E8, 0x8064F548] m_banti.c: .text: [0x80377114, 0x80378858] .rodata: [0x80641388, 0x806413E0] diff --git a/include/m_actor.h b/include/m_actor.h index 6527c19e..a905e5d4 100644 --- a/include/m_actor.h +++ b/include/m_actor.h @@ -339,6 +339,22 @@ typedef struct actor_shape_info_s { /* 0x2F */ u8 unused_2F[0x48-0x2F]; } Shape_Info; +typedef struct actor_shadow_s{ + /* 0x00 */ xyz_t position; + /* 0x0C */ f32 groundY; + /* 0x10 */ f32 unk10; + /* 0x14 */ f32 unk14; + /* 0x18 */ f32 unk18; + /* 0x1C */ f32 unk1C; + /* 0x20 */ s16 unk20; + /* 0x22 */ s16 unk22; + /* 0x24 */ s16 unk24; + /* 0x26 */ s16 unk26; + /* 0x28 */ char pad28[0xC]; + /* 0x34 */ int unk34; + /* 0x38 */ int kind; +}Shadow_Info; + /* sizeof(struct actor_s) == 0x174 */ struct actor_s { /* 0x000 */ s16 id; /* unique actor type ID */ @@ -446,8 +462,6 @@ extern Hilite* HiliteReflect_xlu_init(xyz_t* pos, xyz_t* eye, xyz_t* light_direc extern void Setpos_HiliteReflect_init(xyz_t* pos, GAME_PLAY* play); extern void Setpos_HiliteReflect_xlu_init(xyz_t* pos, GAME_PLAY* play); -extern void mAc_ActorShadowCircle(ACTOR* actor, LightsN* lightsN, GAME_PLAY* play); -extern void mAc_ActorShadowEllipse(ACTOR* actor, LightsN* lightsN, GAME_PLAY* play); #ifdef __cplusplus } diff --git a/include/m_actor_shadow.h b/include/m_actor_shadow.h new file mode 100644 index 00000000..c3329259 --- /dev/null +++ b/include/m_actor_shadow.h @@ -0,0 +1,35 @@ +#ifndef M_ACTOR_SHADOW_H +#define M_ACTOR_SHADOW_H + +#include "types.h" +#include "m_actor.h" + +int mActorShadow_OperateScrollLimit(int, int, int); +Gfx* mActorShadow_TileScroll2(u32 *, u32 *, int, int, int, int, int, int, u32 *, u32 *, int, int, int, int, int, int, GAME *); +void mActorShadow_AdjustRate(f32 *); +void mActorShadow_GetTimeAngleY_TimeAlpha(Shadow_Info *, GAME_PLAY *); +void mActorShadow_GetGroundAverageAngle(Shadow_Info *); +void mActorShadow_GetDistanceRate(Shadow_Info *, f32); +f32 mActorShadow_GetAbsBigger(f32, f32); +void mActorShadow_RadiusScaleRate(ACTOR *, Shadow_Info *); +void mActorShadow_GetShadowTopPos_GetSlideS(Shadow_Info *); +Gfx* mActorShadow_SetTexScroll(ACTOR *, Shadow_Info *, GAME *); +void mActorShadow_GetLastAlphaScale(f32 *, u8 *, ACTOR *, Shadow_Info *); +void mActorShadow_DrawActorShadow(ACTOR *, Shadow_Info *, GAME_PLAY *, int, xyz_t, f32); +void mActorShadow_GetShadowPosition(ACTOR *, xyz_t *); +int mActorShadow_GetShadowKind(void); +f32 mAc_GetShadowGroundY_NoneForce(const Shadow_Info *); +f32 mAc_GetShadowGroundY_Force(const Shadow_Info *); +void mAc_DecideShadowRadius_IamNotFish(Shadow_Info *, ACTOR *, f32 *); +void mAc_DecideShadowRadius_IamFish(Shadow_Info *, ACTOR *, f32 *); +void mAc_ActorShadowDraw_ShadowDrawFlagOff(ACTOR *, GAME_PLAY *, int, xyz_t, f32); +void mAc_ActorShadowDraw_ShadowDrawFlagOn(ACTOR *, GAME_PLAY *, int, xyz_t, f32); +void mAc_ActorShadowDraw(ACTOR *, GAME_PLAY *, int, xyz_t, f32); +void mActorShadow_SetForceShadowPos(ACTOR *, xyz_t *); +void mActorShadow_UnSetForceShadowPos(ACTOR *); +void mAc_NormalActorShadow(ACTOR *, GAME_PLAY *, f32); +void mAc_UnagiActorShadow(ACTOR *, GAME_PLAY *, xyz_t); +void mAc_ActorShadowCircle(ACTOR *, LightsN *, GAME_PLAY *); +void mAc_ActorShadowEllipse(ACTOR *, LightsN *, GAME_PLAY *); + +#endif diff --git a/include/m_collision_bg.h b/include/m_collision_bg.h index 9d20ac3f..024c0b0b 100644 --- a/include/m_collision_bg.h +++ b/include/m_collision_bg.h @@ -106,6 +106,7 @@ extern u32 mCoBG_Wpos2BgAttribute_Original(xyz_t wpos); extern u32 mCoBG_Wpos2Attribute(xyz_t wpos, char* is_diggable); extern int mCoBG_CheckWaterAttribute(u32 attribute); extern f32 mCoBG_GetBgY_AngleS_FromWpos(s_xyz* angle_to_ground, xyz_t wpos, f32 offset_y); +extern f32 mCoBG_GetShadowBgY_AngleS_FromWpos(f32, s_xyz*, xyz_t); extern int mCoBG_CheckWaterAttribute_OutOfSea(u32 attribute); extern int mCoBG_CheckHole_OrgAttr(u32 attribute); extern f32 mCoBG_GetBgY_OnlyCenter_FromWpos2(xyz_t wpos, f32 foot_dist); diff --git a/include/m_kankyo.h b/include/m_kankyo.h index 28d68de4..edc17e16 100644 --- a/include/m_kankyo.h +++ b/include/m_kankyo.h @@ -3,6 +3,7 @@ #include "types.h" #include "m_lights.h" +#include "game.h" #ifdef __cplusplus extern "C" { @@ -38,7 +39,9 @@ typedef struct kankyo_s { /* 0x00 */ Lights sun_light; /* 0x0E */ u8 pad[0x9A - 0x0E]; /* 0x9A */ u8 ambientColor[3]; - /* 0x9E */ u8 pad2[0xC8 - 0x9E]; + /* 0x9E */ u8 pad2[0xC0 - 0x9E]; + /* 0xC0 */ f32 unkC0; + /* 0xC4 */ u8 unkC4; /* 0xC8 */ Nature nature; } Kankyo; @@ -47,7 +50,7 @@ extern int mEnv_NowWeather(); extern int mEnv_WindMove(); extern void mEnv_ManagePointLight(GAME_PLAY*, Kankyo*, Global_light*); extern void Global_kankyo_set(GAME_PLAY*, Kankyo*, Global_light*); - +extern void mEnv_GetShadowPrimColor_Light(u8*,u8*,u8*,GAME*); #ifdef __cplusplus } #endif diff --git a/rel/ac_airplane.c b/rel/ac_airplane.c index 3a7d374e..62d10e4d 100644 --- a/rel/ac_airplane.c +++ b/rel/ac_airplane.c @@ -10,6 +10,7 @@ #include "m_controller.h" #include "m_name_table.h" #include "m_common_data.h" +#include "m_actor_shadow.h" static void Airplane_Actor_ct(ACTOR* actor, GAME* game); static void Airplane_Actor_dt(ACTOR* actor, GAME* game); diff --git a/rel/m_actor_shadow.c b/rel/m_actor_shadow.c new file mode 100644 index 00000000..c2e118bd --- /dev/null +++ b/rel/m_actor_shadow.c @@ -0,0 +1,411 @@ +#include "m_actor_shadow.h" + +#include "m_collision_bg.h" +#include "m_common_data.h" +#include "m_rcp.h" +#include "sys_matrix.h" +#include "m_lib.h" +#include "m_lights.h" + + +extern Gfx ef_shadow_out_modelT[]; +extern Gfx ef_shadow_in_modelT[]; + + +int mActorShadow_OperateScrollLimit(int value, int step, int limit) { + if (step != 0) { + if (step > 0) { + value += step; + if (value > limit) { + value = limit; + } + } else if (step < 0) { + value += step; + if (value < limit) { + value = limit; + } + } + } + return value; +} + +Gfx* mActorShadow_TileScroll2(u32* x1, u32* y1, int step1, int step2, int limit1, int limit2, int width1, +int height1, u32* x2, u32* y2, int step3, int step4, int limit3, int limit4, +int width2, int height2, GAME* game){ + + + *x1 = mActorShadow_OperateScrollLimit(*x1, step1, limit1); + *y1 = mActorShadow_OperateScrollLimit(*y1, step2, limit2); + *x2 = mActorShadow_OperateScrollLimit(*x2, step3, limit3); + *y2 = mActorShadow_OperateScrollLimit(*y2, step4, limit4); + + return two_tex_scroll(game->graph, 0, *x1, *y1, width1, height1, 1, *x2, *y2, width2, height2); +} + + +void mActorShadow_AdjustRate(f32* rate) { + if (*rate < 0.0f) { + *rate = 0.0f; + } else if (*rate > 1.0f) { + *rate = 1.0f; + } +} + +void mActorShadow_GetTimeAngleY_TimeAlpha(Shadow_Info* shadow, GAME_PLAY* play){ + f32 timef; + int timesec = Common_Get(time.now_sec); + shadow->unk1C = play->kankyo.unkC4; + + // Between 4 a.m and 8 p.m + if((timesec >= 14400) && ( timesec < 72000)){ + timef = (timesec - 14400) / 57600.0f; + } //Between 12 a.m and 4 a.m + else if (timesec < 14400){ + timef = 0.5f + timesec / 28800.0f; + } // Between 8 p.m and 12 a.m + else{ + timef = (timesec - 72000)/ 28800.0f; + } + + shadow->unk26 = 0x8000 - ((s16)(16384.0f * timef) + 0x6000); +} + + +void mActorShadow_GetGroundAverageAngle(Shadow_Info* shadow){ + static xyz_t angle_range_table[4] = { + { 10.0f, 0.0f, 10.0f }, + { 10.0f, 0.0f, -10.0f }, + { -10.0f, 0.0f, 10.0f }, + { -10.0f, 0.0f, -10.0f }, + }; + + int x = 0; + int y = 0; + int z = 0; + int i; + + for (i = 0; i < 4; i++) { + xyz_t pos = shadow->position; + s_xyz sangle = {0, 0, 0}; + + pos.x += angle_range_table[i].x; + pos.y += angle_range_table[i].y; + pos.z += angle_range_table[i].z; + + mCoBG_GetBgY_AngleS_FromWpos(&sangle, pos, 0.0f); + + x += sangle.x; + y += sangle.y; + z += sangle.z; + } + + shadow->unk20 = x >> 2; + shadow->unk22 = y >> 2; + shadow->unk24 = z >> 2; +} + +void mActorShadow_GetDistanceRate(Shadow_Info* shadow, f32 rate) { + f32 xcalc; + f32 disty = shadow->position.y - shadow->groundY; + + disty = disty >= 0.0f ? disty : -disty; + xcalc = rate + 100.0f; + + if (disty > xcalc){ + shadow->unk14 = 0.600000023842f; + shadow->unk18 = 0; + return; + } + + xcalc = (xcalc - disty) / xcalc; + shadow->unk14 = xcalc * 0.399999976158f + 0.6f; + shadow->unk18 = xcalc; +} +f32 mActorShadow_GetAbsBigger(f32 a, f32 b) { + a = a >= 0.0f ? a : -a; + b = b >= 0.0f ? b : -b; + + if(a > b){ + return a; + } + return b; +} + +void mActorShadow_RadiusScaleRate(ACTOR* actor, Shadow_Info* shadow) { + f32 abs_bigger = mActorShadow_GetAbsBigger(actor->shape_info.shadow_size_x, actor->shape_info.shadow_size_z); + shadow->unk10 = (abs_bigger / 19.0f) * 0.018f; +} + +void mActorShadow_GetShadowTopPos_GetSlideS(Shadow_Info* shadow) { + + xyz_t wpos; + xyz_t base; + f32 bg_y; + int res; + + if (shadow->kind == 0) { + base.x = 0.0f; + base.y = 0.0f; + base.z = -40.0f; + sMath_RotateY(&base, shadow->unk26 * (9.58738019108e-05f)); + wpos.x = shadow->position.x + base.x; + wpos.y = shadow->position.y + base.y; + wpos.z = shadow->position.z + base.z; + res = 0; + bg_y = mCoBG_GetShadowBgY_AngleS_FromWpos(0.0f, NULL, wpos); + if ((shadow->position.y - bg_y) > 20.0f) { + shadow->unk34 = 28; + return; + } + } + shadow->unk34 = 0; +} + +Gfx* mActorShadow_SetTexScroll(ACTOR* actor, Shadow_Info* shadow, GAME* game){ + + u32 y1 = 0; + u32 x1 = 0; + u32 y2 = 0; + int step; + + if(actor->shape_info.unk_20 < shadow->unk34){ + step = 0xD; + } + else if(actor->shape_info.unk_20 > shadow->unk34){ + step = -0xD; + } + else{ + step = 0; + } + + mActorShadow_TileScroll2(&x1, &y1, 0, 0, 0, 0, 0x20, 0x10, (u32*)&actor->shape_info.unk_20, &y2, step, 0, shadow->unk34, 0, 0x20, 0x10, game); +} + + +void mActorShadow_GetLastAlphaScale(f32* scale, u8* alpha, ACTOR* actor, Shadow_Info* shadow) { + + f32 alph = shadow->unk1C * shadow->unk18 * actor->shape_info.shadow_alpha_change_rate * 0.75f; + + *scale = shadow->unk10 * shadow->unk14 * actor->shape_info.shadow_size_change_rate; + + if (shadow->kind == 1) { + alph *= 0.7f; + } + *alpha = alph; +} + + +void mActorShadow_DrawActorShadow(ACTOR* actor, Shadow_Info* shadow, GAME_PLAY* play, int id, xyz_t ofs, f32 rad) { + f32 x, y, z; + f32 y_adjust; + f32 scale; + u8 alpha; + u8 r, g, b; + int scene; + Gfx* texscroll; + GRAPH* graph; + GAME* game = (GAME*)play; + + + scene = Save_Get(scene_no); + + mActorShadow_GetLastAlphaScale(&scale, &alpha, actor, shadow); + graph = game->graph; + _texture_z_light_fog_prim_shadow(graph); + + OPEN_DISP(graph); + + y_adjust = (scene == 19 || scene == 27 || scene == 28 || scene == 34) ? 0.5f : + ((scene == 15 || scene == 16 || scene == 49) ? 0.6f : 2.0f); + + switch (actor->shape_info.force_shadow_position) { + case 1: + x = actor->shape_info.shadow_position->x + ofs.x; + y = actor->shape_info.shadow_position->y + y_adjust + ofs.y; + z = actor->shape_info.shadow_position->z + ofs.z; + Matrix_translate(x, y, z, 0); + break; + default: + x = shadow->position.x + ofs.x; + y = shadow->groundY + y_adjust + ofs.y; + z = shadow->position.z + ofs.z; + Matrix_translate(x, y, z, 0); + break; + } + + switch (actor->shape_info.force_shadow_position) { + case 1: + Matrix_RotateZ(0, 1); + Matrix_RotateX(0, 1); + break; + default: + Matrix_RotateZ(shadow->unk24, 1); + Matrix_RotateX(shadow->unk20, 1); + break; + } + + if ((shadow->kind == 0) && (id == 0)) { + Matrix_RotateY(shadow->unk26, 1); + } + + switch (id) { + case 1: + Matrix_scale(shadow->unk10, shadow->unk10, rad, 1); + break; + default: + switch (actor->shape_info.force_shadow_position) { + case 1: + Matrix_scale(shadow->unk10, shadow->unk10, shadow->unk10, 1); + break; + default: + Matrix_scale(scale, scale, scale, 1); + break; + } + break; + } + + gSPMatrix(NEXT_SHADOW_DISP, _Matrix_to_Mtx_new(game->graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + mEnv_GetShadowPrimColor_Light(&r, &g, &b, game); + gDPSetPrimColor(NEXT_SHADOW_DISP, 0, 0xFF, r, g, b, (u8)alpha); + + if ((shadow->kind == 0) && (id == 0)) { + texscroll = mActorShadow_SetTexScroll(actor, shadow, game); + if (texscroll != NULL) { + gSPSegment(NEXT_SHADOW_DISP, 0x08, texscroll); + gSPDisplayList(NEXT_SHADOW_DISP, ef_shadow_out_modelT); + } + } else { + gSPDisplayList(NEXT_SHADOW_DISP, ef_shadow_in_modelT); + } + + CLOSE_DISP(graph); + +} + +void mActorShadow_GetShadowPosition(ACTOR* actor, xyz_t* position){ + + if(actor->shape_info.shadow_position != NULL){ + *position = *actor->shape_info.shadow_position; + } + else { + *position = actor->world.position; + } +} + +int mActorShadow_GetShadowKind(void) { + if (!(mFI_GetFieldId() & 0xF000)) { + return 0; + } else { + return 1; + } +} + +f32 mAc_GetShadowGroundY_NoneForce(const Shadow_Info* shadow){ + f32 res = mCoBG_GetShadowBgY_AngleS_FromWpos(0.0f, NULL, shadow->position); + return res; +} + +f32 mAc_GetShadowGroundY_Force(const Shadow_Info* shadow){ + return mCoBG_GetBgY_OnlyCenter_FromWpos2(shadow->position, 0.0f); +} + +void mAc_DecideShadowRadius_IamNotFish(Shadow_Info* shadow, ACTOR* actor, f32* radius) { + mActorShadow_RadiusScaleRate(actor, shadow); + *radius = 0.01f; +} + +void mAc_DecideShadowRadius_IamFish(Shadow_Info* shadow, ACTOR* actor, f32* radius) { + shadow->unk10 = (actor->shape_info.shadow_size_x / 19.0f) * 0.018f; + *radius = (actor->shape_info.shadow_size_z / 19.0f) * 0.018f; +} + +void mAc_ActorShadowDraw_ShadowDrawFlagOff(ACTOR* actor, GAME_PLAY* play, int arg2, xyz_t arg3, f32 arg6){ + +} + +void mAc_ActorShadowDraw_ShadowDrawFlagOn(ACTOR* actor, GAME_PLAY* play, int proc, xyz_t pos, f32 rate){ + static void (*set_raius_proc[])(Shadow_Info*, ACTOR*, f32*) = { + mAc_DecideShadowRadius_IamNotFish, + mAc_DecideShadowRadius_IamFish, + }; + static f32 (*get_ground_y_proc[])(const Shadow_Info*) = { + mAc_GetShadowGroundY_NoneForce, + mAc_GetShadowGroundY_Force, + }; + + Shadow_Info shadow; + f32 rad = 0.01f; + u8 ground_y_proc; + bzero(&shadow, sizeof(Shadow_Info)); + + shadow.kind = mActorShadow_GetShadowKind(); + mActorShadow_GetShadowPosition(actor, &shadow.position); + mActorShadow_AdjustRate(&actor->shape_info.shadow_size_change_rate); + mActorShadow_AdjustRate(&actor->shape_info.shadow_alpha_change_rate); + + ground_y_proc = actor->shape_info.force_shadow_position & 1; + shadow.groundY = get_ground_y_proc[ground_y_proc](&shadow); + + mActorShadow_GetTimeAngleY_TimeAlpha(&shadow, play); + mActorShadow_GetGroundAverageAngle(&shadow); + mActorShadow_GetDistanceRate(&shadow, rate); + set_raius_proc[proc & 1](&shadow, actor, &rad); + mActorShadow_GetShadowTopPos_GetSlideS(&shadow); + mActorShadow_DrawActorShadow(actor, &shadow, play, proc, pos, rad); + actor->shape_info.force_shadow_position = 0; +} + +void mAc_ActorShadowDraw(ACTOR* actor, GAME_PLAY* play, int arg2, xyz_t arg3, f32 arg6) { + + static void (*shadwo_draw_proc[])(ACTOR* actor, GAME_PLAY* play, int arg2, xyz_t arg3, f32 arg6) = { + mAc_ActorShadowDraw_ShadowDrawFlagOff, + mAc_ActorShadowDraw_ShadowDrawFlagOn, +}; + + if (actor->id == 0x4A) { + mActorShadow_UnSetForceShadowPos(actor); + actor->shape_info.shadow_position = &actor->world.position; + } + + shadwo_draw_proc[actor->shape_info.draw_shadow & 1](actor, play, arg2, arg3, arg6); + actor->shape_info.shadow_position = &actor->world.position; +} + +xyz_t mActorShadow_offset0 = { 0.0f, 0.0f, 0.0f }; + + +void mActorShadow_SetForceShadowPos(ACTOR* actor, xyz_t* pos) { + actor->shape_info.force_shadow_position = 1; + actor->shape_info.shadow_position = pos; +} + +void mActorShadow_UnSetForceShadowPos(ACTOR* actor) { + actor->shape_info.force_shadow_position = 0; + actor->shape_info.shadow_position = &actor->world.position; +} + + +void mAc_NormalActorShadow(ACTOR* actor, GAME_PLAY* play, f32 rad){ + mAc_ActorShadowDraw(actor, play, 0, mActorShadow_offset0, rad); +} + +void mAc_UnagiActorShadow(ACTOR* actor, GAME_PLAY* play, xyz_t pos){ + mAc_ActorShadowDraw(actor, play, 1, pos, 1.0f); +} + +void mAc_ActorShadowCircle(ACTOR* actor, LightsN* lights, GAME_PLAY* play){ + mAc_ActorShadowDraw(actor, play, 0, mActorShadow_offset0, 1.0f); +} + +void mAc_ActorShadowEllipse(ACTOR* actor, LightsN* lights, GAME_PLAY* play){ + + static xyz_t tunekiti_offset = { 0.0f, 1.0f, 0.0f }; + + if(actor->id == 0x79){ + mAc_ActorShadowDraw(actor, play, 0, tunekiti_offset, 1.0f); + + } + else{ + mAc_ActorShadowDraw(actor, play, 0, mActorShadow_offset0, 1.0f); + } +} \ No newline at end of file