Warp on quest completion

From VbGORE Visual Basic Online RPG Engine


This tutorial will help you to add a new feature on your quest system. It's simple: When the quest is finished, the player will be warped to the place that you choose.


In Server, Declares.bas, Find :

'************ Quest ************
Public Type Quest
    Name As String                  'The quest's name
    StartTxt As String              'What the NPC says to the player to explain the crisis
    AcceptTxt As String             'What the NPC says when the player accepts the quest
    IncompleteTxt As String         'What the NPC says to the player when they return without completing the quest
    FinishTxt As String             'What the NPC says when the player finishes the quest
    AcceptReqLvl As Long            'What level the user is required to be to accept
    AcceptReqObj As Integer         'Index of the object the user is required to have to accept
    AcceptReqObjAmount As Integer   'How much of the object the user must have before accepting
    AcceptReqFinishQuest As Integer 'Quest that must be finished prior to accepting this quest
    AcceptRewExp As Long            'Amount of Exp the user gets for accepting the quest
    AcceptRewGold As Long           'Amount of gold the user gets for accepting the quest
    AcceptRewObj As Integer         'Object the user gets for accepting the quest
    AcceptRewObjAmount As Integer   'Amount of the object the user gets for accepting the quest
    AcceptLearnSkill As Byte        'Skill the user learns for accepting the quest (by SkID value)
    FinishReqObj As Integer         'Object the user must have to finish the quest
    FinishReqObjAmount As Integer   'Amount of the object the user must have to finish the quest
    FinishReqNPC As Integer         'Index of the NPC the user must kill to finish the quest
    FinishReqNPCAmount As Integer   'How many of the NPCs the user must kill to finish the quest
    FinishRewExp As Long            'Exp the user gets for finishing the quest
    FinishRewGold As Long           'How much gold the user gets for finishing the quest
    FinishRewObj As Integer         'The index of the object the user gets for finishing the quest
    FinishRewObjAmount As Integer   'The amount of the object the user gets for finishing the quest
    FinishLearnSkill As Byte        'Skill the user learns for finishing the quest (by SkID value)
    Redoable As Byte                'If the quest can be done infinite times
End Type

Append The following

FinishWarpMap As Integer
FinishWarpX As Byte
FinishWarpY As Byte

Very Easy, Then go to Server,FileIO.bas Find this:

Public Sub Load_Quests()

If you have not modified the code before, Replace The whole sub with : Getting SQL DATA INIT

Public Sub Load_Quests()
 
    Log "Call Load_Quests", CodeTracker '//\\LOGLINE//\\
 
    'Get the number of quests (Sort by id, descending, only get 1 entry, only return id)
    DB_RS.Open "SELECT id FROM quests ORDER BY id DESC LIMIT 1", DB_Conn, adOpenStatic, adLockOptimistic
    If DB_RS.EOF Then MsgBox "Oh crap, you don't have any quests! This isn't going to be pretty...", vbOKOnly
    NumQuests = DB_RS(0)
    DB_RS.Close
 
    Log "Load_Quests: Resizing QuestData array by NumQuests (" & NumQuests & ")", CodeTracker '//\\LOGLINE//\\
 
    'Resize the quests array
    ReDim QuestData(1 To NumQuests)
 
    'Retrieve the data from the database
    DB_RS.Open "SELECT * FROM quests", DB_Conn, adOpenStatic, adLockOptimistic
 
    'Fill in the information
    Do While Not DB_RS.EOF  'Loop until we reach the end of the recordset
        With QuestData(DB_RS!id)
            Log "Load_Quests: Filling QuestData for quest " & DB_RS!id, CodeTracker '//\\LOGLINE//\\
            .Name = Trim$(DB_RS!Name)
            .Redoable = Val(DB_RS!Redoable)
            .StartTxt = Trim$(DB_RS!text_start)
            .AcceptTxt = Trim$(DB_RS!text_accept)
            .IncompleteTxt = Trim$(DB_RS!text_incomplete)
            .FinishTxt = Trim$(DB_RS!text_finish)
            .AcceptReqLvl = Val(DB_RS!accept_req_level)
            .AcceptReqObj = Val(DB_RS!accept_req_obj)
            .AcceptReqObjAmount = Val(DB_RS!accept_req_objamount)
            .AcceptReqFinishQuest = Val(DB_RS!accept_req_finishquest)
            .AcceptRewExp = Val(DB_RS!accept_reward_exp)
            .AcceptRewGold = Val(DB_RS!accept_reward_gold)
            .AcceptRewObj = Val(DB_RS!accept_reward_obj)
            .AcceptRewObjAmount = Val(DB_RS!accept_reward_objamount)
            .AcceptLearnSkill = Val(DB_RS!accept_reward_learnskill)
            .FinishReqObj = Val(DB_RS!finish_req_obj)
            .FinishReqObjAmount = Val(DB_RS!finish_req_objamount)
            .FinishReqNPC = Val(DB_RS!finish_req_killnpc)
            .FinishReqNPCAmount = Val(DB_RS!finish_req_killnpcamount)
            .FinishRewExp = Val(DB_RS!finish_reward_exp)
            .FinishRewGold = Val(DB_RS!finish_reward_gold)
            .FinishRewObj = Val(DB_RS!finish_reward_obj)
            .FinishRewObjAmount = Val(DB_RS!finish_reward_objamount)
            .FinishLearnSkill = Val(DB_RS!finish_reward_learnskill)
            .FinishWarpMap = Val(DB_RS!finish_warpmap)
            .FinishWarpX = Val(DB_RS!finish_warpx)
            .FinishWarpY = Val(DB_RS!finish_warpy)
 
        End With
        DB_RS.MoveNext
    Loop
 
    'Close the recordset
    DB_RS.Close
 
End Sub

Now we move on to Server, Quest.bas Find

Private Sub Quest_CheckIfComplete(ByVal UserIndex As Integer, ByVal NPCIndex As Integer, ByVal UserQuestSlot As Byte)

If you have not modified this part of code, Replace the whole sub with :

Private Sub Quest_CheckIfComplete(ByVal UserIndex As Integer, ByVal NPCIndex As Integer, ByVal UserQuestSlot As Byte)
 
'*****************************************************************
'Checks if a quest is ready to be completed
'*****************************************************************
Dim ReqObjSlot As Byte
Dim Slot As Byte
Dim s As String
Dim i As Long
Dim tPos As WorldPos
Dim nPos As WorldPos
 
    Log "Call Quest_CheckIfComplete(" & UserIndex & "," & NPCIndex & "," & UserQuestSlot & ")", CodeTracker '//\\LOGLINE//\\
 
    'Check NPC kills
    If QuestData(NPCList(NPCIndex).Quest).FinishReqNPC Then
        If UserList(UserIndex).QuestStatus(UserQuestSlot).NPCKills < QuestData(NPCList(NPCIndex).Quest).FinishReqNPCAmount Then
            Quest_SayIncomplete UserIndex, NPCIndex
            Exit Sub
        End If
    End If
 
    'Check objects
    If QuestData(NPCList(NPCIndex).Quest).FinishReqObj Then
 
        'Check through the user's slots looking for the object of the same index
        For Slot = 1 To MAX_INVENTORY_SLOTS
            If UserList(UserIndex).Object(Slot).ObjIndex = QuestData(NPCList(NPCIndex).Quest).FinishReqObj Then
 
                'Cache the required object slot (we will be using it later if the quest is complete)
                ReqObjSlot = Slot
 
                'Check the amount the user has
                If UserList(UserIndex).Object(Slot).Amount < QuestData(NPCList(NPCIndex).Quest).FinishReqObjAmount Then
                    Quest_SayIncomplete UserIndex, NPCIndex
                    Exit Sub
                Else
                    'We will set the slot to 0 so we can check if we ran out of slots or found the object we were looking for
                    Slot = 0
                    Exit For
                End If
 
                'And now we check! lawlz! ^_^
                If Slot <> 0 Then
                    Quest_SayIncomplete UserIndex, NPCIndex
                    Exit Sub
                End If
 
            End If
        Next Slot
 
        'If we made it through the whole loop without finding a slot (that is, if the slot = MAX_INVENTORY_SLOTS + 1) then
        'the object was not found in the user's inventory at all, so give them the missing error and abort
        If Slot = MAX_INVENTORY_SLOTS + 1 Then
            Quest_SayIncomplete UserIndex, NPCIndex
            Exit Sub
        End If
 
    End If
 
    '*** Quest was completed! ***
 
    'Say the finishing text
    ConBuf.PreAllocate 5 + Len(NPCList(NPCIndex).Name) + Len(QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishTxt)
    ConBuf.Put_Byte DataCode.Comm_Talk
    ConBuf.Put_String NPCList(NPCIndex).Name & ": " & QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishTxt
    ConBuf.Put_Byte DataCode.Comm_FontType_Talk
    Data_Send ToNPCArea, NPCIndex, ConBuf.Get_Buffer, NPCList(NPCIndex).Pos.Map
 
    'The user is done, give them the rewards
    'EXP reward
    If QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishRewExp > 0 Then
        User_RaiseExp UserIndex, QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishRewExp
        ConBuf.PreAllocate 6
        ConBuf.Put_Byte DataCode.Server_Message
        ConBuf.Put_Byte 3
        ConBuf.Put_Long QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishRewExp
        Data_Send ToIndex, UserIndex, ConBuf.Get_Buffer
    End If
 
    'Gold reward
    If QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishRewGold > 0 Then
        UserList(UserIndex).Stats.BaseStat(SID.Gold) = UserList(UserIndex).Stats.BaseStat(SID.Gold) + QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishRewGold
        ConBuf.PreAllocate 6
        ConBuf.Put_Byte DataCode.Server_Message
        ConBuf.Put_Byte 4
        ConBuf.Put_Long QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishRewGold
        Data_Send ToIndex, UserIndex, ConBuf.Get_Buffer
    End If
 
    'Remove the quest object
    If ReqObjSlot > 0 Then
        User_RemoveObj UserIndex, ReqObjSlot, QuestData(NPCList(NPCIndex).Quest).FinishReqObjAmount
    End If
 
    'Give the object reward
    If QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishRewObj > 0 Then
        User_GiveObj UserIndex, QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishRewObj, QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishRewObjAmount
    End If
 
    'Learn skill reward
    If QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishLearnSkill > 0 Then
        User_GiveSkill UserIndex, QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishLearnSkill
    End If
    'After Quest Warp
 
    If QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishWarpMap > 0 Then
tpos.Map = QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishWarpMap
tpos.X = QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishWarpX
tpos.Y = QuestData(UserList(UserIndex).Quest(UserQuestSlot)).FinishWarpY
Server_ClosestLegalPos tpos, npos
 
        If Server_LegalPos(tpos.Map, tpos.X,tpos.Y, 1) Then
User_WarpChar UserIndex, npos.Map, npos.X, npos.Y, False
'You may Put Your Own Message To the client here
End If
End If
 
 
 
    'Add the quest to the user's finished quest list
    If QuestData(UserList(UserIndex).Quest(UserQuestSlot)).Redoable Then
 
        'Only add a redoable quest in the list once
        Log "Quest_CheckIfComplete: Using InStr() operation", CodeTracker '//\\LOGLINE//\\
        If UserList(UserIndex).NumCompletedQuests > 0 Then
            For i = 1 To UserList(UserIndex).NumCompletedQuests
 
                'If we find the quest in here, leave and don't add it to the list
                If UserList(UserIndex).CompletedQuests(i) = UserList(UserIndex).Quest(UserQuestSlot) Then Exit For
 
                'We hit the end of the loop and no match found, set the add to list flag and leave
                If i = UserList(UserIndex).NumCompletedQuests Then
                    i = -1
                    Exit For
                End If
 
            Next i
        Else
 
            'The user has never completed a quest before, so we have to add this one
            i = -1
 
        End If
 
    Else
 
        'Set the flag to add to the list
        i = -1
 
    End If
 
    'Add to the list if needed
    If i = -1 Then
        UserList(UserIndex).NumCompletedQuests = UserList(UserIndex).NumCompletedQuests + 1
        ReDim Preserve UserList(UserIndex).CompletedQuests(1 To UserList(UserIndex).NumCompletedQuests)
        UserList(UserIndex).CompletedQuests(UserList(UserIndex).NumCompletedQuests) = UserList(UserIndex).Quest(UserQuestSlot)
    End If
 
    'Clear the quest slot so it can be used again
    UserList(UserIndex).QuestStatus(UserQuestSlot).NPCKills = 0
    UserList(UserIndex).Quest(UserQuestSlot) = 0
 
    'Update the quest text
    Quest_SendText UserIndex, UserQuestSlot
 
End Sub

Finally, Add these row to SQL:VBGORE:QUESTS (and you can use those tags when making the quest)

finish_warpmap
finish_warpx
finish_warpy