2 changed files with 294 additions and 1 deletions
			
			
		@ -1,9 +1,278 @@
				@@ -1,9 +1,278 @@
					 | 
				
			||||
package engine.mobileAI.MobHandlers; | 
				
			||||
 | 
				
			||||
import engine.objects.Mob; | 
				
			||||
import engine.Enum; | 
				
			||||
import engine.InterestManagement.InterestManager; | 
				
			||||
import engine.gameManager.ChatManager; | 
				
			||||
import engine.gameManager.PowersManager; | 
				
			||||
import engine.gameManager.ZoneManager; | 
				
			||||
import engine.math.Vector3f; | 
				
			||||
import engine.math.Vector3fImmutable; | 
				
			||||
import engine.mobileAI.Threads.MobAIThread; | 
				
			||||
import engine.mobileAI.utilities.CombatUtilities; | 
				
			||||
import engine.mobileAI.utilities.MovementUtilities; | 
				
			||||
import engine.objects.*; | 
				
			||||
import engine.powers.PowersBase; | 
				
			||||
import engine.server.MBServerStatics; | 
				
			||||
 | 
				
			||||
import java.util.Map; | 
				
			||||
import java.util.concurrent.ThreadLocalRandom; | 
				
			||||
 | 
				
			||||
public class MobHandler { | 
				
			||||
    public static void run(Mob mob){ | 
				
			||||
 | 
				
			||||
        if (!mob.isAlive()) { | 
				
			||||
            CheckForRespawn(mob); | 
				
			||||
            return; | 
				
			||||
        } | 
				
			||||
 | 
				
			||||
        if(mob.playerAgroMap.isEmpty()) | 
				
			||||
            return; | 
				
			||||
 | 
				
			||||
        CheckToSendMobHome(mob); | 
				
			||||
 | 
				
			||||
        if(mob.combatTarget == null || !mob.combatTarget.isAlive()){ | 
				
			||||
            CheckForAggro(mob); | 
				
			||||
            return; | 
				
			||||
        } | 
				
			||||
        if(mob.combatTarget != null) | 
				
			||||
            CheckToDropAggro(mob); | 
				
			||||
 | 
				
			||||
        if(MovementUtilities.canMove(mob)) | 
				
			||||
            CheckMobMovement(mob); | 
				
			||||
 | 
				
			||||
        if(mob.combatTarget != null && CombatUtilities.inRangeToAttack(mob,mob.combatTarget)) | 
				
			||||
            CheckToAttack(mob); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static void CheckToDropAggro(Mob mob){ | 
				
			||||
        if(mob.loc.distanceSquared(mob.combatTarget.loc) > (64f * 64f)) | 
				
			||||
            mob.setCombatTarget(null); | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static void CheckForRespawn(Mob mob){ | 
				
			||||
        try { | 
				
			||||
 | 
				
			||||
            if (mob.deathTime == 0) { | 
				
			||||
                mob.setDeathTime(System.currentTimeMillis()); | 
				
			||||
                return; | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            //handles checking for respawn of dead mobs even when no players have mob loaded
 | 
				
			||||
            //Despawn Timer with Loot currently in inventory.
 | 
				
			||||
 | 
				
			||||
            if (!mob.despawned) { | 
				
			||||
 | 
				
			||||
                if (mob.getCharItemManager().getInventoryCount() > 0) { | 
				
			||||
                    if (System.currentTimeMillis() > mob.deathTime + MBServerStatics.DESPAWN_TIMER_WITH_LOOT) { | 
				
			||||
                        mob.despawn(); | 
				
			||||
                        mob.deathTime = System.currentTimeMillis(); | 
				
			||||
                        return; | 
				
			||||
                    } | 
				
			||||
                    //No items in inventory.
 | 
				
			||||
                } else if (mob.isHasLoot()) { | 
				
			||||
                    if (System.currentTimeMillis() > mob.deathTime + MBServerStatics.DESPAWN_TIMER_ONCE_LOOTED) { | 
				
			||||
                        mob.despawn(); | 
				
			||||
                        mob.deathTime = System.currentTimeMillis(); | 
				
			||||
                        return; | 
				
			||||
                    } | 
				
			||||
                    //Mob never had Loot.
 | 
				
			||||
                } else { | 
				
			||||
                    if (System.currentTimeMillis() > mob.deathTime + MBServerStatics.DESPAWN_TIMER) { | 
				
			||||
                        mob.despawn(); | 
				
			||||
                        mob.deathTime = System.currentTimeMillis(); | 
				
			||||
                        return; | 
				
			||||
                    } | 
				
			||||
                } | 
				
			||||
                return; | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if(Mob.discDroppers.contains(mob)) | 
				
			||||
                return; | 
				
			||||
 | 
				
			||||
            if (mob.despawned && System.currentTimeMillis() > (mob.deathTime + (mob.spawnTime * 1000L))) { | 
				
			||||
                if (!Zone.respawnQue.contains(mob)) { | 
				
			||||
                    Zone.respawnQue.add(mob); | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
        } catch (Exception e) { | 
				
			||||
            //(aiAgent.getObjectUUID() + " " + aiAgent.getName() + " Failed At: CheckForRespawn" + " " + e.getMessage());
 | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static void CheckForAggro(Mob mob){ | 
				
			||||
        PlayerCharacter tar = null; | 
				
			||||
        for(int id : mob.playerAgroMap.keySet()){ | 
				
			||||
            PlayerCharacter target = PlayerCharacter.getFromCache(id); | 
				
			||||
            if(tar == null || mob.loc.distanceSquared(tar.loc) < mob.loc.distanceSquared(target.loc)) | 
				
			||||
                if(MobCanAggro(mob,target)) | 
				
			||||
                    tar = target; | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static Boolean MobCanAggro(Mob mob, PlayerCharacter loadedPlayer){ | 
				
			||||
        if (loadedPlayer == null) | 
				
			||||
            return false; | 
				
			||||
 | 
				
			||||
        //Player is Dead, Mob no longer needs to attempt to aggro. Remove them from aggro map.
 | 
				
			||||
        if (!loadedPlayer.isAlive()) | 
				
			||||
            return false; | 
				
			||||
 | 
				
			||||
        //Can't see target, skip aggro.
 | 
				
			||||
        if (!mob.canSee(loadedPlayer)) | 
				
			||||
            return false; | 
				
			||||
 | 
				
			||||
        // No aggro for this race type
 | 
				
			||||
        if (mob.notEnemy != null && mob.notEnemy.size() > 0 && mob.notEnemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType())) | 
				
			||||
            return false; | 
				
			||||
 | 
				
			||||
        //mob has enemies and this player race is not it
 | 
				
			||||
        if (mob.enemy != null && mob.enemy.size() > 0 && !mob.enemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType())) | 
				
			||||
            return false; | 
				
			||||
 | 
				
			||||
        return true; | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static void CheckMobMovement(Mob mob){ | 
				
			||||
        if(!mob.isAlive()) | 
				
			||||
            return; | 
				
			||||
 | 
				
			||||
        if(mob.combatTarget == null){ | 
				
			||||
            //patrol
 | 
				
			||||
            Patrol(mob); | 
				
			||||
        }else{ | 
				
			||||
            //combat movement
 | 
				
			||||
            if(CombatUtilities.inRangeToAttack(mob,mob.combatTarget)) | 
				
			||||
                return; | 
				
			||||
            else | 
				
			||||
                MovementUtilities.aiMove(mob,mob.combatTarget.loc,false); | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static void CheckToAttack(Mob mob){ | 
				
			||||
        try { | 
				
			||||
 | 
				
			||||
            PlayerCharacter target = (PlayerCharacter) mob.combatTarget; | 
				
			||||
 | 
				
			||||
            if (!mob.canSee(target)) { | 
				
			||||
                mob.setCombatTarget(null); | 
				
			||||
                return; | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (mob.BehaviourType.callsForHelp) | 
				
			||||
                MobCallForHelp(mob); | 
				
			||||
 | 
				
			||||
            if (mob.isMoving() && mob.getRange() > 20) | 
				
			||||
                return; | 
				
			||||
 | 
				
			||||
            if(target.combatStats == null) | 
				
			||||
                target.combatStats = new PlayerCombatStats(target); | 
				
			||||
 | 
				
			||||
            ItemBase mainHand = mob.getWeaponItemBase(true); | 
				
			||||
            ItemBase offHand = mob.getWeaponItemBase(false); | 
				
			||||
 | 
				
			||||
            if (mainHand == null && offHand == null) { | 
				
			||||
                CombatUtilities.combatCycle(mob, target, true, null); | 
				
			||||
                int delay = 3000; | 
				
			||||
                mob.setLastAttackTime(System.currentTimeMillis() + delay); | 
				
			||||
            } else if (mob.getWeaponItemBase(true) != null) { | 
				
			||||
                int delay = 3000; | 
				
			||||
                CombatUtilities.combatCycle(mob, target, true, mob.getWeaponItemBase(true)); | 
				
			||||
                mob.setLastAttackTime(System.currentTimeMillis() + delay); | 
				
			||||
            } else if (mob.getWeaponItemBase(false) != null) { | 
				
			||||
                int attackDelay = 3000; | 
				
			||||
                CombatUtilities.combatCycle(mob, target, false, mob.getWeaponItemBase(false)); | 
				
			||||
                mob.setLastAttackTime(System.currentTimeMillis() + attackDelay); | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            if (target.getPet() != null) | 
				
			||||
                if (target.getPet().getCombatTarget() == null && target.getPet().assist) | 
				
			||||
                    target.getPet().setCombatTarget(mob); | 
				
			||||
 | 
				
			||||
        } catch (Exception e) { | 
				
			||||
            ////(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackPlayer" + " " + e.getMessage());
 | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    public static void MobCallForHelp(Mob mob) { | 
				
			||||
 | 
				
			||||
        try { | 
				
			||||
 | 
				
			||||
            boolean callGotResponse = false; | 
				
			||||
 | 
				
			||||
            if (mob.nextCallForHelp == 0) | 
				
			||||
                mob.nextCallForHelp = System.currentTimeMillis(); | 
				
			||||
 | 
				
			||||
            if (mob.nextCallForHelp < System.currentTimeMillis()) | 
				
			||||
                return; | 
				
			||||
 | 
				
			||||
            //mob sends call for help message
 | 
				
			||||
 | 
				
			||||
            ChatManager.chatSayInfo(null, mob.getName() + " calls for help!"); | 
				
			||||
 | 
				
			||||
            Zone mobCamp = mob.getParentZone(); | 
				
			||||
 | 
				
			||||
            for (Mob helper : mobCamp.zoneMobSet) { | 
				
			||||
                if (helper.BehaviourType.respondsToCallForHelp && helper.BehaviourType.BehaviourHelperType.equals(mob.BehaviourType)) { | 
				
			||||
                    helper.setCombatTarget(mob.getCombatTarget()); | 
				
			||||
                    callGotResponse = true; | 
				
			||||
                } | 
				
			||||
            } | 
				
			||||
 | 
				
			||||
            //wait 60 seconds to call for help again
 | 
				
			||||
 | 
				
			||||
            if (callGotResponse) | 
				
			||||
                mob.nextCallForHelp = System.currentTimeMillis() + 60000; | 
				
			||||
 | 
				
			||||
        } catch (Exception e) { | 
				
			||||
            //(mob.getObjectUUID() + " " + mob.getName() + " Failed At: MobCallForHelp" + " " + e.getMessage());
 | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    private static void Patrol(Mob mob) { | 
				
			||||
 | 
				
			||||
        try { | 
				
			||||
 | 
				
			||||
            //make sure mob is out of combat stance
 | 
				
			||||
 | 
				
			||||
            int patrolDelay = ThreadLocalRandom.current().nextInt((int) (MobAIThread.AI_PATROL_DIVISOR * 0.5f), MobAIThread.AI_PATROL_DIVISOR) + MobAIThread.AI_PATROL_DIVISOR; | 
				
			||||
 | 
				
			||||
            //early exit while waiting to patrol again
 | 
				
			||||
 | 
				
			||||
            if (mob.stopPatrolTime + (patrolDelay * 1000) > System.currentTimeMillis()) | 
				
			||||
                return; | 
				
			||||
 | 
				
			||||
            if (mob.lastPatrolPointIndex > mob.patrolPoints.size() - 1) | 
				
			||||
                mob.lastPatrolPointIndex = 0; | 
				
			||||
 | 
				
			||||
            mob.destination = mob.patrolPoints.get(mob.lastPatrolPointIndex); | 
				
			||||
            mob.lastPatrolPointIndex += 1; | 
				
			||||
 | 
				
			||||
            MovementUtilities.aiMove(mob, mob.destination, true); | 
				
			||||
 | 
				
			||||
        } catch (Exception e) { | 
				
			||||
            ////(mob.getObjectUUID() + " " + mob.getName() + " Failed At: AttackTarget" + " " + e.getMessage());
 | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
 | 
				
			||||
    private static void CheckToSendMobHome(Mob mob) { | 
				
			||||
 | 
				
			||||
        if(mob.isNecroPet()) | 
				
			||||
            return; | 
				
			||||
 | 
				
			||||
        try { | 
				
			||||
 | 
				
			||||
            if (!MovementUtilities.inRangeOfBindLocation(mob)) { | 
				
			||||
 | 
				
			||||
                PowersBase recall = PowersManager.getPowerByToken(-1994153779); | 
				
			||||
                PowersManager.useMobPower(mob, mob, recall, 40); | 
				
			||||
 | 
				
			||||
                for (Map.Entry playerEntry : mob.playerAgroMap.entrySet()) | 
				
			||||
                    PlayerCharacter.getFromCache((int) playerEntry.getKey()).setHateValue(0); | 
				
			||||
 | 
				
			||||
                mob.setCombatTarget(null); | 
				
			||||
            } | 
				
			||||
        } catch (Exception e) { | 
				
			||||
            //(mob.getObjectUUID() + " " + mob.getName() + " Failed At: CheckToSendMobHome" + " " + e.getMessage());
 | 
				
			||||
        } | 
				
			||||
    } | 
				
			||||
} | 
				
			||||
				 
					 | 
				
			||||
					Loading…
					
					
				
		Reference in new issue