1022 lines
48 KiB
C#
1022 lines
48 KiB
C#
/*
|
||
* @Author: 白哉
|
||
* @Description: 行为逻辑类
|
||
* @Date: 2025年04月10日 星期四 11:04:44
|
||
* @Modify:
|
||
*/
|
||
|
||
|
||
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using Logic;
|
||
using Logic.Action;
|
||
using Logic.CrashSight;
|
||
using Logic.Skill;
|
||
using RuntimeData;
|
||
using TH1_Core.Events;
|
||
using TH1_Core.Managers;
|
||
using TH1_Logic.Core;
|
||
using TH1Renderer;
|
||
using Unity.VisualScripting.Antlr3.Runtime.Tree;
|
||
using UnityEngine;
|
||
|
||
|
||
//这里是所有BuildAction派生子类的实现模块
|
||
namespace TH1_Logic.Action
|
||
{
|
||
|
||
public enum PlayerActionType
|
||
{
|
||
None,
|
||
OfferAlly,
|
||
AcceptAlly,
|
||
RefuseAlly,
|
||
BreakAlly,
|
||
Embassy,
|
||
SelectHero,
|
||
FinishHeroTask,
|
||
BreakEmbassy,
|
||
SelectTreasureOptionA,
|
||
SelectTreasureOptionB,
|
||
TreasureGainCoin,
|
||
TreasureGainUnit,
|
||
TreasureGainTech,
|
||
TreasureGainCulture,
|
||
TreasureGainCityExp,
|
||
DanegeldDemand,
|
||
DanegeldPay,
|
||
DanegeldReject,
|
||
Max
|
||
}
|
||
|
||
//UnitAction单位行动逻辑类
|
||
public class PlayerActionAction : ActionLogicBase
|
||
{
|
||
public PlayerActionAction(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return false;
|
||
}
|
||
|
||
protected bool PlayerActionCheckBaseInfo(CommonActionParams actionParam)
|
||
{
|
||
//鲁棒性判断,必须包含playerData,表明是哪个玩家正在操作哪个单位
|
||
if (actionParam.PlayerData == null) return false;
|
||
return true;
|
||
}
|
||
}
|
||
|
||
//UnitAction单位行动逻辑类
|
||
public class PlayerActionDiplomacy : PlayerActionAction
|
||
{
|
||
public PlayerActionDiplomacy(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
//Step #1 鲁棒性判断
|
||
if (actionParams.PlayerData == null) return false;
|
||
if (actionParams.MainObjectType != MainObjectType.Player) return false;
|
||
if (actionParams.TargetPlayerData == null) return false;
|
||
if (!CheckCan(actionParams)) return false;
|
||
|
||
MapData map = actionParams.MapData;
|
||
PlayerData player = actionParams.PlayerData;
|
||
PlayerData targetPlayer = actionParams.TargetPlayerData;
|
||
if (IsDanegeldAction(_actionId.PlayerActionType))
|
||
return ExecuteDanegeld(actionParams, player, targetPlayer);
|
||
if (!map.GetCapitalCityDataByPlayerId(actionParams.TargetPlayerData.Id, out var targetCity)) return false;
|
||
if (!map.GetCapitalCityDataByPlayerId(actionParams.PlayerData.Id, out var city)) return false;
|
||
if (!map.GetGridDataByCityId(targetCity.Id, out var targetGrid)) return false;
|
||
actionParams.PlayerData.GetCountryDiplomacyInfo(actionParams.TargetPlayerData.Id, out var dipInfo);
|
||
actionParams.TargetPlayerData.GetCountryDiplomacyInfo(actionParams.PlayerData.Id,out var dipInfo2);
|
||
//Step #2 处理大使馆
|
||
if (_actionId.PlayerActionType == PlayerActionType.Embassy)
|
||
{
|
||
//Step #1建立大使馆,
|
||
dipInfo.IsEmbassy = true;
|
||
//如果是真人玩家 在其他首都建立大使馆,更新对应城市的视觉,播放大使馆建立特效
|
||
if (actionParams.MapData == Main.MapData && player.Id == Main.MapData.PlayerMap.SelfPlayerId)
|
||
{
|
||
targetCity.SetCityRenderer(actionParams.MapData);
|
||
targetGrid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Treasure));
|
||
}
|
||
|
||
//如果是真人玩家 AI在真人玩家的首都建立大使馆,更新对应城市的视觉,
|
||
if (actionParams.MapData == Main.MapData && targetPlayer.Id == Main.MapData.PlayerMap.SelfPlayerId)
|
||
{
|
||
city.SetCityRenderer(actionParams.MapData);
|
||
}
|
||
|
||
|
||
//Step #2 如果对方还没有meet我,加入meetlist
|
||
if(!targetPlayer.MeetPlayers.Contains(player.Id))
|
||
Main.PlayerLogic.AddMeetPlayer(map,targetPlayer,player);
|
||
|
||
//Step #3 更新大使馆周围一格的视野,会自动处理视觉部分
|
||
var gidList = map.GridMap.GetAroundGridIdList(1,targetGrid,true );
|
||
Main.PlayerLogic.UpdateSight_LogicView(map,player,gidList);
|
||
|
||
//step #4 扣钱
|
||
player.SpendCoin(GetCost(actionParams));
|
||
|
||
//Step #5 如果是真人玩家发起,弹出一个announce,并关闭当前info
|
||
if (player.Id == Main.MapData.PlayerMap.SelfPlayerId)
|
||
{
|
||
var announcement = new ShowUIAnnounceDiplomacy { PlayerActionType = PlayerActionType.Embassy,PlayerId = player.Id,TargetPlayerId = targetPlayer.Id };
|
||
EventManager.Publish(announcement);
|
||
EventManager.Publish(new HideUIInfoDiplomacy());
|
||
}
|
||
|
||
//Step #6 如果是其他玩家发起但是目标是真人玩家,弹出一个announce,并关闭当前info
|
||
if (targetPlayer.Id == Main.MapData.PlayerMap.SelfPlayerId)
|
||
{
|
||
var announcement = new ShowUIAnnounceDiplomacy { PlayerActionType = PlayerActionType.Embassy,PlayerId = player.Id,TargetPlayerId = targetPlayer.Id };
|
||
EventManager.Publish(announcement);
|
||
EventManager.Publish(new HideUIInfoDiplomacy());
|
||
}
|
||
|
||
|
||
return true;
|
||
}
|
||
//Step #3 处理申请结盟
|
||
if (_actionId.PlayerActionType == PlayerActionType.OfferAlly)
|
||
{
|
||
//Step #1 让对方收到我方邮件
|
||
dipInfo2.IsLeagueRequest = true;
|
||
|
||
//Step #2 如果对方还没有meet我,加入meetlist
|
||
if(!targetPlayer.MeetPlayers.Contains(player.Id))
|
||
Main.PlayerLogic.AddMeetPlayer(map,targetPlayer,player);
|
||
|
||
//Step #3 如果是真人玩家发起,弹出一个notify,并关闭当前info
|
||
if (Main.MapData == actionParams.MapData && player.Id == Main.MapData.PlayerMap.SelfPlayerId)
|
||
{
|
||
EventManager.Publish(new ShowUINotifyCommon(){UINotifyCommonType = UINotifyCommonType.DiplomacyOfferAlly});
|
||
EventManager.Publish(new HideUIInfoDiplomacy());
|
||
}
|
||
//Step #4 如果是真人玩家收到,那么要到下回合开始的时候才会触发
|
||
return true;
|
||
}
|
||
|
||
//Step #4 处理accept结盟
|
||
if (_actionId.PlayerActionType == PlayerActionType.AcceptAlly)
|
||
{
|
||
//Step #1 关闭我方的对方结盟信件请求标记,登记为盟友
|
||
dipInfo.IsLeagueRequest = false;
|
||
//如果我方也给对方发邮件,也关闭
|
||
dipInfo2.IsLeagueRequest = false;
|
||
dipInfo.DiplomacyState = DiplomacyState.League;
|
||
dipInfo2.DiplomacyState = DiplomacyState.League;
|
||
//Step #2 如果target是真map真人玩家 弹出一个presentationUI 提示,达成盟友,更新双方首都的cityinfo
|
||
if (map == Main.MapData && targetPlayer.Id == map.PlayerMap.SelfPlayerId)
|
||
{
|
||
var announcement = new ShowUIAnnounceDiplomacy { PlayerActionType = PlayerActionType.AcceptAlly,PlayerId = player.Id,TargetPlayerId = targetPlayer.Id };
|
||
EventManager.Publish(announcement);
|
||
city.SetCityRenderer(actionParams.MapData);
|
||
targetCity.SetCityRenderer(actionParams.MapData);
|
||
}
|
||
//Step #3 如果是真map,我方是真人玩家,更新双方首都的cityinfo
|
||
if (map == Main.MapData && player.Id == map.PlayerMap.SelfPlayerId)
|
||
{
|
||
|
||
city.SetCityRenderer(actionParams.MapData);
|
||
targetCity.SetCityRenderer(actionParams.MapData);
|
||
}
|
||
//Step #4 如果是真map,双方有一个是真人玩家,就要处理的视觉情况
|
||
if (map == Main.MapData && (player.Id == map.PlayerMap.SelfPlayerId) ||
|
||
(targetPlayer.Id == map.PlayerMap.SelfPlayerId))
|
||
{
|
||
foreach (var tunit in map.UnitMap.UnitList)
|
||
{
|
||
if(!map.GetPlayerDataByUnitId(tunit.Id,out var uplayer))continue;
|
||
if (uplayer.Id == map.PlayerMap.SelfPlayerId) continue;
|
||
if (uplayer.Id == targetPlayer.Id || uplayer.Id == player.Id)
|
||
tunit.Renderer(map)?.InstantUpdateUnit(true);
|
||
}
|
||
city.SetCityRenderer(actionParams.MapData);
|
||
targetCity.SetCityRenderer(actionParams.MapData);
|
||
EventManager.Publish(new HideUIInfoDiplomacy());
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
//Step #5 处理refuse结盟
|
||
if (_actionId.PlayerActionType == PlayerActionType.RefuseAlly)
|
||
{
|
||
//Step #1 关闭对方的结盟请求标记
|
||
dipInfo.IsLeagueRequest = false;
|
||
//Step #2 如果target是真map真人玩家 弹出一个presentationUI 提示,明确拒绝对方
|
||
if (map == Main.MapData && targetPlayer.Id == map.PlayerMap.SelfPlayerId)
|
||
{
|
||
var announcement = new ShowUIAnnounceDiplomacy { PlayerActionType = PlayerActionType.RefuseAlly,PlayerId = player.Id ,TargetPlayerId = targetPlayer.Id };
|
||
EventManager.Publish(announcement);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
//Step #6 处理break结盟
|
||
if (_actionId.PlayerActionType == PlayerActionType.BreakAlly)
|
||
{
|
||
if (dipInfo.IsTeammate || dipInfo2.IsTeammate) return false;
|
||
//Step #1 设置双方的外交状态为背盟
|
||
dipInfo.DiplomacyState = DiplomacyState.LeagueRupture;
|
||
dipInfo2.DiplomacyState = DiplomacyState.LeagueRupture;
|
||
|
||
var disbandList = new List<UnitData>();
|
||
//Step #2 所有单位跳过本回合,所有对方领土的单位自动解散
|
||
foreach (var unit in map.UnitMap.UnitList)
|
||
{
|
||
if(!map.GetPlayerDataByUnitId(unit.Id,out var uplayer))continue;
|
||
if(uplayer.Id != player.Id) continue;
|
||
if (!map.GetGridDataByUnitId(unit.Id, out var ugrid)) continue;
|
||
var gridHasPlayer = map.GetPlayerDataByTerritoryGridId(ugrid.Id, out var ugridPlayer);
|
||
//如果是对方领土上的己方unit,强制解散
|
||
if (gridHasPlayer && ugridPlayer.Id == targetPlayer.Id)
|
||
{
|
||
//加入解散列表。不能就地解散因为会影响到map.UnitMap.UnitList
|
||
disbandList.Add(unit);
|
||
}
|
||
else
|
||
{
|
||
unit.ClearActionPoint();
|
||
unit.Renderer(map)?.InstantUpdateUnit(true);
|
||
}
|
||
}
|
||
|
||
foreach (var unit in disbandList)
|
||
{
|
||
var action = ActionLogicFactory.GetActionLogic(new CommonActionId()
|
||
{ ActionType = CommonActionType.UnitAction, UnitActionType = UnitActionType.ForceDisband });
|
||
var param = new CommonActionParams(mapData: map, playerData:player,unitData: unit, mainObjectType: MainObjectType.Unit);
|
||
action?.CompleteExecute(param);
|
||
}
|
||
|
||
//Step #3 如果target是真map真人玩家 弹出一个presentationUI 提示,明确背叛对方,更新双方cityinfo
|
||
if (map == Main.MapData && targetPlayer.Id == map.PlayerMap.SelfPlayerId)
|
||
{
|
||
var announcement = new ShowUIAnnounceDiplomacy { PlayerActionType = PlayerActionType.BreakAlly,PlayerId = player.Id,TargetPlayerId = targetPlayer.Id };
|
||
EventManager.Publish(announcement);
|
||
}
|
||
//Step #4 如果是真map,双方有一个是真人玩家,就要处理的视觉情况
|
||
if (map == Main.MapData && (player.Id == map.PlayerMap.SelfPlayerId) ||
|
||
(targetPlayer.Id == map.PlayerMap.SelfPlayerId))
|
||
{
|
||
foreach (var tunit in map.UnitMap.UnitList)
|
||
{
|
||
if(!map.GetPlayerDataByUnitId(tunit.Id,out var uplayer))continue;
|
||
if (uplayer.Id == map.PlayerMap.SelfPlayerId) continue;
|
||
if (uplayer.Id == targetPlayer.Id || uplayer.Id == player.Id)
|
||
tunit.Renderer(map)?.InstantUpdateUnit(true);
|
||
}
|
||
city.SetCityRenderer(actionParams.MapData);
|
||
targetCity.SetCityRenderer(actionParams.MapData);
|
||
EventManager.Publish(new HideUIInfoDiplomacy());
|
||
//关闭当前的场上的高亮
|
||
Main.Instance.MapInteractionLogic.CancelAllHighlight();
|
||
}
|
||
|
||
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
|
||
//Step #1 鲁棒性判断
|
||
if (actionParams.PlayerData == null || !actionParams.PlayerData.IsSurvival) return false;
|
||
if (actionParams.MainObjectType != MainObjectType.Player) return false;
|
||
if (actionParams.TargetPlayerData == null || !actionParams.TargetPlayerData.IsSurvival ) return false;
|
||
if (!actionParams.PlayerData.MeetPlayers.Contains(actionParams.TargetPlayerData.Id)) return false;
|
||
|
||
if (IsDanegeldAction(_actionId.PlayerActionType))
|
||
return CheckCanDanegeld(actionParams);
|
||
|
||
//Step #2 判断钱够不够
|
||
if (GetCost(actionParams) > actionParams.PlayerData.PlayerCoin)
|
||
return false;
|
||
//Step #3 如果不具备科技 return
|
||
if (!actionParams.PlayerData.TechTree.CheckActionCan(_actionId))
|
||
return false;
|
||
|
||
//Step #4 处理大使馆
|
||
if (_actionId.PlayerActionType == PlayerActionType.Embassy)
|
||
{
|
||
//如果对方没有原始首都,不可建立大使馆
|
||
actionParams.MapData.GetCapitalCityDataByPlayerId(actionParams.TargetPlayerData.Id,out var city);
|
||
if (!Main.CityLogic.CheckCradleCapital(actionParams.MapData, actionParams.TargetPlayerData, city))
|
||
return false;
|
||
|
||
//如果已经在对方建立了大使馆,不可再次建立大使馆
|
||
actionParams.PlayerData.GetCountryDiplomacyInfo(actionParams.TargetPlayerData.Id, out var dipInfo);
|
||
if (dipInfo.IsEmbassy) return false;
|
||
return true;
|
||
}
|
||
|
||
//Step #5 判断能否申请结盟
|
||
if (_actionId.PlayerActionType == PlayerActionType.OfferAlly)
|
||
{
|
||
actionParams.PlayerData.GetCountryDiplomacyInfo(actionParams.TargetPlayerData.Id, out var dipInfo);
|
||
//如果刚解除结盟或者已经结盟 return
|
||
if (dipInfo.DiplomacyState == DiplomacyState.League ||
|
||
dipInfo.DiplomacyState == DiplomacyState.LeagueRupture)
|
||
return false;
|
||
|
||
//如果对方已经有一个来自我方的结盟请求
|
||
actionParams.TargetPlayerData.GetCountryDiplomacyInfo(actionParams.PlayerData.Id,out var dipInfo2);
|
||
if (dipInfo2.IsLeagueRequest) return false;
|
||
|
||
return true;
|
||
}
|
||
//Step #6 && #7 判断能否refuse / accept 结盟
|
||
if (_actionId.PlayerActionType == PlayerActionType.RefuseAlly || _actionId.PlayerActionType == PlayerActionType.AcceptAlly)
|
||
{
|
||
actionParams.PlayerData.GetCountryDiplomacyInfo(actionParams.TargetPlayerData.Id, out var dipInfo);
|
||
//如果刚解除结盟或者已经结盟 return
|
||
if (dipInfo.DiplomacyState == DiplomacyState.League ||
|
||
dipInfo.DiplomacyState == DiplomacyState.LeagueRupture)
|
||
return false;
|
||
|
||
//如果对方没有结盟请求
|
||
//actionParams.TargetPlayerData.DiplomacyData.GetCountryDiplomacyInfo(actionParams.PlayerData.Id,out var dipInfo2);
|
||
if (!dipInfo.IsLeagueRequest) return false;
|
||
return true;
|
||
}
|
||
|
||
//Step #8 判断能否break结盟
|
||
if (_actionId.PlayerActionType == PlayerActionType.BreakAlly)
|
||
{
|
||
actionParams.PlayerData.GetCountryDiplomacyInfo(actionParams.TargetPlayerData.Id, out var dipInfo);
|
||
if (dipInfo.IsTeammate) return false;
|
||
//如果没有结盟 return
|
||
if (dipInfo.DiplomacyState != DiplomacyState.League) return false;
|
||
//如果对方率先break,return
|
||
actionParams.TargetPlayerData.GetCountryDiplomacyInfo(actionParams.PlayerData.Id,out var dipInfo2);
|
||
if (dipInfo2.IsTeammate) return false;
|
||
if (dipInfo2.DiplomacyState == DiplomacyState.LeagueRupture) return false;
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
public override bool CheckShow(CommonActionParams actionParams,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
//Step #1 鲁棒性判断
|
||
if (actionParams.PlayerData == null || !actionParams.PlayerData.IsSurvival) return false;
|
||
if (actionParams.MainObjectType != MainObjectType.Player) return false;
|
||
if (actionParams.TargetPlayerData == null || !actionParams.TargetPlayerData.IsSurvival ) return false;
|
||
if (!actionParams.PlayerData.MeetPlayers.Contains(actionParams.TargetPlayerData.Id)) return false;
|
||
|
||
if (IsDanegeldAction(_actionId.PlayerActionType))
|
||
return CheckShowDanegeld(actionParams, out showType);
|
||
|
||
//如果不是breakAlly,默认返回团,详细处理showType
|
||
if (_actionId.PlayerActionType != PlayerActionType.BreakAlly)
|
||
{
|
||
|
||
//Step #2 如果不具备科技 return
|
||
if (!actionParams.PlayerData.TechTree.CheckActionCan(_actionId))
|
||
{
|
||
showType = ShowType.Locked;
|
||
return true;
|
||
}
|
||
//Step #3 判断钱够不够
|
||
if (GetCost(actionParams) > actionParams.PlayerData.PlayerCoin)
|
||
{
|
||
showType = ShowType.Cost;
|
||
return true;
|
||
}
|
||
|
||
//Step #4 处理大使馆
|
||
if (_actionId.PlayerActionType == PlayerActionType.Embassy)
|
||
{
|
||
//如果对方没有原始首都,不可建立大使馆
|
||
actionParams.MapData.GetCapitalCityDataByPlayerId(actionParams.TargetPlayerData.Id,out var city);
|
||
if (!Main.CityLogic.CheckCradleCapital(actionParams.MapData, actionParams.TargetPlayerData, city))
|
||
{
|
||
showType = ShowType.Locked;
|
||
return true;
|
||
}
|
||
|
||
|
||
//如果已经在对方建立了大使馆,不可再次建立大使馆
|
||
actionParams.PlayerData.GetCountryDiplomacyInfo(actionParams.TargetPlayerData.Id, out var dipInfo);
|
||
if (dipInfo.IsEmbassy)
|
||
{
|
||
showType = ShowType.Done;
|
||
return true;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
//Step #5 判断能否申请结盟
|
||
if (_actionId.PlayerActionType == PlayerActionType.OfferAlly)
|
||
{
|
||
actionParams.PlayerData.GetCountryDiplomacyInfo(actionParams.TargetPlayerData.Id, out var dipInfo);
|
||
//如果刚解除结盟或者已经结盟 return
|
||
if (dipInfo.DiplomacyState == DiplomacyState.League)
|
||
{
|
||
showType = ShowType.Done;
|
||
return true;
|
||
}
|
||
if(dipInfo.DiplomacyState == DiplomacyState.LeagueRupture)
|
||
{
|
||
showType = ShowType.Locked;
|
||
return true;
|
||
}
|
||
|
||
|
||
//如果对方已经有一个来自我方的结盟请求
|
||
actionParams.TargetPlayerData.GetCountryDiplomacyInfo(actionParams.PlayerData.Id,out var dipInfo2);
|
||
if (dipInfo2.IsLeagueRequest)
|
||
{
|
||
showType = ShowType.Send;
|
||
return true;
|
||
}
|
||
return true;
|
||
}
|
||
//Step #6 && #7 判断能否refuse / accept 结盟
|
||
if (_actionId.PlayerActionType == PlayerActionType.RefuseAlly || _actionId.PlayerActionType == PlayerActionType.AcceptAlly)
|
||
{
|
||
return true;
|
||
}
|
||
}
|
||
else
|
||
//Step #8 判断能否break结盟
|
||
{
|
||
actionParams.PlayerData.GetCountryDiplomacyInfo(actionParams.TargetPlayerData.Id, out var dipInfo);
|
||
if (dipInfo.IsTeammate) return false;
|
||
//如果没有结盟 return
|
||
if (dipInfo.DiplomacyState != DiplomacyState.League) return false;
|
||
//如果对方率先break,return
|
||
actionParams.TargetPlayerData.GetCountryDiplomacyInfo(actionParams.PlayerData.Id,out var dipInfo2);
|
||
if (dipInfo2.IsTeammate) return false;
|
||
if (dipInfo2.DiplomacyState == DiplomacyState.LeagueRupture) return false;
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
public override ActionShowState CheckShowState(CommonActionParams actionParams)
|
||
{
|
||
//Step #1 鲁棒性判断
|
||
if (actionParams.PlayerData == null) return ActionShowState.None;
|
||
if (actionParams.MainObjectType != MainObjectType.Player) return ActionShowState.None;
|
||
if (actionParams.TargetPlayerData == null) return ActionShowState.None;
|
||
|
||
MapData map = actionParams.MapData;
|
||
PlayerData player = actionParams.PlayerData;
|
||
PlayerData targetPlayer = actionParams.TargetPlayerData;
|
||
if (IsDanegeldAction(_actionId.PlayerActionType))
|
||
return CheckShowStateDanegeld(actionParams);
|
||
if (!map.GetCapitalCityDataByPlayerId(actionParams.TargetPlayerData.Id, out var city)) return ActionShowState.None;
|
||
if (!map.GetGridDataByCityId(city.Id, out var grid)) return ActionShowState.None;
|
||
actionParams.PlayerData.GetCountryDiplomacyInfo(actionParams.TargetPlayerData.Id, out var dipInfo);
|
||
actionParams.TargetPlayerData.GetCountryDiplomacyInfo(actionParams.PlayerData.Id,out var dipInfo2);
|
||
|
||
//Step #2 计算结盟按钮的情况
|
||
if (_actionId.PlayerActionType == PlayerActionType.OfferAlly)
|
||
{
|
||
//如果没有科技
|
||
if (!actionParams.PlayerData.TechTree.CheckActionCan(_actionId))
|
||
return ActionShowState.Unavailable;
|
||
//如果已经发送过,还没被回应
|
||
if(dipInfo2.IsLeagueRequest || dipInfo.DiplomacyState == DiplomacyState.LeagueRupture) return ActionShowState.Unavailable;
|
||
//如果已经结盟
|
||
if (dipInfo.DiplomacyState == DiplomacyState.League ) return ActionShowState.Finished;
|
||
//其他情况一律是available
|
||
return ActionShowState.Available;
|
||
}
|
||
|
||
//Step #3 计算breakAlly按钮的情况
|
||
if (_actionId.PlayerActionType == PlayerActionType.BreakAlly)
|
||
{
|
||
if (dipInfo.IsTeammate || dipInfo2.IsTeammate) return ActionShowState.Unavailable;
|
||
return ActionShowState.Available;
|
||
}
|
||
|
||
//Step #4 计算embassy按钮的情况
|
||
if (_actionId.PlayerActionType == PlayerActionType.Embassy)
|
||
{
|
||
//如果没有科技
|
||
if (!actionParams.PlayerData.TechTree.CheckActionCan(_actionId))
|
||
return ActionShowState.Unavailable;
|
||
//如果对方已经丢失原始首都
|
||
if (!map.GetCapitalCityDataByPlayerId(targetPlayer.Id, out var targetCapital)) return ActionShowState.None;
|
||
if (!Main.CityLogic.CheckCradleCapital(map, targetPlayer, targetCapital)) return ActionShowState.Unavailable;
|
||
//如果钱不够
|
||
if (player.PlayerCoin < GetCost(actionParams)) return ActionShowState.Expensive;
|
||
//如果已经建立了大使馆
|
||
if (dipInfo.IsEmbassy) return ActionShowState.Finished;
|
||
//其他情况一律是available
|
||
return ActionShowState.Available;
|
||
}
|
||
|
||
return ActionShowState.None;
|
||
}
|
||
|
||
public static bool IsDanegeldAction(PlayerActionType playerActionType)
|
||
{
|
||
return playerActionType == PlayerActionType.DanegeldDemand
|
||
|| playerActionType == PlayerActionType.DanegeldPay
|
||
|| playerActionType == PlayerActionType.DanegeldReject;
|
||
}
|
||
|
||
public static void GetPendingDanegeldDemanders(MapData map, PlayerData targetPlayer, List<PlayerData> result)
|
||
{
|
||
result?.Clear();
|
||
if (map?.PlayerMap?.PlayerDataList == null || targetPlayer == null || result == null) return;
|
||
foreach (var demander in map.PlayerMap.PlayerDataList)
|
||
{
|
||
if (demander == null || demander.Id == targetPlayer.Id) continue;
|
||
if (!demander.IsSurvival) continue;
|
||
if (!TryGetDanegeldRelation(demander, targetPlayer, out var info)) continue;
|
||
if (info.DanegeldState == DanegeldState.Demanding) result.Add(demander);
|
||
}
|
||
result.Sort((a, b) => a.Id.CompareTo(b.Id));
|
||
}
|
||
|
||
public static bool RejectPendingDanegeldDemandsInTurnEnd(MapData map, PlayerData targetPlayer)
|
||
{
|
||
if (map == null || targetPlayer == null) return false;
|
||
var demanders = new List<PlayerData>();
|
||
GetPendingDanegeldDemanders(map, targetPlayer, demanders);
|
||
var rejected = false;
|
||
foreach (var demander in demanders)
|
||
{
|
||
var actionId = new CommonActionId
|
||
{
|
||
ActionType = CommonActionType.PlayerAction,
|
||
PlayerActionType = PlayerActionType.DanegeldReject
|
||
};
|
||
var action = ActionLogicFactory.GetActionLogic(actionId);
|
||
var param = new CommonActionParams(mapData: map, playerData: targetPlayer,
|
||
targetPlayer: demander, mainObjectType: MainObjectType.Player);
|
||
param.RefreshParams();
|
||
if (action?.ExecuteWithoutFullActionPeriod(param) == true) rejected = true;
|
||
}
|
||
|
||
return rejected;
|
||
}
|
||
|
||
public static void ClearExpiredDanegeldRefusals(MapData map, PlayerData targetPlayer)
|
||
{
|
||
if (map?.PlayerMap?.PlayerDataList == null || targetPlayer == null) return;
|
||
foreach (var demander in map.PlayerMap.PlayerDataList)
|
||
{
|
||
if (demander == null || demander.Id == targetPlayer.Id) continue;
|
||
if (!TryGetDanegeldRelation(demander, targetPlayer, out var info)) continue;
|
||
if (info.DanegeldState != DanegeldState.Refused) continue;
|
||
if (targetPlayer.Turn <= info.DanegeldRefusedTurn) continue;
|
||
info.DanegeldState = DanegeldState.Clear;
|
||
info.DanegeldRefusedTurn = 0;
|
||
}
|
||
}
|
||
|
||
public static int GetDanegeldRaidMultiplier(PlayerData raider, PlayerData targetPlayer)
|
||
{
|
||
if (raider == null || targetPlayer == null) return 1;
|
||
if (!TryGetDanegeldRelation(raider, targetPlayer, out var info)) return 1;
|
||
return info.DanegeldState == DanegeldState.Refused ? 2 : 1;
|
||
}
|
||
|
||
private bool ExecuteDanegeld(CommonActionParams actionParams, PlayerData player, PlayerData targetPlayer)
|
||
{
|
||
if (_actionId.PlayerActionType == PlayerActionType.DanegeldDemand)
|
||
{
|
||
if (!TryGetDanegeldRelation(player, targetPlayer, out var info)) return false;
|
||
player.SpendCoin(GetDanegeldDemandCost(actionParams));
|
||
info.DanegeldState = DanegeldState.Demanding;
|
||
info.LastDanegeldDemandTurn = player.Turn;
|
||
info.DanegeldRefusedTurn = 0;
|
||
if(!targetPlayer.MeetPlayers.Contains(player.Id))
|
||
Main.PlayerLogic.AddMeetPlayer(actionParams.MapData,targetPlayer,player);
|
||
if (actionParams.MapData == Main.MapData && player.Id == Main.MapData.PlayerMap.SelfPlayerId)
|
||
{
|
||
EventManager.Publish(new ShowUINotifyCommon(){UINotifyCommonType = UINotifyCommonType.HakureiDanegeldDemandStarted});
|
||
EventManager.Publish(new HideUIInfoDiplomacy());
|
||
}
|
||
return true;
|
||
}
|
||
|
||
if (!TryGetDanegeldRelation(targetPlayer, player, out var demanderToPlayer)) return false;
|
||
|
||
if (_actionId.PlayerActionType == PlayerActionType.DanegeldPay)
|
||
{
|
||
var payAmount = GetDanegeldActualPaymentAmount(actionParams);
|
||
if (payAmount > 0)
|
||
{
|
||
player.SpendCoin(payAmount);
|
||
targetPlayer.AddCoin(payAmount);
|
||
}
|
||
ReimuNorwaySkillUtil.EnqueueDanegeldPaymentNotice(actionParams.MapData, player, targetPlayer.Id,
|
||
payAmount, targetPlayer.Id);
|
||
|
||
demanderToPlayer.DanegeldState = DanegeldState.Clear;
|
||
demanderToPlayer.DanegeldRefusedTurn = 0;
|
||
return true;
|
||
}
|
||
|
||
if (_actionId.PlayerActionType == PlayerActionType.DanegeldReject)
|
||
{
|
||
var demandedAmount = GetDanegeldPaymentAmount(actionParams);
|
||
demanderToPlayer.DanegeldState = DanegeldState.Refused;
|
||
demanderToPlayer.DanegeldRefusedTurn = player.Turn;
|
||
ReimuNorwaySkillUtil.EnqueueDanegeldRejectedNotice(actionParams.MapData, player, targetPlayer.Id,
|
||
demandedAmount, targetPlayer.Id);
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
private bool CheckCanDanegeld(CommonActionParams actionParams)
|
||
{
|
||
var player = actionParams.PlayerData;
|
||
var targetPlayer = actionParams.TargetPlayerData;
|
||
if (player == null || targetPlayer == null || player.Id == targetPlayer.Id) return false;
|
||
|
||
if (_actionId.PlayerActionType == PlayerActionType.DanegeldDemand)
|
||
{
|
||
if (!player.TechTree.CheckActionCan(_actionId)) return false;
|
||
if (player.PlayerCoin < GetDanegeldDemandCost(actionParams)) return false;
|
||
if (!TryGetDanegeldRelation(player, targetPlayer, out var info)) return false;
|
||
if (!TryGetDanegeldRelation(targetPlayer, player, out var targetInfo)) return false;
|
||
if (info.IsTeammate || targetInfo.IsTeammate) return false;
|
||
if (actionParams.MapData.SameUnion(player.Id, targetPlayer.Id)) return false;
|
||
if (info.DiplomacyState == DiplomacyState.League || targetInfo.DiplomacyState == DiplomacyState.League)
|
||
return false;
|
||
if (CheckDanegeldDemandInCooldown(player, info)) return false;
|
||
return info.DanegeldState == DanegeldState.Clear;
|
||
}
|
||
|
||
if (!TryGetDanegeldRelation(targetPlayer, player, out var demanderToPlayer)) return false;
|
||
return demanderToPlayer.DanegeldState == DanegeldState.Demanding;
|
||
}
|
||
|
||
private bool CheckShowDanegeld(CommonActionParams actionParams, out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
if (_actionId.PlayerActionType != PlayerActionType.DanegeldDemand)
|
||
return CheckCanDanegeld(actionParams);
|
||
|
||
if (!Table.Instance.PlayerDataAssets.CheckActionInTechPool(_actionId, actionParams.PlayerData))
|
||
return false;
|
||
|
||
if (!actionParams.PlayerData.TechTree.CheckActionCan(_actionId))
|
||
{
|
||
showType = ShowType.Locked;
|
||
return true;
|
||
}
|
||
|
||
if (!TryGetDanegeldRelation(actionParams.PlayerData, actionParams.TargetPlayerData, out var info))
|
||
return false;
|
||
if (!TryGetDanegeldRelation(actionParams.TargetPlayerData, actionParams.PlayerData, out var targetInfo))
|
||
return false;
|
||
if (info.IsTeammate || targetInfo.IsTeammate || actionParams.MapData.SameUnion(actionParams.PlayerData.Id, actionParams.TargetPlayerData.Id)
|
||
|| info.DiplomacyState == DiplomacyState.League || targetInfo.DiplomacyState == DiplomacyState.League)
|
||
{
|
||
showType = ShowType.Locked;
|
||
return true;
|
||
}
|
||
|
||
if (info.DanegeldState == DanegeldState.Demanding)
|
||
{
|
||
showType = ShowType.Send;
|
||
return true;
|
||
}
|
||
|
||
if (info.DanegeldState == DanegeldState.Refused)
|
||
{
|
||
showType = ShowType.Locked;
|
||
return true;
|
||
}
|
||
|
||
if (CheckDanegeldDemandInCooldown(actionParams.PlayerData, info))
|
||
{
|
||
showType = ShowType.Cold;
|
||
return true;
|
||
}
|
||
|
||
if (actionParams.PlayerData.PlayerCoin < GetDanegeldDemandCost(actionParams))
|
||
{
|
||
showType = ShowType.Cost;
|
||
return true;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
private ActionShowState CheckShowStateDanegeld(CommonActionParams actionParams)
|
||
{
|
||
if (_actionId.PlayerActionType != PlayerActionType.DanegeldDemand)
|
||
return CheckCanDanegeld(actionParams) ? ActionShowState.Available : ActionShowState.None;
|
||
|
||
if (!Table.Instance.PlayerDataAssets.CheckActionInTechPool(_actionId, actionParams.PlayerData))
|
||
return ActionShowState.None;
|
||
if (!actionParams.PlayerData.TechTree.CheckActionCan(_actionId))
|
||
return ActionShowState.Unavailable;
|
||
if (!TryGetDanegeldRelation(actionParams.PlayerData, actionParams.TargetPlayerData, out var info))
|
||
return ActionShowState.None;
|
||
if (!TryGetDanegeldRelation(actionParams.TargetPlayerData, actionParams.PlayerData, out var targetInfo))
|
||
return ActionShowState.None;
|
||
if (info.IsTeammate || targetInfo.IsTeammate || actionParams.MapData.SameUnion(actionParams.PlayerData.Id, actionParams.TargetPlayerData.Id)
|
||
|| info.DiplomacyState == DiplomacyState.League || targetInfo.DiplomacyState == DiplomacyState.League)
|
||
return ActionShowState.Unavailable;
|
||
if (info.DanegeldState != DanegeldState.Clear) return ActionShowState.Unavailable;
|
||
if (CheckDanegeldDemandInCooldown(actionParams.PlayerData, info)) return ActionShowState.Unavailable;
|
||
if (actionParams.PlayerData.PlayerCoin < GetDanegeldDemandCost(actionParams))
|
||
return ActionShowState.Expensive;
|
||
return ActionShowState.Available;
|
||
}
|
||
|
||
public override int GetCost(CommonActionParams actionParams)
|
||
{
|
||
return _actionId.PlayerActionType == PlayerActionType.DanegeldDemand
|
||
? GetDanegeldDemandCost(actionParams)
|
||
: base.GetCost(actionParams);
|
||
}
|
||
|
||
public static int GetDanegeldDemandCost(CommonActionParams actionParams)
|
||
{
|
||
return GetDanegeldDemandCost(actionParams?.MapData, actionParams?.PlayerData);
|
||
}
|
||
|
||
public static int GetDanegeldDemandCost(MapData map, PlayerData player)
|
||
{
|
||
if (map == null || player == null) return 0;
|
||
return Mathf.Min(map.GetCityCount(player.Id) * 3, 15);
|
||
}
|
||
|
||
public static int GetDanegeldPaymentAmount(CommonActionParams actionParams)
|
||
{
|
||
return GetDanegeldPaymentAmount(actionParams?.MapData, actionParams?.PlayerData);
|
||
}
|
||
|
||
public static int GetDanegeldPaymentAmount(MapData map, PlayerData player)
|
||
{
|
||
if (map == null || player == null) return 0;
|
||
var coinPerTurn = Main.PlayerLogic.GetPlayerCoinPerTurn(map, player.Id);
|
||
if (coinPerTurn <= 0) return 0;
|
||
return (coinPerTurn + 4) / 5;
|
||
}
|
||
|
||
public static int GetDanegeldActualPaymentAmount(CommonActionParams actionParams)
|
||
{
|
||
return GetDanegeldActualPaymentAmount(actionParams?.MapData, actionParams?.PlayerData);
|
||
}
|
||
|
||
public static int GetDanegeldActualPaymentAmount(MapData map, PlayerData player)
|
||
{
|
||
if (map == null || player == null) return 0;
|
||
return Mathf.Min(GetDanegeldPaymentAmount(map, player), Mathf.Max(0, player.PlayerCoin));
|
||
}
|
||
|
||
private static bool CheckDanegeldDemandInCooldown(PlayerData demander, CountryDiplomacyInfo info)
|
||
{
|
||
if (demander == null || info == null || info.LastDanegeldDemandTurn == 0) return false;
|
||
return demander.Turn < info.LastDanegeldDemandTurn + 2;
|
||
}
|
||
|
||
private static bool TryGetDanegeldRelation(PlayerData demander, PlayerData targetPlayer, out CountryDiplomacyInfo info)
|
||
{
|
||
info = null;
|
||
if (demander == null || targetPlayer == null) return false;
|
||
return demander.GetCountryDiplomacyInfo(targetPlayer.Id, out info) && info != null;
|
||
}
|
||
|
||
}
|
||
|
||
//如果有空的槽位,那么将空的槽位设置为选择的特定hero。
|
||
//[actionId参数]只要一个giantType即可
|
||
//[param参数]只要player即可
|
||
public class PlayerActionSelectHero : PlayerActionAction
|
||
{
|
||
public PlayerActionSelectHero(CommonActionId id) : base(id) { }
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
if (!CheckCan(actionParams)) return false;
|
||
var player = actionParams.PlayerData;
|
||
var heroD = player.PlayerHeroData;
|
||
return heroD?.AddHero(actionParams.MapData,actionParams.PlayerData,_actionId.GiantType)??false;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
//Step #1 基础鲁棒性检查
|
||
if (!PlayerActionCheckBaseInfo(actionParams)) return false;
|
||
var player = actionParams.PlayerData;
|
||
var heroD = player.PlayerHeroData;
|
||
|
||
//Step #2 检查英雄类型属于当前玩家阵营
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitType.Giant, _actionId.GiantType,
|
||
1, out var info)) return false;
|
||
if (info.GiantEmpire != actionParams.PlayerData.Empire) return false;
|
||
if (!ContentGate.CanUseHeroForPlayer(player, _actionId.GiantType))
|
||
{
|
||
#if UNITY_EDITOR
|
||
if (!Logic.AI.AIDirectorBatchRuntime.SkipPresentationWait)
|
||
LogSystem.LogWarning($"Blocked unavailable hero select: player={player.Id}, giant={_actionId.GiantType}");
|
||
#else
|
||
LogSystem.LogWarning($"Blocked unavailable hero select: player={player.Id}, giant={_actionId.GiantType}");
|
||
#endif
|
||
return false;
|
||
}
|
||
//Step #3 检查当前玩家的HeroData,是否已经出了英雄,且拥有空的槽位
|
||
if (heroD.HeroCount >= heroD.MaxHeroCount) return false;
|
||
if (heroD.HasHero(_actionId.GiantType)) return false;
|
||
|
||
return true;
|
||
}
|
||
}
|
||
|
||
public class PlayerActionTreasureReward : PlayerActionAction
|
||
{
|
||
public PlayerActionTreasureReward(CommonActionId id) : base(id) { }
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
if (!CheckCan(actionParams)) return false;
|
||
|
||
var player = actionParams.PlayerData;
|
||
var groupId = actionParams.GridId;
|
||
if (!player.TryGetTreasureActionOptionGroup(groupId, out var group)) return false;
|
||
if (!group.TryGetOption(_actionId, out var option)) return false;
|
||
|
||
var ret = ExecuteTreasureReward(actionParams, group, option);
|
||
if (!ret) return false;
|
||
player.RemoveTreasureActionOptionGroup(groupId);
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
if (!PlayerActionCheckBaseInfo(actionParams)) return false;
|
||
if (actionParams.MainObjectType != MainObjectType.Player) return false;
|
||
if (!IsTreasureRewardAction(_actionId.PlayerActionType)) return false;
|
||
if (actionParams.GridId == 0) return false;
|
||
if (!actionParams.PlayerData.TryGetTreasureActionOptionGroup(actionParams.GridId, out var group)) return false;
|
||
return group.TryGetOption(_actionId, out _);
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams, out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParams);
|
||
}
|
||
|
||
private static bool IsTreasureRewardAction(PlayerActionType playerActionType)
|
||
{
|
||
return playerActionType == PlayerActionType.TreasureGainCoin
|
||
|| playerActionType == PlayerActionType.TreasureGainUnit
|
||
|| playerActionType == PlayerActionType.TreasureGainTech
|
||
|| playerActionType == PlayerActionType.TreasureGainCulture
|
||
|| playerActionType == PlayerActionType.TreasureGainCityExp;
|
||
}
|
||
|
||
private bool ExecuteTreasureReward(CommonActionParams actionParams, ActionOptionGroup group, ActionOption option)
|
||
{
|
||
if (!actionParams.MapData.GridMap.GetGridDataByGid(group.SourceGridId, out var sourceGrid)) return false;
|
||
var player = actionParams.PlayerData;
|
||
|
||
if (option.RewardType == TreasureActionRewardType.Coin)
|
||
{
|
||
player.AddCoin(option.Value, Table.Instance.GridToWorld(sourceGrid));
|
||
return true;
|
||
}
|
||
|
||
if (option.RewardType == TreasureActionRewardType.Unit)
|
||
{
|
||
if (!actionParams.MapData.GetCapitalCityDataByPlayerId(player.Id, out var capital)) return false;
|
||
if (!actionParams.MapData.GetGridDataByCityId(capital.Id, out var capitalGrid)) return false;
|
||
if (actionParams.MapData.UnitMap.GetUnitDataByUnitId(group.SourceUnitId, out var sourceUnit) &&
|
||
actionParams.MapData.GetGridDataByUnitId(sourceUnit.Id, out var sourceUnitGrid) &&
|
||
sourceUnitGrid.Id == sourceGrid.Id)
|
||
Main.UnitLogic.PassiveMoveAway(actionParams.MapData, sourceUnit);
|
||
|
||
if (!actionParams.MapData.AddUnitData(sourceGrid.Id, capital.Id, option.UnitFullType, out var unit) &&
|
||
!actionParams.MapData.AddUnitData(capitalGrid.Id, capital.Id, option.UnitFullType, out unit))
|
||
return false;
|
||
if (option.UnitFullType.UnitType == UnitType.RammerShip)
|
||
unit.AddSkill_Legacy(SkillType.OFFICER, actionParams.MapData, true, -1, false, -1, false, SpecialAddSkillType.Normal, 0);
|
||
unit.SetOfficer();
|
||
unit.Health = unit.GetMaxHealth();
|
||
unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
|
||
capital.SetCityRenderer(actionParams.MapData);
|
||
return true;
|
||
}
|
||
|
||
if (option.RewardType == TreasureActionRewardType.Tech)
|
||
{
|
||
if (option.TechType == TechType.None) return false;
|
||
Main.PlayerLogic.ResearchTech(actionParams.MapData, player, option.TechType, 0);
|
||
if (player.IsSelfPlayer())
|
||
EventManager.Publish(new ShowUINotifyCommon(){UINotifyCommonType = UINotifyCommonType.ExamineTech});
|
||
return true;
|
||
}
|
||
|
||
if (option.RewardType == TreasureActionRewardType.Culture)
|
||
{
|
||
player.AddCulturePoint(option.Value);
|
||
if (player.IsSelfPlayer())
|
||
EventManager.Publish(new ShowUINotifyCommon(){UINotifyCommonType = UINotifyCommonType.ExamineCulture});
|
||
return true;
|
||
}
|
||
|
||
if (option.RewardType == TreasureActionRewardType.CityExp)
|
||
{
|
||
if (!actionParams.MapData.GetCapitalCityDataByPlayerId(player.Id, out var capital)) return false;
|
||
Main.CityLogic.GridGiveCityExp_LogicView(actionParams.MapData, player, capital.Grid(actionParams.MapData), capital, option.Value);
|
||
if (player.IsSelfPlayer())
|
||
EventManager.Publish(new ShowUINotifyCommon(){UINotifyCommonType = UINotifyCommonType.ExamineCityExp});
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
}
|
||
|
||
//立即完成一个英雄的升级任务
|
||
//[actionId参数]只要一个giantType即可
|
||
//[param参数]只要player即可
|
||
public class PlayerActionFinishHeroTask : PlayerActionAction
|
||
{
|
||
public PlayerActionFinishHeroTask(CommonActionId id) : base(id) { }
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
var player = actionParams.PlayerData;
|
||
var heroD = player.PlayerHeroData;
|
||
player.GetHeroCostDiscount(actionParams.MapData, out var discount);
|
||
var cost = heroD.GetHeroFinishTaskCost(_actionId.GiantType, discount);
|
||
var can = heroD.ForceFinishHeroTask(_actionId.GiantType);
|
||
if (can)
|
||
{
|
||
if (actionParams.MapData.CheckIsRealPlayer(actionParams.PlayerData.Id))
|
||
{
|
||
actionParams.PlayerData.AddCulturePoint(-cost);
|
||
}
|
||
}
|
||
|
||
return can;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
//Step #1 基础鲁棒性检查
|
||
if (!PlayerActionCheckBaseInfo(actionParams)) return false;
|
||
var player = actionParams.PlayerData;
|
||
var heroD = player.PlayerHeroData;
|
||
|
||
//Step #2 检查英雄类型属于当前玩家阵营
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitType.Giant, _actionId.GiantType,
|
||
1, out var info)) return false;
|
||
if (info.GiantEmpire != actionParams.PlayerData.Empire) return false;
|
||
if (!ContentGate.CanUseHeroForPlayer(player, _actionId.GiantType))
|
||
{
|
||
LogSystem.LogWarning($"Blocked unavailable hero task finish: player={player.Id}, giant={_actionId.GiantType}");
|
||
return false;
|
||
}
|
||
|
||
//Step #3 检查player是否拥有该英雄
|
||
if (!heroD.HasHero(_actionId.GiantType)) return false;
|
||
|
||
//Step #4 如果是玩家,检查文化值是否够
|
||
if (actionParams.PlayerData == actionParams.MapData.PlayerMap.SelfPlayerData)
|
||
{
|
||
player.GetHeroCostDiscount(actionParams.MapData, out var discount);
|
||
var cost = heroD.GetHeroFinishTaskCost(_actionId.GiantType, discount);
|
||
if (cost > actionParams.PlayerData.PlayerCultureInfo.PlayerCulture)
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
}
|
||
}
|