Bem, este tutorial, vai basicamente permitir que você conjure magias com clique no mapa, na posição do mouse, claro, com um alcance editado por você no editor. Sem mais delongas, vamos ao tutorial.
Primeiramente, abra a pasta do cliente, e em "data files > graphics" , adicione esta imagem, ou uma de tamanho similar a esta:
Agora vamos ao código, então abra seu Cliente.vbp , e no final de "ModGlobals" , adicione isto:
Agora, em "ModGameLogic" , procure por:
E substitua esta linha por esta:
Ainda nesta SUB "CastSpell" , abaixo de :
Adicione isto:
Ainda nesta SUB "CastSpell" , procure por:
E substitua por:
E acima disto, adicione isto:
Agora, no final de "ModDirectX7" , adicione isto:
Agora procure pela SUB "picScreen_MouseDown" , e abaixo de :
Adicione isto:
Agora procure pela SUB "picSpells_DblClick()" , e troque isto:
Por isto:
Agora procure pela SUB "SendHotbarUse(ByVal Slot As Long)" , e troque essa parte:
Por isto:
Agora, em "ModTypes" , no tipo "Private Type SpellRec" , acima de "End Type" , adicione isto:
Agora, em "ModGameEditors" , na SUB "SpellEditorInit()" , procure por:
E abaixo disto, adicione isto:
Pra finalizar o cliente, abra seu Editor de Magias de "forms" , e adicione:
1x CheckBox
Caption: Is mouse-pointer
Name: chkSpellMouse
Então, dê duplo clique para abrir o código do "CheckBox" , e adicione isto dentro:
Ainda em "ModTypes" , no tipo "Public Type TempPlayerRec" , acima de "End Type" , adicione isto:
Agora, em "ModServerLoop", na "Sub ServerLoop()" procure por isto:
Adicione isto:
E acima disto:
Adicione isto:
Agora, no final de "ModCombat" , adicione isto:
E pronto, agora você faz magias com um clique!
Pontos a considerar:
-Por mais que esteja em 1.0 , não foram encontrados bugs;
-Pra conforto do jogador, lembre de impedir no cliente "BltTargetHover" e captura de alvos, quando estiver com "MemSpell" , evita que a imagem de alvo mostre quando você não quer;
- Funcional com as magias da versão 2.0 do E.O (Dano HP/MP e Cura HP/MP);
- Explicando valores do editor: Range = Distância que o mouse pode se afastar do jogador e AOE = Área do efeito e da animação onde for clicado;
- Cliente: X = Pode castar , X = Não pode castar
- Foi bem extenso, então qualquer erro, 99% de chance de ser algo que esqueci, então só perguntar, que atualizo o tópico quando disponível;
Primeiramente, abra a pasta do cliente, e em "data files > graphics" , adicione esta imagem, ou uma de tamanho similar a esta:
Nome: "spellxy.bmp"
-CLIENT~SIDE-
Agora vamos ao código, então abra seu Cliente.vbp , e no final de "ModGlobals" , adicione isto:
- Spoiler:
Public MemSpell As Long
Agora, em "ModGameLogic" , procure por:
- Spoiler:
Public Sub CastSpell(ByVal spellslot As Long)
E substitua esta linha por esta:
- Spoiler:
Public Sub CastSpell(ByVal spellslot As Long, ByVal X As Long, ByVal Y As Long)
Ainda nesta SUB "CastSpell" , abaixo de :
- Spoiler:
If SpellCD(spellslot) > 0 Then
AddText "Spell has not cooled down yet!", BrightRed
Exit Sub
End If
Adicione isto:
- Spoiler:
If SpellBuffer > 0 Then Exit Sub
If X < 0 Or X > Map.MaxX Then Exit Sub
If Y < 0 Or Y > Map.MaxY Then Exit Sub
Ainda nesta SUB "CastSpell" , procure por:
- Spoiler:
If PlayerSpells(spellslot) > 0 Then
If GetTickCount > Player(MyIndex).AttackTimer + 1000 Then
If Player(MyIndex).Moving = 0 Then
Set Buffer = New clsBuffer
Buffer.WriteLong CCast
Buffer.WriteLong spellslot
SendData Buffer.ToArray()
Set Buffer = Nothing
SpellBuffer = spellslot
SpellBufferTimer = GetTickCount
Else
Call AddText("Cannot cast while walking!", BrightRed)
End If
End If
Else
Call AddText("No spell here.", BrightRed)
End If
E substitua por:
- Spoiler:
If PlayerSpells(spellslot) > 0 Then
If GetTickCount > Player(MyIndex).AttackTimer + 1000 Then
If Player(MyIndex).Moving = 0 Then
Set Buffer = New clsBuffer
Buffer.WriteLong CCast
Buffer.WriteLong spellslot
Buffer.WriteLong X
Buffer.WriteLong Y
SendData Buffer.ToArray()
Set Buffer = Nothing
SpellBuffer = spellslot
SpellBufferTimer = GetTickCount
Else
Call AddText("Cannot cast while walking!", BrightRed)
End If
End If
Else
Call AddText("No spell here.", BrightRed)
End If
- Spoiler:
' render the decals
For i = 1 To MAX_BYTE
Call BltBlood(i)
Next
E acima disto, adicione isto:
- Spoiler:
'Draw current memSpell on mouse pointer
If MemSpell > 0 And MemSpell < MAX_SPELLS Then
If isInRange(Spell(MemSpell).Range, GetPlayerX(MyIndex), GetPlayerY(MyIndex), CurX, CurY) Then
BltSpellXY CurX * 32, CurY * 32
Else
BltSpellXYOutRange CurX * 32, CurY * 32
End If
End If
Agora, no final de "ModDirectX7" , adicione isto:
- Spoiler:
Public Function isInRange(ByVal Range As Long, ByVal x1 As Long, ByVal y1 As Long, ByVal x2 As Long, ByVal y2 As Long) As Boolean
Dim nVal As Long
isInRange = False
nVal = Sqr((x1 - x2) ^ 2 + (y1 - y2) ^ 2)
If nVal <= Range Then isInRange = True
End Function
Public Sub BltSpellXY(ByVal X As Long, ByVal Y As Long)
Dim sRECT As DxVBLib.RECT
Dim width As Long, height As Long
' If debug mode, handle error then exit out
If Options.Debug = 1 Then On Error GoTo errorhandler
If DDS_SpellXY Is Nothing Then Exit Sub
width = DDSD_SpellXY.lWidth / 2
height = DDSD_SpellXY.lHeight
With sRECT
.top = 0
.Bottom = height
.Left = 0
.Right = width
End With
X = X - ((width - 32) / 2)
Y = Y - ((height - 32) / 2)
X = ConvertMapX(X)
Y = ConvertMapY(Y)
' clipping
If Y < 0 Then
With sRECT
.top = .top - Y
End With
Y = 0
End If
If X < 0 Then
With sRECT
.Left = .Left - X
End With
X = 0
End If
If Y + height > DDSD_BackBuffer.lHeight Then
sRECT.Bottom = sRECT.Bottom - (Y + height - DDSD_BackBuffer.lHeight)
End If
If X + width > DDSD_BackBuffer.lWidth Then
sRECT.Right = sRECT.Right - (X + width - DDSD_BackBuffer.lWidth)
End If
' /clipping
Call Engine_BltFast(X, Y, DDS_SpellXY, sRECT, DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY)
' Error handler
Exit Sub
errorhandler:
HandleError "BltSpellXY", "modDirectDraw7", Err.Number, Err.Description, Err.Source, Err.HelpContext
Err.Clear
Exit Sub
End Sub
Public Sub BltSpellXYOutRange(ByVal X As Long, ByVal Y As Long)
Dim sRECT As DxVBLib.RECT
Dim width As Long, height As Long
' If debug mode, handle error then exit out
If Options.Debug = 1 Then On Error GoTo errorhandler
If DDS_SpellXY Is Nothing Then Exit Sub
width = DDSD_SpellXY.lWidth / 2
height = DDSD_SpellXY.lHeight
With sRECT
.top = 0
.Bottom = height
.Left = width
.Right = .Left + width
End With
X = X - ((width - 32) / 2)
Y = Y - ((height - 32) / 2)
X = ConvertMapX(X)
Y = ConvertMapY(Y)
' clipping
If Y < 0 Then
With sRECT
.top = .top - Y
End With
Y = 0
End If
If X < 0 Then
With sRECT
.Left = .Left - X
End With
X = 0
End If
If Y + height > DDSD_BackBuffer.lHeight Then
sRECT.Bottom = sRECT.Bottom - (Y + height - DDSD_BackBuffer.lHeight)
End If
If X + width > DDSD_BackBuffer.lWidth Then
sRECT.Right = sRECT.Right - (X + width - DDSD_BackBuffer.lWidth)
End If
' /clipping
Call Engine_BltFast(X, Y, DDS_SpellXY, sRECT, DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY)
' Error handler
Exit Sub
errorhandler:
HandleError "BltSpellXYOutRange", "modDirectDraw7", Err.Number, Err.Description, Err.Source, Err.HelpContext
Err.Clear
Exit Sub
End Sub
Agora procure pela SUB "picScreen_MouseDown" , e abaixo de :
- Spoiler:
' If debug mode, handle error then exit out
If Options.Debug = 1 Then On Error GoTo errorhandler
Adicione isto:
- Spoiler:
'Right mouse click, cancel
If Button = vbRightButton Then
MemSpell = 0
End If
'Check for mouse spell
If MemSpell > 0 Then
CastSpell MemSpell, CurX, CurY
MemSpell = 0
End If
Agora procure pela SUB "picSpells_DblClick()" , e troque isto:
- Spoiler:
If spellnum <> 0 Then
Call CastSpell(spellnum)
Exit Sub
End If
Por isto:
- Spoiler:
If spellnum <> 0 Then
If Spell(spellnum).IsMouse = True Then
MemSpell = spellnum
Else
Call CastSpell(spellnum, 0, 0)
End If
Exit Sub
End If
Agora procure pela SUB "SendHotbarUse(ByVal Slot As Long)" , e troque essa parte:
- Spoiler:
' check if spell
If Hotbar(Slot).sType = 2 Then ' spell
Call CastSpell(PlayerSpells(Hotbar(Slot).Slot))
Exit Sub
End If
Por isto:
- Spoiler:
' check if spell
If Hotbar(Slot).sType = 2 Then ' spell
For X = 1 To MAX_PLAYER_SPELLS
' is the spell matching the hotbar?
If PlayerSpells(X) = Hotbar(Slot).Slot Then
If Spell(X).IsMouse Then
MemSpell = X
Else
' found it, cast it
CastSpell X, 0, 0
End If
Exit Sub
End If
Next
' can't find the spell, exit out
Exit Sub
End If
Agora, em "ModTypes" , no tipo "Private Type SpellRec" , acima de "End Type" , adicione isto:
- Spoiler:
IsMouse As Boolean
Agora, em "ModGameEditors" , na SUB "SpellEditorInit()" , procure por:
- Spoiler:
.scrlStun.Value = Spell(EditorIndex).StunDuration
E abaixo disto, adicione isto:
- Spoiler:
If Spell(EditorIndex).IsMouse Then
.chkSpellMouse.Value = 1
Else
.chkSpellMouse.Value = 0
End If
Pra finalizar o cliente, abra seu Editor de Magias de "forms" , e adicione:
1x CheckBox
Caption: Is mouse-pointer
Name: chkSpellMouse
Então, dê duplo clique para abrir o código do "CheckBox" , e adicione isto dentro:
- Spoiler:
Spell(EditorIndex).IsMouse = chkSpellMouse.Value
-SERVER~SIDE-
Agora, abra seu "server.vbp" , e em "ModTypes" , no tipo "Private Type SpellRec" , acima de "End Type" , adicione isto:
- Spoiler:
IsMouse As Boolean
Ainda em "ModTypes" , no tipo "Public Type TempPlayerRec" , acima de "End Type" , adicione isto:
- Spoiler:
mouseX As Long
mouseY As Long
Agora, em "ModServerLoop", na "Sub ServerLoop()" procure por isto:
- Spoiler:
If GetTickCount > TempPlayer(i).spellBuffer.Timer + (Spell(Player(i).Spell(TempPlayer(i).spellBuffer.Spell)).CastTime * 1000) Then
CastSpell i, TempPlayer(i).spellBuffer.Spell, TempPlayer(i).spellBuffer.Target, TempPlayer(i).spellBuffer.tType
TempPlayer(i).spellBuffer.Spell = 0
TempPlayer(i).spellBuffer.Timer = 0
TempPlayer(i).spellBuffer.Target = 0
TempPlayer(i).spellBuffer.tType = 0
End If
E substitua por isto:
- Spoiler:
If GetTickCount > TempPlayer(i).spellBuffer.Timer + (Spell(Player(i).Spell(TempPlayer(i).spellBuffer.Spell)).CastTime * 1000) Then
If Spell(TempPlayer(i).spellBuffer.Spell).IsMouse Then
CastMouseSpell i, TempPlayer(i).spellBuffer.Spell, TempPlayer(i).spellBuffer.Target, TempPlayer(i).spellBuffer.tType
Else
CastSpell i, TempPlayer(i).spellBuffer.Spell, TempPlayer(i).spellBuffer.Target, TempPlayer(i).spellBuffer.tType
End If
TempPlayer(i).spellBuffer.Spell = 0
TempPlayer(i).spellBuffer.Timer = 0
TempPlayer(i).spellBuffer.Target = 0
TempPlayer(i).spellBuffer.tType = 0
End If
Agora, em "ModHandleData" , substitua sua "Sub HandleCast" , por esta:
- Spoiler:
Sub HandleCast(ByVal Index As Long, ByRef Data() As Byte, ByVal StartAddr As Long, ByVal ExtraVar As Long)
Dim n As Long
Dim X As Long, Y As Long
Dim Buffer As clsBuffer
If Index <= 0 Or Index > MAX_PLAYERS Then Exit Sub
If TempPlayer(Index).InGame = False Then Exit Sub
Set Buffer = New clsBuffer
Buffer.WriteBytes Data()
' Spell slot
n = Buffer.ReadLong 'CLng(Parse(1))
X = Buffer.ReadLong
Y = Buffer.ReadLong
Set Buffer = Nothing
If n <= 0 Or n > MAX_PLAYER_SPELLS Then Exit Sub
'Check for validate coordinates
If X < 0 Or X > Map(GetPlayerMap(Index)).MaxX Then Exit Sub
If Y < 0 Or Y > Map(GetPlayerMap(Index)).MaxY Then Exit Sub
'Check if is a mouse spell type
If Spell(n).IsMouse = True Then
TempPlayer(Index).mouseX = X
TempPlayer(Index).mouseY = Y
'Set the spell and coordinates
Call BufferSpell(Index, n)
Else
TempPlayer(Index).mouseX = 0
TempPlayer(Index).mouseY = 0
'Even if client send us coordinates without right spell, we zero it
Call BufferSpell(Index, n)
End If
End Sub
Ainda em "ModHandleData" , na "Sub HandleHotbarUse", substitua isto:
- Spoiler:
Case 2 ' spell
For i = 1 To MAX_PLAYER_SPELLS
If Player(Index).Spell(i) > 0 Then
If Player(Index).Spell(i) = Player(Index).Hotbar(Slot).Slot Then
BufferSpell Index, i
Exit Sub
End If
End If
Next
Por isto:
- Spoiler:
Case 2 ' spell
For i = 1 To MAX_PLAYER_SPELLS
If Player(Index).Spell(i) > 0 Then
If Player(Index).Spell(i) = Player(Index).Hotbar(Slot).Slot Then
If Spell(Player(Index).Spell(i)).IsMouse Then
PlayerMsg Index, "Click spell...", White
Else
BufferSpell Index, i
End If
Exit Sub
End If
End If
Next
Agora, em "ModCombat" , na "Public Sub BufferSpell" , abaixo de :
- Spoiler:
Dim TargetType As Byte
Dim Target As Long
Adicione isto:
- Spoiler:
Dim X As Long, Y As Long
E substitua isto:
- Spoiler:
- HasBuffered = False
Por isso:
- Spoiler:
X = TempPlayer(Index).mouseX
Y = TempPlayer(Index).mouseY
HasBuffered = False
If Spell(SpellNum).IsMouse Then
If X < 0 Or X > Map(GetPlayerMap(Index)).MaxX Then
PlayerMsg Index, "X inválido", White
Exit Sub
End If
If Y < 0 Or Y > Map(GetPlayerMap(Index)).MaxY Then
PlayerMsg Index, "Y inválido", White
Exit Sub
End If
If Not isInRange(Range, GetPlayerX(Index), GetPlayerY(Index), X, Y) Then
PlayerMsg Index, "Spell click too far from range:" & Range, BrightRed
Else
HasBuffered = True
End If
Else
E acima disto:
- Spoiler:
If HasBuffered Then
SendAnimation MapNum, Spell(SpellNum).CastAnim, 0, 0, TARGET_TYPE_PLAYER, Index
SendActionMsg MapNum, "Casting " & Trim$(Spell(SpellNum).Name) & "!", BrightRed, ACTIONMSG_SCROLL, GetPlayerX(Index) * 32, GetPlayerY(Index) * 32
TempPlayer(Index).spellBuffer.Spell = spellslot
TempPlayer(Index).spellBuffer.Timer = GetTickCount
TempPlayer(Index).spellBuffer.Target = TempPlayer(Index).Target
TempPlayer(Index).spellBuffer.tType = TempPlayer(Index).TargetType
Exit Sub
Else
SendClearSpellBuffer Index
End If
Adicione isto:
- Spoiler:
End If
Agora, no final de "ModCombat" , adicione isto:
- Spoiler:
Public Sub CastMouseSpell(ByVal Index As Long, ByVal spellslot As Long, ByVal Target As Long, ByVal TargetType As Byte)
Dim SpellNum As Long
Dim MPCost As Long
Dim LevelReq As Long
Dim MapNum As Long
Dim Vital As Long
Dim DidCast As Boolean
Dim ClassReq As Long
Dim AccessReq As Long
Dim i As Long
Dim AoE As Long
Dim Range As Long
Dim VitalType As Byte
Dim increment As Boolean
Dim X As Long, Y As Long
Dim mX As Long, mY As Long
Dim Buffer As clsBuffer
Dim SpellCastType As Long
DidCast = False
' Prevent subscript out of range
If spellslot <= 0 Or spellslot > MAX_PLAYER_SPELLS Then Exit Sub
SpellNum = GetPlayerSpell(Index, spellslot)
MapNum = GetPlayerMap(Index)
' Make sure player has the spell
If Not HasSpell(Index, SpellNum) Then Exit Sub
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
Else
SpellCastType = 1 ' self-cast AoE
End If
End If
' set the vital
Vital = Spell(SpellNum).Vital
AoE = Spell(SpellNum).AoE
Range = Spell(SpellNum).Range
mX = TempPlayer(Index).mouseX
mY = TempPlayer(Index).mouseY
If Spell(SpellNum).IsMouse = True Then
If mX < 0 Or mX > Map(GetPlayerMap(Index)).MaxX Then
PlayerMsg Index, "X inválido", White
Exit Sub
End If
If mY < 0 Or mY > Map(GetPlayerMap(Index)).MaxY Then
PlayerMsg Index, "Y inválido", White
Exit Sub
End If
'Check for range in mouse
If Not isInRange(Range, GetPlayerX(Index), GetPlayerY(Index), mX, mY) Then
PlayerMsg Index, "Spell click too far from range:" & Range, BrightRed
Else
Select Case SpellCastType
Case 0 ' self-cast target
Select Case Spell(SpellNum).Type
Case SPELL_TYPE_HEALHP
SpellPlayer_Effect Vitals.HP, True, Index, Vital, SpellNum
DidCast = True
Case SPELL_TYPE_HEALMP
SpellPlayer_Effect Vitals.MP, True, Index, Vital, SpellNum
DidCast = True
Case SPELL_TYPE_WARP
SendAnimation MapNum, Spell(SpellNum).SpellAnim, 0, 0, TARGET_TYPE_PLAYER, Index
PlayerWarp Index, Spell(SpellNum).Map, Spell(SpellNum).X, Spell(SpellNum).Y
SendAnimation GetPlayerMap(Index), Spell(SpellNum).SpellAnim, 0, 0, TARGET_TYPE_PLAYER, Index
DidCast = True
End Select
Case 1, 3 ' self-cast AOE & targetted AOE
Select Case Spell(SpellNum).Type
Case SPELL_TYPE_DAMAGEHP
DidCast = True
'Check Hit
SpellOnCoordinate Index, GetPlayerMap(Index), SpellNum, mX, mY, Vital
Case SPELL_TYPE_HEALHP, SPELL_TYPE_HEALMP, SPELL_TYPE_DAMAGEMP
If Spell(SpellNum).Type = SPELL_TYPE_HEALHP Then
VitalType = Vitals.HP
increment = True
ElseIf Spell(SpellNum).Type = SPELL_TYPE_HEALMP Then
VitalType = Vitals.MP
increment = True
ElseIf Spell(SpellNum).Type = SPELL_TYPE_DAMAGEMP Then
VitalType = Vitals.MP
increment = False
End If
DidCast = True
For i = 1 To Player_HighIndex
If IsPlaying(i) Then
If GetPlayerMap(i) = GetPlayerMap(Index) Then
If isInRange(AoE, mX, mY, GetPlayerX(i), GetPlayerY(i)) Then
SpellPlayer_Effect VitalType, increment, i, Vital, SpellNum
End If
End If
End If
Next
For i = 1 To MAX_MAP_NPCS
If MapNpc(MapNum).Npc(i).Num > 0 Then
If MapNpc(MapNum).Npc(i).Vital(HP) > 0 Then
If isInRange(AoE, mX, mY, MapNpc(MapNum).Npc(i).X, MapNpc(MapNum).Npc(i).Y) Then
SpellNpc_Effect VitalType, increment, i, Vital, SpellNum, MapNum
End If
End If
End If
Next
End Select
Case 2 ' targetted
'It's clicked, we don't need target :)
End Select
End If
Else 'is not a mouse-type one
PlayerMsg Index, "This is not a mouse spell", Red
SendClearSpellBuffer Index
Exit Sub
End If
If DidCast Then
Call SetPlayerVital(Index, Vitals.MP, GetPlayerVital(Index, Vitals.MP) - MPCost)
Call SendVital(Index, Vitals.MP)
' send vitals to party if in one
If TempPlayer(Index).inParty > 0 Then SendPartyVitals TempPlayer(Index).inParty, Index
TempPlayer(Index).SpellCD(spellslot) = GetTickCount + (Spell(SpellNum).CDTime * 1000)
Call SendCooldown(Index, spellslot)
SendActionMsg MapNum, Trim$(Spell(SpellNum).Name) & "!", BrightRed, ACTIONMSG_SCROLL, GetPlayerX(Index) * 32, GetPlayerY(Index) * 32
End If
End Sub
Public Sub SpellOnCoordinate(ByVal Index As Long, ByVal MapNum As Long, ByVal SpellNum As Long, ByVal X As Long, ByVal Y As Long, ByVal Damage As Long)
Dim Area As Long, Range As Long
Dim i As Long
If Index <= 0 Or Index > MAX_PLAYERS Then Exit Sub
If MapNum <= 0 Or MapNum > MAX_MAPS Then Exit Sub
If X < 0 Or X > Map(MapNum).MaxX Then Exit Sub
If Y < 0 Or Y > Map(MapNum).MaxY Then Exit Sub
If SpellNum <= 0 Or SpellNum > MAX_SPELLS Then Exit Sub
Area = Spell(SpellNum).AoE
Range = Spell(SpellNum).Range
'Check if we want to hit in area
If Area > 0 Then
'//AREA//
For i = 1 To MAX_PLAYERS
If IsPlaying(i) And Index <> i And GetPlayerMap(i) = MapNum Then
If isInRange(Range, X, Y, GetPlayerX(i), GetPlayerY(i)) Then
PlayerDamagePlayer Index, i, Damage
End If
End If
Next
For i = 1 To MAX_MAP_NPCS
If MapNpc(MapNum).Npc(i).Num > 0 And GetPlayerMap(Index) = MapNum Then
If isInRange(Range, X, Y, MapNpc(MapNum).Npc(i).X, MapNpc(MapNum).Npc(i).Y) Then
PlayerDamageNpc Index, MapNum, i, Damage
End If
End If
Next
Else
'//ON TILE X,Y ONLY//
For i = 1 To MAX_PLAYERS
If IsPlaying(i) And Index <> i Then
If GetPlayerMap(i) = MapNum And GetPlayerX(i) = X And GetPlayerY(i) = Y Then
PlayerDamagePlayer Index, i, Damage
End If
End If
Next
For i = 1 To MAX_MAP_NPCS
If MapNpc(MapNum).Npc(i).Num > 0 Then
If GetPlayerMap(Index) = MapNum And MapNpc(MapNum).Npc(i).X = X And MapNpc(MapNum).Npc(i).Y = Y Then
PlayerDamageNpc Index, MapNum, i, Damage
End If
End If
Next
End If
If Spell(SpellNum).SpellAnim > 0 Then
SendAnimation MapNum, Spell(SpellNum).SpellAnim, X, Y
End If
End Sub
Public Sub PlayerDamagePlayer(ByVal Attacker As Long, ByVal Victim As Long, ByVal Damage As Long)
If Attacker <= 0 Or Attacker > MAX_PLAYERS Then Exit Sub
If Victim <= 0 Or Victim > MAX_PLAYERS Then Exit Sub
If Damage >= GetPlayerVital(Victim, Vitals.HP) Then
OnDeath Victim
Else
SendActionMsg GetPlayerMap(Victim), "-" & Damage, BrightRed, 1, (GetPlayerX(Victim) * 32), (GetPlayerY(Victim) * 32)
SendBlood GetPlayerMap(Victim), GetPlayerX(Victim), GetPlayerY(Victim)
Call SetPlayerVital(Victim, Vitals.HP, GetPlayerVital(Victim, Vitals.HP) - Damage)
Call SendVital(Attacker, Vitals.HP)
End If
End Sub
Public Sub PlayerDamageNpc(ByVal Index As Long, ByVal MapNum As Long, ByVal MapNpcNum As Long, ByVal Damage As Long)
Dim Exp As Long
Dim NpcNum As Long
Dim d As Long
Dim n As Long
Dim i As Long
Dim Buffer As clsBuffer
If Index <= 0 Or Index > MAX_PLAYERS Then Exit Sub
If MapNpcNum <= 0 Or MapNpcNum > MAX_MAP_NPCS Then Exit Sub
If MapNum <= 0 Or MapNum > MAX_MAPS Then Exit Sub
NpcNum = Map(MapNum).Npc(MapNpcNum)
If NpcNum <= 0 Or NpcNum > MAX_NPCS Then Exit Sub
If Damage >= MapNpc(MapNum).Npc(MapNpcNum).Vital(Vitals.HP) Then
SendActionMsg MapNum, "-" & MapNpc(MapNum).Npc(MapNpcNum).Vital(Vitals.HP), BrightRed, 1, (MapNpc(MapNum).Npc(MapNpcNum).X * 32), (MapNpc(MapNum).Npc(MapNpcNum).Y * 32)
SendBlood MapNum, MapNpc(MapNum).Npc(MapNpcNum).X, MapNpc(MapNum).Npc(MapNpcNum).Y
' 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(Index).inParty > 0 Then
' pass through party sharing function
Party_ShareExp TempPlayer(Index).inParty, Exp, Index
Else
' no party - keep exp for self
GivePlayerEXP Index, 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
' 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 MapNum, MapNpc(MapNum).Npc(MapNpcNum).X, MapNpc(MapNum).Npc(MapNpcNum).Y
' Set the NPC target to the player
MapNpc(MapNum).Npc(MapNpcNum).TargetType = 1 ' player
MapNpc(MapNum).Npc(MapNpcNum).Target = Index
' 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 = Index
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
SendMapNpcVitals MapNum, MapNpcNum
End If
End Sub
E pronto, agora você faz magias com um clique!
Pontos a considerar:
-Por mais que esteja em 1.0 , não foram encontrados bugs;
-Pra conforto do jogador, lembre de impedir no cliente "BltTargetHover" e captura de alvos, quando estiver com "MemSpell" , evita que a imagem de alvo mostre quando você não quer;
- Funcional com as magias da versão 2.0 do E.O (Dano HP/MP e Cura HP/MP);
- Explicando valores do editor: Range = Distância que o mouse pode se afastar do jogador e AOE = Área do efeito e da animação onde for clicado;
- Cliente: X = Pode castar , X = Não pode castar
- Foi bem extenso, então qualquer erro, 99% de chance de ser algo que esqueci, então só perguntar, que atualizo o tópico quando disponível;
~Créditos~
Eu - lucas100vzs/Kotol