]> www.infradead.org Git - users/mchehab/andors-trail.git/commitdiff
Updated reward system for conversations. Rewards can now be skills or actorconditions...
authoroskar.wiksten <oskar.wiksten@08aca716-68be-ccc6-4d58-36f5abd142ac>
Thu, 5 Jan 2012 20:14:53 +0000 (20:14 +0000)
committeroskar.wiksten <oskar.wiksten@08aca716-68be-ccc6-4d58-36f5abd142ac>
Thu, 5 Jan 2012 20:14:53 +0000 (20:14 +0000)
Item requirements for selecting conversation replies now also support rrequring the player to be wearing a specific item, and having a requirement without removing the item when selecting the reply.

git-svn-id: https://andors-trail.googlecode.com/svn/trunk@210 08aca716-68be-ccc6-4d58-36f5abd142ac

AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/ConversationActivity.java
AndorsTrail/src/com/gpl/rpg/AndorsTrail/activity/HeroinfoActivity_Skills.java
AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ActorStatsController.java
AndorsTrail/src/com/gpl/rpg/AndorsTrail/controller/ConversationController.java
AndorsTrail/src/com/gpl/rpg/AndorsTrail/conversation/ConversationCollection.java
AndorsTrail/src/com/gpl/rpg/AndorsTrail/conversation/Phrase.java
AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/actor/Player.java
AndorsTrail/src/com/gpl/rpg/AndorsTrail/model/item/Inventory.java
AndorsTrail/src/com/gpl/rpg/AndorsTrail/resource/parsers/ConversationListParser.java

index 7ac388e5cd09fe87d18619e5b98e6952230a62a5..2807c071973e36914965ba941ff96a6289af022e 100644 (file)
@@ -207,9 +207,9 @@ public final class ConversationActivity extends Activity implements OnKeyListene
        
        phrase = world.conversationLoader.loadPhrase(phraseID, conversationCollection, getResources());
        if (AndorsTrailApplication.DEVELOPMENT_DEBUGMESSAGES) {
-               if (phrase == null) phrase = new Phrase("(phrase \"" + phraseID + "\" not implemented yet)", null, null, null);
+               if (phrase == null) phrase = new Phrase("(phrase \"" + phraseID + "\" not implemented yet)", null, null);
        }
-       Loot loot = ConversationController.applyPhraseEffect(player, phrase, world.quests, world.dropLists);
+       Loot loot = ConversationController.applyPhraseRewards(player, phrase, world);
        
        if (phrase.message == null) {
                for (Reply r : phrase.replies) {
index 37fe20006f1cc39249009ab650003b9a9febabd3..15be691b7755990686ad722bbca5266970bec2b0 100644 (file)
@@ -57,7 +57,7 @@ public final class HeroinfoActivity_Skills extends Activity {
                        if (resultCode != RESULT_OK) break;
                        
                        int skillID = data.getExtras().getInt("skillID");
-                       player.addSkillLevel(skillID);
+                       player.addSkillLevel(skillID, true);
                        break;
                }
        }
index eba2f07ea273bd3787794e430531dff2e86bd341..25cd0112af41f6feebc33b91d08d9818b850be67 100644 (file)
@@ -47,20 +47,48 @@ public class ActorStatsController {
                }
        }
        
-       private static void applyActorCondition(Actor actor, ActorConditionEffect e) { applyActorCondition(actor, e, e.duration); }
+       public static void applyActorCondition(Actor actor, ActorConditionEffect e) { applyActorCondition(actor, e, e.duration); }
        private static void applyActorCondition(Actor actor, ActorConditionEffect e, int duration) {
-               final ActorConditionType type = e.conditionType;
                if (e.isRemovalEffect()) {
-                       removeAllConditionsOfType(actor, type.conditionTypeID);
+                       removeAllConditionsOfType(actor, e.conditionType.conditionTypeID);
                } else if (e.magnitude > 0) {
-                       if (!e.conditionType.isStacking) {
-                               if (actor.hasCondition(type.conditionTypeID)) return;
-                               //TODO: Maybe only keep the one with the highest magnitude?
+                       if (e.conditionType.isStacking) {
+                               addStackableActorCondition(actor, e, duration);
+                       } else {
+                               addNonStackableActorCondition(actor, e, duration);
                        }
-                       actor.conditions.add(e.createCondition(duration));
                }
        }
 
+       private static void addStackableActorCondition(Actor actor, ActorConditionEffect e, int duration) {
+               final ActorConditionType type = e.conditionType;
+               int magnitude = e.magnitude;
+               
+               for(int i = actor.conditions.size() - 1; i >= 0; --i) {
+                       ActorCondition c = actor.conditions.get(i);
+                       if (!type.conditionTypeID.equals(c.conditionType.conditionTypeID)) continue;
+                       if (c.duration == duration) {
+                               // If the actor already has a condition of this type and the same duration, just increase the magnitude instead.
+                               actor.conditions.remove(i);
+                               magnitude += c.magnitude;
+                               break;
+                       }
+               }
+               actor.conditions.add(new ActorCondition(type, magnitude, duration));
+       }
+       private static void addNonStackableActorCondition(Actor actor, ActorConditionEffect e, int duration) {
+               final ActorConditionType type = e.conditionType;
+               
+               for(int i = actor.conditions.size() - 1; i >= 0; --i) {
+                       ActorCondition c = actor.conditions.get(i);
+                       if (!type.conditionTypeID.equals(c.conditionType.conditionTypeID)) continue;
+                       if (c.magnitude > e.magnitude) return;
+                       // If the actor already has this condition, but of a lower magnitude, we remove the old one and add this higher magnitude.
+                       actor.conditions.remove(i);
+               }
+               actor.conditions.add(e.createCondition(duration));
+       }
+
        public static void removeAllTemporaryConditions(final Actor actor) {
                for(int i = actor.conditions.size() - 1; i >= 0; --i) {
                        if (!actor.conditions.get(i).isTemporaryEffect()) continue;
index 4a86afde991f2f88cf0be87f68dfc53c45b98a1f..44bbb3aa6ee6e237053c68ae76549adf50e9050a 100644 (file)
@@ -1,53 +1,78 @@
 package com.gpl.rpg.AndorsTrail.controller;\r
 \r
+import com.gpl.rpg.AndorsTrail.context.WorldContext;\r
 import com.gpl.rpg.AndorsTrail.conversation.Phrase;\r
 import com.gpl.rpg.AndorsTrail.conversation.Phrase.Reply;\r
+import com.gpl.rpg.AndorsTrail.conversation.Phrase.Reward;\r
+import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;\r
+import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionEffect;\r
+import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionType;\r
 import com.gpl.rpg.AndorsTrail.model.actor.Player;\r
-import com.gpl.rpg.AndorsTrail.model.item.DropListCollection;\r
 import com.gpl.rpg.AndorsTrail.model.item.ItemTypeCollection;\r
 import com.gpl.rpg.AndorsTrail.model.item.Loot;\r
-import com.gpl.rpg.AndorsTrail.model.quest.QuestCollection;\r
 import com.gpl.rpg.AndorsTrail.model.quest.QuestLogEntry;\r
 import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress;\r
+import com.gpl.rpg.AndorsTrail.util.ConstRange;\r
 \r
 public final class ConversationController {\r
 \r
-       public static Loot applyPhraseEffect(final Player player, final Phrase phrase, final QuestCollection questcollection, final DropListCollection dropListCollection) {\r
-               if (phrase.rewardDropListID == null && phrase.progressQuest == null) return null;\r
+       private static final ConstRange always = new ConstRange(1, 1);\r
+       \r
+       public static Loot applyPhraseRewards(final Player player, final Phrase phrase, final WorldContext world) {\r
+               if (phrase.rewards == null || phrase.rewards.length == 0) return null;\r
                \r
                final Loot loot = new Loot();\r
-               if (phrase.rewardDropListID != null) {\r
-                       dropListCollection.getDropList(phrase.rewardDropListID).createRandomLoot(loot, player);\r
-                       player.inventory.add(loot);\r
-               }\r
-               if (phrase.progressQuest != null) {\r
-                       boolean added = player.addQuestProgress(phrase.progressQuest);\r
-                       if (added) {  // Only apply exp reward if the quest stage was reached just now (and not re-reached)\r
-                               QuestLogEntry stage = questcollection.getQuestLogEntry(phrase.progressQuest);\r
-                               if (stage != null) {\r
-                                       loot.exp = stage.rewardExperience;\r
-                                       player.addExperience(stage.rewardExperience);\r
+               for (Reward reward : phrase.rewards) {\r
+                       switch (reward.rewardType) {\r
+                       case Reward.REWARD_TYPE_ACTOR_CONDITION:\r
+                               int magnitude = 1;\r
+                               int duration = reward.value;\r
+                               if (reward.value == ActorCondition.DURATION_FOREVER) duration = ActorCondition.DURATION_FOREVER;\r
+                               else if (reward.value == ActorCondition.MAGNITUDE_REMOVE_ALL) magnitude = ActorCondition.MAGNITUDE_REMOVE_ALL;\r
+                               \r
+                               ActorConditionType conditionType = world.actorConditionsTypes.getActorConditionType(reward.rewardID);\r
+                               ActorConditionEffect e = new ActorConditionEffect(conditionType, magnitude, duration, always);\r
+                               ActorStatsController.applyActorCondition(player, e);\r
+                               break;\r
+                       case Reward.REWARD_TYPE_SKILL_INCREASE:\r
+                               player.addSkillLevel(Integer.parseInt(reward.rewardID), false);\r
+                               break;\r
+                       case Reward.REWARD_TYPE_DROPLIST:\r
+                               world.dropLists.getDropList(reward.rewardID).createRandomLoot(loot, player);\r
+                               break;\r
+                       case Reward.REWARD_TYPE_QUEST_PROGRESS:\r
+                               QuestProgress progress = new QuestProgress(reward.rewardID, reward.value);\r
+                               boolean added = player.addQuestProgress(progress);\r
+                               if (added) {  // Only apply exp reward if the quest stage was reached just now (and not re-reached)\r
+                                       QuestLogEntry stage = world.quests.getQuestLogEntry(progress);\r
+                                       if (stage != null) {\r
+                                               loot.exp += stage.rewardExperience;\r
+                                       }\r
                                }\r
+                               break;\r
                        }\r
                }\r
+               \r
+               player.inventory.add(loot);\r
+               player.addExperience(loot.exp);\r
                return loot;\r
        }\r
        \r
        public static void applyReplyEffect(final Player player, final Reply reply) {\r
                if (!reply.requiresItem()) return;\r
                \r
-               if (ItemTypeCollection.isGoldItemType(reply.requiresItemTypeID)) {\r
-                       player.inventory.gold -= reply.requiresItemQuantity;\r
-               } else {\r
-                       player.inventory.removeItem(reply.requiresItemTypeID, reply.requiresItemQuantity);\r
+               if (reply.itemRequirementType == Reply.ITEM_REQUIREMENT_TYPE_INVENTORY_REMOVE) {\r
+                       if (ItemTypeCollection.isGoldItemType(reply.requiresItemTypeID)) {\r
+                               player.inventory.gold -= reply.requiresItemQuantity;\r
+                       } else {\r
+                               player.inventory.removeItem(reply.requiresItemTypeID, reply.requiresItemQuantity);\r
+                       }\r
                }\r
        }\r
     \r
        public static boolean canSelectReply(final Player player, final Reply reply) {\r
                if (!hasRequiredQuestProgress(player, reply.requiresProgress)) return false;\r
-               if (reply.requiresItem()) {\r
-                       if (!hasRequiredItems(player, reply.requiresItemTypeID, reply.requiresItemQuantity)) return false;\r
-               }\r
+               if (!hasRequiredItems(player, reply)) return false;\r
                return true;\r
     }\r
        \r
@@ -56,10 +81,16 @@ public final class ConversationController {
        return player.hasExactQuestProgress(progress);\r
     }\r
        \r
-       private static boolean hasRequiredItems(final Player player, String requiresItemTypeID, int requiresItemQuantity) {\r
-       if (ItemTypeCollection.isGoldItemType(requiresItemTypeID)) return player.inventory.gold >= requiresItemQuantity;\r
-               \r
-       return player.inventory.hasItem(requiresItemTypeID, requiresItemQuantity);\r
+       private static boolean hasRequiredItems(final Player player, Reply reply) {\r
+               if (!reply.requiresItem()) return true;\r
+               \r
+       if (ItemTypeCollection.isGoldItemType(reply.requiresItemTypeID)) { \r
+               return player.inventory.gold >= reply.requiresItemQuantity;\r
+       } else if (reply.itemRequirementType == Reply.ITEM_REQUIREMENT_TYPE_WEAR_KEEP) {\r
+               return player.inventory.isWearing(reply.requiresItemTypeID);\r
+       } else {\r
+               return player.inventory.hasItem(reply.requiresItemTypeID, reply.requiresItemQuantity);\r
+       }\r
     }\r
 \r
        public static String getDisplayMessage(Phrase phrase, Player player) { return replacePlayerName(phrase.message, player); }\r
index f29086265bddec1bc860a1c6095db9463052c1b8..5c08588b640d8ff9c1aeacb509d7b7fdfad110e0 100644 (file)
@@ -7,6 +7,7 @@ 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;
@@ -14,6 +15,7 @@ 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;
 
@@ -137,9 +139,11 @@ public final class ConversationCollection {
        public void verifyData(QuestCollection quests) {
        if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
                for (Phrase p : phrases.values()) {
-                               if (p.progressQuest != null) {
-                                       quests.getQuestLogEntry(p.progressQuest); // Will warn inside if invalid.
-                       }
+                       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.
+                               }
                }
        }
     }
@@ -151,10 +155,15 @@ public final class ConversationCollection {
                                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 (nextPhrase.progressQuest == null) {
+                                       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.");
                                        }
                                }
@@ -162,12 +171,24 @@ public final class ConversationCollection {
                }       
     }
 
+       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.progressQuest == null) continue;
-                               suppliedStages.add(p.progressQuest.toString());
+                               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());
+                               }
                        }
                }
        }
@@ -215,8 +236,11 @@ public final class ConversationCollection {
        public void DEBUG_getUsedDroplists(HashSet<DropList> usedDropLists, final DropListCollection dropListCollection) {
                if (AndorsTrailApplication.DEVELOPMENT_VALIDATEDATA) {
                        for (Phrase p : phrases.values()) {
-                               if (p.rewardDropListID != null) {
-                                       DropList d = dropListCollection.getDropList(p.rewardDropListID);
+                               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);
                                }
                        }
index e5f8e4e30d790c279956986a3f24fe4cd7e83c8f..f9915a002c0e3a09a9fde6d911faad4df03525f6 100644 (file)
@@ -7,23 +7,26 @@ public final class Phrase {
        
        public final String message;
        public final Reply[] replies;
-       public final QuestProgress progressQuest;       // If this phrase is reached, this quest will be updated.
-       public final String rewardDropListID;           // If this phrase is reached, player will be awarded all these items
+       public final Reward[] rewards; // If this phrase is reached, player will be awarded all these rewards
        
-       public Phrase(String message, Reply[] replies, QuestProgress progressQuest, String rewardDropListID) {
+       public Phrase(String message, Reply[] replies, Reward[] rewards) {
                this.message = message;
                if (replies == null) replies = NO_REPLIES;
                this.replies = replies;
-               this.progressQuest = progressQuest;
-               this.rewardDropListID = rewardDropListID;
+               this.rewards = rewards;
        }
 
        public static final class Reply {
+               public static final int ITEM_REQUIREMENT_TYPE_INVENTORY_REMOVE = 0; // Player must have item(s) in inventory. Items will be removed when selecting reply.
+               public static final int ITEM_REQUIREMENT_TYPE_INVENTORY_KEEP = 1; // Player must have item(s) in inventory. Items will NOT be removed when selecting reply.
+               public static final int ITEM_REQUIREMENT_TYPE_WEAR_KEEP = 2; // Player must be wearing item(s). Items will NOT be removed when selecting reply.
+               
                public final String text;
                public final String nextPhrase;
                public final QuestProgress requiresProgress;
                public final String requiresItemTypeID;
                public final int requiresItemQuantity;
+               public final int itemRequirementType;
                
                public boolean requiresItem() {
                        if (requiresItemTypeID == null) return false;
@@ -31,12 +34,30 @@ public final class Phrase {
                return true;
                }
                
-               public Reply(String text, String nextPhrase, QuestProgress requiresProgress, String requiresItemTypeID, int requiresItemQuantity) {
+               public Reply(String text, String nextPhrase, QuestProgress requiresProgress, String requiresItemTypeID, int requiresItemQuantity, int itemRequirementType) {
                        this.text = text;
                        this.nextPhrase = nextPhrase;
                        this.requiresProgress = requiresProgress;
                        this.requiresItemTypeID = requiresItemTypeID;
                        this.requiresItemQuantity = requiresItemQuantity;
+                       this.itemRequirementType = itemRequirementType;
+               }
+       }
+       
+       public static final class Reward {
+               public static final int REWARD_TYPE_QUEST_PROGRESS = 0;
+               public static final int REWARD_TYPE_DROPLIST = 1;
+               public static final int REWARD_TYPE_SKILL_INCREASE = 2;
+               public static final int REWARD_TYPE_ACTOR_CONDITION = 3;
+               
+               public final int rewardType;
+               public final String rewardID;
+               public final int value;
+               
+               public Reward(int rewardType, String rewardID, int value) {
+                       this.rewardType = rewardType;
+                       this.rewardID = rewardID;
+                       this.value = value;
                }
        }
 }
index d8f0cb7c90309ce580d7f5c6f4e67ff1fdd7b5a8..23a9ec09aebb206de194b98df0d30c2ff3c7246a 100644 (file)
@@ -136,11 +136,13 @@ public final class Player extends Actor {
        public boolean hasSkill(int skillID) {
                return getSkillLevel(skillID) > 0;
        }
-       public void addSkillLevel(int skillID) {
-               if (!hasAvailableSkillpoints()) return;
+       public void addSkillLevel(int skillID, boolean requireAvailableSkillpoint) {
+               if (requireAvailableSkillpoint) {
+                       if (!hasAvailableSkillpoints()) return;
+                       --availableSkillIncreases;
+               }
                if (!skillLevels.containsKey(skillID)) skillLevels.put(skillID, 1);
                else skillLevels.put(skillID, skillLevels.get(skillID) + 1);
-               --availableSkillIncreases;
                ActorStatsController.recalculatePlayerCombatTraits(this);
        }
        public boolean nextLevelAddsNewSkillpoint() {
index e1e9fb2af6b86fa37f5227ac11d6db046a2d20a5..807c507353683491c424e24fc93b0d0f8f3eb218 100644 (file)
@@ -24,6 +24,14 @@ public final class Inventory extends ItemContainer {
        public boolean isEmptySlot(int slot) {\r
                return wear[slot] == null;\r
        }\r
+\r
+       public boolean isWearing(String itemTypeID) {\r
+               for(int i = 0; i < NUM_WORN_SLOTS; ++i) {\r
+                       if (wear[i] == null) continue;\r
+                       if (wear[i].id.equals(itemTypeID)) return true;\r
+               }\r
+               return false;\r
+       }\r
        \r
        \r
        // ====== PARCELABLE ===================================================================\r
index ef6245f3d2ca83ecc5ae77159a84ff15cd34fa42..06980dd3469947748db914ea4096985624809b5e 100644 (file)
@@ -4,6 +4,7 @@ import java.util.ArrayList;
 
 import com.gpl.rpg.AndorsTrail.conversation.Phrase;
 import com.gpl.rpg.AndorsTrail.conversation.Phrase.Reply;
+import com.gpl.rpg.AndorsTrail.conversation.Phrase.Reward;
 import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress;
 import com.gpl.rpg.AndorsTrail.resource.ResourceFileTokenizer;
 import com.gpl.rpg.AndorsTrail.resource.ResourceFileTokenizer.ResourceParserFor;
@@ -25,6 +26,7 @@ public final class ConversationListParser extends ResourceParserFor<Phrase> {
                                        , QuestProgress.parseQuestProgress(parts[2])            // requiresProgress
                                , ResourceParserUtils.parseNullableString(parts[3])     // requiresItemType
                                , ResourceParserUtils.parseInt(parts[4], 0)                     // requiresItemQuantity
+                               , Reply.ITEM_REQUIREMENT_TYPE_INVENTORY_REMOVE          // itemRequirementType
                                );
                }
        };
@@ -37,11 +39,17 @@ public final class ConversationListParser extends ResourceParserFor<Phrase> {
                replyResourceTokenizer.tokenizeArray(parts[4], replies, replyParser);
                final Reply[] _replies = replies.toArray(new Reply[replies.size()]);
                
+               final ArrayList<Reward> rewards = new ArrayList<Reward>();
+               QuestProgress questProgress = QuestProgress.parseQuestProgress(parts[2]);
+               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()]);
+               
                return new Pair<String, Phrase>(parts[0], new Phrase(
                                ResourceParserUtils.parseNullableString(parts[1])       // message
                        , _replies                                                                                      // replies
-                       , QuestProgress.parseQuestProgress(parts[2])            // questProgress
-                       , ResourceParserUtils.parseNullableString(parts[3])     // rewardDroplist
+                               , _rewards                                                                                      // rewards
                        ));
        }
 }