diff --git a/scripts/object/mobile/respec_seller_f_1.py b/scripts/object/mobile/respec_seller_f_1.py index ccad8904..1ff6ade9 100644 --- a/scripts/object/mobile/respec_seller_f_1.py +++ b/scripts/object/mobile/respec_seller_f_1.py @@ -1,4 +1,9 @@ import sys +from resources.datatables import Options def setup(core, object): + object.setAttachment('radial_filename', 'conversation') + object.setAttachment('conversationFile', 'respec') + object.setOptions(Options.CONVERSABLE, True) + object.setOptions(Options.INVULNERABLE, True) return \ No newline at end of file diff --git a/scripts/radial/conversation.py b/scripts/radial/conversation.py new file mode 100644 index 00000000..0603ecb1 --- /dev/null +++ b/scripts/radial/conversation.py @@ -0,0 +1,14 @@ +from resources.common import RadialOptions +import sys + +def createRadial(core, owner, target, radials): + radials.add(RadialOptions(0, 21, 1, '')) + radials.add(RadialOptions(0, 7, 1, '')) + radials.add(RadialOptions(0, 26, 1, '')) + return + +def handleSelection(core, owner, target, option): + if option == 26 and target: + core.conversationService.handleStartConversation(owner, target) + return + \ No newline at end of file diff --git a/scripts/static_spawns/tatooine.py b/scripts/static_spawns/tatooine.py index 785f26b5..58723194 100644 --- a/scripts/static_spawns/tatooine.py +++ b/scripts/static_spawns/tatooine.py @@ -9,6 +9,8 @@ def addPlanetSpawns(core, planet): #stcSvc.spawnObject('object/mobile/shared_3po_protocol_droid_red.iff', 'tatooine', long(26582), float(-14.3), float(2.0), float(47.4), float(0.70), float(0.71)) stcSvc.spawnObject('object/tangible/terminal/shared_terminal_character_builder.iff', 'tatooine', long(0), float(3525), float(4), float(-4801), float(0.70), float(0.71)) + #stcSvc.spawnObject('object/mobile/shared_respec_seller_f_1.iff', 'tatooine', long(0), float(3533.14), float(5), float(-4788.86), float(-0.3327), float(0.9288)) + return diff --git a/src/main/NGECore.java b/src/main/NGECore.java index 9320afd1..88977fe3 100644 --- a/src/main/NGECore.java +++ b/src/main/NGECore.java @@ -52,6 +52,7 @@ import services.AttributeService; import services.BuffService; import services.CharacterService; import services.ConnectionService; +import services.ConversationService; import services.DevService; import services.EntertainmentService; import services.EquipmentService; @@ -167,6 +168,7 @@ public class NGECore { //public MissionService missionService; public InstanceService instanceService; public DevService devService; + public ConversationService conversationService; // Login Server public NetworkDispatch loginDispatch; @@ -191,6 +193,7 @@ public class NGECore { private ObjectDatabase buildingODB; + public NGECore() { @@ -264,6 +267,7 @@ public class NGECore { equipmentService = new EquipmentService(this); entertainmentService = new EntertainmentService(this); devService = new DevService(this); + conversationService = new ConversationService(this); if (config.keyExists("JYTHONCONSOLE.PORT")) { int jythonPort = config.getInt("JYTHONCONSOLE.PORT"); diff --git a/src/resources/common/ConversationOption.java b/src/resources/common/ConversationOption.java index 768301d6..840fdcba 100644 --- a/src/resources/common/ConversationOption.java +++ b/src/resources/common/ConversationOption.java @@ -24,9 +24,11 @@ package resources.common; public class ConversationOption { private OutOfBand outOfBand; - - public ConversationOption(OutOfBand outOfBand) { + private int index; + + public ConversationOption(OutOfBand outOfBand, int index) { this.setOutOfBand(outOfBand); + this.setIndex(index); } public OutOfBand getOutOfBand() { @@ -37,4 +39,12 @@ public class ConversationOption { this.outOfBand = outOfBand; } + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + } diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index 9db67666..b0749e89 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -171,14 +171,13 @@ public class CreatureObject extends TangibleObject implements IPersistent { private boolean staticNPC = false; // temp @NotPersistent private int flourishCount = 0; - @NotPersistent private boolean performingEffect; - @NotPersistent private boolean performingFlourish; - private int coverCharge; + @NotPersistent + private TangibleObject conversingNpc; public CreatureObject(long objectID, Planet planet, Point3D position, Quaternion orientation, String Template) { super(objectID, planet, Template, position, orientation); @@ -1747,4 +1746,17 @@ public class CreatureObject extends TangibleObject implements IPersistent { this.stationary = stationary; } } + + public TangibleObject getConversingNpc() { + synchronized(objectMutex) { + return conversingNpc; + } + } + + public void setConversingNpc(TangibleObject conversingNpc) { + synchronized(objectMutex) { + this.conversingNpc = conversingNpc; + } + } + } diff --git a/src/services/ConversationService.java b/src/services/ConversationService.java new file mode 100644 index 00000000..dac17b45 --- /dev/null +++ b/src/services/ConversationService.java @@ -0,0 +1,144 @@ +/******************************************************************************* + * 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; + +import java.util.Map; +import java.util.Vector; +import java.util.concurrent.ConcurrentHashMap; + +import org.python.core.Py; +import org.python.core.PyObject; + +import protocol.swg.ObjControllerMessage; +import protocol.swg.objectControllerObjects.NpcConversationMessage; +import protocol.swg.objectControllerObjects.NpcConversationOptions; +import protocol.swg.objectControllerObjects.StartNpcConversation; +import protocol.swg.objectControllerObjects.StopNpcConversation; +import resources.common.ConversationOption; +import resources.common.OutOfBand; +import resources.objects.creature.CreatureObject; +import resources.objects.tangible.TangibleObject; +import main.NGECore; +import engine.resources.service.INetworkDispatch; +import engine.resources.service.INetworkRemoteEvent; + +public class ConversationService implements INetworkDispatch { + + private NGECore core; + private Map conversationHandlers = new ConcurrentHashMap(); + + public ConversationService(NGECore core) { + this.core = core; + } + + public void handleStartConversation(CreatureObject player, TangibleObject npc) { + if(npc.getAttachment("conversationFile") == null) + return; + + if(player.getConversingNpc() != null && player.getConversingNpc() != npc) + handleEndConversation(player, player.getConversingNpc()); + + sendStartConversation(player, npc); + core.scriptService.callScript("scripts/conversation/", (String) npc.getAttachment("conversationFile"), "startConversation", core, player, npc); + } + + public void handleConversationSelection(CreatureObject player, int selectionId) { + + TangibleObject npc = player.getConversingNpc(); + + if(npc == null) + return; + + PyObject func = conversationHandlers.get(player); + + if(func == null) + return; + + conversationHandlers.remove(player); + + func.__call__(Py.java2py(core), Py.java2py(player), Py.java2py(npc), Py.java2py(selectionId)); + + } + + public void handleEndConversation(CreatureObject player, TangibleObject npc) { + + conversationHandlers.remove(player); + player.setConversingNpc(null); + core.scriptService.callScript("scripts/conversation/", (String) npc.getAttachment("conversationFile"), "endConversation", core, player, npc); + + } + + public void sendStartConversation(CreatureObject player, TangibleObject npc) { + if(player.getClient() == null) + return; + + StartNpcConversation startConvo = new StartNpcConversation(player.getObjectID(), npc.getObjectID()); + ObjControllerMessage objController = new ObjControllerMessage(0x0B, startConvo); + player.getClient().getSession().write(objController.serialize()); + } + + public void sendStopConversation(CreatureObject player, TangibleObject npc, String stfFile, String stfLabel) { + if(player.getClient() == null) + return; + + StopNpcConversation stopConvo = new StopNpcConversation(player.getObjectID(), npc.getObjectID(), stfFile, stfLabel); + ObjControllerMessage objController = new ObjControllerMessage(0x0B, stopConvo); + player.getClient().getSession().write(objController.serialize()); + } + + public void sendConversationMessage(CreatureObject player, TangibleObject npc, OutOfBand outOfBand) { + if(player.getClient() == null) + return; + + NpcConversationMessage convoMessage = new NpcConversationMessage(player.getObjectID(), outOfBand); + ObjControllerMessage objController = new ObjControllerMessage(0x0B, convoMessage); + player.getClient().getSession().write(objController.serialize()); + } + + public void sendConversationOptions(CreatureObject player, TangibleObject npc, Vector options, PyObject handler) { + if(player.getClient() == null) + return; + + conversationHandlers.put(player, handler); + + NpcConversationOptions convoOptions = new NpcConversationOptions(player.getObjectID(), npc.getObjectID()); + options.forEach(convoOptions::addOption); + ObjControllerMessage objController = new ObjControllerMessage(0x0B, convoOptions); + player.getClient().getSession().write(objController.serialize()); + } + + + @Override + public void insertOpcodes(Map arg0, + Map arg1) { + // TODO Auto-generated method stub + + } + + @Override + public void shutdown() { + // TODO Auto-generated method stub + + } + + +}