From 4cebce48645bcefd509cf1d39b34c8b24eed2411 Mon Sep 17 00:00:00 2001 From: MysterD Date: Sun, 5 Sep 2021 14:17:20 -0700 Subject: [PATCH] Added Waluigi - model provided by Super Keeberghrh --- Makefile.split | 4 + actors/custom0.c | 3 + actors/custom0.h | 12 + actors/custom0_geo.c | 1 + actors/waluigi/custom_waluigi_cap.rgba16.png | Bin 0 -> 411 bytes actors/waluigi/geo.inc.c | 1068 +++++ actors/waluigi/geo_header.h | 243 + actors/waluigi/model.inc.c | 4246 +++++++++++++++++ actors/waluigi_cap/geo.inc.c | 85 + actors/waluigi_cap/model.inc.c | 416 ++ actors/zcustom0.c | 3 + actors/zcustom0.h | 3 + actors/zcustom0_geo.c | 2 + bin/segment2.c | 9 +- developer/network.sh | 4 +- include/model_ids.h | 6 + include/types.h | 2 + levels/scripts.c | 24 +- src/engine/graph_node.h | 1 + src/game/characters.c | 179 +- src/game/characters.h | 12 +- src/game/hud.h | 1 + src/game/mario_actions_moving.c | 2 +- src/game/object_list_processor.c | 2 + src/game/rendering_graph_node.c | 22 + src/pc/pc_main.c | 2 + .../segment2/custom_waluigi_head.rgba16.png | Bin 0 -> 3426 bytes 27 files changed, 6333 insertions(+), 19 deletions(-) create mode 100644 actors/waluigi/custom_waluigi_cap.rgba16.png create mode 100644 actors/waluigi/geo.inc.c create mode 100644 actors/waluigi/geo_header.h create mode 100644 actors/waluigi/model.inc.c create mode 100644 actors/waluigi_cap/geo.inc.c create mode 100644 actors/waluigi_cap/model.inc.c create mode 100644 textures/segment2/custom_waluigi_head.rgba16.png diff --git a/Makefile.split b/Makefile.split index a65df8dd..be322eb1 100644 --- a/Makefile.split +++ b/Makefile.split @@ -75,6 +75,10 @@ ZCUSTOM_DIRS := luigi CUSTOM_DIRS += toad_cap ZCUSTOM_DIRS += toad_player +# Add Waluigi +CUSTOM_DIRS += waluigi_cap +ZCUSTOM_DIRS += waluigi + # Actor Files CUSTOM_FILES := $(foreach dir,$(addprefix $(ACTOR_DIR)/,$(CUSTOM_DIRS)),$(patsubst %.png,%.inc.c,$(wildcard $(dir)/*.png))) AMP_CHUCKYA_FILES := $(foreach dir,$(addprefix $(ACTOR_DIR)/,$(AMP_DIRS)),$(patsubst %.png,%.inc.c,$(wildcard $(dir)/*.png))) diff --git a/actors/custom0.c b/actors/custom0.c index 0ead73b7..f78d1d14 100644 --- a/actors/custom0.c +++ b/actors/custom0.c @@ -6,3 +6,6 @@ // luigi_cap #include "luigi_cap/model.inc.c" + +// waluigi_cap +#include "waluigi_cap/model.inc.c" diff --git a/actors/custom0.h b/actors/custom0.h index 8c5fb2d9..0523c1ce 100644 --- a/actors/custom0.h +++ b/actors/custom0.h @@ -28,4 +28,16 @@ extern const GeoLayout toads_cap_geo[]; extern const GeoLayout toads_metal_cap_geo[]; extern const GeoLayout toads_wing_cap_geo[]; +// waluigi_cap +extern const GeoLayout waluigis_cap_geo[]; +extern const GeoLayout waluigis_metal_cap_geo[]; +extern const GeoLayout waluigis_wing_cap_geo[]; +extern const GeoLayout waluigis_winged_metal_cap_geo[]; +extern const Gfx waluigi_cap_seg3_dl_03022F48[]; +extern const Gfx waluigi_cap_seg3_dl_03022FF8[]; +extern const Gfx waluigi_cap_seg3_dl_030230B0[]; +extern const Gfx waluigi_cap_seg3_dl_03023160[]; +extern const Gfx waluigi_cap_seg3_dl_03023108[]; +extern const Gfx waluigi_cap_seg3_dl_03023298[]; + #endif diff --git a/actors/custom0_geo.c b/actors/custom0_geo.c index 429e1d40..20ddf17b 100644 --- a/actors/custom0_geo.c +++ b/actors/custom0_geo.c @@ -6,3 +6,4 @@ #include "luigi_cap/geo.inc.c" // custom luigi_cap #include "toad_cap/geo.inc.c" // custom toad_cap +#include "waluigi_cap/geo.inc.c" // custom waluigi_cap diff --git a/actors/waluigi/custom_waluigi_cap.rgba16.png b/actors/waluigi/custom_waluigi_cap.rgba16.png new file mode 100644 index 0000000000000000000000000000000000000000..411a27ef1f6c0dc2137dde5a0e6fd7e3594c2253 GIT binary patch literal 411 zcmV;M0c8G(P)<{AO-V#SR9Fe^mE8`)APj|v8u3kh|Htu7T)dc^DM{%M6t-kHTcXyj zJ?8^k49l`iM_!jB&Eb6l9KHj$-X56e`CY4tF+OU~`Lp1if|fBC_JX(odd(?J3#18< z&09j$6mhOYT&u1202P7I^a{RH>$!wA|NjOZ3&NZNVNMlyj7@+YJyt1eK`MZiycJ5* zt@c3Gkp0eUuD3^sumI2~Nq!OX+^9hn6~F1A4JiOve%DtHflags |= flags; } +} + +f32 get_character_anim_offset(struct MarioState* m) { + if (m == NULL || m->marioObj == NULL) { return 0; } + struct Object* marioObj = m->marioObj; + struct Character* c = get_character(m); + if (!c->animOffsetEnabled) { return 0; } + s32 animID = marioObj->header.gfx.unk38.animID; + if (animID < 0 || animID >= ANIM_TYPE_MAX) { return 0; } + + switch (sAnimTypes[animID]) { + case ANIM_TYPE_LOWY: + if (m->minimumBoneY < c->animOffsetLowYPoint) { + return -(m->minimumBoneY - c->animOffsetLowYPoint); + } + break; + case ANIM_TYPE_FEET: + return c->animOffsetFeet; + break; + case ANIM_TYPE_HAND: + return c->animOffsetHand; + break; + } + return 0; +} + +void update_character_anim_offset(struct MarioState* m) { + if (m == NULL || m->marioObj == NULL) { return; } + struct Object* marioObj = m->marioObj; + struct Character* c = get_character(m); + if (!c->animOffsetEnabled) { return; } + + f32 targetOffset = get_character_anim_offset(m); + + // smooth + f32 alpha = (fabs(targetOffset - m->curAnimOffset) / 80.0f) + 0.5f; + alpha = (alpha + 0.5f) / 2.0f; + alpha *= alpha; + m->curAnimOffset = (m->curAnimOffset * alpha) + (targetOffset * (1.0f - alpha)); + if (m->curAnimOffset > 40) { m->curAnimOffset = 40; } + if (m->curAnimOffset < -40) { m->curAnimOffset = -40; } + + //s32 animID = marioObj->header.gfx.unk38.animID; + //LOG_INFO(">>> [%d] : %d :: %f, %f", animID, sAnimTypes[animID], m->curAnimOffset, m->minimumBoneY); + + marioObj->header.gfx.pos[1] = m->pos[1] + m->curAnimOffset; + marioObj->header.gfx.node.flags |= GRAPH_RENDER_PLAYER; } \ No newline at end of file diff --git a/src/game/characters.h b/src/game/characters.h index 927a6886..e53c6225 100644 --- a/src/game/characters.h +++ b/src/game/characters.h @@ -7,6 +7,7 @@ enum CharacterType { CT_MARIO, CT_LUIGI, CT_TOAD, + CT_WALUIGI, // must be last CT_MAX @@ -24,8 +25,13 @@ struct Character { u8 capEnemyLayer; Gfx* capEnemyGfx; Gfx* capEnemyDecalGfx; - f32 soundFreqScale; + // anim + u8 animOffsetEnabled; + f32 animOffsetLowYPoint; + f32 animOffsetFeet; + f32 animOffsetHand; // sounds + f32 soundFreqScale; s32 soundYahWahHoo; s32 soundHoohoo; s32 soundYahoo; @@ -119,8 +125,12 @@ enum CharacterSound { struct MarioState; extern struct Character gCharacters[]; struct Character* get_character(struct MarioState* m); + void play_character_sound(struct MarioState* m, enum CharacterSound characterSound); void play_character_sound_offset(struct MarioState* m, enum CharacterSound characterSound, u32 offset); void play_character_sound_if_no_flag(struct MarioState* m, enum CharacterSound characterSound, u32 flags); +f32 get_character_anim_offset(struct MarioState* m); +void update_character_anim_offset(struct MarioState* m); + #endif // CHARACTERS_H diff --git a/src/game/hud.h b/src/game/hud.h index 76167426..b6451385 100644 --- a/src/game/hud.h +++ b/src/game/hud.h @@ -21,6 +21,7 @@ enum CameraHUDLut { GLYPH_CAM_ARROW_DOWN, GLYPH_CAM_LUIGI_HEAD, GLYPH_CAM_TOAD_HEAD, + GLYPH_CAM_WALUIGI_HEAD, }; // Functions diff --git a/src/game/mario_actions_moving.c b/src/game/mario_actions_moving.c index 975247b3..01c96c76 100644 --- a/src/game/mario_actions_moving.c +++ b/src/game/mario_actions_moving.c @@ -89,7 +89,7 @@ void play_step_sound(struct MarioState *m, s16 frame1, s16 frame2) { } void align_with_floor(struct MarioState *m) { - m->pos[1] = m->floorHeight; + m->pos[1] = m->floorHeight + get_character_anim_offset(m); mtxf_align_terrain_triangle(sFloorAlignMatrix[m->playerIndex], m->pos, m->faceAngle[1], 40.0f); m->marioObj->header.gfx.throwMatrix = &sFloorAlignMatrix[m->playerIndex]; } diff --git a/src/game/object_list_processor.c b/src/game/object_list_processor.c index 3704cf49..8786392a 100644 --- a/src/game/object_list_processor.c +++ b/src/game/object_list_processor.c @@ -299,6 +299,8 @@ void bhv_mario_update(void) { i++; } + update_character_anim_offset(gMarioState); + // reset mario state to the local player gMarioState = &gMarioStates[0]; } diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index ed7f13e8..1ef61d39 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -10,6 +10,7 @@ #include "rendering_graph_node.h" #include "shadow.h" #include "sm64.h" +#include "game/level_update.h" /** * This file contains the code that processes the scene graph for rendering. @@ -147,6 +148,7 @@ static Gfx *sViewportPos; static Vp sPrevViewport; struct Object* gCurGraphNodeProcessingObject; +struct MarioState* gCurGraphNodeMarioState; void mtx_patch_interpolated(void) { s32 i; @@ -797,6 +799,12 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) { gMatStackFixed[gMatStackIndex] = matrixPtr; mtxf_to_mtx(mtxInterpolated, gMatStackInterpolated[gMatStackIndex]); gMatStackInterpolatedFixed[gMatStackIndex] = mtxInterpolated; + + if (gCurGraphNodeMarioState != NULL) { + Vec3f translated = { 0 }; + get_pos_from_transform_mtx(translated, gMatStack[gMatStackIndex], *gCurGraphNodeCamera->matrixPtr); + gCurGraphNodeMarioState->minimumBoneY = fmin(gCurGraphNodeMarioState->minimumBoneY, translated[1] - gCurGraphNodeMarioState->marioObj->header.gfx.pos[1]); + } if (node->displayList != NULL) { geo_append_display_list(node->displayList, node->node.flags >> 8); } @@ -1069,10 +1077,23 @@ static void interpolate_matrix(Mat4 result, Mat4 a, Mat4 b) { */ static void geo_process_object(struct Object *node) { struct Object* lastProcessingObject = gCurGraphNodeProcessingObject; + struct MarioState* lastMarioState = gCurGraphNodeMarioState; gCurGraphNodeProcessingObject = node; Mat4 mtxf; s32 hasAnimation = (node->header.gfx.node.flags & GRAPH_RENDER_HAS_ANIMATION) != 0; Vec3f scaleInterpolated; + if (node->header.gfx.node.flags & GRAPH_RENDER_PLAYER) { + gCurGraphNodeMarioState = NULL; + for (int i = 0; i < MAX_PLAYERS; i++) { + if (gMarioStates[i].marioObj == node) { + gCurGraphNodeMarioState = &gMarioStates[i]; + break; + } + } + if (gCurGraphNodeMarioState != NULL) { + gCurGraphNodeMarioState->minimumBoneY = 999; + } + } if (node->header.gfx.unk18 == gCurGraphNodeRoot->areaIndex) { if (node->header.gfx.throwMatrix != NULL) { mtxf_mul(gMatStack[gMatStackIndex + 1], *node->header.gfx.throwMatrix, @@ -1194,6 +1215,7 @@ static void geo_process_object(struct Object *node) { node->header.gfx.throwMatrixInterpolated = NULL; } gCurGraphNodeProcessingObject = lastProcessingObject; + gCurGraphNodeMarioState = lastMarioState; } /** diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index 01cad86a..fda30d3d 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -213,6 +213,8 @@ void main_func(void) { fs_init(sys_ropaths, gamedir, userpath); configfile_load(configfile_name()); + if (configPlayerModel >= CT_MAX) { configPlayerModel = 0; } + if (configPlayerPalette >= 16) { configPlayerPalette = 0; } if (gCLIOpts.FullScreen == 1) configWindow.fullscreen = true; diff --git a/textures/segment2/custom_waluigi_head.rgba16.png b/textures/segment2/custom_waluigi_head.rgba16.png new file mode 100644 index 0000000000000000000000000000000000000000..44da9765ff93c73015e47cad44c19d62f222e603 GIT binary patch literal 3426 zcmV-o4W06dP)KLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=00004XF*Lt006O$eEU(80000WV@Og>004R=004l4008;_004mL004C` z008P>0026e000+nl3&F}0007gNklf+$ zTsN5*{KhJAgtdZhMbWJoW9%b*VTVE&!T3E0rX$H@^)_fscYs2@+Dl6&1R7#R&FzgeAji|L7@0Gw}pgxt13RM!A-u3c(9 z)GYm>915#6Y==c@?)scx=c5$lXK}3lA)%1q`^+M`xwJ9Fs@FaaPFE0XT%x6D0?%v& zJ*xjsSfTb*H6tHqDJ%&v6ZwI*8e0#sCH;gv;3&b4rQk1h3Ff>b86TAzCdDT4zkbHeZhydMfEfnwBPx;O~n1(0)K_Z%9 zYEEP7OL#-$ra+!_u`)i)hw)(m!a{(6yFHVC-N;`90Fyu_l@aevTmS$707*qoM6N<$ Ef