/* * Copyright 2014 The Skfiy Open Association. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.skfiy.typhon.spi.war; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; import javax.cache.Cache; import javax.cache.Caching; import javax.inject.Inject; import javax.management.ObjectName; import org.apache.commons.lang3.StringUtils; import org.apache.commons.math.util.MathUtils; import org.apache.commons.modeler.ManagedBean; import org.skfiy.typhon.AbstractComponent; import org.skfiy.typhon.Typhons; import org.skfiy.typhon.dobj.BSaSkill; import org.skfiy.typhon.dobj.HeroItemDobj; import org.skfiy.typhon.dobj.JoinSkill; import org.skfiy.typhon.domain.FightGroup; import org.skfiy.typhon.domain.Friend; import org.skfiy.typhon.domain.HeroPropertyKeys; import org.skfiy.typhon.domain.IHeroEntity; import org.skfiy.typhon.domain.ITroop; import org.skfiy.typhon.domain.Normal; import org.skfiy.typhon.domain.Player; import org.skfiy.typhon.domain.Troop; import org.skfiy.typhon.domain.VacantData; import org.skfiy.typhon.domain.item.HeroItem; import org.skfiy.typhon.domain.item.IFightItem; import org.skfiy.typhon.domain.item.IFightItem.Shot; import org.skfiy.typhon.domain.item.Race; import org.skfiy.typhon.domain.item.SuccorObject; import org.skfiy.typhon.packet.MultipleValue; import org.skfiy.typhon.packet.Packet; import org.skfiy.typhon.packet.PacketSuccor; import org.skfiy.typhon.packet.SingleValue; import org.skfiy.typhon.script.Script; import org.skfiy.typhon.script.ScriptManager; import org.skfiy.typhon.session.Session; import org.skfiy.typhon.session.SessionContext; import org.skfiy.typhon.session.SessionManager; import org.skfiy.typhon.session.SessionUtils; import org.skfiy.typhon.spi.CacheKeys; import org.skfiy.typhon.spi.ItemProvider; import org.skfiy.typhon.spi.RoleProvider; import org.skfiy.typhon.spi.hero.HeroProvider; import org.skfiy.typhon.spi.society.Society; import org.skfiy.typhon.spi.society.SocietyProvider; import org.skfiy.typhon.spi.war.WarCombo.Point; import org.skfiy.typhon.util.ComponentUtils; import org.skfiy.typhon.util.FastRandom; import org.skfiy.typhon.util.MBeanUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import org.skfiy.typhon.domain.IHeroEntity.Rabbet; /** * * @author Kevin Zou <kevinz@skfiy.org> */ public class WarProvider extends AbstractComponent { private static final Logger LOG = LoggerFactory.getLogger(WarProvider.class); private static final int ROW_1ST = 0; private static final int ROW_2ND = 1; private static final int ROW_3RD = 2; private static final double MIN_FACTOR = 0.95; private final Random HOLD_POINT_RANDOM = new FastRandom(); private final Random FACTOR_RANDOM = new FastRandom(); private static final FastRandom HERO_ID_RANDOM = new FastRandom(); private ObjectName oname; // 初始数据配置 private RaceFactorData[] raceFactors; private TerrainFactorData[] terrainFactors; private double[] furyFactors; private final Map<String, BSaSkill> bsaSkills = new HashMap<>(); private final Map<Integer, Map<String, JoinSkill>> joinSkills = new HashMap<>(); private final List<Map<Shot, Double>> combosRatioFactors = new ArrayList<>(15); @Inject private ScriptManager scriptManager; @Inject private RoleProvider roleProvider; @Inject private SessionManager sessionManager; @Inject private ItemProvider itemProvider; @Inject private HeroProvider heroProvider; @Inject private SocietyProvider societyProvider; private Cache<Integer, VacantData> roleVacantDataCache; @Override protected void doInit() { loadRaceWarFactor(); loadTerrainWarFactor(); loadFuryWarFactor(); loadCombosRatioFactor(); loadBSaSkillConfig(); // 加载必杀配置 loadJoinSkillConfig(); // 加载合体技配置 // register mbean ManagedBean managedBean = MBeanUtils.findManagedBean(getClass()); MBeanUtils.registerComponent(this, managedBean); roleVacantDataCache = Caching.getCacheManager().getCache(CacheKeys.ROLE_VACANT_DATA_CACHE_KEY); } @Override protected void doReload() { // doInit(); } @Override protected void doDestroy() { if (oname != null) { MBeanUtils.REGISTRY.unregisterComponent(oname); } } /** * * @param packet */ public void searchSuccor(Packet packet) { Player player = SessionUtils.getPlayer(); Normal normal = player.getNormal(); MultipleValue result = MultipleValue.createResult(packet); List<Friend> friends = normal.getFriends(); Collections.shuffle(friends); int fc = Typhons.getInteger("typhon.spi.war.commendatoryFriendCount", 10); int fl = fc - 5; if (friends.size() < fl) { fl = friends.size(); } int levelLimit = Typhons.getInteger("typhon.spi.war.commendatoryFriendLevelLimit", 5); int minLevelLimit = normal.getLevel() - levelLimit; int maxLevelLimit = normal.getLevel() + levelLimit; for (Friend friend : friends) { if (result.getVals().size() >= fl) { break; } if (chectSuccor(normal, friend.getRid())) { continue; } if (reset(friend.getRid(), minLevelLimit, maxLevelLimit)) { result.addVal(newPacketSuccor(friend.getRid(), null)); } } Iterator<Cache.Entry<Integer, VacantData>> it = roleVacantDataCache.iterator(); Cache.Entry<Integer, VacantData> entry; while (it.hasNext()) { if (result.getVals().size() >= fc) { break; } entry = it.next(); VacantData vacantData = entry.getValue(); if (vacantData == null || chectSuccor(normal, vacantData.getRid())) { continue; } int level = vacantData.findHeroProperty( vacantData.getFightGroup(vacantData.getLastFidx())[vacantData .getCaptain()]).getLevel(); if (vacantData.getRid() == player.getRole().getRid() || level < minLevelLimit || level > maxLevelLimit || normal.findFriend(vacantData.getRid()) != null) { continue; } result.addVal(newPacketSuccor(vacantData.getRid(), vacantData)); } HeroItem primaryHero = normal.getFightGroup(normal.getLastFidx()).getHeroItem(FightGroup.PRIMARY_POS); // 系统默认生成 for (int i = result.getVals().size(); i < fc; i++) { PacketSuccor succor = new PacketSuccor(); succor.setName(randomName((List) result.getVals())); succor.setIid(randomSuccorHeroId()); succor.setLevel(normal.getLevel()); succor.setStar(primaryHero.getStar().name()); succor.setPowerGuess((int) (primaryHero.getPowerGuess() * (1 + HERO_ID_RANDOM .nextInt(10) / 10))); succor.setPlayerLevel(normal.getLevel()); succor.setLadder(primaryHero.getLadder()); result.addVal(succor); } SessionContext.getSession().write(result); } private boolean chectSuccor(Normal normal, int rid) { boolean bool = false; int CD = Typhons.getInteger("typhon.spi.Warprovider.CD") * 60 * 1000; for (SuccorObject object : normal.getSuccors()) { if (object.getRid() == rid && (System.currentTimeMillis() - object.getTime()) < CD) { bool = true; } } return bool; } private boolean reset(int rid, int minLevelLimit, int maxLevelLimit) { Session otherSession = sessionManager.getSession(rid); boolean bool = false; int level; if (otherSession != null) { Player player = SessionUtils.getPlayer(otherSession); Normal benormal = player.getNormal(); FightGroup fightGroup = benormal.getFightGroup(benormal.getLastFidx()); level = fightGroup.getHeroItems()[fightGroup.getCaptain()].getLevel(); } else { VacantData vacantData = roleProvider.loadVacantData(rid); level = vacantData.findHeroProperty( vacantData.getFightGroup(vacantData.getLastFidx())[vacantData .getCaptain()]).getLevel(); } if (level >= minLevelLimit && level <= maxLevelLimit) { bool = true; } return bool; } /** * 加载好友数据. * * @param packet 协议包 */ public void loadSuccorData(SingleValue packet) { Player player = SessionUtils.getPlayer(); Normal normal = player.getNormal(); HeroItem primaryHero = normal.getFightGroup(normal.getLastFidx()).getHeroItems()[FightGroup.PRIMARY_POS]; int rid = (int) packet.getVal(); JSONObject json; if (rid <= 0) { json = buildSuccorData(primaryHero); } else { IHeroEntity heroEntity; Session beSession = sessionManager.getSession(rid); if (beSession != null) { Normal beNormal = SessionUtils.getPlayer(beSession).getNormal(); FightGroup fightGroup = beNormal.getFightGroup(beNormal.getLastFidx()); heroEntity = fightGroup.getHeroItem(fightGroup.getCaptain()); } else { VacantData vacantData = roleProvider.loadVacantData(rid); heroEntity = vacantData.getPrimaryHero(); } if (primaryHero.getExtraAtk() > heroEntity.getExtraAtk()) { json = buildSuccorData(primaryHero); } else { json = new JSONObject(); int tong = heroEntity.getExtraTong(); int wu = heroEntity.getExtraWu(); int zhi = heroEntity.getExtraZhi(); int atk = heroEntity.getExtraAtk(); int def = heroEntity.getExtraDef(); int matk = heroEntity.getExtraMatk(); int mdef = heroEntity.getExtraMdef(); int hp = heroEntity.getExtraHp(); int critRate = heroEntity.getExtraCritRate(); int decritRate = heroEntity.getExtraDecritRate(); int critMagn = heroEntity.getExtraCritMagn(); int parryRate = heroEntity.getExtraParryRate(); int deparryRate = heroEntity.getExtraDeparryRate(); int parryValue = heroEntity.getExtraParryValue(); if (heroEntity.getRabbets() != null) { for (Rabbet rabbet : heroEntity.getRabbets()) { tong += rabbet.getTong(); wu += rabbet.getWu(); zhi += rabbet.getZhi(); atk += rabbet.getAtk(); def += rabbet.getDef(); matk += rabbet.getMatk(); mdef += rabbet.getMdef(); hp += rabbet.getHp(); critRate += rabbet.getCritRate(); decritRate += rabbet.getDecritRate(); critMagn += rabbet.getCritMagn(); parryRate += rabbet.getParryRate(); deparryRate += rabbet.getDeparryRate(); parryValue += rabbet.getParryValue(); } } json.put("extraTong", tong); json.put("extraWu", wu); json.put("extraZhi", zhi); json.put("extraAtk", atk); json.put("extraDef", def); json.put("extraMatk", matk); json.put("extraMdef", mdef); json.put("extraHp", hp); json.put("extraCritRate", critRate); json.put("extraDecritRate", decritRate); json.put("extraCritMagn", critMagn); json.put("extraParryRate", parryRate); json.put("extraDeparryRate", deparryRate); json.put("extraParryValue", parryValue); } json.put("star", heroEntity.getStar()); } json.put("id", packet.getId()); json.put("type", Packet.Type.rs); player.getSession().write(packet.getNs(), json); } /** * * @param lab * @param troop * @param hero * @return */ public FightObject newFightObject(int lab, Troop troop, IHeroEntity hero) { HeroItemDobj heroItemDobj = itemProvider.getItem(hero.getId()); FightObject fo = new FightObject(lab, hero.getLevel(), hero.getLadder(), hero.getStar(), heroItemDobj); fo.setBaseAtk(getAtk(troop, hero)); fo.setMaxDef(getDef(troop, hero)); fo.setBaseMatk(getMatk(troop, hero)); fo.setMaxMdef(getMdef(troop, hero)); fo.setMaxHp((int) (getHp(troop, hero) * Typhons.getDouble("typhon.spi.pvp.hpMagn", 1.5))); fo.setMaxCritRate(getCritRate(troop, hero)); fo.setMaxDecritRate(getDecritRate(troop, hero)); fo.setMaxCritMagn(getCritMagn(troop, hero)); fo.setMaxParryRate(getParryRate(troop, hero)); fo.setMaxDeparryRate(getDeparryRate(troop, hero)); fo.setMaxParryValue(getParryValue(troop, hero)); fo.setShots(getHeroItemDobjShots(heroItemDobj, hero.getLadder())); return fo; } /** * * @param heroItemDobj * @param ladder * @return */ public Shot[] getHeroItemDobjShots(HeroItemDobj heroItemDobj, int ladder) { if (ladder < 2) { return heroItemDobj.getShots1(); } else if (ladder < 4) { return heroItemDobj.getShots2(); } else if (ladder < 7) { return heroItemDobj.getShots3(); } else if (ladder < 11) { return heroItemDobj.getShots4(); } else { return heroItemDobj.getShots5(); } } // ===========================Begin 获取援军信息================================================== public FightObject loadSuccorFightObject(int rid, int fgidx, FightObject primaryFobj) { if (rid <= 0) { // 机器人 int atk = (int) (primaryFobj.getAtk() * 1.1); int def = (int) (primaryFobj.getDef() * 1.1); int matk = (int) (primaryFobj.getMatk() * 1.1); int mdef = (int) (primaryFobj.getMdef() * 1.1); int hp = (int) (primaryFobj.getHp() * 1.1); int critRate = (int) (primaryFobj.getCritRate() * 1.1); int decritRate = (int) (primaryFobj.getDecritRate() * 1.1); int critMagn = (int) (primaryFobj.getCritMagn() * 1.1); int parryRate = (int) (primaryFobj.getParryRate() * 1.1); int deparryRate = (int) (primaryFobj.getDeparryRate() * 1.1); int parryValue = (int) (primaryFobj.getParryValue() * 1.1); FightObject fo = new FightObject(9, primaryFobj.getLevel(), primaryFobj.getLadder(), primaryFobj.getStar(), (HeroItemDobj) itemProvider.getItem(randomSuccorHeroId())); fo.setBaseAtk(atk); fo.setMaxDef(def); fo.setBaseMatk(matk); fo.setMaxMdef(mdef); fo.setMaxHp(hp); fo.setMaxCritRate(critRate); fo.setMaxDecritRate(decritRate); fo.setMaxCritMagn(critMagn); fo.setMaxParryRate(parryRate); fo.setMaxDeparryRate(deparryRate); fo.setMaxParryValue(parryValue); return fo; } else { IHeroEntity heroEntity; ITroop itroop; HeroItemDobj heroItemDobj; Session session = sessionManager.getSession(rid); if (session != null) { Normal normal = SessionUtils.getPlayer(session).getNormal(); FightGroup fightGroup = normal.getFightGroup(fgidx); heroEntity = (HeroItem) normal.player().getHeroBag().findNode(fightGroup.getSuccor()) .getItem(); itroop = normal; } else { VacantData vacantData = roleProvider.loadVacantData(rid); heroEntity = vacantData.findHeroProperty(vacantData.getPvpSuccorIid()); itroop = vacantData; } heroItemDobj = (HeroItemDobj) itemProvider.getItem(heroEntity.getId()); FightObject fo = new FightObject(9, heroEntity.getLevel(), heroEntity.getLadder(), heroEntity.getStar(), heroItemDobj); int atk = 0; int def = 0; int matk = 0; int mdef = 0; int hp = 0; int critRate = 0; int decritRate = 0; int critMagn = 0; int parryRate = 0; int deparryRate = 0; int parryValue = 0; for (int i = 0; i < ITroop.MAX_TROOP_SIZE; i++) { Troop troop = itroop.getTroop(ITroop.Type.valueOf(i)); atk += troop.getAtk() + troop.getAcePack().getAtk(); def += troop.getDef() + troop.getAcePack().getDef(); matk += troop.getMatk() + troop.getAcePack().getMatk(); mdef += troop.getMdef() + troop.getAcePack().getMdef(); hp += troop.getHp() + troop.getAcePack().getHp(); critRate += troop.getCritRate() + troop.getAcePack().getCritRate(); decritRate += troop.getDecritRate() + troop.getAcePack().getDecritRate(); critMagn += troop.getCritMagn() + troop.getAcePack().getCritMagn(); parryRate += troop.getParryRate() + troop.getAcePack().getParryRate(); deparryRate += troop.getDeparryRate() + troop.getAcePack().getDeparryRate(); parryValue += troop.getParryValue() + troop.getAcePack().getParryValue(); } fo.setBaseAtk(heroProvider.getAtk(heroEntity) + atk / ITroop.MAX_TROOP_SIZE); fo.setMaxDef(heroProvider.getDef(heroEntity) + def / ITroop.MAX_TROOP_SIZE); fo.setBaseMatk(heroProvider.getMatk(heroEntity) + matk / ITroop.MAX_TROOP_SIZE); fo.setMaxMdef(heroProvider.getMdef(heroEntity) + mdef / ITroop.MAX_TROOP_SIZE); fo.setMaxHp(heroProvider.getHp(heroEntity) + hp / ITroop.MAX_TROOP_SIZE); fo.setMaxCritRate(heroProvider.getCritRate(heroEntity) + critRate / ITroop.MAX_TROOP_SIZE / 500); fo.setMaxDecritRate(heroProvider.getDecritRate(heroEntity) + decritRate / ITroop.MAX_TROOP_SIZE / 500); fo.setMaxCritMagn(heroProvider.getCritMagn(heroEntity) + critMagn / ITroop.MAX_TROOP_SIZE / 100); fo.setMaxParryRate(heroProvider.getParryRate(heroEntity) + parryRate / ITroop.MAX_TROOP_SIZE / 500); fo.setMaxDeparryRate(heroProvider.getDeparryRate(heroEntity) + deparryRate / ITroop.MAX_TROOP_SIZE / 600); fo.setMaxParryValue(heroProvider.getParryValue(heroEntity) + parryValue / ITroop.MAX_TROOP_SIZE); return fo; } } // ===========================End 获取援军信息==================================================== //=============================== Begin ======================================================== public int getAtk(Troop troop, IHeroEntity heroEntity) { int atk = heroProvider.getAtk(heroEntity); if (troop != null) { atk += troop.getAtk() + troop.getAcePack().getAtk(); } return (int) atk; } public int getDef(Troop troop, IHeroEntity heroEntity) { int def = heroProvider.getDef(heroEntity); if (troop != null) { def += troop.getDef() + troop.getAcePack().getDef(); } return (int) def; } public int getMatk(Troop troop, IHeroEntity heroEntity) { int matk = heroProvider.getMatk(heroEntity); if (troop != null) { matk += troop.getMatk() + troop.getAcePack().getMatk(); } return (int) matk; } public int getMdef(Troop troop, IHeroEntity heroEntity) { int mdef = heroProvider.getMdef(heroEntity); if (troop != null) { mdef += troop.getMdef() + troop.getAcePack().getMdef(); } return (int) mdef; } public int getHp(Troop troop, IHeroEntity heroEntity) { int hp = heroProvider.getHp(heroEntity); if (troop != null) { hp += troop.getHp() + troop.getAcePack().getHp(); } return hp; } public double getCritRate(Troop troop, IHeroEntity heroEntity) { double critRate = heroProvider.getCritRate(heroEntity); if (troop != null) { critRate += troop.getCritRate() + troop.getAcePack().getCritRate() / 500; } return critRate; } public double getDecritRate(Troop troop, IHeroEntity heroEntity) { double decritRate = heroProvider.getDecritRate(heroEntity); if (troop != null) { decritRate += troop.getDecritRate() + troop.getAcePack().getDecritRate() / 500; } return decritRate; } public double getCritMagn(Troop troop, IHeroEntity heroEntity) { double critMagn = heroProvider.getCritMagn(heroEntity); if (troop != null) { critMagn += troop.getCritMagn() + troop.getAcePack().getCritMagn() / 100; } return critMagn; } public double getParryRate(Troop troop, IHeroEntity heroEntity) { double parryRate = heroProvider.getParryRate(heroEntity); if (troop != null) { parryRate += troop.getParryRate() + troop.getAcePack().getParryRate() / 500; } return parryRate; } public double getDeparryRate(Troop troop, IHeroEntity heroEntity) { double deparryRate = heroProvider.getDeparryRate(heroEntity); if (troop != null) { deparryRate += troop.getDeparryRate() + troop.getAcePack().getDeparryRate() / 600; } return deparryRate; } public double getParryValue(Troop troop, IHeroEntity heroEntity) { double parryValue = heroProvider.getParryValue(heroEntity); if (troop != null) { parryValue += troop.getParryValue(); parryValue *= (1 + troop.getAcePack().getParryValue() / 100); } return parryValue; } //=============================== End ========================================================== /** * 获得怒气所能够增加的伤害. * * @param c 怒气值 * @return 怒气伤害系数 */ public double getFuryFactor(int c) { double r = 1; if (c >= 0 && c <= 10) { r = furyFactors[c]; } return r; } /** * 获得兵种相克因数. * * @param a 攻击方 * @param b 防御方 * @return 相克因数 */ public double getRaceFactor(Race a, Race b) { for (RaceFactorData data : raceFactors) { if (a == data.Name) { switch (b) { case Ce: return data.Ce; case Bu: return data.Bu; case Qi: return data.Qi; case Gong: return data.Gong; case Che: return data.Che; } } } return 1; } /** * 获取兵种与地形的相克因数. * * @param r 兵种 * @param t 地形 * @return 因数 */ public double getTerrainFactor(Race r, Terrain t) { for (TerrainFactorData data : terrainFactors) { if (r == data.Name) { switch (t) { case SLu: return data.SLu; case SLing: return data.SLing; case PYuan: return data.PYuan; case SDi: return data.SDi; case CGuan: return data.CGuan; } } } return 1; } /** * 战斗之前的装备工作. * * @param warInfo */ public void prepare(WarInfo warInfo) { // 释放被动技能 desorbLedaerSkill(warInfo, warInfo.getAttackerEntity()); desorbLedaerSkill(warInfo, warInfo.getDefenderEntity()); } /** * * @param warInfo * @return */ public WarReport finalAttack(WarInfo warInfo) { prepare(warInfo); WarReport warReport = new WarReport(); warReport.setAttackerEntity(newWarReportEntity(warInfo.getAttackerEntity())); warReport.setDefenderEntity(newWarReportEntity(warInfo.getDefenderEntity())); // CACHE warInfo.setWarReport(warReport); WarReport.Round round; WarReport.Effect effect = WarReport.Effect.C; for (;;) { round = new WarReport.Round(); if (warInfo.getNextDire() == Direction.S) { warInfo.setNextDire(Direction.N); effect = attackX(warInfo, Direction.S, round, round.getSdetails(), round.getSbufDetails()); } if (effect == WarReport.Effect.C && warInfo.getNextDire() == Direction.N) { warInfo.setNextDire(Direction.S); effect = attackX(warInfo, Direction.N, round, round.getNdetails(), round.getNbufDetails()); if (effect != WarReport.Effect.C) { effect = (effect == WarReport.Effect.W ? WarReport.Effect.D : WarReport.Effect.W); } } // FIXME 测试数据 round.setSjson(JSON.toJSON(warInfo.getAttackerEntity())); round.setNjson(JSON.toJSON(warInfo.getDefenderEntity())); warReport.addRound(round); // 如果10回合未结束战斗, 算攻击方输 if (warInfo.getRound() >= Typhons.getInteger("typhon.spi.pvp.allRounds", 10)) { effect = WarReport.Effect.D; } warInfo.setRound(warInfo.getRound() + 1); // 战斗结束 if (effect != WarReport.Effect.C) { warReport.setEffect(effect); break; } } return warReport; } public void attack(Shot shot, WarInfo warInfo, FightObject aobj, WarInfo.Entity attackerEntity, WarInfo.Entity defenderEntity, Direction dire, List<Object> outputs) { if (aobj.getStatus() == FightObject.Status.CONFUSION) { List<FightObject> goals = new ArrayList<>(); goals.add(defenderEntity.findFightGoal(true)); outputs.add(_GJi(warInfo, aobj, goals)); return; } switch (shot) { case GJi: { int num = 1; if (aobj.getRace() == Race.Gong) { num = 2; } outputs.add(_GJi(warInfo, aobj, defenderEntity.findFightGoals(num))); break; } case BSa: { Script script = scriptManager.getScript("war.bs." + aobj.getBsaSkill()); MultiAttackResult mar = (MultiAttackResult) script.invoke(null, new BSaWapper(attackerEntity, defenderEntity, aobj, bsaSkills.get(aobj.getBsaSkill()), warInfo)); if (mar != null) { AttackEntry sae = new AttackEntry(); sae.setLab(aobj.getLab()); mar.setSource(sae); mar.setShot(shot); outputs.add(mar); } break; } case FYu: { outputs.add(fyuAttack(warInfo, attackerEntity.getDire(), aobj)); break; } case JCe: { int num = 1; if (aobj.getRace() == Race.Gong) { num = 2; } outputs.add(_JCe(warInfo, aobj, defenderEntity.findFightGoals(num))); break; } case QXi: { FightObject goal = defenderEntity.findFightGoal(); outputs.add(_QXi(warInfo, aobj, goal)); break; } case Q7: { if (aobj.getFury() >= aobj.getMaxFury()) { Script script = scriptManager.getScript("war.bs." + aobj.getBsaSkill()); MultiAttackResult mar = (MultiAttackResult) script.invoke(null, new BSaWapper(attackerEntity, defenderEntity, aobj, bsaSkills.get(aobj.getBsaSkill()), warInfo)); if (mar != null) { AttackEntry sae = new AttackEntry(); sae.setLab(aobj.getLab()); mar.setSource(sae); mar.setShot(Shot.Q7); outputs.add(mar); } } else { aobj.incrementFury(1); aobj.removeAllDebuff(); // result AttackEntry source = new AttackEntry(); source.setLab(aobj.getLab()); AttackResult ar = new AttackResult(); ar.setShot(shot); ar.setSource(source); outputs.add(ar); } break; } case YHu: { // 输出参数 AttackEntry source = new AttackEntry(); source.setLab(aobj.getLab()); int num = 1; if (attackerEntity.getSuccor().getRace() == Race.Gong) { num = 2; } AttackResult ar = _YHu(warInfo, attackerEntity.getSuccor(), defenderEntity.findFightGoals(num)); ar.setSource(source); outputs.add(ar); break; } } } /** * * @param warInfo * @param dire * @param aobj * @return */ public Object fyuAttack(WarInfo warInfo, Direction dire, FightObject aobj) { Script script = scriptManager.getScript("war.BufferSkillScriptFactory"); BufferSkill bufferSkill = (BufferSkill) script.invoke(null, new Object[]{warInfo, dire, aobj, Shot.FYu}); return bufferSkill.onBefore(); } /** * * @param warInfo * @param dire * @param combo * @param bobjs * @param j * @param joinSkill * @return */ public ComboResult skillComboAoeAttack(WarInfo warInfo, Direction dire, WarCombo combo, List<FightObject> bobjs, double j, JoinSkill joinSkill) { double factor = getAttackFactor(); // 攻击系数 double x = calculateSkillComboX(warInfo, combo, false); double f1; double s; double r; double dehp; double _cr = 0; double _cm = 0; for (FightObject fo : combo.getFightObjects()) { _cr += fo.getCritRate(); _cm += fo.getCritMagn(); } _cr /= combo.getFightObjectSize(); _cm /= combo.getFightObjectSize(); ComboResult cr = new ComboResult(); cr.setShot(combo.getShot()); cr.setCount(combo.getComboCount()); double e_m = 1; // 4,5人必杀combo不乘以1.5的系统 if (!"none".equals(joinSkill.getJointArea()) && joinSkill.getAttackerCntNeeded() > 3) { e_m = 1.5; } for (FightObject bobj : bobjs) { f1 = getFuryFactor(bobj.getFury()); // 守方怒气系数 s = 1; // 兵种相克系数 r = 1; // 暴击倍率 dehp = Math.max((factor * (x - (bobj.getDef() + bobj.getMdef()) / 2 * f1) * s * r * j), x / 10); if (LOG.isDebugEnabled()) { LOG.debug("{} = <{} * ({} - {} * {}) * {} * {} * {}> -> <_cr(暴击率): {}, _pr(暴伤): {}, r: {}>", dehp, factor, x, bobj.getDef(), f1, s, r, _cr, _cm, r); } if (!joinSkill.getJointArea().equals(bobj.getArea().name())) { dehp *= e_m; } int hp = (int) dehp; bobj.decrementHp(hp); AttackEntry ae = new AttackEntry(); ae.setLab(bobj.getLab()); ae.setVal(hp); cr.addTarget(ae); } return cr; } /** * * @param fightObjects * @param holdPoints * @return */ public Collection<WarCombo> calculateCombo(List<FightObject> fightObjects, int[] holdPoints) { Shot[][] table = toShotTable(fightObjects, holdPoints); Map<Shot, WarCombo> combos = new HashMap<>(); Shot shot, temp; int x1, y1, x2, y2, x3, y3; for (int i = 0; i < table.length; i++) { Shot[] shots = table[i]; for (int j = 0; j < 3; j++) { // 第一条线 shot = shots[j]; x1 = i; y1 = j; if (i == 0) { x2 = x1 + 1; y2 = y1 + 1; x3 = x2 + 1; y3 = y2 + 1; temp = isCombo(shot, table[x2][y2], table[x3][y3]); if (temp != null) { plusComboPoint(combos, temp, x1, y1, fightObjects.get(y1)); plusComboPoint(combos, temp, x2, y2, fightObjects.get(y2)); plusComboPoint(combos, temp, x3, y3, fightObjects.get(y3)); } } else if (i == 2) { // 第三条线 x2 = x1 - 1; y2 = y1 + 1; x3 = x2 - 1; y3 = y2 + 1; temp = isCombo(shot, table[x2][y2], table[x3][y3]); if (temp != null) { plusComboPoint(combos, temp, x1, y1, fightObjects.get(y1)); plusComboPoint(combos, temp, x2, y2, fightObjects.get(y2)); plusComboPoint(combos, temp, x3, y3, fightObjects.get(y3)); } } // 计算直线 x3 = x2 = x1; y2 = y1 + 1; y3 = y2 + 1; temp = isCombo(shot, table[x2][y2], table[x3][y3]); if (temp != null) { plusComboPoint(combos, temp, x1, y1, fightObjects.get(y1)); plusComboPoint(combos, temp, x2, y2, fightObjects.get(y2)); plusComboPoint(combos, temp, x3, y3, fightObjects.get(y3)); if (temp == Shot.Q7) { if (j == 0) { temp = table[i][3]; if (temp != Shot.Miss && temp != Shot.Q7) { plusComboPoint(combos, temp, x1, y1, fightObjects.get(y1)); plusComboPoint(combos, temp, x2, y2, fightObjects.get(y2)); plusComboPoint(combos, temp, x3, y3, fightObjects.get(y3)); } else if (temp == Shot.Q7) { temp = table[i][4]; if (temp != Shot.Miss && temp != Shot.Q7) { // 1combo plusComboPoint(combos, temp, x1, y1, fightObjects.get(y1)); plusComboPoint(combos, temp, x2, y2, fightObjects.get(y2)); plusComboPoint(combos, temp, x3, y3, fightObjects.get(y3)); } } } else if (j == 1) { // First temp = table[i][0]; if (temp != Shot.Miss && temp != Shot.Q7) { plusComboPoint(combos, temp, i, j, fightObjects.get(j)); plusComboPoint(combos, temp, i, j + 1, fightObjects.get(j + 1)); plusComboPoint(combos, temp, i, j + 2, fightObjects.get(j + 2)); } // Last temp = table[i][4]; if (temp != Shot.Miss && temp != Shot.Q7) { plusComboPoint(combos, temp, i, j + 1, fightObjects.get(y1)); plusComboPoint(combos, temp, i, j + 2, fightObjects.get(y2)); plusComboPoint(combos, temp, i, j + 3, fightObjects.get(y3)); } //====================================================// } else if (j == 2 && table[i][1] != Shot.Miss) { temp = table[i][1]; if (temp == Shot.Q7) { temp = table[i][0]; } if (temp != Shot.Miss && temp != Shot.Q7) { plusComboPoint(combos, temp, i, 2, fightObjects.get(2)); plusComboPoint(combos, temp, i, 3, fightObjects.get(3)); plusComboPoint(combos, temp, i, 4, fightObjects.get(4)); } } } } // 如果为7的连锁 } } if (LOG.isDebugEnabled()) { StringBuilder sb = new StringBuilder(); for (WarCombo combo : combos.values()) { sb.append("\n").append(StringUtils.leftPad(combo.getShot().name(), 4)); sb.append("(") .append(StringUtils.leftPad(String.valueOf(combo.getComboCount()), 2)) .append(")"); sb.append(": {"); for (Point point : combo.getPoints()) { sb.append(StringUtils.leftPad(table[point.getX()][point.getY()].name(), 4)); sb.append("[").append(point.getX()).append(", ").append(point.getY()) .append("] "); } sb.deleteCharAt(sb.length() - 1); sb.append("}"); } LOG.debug(sb.toString()); } // 按照攻击要求排序 List<WarCombo> warCombos = new ArrayList<>(combos.values()); Collections.sort(warCombos); return warCombos; } /** * * @param s1 * @param s2 * @param s3 * @return */ protected Shot isCombo(IFightItem.Shot s1, IFightItem.Shot s2, IFightItem.Shot s3) { IFightItem.Shot rs = s1.equals(s2); if (rs != null) { return rs.equals(s3); } return null; } /** * * @param fo * @param p * @return */ protected Shot getPrevShot(FightObject fo, int p) { return getShot(fo, p - 1); } /** * * @param fo * @param p * @return */ protected Shot getNextShot(FightObject fo, int p) { return getShot(fo, p + 1); } /** * * @param fo * @param p * @return */ protected Shot getShot(FightObject fo, int p) { Shot[] shots = fo.getShots(); if (p < 0) { return shots[shots.length + p]; } else if (p >= shots.length) { return shots[p - shots.length]; } return shots[p]; } /** * * @param critRate * @param decritRate * @param critMagn * @return */ public double getCritMagn(double critRate, double decritRate, double critMagn) { if (getCritRate() <= critRate - decritRate) { return critMagn; } return 1D; } /** * * @param afo * @param bfo * @return */ protected double getCritMagn(FightObject afo, FightObject bfo) { // 减去对方的韧性 if (getCritRate() <= afo.getCritRate() - bfo.getDecritRate()) { return afo.getCritMagn(); } return 1F; } /** * * @param parryRate * @param deparryRate * @param parryValue * @return */ public double getParryValue(double parryRate, double deparryRate, double parryValue) { if (getCritRate() <= parryRate - deparryRate) { return parryValue; } return 0D; } /** * * @param afo * @param bfo * @return */ protected double getParryValue(FightObject afo, FightObject bfo) { // 减去对方的抗性 if (getCritRate() <= afo.getParryRate() - bfo.getDeparryRate()) { return afo.getParryValue(); } return 0F; } /** * * @param terrain * @param afo * @param bfo * @param atk * @param def * @param j * @return */ public int attack1(Terrain terrain, FightObject afo, FightObject bfo, int atk, int def, double j) { double factor = getAttackFactor(); // 攻击系数 double p1 = getTerrainFactor(afo.getRace(), terrain); // 地形相克系数 double f = getFuryFactor(afo.getFury()); // 攻方怒气系数 double f1 = getFuryFactor(bfo.getFury()); // 守方怒气系数 double r = getCritMagn(afo, bfo); // 暴击倍率 double g1 = getParryValue(bfo, afo); // 格挡伤害 double dehp = factor * (atk * p1 * f - def * f1) * r * j * Typhons.getDouble("typhon.spi.pvp.damageMagn", 1) - g1; int a = (int) (Math.max(dehp, atk / 10) - g1); int hp = Math.max(a, 1); if (LOG.isDebugEnabled()) { LOG.debug("a:{}->b:{} - {}={} * ({} * {} * {} - {} * {}) * {} -> {}", afo.getHeroId(), bfo.getHeroId(), hp, factor, atk, p1, f, def, f1, r, j, g1); } return hp; } /** * 对防守方造成攻击伤害,并返回详细信息. * * @param terrain 地形 * @param afo 攻击方 * @param bfo 防守方 * @param atk 攻击力 * @param def 防御力 * @param j 额外系数 * @return 造成伤害的详细信息 */ public AttackEntry attack0(Terrain terrain, FightObject afo, FightObject bfo, int atk, int def, double j) { double p1 = getTerrainFactor(afo.getRace(), terrain); // 地形相克系数 double f = getFuryFactor(afo.getFury()); // 攻方怒气系数 double f1 = getFuryFactor(bfo.getFury()); // 守方怒气系数 double r = getCritMagn(afo, bfo); // 暴击倍率 double g1 = getParryValue(bfo, afo); // 格挡伤害 AttackEntry ae = attack0(atk, def, p1, f, f1, r, j, g1); ae.setLab(bfo.getLab()); return ae; } /** * 计算攻击造成伤害. 返回攻击血量, 暴击, 格挡信息. * * @param atk 攻击力 * @param def 防御力 * @param p1 地形相克系数 * @param f 攻方怒气系数 * @param f1 守方怒气系数 * @param r 暴击倍率 * @param j 攻击额外系数 * @param g1 格挡伤害 * @return 返回攻击血量, 暴击, 格挡信息 */ public AttackEntry attack0(int atk, int def, double p1, double f, double f1, double r, double j, double g1) { double factor = getAttackFactor(); // 攻击系数 double dehp = factor * (atk * p1 * f - def * f1) * r * j * Typhons.getDouble("typhon.spi.pvp.damageMagn", 1); int a = (int) (Math.max(dehp, atk / 10) - g1); int hp = Math.max(a, 1); if (LOG.isDebugEnabled()) { LOG.debug("{}={} * ({} * {} * {} - {} * {}) * {} * {} -> {}", hp, factor, atk, p1, f, def, f1, r, j, g1); } AttackEntry ae = new AttackEntry(); ae.setVal(hp); ae.crited(r); ae.parried(g1); return ae; } private AttackResult _GJi(WarInfo warInfo, FightObject aobj, List<FightObject> goals) { // 输出参数 AttackEntry source = new AttackEntry(); source.setLab(aobj.getLab()); AttackResult ar = new AttackResult(); int atk = aobj.getAtk(); if (aobj.getStatus() == FightObject.Status.CONFUSION) { atk = Math.max(aobj.getAtk(), aobj.getMatk()); } for (FightObject goal : goals) { AttackEntry ae = attack0(warInfo.getTerrain(), aobj, goal, atk, goal.getDef(), 1); goal.decrementHp((int) ae.getVal()); ae.setLab(goal.getLab()); ar.setShot(Shot.GJi); ar.setSource(source); ar.addTarget(ae); } return ar; } private AttackResult _JCe(WarInfo warInfo, FightObject aobj, List<FightObject> goals) { // 输出参数 AttackEntry source = new AttackEntry(); source.setLab(aobj.getLab()); AttackResult ar = new AttackResult(); for (FightObject goal : goals) { AttackEntry ae = attack0(warInfo.getTerrain(), aobj, goal, aobj.getMatk(), goal.getMdef(), 1); goal.decrementHp((int) ae.getVal()); ae.setLab(goal.getLab()); ar.setShot(Shot.JCe); ar.setSource(source); ar.addTarget(ae); } return ar; } private AttackResult _QXi(WarInfo warInfo, FightObject aobj, FightObject goal) { double j = 0.6; // 如果对方怒气为0则系数乘2 if (goal.getFury() <= 0) { j *= 2; } int atk; int def; if (aobj.getAtk() > aobj.getMatk()) { atk = aobj.getAtk(); def = goal.getDef(); } else { atk = aobj.getMatk(); def = goal.getMdef(); } AttackEntry ae = attack0(warInfo.getTerrain(), aobj, goal, atk, def, j); goal.decrementHp((int) ae.getVal()); goal.decrementFury(1); ae.setLab(goal.getLab()); // 输出参数 AttackEntry source = new AttackEntry(); source.setLab(aobj.getLab()); AttackResult ar = new AttackResult(); ar.setShot(Shot.QXi); ar.setSource(source); ar.addTarget(ae); return ar; } private AttackResult _YHu(WarInfo warInfo, FightObject aobj, List<FightObject> goals) { AttackResult ar = new AttackResult(); ar.setShot(Shot.YHu); int atk; int def; for (FightObject goal : goals) { if (aobj.getAtk() > aobj.getMatk()) { atk = aobj.getAtk(); def = goal.getDef(); } else { atk = aobj.getMatk(); def = goal.getMdef(); } AttackEntry ae = attack0(warInfo.getTerrain(), aobj, goal, atk, def, 1); goal.decrementHp((int) ae.getVal()); ae.setLab(goal.getLab()); ar.addTarget(ae); } return ar; } // private //======================== Begin =============================================================== private void desorbLedaerSkill(WarInfo warInfo, WarInfo.Entity entity) { FightObject fo = entity.getFightObject(entity.getCaptain()); if (fo.getLadderSkill() != null) { Script script = scriptManager.getScript(("war.cs." + fo.getLadderSkill()).intern()); // 释放自己的队长技能 List<FightObject> list = new ArrayList<>(entity.getFightObjects()); list.add(entity.getSuccor()); script.invoke(null, list); // 释放好友的队长技能 script = scriptManager.getScript("war.cs." + entity.getSuccor().getLadderSkill().intern()); script.invoke(null, list); } } private WarReport.Effect attackX(WarInfo warInfo, Direction dire, WarReport.Round round, List<Object> details, List<Object> bufDetails) { int[] holdPoints = randomHoldPoints(); // 拉霸停止点 switch (dire) { case N: round.setNholdPoints(holdPoints); break; case S: round.setSholdPoints(holdPoints); break; } return attack(holdPoints, warInfo, dire, details, bufDetails); } public WarReport.Effect attack(int[] holdPoints, WarInfo warInfo, Direction dire, List<Object> details, List<Object> bufDetails) { WarInfo.Entity attackerEntity; WarInfo.Entity defenderEntity; switch (dire) { case S: attackerEntity = warInfo.getAttackerEntity(); defenderEntity = warInfo.getDefenderEntity(); break; default: attackerEntity = warInfo.getDefenderEntity(); defenderEntity = warInfo.getAttackerEntity(); } // 增加出手次数 attackerEntity.incrementAtkCount(); // 执行BufferSkill Object bufferSkillRs; for (FightObject fo : attackerEntity.getFightObjects()) { if (!fo.isDead() && fo.getBufferSkills().size() > 0) { for (Object bs : fo.getBufferSkills().toArray()) { bufferSkillRs = ((BufferSkill) bs).onAfter(); if (bufferSkillRs != null) { bufDetails.add(bufferSkillRs); } } } } // BUFFER if (attackerEntity.isOver()) { return WarReport.Effect.D; } Collection<WarCombo> combos; FightObject source; FightObject goal; for (int i = 0; i < holdPoints.length; i++) { source = attackerEntity.getFightObject(i); if (source.isDead() || source.getStatus() == FightObject.Status.SLEEPING) { continue; } attack(source.getShot(holdPoints[i]), warInfo, source, attackerEntity, defenderEntity, dire, details); if (attackerEntity.isOver()) { return WarReport.Effect.D; } if (defenderEntity.isOver()) { return WarReport.Effect.W; } } combos = calculateCombo(attackerEntity.getFightObjects(), holdPoints); for (WarCombo warCombo : combos) { switch (warCombo.getShot()) { case GJi: { double j = combosRatioFactors.get(warCombo.getComboCount() - 1).get( warCombo.getShot()); goal = defenderEntity.findFightGoal(); AttackEntry ae = new AttackEntry(); ae.setLab(goal.getLab()); int sumHp = 0; for (FightObject fobj : warCombo.getFightObjects()) { sumHp += attack1(warInfo.getTerrain(), fobj, goal, fobj.getAtk(), goal.getDef(), 1); } int hp = (int) (sumHp * j); goal.decrementHp(hp); ae.setVal(hp); // result ComboResult cr = new ComboResult(); cr.setCount(warCombo.getComboCount()); cr.setShot(Shot.GJi); cr.addTarget(ae); details.add(cr); break; } case FYu: { ComboResult cr = new ComboResult(); cr.setCount(warCombo.getComboCount()); cr.setShot(Shot.FYu); double j = combosRatioFactors.get(warCombo.getComboCount() - 1).get( warCombo.getShot()); int hp; for (FightObject fo : attackerEntity.getFightObjects()) { if (fo.isDead()) { continue; } hp = (int) (fo.getMaxHp() * j); fo.incrementHp(hp); AttackEntry ae = new AttackEntry(); ae.setLab(fo.getLab()); ae.setVal(hp); cr.addTarget(ae); } details.add(cr); break; } case JCe: { double j = combosRatioFactors.get(warCombo.getComboCount() - 1).get( warCombo.getShot()); goal = defenderEntity.findFightGoal(); AttackEntry ae = new AttackEntry(); ae.setLab(goal.getLab()); int sumHp = 0; for (FightObject fobj : warCombo.getFightObjects()) { sumHp += attack1(warInfo.getTerrain(), fobj, goal, fobj.getMatk(), goal.getMdef(), 1); } int hp = (int) (sumHp * j); goal.decrementHp(hp); ae.setVal(hp); ComboResult cr = new ComboResult(); cr.setCount(warCombo.getComboCount()); cr.setShot(warCombo.getShot()); cr.addTarget(ae); details.add(cr); break; } case QXi: { double j = combosRatioFactors.get(warCombo.getComboCount() - 1).get( warCombo.getShot()); goal = defenderEntity.findFightGoal(); AttackEntry ae = new AttackEntry(); ae.setLab(goal.getLab()); int atk; int def; int sumHp = 0; for (FightObject fobj : warCombo.getFightObjects()) { if (fobj.getAtk() > fobj.getMatk()) { atk = fobj.getAtk(); def = goal.getDef(); } else { atk = fobj.getMatk(); def = goal.getMdef(); } sumHp += attack1(warInfo.getTerrain(), fobj, goal, atk, def, 1); } int hp = (int) (sumHp * j); goal.decrementHp(hp); goal.decrementFury(1); ae.setVal(hp); // result ComboResult cr = new ComboResult(); cr.setCount(warCombo.getComboCount()); cr.setShot(Shot.QXi); cr.addTarget(ae); details.add(cr); break; } case BSa: { double j = combosRatioFactors.get(warCombo.getComboCount() - 1).get( warCombo.getShot()); JoinSkill js = joinSkills.get(warCombo.getFightObjectSize()).get( warCombo.getAreaString()); ComboResult cr = skillComboAoeAttack(warInfo, dire, warCombo, defenderEntity.findFightGoals(js.getNumOfTargets()), js.getFactor() * j, js); if (!"none".equals(js.getJointArea()) && js.getAttackerCntNeeded() >= 4) { for (FightObject fo : attackerEntity.getFightObjects()) { if (fo.isDead()) { continue; } if (js.getAttackerCntNeeded() == 4) { new Shu4SkillBuffer(warInfo, dire, fo).onBefore(); } else if (js.getAttackerCntNeeded() == 5) { new Shu5SkillBuffer(warInfo, dire, fo).onBefore(); } } } details.add(cr); break; } case YHu: { double j = combosRatioFactors.get(warCombo.getComboCount() - 1).get( warCombo.getShot()); FightObject succor = attackerEntity.getSuccor(); Script script = scriptManager.getScript("war.bs." + succor.getBsaSkill()); ComboResult cr = new ComboResult(); cr.setCount(warCombo.getComboCount()); cr.setShot(Shot.YHu); MultiAttackResult mar = (MultiAttackResult) script.invoke(null, new BSaWapper(attackerEntity, defenderEntity, succor, bsaSkills.get(succor.getBsaSkill()), warInfo, j)); if (mar != null) { cr.setTargets(mar.getTargets()); } details.add(cr); break; } case Q7: { if (warCombo.getComboCount() <= 1) { for (FightObject fo : attackerEntity.getFightObjects()) { fo.incrementFury(1); } } else { // 变怒 scriptManager.getScript("war.Q7ComboScript").invoke(null, new Q7ComboWapper(warInfo, attackerEntity, warCombo)); } ComboResult cr = new ComboResult(); cr.setCount(warCombo.getComboCount()); cr.setShot(Shot.Q7); details.add(cr); break; } } if (attackerEntity.isOver()) { return WarReport.Effect.D; } if (defenderEntity.isOver()) { return WarReport.Effect.W; } } return WarReport.Effect.C; } /** * * @param we * @return */ public WarReport.Entity newWarReportEntity(WarInfo.Entity we) { WarReport.Entity rs = new WarReport.Entity(); rs.setRoleName(we.getRoleName()); rs.setLevel(we.getLevel()); rs.setPowerGuess(we.getPowerGuess()); rs.setSuccorIid(we.getSuccor().getHeroId()); // FIXME Test rs.setSuccorAtk(we.getSuccor().getAtk()); rs.setSuccorFury(we.getSuccor().getFury()); List<JSONObject> heros = new ArrayList<>(we.getFightObjects().size()); for (FightObject fo : we.getFightObjects()) { JSONObject json = new JSONObject(); json.put(HeroPropertyKeys.ID, fo.getHeroId()); json.put(HeroPropertyKeys.LADDER, fo.getLadder()); json.put(HeroPropertyKeys.STAR, fo.getStar()); json.put(HeroPropertyKeys.LEVEL, fo.getLevel()); json.put(HeroPropertyKeys.HP, fo.getMaxHp()); json.put(HeroPropertyKeys.FURY, fo.getFury()); // FIXME Test Data json.put(HeroPropertyKeys.ATK, fo.getAtk()); json.put(HeroPropertyKeys.DEF, fo.getDef()); json.put(HeroPropertyKeys.MATK, fo.getMatk()); json.put(HeroPropertyKeys.MDEF, fo.getMdef()); json.put(HeroPropertyKeys.CRIT_RATE, MathUtils.round(fo.getCritRate(), 3)); json.put(HeroPropertyKeys.DECRIT_RATE, MathUtils.round(fo.getDecritRate(), 3)); json.put(HeroPropertyKeys.CRIT_MAGN, MathUtils.round(fo.getCritMagn(), 3)); json.put(HeroPropertyKeys.PARRY_RATE, MathUtils.round(fo.getParryRate(), 3)); json.put(HeroPropertyKeys.DEPARRY_RATE, MathUtils.round(fo.getDeparryRate(), 3)); json.put(HeroPropertyKeys.PARRY_VALUE, MathUtils.round(fo.getParryValue(), 3)); heros.add(json); } rs.setHeros(heros); return rs; } /** * * @return */ public String randomSuccorHeroId() { String[] ids = Typhons.getProperty("typhon.spi.pve.buildHeroIds").split(","); int i = HERO_ID_RANDOM.nextInt(ids.length); return ids[i]; } private PacketSuccor newPacketSuccor(int rid, VacantData vacantData) { Session otherSession = sessionManager.getSession(rid); PacketSuccor succor; int societyId; if (otherSession != null) { Normal otherNormal = SessionUtils.getPlayer(otherSession).getNormal(); FightGroup fightGroup = otherNormal.getFightGroup(otherNormal.getLastFidx()); HeroItem primaryHero = fightGroup.getHeroItem(fightGroup.getCaptain()); succor = new PacketSuccor(); succor.setRid(otherNormal.player().getRole().getRid()); succor.setName(otherNormal.player().getRole().getName()); succor.setPlayerLevel(otherNormal.getLevel()); succor.setIid(primaryHero.getId()); succor.setLevel(primaryHero.getLevel()); succor.setStar(primaryHero.getStar().name()); succor.setPowerGuess(primaryHero.getPowerGuess()); succor.setLadder(primaryHero.getLadder()); succor.setAvatar(otherNormal.getAvatar()); succor.setAvatarBorder(otherNormal.getAvatarBorder()); societyId = otherNormal.getSocietyId(); } else { if (vacantData == null) { vacantData = roleProvider.loadVacantData(rid); } succor = new PacketSuccor(); succor.setRid(vacantData.getRid()); succor.setName(vacantData.getName()); succor.setIid(vacantData.getPrimaryHero().getId()); succor.setPlayerLevel(vacantData.getLevel()); succor.setStar(vacantData.getPrimaryHero().getStar().name()); succor.setPowerGuess(vacantData.getPrimaryHero().getPowerGuess()); succor.setLevel(vacantData.getPrimaryHero().getLevel()); succor.setLadder(vacantData.getPrimaryHero().getLadder()); succor.setAvatar(vacantData.getAvatar()); succor.setAvatarBorder(vacantData.getAvatarBorder()); societyId = vacantData.getSocietyId(); } Society society = societyProvider.findBySid(societyId); if (society != null) { succor.setSocietyName(society.getName()); } return succor; } /** * * @return */ private int[] randomHoldPoints() { int[] points = {HOLD_POINT_RANDOM.nextInt(14), HOLD_POINT_RANDOM.nextInt(14), HOLD_POINT_RANDOM.nextInt(14), HOLD_POINT_RANDOM.nextInt(14), HOLD_POINT_RANDOM.nextInt(14)}; return points; } //======================== End ================================================================= private double calculateSkillComboX(WarInfo warInfo, WarCombo combo, boolean b) { double sum = 0; FightObject fo; double atk; double f; double p1; StringBuilder sb = null; if (LOG.isDebugEnabled()) { sb = new StringBuilder("("); } for (Point point : combo.getPoints()) { fo = point.getFightObject(); atk = Math.max(fo.getAtk(), fo.getMatk()); f = getFuryFactor(fo.getFury()); // 地形相克系数 if (b) { p1 = getTerrainFactor(fo.getRace(), warInfo.getTerrain()); } else { p1 = 1; } sum += atk * p1 * f; if (LOG.isDebugEnabled()) { sb.append("(").append(fo.getHeroId()).append(": "); sb.append(atk).append(" * ").append(p1).append(" * "); sb.append(f).append(") + "); } } double res = sum / combo.getPoints().size(); if (LOG.isDebugEnabled()) { sb.deleteCharAt(sb.length() - 1).deleteCharAt(sb.length() - 1); sb.append(")"); LOG.debug("{} = {} / {}", res, sum, combo.getPoints().size()); } return res; } private void plusComboPoint(Map<Shot, WarCombo> combos, Shot shot, int x, int y, FightObject fo) { WarCombo warCombo = combos.get(shot); if (warCombo == null) { warCombo = new WarCombo(shot); combos.put(shot, warCombo); } warCombo.addPoint(new WarCombo.Point(x, y, fo)); } private Shot[][] toShotTable(List<FightObject> fightObjects, int[] holdPoints) { Shot[][] table = new Shot[3][5]; for (int i = 0; i < fightObjects.size(); i++) { FightObject fightObject = fightObjects.get(i); if (!fightObject.isAvailable()) { table[ROW_1ST][i] = IFightItem.Shot.None; table[ROW_2ND][i] = IFightItem.Shot.None; table[ROW_3RD][i] = IFightItem.Shot.None; } else { table[ROW_1ST][i] = getNextShot(fightObject, holdPoints[i]); table[ROW_2ND][i] = getShot(fightObject, holdPoints[i]); table[ROW_3RD][i] = getPrevShot(fightObject, holdPoints[i]); } } if (LOG.isDebugEnabled()) { StringBuilder sb = new StringBuilder(); sb.append("\n++++++++++++++++++++++++++++++++++++"); for (Shot[] shots : table) { sb.append("\n+"); for (Shot shot : shots) { sb.append(org.apache.commons.lang3.StringUtils.center(shot.name(), 6)).append( "+"); } sb.append("\n++++++++++++++++++++++++++++++++++++"); } LOG.debug(sb.toString()); } return table; } //=======================================加载配置数据=================================================== private void loadTerrainWarFactor() { JSONArray array = JSON.parseArray(ComponentUtils.readDataFile("terrain_war_factor.json")); TerrainFactorData[] factors = new TerrainFactorData[array.size()]; for (int i = 0; i < factors.length; i++) { factors[i] = new TerrainFactorData(array.getJSONObject(i)); } terrainFactors = factors; } private void loadRaceWarFactor() { JSONArray array = JSON.parseArray(ComponentUtils.readDataFile("race_war_factor.json")); RaceFactorData[] factors = new RaceFactorData[array.size()]; for (int i = 0; i < factors.length; i++) { factors[i] = new RaceFactorData(array.getJSONObject(i)); } raceFactors = factors; } private void loadFuryWarFactor() { JSONArray array = JSON.parseArray(ComponentUtils.readDataFile("fury_war_factor.json")); double[] factors = new double[array.size()]; for (int i = 0; i < factors.length; i++) { factors[i] = array.getJSONObject(i).getDouble("v"); } furyFactors = factors; } private void loadCombosRatioFactor() { JSONArray array = JSON.parseArray(ComponentUtils.readDataFile("client/combos_ratio.json")); for (int i = 0; i < array.size(); i++) { JSONObject json = array.getJSONObject(i); Map<Shot, Double> factors = new HashMap<>(json.size()); for (String k : json.keySet()) { factors.put(Shot.valueOf(k), json.getDoubleValue(k)); } combosRatioFactors.add(factors); } } private void loadBSaSkillConfig() { List<BSaSkill> list = JSON.parseArray(ComponentUtils.readDataFile("BSa_skill.json"), BSaSkill.class); for (BSaSkill bs : list) { bsaSkills.put(bs.getId(), bs); } } private void loadJoinSkillConfig() { List<JoinSkill> list = JSON.parseArray(ComponentUtils.readDataFile("Joint_skill.json"), JoinSkill.class); for (JoinSkill js : list) { Map<String, JoinSkill> map = joinSkills.get(js.getAttackerCntNeeded()); if (map == null) { map = new HashMap<>(3); joinSkills.put(js.getAttackerCntNeeded(), map); } map.put(js.getJointArea(), js); } } //======================战斗系数================================================================== private double getAttackFactor() { return (MIN_FACTOR + FACTOR_RANDOM.nextInt(11) / 100D); } private double getCritRate() { return (FACTOR_RANDOM.nextInt(101) / 100D); } private String randomName(List<PacketSuccor> vals) { String name; f1: for (;;) { name = roleProvider.randomName(); for (PacketSuccor ps : vals) { if (name.equals(ps.getName())) { continue f1; } } return name; } } private JSONObject buildSuccorData(HeroItem hero) { JSONObject json = new JSONObject(); double p = Typhons.getDouble("typhon.spi.war.succorMagn"); json.put("extraTong", hero.getExtraTong() * p); json.put("extraWu", hero.getExtraWu() * p); json.put("extraZhi", hero.getExtraZhi() * p); json.put("extraAtk", hero.getExtraAtk() * p); json.put("extraDef", hero.getExtraDef() * p); json.put("extraMatk", hero.getExtraMatk() * p); json.put("extraMdef", hero.getExtraMdef() * p); json.put("extraHp", hero.getExtraHp() * p); json.put("extraCritRate", hero.getExtraCritRate() * p); json.put("extraDecritRate", hero.getExtraDecritRate() * p); json.put("extraCritMagn", hero.getExtraCritMagn() * p); json.put("extraParryRate", hero.getExtraParryRate() * p); json.put("extraParryValue", hero.getExtraParryValue() * p); json.put("extraDeparryRate", hero.getExtraDeparryRate() * p); json.put("star", hero.getStar()); json.put("level", hero.getLevel()); return json; } private class RaceFactorData { Race Name; double Ce; double Bu; double Qi; double Gong; double Che; RaceFactorData(JSONObject obj) { Name = Race.valueOf(obj.getString("Name")); Ce = obj.getDouble("Ce"); Bu = obj.getDouble("Bu"); Qi = obj.getDouble("Qi"); Gong = obj.getDouble("Gong"); Che = obj.getDouble("Che"); } } private class TerrainFactorData { Race Name; double SLu; double SLing; double PYuan; double SDi; double CGuan; TerrainFactorData(JSONObject obj) { Name = Race.valueOf(obj.getString("Name")); SLu = obj.getDouble("SLu"); SLing = obj.getDouble("SLing"); PYuan = obj.getDouble("PYuan"); SDi = obj.getDouble("SDi"); CGuan = obj.getDouble("CGuan"); } } }