WIP more backend work on battle logic

This commit is contained in:
Stephen Seo 2018-09-06 17:08:36 +09:00
parent 2aec173e80
commit 0520e163f8
10 changed files with 716 additions and 129 deletions

View file

@ -8,9 +8,8 @@ import com.seodisparate.TurnBasedMinecraft.common.Battle;
import com.seodisparate.TurnBasedMinecraft.common.BattleManager; import com.seodisparate.TurnBasedMinecraft.common.BattleManager;
import com.seodisparate.TurnBasedMinecraft.common.Config; import com.seodisparate.TurnBasedMinecraft.common.Config;
import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleDecision; import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleDecision;
import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleEntered;
import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleExited;
import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleInfo; import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleInfo;
import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleMessage;
import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleRequestInfo; import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleRequestInfo;
import com.seodisparate.TurnBasedMinecraft.common.networking.PacketHandler; import com.seodisparate.TurnBasedMinecraft.common.networking.PacketHandler;
@ -39,6 +38,7 @@ public class TurnBasedMinecraftMod
private static BattleManager battleManager; private static BattleManager battleManager;
private static int packetHandlerID = 0; private static int packetHandlerID = 0;
public static Entity attackingEntity; public static Entity attackingEntity;
public static int attackingDamage = 0;
public static Config config; public static Config config;
public static Battle currentBattle; public static Battle currentBattle;
@ -63,16 +63,6 @@ public class TurnBasedMinecraftMod
} }
// register packets // register packets
PacketHandler.INSTANCE.registerMessage(
PacketBattleEntered.HandlerBattleEntered.class,
PacketBattleEntered.class,
packetHandlerID++,
Side.CLIENT);
PacketHandler.INSTANCE.registerMessage(
PacketBattleExited.HandlerBattleExited.class,
PacketBattleExited.class,
packetHandlerID++,
Side.CLIENT);
PacketHandler.INSTANCE.registerMessage( PacketHandler.INSTANCE.registerMessage(
PacketBattleInfo.HandlerBattleInfo.class, PacketBattleInfo.HandlerBattleInfo.class,
PacketBattleInfo.class, PacketBattleInfo.class,
@ -88,6 +78,11 @@ public class TurnBasedMinecraftMod
PacketBattleDecision.class, PacketBattleDecision.class,
packetHandlerID++, packetHandlerID++,
Side.SERVER); Side.SERVER);
PacketHandler.INSTANCE.registerMessage(
PacketBattleMessage.HandlerBattleMessage.class,
PacketBattleMessage.class,
packetHandlerID++,
Side.CLIENT);
} }
@EventHandler @EventHandler
@ -111,6 +106,7 @@ public class TurnBasedMinecraftMod
logger.debug("Canceled LivingAttackEvent between " + attackingEntity + " and " + event.getEntity()); logger.debug("Canceled LivingAttackEvent between " + attackingEntity + " and " + event.getEntity());
event.setCanceled(true); event.setCanceled(true);
} }
attackingDamage = (int) event.getAmount();
} }
public static BattleManager getBattleManager() public static BattleManager getBattleManager()

View file

@ -2,19 +2,19 @@ package com.seodisparate.TurnBasedMinecraft.common;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Map; import java.util.Map;
import java.util.PriorityQueue; import java.util.PriorityQueue;
import java.util.SortedSet; import java.util.Queue;
import java.util.TreeSet;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod; import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod;
import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleInfo; import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleInfo;
import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleMessage;
import com.seodisparate.TurnBasedMinecraft.common.networking.PacketHandler; import com.seodisparate.TurnBasedMinecraft.common.networking.PacketHandler;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
@ -37,6 +37,9 @@ public class Battle
private AtomicInteger undecidedCount; private AtomicInteger undecidedCount;
private Duration timer; private Duration timer;
private boolean isServer;
private boolean battleEnded;
public enum State public enum State
{ {
DECISION, DECISION,
@ -79,8 +82,9 @@ public class Battle
} }
} }
public Battle(int id, Collection<Entity> sideA, Collection<Entity> sideB) public Battle(int id, Collection<Entity> sideA, Collection<Entity> sideB, boolean isServer)
{ {
this.isServer = isServer;
this.id = id; this.id = id;
this.sideA = new Hashtable<Integer, Combatant>(); this.sideA = new Hashtable<Integer, Combatant>();
this.sideB = new Hashtable<Integer, Combatant>(); this.sideB = new Hashtable<Integer, Combatant>();
@ -129,10 +133,22 @@ public class Battle
} }
} }
for(Combatant c : this.sideA.values())
{
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getEntityId(), 0, id);
}
for(Combatant c : this.sideB.values())
{
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getEntityId(), 0, id);
}
lastUpdated = null; lastUpdated = null;
state = State.DECISION; state = State.DECISION;
undecidedCount.set(playerCount.get()); undecidedCount.set(playerCount.get());
timer = TurnBasedMinecraftMod.BattleDecisionTime; timer = TurnBasedMinecraftMod.BattleDecisionTime;
battleEnded = false;
notifyPlayersBattleInfo();
} }
public int getId() public int getId()
@ -140,6 +156,21 @@ public class Battle
return id; return id;
} }
public Entity getCombatantEntity(int entityID)
{
Combatant c = sideA.get(entityID);
if(c != null)
{
return c.entity;
}
c = sideB.get(entityID);
if(c != null)
{
return c.entity;
}
return null;
}
public boolean hasCombatant(int entityID) public boolean hasCombatant(int entityID)
{ {
return sideA.containsKey(entityID) || sideB.containsKey(entityID); return sideA.containsKey(entityID) || sideB.containsKey(entityID);
@ -170,6 +201,8 @@ public class Battle
undecidedCount.incrementAndGet(); undecidedCount.incrementAndGet();
} }
} }
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getEntityId(), 0, id);
notifyPlayersBattleInfo();
} }
public void addCombatantToSideB(Entity e) public void addCombatantToSideB(Entity e)
@ -192,6 +225,8 @@ public class Battle
undecidedCount.incrementAndGet(); undecidedCount.incrementAndGet();
} }
} }
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getEntityId(), 0, id);
notifyPlayersBattleInfo();
} }
public void clearCombatants() public void clearCombatants()
@ -271,9 +306,9 @@ public class Battle
return state; return state;
} }
public void notifyPlayersBattleInfo() protected void notifyPlayersBattleInfo()
{ {
if(TurnBasedMinecraftMod.getBattleManager() == null) if(!isServer)
{ {
return; return;
} }
@ -284,29 +319,95 @@ public class Battle
} }
} }
public void update() /**
* @return True if battle has ended
*/
public boolean update()
{ {
if(battleEnded)
{
return true;
}
if(lastUpdated == null) if(lastUpdated == null)
{ {
lastUpdated = Instant.now(); lastUpdated = Instant.now();
update(Duration.ZERO); return update(Duration.ZERO);
} }
else else
{ {
Instant now = Instant.now(); Instant now = Instant.now();
update(Duration.between(lastUpdated, now)); Duration dt = Duration.between(lastUpdated, now);
lastUpdated = now; lastUpdated = now;
return update(dt);
} }
} }
private void update(final Duration dt) private void sendMessageToAllPlayers(PacketBattleMessage.MessageType type, int from, int to, int amount)
{ {
if(!isServer)
{
return;
}
for(Combatant p : players.values())
{
if(p.entity.isEntityAlive())
{
PacketHandler.INSTANCE.sendTo(new PacketBattleMessage(type, from, to, amount), (EntityPlayerMP)p.entity);
}
}
}
private boolean update(final Duration dt)
{
if(battleEnded)
{
return true;
}
switch(state) switch(state)
{ {
case DECISION: case DECISION:
timer = timer.minus(dt); timer = timer.minus(dt);
if(timer.isNegative() || timer.isZero() || undecidedCount.get() <= 0) if(timer.isNegative() || timer.isZero() || undecidedCount.get() <= 0)
{ {
for(Combatant c : sideA.values())
{
// picking decision for sideA non-players
if(!(c.entity instanceof EntityPlayer) && c.decision == Decision.UNDECIDED && c.entityInfo != null)
{
int percentage = (int)(Math.random() * 100);
if(percentage < c.entityInfo.decisionAttack)
{
c.decision = Decision.ATTACK;
}
else if(percentage - c.entityInfo.decisionAttack < c.entityInfo.decisionDefend)
{
c.decision = Decision.DEFEND;
}
else if(percentage - c.entityInfo.decisionAttack - c.entityInfo.decisionDefend < c.entityInfo.decisionFlee)
{
c.decision = Decision.FLEE;
}
}
}
for(Combatant c : sideB.values())
{
if(!(c.entity instanceof EntityPlayer) && c.decision == Decision.UNDECIDED && c.entityInfo != null)
{
int percentage = (int)(Math.random() * 100);
if(percentage < c.entityInfo.decisionAttack)
{
c.decision = Decision.ATTACK;
}
else if(percentage - c.entityInfo.decisionAttack < c.entityInfo.decisionDefend)
{
c.decision = Decision.DEFEND;
}
else if(percentage - c.entityInfo.decisionAttack - c.entityInfo.decisionDefend < c.entityInfo.decisionFlee)
{
c.decision = Decision.FLEE;
}
}
}
state = State.ACTION; state = State.ACTION;
timer = TurnBasedMinecraftMod.BattleDecisionTime; timer = TurnBasedMinecraftMod.BattleDecisionTime;
turnOrderQueue.clear(); turnOrderQueue.clear();
@ -319,7 +420,6 @@ public class Battle
turnOrderQueue.add(c); turnOrderQueue.add(c);
} }
update(Duration.ZERO); update(Duration.ZERO);
// TODO assign decisions to non-players
} }
break; break;
case ACTION: case ACTION:
@ -335,6 +435,7 @@ public class Battle
switch(next.decision) switch(next.decision)
{ {
case UNDECIDED: case UNDECIDED:
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DID_NOTHING, next.entity.getEntityId(), 0, 0);
next = turnOrderQueue.poll(); next = turnOrderQueue.poll();
continue; continue;
case ATTACK: case ATTACK:
@ -372,6 +473,7 @@ public class Battle
TurnBasedMinecraftMod.attackingEntity = next.entity; TurnBasedMinecraftMod.attackingEntity = next.entity;
((EntityPlayer)next.entity).attackTargetEntityWithCurrentItem(target.entity); ((EntityPlayer)next.entity).attackTargetEntityWithCurrentItem(target.entity);
TurnBasedMinecraftMod.attackingEntity = null; TurnBasedMinecraftMod.attackingEntity = null;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, next.entity.getEntityId(), target.entity.getEntityId(), TurnBasedMinecraftMod.attackingDamage);
if(!(target.entity instanceof EntityPlayer) && target.entityInfo.defenseDamage > 0) if(!(target.entity instanceof EntityPlayer) && target.entityInfo.defenseDamage > 0)
{ {
if((int)(Math.random() * 100) < target.entityInfo.defenseDamageProbability) if((int)(Math.random() * 100) < target.entityInfo.defenseDamageProbability)
@ -381,6 +483,7 @@ public class Battle
TurnBasedMinecraftMod.attackingEntity = target.entity; TurnBasedMinecraftMod.attackingEntity = target.entity;
next.entity.attackEntityFrom(defenseDamageSource, target.entityInfo.defenseDamage); next.entity.attackEntityFrom(defenseDamageSource, target.entityInfo.defenseDamage);
TurnBasedMinecraftMod.attackingEntity = null; TurnBasedMinecraftMod.attackingEntity = null;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, target.entity.getEntityId(), next.entity.getEntityId(), target.entityInfo.defenseDamage);
} }
} }
} }
@ -388,11 +491,13 @@ public class Battle
{ {
// blocked // blocked
--target.remainingDefenses; --target.remainingDefenses;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFEND, target.entity.getEntityId(), next.entity.getEntityId(), 0);
} }
} }
else else
{ {
// miss // miss
sendMessageToAllPlayers(PacketBattleMessage.MessageType.MISS, next.entity.getEntityId(), target.entity.getEntityId(), 0);
} }
} }
else else
@ -447,8 +552,9 @@ public class Battle
} }
// attack // attack
TurnBasedMinecraftMod.attackingEntity = next.entity; TurnBasedMinecraftMod.attackingEntity = next.entity;
target.entity.attackEntityFrom(damageSource, next.entityInfo.attackPower); target.entity.attackEntityFrom(damageSource, damageAmount);
TurnBasedMinecraftMod.attackingEntity = null; TurnBasedMinecraftMod.attackingEntity = null;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, next.entity.getEntityId(), target.entity.getEntityId(), damageAmount);
if(!(target.entity instanceof EntityPlayer) && target.entityInfo.defenseDamage > 0) if(!(target.entity instanceof EntityPlayer) && target.entityInfo.defenseDamage > 0)
{ {
if((int)(Math.random() * 100) < target.entityInfo.defenseDamageProbability) if((int)(Math.random() * 100) < target.entityInfo.defenseDamageProbability)
@ -458,6 +564,7 @@ public class Battle
TurnBasedMinecraftMod.attackingEntity = target.entity; TurnBasedMinecraftMod.attackingEntity = target.entity;
next.entity.attackEntityFrom(defenseDamageSource, target.entityInfo.defenseDamage); next.entity.attackEntityFrom(defenseDamageSource, target.entityInfo.defenseDamage);
TurnBasedMinecraftMod.attackingEntity = null; TurnBasedMinecraftMod.attackingEntity = null;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, target.entity.getEntityId(), next.entity.getEntityId(), target.entityInfo.defenseDamage);
} }
} }
} }
@ -465,16 +572,19 @@ public class Battle
{ {
// blocked // blocked
--target.remainingDefenses; --target.remainingDefenses;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFEND, target.entity.getEntityId(), next.entity.getEntityId(), 0);
} }
} }
else else
{ {
// miss // miss
sendMessageToAllPlayers(PacketBattleMessage.MessageType.MISS, next.entity.getEntityId(), target.entity.getEntityId(), 0);
} }
} }
break; break;
case DEFEND: case DEFEND:
next.remainingDefenses = TurnBasedMinecraftMod.config.getDefenseDuration(); next.remainingDefenses = TurnBasedMinecraftMod.config.getDefenseDuration();
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENDING, next.entity.getEntityId(), 0, 0);
break; break;
case FLEE: case FLEE:
int fastestEnemySpeed = 0; int fastestEnemySpeed = 0;
@ -552,13 +662,19 @@ public class Battle
{ {
sideB.remove(next.entity.getEntityId()); sideB.remove(next.entity.getEntityId());
} }
sendMessageToAllPlayers(PacketBattleMessage.MessageType.FLEE, next.entity.getEntityId(), 0, 1);
if(next.entity instanceof EntityPlayer) if(next.entity instanceof EntityPlayer)
{ {
players.remove(next.entity.getEntityId()); players.remove(next.entity.getEntityId());
playerCount.decrementAndGet(); playerCount.decrementAndGet();
// TODO notify player exited battle PacketHandler.INSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, 0, 0, 0), (EntityPlayerMP)next.entity);
} }
} }
else
{
// flee fail
sendMessageToAllPlayers(PacketBattleMessage.MessageType.FLEE, next.entity.getEntityId(), 0, 0);
}
break; break;
case USE_ITEM: case USE_ITEM:
break; break;
@ -578,8 +694,57 @@ public class Battle
break; break;
} }
case HEALTH_CHECK: case HEALTH_CHECK:
// TODO Queue<Integer> removeQueue = new ArrayDeque<Integer>();
for(Combatant c : sideA.values())
{
if(!c.entity.isEntityAlive())
{
removeQueue.add(c.entity.getEntityId());
if(c.entity instanceof EntityPlayer)
{
PacketHandler.INSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, c.entity.getEntityId(), 0, 0), (EntityPlayerMP)c.entity);
}
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DIED, c.entity.getEntityId(), 0, 0);
}
}
for(Combatant c : sideB.values())
{
if(!c.entity.isEntityAlive())
{
removeQueue.add(c.entity.getEntityId());
if(c.entity instanceof EntityPlayer)
{
PacketHandler.INSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, c.entity.getEntityId(), 0, 0), (EntityPlayerMP)c.entity);
}
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DIED, c.entity.getEntityId(), 0, 0);
}
}
boolean didRemove = !removeQueue.isEmpty();
Integer toRemove = removeQueue.poll();
while(toRemove != null)
{
sideA.remove(toRemove);
sideB.remove(toRemove);
if(players.remove(toRemove) != null)
{
playerCount.decrementAndGet();
}
toRemove = removeQueue.poll();
}
if(players.isEmpty() || sideA.isEmpty() || sideB.isEmpty())
{
battleEnded = true;
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENDED, 0, 0, 0);
}
else if(didRemove)
{
notifyPlayersBattleInfo();
}
state = State.DECISION;
undecidedCount.set(playerCount.get());
timer = TurnBasedMinecraftMod.BattleDecisionTime;
break; break;
} }
return battleEnded;
} }
} }

View file

@ -6,12 +6,9 @@ import java.util.Hashtable;
import java.util.Map; import java.util.Map;
import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod; import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod;
import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleEntered;
import com.seodisparate.TurnBasedMinecraft.common.networking.PacketHandler;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingAttackEvent;
public class BattleManager public class BattleManager
@ -104,13 +101,7 @@ public class BattleManager
{ {
battle.addCombatantToSideA(notInBattle); battle.addCombatantToSideA(notInBattle);
} }
if(notInBattle instanceof EntityPlayerMP)
{
PacketHandler.INSTANCE.sendTo(new PacketBattleEntered(IDCounter), (EntityPlayerMP)notInBattle);
}
battle.notifyPlayersBattleInfo();
return true; return true;
} }
@ -120,22 +111,8 @@ public class BattleManager
{ {
++IDCounter; ++IDCounter;
} }
Battle newBattle = new Battle(IDCounter, sideA, sideB); Battle newBattle = new Battle(IDCounter, sideA, sideB, true);
battleMap.put(IDCounter, newBattle); battleMap.put(IDCounter, newBattle);
for(Entity e : sideA)
{
if(e instanceof EntityPlayerMP)
{
PacketHandler.INSTANCE.sendTo(new PacketBattleEntered(IDCounter), (EntityPlayerMP)e);
}
}
for(Entity e : sideB)
{
if(e instanceof EntityPlayerMP)
{
PacketHandler.INSTANCE.sendTo(new PacketBattleEntered(IDCounter), (EntityPlayerMP)e);
}
}
newBattle.notifyPlayersBattleInfo(); newBattle.notifyPlayersBattleInfo();
return newBattle; return newBattle;
} }

View file

@ -1,5 +1,8 @@
package com.seodisparate.TurnBasedMinecraft.common; package com.seodisparate.TurnBasedMinecraft.common;
import java.util.ArrayDeque;
import java.util.Queue;
public class BattleUpdater implements Runnable public class BattleUpdater implements Runnable
{ {
private BattleManager manager; private BattleManager manager;
@ -14,11 +17,22 @@ public class BattleUpdater implements Runnable
@Override @Override
public void run() public void run()
{ {
Queue<Integer> endedQueue = new ArrayDeque<Integer>();
Integer ended;
while(isRunning) while(isRunning)
{ {
for(Battle e : manager.battleMap.values()) for(Battle e : manager.battleMap.values())
{ {
e.update(); if(e.update())
{
endedQueue.add(e.getId());
}
}
ended = endedQueue.poll();
while(ended != null)
{
manager.battleMap.remove(ended);
ended = endedQueue.poll();
} }
try { Thread.sleep(250); } catch (Exception e) { /* ignored */ } try { Thread.sleep(250); } catch (Exception e) { /* ignored */ }
} }

View file

@ -27,9 +27,9 @@ public class Config
private Map<String, EntityInfo> entityInfoMap; private Map<String, EntityInfo> entityInfoMap;
private Set<EntityInfo.Category> ignoreBattleTypes; private Set<EntityInfo.Category> ignoreBattleTypes;
private Logger logger; private Logger logger;
private int playerSpeed; private int playerSpeed = 50;
private int playerHasteSpeed; private int playerHasteSpeed = 80;
private int playerSlowSpeed; private int playerSlowSpeed = 20;
private int playerAttackProbability = 100; private int playerAttackProbability = 100;
private int playerEvasion = 10; private int playerEvasion = 10;
private int defenseDuration = 1; private int defenseDuration = 1;
@ -298,6 +298,28 @@ public class Config
{ {
eInfo.speed = Integer.parseInt(xmlReader.getElementText()); 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(classType))); } while(!(xmlReader.isEndElement() && xmlReader.getLocalName().equals(classType)));
entityInfoMap.put(eInfo.classType.getName(), eInfo); entityInfoMap.put(eInfo.classType.getName(), eInfo);
@ -368,6 +390,10 @@ public class Config
protected EntityInfo getMatchingEntityInfo(Object entity) protected EntityInfo getMatchingEntityInfo(Object entity)
{ {
if(entity == null)
{
return null;
}
EntityInfo matching = entityInfoMap.get(entity.getClass().getName()); EntityInfo matching = entityInfoMap.get(entity.getClass().getName());
if(matching.classType.isInstance(entity)) if(matching.classType.isInstance(entity))
{ {

View file

@ -19,6 +19,9 @@ public class EntityInfo
public int evasion; public int evasion;
public int speed; public int speed;
public Category category; public Category category;
public int decisionAttack;
public int decisionDefend;
public int decisionFlee;
public enum Category public enum Category
{ {
@ -208,6 +211,9 @@ public class EntityInfo
evasion = 15; evasion = 15;
speed = 50; speed = 50;
category = Category.UNKNOWN; category = Category.UNKNOWN;
decisionAttack = 70;
decisionDefend = 20;
decisionFlee = 10;
} }
public EntityInfo clone() public EntityInfo clone()
@ -230,6 +236,9 @@ public class EntityInfo
newEntityInfo.evasion = evasion; newEntityInfo.evasion = evasion;
newEntityInfo.speed = speed; newEntityInfo.speed = speed;
newEntityInfo.category = category; newEntityInfo.category = category;
newEntityInfo.decisionAttack = decisionAttack;
newEntityInfo.decisionDefend = decisionDefend;
newEntityInfo.decisionFlee = decisionFlee;
return newEntityInfo; return newEntityInfo;
} }
} }

View file

@ -1,43 +0,0 @@
package com.seodisparate.TurnBasedMinecraft.common.networking;
import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod;
import com.seodisparate.TurnBasedMinecraft.common.Battle;
import io.netty.buffer.ByteBuf;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
public class PacketBattleEntered implements IMessage
{
private int battleID;
public PacketBattleEntered() {}
public PacketBattleEntered(int battleID)
{
this.battleID = battleID;
}
@Override
public void fromBytes(ByteBuf buf)
{
battleID = buf.readInt();
}
@Override
public void toBytes(ByteBuf buf)
{
buf.writeInt(battleID);
}
public static class HandlerBattleEntered implements IMessageHandler<PacketBattleEntered, IMessage>
{
@Override
public IMessage onMessage(PacketBattleEntered message, MessageContext ctx)
{
TurnBasedMinecraftMod.currentBattle = new Battle(message.battleID, null, null);
return null;
}
}
}

View file

@ -1,31 +0,0 @@
package com.seodisparate.TurnBasedMinecraft.common.networking;
import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod;
import io.netty.buffer.ByteBuf;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
public class PacketBattleExited implements IMessage
{
@Override
public void fromBytes(ByteBuf buf)
{
}
@Override
public void toBytes(ByteBuf buf)
{
}
public static class HandlerBattleExited implements IMessageHandler<PacketBattleExited, IMessage>
{
@Override
public IMessage onMessage(PacketBattleExited message, MessageContext ctx)
{
TurnBasedMinecraftMod.currentBattle = null;
return null;
}
}
}

View file

@ -0,0 +1,233 @@
package com.seodisparate.TurnBasedMinecraft.common.networking;
import java.util.HashMap;
import java.util.Map;
import com.seodisparate.TurnBasedMinecraft.TurnBasedMinecraftMod;
import com.seodisparate.TurnBasedMinecraft.common.Battle;
import io.netty.buffer.ByteBuf;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.scoreboard.ScorePlayerTeam;
import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
public class PacketBattleMessage implements IMessage
{
public enum MessageType
{
ENTERED(0),
FLEE(1),
DIED(2),
ENDED(3),
ATTACK(4),
DEFEND(5),
DEFENSE_DAMAGE(6),
MISS(7),
DEFENDING(8),
DID_NOTHING(9);
private int value;
private static Map<Integer, MessageType> map = new HashMap<Integer, MessageType>();
private MessageType(int value)
{
this.value = value;
}
public int getValue()
{
return value;
}
static
{
for(MessageType type : MessageType.values())
{
map.put(type.getValue(), type);
}
}
public static MessageType valueOf(int value)
{
return map.get(value);
}
}
MessageType messageType;
int entityIDFrom;
int entityIDTo;
int amount;
public PacketBattleMessage() {}
public PacketBattleMessage(MessageType messageType, int entityIDFrom, int entityIDTo, int amount)
{
this.messageType = messageType;
this.entityIDFrom = entityIDFrom;
this.entityIDTo = entityIDTo;
this.amount = amount;
}
@Override
public void fromBytes(ByteBuf buf)
{
messageType = MessageType.valueOf(buf.readInt());
entityIDFrom = buf.readInt();
entityIDTo = buf.readInt();
amount = buf.readInt();
}
@Override
public void toBytes(ByteBuf buf)
{
buf.writeInt(messageType.getValue());
buf.writeInt(entityIDFrom);
buf.writeInt(entityIDTo);
buf.writeInt(amount);
}
public static class HandlerBattleMessage implements IMessageHandler<PacketBattleMessage, IMessage>
{
@Override
public IMessage onMessage(PacketBattleMessage message, MessageContext ctx)
{
Entity fromEntity = Minecraft.getMinecraft().world.getEntityByID(message.entityIDFrom);
String from = "Unknown";
if(fromEntity != null)
{
if(fromEntity.hasCustomName())
{
from = fromEntity.getCustomNameTag();
}
else if(fromEntity instanceof EntityPlayer)
{
from = ScorePlayerTeam.formatPlayerName(fromEntity.getTeam(), fromEntity.getName());
}
else
{
from = fromEntity.getName();
}
}
else if(TurnBasedMinecraftMod.currentBattle != null)
{
fromEntity = TurnBasedMinecraftMod.currentBattle.getCombatantEntity(message.entityIDFrom);
if(fromEntity != null)
{
if(fromEntity.hasCustomName())
{
from = fromEntity.getCustomNameTag();
}
else if(fromEntity instanceof EntityPlayer)
{
from = ScorePlayerTeam.formatPlayerName(fromEntity.getTeam(), fromEntity.getName());
}
else
{
from = fromEntity.getName();
}
}
}
Entity toEntity = Minecraft.getMinecraft().world.getEntityByID(message.entityIDTo);
String to = "Unknown";
if(toEntity != null)
{
if(toEntity.hasCustomName())
{
to = toEntity.getCustomNameTag();
}
else if(toEntity instanceof EntityPlayer)
{
to = ScorePlayerTeam.formatPlayerName(toEntity.getTeam(), toEntity.getName());
}
else
{
to = toEntity.getName();
}
}
else if(TurnBasedMinecraftMod.currentBattle != null)
{
toEntity = TurnBasedMinecraftMod.currentBattle.getCombatantEntity(message.entityIDTo);
if(toEntity != null)
{
if(toEntity.hasCustomName())
{
to = toEntity.getCustomNameTag();
}
else if(toEntity instanceof EntityPlayer)
{
to = ScorePlayerTeam.formatPlayerName(toEntity.getTeam(), toEntity.getName());
}
else
{
to = toEntity.getName();
}
}
}
switch(message.messageType)
{
case ENTERED:
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
from + " entered battle!"));
if(TurnBasedMinecraftMod.currentBattle == null || TurnBasedMinecraftMod.currentBattle.getId() != message.amount)
{
TurnBasedMinecraftMod.currentBattle = new Battle(message.amount, null, null, false);
}
break;
case FLEE:
if(message.amount != 0)
{
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
from + " fled battle!"));
}
else
{
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
from + " tried to flee battle but failed!"));
}
break;
case DIED:
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
from + " died in battle!"));
break;
case ENDED:
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
"Battle has ended!"));
TurnBasedMinecraftMod.currentBattle = null;
// TODO kick player out of battle
break;
case ATTACK:
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
from + " attacked " + to + " and dealt " + message.amount + " damage!"));
break;
case DEFEND:
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
from + " blocked " + to + "'s attack!"));
break;
case DEFENSE_DAMAGE:
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
from + " retaliated from " + to + "'s attack and dealt " + message.amount + " damage!"));
break;
case MISS:
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
from + " attacked " + to + " but missed!"));
break;
case DEFENDING:
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
from + " is defending!"));
break;
case DID_NOTHING:
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentString(
from + " did nothing!"));
break;
}
return null;
}
}
}

View file

@ -28,12 +28,18 @@
<!-- 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. --> <!-- 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. --> <!-- Category: Sets the type of the entity, used by "IgnoreBattleTypes" to determine what types ignore battle. -->
<!-- Conflicts: (Optional) Tells the mod that this entity should not be mistaken for the listed entities (possible because some entities derive from others; CaveSpiders are also Spiders). --> <!-- Conflicts: (Optional) Tells the mod that this entity should not be mistaken for the listed entities (possible because some entities derive from others; CaveSpiders are also Spiders). -->
<!-- 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 -->
<net.minecraft.entity.monster.EntityBlaze> <net.minecraft.entity.monster.EntityBlaze>
<AttackPower Probability="50">5</AttackPower> <AttackPower Probability="50">5</AttackPower>
<AttackEffect Probability="75">fire</AttackEffect> <AttackEffect Probability="75">fire</AttackEffect>
<Evasion>5</Evasion> <Evasion>5</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>45</Speed> <Speed>45</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityBlaze> </net.minecraft.entity.monster.EntityBlaze>
<net.minecraft.entity.monster.EntityCaveSpider> <net.minecraft.entity.monster.EntityCaveSpider>
<AttackPower Probability="75">2</AttackPower> <AttackPower Probability="75">2</AttackPower>
@ -41,6 +47,11 @@
<Evasion>35</Evasion> <Evasion>35</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>75</Speed> <Speed>75</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityCaveSpider> </net.minecraft.entity.monster.EntityCaveSpider>
<net.minecraft.entity.monster.EntityCreeper> <net.minecraft.entity.monster.EntityCreeper>
<IgnoreBattle>true</IgnoreBattle> <IgnoreBattle>true</IgnoreBattle>
@ -48,6 +59,11 @@
<Evasion>5</Evasion> <Evasion>5</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>25</Speed> <Speed>25</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityCreeper> </net.minecraft.entity.monster.EntityCreeper>
<net.minecraft.entity.monster.EntityElderGuardian> <net.minecraft.entity.monster.EntityElderGuardian>
<AttackPower Probability="65">8</AttackPower> <AttackPower Probability="65">8</AttackPower>
@ -55,24 +71,44 @@
<Evasion>25</Evasion> <Evasion>25</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>45</Speed> <Speed>45</Speed>
<Decision>
<Attack>80</Attack>
<Defend>20</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityElderGuardian> </net.minecraft.entity.monster.EntityElderGuardian>
<net.minecraft.entity.monster.EntityEnderman> <net.minecraft.entity.monster.EntityEnderman>
<AttackPower Probability="80">7</AttackPower> <AttackPower Probability="80">7</AttackPower>
<Evasion>40</Evasion> <Evasion>40</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>70</Speed> <Speed>70</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityEnderman> </net.minecraft.entity.monster.EntityEnderman>
<net.minecraft.entity.monster.EntityEndermite> <net.minecraft.entity.monster.EntityEndermite>
<AttackPower Probability="80">2</AttackPower> <AttackPower Probability="80">2</AttackPower>
<Evasion>40</Evasion> <Evasion>40</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>35</Speed> <Speed>35</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityEndermite> </net.minecraft.entity.monster.EntityEndermite>
<net.minecraft.entity.monster.EntityEvoker> <net.minecraft.entity.monster.EntityEvoker>
<AttackPower Probability="60">6</AttackPower> <AttackPower Probability="60">6</AttackPower>
<Evasion>35</Evasion> <Evasion>35</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>35</Speed> <Speed>35</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityEvoker> </net.minecraft.entity.monster.EntityEvoker>
<net.minecraft.entity.monster.EntityGhast> <net.minecraft.entity.monster.EntityGhast>
<IgnoreBattle>true</IgnoreBattle> <IgnoreBattle>true</IgnoreBattle>
@ -80,12 +116,22 @@
<Evasion>35</Evasion> <Evasion>35</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>60</Speed> <Speed>60</Speed>
<Decision>
<Attack>75</Attack>
<Defend>0</Defend>
<Flee>25</Flee>
</Decision>
</net.minecraft.entity.monster.EntityGhast> </net.minecraft.entity.monster.EntityGhast>
<net.minecraft.entity.monster.EntityGiantZombie> <net.minecraft.entity.monster.EntityGiantZombie>
<AttackPower Probability="35">11</AttackPower> <AttackPower Probability="35">11</AttackPower>
<Evasion>2</Evasion> <Evasion>2</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>45</Speed> <Speed>45</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityGiantZombie> </net.minecraft.entity.monster.EntityGiantZombie>
<net.minecraft.entity.monster.EntityGuardian> <net.minecraft.entity.monster.EntityGuardian>
<AttackPower Probability="55">6</AttackPower> <AttackPower Probability="55">6</AttackPower>
@ -93,6 +139,11 @@
<Evasion>25</Evasion> <Evasion>25</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>50</Speed> <Speed>50</Speed>
<Decision>
<Attack>80</Attack>
<Defend>20</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityGuardian> </net.minecraft.entity.monster.EntityGuardian>
<net.minecraft.entity.monster.EntityHusk> <net.minecraft.entity.monster.EntityHusk>
<AttackPower Probability="70">3</AttackPower> <AttackPower Probability="70">3</AttackPower>
@ -100,60 +151,110 @@
<Evasion>5</Evasion> <Evasion>5</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>25</Speed> <Speed>25</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityHusk> </net.minecraft.entity.monster.EntityHusk>
<net.minecraft.entity.monster.EntityIronGolem> <net.minecraft.entity.monster.EntityIronGolem>
<AttackPower Probability="85" Variance="7">14</AttackPower> <AttackPower Probability="85" Variance="7">14</AttackPower>
<Evasion>5</Evasion> <Evasion>5</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>45</Speed> <Speed>45</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityIronGolem> </net.minecraft.entity.monster.EntityIronGolem>
<net.minecraft.entity.monster.EntityMagmaCube> <net.minecraft.entity.monster.EntityMagmaCube>
<AttackPower Probability="35">3</AttackPower> <AttackPower Probability="35">3</AttackPower>
<Evasion>12</Evasion> <Evasion>12</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>35</Speed> <Speed>35</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityMagmaCube> </net.minecraft.entity.monster.EntityMagmaCube>
<net.minecraft.entity.monster.EntityPigZombie> <net.minecraft.entity.monster.EntityPigZombie>
<AttackPower Probability="70">8</AttackPower> <AttackPower Probability="70">8</AttackPower>
<Evasion>10</Evasion> <Evasion>10</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>50</Speed> <Speed>50</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityPigZombie> </net.minecraft.entity.monster.EntityPigZombie>
<net.minecraft.entity.monster.EntityPolarBear> <net.minecraft.entity.monster.EntityPolarBear>
<AttackPower Probability="67">6</AttackPower> <AttackPower Probability="67">6</AttackPower>
<Evasion>5</Evasion> <Evasion>5</Evasion>
<Category>animal</Category> <Category>animal</Category>
<Speed>35</Speed> <Speed>35</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityPolarBear> </net.minecraft.entity.monster.EntityPolarBear>
<net.minecraft.entity.monster.EntityShulker> <net.minecraft.entity.monster.EntityShulker>
<AttackPower Probability="80">4</AttackPower> <AttackPower Probability="80">4</AttackPower>
<Evasion>15</Evasion> <Evasion>15</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>10</Speed> <Speed>10</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityShulker> </net.minecraft.entity.monster.EntityShulker>
<net.minecraft.entity.monster.EntitySilverFish> <net.minecraft.entity.monster.EntitySilverFish>
<AttackPower Probability="85">1</AttackPower> <AttackPower Probability="85">1</AttackPower>
<Evasion>37</Evasion> <Evasion>37</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>35</Speed> <Speed>35</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntitySilverFish> </net.minecraft.entity.monster.EntitySilverFish>
<net.minecraft.entity.monster.EntitySkeleton> <net.minecraft.entity.monster.EntitySkeleton>
<AttackPower Probability="75" Variance="1">3</AttackPower> <AttackPower Probability="75" Variance="1">3</AttackPower>
<Evasion>13</Evasion> <Evasion>13</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>30</Speed> <Speed>30</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntitySkeleton> </net.minecraft.entity.monster.EntitySkeleton>
<net.minecraft.entity.monster.EntitySlime> <net.minecraft.entity.monster.EntitySlime>
<AttackPower Probability="35">2</AttackPower> <AttackPower Probability="35">2</AttackPower>
<Evasion>10</Evasion> <Evasion>10</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>30</Speed> <Speed>30</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntitySlime> </net.minecraft.entity.monster.EntitySlime>
<net.minecraft.entity.monster.EntitySnowman> <net.minecraft.entity.monster.EntitySnowman>
<AttackPower Probability="80">0</AttackPower> <AttackPower Probability="80">0</AttackPower>
<Evasion>5</Evasion> <Evasion>5</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>60</Speed> <Speed>60</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntitySnowman> </net.minecraft.entity.monster.EntitySnowman>
<net.minecraft.entity.monster.EntitySpider> <net.minecraft.entity.monster.EntitySpider>
<AttackPower Probability="70">2</AttackPower> <AttackPower Probability="70">2</AttackPower>
@ -163,6 +264,11 @@
</Conflicts> </Conflicts>
<Category>monster</Category> <Category>monster</Category>
<Speed>70</Speed> <Speed>70</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntitySpider> </net.minecraft.entity.monster.EntitySpider>
<net.minecraft.entity.monster.EntityStray> <net.minecraft.entity.monster.EntityStray>
<AttackPower Probability="75" Variance="1">3</AttackPower> <AttackPower Probability="75" Variance="1">3</AttackPower>
@ -170,24 +276,44 @@
<Evasion>13</Evasion> <Evasion>13</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>30</Speed> <Speed>30</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityStray> </net.minecraft.entity.monster.EntityStray>
<net.minecraft.entity.monster.EntityVex> <net.minecraft.entity.monster.EntityVex>
<AttackPower Probability="65">9</AttackPower> <AttackPower Probability="65">9</AttackPower>
<Evasion>30</Evasion> <Evasion>30</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>80</Speed> <Speed>80</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityVex> </net.minecraft.entity.monster.EntityVex>
<net.minecraft.entity.monster.EntityVindicator> <net.minecraft.entity.monster.EntityVindicator>
<AttackPower Probability="70">13</AttackPower> <AttackPower Probability="70">13</AttackPower>
<Evasion>10</Evasion> <Evasion>10</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>35</Speed> <Speed>35</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityVindicator> </net.minecraft.entity.monster.EntityVindicator>
<net.minecraft.entity.monster.EntityWitch> <net.minecraft.entity.monster.EntityWitch>
<AttackPower Probability="75" Variance="1">5</AttackPower> <AttackPower Probability="75" Variance="1">5</AttackPower>
<Evasion>8</Evasion> <Evasion>8</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>35</Speed> <Speed>35</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityWitch> </net.minecraft.entity.monster.EntityWitch>
<net.minecraft.entity.monster.EntityWitherSkeleton> <net.minecraft.entity.monster.EntityWitherSkeleton>
<AttackPower Probability="70">8</AttackPower> <AttackPower Probability="70">8</AttackPower>
@ -195,6 +321,11 @@
<Evasion>7</Evasion> <Evasion>7</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>65</Speed> <Speed>65</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityWitherSkeleton> </net.minecraft.entity.monster.EntityWitherSkeleton>
<net.minecraft.entity.monster.EntityZombie> <net.minecraft.entity.monster.EntityZombie>
<AttackPower Probability="70">3</AttackPower> <AttackPower Probability="70">3</AttackPower>
@ -205,24 +336,44 @@
<Evasion>5</Evasion> <Evasion>5</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>25</Speed> <Speed>25</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityZombie> </net.minecraft.entity.monster.EntityZombie>
<net.minecraft.entity.monster.EntityZombieVillager> <net.minecraft.entity.monster.EntityZombieVillager>
<AttackPower Probability="70">3</AttackPower> <AttackPower Probability="70">3</AttackPower>
<Evasion>5</Evasion> <Evasion>5</Evasion>
<Category>monster</Category> <Category>monster</Category>
<Speed>25</Speed> <Speed>25</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.monster.EntityZombieVillager> </net.minecraft.entity.monster.EntityZombieVillager>
<net.minecraft.entity.passive.EntityBat> <net.minecraft.entity.passive.EntityBat>
<AttackPower Probability="70">0</AttackPower> <AttackPower Probability="70">0</AttackPower>
<Evasion>35</Evasion> <Evasion>35</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>75</Speed> <Speed>75</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</net.minecraft.entity.passive.EntityBat> </net.minecraft.entity.passive.EntityBat>
<net.minecraft.entity.passive.EntityChicken> <net.minecraft.entity.passive.EntityChicken>
<AttackPower Probability="70">0</AttackPower> <AttackPower Probability="70">0</AttackPower>
<Evasion>10</Evasion> <Evasion>10</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>35</Speed> <Speed>35</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</net.minecraft.entity.passive.EntityChicken> </net.minecraft.entity.passive.EntityChicken>
<net.minecraft.entity.passive.EntityCow> <net.minecraft.entity.passive.EntityCow>
<AttackPower Probability="50">0</AttackPower> <AttackPower Probability="50">0</AttackPower>
@ -232,102 +383,187 @@
</Conflicts> </Conflicts>
<Category>passive</Category> <Category>passive</Category>
<Speed>20</Speed> <Speed>20</Speed>
<Decision>
<Attack>0</Attack>
<Defend>10</Defend>
<Flee>80</Flee>
</Decision>
</net.minecraft.entity.passive.EntityCow> </net.minecraft.entity.passive.EntityCow>
<net.minecraft.entity.passive.EntityDonkey> <net.minecraft.entity.passive.EntityDonkey>
<AttackPower Probability="70">0</AttackPower> <AttackPower Probability="70">0</AttackPower>
<Evasion>10</Evasion> <Evasion>10</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>65</Speed> <Speed>65</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</net.minecraft.entity.passive.EntityDonkey> </net.minecraft.entity.passive.EntityDonkey>
<net.minecraft.entity.passive.EntityHorse> <net.minecraft.entity.passive.EntityHorse>
<AttackPower Probability="70">0</AttackPower> <AttackPower Probability="70">0</AttackPower>
<Evasion>10</Evasion> <Evasion>10</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>65</Speed> <Speed>65</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</net.minecraft.entity.passive.EntityHorse> </net.minecraft.entity.passive.EntityHorse>
<net.minecraft.entity.passive.EntityLlama> <net.minecraft.entity.passive.EntityLlama>
<AttackPower Probability="70">1</AttackPower> <AttackPower Probability="70">1</AttackPower>
<Evasion>10</Evasion> <Evasion>10</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>50</Speed> <Speed>50</Speed>
<Decision>
<Attack>65</Attack>
<Defend>0</Defend>
<Flee>25</Flee>
</Decision>
</net.minecraft.entity.passive.EntityLlama> </net.minecraft.entity.passive.EntityLlama>
<net.minecraft.entity.passive.EntityMooshroom> <net.minecraft.entity.passive.EntityMooshroom>
<AttackPower Probability="70">0</AttackPower> <AttackPower Probability="70">0</AttackPower>
<Evasion>1</Evasion> <Evasion>1</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>20</Speed> <Speed>20</Speed>
<Decision>
<Attack>0</Attack>
<Defend>10</Defend>
<Flee>80</Flee>
</Decision>
</net.minecraft.entity.passive.EntityMooshroom> </net.minecraft.entity.passive.EntityMooshroom>
<net.minecraft.entity.passive.EntityMule> <net.minecraft.entity.passive.EntityMule>
<AttackPower Probability="70">0</AttackPower> <AttackPower Probability="70">0</AttackPower>
<Evasion>10</Evasion> <Evasion>10</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>50</Speed> <Speed>50</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</net.minecraft.entity.passive.EntityMule> </net.minecraft.entity.passive.EntityMule>
<net.minecraft.entity.passive.EntityOcelot> <net.minecraft.entity.passive.EntityOcelot>
<AttackPower Probability="70" Variance="1">1</AttackPower> <AttackPower Probability="70" Variance="1">1</AttackPower>
<Evasion>10</Evasion> <Evasion>10</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>75</Speed> <Speed>75</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</net.minecraft.entity.passive.EntityOcelot> </net.minecraft.entity.passive.EntityOcelot>
<net.minecraft.entity.passive.EntityParrot> <net.minecraft.entity.passive.EntityParrot>
<AttackPower Probability="70">0</AttackPower> <AttackPower Probability="70">0</AttackPower>
<Evasion>35</Evasion> <Evasion>35</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>70</Speed> <Speed>70</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</net.minecraft.entity.passive.EntityParrot> </net.minecraft.entity.passive.EntityParrot>
<net.minecraft.entity.passive.EntityPig> <net.minecraft.entity.passive.EntityPig>
<AttackPower Probability="70">0</AttackPower> <AttackPower Probability="70">0</AttackPower>
<Evasion>10</Evasion> <Evasion>10</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>30</Speed> <Speed>30</Speed>
<Decision>
<Attack>0</Attack>
<Defend>5</Defend>
<Flee>85</Flee>
</Decision>
</net.minecraft.entity.passive.EntityPig> </net.minecraft.entity.passive.EntityPig>
<net.minecraft.entity.passive.EntityRabbit> <net.minecraft.entity.passive.EntityRabbit>
<AttackPower Probability="70">0</AttackPower> <AttackPower Probability="70">0</AttackPower>
<Evasion>40</Evasion> <Evasion>40</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>75</Speed> <Speed>75</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>100</Flee>
</Decision>
</net.minecraft.entity.passive.EntityRabbit> </net.minecraft.entity.passive.EntityRabbit>
<net.minecraft.entity.passive.EntitySheep> <net.minecraft.entity.passive.EntitySheep>
<AttackPower Probability="70">0</AttackPower> <AttackPower Probability="70">0</AttackPower>
<Evasion>5</Evasion> <Evasion>5</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>30</Speed> <Speed>30</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</net.minecraft.entity.passive.EntitySheep> </net.minecraft.entity.passive.EntitySheep>
<net.minecraft.entity.passive.EntitySkeletonHorse> <net.minecraft.entity.passive.EntitySkeletonHorse>
<AttackPower Probability="70">0</AttackPower> <AttackPower Probability="70">0</AttackPower>
<Evasion>5</Evasion> <Evasion>5</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>65</Speed> <Speed>65</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</net.minecraft.entity.passive.EntitySkeletonHorse> </net.minecraft.entity.passive.EntitySkeletonHorse>
<net.minecraft.entity.passive.EntitySquid> <net.minecraft.entity.passive.EntitySquid>
<AttackPower Probability="70">0</AttackPower> <AttackPower Probability="70">0</AttackPower>
<Evasion>15</Evasion> <Evasion>15</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>40</Speed> <Speed>40</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</net.minecraft.entity.passive.EntitySquid> </net.minecraft.entity.passive.EntitySquid>
<net.minecraft.entity.passive.EntityVillager> <net.minecraft.entity.passive.EntityVillager>
<AttackPower Probability="70">0</AttackPower> <AttackPower Probability="70">0</AttackPower>
<Evasion>5</Evasion> <Evasion>5</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>35</Speed> <Speed>35</Speed>
<Decision>
<Attack>0</Attack>
<Defend>10</Defend>
<Flee>80</Flee>
</Decision>
</net.minecraft.entity.passive.EntityVillager> </net.minecraft.entity.passive.EntityVillager>
<net.minecraft.entity.passive.EntityWolf> <net.minecraft.entity.passive.EntityWolf>
<AttackPower Probability="70">4</AttackPower> <AttackPower Probability="70">4</AttackPower>
<Evasion>20</Evasion> <Evasion>20</Evasion>
<Category>animal</Category> <Category>animal</Category>
<Speed>70</Speed> <Speed>70</Speed>
<Decision>
<Attack>80</Attack>
<Defend>15</Defend>
<Flee>5</Flee>
</Decision>
</net.minecraft.entity.passive.EntityWolf> </net.minecraft.entity.passive.EntityWolf>
<net.minecraft.entity.passive.EntityZombieHorse> <net.minecraft.entity.passive.EntityZombieHorse>
<AttackPower Probability="70">0</AttackPower> <AttackPower Probability="70">0</AttackPower>
<Evasion>8</Evasion> <Evasion>8</Evasion>
<Category>passive</Category> <Category>passive</Category>
<Speed>65</Speed> <Speed>65</Speed>
<Decision>
<Attack>0</Attack>
<Defend>0</Defend>
<Flee>90</Flee>
</Decision>
</net.minecraft.entity.passive.EntityZombieHorse> </net.minecraft.entity.passive.EntityZombieHorse>
<net.minecraft.entity.boss.EntityDragon> <net.minecraft.entity.boss.EntityDragon>
<AttackPower Probability="70" Variance="2">10</AttackPower> <AttackPower Probability="70" Variance="2">10</AttackPower>
<Evasion>27</Evasion> <Evasion>27</Evasion>
<Category>boss</Category> <Category>boss</Category>
<Speed>63</Speed> <Speed>63</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.boss.EntityDragon> </net.minecraft.entity.boss.EntityDragon>
<net.minecraft.entity.boss.EntityWither> <net.minecraft.entity.boss.EntityWither>
<AttackPower Probability="70">8</AttackPower> <AttackPower Probability="70">8</AttackPower>
@ -335,6 +571,11 @@
<AttackEffect Probability="90">wither</AttackEffect> <AttackEffect Probability="90">wither</AttackEffect>
<Category>boss</Category> <Category>boss</Category>
<Speed>68</Speed> <Speed>68</Speed>
<Decision>
<Attack>100</Attack>
<Defend>0</Defend>
<Flee>0</Flee>
</Decision>
</net.minecraft.entity.boss.EntityWither> </net.minecraft.entity.boss.EntityWither>
</EntityStats> </EntityStats>
</TurnBasedMinecraftConfig> </TurnBasedMinecraftConfig>