forked from MagicBane/Server
				
			
				 2 changed files with 294 additions and 1 deletions
			
			
		| @ -1,9 +1,278 @@ | |||||||
| package engine.mobileAI.MobHandlers; | 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 class MobHandler { | ||||||
|     public static void run(Mob mob){ |     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