From 71b75f0d7afcb6f29099ffce23a69731e7cb56b7 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 22 Jan 2010 05:17:57 +0000 Subject: [PATCH] - 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) --- src/d_iwad.cpp | 4 +- src/d_main.cpp | 5 +- src/d_net.cpp | 31 +- src/d_protocol.h | 7 +- src/p_conversation.cpp | 287 ++++++++-------- src/p_conversation.h | 14 +- src/version.h | 4 +- src/win32/i_input.cpp | 17 +- zdoom.vcproj | 746 ++++++++++++++++++++--------------------- 9 files changed, 558 insertions(+), 557 deletions(-) diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 3beb23fba0..3cf9773ce0 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -283,11 +283,11 @@ static EIWADType ScanIWAD (const char *iwad) } else if (lumpsfound[Check_invcurs]) { - return IWAD_StrifeTeaser2; + return IWAD_StrifeTeaser2; // Strife0.wad from 14 Mar 1996 } else { - return IWAD_StrifeTeaser; + return IWAD_StrifeTeaser; // Strife0.wad from 22 Feb 1996 } } else if (lumpsfound[Check_map01]) diff --git a/src/d_main.cpp b/src/d_main.cpp index 3de2bab7c4..534f30afe5 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1046,7 +1046,10 @@ void D_DoStrifeAdvanceDemo () pagetic = 7 * TICRATE; pagename = "PANEL1"; S_Sound (CHAN_VOICE | CHAN_UI, voices[0], 1, ATTN_NORM); - S_StartMusic ("d_intro"); + // The new Strife teaser has D_FMINTR. + // The full retail Strife has D_INTRO. + // And the old Strife teaser has both. (I do not know which one it actually uses, nor do I care.) + S_StartMusic (gameinfo.flags & GI_TEASER2 ? "d_fmintr" : "d_intro"); break; case 4: diff --git a/src/d_net.cpp b/src/d_net.cpp index cf30c58309..264aed1dfb 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2367,8 +2367,10 @@ void Net_DoCommand (int type, BYTE **stream, int player) } break; - case DEM_CONVERSATION: - P_ConversationCommand (player, stream); + case DEM_CONVREPLY: + case DEM_CONVCLOSE: + case DEM_CONVNULL: + P_ConversationCommand (type, player, stream); break; case DEM_SETSLOT: @@ -2500,29 +2502,8 @@ void Net_SkipCommand (int type, BYTE **stream) skip = 3 + *(*stream + 2) * 4; break; - case DEM_CONVERSATION: - { - t = **stream; - skip = 1; - - switch (t) - { - case CONV_ANIMATE: - skip += 1; - break; - - case CONV_GIVEINVENTORY: - skip += strlen ((char *)(*stream + skip)) + 1; - break; - - case CONV_TAKEINVENTORY: - skip += strlen ((char *)(*stream + skip)) + 3; - break; - - default: - break; - } - } + case DEM_CONVREPLY: + skip = 3; break; case DEM_SETSLOT: diff --git a/src/d_protocol.h b/src/d_protocol.h index eae1f4aa9f..a78c39ae25 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -147,14 +147,17 @@ enum EDemoCommand DEM_ADDCONTROLLER, // 48 Player to add to the controller list. DEM_DELCONTROLLER, // 49 Player to remove from the controller list. DEM_KILLCLASSCHEAT, // 50 String: Class to kill. - DEM_CONVERSATION, // 51 Make conversations work. + DEM_UNDONE11, // 51 DEM_SUMMON2, // 52 String: Thing to fabricate, WORD: angle offset DEM_SUMMONFRIEND2, // 53 DEM_SUMMONFOE2, // 54 DEM_ADDSLOTDEFAULT, // 55 DEM_ADDSLOT, // 56 DEM_SETSLOT, // 57 - DEM_SUMMONMBF, + DEM_SUMMONMBF, // 58 + DEM_CONVREPLY, // 59 Word: Dialogue node, Byte: Reply number + DEM_CONVCLOSE, // 60 + DEM_CONVNULL, // 61 }; // The following are implemented by cht_DoCheat in m_cheat.cpp diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 53667881c9..a2840f3552 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -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(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(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 (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(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; } } diff --git a/src/p_conversation.h b/src/p_conversation.h index a6da8a8b6a..13658e0f08 100644 --- a/src/p_conversation.h +++ b/src/p_conversation.h @@ -17,6 +17,7 @@ struct FStrifeDialogueNode ~FStrifeDialogueNode (); const PClass *DropType; const PClass *ItemCheck[3]; + int ThisNodeNum; // location of this node in StrifeDialogues int ItemCheckNode; // index into StrifeDialogues const PClass *SpeakerType; @@ -47,17 +48,6 @@ struct FStrifeDialogueReply FBrokenLines *ReplyLines; }; -// [CW] These are used to make conversations work. -enum -{ - CONV_NPCANGLE, - CONV_ANIMATE, - CONV_GIVEINVENTORY, - CONV_TAKEINVENTORY, - CONV_SETNULL, - CONV_CLOSE, -}; - extern TArray StrifeDialogues; // There were 344 types in Strife, and Strife conversations refer @@ -74,6 +64,6 @@ void P_FreeStrifeConversations (); void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveangle); void P_ResumeConversation (); -void P_ConversationCommand (int player, BYTE **stream); +void P_ConversationCommand (int netcode, int player, BYTE **stream); #endif diff --git a/src/version.h b/src/version.h index 80a8fd8618..769e8005cc 100644 --- a/src/version.h +++ b/src/version.h @@ -64,11 +64,11 @@ // Protocol version used in demos. // Bump it if you change existing DEM_ commands or add new ones. // Otherwise, it should be safe to leave it alone. -#define DEMOGAMEVERSION 0x212 +#define DEMOGAMEVERSION 0x213 // Minimum demo version we can play. // Bump it whenever you change or remove existing DEM_ commands. -#define MINDEMOVERSION 0x211 +#define MINDEMOVERSION 0x213 // SAVEVER is the version of the information stored in level snapshots. // Note that SAVEVER is not directly comparable to VERSION. diff --git a/src/win32/i_input.cpp b/src/win32/i_input.cpp index a40923d7bf..e9d2a26bbf 100644 --- a/src/win32/i_input.cpp +++ b/src/win32/i_input.cpp @@ -598,7 +598,7 @@ bool I_InitInput (void *hwnd) g_pdi = NULL; g_pdi3 = NULL; - if (!norawinput) FindRawInputFunctions(); + FindRawInputFunctions(); // Try for DirectInput 8 first, then DirectInput 3 for NT 4's benefit. DInputDLL = LoadLibrary("dinput8.dll"); @@ -938,13 +938,16 @@ bool FInputDevice::WndProcHook(HWND hWnd, UINT message, WPARAM wParam, LPARAM lP static void FindRawInputFunctions() { - HMODULE user32 = GetModuleHandle("user32.dll"); - - if (user32 == NULL) + if (!norawinput) { - return; // WTF kind of broken system are we running on? - } + HMODULE user32 = GetModuleHandle("user32.dll"); + + if (user32 == NULL) + { + return; // WTF kind of broken system are we running on? + } #define RIF(name,ret,args) \ - My##name = (name##Proto)GetProcAddress(user32, #name); + My##name = (name##Proto)GetProcAddress(user32, #name); #include "rawinput.h" + } } diff --git a/zdoom.vcproj b/zdoom.vcproj index 97a2f13788..793cce76c0 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - @@ -1872,6 +1864,14 @@ Outputs="$(IntDir)/$(InputName).obj" /> + + + @@ -2061,6 +2061,14 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -2071,14 +2079,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - + + + - - - + + + @@ -5363,14 +5371,6 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> - - - @@ -5649,7 +5649,7 @@ />