From 7902b062821d7d170e3e2ee86a315e314a551d06 Mon Sep 17 00:00:00 2001 From: WEBXOSS Date: Fri, 8 Sep 2017 01:28:20 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=A9=20coding=20card=20effects?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CardInfo.js | 255 +++++++++++++++++++++++++++++++++++++++------------- Game.js | 10 +++ Player.js | 51 +++++++++++ 3 files changed, 253 insertions(+), 63 deletions(-) diff --git a/CardInfo.js b/CardInfo.js index 264ef8b..212d5e5 100644 --- a/CardInfo.js +++ b/CardInfo.js @@ -117840,10 +117840,7 @@ var CardInfo = { },this); return this.player.selectTargetAsyn(cards).callback(this,function (target) { if (!target) return; - var cards = target.zone.getNonTrapCards().filter(function (c) { - return (c !== target) && !c.charm && !c.acceingCard; - },this); - cards.push(target); + var cards = target.getBottomCards().concat(target); this.game.moveCards(cards,card.zone); return function afterSummonAsyn (event) { return this.game.blockAsyn(this,function () { @@ -122993,6 +122990,7 @@ var CardInfo = { var card = cards[0]; if (!card) return; if (card.type !== 'SIGNI') return; + // TODO: getLevelAsyn var level = card.level; return this.player.selectSelfSigniAsyn().callback(this,function (card) { if (level === 1) { @@ -123545,20 +123543,6 @@ var CardInfo = { "timing": "メインフェイズ\nアタックフェイズ", "imgUrl": "http://www.takaratomy.co.jp/products/wixoss/wxwp/images/card/WX17/WX17-020.jpg", "illust": "ふーみ", - faqs: [ - { - "q": "自分の手札が1枚も無いときに使用した場合はどうなりますか?", - "a": "その場合でも、選んだ効果をそのまま処理することができます。手札が無い場合、手札を捨てる効果は無視して処理を行います。" - }, - { - "q": "デッキが残り1枚のときに①の効果で使用したらどうなりますか?", - "a": "その場合は残り1枚のデッキを引き、手札を1枚捨てて効果は終了します。その後リフレッシュを行います。" - }, - { - "q": "凍結されたルリグは《燐廻転生》などの効果によってもアップしませんか?", - "a": "いいえ、アップする効果によってアップすることはできます。ですが効果によってアップした場合も凍結状態ですので、その後アタックなどでダウンした場合はやはり次のアップフェイズにはアップしません。" - } - ], "classes": [], "costWhite": 0, "costBlack": 0, @@ -123567,14 +123551,37 @@ var CardInfo = { "costGreen": 0, "costColorless": 0, "guardFlag": false, - cardSkills: [ - "以下の3つから1つを選ぶ。", - "①あなたはカードを2枚引く。その後、あなたは手札を1枚捨てる。", - "②対戦相手のシグニ1体をダウンする。その後、あなたは手札を1枚捨てる。", + "multiEner": false, + cardText: "どれがいいんでしょう。~ピルルク~", + // ====================== + // 技艺效果 + // ====================== + timmings: ['mainPhase'], + artsEffectTexts: [ + "以下の3つから1つを選ぶ。\n" + + "①あなたはカードを2枚引く。その後、あなたは手札を1枚捨てる。\n" + + "②対戦相手のシグニ1体をダウンする。その後、あなたは手札を1枚捨てる。\n" + "③対戦相手のルリグ1体を凍結する。その後、あなたは手札を1枚捨てる。" ], - "multiEner": false, - cardText: "どれがいいんでしょう。~ピルルク~" + artsEffect: [{ + actionAsyn: function () { + this.player.draw(2); + return this.player.discardAsyn(1); + }, + },{ + actionAsyn: function () { + return this.player.selectOpponentSigniAsyn().callback(this,function (card) { + if (!card) return; + card.down(); + return this.player.discardAsyn(1); + }); + }, + },{ + actionAsyn: function () { + this.player.opponent.lrig.freeze(); + return this.player.discardAsyn(1); + }, + }], }, "2419": { "pid": 2419, @@ -123593,16 +123600,6 @@ var CardInfo = { "timing": "メインフェイズ\nアタックフェイズ\nスペルカットイン", "imgUrl": "http://www.takaratomy.co.jp/products/wixoss/wxwp/images/card/WX17/WX17-021.jpg", "illust": "pepo", - faqs: [ - { - "q": "場には自分のシグニ1体だけしかいません。《大盤振舞》で、このシグニを+5000だけすることはできますか?", - "a": "いいえ、合計で+20000する効果ですので、シグニが1体だけでしたらそのシグニを+20000します。+5000だけするということはできません。" - }, - { - "q": "対戦相手のシグニと自分のシグニを両方同時に選べますか?", - "a": "はい、可能です。" - } - ], "classes": [], "costWhite": 0, "costBlack": 0, @@ -123611,11 +123608,45 @@ var CardInfo = { "costGreen": 1, "costColorless": 0, "guardFlag": false, - cardSkills: [ + "multiEner": false, + cardText: "さ、お料理の基本、覚えてる?~メル~", + // ====================== + // 技艺效果 + // ====================== + timmings: ['mainPhase'], + artsEffectTexts: [ "ターン終了時まで、好きな数のシグニのパワーを合わせて+20000する。この効果では1000単位でしか数字を割り振ることができない。" ], - "multiEner": false, - cardText: "さ、お料理の基本、覚えてる?~メル~" + artsEffect: { + actionAsyn: function () { + var left = 20000; + var signis = concat(this.player.signis,this.player.opponent.signis); + this.game.frameStart(); + return Callback.loop(this,signis.length,function () { + if (!signis.length) return; + if (left <= 0) return; + return this.player.selectTargetAsyn(signis).callback(this,function (signi) { + if (!signi) return; + removeFromArr(signi,signis); + var powers = []; + if (signis.length) { + for (var power = 1000; power <= left; power += 1000) { + powers.push(power); + } + } else { + powers = [left]; + } + // TODO: selectNumbersAsyn, localize POWER + return this.player.selectNumbersAsyn('POWER',powers).callback(function (power) { + left -= power; + this.game.tillTurnEndAdd(this,signi,'power',power); + }) + }) + }).callback(this,function () { + this.game.frameEnd(); + }); + }, + }, }, "2420": { "pid": 2420, @@ -123633,24 +123664,6 @@ var CardInfo = { "limiting": "リル", "imgUrl": "http://www.takaratomy.co.jp/products/wixoss/wxwp/images/card/WX17/WX17-026.jpg", "illust": "クロサワテツ", - faqs: [ - { - "q": "《武装の全知 ギルガメジ》のライズはどのようにしたらいいですか?", - "a": "《武装の全知 ギルガメジ》はあなたの場のシグニが《ライズアイコン》を持つシグニ1体と<武勇>のシグニ2体の合計3体の場合に出すことができます。どれかのシグニゾーン1つに3体全てを重ね、その上に《武装の全知 ギルガメジ》を出します。" - }, - { - "q": "自動能力はどのように処理しますか?", - "a": "《武装の全知 ギルガメジ》がアタックしたとき、例えば下からレベル3と4のシグニをトラッシュに置いた場合、対戦相手の好きな数のシグニをレベル合計が7になるようにトラッシュに置きます。(レベル3,4の2体や、1,2,4の3体など)\n「等しくなるように」という制限がありますので、例えば《武装の全知 ギルガメジ》の下からレベル3を1体トラッシュに置き、対戦相手のレベル2のシグニ1体をトラッシュに置く、といったことはできません。" - }, - { - "q": "《火竜点睛》で《武装の全知 ギルガメジ》を場に出した場合、《火竜点睛》の効果で比べるパワーは《武装の全知 ギルガメジ》の【常】でプラスされた後ですか?", - "a": "はい、【常】のプラスを計算してからとなります。下にカードが4枚ある場合は+4000し、パワー16000以下のシグニのバニッシュとなります。" - }, - { - "q": "《武装の全知 ギルガメジ》の下にカードが3枚あり、自身のパワーは15000です。「パワー15000以上のシグニの効果を受けない」という能力を持つ対戦相手のシグニに対して自動能力を発動しました。レベルの条件は合うものとして、その対戦相手のシグニをトラッシュに置くことはできますか?", - "a": "はい、可能です。\n自動能力を発動して《武装の全知 ギルガメジ》が自身の下からカードをトラッシュに置いた時点でパワーは14000以下となります。そのあとで対戦相手のシグニをトラッシュに置くためです。" - } - ], "classes": [ "精像", "武勇" @@ -123662,15 +123675,131 @@ var CardInfo = { "costGreen": 0, "costColorless": 0, "guardFlag": false, - cardSkills: [ - "[ライズ]《ライズアイコン》を持つシグニ1体と<武勇>のシグニ2体の上に出す", - "【常】:このシグニのパワーはこの下にあるカード1枚につき、+1000される。", - "【自】:このシグニがアタックしたとき、この下から好きな枚数のシグニをトラッシュに置く。その後、対戦相手のシグニを、レベルの合計がこの方法でトラッシュに置いたシグニのレベルの合計と等しくなるようにトラッシュに置く。", - "【出】:あなたのトラッシュからレベル3以下のシグニ1枚を場に出す。" - ], "multiEner": false, cardText: "武器の全てを味わい、全てを知った我にかなうと思うてか!~ギルガメジ~", - "lifeBurst": "あなたのトラッシュから<武勇>のシグニ1枚を手札に加えるか場に出す。" + // ====================== + // Rise + // ====================== + extraTexts: [ + "[ライズ]《ライズ》を持つシグニ1体と<武勇>のシグニ2体の上に出す", + ], + rise: function (card) { + if (card.player.signis.length !== 3) return false; + return card.player.signis.every(function (signi) { + return signi.rise || signi.hasClass('武勇'); + }) && card.player.signis.some(function (signi) { + return signi.rise; + }); + }, + beforeSummonAsyn: function (zone) { + // 这里不少代码和 WX16-027 重复,改动注意两边一起改。 + // 暂不抽象,等特殊处理的效果多了再找共性。 + var card = zone.getSigni(); + // 选中区域 SIGNI 以外的其他 SIGNI + var signis = this.player.signis.filter(function (signi) { + return (signi !== card); + },this); + // 其他区域的卡都移动到选中的区域,注意 SIGNI 最后移动,因为 SIGNI 移动会处理底下的卡 + this.game.frameStart(); + signis.forEach(function (signi) { + var cards = signi.getBottomCards().concat(signi); + this.game.moveCards(cards,card.zone); + },this); + this.game.frameEnd(); + // 完成召唤时手动触发 onRised + return function afterSummonAsyn(event) { + return this.game.blockAsyn(this,function () { + signis.forEach(function (signi) { + signi.onRised.trigger(event); + },this); + }); + }; + }, + // ====================== + // 常时效果 + // ====================== + constEffectTexts: [ + "【常】:このシグニのパワーはこの下にあるカード1枚につき、+1000される。", + "【自】:このシグニがアタックしたとき、この下から好きな枚数のシグニをトラッシュに置く。その後、対戦相手のシグニを、レベルの合計がこの方法でトラッシュに置いたシグニのレベルの合計と等しくなるようにトラッシュに置く。", + ], + constEffects: [{ + action: function (set,add) { + // TODO: QA: charm and traps + var value = this.zone.getBottomCards().length * 1000; + if (!value) return; + add(this,'powers',value); + } + },{ + auto: 'onAttack', + effect: { + actionAsyn: function () { + var cards = this.getBottomCards().filter(function (card) { + return (card.type === 'SIGNI'); + },this); + if (!cards.length) return; + return this.player.selectSomeAsyn('TRASH',cards).callback(this,function (cards) { + if (!cards.length) return; + var level = 0; + cards.forEach(function (card) { + level += card.level; + },this); + this.game.trashCards(cards); + + var bitmaps = []; + var len = this.player.opponent.signis.length + this.game.getSubsets(this.player.opponent.signis).forEach(function (signis,bitmap) { + var total = signis.reduce(function (total,signi) { + return total + signi.level; + },0); + if (total !== level) return; + // 取反,选择的是要废弃的而不是留在场上的。 + bitmaps.push(~bitmap & ((1 << len) - 1)) + }); + return this.player.selectGroupAsyn({ + items: this.player.opponent.signis, + bitmaps: bitmaps, + selectAsyn: this.player.selectTargetAsyn.bind(this.player), + }).callback(this,function (cards) { + if (!cards) return; + return this.game.trashCardsAsyn(cards); + }); + }); + }, + }, + }], + // ====================== + // 出场效果 + // ====================== + startUpEffectTexts: [ + "【出】:あなたのトラッシュからレベル3以下のシグニ1枚を場に出す。" + ], + startUpEffects: [{ + actionAsyn: function () { + var filter = function (card) { + return card.level <= 3; + }; + return this.player.rebornAsyn(filter,1); + } + }], + // ====================== + // 迸发效果 + // ====================== + burstEffectTexts: [ + "【※】:あなたのトラッシュから<武勇>のシグニ1枚を手札に加えるか場に出す。" + ], + burstEffect: { + actionAsyn: function () { + var filter = function (card) { + return card.hasClass('武勇'); + }; + return this.player.selectTextAsyn('CHOOSE_EFFECT',['ADD_TO_HAND', 'SUMMON_SIGNI']).callback(this,function (text) { + if (text === 'ADD_TO_HAND') { + return this.player.seekAsyn(filter,1); + } + return this.player.seekAndSummonAsyn(filter,1); + }); + }, + }, }, "2421": { "pid": 2421, @@ -123723,7 +123852,7 @@ var CardInfo = { "《レイヤーアイコン》【自】:このシグニがバニッシュされたとき、ターン終了時まで、対戦相手のシグニ1体はすべての能力を失い、新たに得られない。" ], "multiEner": false, - cardText: "みーんな眠っちゃえ!~ピグシイ~" + cardText: "みーんな眠っちゃえ!~ピグシイ~", }, "2422": { "pid": 2422, diff --git a/Game.js b/Game.js index a1dae50..a993d4a 100644 --- a/Game.js +++ b/Game.js @@ -1134,4 +1134,14 @@ Game.prototype.getLiveMessagePacks = function () { return this.hostPlayer.messagePacks; }; +Game.prototype.getSubsets = function (arr) { + var subsets = []; + for (var i = 0; i < (1 << arr.length); i++) { + subsets.push(arr.filter(function (item,idx) { + return idx & i; + })); + } + return subsets; +}; + global.Game = Game; \ No newline at end of file diff --git a/Player.js b/Player.js index 344fc58..a0118b7 100644 --- a/Player.js +++ b/Player.js @@ -2100,6 +2100,57 @@ Player.prototype.seekAndSummonAsyn = function (filter,n,dontTriggerStartUp) { }); }; +// 选择可行的组合,返回 items (选择的组合) 或 null (无可行组合) +Player.prototype.selectGroupAsyn = function (options) { + // 总的候选项 + var items = options.items; + + // 满足的组合,如 [1001, 0101, 0110] + var bitmaps = options.bitmaps; + + // 如何处理选择,参数: targets,optional + var selectAsyn = options.selectAsyn; + + // 0 或 1 个组合,直接返回 + if (!bitmaps.length) return Callback.immediately(null); + if (bitmaps.length === 1) { + return Callback.immediately(items.filter(function (item,idx) { + return bitmaps[0] & (1 << idx); + })); + } + + // 本次选择的候选项 + var mask = bitmaps.reduce(function (mask,bitmap) { + return mask | bitmap; + },0); + var targets = items.filter(function (item,idx) { + return mask & (1 << idx); + }); + var optional = bitmaps.some(function (bitmap) { + return !bitmap; + }); + // 选择 1 次 + return selectAsyn(targets,optional).callback(this,function (item) { + if (item === null) return []; + // 筛选出下次选择的组合 + var idx = items.indexOf(item); + bitmaps = bitmaps.filter(function (bitmap) { + return bitmap & (idx << 1); + }).map(function (bitmap) { + return bitmap & ~(idx << 1); + }); + // 递归 + return this.selectGroupAsyn({ + items: items, + bitmaps: bitmaps, + selectAsyn: selectAsyn, + }).callback(this,function (items) { + if (items === null) return [item] + return [item].concat(items); + }); + }); +}; + Player.prototype.pickCardAsyn = function (filter,min,max,zone) { if (!isNum(min)) min = 1; if (!isNum(max)) max = 1;