added barracks list to city object
This commit is contained in:
+186
-364
@@ -29,300 +29,150 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
import static engine.math.FastMath.sqr;
|
import static engine.math.FastMath.sqr;
|
||||||
public class MobileFSM {
|
public class MobileFSM {
|
||||||
private static void mobAttack(Mob aiAgent) {
|
private static void AttackTarget(Mob mob, AbstractWorldObject target) {
|
||||||
|
if(target == null || mob == null){
|
||||||
AbstractGameObject target = aiAgent.getCombatTarget();
|
|
||||||
if (target == null) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (target.getObjectType()) {
|
switch (target.getObjectType()) {
|
||||||
case PlayerCharacter:
|
case PlayerCharacter:
|
||||||
PlayerCharacter player = (PlayerCharacter) target;
|
PlayerCharacter targetPlayer = (PlayerCharacter) target;
|
||||||
if (!player.isActive()) {
|
if (canCast(mob) == true) {
|
||||||
aiAgent.setCombatTarget(null);
|
if (MobCast(mob) == false) {
|
||||||
CheckMobMovement(aiAgent);
|
AttackPlayer(mob, targetPlayer);
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (aiAgent.isNecroPet() && player.inSafeZone()) {
|
|
||||||
aiAgent.setCombatTarget(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (canCast(aiAgent) == true) {
|
|
||||||
if (MobCast(aiAgent) == false) {
|
|
||||||
handlePlayerAttackForMob(aiAgent, player);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handlePlayerAttackForMob(aiAgent, player);
|
AttackPlayer(mob, targetPlayer);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Building:
|
case Building:
|
||||||
Building building = (Building) target;
|
Building targetBuilding = (Building) target;
|
||||||
petHandleBuildingAttack(aiAgent, building);
|
AttackBuilding(mob, targetBuilding);
|
||||||
break;
|
break;
|
||||||
case Mob:
|
case Mob:
|
||||||
Mob mob = (Mob) target;
|
Mob targetMob = (Mob) target;
|
||||||
handleMobAttackForMob(aiAgent, mob);
|
AttackMob(mob,targetMob);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static void petHandleBuildingAttack(Mob aiAgent, Building building) {
|
public static void AttackPlayer(Mob mob, PlayerCharacter target){
|
||||||
|
if (mob.getMobBase().getSeeInvis() < target.getHidden() || !target.isAlive()) {
|
||||||
int buildingHitBox = (int) CombatManager.calcHitBox(building);
|
mob.setCombatTarget(null);
|
||||||
|
|
||||||
if (building.getRank() == -1) {
|
|
||||||
aiAgent.setCombatTarget(null);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (mob.BehaviourType.callsForHelp) {
|
||||||
if (!building.isVulnerable()) {
|
MobCallForHelp(mob);
|
||||||
aiAgent.setCombatTarget(null);
|
}
|
||||||
|
if (!MovementUtilities.inRangeDropAggro(mob, target)) {
|
||||||
|
mob.setAggroTargetID(0);
|
||||||
|
mob.setCombatTarget(null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (CombatUtilities.inRange2D(mob, target, mob.getRange())) {
|
||||||
if (BuildingManager.getBuildingFromCache(building.getObjectUUID()) == null) {
|
//no weapons, default mob attack speed 3 seconds.
|
||||||
aiAgent.setCombatTarget(null);
|
if (System.currentTimeMillis() < mob.getLastAttackTime())
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (building.getParentZone() != null && building.getParentZone().isPlayerCity()) {
|
|
||||||
|
|
||||||
for (Mob mob : building.getParentZone().zoneMobSet) {
|
|
||||||
|
|
||||||
if (!mob.isPlayerGuard())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mob.getCombatTarget() != null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mob.getGuild() != null && building.getGuild() != null)
|
|
||||||
if (!Guild.sameGuild(mob.getGuild().getNation(), building.getGuild().getNation()))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mob.setCombatTarget(aiAgent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CombatUtilities.inRangeToAttack(aiAgent, building)) {
|
|
||||||
//not time to attack yet.
|
|
||||||
|
|
||||||
if (!CombatUtilities.RunAIRandom())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (System.currentTimeMillis() < aiAgent.getLastAttackTime())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (aiAgent.getRange() >= 30 && aiAgent.isMoving())
|
|
||||||
return;
|
|
||||||
|
|
||||||
//reset attack animation
|
|
||||||
if (aiAgent.isSiege())
|
|
||||||
MovementManager.sendRWSSMsg(aiAgent);
|
|
||||||
|
|
||||||
// Fire siege balls
|
|
||||||
// TODO: Fix animations not following stone
|
|
||||||
|
|
||||||
//no weapons, defualt mob attack speed 3 seconds.
|
|
||||||
ItemBase mainHand = aiAgent.getWeaponItemBase(true);
|
|
||||||
ItemBase offHand = aiAgent.getWeaponItemBase(false);
|
|
||||||
|
|
||||||
if (mainHand == null && offHand == null) {
|
|
||||||
|
|
||||||
CombatUtilities.combatCycle(aiAgent, building, true, null);
|
|
||||||
int delay = 3000;
|
|
||||||
|
|
||||||
if (aiAgent.isSiege())
|
|
||||||
delay = 15000;
|
|
||||||
|
|
||||||
aiAgent.setLastAttackTime(System.currentTimeMillis() + delay);
|
|
||||||
} else
|
|
||||||
//TODO set offhand attack time.
|
|
||||||
if (aiAgent.getWeaponItemBase(true) != null) {
|
|
||||||
|
|
||||||
int attackDelay = 3000;
|
|
||||||
|
|
||||||
if (aiAgent.isSiege())
|
|
||||||
attackDelay = 15000;
|
|
||||||
|
|
||||||
CombatUtilities.combatCycle(aiAgent, building, true, aiAgent.getWeaponItemBase(true));
|
|
||||||
aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay);
|
|
||||||
|
|
||||||
} else if (aiAgent.getWeaponItemBase(false) != null) {
|
|
||||||
|
|
||||||
int attackDelay = 3000;
|
|
||||||
|
|
||||||
if (aiAgent.isSiege())
|
|
||||||
attackDelay = 15000;
|
|
||||||
|
|
||||||
CombatUtilities.combatCycle(aiAgent, building, false, aiAgent.getWeaponItemBase(false));
|
|
||||||
aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aiAgent.isSiege()) {
|
|
||||||
PowerProjectileMsg ppm = new PowerProjectileMsg(aiAgent, building);
|
|
||||||
ppm.setRange(50);
|
|
||||||
DispatchMessage.dispatchMsgToInterestArea(aiAgent, ppm, DispatchChannel.SECONDARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Outside of attack Range, Move to players predicted loc.
|
|
||||||
|
|
||||||
if (!aiAgent.isMoving())
|
|
||||||
if (MovementUtilities.canMove(aiAgent))
|
|
||||||
MovementUtilities.moveToLocation(aiAgent, building.getLoc(), aiAgent.getRange() + buildingHitBox);
|
|
||||||
}
|
|
||||||
private static void handlePlayerAttackForMob(Mob aiAgent, PlayerCharacter player) {
|
|
||||||
|
|
||||||
if (aiAgent.getMobBase().getSeeInvis() < player.getHidden()) {
|
|
||||||
aiAgent.setCombatTarget(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!player.isAlive()) {
|
|
||||||
aiAgent.setCombatTarget(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aiAgent.BehaviourType.callsForHelp) {
|
|
||||||
MobCallForHelp(aiAgent);
|
|
||||||
}
|
|
||||||
if (!MovementUtilities.inRangeDropAggro(aiAgent, player)) {
|
|
||||||
aiAgent.setAggroTargetID(0);
|
|
||||||
aiAgent.setCombatTarget(null);
|
|
||||||
MovementUtilities.moveToLocation(aiAgent, aiAgent.getTrueBindLoc(), 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (CombatUtilities.inRange2D(aiAgent, player, aiAgent.getRange())) {
|
|
||||||
|
|
||||||
//no weapons, defualt mob attack speed 3 seconds.
|
|
||||||
|
|
||||||
if (System.currentTimeMillis() < aiAgent.getLastAttackTime())
|
|
||||||
return;
|
|
||||||
|
|
||||||
//if (!CombatUtilities.RunAIRandom())
|
|
||||||
// return;
|
|
||||||
|
|
||||||
// ranged mobs cant attack while running. skip until they finally stop.
|
// ranged mobs cant attack while running. skip until they finally stop.
|
||||||
//if (aiAgent.getRange() >= 30 && aiAgent.isMoving())
|
if (mob.isMoving())
|
||||||
if (aiAgent.isMoving())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// add timer for last attack.
|
// add timer for last attack.
|
||||||
// player.setTimeStamp("LastCombatPlayer", System.currentTimeMillis());
|
ItemBase mainHand = mob.getWeaponItemBase(true);
|
||||||
ItemBase mainHand = aiAgent.getWeaponItemBase(true);
|
ItemBase offHand = mob.getWeaponItemBase(false);
|
||||||
ItemBase offHand = aiAgent.getWeaponItemBase(false);
|
|
||||||
|
|
||||||
if (mainHand == null && offHand == null) {
|
if (mainHand == null && offHand == null) {
|
||||||
|
CombatUtilities.combatCycle(mob, target, true, null);
|
||||||
CombatUtilities.combatCycle(aiAgent, player, true, null);
|
|
||||||
int delay = 3000;
|
int delay = 3000;
|
||||||
|
if (mob.isSiege())
|
||||||
if (aiAgent.isSiege())
|
|
||||||
delay = 11000;
|
delay = 11000;
|
||||||
|
mob.setLastAttackTime(System.currentTimeMillis() + delay);
|
||||||
aiAgent.setLastAttackTime(System.currentTimeMillis() + delay);
|
} else if (mob.getWeaponItemBase(true) != null) {
|
||||||
|
int delay = 3000;
|
||||||
} else
|
if (mob.isSiege())
|
||||||
//TODO set offhand attack time.
|
delay = 11000;
|
||||||
if (aiAgent.getWeaponItemBase(true) != null) {
|
CombatUtilities.combatCycle(mob, target, true, mob.getWeaponItemBase(true));
|
||||||
|
mob.setLastAttackTime(System.currentTimeMillis() + delay);
|
||||||
int delay = 3000;
|
} else if (mob.getWeaponItemBase(false) != null) {
|
||||||
|
int attackDelay = 3000;
|
||||||
if (aiAgent.isSiege())
|
if (mob.isSiege())
|
||||||
delay = 11000;
|
attackDelay = 11000;
|
||||||
|
CombatUtilities.combatCycle(mob, target, false, mob.getWeaponItemBase(false));
|
||||||
CombatUtilities.combatCycle(aiAgent, player, true, aiAgent.getWeaponItemBase(true));
|
mob.setLastAttackTime(System.currentTimeMillis() + attackDelay);
|
||||||
aiAgent.setLastAttackTime(System.currentTimeMillis() + delay);
|
|
||||||
} else if (aiAgent.getWeaponItemBase(false) != null) {
|
|
||||||
|
|
||||||
int attackDelay = 3000;
|
|
||||||
|
|
||||||
if (aiAgent.isSiege())
|
|
||||||
attackDelay = 11000;
|
|
||||||
if (aiAgent.BehaviourType.callsForHelp) {
|
|
||||||
MobCallForHelp(aiAgent);
|
|
||||||
}
|
|
||||||
CombatUtilities.combatCycle(aiAgent, player, false, aiAgent.getWeaponItemBase(false));
|
|
||||||
aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!MovementUtilities.updateMovementToCharacter(aiAgent, player))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!MovementUtilities.canMove(aiAgent))
|
|
||||||
return;
|
|
||||||
|
|
||||||
//this stops mobs from attempting to move while they are underneath a player.
|
|
||||||
if (CombatUtilities.inRangeToAttack2D(aiAgent, player))
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
private static void handleMobAttackForMob(Mob aiAgent, Mob mob) {
|
|
||||||
|
|
||||||
|
|
||||||
if (!mob.isAlive()) {
|
|
||||||
aiAgent.setCombatTarget(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CombatUtilities.inRangeToAttack(aiAgent, mob)) {
|
|
||||||
//not time to attack yet.
|
|
||||||
if (System.currentTimeMillis() < aiAgent.getLastAttackTime()) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CombatUtilities.RunAIRandom())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (aiAgent.getRange() >= 30 && aiAgent.isMoving())
|
|
||||||
return;
|
|
||||||
//no weapons, defualt mob attack speed 3 seconds.
|
|
||||||
ItemBase mainHand = aiAgent.getWeaponItemBase(true);
|
|
||||||
ItemBase offHand = aiAgent.getWeaponItemBase(false);
|
|
||||||
|
|
||||||
if (mainHand == null && offHand == null) {
|
|
||||||
|
|
||||||
CombatUtilities.combatCycle(aiAgent, mob, true, null);
|
|
||||||
int delay = 3000;
|
|
||||||
|
|
||||||
if (aiAgent.isSiege())
|
|
||||||
delay = 11000;
|
|
||||||
|
|
||||||
aiAgent.setLastAttackTime(System.currentTimeMillis() + delay);
|
|
||||||
} else
|
|
||||||
//TODO set offhand attack time.
|
|
||||||
if (aiAgent.getWeaponItemBase(true) != null) {
|
|
||||||
|
|
||||||
int attackDelay = 3000;
|
|
||||||
|
|
||||||
if (aiAgent.isSiege())
|
|
||||||
attackDelay = 11000;
|
|
||||||
|
|
||||||
CombatUtilities.combatCycle(aiAgent, mob, true, aiAgent.getWeaponItemBase(true));
|
|
||||||
aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay);
|
|
||||||
|
|
||||||
} else if (aiAgent.getWeaponItemBase(false) != null) {
|
|
||||||
|
|
||||||
int attackDelay = 3000;
|
|
||||||
|
|
||||||
if (aiAgent.isSiege())
|
|
||||||
attackDelay = 11000;
|
|
||||||
|
|
||||||
CombatUtilities.combatCycle(aiAgent, mob, false, aiAgent.getWeaponItemBase(false));
|
|
||||||
aiAgent.setLastAttackTime(System.currentTimeMillis() + attackDelay);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//use this so mobs dont continue to try to move if they are underneath a flying target. only use 2D range check.
|
|
||||||
if (CombatUtilities.inRangeToAttack2D(aiAgent, mob))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!MovementUtilities.updateMovementToCharacter(aiAgent, mob))
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
private static void patrol(Mob mob) {
|
public static void AttackBuilding(Mob mob, Building target){
|
||||||
|
if (target.getRank() == -1 || !target.isVulnerable() || BuildingManager.getBuildingFromCache(target.getObjectUUID()) == null) {
|
||||||
|
mob.setCombatTarget(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
City playercity = ZoneManager.getCityAtLocation(mob.getLoc());
|
||||||
|
if(playercity != null) {
|
||||||
|
for (Building barracks : playercity.cityBarracks) {
|
||||||
|
for(AbstractCharacter guardCaptain : barracks.getHirelings().keySet()){
|
||||||
|
if(guardCaptain.getCombatTarget() == null){
|
||||||
|
guardCaptain.setCombatTarget(mob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mob.isSiege())
|
||||||
|
MovementManager.sendRWSSMsg(mob);
|
||||||
|
ItemBase mainHand = mob.getWeaponItemBase(true);
|
||||||
|
ItemBase offHand = mob.getWeaponItemBase(false);
|
||||||
|
if (mainHand == null && offHand == null) {
|
||||||
|
CombatUtilities.combatCycle(mob, target, true, null);
|
||||||
|
int delay = 3000;
|
||||||
|
if (mob.isSiege())
|
||||||
|
delay = 15000;
|
||||||
|
mob.setLastAttackTime(System.currentTimeMillis() + delay);
|
||||||
|
} else
|
||||||
|
if (mob.getWeaponItemBase(true) != null) {
|
||||||
|
int attackDelay = 3000;
|
||||||
|
if (mob.isSiege())
|
||||||
|
attackDelay = 15000;
|
||||||
|
CombatUtilities.combatCycle(mob, target, true, mob.getWeaponItemBase(true));
|
||||||
|
mob.setLastAttackTime(System.currentTimeMillis() + attackDelay);
|
||||||
|
} else if (mob.getWeaponItemBase(false) != null) {
|
||||||
|
int attackDelay = 3000;
|
||||||
|
if (mob.isSiege())
|
||||||
|
attackDelay = 15000;
|
||||||
|
CombatUtilities.combatCycle(mob, target, false, mob.getWeaponItemBase(false));
|
||||||
|
mob.setLastAttackTime(System.currentTimeMillis() + attackDelay);
|
||||||
|
}
|
||||||
|
if (mob.isSiege()) {
|
||||||
|
PowerProjectileMsg ppm = new PowerProjectileMsg(mob, target);
|
||||||
|
ppm.setRange(50);
|
||||||
|
DispatchMessage.dispatchMsgToInterestArea(mob, ppm, DispatchChannel.SECONDARY, MBServerStatics.CHARACTER_LOAD_RANGE, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void AttackMob(Mob mob, Mob target){
|
||||||
|
if (mob.getRange() >= 30 && mob.isMoving())
|
||||||
|
return;
|
||||||
|
//no weapons, default mob attack speed 3 seconds.
|
||||||
|
ItemBase mainHand = mob.getWeaponItemBase(true);
|
||||||
|
ItemBase offHand = mob.getWeaponItemBase(false);
|
||||||
|
if (mainHand == null && offHand == null) {
|
||||||
|
CombatUtilities.combatCycle(mob, target, true, null);
|
||||||
|
int delay = 3000;
|
||||||
|
if (mob.isSiege())
|
||||||
|
delay = 11000;
|
||||||
|
mob.setLastAttackTime(System.currentTimeMillis() + delay);
|
||||||
|
} else
|
||||||
|
if (mob.getWeaponItemBase(true) != null) {
|
||||||
|
int attackDelay = 3000;
|
||||||
|
if (mob.isSiege())
|
||||||
|
attackDelay = 11000;
|
||||||
|
CombatUtilities.combatCycle(mob, target, true, mob.getWeaponItemBase(true));
|
||||||
|
mob.setLastAttackTime(System.currentTimeMillis() + attackDelay);
|
||||||
|
} else if (mob.getWeaponItemBase(false) != null) {
|
||||||
|
int attackDelay = 3000;
|
||||||
|
if (mob.isSiege())
|
||||||
|
attackDelay = 11000;
|
||||||
|
CombatUtilities.combatCycle(mob, target, false, mob.getWeaponItemBase(false));
|
||||||
|
mob.setLastAttackTime(System.currentTimeMillis() + attackDelay);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
private static void Patrol(Mob mob) {
|
||||||
//make sure mob is out of combat stance
|
//make sure mob is out of combat stance
|
||||||
if (mob.isCombat() && mob.getCombatTarget() == null) {
|
if (mob.isCombat() && mob.getCombatTarget() == null) {
|
||||||
mob.setCombat(false);
|
mob.setCombat(false);
|
||||||
@@ -495,53 +345,32 @@ public class MobileFSM {
|
|||||||
if (mob == null) {
|
if (mob == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(mob.BehaviourType.ordinal() == Enum.MobBehaviourType.GuardCaptain.ordinal()){
|
if (mob.isAlive() == false) {
|
||||||
//this is a player slotted guard captain
|
//no need to continue if mob is dead, check for respawn and move on
|
||||||
GuardCaptainLogic(mob);
|
CheckForRespawn(mob);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(mob.BehaviourType.ordinal() == Enum.MobBehaviourType.GuardMinion.ordinal()){
|
if (mob.playerAgroMap.isEmpty()) {
|
||||||
//this is a player slotted guard minion
|
//no players loaded, no need to proceed
|
||||||
GuardMinionLogic(mob);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(mob.BehaviourType.ordinal() == Enum.MobBehaviourType.GuardWallArcher.ordinal()){
|
CheckToSendMobHome(mob);
|
||||||
//this is a player slotted guard minion
|
switch(mob.BehaviourType){
|
||||||
GuardWallArcherLogic(mob);
|
case GuardCaptain:
|
||||||
return;
|
GuardCaptainLogic(mob);
|
||||||
}
|
break;
|
||||||
if (mob.isPet() == false && mob.isSummonedPet() == false && mob.isNecroPet() == false) {
|
case GuardMinion:
|
||||||
if (mob.isAlive() == false) {
|
GuardMinionLogic(mob);
|
||||||
//no need to continue if mob is dead, check for respawn and move on
|
break;
|
||||||
CheckForRespawn(mob);
|
case GuardWallArcher:
|
||||||
return;
|
GuardWallArcherLogic(mob);
|
||||||
}
|
break;
|
||||||
//check to see if mob has wandered too far from his bind loc
|
case Pet1:
|
||||||
CheckToSendMobHome(mob);
|
PetLogic(mob);
|
||||||
//check to see if players have mob loaded
|
break;
|
||||||
if (mob.playerAgroMap.isEmpty()) {
|
default:
|
||||||
//no players loaded, no need to proceed
|
DefaultLogic(mob);
|
||||||
return;
|
break;
|
||||||
}
|
|
||||||
//check for players that can be aggroed if mob is agressive and has no target
|
|
||||||
if (mob.BehaviourType.isAgressive && mob.getCombatTarget() == null && mob.BehaviourType != Enum.MobBehaviourType.SimpleStandingGuard) {
|
|
||||||
//normal aggro
|
|
||||||
CheckForAggro(mob);
|
|
||||||
} else if (mob.BehaviourType == Enum.MobBehaviourType.SimpleStandingGuard) {
|
|
||||||
//safehold guard
|
|
||||||
SafeGuardAggro(mob);
|
|
||||||
}
|
|
||||||
//check if mob can move for patrol or moving to target
|
|
||||||
if (mob.BehaviourType.canRoam) {
|
|
||||||
CheckMobMovement(mob);
|
|
||||||
}
|
|
||||||
//check if mob can attack if it isn't wimpy
|
|
||||||
if (!mob.BehaviourType.isWimpy && !mob.isMoving() && mob.combatTarget != null) {
|
|
||||||
CheckForAttack(mob);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
CheckMobMovement(mob);
|
|
||||||
CheckForAttack(mob);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static void CheckForAggro(Mob aiAgent) {
|
private static void CheckForAggro(Mob aiAgent) {
|
||||||
@@ -584,7 +413,7 @@ public class MobileFSM {
|
|||||||
mob.updateLocation();
|
mob.updateLocation();
|
||||||
if (mob.isPet() == false && mob.isSummonedPet() == false && mob.isNecroPet() == false) {
|
if (mob.isPet() == false && mob.isSummonedPet() == false && mob.isNecroPet() == false) {
|
||||||
if (mob.getCombatTarget() == null) {
|
if (mob.getCombatTarget() == null) {
|
||||||
patrol(mob);
|
Patrol(mob);
|
||||||
} else {
|
} else {
|
||||||
chaseTarget(mob);
|
chaseTarget(mob);
|
||||||
}
|
}
|
||||||
@@ -606,54 +435,49 @@ public class MobileFSM {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static void CheckForRespawn(Mob aiAgent) {
|
private static void CheckForRespawn(Mob aiAgent) {
|
||||||
|
if (aiAgent.deathTime == 0) {
|
||||||
|
aiAgent.setDeathTime(System.currentTimeMillis());
|
||||||
|
}
|
||||||
//handles checking for respawn of dead mobs even when no players have mob loaded
|
//handles checking for respawn of dead mobs even when no players have mob loaded
|
||||||
//Despawn Timer with Loot currently in inventory.
|
//Despawn Timer with Loot currently in inventory.
|
||||||
if (aiAgent.getCharItemManager().getInventoryCount() > 0) {
|
if (aiAgent.getCharItemManager().getInventoryCount() > 0) {
|
||||||
if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_WITH_LOOT) {
|
if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_WITH_LOOT) {
|
||||||
aiAgent.despawn();
|
aiAgent.despawn();
|
||||||
//update time of death after mob despawns so respawn time happens after mob despawns.
|
|
||||||
if (aiAgent.deathTime != 0) {
|
|
||||||
aiAgent.setDeathTime(System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
respawn(aiAgent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//No items in inventory.
|
//No items in inventory.
|
||||||
} else {
|
} else {
|
||||||
//Mob's Loot has been looted.
|
//Mob's Loot has been looted.
|
||||||
if (aiAgent.isHasLoot()) {
|
if (aiAgent.isHasLoot()) {
|
||||||
if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_ONCE_LOOTED) {
|
if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER_ONCE_LOOTED) {
|
||||||
aiAgent.despawn();
|
aiAgent.despawn();
|
||||||
//update time of death after mob despawns so respawn time happens after mob despawns.
|
|
||||||
if (aiAgent.deathTime != 0) {
|
|
||||||
aiAgent.setDeathTime(System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
respawn(aiAgent);
|
|
||||||
}
|
}
|
||||||
//Mob never had Loot.
|
//Mob never had Loot.
|
||||||
} else {
|
} else {
|
||||||
if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER) {
|
if (System.currentTimeMillis() > aiAgent.deathTime + MBServerStatics.DESPAWN_TIMER) {
|
||||||
aiAgent.despawn();
|
aiAgent.despawn();
|
||||||
//update time of death after mob despawns so respawn time happens after mob despawns.
|
//update time of death after mob despawns so respawn time happens after mob despawns.
|
||||||
if (aiAgent.deathTime != 0) {
|
|
||||||
aiAgent.setDeathTime(System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
respawn(aiAgent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (System.currentTimeMillis() > aiAgent.deathTime + (aiAgent.spawnTime * 1000)) {
|
||||||
|
aiAgent.respawn();
|
||||||
|
aiAgent.setCombatTarget(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public static void CheckForAttack(Mob mob) {
|
public static void CheckForAttack(Mob mob) {
|
||||||
//checks if mob can attack based on attack timer and range
|
//checks if mob can attack based on attack timer and range
|
||||||
if (mob.isAlive())
|
if (mob.isAlive() == false){
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!mob.isCombat()) {
|
if (!mob.isCombat()) {
|
||||||
mob.setCombat(true);
|
mob.setCombat(true);
|
||||||
UpdateStateMsg rwss = new UpdateStateMsg();
|
UpdateStateMsg rwss = new UpdateStateMsg();
|
||||||
rwss.setPlayer(mob);
|
rwss.setPlayer(mob);
|
||||||
DispatchMessage.sendToAllInRange(mob, rwss);
|
DispatchMessage.sendToAllInRange(mob, rwss);
|
||||||
}
|
}
|
||||||
mobAttack(mob);
|
if(System.currentTimeMillis() > mob.getLastAttackTime()) {
|
||||||
|
AttackTarget(mob, mob.getCombatTarget());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private static void CheckToSendMobHome(Mob mob) {
|
private static void CheckToSendMobHome(Mob mob) {
|
||||||
|
|
||||||
@@ -705,23 +529,10 @@ public class MobileFSM {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static void respawn(Mob aiAgent) {
|
|
||||||
|
|
||||||
if (!aiAgent.canRespawn())
|
|
||||||
return;
|
|
||||||
|
|
||||||
long spawnTime = aiAgent.getSpawnTime();
|
|
||||||
|
|
||||||
if (aiAgent.isPlayerGuard() && aiAgent.npcOwner != null && !aiAgent.npcOwner.isAlive())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (System.currentTimeMillis() > aiAgent.deathTime + spawnTime) {
|
|
||||||
aiAgent.respawn();
|
|
||||||
aiAgent.setCombatTarget(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private static void chaseTarget(Mob mob) {
|
private static void chaseTarget(Mob mob) {
|
||||||
mob.updateMovementState();
|
mob.updateMovementState();
|
||||||
|
if (CombatUtilities.inRangeToAttack2D(mob, mob.getCombatTarget()))
|
||||||
|
return;
|
||||||
if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mob.getRange()) == false) {
|
if (CombatUtilities.inRange2D(mob, mob.getCombatTarget(), mob.getRange()) == false) {
|
||||||
if (mob.getRange() > 15) {
|
if (mob.getRange() > 15) {
|
||||||
mob.destination = mob.getCombatTarget().getLoc();
|
mob.destination = mob.getCombatTarget().getLoc();
|
||||||
@@ -749,17 +560,9 @@ public class MobileFSM {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static void GuardCaptainLogic(Mob mob){
|
public static void GuardCaptainLogic(Mob mob){
|
||||||
if (mob.playerAgroMap.isEmpty()) {
|
if(mob.getCombatTarget() == null) {
|
||||||
//no players loaded, no need to proceed
|
CheckForPlayerGuardAggro(mob);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (mob.isAlive() == false) {
|
|
||||||
//no need to continue if mob is dead, check for respawn and move on
|
|
||||||
CheckForRespawn(mob);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CheckToSendMobHome(mob);
|
|
||||||
CheckForPlayerGuardAggro(mob);
|
|
||||||
CheckMobMovement(mob);
|
CheckMobMovement(mob);
|
||||||
if(mob.getCombatTarget() != null) {
|
if(mob.getCombatTarget() != null) {
|
||||||
CheckForAttack(mob);
|
CheckForAttack(mob);
|
||||||
@@ -777,12 +580,7 @@ public class MobileFSM {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(mob.isAlive() == false){
|
if(mob.npcOwner.isAlive() == false && mob.getCombatTarget() == null){
|
||||||
CheckForRespawn(mob);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CheckToSendMobHome(mob);
|
|
||||||
if(mob.npcOwner.isAlive() == false){
|
|
||||||
CheckForPlayerGuardAggro(mob);
|
CheckForPlayerGuardAggro(mob);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -792,11 +590,7 @@ public class MobileFSM {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static void GuardWallArcherLogic(Mob mob){
|
public static void GuardWallArcherLogic(Mob mob){
|
||||||
if(mob.isAlive() == false){
|
if(mob.getCombatTarget() == null){
|
||||||
CheckForRespawn(mob);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(mob.npcOwner.isAlive() == false){
|
|
||||||
CheckForPlayerGuardAggro(mob);
|
CheckForPlayerGuardAggro(mob);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -804,6 +598,34 @@ public class MobileFSM {
|
|||||||
CheckForAttack(mob);
|
CheckForAttack(mob);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private static void PetLogic(Mob mob){
|
||||||
|
if(MovementUtilities.canMove(mob)){
|
||||||
|
CheckMobMovement(mob);
|
||||||
|
}
|
||||||
|
if(mob.getCombatTarget() != null) {
|
||||||
|
CheckForAttack(mob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static void DefaultLogic(Mob mob){
|
||||||
|
//check for players that can be aggroed if mob is agressive and has no target
|
||||||
|
if (mob.BehaviourType.isAgressive && mob.getCombatTarget() == null) {
|
||||||
|
if (mob.BehaviourType == Enum.MobBehaviourType.SimpleStandingGuard) {
|
||||||
|
//safehold guard
|
||||||
|
SafeGuardAggro(mob);
|
||||||
|
} else {
|
||||||
|
//normal aggro
|
||||||
|
CheckForAggro(mob);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//check if mob can move for patrol or moving to target
|
||||||
|
if (mob.BehaviourType.canRoam) {
|
||||||
|
CheckMobMovement(mob);
|
||||||
|
}
|
||||||
|
//check if mob can attack if it isn't wimpy
|
||||||
|
if (!mob.BehaviourType.isWimpy && !mob.isMoving() && mob.combatTarget != null) {
|
||||||
|
CheckForAttack(mob);
|
||||||
|
}
|
||||||
|
}
|
||||||
public static void CheckForPlayerGuardAggro(Mob mob) {
|
public static void CheckForPlayerGuardAggro(Mob mob) {
|
||||||
//looks for and sets mobs combatTarget
|
//looks for and sets mobs combatTarget
|
||||||
if (!mob.isAlive()) {
|
if (!mob.isAlive()) {
|
||||||
|
|||||||
@@ -473,10 +473,13 @@ public class InfoCmd extends AbstractDevCmd {
|
|||||||
output += "BuildingID : " + targetMob.getRegion().parentBuildingID;
|
output += "BuildingID : " + targetMob.getRegion().parentBuildingID;
|
||||||
output += "building level : " + targetMob.getRegion().level;
|
output += "building level : " + targetMob.getRegion().level;
|
||||||
output += "building room : " + targetMob.getRegion().room;
|
output += "building room : " + targetMob.getRegion().room;
|
||||||
}else if(targetMob.building != null) {
|
}
|
||||||
output += newline;
|
if(targetMob.building != null) {
|
||||||
output += "BuildingID : " + targetMob.building;
|
output += "Building Name: " + targetMob.building.getName() + newline;
|
||||||
output += "In BuildingLoc : " + targetMob.inBuildingLoc;
|
output += "BuildingID : " + targetMob.building + newline;
|
||||||
|
output += "Bind Loc : " + targetMob.getBindLoc() + newline;
|
||||||
|
output += "Curr Loc : " + targetMob.getLoc() + newline;
|
||||||
|
output += "InBuildingLoc : " + targetMob.inBuildingLoc + newline;
|
||||||
}else{
|
}else{
|
||||||
output += newline;
|
output += newline;
|
||||||
output += "No building found.";
|
output += "No building found.";
|
||||||
|
|||||||
@@ -185,6 +185,9 @@ public class RemoveObjectCmd extends AbstractDevCmd {
|
|||||||
DbManager.BuildingQueries.DELETE_FROM_DATABASE(building);
|
DbManager.BuildingQueries.DELETE_FROM_DATABASE(building);
|
||||||
DbManager.removeFromCache(building);
|
DbManager.removeFromCache(building);
|
||||||
zone.zoneBuildingSet.remove(building);
|
zone.zoneBuildingSet.remove(building);
|
||||||
|
if(building.getBlueprint() != null && building.getBlueprint().getBuildingGroup().equals(BuildingGroup.BARRACK)){
|
||||||
|
building.RemoveFromBarracksList();
|
||||||
|
}
|
||||||
WorldGrid.RemoveWorldObject(building);
|
WorldGrid.RemoveWorldObject(building);
|
||||||
WorldGrid.removeObject(building, pc);
|
WorldGrid.removeObject(building, pc);
|
||||||
|
|
||||||
|
|||||||
@@ -71,11 +71,11 @@ public class LootManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static void RunBootySet(ArrayList<BootySetEntry> entries, Mob mob, float multiplier, boolean inHotzone, boolean fromDeath) {
|
private static void RunBootySet(ArrayList<BootySetEntry> entries, Mob mob, float multiplier, boolean inHotzone, boolean fromDeath) {
|
||||||
|
|
||||||
for (BootySetEntry bse : entries) {
|
for (BootySetEntry bse : entries) {
|
||||||
|
int roll = ThreadLocalRandom.current().nextInt(101);
|
||||||
switch (bse.bootyType) {
|
switch (bse.bootyType) {
|
||||||
case "GOLD":
|
case "GOLD":
|
||||||
if (ThreadLocalRandom.current().nextInt(100) <= (bse.dropChance * multiplier) || fromDeath) {
|
if (roll > (bse.dropChance * multiplier) || fromDeath) {
|
||||||
//early exit, failed to hit minimum chance roll OR booty was generated from mob's death
|
//early exit, failed to hit minimum chance roll OR booty was generated from mob's death
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -87,7 +87,7 @@ public class LootManager {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "LOOT":
|
case "LOOT":
|
||||||
if (ThreadLocalRandom.current().nextInt(100) <= (bse.dropChance * multiplier) || fromDeath) {
|
if (roll > (bse.dropChance * multiplier) || fromDeath) {
|
||||||
//early exit, failed to hit minimum chance roll OR booty was generated from mob's death
|
//early exit, failed to hit minimum chance roll OR booty was generated from mob's death
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -111,7 +111,7 @@ public class LootManager {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
case "EQUIP":
|
case "EQUIP":
|
||||||
if (ThreadLocalRandom.current().nextInt(100) <= (bse.dropChance * multiplier) || !fromDeath) {
|
if (roll > (bse.dropChance * multiplier) && fromDeath) {
|
||||||
//early exit, failed to hit minimum chance roll OR booty wasn't generated from mob's death
|
//early exit, failed to hit minimum chance roll OR booty wasn't generated from mob's death
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,9 @@ public class DestroyBuildingHandler extends AbstractClientMsgHandler {
|
|||||||
WorldGrid.RemoveWorldObject(building);
|
WorldGrid.RemoveWorldObject(building);
|
||||||
WorldGrid.removeObject(building);
|
WorldGrid.removeObject(building);
|
||||||
building.getParentZone().zoneBuildingSet.remove(building);
|
building.getParentZone().zoneBuildingSet.remove(building);
|
||||||
|
if(building.getBlueprint() != null && building.getBlueprint().getBuildingGroup().equals(BuildingGroup.BARRACK)){
|
||||||
|
building.RemoveFromBarracksList();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -879,6 +879,9 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
|||||||
WorldGrid.RemoveWorldObject(building);
|
WorldGrid.RemoveWorldObject(building);
|
||||||
WorldGrid.removeObject(building);
|
WorldGrid.removeObject(building);
|
||||||
building.getParentZone().getParent().zoneBuildingSet.remove(building);
|
building.getParentZone().getParent().zoneBuildingSet.remove(building);
|
||||||
|
if(building.getBlueprint() != null && building.getBlueprint().getBuildingGroup().equals(BuildingGroup.BARRACK)){
|
||||||
|
building.RemoveFromBarracksList();
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// remove gold from walls already placed before returning.
|
// remove gold from walls already placed before returning.
|
||||||
@@ -1338,6 +1341,9 @@ public class PlaceAssetMsgHandler extends AbstractClientMsgHandler {
|
|||||||
WorldGrid.RemoveWorldObject(building);
|
WorldGrid.RemoveWorldObject(building);
|
||||||
WorldGrid.removeObject(building);
|
WorldGrid.removeObject(building);
|
||||||
building.getParentZone().zoneBuildingSet.remove(building);
|
building.getParentZone().zoneBuildingSet.remove(building);
|
||||||
|
if(building.getBlueprint() != null && building.getBlueprint().getBuildingGroup().equals(BuildingGroup.BARRACK)){
|
||||||
|
building.RemoveFromBarracksList();
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -707,43 +707,31 @@ public class Building extends AbstractWorldObject {
|
|||||||
if (this.parentZone != null) {
|
if (this.parentZone != null) {
|
||||||
|
|
||||||
this.parentZone.zoneBuildingSet.remove(this);
|
this.parentZone.zoneBuildingSet.remove(this);
|
||||||
|
if(this.getBlueprint() != null && this.getBlueprint().getBuildingGroup().equals(BuildingGroup.BARRACK)){
|
||||||
|
this.RemoveFromBarracksList();
|
||||||
|
}
|
||||||
zone.zoneBuildingSet.add(this);
|
zone.zoneBuildingSet.add(this);
|
||||||
|
|
||||||
} else
|
} else
|
||||||
zone.zoneBuildingSet.add(this);
|
zone.zoneBuildingSet.add(this);
|
||||||
else if (this.parentZone != null)
|
else if (this.parentZone != null) {
|
||||||
this.parentZone.zoneBuildingSet.remove(this);
|
this.parentZone.zoneBuildingSet.remove(this);
|
||||||
|
if(this.getBlueprint() != null && this.getBlueprint().getBuildingGroup().equals(BuildingGroup.BARRACK)){
|
||||||
|
this.RemoveFromBarracksList();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (this.parentZone == null) {
|
if (this.parentZone == null) {
|
||||||
this.parentZone = zone;
|
this.parentZone = zone;
|
||||||
this.setLoc(new Vector3fImmutable(this.statLat + zone.absX, this.statAlt + zone.absY, this.statLon + zone.absZ));
|
this.setLoc(new Vector3fImmutable(this.statLat + zone.absX, this.statAlt + zone.absY, this.statLon + zone.absZ));
|
||||||
} else
|
} else
|
||||||
this.parentZone = zone;
|
this.parentZone = zone;
|
||||||
|
if(this.getBlueprint() != null && this.getBlueprint().getBuildingGroup().equals(BuildingGroup.BARRACK)){
|
||||||
|
AddToBarracksList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Sets the relative position to a parent zone
|
//Sets the relative position to a parent zone
|
||||||
|
|
||||||
public final void setRelPos(Zone zone, float locX, float locY, float locZ) {
|
|
||||||
|
|
||||||
//update ZoneManager's zone building list
|
|
||||||
|
|
||||||
if (zone != null)
|
|
||||||
if (this.parentZone != null) {
|
|
||||||
if (zone.getObjectUUID() != this.parentZone.getObjectUUID()) {
|
|
||||||
this.parentZone.zoneBuildingSet.remove(this);
|
|
||||||
zone.zoneBuildingSet.add(this);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
zone.zoneBuildingSet.add(this);
|
|
||||||
else if (this.parentZone != null)
|
|
||||||
this.parentZone.zoneBuildingSet.remove(this);
|
|
||||||
|
|
||||||
this.statLat = locX;
|
|
||||||
this.statAlt = locY;
|
|
||||||
this.statLon = locZ;
|
|
||||||
this.parentZone = zone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float getStatLat() {
|
public float getStatLat() {
|
||||||
return statLat;
|
return statLat;
|
||||||
}
|
}
|
||||||
@@ -1757,4 +1745,13 @@ public class Building extends AbstractWorldObject {
|
|||||||
return false;
|
return false;
|
||||||
return this.taxDateTime != null;
|
return this.taxDateTime != null;
|
||||||
}
|
}
|
||||||
|
public void AddToBarracksList(){
|
||||||
|
City playerCity = ZoneManager.getCityAtLocation(this.loc);
|
||||||
|
if(playerCity != null){
|
||||||
|
playerCity.cityBarracks.add(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void RemoveFromBarracksList(){
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ public class City extends AbstractWorldObject {
|
|||||||
|
|
||||||
public volatile boolean protectionEnforced = true;
|
public volatile boolean protectionEnforced = true;
|
||||||
private String hash;
|
private String hash;
|
||||||
|
public ArrayList<Building>cityBarracks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ResultSet Constructor
|
* ResultSet Constructor
|
||||||
|
|||||||
@@ -1343,7 +1343,7 @@ public class Mob extends AbstractIntelligenceAgent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean canRespawn() {
|
public boolean canRespawn() {
|
||||||
return System.currentTimeMillis() > this.deathTime;
|
return System.currentTimeMillis() > this.deathTime + (spawnTime * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user