Modify Reply quest- & item requirements into an array of requirements

This commit is contained in:
Oskar Wiksten
2013-07-15 18:36:05 +02:00
parent dfe7fde7e3
commit cf9b485971
9 changed files with 125 additions and 106 deletions

View File

@@ -7,6 +7,7 @@ import com.gpl.rpg.AndorsTrail.context.WorldContext;
import com.gpl.rpg.AndorsTrail.conversation.ConversationCollection;
import com.gpl.rpg.AndorsTrail.conversation.Phrase;
import com.gpl.rpg.AndorsTrail.conversation.Phrase.Reply;
import com.gpl.rpg.AndorsTrail.conversation.Phrase.Requirement;
import com.gpl.rpg.AndorsTrail.conversation.Phrase.Reward;
import com.gpl.rpg.AndorsTrail.model.ability.ActorCondition;
import com.gpl.rpg.AndorsTrail.model.ability.ActorConditionEffect;
@@ -119,40 +120,46 @@ public final class ConversationController {
}
private static void applyReplyEffect(final Player player, final Reply reply) {
if (!reply.requiresItem()) return;
if (reply.itemRequirementType == Reply.ITEM_REQUIREMENT_TYPE_INVENTORY_REMOVE) {
if (ItemTypeCollection.isGoldItemType(reply.requiresItemTypeID)) {
player.inventory.gold -= reply.requiresItemQuantity;
} else {
player.inventory.removeItem(reply.requiresItemTypeID, reply.requiresItemQuantity);
if (!reply.hasRequirements()) return;
for (Requirement requirement : reply.requires) {
if (requirement.requireType == Requirement.REQUIREMENT_TYPE_INVENTORY_REMOVE) {
if (ItemTypeCollection.isGoldItemType(requirement.requireID)) {
player.inventory.gold -= requirement.value;
} else {
player.inventory.removeItem(requirement.requireID, requirement.value);
}
}
}
}
private static boolean canSelectReply(final Player player, final Reply reply) {
if (!hasRequiredQuestProgress(player, reply.requiresProgress)) return false;
if (!hasRequiredItems(player, reply)) return false;
if (!reply.hasRequirements()) return true;
for (Requirement requirement : reply.requires) {
if (!playerSatisfiesRequirement(player, requirement)) return false;
}
return true;
}
private static boolean hasRequiredQuestProgress(final Player player, final QuestProgress progress) {
if (progress == null) return true;
return player.hasExactQuestProgress(progress);
private static boolean playerSatisfiesRequirement(final Player player, final Requirement requirement) {
switch (requirement.requireType) {
case Phrase.Requirement.REQUIREMENT_TYPE_QUEST_PROGRESS:
return player.hasExactQuestProgress(requirement.requireID, requirement.value);
case Phrase.Requirement.REQUIREMENT_TYPE_WEAR_KEEP:
return player.inventory.isWearing(requirement.requireID);
case Phrase.Requirement.REQUIREMENT_TYPE_INVENTORY_KEEP:
case Phrase.Requirement.REQUIREMENT_TYPE_INVENTORY_REMOVE:
if (ItemTypeCollection.isGoldItemType(requirement.requireID)) {
return player.inventory.gold >= requirement.value;
} else {
return player.inventory.hasItem(requirement.requireID, requirement.value);
}
default:
return true;
}
}
private static boolean hasRequiredItems(final Player player, Reply reply) {
if (!reply.requiresItem()) return true;
if (ItemTypeCollection.isGoldItemType(reply.requiresItemTypeID)) {
return player.inventory.gold >= reply.requiresItemQuantity;
} else if (reply.itemRequirementType == Reply.ITEM_REQUIREMENT_TYPE_WEAR_KEEP) {
return player.inventory.isWearing(reply.requiresItemTypeID);
} else {
return player.inventory.hasItem(reply.requiresItemTypeID, reply.requiresItemQuantity);
}
}
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) {

View File

@@ -17,30 +17,35 @@ public final class Phrase {
}
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;
if (requiresItemQuantity <= 0) return false;
return true;
public final Requirement[] requires;
public boolean hasRequirements() {
return requires != null;
}
public Reply(String text, String nextPhrase, QuestProgress requiresProgress, String requiresItemTypeID, int requiresItemQuantity, int itemRequirementType) {
public Reply(String text, String nextPhrase, Requirement[] requires) {
this.text = text;
this.nextPhrase = nextPhrase;
this.requiresProgress = requiresProgress;
this.requiresItemTypeID = requiresItemTypeID;
this.requiresItemQuantity = requiresItemQuantity;
this.itemRequirementType = itemRequirementType;
this.requires = requires;
}
}
public static final class Requirement {
public static final int REQUIREMENT_TYPE_QUEST_PROGRESS = 0;
public static final int REQUIREMENT_TYPE_INVENTORY_REMOVE = 1; // Player must have item(s) in inventory. Items will be removed when selecting reply.
public static final int REQUIREMENT_TYPE_INVENTORY_KEEP = 2; // Player must have item(s) in inventory. Items will NOT be removed when selecting reply.
public static final int REQUIREMENT_TYPE_WEAR_KEEP = 3; // Player must be wearing item(s). Items will NOT be removed when selecting reply.
public final int requireType;
public final String requireID;
public final int value;
public Requirement(int requireType, String requireID, int value) {
this.requireType = requireType;
this.requireID = requireID;
this.value = value;
}
}

View File

@@ -3,8 +3,8 @@ package com.gpl.rpg.AndorsTrail.resource.parsers;
import com.gpl.rpg.AndorsTrail.AndorsTrailApplication;
import com.gpl.rpg.AndorsTrail.conversation.Phrase;
import com.gpl.rpg.AndorsTrail.conversation.Phrase.Reply;
import com.gpl.rpg.AndorsTrail.conversation.Phrase.Requirement;
import com.gpl.rpg.AndorsTrail.conversation.Phrase.Reward;
import com.gpl.rpg.AndorsTrail.model.quest.QuestProgress;
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;
@@ -18,30 +18,24 @@ public final class ConversationListParser extends JsonCollectionParserFor<Phrase
private final TranslationLoader translationLoader;
private final JsonArrayParserFor<Requirement> requirementParser = new JsonArrayParserFor<Requirement>(Requirement.class) {
@Override
protected Requirement parseObject(JSONObject o) throws JSONException {
return new Requirement(
o.optInt(JsonFieldNames.ReplyRequires.requireType, Requirement.REQUIREMENT_TYPE_QUEST_PROGRESS)
,o.getString(JsonFieldNames.ReplyRequires.requireID)
,o.optInt(JsonFieldNames.ReplyRequires.value, 0)
);
}
};
private final JsonArrayParserFor<Reply> replyParser = new JsonArrayParserFor<Reply>(Reply.class) {
@Override
protected Reply parseObject(JSONObject o) throws JSONException {
JSONObject requires = o.optJSONObject(JsonFieldNames.Reply.requires);
String requiresProgress = null;
String requiresItemTypeID = null;
int requiresItemQuantity = 0;
int itemRequirementType = Reply.ITEM_REQUIREMENT_TYPE_INVENTORY_REMOVE;
if (requires != null) {
requiresProgress = requires.optString(JsonFieldNames.ReplyRequires.progress, null);
JSONObject requiresItem = requires.optJSONObject(JsonFieldNames.ReplyRequires.item);
if (requiresItem != null) {
requiresItemTypeID = requiresItem.getString(JsonFieldNames.ReplyRequiresItem.itemID);
requiresItemQuantity = requiresItem.getInt(JsonFieldNames.ReplyRequiresItem.quantity);
itemRequirementType = requiresItem.optInt(JsonFieldNames.ReplyRequiresItem.requireType, Reply.ITEM_REQUIREMENT_TYPE_INVENTORY_REMOVE);
}
}
return new Reply(
translationLoader.translateConversationReply(o.optString(JsonFieldNames.Reply.text, ""))
,o.getString(JsonFieldNames.Reply.nextPhraseID)
,QuestProgress.parseQuestProgress(requiresProgress)
,requiresItemTypeID
,requiresItemQuantity
,itemRequirementType
,requirementParser.parseArray(o.optJSONArray(JsonFieldNames.Reply.requires))
);
}
};

View File

@@ -72,14 +72,9 @@ public final class JsonFieldNames {
}
public static final class ReplyRequires {
public static final String progress = "progress";
public static final String item = "item";
}
public static final class ReplyRequiresItem {
public static final String itemID = "itemID";
public static final String quantity = "quantity";
public static final String requireType = "requireType";
public static final String requireID = "requireID";
public static final String value = "value";
}
public static final class PhraseReward {

View File

@@ -13,6 +13,13 @@ var ATEditor = (function(ATEditor, model, defaults, importExport) {
$scope.addReward = function(phrase) {
phrase.rewards.push({});
};
$scope.removeRequirement = function(reply, requirement) {
var idx = reply.requires.indexOf(requirement);
reply.requires.splice(idx, 1);
};
$scope.addRequirement = function(reply) {
reply.requires.push({});
};
$scope.proceedToPhrase = function(obj, prop) {
var phraseId = obj[prop];
if (phraseId) {

View File

@@ -44,7 +44,7 @@ var ATEditor = (function(ATEditor, _) {
,size: 0
}
,reply: {
requires: { item: { requireType: 0 } }
requires: []
}
};

View File

@@ -28,8 +28,10 @@ var ATEditor = (function(ATEditor, _) {
_.each(o.replies, function(reply) {
ATEditor.defaults.addDefaults('reply', reply);
if (reply.nextPhraseID && reply.nextPhraseID.length === 1) { reply.replyLeadsTo = reply.nextPhraseID; }
reply.requiresItems = ATEditor.utils.hasValues(reply.requires.item);
reply.requiresQuest = _.toBool(reply.requires.progress);
_.each(reply.requires, function(require) {
if (!require.requireType) { require.requireType = 0; }
});
reply.hasRequirements = ATEditor.utils.hasValues(reply.requires);
});
_.each(o.rewards, function(reward) {
if (!reward.rewardType) { reward.rewardType = 0; }
@@ -92,11 +94,8 @@ var ATEditor = (function(ATEditor, _) {
_.each(o.replies, function(reply) {
if (reply.replyLeadsTo) { reply.nextPhraseID = reply.replyLeadsTo; }
delete reply.replyLeadsTo;
var requires = reply.requires;
if (!reply.requiresItems) { delete requires.item; }
delete reply.requiresItems;
if (!reply.requiresQuest) { delete requires.progress; }
delete reply.requiresQuest;
if (!o.hasRequirements) { delete o.requires; }
delete reply.hasRequirements;
});
if (o.hasOnlyNextReply) {
o.replies = [ { text: "N", nextPhraseID: o.nextPhraseID } ];

View File

@@ -239,14 +239,20 @@ var ATEditor = (function(ATEditor, model, FieldList, _) {
nextPhraseID: obj.nextPhraseID
};
if (obj.requires_Progress) { result.requires = { progress: obj.requires_Progress }; }
if (obj.requires_Progress) {
result.requires = [];
result.requires.push({
requireType: 0,
requireID: obj.requires_Progress
});
}
if (obj.requires_itemID) {
result.requires = result.requires || {};
result.requires.item = {
itemID: obj.requires_itemID,
quantity: obj.requires_Quantity,
requireType: obj.requires_Type
};
result.requires = result.requires || [];
result.requires.push({
requireType: 1 + obj.requires_Type,
requireID: obj.requires_itemID,
value: obj.requires_Quantity
});
}
return result;

View File

@@ -122,30 +122,36 @@
</div>
</div>
<div class="fieldWithLabel">
<label class="checkbox"><input type="checkbox" id="requiresItems" ng-model="reply.requiresItems" />Player must have item(s) to select this reply</label>
<label class="checkbox"><input type="checkbox" id="hasRequirements" ng-model="reply.hasRequirements" />Player must fulfill requirements to select this reply</label>
</div>
<div class="fieldWithLabel" ng-ds-fade="reply.requiresItems">
<label for="requires_itemID">Required item ID</label>
<input type="text" size="30" id="requires_itemID" class="field at-input-id" ng-model="reply.requires.item.itemID" />
</div>
<div class="fieldWithLabel" ng-ds-fade="reply.requiresItems">
<label for="requires_Quantity">Required item quantity</label>
<input type="text" size="5" id="requires_Quantity" class="field at-input-quantity" ng-model="reply.requires.item.quantity" />
</div>
<div class="fieldWithLabel" ng-ds-fade="reply.requiresItems">
<label for="requires_Type">Player should have item in:</label>
<select class="field" id="requires_Type" ng-model="reply.requires.item.requireType">
<option value="0">Inventory &amp; item will be removed</option>
<option value="1">Inventory</option>
<option value="2">Worn equipment</option>
</select>
</div>
<div class="fieldWithLabel">
<label class="checkbox"><input type="checkbox" id="requiresQuest" ng-model="reply.requiresQuest" />Player must have progressed quest to select this reply</label>
</div>
<div class="fieldWithLabel" ng-ds-fade="reply.requiresQuest">
<label for="requires_Progress" class="hint hint--left" data-hint="For example, 'mikhail:20' would require that the quest mikhail is at at least stage 20.">Quest stage required:</label>
<input type="text" size="30" id="requires_Progress" class="field at-input-id" ng-model="reply.requires.progress" placeholder="questname:stage"/>
<div class="fieldWithLabel" ng-ds-fade="reply.hasRequirements">
<label for="rewards">Requirements</label>
<table class="field" id="requirements">
<thead><tr>
<th>Type</th>
<th><span class="hint hint--top" data-hint="Id of the item or quest to be required.">ID</span></th>
<th><span class="hint hint--left" data-hint="For item requirements: how many items to require. For quest progress: which quest stage to require.">
Value
</span></th>
<th></th>
</tr></thead>
<tbody>
<tr ng-repeat="require in reply.requires">
<td>
<select class="field" id="requireType" ng-model="require.requireType">
<option value="0">Quest progress</option>
<option value="1">Inventory &amp; item will be removed</option>
<option value="2">Inventory</option>
<option value="3">Worn equipment</option>
</select>
</td>
<td><input type="text" size="30" ng-model="require.requireID" id="requireID" class="at-input-id"/></td>
<td><input type="text" size="3" ng-model="require.value" class="at-input-quantity" /></td>
<td><a ng-click="removeRequirement(reply, require)" class="btn btn-mini" title="Remove row"><i class="icon-trash"></i></a></td>
</tr>
</tbody>
</table>
<button ng-click="addRequirement(reply)" class="btn" title="Add requirement"><i class="icon-plus-sign"></i> Add requirement</button>
</div>
</fieldset>