Merge pull request #899 from universe-st/PR-Branch

AI性能优化
This commit is contained in:
Spmario233 2024-02-03 15:21:11 +08:00 committed by GitHub
commit 3a7bfd4092
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 210 additions and 98 deletions

View File

@ -24,15 +24,21 @@ export class Basic extends Uninstantable {
if (ui.selected.buttons.length >= range[0]) {
ok = true;
}
CacheContext.setCacheContext(new CacheContext());
CacheContext.setInCacheEnvironment(true);
if (range[1] <= -1) {
j = 0;
for (i = 0; i < ui.selected.buttons.length; i++) {
j += check(ui.selected.buttons[i]);
}
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext();
return (j > 0);
}
buttons = get.selectableButtons();
if (buttons.length == 0) {
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext();
return ok;
}
buttons2 = buttons.slice(0);
@ -50,9 +56,13 @@ export class Basic extends Uninstantable {
// });
if (check(buttons[ix]) <= 0) {
if (!forced || ok) {
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext();
return ok;
}
}
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext();
buttons[ix].classList.add('selected');
ui.selected.buttons.add(buttons[ix]);
game.check();
@ -86,11 +96,13 @@ export class Basic extends Uninstantable {
if (ui.selected.cards.length == 0) return true;
j = 0;
CacheContext.setCacheContext(new CacheContext());
CacheContext.setInCacheEnvironment(true);
for (i = 0; i < ui.selected.cards.length; i++) {
effect = check(ui.selected.cards[i]);
if (effect < 0) j -= Math.sqrt(-effect);
else j += Math.sqrt(effect);
}
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext();
return (j > 0);
}
@ -109,6 +121,7 @@ export class Basic extends Uninstantable {
// });
var ix = 0;
CacheContext.setCacheContext(new CacheContext());
CacheContext.setInCacheEnvironment(true);
var checkix = check(cards[0], cards2);
for (i = 1; i < cards.length; i++) {
var checkixtmp = check(cards[i], cards2);
@ -119,10 +132,12 @@ export class Basic extends Uninstantable {
}
if (check(cards[ix]) <= 0) {
if (!forced || ok) {
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext();
return ok;
}
}
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext();
if (typeof cards[ix] == 'string') {
ui.click.skill(cards[ix]);
@ -168,11 +183,13 @@ export class Basic extends Uninstantable {
if (range[1] <= -1) {
j = 0;
CacheContext.setCacheContext(new CacheContext());
CacheContext.setInCacheEnvironment(true);
for (i = 0; i < ui.selected.targets.length; i++) {
effect = check(ui.selected.targets[i]);
if (effect < 0) j -= Math.sqrt(-effect);
else j += Math.sqrt(effect);
}
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext();
return (j > 0);
}
@ -189,6 +206,7 @@ export class Basic extends Uninstantable {
// });
let ix = 0;
CacheContext.setCacheContext(new CacheContext());
CacheContext.setInCacheEnvironment(true);
let checkix = check(targets[0], targets2);
for (i = 1; i < targets.length; i++) {
let checkixtmp = check(targets[i], targets2);
@ -199,10 +217,12 @@ export class Basic extends Uninstantable {
}
if (check(targets[ix]) <= 0) {
if (!forced || ok) {
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext();
return ok;
}
}
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext();
targets[ix].classList.add('selected');
ui.selected.targets.add(targets[ix]);

View File

@ -7496,7 +7496,7 @@ export class Game extends Uninstantable {
const argumentArray = Array.from(arguments), name = argumentArray[argumentArray.length - 2];
let skills = argumentArray[argumentArray.length - 1];
if (typeof skills.getModableSkills == 'function') {
skills = skills.getModableSkills(_status.event.useCache === true);
skills = skills.getModableSkills();
} else if (typeof skills.getSkills == 'function') {
skills = skills.getSkills().concat(lib.skill.global);
game.expandSkills(skills);
@ -7510,8 +7510,8 @@ export class Game extends Uninstantable {
skills.forEach(value => {
var mod = get.info(value).mod[name];
if (!mod) return;
const result = mod.apply(this, arg);
if (typeof arg[arg.length - 1] != 'object' && result != undefined) arg[arg.length - 1] = result;
const result = mod.call(this,...arg);
if (result != undefined && typeof arg[arg.length - 1] != 'object') arg[arg.length - 1] = result;
});
return arg[arg.length - 1];
}

View File

@ -2866,8 +2866,10 @@ export class Get extends Uninstantable {
if (!lib.characterInitFilter[node.name]) return true;
return lib.characterInitFilter[node.name](tag) !== false;
});
const str = initFilters.reduce((strx, stry) => strx + lib.InitFilter[stry] + '<br>').slice(0, -4);
uiintro.addText(str);
if(initFilters.length){
const str = initFilters.reduce((strx, stry) => strx + lib.InitFilter[stry] + '<br>').slice(0, -4);
uiintro.addText(str);
}
}
if (!node.noclick) {
@ -4028,7 +4030,7 @@ export class Get extends Uninstantable {
if (!from || !to) return 0;
from = from._trueMe || from;
arguments[0] = from;
var att = get.rawAttitude.apply(this, arguments);
var att = CacheContext.requireCacheContext().get.rawAttitude.apply(this, arguments);
if (from.isMad()) att = -att;
if (to.isMad() && att > 0) {
if (to.identity == 'zhu') {
@ -4192,11 +4194,8 @@ export class Get extends Uninstantable {
return 1;
}
static cacheOrder(item){
let cache = CacheContext.getCacheContext();
if(cache){
return cache.get.order(item);
}
return get.order(item);
let cache = CacheContext.requireCacheContext();
return cache.get.order(item);
}
static order(item) {
let cache = CacheContext.requireCacheContext();
@ -4235,13 +4234,11 @@ export class Get extends Uninstantable {
return result;
}
static cacheEffectUse(target, card, player, player2, isLink){
let cache = CacheContext.getCacheContext();
if(cache){
return cache.get.effect_use(target,card,player,player2,isLink);
}
return get.effect_use(target,card,player,player2,isLink);
let cache = CacheContext.requireCacheContext();
return cache.get.effect_use(target,card,player,player2,isLink);
}
static effect_use(target, card, player, player2, isLink) {
let cache = CacheContext.requireCacheContext();
var event = _status.event;
var eventskill = null;
if (player == undefined) player = _status.event.player;
@ -4262,7 +4259,7 @@ export class Get extends Uninstantable {
info.changeTarget(player, targets);
var eff = 0;
for (var i of targets) {
eff += get.effect(i, card, player, player2, isLink);
eff += cache.get.effect(i, card, player, player2, isLink);
}
return eff;
}
@ -4280,10 +4277,10 @@ export class Get extends Uninstantable {
for (var i = 0; i < skills1.length; i++) {
temp1 = get.info(skills1[i]).ai;
if (temp1 && typeof temp1.effect == 'object' && typeof temp1.effect.player_use == 'function') {
temp1 = temp1.effect.player_use(card, player, target, result1, isLink);
temp1 = cache.delegate(temp1.effect).player_use(card, player, target, result1, isLink);
}
else if (temp1 && typeof temp1.effect == 'object' && typeof temp1.effect.player == 'function') {
temp1 = temp1.effect.player(card, player, target, result1, isLink);
temp1 = cache.delegate(temp1.effect).player(card, player, target, result1, isLink);
}
else temp1 = undefined;
if (typeof temp1 == 'object') {
@ -4323,7 +4320,7 @@ export class Get extends Uninstantable {
target: target,
skill: skills2[i],
isLink: isLink,
})) temp2 = temp2.effect(card, player, target, result2, isLink);
})) temp2 = cache.delegate(temp2).effect(card, player, target, result2, isLink);
else temp2 = undefined;
}
else if (temp2 && typeof temp2.effect == 'object' && typeof temp2.effect.target_use == 'function') {
@ -4332,7 +4329,7 @@ export class Get extends Uninstantable {
target: target,
skill: skills2[i],
isLink: isLink,
})) temp2 = temp2.effect.target_use(card, player, target, result2, isLink);
})) temp2 = cache.delegate(temp2.effect).target_use(card, player, target, result2, isLink);
else temp2 = undefined;
}
else if (temp2 && typeof temp2.effect == 'object' && typeof temp2.effect.target == 'function') {
@ -4341,7 +4338,7 @@ export class Get extends Uninstantable {
target: target,
skill: skills2[i],
isLink: isLink,
})) temp2 = temp2.effect.target(card, player, target, result2, isLink);
})) temp2 = cache.delegate(temp2.effect).target(card, player, target, result2, isLink);
else temp2 = undefined;
}
else temp2 = undefined;
@ -4386,7 +4383,7 @@ export class Get extends Uninstantable {
result2 += temp02;
result1 += temp01;
if (typeof card == 'object' && !result.ignoreStatus) {
if (get.attitude(player, target) < 0) {
if (cache.get.attitude(player, target) < 0) {
result2 *= Math.sqrt(threaten);
}
else {
@ -4394,7 +4391,7 @@ export class Get extends Uninstantable {
}
if (target.hp == 1) result2 *= 2.5;
if (target.hp == 2) result2 *= 1.8;
let countTargetCards = target.cacheCountCards('h');
let countTargetCards = target.countCards('h');
if (countTargetCards == 0) {
if (get.tag(card, 'respondSha') || get.tag(card, 'respondShan')) {
result2 *= 1.7;
@ -4419,32 +4416,30 @@ export class Get extends Uninstantable {
if (zerotarget) result2 = 0;
var final = 0;
if (player2) {
final = (result1 * get.attitude(player2, player) + (target ? result2 * get.attitude(player2, target) : 0));
final = (result1 * cache.get.attitude(player2, player) + (target ? result2 * cache.get.attitude(player2, target) : 0));
}
else final = (result1 * get.attitude(player, player) + (target ? result2 * get.attitude(player, target) : 0));
else final = (result1 * cache.get.attitude(player, player) + (target ? result2 * cache.get.attitude(player, target) : 0));
if (!isLink && get.tag(card, 'natureDamage') && !zerotarget) {
var info = get.info(card);
if (!info || !info.ai || !info.ai.canLink) {
if (target.isLinked()) game.players.forEach(function (current) {
if (current != target && current.isLinked()) final += get.effect(current, card, player, player2, true);
if (current != target && current.isLinked()) final += cache.get.effect(current, card, player, player2, true);
});
}
else if (info.ai.canLink(player, target, card)) {
game.players.forEach(function (current) {
if (current != target && current.isLinked()) final += get.effect(current, card, player, player2, true);
if (current != target && current.isLinked()) final += cache.get.effect(current, card, player, player2, true);
});
}
}
return final;
}
static cacheEffect(target, card, player, player2, isLink){
let cache = CacheContext.getCacheContext();
if(cache){
return cache.get.effect(target,card,player,player2,isLink);
}
return get.effect(target,card,player,player2,isLink);
let cache = CacheContext.requireCacheContext();
return cache.get.effect(target,card,player,player2,isLink);
}
static effect(target, card, player, player2, isLink) {
let cache = CacheContext.requireCacheContext();
var event = _status.event;
var eventskill = null;
if (player == undefined) player = _status.event.player;
@ -4505,7 +4500,7 @@ export class Get extends Uninstantable {
game.expandSkills(skills2);
for (var i = 0; i < skills2.length; i++) {
temp2 = get.info(skills2[i]).ai;
if (temp2 && temp2.threaten) temp3 = temp2.threaten;
if (temp2 && temp2.threaten) temp3 = cache.delegate(temp2).threaten;
else temp3 = undefined;
if (temp2 && typeof temp2.effect == 'function') {
if (!player.hasSkillTag('ignoreSkill', true, {
@ -4513,7 +4508,7 @@ export class Get extends Uninstantable {
target: target,
skill: skills2[i],
isLink: isLink,
})) temp2 = temp2.effect(card, player, target, result2, isLink);
})) temp2 = cache.delegate(temp2).effect(card, player, target, result2, isLink);
else temp2 = undefined;
}
else if (temp2 && typeof temp2.effect == 'object' && typeof temp2.effect.target == 'function') {
@ -4522,7 +4517,7 @@ export class Get extends Uninstantable {
target: target,
skill: skills2[i],
isLink: isLink,
})) temp2 = temp2.effect.target(card, player, target, result2, isLink);
})) temp2 = cache.delegate(temp2.effect).target(card, player, target, result2, isLink);
else temp2 = undefined;
}
else temp2 = undefined;
@ -4567,7 +4562,7 @@ export class Get extends Uninstantable {
result2 += temp02;
result1 += temp01;
if (typeof card == 'object' && !result.ignoreStatus) {
if (get.attitude(player, target) < 0) {
if (cache.get.attitude(player, target) < 0) {
result2 *= Math.sqrt(threaten);
}
else {
@ -4576,7 +4571,7 @@ export class Get extends Uninstantable {
// *** continue here ***
if (target.hp == 1) result2 *= 2.5;
if (target.hp == 2) result2 *= 1.8;
let targetCountCards = target.cacheCountCards('h');
let targetCountCards = target.countCards('h');
if (targetCountCards == 0) {
if (get.tag(card, 'respondSha') || get.tag(card, 'respondShan')) {
result2 *= 1.7;
@ -4601,19 +4596,19 @@ export class Get extends Uninstantable {
if (zerotarget) result2 = 0;
var final = 0;
if (player2) {
final = (result1 * get.attitude(player2, player) + (target ? result2 * get.attitude(player2, target) : 0));
final = (result1 * cache.get.attitude(player2, player) + (target ? result2 * cache.get.attitude(player2, target) : 0));
}
else final = (result1 * get.attitude(player, player) + (target ? result2 * get.attitude(player, target) : 0));
else final = (result1 * cache.get.attitude(player, player) + (target ? result2 * cache.get.attitude(player, target) : 0));
if (!isLink && get.tag(card, 'natureDamage') && !zerotarget) {
var info = get.info(card);
if (!info || !info.ai || !info.ai.canLink) {
if (target.isLinked()) game.players.forEach(function (current) {
if (current != target && current.isLinked()) final += get.effect(current, card, player, player2, true);
if (current != target && current.isLinked()) final += cache.get.effect(current, card, player, player2, true);
});
}
else if (info.ai.canLink(player, target, card)) {
game.players.forEach(function (current) {
if (current != target && current.isLinked()) final += get.effect(current, card, player, player2, true);
if (current != target && current.isLinked()) final += cache.get.effect(current, card, player, player2, true);
});
}
}

View File

@ -9,24 +9,49 @@ import { hex_md5 } from "../crypt/md5.js";
export class CacheContext{
constructor(){
this.lib = this.createCacheProxy(Library);
this.game = this.createCacheProxy(Game);
this.get = this.createCacheProxy(Get);
this.sourceMap = {};
this.lib = this._createCacheProxy(Library);
this.game = this._createCacheProxy(Game);
this.get = this._createCacheProxy(Get);
this.sourceMap = new Map();
this.storageMap = new Map();
}
/**
* 设置当前是否处于缓存环境当使用inject对类进行注入时只在缓存环境下会返回缓存值
* @param {boolean} cache
*/
static setInCacheEnvironment(cache){
_status.cacheEnvironment = cache;
}
/**
* 设置一个公有的缓存上下文缓存上下文持有期间假设所缓存的函数在参数相同时绝对不会注意是绝对不会返回不同的返回值
* 使用inject对类进行注入时将应用公有的缓存上下文
* @param {CacheContext} context
*/
static setCacheContext(context){
_status.cacheContext = context;
}
/**
* 返回当前公有的缓存上下文
* @returns {CacheContext} 缓存上下文
*/
static getCacheContext(){
return _status.cacheContext;
}
/**
* 移除当前公有的缓存上下文
*/
static removeCacheContext(){
delete _status.cacheContext;
}
/**
* 返回公有的缓存上下文没有就创建一个新的返回不会设置为新的公有缓存上下文
* @returns {CacheContext} 缓存上下文
*/
static requireCacheContext(){
let cache = CacheContext.getCacheContext();
if(!cache){
@ -35,15 +60,57 @@ export class CacheContext{
return cache;
}
/**
* 对一个对象进行代理对象的所有函数都将按条件返回缓存结果
* 注意以cache开头的方法依然保持原来的调用
* 如果所代理的对象拥有cacheSupportFunction方法返回一个方法名数组只有允许的方法才会返回缓存结果剩余方法依然保持原来的调用
* @param {any} source 需要代理的对象
* @returns
*/
delegate(source){
if(source === null || source === undefined)return null;
if(typeof source.getCacheKey !== 'function')return source;
let cacheKey = source.getCacheKey();
if(this.sourceMap[cacheKey]){
return this.sourceMap[cacheKey];
if(source === null || source === undefined)return source;
if(source._cacheDelegateSource)return source;
let proxy = this.sourceMap.get(source);
if(proxy){
return proxy;
}
this.sourceMap[cacheKey] = this.createCacheProxy(source);
return this.sourceMap[cacheKey];
proxy = this._createCacheProxy(source);
this.sourceMap.set(source,proxy);
return proxy;
}
/**
* 对一个类进行注入methods为可以返回缓存的所有方法注入后此类的相关方法会在公有缓存上下文下返回缓存值
* @param {any} source
* @param {Array<string>} methods
* @returns
*/
static inject(source,methods){
if(source == null || source === undefined)return null;
for(let method of methods){
let func = source[method];
if(typeof func != 'function')continue;
source[method] = function(){
try{
if(!_status.cacheEnvironment){
return func.call(this,...arguments);
}
return CacheContext
._getCacheValueFromObject(CacheContext.requireCacheContext()._requireStorage(this),method,arguments,this,func);
}catch(e){
return func.call(this,...arguments);
}
}
}
}
_requireStorage(obj){
let storage = this.storageMap.get(obj);
if(!storage){
storage = {};
this.storageMap.set(obj,storage);
}
return storage;
}
/**
@ -51,11 +118,12 @@ export class CacheContext{
* @param {T} delegateObject
* @returns {T}
*/
createCacheProxy(delegateObject){
_createCacheProxy(delegateObject){
const cacheFuncObj = {};
const cacheStorage = {};
return new Proxy(delegateObject,{
get:(target,key)=>{
if(key == '_cacheDelegateSource')return delegateObject;
let value = target[key];
if(key.indexOf('cache') == 0){
return value;
@ -71,9 +139,9 @@ export class CacheContext{
wrapFunc = function(){
try{
return CacheContext
.getCacheValueFromObject(cacheStorage,key,arguments,target);
._getCacheValueFromObject(cacheStorage,key,arguments,target);
}catch(e){
return value.apply(target,arguments);
return value.call(target,...arguments);
}
};
cacheFuncObj[key] = wrapFunc;
@ -85,20 +153,22 @@ export class CacheContext{
});
}
static getCacheValueFromObject(storage,key,params,source){
static _getCacheValueFromObject(storage,key,params,source,func){
let cache = storage;
let funcCache = CacheContext.ensureMember(cache,key);
let cacheKey = CacheContext.wrapParametersToCacheKey(params);
let funcCache = CacheContext._ensureMember(cache,key);
let cacheKey = CacheContext._wrapParametersToCacheKey(params);
let ret = funcCache[cacheKey];
if(ret === undefined){
ret = source[key](...params);
ret = ((typeof func == 'function')?func:source[key]).call(source,...params);
funcCache[cacheKey] = ret;
//console.log('缓存未命中!'+key+":"+cacheKey+":"+params.length+":ret:"+ret);
}else{
//console.log(key+":"+cacheKey+":"+params.length+":ret:"+ret);
}
//console.log(key+":"+cacheKey+":"+params.length+":ret:"+ret);
return ret;
}
static ensureMember(obj,key){
static _ensureMember(obj,key){
let mem = obj[key];
if(!mem){
mem = {};
@ -107,14 +177,14 @@ export class CacheContext{
return mem;
}
static wrapParametersToCacheKey(params){
static _wrapParametersToCacheKey(params){
return Array.from(params)
.filter(p=>!(p instanceof CacheContext))
.map(param=>CacheContext.wrapParameterToCacheKey(param))
.map(param=>CacheContext._wrapParameterToCacheKey(param))
.join('-');
}
static wrapParameterToCacheKey(param){
static _wrapParameterToCacheKey(param){
if(param === null)return 'null';
if(param === undefined)return 'undefined';
if(typeof param === 'string')return `[str:${param}]`;
@ -122,11 +192,11 @@ export class CacheContext{
if(typeof param === 'boolean')return `[bl:${param}]`;
if(typeof param.getCacheKey == 'function')return param.getCacheKey();
if(Array.isArray(param)){
return `[arr:[${param.filter(p=>!(p instanceof CacheContext)).map(p=>CacheContext.wrapParameterToCacheKey(p)).join('-')}]]`;
return `[arr:[${param.filter(p=>!(p instanceof CacheContext)).map(p=>CacheContext._wrapParameterToCacheKey(p)).join('-')}]]`;
}
if(typeof param === 'function')return `[f:${hex_md5(param.toString())}]`;
let entries = Object.entries(param);
entries.sort((a,b)=>a[0]<b[0]?-1:1);
return `[obj:{${entries.map(e=>e[0]+":"+CacheContext.wrapParameterToCacheKey(e[1])).join(',')}}]`;
return `[obj:{${entries.map(e=>e[0]+":"+CacheContext._wrapParameterToCacheKey(e[1])).join(',')}}]`;
}
}

View File

@ -3247,6 +3247,8 @@ export class Player extends HTMLDivElement {
if(arg2){
if(typeof arg2 == 'string'){
filter = card=>(getCardName(card) == arg2);
}else if(Array.isArray(arg2)){
filter = card=>arg2.includes(getCardName(card));
}else if(typeof arg2 == 'object'){
filter = card=>{
for (let j in arg2) {
@ -3355,13 +3357,6 @@ export class Player extends HTMLDivElement {
}
return list;
}
cacheCountCards(arg1){
let cache = CacheContext.getCacheContext();
if(cache){
return cache.delegate(this).countCards(arg1);
}
return this.countCards(arg1);
}
countCards(arg1, arg2) {
let count = 0;
for(let item of this.iterableGetCards(arg1,arg2)){
@ -3398,19 +3393,15 @@ export class Player extends HTMLDivElement {
}
return skills;
}
getModableSkills(useCache) {
var func = function (player) {
var skills = player.getSkills().concat(lib.skill.global);
game.expandSkills(skills);
skills = skills.filter(function (skill) {
var info = get.info(skill);
return info && info.mod;
});
skills.sort((a, b) => get.priority(a) - get.priority(b));
return skills;
};
if (!useCache) return func(this);
return game.callFuncUseStepCache("player.getModableSkills", func, [this]);
getModableSkills() {
var skills = this.getSkills().concat(lib.skill.global);
game.expandSkills(skills);
skills = skills.filter(function (skill) {
var info = get.info(skill);
return info && info.mod;
});
skills.sort((a, b) => get.priority(a) - get.priority(b));
return skills;
}
getSkills(arg2, arg3, arg4) {
var skills = this.skills.slice(0);
@ -4760,9 +4751,6 @@ export class Player extends HTMLDivElement {
}
});
}
cacheSupportFunction(){
return ['hasCard','hasValueTarget','getCardIndex','countCards','getSkills','getUseValue','canUse'];
}
moveCard() {
var next = game.createEvent('moveCard');
next.player = this;
@ -4830,7 +4818,7 @@ export class Player extends HTMLDivElement {
this.logSkill(event.logSkill);
}
else if (Array.isArray(event.logSkill)) {
this.logSkill.apply(this, event.logSkill);
this.logSkill.call(this,...event.logSkill);
}
}
if (result.card || !result.skill) {
@ -6914,8 +6902,47 @@ export class Player extends HTMLDivElement {
return player.canUse(card, current, distance, includecard);
});
}
hasValueTarget() {
return this.getUseValue.apply(this, arguments) > 0;
hasValueTarget(card, distance, includecard) {
if (typeof (card) == 'string') {
card = { name: card, isCard: true };
}
var player = this;
var targets = game.filterPlayer();
var value = [];
var min = 0;
var info = get.info(card);
if (!info || info.notarget) return false;
var range;
var select = get.copy(info.selectTarget);
if (select == undefined) {
if (info.filterTarget == undefined) return true;
range = [1, 1];
}
else if (typeof select == 'number') range = [select, select];
else if (get.itemtype(select) == 'select') range = select;
else if (typeof select == 'function') range = select(card, player);
if (info.singleCard) range = [1, 1];
game.checkMod(card, player, range, 'selectTarget', player);
if (!range) return false;
let cache = CacheContext.requireCacheContext();
for (var i = 0; i < targets.length; i++) {
if (player.canUse(card, targets[i], distance, includecard)) {
var eff = cache.get.effect(targets[i], card, player, player);
if(range[1]==1 && eff > 0){
return true;
}
value.push(eff);
}
}
value.sort(function (a, b) {
return b - a;
});
for (var i = 0; i < value.length; i++) {
if (i == range[1] || range[1] != -1 && value[i] <= 0) break;
min += value[i];
}
return min > 0;
}
getUseValue(card, distance, includecard) {
if (typeof (card) == 'string') {
@ -6940,10 +6967,7 @@ export class Player extends HTMLDivElement {
game.checkMod(card, player, range, 'selectTarget', player);
if (!range) return 0;
let cache = CacheContext.getCacheContext();
if(!cache){
cache = new CacheContext();
}
let cache = CacheContext.requireCacheContext();
for (var i = 0; i < targets.length; i++) {
if (player.canUse(card, targets[i], distance, includecard)) {
var eff = cache.get.effect(targets[i], card, player, player);
@ -8076,7 +8100,7 @@ export class Player extends HTMLDivElement {
return targets;
}
isEnemyOf() {
return !this.isFriendOf.apply(this, arguments);
return !this.isFriendOf.call(this,...arguments);
}
isFriendOf(player) {
if (get.mode() == 'guozhan') {
@ -10154,3 +10178,6 @@ export class Player extends HTMLDivElement {
}
}
}
CacheContext.inject(Player.prototype,
['hasCard','hasValueTarget','getModableSkills','getCardIndex','countCards','getSkills','getUseValue','canUse']);