Загрузка данных


local RunService = game:GetService("RunService")

local Toad = {}
Toad.__index = Toad

local FOLLOW_RADIUS   = 8
local AGGRO_RADIUS    = 15
local LEASH_RADIUS    = 20
local JUMP_HEIGHT     = 5
local JUMP_TIME       = 0.45
local ATTACK_DAMAGE   = 10

function Toad.new(model, owner)
    local self = setmetatable({}, Toad)
    self.model = model
    self.owner = owner
    self.state = "Follow"
    self.target = nil
    return self
end

function Toad:FindEnemy()
    local myPos = self.model.PrimaryPart.Position
    local best, bestDist
    for _, enemy in ipairs(workspace.Enemies:GetChildren()) do
        if enemy.PrimaryPart then
            local d = (enemy.PrimaryPart.Position - myPos).Magnitude
            if not bestDist or d < bestDist then
                best, bestDist = enemy, d
            end
        end
    end
    return best, bestDist
end

function Toad:Update()
    if self.state == "Jumping" then return end

    local ownerPos = self.owner.PrimaryPart.Position
    local myPos = self.model.PrimaryPart.Position

    if self.target then
        if not self.target.Parent
        or (self.target.PrimaryPart.Position - ownerPos).Magnitude > LEASH_RADIUS then
            self.target = nil
        end
    end

    if not self.target then
        local enemy, dist = self:FindEnemy()
        if enemy and dist <= AGGRO_RADIUS then
            self.target = enemy
        end
    end

    if self.target then
        self:JumpTo(self.target.PrimaryPart.Position, true)
    else
        if (myPos - ownerPos).Magnitude > FOLLOW_RADIUS then
            local off = Vector3.new(math.random(-4,4), 0, math.random(-4,4))
            self:JumpTo(ownerPos + off, false)
        end
    end
end

function Toad:JumpTo(targetPos, isAttack)
    self.state = "Jumping"
    local root = self.model.PrimaryPart
    local start = root.Position
    local t0 = tick()

    local conn
    conn = RunService.Heartbeat:Connect(function()
        local a = (tick() - t0) / JUMP_TIME
        if a >= 1 then
            conn:Disconnect()
            root.CFrame = CFrame.new(targetPos)
            if isAttack and self.target and self.target.Parent then
                self:Hit(self.target)
            end
            self.state = "Follow"
            return
        end

        local flat = start:Lerp(targetPos, a)
        local height = math.sin(a * math.pi) * JUMP_HEIGHT
        local pos = flat + Vector3.new(0, height, 0)

        local lookDir = (targetPos - start)
        local yaw = math.atan2(-lookDir.X, -lookDir.Z)
        local flip = CFrame.Angles(a * math.pi * 2, 0, 0)

        root.CFrame = CFrame.new(pos) * CFrame.Angles(0, yaw, 0) * flip
    end)
end

function Toad:Hit(enemy)
    local hum = enemy:FindFirstChild("Humanoid")
    if hum then
        hum:TakeDamage(ATTACK_DAMAGE)
    end
end

return Toad