Password-Changing NPC (Scripting and Source Editing)

Hello! After working with the source for over an hour, I’ve finally completed my password-changing NPC!

I’ll explain exactly what this does at the end.

Credit to: -Admiral Refuge & Spechno (Minor Scripting Edits)
              -Bobosk (Helped me locate essential Subs in the source)

What you need:-VB6 & Eclipse Source Files
                      -Main.txt

Let’s get started with the scripting first! Open up your Main.txt.

Find this:

' Out-dated: Executes query box responses.
Sub QueryBox(Index, Prompt)
	Value = GetVar("responses.ini", "Responses", CStr(Index))
End Sub

Replace it with this:

' **Executes QueryBoxes.
   Sub QueryBox(index, script)

		Value = GetVar("responses.ini", GetPlayerLogin(Index), Cstr(index))

	   Select Case script

' Asks player to input new password.

    Case 0

	  Select Case Value

	Case GetVar("Accounts\" & GetPlayerLogin(Index) & "_Info.ini", "ACCESS", "Password")

		Call PlayerQueryBox(Index, "Please enter your new password.", 1)

' Rejects password if it's incorrect.

    	Case Else

		MsgBox "I'm sorry, but that password is incorrect. Please visit me when you know your password and want to change it.", 0, "Incorrect Password!"

	End Select

    Case 1

	Select Case Value

' Asks you to input a new password if the password you inputted is the same as the current one.

	Case GetVar("Accounts\" & GetPlayerLogin(Index) & "_Info.ini", "ACCESS", "Password")

		Call PlayerQueryBox(Index, "I'm sorry, but that's your current password. Please choose a different password.", 1)	

	Case Else

' Sets password length requirement; must be at least 3 characters long.

	    If Len(Value) < 3 Then

		Call PlayerQueryBox(Index, "Your password must be at least 3 characters in length! Please choose another password.", 1)

	    Else

' Changes password.

		Call PutVar("Accounts\" & GetPlayerLogin(Index) & "_Info.ini", "ACCESS", "Password", Trim(Value))
		MsgBox "Your password has been changed to: " & Value & ". Please come back to me whenever you want to change your password again.", 0, "Password Changed Successfully!"

	    End If

	End Select 
    End Select

    End Sub

Find this:

' Executes whenever a scripted NPC does an action.
Sub ScriptedNPC(Index, Script)
	Select Case Script
		Case 0
			Call PlayerMsg(Index, "This scripted NPC has no apparent use.", WHITE)
			Exit Sub

		Case Else
			Call PlayerMsg(Index, "No NPC script found. Please contact an admin to solve this problem.", WHITE)
			Exit Sub
	End Select
End Sub

Replace it with this:

' Executes whenever a scripted NPC does an action.
Sub ScriptedNPC(Index, Script)
   Select Case Script

' Allows players to change their password by talking to an NPC

		Case 0			
			MsgBox "Hey, I'm the password changer. I can change your password for you.", 0, "Password Changer"
			Call PlayerQueryBox(Index, "Please enter your password.", 0)

		Case Else
			Call PlayerMsg(Index, "No NPC script found. Please contact an admin to solve this problem.", WHITE)
			Exit Sub
	End Select
End Sub

That’s All for scripting! Now let’s move onto the source. ALL SOURCE EDITS TAKE PLACE ON THE SERVER SIDE!!!

Open up VB6 and go to modDatabase.

Find this:

Sub SavePlayer(ByVal Index As Long)
    Dim FileName As String
    Dim f As Long 'File
    Dim I As Integer

    On Error Resume Next

    ' Save login information first
    FileName = App.Path & "\Accounts\" & Trim$(Player(Index).Login) & "_Info.ini"

    Call PutVar(FileName, "ACCESS", "Login", Trim$(Player(Index).Login))
    Call PutVar(FileName, "ACCESS", "Password", Trim$(Player(Index).Password))
    Call PutVar(FileName, "ACCESS", "Email", Trim$(Player(Index).Email))

    ' Make the directory
    If LCase$(Dir(App.Path & "\Accounts\" & Trim$(Player(Index).Login), vbDirectory)) <> LCase$(Trim$(Player(Index).Login)) Then
        Call MkDir(App.Path & "\Accounts\" & Trim$(Player(Index).Login))
    End If

    ' Now save their characters
    For I = 1 To MAX_CHARS
        FileName = App.Path & "\Accounts\" & Trim$(Player(Index).Login) & "\Char" & I & ".dat"

        ' Save the character
        f = FreeFile
        Open FileName For Binary As #f
        Put #f, , Player(Index).Char(I)
        Close #f

    Next I
End Sub

Replace it with this:

Sub SavePlayer(ByVal Index As Long)
    Dim FileName As String
    Dim f As Long 'File
    Dim I As Integer
    Dim Value As String

    On Error Resume Next

    ' Save login information first
    FileName = App.Path & "\Accounts\" & Trim$(Player(Index).Login) & "_Info.ini"

    ' Saves any changes to passwords

    If GetVar(App.Path & "\Responses.ini", GetPlayerLogin(Index), CStr(Index)) = vbNullString Then

    Call PutVar(FileName, "ACCESS", "Password", Trim$(Player(Index).Password))

    Else

    Value = GetVar(App.Path & "\Responses.ini", GetPlayerLogin(Index), CStr(Index))
    Call PutVar(FileName, "ACCESS", "Password", Trim$(Value))

    End If

    Call PutVar(FileName, "ACCESS", "Login", Trim$(Player(Index).Login))
    Call PutVar(FileName, "ACCESS", "Email", Trim$(Player(Index).Email))

    ' Make the directory
    If LCase$(Dir(App.Path & "\Accounts\" & Trim$(Player(Index).Login), vbDirectory)) <> LCase$(Trim$(Player(Index).Login)) Then
        Call MkDir(App.Path & "\Accounts\" & Trim$(Player(Index).Login))
    End If

    ' Now save their characters
    For I = 1 To MAX_CHARS
        FileName = App.Path & "\Accounts\" & Trim$(Player(Index).Login) & "\Char" & I & ".dat"

        ' Save the character
        f = FreeFile
        Open FileName For Binary As #f
        Put #f, , Player(Index).Char(I)
        Close #f

    Next I
End Sub

I’m not sure if this is needed, but it worked for me. Find this:

Sub ClearPlayer(ByVal Index As Long)
    Dim I As Long
    Dim n As Long

    Player(Index).Login = vbNullString
    Player(Index).Password = vbNullString
    For I = 1 To MAX_CHARS
        Player(Index).Char(I).Name = vbNullString
        Player(Index).Char(I).Class = 0
        Player(Index).Char(I).LEVEL = 0
        Player(Index).Char(I).Sprite = 0
        Player(Index).Char(I).Exp = 0
        Player(Index).Char(I).Access = 0
        Player(Index).Char(I).PK = NO
        Player(Index).Char(I).POINTS = 0
        Player(Index).Char(I).Guild = vbNullString

        Player(Index).Char(I).HP = 0
        Player(Index).Char(I).MP = 0
        Player(Index).Char(I).SP = 0

        Player(Index).Char(I).MAXHP = 0
        Player(Index).Char(I).MAXMP = 0
        Player(Index).Char(I).MAXSP = 0

        Player(Index).Char(I).STR = 0
        Player(Index).Char(I).DEF = 0
        Player(Index).Char(I).Speed = 0
        Player(Index).Char(I).Magi = 0

        For n = 1 To MAX_INV
            Player(Index).Char(I).Inv(n).num = 0
            Player(Index).Char(I).Inv(n).Value = 0
            Player(Index).Char(I).Inv(n).Dur = 0
        Next n
        For n = 1 To MAX_BANK
            Player(Index).Char(I).Bank(n).num = 0
            Player(Index).Char(I).Bank(n).Value = 0
            Player(Index).Char(I).Bank(n).Dur = 0
        Next n
        For n = 1 To MAX_PLAYER_SPELLS
            Player(Index).Char(I).Spell(n) = 0
        Next n

        Player(Index).Char(I).ArmorSlot = 0
        Player(Index).Char(I).WeaponSlot = 0
        Player(Index).Char(I).HelmetSlot = 0
        Player(Index).Char(I).ShieldSlot = 0
        Player(Index).Char(I).LegsSlot = 0
        Player(Index).Char(I).RingSlot = 0
        Player(Index).Char(I).NecklaceSlot = 0

        Player(Index).Char(I).Map = 0
        Player(Index).Char(I).X = 0
        Player(Index).Char(I).Y = 0
        Player(Index).Char(I).Dir = 0

        Player(Index).Locked = False
        Player(Index).LockedSpells = False
        Player(Index).LockedItems = False
        Player(Index).LockedAttack = False

        ' Temporary vars
        Player(Index).Buffer = vbNullString
        Player(Index).IncBuffer = vbNullString
        Player(Index).CharNum = 0
        Player(Index).InGame = False
        Player(Index).AttackTimer = 0
        Player(Index).DataTimer = 0
        Player(Index).DataBytes = 0
        Player(Index).DataPackets = 0
        Player(Index).PartyPlayer = 0
        Player(Index).InParty = False
        Player(Index).Target = 0
        Player(Index).TargetType = 0
        Player(Index).CastedSpell = NO
        Player(Index).PartyStarter = NO
        Player(Index).GettingMap = NO
        Player(Index).Emoticon = -1
        Player(Index).InTrade = False
        Player(Index).TradePlayer = 0
        Player(Index).TradeOk = 0
        Player(Index).TradeItemMax = 0
        Player(Index).TradeItemMax2 = 0
        For n = 1 To MAX_PLAYER_TRADES
            Player(Index).Trading(n).InvName = vbNullString
            Player(Index).Trading(n).InvNum = 0
        Next n
        Player(Index).ChatPlayer = 0
    Next I

End Sub

Replace it with this:

Sub ClearPlayer(ByVal Index As Long)
    Dim I As Long
    Dim n As Long
    Dim FileName As String

    FileName = App.Path & "\Accounts\" & Trim$(Player(Index).Login) & "_Info.ini"

    Player(Index).Login = vbNullString
    Player(Index).Password = GetVar(FileName, "ACCESS", "Password")
    For I = 1 To MAX_CHARS
        Player(Index).Char(I).Name = vbNullString
        Player(Index).Char(I).Class = 0
        Player(Index).Char(I).LEVEL = 0
        Player(Index).Char(I).Sprite = 0
        Player(Index).Char(I).Exp = 0
        Player(Index).Char(I).Access = 0
        Player(Index).Char(I).PK = NO
        Player(Index).Char(I).POINTS = 0
        Player(Index).Char(I).Guild = vbNullString

        Player(Index).Char(I).HP = 0
        Player(Index).Char(I).MP = 0
        Player(Index).Char(I).SP = 0

        Player(Index).Char(I).MAXHP = 0
        Player(Index).Char(I).MAXMP = 0
        Player(Index).Char(I).MAXSP = 0

        Player(Index).Char(I).STR = 0
        Player(Index).Char(I).DEF = 0
        Player(Index).Char(I).Speed = 0
        Player(Index).Char(I).Magi = 0

        For n = 1 To MAX_INV
            Player(Index).Char(I).Inv(n).num = 0
            Player(Index).Char(I).Inv(n).Value = 0
            Player(Index).Char(I).Inv(n).Dur = 0
        Next n
        For n = 1 To MAX_BANK
            Player(Index).Char(I).Bank(n).num = 0
            Player(Index).Char(I).Bank(n).Value = 0
            Player(Index).Char(I).Bank(n).Dur = 0
        Next n
        For n = 1 To MAX_PLAYER_SPELLS
            Player(Index).Char(I).Spell(n) = 0
        Next n

        Player(Index).Char(I).ArmorSlot = 0
        Player(Index).Char(I).WeaponSlot = 0
        Player(Index).Char(I).HelmetSlot = 0
        Player(Index).Char(I).ShieldSlot = 0
        Player(Index).Char(I).LegsSlot = 0
        Player(Index).Char(I).RingSlot = 0
        Player(Index).Char(I).NecklaceSlot = 0

        Player(Index).Char(I).Map = 0
        Player(Index).Char(I).X = 0
        Player(Index).Char(I).Y = 0
        Player(Index).Char(I).Dir = 0

        Player(Index).Locked = False
        Player(Index).LockedSpells = False
        Player(Index).LockedItems = False
        Player(Index).LockedAttack = False

        ' Temporary vars
        Player(Index).Buffer = vbNullString
        Player(Index).IncBuffer = vbNullString
        Player(Index).CharNum = 0
        Player(Index).InGame = False
        Player(Index).AttackTimer = 0
        Player(Index).DataTimer = 0
        Player(Index).DataBytes = 0
        Player(Index).DataPackets = 0
        Player(Index).PartyPlayer = 0
        Player(Index).InParty = False
        Player(Index).Target = 0
        Player(Index).TargetType = 0
        Player(Index).CastedSpell = NO
        Player(Index).PartyStarter = NO
        Player(Index).GettingMap = NO
        Player(Index).Emoticon = -1
        Player(Index).InTrade = False
        Player(Index).TradePlayer = 0
        Player(Index).TradeOk = 0
        Player(Index).TradeItemMax = 0
        Player(Index).TradeItemMax2 = 0
        For n = 1 To MAX_PLAYER_TRADES
            Player(Index).Trading(n).InvName = vbNullString
            Player(Index).Trading(n).InvNum = 0
        Next n
        Player(Index).ChatPlayer = 0
    Next I

End Sub

That’s it for modDatabase.

Now, open up modHandleData.

Look for this:

Public Sub Packet_QueryBox(ByVal Index As Long, ByVal Response As String, ByVal PromptNum As Long)
    If SCRIPTING = 1 Then
        Call PutVar(App.Path & "\Responses.ini", "Responses", CStr(Index), Response)
        MyScript.ExecuteStatement "Scripts\Main.txt", "QueryBox " & Index & "," & PromptNum
    End If
End Sub

Replace it with this:

Public Sub Packet_QueryBox(ByVal Index As Long, ByVal Response As String, ByVal PromptNum As Long)
    If SCRIPTING = 1 Then
        Call PutVar(App.Path & "\Responses.ini", GetPlayerLogin(Index), CStr(Index), Response)
        MyScript.ExecuteStatement "Scripts\Main.txt", "QueryBox " & Index & "," & PromptNum
    End If
End Sub

That should be all!

How to use this: Go into your game, and type “/editnpcs.” Find an available slot, and set the sprite to whatever you want. Set the HP to at least 1. Then, make the NPC a scripted NPC. Set the script to 0. Save your changes, and then place the NPC on the map.

What this does: When you talk to the NPC, a message box will pop up and tell you that he’s the password changer (you can change this). After that, you will be prompted to enter your current password. If the password that you type in is incorrect, the NPC will tell you that your password is wrong and to try again later when you know your password. This was intended to prevent siblings or friends from changing your password without your knowledge and gaining access to your account. If the password that you type in is correct, you will be prompted to type in a new password. If the new password you type in is the same as your existing password, it will tell you that you must select a different password because the password you entered is the same. Additionally, if the new password you type in is less than 3 characters in length, you will be asked to choose a different password because the one you typed in is too short.

After you type in an appropriate new password, a message box will pop up telling that your new password is whatever you selected and to come back to the NPC whenever you want to change your password again.

As far as I know, this works perfectly with no flaws. If anyone finds any errors/flaws, please tell me, and I’ll get to fixing them.

Thanks again to the people who helped me perfect this, and I hope you all enjoy it!

Is this for when you forget your password?

No, it’s simply for changing your password if you already know it.

Somebody should design a password reset system.
I believe one value of this password system is changing your password when somebody else figures it out. Am I right?

Well, I never really thought of that, but I guess so. It’s just so you can change your password for whatever reason, since by default, there is no option to do that, other than having the server owner change your password in a .INI file. I thought it would be easier for players if they can just simply change it in-game instead of having to ask the server owner to change it for them.

Log in to reply