From 603e905c42ca9a95f30e0a3b21c24085fbddcf7a Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Thu, 31 Aug 2006 00:16:12 +0000 Subject: [PATCH] SVN r314 (trunk) --- docs/rh-log.txt | 20 ++++- src/c_console.cpp | 87 +++++++++++-------- src/d_player.h | 2 +- src/g_heretic/a_hereticweaps.cpp | 4 +- src/g_hexen/a_magelightning.cpp | 2 +- src/g_hexen/a_serpent.cpp | 2 +- src/g_raven/a_ravenambient.cpp | 4 +- src/g_shared/a_morph.cpp | 17 +--- src/g_shared/a_sharedglobal.h | 2 +- src/g_shared/hudmessages.cpp | 53 +++++------ src/g_shared/sbar.h | 2 +- src/g_strife/a_inquisitor.cpp | 2 +- src/g_strife/a_strifestuff.cpp | 2 +- src/g_strife/strife_sbar.cpp | 6 +- src/m_menu.cpp | 14 +-- src/name.cpp | 44 ++++++++++ src/name.h | 17 +++- src/namedef.h | 10 +++ src/p_conversation.cpp | 14 +-- src/p_conversation.h | 4 +- src/p_mobj.cpp | 2 +- src/p_user.cpp | 10 +-- src/s_advsound.cpp | 2 +- src/s_sound.cpp | 4 +- src/s_sound.h | 2 +- src/thingdef.cpp | 4 + src/thingdef_codeptr.cpp | 40 +++++++++ src/v_font.cpp | 7 +- src/v_font.h | 4 +- src/v_text.cpp | 145 ++++++++++++++++++------------- src/v_text.h | 16 ++-- src/v_video.h | 1 + src/wi_stuff.cpp | 10 +-- src/zstring.cpp | 8 ++ src/zstring.h | 1 + 35 files changed, 365 insertions(+), 199 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 136e31c346..33ed749cbd 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,21 @@ +August 30, 2006 +- Added the FNameNoInit class that is exactly like FName except it does not + initialize its index, so it can be used from inside Actors without + overwriting the runtime default value. +- V_BreakLines() now returns an array of FStrings instead of char *'s. +- Added support for custom text colors in messages like this: + print (s:"\c[Chartreuce]This text is in the color 'Bleargh'"); + This also obsoletes some of the functionality of the r: print specifier + before it was even saw a release version, because you can do this with the + standard colors too: + print (s:"\c[Green]Some text"); +- Added two new decorate functionns: A_PlaySoundEx("sound_name", "channel" + [, bLooping]) and A_StopSoundEx("channel"), where "channel" is "Auto", + "Weapon", "Voice", "Item", "Body", "SoundSlot5", "SoundSlot6", or + "SoundSlot7". +- Added a third parameter to S_IsActorPlayingSomething() to allow it to check + if the actor is playing a specific sound. + August 29, 2006 - Moved the text color definitions out of the executable and into an external data file. @@ -9,7 +27,7 @@ August 29, 2006 #RGB color strings. August 27, 2006 (Changes by Graf Zahl) -- fixed: callstatechain didn`t check for NULL code pointers +- fixed: callstatechain didn't check for NULL code pointers August 25, 2006 - Fixed: Multiple-choice sound sequences could not be assigned IDs for use diff --git a/src/c_console.cpp b/src/c_console.cpp index 591ce5e8cf..5534ce6017 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -165,9 +165,9 @@ CVAR (String, con_ctrl_d, "", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) static struct NotifyText { - int timeout; - int printlevel; - byte text[256]; + int TimeOut; + int PrintLevel; + FString Text; } NotifyStrings[NUMNOTIFIES]; static int NotifyTop, NotifyTopGoal; @@ -556,7 +556,7 @@ void C_AddNotifyString (int printlevel, const char *source) REPLACELINE } addtype = NEWLINE; - brokenlines_t *lines; + FBrokenLines *lines; int i, len, width; if ((printlevel != 128 && !show_messages) || @@ -573,11 +573,9 @@ void C_AddNotifyString (int printlevel, const char *source) width = con_scaletext > 1 ? DisplayWidth/2 : con_scaletext == 1 ? DisplayWidth / CleanXfac : DisplayWidth; - if (addtype == APPENDLINE && NotifyStrings[NUMNOTIFIES-1].printlevel == printlevel) + if (addtype == APPENDLINE && NotifyStrings[NUMNOTIFIES-1].PrintLevel == printlevel) { - FString str; - - str.Format("%s%s", NotifyStrings[NUMNOTIFIES-1].text, source); + FString str = NotifyStrings[NUMNOTIFIES-1].Text + source; lines = V_BreakLines (width, str); } else @@ -589,17 +587,23 @@ void C_AddNotifyString (int printlevel, const char *source) if (lines == NULL) return; - for (i = 0; lines[i].width != -1; i++) + for (i = 0; lines[i].Width >= 0; i++) { if (addtype == NEWLINE) - memmove (&NotifyStrings[0], &NotifyStrings[1], sizeof(struct NotifyText) * (NUMNOTIFIES-1)); - strcpy ((char *)NotifyStrings[NUMNOTIFIES-1].text, lines[i].string); - NotifyStrings[NUMNOTIFIES-1].timeout = gametic + (int)(con_notifytime * TICRATE); - NotifyStrings[NUMNOTIFIES-1].printlevel = printlevel; + { + for (int j = 0; j < NUMNOTIFIES-1; ++j) + { + NotifyStrings[j] = NotifyStrings[j+1]; + } + } + NotifyStrings[NUMNOTIFIES-1].Text = lines[i].Text; + NotifyStrings[NUMNOTIFIES-1].TimeOut = gametic + (int)(con_notifytime * TICRATE); + NotifyStrings[NUMNOTIFIES-1].PrintLevel = printlevel; addtype = NEWLINE; } V_FreeBrokenLines (lines); + lines = NULL; switch (source[len-1]) { @@ -662,7 +666,7 @@ void AddToConsole (int printlevel, const char *text) char *work_p; char *linestart; - int cc = CR_TAN; + FString cc = 'A' + CR_TAN; int size, len; int x; int maxwidth; @@ -738,8 +742,23 @@ void AddToConsole (int printlevel, const char *text) if (*work_p == TEXTCOLOR_ESCAPE) { work_p++; - if (*work_p) + if (*work_p == '[') + { + char *start = work_p; + while (*work_p != ']' && *work_p != '\0') + { + work_p++; + } + if (*work_p != '\0') + { + work_p++; + } + cc = FString(start, work_p - start); + } + else if (*work_p != '\0') + { cc = *work_p++; + } continue; } int w = ConFont->GetCharWidth (*work_p); @@ -757,9 +776,9 @@ void AddToConsole (int printlevel, const char *text) } if (*work_p) { - linestart = work_p - 2; + linestart = work_p - 1 - cc.Len(); linestart[0] = TEXTCOLOR_ESCAPE; - linestart[1] = cc; + strncpy (linestart + 1, cc, cc.Len()); } else { @@ -908,7 +927,7 @@ void C_FlushDisplay () int i; for (i = 0; i < NUMNOTIFIES; i++) - NotifyStrings[i].timeout = 0; + NotifyStrings[i].TimeOut = 0; } void C_AdjustBottom () @@ -996,13 +1015,13 @@ static void C_DrawNotifyText () for (i = 0; i < NUMNOTIFIES; i++) { - if (NotifyStrings[i].timeout == 0) + if (NotifyStrings[i].TimeOut == 0) continue; - j = NotifyStrings[i].timeout - gametic; + j = NotifyStrings[i].TimeOut - gametic; if (j > 0) { - if (!show_messages && NotifyStrings[i].printlevel != 128) + if (!show_messages && NotifyStrings[i].PrintLevel != 128) continue; fixed_t alpha; @@ -1016,45 +1035,45 @@ static void C_DrawNotifyText () alpha = OPAQUE; } - if (NotifyStrings[i].printlevel >= PRINTLEVELS) + if (NotifyStrings[i].PrintLevel >= PRINTLEVELS) color = CR_UNTRANSLATED; else - color = PrintColors[NotifyStrings[i].printlevel]; + color = PrintColors[NotifyStrings[i].PrintLevel]; if (con_scaletext == 1) { if (!center) - screen->DrawText (color, 0, line, (char *)NotifyStrings[i].text, - DTA_CleanNoMove, true, DTA_Alpha, alpha, TAG_DONE); + screen->DrawText (color, 0, line, NotifyStrings[i].Text, + DTA_CleanNoMove, true, DTA_Alpha, alpha, TAG_DONE); else screen->DrawText (color, (SCREENWIDTH - - SmallFont->StringWidth (NotifyStrings[i].text)*CleanXfac)/2, - line, (char *)NotifyStrings[i].text, DTA_CleanNoMove, true, + SmallFont->StringWidth (NotifyStrings[i].Text)*CleanXfac)/2, + line, NotifyStrings[i].Text, DTA_CleanNoMove, true, DTA_Alpha, alpha, TAG_DONE); } else if (con_scaletext == 0) { if (!center) - screen->DrawText (color, 0, line, (char *)NotifyStrings[i].text, + screen->DrawText (color, 0, line, NotifyStrings[i].Text, DTA_Alpha, alpha, TAG_DONE); else screen->DrawText (color, (SCREENWIDTH - - SmallFont->StringWidth (NotifyStrings[i].text))/2, - line, (char *)NotifyStrings[i].text, + SmallFont->StringWidth (NotifyStrings[i].Text))/2, + line, NotifyStrings[i].Text, DTA_Alpha, alpha, TAG_DONE); } else { if (!center) - screen->DrawText (color, 0, line, (char *)NotifyStrings[i].text, + screen->DrawText (color, 0, line, NotifyStrings[i].Text, DTA_VirtualWidth, screen->GetWidth() / 2, DTA_VirtualHeight, screen->GetHeight() / 2, DTA_KeepRatio, true, DTA_Alpha, alpha, TAG_DONE); else screen->DrawText (color, (screen->GetWidth() / 2 - - SmallFont->StringWidth (NotifyStrings[i].text))/2, - line, (char *)NotifyStrings[i].text, + SmallFont->StringWidth (NotifyStrings[i].Text))/2, + line, NotifyStrings[i].Text, DTA_VirtualWidth, screen->GetWidth() / 2, DTA_VirtualHeight, screen->GetHeight() / 2, DTA_KeepRatio, true, @@ -1071,7 +1090,7 @@ static void C_DrawNotifyText () line += lineadv; skip++; } - NotifyStrings[i].timeout = 0; + NotifyStrings[i].TimeOut = 0; } } if (canskip) diff --git a/src/d_player.h b/src/d_player.h index cfa3553261..0f11d68ce6 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -110,7 +110,7 @@ public: fixed_t SideMove1, SideMove2; int ScoreIcon; int SpawnMask; - int MorphWeapon; // actually a name + FNameNoInit MorphWeapon; int GetMaxHealth() const; }; diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index 64d350941f..c97d1b43d2 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -2534,7 +2534,7 @@ void A_SkullRodStorm (AActor *actor) mo->momz = -mo->Speed; mo->special2 = actor->special2; // Transfer player number P_CheckMissileSpawn (mo); - if (actor->special1 != -1 && !S_IsActorPlayingSomething (actor, CHAN_BODY)) + if (actor->special1 != -1 && !S_IsActorPlayingSomething (actor, CHAN_BODY, -1)) { S_LoopedSoundID (actor, CHAN_BODY, actor->special1, 1, ATTN_NORM); } @@ -2909,7 +2909,7 @@ void A_FirePhoenixPL2 (AActor *actor) mo->momx = pmo->momx + FixedMul (mo->Speed, finecosine[angle>>ANGLETOFINESHIFT]); mo->momy = pmo->momy + FixedMul (mo->Speed, finesine[angle>>ANGLETOFINESHIFT]); mo->momz = FixedMul (mo->Speed, slope); - if (!player->refire || !S_IsActorPlayingSomething (pmo, CHAN_WEAPON)) + if (!player->refire || !S_IsActorPlayingSomething (pmo, CHAN_WEAPON, -1)) { S_LoopedSoundID (pmo, CHAN_WEAPON, soundid, 1, ATTN_NORM); } diff --git a/src/g_hexen/a_magelightning.cpp b/src/g_hexen/a_magelightning.cpp index 44076cf85d..3548798862 100644 --- a/src/g_hexen/a_magelightning.cpp +++ b/src/g_hexen/a_magelightning.cpp @@ -138,7 +138,7 @@ int ALightning::SpecialMissileHit (AActor *thing) { P_DamageMobj(thing, this, target, 3, MOD_ELECTRIC); } - if (!(S_IsActorPlayingSomething (this, CHAN_WEAPON))) + if (!(S_IsActorPlayingSomething (this, CHAN_WEAPON, -1))) { S_Sound (this, CHAN_WEAPON, "MageLightningZap", 1, ATTN_NORM); } diff --git a/src/g_hexen/a_serpent.cpp b/src/g_hexen/a_serpent.cpp index 893c765a28..3b87067ab8 100644 --- a/src/g_hexen/a_serpent.cpp +++ b/src/g_hexen/a_serpent.cpp @@ -704,7 +704,7 @@ void A_SerpentHeadCheck (AActor *actor) void A_SerpentFXSound (AActor *actor) { - if (!S_IsActorPlayingSomething (actor, CHAN_BODY)) + if (!S_IsActorPlayingSomething (actor, CHAN_BODY, -1)) { S_LoopedSound (actor, CHAN_BODY, "SerpentFXContinuous", 1, ATTN_NORM); } diff --git a/src/g_raven/a_ravenambient.cpp b/src/g_raven/a_ravenambient.cpp index 6ae25e6b1d..dcb1f92c33 100644 --- a/src/g_raven/a_ravenambient.cpp +++ b/src/g_raven/a_ravenambient.cpp @@ -65,7 +65,7 @@ END_DEFAULTS void A_WindSound (AActor *self) { - if (!S_IsActorPlayingSomething (self, 6)) + if (!S_IsActorPlayingSomething (self, 6, -1)) { S_LoopedSound (self, 6, "world/wind", 1, ATTN_NORM); } @@ -79,7 +79,7 @@ void A_WindSound (AActor *self) void A_WaterfallSound (AActor *self) { - if (!S_IsActorPlayingSomething (self, 6)) + if (!S_IsActorPlayingSomething (self, 6, -1)) { S_LoopedSound (self, 6, "world/waterfall", 1, ATTN_NORM); } diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 0167694846..86386f7110 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -302,11 +302,11 @@ int AMorphProjectile::DoSpecialDamage (AActor *target, int damage) { if (target->player) { - P_MorphPlayer (target->player, PClass::FindClass (ENamedName(PlayerClass))); + P_MorphPlayer (target->player, PClass::FindClass (PlayerClass)); } else { - P_MorphMonster (target, PClass::FindClass (ENamedName(MonsterClass))); + P_MorphMonster (target, PClass::FindClass (MonsterClass)); } return -1; } @@ -314,18 +314,7 @@ int AMorphProjectile::DoSpecialDamage (AActor *target, int damage) void AMorphProjectile::Serialize (FArchive &arc) { Super::Serialize (arc); - - // Hack alert: The classes have to be serialized as names. - // But due to the way an actor is constructed they cannot - // be declared as names. - FName PlayerClassName = ENamedName(PlayerClass); - FName MonsterClassName = ENamedName(MonsterClass); - - arc << PlayerClassName << MonsterClassName; - - PlayerClass = PlayerClassName; - MonsterClass = MonsterClassName; - + arc << PlayerClass << MonsterClass; } diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index 5eaf78c81f..67d5dd4ff2 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -211,7 +211,7 @@ public: int DoSpecialDamage (AActor *target, int damage); void Serialize (FArchive &arc); - int PlayerClass, MonsterClass; // really FNames but they would be destroyed by the construction process + FNameNoInit PlayerClass, MonsterClass; }; class AMorphedMonster : public AActor diff --git a/src/g_shared/hudmessages.cpp b/src/g_shared/hudmessages.cpp index 78b5acdcd3..1173ad1e04 100644 --- a/src/g_shared/hudmessages.cpp +++ b/src/g_shared/hudmessages.cpp @@ -222,10 +222,10 @@ void DHUDMessage::ResetText (const char *text) if (Lines) { - for (; Lines[NumLines].width != -1; NumLines++) + for (; Lines[NumLines].Width >= 0; NumLines++) { Height += Font->GetHeight (); - Width = MAX (Width, Lines[NumLines].width); + Width = MAX (Width, Lines[NumLines].Width); } } @@ -360,7 +360,7 @@ void DHUDMessage::Draw (int bottom) { int drawx; - drawx = CenterX ? x - Lines[i].width*xscale/2 : x; + drawx = CenterX ? x - Lines[i].Width*xscale/2 : x; DoDraw (i, drawx, y, clean, hudheight); y += ystep; } @@ -390,13 +390,13 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight) { if (con_scaletext <= 1) { - screen->DrawText (TextColor, x, y, Lines[linenum].string, + screen->DrawText (TextColor, x, y, Lines[linenum].Text, DTA_CleanNoMove, clean, TAG_DONE); } else { - screen->DrawText (TextColor, x, y, Lines[linenum].string, + screen->DrawText (TextColor, x, y, Lines[linenum].Text, DTA_VirtualWidth, SCREENWIDTH/2, DTA_VirtualHeight, SCREENHEIGHT/2, DTA_KeepRatio, true, @@ -405,7 +405,7 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight) } else { - screen->DrawText (TextColor, x, y, Lines[linenum].string, + screen->DrawText (TextColor, x, y, Lines[linenum].Text, DTA_VirtualWidth, HUDWidth, DTA_VirtualHeight, hudheight, TAG_DONE); @@ -483,14 +483,14 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh { if (con_scaletext <= 1) { - screen->DrawText (TextColor, x, y, Lines[linenum].string, + screen->DrawText (TextColor, x, y, Lines[linenum].Text, DTA_CleanNoMove, clean, DTA_Alpha, trans, TAG_DONE); } else { - screen->DrawText (TextColor, x, y, Lines[linenum].string, + screen->DrawText (TextColor, x, y, Lines[linenum].Text, DTA_VirtualWidth, SCREENWIDTH/2, DTA_VirtualHeight, SCREENHEIGHT/2, DTA_Alpha, trans, @@ -500,7 +500,7 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh } else { - screen->DrawText (TextColor, x, y, Lines[linenum].string, + screen->DrawText (TextColor, x, y, Lines[linenum].Text, DTA_VirtualWidth, HUDWidth, DTA_VirtualHeight, hudheight, DTA_Alpha, trans, @@ -576,14 +576,14 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu { if (con_scaletext <= 1) { - screen->DrawText (TextColor, x, y, Lines[linenum].string, + screen->DrawText (TextColor, x, y, Lines[linenum].Text, DTA_CleanNoMove, clean, DTA_Alpha, trans, TAG_DONE); } else { - screen->DrawText (TextColor, x, y, Lines[linenum].string, + screen->DrawText (TextColor, x, y, Lines[linenum].Text, DTA_VirtualWidth, SCREENWIDTH/2, DTA_VirtualHeight, SCREENHEIGHT/2, DTA_Alpha, trans, @@ -593,7 +593,7 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu } else { - screen->DrawText (TextColor, x, y, Lines[linenum].string, + screen->DrawText (TextColor, x, y, Lines[linenum].Text, DTA_VirtualWidth, HUDWidth, DTA_VirtualHeight, hudheight, DTA_Alpha, trans, @@ -626,14 +626,7 @@ DHUDMessageTypeOnFadeOut::DHUDMessageTypeOnFadeOut (const char *text, float x, f if (TypeOnTime == 0.f) TypeOnTime = 0.1f; CurrLine = 0; - if (Lines[0].string != NULL) - { - LineLen = (int)strlen (Lines[0].string); - } - else - { - LineLen = 0; - } + LineLen = (int)Lines[0].Text.Len(); LineVisible = 0; State = 3; } @@ -674,7 +667,7 @@ bool DHUDMessageTypeOnFadeOut::Tick () } else { - LineLen = (int)strlen (Lines[CurrLine].string); + LineLen = (int)Lines[CurrLine].Text.Len(); } } } @@ -695,7 +688,7 @@ void DHUDMessageTypeOnFadeOut::ScreenSizeChanged () for (i = 0; i < CurrLine; ++i) { - charCount += (int)strlen (Lines[i].string); + charCount += (int)Lines[i].Text.Len(); } charCount += LineVisible; @@ -703,7 +696,7 @@ void DHUDMessageTypeOnFadeOut::ScreenSizeChanged () if (State == 3) { CurrLine = 0; - LineLen = (int)strlen (Lines[0].string); + LineLen = (int)Lines[0].Text.Len(); Tics = (int)(charCount * TypeOnTime) - 1; Tick (); } @@ -725,35 +718,33 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in } else if (linenum == CurrLine) { - char stop; - - stop = Lines[linenum].string[LineVisible]; - Lines[linenum].string[LineVisible] = 0; if (hudheight == 0) { if (con_scaletext <= 1) { - screen->DrawText (TextColor, x, y, Lines[linenum].string, + screen->DrawText (TextColor, x, y, Lines[linenum].Text, DTA_CleanNoMove, clean, + DTA_TextLen, LineVisible, TAG_DONE); } else { - screen->DrawText (TextColor, x, y, Lines[linenum].string, + screen->DrawText (TextColor, x, y, Lines[linenum].Text, DTA_VirtualWidth, SCREENWIDTH/2, DTA_VirtualHeight, SCREENHEIGHT/2, DTA_KeepRatio, true, + DTA_TextLen, LineVisible, TAG_DONE); } } else { - screen->DrawText (TextColor, x, y, Lines[linenum].string, + screen->DrawText (TextColor, x, y, Lines[linenum].Text, DTA_VirtualWidth, HUDWidth, DTA_VirtualHeight, hudheight, + DTA_TextLen, LineVisible, TAG_DONE); } - Lines[linenum].string[LineVisible] = stop; } } else diff --git a/src/g_shared/sbar.h b/src/g_shared/sbar.h index 5cec9ce6bb..4ab4c60a87 100644 --- a/src/g_shared/sbar.h +++ b/src/g_shared/sbar.h @@ -69,7 +69,7 @@ public: virtual void ScreenSizeChanged (); protected: - brokenlines_t *Lines; + FBrokenLines *Lines; int Width, Height, NumLines; float Left, Top; bool CenterX; diff --git a/src/g_strife/a_inquisitor.cpp b/src/g_strife/a_inquisitor.cpp index 8cc18a4a6c..77f07d0cf6 100644 --- a/src/g_strife/a_inquisitor.cpp +++ b/src/g_strife/a_inquisitor.cpp @@ -277,7 +277,7 @@ void A_InquisitorCheckLand (AActor *self) A_ShutUp (self); return; } - if (!S_IsActorPlayingSomething (self, CHAN_ITEM)) + if (!S_IsActorPlayingSomething (self, CHAN_ITEM, -1)) { S_LoopedSound (self, CHAN_ITEM, "inquisitor/jump", 1, ATTN_NORM); } diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index 92d731b89a..cb148c8ae7 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -806,7 +806,7 @@ void A_Countdown (AActor *self) void A_LoopActiveSound (AActor *self) { - if (self->ActiveSound != 0 && !S_IsActorPlayingSomething (self, CHAN_VOICE)) + if (self->ActiveSound != 0 && !S_IsActorPlayingSomething (self, CHAN_VOICE, -1)) { S_LoopedSoundID (self, CHAN_VOICE, self->ActiveSound, 1, ATTN_NORM); } diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp index 3d0b32fc08..ef52e5bdf2 100644 --- a/src/g_strife/strife_sbar.cpp +++ b/src/g_strife/strife_sbar.cpp @@ -584,11 +584,11 @@ private: if (CPlayer->LogText != NULL) { - brokenlines_t *lines = V_BreakLines (272, CPlayer->LogText); - for (i = 0; lines[i].width >= 0; ++i) + FBrokenLines *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); + lines[i].Text, DTA_CleanNoMove, true, TAG_DONE); } V_FreeBrokenLines (lines); } diff --git a/src/m_menu.cpp b/src/m_menu.cpp index e55d405e73..f2543f2dd1 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -230,7 +230,7 @@ static int PlayerTics; static int PlayerRotation; static DCanvas *SavePic; -static brokenlines_t *SaveComment; +static FBrokenLines *SaveComment; static List SaveGames; static FSaveGameNode *TopSaveGame; static FSaveGameNode *SelSaveGame; @@ -1079,10 +1079,10 @@ static void M_DrawSaveLoadCommon () // I'm not sure why SaveComment would go NULL in this loop, but I got // a crash report where it was NULL when i reached 1, so now I check // for that. - for (i = 0; SaveComment != NULL && SaveComment[i].width != -1 && i < 6; ++i) + for (i = 0; SaveComment != NULL && SaveComment[i].Width >= 0 && i < 6; ++i) { screen->DrawText (CR_GOLD, commentLeft, commentTop - + SmallFont->GetHeight()*i*CleanYfac, SaveComment[i].string, + + SmallFont->GetHeight()*i*CleanYfac, SaveComment[i].Text, DTA_CleanNoMove, true, TAG_DONE); } } @@ -3099,15 +3099,15 @@ void M_Drawer () BorderNeedRefresh = screen->GetPageCount (); SB_state = screen->GetPageCount (); - brokenlines_t *lines = V_BreakLines (320, messageString); + FBrokenLines *lines = V_BreakLines (320, messageString); y = 100; - for (i = 0; lines[i].width != -1; i++) + for (i = 0; lines[i].Width >= 0; i++) y -= screen->Font->GetHeight () / 2; - for (i = 0; lines[i].width != -1; i++) + for (i = 0; lines[i].Width >= 0; i++) { - screen->DrawText (CR_UNTRANSLATED, 160 - lines[i].width/2, y, lines[i].string, + screen->DrawText (CR_UNTRANSLATED, 160 - lines[i].Width/2, y, lines[i].Text, DTA_Clean, true, TAG_DONE); y += screen->Font->GetHeight (); } diff --git a/src/name.cpp b/src/name.cpp index 44d691eda2..db79902987 100644 --- a/src/name.cpp +++ b/src/name.cpp @@ -122,6 +122,50 @@ int FName::NameManager::FindName (const char *text, bool noCreate) return AddName (text, hash, bucket); } +//========================================================================== +// +// The same as above, but the text length is also passed, for creating +// a name from a substring. +// +//========================================================================== + +int FName::NameManager::FindName (const char *text, size_t textLen, bool noCreate) +{ + if (!Inited) + { + InitBuckets (); + } + + if (text == NULL) + { + return 0; + } + + unsigned int hash = MakeKey (text, textLen); + unsigned int bucket = hash % HASH_SIZE; + int scanner = Buckets[bucket]; + + // See if the name already exists. + while (scanner >= 0) + { + if (NameArray[scanner].Hash == hash && + strnicmp (NameArray[scanner].Text, text, textLen) == 0 && + NameArray[scanner].Text[textLen] == '\0') + { + return scanner; + } + scanner = NameArray[scanner].NextHash; + } + + // If we get here, then the name does not exist. + if (noCreate) + { + return 0; + } + + return AddName (text, hash, bucket); +} + //========================================================================== // // FName :: NameManager :: InitBuckets diff --git a/src/name.h b/src/name.h index 0763cf7814..6a32494190 100644 --- a/src/name.h +++ b/src/name.h @@ -49,6 +49,7 @@ public: FName () : Index(0) {} FName (const char *text) { Index = NameData.FindName (text, false); } FName (const char *text, bool noCreate) { Index = NameData.FindName (text, noCreate); } + FName (const char *text, size_t textlen, bool noCreate) { Index = NameData.FindName (text, textlen, noCreate); } FName (const FName &other) { Index = other.Index; } FName (ENamedName index) { Index = index; } // ~FName () {} // Names can be added but never removed. @@ -82,7 +83,7 @@ public: bool operator > (ENamedName index) const { return Index > index; } bool operator >= (ENamedName index) const { return Index >= index; } -private: +protected: int Index; struct NameEntry @@ -108,6 +109,7 @@ private: int Buckets[HASH_SIZE]; int FindName (const char *text, bool noCreate); + int FindName (const char *text, size_t textlen, bool noCreate); int AddName (const char *text, unsigned int hash, unsigned int bucket); NameBlock *AddBlock (size_t len); void InitBuckets (); @@ -115,6 +117,19 @@ private: }; static NameManager NameData; + + enum EDummy { NoInit }; + FName (EDummy) {} +}; + +class FNameNoInit : public FName +{ +public: + FNameNoInit() : FName(NoInit) {} + + FName &operator = (const char *text) { Index = NameData.FindName (text, false); return *this; } + FName &operator = (const FName &other) { Index = int(other); return *this; } + FName &operator = (ENamedName index) { Index = index; return *this; } }; #endif diff --git a/src/namedef.h b/src/namedef.h index d3796fd9aa..cfde2d6e79 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -6,6 +6,16 @@ xx(Object) xx(Untranslated) +// Per-actor sound channels +xx(Auto) +xx(Weapon) +xx(Voice) +xx(Item) +xx(Body) +xx(SoundSlot5) +xx(SoundSlot6) +xx(SoundSlot7) + // Hexen sound sequence names xx(Platform) xx(PlatformMetal) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 55f887e700..5ef5bc2388 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -82,7 +82,7 @@ static void CleanupConversationMenu (); static void ConversationMenuEscaped (); static FStrifeDialogueNode *CurNode, *PrevNode; -static brokenlines_t *DialogueLines; +static FBrokenLines *DialogueLines; static AActor *ConversationNPC, *ConversationPC; static angle_t ConversationNPCAngle; static bool ConversationFaceTalker; @@ -695,9 +695,9 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang } ShowGold |= reply->NeedsGold; reply->ReplyLines = V_BreakLines (320-50-10, reply->Reply); - for (j = 0; reply->ReplyLines[j].width != -1; ++j) + for (j = 0; reply->ReplyLines[j].Width >= 0; ++j) { - item.label = reply->ReplyLines[j].string; + item.label = reply->ReplyLines[j].Text.LockBuffer(); item.b.position = j == 0 ? i : 0; item.c.extra = reply; ConversationItems.Push (item); @@ -715,7 +715,7 @@ void P_StartConversation (AActor *npc, AActor *pc, bool facetalker, bool saveang // Determine where the top of the reply list should be positioned. i = (gameinfo.gametype & GAME_Raven) ? 9 : 8; ConversationMenu.y = MIN (140, 192 - ConversationItems.Size() * i); - for (i = 0; DialogueLines[i].width != -1; ++i) + for (i = 0; DialogueLines[i].Width >= 0; ++i) { } i = 44 + i * 10; if (ConversationMenu.y - 100 < i - screen->GetHeight() / CleanYfac / 2) @@ -808,7 +808,7 @@ static void DrawConversationMenu () // Dim the screen behind the dialogue (but only if there is no backdrop). if (CurNode->Backdrop <= 0) { - for (i = 0; DialogueLines[i].width != -1; ++i) + for (i = 0; DialogueLines[i].Width >= 0; ++i) { } screen->Dim (0, 0.45f, 14 * screen->GetWidth() / 320, 13 * screen->GetHeight() / 200, 308 * screen->GetWidth() / 320 - 14 * screen->GetWidth () / 320, @@ -830,9 +830,9 @@ static void DrawConversationMenu () y += linesize * 3 / 2; } x = 24 * screen->GetWidth() / 320; - for (i = 0; DialogueLines[i].width >= 0; ++i) + for (i = 0; DialogueLines[i].Width >= 0; ++i) { - screen->DrawText (CR_UNTRANSLATED, x, y, DialogueLines[i].string, + screen->DrawText (CR_UNTRANSLATED, x, y, DialogueLines[i].Text, DTA_CleanNoMove, true, TAG_DONE); y += linesize; } diff --git a/src/p_conversation.h b/src/p_conversation.h index 09ee2dc4b5..8ee35c2796 100644 --- a/src/p_conversation.h +++ b/src/p_conversation.h @@ -10,7 +10,7 @@ struct FStrifeDialogueReply; class FTexture; -struct brokenlines_t; +struct FBrokenLines; // FStrifeDialogueNode holds text an NPC says to the player struct FStrifeDialogueNode @@ -45,7 +45,7 @@ struct FStrifeDialogueReply char *QuickNo; bool NeedsGold; - brokenlines_t *ReplyLines; + FBrokenLines *ReplyLines; }; extern TArray StrifeDialogues; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 83ed0850a6..c1eb165344 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2391,7 +2391,7 @@ bool AActor::AdjustReflectionAngle (AActor *thing, angle_t &angle) void AActor::PlayActiveSound () { - if (ActiveSound && !S_IsActorPlayingSomething (this, CHAN_VOICE)) + if (ActiveSound && !S_IsActorPlayingSomething (this, CHAN_VOICE, -1)) { S_SoundID (this, CHAN_VOICE, ActiveSound, 1, (flags3 & MF3_FULLVOLACTIVE) ? ATTN_NONE : ATTN_IDLE); diff --git a/src/p_user.cpp b/src/p_user.cpp index 112c7c5929..8dd8e16228 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -400,12 +400,8 @@ void APlayerPawn::Serialize (FArchive &arc) << SideMove2 << ScoreIcon << InvFirst - << InvSel; - - // Serialize the name, not the index - FName MorphWeaponName = ENamedName(MorphWeapon); - arc << MorphWeaponName; - MorphWeapon = MorphWeaponName; + << InvSel + << MorphWeapon; } //=========================================================================== @@ -917,7 +913,7 @@ void APlayerPawn::MorphPlayerThink () void APlayerPawn::ActivateMorphWeapon () { - const PClass *morphweapon = PClass::FindClass (ENamedName(MorphWeapon)); + const PClass *morphweapon = PClass::FindClass (MorphWeapon); player->PendingWeapon = WP_NOCHANGE; player->psprites[ps_weapon].sy = WEAPONTOP; diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index da6639de21..c6b9cf7c8b 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -1584,7 +1584,7 @@ void AAmbientSound::Tick () if ((ambient->type & CONTINUOUS) == CONTINUOUS) { - if (S_IsActorPlayingSomething (this, CHAN_BODY)) + if (S_IsActorPlayingSomething (this, CHAN_BODY, -1)) return; if (ambient->sound[0]) diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 1cb1abc883..81630ba2f0 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1195,7 +1195,7 @@ bool S_GetSoundPlayingInfo (AActor *ent, int sound_id) // //========================================================================== -bool S_IsActorPlayingSomething (AActor *actor, int channel) +bool S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id) { int i; @@ -1210,7 +1210,7 @@ bool S_IsActorPlayingSomething (AActor *actor, int channel) { if (channel == 0 || Channel[i].entchannel == channel) { - return true; + return sound_id < 0 || Channel[i].sound_id == sound_id; } } } diff --git a/src/s_sound.h b/src/s_sound.h index ccc68379fc..22a899b5b5 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -150,7 +150,7 @@ void S_StopAllChannels (void); // Is the sound playing on one of the entity's channels? bool S_GetSoundPlayingInfo (AActor *ent, int sound_id); bool S_GetSoundPlayingInfo (fixed_t *pt, int sound_id); -bool S_IsActorPlayingSomething (AActor *actor, int channel); +bool S_IsActorPlayingSomething (AActor *actor, int channel, int sound_id); // Moves all sounds from one mobj to another void S_RelinkSound (AActor *from, AActor *to); diff --git a/src/thingdef.cpp b/src/thingdef.cpp index 9e092c870d..55fea1e6ff 100644 --- a/src/thingdef.cpp +++ b/src/thingdef.cpp @@ -451,6 +451,8 @@ ACTOR(PlayWeaponSound) ACTOR(FLoopActiveSound) ACTOR(LoopActiveSound) ACTOR(StopSound) +ACTOR(PlaySoundEx) +ACTOR(StopSoundEx) ACTOR(SeekerMissile) ACTOR(Jump) ACTOR(ExplodeParms) @@ -668,6 +670,8 @@ AFuncDesc AFTable[]= FUNC(A_FLoopActiveSound, NULL ) FUNC(A_LoopActiveSound, NULL ) FUNC(A_StopSound, NULL ) + FUNC(A_PlaySoundEx, "STi" ) + FUNC(A_StopSoundEx, "T" ) FUNC(A_SeekerMissile, "XX" ) FUNC(A_Jump, "XL" ) FUNC(A_CustomMissile, "MXXxxx" ) diff --git a/src/thingdef_codeptr.cpp b/src/thingdef_codeptr.cpp index 36fbbdca37..d6dcdb885b 100644 --- a/src/thingdef_codeptr.cpp +++ b/src/thingdef_codeptr.cpp @@ -287,6 +287,46 @@ void A_StopSound(AActor * self) S_StopSound(self, CHAN_VOICE); } +void A_PlaySoundEx (AActor *self) +{ + int index = CheckIndex(3); + if (index < 0) return; + + int soundid = StateParameters[index]; + ENamedName channel = ENamedName(StateParameters[index + 1]); + BOOL looping = StateParameters[index + 2]; + + if (channel < NAME_Auto || channel > NAME_SoundSlot7) + { + channel = NAME_Auto; + } + + if (!looping) + { + S_SoundID (self, channel - NAME_Auto, soundid, 1, ATTN_NORM); + } + else + { + if (!S_IsActorPlayingSomething (self, channel - NAME_Auto, soundid)) + { + S_LoopedSoundID (self, channel - NAME_Auto, soundid, 1, ATTN_NORM); + } + } +} + +void A_StopSoundEx (AActor *self) +{ + int index = CheckIndex (1); + if (index < 0) return; + + ENamedName channel = ENamedName(StateParameters[index]); + + if (channel > NAME_Auto && channel <= NAME_SoundSlot7) + { + S_StopSound (self, channel - NAME_Auto); + } +} + //========================================================================== // // Generic seeker missile function diff --git a/src/v_font.cpp b/src/v_font.cpp index ea116569e1..3c15486f92 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -123,6 +123,7 @@ static int STACK_ARGS TranslationMapCompare (const void *a, const void *b); // PUBLIC DATA DEFINITIONS ------------------------------------------------- FFont *FFont::FirstFont = NULL; +int NumTextColors; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -148,7 +149,6 @@ static const byte myislower[256] = static TArray TranslationParms[2]; static TArray TranslationLookup; -static int NumTextColors; // CODE -------------------------------------------------------------------- @@ -1788,10 +1788,9 @@ static int STACK_ARGS TranslationMapCompare (const void *a, const void *b) // //========================================================================== -EColorRange V_FindFontColor (const char *daname) +EColorRange V_FindFontColor (FName name) { - FName name(daname, true); - unsigned int min = 0, max = TranslationLookup.Size() - 1; + int min = 0, max = TranslationLookup.Size() - 1; while (min <= max) { diff --git a/src/v_font.h b/src/v_font.h index 5d8ec74727..f41dca493f 100644 --- a/src/v_font.h +++ b/src/v_font.h @@ -67,6 +67,8 @@ enum EColorRange NUM_TEXT_COLORS }; +extern int NumTextColors; + inline FArchive &operator<< (FArchive &arc, EColorRange &i) { BYTE val = (BYTE)i; @@ -149,6 +151,6 @@ extern FFont *SmallFont, *SmallFont2, *BigFont, *ConFont; void V_InitCustomFonts (); void V_InitFontColors (); -EColorRange V_FindFontColor (const char *name); +EColorRange V_FindFontColor (FName name); #endif //__V_FONT_H__ diff --git a/src/v_text.cpp b/src/v_text.cpp index 7ac65d5ec3..528b7a7090 100644 --- a/src/v_text.cpp +++ b/src/v_text.cpp @@ -62,7 +62,7 @@ void STACK_ARGS DCanvas::DrawChar (int normalcolor, int x, int y, byte character if (Font == NULL) return; - if (normalcolor >= NUM_TEXT_COLORS) + if (normalcolor >= NumTextColors) normalcolor = CR_UNTRANSLATED; FTexture *pic; @@ -89,6 +89,7 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st DWORD tag; BOOL boolval; + int maxstrlen = INT_MAX; int w, maxwidth; const byte *ch; int c; @@ -104,9 +105,9 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st if (Font == NULL || string == NULL) return; - if (normalcolor >= NUM_TEXT_COLORS) + if (normalcolor >= NumTextColors) normalcolor = CR_UNTRANSLATED; - boldcolor = normalcolor ? normalcolor - 1 : NUM_TEXT_COLORS - 1; + boldcolor = normalcolor ? normalcolor - 1 : NumTextColors - 1; range = Font->GetColorTranslation ((EColorRange)normalcolor); height = Font->GetHeight () + 1; @@ -181,13 +182,17 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st maxwidth = va_arg (tags, int); scalex = scaley = 1; break; + + case DTA_TextLen: + maxstrlen = va_arg (tags, int); + break; } tag = va_arg (tags, DWORD); } height *= scaley; - for (;;) + while ((const char *)ch - string < maxstrlen) { c = *ch++; if (!c) @@ -195,25 +200,43 @@ void STACK_ARGS DCanvas::DrawText (int normalcolor, int x, int y, const char *st if (c == TEXTCOLOR_ESCAPE) { - int newcolor = toupper(*ch++); + int newcolor = *ch++; - if (newcolor == 0) + if (newcolor == '\0') { return; } - else if (newcolor == '-') + else if (newcolor == '-') // Normal { newcolor = normalcolor; } - else if (newcolor >= 'A' && newcolor < NUM_TEXT_COLORS + 'A') - { - newcolor -= 'A'; - } - else if (newcolor == '+') + else if (newcolor == '+') // Bold { newcolor = boldcolor; } - else + else if (newcolor == '[') // Named + { + const byte *namestart = ch; + while (*ch != ']' && *ch != '\0') + { + ch++; + } + FName rangename((const char *)namestart, int(ch - namestart), true); + if (*ch != '\0') + { + ch++; + } + newcolor = V_FindFontColor (rangename); + } + else if (newcolor >= 'A' && newcolor < NUM_TEXT_COLORS + 'A') // Standard, uppercase + { + newcolor -= 'A'; + } + else if (newcolor >= 'a' && newcolor < NUM_TEXT_COLORS + 'a') // Standard, lowercase + { + newcolor -= 'a'; + } + else // Incomplete! { continue; } @@ -251,8 +274,18 @@ int FFont::StringWidth (const BYTE *string) const { if (*string == TEXTCOLOR_ESCAPE) { - if (*(++string)) + ++string; + if (*string == '[') + { + while (*string != '\0' && *string != ']') + { + ++string; + } + } + else if (*string != '\0') + { ++string; + } continue; } else if (*string == '\n') @@ -274,10 +307,8 @@ int FFont::StringWidth (const BYTE *string) const // // Break long lines of text into multiple lines no longer than maxwidth pixels // -static void breakit (brokenlines_t *line, const byte *start, const byte *string, bool keepspace, char linecolor) +static void breakit (FBrokenLines *line, const byte *start, const byte *string, bool keepspace, FString &linecolor) { - int extra; - // Leave out trailing white space if (!keepspace) { @@ -285,34 +316,23 @@ static void breakit (brokenlines_t *line, const byte *start, const byte *string, string--; } - if (linecolor == 0) + if (!linecolor.IsEmpty()) { - extra = 0; + line->Text = TEXTCOLOR_ESCAPE; + line->Text += linecolor; } - else - { - extra = 2; - } - - line->string = new char[string - start + extra + 1]; - if (linecolor) - { - line->string[0] = TEXTCOLOR_ESCAPE; - line->string[1] = linecolor; - } - strncpy (line->string + extra, (char *)start, string - start); - line->string[string - start + extra] = 0; - line->width = screen->Font->StringWidth (line->string); + line->Text.AppendCStrPart ((const char *)start, string - start); + line->Width = screen->Font->StringWidth (line->Text); } -brokenlines_t *V_BreakLines (int maxwidth, const byte *string, bool keepspace) +FBrokenLines *V_BreakLines (int maxwidth, const byte *string, bool keepspace) { - brokenlines_t lines[128]; // Support up to 128 lines (should be plenty) + FBrokenLines lines[128]; // Support up to 128 lines (should be plenty) const byte *space = NULL, *start = string; int i, c, w, nw; - char lastcolor = 0, linecolor = 0; - BOOL lastWasSpace = false; + FString lastcolor, linecolor; + bool lastWasSpace = false; int kerning = screen->Font->GetDefaultKerning (); i = w = 0; @@ -323,7 +343,23 @@ brokenlines_t *V_BreakLines (int maxwidth, const byte *string, bool keepspace) { if (*string) { - lastcolor = *string++; + if (*string == '[') + { + const byte *start = string; + while (*string != ']' && *string != '\0') + { + string++; + } + if (*string != '\0') + { + string++; + } + lastcolor = FString((const char *)start, string - start); + } + else + { + lastcolor = *string++; + } } continue; } @@ -348,11 +384,12 @@ brokenlines_t *V_BreakLines (int maxwidth, const byte *string, bool keepspace) if (!space) space = string - 1; - lines[i].nlterminated = (c == '\n'); + lines[i].NLTerminated = (c == '\n'); breakit (&lines[i], start, space, keepspace, linecolor); if (c == '\n') { - linecolor = lastcolor = 0; + // Why did I do it like this? Why? Oh why? + linecolor = lastcolor = ""; } else { @@ -388,7 +425,7 @@ brokenlines_t *V_BreakLines (int maxwidth, const byte *string, bool keepspace) { if (keepspace || !isspace (*s)) { - lines[i].nlterminated = (*s == '\n'); + lines[i].NLTerminated = (*s == '\n'); s++; breakit (&lines[i++], start, string, keepspace, linecolor); break; @@ -397,30 +434,22 @@ brokenlines_t *V_BreakLines (int maxwidth, const byte *string, bool keepspace) } } + // Make a copy of the broken lines and return them + FBrokenLines *broken = new FBrokenLines[i+1]; + + for (c = 0; c < i; ++c) { - // Make a copy of the broken lines and return them - brokenlines_t *broken = new brokenlines_t[i+1]; - - memcpy (broken, lines, sizeof(brokenlines_t) * i); - broken[i].string = NULL; - broken[i].width = -1; - - return broken; + broken[c] = lines[c]; } + broken[c].Width = -1; + + return broken; } -void V_FreeBrokenLines (brokenlines_t *lines) +void V_FreeBrokenLines (FBrokenLines *lines) { if (lines) { - int i = 0; - - while (lines[i].width != -1) - { - delete[] lines[i].string; - lines[i].string = NULL; - i++; - } delete[] lines; } } diff --git a/src/v_text.h b/src/v_text.h index 06e031244d..49838780c3 100644 --- a/src/v_text.h +++ b/src/v_text.h @@ -37,12 +37,12 @@ #include "doomtype.h" #include "v_font.h" -struct brokenlines_t +struct FBrokenLines { - short width; - byte nlterminated; - byte pad; - char *string; + short Width; + BYTE NLTerminated; + BYTE Pad; + FString Text; }; #define TEXTCOLOR_ESCAPE '\034' @@ -73,9 +73,9 @@ struct brokenlines_t #define TEXTCOLOR_NORMAL "\034-" #define TEXTCOLOR_BOLD "\034+" -brokenlines_t *V_BreakLines (int maxwidth, const byte *str, bool keepspace=false); -void V_FreeBrokenLines (brokenlines_t *lines); -inline brokenlines_t *V_BreakLines (int maxwidth, const char *str, bool keepspace=false) +FBrokenLines *V_BreakLines (int maxwidth, const byte *str, bool keepspace=false); +void V_FreeBrokenLines (FBrokenLines *lines); +inline FBrokenLines *V_BreakLines (int maxwidth, const char *str, bool keepspace=false) { return V_BreakLines (maxwidth, (const byte *)str, keepspace); } #endif //__V_TEXT_H__ diff --git a/src/v_video.h b/src/v_video.h index c98d348eaf..b2171f11d7 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -100,6 +100,7 @@ enum DTA_Masked, // true(default)=use masks from texture, false=ignore masks DTA_HUDRules, // use fullscreen HUD rules to position and size textures DTA_KeepRatio, // doesn't adjust screen size for DTA_Virtual* if the aspect ratio is not 4:3 + DTA_TextLen, // for DrawText: stop after this many characters, even if \0 not hit }; enum diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 1b4d4e9ba3..f1906e2da3 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -731,20 +731,20 @@ int WI_DrawName(int y,const char * levelname, bool nomove=false) if (!l) return 0; screen->SetFont(BigFont); - brokenlines_t * lines = V_BreakLines(320, p); + FBrokenLines *lines = V_BreakLines(320, p); if (lines) { - for (i=0; lines[i].width != -1; i++) + for (i = 0; lines[i].Width >= 0; i++) { if (!nomove) { - screen->DrawText(CR_UNTRANSLATED, 160 - lines[i].width/2, y+h, lines[i].string, DTA_Clean, true, TAG_DONE); + screen->DrawText(CR_UNTRANSLATED, 160 - lines[i].Width/2, y+h, lines[i].Text, DTA_Clean, true, TAG_DONE); } else { - screen->DrawText(CR_UNTRANSLATED, (SCREENWIDTH - lines[i].width * CleanXfac) / 2, (y+h) * CleanYfac, - lines[i].string, DTA_CleanNoMove, true, TAG_DONE); + screen->DrawText(CR_UNTRANSLATED, (SCREENWIDTH - lines[i].Width * CleanXfac) / 2, (y+h) * CleanYfac, + lines[i].Text, DTA_CleanNoMove, true, TAG_DONE); } h+=lumph; } diff --git a/src/zstring.cpp b/src/zstring.cpp index 829ded1cb7..a35443be25 100644 --- a/src/zstring.cpp +++ b/src/zstring.cpp @@ -279,6 +279,14 @@ FString &FString::operator += (char tail) return *this; } +FString &FString::AppendCStrPart (const char *tail, size_t tailLen) +{ + size_t len1 = Len(); + ReallocBuffer (len1 + tailLen); + StrCopy (Chars + len1, tail, tailLen); + return *this; +} + void FString::Truncate (long newlen) { if (newlen >= 0 && newlen < (long)Len()) diff --git a/src/zstring.h b/src/zstring.h index 2e1788a4d1..97059f1474 100644 --- a/src/zstring.h +++ b/src/zstring.h @@ -104,6 +104,7 @@ public: FString &operator += (const FString &tail); FString &operator += (const char *tail); FString &operator += (char tail); + FString &AppendCStrPart (const char *tail, size_t tailLen); FString Left (size_t numChars) const; FString Right (size_t numChars) const;