[Aportes indexados] Invocar BOSS de clanes desde .ini

Bramhh

Fundador Evolutionao
Miembro del equipo
Moderador de AO
Moderador
En base a la publicación https://www.gs-zone.org/temas/didactico-invocar-boss-4-personas.100382/#post-847088 que hice ahora lo aporto pero para cargar desde un archivo en la carpeta Dat del servidor.

Comenzamos así todo en el Servidor.

En General (Sub Main)
Abajo de

Código:
Call InicializaEstadisticas
Agregamos
Código:
Call CargarBossClanes

Luego buscamos el modulo "modGuilds" y en la parte superior de declaraciones ponemos....
Abajo de...

Código:
Private Const MAXANTIFACCION As Byte = 5
'puntos maximos de antifaccion que un clan tolera antes de ser cambiada su alineacion

Agregamos

Código:
'Para las invocaciones
Public estadoBossClan As Boolean
Public invocadores() As Integer
Public bossInvocadoIndex As Integer
Public cantidadinvocadores As Integer

Private Type Boss
    NumNpc As Integer
    Mapa As Integer
    CoordXBoss As Byte
    CoordYBoss As Byte
    CoordXInvocador() As Byte
    CoordYInvocador() As Byte
End Type

Public datosBoss As Boss

Ahora al final del módulo agregamos 2 Subs...

Código:
Public Sub CargarBossClanes()
'**Código by Bramh**
'**7/10/2021**
 
    If frmMain.Visible Then frmMain.txStatus.Caption = "Cargando sistema de boss"
 
    'Declaraciones
    Dim ubicacionArchivo As String
    Dim cantinvocadoresMax As Byte
    Dim loopX As Long

    ubicacionArchivo = App.Path & "\Dat\BossClanes.ini"

    'Número total de invocadores
    cantidadinvocadores = val(GetVar(ubicacionArchivo, "DatosBoss", "CantidadInvocadores"))

    With datosBoss
        .NumNpc = val(GetVar(ubicacionArchivo, "DatosBoss", "NumNpcBoss"))
        .Mapa = val(GetVar(ubicacionArchivo, "DatosBoss", "MapInvocarBoss"))
        .CoordXBoss = val(GetVar(ubicacionArchivo, "DatosBoss", "MapInvocarBossCordX"))
        .CoordYBoss = val(GetVar(ubicacionArchivo, "DatosBoss", "MapInvocarBossCordY"))

        ReDim invocadores(1 To cantidadinvocadores) As Integer
        ReDim .CoordXInvocador(1 To cantidadinvocadores) As Byte
        ReDim .CoordYInvocador(1 To cantidadinvocadores) As Byte
    
        For loopX = 1 To cantidadinvocadores
            .CoordXInvocador(loopX) = GetVar(ubicacionArchivo, "DatosBoss", "InvocadorCoordX" & loopX)
            .CoordYInvocador(loopX) = GetVar(ubicacionArchivo, "DatosBoss", "InvocadorCoordY" & loopX)
        Next loopX
    End With

End Sub

Y a continuación de ese sub agregamos.... otra más...

Código:
Public Sub invocarBoss()
'**Código by Bramh**
'**7/10/2021**
    Dim loopZ As Long
    With datosBoss
        If MapData(.Mapa, .CoordXInvocador(1), .CoordYInvocador(1)).UserIndex > 0 And MapData(.Mapa, .CoordXInvocador(2), .CoordYInvocador(2)).UserIndex > 0 And MapData(.Mapa, .CoordXInvocador(3), .CoordYInvocador(3)).UserIndex > 0 And MapData(.Mapa, .CoordXInvocador(4), .CoordYInvocador(4)).UserIndex > 0 Then
        
            For loopZ = 1 To cantidadinvocadores
                invocadores(loopZ) = MapData(.Mapa, .CoordXInvocador(loopZ), .CoordYInvocador(loopZ)).UserIndex
            Next loopZ
        
            'Si no están muertos.....
            If (UserList(invocadores(1)).Flags.Muerto = 0) And UserList(invocadores(2)).Flags.Muerto = 0 And UserList(invocadores(3)).Flags.Muerto = 0 And UserList(invocadores(4)).Flags.Muerto = 0 And bossInvocadoIndex = 0 Then
                estadoBossClan = True
                Dim tmpWP As WorldPos
                tmpWP.map = .Mapa
                tmpWP.X = .CoordXBoss
                tmpWP.Y = .CoordYBoss

                '673 estadoBossClan index
                bossInvocadoIndex = SpawnNpc(.NumNpc, tmpWP, True, False)
                Call SendData(SendTarget.ToAll, 0, PrepareMessageConsoleMsg("Se ha invocado el boss de clanes, en Dungeon Hodor, vea el mapa para localizar el sitio!" & vbNewLine & "¡No dejes que saquen ventaja!" & vbNewLine & "¡Apúrate a ir!", FontTypeNames.FONTTYPE_CENTINELA))
            End If
        End If
    End With
End Sub

Luego buscamos.....
Código:
Sub MuereNpc(ByVal NpcIndex As Integer, ByVal UserIndex As Integer)
Luego de "IsPretoriano as Boolean"
agregamos
Código:
If estadoBossClan Then
        If NpcIndex = bossInvocadoIndex Then
            SendData SendTarget.toall, 0, PrepareMessageConsoleMsg(UserList(UserIndex).Name & " Ha derrotado al boss " & MiNPC.Name, FontTypeNames.FONTTYPE_CENTINELA)
            estadoBossClan = False
            dim tz as long
            For tz = 1 To 4
                If invocadores(tz) > 0 Then
                    UserList(invocadores(tz)).Stats.GLD = UserList(invocadores(tz)).Stats.GLD + 20000
                    WriteUpdateGold invocadores(tz)
                    Call WriteConsoleMsg(invocadores(tz), "Has recibido 20.000 monedas de oro como premio por derrotar al boss de clanes.", FontTypeNames.FONTTYPE_INFOBOLD)
                End If
            Next tz
        End If
    End If

Y buscamos.... en "Usuarios"
Código:
'<< Actualizamos clientes >>
        Call ChangeUserChar(UserIndex, .Char.Body, .Char.Head, .Char.heading, NingunArma, NingunEscudo, NingunCasco)
        Call WriteUpdateUserStats(UserIndex)
Y arriba de eso agregamos....
Código:
If estadoBossClan Then
            Dim iz as long
            For iz = 1 To 4
                Dim tmpN As String
                If invocadores(iz) > 0 Then
                    If invocadores(iz) = UserIndex Then
                        If UserList(invocadores(iz)).Flags.Muerto = 1 Then
                            'murieron todos, desaparece el npc
                            tmpN = Npclist(bossInvocadoIndex).Name
                            QuitarNPC bossInvocadoIndex
                            invocadores(iz) = 0
                            estadoBossClan = False
                        End If
                    End If
                End If
            Next iz
        
            If Not estadoBossClan Then
                bossInvocadoIndex = 0
            End If
        
            SendData SendTarget.toall, 0, PrepareMessageConsoleMsg("Uno de los 4 invocadores del " & tmpN & " de la zona de clanes ha muerto, la estadoBossClan desaparece hasta que otros 4 valientes guerreros quieran enfrentarle.", FontTypeNames.FONTTYPE_CENTINELA)
        End If

Y en "Sub CloseSocket(ByVal UserIndex As Integer)" debemos.... agregar....

abajo de

Código:
If UserIndex = LastUser Then
        Do Until UserList(LastUser).Flags.UserLogged
            LastUser = LastUser - 1
            If LastUser < 1 Then Exit Do
        Loop
    End If

Agregamos.....

Código:
    If estadoBossClan Then
        Dim zss As Long
        For zss = 1 To 4
            If (invocadores(zss) = UserIndex) Then
                estadoBossClan = False
                QuitarNPC bossInvocadoIndex
                invocadores(zss) = 0
            End If
        Next zss
    End If

    If Not estadoBossClan Then
        bossInvocadoIndex = 0
    End If

Eso es todo creo....

ahora lo más importante....

BossClanes.ini (Lo creamos en el Dat del Servidor).


Y la estructura es la siguiente....

Código:
[DatosBoss]
NumNpcBoss=673
MapInvocarBoss=190
MapInvocarBossCordX=59
MapInvocarBossCordY=23
CantidadInvocadores=4
InvocadorCoordX1=56
InvocadorCoordY1=21
InvocadorCoordX2=63
InvocadorCoordY2=21
InvocadorCoordX3=56
InvocadorCoordY3=26
InvocadorCoordX4=63
InvocadorCoordY4=26

Obviamente es simple de entender, el numero de npc, el mapa del npc donde se invoca, la coordX e Y donde se invoca el boss.
Luego los 4 invocadores y donde deben ponerse.


FUNCIONAL 100% SUPER TESTEADO

Boss desaparece al morir un invocador, al desconectar un invocador o al matar al boss y no deja crear 2 boss si ya hay uno invocado.


Listo por ahora, dps posteo un sistema super completo y funcional de quest por npc, saludos y espero que le sirva!

PD: POR FAVOR A LOS PROGRAMADORES MÁS CAPACITADOS QUE YO, APORTEN UNA MEJORA AL SISTEMA SI LE VEN COMO MEJORARLO, GRACIAS :D
 
Última edición:
M

Miembro

Invitado
Tip si te interesa...

Código:
'Créditos: @Gordis150 <3

Private Type Boss
    MapaBoss As WorldPos
End Type

Public datosBoss As Boss

Dim TempStr As String 'Temporal String
Dim Ascii as Byte 'Código Ascii para el separador

Ascii = Asc("-") 'Declaración del separador

Dim Leer As clsIniManager
Set Leer = New clsIniManager

Leer.Initialize "BossClanes.ini" 'Abrimos el archivo

'Leemos el valor
TempStr = vbNullString 'Reseteamos la variable temporal (para cada ves que se tenga que leer algo de este estilo)
TempStr = Leer.GetValue("DatosBoss", "MapaBoss") 'Leemos [DatosBoss] y luego la propiedad "MapaBoss" del archivo BossClanes.ini

datosBoss.MapaBoss.Map = General.ReadField(1, TempStr, Ascii) 'Leo el Mapa y separo con el separador
datosBoss.MapaBoss.X = General.ReadField(2, TempStr, Ascii) 'Leo la posición X
datosBoss.MapaBoss.Y = General.ReadField(3, TempStr, Ascii) 'Leo la posición Y

Set Leer = Nothing

En el BossClanes.ini

Código:
[DatosBoss]
MapaBoss=190-59-23

----------

Si no tienen el readfield (cosa rara) se los dejo:

Código:
Function ReadField(ByVal Pos As Integer, ByRef Text As String, ByVal SepASCII As Byte) As String
'*****************************************************************
'Author: Juan Martín Sotuyo Dodero (Maraxus)
'Last Modify Date: 11/15/2004
'Gets a field from a delimited string
'*****************************************************************

Dim i As Long
Dim lastPos As Long
Dim CurrentPos As Long
Dim delimiter As String * 1
   
delimiter = Chr$(SepASCII)
   
For i = 1 To Pos
    lastPos = CurrentPos
    CurrentPos = InStr(lastPos + 1, Text, delimiter, vbBinaryCompare)
Next i
   
If CurrentPos = 0 Then
    ReadField = mid$(Text, lastPos + 1, Len(Text) - lastPos)
Else
    ReadField = mid$(Text, lastPos + 1, CurrentPos - lastPos - 1)
End If

End Function

Lo mismo podrías aplicar a los usuarios (con o sin mapa), sin mapa sería:

Código:
InvocadorUnoCoord(0 To 1) As Byte

TempStr = vbNullString
TempStr = Leer.GetValue("DatosBoss", "InvocadorUnoCoord")

BossClanes.InvocadorUnoCoord(0) = val(General.ReadField(1, TempStr, Ascii))
BossClanes.InvocadorUnoCoord(1) = val(General.ReadField(2, TempStr, Ascii))

Y el el BossClanes.ini

Código:
InvocadorUnoCoord=56-21
 
Última edición por un moderador:

Bramhh

Fundador Evolutionao
Miembro del equipo
Moderador de AO
Moderador
Tip si te interesa...

Código:
'Créditos: @Gordis150 <3

Private Type Boss
    MapaBoss As WorldPos
End Type

Public datosBoss As Boss

Dim TempStr As String 'Temporal String
Dim Ascii as Byte 'Código Ascii para el separador

Ascii = Asc("-") 'Declaración del separador

Dim Leer As clsIniManager
Set Leer = New clsIniManager

Leer.Initialize "BossClanes.ini" 'Abrimos el archivo

'Leemos el valor
TempStr = vbNullString 'Reseteamos la variable temporal (para cada ves que se tenga que leer algo de este estilo)
TempStr = Leer.GetValue("DatosBoss", "MapaBoss") 'Leemos [DatosBoss] y luego la propiedad "MapaBoss" del archivo BossClanes.ini

datosBoss.MapaBoss.Map = General.ReadField(1, TempStr, Ascii) 'Leo el Mapa y separo con el separador
datosBoss.MapaBoss.X = General.ReadField(2, TempStr, Ascii) 'Leo la posición X
datosBoss.MapaBoss.Y = General.ReadField(3, TempStr, Ascii) 'Leo la posición Y

Set Leer = Nothing

En el BossClanes.ini

Código:
[DatosBoss]
MapaBoss=190-59-23

----------

Si no tienen el readfield (cosa rara) se los dejo:

Código:
Function ReadField(ByVal Pos As Integer, ByRef Text As String, ByVal SepASCII As Byte) As String
'*****************************************************************
'Author: Juan Martín Sotuyo Dodero (Maraxus)
'Last Modify Date: 11/15/2004
'Gets a field from a delimited string
'*****************************************************************

Dim i As Long
Dim lastPos As Long
Dim CurrentPos As Long
Dim delimiter As String * 1
  
delimiter = Chr$(SepASCII)
  
For i = 1 To Pos
    lastPos = CurrentPos
    CurrentPos = InStr(lastPos + 1, Text, delimiter, vbBinaryCompare)
Next i
  
If CurrentPos = 0 Then
    ReadField = mid$(Text, lastPos + 1, Len(Text) - lastPos)
Else
    ReadField = mid$(Text, lastPos + 1, CurrentPos - lastPos - 1)
End If

End Function

Lo mismo podrías aplicar a los usuarios (con o sin mapa), sin mapa sería:

Código:
InvocadorUnoCoord(0 To 1) As Byte

TempStr = vbNullString
TempStr = Leer.GetValue("DatosBoss", "InvocadorUnoCoord")

BossClanes.InvocadorUnoCoord(0) = val(General.ReadField(1, TempStr, Ascii))
BossClanes.InvocadorUnoCoord(1) = val(General.ReadField(2, TempStr, Ascii))

Y el el BossClanes.ini

Código:
InvocadorUnoCoord=56-21
Ah es una alternativa para leer los datos, me gusta, gracias, +10 a eso
 

CUICUI

Inmortal Lvl 8
SendData SendTarget.toall, 0, PrepareMessageConsoleMsg("Se ha invocado el boss de clanes, en Dungeon Hodor, vea el mapa para localizar el sitio!", FontTypeNames.FONTTYPE_CENTINELA)
SendData SendTarget.toall, 0, PrepareMessageConsoleMsg("¡No dejes que saquen ventaja!", FontTypeNames.FONTTYPE_CITIZEN)
SendData SendTarget.toall, 0, PrepareMessageConsoleMsg("¡Apúrate a ir!", FontTypeNames.FONTTYPE_CITIZEN)

por que en vez de 3 llamados al SendData no haces simplemente así?:
Código:
Call SendData(SendTarget.ToAll, 0, PrepareMessageConsoleMsg("Se ha invocado el boss de clanes, en Dungeon Hodor, vea el mapa para localizar el sitio!" & vbNewLine & "¡No dejes que saquen ventaja!" & vbNewLine & "¡Apúrate a ir!", FontTypeNames.FONTTYPE_CENTINELA))
 

Bramhh

Fundador Evolutionao
Miembro del equipo
Moderador de AO
Moderador
por que en vez de 3 llamados al SendData no haces simplemente así?:
Código:
Call SendData(SendTarget.ToAll, 0, PrepareMessageConsoleMsg("Se ha invocado el boss de clanes, en Dungeon Hodor, vea el mapa para localizar el sitio!" & vbNewLine & "¡No dejes que saquen ventaja!" & vbNewLine & "¡Apúrate a ir!", FontTypeNames.FONTTYPE_CENTINELA))
Opa!, muchas gracias, lo aplico +1 para aplicar al sistema

PD: se me paso ese dato no menor, ahí edito
 
Última edición:
Arriba