diff --git a/core/src/main/assets/messages/scenes/scenes.properties b/core/src/main/assets/messages/scenes/scenes.properties index 0fbcda433..267d80325 100644 --- a/core/src/main/assets/messages/scenes/scenes.properties +++ b/core/src/main/assets/messages/scenes/scenes.properties @@ -48,6 +48,12 @@ scenes.gamescene.pick_up=Pick Up scenes.gamescene.purchase=Purchase scenes.gamescene.trample=Trample scenes.gamescene.examine=Examine +scenes.gamescene.tutorial_move_mobile=Tap a location to to move and interact. +scenes.gamescene.tutorial_move_desktop=Use the mouse or arrow keys to move and interact. +scenes.gamescene.tutorial_move_controller=Select a location or use the left stick to move or interact. +scenes.gamescene.tutorial_guidebook=Select the blinking journal button to read the book you just picked up. +scenes.gamescene.tutorial_ui_mobile=Hero info is on the top left, and your inventory and game actions are below, good luck! +scenes.gamescene.tutorial_ui_desktop=Hero info is below, and your inventory and game actions are to the right, good luck! scenes.heroselectscene.title=Choose Your Hero scenes.heroselectscene.options=Game Options diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java index 199ff44f5..a99744f58 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/hero/Hero.java @@ -2020,6 +2020,11 @@ public class Hero extends Char { } else { chance = 0.2f - (Dungeon.depth / 100f); } + + //don't want to let the player search though hidden doors in tutorial + if (SPDSettings.intro()){ + chance = 0; + } if (Random.Float() < chance) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/journal/Guidebook.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/journal/Guidebook.java index 05e48ed5e..728a1a270 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/journal/Guidebook.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/journal/Guidebook.java @@ -27,11 +27,8 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.journal.Document; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; -import com.shatteredpixel.shatteredpixeldungeon.windows.WndJournal; -import com.shatteredpixel.shatteredpixeldungeon.windows.WndStory; -import com.watabou.noosa.Game; +import com.shatteredpixel.shatteredpixeldungeon.ui.GameLog; import com.watabou.noosa.audio.Sample; -import com.watabou.utils.Callback; public class Guidebook extends Item { @@ -42,35 +39,10 @@ public class Guidebook extends Item { @Override public final boolean doPickUp(Hero hero, int pos) { GameScene.pickUpJournal(this, pos); - String page = Document.GUIDE_INTRO; - Game.runOnRenderThread(new Callback() { - @Override - public void call() { - GameScene.show(new WndStory(Document.ADVENTURERS_GUIDE.pageSprite(page), - Document.ADVENTURERS_GUIDE.pageTitle(page), - Document.ADVENTURERS_GUIDE.pageBody(page)){ - - float elapsed = 0; - - @Override - public void update() { - elapsed += Game.elapsed; - super.update(); - } - - @Override - public void hide() { - //prevents accidentally closing - if (elapsed >= 1) { - super.hide(); - } - } - }); - } - }); - Document.ADVENTURERS_GUIDE.readPage(Document.GUIDE_INTRO); + GameScene.flashForDocument(Document.ADVENTURERS_GUIDE, Document.GUIDE_INTRO); Sample.INSTANCE.play( Assets.Sounds.ITEM ); hero.spendAndNext( TIME_TO_PICK_UP ); + GameLog.wipe(); return true; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/RegularPainter.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/RegularPainter.java index 741649340..4d0769a7b 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/RegularPainter.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/RegularPainter.java @@ -22,6 +22,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.painters; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.SPDSettings; import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon; import com.shatteredpixel.shatteredpixeldungeon.journal.Document; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; @@ -247,11 +248,13 @@ public abstract class RegularPainter extends Painter { d.type = Room.Door.Type.UNLOCKED; } + //entrance doors on floor 1 are hidden during tutorial //entrance doors on floor 2 are hidden if the player hasn't picked up 2nd guidebook page - if (Dungeon.depth == 2 - && !Document.ADVENTURERS_GUIDE.isPageFound(Document.GUIDE_SEARCHING) - && r instanceof EntranceRoom){ - d.type = Room.Door.Type.HIDDEN; + if (r instanceof EntranceRoom || n instanceof EntranceRoom){ + if ((Dungeon.depth == 1 && SPDSettings.intro()) + || (Dungeon.depth == 2 && !Document.ADVENTURERS_GUIDE.isPageFound(Document.GUIDE_SEARCHING))) { + d.type = Room.Door.Type.HIDDEN; + } } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/EntranceRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/EntranceRoom.java index 061841cbc..596b4aded 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/EntranceRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/EntranceRoom.java @@ -22,6 +22,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.SPDSettings; import com.shatteredpixel.shatteredpixeldungeon.items.journal.GuidePage; import com.shatteredpixel.shatteredpixeldungeon.items.journal.Guidebook; import com.shatteredpixel.shatteredpixeldungeon.journal.Document; @@ -50,7 +51,16 @@ public class EntranceRoom extends StandardRoom { return false; } - public void paint( Level level ) { + @Override + public boolean canPlaceTrap(Point p) { + if (Dungeon.depth == 1) { + return false; + } else { + return super.canPlaceTrap(p); + } + } + + public void paint(Level level ) { Painter.fill( level, this, Terrain.WALL ); Painter.fill( level, this, 1, Terrain.EMPTY ); @@ -75,7 +85,8 @@ public class EntranceRoom extends StandardRoom { Random.pushGenerator(); //places the first guidebook page on floor 1 - if (Dungeon.depth == 1 && !Document.ADVENTURERS_GUIDE.isPageRead(Document.GUIDE_INTRO)){ + if (Dungeon.depth == 1 && + (!Document.ADVENTURERS_GUIDE.isPageRead(Document.GUIDE_INTRO) || SPDSettings.intro() )){ int pos; do { //can't be on bottom row of tiles diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java index ff7f44ac3..3c726b7c5 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java @@ -60,6 +60,7 @@ import com.shatteredpixel.shatteredpixeldungeon.journal.Document; import com.shatteredpixel.shatteredpixeldungeon.journal.Journal; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.RegularLevel; +import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.secret.SecretRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap; @@ -114,6 +115,7 @@ import com.shatteredpixel.shatteredpixeldungeon.windows.WndOptions; import com.shatteredpixel.shatteredpixeldungeon.windows.WndResurrect; import com.shatteredpixel.shatteredpixeldungeon.windows.WndStory; import com.watabou.glwrap.Blending; +import com.watabou.input.ControllerHandler; import com.watabou.input.PointerEvent; import com.watabou.noosa.Camera; import com.watabou.noosa.Game; @@ -127,6 +129,7 @@ import com.watabou.noosa.Visual; import com.watabou.noosa.audio.Music; import com.watabou.noosa.audio.Sample; import com.watabou.noosa.particles.Emitter; +import com.watabou.utils.Callback; import com.watabou.utils.DeviceCompat; import com.watabou.utils.GameMath; import com.watabou.utils.Point; @@ -479,6 +482,21 @@ public class GameScene extends PixelScene { && (InterlevelScene.mode == InterlevelScene.Mode.DESCEND || InterlevelScene.mode == InterlevelScene.Mode.FALL)) { GLog.h(Messages.get(this, "descend"), Dungeon.depth); Sample.INSTANCE.play(Assets.Sounds.DESCEND); + + //Tutorial + if (SPDSettings.intro()){ + + if (ControllerHandler.isControllerConnected()){ + GLog.p(Messages.get(GameScene.class, "tutorial_move_controller")); + } else if (SPDSettings.interfaceSize() == 0){ + GLog.p(Messages.get(GameScene.class, "tutorial_move_mobile")); + } else { + GLog.p(Messages.get(GameScene.class, "tutorial_move_desktop")); + } + toolbar.visible = false; + status.visible = false; + if (inventory != null) inventory.visible = false; + } for (Char ch : Actor.chars()){ if (ch instanceof DriedRose.GhostHero){ @@ -771,15 +789,19 @@ public class GameScene extends PixelScene { float tagWidth = Tag.SIZE + (tagsOnLeft ? insets.left : insets.right); float tagLeft = tagsOnLeft ? 0 : uiCamera.width - tagWidth; - float invWidth = (scene.inventory != null && scene.inventory.visible) ? scene.inventory.width() : 0; - float y = SPDSettings.interfaceSize() == 0 ? scene.toolbar.top()-2 : scene.status.top()-2; - if (tagsOnLeft) { - scene.log.setRect(tagWidth, y, uiCamera.width - tagWidth - insets.right - invWidth, 0); - } else if (invWidth > 0) { - scene.log.setRect(insets.left, y, uiCamera.width - invWidth, 0); + if (SPDSettings.interfaceSize() == 0){ + if (tagsOnLeft) { + scene.log.setRect(tagWidth, y, uiCamera.width - tagWidth - insets.right, 0); + } else { + scene.log.setRect(insets.left, y, uiCamera.width - tagWidth - insets.left, 0); + } } else { - scene.log.setRect(insets.left, y, uiCamera.width - tagWidth - insets.left, 0); + if (tagsOnLeft) { + scene.log.setRect(tagWidth, y, 160 - tagWidth, 0); + } else { + scene.log.setRect(insets.left, y, 160 - insets.left, 0); + } } float pos = scene.toolbar.top(); @@ -1021,9 +1043,42 @@ public class GameScene extends PixelScene { if (scene != null) scene.menu.pickup( item, pos ); } - //TODO currently only works with guidebooks public static void flashForDocument( Document doc, String page ){ - if (scene != null) scene.menu.flashForPage( doc, page ); + if (scene != null) { + scene.menu.flashForPage( doc, page ); + //we use a callback here so that regular pickup text appears first + if (SPDSettings.intro()) { + Game.runOnRenderThread(new Callback() { + @Override + public void call() { + GLog.p(Messages.get(GameScene.class, "tutorial_guidebook")); + } + }); + } + } + } + + public static void endIntro(){ + if (scene != null){ + SPDSettings.intro(false); + //TODO this is very sudden, should have UI and doors fade in + scene.status.visible = true; + scene.toolbar.visible = true; + if (scene.inventory != null) scene.inventory.visible = true; + GameLog.wipe(); + if (SPDSettings.interfaceSize() == 0){ + GLog.p(Messages.get(GameScene.class, "tutorial_ui_mobile")); + } else { + GLog.p(Messages.get(GameScene.class, "tutorial_ui_desktop")); + } + + //clear hidden doors, it's floor 1 so there are only the entrance ones + for (int i = 0; i < Dungeon.level.length(); i++){ + if (Dungeon.level.map[i] == Terrain.SECRET_DOOR){ + Dungeon.level.discover(i); + } + } + } } public static void updateKeyDisplay(){ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/WelcomeScene.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/WelcomeScene.java index ddd686154..4183415c3 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/WelcomeScene.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/WelcomeScene.java @@ -86,6 +86,11 @@ public class WelcomeScene extends PixelScene { if (ShatteredPixelDungeon.versionCode == previousVersion && !SPDSettings.intro()) { ShatteredPixelDungeon.switchNoFade(TitleScene.class); return; + } else { + //TODO temporary so alpha/beta players can test the tutorial + if (previousVersion <= 651){ + SPDSettings.intro(true); + } } Music.INSTANCE.playTracks( @@ -181,7 +186,6 @@ public class WelcomeScene extends PixelScene { String message; if (previousVersion == 0 || SPDSettings.intro()) { message = Document.INTROS.pageBody(0); - Document.INTROS.readPage(0); } else if (previousVersion <= ShatteredPixelDungeon.versionCode) { if (previousVersion < LATEST_UPDATE){ message = Messages.get(this, "update_intro"); @@ -198,6 +202,7 @@ public class WelcomeScene extends PixelScene { } else { message = Messages.get(this, "what_msg"); } + Document.INTROS.readPage(0); message = "Greetings Alpha Testers!\n\nAll of the gameplay changes for v1.4.0 are in place, but there's still a bit of UI/UX work and lore to finish up.\n\nKeep in mind that this is an early release, so bugs are to be expected. Please let me know if you encounter any!"; @@ -206,7 +211,7 @@ public class WelcomeScene extends PixelScene { text.setPos((w - text.width()) / 2f, (topRegion + 2) + (textSpace - text.height())/2); add(text); - if (previousVersion == 0 && ControllerHandler.isControllerConnected()){ + if (SPDSettings.intro() && ControllerHandler.isControllerConnected()){ addToFront(new WndHardNotification(Icons.CONTROLLER.get(), Messages.get(WelcomeScene.class, "controller_title"), Messages.get(WelcomeScene.class, "controller_body"), diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/MenuPane.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/MenuPane.java index 50a1d5814..5f7d1dd58 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/MenuPane.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ui/MenuPane.java @@ -316,7 +316,15 @@ public class MenuPane extends Component { } else if (flashingDoc.pageNames().contains(flashingPage)){ GameScene.show( new WndStory( flashingDoc.pageSprite(flashingPage), flashingDoc.pageTitle(flashingPage), - flashingDoc.pageBody(flashingPage) )); + flashingDoc.pageBody(flashingPage) ){ + @Override + public void hide() { + super.hide(); + if (SPDSettings.intro()){ + GameScene.endIntro(); + } + } + }); flashingDoc.readPage(flashingPage); } else { GameScene.show( new WndJournal() );