Added two new sub-blocks for Choice blocks

Added two new sub-blocks for Choice blocks: Require and Exclude.
The syntax for both is the same as Cost blocks.

Require defines what item must be present in your inventory in order to show this choice/reply.
Exclude defines what item must not be present in your inventory in order to show this choice/reply.

If any Require/Exclude blocks are defined then this choice/reply will be hidden until all blocks of both types are satisfied.
This commit is contained in:
FishyClockwork 2016-10-28 13:42:37 +02:00 committed by Christoph Oelckers
parent 87ea75169e
commit b1880964fa
4 changed files with 75 additions and 9 deletions

View File

@ -585,6 +585,8 @@ xx(Ifitem)
xx(Choice) xx(Choice)
xx(Link) xx(Link)
xx(Goodbye) xx(Goodbye)
xx(Require)
xx(Exclude)
// Special menus // Special menus
xx(Mainmenu) xx(Mainmenu)

View File

@ -516,6 +516,8 @@ static void ParseReplies (FStrifeDialogueReply **replyptr, Response *responses)
reply->ItemCheck[k].Item = dyn_cast<PClassInventory>(GetStrifeType(rsp->Item[k])); reply->ItemCheck[k].Item = dyn_cast<PClassInventory>(GetStrifeType(rsp->Item[k]));
reply->ItemCheck[k].Amount = rsp->Count[k]; reply->ItemCheck[k].Amount = rsp->Count[k];
} }
reply->ItemCheckRequire.Clear();
reply->ItemCheckExclude.Clear();
// If the first item check has a positive amount required, then // If the first item check has a positive amount required, then
// add that to the reply string. Otherwise, use the reply as-is. // add that to the reply string. Otherwise, use the reply as-is.
@ -656,6 +658,38 @@ CUSTOM_CVAR(Float, dlg_musicvolume, 1.0f, CVAR_ARCHIVE)
else if (self > 1.f) self = 1.f; else if (self > 1.f) self = 1.f;
} }
//============================================================================
//
// ShouldSkipReply
//
// Determines whether this reply should be skipped or not.
//
//============================================================================
static bool ShouldSkipReply(FStrifeDialogueReply *reply, player_t *player)
{
if (reply->Reply == nullptr)
return true;
int i;
for (i = 0; i < (int)reply->ItemCheckRequire.Size(); ++i)
{
if (!CheckStrifeItem(player, reply->ItemCheckRequire[i].Item, reply->ItemCheckRequire[i].Amount))
{
return true;
}
}
for (i = 0; i < (int)reply->ItemCheckExclude.Size(); ++i)
{
if (CheckStrifeItem(player, reply->ItemCheckExclude[i].Item, reply->ItemCheckExclude[i].Amount))
{
return true;
}
}
return false;
}
//============================================================================ //============================================================================
// //
// The conversation menu // The conversation menu
@ -673,6 +707,7 @@ class DConversationMenu : public DMenu
bool mShowGold; bool mShowGold;
FStrifeDialogueNode *mCurNode; FStrifeDialogueNode *mCurNode;
int mYpos; int mYpos;
player_t *mPlayer;
public: public:
static int mSelection; static int mSelection;
@ -683,9 +718,10 @@ public:
// //
//============================================================================= //=============================================================================
DConversationMenu(FStrifeDialogueNode *CurNode) DConversationMenu(FStrifeDialogueNode *CurNode, player_t *player)
{ {
mCurNode = CurNode; mCurNode = CurNode;
mPlayer = player;
mDialogueLines = NULL; mDialogueLines = NULL;
mShowGold = false; mShowGold = false;
@ -720,7 +756,7 @@ public:
int i,j; int i,j;
for (reply = CurNode->Children, i = 1; reply != NULL; reply = reply->Next) for (reply = CurNode->Children, i = 1; reply != NULL; reply = reply->Next)
{ {
if (reply->Reply == NULL) if (ShouldSkipReply(reply, mPlayer))
{ {
continue; continue;
} }
@ -778,6 +814,13 @@ public:
} }
ConversationMenuY = mYpos; ConversationMenuY = mYpos;
//ConversationMenu.indent = 50; //ConversationMenu.indent = 50;
// Because replies can be selectively hidden mResponses.Size() won't be consistent.
// So make sure mSelection doesn't exceed mResponses.Size(). [FishyClockwork]
if (mSelection >= (int)mResponses.Size())
{
mSelection = mResponses.Size() - 1;
}
} }
//============================================================================= //=============================================================================
@ -839,12 +882,24 @@ public:
} }
else else
{ {
// Send dialogue and reply numbers across the wire.
assert((unsigned)mCurNode->ThisNodeNum < StrifeDialogues.Size()); assert((unsigned)mCurNode->ThisNodeNum < StrifeDialogues.Size());
assert(StrifeDialogues[mCurNode->ThisNodeNum] == mCurNode); assert(StrifeDialogues[mCurNode->ThisNodeNum] == mCurNode);
// This is needed because mSelection represents the replies currently being displayed which will
// not match up with what's supposed to be selected if there are any hidden/skipped replies. [FishyClockwork]
FStrifeDialogueReply *reply = mCurNode->Children;
int replynum = mSelection;
for (int i = 0; i <= mSelection && reply != nullptr; reply = reply->Next)
{
if (ShouldSkipReply(reply, mPlayer))
replynum++;
else
i++;
}
// Send dialogue and reply numbers across the wire.
Net_WriteByte(DEM_CONVREPLY); Net_WriteByte(DEM_CONVREPLY);
Net_WriteWord(mCurNode->ThisNodeNum); Net_WriteWord(mCurNode->ThisNodeNum);
Net_WriteByte(mSelection); Net_WriteByte(replynum);
} }
Close(); Close();
return true; return true;
@ -1169,7 +1224,7 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang
S_Sound (npc, CHAN_VOICE|CHAN_NOPAUSE, CurNode->SpeakerVoice, 1, ATTN_NORM); S_Sound (npc, CHAN_VOICE|CHAN_NOPAUSE, CurNode->SpeakerVoice, 1, ATTN_NORM);
} }
DConversationMenu *cmenu = new DConversationMenu(CurNode); DConversationMenu *cmenu = new DConversationMenu(CurNode, pc->player);
if (CurNode != PrevNode) if (CurNode != PrevNode)

View File

@ -45,6 +45,8 @@ struct FStrifeDialogueReply
int ActionSpecial; int ActionSpecial;
int Args[5]; int Args[5];
TArray<FStrifeDialogueItemCheck> ItemCheck; TArray<FStrifeDialogueItemCheck> ItemCheck;
TArray<FStrifeDialogueItemCheck> ItemCheckRequire;
TArray<FStrifeDialogueItemCheck> ItemCheckExclude;
char *Reply; char *Reply;
char *QuickYes; char *QuickYes;
int NextNode; // index into StrifeDialogues int NextNode; // index into StrifeDialogues

View File

@ -76,11 +76,11 @@ class USDFParser : public UDMFParserBase
//=========================================================================== //===========================================================================
// //
// Parse a cost block // Parse a cost/require/exclude block
// //
//=========================================================================== //===========================================================================
bool ParseCost(FStrifeDialogueReply *response) bool ParseCostRequireExclude(FStrifeDialogueReply *response, FName type)
{ {
FStrifeDialogueItemCheck check; FStrifeDialogueItemCheck check;
check.Item = NULL; check.Item = NULL;
@ -101,7 +101,12 @@ class USDFParser : public UDMFParserBase
} }
} }
response->ItemCheck.Push(check); switch (type)
{
case NAME_Cost: response->ItemCheck.Push(check); break;
case NAME_Require: response->ItemCheckRequire.Push(check); break;
case NAME_Exclude: response->ItemCheckExclude.Push(check); break;
}
return true; return true;
} }
@ -206,7 +211,9 @@ class USDFParser : public UDMFParserBase
switch(key) switch(key)
{ {
case NAME_Cost: case NAME_Cost:
ParseCost(reply); case NAME_Require:
case NAME_Exclude:
ParseCostRequireExclude(reply, key);
break; break;
default: default: