欢迎光临散文网 会员登陆 & 注册

测试

2023-03-10 21:50 作者:Haruna丶Sion  | 我要投稿

Effect = Class:extend()

Duel = {}

Helper = {}

Modifier = {}


function Effect:init(card, type, time, name)

    -- ctx 可能为 Card Player Attack

    local effect = GameEffect.Effect(type, time or 0)

    self.effect = effect

    if name ~= nil then

        effect.effectName = name

    end

    if type == EffectType.Event then

        -- 等待优化

        effect.card = card;

        game:AddEffect(effect)

    else

        card:AddEffect(effect)

    end

end


function Effect:SetOperation(call)

    if call == nil and self.effect.card ~= nil then

        print("========================ERROR EMPTY CALL: " .. self.effect.card.cardId .. "=========================")

    end

    local effect = self.effect


    local operation = function(...)

        local status, err = pcall(call, ...)

        if err then

            print(err)

        end

    end


    self.co = coroutine.create(operation);

    effect:SetOperation(function(...)

        if coroutine.status(self.co) == 'dead' then

            self.co = coroutine.create(operation)

        end

        coroutine.resume(self.co, ...)

    end)

end


function Effect:SetDestroy(call)

    if call == nil and self.effect.card ~= nil then

        print("========================ERROR EMPTY CALL: " .. self.effect.card.cardId .. "=========================")

    end

    local effect = self.effect


    local operation = function(...)

        local status, err = pcall(call, ...)

        if err then

            print(err)

        end

    end


    self.de_co = coroutine.create(operation);

    effect:SetDestroy(function(...)

        if coroutine.status(self.de_co) == 'dead' then

            self.de_co = coroutine.create(operation)

        end

        coroutine.resume(self.de_co, ...)

    end)

end


function Effect:SetCondition(call)

    local effect = self.effect

    effect:SetCondition(call)

end


function Effect:SetEventPlayer(eventPlayer)

    local effect = self.effect

    effect.EventPlayer = eventPlayer

end


function Effect:SetOnce()

    local effect = self.effect

    effect.IsOnce = true

end


function Helper.CreateCharaCard(charaId)

    local card = PlayObject.Card(null)

    card.id = -charaId

    return card

end


function Helper.RequestThroughout(player, card)

    card.IsThroughout = false

    if player.NormalActionUsed or player.ThroughoutActionUsed then

        return false

    end

    local used = game:FilterLogs(GameLogType.PlayCard, player)


    if used >1 then

        return false

    end


    local throughout = Duel.ShowDialog(player, "是否要使用全力化?")

    if throughout then

        card.IsThroughout = true

        player.ThroughoutActionUsed = true

    end

    

    return throughout

end


function Helper.AddExtendAction(player, actionName, call, condition)

    local operation = function(...)

        local status, err = pcall(call, ...)

        if err then

            print(err)

        end

    end

    local co = coroutine.create(operation);

    player:AddExtendAction(actionName, function(...)

        if coroutine.status(co) == 'dead' then

            co = coroutine.create(operation)

        end

        coroutine.resume(co, ...)

    end, condition)

end


function Helper.RemoveListener(card, effectName)

    if card ~=nil then

        game:RemoveEffect(card.id.."#"..effectName)

    else

        game:RemoveEffect(effectName)

    end

end


function Helper.Listen(effectName, card, event, eventPlayer, operation, condition)

    local e

    if card ~=nil then

        e = Effect(card, EffectType.Event, event, card.id.."#"..effectName)

    else

        e = Effect(card, EffectType.Event, event, effectName)

    end

    e:SetEventPlayer(eventPlayer)

    e:SetOperation(operation)

    if condition ~=nil then

        e:SetCondition(condition)

    end

    return e

end


function Helper.ListenOnce(effectName, card, event, eventPlayer, operation, condition)

    local e = Helper.Listen(effectName, card, event, eventPlayer, operation, condition)

    e:SetOnce()

    return e

end


function Helper.RemoveModifiersNextAttack(card, ctx, modifiers, condition)

    local function clear(effect)

        Helper.RemoveListener(effect.card, "helper_e1")

        Helper.RemoveListener(effect.card, "helper_e2")

        for key, eventName in pairs(modifiers) do

            ctx:RemoveModifier(effect.card, eventName)

        end

        effect:Complete()

    end


    Helper.ListenOnce("helper_e1", card, GameEventCode.END_TURN, -1, function(effect)

        clear(effect)

    end)

    

    Helper.Listen("helper_e2", card, GameEventCode.ATTACK, card.user.id, function(effect, payload)

        local attack = payload.attack

        if condition == nil or condition(attack) then

            clear(effect)

        else

            effect:Complete()

        end

    end)

end



function Modifier.MaxAura(card, value, op, condition)

    local m = GameEffect.MaxAuraModifier(value, op, condition);

    m.source = card;

    return m;

end


function Modifier.CardSubType(card, type, condition)

    local m = GameEffect.CardSubTypeModifier(type, condition);

    m.source = card;

    return m;

end


function Modifier.RemoveCardFlag(card, flag, condition)

    local m = GameEffect.RemoveCardFlagModifier(flag, condition);

    m.source = card;

    return m;

end


function Modifier.RemoveAttackFlag(card, flag, condition)

    local m = GameEffect.RemoveAttackFlagModifier(flag, condition);

    m.source = card;

    return m;

end


-- 攻击Buff


function Modifier.AttackDamageReplace(card, aura, life, condition)

    local m = GameEffect.AttackDamageReplace(aura, life, condition)

    m.source = card;

    return m;

end


function Modifier.AttackDamageExchange(card, condition)

    local m = GameEffect.AttackDamageExchange(condition);

    m.source = card;

    return m;

end


function Modifier.AttackDamageMultiple(card, aura, life, condition)

    local m = GameEffect.AttackDamageMultiple(aura, life, condition);

    m.source = card;

    return m;

end


function Modifier.AttackDamageDivide(card, aura, life, type, condition)

    local m = GameEffect.AttackDamageDivide(aura, life, type, condition);

    m.source = card;

    return m;

end


function Modifier.AttackDamagePlus(card, aura, life, condition)

    local m = GameEffect.AttackDamagePlus(aura, life, condition);

    m.source = card;

    return m;

end


-- 攻击Buff 结束


function Modifier.Cost(card, value, op, condition)

    local m = GameEffect.CostModifier(value, op, condition)

    m.source = card;

    return m;

end


function Modifier.Charge(card, value, op, condition)

    local m = GameEffect.ChargeModifier(value, op, condition)

    m.source = card;

    return m;

end


function Modifier.AttackRange(card, value, op, condition)

    local m = GameEffect.AttackRangeModifier(value, op, condition)

    m.source = card;

    return m;

end


function Modifier.AttackFlag(card, flag, condition)

    local m = GameEffect.AttackFlagModifier(flag, condition);

    m.source = card;

    return m;

end


function Modifier.CardFlag(card, flag, count, condition)

    count = count or 0

    local m = GameEffect.CardFlagModifier(flag, count, condition);

    m.source = card;

    return m;

end


function Modifier.HandLimit(card, value, condition)

    local m = GameEffect.HandLimitModifier(value, condition);

    m.source = card;

    return m;

end


function Modifier.PlayerFlag(card, flag, condition)

    local m = GameEffect.PlayerFlagModifier(flag, condition);

    m.source = card;

    return m;

end


function Modifier.AdditionalCardCost(cost, condition)

    local m = GameEffect.AdditionalCardCostModifier(cost, condition);

    m.source = card;

    return m;

end


function Modifier.CardUseLimit(card, condition)

    local m = GameEffect.CardUseLimitModifier(condition);

    m.source = card;

    return m;

end


function Modifier.NormalActionLimit(card, condition)

    local m = GameEffect.NormalActionLimitModifier(condition);

    m.source = card;

    return m;

end


function Modifier.Distance(card, value, op, condition)

    local m = GameEffect.DistanceModifier(value, op, condition);

    m.source = card;

    return m;

end


function Modifier.ExpertDistance(card, value, op, condition)

    local m = GameEffect.ExpertDistanceModifier(value, op, condition);

    m.source = card;

    return m;

end


function Modifier.DrawCardLimit(card, value, op, condition)

    local m = GameEffect.DrawCardLimitModifier(value, op, condition);

    m.overlay = true;

    m.source = card;

    return m;

end


function Duel.CheckEvent(player, code, payload)

    local co = coroutine.running()

    System.CheckEvent(player, code, payload,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.DisableToken(tokenZone)

    System.DisableToken(tokenZone)

end



function Duel.ShowMark(type, content)

    local co = coroutine.running()

    System.ShowMark(type, content, function(...)

        coroutine.resume(co, ...)

    end)

    return coroutine.yield(co)

end



function Duel.Sync()

    local co = coroutine.running()

    System.Sync(function(...)

        coroutine.resume(co, ...)

    end)

    return coroutine.yield(co)

end


function Duel.ShowDialog(player, content)

    local co = coroutine.running()

    System.ShowDialog(player, content,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.LoseGame(player)

    local co = coroutine.running()

    System.LoseGame(player,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.WinGame(player)

    local co = coroutine.running()

    System.WinGame(player,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.Irritation(player, value)

    local co = coroutine.running()

    System.Irritation(player, value,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.DealDamage(player, type, count)

    local co = coroutine.running()

    System.DealDamage(player, type, count,

            function(...)

                coroutine.resume(co, ...)

            end)

    return coroutine.yield(co)

end


function Duel.RemoveCard(card)

    card.status = CardStatus.None

    card.isProcessing = false

    Duel.MoveCard(card.owner, card.zone, card.owner:GetCardZone(CardZoneType.Outside), {card}, 0)

end


function Duel.DrawCard(player, count)

    local co = coroutine.running()

    System.DrawCard(player, count,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.OpenHandCards(viewer, target)

    local hand = target:GetCardZone(CardZoneType.Hand)

    Duel.SelectCard(viewer, "查看手牌", hand.list, 0, 0)

end


function Duel.OpenCard(card)

    local co = coroutine.running()

    System.OpenCard(card,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.ActivateCard(player, card)

    local co = coroutine.running()

    System.ActivateCard(player, card,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.DestroyEnhanceCard(player, card)

    local co = coroutine.running()

    System.DestroyEnhanceCard(player, card,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.MoveTop(player, origin, target, cards)

    Duel.MoveCard(player, origin, target, cards, Util.len(target.list))

end


function Duel.MoveBottom(player, origin, target, cards)

    Duel.MoveCard(player, origin, target, cards, 0)

end


function Duel.MoveCards(player, target, cards, position)

    if cards.Count ~= nil and cards.Length ~= nil then

        for _, card in pairs(cards) do

            Duel.MoveCard(player, card.zone, target, { card }, position);

        end

    else

        for i = 0, Util.len(cards)-1, 1 do

            Duel.MoveCard(player, cards[i].zone, target, { cards[i]}, position);

        end

    end

end


function Duel.MoveCard(player, origin, target, cards, position)

    local move_cards = cards

    if target.type == CardZoneType.Hand or target.type == CardZoneType.Deck then

        move_cards = Util.find_cards(cards, function(c)

            return not c:HasFlag(CardFlag.UNRETURN)

        end)

    end

    

    local co = coroutine.running()

    System.MoveCard(player, origin, target, move_cards, position,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.FoldCard(player, count)

    local co = coroutine.running()

    System.FoldCard(player, count,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.PlayCardEffect(player, card, type)

    local co = coroutine.running()

    System.PlayCardEffect(player, card, type,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.ClearCardEffect(player, card, type)

    local co = coroutine.running()

    System.ClearCardEffect(player, card, type,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.RequestChooseToken(player, zones, count, target)

    local total = 0;

    for _, zone in pairs(zones) do

        total = total + zone:GetMovableCount()

    end

    if total == 0 then 

        return {}

    end

    local co = coroutine.running()

    System.RequestChooseToken(player, zones, count, target,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.RequestCount(player, min, max, description)

    local co = coroutine.running()

    System.RequestCount(player, min, max, description,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.SelectCard(player, text, cards, min, max, condition)

    local co = coroutine.running()

    local list = cards

    local mask = {}

    if list.Count ~= nil then

        list = Util.ListToArray(cards)

    end

    if condition ~= nil then

        mask = Util.find_cardIds_revert(list, condition)

    end

    System.SelectCards(player, text, list, min, max, mask,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.RequestNextScene(player, choice)

    local co = coroutine.running()

    System.RequestNextScene(player, choice,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.SelectCardId(player, text, cards, min, max)

    local co = coroutine.running()

    System.SelectCardsId(player, text, cards, min, max,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.PlayCard(player, parentCard, card, skip_cost)

    if not card:IsCardUsable() then

        return

    end


    if card.type == CardType.Combine then

        local hand = player:GetCardZone(CardZoneType.Hand)

        local pool = Util.find_cards(hand.list, function(c) 

            return c.mainType == card.mainType and c.subType == card.subType

        end)

        local selection = Duel.SelectCard(player, "弃置1张同类型的牌", pool, 1, 1)

        if Util.len(selection) > 0 then

            local select = selection[0]

            Duel.MoveCard(player, select.zone, select.owner:GetCardZone(CardZoneType.Discard), {select}, 0);

        else 

            return;

        end

    end

    

    local co = coroutine.running()

    System.PlayCard(player, parentCard, card, skip_cost or false,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.DeclareAttack(player, attack)

    local co = coroutine.running()

    System.DeclareAttack(player, attack,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.ResetCard(card)

    local co = coroutine.running()

    System.ResetCard(card,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.ArrowEffectMovePoint(card, player, origin, target, count, force)

    if force or card.owner ~= player or not player:HasFlag(PlayerFlag.DOUBLE_ARROW) then

        local co = coroutine.running()

        System.ArrowEffectMovePoint(card, player, origin, target, count,

            function(...)

                coroutine.resume(co, ...)

            end)

        return coroutine.yield(co)

    else

        Duel.DoubleArrowEffectMovePoint(card, player, origin, target, count)

    end

end


local function GetZoneName(player, zone)

    if zone.type == TokenZoneType.Distance then

        return "距"

    elseif zone.type == TokenZoneType.Shadow then

        return "虚"

    elseif zone.type == TokenZoneType.Outside then

        return "游戏外"

    else

        if zone.owner == nil then

            return "未知"

        else

            local decorator = player.id == zone.owner.id and "自" or "敌"

            if zone.type == TokenZoneType.Life then

                return decorator.."命"

            elseif zone.type == TokenZoneType.Aura then

                return decorator.."装"

            elseif zone.type == TokenZoneType.Flare then

                return decorator.."气"

            else

                return "未知"

            end

        end

    end

end


function Duel.DoubleArrowEffectMovePoint(card, player, origin, target, count)

    local originName = GetZoneName(player, origin)

    local targetName = GetZoneName(player, target)

    local index = Duel.Choose(player, {

        originName.."("..count..")→"..targetName,

        targetName.."("..count..")→"..originName

    })

    if index == 0 then

        Duel.ArrowEffectMovePoint(card, player, origin, target, count, true)

    else

        Duel.ArrowEffectMovePoint(card, player, target, origin, count, true)

    end

end


function Duel.MovePoint(player, origin, target, count)

    local co = coroutine.running()

    System.MovePoint(player, origin, target, count,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.MoveToken(player, origin, target, tokens)

    local co = coroutine.running()

    System.MoveToken(player, origin, target, tokens,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.MoveTokens(player, target, tokens)

    if tokens.Count ~= nil and tokens.Length ~= nil then

        for _, token in pairs(tokens) do

            Duel.MoveToken(player, token.zone, target, { token});

        end

    else

        for i = 0, Util.len(tokens)-1, 1 do

            Duel.MoveToken(player, tokens[i].zone, target, { tokens[i]});

        end

    end

end


function Duel.ImmediateResurgence(player, card)

    local co = coroutine.running()

    System.ImmediateResurgence(player, card,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.RestoreCombineCard(player, card)

    local co = coroutine.running()

    System.RestoreCombineCard(player, card,

            function(...)

                coroutine.resume(co, ...)

            end)

    return coroutine.yield(co)

end


function Duel.Choose(player, options, mask, button)

    local showButton = button or false

    local co = coroutine.running()

    if mask == nil or Util.len(mask) == 0 then

        mask = {}

        for _ in pairs(options) do

            table.insert(mask, true)

        end

    end

    System.Choose(player, options, mask, showButton,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.ShuffleDeck(player)

    local co = coroutine.running()

    System.ShuffleDeck(player,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.RequestNormalAction(player)

    if player.IsTerminal then

        return

    end

    local co = coroutine.running()

    System.RequestNormalAction(player,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.NormalAction(player, type)

    local co = coroutine.running()

    System.NormalAction(player, type,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.SealCard(player, parent, seal)

    local co = coroutine.running()

    System.SealCard(player, parent, seal,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.CancelAttack(player, attack)

    local co = coroutine.running()

    System.CancelAttack(player, attack,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co)

end


function Duel.StopProcess(card)

    local co = coroutine.running()

    System.StopProcess(player,

        function(...)

            coroutine.resume(co, ...)

            game:MoveNextPhase()

        end)

    return coroutine.yield(co)

end


function Duel.ExtendCard(player, cardId, used)

    local extend = player:GetCardZone(CardZoneType.Extend)

    local select = null


    local iter = extend.list:GetEnumerator();


    while iter:MoveNext() do

        local card = iter.Current

        if card.cardId == cardId then

            select = card

        end

    end


    if select ~= nil then

        select.CanUse = false

        select.status = CardStatus.None;

        if used then

            select.status = CardStatus.Used;

        end

        local target = select.data.type == CardType.Special and player:GetCardZone(CardZoneType.Special) or player:GetCardZone(CardZoneType.Hand)

        Duel.MoveCard(player, select.zone, target, { select }, Util.len(target.list))

        return select

    end

end


function Duel.ActivateCardImage(player, cardId)

    Duel.ActivateCard(player, PlayObject.Card(cardId))

end


function Duel.DeclareCardName(player)

    local co = coroutine.running()

    System.DeclareCardName(player,

        function(...)

            coroutine.resume(co, ...)

        end)

    return coroutine.yield(co) 

end


测试的评论 (共 条)

分享到微博请遵守国家法律