Suporte ao desenvolvimento de jogos!


    [2016] Npc atacando com spells

    Compartilhe
    avatar
    EpicMelanie
    Novato
    Novato

    Mensagens : 12
    Créditos : 5

    [2016] Npc atacando com spells

    Mensagem por EpicMelanie em Sex Abr 08, 2016 5:26 pm

    Andei procurando por algum sistema que faça o NPC usar spells, encontrei vários tutoriais que, ao final da explicação, pediam para baixar um arquivo... Porém TODOS os links estavam quebrados.
    Então consegui extrair esse sistema de uma modificação que fizeram da eclipse e, pelo menos aqui está funcionando perfeitamente.

    (Obs: Não sei quem criou esse sistema, por isso não coloquei créditos.)

    ~ Server Side~
    Em modConstants, encontre:

    Código:
    Public Const MAX_PARTY_MEMBERS As Long = 4

    e adicione em baixo:

    Código:
    Public Const MAX_NPC_SPELLS As Long = 5

    - Define o máximo de spells que o Npc pode usar.

    Em modTypes, encontre Private Type NpcRec e adicione isso antes de End Type:
    Código:
    Spell(1 To MAX_NPC_SPELLS) As Long

    Em modTypes, encontre Private Type MapNpcRec e adicione isso antes de End Type:

    Código:
       SpellTimer(1 To MAX_NPC_SPELLS) As Long

        Heals As Integer


    Em modGameLogic, encontre Sub NpcAttackPlayer e adicione esse código DEPOIS do final da sub NpcAttackPlayer (depois do End Sub):
    Código:
    Sub NpcSpellPlayer(ByVal MapNpcNum As Long, ByVal Victim As Long, SpellSlotNum As Long)
        Dim mapnum As Long
        Dim i As Long
        Dim n As Long
        Dim SpellNum As Long
        Dim Buffer As clsBuffer
        Dim InitDamage As Long
        Dim Damage As Long
        Dim MaxHeals As Long

        ' 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
        
        If SpellSlotNum <= 0 Or SpellSlotNum > MAX_NPC_SPELLS Then Exit Sub

        ' The Variables
        mapnum = GetPlayerMap(Victim)
        SpellNum = NPC(MapNpc(mapnum).NPC(MapNpcNum).Num).Spell(SpellSlotNum)
        
        ' Send this packet so they can see the person attacking
        Set Buffer = New clsBuffer
        Buffer.WriteLong SNpcAttack
        Buffer.WriteLong MapNpcNum
        SendDataToMap mapnum, Buffer.ToArray()
        Set Buffer = Nothing
        
        ' CoolDown Time
        If MapNpc(mapnum).NPC(MapNpcNum).SpellTimer(SpellSlotNum) > GetTickCount Then Exit Sub
        ' Spell Types
            Select Case Spell(SpellNum).Type
        
                ' AOE Healing Spells
                Case SPELL_TYPE_HEALHP
                If SpellSlotNum <= 0 Or SpellSlotNum > MAX_NPC_SPELLS Then Exit Sub 'check for subscript out of range
                ' Make sure an npc waits for the spell to cooldown
                MaxHeals = 1 + NPC(MapNpc(mapnum).NPC(MapNpcNum).Num).Stat(Stats.intelligence) \ 25
                If MapNpc(mapnum).NPC(MapNpcNum).Heals >= MaxHeals Then Exit Sub
                    If MapNpc(mapnum).NPC(MapNpcNum).Vital(Vitals.HP) <= NPC(MapNpc(mapnum).NPC(MapNpcNum).Num).HP * 0.3 Then
                        If Spell(SpellNum).IsAoE Then
                            For i = 1 To MAX_MAP_NPCS
                                If MapNpc(mapnum).NPC(i).Num > 0 Then
                                    If MapNpc(mapnum).NPC(i).Vital(Vitals.HP) > 0 Then
                                        If isInRange(Spell(SpellNum).AoE, MapNpc(mapnum).NPC(MapNpcNum).x, MapNpc(mapnum).NPC(MapNpcNum).y, MapNpc(mapnum).NPC(i).x, MapNpc(mapnum).NPC(i).y) Then
                                            InitDamage = Spell(SpellNum).Vital + (NPC(MapNpc(mapnum).NPC(MapNpcNum).Num).Stat(Stats.intelligence) / 2)
                        
                                            MapNpc(mapnum).NPC(i).Vital(Vitals.HP) = MapNpc(mapnum).NPC(i).Vital(Vitals.HP) + InitDamage
                                            SendActionMsg mapnum, "+" & InitDamage, BrightGreen, 1, (MapNpc(mapnum).NPC(i).x * 32), (MapNpc(mapnum).NPC(i).y * 32)
                                            Call SendAnimation(mapnum, Spell(SpellNum).SpellAnim, 0, 0, TARGET_TYPE_NPC, MapNpcNum)
                        
                                            If MapNpc(mapnum).NPC(i).Vital(Vitals.HP) > NPC(MapNpc(mapnum).NPC(i).Num).HP Then
                                                MapNpc(mapnum).NPC(i).Vital(Vitals.HP) = NPC(MapNpc(mapnum).NPC(i).Num).HP
                                            End If
                        
                                            MapNpc(mapnum).NPC(MapNpcNum).Heals = MapNpc(mapnum).NPC(MapNpcNum).Heals + 1
                        
                                            MapNpc(mapnum).NPC(MapNpcNum).SpellTimer(SpellSlotNum) = GetTickCount + Spell(SpellNum).CDTime * 1000
                                            Exit Sub
                                        End If
                                    End If
                                End If
                            Next
                        Else
                        ' Non AOE Healing Spells
                            InitDamage = Spell(SpellNum).Vital + (NPC(MapNpc(mapnum).NPC(MapNpcNum).Num).Stat(Stats.intelligence) / 2)
                        
                            MapNpc(mapnum).NPC(MapNpcNum).Vital(Vitals.HP) = MapNpc(mapnum).NPC(MapNpcNum).Vital(Vitals.HP) + InitDamage
                            SendActionMsg mapnum, "+" & InitDamage, BrightGreen, 1, (MapNpc(mapnum).NPC(MapNpcNum).x * 32), (MapNpc(mapnum).NPC(MapNpcNum).y * 32)
                            Call SendAnimation(mapnum, Spell(SpellNum).SpellAnim, 0, 0, TARGET_TYPE_NPC, MapNpcNum)
                        
                            If MapNpc(mapnum).NPC(MapNpcNum).Vital(Vitals.HP) > NPC(MapNpc(mapnum).NPC(MapNpcNum).Num).HP Then
                                MapNpc(mapnum).NPC(MapNpcNum).Vital(Vitals.HP) = NPC(MapNpc(mapnum).NPC(MapNpcNum).Num).HP
                            End If
                        
                            MapNpc(mapnum).NPC(MapNpcNum).Heals = MapNpc(mapnum).NPC(MapNpcNum).Heals + 1
                        
                            MapNpc(mapnum).NPC(MapNpcNum).SpellTimer(SpellSlotNum) = GetTickCount + Spell(SpellNum).CDTime * 1000
                            Exit Sub
                        End If
                    End If
                    
                ' AOE Damaging Spells
                Case SPELL_TYPE_DAMAGEHP
                     If SpellSlotNum <= 0 Or SpellSlotNum > MAX_NPC_SPELLS Then Exit Sub 'check for subscript out of range
                ' Make sure an npc waits for the spell to cooldown
                    If Spell(SpellNum).IsAoE Then
                        For i = 1 To Player_HighIndex
                            If IsPlaying(i) Then
                                If GetPlayerMap(i) = mapnum Then
                                    If isInRange(Spell(SpellNum).AoE, MapNpc(mapnum).NPC(MapNpcNum).x, MapNpc(mapnum).NPC(MapNpcNum).y, GetPlayerX(i), GetPlayerY(i)) Then
                                        InitDamage = Spell(SpellNum).Vital + (NPC(MapNpc(mapnum).NPC(MapNpcNum).Num).Stat(Stats.intelligence) / 2)
                                        Damage = InitDamage - Player(i).Stat(Stats.willpower)
                                            If Damage <= 0 Then
                                                SendActionMsg GetPlayerMap(i), "RESIST!", Pink, 1, (GetPlayerX(i) * 32), (GetPlayerY(i) * 32)
                                                Exit Sub
                                            Else
                                                NpcAttackPlayer MapNpcNum, i, Damage
                                                SendAnimation mapnum, Spell(SpellNum).SpellAnim, 0, 0, TARGET_TYPE_PLAYER, MapNpcNum
                                                MapNpc(mapnum).NPC(MapNpcNum).SpellTimer(SpellSlotNum) = GetTickCount + Spell(SpellNum).CDTime * 1000
                                                Exit Sub
                                            End If
                                    End If
                                End If
                            End If
                        Next
                    ' Non AoE Damaging Spells
                    Else
                        If isInRange(Spell(SpellNum).Range, MapNpc(mapnum).NPC(MapNpcNum).x, MapNpc(mapnum).NPC(MapNpcNum).y, GetPlayerX(Victim), GetPlayerY(Victim)) Then
                        InitDamage = Spell(SpellNum).Vital + (NPC(MapNpc(mapnum).NPC(MapNpcNum).Num).Stat(Stats.intelligence) / 2)
                        Damage = InitDamage - Player(Victim).Stat(Stats.willpower)
                            If Damage <= 0 Then
                                SendActionMsg GetPlayerMap(Victim), "RESIST!", Pink, 1, (GetPlayerX(Victim) * 32), (GetPlayerY(Victim) * 32)
                                Exit Sub
                            Else
                                NpcAttackPlayer MapNpcNum, Victim, Damage
                                SendAnimation mapnum, Spell(SpellNum).SpellAnim, 0, 0, TARGET_TYPE_PLAYER, Victim
                                MapNpc(mapnum).NPC(MapNpcNum).SpellTimer(SpellSlotNum) = GetTickCount + Spell(SpellNum).CDTime * 1000
                                Exit Sub
                            End If
                        End If
                    End If
                End Select
    End Sub

    Em modServerLoop, encontre essas 3 linhas e DELETE:

    Código:
    Else
                                ' lol no npc combat
                            End If
    Procure por isso:

    Código:
    ' ////////////////////////////////////////////
    ' // This is used for regenerating NPC's HP //
    ' ////////////////////////////////////////////

    Acima disso, adicione esse código:

    Código:
    ' Spell Casting

                                    For i = 1 To MAX_NPC_SPELLS

                                        If Npc(npcNum).Spell(i) > 0 Then

                                            If MapNpc(mapnum).Npc(x).SpellTimer(i) + (Spell(Npc(npcNum).Spell(i)).CastTime * 1000) < GetTickCount Then

                                                NpcSpellPlayer x, target, i

                                            End If

                                        End If

                                    Next

                                End If

    Agora, ~CLIENT SIDE~:


    Em modConstants, encontre:

    Código:
    Public Const MAX_PARTY_MEMBERS As Long = 4

    e adicione em baixo:

    Código:
    Public Const MAX_NPC_SPELLS As Long = 5

    Encontre Private Type NpcRec e adicione isso antes de End Type:
    Código:
    Spell(1 To MAX_NPC_SPELLS) As Long

    Em modGameEditors, vá até Public Sub NpcEditorInit e encontre essa linha:

    Código:
    .txtDamage.text = Npc(EditorIndex).Damage
    Abaixo disso, adicione:

    Código:
    .scrlSpellNum.Max = MAX_NPC_SPELLS
     .scrlSpellNum.Value = 1



    Agora é a parte que falta em vários (se não todos) tutoriais:


    Vá até frmEditor_NPC e aumente o tamanho da frm, de forma que caiba outro Frame.

    E, faça o seguinte:


    Img:


    -Adicione um frame, e em (name) coloque fraSpell

    -Adicione um HScrollBar, e em (name) coloque scrlSpellNum  e Height: 255

    -Adicione um Label, em (name) coloque lblSpellName e em Caption coloque Spell: None

    -Adicione outro Label, em (name) coloque lblSpellNum e em Caption coloque Num: 0

    -Adicione outro HScrollBar e em (name) coloque scrlSpell  e Height: 255

    Agora de 2 cliques no Form para editar os códigos.
    No topo dos códigos, encontre Option Explicit e, adicione em baixo:

    Código:
    Private SpellIndex As Long

    Agora, no FINAL dos códigos do frmEditor_NPC, depois de end sub, adicione:

    Código:
    Private Sub scrlSpell_Change()
    lblSpellNum.Caption = "Num: " & scrlSpell.Value
        If scrlSpell.Value > 0 Then
            lblSpellName.Caption = "Spell: " & Trim$(Spell(scrlSpell.Value).Name)
        Else
            lblSpellName.Caption = "Spell: None"
        End If
        NPC(EditorIndex).Spell(SpellIndex) = scrlSpell.Value
    End Sub

    Private Sub scrlSpellNum_Change()
    SpellIndex = scrlSpellNum.Value
        fraSpell.Caption = "Spell - " & SpellIndex
        scrlSpell.Value = NPC(EditorIndex).Spell(SpellIndex)
    End Sub

    Salve e compile.
    avatar
    Profane ~
    Administrador
    Administrador

    Mensagens : 703
    Créditos : 119

    Re: [2016] Npc atacando com spells

    Mensagem por Profane ~ em Dom Abr 10, 2016 2:32 pm

    Algo a citar em relação o uso de tal fatores; 

    Ao usar isso, em questão de loop do server, e leituras; Caso tenha mais de um Npc com spell implantada em sua classe, e o mesmo targetar o alvo player; e o mesmo não se encontrar no mapa; Tem grandes chances de quebrar o servidor.

    O Castspell usa a leitura de envio para seres que estão nos quadrantes do GetPlayerMap Atual; porém basicamente o Npc não muda de mapa ><; Os players, sim. 

    Npc -> castspell enquanto o player está no mapa, player muda de mapa por N motivos, acaba gerando o out of range. 

    Uma defesa contra isso é em seu serverloop, na leitura de envio e pós analisar se de fato o Alvo em questão está no Mapa.


    _________________
    "If you don't belong here, just build a place where you do."
    avatar
    EpicMelanie
    Novato
    Novato

    Mensagens : 12
    Créditos : 5

    Re: [2016] Npc atacando com spells

    Mensagem por EpicMelanie em Dom Abr 10, 2016 4:09 pm

    Então, algo para evitar isso seria adicionar essa checagem:

    Edit: Não deu certo.
    Apesar de eu ter feito testes com esse sistema e ele não ter bugado (ainda), vou tentar fazer esse tipo de checagem ( se o jogador não estiver no mapa, exit sub e bla bla bla ).

    -------------------------------------------------------------------------------------------------------
    Eu apenas copiei e colei o código pois não tenho tanta experiência para desenvolver meus próprios sistemas (comecei há pouco tempo), peço desculpas.
    avatar
    Profane ~
    Administrador
    Administrador

    Mensagens : 703
    Créditos : 119

    Re: [2016] Npc atacando com spells

    Mensagem por Profane ~ em Seg Abr 11, 2016 1:54 pm

    Não precisa pedir desculpas >< Entendo o que fez, eh uma contribuição excelente sem dúvidas >< 

    Vi que informou que copiou, colou e etc.. mas você foi preparar o topico, separar os codigos, verificar entre outros. Bom trabalho. 

    Em relação a checagem, a propria sub já tem; observe:

    Código:
     Check for subscript out of range[size=12][/size]
        If MapNpc(GetPlayerMap(Victim)).NPC(MapNpcNum).Num <= 0 Then[size=12][/size]
            Exit Sub[size=12][/size]
        End If

    O Caso é que apenas na sub eu creio que não processe tudo, pq ao enviar dps dessa checagem que é o problema ><

    Player Está no mapa, Npc envia a spell, passou por essa primeira checagem, player muda de mapa, bump >< quebra.

    Com muitos players ai que vira um problema ou muitos npc's. 

    Precisando de ajuda montamos algo ;3 De qualquer forma, bom trabalho.


    _________________
    "If you don't belong here, just build a place where you do."

    Conteúdo patrocinado

    Re: [2016] Npc atacando com spells

    Mensagem por Conteúdo patrocinado


      Data/hora atual: Dom Jul 22, 2018 4:14 am