summaryrefslogtreecommitdiff
path: root/src/koopatlas
diff options
context:
space:
mode:
Diffstat (limited to 'src/koopatlas')
-rw-r--r--src/koopatlas/core.cpp25
-rw-r--r--src/koopatlas/core.h6
-rw-r--r--src/koopatlas/map.cpp4
-rw-r--r--src/koopatlas/pathmanager.cpp8
-rw-r--r--src/koopatlas/shop.cpp507
-rw-r--r--src/koopatlas/shop.h62
6 files changed, 611 insertions, 1 deletions
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
+