package com.unlucky.screen; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.Group; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.Touchable; import com.badlogic.gdx.scenes.scene2d.ui.*; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Array; import com.unlucky.battle.SpecialMove; import com.unlucky.battle.SpecialMoveset; import com.unlucky.entity.Player; import com.unlucky.main.Unlucky; import com.unlucky.resource.ResourceManager; import com.unlucky.resource.Util; import com.unlucky.ui.smove.SMoveTooltip; /** * Screen for managing the player's special moveset * The player can drag and drop unlocked special moves onto their moveset * * @author Ming Li */ public class SpecialMoveScreen extends MenuExtensionScreen { private Player player; // screen banner private Image banner; private Label bannerLabel; // bg layer private Image bg; // ui private Label.LabelStyle white; private Label.LabelStyle red; private Label.LabelStyle green; private Label.LabelStyle headerStyle; private Label turnPrompt; // the smove slots to be arranged in a pentagon private Image[] slots; private Array<Image> garbage; private SMoveTooltip tooltip; private Image selectedSlot; // 0 - add button, 1 - remove button private ImageButton[] smoveButtons; private Label[] smoveButtonLabels; // 0 - enabled, 1 - disabled private ImageButton.ImageButtonStyle[] addButtonStyle; private ImageButton.ImageButtonStyle[] removeButtonStyle; private SpecialMove smoveToAdd = null; private int smoveToRemove = -1; private Label smoveset; // scroll pane private Table scrollTable; private Table selectionContainer; private ScrollPane scrollPane; // dialogs private Dialog warningFullDialog; public SpecialMoveScreen(final Unlucky game, final ResourceManager rm) { super(game, rm); this.player = game.player; garbage = new Array<Image>(); white = new Label.LabelStyle(rm.pixel10, Color.WHITE); red = new Label.LabelStyle(rm.pixel10, Color.RED); green = new Label.LabelStyle(rm.pixel10, new Color(0, 225 / 255.f, 0, 1)); headerStyle = new Label.LabelStyle(rm.pixel10, new Color(1, 150 / 255.f, 66 / 255.f, 1)); // create banner banner = new Image(rm.skin, "default-slider"); banner.setPosition(8, 102); banner.setSize(164, 12); stage.addActor(banner); bannerLabel = new Label("MANAGE SPECIAL MOVES", rm.skin); bannerLabel.setStyle(headerStyle); bannerLabel.setSize(50, 12); bannerLabel.setTouchable(Touchable.disabled); bannerLabel.setPosition(14, 102); bannerLabel.setAlignment(Align.left); stage.addActor(bannerLabel); stage.addActor(exitButton); exitButton.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { unselectSlot(); if (!game.player.settings.muteSfx) rm.buttonclick0.play(game.player.settings.sfxVolume); smoveButtons[0].setStyle(addButtonStyle[1]); smoveButtons[0].setTouchable(Touchable.disabled); smoveButtons[1].setStyle(removeButtonStyle[1]); smoveButtons[1].setTouchable(Touchable.disabled); smoveToRemove = -1; smoveToAdd = null; game.menuScreen.transitionIn = 1; setSlideScreen(game.menuScreen, true); } }); // create bg bg = new Image(rm.skin, "default-slider"); bg.setPosition(8, 6); bg.setSize(184, 92); bg.setTouchable(Touchable.enabled); stage.addActor(bg); turnPrompt = new Label("", white); turnPrompt.setFontScale(0.5f); turnPrompt.setPosition(12, 92); turnPrompt.setTouchable(Touchable.disabled); stage.addActor(turnPrompt); // create slots slots = new Image[SpecialMoveset.MAX_MOVES]; for (int i = 0; i < slots.length; i++) { slots[i] = new Image(rm.smoveSlots[0]); Vector2 pos = getSlotPositions(i); slots[i].setPosition(pos.x, pos.y); stage.addActor(slots[i]); } scrollTable = new Table(); tooltip = new SMoveTooltip(rm.skin, headerStyle); stage.addActor(tooltip); selectedSlot = new Image(rm.smoveSlots[1]); selectedSlot.setVisible(false); stage.addActor(selectedSlot); bg.addListener(new ClickListener() { public void clicked(InputEvent event, float x, float y) { unselectSlot(); smoveButtons[1].setStyle(removeButtonStyle[1]); smoveButtons[1].setTouchable(Touchable.disabled); smoveToRemove = -1; } }); smoveset = new Label("Special\nMoveset", headerStyle); smoveset.setFontScale(0.5f); smoveset.setPosition(130, 40); smoveset.setAlignment(Align.center); smoveset.setTouchable(Touchable.disabled); stage.addActor(smoveset); createSmoveButtons(); warningFullDialog = new Dialog("Warning", rm.dialogSkin) { { Label l = new Label("Your special moveset is full.", rm.dialogSkin); l.setFontScale(0.5f); l.setAlignment(Align.center); text(l); getButtonTable().defaults().width(40); getButtonTable().defaults().height(15); button("OK", "ok"); } @Override protected void result(Object object) { if (!game.player.settings.muteSfx) rm.buttonclick2.play(game.player.settings.sfxVolume); } }; warningFullDialog.getTitleLabel().setAlignment(Align.center); } @Override public void show() { game.fps.setPosition(2, 2); stage.addActor(game.fps); super.showSlide(false); scrollTable.remove(); createScrollPane(); smoveButtons[0].toFront(); smoveButtons[1].toFront(); smoveButtonLabels[0].toFront(); smoveButtonLabels[1].toFront(); addSmoveActors(); // update turn cd turnPrompt.setText("Special moves can be used in battle every " + player.smoveCd + " turns."); } /** * Creates the two add and remove smove buttons */ private void createSmoveButtons() { smoveButtons = new ImageButton[2]; smoveButtonLabels = new Label[2]; addButtonStyle = new ImageButton.ImageButtonStyle[2]; removeButtonStyle = new ImageButton.ImageButtonStyle[2]; String[] str = new String[] { "ADD", "REMOVE" }; for (int i = 0; i < 2; i++) { addButtonStyle[i] = new ImageButton.ImageButtonStyle(); removeButtonStyle[i] = new ImageButton.ImageButtonStyle(); smoveButtonLabels[i] = new Label(str[i], white); smoveButtonLabels[i].setFontScale(0.5f); smoveButtonLabels[i].setSize(38, 18); smoveButtonLabels[i].setAlignment(Align.center); smoveButtonLabels[i].setTouchable(Touchable.disabled); } // enabled add addButtonStyle[0].imageUp = new TextureRegionDrawable(rm.smoveButtons[0][0]); addButtonStyle[0].imageDown = new TextureRegionDrawable(rm.smoveButtons[1][0]); // disabled add addButtonStyle[1].imageUp = new TextureRegionDrawable(rm.smoveButtons[2][0]); // enabled remove removeButtonStyle[0].imageUp = new TextureRegionDrawable(rm.smoveButtons[0][1]); removeButtonStyle[0].imageDown = new TextureRegionDrawable(rm.smoveButtons[1][1]); // disabled remove removeButtonStyle[1].imageUp = new TextureRegionDrawable(rm.smoveButtons[2][1]); smoveButtons[0] = new ImageButton(addButtonStyle[1]); smoveButtons[1] = new ImageButton(removeButtonStyle[1]); smoveButtons[0].setPosition(96, 64); smoveButtons[1].setPosition(96, 14); smoveButtons[0].setTouchable(Touchable.disabled); smoveButtons[1].setTouchable(Touchable.disabled); smoveButtonLabels[0].setPosition(94, 64); smoveButtonLabels[1].setPosition(98, 14); stage.addActor(smoveButtons[0]); stage.addActor(smoveButtons[1]); stage.addActor(smoveButtonLabels[0]); stage.addActor(smoveButtonLabels[1]); // add button smoveButtons[0].addListener(new ClickListener() { public void clicked(InputEvent event, float x, float y) { if (!game.player.settings.muteSfx) rm.buttonclick1.play(game.player.settings.sfxVolume); unselectSlot(); add(); } }); // remove button smoveButtons[1].addListener(new ClickListener() { public void clicked(InputEvent event, float x, float y) { if (!game.player.settings.muteSfx) rm.buttonclick1.play(game.player.settings.sfxVolume); if (smoveToRemove != -1) { unselectSlot(); smoveButtons[1].setStyle(removeButtonStyle[1]); smoveButtons[1].setTouchable(Touchable.disabled); player.smoveset.remove(smoveToRemove); addSmoveActors(); game.save.save(); } } }); } /** * Adds an smove from the selection to the player's smoveset */ private void add() { if (player.smoveset.isFull()) { warningFullDialog.show(stage); return; } if (smoveToAdd != null) { // already two of a kind in the set if (!player.smoveset.canAdd(smoveToAdd.id)) { new Dialog("Warning", rm.dialogSkin) { { Label l = new Label("Cannot have more than\n2 of " + smoveToAdd.name + ".", rm.dialogSkin); l.setFontScale(0.5f); l.setAlignment(Align.center); text(l); getButtonTable().defaults().width(40); getButtonTable().defaults().height(15); button("OK", "ok"); } @Override protected void result(Object object) { if (!game.player.settings.muteSfx) rm.buttonclick2.play(game.player.settings.sfxVolume); } }.show(stage).getTitleLabel().setAlignment(Align.center); return; } // add smove player.smoveset.addSMove(smoveToAdd.id); addSmoveActors(); game.save.save(); } } /** * Adds the icons of the currently equipped smoves */ private void addSmoveActors() { // clear garbage and remove from stage for (Image i : garbage) i.remove(); garbage.clear(); Array<SpecialMove> set = player.smoveset.smoveset; for (int i = 0; i < set.size; i++) { Image icon = new Image(set.get(i).icon.getDrawable()); garbage.add(icon); Vector2 pos = getSlotPositions(i); icon.setPosition(pos.x + 1, pos.y + 1); addSmoveEvent(icon, i, set.get(i)); stage.addActor(icon); } } /** * Returns the positions of the slot at a given smove index * * @param index * @return */ private Vector2 getSlotPositions(int index) { // middle left if (index == 0) return new Vector2(116, 40); // top if (index == 1) return new Vector2(138, 69); // top right if (index == 2) return new Vector2(170, 56); // bottom right if (index == 3) return new Vector2(170, 24); // bottom left else return new Vector2(138, 10); } /** * Shows the smove tooltip and enables the remove button * @param icon * @param index */ private void addSmoveEvent(final Image icon, final int index, final SpecialMove smove) { final Vector2 pos = getSlotPositions(index); icon.addListener(new ClickListener() { public void clicked(InputEvent event, float x, float y) { // unselect slots if (selectedSlot.isVisible()) { selectedSlot.setVisible(false); tooltip.setVisible(false); smoveButtons[1].setStyle(removeButtonStyle[1]); smoveButtons[1].setTouchable(Touchable.disabled); smoveToRemove = -1; } else { if (!game.player.settings.muteSfx) rm.invselectclick.play(game.player.settings.sfxVolume); // show selected slot selectedSlot.setPosition(pos.x, pos.y); selectedSlot.setVisible(true); // show tooltip Vector2 t = getTooltipCoords(pos, index); tooltip.show(smove, t.x, t.y); tooltip.toFront(); // enable remove button smoveButtons[1].setStyle(removeButtonStyle[0]); smoveButtons[1].setTouchable(Touchable.enabled); smoveToRemove = index; } } }); } private Vector2 getTooltipCoords(Vector2 pos, int index) { Vector2 ret = new Vector2(); if (index == 0) ret.set(pos.x + 16, pos.y - tooltip.getHeight() / 4); if (index == 1 || index == 2) ret.set(pos.x + 10, pos.y - tooltip.getHeight()); if (index == 3 || index == 4) ret.set(pos.x - 4, pos.y + tooltip.getHeight() / 2 + 2); return ret; } private void unselectSlot() { // unselect slots if (selectedSlot.isVisible()) { selectedSlot.setVisible(false); tooltip.setVisible(false); } } /** * Creates the scroll pane displaying all the special moves, icons and descs */ private void createScrollPane() { scrollTable = new Table(); scrollTable.setFillParent(true); stage.addActor(scrollTable); selectionContainer = new Table(); ButtonGroup bg = new ButtonGroup(); bg.setMaxCheckCount(1); bg.setMinCheckCount(0); for (int i = 0; i < Util.SMOVES_ORDER_BY_LVL.length; i++) { SpecialMove smove = Util.SMOVES_ORDER_BY_LVL[i]; Group smoveGroup = new Group(); smoveGroup.setSize(80, 30); smoveGroup.setTransform(false); Image frame = new Image(rm.smoveFrame); frame.setPosition(3, 7); frame.setTouchable(Touchable.disabled); Image icon = new Image(smove.icon.getDrawable()); icon.setPosition(4, 8); icon.setTouchable(Touchable.disabled); Label name = new Label(smove.name, headerStyle); name.setFontScale(0.5f); name.setPosition(20, 20); name.setTouchable(Touchable.disabled); Label desc = new Label(smove.desc, white); desc.setFontScale(0.5f); desc.setPosition(20, 6); desc.setTouchable(Touchable.disabled); Label status; // green label if unlocked if (player.getLevel() >= smove.levelUnlocked) status = new Label("UNLOCKED", green); // red label with level to unlock else status = new Label("UNLOCKED AT LV." + smove.levelUnlocked, red); status.setFontScale(0.5f); status.setPosition(20, 3); status.setTouchable(Touchable.disabled); final TextButton button = new TextButton("", rm.skin); button.setFillParent(true); button.setTouchable(player.getLevel() >= smove.levelUnlocked ? Touchable.enabled : Touchable.disabled); bg.add(button); addScrollPaneEvents(button, smove); smoveGroup.addActor(button); smoveGroup.addActor(frame); smoveGroup.addActor(icon); smoveGroup.addActor(name); smoveGroup.addActor(desc); smoveGroup.addActor(status); selectionContainer.add(smoveGroup).padBottom(2).size(80, 30).row(); } selectionContainer.pack(); selectionContainer.setTransform(false); selectionContainer.setOrigin(selectionContainer.getWidth() / 2, selectionContainer.getHeight() / 2); scrollPane = new ScrollPane(selectionContainer, rm.skin); scrollPane.setScrollingDisabled(true, false); scrollPane.setFadeScrollBars(true); // remove scroll bar scrollPane.setupFadeScrollBars(0, 0); scrollPane.layout(); scrollTable.add(scrollPane).size(120, 80).fill(); scrollTable.setPosition(-48, -12); } /** * Handles button checked events for the smove scroll pane * @param button * @param smove */ private void addScrollPaneEvents(final TextButton button, final SpecialMove smove) { button.addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { unselectSlot(); smoveButtons[1].setStyle(removeButtonStyle[1]); smoveButtons[1].setTouchable(Touchable.disabled); if (button.isChecked()) { if (!game.player.settings.muteSfx) rm.invselectclick.play(game.player.settings.sfxVolume); smoveToAdd = smove; smoveButtons[0].setStyle(addButtonStyle[0]); smoveButtons[0].setTouchable(Touchable.enabled); } else { smoveToAdd = null; smoveButtons[0].setStyle(addButtonStyle[1]); smoveButtons[0].setTouchable(Touchable.disabled); } } }); } }