import { SkillCfg } from "cfg/parsers/SkillCfg"; import e from "express"; import { SKillEffectData } from "message/SkillInfo"; import CfgMan from "../CfgMan"; import { PetHandler } from "../Handler/PetHandler"; import { PlayerHandler } from "../Handler/PlayerHandler"; import { CondDecideType, EnhanceCustomType, GameCampType, GameUnitType, SkillEffectType, SkillEffectValueType, SkillRangeUnitType, SkillType, SkillUserType, TriggerType } from "./SkillConst"; import { SkillParam, SkillTarget } from "./SkillParam"; import { TriggerCtrl } from "./TriggerCtrl"; import TriggerManager from "./TriggerMan"; export class Skill { _currCount: number; _roundCount: number; _startround: number; _delayround: number; _id: number; _data: SkillCfg; _type: any; _param: number; _tgctrl: TriggerCtrl; _man: any; _owner: PlayerHandler; _start: boolean; _cb: any; halo_v: number = -1; rd: number = 0; _orign_effcnt: number = 0; _orign_cardpt: number = 0; private _subskill: Skill; private _subskill2: Skill; _sender: PetHandler; _petowner: PetHandler; // LIFE-CYCLE CALLBACKS: // onLoad () {}; // start () {}; // update (dt) {}; init(skillid: number, skilldata: SkillCfg, manager: any) { this._currCount = 0; // 当前计数 this._roundCount = 0; // 回合数 this._startround = 0; // 触发后回合数 this._delayround = 0; // 延迟回合数 this._id = skillid; this._data = skilldata; this._type = skilldata.skill_typeid; // todo: 根据bufftype处理paramlst this._param = TriggerManager.handleEffectParam(this._type, skilldata.eff_num); this._tgctrl = TriggerManager.addSkillTrigger(this._id, skilldata.tigger_typeid, skilldata.cond_typeid, skilldata.cond_rangeid, skilldata.cond_num); this._man = manager; }; triggerType() { return this._data.tigger_typeid; }; skillname() { return this._data.name; }; clear() { this._id = 0; this._data = null; }; removeSelf() { }; isSkill() { return true; }; isOver() { return false; }; isSame(id: number) { return this._id == id; }; isBornSkill(){ return this._type == SkillType.BORN; }; isDieSkill(){ return this._type == SkillType.DEAD; }; isAPHaloSkill(){ return this._type == SkillType.HALO; }; isTauntSkill(){ return this._data.effect_typeid == SkillEffectType.TAUNT; }; isTransEffCardSkill(){ return this._data.effect_typeid == SkillEffectType.CARD_CHG_EN; }; isAttackSkill(){ return this._data.effect_typeid == SkillEffectType.ATTACK; }; isRebornSkill(){ return this._data.effect_typeid == SkillEffectType.REBORN; }; isBuffHaloSkill(){ return this._type == SkillType.HALO_SKILL; }; isSingleTarget(){ switch(this._data.rangeid){ case SkillRangeUnitType.ALL: case SkillRangeUnitType.ALL_EXSELF: return false; default: return true; } }; isAllTarget(){ return this._data.rangeid == SkillRangeUnitType.ALL; }; isInRange(srcpet: PetHandler, dstpet: PetHandler, exhero: boolean){ switch(this._data.rangeid){ case SkillRangeUnitType.SELF: return srcpet == dstpet; case SkillRangeUnitType.SINGLE: return false; case SkillRangeUnitType.OTHER: return false; case SkillRangeUnitType.ALL: return true; case SkillRangeUnitType.ALL_EXSELF: case SkillRangeUnitType.RANDOM_ONE_EXSELF: return srcpet != dstpet; case SkillRangeUnitType.RANDOM_ONE: return !!dstpet; case SkillRangeUnitType.OWNER: return dstpet == this._petowner; case SkillRangeUnitType.ALL_EXOWNER: case SkillRangeUnitType.RANDOM_ONE_EXOWNER: return dstpet != this._petowner; case SkillRangeUnitType.MAXAP_ONE: return dstpet == this._owner.getMaxAPPet(exhero); case SkillRangeUnitType.MINAP_ONE: return dstpet == this._owner.getMinAPPet(exhero); case SkillRangeUnitType.PET_LAST: return dstpet == this._owner.getLastPet(); case SkillRangeUnitType.RANDOM_ONE_NOSHIELD: return dstpet && !dstpet.hasShield(); default: return false; } }; // 技能光环是否能影响dst canEffect(srcpet: PetHandler, dstpet: PetHandler){ if(this._data.friendlyid != GameCampType.SELF){ return false; } let tgok = false; switch(this._data.targetid){ case GameUnitType.BATTLEUNIT: tgok = this.isInRange(srcpet, dstpet, false); break; case GameUnitType.HERO: tgok = dstpet._isHero; break; case GameUnitType.PET: if(!dstpet._isHero){ tgok = this.isInRange(srcpet, dstpet, true); } break; default: break; } return tgok; }; getExPet(src: PetHandler){ switch(this._data.rangeid){ case SkillRangeUnitType.ALL_EXOWNER: return this._petowner; case SkillRangeUnitType.ALL_EXSELF: return src; }; return null; }; getTargets(param: SkillParam): SkillTarget[]{ return this._owner._owner.getSkillTargets(this, param); }; getOppTargets(st: SkillTarget): SkillTarget[]{ return this._owner._owner.getSkillOppTargets(st); }; getQuoteValue(count: number, maxcount: number, effcount: number){ return this.getFinalValue(EnhanceCustomType.QUOTE_TIMES, count, maxcount, effcount, true); }; getEffValue(ac?: number, ap?: number, sp?: number): number{ let nmin = CfgMan.calcEffctValueEx(EnhanceCustomType.EFF_VALUE, this._data.eff_numtypeid, this._data.num_signid, this._data.eff_num, ap, sp); let nmax = CfgMan.calcEffctValueEx(EnhanceCustomType.EFF_VALUE, this._data.eff_numtypeid, this._data.num_signid, this._data.eff_nummax, ap, sp); return this.getFinalValue(EnhanceCustomType.EFF_VALUE, nmin, nmax, ac); }; getFinalValue(vtype:EnhanceCustomType, nmin: number, nmax: number, ac:number, needfix: boolean = false): number{ let n = 0; if(CfgMan.canEnhanceValue(vtype, this._data.edd_effid)){ n = CfgMan.randomEffValue(nmin, nmax, this._data.edd_effid, this._data.eddeffnum_signid, this._data.edd_effnum, ac); }else{ n = CfgMan.roundV(nmin, nmax); } if(needfix && n == 0){ n = 1; } return n; }; getHaloValue(): number{ if(!this.isAPHaloSkill()){ return 0; } this.checkHaloValue(); return this.halo_v; }; addHaloValue(v: number): number{ this.checkHaloValue(); if(this.halo_v > 0){ let tmp = this.halo_v; this.halo_v += v; if(this.halo_v < 0){ this.halo_v = 0; return -tmp; }else{ return v; } } return 0; }; resetHaloValue(){ this.halo_v = -1; }; checkHaloValue(){ if(this.halo_v < 0){ this.halo_v = this.getEffValue(this._orign_effcnt, this._orign_cardpt); } }; _triggerSubSkill(sk: Skill, skid: number, skusertype: number, skcount: number, skmaxcount: number, param: SkillParam, sts: SkillTarget[], cb?: any){ if(skid && !sk){ sk = this._owner.newSkill(skid); sk.setOrignParam(this._orign_effcnt, this._orign_cardpt, this._sender, this._petowner); } if(sk){ let pl = []; let bst = false; switch(skusertype){ case SkillUserType.SRC_HERO: case SkillUserType.SRC_PLAYER: { let sp = param.clone(); let ph = sp.srcplayer? sp.srcplayer: sp.srcpet._owner; sp.srcpet = ph._self; pl.push(sp); } break; case SkillUserType.TARGET: if(sts && sts.length > 0){ sts.forEach((item: SkillTarget)=>{ let sp = param.oppClone(); if(item.dsttype != GameUnitType.NONE){ if(item.dsttype == GameUnitType.PLAYER){ sp.srcplayer = (item.dst as PlayerHandler); sp.srcpet = sp.srcplayer._self; }else { sp.srcpet = (item.dst as PetHandler); sp.srcplayer = sp.srcpet._owner; } } pl.push(sp); }); bst = true; }else{ pl.push(param.oppClone()); } break; default: pl.push(param); break; } let ncount = this.getQuoteValue(skcount, skmaxcount, param.edd_cnt); for(let i=0; i{ if(this.isTotalCardSkill()){ if(cdt == CondDecideType.EQUAL){ this._owner.addTotalCard(-v); }else if(cdt == CondDecideType.GREATER){ this._owner.resetTotalCard(); } } })){ this.trigger(tg_target, cb); return 1; }else{ return 0; } }; handleCard(efftype: SkillEffectType, effvalue: number, tgt: SkillTarget){ let res = effvalue; switch(efftype){ case SkillEffectType.CARD_ADD: if(tgt.dsttype == GameUnitType.PLAYER){ let n = (tgt.dst as PlayerHandler).addCard(res, tgt.srcPlayer()); if(n >= 0){ tgt.success(efftype, n); }else{ tgt.fail(efftype, n); } }else{ tgt.fail(efftype, -1); } break; case SkillEffectType.CARD_ADD_LIMIT: if(tgt.dsttype == GameUnitType.PLAYER){ let n = (tgt.dst as PlayerHandler).addCardLimit(res, tgt.srcPlayer()); if(n >= 0){ tgt.success(efftype, n); }else{ tgt.fail(efftype, -1); } }else{ tgt.fail(efftype, -1); } break; case SkillEffectType.CARD_STEAL: if(tgt.dsttype == GameUnitType.PLAYER){ let n = tgt.srcplayer.stealCard((tgt.dst as PlayerHandler), res); if(n >= 0){ tgt.success(efftype, n); }else{ tgt.fail(efftype, -1); } }else{ tgt.fail(efftype, -1); } break; case SkillEffectType.CARD_CHG_EN: //todo: 暂不处理 break; case SkillEffectType.CARD_GETDIRECT: if(tgt.dsttype == GameUnitType.PLAYER){ let cardid = this._data.quotecardid; let ncount = this.getQuoteValue(this._data.quotecard_times, this._data.quotecard_timesmax, this._orign_effcnt); let n = (tgt.dst as PlayerHandler).addDirectCard(cardid, ncount, tgt.srcPlayer()); if(n >= 0){ tgt.success(efftype, n); }else{ tgt.fail(efftype, -1); } }else{ tgt.fail(efftype, -1); } break; case SkillEffectType.CARD_DROP: { if(tgt.dsttype == GameUnitType.PLAYER){ let n = (tgt.dst as PlayerHandler).dropCard(res, tgt.srcPlayer()); if(n >= 0){ tgt.success(efftype, n); }else{ tgt.fail(efftype, n); } }else{ tgt.fail(efftype, -1); } break; }break; default: break; } }; handlePower(efftype: SkillEffectType, effvalue: number, tgt: SkillTarget){ switch(efftype){ case SkillEffectType.POWER_ENHANCE: case SkillEffectType.POWEREX_ENHANCE: if(tgt.dsttype != GameUnitType.NONE){ let n = efftype == SkillEffectType.POWER_ENHANCE? tgt.dst.addBaseAP(effvalue, tgt.srcPet()) : tgt.dst.addExAP(effvalue, tgt.srcPet()); tgt.success(efftype, n); tgt.success(SkillEffectType.CHG_AP, n); }else{ tgt.fail(efftype, -1); } break; case SkillEffectType.HURT_POWER: case SkillEffectType.HURT_ALL: let effv = this.EMV(effvalue); if(tgt.dsttype != GameUnitType.NONE){ let oldhp = tgt.dst.getHP(); let n = tgt.dst.beHurt(effv, tgt.srcPet()); tgt.success(efftype, n); if(n != 0){ tgt.success(SkillEffectType.CHG_AP, n); } let dthp = tgt.dst.getHP() - oldhp; if(dthp != 0){ tgt.success(SkillEffectType.CHG_HP, dthp); } if(n == 0 && dthp == 0){ tgt.success(SkillEffectType.CHG_AP, 0); } let hv = n + dthp; let pet = tgt.srcPet(); if(!this.canEM() && hv != 0 && pet && pet.canHPS()){ //吸血 let sv = pet.HPS(hv); if(sv != 0){ tgt.success(SkillEffectType.CHG_AP, sv, true); } } }else{ tgt.fail(efftype, -1); } break; default: break; } }; handleHP(effvalue: number, tgt: SkillTarget){ let efftype = SkillEffectType.HURT_HP; if(tgt.dsttype != GameUnitType.NONE){ let effv = this.EMV(effvalue); let n = tgt.dst.addHP(effv, tgt.srcPet()); tgt.success(efftype, n); tgt.success(SkillEffectType.CHG_HP, n); }else{ tgt.fail(efftype, -1); } }; handleHPS(effvalue: number, tgt: SkillTarget){ let efftype = SkillEffectType.HP_STEAL_ENHANCE; if(tgt.dsttype != GameUnitType.NONE){ let effv = effvalue/100; let n = tgt.dst.addHPS(effv, tgt.srcPet()); tgt.success(efftype, n); }else{ tgt.fail(efftype, -1); } }; summon(efftype: SkillEffectType, exparam: SkillParam, tgt: SkillTarget){ switch(efftype){ case SkillEffectType.SUMMON_NPC: { let ncount = this.getQuoteValue(this._data.quoteunit_times, this._data.quoteunit_timesmax, exparam.edd_cnt); let obj = tgt.srcpet? tgt.srcpet: tgt.srcplayer; let n = obj.summonPet(this._data.quoteunitid, ncount, exparam); if(n >= 0){ tgt.success(efftype, n); }else{ tgt.fail(efftype, -1); } } break; case SkillEffectType.SUMMON_SKILL: { let obj = tgt.srcpet? tgt.srcpet: tgt.srcplayer; if(!obj){ tgt.fail(efftype, -1); return; } let n1 = this.getQuoteValue(this._data.quoteskill_times, this._data.quoteskill_timesmax, exparam.edd_cnt); let r1 = obj.useSkill(this._data.quoteskillid, n1, exparam); r1 && tgt.success(efftype, this._data.quoteskillid); let n2 = this.getQuoteValue(this._data.quoteskill2_times, this._data.quoteskill2_timesmax, exparam.edd_cnt); let r2 = obj.useSkill(this._data.quoteskill2id, n2, exparam); r2 && tgt.success(efftype, this._data.quoteskill2id); if(!r1 && !r2){ tgt.fail(efftype, -1); } } break; case SkillEffectType.SKILL_GET: { let sender: PetHandler = null; if(this.isBuffHaloSkill()){ if(tgt.srcpet){ sender = tgt.srcpet; }else if(tgt.srcplayer){ sender = tgt.srcplayer._self; } } let bres1 = false, bres2 = false; if(this._data.getskillid){ let obj = tgt.getTarget(this._data.skill_ownersid); if(!obj){ tgt.fail(efftype, this._data.getskillid); }else{ let ncount = this.getFinalValue(EnhanceCustomType.GET_TIMES, this._data.getskill_times, this._data.getskill_timesmax, exparam.edd_cnt, true); let res = obj.useSkillEx(this._data.getskillid, ncount, sender); res? tgt.success(efftype, this._data.getskillid): tgt.fail(efftype, this._data.getskillid); } bres1 = true; } if(this._data.getskill2id){ let obj = tgt.getTarget(this._data.skill2_ownersid); if(!obj){ tgt.fail(efftype, this._data.getskill2id); }else{ let ncount = this.getFinalValue(EnhanceCustomType.GET_TIMES, this._data.getskill2_times, this._data.getskill2_timesmax, exparam.edd_cnt, true); let res = obj.useSkillEx(this._data.getskill2id, ncount, sender); res? tgt.success(efftype, this._data.getskill2id): tgt.fail(efftype, this._data.getskill2id); } bres2 = true; } if(!bres1 && !bres2){ tgt.fail(efftype, -1); } } break; default: break; } }; taunt(tgt:SkillTarget){ let efftype = SkillEffectType.TAUNT; if(tgt.dsttype != GameUnitType.NONE){ tgt.dst.taunt(); tgt.success(efftype, 1); }else{ tgt.fail(efftype, -1); } }; addBuff(efftype: SkillEffectType, effvalue: number, tgt: SkillTarget){ switch(efftype){ case SkillEffectType.BUFF_SHIELD: if(tgt.dsttype != GameUnitType.NONE){ let n = tgt.dst.addBuff(efftype, 1, tgt.srcPet()); if(n){ tgt.success(efftype, n); }else{ tgt.fail(efftype, n); } }else{ tgt.fail(efftype, -1); } break; default: break; } }; reduceHurt(effvalue: number, tgt: SkillTarget){ let efftype = SkillEffectType.HURT_REDUCE; if(tgt.dsttype != GameUnitType.NONE){ let n = tgt.dst.addReduceHurt(effvalue, tgt.srcPet()); tgt.success(efftype, n); }else{ tgt.fail(efftype, -1); } }; enhanceMagic(effvalue: number, tgt: SkillTarget){ let efftype = SkillEffectType.ENHANCE_MAGIC; if(tgt.dsttype != GameUnitType.NONE){ let obj = tgt.dst; let n = obj.addEM(effvalue); if(n >= 0){ tgt.success(efftype, n); }else{ tgt.fail(efftype, n); } }else{ tgt.fail(efftype, -1); } }; EMV(effvalue: number){ if(!this._data.spellpower){ return effvalue; } let ev = this._owner.getEM(); return effvalue + ev; }; canEM(){ return this._data.spellpower; }; reborn(tgt: SkillTarget){ let efftype = SkillEffectType.REBORN; if(tgt.dsttype != GameUnitType.NONE){ let res = tgt.dst.reborn(tgt.srcPet()); if(res){ tgt.success(efftype, 1); }else{ tgt.fail(efftype, -1); } }else{ tgt.fail(efftype, -1); } }; silent(effvalue: number, tgt: SkillTarget){ let efftype = SkillEffectType.REBORN; if(tgt.dsttype != GameUnitType.NONE){ let res = tgt.dst.beSilent(effvalue); if(res){ tgt.success(efftype, res); }else{ tgt.fail(efftype, -1); } }else{ tgt.fail(efftype, -1); } }; attack(effvalue: number, tgt: SkillTarget, param: SkillParam, isAtkBack: boolean = false){ let efftype = isAtkBack? SkillEffectType.ATTACK_BACK: SkillEffectType.ATTACK; if(tgt.dsttype != GameUnitType.NONE){ let obj = tgt.srcpet? tgt.srcpet: tgt.srcplayer; let v = effvalue; let oldhp = tgt.dst.getHP(); let dst = tgt.dsttype == GameUnitType.PLAYER? (tgt.dst as PlayerHandler)._self: (tgt.dst as PetHandler); // let n = obj.canAttack()? obj.attack(this, dst, param, v, isAtkBack): 1; let n = obj.attack(this, dst, param, v, isAtkBack); if(n <= 0){ tgt.success(efftype, n); if(n != 0){ tgt.success(SkillEffectType.CHG_AP, n); } // if(this._data.quoteskillid){ // let dp = this._data.skill_users? param.oppClone(): param; // let pet = tgt.srcpet; // if(!pet && tgt.srcplayer){ // pet = tgt.srcplayer._self; // } // (tgt.dst as PetHandler).attack(pet, dp, 0, true); // } let dthp = tgt.dst.getHP() - oldhp; if(dthp != 0){ tgt.success(SkillEffectType.CHG_HP, dthp); } if(n == 0 && dthp == 0){ tgt.success(SkillEffectType.CHG_AP, 0); } let hv = n + dthp; let pet = tgt.srcPet(); if(!this.canEM() && hv != 0 && pet && pet.canHPS()){ //吸血 let sv = pet.HPS(hv); if(sv != 0){ tgt.success(SkillEffectType.CHG_AP, sv, true); } } tgt.success(efftype, hv); }else{ tgt.fail(efftype, n); } }else{ tgt.fail(efftype, -1); } }; setOwner(owner: PlayerHandler) { this._owner = owner; }; setTriggerCallback(cb: any) { this._cb = cb; }; setOrignParam(effcnt: number, cardpoint: number, source: PetHandler, petowner: PetHandler){ this._orign_effcnt = effcnt; this._orign_cardpt = cardpoint; this._sender = source; this._petowner = petowner; }; isTotalCardSkill(){ return this._tgctrl._cond.isTempTotalCard(); }; clone() { let obj = new Skill(); obj._currCount = 0; // 当前计数 obj._roundCount = 0; // 回合数 obj._startround = 0; // 触发后回合数 obj._delayround = 0; // 延迟回合数 obj._id = this._id; obj._data = this._data; obj._type = this._type; obj._param = this._param; obj._tgctrl = this._tgctrl; return obj; }; };