785 lines
38 KiB
C#
785 lines
38 KiB
C#
/*
|
||
* @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;
|
||
}
|
||
|
||
}
|
||
}
|