-- Rush Duel 基础
RushDuel = RushDuel or {}

-- 新种族
RACE_MAGICALKNIGHT = 0x4000000 -- 魔导骑士
RACE_HYDRAGON = 0x8000000 -- 多头龙
RACE_OMEGAPSYCHO = 0x10000000 -- 欧米茄念动力
RACE_CELESTIALWARRIOR = 0x20000000 -- 天界战士
RACE_GALAXY = 0x40000000 -- 银河
RACE_CYBORG = 0x80000000 -- 电子人

RACE_ALL = 0xffffffff

-- 特殊调整
EFFECT_LEGEND_CARD = 120000000 -- 传说卡标识 (改变卡名不影响)
EFFECT_CANNOT_SINGLE_TRIBUTE = 120170045 -- 监狱岛 大姐头巨岩 (与下面的效果结合变成不能上级召唤)
EFFECT_CANNOT_DOUBLE_TRIBUTE = 120120029 -- 魔将 雅灭鲁拉 (不能使用：双重解放)
EFFECT_PLAYER_CANNOT_ATTACK = 120155054 -- 幻刃封锁 (对方不能攻击时不能发动)
EFFECT_PLAYER_RACE_CANNOT_ATTACK = 120155055 -- 幻刃封锁 (不能选择不能攻击的种族)

FLAG_NOT_SUMMON_TURN = 120000001 -- 召唤·特殊召唤的回合被盖放, 不再符合召唤·特殊召唤的回合的条件

-- 创建效果: 玩家对象的全局效果
function RushDuel.CreatePlayerTargetGlobalEffect(code, value)
    local e1 = Effect.GlobalEffect()
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(code)
    e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET)
    e1:SetTargetRange(1, 1)
    if value ~= nil then
        e1:SetValue(value)
    end
    Duel.RegisterEffect(e1, 0)
    return e1
end
-- 创建效果: 影响全场的全局效果
function RushDuel.CreateFieldGlobalEffect(is_continuous, code, operation)
    local e1 = Effect.GlobalEffect()
    if is_continuous then
        e1:SetType(EFFECT_TYPE_FIELD + EFFECT_TYPE_CONTINUOUS)
    else
        e1:SetType(EFFECT_TYPE_FIELD)
    end
    e1:SetCode(code)
    e1:SetOperation(operation)
    Duel.RegisterEffect(e1, 0)
    return e1
end
-- 创建效果: 在LP槽显示提示信息
function RushDuel.CreateHintEffect(e, desc, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetDescription(desc)
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET + EFFECT_FLAG_CLIENT_HINT)
    e1:SetTargetRange(s_range, o_range)
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    return e1
end
-- 创建效果: 只能用特定类型的怪兽攻击 (对玩家效果)
function RushDuel.CreateAttackLimitEffect(e, target, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_ATTACK)
    e1:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
    e1:SetTargetRange(s_range, o_range)
    if target ~= nil then
        e1:SetTarget(target)
    end
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    return e1
end
-- 创建效果: 不能攻击 (对玩家效果)
function RushDuel.CreateCannotAttackEffect(e, hint, player, s_range, o_range, reset)
    local s_target, o_traget = 0, 0
    if s_range == 1 then
        s_target = LOCATION_MZONE
    end
    if o_range == 1 then
        o_traget = LOCATION_MZONE
    end
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_ATTACK)
    e1:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
    e1:SetTargetRange(s_target, o_traget)
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    local e2 = Effect.CreateEffect(e:GetHandler())
    e2:SetDescription(hint)
    e2:SetType(EFFECT_TYPE_FIELD)
    e2:SetCode(EFFECT_PLAYER_CANNOT_ATTACK)
    e2:SetProperty(EFFECT_FLAG_PLAYER_TARGET + EFFECT_FLAG_CLIENT_HINT)
    e2:SetTargetRange(s_range, o_range)
    e2:SetReset(reset)
    Duel.RegisterEffect(e2, player)
    return e1, e2
end
-- 创建效果: 不能用某些种族攻击 (对玩家效果)
function RushDuel.CreateRaceCannotAttackEffect(e, hint, race, player, s_range, o_range, reset)
    local s_target, o_traget = 0, 0
    if s_range == 1 then
        s_target = LOCATION_MZONE
    end
    if o_range == 1 then
        o_traget = LOCATION_MZONE
    end
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_ATTACK)
    e1:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
    e1:SetTargetRange(s_target, o_traget)
    e1:SetTarget(function(e, c)
        return c:IsRace(race)
    end)
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    local e2 = Effect.CreateEffect(e:GetHandler())
    e2:SetDescription(hint)
    e2:SetType(EFFECT_TYPE_FIELD)
    e2:SetCode(EFFECT_PLAYER_RACE_CANNOT_ATTACK)
    e2:SetProperty(EFFECT_FLAG_PLAYER_TARGET + EFFECT_FLAG_CLIENT_HINT)
    e2:SetTargetRange(s_range, o_range)
    e2:SetValue(race)
    e2:SetReset(reset)
    Duel.RegisterEffect(e2, player)
    return e1, e2
end
-- 创建效果: 不能直接攻击 (对玩家效果)
function RushDuel.CreateCannotDirectAttackEffect(e, target, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_DIRECT_ATTACK)
    e1:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
    e1:SetTargetRange(s_range, o_range)
    if target ~= nil then
        e1:SetTarget(target)
    end
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    return e1
end
-- 创建效果: 不能选择攻击目标 (对玩家效果)
function RushDuel.CreateCannotSelectBattleTargetEffect(e, target, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_SELECT_BATTLE_TARGET)
    e1:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
    e1:SetTargetRange(s_range, o_range)
    if target ~= nil then
        e1:SetTarget(target)
    end
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    return e1
end
-- 创建效果: 不能召唤怪兽 (对玩家效果)
function RushDuel.CreateCannotSummonEffect(e, desc, target, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetDescription(desc)
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_SUMMON)
    e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET + EFFECT_FLAG_CLIENT_HINT)
    e1:SetTargetRange(s_range, o_range)
    if target ~= nil then
        e1:SetTarget(target)
    end
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    return e1
end
-- 创建效果: 不能盖放怪兽 (对玩家效果)
function RushDuel.CreateCannotSetMonsterEffect(e, desc, target, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetDescription(desc)
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_MSET)
    e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET + EFFECT_FLAG_CLIENT_HINT)
    e1:SetTargetRange(s_range, o_range)
    if target ~= nil then
        e1:SetTarget(target)
    end
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    local e2 = Effect.CreateEffect(e:GetHandler())
    e2:SetType(EFFECT_TYPE_FIELD)
    e2:SetCode(EFFECT_LIMIT_SPECIAL_SUMMON_POSITION)
    e2:SetProperty(EFFECT_FLAG_PLAYER_TARGET)
    e2:SetTargetRange(s_range, o_range)
    e2:SetTarget(function(e, c, sump, sumtype, sumpos, targetp)
        return sumpos&POS_FACEDOWN > 0 and (not target or target(e, c))
    end)
    e2:SetReset(reset)
    Duel.RegisterEffect(e2, player)
    return e1, e2
end
-- 创建效果: 不能特殊召唤怪兽 (对玩家效果)
function RushDuel.CreateCannotSpecialSummonEffect(e, desc, target, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetDescription(desc)
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_SPECIAL_SUMMON)
    e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET + EFFECT_FLAG_CLIENT_HINT)
    e1:SetTargetRange(s_range, o_range)
    if target ~= nil then
        e1:SetTarget(target)
    end
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    return e1
end
-- 创建效果: 只能用1只怪兽进行攻击 (对玩家效果)
function RushDuel.CreateOnlySoleAttackEffect(e, code, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetType(EFFECT_TYPE_FIELD + EFFECT_TYPE_CONTINUOUS)
    e1:SetCode(EVENT_ATTACK_ANNOUNCE)
    e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE)
    e1:SetOperation(function(e, tp, eg, ep, ev, re, r, rp)
        if Duel.GetFlagEffect(tp, code) == 0 then
            e:GetLabelObject():SetLabel(eg:GetFirst():GetFieldID())
            Duel.RegisterFlagEffect(tp, code, reset, 0, 1)
        end
    end)
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    local e2 = Effect.CreateEffect(e:GetHandler())
    e2:SetType(EFFECT_TYPE_FIELD)
    e2:SetCode(EFFECT_CANNOT_ATTACK_ANNOUNCE)
    e2:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
    e2:SetTargetRange(s_range, o_range)
    e2:SetCondition(function(e)
        return Duel.GetFlagEffect(e:GetHandlerPlayer(), code) ~= 0
    end)
    e2:SetTarget(function(e, c)
        return c:GetFieldID() ~= e:GetLabel()
    end)
    e1:SetLabelObject(e2)
    e2:SetReset(reset)
    Duel.RegisterEffect(e2, player)
end
-- 创建效果: 只能用这张卡进行攻击 (对玩家效果)
function RushDuel.CreateOnlyThisAttackEffect(e, code, player, s_range, o_range, reset)
    local c = e:GetHandler()
    local e1 = Effect.CreateEffect(c)
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_ATTACK_ANNOUNCE)
    e1:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE)
    e1:SetLabelObject(c)
    e1:SetTargetRange(s_range, o_range)
    e1:SetTarget(function(e, c)
        return not (c == e:GetLabelObject() and c:GetFlagEffect(code) ~= 0)
    end)
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    c:RegisterFlagEffect(code, RESET_EVENT + RESETS_STANDARD - RESET_TURN_SET + reset, 0, 1)
end
-- 创建效果: 不能把效果发动 (对玩家效果)
function RushDuel.CreateCannotActivateEffect(e, desc, value, player, s_range, o_range, reset)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetDescription(desc)
    e1:SetType(EFFECT_TYPE_FIELD)
    e1:SetCode(EFFECT_CANNOT_ACTIVATE)
    e1:SetProperty(EFFECT_FLAG_PLAYER_TARGET + EFFECT_FLAG_CLIENT_HINT)
    e1:SetTargetRange(s_range, o_range)
    if value ~= nil then
        e1:SetValue(value)
    end
    e1:SetReset(reset)
    Duel.RegisterEffect(e1, player)
    return e1
end
-- 创建效果: Buff类效果
function RushDuel.CreateSingleEffect(e, desc, card, code, value, reset, forced)
    local e1 = Effect.CreateEffect(e:GetHandler())
    e1:SetType(EFFECT_TYPE_SINGLE)
    e1:SetCode(code)
    if value ~= nil then
        e1:SetValue(value)
    end
    if desc ~= nil then
        e1:SetDescription(desc)
        e1:SetProperty(EFFECT_FLAG_CLIENT_HINT)
    end
    if reset ~= nil then
        e1:SetReset(reset)
    end
    card:RegisterEffect(e1, forced)
    return e1
end
-- 创建效果: 选择效果
function RushDuel.CreateMultiChooseEffect(card, condition, cost, hint1, target1, operation1, hint2, target2, operation2, category1, category2)
    local e1 = Effect.CreateEffect(card)
    e1:SetType(EFFECT_TYPE_IGNITION)
    e1:SetRange(LOCATION_MZONE)
    local e2 = e1:Clone()
    e1:SetDescription(hint1)
    e2:SetDescription(hint2)
    e1:SetCategory(category1 or 0)
    e2:SetCategory(category2 or 0)
    if condition ~= nil then
        e1:SetCondition(condition)
        e2:SetCondition(condition)
    end
    if cost ~= nil then
        e1:SetCost(cost)
        e2:SetCost(cost)
    end
    if target1 ~= nil then
        e1:SetTarget(target1)
    end
    if target2 ~= nil then
        e2:SetTarget(target2)
    end
    e1:SetOperation(operation1)
    e2:SetOperation(operation2)
    card:RegisterEffect(e1)
    card:RegisterEffect(e2)
    return e1, e2
end

-- 添加记述卡牌列表
function RushDuel.AddCodeList(card, ...)
    for _, list in ipairs {...} do
        local type = aux.GetValueType(list)
        if type == "number" then
            aux.AddCodeList(card, list)
        elseif type == "table" then
            aux.AddCodeList(card, table.unpack(list))
        end
    end
end
-- 添加永续效果列表
function RushDuel.AddContinuousEffect(c, ...)
    if c:IsStatus(STATUS_COPYING_EFFECT) then
        return
    end
    if c.continuous_effect == nil then
        local mt = getmetatable(c)
        mt.continuous_effect = {...}
    else
        for _, e in ipairs {...} do
            table.insert(c.continuous_effect, e)
        end
    end
end

-- 获取效果值列表
function RushDuel.GetEffectValues(card, code)
    local effects = {card:IsHasEffect(code)}
    local values = {}
    for i, effect in ipairs(effects) do
        values[i] = effect:GetValue()
    end
    return values
end

-- 抹平表
function RushDuel.FlatTable(...)
    local result = {}
    for _, item in ipairs({...}) do
        if type(item) == "table" then
            local datas = RushDuel.FlatTable(table.unpack(item))
            for _, data in ipairs(datas) do
                table.insert(result, data)
            end
        else
            table.insert(result, item)
        end
    end
    return result
end
-- 递归检查表
function RushDuel.FlatCheck(check, ...)
    for _, item in ipairs({...}) do
        if type(item) == "table" then
            if RushDuel.FlatCheck(check, table.unpack(item)) then
                return true
            end
        elseif check(item) then
            return true
        end
    end
    return false
end
