It’s a very large script. The AI is designed for fast paced combat, so that is why I cannot lower the check rate.
local Remote_Events = game.ReplicatedStorage.Remote_Events
local Server_Events = game.ServerStorage.Server_Events
local Humanoids = game.ReplicatedStorage.Humanoids
local Effect_Storage = game.ServerStorage.Game_Effects
local Module_Scripts = game.ReplicatedStorage.Module_Scripts
local Function_Module = require(Module_Scripts.Function_Module)
local Item_Data = require(Module_Scripts.Item_Data)
local Stun_Module = require(Module_Scripts.Stun_Module)
local Effects = require(Module_Scripts.Effect_Module)
local Npc_Data_Module = require(Module_Scripts.Npc_Data)
local Item_Module = require(Module_Scripts.Item_Module)
local Climb_Module = require(Module_Scripts.Climb_Module)
local Stamina_Module = require(Module_Scripts.Stamina_Module)
local Move_Directions = {
"0,0,-1", "0,0,1", "-1,0,0", "1,0,0",
"1,0,-1", "1,0,1", "-1,0,-1", "-1,0,1",
}
local Action_Input = function(Npc, Input_Name, Action_Module) --Always put returns at the end unless it's a global return like stats.loaded
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
if Input_Name == "Block_End" then
C_Stats.Mouse2_Down.Value = false
Action_Module.Block_Input(Npc, false)
elseif Input_Name == "Light_End" then
C_Stats.Mouse1_Down.Value = false
elseif Input_Name == "Sprint_End" then
Action_Module.Sprint(Npc, false)
end
if Stats.Knocked_Out.Value or not Stats.Loaded.Value then return end
if not Stats.Climbing.Value and not C_Stats.Eating.Value and not C_Stats.Heavy_Attacking.Value and not C_Stats.Using_Skill.Value then
if Input_Name == "Dodge" then
Action_Module.Dodge(Npc)
elseif Input_Name == "Eat" then
Action_Module.Eat_Item(Npc)
elseif Input_Name == "Interact" then
Action_Module.Interact(Npc)
elseif Input_Name == "Visor" then
Action_Module.Change_Visor(Npc)
end
end
if Input_Name == "Sprint_Start" then
Action_Module.Sprint(Npc, true)
elseif Input_Name == "Climb" then
Climb_Module.Climb(Npc)
end
if not Stats.Climbing.Value and not Stats.Knocked_Out.Carry.Value and not C_Stats.Equipping.Value then
if Stats.Stunned.Value or C_Stats.Light_Attacking.Value or C_Stats.Heavy_Attacking.Value or C_Stats.Kicking.Value or C_Stats.Using_Skill.Value or C_Stats.Eating.Value then return end
if Input_Name == "Block_Start" then
C_Stats.Mouse2_Down.Value = true
C_Stats.Mouse2_Down.Time.Value = time()
Action_Module.Block_Input(Npc, true)
end
if C_Stats.Blocking.Value then return end
if Input_Name == "Light_Start" then
Action_Module.Light_Start(Npc)
elseif Input_Name == "Switch_Primary" then
Action_Module.Weapon_Switch(Npc, Stats.Equip_Slots.Weapon.Primary)
elseif Input_Name == "Switch_Secondary" then
Action_Module.Weapon_Switch(Npc, Stats.Equip_Slots.Weapon.Secondary)
elseif Input_Name == "Switch_Shield" then
Action_Module.Weapon_Switch(Npc, Stats.Equip_Slots.Shield.Shield)
elseif Input_Name == "Heavy_Attack" then
Action_Module.Heavy_Start(Npc)
elseif Input_Name == "Kick" then
Action_Module.Kick_Attack(Npc)
end
end
end
local Set_Combat = function(Stats,Enemy_Stats)
Stats.In_Combat.Timer.Value = 30
Stats.In_Combat.Value = true
Stats.In_Combat.Enemy.Value = Enemy_Stats.Parent
Enemy_Stats.In_Combat.Timer.Value = 30
Enemy_Stats.In_Combat.Value = true
Enemy_Stats.In_Combat.Enemy.Value = Stats.Parent
end
local Get_Enemy_Armor = function(Enemy)
if not Enemy then return "Soft" end
local Enemy_Stats = Enemy.Character_Data
local Soft_Rating = 0
local Hard_Rating = 0
local Type = "Soft"
for i,Armor_Value in pairs(Enemy_Stats.Armored_Parts:GetChildren()) do
if Armor_Value.Value then
local Armor_Data = Item_Data[Armor_Value.Value.Name]
Soft_Rating += Armor_Data.Soft_Armor
Hard_Rating += Armor_Data.Hard_Armor
end
end
if Hard_Rating > Soft_Rating then
Type = "Hard"
end
return Type
end
local Find_Best_Weapon = function(Npc)
local Stats = Npc.Character_Data
local Weapon_Slots = Stats.Equip_Slots.Weapon
local Enemy_Armor = Get_Enemy_Armor(Stats.In_Combat.Enemy.Value)
local Usable_Slot = nil
local Target_Slot = nil
for i,Slot in pairs(Weapon_Slots:GetChildren()) do
if not Slot.Value then
local Found_Weapon = nil
for i,Item in pairs(Stats.Inventory:GetChildren()) do
if Item_Data[Item.Name].Type == "Weapon" then
Found_Weapon = Item
end
end
if Found_Weapon then
Item_Module.Equip(Stats,Found_Weapon,Slot.Name)
wait(0.5)
end
end
if Slot.Value then
local Data = Item_Data[Slot.Value.Name]
local Has_Arrows = Stats.Inventory:FindFirstChild("Item_15")
local Usable = true
if Data.Class == "Ranged" then
if not Has_Arrows then
Usable = false
end
Data = Item_Data["Item_15"] --Arrow Data
end
if Usable then
Usable_Slot = Slot
end
if Usable and (Enemy_Armor == "Hard" and Data.Hard_Penetration > Data.Soft_Penetration) or (Enemy_Armor == "Soft" and Data.Soft_Penetration >= Data.Hard_Penetration) then
Target_Slot = Slot
break
end
end
end
if not Target_Slot and Usable_Slot then
Target_Slot = Usable_Slot
end
return Target_Slot
end
local Equip_Any_Weapon = function(Npc, Action_Module)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Weapon_Slots = Stats.Equip_Slots.Weapon
local Target_Slot = C_Stats.Desired_Weapon.Value
if Target_Slot then
Action_Input(Npc, "Switch_"..Target_Slot.Name, Action_Module)
end
end
local Unequip_Any_Weapon = function(Npc, Action_Module)
local Stats = Npc.Character_Data
local Weapon_Slots = Stats.Equip_Slots.Weapon
if Stats.Held_Weapon.Value then
Action_Input(Npc, "Switch_"..Stats.Held_Weapon.Value.Name, Action_Module)
end
end
local Get_Food_Item = function(Stats)
return Stats.Inventory:FindFirstChild(Stats.Food_Item.Value)
end
local Eat_Food = function(Npc, Action_Module)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
if Get_Food_Item(Stats) and Stats.Hunger.Value < 50 then
Action_Input(Npc, "Eat", Action_Module)
else
local Nearest = nil
local Distance = 100
for i,Item in pairs(workspace.Drop_Folder:GetChildren()) do
if Item_Data[Item.Name].Type == "Food" then
local New_Distance = (Item.PrimaryPart.Position - Npc.PrimaryPart.Position).Magnitude
if New_Distance < Distance then
Distance = New_Distance
Nearest = Item
end
end
end
C_Stats.Target_Item.Value = Nearest
end
end
local Get_Weapon_Distance = function(Stats)
local Weapon_Slot = Stats.Held_Weapon.Value
local Distance = 0
if Weapon_Slot then
local Item = Weapon_Slot.Value
local Data = Item_Data[Item.Name]
if Data.Weapon_Type == "Sword" then
Distance = 2
elseif Data.Weapon_Type == "Spear" then
Distance = 7
elseif Data.Weapon_Type == "Axe" or Data.Weapon_Type == "Hammer" then
Distance = 3
elseif Data.Weapon_Type == "Mace" then
Distance = 1
elseif Data.Weapon_Type == "Bow" then
Distance = 70
end
end
return Distance
end
local Get_Target_Point = function(Npc, Look_Point)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Enemy = C_Stats.Target_Enemy.Value
local Desired_Point = nil
if C_Stats.Current_Behaviour.Value == "Attack" and Enemy then
Desired_Point = Enemy.PrimaryPart.Position + (Enemy.Humanoid.MoveDirection / 2)
if not Look_Point then
local Target_Distance = Get_Weapon_Distance(Stats)
if Target_Distance then
Desired_Point -= (Desired_Point - Npc.PrimaryPart.Position).Unit * Target_Distance
end
end
elseif C_Stats.Current_Behaviour.Value == "Get_Item" and C_Stats.Target_Item.Value then
Desired_Point = C_Stats.Target_Item.Value.PrimaryPart.Position
elseif C_Stats.Current_Behaviour.Value == "Get_Body" and C_Stats.Target_Body.Value then
Desired_Point = C_Stats.Target_Body.Value.PrimaryPart.Position
elseif C_Stats.Current_Behaviour.Value == "Run_Away" and C_Stats.Target_Enemy.Value then
Desired_Point = Npc.PrimaryPart.Position + ((Npc.PrimaryPart.Position - Enemy.PrimaryPart.Position).Unit * 50) + Vector3.new(0,15,0)
elseif C_Stats.Current_Behaviour.Value == "Dialog" and C_Stats.Target_Speaker.Value then
Desired_Point = C_Stats.Target_Speaker.Value.PrimaryPart.Position
if not Look_Point then
Desired_Point = Npc.PrimaryPart.Position
end
end
return Desired_Point
end
local Relative_Vector = function(Center, Vector)
return (Center * CFrame.new(Vector)).Position - Center.Position
end
local Check_Move_Direction = function(Npc, Desired_Point, Locked, Vector)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Weight = 0
local Ray_Vector = Vector3.new()
local Center = Npc.PrimaryPart.CFrame
local Blocks = {workspace.Block_Terrain}
local Base_Distance = (Npc.PrimaryPart.Position - Desired_Point).Magnitude
local Unit_Target = Npc.PrimaryPart.Position - ((Npc.PrimaryPart.Position - Desired_Point).Unit)
if (C_Stats.Current_Behaviour.Value == "Attack" and Base_Distance < 0.3) or (Stats.Climbing.Value and Base_Distance < 0.6) or (C_Stats.Current_Behaviour.Value ~= "Attack" and Base_Distance < 6) then
return 0
end
if not Stats.Climbing.Value then
Weight = 10 / ((Center * CFrame.new(Vector)).Position - Desired_Point).Magnitude
else
Weight = 1 / ((Center * CFrame.new(Vector)).Position - Unit_Target).Magnitude
end
Ray_Vector = Relative_Vector(Center, Vector) * 3
local Obstructed, Point = workspace:FindPartOnRayWithWhitelist(Ray.new(Center.Position + Vector3.new(0,-1,0),Ray_Vector),Blocks)
local Wall, Point_2 = workspace:FindPartOnRayWithWhitelist(Ray.new(Center.Position + Vector3.new(0,3,0),Ray_Vector),Blocks)
C_Stats.Path_Obstructed.Value = Obstructed
C_Stats.Path_Obstructed.Is_Wall.Value = Wall
if Wall then
Weight *= ((Center.Position + Vector3.new(0,3,0)) - Point_2).Magnitude / 4
end
if Stats.Climbing.Value then
if Vector.Y ~= 0 then
if string.find(math.floor(Vector.Y), "1") then
Weight *= 6
else
Weight *= 4
end
end
end
return Weight
end
local Convert_Vector = function(String, Climbing)
local Nums = string.split(String,",")
if not Climbing then
return Vector3.new(tonumber(Nums[1]),tonumber(Nums[2]),tonumber(Nums[3])).Unit
else
return Vector3.new(tonumber(Nums[1]),tonumber(Nums[3]),tonumber(Nums[2])).Unit
end
end
local Check_Target_Visible = function(Main_P, Target_P)
local Dir = CFrame.new(Main_P, Target_P).LookVector
local Dist = (Main_P - Target_P).Magnitude
local Checker = Ray.new(Main_P, Dir * Dist)
local Wall = workspace:FindPartOnRayWithWhitelist(Checker,{workspace.Block_Terrain, workspace.Decorations.Blocks})
return Wall
end
local Behaviour_Considerations = {
Attack = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Enemy = C_Stats.Target_Enemy.Value
local Has_Weapon = C_Stats.Desired_Weapon.Value
local Weight = 0
if Has_Weapon and Enemy and Enemy.Humanoid.Health > 0 and (Stats.Equip_Slots.Weapon.Primary.Value or Stats.Equip_Slots.Weapon.Secondary.Value) and not C_Stats.Target_Body.Value and (Npc.PrimaryPart.Position - Enemy.PrimaryPart.Position).Magnitude < 100 then
Weight = 0.5 + ((Npc.Humanoid.Health / Npc.Humanoid.MaxHealth) / 2)
end
return Weight
end,
Get_Item = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Weight = 0
if C_Stats.Target_Item.Value then
if C_Stats.Target_Item.Value.Parent == workspace.Drop_Folder then
Weight = 0.6
if C_Stats.Target_Enemy.Value or C_Stats.Target_Speaker.Value then
Weight /= 2
end
else
C_Stats.Target_Item.Value = nil
end
end
return Weight
end,
Get_Body = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Target_Body = C_Stats.Target_Body.Value
local Weight = 0
if Target_Body then
Weight = 2
end
return Weight
end,
Run_Away = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Enemy = C_Stats.Target_Enemy.Value
local Mood = Function_Module.Get_Npc_Mood(C_Stats)
local Weight = 0
if Enemy and Enemy.Humanoid.Health > 0 and ((Npc.PrimaryPart.Position - Enemy.PrimaryPart.Position).Magnitude < 100 or Stats.Climbing.Value) then
Weight = ((-(Npc.Humanoid.Health / 100)) + (Enemy.Humanoid.Health / 100)) * 1.5
if Mood == "Afraid" then
Weight *= 1.2
end
end
return Weight
end,
Dialog = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Speaker = C_Stats.Target_Speaker.Value
local Weight = 0
if Speaker then
Weight = 0.8
end
return Weight
end,
Do_Nothing = function(Npc)
return 0.2
end,
}
local Action_Considerations = {
Equip_Weapon = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Weight = 0
if Stats.Knocked_Out.Value or not Stats.Loaded.Value or Stats.Climbing.Value or Stats.Knocked_Out.Carry.Value or C_Stats.Equipping.Value then return 0 end
if Stats.Stunned.Value or C_Stats.Light_Attacking.Value or C_Stats.Heavy_Attacking.Value or C_Stats.Kicking.Value or C_Stats.Using_Skill.Value or C_Stats.Eating.Value or C_Stats.Blocking.Value then return 0 end
if C_Stats.Desired_Weapon.Value and Stats.Held_Weapon.Value ~= C_Stats.Desired_Weapon.Value and C_Stats.Current_Behaviour.Value == "Attack" then
Weight = 1
end
return Weight
end,
Unequip_Weapon = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Weight = 0
if Stats.Knocked_Out.Value or not Stats.Loaded.Value or Stats.Climbing.Value or Stats.Knocked_Out.Carry.Value or C_Stats.Equipping.Value then return 0 end
if Stats.Stunned.Value or C_Stats.Light_Attacking.Value or C_Stats.Heavy_Attacking.Value or C_Stats.Kicking.Value or C_Stats.Using_Skill.Value or C_Stats.Eating.Value or C_Stats.Blocking.Value then return 0 end
if Stats.Held_Weapon.Value and (C_Stats.Current_Behaviour.Value == "Do_Nothing" or C_Stats.Current_Behaviour.Value == "Get_Item" or not C_Stats.Desired_Weapon.Value) then
Weight = 1
end
return Weight
end,
Switch_Shield = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Weapon_Slot = Stats.Held_Weapon.Value
local Shield = Stats.Equip_Slots.Shield.Shield.Value
local Weight = 0
if Stats.Knocked_Out.Value or not Stats.Loaded.Value or Stats.Climbing.Value or Stats.Knocked_Out.Carry.Value or C_Stats.Equipping.Value then return 0 end
if Stats.Stunned.Value or C_Stats.Light_Attacking.Value or C_Stats.Heavy_Attacking.Value or C_Stats.Kicking.Value or C_Stats.Using_Skill.Value or C_Stats.Eating.Value or C_Stats.Blocking.Value then return 0 end
if not Stats.Held_Shield.Value and Shield and C_Stats.Current_Behaviour.Value == "Attack" then
if (Weapon_Slot and Item_Data[Weapon_Slot.Value.Name].Handle_Type == "Two") and Item_Data[Shield.Name].Handle_Type == "Grip" then return 0 end
Weight = 0.6
if Npc.Humanoid.Health < 40 then
Weight *= 1.5
end
elseif Stats.Held_Shield.Value and (C_Stats.Current_Behaviour.Value == "Do_Nothing" or C_Stats.Current_Behaviour.Value == "Get_Item") then
Weight = 0.9
end
return Weight
end,
Light_Start = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Enemy = C_Stats.Target_Enemy.Value
local Weapon_Slot = Stats.Held_Weapon.Value
local Weight = 0
if Stats.Knocked_Out.Value or not Stats.Loaded.Value or Stats.Climbing.Value or Stats.Knocked_Out.Carry.Value or C_Stats.Equipping.Value then return 0 end
if Stats.Stunned.Value or C_Stats.Light_Attacking.Value or C_Stats.Heavy_Attacking.Value or C_Stats.Kicking.Value or C_Stats.Using_Skill.Value or C_Stats.Eating.Value or C_Stats.Blocking.Value then return 0 end
if not Stats.Held_Weapon.Value or C_Stats.Cooldowns.Light.Value then return 0 end
if C_Stats.Current_Behaviour.Value == "Attack" and Enemy and Weapon_Slot and C_Stats.Point_Visible.Value then
local Enemy_Stats = Enemy.Character_Data
if Stats.Held_Weapon.Class.Value == "Melee" and (Npc.PrimaryPart.Position - Enemy.PrimaryPart.Position).Magnitude < 5 + Get_Weapon_Distance(Stats) then
Weight = 0.6
if Enemy_Stats.Stunned.Value or Enemy_Stats.Attacking.Heavy.Value or (Stats.Blocking.Block_Strength.Value > 0 and Stats.Blocking.Hit_Count.Value >= Stats.Blocking.Block_Strength.Value - 2) then
Weight = 1.1
end
elseif Stats.Held_Weapon.Class.Value == "Ranged" then
Weight = 0.7
end
end
return Weight
end,
Light_End = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Enemy = C_Stats.Target_Enemy.Value
local Weight = 0
if C_Stats.Mouse1_Down.Value and time() - C_Stats.Mouse1_Down.Time.Value > 1 then
if Enemy and Stats.Held_Weapon.Value then
local Enemy_Stats = Enemy.Character_Data
local Weapon_Data = Item_Data[Stats.Held_Weapon.Value.Value.Name]
if time() - C_Stats.Mouse1_Down.Time.Value > 2.5-(Weapon_Data.Draw_Speed * 2) then
Weight = 1
end
if Enemy_Stats.Stunned.Value or Enemy_Stats.Attacking.Value then
Weight = 3
end
elseif not Enemy then
Weight = 1
end
end
return Weight
end,
Heavy_Attack = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Enemy = C_Stats.Target_Enemy.Value
local Weight = 0
if Stats.Knocked_Out.Value or not Stats.Loaded.Value or Stats.Climbing.Value or Stats.Knocked_Out.Carry.Value or C_Stats.Equipping.Value then return 0 end
if Stats.Stunned.Value or C_Stats.Light_Attacking.Value or C_Stats.Heavy_Attacking.Value or C_Stats.Kicking.Value or C_Stats.Using_Skill.Value or C_Stats.Eating.Value or C_Stats.Blocking.Value then return 0 end
if not Stats.Held_Weapon.Value or C_Stats.Cooldowns.Heavy.Value then return 0 end
if C_Stats.Current_Behaviour.Value == "Attack" and Stats.Held_Weapon.Class.Value == "Melee" and Enemy and C_Stats.Point_Visible.Value then
local Enemy_Stats = Enemy.Character_Data
if (Npc.PrimaryPart.Position - Enemy.PrimaryPart.Position).Magnitude < 4 + Get_Weapon_Distance(Stats) then
Weight = 0.7
if Enemy_Stats.Stunned.Value or Enemy_Stats.Blocking.Value then
Weight = 1.2
end
end
end
return Weight
end,
Kick = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Enemy = C_Stats.Target_Enemy.Value
local Weight = 0
if Stats.Knocked_Out.Value or not Stats.Loaded.Value or Stats.Climbing.Value or Stats.Knocked_Out.Carry.Value or C_Stats.Equipping.Value then return 0 end
if Stats.Stunned.Value or C_Stats.Light_Attacking.Value or C_Stats.Heavy_Attacking.Value or C_Stats.Kicking.Value or C_Stats.Using_Skill.Value or C_Stats.Eating.Value or C_Stats.Blocking.Value then return 0 end
if C_Stats.Cooldowns.Kick.Value then return 0 end
if C_Stats.Current_Behaviour.Value == "Attack" and Enemy and C_Stats.Point_Visible.Value then
local Enemy_Stats = Enemy.Character_Data
if (Npc.PrimaryPart.Position - Enemy.PrimaryPart.Position).Magnitude < 4 then
Weight = 0.5
if Enemy_Stats.Attacking.Value then
Weight = 0.8
end
if not C_Stats.Light_Attacking.Value and C_Stats.Cooldowns.Light.Value then
Weight = 1
end
end
end
return Weight
end,
Block_Start = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Enemy = C_Stats.Target_Enemy.Value
local Weight = 0
if Stats.Knocked_Out.Value or not Stats.Loaded.Value or Stats.Climbing.Value or Stats.Knocked_Out.Carry.Value or C_Stats.Equipping.Value then return 0 end
if Stats.Stunned.Value or C_Stats.Light_Attacking.Value or C_Stats.Heavy_Attacking.Value or C_Stats.Kicking.Value or C_Stats.Using_Skill.Value or C_Stats.Eating.Value then return 0 end
if not Function_Module.Get_Blocking(Stats) or Stats.Blocking.Block_Strength.Value < 0 then return 0 end
if C_Stats.Current_Behaviour.Value == "Attack" and Enemy and not C_Stats.Blocking.Value and not C_Stats.Mouse2_Down.Value and time() - C_Stats.Mouse2_Down.Time.Value > 1.05 and C_Stats.Point_Visible.Value then
local Enemy_Stats = Enemy.Character_Data
if Enemy_Stats.Held_Weapon.Class.Value == "Melee" or Stats.Held_Shield.Value then
if Enemy_Stats.Attacking.Value and not Enemy_Stats.Attacking.Heavy.Value then
Weight = 1
end
if Stats.Blocking.Block_Strength.Value > 0 and Stats.Blocking.Hit_Count.Value >= Stats.Blocking.Block_Strength.Value - 1 then
Weight = 0
end
end
end
return Weight
end,
Block_End = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Enemy = C_Stats.Target_Enemy.Value
local Weight = 0
if C_Stats.Mouse2_Down.Value and time() - C_Stats.Mouse2_Down.Time.Value > 1 then
if Enemy and Stats.Held_Weapon.Value then
local Enemy_Stats = Enemy.Character_Data
Weight = (time() - C_Stats.Mouse2_Down.Time.Value) / 4
if Enemy_Stats.Attacking.Value and not Enemy_Stats.Attacking.Heavy.Value then
Weight = 0
end
if Enemy_Stats.Stunned.Value or Enemy_Stats.Attacking.Heavy.Value or (Stats.Blocking.Block_Strength.Value > 0 and Stats.Blocking.Hit_Count.Value >= Stats.Blocking.Block_Strength.Value - 1) then
Weight *= 3
end
if Enemy_Stats.Held_Weapon.Class.Value == "Melee" and (Npc.PrimaryPart.Position - Enemy.PrimaryPart.Position).Magnitude > 16 then
Weight = 10
end
elseif not Enemy then
Weight = 1
end
end
return Weight
end,
Dodge = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Enemy = C_Stats.Target_Enemy.Value
local Desired_Point = Get_Target_Point(Npc, false)
local Weight = 0
if Stats.Knocked_Out.Value or not Stats.Loaded.Value or Stats.Climbing.Value or C_Stats.Eating.Value or C_Stats.Heavy_Attacking.Value or C_Stats.Using_Skill.Value then return 0 end
if Stats.Held_Weapon.Value and Stats.Held_Weapon.Class.Value == "Ranged" and C_Stats.Light_Attacking.Value then return 0 end
if C_Stats.Cooldowns.Dodge.Value or Stats.Stunned.Dodge_Stun.Value or Npc.Humanoid.FloorMaterial == Enum.Material.Air then return 0 end
if C_Stats.Current_Behaviour.Value == "Attack" and Enemy and C_Stats.Point_Visible.Value then
local Enemy_Stats = Enemy.Character_Data
local Distance = (Npc.PrimaryPart.Position - Enemy.PrimaryPart.Position).Magnitude
local Attack_Distance = 8+Get_Weapon_Distance(Stats)
if Enemy_Stats.Attacking.Value or (Stats.Blocking.Block_Strength.Value > 0 and Stats.Blocking.Hit_Count.Value >= Stats.Blocking.Block_Strength.Value - 2) then
Weight = 1.5
end
if Stats.Held_Weapon.Class.Value == "Melee" and (Distance > Attack_Distance or (C_Stats.Light_Attacking.Value and Distance < Attack_Distance)) then
Weight = 2
end
if Stats.Stunned.Value and not Stats.Stunned.Dodge_Stun.Value then
Weight = 3
end
else
if Desired_Point and (Npc.PrimaryPart.Position - Desired_Point).Magnitude > 50 then
Weight = 1
end
end
return Weight
end,
Sprint_Start = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Weight = 0
if Stats.Knocked_Out.Value or not Stats.Loaded.Value then return 0 end
if Npc.Humanoid.MoveDirection.Magnitude > 0.5 and not Stats.Sprinting.Value then
local Desired_Point = Get_Target_Point(Npc, false)
if Desired_Point then
Weight = ((Npc.PrimaryPart.Position - Desired_Point).Magnitude / 100) - 0.2
end
if Stats.In_Combat.Value then
Weight += 2
end
if C_Stats.Current_Behaviour.Value == "Run_Away" then
Weight += 1
end
end
return Weight
end,
Sprint_End = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Weight = 0
if Npc.Humanoid.MoveDirection.Magnitude < 0.5 and Stats.Sprinting.Value then
Weight = 0.2
Weight += (1-(Stats.Hunger.Value / 100)) / 2
end
return Weight
end,
Eat = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Weight = 0
if Stats.Knocked_Out.Value or not Stats.Loaded.Value or Stats.Climbing.Value or C_Stats.Eating.Value or C_Stats.Heavy_Attacking.Value or C_Stats.Using_Skill.Value then return 0 end
if C_Stats.Cooldowns.Eat.Value or C_Stats.Light_Attacking.Value or C_Stats.Blocking.Value then return 0 end
Weight = 1 - (Stats.Hunger.Value / 100)
if not Get_Food_Item(Stats) then
if C_Stats.Current_Behaviour.Value == "Attack" or C_Stats.Current_Behaviour.Value == "Run_Away" or C_Stats.Current_Behaviour.Value == "Dialog" then
Weight = 0
end
elseif Npc.Humanoid.Health < 40 then
Weight *= 2
end
return Weight
end,
Find_Body = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Enemy = C_Stats.Target_Enemy.Value
local Target_Body = C_Stats.Target_Body.Value
local Weight = 0
if Enemy and not Target_Body and (Npc.PrimaryPart.Position - Enemy.PrimaryPart.Position).Magnitude < 100 then
if (C_Stats.Current_Behaviour.Value == "Attack" and Enemy.Humanoid.Health > 0) or (Enemy.Humanoid.Health <= 0 and not Enemy.Humanoid:FindFirstChild("Life_Absorbed")) then
local Enemy_Stats = Enemy.Character_Data
if Enemy_Stats.Knocked_Out.Value and not Enemy_Stats.Knocked_Out.Carry.Value then
Weight = 2
end
end
end
return Weight
end,
Interact = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Target_Item = C_Stats.Target_Item.Value
local Target_Body = C_Stats.Target_Body.Value
local Desired_Point = Get_Target_Point(Npc, false)
local Weight = 0
if Stats.Knocked_Out.Value or not Stats.Loaded.Value or Stats.Climbing.Value or C_Stats.Eating.Value or C_Stats.Heavy_Attacking.Value or C_Stats.Using_Skill.Value then return 0 end
if C_Stats.Blocking.Value or C_Stats.Light_Attacking.Value then return 0 end
if Desired_Point then
if C_Stats.Current_Behaviour.Value == "Get_Item" and Target_Item and (Desired_Point - Npc.PrimaryPart.Position).Magnitude < 8 then
if not C_Stats.Target_Enemy.Value then
Weight = 1.2
else
Weight = 0.6
end
elseif C_Stats.Current_Behaviour.Value == "Get_Body" and Target_Body and (Desired_Point - Npc.PrimaryPart.Position).Magnitude < 6 then
Weight = 3
end
end
return Weight
end,
Climb = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Target_Point = Get_Target_Point(Npc, false)
local Root_Point = Npc.PrimaryPart.Position
local Weight = 0
if Stats.Knocked_Out.Value or not Stats.Loaded.Value then return 0 end
if Target_Point then
local Height = (Vector3.new(0,Target_Point.Y,0) - Vector3.new(0,Root_Point.Y,0)).Magnitude
if Height > 3 and C_Stats.Stamina.Value > 15 + Height then
local Can_Climb, Is_Down = Climb_Module.Detect(Npc)
if Can_Climb then
if (C_Stats.Path_Obstructed.Value and C_Stats.Path_Obstructed.Is_Wall.Value) or Is_Down then
Weight = 1.5
end
end
end
end
return Weight
end,
Jump = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Enemy = C_Stats.Target_Enemy.Value
local Weight = 0
if Stats.Knocked_Out.Value or not Stats.Loaded.Value then return 0 end
if Npc.Humanoid.FloorMaterial ~= Enum.Material.Air then
if C_Stats.Path_Obstructed.Value and not C_Stats.Path_Obstructed.Is_Wall.Value then
Weight = 1
end
end
return Weight
end,
Do_Nothing = function(Npc)
local C_Stats = Npc.Npc_Stats
local Weight = 0.1
if C_Stats.Current_Behaviour.Value == "Do_Nothing" then
Weight *= 2
end
return Weight
end,
}
local Movement_Considerations = {
Stop = function(Npc)
return 0.1
end,
}
for i,Vector_String in pairs(Move_Directions) do
Movement_Considerations[Vector_String] = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Weight = 0
local Desired_Point = Get_Target_Point(Npc, false)
if Desired_Point then
Weight = Check_Move_Direction(Npc,Desired_Point,Stats.Mouse_Locked.Value,Convert_Vector(Vector_String, Stats.Climbing.Value))
end
return Weight
end
end
local Get_Best = function(Table, ...)
local Best = {Weight = -1, Value = nil}
for i,F in pairs(Table) do
local Current_Weight = F(...)
if Current_Weight > Best.Weight then
Best = {Weight = Current_Weight, Value = i}
end
end
return Best.Value, Best.Weight
end
local Actions_Main = function(Npc, Action_Module)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Behaviour = Get_Best(Behaviour_Considerations, Npc)
local Action = Get_Best(Action_Considerations, Npc)
if Npc.Name == "Npc_1" then
--print(Behaviour,Action)
end
C_Stats.Current_Behaviour.Value = Behaviour
if Action == "Equip_Weapon" then
Equip_Any_Weapon(Npc, Action_Module)
elseif Action == "Unequip_Weapon" then
Unequip_Any_Weapon(Npc, Action_Module)
elseif Action == "Eat" then
Eat_Food(Npc, Action_Module)
elseif Action == "Jump" then
Npc.Humanoid.Jump = true
elseif Action == "Find_Body" then
C_Stats.Target_Body.Value = C_Stats.Target_Enemy.Value
elseif Action ~= "Do_Nothing" then
Action_Input(Npc, Action, Action_Module)
end
end
local Movement_Main = function(Npc)
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
local Direction = Get_Best(Movement_Considerations, Npc)
if not Stats.Climbing.Value then
if Direction ~= "Stop" then
Npc.Humanoid:Move(Relative_Vector(Npc.PrimaryPart.CFrame, Convert_Vector(Direction, false)))
else
Npc.Humanoid:Move(Vector3.new(0,0,0))
end
else
if Direction ~= "Stop" then
C_Stats.Climb_Direction.Value = Convert_Vector(Direction, true)
else
C_Stats.Climb_Direction.Value = Vector3.new(0,0,0)
end
end
end
local Main = function(Npc)
local Npc_Data = Npc_Data_Module[Npc.Name]
if Npc_Data then
local Module_Clone = Module_Scripts.Action_Module:Clone()
local Action_Module = require(Module_Clone)
local C_Stats = Npc:WaitForChild("Npc_Stats")
local Stats = Npc:WaitForChild("Character_Data")
local Look_Object = nil
local Changes = {}
Action_Module.Enable_Hitting(Npc)
Action_Module.Enable_Cancelling(Npc)
Stamina_Module.Stamina_Loop(C_Stats,Npc.Humanoid,Stats)
spawn(function()
while Npc.Humanoid:GetState() ~= Enum.HumanoidStateType.Dead and Npc.Parent do
if C_Stats.Target_Enemy.Value then
wait(0.1)
else
wait(0.5)
end
spawn(function()
Actions_Main(Npc, Action_Module)
end)
spawn(function()
Look_Object = Npc.PrimaryPart:FindFirstChild("Mouse_Lock")
if Look_Object and not Stats.Climbing.Value then
if not Stats.Knocked_Out.Value then
if Stats.Mouse_Locked.Value or C_Stats.Current_Behaviour.Value == "Dialog" then
local Target_P = Get_Target_Point(Npc, true)
if C_Stats.Current_Behaviour.Value == "Dialog" then
Look_Object.D = 500 / Npc_Data.Dialog_Turn_Speed
else
Look_Object.D = 150
end
Look_Object.MaxTorque = Vector3.new(500000,500000,500000)
if Target_P then
Look_Object.CFrame = CFrame.new(Npc.PrimaryPart.Position, Vector3.new(Target_P.X,Npc.PrimaryPart.Position.Y,Target_P.Z))
end
else
Look_Object.D = 150
Look_Object.MaxTorque = Vector3.new(500000,0,500000)
Look_Object.CFrame = CFrame.new(Npc.PrimaryPart.Position, Npc.PrimaryPart.Position + Vector3.new(0,0,-1))
end
else
Look_Object.MaxTorque = Vector3.new(0,0,0)
end
end
Movement_Main(Npc)
end)
end
end)
C_Stats.Target_Enemy:GetPropertyChangedSignal("Value"):Connect(function()
local Add_Function = function(Stat)
if Stat:IsA("ValueBase") and ((not Stat:IsA("NumberValue") and not Stat:IsA("IntValue")) or Stat.Parent.Name == "Blocking") then
local Change_Event = Stat.Changed:Connect(function()
Actions_Main(Npc, Action_Module)
end)
table.insert(Changes,1,Change_Event)
end
end
for i,Event in pairs(Changes) do
Event:Disconnect()
end
if C_Stats.Target_Enemy.Value then
for i,Stat in pairs(C_Stats.Target_Enemy.Value.Character_Data:GetDescendants()) do
Add_Function(Stat)
end
Add_Function(Stats.Stunned)
Add_Function(Stats.Stunned.Dodge_Stun)
Add_Function(Stats.Blocking)
Add_Function(Stats.Blocking.Hit_Count)
end
end)
spawn(function()
while Npc.Humanoid:GetState() ~= Enum.HumanoidStateType.Dead and Npc.Parent do
wait(1)
local Target_P = Get_Target_Point(Npc, true)
if Target_P then
local Is_Blocked = Check_Target_Visible(Npc.PrimaryPart.Position, Target_P)
C_Stats.Point_Visible.Value = not Is_Blocked
end
C_Stats.Desired_Weapon.Value = Find_Best_Weapon(Npc)
end
end)
Stats.Inventory.ChildAdded:Connect(function(Item)
local Data = Item_Data[Item.Name]
if Data.Type == "Food" then
Stats.Food_Item.Value = Item.Name
end
end)
Npc.Humanoid.Died:Connect(function()
Module_Clone:Destroy()
if Look_Object then
Look_Object:Destroy()
end
for i,Event in pairs(Changes) do
Event:Disconnect()
end
end)
end
end
local Select_Enemy = function(Player, Npc, Enemy)
if (Player and Enemy and Player.Character ~= Enemy) then return end
local C_Stats = Npc.Npc_Stats
local Stats = Npc.Character_Data
C_Stats.Target_Enemy.Value = Enemy
end
local Dialog_Change = function(Player, Npc, Bool)
if Npc then
local Character = Player.Character
local Stats = Character.Character_Data
local Npc_Stats = Npc.Npc_Stats
if Bool then
Npc_Stats.Target_Speaker.Value = Character
else
Npc_Stats.Target_Speaker.Value = nil
end
end
end
wait(1)
Remote_Events.Npc_Hostile_Event.OnServerEvent:Connect(Select_Enemy)
Server_Events.Npc_Hostile_Event.Event:Connect(Select_Enemy)
Server_Events.Npc_Character_Event.Event:Connect(Main)
Remote_Events.Set_Dialog_Event.OnServerEvent:Connect(Dialog_Change)
Server_Events.Set_Dialog_Event.Event:Connect(Dialog_Change)