static void ParseSpawnMap(FScanner &sc, SpawnMap & themap, const char *descript) { TMap<int, bool> defined; int error = 0; MapinfoSpawnItem editem; editem.filename = sc.ScriptName; while (true) { if (sc.CheckString("}")) return; else if (sc.CheckNumber()) { int ednum = sc.Number; sc.MustGetStringName("="); sc.MustGetString(); bool *def = defined.CheckKey(ednum); if (def != NULL) { sc.ScriptMessage("%s %d defined more than once", descript, ednum); error++; } else if (ednum < 0) { sc.ScriptMessage("%s must be positive, got %d", descript, ednum); error++; } defined[ednum] = true; editem.classname = sc.String; themap.Insert(ednum, editem); } else { sc.ScriptError("Number expected"); } } if (error > 0) { sc.ScriptError("%d errors encountered in %s definition", error, descript); } }
void FTextureManager::ParseWarp(FScanner &sc) { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny | TEXMAN_ShortNameOnly; bool isflat = false; bool type2 = sc.Compare ("warp2"); // [GRB] sc.MustGetString (); if (sc.Compare ("flat")) { isflat = true; sc.MustGetString (); } else if (sc.Compare ("texture")) { isflat = false; sc.MustGetString (); } else { sc.ScriptError (NULL); } FTextureID picnum = CheckForTexture (sc.String, isflat ? FTexture::TEX_Flat : FTexture::TEX_Wall, texflags); if (picnum.isValid()) { FTexture *warper = Texture(picnum); // don't warp a texture more than once if (!warper->bWarped) { if (type2) warper = new FWarp2Texture (warper); else warper = new FWarpTexture (warper); ReplaceTexture (picnum, warper, false); } if (sc.CheckFloat()) { static_cast<FWarpTexture*>(warper)->SetSpeed(float(sc.Float)); } // No decals on warping textures, by default. // Warping information is taken from the last warp // definition for this texture. warper->bNoDecals = true; if (sc.GetString ()) { if (sc.Compare ("allowdecals")) { warper->bNoDecals = false; } else { sc.UnGet (); } } } }
static void ParseActorProperty(FScanner &sc, Baggage &bag) { static const char *statenames[] = { "Spawn", "See", "Melee", "Missile", "Pain", "Death", "XDeath", "Burn", "Ice", "Raise", "Crash", "Crush", "Wound", "Disintegrate", "Heal", NULL }; strlwr (sc.String); FString propname = sc.String; if (sc.CheckString (".")) { sc.MustGetString (); propname += '.'; strlwr (sc.String); propname += sc.String; } else { sc.UnGet (); } FPropertyInfo *prop = FindProperty(propname); if (prop != NULL) { if (bag.Info->Class->IsDescendantOf(prop->cls)) { ParsePropertyParams(sc, prop, (AActor *)bag.Info->Class->Defaults, bag); } else { sc.ScriptMessage("\"%s\" requires an actor of type \"%s\"\n", propname.GetChars(), prop->cls->TypeName.GetChars()); FScriptPosition::ErrorCounter++; } } else if (!propname.CompareNoCase("States")) { if (bag.StateSet) { sc.ScriptMessage("'%s' contains multiple state declarations", bag.Info->Class->TypeName.GetChars()); FScriptPosition::ErrorCounter++; } ParseStates(sc, bag.Info, (AActor *)bag.Info->Class->Defaults, bag); bag.StateSet=true; } else if (MatchString(propname, statenames) != -1) { bag.statedef.SetStateLabel(propname, CheckState (sc, bag.Info->Class)); } else { sc.ScriptError("\"%s\" is an unknown actor property\n", propname.GetChars()); } }
//========================================================================== //*** // DoActionSpecials // handles action specials as code pointers // //========================================================================== bool DoActionSpecials(FScanner &sc, FState & state, Baggage &bag) { int i; int min_args, max_args; FString specname = sc.String; int special = P_FindLineSpecial(sc.String, &min_args, &max_args); if (special > 0 && min_args >= 0) { int paramindex=PrepareStateParameters(&state, 6, bag.Info->Class); StateParams.Set(paramindex, new FxConstant(special, sc)); // Make this consistent with all other parameter parsing if (sc.CheckToken('(')) { for (i = 0; i < 5;) { StateParams.Set(paramindex+i+1, ParseExpression (sc, bag.Info->Class)); i++; if (!sc.CheckToken (',')) break; } sc.MustGetToken (')'); } else i=0; if (i < min_args) { sc.ScriptError ("Too few arguments to %s", specname.GetChars()); } if (i > max_args) { sc.ScriptError ("Too many arguments to %s", specname.GetChars()); } state.SetAction(FindGlobalActionFunction("A_CallSpecial"), false); return true; } return false; }
void SBarInfoCommand::setString(FScanner &sc, const char* source, int strnum, int maxlength, bool exact) { if(!exact) { if(maxlength != -1 && strlen(source) > (unsigned int) maxlength) { sc.ScriptError("%s is greater than %d characters.", source, maxlength); return; } } else { if(maxlength != -1 && strlen(source) != (unsigned int) maxlength) { sc.ScriptError("%s must be %d characters.", source, maxlength); return; } } string[strnum] = source; }
static int ParseLumpName(FScanner &scanner, char *buffer) { scanner.MustGetToken(TK_StringConst); if (strlen(scanner.String) > 8) { scanner.ScriptError("String too long. Maximum size is 8 characters."); return 0; } uppercopy(buffer, scanner.String); return 1; }
void gl_ParseObject(FScanner &sc) { int type; FString name; // get name sc.GetString(); name = sc.String; if (!PClass::FindClass(name)) sc.ScriptMessage("Warning: dynamic lights attached to non-existent actor %s\n", name.GetChars()); // check for opening brace sc.GetString(); if (sc.Compare("{")) { ScriptDepth++; while (ScriptDepth) { sc.GetString(); type = sc.MatchString(LightTags); switch (type) { case LIGHTTAG_OPENBRACE: ScriptDepth++; break; case LIGHTTAG_CLOSEBRACE: ScriptDepth--; break; case LIGHTTAG_FRAME: gl_ParseFrame(sc, name); break; default: sc.ScriptError("Unknown tag: %s\n", sc.String); } } } else { sc.ScriptError("Expected '{'.\n"); } }
//converts a string into a tranlation. EColorRange SBarInfo::GetTranslation(FScanner &sc, const char* translation) { EColorRange returnVal = CR_UNTRANSLATED; FString namedTranslation; //we must send in "[translation]" const BYTE *trans_ptr; namedTranslation.Format("[%s]", translation); trans_ptr = (const BYTE *)(&namedTranslation[0]); if((returnVal = V_ParseFontColor(trans_ptr, CR_UNTRANSLATED, CR_UNTRANSLATED)) == CR_UNDEFINED) { sc.ScriptError("Missing definition for color %s.", translation); } return returnVal; }
EColorRange GetTranslation(FScanner &sc) { if (!sc.CheckToken(TK_Null)) sc.MustGetToken(TK_Identifier); EColorRange returnVal = CR_UNTRANSLATED; FString namedTranslation; //we must send in "[translation]" const BYTE *trans_ptr; namedTranslation.Format("[%s]", sc.String); trans_ptr = (const BYTE *)(&namedTranslation[0]); if((returnVal = V_ParseFontColor(trans_ptr, CR_UNTRANSLATED, CR_UNTRANSLATED)) == CR_UNDEFINED) { sc.ScriptError("Missing definition for color %s.", sc.String); } return returnVal; }
//========================================================================== // // Reads an actor definition // //========================================================================== static void ParseActor(FScanner &sc) { FActorInfo * info=NULL; Baggage bag; info = ParseActorHeader(sc, &bag); sc.MustGetToken('{'); while (sc.MustGetAnyToken(), sc.TokenType != '}') { switch (sc.TokenType) { case TK_Action: ParseActionDef (sc, info->Class); break; case TK_Const: ParseConstant (sc, &info->Class->Symbols, info->Class); break; case TK_Enum: ParseEnum (sc, &info->Class->Symbols, info->Class); break; case TK_Native: ParseNativeVariable (sc, &info->Class->Symbols, info->Class); break; case TK_Var: ParseUserVariable (sc, &info->Class->Symbols, info->Class); break; case TK_Identifier: ParseActorProperty(sc, bag); break; case '+': case '-': ParseActorFlag(sc, bag, sc.TokenType); break; default: sc.ScriptError("Unexpected '%s' in definition of '%s'", sc.String, bag.Info->Class->TypeName.GetChars()); break; } } FinishActor(sc, info, bag); sc.SetCMode (false); }
void ParseSplash (FScanner &sc) { int splashnum; FSplashDef *splashdef; bool isnew = false; FName name; sc.MustGetString (); name = sc.String; splashnum = (int)FindSplash (name); if (splashnum < 0) { FSplashDef def; SetSplashDefaults (&def); def.Name = name; splashnum = (int)Splashes.Push (def); isnew = true; } splashdef = &Splashes[splashnum]; sc.MustGetString (); if (!sc.Compare ("modify")) { // Set defaults if (!isnew) { // New ones already have their defaults set before they're pushed. SetSplashDefaults (splashdef); } } else { sc.MustGetString(); } if (!sc.Compare ("{")) { sc.ScriptError ("Expected {"); } else { GenericParse (sc, SplashParser, SplashKeywords, splashdef, "splash", splashdef->Name); } }
FTextureID FTextureManager::ParseFramenum (FScanner &sc, FTextureID basepicnum, int usetype, bool allowMissing) { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; FTextureID framenum; sc.MustGetString (); if (IsNum (sc.String)) { framenum = basepicnum + (atoi(sc.String) - 1); } else { framenum = CheckForTexture (sc.String, usetype, texflags); if (!framenum.Exists() && !allowMissing) { sc.ScriptError ("Unknown texture %s", sc.String); } } return framenum; }
static void ParseTime (FScanner &sc, DWORD &min, DWORD &max) { sc.MustGetString (); if (sc.Compare ("tics")) { sc.MustGetFloat (); min = max = DWORD(sc.Float * 1000 / 35); } else if (sc.Compare ("rand")) { sc.MustGetFloat (); min = DWORD(sc.Float * 1000 / 35); sc.MustGetFloat (); max = DWORD(sc.Float * 1000 / 35); } else { sc.ScriptError ("Must specify a duration for animation frame"); } }
void ParseTerrain (FScanner &sc) { int terrainnum; FName name; sc.MustGetString (); name = sc.String; terrainnum = (int)P_FindTerrain (name); if (terrainnum < 0) { FTerrainDef def; memset (&def, 0, sizeof(def)); def.Splash = -1; def.Name = name; terrainnum = (int)Terrains.Push (def); } // Set defaults sc.MustGetString (); if (!sc.Compare ("modify")) { name = Terrains[terrainnum].Name; memset (&Terrains[terrainnum], 0, sizeof(FTerrainDef)); Terrains[terrainnum].Splash = -1; Terrains[terrainnum].Name = name; } else { sc.MustGetString (); } if (sc.Compare ("{")) { GenericParse (sc, TerrainParser, TerrainKeywords, &Terrains[terrainnum], "terrain", Terrains[terrainnum].Name); } else { sc.ScriptError ("Expected {"); } }
void FTextureManager::ParseTime (FScanner &sc, uint32_t &min, uint32_t &max) { sc.MustGetString (); if (sc.Compare ("tics")) { sc.MustGetFloat (); min = max = uint32_t(sc.Float * 1000 / 35); } else if (sc.Compare ("rand")) { sc.MustGetFloat (); min = uint32_t(sc.Float * 1000 / 35); sc.MustGetFloat (); max = uint32_t(sc.Float * 1000 / 35); } else { min = max = 1; sc.ScriptError ("Must specify a duration for animation frame"); } }
void ParseBlock(TDeletingArray<SBarInfoCommand *> &commands, FScanner &sc, bool fullScreenOffsets) { if(sc.CheckToken('{')) { while(SBarInfoCommand *cmd = NextCommand(sc)) { cmd->Parse(sc, fullScreenOffsets); commands.Push(cmd); } } else { if(SBarInfoCommand *cmd = NextCommand(sc)) { cmd->Parse(sc, fullScreenOffsets); commands.Push(cmd); } else sc.ScriptError("Missing command for flow control statement."); } }
static void ParseDamageDefinition(FScanner &sc) { sc.SetCMode (true); // This may be 100% irrelevant for such a simple syntax, but I don't know // Get DamageType sc.MustGetString(); FName damageType = sc.String; DamageTypeDefinition dtd; sc.MustGetToken('{'); while (sc.MustGetAnyToken(), sc.TokenType != '}') { if (sc.Compare("FACTOR")) { sc.MustGetFloat(); dtd.DefaultFactor = sc.Float; if (dtd.DefaultFactor == 0) dtd.ReplaceFactor = true; } else if (sc.Compare("REPLACEFACTOR")) { dtd.ReplaceFactor = true; } else if (sc.Compare("NOARMOR")) { dtd.NoArmor = true; } else { sc.ScriptError("Unexpected data (%s) in damagetype definition.", sc.String); } } dtd.Apply(damageType); sc.SetCMode (false); // (set to true earlier in function) }
void Parse(FScanner &sc, bool fullScreenOffsets) { this->fullScreenOffsets = fullScreenOffsets; if(sc.CheckToken(',')) { while(sc.CheckToken(TK_Identifier)) { if(sc.Compare("forcescaled")) forceScaled = true; else if(sc.Compare("fullscreenoffsets")) this->fullScreenOffsets = true; else sc.ScriptError("Unkown flag '%s'.", sc.String); if(!sc.CheckToken('|') && !sc.CheckToken(',')) { SBarInfoCommandFlowControl::Parse(sc, this->fullScreenOffsets); return; } } sc.MustGetToken(TK_FloatConst); alpha = sc.Float; } SBarInfoCommandFlowControl::Parse(sc, this->fullScreenOffsets); }
void SBarInfo::ParseMugShotBlock(FScanner &sc, FMugShotState &state) { sc.MustGetToken('{'); while(!sc.CheckToken('}')) { FMugShotFrame frame; bool multiframe = false; if(sc.CheckToken('{')) multiframe = true; do { sc.MustGetToken(TK_Identifier); if(strlen(sc.String) > 5) sc.ScriptError("MugShot frames cannot exceed 5 characters."); frame.Graphic.Push(sc.String); } while(multiframe && sc.CheckToken(',')); if(multiframe) sc.MustGetToken('}'); frame.Delay = getSignedInteger(sc); sc.MustGetToken(';'); state.Frames.Push(frame); } }
void FTextureManager::ParseAnimatedDoor(FScanner &sc) { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; FDoorAnimation anim; TArray<FTextureID> frames; bool error = false; FTextureID v; sc.MustGetString(); anim.BaseTexture = CheckForTexture (sc.String, FTexture::TEX_Wall, texflags); if (!anim.BaseTexture.Exists()) { error = true; } else { Texture(anim.BaseTexture)->bNoDecals = true; } while (sc.GetString()) { if (sc.Compare ("opensound")) { sc.MustGetString (); anim.OpenSound = sc.String; } else if (sc.Compare ("closesound")) { sc.MustGetString (); anim.CloseSound = sc.String; } else if (sc.Compare ("pic")) { sc.MustGetString (); if (IsNum (sc.String)) { v = anim.BaseTexture + (atoi(sc.String) - 1); } else { v = CheckForTexture (sc.String, FTexture::TEX_Wall, texflags); if (!v.Exists() && anim.BaseTexture.Exists() && !error) { sc.ScriptError ("Unknown texture %s", sc.String); } } frames.Push(v); } else if (sc.Compare("allowdecals")) { if (anim.BaseTexture.Exists()) Texture(anim.BaseTexture)->bNoDecals = false; } else { sc.UnGet (); break; } } if (!error) { anim.TextureFrames = new FTextureID[frames.Size()]; memcpy (anim.TextureFrames, &frames[0], sizeof(FTextureID) * frames.Size()); anim.NumTextureFrames = frames.Size(); mAnimatedDoors.Push (anim); } }
void FTeam::ParseTeamDefinition (FScanner &Scan) { FTeam Team; int valid = -1; Scan.MustGetString (); Team.m_Name = Scan.String; Scan.MustGetStringName ("{"); while (!Scan.CheckString ("}")) { Scan.MustGetString (); switch (Scan.MatchString (TeamInfoOptions)) { case TEAMINFO_Game: Scan.MustGetString (); if (Scan.Compare("Any")) valid = 1; else if (CheckGame(Scan.String, false)) valid = 1; else if (valid == -1) valid = 0; break; case TEAMINFO_PlayerColor: Scan.MustGetString (); Team.m_iPlayerColor = V_GetColor (NULL, Scan.String); break; case TEAMINFO_TextColor: Scan.MustGetString (); Team.m_TextColor.AppendFormat ("[%s]", Scan.String); break; case TEAMINFO_Logo: Scan.MustGetString (); Team.m_Logo = Scan.String; break; case TEAMINFO_AllowCustomPlayerColor: Team.m_bAllowCustomPlayerColor = true; break; case TEAMINFO_PlayerStartThingNumber: Scan.MustGetNumber (); break; case TEAMINFO_RailColor: case TEAMINFO_FlagItem: case TEAMINFO_SkullItem: case TEAMINFO_SmallFlagHUDIcon: case TEAMINFO_SmallSkullHUDIcon: case TEAMINFO_LargeFlagHUDIcon: case TEAMINFO_LargeSkullHUDIcon: case TEAMINFO_WinnerPic: case TEAMINFO_LoserPic: case TEAMINFO_WinnerTheme: case TEAMINFO_LoserTheme: Scan.MustGetString (); break; default: Scan.ScriptError ("ParseTeamDefinition: Unknown team option '%s'.\n", Scan.String); break; } } if (valid) Teams.Push (Team); }
static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc) { sc.MustGetStringName("{"); while (!sc.CheckString("}")) { sc.MustGetString(); if (sc.Compare("ifgame")) { if (!CheckSkipGameBlock(sc)) { // recursively parse sub-block ParseOptionMenuBody(sc, desc); } } else if (sc.Compare("ifoption")) { if (!CheckSkipOptionBlock(sc)) { // recursively parse sub-block ParseOptionMenuBody(sc, desc); } } else if (sc.Compare("Class")) { sc.MustGetString(); const PClass *cls = PClass::FindClass(sc.String); if (cls == NULL || !cls->IsDescendantOf(RUNTIME_CLASS(DOptionMenu))) { sc.ScriptError("Unknown menu class '%s'", sc.String); } desc->mClass = cls; } else if (sc.Compare("Title")) { sc.MustGetString(); desc->mTitle = sc.String; } else if (sc.Compare("Position")) { sc.MustGetNumber(); desc->mPosition = sc.Number; } else if (sc.Compare("DefaultSelection")) { sc.MustGetNumber(); desc->mSelectedItem = sc.Number; } else if (sc.Compare("ScrollTop")) { sc.MustGetNumber(); desc->mScrollTop = sc.Number; } else if (sc.Compare("Indent")) { sc.MustGetNumber(); desc->mIndent = sc.Number; } else if (sc.Compare("Submenu")) { sc.MustGetString(); FString label = sc.String; sc.MustGetStringName(","); sc.MustGetString(); FOptionMenuItem *it = new FOptionMenuItemSubmenu(label, sc.String); desc->mItems.Push(it); } else if (sc.Compare("Option")) { sc.MustGetString(); FString label = sc.String; sc.MustGetStringName(","); sc.MustGetString(); FString cvar = sc.String; sc.MustGetStringName(","); sc.MustGetString(); FString values = sc.String; FString check; int center = 0; if (sc.CheckString(",")) { sc.MustGetString(); if (*sc.String != 0) check = sc.String; if (sc.CheckString(",")) { sc.MustGetNumber(); center = sc.Number; } } FOptionMenuItem *it = new FOptionMenuItemOption(label, cvar, values, check, center); desc->mItems.Push(it); } else if (sc.Compare("Command")) { sc.MustGetString(); FString label = sc.String; sc.MustGetStringName(","); sc.MustGetString(); FOptionMenuItem *it = new FOptionMenuItemCommand(label, sc.String); desc->mItems.Push(it); } else if (sc.Compare("SafeCommand")) { sc.MustGetString(); FString label = sc.String; sc.MustGetStringName(","); sc.MustGetString(); FOptionMenuItem *it = new FOptionMenuItemSafeCommand(label, sc.String); desc->mItems.Push(it); } else if (sc.Compare("Control") || sc.Compare("MapControl")) { bool map = sc.Compare("MapControl"); sc.MustGetString(); FString label = sc.String; sc.MustGetStringName(","); sc.MustGetString(); FOptionMenuItem *it = new FOptionMenuItemControl(label, sc.String, map? &AutomapBindings : &Bindings); desc->mItems.Push(it); } else if (sc.Compare("ColorPicker")) { sc.MustGetString(); FString label = sc.String; sc.MustGetStringName(","); sc.MustGetString(); FOptionMenuItem *it = new FOptionMenuItemColorPicker(label, sc.String); desc->mItems.Push(it); } else if (sc.Compare("StaticText")) { sc.MustGetString(); FString label = sc.String; bool cr = false; if (sc.CheckString(",")) { sc.MustGetNumber(); cr = !!sc.Number; } FOptionMenuItem *it = new FOptionMenuItemStaticText(label, cr); desc->mItems.Push(it); } else if (sc.Compare("StaticTextSwitchable")) { sc.MustGetString(); FString label = sc.String; sc.MustGetStringName(","); sc.MustGetString(); FString label2 = sc.String; sc.MustGetStringName(","); sc.MustGetString(); FName action = sc.String; bool cr = false; if (sc.CheckString(",")) { sc.MustGetNumber(); cr = !!sc.Number; } FOptionMenuItem *it = new FOptionMenuItemStaticTextSwitchable(label, label2, action, cr); desc->mItems.Push(it); } else if (sc.Compare("Slider")) { sc.MustGetString(); FString text = sc.String; sc.MustGetStringName(","); sc.MustGetString(); FString action = sc.String; sc.MustGetStringName(","); sc.MustGetFloat(); double min = sc.Float; sc.MustGetStringName(","); sc.MustGetFloat(); double max = sc.Float; sc.MustGetStringName(","); sc.MustGetFloat(); double step = sc.Float; int showvalue = 1; if (sc.CheckString(",")) { sc.MustGetNumber(); showvalue = sc.Number; } FOptionMenuItem *it = new FOptionMenuSliderCVar(text, action, min, max, step, showvalue); desc->mItems.Push(it); } else if (sc.Compare("screenresolution")) { sc.MustGetString(); FOptionMenuItem *it = new FOptionMenuScreenResolutionLine(sc.String); desc->mItems.Push(it); } else { sc.ScriptError("Unknown keyword '%s'", sc.String); } } }
static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc) { sc.MustGetStringName("{"); while (!sc.CheckString("}")) { sc.MustGetString(); if (sc.Compare("else")) { SkipSubBlock(sc); } else if (sc.Compare("ifgame")) { if (!CheckSkipGameBlock(sc)) { // recursively parse sub-block ParseListMenuBody(sc, desc); } } else if (sc.Compare("ifoption")) { if (!CheckSkipOptionBlock(sc)) { // recursively parse sub-block ParseListMenuBody(sc, desc); } } else if (sc.Compare("Class")) { sc.MustGetString(); const PClass *cls = PClass::FindClass(sc.String); if (cls == NULL || !cls->IsDescendantOf(RUNTIME_CLASS(DListMenu))) { sc.ScriptError("Unknown menu class '%s'", sc.String); } desc->mClass = cls; } else if (sc.Compare("Selector")) { sc.MustGetString(); desc->mSelector = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch); sc.MustGetStringName(","); sc.MustGetNumber(); desc->mSelectOfsX = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); desc->mSelectOfsY = sc.Number; } else if (sc.Compare("Linespacing")) { sc.MustGetNumber(); desc->mLinespacing = sc.Number; } else if (sc.Compare("Position")) { sc.MustGetNumber(); desc->mXpos = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); desc->mYpos = sc.Number; } else if (sc.Compare("Centermenu")) { desc->mCenter = true; } else if (sc.Compare("MouseWindow")) { sc.MustGetNumber(); desc->mWLeft = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); desc->mWRight = sc.Number; } else if (sc.Compare("StaticPatch") || sc.Compare("StaticPatchCentered")) { bool centered = sc.Compare("StaticPatchCentered"); sc.MustGetNumber(); int x = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); int y = sc.Number; sc.MustGetStringName(","); sc.MustGetString(); FTextureID tex = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch); FListMenuItem *it = new FListMenuItemStaticPatch(x, y, tex, centered); desc->mItems.Push(it); } else if (sc.Compare("StaticText") || sc.Compare("StaticTextCentered")) { bool centered = sc.Compare("StaticTextCentered"); sc.MustGetNumber(); int x = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); int y = sc.Number; sc.MustGetStringName(","); sc.MustGetString(); FListMenuItem *it = new FListMenuItemStaticText(x, y, sc.String, desc->mFont, desc->mFontColor, centered); desc->mItems.Push(it); } else if (sc.Compare("PatchItem")) { sc.MustGetString(); FTextureID tex = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch); sc.MustGetStringName(","); sc.MustGetString(); int hotkey = sc.String[0]; sc.MustGetStringName(","); sc.MustGetString(); FName action = sc.String; int param = 0; if (sc.CheckString(",")) { sc.MustGetNumber(); param = sc.Number; } FListMenuItem *it = new FListMenuItemPatch(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, tex, action, param); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; } else if (sc.Compare("TextItem")) { sc.MustGetString(); FString text = sc.String; sc.MustGetStringName(","); sc.MustGetString(); int hotkey = sc.String[0]; sc.MustGetStringName(","); sc.MustGetString(); FName action = sc.String; int param = 0; if (sc.CheckString(",")) { sc.MustGetNumber(); param = sc.Number; } FListMenuItem *it = new FListMenuItemText(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, param); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; } else if (sc.Compare("Font")) { sc.MustGetString(); FFont *newfont = V_GetFont(sc.String); if (newfont != NULL) desc->mFont = newfont; if (sc.CheckString(",")) { sc.MustGetString(); desc->mFontColor2 = desc->mFontColor = V_FindFontColor((FName)sc.String); if (sc.CheckString(",")) { sc.MustGetString(); desc->mFontColor2 = V_FindFontColor((FName)sc.String); } } else { desc->mFontColor = OptionSettings.mFontColor; desc->mFontColor2 = OptionSettings.mFontColorValue; } } else if (sc.Compare("NetgameMessage")) { sc.MustGetString(); desc->mNetgameMessage = sc.String; } else if (sc.Compare("PlayerDisplay")) { bool noportrait = false; FName action = NAME_None; sc.MustGetNumber(); int x = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); int y = sc.Number; sc.MustGetStringName(","); sc.MustGetString(); PalEntry c1 = V_GetColor(NULL, sc.String); sc.MustGetStringName(","); sc.MustGetString(); PalEntry c2 = V_GetColor(NULL, sc.String); if (sc.CheckString(",")) { sc.MustGetNumber(); noportrait = !!sc.Number; if (sc.CheckString(",")) { sc.MustGetString(); action = sc.String; } } FListMenuItemPlayerDisplay *it = new FListMenuItemPlayerDisplay(desc, x, y, c1, c2, noportrait, action); desc->mItems.Push(it); } else if (sc.Compare("PlayerNameBox")) { sc.MustGetString(); FString text = sc.String; sc.MustGetStringName(","); sc.MustGetNumber(); int ofs = sc.Number; sc.MustGetStringName(","); sc.MustGetString(); FListMenuItem *it = new FPlayerNameBox(desc->mXpos, desc->mYpos, desc->mLinespacing, ofs, text, desc->mFont, desc->mFontColor, sc.String); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; } else if (sc.Compare("ValueText")) { sc.MustGetString(); FString text = sc.String; sc.MustGetStringName(","); sc.MustGetString(); FName action = sc.String; FName values; if (sc.CheckString(",")) { sc.MustGetString(); values = sc.String; } FListMenuItem *it = new FValueTextItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, values); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; } else if (sc.Compare("Slider")) { sc.MustGetString(); FString text = sc.String; sc.MustGetStringName(","); sc.MustGetString(); FString action = sc.String; sc.MustGetStringName(","); sc.MustGetNumber(); int min = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); int max = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); int step = sc.Number; FListMenuItem *it = new FSliderItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, action, min, max, step); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; } else { sc.ScriptError("Unknown keyword '%s'", sc.String); } } }
void MapLoader::parseEDLinedef(FScanner &sc, TMap<int, EDLinedef> &EDLines) { EDLinedef ld; bool argsset = false; memset(&ld, 0, sizeof(ld)); ld.alpha = 1.; sc.MustGetStringName("{"); while (!sc.CheckString("}")) { sc.MustGetString(); if (sc.Compare("recordnum")) { sc.CheckString("="); sc.MustGetNumber(); ld.recordnum = sc.Number; } else if (sc.Compare("tag")) { sc.CheckString("="); sc.MustGetNumber(); ld.tag = sc.Number; } else if (sc.Compare("id")) { sc.CheckString("="); sc.MustGetNumber(); ld.id = sc.Number; } else if (sc.Compare("special")) { sc.CheckString("="); if (sc.CheckNumber()) { // Oh joy, this is going to be fun... // Here we cannot do anything because we need the tag to make this work. // For now just store a negative number and resolve this later. ld.special = -sc.Number; } else { sc.MustGetString(); ld.special = P_FindLineSpecial(sc.String); } } else if (sc.Compare("args")) { sc.CheckString("="); sc.MustGetStringName("{"); int c = 0; while (true) { sc.MustGetNumber(); ld.args[c++] = sc.Number; if (sc.CheckString("}")) break; sc.MustGetStringName(","); } argsset = true; } else if (sc.Compare("alpha")) { sc.CheckString("="); sc.MustGetFloat(); ld.alpha = sc.Float; } else if (sc.Compare("extflags")) { // these are needed to build the proper activation mask out of the possible flags which do not match ZDoom 1:1. uint32_t actmethod = 0; uint32_t acttype = 0; do { sc.CheckString("="); sc.MustGetString(); for (const char *tok = strtok(sc.String, ",+ \t"); tok != nullptr; tok = strtok(nullptr, ",+ \t")) { if (!stricmp(tok, "USE")) actmethod |= SPAC_Use | SPAC_MUse; else if (!stricmp(tok, "CROSS")) actmethod |= SPAC_Cross | SPAC_MCross | SPAC_PCross; else if (!stricmp(tok, "IMPACT")) ld.activation |= SPAC_Impact; else if (!stricmp(tok, "PUSH")) actmethod |= SPAC_Push; else if (!stricmp(tok, "PLAYER")) acttype |= SPAC_Use | SPAC_Cross | SPAC_Push; else if (!stricmp(tok, "MONSTER")) acttype |= SPAC_MUse | SPAC_MCross | SPAC_MPush; else if (!stricmp(tok, "MISSILE")) acttype |= SPAC_PCross; else if (!stricmp(tok, "REPEAT")) ld.flags |= ML_REPEAT_SPECIAL; else if (!stricmp(tok, "1SONLY")) ld.flags |= ML_FIRSTSIDEONLY; else if (!stricmp(tok, "ADDITIVE")) ld.flags |= ML_ADDTRANS; else if (!stricmp(tok, "BLOCKALL")) ld.flags |= ML_BLOCKEVERYTHING; else if (!stricmp(tok, "ZONEBOUNDARY")) ld.flags |= ML_ZONEBOUNDARY; else if (!stricmp(tok, "CLIPMIDTEX")) ld.flags |= ML_CLIP_MIDTEX; else sc.ScriptError("Unknown option '%s'", tok); } } while (sc.CheckString("|")); // Unquoted strings with '|' separator - parse as a separate string in the loop. // and finally we must mask in the activation method ld.activation |= (actmethod & acttype); } else { sc.ScriptError("Unknown property '%s'", sc.String); } } if (ld.tag == 0) ld.tag = ld.id; // urgh... if (ld.special < 0) // translate numeric specials. { line_t line; maplinedef_t mld; mld.special = -ld.special; mld.tag = ld.tag; Level->TranslateLineDef(&line, &mld); ld.special = line.special; ld.activation = line.activation; ld.flags = (ld.flags & ~(ML_REPEAT_SPECIAL | ML_FIRSTSIDEONLY)) | (line.flags & (ML_REPEAT_SPECIAL | ML_FIRSTSIDEONLY)); if (!argsset) memcpy(ld.args, line.args, sizeof(ld.args)); } EDLines[ld.recordnum] = ld; }
void FTextureManager::ParseAnim (FScanner &sc, int usetype) { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; TArray<FAnimDef::FAnimFrame> frames (32); FTextureID picnum; int defined = 0; bool optional = false, missing = false; sc.MustGetString (); if (sc.Compare ("optional")) { optional = true; sc.MustGetString (); } picnum = CheckForTexture (sc.String, usetype, texflags); if (!picnum.Exists()) { if (optional) { missing = true; } else { Printf (PRINT_BOLD, "ANIMDEFS: Can't find %s\n", sc.String); } } // no decals on animating textures, by default if (picnum.isValid()) { Texture(picnum)->bNoDecals = true; } while (sc.GetString ()) { if (sc.Compare ("allowdecals")) { if (picnum.isValid()) { Texture(picnum)->bNoDecals = false; } continue; } else if (sc.Compare ("range")) { if (defined == 2) { sc.ScriptError ("You cannot use \"pic\" and \"range\" together in a single animation."); } if (defined == 1) { sc.ScriptError ("You can only use one \"range\" per animation."); } defined = 1; ParseRangeAnim (sc, picnum, usetype, missing); } else if (sc.Compare ("pic")) { if (defined == 1) { sc.ScriptError ("You cannot use \"pic\" and \"range\" together in a single animation."); } defined = 2; ParsePicAnim (sc, picnum, usetype, missing, frames); } else { sc.UnGet (); break; } } // If base pic is not present, don't add this anim // ParseRangeAnim adds the anim itself, but ParsePicAnim does not. if (picnum.isValid() && defined == 2) { if (frames.Size() < 2) { sc.ScriptError ("Animation needs at least 2 frames"); } AddComplexAnim (picnum, frames); } }
static void parseMapthing(FScanner &sc, TMap<int, EDMapthing> &EDThings) { EDMapthing mt; memset(&mt, 0, sizeof(mt)); mt.flags |= MTF_SINGLE | MTF_COOPERATIVE | MTF_DEATHMATCH; // Extradata uses inverse logic, like Doom.exe sc.MustGetStringName("{"); while (!sc.CheckString("}")) { sc.MustGetString(); if (sc.Compare("recordnum")) { sc.CheckString("="); sc.MustGetNumber(); mt.recordnum = sc.Number; } else if (sc.Compare("tid")) { sc.CheckString("="); sc.MustGetNumber(); mt.tid = sc.Number; } else if (sc.Compare("type")) { sc.CheckString("="); if (sc.CheckNumber()) { mt.type = sc.Number; } else { // Class name. sc.MustGetString(); // According to the Eternity Wiki a name may be prefixed with 'thing:'. const char *pos = strchr(sc.String, ':'); // Eternity never checks if the prefix actually is 'thing'. if (pos) pos++; else pos = sc.String; const PClass *cls = PClass::FindClass(pos); if (cls != nullptr) { FDoomEdMap::Iterator it(DoomEdMap); FDoomEdMap::Pair *pair; while (it.NextPair(pair)) { if (pair->Value.Type == cls) { mt.type = pair->Key; break; } } } else { // Let's hope this isn't an internal Eternity name. // If so, a name mapping needs to be defined... sc.ScriptError("Unknown type '%s'", sc.String); } } } else if (sc.Compare("args")) { sc.CheckString("="); sc.MustGetStringName("{"); int c = 0; while (!sc.CheckString("}")) { sc.MustGetNumber(); mt.args[c++] = sc.Number; } } else if (sc.Compare("height")) { sc.CheckString("="); sc.MustGetFloat(); // no idea if Eternity allows fractional numbers. Better be safe and do it anyway. mt.height = sc.Float; } else if (sc.Compare("options")) { sc.CheckString("="); do { sc.MustGetString(); for (const char *tok = strtok(sc.String, ",+ \t"); tok != nullptr; tok = strtok(nullptr, ",+ \t")) { if (!stricmp(tok, "EASY")) mt.skillfilter |= 3; else if (!stricmp(tok, "NORMAL")) mt.skillfilter |= 4; else if (!stricmp(tok, "HARD")) mt.skillfilter |= 24; else if (!stricmp(tok, "AMBUSH")) mt.flags |= MTF_AMBUSH; else if (!stricmp(tok, "NOTSINGLE")) mt.flags &= ~MTF_SINGLE; else if (!stricmp(tok, "NOTDM")) mt.flags &= ~MTF_DEATHMATCH; else if (!stricmp(tok, "NOTCOOP")) mt.flags &= ~MTF_COOPERATIVE; else if (!stricmp(tok, "FRIEND")) mt.flags |= MTF_FRIENDLY; else if (!stricmp(tok, "DORMANT")) mt.flags |= MTF_DORMANT; else sc.ScriptError("Unknown option '%s'", tok); } } while (sc.CheckString("|")); // Unquoted strings with '|' separator - parse as a separate string in the loop. } else { sc.ScriptError("Unknown property '%s'", sc.String); } } EDThings[mt.recordnum] = mt; }
static void parseSector(FScanner &sc, TMap<int, EDSector> &EDSectors) { EDSector sec; memset(&sec, 0, sizeof(sec)); sec.Overlayalpha[sector_t::floor] = sec.Overlayalpha[sector_t::ceiling] = 1.; sec.floorterrain = sec.ceilingterrain = -1; sc.MustGetStringName("{"); while (!sc.CheckString("}")) { sc.MustGetString(); if (sc.Compare("recordnum")) { sc.CheckString("="); sc.MustGetNumber(); sec.recordnum = sc.Number; } else if (sc.Compare("flags")) { uint32_t *flagvar = nullptr; if (sc.CheckString(".")) { sc.MustGetString(); if (sc.Compare("add")) { flagvar = &sec.flagsAdd; } else if (sc.Compare("remove")) { flagvar = &sec.flagsRemove; } else { sc.ScriptError("Invalid property 'flags.%s'", sc.String); } } else { sec.flagsSet = true; flagvar = &sec.flags; } sc.CheckString("="); do { sc.MustGetString(); for (const char *tok = strtok(sc.String, ",+ \t"); tok != nullptr; tok = strtok(nullptr, ",+ \t")) { if (!stricmp(tok, "SECRET")) *flagvar |= SECF_SECRET | SECF_WASSECRET; else if (!stricmp(tok, "FRICTION")) *flagvar |= SECF_FRICTION; else if (!stricmp(tok, "PUSH")) *flagvar |= SECF_PUSH; else if (!stricmp(tok, "KILLSOUND")) *flagvar |= SECF_SILENT; else if (!stricmp(tok, "KILLMOVESOUND")) *flagvar |= SECF_SILENTMOVE; else sc.ScriptError("Unknown option '%s'", tok); } } while (sc.CheckString("|")); // Unquoted strings with '|' separator - parse as a separate string in the loop. } else if (sc.Compare("damage")) { sc.CheckString("="); sc.MustGetNumber(); sec.damageamount = sc.Number; } else if (sc.Compare("damagemod")) { sc.CheckString("="); sc.MustGetString(); sec.damagetype = sc.String; } else if (sc.Compare("damagemask")) { sc.CheckString("="); sc.MustGetNumber(); sec.damageinterval = sc.Number; } else if (sc.Compare("damageflags")) { uint32_t *flagvar = nullptr; uint8_t *leakvar = nullptr; if (sc.CheckString(".")) { sc.MustGetString(); if (sc.Compare("add")) { flagvar = &sec.damageflagsAdd; leakvar = &sec.leakyadd; } else if (sc.Compare("remove")) { flagvar = &sec.damageflagsRemove; leakvar = &sec.leakyremove; } else { sc.ScriptError("Invalid property 'flags.%s'", sc.String); } } else { sec.damageflagsSet = true; flagvar = &sec.damageflags; leakvar = &sec.leaky; } sc.CheckString("="); do { sc.MustGetString(); for (const char *tok = strtok(sc.String, ",+ \t"); tok != nullptr; tok = strtok(nullptr, ",+ \t")) { if (!stricmp(tok, "LEAKYSUIT")) *leakvar |= 1; else if (!stricmp(tok, "IGNORESUIT")) *leakvar |= 2; // these 2 bits will be used to set 'leakychance', but this can only be done when the sector gets initialized else if (!stricmp(tok, "ENDGODMODE")) *flagvar |= SECF_ENDGODMODE; else if (!stricmp(tok, "ENDLEVEL")) *flagvar |= SECF_ENDLEVEL; else if (!stricmp(tok, "TERRAINHIT")) *flagvar |= SECF_DMGTERRAINFX; else sc.ScriptError("Unknown option '%s'", tok); } } while (sc.CheckString("|")); // Unquoted strings with '|' separator - parse as a separate string in the loop. } else if (sc.Compare("floorterrain")) { sc.CheckString("="); sc.MustGetString(); sec.floorterrain = P_FindTerrain(sc.String); } else if (sc.Compare("floorangle")) { sc.CheckString("="); sc.MustGetFloat(); sec.angle[sector_t::floor] = sc.Float; } else if (sc.Compare("flooroffsetx")) { sc.CheckString("="); sc.MustGetFloat(); sec.xoffs[sector_t::floor] = sc.Float; } else if (sc.Compare("flooroffsety")) { sc.CheckString("="); sc.MustGetFloat(); sec.yoffs[sector_t::floor] = sc.Float; } else if (sc.Compare("ceilingterrain")) { sc.CheckString("="); sc.MustGetString(); sec.ceilingterrain = P_FindTerrain(sc.String); } else if (sc.Compare("ceilingangle")) { sc.CheckString("="); sc.MustGetFloat(); sec.angle[sector_t::ceiling] = sc.Float; } else if (sc.Compare("ceilingoffsetx")) { sc.CheckString("="); sc.MustGetFloat(); sec.xoffs[sector_t::ceiling] = sc.Float; } else if (sc.Compare("ceilingoffsety")) { sc.CheckString("="); sc.MustGetFloat(); sec.yoffs[sector_t::ceiling] = sc.Float; } else if (sc.Compare("colormaptop") || sc.Compare("colormapbottom")) { sc.CheckString("="); sc.MustGetString(); // these properties are not implemented by ZDoom } else if (sc.Compare("colormapmid")) { sc.CheckString("="); sc.MustGetString(); // Eternity is based on SMMU and uses colormaps differently than all other ports. // The only solution here is to convert the colormap to an RGB value and set it as the sector's color. uint32_t cmap = R_ColormapNumForName(sc.String); if (cmap != 0) { sec.color = R_BlendForColormap(cmap) & 0xff000000; sec.colorSet = true; } } else if (sc.Compare("overlayalpha")) { sc.MustGetStringName("."); sc.MustGetString(); if (sc.Compare("floor")) { sc.MustGetNumber(); if (sc.CheckString("%")) sc.Float = sc.Number / 100.f; else sc.Float = sc.Number / 255.f; sec.Overlayalpha[sector_t::floor] = sc.Float; } else if (sc.Compare("ceiling")) { sc.MustGetFloat(); if (sc.CheckString("%")) sc.Float = sc.Number / 100.f; else sc.Float = sc.Number / 255.f; sec.Overlayalpha[sector_t::floor] = sc.Float; } } else if (sc.Compare("portalflags")) { int dest = 0; sc.MustGetStringName("."); sc.MustGetString(); if (sc.Compare("floor")) dest = sector_t::floor; else if (sc.Compare("ceiling")) dest = sector_t::ceiling; else sc.ScriptError("Unknown portal type '%s'", sc.String); sc.CheckString("="); do { sc.MustGetString(); for (const char *tok = strtok(sc.String, ",+ \t"); tok != nullptr; tok = strtok(nullptr, ",+ \t")) { if (!stricmp(tok, "DISABLED")) sec.portalflags[dest] |= PLANEF_DISABLED; else if (!stricmp(tok, "NORENDER")) sec.portalflags[dest] |= PLANEF_NORENDER; else if (!stricmp(tok, "NOPASS")) sec.portalflags[dest] |= PLANEF_NOPASS; else if (!stricmp(tok, "BLOCKSOUND")) sec.portalflags[dest] |= PLANEF_BLOCKSOUND; else if (!stricmp(tok, "OVERLAY")) sec.portalflags[dest] |= 0; // we do not use this. Alpha is the sole determinant for overlay drawing else if (!stricmp(tok, "ADDITIVE")) sec.portalflags[dest] |= PLANEF_ADDITIVE; else if (!stricmp(tok, "USEGLOBALTEX")) {} // not implemented else sc.ScriptError("Unknown option '%s'", tok); } } while (sc.CheckString("|")); // Unquoted strings with '|' separator - parse as a separate string in the loop. } else { sc.ScriptError("Unknown property '%s'", sc.String); } } EDSectors[sec.recordnum] = sec; }
void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, TexInit &init) { FString patchname; int Mirror = 0; sc.MustGetString(); init.TexName = sc.String; sc.MustGetStringName(","); sc.MustGetNumber(); part.OriginX = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); part.OriginY = sc.Number; if (sc.CheckString("{")) { while (!sc.CheckString("}")) { sc.MustGetString(); if (sc.Compare("flipx")) { Mirror |= 1; } else if (sc.Compare("flipy")) { Mirror |= 2; } else if (sc.Compare("rotate")) { sc.MustGetNumber(); sc.Number = (((sc.Number + 90)%360)-90); if (sc.Number != 0 && sc.Number !=90 && sc.Number != 180 && sc.Number != -90) { sc.ScriptError("Rotation must be a multiple of 90 degrees."); } part.Rotate = (sc.Number / 90) & 3; } else if (sc.Compare("Translation")) { int match; bComplex = true; if (part.Translation != NULL) delete part.Translation; part.Translation = NULL; part.Blend = 0; static const char *maps[] = { "inverse", "gold", "red", "green", "blue", NULL }; sc.MustGetString(); match = sc.MatchString(maps); if (match >= 0) { part.Blend = BLEND_SPECIALCOLORMAP1 + match; } else if (sc.Compare("ICE")) { part.Blend = BLEND_ICEMAP; } else if (sc.Compare("DESATURATE")) { sc.MustGetStringName(","); sc.MustGetNumber(); part.Blend = BLEND_DESATURATE1 + clamp(sc.Number-1, 0, 30); } else { sc.UnGet(); part.Translation = new FRemapTable; part.Translation->MakeIdentity(); do { sc.MustGetString(); part.Translation->AddToTranslation(sc.String); } while (sc.CheckString(",")); } } else if (sc.Compare("Colormap")) { float r1,g1,b1; float r2,g2,b2; sc.MustGetFloat(); r1 = (float)sc.Float; sc.MustGetStringName(","); sc.MustGetFloat(); g1 = (float)sc.Float; sc.MustGetStringName(","); sc.MustGetFloat(); b1 = (float)sc.Float; if (!sc.CheckString(",")) { part.Blend = AddSpecialColormap(0,0,0, r1, g1, b1); } else { sc.MustGetFloat(); r2 = (float)sc.Float; sc.MustGetStringName(","); sc.MustGetFloat(); g2 = (float)sc.Float; sc.MustGetStringName(","); sc.MustGetFloat(); b2 = (float)sc.Float; part.Blend = AddSpecialColormap(r1, g1, b1, r2, g2, b2); } } else if (sc.Compare("Blend")) { bComplex = true; if (part.Translation != NULL) delete part.Translation; part.Translation = NULL; part.Blend = 0; if (!sc.CheckNumber()) { sc.MustGetString(); part.Blend = V_GetColor(NULL, sc); } else { int r,g,b; r = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); g = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); b = sc.Number; //sc.MustGetStringName(","); This was never supposed to be here. part.Blend = MAKERGB(r, g, b); } // Blend.a may never be 0 here. if (sc.CheckString(",")) { sc.MustGetFloat(); if (sc.Float > 0.f) part.Blend.a = clamp<int>(int(sc.Float*255), 1, 254); else part.Blend = 0; } else part.Blend.a = 255; } else if (sc.Compare("alpha")) { sc.MustGetFloat(); part.Alpha = clamp<blend_t>(int(sc.Float * BLENDUNIT), 0, BLENDUNIT); // bComplex is not set because it is only needed when the style is not OP_COPY. } else if (sc.Compare("style")) { static const char *styles[] = {"copy", "translucent", "add", "subtract", "reversesubtract", "modulate", "copyalpha", "copynewalpha", "overlay", NULL }; sc.MustGetString(); part.op = sc.MustMatchString(styles); bComplex |= (part.op != OP_COPY); bTranslucentPatches = bComplex; } else if (sc.Compare("useoffsets")) { init.UseOffsets = true; } } } if (Mirror & 2) { part.Rotate = (part.Rotate + 2) & 3; Mirror ^= 1; } if (Mirror & 1) { part.Rotate |= 4; } }
FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, ETextureType usetype) : Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) { TArray<TexPart> parts; TArray<TexInit> inits; bool bSilent = false; bMultiPatch = true; sc.SetCMode(true); sc.MustGetString(); const char* textureName = NULL; if (sc.Compare("optional")) { bSilent = true; sc.MustGetString(); if (sc.Compare(",")) { // this is not right. Apparently a texture named 'optional' is being defined right now... sc.UnGet(); textureName = "optional"; bSilent = false; } } Name = !textureName ? sc.String : textureName; Name.ToUpper(); sc.MustGetStringName(","); sc.MustGetNumber(); Width = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); Height = sc.Number; UseType = usetype; bool offset2set = false; if (sc.CheckString("{")) { while (!sc.CheckString("}")) { sc.MustGetString(); if (sc.Compare("XScale")) { sc.MustGetFloat(); Scale.X = sc.Float; if (Scale.X == 0) sc.ScriptError("Texture %s is defined with null x-scale\n", Name.GetChars()); } else if (sc.Compare("YScale")) { sc.MustGetFloat(); Scale.Y = sc.Float; if (Scale.Y == 0) sc.ScriptError("Texture %s is defined with null y-scale\n", Name.GetChars()); } else if (sc.Compare("WorldPanning")) { bWorldPanning = true; } else if (sc.Compare("NullTexture")) { UseType = ETextureType::Null; } else if (sc.Compare("NoDecals")) { bNoDecals = true; } else if (sc.Compare("Patch")) { TexPart part; TexInit init; ParsePatch(sc, part, init); if (init.TexName.IsNotEmpty()) { parts.Push(part); init.UseType = ETextureType::WallPatch; init.Silent = bSilent; init.HasLine = true; init.sc = sc; inits.Push(init); } part.Texture = NULL; part.Translation = NULL; } else if (sc.Compare("Sprite")) { TexPart part; TexInit init; ParsePatch(sc, part, init); if (init.TexName.IsNotEmpty()) { parts.Push(part); init.UseType = ETextureType::Sprite; init.Silent = bSilent; init.HasLine = true; init.sc = sc; inits.Push(init); } part.Texture = NULL; part.Translation = NULL; } else if (sc.Compare("Graphic")) { TexPart part; TexInit init; ParsePatch(sc, part, init); if (init.TexName.IsNotEmpty()) { parts.Push(part); init.UseType = ETextureType::MiscPatch; init.Silent = bSilent; init.HasLine = true; init.sc = sc; inits.Push(init); } part.Texture = NULL; part.Translation = NULL; } else if (sc.Compare("Offset")) { sc.MustGetNumber(); _LeftOffset[0] = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); _TopOffset[0] = sc.Number; if (!offset2set) { _LeftOffset[1] = _LeftOffset[0]; _TopOffset[1] = _TopOffset[0]; } } else if (sc.Compare("Offset2")) { sc.MustGetNumber(); _LeftOffset[1] = sc.Number; sc.MustGetStringName(","); sc.MustGetNumber(); _TopOffset[1] = sc.Number; offset2set = true; } else { sc.ScriptError("Unknown texture property '%s'", sc.String); } } NumParts = parts.Size(); Parts = new TexPart[NumParts]; memcpy(Parts, &parts[0], NumParts * sizeof(*Parts)); Inits = new TexInit[NumParts]; for (int i = 0; i < NumParts; i++) { Inits[i] = inits[i]; } } if (Width <= 0 || Height <= 0) { UseType = ETextureType::Null; Printf("Texture %s has invalid dimensions (%d, %d)\n", Name.GetChars(), Width, Height); Width = Height = 1; } CalcBitSize (); sc.SetCMode(false); }
static int ParseStandardProperty(FScanner &scanner, UMapEntry *mape) { // find the next line with content. // this line is no property. scanner.MustGetToken(TK_Identifier); FString pname = scanner.String; scanner.MustGetToken('='); if (!pname.CompareNoCase("levelname")) { scanner.MustGetToken(TK_StringConst); mape->LevelName = scanner.String; } else if (!pname.CompareNoCase("next")) { ParseLumpName(scanner, mape->nextmap); } else if (!pname.CompareNoCase("nextsecret")) { ParseLumpName(scanner, mape->nextsecret); } else if (!pname.CompareNoCase("levelpic")) { ParseLumpName(scanner, mape->levelpic); } else if (!pname.CompareNoCase("skytexture")) { ParseLumpName(scanner, mape->skytexture); } else if (!pname.CompareNoCase("music")) { ParseLumpName(scanner, mape->music); } else if (!pname.CompareNoCase("endpic")) { ParseLumpName(scanner, mape->endpic); } else if (!pname.CompareNoCase("endcast")) { scanner.MustGetBoolToken(); if (scanner.Number) strcpy(mape->endpic, "$CAST"); else strcpy(mape->endpic, "-"); } else if (!pname.CompareNoCase("endbunny")) { scanner.MustGetBoolToken(); if (scanner.Number) strcpy(mape->endpic, "$BUNNY"); else strcpy(mape->endpic, "-"); } else if (!pname.CompareNoCase("endgame")) { scanner.MustGetBoolToken(); if (scanner.Number) strcpy(mape->endpic, "!"); else strcpy(mape->endpic, "-"); } else if (!pname.CompareNoCase("exitpic")) { ParseLumpName(scanner, mape->exitpic); } else if (!pname.CompareNoCase("enterpic")) { ParseLumpName(scanner, mape->enterpic); } else if (!pname.CompareNoCase("nointermission")) { scanner.MustGetBoolToken(); mape->nointermission = scanner.Number; } else if (!pname.CompareNoCase("partime")) { scanner.MustGetValue(false); mape->partime = TICRATE * scanner.Number; } else if (!pname.CompareNoCase("intertext")) { mape->InterText = ParseMultiString(scanner, 1); if (mape->InterText.IsEmpty()) return 0; } else if (!pname.CompareNoCase("intertextsecret")) { mape->InterTextSecret = ParseMultiString(scanner, 1); if (mape->InterTextSecret.IsEmpty()) return 0; } else if (!pname.CompareNoCase("interbackdrop")) { ParseLumpName(scanner, mape->interbackdrop); } else if (!pname.CompareNoCase("intermusic")) { ParseLumpName(scanner, mape->intermusic); } else if (!pname.CompareNoCase("episode")) { FString Episode = ParseMultiString(scanner, 1); if (Episode.IsEmpty()) return 0; if (Episode.Compare("-") == 0) { // clear the given episode for (unsigned i = 0; i < AllEpisodes.Size(); i++) { if (AllEpisodes[i].mEpisodeMap.CompareNoCase(mape->MapName) == 0) { AllEpisodes.Delete(i); break; } } } else { auto split = Episode.Split("\n"); // add the given episode FEpisode epi; epi.mEpisodeName = strbin1(split[1]); epi.mEpisodeMap = mape->MapName; epi.mPicName = split[0]; epi.mShortcut = split[2][0]; unsigned i; for (i = 0; i < AllEpisodes.Size(); i++) { if (AllEpisodes[i].mEpisodeMap.CompareNoCase(mape->MapName) == 0) { AllEpisodes[i] = std::move(epi); break; } } if (i == AllEpisodes.Size()) { AllEpisodes.Push(epi); } } } else if (!pname.CompareNoCase("bossaction")) { scanner.MustGetToken(TK_Identifier); int classnum, special, tag; if (!stricmp(scanner.String, "clear")) { // mark level free of boss actions classnum = special = tag = -1; mape->BossActions.Clear(); } else { FName type = scanner.String; scanner.MustGetToken(','); scanner.MustGetValue(false); int special = scanner.Number; scanner.MustGetToken(','); scanner.MustGetValue(false); int tag = scanner.Number; // allow no 0-tag specials here, unless a level exit. if (tag != 0 || special == 11 || special == 51 || special == 52 || special == 124) { // This cannot be evaluated here because this needs to be done in the context of the level being used. FSpecialAction & bossact = mape->BossActions[mape->BossActions.Reserve(1)]; bossact = { type, special | 0x40000000, {tag} }; }; } } else { // Skip over all unknown properties. do { if (!scanner.CheckValue(true)) { scanner.MustGetAnyToken(); if (scanner.TokenType != TK_Identifier && scanner.TokenType != TK_StringConst && scanner.TokenType != TK_True && scanner.TokenType != TK_False) { scanner.ScriptError("Identifier or value expected"); } } } while (scanner.CheckToken(',')); } return 1; }