From 6c21616c85741f2898cb5c8f4c513af8d595c74c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 11 May 2008 21:16:32 +0000 Subject: [PATCH] - Changed: HIRESTEX 'define' textures now replace existing textures of type MiscPatch with the same name. - Added UDMF line trigger types MonsterUse and MonsterPush. - Separated skill and class filter bits from FMapThing::flags so that UDMF can define up to 16 of each. Also separated easy/baby and hard/nightmare and changed default MAPINFO definitions. - Changed: Crosshair drawing uses the current player class's default health instead of 100 to calculate the color for the crosshair. - Added SECF_NOFALLINGDAMAGE flag plus Sector_ChangeFlags to set it. Also separated all user settable flags from MoreFlags into their own Flags variable. SVN r964 (trunk) --- docs/rh-log.txt | 14 + src/actionspecials.h | 1 + src/decallib.cpp | 18 +- src/decallib.h | 10 +- src/doomdata.h | 29 +- src/doomdef.h | 4 + src/g_level.cpp | 18 +- src/g_shared/a_decals.cpp | 4 +- src/g_shared/a_skies.cpp | 4 +- src/g_shared/shared_sbar.cpp | 2 +- src/namedef.h | 96 +++- src/p_buildmap.cpp | 4 +- src/p_lnspec.cpp | 19 + src/p_mobj.cpp | 8 +- src/p_saveg.cpp | 1 + src/p_setup.cpp | 480 ++++++++++-------- src/p_setup.h | 2 + src/p_spec.cpp | 22 +- src/p_udmf.cpp | 695 +++++++++++++++++++++++++++ src/p_user.cpp | 3 + src/p_xlat.cpp | 1 - src/r_defs.h | 12 +- src/s_sound.cpp | 2 +- src/textures/texturemanager.cpp | 10 +- src/thingdef/thingdef_properties.cpp | 8 +- src/version.h | 2 +- wadsrc/mapinfo/doomcommon.txt | 4 +- wadsrc/mapinfo/heretic.txt | 4 +- wadsrc/mapinfo/hexen.txt | 4 +- wadsrc/mapinfo/strife.txt | 4 +- zdoom.vcproj | 434 ++++++++--------- 31 files changed, 1417 insertions(+), 502 deletions(-) create mode 100644 src/p_udmf.cpp diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 398295aad..bdb9a01f4 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,11 @@ +May 11, 2008 (Changes by Graf Zahl) +- Changed: HIRESTEX 'define' textures now replace existing textures + of type MiscPatch with the same name. +- Added UDMF line trigger types MonsterUse and MonsterPush. +- Separated skill and class filter bits from FMapThing::flags so that + UDMF can define up to 16 of each. Also separated easy/baby and + hard/nightmare and changed default MAPINFO definitions. + May 10, 2008 - Fixed: FWadCollection::MergeLumps() did not initialize the flags for any marker lumps it inserted. @@ -10,6 +18,12 @@ May 9, 2008 - Renamed timidity_config and timidity_voices to midi_config and midi_voices respectively. +May 9, 2008 (Changes by Graf Zahl) +- Changed: Crosshair drawing uses the current player class's default health instead + of 100 to calculate the color for the crosshair. +- Added SECF_NOFALLINGDAMAGE flag plus Sector_ChangeFlags to set it. Also separated + all user settable flags from MoreFlags into their own Flags variable. + May 8, 2008 - Reduced volume, expression, and panning controllers back to 7 bits. - Added very basic Soundfont support to the internal TiMidity. Things missing: diff --git a/src/actionspecials.h b/src/actionspecials.h index 9245750ad..72792973d 100644 --- a/src/actionspecials.h +++ b/src/actionspecials.h @@ -51,6 +51,7 @@ DEFINE_SPECIAL(ExtraFloor_LightOnly, 50, -1, -1) DEFINE_SPECIAL(Sector_SetLink, 51, 4, 4) DEFINE_SPECIAL(Scroll_Wall, 52, 5, 5) DEFINE_SPECIAL(Line_SetTextureOffset, 53, 5, 5) +DEFINE_SPECIAL(Sector_ChangeFlags, 54, 3, 3) DEFINE_SPECIAL(Plat_PerpetualRaise, 60, 3, 3) DEFINE_SPECIAL(Plat_Stop, 61, 1, 1) diff --git a/src/decallib.cpp b/src/decallib.cpp index d58eb794b..d57012f30 100644 --- a/src/decallib.cpp +++ b/src/decallib.cpp @@ -405,7 +405,7 @@ void FDecalLib::ReadDecals(FScanner &sc) } } -BYTE FDecalLib::GetDecalID (FScanner &sc) +WORD FDecalLib::GetDecalID (FScanner &sc) { sc.MustGetString (); if (!IsNum (sc.String)) @@ -416,18 +416,18 @@ BYTE FDecalLib::GetDecalID (FScanner &sc) else { unsigned long num = strtoul (sc.String, NULL, 10); - if (num < 1 || num > 255) + if (num < 1 || num > 65535) { - sc.MustGetStringName ("Decal ID must be between 1 and 255"); + sc.MustGetStringName ("Decal ID must be between 1 and 65535"); } - return (BYTE)num; + return (WORD)num; } } void FDecalLib::ParseDecal (FScanner &sc) { FString decalName; - BYTE decalNum; + WORD decalNum; FDecalTemplate newdecal; int code, picnum; @@ -544,7 +544,7 @@ void FDecalLib::ParseDecal (FScanner &sc) void FDecalLib::ParseDecalGroup (FScanner &sc) { FString groupName; - BYTE decalNum; + WORD decalNum; FDecalBase *targetDecal; FDecalGroup *group; @@ -839,7 +839,7 @@ void FDecalLib::ReplaceDecalRef (FDecalBase *from, FDecalBase *to, FDecalBase *r root->ReplaceDecalRef (from, to); } -void FDecalLib::AddDecal (const char *name, BYTE num, const FDecalTemplate &decal) +void FDecalLib::AddDecal (const char *name, WORD num, const FDecalTemplate &decal) { FDecalTemplate *newDecal = new FDecalTemplate; @@ -912,7 +912,7 @@ void FDecalLib::AddDecal (FDecalBase *decal) } } -const FDecalTemplate *FDecalLib::GetDecalByNum (BYTE num) const +const FDecalTemplate *FDecalLib::GetDecalByNum (WORD num) const { if (num == 0) { @@ -940,7 +940,7 @@ const FDecalTemplate *FDecalLib::GetDecalByName (const char *name) const return NULL; } -FDecalBase *FDecalLib::ScanTreeForNum (const BYTE num, FDecalBase *root) +FDecalBase *FDecalLib::ScanTreeForNum (const WORD num, FDecalBase *root) { while (root != NULL) { diff --git a/src/decallib.h b/src/decallib.h index c829fd11a..984470094 100644 --- a/src/decallib.h +++ b/src/decallib.h @@ -61,7 +61,7 @@ protected: FDecalBase *Left, *Right; FName Name; - BYTE SpawnID; + WORD SpawnID; TArray Users; // Which actors generate this decal }; @@ -98,22 +98,22 @@ public: void ReadDecals (FScanner &sc); void ReadAllDecals (); - const FDecalTemplate *GetDecalByNum (BYTE num) const; + const FDecalTemplate *GetDecalByNum (WORD num) const; const FDecalTemplate *GetDecalByName (const char *name) const; private: struct FTranslation; static void DelTree (FDecalBase *root); - static FDecalBase *ScanTreeForNum (const BYTE num, FDecalBase *root); + static FDecalBase *ScanTreeForNum (const WORD num, FDecalBase *root); static FDecalBase *ScanTreeForName (const char *name, FDecalBase *root); static void ReplaceDecalRef (FDecalBase *from, FDecalBase *to, FDecalBase *root); FTranslation *GenerateTranslation (DWORD start, DWORD end); - void AddDecal (const char *name, BYTE num, const FDecalTemplate &decal); + void AddDecal (const char *name, WORD num, const FDecalTemplate &decal); void AddDecal (FDecalBase *decal); FDecalAnimator *FindAnimator (const char *name); - BYTE GetDecalID (FScanner &sc); + WORD GetDecalID (FScanner &sc); void ParseDecal (FScanner &sc); void ParseDecalGroup (FScanner &sc); void ParseGenerator (FScanner &sc); diff --git a/src/doomdata.h b/src/doomdata.h index 10a0cb0e6..fc77b5ed9 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -170,6 +170,8 @@ enum SPAC SPAC_UseThrough = 1<<6, // when player uses line (doesn't block) // SPAC_PTOUCH is mapped to SPAC_PCross|SPAC_Impact SPAC_AnyCross = 1<<7, // when anything without the MF2_TELEPORT flag crosses the line + SPAC_MUse = 1<<8, // monsters can use + SPAC_MPush = 1<<9, // monsters can push SPAC_PlayerActivate = (SPAC_Cross|SPAC_Use|SPAC_Impact|SPAC_Push|SPAC_AnyCross|SPAC_UseThrough), }; @@ -269,31 +271,19 @@ typedef struct // Internal representation of a mapthing struct FMapThing { - unsigned short thingid; + int thingid; fixed_t x; fixed_t y; fixed_t z; short angle; short type; - short flags; - short special; + WORD SkillFilter; + WORD ClassFilter; + DWORD flags; + int special; int args[5]; void Serialize (FArchive &); - - FMapThing &operator =(mapthinghexen_t &mt) - { - thingid = mt.thingid; - x = LittleShort(mt.x)< 0) skill.SpawnFilter |= (1<<(sc.Number-1)); + } + else + { + sc.MustGetString (); + if (sc.Compare("baby")) skill.SpawnFilter |= 1; + else if (sc.Compare("easy")) skill.SpawnFilter |= 2; + else if (sc.Compare("normal")) skill.SpawnFilter |= 4; + else if (sc.Compare("hard")) skill.SpawnFilter |= 8; + else if (sc.Compare("nightmare")) skill.SpawnFilter |= 16; + } } else if (sc.Compare("ACSReturn")) { diff --git a/src/g_shared/a_decals.cpp b/src/g_shared/a_decals.cpp index fe125459d..782c26386 100644 --- a/src/g_shared/a_decals.cpp +++ b/src/g_shared/a_decals.cpp @@ -722,8 +722,10 @@ void ADecal::BeginPlay () Super::BeginPlay (); + int decalid = args[0] + (args[1] << 8); // [KS] High byte for decals. + // If no decal is specified, don't try to create one. - if (args[0] != 0 && (tpl = DecalLibrary.GetDecalByNum (args[0])) != 0) + if (decalid != 0 && (tpl = DecalLibrary.GetDecalByNum (decalid)) != 0) { if (tpl->PicNum == 65535) { diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp index a6214a066..4ec3a8ad7 100644 --- a/src/g_shared/a_skies.cpp +++ b/src/g_shared/a_skies.cpp @@ -232,11 +232,11 @@ END_DEFAULTS void ASectorSilencer::BeginPlay () { Super::BeginPlay (); - Sector->MoreFlags |= SECF_SILENT; + Sector->Flags |= SECF_SILENT; } void ASectorSilencer::Destroy () { - Sector->MoreFlags &= ~SECF_SILENT; + Sector->Flags &= ~SECF_SILENT; Super::Destroy (); } diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 74e5a0e04..3ec0dcc48 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -1026,7 +1026,7 @@ void DBaseStatusBar::DrawCrosshair () if (crosshairhealth) { - int health = CPlayer->health; + int health = Scale(CPlayer->health, 100, CPlayer->mo->GetDefault()->health); if (health >= 85) { diff --git a/src/namedef.h b/src/namedef.h index 5f58d7c88..0383a6764 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -224,7 +224,7 @@ xx(Communicator) // Textmap properties //xx(X) //xx(Y) -//xx(Z) +xx(Height) //xx(Tid) //xx(Angle) xx(Type) @@ -237,18 +237,100 @@ xx(Arg4) xx(Id) xx(V1) xx(V2) -xx(Frontside) -xx(Backside) + +xx(Sidefront) +xx(Sideback) xx(Offsetx) xx(Offsety) xx(Texturetop) xx(Texturebottom) xx(Texturemiddle) xx(Sector) -xx(Floorheight) -xx(Ceilingheight) +xx(Heightfloor) +xx(Heightceiling) xx(Lightlevel) xx(Tag) -xx(Floorpic) -xx(Ceilingpic) +xx(Texturefloor) +xx(Textureceiling) +xx(Skill1) +xx(Skill2) +xx(Skill3) +xx(Skill4) +xx(Skill5) +xx(Skill6) +xx(Skill7) +xx(Skill8) +xx(Skill9) +xx(Skill10) +xx(Skill11) +xx(Skill12) +xx(Skill13) +xx(Skill14) +xx(Skill15) +xx(Skill16) +xx(Medium) +xx(Hard) +xx(Ambush) +xx(Dormant) +xx(Class0) +xx(Class1) +xx(Class2) +xx(Class3) +xx(Class4) +xx(Class5) +xx(Class6) +xx(Class7) +xx(Class8) +xx(Class9) +xx(Class10) +xx(Class11) +xx(Class12) +xx(Class13) +xx(Class14) +xx(Class15) +xx(Class16) +xx(Single) +xx(Coop) +xx(Dm) +xx(Translucent) +xx(Invisible) +xx(Friend) +xx(Strifeally) +xx(Standing) + +xx(Blocking) +xx(Blockmonsters) +xx(Twosided) +xx(Dontpegtop) +xx(Dontpegbottom) +xx(Secret) +xx(Soundblock) +xx(Dontdraw) +xx(Mapped) +xx(Monsteractivate) +xx(Blockplayers) +xx(Blockeverything) +xx(Zoneboundary) +xx(Jumpover) +xx(Blockfloating) +xx(Clipmidtex) +xx(Wrapmidtex) +xx(Midtex3d) +xx(Checkswitchrange) +xx(Firstsideonly) +xx(Transparent) +xx(Passuse) + +xx(Playercross) +xx(Playeruse) +xx(Monstercross) +xx(Impact) +xx(Playerpush) +xx(Missilecross) +xx(Anycross) +xx(Monsteruse) +xx(Monsterpush) + +xx(ZDoom) +xx(ZDoomTranslated) diff --git a/src/p_buildmap.cpp b/src/p_buildmap.cpp index c2319f7a8..51a866c5b 100644 --- a/src/p_buildmap.cpp +++ b/src/p_buildmap.cpp @@ -626,7 +626,9 @@ static int LoadSprites (spritetype *sprites, int numsprites, sectortype *bsector mapthings[count].z = (bsectors[sprites[i].sectnum].floorz - sprites[i].z) << 8; mapthings[count].angle = (((2048-sprites[i].ang) & 2047) * 360) >> 11; mapthings[count].type = 9988; - mapthings[count].flags = MTF_FIGHTER|MTF_CLERIC|MTF_MAGE|MTF_SINGLE|MTF_COOPERATIVE|MTF_DEATHMATCH|MTF_EASY|MTF_NORMAL|MTF_HARD; + mapthings[count].ClassFilter = 0xffff; + mapthings[count].SkillFilter = 0xffff; + mapthings[count].flags = MTF_SINGLE|MTF_COOPERATIVE|MTF_DEATHMATCH; mapthings[count].special = 0; mapthings[count].args[0] = picnum & 255; diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 7570e5260..a9145d7e5 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -1802,6 +1802,25 @@ FUNC(LS_Sector_ChangeSound) return rtn; } +FUNC(LS_Sector_ChangeFlags) +// Sector_ChangeFlags (tag, set, clear) +{ + int secNum; + bool rtn; + + if (!arg0) + return false; + + secNum = -1; + rtn = false; + while ((secNum = P_FindSectorFromTag (arg0, secNum)) >= 0) + { + sectors[secNum].Flags = (sectors[secNum].Flags | arg1) & ~arg2; + rtn = true; + } + return rtn; +} + struct FThinkerCollection { int RefNum; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 6512686d5..fc1f292fe 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1824,6 +1824,8 @@ void P_MonsterFallingDamage (AActor *mo) if (!(level.flags&LEVEL_MONSTERFALLINGDAMAGE)) return; + if (mo->floorsector->Flags & SECF_NOFALLINGDAMAGE) + return; mom = abs(mo->momz); if (mom > 35*FRACUNIT) @@ -3835,7 +3837,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) } mask = G_SkillProperty(SKILLP_SpawnFilter); - if (!(mthing->flags & mask)) + if (!(mthing->SkillFilter & mask)) { return NULL; } @@ -3845,7 +3847,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position) if (!multiplayer) { // Single player int spawnmask = players[consoleplayer].GetSpawnClass(); - if (spawnmask != 0 && (mthing->flags & spawnmask) == 0) + if (spawnmask != 0 && (mthing->ClassFilter & spawnmask) == 0) { // Not for current class return NULL; } @@ -4506,7 +4508,7 @@ void P_PlaySpawnSound(AActor *missile, AActor *spawner) { // If there is no spawner use the spawn position. // But not in a silenced sector. - if (!(missile->Sector->MoreFlags & SECF_SILENT)) + if (!(missile->Sector->Flags & SECF_SILENT)) S_SoundID (&missile->x, CHAN_WEAPON, missile->SeeSound, 1, ATTN_NORM); } } diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index c52a74632..8e990c9a6 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -330,6 +330,7 @@ void P_SerializeWorld (FArchive &arc) << sec->CeilingFlags << sec->sky << sec->MoreFlags + << sec->Flags << sec->FloorSkyBox << sec->CeilingSkyBox << sec->ZoneNumber << sec->oldspecial; diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 91a72ca65..4c72d48f8 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -72,6 +72,9 @@ extern void P_TranslateLineDef (line_t *ld, maplinedef_t *mld); extern void P_TranslateTeleportThings (void); extern int P_TranslateSectorSpecial (int); +void P_ParseTextMap(MapData *map); +void P_SpawnTextThings(int position); + extern int numinterpolations; extern unsigned int R_OldBlend; @@ -116,7 +119,7 @@ zone_t* zones; FExtraLight* ExtraLights; FLightStack* LightStacks; -static TArray MapThingsConverted; +TArray MapThingsConverted; int sidecount; struct sidei_t // [RH] Only keep BOOM sidedef init stuff around for init @@ -140,7 +143,7 @@ struct sidei_t // [RH] Only keep BOOM sidedef init stuff around for init } b; }; } *sidetemp; -static WORD *linemap; +TArray linemap; bool UsingGLNodes; @@ -174,7 +177,7 @@ FBlockNode** blocklinks; // for thing chains // BYTE* rejectmatrix; -static bool ForceNodeBuild; +bool ForceNodeBuild; // Maintain single and multi player starting spots. TArray deathmatchstarts (16); @@ -326,6 +329,7 @@ MapData *P_OpenMapData(const char * mapname) } else { + map->isText = true; map->MapLumps[1].FilePos = Wads.GetLumpOffset(lump_name + 1); map->MapLumps[1].Size = Wads.LumpLength(lump_name + 1); for(int i = 2;; i++) @@ -407,6 +411,7 @@ MapData *P_OpenMapData(const char * mapname) if (i == 1 && !strnicmp(lumpname, "TEXTMAP", 8)) { + map->isText = true; map->MapLumps[1].FilePos = offset; map->MapLumps[1].Size = size; for(int i = 2;; i++) @@ -1318,7 +1323,7 @@ void P_LoadNodes (MapData * map) //=========================================================================== CVAR(Bool, dumpspawnedthings, false, 0) -static void SpawnMapThing(int index, FMapThing *mt, int position) +void SpawnMapThing(int index, FMapThing *mt, int position) { AActor *spawned = P_SpawnMapThing(mt, position); if (dumpspawnedthings) @@ -1335,6 +1340,15 @@ static void SpawnMapThing(int index, FMapThing *mt, int position) // //=========================================================================== +WORD MakeSkill(int flags) +{ + WORD res = 0; + if (flags & 1) res |= 1+2; + if (flags & 2) res |= 4; + if (flags & 4) res |= 8+16; + return res; +} + void P_LoadThings (MapData * map, int position) { FMapThing mt2; // [RH] for translation @@ -1362,6 +1376,10 @@ void P_LoadThings (MapData * map, int position) short flags = LittleShort(mt->options); memset (&mt2, 0, sizeof(mt2)); + + mt2.SkillFilter = MakeSkill(flags); + mt2.ClassFilter = 0xffff; // Doom map format doesn't have class flags so spawn for all player classes + flags &= ~MTF_SKILLMASK; mt2.flags = (short)((flags & 0xf) | 0x7e0); if (gameinfo.gametype == GAME_Strife) { @@ -1423,7 +1441,18 @@ void P_LoadThings2 (MapData * map, int position) for(int i = 0; i< numthings; i++) { - mti[i] = mth[i]; + mti[i].thingid = mth[i].thingid; + mti[i].x = LittleShort(mth[i].x)<> MTF_CLASS_SHIFT; + mti[i].flags &= ~(MTF_SKILLMASK|MTF_CLASS_MASK); } delete[] mtp; @@ -1486,7 +1515,10 @@ void P_AdjustLine (line_t *ld) ld->bbox[BOXBOTTOM] = v2->y; ld->bbox[BOXTOP] = v1->y; } +} +void P_SetLineID (line_t *ld) +{ // [RH] Set line id (as appropriate) here // for Doom format maps this must be done in P_TranslateLineDef because // the tag doesn't always go into the first arg. @@ -1543,89 +1575,89 @@ void P_SaveLineSpecial (line_t *ld) } } -// killough 4/4/98: delay using sidedefs until they are loaded -void P_FinishLoadingLineDefs () +void P_FinishLoadingLineDef(line_t *ld, int alpha) { - WORD len; - int i, linenum; - line_t *ld = lines; + ld->frontsector = ld->sidenum[0]!=NO_SIDE ? sides[ld->sidenum[0]].sector : 0; + ld->backsector = ld->sidenum[1]!=NO_SIDE ? sides[ld->sidenum[1]].sector : 0; + float dx = FIXED2FLOAT(ld->v2->x - ld->v1->x); + float dy = FIXED2FLOAT(ld->v2->y - ld->v1->y); + SBYTE light; + int linenum = ld-lines; - for (i = numlines, linenum = 0; i--; ld++, linenum++) + if (ld->frontsector == NULL) { - ld->frontsector = ld->sidenum[0]!=NO_SIDE ? sides[ld->sidenum[0]].sector : 0; - ld->backsector = ld->sidenum[1]!=NO_SIDE ? sides[ld->sidenum[1]].sector : 0; - float dx = FIXED2FLOAT(ld->v2->x - ld->v1->x); - float dy = FIXED2FLOAT(ld->v2->y - ld->v1->y); - SBYTE light; + Printf ("Line %d has no front sector\n", linemap[linenum]); + } - if (ld->frontsector == NULL) + // [RH] Set some new sidedef properties + int len = (int)(sqrtf (dx*dx + dy*dy) + 0.5f); + light = dy == 0 ? level.WallHorizLight : + dx == 0 ? level.WallVertLight : 0; + + if (ld->sidenum[0] != NO_SIDE) + { + sides[ld->sidenum[0]].linenum = linenum; + sides[ld->sidenum[0]].TexelLength = len; + sides[ld->sidenum[0]].Light = light; + } + if (ld->sidenum[1] != NO_SIDE) + { + sides[ld->sidenum[1]].linenum = linenum; + sides[ld->sidenum[1]].TexelLength = len; + sides[ld->sidenum[1]].Light = light; + } + + switch (ld->special) + { // killough 4/11/98: handle special types + int j; + + case TranslucentLine: // killough 4/11/98: translucent 2s textures + // [RH] Second arg controls how opaque it is. + if (alpha < 0) { - Printf ("Line %d has no front sector\n", linemap[linenum]); + alpha = ld->args[1]; } - - // [RH] Set some new sidedef properties - len = (int)(sqrtf (dx*dx + dy*dy) + 0.5f); - light = dy == 0 ? level.WallHorizLight : - dx == 0 ? level.WallVertLight : 0; - - if (ld->sidenum[0] != NO_SIDE) + alpha = Scale(alpha, FRACUNIT, 255); + if (!ld->args[0]) { - sides[ld->sidenum[0]].linenum = linenum; - sides[ld->sidenum[0]].TexelLength = len; - sides[ld->sidenum[0]].Light = light; - } - if (ld->sidenum[1] != NO_SIDE) - { - sides[ld->sidenum[1]].linenum = linenum; - sides[ld->sidenum[1]].TexelLength = len; - sides[ld->sidenum[1]].Light = light; - } - - switch (ld->special) - { // killough 4/11/98: handle special types - int j; - int alpha; - - case TranslucentLine: // killough 4/11/98: translucent 2s textures - // [RH] Second arg controls how opaque it is. - alpha = sidetemp[ld->sidenum[0]].a.alpha; - if (alpha < 0) + ld->Alpha = alpha; + if (ld->args[2] == 1) { - alpha = Scale(ld->args[1], FRACUNIT, 255); - } - if (!ld->args[0]) - { - ld->Alpha = alpha; - if (ld->args[2] == 1) + sides[ld->sidenum[0]].Flags |= WALLF_ADDTRANS; + if (ld->sidenum[1] != NO_SIDE) { - sides[ld->sidenum[0]].Flags |= WALLF_ADDTRANS; - if (ld->sidenum[1] != NO_SIDE) - { - sides[ld->sidenum[1]].Flags |= WALLF_ADDTRANS; - } + sides[ld->sidenum[1]].Flags |= WALLF_ADDTRANS; } } - else + } + else + { + for (j = 0; j < numlines; j++) { - for (j = 0; j < numlines; j++) + if (lines[j].id == ld->args[0]) { - if (lines[j].id == ld->args[0]) + lines[j].Alpha = alpha; + if (lines[j].args[2] == 1) { - lines[j].Alpha = alpha; - if (lines[j].args[2] == 1) + sides[lines[j].sidenum[0]].Flags |= WALLF_ADDTRANS; + if (lines[j].sidenum[1] != NO_SIDE) { - sides[lines[j].sidenum[0]].Flags |= WALLF_ADDTRANS; - if (lines[j].sidenum[1] != NO_SIDE) - { - sides[lines[j].sidenum[1]].Flags |= WALLF_ADDTRANS; - } + sides[lines[j].sidenum[1]].Flags |= WALLF_ADDTRANS; } } } } - ld->special = 0; - break; } + ld->special = 0; + break; + } +} +// killough 4/4/98: delay using sidedefs until they are loaded +void P_FinishLoadingLineDefs () +{ + for (int i = 0; i < numlines; i++) + { + P_FinishLoadingLineDef(&lines[i], sidetemp[lines[i].sidenum[0]].a.alpha); } } @@ -1639,7 +1671,7 @@ void P_LoadLineDefs (MapData * map) numlines = lumplen / sizeof(maplinedef_t); lines = new line_t[numlines]; - linemap = new WORD[numlines]; + linemap.Resize(numlines); memset (lines, 0, numlines*sizeof(line_t)); mldf = new char[lumplen]; @@ -1720,7 +1752,7 @@ void P_LoadLineDefs2 (MapData * map) numlines = lumplen / sizeof(maplinedef2_t); lines = new line_t[numlines]; - linemap = new WORD[numlines]; + linemap.Resize(numlines); memset (lines, 0, numlines*sizeof(line_t)); mldf = new char[lumplen]; @@ -1778,6 +1810,7 @@ void P_LoadLineDefs2 (MapData * map) P_SetSideNum (&ld->sidenum[1], LittleShort(mld->sidenum[1])); P_AdjustLine (ld); + P_SetLineID(ld); P_SaveLineSpecial (ld); if (level.flags & LEVEL_CLIPMIDTEX) ld->flags |= ML_CLIP_MIDTEX; if (level.flags & LEVEL_WRAPMIDTEX) ld->flags |= ML_WRAP_MIDTEX; @@ -1847,6 +1880,11 @@ static void P_LoopSidedefs () { int i; + if (sidetemp == NULL) + { + sidetemp = new sidei_t[MAX(numvertexes, numsides)]; + } + for (i = 0; i < numvertexes; ++i) { sidetemp[i].b.first = NO_SIDE; @@ -1980,6 +2018,112 @@ int P_DetermineTranslucency (int lumpnum) return newcolor.r; } +void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, mapsidedef_t *msd, int special, int tag, short *alpha) +{ + char name[9]; + name[8] = 0; + + switch (special) + { + case Transfer_Heights: // variable colormap via 242 linedef + // [RH] The colormap num we get here isn't really a colormap, + // but a packed ARGB word for blending, so we also allow + // the blend to be specified directly by the texture names + // instead of figuring something out from the colormap. + if (sec != NULL) + { + SetTexture (sd, side_t::bottom, &sec->bottommap, msd->bottomtexture); + SetTexture (sd, side_t::mid, &sec->midmap, msd->midtexture); + SetTexture (sd, side_t::top, &sec->topmap, msd->toptexture); + } + break; + + case Static_Init: + // [RH] Set sector color and fog + // upper "texture" is light color + // lower "texture" is fog color + { + DWORD color, fog; + bool colorgood, foggood; + + SetTextureNoErr (sd, side_t::bottom, &fog, msd->bottomtexture, &foggood); + SetTextureNoErr (sd, side_t::top, &color, msd->toptexture, &colorgood); + strncpy (name, msd->midtexture, 8); + sd->SetTexture(side_t::mid, + TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable)); + + if (colorgood | foggood) + { + int s; + FDynamicColormap *colormap = NULL; + + for (s = 0; s < numsectors; s++) + { + if (sectors[s].tag == tag) + { + if (!colorgood) color = sectors[s].ColorMap->Color; + if (!foggood) fog = sectors[s].ColorMap->Fade; + if (colormap == NULL || + colormap->Color != color || + colormap->Fade != fog) + { + colormap = GetSpecialLights (color, fog, 0); + } + sectors[s].ColorMap = colormap; + } + } + } + } + break; + + case TranslucentLine: // killough 4/11/98: apply translucency to 2s normal texture + if (checktranmap) + { + int lumpnum; + + if (strnicmp ("TRANMAP", msd->midtexture, 8) == 0) + { + // The translator set the alpha argument already; no reason to do it again. + sd->SetTexture(side_t::mid, 0); + } + else if ((lumpnum = Wads.CheckNumForName (msd->midtexture)) > 0 && + Wads.LumpLength (lumpnum) == 65536) + { + *alpha = (short)P_DetermineTranslucency (lumpnum); + sd->SetTexture(side_t::mid, 0); + } + else + { + strncpy (name, msd->midtexture, 8); + sd->SetTexture(side_t::mid, + TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable)); + } + + strncpy (name, msd->toptexture, 8); + sd->SetTexture(side_t::top, TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable)); + + strncpy (name, msd->bottomtexture, 8); + sd->SetTexture(side_t::bottom, TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable)); + break; + } + // Fallthrough for Hexen maps is intentional + + default: // normal cases + strncpy (name, msd->midtexture, 8); + sd->SetTexture(side_t::mid, + TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable)); + + strncpy (name, msd->toptexture, 8); + sd->SetTexture(side_t::top, + TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable)); + + strncpy (name, msd->bottomtexture, 8); + sd->SetTexture(side_t::bottom, + TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable)); + break; + } +} + // killough 4/4/98: delay using texture names until // after linedefs are loaded, to allow overloading. // killough 5/3/98: reformatted, cleaned up @@ -1987,12 +2131,9 @@ int P_DetermineTranslucency (int lumpnum) void P_LoadSideDefs2 (MapData * map) { int i; - char name[9]; char * msdf = new char[map->Size(ML_SIDEDEFS)]; map->Read(ML_SIDEDEFS, msdf); - name[8] = 0; - for (i = 0; i < numsides; i++) { mapsidedef_t *msd = ((mapsidedef_t*)msdf) + sidetemp[i].a.map; @@ -2024,105 +2165,8 @@ void P_LoadSideDefs2 (MapData * map) { sd->sector = sec = §ors[LittleShort(msd->sector)]; } - switch (sidetemp[i].a.special) - { - case Transfer_Heights: // variable colormap via 242 linedef - // [RH] The colormap num we get here isn't really a colormap, - // but a packed ARGB word for blending, so we also allow - // the blend to be specified directly by the texture names - // instead of figuring something out from the colormap. - if (sec != NULL) - { - SetTexture (sd, side_t::bottom, &sec->bottommap, msd->bottomtexture); - SetTexture (sd, side_t::mid, &sec->midmap, msd->midtexture); - SetTexture (sd, side_t::top, &sec->topmap, msd->toptexture); - } - break; - - case Static_Init: - // [RH] Set sector color and fog - // upper "texture" is light color - // lower "texture" is fog color - { - DWORD color, fog; - bool colorgood, foggood; - - SetTextureNoErr (sd, side_t::bottom, &fog, msd->bottomtexture, &foggood); - SetTextureNoErr (sd, side_t::top, &color, msd->toptexture, &colorgood); - strncpy (name, msd->midtexture, 8); - sd->SetTexture(side_t::mid, - TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable)); - - if (colorgood | foggood) - { - int s; - FDynamicColormap *colormap = NULL; - - for (s = 0; s < numsectors; s++) - { - if (sectors[s].tag == sidetemp[i].a.tag) - { - if (!colorgood) color = sectors[s].ColorMap->Color; - if (!foggood) fog = sectors[s].ColorMap->Fade; - if (colormap == NULL || - colormap->Color != color || - colormap->Fade != fog) - { - colormap = GetSpecialLights (color, fog, 0); - } - sectors[s].ColorMap = colormap; - } - } - } - } - break; - - case TranslucentLine: // killough 4/11/98: apply translucency to 2s normal texture - if (!map->HasBehavior) - { - int lumpnum; - - if (strnicmp ("TRANMAP", msd->midtexture, 8) == 0) - { - // The translator set the alpha argument already; no reason to do it again. - sd->SetTexture(side_t::mid, 0); - } - else if ((lumpnum = Wads.CheckNumForName (msd->midtexture)) > 0 && - Wads.LumpLength (lumpnum) == 65536) - { - sidetemp[i].a.alpha = P_DetermineTranslucency (lumpnum); - sd->SetTexture(side_t::mid, 0); - } - else - { - strncpy (name, msd->midtexture, 8); - sd->SetTexture(side_t::mid, - TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable)); - } - - strncpy (name, msd->toptexture, 8); - sd->SetTexture(side_t::top, TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable)); - - strncpy (name, msd->bottomtexture, 8); - sd->SetTexture(side_t::bottom, TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable)); - break; - } - // Fallthrough for Hexen maps is intentional - - default: // normal cases - strncpy (name, msd->midtexture, 8); - sd->SetTexture(side_t::mid, - TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable)); - - strncpy (name, msd->toptexture, 8); - sd->SetTexture(side_t::top, - TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable)); - - strncpy (name, msd->bottomtexture, 8); - sd->SetTexture(side_t::bottom, - TexMan.GetTexture (name, FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable)); - break; - } + P_ProcessSideTextures(!map->HasBehavior, sd, sec, msd, + sidetemp[i].a.special, sidetemp[i].a.tag, &sidetemp[i].a.alpha); } delete[] msdf; } @@ -3192,55 +3236,67 @@ void P_SetupLevel (char *lumpname, int position) } else { - // Doom format maps get strict monster activation unless the mapinfo + // We need translators only for Doom format maps. + // If none has been defined in a map use the game's default. + P_LoadTranslator(level.info->translator != NULL? (const char *)level.info->translator : gameinfo.translator); + } + + if (!map->HasBehavior || map->isText) + { + // Doom format and UDMF text maps get strict monster activation unless the mapinfo // specifies differently. if (!(level.flags & LEVEL_LAXACTIVATIONMAPINFO)) { level.flags &= ~LEVEL_LAXMONSTERACTIVATION; } - - // We need translators only for Doom format maps. - // If none has been defined in a map use the game's default. - P_LoadTranslator(level.info->translator != NULL? (const char *)level.info->translator : gameinfo.translator); } + FBehavior::StaticLoadDefaultModules (); P_LoadStrifeConversations (map, lumpname); - clock (times[0]); - P_LoadVertexes (map); - unclock (times[0]); - - // Check for maps without any BSP data at all (e.g. SLIGE) - clock (times[1]); - P_LoadSectors (map); - unclock (times[1]); + if (!map->isText) + { + clock (times[0]); + P_LoadVertexes (map); + unclock (times[0]); + + // Check for maps without any BSP data at all (e.g. SLIGE) + clock (times[1]); + P_LoadSectors (map); + unclock (times[1]); - clock (times[2]); - P_LoadSideDefs (map); - unclock (times[2]); + clock (times[2]); + P_LoadSideDefs (map); + unclock (times[2]); - clock (times[3]); - if (!map->HasBehavior) - P_LoadLineDefs (map); + clock (times[3]); + if (!map->HasBehavior) + P_LoadLineDefs (map); + else + P_LoadLineDefs2 (map); // [RH] Load Hexen-style linedefs + unclock (times[3]); + + clock (times[4]); + P_LoadSideDefs2 (map); + unclock (times[4]); + + clock (times[5]); + P_FinishLoadingLineDefs (); + unclock (times[5]); + + } else - P_LoadLineDefs2 (map); // [RH] Load Hexen-style linedefs - unclock (times[3]); - - clock (times[4]); - P_LoadSideDefs2 (map); - unclock (times[4]); - - clock (times[5]); - P_FinishLoadingLineDefs (); - unclock (times[5]); + { + P_ParseTextMap(map); + } clock (times[6]); P_LoopSidedefs (); unclock (times[6]); - delete[] linemap; - linemap = NULL; + linemap.Clear(); + linemap.ShrinkToFit(); } else { @@ -3295,7 +3351,7 @@ void P_SetupLevel (char *lumpname, int position) } } } - else + else if (!map->isText) // regular nodes are not supported for text maps { clock (times[7]); P_LoadSubsectors (map); @@ -3309,6 +3365,7 @@ void P_SetupLevel (char *lumpname, int position) if (!ForceNodeBuild) P_LoadSegs (map); unclock (times[9]); } + else ForceNodeBuild = true; } if (ForceNodeBuild) @@ -3363,11 +3420,16 @@ void P_SetupLevel (char *lumpname, int position) if (!buildmap) { - clock (times[14]); - if (!map->HasBehavior) - P_LoadThings (map, position); - else - P_LoadThings2 (map, position); // [RH] Load Hexen-style things + if (!map->isText) + { + clock (times[14]); + if (!map->HasBehavior) + P_LoadThings (map, position); + else + P_LoadThings2 (map, position); // [RH] Load Hexen-style things + } + else P_SpawnTextThings(position); + for (i = 0; i < MAXPLAYERS; ++i) { if (playeringame[i] && players[i].mo != NULL) diff --git a/src/p_setup.h b/src/p_setup.h index aeb4254aa..4e22a7cc2 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -34,6 +34,7 @@ struct MapData bool HasBehavior; bool CloseOnDestruct; bool Encrypted; + bool isText; int lumpnum; FileReader * file; @@ -45,6 +46,7 @@ struct MapData HasBehavior = false; CloseOnDestruct = true; Encrypted = false; + isText = false; } ~MapData() diff --git a/src/p_spec.cpp b/src/p_spec.cpp index e0ae65cc6..c2a6bdb69 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -280,17 +280,27 @@ bool P_TestActivateLine (line_t *line, AActor *mo, int side, int activationType) { if (mo->flags2 & MF2_NOTELEPORT) return false; } - if ((lineActivation & activationType) == 0 && - (activationType != SPAC_MCross || lineActivation != SPAC_Cross)) - { - return false; - } - if (activationType == SPAC_Use) { if (!P_CheckSwitchRange(mo, line, side)) return false; } + if ((lineActivation & activationType) == 0) + { + if (activationType == SPAC_Use && (lineActivation & SPAC_MUse) && !mo->player && mo->flags4 & MF4_CANUSEWALLS) + { + return true; + } + if (activationType == SPAC_Push && (lineActivation & SPAC_MPush) && !mo->player && mo->flags2 & MF2_PUSHWALL) + { + return true; + } + if (activationType != SPAC_MCross || lineActivation != SPAC_Cross) + { + return false; + } + } + if (mo && !mo->player && !(mo->flags & MF_MISSILE) && !(line->flags & ML_MONSTERSCANACTIVATE) && diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp new file mode 100644 index 000000000..d4a322be7 --- /dev/null +++ b/src/p_udmf.cpp @@ -0,0 +1,695 @@ +/* +** p_udmf.cpp +** +** UDMF text map parser +** +**--------------------------------------------------------------------------- +** Copyright 2008 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "r_data.h" +#include "p_setup.h" +#include "sc_man.h" +#include "vectors.h" +#include "p_lnspec.h" +#include "templates.h" +#include "i_system.h" + +extern void P_TranslateLineDef (line_t *ld, maplinedef_t *mld); +extern int P_TranslateSectorSpecial (int); +void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, mapsidedef_t *msd, int special, int tag, short *alpha); +void P_AdjustLine (line_t *ld); +void P_FinishLoadingLineDef(line_t *ld, int alpha); +void SpawnMapThing(int index, FMapThing *mt, int position); +extern bool ForceNodeBuild; +extern TArray MapThingsConverted; +extern TArray linemap; + +struct UDMFParser +{ + FScanner sc; + FName namespc; + bool isTranslated; + bool isExtended; + + TArray ParsedLines; + TArray ParsedSides; + TArray ParsedSideTextures; + TArray ParsedSectors; + TArray ParsedVertices; + + FDynamicColormap *fogMap, *normMap; + + UDMFParser() + { + linemap.Clear(); + fogMap = normMap = NULL; + } + + void Flag(DWORD &value, int mask, const FString &svalue) + { + if (!svalue.CompareNoCase("true")) + { + value |= mask; + } + else + { + value &= ~mask; + } + } + + void ParseThing(FMapThing *th) + { + memset(th, 0, sizeof(*th)); + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + FName key = sc.String; + sc.MustGetStringName("="); + sc.MustGetString(); + FString value = sc.String; + sc.MustGetStringName(";"); + switch(key) + { + case NAME_TID: + th->thingid = (WORD)strtol(value, NULL, 0); + break; + case NAME_X: + th->x = FLOAT2FIXED(strtod(value, NULL)); + break; + case NAME_Y: + th->y = FLOAT2FIXED(strtod(value, NULL)); + break; + case NAME_Height: + th->z = FLOAT2FIXED(strtod(value, NULL)); + break; + case NAME_Angle: + th->angle = (short)strtol(value, NULL, 0); + break; + case NAME_Type: + th->type = (short)strtol(value, NULL, 0); + break; + case NAME_Special: + th->special = (short)strtol(value, NULL, 0); + break; + case NAME_Arg0: + case NAME_Arg1: + case NAME_Arg2: + case NAME_Arg3: + case NAME_Arg4: + th->args[int(key)-int(NAME_Arg0)] = strtol(value, NULL, 0); + break; + case NAME_Skill1: + case NAME_Skill2: + case NAME_Skill3: + case NAME_Skill4: + case NAME_Skill5: + case NAME_Skill6: + case NAME_Skill7: + case NAME_Skill8: + case NAME_Skill9: + case NAME_Skill10: + case NAME_Skill11: + case NAME_Skill12: + case NAME_Skill13: + case NAME_Skill14: + case NAME_Skill15: + case NAME_Skill16: + if (!value.CompareNoCase("true")) th->SkillFilter |= (1<<(int(key)-NAME_Skill1)); + else th->SkillFilter &= ~(1<<(int(key)-NAME_Skill1)); + break; + + case NAME_Class0: + case NAME_Class1: + case NAME_Class2: + case NAME_Class3: + case NAME_Class4: + case NAME_Class5: + case NAME_Class6: + case NAME_Class7: + case NAME_Class8: + case NAME_Class9: + case NAME_Class10: + case NAME_Class11: + case NAME_Class12: + case NAME_Class13: + case NAME_Class14: + case NAME_Class15: + case NAME_Class16: + if (!value.CompareNoCase("true")) th->ClassFilter |= (1<<(int(key)-NAME_Class1)); + else th->SkillFilter &= ~(1<<(int(key)-NAME_Class1)); + break; + + case NAME_Ambush: + Flag(th->flags, MTF_AMBUSH, value); break; + case NAME_Dormant: + Flag(th->flags, MTF_DORMANT, value); break; + case NAME_Single: + Flag(th->flags, MTF_SINGLE, value); break; + case NAME_Coop: + Flag(th->flags, MTF_COOPERATIVE, value); break; + case NAME_Dm: + Flag(th->flags, MTF_DEATHMATCH, value); break; + case NAME_Translucent: + Flag(th->flags, MTF_SHADOW, value); break; + case NAME_Invisible: + Flag(th->flags, MTF_ALTSHADOW, value); break; + case NAME_Friend: + case NAME_Strifeally: + Flag(th->flags, MTF_FRIENDLY, value); break; + case NAME_Standing: + Flag(th->flags, MTF_STANDSTILL, value); break; + + default: + break; + } + } + if (isTranslated) + { + // NOTE: Handling of this is undefined in the UDMF spec yet! + maplinedef_t mld; + line_t ld; + + mld.flags = 0; + mld.special = th->special; + mld.tag = th->args[0]; + P_TranslateLineDef(&ld, &mld); + th->special = ld.special; + memcpy(th->args, ld.args, sizeof (ld.args)); + } + } + + void ParseLinedef(line_t *ld) + { + bool passuse = false; + + memset(ld, 0, sizeof(*ld)); + ld->Alpha = FRACUNIT; + ld->id = -1; + ld->sidenum[0] = ld->sidenum[1] = NO_SIDE; + if (level.flags & LEVEL_CLIPMIDTEX) ld->flags |= ML_CLIP_MIDTEX; + if (level.flags & LEVEL_WRAPMIDTEX) ld->flags |= ML_WRAP_MIDTEX; + if (level.flags & LEVEL_CHECKSWITCHRANGE) ld->flags |= ML_CHECKSWITCHRANGE; + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + FName key = sc.String; + sc.MustGetStringName("="); + sc.MustGetString(); + FString value = sc.String; + sc.MustGetStringName(";"); + switch(key) + { + case NAME_V1: + ld->v1 = (vertex_t*)(intptr_t)strtol(value, NULL, 0); // must be relocated later + break; + case NAME_V2: + ld->v2 = (vertex_t*)(intptr_t)strtol(value, NULL, 0); // must be relocated later + break; + case NAME_Special: + ld->special = strtol(value, NULL, 0); + break; + case NAME_Id: + ld->id = strtol(value, NULL, 0); + break; + case NAME_Sidefront: + ld->sidenum[0] = strtol(value, NULL, 0); + break; + case NAME_Sideback: + ld->sidenum[1] = strtol(value, NULL, 0); + break; + case NAME_Arg0: + case NAME_Arg1: + case NAME_Arg2: + case NAME_Arg3: + case NAME_Arg4: + ld->args[int(key)-int(NAME_Arg0)] = strtol(value, NULL, 0); + break; + case NAME_Blocking: + Flag(ld->flags, ML_BLOCKING, value); break; + case NAME_Blockmonsters: + Flag(ld->flags, ML_BLOCKMONSTERS, value); break; + case NAME_Twosided: + Flag(ld->flags, ML_TWOSIDED, value); break; + case NAME_Dontpegtop: + Flag(ld->flags, ML_DONTPEGTOP, value); break; + case NAME_Dontpegbottom: + Flag(ld->flags, ML_DONTPEGBOTTOM, value); break; + case NAME_Secret: + Flag(ld->flags, ML_SECRET, value); break; + case NAME_Soundblock: + Flag(ld->flags, ML_SOUNDBLOCK, value); break; + case NAME_Dontdraw: + Flag(ld->flags, ML_DONTDRAW, value); break; + case NAME_Mapped: + Flag(ld->flags, ML_MAPPED, value); break; + case NAME_Monsteractivate: + Flag(ld->flags, ML_MONSTERSCANACTIVATE, value); break; + case NAME_Blockplayers: + if (isExtended) Flag(ld->flags, ML_BLOCK_PLAYERS, value); break; + case NAME_Blockeverything: + if (isExtended) Flag(ld->flags, ML_BLOCKEVERYTHING, value); break; + case NAME_Zoneboundary: + if (isExtended) Flag(ld->flags, ML_ZONEBOUNDARY, value); break; + case NAME_Jumpover: + if (isExtended || namespc == NAME_Strife) Flag(ld->flags, ML_RAILING, value); break; + case NAME_Blockfloating: + if (isExtended || namespc == NAME_Strife) Flag(ld->flags, ML_BLOCK_FLOATERS, value); break; + case NAME_Clipmidtex: + if (isExtended) Flag(ld->flags, ML_CLIP_MIDTEX, value); break; + case NAME_Wrapmidtex: + if (isExtended) Flag(ld->flags, ML_WRAP_MIDTEX, value); break; + case NAME_Midtex3d: + if (isExtended) Flag(ld->flags, ML_3DMIDTEX, value); break; + case NAME_Checkswitchrange: + if (isExtended) Flag(ld->flags, ML_CHECKSWITCHRANGE, value); break; + case NAME_Firstsideonly: + if (isExtended) Flag(ld->flags, ML_FIRSTSIDEONLY, value); break; + case NAME_Transparent: + ld->Alpha = !value.CompareNoCase("true")? FRACUNIT*3/4 : FRACUNIT; break; + case NAME_Passuse: + passuse = !value.CompareNoCase("true"); + case NAME_Playercross: + if (isExtended) Flag(ld->activation, SPAC_Cross, value); break; + case NAME_Playeruse: + if (isExtended) Flag(ld->activation, SPAC_Use, value); break; + case NAME_Monstercross: + if (isExtended) Flag(ld->activation, SPAC_MCross, value); break; + case NAME_Impact: + if (isExtended) Flag(ld->activation, SPAC_Impact, value); break; + case NAME_Playerpush: + if (isExtended) Flag(ld->activation, SPAC_Push, value); break; + case NAME_Missilecross: + if (isExtended) Flag(ld->activation, SPAC_PCross, value); break; + case NAME_Monsteruse: + if (isExtended) Flag(ld->activation, SPAC_MUse, value); break; + case NAME_Monsterpush: + if (isExtended) Flag(ld->activation, SPAC_MPush, value); break; + + default: + break; + } + } + if (isTranslated) + { + } + else + { + int saved = ld->flags; + + maplinedef_t mld; + memset(&mld, 0, sizeof(mld)); + mld.special = ld->special; + mld.tag = ld->id; + P_TranslateLineDef(ld, &mld); + ld->flags = saved | (ld->flags&(ML_MONSTERSCANACTIVATE|ML_REPEAT_SPECIAL|ML_FIRSTSIDEONLY)); + } + if (passuse && (ld->activation & SPAC_Use)) + { + ld->activation = (ld->activation & ~SPAC_Use) | SPAC_UseThrough; + } + } + + void ParseSidedef(side_t *sd, mapsidedef_t *sdt) + { + fixed_t texofs[2]={0,0}; + + memset(sd, 0, sizeof(*sd)); + strncpy(sdt->bottomtexture, "-", 8); + strncpy(sdt->toptexture, "-", 8); + strncpy(sdt->midtexture, "-", 8); + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + FName key = sc.String; + sc.MustGetStringName("="); + sc.MustGetString(); + FString value = sc.String; + sc.MustGetStringName(";"); + switch(key) + { + case NAME_Offsetx: + texofs[0] = strtol(value, NULL, 0) << FRACBITS; + break; + + case NAME_Offsety: + texofs[1] = strtol(value, NULL, 0) << FRACBITS; + break; + + case NAME_Texturetop: + strncpy(sdt->toptexture, value, 8); + break; + + case NAME_Texturebottom: + strncpy(sdt->bottomtexture, value, 8); + break; + + case NAME_Texturemiddle: + strncpy(sdt->midtexture, value, 8); + break; + + case NAME_Sector: + sd->sector = (sector_t*)(intptr_t)strtol(value, NULL, 0); + break; + + default: + break; + } + } + // initialization of these is delayed to allow separate offsets and add them with the global ones. + sd->AddTextureXOffset(side_t::top, texofs[0]); + sd->AddTextureXOffset(side_t::mid, texofs[0]); + sd->AddTextureXOffset(side_t::bottom, texofs[0]); + sd->AddTextureYOffset(side_t::top, texofs[1]); + sd->AddTextureYOffset(side_t::mid, texofs[1]); + sd->AddTextureYOffset(side_t::bottom, texofs[1]); + } + + void ParseSector(sector_t *sec) + { + memset(sec, 0, sizeof(*sec)); + sec->lightlevel = 255; + sec->floor_xscale = FRACUNIT; // [RH] floor and ceiling scaling + sec->floor_yscale = FRACUNIT; + sec->ceiling_xscale = FRACUNIT; + sec->ceiling_yscale = FRACUNIT; + sec->oldspecial = !!(sec->special&SECRET_MASK); + sec->thinglist = NULL; + sec->touching_thinglist = NULL; // phares 3/14/98 + sec->seqType = (level.flags & LEVEL_SNDSEQTOTALCTRL)? 0:-1; + sec->nextsec = -1; //jff 2/26/98 add fields to support locking out + sec->prevsec = -1; // stair retriggering until build completes + sec->heightsec = NULL; // sector used to get floor and ceiling height + // killough 3/7/98: end changes + + sec->gravity = 1.f; // [RH] Default sector gravity of 1.0 + sec->ZoneNumber = 0xFFFF; + + // killough 8/28/98: initialize all sectors to normal friction + sec->friction = ORIG_FRICTION; + sec->movefactor = ORIG_FRICTION_FACTOR; + + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + FName key = sc.String; + sc.MustGetStringName("="); + sc.MustGetString(); + FString value = sc.String; + sc.MustGetStringName(";"); + switch(key) + { + case NAME_Heightfloor: + sec->floortexz = strtol(value, NULL, 0) << FRACBITS; + break; + + case NAME_Heightceiling: + sec->ceilingtexz = strtol(value, NULL, 0) << FRACBITS; + break; + + case NAME_Texturefloor: + sec->floorpic = TexMan.GetTexture (value, FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable); + break; + + case NAME_Textureceiling: + sec->ceilingpic = TexMan.GetTexture (value, FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable); + break; + + case NAME_Lightlevel: + sec->lightlevel = (BYTE)clamp(strtol(value, NULL, 0), 0, 255); + break; + + case NAME_Special: + sec->special = (short)strtol(value, NULL, 0); + if (isTranslated) sec->special = P_TranslateSectorSpecial(sec->special); + break; + + case NAME_Tag: + sec->tag = (short)strtol(value, NULL, 0); + break; + + default: + break; + } + } + + sec->floorplane.d = -sec->floortexz; + sec->floorplane.c = FRACUNIT; + sec->floorplane.ic = FRACUNIT; + sec->ceilingplane.d = sec->ceilingtexz; + sec->ceilingplane.c = -FRACUNIT; + sec->ceilingplane.ic = -FRACUNIT; + + // [RH] Sectors default to white light with the default fade. + // If they are outside (have a sky ceiling), they use the outside fog. + if (level.outsidefog != 0xff000000 && (sec->ceilingpic == skyflatnum || (sec->special&0xff) == Sector_Outside)) + { + if (fogMap == NULL) + fogMap = GetSpecialLights (PalEntry (255,255,255), level.outsidefog, 0); + sec->ColorMap = fogMap; + } + else + { + if (normMap == NULL) + normMap = GetSpecialLights (PalEntry (255,255,255), level.fadeto, NormalLight.Desaturate); + sec->ColorMap = normMap; + } + } + + void ParseVertex(vertex_t *vt) + { + vt->x = vt->y = 0; + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + FName key = sc.String; + sc.MustGetStringName("="); + sc.MustGetString(); + FString value = sc.String; + sc.MustGetStringName(";"); + switch(key) + { + case NAME_X: + vt->x = FLOAT2FIXED(strtod(value, NULL)); + break; + case NAME_Y: + vt->y = FLOAT2FIXED(strtod(value, NULL)); + break; + default: + break; + } + } + } + + void ProcessLineDefs() + { + int sidecount = 0; + for(unsigned i = 0, skipped = 0; i < ParsedLines.Size();) + { + // Relocate the vertices + intptr_t v1i = intptr_t(ParsedLines[i].v1); + intptr_t v2i = intptr_t(ParsedLines[i].v2); + + if (v1i >= numvertexes || v2i >= numvertexes || v1i < 0 || v2i < 0) + { + I_Error ("Line %d has invalid vertices: %d and/or %d.\nThe map only contains %d vertices.", i+skipped, v1i, v2i, numvertexes); + } + else if (v1i == v2i || + (vertexes[v1i].x == vertexes[v2i].x && vertexes[v1i].y == vertexes[v2i].y)) + { + Printf ("Removing 0-length line %d\n", i+skipped); + ParsedLines.Delete(i); + ForceNodeBuild = true; + skipped++; + } + else + { + ParsedLines[i].v1 = &vertexes[v1i]; + ParsedLines[i].v2 = &vertexes[v2i]; + + if (ParsedLines[i].sidenum[0] != NO_SIDE) + sidecount++; + if (ParsedLines[i].sidenum[1] != NO_SIDE) + sidecount++; + linemap.Push(i+skipped); + i++; + } + } + numlines = ParsedLines.Size(); + numsides = sidecount; + lines = new line_t[numlines]; + sides = new side_t[numsides]; + + for(int line = 0, side = 0; line < numlines; line++) + { + short tempalpha[2] = {-1,-1}; + + lines[line] = ParsedLines[line]; + + for(int sd = 0; sd < 2; sd++) + { + if (lines[line].sidenum[sd] != NO_SIDE) + { + int mapside = lines[line].sidenum[sd]; + sides[side] = ParsedSides[mapside]; + sides[side].linenum = line; + sides[side].sector = §ors[intptr_t(sides[side].sector)]; + lines[line].sidenum[sd] = side; + + P_ProcessSideTextures(!isExtended, &sides[side], sides[side].sector, &ParsedSideTextures[mapside], + lines[line].special, lines[line].args[0], &tempalpha[sd]); + + side++; + } + } + + P_AdjustLine(&lines[line]); + P_FinishLoadingLineDef(&lines[line], tempalpha[0]); + } + } + + void ParseTextMap(MapData *map) + { + char *buffer = new char[map->Size(ML_TEXTMAP)]; + + isTranslated = true; + isExtended = false; + + map->Read(ML_TEXTMAP, buffer); + sc.OpenMem(Wads.GetLumpFullName(map->lumpnum), buffer, map->Size(ML_TEXTMAP)); + sc.SetCMode(true); + while (sc.GetString()) + { + if (sc.Compare("namespace")) + { + sc.MustGetStringName("="); + sc.MustGetString(); + namespc = sc.String; + if (namespc == NAME_ZDoom) + { + isTranslated = false; + isExtended = true; + } + else if (namespc == NAME_Hexen) + { + isTranslated = false; + } + else if (namespc == NAME_ZDoomTranslated) + { + isExtended = true; + } + else if (namespc == NAME_Doom) + { + } + else if (namespc == NAME_Heretic) + { + } + else if (namespc == NAME_Strife) + { + } + else + { + sc.ScriptError("Unknown namespace %s", sc.String); + } + sc.MustGetStringName(";"); + } + else if (sc.Compare("thing")) + { + FMapThing th; + ParseThing(&th); + MapThingsConverted.Push(th); + } + else if (sc.Compare("linedef")) + { + line_t li; + ParseLinedef(&li); + ParsedLines.Push(li); + } + else if (sc.Compare("sidedef")) + { + side_t si; + mapsidedef_t st; + ParseSidedef(&si, &st); + ParsedSides.Push(si); + ParsedSideTextures.Push(st); + } + else if (sc.Compare("sector")) + { + sector_t sec; + ParseSector(&sec); + ParsedSectors.Push(sec); + } + else if (sc.Compare("vertex")) + { + vertex_t vt; + ParseVertex(&vt); + ParsedVertices.Push(vt); + } + } + + // Create the real vertices + numvertexes = ParsedVertices.Size(); + vertexes = new vertex_t[numvertexes]; + memcpy(vertexes, &ParsedVertices[0], numvertexes * sizeof(*vertexes)); + + // Create the real sectors + numsectors = ParsedSectors.Size(); + sectors = new sector_t[numsectors]; + sectors[0].e = new extsector_t[numsectors]; + memcpy(sectors, &ParsedSectors[0], numsectors * sizeof(*sectors)); + for(int i = 0; i < numsectors; i++) + { + sectors[i].e = §ors[0].e[i]; + } + + // Create the real linedefs and decompress the sidedefs + ProcessLineDefs(); + + } +}; + +void P_ParseTextMap(MapData *map) +{ + UDMFParser parse; + + parse.ParseTextMap(map); +} + +void P_SpawnTextThings(int position) +{ + for(unsigned i=0; ifloorsector->Flags & SECF_NOFALLINGDAMAGE) + return; mom = abs (actor->momz); diff --git a/src/p_xlat.cpp b/src/p_xlat.cpp index dee30cfea..440ba7e3e 100644 --- a/src/p_xlat.cpp +++ b/src/p_xlat.cpp @@ -63,7 +63,6 @@ typedef enum void P_TranslateLineDef (line_t *ld, maplinedef_t *mld) { - static FMemLump tlatebase; unsigned short special = (unsigned short) LittleShort(mld->special); short tag = LittleShort(mld->tag); DWORD flags = LittleShort(mld->flags); diff --git a/src/r_defs.h b/src/r_defs.h index 39ba1bb8d..bd86106a9 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -233,10 +233,9 @@ enum SECF_ABSLIGHTING = 1 // floor/ceiling light is absolute, not relative }; -// Misc sector flags +// Internal sector flags enum { - SECF_SILENT = 1, // actors in sector make no noise SECF_FAKEFLOORONLY = 2, // when used as heightsec in R_FakeFlat, only copies floor SECF_CLIPFAKEPLANES = 4, // as a heightsec, clip planes to target sector's planes SECF_NOFAKELIGHT = 8, // heightsec does not change lighting @@ -247,6 +246,12 @@ enum SECF_DRAWN = 128, // sector has been drawn at least once }; +enum +{ + SECF_SILENT = 1, // actors in sector make no noise + SECF_NOFALLINGDAMAGE= 2, // No falling damage in this sector +}; + struct FDynamicColormap; struct FLightStack @@ -412,7 +417,8 @@ struct sector_t short mod; // [RH] Means-of-death for applied damage WORD ZoneNumber; // [RH] Zone this sector belongs to - WORD MoreFlags; // [RH] Misc sector flags + WORD MoreFlags; // [RH] Internal sector flags + DWORD Flags; // Sector flags // [RH] Action specials for sectors. Like Skull Tag, but more // flexible in a Bloody way. SecActTarget forms a list of actors diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 6da30f509..efe879679 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -855,7 +855,7 @@ void S_SoundID (int channel, int sound_id, float volume, int attenuation) void S_SoundID (AActor *ent, int channel, int sound_id, float volume, int attenuation) { - if (ent->Sector->MoreFlags & SECF_SILENT) + if (ent->Sector->Flags & SECF_SILENT) return; S_StartSound (&ent->x, ent, channel, sound_id, volume, SELECT_ATTEN(attenuation)); } diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 6ede2bb04..01dccf5e5 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -617,9 +617,13 @@ void FTextureManager::LoadHiresTex(int wadnum) newtex->SetScaledSize(width, height); memcpy(newtex->Name, src, sizeof(newtex->Name)); - int oldtex = TexMan.CheckForTexture(src, FTexture::TEX_Override); - if (oldtex>=0) TexMan.ReplaceTexture(oldtex, newtex, true); - else TexMan.AddTexture(newtex); + int oldtex = TexMan.CheckForTexture(src, FTexture::TEX_MiscPatch); + if (oldtex>=0) + { + ReplaceTexture(oldtex, newtex, true); + newtex->UseType = FTexture::TEX_Override; + } + else AddTexture(newtex); } } //else Printf("Unable to define hires texture '%s'\n", tex->Name); diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index c96991dfd..17f119820 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -2303,15 +2303,15 @@ static void PlayerSpawnClass (FScanner &sc, APlayerPawn *defaults, Baggage &bag) if (sc.Compare ("Any")) defaults->SpawnMask = 0; else if (sc.Compare ("Fighter")) - defaults->SpawnMask |= MTF_FIGHTER; + defaults->SpawnMask |= 1; else if (sc.Compare ("Cleric")) - defaults->SpawnMask |= MTF_CLERIC; + defaults->SpawnMask |= 2; else if (sc.Compare ("Mage")) - defaults->SpawnMask |= MTF_MAGE; + defaults->SpawnMask |= 4; else if (IsNum(sc.String)) { int val = strtol(sc.String, NULL, 0); - defaults->SpawnMask = (val*MTF_FIGHTER) & (MTF_FIGHTER|MTF_CLERIC|MTF_MAGE); + if (val > 0) defaults->SpawnMask |= 1<<(val-1); } } diff --git a/src/version.h b/src/version.h index 2e668f261..05f83ef2a 100644 --- a/src/version.h +++ b/src/version.h @@ -75,7 +75,7 @@ // SAVESIG should match SAVEVER. // MINSAVEVER is the minimum level snapshot version that can be loaded. -#define MINSAVEVER 954 +#define MINSAVEVER 964 #if SVN_REVISION_NUMBER < MINSAVEVER // Never write a savegame with a version lower than what we need diff --git a/wadsrc/mapinfo/doomcommon.txt b/wadsrc/mapinfo/doomcommon.txt index 6ade281bc..5a8fdd104 100644 --- a/wadsrc/mapinfo/doomcommon.txt +++ b/wadsrc/mapinfo/doomcommon.txt @@ -2,7 +2,7 @@ skill baby AmmoFactor 2 DamageFactor 0.5 EasyBossBrain - SpawnFilter "Easy" + SpawnFilter "Baby" PicName "M_JKILL" Key i @@ -27,7 +27,7 @@ skill nightmare FastMonsters DisableCheats RespawnTime 12 - SpawnFilter "Hard" + SpawnFilter "Nightmare" PicName "M_NMARE" MustConfirm Key n diff --git a/wadsrc/mapinfo/heretic.txt b/wadsrc/mapinfo/heretic.txt index 0bd8a7889..7050c9f87 100644 --- a/wadsrc/mapinfo/heretic.txt +++ b/wadsrc/mapinfo/heretic.txt @@ -5,7 +5,7 @@ skill baby DoubleAmmoFactor 1.5 DamageFactor 0.5 EasyBossBrain - SpawnFilter "Easy" + SpawnFilter "Baby" Name "$MNU_WETNURSE" skill easy @@ -28,7 +28,7 @@ skill nightmare DoubleAmmoFactor 1.5 FastMonsters DisableCheats - SpawnFilter "Hard" + SpawnFilter "Nightmare" Name "$MNU_BLACKPLAGUE" clearepisodes diff --git a/wadsrc/mapinfo/hexen.txt b/wadsrc/mapinfo/hexen.txt index 6a621f6dc..a8a6806b0 100644 --- a/wadsrc/mapinfo/hexen.txt +++ b/wadsrc/mapinfo/hexen.txt @@ -6,7 +6,7 @@ skill baby DoubleAmmoFactor 1.5 DamageFactor 0.5 EasyBossBrain - SpawnFilter "Easy" + SpawnFilter "Baby" Name "$MNU_WETNURSE" PlayerClassName "fighter" "$MNU_SQUIRE" PlayerClassName "cleric" "$MNU_ALTARBOY" @@ -42,7 +42,7 @@ skill nightmare DoubleAmmoFactor 1.5 FastMonsters DisableCheats - SpawnFilter "Hard" + SpawnFilter "Nightmare" Name "$MNU_BLACKPLAGUE" PlayerClassName "fighter" "$MNU_TITAN" PlayerClassName "cleric" "$MNU_POPE" diff --git a/wadsrc/mapinfo/strife.txt b/wadsrc/mapinfo/strife.txt index 091f45312..91dcccc74 100644 --- a/wadsrc/mapinfo/strife.txt +++ b/wadsrc/mapinfo/strife.txt @@ -4,7 +4,7 @@ skill baby AmmoFactor 2 DamageFactor 0.5 EasyBossBrain - SpawnFilter "Easy" + SpawnFilter "Baby" PicName "M_JKILL" Key t @@ -28,7 +28,7 @@ skill nightmare FastMonsters DisableCheats RespawnTime 16 - SpawnFilter "Hard" + SpawnFilter "Nightmare" PicName "M_NMARE" Key b diff --git a/zdoom.vcproj b/zdoom.vcproj index 8f2a5c58b..790787339 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + @@ -926,16 +930,6 @@ Outputs=""src/$(InputName).h"" /> - - - @@ -946,6 +940,16 @@ Outputs=""src/$(InputName).h"" /> + + + @@ -1540,6 +1544,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - @@ -1928,6 +1924,14 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + - - - @@ -2802,6 +2798,14 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> + + + @@ -3068,7 +3072,7 @@ />