--[[
 -- @Description:
 -- Hello , DiaoSi ~ ( or not ? ) ,glad you saw my comment
 -- If you think my mod is okay , you can sponsor my breakfast by a tiny amount donation  ($_$)
 -- paypal:td1madao@163.com     alipay:td1madao@163.com
 -- If any question ,Please email me
 -- What's more ,don't modify and republish my mods . 3Q for cooperation
 -- What's more ,don't modify and republish my mods . 3Q for cooperation
 -- What's more ,don't modify and republish my mods . 3Q for cooperation
 -- @version 1.0.0
 -- @author td1madao
 -- @email td1madao@163.com
 -- @qq 360810498
 -- @date 16/8/6
 ]]
local TD = TD.td1madao.rivendst
local function server_qeffect(v)
    if not v then
        return
    end
    TD.below(v, "rivenq2")
    TD.below(v, "rivenq1")
    TD.color(TD.below(v, "firesplash_fx"), 0, 1, 0).Transform:SetScale(0.5, 0.5, 0.5)
end

local function server_rivendstRCancelFn(inst)
    local syn = TD.getC(inst, "rivendst_common_synchronizer")
    syn:server_set("rivenRtwice", false)
    syn.server_rivenRBuff = false
    local equip = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
    if equip and equip:HasTag('rivendstsword') and equip.AnimState and equip.components.equippable and equip.components.equippable.onequipfn then
        equip.components.equippable.onequipfn(equip, inst)
    end
end

local s1 = _G.State {
    name = "td1madao_rivendst_q1",
    tags = { "notalking", "abouttoattack", "autopredict", "td1madao_skill" },
    onenter = function(inst, pos)
        TD.see("td1madao_rivendst_q1_enter")
        local dmg = 10
        local equip = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
        if equip and equip.components.weapon then
            dmg = equip.components.weapon.damage or 10
        end
        local playerPos = Vector3(inst:GetPosition():Get())
        playerPos.y = 0
        if not pos then
            pos = playerPos
        end
        local syn = TD.getC(inst, "rivendst_common_synchronizer")
        syn.server_local_tag = "q"
        inst:ForceFacePoint(pos.x, pos.y, pos.z)
        inst.components.combat:SetTarget(nil)
        syn.server_x = pos.x
        syn.server_y = pos.y
        syn.server_z = pos.z
        syn.server_dmg = dmg
        inst.sg:SetTimeout(10 * FRAMES)
        local dist = TD.dist(playerPos.x, pos.x, playerPos.z, pos.z)
        if dist > 8 then
            dist = 8
        end
        TD.getC(inst, "rivendst_global_anim"):server_set("common_rotation", inst:GetRotation())
        TD.getC(inst, "rivendst_global_anim"):server_set("common_speed", dist * 4)
        TD.getC(inst, "rivendst_global_anim"):server_setByAnimNum("animQ1")
    end,
    timeline =
    {
        TimeEvent(5 * FRAMES, function(inst)
            inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_weapon")
            local ents = TD.find(inst, 4)
            server_qeffect(inst)
            TD.server_attack(inst, ents, function(v)
                server_qeffect(v)
            end, 1, true)
        end),
    },
    ontimeout = function(inst)
        TD.see("td1madao_rivendst_q1_timeout")
        inst.sg:GoToState("idle")
    end,
    onexit = function(inst)
        local syn = TD.getC(inst, "rivendst_common_synchronizer")
        TD.see("td1madao_rivendst_q1_exit")
        syn.server_aftercast = true
        if inst.components.playercontroller ~= nil then
            inst.components.playercontroller:Enable(true)
        end
        if inst.Physics.ClearMotorVelOverride ~= nil then
            inst.Physics:ClearMotorVelOverride()
        end
    end,
}
local s2 = _G.State {
    name = "td1madao_rivendst_q2",
    tags = { "notalking", "abouttoattack", "autopredict", "td1madao_skill" },
    onenter = function(inst, pos)
        TD.see("td1madao_rivendst_q2_enter")
        local dmg = 10
        local equip = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
        if equip and equip.components.weapon then
            dmg = equip.components.weapon.damage or 10
        end
        local playerPos = Vector3(inst:GetPosition():Get())
        playerPos.y = 0
        if not pos then
            pos = playerPos
        end
        local syn = TD.getC(inst, "rivendst_common_synchronizer")
        syn.server_local_tag = "q"
        inst:ForceFacePoint(pos.x, pos.y, pos.z)
        inst.components.combat:SetTarget(nil)
        syn.server_x = pos.x
        syn.server_y = pos.y
        syn.server_z = pos.z
        syn.server_dmg = dmg
        inst.sg:SetTimeout(10 * FRAMES)
        local dist = TD.dist(playerPos.x, pos.x, playerPos.z, pos.z)
        if dist > 8 then
            dist = 8
        end
        TD.getC(inst, "rivendst_global_anim"):server_set("common_rotation", inst:GetRotation())
        TD.getC(inst, "rivendst_global_anim"):server_set("common_speed", dist * 4)
        TD.getC(inst, "rivendst_global_anim"):server_setByAnimNum("animQ2")
    end,
    timeline =
    {
        TimeEvent(5 * FRAMES, function(inst)
            inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_weapon")
            local ents = TD.find(inst, 4)
            server_qeffect(inst)
            TD.server_attack(inst, ents, function(v)
                server_qeffect(v)
            end, 1, true)
        end),
    },
    ontimeout = function(inst)
        TD.see("td1madao_rivendst_q2_timeout")
        inst.sg:GoToState("idle")
    end,
    onexit = function(inst)
        TD.see("td1madao_rivendst_q2_exit")
        local syn = TD.getC(inst, "rivendst_common_synchronizer")
        syn.server_aftercast = true
        if inst.components.playercontroller ~= nil then
            inst.components.playercontroller:Enable(true)
        end
        if inst.Physics.ClearMotorVelOverride ~= nil then
            inst.Physics:ClearMotorVelOverride()
        end
    end,
}
local s3 = _G.State {
    name = "td1madao_rivendst_q3",
    tags = { "notalking", "abouttoattack", "autopredict", "td1madao_skill" },
    onenter = function(inst, pos)
        TD.see("td1madao_rivendst_q3_enter")
        local dmg = 10
        local equip = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
        if equip and equip.components.weapon then
            dmg = equip.components.weapon.damage or 10
        end
        local playerPos = Vector3(inst:GetPosition():Get())
        playerPos.y = 0
        if not pos then
            pos = playerPos
        end
        local syn = TD.getC(inst, "rivendst_common_synchronizer")
        syn.server_local_tag = "q"
        inst:ForceFacePoint(pos.x, pos.y, pos.z)
        inst.components.combat:SetTarget(nil)
        syn.server_dmg = dmg
        inst.sg:SetTimeout(20 * FRAMES)
        local dist = TD.dist(playerPos.x, pos.x, playerPos.z, pos.z)
        local odist = dist
        if odist > 13 then
            odist = 13
        end
        local spx = playerPos.x + (pos.x - playerPos.x) * (odist / dist)
        local spz = playerPos.z + (pos.z - playerPos.z) * (odist / dist)
        pos.x = spx
        pos.z = spz
        syn.server_x = pos.x
        syn.server_y = pos.y
        syn.server_z = pos.z
        if TD.canMoveTo(inst, spx, 0, spz) then
            TD.getC(inst, "rivendst_global_anim"):server_set("common_speed", dist * 5)
            TD.fly(inst)
            syn.server_q3fly = true
        else
            TD.getC(inst, "rivendst_global_anim"):server_set("common_speed", dist * 4 / 6)
            syn.server_q3fly = false
        end
        TD.getC(inst, "rivendst_global_anim"):server_set("common_rotation", inst:GetRotation())
        TD.getC(inst, "rivendst_global_anim"):server_setByAnimNum("animQ3")
    end,
    timeline =
    {
        TimeEvent(12 * FRAMES, function(inst)
            inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_weapon")
        end),
        TimeEvent(18 * FRAMES, function(inst)
            local syn = TD.getC(inst, "rivendst_common_synchronizer")
            if syn.server_q3fly then
                TD.stopFly(inst)
                inst.Transform:SetPosition(syn.server_x, 0, syn.server_z)
            end
            local ents = TD.find(inst, 4)
            server_qeffect(inst)
            TD.server_attack(inst, ents, function(v)
                server_qeffect(v)
                TD.blewUp(v, inst)
            end, 1, true)
        end),
    },
    ontimeout = function(inst)
        TD.see("td1madao_rivendst_q3_timeout")
        inst.sg:GoToState("idle")
    end,
    onexit = function(inst)
        TD.see("td1madao_rivendst_q3_exit")
        local syn = TD.getC(inst, "rivendst_common_synchronizer")
        syn.server_aftercast = true
        local tag = syn.server_local_tag
        local skill = TD.getC(inst, "rivendst_common_skill_manager").skill
        local skillBuffer = TD.getC(inst, "rivendst_common_skill_manager").skillBuffer
        local cd = skillBuffer[tag].maxCd - 1
        if cd < 0 then
            cd = 1
        end
        skill[tag].cd = cd

        local skill_manager = TD.getC(inst, "rivendst_common_skill_manager")
        local num = skill_manager:player_letter2num(tag)
        syn:server_setAllInCd(num)

        if inst.components.playercontroller ~= nil then
            inst.components.playercontroller:Enable(true)
        end
        if inst.Physics.ClearMotorVelOverride ~= nil then
            inst.Physics:ClearMotorVelOverride()
        end
    end,
}
local s4 = _G.State {
    name = "td1madao_rivendst_w",
    tags = { "notalking", "abouttoattack", "autopredict", "td1madao_skill" },
    onenter = function(inst)
        TD.see("td1madao_rivendst_w_enter")
        local dmg = 10
        local equip = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
        if equip and equip.components.weapon then
            dmg = equip.components.weapon.damage or 10
        end
        local syn = TD.getC(inst, "rivendst_common_synchronizer")
        syn.server_local_tag = "w"
        inst.components.combat:SetTarget(nil)
        syn.server_dmg = dmg
        inst.sg:SetTimeout(9 * FRAMES)
        TD.getC(inst, "rivendst_global_anim"):server_setByAnimNum("animW")
    end,
    timeline =
    {
        TimeEvent(5 * FRAMES, function(inst)
            inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_weapon")
            local ents = TD.find(inst, 4)
            TD.below(inst, "rivenw").Transform:SetScale(.4, .4, .4)
            TD.server_attack(inst, ents, function(v)
                TD.dizzy(v, inst)
            end, 1, true)
        end),
    },
    ontimeout = function(inst)
        TD.see("td1madao_rivendst_w_timeout")
        inst.sg:GoToState("idle")
    end,
    onexit = function(inst)
        TD.see("td1madao_rivendst_w_exit")
        local syn = TD.getC(inst, "rivendst_common_synchronizer")
        syn.server_aftercast = true
        local tag = syn.server_local_tag
        local skill = TD.getC(inst, "rivendst_common_skill_manager").skill
        local skillBuffer = TD.getC(inst, "rivendst_common_skill_manager").skillBuffer
        local cd = skillBuffer[tag].maxCd - 1
        if cd < 0 then
            cd = 1
        end
        skill[tag].cd = cd
        local skill_manager = TD.getC(inst, "rivendst_common_skill_manager")
        local num = skill_manager:player_letter2num(tag)
        syn:server_setAllInCd(num)
        if inst.components.playercontroller ~= nil then
            inst.components.playercontroller:Enable(true)
        end
    end,
}
local s5 = _G.State {
    name = "td1madao_rivendst_e",
    tags = { "notalking", "abouttoattack", "autopredict", "td1madao_skill" },
    onenter = function(inst, pos)
        TD.see("td1madao_rivendst_e_enter")
        local playerPos = Vector3(inst:GetPosition():Get())
        playerPos.y = 0
        if not pos then
            pos = playerPos
        end
        local syn = TD.getC(inst, "rivendst_common_synchronizer")
        syn.server_local_tag = "e"
        inst:ForceFacePoint(pos.x, pos.y, pos.z)
        inst.components.combat:SetTarget(nil)
        syn.server_x = pos.x
        syn.server_y = pos.y
        syn.server_z = pos.z
        inst.sg:SetTimeout(10 * FRAMES)
        local dist = TD.dist(playerPos.x, pos.x, playerPos.z, pos.z)
        if dist > 12 then
            dist = 12
        end
        TD.getC(inst, "rivendst_global_anim"):server_set("common_rotation", inst:GetRotation())
        TD.getC(inst, "rivendst_global_anim"):server_set("common_speed", dist * 5)
        TD.getC(inst, "rivendst_global_anim"):server_setByAnimNum("animE")
    end,
    timeline =
    {
        TimeEvent(1 * FRAMES, function(inst)
            inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_weapon")
            inst.rivenServerForcefieldfx = TD.color(TD.child(inst, "rivendst_shield"), 0, 1, 0)
            inst.components.health.absorb = 1
            local syn = TD.getC(inst, "rivendst_common_synchronizer")
            syn.server_armor = 45
            TD.getC(inst, "rivendst_common_task_manager"):player_task(3, function()
                syn.server_armor = 0
                inst.components.health.absorb = 0
                TD.remove(inst.rivenServerForcefieldfx)
                inst.rivenServerForcefieldfx = nil
            end, "td1madaoRivendstArmorCDTimeOut")
        end),
    },
    ontimeout = function(inst)
        TD.see("td1madao_rivendst_e_timeout")
        inst.sg:GoToState("idle")
    end,
    onexit = function(inst)
        TD.see("td1madao_rivendst_e_exit")
        local syn = TD.getC(inst, "rivendst_common_synchronizer")
        syn.server_aftercast = true
        local tag = syn.server_local_tag
        local skill = TD.getC(inst, "rivendst_common_skill_manager").skill
        local skillBuffer = TD.getC(inst, "rivendst_common_skill_manager").skillBuffer
        local cd = skillBuffer[tag].maxCd - 1
        if cd < 0 then
            cd = 1
        end
        skill[tag].cd = cd
        local skill_manager = TD.getC(inst, "rivendst_common_skill_manager")
        local num = skill_manager:player_letter2num(tag)
        syn:server_setAllInCd(num)
        if inst.components.playercontroller ~= nil then
            inst.components.playercontroller:Enable(true)
        end
    end,
}
local s6 = _G.State {
    name = "td1madao_rivendst_r1",
    tags = {},
    onenter = function(inst)
        TD.see("td1madao_rivendst_r1_enter")
        local equip = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
        local syn = TD.getC(inst, "rivendst_common_synchronizer")
        syn:server_set("rivenRtwice", true)
        syn.server_rivenRBuff = true
        syn.server_aftercast = true
        TD.getC(inst, "rivendst_common_task_manager"):player_task(15, function()
            local rivenRtwice = syn:server_get("rivenRtwice")
            if not rivenRtwice then
                return
            end
            server_rivendstRCancelFn(inst)
            local tag = "r"
            local skill = TD.getC(inst, "rivendst_common_skill_manager").skill
            local skillBuffer = TD.getC(inst, "rivendst_common_skill_manager").skillBuffer
            local cd = skillBuffer[tag].maxCd - 1
            if cd < 0 then
                cd = 1
            end
            skill[tag].cd = cd
            local skill_manager = TD.getC(inst, "rivendst_common_skill_manager")
            local num = skill_manager:player_letter2num(tag)
            syn:server_setAllInCd(num)
            TD.getC(inst, "rivendst_common_task_manager"):common_clean("td1madaoRivendstRBuff")
        end, "td1madaoRivendstRBuff")
        local fx2 = TD.color(TD.below(inst, "statue_transition"), 0, 1, 0)
        fx2.Transform:SetScale(2, 2, 2)
        if equip and equip:HasTag('rivendstsword') and equip.AnimState and equip.components.equippable and equip.components.equippable.onequipfn then
            equip.components.equippable.onequipfn(equip, inst)
        end
        inst.sg:SetTimeout(2 * FRAMES)
    end,
    timeline =
    {
        TimeEvent(1 * FRAMES, function(inst) end),
    },
    ontimeout = function(inst)
        TD.see("td1madao_rivendst_r1_timeout")
        inst.sg:GoToState("idle")
    end,
    onexit = function(inst)
        TD.see("td1madao_rivendst_r1_exit")
    end,
}
local s7 = _G.State {
    name = "td1madao_rivendst_r2",
    tags = { "notalking", "abouttoattack", "autopredict", "td1madao_skill" },
    onenter = function(inst, pos)
        TD.see("td1madao_rivendst_r2_enter")
        local dmg = 10
        local equip = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
        if equip and equip.components.weapon then
            dmg = equip.components.weapon.damage or 10
        end
        local playerPos = Vector3(inst:GetPosition():Get())
        playerPos.y = 0
        if not pos then
            pos = playerPos
        end
        local syn = TD.getC(inst, "rivendst_common_synchronizer")
        syn.server_local_tag = "r"
        inst:ForceFacePoint(pos.x, pos.y, pos.z)
        inst.components.combat:SetTarget(nil)
        syn.server_x = pos.x
        syn.server_y = pos.y
        syn.server_z = pos.z
        syn.server_dmg = dmg
        inst.sg:SetTimeout(30 * FRAMES)
        syn.server_angel = math.atan2(pos.z - playerPos.z, pos.x - playerPos.x)
        local dist = math.sqrt((pos.x - playerPos.x) * (pos.x - playerPos.x) + (pos.z - playerPos.z) * (pos.z - playerPos.z))
        TD.getC(inst, "rivendst_global_anim"):server_set("common_rotation", inst:GetRotation())
        TD.getC(inst, "rivendst_global_anim"):server_set("common_speed", dist * 4)
        TD.getC(inst, "rivendst_global_anim"):server_setByAnimNum("animR2")
    end,
    timeline =
    {
        TimeEvent(18 * FRAMES, function(inst)
            inst.SoundEmitter:PlaySound("dontstarve/tentacle/tentacle_attack")
            if inst.Physics.ClearMotorVelOverride ~= nil then
                inst.Physics:ClearMotorVelOverride()
            end
        end),
        TimeEvent(21 * FRAMES, function(inst)
            local playerPos = Vector3(inst:GetPosition():Get())
            local fx = TD.spawn("rivenr")
            local syn = TD.getC(inst, "rivendst_common_synchronizer")
            fx.Transform:SetScale(4, 4, 4)
            fx.Transform:SetPosition(playerPos.x, playerPos.y, playerPos.z)
            fx:ForceFacePoint(syn.server_x, syn.server_y, syn.server_z)
            fx.Physics:SetMotorVelOverride(15, 0, 0)
            fx.Physics:SetCollides(false)
        end),
        TimeEvent(24 * FRAMES, function(inst)
            local x3, y3, z3 = inst:GetPosition():Get()
            local ents = TD.find(inst, 20)
            local syn = TD.getC(inst, "rivendst_common_synchronizer")
            TD.server_attack(inst, ents, nil, 3, true, function(v)
                local x4, y4, z4 = v:GetPosition():Get()
                local ang = math.abs((math.atan2(z4 - z3, x4 - x3)) - syn.server_angel)
                return ang < .8
            end)
        end),
        TimeEvent(26 * FRAMES, function(inst)
            server_rivendstRCancelFn(inst)
        end),
    },
    ontimeout = function(inst)
        TD.see("td1madao_rivendst_r2_timeout")
        inst.sg:GoToState("idle")
    end,
    onexit = function(inst)
        TD.see("td1madao_rivendst_r2_exit")
        local syn = TD.getC(inst, "rivendst_common_synchronizer")
        syn.server_aftercast = true
        local tag = syn.server_local_tag
        local skill = TD.getC(inst, "rivendst_common_skill_manager").skill
        local skillBuffer = TD.getC(inst, "rivendst_common_skill_manager").skillBuffer
        local cd = skillBuffer[tag].maxCd - 1
        if cd < 0 then
            cd = 1
        end
        TD.getC(inst, "rivendst_common_task_manager"):common_clean("td1madaoRivendstRBuff")
        skill[tag].cd = cd
        local skill_manager = TD.getC(inst, "rivendst_common_skill_manager")
        local num = skill_manager:player_letter2num(tag)
        syn:server_setAllInCd(num)
        if inst.components.playercontroller ~= nil then
            inst.components.playercontroller:Enable(true)
        end
    end,
}
local route = _G.State {
    name = "td1madao_rivendst_accepter",
    tags = {},
    onenter = function(inst)
        TD.see("td1madao_rivendst_accepter")
        if inst.PerformBufferedAction then
            inst:PerformBufferedAction()
        end
    end,
    timeline =
    {},
    ontimeout = function(inst)
    end,
    onexit = function(inst)
    end,
}
TD.server(function()
    AddStategraphState("wilson", route)
    AddStategraphState("wilson", s1)
    AddStategraphState("wilson", s2)
    AddStategraphState("wilson", s3)
    AddStategraphState("wilson", s4)
    AddStategraphState("wilson", s5)
    AddStategraphState("wilson", s6)
    AddStategraphState("wilson", s7)
end)
AddStategraphState("wilson_client", route)