EO [Any Version] Damage w/ DOT Fix

Hey there!

So, as far as I know, this bug exists in every single Eclipse Engine to date. (Besides my own of course, hehe)

The issue lies in the reading of damage while a DOT is active on an NPC. If you’re attacking while a DOT is active, the damage will not be read. I can’t quite remember why, as I made this fix quite a while ago, but it doesn’t haha.

I had previously released this fix for EVB and the IndieRising community exclusively because of the former management of this place pissed me off from time to time, but I’ll be posting it here now because of the change in ownership 😄

Before we dive into the fix, know that if there are any errors, it’s cause I’m pulling the fix straight out of my Engine. I’m trying to take out any extra stuff that I have that may cause errors, but I may miss something. Just know that I offer full support for any and all tutorials I release and if you find a bug, just post below and I’ll help you fix it 😄

Alright, this is all Server Sided:

First of all, add this to modCombat:

! ```
Public Sub PlayerAttackNpcDOT(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)

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

If Damage > 0 Then

! ’ 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

If Damage >= MapNpc(mapnum).NPC(MapNpcNum).Vital(Vitals.HP) Then

    ' 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, GetPlayerMap(attacker)
’ no party - keep exp for self
GivePlayerEXP attacker, exp
End If

    'Drop the goods if they get it
        For n = 1 To MAX_NPC_DROPS
        If NPC(NPCNum).DropItem(n) = 0 Then Exit For

        If Rnd <= NPC(NPCNum).DropChance(n) Then
        Call SpawnItem(NPC(NPCNum).DropItem(n), NPC(NPCNum).DropItemValue(n), 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
    UpdateMapBlock mapnum, MapNpc(mapnum).NPC(MapNpcNum).x, MapNpc(mapnum).NPC(MapNpcNum).y, False

    ' 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

    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
    ' NPC not dead, just do the damage
    MapNpc(mapnum).NPC(MapNpcNum).Vital(Vitals.HP) = MapNpc(mapnum).NPC(MapNpcNum).Vital(Vitals.HP) - Damage

! ’ 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
End If

    ' set the regen timer
    MapNpc(mapnum).NPC(MapNpcNum).stopRegen = True
    MapNpc(mapnum).NPC(MapNpcNum).stopRegenTimer = GetTickCount

    End If

    SendMapNpcVitals mapnum, MapNpcNum

End If
End Sub

! !   ! Now, in modCombat -> HandleDOT_Npc find this: !
PlayerAttackNpc .Caster, index, Vital, , True
! and replace it with this: !
PlayerAttackNpcDOT .Caster, index, Vital, , True
! ```
 And I’m fairly sure that’s it!
! Now to explain what this does:
! Instead of using the same function for damage as a normal attack, DoTs will now be calculated using a separate function. This allows for both types of damage to be read at the same time.
! Now, this should work, but if you encounter any bugs while adding this tutorial feel free to post below and I’ll help you out 😄
! ~SkywardRiver

UpdateMapBlock sub or fuction not found

UpdateMapBlock sub or fuction not found

I believe that’s EO 3.0 and up. Go ahead and delete that line 🙂

k thx and porps on your new game i beta tested skyward cant wait for your next game

Log in to reply