From f58b7b6a5b8f77a0546d1fb5b0961dee00ec48e3 Mon Sep 17 00:00:00 2001 From: Treeku Date: Fri, 18 Apr 2014 19:09:45 +0100 Subject: [PATCH] Overhauled Mounts (still buggy) --- scripts/commands/dismount.py | 16 +- scripts/commands/mount.py | 18 +- .../vehicle/speederbike_swoop_pcd.py | 12 +- .../mobile/vehicle/speederbike_swoop.py | 14 +- .../vehicle_deed/speederbike_swoop_deed.py | 19 +- scripts/radial/creature/vehicle.py | 31 + scripts/radial/datapad/vehicle_pcd.py | 21 + scripts/radial/deeds/vehicleDeed.py | 16 + src/main/NGECore.java | 4 + src/resources/datatables/Posture.java | 34 +- src/resources/datatables/State.java | 69 ++ .../objects/creature/CreatureObject.java | 147 ++-- .../objects/player/PlayerObject.java | 11 + .../objects/tangible/TangibleObject.java | 10 +- src/services/SimulationService.java | 25 +- src/services/combat/CombatService.java | 6 + src/services/object/ObjectService.java | 12 +- src/services/pet/MountService.java | 766 ++++++++++++++++++ 18 files changed, 1058 insertions(+), 173 deletions(-) create mode 100644 scripts/radial/creature/vehicle.py create mode 100644 scripts/radial/datapad/vehicle_pcd.py create mode 100644 scripts/radial/deeds/vehicleDeed.py create mode 100644 src/resources/datatables/State.java create mode 100644 src/services/pet/MountService.java diff --git a/scripts/commands/dismount.py b/scripts/commands/dismount.py index df9f2733..08aeba54 100644 --- a/scripts/commands/dismount.py +++ b/scripts/commands/dismount.py @@ -4,13 +4,15 @@ def setup(): return def run(core, actor, target, commandString): - if actor.canMount(target) is False: return - - if not actor.isMounted(): - actor.setMounted(1) - target.initMount(actor) - else: - target.unmount(actor) + if not target: + return + + if actor.getObjectID() != target.getOwnerId(): + return + + + if core.mountService.isMounted(actor) is True: + core.mountService.dismount(actor, target) return diff --git a/scripts/commands/mount.py b/scripts/commands/mount.py index 14a0f3e4..40b6e080 100644 --- a/scripts/commands/mount.py +++ b/scripts/commands/mount.py @@ -4,13 +4,13 @@ def setup(): return def run(core, actor, target, commandString): - if actor.canMount(target) is False: return - - if not actor.isMounted(): - actor.setMounted(1) - target.initMount(actor) - else: - target.unmount(actor) - + if not target: + return + + if actor.getObjectID() != target.getOwnerId(): + return + + if core.mountService.isMounted(actor) is False: + core.mountService.mount(actor, target) + return - diff --git a/scripts/object/intangible/vehicle/speederbike_swoop_pcd.py b/scripts/object/intangible/vehicle/speederbike_swoop_pcd.py index ace4cdfc..d7c3f4a1 100644 --- a/scripts/object/intangible/vehicle/speederbike_swoop_pcd.py +++ b/scripts/object/intangible/vehicle/speederbike_swoop_pcd.py @@ -1,15 +1,5 @@ import sys def setup(core, object): - object.setAttachment('radial_filename', 'vehicle_pcd') - return - -def use(core, actor, object): - if object and actor.getAttachment('activeVehicleID') == None: - swoop = core.objectService.createObject('object/mobile/vehicle/shared_speederbike_swoop.iff', 0, actor.getPlanet(), actor.getPosition(), actor.getOrientation()) - - swoop.setOwnerId(actor.getObjectID()) - actor.setAttachment('activeVehicleID', swoop.getObjectID()) - - core.simulationService.add(swoop, swoop.getPosition().x, swoop.getPosition().z, True) + object.setAttachment('radial_filename', 'datapad/vehicle_pcd') return \ No newline at end of file diff --git a/scripts/object/mobile/vehicle/speederbike_swoop.py b/scripts/object/mobile/vehicle/speederbike_swoop.py index 4626c764..0f6896cd 100644 --- a/scripts/object/mobile/vehicle/speederbike_swoop.py +++ b/scripts/object/mobile/vehicle/speederbike_swoop.py @@ -1,16 +1,6 @@ import sys def setup(core, object): - object.setAttachment('radial_filename', 'vehicle') - return - -def use(core, actor, object): - vehicle = actor.getContainer() - - if vehicle: - if vehicle.getObjectID() == object.getObjectID(): - vehicle.remove(actor) - else: - vehicle.add(actor) - + object.setAttachment('radial_filename', 'creature/vehicle') + object.setAttachment('passengers', 0) return \ No newline at end of file diff --git a/scripts/object/tangible/deed/vehicle_deed/speederbike_swoop_deed.py b/scripts/object/tangible/deed/vehicle_deed/speederbike_swoop_deed.py index 4b0e320f..48f0518e 100644 --- a/scripts/object/tangible/deed/vehicle_deed/speederbike_swoop_deed.py +++ b/scripts/object/tangible/deed/vehicle_deed/speederbike_swoop_deed.py @@ -1,24 +1,9 @@ import sys def setup(core, object): - object.setAttachment('radial_filename', 'vehicleDeed') + object.setAttachment('radial_filename', 'deeds/vehicleDeed') return def use(core, actor, object): - datapad = actor.getSlottedObject('datapad') - pcd = core.objectService.createObject('object/intangible/vehicle/shared_speederbike_swoop_pcd.iff', actor.getPlanet(), actor.getPosition().x, actor.getPosition().z,actor.getPosition().y) - - if datapad and pcd: - - datapad.add(pcd) - core.objectService.destroyObject(object) - - vehicleId = actor.getAttachment('activeVehicleID') - - if vehicleId == None: - vehicle = core.objectService.createObject('object/mobile/vehicle/shared_speederbike_swoop.iff', actor.getPlanet(), actor.getPosition().x, actor.getPosition().z,actor.getPosition().y) - vehicle.setOwnerId(actor.getObjectID()) - core.simulationService.add(vehicle, vehicle.getPosition().x, vehicle.getPosition().z, True) - actor.setAttachment('activeVehicleID', vehicle.getObjectID()) - + core.mountService.generateVehicle(actor, object, 'object/mobile/vehicle/shared_speederbike_swoop.iff', 'object/intangible/vehicle/shared_speederbike_swoop_pcd.iff') return \ No newline at end of file diff --git a/scripts/radial/creature/vehicle.py b/scripts/radial/creature/vehicle.py new file mode 100644 index 00000000..be1e7319 --- /dev/null +++ b/scripts/radial/creature/vehicle.py @@ -0,0 +1,31 @@ +from resources.common import RadialOptions +import sys + +def createRadial(core, owner, target, radials): + master = core.objectService.getObject(target.getOwnerId()) + + radials.add(RadialOptions(0, 7, 1, '')) + if core.mountService.canMount(owner, target): + radials.add(RadialOptions(1, 40, 3, '@pet/pet_menu:menu_enter_exit')) + radials.add(RadialOptions(0, 21, 1, '')) + if target.getOwnerId() == owner.getObjectID(): + radials.add(RadialOptions(0, 60, 3, '@pet/pet_menu:menu_store')) + if core.mountService.canRepair(owner, target): + radials.add(RadialOptions(0, 114, 3, '@pet/pet_menu:menu_repair_vehicle')) + return + +def handleSelection(core, owner, target, option): + mntSvc = core.mountService + + if target: + if option == 21: + if mntSvc.isMounted(actor): + mntSvc.mount(actor, target) + else: + mntSvc.unmount(actor, target) + elif option == 60: + mntSvc.store(actor, target) + elif option == 114: + mntSvc.repair(actor, target) + return + diff --git a/scripts/radial/datapad/vehicle_pcd.py b/scripts/radial/datapad/vehicle_pcd.py new file mode 100644 index 00000000..fc880185 --- /dev/null +++ b/scripts/radial/datapad/vehicle_pcd.py @@ -0,0 +1,21 @@ +from resources.common import RadialOptions +import sys + +def createRadial(core, owner, target, radials): + #if not core.mountService.getMount(target): + # radials.add(RadialOptions(0, 21, 3, '@pet_menu:menu_call')) + #else: + # radials.add(RadialOptions(0, 21, 3, '@pet_menu:menu_store')) + radials.add(RadialOptions(0, 61, 1, '')) + radials.add(RadialOptions(0, 7, 1, '')) + radials.add(RadialOptions(0, 15, 1, '')) + return + +def handleSelection(core, owner, target, option): + if option == 61 and target: + core.mountService.call(owner, target) + elif option == 15 and target: + core.mountService.destroy(owner, target) + + return + \ No newline at end of file diff --git a/scripts/radial/deeds/vehicleDeed.py b/scripts/radial/deeds/vehicleDeed.py new file mode 100644 index 00000000..033462ad --- /dev/null +++ b/scripts/radial/deeds/vehicleDeed.py @@ -0,0 +1,16 @@ +from resources.common import RadialOptions +import sys + +def createRadial(core, owner, target, radials): + radials.add(RadialOptions(0, 7, 1, '')) + radials.add(RadialOptions(0, 15, 1, '')) + radials.add(RadialOptions(0, 61, 3, '@pet_menu:menu_generate')) + return + +def handleSelection(core, owner, target, option): + if option == 61 and target: + core.objectService.useObject(owner, target) + if option == 15 and target: + core.objectService.destroyObject(target) + return + \ No newline at end of file diff --git a/src/main/NGECore.java b/src/main/NGECore.java index ee431544..55e3965a 100644 --- a/src/main/NGECore.java +++ b/src/main/NGECore.java @@ -85,6 +85,7 @@ import services.LoginService; import services.map.MapService; import services.object.ObjectService; import services.object.UpdateService; +import services.pet.MountService; import services.resources.HarvesterService; import services.resources.ResourceService; import services.retro.RetroService; @@ -181,6 +182,7 @@ public class NGECore { public HousingService housingService; public LootService lootService; public HarvesterService harvesterService; + public MountService mountService; // Login Server @@ -302,6 +304,7 @@ public class NGECore { housingService = new HousingService(this); lootService = new LootService(this); harvesterService = new HarvesterService(this); + mountService = new MountService(this); if (config.keyExists("JYTHONCONSOLE.PORT")) { int jythonPort = config.getInt("JYTHONCONSOLE.PORT"); @@ -355,6 +358,7 @@ public class NGECore { zoneDispatch.addService(entertainmentService); //zoneDispatch.addService(missionService); zoneDispatch.addService(bazaarService); + zoneDispatch.addService(mountService); if (optionsConfigLoaded && options.getInt("LOAD.RESOURCE.SYSTEM") == 1) { zoneDispatch.addService(surveyService); diff --git a/src/resources/datatables/Posture.java b/src/resources/datatables/Posture.java index 312337f1..f319ea46 100644 --- a/src/resources/datatables/Posture.java +++ b/src/resources/datatables/Posture.java @@ -1,21 +1,23 @@ package resources.datatables; public class Posture { + // Posture.iff - public static final int Invalid = -1; - public static final int Upright = 0; - public static final int Crouched = 1; - public static final int Prone = 2; - public static final int Sneaking = 3; - public static final int Blocking = 4; - public static final int Climbing = 5; - public static final int Flying = 6; - public static final int LyingDown = 7; - public static final int Sitting = 8; - public static final int SkillAnimating = 9; - public static final int DrivingVehicle = 10; - public static final int RidingCreature = 11; - public static final int KnockedDown = 12; - public static final int Incapacitated = 13; - public static final int Dead = 14; + public static final byte Invalid = -1; + public static final byte Upright = 0; + public static final byte Crouched = 1; + public static final byte Prone = 2; + public static final byte Sneaking = 3; + public static final byte Blocking = 4; + public static final byte Climbing = 5; + public static final byte Flying = 6; + public static final byte LyingDown = 7; + public static final byte Sitting = 8; + public static final byte SkillAnimating = 9; + public static final byte DrivingVehicle = 10; + public static final byte RidingCreature = 11; + public static final byte KnockedDown = 12; + public static final byte Incapacitated = 13; + public static final byte Dead = 14; + } diff --git a/src/resources/datatables/State.java b/src/resources/datatables/State.java new file mode 100644 index 00000000..dafd0c64 --- /dev/null +++ b/src/resources/datatables/State.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * 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 resources.datatables; + +public class State { + + public static long Invalid = 0x00L; + public static long Cover = 0x1L; + public static long Combat = 0x2L; + public static long Peace = 0x4L; + public static long Aiming = 0x8L; + public static long Alert = 0x10L; + public static long Berserk = 0x20L; + public static long FeignDeath = 0x40L; + public static long CombatAttitudeEvasive = 0x80L; + public static long CombatAttitudeNormal = 0x100L; + public static long CombatAttitudeAggressive = 0x200L; + public static long Tumbling = 0x400L; + public static long Rallied = 0x800L; + public static long Stunned = 0x1000L; + public static long Blinded = 0x2000L; + public static long Dizzy = 0x4000L; + public static long Intimidated = 0x8000L; + public static long Immobilized = 0x10000L; + public static long Frozen = 0x20000L; + public static long Swimming = 0x40000L; + public static long SittingOnChair = 0x80000L; + public static long Crafting = 0x100000L; + public static long GlowingJedi = 0x200000L; + public static long MaskScent = 0x400000L; + public static long Poisoned = 0x800000L; + public static long Bleeding = 0x1000000L; + public static long Diseased = 0x2000000L; + public static long OnFire = 0x4000000L; + public static long RidingMount = 0x8000000L; + public static long MountedCreature = 0x10000000L; + public static long PilotingShip = 0x20000000L; + public static long ShipOperations = 0x40000000L; + public static long ShipGunner = 0x80000000L; + public static long ShipInterior = 0x100000000L; + public static long PilotingPobShip = 0x200000000L; + public static long PerformingDeathBlow = 0x400000000L; + public static long Disguised = 0x800000000L; + public static long ElectricBurned = 0x1000000000L; + public static long ColdBurned = 0x2000000000L; + public static long AcidBurned = 0x4000000000L; + public static long EnergyBurned = 0x8000000000L; + public static long KineticBurned = 0x10000000000L; + +} diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index fc44c02e..de0c002c 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -34,7 +34,6 @@ import org.apache.mina.core.buffer.IoBuffer; import protocol.swg.ObjControllerMessage; import protocol.swg.PlayMusicMessage; -import protocol.swg.UpdateContainmentMessage; import protocol.swg.UpdatePostureMessage; import protocol.swg.UpdatePVPStatusMessage; import protocol.swg.chat.ChatSystemMessage; @@ -51,7 +50,6 @@ import main.NGECore; import engine.clients.Client; import resources.common.Cooldown; import resources.common.OutOfBand; -import resources.datatables.Options; import resources.objects.Buff; import resources.objects.DamageOverTime; import resources.objects.SWGList; @@ -68,7 +66,7 @@ import resources.objects.player.PlayerObject; import resources.objects.tangible.TangibleObject; import services.command.BaseSWGCommand; -@Entity(version=8) +@Entity(version=9) public class CreatureObject extends TangibleObject implements IPersistent { @NotPersistent @@ -130,7 +128,9 @@ public class CreatureObject extends TangibleObject implements IPersistent { private boolean performanceType = false; private boolean acceptBandflourishes = true; private boolean groupDance = true; + @NotPersistent private CreatureObject performanceWatchee; + @NotPersistent private CreatureObject performanceListenee; @NotPersistent private Vector performanceAudience = new Vector(); @@ -186,10 +186,8 @@ public class CreatureObject extends TangibleObject implements IPersistent { private TangibleObject conversingNpc; @NotPersistent private ConcurrentHashMap cooldowns = new ConcurrentHashMap(); - - public boolean mounted = false; @NotPersistent - public CreatureObject mountedVehicle; + private long tefTime = System.currentTimeMillis(); public CreatureObject(long objectID, Planet planet, Point3D position, Quaternion orientation, String Template) { super(objectID, planet, Template, position, orientation); @@ -371,7 +369,6 @@ public class CreatureObject extends TangibleObject implements IPersistent { } public void setPosture(byte posture) { - synchronized(objectMutex) { if (this.posture == 0x09) { stopPerformance(); @@ -390,16 +387,13 @@ public class CreatureObject extends TangibleObject implements IPersistent { } public void startPerformance() { - - getClient().getSession().write(messageBuilder.buildStartPerformance(true)); - + setStationary(true); } public void stopPerformance() { - String type = ""; + synchronized(objectMutex) { - // Some reason this prevents the animation for playing an instrument when stopping (unless that's what "" does) setCurrentAnimation(getCurrentAnimation()); @@ -407,17 +401,16 @@ public class CreatureObject extends TangibleObject implements IPersistent { setPerformanceId(0,true); type = (performanceType) ? "dance" : "music"; + if (entertainerExperience != null) { entertainerExperience.cancel(true); entertainerExperience = null; } } - sendSystemMessage("@performance:" + type + "_stop_self",(byte)0); + sendSystemMessage("@performance:" + type + "_stop_self",(byte)0); stopAudience(); - - getClient().getSession().write(messageBuilder.buildStartPerformance(false)); - + setStationary(false); } public void stopAudience() { @@ -472,7 +465,13 @@ public class CreatureObject extends TangibleObject implements IPersistent { } notifyObservers(messageBuilder.buildFactionDelta(faction), true); - //updatePvpStatus(); + + + CreatureObject companion = NGECore.getInstance().mountService.getCompanion(this); + + if (companion != null) { + companion.setFaction(faction); + } } @Override @@ -482,7 +481,12 @@ public class CreatureObject extends TangibleObject implements IPersistent { } notifyObservers(messageBuilder.buildFactionStatusDelta(factionStatus), true); - //updatePvpStatus(); + + CreatureObject companion = NGECore.getInstance().mountService.getCompanion(this); + + if (companion != null) { + companion.setFactionStatus(factionStatus); + } } public float getHeight() { @@ -530,7 +534,25 @@ public class CreatureObject extends TangibleObject implements IPersistent { notifyObservers(stateDelta, true); } - + + public void setState(long state, boolean add) { + synchronized(objectMutex) { + if (state != 0) { + if (add) { + stateBitmask = (stateBitmask | state); + } else { + stateBitmask = (stateBitmask & ~state); + } + } + } + } + + public boolean getState(long state) { + synchronized(objectMutex) { + return ((stateBitmask & state) == state); + } + } + public long getOwnerId() { synchronized(objectMutex) { return ownerId; @@ -541,6 +563,9 @@ public class CreatureObject extends TangibleObject implements IPersistent { synchronized(objectMutex) { this.ownerId = ownerId; } + + setStringAttribute("owner", NGECore.getInstance().objectService.getObject(ownerId).getCustomName()); + notifyObservers(messageBuilder.buildOwnerIdDelta(ownerId), true); } @@ -1715,6 +1740,8 @@ public class CreatureObject extends TangibleObject implements IPersistent { synchronized(objectMutex) { this.stationary = stationary; } + + notifyObservers(messageBuilder.buildStartPerformance(stationary), true); } public TangibleObject getConversingNpc() { @@ -1782,78 +1809,20 @@ public class CreatureObject extends TangibleObject implements IPersistent { return (PlayerObject) this.getSlottedObject("ghost"); } - public boolean isMounted() { - return mounted; - } - - public void setMounted(boolean mounted) { - this.mounted = mounted; - } - - public CreatureObject getMountedVehicle() { - return mountedVehicle; - } - - public void setMountedVehicle(CreatureObject mountedVehicle) { - this.mountedVehicle = mountedVehicle; - } - - public boolean canMount(CreatureObject vehicle) - { - if(vehicle.getOwnerId() == this.getObjectId()) return true; - return false; - } - - public void mount(CreatureObject owner) { - boolean remove = false; - synchronized(objectMutex) - { - if ((this.getOptionsBitmask() & Options.MOUNT) == Options.MOUNT) - { - remove = true; - _add(owner); - UpdateContainmentMessage updateContainmentMessage = new UpdateContainmentMessage(owner.getObjectID(), this.getObjectID(), 4); - notifyObservers(updateContainmentMessage, true); - } - } - - if(remove) NGECore.getInstance().simulationService.remove(owner, owner.getWorldPosition().x, owner.getWorldPosition().z, false); - } - - public void unmount(CreatureObject owner) { - boolean add = false; - synchronized(objectMutex) { - if ((this.getOptionsBitmask() & Options.MOUNT) == Options.MOUNT){ - add = true; - _remove(owner); - UpdateContainmentMessage updateContainmentMessage = new UpdateContainmentMessage(owner.getObjectID(), 0, -1); - notifyObservers(updateContainmentMessage, true); - } - } - if(add) { - owner.setMounted(false); - owner.setMountedVehicle(null); - owner.setStateBitmask(0); - owner.setPosture((byte) 0); - NGECore.getInstance().simulationService.add(owner, getWorldPosition().x, getWorldPosition().z, false); - NGECore.getInstance().simulationService.teleport(owner, getWorldPosition(), getOrientation(), 0); - } - } - - public void initMount(CreatureObject owner) { - synchronized(objectMutex) { - setStateBitmask(0x10000000); - owner.setMountedVehicle(this); - - this.mount(owner); - - owner.setStateBitmask(0x8000000); - this.setPosture((byte)10); - } - } - //public float getCooldown(String cooldownGroup) { //return ((float) getCooldown(cooldownGroup) / (float) 1000); //} + public long getTefTime() { + synchronized(objectMutex) { + return (((tefTime - System.currentTimeMillis()) > 0) ? (tefTime - System.currentTimeMillis()) : 0); + } + } + + public void setTefTime(long tefTime) { + synchronized(objectMutex) { + this.tefTime = tefTime + System.currentTimeMillis(); + } + } + } diff --git a/src/resources/objects/player/PlayerObject.java b/src/resources/objects/player/PlayerObject.java index 7c956d6f..ec8e7da5 100644 --- a/src/resources/objects/player/PlayerObject.java +++ b/src/resources/objects/player/PlayerObject.java @@ -142,6 +142,9 @@ public class PlayerObject extends IntangibleObject { private byte godLevel = 0; + @NotPersistent + private boolean callingCompanion = false; + public PlayerObject() { super(); messageBuilder = new PlayerMessageBuilder(this); @@ -864,4 +867,12 @@ public class PlayerObject extends IntangibleObject { } } + public boolean isCallingCompanion() { + return callingCompanion; + } + + public void setCallingCompanion(boolean callingCompanion) { + this.callingCompanion = callingCompanion; + } + } diff --git a/src/resources/objects/tangible/TangibleObject.java b/src/resources/objects/tangible/TangibleObject.java index 4d8d18fc..21d8134f 100644 --- a/src/resources/objects/tangible/TangibleObject.java +++ b/src/resources/objects/tangible/TangibleObject.java @@ -54,7 +54,7 @@ import engine.resources.scene.Planet; import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; -@Persistent(version=6) +@Persistent(version=7) public class TangibleObject extends SWGObject { // TODO: Thread safety @@ -262,6 +262,14 @@ public class TangibleObject extends SWGObject { } } + + if (getClient() != null) { + CreatureObject companion = NGECore.getInstance().mountService.getCompanion((CreatureObject) this); + + if (companion != null) { + companion.updatePvpStatus(); + } + } } public void setCustomizationVariable(String type, byte value) diff --git a/src/services/SimulationService.java b/src/services/SimulationService.java index 67406a06..f16e3557 100644 --- a/src/services/SimulationService.java +++ b/src/services/SimulationService.java @@ -80,6 +80,8 @@ import resources.objects.player.PlayerObject; import resources.objects.tangible.TangibleObject; import resources.common.*; import resources.common.collidables.AbstractCollidable; +import resources.datatables.DisplayType; +import resources.datatables.Options; import resources.datatables.PlayerFlags; import resources.datatables.Posture; import services.ai.LairActor; @@ -333,8 +335,9 @@ public class SimulationService implements INetworkDispatch { CreatureObject object = (CreatureObject) client.getParent(); - if (object.mounted) - object=object.getMountedVehicle(); + if (core.mountService.isMounted(object)) { + object = (CreatureObject) object.getContainer(); + } Point3D newPos; Point3D oldPos; @@ -432,8 +435,14 @@ public class SimulationService implements INetworkDispatch { System.out.println("NULL Object"); return; } + CreatureObject object = (CreatureObject) client.getParent(); + if (core.mountService.isMounted(object)) { + object.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cant_mount"), DisplayType.Broadcast); + core.mountService.dismount(object, (CreatureObject) object.getContainer()); + } + Point3D newPos = new Point3D(dataTransform.getXPosition(), dataTransform.getYPosition(), dataTransform.getZPosition()); if(Float.isNaN(newPos.x) || Float.isNaN(newPos.y) || Float.isNaN(newPos.z)) return; @@ -747,6 +756,7 @@ public class SimulationService implements INetworkDispatch { return; final CreatureObject object = (CreatureObject) client.getParent(); + SWGObject container = object.getContainer(); PlayerObject ghost = (PlayerObject) object.getSlottedObject("ghost"); if(object.getAttachment("proposer") != null) @@ -763,16 +773,13 @@ public class SimulationService implements INetworkDispatch { core.combatService.handleEndDuel(object, opponent, true); } } - System.out.print(object.getAttachment("activeVehicleID")); - if(object.getAttachment("activeVehicleID") != null) - { - if(object.isMounted()) object.getMountedVehicle().unmount(object); - long vehicleID = ((java.math.BigInteger) object.getAttachment("activeVehicleID")).longValue(); - core.objectService.destroyObject(vehicleID); - object.setAttachment("activeVehicleID", null); + if (core.mountService.isMounted(object)) { + core.mountService.dismount(object, (CreatureObject) container); } + core.mountService.storeAll(object); + /* object.createTransaction(core.getCreatureODB().getEnvironment()); core.getCreatureODB().put(object, Long.class, CreatureObject.class, object.getTransaction()); diff --git a/src/services/combat/CombatService.java b/src/services/combat/CombatService.java index 87bfcd31..344cc120 100644 --- a/src/services/combat/CombatService.java +++ b/src/services/combat/CombatService.java @@ -41,6 +41,7 @@ import protocol.swg.objectControllerObjects.CombatSpam; import protocol.swg.objectControllerObjects.CommandEnqueueRemove; import protocol.swg.objectControllerObjects.StartTask; import resources.common.FileUtilities; +import resources.datatables.Options; import resources.datatables.Posture; import resources.objects.Buff; import resources.objects.DamageOverTime; @@ -279,6 +280,11 @@ public class CombatService implements INetworkDispatch { private void applyDamage(CreatureObject attacker, TangibleObject target, int damage) { target.setConditionDamage(target.getConditionDamage() + damage); + + if (target.getOption(Options.MOUNT)) { + core.mountService.damage((CreatureObject) target); + } + DamageTaken event = events.new DamageTaken(); event.attacker = attacker; event.damage = damage; diff --git a/src/services/object/ObjectService.java b/src/services/object/ObjectService.java index f39729ad..14beded4 100644 --- a/src/services/object/ObjectService.java +++ b/src/services/object/ObjectService.java @@ -719,7 +719,15 @@ public class ObjectService implements INetworkDispatch { return; } - if (object.getIntAttribute("reuse_time") > 0) { + int reuse_time; + + try { + reuse_time = object.getIntAttribute("reuse_time"); + } catch (NumberFormatException e) { + reuse_time = 0; + } + + if (reuse_time > 0) { try { DatatableVisitor visitor = ClientFileManager.loadFile("datatables/timer/template_command_mapping.iff", DatatableVisitor.class); @@ -745,7 +753,7 @@ public class ObjectService implements INetworkDispatch { return; } - creature.addCooldown(cooldownGroup, object.getIntAttribute("reuse_item")); + creature.addCooldown(cooldownGroup, object.getIntAttribute("reuse_time")); } break; diff --git a/src/services/pet/MountService.java b/src/services/pet/MountService.java new file mode 100644 index 00000000..59f49f63 --- /dev/null +++ b/src/services/pet/MountService.java @@ -0,0 +1,766 @@ +/******************************************************************************* + * 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.pet; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.LongAdder; + +import protocol.swg.UpdateContainmentMessage; +import main.NGECore; +import resources.common.OutOfBand; +import resources.datatables.DisplayType; +import resources.datatables.Options; +import resources.datatables.Posture; +import resources.datatables.StateStatus; +import resources.objects.building.BuildingObject; +import resources.objects.creature.CreatureObject; +import resources.objects.player.PlayerObject; +import engine.resources.container.Traverser; +import engine.resources.objects.SWGObject; +import engine.resources.service.INetworkDispatch; +import engine.resources.service.INetworkRemoteEvent; + +public class MountService implements INetworkDispatch { + + private NGECore core; + + public MountService(NGECore core) { + this.core = core; + } + + // Creature mounts are considered pets as well + // Pet abilities and petId is in PLAY9 + + // The functions for vehicles, mounts and pets are similar, but not the same + // Hence the multiple services. + + public void generateVehicle(CreatureObject actor, SWGObject deed, String vehicleTemplate, String pcdTemplate) { + if (actor == null || vehicleTemplate == null || pcdTemplate == null) { + return; + } + + if (actor.getSlottedObject("ghost") == null) { + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:failed_to_call_vehicle"), DisplayType.Broadcast); + return; + } + + SWGObject datapad = actor.getSlottedObject("datapad"); + + if (datapad == null) { + return; + } + + // Unsure if these are the right attributes. It doesn't generate the vehicle if the datapad has max # of vehicles. + //if (datapad.getIntAttribute("data_size") >= datapad.getIntAttribute("datapad_slots")) { + //actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:has_max_vehicle"), DisplayType.Broadcast); + //return; + //} + + if (actor.getTefTime() > 0){ + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:prose_cant_generate_yet", actor.getTefTime()), DisplayType.Broadcast); + return; + } + + SWGObject pcd = core.objectService.createObject(pcdTemplate, actor.getPlanet()); + + if (pcd == null) { + return; + } + + if (pcd.getSlottedObject("inventory") == null) { + pcd.add(core.objectService.createObject("object/tangible/inventory/shared_character_inventory.iff", pcd.getPlanet())); + } + + CreatureObject vehicle = (CreatureObject) core.objectService.createObject(vehicleTemplate, actor.getPlanet()); + + if (vehicle == null) { + return; + } + + vehicle.setOptions(Options.MOUNT | Options.ATTACKABLE, true); + + vehicle.setOwnerId(actor.getObjectID()); + + pcd.setAttachment("companionId", vehicle.getObjectID()); + + pcd.getSlottedObject("inventory").add(vehicle); + + datapad.add(pcd); + + if (deed != null) { + core.objectService.destroyObject(deed); + } + + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:device_added"), DisplayType.Broadcast); + + call(actor, pcd); + } + + public void generateMount(CreatureObject actor, SWGObject deed, String vehicleTemplate, String pcdTemplate) { + return; // NOT IMPLEMENTED + } + + public void call(CreatureObject actor, SWGObject pcd) { + if (actor == null) { + return; + } + + if (pcd == null) { + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cant_call"), DisplayType.Broadcast); + return; + } + + if (isMounted(actor)) { + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cannot_call_another_rideable"), DisplayType.Broadcast); + return; + } + + if (actor.getCombatFlag() == 1) { + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cannot_call_in_combat"), DisplayType.Broadcast); + return; + } + + if (actor.getContainer() != null) { + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cannot_call_indoors"), DisplayType.Broadcast); + return; + } + + if (actor.getPosture() == Posture.Dead) { + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cannot_call_while_dead"), DisplayType.Broadcast); + return; + } + + if (pcd.getSlottedObject("inventory") == null) { + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cant_call"), DisplayType.Broadcast); + return; + } + + if (actor.isInStealth()) { + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:no_mount_stealth"), DisplayType.Broadcast); + return; + } + + if (pcd.getStringAttribute("required_faction") != null && pcd.getStringAttribute("required_faction").length() > 0) { + if (!actor.getFaction().equals(pcd.getStringAttribute("required_faction"))) { + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:officer_faction"), DisplayType.Broadcast); + return; + } + } + + PlayerObject player = (PlayerObject) actor.getSlottedObject("ghost"); + + if (player == null) { + return; + } + + CreatureObject mount = (CreatureObject) core.objectService.getObject((Long) pcd.getAttachment("companionId")); + + if (mount == null) { + // Somehow the vehicle object has got lost + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cant_call"), DisplayType.Broadcast); + return; + } + + mount.setFaction(actor.getFaction()); + mount.setFactionStatus(actor.getFactionStatus()); + + if (pcd.getTemplate().contains("vehicle")) { + callVehicle(actor, pcd, player, mount); + } else { + callMount(actor, pcd, player, mount); + } + } + + private void callVehicle(CreatureObject actor, SWGObject pcd, PlayerObject player, CreatureObject mount) { + if ((mount.getLevel() - actor.getLevel()) > 5) { + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cant_call_level"), DisplayType.Broadcast); + return; + } + + // FIXME Movement skillmod should always be used instead of CREO4 speed vars directly. Movement skillmod should NEVER be 0 unless rooted. Currently it is, which is wrong. + //if (actor.getSkillModBase("movement") == 0) { + //actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cant_call_vehicle_rooted"), DisplayType.Broadcast); + //return; + //} + + if (actor.getPlanet().getName().contains("kashyyyk") && !actor.getPlanet().getName().contains("_main")) { + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:vehicle_restricted_scene"), DisplayType.Broadcast); + //mount_restricted_scene for creature mounts + return; + } + + if (player.isCallingCompanion()) { + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cant_call_1sec"), DisplayType.Broadcast); + return; + } + + storeAll(actor); + + player.setCallingCompanion(true); + + if (actor.getTefTime() > 0) { + actor.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:call_vehicle_delay", actor.getTefTime()), DisplayType.Broadcast); + } + + try { + while (actor.getTefTime() > 0) { + Thread.sleep(3000); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + + SWGObject datapad = actor.getSlottedObject("datapad"); + + if (datapad == null) { + return; + } + + datapad.viewChildren(actor, false, false, new Traverser() { + + public void process(SWGObject pcd) { + if (pcd.getAttachment("companionId") != null && mount.getObjectID() == ((Long) pcd.getAttachment("companionId"))) { + if (pcd.getSlottedObject("inventory") != null) { + LongAdder adder = new LongAdder(); + pcd.getSlottedObject("inventory").viewChildren(actor, false, false, (obj) -> adder.increment()); + + if (adder.intValue() == 1) { + pcd.getSlottedObject("inventory").remove(mount); + mount.setPosition(actor.getPosition().clone()); + mount.setOrientation(actor.getOrientation().clone()); + mount.setPlanet(actor.getPlanet()); + core.simulationService.add(mount, actor.getWorldPosition().x, actor.getWorldPosition().z, false); + } + } + } + } + + }); + + player.setCallingCompanion(false); + + System.out.println("Got to end"); + } + + private void callMount(CreatureObject actor, SWGObject pcd, PlayerObject player, CreatureObject mount) { + return; // NOT IMPLEMENTED + } + + public void damage(CreatureObject mount) { + // alter components to progressively reduce the painting. + //stfs + //customization_fading_veh + //customization_gone_veh + + if (mount == null) { + return; + } + + CreatureObject owner = (CreatureObject) core.objectService.getObject(mount.getOwnerId()); + + if (!mount.getTemplate().contains("vehicle")) { + dismount(owner, mount); + store(owner, mount); + mount.setConditionDamage(0); + return; + } + + if (mount.getConditionDamage() >= mount.getMaxDamage()) { + disable(mount); + } + } + + public void disable(CreatureObject mount) { + mount.setOptions(Options.DISABLED, true); + + mount.viewChildren(mount, false, false, new Traverser() { + + public void process(SWGObject object) { + if (object == null || !(object instanceof CreatureObject)) { + return; + } + + CreatureObject rider = (CreatureObject) object; + + dismount(rider, mount); + + rider.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:veh_disabled"), DisplayType.Broadcast); + } + + }); + } + + public boolean canRepair(CreatureObject actor, CreatureObject mount) { + if (actor == null || mount == null) { + return false; + } + + if (!mount.getOption(Options.MOUNT)) { + return false; + } + + if (!mount.getTemplate().contains("vehicle")) { + return false; + } + + if (mount.getOwnerId() != actor.getObjectID()) { + return false; + } + + if (mount.getOption(Options.DISABLED)) { + return false; + } + + if (mount.getConditionDamage() == 0) { + return false; + } + + List surroundings = core.simulationService.get(mount.getPlanet(), mount.getPosition().x, mount.getPosition().z, 32); + + for (SWGObject object : surroundings) { + if (object instanceof BuildingObject) { + if (object.getTemplate().contains("garage")) { + return true; + } + } + } + + return false; + } + + public void repair(CreatureObject repairer, CreatureObject mount) { + if (repairer == null || mount == null) { + return; + } + + if (!mount.getOption(Options.MOUNT)) { + return; + } + + if (core.objectService.getObject(mount.getOwnerId()) != repairer) { + return; + } + + if (mount.getOption(Options.DISABLED)) { + repairer.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cannot_repair_disabled"), DisplayType.Broadcast); + return; + } + + if (mount.getConditionDamage() == 0) { + repairer.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:undamaged_vehicle"), DisplayType.Broadcast); + return; + } + + // This should produce an SUI window regarding cost and cost might be determined differently. + // But at the moment it's not important. + + if (!canRepair(repairer, mount)) { + repairer.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:repair_unrecognized_garages"), DisplayType.Broadcast); + return; + } + + int cost = mount.getConditionDamage(); + + if (repairer.getCashCredits() < cost) { + repairer.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:repair_failed_due_to_funds"), DisplayType.Broadcast); + return; + } + + mount.setConditionDamage(0); + + mount.setOptions(Options.DISABLED, false); + + repairer.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:repaired_to_max"), DisplayType.Broadcast); + } + + public void mount(CreatureObject rider, CreatureObject mount) { + // FIXME like above, movement skillmod should be used instead of creo4 vars and never be 0, otherwise it thinks we are always rooted + //if (rider.getSkillModBase("movement") == 0) { + //rider.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cant_mount_rooted"), DisplayType.Broadcast); + //return; + //} + + if (mount.getOption(Options.DISABLED)) { + rider.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cant_mount_veh_disabled"), DisplayType.Broadcast); + return; + } + + if (!mount.getOption(Options.MOUNT)) { + return; + } + + if (!canMount(rider, mount)) { + rider.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cant_mount"), DisplayType.Broadcast); + return; + } + + mount._add(rider); + mount.setStateBitmask(mount.getStateBitmask() | 0x10000000); + //mount.setState(State.MountedCreature, true); + mount.notifyObservers(new UpdateContainmentMessage(rider.getObjectID(), mount.getObjectID(), 4), true); + //rider.setState(State.RidingMount, true); + rider.setStateBitmask(rider.getStateBitmask() | 0x8000000); + //rider.setPosture((mount.getTemplate().contains("vehicle")) ? Posture.DrivingVehicle : Posture.RidingCreature); + rider.setPosture((byte) 11); + core.simulationService.remove(rider, rider.getWorldPosition().x, rider.getWorldPosition().z, false); + } + + public CreatureObject getMount(SWGObject pcd) { + if (pcd == null) { + return null; + } + + if (pcd.getAttachment("companionId") == null) { + return null; + } + + CreatureObject mount = (CreatureObject) core.objectService.getObject((Long) pcd.getAttachment("companionId")); + + if (mount == null) { + return null; + } + + if (mount.getContainer() != null) { + return null; + } + + return mount; + } + + public CreatureObject getCompanion(CreatureObject actor) { + if (actor == null) { + return null; + } + + if (isMounted(actor)) { + return (CreatureObject) actor.getContainer(); + } + + SWGObject datapad = actor.getSlottedObject("datapad"); + + if (datapad == null) { + return null; + } + + final List companions = new ArrayList(); + + datapad.viewChildren(actor, false, false, new Traverser() { + + public void process(SWGObject pcd) { + if (pcd.getAttachment("companionId") != null) { + if (pcd.getSlottedObject("inventory") != null) { + LongAdder adder = new LongAdder(); + pcd.getSlottedObject("inventory").viewChildren(actor, false, false, (obj) -> adder.increment()); + + if (adder.intValue() == 0) { + CreatureObject companion = (CreatureObject) core.objectService.getObject((Long) pcd.getAttachment("companionId")); + companions.add(companion); + } + } + } + } + + }); + + if (companions.size() > 0) { + return companions.get(0); + } else { + return null; + } + } + + public boolean isMounted(CreatureObject rider) { + if (rider.getContainer() == null) { + return false; + } + + if (!(rider.getContainer() instanceof CreatureObject)) { + return false; + } + + CreatureObject mount = (CreatureObject) rider.getContainer(); + + if (!mount.getOption(Options.MOUNT)) { + return false; + } + + if (mount.getSlottedObject("rider") != rider) { + return false; + } + + return true; + } + + public boolean isMounted(SWGObject actor, CreatureObject mount) { + return actor.getContainer() == mount; + } + + public boolean canMount(CreatureObject rider, CreatureObject mount) { + if (mount == null) { + return false; + } + + if (!mount.getOption(Options.MOUNT)) { + return false; + } + + if (isMounted(rider)) { + return false; + } + + if (rider.getObjectID() == mount.getOwnerId()) { + return true; + } + + // It's a potential passenger + + // See if there's driver first + if (mount.getSlottedObject("rider") == null) { + return false; + } + + int passengers = 0; + + if (mount.getAttachment("passengers") != null){ + passengers = (Integer) mount.getAttachment("passengers"); + } + + int passengerSlot = 0; + + for (int i = 1; i <= passengers; i++) { + if (mount.getSlottedObject("rider" + i) == null) { + passengerSlot = i; + break; + } + } + + if (passengerSlot == 0) { + return false; + } + + CreatureObject owner = (CreatureObject) NGECore.getInstance().objectService.getObject(mount.getOwnerId()); + + if (owner == null) { + return false; + } + + if (owner.isAttackableBy(rider)) { + return false; + } + + if (rider.getGroupId() == 0 || rider.getGroupId() != owner.getGroupId()) { + return false; + } + + return true; + } + + public void dismount(CreatureObject rider, CreatureObject mount) { + if (rider == null || mount == null) { + return; + } + + if (!isMounted(rider)) { + return; + } + + if (!mount.getOption(Options.MOUNT)) { + return; + } + + if (rider.getObjectID() == mount.getOwnerId()) { + CreatureObject owner = rider; + + mount.viewChildren(owner, false, false, new Traverser() { + + public void process(SWGObject passenger) { + if (passenger != owner) { + mount._remove(passenger); + mount.notifyObservers(new UpdateContainmentMessage(passenger.getObjectID(), 0, -1), false); + + if (passenger instanceof CreatureObject) { + ((CreatureObject) passenger).setState(StateStatus.RidingMount, false); + ((CreatureObject) passenger).setPosture(Posture.Upright); + } + + core.simulationService.add(passenger, mount.getWorldPosition().x, mount.getWorldPosition().z, false); + core.simulationService.teleport(passenger, mount.getWorldPosition(), mount.getOrientation(), 0); + } + } + + }); + } + + mount._remove(rider); + mount.notifyObservers(new UpdateContainmentMessage(rider.getObjectID(), 0, -1), false); + + if (rider.getObjectID() == mount.getOwnerId()) { + mount.setState(StateStatus.MountedCreature, false); + } + + core.simulationService.add(rider, mount.getWorldPosition().x, mount.getWorldPosition().z, false); + core.simulationService.teleport(rider, mount.getWorldPosition(), mount.getOrientation(), 0); + + if (!mount.getTemplate().contains("vehicle") && rider.getObjectID() == mount.getOwnerId()) { + store(rider, mount); + } + } + + /* + * They seem to have been stored in the inventory of the pcd object. + * Judging by the fact pcds have inventories and many other things don't. + */ + public void store(CreatureObject storer, CreatureObject mount) { + if (mount.getContainer() != null) { + return; + } + + if (mount.getOwnerId() == 0) { + return; + } + + CreatureObject owner = (CreatureObject) core.objectService.getObject(mount.getOwnerId()); + + if (owner == null || storer == null || owner != storer) { + return; + } + + PlayerObject player = (PlayerObject) owner.getSlottedObject("ghost"); + + if (player.isCallingCompanion()) { + storer.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:cant_store_1sec"), DisplayType.Broadcast); + return; + } + + if (isMounted(owner, mount)) { + storer.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:must_dismount"), DisplayType.Broadcast); + return; + } + + if (owner.getTefTime() > 0){ + owner.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:prose_cant_store_yet", owner.getTefTime()), DisplayType.Broadcast); + return; + } + + SWGObject datapad = owner.getSlottedObject("datapad"); + + if (datapad == null) { + return; + } + + datapad.viewChildren(owner, false, false, new Traverser() { + + public void process(SWGObject pcd) { + if (pcd.getAttachment("companionId") != null && mount.getObjectID() == ((Long) pcd.getAttachment("companionId"))) { + if (pcd.getSlottedObject("inventory") != null) { + LongAdder adder = new LongAdder(); + pcd.getSlottedObject("inventory").viewChildren(owner, false, false, (obj) -> adder.increment()); + + if (adder.intValue() == 0) { + core.simulationService.remove(mount, mount.getWorldPosition().x, mount.getWorldPosition().z, true); + pcd.getSlottedObject("inventory").add(mount); + } + } + } + } + + }); + } + + public void storeAll(CreatureObject actor) { + while (getCompanion(actor) != null) { + store(actor, getCompanion(actor)); + } + + /* + if (actor == null) { + return; + } + + SWGObject datapad = actor.getSlottedObject("datapad"); + + if (datapad == null) { + return; + } + + datapad.viewChildren(actor, false, false, new Traverser() { + + public void process(SWGObject pcd) { + if (pcd.getAttachment("companionId") != null) { + if (pcd.getSlottedObject("inventory") != null) { + LongAdder adder = new LongAdder(); + pcd.getSlottedObject("inventory").viewChildren(actor, false, false, (obj) -> adder.increment()); + + if (adder.intValue() == 0) { + long companionId = (pcd.getAttachment("companionId") == null) ? 0L : (Long) pcd.getAttachment("companionId"); + store(actor, (CreatureObject) core.objectService.getObject(companionId)); + } + } + } + } + + }); + */ + } + + public void destroy(CreatureObject destroyer, SWGObject pcd) { + if (destroyer == null || pcd == null || pcd.getGrandparent() == null) { + return; + } + + if (destroyer.getObjectID() != pcd.getGrandparent().getObjectID()) { + return; + } + + if (pcd.getAttachment("companionId") == null) { + return; + } + + CreatureObject mount = (CreatureObject) core.objectService.getObject((Long) pcd.getAttachment("companionId")); + + dismount(destroyer, mount); + + store(destroyer, mount); + + String type = mount.getTemplate(); + + core.objectService.destroyObject(mount); + core.objectService.destroyObject(pcd); + + if (type.contains("vehicle")) { + destroyer.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:vehicle_released"), DisplayType.Broadcast); + } else { + destroyer.sendSystemMessage(OutOfBand.ProsePackage("@pet_menu:pet_released"), DisplayType.Broadcast); + } + } + + public void insertOpcodes(Map arg0, Map arg1) { + + } + + public void shutdown() { + + } + +}