FANDOM


;   THIS SCRIPT IS COPYRIGHT(c) 2009 Reality Crafters LLC. ALL RIGHTS RESERVER. 

;   Written By: Robert 'UUICEO' Quackenbush
;
;   This is the BASE Script which Script Crafters Workshop Attack Tab will be based off.
;   You are not permitted to share this script with ANYONE including other owners of
;   Script Crafters Workshop.
Using "RC_Core.rcm"

Dim AIData%(1, 10)
Dim EffectData%(1, 17)
Dim Moral%(1)
Dim NonWeaponDMG%(1, 1) ; The min/max amount of damage the mob can do for the attack type
Dim AnimType$(1) ; The animation the mob will use this combat round
Dim MaxAbilitiesKnown(1) ; Total # of abilities the mob knows
Dim AbilityNames$(1, 20) ; Up to 20 abilities per mob
Dim AbilityData%(1, 20, 1) ; If ability has range requirements they will be here

Function Main()

    Attacker = Actor()
    Target = Contextactor()
    MaxLevelDiff% = 10
    LevelDiff% = CheckLevelDiff%(Attacker, Target, MaxLevelDiff%)
    If LevelDiff% = -1 Then
        If ActorLevel(Attacker) > ActorLevel(Target) Then
            Output(Attacker, "You are too high a level to attack that.")
        Else
            Output(Attacker, "You are too low a level to attack that.")
        EndIf
        Return
    EndIf
    AttackerHealth% = Attribute(Attacker, "Health")
    TargetHealth% = Attribute(Target, "Health")
    AddActorEffect(Attacker, "Combat", "", 0, 2, 232)
    AddActorEffect(Target, "Combat", "", 0, 2, 232)
    AttackerHasEffect% = CheckEffect%(Attacker, 0)
    TargetHasEffect% = CheckEffect%(Target, 1)
    AIState% = CheckAI%(Attacker, Target)
    CombatActive% = CheckCombatActive%(Attacker, Target)
    InRange% = CheckDistance%(Attacker, Target)
    AttWeapon$ = ItemName(ActorWeapon(Attacker))
    TarWeapon$ = ItemName(ActorWeapon(Target))
    GetCombatAnimation(AttWeapon$, TarWeapon$, Attacker, Target)

    Retreating = UpdateAI%(Attacker, Target, AIState%) ; Increase or Decrease the combat
;                                                        effectiveness according to the
;                                                        position the AI is in.

    AttackerDefence% = CalculateDefenceValue%(Attacker, CombatActive%)
    TargetDefence% = CalculateDefenceValue%(Target, CombatActive%)
    Attacker_AttackValue% = CalculateAttackValue%(Attacker) + Moral%(0)
    Target_AttackValue% = CalculateAttackValue%(Target) + Moral%(1)
    Attacker_AdjustedAttackValue% = (Attacker_AttackValue% - (TargetDefence% / 4)) + Rand(-15, 15)
    Target_AdjustedAttackValue% = (Target_AttackValue% - (AttackerDefence% / 4)) + Rand(-15, 15)
    If Attacker_AdjustedAttackValue% > TargetDefence% Then
        AttackerHit% = 1
        If AIState% = 2 Or AIState% = 3
            CheckClass(Attacker, 0)
        EndIf
    Else
        AttackerHit% = 0
    EndIf
    If AttackerHit% = 1 And (AIState% = 2 Or AIState% = 3) And Retreating <> 1 Then
        If Rand(1, 100) < 51 Then
            AUsingAbility = UseAbility%(Attacker, Target, AIState%, 0)
        EndIf
    EndIf
    If Target_AdjustedAttackValue% > AttackerDefence% Then
        TargetHit% = 1
        If AIState% = 1 Or AIState% = 3
            CheckClass(Target, 1)
        EndIf
    Else
        TargetHit% = 0
    EndIf
    If TargetHit% = 1 And (AIState% = 1 Or AIState% = 3) And Retreating <> 11 Then
        If Rand(1, 100) < 51 Then
            TUsingAbility = UseAbility%(Attacker, Target, AIState%, 1)
        EndIf
    EndIf
    If AttackerHit% = 1 And AUsingAbility = 0 Then
        MaxDmg% = ItemDamage(ActorWeapon(Attacker)) + NonWeaponDMG%(0, 1) + Moral%(0) + Int(Attribute(Attacker, "Strength") / 4)
        MinDmg% = 1
        If NonWeaponDMG%(0, 0) > 0 Then
            MinDmg% = NonWeaponDMG%(0, 0)
        EndIf
        AnimateActor(Attacker, AnimType$(0), 1.0)
        DamageDealt% = Rand(MinDmg%, MaxDmg%)
        If DamageDealt% > 0 Then
            CreateFloatingNumber(Target, -DamageDealt%, 25, 200, 200)
            Output(Attacker, "You hit " + Name(Target) + " for " + DamageDealt% + " Damage.", 20, 250, 10)
            Output(Target, "You were hit by " + Name(Attacker) + " for " + DamageDealt% + " Damage.", 20, 250, 10)
            If TargetHealth% <= DamageDealt% Then
                TargetKilled% = 1
            Else
                TargetKilled% = 0
                SetAttribute(Target, "Health", Attribute(Target, "Health") - DamageDealt)
            EndIf
        Else
            Output(Attacker, "You missed.")
        EndIf
    Else
;        AnimateActor(Attacker, AnimType$(0), 1.0)
;        Output(Attacker, "You missed.")
    EndIf

    If TargetHit% = 1 And CombatActive% = 1 And TUsingAbility = 0 Then
        MaxDmg% = ItemDamage(ActorWeapon(Target)) + NonWeaponDMG%(1, 1) + Moral%(1) + Int(Attribute(Target, "Strength") / 4)
        MinDmg% = 1
        If NonWeaponDMG%(1, 0) > 0 Then
            MinDmg% = NonWeaponDMG%(1, 0)
        EndIf
        AnimateActor(Target, AnimType$(1), 1.0)
        DamageDealt% = Rand(MinDmg%, MaxDmg%)
        If DamageDealt% > 0 Then
            CreateFloatingNumber(Attacker, -DamageDealt%, 25, 200, 200)
            Output(Target, "You hit " + Name(Attacker) + " for " + DamageDealt% + " Damage.", 20, 250, 10)
            Output(Attacker, "You were hit by " + Name(Target) + " for " + DamageDealt% + " Damage.", 20, 250, 10)
            If AttackerHealth% <= DamageDealt% Then
                AttackerKilled% = 1
            Else
                AttackerKilled% = 0
                SetAttribute(Attacker, "Health", Attribute(Attacker, "Health") - DamageDealt)
            EndIf
        Else
            Output(Target, "You missed.")
        EndIf
    Else
;        AnimateActor(Target, AnimType$(1), 1.0)
;        Output(Target, "You missed.")
    EndIf
    If TargetKilled% = 1 Then
;        Output(Attacker, "You killed " + Name(Target) + "!", 25, 150, 100)
        Output(Target, "You were killed by " + Name(Attacker) + "!", 25, 200, 50)
        GiveKillXP(Target, Attacker)
        LootDrop(Attacker, Target, 1, Attacker)
        KillActor(Target, Attacker)
    EndIf
    If AttackerKilled% = 1 Then
;        Output(Target, "You killed " + Name(Attacker) + "!", 25, 150, 100)
        Output(Attacker, "You were killed by " + Name(Target) + "!", 25, 200, 50)
        GiveKillXP(Attacker, Target)
        LootDrop(Attacker, Target, 0, Target)
        KillActor(Attacker, Target)
    EndIf

End Function

; Determine which animation the actors will use when in combat
Function GetCombatAnimation(AttWeapon$, TarWeapon$, fAttacker, fTarget)

    Pass = -1
    Repeat

        Pass = Pass + 1
        If Pass = 1 Then
            Check = ItemWeaponType(TarWeapon$)
        Else
            Check = ItemWeaponType(AttWeapon$)
        EndIf

        Select Check
       
           Case 0

                AnimType$(Pass) = "Default attack"
           
           Case 1

                AnimType$(Pass) = "Right hand attack"

            Case 2

                AnimType$(Pass) = "Two hand attack"

            Case 3
           
                AnimType$(Pass) = "Bow attack"
           
        End Select

    Until Pass = 1
       
End Function

; Determine what class each actor is and get any special info for that class
Function CheckClass(fCurrentActor, WHO%)

    AC$ = Lower(Class(fCurrentActor))
   
    Select AC$
       
        Case "dog"
           
            AIData%(WHO%, 0) = 1 ; Treasure type 1 (small furry animals)
            AnimType$(WHO%) = "Bite"
            If Name(fCurrentActor) = "Attack Dog" Then
                NonWeaponDMG%(WHO%, 0) = 3
                NonWeaponDMG%(WHO%, 1) = 10
            EndIf
           
        Case "spider"

            MaxAbilitiesKnown(WHO%) = 1
            AIData%(WHO%, 0) = 2 ; Treasure type 2 (Arachnid)
            AnimType$(WHO%) = "Bite"
            If Name(fCurrentActor) = "Spider" Then
                NonWeaponDMG%(WHO%, 0) = 5
                NonWeaponDMG%(WHO%, 1) = 15
            EndIf
       
        Case "none"

            NonWeaponDMG%(WHO%, 0) = 5
            NonWeaponDMG%(WHO%, 1) = 25
           
        Case "ant"
       
            AIData%(WHO%, 0) = 3 ; Treasure type 3 (Ant)
            AnimType$(WHO%) = "Bite"
            If Name(fCurrentActor) = "Black Ant" Then
                MaxAbilitiesKnown(WHO%) = 0
                NonWeaponDMG%(WHO%, 0) = 1
                NonWeaponDMG%(WHO%, 1) = 3
            EndIf
            If Name(fCurrentActor) = "Red Ant" Then

                MaxAbilitiesKnown(WHO%) = 1
                AbilityNames$(WHO%, 1) = "Flame Breath"
                AbilityData%(WHO%, 1, 0) = 1 ; Ability Minimum Range
                AbilityData%(WHO%, 1, 1) = 10; Ability Maximum Range

                NonWeaponDMG%(WHO%, 0) = 3
                NonWeaponDMG%(WHO%, 1) = 6
            EndIf

    End Select

End Function

Function CheckEffect%(fCurrentActor, WHO%)

; Only add actual 'ACTOR EFFECTS' here. Those are things that give an effect to the actor
; from some other item or spell.  These things usually give an Effect Icon on the players
; screen. Such items would include drinking a 'Strength' Potion or getting a 'Blessing'
; spell cast on you. These should be things that have an extended duration like a potion
; to increase your Dexterity for 5 minutes rather than an immediate effect that goes away
; right away (such as a heal potion).

; *** PLEASE NOTE ***
; Anything lised below should not be automatically handled by the Effect (Such as a
; Strength Effect). If your strength effect does more than increase the strength of the
; effected person then it is OK to add it in.. but if it only effects the strength of the
; effected person then there is no need to add it in here because the addeffect command
; will handle adding and removing the bonus to the effected player and nothing else need
; be done.  But, If you wanted to increase a players attack as well as their strength
; with a Strength potion/spell then you would need to add it in here and also add
; everything but the Strength part that the effect is going to imbue to the effected.

    If ActorHasEffect(fCurrentActor, "Defence")
        RtnValue% = 1
        EffectData%(WHO%, 1) = 5
    EndIf
    If ActorHasEffect(fCurrentActor, "Strength")
        RtnValue% = RtnValue% + 2
        EffectData%(WHO%, 2) = 3
    EndIf
    If ActorHasEffect(fCurrentActor, "Dexterity")
        RtnValue% = RtnValue% + 4
        EffectData%(WHO%, 3) = 0
    EndIf
    If ActorHasEffect(fCurrentActor, "Dodge")
        RtnValue% = RtnValue% + 8
        EffectData%(WHO%, 4) = 0
    EndIf
    If ActorHasEffect(fCurrentActor, "Speed")
        RtnValue% = RtnValue% + 16
        EffectData%(WHO%, 5) = 0
    EndIf
    If ActorHasEffect(fCurrentActor, "Shield")
        RtnValue% = RtnValue% + 32
        EffectData%(WHO%, 6) = 0
    EndIf
    If ActorHasEffect(fCurrentActor, "Blessing")
        RtnValue% = RtnValue% + 64
        EffectData%(WHO%, 7) = 0
    EndIf
    If ActorHasEffect(fCurrentActor, "Sleep")
        RtnValue% = RtnValue% + 128
        EffectData%(WHO%, 8) = 1
    EndIf
    If ActorHasEffect(fCurrentActor, "Stun")
        RtnValue% = RtnValue% + 256
        EffectData%(WHO%, 9) = 1
    EndIf
    If ActorHasEffect(fCurrentActor, "UnUsed")
        RtnValue% = RtnValue% + 512
        EffectData%(WHO%, 10) = 0
    EndIf
    If ActorHasEffect(fCurrentActor, "UnUsed")
        RtnValue% = RtnValue% + 1024
        EffectData%(WHO%, 11) = 0
    EndIf
    If ActorHasEffect(fCurrentActor, "UnUsed")
        RtnValue% = RtnValue% + 2048
        EffectData%(WHO%, 12) = 0
    EndIf
    If ActorHasEffect(fCurrentActor, "UnUsed")
        RtnValue% = RtnValue% + 4096
        EffectData%(WHO%, 13) = 0
    EndIf
    If ActorHasEffect(fCurrentActor, "UnUsed")
        RtnValue% = RtnValue% + 8192
        EffectData%(WHO%, 14) = 0
    EndIf
    If ActorHasEffect(fCurrentActor, "UnUsed")
        RtnValue% = RtnValue% + 16384
        EffectData%(WHO%, 15) = 0
    EndIf
    If ActorHasEffect(fCurrentActor, "UnUsed")
        RtnValue% = RtnValue% + 32768
        EffectData%(WHO%, 16) = 0
    EndIf
    If ActorHasEffect(fCurrentActor, "UnUsed")
        RtnValue% = RtnValue% + 65536
        EffectData%(WHO%, 17) = 0
    EndIf
    Return(RtnValue%)

End Function

; Check to ensure the levels of Attacker and Target are within the allowed range
Function CheckLevelDiff%(fAttacker, fTarget, MaxLevelDiff)

    If Abs(ActorLevel(fAttacker) - ActorLevel(fTarget)) > MaxLevelDiff Then
        Return(-1)
    Else
        Return(Abs(ActorLevel(fAttacker) - ActorLevel(fTarget)))
    EndIf

End Function

; Check to see if Target and Attacker have targeted each other. If so then combat is active
Function CheckCombatActive%(fAttacker, fTarget)

; If Target has targeted the attacker and vise-versa
; then we can assume the combat is active.

    If ActorTarget(fTarget) = fAttacker And ActorTarget(fAttacker) = fTarget Then
        Return(True)
    Else
        Return(False)
    EndIf

End Function

; Check the distance between Attacker and Target to determine if they are within weapons range
Function CheckDistance%(fAttacker, fTarget)

       ActualDistance% = ActorDistance(fAttacker, fTarget) ; Actual distance between attacker and defender
       AttackRange% = ItemRange(ActorWeapon(fAttacker)) ; Weapon range of attacker
       DefenderRange% = ItemRange(ActorWeapon(fTarget)) ; Weapon range of defender
       If AttackerRange% <= ActualDistance% Then
              Amin% = 1 ; Attacker Weapon is in range
       Else
              Amin% = 0 ; Attacker Weapon is not in range
       EndIf
       If DefenderRange% <= ActualDistance% Then
              If Amin% = 1 Then
                     Return(3) ; Both Attacker and Target weapons are in range
              Else
                     Return(2) ; Only Defender weapon is in range
              EndIf
       Else
              Return(Amin%)
       EndIf
End Function

; Determin Base defence value based on current actors 'speed', defence, dexterity
; + (amulet & ring values) + all armor values
Function CalculateDefenceValue%(fCurrentActor, fCombatActive%)

    MySpeed = MySpeed + ItemAttribute(ActorAmulet(fCurrentActor, 1), "Speed")
    MySpeed = MySpeed + ItemAttribute(ActorAmulet(fCurrentActor, 2), "Speed")
    MySpeed = MySpeed + ItemAttribute(ActorRing(fCurrentActor, 1), "Speed")
    MySpeed = MySpeed + ItemAttribute(ActorRing(fCurrentActor, 2), "Speed")
    MySpeed = MySpeed + ItemAttribute(ActorRing(fCurrentActor, 3), "Speed")
    MySpeed = MySpeed + ItemAttribute(ActorRing(fCurrentActor, 4), "Speed")
    MyDex   = MyDex   + ItemAttribute(ActorAmulet(fCurrentActor, 1), "Dexterity")
    MyDex   = MyDex   + ItemAttribute(ActorAmulet(fCurrentActor, 2), "Dexterity")
    MyDex   = MyDex   + ItemAttribute(ActorRing(fCurrentActor, 1), "Dexterity")
    MyDex   = MyDex   + ItemAttribute(ActorRing(fCurrentActor, 2), "Dexterity")
    MyDex   = MyDex   + ItemAttribute(ActorRing(fCurrentActor, 3), "Dexterity")
    MyDex   = MyDex   + ItemAttribute(ActorRing(fCurrentActor, 4), "Dexterity")

    MyDef   = MyDef   + ItemAttribute(ActorAmulet(fCurrentActor, 1), "Defence")
    MyDef   = MyDef   + ItemAttribute(ActorAmulet(fCurrentActor, 2), "Defence")
    MyDef   = MyDef   + ItemAttribute(ActorRing(fCurrentActor, 1), "Defence")
    MyDef   = MyDef   + ItemAttribute(ActorRing(fCurrentActor, 2), "Defence")
    MyDef   = MyDef   + ItemAttribute(ActorRing(fCurrentActor, 3), "Defence")
    MyDef   = MyDef   + ItemAttribute(ActorRing(fCurrentActor, 4), "Defence")
    If fCombatActive%
   MySpeed = MySpeed + Attribute(fCurrentActor, "Speed")
   MyDef   = MyDef   + Attribute(fCurrentActor, "Defence")
   MyDex   = MyDex   + Attribute(fCurrentActor, "Dexterity")
    EndIf
    Belt    = ItemArmor(ActorBelt(fCurrentActor))
    Chest   = ItemArmor(ActorChest(fCurrentActor))
    Feet    = ItemArmor(ActorFeet(fCurrentActor))
    Hands   = ItemArmor(ActorHands(fCurrentActor))
    Hat     = ItemArmor(ActorHat(fCurrentActor))
    Legs    = ItemArmor(ActorLegs(fCurrentActor))
    Shield  = ItemArmor(ActorShield(fCurrentActor))
    RtnValue% = (MySpeed + MyDex + MyDef + Belt + Chest + Feet + Hands + Hat + Legs + Shield)
    Return(RtnValue%)
   
End Function

; Determin Base attack value based on current actors strength + (amulet & ring values)
Function CalculateAttackValue%(fCurrentActor)

    Combat  = Combat  + ItemAttribute(ActorAmulet(fCurrentActor, 1), "Combat")
    Combat  = Combat  + ItemAttribute(ActorAmulet(fCurrentActor, 2), "Combat")
    Combat  = Combat  + ItemAttribute(ActorRing(fCurrentActor, 1), "Combat")
    Combat  = Combat  + ItemAttribute(ActorRing(fCurrentActor, 2), "Combat")
    Combat  = Combat  + ItemAttribute(ActorRing(fCurrentActor, 3), "Combat")
    Combat  = Combat  + ItemAttribute(ActorRing(fCurrentActor, 4), "Combat")
    MyStr   = MyStr   + ItemAttribute(ActorAmulet(fCurrentActor, 1), "Strength")
    MyStr   = MyStr   + ItemAttribute(ActorAmulet(fCurrentActor, 2), "Strength")
    MyStr   = MyStr   + ItemAttribute(ActorRing(fCurrentActor, 1), "Strength")
    MyStr   = MyStr   + ItemAttribute(ActorRing(fCurrentActor, 2), "Strength")
    MyStr   = MyStr   + ItemAttribute(ActorRing(fCurrentActor, 3), "Strength")
    MyStr   = MyStr   + ItemAttribute(ActorRing(fCurrentActor, 4), "Strength")
    MyStr   = MyStr   + Attribute(fCurrentActor, "Strength")
    RtnValue% = ((MyStr * 2) + Combat)
    Return(RtnValue%)
   
End Function

; Determine which (if any) combatants are NPC's
Function CheckAI%(fAttacker, fTarget)

       If ActorIsHuman(fAttacker)
              RtnValue% = 1 ; Only Attacker is Human
       EndIf
       If ActorIsHuman(fTarget) And RtnValue% = 1 Then
              Return(0) ; Both Attacker and Target are Human
       ElseIf ActorIsHuman(fTarget) And RtnValue% = 0 Then
              RtnValue% = 2 ; Only Target is Human
       ElseIf RtnValue% = 0 And ActorIsHuman(fTarget) = False Then
              RtnValue% = 3 ; Neither Attacker or Target are Human
       EndIf
       Return(RtnValue%)

End Function

; Calculate Retreat values and strength positions in the fight
Function UpdateAI%(fAttacker, fTarget, AIState%)

    If AIState% = 0 Then
        Return(0)
    EndIf

    If AIState% = 1 Or AIState% = 3 Then ; Target is AI or Both are AI

        If Attribute(fTarget, "Intelligence") < 10 Then
            TPosition = TPosition - 2
            TRetreat = TRetreat - 3
        EndIf
        If Attribute(fTarget, "Intelligence") < 6 Then
            TPosition = TPosition - 2
            TRetreat = TRetreat - 5
        EndIf
        If Attribute(fTarget, "Intelligence") > 9 Then
            TPosition = TPosition + 2
        EndIf
        If Attribute(fTarget, "Intelligence") > 14 Then
            TPosition = TPosition + 1
        EndIf
        If Attribute(fTarget, "Intelligence") > 19 Then
            TPosition = TPosition + 1
        EndIf
        If Attribute(fTarget, "Intelligence") > 24 Then
            TPosition = TPosition + 1
        EndIf
        If Attribute(fTarget, "Health") < (MaxAttribute(fTarget, "Health") / 3) Then
            TRetreat = TRetreat + 3
            TPosition = TPosition - 1
        EndIf
        If Attribute(fTarget, "Health") < (MaxAttribute(fTarget, "Health") / 2) Then
            TRetreat = TRetreat + 2
            TPosition = TPosition - 1
        EndIf
        If Attribute(fAttacker, "Health") < (MaxAttribute(fAttacker, "Health") / 3) Then
            TRetreat = TRetreat - 3
            TPosition = TPosition + 1
        EndIf
        If Attribute(fAttacker, "Health") < (MaxAttribute(fAttacker, "Health") / 2) Then
            TRetreat = TRetreat - 2
            TPosition = TPosition + 1
        EndIf
        Moral%(1) = TPosition
    EndIf

    If AIState% = 2 Or AIState% = 3 Then ; Attacker is AI Or Both are AI

        If Attribute(fAttacker, "Intelligence") < 10 Then
            APosition = APosition - 2
            ARetreat = ARetreat - 3
        EndIf
        If Attribute(fAttacker, "Intelligence") < 6 Then
            APosition = APosition - 2
            ARetreat = ARetreat - 5
        EndIf
        If Attribute(fAttacker, "Intelligence") < 10 Then
            APosition = APosition - 2
        EndIf
        If Attribute(fAttacker, "Intelligence") > 9 Then
            APosition = APosition + 2
        EndIf
        If Attribute(fAttacker, "Intelligence") > 14 Then
            APosition = APosition + 1
        EndIf
        If Attribute(fAttacker, "Intelligence") > 19 Then
            APosition = APosition + 1
        EndIf
        If Attribute(fAttacker, "Intelligence") > 24 Then
            APosition = APosition + 1
        EndIf
        If Attribute(fAttacker, "Health") < (MaxAttribute(fAttacker, "Health") / 3) Then
            ARetreat = ARetreat + 3
            APosition = APosition - 1
        EndIf
        If Attribute(fAttacker, "Health") < (MaxAttribute(fAttacker, "Health") / 2) Then
            ARetreat = ARetreat + 2
            APosition = APosition - 1
        EndIf
        If Attribute(fTarget, "Health") < (MaxAttribute(fTarget, "Health") / 3) Then
            ARetreat = ARetreat - 3
            APosition = APosition + 1
        EndIf
        If Attribute(fTarget, "Health") < (MaxAttribute(fTarget, "Health") / 2) Then
            ARetreat = ARetreat - 2
            APosition = APosition + 1
        EndIf
        Moral%(0) = APosition
    EndIf
    If AIState% = 3 Then
        If TRetreat <= ARetreat Then
            If TRetreat < 0 Then
                needed = 5
            EndIf
            If TRetreat < -1 Then
                needed = needed + 4
            EndIf
            If TRetreat < -2 Then
                needed = needed + 3
            EndIf
            If TRetreat < -3 Then
                needed = needed + 2
            EndIf
            If TRetreat < -4 Then
                needed = needed + 1
            EndIf
            If TRetreat < -5 Then
                needed = needed + 1
            EndIf
            If TRetreat < -6 Then
                needed = needed + 1
            EndIf
            If TRetreat < -7 Then
                needed = needed + 1
            EndIf
            If TRetreat < -8 Then
                needed = needed + 1
            EndIf
            If TRetreat < -9 Then
                needed = needed + 1
            EndIf
            If (Rand(1, 20) + TPosition) < needed Then
                If ActorAggressiveness(fTarget) <> 2 Then
                    TRetreating = True
                Else
                    TRetreating = False
                EndIf
            Else
                TRetreating = False
            EndIf
        Else
            If ARetreat < 0 Then
                needed = 5
            EndIf
            If ARetreat < -1 Then
                needed = needed + 4
            EndIf
            If ARetreat < -2 Then
                needed = needed + 3
            EndIf
            If ARetreat < -3 Then
                needed = needed + 2
            EndIf
            If ARetreat < -4 Then
                needed = needed + 1
            EndIf
            If ARetreat < -5 Then
                needed = needed + 1
            EndIf
            If ARetreat < -6 Then
                needed = needed + 1
            EndIf
            If ARetreat < -7 Then
                needed = needed + 1
            EndIf
            If ARetreat < -8 Then
                needed = needed + 1
            EndIf
            If ARetreat < -9 Then
                needed = needed + 1
            EndIf
            If (Rand(1, 20) + APosition) < needed Then
                If ActorAggressiveness(fAttacker) <> 2 Then
                    ARetreating = True
                Else
                    ARetreating = False
                EndIf
            Else
                ARetreating = False
            EndIf
        EndIf

    ElseIf AIState% = 2 Then

            If ARetreat < 0 Then
                needed = 5
            EndIf
            If ARetreat < -1 Then
                needed = needed + 4
            EndIf
            If ARetreat < -2 Then
                needed = needed + 3
            EndIf
            If ARetreat < -3 Then
                needed = needed + 2
            EndIf
            If ARetreat < -4 Then
                needed = needed + 1
            EndIf
            If ARetreat < -5 Then
                needed = needed + 1
            EndIf
            If ARetreat < -6 Then
                needed = needed + 1
            EndIf
            If ARetreat < -7 Then
                needed = needed + 1
            EndIf
            If ARetreat < -8 Then
                needed = needed + 1
            EndIf
            If ARetreat < -9 Then
                needed = needed + 1
            EndIf
            If Rand(1, 25) < needed Then
                ARetreating = True
                If (Rand(1, 20) + APosition) < needed
                    If ActorAggressiveness(fAttacker) <> 2 Then
                        ARetreating = True
                    Else
                        ARetreating = False
                    EndIf
                Else
                    ARetreating = False
                EndIf
            Else
                ARetreating = False
            EndIf

    ElseIf AIState% = 1 Then

            If TRetreat < 0 Then
                needed = 5
            EndIf
            If TRetreat < -1 Then
                needed = needed + 4
            EndIf
            If TRetreat < -2 Then
                needed = needed + 3
            EndIf
            If TRetreat < -3 Then
                needed = needed + 2
            EndIf
            If TRetreat < -4 Then
                needed = needed + 1
            EndIf
            If TRetreat < -5 Then
                needed = needed + 1
            EndIf
            If TRetreat < -6 Then
                needed = needed + 1
            EndIf
            If TRetreat < -7 Then
                needed = needed + 1
            EndIf
            If TRetreat < -8 Then
                needed = needed + 1
            EndIf
            If TRetreat < -9 Then
                needed = needed + 1
            EndIf
            If Rand(1, 25) < needed Then
                If (Rand(1, 20) + TPosition) < needed Then
                    If ActorAggressiveness(fTarget) <> 2 Then
                        TRetreating = True
                    Else
                        TRetreating = False
                    EndIf
                Else
                    TRetreating = False
                EndIf
            Else
                TRetreating = False
            EndIf

    EndIf
    If TRetreating = True Then
        Output(fAttacker, Name(fTarget) + " is fleeing!")
        X = ActorX(fTarget) + Rand(-250, 250)
        Z = ActorZ(fTarget) + Rand(-250, 250)
        SetActorTarget(fTarget)
        SetActorDestination(fTarget, X, Z)
        SetActorAIState(fTarget, 2)
        DoEvents(1500)
    EndIf
    If ARetreating = True Then
        Output(fTarget, Name(fAttacker) + " is fleeing!")
        X = ActorX(fAttacker) + Rand(-250, 250)
        Z = ActorZ(fAttacker) + Rand(-250, 250)
        SetActorTarget(fAttacker)
        SetActorDestination(fAttacker, X, Z)
        SetActorAIState(fAttacker, 2)
        DoEvents(1500)
    EndIf
    If ARetreating = True Then
        Return(1)
    ElseIf TRetreating = True Then
        Return(11)
    Else
        Return(0)
    EndIf

End Function

; Allows an NPC to use an ability if they have one to use
Function UseAbility%(fAttacker, fTarget, AIState%, WHO%)

; WHO% 0 = Attacker
; WHO% 1 = Target

   AB = Rand(1, MaxAbilitiesKnown(WHO%))
   
   Select WHO%
   
      Case 0

         AbilityUsed = 1

      Case 1

         AbilityUsed = 1

   End Select

   If AB > 0 And AbilityUsed = 1 Then
      ThreadExecute(AbilityNames$(WHO%, AB), "Main", fAttacker, fTarget)
      Return(1)
   Else
      Return(0)
   EndIf

End Function

; Determine loot dropped for Victor after combat is over
Function LootDrop(fAttacker, fTarget, WHO%, Victor%)

   If WHO% = 0 Then
      Losser = fAttacker
   Else
      Losser = fTarget
   EndIf
   LosLVL = ActorLevel(Losser)
;    Output(Victor%, "AIData%(WHO%, 0) = " + AIData%(WHO%, 0))
   Select AIData%(WHO%, 0)
   
      Case 1 ;    Small furry animal loot
         MaxDrop = Rand(0, 3) ; Maximum # of items to be dropped
         GG = 0 ;    GG = Give Gold
         If MaxDrop > 0 Then
            For i = 1 to MaxDrop
               CanDrop = Rand(1, 100)
               If CanDrop < 11 Then
                  GiveItem(Victor%, "Dog pelt", 1)
                  Output(Victor%, "You got 1 Animal pelt")
                  TD = TD + 1
               ElseIf CanDrop > 10 And CanDrop < 21 Then
                  GiveItem(Victor%, "Raw meat", 1)
                  Output(Victor%, "You got 1 Raw meat")
                  TD = TD + 1
               ElseIf CanDrop > 20 And CanDrop < 31 Then
                  GiveItem(Victor%, "Bones", 1)
                  Output(Victor%, "You got some bones")
                  TD = TD + 1
               ElseIf CanDrop > 30 And CanDrop < 41 Then
                  GiveItem(Victor%, "Bone dust", 1)
                  Output(Victor%, "You got 1 bone dust")
                  TD = TD + 1
               EndIf
            Next
            If TD = 0 Then
               Output(Victor%, "Nothing of value dropped.")
            EndIf
         Else
            Output(Victor%, "Nothing of value dropped.")
         EndIf

      Case 2 ; Arachnid loot
         MaxDrop = Rand(1, 2)
         GG = 0
         For i = 1 to MaxDrop
            CanDrop = Rand(1, 100)
            If CanDrop < 91 Then
               GiveItem(Victor%, "Small spider web", 1)
               Output(Victor%, "You got 1 Small spider web.")
               TD = TD + 1
            ElseIf CanDrop = 99 Then
               GiveItem(Victor%, "Spider eggsack", 1)
               Output(Victor%, "You got 1 Spider eggsack.")
               TD = TD + 1
            EndIf
         Next
         If TD = 0 Then
            Output(Victor%, "Nothing of value dropped.")
         EndIf
       
      Case 3 ; Ant loot
         MaxDrop = Rand(0, 1)
         GG = 0
         If MaxDrop > 0 Then
            For i = 1 to MaxDrop
               CanDrop = Rand(1, 100)
               If CanDrop < 21 Then
                  GiveItem(Victor%, "Goop", 1)
                  Output(Victor%, "You got 1 Ant goop")
                  TD = TD + 1
               ElseIf CanDrop = 21 Then
                  GiveItem(Victor%, "Garnet", 1)
                  Output(Victor%, "You got 1 Garnet")
                  TD = TD + 1
               ElseIf CanDrop = 22 Then
                  GiveItem(Victor%, "Gold powder", 1)
                  Output(Victor%, "You got 1 Gold powder")
                  TD = TD + 1
               ElseIf CanDrop = 23 Then
                  GiveItem(Victor%, "Jasper", 1)
                  Output(Victor%, "You got 1 Jasper")
                  TD = TD + 1
               ElseIf CanDrop = 24 Then
                  GiveItem(Victor%, "Amber", 1)
                  Output(Victor%, "You got 1 Amber")
                  TD = TD + 1
               ElseIf CanDrop = 25 Then
                  GiveItem(Victor%, "Diamond", 1)
                  Output(Victor%, "You got 1 Diamond")
                  TD = TD + 1
               EndIf
            Next
            If TD = 0 Then
               Output(Victor%, "Nothing of value dropped.")
            EndIf
         Else
            Output(Victor%, "Nothing of value dropped.")
         EndIf
       
        Case 4 ; Bird loot

            GG = 0
       
        Case 5 ; Mutant loot
       
            GG = 150
        Case 6
       
        Case 7
       
        Case 8
       
        Case 9
       
        Case 10
       
    End Select


End Function