diff --git a/Codigo/AI_NPC.bas b/Codigo/AI_NPC.bas index ab0ffb9d..cb72a7fa 100644 --- a/Codigo/AI_NPC.bas +++ b/Codigo/AI_NPC.bas @@ -600,9 +600,7 @@ Private Sub AI_AtacarUsuarioObjetivo(ByVal AtackerNpcIndex As Integer) Call AnimacionIdle(AtackerNpcIndex, True) If UserIndexFront > 0 Then If UserList(UserIndexFront).flags.Muerto = 0 Then - If UserList(UserIndexFront).Faccion.Status = 1 And (.NPCtype = e_NPCType.GuardiaReal) Then - - Else + If EsEnemigo(AtackerNpcIndex, UserIndexFront) Then Call NpcAtacaUser(AtackerNpcIndex, UserIndexFront, tHeading) End If End If @@ -1281,22 +1279,26 @@ Private Function EsEnemigo(ByVal NpcIndex As Integer, ByVal UserIndex As Integer 100 If NpcIndex = 0 Or UserIndex = 0 Then Exit Function -102 With NpcList(NpcIndex) + EsEnemigo = True +102 With NpcList(NpcIndex) + ' Si el NPC tiene un atacante 104 If .flags.AttackedBy <> vbNullString Then + ' Si el usuario actual es el atacante 106 EsEnemigo = (UserIndex = NameIndex(.flags.AttackedBy).ArrayIndex) 108 If EsEnemigo Then Exit Function + ' Si no es el atacante, preguntamos si el NPC puede atacarlo +109 EsEnemigo = CanAttackNotOwner(NpcIndex, UserIndex) End If 110 Select Case .flags.AIAlineacion Case e_Alineacion.Real -112 EsEnemigo = (Status(UserIndex) Mod 2) <> 1 +112 EsEnemigo = EsEnemigo And (Status(UserIndex) Mod 2) <> 1 114 Case e_Alineacion.Caos -116 EsEnemigo = (Status(UserIndex) Mod 2) <> 0 +116 EsEnemigo = EsEnemigo And (Status(UserIndex) Mod 2) <> 0 118 Case e_Alineacion.ninguna -120 EsEnemigo = True ' Ok. No hay nada especial para hacer, cualquiera puede ser enemigo! End Select diff --git a/Codigo/Admin.bas b/Codigo/Admin.bas index ac3eb30d..c44d2816 100644 --- a/Codigo/Admin.bas +++ b/Codigo/Admin.bas @@ -93,6 +93,7 @@ Public IntervaloMagiaGolpe As Long Public IntervaloGolpeMagia As Long Public IntervaloUserPuedeCastear As Long Public IntervaloTrabajarExtraer As Long +Public IntervaloNpcOwner As Long Public IntervaloTrabajarConstruir As Long diff --git a/Codigo/Declares.bas b/Codigo/Declares.bas index 84c683e1..b447ddcb 100644 --- a/Codigo/Declares.bas +++ b/Codigo/Declares.bas @@ -2553,6 +2553,7 @@ Public Type t_NPCFlags ' UseAINow As Boolean No se usa, borrar de la DB!!!! Sound As Integer AttackedBy As String + AttackedTime As Long AttackedFirstBy As String backup As Byte RespawnOrigPos As Byte diff --git a/Codigo/EffectProvoked.cls b/Codigo/EffectProvoked.cls index e5b1f616..bf53535d 100644 --- a/Codigo/EffectProvoked.cls +++ b/Codigo/EffectProvoked.cls @@ -68,6 +68,7 @@ Public Sub Setup(ByVal SourceIndex As Integer, ByVal SourceType As e_ReferenceTy If SourceType = eUser Then Call SetUserRef(NpcList(TargetIndex).TargetUser, SourceIndex) NpcList(TargetIndex).flags.AttackedBy = UserList(SourceIndex).name + NpcList(TargetIndex).flags.AttackedTime = GetTickCount Else Call SetNpcRef(NpcList(TargetIndex).TargetNPC, SourceIndex) End If diff --git a/Codigo/FileIO.bas b/Codigo/FileIO.bas index 030cb748..f54c469e 100644 --- a/Codigo/FileIO.bas +++ b/Codigo/FileIO.bas @@ -2701,6 +2701,7 @@ Sub LoadIntervalos() 'TODO : Agregar estos intervalos al form!!! 206 IntervaloMagiaGolpe = val(Lector.GetValue("INTERVALOS", "IntervaloMagiaGolpe")) 208 IntervaloGolpeMagia = val(Lector.GetValue("INTERVALOS", "IntervaloGolpeMagia")) +209 IntervaloNpcOwner = val(Lector.GetValue("INTERVALOS", "IntervaloNpcOwner", "10000")) 'frmMain.tLluvia.Interval = val(Lector.GetValue("INTERVALOS", "IntervaloPerdidaStaminaLluvia")) 'FrmInterv.txtIntervaloPerdidaStaminaLluvia.Text = frmMain.tLluvia.Interval diff --git a/Codigo/FrmInterv.frm b/Codigo/FrmInterv.frm index 31d914cd..85f73569 100644 --- a/Codigo/FrmInterv.frm +++ b/Codigo/FrmInterv.frm @@ -896,6 +896,7 @@ Private Sub Command2_Click() 140 Call WriteVar(IniPath & "intervalo.ini", "INTERVALOS", "IntervaloTrabajarExtraer", CStr(IntervaloTrabajarExtraer)) 142 Call WriteVar(IniPath & "intervalo.ini", "INTERVALOS", "IntervaloTrabajarConstruir", CStr(IntervaloTrabajarConstruir)) 144 Call WriteVar(IniPath & "intervalo.ini", "INTERVALOS", "IntervaloUserPuedeAtacar", CStr(IntervaloUserPuedeAtacar)) +145 Call WriteVar(IniPath & "intervalo.ini", "INTERVALOS", "IntervaloNpcOwner", CStr(IntervaloNpcOwner)) 'Call WriteVar(IniPath & "intervalo.ini", "INTERVALOS", "IntervaloPerdidaStaminaLluvia", frmMain.tLluvia.Interval) 146 MsgBox "Los intervalos se han guardado sin problemas" diff --git a/Codigo/GameLogic.bas b/Codigo/GameLogic.bas index 63ed448b..631c4ebd 100644 --- a/Codigo/GameLogic.bas +++ b/Codigo/GameLogic.bas @@ -1587,6 +1587,10 @@ Sub LookatTile(ByVal UserIndex As Integer, ByVal Map As Integer, ByVal X As Inte End If End If + + If EsGM(UserIndex) And GetOwnedBy(TempCharIndex) <> 0 Then + estatus = estatus & " | Owned by " & NpcList(TempCharIndex).flags.AttackedBy + End If 456 estatus = estatus & ">" diff --git a/Codigo/MODULO_NPCs.bas b/Codigo/MODULO_NPCs.bas index 01a923ed..971a7dd7 100644 --- a/Codigo/MODULO_NPCs.bas +++ b/Codigo/MODULO_NPCs.bas @@ -319,6 +319,7 @@ Sub ResetNpcFlags(ByVal NpcIndex As Integer) 102 .AfectaParalisis = 0 104 .AguaValida = 0 106 .AttackedBy = vbNullString +107 .AttackedTime = 0 108 .AttackedFirstBy = vbNullString 112 .backup = 0 116 .Domable = 0 @@ -1674,6 +1675,7 @@ Sub DoFollow(ByVal NpcIndex As Integer, ByVal UserName As String) player = NameIndex(username) If IsValidUserRef(player) Then 114 .flags.AttackedBy = username +115 .flags.AttackedTime = GetTickCount 116 .targetUser = player 118 .flags.Follow = True 120 Call SetMovement(NpcIndex, e_TipoAI.NpcDefensa) @@ -2134,36 +2136,26 @@ UserCanAttackNpc.TurnPK = False End If If NpcList(NpcIndex).flags.team = 0 Then - If NpcList(NpcIndex).flags.AttackedBy <> "" Then - Dim CurrentOwner As t_UserReference - Dim CurrentOwnerIndex As Integer - Dim AttackedNpcIndex As Integer - - CurrentOwner = NameIndex(NpcList(NpcIndex).flags.AttackedBy) - If IsValidUserRef(CurrentOwner) Then - CurrentOwnerIndex = CurrentOwner.ArrayIndex - - If CurrentOwnerIndex <> UserIndex And IsValidNpcRef(UserList(CurrentOwnerIndex).flags.NPCAtacado) Then - If UserList(CurrentOwnerIndex).flags.NPCAtacado.ArrayIndex = NpcIndex And _ - UserList(CurrentOwnerIndex).flags.Muerto = 0 And _ - (Status(CurrentOwnerIndex) = Ciudadano Or Status(CurrentOwnerIndex) = Armada Or Status(CurrentOwnerIndex) = Consejo) And _ - Distancia(UserList(CurrentOwnerIndex).pos, UserList(UserIndex).pos) <= 12 And _ - (UserList(UserIndex).GuildIndex = 0 Or UserList(UserIndex).GuildIndex <> UserList(CurrentOwnerIndex).GuildIndex) And _ - (UserList(UserIndex).Grupo.EnGrupo = False Or UserList(UserIndex).Grupo.id <> UserList(CurrentOwnerIndex).Grupo.id) Then - - - If UserList(UserIndex).flags.Seguro Then - UserCanAttackNpc.result = eRemoveSafeCitizenNpc - Exit Function - Else - UserCanAttackNpc.TurnPK = True - UserCanAttackNpc.CanAttack = True - UserCanAttackNpc.result = eAttackCitizenNpc - Exit Function - End If - End If - End If - End If + Dim CurrentOwnerIndex As Integer: CurrentOwnerIndex = GetOwnedBy(NpcIndex) + If CurrentOwnerIndex <> 0 Then + If CurrentOwnerIndex <> UserIndex And IsValidNpcRef(UserList(CurrentOwnerIndex).flags.NPCAtacado) Then + If UserList(CurrentOwnerIndex).flags.NPCAtacado.ArrayIndex = NpcIndex And _ + UserList(CurrentOwnerIndex).flags.Muerto = 0 And _ + (Status(CurrentOwnerIndex) = Ciudadano Or Status(CurrentOwnerIndex) = Armada Or Status(CurrentOwnerIndex) = consejo) And _ + (UserList(UserIndex).GuildIndex = 0 Or UserList(UserIndex).GuildIndex <> UserList(CurrentOwnerIndex).GuildIndex) And _ + (UserList(UserIndex).Grupo.EnGrupo = False Or UserList(UserIndex).Grupo.Id <> UserList(CurrentOwnerIndex).Grupo.Id) Then + + If UserList(UserIndex).flags.Seguro Then + UserCanAttackNpc.Result = eRemoveSafeCitizenNpc + Exit Function + Else + UserCanAttackNpc.TurnPK = True + UserCanAttackNpc.CanAttack = True + UserCanAttackNpc.Result = eAttackCitizenNpc + Exit Function + End If + End If + End If End If End If End If @@ -2386,3 +2378,30 @@ Public Function GetDefenseBonus(ByVal NpcIndex As Integer) As Integer GetDefenseBonus = NpcList(NpcIndex).Modifiers.DefenseBonus End Function +' Retorna el usuario que esta atacando al NPC actualmente (medido con tiempo) +Public Function GetOwnedBy(ByVal NpcIndex As Integer) As Integer + GetOwnedBy = 0 + With NpcList(NpcIndex).flags + If .AttackedBy = vbNullString Then Exit Function + If GetTickCount - .AttackedTime > IntervaloNpcOwner Then Exit Function + Dim Attacker As t_UserReference: Attacker = NameIndex(.AttackedBy) + If Not IsValidUserRef(Attacker) Then Exit Function + GetOwnedBy = Attacker.ArrayIndex + End With +End Function + +' Retorna si un NPC puede atacar un usuario diferente al que lo esta atacando +Public Function CanAttackNotOwner(ByVal NpcIndex As Integer, ByVal UserIndex As Integer) As Boolean + Dim AttackResult As t_AttackInteractionResult + AttackResult = UserCanAttackNpc(UserIndex, NpcIndex) + + ' Si el usuario puede atacar al NPC + If AttackResult.CanAttack Then + ' Lo atacamos solo si puede atacar sin hacerse PK (no lo forzamos a hacerse PK) + CanAttackNotOwner = AttackResult.TurnPK + Else + ' En caso que el usuario no pueda atacar al NPC, este debe ignorarlo a el + ' Excepto que no pueda atacar por los siguientes motivos: esta montado, esta fuera de su campo de vision + CanAttackNotOwner = AttackResult.Result = eMounted Or AttackResult.Result = eOutOfRange + End If +End Function diff --git a/Codigo/Modulo_UsUaRiOs.bas b/Codigo/Modulo_UsUaRiOs.bas index 91679342..67eec5b1 100644 --- a/Codigo/Modulo_UsUaRiOs.bas +++ b/Codigo/Modulo_UsUaRiOs.bas @@ -1934,7 +1934,10 @@ Sub NPCAtacado(ByVal NpcIndex As Integer, ByVal UserIndex As Integer, Optional B 104 If Not IsSet(NpcList(npcIndex).flags.StatusMask, eTaunted) And NpcList(npcIndex).Movement <> Estatico And NpcList(npcIndex).flags.AttackedFirstBy = vbNullString Then 106 Call SetUserRef(NpcList(npcIndex).TargetUser, UserIndex) 108 NpcList(NpcIndex).Hostile = 1 -110 If AffectsOwner Then NpcList(NpcIndex).flags.AttackedBy = UserList(UserIndex).name +110 If AffectsOwner Then + NpcList(NpcIndex).flags.AttackedBy = UserList(UserIndex).name + NpcList(NpcIndex).flags.AttackedTime = GetTickCount + End If End If 'Guarda el NPC que estas atacando ahora. diff --git a/Codigo/Protocol.bas b/Codigo/Protocol.bas index 99a3a626..b83a3a12 100644 --- a/Codigo/Protocol.bas +++ b/Codigo/Protocol.bas @@ -3294,7 +3294,7 @@ Private Sub HandleWorkLeftClick(ByVal UserIndex As Integer) Exit Sub End If -564 If LenB(NpcList(tN).flags.AttackedBy) <> 0 Then +564 If GetOwnedBy(tN) <> 0 Then 566 Call WriteConsoleMsg(UserIndex, "No puedes domar una criatura que esta luchando con un jugador.", e_FontTypeNames.FONTTYPE_INFO) Exit Sub End If diff --git a/Codigo/SistemaCombate.bas b/Codigo/SistemaCombate.bas index c092d533..0fc1700a 100644 --- a/Codigo/SistemaCombate.bas +++ b/Codigo/SistemaCombate.bas @@ -2081,6 +2081,7 @@ Sub AllMascotasAtacanUser(ByVal victim As Integer, ByVal Maestro As Integer) If IsValidNpcRef(.MascotasIndex(iCount)) Then 108 If IsSet(NpcList(mascotaIndex).flags.BehaviorFlags, e_BehaviorFlags.eAttackUsers) Then 110 NpcList(mascotaIndex).flags.AttackedBy = UserList(victim).Name +111 NpcList(mascotaIndex).flags.AttackedTime = GetTickCount 112 Call SetUserRef(NpcList(mascotaIndex).TargetUser, victim) 114 Call SetMovement(mascotaIndex, e_TipoAI.NpcDefensa) 116 NpcList(mascotaIndex).Hostile = 0 @@ -2126,6 +2127,7 @@ Public Sub AllMascotasAtacanNPC(ByVal NpcIndex As Integer, ByVal UserIndex As In 110 Call SetNpcRef(.TargetNPC, NpcIndex) 112 Call SetMovement(mascotaIdx, e_TipoAI.NpcAtacaNpc) NpcList(NpcIndex).flags.AttackedBy = UserList(UserIndex).name + NpcList(NpcIndex).flags.AttackedTime = GetTickCount Call SetNpcRef(UserList(UserIndex).flags.NPCAtacado, NpcIndex) End If End With diff --git a/Codigo/clsIniManager.cls b/Codigo/clsIniManager.cls index fd6025f9..745bea04 100644 --- a/Codigo/clsIniManager.cls +++ b/Codigo/clsIniManager.cls @@ -371,9 +371,10 @@ End Sub ' ' @param Main The name of the main section in which we will be searching. ' @param key The key of the value we are looking for. +' @param DefaultValue Default value if key is not found. ' @returns The value asociated with the given key under the requeted main section of the INI file or a null string if it's not found. -Public Function GetValue(ByVal Main As String, ByVal Key As String) +Public Function GetValue(ByVal Main As String, ByVal key As String, Optional ByVal DefaultValue As String = "") As String On Error GoTo GetValue_Err @@ -385,7 +386,6 @@ Public Function GetValue(ByVal Main As String, ByVal Key As String) '************************************************************** Dim i As Long Dim j As Long - Dim retval As String 'Search for the main node i = FindMain(UCase$(Main)) @@ -396,9 +396,11 @@ Public Function GetValue(ByVal Main As String, ByVal Key As String) j = FindKey(fileData(i), UCase$(Key)) 'If we found it we return it - If j >= 0 Then retval = fileData(i).values(j).Value - - GetValue = retval + If j >= 0 Then + GetValue = fileData(i).values(j).Value + Else + GetValue = DefaultValue + End If End If diff --git a/intervalos.ini b/intervalos.ini index 8929b6d0..4fc680fb 100644 --- a/intervalos.ini +++ b/intervalos.ini @@ -17,6 +17,7 @@ IntervaloFrio=75 IntervaloWAVFX=190 IntervaloMover=200 IntervaloNpcAI=150 +IntervaloNpcOwner=10000 IntervaloTrabajarExtraer=3000 IntervaloTrabajarConstruir=500 IntervaloWS=180 'Cantidad de minutos