This commit is contained in:
WEBXOSS 2016-11-17 22:13:19 +08:00
parent deffae5f3a
commit f8f461aea1
8 changed files with 9283 additions and 5768 deletions

37
Card.js
View file

@ -4,6 +4,7 @@ function Card (game,player,zone,pid,side) {
// 引用
this.game = game;
this.player = player;
this.owner = player;
this.zone = zone;
// 状态
@ -98,6 +99,8 @@ function Card (game,player,zone,pid,side) {
this.effectFilters = [];
this.registeredEffects = [];
this.charm = null; // 魅饰卡
this._data = null; // 私有的数据储存,约定: 只能在 CardInfo.js 自身的代码里访问
this.fieldData = {}; // 离场即清空的数据
// 时点
this.onMove = new Timming(game);
@ -123,7 +126,6 @@ function Card (game,player,zone,pid,side) {
this.doubleCrash = false;
this.tripleCrash = false;
this.frozen = false;
this._trashWhenTurnEnd = false;
this.forceSummonZone = false;
this.trashCharmInsteadOfBanish = false;
this.attachedCostColorless = 0; // <星占之巫女 忆·夜>
@ -144,10 +146,12 @@ function Card (game,player,zone,pid,side) {
this.discardSpellInsteadOfBanish = false; // <核心代号 S・W・T>
this.attackCostColorless = 0; // <黑幻虫 水熊虫>
this.canNotGainAbility = false; // <迷宫代号 金阁>
this.canNotGainAbilityBySelfPlayer = false; // <城堡代号 凡尔赛宫>
this._SnoropNaturalPlantPrincess = false; // <罗植姬 雪花莲>
this._CodeLabyrinthLouvre = null; // <卢浮宫>
this.powerAddProtected = false; // <幻兽 苍龙>
this._GustaftCenterBallista = false; // <弩中砲 グスタフト>
this.colorLost = false; // <侍从 ∞>
this.banishProtections = [];
// 注意hasAbility
}
@ -255,8 +259,9 @@ Card.prototype.canGrow = function (ignoreCost) {
}
}
if (!ignoreCost && !this.player.enoughCost(this.getGrowCostObj())) return false;
// LRIG type
if (this.classes.every(function (cls) {
return !this.player.lrig.hasClass(cls);
return !this.player.lrig.hasClass(cls) && (cls !== '?'); // <紡ぐ者>
},this)) {
return false;
}
@ -305,13 +310,20 @@ Card.prototype.canSummon = function () {
Card.prototype.canSummonWith = function (signis) {
// 类型
if (this.type !== 'SIGNI') return false;
// <绿罗植 世界树>
if (this.player.canNotUseColorlessSigni) {
if (this.hasColor('colorless')) {
return false;
}
}
// summonConditions
var flag = this.summonConditions.some(function (condition) {
return !condition.call(this);
},this);
if (flag) return false;
// 限定
if (!this.checkLimiting()) return false;
flag = ths.player.ignoreLimitingOfLevel5Signi && (this.level === 5);
if (!flag && !this.checkLimiting()) return false;
// 等级限制
if (this.level > this.player.lrig.level) return false;
// SIGNI 数量限制
@ -466,6 +478,12 @@ Card.prototype.canUse = function (timming,ignoreCost) {
if (!this.checkLimiting()) return false;
if (this.useCondition && !this.useCondition()) return false;
if (this.type === 'SPELL') {
// <绿罗植 世界树>
if (this.player.canNotUseColorlessSpell) {
if (this.hasColor('colorless')) {
return false;
}
}
if (this.player.spellBanned) return false;
if (ignoreCost) return true;
return this.enoughCost();
@ -503,8 +521,12 @@ Card.prototype.hasClass = function (cls) {
},this);
};
// 注意:不保证唯一性
Card.prototype.getColors = function (ignoreColorless) {
var colors = this.otherColors.concat(this.color);
if (this.colorLost) {
colors = ['colorless'];
}
if (ignoreColorless) {
removeFromArr('colorless',colors);
}
@ -709,7 +731,7 @@ Card.prototype.moveTo = function (zone,arg) {
// 是 SIGNI
leaveFieldEvent = moveEvent;
card.frozen = false;
card._trashWhenTurnEnd = false;
card.fieldData = {};
charm = card.charm;
card.charm = null;
removeFromArr(card,card.player.signis);
@ -996,6 +1018,7 @@ Card.prototype.attackAsyn = function () {
// onAttack 的事件对象
var event = {
prevented: prevented,
preventedByGuard: false,
card: card,
banishAttackingSigniSource: null,
wontBeDamaged: false,
@ -1117,9 +1140,11 @@ Card.prototype.attackAsyn = function () {
}).callback(this,function (succ) {
if (succ) {
event.prevented = true;
event.preventedByGuard = true;
return;
};
if (event.wontBeDamaged || opponent.wontBeDamaged) return;
if (player.wontBeDamagedByOpponentLrig) return;
crashArg.damage = true;
if (opponent.lifeClothZone.cards.length) {
var count = 1;
@ -1300,7 +1325,7 @@ Card.prototype.banishSigniAsyn = function (power,min,max,above) {
});
};
Card.prototype.decreasePowerAsyn = function(power,filter) {
Card.prototype.decreasePowerAsyn = function (power,filter) {
return this.player.selectOpponentSigniAsyn(filter).callback(this,function (card) {
if (!card) return;
this.game.tillTurnEndAdd(this,card,'power',-power);
@ -1308,7 +1333,7 @@ Card.prototype.decreasePowerAsyn = function(power,filter) {
};
Card.prototype.trashWhenTurnEnd = function () {
this._trashWhenTurnEnd = true;
this.fieldData.trashWhenTurnEnd = true;
};
// 获得所谓的类别,在wx中,类别组成为"大类:小类"

File diff suppressed because it is too large Load diff

View file

@ -144,7 +144,7 @@ ConstEffect.prototype.add = function (target,prop,value,arg) {
ConstEffect.prototype._setAdd = function (masks,target,prop,value,arg) {
if (!arg) arg = {};
var mask = new Mask(target,prop,value,!!arg.forced);
var mask = new Mask(this.source,target,prop,value,!!arg.forced);
if (!mask.checkFilter(this.source)) return;
this.constEffectManager.setBase(target,prop);
masks.push(mask);

17
Game.js
View file

@ -996,11 +996,20 @@ Game.prototype.setAdd = function (source,obj,prop,value,isSet,arg) {
if (!arg) arg = {};
if (!arg.forced) {
if (obj.isEffectFiltered && obj.isEffectFiltered(source)) return;
if (obj.canNotGainAbility) {
if (inArr(prop,Card.abilityProps)) return;
var card = null;
if (obj.player && inArr(prop,Card.abilityProps)) {
card = obj;
} else if (isObj(value) && (value.constructor === Effect)) {
card = value.source;
if (card.isEffectFiltered(source)) return;
}
if (card) {
if (card.canNotGainAbility || card.player.canNotGainAbility) return;
if (card.canNotGainAbilityBySelfPlayer) {
if (source.player === card.player) {
return;
}
}
if (isObj(value) && (value.constructor === Effect)) {
if (value.source.canNotGainAbility) return;
}
}
var destroyTimming = [this.phase.onTurnEnd];

22
Mask.js
View file

@ -1,6 +1,7 @@
'use strict';
function Mask (target,prop,value,forced) {
function Mask (source,target,prop,value,forced) {
this.source = source;
this.target = target;
this.prop = prop;
this.value = value;
@ -26,10 +27,15 @@ Mask.prototype.set = function (reset) {
var timming = item;
var effect = this.value;
var source = effect.source;
if (source.canNotGainAbility || source.player.canNotGainAbility) {
// 不能获得新能力
if (source.canNotGainAbility || source.player.canNotGainAbility) {
return;
}
if (source.canNotGainAbilityBySelfPlayer) {
if (this.source.player === source.player) {
return;
}
}
effect.disabled = false;
timming.effects.push(effect);
effect.source.registeredEffects.push(effect);
@ -46,10 +52,16 @@ Mask.prototype.set = function (reset) {
effect.disabled = true;
},this);
} else {
if (!reset && inArr(this.prop,Card.abilityProps)) {
if (!reset && target.player && inArr(this.prop,Card.abilityProps)) {
// 不能获得新能力
if (target.canNotGainAbility) return;
if (target.player && target.player.canNotGainAbility) return;
if (target.canNotGainAbility && target.player.canNotGainAbility) {
return;
}
if (target.canNotGainAbilityBySelfPlayer) {
if (this.source === target.player) {
return;
}
}
}
target[this.prop] = this.value;
}

View file

@ -279,8 +279,12 @@ Phase.prototype.endPhase = function () {
// 处理"回合结束时,把XXX放到废弃区".
// 同时触发"回合结束时"时点.
var cards = concat(this.player.signis,this.player.opponent.signis).filter(function (signi) {
if (signi._trashWhenTurnEnd) {
signi._trashWhenTurnEnd = false;
if (signi.fieldData.excludeWhenTurnEnd) {
signi.fieldData.excludeWhenTurnEnd = false;
return true;
}
if (signi.fieldData.trashWhenTurnEnd) {
signi.fieldData.trashWhenTurnEnd = false;
return true;
}
},this);

View file

@ -102,11 +102,13 @@ function Player (game,io,mainDeck,lrigDeck) {
this.spellBanned = false;
this.skipEnerPhase = false;
this.ignoreLimitingOfArtsAndSpell = false;
this.ignoreLimitingOfLevel5Signi = false; // <紡ぐ者>
this.summonPowerLimit = 0;
this.additionalRevealCount = 0; // <反复的独立性 网格>
this.useBikouAsWhiteCost = false; // <不思議な童話 メルへ>
this.burstTwice = false; // <Burst Rush>
this.wontBeDamaged = false; // <音阶的右律 G>
this.wontBeDamagedByOpponentLrig = false; // <紡ぐ者>
this.charmedActionEffectBanned = false; // <黒幻蟲 アラクネ・パイダ>
this.canNotGrow = false; // <ドント・グロウ>
this._HammerChance = false; // <ハンマー・チャンス>
@ -133,10 +135,12 @@ function Player (game,io,mainDeck,lrigDeck) {
this.canNotBeBounced = false;
this.canNotGainAbility = false;
this.canNotBeDownedByOpponentEffect = false;
this.canNotUseColorlessSigni = false; // <绿罗植 世界树>
this.canNotUseColorlessSpell = false; // <绿罗植 世界树>
this.usedActionEffects = [];
this.chain = null;
this.inResonaAction = false; // 是否正在执行共鸣单位的出现条件
this.inResonaAction = null; // 是否正在执行共鸣单位的出现条件. (同时也是正在执行出现条件的那只共鸣单位)
this.inActionEffectCost = false; // 是否正在支付起动能力的COST
this.bannedCards = []; // <漆黑之棺>
this.oneArtEachTurn = false; // <博愛の使者 サシェ・リュンヌ>
@ -441,9 +445,9 @@ Player.prototype.getResonas = function (arg) {
};
Player.prototype.summonResonaAsyn = function (card) {
this.inResonaAction = true;
this.inResonaAction = card;
return card.resonaAsyn().callback(this,function (resonaArg) {
this.inResonaAction = false;
this.inResonaAction = null;
return this.selectSummonZoneAsyn(false).callback(this,function (zone) {
if (!zone) return;
return this.game.blockAsyn(this,function () {
@ -507,10 +511,10 @@ Player.prototype.useSpellAsyn = function () {
return this.selectAsyn('USE_SPELL',cards).callback(this,this.handleSpellAsyn);
};
Player.prototype.handleSpellAsyn = function (card,ignoreCost,costObj) {
Player.prototype.handleSpellAsyn = function (card,ignoreCost,costObj,arg) {
if (!costObj) costObj = card;
if (!arg) arg = {};
var effect,target,costArg;
var owner = card.player;
this.game.setData(this,'flagSpellUsed',true);
var count = this.game.getData(this,'CodeHeartAMS') || 0;
this.game.setData(this,'CodeHeartAMS',count + 1);
@ -599,11 +603,16 @@ Player.prototype.handleSpellAsyn = function (card,ignoreCost,costObj) {
}).callback(this,function () {
// 6. 放到废弃区
// 恢复控制权
card.player = owner;
card.player = card.owner;
this.game.spellToCutIn = null;
if (card.zone !== this.checkZone) return;
return this.game.blockAsyn(this,function () {
// <皮露露可 APEX>
if (arg.excludeAfterUse) {
card.exclude()
} else {
card.trash();
}
});
}).callback(this,function () {
// <混乱交织> 的特殊处理
@ -655,11 +664,23 @@ Player.prototype.handleArtsAsyn = function (card,ignoreCost) {
}
}).callback(this,function () {
// 2. 支付费用
// アンコール费用
// アンコール费用,约定: 除了颜色费用,其它属性直接覆盖
if (!card.encore) return;
var encoredCost = Object.create(costObj);
var enerCostProps = [
'costColorless',
'costWhite',
'costBlack',
'costRed',
'costBlue',
'costGreen',
];
for (var prop in card.encore) {
if (inArr(prop,enerCostProps)) {
encoredCost[prop] += card.encore[prop];
} else {
encoredCost[prop] = card.encore[prop];
}
}
if (!this.enoughCost(encoredCost)) return;
return this.confirmAsyn('CONFIRM_ENCORE').callback(this,function (answer) {
@ -766,11 +787,12 @@ Player.prototype.useMainPhaseArtsAsyn = function () {
});
};
Player.prototype.canUseActionEffect = function (effect,onAttack,arg) {
Player.prototype.canUseActionEffect = function (effect,arg) {
if (!arg) arg = {};
if (this.charmedActionEffectBanned && effect.source.charm) return false;
if (effect.source.abilityLost) return false;
if (onAttack && !effect.onAttack) return false;
if (!onAttack && effect.onAttack) return false;
if (arg.onAttack && !effect.onAttack) return false;
if (!arg.onAttack && effect.onAttack) return false;
if (effect.cross && !effect.source.crossed) return false;
if (effect.once && inArr(effect,this.usedActionEffects)) return false;
if (effect.useCondition && !effect.useCondition.call(effect.source,arg)) return false;
@ -786,51 +808,51 @@ Player.prototype.canUseActionEffect = function (effect,onAttack,arg) {
} else {
obj.costColorless = effect.source.attachedCostColorless;
}
if (arg.ignoreExceedCost) {
obj.costExceed = 0;
}
return this.enoughCost(obj);
};
// 玩家使用起动效果
Player.prototype.useActionEffectAsyn = function () {
var effects = [];
concat(this.lrig,this.signis).forEach(function (card) {
var cards = concat(this.lrig,this.signis,this.trashZone.cards,this.hands);
cards.forEach(function (card) {
card.actionEffects.forEach(function (effect) {
if (effect.spellCutIn) return;
if (effect.attackPhase && !effect.mainPhase) return;
if (effect.activatedInTrashZone) return;
if (effect.activatedInTrashZone && card.zone !== this.trashZone) return;
if (effect.activatedInHand && card.zone !== this.handZone) return;
if (this.canUseActionEffect(effect)) {
effects.push(effect);
}
},this);
},this);
this.trashZone.cards.forEach(function (card) {
// if (card.type !== 'SIGNI') return;
card.actionEffects.forEach(function (effect) {
if (effect.spellCutIn) return;
if (effect.attackPhase && !effect.mainPhase) return;
if (!effect.activatedInTrashZone) return;
if (this.canUseActionEffect(effect)) {
effects.push(effect);
}
},this);
},this);
});
});
if (!effects.length) return Callback.never();
return this.selectAsyn('USE_ACTION_EFFECT',effects).callback(this,function (effect) {
return this.handleActionEffectAsyn(effect,{},true);
return this.handleActionEffectAsyn(effect,{
cancelable: true,
});
});
};
Player.prototype.useOnAttackActionEffectAsyn = function (event) {
var effects = this.lrig.actionEffects.filter(function (effect) {
return this.canUseActionEffect(effect,true,event);
return this.canUseActionEffect(effect,{
onAttack: true,
event: event,
});
},this);
if (!effects.length) return Callback.immediately();
return this.selectOptionalAsyn('LAUNCH',effects).callback(this,function (effect) {
if (!effect) return;
return this.handleActionEffectAsyn(effect,event);
return this.handleActionEffectAsyn(effect,{event: event});
});
};
Player.prototype.handleActionEffectAsyn = function (effect,event,cancelable) {
Player.prototype.handleActionEffectAsyn = function (effect,arg) {
if (!arg) arg = {};
this.usedActionEffects.push(effect);
return this.game.blockAsyn(this,function () {
var obj = Object.create(effect);
@ -839,6 +861,9 @@ Player.prototype.handleActionEffectAsyn = function (effect,event,cancelable) {
} else {
obj.costColorless = effect.source.attachedCostColorless;
}
if (arg.ignoreExceedCost) {
obj.costExceed = 0;
}
// <混沌之键主 乌姆尔=FYRA>
if (effect.activatedInTrashZone) {
if (this.game.getData(effect.source,'zeroActionCostInTrash')) {
@ -847,12 +872,12 @@ Player.prototype.handleActionEffectAsyn = function (effect,event,cancelable) {
}
}
this.inActionEffectCost = true;
return this.payCostAsyn(obj,cancelable).callback(this,function (costArg) {
return this.payCostAsyn(obj,arg.cancelable).callback(this,function (costArg) {
this.inActionEffectCost = false;
if (!costArg) return; // canceled
effect.source.activate();
return this.game.blockAsyn(effect.source,this,function () {
return effect.actionAsyn.call(effect.source,costArg,event);
return effect.actionAsyn.call(effect.source,costArg,arg);
});
});
});
@ -1049,6 +1074,12 @@ Player.prototype.crashAsyn = function (n,arg) {
Player.prototype.damageAsyn = function () {
if (this.wontBeDamaged) return Callback.immediately(false);
if (this.wontBeDamagedByOpponentLrig) {
var source = this.game.getEffectSource();
if (source === this.player.opponent.lrig) {
return Callback.immediately(false);
}
}
if (!this.lifeClothZone.cards.length) {
if (this.game.win(this.opponent)) return Callback.never();
return Callback.immediately(false);

@ -1 +1 @@
Subproject commit 1cd5ce68eaa244096cfb358624c88f5b0c2c04b3
Subproject commit a1b421e2b205a326cddfb8d1d9b2db27f2efac86