Print Page | Close Window

Adding scripting capabitlies to a MS serv

Printed From: Mirage Source
Category: Tutorials
Forum Name: Temporary Archive (Read Only)
Forum Discription: Temporary 3.0.3 archive tutorials, will be deleted when converted.
URL: http://ms.shannaracorp.com/backup-forums/forum_posts.asp?TID=205
Printed Date: 20 December 2006 at 5:53pm
Software Version: Web Wiz Forums 8.01 - http://www.webwizforums.com


Topic: Adding scripting capabitlies to a MS serv
Posted By: Sync
Subject: Adding scripting capabitlies to a MS serv
Date Posted: 11 February 2006 at 3:30pm
[size=18px>This is NOT a beginner tutorial! The server is heavily modified and is not a full copy and paste tutorual! You have been warned!

First, http://www.dragonbound.com/classes.zip - download the needed classes and add them to the server project. This will allow you to add them as objects to use in scripting.

You need the scripting control referenced to do any scripting of course. Go to Project -> Components and check Microsoft Script Control 1.0. Add it to frmServer and name it ScriptControl.

Note: One major problem with using classes is you can't use an attribute called Type, so I renamed it to Typ. You'll have to change this in a lot of places.

Now in the server open up modTypes.

You can comment out the PlayerInvRec, PlayerRec, AccountRec, MapItemRec, MapNpcRec, SpellRec and TempTileRec UDTs (Types) as they won't be needed anymore. If you've changed any of these be sure to modify the corresponding classes.

Now you need to change some variable declarations to use classes. Here are the ones you need to change.

Public Map(1 To MAX_MAPS) As clsMap
Public TempTile(1 To MAX_MAPS) As clsTempTile
Public Player(1 To MAX_PLAYERS) As clsAccount
Public MapItem(1 To MAX_MAPS, 1 To MAX_MAP_ITEMS) As clsMapItem
Public MapNpc(1 To MAX_MAPS, 1 To MAX_MAP_NPCS) As clsMapNpc
Public Spell(1 To MAX_SPELLS) As clsSpell


I'm only adding support for scripting NPCs. You can extended it to other things based off this implementation. Open up modDatabase and add the following to the end of SaveNpc.

Call PutVar(FileName, "NPC" & NpcNum, "Script", Trim(Npc(NpcNum).Script))


And then below

Npc(i).MAGI = GetVar(FileName, "NPC" & i, "MAGI")


in LoadNpcs add

Npc(i).Script = GetVar(FileName, "NPC" & i, "Script")



This allows us to set a script file for a NPC.

Since maps are now classes and not UDTs we'll need to alter the saving and loading functions. I'm just going to paste them in. It just puts the class variables into the UDT and saves it. Vice versa for loading. This way you don't have to start your maps over. :)

Sub SaveMap(ByVal MapNum As Long)
Dim FileName As String
Dim f As Long
Dim J As Long 'ADDED
Dim K As Long 'ADDED
Dim MapTmp As MapRec 'ADDED

    FileName = App.Path & "\maps\map" & MapNum & ".dat"
        
    f = FreeFile
    Open FileName For Binary As #f
        'REMOVED
        'Put #f, , Map(MapNum)
       
        'ADDED
        With MapTmp
             .Name = Map(MapNum).Name
             .Revision = Map(MapNum).Revision
             .Moral = Map(MapNum).Moral
             .Up = Map(MapNum).Up
             .Down = Map(MapNum).Down
             .Left = Map(MapNum).Left
             .Right = Map(MapNum).Right
             .Music = Map(MapNum).Music
             .BootMap = Map(MapNum).BootMap
             .BootX = Map(MapNum).BootX
             .BootY = Map(MapNum).BootY
             .Shop = Map(MapNum).Shop
             .Indoors = Map(MapNum).Indoors
            
             For J = 0 To MAX_MAPX
                 For K = 0 To MAX_MAPY
                     .Tile(J, K).Ground = Map(MapNum).Tile(J, K).Ground
                     .Tile(J, K).Mask = Map(MapNum).Tile(J, K).Mask
                     .Tile(J, K).Anim = Map(MapNum).Tile(J, K).Anim
                     .Tile(J, K).Fringe = Map(MapNum).Tile(J, K).Fringe
                     .Tile(J, K).Type = Map(MapNum).Tile(J, K).Typ
                     .Tile(J, K).Data1 = Map(MapNum).Tile(J, K).Data1
                     .Tile(J, K).Data2 = Map(MapNum).Tile(J, K).Data2
                     .Tile(J, K).Data3 = Map(MapNum).Tile(J, K).Data3
                 Next K
             Next J
            
             For J = 1 To MAX_MAP_NPCS
                 .Npc(J) = Map(MapNum).Npc(J)
             Next J
        End With
       
        'ADDED
        Put #f, , MapTmp
    Close #f
End Sub

Sub SaveMaps()
Dim i As Long

    For i = 1 To MAX_MAPS
        Call SaveMap(i)
    Next i
End Sub

Sub LoadMaps()
Dim FileName As String
Dim i As Long
Dim J As Long 'ADDED
Dim K As Long 'ADDED
Dim f As Long
Dim MapTmp As MapRec 'ADDED

    Call CheckMaps
   
    For i = 1 To MAX_MAPS
        FileName = App.Path & "\maps\map" & i & ".dat"
       
        f = FreeFile
        Open FileName For Binary As #f
             'REMOVED
             'Get #f, , Map(i)
            
             'ADDED
             Get #f, , MapTmp
            
             'ADDED
             With Map(i)
                 .Name = MapTmp.Name
                 .Revision = MapTmp.Revision
                 .Moral = MapTmp.Moral
                 .Up = MapTmp.Up
                 .Down = MapTmp.Down
                 .Left = MapTmp.Left
                 .Right = MapTmp.Right
                 .Music = MapTmp.Music
                 .BootMap = MapTmp.BootMap
                 .BootX = MapTmp.BootX
                 .BootY = MapTmp.BootY
                 .Shop = MapTmp.Shop
                 .Indoors = MapTmp.Indoors
                
                 For J = 0 To MAX_MAPX
                     For K = 0 To MAX_MAPY
                           .Tile(J, K).Ground = MapTmp.Tile(J, K).Ground
                           .Tile(J, K).Mask = MapTmp.Tile(J, K).Mask
                           .Tile(J, K).Anim = MapTmp.Tile(J, K).Anim
                           .Tile(J, K).Fringe = MapTmp.Tile(J, K).Fringe
                           .Tile(J, K).Typ = MapTmp.Tile(J, K).Type
                           .Tile(J, K).Data1 = MapTmp.Tile(J, K).Data1
                           .Tile(J, K).Data2 = MapTmp.Tile(J, K).Data2
                           .Tile(J, K).Data3 = MapTmp.Tile(J, K).Data3
                     Next K
                 Next J
                
                 For J = 1 To MAX_MAP_NPCS
                     .Npc(J) = MapTmp.Npc(J)
                 Next J
             End With
        Close #f
   
        DoEvents
    Next i
End Sub


We need a sub to add all our class objects to the scripting control. This allows us to use them in scripts. Add this somewhere in modGeneral.

Private Sub Scripting_Init()
Dim Account     As New clsAccount
Dim Item        As New clsItem
Dim Map         As New clsMap
Dim MapItem     As New clsMapItem
Dim MapNpc      As New clsMapNpc
Dim Player      As New clsPlayer
Dim PlayerInv   As New clsPlayerInv
Dim Spell       As New clsSpell
Dim TempTile    As New clsTempTile
Dim Tile        As New clsTile
Dim Funcs       As New clsFunctions

    ' Add the objects to the scripting engine.
    frmServer.ScriptControl.AddObject "Account", Account, True
    frmServer.ScriptControl.AddObject "Item", Item, True
    frmServer.ScriptControl.AddObject "Map", Map, True
    frmServer.ScriptControl.AddObject "MapItem", MapItem, True
    frmServer.ScriptControl.AddObject "MapNpc", MapNpc, True
    frmServer.ScriptControl.AddObject "Player", Player, True
    frmServer.ScriptControl.AddObject "PlayerInv", PlayerInv, True
    frmServer.ScriptControl.AddObject "Spell", Spell, True
    frmServer.ScriptControl.AddObject "TempTile", TempTile, True
    frmServer.ScriptControl.AddObject "Tile", Tile, True
    frmServer.ScriptControl.AddObject "Funcs", Funcs, True
   
    ' Clean up.
    Set Account = Nothing
    Set Item = Nothing
    Set Map = Nothing
    Set MapItem = Nothing
    Set MapNpc = Nothing
    Set Player = Nothing
    Set PlayerInv = Nothing
    Set Spell = Nothing
    Set TempTile = Nothing
    Set Tile = Nothing
    Set Funcs = Nothing
End Sub


I also wrote a simple function to load scripts.

Public Function OpenScript(ByVal strFilename As String) As String
    If Not FileExist("\scripts\" & strFilename) Then Exit Function

Dim intFileNum As Integer
Dim strBuffer As String

    intFileNum = FreeFile

    Open App.Path & "\scripts\" & strFilename For Input As #intFileNum
        OpenScript = Input$(LOF(intFileNum), #intFileNum)
    Close #intFileNum
End Function


Now in the top of InitServer also modGeneral add

Scripting_Init()


to initialize the scripting stuff.

Now for the memory intesive part of creating the objects. Put this right below Scripting_Init()

    'ADDED
    Scripting_Init
   
    '
    ' INIT ALL CLASS OBJECTS
    '
    For i = 1 To MAX_MAPS
        Set Map(i) = New clsMap
        Set TempTile(i) = New clsTempTile
    Next i
   
    For i = 1 To MAX_PLAYERS
        Set Player(i) = New clsAccount
    Next i
   
    For i = 1 To MAX_MAPS
        For f = 1 To MAX_MAP_ITEMS
             Set MapItem(i, f) = New clsMapItem
        Next f
    Next i
   
    For i = 1 To MAX_MAPS
        For f = 1 To MAX_MAP_NPCS
             Set MapNpc(i, f) = New clsMapNpc
        Next f
    Next i
   
    For i = 1 To MAX_SPELLS
        Set Spell(i) = New clsSpell
    Next i


You could modify it to only create them when need. Or even better use collections instead of static arrays, but that's another tutorial. :) If you're not sure what this is doing, learn classes. :P

Now open modGameLogic and go to Sub SpawnNPC and right below

MapNpc(MapNum, MapNpcNum).Dir = Int(Rnd * 4)


add

        On Error Resume Next
        If Npc(NpcNum).Script <> "" And frmServer.ScriptControl.Modules.Item("NPC_" & CStr(MapNum & "_" & MapNpcNum)) Is Nothing Then
             On Error GoTo 0
             ' Create the scripting module for this NPC.
             frmServer.ScriptControl.Modules.Add "NPC_" & CStr(MapNum & "_" & MapNpcNum)
             MapNpc(MapNum, MapNpcNum).Script = frmServer.ScriptControl.Modules("NPC_" & CStr(MapNum & "_" & MapNpcNum))
       
             ' Add the code to the new module.
             MapNpc(MapNum, MapNpcNum).Script.AddCode OpenScript(Npc(NpcNum).Script)
        End If
        On Error GoTo 0


This loads a NPCs script when it spawns, if it has one.

I'm going add in the capabilitiy of doing things when NPCs move and die.

For dying go to AttackNpc in modGameLogic and add

        If MapNpc(MapNum, MapNpcNum).Script.Procedures.Count > 0 Then
             MapNpc(MapNum, MapNpcNum).Script.Run "Killed", Map(MapNum), MapNpc(MapNum, MapNpcNum), Player(Attacker)
        End If


right below

Call SendDataToMap(MapNum, "NPCDEAD" & SEP_CHAR & MapNpcNum & SEP_CHAR & END_CHAR)


And add

    If MapNpc(MapNum, MapNpcNum).Script.Procedures.Count > 0 Then
        MapNpc(MapNum, MapNpcNum).Script.Run "Move", Map(MapNum), MapNpc(MapNum, MapNpcNum)
    End If


to the end of NpcMove.

When you call run if you want to pass parameters just do so as you would any others. Just make sure you add them in the script.

Now create a folder in the server root directory called scripts.

Here's a sample script.

Sub Move(Map, Npc)
    If Npc.X => 5 And Npc.X <= 10 And Npc.Y => 5 And Npc.Y <= 10 Then
        GlobalMsg Npc.Num & " has opened a portal to another world.", 3
    End If
End Sub

Sub Killed(Map, Npc, Killer)
    GlobalMsg "My comrades will avenge my death, " & Trim(Killer.Char(Killer.CharNum).Name) & "!", 3
End Sub


Don't type any variables in scripts! It doesn't work. (Eg. Blah As String)

Save it and then edit a NPC, Pirate for example. Add the line Script=whatever_u_called_it_above.txt

No need for a path, just the filename with the extension. You will probably want to incorporate this into the NPC editor instead of doing it by hand.

Now start up the server, login and add whatever NPC you edited above. You should see a message when it dies and walks within a certain area.

I believe this is it. It's been a while since I've used it. If this doesn't work with a few corrections I'll just upload my version of the server. Don't forget to change .Type's to .Typ's! Enjoy!



Print Page | Close Window

Bulletin Board Software by Web Wiz Forums version 8.01 - http://www.webwizforums.com
Copyright ©2001-2006 Web Wiz Guide - http://www.webwizguide.info