From 6d91b28eb97af4b4e452d0b8d63e013b92a413da Mon Sep 17 00:00:00 2001 From: CharonInferar Date: Sat, 12 Jul 2014 03:04:32 +0200 Subject: [PATCH] Fixed #0000063 - Fixed: Incap timer reset to 10s -Fixed NPC AI not deathblowing when it should - Added: NPCs now engage factional enemies --- .../objects/tangible/TangibleObject.java | 10 +++ src/services/CharacterService.java | 2 +- src/services/SimulationService.java | 10 +++ src/services/ai/AIActor.java | 68 ++++++++++++++++++- src/services/ai/states/AttackState.java | 21 ++++-- src/services/combat/CombatService.java | 8 +++ 6 files changed, 110 insertions(+), 9 deletions(-) diff --git a/src/resources/objects/tangible/TangibleObject.java b/src/resources/objects/tangible/TangibleObject.java index 2a62ead1..7ee29c12 100644 --- a/src/resources/objects/tangible/TangibleObject.java +++ b/src/resources/objects/tangible/TangibleObject.java @@ -401,6 +401,16 @@ public class TangibleObject extends SWGObject implements Serializable { companion.updatePvpStatus(); } } + + + if (this instanceof CreatureObject){ + if (((CreatureObject)this).isPlayer()){ + // Here a specific CREO delta must be sent to update the faction info in character sheet and symbol in name + // If anyone knows which that would be, please replace it here! + sendBaselines(this.getClient()); + + } + } } public boolean isAttackableBy(CreatureObject attacker) { diff --git a/src/services/CharacterService.java b/src/services/CharacterService.java index 3fa7a8df..9755562a 100644 --- a/src/services/CharacterService.java +++ b/src/services/CharacterService.java @@ -268,7 +268,7 @@ public class CharacterService implements INetworkDispatch { object.setPosition(SpawnPoint.getRandomPosition(new Point3D(3528, 0, -4804), (float) 0.5, 3, core.terrainService.getPlanetByName("tatooine").getID())); object.setCashCredits(100); object.setBankCredits(1000); - object.setIncapTimer(60); + object.setIncapTimer(10); object.setOptionsBitmask(Options.ATTACKABLE); //object.setPosition(new Point3D(0, 0, 0)); object.setOrientation(new Quaternion(1, 0, 0, 0)); diff --git a/src/services/SimulationService.java b/src/services/SimulationService.java index 8b7822f3..052e1b6c 100644 --- a/src/services/SimulationService.java +++ b/src/services/SimulationService.java @@ -277,6 +277,16 @@ public class SimulationService implements INetworkDispatch { ); return checkObject.get(); } + + public Vector getAllNearNPCs(int distance, SWGObject value ){ + Vector foundCreatures = new Vector(); + core.simulationService.get(value.getPlanet(), value.getWorldPosition().x, value.getWorldPosition().z, distance).stream().forEach((objecta) -> { + if (objecta instanceof CreatureObject) + foundCreatures.add((CreatureObject)objecta); + } + ); + return foundCreatures; + } public boolean move(SWGObject object, int oldX, int oldZ, int newX, int newZ) { if(quadTrees.get(object.getPlanet().getName()).remove(oldX, oldZ, object)) { diff --git a/src/services/ai/AIActor.java b/src/services/ai/AIActor.java index bd9c2819..477dcd67 100644 --- a/src/services/ai/AIActor.java +++ b/src/services/ai/AIActor.java @@ -50,6 +50,7 @@ import services.ai.states.RetreatState; import services.combat.CombatEvents.DamageTaken; import services.spawn.MobileTemplate; import tools.DevLog; +import resources.datatables.FactionStatus; import java.util.Random; @@ -67,6 +68,7 @@ public class AIActor { private long lastAttackTimestamp; private ScheduledFuture regenTask; private ScheduledFuture aggroCheckTask; + private ScheduledFuture factionCheckTask; private boolean isStalking = false; private byte milkState = 0; private boolean hasBeenHarvested = false; @@ -149,6 +151,65 @@ public class AIActor { e.printStackTrace(); } }, 0, 5000, TimeUnit.MILLISECONDS); + } + if(creature.getFaction().length()>0 || !creature.getOption(Options.AGGRESSIVE)) { + factionCheckTask = scheduler.scheduleAtFixedRate(() -> { + try { + + if(creature == null || creature.getFactionStatus()!=FactionStatus.Combatant || creature.getObservers().isEmpty() || creature.isInCombat()) + return; + + creature.getObservers().stream().map(Client::getParent).filter(obj -> obj.inRange(creature.getWorldPosition(), 15)).forEach((obj) -> { + if(new Random().nextFloat() <= 0.5 || creature.isInCombat()) { + DevLog.debugout("Charon", "CHECK faction creature ", "added " + creature.getFaction()); + DevLog.debugout("Charon", "CHECK faction obj", "added " + ((TangibleObject)obj).getFaction()); + DevLog.debugout("Charon", "CHECK factionCheckTask", "added " + obj.getCustomName()); + DevLog.debugout("Charon", "CHECK isFactionEnemy", "res " + NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)); + if (obj instanceof CreatureObject && NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)){ + CreatureObject addedObject = (CreatureObject) obj; + if (addedObject.getCalledPet()!=null){ + CreatureObject calledPet = addedObject.getCalledPet(); + if (calledPet.getPosture() != 13 && calledPet.getPosture() != 14){ + addDefender(calledPet); + } + } + if (addedObject.getPosture() != 13 && addedObject.getPosture() != 14){ + addDefender(addedObject); + DevLog.debugout("Charon", "faction creature ", "added " + creature.getFaction()); + DevLog.debugout("Charon", "faction obj", "added " + ((TangibleObject)obj).getFaction()); + DevLog.debugout("Charon", "factionCheckTask", "added " + obj.getCustomName()); + } + } + } + }); + + NGECore.getInstance().simulationService.getAllNearNPCs(15, creature).forEach((obj) -> { + if(new Random().nextFloat() <= 0.5 || creature.isInCombat()) { + DevLog.debugout("Charon", "CHECK faction creature ", "added " + creature.getFaction()); + DevLog.debugout("Charon", "CHECK faction obj", "added " + ((TangibleObject)obj).getFaction()); + DevLog.debugout("Charon", "CHECK factionCheckTask", "added " + obj.getCustomName()); + DevLog.debugout("Charon", "CHECK isFactionEnemy", "res " + NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)); + if (obj instanceof CreatureObject && NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)){ + CreatureObject addedObject = (CreatureObject) obj; + if (addedObject.getCalledPet()!=null){ + CreatureObject calledPet = addedObject.getCalledPet(); + if (calledPet.getPosture() != 13 && calledPet.getPosture() != 14){ + addDefender(calledPet); + } + } + if (addedObject.getPosture() != 13 && addedObject.getPosture() != 14){ + addDefender(addedObject); + DevLog.debugout("Charon", "faction creature ", "added " + creature.getFaction()); + DevLog.debugout("Charon", "faction obj", "added " + ((TangibleObject)obj).getFaction()); + DevLog.debugout("Charon", "factionCheckTask", "added " + obj.getCustomName()); + } + } + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + }, 0, 5000, TimeUnit.MILLISECONDS); } } @@ -378,7 +439,10 @@ public class AIActor { // Sometimes these tasks are null? try { - aggroCheckTask.cancel(true); + if (aggroCheckTask!=null) + aggroCheckTask.cancel(true); + if (factionCheckTask!=null) + factionCheckTask.cancel(true); } catch(Exception e) { } @@ -409,6 +473,8 @@ public class AIActor { // Make sure to kill all AI helper threads if (aggroCheckTask!=null) aggroCheckTask.cancel(true); + if (factionCheckTask!=null) + factionCheckTask.cancel(true); if (regenTask!=null) regenTask.cancel(true); if (movementFuture!=null){ diff --git a/src/services/ai/states/AttackState.java b/src/services/ai/states/AttackState.java index 90233e6b..9bcccb22 100644 --- a/src/services/ai/states/AttackState.java +++ b/src/services/ai/states/AttackState.java @@ -78,13 +78,20 @@ public class AttackState extends AIState { if(weapon != null) maxDistance = weapon.getMaxRange() - 1; } - if(actor.getFollowObject().getWorldPosition().getDistance(creature.getWorldPosition()) > maxDistance) - actor.setNextPosition(actor.getFollowObject().getPosition()); - else { - //recover(actor); - actor.faceObject(actor.getFollowObject()); - actor.scheduleMovement(); - return StateResult.UNFINISHED; + try{ + if(actor.getFollowObject().getWorldPosition().getDistance(creature.getWorldPosition()) > maxDistance) + actor.setNextPosition(actor.getFollowObject().getPosition()); + else { + //recover(actor); + actor.faceObject(actor.getFollowObject()); + actor.scheduleMovement(); + return StateResult.UNFINISHED; + } + } catch (Exception e){ + DevLog.debugout("Charon", "AI Attack State Exception move method", "actor " + actor); + DevLog.debugout("Charon", "AI Attack State Exception move method", "actor.getFollowObject() " + actor.getFollowObject()); + DevLog.debugout("Charon", "AI Attack State Exception move method", "actor.getFollowObject().getWorldPosition() " + actor.getFollowObject().getWorldPosition()); + DevLog.debugout("Charon", "AI Attack State Exception move method", "creature.getWorldPosition() " + creature.getWorldPosition()); } } diff --git a/src/services/combat/CombatService.java b/src/services/combat/CombatService.java index caf2b037..21eec82c 100644 --- a/src/services/combat/CombatService.java +++ b/src/services/combat/CombatService.java @@ -853,6 +853,14 @@ public class CombatService implements INetworkDispatch { return; } + if (!attacker.isPlayer()){ + AIActor aiActor = (AIActor)attacker.getAttachment("AI"); + if (aiActor.getMobileTemplate().isDeathblow()){ + deathblowPlayer(attacker, target); + return; + } + } + synchronized(target.getMutex()) { if (core.mountService.isMounted(target)) { core.mountService.dismount(target, (CreatureObject) target.getContainer());