Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

[EO] Alatar's Quest System v1.2


Alatar
 Share

Recommended Posts

That is because that is also the delete button when num lock isn't on I suggest removing that part or add a check to make it only work if the quest log is open or whatever you want. It does it for everyone =)
I just removed it from my project cause I didn't like the way it worked and you can cancel a quest so easily
Link to comment
Share on other sites

  • Replies 703
  • Created
  • Last Reply

Top Posters In This Topic

I did all you  told me to do in the quest side and that pretty much what i did but i just wanted to check if the server side was working without doing the client side. And i compiled and got this error

"compile error
Varialbe not define"

Then it goes to the sciprt with which there is a problem. [modtype]

PlayerQuest(1 To MAX_QUESTS) As PlayerQuestRec

It highlights max_quests

i put a number there but it was of no use!! :sad:

help!!!!!!!!!!!=
Link to comment
Share on other sites

  • 3 weeks later...
I am not sure if something like this has been posted here yet- but here is a nice small but big fix so the quest can differentiate when talking to an NPC- this fixes if they are talking to NPC for GOTALK, GOGIVE or GOGET … and makes em work ;)

**Server side-
in ModsvQuests replace  Sub CheckTasks (NOT THE BIG CHECKTASK) with:**

```
Public Sub CheckTasks(ByVal Index As Long, ByVal TaskType As Long, ByVal TargetIndex As Long)
    Dim i As Long
    For i = 1 To MAX_QUESTS
        If QuestInProgress(Index, i) Then
          Dim ActualTask As Long
          ActualTask = Player(Index).PlayerQuest(i).ActualTask
            If TaskType = Quest(i).Task(ActualTask).Order Then
                Call CheckTask(Index, i, TaskType, TargetIndex)
            End If
        End If
    Next
End Sub
```
Not completely tested but should work- enjoy :)
Link to comment
Share on other sites

  • 2 weeks later...
Another bug fixe for taking items:

**Server Side**

In **modSvQuests**, in **EndQuest** replace this:
```
'remove items on the end
    If Quest(QuestNum).QuestRemoveItem > 0 And Quest(QuestNum).QuestRemoveItem < MAX_ITEMS Then
        If Quest(QuestNum).QuestRemoveItemValue > 0 And Quest(QuestNum).QuestRemoveItemValue < MAX_INV Then 'ToDo: stuff with currency
            For i = 1 To MAX_INV
                If HasItem(Index, Quest(QuestNum).QuestRemoveItem) Then
                    TakeInvItem Index, Quest(QuestNum).QuestRemoveItem, Quest(QuestNum).QuestRemoveItemValue 'todo: currency stuff...
                End If
            Next
        End If
    End If
```
With this:
```
'remove items on the end
    If Quest(QuestNum).QuestRemoveItem > 0 And Quest(QuestNum).QuestRemoveItem < MAX_ITEMS Then
        If Quest(QuestNum).QuestRemoveItemValue > 0 And Quest(QuestNum).QuestRemoveItemValue < MAX_INV Then 'ToDo: stuff with currency
            For i = 1 To Quest(QuestNum).QuestRemoveItemValue
                If HasItem(Index, Quest(QuestNum).QuestRemoveItem) Then
                    TakeInvItem Index, Quest(QuestNum).QuestRemoveItem, Quest(QuestNum).QuestRemoveItemValue 'todo: currency stuff...
                End If
            Next
        End If
    End If
```
Link to comment
Share on other sites

For some reason I cannot have CS:DE converted convo system and this at the same time, I don't know why, but when pressing ctrl with a npc, it does not open the quest box. I tested lots of stuff, and I opened the version w/o the convo, and it works fine as soon as I click ctrl. I haven't moved any boxes at all when I made the convo system. Anybody can help me?
Link to comment
Share on other sites

@Whack:

> For some reason I cannot have CS:DE converted convo system and this at the same time, I don't know why, but when pressing ctrl with a npc, it does not open the quest box. I tested lots of stuff, and I opened the version w/o the convo, and it works fine as soon as I click ctrl. I haven't moved any boxes at all when I made the convo system. Anybody can help me?

In Server modCombat under "Public Function CanPlayerAttackNpc" find these lines:

```
If NPC(npcNum).Behaviour = NPC_BEHAVIOUR_FRIENDLY Then
                            Call CheckTasks(attacker, QUEST_TYPE_GOTALK, npcNum)
                            Call CheckTasks(attacker, QUEST_TYPE_GOGIVE, npcNum)
                            Call CheckTasks(attacker, QUEST_TYPE_GOGET, npcNum)

                            If NPC(npcNum).Quest = YES Then
                                If CanStartQuest(attacker, NPC(npcNum).QuestNum) Then
                                    'if can start show the request message (chat1)
                                    QuestMessage attacker, NPC(npcNum).QuestNum, Trim$(Quest(NPC(npcNum).QuestNum).Chat(1)), NPC(npcNum).QuestNum
                                    Exit Function
                                End If
                                If QuestInProgress(attacker, NPC(npcNum).QuestNum) Then
                                    'if the quest is in progress show the meanwhile message (chat2)
                                    PlayerMsg attacker, Trim$(NPC(npcNum).Name) + ": " + Trim$(Quest(NPC(npcNum).QuestNum).Chat(2)), BrightGreen
                                    'QuestMessage attacker, NPC(npcNum).QuestNum, Trim$(Quest(NPC(npcNum).QuestNum).Chat(2)), 0
                                    Exit Function
                                End If
                            End If
```
And right under those add:

```
If NPC(npcNum).Quest = NO Then
                                If NPC(npcNum).Convo = False Then
                                  If Len(Trim$(NPC(npcNum).AttackSay)) > 0 Then
                                    PlayerMsg attacker, Trim$(NPC(npcNum).Name) + ": " + Trim$(Quest(NPC(npcNum).QuestNum).Chat(2)), BrightGreen
                                  End If
                                Else
                                    InitChat attacker, mapNum, mapNpcNum
                                End If
                                Exit Function
                            End If
                        End If
```
IF youre using a speech window instead of regular text messages for a non-convo npc, then replace:

```
PlayerMsg attacker, Trim$(NPC(npcNum).Name) + ": " + Trim$(Quest(NPC(npcNum).QuestNum).Chat(2)), BrightGreen
```
with:

```
Call SpeechWindow(attacker, Trim$(NPC(npcNum).AttackSay), npcNum)
```
Link to comment
Share on other sites

@Whack:

> hmm…doesn't seem to be helping. After putting that first code in, I get End If without Block If, so I erased one End If, and the server works, but when I test it nothing happens again. :/

You might be missing something from the tutorial.. Can you post a screenie of your modCombat in the meantime? Also, you may want to try deleting all npc data and starting a new char.
Link to comment
Share on other sites

Let me try deleting all npc data and characters, then try again.

if that doesn't help I will upload my modCombat. please understand that my server and client.vbp's have the convo system on them, but my client.exe and server.exe only have the quests. When I just run the .exes, it works fine. But when I open them in vbp, with the convo system, everything works fine except for the quests not opening when I press ctrl on npc.

Edit: Deleting accounts and npc data did not help, here is my **whole** modCombat. Beware: huge spoiler

>! Option Explicit
>! ' ################################
' ##      Basic Calculations    ##
' ################################
>! Function GetPlayerMaxVital(ByVal Index As Long, ByVal Vital As Vitals) As Long
    If Index > MAX_PLAYERS Then Exit Function
    Select Case Vital
        Case HP
            Select Case GetPlayerClass(Index)
                Case 1 ' Warrior
                    GetPlayerMaxVital = ((GetPlayerLevel(Index) / 2) + (GetPlayerStat(Index, Endurance) / 2)) * 15 + 150
                Case 2 ' Mage
                    GetPlayerMaxVital = ((GetPlayerLevel(Index) / 2) + (GetPlayerStat(Index, Endurance) / 2)) * 5 + 65
                Case Else ' Anything else - Warrior by default
                    GetPlayerMaxVital = ((GetPlayerLevel(Index) / 2) + (GetPlayerStat(Index, Endurance) / 2)) * 15 + 150
            End Select
        Case MP
            Select Case GetPlayerClass(Index)
                Case 1 ' Warrior
                    GetPlayerMaxVital = ((GetPlayerLevel(Index) / 2) + (GetPlayerStat(Index, Intelligence) / 2)) * 5 + 25
                Case 2 ' Mage
                    GetPlayerMaxVital = ((GetPlayerLevel(Index) / 2) + (GetPlayerStat(Index, Intelligence) / 2)) * 30 + 85
                Case Else ' Anything else - Warrior by default
                    GetPlayerMaxVital = ((GetPlayerLevel(Index) / 2) + (GetPlayerStat(Index, Intelligence) / 2)) * 5 + 25
            End Select
    End Select
End Function
>! Function GetPlayerVitalRegen(ByVal Index As Long, ByVal Vital As Vitals) As Long
    Dim i As Long
>!     ' Prevent subscript out of range
    If IsPlaying(Index) = False Or Index <= 0 Or Index > MAX_PLAYERS Then
        GetPlayerVitalRegen = 0
        Exit Function
    End If
>!     Select Case Vital
        Case HP
            i = (GetPlayerStat(Index, Stats.Willpower) * 0.8) + 6
        Case MP
            i = (GetPlayerStat(Index, Stats.Willpower) / 4) + 12.5
    End Select
>!     If i < 2 Then i = 2
    GetPlayerVitalRegen = i
End Function
>! Function GetPlayerDamage(ByVal Index As Long) As Long
    Dim weaponNum As Long

    GetPlayerDamage = 0
>!     ' Check for subscript out of range
    If IsPlaying(Index) = False Or Index <= 0 Or Index > MAX_PLAYERS Then
        Exit Function
    End If
    If GetPlayerEquipment(Index, Weapon) > 0 Then
        weaponNum = GetPlayerEquipment(Index, Weapon)
        GetPlayerDamage = 0.085 * 5 * GetPlayerStat(Index, Strength) * Item(weaponNum).Data2 + (GetPlayerLevel(Index) / 5)
    Else
        GetPlayerDamage = 0.085 * 5 * GetPlayerStat(Index, Strength) + (GetPlayerLevel(Index) / 5)
    End If
>! End Function
Function GetPlayerDef(ByVal Index As Long) As Long
    Dim DefNum As Long
    Dim Def As Long

    GetPlayerDef = 0
    Def = 0
    ' Check for subscript out of range
    If IsPlaying(Index) = False Or Index <= 0 Or Index > MAX_PLAYERS Then
        Exit Function
    End If

    If GetPlayerEquipment(Index, Armor) > 0 Then
        DefNum = GetPlayerEquipment(Index, Armor)
        Def = Def + Item(DefNum).Data2
    End If

    If GetPlayerEquipment(Index, Helmet) > 0 Then
        DefNum = GetPlayerEquipment(Index, Helmet)
        Def = Def + Item(DefNum).Data2
    End If

    If GetPlayerEquipment(Index, Shield) > 0 Then
        DefNum = GetPlayerEquipment(Index, Shield)
        Def = Def + Item(DefNum).Data2
    End If

  If Not GetPlayerEquipment(Index, Armor) > 0 And Not GetPlayerEquipment(Index, Helmet) > 0 And Not GetPlayerEquipment(Index, Shield) > 0 Then
        GetPlayerDef = 0.085 * GetPlayerStat(Index, Endurance) + (GetPlayerLevel(Index) / 5)
    Else
        GetPlayerDef = 0.085 * GetPlayerStat(Index, Endurance) * Def + (GetPlayerLevel(Index) / 5)
    End If

>! End Function
>! Function GetNpcMaxVital(ByVal npcNum As Long, ByVal Vital As Vitals) As Long
    Dim x As Long
>!     ' Prevent subscript out of range
    If npcNum <= 0 Or npcNum > MAX_NPCS Then
        GetNpcMaxVital = 0
        Exit Function
    End If
>!     Select Case Vital
        Case HP
            GetNpcMaxVital = NPC(npcNum).HP
        Case MP
            GetNpcMaxVital = 30 + (NPC(npcNum).Stat(Intelligence) * 10) + 2
    End Select
>! End Function
>! Function GetNpcVitalRegen(ByVal npcNum As Long, ByVal Vital As Vitals) As Long
    Dim i As Long
>!     'Prevent subscript out of range
    If npcNum <= 0 Or npcNum > MAX_NPCS Then
        GetNpcVitalRegen = 0
        Exit Function
    End If
>!     Select Case Vital
        Case HP
            i = (NPC(npcNum).Stat(Stats.Willpower) * 0.8) + 6
        Case MP
            i = (NPC(npcNum).Stat(Stats.Willpower) / 4) + 12.5
    End Select

    GetNpcVitalRegen = i
>! End Function
>! Function GetNpcDamage(ByVal npcNum As Long) As Long
    GetNpcDamage = 0.085 * 5 * NPC(npcNum).Stat(Stats.Strength) * NPC(npcNum).Damage + (NPC(npcNum).Level / 5)
End Function
>! ' ###############################
' ##      Luck-based rates    ##
' ###############################
>! Public Function CanPlayerBlock(ByVal Index As Long) As Boolean
Dim rate As Long
Dim rndNum As Long
>!     CanPlayerBlock = False
>!     rate = 0
    ' TODO : make it based on shield lulz
End Function
>! Public Function CanPlayerCrit(ByVal Index As Long) As Boolean
Dim rate As Long
Dim rndNum As Long
>!     CanPlayerCrit = False
>!     rate = GetPlayerStat(Index, Agility) / 52.08
    rndNum = RAND(1, 100)
    If rndNum <= rate Then
        CanPlayerCrit = True
    End If
End Function
>! Public Function CanPlayerDodge(ByVal Index As Long) As Boolean
Dim rate As Long
Dim rndNum As Long
>!     CanPlayerDodge = False
>!     rate = GetPlayerStat(Index, Agility) / 83.3
    rndNum = RAND(1, 100)
    If rndNum <= rate Then
        CanPlayerDodge = True
    End If
End Function
>! Public Function CanPlayerParry(ByVal Index As Long) As Boolean
Dim rate As Long
Dim rndNum As Long
>!     CanPlayerParry = False
>!     rate = GetPlayerStat(Index, Strength) * 0.25
    rndNum = RAND(1, 100)
    If rndNum <= rate Then
        CanPlayerParry = True
    End If
End Function
>! Public Function CanNpcBlock(ByVal npcNum As Long) As Boolean
Dim rate As Long
Dim rndNum As Long
>!     CanNpcBlock = False
>!     rate = 0
    ' TODO : make it based on shield lol
End Function
>! Public Function CanNpcCrit(ByVal npcNum As Long) As Boolean
Dim rate As Long
Dim rndNum As Long
>!     CanNpcCrit = False
>!     rate = NPC(npcNum).Stat(Stats.Agility) / 52.08
    rndNum = RAND(1, 100)
    If rndNum <= rate Then
        CanNpcCrit = True
    End If
End Function
>! Public Function CanNpcDodge(ByVal npcNum As Long) As Boolean
Dim rate As Long
Dim rndNum As Long
>!     CanNpcDodge = False
>!     rate = NPC(npcNum).Stat(Stats.Agility) / 83.3
    rndNum = RAND(1, 100)
    If rndNum <= rate Then
        CanNpcDodge = True
    End If
End Function
>! Public Function CanNpcParry(ByVal npcNum As Long) As Boolean
Dim rate As Long
Dim rndNum As Long
>!     CanNpcParry = False
>!     rate = NPC(npcNum).Stat(Stats.Strength) * 0.25
    rndNum = RAND(1, 100)
    If rndNum <= rate Then
        CanNpcParry = True
    End If
End Function
>! ' ###################################
' ##      Player Attacking NPC    ##
' ###################################
>! Public Sub TryPlayerAttackNpc(ByVal Index As Long, ByVal mapNpcNum As Long)
Dim blockAmount As Long
Dim npcNum As Long
Dim mapNum As Long
Dim Damage As Long
>!     Damage = 0
>!     ' Can we attack the npc?
    If CanPlayerAttackNpc(Index, mapNpcNum) Then

        mapNum = GetPlayerMap(Index)
        npcNum = MapNpc(mapNum).NPC(mapNpcNum).Num

        ' check if NPC can avoid the attack
        If CanNpcDodge(npcNum) Then
            SendActionMsg mapNum, "Dodge!", Pink, 1, (MapNpc(mapNum).NPC(mapNpcNum).x * 32), (MapNpc(mapNum).NPC(mapNpcNum).y * 32)
            Exit Sub
        End If
        If CanNpcParry(npcNum) Then
            SendActionMsg mapNum, "Parry!", Pink, 1, (MapNpc(mapNum).NPC(mapNpcNum).x * 32), (MapNpc(mapNum).NPC(mapNpcNum).y * 32)
            Exit Sub
        End If
>!         ' Get the damage we can do
        Damage = GetPlayerDamage(Index)

        ' if the npc blocks, take away the block amount
        blockAmount = CanNpcBlock(mapNpcNum)
        Damage = Damage - blockAmount

        ' take away armour
        Damage = Damage - RAND(1, (NPC(npcNum).Stat(Stats.Agility) * 2))
        ' randomise from 1 to max hit
        Damage = RAND(1, Damage)

        ' * 1.5 if it's a crit!
        If CanPlayerCrit(Index) Then
            Damage = Damage * 1.5
            SendActionMsg mapNum, "Critical!", BrightCyan, 1, (GetPlayerX(Index) * 32), (GetPlayerY(Index) * 32)
        End If

        If Damage > 0 Then
            Call PlayerAttackNpc(Index, mapNpcNum, Damage)
        Else
            Call PlayerMsg(Index, "Your attack does nothing.", BrightRed)
        End If
    End If
End Sub
>! Public Function CanPlayerAttackNpc(ByVal attacker As Long, ByVal mapNpcNum As Long, Optional ByVal IsSpell As Boolean = False) As Boolean
    Dim mapNum As Long
    Dim npcNum As Long
    Dim NpcX As Long
    Dim NpcY As Long
    Dim attackspeed As Long
>!     ' Check for subscript out of range
    If IsPlaying(attacker) = False Or mapNpcNum <= 0 Or mapNpcNum > MAX_MAP_NPCS Then
        Exit Function
    End If
>!     ' Check for subscript out of range
    If MapNpc(GetPlayerMap(attacker)).NPC(mapNpcNum).Num <= 0 Then
        Exit Function
    End If
>!     mapNum = GetPlayerMap(attacker)
    npcNum = MapNpc(mapNum).NPC(mapNpcNum).Num

    ' Make sure the npc isn't already dead
    If MapNpc(mapNum).NPC(mapNpcNum).Vital(Vitals.HP) <= 0 Then
        If NPC(MapNpc(mapNum).NPC(mapNpcNum).Num).Behaviour <> NPC_BEHAVIOUR_FRIENDLY Then
            If NPC(MapNpc(mapNum).NPC(mapNpcNum).Num).Behaviour <> NPC_BEHAVIOUR_SHOPKEEPER Then
                Exit Function
            End If
        End If
    End If
>!     ' Make sure they are on the same map
    If IsPlaying(attacker) Then

        ' exit out early
        If IsSpell Then
            If npcNum > 0 Then
                If NPC(npcNum).Behaviour <> NPC_BEHAVIOUR_FRIENDLY And NPC(npcNum).Behaviour <> NPC_BEHAVIOUR_SHOPKEEPER Then
                    TempPlayer(attacker).targetType = TARGET_TYPE_NPC
                    TempPlayer(attacker).target = mapNpcNum
                    SendTarget attacker

                    CanPlayerAttackNpc = True
                    Exit Function
                End If
            End If
        End If
>!         ' attack speed from weapon
        If GetPlayerEquipment(attacker, Weapon) > 0 Then
            attackspeed = Item(GetPlayerEquipment(attacker, Weapon)).Speed
        Else
            attackspeed = 1000
        End If
>!         If npcNum > 0 And GetTickCount > TempPlayer(attacker).AttackTimer + attackspeed Then
            ' Check if at same coordinates
            Select Case GetPlayerDir(attacker)
                Case DIR_LEFT
                    NpcX = MapNpc(mapNum).NPC(mapNpcNum).x + 1
                    NpcY = MapNpc(mapNum).NPC(mapNpcNum).y
                Case DIR_RIGHT
                    NpcX = MapNpc(mapNum).NPC(mapNpcNum).x - 1
                    NpcY = MapNpc(mapNum).NPC(mapNpcNum).y
            End Select
>!             If NpcX = GetPlayerX(attacker) Then
                If NpcY = GetPlayerY(attacker) Then
                If NPC(npcNum).Behaviour = NPC_BEHAVIOUR_FRIENDLY Then
                            If NPC(npcNum).Convo = True Then
                                InitChat attacker, mapNum, mapNpcNum
                            End If
                            Exit Function
                        End If
                    If NPC(npcNum).Behaviour <> NPC_BEHAVIOUR_FRIENDLY And NPC(npcNum).Behaviour <> NPC_BEHAVIOUR_SHOPKEEPER Then

                        TempPlayer(attacker).targetType = TARGET_TYPE_NPC
                        TempPlayer(attacker).target = mapNpcNum
                        SendTarget attacker
                        CanPlayerAttackNpc = True
                    Else
                                            If NPC(npcNum).Behaviour = NPC_BEHAVIOUR_FRIENDLY Then
                            Call CheckTasks(attacker, QUEST_TYPE_GOTALK, npcNum)
                            Call CheckTasks(attacker, QUEST_TYPE_GOGIVE, npcNum)
                            Call CheckTasks(attacker, QUEST_TYPE_GOGET, npcNum)

                            If NPC(npcNum).Quest = YES Then
                                If CanStartQuest(attacker, NPC(npcNum).QuestNum) Then
                                    'if can start show the request message (chat1)
                                    QuestMessage attacker, NPC(npcNum).QuestNum, Trim$(Quest(NPC(npcNum).QuestNum).Chat(1)), NPC(npcNum).QuestNum
                                    Exit Function
                                End If
                                If QuestInProgress(attacker, NPC(npcNum).QuestNum) Then
                                    'if the quest is in progress show the meanwhile message (chat2)
                                    PlayerMsg attacker, Trim$(NPC(npcNum).Name) + ": " + Trim$(Quest(NPC(npcNum).QuestNum).Chat(2)), BrightGreen
                                    'QuestMessage attacker, NPC(npcNum).QuestNum, Trim$(Quest(NPC(npcNum).QuestNum).Chat(2)), 0
                                    Exit Function
                                End If
                            End If
                        End If
                        If Len(Trim$(NPC(npcNum).AttackSay)) > 0 Then
                            PlayerMsg attacker, Trim$(NPC(npcNum).Name) & ": " & Trim$(NPC(npcNum).AttackSay), White
                        End If
                    End If
                End If
            End If
        End If
    End If
>! End Function
>! Public Sub PlayerAttackNpc(ByVal attacker As Long, ByVal mapNpcNum As Long, ByVal Damage As Long, Optional ByVal spellnum As Long, Optional ByVal overTime As Boolean = False)
    Dim Name As String
    Dim exp As Long
    Dim n As Long
    Dim i As Long
    Dim STR As Long
    Dim Def As Long
    Dim mapNum As Long
    Dim npcNum As Long
    Dim Buffer As clsBuffer
>!     ' Check for subscript out of range
    If IsPlaying(attacker) = False Or mapNpcNum <= 0 Or mapNpcNum > MAX_MAP_NPCS Or Damage < 0 Then
        Exit Sub
    End If
>!     mapNum = GetPlayerMap(attacker)
    npcNum = MapNpc(mapNum).NPC(mapNpcNum).Num
    Name = Trim$(NPC(npcNum).Name)

    ' Check for weapon
    n = 0
>!     If GetPlayerEquipment(attacker, Weapon) > 0 Then
        n = GetPlayerEquipment(attacker, Weapon)
    End If

    ' set the regen timer
    TempPlayer(attacker).stopRegen = True
    TempPlayer(attacker).stopRegenTimer = GetTickCount
>!     If Damage >= MapNpc(mapNum).NPC(mapNpcNum).Vital(Vitals.HP) Then

        SendActionMsg GetPlayerMap(attacker), "-" & MapNpc(mapNum).NPC(mapNpcNum).Vital(Vitals.HP), BrightRed, 1, (MapNpc(mapNum).NPC(mapNpcNum).x * 32), (MapNpc(mapNum).NPC(mapNpcNum).y * 32)
        SendBlood GetPlayerMap(attacker), MapNpc(mapNum).NPC(mapNpcNum).x, MapNpc(mapNum).NPC(mapNpcNum).y

        ' send the sound
        If spellnum > 0 Then SendMapSound attacker, MapNpc(mapNum).NPC(mapNpcNum).x, MapNpc(mapNum).NPC(mapNpcNum).y, SoundEntity.seSpell, spellnum

        ' send animation
        If n > 0 Then
            If Not overTime Then
                If spellnum = 0 Then Call SendAnimation(mapNum, Item(GetPlayerEquipment(attacker, Weapon)).Animation, MapNpc(mapNum).NPC(mapNpcNum).x, MapNpc(mapNum).NPC(mapNpcNum).y)
            End If
        End If
>!         ' Calculate exp to give attacker
        exp = NPC(npcNum).exp
>!         ' Make sure we dont get less then 0
        If exp < 0 Then
            exp = 1
        End If
>!         ' in party?
        If TempPlayer(attacker).inParty > 0 Then
            ' pass through party sharing function
            Party_ShareExp TempPlayer(attacker).inParty, exp, attacker
        Else
            ' no party - keep exp for self
            GivePlayerEXP attacker, exp
        End If

        'Drop the goods if they get it
        n = Int(Rnd * NPC(npcNum).DropChance) + 1
>!         If n = 1 Then
            Call SpawnItem(NPC(npcNum).DropItem, NPC(npcNum).DropItemValue, mapNum, MapNpc(mapNum).NPC(mapNpcNum).x, MapNpc(mapNum).NPC(mapNpcNum).y)
        End If
>!         ' Now set HP to 0 so we know to actually kill them in the server loop (this prevents subscript out of range)
        MapNpc(mapNum).NPC(mapNpcNum).Num = 0
        MapNpc(mapNum).NPC(mapNpcNum).SpawnWait = GetTickCount
        MapNpc(mapNum).NPC(mapNpcNum).Vital(Vitals.HP) = 0

        ' clear DoTs and HoTs
        For i = 1 To MAX_DOTS
            With MapNpc(mapNum).NPC(mapNpcNum).DoT(i)
                .Spell = 0
                .Timer = 0
                .Caster = 0
                .StartTime = 0
                .Used = False
            End With

            With MapNpc(mapNum).NPC(mapNpcNum).HoT(i)
                .Spell = 0
                .Timer = 0
                .Caster = 0
                .StartTime = 0
                .Used = False
            End With
        Next

        Call CheckTasks(attacker, QUEST_TYPE_GOSLAY, npcNum)

        ' send death to the map
        Set Buffer = New clsBuffer
        Buffer.WriteLong SNpcDead
        Buffer.WriteLong mapNpcNum
        SendDataToMap mapNum, Buffer.ToArray()
        Set Buffer = Nothing

        'Loop through entire map and purge NPC from targets
        For i = 1 To Player_HighIndex
            If IsPlaying(i) And IsConnected(i) Then
                If Player(i).Map = mapNum Then
                    If TempPlayer(i).targetType = TARGET_TYPE_NPC Then
                        If TempPlayer(i).target = mapNpcNum Then
                            TempPlayer(i).target = 0
                            TempPlayer(i).targetType = TARGET_TYPE_NONE
                            SendTarget i
                        End If
                    End If
                End If
            End If
        Next
    Else
        ' NPC not dead, just do the damage
        MapNpc(mapNum).NPC(mapNpcNum).Vital(Vitals.HP) = MapNpc(mapNum).NPC(mapNpcNum).Vital(Vitals.HP) - Damage
>!         ' Check for a weapon and say damage
        SendActionMsg mapNum, "-" & Damage, BrightRed, 1, (MapNpc(mapNum).NPC(mapNpcNum).x * 32), (MapNpc(mapNum).NPC(mapNpcNum).y * 32)
        SendBlood GetPlayerMap(attacker), MapNpc(mapNum).NPC(mapNpcNum).x, MapNpc(mapNum).NPC(mapNpcNum).y

        ' send the sound
        If spellnum > 0 Then SendMapSound attacker, MapNpc(mapNum).NPC(mapNpcNum).x, MapNpc(mapNum).NPC(mapNpcNum).y, SoundEntity.seSpell, spellnum

        ' send animation
        If n > 0 Then
            If Not overTime Then
                If spellnum = 0 Then Call SendAnimation(mapNum, Item(GetPlayerEquipment(attacker, Weapon)).Animation, 0, 0, TARGET_TYPE_NPC, mapNpcNum)
            End If
        End If
>!         ' Set the NPC target to the player
        MapNpc(mapNum).NPC(mapNpcNum).targetType = 1 ' player
        MapNpc(mapNum).NPC(mapNpcNum).target = attacker
>!         ' Now check for guard ai and if so have all onmap guards come after'm
        If NPC(MapNpc(mapNum).NPC(mapNpcNum).Num).Behaviour = NPC_BEHAVIOUR_GUARD Then
            For i = 1 To MAX_MAP_NPCS
                If MapNpc(mapNum).NPC(i).Num = MapNpc(mapNum).NPC(mapNpcNum).Num Then
                    MapNpc(mapNum).NPC(i).target = attacker
                    MapNpc(mapNum).NPC(i).targetType = 1 ' player
                End If
            Next
        End If

        ' set the regen timer
        MapNpc(mapNum).NPC(mapNpcNum).stopRegen = True
        MapNpc(mapNum).NPC(mapNpcNum).stopRegenTimer = GetTickCount

        ' if stunning spell, stun the npc
        If spellnum > 0 Then
            If Spell(spellnum).StunDuration > 0 Then StunNPC mapNpcNum, mapNum, spellnum
            ' DoT
            If Spell(spellnum).Duration > 0 Then
                AddDoT_Npc mapNum, mapNpcNum, spellnum, attacker
            End If
        End If

        SendMapNpcVitals mapNum, mapNpcNum
    End If
>!     If spellnum = 0 Then
        ' Reset attack timer
        TempPlayer(attacker).AttackTimer = GetTickCount
    End If
End Sub
>! ' ###################################
' ##      NPC Attacking Player    ##
' ###################################
>! Public Sub TryNpcAttackPlayer(ByVal mapNpcNum As Long, ByVal Index As Long)
Dim mapNum As Long, npcNum As Long, blockAmount As Long, Damage As Long
>!     ' Can the npc attack the player?
    If CanNpcAttackPlayer(mapNpcNum, Index) Then
        mapNum = GetPlayerMap(Index)
        npcNum = MapNpc(mapNum).NPC(mapNpcNum).Num

        ' check if PLAYER can avoid the attack
        If CanPlayerDodge(Index) Then
            SendActionMsg mapNum, "Dodge!", Pink, 1, (Player(Index).x * 32), (Player(Index).y * 32)
            Exit Sub
        End If
        If CanPlayerParry(Index) Then
            SendActionMsg mapNum, "Parry!", Pink, 1, (Player(Index).x * 32), (Player(Index).y * 32)
            Exit Sub
        End If
>!         ' Get the damage we can do
        Damage = GetNpcDamage(npcNum)

        ' if the player blocks, take away the block amount
        blockAmount = CanPlayerBlock(Index)
        Damage = Damage - blockAmount

        ' take away armour
        Damage = Damage - RAND(1, (GetPlayerStat(Index, Agility) * 2))

        ' randomise for up to 10% lower than max hit
        Damage = RAND(1, Damage)

        ' * 1.5 if crit hit
        If CanNpcCrit(Index) Then
            Damage = Damage * 1.5
            SendActionMsg mapNum, "Critical!", BrightCyan, 1, (MapNpc(mapNum).NPC(mapNpcNum).x * 32), (MapNpc(mapNum).NPC(mapNpcNum).y * 32)
        End If

        Damage = Damage - GetPlayerDef(Index)
>!         If Damage > 0 Then
            Call NpcAttackPlayer(mapNpcNum, Index, Damage)
        End If
    End If
End Sub
>! Function CanNpcAttackPlayer(ByVal mapNpcNum As Long, ByVal Index As Long) As Boolean
    Dim mapNum As Long
    Dim npcNum As Long
>!     ' Check for subscript out of range
    If mapNpcNum <= 0 Or mapNpcNum > MAX_MAP_NPCS Or Not IsPlaying(Index) Then
        Exit Function
    End If
>!     ' Check for subscript out of range
    If MapNpc(GetPlayerMap(Index)).NPC(mapNpcNum).Num <= 0 Then
        Exit Function
    End If
>!     mapNum = GetPlayerMap(Index)
    npcNum = MapNpc(mapNum).NPC(mapNpcNum).Num
>!     ' Make sure the npc isn't already dead
    If MapNpc(mapNum).NPC(mapNpcNum).Vital(Vitals.HP) <= 0 Then
        Exit Function
    End If
>!     ' Make sure npcs dont attack more then once a second
    If GetTickCount < MapNpc(mapNum).NPC(mapNpcNum).AttackTimer + 1000 Then
        Exit Function
    End If
>!     ' Make sure we dont attack the player if they are switching maps
    If TempPlayer(Index).GettingMap = YES Then
        Exit Function
    End If
>!     MapNpc(mapNum).NPC(mapNpcNum).AttackTimer = GetTickCount
>!     ' Make sure they are on the same map
    If IsPlaying(Index) Then
        If npcNum > 0 Then
>!             ' Check if at same coordinates
            If (GetPlayerY(Index) + 1 = MapNpc(mapNum).NPC(mapNpcNum).y) And (GetPlayerX(Index) = MapNpc(mapNum).NPC(mapNpcNum).x) Then
                CanNpcAttackPlayer = True
            Else
                If (GetPlayerY(Index) - 1 = MapNpc(mapNum).NPC(mapNpcNum).y) And (GetPlayerX(Index) = MapNpc(mapNum).NPC(mapNpcNum).x) Then
                    CanNpcAttackPlayer = True
                Else
                    If (GetPlayerY(Index) = MapNpc(mapNum).NPC(mapNpcNum).y) And (GetPlayerX(Index) + 1 = MapNpc(mapNum).NPC(mapNpcNum).x) Then
                        CanNpcAttackPlayer = True
                    Else
                        If (GetPlayerY(Index) = MapNpc(mapNum).NPC(mapNpcNum).y) And (GetPlayerX(Index) - 1 = MapNpc(mapNum).NPC(mapNpcNum).x) Then
                            CanNpcAttackPlayer = True
                        End If
                    End If
                End If
            End If
        End If
    End If
End Function
>! Sub NpcAttackPlayer(ByVal mapNpcNum As Long, ByVal victim As Long, ByVal Damage As Long)
    Dim Name As String
    Dim exp As Long
    Dim mapNum As Long
    Dim i As Long
    Dim Buffer As clsBuffer
>!     ' Check for subscript out of range
    If mapNpcNum <= 0 Or mapNpcNum > MAX_MAP_NPCS Or IsPlaying(victim) = False Then
        Exit Sub
    End If
>!     ' Check for subscript out of range
    If MapNpc(GetPlayerMap(victim)).NPC(mapNpcNum).Num <= 0 Then
        Exit Sub
    End If
>!     mapNum = GetPlayerMap(victim)
    Name = Trim$(NPC(MapNpc(mapNum).NPC(mapNpcNum).Num).Name)

    ' Send this packet so they can see the npc attacking
    Set Buffer = New clsBuffer
    Buffer.WriteLong SNpcAttack
    Buffer.WriteLong mapNpcNum
    SendDataToMap mapNum, Buffer.ToArray()
    Set Buffer = Nothing

    If Damage <= 0 Then
        Exit Sub
    End If

    ' set the regen timer
    MapNpc(mapNum).NPC(mapNpcNum).stopRegen = True
    MapNpc(mapNum).NPC(mapNpcNum).stopRegenTimer = GetTickCount
>!     If Damage >= GetPlayerVital(victim, Vitals.HP) Then
        ' Say damage
        SendActionMsg GetPlayerMap(victim), "-" & GetPlayerVital(victim, Vitals.HP), BrightRed, 1, (GetPlayerX(victim) * 32), (GetPlayerY(victim) * 32)

        ' send the sound
        SendMapSound victim, GetPlayerX(victim), GetPlayerY(victim), SoundEntity.seNpc, MapNpc(mapNum).NPC(mapNpcNum).Num

        ' kill player
        KillPlayer victim

        ' Player is dead
        Call GlobalMsg(GetPlayerName(victim) & " has been killed by " & Name, BrightRed)
>!         ' Set NPC target to 0
        MapNpc(mapNum).NPC(mapNpcNum).target = 0
        MapNpc(mapNum).NPC(mapNpcNum).targetType = 0
    Else
        ' Player not dead, just do the damage
        Call SetPlayerVital(victim, Vitals.HP, GetPlayerVital(victim, Vitals.HP) - Damage)
        Call SendVital(victim, Vitals.HP)
        Call SendAnimation(mapNum, NPC(MapNpc(GetPlayerMap(victim)).NPC(mapNpcNum).Num).Animation, 0, 0, TARGET_TYPE_PLAYER, victim)

        ' send vitals to party if in one
        If TempPlayer(victim).inParty > 0 Then SendPartyVitals TempPlayer(victim).inParty, victim

        ' send the sound
        SendMapSound victim, GetPlayerX(victim), GetPlayerY(victim), SoundEntity.seNpc, MapNpc(mapNum).NPC(mapNpcNum).Num

        ' Say damage
        SendActionMsg GetPlayerMap(victim), "-" & Damage, BrightRed, 1, (GetPlayerX(victim) * 32), (GetPlayerY(victim) * 32)
        SendBlood GetPlayerMap(victim), GetPlayerX(victim), GetPlayerY(victim)

        ' set the regen timer
        TempPlayer(victim).stopRegen = True
        TempPlayer(victim).stopRegenTimer = GetTickCount
    End If
>! End Sub
>! ' ###################################
' ##    Player Attacking Player    ##
' ###################################
>! Public Sub TryPlayerAttackPlayer(ByVal attacker As Long, ByVal victim As Long)
Dim blockAmount As Long
Dim npcNum As Long
Dim mapNum As Long
Dim Damage As Long
>!     Damage = 0
>!     ' Can we attack the npc?
    If CanPlayerAttackPlayer(attacker, victim) Then

        mapNum = GetPlayerMap(attacker)

        ' check if NPC can avoid the attack
        If CanPlayerDodge(victim) Then
            SendActionMsg mapNum, "Dodge!", Pink, 1, (GetPlayerX(victim) * 32), (GetPlayerY(victim) * 32)
            Exit Sub
        End If
        If CanPlayerParry(victim) Then
            SendActionMsg mapNum, "Parry!", Pink, 1, (GetPlayerX(victim) * 32), (GetPlayerY(victim) * 32)
            Exit Sub
        End If
>!         ' Get the damage we can do
        Damage = GetPlayerDamage(attacker)

        ' if the npc blocks, take away the block amount
        blockAmount = CanPlayerBlock(victim)
        Damage = Damage - blockAmount

        ' take away armour
        Damage = Damage - RAND(1, (GetPlayerStat(victim, Agility) * 2))

        ' randomise for up to 10% lower than max hit
        Damage = RAND(1, Damage)

        ' * 1.5 if can crit
        If CanPlayerCrit(attacker) Then
            Damage = Damage * 1.5
            SendActionMsg mapNum, "Critical!", BrightCyan, 1, (GetPlayerX(attacker) * 32), (GetPlayerY(attacker) * 32)
        End If

        Damage = Damage - GetPlayerDef(victim)
>!         If Damage > 0 Then
            Call PlayerAttackPlayer(attacker, victim, Damage)
        Else
            Call PlayerMsg(attacker, "Your attack does nothing.", BrightRed)
        End If
    End If
End Sub
>! Function CanPlayerAttackPlayer(ByVal attacker As Long, ByVal victim As Long, Optional ByVal IsSpell As Boolean = False) As Boolean
>!     If Not IsSpell Then
        ' Check attack timer
        If GetPlayerEquipment(attacker, Weapon) > 0 Then
            If GetTickCount < TempPlayer(attacker).AttackTimer + Item(GetPlayerEquipment(attacker, Weapon)).Speed Then Exit Function
        Else
            If GetTickCount < TempPlayer(attacker).AttackTimer + 1000 Then Exit Function
        End If
    End If
>!     ' Check for subscript out of range
    If Not IsPlaying(victim) Then Exit Function
>!     ' Make sure they are on the same map
    If Not GetPlayerMap(attacker) = GetPlayerMap(victim) Then Exit Function
>!     ' Make sure we dont attack the player if they are switching maps
    If TempPlayer(victim).GettingMap = YES Then Exit Function
>!     If Not IsSpell Then
        ' Check if at same coordinates
        Select Case GetPlayerDir(attacker)
            Case DIR_LEFT
                If Not ((GetPlayerY(victim) = GetPlayerY(attacker)) And (GetPlayerX(victim) + 1 = GetPlayerX(attacker))) Then Exit Function
            Case DIR_RIGHT
                If Not ((GetPlayerY(victim) = GetPlayerY(attacker)) And (GetPlayerX(victim) - 1 = GetPlayerX(attacker))) Then Exit Function
            Case Else
                Exit Function
        End Select
    End If
>!     ' Check if map is attackable
    If Not Map(GetPlayerMap(attacker)).Moral = MAP_MORAL_NONE Then
        If GetPlayerPK(victim) = NO Then
            Call PlayerMsg(attacker, "This is a safe zone!", BrightRed)
            Exit Function
        End If
    End If
>!     ' Make sure they have more then 0 hp
    If GetPlayerVital(victim, Vitals.HP) <= 0 Then Exit Function
>!     ' Check to make sure that they dont have access
    If GetPlayerAccess(attacker) > ADMIN_MONITOR Then
        Call PlayerMsg(attacker, "Admins cannot attack other players.", BrightBlue)
        Exit Function
    End If
>!     ' Check to make sure the victim isn't an admin
    If GetPlayerAccess(victim) > ADMIN_MONITOR Then
        Call PlayerMsg(attacker, "You cannot attack " & GetPlayerName(victim) & "!", BrightRed)
        Exit Function
    End If
>!     ' Make sure attacker is high enough level
    If GetPlayerLevel(attacker) < 10 Then
        Call PlayerMsg(attacker, "You are below level 10, you cannot attack another player yet!", BrightRed)
        Exit Function
    End If
>!     ' Make sure victim is high enough level
    If GetPlayerLevel(victim) < 10 Then
        Call PlayerMsg(attacker, GetPlayerName(victim) & " is below level 10, you cannot attack this player yet!", BrightRed)
        Exit Function
    End If

    TempPlayer(attacker).targetType = TARGET_TYPE_PLAYER
TempPlayer(attacker).target = victim
SendTarget attacker
>!     CanPlayerAttackPlayer = True
End Function
>! Sub PlayerAttackPlayer(ByVal attacker As Long, ByVal victim As Long, ByVal Damage As Long, Optional ByVal spellnum As Long = 0)
    Dim exp As Long
    Dim n As Long
    Dim i As Long
    Dim Buffer As clsBuffer
>!     ' Check for subscript out of range
    If IsPlaying(attacker) = False Or IsPlaying(victim) = False Or Damage < 0 Then
        Exit Sub
    End If
>!     ' Check for weapon
    n = 0
>!     If GetPlayerEquipment(attacker, Weapon) > 0 Then
        n = GetPlayerEquipment(attacker, Weapon)
    End If

    ' set the regen timer
    TempPlayer(attacker).stopRegen = True
    TempPlayer(attacker).stopRegenTimer = GetTickCount
>!     If Damage >= GetPlayerVital(victim, Vitals.HP) Then
        SendActionMsg GetPlayerMap(victim), "-" & GetPlayerVital(victim, Vitals.HP), BrightRed, 1, (GetPlayerX(victim) * 32), (GetPlayerY(victim) * 32)

        ' send the sound
        If spellnum > 0 Then SendMapSound victim, GetPlayerX(victim), GetPlayerY(victim), SoundEntity.seSpell, spellnum

        ' Player is dead
        Call GlobalMsg(GetPlayerName(victim) & " has been killed by " & GetPlayerName(attacker), BrightRed)
        ' Calculate exp to give attacker
        exp = (GetPlayerExp(victim) \ 10)
>!         ' Make sure we dont get less then 0
        If exp < 0 Then
            exp = 0
        End If
>!         If exp = 0 Then
            Call PlayerMsg(victim, "You lost no exp.", BrightRed)
            Call PlayerMsg(attacker, "You received no exp.", BrightBlue)
        Else
            Call SetPlayerExp(victim, GetPlayerExp(victim) - exp)
            SendEXP victim
            Call PlayerMsg(victim, "You lost " & exp & " exp.", BrightRed)

            ' check if we're in a party
            If TempPlayer(attacker).inParty > 0 Then
                ' pass through party exp share function
                Party_ShareExp TempPlayer(attacker).inParty, exp, attacker
            Else
                ' not in party, get exp for self
                GivePlayerEXP attacker, exp
            End If
        End If

        ' purge target info of anyone who targetted dead guy
        For i = 1 To Player_HighIndex
            If IsPlaying(i) And IsConnected(i) Then
                If Player(i).Map = GetPlayerMap(attacker) Then
                    If TempPlayer(i).target = TARGET_TYPE_PLAYER Then
                        If TempPlayer(i).target = victim Then
                            TempPlayer(i).target = 0
                            TempPlayer(i).targetType = TARGET_TYPE_NONE
                            SendTarget i
                        End If
                    End If
                End If
            End If
        Next
>!         If GetPlayerPK(victim) = NO Then
            If GetPlayerPK(attacker) = NO Then
                Call SetPlayerPK(attacker, YES)
                Call SendPlayerData(attacker)
                Call GlobalMsg(GetPlayerName(attacker) & " has been deemed a Player Killer!!!", BrightRed)
            End If
>!         Else
            Call GlobalMsg(GetPlayerName(victim) & " has paid the price for being a Player Killer!!!", BrightRed)
        End If

        Call CheckTasks(attacker, QUEST_TYPE_GOKILL, victim)
>!         Call OnDeath(victim)
    Else
        ' Player not dead, just do the damage
        Call SetPlayerVital(victim, Vitals.HP, GetPlayerVital(victim, Vitals.HP) - Damage)
        Call SendVital(victim, Vitals.HP)

        ' send vitals to party if in one
        If TempPlayer(victim).inParty > 0 Then SendPartyVitals TempPlayer(victim).inParty, victim

        ' send the sound
        If spellnum > 0 Then SendMapSound victim, GetPlayerX(victim), GetPlayerY(victim), SoundEntity.seSpell, spellnum

        SendActionMsg GetPlayerMap(victim), "-" & Damage, BrightRed, 1, (GetPlayerX(victim) * 32), (GetPlayerY(victim) * 32)
        SendBlood GetPlayerMap(victim), GetPlayerX(victim), GetPlayerY(victim)

        ' set the regen timer
        TempPlayer(victim).stopRegen = True
        TempPlayer(victim).stopRegenTimer = GetTickCount

        'if a stunning spell, stun the player
        If spellnum > 0 Then
            If Spell(spellnum).StunDuration > 0 Then StunPlayer victim, spellnum
            ' DoT
            If Spell(spellnum).Duration > 0 Then
                AddDoT_Player victim, spellnum, attacker
            End If
        End If
    End If
>!     ' Reset attack timer
    TempPlayer(attacker).AttackTimer = GetTickCount
End Sub
>! ' ############
' ## Spells ##
' ############
>! Public Sub BufferSpell(ByVal Index As Long, ByVal spellslot As Long)
    Dim spellnum As Long
    Dim MPCost As Long
    Dim LevelReq As Long
    Dim mapNum As Long
    Dim SpellCastType As Long
    Dim ClassReq As Long
    Dim AccessReq As Long
    Dim Range As Long
    Dim HasBuffered As Boolean

    Dim targetType As Byte
    Dim target As Long

    ' Prevent subscript out of range
    If spellslot <= 0 Or spellslot > MAX_PLAYER_SPELLS Then Exit Sub

    spellnum = GetPlayerSpell(Index, spellslot)
    mapNum = GetPlayerMap(Index)

    If spellnum <= 0 Or spellnum > MAX_SPELLS Then Exit Sub

    ' Make sure player has the spell
    If Not HasSpell(Index, spellnum) Then Exit Sub

    ' see if cooldown has finished
    If TempPlayer(Index).SpellCD(spellslot) > GetTickCount Then
        PlayerMsg Index, "Spell hasn't cooled down yet!", BrightRed
        Exit Sub
    End If
>!     MPCost = Spell(spellnum).MPCost
>!     ' Check if they have enough MP
    If GetPlayerVital(Index, Vitals.MP) < MPCost Then
        Call PlayerMsg(Index, "Not enough mana!", BrightRed)
        Exit Sub
    End If

    LevelReq = Spell(spellnum).LevelReq
>!     ' Make sure they are the right level
    If LevelReq > GetPlayerLevel(Index) Then
        Call PlayerMsg(Index, "You must be level " & LevelReq & " to cast this spell.", BrightRed)
        Exit Sub
    End If

    AccessReq = Spell(spellnum).AccessReq

    ' make sure they have the right access
    If AccessReq > GetPlayerAccess(Index) Then
        Call PlayerMsg(Index, "You must be an administrator to cast this spell.", BrightRed)
        Exit Sub
    End If

    ClassReq = Spell(spellnum).ClassReq

    ' make sure the classreq > 0
    If ClassReq > 0 Then ' 0 = no req
        If ClassReq <> GetPlayerClass(Index) Then
            Call PlayerMsg(Index, "Only " & CheckGrammar(Trim$(Class(ClassReq).Name)) & " can use this spell.", BrightRed)
            Exit Sub
        End If
    End If

    ' find out what kind of spell it is! self cast, target or AOE
    If Spell(spellnum).Range > 0 Then
        ' ranged attack, single target or aoe?
        If Not Spell(spellnum).IsAoE Then
            SpellCastType = 2 ' targetted
        Else
            SpellCastType = 3 ' targetted aoe
        End If
    Else
        If Not Spell(spellnum).IsAoE Then
            SpellCastType = 0 ' self-cast
Link to comment
Share on other sites

@Whack.. I see where the problem lies.. there is some redundancy in the code. In modCombat > Public Function CanPlayerAttackNpc… replace the entire thing with this:

```
Public Function CanPlayerAttackNpc(ByVal attacker As Long, ByVal mapNpcNum As Long, Optional ByVal IsSpell As Boolean = False) As Boolean
    Dim mapNum As Long
    Dim npcNum As Long
    Dim NpcX As Long
    Dim NpcY As Long
    Dim attackspeed As Long

    ' Check for subscript out of range
    If IsPlaying(attacker) = False Or mapNpcNum <= 0 Or mapNpcNum > MAX_MAP_NPCS Then
        Exit Function
    End If

    ' Check for subscript out of range
    If MapNpc(GetPlayerMap(attacker)).NPC(mapNpcNum).Num <= 0 Then
        Exit Function
    End If

    mapNum = GetPlayerMap(attacker)
    npcNum = MapNpc(mapNum).NPC(mapNpcNum).Num

    ' Make sure the npc isn't already dead
    If MapNpc(mapNum).NPC(mapNpcNum).Vital(Vitals.HP) <= 0 Then
        If NPC(MapNpc(mapNum).NPC(mapNpcNum).Num).Behaviour <> NPC_BEHAVIOUR_FRIENDLY Then
            If NPC(MapNpc(mapNum).NPC(mapNpcNum).Num).Behaviour <> NPC_BEHAVIOUR_SHOPKEEPER Then
                Exit Function
            End If
        End If
    End If

    ' Make sure they are on the same map
    If IsPlaying(attacker) Then

        ' exit out early
        If IsSpell Then
            If npcNum > 0 Then
                If NPC(npcNum).Behaviour <> NPC_BEHAVIOUR_FRIENDLY And NPC(npcNum).Behaviour <> NPC_BEHAVIOUR_SHOPKEEPER Then
                    CanPlayerAttackNpc = True
                    Exit Function
                End If
            End If
        End If

        ' attack speed from weapon
        If GetPlayerEquipment(attacker, Weapon) > 0 Then
            attackspeed = Item(GetPlayerEquipment(attacker, Weapon)).Speed
        Else
            attackspeed = 1000
        End If

        If npcNum > 0 And GetTickCount > TempPlayer(attacker).AttackTimer + attackspeed Then
            ' Check if at same coordinates
            Select Case GetPlayerDir(attacker)
                Case DIR_UP
                    NpcX = MapNpc(mapNum).NPC(mapNpcNum).x
                    NpcY = MapNpc(mapNum).NPC(mapNpcNum).y + 1
                Case DIR_DOWN
                    NpcX = MapNpc(mapNum).NPC(mapNpcNum).x
                    NpcY = MapNpc(mapNum).NPC(mapNpcNum).y - 1
                Case DIR_LEFT
                    NpcX = MapNpc(mapNum).NPC(mapNpcNum).x + 1
                    NpcY = MapNpc(mapNum).NPC(mapNpcNum).y
                Case DIR_RIGHT
                    NpcX = MapNpc(mapNum).NPC(mapNpcNum).x - 1
                    NpcY = MapNpc(mapNum).NPC(mapNpcNum).y
            End Select

            If NpcX = GetPlayerX(attacker) Then
                If NpcY = GetPlayerY(attacker) Then
                    If NPC(npcNum).Behaviour <> NPC_BEHAVIOUR_FRIENDLY And NPC(npcNum).Behaviour <> NPC_BEHAVIOUR_SHOPKEEPER Then
                        CanPlayerAttackNpc = True
                    Else
                        'ALATAR
                        If NPC(npcNum).Behaviour = NPC_BEHAVIOUR_FRIENDLY Then
                            Call CheckTasks(attacker, QUEST_TYPE_GOTALK, npcNum)
                            Call CheckTasks(attacker, QUEST_TYPE_GOGIVE, npcNum)
                            Call CheckTasks(attacker, QUEST_TYPE_GOGET, npcNum)

                            If NPC(npcNum).Quest = YES Then
                                If CanStartQuest(attacker, NPC(npcNum).QuestNum) Then
                                    'if can start show the request message (chat1)
                                    QuestMessage attacker, NPC(npcNum).QuestNum, Trim$(Quest(NPC(npcNum).QuestNum).Chat(1)), NPC(npcNum).QuestNum
                                    Exit Function
                                End If
                                If QuestInProgress(attacker, NPC(npcNum).QuestNum) Then
                                    'if the quest is in progress show the meanwhile message (chat2)
                                    PlayerMsg attacker, Trim$(NPC(npcNum).Name) + ": " + Trim$(Quest(NPC(npcNum).QuestNum).Chat(2)), BrightGreen
                                    'QuestMessage attacker, NPC(npcNum).QuestNum, Trim$(Quest(NPC(npcNum).QuestNum).Chat(2)), 0
                                    Exit Function
                                End If
                            End If

                        If NPC(npcNum).Quest = NO Then
                                If NPC(npcNum).Convo = False Then
                                  If Len(Trim$(NPC(npcNum).AttackSay)) > 0 Then
                                    Call SpeechWindow(attacker, Trim$(NPC(npcNum).AttackSay), npcNum)
                                  End If
                                Else
                                    InitChat attacker, mapNum, mapNpcNum
                                End If
                                Exit Function
                            End If
                        End If

                    End If
                End If
            End If
        End If
    End If

End Function
```
Replace the "Call Speechwindow" with```
PlayerMsg attacker, Trim$(NPC(npcNum).Name) + ": " + Trim$(Quest(NPC(npcNum).QuestNum).Chat(2)), BrightGreen
```
That should work..
Link to comment
Share on other sites

There seems to be a problem with multiple quests in the quest log. I don't know if theres a fix for it already somewhere in here, but when you have multiple quests in your log and you delete one, then try to delete the next, it says (Name of first quest deleted here) has been deleted! and the quest you tried to delete is still there.
Link to comment
Share on other sites

Can someone tell me how to raise the xp rewards to higher than 255… I thought raising the hscrollbar max value to a higher number alone would do it. Any help is appreciated.

Edit: Solved. I switched the scroll bar to a text input box.
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share


×
×
  • Create New...