package com.iambookmaster.client.player; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.VerticalPanel; import com.iambookmaster.client.beans.Alchemy; import com.iambookmaster.client.beans.Battle; import com.iambookmaster.client.beans.ParagraphConnection; import com.iambookmaster.client.beans.Parameter; import com.iambookmaster.client.common.AnimationTimer; import com.iambookmaster.client.common.SpanHTML; import com.iambookmaster.client.common.SpanLabel; import com.iambookmaster.client.locale.AppConstants; import com.iambookmaster.client.locale.AppLocale; import com.iambookmaster.client.locale.AppMessages; import com.iambookmaster.client.model.Model; import com.iambookmaster.client.player.PlayerState.FighterData; public class BattlePanelStandard extends VerticalPanel implements BattlePanel{ private static final AppConstants appConstants = AppLocale.getAppConstants(); private static final AppMessages appMessages = AppLocale.getAppMessages(); private static int battleCounter; private Battle battle; private Button attack; private Button auto; private Model model; private PlayerState playerState; private BattleListener playerListener; public String battleName; public ClickHandler mainClickHandler; private HeroWidget heroWidget; private FlowPanel alchemyPanel; private AnimationTimer animationTimer; // private int battleConsoleHeight; private ArrayList<ParagraphConnection> vitalConnections; private ArrayList<String> messages = new ArrayList<String>(); public BattlePanelStandard(Model mod, Battle btl, PlayerState ps, PlayerListener playerLs) { animationTimer = new AnimationTimer(); battleName = "BattlePanelStandard"+String.valueOf(battleCounter++); this.battle = btl; this.playerState = ps; this.model = mod; setWidth("100%"); List<ParagraphConnection> list = model.getOutputParagraphConnections(playerState.getCurrentParagraph()); for (ParagraphConnection connection : list) { if (connection.getType()==ParagraphConnection.TYPE_VITAL_LESS || connection.getType()==ParagraphConnection.TYPE_ENEMY_VITAL_LESS) { if (vitalConnections == null) { vitalConnections = new ArrayList<ParagraphConnection>(); } vitalConnections.add(connection); } } playerListener = new BattleListenerAdapter(appConstants,appMessages,playerState) { @Override protected void addMessage(String message) { messages.add(message); } }; setStyleName(PlayerStyles.BATTLE_PANEL); setSize("100%", "100%"); if (battle.getVital()==null) { errorState(); Window.alert(appMessages.playerBattleNoVital(battle.getName())); return; } if (playerState.getCurrentParagraph().getEnemies()==null && playerState.getCurrentParagraph().getEnemies().size()==0) { errorState(); Window.alert(appConstants.playerBattleNoEmenies()); return; } mainClickHandler = new ClickHandler(){ public void onClick(ClickEvent event) { if (event.getSource()==attack) { playerState.nextBattleRound(playerListener); redraw(); } else if (event.getSource()==auto) { attack.setEnabled(false); auto.setEnabled(false); new Timer() { @Override public void run() { if (playerState.nextBattleRound(playerListener)) { redraw(); } else { redraw(); cancel(); } } }.scheduleRepeating(500); } } }; redraw(); } private void redraw() { if (getWidgetCount()>0) { clear(); } boolean heroAlive = playerState.isHeroAlive(); boolean battleActive = heroAlive && playerState.isBattleActive(); Label label = new Label(battle.getName()); add(label); setCellWidth(label, "100%"); setCellHorizontalAlignment(label, HasHorizontalAlignment.ALIGN_CENTER); //add Hero heroWidget = new HeroWidget(playerState.getParameters(),heroAlive); add(heroWidget); //add partners //add enemies for (FighterData npc : playerState.getFighters()) { NPCWidget widget = new NPCWidget(npc,battleActive); add(widget); } HorizontalPanel horizontalPanel = new HorizontalPanel(); horizontalPanel.setSize("100%", "100%"); horizontalPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER); attack = new Button(appConstants.playerButtonAttack(),mainClickHandler); attack.setTitle(appConstants.playerButtonAttackTitle()); attack.setEnabled(battleActive); horizontalPanel.add(attack); if (battle.isOneTurnBattle()) { horizontalPanel.setCellWidth(attack,"100%"); } else { horizontalPanel.setCellWidth(attack,"50%"); auto = new Button(appConstants.playerButtonAutoBattle(),mainClickHandler); auto.setTitle(appConstants.playerButtonAutoBattleTitle()); auto.setEnabled(battleActive); horizontalPanel.add(auto); horizontalPanel.setCellWidth(auto,"50%"); } add(horizontalPanel); if (battleActive) { //all applicable alchemy alchemyPanel = new FlowPanel(); alchemyPanel.setWidth("100%"); add(alchemyPanel); updateAlchemyStatus(true); } if (model.getSettings().isShowBattleConsole()) { for (String message : messages) { label = new HTML(message); label.addStyleName(PlayerStyles.BATTLE_MESSAGE); add(label); } messages.clear(); } } public class AlchemyLink extends Image implements ClickHandler{ private Alchemy alchemy; private boolean enabled=true; public AlchemyLink(Alchemy alchemy) { this.alchemy = alchemy; setStyleName(PlayerStyles.ALCHEMY_LINK); setEnabled(true); addClickHandler(this); } public void setEnabled(boolean enabled) { this.enabled = enabled; if (enabled) { setUrl(PlayImages.SELECT); setStyleName(PlayerStyles.CLICKABLE); } else { removeStyleName(PlayerStyles.CLICKABLE); setUrl(PlayImages.SELECT_DISABLED); } } public void onClick(ClickEvent event) { if (enabled && playerState.doAlchemyInBattle(alchemy)) { redraw(); } } } private void updateAlchemyStatus(boolean enable) { ArrayList<Alchemy> alchemyList = playerState.getAlchemy(true, true); alchemyPanel.clear(); if (alchemyList != null) { for (Alchemy alchemy : alchemyList) { if (alchemy.getBattleLimit() == null) { if (alchemy.getFromValue()>0) { heroWidget.addParameter(alchemy.getFrom(), playerState.getParameters().get(alchemy.getFrom()),playerState.getParameters()); } } else { heroWidget.addParameter(alchemy.getBattleLimit(), playerState.getHeroBatleLimits().get(alchemy.getBattleLimit()),playerState.getParameters()); } alchemyPanel.add(new SpanHTML(alchemy.getName())); AlchemyLink link = new AlchemyLink(alchemy); alchemyPanel.add(link); link.setEnabled(enable); } } } private void errorState() { } public class NPCWidget extends FlowPanel implements ClickHandler{ private SpanLabel name; private FighterData data; public NPCWidget(FighterData data, boolean active) { this.data = data; if (data.isAlive()) { if (data.isFriend()) { setStyleName(PlayerStyles.NPC_FRIEND); } else if (playerState.getFighters().size()<2) { setStyleName(PlayerStyles.NPC_SINGLE); } else if (playerState.isTarget(data)) { setStyleName(PlayerStyles.NPC_SELECTED); } else if (data.isCanBeTarget()){ if (active) { setTitle(appConstants.battleClickToSelectTarget()); sinkEvents(Event.ONCLICK); } setStyleName(PlayerStyles.NPC_NON_SELECTED); } else { setStyleName(PlayerStyles.NPC_NON_AVAILABLE); } } else { setStyleName(PlayerStyles.NPC_DEAD); } name = new SpanLabel(data.getNpc().getNpc().getName()+":"); add(name); for (Parameter parameter : data.getParameters().keySet()) { int value = data.getParameters().get(parameter); SpanLabel label = new SpanLabel(parameter.getName()); label.setStyleName(PlayerStyles.PARAMETER_NAME); add(label); add(new ParameterWidget(parameter,value,null)); } } @Override public void onBrowserEvent(Event event) { onClick(null); } public void onClick(ClickEvent event) { if (data.isCanBeTarget()) { playerState.selectTarget(data); redraw(); } } } public class HeroWidget extends FlowPanel { private HashSet<Parameter> used; private SpanLabel name; public HeroWidget(Map<Parameter,Integer> parameters, boolean heroAlive) { if (heroAlive) { if (playerState.isHeroFighting()) { setStyleName(PlayerStyles.HERO_ALIVE); } else { setStyleName(PlayerStyles.HERO_INACTIVE); } } else { setStyleName(PlayerStyles.HERO_DEAD); } used = new HashSet<Parameter>(playerState.getParameters().size()); name = new SpanLabel(appConstants.playerBattleHero()); add(name); for (Parameter parameter : playerState.getParameters().keySet()) { //add parameter to the list if (battle.dependsOn(parameter)) { Integer value = playerState.getParameters().get(parameter); addParameter(parameter,value,playerState.getParameters()); } } } public void addParameter(Parameter parameter, int value, Map<Parameter,Integer> params) { if (used.contains(params) || parameter.isInvisible()) { return; } used.add(parameter); if (parameter.getLimit() != null) { used.add(parameter.getLimit()); } SpanLabel label = new SpanLabel(parameter.getName()+":"); label.setStyleName(PlayerStyles.PARAMETER_NAME); add(label); add(new ParameterWidget(parameter,value,params)); } } public class ParameterWidget extends SpanLabel{ private Parameter parameter; public ParameterWidget(Parameter parameter, int value, Map<Parameter, Integer> params) { setStyleName(PlayerStyles.PARAMETER_VALUE); this.parameter = parameter; apply(value,params); } public void apply(int val, Map<Parameter, Integer> params) { if (parameter.getLimit()==null || params==null) { //no limit setText(String.valueOf(val)); } else { //update value/limit setText(String.valueOf(val)+"/"+params.get(parameter.getLimit())); } } } public void close() { // playerState.removePlayerStateListener(playerStateListener); } @Override protected void onDetach() { super.onDetach(); animationTimer.cancel(); close(); } public void restore() { //TODO } }