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

Showing Multiple Damage Blits at Once (Plus a Bug Fix!)


balliztik1
 Share

Recommended Posts

(Written in response to this topic: [annoying attack damage show](http://www.touchofdeathforums.com/smf/index.php/topic,46371.0))

After reading Zultar's request, I decided to undertake the task of having the client show more than one damage value. There's only a couple simple steps, all within the client source.

The first step is to make the current single variables into arrays. Open up modGlobal and locate these variables:

```
' Damage Variables
Public DmgDamage As Long
Public DmgTime As Long
Public NPCDmgDamage As Long
Public NPCDmgTime As Long
Public NPCWho As Long
```
```
Public ii As Long, iii As Long
```
Simply change them to arrays like so:

```
' Damage Variables
Public DmgDamage() As Long
Public DmgTime() As Long
Public NPCDmgDamage() As Long
Public NPCDmgTime() As Long
Public NPCWho() As Long
```
```
Public ii() As Long, iii() As Long
```

The second step is to give those arrays a range via ReDimming. Since most of the array ReDims happen in the "maxinfo" packet, I decided to throw the damage ReDims in there, too. There's many other places where you could put these, though. "maxinfo" is received when a player logs in, so I figured it was appropriate, but you can put it in the client's initialization, when the MainMenu is first loaded, etc. In modHandleData, you'll find some ReDims like this:

```
        ReDim Map(0 To MAX_MAPS) As MapRec
        ReDim Player(1 To MAX_PLAYERS) As PlayerRec
        ReDim Item(1 To MAX_ITEMS) As ItemRec
```
There will be a lot more of them. Just paste our ReDims around that area somewhere:

```
        ReDim ii(0 To 9) As Long
        ReDim iii(0 To 9) As Long
        ReDim DmgDamage(0 To 9) As Long
        ReDim DmgTime(0 To 9) As Long
        ReDim NPCDmgDamage(0 To 9) As Long
        ReDim NPCDmgTime(0 To 9) As Long
```
I have mine range from 0 to 9, to allow 10 damages at once. A damage is blitted for 2 seconds, so unless you have super-fast weapons, you won't need too many. 10 is more than enough, regularly.

You'll notice that NPCWho's ReDim is missing from that list. There's a purpose for that. NPCWho determines which Map NPC slot you're attacking. As such, when you switch maps, the damage blits will appear over an NPC of that slot on the new map, a slight bug in the engine. Might as well kill two birds with one stone and take down that bug while adding this. Find this in modHandleData:

```
    If (casestring = "checkformap") Then
```
Paste this in that block somewhere:

```
        ReDim NPCWho(0 To 9) As Long
```
This will clear the array when a map loads, assuring that improper blits are cleared.

Third, you'll have to change the handling of the "blitplayerdmg" and "blitnpcdmg" packets, still in modHandleData. When they arrive, they change the once singlular variables. You'll have to set them up to handle an array. I used a circular array method like Robin suggested. Change the packets to look like so:

```
    ' ::::::::::::::::::::::::
    ' :: Blit Player Damage ::
    ' ::::::::::::::::::::::::
    If casestring = "blitplayerdmg" Then

        For X = 9 To 1 Step -1
            iii(X) = iii(X - 1)
            DmgDamage(X) = DmgDamage(X - 1)
            NPCWho(X) = NPCWho(X - 1)
            DmgTime(X) = DmgTime(X - 1)
        Next

        DmgDamage(0) = Val(parse(1))
        NPCWho(0) = Val(parse(2))
        DmgTime(0) = GetTickCount
        iii(0) = 0
        Exit Sub
    End If

    ' :::::::::::::::::::::
    ' :: Blit NPC Damage ::
    ' :::::::::::::::::::::
    If casestring = "blitnpcdmg" Then

        For X = 9 To 1 Step -1
            ii(X) = ii(X - 1)
            NPCDmgDamage(X) = NPCDmgDamage(X - 1)
            NPCDmgTime(X) = NPCDmgTime(X - 1)
        Next

        NPCDmgDamage(0) = Val(parse(1))
        NPCDmgTime(0) = GetTickCount
        ii(0) = 0
        Exit Sub
    End If
```

The final step is to incorporate these variables into the actual blitting. In modGameLogic's GameLoop is where this happens. Just search for "' Draw NPC's damage on player". The following ~30 lines of code use our variables heavily. What I did is ran a For-loop, checking an I value of 0 to 9 and blitting each. As such, you have to add "(I)" to the end of each variable. I've got it all done up here, so you can just paste over the NPC and Player blitting with this:

```
                    ' Draw NPC's damage on player
                    If frmMirage.chkNpcDamage.Value = 1 Then
                        For I = 0 To 9
                            If frmMirage.chkPlayerName.Value = 0 Then
                                If GetTickCount < NPCDmgTime(I) + 2000 Then
                                    Call DrawText(TexthDC, (Int(Len(NPCDmgDamage(I))) / 2) * 3 + NewX + sx, NewY - 22 - ii(I) + sx, NPCDmgDamage(I), QBColor(BRIGHTRED))
                                End If
                            Else
                                If GetPlayerGuild(MyIndex) <> vbNullString Then
                                    If GetTickCount < NPCDmgTime(I) + 2000 Then
                                        Call DrawText(TexthDC, (Int(Len(NPCDmgDamage(I))) / 2) * 3 + NewX + sx, NewY - 42 - ii(I) + sx, NPCDmgDamage(I), QBColor(BRIGHTRED))
                                    End If
                                Else
                                    If GetTickCount < NPCDmgTime(I) + 2000 Then
                                        Call DrawText(TexthDC, (Int(Len(NPCDmgDamage(I))) / 2) * 3 + NewX + sx, NewY - 22 - ii(I) + sx, NPCDmgDamage(I), QBColor(BRIGHTRED))
                                    End If
                                End If
                            End If
                            ii(I) = ii(I) + 1
                        Next
                    End If

                    ' Draw player's damage on NPC
                    If frmMirage.chkPlayerDamage.Value = 1 Then
                        For I = 0 To 9
                            If NPCWho(I) > 0 Then
                                If MapNpc(NPCWho(I)).Num > 0 Then
                                    If frmMirage.chkNpcName.Value = 0 Then
                                        If Npc(MapNpc(NPCWho(I)).Num).Big = 0 Then
                                            If GetTickCount < DmgTime(I) + 2000 Then
                                                Call DrawText(TexthDC, (MapNpc(NPCWho(I)).X - NewPlayerX) * PIC_X + sx + (Int(Len(DmgDamage(I))) / 2) * 3 + MapNpc(NPCWho(I)).xOffset - NewXOffset, (MapNpc(NPCWho(I)).y - NewPlayerY) * PIC_Y + sx - 20 + MapNpc(NPCWho(I)).yOffset - NewYOffset - iii(I), DmgDamage(I), QBColor(WHITE))
                                            End If
                                        Else
                                            If GetTickCount < DmgTime(I) + 2000 Then
                                                Call DrawText(TexthDC, (MapNpc(NPCWho(I)).X - NewPlayerX) * PIC_X + sx + (Int(Len(DmgDamage(I))) / 2) * 3 + MapNpc(NPCWho(I)).xOffset - NewXOffset, (MapNpc(NPCWho(I)).y - NewPlayerY) * PIC_Y + sx - 47 + MapNpc(NPCWho(I)).yOffset - NewYOffset - iii(I), DmgDamage(I), QBColor(WHITE))
                                            End If
                                        End If
                                    Else
                                        If Npc(MapNpc(NPCWho(I)).Num).Big = 0 Then
                                            If GetTickCount < DmgTime(I) + 2000 Then
                                                Call DrawText(TexthDC, (MapNpc(NPCWho(I)).X - NewPlayerX) * PIC_X + sx + (Int(Len(DmgDamage(I))) / 2) * 3 + MapNpc(NPCWho(I)).xOffset - NewXOffset, (MapNpc(NPCWho(I)).y - NewPlayerY) * PIC_Y + sx - 30 + MapNpc(NPCWho(I)).yOffset - NewYOffset - iii(I), DmgDamage(I), QBColor(WHITE))
                                            End If
                                        Else
                                            If GetTickCount < DmgTime(I) + 2000 Then
                                                Call DrawText(TexthDC, (MapNpc(NPCWho(I)).X - NewPlayerX) * PIC_X + sx + (Int(Len(DmgDamage(I))) / 2) * 3 + MapNpc(NPCWho(I)).xOffset - NewXOffset, (MapNpc(NPCWho(I)).y - NewPlayerY) * PIC_Y + sx - 57 + MapNpc(NPCWho(I)).yOffset - NewYOffset - iii(I), DmgDamage(I), QBColor(WHITE))
                                            End If
                                        End If
                                    End If
                                    iii(I) = iii(I) + 1
                                End If
                            End If
                        Next
                    End If
```

If all goes well, this should give you the ability to have up to 10 damages at once showing. Enjoy! :)
Link to comment
Share on other sites

Bumped. While playing AST, I noticed a blitting error that occurs when switching maps. I've included a fix to this in part 2 of the tutorial. To change it if you implemented before the fix, remove the old ReDim of NPCWho and look at step 2 for placing it in the new block of code.
Link to comment
Share on other sites

@♪♫♪:

> Bumped. While playing AST, I noticed a blitting error that occurs when switching maps. I've included a fix to this in part 2 of the tutorial. To change it if you implemented before the fix, remove the old ReDim of NPCWho and look at step 2 for placing it in the new block of code.

Just wondering what was was the error, How did it look ?

Regards, Xeross
Link to comment
Share on other sites

@Xeross:

> Just wondering what was was the error, How did it look ?
>
> Regards, Xeross

"when you switch maps, the damage blits will appear over an NPC of that slot on the new map, a slight bug in the engine"

If you're not adding this to your source, then the fix is in this topic: http://www.touchofdeathforums.com/smf/index.php/topic,46540.0.html
Link to comment
Share on other sites

What about when the same monster respawns and the damage still shows over it's head? I have noticed that is a very similar error but it can be fixed if the blt dmg is terminated once the monster dies or just let the damage finish even after the monster is dead, that way when it finishes it's loop, it won't start on another NPC. You should try saving the initial NPC coordinates to place the blt dmg then just use thoes briefly saved coordinates to keep plotting the damage if the NPC is dead.
Link to comment
Share on other sites

@MrMiguuâ„¢:

> What about when the same monster respawns and the damage still shows over it's head? I have noticed that is a very similar error but it can be fixed if the blt dmg is terminated once the monster dies or just let the damage finish even after the monster is dead, that way when it finishes it's loop, it won't start on another NPC. You should try saving the initial NPC coordinates to place the blt dmg then just use thoes briefly saved coordinates to keep plotting the damage if the NPC is dead.

But if you save the coordinates and the NPC moves, then the blits won't move with the NPC. But that might be what is needed, honestly. I'll try to get this fixed up.
To do:

* Damage blitting upon casting spells
* NPC death damage blit
* Unblit player damage upon death
Link to comment
Share on other sites

hello, where should i put this, i am confused where to put this.

```
        ReDim ii(0 To 9) As Long
        ReDim iii(0 To 9) As Long
        ReDim DmgDamage(0 To 9) As Long
        ReDim DmgTime(0 To 9) As Long
        ReDim NPCDmgDamage(0 To 9) As Long
        ReDim NPCDmgTime(0 To 9) As Long
```
and this too.
```
        ReDim NPCWho(0 To 9) As Long
```
thanks
Link to comment
Share on other sites

just like this?

```
If casestring = "maxinfo" Then
        GAME_NAME = Trim$(parse(1))
        MAX_PLAYERS = Val(parse(2))
        MAX_ITEMS = Val(parse(3))
        MAX_NPCS = Val(parse(4))
        MAX_SHOPS = Val(parse(5))
        MAX_SPELLS = Val(parse(6))
        MAX_MAPS = Val(parse(7))
        MAX_MAP_ITEMS = Val(parse(8))
        MAX_MAPX = Val(parse(9))
        MAX_MAPY = Val(parse(10))
        MAX_EMOTICONS = Val(parse(11))
        MAX_ELEMENTS = Val(parse(12))
        paperdoll = Val(parse(13))
        SpriteSize = Val(parse(14))
        MAX_SCRIPTSPELLS = Val(parse(15))
        CustomPlayers = Val(parse(16))
        lvl = Val(parse(17))
        MAX_PARTY_MEMBERS = Val(parse(18))
        STAT1 = parse(19)
        STAT2 = parse(20)
        STAT3 = parse(21)
        STAT4 = parse(22)

        ReDim ii(0 To 9) As Long
        ReDim iii(0 To 9) As Long
        ReDim DmgDamage(0 To 9) As Long
        ReDim DmgTime(0 To 9) As Long
        ReDim NPCDmgDamage(0 To 9) As Long
        ReDim NPCDmgTime(0 To 9) As Long
```
and this

```
If (casestring = "checkformap") Then
        GettingMap = True
        ReDim NPCWho(0 To 9) As Long
```
sorry im not really good at this.  :sad:
Link to comment
Share on other sites

  • 6 months later...
Sorry for the necropost, but I just added this to Eclipse Stable 1.2 and noticed that when I killed something, the damage floaters are still above it when it respawned, but eventually floated away.

Apparently, now I also get RTE 9 when attacking, on line 'NPCWho(X) = NPCWho(X - 1)'.
Link to comment
Share on other sites

@Zamin:

> Make sure you change all the "frmMirage";s to "frmStable"??
>
> I guess Ballie will give you a better answer.

Yep, I know that the frmMirage error looks different than the RTE 9 error I am getting now. It only happen when I attack a monster (not kill it). I don't know why it refers to that line though.
Link to comment
Share on other sites

Rather than limiting it in a static array (Well, technically it's a dynamic array but you're re-setting it to a set size) you should re-count the subscript when new damage messages come in and set up some message clearing in the rendering subroutine, then re-dim to the new size.
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...