796 lines
26 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
_from: PetHandler;
_petowner: PetHandler;
private _sts: SkillTarget[] = null;
// 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;
};
isSummonSkill(){
return this._data.effect_typeid == SkillEffectType.SKILL_GET;
};
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;
};
getSourceTargets(): SkillTarget[]{
if(!this._from){
return null;
}
return this._owner._owner.singleSkillTargets(this, this._petowner, this._from);
};
getSelfTargets(): SkillTarget[]{
if(!this._petowner){
return null;
}
return this._owner._owner.singleSkillTargets(this, this._petowner, this._petowner);
};
getTargets(param: SkillParam): SkillTarget[]{
return this._owner._owner.getSkillTargets(this, param);
};
getOppTargets(st: SkillTarget): SkillTarget[]{
return this._owner._owner.getSkillOppTargets(st);
};
setTargets(tgt: SkillTarget[]){
// todo是否需要拷贝
if(tgt && tgt.length > 0){
this._sts = tgt;
}
};
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._from, this._petowner, 0);
}
if(sk){
switch(skusertype){
case SkillUserType.NONE:
sk.setTargets(null);
break;
case SkillUserType.TARGET:
sk.setTargets(sts);
break;
case SkillUserType.SRC:
sk.setTargets(this.getSourceTargets());
break;
}
let ncount = this.getQuoteValue(skcount, skmaxcount, this._orign_effcnt);
for(let i=0; i<ncount;i++){
sk.trigger(param, cb);
}
}
};
_real_trigger(ncount: number, param: SkillParam, cb?: any) {
if(!this._sts){
this._sts = this.getTargets(param);
}
for(let i=0; i<ncount;i++){
let res = TriggerManager.onTrigger(this, param, this._sts);
this._currCount++;
if (!this._start) {
this._start = true;
}
cb && cb(this, param, res);
this._cb && this._cb(this, param, res);
}
};
trigger(param: SkillParam, cb?: any) {
if(!this._sts){
this._sts = this.getTargets(param);
}
if(!this.isSummonSkill()){
let ncount = this.getFinalValue(EnhanceCustomType.RELEASE_TIMES, this._data.release_times,
this._data.release_timesmax, this._orign_effcnt, true);
this._real_trigger(ncount, param, cb);
this._triggerSubSkill(this._subskill, this._data.quoteskillid, this._data.skill_usersid,
this._data.quoteskill_times, this._data.quoteskill_timesmax, param, this._sts, cb);
this._triggerSubSkill(this._subskill2, this._data.quoteskill2id, this._data.skill2_usersid,
this._data.quoteskill2_times, this._data.quoteskill2_timesmax, param, this._sts, cb);
}else{
this._triggerSubSkill(this._subskill, this._data.quoteskillid, this._data.skill_usersid,
this._data.quoteskill_times, this._data.quoteskill_timesmax, param, this._sts, cb);
this._triggerSubSkill(this._subskill2, this._data.quoteskill2id, this._data.skill2_usersid,
this._data.quoteskill2_times, this._data.quoteskill2_timesmax, param, this._sts, cb);
let ncount = this.getFinalValue(EnhanceCustomType.RELEASE_TIMES, this._data.release_times,
this._data.release_timesmax, this._orign_effcnt, true);
this._real_trigger(ncount, param, cb);
}
};
checkTrigger(tg_type: TriggerType, tg_value: PlayerHandler, tg_target: SkillParam, cb?: any) {
if (tg_type == TriggerType.ROUND_START_MYSELF) {
this._roundCount++;
if (this._start) {
this._startround++;
}
}
if(this._tgctrl.checkTrigger(tg_type, tg_value, this._owner, (cdt: CondDecideType, v: number)=>{
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);
}
};
getGKValue(count: number, countmax: number, effcount: number): number{
return this.getFinalValue(EnhanceCustomType.GET_TIMES, count, countmax, effcount, true);
};
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, this._orign_effcnt);
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:
{
//nothing to do
}
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, bres3 = false;
if(this._data.getskillid){
let cnt = this.getGKValue(this._data.getskill_times, this._data.getskill_timesmax, this._orign_effcnt);
let res = tgt.dst.summonSkill(this._data.getskillid, cnt, this._data.skill_ownersid, this, exparam);
res? tgt.success(efftype, this._data.getskillid): tgt.fail(efftype, this._data.getskillid);
bres1 = true;
}
if(this._data.getskill2id){
let cnt = this.getGKValue(this._data.getskill2_times, this._data.getskill2_timesmax, this._orign_effcnt);
let res = tgt.dst.summonSkill(this._data.getskill2id, cnt, this._data.skill2_ownersid, this, exparam);
res? tgt.success(efftype, this._data.getskill2id): tgt.fail(efftype, this._data.getskill2id);
bres2 = true;
}
if(this._data.getskill3id){
let cnt = this.getGKValue(this._data.getskill3_times, this._data.getskill3_timesmax, this._orign_effcnt);
let res = tgt.dst.summonSkill(this._data.getskill3id, cnt, this._data.skill3_ownersid, this, exparam);
res? tgt.success(efftype, this._data.getskill3id): tgt.fail(efftype, this._data.getskill3id);
bres2 = true;
}
if(!bres1 && !bres2 && !bres3){
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, tgtflag: number){
this._orign_effcnt = effcnt;
this._orign_cardpt = cardpoint;
this._from = source;
this._petowner = petowner;
switch(tgtflag){
case SkillUserType.TARGET:
if(source && source != petowner){
this.setTargets(this.getSelfTargets());
}
break;
case SkillUserType.SRC:
this.setTargets(this.getSourceTargets());
break;
}
};
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;
};
};