From fe62c05b4b4bb3cdd6d018309d91aca75dfd82ee Mon Sep 17 00:00:00 2001 From: Zukero Date: Wed, 26 Jul 2017 15:50:50 +0200 Subject: [PATCH] Fixed many bugs in the TMX Maps management. Added the removeQuestProgress dialogue reward type. Initiallized the GDEVisitor class to help with finding dependencies (through the Beanshell console only for now). --- hacked-libtiled/tiled/core/Map.java | 5 +- hacked-libtiled/tiled/io/TMXMapWriter.java | 7 +- .../model/gamedata/Dialogue.java | 2 + .../model/maps/ReplaceArea.java | 7 +- .../atcontentstudio/model/maps/TMXMap.java | 3 +- .../ui/gamedataeditors/DialogueEditor.java | 5 + .../atcontentstudio/ui/map/TMXMapEditor.java | 52 +++- .../atcontentstudio/ui/tools/GDEVisitor.java | 223 ++++++++++++++++++ 8 files changed, 296 insertions(+), 8 deletions(-) create mode 100644 src/com/gpl/rpg/atcontentstudio/ui/tools/GDEVisitor.java diff --git a/hacked-libtiled/tiled/core/Map.java b/hacked-libtiled/tiled/core/Map.java index 4738097..1a29def 100644 --- a/hacked-libtiled/tiled/core/Map.java +++ b/hacked-libtiled/tiled/core/Map.java @@ -111,11 +111,14 @@ public class Map implements Iterable public MapLayer addLayer(MapLayer layer) { layer.setMap(this); - layers.add(layer); if (layer instanceof TileLayer) { tileLayers.add((TileLayer) layer); + layers.add(layer); } else if (layer instanceof ObjectGroup) { + layers.insertElementAt(layer, objectGroups.size()); objectGroups.add((ObjectGroup) layer); + } else { + layers.add(layer); } return layer; } diff --git a/hacked-libtiled/tiled/io/TMXMapWriter.java b/hacked-libtiled/tiled/io/TMXMapWriter.java index 0d78cfa..d7b5335 100644 --- a/hacked-libtiled/tiled/io/TMXMapWriter.java +++ b/hacked-libtiled/tiled/io/TMXMapWriter.java @@ -181,7 +181,12 @@ public class TMXMapWriter firstgid += tileset.getMaxTileId() + 1; } - for (MapLayer layer : map) { + for (MapLayer layer : map.getTileLayers()) { + writeMapLayer(layer, w, wp); + } + + for (MapLayer layer : map.getObjectGroup()) { + if (map.getTileLayers().contains(layer)) continue; writeMapLayer(layer, w, wp); } firstGidPerTileset = null; diff --git a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Dialogue.java b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Dialogue.java index 7cb382f..d28c4e2 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/gamedata/Dialogue.java +++ b/src/com/gpl/rpg/atcontentstudio/model/gamedata/Dialogue.java @@ -54,6 +54,7 @@ public class Dialogue extends JSONElement { public enum RewardType { questProgress, + removeQuestProgress, dropList, skillIncrease, actorCondition, @@ -264,6 +265,7 @@ public class Dialogue extends JSONElement { reward.reward_obj = proj.getItem(reward.reward_obj_id); break; case questProgress: + case removeQuestProgress: reward.reward_obj = proj.getQuest(reward.reward_obj_id); if (reward.reward_obj != null && reward.reward_value != null) { QuestStage stage = ((Quest)reward.reward_obj).getStage(reward.reward_value); diff --git a/src/com/gpl/rpg/atcontentstudio/model/maps/ReplaceArea.java b/src/com/gpl/rpg/atcontentstudio/model/maps/ReplaceArea.java index 7da01b3..3dd2423 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/maps/ReplaceArea.java +++ b/src/com/gpl/rpg/atcontentstudio/model/maps/ReplaceArea.java @@ -12,7 +12,7 @@ import com.gpl.rpg.atcontentstudio.ui.DefaultIcons; public class ReplaceArea extends MapObject { public Requirement requirement = null; - public boolean oldSchoolRequirement = true; + public boolean oldSchoolRequirement = false; public List replacements = null; @@ -26,14 +26,12 @@ public class ReplaceArea extends MapObject { // requireType = Requirement.RequirementType.questProgress.toString(); requireValue = fields[1]; requireId = fields[0]; + oldSchoolRequirement = true; } /*else if (fields.length == 3) { requireValue = fields[2]; requireType = fields[0]; requireId = fields[1]; }*/ - oldSchoolRequirement = true; - } else { - oldSchoolRequirement = false; } requirement = new Requirement(); //Replace areas only support questProgress requirements ATM @@ -45,6 +43,7 @@ public class ReplaceArea extends MapObject { for (Object s : obj.getProperties().keySet()) { + if (!TMXMap.isPaintedLayerName(s.toString())) continue; if (replacements == null) replacements = new ArrayList(); replacements.add(new Replacement(s.toString(), obj.getProperties().getProperty(s.toString()))); } diff --git a/src/com/gpl/rpg/atcontentstudio/model/maps/TMXMap.java b/src/com/gpl/rpg/atcontentstudio/model/maps/TMXMap.java index 7efa41f..2a6ec8a 100644 --- a/src/com/gpl/rpg/atcontentstudio/model/maps/TMXMap.java +++ b/src/com/gpl/rpg/atcontentstudio/model/maps/TMXMap.java @@ -273,11 +273,12 @@ public class TMXMap extends GameDataElement { public void save() { if (writable) { + String xml = toXml(); try { //TODO: check in fileutils, to test the workspace's filesystem once at startup, and figure out how many of these can occur, instead of hard-coded '2' dismissNextChangeNotif += 2; FileWriter w = new FileWriter(tmxFile); - w.write(toXml()); + w.write(xml); w.close(); this.state = State.saved; changedOnDisk = false; diff --git a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DialogueEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DialogueEditor.java index c86e3cd..d8c5922 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DialogueEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/gamedataeditors/DialogueEditor.java @@ -417,6 +417,7 @@ public class DialogueEditor extends JSONElementEditor { rewardObj = addItemBox(pane, ((Dialogue)target).getProject(), "Item: ", (Item) reward.reward_obj, writable, listener); rewardValue = addIntegerField(pane, "Quantity: ", reward.reward_value, false, writable, listener); break; + case removeQuestProgress: case questProgress: rewardMap = null; rewardObjId = null; @@ -826,6 +827,10 @@ public class DialogueEditor extends JSONElementEditor { label.setText("Give quest progress "+rewardObjDesc+":"+reward.reward_value); if (reward.reward_obj != null) label.setIcon(new ImageIcon(reward.reward_obj.getIcon())); break; + case removeQuestProgress: + label.setText("Removes quest progress "+rewardObjDesc+":"+reward.reward_value); + if (reward.reward_obj != null) label.setIcon(new ImageIcon(reward.reward_obj.getIcon())); + break; case removeSpawnArea: label.setText("Remove all monsters in spawnarea area "+rewardObjDesc+" on map "+reward.map_name); label.setIcon(new ImageIcon(DefaultIcons.getNPCIcon())); diff --git a/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java b/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java index b6342e6..55700df 100644 --- a/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java +++ b/src/com/gpl/rpg/atcontentstudio/ui/map/TMXMapEditor.java @@ -260,7 +260,12 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe addTileLayer.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - layerListModel.addObject(new tiled.core.TileLayer()); + tiled.core.TileLayer layer = new tiled.core.TileLayer(map.tmxMap.getWidth(), map.tmxMap.getHeight()); + layerListModel.addObject(layer); + map.state = GameDataElement.State.modified; + map.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(TMXMapEditor.this); + targetUpdated(); } }); addObjectGroup = new JButton(new ImageIcon(DefaultIcons.getCreateObjectGroupIcon())); @@ -270,6 +275,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe @Override public void actionPerformed(ActionEvent e) { layerListModel.addObject(new tiled.core.ObjectGroup()); + map.state = GameDataElement.State.modified; + map.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(TMXMapEditor.this); + targetUpdated(); } }); deleteLayer = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon())); @@ -279,6 +288,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe @Override public void actionPerformed(ActionEvent e) { layerListModel.removeObject(selectedLayer); + map.state = GameDataElement.State.modified; + map.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(TMXMapEditor.this); + targetUpdated(); } }); JPanel layersButtonsPane = new JPanel(); @@ -363,6 +376,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe @Override public void actionPerformed(ActionEvent e) { groupObjectsListModel.addObject(MapObject.newMapchange(new tiled.core.MapObject(0, 0, 32, 32), map)); + map.state = GameDataElement.State.modified; + map.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(TMXMapEditor.this); + targetUpdated(); } }); addSpawn = new JButton(new ImageIcon(DefaultIcons.getCreateSpawnareaIcon())); @@ -372,6 +389,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe @Override public void actionPerformed(ActionEvent e) { groupObjectsListModel.addObject(MapObject.newSpawnArea(new tiled.core.MapObject(0, 0, 32, 32), map)); + map.state = GameDataElement.State.modified; + map.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(TMXMapEditor.this); + targetUpdated(); } }); addRest = new JButton(new ImageIcon(DefaultIcons.getCreateRestIcon())); @@ -381,6 +402,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe @Override public void actionPerformed(ActionEvent e) { groupObjectsListModel.addObject(MapObject.newRest(new tiled.core.MapObject(0, 0, 32, 32), map)); + map.state = GameDataElement.State.modified; + map.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(TMXMapEditor.this); + targetUpdated(); } }); addKey = new JButton(new ImageIcon(DefaultIcons.getCreateKeyIcon())); @@ -390,6 +415,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe @Override public void actionPerformed(ActionEvent e) { groupObjectsListModel.addObject(MapObject.newKey(new tiled.core.MapObject(0, 0, 32, 32), map)); + map.state = GameDataElement.State.modified; + map.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(TMXMapEditor.this); + targetUpdated(); } }); addReplace = new JButton(new ImageIcon(DefaultIcons.getCreateReplaceIcon())); @@ -399,6 +428,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe @Override public void actionPerformed(ActionEvent e) { groupObjectsListModel.addObject(MapObject.newReplace(new tiled.core.MapObject(0, 0, 32, 32), map)); + map.state = GameDataElement.State.modified; + map.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(TMXMapEditor.this); + targetUpdated(); } }); addScript = new JButton(new ImageIcon(DefaultIcons.getCreateScriptIcon())); @@ -408,6 +441,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe @Override public void actionPerformed(ActionEvent e) { groupObjectsListModel.addObject(MapObject.newScript(new tiled.core.MapObject(0, 0, 32, 32), map)); + map.state = GameDataElement.State.modified; + map.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(TMXMapEditor.this); + targetUpdated(); } }); addContainer = new JButton(new ImageIcon(DefaultIcons.getCreateContainerIcon())); @@ -417,6 +454,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe @Override public void actionPerformed(ActionEvent e) { groupObjectsListModel.addObject(MapObject.newContainer(new tiled.core.MapObject(0, 0, 32, 32), map)); + map.state = GameDataElement.State.modified; + map.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(TMXMapEditor.this); + targetUpdated(); } }); addSign = new JButton(new ImageIcon(DefaultIcons.getCreateSignIcon())); @@ -426,6 +467,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe @Override public void actionPerformed(ActionEvent e) { groupObjectsListModel.addObject(MapObject.newSign(new tiled.core.MapObject(0, 0, 32, 32), map)); + map.state = GameDataElement.State.modified; + map.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(TMXMapEditor.this); + targetUpdated(); } }); deleteObject = new JButton(new ImageIcon(DefaultIcons.getNullifyIcon())); @@ -435,6 +480,10 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe @Override public void actionPerformed(ActionEvent e) { groupObjectsListModel.removeObject(selectedMapObject); + map.state = GameDataElement.State.modified; + map.childrenChanged(new ArrayList()); + ATContentStudio.frame.editorChanged(TMXMapEditor.this); + targetUpdated(); } }); @@ -514,6 +563,7 @@ public class TMXMapEditor extends Editor implements TMXMap.MapChangedOnDiskListe } else if (selected instanceof ReplaceArea) { //Replace areas only use questProgress requirements ATM //requirementTypeCombo = addEnumValueBox(pane, "Requirement type: ", Requirement.RequirementType.values(), ((ReplaceArea)selected).requirement.type, ((TMXMap)target).writable, listener); + areaField = addTextField(pane, "Area ID: ", ((ReplaceArea)selected).name, ((TMXMap)target).writable, listener); requirementParamsPane = new JPanel(); requirementParamsPane.setLayout(new JideBoxLayout(requirementParamsPane, JideBoxLayout.PAGE_AXIS, 6)); pane.add(requirementParamsPane, JideBoxLayout.FIX); diff --git a/src/com/gpl/rpg/atcontentstudio/ui/tools/GDEVisitor.java b/src/com/gpl/rpg/atcontentstudio/ui/tools/GDEVisitor.java new file mode 100644 index 0000000..4a9205e --- /dev/null +++ b/src/com/gpl/rpg/atcontentstudio/ui/tools/GDEVisitor.java @@ -0,0 +1,223 @@ +package com.gpl.rpg.atcontentstudio.ui.tools; + +import java.util.ArrayList; +import java.util.List; + +import com.gpl.rpg.atcontentstudio.model.GameDataElement; +import com.gpl.rpg.atcontentstudio.model.GameSource; +import com.gpl.rpg.atcontentstudio.model.gamedata.ActorCondition; +import com.gpl.rpg.atcontentstudio.model.gamedata.Dialogue; +import com.gpl.rpg.atcontentstudio.model.gamedata.Droplist; +import com.gpl.rpg.atcontentstudio.model.gamedata.Item; +import com.gpl.rpg.atcontentstudio.model.gamedata.ItemCategory; +import com.gpl.rpg.atcontentstudio.model.gamedata.NPC; +import com.gpl.rpg.atcontentstudio.model.gamedata.Quest; +import com.gpl.rpg.atcontentstudio.model.gamedata.Requirement; +import com.gpl.rpg.atcontentstudio.model.maps.ContainerArea; +import com.gpl.rpg.atcontentstudio.model.maps.KeyArea; +import com.gpl.rpg.atcontentstudio.model.maps.MapChange; +import com.gpl.rpg.atcontentstudio.model.maps.MapObject; +import com.gpl.rpg.atcontentstudio.model.maps.MapObjectGroup; +import com.gpl.rpg.atcontentstudio.model.maps.ReplaceArea; +import com.gpl.rpg.atcontentstudio.model.maps.RestArea; +import com.gpl.rpg.atcontentstudio.model.maps.ScriptArea; +import com.gpl.rpg.atcontentstudio.model.maps.SignArea; +import com.gpl.rpg.atcontentstudio.model.maps.SpawnArea; +import com.gpl.rpg.atcontentstudio.model.maps.TMXMap; +import com.gpl.rpg.atcontentstudio.model.sprites.Spritesheet; + +public class GDEVisitor { + + public static List findDependencies(GameDataElement origin, boolean includeSource) { + List visited = new ArrayList(); + visit(origin, visited, includeSource); + return visited; + } + + private static void visit(GameDataElement element, List visited, boolean includeSource) { + if (element == null) return; + if (visited.contains(element)) return; + if (!(includeSource || element.getDataType() != GameSource.Type.source)) return; + + visited.add(element); + element.link(); + if (element instanceof ActorCondition) { + visitActorCondition((ActorCondition)element, visited, includeSource); + } else if (element instanceof Dialogue) { + visitDialogue((Dialogue)element, visited, includeSource); + } else if (element instanceof Droplist) { + visitDroplist((Droplist)element, visited, includeSource); + } else if (element instanceof Item) { + visitItem((Item)element, visited, includeSource); + } else if (element instanceof ItemCategory) { + visitItemCategory((ItemCategory)element, visited, includeSource); + } else if (element instanceof NPC) { + visitNPC((NPC)element, visited, includeSource); + } else if (element instanceof Quest) { + visitQuest((Quest)element, visited, includeSource); + } else if (element instanceof TMXMap) { + visitTMXMap((TMXMap)element, visited, includeSource); + } else if (element instanceof Spritesheet) { + visitSpritesheet((Spritesheet)element, visited, includeSource); + } + + } + + private static void visitActorCondition(ActorCondition element, List visited, boolean includeSource) { + if (element.icon_id != null) visit(element.getProject().getSpritesheet(element.icon_id.split(":")[0]), visited, includeSource); + + for (GameDataElement backlink : element.getBacklinks()) { + visit(backlink, visited, includeSource); + } + } + + private static void visitDialogue(Dialogue element, List visited, boolean includeSource) { + visit(element.switch_to_npc, visited, includeSource); + if (element.replies != null) { + for (Dialogue.Reply reply : element.replies) { + visit(reply.next_phrase, visited, includeSource); + if (reply.requirements != null) { + for (Requirement req : reply.requirements) { + visit(req.required_obj, visited, includeSource); + } + } + } + } + if (element.rewards != null) { + for (Dialogue.Reward reward : element.rewards) { + visit(reward.reward_obj, visited, includeSource); + visit(reward.map, visited, includeSource); + } + } + + for (GameDataElement backlink : element.getBacklinks()) { + visit(backlink, visited, includeSource); + } + } + + private static void visitDroplist(Droplist element, List visited, boolean includeSource) { + if (element.dropped_items != null) { + for (Droplist.DroppedItem droppedItem : element.dropped_items) { + visit(droppedItem.item, visited, includeSource); + } + } + + for (GameDataElement backlink : element.getBacklinks()) { + visit(backlink, visited, includeSource); + } + } + + private static void visitItem(Item element, List visited, boolean includeSource) { + visit(element.category, visited, includeSource); + if (element.icon_id != null) visit(element.getProject().getSpritesheet(element.icon_id.split(":")[0]), visited, includeSource); + if (element.equip_effect != null && element.equip_effect.conditions != null) { + for (Item.ConditionEffect condEffect : element.equip_effect.conditions) { + visit(condEffect.condition, visited, includeSource); + } + } + if (element.hit_effect != null) { + if (element.hit_effect.conditions_source != null) { + for (Item.ConditionEffect condEffect : element.hit_effect.conditions_source) { + visit(condEffect.condition, visited, includeSource); + } + } + if (element.hit_effect.conditions_target != null) { + for (Item.ConditionEffect condEffect : element.hit_effect.conditions_target) { + visit(condEffect.condition, visited, includeSource); + } + } + } + + + for (GameDataElement backlink : element.getBacklinks()) { + visit(backlink, visited, includeSource); + } + } + + private static void visitItemCategory(ItemCategory element, List visited, boolean includeSource) { + //Nothing to visit + } + + private static void visitNPC(NPC element, List visited, boolean includeSource) { + visit(element.dialogue, visited, includeSource); + visit(element.droplist, visited, includeSource); + if (element.icon_id != null) visit(element.getProject().getSpritesheet(element.icon_id.split(":")[0]), visited, includeSource); + if (element.hit_effect != null) { + if (element.hit_effect.conditions_source != null) { + for (NPC.TimedConditionEffect condEffect : element.hit_effect.conditions_source) { + visit(condEffect.condition, visited, includeSource); + } + } + if (element.hit_effect.conditions_target != null) { + for (NPC.TimedConditionEffect condEffect : element.hit_effect.conditions_target) { + visit(condEffect.condition, visited, includeSource); + } + } + } + + + for (GameDataElement backlink : element.getBacklinks()) { + visit(backlink, visited, includeSource); + } + } + + private static void visitQuest(Quest element, List visited, boolean includeSource) { + //Nothing to visit + + + for (GameDataElement backlink : element.getBacklinks()) { + visit(backlink, visited, includeSource); + } + } + + private static void visitTMXMap(TMXMap element, List visited, boolean includeSource) { + // TODO Auto-generated method stub + if (element.groups != null) { + for (MapObjectGroup group : element.groups) { + if (group.mapObjects != null) { + for (MapObject obj : group.mapObjects) { + if (obj instanceof ContainerArea) { + visit(((ContainerArea)obj).droplist, visited, includeSource); + } else if (obj instanceof KeyArea) { + visit(((KeyArea)obj).dialogue, visited, includeSource); + if (((KeyArea)obj).requirement != null) { + visit(((KeyArea)obj).requirement.required_obj, visited, includeSource); + } + } else if (obj instanceof MapChange) { + visit(((MapChange)obj).map, visited, includeSource); + } else if (obj instanceof ReplaceArea) { + if (((ReplaceArea)obj).requirement != null) { + visit(((ReplaceArea)obj).requirement.required_obj, visited, includeSource); + } + } else if (obj instanceof RestArea) { + //Nothing to visit + } else if (obj instanceof ScriptArea) { + visit(((ScriptArea)obj).dialogue, visited, includeSource); + } else if (obj instanceof SignArea) { + visit(((SignArea)obj).dialogue, visited, includeSource); + } else if (obj instanceof SpawnArea) { + if (((SpawnArea)obj).spawnGroup != null) { + for (NPC npc : ((SpawnArea)obj).spawnGroup) { + visit(npc, visited, includeSource); + } + } + } + } + } + } + } + + for (GameDataElement backlink : element.getBacklinks()) { + visit(backlink, visited, includeSource); + } + } + + private static void visitSpritesheet(Spritesheet element, List visited, boolean includeSource) { + //Nothing to visit + + //Not even the backlinks. Makes no sense. + } + + + +}