diff --git a/scripts/commands/activatequest.py b/scripts/commands/activatequest.py index f17c5523..d101d2b3 100644 --- a/scripts/commands/activatequest.py +++ b/scripts/commands/activatequest.py @@ -4,10 +4,10 @@ def setup(): return def run(core, actor, target, commandString): + if core.questService.adminActivateQuest(actor, commandString) is False: actor.sendSystemMessage(' \\#FE2EF7 [GM] \\#FFFFFF activateQuest: Error. You have specified an invalid quest.', 0) return - - core.questService.sendQuestWindow(actor, actor.getPlayerObject().getQuestJournal().get(0)) + #core.questService.sendQuestWindow(actor, commandString) actor.sendSystemMessage(' \\#FE2EF7 [GM] \\#FFFFFF activateQuest: Command completed successfully.', 0) return diff --git a/scripts/commands/setgodmode.py b/scripts/commands/setgodmode.py index aeff3947..2206ce23 100644 --- a/scripts/commands/setgodmode.py +++ b/scripts/commands/setgodmode.py @@ -1,12 +1,9 @@ # This file will be updated at a later date with a new command. import sys -from resources.common import ProsePackage -from resources.common import OutOfBand -from protocol.swg import CreateClientPathMessage + def setup(): return def run(core, actor, target, commandString): - core.questService.giveBasicQuest(actor) return \ No newline at end of file diff --git a/scripts/object/tangible/quest/speeder_debris_wiring.py b/scripts/object/tangible/quest/speeder_debris_wiring.py index ccad8904..be9c7f1f 100644 --- a/scripts/object/tangible/quest/speeder_debris_wiring.py +++ b/scripts/object/tangible/quest/speeder_debris_wiring.py @@ -1,4 +1,5 @@ import sys def setup(core, object): + object.setAttachment('radial_filename', 'object/quest/speeder_debris_wiring') return \ No newline at end of file diff --git a/scripts/object/tangible/quest/speeder_junk_engine.py b/scripts/object/tangible/quest/speeder_junk_engine.py index ccad8904..b420c04f 100644 --- a/scripts/object/tangible/quest/speeder_junk_engine.py +++ b/scripts/object/tangible/quest/speeder_junk_engine.py @@ -1,4 +1,5 @@ import sys def setup(core, object): + object.setAttachment('radial_filename', 'object/quest/speeder_junk_engine') return \ No newline at end of file diff --git a/scripts/object/tangible/quest/speeder_junk_power.py b/scripts/object/tangible/quest/speeder_junk_power.py index ccad8904..3355eabb 100644 --- a/scripts/object/tangible/quest/speeder_junk_power.py +++ b/scripts/object/tangible/quest/speeder_junk_power.py @@ -1,4 +1,5 @@ import sys def setup(core, object): + object.setAttachment('radial_filename', 'object/quest/speeder_junk_power') return \ No newline at end of file diff --git a/scripts/object/tangible/quest/speeder_junk_steering.py b/scripts/object/tangible/quest/speeder_junk_steering.py index ccad8904..f99a2770 100644 --- a/scripts/object/tangible/quest/speeder_junk_steering.py +++ b/scripts/object/tangible/quest/speeder_junk_steering.py @@ -1,4 +1,5 @@ import sys def setup(core, object): + object.setAttachment('radial_filename', 'object/quest/speeder_junk_steering') return \ No newline at end of file diff --git a/scripts/quest_rewards/item_deed_landspeeder_x38_02_01.py b/scripts/quest_rewards/item_deed_landspeeder_x38_02_01.py new file mode 100644 index 00000000..67c43fef --- /dev/null +++ b/scripts/quest_rewards/item_deed_landspeeder_x38_02_01.py @@ -0,0 +1,4 @@ +import sys + +def run(): + return "object/tangible/deed/vehicle_deed/shared_landspeeder_xp38_deed.iff" \ No newline at end of file diff --git a/scripts/radial/object/quest/speeder_debris_wiring.py b/scripts/radial/object/quest/speeder_debris_wiring.py new file mode 100644 index 00000000..db8b6e25 --- /dev/null +++ b/scripts/radial/object/quest/speeder_debris_wiring.py @@ -0,0 +1,13 @@ +from resources.common import RadialOptions +import sys + +def createRadial(core, owner, target, radials): + radials.add(RadialOptions(0, 21, 1, core.questService.getQuestItemRadialName(owner, target.getTemplate()))) + radials.add(RadialOptions(0, 7, 1, '')) + return + +def handleSelection(core, owner, target, option): + if option == 21 and target: + core.questService.handleQuestItemRadialSelection(owner, target) + return + return \ No newline at end of file diff --git a/scripts/radial/object/quest/speeder_junk_engine.py b/scripts/radial/object/quest/speeder_junk_engine.py new file mode 100644 index 00000000..db8b6e25 --- /dev/null +++ b/scripts/radial/object/quest/speeder_junk_engine.py @@ -0,0 +1,13 @@ +from resources.common import RadialOptions +import sys + +def createRadial(core, owner, target, radials): + radials.add(RadialOptions(0, 21, 1, core.questService.getQuestItemRadialName(owner, target.getTemplate()))) + radials.add(RadialOptions(0, 7, 1, '')) + return + +def handleSelection(core, owner, target, option): + if option == 21 and target: + core.questService.handleQuestItemRadialSelection(owner, target) + return + return \ No newline at end of file diff --git a/scripts/radial/object/quest/speeder_junk_power.py b/scripts/radial/object/quest/speeder_junk_power.py new file mode 100644 index 00000000..db8b6e25 --- /dev/null +++ b/scripts/radial/object/quest/speeder_junk_power.py @@ -0,0 +1,13 @@ +from resources.common import RadialOptions +import sys + +def createRadial(core, owner, target, radials): + radials.add(RadialOptions(0, 21, 1, core.questService.getQuestItemRadialName(owner, target.getTemplate()))) + radials.add(RadialOptions(0, 7, 1, '')) + return + +def handleSelection(core, owner, target, option): + if option == 21 and target: + core.questService.handleQuestItemRadialSelection(owner, target) + return + return \ No newline at end of file diff --git a/scripts/radial/object/quest/speeder_junk_steering.py b/scripts/radial/object/quest/speeder_junk_steering.py new file mode 100644 index 00000000..db8b6e25 --- /dev/null +++ b/scripts/radial/object/quest/speeder_junk_steering.py @@ -0,0 +1,13 @@ +from resources.common import RadialOptions +import sys + +def createRadial(core, owner, target, radials): + radials.add(RadialOptions(0, 21, 1, core.questService.getQuestItemRadialName(owner, target.getTemplate()))) + radials.add(RadialOptions(0, 7, 1, '')) + return + +def handleSelection(core, owner, target, option): + if option == 21 and target: + core.questService.handleQuestItemRadialSelection(owner, target) + return + return \ No newline at end of file diff --git a/src/protocol/swg/ErrorMessage.java b/src/protocol/swg/ErrorMessage.java index 02c4ad00..0181b292 100644 --- a/src/protocol/swg/ErrorMessage.java +++ b/src/protocol/swg/ErrorMessage.java @@ -30,10 +30,12 @@ public class ErrorMessage extends SWGMessage { private String errorType; private String errorMessage; + private boolean isFatal; - public ErrorMessage(String errorType, String errorMessage) { + public ErrorMessage(String errorType, String errorMessage, boolean isFatal) { this.errorType = errorType; this.errorMessage = errorMessage; + this.isFatal = isFatal; } public void deserialize(IoBuffer data) { @@ -47,7 +49,7 @@ public class ErrorMessage extends SWGMessage { result.putInt(Opcodes.ErrorMessage); result.put(getAsciiString(errorType)); result.put(getAsciiString(errorMessage)); - result.put((byte)0); + result.put((byte) (isFatal ? 1 : 0)); return result.flip(); } diff --git a/src/protocol/swg/objectControllerObjects/ShowLootBox.java b/src/protocol/swg/objectControllerObjects/ShowLootBox.java index c20121a3..dc9fde15 100644 --- a/src/protocol/swg/objectControllerObjects/ShowLootBox.java +++ b/src/protocol/swg/objectControllerObjects/ShowLootBox.java @@ -22,6 +22,7 @@ package protocol.swg.objectControllerObjects; import java.nio.ByteOrder; +import java.util.ArrayList; import java.util.Vector; import org.apache.mina.core.buffer.IoBuffer; @@ -32,15 +33,15 @@ import protocol.swg.ObjControllerMessage; public class ShowLootBox extends ObjControllerObject { private long playerId; - private Vector rewards; - private SWGObject reward; + private ArrayList rewards; + private long reward; - public ShowLootBox(long playerId, SWGObject reward) { + public ShowLootBox(long playerId, long reward) { this.playerId = playerId; this.reward = reward; } - public ShowLootBox(long playerId, Vector rewards) { + public ShowLootBox(long playerId, ArrayList rewards) { this.playerId = playerId; this.rewards = rewards; } @@ -67,11 +68,11 @@ public class ShowLootBox extends ObjControllerObject { if (rewards == null) { buffer.putInt(1); - buffer.putLong(reward.getObjectId()); + buffer.putLong(reward); } else { buffer.putInt(rewards.size()); - for(SWGObject obj : rewards) { - buffer.putLong(obj.getObjectID()); + for(Long id : rewards) { + buffer.putLong(id); } } return buffer.flip(); diff --git a/src/resources/common/SpawnPoint.java b/src/resources/common/SpawnPoint.java index f0fac9af..6c0a0d5c 100644 --- a/src/resources/common/SpawnPoint.java +++ b/src/resources/common/SpawnPoint.java @@ -21,6 +21,7 @@ ******************************************************************************/ package resources.common; +import java.io.Serializable; import java.util.Random; import main.NGECore; @@ -31,7 +32,9 @@ import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; @Persistent -public class SpawnPoint { +public class SpawnPoint implements Serializable{ + + private static final long serialVersionUID = 1L; private Point3D position; private Quaternion orientation; diff --git a/src/resources/objects/player/PlayerObject.java b/src/resources/objects/player/PlayerObject.java index ea24c4cf..fa4910eb 100644 --- a/src/resources/objects/player/PlayerObject.java +++ b/src/resources/objects/player/PlayerObject.java @@ -45,9 +45,8 @@ import resources.objects.intangible.IntangibleObject; import resources.objects.resource.ResourceContainerObject; import resources.objects.waypoint.WaypointObject; import resources.quest.Quest; +import services.quest.QuestItem; import engine.clients.Client; -import engine.resources.common.CRC; -import engine.resources.common.StringUtilities; import engine.resources.objects.Baseline; import engine.resources.scene.Planet; import engine.resources.scene.Point3D; @@ -96,6 +95,7 @@ public class PlayerObject extends IntangibleObject implements Serializable { baseline.put("holoEmote", ""); baseline.put("holoEmoteUses", 0); baseline.put("activeMissions", new ArrayList()); // TODO: Look at MissionCriticalObject in CREO4, could use that instead of this + baseline.put("questRetrieveItemTemplates", new TreeMap()); return baseline; } @@ -187,7 +187,7 @@ public class PlayerObject extends IntangibleObject implements Serializable { baseline.put("maxConsumable", 100); baseline.put("waypointList", new SWGMap(this, 9, 16, false)); baseline.put("defendersList", new SWGSet(this, 9, 17, false)); - baseline.put("kills", 0); + baseline.put("killMeterPoints", 0); baseline.put("19", 0); baseline.put("pet", (long) 0); baseline.put("petAbilities", new SWGList(this, 9, 21, false)); @@ -595,6 +595,16 @@ public class PlayerObject extends IntangibleObject implements Serializable { return (SWGList) getBaseline(8).get("questJournal"); } + @SuppressWarnings("unchecked") + public TreeMap getQuestRetrieveItemTemplates() { + return (TreeMap) otherVariables.get("questRetrieveItemTemplates"); + } + + public boolean hasRetrieveItemTemplate(String template) { + TreeMap templates = getQuestRetrieveItemTemplates(); + return templates.containsKey(template); + } + public int getActiveQuest() { return (int) getBaseline(8).get("activeQuest"); } @@ -769,20 +779,16 @@ public class PlayerObject extends IntangibleObject implements Serializable { return (SWGSet) getBaseline(8).get("defendersList"); } - public int getKills() { - return (int) getBaseline(9).get("kills"); + public int getKillMeterPoints() { + return (int) getBaseline(9).get("killMeterPoints"); } - public void setKills(int kills) { + public void setKillMeterPoints(int points) { if (getClient() != null) { - getClient().getSession().write(getBaseline(9).set("kills", kills)); + getClient().getSession().write(getBaseline(9).set("killMeterPoints", points)); } } - public void addKills(int kills) { - setKills(getKills() + kills); - } - public long getPet() { return (long) getBaseline(9).get("pet"); } diff --git a/src/resources/quest/Quest.java b/src/resources/quest/Quest.java index f38764f5..078731cf 100644 --- a/src/resources/quest/Quest.java +++ b/src/resources/quest/Quest.java @@ -22,6 +22,7 @@ package resources.quest; import java.io.Serializable; +import java.util.BitSet; import org.apache.mina.core.buffer.IoBuffer; @@ -33,11 +34,15 @@ public class Quest extends Delta implements Serializable { private static final long serialVersionUID = 1L; private long ownerId; - private short activeStep = 1; - private short completedStep; + private int activeStep; // Quest starts at step 0 + private BitSet activeStepBitmask = new BitSet(16); + private BitSet completedStepBitmask = new BitSet(16); + private boolean isCompleted = false; + private boolean recievedAward = false; private String name; - private String filePath; + + private long waypointId; public Quest() {} @@ -45,10 +50,10 @@ public class Quest extends Delta implements Serializable { this.ownerId = ownerId; if (name.endsWith(".qst")) { - this.filePath = "quest/"+name; + //this.filePath = "quest/"+name; this.name = name.split(".qst")[0]; } else { - this.filePath = "quest/"+name+".qst"; + //this.filePath = "quest/"+name+".qst"; this.name = name; } @@ -56,7 +61,6 @@ public class Quest extends Delta implements Serializable { String[] split = name.split("/"); this.name = split[split.length - 1]; } - } public long getOwnerId() { @@ -67,38 +71,38 @@ public class Quest extends Delta implements Serializable { this.ownerId = ownerId; } - public short getActiveStep() { + public int getActiveStep() { return activeStep; } - public void setActiveStep(short activeStep) { + public void setActiveStep(int activeStep) { this.activeStep = activeStep; } - public short getCompletedStep() { - return completedStep; - } - - public void setCompletedStep(short completedStep) { - this.completedStep = completedStep; - } - public boolean isCompleted() { return isCompleted; } public void setCompleted(boolean isCompleted) { + if (isCompleted) { + //activeStepBitmask.set(activeStep, false); + completedStepBitmask.set(activeStep); + } this.isCompleted = isCompleted; } + public boolean hasRecievedAward() { + return recievedAward; + } + + public void setRecievedAward(boolean recievedAward) { + this.recievedAward = recievedAward; + } + public String getName() { return name; } - public String getFilePath() { - return filePath; - } - public int getCrc() { return CRC.StringtoCRC(getCrcName()); } @@ -106,25 +110,71 @@ public class Quest extends Delta implements Serializable { public String getCrcName() { return "quest/" + name; } + + public long getWaypointId() { + return waypointId; + } + public void setWaypointId(long waypointId) { + this.waypointId = waypointId; + } + + public void incrementQuestStep() { + activeStepBitmask.set(activeStep, false); + completedStepBitmask.set(activeStep); + this.activeStep++; + activeStepBitmask.set(activeStep); + } + public byte[] getBytes() { + byte[] activeStepBytes = activeStepBitmask.toByteArray(); + byte[] completedStepBytes = completedStepBitmask.toByteArray(); + IoBuffer buffer = createBuffer(23); buffer.put((byte) 0); buffer.putInt(getCrc()); - buffer.putLong(ownerId); + buffer.putLong(ownerId); // quest giver id? - buffer.putShort(activeStep); - buffer.putShort(completedStep); + // Probably a MUCH better way of doing this, but... well... I can't stand bitmasks. + switch (activeStepBytes.length) { + case 0: + buffer.putShort((short) 0); + break; + + case 1: + buffer.put(activeStepBytes[0]); + buffer.put((byte) 0); + break; + + case 2: + buffer.put(activeStepBytes); + break; + } - buffer.put((byte) ((isCompleted) ? 1 : 0)); // isCompleted + switch (completedStepBytes.length) { + case 0: + buffer.putShort((short) 0); + break; + + case 1: + buffer.put(completedStepBytes[0]); + buffer.put((byte) 0); + break; + + case 2: + buffer.put(completedStepBytes); + break; + } + + buffer.put((byte) ((isCompleted) ? 1 : 0)); buffer.putInt(0); // questCounter - buffer.put((byte) 0); // ? + buffer.put((byte) ((recievedAward) ? 1 : 0)); buffer.flip(); - + return buffer.array(); } diff --git a/src/services/LoginService.java b/src/services/LoginService.java index 2b3f02b5..ac16029e 100644 --- a/src/services/LoginService.java +++ b/src/services/LoginService.java @@ -125,7 +125,7 @@ public class LoginService implements INetworkDispatch{ } // No matter what, this will always show that the login server is unavailable at this time. Removing the error message will just keep the connecting message up. - ErrorMessage errMsg = new ErrorMessage("Wrong Password", "The username or password you entered was incorrect."); + ErrorMessage errMsg = new ErrorMessage("Wrong Password", "The username or password you entered was incorrect.", false); session.write(errMsg.serialize()); Disconnect disconnect = new Disconnect((Integer)session.getAttribute("connectionId"), 6); @@ -137,7 +137,7 @@ public class LoginService implements INetworkDispatch{ } if(!version.equals("20111130-15:46")) { - ErrorMessage clientErr = new ErrorMessage("Invalid Client", "The version of your client is invalid."); + ErrorMessage clientErr = new ErrorMessage("Invalid Client", "The version of your client is invalid.", true); session.write(clientErr.serialize()); Disconnect disconnect = new Disconnect((Integer)session.getAttribute("connectionId"), 6); @@ -159,7 +159,7 @@ public class LoginService implements INetworkDispatch{ if (!core.getActiveConnectionsMap().containsKey(session)) { Disconnect disconnect = new Disconnect((Integer)session.getAttribute("connectionId"), 6); session.write(disconnect); - ErrorMessage errMsg = new ErrorMessage("Error Logging In", "Your client could not be added to the connections at this time."); + ErrorMessage errMsg = new ErrorMessage("Error Logging In", "Your client could not be added to the connections at this time.", false); session.write(errMsg.serialize()); session.close(false); @@ -175,7 +175,7 @@ public class LoginService implements INetworkDispatch{ LoginClientToken clientToken = new LoginClientToken(client.getSessionKey(), id, user); CharacterCreationDisabled charCreationDisabled = new CharacterCreationDisabled(0); - StationIdHasJediSlot jediSlot = new StationIdHasJediSlot(false); + StationIdHasJediSlot jediSlot = new StationIdHasJediSlot(false); // Ziggy - shows a pop-up at the character selection screen, saying that this account has an unused Unlocked Slot when set to true. ServerNowEpochTime time = new ServerNowEpochTime((int) (System.currentTimeMillis() / 1000)); //System.out.println("ServerNowEpochTime " + (int) (System.currentTimeMillis() / 1000)); //tools.CharonPacketUtils.printAnalysis(time.serialize(), "ServerNowEpochTime"); diff --git a/src/services/PlayerService.java b/src/services/PlayerService.java index 996a2214..d9dad2b3 100644 --- a/src/services/PlayerService.java +++ b/src/services/PlayerService.java @@ -1307,7 +1307,7 @@ public class PlayerService implements INetworkDispatch { inventory.add(item); - ObjControllerMessage objController = new ObjControllerMessage(11, new ShowLootBox(reciever.getObjectID(), item)); + ObjControllerMessage objController = new ObjControllerMessage(11, new ShowLootBox(reciever.getObjectID(), item.getObjectID())); client.getSession().write(objController.serialize()); } @@ -1331,11 +1331,14 @@ public class PlayerService implements INetworkDispatch { if (inventory == null) return; + ArrayList itemsId = new ArrayList(); + for (SWGObject obj : items) { inventory.add(obj); + itemsId.add(obj.getObjectID()); } - ObjControllerMessage objController = new ObjControllerMessage(11, new ShowLootBox(reciever.getObjectID(), items)); + ObjControllerMessage objController = new ObjControllerMessage(11, new ShowLootBox(reciever.getObjectID(), itemsId)); client.getSession().write(objController.serialize()); } diff --git a/src/services/SimulationService.java b/src/services/SimulationService.java index 874ac673..0d3366fe 100644 --- a/src/services/SimulationService.java +++ b/src/services/SimulationService.java @@ -185,11 +185,15 @@ public class SimulationService implements INetworkDispatch { } public void insertSnapShotObjects() { + System.out.println("Inserting snapshot buildings..."); List objectList = new ArrayList(core.objectService.getObjectList().values()); for(SWGObject obj : objectList) { - if(obj.getParentId() == 0 && /*(*/obj.isInSnapshot() /*|| obj.getAttachment("isBuildout") != null)*/) + // Buildings are inserted via another method from the odb, so no need to load them into the quadtree as well + if(obj.getParentId() == 0 && (obj.isInSnapshot() || obj.getAttachment("isBuildout") != null) && obj.getAttachment("buildoutBuilding") == null) { add(obj, obj.getPosition().x, obj.getPosition().z); + } } + System.out.println("Snapshots inserted!"); } public void insertPersistentBuildings() { diff --git a/src/services/object/ObjectService.java b/src/services/object/ObjectService.java index 9bd27972..94b7182e 100644 --- a/src/services/object/ObjectService.java +++ b/src/services/object/ObjectService.java @@ -236,7 +236,7 @@ public class ObjectService implements INetworkDispatch { } public void loadServerTemplates() { - System.out.println("Loading server templates..."); + System.out.println("Loading server templates... (" + loadServerTemplateTasks.size() + " templates)"); loadServerTemplateTasks.forEach(Runnable::run); loadServerTemplateTasks.clear(); System.out.println("Finished loading server templates..."); @@ -1440,7 +1440,7 @@ public class ObjectService implements INetworkDispatch { if (core.getSWGObjectODB().contains(objectId) && !duplicate.containsValue(objectId)) continue; containers.add(objectId); - object = createObject(template, objectId, planet, new Point3D(px + x1, py, pz + z1), new Quaternion(qw, qx, qy, qz), null, true, false); + object = createObject(template, objectId, planet, new Point3D(px + x1, py, pz + z1), new Quaternion(qw, qx, qy, qz), null, true, true); object.setAttachment("childObjects", null); /*if (!duplicate.containsValue(objectId)) { @@ -1449,7 +1449,7 @@ public class ObjectService implements INetworkDispatch { ((BuildingObject) object).getTransaction().commitSync(); }*/ } else { - object = createObject(template, 0, planet, new Point3D(px + x1, py, pz + z1), new Quaternion(qw, qx, qy, qz), null, false, false); + object = createObject(template, 0, planet, new Point3D(px + x1, py, pz + z1), new Quaternion(qw, qx, qy, qz), null, false, true); } if(object == null) continue; @@ -1459,7 +1459,7 @@ public class ObjectService implements INetworkDispatch { if (!duplicate.containsValue(objectId) && object instanceof BuildingObject && portalCRC != 0) persistentBuildings.add((BuildingObject) object); } else if(containerId != 0) { - object = createObject(template, 0, planet, new Point3D(px, py, pz), new Quaternion(qw, qx, qy, qz), null, false, false); + object = createObject(template, 0, planet, new Point3D(px, py, pz), new Quaternion(qw, qx, qy, qz), null, false, true); if(containers.contains(containerId)) { object.setContainerPermissions(WorldPermissions.WORLD_PERMISSIONS); object.setisInSnapshot(false); @@ -1477,7 +1477,7 @@ public class ObjectService implements INetworkDispatch { parent.add(object); } } else { - object = createObject(template, 0, planet, new Point3D(px + x1, py, pz + z1), new Quaternion(qw, qx, qy, qz), null, false, false); + object = createObject(template, 0, planet, new Point3D(px + x1, py, pz + z1), new Quaternion(qw, qx, qy, qz), null, false, true); object.setContainerPermissions(WorldPermissions.WORLD_PERMISSIONS); } @@ -1494,6 +1494,7 @@ public class ObjectService implements INetworkDispatch { } for(BuildingObject building : persistentBuildings) { + building.setAttachment("buildoutBuilding", true); core.getSWGObjectODB().put(building.getObjectID(), building); destroyObject(building); } diff --git a/src/services/quest/QuestData.java b/src/services/quest/QuestData.java index cccc2dfe..935059c4 100644 --- a/src/services/quest/QuestData.java +++ b/src/services/quest/QuestData.java @@ -26,8 +26,7 @@ import java.util.Vector; public class QuestData { private String name; - private String fileName; - + private Vector tasks; private int tasksAvailableId; @@ -36,8 +35,7 @@ public class QuestData { public QuestData(String questName) { if (questName.endsWith(".qst")) { - this.fileName = questName; - + if (questName.contains("/")) { String[] split = questName.split("/"); questName = split[split.length - 1]; @@ -54,10 +52,6 @@ public class QuestData { return name; } - public String getFileName() { - return fileName; - } - public Vector getTasks() { return tasks; } diff --git a/src/services/quest/QuestItem.java b/src/services/quest/QuestItem.java new file mode 100644 index 00000000..773af9f9 --- /dev/null +++ b/src/services/quest/QuestItem.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * 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.quest; + +public class QuestItem { + private String questName; + private int task; + + public QuestItem(String questName, int task) { + this.questName = questName; + this.task = task; + } + + public String getQuestName() { + return questName; + } + + public int getTask() { + return task; + } +} diff --git a/src/services/quest/QuestList.java b/src/services/quest/QuestList.java new file mode 100644 index 00000000..fae203e6 --- /dev/null +++ b/src/services/quest/QuestList.java @@ -0,0 +1,341 @@ +/******************************************************************************* + * 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.quest; + +public class QuestList { + private int level; + private int tier; + private int rewardExperienceAmount; + private int rewardFactionAmount; + private int rewardBankCredits; + private int rewardLootCount; + private int rewardLootCount2; + private int rewardLootCount3; + private int rewardExclusiveLootCount; + private int rewardExclusiveLootCount2; + private int rewardExclusiveLootCount3; + private int rewardExclusiveLootCount4; + private int rewardExclusiveLootCount5; + private int rewardExclusiveLootCount6; + private int rewardExclusiveLootCount7; + private int rewardExclusiveLootCount8; + private int rewardExclusiveLootCount9; + private int rewardExclusiveLootCount10; + private String type; + private String journalEntryTitle; + private String journalEntryDescription; + private String journalEntryCompletionSummary; + private String category; + private String visible; + private String prerequisteQuests; + private String exclusionQuests; + private String rewardExperienceType; + private String rewardFactionType; + private String rewardLootName; + private String rewardLootName2; + private String rewardLootName3; + private String rewardExclusiveLootName; + private String rewardExclusiveLootName2; + private String rewardExclusiveLootName3; + private String rewardExclusiveLootName4; + private String rewardExclusiveLootName5; + private String rewardExclusiveLootName6; + private String rewardExclusiveLootName7; + private String rewardExclusiveLootName8; + private String rewardExclusiveLootName9; + private String rewardExclusiveLootName10; + private String rewardBadge; + + private boolean allowRepeats; + private boolean completeWhenTasksComplete; + + public QuestList() { } + + public int getLevel() { + return level; + } + public void setLevel(int level) { + this.level = level; + } + public int getTier() { + return tier; + } + public void setTier(int tier) { + this.tier = tier; + } + public int getRewardExperienceAmount() { + return rewardExperienceAmount; + } + public void setRewardExperienceAmount(int rewardExperienceAmount) { + this.rewardExperienceAmount = rewardExperienceAmount; + } + public int getRewardFactionAmount() { + return rewardFactionAmount; + } + public void setRewardFactionAmount(int rewardFactionAmount) { + this.rewardFactionAmount = rewardFactionAmount; + } + public int getRewardBankCredits() { + return rewardBankCredits; + } + public void setRewardBankCredits(int rewardBankCredits) { + this.rewardBankCredits = rewardBankCredits; + } + public int getRewardLootCount() { + return rewardLootCount; + } + public void setRewardLootCount(int rewardLootCount) { + this.rewardLootCount = rewardLootCount; + } + public int getRewardLootCount2() { + return rewardLootCount2; + } + public void setRewardLootCount2(int rewardLootCount2) { + this.rewardLootCount2 = rewardLootCount2; + } + public int getRewardLootCount3() { + return rewardLootCount3; + } + public void setRewardLootCount3(int rewardLootCount3) { + this.rewardLootCount3 = rewardLootCount3; + } + public int getRewardExclusiveLootCount() { + return rewardExclusiveLootCount; + } + public void setRewardExclusiveLootCount(int rewardExclusiveLootCount) { + this.rewardExclusiveLootCount = rewardExclusiveLootCount; + } + public int getRewardExclusiveLootCount2() { + return rewardExclusiveLootCount2; + } + public void setRewardExclusiveLootCount2(int rewardExclusiveLootCount2) { + this.rewardExclusiveLootCount2 = rewardExclusiveLootCount2; + } + public int getRewardExclusiveLootCount3() { + return rewardExclusiveLootCount3; + } + public void setRewardExclusiveLootCount3(int rewardExclusiveLootCount3) { + this.rewardExclusiveLootCount3 = rewardExclusiveLootCount3; + } + public int getRewardExclusiveLootCount4() { + return rewardExclusiveLootCount4; + } + public void setRewardExclusiveLootCount4(int rewardExclusiveLootCount4) { + this.rewardExclusiveLootCount4 = rewardExclusiveLootCount4; + } + public int getRewardExclusiveLootCount5() { + return rewardExclusiveLootCount5; + } + public void setRewardExclusiveLootCount5(int rewardExclusiveLootCount5) { + this.rewardExclusiveLootCount5 = rewardExclusiveLootCount5; + } + public int getRewardExclusiveLootCount6() { + return rewardExclusiveLootCount6; + } + public void setRewardExclusiveLootCount6(int rewardExclusiveLootCount6) { + this.rewardExclusiveLootCount6 = rewardExclusiveLootCount6; + } + public int getRewardExclusiveLootCount7() { + return rewardExclusiveLootCount7; + } + public void setRewardExclusiveLootCount7(int rewardExclusiveLootCount7) { + this.rewardExclusiveLootCount7 = rewardExclusiveLootCount7; + } + public int getRewardExclusiveLootCount8() { + return rewardExclusiveLootCount8; + } + public void setRewardExclusiveLootCount8(int rewardExclusiveLootCount8) { + this.rewardExclusiveLootCount8 = rewardExclusiveLootCount8; + } + public int getRewardExclusiveLootCount9() { + return rewardExclusiveLootCount9; + } + public void setRewardExclusiveLootCount9(int rewardExclusiveLootCount9) { + this.rewardExclusiveLootCount9 = rewardExclusiveLootCount9; + } + public int getRewardExclusiveLootCount10() { + return rewardExclusiveLootCount10; + } + public void setRewardExclusiveLootCount10(int rewardExclusiveLootCount10) { + this.rewardExclusiveLootCount10 = rewardExclusiveLootCount10; + } + public String getType() { + return type; + } + public void setType(String type) { + this.type = type; + } + public String getJournalEntryTitle() { + return journalEntryTitle; + } + public void setJournalEntryTitle(String journalEntryTitle) { + this.journalEntryTitle = journalEntryTitle; + } + public String getJournalEntryDescription() { + return journalEntryDescription; + } + public void setJournalEntryDescription(String journalEntryDescription) { + this.journalEntryDescription = journalEntryDescription; + } + public String getJournalEntryCompletionSummary() { + return journalEntryCompletionSummary; + } + public void setJournalEntryCompletionSummary( + String journalEntryCompletionSummary) { + this.journalEntryCompletionSummary = journalEntryCompletionSummary; + } + public String getCategory() { + return category; + } + public void setCategory(String category) { + this.category = category; + } + public String getVisible() { + return visible; + } + public void setVisible(String visible) { + this.visible = visible; + } + public String getPrerequisteQuests() { + return prerequisteQuests; + } + public void setPrerequisteQuests(String prerequisteQuests) { + this.prerequisteQuests = prerequisteQuests; + } + public String getExclusionQuests() { + return exclusionQuests; + } + public void setExclusionQuests(String exclusionQuests) { + this.exclusionQuests = exclusionQuests; + } + public String getRewardExperienceType() { + return rewardExperienceType; + } + public void setRewardExperienceType(String rewardExperienceType) { + this.rewardExperienceType = rewardExperienceType; + } + public String getRewardFactionType() { + return rewardFactionType; + } + public void setRewardFactionType(String rewardFactionType) { + this.rewardFactionType = rewardFactionType; + } + public String getRewardLootName() { + return rewardLootName; + } + public void setRewardLootName(String rewardLootName) { + this.rewardLootName = rewardLootName; + } + public String getRewardLootName2() { + return rewardLootName2; + } + public void setRewardLootName2(String rewardLootName2) { + this.rewardLootName2 = rewardLootName2; + } + public String getRewardLootName3() { + return rewardLootName3; + } + public void setRewardLootName3(String rewardLootName3) { + this.rewardLootName3 = rewardLootName3; + } + public String getRewardExclusiveLootName() { + return rewardExclusiveLootName; + } + public void setRewardExclusiveLootName(String rewardExclusiveLootName) { + this.rewardExclusiveLootName = rewardExclusiveLootName; + } + public String getRewardExclusiveLootName2() { + return rewardExclusiveLootName2; + } + public void setRewardExclusiveLootName2(String rewardExclusiveLootName2) { + this.rewardExclusiveLootName2 = rewardExclusiveLootName2; + } + public String getRewardExclusiveLootName3() { + return rewardExclusiveLootName3; + } + public void setRewardExclusiveLootName3(String rewardExclusiveLootName3) { + this.rewardExclusiveLootName3 = rewardExclusiveLootName3; + } + public String getRewardExclusiveLootName4() { + return rewardExclusiveLootName4; + } + public void setRewardExclusiveLootName4(String rewardExclusiveLootName4) { + this.rewardExclusiveLootName4 = rewardExclusiveLootName4; + } + public String getRewardExclusiveLootName5() { + return rewardExclusiveLootName5; + } + public void setRewardExclusiveLootName5(String rewardExclusiveLootName5) { + this.rewardExclusiveLootName5 = rewardExclusiveLootName5; + } + public String getRewardExclusiveLootName6() { + return rewardExclusiveLootName6; + } + public void setRewardExclusiveLootName6(String rewardExclusiveLootName6) { + this.rewardExclusiveLootName6 = rewardExclusiveLootName6; + } + public String getRewardExclusiveLootName7() { + return rewardExclusiveLootName7; + } + public void setRewardExclusiveLootName7(String rewardExclusiveLootName7) { + this.rewardExclusiveLootName7 = rewardExclusiveLootName7; + } + public String getRewardExclusiveLootName8() { + return rewardExclusiveLootName8; + } + public void setRewardExclusiveLootName8(String rewardExclusiveLootName8) { + this.rewardExclusiveLootName8 = rewardExclusiveLootName8; + } + public String getRewardExclusiveLootName9() { + return rewardExclusiveLootName9; + } + public void setRewardExclusiveLootName9(String rewardExclusiveLootName9) { + this.rewardExclusiveLootName9 = rewardExclusiveLootName9; + } + public String getRewardExclusiveLootName10() { + return rewardExclusiveLootName10; + } + public void setRewardExclusiveLootName10(String rewardExclusiveLootName10) { + this.rewardExclusiveLootName10 = rewardExclusiveLootName10; + } + public String getRewardBadge() { + return rewardBadge; + } + public void setRewardBadge(String rewardBadge) { + this.rewardBadge = rewardBadge; + } + public boolean isAllowRepeats() { + return allowRepeats; + } + public void setAllowRepeats(boolean allowRepeats) { + this.allowRepeats = allowRepeats; + } + + public boolean isCompleteWhenTasksComplete() { + return completeWhenTasksComplete; + } + + public void setCompleteWhenTasksComplete(boolean completeWhenTasksComplete) { + this.completeWhenTasksComplete = completeWhenTasksComplete; + } + +} diff --git a/src/services/quest/QuestService.java b/src/services/quest/QuestService.java index 243f1e54..dbaf21d3 100644 --- a/src/services/quest/QuestService.java +++ b/src/services/quest/QuestService.java @@ -21,31 +21,19 @@ ******************************************************************************/ package services.quest; -import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.File; -import java.io.IOException; -import java.nio.ByteOrder; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - import org.apache.mina.core.buffer.IoBuffer; import org.apache.mina.core.session.IoSession; -import org.xml.sax.SAXException; import protocol.swg.CommPlayerMessage; import protocol.swg.ObjControllerMessage; import protocol.swg.PlayMusicMessage; import protocol.swg.objectControllerObjects.ForceActivateQuest; +import protocol.swg.objectControllerObjects.ShowLootBox; import resources.common.ObjControllerOpcodes; import resources.common.OutOfBand; import resources.common.ProsePackage; @@ -53,24 +41,21 @@ import resources.datatables.DisplayType; import resources.objects.SWGList; import resources.objects.creature.CreatureObject; import resources.objects.player.PlayerObject; -import resources.objects.waypoint.WaypointObject; +import resources.objects.tangible.TangibleObject; import resources.quest.Quest; import main.NGECore; import engine.clientdata.ClientFileManager; import engine.clientdata.visitors.DatatableVisitor; -import engine.clients.Client; import engine.resources.common.CRC; -import engine.resources.common.StringUtilities; import engine.resources.objects.SWGObject; -import engine.resources.scene.Point3D; import engine.resources.service.INetworkDispatch; import engine.resources.service.INetworkRemoteEvent; -@SuppressWarnings("unused") public class QuestService implements INetworkDispatch { private NGECore core; private Map questMap = new ConcurrentHashMap(); + private Map questRewardMap = new ConcurrentHashMap(); public QuestService(NGECore core) { this.core = core; @@ -133,6 +118,265 @@ public class QuestService implements INetworkDispatch { return false; } + public void sendQuestWindow(CreatureObject reciever, String questName) { + if (reciever == null || reciever.getClient() == null || reciever.getClient().getSession() == null) + return; + + ObjControllerMessage objMsg = new ObjControllerMessage(11, new ForceActivateQuest(reciever.getObjectID(), CRC.StringtoCRC("quest/" + questName))); + reciever.getClient().getSession().write(objMsg.serialize()); + } + + public void activateNextTask(CreatureObject quester, String questName) { + + for (Quest quest : quester.getPlayerObject().getQuestJournal()) { + if (quest.getName().equals(questName) && !quest.isCompleted()) + activateNextTask(quester, quest); + } + } + + public void activateNextTask(CreatureObject quester, Quest quest) { + QuestData qData = getQuestData(quest.getName()); + + if (qData == null) + return; + + PlayerObject player = quester.getPlayerObject(); + + if (player == null) + return; + + if (quest.getWaypointId() != 0) + core.objectService.destroyObject(quest.getWaypointId()); + + int activeStep = quest.getActiveStep(); + + QuestTask task = qData.getTasks().get(activeStep); + + String[] splitType = task.getType().split("\\."); + String type = splitType[splitType.length - 1]; + + switch (type) { + + // quest.task.ground.comm_player + case "comm_player": + + CommPlayerMessage message = new CommPlayerMessage(quester.getObjectID(), OutOfBand.ProsePackage(task.getCommMessageText()), task.getNpcAppearanceTemplate()); + quester.getClient().getSession().write(message.serialize()); + + break; + + // quest.task.ground.retrieve_item + case "retrieve_item": + String template = task.getServerTemplate(); + player.getQuestRetrieveItemTemplates().put(template, new QuestItem(quest.getName(), activeStep)); + break; + + case "timer": + break; + + default: + System.out.println("Don't know what to do for quest task: " + type); + break; + + } + + //if (task.getGrantQuestOnComplete() != null && !task.getGrantQuestOnComplete().equals("")) + //activateQuest(quester, task.getGrantQuestOnComplete()); + + if (activeStep + 1 >= qData.getTasks().size()) { + QuestList listItem = questRewardMap.get(quest.getName()); + + if (listItem.isCompleteWhenTasksComplete()) + completeQuest(player, quest); // Should this be the Force Complete Quest packet sent instead? + + /*else + sendQuestCompleteWindow(quester, quest.getName());*/ + return; + } + + quest.incrementQuestStep(); // After handling the quest type, we can now increment the step + + if (!task.isVisible()) { + player.getContainer().getClient().getSession().write(player.getBaseline(8).createDelta(7)); + activateNextTask(quester, quest); + return; + } + + } + + public void activateQuest(CreatureObject quester, String questString) { + System.out.println("Activating quest: " + questString); + Quest quest = new Quest(questString, quester.getObjectID()); + + PlayerObject player = quester.getPlayerObject(); + + if (player == null) + return; + + QuestList info = questRewardMap.get(questString); + if (info == null) { + info = getQuestListDatatable(questString); + } + + ProsePackage prose = new ProsePackage("@quest/ground/system_message:quest_received"); + prose.setToCustomString(info.getJournalEntryTitle()); + quester.sendSystemMessage(new OutOfBand(prose), DisplayType.Quest); + + PlayMusicMessage music = new PlayMusicMessage("sound/ui_npe2_quest_received.snd", quester.getObjectID(), 0, true); + quester.getClient().getSession().write(music.serialize()); + + player.getQuestJournal().add(quest); + player.setActiveQuest(quest.getCrc()); + + activateNextTask(quester, quest); + } + + public void completeQuest(PlayerObject player, Quest quest) { + if (player == null || quest == null) + return; + + CreatureObject creo = (CreatureObject) player.getContainer(); + + if (!quest.isCompleted()) { + quest.setCompleted(true); + } + + QuestList info = getQuestList(quest.getName()); + + ArrayList recievedItems = new ArrayList(); + TangibleObject inventory = (TangibleObject) creo.getSlottedObject("inventory"); + + if (inventory == null) + return; + + // TODO: Give other awards - exclusive loots, faction points + // Recieving quest awards (faction, item, exp, credits) - http://youtu.be/-L7Rz1WpmGM?t=14m50s + + // Give quest items + + if (info.getRewardLootName() != null && !info.getRewardLootName().equals("")) { + SWGObject rewardLoot = core.objectService.createObject(core.scriptService.getMethod("scripts/quest_rewards/", info.getRewardLootName(), "run").__call__().asString(), creo.getPlanet()); + inventory.add(rewardLoot); + recievedItems.add(rewardLoot.getObjectID()); + } + + if (recievedItems.size() != 0) { + + for (long item : recievedItems) { + creo.sendSystemMessage(OutOfBand.ProsePackage("@quest/ground/system_message:placed_in_inventory", "TO", item), DisplayType.Broadcast); + } + + ObjControllerMessage objMessage = new ObjControllerMessage(11, new ShowLootBox(creo.getObjectID(), recievedItems)); + creo.getClient().getSession().write(objMessage.serialize()); + } + + // Give credits + if (info.getRewardBankCredits() != 0) { + creo.addBankCredits(info.getRewardBankCredits()); + creo.sendSystemMessage(OutOfBand.ProsePackage("@base_player:prose_transfer_success", "DI", info.getRewardBankCredits()), DisplayType.Broadcast); + } + + // Give experience - TODO: Give specific type of experience. + if (info.getRewardExperienceAmount() == 0 && info.getTier() != -1 && !(info.getTier() > 6)) { + int experienceAward = 0; + try { + DatatableVisitor experienceVisitor = ClientFileManager.loadFile("clientdata/datatables/quest/quest_experience", DatatableVisitor.class); + + for (int r = 0; r < experienceVisitor.getRowCount(); r++) { + if ((int) experienceVisitor.getObject(r, 0) == creo.getLevel()) { + + if (info.getTier() > 6 || info.getTier() == -1) + return; + + experienceAward = (int) experienceVisitor.getObject(r, info.getTier()); + } + } + } catch (InstantiationException | IllegalAccessException e) { e.printStackTrace(); } + if (experienceAward != 0) + core.playerService.giveExperience(creo, experienceAward); + } else { + core.playerService.giveExperience(creo, info.getRewardExperienceAmount()); + } + + // Update quest & client + quest.setRecievedAward(true); + creo.getClient().getSession().write(player.getBaseline(8).createDelta(7)); + } + + public void sendQuestAcceptWindow(CreatureObject reciever, String questName) { + + } + + public void sendQuestCompleteWindow(CreatureObject reciever, String questName) { + + } + + public String getQuestItemRadialName(CreatureObject quester, String template) { + String radialName = ""; + + PlayerObject player = quester.getPlayerObject(); + if (player == null) + return radialName; + + if (player.getQuestRetrieveItemTemplates().size() == 0) + return radialName; + + if (!player.hasRetrieveItemTemplate(template)) + return radialName; + + QuestItem item = player.getQuestRetrieveItemTemplates().get(template); + QuestData data = getQuestData(item.getQuestName()); + + return data.getTasks().get(item.getTask()).getRetrieveMenuText(); + } + + public void handleQuestItemRadialSelection(CreatureObject quester, SWGObject target) { + if (quester == null || target == null) + return; + + PlayerObject player = quester.getPlayerObject(); + if (player == null) + return; + + if (!player.hasRetrieveItemTemplate(target.getTemplate())) { + System.out.println("Player doesn't have the template: " + target.getTemplate()); + return; + } + + QuestItem item = player.getQuestRetrieveItemTemplates().get(target.getTemplate()); + activateNextTask(quester, item.getQuestName()); + + player.getQuestRetrieveItemTemplates().remove(target.getTemplate(), item); + + if (player.hasRetrieveItemTemplate(target.getTemplate())) + System.out.println("STILL HAS TEMPLATE!!"); + } + + public QuestData getQuestData(String questName) { + if (questMap.containsKey(questName)) + return questMap.get(questName); + else { + QuestData data = getQuestDatatable(questName); // parsing puts it in quest map + questMap.put(questName, data); + if (!questRewardMap.containsKey(questName)) { + QuestList listing = getQuestList(questName); + questRewardMap.put(questName, listing); + } + return data; + } + } + + public QuestList getQuestList(String questName) { + if (questRewardMap.containsKey(questName)) + return questRewardMap.get(questName); + else { + System.out.println("Doesn't have it. Getting it from the list..."); + QuestList list = getQuestListDatatable(questName); // parsing puts it in quest map + questRewardMap.put(questName, list); + return list; + } + } + public boolean adminActivateQuest(CreatureObject creo, String questName) { PlayerObject ghost = creo.getPlayerObject(); @@ -140,96 +384,37 @@ public class QuestService implements INetworkDispatch { if (ghost == null) return false; - Quest quest = new Quest(questName, creo.getObjectID()); + if (questName.endsWith(".qst")) { + File questXml = new File("clientdata/quest/" + questName); + if (!questXml.exists()) + return false; + questName = questName.split(".qst")[0]; + } else { + File questXml = new File("clientdata/quest/" + questName + ".qst"); + if (!questXml.exists()) + return false; + } - File questXml = new File("clientdata/" + quest.getFilePath()); - if (!questXml.exists()) return false; + if (questName.contains("/")) { + String[] split = questName.split("/"); + questName = split[split.length - 1]; + } - QuestData questData = getQuestData(quest); + QuestData questData = getQuestData(questName); if (questData == null) return false; - //ProsePackage prose = new ProsePackage("@quest/ground/system_message:quest_received"); - //prose.setToCustomString(questData.getTasks().get(0).getJournalEntryTitle()); - - //creo.sendSystemMessage(new OutOfBand(prose), DisplayType.Quest); - - PlayMusicMessage music = new PlayMusicMessage("sound/ui_npe2_quest_received.snd", creo.getObjectID(), 0, true); - creo.getClient().getSession().write(music.serialize()); - - QuestTask activeTask = questData.getTasks().get(0); - - - /*if (activeTask.createsWaypoint()) { - WaypointObject waypoint = (WaypointObject) core.objectService.createObject("object/waypoint/shared_waypoint.iff", core.terrainService.getPlanetByName(activeTask.getPlanet())); - Point3D position = new Point3D(activeTask.getLocationX(), activeTask.getLocationY(), activeTask.getLocationZ()); - waypoint.setPosition(position); - waypoint.setName(activeTask.getWaypointName()); - waypoint.setColor(WaypointObject.BLUE); - waypoint.setActive(true); - waypoint.setStringAttribute("", ""); - - ghost.getWaypoints().put(waypoint.getObjectID(), waypoint); - }*/ - - ghost.getQuestJournal().add(quest); - ghost.setActiveQuest(quest.getCrc()); - - beginNextQuestStep(creo, quest); + activateQuest(creo, questName); return true; } - public void sendQuestWindow(CreatureObject reciever, Quest quest) { - - ObjControllerMessage objMsg = new ObjControllerMessage(11, new ForceActivateQuest(reciever.getObjectID(), CRC.StringtoCRC(quest.getCrcName()))); - reciever.getClient().getSession().write(objMsg.serialize()); - } - - public void beginNextQuestStep(CreatureObject quester, Quest quest) { - QuestData qData = getQuestData(quest); + private QuestData getQuestDatatable(String quest) { - if (qData == null) - return; + QuestData data = new QuestData(quest); - // TODO: Get QuestTask for the active step - QuestTask task = qData.getTasks().get(0); - - String[] splitType = task.getType().split("\\."); - String type = splitType[splitType.length - 1]; - - switch (type) { - - case "comm_player": - CommPlayerMessage message = new CommPlayerMessage(quester.getObjectID(), OutOfBand.ProsePackage(task.getCommMessageText()), task.getCommAppearanceTemplate()); - quester.getClient().getSession().write(message.serialize()); - break; - - default: - System.out.println("Don't know what to do for quest step: " + type); - break; - - } - - } - - public QuestData getQuestData(Quest quest) { - - if (questMap.containsKey(quest.getName())) - return questMap.get(quest.getName()); - else { - QuestData data = getQuestDatatable(quest); // parsing puts it in quest map - return data; - } - } - - private QuestData getQuestDatatable(Quest quest) { - - QuestData data = new QuestData(quest.getFilePath()); - - // visitor.getObjectByColumnNameAndIndex("JOURNAL_ENTRY_TITLE", r) try { - DatatableVisitor visitor = ClientFileManager.loadFile("datatables/questtask/quest/" + quest.getName() + ".iff", DatatableVisitor.class); + DatatableVisitor visitor = ClientFileManager.loadFile("datatables/questtask/quest/" + quest + ".iff", DatatableVisitor.class); for (int r = 0; r < visitor.getRowCount(); r++) { @@ -267,12 +452,14 @@ public class QuestService implements INetworkDispatch { if (visitor.getObjectByColumnNameAndIndex("INTERIOR_WAYPOINT_APPERANCE", r) != null) task.setInteriorWaypointAppearance((String) visitor.getObjectByColumnNameAndIndex("INTERIOR_WAYPOINT_APPERANCE", r)); if (visitor.getObjectByColumnNameAndIndex("SIGNALS_ON_FAIL", r) != null) task.setSignalsOnFail((String) visitor.getObjectByColumnNameAndIndex("SIGNALS_ON_FAIL", r)); if (visitor.getObjectByColumnNameAndIndex("COMM_MESSAGE_TEXT", r) != null) task.setCommMessageText((String) visitor.getObjectByColumnNameAndIndex("COMM_MESSAGE_TEXT", r)); - if (visitor.getObjectByColumnNameAndIndex("NPC_APPEARANCE_SERVER_TEMPLATE", r) != null) task.setCommAppearanceTemplate(convertToSharedFile((String) visitor.getObjectByColumnNameAndIndex("NPC_APPEARANCE_SERVER_TEMPLATE", r))); + if (visitor.getObjectByColumnNameAndIndex("NPC_APPEARANCE_SERVER_TEMPLATE", r) != null) task.setNpcAppearanceTemplate(convertToSharedFile((String) visitor.getObjectByColumnNameAndIndex("NPC_APPEARANCE_SERVER_TEMPLATE", r))); if (visitor.getObjectByColumnNameAndIndex("SERVER_TEMPLATE", r) != null) task.setServerTemplate(convertToSharedFile((String) visitor.getObjectByColumnNameAndIndex("SERVER_TEMPLATE", r))); if (visitor.getObjectByColumnNameAndIndex("NUM_REQUIRED", r) != null) task.setNumRequired((int) visitor.getObjectByColumnNameAndIndex("NUM_REQUIRED", r)); if (visitor.getObjectByColumnNameAndIndex("ITEM_NAME", r) != null) task.setItemName((String) visitor.getObjectByColumnNameAndIndex("ITEM_NAME", r)); if (visitor.getObjectByColumnNameAndIndex("DROP_PERCENT", r) != null) task.setDropPercent((int) visitor.getObjectByColumnNameAndIndex("DROP_PERCENT", r)); - + if (visitor.getObjectByColumnNameAndIndex("RETRIEVE_MENU_TEXT", r) != null) task.setRetrieveMenuText((String) visitor.getObjectByColumnNameAndIndex("RETRIEVE_MENU_TEXT", r)); + //if (visitor.getObjectByColumnNameAndIndex("", r)) + data.getTasks().add(task); } @@ -280,12 +467,46 @@ public class QuestService implements INetworkDispatch { e.printStackTrace(); } - questMap.put(quest.getName(), data); return data; } + private QuestList getQuestListDatatable(String quest) { + QuestList qList = new QuestList(); + + try { + DatatableVisitor visitor = ClientFileManager.loadFile("datatables/questlist/quest/" + quest + ".iff", DatatableVisitor.class); + // Should only have 1 row with info + + // not the full list. + if (visitor.getObjectByColumnNameAndIndex("LEVEL", 0) != null) qList.setLevel((int) visitor.getObjectByColumnNameAndIndex("LEVEL", 0)); + if (visitor.getObjectByColumnNameAndIndex("TIER", 0) != null) qList.setTier((int) visitor.getObjectByColumnNameAndIndex("TIER", 0)); + if (visitor.getObjectByColumnNameAndIndex("TYPE", 0) != null) qList.setType((String) visitor.getObjectByColumnNameAndIndex("TYPE", 0)); + if (visitor.getObjectByColumnNameAndIndex("JOURNAL_ENTRY_TITLE", 0) != null) qList.setJournalEntryTitle((String) visitor.getObjectByColumnNameAndIndex("JOURNAL_ENTRY_TITLE", 0)); + if (visitor.getObjectByColumnNameAndIndex("JOURNAL_ENTRY_DESCRIPTION", 0) != null) qList.setJournalEntryDescription((String) visitor.getObjectByColumnNameAndIndex("JOURNAL_ENTRY_DESCRIPTION", 0)); + if (visitor.getObjectByColumnNameAndIndex("CATEGORY", 0) != null) qList.setCategory((String) visitor.getObjectByColumnNameAndIndex("CATEGORY", 0)); + if (visitor.getObjectByColumnNameAndIndex("visible", 0) != null) qList.setVisible((String) visitor.getObjectByColumnNameAndIndex("visible", 0)); + if (visitor.getObjectByColumnNameAndIndex("JOURNAL_ENTRY_COMPLETION_SUMMARY", 0) != null) qList.setJournalEntryCompletionSummary((String) visitor.getObjectByColumnNameAndIndex("JOURNAL_ENTRY_COMPLETION_SUMMARY", 0)); + if (visitor.getObjectByColumnNameAndIndex("PREREQUISITE_QUESTS", 0) != null) qList.setPrerequisteQuests((String) visitor.getObjectByColumnNameAndIndex("PREREQUISITE_QUESTS", 0)); + if (visitor.getObjectByColumnNameAndIndex("EXCLUSION_QUESTS", 0) != null) qList.setExclusionQuests((String) visitor.getObjectByColumnNameAndIndex("EXCLUSION_QUESTS", 0)); + if (visitor.getObjectByColumnNameAndIndex("ALLOW_REPEATS", 0) != null) qList.setAllowRepeats((boolean) visitor.getObjectByColumnNameAndIndex("ALLOW_REPEATS", 0)); + if (visitor.getObjectByColumnNameAndIndex("QUEST_REWARD_EXPERIENCE_TYPE", 0) != null) qList.setRewardExperienceType((String) visitor.getObjectByColumnNameAndIndex("QUEST_REWARD_EXPERIENCE_TYPE", 0)); + if (visitor.getObjectByColumnNameAndIndex("QUEST_REWARD_EXPERIENCE_AMOUNT", 0) != null) qList.setRewardExperienceAmount((int) visitor.getObjectByColumnNameAndIndex("QUEST_REWARD_EXPERIENCE_AMOUNT", 0)); + if (visitor.getObjectByColumnNameAndIndex("QUEST_REWARD_FACTION_NAME", 0) != null) qList.setRewardFactionType((String) visitor.getObjectByColumnNameAndIndex("QUEST_REWARD_FACTION_NAME", 0)); + if (visitor.getObjectByColumnNameAndIndex("QUEST_REWARD_FACTION_AMOUNT", 0) != null) qList.setRewardFactionAmount((int) visitor.getObjectByColumnNameAndIndex("QUEST_REWARD_FACTION_AMOUNT", 0)); + if (visitor.getObjectByColumnNameAndIndex("QUEST_REWARD_BANK_CREDITS", 0) != null) qList.setRewardBankCredits((int) visitor.getObjectByColumnNameAndIndex("QUEST_REWARD_BANK_CREDITS", 0)); + if (visitor.getObjectByColumnNameAndIndex("QUEST_REWARD_LOOT_NAME", 0) != null) qList.setRewardLootName((String) visitor.getObjectByColumnNameAndIndex("QUEST_REWARD_LOOT_NAME", 0)); + if (visitor.getObjectByColumnNameAndIndex("QUEST_REWARD_LOOT_COUNT", 0) != null) qList.setRewardLootCount((int) visitor.getObjectByColumnNameAndIndex("QUEST_REWARD_LOOT_COUNT", 0)); + if (visitor.getObjectByColumnNameAndIndex("COMPLETE_WHEN_TASKS_COMPLETE", 0) != null) qList.setCompleteWhenTasksComplete((boolean) visitor.getObjectByColumnNameAndIndex("COMPLETE_WHEN_TASKS_COMPLETE", 0)); + + } catch (InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + } + + return qList; + } + // useful for custom quest scripts, and for the some of the datatables that are all screwed up - private QuestData parseXmlQuestData(Quest quest) { + /*private QuestData parseXmlQuestData(Quest quest) { try { if (questMap.containsKey(quest.getName())) return null; @@ -311,7 +532,7 @@ public class QuestService implements INetworkDispatch { } catch(SAXException | ParserConfigurationException | IOException e) { } return null; - } + }*/ private String convertToSharedFile(String template) { String[] split = template.split("/"); diff --git a/src/services/quest/QuestTask.java b/src/services/quest/QuestTask.java index 1f77bb4f..1934259c 100644 --- a/src/services/quest/QuestTask.java +++ b/src/services/quest/QuestTask.java @@ -46,11 +46,12 @@ public class QuestTask { private String waitMarkerPlanetName; private String waitMarkerCellName; private String commMessageText; - private String commAppearanceTemplate; // NPC Appearance Server Template + private String npcAppearanceTemplate; // NPC Appearance Server Template private String tasksOnComplete; private String serverTemplate; private String itemName; private String tasksOnFail; + private String retrieveMenuText; private boolean visible; private boolean grantQuestOnCompleteShowSystemMessage; @@ -261,12 +262,12 @@ public class QuestTask { this.commMessageText = commMessageText; } - public String getCommAppearanceTemplate() { - return commAppearanceTemplate; + public String getNpcAppearanceTemplate() { + return npcAppearanceTemplate; } - public void setCommAppearanceTemplate(String commAppearanceTemplate) { - this.commAppearanceTemplate = commAppearanceTemplate; + public void setNpcAppearanceTemplate(String npcAppearanceTemplate) { + this.npcAppearanceTemplate = npcAppearanceTemplate; } public boolean isVisible() { @@ -442,4 +443,12 @@ public class QuestTask { public void setDropPercent(int dropPercent) { this.dropPercent = dropPercent; } + + public String getRetrieveMenuText() { + return retrieveMenuText; + } + + public void setRetrieveMenuText(String retrieveMenuText) { + this.retrieveMenuText = retrieveMenuText; + } } diff --git a/src/services/quest/SWGQuestDataHandler.java b/src/services/quest/SWGQuestDataHandler.java index c2ea3d3f..342e0a8f 100644 --- a/src/services/quest/SWGQuestDataHandler.java +++ b/src/services/quest/SWGQuestDataHandler.java @@ -171,7 +171,7 @@ public class SWGQuestDataHandler extends DefaultHandler { break; case "NPC Appearance Server Template": - task.setCommAppearanceTemplate(attributes.getValue("value")); + task.setNpcAppearanceTemplate(attributes.getValue("value")); break; default: