Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Adding in player options
#1
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:
[Image: frmoptionsks7.png]

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
Reply


Messages In This Thread

Forum Jump:


Users browsing this thread: 1 Guest(s)