Public Repository for the Magicbane Shadowbane Emulator
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

242 lines
7.8 KiB

package engine.mobileAI.Behaviours;
import engine.Enum;
import engine.InterestManagement.WorldGrid;
import engine.math.Vector3fImmutable;
import engine.mobileAI.utilities.CombatUtilities;
import engine.mobileAI.utilities.MovementUtilities;
import engine.objects.*;
import engine.server.MBServerStatics;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
public class StandardMob {
public static void run(Mob mob){
if(!mob.isAlive()){
CheckForRespawn(mob);
return;
}
HashSet<AbstractWorldObject> inRange = WorldGrid.getObjectsInRangePartial(mob.loc, MBServerStatics.CHARACTER_LOAD_RANGE, MBServerStatics.MASK_PLAYER);
if(inRange.isEmpty())
return;
if (mob.isMoving()) {
mob.setLoc(mob.getMovementLoc());
mob.updateLocation();
}
if(mob.combatTarget == null) {
if (!inRange.isEmpty()) {
CheckForAggro(mob);
}
}else{
CheckToDropCombatTarget(mob);
if(mob.combatTarget == null){
CheckForAggro(mob);
}
}
if(MovementUtilities.canMove(mob))
CheckForMovement(mob);
if(mob.combatTarget != null && !mob.isMoving())
CheckForAttack(mob);
}
public static void CheckToDropCombatTarget(Mob mob){
if(!mob.combatTarget.isAlive()){
mob.setCombatTarget(null);
return;
}
if(mob.combatTarget.getObjectType().equals(Enum.GameObjectType.PlayerCharacter)){
PlayerCharacter pcTarget = (PlayerCharacter) mob.combatTarget;
if (!mob.canSee(pcTarget)) {
mob.setCombatTarget(null);
return;
}
}
if(mob.bindLoc.distanceSquared(mob.combatTarget.loc) > 90 * 90){
mob.setCombatTarget(null);
}
}
public static void CheckForRespawn(Mob mob){
if (mob.deathTime == 0) {
mob.setDeathTime(System.currentTimeMillis());
return;
}
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_ONCE_LOOTED) {
mob.despawn();
mob.deathTime = System.currentTimeMillis();
return;
}
}
return;
}
if(Mob.discDroppers.contains(mob))
return;
if (System.currentTimeMillis() > (mob.deathTime + (mob.spawnTime * 1000L))) {
Zone.respawnQue.add(mob);
}
}
public static void CheckForAggro(Mob mob){
if(mob == null || !mob.isAlive() || mob.playerAgroMap.isEmpty()){
return;
}
if(mob.BehaviourType.equals(Enum.MobBehaviourType.HamletGuard)){
return;
}
if(mob.hate_values == null)
mob.hate_values = new HashMap<>();
if(mob.combatTarget != null)
return;
HashSet<AbstractWorldObject> inRange = WorldGrid.getObjectsInRangePartial(mob.loc, 60f, MBServerStatics.MASK_PLAYER);
if(inRange.isEmpty()){
mob.setCombatTarget(null);
return;
}
//clear out any players who are not in hated range anymore
ArrayList<PlayerCharacter> toRemove = new ArrayList<>();
for(PlayerCharacter pc : mob.hate_values.keySet()){
if(!inRange.contains(pc))
toRemove.add(pc);
}
for(PlayerCharacter pc : toRemove){
mob.hate_values.remove(pc);
}
//find most hated target
PlayerCharacter mostHated = null;
for(AbstractWorldObject awo : inRange){
PlayerCharacter loadedPlayer = (PlayerCharacter)awo;
if (loadedPlayer == null)
continue;
//Player is Dead, Mob no longer needs to attempt to aggro. Remove them from aggro map.
if (!loadedPlayer.isAlive())
continue;
//Can't see target, skip aggro.
if (!mob.canSee(loadedPlayer))
continue;
// No aggro for this race type
if (mob.notEnemy != null && mob.notEnemy.size() > 0 && mob.notEnemy.contains(loadedPlayer.getRace().getRaceType().getMonsterType()))
continue;
//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()))
continue;
if(mostHated == null)
mostHated = loadedPlayer;
if(mob.hate_values.containsKey(loadedPlayer))
if(mob.hate_values.get(loadedPlayer) > mob.hate_values.get(mostHated))
mostHated = loadedPlayer;
}
if(mostHated != null)
mob.setCombatTarget(mostHated);
}
public static void CheckForMovement(Mob mob){
if(mob.combatTarget != null){
//chase player
if(!CombatUtilities.inRange2D(mob,mob.combatTarget,mob.getRange())) {
MovementUtilities.aiMove(mob, mob.combatTarget.loc, false);
}else{
mob.stopMovement(mob.getMovementLoc());
}
}else{
//patrol
if (mob.isMoving())
return;
Vector3fImmutable patrolPoint = Vector3fImmutable.getRandomPointOnCircle(mob.bindLoc, 40f);
MovementUtilities.aiMove(mob, patrolPoint, true);
}
}
public static void CheckForAttack(Mob mob){
if(mob.isMoving())
return;
if(mob.getLastAttackTime() > System.currentTimeMillis())
return;
if (mob.BehaviourType.callsForHelp)
MobCallForHelp(mob);
ItemBase mainHand = mob.getWeaponItemBase(true);
ItemBase offHand = mob.getWeaponItemBase(false);
if(!CombatUtilities.inRange2D(mob,mob.combatTarget,mob.getRange()))
return;
if (mainHand == null && offHand == null) {
CombatUtilities.combatCycle(mob, mob.combatTarget, true, null);
int delay = 3000;
mob.setLastAttackTime(System.currentTimeMillis() + delay);
} else if (mob.getWeaponItemBase(true) != null) {
int delay = 3000;
CombatUtilities.combatCycle(mob, mob.combatTarget, true, mob.getWeaponItemBase(true));
mob.setLastAttackTime(System.currentTimeMillis() + delay);
} else if (mob.getWeaponItemBase(false) != null) {
int attackDelay = 3000;
CombatUtilities.combatCycle(mob, mob.combatTarget, false, mob.getWeaponItemBase(false));
mob.setLastAttackTime(System.currentTimeMillis() + attackDelay);
}
}
public static void MobCallForHelp(Mob mob){
HashSet<AbstractWorldObject> mobs = WorldGrid.getObjectsInRangePartial(mob.loc,60f, MBServerStatics.MASK_MOB);
for(AbstractWorldObject awo : mobs){
Mob responder = (Mob)awo;
if(responder.combatTarget == null)
if(MovementUtilities.canMove(responder))
MovementUtilities.aiMove(responder,mob.loc,false);
}
}
}