#include "koopatlas/shop.h" CREATE_STATE(dWMShop_c, Hidden); CREATE_STATE(dWMShop_c, ShowWait); CREATE_STATE(dWMShop_c, ButtonActivateWait); CREATE_STATE(dWMShop_c, Wait); CREATE_STATE(dWMShop_c, HideWait); void dWMShop_c::ShopModel_c::setupItem(float x, float y, ItemTypes type) { static const char* Produce[ITEM_TYPE_COUNT][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.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" } }; this->x = x; this->y = y; int id = (int)type; allocator.link(-1, GameHeaps[0], 0, 0x20); res.data = getResource(Produce[id][0], Produce[id][1]); nw4r::g3d::ResMdl mdlRes = res.GetResMdl(Produce[id][2]); model.setup(mdlRes, &allocator, ANM_VTX, 1, 0); SetupTextures_Item(&model, 1); nw4r::g3d::ResAnmChr anmChr = res.GetResAnmChr(Produce[id][3]); animation.setup(mdlRes, anmChr, &allocator, 0); playAnim(Produce[id][3], 1.0f); allocator.unlink(); } void dWMShop_c::ShopModel_c::setupLakitu(int id) { static const char* models[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" }; allocator.link(-1, GameHeaps[0], 0, 0x20); res.data = getResource("lakitu", models[id]); nw4r::g3d::ResMdl mdlRes = res.GetResMdl("lakitu"); model.setup(mdlRes, &allocator, ANM_VTX, 1, 0); SetupTextures_Item(&model, 1); nw4r::g3d::ResAnmChr anmChr = res.GetResAnmChr("idle"); animation.setup(mdlRes, anmChr, &allocator, 0); playAnim("idle", 1.0f); allocator.unlink(); } void dWMShop_c::ShopModel_c::playAnim(const char *name, float rate) { nw4r::g3d::ResAnmChr anmChr = res.GetResAnmChr(name); animation.bind(&model, anmChr, 1); model.bindAnim(&animation, 0.0f); animation.setUpdateRate(rate); } void dWMShop_c::ShopModel_c::execute() { model._vf1C(); } void dWMShop_c::ShopModel_c::draw() { mMtx mtx; Vec pos = {250.0f, 170.0f, 3000.0f}; Vec scale = {1.0f, 1.0f, 1.0f}; mtx.translation(pos.x, pos.y, pos.z); model.setDrawMatrix(mtx); model.setScale(&scale); model.calcWorld(false); model.scheduleForDrawing(); } 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() : state(this, &StateID_Hidden) { layoutLoaded = false; visible = false; } int dWMShop_c::onCreate() { if (!layoutLoaded) { bool gotFile = layout.loadArc("shop.arc", false); if (!gotFile) return false; selected = 0; lastTopRowChoice = 0; layout.build("shop.brlyt"); layout.layout.rootPane->trans.x = -112.0f; if (IsWideScreen()) { layout.layout.rootPane->scale.x = 0.735f; } else { 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; } static const char *brlanNames[] = { "shop_Show.brlan", "shop_Hide.brlan", "shop_ActivateButton.brlan", "shop_DeactivateButton.brlan" }; static const char *groupNames[] = { "BaseGroup", "BaseGroup", "GBtn00", "GBtn01", "GBtn02", "GBtn03", "GBtn1", "GBtn2", "GBtn00", "GBtn01", "GBtn02", "GBtn03", "GBtn1", "GBtn2", }; static const int brlanIDs[] = { 0, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, }; layout.loadAnimations(brlanNames, 4); layout.loadGroups(groupNames, brlanIDs, 14); layout.disableAllAnimations(); layout.drawOrder = 1; static const char *tbNames[] = { "Title", "TitleShadow", "CoinCount", "CoinCountShadow", "BackText", "BuyText", }; layout.getTextBoxes(tbNames, &Title, 6); layoutLoaded = true; } return true; } int dWMShop_c::onDelete() { deleteModels(); return layout.free(); } int dWMShop_c::onExecute() { state.execute(); if (visible) { layout.execAnimations(); layout.update(); lakituModel->execute(); for (int i = 0; i < 12; i++) itemModels[i].execute(); } layout.execAnimations(); layout.update(); return true; } int dWMShop_c::onDraw() { if (visible) layout.scheduleForDrawing(); return true; } void dWMShop_c::specialDraw1() { if (visible) { lakituModel->draw(); for (int i = 0; i < 12; i++) itemModels[i].draw(); // if (wasOff) { effect.spawn("Wm_ob_greencoinkira", 0, &pos, &rot, &scale); wasOff = false; } // if(this->ska.isAnimationDone()) // this->ska.setCurrentFrame(0.0); } } void dWMShop_c::show(int shopNumber) { shopKind = shopNumber; state.setState(&StateID_ShowWait); } // Hidden void dWMShop_c::beginState_Hidden() { } void dWMShop_c::executeState_Hidden() { } void dWMShop_c::endState_Hidden() { } // ShowWait void dWMShop_c::beginState_ShowWait() { MapSoundPlayer(SoundRelatedClass, SE_SYS_DIALOGUE_IN, 1); layout.disableAllAnimations(); layout.enableNonLoopAnim(SHOW_ALL); visible = true; loadModels(); } void dWMShop_c::executeState_ShowWait() { if (!layout.isAnimOn(SHOW_ALL)) { selected = 0; layout.enableNonLoopAnim(ACTIVATE_BUTTON); state.setState(&StateID_ButtonActivateWait); } } void dWMShop_c::endState_ShowWait() { } // ButtonActivateWait void dWMShop_c::beginState_ButtonActivateWait() { } void dWMShop_c::executeState_ButtonActivateWait() { if (!layout.isAnyAnimOn()) state.setState(&StateID_Wait); } void dWMShop_c::endState_ButtonActivateWait() { } // Wait void dWMShop_c::beginState_Wait() { } void dWMShop_c::executeState_Wait() { int nowPressed = Remocon_GetPressed(GetActiveRemocon()); int newSelection = -1; if (nowPressed & WPAD_ONE) { // Hide the thing state.setState(&StateID_HideWait); } else if (nowPressed & WPAD_UP) { // Move up if (selected == 4) newSelection = lastTopRowChoice; else if (selected == 5) newSelection = 4; } else if (nowPressed & WPAD_DOWN) { // Move down if (selected <= 3) newSelection = 4; else if (selected == 4) newSelection = 5; } else if (nowPressed & WPAD_LEFT) { // Just use the previous choice if (selected > 0) newSelection = selected - 1; } else if (nowPressed & WPAD_RIGHT) { // Just use the next choice if (selected < 5) newSelection = selected + 1; } else if (nowPressed & WPAD_TWO) { buyItem(selected); } if (newSelection > -1) { MapSoundPlayer(SoundRelatedClass, SE_SYS_CURSOR, 1); layout.enableNonLoopAnim(DEACTIVATE_BUTTON+selected); layout.enableNonLoopAnim(ACTIVATE_BUTTON+newSelection); selected = newSelection; if (newSelection <= 3) lastTopRowChoice = newSelection; } } void dWMShop_c::endState_Wait() { } // HideWait void dWMShop_c::beginState_HideWait() { MapSoundPlayer(SoundRelatedClass, SE_SYS_DIALOGUE_OUT_AUTO, 1); layout.enableNonLoopAnim(HIDE_ALL); } void dWMShop_c::executeState_HideWait() { if (!layout.isAnimOn(HIDE_ALL)) state.setState(&StateID_Hidden); } void dWMShop_c::endState_HideWait() { visible = false; } // 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 const dWMShop_c::ItemTypes dWMShop_c::Inventory[10][12] = { { // Yoshi's Island COINS, MUSHROOM, FIRE_FLOWER, PROPELLER, FIRE_FLOWER, ICE_FLOWER, FIRE_FLOWER, MUSHROOM, MUSHROOM, ONE_UP, PROPELLER, PROPELLER }, { // Desert COINS, MUSHROOM, FIRE_FLOWER, PROPELLER, FIRE_FLOWER, STARMAN, FIRE_FLOWER, MUSHROOM, FIRE_FLOWER, FIRE_FLOWER, PROPELLER, PROPELLER }, { // Mountain COINS, MUSHROOM, MINI_SHROOM, PROPELLER, MUSHROOM, MINI_SHROOM, PROPELLER, MUSHROOM, MINI_SHROOM, PROPELLER, PROPELLER, HAMMER }, { // Japan COINS, MUSHROOM, ONE_UP, HAMMER, ONE_UP, ONE_UP, ONE_UP, PROPELLER, ICE_FLOWER, ONE_UP, FIRE_FLOWER, PROPELLER }, { // FreezeFlame COINS, MUSHROOM, ICE_FLOWER, PENGUIN, ICE_FLOWER, PENGUIN, ICE_FLOWER, ICE_FLOWER, PENGUIN, PENGUIN, PENGUIN, ICE_FLOWER }, { // Ghost COINS, MUSHROOM, STARMAN, PROPELLER, MINI_SHROOM, PROPELLER, MINI_SHROOM, PROPELLER, PROPELLER, COINS, PROPELLER, PROPELLER }, { // Space COINS, MUSHROOM, STARMAN, HAMMER, STARMAN, STARMAN, STARMAN, HAMMER, HAMMER, ONE_UP, HAMMER, HAMMER }, { // Koopa MUSHROOM, ONE_UP, PROPELLER, HAMMER, HAMMER, PROPELLER, HAMMER, PROPELLER, HAMMER, PROPELLER, HAMMER, PROPELLER }, { // Unknown COINS, MUSHROOM, FIRE_FLOWER, PENGUIN, MUSHROOM, MUSHROOM, MUSHROOM, MUSHROOM, MUSHROOM, MUSHROOM, MUSHROOM, MUSHROOM }, { // Goldwood MUSHROOM, ONE_UP, FIRE_FLOWER, MINI_SHROOM, FIRE_FLOWER, PROPELLER, FIRE_FLOWER, FIRE_FLOWER, FIRE_FLOWER, STARMAN, FIRE_FLOWER, FIRE_FLOWER } }; void dWMShop_c::loadModels() { lakituModel = new ShopModel_c; lakituModel->setupLakitu(shopKind); itemModels = new ShopModel_c[ITEM_COUNT]; for (int i = 0; i < ITEM_COUNT; i++) itemModels[i].setupItem(0.0f, 0.0f, Inventory[shopKind][i]); } void dWMShop_c::deleteModels() { if (lakituModel) delete lakituModel; lakituModel = 0; if (itemModels) delete[] itemModels; itemModels = 0; } void dWMShop_c::buyItem(int item) { static int itemDefs[6][3] = { // Cost, Start Index, Count {1, 0, 1}, {1, 1, 1}, {2, 2, 1}, {3, 3, 1}, {5, 4, 3}, {8, 7, 5} }; int cost = itemDefs[item][0], cash = getStarCoinCount(); if (cost > cash) { lakituModel->playAnim("notenough", 1.0f); 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->spentStarCoins += cost; // Work out what we need to apply int appliedItems[ITEM_TYPE_COUNT]; for (int i = 0; i < ITEM_TYPE_COUNT; i++) appliedItems[i] = 0; int invStartIndex = itemDefs[item][1], invCount = itemDefs[item][2]; for (int i = 0; i < invCount; i++) appliedItems[(int)Inventory[shopKind][invStartIndex]]++; // TODO: Make this work with hammers for (int i = 0; i < 7; i++) { block->powerups_available[i] += appliedItems[i]; if (block->powerups_available[i] > 99) block->powerups_available[i] = 99; } // Apply coins and lives to everyone for (int i = 0; i < 4; i++) { block->player_coins[i] += (appliedItems[(int)COINS] * 50); while (block->player_coins[i] >= 100) { block->player_coins[i] -= 100; block->player_lives[i]++; } block->player_lives[i] += appliedItems[(int)ONE_UP]; if (block->player_lives[i] > 99) block->player_lives[i] = 99; } state.setState(&StateID_HideWait); }