diff --git a/docs/rh-log.txt b/docs/rh-log.txt index eb2a05e52f..bf9d6b86c0 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,19 @@ August 8, 2008 +- SBARINFO update: + * Added: The ability to have drawkeybar auto detect spacing. + * Added: Offset parameter to drawkeybar to allow two key bars with + different keys. + * Added: Multi-row/column keybar parameters. Spacing can also be auto. + These defualt to left to right/top to bottom but can be switched. + * Added: Drawshadow flag to drawnumber. This will draw a solid color and + translucent number under the normal number. + * Added: hexenarmor to drawimage. This takes a parameter for a hexen + armor type and will fade the image like the hexen status bar. + * Added: centerbottom offset to draw(switchable)image. + * Added: translucent flag to drawinventorybar. + * Fixed: Accidentally removed flag from DrawTexture that allowed negative + coordinates to work with fullscreenoffsets. Hopefully this is the last + major bug in the fullscreenoffsets system. - Ported vlinetallasm4 to AMD64 assembly. Even with the increased number of registers AMD64 provides, this routine still needs to be written as self- modifying code for maximum performance. The additional registers do allow diff --git a/src/g_shared/sbarinfo.h b/src/g_shared/sbarinfo.h index 0f078b1482..70be21881b 100644 --- a/src/g_shared/sbarinfo.h +++ b/src/g_shared/sbarinfo.h @@ -170,10 +170,12 @@ enum //drawimage flags DRAWIMAGE_SWITCHABLE_AND = 0x40, DRAWIMAGE_INVULNERABILITY = 0x80, DRAWIMAGE_OFFSET_CENTER = 0x100, - DRAWIMAGE_ARMOR = 0x200, - DRAWIMAGE_WEAPONICON = 0x400, - DRAWIMAGE_SIGIL = 0x800, - DRAWIMAGE_KEYSLOT = 0x1000, + DRAWIMAGE_OFFSET_CENTERBOTTOM = 0x200, + DRAWIMAGE_ARMOR = 0x400, + DRAWIMAGE_WEAPONICON = 0x800, + DRAWIMAGE_SIGIL = 0x1000, + DRAWIMAGE_KEYSLOT = 0x2000, + DRAWIMAGE_HEXENARMOR = 0x4000, }; enum //drawnumber flags @@ -198,6 +200,7 @@ enum //drawnumber flags DRAWNUMBER_FILLZEROS = 0x20000, DRAWNUMBER_WHENNOTZERO = 0x40000, DRAWNUMBER_POWERUPTIME = 0x80000, + DRAWNUMBER_DRAWSHADOW = 0x100000, }; enum //drawbar flags (will go into special2) @@ -216,10 +219,11 @@ enum //drawselectedinventory flags enum //drawinventorybar flags { - DRAWINVENTORYBAR_ALWAYSSHOW = 1, - DRAWINVENTORYBAR_NOARTIBOX = 2, - DRAWINVENTORYBAR_NOARROWS = 4, - DRAWINVENTORYBAR_ALWAYSSHOWCOUNTER = 8, + DRAWINVENTORYBAR_ALWAYSSHOW = 0x1, + DRAWINVENTORYBAR_NOARTIBOX = 0x2, + DRAWINVENTORYBAR_NOARROWS = 0x4, + DRAWINVENTORYBAR_ALWAYSSHOWCOUNTER = 0x8, + DRAWINVENTORYBAR_TRANSLUCENT = 0x10, }; enum //drawgem flags @@ -248,7 +252,8 @@ enum //drawmugshot flags enum //drawkeybar flags { - DRAWKEYBAR_VERTICAL = 1, + DRAWKEYBAR_VERTICAL = 0x1, + DRAWKEYBAR_REVERSEROWS = 0x2, }; enum //event flags @@ -345,9 +350,9 @@ public: void SetMugShotState(const char* stateName, bool waitTillDone=false, bool reset=false); private: void doCommands(SBarInfoBlock &block, int xOffset=0, int yOffset=0, int alpha=FRACUNIT); - void DrawGraphic(FTexture* texture, int x, int y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, bool translate=false, bool dim=false, bool center=false); - void DrawString(const char* str, int x, int y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, EColorRange translation, int spacing=0); - void DrawNumber(int num, int len, int x, int y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, EColorRange translation, int spacing=0, bool fillzeros=false); + void DrawGraphic(FTexture* texture, int x, int y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, bool translate=false, bool dim=false, int offsetflags=0); + void DrawString(const char* str, int x, int y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, EColorRange translation, int spacing=0, bool drawshadow=false); + void DrawNumber(int num, int len, int x, int y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, EColorRange translation, int spacing=0, bool fillzeros=false, bool drawshadow=false); void DrawFace(const char *defaultFace, int accuracy, int stateflags, int x, int y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets); int updateState(bool xdth, bool animatedgodmode); void DrawInventoryBar(int type, int num, int x, int y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, bool alwaysshow, diff --git a/src/g_shared/sbarinfo_display.cpp b/src/g_shared/sbarinfo_display.cpp index 26a0dc2e5f..1804a08a7f 100644 --- a/src/g_shared/sbarinfo_display.cpp +++ b/src/g_shared/sbarinfo_display.cpp @@ -62,6 +62,7 @@ static FRandom pr_chainwiggle; //use the same method of chain wiggling as hereti EXTERN_CVAR(Int, fraglimit) EXTERN_CVAR(Int, screenblocks) +EXTERN_CVAR(Bool, vid_fps) enum { @@ -486,11 +487,11 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a if(drawAlt != 0) //draw 'off' image { if(cmd.special != -1 && drawAlt == 1) - DrawGraphic(Images[cmd.special], cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, !!(cmd.flags & DRAWIMAGE_OFFSET_CENTER)); + DrawGraphic(Images[cmd.special], cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, !!(cmd.flags & (DRAWIMAGE_OFFSET_CENTER|DRAWIMAGE_OFFSET_CENTERBOTTOM))); else if(cmd.special2 != -1 && drawAlt == 2) - DrawGraphic(Images[cmd.special2], cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, !!(cmd.flags & DRAWIMAGE_OFFSET_CENTER)); + DrawGraphic(Images[cmd.special2], cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, !!(cmd.flags & (DRAWIMAGE_OFFSET_CENTER|DRAWIMAGE_OFFSET_CENTERBOTTOM))); else if(cmd.special3 != -1 && drawAlt == 3) - DrawGraphic(Images[cmd.special3], cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, !!(cmd.flags & DRAWIMAGE_OFFSET_CENTER)); + DrawGraphic(Images[cmd.special3], cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false,(cmd.flags & (DRAWIMAGE_OFFSET_CENTER|DRAWIMAGE_OFFSET_CENTERBOTTOM))); break; } } @@ -528,12 +529,28 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a if (item != NULL) texture = TexMan[item->Icon]; } + else if(cmd.flags & DRAWIMAGE_HEXENARMOR) + { + AHexenArmor *harmor = CPlayer->mo->FindInventory(); + if (harmor != NULL) + { + if (harmor->Slots[cmd.value] > 0 && harmor->SlotsIncrement[cmd.value] > 0) + { + //combine the alpha values + alpha = fixed_t(((double) alpha / (double) FRACUNIT) * ((double) MIN (OPAQUE, Scale(harmor->Slots[cmd.value], OPAQUE, harmor->SlotsIncrement[cmd.value])) / (double) OPAQUE) * FRACUNIT); + texture = Images[cmd.image_index]; + } + else + break; + } + } else if((cmd.flags & DRAWIMAGE_INVENTORYICON)) texture = TexMan[cmd.sprite_index]; else if(cmd.image_index >= 0) texture = Images[cmd.image_index]; - DrawGraphic(texture, cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, !!(cmd.flags & DRAWIMAGE_OFFSET_CENTER)); + // if we reach here with DRAWIMAGE_HEXENARMOR set we know we want it to be dim. + DrawGraphic(texture, cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, !!(cmd.flags & DRAWIMAGE_TRANSLATABLE), false, (cmd.flags & (DRAWIMAGE_OFFSET_CENTER|DRAWIMAGE_OFFSET_CENTERBOTTOM))); break; } case SBARINFO_DRAWNUMBER: @@ -653,6 +670,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a } } bool fillzeros = !!(cmd.flags & DRAWNUMBER_FILLZEROS); + bool drawshadow = !!(cmd.flags & DRAWNUMBER_DRAWSHADOW); EColorRange translation = cmd.translation; if(cmd.special3 != -1 && value <= cmd.special3) //low translation = cmd.translation2; @@ -660,7 +678,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a translation = cmd.translation3; if((cmd.flags & DRAWNUMBER_WHENNOTZERO) && value == 0) break; - DrawNumber(value, cmd.special, cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, translation, cmd.special2, fillzeros); + DrawNumber(value, cmd.special, cmd.x, cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets, translation, cmd.special2, fillzeros, drawshadow); break; } case SBARINFO_DRAWMUGSHOT: @@ -714,6 +732,8 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a noarrows = true; if((cmd.flags & DRAWINVENTORYBAR_ALWAYSSHOWCOUNTER)) alwaysshowcounter = true; + if(cmd.flags & DRAWINVENTORYBAR_TRANSLUCENT) + alpha = fixed_t((((double) alpha / (double) FRACUNIT) * ((double) HX_SHADOW / (double) FRACUNIT)) * FRACUNIT); if(drawingFont != cmd.font) { drawingFont = cmd.font; @@ -898,6 +918,8 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a y = cmd.y + yOffset; w = fg->GetScaledWidth(); h = fg->GetScaledHeight(); + if(vid_fps && x < 0 && y >= 0) + y += 10; } if(cmd.special3 != 0) @@ -907,6 +929,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a DTA_DestWidth, w, DTA_DestHeight, h, DTA_Alpha, alpha, + DTA_HUDRules, HUD_Normal, TAG_DONE); } else @@ -918,6 +941,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a DTA_DestWidth, w, DTA_DestHeight, h, DTA_Alpha, alpha, + DTA_HUDRules, HUD_Normal, TAG_DONE); } else @@ -944,6 +968,8 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a cy = cmd.y + cmd.special3 + yOffset; cw = fg->GetScaledWidth() - fg->GetScaledLeftOffset() - cmd.special3 * 2; ch = fg->GetScaledHeight() - fg->GetScaledTopOffset() - cmd.special3 * 2; + if(vid_fps && x < 0 && y >= 0) + y += 10; } if (horizontal) @@ -986,6 +1012,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a DTA_ClipRight, cr, DTA_ClipBottom, cb, DTA_Alpha, alpha, + DTA_HUDRules, HUD_Normal, TAG_DONE); } else @@ -1003,6 +1030,7 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a DTA_ClipRight, cr, DTA_ClipBottom, cb, DTA_Alpha, alpha, + DTA_HUDRules, HUD_Normal, TAG_DONE); } break; @@ -1051,12 +1079,18 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a if(Scaled) screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true); } + else + { + if(vid_fps && x < 0 && y >= 0) + y += 10; + } screen->DrawTexture (shaders[(vertical << 1) + reverse], x, y, DTA_DestWidth, w, DTA_DestHeight, h, DTA_Alpha, alpha, DTA_AlphaChannel, true, DTA_FillColor, 0, + DTA_HUDRules, HUD_Normal, TAG_DONE); break; } @@ -1073,7 +1107,10 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a AInventory *item = CPlayer->mo->Inventory; if(item == NULL) break; - for(int i = 0;i < cmd.value;i++) + int slotOffset = 0; + int rowOffset = 0; + int rowWidth = 0; + for(int i = 0;i < cmd.value+cmd.special2;i++) { while(!item->Icon.isValid() || !item->IsKindOf(RUNTIME_CLASS(AKey))) { @@ -1081,10 +1118,41 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a if(item == NULL) goto FinishDrawKeyBar; } - if(!vertical) - DrawGraphic(TexMan[item->Icon], cmd.x+(cmd.special*i), cmd.y, xOffset, yOffset, alpha, block.fullScreenOffsets); - else - DrawGraphic(TexMan[item->Icon], cmd.x, cmd.y+(cmd.special*i), xOffset, yOffset, alpha, block.fullScreenOffsets); + if(i >= cmd.special2) //Should we start drawing? + { + if(!vertical) + { + DrawGraphic(TexMan[item->Icon], cmd.x+slotOffset, cmd.y+rowOffset, xOffset, yOffset, alpha, block.fullScreenOffsets); + rowWidth = cmd.special4 == -1 ? TexMan[item->Icon]->GetScaledHeight()+2 : cmd.special4; + } + else + { + DrawGraphic(TexMan[item->Icon], cmd.x+rowOffset, cmd.y+slotOffset, xOffset, yOffset, alpha, block.fullScreenOffsets); + rowWidth = cmd.special4 == -1 ? TexMan[item->Icon]->GetScaledWidth()+2 : cmd.special4; + } + + // If cmd.special is -1 then the slot size is auto detected + if(cmd.special == -1) + { + if(!vertical) + slotOffset += TexMan[item->Icon]->GetScaledWidth() + 2; + else + slotOffset += TexMan[item->Icon]->GetScaledHeight() + 2; + } + else + slotOffset += cmd.special; + + if(cmd.special3 > 0 && (i % cmd.special3 == cmd.special3-1)) + { + if(cmd.flags & DRAWKEYBAR_REVERSEROWS) + rowOffset -= rowWidth; + else + rowOffset += rowWidth; + rowWidth = 0; + slotOffset = 0; + } + } + item = item->Inventory; if(item == NULL) break; @@ -1239,12 +1307,12 @@ void DSBarInfo::doCommands(SBarInfoBlock &block, int xOffset, int yOffset, int a //draws an image with the specified flags void DSBarInfo::DrawGraphic(FTexture* texture, int x, int y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, - bool translate, bool dim, bool center) //flags + bool translate, bool dim, int offsetflags) //flags { if (texture == NULL) return; - if(center) + if(offsetflags & DRAWIMAGE_OFFSET_CENTER) { x -= (texture->GetWidth()/2)-texture->LeftOffset; y -= (texture->GetHeight()/2)-texture->TopOffset; @@ -1272,17 +1340,21 @@ void DSBarInfo::DrawGraphic(FTexture* texture, int x, int y, int xOffset, int yO { w = texture->GetScaledWidth(); h = texture->GetScaledHeight(); + if(vid_fps && x < 0 && y >= 0) + y += 10; } screen->DrawTexture(texture, x, y, DTA_DestWidth, w, DTA_DestHeight, h, DTA_Translation, translate ? getTranslation() : 0, DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, + DTA_CenterBottomOffset, (offsetflags & DRAWIMAGE_OFFSET_CENTERBOTTOM), + DTA_HUDRules, HUD_Normal, DTA_Alpha, alpha, TAG_DONE); } -void DSBarInfo::DrawString(const char* str, int x, int y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, EColorRange translation, int spacing) +void DSBarInfo::DrawString(const char* str, int x, int y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, EColorRange translation, int spacing, bool drawshadow) { x += spacing; while(*str != '\0') @@ -1319,11 +1391,28 @@ void DSBarInfo::DrawString(const char* str, int x, int y, int xOffset, int yOffs if(Scaled) screen->VirtualToRealCoordsInt(rx, ry, rw, rh, 320, 200, true); } + else + { + if(vid_fps && x < 0 && y >= 0) + y += 10; + } + if(drawshadow) + { + int salpha = fixed_t(((double) alpha / (double) FRACUNIT) * ((double) HR_SHADOW / (double) FRACUNIT) * FRACUNIT); + screen->DrawTexture(character, rx+2, ry+2, + DTA_DestWidth, rw, + DTA_DestHeight, rh, + DTA_Alpha, salpha, + DTA_HUDRules, HUD_Normal, + DTA_FillColor, 0, + TAG_DONE); + } screen->DrawTexture(character, rx, ry, DTA_DestWidth, rw, DTA_DestHeight, rh, DTA_Translation, drawingFont->GetColorTranslation(translation), DTA_Alpha, alpha, + DTA_HUDRules, HUD_Normal, TAG_DONE); if(SBarInfoScript->spacingCharacter == '\0') x += width + spacing - (character->LeftOffset+1); @@ -1334,7 +1423,7 @@ void DSBarInfo::DrawString(const char* str, int x, int y, int xOffset, int yOffs } //draws the specified number up to len digits -void DSBarInfo::DrawNumber(int num, int len, int x, int y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, EColorRange translation, int spacing, bool fillzeros) +void DSBarInfo::DrawNumber(int num, int len, int x, int y, int xOffset, int yOffset, int alpha, bool fullScreenOffsets, EColorRange translation, int spacing, bool fillzeros, bool drawshadow) { FString value; int maxval = (int) ceil(pow(10., len))-1; @@ -1359,7 +1448,7 @@ void DSBarInfo::DrawNumber(int num, int len, int x, int y, int xOffset, int yOff x -= int(drawingFont->StringWidth(value)+(spacing * value.Len())); else //monospaced, so just multiplay the character size x -= int((drawingFont->GetCharWidth((int) SBarInfoScript->spacingCharacter) + spacing) * value.Len()); - DrawString(value, x, y, xOffset, yOffset, alpha, fullScreenOffsets, translation, spacing); + DrawString(value, x, y, xOffset, yOffset, alpha, fullScreenOffsets, translation, spacing, drawshadow); } //draws the mug shot diff --git a/src/g_shared/sbarinfo_parser.cpp b/src/g_shared/sbarinfo_parser.cpp index 7421f1f32f..06e5800125 100644 --- a/src/g_shared/sbarinfo_parser.cpp +++ b/src/g_shared/sbarinfo_parser.cpp @@ -458,6 +458,23 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block) cmd.flags |= DRAWIMAGE_WEAPONICON; else if(sc.Compare("sigil")) cmd.flags |= DRAWIMAGE_SIGIL; + else if(sc.Compare("hexenarmor")) + { + cmd.flags = DRAWIMAGE_HEXENARMOR; + sc.MustGetToken(TK_Identifier); + if(sc.Compare("armor")) + cmd.value = 0; + else if(sc.Compare("shield")) + cmd.value = 1; + else if(sc.Compare("helm")) + cmd.value = 2; + else if(sc.Compare("amulet")) + cmd.value = 3; + else + sc.ScriptError("Unkown armor type: '%s'", sc.String); + sc.MustGetToken(','); + getImage = true; + } else if(sc.Compare("translatable")) { cmd.flags |= DRAWIMAGE_TRANSLATABLE; @@ -489,8 +506,10 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block) sc.MustGetToken(TK_Identifier); if(sc.Compare("center")) cmd.flags |= DRAWIMAGE_OFFSET_CENTER; + else if(sc.Compare("centerbottom")) + cmd.flags |= DRAWIMAGE_OFFSET_CENTERBOTTOM; else - sc.ScriptError("Expected 'center' got '%s' instead.", sc.String); + sc.ScriptError("Expected 'center' or 'centerbottom' got '%s' instead.", sc.String); } sc.MustGetToken(';'); break; @@ -607,6 +626,8 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block) cmd.flags |= DRAWNUMBER_FILLZEROS; else if(sc.Compare("whennotzero")) cmd.flags |= DRAWNUMBER_WHENNOTZERO; + else if(sc.Compare("drawshadow")) + cmd.flags |= DRAWNUMBER_DRAWSHADOW; else sc.ScriptError("Unknown flag '%s'.", sc.String); if(!sc.CheckToken('|')) @@ -774,6 +795,10 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block) { cmd.flags |= DRAWINVENTORYBAR_ALWAYSSHOWCOUNTER; } + else if(sc.Compare("translucent")) + { + cmd.flags |= DRAWINVENTORYBAR_TRANSLUCENT; + } else { sc.ScriptError("Unknown flag '%s'.", sc.String); @@ -1015,10 +1040,45 @@ void SBarInfo::ParseSBarInfoBlock(FScanner &sc, SBarInfoBlock &block) else if(!sc.Compare("horizontal")) sc.ScriptError("Unknown direction '%s'.", sc.String); sc.MustGetToken(','); - sc.MustGetToken(TK_IntConst); - cmd.special = sc.Number; + while(sc.CheckToken(TK_Identifier)) + { + if(sc.Compare("reverserows")) + cmd.flags |= DRAWKEYBAR_REVERSEROWS; + else + sc.ScriptError("Unknown flag '%s'.", sc.String); + if(!sc.CheckToken('|')) + sc.MustGetToken(','); + } + if(sc.CheckToken(TK_Auto)) + cmd.special = -1; + else + { + sc.MustGetToken(TK_IntConst); + cmd.special = sc.Number; + } sc.MustGetToken(','); this->getCoordinates(sc, cmd, block.fullScreenOffsets); + if(sc.CheckToken(',')) + { + //key offset + sc.MustGetToken(TK_IntConst); + cmd.special2 = sc.Number; + if(sc.CheckToken(',')) + { + //max per row/column + sc.MustGetToken(TK_IntConst); + cmd.special3 = sc.Number; + sc.MustGetToken(','); + //row/column spacing (opposite of previous) + if(sc.CheckToken(TK_Auto)) + cmd.special4 = -1; + else + { + sc.MustGetToken(TK_IntConst); + cmd.special4 = sc.Number; + } + } + } sc.MustGetToken(';'); break; case SBARINFO_GAMEMODE: