以前开发的游戏活动,在普通的游戏活动上添加了跨服玩法,需要用到世界服务器中转,提供思路给大家参考
简单介绍就是以帮会为组织的攻城类玩法,首先对服务器进行分组,每组的服务器玩家共同开采矿产,互相争夺矿产主权
public class MineGamer {
/**
* 跨服国战分组id
*/
private int groupId;
/**
* 区服标志
*/
private int serverType;
/**
* 服务器ID
*/
private int serverId;
/**
* 源服务器ID
*/
private int sourceId;
/**
* 玩家ID
*/
private long gamerId;
/**
* 工会ID
*/
private long armyId;
/**
* 昵称
*/
private String nickName;
/**
* 头像
*/
private String avatar;
/**
* 战力
*/
private long power;
/**
* 等级
*/
private int level;
玩家实体类,主要是服务器和展示信息。
public class WorldMineSimpleDto {
/**
* 矿ID
*/
private int mineId;
/**
* 矿区
*/
private int page;
/**
* 矿类型
*/
private int type;
/**
* 矿级别
*/
private int level;
/**
* 天降宝箱状态
*/
private int boxActive;
/**
* 天降宝箱id
*/
private int exboxId;
/**
* 占领时间 小于10min为保护状态
*/
private long occupeTime;
/**
* 预计占领结束时间
*/
private long occupeEndTime;
/**
* 领取宝箱状态
*/
private List<Integer> boxReward;
/**
* 玩家信息
*/
private MineGamer mineGamer;
矿产实体类,为矿产分区占领等信息,其余类怪物npc,活动状态及时间,玩家占领等信息都比较少。
跨服功能的主要重心都在世界服,主要处理和保存活动信息
活动分组管理:初始读取夺矿战分组配置表
public class CrossMineGroupService extends ConfigServiceAdapter {
private static Map<Integer, SeizeMineGroupServerConfig> CONFIG_MAPS = new HashMap<>();
@Override
public void clear() {
CONFIG_MAPS.clear();
}
@Override
public void initialize() {
Collection<SeizeMineGroupServerConfig> list = dataConfig.listAll(this, SeizeMineGroupServerConfig.class);
for (SeizeMineGroupServerConfig cfg : list) {
CONFIG_MAPS.put(cfg.getId(), cfg);
}
}
public static SeizeMineGroupServerConfig get(int id) {
return CONFIG_MAPS.get(id);
}
public static SeizeMineGroupServerConfig get(int serverId, int serverType) {
Collection<SeizeMineGroupServerConfig> groupServerConfigList = getCrossBattleGroupServerList();
for (SeizeMineGroupServerConfig groupServerConfig : groupServerConfigList) {
Set<ServerStruct> serverStructs = groupServerConfig.getServerStructs();
for (ServerStruct serverStruct : serverStructs) {
if (serverStruct.getServerId() == serverId && serverStruct.getServerType() == serverType) {
return groupServerConfig;
}
}
}
return null;
}
/**
* 服务器简单结构
* @author CharonWang
*
*/
public class ServerStruct {
/**
* 服务器类型
*/
private int serverType;
/**
* 服务器ID
*/
private int serverId;
public static ServerStruct valueOf(int serverType, int serverId) {
ServerStruct model = new ServerStruct();
model.serverType = serverType;
model.serverId = serverId;
return model;
}
//矿产分组表
@DataFile(fileName = "seize_mine_groups_server_config")
public class SeizeMineGroupServerConfig implements ModelAdapter {
/**
* 组ID
*/
private int id;
/**
* 服务器列表
*/
private String servers;
/**
* 组名称
*/
private String name;
@FieldIgnore
private Set<ServerStruct> serverStructs = new HashSet<>();
@Override
public void initialize() {
List<String> serverList = JSONObject.parseArray(servers, String.class);
for (String server : serverList) {
String[] strArray = server.split("-");
serverStructs.add(ServerStruct.valueOf(Integer.valueOf(strArray[0]), Integer.valueOf(strArray[1])));
}
}
活动时间管理
/**
* 跨服夺矿战信息
* @author aurora
*
*/
public class MineEntity extends RedisEntity {
/**
* 状态
*/
private int state;
/**
* 状态结束时间
*/
private long stateEndTime;
根据配置的活动时间,定时器控制活动状态,具体方法代码如下,战斗功能不是写我的也比较长最后再贴,其余的就是基本的增删改查
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
mineEntity = mineDao.get();
if (mineEntity.getState() == 0) {
mineEntity.setStateEndTime(System.currentTimeMillis());
mineEntity.setState(MineState.PREPARE.getId());
mineDao.update(mineEntity);
}
mineWorldDao.initMineWorld(mineEntity.getState());
schedule.addEverySecond(new Runnable() {
@Override
public void run() {
processMineState();
}
}, 5);
}
// 跨服夺矿战战状态处理
@SuppressWarnings("incomplete-switch")
private void processMineState() {
MineState state = MineState.getState(mineEntity.getState());
if (state != MineState.PREPARE) {
isfreshMine();
}
if (System.currentTimeMillis() < mineEntity.getStateEndTime()) {
return;
}
switch (state) {
case MESSPLAY:
if (System.currentTimeMillis() < mineEntity.getStateEndTime()) {
return;
}
// 发送宝箱倒计时
processMineBox();
// 更新时间,延长30min
mineEntity.setStateEndTime(mineEntity.getStateEndTime() + 30 * 60 * 1000);
mineEntity.setState(MineState.SENDREWARD.getId());
mineDao.update(mineEntity);
break;
case SENDREWARD:
if (System.currentTimeMillis() < mineEntity.getStateEndTime()) {
return;
}
// 发送邮件宝箱
sendMineBoxReward();
// 更新发宝箱的时间
mineEntity.setStateEndTime(getBoxTime());
mineEntity.setState(WarState.MESSPLAY.getId());
mineDao.update(mineEntity);
break;
case PREPARE:
clean();
initMine();
// 初始化发宝箱时间
mineEntity.setStateEndTime(getBoxTime());
mineEntity.setState(MineState.MESSPLAY.getId());
mineDao.update(mineEntity);
break;
}
}
private void isfreshMine() {
Collection<Integer> allGroupIds = CrossMineGroupService.allGroupIds();
for (Integer groupId : allGroupIds) {
List<MineWorldPlayerEntity> mineList = mineWorldDao.getMineList(groupId);
for (MineWorldPlayerEntity mineWorld : mineList) {
if (mineWorld == null) {
LOGGER.error("mineWorld can't find groupId:{}", groupId);
continue;
}
// 判断是否为有主高级矿 占领时间已过
if (mineWorld != null && mineWorld.getOccuperId() != 0) {
if (System.currentTimeMillis() >= mineWorld.getOccupeEndTime()) {
boolean settleReward = settleReward(mineWorld, 1);
if (settleReward) {
mineWorld.initi();
mineWorldDao.update(mineWorld);
}
}
}
}
}
}
private long getBoxTime() {
long boxtime1 = TimeUtils.getTodayFixTime(12);
long boxtime2 = TimeUtils.getTodayFixTime(21);
long timeMillis = System.currentTimeMillis();
if (timeMillis <= boxtime1) {
timeMillis = boxtime1;
} else if (timeMillis > boxtime1 && timeMillis <= boxtime2) {
timeMillis = boxtime2;
} else {
// 设置为第二天12点
timeMillis = boxtime1 + 24 * 60 * 60 * 1000;
}
return timeMillis;
}
// 跨服国夺矿战宝箱发送倒计时
private void processMineBox() {
Collection<Integer> allGroupIds = CrossMineGroupService.allGroupIds();
for (Integer groupId : allGroupIds) {
List<MineWorldPlayerEntity> mineList = mineWorldDao.getMineList(groupId);
for (MineWorldPlayerEntity mineWorld : mineList) {
if (mineWorld == null) {
LOGGER.error("mineWorld can't find groupId:{}", groupId);
continue;
}
SeizeMineConfig mineConfig = MineWorldService.getMineConfig(mineWorld.getMineId());
// 判断是否为有主高级矿 是激活&& mineConfig.getMineType() == 2
if (mineWorld.getOccuperId() != 0) {
if (!mineConfig.getExBox().isEmpty() && mineConfig.getExBoxId() > 0) {
mineWorld.setBoxActive(1);
mineWorld.setExboxId(mineConfig.getExBoxId());
mineWorldDao.update(mineWorld);
}
}
}
}
}
// 跨服国夺矿战宝箱处理
private void sendMineBoxReward() {
Collection<Integer> allGroupIds = CrossMineGroupService.allGroupIds();
for (Integer groupId : allGroupIds) {
List<MineWorldPlayerEntity> mineList = mineWorldDao.getMineList(groupId);
for (MineWorldPlayerEntity mineWorld : mineList) {
if (mineWorld == null) {
LOGGER.error("mineWorld can't find groupId:{}", groupId);
continue;
}
// 判断是否为已激活有主矿
if (mineWorld.getBoxActive() == 1) {
// 发放奖励
int exboxId = mineWorld.getExboxId();
mineWorld.setBoxActive(0);
mineWorld.setExboxId(0);
mineWorldDao.update(mineWorld);
if (mineWorld.getOccuperId() != 0) {
SeizeMineExboxConfig exboxConfig = MineExBoxConfigService.getMineConfig(exboxId);
if (exboxConfig != null && exboxConfig.getRewards() != null) {
sendExBoxReward(mineWorld, exboxConfig.getRewards());
}
}
}
}
}
}
/**
* 初始化矿类
*/
private void initMine() {
Collection<Integer> allGroupIds = CrossMineGroupService.allGroupIds();
for (Integer groupId : allGroupIds) {
Set<Integer> mineIds = MineWorldService.getMineId();
for (Integer mineId : mineIds) {
MineWorldPlayerEntity mineEntiy = MineWorldPlayerEntity.valueof(groupId, mineId, MineWorldService.getMineConfig(mineId).getPage(),
MineWorldService.getBattleMonster(mineId));
mineWorldDao.update(mineEntiy);
}
}
}
/**
* 清理夺矿战上期数据
*/
public void clean() {
if (mineEntity.getState() != WarState.PREPARE.getId()) {
return;
}
Collection<Integer> allGroupIds = CrossWarGroupServerService.allGroupIds();
for (Integer groupId : allGroupIds) {
mineWorldDao.cleanMine(groupId);
}
mineWorldDao.cleanMap();
}
夺矿玩法分为游戏服和世界服,游戏服主要是储存玩家数据,和客户端对接协议,和世界服信息交互。
查询矿产一套流程代码
/**
* 一键搜索剩余矿区信息
*
* @param object
* @return
*/
@RequestMapping(value = "/queryMineList", method = RequestMethod.POST)
public @ResponseBody GaloshesJsonResultProtocol queryMineList(@RequestBody JSONObject object) {
return handle(object, new HandlerResultCallBack<Object>() {
@Override
public Object call(Long gamerId, JSONObject object) throws Exception {
MineTypeListDto queryMineList = mineFacade.queryMineList(gamerId);
return queryMineList;
}
});
}
public MineTypeListDto queryMineList(Long gamerId) {
JSONObject param = new JSONObject();
param.put("gamerId", gamerId);
MineTypeListDto queryDto = worldService.obtainTCrossBattle(param, "mine/queryMineList", MineTypeListDto.class);
return queryDto;
}
与世界服建立连接,后面的新项目使用了RPC协议会比现在舒服很多
@Component
public class WorldService implements GameInit {
public final static String WORLD_CONTEXT_NAME = "domain-world";
public final static String REGIST_URI = "system/regist";
public final static String FORWARD_URI = "system/forward";
public List<WorldRankInfo> pagodaRanks = Lists.newCopyOnWriteArrayList();
private static final Logger LOGGER = LoggerFactory.getLogger(WorldService.class);
@Autowired
private IHttpClient httpClient;
@Value("${server.worldUrl}")
private String worldUrl;
@Value("${server.worldEnable}")
private boolean worldEnable = false;
@Value("${server.flag}")
public String serverType;
@Autowired
@Qualifier("serverId")
public int serverId;
@Value("${server.compose}")
private String compose;
public boolean registToWord() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("serverId", serverId);
jsonObject.put("port", 30000 + serverId);
jsonObject.put("serverType", serverType);
jsonObject.put("composeIds", compose);
try {
String res = httpClient.sendPost(getPath(REGIST_URI), jsonObject.toJSONString(), "application/json");
if (res == null) {
return false;
}
JsonResultProtocol jsonResultProtocol = JSON.parseObject(res, JsonResultProtocol.class);
if (jsonResultProtocol.getResult() == ResultCode.SUCCESS.getCode()) {
return true;
}
return false;
} catch (Exception e) {
LOGGER.error("{}", e);
return false;
}
}
/**
* 从世界服获取消息
*
* @param jsonObject 数据
* @param path 绝对路径,以下划线开头
* @return
* @return
*/
public <T> T obtainTCrossBattle(JSONObject jsonObject, String path, Class<T> tClazz) {
if (path == null || path.isEmpty()) {
throw new RuntimeException("path is null!!!!!");
}
try {
String fullUrl = getPath(path);
jsonObject.put("serverId", serverId);
jsonObject.put("serverType", serverType);
String res = httpClient.sendPost(fullUrl, jsonObject.toJSONString(), "application/json");
if (res == null) {
throw new CrossBattleRemoteDataException();
}
JsonResultProtocol parseObject = JSON.parseObject(res, JsonResultProtocol.class);
if (parseObject.getMessage() == null || "".equals(parseObject.getMessage())) {
throw new CrossBattleRemoteDataException();
}
return JSON.parseObject(parseObject.getMessage().toString(), tClazz);
} catch (Exception e) {
LOGGER.error("{}", e);
throw new CrossBattleRemoteDataException();
}
}
世界服用的redis数据库,主要保存矿产数据,处理玩家间的信息。
/**
* 一键搜索剩余矿区信息
*
* @param object
* @return
*/
@RequestMapping(value = "/queryMineList", method = RequestMethod.POST)
@ResponseBody
public JsonResultProtocol queryMineList(@RequestBody JSONObject object) {
JsonResultProtocol jsonResultProtocol = new JsonResultProtocol();
try {
int serverType = object.getIntValue("serverType");
int serverId = object.getIntValue("serverId");
MineTypeListDto dto = mineFacade.queryMineList(serverId, serverType);
jsonResultProtocol.setup(ResultCode.SUCCESS.getCode(), JSON.toJSONString(dto));
} catch (Exception e) {
LOGGER.error("{}", e);
jsonResultProtocol.setup(ResultCode.SERVER_ERROR.getCode());
}
return jsonResultProtocol;
}
/**
* 获取矿区矿产信息
*/
public MineTypeListDto queryMineList(int serverId, int serverType) {
List<WorldMineSimpleDto> mineSimpleDtoList = Lists.newArrayList();
int groupId = CrossMineGroupService.getGroupId(serverId, serverType);
if (groupId <= 0) {
LOGGER.error("CrossMine can't find groupId, serverId:{}, serverType:{}", serverId, serverType);
return null;
}
List<MineWorldPlayerEntity> mineList = mineWorldDao.getMineList(groupId);
// 记录剩余矿区信息
for (MineWorldPlayerEntity mineWorldPlayerEntity : mineList) {
if (mineWorldPlayerEntity.getOccuperId() != 0) {
continue;
}
int idpage = mineWorldPlayerEntity.getPage();
int mineId = mineWorldPlayerEntity.getMineId();
SeizeMineConfig mineConfig = MineWorldService.getMineConfig(mineId);
WorldMineSimpleDto mineSimple = WorldMineSimpleDto.valueOf(mineId, idpage, mineConfig.getMineType(), mineConfig.getMineLevel(),
mineWorldPlayerEntity.getMineGamer());
mineSimple.setOccupeTime(mineWorldPlayerEntity.getOccupeTime());
mineSimple.setOccupeEndTime(mineWorldPlayerEntity.getOccupeEndTime());
if (mineConfig.getMineType() == 2) {
// 高级矿信息储存
mineSimple.setBoxActive(mineWorldPlayerEntity.getBoxActive());
}
mineSimpleDtoList.add(mineSimple);
}
return MineTypeListDto.valueOf(mineSimpleDtoList);
}
主要流程就是这样,当初做的比较匆忙,现在回想还是有很多可以优化的地方,也给大家写功能的时候参考
获取矿产占领者的id进入战斗,击败对方则更新占领城池广播,如果对手是玩家,通知对手加入仇人信息
// 获取矿产信息
MineWorldPlayerEntity mineWorldPlayerEntity = mineWorldDao.get(groupId, mineId);
SeizeMineConfig mineConfig = MineWorldService.getMineConfig(mineId);
// 判断是否已经占领过矿
List<MineWorldPlayerEntity> mineList = mineWorldDao.getMineList(groupId);
for (MineWorldPlayerEntity minePlayerEntity : mineList) {
if (minePlayerEntity.getOccuperId() == gamerId) {
SeizeMineConfig gamerMine = MineWorldService.getMineConfig(minePlayerEntity.getMineId());
if (gamerMine.getMineType() == mineConfig.getMineType()) {
return null;
}
}
}
long protectTime = globalService.load(GlobalConfigKey.SEIZEMINEPROTECTTIME).findInt() * TimeConstant.ONE_MINUTE_MILLISECOND;
if (mineConfig.getMineLevel() == 1) {
// 如果当前未过保护时间 低级矿保护
if (mineWorldPlayerEntity.getOccupeTime() + protectTime >= System.currentTimeMillis()) {
return null;
}
}
List<BattleRole> opponentBattleRoleList = Lists.newArrayList();
WorldMinePlayResultDto playResultDto;
if (mineWorldPlayerEntity.getOccuperId() == 0) {
// 对手怪物信息
opponentBattleRoleList = MineWorldService.getBattleRole(mineId);
LinkedList<BattleRole> opponentBattleRoles = Lists.newLinkedList();
for (BattleRole battleRole : opponentBattleRoleList) {
BattleRole copyBattleRole = new BattleRole(battleRole.getRoleId(), battleRole.getBelong(), battleRole.getVocation(),
battleRole.getBattleAttr().copy(), battleRole.getTotalAttr().copy(), battleRole.getBattleSkillAttrs());
opponentBattleRoles.add(copyBattleRole);
}
LinkedList<BattleRole> challengeBattleRoles = worldMinePlayDto.getChallengeBattleRoles();
for (BattleRole battleRole : challengeBattleRoles) {
battleRole.setTotalAttr(battleRole.getBattleAttr().copy());
}
BattleFight battleFight = new BattleFight(gamerId, mineId, challengeBattleRoles, opponentBattleRoles);
BattleResult battleResult = battleMonitor.playBattle(battleFight, false, PlayType.NONE, null);
playResultDto = WorldMinePlayResultDto.valueOf(battleResult, 1);
} else {
// 对手是玩家
MineGamer mineGamersource = mineWorldPlayerEntity.getMineGamer();
GamerBattleRoleDto battle = getBattle(mineGamersource.getServerType(), mineGamersource.getServerId(), mineGamersource.getGamerId());
if (battle == null) {
LOGGER.error("CrossMine can't getBattle Message, serverType:{}, serverId:{}", mineGamersource.getServerType(),
mineGamersource.getServerId());
return null;
}
LinkedList<BattleRole> challengeBattleRoles = worldMinePlayDto.getChallengeBattleRoles();
for (BattleRole battleRole : challengeBattleRoles) {
battleRole.setTotalAttr(battleRole.getBattleAttr().copy());
}
BattleFight battleFight = new BattleFight(gamerId, mineGamersource.getGamerId(), challengeBattleRoles, battle.getChallengeBattleRoles());
BattleResult battleResult = battleMonitor.playBattle(battleFight, PlayType.NONE, null);
playResultDto = WorldMinePlayResultDto.valueOf(battleResult, battle.getPoints(), 2);
// 更新玩家仇人信息
mineGamer.setGroupId(groupId);
saveOppend(mineGamersource, mineGamer, battleResult, mineId);
}
// 玩家胜利更新数据
if (playResultDto.getWinner() == gamerId) {
// 被攻击玩家结算奖励
if (mineWorldPlayerEntity.getOccuperId() != 0) {
boolean settleReward = settleReward(mineWorldPlayerEntity, 3);
if (!settleReward) {
return null;
}
mineWorldPlayerEntity.initi();
}
// 初始矿产占领时长
long initialTime = globalService.load(GlobalConfigKey.SeizeMineInitialTime).findInt() * TimeConstant.ONE_MINUTE_MILLISECOND;
mineWorldPlayerEntity.setOccuperId(gamerId);
mineWorldPlayerEntity.setOccupeTime(System.currentTimeMillis());
mineWorldPlayerEntity.setOccupeEndTime(mineWorldPlayerEntity.getOccupeTime() + initialTime);
mineWorldPlayerEntity.setMineGamer(mineGamer);
mineWorldDao.update(mineWorldPlayerEntity);
// 记录消息类
MineWorldMessageEntity messageEntity = MineWorldMessageEntity.valueof(groupId, mineId, mineGamer);
List<MineWorldMessageEntity> mineMessageList = mineWorldMessageDao.getMineMessageList(groupId);
// 储存最多30条
if (mineMessageList.size() >= 30) {
mineMessageList.remove(0);
}
mineMessageList.add(messageEntity);
mineWorldMessageDao.saveMineMessageList(groupId, mineMessageList);
}
return playResultDto;
}
发送信息到被攻击者服务器
/**
*
* @param mineGamer
* 被攻打者信息
* @param oppendMineGamer
* 攻打记录的仇敌
* @param battleResult
* @param mineId
* @return
*/
private boolean saveOppend(MineGamer mineGamer, MineGamer oppendMineGamer, BattleResult battleResult, int mineId) {
int serverId = mineGamer.getServerId();
int serverType = mineGamer.getServerType();
Server server = serverDao.getServer(serverId, serverType);
if (server == null) {
LOGGER.error("serizeMina saveOppend server not found, serverType:{},serverId:{}", serverType, serverId);
return false;
}
String url = "http://" + server.getHost() + ":" + server.getPort() + "/" + PathConstant.GAME_CONTEXT_NAME + PathConstant.WORLD_OPPONENT_MINE;
JSONObject jsonObject = new JSONObject();
jsonObject.put("mineGamer", mineGamer);
jsonObject.put("oppendMineGamer", oppendMineGamer);
jsonObject.put("battleResult", battleResult);
jsonObject.put("mineId", mineId);
String result = innerHttpClient.sendPost(url, jsonObject.toJSONString(), "application/json");
if (StringUtils.isEmpty(result)) {
LOGGER.error("serizeMina saveOppend http error, url:{},jsonObject:{}", url, jsonObject.toJSONString());
return false;
}
JsonResultProtocol jsonResultProtocol = JSON.parseObject(result, JsonResultProtocol.class);
if (jsonResultProtocol.getResult() != ResultCode.SUCCESS.getCode()) {
LOGGER.error("serizeMina saveOppend result error, url:{},jsonObject:{},result:{}", url, jsonObject.toJSONString(),
JSONObject.toJSONString(jsonResultProtocol));
return false;
}
boolean istrue = JSONObject.parseObject(jsonResultProtocol.getMessage().toString(), boolean.class);
return istrue;
}
战斗类
public class BattleMonitor {
@Resource
private FightMonitor fightMonitor;
public BattleResult playBattle(BattleFight battleFight, boolean copyAttr, PlayType playType, Object object) {
if (copyAttr) {
copyAttr(battleFight);
}
return play(battleFight, playType, object);
}
private void copyAttr(BattleFight battleFight) {
LinkedList<BattleRole> challengeRoleAttrs = battleFight.getChallengeRoleAttrs();
for (BattleRole battleRole : challengeRoleAttrs) {
battleRole.setTotalAttr(battleRole.getBattleAttr().copy());
}
LinkedList<BattleRole> opponentRoleAttrs = battleFight.getOpponentRoleAttrs();
for (BattleRole battleRole : opponentRoleAttrs) {
battleRole.setTotalAttr(battleRole.getBattleAttr().copy());
}
}
private BattleResult play(BattleFight battleFight, PlayType playType, Object object) {
BattleResult battleResult = new BattleResult();
Iterator<BattleRole> challengeRoles = battleFight.getChallengeRoleAttrs().iterator();
Iterator<BattleRole> defenceRoles = battleFight.getOpponentRoleAttrs().iterator();
BattleRole challengeRole = challengeRoles.next();
while (challengeRoles.hasNext() && !challengeRole.hasAlive()) {
challengeRole = challengeRoles.next();
}
BattleRole defenceRole = defenceRoles.next();
while (defenceRoles.hasNext() && !defenceRole.hasAlive()) {
defenceRole = defenceRoles.next();
}
boolean challengeFirst = true;
boolean defenceFirst = true;
long winner = 0;
long last = 0;
long lastLeftHp = 0;
List<Long> left = Lists.newArrayList();
for (;;) {
FightResult fightResult = fightMonitor.fight(challengeRole, defenceRole, challengeFirst, defenceFirst, playType, object);
battleResult.addReports(fightResult.getReports());
if (fightResult.hasWinnerWas(challengeRole.getRoleId())) {
if (!defenceRoles.hasNext()) {
winner = battleFight.getChallenge();
last = challengeRole.getRoleId();
lastLeftHp = challengeRole.getTotalAttr().getHp();
break;
}
defenceRole = defenceRoles.next();
defenceFirst = true;
challengeFirst = false;
challengeRole.cleanAccumulateSpeed();
} else {
if (!challengeRoles.hasNext()) {
winner = battleFight.getOpponent();
last = defenceRole.getRoleId();
lastLeftHp = defenceRole.getTotalAttr().getHp();
break;
}
challengeRole = challengeRoles.next();
challengeFirst = true;
defenceFirst = false;
defenceRole.cleanAccumulateSpeed();
}
}
//win
if (winner == battleFight.getChallenge()) {
left.add(challengeRole.getRoleId());
while (challengeRoles.hasNext()) {
left.add(challengeRoles.next().getRoleId());
}
} else {
left.add(defenceRole.getRoleId());
while (defenceRoles.hasNext()) {
left.add(defenceRoles.next().getRoleId());
}
}
battleResult.win(winner, last, lastLeftHp, left);
return battleResult;
}
public BattleResult playBattle(BattleFight battleFight, PlayType playType, Object object) {
return playBattle(battleFight, true, playType, object);
}
}
@Component
public class FightMonitor {
@Resource
private BaseAttackAct baseAttackAct;
@Resource
private BaseSkillAct baseSkillAct;
@Resource
private EffectAct effectAct;
/**
* 判断谁先出手
* @param challengeRole
* @param opponentRole
* @param challengeFirst
* @param defenceFirst
* @return
*/
private boolean hasChallengeRoleActFirst(BattleRole challengeRole, BattleRole opponentRole, boolean challengeFirst, boolean defenceFirst) {
if (challengeFirst) {
if (defenceFirst) {
if (challengeRole.getBattleAttr().getSpeed() > opponentRole.getBattleAttr().getSpeed()) {
return true;
}
} else {
return true;
}
}
return false;
}
public FightResult fight(BattleRole challengeRole, BattleRole opponentRole, boolean challengeFirst, boolean defenceFirst, PlayType playType,
Object object) {
long winner = 0;
List<RoundReport> reports = Lists.newArrayList();
boolean firstAttack = hasChallengeRoleActFirst(challengeRole, opponentRole, challengeFirst, defenceFirst);
BattleRole attackRole = null;
BattleRole defenceRole = null;
if (firstAttack) {
attackRole = challengeRole;
defenceRole = opponentRole;
} else {
defenceRole = challengeRole;
attackRole = opponentRole;
boolean challengeTemp = challengeFirst;
challengeFirst = defenceFirst;
defenceFirst = challengeTemp;
}
int attackRound = 1;
int defenceRound = 1;
for (;;) {
if (!attackRole.hasAlive()) {
winner = attackRole.getRoleId();
break;
}
RoundReport roundReport = roundAttack(attackRole, defenceRole, challengeFirst, defenceFirst, attackRound, defenceRound, playType, object);
challengeFirst = false;
defenceFirst = false;
reports.add(roundReport);
if (!defenceRole.hasAlive()) {
winner = attackRole.getRoleId();
break;
}
if (!attackRole.hasAlive()) {
winner = defenceRole.getRoleId();
break;
}
BattleRole tempRole = attackRole;
attackRole = defenceRole;
defenceRole = tempRole;
attackRound++;
int tempRound = attackRound;
attackRound = defenceRound;
defenceRound = tempRound;
}
return new FightResult(winner, reports);
}
private RoundReport roundAttack(BattleRole attackRole, BattleRole defenceRole, boolean challengeFirst, boolean defenceFirst, int attackRound,
int defenceRound, PlayType playType, Object object) {
RoundReport roundReport = new RoundReport(attackRole.getRoleId(), attackRole.getBelong(), defenceRole.getRoleId());
List<ActResult> bufferActs = effectAct.processEffect(attackRole);
if (bufferActs.size() > 0) {
roundReport.addActResults(bufferActs);
}
for (BattleSkillAttr battleSkillAttr : attackRole.getBattleSkillAttrs()) {
//在battleSkillAttr中增加一个方法 用来使技率生效影响基本技能触发几率
if (battleSkillAttr.canTriggerSkill(attackRound, attackRole.getTotalAttr().getSkillChance())) {
ActResult result = baseSkillAct.act(battleSkillAttr, attackRole, defenceRole, challengeFirst, attackRound);
roundReport.addActResult(result);
break;
}
}
// 判断战斗回合大于100,被攻击着输
if (attackRound > 100) {
if (defenceRole.getBattleAttr().getHp() > attackRole.getBattleAttr().getHp()) {
attackRole.getBattleAttr().setHp(0);
} else {
defenceRole.getBattleAttr().setHp(0);
}
}
List<ActResult> act = baseAttackAct.act(attackRole, defenceRole, challengeFirst, defenceFirst, playType, object);
roundReport.addActResults(act);
return roundReport;
}
}
差不多就是这些,现在是用lua语言写起来简单很多,新接的战令功能根据开始时间和活动持续时间自行运转,看看夺矿战状态流程管理复习下,现在记性不行,要把以前学的都慢慢记录下来了