This tutorial will guide you through adding more layers to a vanilla MS4(3.68) and try and give an explanation as to what is doing what.
*Adding this will require you to delete all your maps. If you want to save them then you will need to create a converter. I am not telling you how to create a converter.
So when I go to add something new, regardless of what it is I like to start in the server
.
Server SideThe next thing I like to do is add whatever I am adding to the UDT which needs it. A UDT is a User Defined Type. That's all those Type PlayerRec, Type UserRec, TypePlayerInvRec and so on. These are all in modTypes, duh.
modTypesUnder the TileRec UDT add in the new layers you want. I am going to add in two new ones. Mine looks like this now.
Code:
Type TileRec
Ground As Integer
Mask As Integer
Mask2 As Integer
Anim As Integer
Anim2 As Integer
Fringe As Integer
Type As Byte
Data1 As Integer
Data2 As Integer
Data3 As Integer
End Type
So honestly, the next place to go I don't really know xD so I am going to use the search option(Ctrl + F) and type in Ground and press search till something obvious comes up. Seems as if our next place is:
modHandleDataIf you don't know, modHandleData does exactly what it's name says. Handles data. All the incoming packets from the client are sorted here and then just done whatever with.
So find the HandleMapData sub.
In this sub you will have to add your new layers in which you added to the TileRec UDT in the last step. Why? Because later you will edit the client side which sends the data to the server, it needs to be received somehow. Anyways, you can see the code that looks like this:
Code:
Map(MapNum).Tile(x, y).Ground = Val(Parse(n))
Map(MapNum).Tile(x, y).Mask = Val(Parse(n + 1))
Map(MapNum).Tile(x, y).Anim = Val(Parse(n + 2))
Map(MapNum).Tile(x, y).Fringe = Val(Parse(n + 3))
Map(MapNum).Tile(x, y).Type = Val(Parse(n + 4))
Map(MapNum).Tile(x, y).Data1 = Val(Parse(n + 5))
Map(MapNum).Tile(x, y).Data2 = Val(Parse(n + 6))
Map(MapNum).Tile(x, y).Data3 = Val(Parse(n + 7))
n = n + 8
It's probably pretty obvious what you need to do here right? I like to keep things organized myself, so instead of being lazy and adding them to the bottom I added them to the same spots that the UDT has them sorted out. I advise you do the same. If you are adding more than two layers ensure you change all the n + # to the correct ones, don't forget the n = n + #. Mine looks like this now.
Code:
Map(MapNum).Tile(x, y).Ground = Val(Parse(n))
Map(MapNum).Tile(x, y).Mask = Val(Parse(n + 1))
Map(MapNum).Tile(x, y).Mask2 = Val(Parse(n + 2))
Map(MapNum).Tile(x, y).Anim = Val(Parse(n + 3))
Map(MapNum).Tile(x, y).Anim2 = Val(Parse(n + 4))
Map(MapNum).Tile(x, y).Fringe = Val(Parse(n + 5))
Map(MapNum).Tile(x, y).Type = Val(Parse(n + 6))
Map(MapNum).Tile(x, y).Data1 = Val(Parse(n + 7))
Map(MapNum).Tile(x, y).Data2 = Val(Parse(n + 8))
Map(MapNum).Tile(x, y).Data3 = Val(Parse(n + 9))
n = n + 10
Wow this is fun haha. We are learning something I hope? Next step...
modServerTCPFind the MapCache_Create sub.
Find this line:
Code:
MapData = MapData & SEP_CHAR & .Ground & SEP_CHAR & .Mask & SEP_CHAR & .Anim & SEP_CHAR & .Fringe & SEP_CHAR & .Type & SEP_CHAR & .Data1 & SEP_CHAR & .Data2 & SEP_CHAR & .Data3
Once again, you will need to add your new layers names in here someplace. As previous, I recommend keeping everything in the same order. So add your new layers in here. Mine looks like this.
Code:
MapData = MapData & SEP_CHAR & .Ground & SEP_CHAR & .Mask & SEP_CHAR & .Mask2 & SEP_CHAR & .Anim & SEP_CHAR & .Anim2 & SEP_CHAR & .Fringe & SEP_CHAR & .Type & SEP_CHAR & .Data1 & SEP_CHAR & .Data2 & SEP_CHAR & .Data3
Notice how it is all in order. This is important when sending/receiving packets.Client SidemodTypesAdd your new types to the UDT. Keep them in the same order as the server!
modHandleDataFind the HandleMapData sub.
You should already know how to do this part. Add your new layers in here. Once again, keep it in order. Don't forget to change the n + # and n = n + # to their new appropriate values.
modClientTCPSub SendMap.
Remember this:
Code:
Packet = Packet & SEP_CHAR & .Ground & SEP_CHAR & .Mask & SEP_CHAR & .Anim & SEP_CHAR & .Fringe & SEP_CHAR & .Type & SEP_CHAR & .Data1 & SEP_CHAR & .Data2 & SEP_CHAR & .Data3
Make it work. Keep it in order! xD.
frmMirageAdd however many new options to the map editor as you need. I only need two so I am putting a new option called optMask2 and one called optAnim2.
modGameEditorsFind the MapEditorMouseDown sub.
If you look at it it should be pretty obvious what needs to happen.
Code:
With Map.Tile(CurX, CurY)
If frmMirage.optGround.Value Then .Ground = EditorTileY * TILESHEET_WIDTH + EditorTileX
If frmMirage.optMask.Value Then .Mask = EditorTileY * TILESHEET_WIDTH + EditorTileX
If frmMirage.optAnim.Value Then .Anim = EditorTileY * TILESHEET_WIDTH + EditorTileX
If frmMirage.optFringe.Value Then .Fringe = EditorTileY * TILESHEET_WIDTH + EditorTileX
Call BltMap
End With
Add in your new layers to this section. I have a new layer called Mask2 and one called Anim2 so I would add these lines.
Code:
If frmMirage.optMask2.Value Then .Mask2 = EditorTileY * TILESHEET_WIDTH + EditorTileX
If frmMirage.optAnim2.Value Then .Anim2 = EditorTileY * TILESHEET_WIDTH + EditorTileX
Scroll down some till you find this:
Code:
If Button = 2 Then
If frmMirage.optLayers.Value Then
With Map.Tile(CurX, CurY)
If frmMirage.optGround.Value Then .Ground = 0
If frmMirage.optMask.Value Then .Mask = 0
If frmMirage.optAnim.Value Then .Anim = 0
If frmMirage.optFringe.Value Then .Fringe = 0
Call BltMap
End With
Else
This section checks if you are pressing the right click button on the mouse, or Button 2. You need to do basically the same thing here as you did in the last step, just without so much stuff. Got it? Good. Now scroll down past a few other subs until you find...
Sub MapEditorClearLayer
Add your new layers in here so they can get cleared properly if you press the clear button.
modDirectDraw7This module handles all the games drawing procedures. This includes drawing layers to the game screen
. Scroll down till you find...
Sub BltMapTile.
I am going to explain something here quickly, I honestly don't know exactly why (maybe somebody could tell me haha) but the way Mirage draws things to the screen is in an order of first to last. The last things are drawn above everything before it. Get it? So if you look at the BltMapTile sub you can see that first the ground is drawn, then the Mask. So since I am just adding a new mask layer (Mask2) I will add it underneath the code for the first mask layer. Follow? This will allow for the Mask2 layer to be drawn over the regular, default Mask layer.
Code:
If .Mask > 0 Then
If TempTile(X, Y).DoorOpen = NO Then
rec.Top = (.Mask \ TILESHEET_WIDTH) * PIC_Y
rec.Bottom = rec.Top + PIC_Y
rec.Left = Int(.Mask Mod TILESHEET_WIDTH) * PIC_X
rec.Right = rec.Left + PIC_X
Call DDS_BackBuffer.BltFast(X * PIC_X, Y * PIC_Y, DDS_Tile, rec, DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY)
End If
End If
I am going to add my new layer, Mask2 right underneath this code. So now this part in my BltMapTile sub looks like this:
Code:
If .Mask > 0 Then
If TempTile(X, Y).DoorOpen = NO Then
rec.Top = (.Mask \ TILESHEET_WIDTH) * PIC_Y
rec.Bottom = rec.Top + PIC_Y
rec.Left = Int(.Mask Mod TILESHEET_WIDTH) * PIC_X
rec.Right = rec.Left + PIC_X
Call DDS_BackBuffer.BltFast(X * PIC_X, Y * PIC_Y, DDS_Tile, rec, DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY)
End If
End If
If .Mask2 > 0 Then
If TempTile(X, Y).DoorOpen = NO Then
rec.Top = (.Mask2 \ TILESHEET_WIDTH) * PIC_Y
rec.Bottom = rec.Top + PIC_Y
rec.Left = Int(.Mask2 Mod TILESHEET_WIDTH) * PIC_X
rec.Right = rec.Left + PIC_X
Call DDS_BackBuffer.BltFast(X * PIC_X, Y * PIC_Y, DDS_Tile, rec, DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY)
End If
End If
It's pretty straight forward and shouldn't be too difficult. The same goes for the Anim layers. Just duplicate the current one and change the names accordingly. One more thing though, if you are adding an extra fringe layer then you will have to find...
Sub BltMapFringeTile
This sub is where all the Fringe layers are drawn so if you want to add another Fringe layer you would go about doing the same thing here as you did with the previous mask layer.
Now you are ready to test it! Delete all the maps in your client folder and your server folder. Start the server. Start the client. Enjoy.
This is my first tutorial for MS4. Horrah. I tested this and it works. Post if you have any problems or questions.