/*
* Copyright (c) 2003-onwards Shaven Puppy Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'Shaven Puppy' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package worm.screens;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import net.puppygames.applet.Area;
import net.puppygames.applet.Game;
import net.puppygames.applet.MiniGame;
import net.puppygames.applet.Screen;
import net.puppygames.applet.screens.DialogScreen;
import worm.Res;
import worm.Worm;
import worm.WormGameState;
import worm.animation.SimpleThingWithLayers;
import worm.buildings.BuildingFeature;
import worm.features.LayersFeature;
import worm.features.ResearchFeature;
import worm.features.SettingFeature;
import com.shavenpuppy.jglib.Resources;
import com.shavenpuppy.jglib.resources.ColorMapFeature;
import com.shavenpuppy.jglib.sprites.Appearance;
import com.shavenpuppy.jglib.sprites.Sprite;
/**
* Choose from one of several items to research.
*/
public class ResearchScreen extends Screen {
private static final long serialVersionUID = 1L;
private static ResearchScreen instance;
// private static final String ID_CASH = "id_cash";
private static final String ID_BACK = "id_back";
private static final String ID_NEXT_LEVEL = "id_next_level";
private static final String BACKGROUND = "background";
private static final String DESCRIPTION = "description";
private static final String TITLE = "title";
private static final String COST = "cost";
private static final String STATS_COLUMN_1 = "stats_1";
private static final String STATS_COLUMN_2 = "stats_2";
private static final String INFO_SPRITE_LOCATION = "info_sprite_location";
private static final String RESEARCH = "research_table";
private static final String CANT_AFFORD = "_off";
private static final String ALREADY_HAVE = "_on";
private static final String GROUP_RESEARCH = "research";
private static final String GROUP_INFO = "info";
private static final String GROUP_ALL_RESEARCHED = "all_researched";
private static final String GROUP_REQUIRES = "requires";
private static final String REQUIRES_LABEL ="requires_label";
// private static final String GROUP_TABLE = "table";
// private static final String GROUP_TREE = "tree";
// private static final String ID_SWITCH_BUTTON = "id_switch_button";
// private static final String ID_SWITCH_LABEL_TREE = "id_switch_label_tree";
// private static final String ID_SWITCH_LABEL_TABLE = "id_switch_label_table";
private static final String ID_MENU = "menu";
private static final int ITEM_RESEARCHED = 0, ITEM_AVAILABLE = 1, ITEM_UNAVAILABLE = 2, ITEM_NOT_READY = 3;
private static Runnable backAction, forwardAction;
private transient SimpleThingWithLayers layers;
private transient boolean atLeastOneAvailable = false;
private transient ResearchFeature current;
/**
* @param name
*/
public ResearchScreen(String name) {
super(name);
}
public static void show(Runnable backAction, Runnable forwardAction) {
ResearchScreen.backAction = backAction;
ResearchScreen.forwardAction = forwardAction;
instance.open();
}
@Override
protected void doCleanup() {
ResearchScreen.backAction = null;
ResearchScreen.forwardAction = null;
removeSprites();
current = null;
}
private void removeSprites() {
if (layers != null) {
layers.remove();
layers = null;
}
}
@Override
protected void doRegister() {
assert instance == null;
instance = this;
}
@Override
protected void doDeregister() {
assert instance == this;
instance = null;
}
@Override
protected void doCreateScreen() {
}
@Override
protected void onClicked(String id) {
if (id.equals(ID_NEXT_LEVEL)) {
close();
forwardAction.run();
} else if (id.equals(ID_BACK)) {
close();
backAction.run();
} else if (id.startsWith(RESEARCH)) {
String researchID = id.split("_")[2];
final ResearchFeature rf = ResearchFeature.getResearch().get(researchID);
if (rf!=null && ( getItemState(rf)==ITEM_AVAILABLE || Game.DEBUG)) {
if (rf.isRegisteredOnly() && !Game.isRegistered()) {
// Show the BUY dialog
Res.getResearchNagDialog().doModal(Game.getMessage("ultraworm.researchscreen.nag_title"), Game.getMessage("ultraworm.researchscreen.nag_message"), new Runnable() {
@Override
public void run() {
if (Res.getResearchNagDialog().getOption() == DialogScreen.OK_OPTION) {
MiniGame.buy(true);
}
}
});
} else if (!Worm.getGameState().isResearched(current.getID())) {
// Story screen depending on building type and world
Worm.getGameState().setResearched(rf.getID());
getResearchRunnable(rf).run();
}
}
} else if (id.equals(ID_MENU)) {
MenuScreen.show(MenuScreen.MENU_STORY_MODE);
}
}
private Runnable getResearchRunnable(final ResearchFeature rf) {
return new Runnable() {
@Override
public void run() {
SettingFeature setting = Worm.getGameState().getWorld().getSetting(rf.getSetting());
rf.getStory().setSetting(setting);
StoryScreen.show("story.screen."+Worm.getGameState().getWorld().getUntranslated(), false, rf.getStory(), new Runnable() {
@Override
public void run() {
// Unresearch!
Worm.getGameState().setUnresearched(rf.getID());
Worm.getGameState().showResearchScreen();
}
}, forwardAction);
}
};
}
private void calcDepends(ResearchFeature rf, Set<ResearchFeature> required) {
if (rf == null || rf.getDepends() == null) {
return;
}
StringTokenizer st = new StringTokenizer(rf.getDepends(), ",", false);
while (st.hasMoreTokens()) {
String depends = st.nextToken();
ResearchFeature req = ResearchFeature.getResearch().get(depends);
if (req == null) {
throw new RuntimeException("There's no '"+depends+"' in research features!");
}
required.add(req);
calcDepends(req, required);
}
}
@Override
protected void onHover(String id, boolean on) {
if (id.startsWith(RESEARCH)) {
setGroupVisible(GROUP_ALL_RESEARCHED, false);
String researchID = id.split("_")[2];
boolean alreadyHave = researchID.endsWith("_"+ALREADY_HAVE);
if (alreadyHave) {
researchID = researchID.substring(0, researchID.length() - ALREADY_HAVE.length());
}
ResearchFeature hovered = ResearchFeature.getResearch().get(researchID);
if (on) {
if (hovered == null || hovered == current) {
return;
}
// Turn this lot off every time..
setGroupVisible(GROUP_REQUIRES, false);
current = hovered;
int thisItemState = getItemState(current);
String titleText;
if (thisItemState==ITEM_UNAVAILABLE) {
titleText = "{font:smallfont.glfont color:text}"+current.getTitle();
} else if (thisItemState==ITEM_NOT_READY){
titleText = "{font:smallfont.glfont color:text}COMING SOON!";
} else {
titleText = "{font:smallfont.glfont color:text-bold}"+current.getTitle();
}
getArea(TITLE).setText(titleText);
getArea(DESCRIPTION).setText("");
getArea(STATS_COLUMN_1).setText("");
getArea(STATS_COLUMN_2).setText("");
if (thisItemState!=ITEM_NOT_READY) {
if (thisItemState==ITEM_UNAVAILABLE) {
setVisible(REQUIRES_LABEL, true);
Set<ResearchFeature> required = new HashSet<ResearchFeature>();
if (hovered.getDepends() != null) {
if (hovered.getDepends().equals("cantResearchThisYet")) {
} else {
calcDepends(hovered, required);
List<ResearchFeature> sorted = new ArrayList<ResearchFeature>(required);
Collections.sort(sorted, new Comparator<ResearchFeature>() {
WormGameState gameState = Worm.getGameState();
@Override
public int compare(ResearchFeature o1, ResearchFeature o2) {
int is1 = getItemState(o1);
int is2 = getItemState(o2);
if (is1 < is2) {
return -1;
} else if (is1 > is2) {
return 1;
} else {
return o1.getID().compareToIgnoreCase(o2.getID());
}
}
});
int i = 0;
for (ResearchFeature rf : sorted) {
Area boxArea = getArea("requires_"+i+"_box");
String areaID = "requires_"+i;
getArea(areaID).setMouseOffAppearance(getArea(RESEARCH + "_" + rf.getID()).getMouseOffAppearance());
getArea(areaID + CANT_AFFORD).setMouseOffAppearance(getArea(RESEARCH + "_" + rf.getID() + CANT_AFFORD).getMouseOffAppearance());
getArea(areaID + ALREADY_HAVE).setMouseOffAppearance(getArea(RESEARCH + "_" + rf.getID() + ALREADY_HAVE).getMouseOffAppearance());
boxArea.setVisible(true);
boxArea.setEnabled(true);
switch (getItemState(rf)) {
case ITEM_RESEARCHED:
boxArea.setMouseOffAppearance((Appearance) Resources.get("research.button.researched.off.animation"));
setVisible(areaID + ALREADY_HAVE, true);
setVisible(areaID, false);
setVisible(areaID + CANT_AFFORD, false);
setEnabled(areaID + ALREADY_HAVE, true);
break;
case ITEM_AVAILABLE:
boxArea.setMouseOffAppearance((Appearance) Resources.get("research.button.on.off.animation"));
setVisible(areaID + ALREADY_HAVE, false);
setVisible(areaID, true);
setVisible(areaID + CANT_AFFORD, false);
setEnabled(areaID, true);
break;
default:
boxArea.setMouseOffAppearance((Appearance) Resources.get("research.button.off.off.animation"));
setVisible(areaID + ALREADY_HAVE, false);
setVisible(areaID, false);
setVisible(areaID + CANT_AFFORD, true);
setEnabled(areaID + CANT_AFFORD, true);
break;
}
i ++;
}
}
}
} else {
if (!current.getSetting().equals("tech") && thisItemState==ITEM_RESEARCHED) {
BuildingFeature thisBuilding = BuildingFeature.getBuildingByResearchName(current.getID());
String descText = thisBuilding.getDescription();
StringBuilder stats_1_text = new StringBuilder();
StringBuilder stats_2_text = new StringBuilder();
thisBuilding.getResearchStats(stats_1_text, stats_2_text);
getArea(DESCRIPTION).setText("{font:tinyfont.glfont color:text}"+descText);
getArea(STATS_COLUMN_1).setText(stats_1_text.toString());
getArea(STATS_COLUMN_2).setText(stats_2_text.toString());
} else {
getArea(DESCRIPTION).setText("{font:tinyfont.glfont color:text}"+current.getDescription());
}
}
}
if (thisItemState==ITEM_RESEARCHED) {
getArea(COST).setText("{font:tinyfont.glfont color:text-bold}"+Game.getMessage("ultraworm.researchscreen.already_researched"));
} else {
getArea(COST).setText("");
}
setGroupVisible(GROUP_INFO, true);
removeSprites();
LayersFeature l = current.getAppearance();
if (l != null) {
Area spriteArea = getArea(INFO_SPRITE_LOCATION);
int spriteX = spriteArea.getBounds().getX();
int spriteY = spriteArea.getBounds().getY();
layers = new SimpleThingWithLayers(this);
l.createSprites(this, layers);
Sprite[] sprite = layers.getSprites();
for (Sprite element : sprite) {
element.setLocation(spriteX, spriteY);
}
}
// if (researched) {
Worm.setMouseAppearance(Res.getMousePointer());
// } else {
// Worm.setMouseAppearance(Res.getMousePointerCantBuild());
// }
} else {
if (hovered == current) {
removeSprites();
setGroupVisible(GROUP_INFO, false);
current = null;
Worm.setMouseAppearance(Res.getMousePointer());
// Turn this lot off every time..
setGroupVisible(GROUP_REQUIRES, false);
}
}
}
}
@Override
protected void onOpen() {
removeSprites();
WormGameState gameState = Worm.getGameState();
String world = gameState.getWorld().getUntranslated();
getArea(BACKGROUND).setMouseOffAppearance((Appearance) Resources.get(world+".research.background.anim"));
current = null;
Worm.setMouseAppearance(Res.getMousePointer());
ColorMapFeature.getDefaultColorMap().copy((ColorMapFeature) Resources.get(world+".colormap"));
if (gameState.getLevel() == 1) {
Res.getIngameInfoDialog().doModal(Game.getMessage("ultraworm.researchscreen.hint_title"), Game.getMessage("ultraworm.researchscreen.hint_message"), null);
}
setGroupEnabled(GROUP_RESEARCH, false);
setGroupVisible(GROUP_RESEARCH, true);
setGroupVisible(GROUP_INFO, false);
setGroupVisible(GROUP_REQUIRES, false);
initButtons();
setGroupVisible(GROUP_ALL_RESEARCHED, !atLeastOneAvailable);
getArea(ID_NEXT_LEVEL).setVisible(forwardAction != null && !atLeastOneAvailable);
getArea(ID_BACK).setVisible(backAction != null);
}
protected void initButtons() {
Map<String, ResearchFeature> allResearch = ResearchFeature.getResearch();
atLeastOneAvailable = false;
for (ResearchFeature rf : allResearch.values()) {
// check state...
int thisItemState = getItemState(rf);
Area boxArea;
String areaID, boxAreaID;
areaID = RESEARCH + "_" + rf.getID();
boxAreaID = areaID + "_box";
boxArea = getArea(boxAreaID);
if (boxArea == null) {
continue;
}
boxArea.setEnabled(true);
// set appearances
switch (thisItemState) {
case ITEM_RESEARCHED:
boxArea.setMouseOffAppearance((Appearance) Resources.get("research.button.researched.off.animation"));
boxArea.setMouseOnAppearance((Appearance) Resources.get("research.button.researched.on.animation"));
setVisible(areaID + ALREADY_HAVE, true);
setVisible(areaID, false);
setVisible(areaID + CANT_AFFORD, false);
setEnabled(areaID + ALREADY_HAVE, true);
break;
case ITEM_AVAILABLE:
atLeastOneAvailable = true;
boxArea.setMouseOffAppearance((Appearance) Resources.get("research.button.on.off.animation"));
boxArea.setMouseOnAppearance((Appearance) Resources.get("research.button.on.on.animation"));
setVisible(areaID + ALREADY_HAVE, false);
setVisible(areaID, true);
setVisible(areaID + CANT_AFFORD, false);
setEnabled(areaID, true);
break;
default:
boxArea.setMouseOffAppearance((Appearance) Resources.get("research.button.off.off.animation"));
boxArea.setMouseOnAppearance((Appearance) Resources.get("research.button.off.on.animation"));
setVisible(areaID + ALREADY_HAVE, false);
setVisible(areaID, false);
setVisible(areaID + CANT_AFFORD, true);
setEnabled(areaID, false);
setEnabled(areaID + CANT_AFFORD, true);
break;
}
boxArea.update();
}
}
protected int getItemState(ResearchFeature rf) {
WormGameState gameState = Worm.getGameState();
int thisItemState = ITEM_RESEARCHED;
if (!rf.isDefaultAvailable() && !gameState.isResearched(rf.getID())) {
thisItemState = ITEM_AVAILABLE;
}
if (rf.getDepends() != null) {
if (rf.getDepends().equals("cantResearchThisYet")) {
thisItemState = ITEM_NOT_READY;
} else {
StringTokenizer st = new StringTokenizer(rf.getDepends(), ",", false);
while (st.hasMoreTokens()) {
String depends = st.nextToken();
if (!gameState.isResearched(depends)) {
thisItemState = ITEM_UNAVAILABLE;
break;
}
}
}
}
return thisItemState;
}
}