- Consolidated all conversation reply handling into a single function executed on all

machines, so when an NPC need to show the "enough" response, it has enough
  information available to do so.
- Some new Strife Teaser fixes I forgot to commit are in here.
- Moved norawinput check into FindRawInputFunctions().


SVN r2120 (trunk)
This commit is contained in:
Randy Heit 2010-01-22 05:17:57 +00:00
commit 71b75f0d7a
9 changed files with 486 additions and 485 deletions

View file

@ -125,8 +125,6 @@ static void ConversationMenuEscaped ();
static FStrifeDialogueNode *CurNode, *PrevNode;
static FBrokenLines *DialogueLines;
static bool Conversation_TakeStuff;
#define NUM_RANDOM_LINES 10
#define NUM_RANDOM_GOODBYES 3
@ -282,7 +280,7 @@ static void LoadScriptFile(FileReader *lump, int numnodes)
{
node = ReadTeaserNode (lump, prevSpeakerType);
}
StrifeDialogues.Push (node);
node->ThisNodeNum = StrifeDialogues.Push(node);
}
}
@ -623,18 +621,23 @@ static void TakeStrifeItem (player_t *player, const PClass *itemtype, int amount
if (itemtype->IsDescendantOf (PClass::FindClass(NAME_QuestItem)))
return;
// Don't take keys
// Don't take keys.
if (itemtype->IsDescendantOf (RUNTIME_CLASS(AKey)))
return;
// Don't take the sigil
// Don't take the sigil.
if (itemtype == RUNTIME_CLASS(ASigil))
return;
Net_WriteByte (DEM_CONVERSATION);
Net_WriteByte (CONV_TAKEINVENTORY);
Net_WriteString (itemtype->TypeName.GetChars ());
Net_WriteWord (amount);
AInventory *item = player->mo->FindInventory (itemtype);
if (item != NULL)
{
item->Amount -= amount;
if (item->Amount <= 0)
{
item->Destroy ();
}
}
}
CUSTOM_CVAR(Float, dlg_musicvolume, 1.0f, CVAR_ARCHIVE)
@ -732,7 +735,7 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang
}
// Set up the menu
::CurNode = CurNode; // only set the global variaböle for the consoleplayer
::CurNode = CurNode; // only set the global variable for the consoleplayer
ConversationMenu.PreDraw = DrawConversationMenu;
ConversationMenu.EscapeHandler = ConversationMenuEscaped;
@ -743,10 +746,13 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang
FString dlgtext;
dlgtext.Format("TXT_%s_%02d", toSay, 1+(pr_randomspeech() % NUM_RANDOM_LINES));
toSay = GStrings[dlgtext.GetChars()];
if (toSay==NULL) toSay = "Go away!"; // Ok, it's lame - but it doesn't look like an error to the player. ;)
toSay = GStrings[dlgtext];
if (toSay == NULL)
{
toSay = "Go away!"; // Ok, it's lame - but it doesn't look like an error to the player. ;)
}
}
DialogueLines = V_BreakLines (SmallFont, screen->GetWidth()/CleanXfac-24*2, toSay);
DialogueLines = V_BreakLines (SmallFont, screen->GetWidth()/CleanXfac - 24*2, toSay);
// Fill out the possible choices
ShowGold = false;
@ -980,93 +986,155 @@ static bool DrawConversationMenu ()
//
// PickConversationReply
//
// Run only on the local machine with the conversation menu up.
//
//============================================================================
static void PickConversationReply ()
{
const char *replyText = NULL;
FStrifeDialogueReply *reply = (FStrifeDialogueReply *)ConversationItems[ConversationMenu.lastOn].c.extra;
int i;
player_t *cp = &players[consoleplayer];
FStrifeDialogueReply *replyscan;
int replynum = 0;
Conversation_TakeStuff = false;
assert(CurNode->ThisNodeNum >= 0 && CurNode->ThisNodeNum < 65536);
assert(StrifeDialogues[CurNode->ThisNodeNum] == CurNode);
M_ClearMenus ();
CleanupConversationMenu ();
// Determine reply number for netcode.
if (reply == NULL)
{
Net_WriteByte (DEM_CONVERSATION);
Net_WriteByte (CONV_NPCANGLE);
Net_WriteByte (DEM_CONVERSATION);
Net_WriteByte (CONV_CLOSE);
replyscan = NULL;
}
else
{
for (replyscan = CurNode->Children; replyscan != NULL && replyscan != reply; ++replynum, replyscan = replyscan->Next)
{ }
}
M_ClearMenus ();
if (replyscan == NULL)
{
Net_WriteByte(DEM_CONVCLOSE);
}
else
{
// Send dialogue and reply numbers across the wire.
assert(replynum < 256);
Net_WriteByte(DEM_CONVREPLY);
Net_WriteWord(CurNode->ThisNodeNum);
Net_WriteByte(replynum);
}
CleanupConversationMenu ();
}
//============================================================================
//
// HandleReply
//
// Run by the netcode on all machines.
//
//============================================================================
static void HandleReply(player_t *player, bool isconsole, int nodenum, int replynum)
{
const char *replyText = NULL;
FStrifeDialogueReply *reply;
FStrifeDialogueNode *node;
AActor *npc;
bool takestuff;
int i;
if (player->ConversationNPC == NULL || (unsigned)nodenum >= StrifeDialogues.Size())
{
return;
}
// Find the reply.
node = StrifeDialogues[nodenum];
for (i = 0, reply = node->Children; reply != NULL && i != replynum; ++i, reply = reply->Next)
{ }
if (reply == NULL)
{
return;
}
npc = player->ConversationNPC;
// Check if you have the requisite items for this choice
for (i = 0; i < 3; ++i)
{
if (!CheckStrifeItem (cp, reply->ItemCheck[i], reply->ItemCheckAmount[i]))
if (!CheckStrifeItem(player, reply->ItemCheck[i], reply->ItemCheckAmount[i]))
{
// No, you don't. Say so and let the NPC animate negatively.
if (reply->QuickNo)
if (reply->QuickNo && isconsole)
{
Printf ("%s\n", reply->QuickNo);
Printf("%s\n", reply->QuickNo);
}
Net_WriteByte (DEM_CONVERSATION);
Net_WriteByte (CONV_ANIMATE);
Net_WriteByte (2);
Net_WriteByte (DEM_CONVERSATION);
Net_WriteByte (CONV_NPCANGLE);
Net_WriteByte (DEM_CONVERSATION);
Net_WriteByte (CONV_CLOSE);
npc->ConversationAnimation(2);
npc->angle = player->ConversationNPCAngle;
npc->flags5 &= ~MF5_INCONVERSATION;
return;
}
}
// Yay, you do! Let the NPC animate affirmatively.
Net_WriteByte (DEM_CONVERSATION);
Net_WriteByte (CONV_ANIMATE);
Net_WriteByte (1);
npc->ConversationAnimation(1);
// If this reply gives you something, then try to receive it.
Conversation_TakeStuff = true;
takestuff = true;
if (reply->GiveType != NULL)
{
if (reply->GiveType->IsDescendantOf(RUNTIME_CLASS(AInventory)))
{
if (reply->GiveType->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
{
if (cp->mo->FindInventory(reply->GiveType) != NULL)
if (player->mo->FindInventory(reply->GiveType) != NULL)
{
Conversation_TakeStuff = false;
takestuff = false;
}
}
if (Conversation_TakeStuff)
if (takestuff)
{
Net_WriteByte (DEM_CONVERSATION);
Net_WriteByte (CONV_GIVEINVENTORY);
Net_WriteString (reply->GiveType->TypeName.GetChars ());
AInventory *item = static_cast<AInventory *>(Spawn(reply->GiveType, 0, 0, 0, NO_REPLACE));
// Items given here should not count as items!
if (item->flags & MF_COUNTITEM)
{
level.total_items--;
item->flags &= ~MF_COUNTITEM;
}
if (item->GetClass()->TypeName == NAME_FlameThrower)
{
// The flame thrower gives less ammo when given in a dialog
static_cast<AWeapon*>(item)->AmmoGive1 = 40;
}
item->flags |= MF_DROPPED;
if (!item->CallTryPickup(player->mo))
{
item->Destroy();
takestuff = false;
}
}
if (reply->GiveType->IsDescendantOf (RUNTIME_CLASS (ASlideshowStarter)))
if (reply->GiveType->IsDescendantOf(RUNTIME_CLASS(ASlideshowStarter)))
gameaction = ga_slideshow;
}
else
{
// Trying to give a non-inventory item.
Conversation_TakeStuff = false;
Printf("Attempting to give non-inventory item %s\n", reply->GiveType->TypeName.GetChars());
takestuff = false;
if (isconsole)
{
Printf("Attempting to give non-inventory item %s\n", reply->GiveType->TypeName.GetChars());
}
}
}
// Take away required items if the give was successful or none was needed.
if (Conversation_TakeStuff)
if (takestuff)
{
for (i = 0; i < 3; ++i)
{
TakeStrifeItem (&players[consoleplayer], reply->ItemCheck[i], reply->ItemCheckAmount[i]);
TakeStrifeItem (player, reply->ItemCheck[i], reply->ItemCheckAmount[i]);
}
replyText = reply->QuickYes;
}
@ -1078,12 +1146,12 @@ static void PickConversationReply ()
// Update the quest log, if needed.
if (reply->LogNumber != 0)
{
cp->SetLogNumber (reply->LogNumber);
player->SetLogNumber(reply->LogNumber);
}
if (replyText != NULL)
if (replyText != NULL && isconsole)
{
Printf ("%s\n", replyText);
Printf("%s\n", replyText);
}
// Does this reply alter the speaker's conversation node? If NextNode is positive,
@ -1091,39 +1159,44 @@ static void PickConversationReply ()
// will show the new node right away without terminating the dialogue.
if (reply->NextNode != 0)
{
int rootnode = FindNode (cp->ConversationNPC->GetDefault()->Conversation);
int rootnode = FindNode (npc->GetDefault()->Conversation);
if (reply->NextNode < 0)
{
cp->ConversationNPC->Conversation = StrifeDialogues[rootnode - reply->NextNode - 1];
npc->Conversation = StrifeDialogues[rootnode - reply->NextNode - 1];
if (gameaction != ga_slideshow)
{
P_StartConversation (cp->ConversationNPC, cp->mo, cp->ConversationFaceTalker, false);
P_StartConversation (npc, player->mo, player->ConversationFaceTalker, false);
return;
}
else
{
S_StopSound (cp->ConversationNPC, CHAN_VOICE);
S_StopSound (npc, CHAN_VOICE);
}
}
else
{
cp->ConversationNPC->Conversation = StrifeDialogues[rootnode + reply->NextNode - 1];
npc->Conversation = StrifeDialogues[rootnode + reply->NextNode - 1];
}
}
Net_WriteByte (DEM_CONVERSATION);
Net_WriteByte (CONV_NPCANGLE);
npc->angle = player->ConversationNPCAngle;
// [CW] Set these to NULL because we're not using to them
// anymore. However, this can interfere with slideshows
// so we don't set them to NULL in that case.
if (gameaction != ga_slideshow)
{
Net_WriteByte (DEM_CONVERSATION);
Net_WriteByte (CONV_SETNULL);
npc->flags5 &= ~MF5_INCONVERSATION;
player->ConversationFaceTalker = false;
player->ConversationNPC = NULL;
player->ConversationPC = NULL;
player->ConversationNPCAngle = 0;
}
I_SetMusicVolume (1.f);
if (isconsole)
{
I_SetMusicVolume (1.f);
}
}
//============================================================================
@ -1170,12 +1243,7 @@ void CleanupConversationMenu ()
void ConversationMenuEscaped ()
{
CleanupConversationMenu ();
Net_WriteByte (DEM_CONVERSATION);
Net_WriteByte (CONV_NPCANGLE);
Net_WriteByte (DEM_CONVERSATION);
Net_WriteByte (CONV_SETNULL);
Net_WriteByte (DEM_CONVNULL);
}
//============================================================================
@ -1186,77 +1254,30 @@ void ConversationMenuEscaped ()
//
//============================================================================
void P_ConversationCommand (int player, BYTE **stream)
void P_ConversationCommand (int netcode, int pnum, BYTE **stream)
{
int type = ReadByte (stream);
player_t *player = &players[pnum];
switch (type)
if (netcode == DEM_CONVREPLY)
{
case CONV_NPCANGLE:
players[player].ConversationNPC->angle = players[player].ConversationNPCAngle;
break;
case CONV_ANIMATE:
players[player].ConversationNPC->ConversationAnimation (ReadByte (stream));
break;
case CONV_GIVEINVENTORY:
int nodenum = ReadWord(stream);
int replynum = ReadByte(stream);
HandleReply(player, pnum == consoleplayer, nodenum, replynum);
}
else
{
assert(netcode == DEM_CONVNULL || netcode == DEM_CONVCLOSE);
if (player->ConversationNPC != NULL)
{
AInventory *item = static_cast<AInventory *> (Spawn (ReadString (stream), 0, 0, 0, NO_REPLACE));
// Items given here should not count as items!
if (item->flags & MF_COUNTITEM)
{
level.total_items--;
item->flags &= ~MF_COUNTITEM;
}
if (item->GetClass()->TypeName == NAME_FlameThrower)
{
// The flame thrower gives less ammo when given in a dialog
static_cast<AWeapon*>(item)->AmmoGive1 = 40;
}
item->flags |= MF_DROPPED;
if (!item->CallTryPickup (players[player].mo))
{
item->Destroy ();
Conversation_TakeStuff = false;
}
player->ConversationNPC->angle = player->ConversationNPCAngle;
player->ConversationNPC->flags5 &= ~MF5_INCONVERSATION;
}
break;
case CONV_TAKEINVENTORY:
if (netcode == DEM_CONVNULL)
{
AInventory *item = players[player].ConversationPC->FindInventory (PClass::FindClass (ReadString (stream)));
if (item != NULL)
{
item->Amount -= ReadWord (stream);
if (item->Amount <= 0)
{
item->Destroy ();
}
}
player->ConversationFaceTalker = false;
player->ConversationNPC = NULL;
player->ConversationPC = NULL;
player->ConversationNPCAngle = 0;
}
break;
case CONV_SETNULL:
if (players[player].ConversationNPC != NULL)
{
players[player].ConversationNPC->flags5 &= ~MF5_INCONVERSATION;
}
players[player].ConversationFaceTalker = false;
players[player].ConversationNPC = NULL;
players[player].ConversationPC = NULL;
players[player].ConversationNPCAngle = 0;
break;
case CONV_CLOSE:
if (players[player].ConversationNPC != NULL)
{
players[player].ConversationNPC->flags5 &= ~MF5_INCONVERSATION;
}
break;
default:
break;
}
}