package com.iambookmaster.server.logic; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import com.iambookmaster.client.beans.AbstractParameter; import com.iambookmaster.client.beans.Alchemy; import com.iambookmaster.client.beans.Battle; import com.iambookmaster.client.beans.DiceValue; import com.iambookmaster.client.beans.Greeting; import com.iambookmaster.client.beans.Modificator; import com.iambookmaster.client.beans.NPC; import com.iambookmaster.client.beans.NPCParams; import com.iambookmaster.client.beans.ObjectBean; import com.iambookmaster.client.beans.Paragraph; import com.iambookmaster.client.beans.ParagraphConnection; import com.iambookmaster.client.beans.Parameter; import com.iambookmaster.client.beans.ParametersCalculation; import com.iambookmaster.client.beans.Sprite; import com.iambookmaster.client.locale.AppConstants; import com.iambookmaster.client.locale.AppMessages; import com.iambookmaster.client.model.Model; import com.iambookmaster.client.model.ParagraphParsingHandler; import com.iambookmaster.client.paragraph.BookDecorator; public class URQBookDecrator implements BookDecorator { public static final String ENCODING = "windows-1251"; private static final String VAR_MODIFICATOR_EXISTS = "modificatorExist"; private static final String VAR_CAN_GO = "canGo"; private static final String VAR_ALCHEMY_DISABLED_PREFIX = "alchemyDisabled"; private static final String VAR_ENEMY_PREFIX = "enemy"; private static final String VAR_BATTLE_MODE = "battleMode"; private static final String VAR_MUST_GO = "mustGo"; private static final String VAR_MODIFICATOR_PREFIX = "modificator"; private static final String VAR_PARAMETER_PREFIX = "parameter"; private static final String VAR_CURRENT_ENEMY_TYPE = "enemyType"; private static final String VAR_CURRENT_PARAGRAPH = "currentLocation"; private static final String VAR_ENEMY_VITAL = "enemyVital"; private static final String VAR_HERO_ATTACK_SELECTION = "heroAttackSelection"; private static final String VAR_ATTACK_VALUE = "attackValue"; private static final String VAR_DEFENSE_VALUE = "defenseValue"; private static final String VAR_DAMAGE_VALUE = "damageValue"; private static final String VAR_TEMP = "temp"; private static final String VAR_CALCULATION = "calc"; private static final String VAR_DICE = "d"; private static final String VAR_DICE_MAX = "dMax"; private static final String VAR_SELECTOR = "targetSelector"; private static final String VAR_SELECTED_ENEMY = "selectedEnemy"; private static final String VAR_TEMP_PARAMETER_PREFIX = "tempParameter"; private static final String VAR_ALCHEMY_USED_IN_BATTLE_ROUND = "alchemyUsed"; private static final String VAR_FATAL = "fatal"; private static final String VAR_DICE_TEMP = "diceTemp"; private static final String VAR_CURRENT_MUSIC = "music"; private static final String VAR_CLEAN_DECORATORS = "cleanDecorators"; private static final char PARAGRAPH_APPLY_PREFIX = 'a'; private static final char PARAGRAPH_PREFIX = 'l'; private static final char PARAGRAPH_INIT_PREFIX = 'i'; private static final char PARAGRAPH_INIT_BATTLE_PREFIX = 'b'; private static final String VALUE_MODIFICATOR_SET = "1"; private static final String VALUE_MODIFICATOR_NOT_SET = "0"; private static final String PROC_ADD_BATTLE_ALCHEMY = "battleAlchemy"; private static final Object PROC_CHECK_ENEMY_ALIVE = "checkEnemyAlive"; private static final String PROC_ENABLE_ALCEMY = "enableAlchemy"; private static final String PROC_SHOW_ENEMY_PARAMS = "showEnemyParams"; private static final String PROC_ADD_PEACE_ALCHEMY = "peaceAlchemy"; private static final String PROC_VITAL = "vitalHeroCheck"; private static final String PROC_SHOW_ENEMY_NAME = "showEnemyName"; private static final String PROC_SHOW_PARAMS = "showHeroParams"; private static final String PROC_USE_ALCEMY = "useAlchemy"; private static final String PROC_ATTACK = "attack"; private static final String PROC_SELECT_TARGET = "target"; private static final String PROC_SELECT_ENEMY = "selectEnemy"; private static final String PROC_SELECT_TARGET_AUTO = "autoTarget"; private static final String PROC_SHOW_ENEMY_SELECTION = "markSelectedTarget"; private static final String PROC_ABOUT = "about"; private static final String PROC_GREETINGS = "greetings"; private static final String PROC_GO_CURRENT = "goCurrent"; private static final String PROC_BATTLE = "battle"; private static final String PROC_CHECK_ENEMY_ALIVE_AND_SHOW_SELECTION = "showAliveEnemyForSelect"; private static final String PROC_CHECK_ENEMY_ALIVE_AND_SELECT = "selectAliveEnemy"; private static final String PROC_CHECK_ENEMY_ALIVE_AND_KILL = "checkEnemyAndKill"; private static final String PROC_CANNOT_USE = "cannotUseObj"; private static final String BEFORE_PARAM = "#"; private static final String AFTER_PARAM = "$"; private StringBuilder buffer; private final AppConstants appConstants; private final AppMessages appMessages; private HashMap<Paragraph, ArrayList<ParagraphAction>> paragraphActions=new HashMap<Paragraph, ArrayList<ParagraphAction>>(); private HashMap<ObjectBean, String> objects=new HashMap<ObjectBean, String>(); private Model model; private HashSet<Parameter> limits; private ArrayList<Parameter> vitals=new ArrayList<Parameter>(); private boolean alchemyPresent; private boolean alchemyPeacePresent; private boolean alchemyBattlePresent; private HashMap<String, String> diceProces=new HashMap<String, String>(); private StringBuilder diceBuffer; private HashSet<Parameter> battleAlchemyLimits; private HashSet<String> battleSet = new HashSet<String>(); private boolean obfuscate=true; private int obsCounter=0; private HashMap<String,String> obs=new HashMap<String, String>(); private boolean hasParameters; private HashMap<String, Integer> music = new HashMap<String, Integer>(); private String getID(Object...ids) { String id; if (ids.length==1) { id = String.valueOf(ids[0]); } else { StringBuffer buffer = new StringBuffer(); for (Object object : ids) { buffer.append(String.valueOf(object)); } id = buffer.toString(); } if (obfuscate) { if (obs.containsKey(id)) { return obs.get(id); } else { StringBuffer buffer = new StringBuffer(); int i=obsCounter++; //first - character buffer.append((char)(65+i%22)); i = i /22; //second - number buffer.append((char)(48+i%10)); i = i /10; //next - characters while (i>0) { buffer.append((char)(65+i%22)); i = i /22; } String res = buffer.toString(); obs.put(id,res); return res; } } else { return id; } } public class ParagraphAction { private int id; private ParagraphConnection connection; private Paragraph to; private Paragraph from; public ParagraphAction(Paragraph from, Paragraph to,ParagraphConnection connection,int id) { super(); this.id = id; this.connection = connection; this.to = to; this.from = from; } public int getId() { return id; } public ParagraphConnection getConnection() { return connection; } public Paragraph getTo() { return to; } public Paragraph getFrom() { return from; } public String getObjectVar() { return objects.get(connection.getObject()); } public String getModificatorVar() { return getID(VAR_MODIFICATOR_PREFIX,connection.getModificator().getId()); } public String getParameterVar() { return getID(VAR_PARAMETER_PREFIX,connection.getParameter().getId()); } public String getActionName() { if (model.getSettings().isShowConnectionNames()) { StringBuilder builder = new StringBuilder(appMessages.urqButtonAction(id)).append(' '); if (connection.getFrom()==from) { //from builder.append(connection.getNameFrom()); } else { builder.append(connection.getNameTo()); } return builder.toString(); } else { return appMessages.urqButtonAction(id); } } } public void println(String text) { int len = buffer.length(); buffer.append("p "); int pos = buffer.length(); buffer.append(text); while (pos<buffer.length()) { switch (buffer.charAt(pos)) { case '\r': if (buffer.charAt(pos+1)=='\n') { buffer.replace(pos, pos+2, "#/$"); } else { buffer.replace(pos, pos+1, "#/$"); } pos = pos + 2; break; case '\n': buffer.replace(pos, pos+1, "#/$"); pos = pos + 2; break; case '$': buffer.insert(pos, "##36"); pos = pos + 4; break; case '#': buffer.replace(pos, pos+1, "##35$"); pos = pos + 4; break; case '&': buffer.replace(pos, pos+1, "##38$"); pos = pos + 4; break; } pos++; if (pos-len>60) { if (pos<buffer.length()) { if (buffer.charAt(pos)==' ') { //check for space buffer.replace(pos, pos+1, "\np #$"); pos = pos + 2; } else if (buffer.charAt(pos-1)==' '){ buffer.replace(pos-1, pos, "#$\np "); pos = pos + 2; } else { buffer.insert(pos, "\np "); } } pos = pos + 3; len = pos; } } buffer.append("#/$\n"); } public void printLine(StringBuilder builder,String text) { int pos = builder.length(); builder.append(text); while (pos<builder.length()) { switch (builder.charAt(pos)) { case '\n': //cut last builder.setLength(pos); break; case '$': buffer.insert(pos, "##36"); pos = pos + 4; break; case '#': buffer.insert(pos, "##35"); pos = pos + 4; break; case '&': buffer.insert(pos, "##38"); pos = pos + 4; break; } pos++; } } public URQBookDecrator(Model mod,AppConstants appConstants,AppMessages appMessages) { this.model = mod; this.appConstants = appConstants; this.appMessages = appMessages; diceBuffer = new StringBuilder(); buffer = new StringBuilder(); buffer.append(":start\nhide_phantoms=0&fp_prec=0\n"); if (model.getSettings().getBookTitle() != null) { println(model.getSettings().getBookTitle()); } if (model.getSettings().getBookAuthors() != null) { println(model.getSettings().getBookAuthors()); } println(appConstants.bookCreatedByText()); buffer.append("btn "); buffer.append(getID(PROC_ABOUT)); buffer.append(','); buffer.append(appConstants.urqAbout()); buffer.append('\n'); if (model.getSettings().isShowAboutOnStart()==false) { addButton(model.getStartParagraph(),appConstants.decoratorStart()); } buffer.append("\nend\n:common\nend\n:"); buffer.append(getID(PROC_ABOUT)); buffer.append('\n'); boolean add=false; if (model.getSettings().getBookDescription() != null) { if (add) { buffer.append("pln \n"); } add=true; println(model.getSettings().getBookDescription()); } if (model.getPlayerRules().length()>0) { if (add) { buffer.append("pln \n"); } add=true; println(model.getPlayerRules()); } if (model.getSettings().getGreetings() != null && model.getSettings().getGreetings().size()>0) { if (add) { buffer.append("pln \n"); } add=true; buffer.append("proc "); buffer.append(getID(PROC_GREETINGS)); buffer.append('\n'); } addButton(model.getStartParagraph(),appConstants.decoratorStart()); buffer.append("\nend\n"); //support procedures HashMap<Object,ArrayList<ParagraphConnection>> objConnections; battleAlchemyLimits = new HashSet<Parameter>(); if (model.getSettings().isHiddenUsingObjects()) { objConnections = new HashMap<Object, ArrayList<ParagraphConnection>>(); for (ParagraphConnection connection : model.getParagraphConnections()) { if (connection.getType()==ParagraphConnection.TYPE_NORMAL && connection.getObject() != null) { ArrayList<ParagraphConnection> list = objConnections.get(connection.getObject()); if (list==null) { list = new ArrayList<ParagraphConnection>(); objConnections.put(connection.getObject(), list); } list.add(connection); } } } else { objConnections=null; } int maxEnemies=0; ArrayList<Paragraph> book = model.getParagraphs(); ArrayList<Integer> numbers = new ArrayList<Integer>(book.size()); for (Paragraph paragraph : book) { numbers.add(paragraph.getNumber()); if (paragraph.getEnemies() != null) { if (maxEnemies < paragraph.getEnemies().size() ) { maxEnemies = paragraph.getEnemies().size(); } } } Collections.sort(numbers); writeGoProc(0,numbers.size(),numbers,false); ArrayList<ObjectBean> objs = model.getObjects(); ArrayList<AbstractParameter> params = model.getParameters(); //check for Parameters limits = new HashSet<Parameter>(); StringBuilder battleAlchemy=null; StringBuilder peaceAlchemy=null; StringBuilder enableAlchemy=null; StringBuilder npcNames=null; StringBuilder alchemyUsage=null; for (AbstractParameter par : params) { if (par instanceof Parameter) { Parameter parameter = (Parameter) par; if (parameter.getLimit() != null) { limits.add(parameter.getLimit()); } if (parameter.isVital()){ vitals.add(parameter); } } else if (par instanceof Alchemy) { Alchemy alchemy = (Alchemy)par; if (alchemyUsage==null) { alchemyUsage = new StringBuilder(); } if (alchemy.getBattleLimit() != null) { battleAlchemyLimits.add(alchemy.getBattleLimit()); } alchemyUsage.append(':'); alchemyUsage.append(getID(PROC_USE_ALCEMY+alchemy.getId())); alchemyUsage.append('\n'); alchemyUsage.append(getID(VAR_ALCHEMY_USED_IN_BATTLE_ROUND)); alchemyUsage.append("=1\n"); alchemyUsage.append(getID(VAR_PARAMETER_PREFIX+alchemy.getFrom().getId())); alchemyUsage.append('='); alchemyUsage.append(getID(VAR_PARAMETER_PREFIX+alchemy.getFrom().getId())); alchemyUsage.append('-'); alchemyUsage.append(alchemy.getFromValue()); alchemyUsage.append('\n'); if (alchemy.getBattleLimit() != null) { alchemyUsage.append("if "); alchemyUsage.append(getID(VAR_BATTLE_MODE)); alchemyUsage.append(">0 then "); alchemyUsage.append(getID(VAR_TEMP_PARAMETER_PREFIX+alchemy.getBattleLimit().getId())); alchemyUsage.append('='); alchemyUsage.append(getID(VAR_TEMP_PARAMETER_PREFIX+alchemy.getBattleLimit().getId())); alchemyUsage.append("-1\n"); } addDiceValue(alchemyUsage, alchemy.getToValue(),false); if (alchemy.isWeapon()) { // alchemyUsage.append('\n'); for (int i = 0; i < maxEnemies; i++) { alchemyUsage.append("if "); alchemyUsage.append(getID(VAR_SELECTED_ENEMY)); alchemyUsage.append('='); alchemyUsage.append(i); alchemyUsage.append(" then "); alchemyUsage.append(getID(VAR_ENEMY_PREFIX,i,alchemy.getTo().getId())); alchemyUsage.append('='); alchemyUsage.append(getID(VAR_ENEMY_PREFIX,i,VAR_PARAMETER_PREFIX,alchemy.getTo().getId())); alchemyUsage.append('-'); alchemyUsage.append(getID(VAR_DICE)); if (alchemy.getTo().isVital() || alchemy.getTo().isNegative()==false) { alchemyUsage.append("&if "); alchemyUsage.append(getID(VAR_ENEMY_PREFIX,i,VAR_PARAMETER_PREFIX,alchemy.getTo().getId())); alchemyUsage.append("<=0 then "); alchemyUsage.append(getID(VAR_ENEMY_PREFIX,i,VAR_PARAMETER_PREFIX,alchemy.getTo().getId())); alchemyUsage.append("=0"); if (alchemy.getTo().isVital()) { //kill the enemy alchemyUsage.append('&'); alchemyUsage.append(getID(VAR_BATTLE_MODE)); alchemyUsage.append('='); alchemyUsage.append(getID(VAR_BATTLE_MODE)); alchemyUsage.append("-1&proc "); alchemyUsage.append(getID(PROC_SELECT_TARGET_AUTO)); } } alchemyUsage.append('\n'); } } else { alchemyUsage.append('&'); alchemyUsage.append(getID(VAR_PARAMETER_PREFIX,alchemy.getTo().getId())); alchemyUsage.append('='); alchemyUsage.append(getID(VAR_PARAMETER_PREFIX,alchemy.getTo().getId())); alchemyUsage.append('+'); alchemyUsage.append(getID(VAR_DICE)); if (model.getSettings().isOverflowControl() ^ alchemy.isOverflowControl()) { if (alchemy.getTo().getLimit() != null) { //control limits alchemyUsage.append("&if "); alchemyUsage.append(getID(VAR_PARAMETER_PREFIX,alchemy.getTo().getLimit().getId())); alchemyUsage.append('<'); alchemyUsage.append(getID(VAR_PARAMETER_PREFIX,alchemy.getTo().getId())); alchemyUsage.append(" then "); alchemyUsage.append(getID(VAR_PARAMETER_PREFIX,alchemy.getTo().getId())); alchemyUsage.append('='); alchemyUsage.append(getID(VAR_PARAMETER_PREFIX,alchemy.getTo().getLimit().getId())); } } alchemyUsage.append('\n'); } alchemyUsage.append("goto "); alchemyUsage.append(getID(PROC_GO_CURRENT)); alchemyUsage.append("\nend\n"); alchemyPresent = true; if (enableAlchemy==null) { enableAlchemy = new StringBuilder(); enableAlchemy.append(':'); enableAlchemy.append(getID(PROC_ENABLE_ALCEMY)); enableAlchemy.append('\n'); } enableAlchemy.append("if "); enableAlchemy.append(getID(VAR_ALCHEMY_DISABLED_PREFIX,alchemy.getId())); enableAlchemy.append("=1 then "); enableAlchemy.append(getID(VAR_ALCHEMY_DISABLED_PREFIX,alchemy.getId())); enableAlchemy.append("=0\n"); if (alchemy.isOnDemand()==false) { if (alchemy.getPlace() != Alchemy.PLACE_BATTLE) { //peace if (peaceAlchemy==null) { alchemyPeacePresent = true; peaceAlchemy = new StringBuilder(); peaceAlchemy.append(':'); peaceAlchemy.append(getID(PROC_ADD_PEACE_ALCHEMY)); peaceAlchemy.append('\n'); peaceAlchemy.append("pln \n"); } addAlchemy(peaceAlchemy,alchemy,false); } if (alchemy.getPlace() != Alchemy.PLACE_PEACE) { //battle if (battleAlchemy==null) { alchemyBattlePresent = true; battleAlchemy = new StringBuilder(); battleAlchemy.append(':'); battleAlchemy.append(getID(PROC_ADD_BATTLE_ALCHEMY)); battleAlchemy.append('\n'); battleAlchemy.append("pln \n"); } addAlchemy(battleAlchemy,alchemy,true); } } } else if (par instanceof NPC) { NPC npc = (NPC)par; if (npcNames==null) { npcNames = new StringBuilder(); npcNames.append(':'); npcNames.append(getID(PROC_SHOW_ENEMY_NAME)); npcNames.append('\n'); } npcNames.append("if "); npcNames.append(getID(VAR_CURRENT_ENEMY_TYPE)); npcNames.append('='); npcNames.append(npc.getId()); npcNames.append(" then p "); printLine(npcNames,npc.getName()); npcNames.append("#$\n"); } } if (npcNames != null) { buffer.append(npcNames.toString()); buffer.append("end\n"); } if (peaceAlchemy != null) { buffer.append(peaceAlchemy.toString()); buffer.append("end\n"); } if (battleAlchemy != null) { buffer.append(battleAlchemy.toString()); buffer.append("end\n"); } if (enableAlchemy != null) { buffer.append(enableAlchemy.toString()); buffer.append("end\n"); } if (alchemyUsage != null) { buffer.append(alchemyUsage.toString()); } StringBuilder[] showEnemyFunctions = new StringBuilder[maxEnemies]; StringBuilder[] checkEnemyAliveFunctions = new StringBuilder[maxEnemies]; for (int i = 0; i < maxEnemies; i++) { showEnemyFunctions[i] = new StringBuilder().append(':') .append(getID(PROC_SHOW_ENEMY_PARAMS,i)).append('\n'); checkEnemyAliveFunctions[i] = new StringBuilder().append(':') .append(getID(PROC_CHECK_ENEMY_ALIVE,i)).append('\n'); } hasParameters = false; for (AbstractParameter par : params) { if (par instanceof Parameter) { Parameter parameter = (Parameter) par; if (limits.contains(parameter)) { //limit is shown with main parameter continue; } if (parameter.isHeroOnly()==false) { //NPC param for (int i = 0; i < maxEnemies; i++) { if (parameter.isInvisible()==false) { //do not show invisible parameters showEnemyFunctions[i].append("if ") .append(getID(VAR_ENEMY_PREFIX,i,VAR_PARAMETER_PREFIX,parameter.getId())) .append("<>0 then p "); printLine(showEnemyFunctions[i], parameter.getName()); showEnemyFunctions[i].append(" #") .append(getID(VAR_ENEMY_PREFIX,i,VAR_PARAMETER_PREFIX,parameter.getId())) .append("$#$\n"); } if (parameter.isVital()) { //check for vital parameters showEnemyFunctions[i].append("if ") .append(getID(VAR_ENEMY_PREFIX,i,VAR_PARAMETER_PREFIX,parameter.getId())) .append("<=0 then ") .append(getID(VAR_ENEMY_PREFIX,i,VAR_PARAMETER_PREFIX,parameter.getId())) .append("=0&") .append(getID(VAR_CURRENT_ENEMY_TYPE)) .append("=0\n"); } //check for alive if (parameter.isVital()) { checkEnemyAliveFunctions[i].append("if ") .append(getID(VAR_ENEMY_PREFIX,i,VAR_PARAMETER_PREFIX,parameter.getId())) .append("<=0 then ") .append(getID(VAR_CURRENT_ENEMY_TYPE)) .append("=0\n"); } } } if (hasParameters==false) { buffer.append(':'); buffer.append(getID(PROC_SHOW_PARAMS)); buffer.append("\np #/$"); buffer.append(appConstants.urlListParameters()); buffer.append("#$\n"); hasParameters = true; } if (parameter.isInvisible()==false) { //do not show invisible parameters buffer.append("if "); if (battleAlchemyLimits.contains(parameter)) { //special limit for the battle buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 and "); buffer.append(getID(VAR_TEMP_PARAMETER_PREFIX)); buffer.append(">0 then "); buffer.append("p "); buffer.append(parameter.getName()); buffer.append(":#"); buffer.append(getID(VAR_TEMP_PARAMETER_PREFIX)); buffer.append(parameter.getId()); buffer.append('$'); if (parameter.getLimit() != null) { buffer.append("/#"); buffer.append(getID(VAR_PARAMETER_PREFIX,parameter.getLimit().getId())); buffer.append('$'); } buffer.append("#$\nif "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append("=0 and "); } buffer.append(getID(VAR_PARAMETER_PREFIX,parameter.getId())); buffer.append("<>0 then "); buffer.append("p "); buffer.append(parameter.getName()); buffer.append(":#"); buffer.append(getID(VAR_PARAMETER_PREFIX,parameter.getId())); buffer.append('$'); if (parameter.getLimit() != null) { buffer.append("/#"); buffer.append(getID(VAR_PARAMETER_PREFIX,parameter.getLimit().getId())); buffer.append('$'); } buffer.append("#$\n"); } } } if (hasParameters) { buffer.append("end\n"); } for (int i = 0; i < maxEnemies; i++) { buffer.append(':'); buffer.append(getID(PROC_CHECK_ENEMY_ALIVE_AND_SHOW_SELECTION,i)); buffer.append("\nproc "); buffer.append(getID(PROC_CHECK_ENEMY_ALIVE,i)); buffer.append("\nif "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append(">0 then "); buffer.append(getID(VAR_SELECTOR)); buffer.append('='); buffer.append(getID(VAR_SELECTOR)); buffer.append("+1&p #/$#"); buffer.append(getID(VAR_SELECTOR)); buffer.append("$#$&"); buffer.append("btn "); buffer.append(getID(PROC_SELECT_ENEMY,i)); buffer.append(",<#"); buffer.append(getID(VAR_SELECTOR)); buffer.append("$>\n"); buffer.append("if "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append(">0 then "); buffer.append("proc "); buffer.append(getID(PROC_SHOW_ENEMY_NAME)); buffer.append("\nend\n"); buffer.append(':'); buffer.append(getID(PROC_CHECK_ENEMY_ALIVE_AND_SELECT,i)); buffer.append("\nproc "); buffer.append(getID(PROC_CHECK_ENEMY_ALIVE,i)); buffer.append('\n'); //alive, select it buffer.append("if "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append(">0 then "); buffer.append(getID(VAR_SELECTED_ENEMY)); buffer.append('='); buffer.append(i); buffer.append('&'); buffer.append(getID(VAR_SELECTOR)); buffer.append('='); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append("\nend\n"); buffer.append(':'); buffer.append(getID(PROC_CHECK_ENEMY_ALIVE_AND_KILL,i)); buffer.append("\nproc "); buffer.append(getID(PROC_CHECK_ENEMY_ALIVE,i)); //is alive? buffer.append("\nif "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append("=0 then "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append('='); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append("-1\nif "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append("=0 then proc "); buffer.append(getID(PROC_SELECT_TARGET_AUTO)); buffer.append("\nend\n"); } //functions for printing NPC parameters and checking is alive for (int i = 0; i < maxEnemies; i++) { showEnemyFunctions[i].append("end\n"); buffer.append(showEnemyFunctions[i].toString()); checkEnemyAliveFunctions[i].append("\nend\n"); buffer.append(checkEnemyAliveFunctions[i].toString()); buffer.append(':'); buffer.append(getID(PROC_SHOW_ENEMY_SELECTION,i)); buffer.append("\nif "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">1 and "); buffer.append(getID(VAR_SELECTED_ENEMY)); buffer.append('='); buffer.append(i); buffer.append(" then p "); buffer.append(appConstants.urqTarget()); buffer.append("#$\nend\n"); } if (maxEnemies>1) { //manual target selection procedure buffer.append(':'); buffer.append(getID(PROC_SELECT_TARGET)); buffer.append("\npln "); buffer.append(appConstants.urqSelectTarget()); buffer.append('\n'); buffer.append(getID(VAR_SELECTOR)); buffer.append("=0\n"); for (int i = 0; i < maxEnemies; i++) { buffer.append("if "); buffer.append(getID(VAR_SELECTOR)); buffer.append('<'); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(" then "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append('='); buffer.append(getID(VAR_ENEMY_PREFIX,i)); buffer.append("&proc "); buffer.append(getID(PROC_CHECK_ENEMY_ALIVE_AND_SHOW_SELECTION,i)); buffer.append('\n'); } buffer.append("btn "); buffer.append(getID(PROC_GO_CURRENT)); buffer.append(','); buffer.append(appConstants.urqCancelTargetSelection()); buffer.append("\nend\n"); //functions for set selected Enemy for (int i = 0; i < maxEnemies; i++) { buffer.append(':'); buffer.append(getID(PROC_SELECT_ENEMY,i)); buffer.append('\n'); buffer.append(getID(VAR_SELECTED_ENEMY)); buffer.append('='); buffer.append(i); buffer.append("\ngoto "); buffer.append(getID(PROC_GO_CURRENT)); buffer.append("\nend\n"); } } if (maxEnemies>0) { //auto target selection procedure buffer.append(':'); buffer.append(getID(PROC_SELECT_TARGET_AUTO)); buffer.append('\n'); buffer.append(getID(VAR_SELECTOR)); buffer.append("=0\n"); buffer.append(getID(VAR_SELECTED_ENEMY)); buffer.append("=-1\n"); for (int i = 0; i < maxEnemies; i++) { buffer.append("if "); buffer.append(getID(VAR_SELECTOR)); buffer.append('<'); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(" then "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append("=1&proc "); buffer.append(getID(PROC_CHECK_ENEMY_ALIVE_AND_SELECT,i)); buffer.append('\n'); } buffer.append("end\n"); //attack selected enemy buffer.append(':'); buffer.append(getID(PROC_ATTACK)); buffer.append('\n'); buffer.append(getID(VAR_HERO_ATTACK_SELECTION)); buffer.append('='); buffer.append(getID(VAR_SELECTED_ENEMY)); buffer.append('&'); buffer.append(getID(VAR_ALCHEMY_USED_IN_BATTLE_ROUND)); buffer.append("=0\n"); buffer.append("goto "); buffer.append(getID(PROC_GO_CURRENT)); buffer.append("\nend\n"); } buffer.append(":Use_"); buffer.append(appConstants.urqSaveGame()); buffer.append("\nif "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append("=0 then save "); buffer.append(getID(PROC_GO_CURRENT)); buffer.append("\nif "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 then pln "); buffer.append(appConstants.urqCannotSaveInBattle()); buffer.append("\nend\n"); buffer.append(":Use_Inv\n"); if (hasParameters) { buffer.append("proc "); buffer.append(getID(PROC_SHOW_PARAMS)); buffer.append('\n'); } if (model.getSettings().isShowModificators()) { //check for modificator buffer.append(getID(VAR_MODIFICATOR_EXISTS)); buffer.append("=0\n"); boolean firstMod = true; for (AbstractParameter parameter : params) { if (parameter instanceof Modificator) { Modificator modificator = (Modificator) parameter; if (firstMod) { buffer.append("p "); buffer.append(appConstants.playerListModificators()); buffer.append('\n'); firstMod = false; } buffer.append("if "); buffer.append(getID(VAR_MODIFICATOR_PREFIX,modificator.getId())); buffer.append('='); buffer.append(VALUE_MODIFICATOR_SET); buffer.append(" then "); buffer.append("p "); buffer.append(modificator.getName()); buffer.append(",&"); buffer.append(getID(VAR_MODIFICATOR_EXISTS)); buffer.append("=1\n"); } } if (firstMod==false) { buffer.append("if "); buffer.append(getID(VAR_MODIFICATOR_EXISTS)); buffer.append("=0 then pln "); buffer.append(appConstants.urqNoModificators()); buffer.append('\n'); buffer.append("if "); buffer.append(getID(VAR_MODIFICATOR_EXISTS)); buffer.append("=1 then pln "); buffer.append('\n'); } } buffer.append("end\n"); if (objs.isEmpty()==false) { buffer.append(':'); buffer.append(getID(PROC_CANNOT_USE)); buffer.append("\npln "); buffer.append(appConstants.urqCannotUseObject()); buffer.append("\nend\n"); } //object using actions for (ObjectBean bean : objs) { StringBuilder builder = new StringBuilder(bean.getName()); for (int i = 0; i < builder.length(); i++) { char c = builder.charAt(i); if (Character.isJavaIdentifierPart(c)==false) { builder.setCharAt(i, ' '); // builder.setCharAt(i, '_'); } } if (builder.length()>32) { builder.setLength(32); } objects.put(bean,builder.toString()); if (objConnections != null) { buffer.append(":Use_"); buffer.append(builder); buffer.append('_'); buffer.append(appConstants.urqUseObjectCommand()); buffer.append('\n'); ArrayList<ParagraphConnection> list = objConnections.get(bean); for (ParagraphConnection connection : list) { buffer.append("if "); buffer.append(getID(VAR_MUST_GO)); buffer.append("=0 and "); buffer.append(getID(VAR_CURRENT_PARAGRAPH)); buffer.append('='); buffer.append(connection.getFrom().getNumber()); buffer.append(" then cls&goto "); buffer.append(getID(PARAGRAPH_PREFIX,connection.getTo().getNumber())); buffer.append('\n'); } buffer.append("goto "); buffer.append(getID(PROC_CANNOT_USE)); buffer.append('\n'); } } buffer.append(':'); buffer.append(getID(PROC_VITAL)); buffer.append('\n'); buffer.append(getID(VAR_TEMP)); buffer.append("=1\n"); for (Parameter parameter : vitals) { buffer.append("if "); buffer.append(getID(VAR_PARAMETER_PREFIX,parameter.getId())); buffer.append("<=0 then "); buffer.append(getID(VAR_MUST_GO)); buffer.append("=1&"); buffer.append(getID(VAR_TEMP)); buffer.append("=0&"); buffer.append(getID(VAR_CAN_GO)); buffer.append("=-1&pln #/$"); buffer.append(appMessages.urqHeroDiedByVitalParameter(parameter.getName())); buffer.append('\n'); } //restart if Game is Over buffer.append("if "); buffer.append(getID(VAR_TEMP)); buffer.append("=0 then btn "); buffer.append(getID(PARAGRAPH_PREFIX,model.getStartParagraph().getNumber())); buffer.append(','); buffer.append(appConstants.playerTitleRestartGame()); buffer.append('\n'); buffer.append("end\n"); } private void writeGoProc(int from, int to, ArrayList<Integer> numbers,boolean prefix) { if (to-from>10) { //use sub calls int mid = from+(to-from)/2; int num = numbers.get(mid); writeGoProc(from,mid,numbers,true); writeGoProc(mid,to,numbers,true); buffer.append(':'); if (prefix) { buffer.append(getID(PROC_GO_CURRENT,from,'_',to)); } else { buffer.append(getID(PROC_GO_CURRENT)); } buffer.append('\n'); buffer.append("if "); buffer.append(getID(VAR_CURRENT_PARAGRAPH)); buffer.append('<'); buffer.append(num); buffer.append(" then goto "); buffer.append(getID(PROC_GO_CURRENT,from,'_',mid)); buffer.append('\n'); buffer.append("goto "); buffer.append(getID(PROC_GO_CURRENT,mid,'_',to)); buffer.append('\n'); } else { buffer.append(':'); if (prefix) { buffer.append(getID(PROC_GO_CURRENT,from,'_',to)); } else { buffer.append(getID(PROC_GO_CURRENT)); } buffer.append('\n'); int len = to-1; for (int i = from; i < len; i++) { int num = numbers.get(i); buffer.append("if "); buffer.append(getID(VAR_CURRENT_PARAGRAPH)); buffer.append('='); buffer.append(num); buffer.append(" then goto "); buffer.append(getID(PARAGRAPH_PREFIX,num)); buffer.append('\n'); } int num = numbers.get(len); buffer.append("goto "); buffer.append(getID(PARAGRAPH_PREFIX,num)); buffer.append('\n'); } } private void addBattleCalculation(StringBuilder builder, Battle battle, int enemyCounter, boolean heroAttack, boolean printResult) { //attack vs. attack if (heroAttack) { if (battle.isOneTurnBattle()) { //one turn builder.append("if "); builder.append(getID(VAR_ATTACK_VALUE)); builder.append('>'); builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_ATTACK_VALUE)); builder.append(" then "); if (printResult) { builder.append("p "); builder.append(appConstants.urqKilled()); } else { builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append("=0&"); builder.append(getID(VAR_BATTLE_MODE)); builder.append('='); builder.append(getID(VAR_BATTLE_MODE)); builder.append("-1&proc "); builder.append(getID(PROC_SELECT_TARGET_AUTO)); } builder.append('\n'); } else { addBattleHeroAttackEnemy(builder,battle,enemyCounter,heroAttack,printResult); } } else if (battle.isOneTurnBattle()) { builder.append("if "); builder.append(getID(VAR_ATTACK_VALUE)); builder.append('<'); builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_ATTACK_VALUE)); builder.append(" then "); if (printResult) { builder.append("p "); builder.append(appConstants.urqKilled()); } else { builder.append(getID(VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append("=0"); } builder.append('\n'); } else if (battle.isOneTurnBattle()==false) { //many turns, enemy attack addBattleEmemyAttackHero(builder,battle,enemyCounter,heroAttack,printResult); } } private void addBattleEmemyAttackHero(StringBuilder builder, Battle battle, int enemyCounter, boolean heroAttack, boolean printResult) { //Enemy attack if (battle.getFatal() == Battle.FATAL_NORMAL) { builder.append("if "); builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_FATAL)); builder.append("=1 then "); builder.append(getID(VAR_TEMP)); builder.append('='); if (battle.isDifferenceIsDamage()) { builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_ATTACK_VALUE)); } else { builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_DAMAGE_VALUE)); } builder.append('&'); if (printResult) { builder.append("&p "); builder.append(appMessages.urqBattleFatalStrike(getID(VAR_TEMP),BEFORE_PARAM,AFTER_PARAM)); builder.append("#$"); } else { builder.append('&'); builder.append(getID(VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append('='); builder.append(getID(VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append('-'); builder.append(getID(VAR_TEMP)); builder.append("&if "); builder.append(getID(VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append('<'); builder.append("0 then "); builder.append(getID(VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append("=0"); } builder.append('\n'); } builder.append("if "); if (battle.getFatal() == Battle.FATAL_NORMAL) { builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_FATAL)); builder.append("=0 and "); } if (battle.isAttackDefense()) { builder.append(getID(VAR_DEFENSE_VALUE)); } else { builder.append(getID(VAR_ATTACK_VALUE)); } builder.append('<'); builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_ATTACK_VALUE)); builder.append(" then "); builder.append(getID(VAR_TEMP)); builder.append('='); if (battle.isDifferenceIsDamage()) { builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_ATTACK_VALUE)); builder.append('-'); if (battle.isAttackDefense()) { builder.append(getID(VAR_DEFENSE_VALUE)); } else { builder.append(getID(VAR_ATTACK_VALUE)); } } else { builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_DAMAGE_VALUE)); } if (printResult) { builder.append("&p "); builder.append(appMessages.urqBattleRoundDamage(getID(VAR_TEMP),BEFORE_PARAM,AFTER_PARAM)); builder.append("#$"); } else { builder.append('&'); builder.append(getID(VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append('='); builder.append(getID(VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append('-'); builder.append(getID(VAR_TEMP)); builder.append("&if "); builder.append(getID(VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append('<'); builder.append("0 then "); builder.append(getID(VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append("=0"); } builder.append('\n'); } private void addBattleHeroAttackEnemy(StringBuilder builder, Battle battle, int enemyCounter, boolean heroAttack, boolean printResult) { //Hero attack enemy if (battle.getFatal() != Battle.FATAL_NONE) { //check for Fatal Strike builder.append("if "); builder.append(getID(VAR_FATAL)); builder.append("=1 then "); if (battle.getFatal() == Battle.FATAL_DEAD) { if (printResult) { builder.append("p "); builder.append(appConstants.urqKillByFatalStrike()); builder.append('\n'); } else { builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append("=0&"); builder.append(getID(VAR_BATTLE_MODE)); builder.append('='); builder.append(getID(VAR_BATTLE_MODE)); builder.append("-1&proc "); builder.append(getID(PROC_SELECT_TARGET_AUTO)); builder.append('\n'); } } else { builder.append(getID(VAR_TEMP)); builder.append('='); if (battle.isDifferenceIsDamage()) { builder.append(getID(VAR_ATTACK_VALUE)); } else { builder.append(getID(VAR_DAMAGE_VALUE)); } builder.append('&'); if (printResult) { builder.append("p "); builder.append(appMessages.urqBattleFatalStrike(getID(VAR_TEMP),BEFORE_PARAM,AFTER_PARAM)); builder.append("#$&if "); builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append("<=0 then p "); builder.append(appConstants.urqKilled()); builder.append('\n'); } else { builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append('='); builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append('-'); builder.append(getID(VAR_TEMP)); //is alive? builder.append("&if "); builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append("<=0 then "); builder.append(getID(VAR_BATTLE_MODE)); builder.append('='); builder.append(getID(VAR_BATTLE_MODE)); builder.append("-1&proc "); builder.append(getID(PROC_SELECT_TARGET_AUTO)); builder.append('\n'); } } } builder.append("if "); if (battle.getFatal() != Battle.FATAL_NONE) { builder.append(getID(VAR_FATAL)); builder.append("=0 and "); } builder.append(getID(VAR_ATTACK_VALUE)); builder.append('>'); if (battle.isAttackDefense()) { builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_DEFENSE_VALUE)); } else { builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_ATTACK_VALUE)); } builder.append(" then "); builder.append(getID(VAR_TEMP)); builder.append('='); if (battle.isDifferenceIsDamage()) { builder.append(getID(VAR_ATTACK_VALUE)); builder.append('-'); if (battle.isAttackDefense()) { builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_DEFENSE_VALUE)); } else { builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_ATTACK_VALUE)); } } else { builder.append(getID(VAR_DAMAGE_VALUE)); } if (printResult) { builder.append("&if "); builder.append(getID(VAR_TEMP)); builder.append(">0 then p "); builder.append(appMessages.urqBattleRoundDamage(getID(VAR_TEMP),BEFORE_PARAM,AFTER_PARAM)); builder.append("#$&if "); builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append("<=0 then p "); builder.append(appConstants.urqKilled()); builder.append('\n'); } else { builder.append('&'); builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append('='); builder.append(getID(VAR_ENEMY_PREFIX,enemyCounter,VAR_PARAMETER_PREFIX,battle.getVital().getId())); builder.append('-'); builder.append(getID(VAR_TEMP)); builder.append('&'); //is still alive builder.append(getID(VAR_CURRENT_ENEMY_TYPE)); builder.append("=1&proc "); builder.append(getID(PROC_CHECK_ENEMY_ALIVE_AND_KILL,enemyCounter)); builder.append('\n'); } } private void addAlchemy(StringBuilder builder, Alchemy alchemy,boolean battle) { builder.append("if "); builder.append(getID(VAR_MUST_GO)); builder.append("=0 and "); builder.append(getID(VAR_BATTLE_MODE)); if (battle) { builder.append(">0"); if (alchemy.isOneTimePerRound()) { builder.append(" and "); builder.append(getID(VAR_ALCHEMY_USED_IN_BATTLE_ROUND)); builder.append("=0"); } if (alchemy.getBattleLimit() != null) { builder.append(" and "); builder.append(getID(VAR_TEMP_PARAMETER_PREFIX,alchemy.getBattleLimit().getId())); builder.append(">0"); } } else { builder.append("=0"); } builder.append(" and "); builder.append(getID(VAR_PARAMETER_PREFIX,alchemy.getFrom().getId())); builder.append(">="); builder.append(alchemy.getFromValue()); builder.append(" and "); builder.append(getID(VAR_ALCHEMY_DISABLED_PREFIX,alchemy.getId())); builder.append("=0 then btn "); builder.append(getID(PROC_USE_ALCEMY,alchemy.getId())); builder.append(','); builder.append(alchemy.getName()); builder.append('\n'); } public ParagraphParsingHandler getParagraphParsingHandler() { return null; } public void appendParagraph(int number,String text,Paragraph paragraph,ArrayList<ParagraphConnection> connections,ArrayList<ParagraphConnection> incomeConnections) { StringBuilder initBuffer=new StringBuilder(); boolean showParams = paragraph==model.getStartParagraph() || (paragraph.getChangeParameters() != null && paragraph.getChangeParameters().size()>0); buffer.append(':'); buffer.append(getID(PARAGRAPH_PREFIX,number)); buffer.append('\n'); //current paragraph number if (paragraph==model.getStartParagraph()) { buffer.append("if "); buffer.append(getID(VAR_CURRENT_PARAGRAPH)); buffer.append("<>"); buffer.append(number); buffer.append(" then proc "); buffer.append(getID(PARAGRAPH_INIT_PREFIX,number)); buffer.append('\n'); initBuffer.append(':'); initBuffer.append(getID(PARAGRAPH_INIT_PREFIX,number)); initBuffer.append("\nperkill\ninvkill\nmusic stop\n"); initBuffer.append("inv+ "); initBuffer.append(appConstants.urqSave()); initBuffer.append('\n'); for (AbstractParameter par : model.getParameters()) { if (par instanceof Parameter) { Parameter parameter = (Parameter) par; if (parameter.isHeroHasInitialValue()) { //initialize this parameter addDiceValue(initBuffer,parameter.getHeroInitialValue(),false); initBuffer.append(getID(VAR_PARAMETER_PREFIX,parameter.getId())); initBuffer.append('='); initBuffer.append(getID(VAR_DICE)); initBuffer.append('\n'); } } } //check for initialized limits for non-initialized parameters for (AbstractParameter par : model.getParameters()) { if (par instanceof Parameter) { Parameter parameter = (Parameter) par; if (parameter.isHeroHasInitialValue()==false && parameter.getLimit() != null && parameter.getLimit().isHeroHasInitialValue()) { //initialize this parameter by limit initBuffer.append(getID(VAR_PARAMETER_PREFIX,parameter.getId())); initBuffer.append('='); initBuffer.append(getID(VAR_PARAMETER_PREFIX,parameter.getLimit().getId())); initBuffer.append('\n'); } } } initBuffer.append("end\n"); } buffer.append(getID(VAR_MUST_GO)); buffer.append("=0\n"); if (model.getSettings().isDisableImages()==false) { // remove all decorators buffer.append("if "); buffer.append(getID(VAR_CLEAN_DECORATORS)); buffer.append(">0 then decordel&"); buffer.append(getID(VAR_CLEAN_DECORATORS)); buffer.append("=0\n"); } if (model.getSettings().isDisableAudio()==false) { if (paragraph.hasBackgroundSounds()) { //set music String url = paragraph.getNextBackgroundSound().getUrl(); if (music.containsKey(url)==false) { music.put(url, music.size()+1); } int idx = music .get(url); buffer.append("if "); buffer.append(getID(VAR_CURRENT_MUSIC)); buffer.append("<>"); buffer.append(idx); buffer.append(" then "); buffer.append(getID(VAR_CURRENT_MUSIC)); buffer.append('='); buffer.append(idx); buffer.append("&music "); buffer.append(url); buffer.append('\n'); } if (paragraph.hasSounds()) { //set music buffer.append("play "); buffer.append(paragraph.getNextSound().getUrl()); buffer.append('\n'); } } if (paragraph.getBattle() != null) { //battle buffer.append("if "); buffer.append(getID(VAR_CURRENT_PARAGRAPH)); buffer.append("<>"); buffer.append(number); buffer.append(" then proc "); buffer.append(getID(PARAGRAPH_INIT_BATTLE_PREFIX,number)); buffer.append('\n'); initBuffer.append(':'); initBuffer.append(getID(PARAGRAPH_INIT_BATTLE_PREFIX,number)); initBuffer.append('\n'); initBuffer.append(getID(VAR_ALCHEMY_USED_IN_BATTLE_ROUND)); initBuffer.append("=0\n"); initBuffer.append(getID(VAR_BATTLE_MODE)); initBuffer.append('='); initBuffer.append(paragraph.getEnemies().size()); initBuffer.append('\n'); initBuffer.append(getID(VAR_HERO_ATTACK_SELECTION)); initBuffer.append("=-1\n"); //add enemies int counter = 0; for (NPCParams npcParams : paragraph.getEnemies()) { NPC npc = npcParams.getNpc(); //type of enemy initBuffer.append(getID(VAR_ENEMY_PREFIX,counter)); initBuffer.append('='); initBuffer.append(npc.getId()); initBuffer.append('\n'); for (Parameter parameter : npc.getValues().keySet()) { int val = npc.getValues().get(parameter); if (val==0) { continue; } if (parameter.isVital() || paragraph.getBattle().dependsOn(parameter)) { initBuffer.append(getID(VAR_ENEMY_PREFIX,counter,VAR_PARAMETER_PREFIX,parameter.getId())); initBuffer.append('='); initBuffer.append(val); initBuffer.append('\n'); } } counter++; } //remember parameters for limits of alchemy for (Parameter parameter : battleAlchemyLimits) { initBuffer.append(getID(VAR_TEMP_PARAMETER_PREFIX,parameter.getId())); initBuffer.append('='); initBuffer.append(getID(VAR_PARAMETER_PREFIX,parameter.getId())); initBuffer.append('\n'); } initBuffer.append("proc "); initBuffer.append(getID(PROC_SELECT_TARGET_AUTO)); initBuffer.append("\nend\n"); //battle rounds counter = 0; for (NPCParams npcParams : paragraph.getEnemies()) { NPC npc = npcParams.getNpc(); //Hero attacks Enemies buffer.append("if "); buffer.append(getID(VAR_HERO_ATTACK_SELECTION)); buffer.append('='); buffer.append(counter); buffer.append(" and "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 then proc "); buffer.append(getProcBattleCaclulation(initBuffer,paragraph.getBattle(),counter,true,false)); buffer.append('\n'); //Enemies attack Hero buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append("=0\nif "); buffer.append(getID(VAR_HERO_ATTACK_SELECTION)); buffer.append(">=0 and "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 then "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append('='); buffer.append(npc.getId()); buffer.append("&proc "); buffer.append(getID(PROC_CHECK_ENEMY_ALIVE,counter)); buffer.append('\n'); //is alive? buffer.append("if "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append(">0 then proc "); buffer.append(getProcBattleCaclulation(initBuffer,paragraph.getBattle(),counter, false,false)); buffer.append('\n'); counter++; } } else { //peace buffer.append(getID(VAR_BATTLE_MODE)); buffer.append("=0\n"); } //select any connection by default //no preselected connection buffer.append(getID(VAR_CAN_GO)); buffer.append("=0\n"); if (alchemyPresent) { buffer.append("proc "); buffer.append(getID(PROC_ENABLE_ALCEMY)); buffer.append('\n'); if (paragraph.getAlchemy() != null) { for (Alchemy alchemy : paragraph.getAlchemy().keySet()) { boolean value = paragraph.getAlchemy().get(alchemy); if (value==false) { //disable alchemy buffer.append(getID(VAR_ALCHEMY_DISABLED_PREFIX,alchemy.getId())); buffer.append("=1\n"); } } } } StringBuilder builder = new StringBuilder(); if (paragraph.getChangeParameters() != null && paragraph.getChangeParameters().size()>0) { for (Parameter parameter : paragraph.getChangeParameters().keySet()) { ParametersCalculation calculation = paragraph.getChangeParameters().get(parameter); addCalculationProc(builder,calculation,VAR_PARAMETER_PREFIX); if (model.getSettings().isOverflowControl() ^ calculation.isOverflowControl()) { if (parameter.getLimit() != null) { //control limits builder.append("&if "); builder.append(getID(VAR_PARAMETER_PREFIX,parameter.getLimit().getId())); builder.append('<'); builder.append(getID(VAR_CALCULATION)); builder.append(" then "); builder.append(getID(VAR_CALCULATION)); builder.append('='); builder.append(getID(VAR_PARAMETER_PREFIX,parameter.getLimit().getId())); builder.append('\n'); } } builder.append(getID(VAR_PARAMETER_PREFIX,parameter.getId())); builder.append('='); builder.append(getID(VAR_CALCULATION)); builder.append('\n'); if (parameter.isNegative()==false) { builder.append("if "); builder.append(getID(VAR_PARAMETER_PREFIX,parameter.getId())); builder.append("<=0 then "); builder.append(getID(VAR_PARAMETER_PREFIX,parameter.getId())); builder.append("=0\n"); } } } if (paragraph.getChangeModificators() != null) { for (Modificator modificator : paragraph.getChangeModificators().keySet()) { boolean value = paragraph.getChangeModificators().get(modificator); builder.append(getID(VAR_MODIFICATOR_PREFIX,modificator.getId())); builder.append('='); if (value) { builder.append(VALUE_MODIFICATOR_SET); } else { builder.append(VALUE_MODIFICATOR_NOT_SET); } builder.append('\n'); } } if (paragraph.getGotObjects().isEmpty()==false) { for (ObjectBean bean : paragraph.getGotObjects()) { String name= objects.get(bean); builder.append("if not "); builder.append(name); builder.append(" then inv+ "); builder.append(name); builder.append('\n'); } } if (paragraph.getLostObjects().isEmpty()==false) { for (ObjectBean bean : paragraph.getLostObjects()) { String name= objects.get(bean); builder.append("if "); builder.append(name); builder.append(" then inv- "); builder.append(name); builder.append('\n'); } } if (builder.length()>0) { buffer.append("if "); buffer.append(getID(VAR_CURRENT_PARAGRAPH)); buffer.append("<>"); buffer.append(number); buffer.append(" then proc "); buffer.append(getID(PARAGRAPH_APPLY_PREFIX,number)); buffer.append('\n'); initBuffer.append(':'); initBuffer.append(getID(PARAGRAPH_APPLY_PREFIX,number)); initBuffer.append('\n'); initBuffer.append(builder.toString()); initBuffer.append("end\n"); } if (model.getSettings().isDisableImages()==false) { //clear text for FireURQ sprites buffer.append("if "); buffer.append(getID(VAR_MUST_GO)); buffer.append("=0 then cls\n"); } //add top image if (model.getSettings().isDisableImages()==false && paragraph.hasTopImages()) { //show images if (paragraph.hasSprites()) { //use decorators buffer.append("if "); buffer.append(getID(VAR_MUST_GO)); buffer.append("=0 then "); buffer.append(getID(VAR_CLEAN_DECORATORS)); buffer.append("=1&image "); buffer.append(paragraph.getNextTopImage().getUrl()); List<Sprite> list = paragraph.getSprites(); buffer.append('\n'); int i=1; for (Sprite sprite : list) { buffer.append("if "); buffer.append(getID(VAR_MUST_GO)); buffer.append("=0 then decoradd sprite"); buffer.append(i++); buffer.append(" ("); buffer.append(20+sprite.getX()); buffer.append(','); buffer.append(55+sprite.getY()); buffer.append(",-1) IMAGE \""); buffer.append(sprite.getPicture().getUrl()); buffer.append("\"\n"); } buffer.append("pln \n"); } else { buffer.append("if "); buffer.append(getID(VAR_MUST_GO)); buffer.append("=0 then textalign=3&image "); buffer.append(paragraph.getNextTopImage().getUrl()); buffer.append("\ntextalign=1\n"); } } //add text of paragraph println(text); if (paragraph.getBattle() != null) { //battle name buffer.append("if "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 then pln &"); println(paragraph.getBattle().getName()); } if (showParams==false && hasParameters) { //show parameters for second entry buffer.append("if "); buffer.append(getID(VAR_CURRENT_PARAGRAPH)); buffer.append('='); buffer.append(number); buffer.append(" then proc "); buffer.append(getID(PROC_SHOW_PARAMS)); buffer.append('\n'); } if (paragraph.getBattle() != null) { //hero round calculation buffer.append("if "); buffer.append(getID(VAR_HERO_ATTACK_SELECTION)); buffer.append(">=0 then p "); buffer.append(appConstants.urqHeroAttack()); buffer.append('#'); buffer.append(getID(VAR_ATTACK_VALUE)); buffer.append('$'); if (paragraph.getBattle().isAttackDefense()) { buffer.append(' '); buffer.append(appConstants.urqHeroDefense()); buffer.append('#'); buffer.append(getID(VAR_DEFENSE_VALUE)); buffer.append('$'); } buffer.append('\n'); int counter = 0; for (@SuppressWarnings("unused") NPCParams npcParams : paragraph.getEnemies()) { NPC npc = npcParams.getNpc(); buffer.append("if "); buffer.append(getID(VAR_HERO_ATTACK_SELECTION)); buffer.append('='); buffer.append(counter); buffer.append(" then proc "); buffer.append(getProcBattleCaclulation(initBuffer,paragraph.getBattle(),counter, true,true)); buffer.append('\n'); // addBattleCalculation(buffer, paragraph.getBattle(),counter, true,true); counter++; } //end of line for hero params buffer.append("if "); buffer.append(getID(VAR_CURRENT_PARAGRAPH)); buffer.append('='); buffer.append(number); buffer.append(" then pln \n"); counter = 0; for (NPCParams npcParams : paragraph.getEnemies()) { NPC npc = npcParams.getNpc(); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append("=0\nif "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 then "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append('='); buffer.append(npc.getId()); buffer.append("&proc "); buffer.append(getID(PROC_CHECK_ENEMY_ALIVE,counter)); buffer.append("\nif "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append(">0 then p #/$&proc "); //alive!!! buffer.append(getID(PROC_SHOW_ENEMY_SELECTION,counter)); buffer.append("\nif "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append(">0 then proc "); buffer.append(getID(PROC_SHOW_ENEMY_NAME)); buffer.append("\nif "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append(">0 then proc "); buffer.append(getID(PROC_SHOW_ENEMY_PARAMS,counter)); buffer.append("\nif "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append(">0 and "); buffer.append(getID(VAR_HERO_ATTACK_SELECTION)); buffer.append(">=0 then p "); //print attack/defense parameters buffer.append(appConstants.urqHeroAttack()); buffer.append('#'); buffer.append(getID(VAR_ENEMY_PREFIX,counter,VAR_ATTACK_VALUE)); buffer.append("$#$"); if (paragraph.getBattle().isAttackDefense()) { buffer.append(appConstants.urqHeroDefense()); buffer.append('#'); buffer.append(getID(VAR_ENEMY_PREFIX,counter,VAR_DEFENSE_VALUE)); buffer.append("$#$"); } buffer.append("\nif "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append(">0 and "); buffer.append(getID(VAR_HERO_ATTACK_SELECTION)); buffer.append(">=0 then proc "); buffer.append(getProcBattleCaclulation(initBuffer,paragraph.getBattle(),counter, false,true)); buffer.append("\nif "); buffer.append(getID(VAR_CURRENT_ENEMY_TYPE)); buffer.append(">0 and "); buffer.append(getID(VAR_HERO_ATTACK_SELECTION)); buffer.append(">=0 then pln \n"); // addBattleCalculation(buffer, paragraph.getBattle(),counter, false,true); counter++; } //clear selected target buffer.append(getID(VAR_HERO_ATTACK_SELECTION)); buffer.append("=-1\n"); //calculate Attack-Defense-Damage for next round addCalculationProc(buffer, paragraph.getBattle().getAttack(), VAR_PARAMETER_PREFIX); buffer.append('\n'); buffer.append(getID(VAR_ATTACK_VALUE)); buffer.append('='); buffer.append(getID(VAR_CALCULATION)); buffer.append('\n'); if (paragraph.getBattle().getFatal() != Battle.FATAL_NONE) { //fatal strike buffer.append(getID(VAR_FATAL)); buffer.append("=0\nif "); buffer.append(getID(VAR_DICE_MAX)); buffer.append("=1 then "); buffer.append(getID(VAR_FATAL)); buffer.append("=1\n"); } if (paragraph.getBattle().isAttackDefense()) { addCalculationProc(buffer, paragraph.getBattle().getDefense(), VAR_PARAMETER_PREFIX); buffer.append('\n'); buffer.append(getID(VAR_DEFENSE_VALUE)); buffer.append('='); buffer.append(getID(VAR_CALCULATION)); buffer.append('\n'); } if (paragraph.getBattle().isDifferenceIsDamage()==false) { addCalculationProc(buffer, paragraph.getBattle().getDamage(), VAR_PARAMETER_PREFIX); buffer.append('\n'); buffer.append(getID(VAR_DAMAGE_VALUE)); buffer.append('='); buffer.append(getID(VAR_CALCULATION)); buffer.append('\n'); } } if (model.getSettings().isDisableImages()==false && paragraph.hasBottomImages()) { //show images buffer.append("if "); buffer.append(getID(VAR_MUST_GO)); buffer.append("=0 then textalign=3&image "); buffer.append(paragraph.getNextBottomImage().getUrl()); buffer.append("\ntextalign=1\n"); } buffer.append(getID(VAR_CURRENT_PARAGRAPH)); buffer.append('='); buffer.append(number); buffer.append('\n'); //check vital parameters if (vitals.isEmpty()==false) { buffer.append("proc "); buffer.append(getID(PROC_VITAL)); buffer.append('\n'); } //add connections ArrayList<ParagraphAction> list = paragraphActions.get(paragraph); if (list == null || list.isEmpty()) { //final paragraph if (paragraph.isSuccess()) { //link to our site } else { addButton(model.getStartParagraph(),appConstants.playerTitleRestartGame()); } } else { for (ParagraphAction action : list) { if (action.getConnection().getStrictness()==ParagraphConnection.STRICTNESS_MUST) { //must go switch (action.getConnection().getType()) { case ParagraphConnection.TYPE_NORMAL: addNonBattleControl(paragraph); if (action.getConnection().isConditional()) { addMustGoCondition(action.getObjectVar(),null,action.getConnection().getTo().getNumber()); } else { buffer.append("cls&goto "); buffer.append(getID(PARAGRAPH_PREFIX,action.getConnection().getTo().getNumber())); buffer.append('\n'); } break; case ParagraphConnection.TYPE_MODIFICATOR: addNonBattleControl(paragraph); addMustGoCondition(action.getModificatorVar(),VALUE_MODIFICATOR_SET,action.getConnection().getTo().getNumber()); break; case ParagraphConnection.TYPE_NO_MODIFICATOR: addNonBattleControl(paragraph); addMustGoCondition(action.getModificatorVar(),VALUE_MODIFICATOR_NOT_SET,action.getConnection().getTo().getNumber()); break; case ParagraphConnection.TYPE_PARAMETER_LESS: addNonBattleControl(paragraph); addDiceValue(buffer, action.getConnection().getParameterValue(),true); buffer.append('\n'); addNonBattleControl(paragraph); builder = new StringBuilder(action.getParameterVar()); builder.append('<'); builder.append(getID(VAR_DICE)); addMustGoCondition(builder.toString(),null,action.getConnection().getTo().getNumber()); break; case ParagraphConnection.TYPE_PARAMETER_MORE: addNonBattleControl(paragraph); addDiceValue(buffer, action.getConnection().getParameterValue(),true); buffer.append('\n'); addNonBattleControl(paragraph); StringBuilder builder2 = new StringBuilder(action.getParameterVar()); builder2.append('>'); builder2.append(getID(VAR_DICE)); addMustGoCondition(builder2.toString(),null,action.getConnection().getTo().getNumber()); break; case ParagraphConnection.TYPE_ENEMY_VITAL_LESS: buffer.append("if "); buffer.append(getID(VAR_CAN_GO)); buffer.append("=0 and "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 then "); addDiceValue(buffer, action.getConnection().getParameterValue(),true); buffer.append("\nif "); buffer.append(getID(VAR_CAN_GO)); buffer.append("=0 and "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 then "); buffer.append(getID(VAR_ENEMY_VITAL)); buffer.append('='); buffer.append(getID(VAR_DICE)); buffer.append("&if "); int counter=0; for (@SuppressWarnings("unused") NPCParams npcParams : paragraph.getEnemies()) { NPC npc = npcParams.getNpc(); if (counter>0) { buffer.append(" or "); } buffer.append(getID(VAR_ENEMY_PREFIX,counter,VAR_PARAMETER_PREFIX,paragraph.getBattle().getVital().getId())); buffer.append('<'); buffer.append(getID(VAR_ENEMY_VITAL)); counter++; } buffer.append(" then "); if (model.getSettings().isSkipMustGoParagraphs()) { //go immediately buffer.append("cls&goto "); buffer.append(getID(PARAGRAPH_PREFIX,action.getConnection().getTo().getNumber())); buffer.append('\n'); } else { buffer.append(getID(VAR_CAN_GO)); buffer.append('='); buffer.append(action.getConnection().getTo().getNumber()); buffer.append('&'); buffer.append(getID(VAR_MUST_GO)); buffer.append("=1\n"); } break; case ParagraphConnection.TYPE_VITAL_LESS: buffer.append("if "); buffer.append(getID(VAR_CAN_GO)); buffer.append("=0 and "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 then "); addDiceValue(buffer, action.getConnection().getParameterValue(),true); buffer.append("\nif "); buffer.append(getID(VAR_CAN_GO)); buffer.append("=0 and "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 and "); buffer.append(getID(VAR_PARAMETER_PREFIX,paragraph.getBattle().getVital().getId())); buffer.append('<'); buffer.append(getID(VAR_DICE)); buffer.append(" then "); if (model.getSettings().isSkipMustGoParagraphs()) { //go immediately buffer.append("cls&goto "); buffer.append(getID(PARAGRAPH_PREFIX,action.getConnection().getTo().getNumber())); buffer.append('\n'); } else { buffer.append(getID(VAR_CAN_GO)); buffer.append('='); buffer.append(action.getConnection().getTo().getNumber()); buffer.append('&'); buffer.append(getID(VAR_MUST_GO)); buffer.append("=1\n"); } break; } } } if (paragraph.getBattle() != null) { //battle actions int counter = 0; for (@SuppressWarnings("unused") NPCParams npcParams : paragraph.getEnemies()) { NPC npc = npcParams.getNpc(); // buffer.append("if "); // buffer.append(VAR_BATTLE_MODE); // buffer.append(">0 and "); // buffer.append(VAR_MUST_GO); // buffer.append("=0 then "); // buffer.append(VAR_CURRENT_ENEMY_TYPE); // buffer.append('='); // buffer.append(npc.getId()); // buffer.append("&proc "); // buffer.append(PROC_CHECK_ENEMY_ALIVE); // buffer.append(counter); // buffer.append("&if "); // buffer.append(VAR_CURRENT_ENEMY_TYPE); // buffer.append(">0 then "); String prefix = new StringBuilder(VAR_ENEMY_PREFIX).append(counter).append(VAR_PARAMETER_PREFIX).toString(); if (paragraph.getBattle().isAttackDefense()) { //calculate defense addCalculationProc(buffer, paragraph.getBattle().getDefense(), prefix); buffer.append('\n'); buffer.append(getID(VAR_ENEMY_PREFIX,counter,VAR_DEFENSE_VALUE)); buffer.append('='); buffer.append(getID(VAR_CALCULATION)); buffer.append('\n'); } if (paragraph.getBattle().isDifferenceIsDamage()==false) { addCalculationProc(buffer, paragraph.getBattle().getDamage(), prefix); buffer.append('\n'); buffer.append(getID(VAR_ENEMY_PREFIX,counter,VAR_DAMAGE_VALUE)); buffer.append('='); buffer.append(getID(VAR_CALCULATION)); buffer.append('\n'); } //calculate attack addCalculationProc(buffer, paragraph.getBattle().getAttack(), prefix); buffer.append('\n'); buffer.append(getID(VAR_ENEMY_PREFIX,counter,VAR_ATTACK_VALUE)); buffer.append('='); buffer.append(getID(VAR_CALCULATION)); buffer.append('\n'); if (paragraph.getBattle().getFatal() == Battle.FATAL_NORMAL) { //fatal strike for Hero buffer.append(getID(VAR_ENEMY_PREFIX,counter,VAR_FATAL)); buffer.append("=0\nif "); buffer.append(getID(VAR_DICE_MAX)); buffer.append("=1 then "); buffer.append(getID(VAR_ENEMY_PREFIX,counter,VAR_FATAL)); buffer.append("=1"); buffer.append('\n'); } counter++; } buffer.append("if "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 and "); buffer.append(getID(VAR_MUST_GO)); buffer.append("=0 then btn "); buffer.append(getID(PROC_ATTACK)); buffer.append(','); buffer.append(appConstants.battleAttack()); buffer.append('\n'); if (paragraph.getEnemies().size()>1) { //target selection buffer.append("if "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">1 and "); buffer.append(getID(VAR_MUST_GO)); buffer.append("=0 then btn "); buffer.append(getID(PROC_SELECT_TARGET)); buffer.append(','); buffer.append(appConstants.urqSelectTargetBtn()); buffer.append('\n'); } } for (ParagraphAction action : list) { String title = action.getActionName(); if (action.getConnection().isConditional()) { if (action.getConnection().getStrictness()==ParagraphConnection.STRICTNESS_MUST) { //must go is already checked addButton(action.getTo(),title,true,getID(VAR_CAN_GO),title); } else { //can or must-not switch (action.getConnection().getType()) { case ParagraphConnection.TYPE_NORMAL: addNonBattleControl(paragraph); if (action.getConnection().getStrictness()==ParagraphConnection.STRICTNESS_MUST_NOT) { //must not addButton(action.getTo(),title,true,action.getObjectVar(),"0"); } else { //can addButton(action.getTo(),title,true,action.getObjectVar(),null); } break; case ParagraphConnection.TYPE_MODIFICATOR: addNonBattleControl(paragraph); if (action.getConnection().getStrictness()==ParagraphConnection.STRICTNESS_MUST_NOT) { addButton(action.getTo(),title,true,action.getModificatorVar(),VALUE_MODIFICATOR_NOT_SET); } else { //can addButton(action.getTo(),title,true,action.getModificatorVar(),VALUE_MODIFICATOR_SET); } break; case ParagraphConnection.TYPE_NO_MODIFICATOR: addNonBattleControl(paragraph); if (action.getConnection().getStrictness()==ParagraphConnection.STRICTNESS_MUST_NOT) { addButton(action.getTo(),title,true,action.getModificatorVar(),VALUE_MODIFICATOR_SET); } else { //can addButton(action.getTo(),title,true,action.getModificatorVar(),VALUE_MODIFICATOR_NOT_SET); } break; case ParagraphConnection.TYPE_PARAMETER_LESS: addNonBattleControl(paragraph); addDiceValue(buffer, action.getConnection().getParameterValue(),true); buffer.append('\n'); addNonBattleControl(paragraph); builder = new StringBuilder(action.getParameterVar()); if (action.getConnection().getStrictness()==ParagraphConnection.STRICTNESS_MUST_NOT) { builder.append(">="); } else { //can builder.append("<"); } builder.append(getID(VAR_DICE)); addButton(action.getTo(),title,true,builder.toString(),null); break; case ParagraphConnection.TYPE_PARAMETER_MORE: addNonBattleControl(paragraph); addDiceValue(buffer, action.getConnection().getParameterValue(),true); buffer.append('\n'); addNonBattleControl(paragraph); StringBuilder builder2 = new StringBuilder(action.getParameterVar()); if (action.getConnection().getStrictness()==ParagraphConnection.STRICTNESS_MUST_NOT) { builder2.append("<="); } else { //can builder2.append(">"); } builder2.append(getID(VAR_DICE)); addButton(action.getTo(),title,true,builder2.toString(),null); break; case ParagraphConnection.TYPE_VITAL_LESS: if (action.getConnection().getStrictness()==ParagraphConnection.STRICTNESS_MUST) { //already checked addButton(action.getTo(),title,true,VAR_CAN_GO,String.valueOf(action.getTo().getNumber())); } else { buffer.append("if "); buffer.append(getID(VAR_MUST_GO)); buffer.append("=0 and "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 then "); addDiceValue(buffer, action.getConnection().getParameterValue(),true); buffer.append("\nif "); buffer.append(getID(VAR_MUST_GO)); buffer.append("=0 and "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 and "); buffer.append(getID(VAR_PARAMETER_PREFIX,paragraph.getBattle().getVital().getId())); if (action.getConnection().getStrictness()==ParagraphConnection.STRICTNESS_CAN) { buffer.append('<'); } else { buffer.append(">="); } buffer.append(getID(VAR_DICE)); buffer.append(" then btn "); buffer.append(getID(PARAGRAPH_PREFIX,action.getConnection().getTo().getNumber())); buffer.append(','); buffer.append(title); buffer.append('\n'); } break; case ParagraphConnection.TYPE_ENEMY_VITAL_LESS: if (action.getConnection().getStrictness()==ParagraphConnection.STRICTNESS_MUST) { //already checked addButton(action.getTo(),title,true,VAR_CAN_GO,String.valueOf(action.getTo().getNumber())); } else { buffer.append("if "); buffer.append(getID(VAR_MUST_GO)); buffer.append("=0 and "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 then "); addDiceValue(buffer, action.getConnection().getParameterValue(),true); buffer.append("\nif "); buffer.append(getID(VAR_MUST_GO)); buffer.append("=0 and "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 then "); buffer.append(getID(VAR_ENEMY_VITAL)); buffer.append('='); buffer.append(getID(VAR_DICE)); buffer.append("&if "); int counter=0; for (@SuppressWarnings("unused") NPCParams npcParams : paragraph.getEnemies()) { NPC npc = npcParams.getNpc(); if (counter>0) { buffer.append(" or "); } buffer.append(getID(VAR_ENEMY_PREFIX,counter,VAR_PARAMETER_PREFIX,paragraph.getBattle().getVital().getId())); if (action.getConnection().getStrictness()==ParagraphConnection.STRICTNESS_CAN) { buffer.append('<'); } else { buffer.append(">="); } buffer.append(getID(VAR_ENEMY_VITAL)); counter++; } buffer.append(" then btn "); buffer.append(getID(PARAGRAPH_PREFIX,action.getConnection().getTo().getNumber())); buffer.append(','); buffer.append(title); buffer.append('\n'); } break; } } } else { addNonBattleControl(paragraph); addButton(action.getTo(),title,true); } } } if (paragraph.getAlchemy() != null) { for (Alchemy alchemy : paragraph.getAlchemy().keySet()) { if (paragraph.getAlchemy().get(alchemy)) { //enable this alchemy if (alchemy.getPlace() != Alchemy.PLACE_PEACE && paragraph.getBattle() != null) { //can be used in the battle addAlchemy(buffer, alchemy,true); } addAlchemy(buffer, alchemy,false); } } } if (alchemyBattlePresent && paragraph.getBattle() != null ) { //add battle alchemy buffer.append("if "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append(">0 then proc "); buffer.append(getID(PROC_ADD_BATTLE_ALCHEMY)); buffer.append('\n'); } if (alchemyPeacePresent) { //add peace alchemy if (paragraph.getBattle() != null) { buffer.append("if "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append("=0 then "); } buffer.append("proc "); buffer.append(getID(PROC_ADD_PEACE_ALCHEMY)); buffer.append('\n'); } if (showParams && hasParameters) { buffer.append("proc "); buffer.append(getID(PROC_SHOW_PARAMS)); buffer.append('\n'); } buffer.append("end\n\n"); if (initBuffer.length()>0) { buffer.append(initBuffer.toString()); } } private String getProcBattleCaclulation(StringBuilder builder, Battle battle, int counter, boolean hero, boolean print) { String procId = getID(PROC_BATTLE,battle.getId(),'_',counter,hero ? 't':'f',print ? 't':'f'); if (battleSet.contains(procId)==false) { battleSet.add(procId); builder.append(':'); builder.append(procId); builder.append('\n'); addBattleCalculation(builder, battle,counter, hero,print); builder.append("end\n"); } return procId; } private void addNonBattleControl(Paragraph paragraph) { if (paragraph.getBattle() != null) { buffer.append("if "); buffer.append(getID(VAR_BATTLE_MODE)); buffer.append("=0 then "); } } private void addCalculationProc(StringBuilder builder, ParametersCalculation calculation, String prefix) { boolean next; if (calculation.getConstant().isZero()) { builder.append(getID(VAR_CALCULATION)); builder.append('='); next=false; } else { addDiceValue(builder,calculation.getConstant(),false); builder.append(getID(VAR_CALCULATION)); builder.append('='); builder.append(getID(VAR_DICE)); next=true; } if (calculation.getParameters().isEmpty()==false) { for (Parameter parameter : calculation.getParameters().keySet()) { int value = calculation.getParameters().get(parameter); if (value==1) { if (next) { builder.append('+'); } } else if (value==-1){ builder.append('-'); } else if (value>0) { if (next) { builder.append('+'); } builder.append(value); builder.append('*'); } else { builder.append('-'); builder.append(value); builder.append('*'); } builder.append(getID(prefix,parameter.getId())); next = true; } } builder.append('\n'); } private void addDiceValue(StringBuilder builder, DiceValue value,boolean inLine) { builder.append(getID(VAR_DICE)); builder.append('='); if (value.getConstant() == 0) { builder.append('0'); } else { builder.append(value.getConstant()); } if (value.isNoDice()==false) { if (inLine) { builder.append('&'); } else { builder.append('\n'); } builder.append("proc "); builder.append(getDiceValueProc(value)); } if (inLine==false) { builder.append('\n'); } } private String getDiceValueProc(DiceValue value) { String key = value.getDiceStr(); String proc = diceProces.get(key); if (proc!=null) { return proc; } proc = getID("dice"+String.valueOf(diceProces.size())); diceProces.put(key, proc); diceBuffer.append(':').append(proc).append('\n'); diceBuffer.append(getID(VAR_DICE_MAX)).append("=0\n"); int max = Math.abs(value.getN()); diceBuffer.append(getID(VAR_DICE)); diceBuffer.append('='); diceBuffer.append(getID(VAR_DICE)); if (value.getN()<0) { diceBuffer.append('-'); } else { diceBuffer.append('+'); } diceBuffer.append(max); diceBuffer.append('\n'); //dice + constant for (int i = 0; i < max; i++) { diceBuffer.append(getID(VAR_DICE_TEMP)); diceBuffer.append('='); diceBuffer.append("rnd*"); diceBuffer.append(value.getSize()); diceBuffer.append('\n'); for (int j = 1; j < value.getSize(); j++) { diceBuffer.append("if "); diceBuffer.append(getID(VAR_DICE_TEMP)); diceBuffer.append('>'); diceBuffer.append(j); diceBuffer.append(" then "); diceBuffer.append(getID(VAR_DICE)); diceBuffer.append('='); diceBuffer.append(getID(VAR_DICE)); if (value.getN()>0) { diceBuffer.append('+'); } else { diceBuffer.append('-'); } diceBuffer.append("1\n"); } } diceBuffer.append("if "); diceBuffer.append(getID(VAR_DICE)); diceBuffer.append('='); diceBuffer.append(value.getSize()*max); diceBuffer.append(" then "); diceBuffer.append(getID(VAR_DICE_MAX)); diceBuffer.append("=1\nend\n"); return proc; } private void addMustGoCondition(String variable, String value, int go) { buffer.append("if "); buffer.append(getID(VAR_MUST_GO)); buffer.append("=0 and "); buffer.append(variable); if (value != null) { buffer.append('='); buffer.append(value); } buffer.append(" then "); if (model.getSettings().isSkipMustGoParagraphs()) { buffer.append("cls&goto "); buffer.append(getID(PARAGRAPH_PREFIX,go)); } else { buffer.append(getID(VAR_MUST_GO)); buffer.append("=1&"); buffer.append(getID(VAR_CAN_GO)); buffer.append('='); buffer.append(go); } buffer.append('\n'); } private void addButton(Paragraph paragraph,String title) { addButton(paragraph,title,false,null,null); } private void addButton(Paragraph paragraph,String title,boolean checkMustGo) { addButton(paragraph,title,checkMustGo,null,null); } private void addButton(Paragraph paragraph,String title,boolean checkMustGo,String variable,String value) { if (checkMustGo) { buffer.append("if "); if (getID(VAR_CAN_GO).equals(variable)) { buffer.append(getID(VAR_CAN_GO)); buffer.append('='); buffer.append(paragraph.getNumber()); } else { buffer.append(getID(VAR_MUST_GO)); buffer.append("=0"); if (variable != null) { buffer.append(" and "); buffer.append(variable); if (value != null) { buffer.append('='); buffer.append(value); } buffer.append(" or "); buffer.append(getID(VAR_CAN_GO)); buffer.append('='); buffer.append(paragraph.getNumber()); } } buffer.append(" then "); } buffer.append("btn "); buffer.append(getID(PARAGRAPH_PREFIX,paragraph.getNumber())); buffer.append(','); buffer.append(title); buffer.append('\n'); } public String decorateNumber(int number,Paragraph from,Paragraph to, ParagraphConnection connection) { ArrayList<ParagraphAction> list = paragraphActions.get(from); if (list==null) { list = new ArrayList<ParagraphAction>(); paragraphActions.put(from, list); } ParagraphAction action = new ParagraphAction(from,to,connection,list.size()+1); list.add(action); return appMessages.urqButtonAction(action.getId()); } public void setStartParagraph(Paragraph paragraph) { //already set } public void endBook() { //add dice calculation procedures buffer.append(diceBuffer.toString()); } public void startBook() { } public byte[] toBytes() { try { return buffer.toString().replace("\r\n", "\n").replace("\n", "\r\n").getBytes(ENCODING); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } public void addGreeting(Greeting greeting) { buffer.append("pln \n"); println(greeting.getName()); if (greeting.getUrl() != null && greeting.getUrl().length()>0) { println(greeting.getUrl()); } if (greeting.getText() != null && greeting.getText().length()>0) { println(greeting.getText()); } } public void endGreeting() { buffer.append("end\n"); } public void startGreeting() { buffer.append(':'); buffer.append(getID(PROC_GREETINGS)); buffer.append('\n'); println(appConstants.urqGreetings()); } public boolean isPlayerMode() { return true; } public boolean isHideAbsoluteModificators() { return false; } }