package com.gpl.rpg.AndorsTrail.context;\r
\r
-import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;\r
import com.gpl.rpg.AndorsTrail.VisualEffectCollection;\r
-import com.gpl.rpg.AndorsTrail.conversation.ConversationCollection;\r
import com.gpl.rpg.AndorsTrail.conversation.ConversationLoader;\r
import com.gpl.rpg.AndorsTrail.model.ModelContainer;\r
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionTypeCollection;\r
\r
public class WorldContext {\r
//Objectcollections\r
- //public final ConversationCollection conversations;\r
public final ConversationLoader conversationLoader;\r
public final ItemTypeCollection itemTypes;\r
public final MonsterTypeCollection monsterTypes;\r
public void reset() {\r
maps.reset();\r
}\r
- \r
- // Selftest method. Not part of the game logic.\r
- public void verifyData(ConversationCollection conversations) {\r
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {\r
- assert(itemTypes.getItemType("gold") != null);\r
-\r
- //Ensure that all phrases that require an item have some droplist that contains them\r
- conversations.verifyData(dropLists);\r
- \r
- //Ensure that all phrases are requested at least once, either by NPCs, mapobjects or by other phrases.\r
- conversations.verifyData(monsterTypes, maps);\r
- \r
- //Ensure that all required quest stages exist\r
- conversations.verifyData(quests);\r
-\r
- //Ensure that all quest stages are required and supplied.\r
- conversations.verifyData(maps);\r
- \r
- //Ensure that all conversations that require quest items have quest progress updates\r
- conversations.verifyData(itemTypes);\r
-\r
- //Ensure that all quest stages are reachable by phrases\r
- quests.verifyData(conversations);\r
- \r
- //Ensure that all NPCs that have a trading conversation also have a droplist\r
- monsterTypes.verifyData(conversations);\r
- \r
- //Ensure that all items have at least one corresponding droplist\r
- itemTypes.verifyData(dropLists);\r
- \r
- //Ensure that all droplists are used by monsters\r
- dropLists.verifyData(monsterTypes, conversations, maps);\r
- \r
- //Ensure that all monsters are used in spawnareas\r
- monsterTypes.verifyData(maps);\r
-\r
- }\r
- }\r
}\r
import java.util.Collection;
import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map.Entry;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
-import com.gpl.rpg.AndorsTrail.conversation.Phrase.Reply;
-import com.gpl.rpg.AndorsTrail.conversation.Phrase.Reward;
-import com.gpl.rpg.AndorsTrail.model.actor.MonsterTypeCollection;
-import com.gpl.rpg.AndorsTrail.model.item.DropList;
-import com.gpl.rpg.AndorsTrail.model.item.DropListCollection;
-import com.gpl.rpg.AndorsTrail.model.item.ItemType;
-import com.gpl.rpg.AndorsTrail.model.item.ItemTypeCollection;
-import com.gpl.rpg.AndorsTrail.model.map.MapCollection;
-import com.gpl.rpg.AndorsTrail.model.quest.QuestCollection;
-import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress;
import com.gpl.rpg.AndorsTrail.resource.parsers.ConversationListParser;
import com.gpl.rpg.AndorsTrail.util.L;
private final HashMap<String, Phrase> phrases = new HashMap<String, Phrase>();
- public boolean isValidPhraseID(String id) {
- if (id.equals(PHRASE_CLOSE)) return true;
- else if (id.equals(PHRASE_SHOP)) return true;
- else if (id.equals(PHRASE_ATTACK)) return true;
- else if (id.equals(PHRASE_REMOVE)) return true;
- else if (phrases.containsKey(id)) return true;
- else return false;
- }
-
public Phrase getPhrase(String id) {
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
if (!phrases.containsKey(id)) {
public Collection<String> initialize(ConversationListParser parser, String input) {
return parser.parseRows(input, phrases);
}
-
- // Selftest method. Not part of the game logic.
- public void verifyData() {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- for (Entry<String, Phrase> e : phrases.entrySet()) {
- final String phraseID = e.getKey();
- for (Reply r : e.getValue().replies) {
- if (!isValidPhraseID(r.nextPhrase)) {
- L.log("WARNING: Phrase \"" + phraseID + "\" has reply to non-existing phrase \"" + r.nextPhrase + "\".");
- } else if (r.nextPhrase == null || r.nextPhrase.length() <= 0) {
- L.log("WARNING: Phrase \"" + phraseID + "\" has a reply that has no nextPhrase.");
- } else if (r.nextPhrase.equals(e.getKey())) {
- L.log("WARNING: Phrase \"" + phraseID + "\" has a reply that points to itself.");
- }
- }
-
- boolean hasNextReply = false;
- boolean hasOtherReply = false;
- for (Reply r : e.getValue().replies) {
- if (r.text.equalsIgnoreCase(REPLY_NEXT)) hasNextReply = true;
- else hasOtherReply = true;
- }
- if (hasNextReply && hasOtherReply) {
- L.log("WARNING: Phrase \"" + phraseID + "\" has both a \"" + REPLY_NEXT + "\" reply and some other reply.");
- }
- }
- }
- }
-
- // Selftest method. Not part of the game logic.
- public void verifyData(MapCollection maps) {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- HashSet<String> requiredQuestStages = new HashSet<String>();
- HashSet<String> suppliedQuestStages = new HashSet<String>();
- this.DEBUG_getSuppliedQuestStages(suppliedQuestStages);
- maps.DEBUG_getRequiredQuestStages(requiredQuestStages);
- this.DEBUG_getRequiredQuestStages(requiredQuestStages);
-
- for (String s : requiredQuestStages) {
- if (!suppliedQuestStages.contains(s)) {
- L.log("WARNING: Queststage \"" + s + "\" is required but never supplied by any phrases.");
- }
- }
- }
- }
-
- // Selftest method. Not part of the game logic.
- public void verifyData(DropListCollection droplists) {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- for (Entry<String, Phrase> e : phrases.entrySet()) {
- for (Reply r : e.getValue().replies) {
- if (r.requiresItem()) {
- if (!droplists.verifyExistsDroplistForItem(r.requiresItemTypeID)) {
- L.log("WARNING: Phrase \"" + e.getKey() + "\" has reply that requires \"" + r.requiresItemTypeID + "\", which is not dropped by any droplist.");
- }
- }
- }
- }
- }
- }
-
- // Selftest method. Not part of the game logic.
- public void verifyData(MonsterTypeCollection monsterTypes, MapCollection maps) {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- HashSet<String> requiredPhrases = monsterTypes.DEBUG_getRequiredPhrases();
- maps.DEBUG_getUsedPhrases(requiredPhrases);
- for (Entry<String, Phrase> e : phrases.entrySet()) {
- for (Reply r : e.getValue().replies) {
- requiredPhrases.add(r.nextPhrase);
- }
- }
- requiredPhrases.remove(PHRASE_ATTACK);
- requiredPhrases.remove(PHRASE_CLOSE);
- requiredPhrases.remove(PHRASE_SHOP);
- requiredPhrases.remove(PHRASE_REMOVE);
-
- // Verify that all supplied phrases are required.
- for (Entry<String, Phrase> e : phrases.entrySet()) {
- if (!requiredPhrases.contains(e.getKey())) {
- L.log("OPTIMIZE: Phrase \"" + e.getKey() + "\" cannot be reached by any monster or other phrase reply.");
- }
- }
- }
- }
-
- // Selftest method. Not part of the game logic.
- public void verifyData(QuestCollection quests) {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- for (Phrase p : phrases.values()) {
- if (p.rewards == null) continue;
- for (Reward r : p.rewards) {
- if (r.rewardType != Reward.REWARD_TYPE_QUEST_PROGRESS) continue;
- quests.getQuestLogEntry(new QuestProgress(r.rewardID, r.value)); // Will warn inside if invalid.
- }
- }
- }
- }
-
- // Selftest method. Not part of the game logic.
- public void verifyData(ItemTypeCollection itemTypes) {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- for (Entry<String, Phrase> e : phrases.entrySet()) {
- for (Reply r : e.getValue().replies) {
- if (!r.requiresItem()) continue;
- ItemType itemType = itemTypes.getItemType(r.requiresItemTypeID);
-
- if (r.itemRequirementType == Reply.ITEM_REQUIREMENT_TYPE_WEAR_KEEP) {
- if (!itemType.isEquippable()) L.log("WARNING: Phrase \"" + e.getKey() + "\" has a reply that requires a worn \"" + itemType + "\", but the item is not wearable.");
- }
-
- if (!itemType.isQuestItem()) continue;
-
- Phrase nextPhrase = getPhrase(r.nextPhrase);
- if (!hasQuestProgressReward(nextPhrase)) {
- L.log("WARNING: Phrase \"" + e.getKey() + "\" has a reply that requires a questitem, but the next phrase does not add quest progress.");
- }
- }
- }
- }
- }
-
- private boolean hasQuestProgressReward(Phrase nextPhrase) {
- if (nextPhrase.rewards == null) return false;
- for (Reward r : nextPhrase.rewards) {
- if (r.rewardType == Reward.REWARD_TYPE_QUEST_PROGRESS) return true;
- }
- return false;
- }
-
- // Selftest method. Not part of the game logic.
- public void DEBUG_getSuppliedQuestStages(HashSet<String> suppliedStages) {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- for (Phrase p : phrases.values()) {
- if (p.rewards == null) continue;
- for (Reward r : p.rewards) {
- if (r.rewardType != Reward.REWARD_TYPE_QUEST_PROGRESS) continue;
- QuestProgress progressQuest = new QuestProgress(r.rewardID, r.value);
- suppliedStages.add(progressQuest.toString());
- }
- }
- }
- }
-
- // Selftest method. Not part of the game logic.
- public void DEBUG_getRequiredQuestStages(HashSet<String> requiredStages) {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- for (Phrase p : phrases.values()) {
- for (Reply r : p.replies) {
- if (r.requiresProgress != null) {
- requiredStages.add(r.requiresProgress.toString());
- }
- }
- }
- }
- }
- // Selftest method. Not part of the game logic.
- public boolean DEBUG_leadsToTradeReply(String phraseID) {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- HashSet<String> visited = new HashSet<String>();
- return DEBUG_leadsToTradeReply(phraseID, visited);
- } else {
- return false;
- }
- }
- private boolean DEBUG_leadsToTradeReply(String phraseID, HashSet<String> visited) {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- if (phraseID.equals(PHRASE_SHOP)) return true;
- if (phraseID.equals(PHRASE_ATTACK)) return false;
- if (phraseID.equals(PHRASE_CLOSE)) return false;
- if (phraseID.equals(PHRASE_REMOVE)) return false;
- if (visited.contains(phraseID)) return false;
- visited.add(phraseID);
-
- Phrase p = getPhrase(phraseID);
- if (p == null) return false;
- for (Reply r : p.replies) {
- if (DEBUG_leadsToTradeReply(r.nextPhrase, visited)) return true;
- }
- }
- return false;
- }
-
- public void DEBUG_getUsedDroplists(HashSet<DropList> usedDropLists, final DropListCollection dropListCollection) {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- for (Phrase p : phrases.values()) {
- if (p.rewards == null) continue;
- for (Reward r : p.rewards) {
- if (r.rewardType != Reward.REWARD_TYPE_DROPLIST) continue;
-
- DropList d = dropListCollection.getDropList(r.rewardID);
- if (d != null) usedDropLists.add(d);
- }
- }
- }
+ // Unit test method. Not part of the game logic.
+ public HashMap<String, Phrase> UNITTEST_getAllPhrases() {
+ return phrases;
}
}
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.HashSet;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
-import com.gpl.rpg.AndorsTrail.context.WorldContext;
-import com.gpl.rpg.AndorsTrail.conversation.ConversationCollection;
-import com.gpl.rpg.AndorsTrail.model.item.DropList;
-import com.gpl.rpg.AndorsTrail.model.item.DropList.DropItem;
-import com.gpl.rpg.AndorsTrail.model.map.MapCollection;
import com.gpl.rpg.AndorsTrail.resource.parsers.MonsterTypeParser;
import com.gpl.rpg.AndorsTrail.util.L;
public final class MonsterTypeCollection {
private final HashMap<String, MonsterType> monsterTypesById = new HashMap<String, MonsterType>();
- public final HashMap<String, MonsterType> DEBUG_monsterTypesById = monsterTypesById;
public MonsterType getMonsterType(String id) {
if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
public void initialize(MonsterTypeParser parser, String input) {
parser.parseRows(input, monsterTypesById);
- }
-
- // Selftest method. Not part of the game logic.
- public void verifyData(WorldContext world, ConversationCollection conversations) {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- for (MonsterType t : monsterTypesById.values()) {
- if (t.phraseID != null) {
- if (!conversations.isValidPhraseID(t.phraseID)) {
- L.log("WARNING: Cannot find phrase \"" + t.phraseID + "\" for MonsterType \"" + t.id + "\".");
- }
- }
-
- if (t.dropList != null && t.isRespawnable && t.phraseID == null) {
- int averageItemDropGold = 0;
- for (DropItem item : t.dropList.DEBUG_items) {
- averageItemDropGold += item.itemType.baseMarketCost * item.quantity.averagef() * item.chance.current / item.chance.max;
- }
-
- float goldPerExpReward = (float) averageItemDropGold / t.exp;
- boolean warn = false;
- if (goldPerExpReward > 0.5) warn = true;
- else if (averageItemDropGold > 30 && goldPerExpReward > 0.3) warn = true;
-
- if (warn) L.log("Monster type " + t.id + " rewards " + averageItemDropGold + " gold drop on average, which is a bit high for the exp: " + t.exp + " (average " + goldPerExpReward + " gold per exp)");
- }
- }
- }
- }
-
- // Selftest method. Not part of the game logic.
- public void verifyData(ConversationCollection conversations) {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- for (MonsterType t : monsterTypesById.values()) {
- if (t.phraseID != null && t.phraseID.length() > 0) {
- if (conversations.DEBUG_leadsToTradeReply(t.phraseID)) {
- if (t.dropList == null) {
- L.log("WARNING: MonsterType \"" + t.id + "\" has conversation \"" + t.phraseID + "\" that leads to a trade, but the monster type does not have a droplist.");
- }
- }
- }
- }
- }
- }
-
- // Selftest method. Not part of the game logic.
- public void verifyData(MapCollection maps) {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- HashSet<String> availableMonsterIDs = new HashSet<String>(monsterTypesById.keySet());
- HashSet<String> usedSpawnedMonsterIDs = new HashSet<String>();
- maps.DEBUG_getSpawnedMonsterIDs(usedSpawnedMonsterIDs);
-
- availableMonsterIDs.removeAll(usedSpawnedMonsterIDs);
- for (String monsterTypeID : availableMonsterIDs) {
- L.log("WARNING: MonsterType \"" + monsterTypeID + "\" is never used on any spawnarea.");
- }
- }
- }
-
- // Selftest method. Not part of the game logic.
- public HashSet<String> DEBUG_getRequiredPhrases() {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- HashSet<String> requiredPhrases = new HashSet<String>();
- for (MonsterType t : monsterTypesById.values()) {
- if (t.phraseID != null && t.phraseID.length() > 0) {
- requiredPhrases.add(t.phraseID);
- }
- }
- return requiredPhrases;
- } else {
- return null;
- }
}
- // Selftest method. Not part of the game logic.
- public void DEBUG_getUsedDroplists(HashSet<DropList> usedDroplists) {
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- for (MonsterType t : monsterTypesById.values()) {
- if (t.dropList != null) usedDroplists.add(t.dropList);
- }
- }
+ // Unit test method. Not part of the game logic.
+ public HashMap<String, MonsterType> UNITTEST_getAllMonsterTypes() {
+ return monsterTypesById;
}
}
public final class DropList {
private final DropItem[] items;
- public final DropItem[] DEBUG_items;
public DropList(DropItem[] items) {
this.items = items;
- this.DEBUG_items = this.items;
}
public DropList(Collection<DropItem> items) {
this.items = items.toArray(new DropItem[items.size()]);
- this.DEBUG_items = this.items;
}
public void createRandomLoot(Loot loot, Player player) {
for (DropItem item : items) {
}
}
}
-
- // Selftest method. Not part of the game logic.
- public boolean DEBUG_contains(String itemTypeID) {
- for (DropItem item : items) {
- if (item.itemType.id.equals(itemTypeID)) return true;
- }
- return false;
+
+ // Unit test method. Not part of the game logic.
+ public DropItem[] UNITTEST_getAllDropItems() {
+ return items;
}
public static class DropItem {
package com.gpl.rpg.AndorsTrail.model.item;\r
\r
import java.util.HashMap;\r
-import java.util.HashSet;\r
-import java.util.Map.Entry;\r
\r
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;\r
-import com.gpl.rpg.AndorsTrail.conversation.ConversationCollection;\r
-import com.gpl.rpg.AndorsTrail.model.actor.MonsterTypeCollection;\r
-import com.gpl.rpg.AndorsTrail.model.map.MapCollection;\r
import com.gpl.rpg.AndorsTrail.resource.parsers.DropListParser;\r
import com.gpl.rpg.AndorsTrail.util.L;\r
\r
public void initialize(final DropListParser parser, String input) {\r
parser.parseRows(input, droplists);\r
}\r
- \r
- // Selftest method. Not part of the game logic.\r
- public boolean verifyExistsDroplistForItem(String itemTypeID) {\r
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {\r
- for (DropList d : droplists.values()) {\r
- if (d.DEBUG_contains(itemTypeID)) return true;\r
- }\r
- }\r
- return false;\r
- }\r
\r
- // Selftest method. Not part of the game logic.\r
- public void verifyData(MonsterTypeCollection monsterTypes, ConversationCollection conversations, MapCollection maps) {\r
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {\r
- HashSet<DropList> usedDroplists = new HashSet<DropList>();\r
- monsterTypes.DEBUG_getUsedDroplists(usedDroplists);\r
- conversations.DEBUG_getUsedDroplists(usedDroplists, this);\r
- maps.DEBUG_getUsedDroplists(usedDroplists);\r
- usedDroplists.add(getDropList(DropListCollection.DROPLIST_STARTITEMS));\r
- \r
- for (Entry<String, DropList> e : droplists.entrySet()) {\r
- if (!usedDroplists.contains(e.getValue())) {\r
- L.log("OPTIMIZE: Droplist " + e.getKey() + " is not used by any monster or conversation phrase.");\r
- }\r
- }\r
- } \r
+ // Unit test method. Not part of the game logic.\r
+ public HashMap<String, DropList> UNITTEST_getAllDropLists() {\r
+ return droplists;\r
}\r
}\r
package com.gpl.rpg.AndorsTrail.model.item;\r
\r
+import java.util.Collection;\r
import java.util.HashMap;\r
\r
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;\r
public void initialize(final ItemTypeParser parser, String input) {\r
parser.parseRows(input, itemTypes);\r
}\r
- \r
- // Selftest method. Not part of the game logic.\r
- public void verifyData(DropListCollection dropLists) {\r
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {\r
- for (ItemType t : itemTypes.values()) {\r
- if (!t.hasManualPrice) {\r
- if (t.effects_hit != null || t.effects_kill != null) {\r
- L.log("OPTIMIZE: Item " + t.id + " uses automatic pricing, but has kill- or hit effects. Should probably use manual pricing?");\r
- }\r
- if (t.effects_equip == null && t.effects_use == null) {\r
- L.log("OPTIMIZE: Item " + t.id + " uses automatic pricing, but has no equip- or use effects. Should probably use manual pricing?");\r
- } else if (!t.isUsable() && !t.isEquippable()) {\r
- L.log("OPTIMIZE: Item " + t.id + " uses automatic pricing, but is neither usable nor equippable. Should probably use manual pricing?");\r
- }\r
- } else {\r
- if (t.baseMarketCost != 0 && t.isQuestItem()) {\r
- L.log("OPTIMIZE: Item " + t.id + " is a quest item, but has a base market price specified.");\r
- } else if (t.baseMarketCost == 0 && t.isOrdinaryItem()) {\r
- L.log("OPTIMIZE: Item " + t.id + " does not have a base market price specified (and is an ordinary item).");\r
- }\r
- }\r
- \r
- if (t.isEquippable()) {\r
- if (t.effects_equip == null && t.effects_hit == null && t.effects_kill == null ) {\r
- L.log("OPTIMIZE: Item " + t.id + " is equippable, but has no equip effect.");\r
- }\r
- } else {\r
- if (t.effects_equip != null || t.effects_hit != null || t.effects_kill != null ) {\r
- L.log("OPTIMIZE: Item " + t.id + " is not equippable, but has equip, hit or kill effect.");\r
- }\r
- }\r
- if (t.isUsable()) {\r
- if (t.effects_use == null) {\r
- L.log("OPTIMIZE: Item " + t.id + " is usable, but has no use effect.");\r
- }\r
- } else {\r
- if (t.effects_use != null) {\r
- L.log("OPTIMIZE: Item " + t.id + " is not usable, but has use effect.");\r
- }\r
- }\r
- \r
- if (!dropLists.verifyExistsDroplistForItem(t.id)) {\r
- L.log("OPTIMIZE: Item " + t.id + " is not dropped by any droplist.");\r
- }\r
- } \r
- }\r
+\r
+ // Unit test method. Not part of the game logic.\r
+ public Collection<ItemType> UNITTEST_getAllItemTypes() {\r
+ return itemTypes.values();\r
}\r
}\r
\ No newline at end of file
import java.io.DataOutputStream;\r
import java.io.IOException;\r
import java.util.ArrayList;\r
-import java.util.Arrays;\r
-import java.util.HashSet;\r
\r
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;\r
import com.gpl.rpg.AndorsTrail.context.WorldContext;\r
-import com.gpl.rpg.AndorsTrail.conversation.ConversationCollection;\r
-import com.gpl.rpg.AndorsTrail.model.item.DropList;\r
import com.gpl.rpg.AndorsTrail.util.L;\r
\r
public final class MapCollection {\r
}\r
}\r
\r
- // Selftest method. Not part of the game logic.\r
- public void verifyData(WorldContext world, ConversationCollection conversations) {\r
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {\r
- for (PredefinedMap m : predefinedMaps) {\r
- for (MapObject o : m.eventObjects) {\r
- if (o.type == MapObject.MAPEVENT_NEWMAP) {\r
- if (!o.shouldHaveDestinationMap()) continue;\r
- \r
- final String desc = "Map \"" + m.name + "\", place \"" + o.id + "\"";\r
- if (o.map == null || o.map.length() <= 0) {\r
- L.log("OPTIMIZE: " + desc + " has no destination map.");\r
- } else if (o.place == null || o.place.length() <= 0) {\r
- L.log("OPTIMIZE: " + desc + " has no destination place.");\r
- } else {\r
- PredefinedMap destination = findPredefinedMap(o.map);\r
- if (destination == null) {\r
- L.log("WARNING: " + desc + " references non-existing destination map \"" + o.map + "\".");\r
- continue;\r
- }\r
- MapObject place = destination.findEventObject(MapObject.MAPEVENT_NEWMAP, o.place);\r
- if (place == null) {\r
- L.log("WARNING: " + desc + " references non-existing destination place \"" + o.place + "\" on map \"" + o.map + "\".");\r
- continue;\r
- }\r
- \r
- if (!o.position.size.equals(place.position.size)) {\r
- L.log("WARNING: " + desc + " references destination place \"" + o.place + "\" on map \"" + o.map + "\", with different mapchange size.");\r
- continue;\r
- }\r
- if (place.shouldHaveDestinationMap()) {\r
- if (!m.name.equalsIgnoreCase(place.map)) {\r
- L.log("WARNING: " + desc + " references destination place \"" + o.place + "\" on map \"" + o.map + "\", but that place does not reference back to this map.");\r
- continue;\r
- }\r
- if (!o.id.equalsIgnoreCase(place.place)) {\r
- L.log("WARNING: " + desc + " references destination place \"" + o.place + "\" on map \"" + o.map + "\", but that place does not reference back to this place.");\r
- continue;\r
- }\r
- }\r
- }\r
- \r
- if (m.findEventObject(MapObject.MAPEVENT_NEWMAP, o.id) != o) {\r
- L.log("WARNING: Map \"" + m.name + "\" contains duplicate maparea with id \"" + o.id + "\".");\r
- continue;\r
- }\r
- } else if (o.type == MapObject.MAPEVENT_KEYAREA) {\r
- if (o.id == null || o.id.length() <= 0) {\r
- L.log("WARNING: Map \"" + m.name + "\" contains keyarea without phraseid.");\r
- continue;\r
- } \r
- conversations.getPhrase(o.id); // Will warn inside if not available.\r
- } else if (o.type == MapObject.MAPEVENT_SIGN) {\r
- if (o.id == null || o.id.length() <= 0) {\r
- L.log("WARNING: Map \"" + m.name + "\" contains sign without phraseid.");\r
- continue;\r
- } \r
- conversations.getPhrase(o.id); // Will warn inside if not available.\r
- } else if (o.type == MapObject.MAPEVENT_REST) {\r
- if (o.id == null || o.id.length() <= 0) {\r
- L.log("WARNING: Map \"" + m.name + "\" contains rest area without id.");\r
- continue;\r
- }\r
- if (m.findEventObject(MapObject.MAPEVENT_REST, o.id) != o) {\r
- L.log("WARNING: Map \"" + m.name + "\" contains duplicate rest area with id \"" + o.id + "\".");\r
- continue;\r
- }\r
- }\r
- }\r
- \r
- for (int i = 0; i < m.spawnAreas.length; ++i) {\r
- MonsterSpawnArea uniqueArea = m.spawnAreas[i];\r
- if (!uniqueArea.isUnique) continue;\r
- \r
- for (int j = 0; j < i; ++j) {\r
- MonsterSpawnArea nonUniqueArea = m.spawnAreas[j];\r
- if (nonUniqueArea.isUnique) continue;\r
- if (nonUniqueArea.area.intersects(uniqueArea.area)) {\r
- L.log("WARNING: Map \"" + m.name + "\" contains unique spawnarea at " + uniqueArea.area.toString() + " that intersects a nonunique spawnarea. Consider placing the unique spawn first to make sure that this monster has a place to spawn.");\r
- }\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- // Selftest method. Not part of the game logic.\r
- public void DEBUG_getRequiredQuestStages(HashSet<String> requiredStages) {\r
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {\r
- for (PredefinedMap m : predefinedMaps) {\r
- for (MapObject o : m.eventObjects) {\r
- if (o.type == MapObject.MAPEVENT_KEYAREA) {\r
- if (o.requireQuestProgress == null) continue;\r
- requiredStages.add(o.requireQuestProgress.toString());\r
- }\r
- }\r
- }\r
- }\r
- }\r
- \r
- // Selftest method. Not part of the game logic.\r
- public void DEBUG_getUsedPhrases(HashSet<String> usedPhrases) {\r
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {\r
- for (PredefinedMap m : predefinedMaps) {\r
- for (MapObject o : m.eventObjects) {\r
- if (o.type == MapObject.MAPEVENT_KEYAREA || o.type == MapObject.MAPEVENT_SIGN) {\r
- if (o.id == null || o.id.length() <= 0) continue;\r
- usedPhrases.add(o.id);\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- // Selftest method. Not part of the game logic.\r
- public void DEBUG_getUsedDroplists(HashSet<DropList> usedDropLists) {\r
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {\r
- for (PredefinedMap m : predefinedMaps) {\r
- for (MapObject o : m.eventObjects) {\r
- if (o.dropList != null) usedDropLists.add(o.dropList);\r
- }\r
- }\r
- }\r
- }\r
- \r
- // Selftest method. Not part of the game logic.\r
- public void DEBUG_getSpawnedMonsterIDs(HashSet<String> usedMonsterTypeIDs) {\r
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {\r
- for (PredefinedMap m : predefinedMaps) {\r
- for (MonsterSpawnArea a : m.spawnAreas) {\r
- usedMonsterTypeIDs.addAll(Arrays.asList(a.monsterTypeIDs));\r
- }\r
- }\r
- }\r
- }\r
-\r
-\r
\r
// ====== PARCELABLE ===================================================================\r
\r
public static MapObject createNewContainerArea(final CoordRect position, final DropList dropList) {
return new MapObject(position, MAPEVENT_CONTAINER, null, null, null, null, dropList);
}
-
- public boolean shouldHaveDestinationMap() {
- if (type != MAPEVENT_NEWMAP) return false;
- if (id.equals("exit")) return false;
- return true;
- }
}
import java.util.Collection;\r
import java.util.Collections;\r
import java.util.HashMap;\r
-import java.util.HashSet;\r
\r
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;\r
-import com.gpl.rpg.AndorsTrail.conversation.ConversationCollection;\r
import com.gpl.rpg.AndorsTrail.resource.parsers.QuestParser;\r
import com.gpl.rpg.AndorsTrail.util.L;\r
\r
public void initialize(QuestParser parser, String input) {\r
parser.parseRows(input, quests);\r
}\r
-\r
- \r
- // Selftest method. Not part of the game logic.\r
- public void verifyData() {\r
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {\r
- for (Quest q : quests.values()) {\r
- if (q.name.trim().length() <= 0) {\r
- L.log("WARNING: Quest \"" + q.questID + "\" has empty name.");\r
- }\r
- if (q.stages.length <= 0) {\r
- L.log("WARNING: Quest \"" + q.questID + "\" has no log entries.");\r
- }\r
- boolean hasFinishingEntry = false;\r
- for (QuestLogEntry entry : q.stages) {\r
- if (entry.finishesQuest) hasFinishingEntry = true;\r
- if (entry.rewardExperience == 1) {\r
- L.log("WARNING: Quest \"" + q.questID + "\" has stage " + entry.progress + " that rewards just 1 exp. Might be malformed resourcefile?");\r
- }\r
- }\r
- if (q.showInLog) {\r
- if (!hasFinishingEntry) {\r
- L.log("WARNING: Quest \"" + q.questID + "\" is shown in log, but has no progress stage that finishes the quest.");\r
- }\r
- }\r
- } \r
- }\r
- }\r
- \r
- // Selftest method. Not part of the game logic.\r
- public void verifyData(ConversationCollection conversations) {\r
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {\r
- final HashSet<String> suppliedStages = new HashSet<String>();\r
- conversations.DEBUG_getSuppliedQuestStages(suppliedStages);\r
- for (Quest q : quests.values()) {\r
- for (QuestLogEntry e : q.stages) {\r
- String s = q.questID + ":" + e.progress;\r
- if (!suppliedStages.contains(s)) {\r
- L.log("OPTIMIZE: Quest stage \"" + s + "\" cannot be reached by any conversation phrase.");\r
- }\r
- }\r
- } \r
- }\r
- }\r
}\r
for (int i = 0; i < questsToLoad.length(); ++i) {
world.quests.initialize(questParser, questsToLoad.getString(i));
}
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- world.quests.verifyData();
- }
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) timingCheckpoint("QuestParser");
// Load conversations
final ConversationListParser conversationListParser = new ConversationListParser();
final TypedArray conversationsListsToLoad = r.obtainTypedArray(conversationsListsResourceId);
- ConversationCollection conversations = new ConversationCollection();
for (int i = 0; i < conversationsListsToLoad.length(); ++i) {
+ ConversationCollection conversations = new ConversationCollection();
Collection<String> ids = conversations.initialize(conversationListParser, conversationsListsToLoad.getString(i));
world.conversationLoader.addIDs(conversationsListsToLoad.getResourceId(i, -1), ids);
}
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- conversations.verifyData();
- }
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) timingCheckpoint("ConversationListParser");
for (int i = 0; i < monstersToLoad.length(); ++i) {
world.monsterTypes.initialize(monsterTypeParser, monstersToLoad.getString(i));
}
-
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- world.monsterTypes.verifyData(world, conversations);
- }
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) timingCheckpoint("MonsterTypeParser");
world.maps.predefinedMaps.addAll(mapReader.transformMaps(loader, world.monsterTypes, world.dropLists));
mapReader = null;
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) timingCheckpoint("mapReader.transformMaps");
-
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- world.maps.verifyData(world, conversations);
- }
// ========================================================================
// ========================================================================
- if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
- world.verifyData(conversations);
- }
- if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) timingCheckpoint("world.verifyData()");
-
if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) {
long duration = System.currentTimeMillis() - start;
L.log("ResourceLoader ran for " + duration + " ms.");
if (questProgress != null) rewards.add(new Reward(Reward.REWARD_TYPE_QUEST_PROGRESS, questProgress.questID, questProgress.progress));
String rewardDroplist = ResourceParserUtils.parseNullableString(parts[3]);
if (rewardDroplist != null) rewards.add(new Reward(Reward.REWARD_TYPE_DROPLIST, rewardDroplist, 0));
- final Reward[] _rewards = rewards.toArray(new Reward[rewards.size()]);
+ Reward[] _rewards = rewards.toArray(new Reward[rewards.size()]);
+ if (_rewards.length == 0) _rewards = null;
return new Pair<String, Phrase>(parts[0], new Phrase(
ResourceParserUtils.parseNullableString(parts[1]) // message