diff --git a/docs/rh-log.txt b/docs/rh-log.txt index ec2ac01b57..096a60e8db 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,12 @@ +April 12, 2008 (Changes by Graf Zahl) +- Added Martin Howe's morph system update. +- Added support for defining composite textures in HIRESTEX. It is not fully tested + and right now can't do much more than the old TEXTUREx method. +- Added a few NULL pointer checks to the texture code. +- Made duplicate class names in DECORATE non-fatal. There is really no stability + concern here and the worst that can happen is that the wrong actor is spawned. + This was a constant hassle when testing with WADs that contain duplicate resources. + April 11, 2008 - Removed some GCC warnings. - Fixed: MinGW doesn't have _get_pgmptr(), so it couldn't compile i_main.cpp. @@ -20,6 +29,15 @@ April 11, 2008 tables.cpp. (And interestingly, VC++ automatically renamed the object file, so I wasn't aware of the problem with GCC.) +April 11, 2008 (Changes by Graf Zahl) +- Added a Gets function to the FileReader class which I planned to use + to enable Timidity to read its config and sound patches from Zips. + I put this on hold though after finding out that the sound quality + isn't even near that of Timidity++. +- GCC-Fixes (FString::GetChars() for Printf calls) +- Added a dummy Weapon.NOLMS flag so that Skulltag weapons using this flag + can be loaded + April 10, 2008 - Changed the MIDIStreamer to send the all notes off controller to each channel when restarting the song, rather than emitting a single note off diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index dcd2f697bf..d8ae64a46a 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -181,7 +181,9 @@ void PClass::InsertIntoHash () } else if (lexx == 0) { // This type has already been inserted - I_FatalError ("Tried to register class '%s' more than once.", TypeName.GetChars()); + // ... but there is no need whatsoever to make it a fatal error! + Printf ("Tried to register class '%s' more than once.\n", TypeName.GetChars()); + break; } else { // Type comes right here diff --git a/src/g_heretic/a_hereticartifacts.cpp b/src/g_heretic/a_hereticartifacts.cpp index ab1c3a88f6..ee2422fee4 100644 --- a/src/g_heretic/a_hereticartifacts.cpp +++ b/src/g_heretic/a_hereticartifacts.cpp @@ -36,7 +36,10 @@ bool AArtiTomeOfPower::Use (bool pickup) { // Attempt to undo chicken if (!P_UndoPlayerMorph (Owner->player)) { // Failed - P_DamageMobj (Owner, NULL, NULL, 1000000, NAME_Telefrag); + if (!(Owner->player->MorphStyle & MORPH_FAILNOTELEFRAG)) + { + P_DamageMobj (Owner, NULL, NULL, 1000000, NAME_Telefrag); + } } else { // Succeeded diff --git a/src/g_raven/a_artitele.cpp b/src/g_raven/a_artitele.cpp index 54252d0cba..6e0411353a 100644 --- a/src/g_raven/a_artitele.cpp +++ b/src/g_raven/a_artitele.cpp @@ -59,16 +59,18 @@ bool AArtiTeleport::Use (bool pickup) destAngle = ANG45 * (playerstarts[Owner->player - players].angle/45); } P_Teleport (Owner, destX, destY, ONFLOORZ, destAngle, true, true, false); - if (Owner->player->morphTics && (Owner->player->MorphStyle & MORPH_UNDOBYCHAOSDEVICE)) - { // Teleporting away will undo any morph effects (pig) - P_UndoPlayerMorph (Owner->player); - } - // The game check is not necessary because only Heretic defines *evillaugh by default - // However if it is there no other game can use it if it wants to. - //if (gameinfo.gametype == GAME_Heretic) - { // Full volume laugh - S_Sound (Owner, CHAN_VOICE, "*evillaugh", 1, ATTN_NONE); - } + bool canlaugh = true; + if (Owner->player->morphTics && (Owner->player->MorphStyle & MORPH_UNDOBYCHAOSDEVICE)) + { // Teleporting away will undo any morph effects (pig) + if (!P_UndoPlayerMorph (Owner->player) && (Owner->player->MorphStyle & MORPH_FAILNOLAUGH)) + { + canlaugh = false; + } + } + if (canlaugh) + { // Full volume laugh + S_Sound (Owner, CHAN_VOICE, "*evillaugh", 1, ATTN_NONE); + } return true; } diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 3ca43c84ff..4c89b8c5dc 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -1755,12 +1755,16 @@ void APowerMorph::InitEffect( ) const PClass *morph_flash = PClass::FindClass (MorphFlash); const PClass *unmorph_flash = PClass::FindClass (UnMorphFlash); const PClass *player_class = PClass::FindClass (PlayerClass); - if (P_MorphPlayer(realplayer, player_class, -1/*INDEFINITELY*/, MorphStyle, morph_flash, unmorph_flash)) + if (P_MorphPlayer(realplayer, realplayer, player_class, -1/*INDEFINITELY*/, MorphStyle, morph_flash, unmorph_flash)) { Owner = realplayer->mo; // Replace the new owner in our owner; safe because we are not attached to anything yet ItemFlags |= IF_CREATECOPYMOVED; // Let the caller know the "real" owner has changed (to the morphed actor) player = realplayer; // Store the player identity (morphing clears the unmorphed actor's "player" field) } + else // morph failed - give the caller an opportunity to fail the pickup completely + { + ItemFlags |= IF_INITEFFECTFAILED; // Let the caller know that the activation failed (can fail the pickup if appropriate) + } } } diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 0197c79f66..13d5edab42 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -21,7 +21,7 @@ static FRandom pr_morphmonst ("MorphMonster"); // //--------------------------------------------------------------------------- -bool P_MorphPlayer (player_t *p, const PClass *spawntype, int duration, int style, const PClass *enter_flash, const PClass *exit_flash) +bool P_MorphPlayer (player_t *activator, player_t *p, const PClass *spawntype, int duration, int style, const PClass *enter_flash, const PClass *exit_flash) { AInventory *item; APlayerPawn *morphed; @@ -36,8 +36,8 @@ bool P_MorphPlayer (player_t *p, const PClass *spawntype, int duration, int styl { return false; } - if (p->mo->flags2 & MF2_INVULNERABLE) - { // Immune when invulnerable + if ((p->mo->flags2 & MF2_INVULNERABLE) && ((p != activator) || (!(style & MORPH_WHENINVULNERABLE)))) + { // Immune when invulnerable unless this is a power we activated return false; } if (p->morphTics) @@ -402,7 +402,7 @@ int AMorphProjectile::DoSpecialDamage (AActor *target, int damage) if (target->player) { const PClass *player_class = PClass::FindClass (PlayerClass); - P_MorphPlayer (target->player, player_class, Duration, MorphStyle, morph_flash, unmorph_flash); + P_MorphPlayer (NULL, target->player, player_class, Duration, MorphStyle, morph_flash, unmorph_flash); } else { diff --git a/src/g_shared/a_morph.h b/src/g_shared/a_morph.h index 2cab5ef8cb..1beb787902 100644 --- a/src/g_shared/a_morph.h +++ b/src/g_shared/a_morph.h @@ -7,30 +7,28 @@ // Morph style states how morphing affects health and // other effects in the game; only valid for players. // Default should be the old Heretic/HeXen behaviour, -// so the (int) value of MORPH_RAVEN *must* be zero. +// so (int) value of MORPH_OLDEFFECTS *must* be zero. enum { - MORPH_OLDEFFECTS = 0, // Default to old Heretic/HeXen behaviour unless flags given - MORPH_ADDSTAMINA = 1, // Power instead of curse (add stamina instead of limiting to health) - MORPH_FULLHEALTH = 2, // New health semantics (!POWER => MaxHealth of animal, POWER => Normal health behaviour) - MORPH_UNDOBYTOMEOFPOWER = 4, - MORPH_UNDOBYCHAOSDEVICE = 8, + MORPH_OLDEFFECTS = 0x00000000, // Default to old Heretic/HeXen behaviour unless flags given + MORPH_ADDSTAMINA = 0x00000001, // Power instead of curse (add stamina instead of limiting to health) + MORPH_FULLHEALTH = 0x00000002, // New health semantics (!POWER => MaxHealth of animal, POWER => Normal health behaviour) + MORPH_UNDOBYTOMEOFPOWER = 0x00000004, // Player unmorphs upon activating a Tome of Power + MORPH_UNDOBYCHAOSDEVICE = 0x00000008, // Player unmorphs upon activating a Chaos Device + MORPH_FAILNOTELEFRAG = 0x00000010, // Player stays morphed if unmorph by Tome of Power fails + MORPH_FAILNOLAUGH = 0x00000020, // Player doesn't laugh if unmorph by Chaos Device fails + MORPH_WHENINVULNERABLE = 0x00000040 // Player can morph when invulnerable but ONLY if doing it to themselves }; struct PClass; class AActor; class player_s; -// -// A_MORPH -// -bool P_MorphPlayer (player_s *player, const PClass *morphclass, int duration = 0, int style = 0, +bool P_MorphPlayer (player_s *activator, player_s *player, const PClass *morphclass, int duration = 0, int style = 0, const PClass *enter_flash = NULL, const PClass *exit_flash = NULL); bool P_UndoPlayerMorph (player_s *player, bool force = false); bool P_MorphMonster (AActor *actor, const PClass *morphclass, int duration = 0, int style = 0, const PClass *enter_flash = NULL, const PClass *exit_flash = NULL); bool P_UpdateMorphedMonster (AActor *actor); - - #endif //__A_MORPH__ diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 9412358b58..5e4ed73d22 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -1227,6 +1227,14 @@ bool AInventory::TryPickup (AActor *toucher) { return false; } + // Some powerups cannot activate absolutely, for + // example, PowerMorph; fail the pickup if so. + if (copy->ItemFlags & IF_INITEFFECTFAILED) + { + if (copy != this) copy->Destroy(); + else ItemFlags &= ~IF_INITEFFECTFAILED; + return false; + } // Handle owner-changing powerups if (copy->ItemFlags & IF_CREATECOPYMOVED) { diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index e4d3b49280..50ecc569fd 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -96,7 +96,8 @@ enum IF_BIGPOWERUP = 1<<12, // Affected by RESPAWN_SUPER dmflag IF_KEEPDEPLETED = 1<<13, // Items with this flag are retained even when they run out. IF_IGNORESKILL = 1<<14, // Ignores any skill related multiplicators when giving this item. - IF_CREATECOPYMOVED = 1<<15 // CreateCopy changed the owner (copy's Owner field holds new owner). + IF_CREATECOPYMOVED = 1<<15, // CreateCopy changed the owner (copy's Owner field holds new owner). + IF_INITEFFECTFAILED = 1<<16 // CreateCopy tried to activate a powerup and activation failed (can happen with PowerMorph) }; struct vissprite_t; diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index a2d0884a26..4c102bcfed 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -6,7 +6,7 @@ #include "actor.h" class FDecalTemplate; -struct vertex_s; +struct vertex_t; struct side_t; extern void P_SpawnDirt (AActor *actor, fixed_t radius); @@ -50,7 +50,7 @@ protected: void CalcFracPos (side_t *wall, fixed_t x, fixed_t y); void Remove (); - static void SpreadLeft (fixed_t r, vertex_s *v1, side_t *feelwall); + static void SpreadLeft (fixed_t r, vertex_t *v1, side_t *feelwall); static void SpreadRight (fixed_t r, side_t *feelwall, fixed_t wallsize); }; diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index bcdd2211e4..e3e01b9d9a 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -440,14 +440,14 @@ const char *cht_Morph (player_t *player, const PClass *morphclass, bool quickund { if (P_UndoPlayerMorph (player)) { - if (!quickundo && oldclass != morphclass && P_MorphPlayer (player, morphclass, 0, style)) + if (!quickundo && oldclass != morphclass && P_MorphPlayer (player, player, morphclass, 0, style)) { return "You feel even stranger."; } return "You feel like yourself again."; } } - else if (P_MorphPlayer (player, morphclass, 0, style)) + else if (P_MorphPlayer (player, player, morphclass, 0, style)) { return "You feel strange..."; } diff --git a/src/p_user.cpp b/src/p_user.cpp index 09aef7d9e5..88ef6b5d9b 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -1061,6 +1061,8 @@ void APlayerPawn::ActivateMorphWeapon () } } P_SetPsprite (player, ps_flash, NULL); + + player->PendingWeapon = WP_NOCHANGE; } //=========================================================================== diff --git a/src/r_data.h b/src/r_data.h index 17eb749620..acc19911bb 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -83,6 +83,7 @@ class FMultiPatchTexture : public FTexture { public: FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflump); + FMultiPatchTexture (FScanner &sc, int usetype); ~FMultiPatchTexture (); const BYTE *GetColumn (unsigned int column, const Span **spans_out); @@ -102,7 +103,13 @@ protected: struct TexPart { SWORD OriginX, OriginY; + BYTE Mirror:2; + BYTE Rotate:2; + BYTE textureOwned:1; FTexture *Texture; + + TexPart(); + ~TexPart(); }; int NumParts; @@ -113,6 +120,7 @@ protected: private: void CheckForHacks (); + void ParsePatch(FScanner &sc, TexPart & part); }; // A texture defined between F_START and F_END markers diff --git a/src/r_defs.h b/src/r_defs.h index 9cca6ac1f4..bc5bfc2041 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -71,21 +71,21 @@ extern size_t MaxDrawSegs; // Note: transformed values not buffered locally, // like some DOOM-alikes ("wt", "WebView") did. // -struct vertex_s +struct vertex_t { fixed_t x, y; - bool operator== (const vertex_s &other) + bool operator== (const vertex_t &other) { return x == other.x && y == other.y; } }; -typedef struct vertex_s vertex_t; // Forward of LineDefs, for Sectors. struct line_t; class player_s; +class FScanner; // // The SECTORS record, at runtime. @@ -744,7 +744,6 @@ public: SWORD LeftOffset, TopOffset; BYTE WidthBits, HeightBits; - //BYTE ScaleX, ScaleY; fixed_t xScale; fixed_t yScale; @@ -888,6 +887,7 @@ public: FTexture *operator[] (const char *texname) { int texnum = GetTexture (texname, FTexture::TEX_MiscPatch); + if (texnum==-1) return NULL; return Textures[texnum].Texture; } FTexture *FindTexture(const char *texname, int usetype = FTexture::TEX_MiscPatch, BITFIELD flags = TEXMAN_TryAny); @@ -901,6 +901,7 @@ public: FTexture *operator() (const char *texname) { int texnum = GetTexture (texname, FTexture::TEX_MiscPatch); + if (texnum==-1) return NULL; return Textures[Translation[texnum]].Texture; } @@ -936,6 +937,7 @@ public: void AddTiles (void *tileFile); void AddHiresTextures (int wadnum); void LoadHiresTex(int wadnum); + void ParseXTexture(FScanner &sc, int usetype); int CreateTexture (int lumpnum, int usetype=FTexture::TEX_Any); // Also calls AddTexture int AddTexture (FTexture *texture); diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index d1c17fcedf..4422eff7df 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -33,6 +33,7 @@ ** */ +#include #include "doomtype.h" #include "files.h" #include "r_data.h" @@ -40,6 +41,9 @@ #include "i_system.h" #include "gi.h" #include "st_start.h" +#include "sc_man.h" +#include "templates.h" +#include "vectors.h" // On the Alpha, accessing the shorts directly if they aren't aligned on a // 4-byte boundary causes unaligned access warnings. Why it does this at @@ -462,6 +466,32 @@ FTextureFormat FMultiPatchTexture::GetFormat() } +//========================================================================== +// +// FMultiPatchTexture :: TexPart :: TexPart +// +//========================================================================== + +FMultiPatchTexture::TexPart::TexPart() +{ + OriginX = OriginY = 0; + Mirror = Rotate = 0; + textureOwned = false; + Texture = NULL; +} + +//========================================================================== +// +// FMultiPatchTexture :: TexPart :: TexPart +// +//========================================================================== + +FMultiPatchTexture::TexPart::~TexPart() +{ + if (textureOwned && Texture != NULL) delete Texture; + Texture = NULL; +} + //========================================================================== // // FTextureManager :: AddTexturesLump @@ -631,3 +661,141 @@ void FTextureManager::AddTexturesLumps (int lump1, int lump2, int patcheslump) } } + +void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part) +{ + FString patchname; + sc.MustGetString(); + + int texno = TexMan.CheckForTexture(sc.String, TEX_WallPatch); + + if (texno < 0) + { + int lumpnum = Wads.CheckNumForFullName(sc.String); + if (lumpnum >= 0) + { + part.Texture = FTexture::CreateTexture(lumpnum, TEX_WallPatch); + part.textureOwned = true; + } + } + else + { + part.Texture = TexMan[texno]; + } + if (part.Texture == NULL) + { + Printf("Unknown patch '%s' in texture '%s'\n", sc.String, Name); + } + sc.MustGetStringName(","); + sc.MustGetNumber(); + part.OriginX = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + part.OriginY = sc.Number; + + /* not yet implemented + if (sc.CheckString("{"); + { + while (!sc.CheckString("}")) + { + sc.MustGetString(); + if (sc.Compare("flipx")) + { + part.Mirror = 1; + } + else if (sc.Compare("flipy")) + { + part.Mirror = 2; + } + else if (sc.Compare("rotate")) + { + sc.MustGetNumber(); + if (sc.Number != 0 && sc.Number !=90 && sc.Number != 180 && sc.Number != 270) + { + sc.ScriptError("Rotation must be 0, 90, 180 or 270 degrees"); + } + part.Rotate = sc.Number / 90; + } + } + } + */ +} + + +FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) +{ + TArray parts; + + sc.MustGetString(); + uppercopy(Name, sc.String); + sc.MustGetStringName(","); + sc.MustGetNumber(); + Width = sc.Number; + sc.MustGetStringName(","); + sc.MustGetNumber(); + Height = sc.Number; + + if (sc.CheckString("{")) + { + while (!sc.CheckString("}")) + { + sc.MustGetString(); + if (sc.Compare("XScale")) + { + sc.MustGetFloat(); + xScale = FLOAT2FIXED(sc.Float); + } + else if (sc.Compare("YScale")) + { + sc.MustGetFloat(); + yScale = FLOAT2FIXED(sc.Float); + } + else if (sc.Compare("WorldPanning")) + { + bWorldPanning = true; + } + else if (sc.Compare("NoDecals")) + { + bNoDecals = true; + } + else if (sc.Compare("Patch")) + { + TexPart part; + ParsePatch(sc, part); + parts.Push(part); + } + } + + NumParts = parts.Size(); + UseType = FTexture::TEX_Override; + Parts = new TexPart[NumParts]; + memcpy(Parts, &parts[0], NumParts * sizeof(*Parts)); + + CalcBitSize (); + + // If this texture is just a wrapper around a single patch, we can simply + // forward GetPixels() and GetColumn() calls to that patch. + if (NumParts == 1) + { + if (Parts->OriginX == 0 && Parts->OriginY == 0 && + Parts->Texture->GetWidth() == Width && + Parts->Texture->GetHeight() == Height && + Parts->Mirror == 0 && Parts->Rotate == 0) + { + bRedirect = true; + } + } + //DefinitionLump = sc.G deflumpnum; + } + + + +} + + + +void FTextureManager::ParseXTexture(FScanner &sc, int usetype) +{ + FTexture *tex = new FMultiPatchTexture(sc, usetype); + TexMan.AddTexture (tex); +} diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 432db37981..dce1ec0947 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -611,6 +611,14 @@ void FTextureManager::LoadHiresTex(int wadnum) } //else Printf("Unable to define hires texture '%s'\n", tex->Name); } + else if (sc.Compare("texture")) + { + ParseXTexture(sc, FTexture::TEX_Override); + } + else if (sc.Compare("sprite")) + { + ParseXTexture(sc, FTexture::TEX_Sprite); + } } } } diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index 71f8ebde55..780f8bc9c4 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -297,10 +297,12 @@ static FActorInfo *CreateNewActor(FScanner &sc, FActorInfo **parentc, Baggage *b *colon++ = 0; } + /* if (PClass::FindClass (sc.String) != NULL) { sc.ScriptError ("Actor %s is already defined.", sc.String); } + */ typeName = sc.String; diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 14fc537cf3..0496de609d 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -752,11 +752,13 @@ static bool CheckFloatParm(FScanner &sc) // [MH] static int ParseMorphStyle (FScanner &sc) { - static const char * morphstyles[]={ - "MRF_ADDSTAMINA", "MRF_FULLHEALTH", "MRF_UNDOBYTOMEOFPOWER", "MRF_UNDOBYCHAOSDEVICE", NULL}; - - static const int morphstyle_values[]={ - MORPH_ADDSTAMINA, MORPH_FULLHEALTH, MORPH_UNDOBYTOMEOFPOWER, MORPH_UNDOBYCHAOSDEVICE}; + static const char * morphstyles[]={ + "MRF_ADDSTAMINA", "MRF_FULLHEALTH", "MRF_UNDOBYTOMEOFPOWER", "MRF_UNDOBYCHAOSDEVICE", + "MRF_FAILNOTELEFRAG", "MRF_FAILNOLAUGH", "MRF_WHENINVULNERABLE", NULL}; + + static const int morphstyle_values[]={ + MORPH_ADDSTAMINA, MORPH_FULLHEALTH, MORPH_UNDOBYTOMEOFPOWER, MORPH_UNDOBYCHAOSDEVICE, + MORPH_FAILNOTELEFRAG, MORPH_FAILNOLAUGH, MORPH_WHENINVULNERABLE}; // May be given flags by number... if (sc.CheckNumber()) @@ -2564,7 +2566,7 @@ static void PowerMorphMorphStyle (FScanner &sc, APowerMorph *defaults, Baggage & static void PowerMorphMorphFlash (FScanner &sc, APowerMorph *defaults, Baggage &bag) { sc.MustGetString (); - defaults->UnMorphFlash = FName(sc.String); + defaults->MorphFlash = FName(sc.String); } //========================================================================== diff --git a/src/v_font.cpp b/src/v_font.cpp index 44bf06fbbc..563181114f 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -322,14 +322,16 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count, stcfn121 = true; } } - if (lump != -1 || i != 124-start || !stcfn121) - charlumps[i] = lump; if (lump >= 0) { FTexture *pic = TexMan[buffer]; if (pic != NULL) { + // set the lump here only if it represents a valid texture + if (i != 124-start || !stcfn121) + charlumps[i] = lump; + int height = pic->GetScaledHeight(); int yoffs = pic->GetScaledTopOffset(); @@ -1200,7 +1202,7 @@ FFontChar1::FFontChar1 (int sourcelump, const BYTE *sourceremap) Name[0] = 0; // Make this texture unnamed // now copy all the properties from the base texture - CopySize(BaseTexture); + if (BaseTexture != NULL) CopySize(BaseTexture); Pixels = NULL; }