diff --git a/AndorsTrail/.classpath b/AndorsTrail/.classpath index 6aed2ebfb..7bc01d9a9 100644 --- a/AndorsTrail/.classpath +++ b/AndorsTrail/.classpath @@ -4,5 +4,6 @@ + diff --git a/AndorsTrail/res/raw/conversationlist_debug.json b/AndorsTrail/res/raw/conversationlist_debug.json index 8518660a4..a4c607dde 100644 --- a/AndorsTrail/res/raw/conversationlist_debug.json +++ b/AndorsTrail/res/raw/conversationlist_debug.json @@ -123,5 +123,63 @@ { "id": "debugrequireskey", "message": "This tile requires a quest progress." - } + }, + { + "id": "debugrequires10gold", + "replies": [ + { + "text": "Too bad.", + "nextPhraseID": "X" + }, + { + "text": "Well, gimme 10 gold then !", + "nextPhraseID": "debugrequires10gold_1" + } + ], + "message": "This tile costs 10 gold !" + }, + { + "id": "debugrequires10gold_1", + "replies": [ + { + "requires": [ + { + "requireType": "consumedMore", + "requireID": "gold", + "value": 100 + } + ], + "nextPhraseID": "debugrequires10gold_3" + }, + { + "nextPhraseID": "debugrequires10gold_2" + } + ] + }, + { + "id": "debugrequires10gold_2", + "rewards": [ + { + "rewardType": "dropList", + "rewardID": "debugrequires10gold_droplist" + } + ], + "replies": [ + { + "text": "When I come to debugmap, I always feel like a star.", + "nextPhraseID": "X" + } + ], + "message": "Okay. But only because it's you M. Coder." + }, + { + "id": "debugrequires10gold_3", + "replies": [ + { + "text": "Damn.", + "nextPhraseID": "X" + } + ], + "message": "Sorry. You already spent 100 gold..." + } ] diff --git a/AndorsTrail/res/raw/droplists_debug.json b/AndorsTrail/res/raw/droplists_debug.json index c9c15d5fc..7d70c8ea1 100644 --- a/AndorsTrail/res/raw/droplists_debug.json +++ b/AndorsTrail/res/raw/droplists_debug.json @@ -161,5 +161,18 @@ "chance": 100 } ] - } + }, + { + "id": "debugrequires10gold_droplist", + "items": [ + { + "quantity": { + "min": 10, + "max": 10 + }, + "itemID": "gold", + "chance": 100 + } + ] + } ] diff --git a/AndorsTrail/res/xml/debugmap.tmx b/AndorsTrail/res/xml/debugmap.tmx index a2669cfca..9e6ed6499 100644 --- a/AndorsTrail/res/xml/debugmap.tmx +++ b/AndorsTrail/res/xml/debugmap.tmx @@ -1,125 +1,124 @@ - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -144,14 +143,20 @@ - + + + + - + + + + @@ -167,6 +172,14 @@ + + + + + + + + diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java index 18b9ed79c..393321225 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java @@ -4,6 +4,7 @@ import android.content.res.Resources; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import com.gpl.rpg.AndorsTrail.context.ControllerContext; import com.gpl.rpg.AndorsTrail.context.WorldContext; +import com.gpl.rpg.AndorsTrail.model.GameStatistics; import com.gpl.rpg.AndorsTrail.model.ability.*; import com.gpl.rpg.AndorsTrail.model.actor.Actor; import com.gpl.rpg.AndorsTrail.model.actor.Monster; @@ -13,6 +14,7 @@ import com.gpl.rpg.AndorsTrail.model.item.ItemTypeCollection; import com.gpl.rpg.AndorsTrail.model.item.Loot; import com.gpl.rpg.AndorsTrail.model.quest.QuestLogEntry; import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress; +import com.gpl.rpg.AndorsTrail.model.script.Requirement; import com.gpl.rpg.AndorsTrail.util.ConstRange; import com.gpl.rpg.AndorsTrail.util.L; @@ -127,17 +129,11 @@ public final class ConversationController { result.actorConditions.add(e); } - private static void applyReplyEffect(final Player player, final Reply reply) { + private static void applyReplyEffect(final WorldContext world, final Reply reply) { if (!reply.hasRequirements()) return; for (Requirement requirement : reply.requires) { - if (requirement.requireType == Requirement.RequirementType.inventoryRemove) { - if (ItemTypeCollection.isGoldItemType(requirement.requireID)) { - player.inventory.gold -= requirement.value; - } else { - player.inventory.removeItem(requirement.requireID, requirement.value); - } - } + requirementFulfilled(world, requirement); } } @@ -145,18 +141,21 @@ public final class ConversationController { if (!reply.hasRequirements()) return true; for (Requirement requirement : reply.requires) { - if (!playerSatisfiesRequirement(world, requirement)) return false; + if (!canFulfillRequirement(world, requirement)) return false; } return true; } - private static boolean playerSatisfiesRequirement(final WorldContext world, final Requirement requirement) { + public static boolean canFulfillRequirement(WorldContext world, Requirement requirement) { Player player = world.model.player; + GameStatistics stats = world.model.statistics; switch (requirement.requireType) { case questProgress: return player.hasExactQuestProgress(requirement.requireID, requirement.value); + case questLatestProgress: + return player.isLatestQuestProgress(requirement.requireID, requirement.value); case wear: - return player.inventory.isWearing(requirement.requireID); + return player.inventory.isWearing(requirement.requireID, requirement.value); case inventoryKeep: case inventoryRemove: if (ItemTypeCollection.isGoldItemType(requirement.requireID)) { @@ -167,14 +166,33 @@ public final class ConversationController { case skillLevel: return player.getSkillLevel(SkillCollection.SkillID.valueOf(requirement.requireID)) >= requirement.value; case killedMonster: - return world.model.statistics.getNumberOfKillsForMonsterType(requirement.requireID) >= requirement.value; + return stats.getNumberOfKillsForMonsterType(requirement.requireID) >= requirement.value; case timerElapsed: return world.model.worldData.hasTimerElapsed(requirement.requireID, requirement.value); + case usedItem: + return stats.getNumberOfTimesItemHasBeenUsed(requirement.requireID) >= requirement.value; + case spentGold: + return stats.getSpentGold() >= requirement.value; + case consumedBonemeals: + return stats.getNumberOfUsedBonemealPotions() >= requirement.value; default: return true; } } + public static void requirementFulfilled(WorldContext world, Requirement requirement) { + Player p = world.model.player; + switch (requirement.requireType) { + case inventoryRemove: + if (ItemTypeCollection.isGoldItemType(requirement.requireID)) { + p.inventory.gold -= requirement.value; + world.model.statistics.addGoldSpent(requirement.value); + } else { + p.inventory.removeItem(requirement.requireID, requirement.value); + } + } + } + private static String getDisplayMessage(Phrase phrase, Player player) { return replacePlayerName(phrase.message, player); } private static String getDisplayMessage(Reply reply, Player player) { return replacePlayerName(reply.text, player); } private static String replacePlayerName(String s, Player player) { @@ -203,7 +221,7 @@ public final class ConversationController { public String getCurrentPhraseID() { return phraseID; } public void playerSelectedReply(final Resources res, Reply r) { - applyReplyEffect(player, r); + applyReplyEffect(world, r); proceedToPhrase(res, r.nextPhrase, true, true); } @@ -260,7 +278,7 @@ public final class ConversationController { if (currentPhrase.message == null) { for (Reply r : currentPhrase.replies) { if (!canSelectReply(world, r)) continue; - applyReplyEffect(player, r); + applyReplyEffect(world, r); proceedToPhrase(res, r.nextPhrase, giveRewards, displayPhraseMessage); return; } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MapController.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MapController.java index c9c3f3cda..bfee4373c 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MapController.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/MapController.java @@ -144,7 +144,10 @@ public final class MapController { } public boolean canEnterKeyArea(MapObject area) { - if (world.model.player.hasExactQuestProgress(area.requireQuestProgress)) return true; + if (ConversationController.canFulfillRequirement(world, area.enteringRequirement)) { + ConversationController.requirementFulfilled(world, area.enteringRequirement); + return true; + } worldEventListeners.onPlayerSteppedOnKeyArea(area); return false; } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/GameStatistics.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/GameStatistics.java index b2852b1c5..15a429951 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/GameStatistics.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/GameStatistics.java @@ -118,6 +118,11 @@ public final class GameStatistics { return result; } + public int getNumberOfTimesItemHasBeenUsed(String itemId) { + if (!usedItems.containsKey(itemId)) return 0; + return usedItems.get(itemId); + } + public int getNumberOfKilledMonsters() { int result = 0; for (int v : killedMonsters.values()) result += v; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Player.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Player.java index c297248a4..eb3b25aee 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Player.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Player.java @@ -140,6 +140,14 @@ public final class Player extends Actor { public boolean hasAnyQuestProgress(String questID) { return questProgress.containsKey(questID); } + public boolean isLatestQuestProgress(String questID, int progress) { + if (!questProgress.containsKey(questID)) return false; + if (!questProgress.get(questID).contains(progress)) return false; + for (int i : questProgress.get(questID)) { + if (i > progress) return false; + } + return true; + } public boolean addQuestProgress(QuestProgress progress) { if (hasExactQuestProgress(progress.questID, progress.progress)) return false; if (!questProgress.containsKey(progress.questID)) questProgress.put(progress.questID, new HashSet()); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/conversation/Reply.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/conversation/Reply.java index 29114604e..f89b6d150 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/conversation/Reply.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/conversation/Reply.java @@ -1,5 +1,7 @@ package com.gpl.rpg.AndorsTrail.model.conversation; +import com.gpl.rpg.AndorsTrail.model.script.Requirement; + public final class Reply { public final String text; public final String nextPhrase; diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/item/Inventory.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/item/Inventory.java index 6e8161959..b4ffb5f21 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/item/Inventory.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/item/Inventory.java @@ -64,6 +64,15 @@ public final class Inventory extends ItemContainer { return false; } + public boolean isWearing(String itemTypeID, int minNumber) { + if (minNumber == 0) return isWearing(itemTypeID); + for(int i = 0; i < NUM_WORN_SLOTS; ++i) { + if (wear[i] == null) continue; + if (wear[i].id.equals(itemTypeID)) minNumber--; + } + return minNumber <= 0; + } + public static boolean isArmorSlot(WearSlot slot) { if (slot == null) return false; switch (slot) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MapObject.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MapObject.java index e3c71a5c5..6fa7ec657 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MapObject.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/MapObject.java @@ -1,7 +1,7 @@ package com.gpl.rpg.AndorsTrail.model.map; import com.gpl.rpg.AndorsTrail.model.item.DropList; -import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress; +import com.gpl.rpg.AndorsTrail.model.script.Requirement; import com.gpl.rpg.AndorsTrail.util.CoordRect; public final class MapObject { @@ -26,7 +26,7 @@ public final class MapObject { public final String id; //placeName on this map or phraseID public final String map; public final String place; - public final QuestProgress requireQuestProgress; + public final Requirement enteringRequirement; public final DropList dropList; public final MapObjectEvaluationType evaluateWhen; @@ -36,7 +36,7 @@ public final class MapObject { , final String id , final String map , final String place - , final QuestProgress requireQuestProgress + , final Requirement enteringRequirement , final DropList dropList , final MapObjectEvaluationType evaluateWhen ) { @@ -45,7 +45,7 @@ public final class MapObject { this.id = id; this.map = map; this.place = place; - this.requireQuestProgress = requireQuestProgress; + this.enteringRequirement = enteringRequirement; this.dropList = dropList; this.evaluateWhen = evaluateWhen; } @@ -59,8 +59,8 @@ public final class MapObject { public static MapObject createRestArea(final CoordRect position, final String placeId) { return new MapObject(position, MapObjectType.rest, placeId, null, null, null, null, MapObjectEvaluationType.whenEntering); } - public static MapObject createKeyArea(final CoordRect position, final String phraseID, final QuestProgress requireQuestStage) { - return new MapObject(position, MapObjectType.keyarea, phraseID, null, null, requireQuestStage, null, MapObjectEvaluationType.whenEntering); + public static MapObject createKeyArea(final CoordRect position, final String phraseID, final Requirement enteringRequirement) { + return new MapObject(position, MapObjectType.keyarea, phraseID, null, null, enteringRequirement, null, MapObjectEvaluationType.whenEntering); } public static MapObject createContainerArea(final CoordRect position, final DropList dropList) { return new MapObject(position, MapObjectType.container, null, null, null, null, dropList, MapObjectEvaluationType.whenEntering); diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java index 7cbfce35a..d0530aa42 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/map/TMXMapTranslator.java @@ -8,6 +8,9 @@ import com.gpl.rpg.AndorsTrail.model.item.DropList; import com.gpl.rpg.AndorsTrail.model.item.DropListCollection; import com.gpl.rpg.AndorsTrail.model.map.TMXMapFileParser.*; import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress; +import com.gpl.rpg.AndorsTrail.model.script.Requirement; +import com.gpl.rpg.AndorsTrail.model.script.Requirement.RequirementType; +import com.gpl.rpg.AndorsTrail.resource.parsers.ResourceParserUtils; import com.gpl.rpg.AndorsTrail.resource.tiles.TileCache; import com.gpl.rpg.AndorsTrail.util.*; @@ -113,23 +116,24 @@ public final class TMXMapTranslator { ); spawnAreas.add(area); } else if (object.type.equalsIgnoreCase("key")) { - QuestProgress requireQuestStage = QuestProgress.parseQuestProgress(object.name); - if (requireQuestStage == null) { - if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { - L.log("OPTIMIZE: Map " + m.name + " contains key area at " + topLeft.toString() + " that cannot be parsed as a quest stage."); - } - continue; - } + Requirement.RequirementType requireType = Requirement.RequirementType.questProgress; + String requireId = null; + int requireValue = 1; String phraseID = ""; for (TMXProperty p : object.properties) { if (p.name.equalsIgnoreCase("phrase")) { phraseID = p.value; + } else if (p.name.equalsIgnoreCase("requireType")) { + requireType = Requirement.RequirementType.valueOf(p.value); + } else if (p.name.equalsIgnoreCase("requireId")) { + requireId = p.value; + } else if (p.name.equalsIgnoreCase("requireValue")) { + requireValue = Integer.parseInt(p.value); } else if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) { L.log("OPTIMIZE: Map " + m.name + ", key " + object.name + "@" + topLeft.toString() + " has unrecognized property \"" + p.name + "\"."); } } - - mapObjects.add(MapObject.createKeyArea(position, phraseID, requireQuestStage)); + mapObjects.add(MapObject.createKeyArea(position, phraseID, new Requirement(requireType, requireId, requireValue))); } else if (object.type.equals("rest")) { mapObjects.add(MapObject.createRestArea(position, object.name)); } else if (object.type.equals("container")) { diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/conversation/Requirement.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/script/Requirement.java similarity index 68% rename from AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/conversation/Requirement.java rename to AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/script/Requirement.java index 975a7aad8..0e656d34a 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/conversation/Requirement.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/script/Requirement.java @@ -1,14 +1,18 @@ -package com.gpl.rpg.AndorsTrail.model.conversation; +package com.gpl.rpg.AndorsTrail.model.script; public final class Requirement { public static enum RequirementType { questProgress + ,questLatestProgress // Highest quest stage reached must match. ,inventoryRemove // Player must have item(s) in inventory. Items will be removed when selecting reply. ,inventoryKeep // Player must have item(s) in inventory. Items will NOT be removed when selecting reply. ,wear // Player must be wearing item(s). Items will NOT be removed when selecting reply. ,skillLevel // Player needs to have a specific skill equal to or above a certain level ,killedMonster ,timerElapsed + ,usedItem + ,spentGold + ,consumedBonemeals } public final RequirementType requireType; @@ -20,4 +24,13 @@ public final class Requirement { this.requireID = requireID; this.value = value; } + + public String toString() { + StringBuffer buf = new StringBuffer(requireType.toString()); + buf.append("--"); + buf.append(requireID); + buf.append("--"); + buf.append(value); + return buf.toString(); + } } diff --git a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ConversationListParser.java b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ConversationListParser.java index 345a300af..fe177012b 100644 --- a/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ConversationListParser.java +++ b/AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ConversationListParser.java @@ -3,8 +3,8 @@ package com.gpl.rpg.AndorsTrail.resource.parsers; import com.gpl.rpg.AndorsTrail.AndorsTrailApplication; import com.gpl.rpg.AndorsTrail.model.conversation.Phrase; import com.gpl.rpg.AndorsTrail.model.conversation.Reply; -import com.gpl.rpg.AndorsTrail.model.conversation.Requirement; import com.gpl.rpg.AndorsTrail.model.conversation.Reward; +import com.gpl.rpg.AndorsTrail.model.script.Requirement; import com.gpl.rpg.AndorsTrail.resource.TranslationLoader; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonArrayParserFor; import com.gpl.rpg.AndorsTrail.resource.parsers.json.JsonCollectionParserFor; diff --git a/AndorsTrailEdit/partials/edit_dialogue.html b/AndorsTrailEdit/partials/edit_dialogue.html index 999ba3532..f9daf4fa4 100644 --- a/AndorsTrailEdit/partials/edit_dialogue.html +++ b/AndorsTrailEdit/partials/edit_dialogue.html @@ -186,12 +186,16 @@
@@ -204,6 +208,16 @@
+
+
+ + +
+
+ + +
+
@@ -229,6 +243,10 @@
+
+ + +
@@ -260,6 +278,28 @@
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+