2021-01-05 11:16:20 +08:00

758 lines
25 KiB
TypeScript

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;
_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, exself: 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(exself);
case SkillRangeUnitType.MINAP_ONE:
return dstpet == this._owner.getMinAPPet(exself);
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);
};
getEnhanceValue(param: SkillParam): number{
return CfgMan.calcEnhanceValue(this._data.edd_effid, this._data.edd_effnum, param.edd_cnt, param.cardpoint);
};
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, ap, sp);
};
getFinalValue(vtype:EnhanceCustomType, nmin: number, nmax: number, ac:number, ap: number, sp: number = 0): 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);
}
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(skillid: number, sk: Skill, param: SkillParam, sts: SkillTarget[], cb?: any){
if(skillid && !sk){
sk = this._owner.newSkill(this._data.quoteskillid);
sk.setOrignParam(this._orign_effcnt, this._orign_cardpt, this._sender, this._petowner);
}
if(sk){
let pl = [];
let bst = false;
switch(this._data.skill_usersid){
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.getFinalValue(EnhanceCustomType.QUOTE_TIMES, this._data.quotecard_times,
this._data.quotecard_timesmax, param.edd_cnt, param.cardpoint);
if(ncount == 0){
ncount = 1;
}
for(let i=0; i<ncount;i++){
for(let j = 0; j < pl.length; j++){
let sp = pl[j];
let st = bst? sts[j]: null;
sk._trigger(sp, cb, st);
}
}
}
};
_trigger(param: SkillParam, cb?: any, target?: SkillTarget) {
//触发buff效果
let res = TriggerManager.onTrigger(this, param, target);
this._currCount++;
if (!this._start) {
this._start = true;
}
cb && cb(this, param, res);
this._cb && this._cb(this, param, res);
this._triggerSubSkill(this._data.quoteskillid, this._subskill, param, res, cb);
};
trigger(param: SkillParam, cb?: any) {
let ncount = this.getFinalValue(EnhanceCustomType.RELEASE_TIMES, this._data.release_times,
this._data.release_timesmax, param.edd_cnt, param.cardpoint);
if(ncount == 0){
ncount = 1;
}
let sp;
if(param.srcpet != this._petowner){
sp = param.clone();
sp.srcpet = this._petowner;
sp.srcplayer = sp.srcpet._owner;
}else{
sp = param;
}
for(let i=0; i<ncount;i++){
this._trigger(sp, cb);
}
};
checkTrigger(tg_type: TriggerType, tg_value: any, 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 n = (tgt.dst as PlayerHandler).addDirectCard(cardid, res, 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 && tgt.dsttype != GameUnitType.PLAYER){
let n = efftype == SkillEffectType.POWER_ENHANCE? (tgt.dst as PetHandler).addBaseAP(effvalue): (tgt.dst as PetHandler).addExAP(effvalue, this);
tgt.success(efftype, 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);
if(n != 0){
tgt.success(SkillEffectType.HURT_POWER, n);
}
let dthp = tgt.dst.getHP() - oldhp;
if(dthp != 0){
tgt.success(SkillEffectType.HURT_HP, dthp);
}
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.HURT_POWER, 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.success(efftype, 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;
let n = tgt.dst.addHPS(effv);
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.getFinalValue(EnhanceCustomType.QUOTE_TIMES, this._data.quoteunit_times, this._data.quoteunit_timesmax,
exparam.edd_cnt, exparam.cardpoint);
if(ncount == 0){
ncount = 1;
}
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 ncount = this.getFinalValue(EnhanceCustomType.QUOTE_TIMES, this._data.quoteskill_times, this._data.quoteskill_timesmax,
exparam.edd_cnt, exparam.cardpoint);
if(ncount == 0){
ncount = 1;
}
let obj = tgt.srcpet? tgt.srcpet: tgt.srcplayer;
let res = obj.useSkill(this._data.quoteskillid, ncount, exparam);
if(res){
tgt.success(efftype, res.length);
}else{
tgt.fail(efftype, -1);
}
}
break;
case SkillEffectType.SKILL_GET:
{
let ncount = this.getFinalValue(EnhanceCustomType.GET_TIMES, this._data.getskill_times, this._data.getskill_timesmax,
exparam.edd_cnt, exparam.cardpoint);
if(ncount == 0){
ncount = 1;
}
let obj;
let sender: PetHandler = null;
if(this.isBuffHaloSkill()){
if(tgt.srcpet){
sender = tgt.srcpet;
}else if(tgt.srcplayer){
sender = tgt.srcplayer._self;
}
}
switch(this._data.skill_ownersid){
case SkillUserType.NONE:
obj = tgt.srcpet? tgt.srcpet: tgt.srcplayer;
break;
case SkillUserType.TARGET:
obj = tgt.dst;
break;
case SkillUserType.SRC_HERO:
obj = tgt.srcplayer? tgt.srcplayer: tgt.srcpet._owner;
break;
case SkillUserType.SRC_PLAYER:
obj = tgt.srcplayer;
break;
}
let n = obj? obj.addSkill(this._data.getskillid, ncount, sender): 0;
if(n){
tgt.success(efftype, this._data.getskillid);
}else{
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);
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.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();
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 && tgt.dsttype != GameUnitType.PLAYER){
let obj = tgt.srcpet? tgt.srcpet: tgt.srcplayer;
let v = effvalue;
let oldhp = tgt.dst.getHP();
let n = obj.attack(this, (tgt.dst as PetHandler), param, v, isAtkBack);
{
tgt.success(efftype, 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.HURT_HP, dthp);
}
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.HURT_POWER, sv, true);
}
}
}
}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;
};
};