diff options
-rw-r--r-- | include/g3dhax.h | 40 | ||||
-rw-r--r-- | kamek_pal.x | 24 | ||||
-rw-r--r-- | koopatlas.yaml | 12 | ||||
-rw-r--r-- | src/bonusRoom.cpp | 62 | ||||
-rw-r--r-- | src/koopatlas/core.cpp | 25 | ||||
-rw-r--r-- | src/koopatlas/core.h | 6 | ||||
-rw-r--r-- | src/koopatlas/map.cpp | 4 | ||||
-rw-r--r-- | src/koopatlas/pathmanager.cpp | 8 | ||||
-rw-r--r-- | src/koopatlas/shop.cpp | 507 | ||||
-rw-r--r-- | src/koopatlas/shop.h | 62 |
10 files changed, 718 insertions, 32 deletions
diff --git a/include/g3dhax.h b/include/g3dhax.h index d358436..551af40 100644 --- a/include/g3dhax.h +++ b/include/g3dhax.h @@ -30,6 +30,7 @@ namespace nw4r { class ResAnmChr { public: void* data; ResAnmChr(void *p = NULL) { data = p; } }; class ResAnmVis { public: void* data; ResAnmVis(void *p = NULL) { data = p; } }; + class ResAnmClr { public: void* data; ResAnmClr(void *p = NULL) { data = p; } }; class ResAnmTexPat { public: void* data; ResAnmTexPat(void *p = NULL) { data = p; } }; class ResAnmTexSrt { public: void* data; ResAnmTexSrt(void *p = NULL) { data = p; } }; @@ -51,7 +52,7 @@ namespace nw4r { void * /*ResTex*/ GetResTex(u32 idx) const; ResAnmChr GetResAnmChr(const char *str) const; ResAnmVis GetResAnmVis(const char *str) const; - void * /*ResAnmClr*/ GetResAnmClr(const char *str) const; + ResAnmClr GetResAnmClr(const char *str) const; ResAnmTexPat GetResAnmTexPat(const char *str) const; ResAnmTexSrt GetResAnmTexSrt(const char *str) const; void * /*ResAnmScn*/ GetResAnmScn(const char *str) const; @@ -89,6 +90,13 @@ namespace nw4r { void * /*ResMdl*/ resMdl); + void *__AnmObjClrRes__Construct( + void * /*MEMAllocator*/ pHeap, + u32 *pSize, + void * /*ResAnmVis*/ resAnm, + void * /*ResMdl*/ resMdl); + + void *__AnmObjTexPatRes__Construct( void * /*MEMAllocator*/ pHeap, u32 *pSize, @@ -315,6 +323,36 @@ namespace m3d { void bind(/*b*/mdl_c *model, nw4r::g3d::ResAnmVis anmRes, int unk); }; + class anmClr_c : public fanm_c { + public: + class child_c : public fanm_c { + ~child_c(); + int _vf0C(); + // some methods missing + }; + + ~anmClr_c(); + int _vf0C(); + void detach(); + void process(); + + bool setup(nw4r::g3d::ResMdl modelRes, nw4r::g3d::ResAnmClr anmRes, + mAllocator_c *allocator, u32 *sizeOutPtr, int count); // count usually 1 or 2, sizeOutPtr usually 0 + + void bind(/*b*/mdl_c *model, nw4r::g3d::ResAnmClr anmRes, int entryNumber, int _param4); // usually entryNumber is 0, param4 is 0 or 1 + + + float getFrameForEntry(int number); + void setFrameForEntry(float value, int number); + float getUpdateRateForEntry(int number); + void setUpdateRateForEntry(float value, int number); + bool isEntryAnimationDone(int number); + bool queryEntrySomething(float value, int number); + void setEntryByte34(u8 value, int number); + float getEntryField28(int number); + + }; + class anmTexPat_c : public banm_c { public: class child_c : public fanm_c { diff --git a/kamek_pal.x b/kamek_pal.x index 7978605..8c337d3 100644 --- a/kamek_pal.x +++ b/kamek_pal.x @@ -737,6 +737,7 @@ SECTIONS { resetAnim__Q23m2d13EmbedLayout_cFib = 0x800C94C0; disableAllAnimations__Q23m2d13EmbedLayout_cFv = 0x800C95F0; isAnimOn__Q23m2d13EmbedLayout_cFi = 0x800C9700; + isAnyAnimOn__Q23m2d13EmbedLayout_cFv = 0x800C9730; free__Q23m2d13EmbedLayout_cFv = 0x800C9A20; execAnimations__Q23m2d13EmbedLayout_cFv = 0x800C9650; scheduleForDrawing__Q23m2d6Base_cFv = 0x80163990; @@ -1237,11 +1238,13 @@ SECTIONS { GetResMdl = 0x80239F70; GetResAnmChr = 0x8023A1F0; GetResAnmVis = 0x8023A260; + GetResAnmClr = 0x8023A2D0; GetResAnmTexPat = 0x8023A340; GetResAnmTexSrt = 0x8023a3b0; GetResAnmChr__Q34nw4r3g3d7ResFileCFPCc = 0x8023a1f0; GetResAnmVis__Q34nw4r3g3d7ResFileCFPCc = 0x8023a260; + GetResAnmClr__Q34nw4r3g3d7ResFileCFPCc = 0x8023A2D0; GetResAnmTexPat__Q34nw4r3g3d7ResFileCFPCc = 0x8023a340; GetResAnmTexSrt__Q34nw4r3g3d7ResFileCFPCc = 0x8023a3b0; @@ -1285,6 +1288,27 @@ SECTIONS { bind__Q23m3d8anmVis_cFPQ23m3d5mdl_cQ34nw4r3g3d9ResAnmVisi = 0x80167ea0; internalBind__Q23m3d8anmVis_cFv = 0x80167f90; + /* m3d::anmClr_c */ + __vt__Q23m3d8anmClr_c = 0x80329860; + __dt__Q23m3d8anmClr_cFv = 0x80165FB0; + vf0C__Q23m3d8anmClr_cFv = 0x801664E0; + detach__Q23m3d8anmClrFv = 0x80166020; + process__Q23m3d8anmClrFv = 0x80166310; + + setup__Q23m3d8anmClr_cFQ34nw4r3g3d6ResMdlQ34nw4r3g3d9ResAnmClrP12mAllocator_cPUii = 0x80165D70; + bind__Q23m3d8anmClr_cFPQ23m3d5mdl_cQ34nw4r3g3d9ResAnmClrii = 0x80166110; + + getFrameForEntry__Q23m3d8anmClrFv = 0x80166420; + setFrameForEntry__Q23m3d8anmClrFfi = 0x80166430; + getUpdateRateForEntry__Q23m3d8anmClrFv = 0x80166440; + setUpdateRateForEntry__Q23m3d8anmClrFfi = 0x80166450; + isEntryAnimationDone__Q23m3d8anmClrFv = 0x80166460; + queryEntrySomething__Q23m3d8anmClrFv = 0x80166470; + setEntryByte34__Q23m3d8anmClrFUci = 0x80166480; + getEntryField28__Q23m3d8anmClrFv = 0x801664A0; + + + /* m3d::anmTexPat_c */ __vt__Q23m3d11anmTexPat_c = 0x80329890; __dt__Q23m3d11anmTexPat_cFv = 0x80166bb0; detach__Q23m3d11anmTexPat_cFv = 0x80166c20; diff --git a/koopatlas.yaml b/koopatlas.yaml index c376f51..1bc3466 100644 --- a/koopatlas.yaml +++ b/koopatlas.yaml @@ -12,6 +12,7 @@ source_files: - ../src/koopatlas/map.cpp - ../src/koopatlas/mapdata.cpp - ../src/koopatlas/pathmanager.cpp + - ../src/koopatlas/shop.cpp hooks: - name: BuildWorldMap @@ -39,6 +40,17 @@ hooks: src_addr_pal: 0x80984710 target_func: 'dWMMap_c::build(void)' + - name: BuildWMShop + type: add_func_pointer + src_addr_pal: 0x80986074 + target_func: 'dWMShop_c::build(void)' + + - name: BuildWMdShopItem + type: add_func_pointer + src_addr_pal: 0x809894B4 + target_func: 'dShopItem::build(void)' + + # fix the STOCK_ITEM references - name: StockItemFix type: patch diff --git a/src/bonusRoom.cpp b/src/bonusRoom.cpp index 2b0144d..c4a84cd 100644 --- a/src/bonusRoom.cpp +++ b/src/bonusRoom.cpp @@ -10,6 +10,8 @@ extern "C" void *PlaySoundAsync(dStageActor_c *, int soundID); extern "C" void *StopBGMMusic(); extern "C" void *StartBGMMusic(); extern "C" dStageActor_c* GetSpecificPlayerActor(int number); +extern "C" void *SoundRelatedClass; +extern "C" void *MapSoundPlayer(void *SoundClass, int soundID, int unk); int Songs[16][4][16][3] = { @@ -159,8 +161,8 @@ const char* Prizes[10][4] = { { "I_penguin", "g3d/I_penguin.brres", "I_penguin", "wait2" }, { "I_propeller", "g3d/I_propeller_model.brres", "I_propeller_model", "wait2" }, { "I_kinoko_bundle","g3d/I_mini_kinoko.brres", "I_mini_kinoko", "wait2" }, - { "I_hammer", "g3d/I_hammer.brres", "I_hammer", "wait2" }, { "I_star", "g3d/I_star.brres", "I_star", "wait2" }, + { "I_hammer", "g3d/I_fireflower.brres", "I_hammer", "wait2" }, { "I_kinoko_bundle","g3d/I_life_kinoko.brres", "I_life_kinoko", "wait2" }, { "obj_coin", "g3d/obj_coin.brres", "obj_coin", "wait2" } }; @@ -199,30 +201,30 @@ int PrizePacks[16][4] = { // Numbers list prizes for each level }; int Notes[24] = { - SE_EMY_PATAMET_STEP, - SE_EMY_PATAMET_STEP_2, - SE_EMY_PATAMET_STEP_3, - SE_EMY_PATAMET_STEP_4, - SE_EMY_PATAMET_STEP_5, - SE_EMY_PATAMET_STEP_6, - SE_EMY_PATAMET_STEP_7, - SE_EMY_PATAMET_STEP_8, - SE_EMY_PATAMET_STEP, - SE_EMY_PATAMET_STEP_2, - SE_EMY_PATAMET_STEP_3, - SE_EMY_PATAMET_STEP_4, - SE_EMY_PATAMET_STEP_5, - SE_EMY_PATAMET_STEP_6, - SE_EMY_PATAMET_STEP_7, - SE_EMY_PATAMET_STEP_8, - SE_EMY_PATAMET_STEP, - SE_EMY_PATAMET_STEP_2, - SE_EMY_PATAMET_STEP_3, - SE_EMY_PATAMET_STEP_4, - SE_EMY_PATAMET_STEP_5, - SE_EMY_PATAMET_STEP_6, - SE_EMY_PATAMET_STEP_7, - SE_EMY_PATAMET_STEP_8, + STRM_BGM_HIKOUSEN_ROUKA, // C + STRM_BGM_HIKOUSEN_ROUKA_FAST, + STRM_BGM_LAST_BOSS_FAST, // D + STRM_BGM_LAST_BOSS, + STRM_BGM_ROAD_TO_LAST_FAST, // E + STRM_BGM_ROAD_TO_LAST, // F + STRM_BGM_LAST_CASTLE_APPEAR, + STRM_BGM_SELECT_W5, // G + STRM_BGM_SELECT_W7, + STRM_BGM_HIKOUSEN, // A + STRM_BGM_HIKOUSEN_BOSS_FAST, + STRM_BGM_HIKOUSEN_FAST, // B + STRM_BGM_OBAKE, // C + STRM_BGM_SHIRO_FAST, + STRM_BGM_SHIRO, // D + STRM_BGM_WATER_FAST, + STRM_BGM_WATER, // E + STRM_BGM_TORIDE_BOSS_FAST, // F + STRM_BGM_TORIDE_BOSS, + STRM_BGM_DEMO_ED, // G + STRM_BGM_DEMO_OP, + STRM_BGM_SELECT_W8, // A + STRM_BGM_MG_BTL, + STRM_BGM_OBAKE_FAST, // B }; @@ -524,10 +526,10 @@ int dSingAlong::onCreate() { OSReport("Creating the Sing Along gang."); // Load in the settings this->song = this->settings & 0xF; - this->prize[0] = (this->settings >> 16) & 0xF; - this->prize[1] = (this->settings >> 20) & 0xF; - this->prize[2] = (this->settings >> 24) & 0xF; - this->prize[3] = (this->settings >> 28) & 0xF; + this->prize[0] = (this->settings >> 28) & 0xF; + this->prize[1] = (this->settings >> 24) & 0xF; + this->prize[2] = (this->settings >> 20) & 0xF; + this->prize[3] = (this->settings >> 16) & 0xF; this->chorus = -1; this->currentNote = 0; @@ -588,7 +590,7 @@ void dSingAlong::RegisterNote(int note) { OSReport("State was checked"); if (note == Songs[song][chorus][currentNote][0]) { - PlaySoundAsync(this, Notes[Songs[song][chorus][currentNote][1]-1]); + MapSoundPlayer(SoundRelatedClass, Notes[Songs[song][chorus][currentNote][1]-1], 1); OSReport("Note was correct"); currentNote += 1; } diff --git a/src/koopatlas/core.cpp b/src/koopatlas/core.cpp index 2317d00..bce31b1 100644 --- a/src/koopatlas/core.cpp +++ b/src/koopatlas/core.cpp @@ -17,6 +17,7 @@ CREATE_STATE_E(dScKoopatlas_c, TitleConfirmHitWait); CREATE_STATE_E(dScKoopatlas_c, PlayerChangeWait); CREATE_STATE_E(dScKoopatlas_c, EasyPairingWait); CREATE_STATE_E(dScKoopatlas_c, PowerupsWait); +CREATE_STATE_E(dScKoopatlas_c, ShopWait); CREATE_STATE_E(dScKoopatlas_c, SaveOpen); CREATE_STATE_E(dScKoopatlas_c, SaveSelect); CREATE_STATE_E(dScKoopatlas_c, SaveWindowClose); @@ -142,6 +143,15 @@ bool WMInit_LoadSIAnims(void *ptr) { DVD_LoadFile(GetDVDClass(), "WorldMap", "SI_star", 0); DVD_LoadFile(GetDVDClass(), "Object", "I_hammer", 0); DVD_LoadFile(GetDVDClass(), "Object", "cobCourse", 0); + DVD_LoadFile(GetDVDClass(), "Object", "obj_coin", 0); + DVD_LoadFile(GetDVDClass(), "Object", "I_kinoko", 0); + DVD_LoadFile(GetDVDClass(), "Object", "I_fireflower", 0); + DVD_LoadFile(GetDVDClass(), "Object", "I_iceflower", 0); + DVD_LoadFile(GetDVDClass(), "Object", "I_penguin", 0); + DVD_LoadFile(GetDVDClass(), "Object", "I_propeller", 0); + DVD_LoadFile(GetDVDClass(), "Object", "I_star", 0); + DVD_LoadFile(GetDVDClass(), "Object", "I_kinoko_bundle", 0); + DVD_LoadFile(GetDVDClass(), "Object", "lakitu", 0); return true; } @@ -246,6 +256,10 @@ bool WMInit_SetupExtra(void *ptr) { // because we require it earlier // it is created in dScKoopatlas_c::onCreate + SpammyReport("creating SHOP\n"); + wm->shop = (dWMShop_c*)CreateParentedObject(WM_SHOP, wm, 0, 0); + + SpammyReport("SetupExtra done\n"); return true; @@ -649,6 +663,17 @@ void dScKoopatlas_c::executeState_PowerupsWait() { } + +/**********************************************************************/ +// STATE_ShopWait : Wait for the user to exit the Shop screen. +void dScKoopatlas_c::executeState_ShopWait() { + + if (shop->isHidden) { + state.setState(&StateID_Normal); + } + +} + /**********************************************************************/ // STATE_SaveOpen : Waiting for the "Save?" YesNoWindow to open void dScKoopatlas_c::executeState_SaveOpen() { diff --git a/src/koopatlas/core.h b/src/koopatlas/core.h index 55baf95..760de19 100644 --- a/src/koopatlas/core.h +++ b/src/koopatlas/core.h @@ -12,6 +12,7 @@ #include "levelinfo.h" #include "koopatlas/mapdata.h" +#include "koopatlas/shop.h" #include "koopatlas/pathmanager.h" #define WM_DEBUGGING @@ -32,10 +33,13 @@ void NewerMapDrawFunc(); #define WM_HUD WM_DANCE_PAKKUN +#define WM_SHOP WM_TOGEZO +#define WM_SHOPITEM WM_PUKU class daWMPlayer_c; class dWMHud_c; class dWMMap_c; +class dWMShop_c; class dWorldCamera_c; class dScKoopatlas_c : public dScene_c { @@ -57,6 +61,7 @@ class dScKoopatlas_c : public dScene_c { DECLARE_STATE(PlayerChangeWait); DECLARE_STATE(EasyPairingWait); DECLARE_STATE(PowerupsWait); + DECLARE_STATE(ShopWait); DECLARE_STATE(SaveOpen); DECLARE_STATE(SaveSelect); DECLARE_STATE(SaveWindowClose); @@ -92,6 +97,7 @@ class dScKoopatlas_c : public dScene_c { daWMPlayer_c *player; dWMHud_c *hud; dWMMap_c *map; + dWMShop_c *shop; int currentMapID; const char *mapPath; diff --git a/src/koopatlas/map.cpp b/src/koopatlas/map.cpp index 2486d34..e37ee4b 100644 --- a/src/koopatlas/map.cpp +++ b/src/koopatlas/map.cpp @@ -371,6 +371,7 @@ void dWMMap_c::renderer_c::renderDoodadLayer(dKPLayer_s *layer) { else frame = anim->start + (delta * value); + float scaleYMod; // and apply it! switch (anim->type) { case dKPDoodad_s::animation_s::X_POS: @@ -387,6 +388,9 @@ void dWMMap_c::renderer_c::renderDoodadLayer(dKPLayer_s *layer) { break; case dKPDoodad_s::animation_s::Y_SCALE: effectiveHeight = (effectiveHeight * frame / 100.0); + + scaleYMod = doodad->height - effectiveHeight; + effectiveY += scaleYMod; break; case dKPDoodad_s::animation_s::OPACITY: // TODO diff --git a/src/koopatlas/pathmanager.cpp b/src/koopatlas/pathmanager.cpp index ee7b596..de2a584 100644 --- a/src/koopatlas/pathmanager.cpp +++ b/src/koopatlas/pathmanager.cpp @@ -530,7 +530,13 @@ void dWMPathManager_c::activatePoint() { int w = currentNode->levelNumber[0] - 1; int l = currentNode->levelNumber[1] - 1; - if ((l > 29) && (l < 38)) { + if (l == 0) { + dWMShop_c::instance->LoadShopForWorld(w); + dScKoopatlas_c::instance->state.setState(&dScKoopatlas_c::instance->StateID_ShopWait); + return; + } + + if ((l >= 29) && (l <= 36)) { SaveBlock *save = GetSaveFile()->GetBlock(-1); u32 conds = save->GetLevelCondition(w, l); diff --git a/src/koopatlas/shop.cpp b/src/koopatlas/shop.cpp new file mode 100644 index 0000000..ed64c8e --- /dev/null +++ b/src/koopatlas/shop.cpp @@ -0,0 +1,507 @@ +#include "koopatlas/shop.h" + + +int getStarCoinCountShop() { + SaveBlock *save = GetSaveFile()->GetBlock(-1); + int coinsSpent = save->credits_hiscore; + int coinsEarned = 0; + + for (int w = 0; w < 10; w++) { + for (int l = 0; l < 10; l++) { + u32 conds = save->GetLevelCondition(w, l); + + if (conds & COND_COIN1) { coinsEarned++; } + if (conds & COND_COIN2) { coinsEarned++; } + if (conds & COND_COIN3) { coinsEarned++; } + } + } + + int coinsLeft = coinsEarned - coinsSpent; + return coinsLeft; +} + + +const char* Produce[10][4] = { + { "I_kinoko", "g3d/I_kinoko.brres", "I_kinoko", "wait2" }, + { "I_fireflower", "g3d/I_fireflower.brres", "I_fireflower", "wait2" }, + { "I_iceflower", "g3d/I_iceflower.brres", "I_iceflower", "wait2" }, + { "I_penguin", "g3d/I_penguin.brres", "I_penguin", "wait2" }, + { "I_propeller", "g3d/I_propeller_model.brres", "I_propeller_model", "wait2" }, + { "I_kinoko_bundle","g3d/I_mini_kinoko.brres", "I_mini_kinoko", "wait2" }, + { "I_star", "g3d/I_star.brres", "I_star", "wait2" }, + { "I_hammer", "g3d/I_hammer.brres", "I_hammer", "wait2" }, + { "I_kinoko_bundle","g3d/I_life_kinoko.brres", "I_life_kinoko", "wait2" }, + { "obj_coin", "g3d/obj_coin.brres", "obj_coin", "wait2" } +}; + +/*****************************************************************************/ +// Shop Model + +class dShopItem: public dActor_c { +public: + int onCreate(); + int onDelete(); + int onExecute(); + int onDraw(); + + int p; + + mHeapAllocator_c allocator; + nw4r::g3d::ResFile resFile; + m3d::mdl_c bodyModel; + m3d::anmChr_c aw; + + static dShopItem *build(); +}; + +dShopItem *dShopItem::build() { + void *buffer = AllocFromGameHeap1(sizeof(dShopItem)); + return new(buffer) dShopItem; +} + +int dShopItem::onCreate() { + + // Settings + p = settings & 0xF; + + // Model creation + allocator.link(-1, GameHeaps[0], 0, 0x20); + + resFile.data = getResource(Produce[p][0], Produce[p][1]); + nw4r::g3d::ResMdl mdl = resFile.GetResMdl(Produce[p][2]); + bodyModel.setup(mdl, &allocator, 0x224, 1, 0); + SetupTextures_Item(&bodyModel, 0); // 800B42B0 + + // Animation Assignment + nw4r::g3d::ResAnmChr anmChr = resFile.GetResAnmChr("wait2"); + aw.setup(mdl, anmChr, &allocator, 0); + aw.bind(&bodyModel, anmChr, 1); + bodyModel.bindAnim(&aw, 0.0); + aw.setUpdateRate(1.0); + allocator.unlink(); + + return true; +} + +int dShopItem::onDelete() { return true; } +int dShopItem::onExecute() { return true; } +int dShopItem::onDraw() { + if (p == 9) { matrix.translation(pos.x, pos.y + (8.0 * scale.y), pos.z); } + else { matrix.translation(pos.x, pos.y, pos.z); } + + matrix.applyRotationYXZ(&rot.x, &rot.y, &rot.z); + + bodyModel.setDrawMatrix(matrix); + bodyModel.setScale(&scale); + bodyModel.calcWorld(false); + bodyModel.scheduleForDrawing(); + bodyModel._vf1C(); + + if(this->aw.isAnimationDone()) + this->aw.setCurrentFrame(0.0); + + return true; +} + + +/*****************************************************************************/ +// Shop Layout +// + + +const char* Lakitu[10] = { + "g3d/yoshi.brres", "g3d/desert.brres", "g3d/mountain.brres", "g3d/sakura.brres", "g3d/santa.brres", + "g3d/ghost.brres", "g3d/space.brres", "g3d/koopa.brres", "g3d/sewer.brres", "g3d/goldwood.brres" +}; + + +dWMShop_c *dWMShop_c::instance = 0; + +dWMShop_c *dWMShop_c::build() { + void *buffer = AllocFromGameHeap1(sizeof(dWMShop_c)); + dWMShop_c *c = new(buffer) dWMShop_c; + + instance = c; + return c; +} + +dWMShop_c::dWMShop_c() { + layoutLoaded = false; +} + +int dWMShop_c::onCreate() { + + if (!layoutLoaded) { + bool gotFile = layout.loadArc("shop.arc", false); + if (!gotFile) + return false; + + currentItem = 0; + isHidden = true; + + static const char *brlanNames[5] = {"shop_hitButton.brlan", "shop_offButton.brlan", "shop_onButton.brlan", "shop_inWindow.brlan", "shop_outWindow.brlan"}; + static const char *groupNames[20] = {"B00_Button", "B01_Button", "B02_Button", "B03_Button", "B05_Button", "B08_Button", + "B00_Button", "B01_Button", "B02_Button", "B03_Button", "B05_Button", "B08_Button", + "B00_Button", "B01_Button", "B02_Button", "B03_Button", "B05_Button", "B08_Button", + "A00_Window", "A00_Window"}; + + bool output = layout.build("shop.brlyt"); + + if (!IsWideScreen()) { + layout.clippingEnabled = true; + layout.clipX = 0; + layout.clipY = 52; + layout.clipWidth = 640; + layout.clipHeight = 352; + layout.layout.rootPane->scale.x = 0.7711f; + layout.layout.rootPane->scale.y = 0.7711f; + } + + layout.loadAnimations(brlanNames, 5); + layout.loadGroups(groupNames, (int[20]){0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 4}, 20); + layout.disableAllAnimations(); + + for (int i = 6; i < 12; i++) { + layout.enableNonLoopAnim(i); + } + + layout.drawOrder = 0x01; + + layoutLoaded = true; + } + + return true; +} + + +int dWMShop_c::onDelete() { + return layout.free(); +} + + +int dWMShop_c::onExecute() { + layout.execAnimations(); + layout.update(); + + if (!isHidden) { + int nowPressed = Remocon_GetPressed(GetActiveRemocon()); + + if (!layout.isAnyAnimOn()) { + if (nowPressed & WPAD_B) { + MapSoundPlayer(SoundRelatedClass, SE_SYS_DIALOGUE_OUT_AUTO, 1); + CloseUpShop(); + } else if (nowPressed & WPAD_DOWN) { + if (currentItem == 6) { return true; } + MapSoundPlayer(SoundRelatedClass, SE_SYS_CURSOR, 1); + int last = currentItem; + if (currentItem == 0) { currentItem = 1; } + else if (currentItem < 5) { currentItem = 5; } + else { currentItem = 6; } + changeItem(last, currentItem); + } else if (nowPressed & WPAD_UP) { + if (currentItem == 0) { return true; } + MapSoundPlayer(SoundRelatedClass, SE_SYS_CURSOR, 1); + int last = currentItem; + if (currentItem < 5) { currentItem = 0; } + else if (currentItem == 5) { currentItem = 1; } + else { currentItem = 5; } + changeItem(last, currentItem); + } else if (nowPressed & WPAD_RIGHT) { + if (currentItem == 6) { currentItem = 6; return true; } + MapSoundPlayer(SoundRelatedClass, SE_SYS_CURSOR, 1); + int last = currentItem; + currentItem += 1; + changeItem(last, currentItem); + } else if (nowPressed & WPAD_LEFT) { + if (currentItem == 0) { return true; } + MapSoundPlayer(SoundRelatedClass, SE_SYS_CURSOR, 1); + int last = currentItem; + currentItem -= 1; + changeItem(last, currentItem); + } else if (nowPressed & WPAD_TWO) { + BuyItem(currentItem); + } + } + } + + return true; +} + +int dWMShop_c::onDraw() { + if (isHidden) { + if (layout.isAnimOn(19)) { layout.scheduleForDrawing(); } + } + + if (!isHidden) { + layout.scheduleForDrawing(); + + Vec pos = {layout.posX, layout.posY, 40000.0}; + S16Vec rot = {0,0,0}; + Vec scale = {1.0, 1.0, 1.0}; + matrix.translation(pos.x, pos.y, pos.z); + matrix.applyRotationYXZ(&rot.x, &rot.y, &rot.z); + + shopkeep.setDrawMatrix(matrix); + shopkeep.setScale(&scale); + shopkeep.calcWorld(false); + shopkeep.scheduleForDrawing(); + shopkeep._vf1C(); + + if(this->ska.isAnimationDone()) + this->ska.setCurrentFrame(0.0); + } + + return true; +} + +void dWMShop_c::specialDraw1() { + OSReport("Lakionnnne...."); + if (!isHidden) { + Vec pos = {layout.posX, layout.posY, 40000.0}; + S16Vec rot = {0,0,0}; + Vec scale = {1.0, 1.0, 1.0}; + matrix.translation(pos.x, pos.y, pos.z); + matrix.applyRotationYXZ(&rot.x, &rot.y, &rot.z); + + shopkeep.setDrawMatrix(matrix); + shopkeep.setScale(&scale); + shopkeep.calcWorld(false); + shopkeep.scheduleForDrawing(); + shopkeep._vf1C(); + + if(this->ska.isAnimationDone()) + this->ska.setCurrentFrame(0.0); + } + return; +} + +void dWMShop_c::specialDraw2() { + OSReport("Lakituuu...."); + if (!isHidden) { + Vec pos = {layout.posX, layout.posY, 40000.0}; + S16Vec rot = {0,0,0}; + Vec scale = {1.0, 1.0, 1.0}; + matrix.translation(pos.x, pos.y, pos.z); + matrix.applyRotationYXZ(&rot.x, &rot.y, &rot.z); + + shopkeep.setDrawMatrix(matrix); + shopkeep.setScale(&scale); + shopkeep.calcWorld(false); + shopkeep.scheduleForDrawing(); + shopkeep._vf1C(); + + if(this->ska.isAnimationDone()) + this->ska.setCurrentFrame(0.0); + } + return; +} + + +void dWMShop_c::changeItem(int last, int current) { + + if (last) { layout.enableNonLoopAnim(last - 1 + 6); } + if (current) { layout.enableNonLoopAnim(current - 1 + 12); } + +} + + // Powerup Listing: + // 0 = Mushroom - 1 + // 1 = Fireflower - 2 + // 2 = Iceflower - 2 + // 3 = Penguin - 3 + // 4 = Propeller - 3 + // 5 = MiniShroom - 2 + // 6 = Starman - 2 + // 7 = Hammer - 3 + // 8 = 1-ups - 2 + // 9 = Coins - 1 + // + // Format: 1coin, 1coin, 2coins, 3coins, 5coins[3] (Value 6-9), 8coins[5] (Value 10-15) + // + // Possible 5 coin combos = 2,2,2 / 1,2,3 / 2,3,2 / 3,2,3 / 3,3,3 + // Possible 8 coin combos = 1,1,2,3,3 / 1,2,2,3,3 / 1,2,3,3,3 / 2,2,2,3,3 / 2,2,3,3,3 / 1,3,3,3,3 / 2,3,3,3,3 / 3,3,3,3,3 + +int Inventory[10][12] = { + { 9, 0, 1, 4, 1, 2, 1, 0, 0, 8, 4, 4 }, // Yoshi Island Shop + { 9, 0, 1, 4, 1, 6, 1, 0, 1, 1, 4, 4 }, // Desert Shop + { 9, 0, 5, 4, 0, 5, 4, 0, 5, 4, 4, 7 }, // Mountain Shop + { 9, 0, 8, 7, 8, 8, 8, 4, 2, 8, 1, 4 }, // Japan Shop + { 9, 0, 2, 3, 2, 3, 2, 2, 3, 3, 3, 2 }, // FreezeFlame Shop + { 9, 0, 6, 4, 5, 4, 5, 4, 4, 9, 4, 4 }, // Ghost Shop + { 9, 0, 6, 7, 6, 6, 6, 7, 7, 8, 7, 7 }, // Space Shop + { 0, 8, 4, 7, 7, 4, 7, 4, 7, 4, 7, 4 }, // Koopa Shop + { 9, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0 }, // Sewer Shop? + { 0, 8, 1, 5, 1, 4, 1, 1, 1, 6, 1, 1 }, // Goldwood Shop +}; + +void dWMShop_c::LoadShopForWorld(int world) { + if (!isHidden) { + return; } + + // Handle showing it + MapSoundPlayer(SoundRelatedClass, SE_SYS_DIALOGUE_IN, 1); + isHidden = false; + layout.enableNonLoopAnim(18); + + // Model creation + allocator.link(-1, GameHeaps[0], 0, 0x20); + + res.data = getResource("lakitu", Lakitu[world]); + nw4r::g3d::ResMdl mdl = res.GetResMdl("lakitu"); + shopkeep.setup(mdl, &allocator, 0x224, 1, 0); + SetupTextures_Item(&shopkeep, 0); // 800B42B0 + + // Animation Assignment (idle, notenough) + nw4r::g3d::ResAnmChr anmChr = res.GetResAnmChr("idle"); + ska.setup(mdl, anmChr, &allocator, 0); + ska.bind(&shopkeep, anmChr, 1); + shopkeep.bindAnim(&ska, 0.0); + ska.setUpdateRate(1.0); + allocator.unlink(); + + + Vec pos = {layout.posX, layout.posY, 40000.0}; + + // Setup all the item buttons for sale + // itemA = (dShopItem*)CreateChildObject(WM_SHOPITEM, this, Inventory[world][0], 0, 0); + // itemB = (dShopItem*)CreateChildObject(WM_SHOPITEM, this, Inventory[world][1], 0, 0); + // itemC = (dShopItem*)CreateChildObject(WM_SHOPITEM, this, Inventory[world][2], 0, 0); + // itemD = (dShopItem*)CreateChildObject(WM_SHOPITEM, this, Inventory[world][3], 0, 0); + // itemEA = (dShopItem*)CreateChildObject(WM_SHOPITEM, this, Inventory[world][4], 0, 0); + // itemEB = (dShopItem*)CreateChildObject(WM_SHOPITEM, this, Inventory[world][5], 0, 0); + // itemEC = (dShopItem*)CreateChildObject(WM_SHOPITEM, this, Inventory[world][6], 0, 0); + // itemFA = (dShopItem*)CreateChildObject(WM_SHOPITEM, this, Inventory[world][7], 0, 0); + // itemFB = (dShopItem*)CreateChildObject(WM_SHOPITEM, this, Inventory[world][8], 0, 0); + // itemFC = (dShopItem*)CreateChildObject(WM_SHOPITEM, this, Inventory[world][9], 0, 0); + // itemFD = (dShopItem*)CreateChildObject(WM_SHOPITEM, this, Inventory[world][10], 0, 0); + // itemFE = (dShopItem*)CreateChildObject(WM_SHOPITEM, this, Inventory[world][11], 0, 0); +} + + +void dWMShop_c::CloseUpShop() { + isHidden = true; + layout.enableNonLoopAnim(19); + changeItem(currentItem, 0); + currentItem = 0; + + // itemA->Delete(); + // itemB->Delete(); + // itemC->Delete(); + // itemD->Delete(); + // itemEA->Delete(); + // itemEB->Delete(); + // itemEC->Delete(); + // itemFA->Delete(); + // itemFB->Delete(); + // itemFC->Delete(); + // itemFD->Delete(); + // itemFE->Delete(); +} + + +void dWMShop_c::BuyItem(int item) { + OSReport("Buy item %d", item); + + if (item == 0) { + MapSoundPlayer(SoundRelatedClass, SE_SYS_INVALID, 1); + return; + } + + layout.enableNonLoopAnim(item-1); + + int cash = getStarCoinCountShop(); + int cost; + + int Powerups[10]; + + Powerups[0] = 0; // Mushroom + Powerups[1] = 0; // Fireflower + Powerups[2] = 0; // Iceflower + Powerups[3] = 0; // Penguin + Powerups[4] = 0; // Propeller + Powerups[5] = 0; // MiniShroom + Powerups[6] = 0; // Starman + Powerups[7] = 0; // Hammer + Powerups[8] = 0; // 1-ups + Powerups[9] = 0; // Coins + + switch(item) { + case 1: + cost = 1; + Powerups[Inventory[world][item-1]]++; + break; + case 2: + cost = 1; + Powerups[Inventory[world][item-1]]++; + break; + case 3: + cost = 2; + Powerups[Inventory[world][item-1]]++; + break; + case 4: + cost = 3; + Powerups[Inventory[world][item-1]]++; + break; + case 5: + cost = 5; + Powerups[Inventory[world][item-1]]++; + Powerups[Inventory[world][item+0]]++; + Powerups[Inventory[world][item+1]]++; + break; + case 6: + cost = 8; + Powerups[Inventory[world][item+1]]++; + Powerups[Inventory[world][item+2]]++; + Powerups[Inventory[world][item+3]]++; + Powerups[Inventory[world][item+4]]++; + Powerups[Inventory[world][item+5]]++; + break; + } + + if (cost > cash) { + MapSoundPlayer(SoundRelatedClass, SE_SYS_INVALID, 1); + return; + } + + MapSoundPlayer(SoundRelatedClass, SE_SYS_DECIDE, 1); + + + SaveFile *file = GetSaveFile(); + SaveBlock *block = file->GetBlock(file->header.current_file); + + block->credits_hiscore += cost; + + + for (int i = 0; i < 7; i++) { // Change this to 8 to support hammers + block->powerups_available[i] = block->powerups_available[i] + Powerups[i]; + + if (block->powerups_available[i] > 99) { block->powerups_available[i] = 99; } + } + + for (int i = 0; i < 4; i++) { // Make sure all players get the reward! + block->player_coins[i] = (Powerups[9] * 50) + block->player_coins[i]; + + for (;block->player_coins[i] < 100; block->player_coins[i] - 100) { + block->player_coins[i] = 1 + block->player_coins[i]; + } + + block->player_lives[i] = Powerups[8] + block->player_lives[i]; + if (block->player_lives[i] > 99) { block->player_lives[i] = 99; } + } + + CloseUpShop(); + return; + +} + + + + + + + + + + + + diff --git a/src/koopatlas/shop.h b/src/koopatlas/shop.h new file mode 100644 index 0000000..b4281b7 --- /dev/null +++ b/src/koopatlas/shop.h @@ -0,0 +1,62 @@ +#ifndef __KOOPATLAS_SHOP_H +#define __KOOPATLAS_SHOP_H + +#include "koopatlas/core.h" + +extern "C" void *SoundRelatedClass; +extern "C" void *MapSoundPlayer(void *SoundClass, int soundID, int unk); + +class dShopItem; + +class dWMShop_c : public dActor_c { + public: + dWMShop_c(); + + int onCreate(); + int onDelete(); + int onExecute(); + int onDraw(); + void specialDraw1(); + void specialDraw2(); + + bool layoutLoaded; + m2d::EmbedLayout_c layout; + + mHeapAllocator_c allocator; + nw4r::g3d::ResFile res; + m3d::mdl_c shopkeep; + m3d::anmChr_c ska; + mMtx matrix; + + char currentItem; + bool isHidden; + int world; + + dShopItem *itemA; + dShopItem *itemB; + dShopItem *itemC; + dShopItem *itemD; + + dShopItem *itemEA; + dShopItem *itemEB; + dShopItem *itemEC; + + dShopItem *itemFA; + dShopItem *itemFB; + dShopItem *itemFC; + dShopItem *itemFD; + dShopItem *itemFE; + + + void LoadShopForWorld(int world); + void CloseUpShop(); + void BuyItem(int item); + + void changeItem(int last, int current); + + static dWMShop_c *build(); + static dWMShop_c *instance; +}; + +#endif + |