From 5e240b00faf2e4cd27082d420a1c0a8bc9d8a512 Mon Sep 17 00:00:00 2001 From: Waverunner Date: Fri, 25 Apr 2014 17:26:48 -0400 Subject: [PATCH] Added aborting for missions, finished delivery missions, cleaned up code --- scripts/conversation/missions/deliver.py | 50 ++++++++-- src/protocol/swg/ObjControllerMessage.java | 1 + .../objectControllerObjects/MissionAbort.java | 61 ++++++++++++ .../common/ObjControllerOpcodes.java | 1 + .../objectives/DeliveryMissionObjective.java | 99 +++++++++++++++++-- .../objectives/DestroyMissionObjective.java | 57 +++++++++++ .../objects/creature/CreatureObject.java | 18 ++++ src/services/mission/MissionObjective.java | 2 +- src/services/mission/MissionService.java | 73 +++++++++++--- 9 files changed, 335 insertions(+), 27 deletions(-) create mode 100644 src/protocol/swg/objectControllerObjects/MissionAbort.java create mode 100644 src/resources/objectives/DestroyMissionObjective.java diff --git a/scripts/conversation/missions/deliver.py b/scripts/conversation/missions/deliver.py index 2f751818..5caef3fa 100644 --- a/scripts/conversation/missions/deliver.py +++ b/scripts/conversation/missions/deliver.py @@ -4,7 +4,12 @@ from resources.objectives import DeliveryMissionObjective import sys def startConversation(core, actor, npc): - mission = npc.getAttachment('assignedMission') + missionId = npc.getAttachment('assignedMission') + + if missionId is None: + return + + mission = core.objectService.getObject(missionId) if mission is None: return @@ -12,21 +17,54 @@ def startConversation(core, actor, npc): objective = mission.getObjective() if mission.getGrandparent().getObjectId() != actor.getObjectId() or objective is None: - core.conversationService.sendStopConversation(actor, npc, 'conversation/respecseller', 's_38') + core.conversationService.sendStopConversation(actor, npc, 'mission/mission_generic', 'npc_job_request_no_job') return if objective.getObjectivePhase() == 0: - handleFirstDeliveryStage(core, actor, npc, objective, mission) + handlePickupStage(core, actor, npc, objective, mission) return - #convSvc.sendConversationMessage(actor, npc, OutOfBand(ProsePackage(mission.getMissionDescription(), 'm' + str(mission.getMissionId()) + 'p'))) + elif objective.getObjectivePhase() == 1: + handleDeliveryStage(core, actor, npc, objective, mission) + return + + elif objective.getObjectivePhase() == 2: + handleCompletionStage(core, actor, npc, objective, mission) + return return def endConversation(core, actor, npc): + core.conversationService.sendStopConversation(actor, npc, 'mission/mission_generic', 'npc_job_request_no_job') return -def handleFirstDeliveryStage(core, actor, npc, objective, mission): +def handlePickupStage(core, actor, npc, objective, mission): + + if objective.getMissionGiver().getObjectId() != npc.getObjectId(): + endConversation(core, actor, npc) + return + core.conversationService.sendStopConversation(actor, npc, mission.getMissionDescription(), 'm' + str(mission.getMissionId()) + 'p') objective.createDeliveryItem() - objective.setObjectivePhase(1) + objective.update() + return + +def handleDeliveryStage(core, actor, npc, objective, mission): + + if objective.getDropOffNpc().getObjectId() != npc.getObjectId(): + endConversation(core, actor, npc) + return + + core.conversationService.sendStopConversation(actor, npc, mission.getMissionDescription(), 'm' + str(mission.getMissionId()) + 'r') + core.objectService.destroyObject(objective.getDeliveryObject()) + objective.update() + return + +def handleCompletionStage(core, actor, npc, objective, mission): + + if objective.getMissionGiver().getObjectId() != npc.getObjectId(): + endConversation(core, actor, npc) + return + + core.conversationService.sendStopConversation(actor, npc, mission.getMissionDescription(), 'm' + str(mission.getMissionId()) + 's') + objective.complete() return \ No newline at end of file diff --git a/src/protocol/swg/ObjControllerMessage.java b/src/protocol/swg/ObjControllerMessage.java index 2c4482d1..cb1ff04b 100644 --- a/src/protocol/swg/ObjControllerMessage.java +++ b/src/protocol/swg/ObjControllerMessage.java @@ -75,6 +75,7 @@ public class ObjControllerMessage extends SWGMessage { public static final int DRAFT_SLOTS_QUERY_RESPONSE = 0x01BF; public static final int RESOURCE_WEIGHTS = 0x0207; public static final int MISSION_ACCEPT_RESPONSE = 0x00FA; + public static final int MISSION_ABORT_RESPONSE = 0x0142; public ObjControllerMessage() { diff --git a/src/protocol/swg/objectControllerObjects/MissionAbort.java b/src/protocol/swg/objectControllerObjects/MissionAbort.java new file mode 100644 index 00000000..2195c511 --- /dev/null +++ b/src/protocol/swg/objectControllerObjects/MissionAbort.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * 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 MissionAbort extends ObjControllerObject { + private long characterId; + private long missionId; + + public MissionAbort() { } + + @Override + public void deserialize(IoBuffer data) { + setCharacterId(data.getLong()); + data.getInt(); + setMissionId(data.getLong()); + } + + @Override + public IoBuffer serialize() { + IoBuffer buffer = IoBuffer.allocate(32).order(ByteOrder.LITTLE_ENDIAN); + + buffer.putInt(ObjControllerMessage.MISSION_ABORT_RESPONSE); + buffer.putLong(characterId); + buffer.putInt(0); + buffer.putLong(missionId); + return null; + } + + public long getMissionId() { return missionId; } + + public void setMissionId(long missionId) { this.missionId = missionId; } + + public long getCharacterId() { return characterId; } + + public void setCharacterId(long characterId) { this.characterId = characterId; } +} diff --git a/src/resources/common/ObjControllerOpcodes.java b/src/resources/common/ObjControllerOpcodes.java index 41db9dbd..c38a6071 100644 --- a/src/resources/common/ObjControllerOpcodes.java +++ b/src/resources/common/ObjControllerOpcodes.java @@ -35,6 +35,7 @@ public class ObjControllerOpcodes { public static final int BUFF_BUILDER_END = 0x5B020000; public static final int MISSION_LIST_REQUEST = 0xF5000000; public static final int MISSION_GENERIC_REQUEST = 0xF9000000; + public static final int MISSION_ABORT = 0x42010000; public static final int ChangeRoleIconChoice = 0x4D040000; public static final int IMAGE_DESIGN_CHANGE = 0x38020000; public static final int IMAGE_DESIGN_END = 0x39020000; diff --git a/src/resources/objectives/DeliveryMissionObjective.java b/src/resources/objectives/DeliveryMissionObjective.java index 6e478756..b5802390 100644 --- a/src/resources/objectives/DeliveryMissionObjective.java +++ b/src/resources/objectives/DeliveryMissionObjective.java @@ -24,6 +24,8 @@ package resources.objectives; import engine.resources.objects.SWGObject; import engine.resources.scene.Point3D; import main.NGECore; +import resources.common.OutOfBand; +import resources.common.ProsePackage; import resources.objects.creature.CreatureObject; import resources.objects.mission.MissionObject; import resources.objects.tangible.TangibleObject; @@ -33,6 +35,8 @@ import services.mission.MissionObjective; public class DeliveryMissionObjective extends MissionObjective { private TangibleObject deliveryObject; + private CreatureObject missionGiver; + private CreatureObject dropOffNpc; private NGECore core = NGECore.getInstance(); public DeliveryMissionObjective(MissionObject parent) { @@ -46,18 +50,44 @@ public class DeliveryMissionObjective extends MissionObjective { return; String template = "object/mobile/shared_dressed_commoner_tatooine_sullustan_male_06.iff"; + Point3D startLoc = parent.getStartLocation(); + Point3D destination = parent.getDestination(); + // TODO: Randomize this process. CreatureObject missionGiver = (CreatureObject) core.staticService.spawnObject(template, parent.getPlanet().name, 0, startLoc.x, startLoc.y, startLoc.z, 0, 1); + if (missionGiver == null) + return; + + missionGiver.setCustomName("a commoner"); missionGiver.setAttachment("conversationFile", "missions/deliver"); missionGiver.setAttachment("radial_filename", "object/conversation"); - missionGiver.setAttachment("assignedMission", getMissionObject()); + missionGiver.setAttachment("assignedMission", getMissionObject().getObjectId()); missionGiver.setOptionsBitmask(264); + setMissionGiver(missionGiver); + + CreatureObject dropOffNpc = (CreatureObject) core.staticService.spawnObject(template, parent.getPlanet().name, 0, destination.x, destination.y, destination.z, 0, 1); + if (dropOffNpc == null) + return; + + dropOffNpc.setCustomName("a commoner"); + dropOffNpc.setAttachment("conversationFile", "missions/deliver"); + dropOffNpc.setAttachment("radial_filename", "object/conversation"); + dropOffNpc.setAttachment("assignedMission", getMissionObject().getObjectId()); + dropOffNpc.setOptionsBitmask(264); + setDropOffNpc(dropOffNpc); if (getObjectivePhase() == 0) { WaypointObject waypoint = (WaypointObject) core.objectService.createObject("object/waypoint/shared_waypoint.iff", parent.getPlanet()); waypoint.setPosition(startLoc); - waypoint.setName("@mission/" + parent.getMissionTitle() + ":" + parent.getMissionId()); + waypoint.setName("@mission/" + parent.getMissionTitle() + ":" + "m" + parent.getMissionId() + "t"); + waypoint.setColor(WaypointObject.ORANGE); + waypoint.setActive(true); + getMissionObject().setAttachedWaypoint(waypoint); + } else if (getObjectivePhase() == 1) { + WaypointObject waypoint = (WaypointObject) core.objectService.createObject("object/waypoint/shared_waypoint.iff", parent.getPlanet()); + waypoint.setPosition(parent.getDestination()); + waypoint.setName("@mission/" + parent.getMissionTitle() + ":" + "m" + parent.getMissionId() + "t"); waypoint.setColor(WaypointObject.ORANGE); waypoint.setActive(true); getMissionObject().setAttachedWaypoint(waypoint); @@ -66,16 +96,62 @@ public class DeliveryMissionObjective extends MissionObjective { setActive(true); } - @Override - public void update() { - } - @Override public void complete() { + CreatureObject completer = (CreatureObject) getMissionObject().getGrandparent(); + + if (completer == null) + return; + + int reward = getMissionObject().getCreditReward(); + + completer.addBankCredits(reward); + + completer.sendSystemMessage(new OutOfBand(new ProsePackage("@mission/mission_generic:success_w_amount", reward)), (byte) 0); + + abort(); + + core.objectService.destroyObject(getMissionObject()); } @Override - public void drop() { + public void abort() { + if (deliveryObject != null) + core.objectService.destroyObject(deliveryObject.getObjectId()); + + if (missionGiver != null) + core.objectService.destroyObject(missionGiver, 360); + + if (dropOffNpc != null) + core.objectService.destroyObject(dropOffNpc, 360); + } + + @Override + public void update() { + + setObjectivePhase(getObjectivePhase() + 1); + + switch(getObjectivePhase()) { + case 1: + WaypointObject waypoint = (WaypointObject) core.objectService.createObject("object/waypoint/shared_waypoint.iff", parent.getPlanet()); + waypoint.setPosition(parent.getDestination()); + waypoint.setName("@mission/" + parent.getMissionTitle() + ":" + "m" + parent.getMissionId() + "t"); + waypoint.setColor(WaypointObject.ORANGE); + waypoint.setActive(true); + getMissionObject().setMissionTargetName("Dropoff Location"); + getMissionObject().setAttachedWaypoint(waypoint); + System.out.println("Waypoint set to " + parent.getDestination().x + " and " + parent.getDestination().z); + break; + case 2: + WaypointObject returnWp = (WaypointObject) core.objectService.createObject("object/waypoint/shared_waypoint.iff", parent.getPlanet()); + returnWp.setPosition(parent.getStartLocation()); + returnWp.setName("@mission/" + parent.getMissionTitle() + ":" + "m" + parent.getMissionId() + "t"); + returnWp.setColor(WaypointObject.ORANGE); + returnWp.setActive(true); + getMissionObject().setMissionTargetName("Return"); + getMissionObject().setAttachedWaypoint(returnWp); + break; + } } public boolean createDeliveryItem() { @@ -103,4 +179,13 @@ public class DeliveryMissionObjective extends MissionObjective { public TangibleObject getDeliveryObject() { return deliveryObject; } public void setDeliveryObject(TangibleObject object) { this.deliveryObject = object; } + + public CreatureObject getMissionGiver() { return missionGiver; } + + public void setMissionGiver(CreatureObject missionGiver) { this.missionGiver = missionGiver; } + + public CreatureObject getDropOffNpc() { return dropOffNpc; } + + public void setDropOffNpc(CreatureObject dropOffNpc) { this.dropOffNpc = dropOffNpc; } + } diff --git a/src/resources/objectives/DestroyMissionObjective.java b/src/resources/objectives/DestroyMissionObjective.java new file mode 100644 index 00000000..e4832756 --- /dev/null +++ b/src/resources/objectives/DestroyMissionObjective.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package resources.objectives; + +import resources.objects.mission.MissionObject; +import services.mission.MissionObjective; + +public class DestroyMissionObjective extends MissionObjective { + + public DestroyMissionObjective(MissionObject parent) { + super(parent); + } + + @Override + public void activate() { + // TODO Auto-generated method stub + + } + + @Override + public void complete() { + // TODO Auto-generated method stub + + } + + @Override + public void abort() { + // TODO Auto-generated method stub + + } + + @Override + public void update() { + // TODO Auto-generated method stub + + } + +} diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index 7680d9bd..d6f2a861 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -251,12 +251,30 @@ public class CreatureObject extends TangibleObject implements IPersistent { getClient().getSession().write(messageBuilder.buildBankCreditsDelta(bankCredits)); } } + + public void addBankCredits(int amountToAdd) { + synchronized(objectMutex) { + this.bankCredits += amountToAdd; + } + if(getClient() != null && getClient().getSession() != null) { + getClient().getSession().write(messageBuilder.buildBankCreditsDelta(bankCredits)); + } + } public int getCashCredits() { synchronized(objectMutex) { return cashCredits; } } + + public void addCashCredits(int amountToAdd) { + synchronized(objectMutex) { + this.cashCredits += amountToAdd; + } + if(getClient() != null && getClient().getSession() != null) { + getClient().getSession().write(messageBuilder.buildCashCreditsDelta(cashCredits)); + } + } public void setCashCredits(int cashCredits) { synchronized(objectMutex) { diff --git a/src/services/mission/MissionObjective.java b/src/services/mission/MissionObjective.java index d74ef6d1..c81fcc0a 100644 --- a/src/services/mission/MissionObjective.java +++ b/src/services/mission/MissionObjective.java @@ -44,7 +44,7 @@ public abstract class MissionObjective { public abstract void activate(); public abstract void complete(); - public abstract void drop(); + public abstract void abort(); public abstract void update(); public long getStartTime() { return startTime; } diff --git a/src/services/mission/MissionService.java b/src/services/mission/MissionService.java index 08415813..40b5abf0 100644 --- a/src/services/mission/MissionService.java +++ b/src/services/mission/MissionService.java @@ -36,14 +36,14 @@ import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; import protocol.swg.ObjControllerMessage; +import protocol.swg.objectControllerObjects.MissionAbort; import protocol.swg.objectControllerObjects.MissionAcceptRequest; import protocol.swg.objectControllerObjects.MissionAcceptResponse; import protocol.swg.objectControllerObjects.MissionListRequest; -import protocol.swg.objectControllerObjects.ObjControllerObject; -import resources.common.Console; import resources.common.SpawnPoint; import resources.common.ObjControllerOpcodes; import resources.objectives.DeliveryMissionObjective; +import resources.objectives.DestroyMissionObjective; import resources.objects.creature.CreatureObject; import resources.objects.mission.MissionObject; import resources.objects.tangible.TangibleObject; @@ -77,6 +77,38 @@ public class MissionService implements INetworkDispatch { @Override public void insertOpcodes(Map swgOpcodes, Map objControllerOpcodes) { + + objControllerOpcodes.put(ObjControllerOpcodes.MISSION_ABORT, new INetworkRemoteEvent() { + + @Override + public void handlePacket(IoSession session, IoBuffer data) throws Exception { + Client client = core.getClient(session); + + if(client == null || client.getSession() == null) + return; + + CreatureObject creature = (CreatureObject) client.getParent(); + + if(creature == null) + return; + + data.order(ByteOrder.LITTLE_ENDIAN); + MissionAbort abort = new MissionAbort(); + abort.deserialize(data); + + MissionObject mission = (MissionObject) core.objectService.getObject(abort.getMissionId()); + + if (mission == null) + return; + + if (mission.getGrandparent().getObjectId() != creature.getObjectId()) + return; + + handleMissionAbort(creature, mission); + } + + }); + objControllerOpcodes.put(ObjControllerOpcodes.MISSION_LIST_REQUEST, new INetworkRemoteEvent() { @Override @@ -112,7 +144,7 @@ public class MissionService implements INetworkDispatch { } else if (terminalType == TerminalType.ARTISAN) { } else { - Console.println("ERROR: Unsupported terminal " + terminal.getObjectId()); + //Console.println("ERROR: Unsupported terminal " + terminal.getObjectId()); } } @@ -155,6 +187,15 @@ public class MissionService implements INetworkDispatch { }); } + public void handleMissionAbort(CreatureObject creature, MissionObject mission) { + MissionObjective objective = mission.getObjective(); + + if (objective != null) + objective.abort(); + + core.objectService.destroyObject(mission.getObjectId()); + } + private void loadMissionEntryCounts() { File missionFolder = new File("./clientdata/string/en/mission"); File[] missionFiles = missionFolder.listFiles(); @@ -177,7 +218,7 @@ public class MissionService implements INetworkDispatch { } } if (gotCount == false) { - System.out.println("!NO ENTRY COUNT FOR " + missionStf); + //System.out.println("!NO ENTRY COUNT FOR " + missionStf); continue; } } catch (Exception e) { e.printStackTrace(); } @@ -192,7 +233,7 @@ public class MissionService implements INetworkDispatch { int ranEntryNum = 1; if (entryCounts.get(missionStf) != null) { ranEntryNum = ran.nextInt(entryCounts.get(missionStf)); } - else { System.out.println(missionStf + " was not found in entryCount and is using entry #1"); } + //else { System.out.println(missionStf + " was not found in entryCount and is using entry #1"); } if (ranEntryNum == 0) return 1; @@ -298,19 +339,23 @@ public class MissionService implements INetworkDispatch { } private void createMissionObjective(CreatureObject creature, MissionObject mission) { - String type = mission.getMissionType(); - System.out.println("Type: " + type); - switch(type) { + switch(mission.getMissionType()) { case "deliver": - DeliveryMissionObjective objective = new DeliveryMissionObjective(mission); + DeliveryMissionObjective deliveryObjective = new DeliveryMissionObjective(mission); - mission.setObjective(objective); + mission.setObjective(deliveryObjective); - objective.activate(); - System.out.println("Went here!"); + deliveryObjective.activate(); break; + case "destroy": + DestroyMissionObjective destroyObjective = new DestroyMissionObjective(mission); + + mission.setObjective(destroyObjective); + + destroyObjective.activate(); + break; default: break; } @@ -331,13 +376,14 @@ public class MissionService implements INetworkDispatch { mission.setMissionLevel(5); + // TODO: Use pre-defined commoner locations Point3D startLocation = SpawnPoint.getRandomPosition(player.getPosition(), (float) 50, (float) 300, player.getPlanetId()); Point3D destination = SpawnPoint.getRandomPosition(startLocation, (float) 50, (float) 500, player.getPlanetId()); mission.setStartLocation(startLocation, player.getPlanet().name); mission.setDestination(destination, player.getPlanet().name); - mission.setCreditReward((int) (50 * ((startLocation.getDistance2D(destination) / 10)))); + mission.setCreditReward((int) (50 + ((startLocation.getDistance2D(destination) / 10)))); mission.setMissionTemplateObject(CRC.StringtoCRC("object/tangible/mission/shared_mission_datadisk.iff")); mission.setMissionTargetName("Datadisk"); @@ -357,6 +403,7 @@ public class MissionService implements INetworkDispatch { private void randomBountyMission(SWGObject player, MissionObject mission) { } + public enum TerminalType {; public static final int GENERIC = 1; public static final int BOUNTYHUNTER = 2;