+# Version 1.6
+
+Fix bug where player can start battle with self.
+
+Change config to use ".toml" instead of ".xml".
+
+Change how battle info text is displayed.
+
# Version 1.5
Fix proper consumption of food/potion items in battle.
}\r
dependencies {\r
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'\r
+ classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.1'\r
}\r
}\r
apply plugin: 'net.minecraftforge.gradle.forge'\r
-//Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.\r
+apply plugin: 'com.github.johnrengelman.shadow'\r
\r
-version = "1.5"\r
-group = "com.seodisparate.TurnBasedMinecraft" // http://maven.apache.org/guides/mini/guide-naming-conventions.html\r
+version = "1.6"\r
+group = "com.seodisparate.TurnBasedMinecraft"\r
archivesBaseName = "TurnBasedMinecraft"\r
\r
sourceCompatibility = targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.\r
// or you may define them like so..\r
//compile "some.group:artifact:version:classifier"\r
//compile "some.group:artifact:version"\r
+ compile "net.consensys.cava:cava-toml:0.3.1"\r
\r
// real examples\r
//compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env\r
exclude 'mcmod.info'\r
}\r
}\r
+\r
+shadowJar {\r
+ classifier ""\r
+\r
+ relocate 'net.consensys.cava', 'shadow.turnbasedmc.net.consensys.cava'\r
+ relocate 'org.antlr.v4', 'shadow.turnbasedmc.org.antlr.v4'\r
+ relocate 'javax.annotation', 'shadow.turnbasedmc.javax.annotation'\r
+}\r
+\r
+reobf { shadowJar { mappingType = "SEARGE" } }\r
+tasks.reobfShadowJar.mustRunAfter shadowJar\r
import net.minecraft.client.settings.GameSettings;
import net.minecraft.entity.Entity;
import net.minecraft.util.SoundCategory;
+import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
+import net.minecraft.util.text.TextFormatting;
public class ClientProxy extends CommonProxy
{
@Override
public void displayString(String message)
{
- Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(message));
+ ITextComponent prefix = new TextComponentString("TBM: ");
+ prefix.getStyle().setColor(TextFormatting.GREEN).setBold(true);
+ ITextComponent text = new TextComponentString(message);
+ prefix.appendSibling(text);
+ text.getStyle().setColor(TextFormatting.WHITE).setBold(false);
+ Minecraft.getMinecraft().player.sendMessage(prefix);
}
@Override
public class AttackerViaBow
{
public static long ATTACK_TIMEOUT = 10000000000L;
-
+
public Entity entity;
public long attackTime;
public int battleID;
-
+
public AttackerViaBow()
{
entity = null;
attackTime = 0;
battleID = -1;
}
-
+
public AttackerViaBow(Entity entity, int battleID)
{
this.entity = entity;
package com.seodisparate.TurnBasedMinecraft.common;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
+import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
-import javax.xml.stream.FactoryConfigurationError;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
-
+import net.consensys.cava.toml.*;
import org.apache.logging.log4j.Logger;
public class Config
private int playerEvasion = 10;
private int defenseDuration = 1;
private int fleeGoodProbability = 90;
- private int fleeBadProbability = 40;
- private int minimumHitPercentage = 1;
+ private int fleeBadProbability = 35;
+ private int minimumHitPercentage = 4;
private int maxInBattle = 8;
private Set<String> musicBattleTypes;
private Set<String> musicSillyTypes;
private boolean oldBattleBehaviorEnabled = false;
private int leaveBattleCooldownSeconds = 5;
private int aggroStartBattleDistance = 8;
-
+
public Config(Logger logger)
{
entityInfoMap = new HashMap<String, EntityInfo>();
musicBattleTypes = new HashSet<String>();
musicSillyTypes = new HashSet<String>();
battleIgnoringPlayers = new HashSet<Integer>();
-
- int internalVersion = 0;
- try
- {
- InputStream is = getClass().getResourceAsStream(TurnBasedMinecraftMod.CONFIG_INTERNAL_PATH);
- if(is == null)
- {
- logger.error("Internal resource is null");
- }
- else
- {
- internalVersion = getConfigFileVersion(is);
- }
- } catch (Throwable t) {}
-
+
+ int internalVersion = getConfigFileVersion(getClass().getResourceAsStream(TurnBasedMinecraftMod.CONFIG_INTERNAL_PATH));
+
if(internalVersion == 0)
{
logger.error("Failed to check version of internal config file");
{
configVersion = internalVersion;
}
-
+
try
{
File testLoad = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH);
{
logger.error("Failed to check/create-new config file");
}
-
- // parse xml
+
+ // parse config
File configFile = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH);
if(!configFile.exists() || !configFile.canRead())
{
logger.error("Failed to read/parse config file " + TurnBasedMinecraftMod.CONFIG_FILE_PATH);
return;
}
-
+
int configVersion = getConfigFileVersion(configFile);
if(configVersion < this.configVersion)
{
logger.error("Failed to parse config file!");
}
}
-
+
private void writeConfig() throws IOException
{
File configFile = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH);
configStream.close();
configOutput.close();
}
-
+
private void moveOldConfig()
{
File configFile = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH);
configFile.renameTo(new File(TurnBasedMinecraftMod.CONFIG_DIRECTORY
+ "TBM_Config_"
+ DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(LocalDateTime.now())
- + ".xml"));
+ + ".toml"));
}
}
-
- private boolean parseConfig(File configFile) throws XMLStreamException, FactoryConfigurationError, IOException
+
+ private boolean parseConfig(File configFile) throws IOException
{
- FileInputStream fis = new FileInputStream(configFile);
- XMLStreamReader xmlReader = XMLInputFactory.newInstance().createXMLStreamReader(fis);
- while(xmlReader.hasNext())
+ TomlParseResult parseResult = Toml.parse(configFile.toPath(), TomlVersion.V0_5_0);
+
+ // client_config
+ {
+ TomlArray battleMusicCategories = parseResult.getArray("client_config.battle_music");
+ if(battleMusicCategories != null)
+ {
+ for (int i = 0; i < battleMusicCategories.size(); ++i)
+ {
+ musicBattleTypes.add(battleMusicCategories.getString(i));
+ }
+ }
+ else
+ {
+ musicBattleTypes.add("monster");
+ musicBattleTypes.add("animal");
+ musicBattleTypes.add("boss");
+ musicBattleTypes.add("player");
+ logNotFound("client_config.battle_music");
+ }
+ }
+ {
+ TomlArray sillyMusicCategories = parseResult.getArray("client_config.silly_music");
+ if(sillyMusicCategories != null)
+ {
+ for (int i = 0; i < sillyMusicCategories.size(); ++i)
+ {
+ musicSillyTypes.add(sillyMusicCategories.getString(i));
+ }
+ }
+ else
+ {
+ musicSillyTypes.add("passive");
+ logNotFound("client_config.silly_music");
+ }
+ }
+
+ try
+ {
+ sillyMusicThreshold = parseResult.getLong("client_config.silly_music_threshold").intValue();
+ }
+ catch (NullPointerException e)
+ {
+ sillyMusicThreshold = 40;
+ logNotFound("client_config.silly_music_threshold", "40");
+ }
+
+ // server_config
+ try
+ {
+ leaveBattleCooldownSeconds = parseResult.getLong("server_config.leave_battle_cooldown").intValue();
+ if (leaveBattleCooldownSeconds < 1)
+ {
+ leaveBattleCooldownSeconds = 1;
+ } else if (leaveBattleCooldownSeconds > 10)
+ {
+ leaveBattleCooldownSeconds = 10;
+ }
+ }
+ catch (NullPointerException e)
+ {
+ leaveBattleCooldownSeconds = 5;
+ logNotFound("server_config.leave_battle_cooldown", "5");
+ }
+
+ try
+ {
+ aggroStartBattleDistance = parseResult.getLong("server_config.aggro_start_battle_max_distance").intValue();
+ if (aggroStartBattleDistance < 5)
+ {
+ aggroStartBattleDistance = 5;
+ } else if (aggroStartBattleDistance > 50)
+ {
+ aggroStartBattleDistance = 50;
+ }
+ }
+ catch (NullPointerException e)
+ {
+ aggroStartBattleDistance = 8;
+ logNotFound("server_config.aggro_start_battle_max_distance", "8");
+ }
+
+ try
+ {
+ oldBattleBehaviorEnabled = parseResult.getBoolean("server_config.old_battle_behavior");
+ }
+ catch (NullPointerException e)
+ {
+ oldBattleBehaviorEnabled = false;
+ logNotFound("server_config.old_battle_behavior", "false");
+ }
+
+ try
+ {
+ onlyOPsSelfDisableTB = !parseResult.getBoolean("server_config.anyone_can_disable_tbm_for_self");
+ }
+ catch (NullPointerException e)
+ {
+ onlyOPsSelfDisableTB = true;
+ logNotFound("server_config.anyone_can_disable_tbm_for_self", "false");
+ }
+
+ try
+ {
+ maxInBattle = parseResult.getLong("server_config.max_in_battle").intValue();
+ if (maxInBattle < 2)
+ {
+ maxInBattle = 2;
+ }
+ }
+ catch (NullPointerException e)
+ {
+ maxInBattle = 8;
+ logNotFound("server_config.max_in_battle", "8");
+ }
+
+ try
+ {
+ freezeCombatantsInBattle = parseResult.getBoolean("server_config.freeze_battle_combatants");
+ }
+ catch (NullPointerException e)
{
- xmlReader.next();
- if(xmlReader.isStartElement())
+ freezeCombatantsInBattle = false;
+ logNotFound("server_config.freeze_battle_combatants", "false");
+ }
+
+ try
+ {
+ TomlArray ignoreTypes = parseResult.getArray("server_config.ignore_battle_types");
+ for(int i = 0; i < ignoreTypes.size(); ++i)
+ {
+ ignoreBattleTypes.add(ignoreTypes.getString(i));
+ }
+ }
+ catch (NullPointerException e)
+ {
+ ignoreBattleTypes.add("passive");
+ ignoreBattleTypes.add("boss");
+ logNotFound("server_config.ignore_battle_types");
+ }
+
+ try
+ {
+ playerSpeed = parseResult.getLong("server_config.player_speed").intValue();
+ }
+ catch (NullPointerException e)
+ {
+ playerSpeed = 50;
+ logNotFound("server_config.player_speed", "50");
+ }
+ try
+ {
+ playerHasteSpeed = parseResult.getLong("server_config.player_haste_speed").intValue();
+ }
+ catch (NullPointerException e)
+ {
+ playerHasteSpeed = 80;
+ logNotFound("server_config.player_haste_speed", "80");
+ }
+ try
+ {
+ playerSlowSpeed = parseResult.getLong("server_config.player_slow_speed").intValue();
+ }
+ catch (NullPointerException e)
+ {
+ playerSlowSpeed = 20;
+ logNotFound("server_config.player_slow_speed", "20");
+ }
+ try
+ {
+ playerAttackProbability = parseResult.getLong("server_config.player_attack_probability").intValue();
+ }
+ catch (NullPointerException e)
+ {
+ playerAttackProbability = 90;
+ logNotFound("server_config.player_attack_probability", "90");
+ }
+ try
+ {
+ playerEvasion = parseResult.getLong("server_config.player_evasion").intValue();
+ }
+ catch (NullPointerException e)
+ {
+ playerEvasion = 10;
+ logNotFound("server_config.player_evasion", "10");
+ }
+
+ try
+ {
+ defenseDuration = parseResult.getLong("server_config.defense_duration").intValue();
+ }
+ catch (NullPointerException e)
+ {
+ defenseDuration = 1;
+ logNotFound("server_config.defense_duration", "1");
+ }
+
+ try
+ {
+ fleeGoodProbability = parseResult.getLong("server_config.flee_good_probability").intValue();
+ }
+ catch (NullPointerException e)
+ {
+ fleeGoodProbability = 90;
+ logNotFound("server_config.flee_good_probability", "90");
+ }
+ try
+ {
+ fleeBadProbability = parseResult.getLong("server_config.flee_bad_probability").intValue();
+ }
+ catch (NullPointerException e)
+ {
+ fleeBadProbability = 35;
+ logNotFound("server_config.flee_bad_probability", "35");
+ }
+
+ try
+ {
+ minimumHitPercentage = parseResult.getLong("server_config.minimum_hit_percentage").intValue();
+ if (minimumHitPercentage < 1)
+ {
+ minimumHitPercentage = 1;
+ }
+ }
+ catch (NullPointerException e)
+ {
+ minimumHitPercentage = 4;
+ logNotFound("server_config.minimum_hit_percentage", "4");
+ }
+
+ try
+ {
+ battleDecisionDurationNanos = parseResult.getLong("server_config.battle_turn_time_seconds") * 1000000000L;
+ if(battleDecisionDurationNanos < BATTLE_DECISION_DURATION_NANO_MIN)
{
- if(xmlReader.getLocalName().equals("TurnBasedMinecraftConfig"))
+ battleDecisionDurationNanos = BATTLE_DECISION_DURATION_NANO_MIN;
+ logger.warn("Config \"server_config.battle_turn_time_seconds\" too low, defaulting to minimum \"5\"");
+ }
+ else if(battleDecisionDurationNanos > BATTLE_DECISION_DURATION_NANO_MAX)
+ {
+ battleDecisionDurationNanos = BATTLE_DECISION_DURATION_NANO_MAX;
+ logger.warn("Config \"server_config.battle_turn_time_seconds\" too high, defaulting to maximum \"60\"");
+ }
+ }
+ catch (NullPointerException e)
+ {
+ battleDecisionDurationNanos = BATTLE_DECISION_DURATION_NANO_DEFAULT;
+ logNotFound("server_config.battle_turn_time_seconds", "15");
+ }
+
+ // entities
+ TomlArray entityArray = parseResult.getArray("server_config.entity");
+ if(entityArray != null)
+ {
+ for(int i = 0; i < entityArray.size(); ++i)
+ {
+ TomlTable entity = entityArray.getTable(i);
+ EntityInfo eInfo = new EntityInfo();
+ try
+ {
+ eInfo.classType = Class.forName(entity.getString("name"));
+ }
+ catch (ClassNotFoundException e)
{
+ logger.error("Entity with class name \"" + entity.getString("name") + "\" not found, skipping...");
continue;
}
- else if(xmlReader.getLocalName().equals("Version"))
+ catch (NullPointerException e)
{
+ logger.error("Entity does not have \"name\", skipping...");
continue;
}
- else if(xmlReader.getLocalName().equals("LeaveBattleCooldown"))
+
+ try
{
- leaveBattleCooldownSeconds = Integer.parseInt(xmlReader.getElementText());
- if(leaveBattleCooldownSeconds <= 0)
+ eInfo.attackPower = entity.getLong("attack_power").intValue();
+ if(eInfo.attackPower < 0)
{
- leaveBattleCooldownSeconds = 1;
+ eInfo.attackPower = 0;
+ logEntityInvalidValue("attack_power", eInfo.classType.getName(), "0");
}
- else if(leaveBattleCooldownSeconds > 10)
+ }
+ catch (NullPointerException e)
+ {
+ logEntityMissingRequiredValue("attack_power", eInfo.classType.getName());
+ continue;
+ }
+
+ try
+ {
+ eInfo.attackProbability = entity.getLong("attack_probability").intValue();
+ if(eInfo.attackProbability < 0 || eInfo.attackProbability > 100)
{
- leaveBattleCooldownSeconds = 10;
+ eInfo.attackProbability = 35;
+ logEntityInvalidValue("attack_probability", eInfo.classType.getName(), "35");
}
}
- else if(xmlReader.getLocalName().equals("AggroStartBattleDistance"))
+ catch (NullPointerException e)
+ {
+ logEntityMissingRequiredValue("attack_probability", eInfo.classType.getName());
+ continue;
+ }
+
+ try
{
- aggroStartBattleDistance = Integer.parseInt(xmlReader.getElementText());
- if(aggroStartBattleDistance < 5)
+ eInfo.attackEffect = EntityInfo.Effect.fromString(entity.getString("attack_effect"));
+ if(eInfo.attackEffect != EntityInfo.Effect.UNKNOWN)
{
- aggroStartBattleDistance = 5;
+ eInfo.attackEffectProbability = entity.getLong("attack_effect_probability").intValue();
+ if(eInfo.attackEffectProbability < 0 || eInfo.attackEffectProbability > 100)
+ {
+ eInfo.attackEffectProbability = 35;
+ logEntityInvalidValue("attack_effect", eInfo.classType.getName(), "35");
+ }
}
- else if(aggroStartBattleDistance > 50)
+ }
+ catch (NullPointerException e)
+ {
+ eInfo.attackEffect = EntityInfo.Effect.UNKNOWN;
+ }
+
+ try
+ {
+ eInfo.attackVariance = entity.getLong("attack_variance").intValue();
+ if(eInfo.attackVariance < 0)
{
- aggroStartBattleDistance = 50;
+ eInfo.attackVariance = 0;
+ logEntityInvalidValue("attack_variance", eInfo.classType.getName(), "0");
}
}
- else if(xmlReader.getLocalName().equals("OldBattleBehavior"))
+ catch (NullPointerException e)
+ {
+ eInfo.attackVariance = 0;
+ }
+
+ try
{
- if(xmlReader.getElementText().toLowerCase().equals("false"))
+ eInfo.defenseDamage = entity.getLong("defense_damage").intValue();
+ if(eInfo.defenseDamage < 0)
{
- oldBattleBehaviorEnabled = false;
+ eInfo.defenseDamage = 0;
+ logEntityInvalidValue("defense_damage", eInfo.classType.getName(), "0");
}
else
{
- oldBattleBehaviorEnabled = true;
+ eInfo.defenseDamageProbability = entity.getLong("defense_damage_probability").intValue();
+ if(eInfo.defenseDamageProbability < 0 || eInfo.defenseDamageProbability > 100)
+ {
+ eInfo.defenseDamageProbability = 35;
+ logEntityInvalidValue("defense_damage_probability", eInfo.classType.getName(), "35");
+ }
}
}
- else if(xmlReader.getLocalName().equals("WhoCanDisableTurnBasedForSelf"))
+ catch (NullPointerException e)
{
- if(xmlReader.getElementText().toLowerCase().equals("any"))
- {
- onlyOPsSelfDisableTB = false;
- }
- else
+ eInfo.defenseDamage = 0;
+ }
+
+ try
+ {
+ eInfo.evasion = entity.getLong("evasion").intValue();
+ if(eInfo.evasion < 0 || eInfo.evasion > 100)
{
- onlyOPsSelfDisableTB = true;
+ eInfo.evasion = 20;
+ logEntityInvalidValue("evasion", eInfo.classType.getName(), "20");
}
}
- else if(xmlReader.getLocalName().equals("MaxInBattle"))
+ catch (NullPointerException e)
{
- maxInBattle = Integer.parseInt(xmlReader.getElementText());
+ logEntityMissingRequiredValue("evasion", eInfo.classType.getName());
+ continue;
}
- else if(xmlReader.getLocalName().equals("FreezeBattleCombatants"))
+
+ try
{
- freezeCombatantsInBattle = !xmlReader.getElementText().toLowerCase().equals("false");
+ eInfo.speed = entity.getLong("speed").intValue();
}
- else if(xmlReader.getLocalName().equals("IgnoreBattleTypes"))
+ catch (NullPointerException e)
{
- do
- {
- xmlReader.next();
- if(xmlReader.isStartElement())
- {
- ignoreBattleTypes.add(xmlReader.getLocalName().toLowerCase());
- }
- } while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("IgnoreBattleTypes")));
+ logEntityMissingRequiredValue("speed", eInfo.classType.getName());
}
- else if(xmlReader.getLocalName().equals("BattleMusic"))
+
+ try
{
- do
- {
- xmlReader.next();
- if(xmlReader.isStartElement())
- {
- if(xmlReader.getLocalName().equals("Normal"))
- {
- do
- {
- xmlReader.next();
- if(xmlReader.isStartElement())
- {
- musicBattleTypes.add(xmlReader.getLocalName().toLowerCase());
- }
- } while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("Normal")));
- }
- else if(xmlReader.getLocalName().equals("Silly"))
- {
- do
- {
- xmlReader.next();
- if(xmlReader.isStartElement())
- {
- musicSillyTypes.add(xmlReader.getLocalName().toLowerCase());
- }
- } while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("Silly")));
- }
- }
- } while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("BattleMusic")));
+ eInfo.ignoreBattle = entity.getBoolean("ignore_battle");
}
- else if(xmlReader.getLocalName().equals("PlayerStats"))
+ catch (NullPointerException e)
{
- do
- {
- xmlReader.next();
- if(xmlReader.isStartElement())
- {
- if(xmlReader.getLocalName().equals("Speed"))
- {
- playerSpeed = Integer.parseInt(xmlReader.getElementText());
- }
- else if(xmlReader.getLocalName().equals("HasteSpeed"))
- {
- playerHasteSpeed = Integer.parseInt(xmlReader.getElementText());
- }
- else if(xmlReader.getLocalName().equals("SlowSpeed"))
- {
- playerSlowSpeed = Integer.parseInt(xmlReader.getElementText());
- }
- else if(xmlReader.getLocalName().equals("AttackProbability"))
- {
- playerAttackProbability = Integer.parseInt(xmlReader.getElementText());
- }
- else if(xmlReader.getLocalName().equals("Evasion"))
- {
- playerEvasion = Integer.parseInt(xmlReader.getElementText());
- }
- }
- } while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("PlayerStats")));
+ eInfo.ignoreBattle = false;
}
- else if(xmlReader.getLocalName().equals("DefenseDuration"))
+
+ eInfo.category = entity.getString("category");
+ if(eInfo.category == null)
{
- defenseDuration = Integer.parseInt(xmlReader.getElementText());
+ logEntityMissingRequiredValue("category", eInfo.classType.getName());
+ continue;
}
- else if(xmlReader.getLocalName().equals("FleeGoodProbability"))
+
+ try
{
- fleeGoodProbability = Integer.parseInt(xmlReader.getElementText());
+ eInfo.decisionAttack = entity.getLong("decision_attack_probability").intValue();
}
- else if(xmlReader.getLocalName().equals("FleeBadProbability"))
+ catch (NullPointerException e)
{
- fleeBadProbability = Integer.parseInt(xmlReader.getElementText());
+ logEntityMissingRequiredValue("decision_attack_probability", eInfo.classType.getName());
+ continue;
}
- else if(xmlReader.getLocalName().equals("MinimumHitPercentage"))
+
+ try
{
- minimumHitPercentage = Integer.parseInt(xmlReader.getElementText());
- if(minimumHitPercentage < 1)
- {
- minimumHitPercentage = 1;
- }
+ eInfo.decisionDefend = entity.getLong("decision_defend_probability").intValue();
}
- else if(xmlReader.getLocalName().equals("BattleTurnTimeSeconds"))
+ catch (NullPointerException e)
{
- try
- {
- int seconds = Integer.parseInt(xmlReader.getElementText());
- battleDecisionDurationNanos = (long)(seconds) * 1000000000L;
- if(battleDecisionDurationNanos < BATTLE_DECISION_DURATION_NANO_MIN)
- {
- battleDecisionDurationNanos = BATTLE_DECISION_DURATION_NANO_MIN;
- }
- else if(battleDecisionDurationNanos > BATTLE_DECISION_DURATION_NANO_MAX)
- {
- battleDecisionDurationNanos = BATTLE_DECISION_DURATION_NANO_MAX;
- }
- } catch (Throwable t)
- {
- logger.warn("Unable to get value for \"BattleTurnTimeSeconds\" from config, using default");
- battleDecisionDurationNanos = BATTLE_DECISION_DURATION_NANO_DEFAULT;
- }
+ logEntityMissingRequiredValue("decision_defend_probability", eInfo.classType.getName());
+ continue;
+ }
+
+ try
+ {
+ eInfo.decisionFlee = entity.getLong("decision_flee_probability").intValue();
+ }
+ catch (NullPointerException e)
+ {
+ logEntityMissingRequiredValue("decision_flee_probability", eInfo.classType.getName());
+ continue;
+ }
+
+ entityInfoMap.put(eInfo.classType.getName(), eInfo);
+ }
+ }
+ return true;
+ }
+
+ private void logNotFound(String option)
+ {
+ logger.warn("Config option \"" + option + "\" not found, setting defaults");
+ }
+
+ private void logNotFound(String option, String defaultValue)
+ {
+ logger.warn("Config option \"" + option + "\" not found, defaulting to \"" + defaultValue + "\"");
+ }
+
+ private void logEntityInvalidValue(String option, String name, String defaultValue)
+ {
+ logger.warn("Invalid \"" + option + "\" for \"" + name + "\", defaulting to " + defaultValue);
+ }
+
+ private void logEntityMissingRequiredValue(String option, String name)
+ {
+ logger.error("Entity \"" + name + "\" does not have option \"" + option + "\", skipping...");
+ }
+
+ private String getRegexEntityName(String name)
+ {
+ String regex = "^\\s*name\\s*=\\s*";
+ regex += "(\"" + name + "\"";
+ regex += "|'" + name + "')";
+ return regex;
+ }
+
+ private boolean addEntityEntry(EntityInfo eInfo)
+ {
+ try
+ {
+ File config = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH);
+ FileWriter fw = new FileWriter(config, true);
+ fw.write("[[server_config.entity]]\n");
+ fw.write("name = \"" + eInfo.classType.getName() + "\"\n");
+ fw.write("attack_power = " + eInfo.attackPower + "\n");
+ fw.write("attack_probability = " + eInfo.attackProbability + "\n");
+ if(eInfo.attackVariance > 0)
+ {
+ fw.write("attack_variance = " + eInfo.attackVariance + "\n");
+ }
+ if(eInfo.attackEffect != EntityInfo.Effect.UNKNOWN && eInfo.attackEffectProbability > 0)
+ {
+ fw.write("attack_effect = \"" + eInfo.attackEffect.toString() + "\"\n");
+ fw.write("attack_effect_probability = " + eInfo.attackEffectProbability + "\n");
+ }
+ if(eInfo.defenseDamage > 0 && eInfo.defenseDamageProbability > 0)
+ {
+ fw.write("defense_damage = " + eInfo.defenseDamage + "\n");
+ fw.write("defense_damage_probability = " + eInfo.defenseDamageProbability + "\n");
+ }
+ fw.write("evasion = " + eInfo.evasion + "\n");
+ fw.write("speed = " + eInfo.speed + "\n");
+ if(eInfo.ignoreBattle)
+ {
+ fw.write("ignoreBattle = true\n");
+ }
+ fw.write("category = \"" + eInfo.category + "\"\n");
+ fw.write("decision_attack_probability = " + eInfo.decisionAttack + "\n");
+ fw.write("decision_defend_probability = " + eInfo.decisionDefend + "\n");
+ fw.write("decision_flee_probability = " + eInfo.decisionFlee + "\n");
+ fw.close();
+
+ entityInfoMap.put(eInfo.classType.getName(), eInfo);
+ }
+ catch (Throwable t)
+ {
+ logger.error("Failed to add entity entry (name = \"" + eInfo.classType.getName() + "\")");
+ return false;
+ }
+ return true;
+ }
+
+ protected boolean editEntityEntry(EntityInfo eInfo)
+ {
+ try
+ {
+ String cached = new String();
+ char buf[] = new char[1024];
+ int read = 0;
+ File config = new File(TurnBasedMinecraftMod.CONFIG_FILE_PATH);
+ {
+ FileReader fr = new FileReader(config);
+ read = fr.read(buf);
+ while (read != -1)
+ {
+ cached += String.valueOf(buf, 0, read);
+ read = fr.read(buf);
+ }
+ fr.close();
+ }
+
+ int nameIndex = -1;
+ {
+ Pattern p = Pattern.compile(getRegexEntityName(eInfo.classType.getName()), Pattern.MULTILINE);
+ Matcher m = p.matcher(cached);
+ if(m.find())
+ {
+ nameIndex = m.start();
}
- else if(xmlReader.getLocalName().equals("SillyMusicThreshold"))
+ }
+ int entryIndex = -1;
+ int nextIndex = -1;
+ if(nameIndex != -1)
+ {
{
- sillyMusicThreshold = Integer.parseInt(xmlReader.getElementText());
- if(sillyMusicThreshold < 0)
+ Pattern p = Pattern.compile("^\\s*\\[\\[\\s*server_config\\s*\\.\\s*entity\\s*]]", Pattern.MULTILINE);
+ Matcher m = p.matcher(cached.substring(0, nameIndex));
+ while(m.find())
{
- sillyMusicThreshold = 0;
+ entryIndex = m.start();
}
- else if(sillyMusicThreshold > 100)
+ if(entryIndex == -1)
{
- sillyMusicThreshold = 100;
+ logger.warn("editEntityEntry: could not find header for entry \"" + eInfo.classType.getName() + "\", skipping to adding it...");
+ return addEntityEntry(eInfo);
}
}
- else if(xmlReader.getLocalName().equals("EntityEntry"))
{
- EntityInfo eInfo = new EntityInfo();
- do
+ Pattern p = Pattern.compile("^\\s*\\[", Pattern.MULTILINE);
+ Matcher m = p.matcher(cached.substring(nameIndex));
+ if(m.find())
{
- xmlReader.next();
- if(xmlReader.isStartElement())
- {
- if(xmlReader.getLocalName().equals("Name"))
- {
- try
- {
- eInfo.classType = Class.forName(xmlReader.getElementText());
- } catch (ClassNotFoundException e)
- {
- logger.error("Failed to get class of name " + xmlReader.getElementText());
- }
- }
- else if(xmlReader.getLocalName().equals("AttackPower"))
- {
- for(int i = 0; i < xmlReader.getAttributeCount(); ++i)
- {
- if(xmlReader.getAttributeLocalName(i).equals("Probability"))
- {
- eInfo.attackProbability = Integer.parseInt(xmlReader.getAttributeValue(i));
- }
- else if(xmlReader.getAttributeLocalName(i).equals("Variance"))
- {
- eInfo.attackVariance = Integer.parseInt(xmlReader.getAttributeValue(i));
- }
- }
- eInfo.attackPower = Integer.parseInt(xmlReader.getElementText());
- }
- else if(xmlReader.getLocalName().equals("AttackEffect"))
- {
- for(int i = 0; i < xmlReader.getAttributeCount(); ++i)
- {
- if(xmlReader.getAttributeLocalName(i).equals("Probability"))
- {
- eInfo.attackEffectProbability = Integer.parseInt(xmlReader.getAttributeValue(i));
- }
- }
- eInfo.attackEffect = EntityInfo.Effect.fromString(xmlReader.getElementText());
- }
- else if(xmlReader.getLocalName().equals("Evasion"))
- {
- eInfo.evasion = Integer.parseInt(xmlReader.getElementText());
- }
- else if(xmlReader.getLocalName().equals("DefenseDamage"))
- {
- for(int i = 0; i < xmlReader.getAttributeCount(); ++i)
- {
- if(xmlReader.getAttributeLocalName(i).equals("Probability"))
- {
- eInfo.defenseDamageProbability = Integer.parseInt(xmlReader.getAttributeValue(i));
- }
- }
- eInfo.defenseDamage = Integer.parseInt(xmlReader.getElementText());
- }
- else if(xmlReader.getLocalName().equals("Category"))
- {
- eInfo.category = xmlReader.getElementText().toLowerCase();
- }
- else if(xmlReader.getLocalName().equals("IgnoreBattle"))
- {
- if(xmlReader.getElementText().toLowerCase().equals("true"))
- {
- eInfo.ignoreBattle = true;
- }
- }
- else if(xmlReader.getLocalName().equals("Speed"))
- {
- eInfo.speed = Integer.parseInt(xmlReader.getElementText());
- }
- else if(xmlReader.getLocalName().equals("Decision"))
- {
- do
- {
- xmlReader.next();
- if(xmlReader.isStartElement())
- {
- if(xmlReader.getLocalName().equals("Attack"))
- {
- eInfo.decisionAttack = Integer.parseInt(xmlReader.getElementText());
- }
- else if(xmlReader.getLocalName().equals("Defend"))
- {
- eInfo.decisionDefend = Integer.parseInt(xmlReader.getElementText());
- }
- else if(xmlReader.getLocalName().equals("Flee"))
- {
- eInfo.decisionFlee = Integer.parseInt(xmlReader.getElementText());
- }
- }
- } while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("Decision")));
- }
- }
- } while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals("EntityEntry")));
- if(eInfo.classType != null)
- {
- entityInfoMap.put(eInfo.classType.getName(), eInfo);
+ nextIndex = m.start() + nameIndex;
}
}
}
+ else
+ {
+ logger.warn("editEntityEntry: could not find entry for \"" + eInfo.classType.getName() + "\", skipping to adding it...");
+ return addEntityEntry(eInfo);
+ }
+
+ String cut = null;
+ if(nextIndex != -1)
+ {
+ cut = cached.substring(0, entryIndex) + cached.substring(nextIndex);
+ }
+ else
+ {
+ cut = cached.substring(0, entryIndex);
+ }
+
+ {
+ FileWriter fw = new FileWriter(config);
+ fw.write(cut);
+ fw.close();
+ }
+
+ return addEntityEntry(eInfo);
+ }
+ catch (Throwable t)
+ {
+ return false;
}
- xmlReader.close();
- fis.close();
- return true;
}
-
+
public int getPlayerSpeed()
{
return playerSpeed;
{
return playerSlowSpeed;
}
-
+
public int getPlayerAttackProbability()
{
return playerAttackProbability;
{
return playerEvasion;
}
-
+
public int getDefenseDuration()
{
return defenseDuration;
}
-
+
public int getFleeGoodProbability()
{
return fleeGoodProbability;
}
-
+
public int getFleeBadProbability()
{
return fleeBadProbability;
}
-
+
/**
* Returns a clone of an EntityInfo (to prevent editing it).
* @param classFullName
{
return entityInfoMap.get(classFullName).clone();
}
-
+
protected EntityInfo getEntityInfoReference(String classFullName)
{
return entityInfoMap.get(classFullName);
}
-
+
protected EntityInfo getMatchingEntityInfo(Object entity)
{
if(entity == null)
}
return null;
}
-
- private int getConfigFileVersion(File configFile)
+
+ private int getConfigFileVersion(InputStream io)
{
+ int version = 0;
try
{
- return getConfigFileVersion(new FileInputStream(configFile));
- } catch(FileNotFoundException e)
+ TomlParseResult result = Toml.parse(io, TomlVersion.V0_5_0);
+ version = result.getLong("version").intValue();
+ }
+ catch (Throwable t)
{
- return 0;
+ // ignored
}
+ return version;
}
-
- private int getConfigFileVersion(InputStream configStream)
- {
- int configVersion = 1;
+ private int getConfigFileVersion(File configFile)
+ {
+ int version = 0;
try
{
- XMLStreamReader xmlReader = XMLInputFactory.newInstance().createXMLStreamReader(configStream);
- while(xmlReader.hasNext())
- {
- xmlReader.next();
- if(xmlReader.isStartElement() && xmlReader.getLocalName().equals("Version"))
- {
- configVersion = Integer.parseInt(xmlReader.getElementText());
- break;
- }
- }
- xmlReader.close();
- } catch (Throwable t)
+ TomlParseResult result = Toml.parse(configFile.toPath(), TomlVersion.V0_5_0);
+ version = result.getLong("version").intValue();
+ }
+ catch (Throwable t)
{
- return 0;
+ // ignored
}
-
- return configVersion;
+ return version;
}
-
+
public boolean isIgnoreBattleType(String type)
{
return ignoreBattleTypes.contains(type);
}
-
+
public int getMinimumHitPercentage()
{
return minimumHitPercentage;
}
-
+
public int getMaxInBattle()
{
return maxInBattle;
}
-
+
public boolean isBattleMusicType(String type)
{
return musicBattleTypes.contains(type.toLowerCase());
}
-
+
public boolean isSillyMusicType(String type)
{
return musicSillyTypes.contains(type.toLowerCase());
}
-
+
public boolean isFreezeCombatantsEnabled()
{
return freezeCombatantsInBattle;
}
-
+
public int getSillyMusicThreshold()
{
return sillyMusicThreshold;
}
-
+
public int getConfigVersion()
{
return configVersion;
}
-
+
public long getDecisionDurationNanos()
{
return battleDecisionDurationNanos;
}
-
+
public int getDecisionDurationSeconds()
{
return (int)(battleDecisionDurationNanos / 1000000000L);
}
-
+
protected void addBattleIgnoringPlayer(int id)
{
battleIgnoringPlayers.add(id);
}
-
+
protected void removeBattleIgnoringPlayer(int id)
{
battleIgnoringPlayers.remove(id);
}
-
+
protected void clearBattleIgnoringPlayers()
{
battleIgnoringPlayers.clear();
{
return battleIgnoringPlayers;
}
-
+
public boolean getIfOnlyOPsCanDisableTurnBasedForSelf()
{
return onlyOPsSelfDisableTB;
}
-
+
protected void setBattleDisabledForAll(boolean isDisabled)
{
battleDisabledForAll = isDisabled;
}
-
+
protected boolean getBattleDisabledForAll()
{
return battleDisabledForAll;
}
-
+
public boolean isOldBattleBehaviorEnabled()
{
return oldBattleBehaviorEnabled;
}
-
+
public int getLeaveBattleCooldownSeconds()
{
return leaveBattleCooldownSeconds;
}
-
+
public long getLeaveBattleCooldownNanos()
{
return (long)leaveBattleCooldownSeconds * 1000000000L;
}
-
+
public int getAggroStartBattleDistance()
{
return aggroStartBattleDistance;
return UNKNOWN;
}
}
+
+ public String toString()
+ {
+ switch(this)
+ {
+ case SPEED:
+ return "speed";
+ case SLOW:
+ return "slow";
+ case HASTE:
+ return "haste";
+ case MINING_FATIGUE:
+ return "mining_fatigue";
+ case STRENGTH:
+ return "strength";
+ case JUMP_BOOST:
+ return "jump_boost";
+ case NAUSEA:
+ return "nausea";
+ case REGENERATION:
+ return "regeneration";
+ case RESISTANCE:
+ return "resistance";
+ case FIRE_RESISTANCE:
+ return "fire_resistance";
+ case WATER_BREATHING:
+ return "water_breathing";
+ case INVISIBILITY:
+ return "invisibility";
+ case BLINDNESS:
+ return "blindness";
+ case NIGHT_VISION:
+ return "night_vision";
+ case HUNGER:
+ return "hunger";
+ case WEAKNESS:
+ return "weakness";
+ case POISON:
+ return "poison";
+ case WITHER:
+ return "wither";
+ case ABSORPTION:
+ return "absorption";
+ case SATURATION:
+ return "saturation";
+ case GLOWING:
+ return "glowing";
+ case LEVITATION:
+ return "levitation";
+ case LUCK:
+ return "luck";
+ case UNLUCK:
+ return "unluck";
+ case FIRE:
+ return "fire";
+ default:
+ return "unknown";
+ }
+ }
public PotionEffect getPotionEffect()
{
@SubscribeEvent
public void entityJoinHandler(EntityJoinWorldEvent event)
{
- if(event.getEntity().world.isRemote)
+ if(event.getWorld().isRemote)
{
return;
}
{
public static final String MODID = "com.seodisparate.turnbasedminecraft";
public static final String NAME = "Turn Based Minecraft Mod";
- public static final String VERSION = "1.5";
- public static final String CONFIG_FILENAME = "TBM_Config.xml";
+ public static final String VERSION = "1.6";
+ public static final String CONFIG_FILENAME = "TBM_Config.toml";
public static final String CONFIG_DIRECTORY = "config/TurnBasedMinecraft/";
public static final String CONFIG_FILE_PATH = CONFIG_DIRECTORY + CONFIG_FILENAME;
public static final String CONFIG_INTERNAL_PATH = "/assets/TurnBasedMinecraft/" + CONFIG_FILENAME;
--- /dev/null
+# Please do not change this option, the mod uses this to keep track of what new
+# changes to add to the config.
+version = 1
+
+[client_config]
+
+# determines what categories use what type of music.
+# Unknown categories sent by the server will default to "battle_music".
+battle_music = ["monster", "animal", "boss", "player"]
+silly_music = ["passive"]
+
+# Minimum percentage of silly entities in battle to use silly music.
+silly_music_threshold = 40
+
+
+[server_config]
+
+# Number of seconds that an entity cannot enter battle after having just left
+# one. Minimum 1, maximum 10.
+leave_battle_cooldown = 5
+
+# Maximum distance for a monster to start battle by targeting a player or other
+# entity in turn-based-battle. Minimum 5, maximum 50.
+aggro_start_battle_max_distance = 8
+
+# If true, only initiate battle on attack. If false, monsters targeting players
+# also trigger battle.
+old_battle_behavior = false
+
+# If true, any player can disable/enable turn-based-battle for themselves with
+# the commands "/tbm-enable" and "/tbm-disable".
+anyone_can_disable_tbm_for_self = false
+
+# Maximum amount of entities in one battle. If max is reached, no more entities
+# will be added to battle until there are less than max entities.
+max_in_battle = 8
+
+# If true, all entities in battle will be frozen in place
+freeze_battle_combatants = false
+
+# Entity categories that will not initiate battle.
+ignore_battle_types = ["passive", "boss"]
+
+# Stats that apply to all players
+player_speed = 50
+player_haste_speed = 80
+player_slow_speed = 20
+player_attack_probability = 90
+player_evasion = 10
+
+# Number of attacks that a "defend" move will block
+defense_duration = 1
+
+# If speed is greater than fastest speed of entity on opposing side, good
+# probability is used.
+flee_good_probability = 90
+flee_bad_probability = 40
+
+# Minimum hit percentage for everyone. If option is set to less than 1,
+# config will assume option of "1" anyway.
+minimum_hit_percentage = 4
+
+# Number of seconds to wait in battle for all players to make a decision.
+# Minimum 5, maximum 60.
+battle_turn_time_seconds = 15
+
+
+# Each "server_config.entity" entry uses the following options:
+# name: full class name of the entity
+# attack_power: how much damage an entity does on successful attack
+# attack_probability: percentage of attack success. (Usually calculated with enemy's evasion to determine actual percentage)
+# attack_variance (optional): determines how much a successful attack's damage varies.
+# attack_effect (optional): applies effect on hit success
+# attack_effect_probability (optional): percentage of attack_effect being applied on hit success.
+# defense_damage (optional): damage dealt to attacker when hit.
+# defense_damage_probability (optional): percentage of defense_damage being applied on received hit.
+# evasion: percentage of evading hit.
+# speed: used to determine turn-order, and flee success rates.
+# ignore_battle (optional): per-entity setting that causes that entity to not enter turn-based-battle.
+# category: Determines type of entity. Used for server config for what groups do not enter turn-based-battle, and for client config for determining what type of battle music to play.
+# decision_attack_probability: Percentage of entity choosing to attack on turn.
+# decision_defend_probability: Percentage of entity choosing to defend on turn.
+# decision_flee_probability: Percentage of entity choosing to flee on turn.
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityBlaze"
+attack_power = 5
+attack_probability = 50
+attack_effect = "fire"
+attack_effect_probability = 75
+evasion = 5
+category = "monster"
+speed = 45
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityCaveSpider"
+attack_power = 2
+attack_probability = 75
+attack_effect = "poison"
+attack_effect_probability = 90
+evasion = 35
+category = "monster"
+speed = 75
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityCreeper"
+ignore_battle = true
+attack_power = 15
+attack_probability = 17
+attack_variance = 7
+evasion = 5
+category = "monster"
+speed = 25
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityElderGuardian"
+attack_power = 8
+attack_probability = 65
+defense_damage = 2
+defense_damage_probability = 35
+evasion = 25
+category = "monster"
+speed = 45
+decision_attack_probability = 80
+decision_defend_probability = 20
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityEnderman"
+attack_power = 7
+attack_probability = 80
+evasion = 40
+category = "monster"
+speed = 70
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityEndermite"
+attack_power = 2
+attack_probability = 80
+evasion = 40
+category = "monster"
+speed = 35
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityEvoker"
+attack_power = 6
+attack_probability = 60
+evasion = 35
+category = "monster"
+speed = 35
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityGhast"
+ignore_battle = true
+attack_power = 13
+attack_probability = 20
+evasion = 35
+category = "monster"
+speed = 60
+decision_attack_probability = 75
+decision_defend_probability = 0
+decision_flee_probability = 25
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityGiantZombie"
+attack_power = 11
+attack_probability = 35
+evasion = 2
+category = "monster"
+speed = 45
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityGuardian"
+attack_power = 6
+attack_probability = 55
+defense_damage = 2
+defense_damage_probability = 30
+evasion = 25
+category = "monster"
+speed = 50
+decision_attack_probability = 80
+decision_defend_probability = 20
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityHusk"
+attack_power = 3
+attack_probability = 70
+attack_effect = "hunger"
+attack_effect_probability = 95
+evasion = 5
+category = "monster"
+speed = 25
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityIronGolem"
+attack_power = 14
+attack_probability = 85
+attack_variance = 7
+evasion = 5
+category = "monster"
+speed = 45
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityMagmaCube"
+attack_power = 3
+attack_probability = 35
+evasion = 12
+category = "monster"
+speed = 35
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityPigZombie"
+attack_power = 8
+attack_probability = 70
+evasion = 10
+category = "monster"
+speed = 50
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityPolarBear"
+attack_power = 6
+attack_probability = 67
+evasion = 5
+category = "animal"
+speed = 35
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityShulker"
+attack_power = 4
+attack_probability = 80
+evasion = 15
+category = "monster"
+speed = 10
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntitySilverfish"
+attack_power = 1
+attack_probability = 85
+evasion = 37
+category = "monster"
+speed = 35
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntitySkeleton"
+attack_power = 3
+attack_probability = 75
+attack_variance = 1
+evasion = 13
+category = "monster"
+speed = 30
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntitySlime"
+attack_power = 2
+attack_probability = 35
+evasion = 10
+category = "monster"
+speed = 30
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntitySnowman"
+attack_power = 0
+attack_probability = 80
+evasion = 5
+category = "passive"
+speed = 60
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntitySpider"
+attack_power = 2
+attack_probability = 70
+evasion = 25
+category = "monster"
+speed = 70
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityStray"
+attack_power = 3
+attack_probability = 75
+attack_variance = 1
+attack_effect = "slow"
+attack_effect_probability = 90
+evasion = 13
+category = "monster"
+speed = 30
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityVex"
+attack_power = 9
+attack_probability = 65
+evasion = 30
+category = "monster"
+speed = 80
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityVindicator"
+attack_power = 13
+attack_probability = 70
+evasion = 10
+category = "monster"
+speed = 35
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityWitch"
+attack_power = 5
+attack_probability = 75
+attack_variance = 1
+evasion = 8
+category = "monster"
+speed = 35
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityWitherSkeleton"
+attack_power = 8
+attack_probability = 70
+attack_effect = "wither"
+attack_effect_probability = 90
+evasion = 7
+category = "monster"
+speed = 65
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityZombie"
+attack_power = 3
+attack_probability = 70
+evasion = 5
+category = "monster"
+speed = 25
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.monster.EntityZombieVillager"
+attack_power = 3
+attack_probability = 70
+evasion = 5
+category = "monster"
+speed = 25
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntityBat"
+attack_power = 0
+attack_probability = 70
+evasion = 35
+category = "passive"
+speed = 75
+decision_attack_probability = 0
+decision_defend_probability = 0
+decision_flee_probability = 90
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntityChicken"
+attack_power = 0
+attack_probability = 70
+evasion = 10
+category = "passive"
+speed = 35
+decision_attack_probability = 0
+decision_defend_probability = 0
+decision_flee_probability = 90
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntityCow"
+attack_power = 0
+attack_probability = 50
+evasion = 1
+category = "passive"
+speed = 20
+decision_attack_probability = 0
+decision_defend_probability = 10
+decision_flee_probability = 80
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntityDonkey"
+attack_power = 0
+attack_probability = 70
+evasion = 10
+category = "passive"
+speed = 65
+decision_attack_probability = 0
+decision_defend_probability = 0
+decision_flee_probability = 90
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntityHorse"
+attack_power = 0
+attack_probability = 70
+evasion = 10
+category = "passive"
+speed = 65
+decision_attack_probability = 0
+decision_defend_probability = 0
+decision_flee_probability = 90
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntityLlama"
+attack_power = 1
+attack_probability = 70
+evasion = 10
+category = "passive"
+speed = 50
+decision_attack_probability = 65
+decision_defend_probability = 0
+decision_flee_probability = 25
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntityMooshroom"
+attack_power = 0
+attack_probability = 70
+evasion = 1
+category = "passive"
+speed = 20
+decision_attack_probability = 0
+decision_defend_probability = 10
+decision_flee_probability = 80
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntityMule"
+attack_power = 0
+attack_probability = 70
+evasion = 10
+category = "passive"
+speed = 50
+decision_attack_probability = 0
+decision_defend_probability = 0
+decision_flee_probability = 90
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntityOcelot"
+attack_power = 1
+attack_probability = 70
+attack_variance = 1
+evasion = 10
+category = "passive"
+speed = 75
+decision_attack_probability = 0
+decision_defend_probability = 0
+decision_flee_probability = 90
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntityParrot"
+attack_power = 0
+attack_probability = 70
+evasion = 35
+category = "passive"
+speed = 70
+decision_attack_probability = 0
+decision_defend_probability = 0
+decision_flee_probability = 90
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntityPig"
+attack_power = 0
+attack_probability = 70
+evasion = 10
+category = "passive"
+speed = 30
+decision_attack_probability = 0
+decision_defend_probability = 5
+decision_flee_probability = 85
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntityRabbit"
+attack_power = 0
+attack_probability = 70
+evasion = 40
+category = "passive"
+speed = 75
+decision_attack_probability = 0
+decision_defend_probability = 0
+decision_flee_probability = 100
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntitySheep"
+attack_power = 0
+attack_probability = 70
+evasion = 5
+category = "passive"
+speed = 30
+decision_attack_probability = 0
+decision_defend_probability = 0
+decision_flee_probability = 90
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntitySkeletonHorse"
+attack_power = 0
+attack_probability = 70
+evasion = 5
+category = "passive"
+speed = 65
+decision_attack_probability = 0
+decision_defend_probability = 0
+decision_flee_probability = 90
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntitySquid"
+attack_power = 0
+attack_probability = 70
+evasion = 15
+category = "passive"
+speed = 40
+decision_attack_probability = 0
+decision_defend_probability = 0
+decision_flee_probability = 90
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntityVillager"
+attack_power = 0
+attack_probability = 70
+evasion = 5
+category = "passive"
+speed = 35
+decision_attack_probability = 0
+decision_defend_probability = 10
+decision_flee_probability = 80
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntityWolf"
+attack_power = 4
+attack_probability = 70
+evasion = 20
+category = "animal"
+speed = 70
+decision_attack_probability = 80
+decision_defend_probability = 15
+decision_flee_probability = 5
+
+[[server_config.entity]]
+name = "net.minecraft.entity.passive.EntityZombieHorse"
+attack_power = 0
+attack_probability = 70
+evasion = 8
+category = "passive"
+speed = 65
+decision_attack_probability = 0
+decision_defend_probability = 0
+decision_flee_probability = 90
+
+[[server_config.entity]]
+name = "net.minecraft.entity.boss.EntityDragon"
+attack_power = 10
+attack_probability = 70
+attack_variance = 2
+evasion = 27
+category = "boss"
+speed = 63
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+
+[[server_config.entity]]
+name = "net.minecraft.entity.boss.EntityWither"
+attack_power = 8
+attack_probability = 70
+attack_effect = "wither"
+attack_effect_probability = 90
+evasion = 20
+category = "boss"
+speed = 68
+decision_attack_probability = 100
+decision_defend_probability = 0
+decision_flee_probability = 0
+++ /dev/null
-<TurnBasedMinecraftConfig>
- <!-- If the mod has a newer version config, it will rename the existing config and place the new config -->
- <Version>6</Version>
- <!-- Number of seconds that an entity cannot enter battle after having just left one. Minimum 1, maximum 10-->
- <LeaveBattleCooldown>5</LeaveBattleCooldown>
- <!-- Maximum distance for a monster to start battle by targeting a player or other entity in turn-based-battle.
- Minimum 5, maximum 50. -->
- <AggroStartBattleDistance>8</AggroStartBattleDistance>
- <!-- If not "false", uses old battle behavior where battles only start on attack/hit. Otherwise, battles can
- start when a hostile mob targets a player or another entity in battle. -->
- <OldBattleBehavior>false</OldBattleBehavior>
- <!-- Determines who can disable turn-based-battle for themselves via command. Must be "op" or "any". If neither, defaults to "op"-->
- <WhoCanDisableTurnBasedForSelf>op</WhoCanDisableTurnBasedForSelf>
- <!-- If there are "MaxInBattle" amount of entities in battle, other entities cannot join until combatants leave battle. -->
- <MaxInBattle>8</MaxInBattle>
- <!-- If not set to "false", then when battle starts all combatants will remain in their starting position. -->
- <FreezeBattleCombatants>false</FreezeBattleCombatants>
- <!-- Types that will not initiate battle with player. They are listed as "Category" per EntiytStats entity.
- Note that items listed in "IgnoreBattleTypes" and "Category" are converted to lowercase before being compared. -->
- <IgnoreBattleTypes>
- <passive></passive>
- <boss></boss>
- </IgnoreBattleTypes>
- <!-- BattleMusic determines what categories a type will play music for. -->
- <!-- Music is placed in "config/TurnBasedMinecraft/Music/battle/" and "config/TurnBasedMinecraft/Music/silly/" -->
- <BattleMusic>
- <Normal>
- <monster></monster>
- <animal></animal>
- <boss></boss>
- <player></player>
- </Normal>
- <Silly>
- <passive></passive>
- </Silly>
- </BattleMusic>
- <PlayerStats>
- <Speed>50</Speed>
- <HasteSpeed>80</HasteSpeed> <!-- Speed used if the player entity has "speed" or "haste" effects -->
- <SlowSpeed>20</SlowSpeed> <!-- Speed used if the player entity has "slow" effect -->
- <AttackProbability>90</AttackProbability>
- <Evasion>10</Evasion>
- </PlayerStats>
- <!-- Determines how many attacks a "defense" move can block before that entity's next turn. -->
- <DefenseDuration>1</DefenseDuration>
- <!-- Probability of escaping battle. If entity's speed is greater than the enemy team's speediest entity, then good probability is used. -->
- <FleeGoodProbability>90</FleeGoodProbability>
- <FleeBadProbability>40</FleeBadProbability>
- <!-- Minimum hit percentage for every entity. If less than 1, it will be stored as 1 anyways. -->
- <MinimumHitPercentage>4</MinimumHitPercentage>
- <!-- Number of seconds to wait in battle for all players to make a decision. Minimum of 5 and maximum of 60. -->
- <BattleTurnTimeSeconds>15</BattleTurnTimeSeconds>
- <!-- Minimum percentage of silly entities in battle to use silly music -->
- <SillyMusicThreshold>40</SillyMusicThreshold>
-
- <!-- Battle stats for entities should be specified here. If an entity is not listed it cannot enter battle. -->
- <!-- Name: The full class name of an entity. -->
- <!-- AttackPower: How much damage an entity does per attack. Usually has a "Probability" attribute between 0 and 100. Also may have a "Variance" attribute that varies the attack power by the specified amount randomly. -->
- <!-- AttackEffect: (Optional) Applies effect to target entity with "Probability" success rate. -->
- <!-- DefenseDamage: (Optional) Applies damage to an attacker when attacked with "Probability" success rate. -->
- <!-- Evasion: Determines the percentage of evading attacks between 0 and 100. -->
- <!-- Note that if the hit probability and evasion result in a percentage less than 1%, the hit chance will be changed ti 1% -->
- <!-- Speed: Value in range of 0 to 100 that determines the order entities act in battle. Higher is sooner. Entities with same speed will take their turn as a group in random order (not at the same time). -->
- <!-- IgnoreBattle: (Optional) Per entity setting to not enter turn-based-battle if value is "true". If "true" these stats will not apply to the entity as they are only used in turn-based-battle. -->
- <!-- Category: Sets the type of the entity, used by "IgnoreBattleTypes" to determine what types ignore battle. -->
- <!-- Decision: Lists percentages of what action taken by the entity, one of Attack, Defend, or Flee. If the sum is less than 100, the mob has a chance to do nothing with the remaining percentage -->
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityBlaze</Name>
- <AttackPower Probability="50">5</AttackPower>
- <AttackEffect Probability="75">fire</AttackEffect>
- <Evasion>5</Evasion>
- <Category>monster</Category>
- <Speed>45</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityCaveSpider</Name>
- <AttackPower Probability="75">2</AttackPower>
- <AttackEffect Probability="90">poison</AttackEffect>
- <Evasion>35</Evasion>
- <Category>monster</Category>
- <Speed>75</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityCreeper</Name>
- <IgnoreBattle>true</IgnoreBattle>
- <AttackPower Probability="17" Variance="7">15</AttackPower>
- <Evasion>5</Evasion>
- <Category>monster</Category>
- <Speed>25</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityElderGuardian</Name>
- <AttackPower Probability="65">8</AttackPower>
- <DefenseDamage Probability="35">2</DefenseDamage>
- <Evasion>25</Evasion>
- <Category>monster</Category>
- <Speed>45</Speed>
- <Decision>
- <Attack>80</Attack>
- <Defend>20</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityEnderman</Name>
- <AttackPower Probability="80">7</AttackPower>
- <Evasion>40</Evasion>
- <Category>monster</Category>
- <Speed>70</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityEndermite</Name>
- <AttackPower Probability="80">2</AttackPower>
- <Evasion>40</Evasion>
- <Category>monster</Category>
- <Speed>35</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityEvoker</Name>
- <AttackPower Probability="60">6</AttackPower>
- <Evasion>35</Evasion>
- <Category>monster</Category>
- <Speed>35</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityGhast</Name>
- <IgnoreBattle>true</IgnoreBattle>
- <AttackPower Probability="20">13</AttackPower>
- <Evasion>35</Evasion>
- <Category>monster</Category>
- <Speed>60</Speed>
- <Decision>
- <Attack>75</Attack>
- <Defend>0</Defend>
- <Flee>25</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityGiantZombie</Name>
- <AttackPower Probability="35">11</AttackPower>
- <Evasion>2</Evasion>
- <Category>monster</Category>
- <Speed>45</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityGuardian</Name>
- <AttackPower Probability="55">6</AttackPower>
- <DefenseDamage Probability="30">2</DefenseDamage>
- <Evasion>25</Evasion>
- <Category>monster</Category>
- <Speed>50</Speed>
- <Decision>
- <Attack>80</Attack>
- <Defend>20</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityHusk</Name>
- <AttackPower Probability="70">3</AttackPower>
- <AttackEffect Probability="95">hunger</AttackEffect>
- <Evasion>5</Evasion>
- <Category>monster</Category>
- <Speed>25</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityIronGolem</Name>
- <AttackPower Probability="85" Variance="7">14</AttackPower>
- <Evasion>5</Evasion>
- <Category>monster</Category>
- <Speed>45</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityMagmaCube</Name>
- <AttackPower Probability="35">3</AttackPower>
- <Evasion>12</Evasion>
- <Category>monster</Category>
- <Speed>35</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityPigZombie</Name>
- <AttackPower Probability="70">8</AttackPower>
- <Evasion>10</Evasion>
- <Category>monster</Category>
- <Speed>50</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityPolarBear</Name>
- <AttackPower Probability="67">6</AttackPower>
- <Evasion>5</Evasion>
- <Category>animal</Category>
- <Speed>35</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityShulker</Name>
- <AttackPower Probability="80">4</AttackPower>
- <Evasion>15</Evasion>
- <Category>monster</Category>
- <Speed>10</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntitySilverfish</Name>
- <AttackPower Probability="85">1</AttackPower>
- <Evasion>37</Evasion>
- <Category>monster</Category>
- <Speed>35</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntitySkeleton</Name>
- <AttackPower Probability="75" Variance="1">3</AttackPower>
- <Evasion>13</Evasion>
- <Category>monster</Category>
- <Speed>30</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntitySlime</Name>
- <AttackPower Probability="35">2</AttackPower>
- <Evasion>10</Evasion>
- <Category>monster</Category>
- <Speed>30</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntitySnowman</Name>
- <AttackPower Probability="80">0</AttackPower>
- <Evasion>5</Evasion>
- <Category>passive</Category>
- <Speed>60</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntitySpider</Name>
- <AttackPower Probability="70">2</AttackPower>
- <Evasion>25</Evasion>
- <Category>monster</Category>
- <Speed>70</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityStray</Name>
- <AttackPower Probability="75" Variance="1">3</AttackPower>
- <AttackEffect Probability="90">slow</AttackEffect>
- <Evasion>13</Evasion>
- <Category>monster</Category>
- <Speed>30</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityVex</Name>
- <AttackPower Probability="65">9</AttackPower>
- <Evasion>30</Evasion>
- <Category>monster</Category>
- <Speed>80</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityVindicator</Name>
- <AttackPower Probability="70">13</AttackPower>
- <Evasion>10</Evasion>
- <Category>monster</Category>
- <Speed>35</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityWitch</Name>
- <AttackPower Probability="75" Variance="1">5</AttackPower>
- <Evasion>8</Evasion>
- <Category>monster</Category>
- <Speed>35</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityWitherSkeleton</Name>
- <AttackPower Probability="70">8</AttackPower>
- <AttackEffect Probability="90">wither</AttackEffect>
- <Evasion>7</Evasion>
- <Category>monster</Category>
- <Speed>65</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityZombie</Name>
- <AttackPower Probability="70">3</AttackPower>
- <Evasion>5</Evasion>
- <Category>monster</Category>
- <Speed>25</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.monster.EntityZombieVillager</Name>
- <AttackPower Probability="70">3</AttackPower>
- <Evasion>5</Evasion>
- <Category>monster</Category>
- <Speed>25</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntityBat</Name>
- <AttackPower Probability="70">0</AttackPower>
- <Evasion>35</Evasion>
- <Category>passive</Category>
- <Speed>75</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>0</Defend>
- <Flee>90</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntityChicken</Name>
- <AttackPower Probability="70">0</AttackPower>
- <Evasion>10</Evasion>
- <Category>passive</Category>
- <Speed>35</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>0</Defend>
- <Flee>90</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntityCow</Name>
- <AttackPower Probability="50">0</AttackPower>
- <Evasion>1</Evasion>
- <Category>passive</Category>
- <Speed>20</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>10</Defend>
- <Flee>80</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntityDonkey</Name>
- <AttackPower Probability="70">0</AttackPower>
- <Evasion>10</Evasion>
- <Category>passive</Category>
- <Speed>65</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>0</Defend>
- <Flee>90</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntityHorse</Name>
- <AttackPower Probability="70">0</AttackPower>
- <Evasion>10</Evasion>
- <Category>passive</Category>
- <Speed>65</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>0</Defend>
- <Flee>90</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntityLlama</Name>
- <AttackPower Probability="70">1</AttackPower>
- <Evasion>10</Evasion>
- <Category>passive</Category>
- <Speed>50</Speed>
- <Decision>
- <Attack>65</Attack>
- <Defend>0</Defend>
- <Flee>25</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntityMooshroom</Name>
- <AttackPower Probability="70">0</AttackPower>
- <Evasion>1</Evasion>
- <Category>passive</Category>
- <Speed>20</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>10</Defend>
- <Flee>80</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntityMule</Name>
- <AttackPower Probability="70">0</AttackPower>
- <Evasion>10</Evasion>
- <Category>passive</Category>
- <Speed>50</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>0</Defend>
- <Flee>90</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntityOcelot</Name>
- <AttackPower Probability="70" Variance="1">1</AttackPower>
- <Evasion>10</Evasion>
- <Category>passive</Category>
- <Speed>75</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>0</Defend>
- <Flee>90</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntityParrot</Name>
- <AttackPower Probability="70">0</AttackPower>
- <Evasion>35</Evasion>
- <Category>passive</Category>
- <Speed>70</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>0</Defend>
- <Flee>90</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntityPig</Name>
- <AttackPower Probability="70">0</AttackPower>
- <Evasion>10</Evasion>
- <Category>passive</Category>
- <Speed>30</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>5</Defend>
- <Flee>85</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntityRabbit</Name>
- <AttackPower Probability="70">0</AttackPower>
- <Evasion>40</Evasion>
- <Category>passive</Category>
- <Speed>75</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>0</Defend>
- <Flee>100</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntitySheep</Name>
- <AttackPower Probability="70">0</AttackPower>
- <Evasion>5</Evasion>
- <Category>passive</Category>
- <Speed>30</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>0</Defend>
- <Flee>90</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntitySkeletonHorse</Name>
- <AttackPower Probability="70">0</AttackPower>
- <Evasion>5</Evasion>
- <Category>passive</Category>
- <Speed>65</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>0</Defend>
- <Flee>90</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntitySquid</Name>
- <AttackPower Probability="70">0</AttackPower>
- <Evasion>15</Evasion>
- <Category>passive</Category>
- <Speed>40</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>0</Defend>
- <Flee>90</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntityVillager</Name>
- <AttackPower Probability="70">0</AttackPower>
- <Evasion>5</Evasion>
- <Category>passive</Category>
- <Speed>35</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>10</Defend>
- <Flee>80</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntityWolf</Name>
- <AttackPower Probability="70">4</AttackPower>
- <Evasion>20</Evasion>
- <Category>animal</Category>
- <Speed>70</Speed>
- <Decision>
- <Attack>80</Attack>
- <Defend>15</Defend>
- <Flee>5</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.passive.EntityZombieHorse</Name>
- <AttackPower Probability="70">0</AttackPower>
- <Evasion>8</Evasion>
- <Category>passive</Category>
- <Speed>65</Speed>
- <Decision>
- <Attack>0</Attack>
- <Defend>0</Defend>
- <Flee>90</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.boss.EntityDragon</Name>
- <AttackPower Probability="70" Variance="2">10</AttackPower>
- <Evasion>27</Evasion>
- <Category>boss</Category>
- <Speed>63</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
- <EntityEntry>
- <Name>net.minecraft.entity.boss.EntityWither</Name>
- <AttackPower Probability="70">8</AttackPower>
- <Evasion>20</Evasion>
- <AttackEffect Probability="90">wither</AttackEffect>
- <Category>boss</Category>
- <Speed>68</Speed>
- <Decision>
- <Attack>100</Attack>
- <Defend>0</Defend>
- <Flee>0</Flee>
- </Decision>
- </EntityEntry>
-</TurnBasedMinecraftConfig>
\ No newline at end of file