• Welcome to Valhalla Legends Archive.
 

Fecking SC mini map :/

Started by Ringo, February 23, 2008, 03:27 AM

Previous topic - Next topic

Ringo

Trying to add view of mini map to one of my SC bots, so it displays after it downloads the map, but im having problems:

I tryed blood bath and lost templed "TILE" and "MTXM" data from the scenario.chk.
I remember years ago, I tryed writeing it as a 16bit image, but it looked even worse than all of them combined.
That image is of testing a few pallets like the following:

Useing each 16 bits as a X/Y cord (after seeing these pallets in SC mpq were no more than 0xFF by 0xFF in size)
Am I going about this right, or is the mini map drawn with starcraft campain editor image tiles?
If so, h ow can i get those tiles?
Should be looking somthing like this: (with out the start location colors ofc)

It was annoying before, and its becoming annoying again since i came back to it, anyone have any ideas?

edit: Should I just print screen ingame on SC/BW, then build my own pallet based on the SS+cords? I would rather not do that, but I guess its always an option if no one knows how its done properly.

thanks

MysT_DooM

#1
it looks good none the less...you're to far ahead of me >< 

But, wouldnt the tiles that the campaign editor be using be the same ones that the client uses anyways? makes sense that way

edit: thinking more bout this, you know how u can get the images of the charecters of the games threw i think the mpq files or or some other file, but then there was this program that converted those files into bmps.  i cant remember what those were called, but the tiles might be located in one of those files maybe

edit2: think those files from the mpq files that were to be converted into bmps were like "gbr" "brp" "somthing3letterish"

edit3: and there was a program which converted those files into bmps

edit4: ahh found it ,, "GRP" files     ,   http://www.starcraft.org/customs/CustomsTutorials/Converting+to+and+from+GRP+graphics


vb6, something about that combination of numbers and letters is sexy

Ringo

Hm, im going to give up I think, I have tryed so many ways that im starting to forget what I have already tryed. :P
I have tryed flipping the cords around, scanning them pallet-like images from top to bottom, bottom to top, left to right, right to left, scanning full-scale maps from stardraft, inverting the pixels, useing the X cord for a pallet index for SC's defalt pallet and so many more things I have forgot most of them. None of them were 100% perfect results.
When i tryed scanning full-scale maps (32² to 1²) and building my own pallet for each titleset, I found that some cords matched, but the pixel didnt, causeing the last pixel drawn to that location to be used every time, but that was probly due to the scaleing down effect. The only other thing I can think of is that the X cord points to a pallet index, and the Y cord points to an image. (like them 256 by 1 pcx's)
I only tryed about 20 differnt pallet images because I couldnt be botherd to sort through all of them. The same is the case with them .GRP I expect, just theres 1000+ of them :P
I expect I was very close to finding out the correct way, but I have lost all motivation now, just for a mini map view. heh :)

Aside, thanks for pointing out that the GRP files are the graphics, they always showed up as .xxx/unknown with the mpq extractor i have used in the past, so I never really botherd looking at them, I always assumed all the graphics were smk's, as they were frame based.
I might try making my own .GRP reader when I get round to it, I opened one up and they look raw pallet index based, so that should be pretty easy.

UserLoser

let me contribute something non-useful, wrong forum ;D

Ringo

Ah.
I thought it wasnt really fit for bot dev, since it was more SC map related rather than bots, thought it would be more of a modding question, even tho its for a bot im trying to finish a mini map view to :P

Ringo

#5
Sorry to bump this 8 month old topic.
I came back to this yesterday and after many hours, I finaly got it finished! (Code below, if anyones interested)
I think what I was orginaly doing wrong all that time ago, was my cords were off/wrong way round or somthing.
After pissing around with the mpq .cv5 titlesetfiles and what not for hours yesterday, I finaly thought of a good way to get the palette data.

What I did was, open stardraft map editor, created a new 256 by 256 map on the titleset I wanted to generate a palette for, then saved the empty map to hard drive.
I then opened the map file from vb, read the scenario.chk file from it, looped through each section of the file and modifyed the 'MTXM' and 'TILE' sections.
Basicly, in a 2d loop, 0 to 255, 0 to 255 and wrote X/Y to the data, so I had 256*256(all) possible entrys, then saved the resulting data to a scenario.chk file.
I then opened the scenario.chk file with stardraft and saved an image of the map to full scale 64mb bitmap file. (File>Save Image)
I then opened that bitmap file, and scaled it down from 32by32 size tiles, to 2by2 size, snipped off the unused parts and saved them to harddrive.
It was then as easy as just lining up the cords in the MTXM or TILE data of a map, to the offsets of the palette images.

Heres the palette images for all titlesets if anyone wants them, they are around 100kb each (10kb for warcraft 2 palettes):
Badlands
Space
Installation
Ashworld
Jungle
Desert
Ice
Twilight
And here's the palettes for warcraft 2:
Forest
Winter
Wasteland
Swamp
The reassion I scaled the palettes down to 2x2 tiles, is because thats the size 64x64 maps are drawn to the 128x128 minimap.

Here's the result, in a new SCGP client ive been writeing over the past few days:

(yeah yeah, I know, its ugly as hell, but its a working progress and only 3 - 4 days old :p)


And here's how maps are drawn to a 128x128 area:


And for anyone who is interested, or being trying to do this to, here's the code:
Note: You must name the palette files by number, so for example, badlands needs to be "0.bmp", Space needs to be "1.bmp" etc. And for warcraft 2 maps, "W0.bmp" for Forest, "W2.bmp" for Winter etc.
This is how to use the code:
If you have the palette files saved to \palette\ and a map saved to \map\, and you wanted to draw the minimap to a 128 by 128 sized picture box called "Picture1", you would do as follows:
bResult = MapPreview(app.path & "\map\(4)Lost Temple.scm", app.path & "\palette\", Picture1.hdc)

Private Declare Function SFileDestroy Lib "Storm" Alias "#262" () As Boolean
Private Declare Function SFileSetLocale Lib "Storm" Alias "#272" _
            (ByVal nNewLocale As Long) As Long
Private Declare Function SFileOpenArchive Lib "Storm" Alias "#266" _
            (ByVal lpFileName As String, ByVal dwPriority As Long, ByVal dwFlags As Long, ByRef hMpq As Long) As Boolean
Private Declare Function SFileOpenFileEx Lib "Storm" Alias "#268" _
            (ByVal hMpq As Long, ByVal lpFileName As String, ByVal dwSearchScope As Long, ByRef hFile As Long) As Boolean
Private Declare Function SFileGetFileSize Lib "Storm" Alias "#265" _
            (ByVal hFile As Long, ByRef lpFileSizeHigh As Long) As Long
Private Declare Function SFileReadFile Lib "Storm" Alias "#269" _
            (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, _
            ByRef lpNumberOfBytesRead As Long, lpOverlapped As Any) As Boolean
Private Declare Function SFileCloseFile Lib "Storm" Alias "#253" _
            (ByVal hFile As Long) As Boolean
Private Declare Function SFileCloseArchive Lib "Storm" Alias "#252" _
            (ByVal hMpq As Long) As Boolean

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
            (ByRef destination As Any, ByRef Source As Any, ByVal numbytes As Long)
Public Declare Function StretchBlt Lib "gdi32" (ByVal hDc As Long, ByVal X As Long, _
            ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, _
            ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, _
            ByVal nSrcWidth As Long, ByVal nSrcHeight As Long, ByVal dwRop As Long) As Long
Public Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hDc As Long) As Long
Public Declare Function DeleteDC Lib "gdi32" (ByVal hDc As Long) As Long
Public Declare Function SelectObject Lib "gdi32" (ByVal hDc As Long, _
            ByVal hObject As Long) As Long
Public Declare Function FillRect Lib "user32" (ByVal hDc As Long, _
            lpRect As RECT, ByVal hBrush As Long) As Long
Public Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As Long
Public Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long

Public Type RECT
    Left            As Long
    Top             As Long
    Right           As Long
    Bottom          As Long
End Type


Public Function ReadMPQFile(ByVal strMPQ As String, ByVal strFile As String, ByRef strBuffer As String) As Boolean
    On Error GoTo ReadMPQFileErr
    If (Len(Dir$(strMPQ)) = 0) Then Exit Function
    Dim lngLengh    As Long
    Dim lngMpq      As Long 'handle to the archive
    Dim lngFile     As Long 'handle to the file
    Dim lngBytes    As Long
    Call SFileDestroy
    Call SFileSetLocale(&H656E5553) 'SUne
    If (SFileOpenArchive(strMPQ, 0, 0, lngMpq) = False) Then GoTo ReadMPQFileErr
    If (SFileOpenFileEx(lngMpq, strFile, 0, lngFile) = False) Then GoTo ReadMPQFileErr
    lngLengh = SFileGetFileSize(lngFile, 0)
    If (lngLengh < 0) Then GoTo ReadMPQFileErr
    strBuffer = String(lngLengh, 0)
    If (SFileReadFile(lngFile, ByVal strBuffer, lngLengh, lngBytes, ByVal 0&) = False) Then GoTo ReadMPQFileErr
    ReadMPQFile = True
ReadMPQFileErr:
    Call SFileCloseFile(lngFile)
    Call SFileCloseArchive(lngMpq)
End Function



Public Function MapPreview(ByVal strMAP As String, ByVal strPAL As String, ByVal lngHdc As Long) As Boolean
    'strMAP = map file to make preview of
    'strPAL = folder to the palettes
    On Error GoTo MapPreviewErr
    If (Len(Dir$(strMAP)) = 0) Then Exit Function
    If (Len(strPAL) = 0) Then Exit Function
    Dim pic         As StdPicture
    Dim strCHK      As String
    Dim S           As String
    Dim strCOL      As String
    Dim strUNIT     As String
    Dim R           As RECT
    Dim i           As Long
    Dim i2          As Long
    Dim lngWidth    As Long
    Dim lngHeight   As Long
    Dim A           As Long
    Dim B           As Long
    Dim C           As Long
    Dim D           As Long
    Dim lngDC       As Long
    Dim X           As Integer
    Dim Y           As Integer
    Dim SizeX       As Long
    Dim SizeY       As Long
    Dim StartX      As Long
    Dim StartY      As Long
    Dim Width       As Long
    Dim Height      As Long
    Dim bW2BN       As Boolean
    Const MiniSize  As Long = 128
   
    '//Check if its a MPQ
    X = FreeFile()
    Open strMAP For Binary As #X
        Get #X, 1, i
        bW2BN = (Not i = &H1A51504D) 'MPQ
        If bW2BN Then
            strCHK = String(LOF(X), 0)
            Get #X, 1, strCHK
        End If
    Close #X
    X = 0
   
    '//Extract the map file
    If (bW2BN = False) Then
        If (ReadMPQFile(strMAP, "staredit\scenario.chk", strCHK) = False) Then Exit Function
    End If
   
    '//Read each section
    C = 1
    Do Until ((C + 7) > Len(strCHK))
        Call CopyMemory(A, ByVal Mid$(strCHK, C, 4), 4): C = C + 4
        Call CopyMemory(B, ByVal Mid$(strCHK, C, 4), 4): C = C + 4
        'If (A = &H454C4954) Then   'TILE'
        If (A = &H4D58544D) Then 'MTXM'
            If (Len(S) = 0) Then S = Mid$(strCHK, C, B)
        ElseIf (A = &H204D4944) Then 'DIM '
            Call CopyMemory(lngWidth, ByVal Mid$(strCHK, C, 2), 2)
            Call CopyMemory(lngHeight, ByVal Mid$(strCHK, C + 2, 2), 2)
        ElseIf (A = &H20415245) Then 'ERA '
            Call CopyMemory(D, ByVal Mid$(strCHK, C, 2), 2)
            D = IIf(bW2BN, (D And &H3), (D And &H7))
        ElseIf (A = &H524C4F43) Then 'COLR'
            If (B > 0) Then strCOL = Mid$(strCHK, C, B)
        ElseIf (A = &H54494E55) Then 'UNIT'
            If (B > 0) Then strUNIT = Mid$(strCHK, C, B)
        End If
        C = C + B
    Loop
    strCHK = vbNullString
    If (lngWidth < 32) Or (lngWidth > 256) Then Exit Function
    If (lngHeight < 32) Or (lngHeight > 256) Then Exit Function
    If (Len(S) < ((lngWidth * lngHeight) * 2)) Then Exit Function

    '//Load the palette
    If (Not Right$(strPAL, 1) = "\") Then strPAL = strPAL & "\"
    Set pic = LoadPicture(strPAL & IIf(bW2BN, "W", vbNullString) & D & ".bmp")
    If (pic Is Nothing) Then Exit Function

    '//Create a dc to the palette bitmap
    lngDC = CreateCompatibleDC(lngHdc)
    Call SelectObject(lngDC, pic.Handle)
   
    '//Scale the drawing to to fit in a 128 by 128 mini map
    If ((lngWidth = 96) Or (lngWidth = 192)) Then StartX = (MiniSize / 8)
    If ((lngHeight = 96) Or (lngHeight = 192)) Then StartY = (MiniSize / 8)
    Width = MiniSize
    Height = MiniSize
    SizeX = (MiniSize / (lngWidth - 1))
    SizeY = (MiniSize / (lngHeight - 1))
    If (lngWidth = lngHeight) Then
        If (lngWidth = 96) Or (lngWidth = 192) Then
            Width = MiniSize - (StartX * 2)
            Height = MiniSize - (StartY * 2)
        End If
    ElseIf (lngWidth > lngHeight) Then
        If (lngWidth = 96) Or (lngWidth = 192) Then
            Width = MiniSize - (StartX * 2)
            Height = (((MiniSize - (StartX * 2)) / lngWidth) * lngHeight)
        Else
            Height = ((MiniSize / lngWidth) * lngHeight)
        End If
        StartY = ((MiniSize / 2) - (Height / 2))
    ElseIf (lngWidth < lngHeight) Then
        If (lngHeight = 96) Or (lngHeight = 192) Then
            Height = MiniSize - (StartY * 2)
            Width = (((MiniSize - (StartY * 2)) / lngHeight) * lngWidth)
        Else
            Width = ((MiniSize / lngHeight) * lngWidth)
        End If
        StartX = ((MiniSize / 2) - (Width / 2))
    End If
   
    '//Draw the image
    A = 1
    For i = 0 To (lngHeight - 1)
        For i2 = 0 To (lngWidth - 1)
            Y = Asc(Mid$(S, A, 1))
            X = Asc(Mid$(S, A + 1, 1))
            A = A + 2
            Call StretchBlt(lngHdc, _
                StartX + (i2 * (Height / lngHeight)), _
                StartY + (i * (Width / lngWidth)), _
                SizeX, _
                SizeY, _
                lngDC, (X * 2), (Y * 2), 2, 2, vbSrcCopy)
        Next i2
    Next i
    Call DeleteDC(lngDC)
     
    '//Find start locations/minerals and draw them to scale
    A = 1
    B = 0
    i = IIf(bW2BN, 7, 35)
    Do Until ((A + i) > Len(strUNIT))
        If bW2BN Then
            Call CopyMemory(X, ByVal Mid$(strUNIT, A, 2), 2)
            Call CopyMemory(Y, ByVal Mid$(strUNIT, A + 2, 2), 2)
            B = Asc(Mid$(strUNIT, A + 4, 1))
            SizeY = Asc(Mid$(strUNIT, A + 5, 1)) And 7
            i2 = ((B = 92) Or (B = 94) Or (B = 95))
        Else
            Call CopyMemory(X, ByVal Mid$(strUNIT, A + 4, 2), 2): X = X \ 32
            Call CopyMemory(Y, ByVal Mid$(strUNIT, A + 6, 2), 2): Y = Y \ 32
            Call CopyMemory(B, ByVal Mid$(strUNIT, A + 8, 2), 2)
            SizeY = Asc(Mid$(strUNIT, A + 16, 1)) And 7
            i2 = ((B = 176) Or (B = 177) Or (B = 178) Or (B = 188) Or (B = 214))
        End If
        If i2 Then
            'min1/min2/min3/gas/startlocation
            If (((B = 176) Or (B = 177) Or (B = 178)) And (bW2BN = False)) Then 'mineral
                '2 wide, 1 high
                C = X + 1
                D = Y
                SizeX = RGB(64, 104, 212)
            ElseIf ((B = 188) And (bW2BN = False)) Then 'gas
                '4 wide, 2 high
                C = X + 2
                D = Y
                X = X - 1
                Y = Y - 1
                SizeX = RGB(64, 104, 212)
            ElseIf ((B = 92) And bW2BN) Then  'gold mine
                C = X + 2
                D = Y + 2
                SizeX = RGB(255, 255, 0)
            Else 'Player
                '4 wide, 3 high
                If (SizeY < Len(strCOL)) Then SizeY = Asc(Mid$(strCOL, SizeY + 1, 1))
                Select Case SizeY
                    Case 0:     SizeX = IIf(bW2BN, RGB(164, 0, 0), RGB(244, 4, 4))
                    Case 1:     SizeX = IIf(bW2BN, RGB(0, 60, 192), RGB(12, 72, 204))
                    Case 2:     SizeX = RGB(44, 180, 148)
                    Case 3:     SizeX = IIf(bW2BN, RGB(44, 180, 148), RGB(136, 64, 156))
                    Case 4:     SizeX = IIf(bW2BN, RGB(152, 72, 176), RGB(248, 140, 20))
                    Case 5:     SizeX = IIf(bW2BN, RGB(240, 132, 20), RGB(112, 48, 20))
                    Case 6:     SizeX = IIf(bW2BN, RGB(40, 40, 60), RGB(204, 224, 208))
                    Case 7:     SizeX = IIf(bW2BN, RGB(252, 252, 72), RGB(252, 252, 56))
                    Case 8:     SizeX = RGB(8, 128, 8)
                    Case 9:     SizeX = RGB(252, 252, 124)
                    Case 10:    SizeX = RGB(236, 196, 176)
                    Case 11:    SizeX = RGB(64, 104, 212) '(minerals)
                    Case 12:    SizeX = RGB(116, 164, 124)
                    Case 13:    SizeX = RGB(144, 144, 184)
                    Case 14:    SizeX = RGB(252, 252, 124)
                    Case 15:    SizeX = RGB(0, 220, 252)
                    Case Else:  SizeX = RGB(5, 5, 5)
                End Select
                C = X + 2
                D = Y + 1
                X = X - 1
                Y = Y - 1
            End If
            R.Top = StartY + (Y * (Height / lngHeight))
            If (lngWidth < 96) And (lngHeight < 96) Then
                R.Left = StartX + (X * (Width / lngWidth)) - 2
                R.Right = StartX + (C * (Width / lngWidth))
                R.Bottom = StartY + (D * (Height / lngHeight)) + 2
            Else
                R.Left = StartX + (X * (Width / lngWidth))
                R.Right = StartX + (C * (Width / lngWidth)) + 1
                R.Bottom = StartY + (D * (Height / lngHeight)) + 1
            End If
            SizeY = CreateSolidBrush(SizeX)
            Call FillRect(lngHdc, R, SizeY)
            Call DeleteObject(SizeY)
        End If
        A = A + (i + 1)
    Loop
    '//return success
    MapPreview = True
MapPreviewErr:
End Function




Enjoy!

Dale

Very nice work Ringo! I'm impressed.

Mystical

That's pretty cool ringo, I'll have to make some use of this when i get around that stage.

Yegg

Keep up the amazing work, Ringo. I've never actually seen someone do that before.

Spht

Nice.  i intended on having a map preview for games back when i was working on this stuff but never got around to it

Ringo

Woops.
There was a few bugs with player start location colors and the unit code variable, but ive fixed them now.
I noticed today, when the "COLR" section of the map is not there, starcraft uses defalt colors.
The variable B also had 16bits still inuse, so I have set it to zero before reuseing it, so it no longer has problems detecting minerals/gas/start location id codes.

Heres some example code of how to use if anyones interested:
SCMiniMap.zip

vuther.de

Nice work Ringo, glad to see people are progressing in development for Battle.net still.

Ringo

#12
I've updated the code above and the palettes, to support warcraft 2 BNE .pud map file's.
Their alot like starcraft scm/scx files, just not compressed into an MPQ archive.


I've also updated the example code/project for anyone whos interested:
SCMiniMap.zip

I think thats the mini map's done and dusted now *hopes*

Yegg

Excellent work again, Ringo. And again, I download your source in case this is of interest to me in the future.

Sixen

Pretty awesome Ringo, i'm surprised. Never seen this done before.
Blizzard Tech Support/Op W@R - FallenArms
The Chat Gem Lives!
http://www.diablofans.com
http://www.sixen.org