2018-08-28 06:13:14 +00:00
|
|
|
package com.seodisparate.TurnBasedMinecraft.common;
|
|
|
|
|
2018-09-06 08:08:36 +00:00
|
|
|
import java.util.ArrayDeque;
|
2018-08-29 06:09:44 +00:00
|
|
|
import java.util.ArrayList;
|
2018-08-28 06:13:14 +00:00
|
|
|
import java.util.Collection;
|
2018-08-29 06:09:44 +00:00
|
|
|
import java.util.HashMap;
|
2018-08-28 06:13:14 +00:00
|
|
|
import java.util.Hashtable;
|
|
|
|
import java.util.Map;
|
2018-09-04 06:21:49 +00:00
|
|
|
import java.util.PriorityQueue;
|
2018-09-06 08:08:36 +00:00
|
|
|
import java.util.Queue;
|
2018-09-11 06:15:31 +00:00
|
|
|
import java.util.Set;
|
2018-09-04 06:21:49 +00:00
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
2018-08-28 06:13:14 +00:00
|
|
|
|
2018-08-30 07:15:20 +00:00
|
|
|
import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleInfo;
|
2018-09-06 08:08:36 +00:00
|
|
|
import com.seodisparate.TurnBasedMinecraft.common.networking.PacketBattleMessage;
|
2018-08-29 06:09:44 +00:00
|
|
|
|
2018-08-28 06:13:14 +00:00
|
|
|
import net.minecraft.entity.Entity;
|
2018-09-05 06:54:06 +00:00
|
|
|
import net.minecraft.entity.EntityLivingBase;
|
2018-08-29 06:09:44 +00:00
|
|
|
import net.minecraft.entity.player.EntityPlayer;
|
2018-08-30 07:15:20 +00:00
|
|
|
import net.minecraft.entity.player.EntityPlayerMP;
|
2018-09-07 07:41:22 +00:00
|
|
|
import net.minecraft.init.Items;
|
|
|
|
import net.minecraft.item.Item;
|
2018-09-17 06:49:10 +00:00
|
|
|
import net.minecraft.item.ItemBow;
|
2018-09-07 07:41:22 +00:00
|
|
|
import net.minecraft.item.ItemFood;
|
|
|
|
import net.minecraft.item.ItemLingeringPotion;
|
|
|
|
import net.minecraft.item.ItemPotion;
|
|
|
|
import net.minecraft.item.ItemSplashPotion;
|
|
|
|
import net.minecraft.item.ItemStack;
|
2018-09-05 06:54:06 +00:00
|
|
|
import net.minecraft.util.DamageSource;
|
2018-09-17 04:27:13 +00:00
|
|
|
import net.minecraftforge.fml.common.FMLCommonHandler;
|
2018-08-28 06:13:14 +00:00
|
|
|
|
|
|
|
public class Battle
|
|
|
|
{
|
2018-08-29 06:09:44 +00:00
|
|
|
private final int id;
|
|
|
|
private Map<Integer, Combatant> sideA;
|
|
|
|
private Map<Integer, Combatant> sideB;
|
2018-09-04 06:21:49 +00:00
|
|
|
private Map<Integer, Combatant> players;
|
|
|
|
private PriorityQueue<Combatant> turnOrderQueue;
|
2018-08-28 06:13:14 +00:00
|
|
|
|
2018-08-29 06:09:44 +00:00
|
|
|
private State state;
|
2018-09-04 06:21:49 +00:00
|
|
|
private AtomicInteger playerCount;
|
|
|
|
private AtomicInteger undecidedCount;
|
2018-09-10 05:59:56 +00:00
|
|
|
private long lastInstant;
|
|
|
|
private long timer;
|
2018-08-29 06:09:44 +00:00
|
|
|
|
2018-09-06 08:08:36 +00:00
|
|
|
private boolean isServer;
|
|
|
|
private boolean battleEnded;
|
|
|
|
|
2018-08-29 06:09:44 +00:00
|
|
|
public enum State
|
|
|
|
{
|
2018-09-10 05:59:56 +00:00
|
|
|
DECISION(0),
|
|
|
|
ACTION(1),
|
|
|
|
DECISION_PLAYER_READY(2);
|
|
|
|
|
|
|
|
private int value;
|
|
|
|
private static Map<Integer, State> map = new HashMap<Integer, State>();
|
|
|
|
|
|
|
|
private State(int value)
|
|
|
|
{
|
|
|
|
this.value = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getValue()
|
|
|
|
{
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
{
|
|
|
|
for(State state : State.values())
|
|
|
|
{
|
|
|
|
map.put(state.value, state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static State valueOf(int stateType)
|
|
|
|
{
|
|
|
|
return map.get(stateType);
|
|
|
|
}
|
2018-08-29 06:09:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public enum Decision
|
|
|
|
{
|
|
|
|
UNDECIDED(0),
|
|
|
|
ATTACK(1),
|
|
|
|
DEFEND(2),
|
|
|
|
FLEE(3),
|
2018-09-11 06:15:31 +00:00
|
|
|
USE_ITEM(4),
|
|
|
|
SWITCH_ITEM(5);
|
2018-08-29 06:09:44 +00:00
|
|
|
|
|
|
|
private int value;
|
|
|
|
private static Map<Integer, Decision> map = new HashMap<Integer, Decision>();
|
|
|
|
|
|
|
|
private Decision(int value)
|
|
|
|
{
|
|
|
|
this.value = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getValue()
|
|
|
|
{
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
{
|
|
|
|
for(Decision decision : Decision.values())
|
|
|
|
{
|
|
|
|
map.put(decision.value, decision);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static Decision valueOf(int decisionType)
|
|
|
|
{
|
|
|
|
return map.get(decisionType);
|
|
|
|
}
|
|
|
|
}
|
2018-08-28 06:13:14 +00:00
|
|
|
|
2018-09-06 08:08:36 +00:00
|
|
|
public Battle(int id, Collection<Entity> sideA, Collection<Entity> sideB, boolean isServer)
|
2018-08-28 06:13:14 +00:00
|
|
|
{
|
2018-09-06 08:08:36 +00:00
|
|
|
this.isServer = isServer;
|
2018-08-28 06:13:14 +00:00
|
|
|
this.id = id;
|
2018-08-29 06:09:44 +00:00
|
|
|
this.sideA = new Hashtable<Integer, Combatant>();
|
|
|
|
this.sideB = new Hashtable<Integer, Combatant>();
|
2018-09-04 06:21:49 +00:00
|
|
|
players = new Hashtable<Integer, Combatant>();
|
|
|
|
turnOrderQueue = new PriorityQueue<Combatant>(new Combatant.CombatantComparator());
|
|
|
|
playerCount = new AtomicInteger(0);
|
|
|
|
undecidedCount = new AtomicInteger(0);
|
2018-08-29 06:09:44 +00:00
|
|
|
if(sideA != null)
|
2018-08-28 06:13:14 +00:00
|
|
|
{
|
2018-08-29 06:09:44 +00:00
|
|
|
for(Entity e : sideA)
|
|
|
|
{
|
2018-09-04 06:21:49 +00:00
|
|
|
EntityInfo entityInfo = TurnBasedMinecraftMod.config.getMatchingEntityInfo(e);
|
2018-09-25 05:55:24 +00:00
|
|
|
if(entityInfo == null && !(e instanceof EntityPlayer) && TurnBasedMinecraftMod.commonProxy.isServerRunning())
|
2018-09-04 06:21:49 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Combatant newCombatant = new Combatant(e, entityInfo);
|
2018-09-05 06:54:06 +00:00
|
|
|
newCombatant.isSideA = true;
|
2018-09-17 06:49:10 +00:00
|
|
|
newCombatant.battleID = getId();
|
2018-09-04 06:21:49 +00:00
|
|
|
this.sideA.put(e.getEntityId(), newCombatant);
|
2018-08-29 06:09:44 +00:00
|
|
|
if(e instanceof EntityPlayer)
|
|
|
|
{
|
2018-09-04 06:21:49 +00:00
|
|
|
newCombatant.recalcSpeedOnCompare = true;
|
|
|
|
playerCount.incrementAndGet();
|
|
|
|
players.put(e.getEntityId(), newCombatant);
|
2018-08-29 06:09:44 +00:00
|
|
|
}
|
2018-09-18 06:56:06 +00:00
|
|
|
if(TurnBasedMinecraftMod.config.isFreezeCombatantsEnabled())
|
|
|
|
{
|
|
|
|
newCombatant.x = e.posX;
|
|
|
|
newCombatant.y = e.posY;
|
|
|
|
newCombatant.z = e.posZ;
|
|
|
|
newCombatant.yaw = e.rotationYaw;
|
|
|
|
newCombatant.pitch = e.rotationPitch;
|
|
|
|
}
|
2018-08-29 06:09:44 +00:00
|
|
|
}
|
2018-08-28 06:13:14 +00:00
|
|
|
}
|
2018-08-29 06:09:44 +00:00
|
|
|
if(sideB != null)
|
2018-08-28 06:13:14 +00:00
|
|
|
{
|
2018-08-29 06:09:44 +00:00
|
|
|
for(Entity e : sideB)
|
|
|
|
{
|
2018-09-04 06:21:49 +00:00
|
|
|
EntityInfo entityInfo = TurnBasedMinecraftMod.config.getMatchingEntityInfo(e);
|
2018-09-25 05:55:24 +00:00
|
|
|
if(entityInfo == null && !(e instanceof EntityPlayer) && TurnBasedMinecraftMod.commonProxy.isServerRunning())
|
2018-09-04 06:21:49 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Combatant newCombatant = new Combatant(e, entityInfo);
|
2018-09-05 06:54:06 +00:00
|
|
|
newCombatant.isSideA = false;
|
2018-09-17 06:49:10 +00:00
|
|
|
newCombatant.battleID = getId();
|
2018-09-04 06:21:49 +00:00
|
|
|
this.sideB.put(e.getEntityId(), newCombatant);
|
2018-08-29 06:09:44 +00:00
|
|
|
if(e instanceof EntityPlayer)
|
|
|
|
{
|
2018-09-04 06:21:49 +00:00
|
|
|
newCombatant.recalcSpeedOnCompare = true;
|
|
|
|
playerCount.incrementAndGet();
|
|
|
|
players.put(e.getEntityId(), newCombatant);
|
2018-08-29 06:09:44 +00:00
|
|
|
}
|
2018-09-18 06:56:06 +00:00
|
|
|
if(TurnBasedMinecraftMod.config.isFreezeCombatantsEnabled())
|
|
|
|
{
|
|
|
|
newCombatant.x = e.posX;
|
|
|
|
newCombatant.y = e.posY;
|
|
|
|
newCombatant.z = e.posZ;
|
|
|
|
newCombatant.yaw = e.rotationYaw;
|
|
|
|
newCombatant.pitch = e.rotationPitch;
|
|
|
|
}
|
2018-08-29 06:09:44 +00:00
|
|
|
}
|
2018-08-28 06:13:14 +00:00
|
|
|
}
|
|
|
|
|
2018-09-06 08:08:36 +00:00
|
|
|
for(Combatant c : this.sideA.values())
|
|
|
|
{
|
2018-09-14 05:14:10 +00:00
|
|
|
if(c.entityInfo != null)
|
|
|
|
{
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getEntityId(), 0, id, c.entityInfo.category);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getEntityId(), 0, id);
|
|
|
|
}
|
2018-09-06 08:08:36 +00:00
|
|
|
}
|
|
|
|
for(Combatant c : this.sideB.values())
|
|
|
|
{
|
2018-09-14 05:14:10 +00:00
|
|
|
if(c.entityInfo != null)
|
|
|
|
{
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getEntityId(), 0, id, c.entityInfo.category);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, c.entity.getEntityId(), 0, id);
|
|
|
|
}
|
2018-09-06 08:08:36 +00:00
|
|
|
}
|
|
|
|
|
2018-09-10 05:59:56 +00:00
|
|
|
lastInstant = System.nanoTime();
|
2018-08-29 06:09:44 +00:00
|
|
|
state = State.DECISION;
|
2018-09-04 06:21:49 +00:00
|
|
|
undecidedCount.set(playerCount.get());
|
2018-09-25 05:55:24 +00:00
|
|
|
timer = TurnBasedMinecraftMod.getBattleDurationNanos();
|
2018-09-06 08:08:36 +00:00
|
|
|
battleEnded = false;
|
|
|
|
|
|
|
|
notifyPlayersBattleInfo();
|
2018-08-28 06:13:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public int getId()
|
|
|
|
{
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2018-09-06 08:08:36 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-08-28 06:13:14 +00:00
|
|
|
public boolean hasCombatant(int entityID)
|
|
|
|
{
|
|
|
|
return sideA.containsKey(entityID) || sideB.containsKey(entityID);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean hasCombatantInSideA(int entityID)
|
|
|
|
{
|
|
|
|
return sideA.containsKey(entityID);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void addCombatantToSideA(Entity e)
|
|
|
|
{
|
2018-09-04 06:21:49 +00:00
|
|
|
EntityInfo entityInfo = TurnBasedMinecraftMod.config.getMatchingEntityInfo(e);
|
2018-09-25 05:55:24 +00:00
|
|
|
if(entityInfo == null && !(e instanceof EntityPlayer) && TurnBasedMinecraftMod.commonProxy.isServerRunning())
|
2018-09-04 06:21:49 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Combatant newCombatant = new Combatant(e, entityInfo);
|
2018-09-05 06:54:06 +00:00
|
|
|
newCombatant.isSideA = true;
|
2018-09-17 06:49:10 +00:00
|
|
|
newCombatant.battleID = getId();
|
2018-09-04 06:21:49 +00:00
|
|
|
sideA.put(e.getEntityId(), newCombatant);
|
2018-08-29 06:09:44 +00:00
|
|
|
if(e instanceof EntityPlayer)
|
|
|
|
{
|
2018-09-04 06:21:49 +00:00
|
|
|
newCombatant.recalcSpeedOnCompare = true;
|
|
|
|
playerCount.incrementAndGet();
|
|
|
|
players.put(e.getEntityId(), newCombatant);
|
2018-08-29 06:09:44 +00:00
|
|
|
if(state == State.DECISION)
|
|
|
|
{
|
2018-09-04 06:21:49 +00:00
|
|
|
undecidedCount.incrementAndGet();
|
2018-08-29 06:09:44 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-18 06:56:06 +00:00
|
|
|
if(TurnBasedMinecraftMod.config.isFreezeCombatantsEnabled())
|
|
|
|
{
|
|
|
|
newCombatant.x = e.posX;
|
|
|
|
newCombatant.y = e.posY;
|
|
|
|
newCombatant.z = e.posZ;
|
|
|
|
newCombatant.yaw = e.rotationYaw;
|
|
|
|
newCombatant.pitch = e.rotationPitch;
|
|
|
|
}
|
2018-09-14 05:14:10 +00:00
|
|
|
if(newCombatant.entityInfo != null)
|
|
|
|
{
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getEntityId(), 0, id, newCombatant.entityInfo.category);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getEntityId(), 0, id);
|
|
|
|
}
|
2018-09-06 08:08:36 +00:00
|
|
|
notifyPlayersBattleInfo();
|
2018-08-28 06:13:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void addCombatantToSideB(Entity e)
|
|
|
|
{
|
2018-09-04 06:21:49 +00:00
|
|
|
EntityInfo entityInfo = TurnBasedMinecraftMod.config.getMatchingEntityInfo(e);
|
2018-09-25 05:55:24 +00:00
|
|
|
if(entityInfo == null && !(e instanceof EntityPlayer) && TurnBasedMinecraftMod.commonProxy.isServerRunning())
|
2018-09-04 06:21:49 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Combatant newCombatant = new Combatant(e, entityInfo);
|
2018-09-05 06:54:06 +00:00
|
|
|
newCombatant.isSideA = false;
|
2018-09-17 06:49:10 +00:00
|
|
|
newCombatant.battleID = getId();
|
2018-09-04 06:21:49 +00:00
|
|
|
sideB.put(e.getEntityId(), newCombatant);
|
2018-08-29 06:09:44 +00:00
|
|
|
if(e instanceof EntityPlayer)
|
|
|
|
{
|
2018-09-04 06:21:49 +00:00
|
|
|
newCombatant.recalcSpeedOnCompare = true;
|
|
|
|
playerCount.incrementAndGet();
|
|
|
|
players.put(e.getEntityId(), newCombatant);
|
2018-08-29 06:09:44 +00:00
|
|
|
if(state == State.DECISION)
|
|
|
|
{
|
2018-09-04 06:21:49 +00:00
|
|
|
undecidedCount.incrementAndGet();
|
2018-08-29 06:09:44 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-18 06:56:06 +00:00
|
|
|
if(TurnBasedMinecraftMod.config.isFreezeCombatantsEnabled())
|
|
|
|
{
|
|
|
|
newCombatant.x = e.posX;
|
|
|
|
newCombatant.y = e.posY;
|
|
|
|
newCombatant.z = e.posZ;
|
|
|
|
newCombatant.yaw = e.rotationYaw;
|
|
|
|
newCombatant.pitch = e.rotationPitch;
|
|
|
|
}
|
2018-09-14 05:14:10 +00:00
|
|
|
if(newCombatant.entityInfo != null)
|
|
|
|
{
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getEntityId(), 0, id, newCombatant.entityInfo.category);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENTERED, newCombatant.entity.getEntityId(), 0, id);
|
|
|
|
}
|
2018-09-06 08:08:36 +00:00
|
|
|
notifyPlayersBattleInfo();
|
2018-08-29 06:09:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void clearCombatants()
|
|
|
|
{
|
|
|
|
sideA.clear();
|
|
|
|
sideB.clear();
|
2018-08-30 07:15:20 +00:00
|
|
|
players.clear();
|
2018-09-04 06:21:49 +00:00
|
|
|
playerCount.set(0);
|
|
|
|
undecidedCount.set(0);
|
2018-08-29 06:09:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public Collection<Combatant> getSideA()
|
|
|
|
{
|
|
|
|
return sideA.values();
|
|
|
|
}
|
|
|
|
|
|
|
|
public Collection<Combatant> getSideB()
|
|
|
|
{
|
|
|
|
return sideB.values();
|
|
|
|
}
|
|
|
|
|
2018-09-11 06:15:31 +00:00
|
|
|
public Set<Map.Entry<Integer, Combatant>> getSideAEntrySet()
|
|
|
|
{
|
|
|
|
return sideA.entrySet();
|
|
|
|
}
|
|
|
|
|
|
|
|
public Set<Map.Entry<Integer, Combatant>> getSideBEntrySet()
|
|
|
|
{
|
|
|
|
return sideB.entrySet();
|
|
|
|
}
|
|
|
|
|
2018-08-29 06:09:44 +00:00
|
|
|
public Collection<Integer> getSideAIDs()
|
|
|
|
{
|
|
|
|
Collection<Integer> sideAIDs = new ArrayList<Integer>(sideA.size());
|
|
|
|
for(Combatant combatant : sideA.values())
|
|
|
|
{
|
|
|
|
sideAIDs.add(combatant.entity.getEntityId());
|
|
|
|
}
|
|
|
|
return sideAIDs;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Collection<Integer> getSideBIDs()
|
|
|
|
{
|
|
|
|
Collection<Integer> sideBIDs = new ArrayList<Integer>(sideB.size());
|
|
|
|
for(Combatant combatant : sideB.values())
|
|
|
|
{
|
|
|
|
sideBIDs.add(combatant.entity.getEntityId());
|
|
|
|
}
|
|
|
|
return sideBIDs;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Combatant getCombatantByID(int entityID)
|
|
|
|
{
|
|
|
|
Combatant combatant = sideA.get(entityID);
|
|
|
|
if(combatant == null)
|
|
|
|
{
|
|
|
|
combatant = sideB.get(entityID);
|
|
|
|
}
|
|
|
|
return combatant;
|
|
|
|
}
|
|
|
|
|
2018-09-05 06:54:06 +00:00
|
|
|
public void setDecision(int entityID, Decision decision, int targetIDOrItemID)
|
2018-08-29 06:09:44 +00:00
|
|
|
{
|
|
|
|
if(state != State.DECISION)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2018-09-04 06:21:49 +00:00
|
|
|
Combatant combatant = players.get(entityID);
|
2018-09-05 06:54:06 +00:00
|
|
|
if(combatant == null || combatant.decision != Decision.UNDECIDED)
|
2018-08-29 06:09:44 +00:00
|
|
|
{
|
2018-09-04 06:21:49 +00:00
|
|
|
return;
|
2018-08-29 06:09:44 +00:00
|
|
|
}
|
2018-09-04 06:21:49 +00:00
|
|
|
combatant.decision = decision;
|
2018-09-05 06:54:06 +00:00
|
|
|
if(decision == Decision.ATTACK)
|
|
|
|
{
|
|
|
|
combatant.targetEntityID = targetIDOrItemID;
|
|
|
|
}
|
2018-09-11 06:15:31 +00:00
|
|
|
else if(decision == Decision.USE_ITEM || decision == Decision.SWITCH_ITEM)
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
|
|
|
combatant.itemToUse = targetIDOrItemID;
|
|
|
|
}
|
2018-09-04 06:21:49 +00:00
|
|
|
undecidedCount.decrementAndGet();
|
2018-08-29 06:09:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public State getState()
|
|
|
|
{
|
|
|
|
return state;
|
2018-08-28 06:13:14 +00:00
|
|
|
}
|
|
|
|
|
2018-09-10 05:59:56 +00:00
|
|
|
public void setState(State state)
|
|
|
|
{
|
|
|
|
this.state = state;
|
|
|
|
}
|
|
|
|
|
|
|
|
public long getTimerSeconds()
|
|
|
|
{
|
|
|
|
return timer / 1000000000;
|
|
|
|
}
|
|
|
|
|
2018-09-14 03:44:45 +00:00
|
|
|
public int getSize()
|
|
|
|
{
|
|
|
|
return sideA.size() + sideB.size();
|
|
|
|
}
|
|
|
|
|
2018-09-06 08:08:36 +00:00
|
|
|
protected void notifyPlayersBattleInfo()
|
2018-08-30 07:15:20 +00:00
|
|
|
{
|
2018-09-06 08:08:36 +00:00
|
|
|
if(!isServer)
|
2018-08-30 07:15:20 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2018-09-10 05:59:56 +00:00
|
|
|
PacketBattleInfo infoPacket = new PacketBattleInfo(getSideAIDs(), getSideBIDs(), timer);
|
2018-09-04 06:21:49 +00:00
|
|
|
for(Combatant p : players.values())
|
2018-08-30 07:15:20 +00:00
|
|
|
{
|
2018-09-12 07:00:55 +00:00
|
|
|
TurnBasedMinecraftMod.NWINSTANCE.sendTo(infoPacket, (EntityPlayerMP)p.entity);
|
2018-08-30 07:15:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-17 06:49:10 +00:00
|
|
|
protected void sendMessageToAllPlayers(PacketBattleMessage.MessageType type, int from, int to, int amount)
|
2018-08-28 06:13:14 +00:00
|
|
|
{
|
2018-09-06 08:08:36 +00:00
|
|
|
if(!isServer)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for(Combatant p : players.values())
|
|
|
|
{
|
|
|
|
if(p.entity.isEntityAlive())
|
|
|
|
{
|
2018-09-12 07:00:55 +00:00
|
|
|
TurnBasedMinecraftMod.NWINSTANCE.sendTo(new PacketBattleMessage(type, from, to, amount), (EntityPlayerMP)p.entity);
|
2018-09-06 08:08:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-17 06:49:10 +00:00
|
|
|
protected void sendMessageToAllPlayers(PacketBattleMessage.MessageType type, int from, int to, int amount, String custom)
|
2018-09-07 07:41:22 +00:00
|
|
|
{
|
|
|
|
if(!isServer)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for(Combatant p : players.values())
|
|
|
|
{
|
|
|
|
if(p.entity.isEntityAlive())
|
|
|
|
{
|
2018-09-12 07:00:55 +00:00
|
|
|
TurnBasedMinecraftMod.NWINSTANCE.sendTo(new PacketBattleMessage(type, from, to, amount, custom), (EntityPlayerMP)p.entity);
|
2018-09-07 07:41:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return true if at least one combatant was removed
|
|
|
|
*/
|
|
|
|
private boolean healthCheck()
|
|
|
|
{
|
|
|
|
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)
|
|
|
|
{
|
2018-09-12 07:00:55 +00:00
|
|
|
TurnBasedMinecraftMod.NWINSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, c.entity.getEntityId(), 0, 0), (EntityPlayerMP)c.entity);
|
2018-09-07 07:41:22 +00:00
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
2018-09-12 07:00:55 +00:00
|
|
|
TurnBasedMinecraftMod.NWINSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, c.entity.getEntityId(), 0, 0), (EntityPlayerMP)c.entity);
|
2018-09-07 07:41:22 +00:00
|
|
|
}
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DIED, c.entity.getEntityId(), 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
boolean didRemove = !removeQueue.isEmpty();
|
2018-09-19 06:00:38 +00:00
|
|
|
for(Integer toRemove = removeQueue.poll(); toRemove != null; toRemove = removeQueue.poll())
|
2018-09-07 07:41:22 +00:00
|
|
|
{
|
|
|
|
sideA.remove(toRemove);
|
|
|
|
sideB.remove(toRemove);
|
|
|
|
if(players.remove(toRemove) != null)
|
|
|
|
{
|
|
|
|
playerCount.decrementAndGet();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(players.isEmpty() || sideA.isEmpty() || sideB.isEmpty())
|
|
|
|
{
|
|
|
|
battleEnded = true;
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ENDED, 0, 0, 0);
|
|
|
|
}
|
|
|
|
else if(didRemove)
|
|
|
|
{
|
|
|
|
notifyPlayersBattleInfo();
|
2018-09-19 06:00:38 +00:00
|
|
|
resetUndecidedCount();
|
2018-09-07 07:41:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return didRemove;
|
|
|
|
}
|
|
|
|
|
2018-09-19 06:00:38 +00:00
|
|
|
private boolean isCreativeCheck()
|
2018-09-14 03:44:45 +00:00
|
|
|
{
|
|
|
|
Queue<Integer> removeQueue = new ArrayDeque<Integer>();
|
|
|
|
for(Combatant c : players.values())
|
|
|
|
{
|
|
|
|
if(c.entity != null && ((EntityPlayer)c.entity).isCreative())
|
|
|
|
{
|
|
|
|
TurnBasedMinecraftMod.NWINSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, c.entity.getEntityId(), 0, 0), (EntityPlayerMP)c.entity);
|
|
|
|
removeQueue.add(c.entity.getEntityId());
|
|
|
|
}
|
|
|
|
}
|
2018-09-19 06:00:38 +00:00
|
|
|
boolean didRemove = false;
|
|
|
|
for(Integer toRemove = removeQueue.poll(); toRemove != null; toRemove = removeQueue.poll())
|
2018-09-14 03:44:45 +00:00
|
|
|
{
|
2018-09-19 06:00:38 +00:00
|
|
|
didRemove = true;
|
2018-09-14 03:44:45 +00:00
|
|
|
sideA.remove(toRemove);
|
|
|
|
sideB.remove(toRemove);
|
|
|
|
players.remove(toRemove);
|
|
|
|
playerCount.decrementAndGet();
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.BECAME_CREATIVE, toRemove, 0, 0);
|
|
|
|
}
|
2018-09-19 06:00:38 +00:00
|
|
|
if(didRemove)
|
|
|
|
{
|
|
|
|
notifyPlayersBattleInfo();
|
|
|
|
resetUndecidedCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
return didRemove;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void resetUndecidedCount()
|
|
|
|
{
|
|
|
|
if(state == State.DECISION)
|
|
|
|
{
|
|
|
|
undecidedCount.set(0);
|
|
|
|
for(Combatant p : players.values())
|
|
|
|
{
|
|
|
|
if(p.decision == Decision.UNDECIDED)
|
|
|
|
{
|
|
|
|
undecidedCount.incrementAndGet();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-09-14 03:44:45 +00:00
|
|
|
}
|
|
|
|
|
2018-09-18 06:56:06 +00:00
|
|
|
private void enforceFreezePositions()
|
|
|
|
{
|
|
|
|
for(Combatant c : sideA.values())
|
|
|
|
{
|
|
|
|
c.entity.setPositionAndRotation(c.x, c.y, c.z, c.yaw, c.pitch);
|
|
|
|
}
|
|
|
|
for(Combatant c : sideB.values())
|
|
|
|
{
|
|
|
|
c.entity.setPositionAndRotation(c.x, c.y, c.z, c.yaw, c.pitch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-10 05:59:56 +00:00
|
|
|
/**
|
|
|
|
* @return True if battle has ended
|
|
|
|
*/
|
|
|
|
public boolean update()
|
|
|
|
{
|
|
|
|
if(battleEnded)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
long nextInstant = System.nanoTime();
|
|
|
|
long dt = nextInstant - lastInstant;
|
|
|
|
lastInstant = nextInstant;
|
|
|
|
return update(dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
private boolean update(final long dt)
|
2018-09-06 08:08:36 +00:00
|
|
|
{
|
|
|
|
if(battleEnded)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
2018-09-18 06:56:06 +00:00
|
|
|
if(TurnBasedMinecraftMod.config.isFreezeCombatantsEnabled())
|
|
|
|
{
|
|
|
|
enforceFreezePositions();
|
|
|
|
}
|
2018-08-29 06:09:44 +00:00
|
|
|
switch(state)
|
|
|
|
{
|
|
|
|
case DECISION:
|
2018-09-10 05:59:56 +00:00
|
|
|
timer -= dt;
|
|
|
|
if(timer <= 0 || undecidedCount.get() <= 0)
|
2018-08-29 06:09:44 +00:00
|
|
|
{
|
2018-09-06 08:08:36 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-09-05 06:54:06 +00:00
|
|
|
state = State.ACTION;
|
2018-09-25 05:55:24 +00:00
|
|
|
timer = TurnBasedMinecraftMod.getBattleDurationNanos();
|
2018-09-10 05:59:56 +00:00
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.TURN_BEGIN, 0, 0, 0);
|
2018-09-04 06:21:49 +00:00
|
|
|
turnOrderQueue.clear();
|
|
|
|
for(Combatant c : sideA.values())
|
|
|
|
{
|
|
|
|
turnOrderQueue.add(c);
|
|
|
|
}
|
|
|
|
for(Combatant c : sideB.values())
|
|
|
|
{
|
|
|
|
turnOrderQueue.add(c);
|
|
|
|
}
|
2018-09-10 05:59:56 +00:00
|
|
|
update(0);
|
2018-08-29 06:09:44 +00:00
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
healthCheck();
|
2018-09-14 03:44:45 +00:00
|
|
|
isCreativeCheck();
|
2018-09-07 07:41:22 +00:00
|
|
|
}
|
2018-08-29 06:09:44 +00:00
|
|
|
break;
|
2018-09-05 06:54:06 +00:00
|
|
|
case ACTION:
|
2018-09-04 06:21:49 +00:00
|
|
|
{
|
2018-09-18 06:56:06 +00:00
|
|
|
for(Combatant next = turnOrderQueue.poll(); next != null; next = turnOrderQueue.poll())
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
if(!next.entity.isEntityAlive())
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
continue;
|
|
|
|
}
|
2018-09-13 05:52:48 +00:00
|
|
|
|
|
|
|
next.remainingDefenses = 0;
|
|
|
|
|
2018-09-07 07:41:22 +00:00
|
|
|
switch(next.decision)
|
|
|
|
{
|
|
|
|
case UNDECIDED:
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DID_NOTHING, next.entity.getEntityId(), 0, 0);
|
|
|
|
break;
|
|
|
|
case ATTACK:
|
|
|
|
Combatant target = null;
|
|
|
|
if(next.entity instanceof EntityPlayer)
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
if(next.isSideA)
|
|
|
|
{
|
|
|
|
target = sideB.get(next.targetEntityID);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
target = sideA.get(next.targetEntityID);
|
|
|
|
}
|
|
|
|
if(target == null || !target.entity.isEntityAlive())
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
break;
|
|
|
|
}
|
2018-09-17 06:49:10 +00:00
|
|
|
ItemStack heldItemStack = ((EntityPlayer)next.entity).getHeldItemMainhand();
|
|
|
|
if(heldItemStack.getItem() instanceof ItemBow)
|
|
|
|
{
|
|
|
|
if(Utility.doesPlayerHaveArrows((EntityPlayer)next.entity))
|
|
|
|
{
|
|
|
|
final Entity nextEntity = next.entity;
|
|
|
|
final Entity targetEntity = target.entity;
|
2018-09-18 06:56:06 +00:00
|
|
|
final float yawDirection = Utility.yawDirection(next.entity.posX, next.entity.posZ, target.entity.posX, target.entity.posZ);
|
|
|
|
final float pitchDirection = Utility.pitchDirection(next.entity.posX, next.entity.posY, next.entity.posZ, target.entity.posX, target.entity.posY, target.entity.posZ);
|
|
|
|
if(TurnBasedMinecraftMod.config.isFreezeCombatantsEnabled())
|
|
|
|
{
|
|
|
|
next.yaw = yawDirection;
|
|
|
|
next.pitch = pitchDirection;
|
|
|
|
}
|
2018-09-17 06:49:10 +00:00
|
|
|
next.entity.getServer().addScheduledTask(() -> {
|
|
|
|
// have player look at attack target
|
2018-09-18 06:56:06 +00:00
|
|
|
((EntityPlayerMP)nextEntity).connection.setPlayerLocation(nextEntity.posX, nextEntity.posY, nextEntity.posZ, yawDirection, pitchDirection);
|
2018-09-17 06:49:10 +00:00
|
|
|
ItemBow itemBow = (ItemBow)heldItemStack.getItem();
|
|
|
|
synchronized(TurnBasedMinecraftMod.attackerViaBow)
|
|
|
|
{
|
|
|
|
TurnBasedMinecraftMod.attackerViaBow.add(new AttackerViaBow(nextEntity, getId()));
|
|
|
|
}
|
|
|
|
itemBow.onPlayerStoppedUsing(((EntityPlayer)nextEntity).getHeldItemMainhand(), nextEntity.getEntityWorld(), (EntityLivingBase)nextEntity, (int)(Math.random() * (itemBow.getMaxItemUseDuration(heldItemStack)) / 3));
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.FIRED_ARROW, nextEntity.getEntityId(), targetEntity.getEntityId(), 0);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.BOW_NO_AMMO, next.entity.getEntityId(), 0, 0);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
int hitChance = TurnBasedMinecraftMod.config.getPlayerAttackProbability();
|
|
|
|
if(target.entity instanceof EntityPlayer)
|
|
|
|
{
|
|
|
|
hitChance -= TurnBasedMinecraftMod.config.getPlayerEvasion();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hitChance -= target.entityInfo.evasion;
|
|
|
|
}
|
2018-09-13 05:52:48 +00:00
|
|
|
if(hitChance < TurnBasedMinecraftMod.config.getMinimumHitPercentage())
|
2018-09-13 05:12:04 +00:00
|
|
|
{
|
2018-09-13 05:52:48 +00:00
|
|
|
hitChance = TurnBasedMinecraftMod.config.getMinimumHitPercentage();
|
2018-09-13 05:12:04 +00:00
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
if((int)(Math.random() * 100) < hitChance)
|
|
|
|
{
|
|
|
|
if(target.remainingDefenses <= 0)
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
// attack
|
2018-09-12 05:43:59 +00:00
|
|
|
final Entity nextEntity = next.entity;
|
|
|
|
final Entity targetEntity = target.entity;
|
2018-09-17 04:27:13 +00:00
|
|
|
final EntityInfo targetEntityInfo = target.entityInfo;
|
2018-09-18 06:56:06 +00:00
|
|
|
final float yawDirection = Utility.yawDirection(next.entity.posX, next.entity.posZ, target.entity.posX, target.entity.posZ);
|
|
|
|
final float pitchDirection = Utility.pitchDirection(next.entity.posX, next.entity.posY, next.entity.posZ, target.entity.posX, target.entity.posY, target.entity.posZ);
|
|
|
|
if(TurnBasedMinecraftMod.config.isFreezeCombatantsEnabled())
|
|
|
|
{
|
|
|
|
next.yaw = yawDirection;
|
|
|
|
next.pitch = pitchDirection;
|
|
|
|
}
|
2018-09-12 07:10:02 +00:00
|
|
|
next.entity.getServer().addScheduledTask(() -> {
|
2018-09-17 06:49:10 +00:00
|
|
|
// have player look at attack target
|
2018-09-18 06:56:06 +00:00
|
|
|
((EntityPlayerMP)nextEntity).connection.setPlayerLocation(nextEntity.posX, nextEntity.posY, nextEntity.posZ, yawDirection, pitchDirection);
|
2018-09-17 04:27:13 +00:00
|
|
|
TurnBasedMinecraftMod.attackingEntity = nextEntity;
|
|
|
|
TurnBasedMinecraftMod.attackingDamage = 0;
|
|
|
|
((EntityPlayer)nextEntity).attackTargetEntityWithCurrentItem(targetEntity);
|
|
|
|
TurnBasedMinecraftMod.attackingEntity = null;
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, nextEntity.getEntityId(), targetEntity.getEntityId(), TurnBasedMinecraftMod.attackingDamage);
|
|
|
|
if(!(targetEntity instanceof EntityPlayer) && targetEntityInfo.defenseDamage > 0)
|
2018-09-07 07:41:22 +00:00
|
|
|
{
|
2018-09-17 04:27:13 +00:00
|
|
|
if((int)(Math.random() * 100) < targetEntityInfo.defenseDamageProbability)
|
|
|
|
{
|
|
|
|
// defense damage
|
|
|
|
DamageSource defenseDamageSource = DamageSource.causeMobDamage((EntityLivingBase)targetEntity);
|
|
|
|
TurnBasedMinecraftMod.attackingEntity = targetEntity;
|
|
|
|
nextEntity.attackEntityFrom(defenseDamageSource, targetEntityInfo.defenseDamage);
|
|
|
|
TurnBasedMinecraftMod.attackingEntity = null;
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, targetEntity.getEntityId(), nextEntity.getEntityId(), targetEntityInfo.defenseDamage);
|
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
}
|
2018-09-17 04:27:13 +00:00
|
|
|
});
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// blocked
|
|
|
|
--target.remainingDefenses;
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFEND, target.entity.getEntityId(), next.entity.getEntityId(), 0);
|
|
|
|
}
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
// miss
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.MISS, next.entity.getEntityId(), target.entity.getEntityId(), 0);
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
if(next.isSideA)
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
int randomTargetIndex = (int)(Math.random() * sideB.size());
|
|
|
|
for(Combatant c : sideB.values())
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
if(randomTargetIndex-- == 0)
|
|
|
|
{
|
|
|
|
target = c;
|
|
|
|
break;
|
|
|
|
}
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
else
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
int randomTargetIndex = (int)(Math.random() * sideA.size());
|
|
|
|
for(Combatant c : sideA.values())
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
if(randomTargetIndex-- == 0)
|
|
|
|
{
|
|
|
|
target = c;
|
|
|
|
break;
|
|
|
|
}
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
if(target == null || !target.entity.isEntityAlive())
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
int hitChance = next.entityInfo.attackProbability;
|
|
|
|
if(target.entity instanceof EntityPlayer)
|
|
|
|
{
|
|
|
|
hitChance -= TurnBasedMinecraftMod.config.getPlayerEvasion();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hitChance -= target.entityInfo.evasion;
|
|
|
|
}
|
2018-09-13 05:52:48 +00:00
|
|
|
if(hitChance < TurnBasedMinecraftMod.config.getMinimumHitPercentage())
|
2018-09-13 05:12:04 +00:00
|
|
|
{
|
2018-09-13 05:52:48 +00:00
|
|
|
hitChance = TurnBasedMinecraftMod.config.getMinimumHitPercentage();
|
2018-09-13 05:12:04 +00:00
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
if((int)(Math.random() * 100) < hitChance)
|
|
|
|
{
|
|
|
|
if(target.remainingDefenses <= 0)
|
|
|
|
{
|
|
|
|
DamageSource damageSource = DamageSource.causeMobDamage((EntityLivingBase)next.entity);
|
|
|
|
int damageAmount = next.entityInfo.attackPower;
|
|
|
|
if(next.entityInfo.attackVariance > 0)
|
|
|
|
{
|
|
|
|
damageAmount += (int)(Math.random() * (next.entityInfo.attackVariance * 2 + 1)) - next.entityInfo.attackVariance;
|
|
|
|
}
|
|
|
|
// attack
|
2018-09-17 04:27:13 +00:00
|
|
|
final Entity nextEntity = next.entity;
|
|
|
|
final EntityInfo nextEntityInfo = next.entityInfo;
|
|
|
|
final Entity targetEntity = target.entity;
|
|
|
|
final EntityInfo targetEntityInfo = target.entityInfo;
|
|
|
|
final int finalDamageAmount = damageAmount;
|
|
|
|
next.entity.getServer().addScheduledTask(() -> {
|
|
|
|
TurnBasedMinecraftMod.attackingEntity = nextEntity;
|
|
|
|
targetEntity.attackEntityFrom(damageSource, finalDamageAmount);
|
|
|
|
TurnBasedMinecraftMod.attackingEntity = null;
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.ATTACK, nextEntity.getEntityId(), targetEntity.getEntityId(), finalDamageAmount);
|
|
|
|
if(!(targetEntity instanceof EntityPlayer) && targetEntityInfo.defenseDamage > 0)
|
2018-09-07 07:41:22 +00:00
|
|
|
{
|
2018-09-17 04:27:13 +00:00
|
|
|
if((int)(Math.random() * 100) < targetEntityInfo.defenseDamageProbability)
|
|
|
|
{
|
|
|
|
// defense damage
|
|
|
|
DamageSource defenseDamageSource = DamageSource.causeMobDamage((EntityLivingBase)targetEntity);
|
|
|
|
TurnBasedMinecraftMod.attackingEntity = targetEntity;
|
|
|
|
nextEntity.attackEntityFrom(defenseDamageSource, targetEntityInfo.defenseDamage);
|
|
|
|
TurnBasedMinecraftMod.attackingEntity = null;
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENSE_DAMAGE, targetEntity.getEntityId(), nextEntity.getEntityId(), targetEntityInfo.defenseDamage);
|
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
}
|
2018-09-17 04:27:13 +00:00
|
|
|
// attack effect
|
|
|
|
if(nextEntityInfo.attackEffect != EntityInfo.Effect.UNKNOWN && nextEntityInfo.attackEffectProbability > 0)
|
2018-09-13 04:52:22 +00:00
|
|
|
{
|
2018-09-17 04:27:13 +00:00
|
|
|
int effectChance = (int)(Math.random() * 100);
|
|
|
|
if(effectChance < nextEntityInfo.attackEffectProbability)
|
|
|
|
{
|
|
|
|
nextEntityInfo.attackEffect.applyEffectToEntity((EntityLivingBase)targetEntity);
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.WAS_AFFECTED, nextEntity.getEntityId(), targetEntity.getEntityId(), 0, nextEntityInfo.attackEffect.getAffectedString());
|
|
|
|
}
|
2018-09-13 04:52:22 +00:00
|
|
|
}
|
2018-09-17 04:27:13 +00:00
|
|
|
});
|
2018-09-07 07:41:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// blocked
|
|
|
|
--target.remainingDefenses;
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFEND, target.entity.getEntityId(), next.entity.getEntityId(), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// miss
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.MISS, next.entity.getEntityId(), target.entity.getEntityId(), 0);
|
|
|
|
}
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
break;
|
|
|
|
case DEFEND:
|
|
|
|
next.remainingDefenses = TurnBasedMinecraftMod.config.getDefenseDuration();
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.DEFENDING, next.entity.getEntityId(), 0, 0);
|
|
|
|
break;
|
|
|
|
case FLEE:
|
|
|
|
int fastestEnemySpeed = 0;
|
|
|
|
if(next.isSideA)
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
for(Combatant c : sideB.values())
|
|
|
|
{
|
|
|
|
if(c.entity instanceof EntityPlayer)
|
|
|
|
{
|
|
|
|
if(TurnBasedMinecraftMod.config.getPlayerSpeed() > fastestEnemySpeed)
|
|
|
|
{
|
|
|
|
fastestEnemySpeed = TurnBasedMinecraftMod.config.getPlayerSpeed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(c.entityInfo.speed > fastestEnemySpeed)
|
|
|
|
{
|
|
|
|
fastestEnemySpeed = c.entityInfo.speed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
for(Combatant c : sideA.values())
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
if(c.entity instanceof EntityPlayer)
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
if(TurnBasedMinecraftMod.config.getPlayerSpeed() > fastestEnemySpeed)
|
|
|
|
{
|
|
|
|
fastestEnemySpeed = TurnBasedMinecraftMod.config.getPlayerSpeed();
|
|
|
|
}
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
else
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
if(c.entityInfo.speed > fastestEnemySpeed)
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
fastestEnemySpeed = c.entityInfo.speed;
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
}
|
|
|
|
int fleeProbability = 0;
|
|
|
|
if(next.entity instanceof EntityPlayer)
|
|
|
|
{
|
|
|
|
if(fastestEnemySpeed >= TurnBasedMinecraftMod.config.getPlayerSpeed())
|
|
|
|
{
|
|
|
|
fleeProbability = TurnBasedMinecraftMod.config.getFleeBadProbability();
|
|
|
|
}
|
2018-09-05 06:54:06 +00:00
|
|
|
else
|
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
fleeProbability = TurnBasedMinecraftMod.config.getFleeGoodProbability();
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
if(fastestEnemySpeed >= next.entityInfo.speed)
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
fleeProbability = TurnBasedMinecraftMod.config.getFleeBadProbability();
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
fleeProbability = TurnBasedMinecraftMod.config.getFleeGoodProbability();
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
if((int)(Math.random() * 100) < fleeProbability)
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
// flee success
|
|
|
|
if(next.isSideA)
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
sideA.remove(next.entity.getEntityId());
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
sideB.remove(next.entity.getEntityId());
|
|
|
|
}
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.FLEE, next.entity.getEntityId(), 0, 1);
|
|
|
|
if(next.entity instanceof EntityPlayer)
|
|
|
|
{
|
|
|
|
players.remove(next.entity.getEntityId());
|
|
|
|
playerCount.decrementAndGet();
|
2018-09-12 07:00:55 +00:00
|
|
|
TurnBasedMinecraftMod.NWINSTANCE.sendTo(new PacketBattleMessage(PacketBattleMessage.MessageType.ENDED, 0, 0, 0), (EntityPlayerMP)next.entity);
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
// flee fail
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.FLEE, next.entity.getEntityId(), 0, 0);
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
break;
|
|
|
|
case USE_ITEM:
|
2018-09-11 07:39:46 +00:00
|
|
|
if(next.itemToUse < 0 || next.itemToUse > 8)
|
|
|
|
{
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getEntityId(), 0, PacketBattleMessage.UsedItemAction.USED_INVALID.getValue());
|
|
|
|
break;
|
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
ItemStack targetItemStack = ((EntityPlayer)next.entity).inventory.getStackInSlot(next.itemToUse);
|
|
|
|
Item targetItem = targetItemStack.getItem();
|
|
|
|
if(targetItem == null)
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getEntityId(), 0, PacketBattleMessage.UsedItemAction.USED_NOTHING.getValue());
|
|
|
|
break;
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
if(targetItem instanceof ItemFood)
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getEntityId(), 0, PacketBattleMessage.UsedItemAction.USED_FOOD.getValue(), targetItemStack.getDisplayName());
|
2018-09-17 04:27:13 +00:00
|
|
|
final Entity nextEntity = next.entity;
|
|
|
|
next.entity.getServer().addScheduledTask(() -> {
|
|
|
|
((ItemFood)targetItem).onItemUseFinish(targetItemStack, nextEntity.world, (EntityLivingBase)nextEntity);
|
|
|
|
});
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
else if(targetItem instanceof ItemPotion && !(targetItem instanceof ItemSplashPotion) && !(targetItem instanceof ItemLingeringPotion))
|
2018-09-05 06:54:06 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getEntityId(), 0, PacketBattleMessage.UsedItemAction.USED_POTION.getValue(), targetItemStack.getDisplayName());
|
2018-09-17 04:27:13 +00:00
|
|
|
final Entity nextEntity = next.entity;
|
|
|
|
final int nextItemToUse = next.itemToUse;
|
|
|
|
next.entity.getServer().addScheduledTask(() -> {
|
|
|
|
((ItemPotion)targetItem).onItemUseFinish(targetItemStack, nextEntity.world, (EntityLivingBase)nextEntity);
|
|
|
|
((EntityPlayer)nextEntity).inventory.setInventorySlotContents(nextItemToUse, new ItemStack(Items.GLASS_BOTTLE));
|
|
|
|
});
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.USED_ITEM, next.entity.getEntityId(), 0, PacketBattleMessage.UsedItemAction.USED_INVALID.getValue(), targetItemStack.getDisplayName());
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
break;
|
2018-09-11 06:15:31 +00:00
|
|
|
case SWITCH_ITEM:
|
2018-09-11 07:39:46 +00:00
|
|
|
if(next.itemToUse < 0 || next.itemToUse > 8)
|
|
|
|
{
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.SWITCHED_ITEM, next.entity.getEntityId(), 0, 0);
|
|
|
|
break;
|
|
|
|
}
|
2018-09-17 04:27:13 +00:00
|
|
|
final Entity nextEntity = next.entity;
|
|
|
|
final int nextItemToUse = next.itemToUse;
|
|
|
|
next.entity.getServer().addScheduledTask(() -> {
|
|
|
|
((EntityPlayer)nextEntity).inventory.currentItem = nextItemToUse;
|
|
|
|
});
|
2018-09-11 07:39:46 +00:00
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.SWITCHED_ITEM, next.entity.getEntityId(), 0, 1);
|
2018-09-11 06:15:31 +00:00
|
|
|
break;
|
2018-09-05 06:54:06 +00:00
|
|
|
}
|
2018-09-06 08:08:36 +00:00
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
for(Combatant c : sideA.values())
|
2018-09-06 08:08:36 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
c.decision = Decision.UNDECIDED;
|
2018-09-06 08:08:36 +00:00
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
for(Combatant c : sideB.values())
|
2018-09-06 08:08:36 +00:00
|
|
|
{
|
2018-09-07 07:41:22 +00:00
|
|
|
c.decision = Decision.UNDECIDED;
|
2018-09-06 08:08:36 +00:00
|
|
|
}
|
2018-09-07 07:41:22 +00:00
|
|
|
state = State.DECISION;
|
2018-09-12 05:43:59 +00:00
|
|
|
undecidedCount.set(players.size());
|
2018-09-07 07:41:22 +00:00
|
|
|
healthCheck();
|
2018-09-14 03:44:45 +00:00
|
|
|
isCreativeCheck();
|
2018-09-17 04:27:13 +00:00
|
|
|
FMLCommonHandler.instance().getMinecraftServerInstance().addScheduledTask(() -> {
|
|
|
|
sendMessageToAllPlayers(PacketBattleMessage.MessageType.TURN_END, 0, 0, 0);
|
|
|
|
});
|
2018-09-07 07:41:22 +00:00
|
|
|
break;
|
|
|
|
} // case ACTION
|
2018-09-10 05:59:56 +00:00
|
|
|
default:
|
|
|
|
state = State.DECISION;
|
|
|
|
break;
|
2018-09-07 07:41:22 +00:00
|
|
|
} // switch(state)
|
2018-09-06 08:08:36 +00:00
|
|
|
return battleEnded;
|
2018-09-10 05:59:56 +00:00
|
|
|
} // update(final long dt)
|
2018-08-28 06:13:14 +00:00
|
|
|
}
|