diff --git a/scripts/mobiles/generic/faction/imperial/imp_defensive_quest_officer.py b/scripts/mobiles/generic/faction/imperial/imp_defensive_quest_officer.py new file mode 100644 index 00000000..5ab86300 --- /dev/null +++ b/scripts/mobiles/generic/faction/imperial/imp_defensive_quest_officer.py @@ -0,0 +1,42 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('fbase_imperial_colonel_extreme') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(False) + mobileTemplate.setSocialGroup("imperial") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("imperial") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setOptionsBitmask(Options.CONVERSABLE | Options.INVULNERABLE) + + templates = Vector() + templates.add('object/mobile/shared_dressed_imperial_colonel_m.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e11.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('imp_defensive_quest_officer', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/imperial/imp_invasion_at_at.py b/scripts/mobiles/generic/faction/imperial/imp_invasion_at_at.py new file mode 100644 index 00000000..b675fa5d --- /dev/null +++ b/scripts/mobiles/generic/faction/imperial/imp_invasion_at_at.py @@ -0,0 +1,42 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('eow_gcw_city_at_st_2') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setScale(1) + mobileTemplate.setSocialGroup("imperial") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("imperial") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + + templates = Vector() + templates.add('object/mobile/vehicle/shared_walker_at_st.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/vehicle/shared_vehicle_atst_ranged.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('imp_invasion_at_at', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/imperial/imp_invasion_at_st.py b/scripts/mobiles/generic/faction/imperial/imp_invasion_at_st.py new file mode 100644 index 00000000..bda2a6a1 --- /dev/null +++ b/scripts/mobiles/generic/faction/imperial/imp_invasion_at_st.py @@ -0,0 +1,42 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('eow_gcw_city_at_st_2') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setScale(1) + mobileTemplate.setSocialGroup("imperial") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("imperial") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + + templates = Vector() + templates.add('object/mobile/vehicle/shared_walker_at_st.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/vehicle/shared_vehicle_atst_ranged.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('imp_invasion_at_st', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/imperial/imp_invasion_general.py b/scripts/mobiles/generic/faction/imperial/imp_invasion_general.py new file mode 100644 index 00000000..194a46b8 --- /dev/null +++ b/scripts/mobiles/generic/faction/imperial/imp_invasion_general.py @@ -0,0 +1,43 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('gcw_city_imperial_general') + mobileTemplate.setLevel(110) + mobileTemplate.setHealth(1000000) + mobileTemplate.setDifficulty(Difficulty.BOSS) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setScale(1) + mobileTemplate.setSocialGroup("imperial") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("imperial") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + + templates = Vector() + templates.add('object/mobile/shared_dressed_imperial_general_m.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e11.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('imp_invasion_general', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/rebel/rebel_defensive_quest_officer.py b/scripts/mobiles/generic/faction/rebel/rebel_defensive_quest_officer.py new file mode 100644 index 00000000..27147933 --- /dev/null +++ b/scripts/mobiles/generic/faction/rebel/rebel_defensive_quest_officer.py @@ -0,0 +1,46 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('crackdown_rebel_colonel') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setSocialGroup("rebel") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("rebel") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + mobileTemplate.setOptionsBitmask(Options.CONVERSABLE | Options.INVULNERABLE) + mobileTemplate.setAIEnabled(False) + + templates = Vector() + templates.add('object/mobile/shared_dressed_rebel_lieutenant_colonel_human_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_lieutenant_colonel_human_male_02.iff') + templates.add('object/mobile/shared_dressed_rebel_lieutenant_colonel_moncal_female_01.iff') + templates.add('object/mobile/shared_dressed_rebel_lieutenant_colonel_rodian_female_01.iff') + templates.add('object/mobile/shared_dressed_rebel_lieutenant_colonel_rodian_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_lieutenant_colonel_zabrak_male_01.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e5.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('rebel_defensive_quest_officer', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/rebel/rebel_invasion_at_xt.py b/scripts/mobiles/generic/faction/rebel/rebel_invasion_at_xt.py new file mode 100644 index 00000000..fbd7c2b2 --- /dev/null +++ b/scripts/mobiles/generic/faction/rebel/rebel_invasion_at_xt.py @@ -0,0 +1,42 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('eow_gcw_city_at_xt_2') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setScale(1) + mobileTemplate.setSocialGroup("rebel") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("rebel") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + + templates = Vector() + templates.add('object/mobile/vehicle/shared_walker_at_xt.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/vehicle/shared_vehicle_atst_ranged.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('rebel_invasion_at_xt', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/rebel/rebel_invasion_general.py b/scripts/mobiles/generic/faction/rebel/rebel_invasion_general.py new file mode 100644 index 00000000..6a6ee374 --- /dev/null +++ b/scripts/mobiles/generic/faction/rebel/rebel_invasion_general.py @@ -0,0 +1,46 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('gcw_city_rebel_general') + mobileTemplate.setLevel(110) + mobileTemplate.setHealth(1000000) + mobileTemplate.setDifficulty(Difficulty.BOSS) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setSocialGroup("rebel") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("rebel") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + + templates = Vector() + templates.add('object/mobile/shared_dressed_rebel_general_human_female_01.iff') + templates.add('object/mobile/shared_dressed_rebel_general_human_female_02.iff') + templates.add('object/mobile/shared_dressed_rebel_general_moncal_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_general_old_twilek_male_01.iff') + templates.add('object/mobile/shared_dressed_rebel_general_rieekan_01.iff') + templates.add('object/mobile/shared_dressed_rebel_general_rodian_female_01.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/carbine/shared_carbine_e5.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('rebel_invasion_general', mobileTemplate) + return \ No newline at end of file diff --git a/scripts/mobiles/generic/faction/rebel/rebel_invasion_hailfire_droid.py b/scripts/mobiles/generic/faction/rebel/rebel_invasion_hailfire_droid.py new file mode 100644 index 00000000..098d612d --- /dev/null +++ b/scripts/mobiles/generic/faction/rebel/rebel_invasion_hailfire_droid.py @@ -0,0 +1,42 @@ +import sys +from services.spawn import MobileTemplate +from services.spawn import WeaponTemplate +from resources.datatables import WeaponType +from resources.datatables import Difficulty +from resources.datatables import Options +from resources.datatables import FactionStatus +from java.util import Vector + + +def addTemplate(core): + mobileTemplate = MobileTemplate() + + mobileTemplate.setCreatureName('eow_gcw_city_at_st_2') + mobileTemplate.setLevel(90) + mobileTemplate.setDifficulty(Difficulty.ELITE) + + mobileTemplate.setMinSpawnDistance(4) + mobileTemplate.setMaxSpawnDistance(8) + mobileTemplate.setDeathblow(True) + mobileTemplate.setScale(1) + mobileTemplate.setSocialGroup("rebel") + mobileTemplate.setAssistRange(0) + mobileTemplate.setStalker(False) + mobileTemplate.setFaction("rebel") + mobileTemplate.setFactionStatus(FactionStatus.Combatant) + + templates = Vector() + templates.add('object/mobile/shared_hailfire_droid.iff') + mobileTemplate.setTemplates(templates) + + weaponTemplates = Vector() + weapontemplate = WeaponTemplate('object/weapon/ranged/vehicle/shared_vehicle_atst_ranged.iff', WeaponType.CARBINE, 1.0, 15, 'energy') + weaponTemplates.add(weapontemplate) + mobileTemplate.setWeaponTemplateVector(weaponTemplates) + + attacks = Vector() + mobileTemplate.setDefaultAttack('rangedShot') + mobileTemplate.setAttacks(attacks) + + core.spawnService.addMobileTemplate('rebel_invasion_hailfire_droid', mobileTemplate) + return \ No newline at end of file diff --git a/src/resources/objects/tangible/TangibleObject.java b/src/resources/objects/tangible/TangibleObject.java index 7ee29c12..256f4071 100644 --- a/src/resources/objects/tangible/TangibleObject.java +++ b/src/resources/objects/tangible/TangibleObject.java @@ -329,9 +329,11 @@ public class TangibleObject extends SWGObject implements Serializable { } public void addDefender(TangibleObject defender) { - if (((CreatureObject)this).getOwnerId()>0){ - if (((CreatureObject)this).getOwnerId()==defender.getObjectID()){ - return; // fix for now until determined where the tamer is added from + if (this instanceof CreatureObject){ + if (((CreatureObject)this).getOwnerId()>0){ + if (((CreatureObject)this).getOwnerId()==defender.getObjectID()){ + return; // fix for now until determined where the tamer is added from + } } } defendersList.add(defender); diff --git a/src/services/DevService.java b/src/services/DevService.java index a06265b2..224308a7 100644 --- a/src/services/DevService.java +++ b/src/services/DevService.java @@ -71,6 +71,14 @@ public class DevService implements INetworkDispatch { public DevService(NGECore core) { this.core = core; loadFrogBuilding(); + // Server developers quick frog access + if (System.getProperty("user.name").equals("Charon")){ + TangibleObject frog = (TangibleObject) core.objectService.createObject("object/tangible/terminal/shared_terminal_character_builder.iff", core.terrainService.getPlanetByName("tatooine")); + frog.setPosition(new Point3D((float)3524, (float)4, (float)-4802)); + frog.setOrientation(new Quaternion((float) 0.9965, 0, (float)-0.09, 0)); + core.simulationService.add(frog, frog.getPosition().x, frog.getPosition().z, true); + } + } public void sendCharacterBuilderSUI(CreatureObject creature, int childMenu) @@ -85,6 +93,8 @@ public class DevService implements INetworkDispatch { suiOptions.put((long) 3, "Locations"); if (System.getProperty("user.name").equals("Charon")) suiOptions.put((long) 4, "Treasure chest test"); + if (System.getProperty("user.name").equals("Charon")) + suiOptions.put((long) 6, "Dearic attack camp"); if (creature.getClient().isGM()) suiOptions.put((long) 200, "Get new CBT"); break; @@ -219,7 +229,12 @@ public class DevService implements INetworkDispatch { //treasureContainer.add(droppedItem); return; - + + case 6: // Locations -890,4, -2994 475,6,-3019 + core.simulationService.transferToPlanet(player, core.terrainService.getPlanetByName("talus"), new Point3D(475,6,-3019), player.getOrientation(), null); + core.invasionService.testPylons(); + return; + // Character case 10: // Set combat level to 90 if (player.getAttachment("hasLeveled") == null) { diff --git a/src/services/SimulationService.java b/src/services/SimulationService.java index 3939b461..4991566c 100644 --- a/src/services/SimulationService.java +++ b/src/services/SimulationService.java @@ -80,6 +80,7 @@ import resources.objects.cell.CellObject; import resources.objects.creature.CreatureObject; import resources.objects.group.GroupObject; import resources.objects.harvester.HarvesterObject; +import resources.objects.installation.InstallationObject; import resources.objects.player.PlayerObject; import resources.objects.tangible.TangibleObject; import resources.common.*; @@ -281,12 +282,62 @@ public class SimulationService implements INetworkDispatch { 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) + if (objecta instanceof CreatureObject && objecta!=value) foundCreatures.add((CreatureObject)objecta); } ); return foundCreatures; } + + public Vector getAllNearNonSameFactionNPCs(int distance, SWGObject value ){ + Vector foundCreatures = new Vector(); + core.simulationService.get(value.getPlanet(), value.getWorldPosition().x, value.getWorldPosition().z, distance).stream().forEach((objecta) -> { + + if (value instanceof CreatureObject){ + CreatureObject npc = (CreatureObject) value; + if (objecta instanceof CreatureObject && objecta!=npc && ((CreatureObject) objecta).getFaction().equals(npc.getFaction())) + foundCreatures.add((CreatureObject)objecta); + } + + if (value instanceof InstallationObject){ + InstallationObject ins = (InstallationObject) value; + if (objecta instanceof CreatureObject && objecta!=ins && ((CreatureObject) objecta).getFaction().equals(ins.getFaction())) + foundCreatures.add((CreatureObject)objecta); + } + } + ); + return foundCreatures; + } + + public Vector getAllNearTANOs(int distance, SWGObject value ){ + Vector foundTANOs = new Vector(); + core.simulationService.get(value.getPlanet(), value.getWorldPosition().x, value.getWorldPosition().z, distance).stream().forEach((objecta) -> { + if (objecta instanceof TangibleObject && objecta!=value) + foundTANOs.add((TangibleObject)objecta); + } + ); + return foundTANOs; + } + + public Vector getAllNearNonSameFactionTANOs(int distance, SWGObject value ){ + Vector foundTANOs = new Vector(); + core.simulationService.get(value.getPlanet(), value.getWorldPosition().x, value.getWorldPosition().z, distance).stream().forEach((objecta) -> { + + if (value instanceof CreatureObject){ + CreatureObject npc = (CreatureObject) value; + if (objecta instanceof CreatureObject && objecta!=npc && ((CreatureObject) objecta).getFaction().equals(npc.getFaction())) + foundTANOs.add((TangibleObject)objecta); + } + + if (value instanceof InstallationObject){ + InstallationObject ins = (InstallationObject) value; + if (objecta instanceof CreatureObject && objecta!=ins && ((CreatureObject) objecta).getFaction().equals(ins.getFaction())) + foundTANOs.add((TangibleObject)objecta); + } + } + ); + return foundTANOs; + } 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 56eaa44d..cc39d5e0 100644 --- a/src/services/ai/AIActor.java +++ b/src/services/ai/AIActor.java @@ -59,7 +59,7 @@ public class AIActor { private CreatureObject creature; private Point3D spawnPosition; private volatile AIState currentState; - private CreatureObject followObject; + private TangibleObject followObject; private Vector movementPoints = new Vector(); private MobileTemplate mobileTemplate; private ScheduledExecutorService scheduler; @@ -157,15 +157,16 @@ public class AIActor { factionCheckTask = scheduler.scheduleAtFixedRate(() -> { try { - if(creature == null || creature.getFactionStatus()!=FactionStatus.Combatant || creature.getObservers().isEmpty() || creature.isInCombat()) + // this is difficult, should NPC not fight when no player is near? || creature.getObservers().isEmpty() + if(creature == null || creature.getFactionStatus()!=FactionStatus.Combatant || 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)); +// 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){ @@ -174,7 +175,32 @@ public class AIActor { addDefender(calledPet); } } - if (addedObject.getPosture() != 13 && addedObject.getPosture() != 14){ + if (addedObject.getPosture() != 13 && addedObject.getPosture() != 14 && ! addedObject.getOption(Options.INVULNERABLE)){ + 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.getAllNearNonSameFactionNPCs(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 & ! calledPet.getOption(Options.INVULNERABLE)){ + addDefender(calledPet); + } + } + if (addedObject.getPosture() != 13 && addedObject.getPosture() != 14 & ! addedObject.getOption(Options.INVULNERABLE)){ addDefender(addedObject); DevLog.debugout("Charon", "faction creature ", "added " + creature.getFaction()); DevLog.debugout("Charon", "faction obj", "added " + ((TangibleObject)obj).getFaction()); @@ -184,26 +210,18 @@ public class AIActor { } }); - NGECore.getInstance().simulationService.getAllNearNPCs(15, creature).forEach((obj) -> { + NGECore.getInstance().simulationService.getAllNearNonSameFactionTANOs(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()); - } + DevLog.debugout("Charon", "TANO1 CHECK", creature.getTemplate() + " spotted near " + obj.getTemplate()); +// DevLog.debugout("Charon", "TANO CHECK faction obj", "added " + ((TangibleObject)obj).getFaction()); +// DevLog.debugout("Charon", "TANO CHECK factionCheckTask", "added " + obj.getCustomName()); +// DevLog.debugout("Charon", "TANO CHECK isFactionEnemy", "res " + NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)); + if (obj instanceof TangibleObject && !(obj instanceof CreatureObject) && NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)){ + TangibleObject addedObject = (TangibleObject) obj; + addDefender(addedObject); + DevLog.debugout("Charon", "TANO1 faction ", creature.getTemplate() + "added " + creature.getFaction()); + DevLog.debugout("Charon", "TANO1 faction obj", "added " + ((TangibleObject)obj).getFaction()); + DevLog.debugout("Charon", "TANO1 factionCheckTask", "added " + obj.getCustomName()); } } }); @@ -231,15 +249,19 @@ public class AIActor { this.spawnPosition = spawnPosition; } - public void addDefender(CreatureObject defender) { +// public void addDefender(CreatureObject defender) { +// addDefender(defender, false); +// } + public void addDefender(TangibleObject defender) { addDefender(defender, false); } - public void addDefender(CreatureObject defender, boolean isAssisting) { + public void addDefender(TangibleObject defender, boolean isAssisting) { creature.addDefender(defender); if(followObject == null) setFollowObject(defender); + System.out.println("getFollowObject "+ getFollowObject().getTemplate()); setCurrentState(new AttackState()); if(!isAssisting) { NGECore.getInstance().simulationService.get(creature.getPlanet(), creature.getWorldPosition().x, creature.getWorldPosition().z, 38).stream().filter((obj) -> @@ -251,7 +273,7 @@ public class AIActor { } } - public void removeDefender(CreatureObject defender) { + public void removeDefender(TangibleObject defender) { creature.removeDefender(defender); damageMap.remove(defender); defender.removeDefender(creature); @@ -292,11 +314,11 @@ public class AIActor { } } - public CreatureObject getFollowObject() { + public TangibleObject getFollowObject() { return followObject; } - public void setFollowObject(CreatureObject followObject) { + public void setFollowObject(TangibleObject followObject) { this.followObject = followObject; } @@ -346,7 +368,7 @@ public class AIActor { @Handler public void handleDamage(DamageTaken event) { - CreatureObject attacker = event.attacker; + CreatureObject attacker = (CreatureObject)event.attacker; if(damageMap.containsKey(attacker)) damageMap.put(attacker, damageMap.get(attacker) + event.damage); else @@ -409,7 +431,8 @@ public class AIActor { } switch(result) { - + + case StateResult.DEAD: setCurrentState(new DeathState()); break; diff --git a/src/services/ai/AIService.java b/src/services/ai/AIService.java index c1e24c7b..c5b15137 100644 --- a/src/services/ai/AIService.java +++ b/src/services/ai/AIService.java @@ -54,6 +54,8 @@ public class AIService { // TODO: implement cell pathfinding, returning straight line for now Vector path = new Vector(); + if (pointA==null || pointB==null) + return path; path.add(pointA); float x = pointB.x - 1 + new Random().nextFloat(); float z = pointB.z - 1 + new Random().nextFloat(); diff --git a/src/services/ai/LairActor.java b/src/services/ai/LairActor.java index 87e5940b..24758886 100644 --- a/src/services/ai/LairActor.java +++ b/src/services/ai/LairActor.java @@ -84,8 +84,8 @@ public class LairActor { spawnNewCreatures(); for(AIActor ai : creatures) { - ai.addDefender(event.attacker); - event.attacker.addDefender(ai.getCreature()); + ai.addDefender((CreatureObject)event.attacker); + ((CreatureObject)event.attacker).addDefender(ai.getCreature()); } diff --git a/src/services/ai/TurretAIActor.java b/src/services/ai/TurretAIActor.java new file mode 100644 index 00000000..6d204ff9 --- /dev/null +++ b/src/services/ai/TurretAIActor.java @@ -0,0 +1,594 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.ai; + +import java.util.Map; +import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import main.NGECore; +import net.engio.mbassy.listener.Handler; +import engine.clients.Client; +import engine.resources.objects.SWGObject; +import engine.resources.scene.Point3D; +import engine.resources.scene.Quaternion; +import resources.datatables.Options; +import resources.objects.cell.CellObject; +import resources.objects.creature.CreatureObject; +import resources.objects.installation.InstallationObject; +import resources.objects.tangible.TangibleObject; +import services.ai.states.TurretAIState; +import services.ai.states.TurretAIState.StateResult; +import services.ai.states.TurretAttackState; +import services.ai.states.TurretIdleState; +import services.combat.CombatEvents.DamageTaken; +import services.spawn.MobileTemplate; +import tools.DevLog; +import resources.datatables.FactionStatus; + +import java.util.Random; + +public class TurretAIActor { + + private TangibleObject creature; + private Point3D spawnPosition; + private volatile TurretAIState currentState; + private TangibleObject followObject; + private Vector movementPoints = new Vector(); + private MobileTemplate mobileTemplate; + private ScheduledExecutorService scheduler; + private Map damageMap = new ConcurrentHashMap(); + private volatile boolean hasReachedPosition; + private long lastAttackTimestamp; + private ScheduledFuture regenTask; + private ScheduledFuture aggroCheckTask; + private ScheduledFuture factionCheckTask; + private boolean isStalking = false; + private byte milkState = 0; + private boolean hasBeenHarvested = false; + private Vector patrolPoints = new Vector(); + private int patrolPointIndex = 0; + private String loiterDestType = "LOITER"; + private Point3D loiterDestination; + private Point3D originPosition; + private float minLoiterDist; + private float maxLoiterDist; + private String waitState = "NO"; + private long waitStartTime = 0L; + private TurretAIState intendedPrimaryTurretAIState; + private Point3D lastPositionBeforeStateChange; + private boolean patrolLoop = true; // default + private ScheduledFuture recoveryFuture; + + public TurretAIActor(TangibleObject creature, Point3D spawnPosition, ScheduledExecutorService scheduler) { + this.creature = creature; + this.spawnPosition = spawnPosition; + setLastPositionBeforeStateChange(spawnPosition); // just to make sure it's initialized + this.scheduler = scheduler; + creature.getEventBus().subscribe(this); + this.currentState = new TurretIdleState(); + setIntendedPrimaryTurretAIState(this.currentState); // to switch back to after aggro + + if(creature.getOption(Options.AGGRESSIVE)) { + aggroCheckTask = scheduler.scheduleAtFixedRate(() -> { + try { + + if(creature == null || creature.getObservers().isEmpty() || creature.isInCombat() || isStalking) + return; + if (creature.getAttachment("tamed")!=null){ + DevLog.debugout("Charon", "Pet AI", "aggroCheckTask tamed==1"); + return; + } + + if (creature.getCustomName().contains("baby")) + DevLog.debugout("Charon", "Pet AI", "baby aggroCheckTask should not be here " +creature.getAttachment("tamed")); + + creature.getObservers().stream().map(Client::getParent).filter(obj -> obj.inRange(creature.getWorldPosition(), 60)).forEach((obj) -> { + if(new Random().nextFloat() <= 0.5 || creature.isInCombat() || isStalking) { + /*if(mobileTemplate.isStalker()) { + setFollowObject((CreatureObject) obj); + setCurrentState(new StalkState()); + } else */ + + if (creature.getAttachment("IsBeingTamed")!=null) + return; + + if (obj instanceof CreatureObject){ + 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); + } + } + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + }, 0, 5000, TimeUnit.MILLISECONDS); + } + if(creature.getFaction().length()>0 || !creature.getOption(Options.AGGRESSIVE)) { + factionCheckTask = scheduler.scheduleAtFixedRate(() -> { + System.out.println("Turret faction thread"); + 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(), 60)).forEach((obj) -> { + if(new Random().nextFloat() <= 0.5 || creature.isInCombat()) { +// DevLog.debugout("Charon", "TURRET CHECK faction creature ", "added " + creature.getFaction()); +// DevLog.debugout("Charon", "TURRET CHECK faction obj", "added " + ((TangibleObject)obj).getFaction()); +// DevLog.debugout("Charon", "TURRET CHECK factionCheckTask", "added " + obj.getCustomName()); +// DevLog.debugout("Charon", "TURRET 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 && ! addedObject.getOption(Options.INVULNERABLE)){ + addDefender(addedObject); +// DevLog.debugout("Charon", "TURRET faction creature ", "added " + creature.getFaction()); +// DevLog.debugout("Charon", "TURRET faction obj", "added " + ((TangibleObject)obj).getFaction()); +// DevLog.debugout("Charon", "TURRET factionCheckTask", "added " + obj.getCustomName()); + } + + } + } + }); + + NGECore.getInstance().simulationService.getAllNearNPCs(60, creature).forEach((obj) -> { + if(new Random().nextFloat() <= 0.5 || creature.isInCombat()) { +// DevLog.debugout("Charon", "TURRET CHECK faction creature ", "added " + creature.getFaction()); +// DevLog.debugout("Charon", "TURRET CHECK faction obj", "added " + ((TangibleObject)obj).getFaction()); +// DevLog.debugout("Charon", "TURRET CHECK factionCheckTask", "added " + obj.getCustomName()); +// DevLog.debugout("Charon", "TURRET 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 & ! calledPet.getOption(Options.INVULNERABLE)){ + addDefender(calledPet); + } + } + if (addedObject.getPosture() != 13 && addedObject.getPosture() != 14 & ! addedObject.getOption(Options.INVULNERABLE)){ + addDefender(addedObject); +// DevLog.debugout("Charon", "TURRET faction creature ", "added " + creature.getFaction()); +// DevLog.debugout("Charon", "TURRET faction obj", "added " + ((TangibleObject)obj).getFaction()); +// DevLog.debugout("Charon", "TURRET factionCheckTask", "added " + obj.getCustomName()); + } + } + } + }); + + NGECore.getInstance().simulationService.getAllNearTANOs(60, creature).forEach((obj) -> { + if(new Random().nextFloat() <= 0.5 || creature.isInCombat()) { + DevLog.debugout("Charon", "TANO CHECK faction creature ", "added " + creature.getFaction()); + DevLog.debugout("Charon", "TANO CHECK faction obj", "added " + ((TangibleObject)obj).getFaction()); + DevLog.debugout("Charon", "TANO CHECK factionCheckTask", "added " + obj.getCustomName()); + DevLog.debugout("Charon", "TANO CHECK isFactionEnemy", "res " + NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)); + if (obj instanceof TangibleObject && !(obj instanceof CreatureObject) && NGECore.getInstance().factionService.isFactionEnemy((TangibleObject)creature, (TangibleObject)obj)){ + TangibleObject addedObject = (TangibleObject) obj; + addDefender(addedObject); + DevLog.debugout("Charon", "TANO faction creature ", "added " + creature.getFaction()); + DevLog.debugout("Charon", "TANO faction obj", "added " + ((TangibleObject)obj).getFaction()); + DevLog.debugout("Charon", "TANO factionCheckTask", "added " + obj.getCustomName()); + } + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + }, 0, 5000, TimeUnit.MILLISECONDS); + + } + } + + public TangibleObject getCreature() { + return creature; + } + + public void setCreature(CreatureObject creature) { + this.creature = creature; + } + + public Point3D getSpawnPosition() { + return spawnPosition; + } + + public void setSpawnPosition(Point3D spawnPosition) { + this.spawnPosition = spawnPosition; + } + +// public void addDefender(CreatureObject defender) { +// addDefender(defender, false); +// } + public void addDefender(TangibleObject defender) { + addDefender(defender, false); + } + + + public void addDefender(TangibleObject defender, boolean isAssisting) { + creature.addDefender(defender); + if(followObject == null) + setFollowObject(defender); + setCurrentState(new TurretAttackState()); +// if(!isAssisting) { +// NGECore.getInstance().simulationService.get(creature.getPlanet(), creature.getWorldPosition().x, creature.getWorldPosition().z, 38).stream().filter((obj) -> +// obj instanceof CreatureObject && +// obj.getAttachment("AI") != null && +// ((TurretAIActor) obj.getAttachment("AI")).getMobileTemplate().getSocialGroup().equals(getMobileTemplate().getSocialGroup()) && +// obj.inRange(creature.getWorldPosition(), ((TurretAIActor) obj.getAttachment("AI")).getMobileTemplate().getAssistRange()) +// ).forEach((obj) -> ((TurretAIActor) obj.getAttachment("AI")).addDefender(defender, true)); +// } + } + + public void removeDefender(TangibleObject defender) { + creature.removeDefender(defender); + damageMap.remove(defender); + defender.removeDefender(creature); + if(followObject == defender) { + setFollowObject(getHighestDamageDealer()); + if(creature.getDefendersList().size() == 0) + setCurrentState(new TurretIdleState()); + } + } + + public CreatureObject getHighestDamageDealer() { + CreatureObject highestDamageDealer = null; + highestDamageDealer = damageMap.keySet().stream().max((c1, c2) -> damageMap.get(c1) - damageMap.get(c2)).orElse(null); + // return first defender if no damage has been dealt + if(highestDamageDealer == null) { + for(TangibleObject tangible : creature.getDefendersList().toArray(new TangibleObject[]{})) { + if(tangible instanceof CreatureObject) + return (CreatureObject) tangible; + } + } + return highestDamageDealer; + } + + public TurretAIState getCurrentState() { + return currentState; + } + + public void setCurrentState(TurretAIState currentState) { + try { + if(currentState.getClass() == this.currentState.getClass()) + return; + if(this.currentState != null) + doStateAction(this.currentState.onExit(this)); + this.currentState = currentState; + doStateAction(currentState.onEnter(this)); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public TangibleObject getFollowObject() { + return followObject; + } + + public void setFollowObject(TangibleObject followObject) { + this.followObject = followObject; + } + + public Vector getMovementPoints() { + return movementPoints; + } + + public void setMovementPoints(Vector movementPoints) { + this.movementPoints = movementPoints; + } + + public MobileTemplate getMobileTemplate() { + return mobileTemplate; + } + + public void setMobileTemplate(MobileTemplate mobileTemplate) { + this.mobileTemplate = mobileTemplate; + } + + public void scheduleRecovery() { + recoveryFuture = scheduler.schedule(() -> { + try { + doStateAction(currentState.recover(TurretAIActor.this)); + } catch (Exception e) { + e.printStackTrace(); + } + }, 2000, TimeUnit.MILLISECONDS); + } + + public void setNextPosition(Point3D position) { + movementPoints.add(0, position); + } + + @Handler + public void handleDamage(DamageTaken event) { + CreatureObject attacker = (CreatureObject)event.attacker; + if(damageMap.containsKey(attacker)) + damageMap.put(attacker, damageMap.get(attacker) + event.damage); + else + damageMap.put(attacker, event.damage); + } + + public Map getDamageMap() { + return damageMap; + } + + public boolean hasReachedPosition() { + return hasReachedPosition; + } + + public void setHasReachedPosition(boolean hasReachedPosition) { + this.hasReachedPosition = hasReachedPosition; + } + + public void faceObject(SWGObject object) { + // Null checks due to a null error at: float direction = + if (object == null) DevLog.debugout("Charon", "AI Actor", "faceObject object is NULL"); + if (creature == null) DevLog.debugout("Charon", "AI Actor", "faceObject creature is NULL"); + if (object.getWorldPosition() == null) DevLog.debugout("Charon", "AI Actor", "faceObject object's position is NULL"); + if (creature.getWorldPosition() == null) DevLog.debugout("Charon", "AI Actor", "faceObject creature's position is NULL"); + + float direction = (float) Math.atan2(object.getWorldPosition().x - creature.getWorldPosition().x, object.getWorldPosition().z - creature.getWorldPosition().z); + if(direction < 0) + direction = (float) (2 * Math.PI + direction); + if(Math.abs(direction - creature.getRadians()) < 0.05) + return; + Quaternion quaternion = new Quaternion((float) Math.cos(direction / 2), 0, (float) Math.sin(direction / 2), 0); + if (quaternion.y < 0.0f && quaternion.w > 0.0f) { + quaternion.y *= -1; + quaternion.w *= -1; + } + if(creature.getContainer() instanceof CellObject) + NGECore.getInstance().simulationService.moveObject(creature, creature.getPosition(), quaternion, creature.getMovementCounter(), 0, (CellObject) creature.getContainer()); + else + NGECore.getInstance().simulationService.moveObject(creature, creature.getPosition(), quaternion, creature.getMovementCounter(), 0, null); + + } + + public long getLastAttackTimestamp() { + return lastAttackTimestamp; + } + + public void setLastAttackTimestamp(long lastAttackTimestamp) { + this.lastAttackTimestamp = lastAttackTimestamp; + } + + public long getTimeSinceLastAttack() { + return System.currentTimeMillis() - getLastAttackTimestamp(); + } + + public void doStateAction(byte result) { + + if (creature==null){ + destroyActor(); + return; + } + + switch(result) { + + case StateResult.DEAD: + destroyActor(); + break; + case StateResult.FINISHED: + case StateResult.UNFINISHED: + return; + case StateResult.IDLE: + setCurrentState(new TurretIdleState()); + return; + + //case StateResult.NONE: + // System.out.println("State action returned error result"); + + } + + } + + public void scheduleDespawn() { + // Sometimes these tasks are null? + + try { + if (aggroCheckTask!=null) + aggroCheckTask.cancel(true); + if (factionCheckTask!=null) + factionCheckTask.cancel(true); + } catch(Exception e) { + + } + + try { + regenTask.cancel(true); + } catch(Exception e) { + + } + + } + + public void destroyActor(){ + creature.getEventBus().unsubscribe(this); + // 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); + } + + public void cancelAggro(){ + try { + aggroCheckTask.cancel(true); + } catch(Exception e) { + } + } + + public ScheduledFuture getRegenTask() { + return regenTask; + } + + public void setRegenTask(ScheduledFuture regenTask) { + this.regenTask = regenTask; + } + + public boolean isStalking() { + return isStalking; + } + + public void setStalking(boolean isStalking) { + this.isStalking = isStalking; + } + + public byte getMilkState() { + synchronized(creature.getMutex()) { + return milkState; + } + } + + public void setMilkState(byte milkState) { + synchronized(creature.getMutex()) { + this.milkState = milkState; + } + } + + public boolean hasBeenHarvested() { + synchronized(creature.getMutex()) { + return hasBeenHarvested; + } + } + + public void setHasBeenHarvested(boolean hasBeenHarvested) { + synchronized(creature.getMutex()) { + this.hasBeenHarvested = hasBeenHarvested; + } + } + + public void setPatrolPoints(Vector patrolPoints){ + this.patrolPoints = patrolPoints; + //setMovementPoints(patrolPoints); + } + + public int getPatrolPointIndex() { + return patrolPointIndex; + } + + public void setPatrolPointIndex(int patrolPointIndex) { + this.patrolPointIndex = patrolPointIndex; + } + + public Point3D getLoiterDestination() { + return loiterDestination; + } + + public void setLoiterDestination(Point3D loiterDestination) { + this.loiterDestination = loiterDestination; + } + + public Point3D getOriginPosition() { + return originPosition; + } + + public void setOriginPosition(Point3D originPosition) { + this.originPosition = originPosition; + } + + public String getLoiterDestType() { + return loiterDestType; + } + + public void setLoiterDestType(String loiterDestType) { + this.loiterDestType = loiterDestType; + } + + public float getMinLoiterDist() { + return minLoiterDist; + } + + public void setMinLoiterDist(float minLoiterDist) { + this.minLoiterDist = minLoiterDist; + } + + public float getMaxLoiterDist() { + return maxLoiterDist; + } + + public void setMaxLoiterDist(float maxLoiterDist) { + this.maxLoiterDist = maxLoiterDist; + } + + public String getWaitState() { + return waitState; + } + + public void setWaitState(String waitState) { + this.waitState = waitState; + } + + public long getWaitStartTime() { + return waitStartTime; + } + + public void setWaitStartTime(long waitStartTime) { + this.waitStartTime = waitStartTime; + } + + public Vector getPatrolPoints() { + return patrolPoints; + } + + public TurretAIState getIntendedPrimaryTurretAIState() { + return intendedPrimaryTurretAIState; + } + + public void setIntendedPrimaryTurretAIState(TurretAIState intendedPrimaryTurretAIState) { + this.intendedPrimaryTurretAIState = intendedPrimaryTurretAIState; + } + + public Point3D getLastPositionBeforeStateChange() { + return lastPositionBeforeStateChange; + } + + public void setLastPositionBeforeStateChange( + Point3D lastPositionBeforeStateChange) { + this.lastPositionBeforeStateChange = lastPositionBeforeStateChange; + } + + public boolean isPatrolLoop() { + return patrolLoop; + } + + public void setPatrolLoop(boolean patrolLoop) { + this.patrolLoop = patrolLoop; + } + +} diff --git a/src/services/ai/states/AIState.java b/src/services/ai/states/AIState.java index f376517e..f5f74585 100644 --- a/src/services/ai/states/AIState.java +++ b/src/services/ai/states/AIState.java @@ -30,6 +30,7 @@ import engine.resources.scene.Quaternion; import resources.common.SpawnPoint; import resources.objects.cell.CellObject; import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; import resources.objects.weapon.WeaponObject; import services.ai.AIActor; @@ -54,6 +55,7 @@ public abstract class AIState { public static final byte PATROL = 5; public static final byte LOITER = 6; public static final byte FOLLOW = 7; + public static final byte ATTACK = 8; } @@ -421,7 +423,7 @@ public abstract class AIState { actor.setFollowObject(null); return; } - CreatureObject target = actor.getFollowObject(); + TangibleObject target = actor.getFollowObject(); float speed = (float) creature.getRunSpeed(); float maxDistance = 6; if(creature.getWeaponId() != 0) { @@ -467,7 +469,7 @@ public abstract class AIState { actor.setFollowObject(null); return; } - CreatureObject target = actor.getFollowObject(); + TangibleObject target = actor.getFollowObject(); float speed = (float) creature.getWalkSpeed(); float maxDistance = 6; if(creature.getWeaponId() != 0) { @@ -544,7 +546,7 @@ public abstract class AIState { actor.setFollowObject(null); return; } - CreatureObject target = actor.getFollowObject(); + TangibleObject target = actor.getFollowObject(); float speed = (float) creature.getWalkSpeed(); float maxDistance = 6; if(creature.getWeaponId() != 0) { @@ -666,7 +668,7 @@ public abstract class AIState { actor.setFollowObject(null); return; } - CreatureObject target = actor.getFollowObject(); + TangibleObject target = actor.getFollowObject(); float speed = (float) creature.getRunSpeed(); float maxDistance = 6; if(creature.getWeaponId() != 0) { diff --git a/src/services/ai/states/AttackState.java b/src/services/ai/states/AttackState.java index 9bcccb22..a5151ce6 100644 --- a/src/services/ai/states/AttackState.java +++ b/src/services/ai/states/AttackState.java @@ -26,6 +26,7 @@ import java.util.Vector; import main.NGECore; import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; import resources.objects.weapon.WeaponObject; import services.ai.AIActor; import tools.DevLog; @@ -105,6 +106,7 @@ public class AttackState extends AIState { @Override public byte recover(AIActor actor) { CreatureObject creature = actor.getCreature(); + DevLog.debugout("Charon", "AI Attack Recover State", creature.getTemplate()); float maxDistance = 0; WeaponObject weapon = null; if(creature.getWeaponId() != 0) { @@ -133,7 +135,7 @@ public class AttackState extends AIState { actor.setCurrentState(new RetreatState()); return StateResult.FINISHED; } - CreatureObject target = actor.getFollowObject(); + TangibleObject target = actor.getFollowObject(); if(target != actor.getHighestDamageDealer() && actor.getHighestDamageDealer() != null) { actor.setFollowObject(actor.getHighestDamageDealer()); target = actor.getFollowObject(); @@ -143,27 +145,32 @@ public class AttackState extends AIState { actor.scheduleRecovery(); return StateResult.UNFINISHED; } - if(target.getPosture() == 13 || target.getPosture() == 14 || target.isInStealth()) { - - actor.setFollowObject(actor.getHighestDamageDealer()); - target = actor.getFollowObject(); - if(target == null) - { - creature.setLookAtTarget(0); - creature.setIntendedTarget(0); - - } - actor.setFollowObject(null); - actor.removeDefender(target); + + if (target instanceof CreatureObject){ + CreatureObject targetCreature = (CreatureObject) target; + if(targetCreature.getPosture() == 13 || targetCreature.getPosture() == 14 || targetCreature.isInStealth()) { + + actor.setFollowObject(actor.getHighestDamageDealer()); + target = (CreatureObject) actor.getFollowObject(); + if(target == null) + { + creature.setLookAtTarget(0); + creature.setIntendedTarget(0); + + } + actor.setFollowObject(null); + actor.removeDefender(target); - actor.setCurrentState(new RetreatState()); - return StateResult.FINISHED; - } - if(target.getWorldPosition().getDistance(creature.getWorldPosition()) > 128 || target.getPosture() == 13 || target.getPosture() == 14) { - actor.removeDefender(target); - actor.scheduleRecovery(); - return StateResult.UNFINISHED; + actor.setCurrentState(new RetreatState()); + return StateResult.FINISHED; + } + if(targetCreature.getWorldPosition().getDistance(creature.getWorldPosition()) > 128 || targetCreature.getPosture() == 13 || targetCreature.getPosture() == 14) { + actor.removeDefender(target); + actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } } + if(target.getWorldPosition().getDistance(creature.getWorldPosition()) > maxDistance) { actor.scheduleRecovery(); return StateResult.UNFINISHED; diff --git a/src/services/ai/states/DeathState.java b/src/services/ai/states/DeathState.java index ed38449f..30461315 100644 --- a/src/services/ai/states/DeathState.java +++ b/src/services/ai/states/DeathState.java @@ -36,12 +36,15 @@ public class DeathState extends AIState { actor.getCreature().setAttachment("radial_filename", "npc/corpse"); //NGECore.getInstance().scriptService.callScript("scripts/radial/npc/corpse", "", "createRadial", NGECore.getInstance(), actor.getCreature().getKiller(), actor.getCreature(), new Vector()); actor.scheduleDespawn(); - CreatureObject killer = (CreatureObject)actor.getCreature().getKiller(); - if (killer==null) - killer = actor.getHighestDamageDealer(); - actor.getCreature().setContainerPermissions(CreatureContainerPermissions.CREATURE_CONTAINER_PERMISSIONS); - NGECore.getInstance().lootService.DropLoot(killer,(TangibleObject)(actor.getCreature())); + if (actor.getCreature().getKiller() instanceof CreatureObject){ + CreatureObject killer = (CreatureObject)actor.getCreature().getKiller(); + if (killer==null) + killer = actor.getHighestDamageDealer(); + actor.getCreature().setContainerPermissions(CreatureContainerPermissions.CREATURE_CONTAINER_PERMISSIONS); + if (killer.isPlayer()) // No point to do this for NPCs + NGECore.getInstance().lootService.DropLoot(killer,(TangibleObject)(actor.getCreature())); + } actor.destroyActor(); // to prevent standing up right after death return 0; diff --git a/src/services/ai/states/TurretAIState.java b/src/services/ai/states/TurretAIState.java new file mode 100644 index 00000000..4ec05cd3 --- /dev/null +++ b/src/services/ai/states/TurretAIState.java @@ -0,0 +1,427 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.ai.states; + +import java.util.NoSuchElementException; +import java.util.Vector; + +import main.NGECore; +import engine.resources.scene.Point3D; +import engine.resources.scene.Quaternion; +import resources.common.SpawnPoint; +import resources.objects.cell.CellObject; +import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; +import resources.objects.weapon.WeaponObject; +import services.ai.TurretAIActor; + +public abstract class TurretAIState { + + public abstract byte onEnter(TurretAIActor actor) throws Exception; + public abstract byte onExit(TurretAIActor actor) throws Exception; + public abstract byte move(TurretAIActor actor) throws Exception; + public abstract byte recover(TurretAIActor actor) throws Exception; + + public enum StateResult {; + + // default error state result + public static final byte NONE = 0; + // finished with state + public static final byte FINISHED = 1; + // unfinished with state, call recover() + public static final byte UNFINISHED = 2; + public static final byte DEAD = 3; + // for deaggro or idling + public static final byte IDLE = 4; + public static final byte PATROL = 5; + public static final byte LOITER = 6; + public static final byte FOLLOW = 7; + + } + + public boolean findNewPosition(TurretAIActor actor, float speed, float stopDistance, Point3D newPosition) { + + speed *= 0.5; // 2 updates per second + TangibleObject creature = actor.getCreature(); + NGECore core = NGECore.getInstance(); + Point3D currentPosition = creature.getPosition(); + Point3D targetPosition = null; + float maxDistance = stopDistance; + boolean finished = false; + float dx, dz, newX = 0, newY = 0, newZ = 0; + Vector movementPoints = actor.getMovementPoints(); + Vector patrolPoints = actor.getPatrolPoints(); + CellObject cell = null; + //while(!finished && movementPoints.size() != 0) { + + + + if (movementPoints.size() != 0){ + try{ + targetPosition = movementPoints.firstElement(); + } catch (NoSuchElementException e) { + targetPosition = currentPosition; + } + } + + if (actor.getCurrentState().getClass().equals(PatrolState.class)){ + targetPosition = patrolPoints.get(actor.getPatrolPointIndex()); + } + + if (actor.getCurrentState().getClass().equals(FollowState.class)){ + targetPosition = actor.getFollowObject().getWorldPosition(); + } + + Vector path = core.aiService.findPath(creature.getPlanetId(), currentPosition, targetPosition); + + float distanceToTarget = targetPosition.getWorldPosition().getDistance(creature.getWorldPosition()); + + if(distanceToTarget > stopDistance) { + maxDistance = Math.min(speed, distanceToTarget - stopDistance); + } else { + return false; + } + + Point3D oldPosition = null; + float pathDistance = 0; + + + + for(int i = 1; i < path.size() && !finished; i++) { + + Point3D currentPathPosition = path.get(i); + cell = currentPathPosition.getCell(); + + if(oldPosition == null) + oldPosition = path.get(0); + Point3D oldWorldPos = oldPosition.getWorldPosition(); + + pathDistance += oldWorldPos.getDistance(currentPathPosition.getWorldPosition()); + if(pathDistance >= maxDistance || i == path.size() - 1 || currentPathPosition.getCell() != creature.getContainer()) { + + finished = true; + + if(movementPoints.size() != 0 && currentPosition.getWorldPosition().getDistance(currentPathPosition.getWorldPosition()) <= stopDistance && cell == creature.getContainer()) { + if(i == path.size() - 1) + movementPoints.remove(0); + finished = false; + } else { + + if(cell == null) + oldPosition = oldPosition.getWorldPosition(); + else { + if(oldPosition.getCell() == null) + oldPosition = core.simulationService.convertPointToModelSpace(oldPosition, cell.getContainer()); + } + + if(pathDistance > maxDistance) { + + float distance = oldWorldPos.getDistance(currentPathPosition.getWorldPosition()); + float travelDistance = distance - (pathDistance - maxDistance); + // temp fix for melee npcs + travelDistance *= 1.3; + if(travelDistance <= 0) { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + } else { + + if(distance > 0) { + dx = currentPathPosition.x - oldPosition.x; + dz = currentPathPosition.z - oldPosition.z; + float deltaDist = (float) Math.sqrt((dx * dx) + (dz * dz)); + newX = (float) (oldPosition.x + (speed * (dx / deltaDist))); + newZ = (float) (oldPosition.z + (speed * (dz / deltaDist))); + + } else { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + } + + } + + if(cell == null) { + float height = core.terrainService.getHeight(creature.getPlanetId(), newX, newZ); + newY = height; + } else { + newY = currentPathPosition.y; + } + } + } + + } else { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + newY = core.terrainService.getHeight(creature.getPlanetId(), newX, newZ); + } + oldPosition = currentPathPosition; + } + //} + newPosition.x = newX; + newPosition.y = newY; + newPosition.z = newZ; + newPosition.setCell(cell); + + return true; + } + + + public boolean findNewLoiterPosition(TurretAIActor actor, float speed, float stopDistance, Point3D newPosition) { + + speed *= 0.5; // 2 updates per second + TangibleObject creature = actor.getCreature(); + NGECore core = NGECore.getInstance(); + Point3D currentPosition = creature.getPosition(); + Point3D targetPosition = null; + float maxDistance = stopDistance; + boolean finished = false; + float dx, dz, newX = 0, newY = 0, newZ = 0; + Vector movementPoints = actor.getMovementPoints(); + CellObject cell = null; + + targetPosition = actor.getLoiterDestination(); + + Vector path = core.aiService.findPath(creature.getPlanetId(), currentPosition, targetPosition); + + float distanceToTarget = targetPosition.getWorldPosition().getDistance(creature.getWorldPosition()); + + if(distanceToTarget > stopDistance) { + maxDistance = Math.min(speed, distanceToTarget - stopDistance); + } else { + return false; + } + + Point3D oldPosition = null; + float pathDistance = 0; + + for(int i = 1; i < path.size() && !finished; i++) { + + Point3D currentPathPosition = path.get(i); + cell = currentPathPosition.getCell(); + + if(oldPosition == null) + oldPosition = path.get(0); + Point3D oldWorldPos = oldPosition.getWorldPosition(); + + pathDistance += oldWorldPos.getDistance(currentPathPosition.getWorldPosition()); + if(pathDistance >= maxDistance || i == path.size() - 1 || currentPathPosition.getCell() != creature.getContainer()) { + + finished = true; + + if(currentPosition.getWorldPosition().getDistance(currentPathPosition.getWorldPosition()) <= stopDistance && cell == creature.getContainer()) { +// if(i == path.size() - 1) +// movementPoints.remove(0); + finished = false; + } else { + + if(cell == null) + oldPosition = oldPosition.getWorldPosition(); + else { + if(oldPosition.getCell() == null) + oldPosition = core.simulationService.convertPointToModelSpace(oldPosition, cell.getContainer()); + } + + if(pathDistance > maxDistance) { + + float distance = oldWorldPos.getDistance(currentPathPosition.getWorldPosition()); + float travelDistance = distance - (pathDistance - maxDistance); + // temp fix for melee npcs + travelDistance *= 1.3; + if(travelDistance <= 0) { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + } else { + + if(distance > 0) { + dx = currentPathPosition.x - oldPosition.x; + dz = currentPathPosition.z - oldPosition.z; + float deltaDist = (float) Math.sqrt((dx * dx) + (dz * dz)); + newX = (float) (oldPosition.x + (speed * (dx / deltaDist))); + newZ = (float) (oldPosition.z + (speed * (dz / deltaDist))); + + } else { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + } + + } + + if(cell == null) { + float height = core.terrainService.getHeight(creature.getPlanetId(), newX, newZ); + newY = height; + } else { + newY = currentPathPosition.y; + } + } + } + + } else { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + newY = core.terrainService.getHeight(creature.getPlanetId(), newX, newZ); + } + oldPosition = currentPathPosition; + } + + newPosition.x = newX; + newPosition.y = newY; + newPosition.z = newZ; + newPosition.setCell(cell); + + return true; + } + + public boolean findNewFollowPosition(TurretAIActor actor, float speed, float stopDistance, Point3D newPosition) { + + speed *= 0.5; // 2 updates per second + TangibleObject creature = actor.getCreature(); + NGECore core = NGECore.getInstance(); + Point3D currentPosition = creature.getPosition(); + Point3D targetPosition = null; + float maxDistance = stopDistance; + boolean finished = false; + float dx, dz, newX = 0, newY = 0, newZ = 0; + Vector movementPoints = actor.getMovementPoints(); + Vector patrolPoints = actor.getPatrolPoints(); + CellObject cell = null; + //while(!finished && movementPoints.size() != 0) { + + + if (movementPoints.size() != 0) + targetPosition = movementPoints.firstElement(); + + if (actor.getCurrentState().getClass().equals(PatrolState.class)){ + targetPosition = patrolPoints.get(actor.getPatrolPointIndex()); + } + + if (actor.getCurrentState().getClass().equals(FollowState.class)){ + targetPosition = actor.getFollowObject().getWorldPosition(); + } + + Vector path = core.aiService.findPath(creature.getPlanetId(), currentPosition, targetPosition); + + float distanceToTarget = targetPosition.getWorldPosition().getDistance(creature.getWorldPosition()); + + if(distanceToTarget > stopDistance) { + maxDistance = Math.min(speed, distanceToTarget - stopDistance); + } else { + return false; + } + + Point3D oldPosition = null; + float pathDistance = 0; + + + + for(int i = 1; i < path.size() && !finished; i++) { + + Point3D currentPathPosition = path.get(i); + cell = currentPathPosition.getCell(); + + if(oldPosition == null) + oldPosition = path.get(0); + Point3D oldWorldPos = oldPosition.getWorldPosition(); + + pathDistance += oldWorldPos.getDistance(currentPathPosition.getWorldPosition()); + if(pathDistance >= maxDistance || i == path.size() - 1 || currentPathPosition.getCell() != creature.getContainer()) { + + finished = true; + + if(movementPoints.size() != 0 && currentPosition.getWorldPosition().getDistance(currentPathPosition.getWorldPosition()) <= stopDistance && cell == creature.getContainer()) { + if(i == path.size() - 1) + movementPoints.remove(0); + finished = false; + } else { + + if(cell == null) + oldPosition = oldPosition.getWorldPosition(); + else { + if(oldPosition.getCell() == null) + oldPosition = core.simulationService.convertPointToModelSpace(oldPosition, cell.getContainer()); + } + + if(pathDistance > maxDistance) { + + float distance = oldWorldPos.getDistance(currentPathPosition.getWorldPosition()); + float travelDistance = distance - (pathDistance - maxDistance); + // temp fix for melee npcs + travelDistance *= 1.3; + if(travelDistance <= 0) { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + } else { + + if(distance > 0) { + dx = currentPathPosition.x - oldPosition.x; + dz = currentPathPosition.z - oldPosition.z; + float deltaDist = (float) Math.sqrt((dx * dx) + (dz * dz)); + newX = (float) (oldPosition.x + (speed * (dx / deltaDist))); + newZ = (float) (oldPosition.z + (speed * (dz / deltaDist))); + + } else { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + } + + } + + if(cell == null) { + float height = core.terrainService.getHeight(creature.getPlanetId(), newX, newZ); + newY = height; + } else { + newY = currentPathPosition.y; + } + } + } + + } else { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + newY = core.terrainService.getHeight(creature.getPlanetId(), newX, newZ); + } + oldPosition = currentPathPosition; + } + //} + newPosition.x = newX; + newPosition.y = newY; + newPosition.z = newZ; + newPosition.setCell(cell); + + return true; + } + + public void doMove(TurretAIActor actor) { + + } + + public void doPatrol(TurretAIActor actor) { + + } + + public void doLoiter(TurretAIActor actor) { + + } + + public void doFollow(TurretAIActor actor) { + + } + +} diff --git a/src/services/ai/states/TurretAttackState.java b/src/services/ai/states/TurretAttackState.java new file mode 100644 index 00000000..7f04794d --- /dev/null +++ b/src/services/ai/states/TurretAttackState.java @@ -0,0 +1,160 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.ai.states; + +import java.util.Random; +import java.util.Vector; + +import main.NGECore; +import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; +import resources.objects.weapon.WeaponObject; +import services.ai.AIActor; +import services.ai.TurretAIActor; +import tools.DevLog; + +public class TurretAttackState extends TurretAIState { + + @Override + public byte onEnter(TurretAIActor actor) { +// DevLog.debugout("Charon", "Turret AI Attack State", "onEnter"); + TangibleObject creature = actor.getCreature(); + +// DevLog.debugout("Charon", "Turret AI Attack State", "onEnter creature.getConditionDamage() " + creature.getConditionDamage()); +// DevLog.debugout("Charon", "Turret AI Attack State", "onEnter creature.getMaximumCondition() " + creature.getMaximumCondition()); + + if(creature.getConditionDamage()>=creature.getMaximumCondition()) + return StateResult.DEAD; + + +// DevLog.debugout("Charon", "Turret AI Attack State", "onEnter creature.getDefendersList().size() " + creature.getDefendersList().size()); +// DevLog.debugout("Charon", "Turret AI Attack State", "onEnter actor.getFollowObject() " + actor.getFollowObject()); + if(!creature.isInCombat() || creature.getDefendersList().size() == 0 || actor.getFollowObject() == null) + return StateResult.FINISHED; + + actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + + @Override + public byte onExit(TurretAIActor actor) { + // TODO Auto-generated method stub + +// actor.getCreature().setLookAtTarget(0); +// actor.getCreature().setIntendedTarget(0); + actor.setFollowObject(null); +// DevLog.debugout("Charon", "AI Attack State", "onExit"); + return StateResult.FINISHED; + } + + @Override + public byte move(TurretAIActor actor) { + + return StateResult.FINISHED; + + } + + @Override + public byte recover(TurretAIActor actor) { + TangibleObject creature = actor.getCreature(); + float maxDistance = 0; + WeaponObject weapon = null; + //weapon = (WeaponObject) creature.getSlottedObject("default_weapon"); + + long weaponID = (long) creature.getAttachment("TurretWeapon"); + weapon = (WeaponObject) NGECore.getInstance().objectService.getObject(weaponID); + //DevLog.debugout("Charon", "AI Attack State", "weapontype " + weapon.getTemplate()); + if(weapon == null) + return StateResult.FINISHED; + + + maxDistance = weapon.getMaxRange() - 1; + + if(actor.getTimeSinceLastAttack() < weapon.getAttackSpeed() * 1000) { + //actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + NGECore core = NGECore.getInstance(); + if(creature.getConditionDamage()>creature.getMaximumCondition()) + return StateResult.DEAD; + + if(!creature.isInCombat() || creature.getDefendersList().size() == 0 || actor.getFollowObject() == null) + { +// creature.setLookAtTarget(0); +// creature.setIntendedTarget(0); + actor.setFollowObject(null); + actor.setCurrentState(new TurretIdleState()); + return StateResult.FINISHED; + } + + TangibleObject target = actor.getFollowObject(); + if(target != actor.getHighestDamageDealer() && actor.getHighestDamageDealer() != null) { + actor.setFollowObject(actor.getHighestDamageDealer()); + target = actor.getFollowObject(); + } + if(target == null) { + DevLog.debugout("Charon", "AI Attack State", "null target"); + actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + + if (target instanceof CreatureObject){ + CreatureObject targetCreature = (CreatureObject) target; + if(targetCreature.getPosture() == 13 || targetCreature.getPosture() == 14 || targetCreature.isInStealth()) { + + actor.setFollowObject(actor.getHighestDamageDealer()); + target = (CreatureObject) actor.getFollowObject(); + if(target == null) + { +// creature.setLookAtTarget(0); +// creature.setIntendedTarget(0); + + } + actor.setFollowObject(null); + actor.removeDefender(target); + + actor.setCurrentState(new TurretIdleState()); + return StateResult.FINISHED; + } + if(targetCreature.getWorldPosition().getDistance(creature.getWorldPosition()) > 128 || targetCreature.getPosture() == 13 || targetCreature.getPosture() == 14) { + actor.removeDefender(target); + actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + } + +// DevLog.debugout("Charon", "AI Attack State", "prior to attacks dist " + target.getWorldPosition().getDistance(creature.getWorldPosition())); +// DevLog.debugout("Charon", "AI Attack State", "prior to attacks maxDistance " + maxDistance); + + if(target.getWorldPosition().getDistance(creature.getWorldPosition()) > maxDistance) { + actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + //actor.faceObject(target); + core.commandService.callCommand(creature, "rangedShot", target, ""); + + actor.setLastAttackTimestamp(System.currentTimeMillis()); + actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + +} diff --git a/src/services/ai/states/TurretIdleState.java b/src/services/ai/states/TurretIdleState.java new file mode 100644 index 00000000..84594f2f --- /dev/null +++ b/src/services/ai/states/TurretIdleState.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.ai.states; + +import services.ai.TurretAIActor; + +public class TurretIdleState extends TurretAIState { + + @Override + public byte onEnter(TurretAIActor actor) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public byte onExit(TurretAIActor actor) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public byte move(TurretAIActor actor) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public byte recover(TurretAIActor actor) { + // TODO Auto-generated method stub + return 0; + } + +} diff --git a/src/services/combat/CombatEvents.java b/src/services/combat/CombatEvents.java index 3dc20ee0..08d25cc8 100644 --- a/src/services/combat/CombatEvents.java +++ b/src/services/combat/CombatEvents.java @@ -23,12 +23,13 @@ package services.combat; import resources.objects.creature.CreatureObject; import engine.resources.common.Event; +import engine.resources.objects.SWGObject; public class CombatEvents implements Event { public class DamageTaken implements Event { - public CreatureObject attacker; + public SWGObject attacker; public int damage; } diff --git a/src/services/combat/CombatService.java b/src/services/combat/CombatService.java index 21eec82c..4281407c 100644 --- a/src/services/combat/CombatService.java +++ b/src/services/combat/CombatService.java @@ -54,6 +54,7 @@ import resources.datatables.Elemental; import resources.datatables.Posture; import resources.datatables.WeaponType; import resources.objects.creature.CreatureObject; +import resources.objects.installation.InstallationObject; import resources.objects.mission.MissionObject; import resources.objects.player.PlayerObject; import resources.objects.tangible.TangibleObject; @@ -240,6 +241,148 @@ public class CombatService implements INetworkDispatch { } } } + + public void doCombatForInstallation(final InstallationObject attacker, final TangibleObject target, final WeaponObject weapon, final CombatCommand command, final int actionCounter) { + if(target instanceof CreatureObject) if(((CreatureObject) target).getPosture() == Posture.Incapacitated || ((CreatureObject) target).getPosture() == Posture.Dead) return; + + boolean success = true; + +// if((command.getAttackType() == 0 || command.getAttackType() == 1 || command.getAttackType() == 3) && !attemptCombat(attacker, target)) +// success = false; + +// if(success && !applySpecialCost(attacker, weapon, command)) +// success = false; + + if(!success) { + IoSession session = attacker.getClient().getSession(); + CommandEnqueueRemove commandRemove = new CommandEnqueueRemove(attacker.getObjectId(), actionCounter); + session.write(new ObjControllerMessage(0x0B, commandRemove).serialize()); + StartTask startTask = new StartTask(actionCounter, attacker.getObjectID(), command.getCommandCRC(), CRC.StringtoCRC(command.getCooldownGroup()), -1); + session.write(new ObjControllerMessage(0x0B, startTask).serialize()); + return; + } + + final Point3D targetPos = target.getPosition(); + final SWGObject targetParent = target.getContainer(); + + if(command.getDelayAttackParticle().length() > 0 || command.getInitialAttackDelay() > -1) { + + if(command.getInitialAttackDelay() > 0) { + + if(command.getDelayAttackParticle().length() > 0) + target.notifyObservers(new PlayClientEffectLocMessage(command.getDelayAttackParticle(), target.getPlanet().getName(), target.getWorldPosition()), true); + + try { + Thread.sleep((long) command.getInitialAttackDelay() * 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + + } else if(command.getInitialAttackDelay() <= 0 && command.getDelayAttackInterval() > 0 && command.getDelayAttackLoops() <= 1) { + + try { + Thread.sleep((long) command.getDelayAttackInterval() * 1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + if(command.getDelayAttackParticle().length() > 0) + target.notifyObservers(new PlayClientEffectLocMessage(command.getDelayAttackParticle(), target.getPlanet().getName(), target.getWorldPosition()), true); + + } + + if(command.getDelayAttackLoops() > 1) { + final ScheduledFuture task = scheduler.scheduleAtFixedRate(new Runnable() { + + @Override + public void run() { + try { + if(command.getDelayAttackParticle().length() > 0) + target.notifyObservers(new PlayClientEffectLocMessage(command.getDelayAttackParticle(), target.getPlanet().getName(), target.getWorldPosition()), true); + + if(command.getAttackType() == 1) + doSingleTargetCombatForInstallation(attacker, target, weapon, command, actionCounter); + //else if(command.getAttackType() == 0 || command.getAttackType() == 2 || command.getAttackType() == 3) + //doAreaCombat(attacker, targetPos, weapon, command, actionCounter, targetParent); + } catch (Exception e) { + e.printStackTrace(); + } + } + + }, 0, (long) (command.getDelayAttackInterval() * 1000), TimeUnit.MILLISECONDS); + + scheduler.schedule(new Runnable() { + + @Override + public void run() { + try { + task.cancel(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + + }, (long) ((command.getDelayAttackInterval() * 1000) * command.getDelayAttackLoops()), TimeUnit.MILLISECONDS); + + return; + + } else { + if(command.getAttackType() == 1) + doSingleTargetCombatForInstallation(attacker, target, weapon, command, actionCounter); + //else if(command.getAttackType() == 0 || command.getAttackType() == 2 || command.getAttackType() == 3) + //doAreaCombat(attacker, targetPos, weapon, command, actionCounter, targetParent); + } + + } else { + + if(command.getAttackType() == 1) + doSingleTargetCombatForInstallation(attacker, target, weapon, command, actionCounter); + //else if(command.getAttackType() == 0 || command.getAttackType() == 2 || command.getAttackType() == 3) + //doAreaCombat(attacker, target, weapon, command, actionCounter); + + } + + if(target instanceof CreatureObject) + { + CreatureObject creature = (CreatureObject)target; + if(creature.getPosture() == Posture.Incapacitated || creature.getPosture() == Posture.Dead) + { + for (TangibleObject defender : new ArrayList(creature.getDefendersList())) + { + defender.removeDefender(creature); + creature.removeDefender(defender); + } + + if(((CreatureObject) target).getPlayerObject() == null) + { + target.setKiller(attacker); + + scheduler.schedule(new Runnable() + { + @Override + public void run() + { + try { + core.objectService.destroyObject(target); + } catch (Exception e) { + e.printStackTrace(); + } + } + + }, 2, TimeUnit.MINUTES); + } + } + } + else if(target instanceof TangibleObject) + { + if(target.getConditionDamage() == target.getMaximumCondition()) + { + for(TangibleObject defender : target.getDefendersList()) defender.removeDefender(target); + core.objectService.destroyObject(target); + } + } + } private void doAreaCombat(CreatureObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { if(target instanceof CreatureObject) { @@ -313,6 +456,24 @@ public class CombatService implements INetworkDispatch { } + private void doSingleTargetCombatForInstallation(InstallationObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { + if(target instanceof CreatureObject) { + doSingleTargetCombatForInstallation(attacker, (CreatureObject) target, weapon, command, actionCounter); + return; + } + + float damage = calculateDamageForInstallation(attacker, target, weapon, command); + + if(damage > 0) + applyDamageForInstallation(attacker, target, (int) damage); + + sendCombatPacketsForInstallation(attacker, target, weapon, command, actionCounter, damage, 0, HitType.HIT); + + if(FileUtilities.doesFileExist("scripts/commands/combat/" + command.getCommandName() + ".py")) + core.scriptService.callScript("scripts/commands/combat/", command.getCommandName(), "run", core, attacker, target, damage); + + } + private void applyDamage(CreatureObject attacker, TangibleObject target, int damage) { target.setConditionDamage(target.getConditionDamage() + damage); @@ -336,9 +497,127 @@ public class CombatService implements INetworkDispatch { event.attacker = attacker; event.damage = damage; target.getEventBus().publish(event); - System.out.println("APPLY DAMAGE2"); attacker.setTefTime(300000); } + + private void applyDamageForInstallation(InstallationObject attacker, TangibleObject target, int damage) { + + target.setConditionDamage(target.getConditionDamage() + damage); + + if (target.getOption(Options.MOUNT)) { + core.mountService.damage((CreatureObject) target); + } + + if (target instanceof CreatureObject){ + CreatureObject targetCreature = (CreatureObject)target; + if (targetCreature.getCalledPet()!=null) { + AIActor petActor = (AIActor) targetCreature.getCalledPet().getAttachment("AI"); + if (petActor!=null){ + petActor.addDefender(attacker); + DevLog.debugout("Charon", "Pet AI", "applyDamage addDefender"); + } + } + } + + DamageTaken event = events.new DamageTaken(); + event.attacker = attacker; + event.damage = damage; + target.getEventBus().publish(event); + //attacker.setTefTime(300000); + } + + private void applyDamageForInstallation(InstallationObject attacker, CreatureObject target, int damage) { + + if(target.getHealth() - damage <= 0 && target.getSlottedObject("ghost") != null) { + + if(target.hasBuff("incapWeaken")) { + + AIActor aiActor = (AIActor)attacker.getAttachment("AI"); + + deathblowPlayerFromInstallation(attacker, target); + return; + } + + + + + AIActor aiActor = (AIActor)attacker.getAttachment("AI"); + if (aiActor.getMobileTemplate().isDeathblow()){ + deathblowPlayerFromInstallation(attacker, target); + return; + } + + + synchronized(target.getMutex()) { + if (core.mountService.isMounted(target)) { + core.mountService.dismount(target, (CreatureObject) target.getContainer()); + } + + target.setHealth(1); + target.setPosture(Posture.Incapacitated); + target.setTurnRadius(0); + target.setSpeedMultiplierBase(0); + + } + + ScheduledFuture incapTask = scheduler.schedule(() -> { + + synchronized(target.getMutex()) { + try { + if(target.getPosture() != 13) + return; + + target.setPosture(Posture.Upright); + target.setTurnRadius(1); + target.setSpeedMultiplierBase(1); + } catch (Exception e) { + e.printStackTrace(); + } + } + + }, target.getIncapTimer(), TimeUnit.SECONDS); + target.setIncapTask(incapTask); + core.buffService.addBuffToCreature(target, "incapWeaken", target); + if(target.getSlottedObject("ghost") != null && attacker.getSlottedObject("ghost") != null) { + target.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_victim_incap", "TT", attacker.getCustomName()), DisplayType.Broadcast); + //attacker.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_target_incap", "TT", target.getCustomName()), DisplayType.Broadcast); + } else {target.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_victim_incap", "TT", "@" + attacker.getStfFilename() + ":" + attacker.getStfName()), DisplayType.Broadcast); } + return; + } else if(target.getHealth() - damage <= 0 && target.getAttachment("AI") != null) { + synchronized(target.getMutex()) { + target.setHealth(0); + target.setPosture(Posture.Dead); + } + attacker.removeDefender(target); + target.removeDefender(attacker); + return; + } + synchronized(target.getMutex()) { + target.setHealth(target.getHealth() - damage); + } + + + if (target instanceof CreatureObject){ + CreatureObject targetCreature = (CreatureObject)target; + if (targetCreature.getCalledPet()!=null) { + AIActor petActor = (AIActor) targetCreature.getCalledPet().getAttachment("AI"); + if (petActor!=null){ + petActor.addDefender(attacker); + DevLog.debugout("Charon", "Pet AI", "applyDamage addDefender"); + } + } + } + + + if (target.getPosture()!=13){ + DamageTaken event = events.new DamageTaken(); + event.attacker = attacker; + event.damage = damage; + target.getEventBus().publish(event); + } + } + + private void doAreaCombat(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { @@ -455,6 +734,27 @@ public class CombatService implements INetworkDispatch { sendCombatPackets(attacker, target, weapon, command, actionCounter, damage, 0, HitType.HIT); } + + private void doSingleTargetCombatForInstallation(InstallationObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { + + float damage = calculateDamageForInstallation(attacker, target, weapon, command); + if(damage > 0) { + damage *= 1.5f; + int damageBeforeArmor = (int) damage; + damage *= 0.99; + int armorAbsorbed = (int) (damageBeforeArmor - damage); + + if(damage > 0) + applyDamageForInstallation(attacker, target, (int) damage); + + sendCombatPacketsForInstallation(attacker, target, weapon, command, actionCounter, damage, armorAbsorbed, HitType.CRITICAL); + + if(FileUtilities.doesFileExist("scripts/commands/combat/" + command.getCommandName() + ".py")) + core.scriptService.callScript("scripts/commands/combat/", command.getCommandName(), "run", core, attacker, target, damage); + + return; + } + } private void sendCombatPackets(CreatureObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter, float damage, int armorAbsorbed, int hitType) { @@ -485,6 +785,21 @@ public class CombatService implements INetworkDispatch { } + private void sendCombatPacketsForInstallation(InstallationObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter, float damage, int armorAbsorbed, int hitType) { + + String animationStr = command.getRandomAnimation(weapon); + int turret_fire = 0xD334C0B8; // 0xA7595B4E + //CombatAction combatAction = new CombatAction(CRC.StringtoCRC(animationStr), attacker.getObjectID(), weapon.getObjectID(), target.getObjectID(), command.getCommandCRC()); + CombatAction combatAction = new CombatAction(turret_fire, attacker.getObjectID(), weapon.getObjectID(), target.getObjectID(), command.getCommandCRC()); + ObjControllerMessage objController = new ObjControllerMessage(0x1B, combatAction); + attacker.notifyObserversInRange(objController, true, 125); + CombatSpam combatSpam = new CombatSpam(attacker.getObjectID(), target.getObjectID(), weapon.getObjectID(), (int) damage, armorAbsorbed, hitType); + ObjControllerMessage objController4 = new ObjControllerMessage(0x1B, combatSpam); + IoBuffer spam = objController4.serialize(); + if(target.getClient() != null) + target.getClient().getSession().write(spam); + } + private void sendHealPackets(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command, int actionCounter) { CombatAction combatAction = new CombatAction(CRC.StringtoCRC(command.getDefaultAnimations()[0]), attacker.getObjectID(), weapon.getObjectID(), target.getObjectID(), command.getCommandCRC()); @@ -682,6 +997,23 @@ public class CombatService implements INetworkDispatch { return rawDamage; } + + private float calculateDamageForInstallation(InstallationObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command) { + + float rawDamage = command.getAddedDamage(); + if(command.getPercentFromWeapon() > 0) { + + float weaponMinDmg = weapon.getMinDamage(); + float weaponMaxDmg = weapon.getMaxDamage(); + + + float weaponDmg = new Random().nextInt((int) (weaponMaxDmg - weaponMinDmg + 1)) + weaponMinDmg; + weaponDmg *= command.getPercentFromWeapon(); + rawDamage += weaponDmg; + + } + return rawDamage; + } private float calculateDamage(CreatureObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command) { @@ -723,6 +1055,24 @@ public class CombatService implements INetworkDispatch { } + private float calculateDamageForInstallation(InstallationObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command) { + + float rawDamage = command.getAddedDamage(); + + if(command.getPercentFromWeapon() > 0 && weapon != attacker.getSlottedObject("default_weapon")) { + + float weaponMinDmg = weapon.getMinDamage(); + float weaponMaxDmg = weapon.getMaxDamage(); + + float weaponDmg = new Random().nextInt((int) (weaponMaxDmg - weaponMinDmg + 1)) + weaponMinDmg; + weaponDmg *= command.getPercentFromWeapon(); + rawDamage += weaponDmg; + } + + return rawDamage; + + } + public byte getHitType(CreatureObject attacker, CreatureObject target, WeaponObject weapon, CombatCommand command) { float r; @@ -1148,6 +1498,26 @@ public class CombatService implements INetworkDispatch { core.playerService.sendCloningWindow(target, attacker.getSlottedObject("ghost") != null); } + + public void deathblowPlayerFromInstallation(InstallationObject attacker, CreatureObject target) { + target.stopIncapTask(); + target.setIncapTask(null); + target.setPosture(Posture.Dead); + + + attacker.removeDefender(target); + target.removeDefender(attacker); + target.setSpeedMultiplierBase(0); + target.setTurnRadius(0); + + if (attacker.getSlottedObject("ghost") != null) + target.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_victim_dead", "TT", attacker.getCustomName()), DisplayType.Broadcast); + else + target.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_victim_dead", "TT", "@" + attacker.getStfFilename() + ":" + attacker.getStfName()), DisplayType.Broadcast); + + core.playerService.sendCloningWindow(target, attacker.getSlottedObject("ghost") != null); + } + public boolean areInDuel(CreatureObject creature1, CreatureObject creature2) { if(creature1.getDuelList().contains(creature2) && creature2.getDuelList().contains(creature1)) @@ -1385,7 +1755,7 @@ public class CombatService implements INetworkDispatch { if(creature.getClient() == null) { if (creature.getAttachment("AI")!=null){ AIActor aiActor = (AIActor) creature.getAttachment("AI"); - CreatureObject target = aiActor.getFollowObject(); + TangibleObject target = aiActor.getFollowObject(); if (target.getClient()!=null) client = target.getClient(); // Use player's client reference that is in combat with that NPC } diff --git a/src/services/command/CommandService.java b/src/services/command/CommandService.java index aa514a51..c593757f 100644 --- a/src/services/command/CommandService.java +++ b/src/services/command/CommandService.java @@ -50,6 +50,7 @@ import protocol.swg.objectControllerObjects.CommandEnqueueRemove; import protocol.swg.objectControllerObjects.StartTask; import resources.objects.cell.CellObject; import resources.objects.creature.CreatureObject; +import resources.objects.installation.InstallationObject; import resources.objects.tangible.TangibleObject; import resources.objects.weapon.WeaponObject; @@ -149,6 +150,7 @@ public class CommandService implements INetworkDispatch { if (!core.simulationService.checkLineOfSight(actor, target)) { actor.showFlyText("@combat_effects:cant_see", 1.5f, new RGB(72, 209, 204), 1, true); + // If this is AI consider side steps to get LOS return false; } @@ -328,8 +330,255 @@ public class CommandService implements INetworkDispatch { return true; } + public boolean callCommandForInstallation(InstallationObject actor, SWGObject target, BaseSWGCommand command, int actionCounter, String commandArgs) { + + if (actor == null) { + return false; + } + + if (command == null) { + return false; + } + + if (command.isDisabled()) { + return false; + } + +// if (actor.hasCooldown(command.getCooldownGroup()) || actor.hasCooldown(command.getCommandName())) { +// return false; +// } + + //TangibleObject weapon = (TangibleObject) core.objectService.getObject(actor.getWeaponId()); + TangibleObject weapon = (TangibleObject) core.objectService.getObject((long)actor.getAttachment("TurretWeapon")); + + if (weapon != null && weapon instanceof WeaponObject && ((WeaponObject) weapon).getWeaponType() == command.getInvalidWeapon()) { + System.out.println("Invalid WEAPON!"); + return false; + } + + + + switch (command.getTargetType()) { + case 0: // Target Not Used For This Command + break; + case 1: // Other Only (objectId/targetName) + if (target == null || target == actor) { + if (commandArgs != null && !commandArgs.equals("")) { + String name = commandArgs.split(" ")[0]; + + target = core.objectService.getObjectByFirstName(name); + + if (target == actor) { + target = null; + } + } + + break; + } + + if (target == actor) { + return false; + } + + if (target.getContainer() == actor || target.getGrandparent() == actor) { + break; + } + + if (command.getMaxRangeToTarget() != 0 && actor.getPosition().getDistance(target.getPosition()) > command.getMaxRangeToTarget()) { + return false; + } + + + if (!target.isInQuadtree() && (target.getContainer() == null || !(target.getContainer() instanceof CellObject))) { + break; + } + + if (!core.simulationService.checkLineOfSight(actor, target)) { + actor.showFlyText("@combat_effects:cant_see", 1.5f, new RGB(72, 209, 204), 1, true); + // If this is AI consider side steps to get LOS + return false; + } + + break; + case 2: // Anyone (objectId/targetName) + if (target == null) { + if (commandArgs != null && !commandArgs.equals("")) { + String name = commandArgs.split(" ")[0]; + + target = core.objectService.getObjectByFirstName(name); + + if (target == actor) { + target = null; + } + + // It's possible they use c cmdString to indicate if it should always be on self + if (name.contains("c")) { + //target = actor; + } + } + + break; + } + + if (target.getContainer() == actor || target.getGrandparent() == actor) { + break; + } + + if (command.getMaxRangeToTarget() != 0 && actor.getPosition().getDistance(target.getPosition()) > command.getMaxRangeToTarget()) { + return false; + } + + if (!target.isInQuadtree() && (target.getContainer() == null || !(target.getContainer() instanceof CellObject))) { + break; + } + + if (!core.simulationService.checkLineOfSight(actor, target)) { + actor.showFlyText("@combat_effects:cant_see", 1.5f, new RGB(72, 209, 204), 1, true); + return false; + } + + break; + case 3: // Free Target Mode (rally points, group waypoints) + target = null; + + if (commandArgs == null) { + break; + } + + String[] args = commandArgs.split(" "); + + float x = 0, y = 0, z = 0; + + try { + if (args.length == 2) { + x = Integer.valueOf(args[0]); + z = Integer.valueOf(args[1]); + } else if (args.length > 2) { + x = Integer.valueOf(args[0]); + y = Integer.valueOf(args[1]); + z = Integer.valueOf(args[2]); + } else { + return false; + } + } catch (NumberFormatException e) { + return false; + } + + Point3D position = new Point3D(x, y, z); + + if (command.getMaxRangeToTarget() != 0 && actor.getPosition().getDistance(position) > command.getMaxRangeToTarget()) { + return false; + } + + break; + case 4: // Any object + if (target == null) { + break; + } + + if (command.getMaxRangeToTarget() != 0 && actor.getPosition().getDistance(target.getPosition()) > command.getMaxRangeToTarget()) { + return false; + } + + if (!target.isInQuadtree() && (target.getContainer() == null || !(target.getContainer() instanceof CellObject))) { + break; + } + + if (!core.simulationService.checkLineOfSight(actor, target)) { + actor.showFlyText("@combat_effects:cant_see", 1.5f, new RGB(72, 209, 204), 1, true); + return false; + } + + break; + default: + break; + } + switch (command.getTarget()) { + case 0: // Ally Only + if (target == null) { + target = actor; + } + + if (!(target instanceof TangibleObject)) { + return false; + } + + TangibleObject object = (TangibleObject) target; + + if (!object.getFaction().equals("") && !object.getFaction().equals(actor.getFaction())) { + return false; + } + + if (actor.getFactionStatus() < object.getFactionStatus()) { + return false; + } + +// if (object.isAttackableBy(actor)) { +// return false; +// } + + // Without this we could be buffing ally NPCs and such + // Think this is checked later on + if (actor.getSlottedObject("ghost") != null && object.getSlottedObject("ghost") == null) { + return false; + } + + break; + case 1: // Enemy Only + if (target == null || !(target instanceof TangibleObject)) { + return false; + } + + TangibleObject targetObject = (TangibleObject) target; + +// if (!targetObject.isAttackableBy(actor)) { +// return false; +// } + + break; + case 2: // Indifferent + break; + default: + break; + } + +// if (command.shouldCallOnTarget()) { +// if (target == null || !(target instanceof CreatureObject)) { +// return false; +// } +// +// actor = (CreatureObject) target; +// } + + long warmupTime = (long) (command.getWarmupTime() * 1000f); + + if(warmupTime > 0) { + try { + Thread.sleep(warmupTime); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + if(command instanceof CombatCommand) { + try { + processCommandForInstallation(actor, target, (BaseSWGCommand) command.clone(), actionCounter, commandArgs); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + } + else + processCommandForInstallation(actor, target, command, actionCounter, commandArgs); + + + return true; + } + public void callCommand(SWGObject actor, String commandName, SWGObject target, String commandArgs) { - callCommand((CreatureObject) actor, target, getCommandByName(commandName), 0, commandArgs); + if (actor instanceof CreatureObject) + callCommand((CreatureObject) actor, target, getCommandByName(commandName), 0, commandArgs); + if (actor instanceof InstallationObject) + callCommandForInstallation((InstallationObject) actor, target, getCommandByName(commandName), 0, commandArgs); } public BaseSWGCommand getCommandByCRC(int commandCRC) { @@ -450,6 +699,22 @@ public class CommandService implements INetworkDispatch { } } + public void processCommandForInstallation(InstallationObject actor, SWGObject target, BaseSWGCommand command, int actionCounter, String commandArgs) { +// if (command.getCooldown() > 0f) { +// actor.addCooldown(command.getCooldownGroup(), command.getCooldown()); +// } + + if (command instanceof CombatCommand) { + processCombatCommandForInstallation(actor, target, (CombatCommand) command, actionCounter, commandArgs); + } else { + if (FileUtilities.doesFileExist("scripts/commands/" + command.getCommandName().toLowerCase() + ".py")) { + core.scriptService.callScript("scripts/commands/", command.getCommandName().toLowerCase(), "run", core, actor, target, commandArgs); + } else if (FileUtilities.doesFileExist("scripts/commands/combat/" + command.getCommandName().toLowerCase() + ".py")) { + core.scriptService.callScript("scripts/commands/combat/", command.getCommandName().toLowerCase(), "run", core, actor, target, commandArgs); + } + } + } + public void processCombatCommand(CreatureObject attacker, SWGObject target, CombatCommand command, int actionCounter, String commandArgs) { if (FileUtilities.doesFileExist("scripts/commands/combat/" + command.getCommandName() + ".py")) { core.scriptService.callScript("scripts/commands/combat/", command.getCommandName(), "setup", core, attacker, target, command); @@ -549,6 +814,100 @@ public class CommandService implements INetworkDispatch { } + public void processCombatCommandForInstallation(InstallationObject attacker, SWGObject target, CombatCommand command, int actionCounter, String commandArgs) { + if (FileUtilities.doesFileExist("scripts/commands/combat/" + command.getCommandName() + ".py")) { + core.scriptService.callScript("scripts/commands/combat/", command.getCommandName(), "setup", core, attacker, target, command); + } + + boolean success = true; + + //if((command.getHitType() == 5 || command.getHitType() == 7) && !(target instanceof CreatureObject)) + // success = false; + + if(!(command.getAttackType() == 2) && !(command.getHitType() == 5) && !(command.getHitType() == 0)) { + if(target == null || !(target instanceof TangibleObject) || target == attacker) + success = false; + } else { + if(target == null) + target = attacker; + else if(!(target instanceof TangibleObject)) + return; + } + + if(target instanceof CreatureObject) { + if(!(command.getHitType() == 5)) + if(((CreatureObject) target).getPosture() == 13) + success = false; + if(!(command.getHitType() == 7)) + if(((CreatureObject) target).getPosture() == 14) + success = false; + } + + if(command.getHitType() == 7 && target.getClient() == null) + success = false; + + WeaponObject weapon; + + + weapon = (WeaponObject) core.objectService.getObject((long)attacker.getAttachment("TurretWeapon")); + + if(weapon == null) + return; + + float maxRange = 0; + + if(command.getMaxRange() == 0) + maxRange = weapon.getMaxRange(); + else + maxRange = command.getMaxRange(); + + Point3D attackerPos = attacker.getWorldPosition(); + Point3D defenderPos = attacker.getWorldPosition(); + + if(attackerPos.getDistance(defenderPos) > maxRange && maxRange != 0) + success = false; + + if(command.getMinRange() > 0) { + if(attackerPos.getDistance(defenderPos) < command.getMinRange()) + success = false; + } + + + if(target != attacker && success && !core.simulationService.checkLineOfSight(attacker, target)) { + attacker.showFlyText("@combat_effects:cant_see", 1.5f, new RGB(72, 209, 204), 1, true); + success = false; + } + + if(!success && attacker.getClient() != null) { + IoSession session = attacker.getClient().getSession(); + CommandEnqueueRemove commandRemove = new CommandEnqueueRemove(attacker.getObjectId(), actionCounter); + session.write(new ObjControllerMessage(0x0B, commandRemove).serialize()); + StartTask startTask = new StartTask(actionCounter, attacker.getObjectID(), command.getCommandCRC(), CRC.StringtoCRC(command.getCooldownGroup()), -1); + session.write(new ObjControllerMessage(0x0B, startTask).serialize()); + } else { + +// if(command.getHitType() == 5) { +// core.combatService.doHeal(attacker, (CreatureObject) target, weapon, command, actionCounter); +// return; +// } +// +// if(command.getHitType() == 7) { +// core.combatService.doRevive(attacker, (CreatureObject) target, weapon, command, actionCounter); +// return; +// } +// +// if(command.getHitType() == 0 && command.getBuffNameSelf() != null && command.getBuffNameSelf().length() > 0) { +// core.combatService.doSelfBuff(attacker, weapon, command, actionCounter); +// return; +// } + for(int i = 0 ; i < command.getAttack_rolls(); i++) { + core.combatService.doCombatForInstallation(attacker, (TangibleObject) target, weapon, command, actionCounter); + } + + } + + } + public void removeCommand(CreatureObject actor, int actionCounter, BaseSWGCommand command) { if (actor == null || actor.getClient() == null || command == null) { return; diff --git a/src/services/gcw/GCWPylon.java b/src/services/gcw/GCWPylon.java new file mode 100644 index 00000000..c2de51de --- /dev/null +++ b/src/services/gcw/GCWPylon.java @@ -0,0 +1,403 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package services.gcw; + +import java.util.Random; +import java.util.Vector; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import engine.resources.scene.Planet; +import engine.resources.scene.Point3D; +import engine.resources.scene.Quaternion; +import main.NGECore; +import resources.datatables.Factions; +import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; + +/** + * @author Charon + */ + +public class GCWPylon extends TangibleObject{ + + private static final long serialVersionUID = 1L; + private int pylonType = 0; + private int pylonFaction = 0; + private int spawnLevel = 0; + private int totalSpawnedUnits = 0; + private String[] soldierTemplates = new String[]{""}; + private String[] rebelSoldierTemplates1 = new String[]{""}; + private String[] rebelSoldierTemplates2 = new String[]{""}; + private String[] rebelSoldierTemplates3 = new String[]{""}; + private String[] imperialSoldierTemplates1 = new String[]{""}; + private String[] imperialSoldierTemplates2 = new String[]{""}; + private String[] imperialSoldierTemplates3 = new String[]{"elite_imperial_stormtrooper_90"}; + + private String[] vehicleTemplates = new String[]{""}; + private String[] rebelVehicleTemplates1 = new String[]{"rebel_invasion_at_xt"}; + private String[] rebelVehicleTemplates2 = new String[]{"rebel_invasion_at_xt"}; + private String[] rebelVehicleTemplates3 = new String[]{"rebel_invasion_at_xt"}; + private String[] imperialVehicleTemplates1 = new String[]{"imp_invasion_at_st"}; + private String[] imperialVehicleTemplates2 = new String[]{"imp_invasion_at_st"}; + private String[] imperialVehicleTemplates3 = new String[]{"imp_invasion_at_st"}; + + private String[] siegeVehicleTemplates = new String[]{""}; + private String[] rebelSiegeVehicleTemplates1 = new String[]{"rebel_invasion_hailfire_droid"}; + private String[] rebelSiegeVehicleTemplates2 = new String[]{"rebel_invasion_hailfire_droid"}; + private String[] rebelSiegeVehicleTemplates3 = new String[]{"rebel_invasion_hailfire_droid"}; + private String[] imperialSiegeVehicleTemplates1 = new String[]{"imp_invasion_at_at"}; + private String[] imperialSiegeVehicleTemplates2 = new String[]{"imp_invasion_at_at"}; + private String[] imperialSiegeVehicleTemplates3 = new String[]{"imp_invasion_at_at"}; + + private String barricadeTemplate = ""; + private String rebelBarricadeTemplate = "object/tangible/destructible/shared_gcw_rebel_barricade.iff"; + private String imperialBarricadeTemplate = "object/tangible/destructible/shared_gcw_imperial_barricade.iff"; + + + private String turretTemplates = ""; + private String[] rebelTurretTemplates1 = new String[]{""}; + private String[] rebelTurretTemplates2 = new String[]{""}; + private String[] rebelTurretTemplates3 = new String[]{"object/tangible/destructible/shared_gcw_rebel_turret.iff"}; + private String[] imperialTurretTemplates1 = new String[]{""}; + private String[] imperialTurretTemplates2 = new String[]{""}; + private String[] imperialTurretTemplates3 = new String[]{"object/tangible/destructible/shared_gcw_imperial_turret.iff"}; + + private String towerTemplate = ""; + private String rebelTowerTemplate = "object/tangible/destructible/shared_gcw_rebel_tower.iff"; + private String imperialTowerTemplate = "object/tangible/destructible/shared_gcw_imperial_tower.iff"; + + private Vector patrolRoute = new Vector(); + + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + + public GCWPylon() { + super(); + } + + public GCWPylon(long objectID, Planet planet, Point3D position, Quaternion orientation, String template){ + super(objectID, planet, position, orientation, template); + } + + public int getPylonType() { + return pylonType; + } + + public void setPylonType(int pylonType) { + this.pylonType = pylonType; + + if (pylonType==PylonType.SoldierPatrol){ + scheduler.scheduleAtFixedRate(new Runnable() { + @Override public void run() { + try { + spawnSoldier(); + } catch (Exception e) { + System.err.println("Exception in SoldierPatrolPylon->scheduleAtFixedRate->spawnSoldier() " + e.getMessage()); + } + } + }, 5, 30, TimeUnit.SECONDS); + } + + if (pylonType==PylonType.VehiclePatrol){ + scheduler.scheduleAtFixedRate(new Runnable() { + @Override public void run() { + try { + spawnVehicle(); + } catch (Exception e) { + System.err.println("Exception in SoldierPatrolPylon->scheduleAtFixedRate->spawnVehicle() " + e.getMessage()); + } + } + }, 5, 80, TimeUnit.SECONDS); + } + + } + + public int getPylonFaction() { + return pylonFaction; + } + + public void setPylonFaction(int pylonFaction) { + this.pylonFaction = pylonFaction; + } + + public int getSpawnLevel() { + return spawnLevel; + } + + public void setSpawnLevel(int spawnLevel) { + this.spawnLevel = spawnLevel; + } + + public void spawnSoldier(){ + + if (NGECore.getInstance().invasionService.getInvasionPhase()==2){ + if (pylonFaction==Factions.Rebel){ + switch (spawnLevel) { + case 1: soldierTemplates = rebelSoldierTemplates1; + case 2: soldierTemplates = rebelSoldierTemplates2; + case 3: soldierTemplates = rebelSoldierTemplates3; + } + } + if (pylonFaction==Factions.Imperial){ + switch (spawnLevel) { + case 1: soldierTemplates = imperialSoldierTemplates1; + case 2: soldierTemplates = imperialSoldierTemplates2; + case 3: soldierTemplates = imperialSoldierTemplates3; + } + } + String soldierTemplate = soldierTemplates[new Random().nextInt(soldierTemplates.length)]; + CreatureObject soldier = (CreatureObject)NGECore.getInstance().spawnService.spawnCreature(soldierTemplate, this.getPlanet().getName(), 0L, this.getPosition().x, this.getPosition().y, this.getPosition().z, this.getOrientation().w, this.getOrientation().x, this.getOrientation().y,this.getOrientation().z,-1); + + NGECore.getInstance().aiService.setPatrol(soldier, patrolRoute); + NGECore.getInstance().aiService.setPatrolLoop(soldier,false); + totalSpawnedUnits++; + } + } + + public void spawnVehicle(){ + + if (NGECore.getInstance().invasionService.getInvasionPhase()==2){ + if (pylonFaction==Factions.Rebel){ + switch (spawnLevel) { + case 1: vehicleTemplates = rebelVehicleTemplates1; + case 2: vehicleTemplates = rebelVehicleTemplates2; + case 3: vehicleTemplates = rebelVehicleTemplates3; + } + } + if (pylonFaction==Factions.Imperial){ + switch (spawnLevel) { + case 1: vehicleTemplates = imperialVehicleTemplates1; + case 2: vehicleTemplates = imperialVehicleTemplates2; + case 3: vehicleTemplates = imperialVehicleTemplates3; + } + } + String vehicleTemplate = vehicleTemplates[new Random().nextInt(vehicleTemplates.length)]; + CreatureObject vehicle = (CreatureObject)NGECore.getInstance().spawnService.spawnCreature(vehicleTemplate, this.getPlanet().getName(), 0L, this.getPosition().x, this.getPosition().y, this.getPosition().z, this.getOrientation().w, this.getOrientation().x, this.getOrientation().y,this.getOrientation().z,-1); + + NGECore.getInstance().aiService.setPatrol(vehicle, get_Dearic_Route_1()); + NGECore.getInstance().aiService.setPatrolLoop(vehicle,false); + totalSpawnedUnits++; + } + } + + public void setPatrolRoute(int route){ + switch(route){ + case PatrolRoute.Dearic1: patrolRoute = get_Dearic_Route_1(); + break; + case PatrolRoute.Dearic2: patrolRoute = get_Dearic_Route_2(); + break; + case PatrolRoute.Dearic3: patrolRoute = get_Dearic_Route_3(); + break; + case PatrolRoute.Dearic4: patrolRoute = get_Dearic_Route_4(); + break; + case PatrolRoute.Dearic5: patrolRoute = get_Dearic_Route_5(); + break; + case PatrolRoute.Dearic6: patrolRoute = get_Dearic_Route_6(); + break; + case PatrolRoute.Dearic7: patrolRoute = get_Dearic_Route_7(); + break; + case PatrolRoute.Dearic8: patrolRoute = get_Dearic_Route_8(); + break; + case PatrolRoute.Dearic9: patrolRoute = get_Dearic_Route_9(); + break; + case PatrolRoute.Dearic10: patrolRoute = get_Dearic_Route_10(); + break; + } + } + + public Vector get_Dearic_Route_1(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(68.0F, 6.00F, -2959F)); + patrolpoints.add(new Point3D(151.93F,6.00F, -2961.66F)); + patrolpoints.add(new Point3D(170.18F, 6.00F, -2992.99F)); + patrolpoints.add(new Point3D(262.76F, 6.00F, -2999.76F)); + patrolpoints.add(new Point3D(275.87F, 6.00F, -3008.44F)); + patrolpoints.add(new Point3D(303.41F, 6.00F, -3005.19F)); + patrolpoints.add(new Point3D(343.31F, 6.00F, -2961.06F)); + patrolpoints.add(new Point3D(379.98F, 6.00F, -2963.31F)); + patrolpoints.add(new Point3D(404.70F, 6.00F, -2980.57F)); + patrolpoints.add(new Point3D(412.54F, 6.00F, -3039.39F)); + patrolpoints.add(new Point3D(423.06F, 6.00F, -3050.75F)); + patrolpoints.add(new Point3D(446.92F, 6.00F, -3046.32F)); + patrolpoints.add(new Point3D(470.48F, 6.00F, -3023.43F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_2(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(76.0F, 6.00F, -2893F)); + patrolpoints.add(new Point3D(153.0F, 6.00F, -2898F)); + patrolpoints.add(new Point3D(162.89F, 6.00F, -2836.9F)); + patrolpoints.add(new Point3D(291.44F, 6.00F, -2844.6F)); + patrolpoints.add(new Point3D(333.19F, 6.00F, -2878.0F)); + patrolpoints.add(new Point3D(337.00F, 6.00F, -2954.0F)); + patrolpoints.add(new Point3D(378.00F, 6.00F, -2959.0F)); + patrolpoints.add(new Point3D(407.00F, 6.00F, -2978.0F)); + patrolpoints.add(new Point3D(414.00F, 6.00F, -3041.0F)); + patrolpoints.add(new Point3D(448.00F, 6.00F, -3043.0F)); + patrolpoints.add(new Point3D(463.00F, 6.00F, -3017.0F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_3(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(199.0F, 6.00F, -2790F)); + patrolpoints.add(new Point3D(200.0F, 6.00F, -2838F)); + patrolpoints.add(new Point3D(294.0F, 6.00F, -2841F)); + patrolpoints.add(new Point3D(335.0F, 6.00F, -2882F)); + patrolpoints.add(new Point3D(341.0F, 6.00F, -2950F)); + patrolpoints.add(new Point3D(378.0F, 6.00F, -2958F)); + patrolpoints.add(new Point3D(405.0F, 6.00F, -2981F)); + patrolpoints.add(new Point3D(473.0F, 6.00F, -3024F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_4(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(332.0F, 6.00F, -2715F)); + patrolpoints.add(new Point3D(324.0F, 6.00F, -2817F)); + patrolpoints.add(new Point3D(302.0F, 6.00F, -2835F)); + patrolpoints.add(new Point3D(338.0F, 6.00F, -2888F)); + patrolpoints.add(new Point3D(342.0F, 6.00F, -2949F)); + patrolpoints.add(new Point3D(407.0F, 6.00F, -2972F)); + patrolpoints.add(new Point3D(415.0F, 6.00F, -3055F)); + patrolpoints.add(new Point3D(451.0F, 6.00F, -3044F)); + patrolpoints.add(new Point3D(460.0F, 6.00F, -3011F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_5(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(384.0F, 6.00F, -2720F)); + patrolpoints.add(new Point3D(404.0F, 6.00F, -2817F)); + patrolpoints.add(new Point3D(417.0F, 6.00F, -2827F)); + patrolpoints.add(new Point3D(414.0F, 6.00F, -2854F)); + patrolpoints.add(new Point3D(384.0F, 6.00F, -2888F)); + patrolpoints.add(new Point3D(384.0F, 6.00F, -2959F)); + patrolpoints.add(new Point3D(407.0F, 6.00F, -2975F)); + patrolpoints.add(new Point3D(416.0F, 6.00F, -3049F)); + patrolpoints.add(new Point3D(450.0F, 6.00F, -3043F)); + patrolpoints.add(new Point3D(474.0F, 6.00F, -3025F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_6(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(590.0F, 6.00F, -2825F)); + patrolpoints.add(new Point3D(567.0F, 6.00F, -2860F)); + patrolpoints.add(new Point3D(563.0F, 6.00F, -2943F)); + patrolpoints.add(new Point3D(563.0F, 6.00F, -2943F)); + patrolpoints.add(new Point3D(507.0F, 6.00F, -2955F)); + patrolpoints.add(new Point3D(500.0F, 6.00F, -3011F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_7(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(723.0F, 6.00F, -2995F)); + patrolpoints.add(new Point3D(720.0F, 6.00F, -2964F)); + patrolpoints.add(new Point3D(623.0F, 6.00F, -2961F)); + patrolpoints.add(new Point3D(614.0F, 6.00F, -3010F)); + patrolpoints.add(new Point3D(510.0F, 6.00F, -3032F)); + patrolpoints.add(new Point3D(484.0F, 6.00F, -3021F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_8(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(733.0F, 6.00F, -3004F)); + patrolpoints.add(new Point3D(701.0F, 6.00F, -3004F)); + patrolpoints.add(new Point3D(699.0F, 6.00F, -3039F)); + patrolpoints.add(new Point3D(627.0F, 6.00F, -3041F)); + patrolpoints.add(new Point3D(605.0F, 6.00F, -3018F)); + patrolpoints.add(new Point3D(509.0F, 6.00F, -3033F)); + patrolpoints.add(new Point3D(496.0F, 6.00F, -3018F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_9(){ + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(330.0F, 23.00F, -3402F)); + patrolpoints.add(new Point3D(360.0F, 6.00F, -3357F)); + patrolpoints.add(new Point3D(415.0F, 6.00F, -3273F)); + patrolpoints.add(new Point3D(464.0F, 6.00F, -3256F)); + patrolpoints.add(new Point3D(467.0F, 6.00F, -3236F)); + patrolpoints.add(new Point3D(498.0F, 6.00F, -3230F)); + patrolpoints.add(new Point3D(501.0F, 6.00F, -3205F)); + patrolpoints.add(new Point3D(481.0F, 6.00F, -3174F)); + patrolpoints.add(new Point3D(482.0F, 6.00F, -3126F)); + patrolpoints.add(new Point3D(437.0F, 6.00F, -3065F)); + patrolpoints.add(new Point3D(465.0F, 6.00F, -3019F)); + return patrolpoints; + } + + public Vector get_Dearic_Route_10(){// just for tests + Vector patrolpoints = new Vector(); + patrolpoints.add(new Point3D(620.0F, 6.00F, -3009F)); + patrolpoints.add(new Point3D(565.0F, 6.00F, -3025F)); + patrolpoints.add(new Point3D(535.0F, 6.00F, -3023F)); + + return patrolpoints; + } + + public class PylonType { + + public static final int SoldierPatrol = 0; + public static final int VehiclePatrol = 1; + public static final int SiegeVehiclePatrol = 2; + public static final int Barricade = 3; + public static final int Turret = 4; + public static final int Tower = 5; + + } + /* + Soldier Patrol Pylons - Spawns a continuous stream of NPCs to aid in the battle - shown with a Helmet icon. + Vehicle Patrol Pylons - Spawns vehicles that are considerably more lethal than the Soldiers - shown with a Terminal icon. + Siege Vehicle Patrol Pylon - Spawns Rebel Hailfire Driods or Imperial AT-ATs (only spawn at a Level 3 Pylon) - shown with the same Terminal icon. + Barricade Pylon - Spawns a barricade that defends units behind it by giving them a defensive buff - shown with a Barricade icon. + Turret Pylon - Spawns an AI controlled turret that fires on enemy units - shown with a Gun Barrel or Turret Dish icon. + Tower Pylon - Spawns a watch tower that grants intelligence to nearby NPCs and offers combat missions to players - shown with a Tower icon. + */ + + public class PatrolRoute { + + public static final int Dearic1 = 0; + public static final int Dearic2 = 1; + public static final int Dearic3 = 2; + public static final int Dearic4 = 3; + public static final int Dearic5 = 4; + public static final int Dearic6 = 5; + public static final int Dearic7 = 6; + public static final int Dearic8 = 7; + public static final int Dearic9 = 8; + public static final int Dearic10 = 9; + + } + + public int getTotalSpawnedUnits() { + return totalSpawnedUnits; + } + + public void setTotalSpawnedUnits(int totalSpawnedUnits) { + this.totalSpawnedUnits = totalSpawnedUnits; + } +} diff --git a/src/services/gcw/InvasionService.java b/src/services/gcw/InvasionService.java index f900c7d8..1e4ed6c2 100644 --- a/src/services/gcw/InvasionService.java +++ b/src/services/gcw/InvasionService.java @@ -21,13 +21,30 @@ ******************************************************************************/ package services.gcw; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import protocol.swg.UpdateContainmentMessage; +import resources.datatables.FactionStatus; import resources.datatables.Factions; +import resources.datatables.Options; +import resources.datatables.WeaponType; +import resources.objects.building.BuildingObject; +import resources.objects.creature.CreatureObject; +import resources.objects.installation.InstallationObject; +import resources.objects.tangible.TangibleObject; +import resources.objects.weapon.WeaponObject; +import services.ai.AIActor; +import services.ai.TurretAIActor; +import services.gcw.GCWPylon.PatrolRoute; +import services.gcw.GCWPylon.PylonType; import main.NGECore; +import engine.clients.Client; import engine.resources.common.CRC; +import engine.resources.objects.SWGObject; import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; import engine.resources.service.INetworkDispatch; @@ -43,36 +60,225 @@ public class InvasionService implements INetworkDispatch { private long bestineInvasionStartTime = 2; private long dearicInvasionStartTime = 3; + private CreatureObject invasionGeneral = null; + private int invasionLocation=InvasionLocation.Dearic; + private int invadingFaction=Factions.Imperial; + private int defendingFaction=Factions.Rebel; private int invasionPhase=2; // Test phase 2 public InvasionService(final NGECore core) { - this.core = core; - - + this.core = core; + } + + + public void spawnOffensiveAssets(){ + spawnOffensiveCamps(); + } + + public void spawnDefensiveAssets(){ + spawnGeneral(); + spawnDefensiveQuestOfficer(); + spawnBarricades(); + spawnTurrets(); } public void testPylons(){ + Quaternion quaternion = new Quaternion(0.28F,0F,0.95F,0F); - SoldierPatrolPylon pylon1 = (SoldierPatrolPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(-48, 4, -2798), quaternion); - pylon1.setPylonFaction(Factions.Imperial); + + + /* + GCWPylon pylon1 = (GCWPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(-48, 6, -2798), quaternion); + core.simulationService.add(pylon1, pylon1.getPosition().x, pylon1.getPosition().z, true); + pylon1.setPatrolRoute(PatrolRoute.Dearic1); + pylon1.setPylonType(PylonType.SoldierPatrol); + pylon1.setPylonFaction(invadingFaction); pylon1.setSpawnLevel(3); + + GCWPylon pylon2 = (GCWPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(-51, 6, -2798), quaternion); + core.simulationService.add(pylon2, pylon2.getPosition().x, pylon2.getPosition().z, true); + pylon2.setPatrolRoute(PatrolRoute.Dearic1); + pylon2.setPylonType(PylonType.VehiclePatrol); + pylon2.setPylonFaction(invadingFaction); + pylon2.setSpawnLevel(3); + +// GCWPylon pylon4 = (GCWPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(506, 6, -3025), quaternion); +// core.simulationService.add(pylon4, pylon4.getPosition().x, pylon4.getPosition().z, true); +// pylon4.setPylonType(PylonType.SoldierPatrol); +// pylon4.setPylonFaction(invadingFaction); +// pylon4.setSpawnLevel(3); + + GCWPylon pylon3 = (GCWPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(5, 6, -2683), quaternion); + core.simulationService.add(pylon3, pylon3.getPosition().x, pylon3.getPosition().z, true); + pylon3.setPatrolRoute(PatrolRoute.Dearic2); + pylon3.setPylonType(PylonType.SoldierPatrol); + pylon3.setPylonFaction(invadingFaction); + pylon3.setSpawnLevel(3); + + + GCWPylon pylon4 = (GCWPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(141, 6, -2517), quaternion); + core.simulationService.add(pylon4, pylon4.getPosition().x, pylon4.getPosition().z, true); + pylon4.setPatrolRoute(PatrolRoute.Dearic3); + pylon4.setPylonType(PylonType.SoldierPatrol); + pylon4.setPylonFaction(invadingFaction); + pylon4.setSpawnLevel(3); + + GCWPylon pylon5 = (GCWPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(275, 6, -2481), quaternion); + core.simulationService.add(pylon5, pylon5.getPosition().x, pylon5.getPosition().z, true); + pylon5.setPatrolRoute(PatrolRoute.Dearic4); + pylon5.setPylonType(PylonType.SoldierPatrol); + pylon5.setPylonFaction(invadingFaction); + pylon5.setSpawnLevel(3); + + GCWPylon pylon6 = (GCWPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(519, 6, -2452), quaternion); + core.simulationService.add(pylon6, pylon6.getPosition().x, pylon6.getPosition().z, true); + pylon6.setPatrolRoute(PatrolRoute.Dearic5); + pylon6.setPylonType(PylonType.SoldierPatrol); + pylon6.setPylonFaction(invadingFaction); + pylon6.setSpawnLevel(3); + + GCWPylon pylon7 = (GCWPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(845, 6, -2550), quaternion); + core.simulationService.add(pylon7, pylon7.getPosition().x, pylon7.getPosition().z, true); + pylon7.setPatrolRoute(PatrolRoute.Dearic6); + pylon7.setPylonType(PylonType.SoldierPatrol); + pylon7.setPylonFaction(invadingFaction); + pylon7.setSpawnLevel(3); + + GCWPylon pylon8 = (GCWPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(1082, 6, -2855), quaternion); + core.simulationService.add(pylon8, pylon8.getPosition().x, pylon8.getPosition().z, true); + pylon8.setPatrolRoute(PatrolRoute.Dearic7); + pylon8.setPylonType(PylonType.SoldierPatrol); + pylon8.setPylonFaction(invadingFaction); + pylon8.setSpawnLevel(3); + + GCWPylon pylon9 = (GCWPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(946, 6, -3075), quaternion); + core.simulationService.add(pylon9, pylon9.getPosition().x, pylon9.getPosition().z, true); + pylon9.setPatrolRoute(PatrolRoute.Dearic8); + pylon9.setPylonType(PylonType.SoldierPatrol); + pylon9.setPylonFaction(invadingFaction); + pylon9.setSpawnLevel(3); + + GCWPylon pylon10 = (GCWPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(314, 43, -3546), quaternion); + core.simulationService.add(pylon10, pylon10.getPosition().x, pylon10.getPosition().z, true); + pylon10.setPatrolRoute(PatrolRoute.Dearic9); + pylon10.setPylonType(PylonType.SoldierPatrol); + pylon10.setPylonFaction(invadingFaction); + pylon10.setSpawnLevel(3); + */ + + + // to test turret + GCWPylon pylon10a = (GCWPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(621, 4, -2996), quaternion); + core.simulationService.add(pylon10a, pylon10a.getPosition().x, pylon10a.getPosition().z, true); + pylon10a.setPatrolRoute(PatrolRoute.Dearic10); + pylon10a.setPylonType(PylonType.SoldierPatrol); + pylon10a.setPylonFaction(invadingFaction); + pylon10a.setSpawnLevel(3); + + + + spawnDefensiveAssets(); + spawnOffensiveAssets(); } public void spawnGeneral(){ - Quaternion quaternion = new Quaternion(0.28F,0F,0.95F,0F); - SoldierPatrolPylon pylon1 = (SoldierPatrolPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(-48, 4, -2798), quaternion); + System.out.println("Spawn general"); + String generalTemplate = ""; + if (invadingFaction==Factions.Imperial){ + generalTemplate = "rebel_invasion_general"; + } + if (invadingFaction==Factions.Rebel){ + generalTemplate = "imp_invasion_general"; + } + + if (invasionLocation==InvasionLocation.Keren){ + invasionGeneral = (CreatureObject) NGECore.getInstance().staticService.spawnObject(generalTemplate, "naboo", 0L, 1786, 6, 2511, 1, 0); + } + if (invasionLocation==InvasionLocation.Bestine){ + invasionGeneral = (CreatureObject) NGECore.getInstance().staticService.spawnObject(generalTemplate, "tatooine", 0L, -1214, 6, -3626, 1, 0); + } + if (invasionLocation==InvasionLocation.Dearic){ + invasionGeneral = (CreatureObject) NGECore.getInstance().staticService.spawnObject(generalTemplate, "talus", 0L, 480.071F, 6, -3006.851F, 1, 0); + } + } public void spawnDefensiveQuestOfficer(){ - Quaternion quaternion = new Quaternion(0.28F,0F,0.95F,0F); - SoldierPatrolPylon pylon1 = (SoldierPatrolPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(-48, 4, -2798), quaternion); + System.out.println("spawnDefensiveQuestOfficer"); + String questOfficerTemplate = ""; + if (invadingFaction==Factions.Imperial){ + questOfficerTemplate = "rebel_defensive_quest_officer"; + } + if (invadingFaction==Factions.Rebel){ + questOfficerTemplate = "imp_defensive_quest_officer"; + } + + if (invasionLocation==InvasionLocation.Keren){ + invasionGeneral = (CreatureObject) NGECore.getInstance().staticService.spawnObject(questOfficerTemplate, "naboo", 0L, 1787, 6, 2512, 1, 0); + } + if (invasionLocation==InvasionLocation.Bestine){ + invasionGeneral = (CreatureObject) NGECore.getInstance().staticService.spawnObject(questOfficerTemplate, "tatooine", 0L, -1195, 6, -3620, 1, 0); + } + if (invasionLocation==InvasionLocation.Dearic){ + invasionGeneral = (CreatureObject) NGECore.getInstance().staticService.spawnObject(questOfficerTemplate, "talus", 0L, 478, 6, -3023, 0, 1); + } } public void spawnOffensiveCamps(){ +// Quaternion quaternion = new Quaternion(0.28F,0F,0.95F,0F); +// String campTemplate = "object/building/military/shared_gcw_battlefield_base.iff"; +// //String campTemplate = "object/building/poi/shared_gcw_rebel_clone_tent_small.iff"; // LOL why doesn't this spawn?!?!?! +// BuildingObject camp = (BuildingObject) core.objectService.createObject(campTemplate, 0, core.terrainService.getPlanetByName("talus"), new Point3D(-890,9, -2994), quaternion); +// core.simulationService.add(camp, camp.getPosition().x, camp.getPosition().z, true); + } + + public void spawnBarricades(){ Quaternion quaternion = new Quaternion(0.28F,0F,0.95F,0F); - SoldierPatrolPylon pylon1 = (SoldierPatrolPylon) core.objectService.createObject("object/tangible/destructible/shared_gcw_city_construction_beacon.iff", 0, core.terrainService.getPlanetByName("talus"), new Point3D(-48, 4, -2798), quaternion); + String campTemplate = "object/tangible/destructible/shared_gcw_rebel_barricade.iff"; + //String campTemplate = "object/building/poi/shared_gcw_rebel_clone_tent_small.iff"; // LOL why doesn't this spawn?!?!?! + TangibleObject barricade = (TangibleObject) core.objectService.createObject(campTemplate, 0, core.terrainService.getPlanetByName("talus"), new Point3D( 475, 6, -3013), quaternion); + core.simulationService.add(barricade, barricade.getPosition().x, barricade.getPosition().z, true); + barricade.setCustomName("Rebel Barricade"); + //barricade.setOptions(Options.ATTACKABLE, true); + barricade.setOptionsBitmask(Options.ATTACKABLE | Options.QUEST); + barricade.setFaction("rebel"); + barricade.setFactionStatus(FactionStatus.Combatant); + barricade.setMaximumCondition(50000); + + } + + public void spawnTurrets(){ + Quaternion quaternion = new Quaternion(0.28F,0F,0.95F,0F); + String turretTemplate = "object/installation/turret/gcw/shared_adv_turret_dish_sm_heat.iff"; + //String turretTemplate = "object/tangible/destructible/shared_gcw_rebel_turret.iff"; + InstallationObject turret = (InstallationObject) core.objectService.createObject(turretTemplate, 0, core.terrainService.getPlanetByName("talus"), new Point3D( 557, 6, -3028), quaternion); + core.simulationService.add(turret, turret.getPosition().x, turret.getPosition().z, true); + turret.setCustomName("Rebel Turret"); + turret.setOptionsBitmask(Options.ATTACKABLE | Options.QUEST); + turret.setFaction("rebel"); + turret.setFactionStatus(FactionStatus.Combatant); + turret.setMaximumCondition(50000); + TurretAIActor actor = new TurretAIActor(turret, turret.getPosition(), scheduler); + turret.setAttachment("AI", actor); + turret.setFaction("rebel"); + + // const static int TURRET = 0x1004; + WeaponObject defaultWeapon = (WeaponObject) core.objectService.createObject("object/weapon/ranged/turret/shared_turret_heat.iff", turret.getPlanet()); + defaultWeapon.setAttackSpeed(1.0F); + defaultWeapon.setWeaponType(WeaponType.RIFLE); + defaultWeapon.setMaxRange(14.0F); // defaultWeapon.setMaxRange(60.0F); + defaultWeapon.setDamageType("energy"); + defaultWeapon.setMinDamage(2000); + defaultWeapon.setMaxDamage(2400); + turret.add(defaultWeapon); + turret.setAttachment("TurretWeapon",defaultWeapon.getObjectID()); + Set newObservers = new HashSet(turret.getObservers()); + for(Client c : newObservers) { + UpdateContainmentMessage ucm = new UpdateContainmentMessage(defaultWeapon.getObjectID(), turret.getObjectID(), 4); + c.getSession().write(ucm.serialize()); + } } @Override diff --git a/src/services/gcw/SoldierPatrolPylon.java b/src/services/gcw/SoldierPatrolPylon.java deleted file mode 100644 index 41003473..00000000 --- a/src/services/gcw/SoldierPatrolPylon.java +++ /dev/null @@ -1,177 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2013 - * - * This File is part of NGECore2. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - * - * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. - * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. - ******************************************************************************/ -package services.gcw; - -import java.util.Random; -import java.util.Vector; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import engine.resources.scene.Planet; -import engine.resources.scene.Point3D; -import engine.resources.scene.Quaternion; -import main.NGECore; -import resources.datatables.Factions; -import resources.objects.creature.CreatureObject; -import resources.objects.tangible.TangibleObject; - -/** - * @author Charon - */ - -public class SoldierPatrolPylon extends TangibleObject{ - - private static final long serialVersionUID = 1L; - private int pylonFaction = 0; - private int spawnLevel = 0; - private int totalSpawnedSoldiers = 0; - private String[] soldierTemplates = new String[]{""}; - private String[] rebelTemplates1 = new String[]{""}; - private String[] rebelTemplates2 = new String[]{""}; - private String[] rebelTemplates3 = new String[]{""}; - private String[] imperialTemplates1 = new String[]{""}; - private String[] imperialTemplates2 = new String[]{""}; - private String[] imperialTemplates3 = new String[]{"elite_imperial_stormtrooper_90"}; - private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); - - public SoldierPatrolPylon() { - super(); - } - - public SoldierPatrolPylon(long objectID, Planet planet, Point3D position, Quaternion orientation, String template){ - super(objectID, planet, position, orientation, template); - - scheduler.scheduleAtFixedRate(new Runnable() { - @Override public void run() { - try { - spawnSoldier(); - } catch (Exception e) { - System.err.println("Exception in SoldierPatrolPylon->scheduleAtFixedRate->spawnSoldier() " + e.getMessage()); - } - } - }, 5, 20, TimeUnit.SECONDS); - - } - - public int getPylonFaction() { - return pylonFaction; - } - - public void setPylonFaction(int pylonFaction) { - this.pylonFaction = pylonFaction; - } - - public int getSpawnLevel() { - return spawnLevel; - } - - public void setSpawnLevel(int spawnLevel) { - this.spawnLevel = spawnLevel; - } - - public void spawnSoldier(){ - - if (NGECore.getInstance().invasionService.getInvasionPhase()==2){ - if (pylonFaction==Factions.Rebel){ - switch (spawnLevel) { - case 1: soldierTemplates = rebelTemplates1; - case 2: soldierTemplates = rebelTemplates2; - case 3: soldierTemplates = rebelTemplates3; - } - } - if (pylonFaction==Factions.Imperial){ - switch (spawnLevel) { - case 1: soldierTemplates = imperialTemplates1; - case 2: soldierTemplates = imperialTemplates2; - case 3: soldierTemplates = imperialTemplates3; - } - } - String soldierTemplate = soldierTemplates[new Random().nextInt(soldierTemplates.length)]; - CreatureObject soldier = (CreatureObject)NGECore.getInstance().spawnService.spawnCreature(soldierTemplate, this.getPlanet().getName(), 0L, this.getPosition().x, this.getPosition().y, this.getPosition().z, this.getOrientation().w, this.getOrientation().x, this.getOrientation().y,this.getOrientation().z,-1); - - NGECore.getInstance().aiService.setPatrol(soldier, get_Dearic_Route_1()); - NGECore.getInstance().aiService.setPatrolLoop(soldier,false); - totalSpawnedSoldiers++; - } - } - - public Vector get_Dearic_Route_1(){ - Vector patrolpoints = new Vector(); - patrolpoints.add(new Point3D(68.0F, 6.00F, -2959F)); - patrolpoints.add(new Point3D(151.93F,6.00F, -2961.66F)); - patrolpoints.add(new Point3D(170.18F, 6.00F, -2992.99F)); - patrolpoints.add(new Point3D(262.76F, 6.00F, -2999.76F)); - patrolpoints.add(new Point3D(275.87F, 6.00F, -3008.44F)); - patrolpoints.add(new Point3D(303.41F, 6.00F, -3005.19F)); - patrolpoints.add(new Point3D(343.31F, 6.00F, -2961.06F)); - patrolpoints.add(new Point3D(379.98F, 6.00F, -2963.31F)); - patrolpoints.add(new Point3D(404.70F, 6.00F, -2980.57F)); - patrolpoints.add(new Point3D(412.54F, 6.00F, -3039.39F)); - patrolpoints.add(new Point3D(423.06F, 6.00F, -3050.75F)); - patrolpoints.add(new Point3D(446.92F, 6.00F, -3046.32F)); - patrolpoints.add(new Point3D(470.48F, 6.00F, -3023.43F)); - return patrolpoints; - } - - public Vector get_Dearic_Route_2(){ - Vector patrolpoints = new Vector(); - return patrolpoints; - } - - public Vector get_Dearic_Route_3(){ - Vector patrolpoints = new Vector(); - return patrolpoints; - } - - public Vector get_Dearic_Route_4(){ - Vector patrolpoints = new Vector(); - return patrolpoints; - } - - public Vector get_Dearic_Route_5(){ - Vector patrolpoints = new Vector(); - return patrolpoints; - } - - public Vector get_Dearic_Route_6(){ - Vector patrolpoints = new Vector(); - return patrolpoints; - } - - public Vector get_Dearic_Route_7(){ - Vector patrolpoints = new Vector(); - return patrolpoints; - } - - public Vector get_Dearic_Route_8(){ - Vector patrolpoints = new Vector(); - return patrolpoints; - } - - public Vector get_Dearic_Route_9(){ - Vector patrolpoints = new Vector(); - return patrolpoints; - } - - - -} diff --git a/src/services/object/ObjectService.java b/src/services/object/ObjectService.java index ba39e09f..ef4d8fce 100644 --- a/src/services/object/ObjectService.java +++ b/src/services/object/ObjectService.java @@ -130,7 +130,7 @@ import services.command.CombatCommand; import services.bazaar.AuctionItem; import services.chat.ChatRoom; import services.equipment.EquipmentService; -import services.gcw.SoldierPatrolPylon; +import services.gcw.GCWPylon; import services.sui.SUIWindow; import services.sui.SUIWindow.SUICallback; import services.sui.SUIWindow.Trigger; @@ -284,7 +284,17 @@ public class ObjectService implements INetworkDispatch { float positionY = core.terrainService.getHeight(planet.getID(), position.x, position.z)-1f; Point3D newpoint = new Point3D(position.x,positionY,position.z); - object = new SoldierPatrolPylon(objectID, planet, position, orientation, Template); + object = new GCWPylon(objectID, planet, position, orientation, Template); + + } else if(Template.startsWith("object/tangible/destructible/")) { + +// float positionY = core.terrainService.getHeight(planet.getID(), position.x, position.z)-1f; +// Point3D newpoint = new Point3D(position.x,positionY,position.z); +// object = new InstallationObject(objectID, planet, newpoint, orientation, Template); + + object = new TangibleObject(objectID, planet, position, orientation, Template); + + //object = new BuildingObject(objectID, planet, position, orientation, Template); } else if(Template.startsWith("object/tangible")) { @@ -376,6 +386,12 @@ public class ObjectService implements INetworkDispatch { Point3D newpoint = new Point3D(position.x,positionY,position.z); object = new HarvesterObject(objectID, planet, newpoint, orientation, Template); + } else if(Template.startsWith("object/installation/turret")) { + + float positionY = core.terrainService.getHeight(planet.getID(), position.x, position.z); + Point3D newpoint = new Point3D(position.x,positionY,position.z); + object = new InstallationObject(objectID, planet, newpoint, orientation, Template); + } else { return null; } diff --git a/src/services/spawn/MobileTemplate.java b/src/services/spawn/MobileTemplate.java index 7060a877..dd4a2fbf 100644 --- a/src/services/spawn/MobileTemplate.java +++ b/src/services/spawn/MobileTemplate.java @@ -62,6 +62,7 @@ public class MobileTemplate implements Cloneable { private List lootGroups = new ArrayList(); private String PCDTemplate=""; private String conversationFileName=""; + private boolean AIEnabled = true; public Vector getTemplates() { @@ -369,5 +370,13 @@ public class MobileTemplate implements Cloneable { public void setConversationFileName(String conversationFileName) { this.conversationFileName = conversationFileName; } + + public boolean isAIEnabled() { + return AIEnabled; + } + + public void setAIEnabled(boolean aIEnabled) { + AIEnabled = aIEnabled; + } } diff --git a/src/services/spawn/SpawnService.java b/src/services/spawn/SpawnService.java index b4b60c52..38b9d45c 100644 --- a/src/services/spawn/SpawnService.java +++ b/src/services/spawn/SpawnService.java @@ -208,13 +208,15 @@ public class SpawnService { armor = 6000; core.skillModService.addSkillMod(creature, "expertise_innate_protection_all", armor); } - - AIActor actor = new AIActor(creature, creature.getPosition(), scheduler); - creature.setAttachment("AI", actor); - creature.setAttachment("radial_filename", "npc/mobile"); - actor.setMobileTemplate(mobileTemplate); - + if (mobileTemplate.isAIEnabled()){ + AIActor actor = new AIActor(creature, creature.getPosition(), scheduler); + creature.setAttachment("AI", actor); + actor.setMobileTemplate(mobileTemplate); + } + + creature.setAttachment("radial_filename", "npc/mobile"); + if(cell == null) { core.simulationService.add(creature, x, z, true);