static void PrintSecretString(const char *string, bool thislevel) { const char *colstr = thislevel? TEXTCOLOR_YELLOW : TEXTCOLOR_CYAN; if (string != NULL) { if (*string == '$') { if (string[1] == 'S' || string[1] == 's') { auto secnum = strtoul(string+2, (char**)&string, 10); if (*string == ';') string++; if (thislevel && secnum < level.sectors.Size()) { if (level.sectors[secnum].isSecret()) colstr = TEXTCOLOR_RED; else if (level.sectors[secnum].wasSecret()) colstr = TEXTCOLOR_GREEN; else colstr = TEXTCOLOR_ORANGE; } } else if (string[1] == 'T' || string[1] == 't') { long tid = strtol(string+2, (char**)&string, 10); if (*string == ';') string++; FActorIterator it(tid); AActor *actor; bool foundone = false; if (thislevel) { while ((actor = it.Next())) { if (!actor->IsKindOf(PClass::FindClass("SecretTrigger"))) continue; foundone = true; break; } } if (foundone) colstr = TEXTCOLOR_RED; else colstr = TEXTCOLOR_GREEN; } } FBrokenLines *brok = V_BreakLines(ConFont, screen->GetWidth()*95/100, string); for (int k = 0; brok[k].Width >= 0; k++) { Printf("%s%s\n", colstr, brok[k].Text.GetChars()); } V_FreeBrokenLines(brok); } }
void FConsoleBuffer::FormatText(FFont *formatfont, int displaywidth) { if (formatfont != mLastFont || displaywidth != mLastDisplayWidth || mBufferWasCleared) { FreeBrokenText(); mBrokenConsoleText.Clear(); mBrokenStart.Clear(); mBrokenStart.Push(0); mBrokenLines.Clear(); mLastFont = formatfont; mLastDisplayWidth = displaywidth; mBufferWasCleared = false; } unsigned brokensize = mBrokenConsoleText.Size(); if (brokensize == mConsoleText.Size()) { // The last line got text appended. We have to wait until here to format it because // it is possible that during display new text will be added from the NetUpdate calls in the software version of DrawTextureV. if (mLastLineNeedsUpdate) { brokensize--; V_FreeBrokenLines(mBrokenConsoleText[brokensize]); mBrokenConsoleText.Resize(brokensize); } } mBrokenLines.Resize(mBrokenStart[brokensize]); mBrokenStart.Resize(brokensize); for (unsigned i = brokensize; i < mConsoleText.Size(); i++) { FBrokenLines *bl = V_BreakLines(formatfont, displaywidth, mConsoleText[i], true); mBrokenConsoleText.Push(bl); mBrokenStart.Push(mBrokenLines.Size()); while (bl->Width != -1) { mBrokenLines.Push(bl); bl++; } } mTextLines = mBrokenLines.Size(); mBrokenStart.Push(mTextLines); mLastLineNeedsUpdate = false; }
void P_StartConversation (AActor *npc, AActor *pc) { FStrifeDialogueReply *reply; menuitem_t item; const char *toSay; int i, j; pc->momx = pc->momy = 0; // Stop moving pc->player->momx = pc->player->momy = 0; if (pc->player - players != consoleplayer) return; ConversationPC = pc; ConversationNPC = npc; CurNode = npc->Conversation; if (pc->player == &players[consoleplayer]) { S_Sound (CHAN_VOICE, "misc/chat", 1, ATTN_NONE); } npc->reactiontime = 2; if (!(npc->flags & MF_FRIENDLY) && !(npc->flags4 & MF4_NOHATEPLAYERS)) { npc->target = pc; } ConversationNPCAngle = npc->angle; A_FaceTarget (npc); pc->angle = R_PointToAngle2 (pc->x, pc->y, npc->x, npc->y); // Check if we should jump to another node while (CurNode->ItemCheck[0] != NULL) { if (CheckStrifeItem (CurNode->ItemCheck[0]) && CheckStrifeItem (CurNode->ItemCheck[1]) && CheckStrifeItem (CurNode->ItemCheck[2])) { int root = FindNode (ConversationNPC->GetDefault()->Conversation); CurNode = StrifeDialogues[root + CurNode->ItemCheckNode - 1]; } else { break; } } if (CurNode->SpeakerVoice != 0) { S_SoundID (npc, CHAN_VOICE, CurNode->SpeakerVoice, 1, ATTN_NORM); } // Set up the menu ConversationMenu.PreDraw = DrawConversationMenu; ConversationMenu.EscapeHandler = CleanupConversationMenu; // Format the speaker's message. toSay = CurNode->Dialogue; if (strncmp (toSay, "RANDOM_", 7) == 0) { for (i = 0; i < NUM_RANDOM_TALKERS; ++i) { if (strcmp (RandomLines[i][0], toSay + 7) == 0) { toSay = RandomLines[i][1 + (pr_randomspeech() % NUM_RANDOM_LINES)]; break; } } } DialogueLines = V_BreakLines (screen->GetWidth()/CleanXfac-24*2, toSay); // Fill out the possible choices ShowGold = false; item.type = numberedmore; item.e.mfunc = PickConversationReply; for (reply = CurNode->Children, i = 1; reply != NULL; reply = reply->Next) { if (reply->Reply == NULL) { continue; } ShowGold |= reply->NeedsGold; reply->ReplyLines = V_BreakLines (320-50-10, reply->Reply); for (j = 0; reply->ReplyLines[j].width != -1; ++j) { item.label = reply->ReplyLines[j].string; item.b.position = j == 0 ? i : 0; item.c.extra = reply; ConversationItems.Push (item); } ++i; } item.label = RandomGoodbyes[pr_randomspeech() % NUM_RANDOM_GOODBYES]; item.b.position = i; item.c.extra = NULL; ConversationItems.Push (item); // Determine where the top of the reply list should be positioned. i = (gameinfo.gametype & GAME_Raven) ? 9 : 8; ConversationMenu.y = MIN<int> (140, 192 - ConversationItems.Size() * i); for (i = 0; DialogueLines[i].width != -1; ++i) { } i = 44 + i * 10; if (ConversationMenu.y - 100 < i - screen->GetHeight() / CleanYfac / 2) { ConversationMenu.y = i - screen->GetHeight() / CleanYfac / 2 + 100; } ConversationMenu.indent = 50; // Finish setting up the menu ConversationMenu.items = &ConversationItems[0]; ConversationMenu.numitems = ConversationItems.Size(); if (CurNode != PrevNode) { // Only reset the selection if showing a different menu. ConversationMenu.lastOn = 0; PrevNode = CurNode; } ConversationMenu.DontDim = true; // And open the menu M_StartControlPanel (false); OptionsActive = true; menuactive = MENU_OnNoPause; ConversationPauseTic = gametic + 20; M_SwitchMenu (&ConversationMenu); }
void DrawPopScreen (int bottom) { char buff[64]; const char *label; int i; AInventory *item; int xscale, yscale, left, top; int bars = (CurrentPop == POP_Status) ? imgINVPOP : imgINVPOP2; int back = (CurrentPop == POP_Status) ? imgINVPBAK : imgINVPBAK2; // Extrapolate the height of the popscreen for smoother movement int height = clamp<int> (PopHeight + FixedMul (r_TicFrac, PopHeightChange), -POP_HEIGHT, 0); xscale = CleanXfac; yscale = CleanYfac; left = screen->GetWidth()/2 - 160*CleanXfac; top = bottom + height * yscale; screen->DrawTexture (Images[back], left, top, DTA_CleanNoMove, true, DTA_Alpha, FRACUNIT*3/4, TAG_DONE); screen->DrawTexture (Images[bars], left, top, DTA_CleanNoMove, true, TAG_DONE); screen->SetFont (SmallFont2); switch (CurrentPop) { case POP_Log: // Draw the latest log message. sprintf (buff, "%02d:%02d:%02d", (level.time/TICRATE)/3600, ((level.time/TICRATE)%3600)/60, (level.time/TICRATE)%60); screen->DrawText (CR_UNTRANSLATED, left+210*xscale, top+8*yscale, buff, DTA_CleanNoMove, true, TAG_DONE); if (CPlayer->LogText != NULL) { brokenlines_t *lines = V_BreakLines (272, CPlayer->LogText); for (i = 0; lines[i].width >= 0; ++i) { screen->DrawText (CR_UNTRANSLATED, left+24*xscale, top+(18+i*12)*yscale, lines[i].string, DTA_CleanNoMove, true, TAG_DONE); } V_FreeBrokenLines (lines); } break; case POP_Keys: // List the keys the player has. int pos, endpos, leftcol; int clipleft, clipright; pos = KeyPopPos; endpos = pos + 10; leftcol = 20; clipleft = left + 17*xscale; clipright = left + (320-17)*xscale; if (KeyPopScroll > 0) { // Extrapolate the scroll position for smoother scrolling int scroll = MAX<int> (0,KeyPopScroll - FixedMul (r_TicFrac, 280/KEY_TIME)); pos -= 10; leftcol = leftcol - 280 + scroll; } for (i = 0, item = CPlayer->mo->Inventory; i < endpos && item != NULL; item = item->Inventory) { if (!item->IsKindOf (RUNTIME_CLASS(AKey))) continue; if (i < pos) { i++; continue; } label = item->GetClass()->Meta.GetMetaString (AMETA_StrifeName); if (label == NULL) { label = item->GetClass()->Name + 1; } int colnum = ((i-pos) / 5) & (KeyPopScroll > 0 ? 3 : 1); int rownum = (i % 5) * 18; screen->DrawTexture (TexMan(item->Icon), left + (colnum * 140 + leftcol)*xscale, top + (6 + rownum)*yscale, DTA_CleanNoMove, true, DTA_ClipLeft, clipleft, DTA_ClipRight, clipright, TAG_DONE); screen->DrawText (CR_UNTRANSLATED, left + (colnum * 140 + leftcol + 17)*xscale, top + (11 + rownum)*yscale, label, DTA_CleanNoMove, true, DTA_ClipLeft, clipleft, DTA_ClipRight, clipright, TAG_DONE); i++; } break; case POP_Status: // Show miscellaneous status items. // Print stats DrINumber2 (CPlayer->accuracy, left+268*xscale, top+28*yscale, 7*xscale, imgFONY0); DrINumber2 (CPlayer->stamina, left+268*xscale, top+52*yscale, 7*xscale, imgFONY0); // How many keys does the player have? for (i = 0, item = CPlayer->mo->Inventory; item != NULL; item = item->Inventory) { if (item->IsKindOf (RUNTIME_CLASS(AKey))) { i++; } } DrINumber2 (i, left+268*xscale, top+76*yscale, 7*xscale, imgFONY0); // Does the player have a communicator? item = CPlayer->mo->FindInventory (RUNTIME_CLASS(ACommunicator)); if (item != NULL) { screen->DrawTexture (TexMan(item->Icon), left + 280*xscale, top + 74*yscale, DTA_CleanNoMove, true, TAG_DONE); } // How much ammo does the player have? static const struct { const TypeInfo *AmmoType; int Y; } AmmoList[7] = { { RUNTIME_CLASS(AClipOfBullets), 19 }, { RUNTIME_CLASS(APoisonBolts), 35 }, { RUNTIME_CLASS(AElectricBolts), 43 }, { RUNTIME_CLASS(AHEGrenadeRounds), 59 }, { RUNTIME_CLASS(APhosphorusGrenadeRounds), 67 }, { RUNTIME_CLASS(AMiniMissiles), 75 }, { RUNTIME_CLASS(AEnergyPod), 83 } }; for (i = 0; i < 7; ++i) { item = CPlayer->mo->FindInventory (AmmoList[i].AmmoType); if (item == NULL) { DrINumber2 (0, left+206*xscale, top+AmmoList[i].Y*yscale, 7*xscale, imgFONY0); DrINumber2 (((AInventory *)GetDefaultByType (AmmoList[i].AmmoType))->MaxAmount, left+239*xscale, top+AmmoList[i].Y*yscale, 7*xscale, imgFONY0); } else { DrINumber2 (item->Amount, left+206*xscale, top+AmmoList[i].Y*yscale, 7*xscale, imgFONY0); DrINumber2 (item->MaxAmount, left+239*xscale, top+AmmoList[i].Y*yscale, 7*xscale, imgFONY0); } } // What weapons does the player have? static const struct { const char *TypeName; int X, Y; } WeaponList[6] = { { "StrifeCrossbow", 23, 19 }, { "AssaultGun", 21, 41 }, { "FlameThrower", 57, 50 }, { "MiniMissileLauncher", 20, 64 }, { "StrifeGrenadeLauncher", 55, 20 }, { "Mauler", 52, 75 }, }; for (i = 0; i < 6; ++i) { item = CPlayer->mo->FindInventory (TypeInfo::FindType (WeaponList[i].TypeName)); if (item != NULL) { screen->DrawTexture (TexMan(item->Icon), left + WeaponList[i].X*xscale, top + WeaponList[i].Y*yscale, DTA_CleanNoMove, true, DTA_LeftOffset, 0, DTA_TopOffset, 0, TAG_DONE); } } break; } screen->SetFont (SmallFont); }