OK! This is my tutorial on how to add options to your game. These will be simple On/Off options such as when the player want to display the FPS or not. OK! The tutorial will show you how to add a frmOptions that displays when the user types '/opt' and the ability to turn all options on or off by typing '/opt on' or '/opt off'. This tutorial was bade for MSE Build 1. Remember to back up your source!
Difficulty: 2/5 (C/P really, try to understand it though)
Creator: Stomach Pulser
::Client Side::We will start off in
'modConstants'. At the very bottom add the following five constants:
Code:
' Player Option Constants
Public Const OPT_DISP_COORDS = 0
Public Const OPT_DISP_FPS = 1
Public Const OPT_DISP_NPC_HP_BARS = 2
Public Const OPT_DISP_PLR_HP_BARS = 3
Public Const OPT_DISP_PLR_MP_BARS = 4
Public Const OPT_FINAL = 4
Why is OPT_FINAL the same as DISP_PLR_MP_BARS? Well, it is set that so we can always use OPT_FINAL as the last one, if we want to add more options in later, we just change OPT_FINAL to whatever the last constant is.
Now head over to
'modTypes'. Go into the
PlayerRec and add an array to the bottom, so that it starts at 0 and ends at OPT_FINAL:
Code:
' Options
POption(0 To OPT_FINAL) As Byte
This is here to hold the player's option choices (on or off).
Open up
'modGameLogic'. At the very bottom add these functions/subs:
Code:
Function GetPlayerOption(ByVal Index As Long, ByVal Opt As Byte) As Byte
GetPlayerOption = Player(Index).POption(Opt)
End Function
Sub SetPlayerOption(ByVal Index As Long, ByVal Opt As Byte, ByVal YesNo As Byte)
Player(Index).POption(Opt) = YesNo
End Sub
Function ReadPlayerOption(ByVal Opt As Byte) As String
Select Case Opt
Case OPT_DISP_COORDS
ReadPlayerOption = "Display FPS: "
Case OPT_DISP_FPS
ReadPlayerOption = "Display Map Coordinates: "
Case OPT_DISP_NPC_HP_BARS
ReadPlayerOption = "Display NPC HP Bars: "
Case OPT_DISP_PLR_HP_BARS
ReadPlayerOption = "Display Player HP Bars: "
Case OPT_DISP_PLR_MP_BARS
ReadPlayerOption = "Display Player MP Bars: "
End Select
End Function
Sub PlayerOptionsInit(ByVal Index As Long)
Dim i
For i = 0 To OPT_FINAL
frmOptions.fraOpt(i).Caption = ReadPlayerOption(i)
If GetPlayerOption(Index, i) = YES Then
frmOptions.optOn(i).Value = True
ElseIf GetPlayerOption(Index, i) = NO Then
frmOptions.optOff(i).Value = True
Else
frmOptions.optOn(i).Value = True
End If
Next i
frmOptions.lblIndex = STR(Index)
frmOptions.Visible = True
End Sub
Sub PlayerOptionsOK(ByVal Index As Long)
Dim i
For i = 0 To OPT_FINAL
If frmOptions.optOn(i).Value = True Then
Call SetPlayerOption(Index, i, YES)
ElseIf frmOptions.optOff(i).Value = True Then
Call SetPlayerOption(Index, i, NO)
Else
Call MsgBox("Deathlycat caught you hacking!!!")
End If
Next i
Call SendUpdatePlayerOptions(Index)
End Sub
Woah! That's a good bit of code. Let's take it apart now...
The function
GetPlayerOption does just that. It takes the player and the option given (0 ~ 4) and the returns whether it is on (true) or off (false).
The sub
SetPlayerOption is similar. It takes the player and set the option given (0 ~ 4) to on or off.
The function
ReadPlayerOption returns the option back as a string. This is where our constants come into play. By using the select case with our constants, it makes the code more readable in case you want to add more options or take some out.
The sub
PlayerOptionsInit is going to be used to set up our frmOptions to display the users current options.
The sub
PlayerOptionsOK is going to be used to get what the player selects in frmOptions and send it to the client for saving. It is only called if the user clicks OK in frmOptions.
Now, let's set up our packet system. Go into
'modClientTCP' and add the following subs at the very bottom:
Code:
Sub SendGetPlayerOptions(ByVal Index As Long)
Dim CatPacket As String
CatPacket = "GETPOPTIONS" & SEP_CHAR & END_CHAR
Call SendData(CatPacket)
End Sub
Sub SendUpdatePlayerOptions(ByVal Index As Long)
Dim CatPacket As String
Dim i As Byte
CatPacket = "UPDATEPOPTIONS" & SEP_CHAR
For i = 0 To OPT_FINAL
CatPacket = CatPacket & STR(GetPlayerOption(Index, i)) & SEP_CHAR
Next i
CatPacket = CatPacket & END_CHAR
Call SendData(CatPacket)
End Sub
These will be used later, but we should discuss what they do anyways...
The sub
SendGetPlayerOptions is a request. It asks the server to send over the player's saved data for their options. It is used to load the player.
The sub
SendUpdatePlayerOptions takes the player's option choices and then send them to the server, asking for the server to save them.
OK, now go into the
'modHandleData' and add this at the very bottom, right before where it says 'end sub':
Code:
' ::::::::::::::::::::::::::::
' :: Update POptions packet ::
' ::::::::::::::::::::::::::::
If LCase(Parse(0)) = "updatepoptions" Then
n = 1
For i = 0 To OPT_FINAL
Call SetPlayerOption(MyIndex, i, Val(Parse(n)))
n = n + 1
Next i
Exit Sub
End If
Basically, this says that if the server sends a packet called
updatepoptions then we are going to take the data in it and save it to the player. This is how we load saved data from the server.
Head back over to
'modGameLogic'. Inside the sub
'HandleData', find:
Code:
' Leave party
If LCase(Mid(MyText, 1, 6)) = "/leave" Then
Call SendLeaveParty
MyText = ""
Exit Sub
End If
After that add this:
Code:
' Options Request
If LCase(Mid(MyText, 1, 4)) = "/opt" Then
If Len(MyText) > 5 Then
ChatText = Mid(MyText, 6, Len(MyText) - 5)
If LCase(ChatText) = "on" Then
For i = 0 To OPT_FINAL
Call SetPlayerOption(MyIndex, i, YES)
Next i
Call SendUpdatePlayerOptions(MyIndex)
ElseIf LCase(ChatText) = "off" Then
For i = 0 To OPT_FINAL
Call SetPlayerOption(MyIndex, i, NO)
Next i
Call SendUpdatePlayerOptions(MyIndex)
End If
Else
Call PlayerOptionsInit(MyIndex)
End If
For i = 0 To OPT_FINAL
If GetPlayerOption(MyIndex, i) = NO Then
Call AddText(ReadPlayerOption(i) & "No", Red)
ElseIf GetPlayerOption(MyIndex, i) = YES Then
Call AddText(ReadPlayerOption(i) & "Yes", White)
Else
Call AddText(ReadPlayerOption(i) & "Invalid", AlertColor)
End If
Next i
MyText = ""
Exit Sub
End If
If you don't understand it it's OK! Let me draw it out for you...
First off, we check to see if the user typed in “
/opt”. If they did, then we check to see if they added anything after that. If they did, we assign it to the variable
chat text. Next, we check to see what chat text is. If it is on or off then we set all of the player's option choices to on or off, respectively and then send a packet to the server telling it to save that. If they didn't type in chat text, then we open up our frmOptions through the
InitPlayerOptions. Because we added:
Code:
frmOptions.Show vbModal
The code will not execute until frmOptions is closed (when we either click OK or Cancel). After frmOptions is closed, we send a packet to the server to save those new options through the use of the sub
PlayerOptionsOK, then we display the users option choices so far by using the
ReadPlayerOption function. That is it.
The last thing we need to do client wise is add the actual
frmOptions itself. To do this click on the
Project tab in the menu bar up top. Click on
Add Form. Then, make sure the dialog box sets it to
Form and hit OK.
Rename this form to
frmOptions.
Set the caption to whatever you want and start adding GUI.
Add two command buttons, rename them to
cmdSend and
cmdCancel. Captions set to whatever you want. Next, add a frame, and name it
fraOpt[b]. Set the caption to your longest option (text wise), in this case it would be [b]Display Map Coordinates. Next, add two option buttons to the frame. Name them
optOn and
optOff. Next, click on the frame and press
Ctrl + C to copy it. Then, press
Ctrl + V to paste it. A dialog box will pop up asking if you want to make the frame a control array. Press
OK. The dialog will ask again for your option buttons, again press
OK. Arrange them how you want. The final piece of GUI is a lone label. Set it's name to
lblIndex and set the visible property to
False. This label will store who the player is. Now, we add the code.
Double click on your
cmdSend and add the following under it:
Code:
Call PlayerOptionsOK(frmOptions.lblIndex)
Me.Visible = False
This just says that when you click the button, it will take the options and set them to the player.
Double click on your
cmdCancel and add the following under it:
Code:
Me.Visible = False
No need to clear the settings as they are reset when we start up frmOptions again.
Phew! That is a lot of things Client Side. But, we are done with that much, the next part is about the same.
::Server Side::Start off in
'modConstants'. At the very bottom add this:
Code:
' Player Option Constants
Public Const OPT_DISP_COORDS = 0
Public Const OPT_DISP_FPS = 1
Public Const OPT_DISP_NPC_HP_BARS = 2
Public Const OPT_DISP_PLR_HP_BARS = 3
Public Const OPT_DISP_PLR_MP_BARS = 4
Public Const OPT_FINAL = 4
Go into
'modTypes' and add this at the bottom of
PlayerRec:
Code:
POption(0 To OPT_FINAL) As Byte
Go into
'modDatabase' and add the following into the sub
SavePlayer at the very bottom, before the 'next i':
Code:
' Options
For n = 0 To OPT_FINAL
Call PutVar(FileName, "CHAR" & i, "OPTION" & n, STR(Player(Index).Char(i).POption(n)))
Next n
This just writes the option data to the player's .ini for their current character.
Find the sub
LoadPlayer at the very bottom, before the 'next I' add this:
Code:
' Options
For n = 0 To OPT_FINAL
Player(Index).Char(i).POption(n) = Val(GetVar(FileName, "CHAR" & i, "OPTION" & n))
Next n
This simply loads the data from the player's .ini into their current char.
Go into
'modServerTCP' and add the following sub at the very bottom:
Code:
Sub SendPlayerOptions(ByVal Index As Long)
Dim CatPacket As String
Dim i As Byte
CatPacket = "UPDATEPOPTIONS" & SEP_CHAR
For i = 0 To OPT_FINAL
CatPacket = CatPacket & STR(GetPlayerOption(Index, i)) & SEP_CHAR
Next i
CatPacket = CatPacket & END_CHAR
Call SendDataTo(Index, CatPacket)
End Sub
This is how we load things into the client. This takes the saved values and send them to the client.
Now, go into your
'modHandleData' and add the following in before the end sub call:
Code:
' :::::::::::::::::::::::::
' :: Send POptions packet::
' :::::::::::::::::::::::::
If LCase(Parse(0)) = "getpoptions" Then
Call SendPlayerOptions(Index)
Exit Sub
End If
' :::::::::::::::::::::::::::
' :: Update POptions packet::
' :::::::::::::::::::::::::::
If LCase(Parse(0)) = "updatepoptions" Then
n = 1
For i = 0 To OPT_FINAL
Call SetPlayerOption(Index, i, Val(Parse(n)))
n = n + 1
Next i
Call SavePlayer(Index)
Exit Sub
End If
End Sub
This are things the client tells us to do. If the client wants the information on the player's options (packet 1), we sent it. If the client sent us information, we update it (packet 2).
Go into
'modGameLogic'. Add the following at the very end of the sub
ClearChar:
Code:
For n = 0 To OPT_FINAL
Player(Index).Char(CharNum).POption(n) = NO
Next n
Finally, add the following at the very bottom of
'modGameLogic':
Code:
Function GetPlayerOption(ByVal Index As Long, ByVal Opt As Byte)
GetPlayerOption = Player(Index).Char(Player(Index).CharNum).POption(Opt)
End Function
Sub SetPlayerOption(ByVal Index As Long, ByVal Opt As Byte, ByVal YesNo As Byte)
Player(Index).Char(Player(Index).CharNum).POption(Opt) = YesNo
End Sub
That is it! If you have any questions/comments, post it here or PM me. Here is what my frmOptions looks like:

Code:
Version Log
v1.0 ~ 2/20/08 - Guide created and posted
v1.1 ~ Fixed up a weird error while loading/saving and an error whilst opening frmOptions