void ParseLinedef(line_t *ld, int index) { bool passuse = false; bool strifetrans = false; bool strifetrans2 = false; FString arg0str, arg1str; int lineid; // forZDoomTranslated namespace FString tagstring; memset(ld, 0, sizeof(*ld)); ld->Alpha = FRACUNIT; ld->sidedef[0] = ld->sidedef[1] = NULL; if (level.flags2 & LEVEL2_CLIPMIDTEX) ld->flags |= ML_CLIP_MIDTEX; if (level.flags2 & LEVEL2_WRAPMIDTEX) ld->flags |= ML_WRAP_MIDTEX; if (level.flags2 & LEVEL2_CHECKSWITCHRANGE) ld->flags |= ML_CHECKSWITCHRANGE; sc.MustGetToken('{'); while (!sc.CheckToken('}')) { FName key = ParseKey(); // This switch contains all keys of the UDMF base spec switch(key) { case NAME_V1: ld->v1 = (vertex_t*)(intptr_t)CheckInt(key); // must be relocated later continue; case NAME_V2: ld->v2 = (vertex_t*)(intptr_t)CheckInt(key); // must be relocated later continue; case NAME_Special: ld->special = CheckInt(key); if (namespc == NAME_Hexen) { if (ld->special < 0 || ld->special > 140 || !HexenLineSpecialOk[ld->special]) ld->special = 0; // NULL all specials which don't exist in Hexen } continue; case NAME_Id: lineid = CheckInt(key); tagManager.AddLineID(index, lineid); continue; case NAME_Sidefront: ld->sidedef[0] = (side_t*)(intptr_t)(1 + CheckInt(key)); continue; case NAME_Sideback: ld->sidedef[1] = (side_t*)(intptr_t)(1 + CheckInt(key)); continue; case NAME_Arg0: case NAME_Arg1: case NAME_Arg2: case NAME_Arg3: case NAME_Arg4: ld->args[int(key)-int(NAME_Arg0)] = CheckInt(key); continue; case NAME_Arg0Str: CHECK_N(Zd); arg0str = CheckString(key); continue; case NAME_Arg1Str: CHECK_N(Zd); arg1str = CheckString(key); continue; case NAME_Blocking: Flag(ld->flags, ML_BLOCKING, key); continue; case NAME_Blockmonsters: Flag(ld->flags, ML_BLOCKMONSTERS, key); continue; case NAME_Twosided: Flag(ld->flags, ML_TWOSIDED, key); continue; case NAME_Dontpegtop: Flag(ld->flags, ML_DONTPEGTOP, key); continue; case NAME_Dontpegbottom: Flag(ld->flags, ML_DONTPEGBOTTOM, key); continue; case NAME_Secret: Flag(ld->flags, ML_SECRET, key); continue; case NAME_Blocksound: Flag(ld->flags, ML_SOUNDBLOCK, key); continue; case NAME_Dontdraw: Flag(ld->flags, ML_DONTDRAW, key); continue; case NAME_Mapped: Flag(ld->flags, ML_MAPPED, key); continue; case NAME_Jumpover: CHECK_N(St | Zd | Zdt | Va) Flag(ld->flags, ML_RAILING, key); continue; case NAME_Blockfloaters: CHECK_N(St | Zd | Zdt | Va) Flag(ld->flags, ML_BLOCK_FLOATERS, key); continue; case NAME_Translucent: CHECK_N(St | Zd | Zdt | Va) strifetrans = CheckBool(key); continue; case NAME_Transparent: CHECK_N(St | Zd | Zdt | Va) strifetrans2 = CheckBool(key); continue; case NAME_Passuse: CHECK_N(Dm | Zd | Zdt | Va) passuse = CheckBool(key); continue; default: break; } // This switch contains all keys of the UDMF base spec which only apply to Hexen format specials if (!isTranslated) switch (key) { case NAME_Playercross: Flag(ld->activation, SPAC_Cross, key); continue; case NAME_Playeruse: Flag(ld->activation, SPAC_Use, key); continue; case NAME_Playeruseback: Flag(ld->activation, SPAC_UseBack, key); continue; case NAME_Monstercross: Flag(ld->activation, SPAC_MCross, key); continue; case NAME_Impact: Flag(ld->activation, SPAC_Impact, key); continue; case NAME_Playerpush: Flag(ld->activation, SPAC_Push, key); continue; case NAME_Missilecross: Flag(ld->activation, SPAC_PCross, key); continue; case NAME_Monsteruse: Flag(ld->activation, SPAC_MUse, key); continue; case NAME_Monsterpush: Flag(ld->activation, SPAC_MPush, key); continue; case NAME_Repeatspecial: Flag(ld->flags, ML_REPEAT_SPECIAL, key); continue; default: break; } // This switch contains all keys which are ZDoom specific if (namespace_bits & (Zd|Zdt|Va)) switch(key) { case NAME_Alpha: ld->Alpha = CheckFixed(key); continue; case NAME_Renderstyle: { const char *str = CheckString(key); if (!stricmp(str, "translucent")) ld->flags &= ~ML_ADDTRANS; else if (!stricmp(str, "add")) ld->flags |= ML_ADDTRANS; else sc.ScriptMessage("Unknown value \"%s\" for 'renderstyle'\n", str); continue; } case NAME_Anycross: Flag(ld->activation, SPAC_AnyCross, key); continue; case NAME_Monsteractivate: Flag(ld->flags, ML_MONSTERSCANACTIVATE, key); continue; case NAME_Blockplayers: Flag(ld->flags, ML_BLOCK_PLAYERS, key); continue; case NAME_Blockeverything: Flag(ld->flags, ML_BLOCKEVERYTHING, key); continue; case NAME_Zoneboundary: Flag(ld->flags, ML_ZONEBOUNDARY, key); continue; case NAME_Clipmidtex: Flag(ld->flags, ML_CLIP_MIDTEX, key); continue; case NAME_Wrapmidtex: Flag(ld->flags, ML_WRAP_MIDTEX, key); continue; case NAME_Midtex3d: Flag(ld->flags, ML_3DMIDTEX, key); continue; case NAME_Checkswitchrange: Flag(ld->flags, ML_CHECKSWITCHRANGE, key); continue; case NAME_Firstsideonly: Flag(ld->flags, ML_FIRSTSIDEONLY, key); continue; case NAME_blockprojectiles: Flag(ld->flags, ML_BLOCKPROJECTILE, key); continue; case NAME_blockuse: Flag(ld->flags, ML_BLOCKUSE, key); continue; case NAME_blocksight: Flag(ld->flags, ML_BLOCKSIGHT, key); continue; case NAME_blockhitscan: Flag(ld->flags, ML_BLOCKHITSCAN, key); continue; // [TP] Locks the special with a key case NAME_Locknumber: ld->locknumber = CheckInt(key); continue; // [TP] Causes a 3d midtex to behave like an impassible line case NAME_Midtex3dimpassible: Flag(ld->flags, ML_3DMIDTEX_IMPASS, key); continue; case NAME_MoreIds: // delay parsing of the tag string until parsing of the sector is complete // This ensures that the ID is always the first tag in the list. tagstring = CheckString(key); break; default: break; } if ((namespace_bits & (Zd | Zdt)) && !strnicmp("user_", key.GetChars(), 5)) { AddUserKey(key, UDMF_Line, index); } } if (tagstring.IsNotEmpty()) { FScanner sc; sc.OpenString("tagstring", tagstring); // scan the string as long as valid numbers can be found while (sc.CheckNumber()) { if (sc.Number != 0) tagManager.AddLineID(index, sc.Number); } } if (isTranslated) { int saved = ld->flags; maplinedef_t mld; memset(&mld, 0, sizeof(mld)); mld.special = ld->special; mld.tag = lineid; 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; } if (strifetrans && ld->Alpha == FRACUNIT) { ld->Alpha = FRACUNIT * 3/4; } if (strifetrans2 && ld->Alpha == FRACUNIT) { ld->Alpha = FRACUNIT * 1/4; } if (ld->sidedef[0] == NULL) { ld->sidedef[0] = (side_t*)(intptr_t)(1); Printf("Line %d has no first side.\n", index); } if (arg0str.IsNotEmpty() && (P_IsACSSpecial(ld->special) || ld->special == 0)) { ld->args[0] = -FName(arg0str); } if (arg1str.IsNotEmpty() && (P_IsThingSpecial(ld->special) || ld->special == 0)) { ld->args[1] = -FName(arg1str); } if ((ld->flags & ML_3DMIDTEX_IMPASS) && !(ld->flags & ML_3DMIDTEX)) // [TP] { Printf ("Line %d has midtex3dimpassible without midtex3d.\n", index); } }
void ParseSector(sector_t *sec, int index) { int lightcolor = -1; int fadecolor = -1; int desaturation = -1; int fplaneflags = 0, cplaneflags = 0; double fp[4] = { 0 }, cp[4] = { 0 }; FString tagstring; memset(sec, 0, sizeof(*sec)); sec->lightlevel = 160; sec->SetXScale(sector_t::floor, FRACUNIT); // [RH] floor and ceiling scaling sec->SetYScale(sector_t::floor, FRACUNIT); sec->SetXScale(sector_t::ceiling, FRACUNIT); sec->SetYScale(sector_t::ceiling, FRACUNIT); sec->SetAlpha(sector_t::floor, FRACUNIT); sec->SetAlpha(sector_t::ceiling, FRACUNIT); 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 sec->sectornum = index; if (floordrop) sec->Flags = SECF_FLOORDROP; // 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.MustGetToken('{'); while (!sc.CheckToken('}')) { FName key = ParseKey(); switch(key) { case NAME_Heightfloor: sec->SetPlaneTexZ(sector_t::floor, CheckInt(key) << FRACBITS); continue; case NAME_Heightceiling: sec->SetPlaneTexZ(sector_t::ceiling, CheckInt(key) << FRACBITS); continue; case NAME_Texturefloor: SetTexture(sec, index, sector_t::floor, CheckString(key), missingTex, false); continue; case NAME_Textureceiling: SetTexture(sec, index, sector_t::ceiling, CheckString(key), missingTex, false); continue; case NAME_Lightlevel: sec->lightlevel = sector_t::ClampLight(CheckInt(key)); continue; case NAME_Special: sec->special = (short)CheckInt(key); if (isTranslated) sec->special = P_TranslateSectorSpecial(sec->special); else if (namespc == NAME_Hexen) { if (sec->special < 0 || sec->special > 255 || !HexenSectorSpecialOk[sec->special]) sec->special = 0; // NULL all unknown specials } continue; case NAME_Id: tagManager.AddSectorTag(index, CheckInt(key)); continue; default: break; } if (namespace_bits & (Zd|Zdt|Va)) switch(key) { case NAME_Xpanningfloor: sec->SetXOffset(sector_t::floor, CheckFixed(key)); continue; case NAME_Ypanningfloor: sec->SetYOffset(sector_t::floor, CheckFixed(key)); continue; case NAME_Xpanningceiling: sec->SetXOffset(sector_t::ceiling, CheckFixed(key)); continue; case NAME_Ypanningceiling: sec->SetYOffset(sector_t::ceiling, CheckFixed(key)); continue; case NAME_Xscalefloor: sec->SetXScale(sector_t::floor, CheckFixed(key)); continue; case NAME_Yscalefloor: sec->SetYScale(sector_t::floor, CheckFixed(key)); continue; case NAME_Xscaleceiling: sec->SetXScale(sector_t::ceiling, CheckFixed(key)); continue; case NAME_Yscaleceiling: sec->SetYScale(sector_t::ceiling, CheckFixed(key)); continue; case NAME_Rotationfloor: sec->SetAngle(sector_t::floor, CheckAngle(key)); continue; case NAME_Rotationceiling: sec->SetAngle(sector_t::ceiling, CheckAngle(key)); continue; case NAME_Lightfloor: sec->SetPlaneLight(sector_t::floor, CheckInt(key)); continue; case NAME_Lightceiling: sec->SetPlaneLight(sector_t::ceiling, CheckInt(key)); continue; case NAME_Alphafloor: sec->SetAlpha(sector_t::floor, CheckFixed(key)); continue; case NAME_Alphaceiling: sec->SetAlpha(sector_t::ceiling, CheckFixed(key)); continue; case NAME_Renderstylefloor: { const char *str = CheckString(key); if (!stricmp(str, "translucent")) sec->ChangeFlags(sector_t::floor, PLANEF_ADDITIVE, 0); else if (!stricmp(str, "add")) sec->ChangeFlags(sector_t::floor, 0, PLANEF_ADDITIVE); else sc.ScriptMessage("Unknown value \"%s\" for 'renderstylefloor'\n", str); continue; } case NAME_Renderstyleceiling: { const char *str = CheckString(key); if (!stricmp(str, "translucent")) sec->ChangeFlags(sector_t::ceiling, PLANEF_ADDITIVE, 0); else if (!stricmp(str, "add")) sec->ChangeFlags(sector_t::ceiling, 0, PLANEF_ADDITIVE); else sc.ScriptMessage("Unknown value \"%s\" for 'renderstyleceiling'\n", str); continue; } case NAME_Lightfloorabsolute: if (CheckBool(key)) sec->ChangeFlags(sector_t::floor, 0, PLANEF_ABSLIGHTING); else sec->ChangeFlags(sector_t::floor, PLANEF_ABSLIGHTING, 0); continue; case NAME_Lightceilingabsolute: if (CheckBool(key)) sec->ChangeFlags(sector_t::ceiling, 0, PLANEF_ABSLIGHTING); else sec->ChangeFlags(sector_t::ceiling, PLANEF_ABSLIGHTING, 0); continue; case NAME_Gravity: sec->gravity = float(CheckFloat(key)); continue; case NAME_Lightcolor: lightcolor = CheckInt(key); continue; case NAME_Fadecolor: fadecolor = CheckInt(key); continue; case NAME_Desaturation: desaturation = int(255*CheckFloat(key)); continue; case NAME_Silent: Flag(sec->Flags, SECF_SILENT, key); continue; case NAME_NoRespawn: Flag(sec->Flags, SECF_NORESPAWN, key); continue; case NAME_Nofallingdamage: Flag(sec->Flags, SECF_NOFALLINGDAMAGE, key); continue; case NAME_Dropactors: Flag(sec->Flags, SECF_FLOORDROP, key); continue; case NAME_SoundSequence: sec->SeqName = CheckString(key); sec->seqType = -1; continue; case NAME_hidden: Flag(sec->MoreFlags, SECF_HIDDEN, key); break; case NAME_Waterzone: Flag(sec->MoreFlags, SECF_UNDERWATER, key); break; case NAME_floorplane_a: fplaneflags |= 1; fp[0] = CheckFloat(key); break; case NAME_floorplane_b: fplaneflags |= 2; fp[1] = CheckFloat(key); break; case NAME_floorplane_c: fplaneflags |= 4; fp[2] = CheckFloat(key); break; case NAME_floorplane_d: fplaneflags |= 8; fp[3] = CheckFloat(key); break; case NAME_ceilingplane_a: cplaneflags |= 1; cp[0] = CheckFloat(key); break; case NAME_ceilingplane_b: cplaneflags |= 2; cp[1] = CheckFloat(key); break; case NAME_ceilingplane_c: cplaneflags |= 4; cp[2] = CheckFloat(key); break; case NAME_ceilingplane_d: cplaneflags |= 8; cp[3] = CheckFloat(key); break; case NAME_MoreIds: // delay parsing of the tag string until parsing of the sector is complete // This ensures that the ID is always the first tag in the list. tagstring = CheckString(key); break; default: break; } if ((namespace_bits & (Zd | Zdt)) && !strnicmp("user_", key.GetChars(), 5)) { AddUserKey(key, UDMF_Sector, index); } } if (tagstring.IsNotEmpty()) { FScanner sc; sc.OpenString("tagstring", tagstring); // scan the string as long as valid numbers can be found while (sc.CheckNumber()) { if (sc.Number != 0) tagManager.AddSectorTag(index, sc.Number); } } sec->secretsector = !!(sec->special&SECRET_MASK); // Reset the planes to their defaults if not all of the plane equation's parameters were found. if (fplaneflags != 15) { sec->floorplane.a = sec->floorplane.b = 0; sec->floorplane.d = -sec->GetPlaneTexZ(sector_t::floor); sec->floorplane.c = FRACUNIT; sec->floorplane.ic = FRACUNIT; } else { double ulen = TVector3<double>(fp[0], fp[1], fp[2]).Length(); // normalize the vector, it must have a length of 1 sec->floorplane.a = FLOAT2FIXED(fp[0] / ulen); sec->floorplane.b = FLOAT2FIXED(fp[1] / ulen); sec->floorplane.c = FLOAT2FIXED(fp[2] / ulen); sec->floorplane.d = FLOAT2FIXED(fp[3] / ulen); sec->floorplane.ic = FLOAT2FIXED(ulen / fp[2]); } if (cplaneflags != 15) { sec->ceilingplane.a = sec->ceilingplane.b = 0; sec->ceilingplane.d = sec->GetPlaneTexZ(sector_t::ceiling); sec->ceilingplane.c = -FRACUNIT; sec->ceilingplane.ic = -FRACUNIT; } else { double ulen = TVector3<double>(cp[0], cp[1], cp[2]).Length(); // normalize the vector, it must have a length of 1 sec->ceilingplane.a = FLOAT2FIXED(cp[0] / ulen); sec->ceilingplane.b = FLOAT2FIXED(cp[1] / ulen); sec->ceilingplane.c = FLOAT2FIXED(cp[2] / ulen); sec->ceilingplane.d = FLOAT2FIXED(cp[3] / ulen); sec->ceilingplane.ic = FLOAT2FIXED(ulen / cp[2]); } if (lightcolor == -1 && fadecolor == -1 && desaturation == -1) { // [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->GetTexture(sector_t::ceiling) == 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; } } else { if (lightcolor == -1) lightcolor = PalEntry(255,255,255); if (fadecolor == -1) { if (level.outsidefog != 0xff000000 && (sec->GetTexture(sector_t::ceiling) == skyflatnum || (sec->special&0xff) == Sector_Outside)) fadecolor = level.outsidefog; else fadecolor = level.fadeto; } if (desaturation == -1) desaturation = NormalLight.Desaturate; sec->ColorMap = GetSpecialLights (lightcolor, fadecolor, desaturation); } }