diff --git a/ngengine_public.jar b/ngengine_public.jar index ebf3d16a..0811dbbf 100644 Binary files a/ngengine_public.jar and b/ngengine_public.jar differ diff --git a/odb/oids/placeholder.txt b/odb/oids/placeholder.txt new file mode 100644 index 00000000..e69de29b diff --git a/scripts/mobiles/lairgroups/tatooine_starter.py b/scripts/mobiles/lairgroups/tatooine_starter.py index 63eda38c..55242c03 100644 --- a/scripts/mobiles/lairgroups/tatooine_starter.py +++ b/scripts/mobiles/lairgroups/tatooine_starter.py @@ -3,7 +3,11 @@ from services.spawn import LairSpawnTemplate from java.util import Vector def addLairGroup(core): - spawnTemplate = LairSpawnTemplate(-1, 'tatooine_kreetle_lair_neutral_small', 5, 20) + spawnTemplate1 = LairSpawnTemplate(-1, 'tatooine_kreetle_lair_neutral_small', 5, 20) + spawnTemplate2 = LairSpawnTemplate(-1, 'tatooine_womprat_lair_neutral_small', 5, 15) + spawnTemplates = Vector() - spawnTemplates.add(spawnTemplate) + #spawnTemplates.add(spawnTemplate1) + spawnTemplates.add(spawnTemplate2) + core.spawnService.addLairGroup('tatooine_starter', spawnTemplates) \ No newline at end of file diff --git a/scripts/mobiles/lairs/tatooine_womprat_lair_neutral_small.py b/scripts/mobiles/lairs/tatooine_womprat_lair_neutral_small.py new file mode 100644 index 00000000..60400598 --- /dev/null +++ b/scripts/mobiles/lairs/tatooine_womprat_lair_neutral_small.py @@ -0,0 +1,4 @@ +import sys + +def addTemplate(core): + core.spawnService.addLairTemplate('tatooine_womprat_lair_neutral_small', 'womprat', 15, 'object/tangible/lair/base/shared_poi_all_lair_brambles_small.iff') \ No newline at end of file diff --git a/scripts/mobiles/tatooine/kreetle.py b/scripts/mobiles/tatooine/kreetle.py new file mode 100644 index 00000000..6d96166b --- /dev/null +++ b/scripts/mobiles/tatooine/kreetle.py @@ -0,0 +1,15 @@ +import sys +from services.spawn import MobileTemplate +from java.util import Vector + +def addTemplate(core): + mobileTemplate = MobileTemplate() + templates = Vector() + templates.add('object/mobile/shared_kreetle.iff') + mobileTemplate.setTemplates(templates) + mobileTemplate.setLevel(5) + attacks = Vector() + mobileTemplate.setDefaultAttack('creatureMeleeAttack') + mobileTemplate.setAttacks(attacks) + core.spawnService.addMobileTemplate('kreetle', mobileTemplate) + \ No newline at end of file diff --git a/scripts/mobiles/tatooine/womprat.py b/scripts/mobiles/tatooine/womprat.py new file mode 100644 index 00000000..f1531b4c --- /dev/null +++ b/scripts/mobiles/tatooine/womprat.py @@ -0,0 +1,15 @@ +import sys +from services.spawn import MobileTemplate +from java.util import Vector + +def addTemplate(core): + mobileTemplate = MobileTemplate() + templates = Vector() + templates.add('object/mobile/shared_womp_rat.iff') + mobileTemplate.setTemplates(templates) + mobileTemplate.setLevel(5) + attacks = Vector() + mobileTemplate.setDefaultAttack('creatureMeleeAttack') + mobileTemplate.setAttacks(attacks) + core.spawnService.addMobileTemplate('womprat', mobileTemplate) + \ No newline at end of file diff --git a/src/main/NGECore.java b/src/main/NGECore.java index 8a68784c..c8ad5d16 100644 --- a/src/main/NGECore.java +++ b/src/main/NGECore.java @@ -24,7 +24,10 @@ package main; import java.io.IOException; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; @@ -37,6 +40,9 @@ import java.util.concurrent.TimeUnit; import org.apache.mina.core.service.IoHandler; import org.apache.mina.core.session.IoSession; +import com.sleepycat.je.Transaction; +import com.sleepycat.persist.EntityCursor; + import protocol.swg.ChatSystemMessage; import net.engio.mbassy.bus.config.BusConfiguration; import resources.common.RadialOptions; @@ -90,6 +96,7 @@ import engine.resources.common.CRC; import engine.resources.common.PHPBB3Auth; import engine.resources.config.Config; import engine.resources.config.DefaultConfig; +import engine.resources.container.Traverser; import engine.resources.database.DatabaseConnection; import engine.resources.database.ObjectDatabase; import engine.resources.objects.SWGObject; @@ -170,6 +177,7 @@ public class NGECore { private ObjectDatabase creatureODB; private ObjectDatabase mailODB; private ObjectDatabase guildODB; + private ObjectDatabase objectIdODB; private BusConfiguration eventBusConfig = BusConfiguration.Default(1, new ThreadPoolExecutor(1, 4, 1, TimeUnit.MINUTES, new LinkedBlockingQueue())); @@ -183,7 +191,6 @@ public class NGECore { public void start() { instance = this; - final ThreadMonitor deadlockDetector = new ThreadMonitor(); Thread deadlockMonitor = new Thread(new Runnable() { @Override @@ -219,6 +226,8 @@ public class NGECore { buildingODB = new ObjectDatabase("building", true, false, true); mailODB = new ObjectDatabase("mails", true, false, true); guildODB = new ObjectDatabase("guild", true, false, true); + objectIdODB = new ObjectDatabase("oids", true, false, false); + // Services loginService = new LoginService(this); connectionService = new ConnectionService(this); @@ -343,9 +352,10 @@ public class NGECore { weatherService = new WeatherService(this); weatherService.loadPlanetSettings(); - // spawnService.loadLairTemplates(); - // spawnService.loadLairGroups(); - // spawnService.loadSpawnAreas(); + /*spawnService.loadMobileTemplates(); + spawnService.loadLairTemplates(); + spawnService.loadLairGroups(); + spawnService.loadSpawnAreas();*/ didServerCrash = false; System.out.println("Started Server."); @@ -451,6 +461,10 @@ public class NGECore { return buildingODB; } + public ObjectDatabase getObjectIdODB() { + return objectIdODB; + } + public int getActiveClients() { int connections = 0; for (Map.Entry c : clients.entrySet()) { @@ -529,7 +543,7 @@ public class NGECore { synchronized(getActiveConnectionsMap()) { for(Client client : getActiveConnectionsMap().values()) { client.getSession().close(true); - connectionService.disconnect(client.getSession()); + connectionService.disconnect(client); } } diff --git a/src/protocol/swg/ObjControllerMessage.java b/src/protocol/swg/ObjControllerMessage.java index 2aa76b4e..a664888c 100644 --- a/src/protocol/swg/ObjControllerMessage.java +++ b/src/protocol/swg/ObjControllerMessage.java @@ -55,6 +55,7 @@ public class ObjControllerMessage extends SWGMessage { public static final int ANIMATION = 0x00F2; public static final int BUFF_BUILDER_START = 0x025C; public static final int BUFF_BUILDER_CHANGE = 0x025A; + public static final int UI_PLAY_EFFECT = 0x0401; public ObjControllerMessage() { diff --git a/src/protocol/swg/ParametersMessage.java b/src/protocol/swg/ParametersMessage.java index fbc87a36..0d4abb53 100644 --- a/src/protocol/swg/ParametersMessage.java +++ b/src/protocol/swg/ParametersMessage.java @@ -40,7 +40,7 @@ public class ParametersMessage extends SWGMessage { IoBuffer packet = IoBuffer.allocate(10).order(ByteOrder.LITTLE_ENDIAN); packet.putShort((short) 2); - packet.putInt(0x7102B15F); + packet.putInt(0x487652DA); packet.putInt(0x00000384); return packet.flip(); diff --git a/src/protocol/swg/SceneDestroyObject.java b/src/protocol/swg/SceneDestroyObject.java index e5fbfd02..2048f614 100644 --- a/src/protocol/swg/SceneDestroyObject.java +++ b/src/protocol/swg/SceneDestroyObject.java @@ -45,6 +45,7 @@ public class SceneDestroyObject extends SWGMessage { result.putInt(0x4D45D504); result.putLong(objectId); + result.put((byte) 0); // unk return result.flip(); } } diff --git a/src/protocol/swg/objectControllerObjects/UiPlayEffect.java b/src/protocol/swg/objectControllerObjects/UiPlayEffect.java new file mode 100644 index 00000000..a4b776fd --- /dev/null +++ b/src/protocol/swg/objectControllerObjects/UiPlayEffect.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * 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 protocol.swg.objectControllerObjects; + +import java.nio.ByteOrder; + +import org.apache.mina.core.buffer.IoBuffer; + +import protocol.swg.ObjControllerMessage; + +public class UiPlayEffect extends ObjControllerObject { + + private long objectId; + private String uiString; + + public UiPlayEffect(long objectId, String uiString) { + this.uiString = uiString; + this.objectId = objectId; + } + + @Override + public void deserialize(IoBuffer data) { + // TODO Auto-generated method stub + + } + + @Override + public IoBuffer serialize() { + + IoBuffer result = IoBuffer.allocate(26 + uiString.length()).order(ByteOrder.LITTLE_ENDIAN); + + result.putInt(ObjControllerMessage.UI_PLAY_EFFECT); + result.putLong(objectId); + result.putInt(0); + result.putLong(objectId); + result.put(getAsciiString(uiString)); + + return result.flip(); + + } +} diff --git a/src/resources/objects/building/BuildingMessageBuilder.java b/src/resources/objects/building/BuildingMessageBuilder.java index d044e0ac..5a751d8f 100644 --- a/src/resources/objects/building/BuildingMessageBuilder.java +++ b/src/resources/objects/building/BuildingMessageBuilder.java @@ -107,7 +107,7 @@ public class BuildingMessageBuilder extends ObjectMessageBuilder { int size = buffer.position(); buffer = IoBuffer.allocate(size).put(buffer.array(), 0, size); buffer.flip(); - buffer = createBaseline("TANO", (byte) 8, buffer, size); + buffer = createBaseline("BUIO", (byte) 8, buffer, size); return buffer; } @@ -118,7 +118,7 @@ public class BuildingMessageBuilder extends ObjectMessageBuilder { int size = buffer.position(); buffer = IoBuffer.allocate(size).put(buffer.array(), 0, size); buffer.flip(); - buffer = createBaseline("TANO", (byte) 9, buffer, size); + buffer = createBaseline("BUIO", (byte) 9, buffer, size); return buffer; } diff --git a/src/resources/objects/creature/CreatureMessageBuilder.java b/src/resources/objects/creature/CreatureMessageBuilder.java index 5582100e..1d7deeb0 100644 --- a/src/resources/objects/creature/CreatureMessageBuilder.java +++ b/src/resources/objects/creature/CreatureMessageBuilder.java @@ -97,7 +97,8 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer.put(getAsciiString(creature.getStfName())); if (creature.getCustomName() == null) { creature.setCustomName(""); }//Not all CreatureObjects have CustomName (Shuttles) buffer.put(getUnicodeString(creature.getCustomName())); - buffer.putInt(0x000F4240); // volume + // buffer.putInt(0x000F4240); // volume + buffer.putInt(1); buffer.putInt(CRC.StringtoCRC(creature.getFaction())); buffer.putInt(creature.getFactionStatus()); @@ -110,11 +111,11 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer.putShort((short) customizationData.length); buffer.put(customizationData); } - buffer.putInt(1); + //buffer.putInt(1); buffer.putInt(0); // TANO Data buffer.putInt(0); - // buffer.putInt(creature.getOptionsBitmask()); // 0x80 = Player, 0x08 = Quest NPC, - buffer.putInt(0x80); + buffer.putInt(creature.getOptionsBitmask()); // 0x80 = Player, 0x08 = Quest NPC, + //buffer.putInt(0x80); buffer.putInt(creature.getIncapTimer()); buffer.putInt(0); buffer.putInt(0x3A98); @@ -126,8 +127,8 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { buffer.putLong(creature.getOwnerId()); float height = creature.getHeight(); - if (height < 0.7 || height > 1.5) - height = 1; + //if (height < 0.7 || height > 1.5) + // height = 1; buffer.putFloat(height); buffer.putInt(0); // battle fatigue buffer.putLong(creature.getStateBitmask()); @@ -296,7 +297,7 @@ public class CreatureMessageBuilder extends ObjectMessageBuilder { for(SWGObject obj : creature.getEquipmentList().get()) { - if(obj instanceof TangibleObject) { + if(obj instanceof TangibleObject && !(obj instanceof WeaponObject)) { TangibleObject tangible = (TangibleObject) obj; if(tangible.getCustomization() == null || tangible.getCustomization().length == 0) { buffer.putShort((short) 0); diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index 9bb8186f..ece8a6a4 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -166,6 +166,7 @@ public class CreatureObject extends TangibleObject implements IPersistent { public CreatureObject(long objectID, Planet planet, Point3D position, Quaternion orientation, String Template) { super(objectID, planet, Template, position, orientation); messageBuilder = new CreatureMessageBuilder(this); + loadTemplateData(); skills = new SWGList(messageBuilder, 1, 3); skillMods = new SWGList(messageBuilder, 4, 3); abilities = new SWGList(messageBuilder, 4, 14); @@ -180,6 +181,19 @@ public class CreatureObject extends TangibleObject implements IPersistent { messageBuilder = new CreatureMessageBuilder(this); } + private void loadTemplateData() { + + /*if(getTemplateData().getAttribute("scale") != null) + setHeight((float) getTemplateData().getAttribute("scale")); + if(getTemplateData().getAttribute("speed") != null) { + //System.out.println(getTemplateData().getAttribute("speed")); + setRunSpeed((float) getTemplateData().getAttribute("speed")); + } + if(getTemplateData().getAttribute("turnRate") != null) + setTurnRadius((float) getTemplateData().getAttribute("turnRate"));*/ + + } + public void setCustomName2(String customName) { setCustomName(customName); @@ -333,6 +347,8 @@ public class CreatureObject extends TangibleObject implements IPersistent { if (this.posture == 0x09) { needsStopPerformance = true; } + if(this.posture == posture) + return; this.posture = posture; } @@ -1085,10 +1101,7 @@ public class CreatureObject extends TangibleObject implements IPersistent { } //destination.getSession().write(messageBuilder.buildBaseline8()); //destination.getSession().write(messageBuilder.buildBaseline9()); - - UpdatePostureMessage upm = new UpdatePostureMessage(getObjectID(), (byte) 0); - destination.getSession().write(upm.serialize()); - + if(destination != getClient()) { UpdatePVPStatusMessage upvpm = new UpdatePVPStatusMessage(getObjectID(), getPvPBitmask(), getFaction()); if(getSlottedObject("ghost") != null) @@ -1134,6 +1147,8 @@ public class CreatureObject extends TangibleObject implements IPersistent { */ destination.getSession().write(upvpm.serialize()); + UpdatePostureMessage upm = new UpdatePostureMessage(getObjectID(), (byte) 0); + destination.getSession().write(upm.serialize()); } } diff --git a/src/resources/objects/player/PlayerMessageBuilder.java b/src/resources/objects/player/PlayerMessageBuilder.java index 2493d3a7..ace201df 100644 --- a/src/resources/objects/player/PlayerMessageBuilder.java +++ b/src/resources/objects/player/PlayerMessageBuilder.java @@ -200,8 +200,8 @@ public class PlayerMessageBuilder extends ObjectMessageBuilder { } } - buffer.putInt(100); // Current force power ? - buffer.putInt(100); // Max force power ? + buffer.putInt(0); // Current force power ? + buffer.putInt(0); // Max force power ? buffer.putInt(0); // Current FS Quest List size ? buffer.putInt(0); // Current FS Quest List update counter ? @@ -292,18 +292,6 @@ public class PlayerMessageBuilder extends ObjectMessageBuilder { buffer.putInt(0); buffer.putInt(0); - buffer.putInt(3); - buffer.putInt(0); - buffer.putInt(0); - - buffer.putInt(0); - buffer.putInt(0); - buffer.putInt(0); - buffer.putInt(0); - buffer.putInt(0); - - buffer.putInt(0); - buffer.putInt(2); buffer.putInt(0); buffer.putInt(0); buffer.putInt(0); @@ -314,7 +302,19 @@ public class PlayerMessageBuilder extends ObjectMessageBuilder { buffer.putInt(0); buffer.putInt(0); - buffer.putInt(4); // jedi state??? + buffer.putInt(0); + buffer.putInt(0); + buffer.putInt(0); + buffer.putInt(0); + buffer.putInt(0); + + buffer.putInt(0); + buffer.putInt(0); + buffer.putInt(0); + buffer.putInt(0); + buffer.putInt(0); + + buffer.putInt(0); // jedi state??? buffer.putShort((short) 0); int size = buffer.position(); @@ -362,24 +362,20 @@ public class PlayerMessageBuilder extends ObjectMessageBuilder { PlayerObject player = (PlayerObject) object; player.setXpListUpdateCounter(player.getXpListUpdateCounter() + 1); - // Some problem with createDelta() - IoBuffer result = bufferPool.allocate(42 + type.length(), false).order(ByteOrder.LITTLE_ENDIAN); - result.putShort((short) 5); - result.putInt(CRC.StringtoCRC("BaselinesMessage")); - result.putLong(object.getContainer().getObjectID()); - result.put("YALP".getBytes()); - result.put((byte) 8); - result.putInt(19 + type.length()); - result.putShort((short) 1); - result.putShort((short) 0); + IoBuffer result = bufferPool.allocate(17 + type.length(), false).order(ByteOrder.LITTLE_ENDIAN); + result.putInt(1); result.putInt(player.getXpListUpdateCounter()); result.put((byte) ((alreadyExists) ? 2 : 0)); - result.putShort((short) type.length()); - result.put(type.getBytes()); + result.put(getAsciiString(type)); result.putInt(amount); - return result.flip(); + int size = result.position(); + result.flip(); + + result = createDelta("PLAY", (byte) 8, (short) 1, (short) 0, result, size + 4); + + return result; } public IoBuffer buildWaypointAddDelta(WaypointObject waypoint) { diff --git a/src/resources/objects/player/PlayerObject.java b/src/resources/objects/player/PlayerObject.java index 44cd7b84..54738f72 100644 --- a/src/resources/objects/player/PlayerObject.java +++ b/src/resources/objects/player/PlayerObject.java @@ -195,7 +195,8 @@ public class PlayerObject extends IntangibleObject { synchronized(objectMutex) { this.totalPlayTime = totalPlayTime; } - notifyObservers(messageBuilder.buildTotalPlayTimeDelta(totalPlayTime), true); + //notifyObservers(messageBuilder.buildTotalPlayTimeDelta(totalPlayTime), true); + getContainer().getClient().getSession().write(messageBuilder.buildTotalPlayTimeDelta(totalPlayTime)); } public String getHome() { @@ -596,13 +597,12 @@ public class PlayerObject extends IntangibleObject { if(destination == null || destination.getSession() == null) return; - - //if(destination.getParent().getObjectID() == getParentId()) { // only send to self - destination.getSession().write(messageBuilder.buildBaseline3()); - destination.getSession().write(messageBuilder.buildBaseline6()); + destination.getSession().write(messageBuilder.buildBaseline3()); + destination.getSession().write(messageBuilder.buildBaseline6()); + if(destination.getParent().getObjectID() == getParentId()) { // only send to self destination.getSession().write(messageBuilder.buildBaseline8()); destination.getSession().write(messageBuilder.buildBaseline9()); - //} + } } diff --git a/src/resources/objects/tangible/TangibleMessageBuilder.java b/src/resources/objects/tangible/TangibleMessageBuilder.java index 720a366a..2a930abf 100644 --- a/src/resources/objects/tangible/TangibleMessageBuilder.java +++ b/src/resources/objects/tangible/TangibleMessageBuilder.java @@ -53,7 +53,7 @@ public class TangibleMessageBuilder extends ObjectMessageBuilder { buffer.putInt(0); buffer.putInt(0); // faction vars - if(tangible.getCustomization() == null || tangible.getCustomization().length < 1) + if(tangible.getCustomization() == null || tangible.getCustomization().length <= 0) buffer.putShort((short) 0); else { buffer.putShort((short) tangible.getCustomization().length); @@ -64,6 +64,8 @@ public class TangibleMessageBuilder extends ObjectMessageBuilder { buffer.putInt(0); //buffer.putInt(0); + if(tangible.getOptionsBitmask() == 0) + tangible.setOptionsBitmask(0x100); buffer.putInt(tangible.getOptionsBitmask()); buffer.putInt(0); // number of item uses buffer.putInt(tangible.getConditionDamage()); diff --git a/src/resources/objects/tangible/TangibleObject.java b/src/resources/objects/tangible/TangibleObject.java index fcb47aef..e766c0ad 100644 --- a/src/resources/objects/tangible/TangibleObject.java +++ b/src/resources/objects/tangible/TangibleObject.java @@ -34,6 +34,7 @@ import protocol.swg.objectControllerObjects.ShowFlyText; import resources.common.RGB; import resources.objects.creature.CreatureObject; +import services.ai.AIActor; import com.sleepycat.persist.model.NotPersistent; import com.sleepycat.persist.model.Persistent; @@ -226,7 +227,7 @@ public class TangibleObject extends SWGObject { } public void addDefender(TangibleObject defender) { - + defendersList.add(defender); if(this instanceof CreatureObject) { @@ -357,8 +358,8 @@ public class TangibleObject extends SWGObject { destination.getSession().write(messageBuilder.buildBaseline3()); destination.getSession().write(messageBuilder.buildBaseline6()); - //destination.getSession().write(messageBuilder.buildBaseline8()); - //destination.getSession().write(messageBuilder.buildBaseline9()); + destination.getSession().write(messageBuilder.buildBaseline8()); + destination.getSession().write(messageBuilder.buildBaseline9()); if(getPvPBitmask() != 0) { UpdatePVPStatusMessage upvpm = new UpdatePVPStatusMessage(getObjectID()); diff --git a/src/services/CharacterService.java b/src/services/CharacterService.java index 3f803056..3c9b93a0 100644 --- a/src/services/CharacterService.java +++ b/src/services/CharacterService.java @@ -264,7 +264,6 @@ public class CharacterService implements INetworkDispatch { if(clientCreateCharacter.getHairCustomization().length > 0) hair.setCustomization(clientCreateCharacter.getHairCustomization()); object._add(hair); - object.addObjectToEquipList(hair); } TangibleObject inventory = (TangibleObject) core.objectService.createObject("object/tangible/inventory/shared_character_inventory.iff", object.getPlanet()); @@ -273,10 +272,13 @@ public class CharacterService implements INetworkDispatch { appInventory.setContainerPermissions(CreaturePermissions.CREATURE_PERMISSIONS); TangibleObject datapad = (TangibleObject) core.objectService.createObject("object/tangible/datapad/shared_character_datapad.iff", object.getPlanet()); datapad.setContainerPermissions(CreatureContainerPermissions.CREATURE_CONTAINER_PERMISSIONS); + datapad.setStaticObject(false); TangibleObject bank = (TangibleObject) core.objectService.createObject("object/tangible/bank/shared_character_bank.iff", object.getPlanet()); bank.setContainerPermissions(CreatureContainerPermissions.CREATURE_CONTAINER_PERMISSIONS); + bank.setStaticObject(false); TangibleObject missionBag = (TangibleObject) core.objectService.createObject("object/tangible/mission_bag/shared_mission_bag.iff", object.getPlanet()); missionBag.setContainerPermissions(CreatureContainerPermissions.CREATURE_CONTAINER_PERMISSIONS); + missionBag.setStaticObject(false); object._add(inventory); object._add(appInventory); diff --git a/src/services/ConnectionService.java b/src/services/ConnectionService.java index dc249362..c3ce890c 100644 --- a/src/services/ConnectionService.java +++ b/src/services/ConnectionService.java @@ -79,8 +79,8 @@ public class ConnectionService implements INetworkDispatch { synchronized(core.getActiveConnectionsMap()) { for(Client c : core.getActiveConnectionsMap().values()) { if(c.getParent() != null) { - if ((System.currentTimeMillis() - c.getSession().getLastReadTime()) > 300000 && c.getSession().getAttribute("disconnectTask") == null) { - disconnect(c.getSession()); + if ((System.currentTimeMillis() - c.getSession().getLastReadTime()) > 300000) { + disconnect(c); } } } @@ -176,13 +176,10 @@ public class ConnectionService implements INetworkDispatch { } - public void disconnect(IoSession session) { - Client client = core.getClient(session); - - if(client == null) - return; - - if(client.getParent() == null) + public void disconnect(Client client) { + //Client client = core.getClient(session); + IoSession session = client.getSession(); + if(session == null || client.getParent() == null) return; CreatureObject object = (CreatureObject) client.getParent(); diff --git a/src/services/EntertainmentService.java b/src/services/EntertainmentService.java index 2ada525d..2f6adb3b 100644 --- a/src/services/EntertainmentService.java +++ b/src/services/EntertainmentService.java @@ -336,7 +336,7 @@ public class EntertainmentService implements INetworkDispatch { } - },10, 10000, TimeUnit.MILLISECONDS); + },10000, 10000, TimeUnit.MILLISECONDS); entertainer.setEntertainerExperience(experienceTask); diff --git a/src/services/LoginService.java b/src/services/LoginService.java index b62fe7da..7bb0a2ef 100644 --- a/src/services/LoginService.java +++ b/src/services/LoginService.java @@ -196,7 +196,7 @@ public class LoginService implements INetworkDispatch{ if (object != null) { if (object.isInQuadtree() && object.getClient() != null) { - core.connectionService.disconnect(object.getClient().getSession()); + core.connectionService.disconnect(object.getClient()); } if (object.isInQuadtree()) { diff --git a/src/services/PlayerService.java b/src/services/PlayerService.java index 5c861834..b209ee48 100644 --- a/src/services/PlayerService.java +++ b/src/services/PlayerService.java @@ -100,7 +100,7 @@ public class PlayerService implements INetworkDispatch { creature.getClient().getSession().write(packet); } - }, 0, 45, TimeUnit.SECONDS); + }, 45, 45, TimeUnit.SECONDS); scheduler.scheduleAtFixedRate(new Runnable() { @@ -123,8 +123,13 @@ public class PlayerService implements INetworkDispatch { public void run() { synchronized(creature.getMutex()) { - if(creature.getAction() < creature.getMaxAction() && creature.getPosture() != 14) - creature.setAction(creature.getAction() + 200); + if(creature.getAction() < creature.getMaxAction() && creature.getPosture() != 14) { + if(creature.getCombatFlag() == 0) + creature.setAction(creature.getAction() + (15 + creature.getLevel() * 5)); + else + creature.setAction(creature.getAction() + ((15 + creature.getLevel() * 5) / 2)); + + } } } @@ -138,18 +143,25 @@ public class PlayerService implements INetworkDispatch { synchronized(creature.getMutex()) { if(creature.getHealth() < creature.getMaxHealth() && creature.getCombatFlag() == 0 && creature.getPosture() != 13 && creature.getPosture() != 14) - creature.setHealth(creature.getHealth() + 300); + creature.setHealth(creature.getHealth() + (36 + creature.getLevel() * 4)); } } }, 0, 1000, TimeUnit.MILLISECONDS); - PlayerObject ghost = (PlayerObject) creature.getSlottedObject("ghost"); + /*final PlayerObject ghost = (PlayerObject) creature.getSlottedObject("ghost"); + scheduler.schedule(new Runnable() { - if (ghost.isSet(PlayerFlags.LD)) { - ghost.toggleFlag(PlayerFlags.LD); - } + @Override + public void run() { + if (ghost.isSet(PlayerFlags.LD)) { + ghost.toggleFlag(PlayerFlags.LD); + } + + } + + }, 1, TimeUnit.SECONDS);*/ } diff --git a/src/services/SimulationService.java b/src/services/SimulationService.java index b3adb121..5e6bc68a 100644 --- a/src/services/SimulationService.java +++ b/src/services/SimulationService.java @@ -193,7 +193,7 @@ public class SimulationService implements INetworkDispatch { Vector childObjects = (Vector) object.getAttachment("childObjects"); if(childObjects != null) { addChildObjects(object, childObjects); - object.setAttachment("childObjects", null); + //object.setAttachment("childObjects", null); } if(notifyObservers) { Point3D pos = new Point3D(x, 0, y); @@ -303,6 +303,8 @@ public class SimulationService implements INetworkDispatch { Point3D oldPos; synchronized(object.getMutex()) { newPos = new Point3D(dataTransform.getXPosition(), dataTransform.getYPosition(), dataTransform.getZPosition()); + if(Float.isNaN(newPos.x) || Float.isNaN(newPos.y) || Float.isNaN(newPos.z)) + return; oldPos = object.getPosition(); //Collection oldObservers = object.getObservers(); //Collection newObservers = new HashSet(); @@ -396,6 +398,8 @@ public class SimulationService implements INetworkDispatch { CreatureObject object = (CreatureObject) client.getParent(); Point3D newPos = new Point3D(dataTransform.getXPosition(), dataTransform.getYPosition(), dataTransform.getZPosition()); + if(Float.isNaN(newPos.x) || Float.isNaN(newPos.y) || Float.isNaN(newPos.z)) + return; Point3D oldPos = object.getPosition(); Quaternion newOrientation = new Quaternion(dataTransform.getWOrientation(), dataTransform.getXOrientation(), dataTransform.getYOrientation(), dataTransform.getZOrientation()); @@ -469,7 +473,108 @@ public class SimulationService implements INetworkDispatch { }); } + + public void moveObject(SWGObject object, Point3D newPosition, Quaternion newOrientation, int movementCounter, float speed, CellObject cell) { + + if(Float.isNaN(newPosition.x) || Float.isNaN(newPosition.y) || Float.isNaN(newPosition.z)) + return; + if(cell == null) { + + Point3D oldPos; + synchronized(object.getMutex()) { + oldPos = object.getPosition(); + if(object.getContainer() == null) + move(object, oldPos.x, oldPos.z, newPosition.x, newPosition.z); + object.setPosition(newPosition); + object.setOrientation(newOrientation); + object.setMovementCounter(movementCounter + 1); + } + if(object.getContainer() != null && newPosition != oldPos) { + object.getContainer()._remove(object); + add(object, newPosition.x, newPosition.z); + } + + UpdateTransformMessage utm = new UpdateTransformMessage(object.getObjectID(), (short) (newPosition.x * 4 + 0.5), (short) (newPosition.y * 4 + 0.5), (short) (newPosition.z * 4 + 0.5), movementCounter + 1, getSpecialDirection(newOrientation), speed); + + List newAwareObjects = get(object.getPlanet(), newPosition.x, newPosition.z, 512); + ArrayList oldAwareObjects = new ArrayList(object.getAwareObjects()); + Collection updateAwareObjects = CollectionUtils.intersection(oldAwareObjects, newAwareObjects); + object.notifyObservers(utm, false); + + for(int i = 0; i < oldAwareObjects.size(); i++) { + SWGObject obj = oldAwareObjects.get(i); + if(!updateAwareObjects.contains(obj) && obj != object && obj.getWorldPosition().getDistance2D(newPosition) > 200 && obj.isInQuadtree() /*&& obj.getParentId() == 0*/) { + if(obj.getAttachment("bigSpawnRange") != null && obj.getWorldPosition().getDistance2D(newPosition) < 512) + continue; + object.makeUnaware(obj); + if(obj.getClient() != null) + obj.makeUnaware(object); + } else if(obj != object && obj.getWorldPosition().getDistance2D(newPosition) > 200 && obj.isInQuadtree() && obj.getAttachment("bigSpawnRange") == null) { + object.makeUnaware(obj); + if(obj.getClient() != null) + obj.makeUnaware(object); + } + } + for(int i = 0; i < newAwareObjects.size(); i++) { + SWGObject obj = newAwareObjects.get(i); + //System.out.println(obj.getTemplate()); + if(!updateAwareObjects.contains(obj) && obj != object && !object.getAwareObjects().contains(obj) && obj.getContainer() != object && obj.isInQuadtree()) { + if(obj.getAttachment("bigSpawnRange") == null && obj.getWorldPosition().getDistance2D(newPosition) > 200) + continue; + object.makeAware(obj); + if(obj.getClient() != null) + obj.makeAware(object); + } + } + + checkForCollidables(object); + MoveEvent event = new MoveEvent(); + event.object = object; + object.getEventBus().publish(event); + + + } else { + + newPosition.setCell(cell); + Point3D oldPos = object.getPosition(); + object.setPosition(newPosition); + object.setOrientation(newOrientation); + object.setMovementCounter(movementCounter + 1); + + UpdateTransformWithParentMessage utm = new UpdateTransformWithParentMessage(object.getObjectID(), cell.getObjectID(), (short) (newPosition.x * 8 + 0.5), (short) (newPosition.y * 8 + 0.5), (short) (newPosition.z * 8 + 0.5), movementCounter + 1, getSpecialDirection(newOrientation), speed); + + if(object.getContainer() != cell) { + remove(object, oldPos.x, oldPos.z); + if(object.getContainer() != null) + object.getContainer()._remove(object); + cell._add(object); + } + object.notifyObservers(utm, false); + + checkForCollidables(object); + + } + + } + + public byte getSpecialDirection(Quaternion orientation) { + byte movementAngle = (byte) 0.0f; + float wOrient = orientation.w; + float yOrient = orientation.y; + float sq = (float) Math.sqrt(1- (orientation.w * orientation.w)); + + if (sq != 0) { + if (orientation.w > 0 && orientation.y < 0) { + wOrient *= -1; + yOrient *= -1; + } + movementAngle = (byte) ((yOrient / sq) * (2 * Math.acos(wOrient) / 0.06283f)); + } + + return movementAngle; + } + @Override public void shutdown() { // TODO Auto-generated method stub @@ -545,6 +650,28 @@ public class SimulationService implements INetworkDispatch { return new Ray(origin, direction); } + + public Point3D convertPointToModelSpace(Point3D point, SWGObject object) { + + Point3D position = object.getPosition(); + + WB_M44 translateMatrix = new WB_M44(1, 0, 0, position.x, 0, 1, 0, position.y, 0, 0, 1, position.z, 0, 0, 0, 1); + + float radians = object.getRadians(); + float sin = (float) Math.sin(radians); + float cos = (float) Math.cos(radians); + + WB_M44 rotationMatrix = new WB_M44(cos, 0, sin, 0, 0, 1, 0, 0, -sin, 0, cos, 0, 0, 0, 0, 1); + + WB_M44 modelSpace = translateMatrix.mult(rotationMatrix).inverse(); + + float x = (float) (modelSpace.m11 * point.x + modelSpace.m12 * point.y + modelSpace.m13 * point.z + modelSpace.m14); + float y = (float) (modelSpace.m21 * point.x + modelSpace.m22 * point.y + modelSpace.m23 * point.z + modelSpace.m24); + float z = (float) (modelSpace.m31 * point.x + modelSpace.m32 * point.y + modelSpace.m33 * point.z + modelSpace.m34); + + return new Point3D(x, y, z); + + } /* * Moved this to ConnectionService which will disconnect them @@ -557,7 +684,7 @@ public class SimulationService implements INetworkDispatch { * and continues sending packets. */ public void handleDisconnect(final IoSession session) { - Client client = core.getClient(session); + final Client client = core.getClient(session); if(client == null) return; @@ -565,11 +692,11 @@ public class SimulationService implements INetworkDispatch { if(client.getParent() == null) return; - CreatureObject object = (CreatureObject) client.getParent(); + final CreatureObject object = (CreatureObject) client.getParent(); PlayerObject ghost = (PlayerObject) object.getSlottedObject("ghost"); //session.suspendWrite(); - + final long objectId = object.getObjectID(); if(!ghost.isSet(PlayerFlags.LD)) ghost.toggleFlag(PlayerFlags.LD); @@ -582,9 +709,11 @@ public class SimulationService implements INetworkDispatch { ScheduledFuture disconnectTask = scheduler.schedule(new Runnable() { @Override public void run() { - core.connectionService.disconnect(session); + if(core.objectService.getObject(objectId).getAttachment("disconnectTask") != null) + core.connectionService.disconnect(client); } }, 5, TimeUnit.MINUTES); + core.removeClient(session); object.setAttachment("disconnectTask", disconnectTask); @@ -626,7 +755,7 @@ public class SimulationService implements INetworkDispatch { object.playEffectObject("clienteffect/skill_granted.cef", ""); object.playMusic("sound/music_acq_bountyhunter.snd"); core.skillService.addSkill(object, ghost.getProfessionWheelPosition()); - } + } } public void transferToPlanet(SWGObject object, Planet planet, Point3D newPos, Quaternion newOrientation, SWGObject newParent) { diff --git a/src/services/TerrainService.java b/src/services/TerrainService.java index c5340311..a570495a 100644 --- a/src/services/TerrainService.java +++ b/src/services/TerrainService.java @@ -31,10 +31,12 @@ import java.util.concurrent.ConcurrentHashMap; import resources.common.FileUtilities; import resources.common.collidables.CollidableCircle; import resources.objects.building.BuildingObject; +import resources.objects.creature.CreatureObject; import engine.clientdata.ClientFileManager; import engine.clientdata.visitors.DatatableVisitor; import engine.resources.config.Config; +import engine.resources.container.Traverser; import engine.resources.objects.SWGObject; import engine.resources.scene.Planet; import engine.resources.scene.Point3D; @@ -235,10 +237,23 @@ public class TerrainService { continue; BuildingObject building = (BuildingObject) object; - + final List creatures = new ArrayList(); + building.viewChildren(building, true, true, new Traverser() { + + @Override + public void process(SWGObject obj) { + if(obj instanceof CreatureObject) + creatures.add((CreatureObject) obj); + } + + }); + for(CreatureObject creature : creatures) { + long parentId = creature.getParentId(); + creature.getContainer().remove(creature); + creature.setParentId(parentId); + } if(building.getTransaction() == null) continue; - building.createTransaction(core.getBuildingODB().getEnvironment()); core.getBuildingODB().put(building, Long.class, BuildingObject.class, building.getTransaction()); building.getTransaction().commitSync(); @@ -265,6 +280,15 @@ public class TerrainService { return true; } + + public boolean isWater(int planetId, Point3D worldPosition) { + if(getPlanetByID(planetId) == null) + return false; + + Planet planet = getPlanetByID(planetId); + + return planet.getTerrainVisitor().isWater(worldPosition.x, worldPosition.z); + } diff --git a/src/services/ai/AIActor.java b/src/services/ai/AIActor.java index 39dd02ee..6fd3eb29 100644 --- a/src/services/ai/AIActor.java +++ b/src/services/ai/AIActor.java @@ -21,9 +21,31 @@ ******************************************************************************/ package services.ai; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import main.NGECore; +import net.engio.mbassy.listener.Handler; + +import engine.resources.objects.SWGObject; import engine.resources.scene.Point3D; +import engine.resources.scene.Quaternion; +import resources.objects.cell.CellObject; import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; import services.ai.states.AIState; +import services.ai.states.AIState.StateResult; +import services.ai.states.AttackState; +import services.ai.states.DeathState; +import services.ai.states.IdleState; +import services.ai.states.RetreatState; +import services.ai.states.SpawnState; +import services.combat.CombatEvents.DamageTaken; +import services.spawn.MobileTemplate; public class AIActor { @@ -31,10 +53,19 @@ public class AIActor { private Point3D spawnPosition; private volatile AIState currentState; private CreatureObject followObject; + private Vector movementPoints = new Vector(); + private MobileTemplate mobileTemplate; + private ScheduledExecutorService scheduler; + private Map damageMap = new ConcurrentHashMap(); + private volatile boolean hasReachedPosition; + private long lastAttackTimestamp; - public AIActor(CreatureObject creature, Point3D spawnPosition) { + public AIActor(CreatureObject creature, Point3D spawnPosition, ScheduledExecutorService scheduler) { this.creature = creature; this.spawnPosition = spawnPosition; + this.scheduler = scheduler; + creature.getEventBus().subscribe(this); + this.currentState = new IdleState(); } public CreatureObject getCreature() { @@ -52,9 +83,42 @@ public class AIActor { public void setSpawnPosition(Point3D spawnPosition) { this.spawnPosition = spawnPosition; } - - public void doAggro(CreatureObject defender) { + + public void addDefender(CreatureObject defender) { creature.addDefender(defender); + if(followObject == null) + setFollowObject(defender); + setCurrentState(new AttackState()); + } + + public void removeDefender(CreatureObject defender) { + creature.removeDefender(defender); + damageMap.remove(defender); + defender.removeDefender(creature); + if(followObject == defender) { + setFollowObject(getHighestDamageDealer()); + if(creature.getDefendersList().size() == 0) + setCurrentState(new RetreatState()); + } + } + + public CreatureObject getHighestDamageDealer() { + CreatureObject highestDamageDealer = null; + int highestDamage = 0; + for(Entry e : damageMap.entrySet()) { + if(e.getValue() > highestDamage && highestDamage > 0) { + highestDamage = e.getValue(); + highestDamageDealer = e.getKey(); + } + } + // 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 AIState getCurrentState() { @@ -62,11 +126,12 @@ public class AIActor { } public void setCurrentState(AIState currentState) { - if(currentState == this.currentState) + if(currentState.getClass() == this.currentState.getClass()) return; - this.currentState.onExit(); + if(this.currentState != null) + doStateAction(this.currentState.onExit(this)); this.currentState = currentState; - currentState.onEnter(); + doStateAction(currentState.onEnter(this)); } public CreatureObject getFollowObject() { @@ -77,4 +142,116 @@ public class AIActor { 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 scheduleMovement() { + scheduler.schedule(new Runnable() { + + @Override + public void run() { + doStateAction(currentState.move(AIActor.this)); + } + + }, 500, TimeUnit.MILLISECONDS); + } + + public void scheduleRecovery() { + scheduler.schedule(new Runnable() { + + @Override + public void run() { + doStateAction(currentState.recover(AIActor.this)); + } + + }, 2000, TimeUnit.MILLISECONDS); + + } + + public void setNextPosition(Point3D position) { + movementPoints.add(0, position); + } + + @Handler + public void handleDamage(DamageTaken event) { + CreatureObject attacker = 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) { + 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) { + + switch(result) { + + case StateResult.DEAD: + setCurrentState(new DeathState()); + case StateResult.FINISHED: + // TODO: add state transitions + case StateResult.UNFINISHED: + return; + case StateResult.IDLE: + setCurrentState(new IdleState()); + //case StateResult.NONE: + // System.out.println("State action returned error result"); + + } + + } } diff --git a/src/services/ai/AIService.java b/src/services/ai/AIService.java index ea980a89..7a97015d 100644 --- a/src/services/ai/AIService.java +++ b/src/services/ai/AIService.java @@ -21,9 +21,15 @@ ******************************************************************************/ package services.ai; +import java.util.Random; import java.util.Vector; +import resources.objects.cell.CellObject; +import resources.objects.creature.CreatureObject; + +import engine.resources.scene.Planet; import engine.resources.scene.Point3D; +import engine.resources.scene.Quaternion; import main.NGECore; @@ -36,6 +42,17 @@ public class AIService { this.core = core; } - + public Vector findPath(int planetId, Point3D pointA, Point3D pointB) { + + // TODO: implement cell pathfinding, returning straight line for now + Vector path = new Vector(); + path.add(pointA); + float x = pointB.x - 1 + new Random().nextFloat(); + float z = pointB.z - 1 + new Random().nextFloat(); + Point3D endPoint = new Point3D(x, core.terrainService.getHeight(planetId, x, z), z); + endPoint.setCell(pointB.getCell()); + path.add(endPoint); + return path; + } } diff --git a/src/services/ai/LairActor.java b/src/services/ai/LairActor.java index 09043e82..778de963 100644 --- a/src/services/ai/LairActor.java +++ b/src/services/ai/LairActor.java @@ -21,8 +21,14 @@ ******************************************************************************/ package services.ai; +import java.util.Random; import java.util.Vector; + +import engine.resources.scene.Point3D; +import main.NGECore; import net.engio.mbassy.listener.Handler; +import resources.common.SpawnPoint; +import resources.objects.creature.CreatureObject; import resources.objects.tangible.TangibleObject; import services.combat.CombatEvents.DamageTaken; @@ -33,6 +39,7 @@ public class LairActor { private int maxSpawns; private String creatureTemplate; private volatile int spawnWave = 0; + private short level; public LairActor(TangibleObject lairObject, String creatureTemplate) { this.lairObject = lairObject; @@ -40,10 +47,11 @@ public class LairActor { lairObject.getEventBus().subscribe(this); } - public LairActor(TangibleObject lairObject, String creatureTemplate, int maxSpawns) { + public LairActor(TangibleObject lairObject, String creatureTemplate, int maxSpawns, short level) { this.lairObject = lairObject; this.creatureTemplate = creatureTemplate; this.maxSpawns = maxSpawns; + this.level = level; lairObject.getEventBus().subscribe(this); } @@ -63,15 +71,17 @@ public class LairActor { @Handler public void handleLairDamageEvent(DamageTaken event) { + spawnNewCreatures(); + for(AIActor ai : creatures) { - ai.doAggro(event.attacker); + ai.addDefender(event.attacker); + event.attacker.addDefender(ai.getCreature()); } - spawnNewCreatures(); } - private void spawnNewCreatures() { + public void spawnNewCreatures() { if(creatures.size() >= maxSpawns) return; @@ -104,11 +114,28 @@ public class LairActor { return; } - - // TODO: spawn creatures + + int creatureAmount = 0; + int tries = 0; + do { + creatureAmount = new Random().nextInt(4) + (maxSpawns / 5); + tries++; + } + while(creatureAmount > maxSpawns && tries < 10); + + for(int i = 0; i < creatureAmount; i++) { + Point3D position = SpawnPoint.getRandomPosition(lairObject.getPosition(), 5, 30, lairObject.getPlanetId()); + CreatureObject creature = NGECore.getInstance().spawnService.spawnCreature(creatureTemplate, lairObject.getPlanet().getName(), 0, position.x, position.y, position.z, level); + if(creature == null || !creature.isInQuadtree()) { + System.out.println("NULL Creature"); + continue; + } + creatures.add((AIActor) creature.getAttachment("AI")); + } healLair(); + } private void healLair() { @@ -142,4 +169,12 @@ public class LairActor { public void setCreatureTemplate(String creatureTemplate) { this.creatureTemplate = creatureTemplate; } + + public short getLevel() { + return level; + } + + public void setLevel(short level) { + this.level = level; + } } diff --git a/src/services/ai/states/AIState.java b/src/services/ai/states/AIState.java index 3da9131c..a6a88631 100644 --- a/src/services/ai/states/AIState.java +++ b/src/services/ai/states/AIState.java @@ -21,12 +21,23 @@ ******************************************************************************/ package services.ai.states; +import java.util.Vector; + +import main.NGECore; + +import engine.resources.scene.Point3D; +import engine.resources.scene.Quaternion; +import resources.objects.cell.CellObject; +import resources.objects.creature.CreatureObject; +import resources.objects.weapon.WeaponObject; +import services.ai.AIActor; + public abstract class AIState { - public abstract byte onEnter(); - public abstract byte onExit(); - public abstract byte move(); - public abstract byte recover(); + public abstract byte onEnter(AIActor actor); + public abstract byte onExit(AIActor actor); + public abstract byte move(AIActor actor); + public abstract byte recover(AIActor actor); public enum StateResult {; @@ -42,6 +53,153 @@ public abstract class AIState { } + public boolean findNewPosition(AIActor actor, float speed, float stopDistance, Point3D newPosition) { + + speed *= 0.5; // 2 updates per second + CreatureObject 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; + //while(!finished && movementPoints.size() != 0) { + + targetPosition = movementPoints.firstElement(); + 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); + 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 + (travelDistance * (dx / deltaDist))); + newZ = (float) (oldPosition.z + (travelDistance * (dz / deltaDist))); + + } else { + newX = currentPathPosition.x; + newZ = currentPathPosition.z; + } + + } + + if(cell == null) { + float height = core.terrainService.getHeight(creature.getPlanetId(), newX, newX); + newY = height; + } else { + newY = currentPathPosition.y; + } + } + } + + } else { + newX = currentPathPosition.x; + newY = currentPathPosition.y; + newZ = currentPathPosition.z; + } + oldPosition = currentPathPosition; + } + //} + newPosition.x = newX; + newPosition.y = newY; + newPosition.z = newZ; + newPosition.setCell(cell); + + return true; + } + public void doMove(AIActor actor) { + + NGECore core = NGECore.getInstance(); + + CreatureObject creature = actor.getCreature(); + if(creature.getPosture() == 14 || creature.getPosture() == 13) { + actor.setFollowObject(null); + return; + } + CreatureObject target = actor.getFollowObject(); + float speed = (float) creature.getRunSpeed(); + float maxDistance = 6; + if(creature.getWeaponId() != 0) { + WeaponObject weapon = (WeaponObject) core.objectService.getObject(creature.getWeaponId()); + if(weapon != null) + maxDistance = weapon.getMaxRange() - 1; + } else if(creature.getSlottedObject("default_weapon") != null) { + WeaponObject weapon = (WeaponObject) creature.getSlottedObject("default_weapon"); + if(weapon != null) + maxDistance = weapon.getMaxRange() - 1; + } + Point3D currentPosition = creature.getWorldPosition(); + + if(target != null && !core.simulationService.checkLineOfSight(creature, target)) + maxDistance = 1; + + Point3D newPosition = new Point3D(); + boolean foundNewPos = findNewPosition(actor, speed, maxDistance, newPosition); + + if(!foundNewPos) + return; + + Point3D newWorldPos = newPosition.getWorldPosition(); + float direction = (float) Math.atan2(newWorldPos.x - currentPosition.x, newWorldPos.z - currentPosition.z); + if(direction < 0) + direction = (float) (2 * Math.PI + direction); + 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; + } + + core.simulationService.moveObject(creature, newPosition, quaternion, creature.getMovementCounter(), 0, newPosition.getCell()); + + } } diff --git a/src/services/ai/states/AttackState.java b/src/services/ai/states/AttackState.java index fedb6112..96baf032 100644 --- a/src/services/ai/states/AttackState.java +++ b/src/services/ai/states/AttackState.java @@ -21,30 +21,131 @@ ******************************************************************************/ package services.ai.states; +import java.util.Random; +import java.util.Vector; + +import main.NGECore; + +import resources.objects.creature.CreatureObject; +import resources.objects.weapon.WeaponObject; +import services.ai.AIActor; + public class AttackState extends AIState { @Override - public byte onEnter() { - // TODO Auto-generated method stub - return 0; + public byte onEnter(AIActor actor) { + CreatureObject creature = actor.getCreature(); + if(creature.getPosture() == 14) + return StateResult.DEAD; + if(creature.getCombatFlag() == 0 || creature.getDefendersList().size() == 0 || actor.getFollowObject() == null) + return StateResult.FINISHED; + actor.scheduleMovement(); + actor.scheduleRecovery(); + return StateResult.UNFINISHED; } @Override - public byte onExit() { + public byte onExit(AIActor actor) { // TODO Auto-generated method stub - return 0; + return StateResult.FINISHED; } @Override - public byte move() { - // TODO Auto-generated method stub - return 0; + public byte move(AIActor actor) { + CreatureObject creature = actor.getCreature(); + if(creature.getPosture() == 14) + return StateResult.DEAD; + actor.getMovementPoints().clear(); + if(actor.getFollowObject() != null) { + if(actor.getSpawnPosition().getWorldPosition().getDistance(creature.getWorldPosition()) > 128 || NGECore.getInstance().terrainService.isWater(creature.getPlanetId(), actor.getFollowObject().getWorldPosition())) { + actor.removeDefender(actor.getFollowObject()); + //actor.scheduleMovement(); + return StateResult.UNFINISHED; + } + float maxDistance = 0; + if(creature.getWeaponId() != 0) { + WeaponObject weapon = (WeaponObject) NGECore.getInstance().objectService.getObject(creature.getWeaponId()); + if(weapon != null) + maxDistance = weapon.getMaxRange() - 1; + } else if(creature.getSlottedObject("default_weapon") != null) { + WeaponObject weapon = (WeaponObject) creature.getSlottedObject("default_weapon"); + if(weapon != null) + maxDistance = weapon.getMaxRange() - 1; + } + if(actor.getFollowObject().getWorldPosition().getDistance2D(creature.getWorldPosition()) > maxDistance) + actor.setNextPosition(actor.getFollowObject().getPosition()); + else { + //recover(actor); + actor.scheduleMovement(); + return StateResult.UNFINISHED; + } + + } + else + return StateResult.FINISHED; + doMove(actor); + actor.scheduleMovement(); + return StateResult.UNFINISHED; } @Override - public byte recover() { - // TODO Auto-generated method stub - return 0; + public byte recover(AIActor actor) { + if(actor.getTimeSinceLastAttack() < 2000) { + //actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + NGECore core = NGECore.getInstance(); + CreatureObject creature = actor.getCreature(); + if(creature.getPosture() == 14) + return StateResult.DEAD; + if(creature.getCombatFlag() == 0 || creature.getDefendersList().size() == 0 || actor.getFollowObject() == null) + return StateResult.FINISHED; + CreatureObject target = actor.getFollowObject(); + if(target != actor.getHighestDamageDealer() && actor.getHighestDamageDealer() != null) { + actor.setFollowObject(actor.getHighestDamageDealer()); + target = actor.getFollowObject(); + } + if(target == null) { + System.out.println("null target"); + actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + if(target.getWorldPosition().getDistance(creature.getWorldPosition()) > 128 || target.getPosture() == 13 || target.getPosture() == 14) { + actor.removeDefender(target); + actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + float maxDistance = 0; + if(creature.getWeaponId() != 0) { + WeaponObject weapon = (WeaponObject) NGECore.getInstance().objectService.getObject(creature.getWeaponId()); + if(weapon != null) + maxDistance = weapon.getMaxRange() - 1; + } else if(creature.getSlottedObject("default_weapon") != null) { + WeaponObject weapon = (WeaponObject) creature.getSlottedObject("default_weapon"); + if(weapon != null) + maxDistance = weapon.getMaxRange() - 1; + } + if(target.getWorldPosition().getDistance2D(creature.getWorldPosition()) > maxDistance) { + actor.scheduleRecovery(); + return StateResult.UNFINISHED; + } + actor.faceObject(target); + + Vector attacks = actor.getMobileTemplate().getAttacks(); + + if(attacks.size() == 0) { + core.commandService.callCommand(creature, actor.getMobileTemplate().getDefaultAttack(), target, ""); + } else { + Random rand = new Random(); + if(rand.nextFloat() <= 0.33f) { + core.commandService.callCommand(creature, attacks.get(rand.nextInt(attacks.size())), target, ""); + } else { + core.commandService.callCommand(creature, actor.getMobileTemplate().getDefaultAttack(), target, ""); + } + } + actor.setLastAttackTimestamp(System.currentTimeMillis()); + actor.scheduleRecovery(); + return StateResult.UNFINISHED; } } diff --git a/src/services/ai/states/DeathState.java b/src/services/ai/states/DeathState.java index aee6e323..e0924f66 100644 --- a/src/services/ai/states/DeathState.java +++ b/src/services/ai/states/DeathState.java @@ -21,28 +21,30 @@ ******************************************************************************/ package services.ai.states; +import services.ai.AIActor; + public class DeathState extends AIState { @Override - public byte onEnter() { + public byte onEnter(AIActor actor) { // TODO Auto-generated method stub return 0; } @Override - public byte onExit() { + public byte onExit(AIActor actor) { // TODO Auto-generated method stub return 0; } @Override - public byte move() { + public byte move(AIActor actor) { // TODO Auto-generated method stub return 0; } @Override - public byte recover() { + public byte recover(AIActor actor) { // TODO Auto-generated method stub return 0; } diff --git a/src/services/ai/states/IdleState.java b/src/services/ai/states/IdleState.java index 597630e9..28391739 100644 --- a/src/services/ai/states/IdleState.java +++ b/src/services/ai/states/IdleState.java @@ -21,28 +21,30 @@ ******************************************************************************/ package services.ai.states; +import services.ai.AIActor; + public class IdleState extends AIState { @Override - public byte onEnter() { + public byte onEnter(AIActor actor) { // TODO Auto-generated method stub return 0; } @Override - public byte onExit() { + public byte onExit(AIActor actor) { // TODO Auto-generated method stub return 0; } @Override - public byte move() { + public byte move(AIActor actor) { // TODO Auto-generated method stub return 0; } @Override - public byte recover() { + public byte recover(AIActor actor) { // TODO Auto-generated method stub return 0; } diff --git a/src/services/ai/states/PatrolState.java b/src/services/ai/states/PatrolState.java index 81e4eace..fef5cb1a 100644 --- a/src/services/ai/states/PatrolState.java +++ b/src/services/ai/states/PatrolState.java @@ -21,28 +21,30 @@ ******************************************************************************/ package services.ai.states; +import services.ai.AIActor; + public class PatrolState extends AIState { @Override - public byte onEnter() { + public byte onEnter(AIActor actor) { // TODO Auto-generated method stub return 0; } @Override - public byte onExit() { + public byte onExit(AIActor actor) { // TODO Auto-generated method stub return 0; } @Override - public byte move() { + public byte move(AIActor actor) { // TODO Auto-generated method stub return 0; } @Override - public byte recover() { + public byte recover(AIActor actor) { // TODO Auto-generated method stub return 0; } diff --git a/src/services/ai/states/RetreatState.java b/src/services/ai/states/RetreatState.java index 64e4fa71..ec4b93f3 100644 --- a/src/services/ai/states/RetreatState.java +++ b/src/services/ai/states/RetreatState.java @@ -21,28 +21,41 @@ ******************************************************************************/ package services.ai.states; +import resources.objects.creature.CreatureObject; +import services.ai.AIActor; + public class RetreatState extends AIState { @Override - public byte onEnter() { + public byte onEnter(AIActor actor) { + /*synchronized(actor.getDamageMap()) { + for(CreatureObject defender : actor.getDamageMap().keySet()) { + actor.removeDefender(defender); + } + }*/ + actor.setFollowObject(null); + actor.scheduleMovement(); + return StateResult.UNFINISHED; + } + + @Override + public byte onExit(AIActor actor) { // TODO Auto-generated method stub return 0; } @Override - public byte onExit() { - // TODO Auto-generated method stub - return 0; + public byte move(AIActor actor) { + actor.setNextPosition(actor.getSpawnPosition()); + doMove(actor); + if(actor.getCreature().getWorldPosition().getDistance2D(actor.getSpawnPosition()) > 4) { + actor.scheduleMovement(); + } + return StateResult.UNFINISHED; } @Override - public byte move() { - // TODO Auto-generated method stub - return 0; - } - - @Override - public byte recover() { + public byte recover(AIActor actor) { // TODO Auto-generated method stub return 0; } diff --git a/src/services/ai/states/SpawnState.java b/src/services/ai/states/SpawnState.java index 4d46a557..a006efa4 100644 --- a/src/services/ai/states/SpawnState.java +++ b/src/services/ai/states/SpawnState.java @@ -21,28 +21,30 @@ ******************************************************************************/ package services.ai.states; +import services.ai.AIActor; + public class SpawnState extends AIState { @Override - public byte onEnter() { + public byte onEnter(AIActor actor) { // TODO Auto-generated method stub return 0; } @Override - public byte onExit() { + public byte onExit(AIActor actor) { // TODO Auto-generated method stub return 0; } @Override - public byte move() { + public byte move(AIActor actor) { // TODO Auto-generated method stub return 0; } @Override - public byte recover() { + public byte recover(AIActor actor) { // TODO Auto-generated method stub return 0; } diff --git a/src/services/combat/CombatCommands.java b/src/services/combat/CombatCommands.java index d6cb5b25..af59b03f 100644 --- a/src/services/combat/CombatCommands.java +++ b/src/services/combat/CombatCommands.java @@ -21,6 +21,7 @@ ******************************************************************************/ package services.combat; +import services.command.CombatCommand; import main.NGECore; public class CombatCommands { @@ -29,6 +30,8 @@ public class CombatCommands { // Auto Attacks + core.commandService.registerCombatCommand("creatureRangedAttack"); + core.commandService.registerCombatCommand("creatureMeleeAttack").setDefaultAnimations(new String[] { "creature_attack_light" }); core.commandService.registerCombatCommand("rangedshotrifle"); core.commandService.registerCombatCommand("rangedshotpistol"); core.commandService.registerCombatCommand("rangedshotlightrifle"); diff --git a/src/services/combat/CombatEvents.java b/src/services/combat/CombatEvents.java index f41a0098..3dc20ee0 100644 --- a/src/services/combat/CombatEvents.java +++ b/src/services/combat/CombatEvents.java @@ -29,6 +29,7 @@ public class CombatEvents implements Event { public class DamageTaken implements Event { public CreatureObject attacker; + public int damage; } diff --git a/src/services/combat/CombatService.java b/src/services/combat/CombatService.java index 9e4d2ba2..e657b941 100644 --- a/src/services/combat/CombatService.java +++ b/src/services/combat/CombatService.java @@ -48,6 +48,7 @@ import resources.objects.player.PlayerObject; import resources.objects.tangible.TangibleObject; import resources.objects.waypoint.WaypointObject; import resources.objects.weapon.WeaponObject; +import services.ai.AIActor; import services.combat.CombatEvents.DamageTaken; import services.command.CombatCommand; import services.sui.SUIService.MessageBoxType; @@ -257,6 +258,7 @@ public class CombatService implements INetworkDispatch { target.setConditionDamage(target.getConditionDamage() + damage); DamageTaken event = events.new DamageTaken(); event.attacker = attacker; + event.damage = damage; target.getEventBus().publish(event); } @@ -379,23 +381,25 @@ public class CombatService implements INetworkDispatch { private void sendCombatPackets(CreatureObject attacker, TangibleObject target, WeaponObject weapon, CombatCommand command, int actionCounter, float damage, int armorAbsorbed, int hitType) { String animationStr = command.getRandomAnimation(weapon); - CombatAction combatAction = new CombatAction(CRC.StringtoCRC(animationStr), attacker.getObjectID(), weapon.getObjectID(), target.getObjectID(), command.getCommandCRC()); ObjControllerMessage objController = new ObjControllerMessage(0x1B, combatAction); attacker.notifyObserversInRange(objController, true, 125); - - StartTask startTask = new StartTask(actionCounter, attacker.getObjectID(), command.getCommandCRC(), CRC.StringtoCRC(command.getCooldownGroup()), command.getCooldown()); - ObjControllerMessage objController2 = new ObjControllerMessage(0x0B, startTask); - attacker.getClient().getSession().write(objController2.serialize()); - - CommandEnqueueRemove commandRemove = new CommandEnqueueRemove(attacker.getObjectID(), actionCounter); - ObjControllerMessage objController3 = new ObjControllerMessage(0x0B, commandRemove); - attacker.getClient().getSession().write(objController3.serialize()); - CombatSpam combatSpam = new CombatSpam(attacker.getObjectID(), target.getObjectID(), weapon.getObjectID(), (int) damage, armorAbsorbed, hitType); ObjControllerMessage objController4 = new ObjControllerMessage(0x1B, combatSpam); IoBuffer spam = objController4.serialize(); - attacker.getClient().getSession().write(spam); + + if(attacker.getClient() != null) { + + StartTask startTask = new StartTask(actionCounter, attacker.getObjectID(), command.getCommandCRC(), CRC.StringtoCRC(command.getCooldownGroup()), command.getCooldown()); + ObjControllerMessage objController2 = new ObjControllerMessage(0x0B, startTask); + attacker.getClient().getSession().write(objController2.serialize()); + + CommandEnqueueRemove commandRemove = new CommandEnqueueRemove(attacker.getObjectID(), actionCounter); + ObjControllerMessage objController3 = new ObjControllerMessage(0x0B, commandRemove); + attacker.getClient().getSession().write(objController3.serialize()); + attacker.getClient().getSession().write(spam); + + } if(target.getClient() != null) target.getClient().getSession().write(spam); @@ -409,13 +413,15 @@ public class CombatService implements INetworkDispatch { ObjControllerMessage objController = new ObjControllerMessage(0x1B, combatAction); attacker.notifyObserversInRange(objController, true, 125); - StartTask startTask = new StartTask(actionCounter, attacker.getObjectID(), command.getCommandCRC(), CRC.StringtoCRC(command.getCooldownGroup()), command.getCooldown()); - ObjControllerMessage objController2 = new ObjControllerMessage(0x0B, startTask); - attacker.getClient().getSession().write(objController2.serialize()); - - CommandEnqueueRemove commandRemove = new CommandEnqueueRemove(attacker.getObjectID(), actionCounter); - ObjControllerMessage objController3 = new ObjControllerMessage(0x0B, commandRemove); - attacker.getClient().getSession().write(objController3.serialize()); + if(attacker.getClient() != null) { + StartTask startTask = new StartTask(actionCounter, attacker.getObjectID(), command.getCommandCRC(), CRC.StringtoCRC(command.getCooldownGroup()), command.getCooldown()); + ObjControllerMessage objController2 = new ObjControllerMessage(0x0B, startTask); + attacker.getClient().getSession().write(objController2.serialize()); + + CommandEnqueueRemove commandRemove = new CommandEnqueueRemove(attacker.getObjectID(), actionCounter); + ObjControllerMessage objController3 = new ObjControllerMessage(0x0B, commandRemove); + attacker.getClient().getSession().write(objController3.serialize()); + } } @@ -490,7 +496,17 @@ public class CombatService implements INetworkDispatch { if(!target.isAttackableBy(attacker)) return false; - target.addDefender(attacker); + if(target.getAttachment("AI") instanceof AIActor && attacker instanceof CreatureObject) { + ((AIActor) target.getAttachment("AI")).addDefender((CreatureObject) attacker); + } else { + target.addDefender(attacker); + } + if(attacker.getAttachment("AI") instanceof AIActor && target instanceof CreatureObject) { + ((AIActor) attacker.getAttachment("AI")).addDefender((CreatureObject) target); + } else { + attacker.addDefender(target); + } + attacker.addDefender(target); return true; @@ -761,7 +777,7 @@ public class CombatService implements INetworkDispatch { public void applyDamage(CreatureObject attacker, final CreatureObject target, int damage) { - if(target.getHealth() - damage <= 0) { + if(target.getHealth() - damage <= 0 && target.getSlottedObject("ghost") != null) { if(target.hasBuff("incapWeaken")) { deathblowPlayer(attacker, target); @@ -798,11 +814,20 @@ public class CombatService implements INetworkDispatch { if(target.getSlottedObject("ghost") != null) attacker.sendSystemMessage("You incapacitate " + target.getCustomName() + ".", (byte) 0); return; + } else if(target.getHealth() - damage <= 0 && target.getAttachment("AI") != null) { + synchronized(target.getMutex()) { + target.setHealth(0); + target.setPosture((byte) 14); + } + return; } synchronized(target.getMutex()) { target.setHealth(target.getHealth() - damage); } - + DamageTaken event = events.new DamageTaken(); + event.attacker = attacker; + event.damage = damage; + target.getEventBus().publish(event); } private boolean isInConeAngle(CreatureObject attacker, SWGObject target, int coneLength, int coneWidth, float directionX, float directionZ) { diff --git a/src/services/command/CombatCommand.java b/src/services/command/CombatCommand.java index a1559418..16198a57 100644 --- a/src/services/command/CombatCommand.java +++ b/src/services/command/CombatCommand.java @@ -591,7 +591,7 @@ public class CombatCommand extends BaseSWGCommand { animations = twoHandedAnimations; break; case 6: - animations = unarmedAnimations; + animations = defaultAnimations; break; case 7: animations = polearmAnimations; @@ -610,11 +610,14 @@ public class CombatCommand extends BaseSWGCommand { break; default: - animations = unarmedAnimations; + animations = defaultAnimations; break; } + if(animations.length == 0) + animations = defaultAnimations; + return animations[new Random().nextInt(animations.length)]; } diff --git a/src/services/command/CommandService.java b/src/services/command/CommandService.java index 5c838cd1..9ea8dca5 100644 --- a/src/services/command/CommandService.java +++ b/src/services/command/CommandService.java @@ -268,7 +268,7 @@ public class CommandService implements INetworkDispatch { } - if(!success) { + if(!success && attacker.getClient() != null) { IoSession session = attacker.getClient().getSession(); CommandEnqueueRemove commandRemove = new CommandEnqueueRemove(attacker.getObjectId(), actionCounter); session.write(new ObjControllerMessage(0x0B, commandRemove).serialize()); @@ -305,6 +305,17 @@ public class CommandService implements INetworkDispatch { if (command == null) return; + if(command instanceof CombatCommand) { + CombatCommand command2; + try { + command2 = (CombatCommand) command.clone(); + processCombatCommand((CreatureObject) actor, target, command2, 0, ""); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + return; + } + core.scriptService.callScript("scripts/commands/", command.getCommandName(), "run", core, actor, target, commandArgs); } diff --git a/src/services/object/ObjectId.java b/src/services/object/ObjectId.java new file mode 100644 index 00000000..36df1736 --- /dev/null +++ b/src/services/object/ObjectId.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * 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.object; + +import com.sleepycat.persist.model.Entity; +import com.sleepycat.persist.model.PrimaryKey; + +@Entity +public class ObjectId { + + @PrimaryKey + public long objectId; + + public ObjectId(long objectId) { + this.objectId = objectId; + } + + public ObjectId() { } + +} diff --git a/src/services/object/ObjectService.java b/src/services/object/ObjectService.java index e6dc3bb5..b275c358 100644 --- a/src/services/object/ObjectService.java +++ b/src/services/object/ObjectService.java @@ -52,6 +52,8 @@ import org.python.core.Py; import org.python.core.PyObject; import com.sleepycat.persist.EntityCursor; +import com.sleepycat.persist.model.Entity; +import com.sleepycat.persist.model.PrimaryKey; import protocol.swg.ChatFriendsListUpdate; import protocol.swg.ChatOnChangeFriendStatus; @@ -59,10 +61,12 @@ import protocol.swg.ChatOnGetFriendsList; import protocol.swg.CmdSceneReady; import protocol.swg.CmdStartScene; import protocol.swg.HeartBeatMessage; +import protocol.swg.ObjControllerMessage; import protocol.swg.ParametersMessage; import protocol.swg.SelectCharacter; import protocol.swg.ServerTimeMessage; import protocol.swg.UnkByteFlag; +import protocol.swg.objectControllerObjects.UiPlayEffect; import engine.clientdata.ClientFileManager; import engine.clientdata.visitors.CrcStringTableVisitor; import engine.clientdata.visitors.DatatableVisitor; @@ -96,19 +100,12 @@ import resources.objects.weapon.WeaponObject; public class ObjectService implements INetworkDispatch { private Map objectList = new ConcurrentHashMap(); - private NGECore core; - private DatabaseConnection databaseConnection; - private AtomicLong highestId = new AtomicLong(); - private Random random = new Random(); - private Map serverTemplates = new ConcurrentHashMap(); - private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); - protected final Object objectMutex = new Object(); public ObjectService(final NGECore core) { @@ -117,11 +114,12 @@ public class ObjectService implements INetworkDispatch { Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { + core.getObjectIdODB().getEnvironment().flushLog(true); synchronized(objectList) { for(SWGObject obj : objectList.values()) { if(obj.getClient() != null && obj.getClient().getSession() != null) { - core.connectionService.disconnect(obj.getClient().getSession()); + core.connectionService.disconnect(obj.getClient()); } } @@ -258,6 +256,9 @@ public class ObjectService implements INetworkDispatch { object.setAttachment("customServerTemplate", customServerTemplate); object.setisInSnapshot(isSnapshot); + if(!core.getObjectIdODB().contains(objectID, Long.class, ObjectId.class)) { + core.getObjectIdODB().put(new ObjectId(objectID), Long.class, ObjectId.class); + } loadServerTemplate(object); objectList.put(objectID, object); @@ -477,10 +478,12 @@ public class ObjectService implements INetworkDispatch { } catch (SQLException e) { e.printStackTrace(); } - if(getObject(newId) == null && getCreatureFromDB(newId) == null) + if(getObject(newId) == null /*&& getCreatureFromDB(newId) == null*/ && !core.getObjectIdODB().contains(newId, Long.class, ObjectId.class)) return newId; - else + else { + System.out.println("Object ID already exists: " + newId); return generateObjectID(); + } } @@ -540,14 +543,23 @@ public class ObjectService implements INetworkDispatch { } else { creature = (CreatureObject) getObject(objectId); - + if(creature.getAttachment("disconnectTask") != null && creature.getClient() != null && !creature.getClient().getSession().isClosing()) + return; + } + PlayerObject ghost = (PlayerObject) creature.getSlottedObject("ghost"); + + if(ghost == null) + return; + + ghost.clearFlagBitmask(PlayerFlags.LD); + if(creature.getAttachment("disconnectTask") != null) { - creature.getAwareObjects().removeAll(creature.getAwareObjects()); ((ScheduledFuture) creature.getAttachment("disconnectTask")).cancel(true); - creature.setAttachment("disconnectTask", null); - } + } + creature.getAwareObjects().removeAll(creature.getAwareObjects()); + creature.setAttachment("disconnectTask", null); creature.setClient(client); Planet planet = core.terrainService.getPlanetByID(creature.getPlanetId()); @@ -586,6 +598,11 @@ public class ObjectService implements INetworkDispatch { Point3D position = creature.getPosition(); + if(Float.isNaN(position.x) || Float.isNaN(position.y) || Float.isNaN(position.z)) { + creature.setPosition(new Point3D(0, 0, 0)); + position = creature.getPosition(); + } + HeartBeatMessage heartBeat = new HeartBeatMessage(); session.write(heartBeat.serialize()); @@ -605,15 +622,12 @@ public class ObjectService implements INetworkDispatch { core.simulationService.handleZoneIn(client); creature.makeAware(creature); - - - PlayerObject ghost = (PlayerObject) creature.getSlottedObject("ghost"); //ChatOnGetFriendsList friendsListMessage = new ChatOnGetFriendsList(ghost); //client.getSession().write(friendsListMessage.serialize()); if (ghost != null) { - ghost.clearFlagBitmask(PlayerFlags.LD); + //ghost.clearFlagBitmask(PlayerFlags.LD); String objectShortName = creature.getCustomName().toLowerCase(); if (creature.getCustomName().contains(" ")) { @@ -642,7 +656,6 @@ public class ObjectService implements INetworkDispatch { } core.playerService.postZoneIn(creature); - } }); @@ -749,7 +762,7 @@ public class ObjectService implements INetworkDispatch { public void readBuildoutDatatable(DatatableVisitor buildoutTable, Planet planet, float x1, float z1) throws InstantiationException, IllegalAccessException { CrcStringTableVisitor crcTable = ClientFileManager.loadFile("misc/object_template_crc_string_table.iff", CrcStringTableVisitor.class); - + List quadtreeObjects = new ArrayList(); for (int i = 0; i < buildoutTable.getRowCount(); i++) { String template; @@ -816,7 +829,7 @@ public class ObjectService implements INetworkDispatch { continue; if(radius > 256) object.setAttachment("bigSpawnRange", new Boolean(true)); - core.simulationService.add(object, object.getPosition().x, object.getPosition().z); + quadtreeObjects.add(object); } else if(containerId != 0) { object = createObject(template, 0, planet, new Point3D(px, py, pz), new Quaternion(qw, qx, qy, qz)); if(containers.contains(containerId)) { @@ -839,7 +852,7 @@ public class ObjectService implements INetworkDispatch { } } else { object = createObject(template, 0, planet, new Point3D(px + x1, py, pz + z1), new Quaternion(qw, qx, qy, qz)); - core.simulationService.add(object, object.getPosition().x, object.getPosition().z); + quadtreeObjects.add(object); } //System.out.println("Spawning: " + template + " at: X:" + object.getPosition().x + " Y: " + object.getPosition().y + " Z: " + object.getPosition().z); @@ -848,7 +861,9 @@ public class ObjectService implements INetworkDispatch { } - + for(SWGObject obj : quadtreeObjects) { + core.simulationService.add(obj, obj.getPosition().x, obj.getPosition().z); + } } diff --git a/src/services/spawn/LairSpawnArea.java b/src/services/spawn/LairSpawnArea.java index 31b26f96..026268cd 100644 --- a/src/services/spawn/LairSpawnArea.java +++ b/src/services/spawn/LairSpawnArea.java @@ -32,6 +32,7 @@ import resources.common.collidables.AbstractCollidable.ExitEvent; import resources.objects.creature.CreatureObject; import services.SimulationService.MoveEvent; import services.TerrainService; +import services.ai.LairActor; import engine.resources.objects.SWGObject; import engine.resources.scene.Planet; import engine.resources.scene.Point3D; @@ -40,6 +41,7 @@ public class LairSpawnArea extends SpawnArea { private LairGroupTemplate lairGroup; private long lastSpawnTime = 0; + private Vector lairs = new Vector(); public LairSpawnArea(Planet planet, AbstractCollidable area, LairGroupTemplate lairGroup) { super(planet, area); @@ -56,24 +58,31 @@ public class LairSpawnArea extends SpawnArea { public void spawnLair(CreatureObject object) { + NGECore core = NGECore.getInstance(); + Vector lairTemplates = lairGroup.getLairSpawnTemplates(); if(lairGroup == null || lairTemplates.isEmpty()) return; - if((System.currentTimeMillis() - lastSpawnTime) < 3000) + if((System.currentTimeMillis() - lastSpawnTime) < 10000) return; - - Point3D randomPosition = getRandomPosition(object.getWorldPosition(), 32.f, 256.f); + + Point3D randomPosition = getRandomPosition(object.getWorldPosition(), 32.f, 200.f); if(randomPosition == null) return; - TerrainService terrainSvc = NGECore.getInstance().terrainService; + TerrainService terrainSvc = core.terrainService; float height = terrainSvc.getHeight(getPlanet().getID(), randomPosition.x, randomPosition.z); randomPosition.y = height; + for(LairActor otherLair : lairs) { + if(otherLair.getLairObject().getWorldPosition().getDistance(randomPosition) < 10) + return; + } + if(!terrainSvc.canBuildAtPosition(object, randomPosition.x, randomPosition.z)) return; @@ -83,7 +92,10 @@ public class LairSpawnArea extends SpawnArea { int level = random.nextInt((int) (lairSpawn.getMaxLevel() - lairSpawn.getMinLevel()) + 1) + lairSpawn.getMinLevel(); - NGECore.getInstance().spawnService.spawnLair(lairSpawn.getLairTemplate(), getPlanet(), randomPosition, level); + LairActor lairActor = core.spawnService.spawnLair(lairSpawn.getLairTemplate(), getPlanet(), randomPosition, (short) level); + if(lairActor == null) + return; + lairs.add(lairActor); lastSpawnTime = System.currentTimeMillis(); } @@ -138,7 +150,7 @@ public class LairSpawnArea extends SpawnArea { if(creature.getSlottedObject("ghost") == null) return; - if(new Random().nextFloat() <= 0.10) + if(new Random().nextFloat() <= 0.05) spawnLair(creature); } diff --git a/src/services/spawn/MobileTemplate.java b/src/services/spawn/MobileTemplate.java index 7af0d515..7c2da0ff 100644 --- a/src/services/spawn/MobileTemplate.java +++ b/src/services/spawn/MobileTemplate.java @@ -21,6 +21,111 @@ ******************************************************************************/ package services.spawn; +import java.util.Vector; + +import resources.datatables.Options; +import resources.datatables.PvpStatus; +import resources.objects.weapon.WeaponObject; + public class MobileTemplate { + + private Vector templates; + private int optionBitmask = Options.ATTACKABLE; + private int pvpBitmask = PvpStatus.Attackable; + private short level; + private Vector attacks; + private String defaultAttack; + private int minDamage; + private int maxDamage; + private int difficulty = 0; + private int health, action; + + public Vector getTemplates() { + return templates; + } + + public void setTemplates(Vector templates) { + this.templates = templates; + } + + public int getOptionBitmask() { + return optionBitmask; + } + + public void setOptionBitmask(int optionBitmask) { + this.optionBitmask = optionBitmask; + } + + public int getPvpBitmask() { + return pvpBitmask; + } + + public void setPvpBitmask(int pvpBitmask) { + this.pvpBitmask = pvpBitmask; + } + + public short getLevel() { + return level; + } + + public void setLevel(short level) { + this.level = level; + } + + public Vector getAttacks() { + return attacks; + } + + public void setAttacks(Vector attacks) { + this.attacks = attacks; + } + + public int getMinDamage() { + return minDamage; + } + + public void setMinDamage(int minDamage) { + this.minDamage = minDamage; + } + + public int getMaxDamage() { + return maxDamage; + } + + public void setMaxDamage(int maxDamage) { + this.maxDamage = maxDamage; + } + + public int getDifficulty() { + return difficulty; + } + + public void setDifficulty(int difficulty) { + this.difficulty = difficulty; + } + + public int getHealth() { + return health; + } + + public void setHealth(int health) { + this.health = health; + } + + public int getAction() { + return action; + } + + public void setAction(int action) { + this.action = action; + } + + public String getDefaultAttack() { + return defaultAttack; + } + + public void setDefaultAttack(String defaultAttack) { + this.defaultAttack = defaultAttack; + } } diff --git a/src/services/spawn/SpawnService.java b/src/services/spawn/SpawnService.java index 37eeca8f..039338fa 100644 --- a/src/services/spawn/SpawnService.java +++ b/src/services/spawn/SpawnService.java @@ -32,16 +32,24 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Random; import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; import org.python.core.Py; import resources.common.collidables.CollidableCircle; import resources.datatables.Options; import resources.datatables.PvpStatus; +import resources.objects.cell.CellObject; +import resources.objects.creature.CreatureObject; import resources.objects.tangible.TangibleObject; +import resources.objects.weapon.WeaponObject; +import services.ai.AIActor; import services.ai.LairActor; +import engine.resources.container.CreatureContainerPermissions; import engine.resources.scene.Planet; import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; @@ -54,7 +62,8 @@ public class SpawnService { private Map mobileTemplates = new ConcurrentHashMap(); private Map lairGroupTemplates = new ConcurrentHashMap(); private Map lairTemplates = new ConcurrentHashMap(); - + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(4); + public SpawnService(NGECore core) { this.core = core; for(Planet planet : core.terrainService.getPlanetList()) { @@ -62,41 +71,169 @@ public class SpawnService { } } - public void spawnCreature(String template, float x, float y, float z) { - spawnCreature(template, new Point3D(x, y, z)); - } - - public void spawnCreature(String template, Point3D position) { + public CreatureObject spawnCreature(String template, String planetName, long cellId, float x, float y, float z, float qW, float qX, float qY, float qZ, short level) { + Planet planet = core.terrainService.getPlanetByName(planetName); + MobileTemplate mobileTemplate = mobileTemplates.get(template); + if(planet == null || mobileTemplate == null) + return null; + + CellObject cell = null; + + if(cellId != 0) { + cell = (CellObject) core.objectService.getObject(cellId); + if(cell == null) + return null; + } + + CreatureObject creature = (CreatureObject) core.objectService.createObject(mobileTemplate.getTemplates().get(new Random().nextInt(mobileTemplate.getTemplates().size())), 0, planet, new Point3D(x, y, z), new Quaternion(qW, qX, qY, qZ)); + + if(creature == null) + return null; + + TangibleObject inventory = (TangibleObject) core.objectService.createObject("object/tangible/inventory/shared_character_inventory.iff", creature.getPlanet()); + inventory.setContainerPermissions(CreatureContainerPermissions.CREATURE_CONTAINER_PERMISSIONS); + + + /*if(mobileTemplate.getCustomWeapon() != null) { + creature.addObjectToEquipList(mobileTemplate.getCustomWeapon()); + creature.add(mobileTemplate.getCustomWeapon()); + creature.setWeaponId(mobileTemplate.getCustomWeapon().getObjectID()); + }*/ + + creature.setOptionsBitmask(mobileTemplate.getOptionBitmask()); + creature.setPvPBitmask(mobileTemplate.getPvpBitmask()); + int difficulty = mobileTemplate.getDifficulty(); + creature.setDifficulty((byte) difficulty); + if(level != -1) + creature.setLevel(level); + else + creature.setLevel(mobileTemplate.getLevel()); + WeaponObject defaultWeapon = (WeaponObject) core.objectService.createObject("object/weapon/creature/shared_creature_default_weapon.iff", creature.getPlanet()); + defaultWeapon.setAttackSpeed(2); + defaultWeapon.setDamageType("@obj_attr_n:armor_eff_kinetic"); + defaultWeapon.setStringAttribute("cat_wpn_damage.damage", "0-0"); + if(mobileTemplate.getMaxDamage() != 0) { + defaultWeapon.setMaxDamage(mobileTemplate.getMaxDamage()); + defaultWeapon.setMinDamage(mobileTemplate.getMinDamage()); + } else { + defaultWeapon.setMaxDamage(creature.getLevel() * 24); + defaultWeapon.setMinDamage(creature.getLevel() * 22); + } + creature.addObjectToEquipList(defaultWeapon); + creature.add(defaultWeapon); + creature.addObjectToEquipList(inventory); + creature.add(inventory); + + int customHealth = mobileTemplate.getHealth(); + if(difficulty > 0 && customHealth == 0) { + if(difficulty == 1) { + creature.setMaxHealth((int) (400 + level * 134 * 2.5)); + creature.setHealth((int) (400 + level * 134 * 2.5)); + creature.setMaxAction((int) (400 + level * 134 * 2.5)); + creature.setAction((int) (400 + level * 134 * 2.5)); + } else if(difficulty == 2) { + creature.setMaxHealth((int) (400 + level * 134 * 10)); + creature.setHealth((int) (400 + level * 134 * 10)); + creature.setMaxAction((int) (400 + level * 134 * 10)); + creature.setAction((int) (400 + level * 134 * 10)); + } + } else if(difficulty <= 0 && customHealth == 0) { + creature.setMaxHealth((int) (400 + level * 134)); + creature.setHealth((int) (400 + level * 134)); + creature.setMaxAction((int) (400 + level * 134)); + creature.setAction((int) (400 + level * 134)); + } else { + creature.setMaxHealth(customHealth); + creature.setHealth(customHealth); + creature.setMaxAction((int) (level * 128)); + creature.setAction((int) (level * 128)); + } + + if(creature.getLevel() > 16) { + int armor = (creature.getLevel() - 16) * 87; + if(armor > 6000) + armor = 6000; + core.skillModService.addSkillMod(creature, "expertise_innate_protection_all", armor); + } + + AIActor actor = new AIActor(creature, creature.getPosition(), scheduler); + creature.setAttachment("AI", actor); + actor.setMobileTemplate(mobileTemplate); + + + if(cell == null) { + core.simulationService.add(creature, x, z, true); + } else { + creature.getPosition().setCell(cell); + cell.add(creature); + } + return creature; } - public void spawnLair(String lairSpawnTemplate, Planet planet, Point3D position, int level) { + public CreatureObject spawnCreature(String mobileTemplate, String planetName, long cellId, float x, float y, float z) { + return spawnCreature(mobileTemplate, planetName, cellId, x, y, z, 1, 0, 0, 0, (short) -1); + } + + public CreatureObject spawnCreature(String mobileTemplate, String planetName, long cellId, float x, float y, float z, short level) { + return spawnCreature(mobileTemplate, planetName, cellId, x, y, z, 1, 0, 0, 0, level); + } + + public CreatureObject spawnCreature(String mobileTemplate, String planetName, long cellId, float x, float z) { + Planet planet = core.terrainService.getPlanetByName(planetName); + return spawnCreature(mobileTemplate, planetName, cellId, x, core.terrainService.getHeight(planet.getID(), x, z), z, 1, 0, 0, 0, (short) -1); + } + + public CreatureObject spawnCreature(String mobileTemplate, String planetName, long cellId, float x, float z, short level) { + Planet planet = core.terrainService.getPlanetByName(planetName); + return spawnCreature(mobileTemplate, planetName, cellId, x, core.terrainService.getHeight(planet.getID(), x, z), z, 1, 0, 0, 0, level); + } + + + public LairActor spawnLair(String lairSpawnTemplate, Planet planet, Point3D position, short level) { LairTemplate lairTemplate = lairTemplates.get(lairSpawnTemplate); if(lairTemplate == null) - return; + return null; TangibleObject lairObject = (TangibleObject) core.objectService.createObject(lairTemplate.getLairCRC(), 0, planet, position, new Quaternion(1, 0, 0, 0)); if(lairObject == null) - return; + return null; lairObject.setOptionsBitmask(Options.ATTACKABLE); lairObject.setPvPBitmask(PvpStatus.Attackable); lairObject.setMaxDamage(1000 * level); - LairActor lairActor = new LairActor(lairObject, lairTemplate.getMobileName()); + LairActor lairActor = new LairActor(lairObject, lairTemplate.getMobileName(), 10, level); lairObject.setAttachment("AI", lairActor); core.simulationService.add(lairObject, position.x, position.z, true); + lairActor.spawnNewCreatures(); + + return lairActor; } public void loadMobileTemplates() { - + Path p = Paths.get("scripts/mobiles"); + FileVisitor fv = new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if(!file.toString().contains("lairs") && !file.toString().contains("spawnareas") && !file.toString().contains("lairgroups")) + core.scriptService.callScript(file.toString().replace(file.getFileName().toString(), ""), file.getFileName().toString().replace(".py", ""), "addTemplate", core); + return FileVisitResult.CONTINUE; + } + }; + try { + Files.walkFileTree(p, fv); + } catch (IOException e) { + e.printStackTrace(); + } + } - public void addMobileTemplate() { - + public void addMobileTemplate(String template, MobileTemplate mobileTemplate) { + mobileTemplates.put(template, mobileTemplate); } public void loadLairTemplates() { diff --git a/src/services/trade/TradeService.java b/src/services/trade/TradeService.java index e425d282..9c80fc3a 100644 --- a/src/services/trade/TradeService.java +++ b/src/services/trade/TradeService.java @@ -202,7 +202,7 @@ public class TradeService implements INetworkDispatch{ } else { - if(objectToTrade.getAttributes().toString().contains("no_trade")) { + if(objectToTrade.getAttributes()/*.toString()*/.containsKey("no_trade")) { return; } @@ -341,7 +341,7 @@ public class TradeService implements INetworkDispatch{ CreatureObject tradePartner = (CreatureObject) core.objectService.getObject(tradingWithClient); CreatureObject actingTrader = (CreatureObject) client.getParent(); - CreatureObject tradePartnerContainer = (CreatureObject) tradePartner.getContainer(); + SWGObject tradePartnerContainer = tradePartner.getContainer(); SWGObject tradePartnerInventory = tradePartner.getSlottedObject("inventory"); SWGObject actingTraderInventory = actingTrader.getSlottedObject("inventory"); diff --git a/src/services/travel/TravelService.java b/src/services/travel/TravelService.java index 488ae1e7..b449d25b 100644 --- a/src/services/travel/TravelService.java +++ b/src/services/travel/TravelService.java @@ -335,9 +335,9 @@ public class TravelService implements INetworkDispatch { float distance = 13 + ran.nextFloat(); float x = (float) (tp.getSpawnLocation().getPosition().x + Math.sin(dirRadian) * distance); - float y = (float) (tp.getSpawnLocation().getPosition().y + Math.cos(dirRadian) * distance); + float z = (float) (tp.getSpawnLocation().getPosition().z + Math.cos(dirRadian) * distance); - Point3D spawnPoint = new Point3D(x, y, tp.getSpawnLocation().getPosition().z); + Point3D spawnPoint = new Point3D(x, tp.getSpawnLocation().getPosition().y, z); core.simulationService.transferToPlanet(actor, planet, spawnPoint, new Quaternion(0, 0, 0, 0), null); }