TH1/Unity/Assets/Scripts/TH1_Logic/Action/TrainUnitActionLogic.cs
2026-06-07 01:03:47 +08:00

785 lines
38 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

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

/*
* @Author: 白哉
* @Description: 行为逻辑类
* @Date: 2025年04月10日 星期四 11:04:44
* @Modify:
*/
using System;
using System.Collections.Generic;
using System.Linq;
using Logic.AI;
using Logic.Audio;
using Logic.CrashSight;
using Logic.Skill;
using RuntimeData;
using TH1_Logic.Core;
using UnityEngine;
using TH1Renderer;
using TH1Resource;
using UnityEditor;
using UnityEngineInternal;
//这里是所有BuildAction派生子类的实现模块
namespace Logic.Action
{
// TrainUnit 训练单位类
public class TrainUnitAction : ActionLogicBase
{
public TrainUnitAction(CommonActionId id) : base(id)
{
}
protected bool TrainUnitActionCheckBaseData(CommonActionParams actionParam)
{
if (actionParam.PlayerData == null) return false;
return true;
}
protected bool TrainUnitActionCheckHasTechCulture(CommonActionParams actionParam)
{
// 特判:特殊兵种只能由对应文明训练
var civId = actionParam.PlayerData.PlayerCivId;
switch (_actionId.UnitType)
{
case UnitType.RemiliaEgyptianKoakuma:
case UnitType.RemiliaEgyptianKoakumaLion:
if (civId != 0) return false;
break;
case UnitType.KaguyaFrenchWolf:
if (civId != 1) return false;
break;
case UnitType.MoriyaHebi:
if (civId != 2) return false;
break;
case UnitType.KomeijiIndianBigGuy:
case UnitType.KomeijiIndianRider:
case UnitType.KomeijiIndianKnight:
case UnitType.KomeijiIndianArcher:
case UnitType.KomeijiIndianCatapult:
case UnitType.KomeijiIndianShip:
case UnitType.KomeijiIndianBomberShip:
case UnitType.KomeijiIndianJuggernaut:
if (civId != 3) return false;
break;
}
//如果有对应科技return true
if(actionParam.PlayerData.TechTree.CheckActionCan(_actionId))
return true;
//检查已拥有的市政卡是否激活了该action
var cultureCardDataAssets = Table.Instance.CultureCardDataAssets;
if (cultureCardDataAssets != null)
{
foreach (var cardType in actionParam.PlayerData.PlayerCultureInfo.CultureCardList)
{
if (cultureCardDataAssets.GetCultureCardInfo(cardType, out var cardInfo)
&& cardInfo.EnableAction)
{
foreach (var enabledAction in cardInfo.EnableActions)
{
if (enabledAction == _actionId)
return true;
}
}
}
}
return false;
}
protected bool TrainUnitActionCheckWaterUnit()
{
if (Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(_actionId.UnitType,_actionId.GiantType,_actionId.UnitLevel,out var info)
&& info.LandType == LandType.WaterAndAshore)
return true;
return false;
}
protected bool TrainUnitActionCheckCityFullPop(CommonActionParams actionParam)
{
if (actionParam.MainObjectType == MainObjectType.City)
{
if (actionParam.MapData.CheckIfCityFullPopulation(actionParam.CityData)) return true;
}
if (actionParam.MainObjectType == MainObjectType.Grid)
{
if (!actionParam.MapData.GetCityDataByTerritoryGid(actionParam.GridData.Id, out var city)) return true;
if (actionParam.MapData.CheckIfCityFullPopulation(city)) return true;
}
return false;
}
protected bool TrainUnitActionCheckCityBelongPlayer(CommonActionParams actionParam)
{
if (actionParam.PlayerData == null) return false;
if (!actionParam.MapData.GetPlayerDataByCityId(actionParam.CityData.Id, out var playerData)
|| playerData.Id != actionParam.PlayerData.Id)
return false;
return true;
}
protected bool TrainUnitActionCheckGridBelongPlayer(CommonActionParams actionParam)
{
if (actionParam.GridData == null ||
!actionParam.MapData.GetPlayerDataByTerritoryGridId(actionParam.GridData.Id, out var player))
return false;
if (player.Id != actionParam.PlayerData.Id)
return false;
return true;
}
protected bool TrainUnitActionCheckUnitOnCity(CommonActionParams actionParam)
{
if (!actionParam.MapData.GetGridDataByCityId(actionParam.CityData?.Id ?? 0, out var grid)) return true;
if (grid.RealUnit(actionParam.MapData, out var unitData)) return true;
return false;
}
protected bool TrainUnitActionCheckEnemyUnitOnGrid(CommonActionParams actionParam)
{
if (actionParam.GridData.VisibleUnit(actionParam.MapData,actionParam.PlayerData, out var unitData)
&& actionParam.MapData.GetPlayerDataByUnitId(unitData.Id,out var unitPlayer)
&& !actionParam.MapData.SameUnion(unitPlayer.Id,actionParam.PlayerId)) return true;
return false;
}
protected bool TrainUnitActionCheckUnitOnGrid(CommonActionParams actionParam)
{
if (actionParam.GridData.VisibleUnit(actionParam.MapData,actionParam.PlayerData, out var unitData)) return true;
return false;
}
protected bool TrainUnitActionCheckMoneyEnough(CommonActionParams actionParam)
{
int cost = GetCost(actionParam);
// BigGuy 类单位消耗文化值而非金币
if (UnitData.IsBigGuyType(_actionId.UnitType))
return actionParam.PlayerData.PlayerCultureInfo.PlayerCulture >= cost;
if (cost > actionParam.PlayerData.PlayerCoin) return false;
return true;
}
protected override bool Execute(CommonActionParams actionParams)
{
if (_actionId.UnitType == UnitType.None)
return false;
if (actionParams.MainObjectType == MainObjectType.City && actionParams.CityData == null)
return false;
if (actionParams.MainObjectType == MainObjectType.Grid && actionParams.GridData == null)
return false;
if (!CheckCan(actionParams)) return false;
GridData gridData = null;
CityData cityData = null;
//如果是city产兵
if (actionParams.MainObjectType == MainObjectType.City)
{
cityData = actionParams.CityData;
//从city处获得准确的gridData
if (!actionParams.MapData.GetGridDataByCityId(actionParams.CityData.Id, out gridData))
return false;
}
//否则如果是grid产兵
if (actionParams.MainObjectType == MainObjectType.Grid)
{
//从actionParams获得准确的gridData
gridData = actionParams.GridData;
if (actionParams.CityData != null)
cityData = actionParams.CityData;
else
actionParams.MapData.GetCityDataByTerritoryGid(gridData.Id, out cityData);
}
if (gridData == null)
return false;
//减去花费BigGuy消耗文化值其他消耗金币
int cost = GetCost(actionParams);
if (UnitData.IsBigGuyType(_actionId.UnitType))
actionParams.PlayerData.AddCulturePoint(-cost);
else
actionParams.PlayerData.SpendCoin(cost);
//生产新单位
if(!actionParams.MapData.AddUnitData(gridData.Id,cityData.Id,new UnitFullType(_actionId.UnitType,_actionId.GiantType,_actionId.UnitLevel),out var newUnit))
return false;
//播放音效
if(newUnit.InMainSight())
AudioManager.Instance.PlayAudio("SFX/UNIT_born");
//Step #4 如果是天狗酒馆每回合首个生产的单位附加1个移动行动点天狗骑兵获得天狗之风
if(actionParams.GridData is { Resource: ResourceType.MoriyaMilitary, NavalBasePoint: > 0 })
{
actionParams.GridData.NavalBasePoint = 0;
newUnit.AddActionPoint(ActionPointType.Move);
//TODO 这里是hard code
if(newUnit.UnitType == UnitType.MoriyaRider)
newUnit.AddSkill_Legacy(SkillType.SNEAK,actionParams.MapData,false,0,false,-1,false,SpecialAddSkillType.Force,newUnit.Id);
//判断是否要更新视觉
if (newUnit.InMainSight())
newUnit.Renderer(actionParams.MapData)?.RenderUpdateUnitGlow();
}
cityData.SetCityRenderer(actionParams.MapData);
//更新视野
var count = Main.PlayerLogic.UpdateSight_LogicView(actionParams.MapData,actionParams.PlayerData,actionParams.MapData.GridMap.GetAroundGridIdList(newUnit.GetSightRange(actionParams.MapData),gridData));
newUnit.HeroTask(actionParams.MapData)?.OnExploredGrids(actionParams.MapData, newUnit, count);
foreach (var kv in actionParams.PlayerData.PlayerHeroData.HeroTaskDict) kv.Value.OnAnyExploredGrids(actionParams.MapData, newUnit, count);
//如果是真mapdata增加得分然后处理得分动画
if (Main.MapData == actionParams.MapData)// && actionParams.PlayerData.Id == actionParams.MapData.PlayerMap.SelfPlayerData.Id)
{
var v1 = Table.Instance.GridToWorld(gridData);
int score = GetCost(actionParams) * 5;
if (actionParams.PlayerData.Id == actionParams.MapData.PlayerMap.SelfPlayerData.Id)
{
MapRenderer.Instance.ProjectileManager.CreateProjectileFaith(v1,score);
}
AchievementDataManager.Instance.OnTrainUnit(actionParams.MapData, actionParams.PlayerData, actionParams.CityData, newUnit);
}
return true;
}
public override bool CheckCan(CommonActionParams actionParam)
{
GridData gridData;
PlayerData playerData;
CityData cityData;
//step #0 基础鲁棒性 (playerData不能为空)
if (!TrainUnitActionCheckBaseData(actionParam)) return false;
//Part1 如果是城市产兵
if (actionParam.MainObjectType == MainObjectType.City)
{
//step #1 city产兵的特殊鲁棒性
if (actionParam.CityData == null) return false;
//step #2 check player操作的city 是不是自己的city,存储gridData
if (!TrainUnitActionCheckCityBelongPlayer(actionParam)) return false;
//step #3 赋值gridData(city的位置)
if (!actionParam.MapData.GetGridDataByCityId(actionParam.CityData.Id, out gridData)) return false;
//step #4如果没科技return
if(!TrainUnitActionCheckHasTechCulture(actionParam)) return false;
//step #5确认是否是水生unit
if (TrainUnitActionCheckWaterUnit()) return false;
//step #6 确认城市是否满员
if (TrainUnitActionCheckCityFullPop(actionParam)) return false;
//step #7 如果城市上面有单位,不能生产,不显示
if (TrainUnitActionCheckUnitOnCity(actionParam)) return false;
//step #8 判断钱够不够
if (!TrainUnitActionCheckMoneyEnough(actionParam)) return false;
//step #9 只处理非英雄
if (_actionId.UnitType == UnitType.Giant) return false;
return true;
}
//Part2 如果是grid产兵
if (actionParam.MainObjectType == MainObjectType.Grid)
{
//step #1 确认基础鲁棒性
if (actionParam.GridData == null) return false;
gridData = actionParam.GridData;
//step #2 进行基础赋值
if (!actionParam.MapData.GetCityDataByTerritoryGid(gridData.Id, out cityData)) return false;
if (!actionParam.MapData.GetPlayerDataByCityId(cityData.Id, out playerData)) return false;
//step #3 check city是不是player的
if (!TrainUnitActionCheckGridBelongPlayer(actionParam)) return false;
//step #4 如果没科技return
if (!TrainUnitActionCheckHasTechCulture(actionParam)) return false;
//step #5 如果城市满员
if (TrainUnitActionCheckCityFullPop(actionParam)) return false;
//step #6如果格子上面有单位不能生产不显示
if (TrainUnitActionCheckUnitOnGrid(actionParam)) return false;
//step #7判断钱够不够
if (!TrainUnitActionCheckMoneyEnough(actionParam)) return false;
//step #8 只处理非英雄
if (_actionId.UnitType == UnitType.Giant) return false;
//----------终于进入正式的特判环节,前面都是通用判断,下面开始进入白名单
//Part 2.2
//军营产兵
if (gridData.Resource == ResourceType.Military ||gridData.Resource == ResourceType.RemiliaMilitary || gridData.Resource == ResourceType.MoriyaMilitary)
{
//step #1 如果水生unit不行
if(TrainUnitActionCheckWaterUnit()) return false;
//step #2 如果是伟人return
if (_actionId.UnitType == UnitType.Giant) return false;
return true;
}
}
return false;
}
public override bool CheckShow(CommonActionParams actionParam,out ShowType showType)
{
showType = ShowType.None;
GridData gridData;
PlayerData playerData;
CityData cityData;
//step #0 基础鲁棒性 (playerData不能为空)
if (!TrainUnitActionCheckBaseData(actionParam)) return false;
//Part1 如果是城市产兵
if (actionParam.MainObjectType == MainObjectType.City)
{
//step #1 city产兵的特殊鲁棒性
if (actionParam.CityData == null) return false;
//step #2 check player操作的city 是不是自己的city,存储gridData
if (!TrainUnitActionCheckCityBelongPlayer(actionParam)) return false;
//step #3 赋值gridData(city的位置)
if (!actionParam.MapData.GetGridDataByCityId(actionParam.CityData.Id, out gridData)) return false;
//step #4如果没科技return
if(!TrainUnitActionCheckHasTechCulture(actionParam)) return false;
//step #5确认是否是水生unit
if (TrainUnitActionCheckWaterUnit()) return false;
//step #8 判断钱够不够
if (!TrainUnitActionCheckMoneyEnough(actionParam)) showType = ShowType.Cost;
//step #6 确认城市是否满员
if (TrainUnitActionCheckCityFullPop(actionParam)) showType = ShowType.Locked;
//step #7 如果城市上面有单位,不能生产,不显示
if (TrainUnitActionCheckUnitOnCity(actionParam)) return false;
//step #9 只处理非英雄
if (_actionId.UnitType == UnitType.Giant) return false;
return true;
}
//Part2 如果是grid产兵
if (actionParam.MainObjectType == MainObjectType.Grid)
{
//step #1 确认基础鲁棒性
if (actionParam.GridData == null) return false;
gridData = actionParam.GridData;
//step #2 进行基础赋值
if (!actionParam.MapData.GetCityDataByTerritoryGid(gridData.Id, out cityData)) return false;
if (!actionParam.MapData.GetPlayerDataByCityId(cityData.Id, out playerData)) return false;
//step #3 check city是不是player的
if (!TrainUnitActionCheckGridBelongPlayer(actionParam)) return false;
//step #4 如果没科技return
if (!TrainUnitActionCheckHasTechCulture(actionParam)) return false;
//step #7判断钱够不够
if (!TrainUnitActionCheckMoneyEnough(actionParam)) showType = ShowType.Cost;
//step #5 如果城市满员
if (TrainUnitActionCheckCityFullPop(actionParam)) showType = ShowType.Locked;
//step #6如果格子上面有单位不能生产不显示
if (TrainUnitActionCheckUnitOnGrid(actionParam)) return false;
//step #8 只处理非英雄
if (_actionId.UnitType == UnitType.Giant) return false;
//----------终于进入正式的特判环节,前面都是通用判断,下面开始进入白名单
//Part 2.2
//军营产兵
if (gridData.Resource == ResourceType.Military ||gridData.Resource == ResourceType.RemiliaMilitary || gridData.Resource == ResourceType.MoriyaMilitary)
{
//step #1 如果水生unit不行
if(TrainUnitActionCheckWaterUnit()) return false;
//step #2 如果是伟人return
if (_actionId.UnitType == UnitType.Giant) return false;
return true;
}
}
return false;
}
public override ActionShowState CheckShowState(CommonActionParams actionParams) { return ActionShowState.None; }
}
public class TrainUnitActionTrainHero : TrainUnitAction
{
private GridData _finalGrid;
private CityData _finalCity;
private UnitData _newUnit;
public TrainUnitActionTrainHero(CommonActionId id) : base(id){}
//确认英雄的冷却cd
private bool CheckGiantHasColdTime(CommonActionParams actionParam)
{
if (actionParam.PlayerData == null) return true;
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitType.Giant, _actionId.GiantType, 1,
out var info)) return true;
if (actionParam.PlayerData.giantPenalty[(uint)info.ChessType] > 0) return true;
return false;
}
private bool TryGetHeroReviveInfo(CommonActionParams actionParam, out int chessIndex, out int coldTime, out int cultureCost)
{
chessIndex = -1;
coldTime = 0;
cultureCost = 0;
if (actionParam?.PlayerData?.PlayerHeroData == null) return false;
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitType.Giant, _actionId.GiantType, 1,
out var info)) return false;
chessIndex = (int)info.ChessType;
if (actionParam.PlayerData.giantPenalty == null
|| chessIndex < 0
|| chessIndex >= actionParam.PlayerData.giantPenalty.Length) return false;
coldTime = actionParam.PlayerData.giantPenalty[chessIndex];
if (coldTime <= 0) return false;
uint heroLevel = actionParam.PlayerData.PlayerHeroData.GetHeroLevel(_actionId.GiantType);
long rawCost = (long)heroLevel * coldTime * 5;
cultureCost = rawCost > int.MaxValue ? int.MaxValue : (int)rawCost;
return cultureCost > 0;
}
public override int GetCost(CommonActionParams actionParams)
{
return TryGetHeroReviveInfo(actionParams, out _, out _, out var cultureCost)
? cultureCost
: base.GetCost(actionParams);
}
private bool CanPayHeroReviveCulture(CommonActionParams actionParam)
{
if (actionParam?.MapData == null || actionParam.PlayerData == null) return false;
if (actionParam.MapData.CheckIsAI(actionParam.PlayerData.Id)) return false;
return TryGetHeroReviveInfo(actionParam, out _, out _, out var cultureCost)
&& actionParam.PlayerData.PlayerCultureInfo.PlayerCulture >= cultureCost;
}
/// <summary>
/// 判断场上的英雄数量是否已经达到 SameUnitCountLimit 上限
/// </summary>
private bool CheckHeroReachMaxCount(CommonActionParams actionParam)
{
// 获取英雄当前等级
uint heroLevel = actionParam.PlayerData.PlayerHeroData.GetHeroLevel(_actionId.GiantType);
// 获取 unitTypeInfo
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(_actionId.UnitType, _actionId.GiantType, heroLevel,
out var heroInfo))
return true;
// 获取当前该玩家场上该英雄的数量
int currentCount = Main.PlayerLogic.GetMapUnitTypeCount(actionParam.MapData, _actionId.UnitType, _actionId.GiantType, actionParam.PlayerData.Id);
// 特判FrenchMokou 和 KaguyaFrenchMokouEgg 共享计数
if (_actionId.GiantType == GiantType.FrenchMokou)
{
currentCount += Main.PlayerLogic.GetMapUnitTypeCount(actionParam.MapData, UnitType.KaguyaFrenchMokouEgg, GiantType.None, actionParam.PlayerData.Id);
}
// 判断是否达到上限 (SameUnitCountLimit 为 0 表示无限制)
if (heroInfo.SameUnitCountLimit > 0 && currentCount >= heroInfo.SameUnitCountLimit)
return true;
return false;
}
protected override bool Execute(CommonActionParams actionParams)
{
//step #0 鲁棒性检查
if (!CheckCan(actionParams)) return false;
bool spendReviveCulture = TryGetHeroReviveInfo(actionParams, out var reviveChessIndex, out _, out var reviveCultureCost);
//step #1 获得准确的gridData和对应的cityData
//step #1 part1 如果是city产英雄
if (actionParams.MainObjectType == MainObjectType.City)
{
_finalCity = actionParams.CityData;
//从city处获得准确的gridData
if (!actionParams.MapData.GetGridDataByCityId(actionParams.CityData.Id, out _finalGrid))
return false;
}
//step #1 part2 否则如果是grid产英雄
if (actionParams.MainObjectType == MainObjectType.Grid)
{
//从actionParams获得准确的gridData
_finalGrid = actionParams.GridData;
if (actionParams.CityData != null)
_finalCity = actionParams.CityData;
else
actionParams.MapData.GetCityDataByTerritoryGid(_finalGrid.Id, out _finalCity);
}
if (_finalGrid == null) return false;
//step #2 确定giant的真实level
var realLv = actionParams.PlayerData.PlayerHeroData.GetHeroLevel(_actionId.GiantType);
//step #3 生产新单位
if (!actionParams.MapData.AddUnitData(_finalGrid.Id, _finalCity.Id,
new UnitFullType(_actionId.UnitType, _actionId.GiantType, realLv), out _newUnit))
return false;
if (spendReviveCulture)
{
actionParams.PlayerData.AddCulturePoint(-reviveCultureCost);
actionParams.PlayerData.giantPenalty[reviveChessIndex] = 0;
}
//播放音效
if(_newUnit.InMainSight())
AudioManager.Instance.PlayAudio("SFX/UNIT_born");
//Step #4 如果是天狗酒馆每回合首个生产的单位附加1个移动行动点
if(actionParams.MainObjectType == MainObjectType.Grid && actionParams.GridData.Resource == ResourceType.MoriyaMilitary && actionParams.GridData.NavalBasePoint > 0)
{
actionParams.GridData.NavalBasePoint = 0;
_newUnit.AddActionPoint(ActionPointType.Move);
//判断是否要更新视觉
if (_newUnit.InMainSight())
_newUnit.Renderer(actionParams.MapData)?.RenderUpdateUnitGlow();
}
//step #5 更新新单位周围的视野
var count = Main.PlayerLogic.UpdateSight_LogicView(actionParams.MapData,actionParams.PlayerData,actionParams.MapData.GridMap.GetAroundGridIdList(_newUnit.GetSightRange(actionParams.MapData),_finalGrid));
_newUnit.HeroTask(actionParams.MapData)?.OnExploredGrids(actionParams.MapData, _newUnit, count);
foreach (var kv in actionParams.PlayerData.PlayerHeroData.HeroTaskDict) kv.Value.OnAnyExploredGrids(actionParams.MapData, _newUnit, count);
ExecuteViewAfter(actionParams);
return true;
}
public override bool CheckCan(CommonActionParams actionParam)
{
//step #0 基础鲁棒性 (playerData不能为空 不是英雄则直接排除
if(_actionId.UnitType != UnitType.Giant) return false;
if (!TrainUnitActionCheckBaseData(actionParam)) return false;
GridData gridData;
PlayerData playerData;
CityData cityData;
//Part1 如果是城市产英雄
if (actionParam.MainObjectType == MainObjectType.City)
{
//step #1 city产兵的特殊鲁棒性
if (actionParam.CityData == null) return false;
//step #2 check player操作的city 是不是自己的city,存储gridData
if (!TrainUnitActionCheckCityBelongPlayer(actionParam)) return false;
//step #3 赋值gridData(city的位置)
if (!actionParam.MapData.GetGridDataByCityId(actionParam.CityData.Id, out gridData)) return false;
//step #4如果HeroList没有英雄
if (!actionParam.PlayerData.PlayerHeroData.HasHero(_actionId.GiantType)) return false;
//step #5 确认城市是否满员
if (TrainUnitActionCheckCityFullPop(actionParam)) return false;
//step #6 如果城市上面有单位,不能生产,不显示
if (TrainUnitActionCheckUnitOnCity(actionParam)) return false;
//step #7 如果英雄在冷却cd
if (CheckGiantHasColdTime(actionParam) && !CanPayHeroReviveCulture(actionParam)) return false;
//step #8 如果英雄违反了UNIQUE或类似的技能如QUARTET
if (CheckHeroReachMaxCount(actionParam)) return false;
return true;
}
//Part2 如果是grid产英雄
if (actionParam.MainObjectType == MainObjectType.Grid)
{
//step #1 确认基础鲁棒性
if (actionParam.GridData == null) return false;
gridData = actionParam.GridData;
//step #2 进行基础赋值
if (!actionParam.MapData.GetCityDataByTerritoryGid(gridData.Id, out cityData)) return false;
if (!actionParam.MapData.GetPlayerDataByCityId(cityData.Id, out playerData)) return false;
//step #3 check grid是不是player的
if (!TrainUnitActionCheckGridBelongPlayer(actionParam)) return false;
//step #4如果HeroList没有英雄
if (!actionParam.PlayerData.PlayerHeroData.HasHero(_actionId.GiantType)) return false;
//step #5 如果城市满员
if (TrainUnitActionCheckCityFullPop(actionParam)) return false;
//step #6如果格子上面有单位不能生产不显示
if (TrainUnitActionCheckUnitOnGrid(actionParam)) return false;
//step #7 如果英雄在冷却cd
if (CheckGiantHasColdTime(actionParam) && !CanPayHeroReviveCulture(actionParam)) return false;
//step #8 如果英雄违反了UNIQUE或类似的技能如QUARTET
if (CheckHeroReachMaxCount(actionParam)) return false;
if (_actionId.UnitType == UnitType.Giant
&& (gridData.Resource is ResourceType.Military or ResourceType.RemiliaMilitary or ResourceType.MoriyaMilitary))
return true;
}
return false;
}
public override bool CheckShow(CommonActionParams actionParam,out ShowType showType)
{
showType = ShowType.None;
//step #0 基础鲁棒性 (playerData不能为空 不是英雄则直接排除
if(_actionId.UnitType != UnitType.Giant) return false;
if (!TrainUnitActionCheckBaseData(actionParam)) return false;
GridData gridData;
PlayerData playerData;
CityData cityData;
//Part1 如果是城市产英雄
if (actionParam.MainObjectType == MainObjectType.City)
{
//step #1 city产兵的特殊鲁棒性
if (actionParam.CityData == null) return false;
//step #2 check player操作的city 是不是自己的city,存储gridData
if (!TrainUnitActionCheckCityBelongPlayer(actionParam)) return false;
//step #3 赋值gridData(city的位置)
if (!actionParam.MapData.GetGridDataByCityId(actionParam.CityData.Id, out gridData)) return false;
//step #4如果HeroList没有英雄
if (!actionParam.PlayerData.PlayerHeroData.HasHero(_actionId.GiantType)) return false;
//step #5 确认城市是否满员
if (TrainUnitActionCheckCityFullPop(actionParam)) showType = ShowType.Locked;
//step #6 如果城市上面有单位,不能生产,不显示
if (TrainUnitActionCheckUnitOnCity(actionParam)) return false;
//step #7 如果英雄在冷却cd
if (CheckGiantHasColdTime(actionParam)) showType = ShowType.Cold;
//step #8 如果英雄违反了UNIQUE或类似的技能如QUARTET
if (CheckHeroReachMaxCount(actionParam)) return false;
return true;
}
//Part2 如果是grid产英雄
if (actionParam.MainObjectType == MainObjectType.Grid)
{
//step #1 确认基础鲁棒性
if (actionParam.GridData == null) return false;
gridData = actionParam.GridData;
//step #2 进行基础赋值
if (!actionParam.MapData.GetCityDataByTerritoryGid(gridData.Id, out cityData)) return false;
if (!actionParam.MapData.GetPlayerDataByCityId(cityData.Id, out playerData)) return false;
//step #3 check grid是不是player的
if (!TrainUnitActionCheckGridBelongPlayer(actionParam)) return false;
//step #4如果HeroList没有英雄
if (!actionParam.PlayerData.PlayerHeroData.HasHero(_actionId.GiantType)) return false;
//step #5 如果城市满员
if (TrainUnitActionCheckCityFullPop(actionParam)) showType = ShowType.Locked;
//step #6如果格子上面有单位不能生产不显示
if (TrainUnitActionCheckUnitOnGrid(actionParam)) return false;
//step #7 如果英雄在冷却cd
if (CheckGiantHasColdTime(actionParam)) showType = ShowType.Cold;
//step #8 如果英雄违反了UNIQUE或类似的技能如QUARTET
if (CheckHeroReachMaxCount(actionParam)) return false;
if (_actionId.UnitType == UnitType.Giant
&& (gridData.Resource is ResourceType.Military or ResourceType.RemiliaMilitary or ResourceType.MoriyaMilitary))
return true;
}
return false;
}
public bool ExecuteViewAfter(CommonActionParams actionParams)
{
//step #0 如果不是真map 不做动画
if (Main.MapData != actionParams.MapData) return false;
//step #1 更新产兵的格子的renderMark
_finalCity.SetCityRenderer(actionParams.MapData);
//step #2 增加得分,然后处理得分动画
var startPos = Table.Instance.GridToWorld(_finalGrid);
int score = GetCost(actionParams) * 5;
actionParams.PlayerData.AddFaith(score,startPos);
AchievementDataManager.Instance.OnTrainUnit(actionParams.MapData, actionParams.PlayerData, actionParams.CityData, _newUnit);
return false;
}
}
//训练kaguya_french特殊兵种 animalWarrior
public class TrainUnitActionTrainKaguyaFrenchAnimalWarrior : TrainUnitAction
{
public TrainUnitActionTrainKaguyaFrenchAnimalWarrior(CommonActionId id) : base(id){}
protected override bool Execute(CommonActionParams actionParams)
{
//if (!CheckCan(actionParams)) return false;
//step #1 获取grid所在的city设置基本数据
actionParams.MapData.GetCityDataByTerritoryGid(actionParams.GridData.Id, out var cityData);
//step #2 如果生产格子上有单位,先把他移开
if(actionParams.GridData.RealUnit(actionParams.MapData,out var unit)) Main.UnitLogic.PassiveMoveAway(actionParams.MapData,unit);
//step #3 生产单位
if(!actionParams.MapData.AddUnitData(actionParams.GridData.Id,cityData.Id,new UnitFullType(_actionId.UnitType,_actionId.GiantType,0),out var newUnit))
return false;
//step #4 扣钱
actionParams.PlayerData.SpendCoin( GetCost(actionParams));
//step #5 消除动物
actionParams.GridData.Resource = ResourceType.None;
//Step #6 更新视野
var count = Main.PlayerLogic.UpdateSight_LogicView(actionParams.MapData,actionParams.PlayerData,actionParams.MapData.GridMap.GetAroundGridIdList(newUnit.GetSightRange(actionParams.MapData),actionParams.GridData));
newUnit.HeroTask(actionParams.MapData)?.OnExploredGrids(actionParams.MapData, newUnit, count);
foreach (var kv in actionParams.PlayerData.PlayerHeroData.HeroTaskDict) kv.Value.OnAnyExploredGrids(actionParams.MapData, newUnit, count);
//Step #7 更新所有建筑的buildingLevel(目前主要是影响kaguyaFrenchYard
Main.PlayerLogic.UpdateTerritoryAllBuildingLevel(actionParams.MapData,actionParams.PlayerData.Id);
//step #7 如果是真mapdata处理视觉
if (Main.MapData == actionParams.MapData)// && actionParams.PlayerData.Id == actionParams.MapData.PlayerMap.SelfPlayerData.Id)
{
actionParams.GridData.Renderer(actionParams.MapData)?.InstantUpdateGrid(true);
var startPos = Table.Instance.GridToWorld(actionParams.GridData);
int score = GetCost(actionParams) * 5;
actionParams.PlayerData.AddFaith(score,startPos);
AchievementDataManager.Instance.OnTrainUnit(actionParams.MapData, actionParams.PlayerData, actionParams.CityData, newUnit);
}
return true;
}
public override bool CheckCan(CommonActionParams actionParam)
{
//step #0 基础鲁棒性
if(_actionId.UnitType != UnitType.KaguyaFrenchAnimalWarrior) return false;
if (!TrainUnitActionCheckBaseData(actionParam)) return false;
//Step #1 如果不是grid产兵直接return 该兵种只能在grid产
if (actionParam.MainObjectType != MainObjectType.Grid) return false;
//Step #2 如果不再自家领地上操作 也不行
if (!TrainUnitActionCheckGridBelongPlayer(actionParam)) return false;
//step #3如果没科技 不行
if(!TrainUnitActionCheckHasTechCulture(actionParam)) return false;
//step #4 如果城市上面有敌人单位,不行(自己人是可以顶的,盟友也不行)
if (TrainUnitActionCheckEnemyUnitOnGrid(actionParam)) return false;
//step #5 如果不是在animal上面不行
if (actionParam.GridData.Resource != ResourceType.Animal) return false;
//step #6 如果没钱,不行
if (!TrainUnitActionCheckMoneyEnough(actionParam)) return false;
return true;
}
public override bool CheckShow(CommonActionParams actionParam,out ShowType showType)
{
showType = ShowType.None;
//step #0 基础鲁棒性
if(_actionId.UnitType != UnitType.KaguyaFrenchAnimalWarrior) return false;
if (!TrainUnitActionCheckBaseData(actionParam)) return false;
//Step #1 如果不是grid产兵直接return 该兵种只能在grid产
if (actionParam.MainObjectType != MainObjectType.Grid) return false;
//Step #2 如果不再自家领地上操作 也不行
if (!TrainUnitActionCheckGridBelongPlayer(actionParam)) return false;
//step #3如果没科技 不行
if(!TrainUnitActionCheckHasTechCulture(actionParam)) return false;
//step #4 如果城市上面有敌人单位,不行(自己人是可以顶的,盟友也不行)
if (TrainUnitActionCheckEnemyUnitOnGrid(actionParam)) return false;
//step #5 如果不是在animal上面不行
if (actionParam.GridData.Resource != ResourceType.Animal) return false;
//step #6 如果没钱,也可以显示
//if (!TrainUnitActionCheckMoneyEnough(actionParam)) return false;
return true;
}
}
}