2450 lines
105 KiB
C#
2450 lines
105 KiB
C#
/*
|
||
* @Author: 白哉
|
||
* @Description: 行为逻辑类
|
||
* @Date: 2025年04月10日 星期四 11:04:44
|
||
* @Modify:
|
||
*/
|
||
|
||
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Net;
|
||
using Logic.AI;
|
||
using Logic.Audio;
|
||
using Logic.CrashSight;
|
||
using Logic.Skill;
|
||
using RuntimeData;
|
||
using TH1_Core.Events;
|
||
using TH1_Core.Managers;
|
||
using TH1_Logic.Action;
|
||
using TH1_Logic.Core;
|
||
using UnityEngine;
|
||
using TH1Renderer;
|
||
using TH1Resource;
|
||
using Unity.VisualScripting;
|
||
|
||
|
||
//这里是所有BuildAction派生子类的实现模块
|
||
namespace Logic.Action
|
||
{
|
||
public enum UnitActionType
|
||
{
|
||
None,Upgrade,Recover,HEAL,Examine,Gather,Capture,Disband,ROYALFLAMES,ROYALFLAMESPRO,HeroUpgrade,
|
||
TEWIFRENCHBUFF,
|
||
MOKOUFRENCHBOOM,
|
||
KAGUYAFRENCHAROUND,
|
||
ForceDisband,
|
||
RemoveRedMist,
|
||
REMILIABUFF,
|
||
AbsorbRedMist,
|
||
REMILIAABSORB,
|
||
KANAKOSIT,
|
||
KANAKOUNSIT,
|
||
AYAMOVEAGAIN,
|
||
KomeijiRinFire,
|
||
KomeijiRinCityExp,
|
||
KomeijiBonePileBoom,
|
||
ReisenFrenchBoom,
|
||
ToggleShenlan,
|
||
CultureUnitUpgrade = 27,
|
||
ReservedReimuProtectionAttackAlly = 28,
|
||
ReimuPayClearExtermination = 29,
|
||
Raid = 30,
|
||
WarCry = 31,
|
||
KasenToggleOniForm = 33,
|
||
SuikaShakeOffMinis = 37,
|
||
SuikaCreateMiniByHp = 38,
|
||
SuikaThrowUnit = 39,
|
||
HakureiAbsorbRune = 40,
|
||
Demolish = 41,
|
||
Disperse = 42,
|
||
ClearHakureiRune = 43,
|
||
AunnPetrify = 44,
|
||
KasenRecallBeastGuide = 45,
|
||
KasenClearBeastGuide = 46,
|
||
}
|
||
|
||
public static class UnitActionUpgradeHelper
|
||
{
|
||
public static bool IsShipUpgradeTarget(UnitType unitType)
|
||
{
|
||
return unitType is UnitType.Ship or UnitType.RammerShip or UnitType.BomberShip
|
||
or UnitType.KomeijiIndianShip or UnitType.KomeijiIndianBomberShip
|
||
or UnitType.HakureiDragonship;
|
||
}
|
||
|
||
public static bool CanUnitUpgradeToShip(UnitData unit, UnitType targetUnitType)
|
||
{
|
||
if (unit == null) return false;
|
||
return unit.UnitFullType.UnitType switch
|
||
{
|
||
UnitType.Boat => targetUnitType is UnitType.Ship or UnitType.RammerShip or UnitType.BomberShip
|
||
or UnitType.KomeijiIndianShip or UnitType.KomeijiIndianBomberShip,
|
||
UnitType.HakureiLongship => targetUnitType is UnitType.Ship or UnitType.BomberShip
|
||
or UnitType.HakureiDragonship,
|
||
_ => false
|
||
};
|
||
}
|
||
|
||
public static bool TryGetCultureUnitUpgradeCost(UnitData unit, out int cost)
|
||
{
|
||
cost = 0;
|
||
if (unit == null) return false;
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitFullType, out _)) return false;
|
||
cost = (int)unit.GetTotalCostWithCarry();
|
||
return true;
|
||
}
|
||
|
||
public static bool ApplyOfficerUpgrade(MapData map, UnitData unit)
|
||
{
|
||
if (map == null || unit == null) return false;
|
||
unit.SetOfficer();
|
||
unit.Health = unit.GetMaxHealth();
|
||
unit.Renderer(map)?.InstantUpdateUnit(true);
|
||
if (unit.Grid(map)?.InMainSight() ?? false)
|
||
AudioManager.Instance.PlayAudio("SFX/UNIT_levelup");
|
||
|
||
if (map == Main.MapData && unit.Player(map) == Main.MapData.PlayerMap.SelfPlayerData)
|
||
{
|
||
EventManager.Publish(new ShowUINotifyMoment()
|
||
{
|
||
MomentSubType = MomentSubType.BattleLevelup,
|
||
Empire = Main.MapData.PlayerMap.SelfPlayerData.Empire
|
||
});
|
||
}
|
||
return true;
|
||
}
|
||
}
|
||
|
||
public static class UnitActionRecoverHelper
|
||
{
|
||
public const int FriendlyTerritoryRecoverValue = 4;
|
||
public const int OutsideTerritoryRecoverValue = 2;
|
||
|
||
public static int GetRecoverValue(MapData map, PlayerData player, GridData grid)
|
||
{
|
||
if (map == null || player == null || grid == null) return OutsideTerritoryRecoverValue;
|
||
if (!map.GetPlayerDataByTerritoryGridId(grid.Id, out var terrPlayerData)) return OutsideTerritoryRecoverValue;
|
||
return map.SameUnion(terrPlayerData.Id, player.Id)
|
||
? FriendlyTerritoryRecoverValue
|
||
: OutsideTerritoryRecoverValue;
|
||
}
|
||
|
||
public static int GetRecoverValue(MapData map, UnitData unit)
|
||
{
|
||
if (map == null || unit == null || !unit.Grid(map, out var grid)) return OutsideTerritoryRecoverValue;
|
||
return GetRecoverValue(map, unit.Player(map), grid);
|
||
}
|
||
|
||
public static int ExecuteRecover(MapData map, UnitData unit)
|
||
{
|
||
if (map == null || unit == null) return 0;
|
||
return Main.UnitLogic.RecoverHealth_Legacy(map, null, unit, GetRecoverValue(map, unit));
|
||
}
|
||
}
|
||
|
||
//UnitAction单位行动逻辑类
|
||
public class UnitActionAction : ActionLogicBase
|
||
{
|
||
public UnitActionAction(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
//鲁棒性判断
|
||
if (actionParams.UnitData == null) return false;
|
||
var unitData = actionParams.UnitData;
|
||
var playerData = actionParams.PlayerData;
|
||
if (playerData == null)
|
||
if (!actionParams.MapData.GetPlayerDataByUnitId(actionParams.UnitData.Id, out playerData))
|
||
return false;
|
||
if (!actionParams.MapData.GetGridDataByUnitId(actionParams.UnitData.Id, out var gridData))
|
||
return false;
|
||
//处理 ToggleShenlan:纯调试/视觉效果,不消耗行动点也不扣费
|
||
if (_actionId.UnitActionType == UnitActionType.ToggleShenlan)
|
||
{
|
||
if (unitData.GetSkill(SkillType.Shenlan, out _))
|
||
{
|
||
unitData.RemoveSkill(SkillType.Shenlan, actionParams.MapData);
|
||
}
|
||
else
|
||
{
|
||
unitData.AddOrOverrideSkill(SkillType.Shenlan, actionParams.MapData, unitData.Id);
|
||
// 仅在获得 Shenlan 时播放 VFX,取消时不播
|
||
gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Dancing));
|
||
gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
}
|
||
unitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
BoatUnitOnLandDiagnostic.ReportIfNeeded(actionParams.MapData, unitData, gridData, $"UnitAction:{_actionId.UnitActionType}");
|
||
return true;
|
||
}
|
||
if (_actionId.UnitActionType == UnitActionType.Capture)
|
||
{
|
||
//处理捕获city的情况
|
||
if (actionParams.MapData.GetCityDataByGid(gridData.Id, out var cityData))
|
||
{
|
||
//Step #1 先更新unit 状态
|
||
actionParams.UnitData.ClearActionPoint();
|
||
actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
|
||
//Step #2 再处理占领城市的所有logic & view
|
||
Main.PlayerLogic.OccupyCity_LogicView(actionParams.MapData, actionParams.UnitData, cityData);
|
||
|
||
//Step #3 再更新heroTask
|
||
unitData.HeroTask(actionParams.MapData)?.OnCaptureCity(actionParams.MapData);
|
||
foreach (var item in actionParams.PlayerData.MomentData.Items)
|
||
{
|
||
item.OnCaptureCity(actionParams.MapData, actionParams.PlayerData, cityData);
|
||
}
|
||
var player = unitData?.Player(actionParams.MapData);
|
||
if (player != null)
|
||
{
|
||
foreach (var kv in player.PlayerHeroData.HeroTaskDict)
|
||
kv.Value.OnPlayerCaptureCity(actionParams.MapData);
|
||
}
|
||
BoatUnitOnLandDiagnostic.ReportIfNeeded(actionParams.MapData, unitData, gridData, $"UnitAction:{_actionId.UnitActionType}");
|
||
return true;
|
||
}
|
||
//处理占领村庄的情况
|
||
else
|
||
{
|
||
gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
cityData = Main.PlayerLogic.OccupyVillage_LogicOnly(actionParams.MapData,actionParams.UnitData,gridData);
|
||
|
||
//Step #3 再更新heroTask
|
||
unitData.HeroTask(actionParams.MapData)?.OnCaptureVillage(actionParams.MapData);
|
||
var player = unitData?.Player(actionParams.MapData);
|
||
if (player != null)
|
||
{
|
||
foreach (var kv in player.PlayerHeroData.HeroTaskDict)
|
||
kv.Value.OnPlayerCaptureVillage(actionParams.MapData);
|
||
}
|
||
|
||
//Step #3.5 如果玩家有视野,播放音效
|
||
if(gridData.InMainSight())
|
||
AudioManager.Instance.PlayAudio("SFX/UNIT_capture");
|
||
|
||
//处理占领城市的特效(所有领土会升起一面旗帜
|
||
HashSet<uint> gridList = new HashSet<uint>();
|
||
cityData.Territory.GetAllTerritoryArea(gridList);
|
||
foreach (var gd in gridList)
|
||
{
|
||
if (actionParams.MapData.GridMap.GetGridDataByGid(gd, out var gdd))
|
||
{
|
||
//设置gdd格子的VFXrendermark
|
||
var t = new GridVFXParams(GridVFXType.Flag);
|
||
t.CivId = playerData.PlayerCivId;
|
||
|
||
gdd.Renderer(actionParams.MapData)?.PlayVFXInSight(t);
|
||
}
|
||
|
||
}
|
||
|
||
actionParams.UnitData.ClearActionPoint();
|
||
unitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
//Step #5 处理NotifyMoment
|
||
if (actionParams.UnitData.Player(actionParams.MapData) == Main.MapData.PlayerMap.SelfPlayerData)
|
||
{
|
||
EventManager.Publish(new ShowUINotifyMoment()
|
||
{
|
||
MomentSubType = MomentSubType.BattleCaptureVillage,
|
||
Empire = Main.MapData.PlayerMap.SelfPlayerData.Empire
|
||
});
|
||
}
|
||
BoatUnitOnLandDiagnostic.ReportIfNeeded(actionParams.MapData, unitData, gridData, $"UnitAction:{_actionId.UnitActionType}");
|
||
return true;
|
||
}
|
||
}
|
||
|
||
if (_actionId.UnitActionType == UnitActionType.Upgrade)
|
||
{
|
||
return UnitActionUpgradeHelper.ApplyOfficerUpgrade(actionParams.MapData, actionParams.UnitData);
|
||
}
|
||
|
||
//处理ship
|
||
if (UnitActionUpgradeHelper.IsShipUpgradeTarget(_actionId.UnitType))
|
||
{
|
||
if (!UnitActionUpgradeHelper.CanUnitUpgradeToShip(actionParams.UnitData, _actionId.UnitType))
|
||
return false;
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(_actionId.UnitType,GiantType.None,0, out var info ))
|
||
return false;
|
||
if (actionParams.PlayerData.PlayerCoin < info.Cost)
|
||
return false;
|
||
actionParams.PlayerData.SpendCoin(info.Cost);
|
||
Main.UnitLogic.UnitTypeTransform(actionParams.MapData,actionParams.UnitData,_actionId.UnitType);
|
||
Main.PlayerLogic.UpdateSight_LogicView(actionParams.MapData,actionParams.PlayerData,actionParams.MapData.GridMap.GetAroundGridIdList(unitData.GetSightRange(actionParams.MapData),gridData));
|
||
actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
actionParams.UnitData.Grid(actionParams.MapData)?.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
//Step #3.5 如果玩家有视野,播放音效
|
||
if(actionParams.UnitData.Grid(actionParams.MapData)?.InMainSight() ?? false)
|
||
AudioManager.Instance.PlayAudio("SFX/UNIT_levelup");
|
||
BoatUnitOnLandDiagnostic.ReportIfNeeded(actionParams.MapData, unitData, gridData, $"UnitAction:{_actionId.UnitType}");
|
||
return true;
|
||
}
|
||
|
||
|
||
//剩下的都需要CP,消耗CP
|
||
//用ret做记录
|
||
bool ret = false;
|
||
|
||
//处理disband
|
||
if (_actionId.UnitActionType == UnitActionType.Disband)
|
||
{
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(actionParams.UnitData.UnitFullType, out _))
|
||
return false;
|
||
var earn = (int)(actionParams.UnitData.GetTotalCostWithCarry() * 0.5f);
|
||
|
||
var startPos = Table.Instance.GridToWorld(gridData);
|
||
actionParams.PlayerData.AddCoin(earn,startPos);
|
||
|
||
if (actionParams.MapData.IsCurrentShowMap())
|
||
{
|
||
//播放雾效
|
||
gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
actionParams.UnitData.Renderer(Main.MapData)?.Die();
|
||
//更新原来所属的城市的cityinfo
|
||
}
|
||
|
||
var city = actionParams.UnitData.City(actionParams.MapData);
|
||
Main.UnitLogic.UnitUnnaturalDie(actionParams.MapData,actionParams.UnitData);
|
||
if (city != null)
|
||
{
|
||
ret = true;
|
||
}
|
||
}
|
||
|
||
if (_actionId.UnitActionType == UnitActionType.Demolish
|
||
|| _actionId.UnitActionType == UnitActionType.Disperse)
|
||
{
|
||
var unitRenderer = actionParams.UnitData.Renderer(actionParams.MapData);
|
||
|
||
if (actionParams.MapData.IsCurrentShowMap())
|
||
{
|
||
gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
unitRenderer?.Die();
|
||
}
|
||
|
||
Main.UnitLogic.UnitUnnaturalDie(actionParams.MapData, actionParams.UnitData);
|
||
BoatUnitOnLandDiagnostic.ReportIfNeeded(actionParams.MapData, actionParams.UnitData, gridData, $"UnitAction:{_actionId.UnitActionType}");
|
||
return true;
|
||
}
|
||
|
||
//处理recover
|
||
if (_actionId.UnitActionType == UnitActionType.Recover)
|
||
{
|
||
//如果有KomeijiFear,清除所有恐惧层数,但不恢复血量
|
||
if (actionParams.UnitData.GetSkill(SkillType.KomeijiFear, out _))
|
||
{
|
||
actionParams.UnitData.RemoveSkill(SkillType.KomeijiFear, actionParams.MapData);
|
||
ret = true;
|
||
actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
}
|
||
else
|
||
{
|
||
int recoverV = UnitActionRecoverHelper.GetRecoverValue(actionParams.MapData,
|
||
actionParams.PlayerData, gridData);
|
||
Main.UnitLogic.RecoverHealth_Legacy(actionParams.MapData, null, actionParams.UnitData, recoverV);
|
||
ret = true;
|
||
if(actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true) ?? false)
|
||
gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Heal));
|
||
}
|
||
}
|
||
|
||
//处理gather
|
||
if (_actionId.UnitActionType == UnitActionType.Gather)
|
||
{
|
||
gridData.Resource = ResourceType.None;
|
||
actionParams.PlayerData.AddCoin(10,Table.Instance.GridToWorld(gridData));
|
||
gridData.Renderer(actionParams.MapData)?.InstantUpdateGrid(true);
|
||
ret = true;
|
||
if (actionParams.MapData == Main.MapData && actionParams.MapData.PlayerMap.SelfPlayerId == playerData.Id)
|
||
{
|
||
gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
}
|
||
}
|
||
|
||
|
||
//处理examine
|
||
if (_actionId.UnitActionType == UnitActionType.Examine)
|
||
{
|
||
unitData.HeroTask(actionParams.MapData)?.OnTreasure(actionParams.MapData);
|
||
var player = unitData?.Player(actionParams.MapData);
|
||
if (player != null)
|
||
{
|
||
foreach (var kv in player.PlayerHeroData.HeroTaskDict)
|
||
kv.Value.OnPlayerTreasure(actionParams.MapData);
|
||
}
|
||
gridData.Resource = ResourceType.None;
|
||
gridData.Renderer(actionParams.MapData)?.InstantUpdateGrid(true);
|
||
//播放雾效
|
||
if (actionParams.MapData == Main.MapData && actionParams.MapData.PlayerMap.SelfPlayerId == playerData.Id)
|
||
{
|
||
gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
AudioManager.Instance.PlayAudio("SFX/UNIT_treasure");
|
||
}
|
||
|
||
var optionGroup = new ActionOptionGroup(gridData.Id, gridData.Id, unitData.Id);
|
||
var firstOption = CreateTreasureActionOption(actionParams, gridData, 0);
|
||
optionGroup.ActionOptionList.Add(firstOption);
|
||
optionGroup.ActionOptionList.Add(CreateDistinctTreasureActionOption(actionParams, gridData, 1, firstOption.ActionId));
|
||
actionParams.PlayerData.AddTreasureActionOptionGroup(optionGroup);
|
||
PresentationManager.EnqueuePendingTreasureChoice(actionParams.MapData, actionParams.PlayerData);
|
||
ret = true;
|
||
//Step #4 Moment
|
||
if (actionParams.MapData == Main.MapData && actionParams.UnitData.Player(actionParams.MapData) ==
|
||
Main.MapData.PlayerMap.SelfPlayerData)
|
||
{
|
||
EventManager.Publish(new ShowUINotifyMoment()
|
||
{
|
||
MomentSubType = MomentSubType.ExploitTreasure,
|
||
Empire = Main.MapData.PlayerMap.SelfPlayerData.Empire
|
||
});
|
||
}
|
||
}
|
||
|
||
|
||
if (ret)
|
||
{
|
||
actionParams.UnitData.ClearActionPoint();
|
||
actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
BoatUnitOnLandDiagnostic.ReportIfNeeded(actionParams.MapData, actionParams.UnitData, gridData, $"UnitAction:{_actionId.UnitActionType}");
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
private ActionOption CreateTreasureActionOption(CommonActionParams actionParams, GridData sourceGrid, int optionIndex)
|
||
{
|
||
var random = actionParams.MapData.Net.GetRandom(actionParams.MapData);
|
||
var rewardType = (TreasureActionRewardType)random.Next((int)TreasureActionRewardType.Coin, (int)TreasureActionRewardType.CityExp + 1);
|
||
return CreateTreasureActionOption(actionParams, sourceGrid, optionIndex, rewardType);
|
||
}
|
||
|
||
private ActionOption CreateDistinctTreasureActionOption(CommonActionParams actionParams, GridData sourceGrid, int optionIndex, CommonActionId excludedActionId)
|
||
{
|
||
var option = CreateTreasureActionOption(actionParams, sourceGrid, optionIndex);
|
||
if (option.ActionId != excludedActionId) return option;
|
||
|
||
var fallbackRewardTypes = new[]
|
||
{
|
||
TreasureActionRewardType.Coin,
|
||
TreasureActionRewardType.Culture,
|
||
TreasureActionRewardType.CityExp,
|
||
TreasureActionRewardType.Unit,
|
||
TreasureActionRewardType.Tech,
|
||
};
|
||
foreach (var fallbackRewardType in fallbackRewardTypes)
|
||
{
|
||
option = CreateTreasureActionOption(actionParams, sourceGrid, optionIndex, fallbackRewardType);
|
||
if (option.ActionId != excludedActionId) return option;
|
||
}
|
||
|
||
return option;
|
||
}
|
||
|
||
private ActionOption CreateTreasureActionOption(CommonActionParams actionParams, GridData sourceGrid, int optionIndex, TreasureActionRewardType rewardType)
|
||
{
|
||
var option = new ActionOption
|
||
{
|
||
OptionIndex = optionIndex,
|
||
ActionId = new CommonActionId
|
||
{
|
||
ActionType = CommonActionType.PlayerAction,
|
||
PlayerActionType = GetTreasureRewardActionType(rewardType),
|
||
},
|
||
Param = new CommonActionParams(actionParams.MapData, actionParams.PlayerData, mainObjectType: MainObjectType.Player)
|
||
{
|
||
GridId = sourceGrid.Id,
|
||
},
|
||
RewardType = rewardType,
|
||
};
|
||
|
||
if (rewardType == TreasureActionRewardType.Coin)
|
||
{
|
||
option.Value = 10;
|
||
}
|
||
else if (rewardType == TreasureActionRewardType.Unit)
|
||
{
|
||
option.UnitFullType = sourceGrid.Terrain == TerrainType.Land
|
||
? new UnitFullType(UnitType.Swordsman, GiantType.None, 0)
|
||
: new UnitFullType(UnitType.RammerShip, GiantType.None, 0);
|
||
}
|
||
else if (rewardType == TreasureActionRewardType.Tech)
|
||
{
|
||
if (TryGetRandomTreasureTech(actionParams, out var techType))
|
||
{
|
||
option.TechType = techType;
|
||
}
|
||
else
|
||
{
|
||
option.RewardType = TreasureActionRewardType.Coin;
|
||
option.ActionId.PlayerActionType = GetTreasureRewardActionType(option.RewardType);
|
||
option.Value = 10;
|
||
}
|
||
}
|
||
else if (rewardType == TreasureActionRewardType.Culture)
|
||
{
|
||
option.Value = 4;
|
||
}
|
||
else if (rewardType == TreasureActionRewardType.CityExp)
|
||
{
|
||
option.Value = 3;
|
||
}
|
||
|
||
return option;
|
||
}
|
||
|
||
private static PlayerActionType GetTreasureRewardActionType(TreasureActionRewardType rewardType)
|
||
{
|
||
return rewardType switch
|
||
{
|
||
TreasureActionRewardType.Coin => PlayerActionType.TreasureGainCoin,
|
||
TreasureActionRewardType.Unit => PlayerActionType.TreasureGainUnit,
|
||
TreasureActionRewardType.Tech => PlayerActionType.TreasureGainTech,
|
||
TreasureActionRewardType.Culture => PlayerActionType.TreasureGainCulture,
|
||
TreasureActionRewardType.CityExp => PlayerActionType.TreasureGainCityExp,
|
||
_ => PlayerActionType.TreasureGainCoin,
|
||
};
|
||
}
|
||
|
||
private bool TryGetRandomTreasureTech(CommonActionParams actionParams, out TechType techType)
|
||
{
|
||
techType = TechType.None;
|
||
if (!Table.Instance.PlayerDataAssets.GetPlayerInfo(actionParams.PlayerData, out var playerInfo)) return false;
|
||
|
||
var canLearnTechList = new List<TechType>();
|
||
foreach (var candidate in playerInfo.TechPool)
|
||
{
|
||
if (actionParams.PlayerData.TechTree.CheckIfTechCanLearn(candidate))
|
||
canLearnTechList.Add(candidate);
|
||
}
|
||
|
||
if (canLearnTechList.Count <= 0) return false;
|
||
var index = actionParams.MapData.Net.GetRandom(actionParams.MapData).Next(0, canLearnTechList.Count);
|
||
techType = canLearnTechList[index];
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
|
||
//鲁棒性判断
|
||
if (actionParams.UnitData == null) return false;
|
||
if (actionParams.PlayerData == null) return false;
|
||
if (!actionParams.MapData.GetGridDataByUnitId(actionParams.UnitData.Id, out var gridData))
|
||
return false;
|
||
//如果unit不是player的,退出
|
||
if(!actionParams.MapData.GetPlayerDataByUnitId(actionParams.UnitData.Id, out var playerData) ||
|
||
playerData != actionParams.PlayerData)
|
||
return false;
|
||
//ToggleShenlan 是调试/视觉切换,不需要钱/科技/CP,只要属于自己即可
|
||
if (_actionId.UnitActionType == UnitActionType.ToggleShenlan)
|
||
return true;
|
||
if (_actionId.UnitActionType == UnitActionType.Demolish)
|
||
{
|
||
return CheckDemolishEnabled(actionParams);
|
||
}
|
||
|
||
if (_actionId.UnitActionType == UnitActionType.Disperse)
|
||
{
|
||
return CheckDisperseEnabled(actionParams);
|
||
}
|
||
|
||
//判断钱够不够
|
||
if (GetCost(actionParams) > actionParams.PlayerData.PlayerCoin)
|
||
return false;
|
||
//如果不具备科技
|
||
if (!actionParams.PlayerData.TechTree.CheckActionCan(_actionId))
|
||
return false;
|
||
|
||
if (_actionId.UnitActionType == UnitActionType.Upgrade)
|
||
{
|
||
//鲁棒性处理
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(actionParams.UnitData.UnitFullType, out var info))
|
||
return false;
|
||
return actionParams.UnitData.IsCanBeOfficer();
|
||
}
|
||
|
||
//先处理不需要CP的 Upgrade UnitShip UnitRammerShip UnitBattleShip 这4个
|
||
if (UnitActionUpgradeHelper.IsShipUpgradeTarget(_actionId.UnitType))
|
||
{
|
||
|
||
if(!UnitActionUpgradeHelper.CanUnitUpgradeToShip(actionParams.UnitData, _actionId.UnitType))
|
||
return false;
|
||
|
||
if (!actionParams.MapData.GetPlayerDataByTerritoryGridId(gridData.Id, out var player1))
|
||
return false;
|
||
if(!actionParams.MapData.SameUnion(player1.Id,actionParams.PlayerData.Id))
|
||
return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
//剩下的都需要CP,如果Unit有没有CP了,return false
|
||
if (actionParams.UnitData.GetActionPoint(ActionPointType.Capture) <= 0)
|
||
return false;
|
||
|
||
//处理capture
|
||
if (_actionId.UnitActionType == UnitActionType.Capture)
|
||
{
|
||
//如果是占领别的城市
|
||
if (actionParams.MapData.GetCityDataByGid(gridData.Id, out var cityData))
|
||
{
|
||
actionParams.MapData.GetPlayerDataByCityId(cityData.Id,out var playerId1);
|
||
actionParams.MapData.GetPlayerDataByUnitId(actionParams.UnitData.Id,out var playerId2);
|
||
return playerId1 != playerId2;
|
||
}
|
||
//如果是占领村庄
|
||
else
|
||
{
|
||
return gridData.Resource == ResourceType.CityCenter;
|
||
}
|
||
}
|
||
|
||
//处理disband
|
||
if (_actionId.UnitActionType == UnitActionType.Disband)
|
||
{
|
||
if ((actionParams.UnitData.UnitType is UnitType.Giant or UnitType.GiantJuggernaut or UnitType.KaguyaFrenchReisenIllusion or UnitType.KaguyaFrenchMokouEgg) || actionParams.UnitData.CarryUnitType == UnitType.Giant)
|
||
return false;
|
||
return true;
|
||
}
|
||
|
||
|
||
//处理recover
|
||
if (_actionId.UnitActionType == UnitActionType.Recover)
|
||
{
|
||
if (actionParams.UnitData.GetSkill(SkillType.KomeijiFear, out _))
|
||
return true;
|
||
if (actionParams.UnitData.GetSkill(SkillType.SAKUYATIRED, out _))
|
||
return true;
|
||
if (actionParams.UnitData.Health < actionParams.UnitData.GetMaxHealth())
|
||
return true;
|
||
return false;
|
||
}
|
||
|
||
//处理gather
|
||
if (_actionId.UnitActionType == UnitActionType.Gather)
|
||
return gridData.Resource == ResourceType.Starfish;
|
||
|
||
//处理examine
|
||
if (_actionId.UnitActionType == UnitActionType.Examine)
|
||
return gridData.Resource == ResourceType.Treasure;
|
||
|
||
//处理战技ROYALFLAMES
|
||
if (_actionId.UnitActionType == UnitActionType.ROYALFLAMES)
|
||
{
|
||
if (!actionParams.UnitData.GetSkill(SkillType.ROYALFLAMES, out var skillInfo))
|
||
return false;
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
public override bool CheckShow(CommonActionParams actionParams,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
//鲁棒性判断
|
||
if (actionParams.UnitData == null) return false;
|
||
if (actionParams.PlayerData == null) return false;
|
||
if (!actionParams.MapData.GetGridDataByUnitId(actionParams.UnitData.Id, out var gridData))
|
||
return false;
|
||
//如果unit不是player的,退出
|
||
if(!actionParams.MapData.GetPlayerDataByUnitId(actionParams.UnitData.Id, out var playerData) ||
|
||
playerData.Id != actionParams.PlayerData.Id)
|
||
return false;
|
||
//判断钱够不够 checkshow中 即使钱不够,也可以显示的
|
||
//if (GetCost() > actionParams.PlayerData.PlayerWealth)
|
||
// return false;
|
||
|
||
//ToggleShenlan:调试技能,永远不在ActionArea中显示(仅靠InputLogic连点触发)
|
||
if (_actionId.UnitActionType == UnitActionType.ToggleShenlan)
|
||
return false;
|
||
if (_actionId.UnitActionType == UnitActionType.Demolish)
|
||
{
|
||
return CheckDemolishEnabled(actionParams);
|
||
}
|
||
|
||
if (_actionId.UnitActionType == UnitActionType.Disperse)
|
||
{
|
||
return CheckDisperseEnabled(actionParams);
|
||
}
|
||
|
||
//如果不具备科技
|
||
if (!actionParams.PlayerData.TechTree.CheckActionCan(_actionId))
|
||
return false;
|
||
|
||
//先处理不需要CP的 Upgrade UnitShip UnitRammerShip UnitBattleShip 这4个
|
||
if (_actionId.UnitActionType == UnitActionType.Upgrade)
|
||
{
|
||
//鲁棒性处理
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(actionParams.UnitData.UnitType,
|
||
actionParams.UnitData.GiantType, actionParams.UnitData.UnitLevel,out var info))
|
||
return false;
|
||
if (actionParams.UnitData.IsCanBeOfficer()) return true;
|
||
return false;
|
||
}
|
||
|
||
|
||
if (UnitActionUpgradeHelper.IsShipUpgradeTarget(_actionId.UnitType))
|
||
{
|
||
|
||
if(!UnitActionUpgradeHelper.CanUnitUpgradeToShip(actionParams.UnitData, _actionId.UnitType))
|
||
return false;
|
||
|
||
if (!actionParams.MapData.GetPlayerDataByTerritoryGridId(gridData.Id, out var player1))
|
||
return false;
|
||
if(!actionParams.MapData.SameUnion(player1.Id,actionParams.PlayerData.Id))
|
||
return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
//剩下的都需要CP,如果Unit有没有CP了,return false
|
||
if (actionParams.UnitData.GetActionPoint(ActionPointType.Capture) <= 0)
|
||
return false;
|
||
|
||
//处理capture
|
||
if (_actionId.UnitActionType == UnitActionType.Capture)
|
||
{
|
||
//如果是占领别的城市
|
||
if (actionParams.MapData.GetCityDataByGid(gridData.Id, out var cityData))
|
||
{
|
||
actionParams.MapData.GetPlayerDataByCityId(cityData.Id,out var playerId1);
|
||
actionParams.MapData.GetPlayerDataByUnitId(actionParams.UnitData.Id,out var playerId2);
|
||
return playerId1 != playerId2;
|
||
}
|
||
//如果是占领村庄
|
||
else
|
||
{
|
||
return gridData.Resource == ResourceType.CityCenter;
|
||
}
|
||
}
|
||
|
||
//处理disband
|
||
if (_actionId.UnitActionType == UnitActionType.Disband)
|
||
{
|
||
if ((actionParams.UnitData.UnitType is UnitType.Giant or UnitType.GiantJuggernaut or UnitType.KaguyaFrenchReisenIllusion or UnitType.KaguyaFrenchMokouEgg) || actionParams.UnitData.CarryUnitType == UnitType.Giant)
|
||
return false;
|
||
return true;
|
||
}
|
||
|
||
|
||
//处理recover
|
||
if (_actionId.UnitActionType == UnitActionType.Recover)
|
||
{
|
||
if (actionParams.UnitData.GetSkill(SkillType.KomeijiFear, out _))
|
||
return true;
|
||
if (actionParams.UnitData.GetSkill(SkillType.SAKUYATIRED, out _))
|
||
return true;
|
||
if (actionParams.UnitData.Health < actionParams.UnitData.GetMaxHealth())
|
||
return true;
|
||
return false;
|
||
}
|
||
|
||
//处理gather
|
||
if (_actionId.UnitActionType == UnitActionType.Gather)
|
||
return gridData.Resource == ResourceType.Starfish;
|
||
|
||
//处理examine
|
||
if (_actionId.UnitActionType == UnitActionType.Examine)
|
||
return gridData.Resource == ResourceType.Treasure;
|
||
|
||
//处理战技ROYALFLAMES
|
||
if (_actionId.UnitActionType == UnitActionType.ROYALFLAMES)
|
||
{
|
||
|
||
if (!actionParams.UnitData.GetSkill(SkillType.ROYALFLAMES, out var skillInfo))
|
||
return false;
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
//付钱
|
||
protected bool UnitActionPayMoney(CommonActionParams actionParam)
|
||
{
|
||
if (actionParam.PlayerData.PlayerCoin - GetCost(actionParam) < 0) return false;
|
||
actionParam.PlayerData.SpendCoin(GetCost(actionParam));
|
||
return true;
|
||
}
|
||
|
||
//确认是否满足基本信息,并且补全actionParam(主要是补充unit所处的grid)
|
||
protected bool UnitActionCheckBaseInfo(CommonActionParams actionParam)
|
||
{
|
||
//鲁棒性判断,必须包含unitData和playerData,表明是哪个玩家正在操作哪个单位
|
||
if (actionParam.UnitData == null) return false;
|
||
if (actionParam.PlayerData == null) return false;
|
||
if (!actionParam.MapData.GetGridDataByUnitId(actionParam.UnitData.Id, out var grid)) return false;
|
||
actionParam.GridData = grid;
|
||
return true;
|
||
}
|
||
protected bool UnitActionCheckUnitBelongPlayer(CommonActionParams actionParam)
|
||
{
|
||
//如果unit不是player的,退出
|
||
if(!actionParam.MapData.GetPlayerDataByUnitId(actionParam.UnitData.Id, out var playerData) ||
|
||
playerData != actionParam.PlayerData)
|
||
return false;
|
||
return true;
|
||
}
|
||
//确认是否有科技
|
||
protected bool UnitActionCheckHasTech(CommonActionParams actionParam)
|
||
{
|
||
//如果没有对应科技,return false
|
||
if (!actionParam.PlayerData.TechTree.CheckActionCan(_actionId))
|
||
return false;
|
||
return true;
|
||
}
|
||
|
||
//确认是否有钱
|
||
protected bool UnitActionCheckHasMoney(CommonActionParams actionParams)
|
||
{
|
||
//判断钱够不够
|
||
if (GetCost(actionParams) > actionParams.PlayerData.PlayerCoin)
|
||
return false;
|
||
return true;
|
||
|
||
}
|
||
|
||
//确认unit是否有CP
|
||
protected bool UnitActionCheckUnitHasCP(CommonActionParams actionParam)
|
||
{
|
||
if (actionParam.UnitData == null || actionParam.UnitData.GetActionPoint(ActionPointType.Capture) <= 0)
|
||
return false;
|
||
return true;
|
||
}
|
||
|
||
//确认unit的UnitTypeData的EnableActions是否包含当前actionId
|
||
protected bool CheckUnitEnableAction(CommonActionParams actionParam)
|
||
{
|
||
if (actionParam.UnitData == null) return false;
|
||
if (_actionId.UnitActionType == UnitActionType.Demolish
|
||
&& HakureiNorwayHeroSkillUtil.IsSumirekoOccultOrb(actionParam.UnitData))
|
||
return true;
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(actionParam.UnitData.UnitFullType, out var info))
|
||
return false;
|
||
if (!info.EnableAction || info.EnableActions == null) return false;
|
||
foreach (var enabledId in info.EnableActions)
|
||
{
|
||
if (enabledId == _actionId)
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
//确认unit是否拥有且能生效这个skill
|
||
protected bool UnitActionCheckUnitHasSkill(CommonActionParams actionParam)
|
||
{
|
||
//将unitActionType转化为skillType
|
||
if (!Enum.TryParse(_actionId.UnitActionType.ToString(), out SkillType skillType)) return false;
|
||
if (actionParam.UnitData == null || !actionParam.UnitData.HasEffectiveSkill(skillType, out var _)) return false;
|
||
return true;
|
||
}
|
||
|
||
protected bool CheckDemolishEnabled(CommonActionParams actionParam)
|
||
{
|
||
return actionParam.UnitData != null
|
||
&& (HakureiNorwayHeroSkillUtil.IsSumirekoOccultOrb(actionParam.UnitData)
|
||
|| CheckUnitEnableAction(actionParam));
|
||
}
|
||
|
||
protected bool CheckDisperseEnabled(CommonActionParams actionParam)
|
||
{
|
||
return actionParam.UnitData != null
|
||
&& actionParam.UnitData.HasEffectiveSkill(SkillType.Undead, out _)
|
||
&& CheckUnitEnableAction(actionParam);
|
||
}
|
||
|
||
}
|
||
|
||
public class UnitActionRaid : UnitActionAction
|
||
{
|
||
private const int BaseRaidCoin = 1;
|
||
|
||
public UnitActionRaid(CommonActionId id) : base(id)
|
||
{
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
if (!TryGetRaidTarget(actionParams, out var city, out var cityPlayer, out var grid)) return false;
|
||
var unit = actionParams.UnitData;
|
||
var player = actionParams.PlayerData;
|
||
var remaining = Main.CityLogic.GetCityRaidRemainingCoin(actionParams.MapData, city);
|
||
if (remaining <= 0) return false;
|
||
|
||
int amount = GetRaidAmount(actionParams, cityPlayer, remaining);
|
||
if (amount <= 0) return false;
|
||
|
||
Main.CityLogic.AddCityRaidedAmount(actionParams.MapData, city, amount);
|
||
player.AddCoin(amount, grid);
|
||
HakureiEinherjarCounter.TryAddPlayerPointFromVikingAction(actionParams.MapData, player);
|
||
ConsumeRaidDoubleMarker(actionParams.MapData, unit);
|
||
unit.ClearActionPoint();
|
||
unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
if (!HasRaidUnlock(actionParams)) return false;
|
||
return TryGetRaidTarget(actionParams, out _, out _, out _);
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams, out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParams);
|
||
}
|
||
|
||
private static bool TryGetRaidTarget(CommonActionParams actionParams, out CityData city,
|
||
out PlayerData cityPlayer, out GridData grid)
|
||
{
|
||
city = null;
|
||
cityPlayer = null;
|
||
grid = null;
|
||
var map = actionParams?.MapData;
|
||
var unit = actionParams?.UnitData;
|
||
var player = actionParams?.PlayerData;
|
||
if (map == null || unit == null || player == null) return false;
|
||
if (!CanUseRaid(actionParams.MapData, unit)) return false;
|
||
if (!HasRaidActionPoint(unit)) return false;
|
||
if (!unit.Grid(map, out grid)) return false;
|
||
if (!map.GetCityDataByTerritoryGid(grid.Id, out city)) return false;
|
||
if (!map.GetPlayerDataByCityId(city.Id, out cityPlayer)) return false;
|
||
if (map.SameUnionOrJustBreakUnion(player.Id, cityPlayer.Id)) return false;
|
||
return Main.CityLogic.GetCityRaidRemainingCoin(map, city) > 0;
|
||
}
|
||
|
||
private static bool HasRaidActionPoint(UnitData unit)
|
||
{
|
||
if (unit == null || unit.IsLimitActionPoint()) return false;
|
||
return unit.ActionPoint.GetValueOrDefault(ActionPointType.Attack, 0) > 0
|
||
|| unit.ActionPoint.GetValueOrDefault(ActionPointType.Common, 0) > 0;
|
||
}
|
||
|
||
private static bool HasRaidUnlock(CommonActionParams actionParams)
|
||
{
|
||
var unit = actionParams?.UnitData;
|
||
var player = actionParams?.PlayerData;
|
||
if (unit == null || player?.TechTree == null) return false;
|
||
if (!CanUseRaid(actionParams.MapData, unit)) return false;
|
||
if (unit.HasEffectiveSkill(SkillType.ValhallaOath, out _)) return true;
|
||
if (!player.TechTree.CheckIfHasTechAtom(TechAtom.HakureiNorseGods)) return false;
|
||
return Table.Instance.TechDataAssets.GetTechAtomInfo(TechAtom.HakureiNorseGods, out var atomInfo)
|
||
&& atomInfo.IsAddSkill
|
||
&& atomInfo.AddSkillType == SkillType.ValhallaOath
|
||
&& (atomInfo.CheckUnitCondition(actionParams.MapData, unit)
|
||
|| unit.UnitType == UnitType.SuikaMini);
|
||
}
|
||
|
||
private static bool CanUseRaid(MapData map, UnitData unit)
|
||
{
|
||
return unit != null
|
||
&& (unit.IsRegularLandAndPortUnit(map)
|
||
|| unit.UnitType == UnitType.SuikaMini);
|
||
}
|
||
|
||
private static int GetRaidAmount(CommonActionParams actionParams, PlayerData cityPlayer, int remaining)
|
||
{
|
||
var unit = actionParams.UnitData;
|
||
var amount = BaseRaidCoin;
|
||
if (unit.ActionPoint.GetValueOrDefault(ActionPointType.Common, 0) > 0)
|
||
amount *= 2;
|
||
amount *= PlayerActionDiplomacy.GetDanegeldRaidMultiplier(actionParams.PlayerData, cityPlayer);
|
||
if (unit.HasEffectiveSkill(SkillType.ReimuOfudaRaidDouble, out _))
|
||
amount *= 2;
|
||
return Mathf.Min(amount, remaining);
|
||
}
|
||
|
||
private static void ConsumeRaidDoubleMarker(MapData map, UnitData unit)
|
||
{
|
||
if (map == null || unit == null) return;
|
||
if (!unit.HasEffectiveSkill(SkillType.ReimuOfudaRaidDouble, out var skill)) return;
|
||
if (!skill.HasLevel)
|
||
{
|
||
unit.RemoveSkill(SkillType.ReimuOfudaRaidDouble, map);
|
||
return;
|
||
}
|
||
|
||
skill.ReduceLevel(map, unit, 1);
|
||
if (skill.IsFinished())
|
||
{
|
||
unit.RemoveSkill(SkillType.ReimuOfudaRaidDouble, map);
|
||
return;
|
||
}
|
||
|
||
unit.Renderer(map)?.SyncStatusWithUnitSkills();
|
||
}
|
||
}
|
||
|
||
public class UnitActionWarCry : UnitActionAction
|
||
{
|
||
private const int WarriorCost = 5;
|
||
private const int SwordsmanCost = 8;
|
||
private const SkillType WarCryTiredSkill = SkillType.RECYCLE;
|
||
|
||
public UnitActionWarCry(CommonActionId id) : base(id)
|
||
{
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
if (!CheckCan(actionParams)) return false;
|
||
var unit = actionParams.UnitData;
|
||
var grid = unit.Grid(actionParams.MapData);
|
||
actionParams.PlayerData.SpendCoin(GetCost(actionParams), grid);
|
||
unit.AddActionPoint(ActionPointType.Attack);
|
||
HakureiEinherjarCounter.TryAddPlayerPointFromVikingAction(actionParams.MapData, actionParams.PlayerData);
|
||
unit.AddSkill_Legacy(SkillType.Berserk, actionParams.MapData, false, 0, false, -1, false,
|
||
SpecialAddSkillType.Force, unit.Id);
|
||
unit.AddSkill_Legacy(WarCryTiredSkill, actionParams.MapData, false, 0, false, -1, false,
|
||
SpecialAddSkillType.Force, unit.Id);
|
||
if (unit.GetSkill(WarCryTiredSkill, out var tiredSkill))
|
||
tiredSkill.SetSkillPriority(SkillPriority.Origin);
|
||
unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
return true;
|
||
}
|
||
|
||
public override int GetCost(CommonActionParams actionParams)
|
||
{
|
||
return actionParams?.UnitData?.UnitType switch
|
||
{
|
||
UnitType.Warrior => WarriorCost,
|
||
UnitType.Swordsman => SwordsmanCost,
|
||
_ => 0
|
||
};
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
if (!CheckShow(actionParams, out _)) return false;
|
||
return actionParams.PlayerData.PlayerCoin >= GetCost(actionParams);
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams, out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
if (!actionParams.PlayerData.TechTree.CheckActionCan(_actionId)) return false;
|
||
if (!IsWarCryUnit(actionParams.UnitData)) return false;
|
||
if (actionParams.UnitData.GetSkill(WarCryTiredSkill, out _)) return false;
|
||
var cost = GetCost(actionParams);
|
||
if (cost <= 0) return false;
|
||
if (actionParams.PlayerData.PlayerCoin < cost) showType = ShowType.Cost;
|
||
return true;
|
||
}
|
||
|
||
private static bool IsWarCryUnit(UnitData unit)
|
||
{
|
||
return unit != null && unit.UnitType is UnitType.Warrior or UnitType.Swordsman;
|
||
}
|
||
}
|
||
|
||
//目前废弃
|
||
public class UnitActionROYALFLAMESPRO : UnitActionAction
|
||
{
|
||
public UnitActionROYALFLAMESPRO(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParam)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParam,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return false;
|
||
}
|
||
}
|
||
|
||
public class UnitActionCultureUnitUpgrade : UnitActionAction
|
||
{
|
||
public UnitActionCultureUnitUpgrade(CommonActionId id) : base(id)
|
||
{
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
if (!CheckCan(actionParams)) return false;
|
||
if (!UnitActionUpgradeHelper.TryGetCultureUnitUpgradeCost(actionParams.UnitData, out var cost))
|
||
return false;
|
||
|
||
actionParams.PlayerData.AddCulturePoint(-cost);
|
||
return UnitActionUpgradeHelper.ApplyOfficerUpgrade(actionParams.MapData, actionParams.UnitData);
|
||
}
|
||
|
||
public override int GetCost(CommonActionParams actionParams)
|
||
{
|
||
return UnitActionUpgradeHelper.TryGetCultureUnitUpgradeCost(actionParams?.UnitData, out var cost) ? cost : 0;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParam)
|
||
{
|
||
if (!UnitActionCheckBaseInfo(actionParam)) return false;
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false;
|
||
if (!actionParam.PlayerData.CanCultureUpgradeUnit(actionParam.MapData)) return false;
|
||
if (!CheckUnitCanCultureUpgrade(actionParam.UnitData)) return false;
|
||
if (!UnitActionUpgradeHelper.TryGetCultureUnitUpgradeCost(actionParam.UnitData, out var cost))
|
||
return false;
|
||
return actionParam.PlayerData.PlayerCultureInfo.PlayerCulture >= cost;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParam, out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
if (!UnitActionCheckBaseInfo(actionParam)) return false;
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false;
|
||
if (!actionParam.PlayerData.CanCultureUpgradeUnit(actionParam.MapData)) return false;
|
||
if (!CheckUnitCanCultureUpgrade(actionParam.UnitData)) return false;
|
||
if (!UnitActionUpgradeHelper.TryGetCultureUnitUpgradeCost(actionParam.UnitData, out _))
|
||
return false;
|
||
return true;
|
||
}
|
||
|
||
public override ActionShowState CheckShowState(CommonActionParams actionParams)
|
||
{
|
||
if (!CheckShow(actionParams, out _)) return ActionShowState.None;
|
||
if (!UnitActionUpgradeHelper.TryGetCultureUnitUpgradeCost(actionParams.UnitData, out var cost))
|
||
return ActionShowState.None;
|
||
return actionParams.PlayerData.PlayerCultureInfo.PlayerCulture >= cost
|
||
? ActionShowState.Available
|
||
: ActionShowState.Expensive;
|
||
}
|
||
|
||
private bool CheckUnitCanCultureUpgrade(UnitData unit)
|
||
{
|
||
return unit != null && unit.IsPrepareOfficer() && !unit.IsOfficer();
|
||
}
|
||
}
|
||
|
||
//英雄升级
|
||
public class UnitActionHeroUpgrade : UnitActionAction
|
||
{
|
||
private int _healthBeforeAnim;
|
||
|
||
private bool CheckUnitCanGiantUpgrade(CommonActionParams actionParams)
|
||
{
|
||
var unit = actionParams.UnitData;
|
||
var player = actionParams.PlayerData;
|
||
if (player == null) return false;
|
||
if(unit == null || unit.UnitType != UnitType.Giant || unit.GiantType == GiantType.None) return false;
|
||
if (!ContentGate.CanUseHeroForPlayer(player, unit.GiantType)) return false;
|
||
if(!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType,unit.GiantType,unit.UnitLevel,out var info)) return false;
|
||
if (!Table.Instance.HeroDataAssets.GetHeroInfo(unit.GiantType, out var heroInfo) ||
|
||
heroInfo.TaskList == null ||
|
||
heroInfo.TaskList.Count <= unit.UnitLevel - 1)
|
||
return false;
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType, unit.GiantType,
|
||
unit.UnitLevel + 1, out _))
|
||
return false;
|
||
|
||
return unit.HeroTask(actionParams.MapData)?.CheckFinished(actionParams.MapData, player) ?? false;
|
||
|
||
}
|
||
|
||
public UnitActionHeroUpgrade(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
|
||
if (actionParams.UnitData == null) return false;
|
||
_healthBeforeAnim = actionParams.UnitData.Health;
|
||
//if (!CheckCan(actionParams)) return false;
|
||
var unit = actionParams.UnitData;
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(unit.UnitType, unit.GiantType, unit.UnitLevel,
|
||
out var info)) return false;
|
||
//step #1 已经升到配置满级就return
|
||
if (!Table.Instance.HeroDataAssets.GetHeroInfo(unit.GiantType, out var heroInfo) ||
|
||
heroInfo.TaskList == null ||
|
||
heroInfo.TaskList.Count <= unit.UnitLevel - 1)
|
||
return false;
|
||
//step #2 英雄升级
|
||
var giantType = unit.GiantType;
|
||
var targetLevel = unit.UnitLevel + 1;
|
||
if (!Main.UnitLogic.HeroUpgrade(actionParams.MapData, unit)) return false;
|
||
|
||
//step #3 回复10点血
|
||
unit.AddHealth(10 + unit.GetHeroUpgradeRecoverAddition(actionParams.MapData));
|
||
|
||
//更新视觉,自动排除非真map情况和不在视野情况
|
||
if(actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true)??false){
|
||
actionParams.UnitData.Grid(actionParams.MapData)?.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Heal));
|
||
|
||
}
|
||
if(actionParams.UnitData.Grid(actionParams.MapData)?.InMainSight()??false)
|
||
AudioManager.Instance.PlayAudio("SFX/UNIT_levelup");
|
||
|
||
//step #3.5 场上所有相同GiantType的英雄单位一起升级
|
||
//若本次升级的是FrenchReisen,则同玩家场上所有KaguyaFrenchReisenIllusion也同步升级到相同等级
|
||
var sameGiantUnits = new System.Collections.Generic.List<UnitData>();
|
||
actionParams.MapData.GetUnitDataListByPlayerId(actionParams.PlayerId, sameGiantUnits);
|
||
bool isFrenchReisenUpgrade = giantType == GiantType.FrenchReisen;
|
||
foreach (var other in sameGiantUnits)
|
||
{
|
||
if (other.Id == unit.Id) continue;
|
||
if (!other.IsAlive()) continue;
|
||
|
||
bool isSameGiantHero = other.UnitType == UnitType.Giant && other.GiantType == giantType;
|
||
bool isReisenIllusion = isFrenchReisenUpgrade && other.UnitType == UnitType.KaguyaFrenchReisenIllusion;
|
||
if (!isSameGiantHero && !isReisenIllusion) continue;
|
||
|
||
if (other.UnitLevel >= targetLevel) continue;
|
||
var otherTargetType = new UnitFullType()
|
||
{ UnitType = other.UnitType, GiantType = other.GiantType, UnitLevel = (uint)targetLevel };
|
||
Main.UnitLogic.UnitTypeTransform(actionParams.MapData, other, otherTargetType);
|
||
if (giantType == GiantType.NorwaySuika && other.UnitType == UnitType.Giant)
|
||
HakureiNorwayHeroSkillUtil.SyncMiniSuikaAfterHeroUpgrade(actionParams.MapData, other);
|
||
other.AddHealth(10 + other.GetHeroUpgradeRecoverAddition(actionParams.MapData));
|
||
other.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
//同类英雄升级后也更新视野
|
||
if (other.Grid(actionParams.MapData) != null)
|
||
Main.PlayerLogic.UpdateSightByRadius_LogicView(actionParams.MapData, actionParams.PlayerData, other.Grid(actionParams.MapData), other.GetSightRange(actionParams.MapData));
|
||
}
|
||
|
||
if (giantType == GiantType.NorwayAunn)
|
||
HakureiNorwayHeroSkillUtil.SyncAunnTwinAfterHeroUpgrade(actionParams.MapData, unit);
|
||
if (giantType == GiantType.NorwaySumireko)
|
||
HakureiNorwayHeroSkillUtil.SyncSumirekoOccultOrbsAfterHeroUpgrade(actionParams.MapData, unit);
|
||
if (giantType == GiantType.NorwaySuika)
|
||
HakureiNorwayHeroSkillUtil.SyncMiniSuikaAfterHeroUpgrade(actionParams.MapData, unit);
|
||
if (giantType == GiantType.NorwayKasen)
|
||
HakureiNorwayHeroSkillUtil.SyncKasenBeastGuidesAfterHeroUpgrade(actionParams.MapData);
|
||
|
||
//step #3.6 升级后更新主英雄视野(升级可能增加视野范围)
|
||
if (unit.Grid(actionParams.MapData) != null)
|
||
Main.PlayerLogic.UpdateSightByRadius_LogicView(actionParams.MapData, actionParams.PlayerData, unit.Grid(actionParams.MapData), unit.GetSightRange(actionParams.MapData));
|
||
|
||
//Step #4 Moment
|
||
if (actionParams.UnitData.Player(actionParams.MapData) == Main.MapData.PlayerMap.SelfPlayerData)
|
||
{
|
||
EventManager.Publish(new ShowUINotifyMoment()
|
||
{
|
||
MomentSubType = MomentSubType.BattleHeroLevelup,
|
||
Empire = Main.MapData.PlayerMap.SelfPlayerData.Empire
|
||
});
|
||
}
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParam)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParam)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false;
|
||
//step #3 check unit是否是hero并满足升级条件
|
||
if (!CheckUnitCanGiantUpgrade(actionParam)) return false;
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParam,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParam);
|
||
}
|
||
|
||
public bool ExecuteViewBefore(CommonActionParams actionParams)
|
||
{
|
||
|
||
return true;
|
||
}
|
||
|
||
public bool ExecuteViewAfter(CommonActionParams actionParams)
|
||
{
|
||
|
||
|
||
return true;
|
||
}
|
||
}
|
||
|
||
|
||
public class UnitActionHEAL : UnitActionAction
|
||
{
|
||
public UnitActionHEAL(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
var map = actionParams.MapData;
|
||
var unit = actionParams.UnitData;
|
||
if (map == null || unit == null) return false;
|
||
if (!map.GetGridDataByUnitId(actionParams.UnitData.Id, out var targetGrid)) return false;
|
||
_sharedAroundBuf ??= new List<GridData>();
|
||
_sharedAroundBuf.Clear();
|
||
map.GridMap.GetAroundGridData(1, 1, targetGrid, _sharedAroundBuf);
|
||
foreach (var grid in _sharedAroundBuf)
|
||
{
|
||
if (!grid.RealUnit(map, out var tunit)) continue;
|
||
if(tunit.Id == unit.Id)continue;
|
||
if (!map.SameUnionByUnitId(unit.Id,tunit.Id)) continue;
|
||
Main.UnitLogic.RecoverHealth_Legacy(map, unit, tunit, 4);
|
||
}
|
||
unit.ClearActionPoint();
|
||
unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParam)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParam)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false;
|
||
//step #3 check是否有CP释放技能
|
||
if (!UnitActionCheckUnitHasCP(actionParam)) return false;
|
||
//step #4 check unit是否拥有skill技能
|
||
if (!UnitActionCheckUnitHasSkill(actionParam)) return false;
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParam,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParam);
|
||
}
|
||
|
||
}
|
||
|
||
public class UnitActionTEWIFRENCHBUFF : UnitActionAction
|
||
{
|
||
public UnitActionTEWIFRENCHBUFF(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
var selfUnit = actionParams.UnitData;
|
||
var selfGrid = actionParams.GridData;
|
||
if(selfGrid == null)
|
||
if(!actionParams.MapData.GetGridDataByUnitId(selfUnit.Id, out selfGrid)) return false;
|
||
if (!actionParams.MapData.GetPlayerDataByUnitId(selfUnit.Id, out var selfPlayer)) return false;
|
||
_sharedAroundBuf ??= new List<GridData>();
|
||
_sharedAroundBuf.Clear();
|
||
actionParams.MapData.GridMap.GetAroundGridData(1,1,selfGrid, _sharedAroundBuf);
|
||
foreach (var grid in _sharedAroundBuf)
|
||
{
|
||
if (grid == selfGrid) continue;
|
||
if(!grid.RealUnit(actionParams.MapData,out var targetUnit))continue;
|
||
if(!actionParams.MapData.GetPlayerDataByUnitId(targetUnit.Id, out var targetPlayer)) continue;
|
||
if(!actionParams.MapData.SameUnion(targetPlayer.Id,selfPlayer.Id)) continue;
|
||
targetUnit.AddSkill_Legacy(SkillType.MOVERANGEUP,actionParams.MapData,false,1,false,-1,false,SpecialAddSkillType.AddTurnLimit,0);
|
||
targetUnit.AddSkill_Legacy(SkillType.HouraisanFrenchFakeMoon,actionParams.MapData,false,1,false, -1,false,SpecialAddSkillType.AddTurnLimit,0);
|
||
targetUnit.AddSkill_Legacy(SkillType.KAGUYAFRENCHSYNERGY,actionParams.MapData,false,1,false, -1,false,SpecialAddSkillType.AddTurnLimit,0);
|
||
if(targetUnit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true)??false)
|
||
grid.Renderer(actionParams.MapData)?.PlayVFXInSight(
|
||
new GridVFXParams(GridVFXType.SkillIcon, SkillType.HouraisanFrenchFakeMoon, targetUnit.UnitFullType));
|
||
}
|
||
|
||
actionParams.UnitData.ClearActionPoint();
|
||
actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParam)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParam)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false;
|
||
//step #3 check是否有CP释放技能
|
||
if (!UnitActionCheckUnitHasCP(actionParam)) return false;
|
||
//step #4 check unit是否拥有skill技能
|
||
if (!UnitActionCheckUnitHasSkill(actionParam)) return false;
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParam,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParam);
|
||
}
|
||
|
||
}
|
||
|
||
public class UnitActionMOKOUFRENCHBOOM : UnitActionAction
|
||
{
|
||
public UnitActionMOKOUFRENCHBOOM(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
if (actionParams.MapData == null) return false;
|
||
var selfUnit = actionParams.UnitData;
|
||
if (selfUnit == null) return false;
|
||
var selfGrid = actionParams.GridData;
|
||
if (selfGrid == null)
|
||
{
|
||
if (!actionParams.MapData.GetGridDataByUnitId(selfUnit.Id, out selfGrid)) return false;
|
||
}
|
||
if (!actionParams.MapData.GetPlayerDataByUnitId(selfUnit.Id, out var selfPlayer)) return false;
|
||
_sharedAroundBuf ??= new List<GridData>();
|
||
_sharedAroundBuf.Clear();
|
||
actionParams.MapData.GridMap.GetAroundGridData(1,1,selfGrid, _sharedAroundBuf);
|
||
foreach (var grid in _sharedAroundBuf)
|
||
{
|
||
if (grid == selfGrid) continue;
|
||
|
||
if(!grid.RealUnit(actionParams.MapData,out var targetUnit))continue;
|
||
var dmg = Table.Instance.CalcDamage(actionParams.MapData,selfUnit,targetUnit,10);
|
||
var dmgType = actionParams.MapData.SameUnionByUnitId(selfUnit.Id, targetUnit.Id) ? DamageType.KillSelf : DamageType.True;
|
||
var settle = Main.UnitLogic.DamageSettlement(actionParams.MapData, selfUnit, targetUnit, dmg, dmgType);
|
||
if (settle == null) continue;
|
||
|
||
if (settle.DamageTargetGrid != null && settle.DamageTargetGrid.InMainSight())
|
||
{
|
||
if (!settle.IsKill)
|
||
{
|
||
settle.DamageTargetGrid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Hurt));
|
||
targetUnit?.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
}
|
||
else
|
||
{
|
||
if (targetUnit == null || targetUnit.CanBeKilled(actionParams.MapData))
|
||
settle.DamageTargetGrid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Die));
|
||
settle.DamageTargetGrid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Hurt));
|
||
settle.DamageTargetGrid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
targetUnit?.Renderer(actionParams.MapData)?.Die();
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
Main.UnitLogic.DamageSettlement(actionParams.MapData, selfUnit, selfUnit, selfUnit.Health, DamageType.KillSelf);
|
||
selfUnit.Renderer(actionParams.MapData)?.Die();
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParam)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParam)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false;
|
||
//step #3 check是否有CP释放技能
|
||
if (!UnitActionCheckUnitHasCP(actionParam)) return false;
|
||
//step #4 check unit是否拥有skill技能
|
||
if (!UnitActionCheckUnitHasSkill(actionParam)) return false;
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParam,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParam);
|
||
}
|
||
|
||
}
|
||
|
||
public class UnitActionKAGUYAFRENCHAROUND : UnitActionAction
|
||
{
|
||
public UnitActionKAGUYAFRENCHAROUND(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
var selfUnit = actionParams.UnitData;
|
||
var selfGrid = actionParams.GridData;
|
||
if(selfGrid == null)
|
||
if(!actionParams.MapData.GetGridDataByUnitId(selfUnit.Id, out selfGrid)) return false;
|
||
if (!actionParams.MapData.GetPlayerDataByUnitId(selfUnit.Id, out var selfPlayer)) return false;
|
||
_sharedAroundBuf ??= new List<GridData>();
|
||
_sharedAroundBuf.Clear();
|
||
actionParams.MapData.GridMap.GetAroundGridData(1,1,selfGrid, _sharedAroundBuf);
|
||
foreach (var grid in _sharedAroundBuf)
|
||
{
|
||
if (grid == selfGrid) continue;
|
||
if(!grid.RealUnit(actionParams.MapData,out var targetUnit))continue;
|
||
if(!actionParams.MapData.GetPlayerDataByUnitId(targetUnit.Id, out var targetPlayer)) continue;
|
||
if(!actionParams.MapData.SameUnion(targetPlayer.Id,selfPlayer.Id)) continue;
|
||
targetUnit.AddSkill_Legacy(SkillType.KAGUYAFRENCHFOREVERBUFF, actionParams.MapData,false,1,true,1,true,SpecialAddSkillType.AddLevel, selfUnit.Id);
|
||
//if (targetUnit.GetSkill(SkillType.KAGUYAFRENCHFOREVERBUFF, out var skill))
|
||
//skill.AddLevel(actionParams.MapData, selfUnit, targetUnit, 1);
|
||
|
||
targetUnit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
grid.Renderer(actionParams.MapData)?.PlayVFXInSight(
|
||
new GridVFXParams(GridVFXType.SkillIcon, SkillType.KAGUYAFRENCHFOREVERBUFF, targetUnit.UnitFullType));
|
||
}
|
||
|
||
actionParams.UnitData.ClearActionPoint();
|
||
actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParam)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParam)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false;
|
||
//step #3 check是否有CP释放技能
|
||
if (!UnitActionCheckUnitHasCP(actionParam)) return false;
|
||
//step #4 check unit是否拥有skill技能
|
||
if (!UnitActionCheckUnitHasSkill(actionParam)) return false;
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParam,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParam);
|
||
}
|
||
|
||
}
|
||
|
||
public class UnitActionForceDisband : UnitActionAction
|
||
{
|
||
public UnitActionForceDisband(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
//Step #1 鲁棒性判断
|
||
if (actionParams.UnitData == null) return false;
|
||
var unitData = actionParams.UnitData;
|
||
var playerData = actionParams.PlayerData;
|
||
if (playerData == null)
|
||
if (!actionParams.MapData.GetPlayerDataByUnitId(actionParams.UnitData.Id, out playerData))
|
||
return false;
|
||
if (!actionParams.MapData.GetGridDataByUnitId(actionParams.UnitData.Id, out var gridData))
|
||
return false;
|
||
|
||
//Step #2 计算花费的金币数,增加金币
|
||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(actionParams.UnitData.UnitFullType, out _)) return false;
|
||
var earn = (int)(actionParams.UnitData.GetTotalCostWithCarry() * 0.5f);
|
||
|
||
//AddCoin自带动画考量
|
||
actionParams.PlayerData.AddCoin(earn,gridData);
|
||
|
||
|
||
//Step #3 如果是真map,需要播放单位死亡动画
|
||
if (actionParams.MapData == Main.MapData)
|
||
{
|
||
//播放雾效
|
||
gridData.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
//通知渲染器播放死亡
|
||
if(MapRenderer.Instance.ROUnitMap.TryGetValue(actionParams.UnitData.Id,out var renderer))
|
||
renderer.Die();
|
||
}
|
||
|
||
//Step #4 单位彻底死亡
|
||
Main.UnitLogic.UnitUnnaturalDie(actionParams.MapData,actionParams.UnitData);
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParam)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParam)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false;
|
||
return true;
|
||
}
|
||
|
||
}
|
||
|
||
public class UnitActionRemoveRedMist : UnitActionAction
|
||
{
|
||
public UnitActionRemoveRedMist(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
//Step #1 鲁棒性判断
|
||
var unit = actionParams.UnitData;
|
||
if (unit == null || !unit.Grid(actionParams.MapData,out var grid)) return false;
|
||
|
||
//Step #2 清除红雾
|
||
grid.RemoveSpType(GridSpType.RemiliaGrid,actionParams.MapData);
|
||
unit.ClearActionPoint();
|
||
if (grid.InMainSight())
|
||
{
|
||
grid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
grid.Renderer(actionParams.MapData)?.InstantUpdateGrid();
|
||
unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(false);
|
||
}
|
||
|
||
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
|
||
//#step #3 check 是否有CP
|
||
if (actionParams.UnitData.GetActionPoint(ActionPointType.Capture) <= 0) return false;
|
||
|
||
//#step #4 check 当前grid是否是remiliaGrid
|
||
if (!actionParams.UnitData.Grid(actionParams.MapData, out var grid) ||
|
||
!grid.HasSpType(GridSpType.RemiliaGrid)) return false;
|
||
|
||
//#step #5 部分格子无法清除红雾
|
||
if (grid.Resource == ResourceType.RemiliaMilitary) return false;
|
||
|
||
//#step #6 如果是remilia阵营的单位,无法清除
|
||
var playerCivId = actionParams.UnitData.Player(actionParams.MapData)?.PlayerCivId;
|
||
if (playerCivId is 0) return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParams);
|
||
}
|
||
|
||
|
||
}
|
||
|
||
public class UnitActionREMILIABUFF : UnitActionAction
|
||
{
|
||
public UnitActionREMILIABUFF(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
var selfUnit = actionParams.UnitData;
|
||
var selfGrid = actionParams.GridData;
|
||
if(selfGrid == null)
|
||
if(!actionParams.MapData.GetGridDataByUnitId(selfUnit.Id, out selfGrid)) return false;
|
||
if (!actionParams.MapData.GetPlayerDataByUnitId(selfUnit.Id, out var selfPlayer)) return false;
|
||
_sharedAroundBuf ??= new List<GridData>();
|
||
_sharedAroundBuf.Clear();
|
||
actionParams.MapData.GridMap.GetAroundGridData(1,1,selfGrid, _sharedAroundBuf);
|
||
foreach (var grid in _sharedAroundBuf)
|
||
{
|
||
if (grid.Resource == ResourceType.CityCenter) continue;
|
||
if (grid.Terrain != TerrainType.Land) continue;
|
||
if (grid.HasSpType(GridSpType.RemiliaGrid)) continue;
|
||
grid.AddSpType(GridSpType.RemiliaGrid,actionParams.MapData,selfUnit);
|
||
if (grid.InMainSight())
|
||
{
|
||
grid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.RedMistCreate));
|
||
grid.Renderer(actionParams.MapData)?.InstantUpdateGrid();
|
||
if(grid.MainSelfPlayerVisibleUnit(out var gridUnit))
|
||
gridUnit.Renderer(actionParams.MapData)?.InstantUpdateUnit(false);
|
||
}
|
||
|
||
}
|
||
|
||
actionParams.UnitData.ClearActionPoint();
|
||
actionParams.UnitData.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParam)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParam)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParam)) return false;
|
||
//step #3 check是否有CP释放技能
|
||
if (!UnitActionCheckUnitHasCP(actionParam)) return false;
|
||
//step #4 check unitTypeData的EnableActions里包含此action
|
||
if (!CheckUnitEnableAction(actionParam)) return false;
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParam,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParam);
|
||
}
|
||
|
||
}
|
||
|
||
public class UnitActionAbsorbRedMist : UnitActionAction
|
||
{
|
||
public UnitActionAbsorbRedMist(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
//Step #1 鲁棒性判断
|
||
var unit = actionParams.UnitData;
|
||
if (unit == null || !unit.Grid(actionParams.MapData,out var grid)) return false;
|
||
|
||
//Step #2 清除红雾
|
||
grid.RemoveSpType(GridSpType.RemiliaGrid,actionParams.MapData);
|
||
if (grid.InMainSight())
|
||
{
|
||
grid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
grid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Heal));
|
||
grid.Renderer(actionParams.MapData)?.InstantUpdateGrid();
|
||
unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(false);
|
||
}
|
||
|
||
//Step #3 恢复血量
|
||
Main.UnitLogic.RecoverHealth_Legacy(actionParams.MapData,actionParams.UnitData,actionParams.UnitData,4);
|
||
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
//#step #2 check unit属于player 且player是斯卡雷特阵营
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
if(actionParams.PlayerData.PlayerCivId != 0) return false;
|
||
|
||
//#step #3 check GetActionPoint(ActionPointType.Capture) 不需要任何CP!
|
||
//if (actionParams.UnitData.GetActionPoint(ActionPointType.Capture) <= 0) return false;
|
||
|
||
//#step #4 check 当前grid是否是remiliaGrid
|
||
if (!actionParams.UnitData.Grid(actionParams.MapData, out var grid) ||
|
||
!grid.HasSpType(GridSpType.RemiliaGrid)) return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParams);
|
||
}
|
||
|
||
|
||
}
|
||
|
||
public class UnitActionHakureiAbsorbRune : UnitActionAction
|
||
{
|
||
private const int RecoverValue = 6;
|
||
|
||
public UnitActionHakureiAbsorbRune(CommonActionId id) : base(id)
|
||
{
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
var unit = actionParams.UnitData;
|
||
if (unit == null || !unit.Grid(actionParams.MapData, out var grid)) return false;
|
||
if (!grid.HasSpType(GridSpType.HakureiRune)) return false;
|
||
|
||
grid.RemoveSpType(GridSpType.HakureiRune, actionParams.MapData);
|
||
Main.UnitLogic.RecoverHealth(actionParams.MapData, unit, unit, RecoverValue);
|
||
|
||
if (grid.InMainSight())
|
||
{
|
||
grid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
grid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Heal));
|
||
grid.Renderer(actionParams.MapData)?.InstantUpdateGrid();
|
||
unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
if (actionParams.UnitData.UnitType != UnitType.HakureiValkyrie) return false;
|
||
if (!CheckUnitEnableAction(actionParams)) return false;
|
||
return actionParams.UnitData.Grid(actionParams.MapData, out var grid)
|
||
&& grid.HasSpType(GridSpType.HakureiRune);
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams, out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParams);
|
||
}
|
||
}
|
||
|
||
public class UnitActionClearHakureiRune : UnitActionAction
|
||
{
|
||
public UnitActionClearHakureiRune(CommonActionId id) : base(id)
|
||
{
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
var unit = actionParams.UnitData;
|
||
if (unit == null || !unit.Grid(actionParams.MapData, out var grid)) return false;
|
||
if (!grid.HasSpType(GridSpType.HakureiRune)) return false;
|
||
|
||
grid.RemoveSpType(GridSpType.HakureiRune, actionParams.MapData);
|
||
unit.ReduceActionPoint(ActionPointType.Capture);
|
||
|
||
if (grid.InMainSight())
|
||
{
|
||
grid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
grid.Renderer(actionParams.MapData)?.InstantUpdateGrid();
|
||
unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
if (!UnitActionCheckUnitHasCP(actionParams)) return false;
|
||
return actionParams.UnitData.Grid(actionParams.MapData, out var grid)
|
||
&& grid.HasSpType(GridSpType.HakureiRune);
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams, out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParams);
|
||
}
|
||
}
|
||
|
||
public class UnitActionKasenRecallBeastGuide : UnitActionAction
|
||
{
|
||
public UnitActionKasenRecallBeastGuide(CommonActionId id) : base(id)
|
||
{
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
if (!CheckCan(actionParams)) return false;
|
||
return HakureiNorwayHeroSkillUtil.TryRecallKasenBeastGuide(actionParams.MapData, actionParams.UnitData);
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
return actionParams.UnitData.Grid(actionParams.MapData, out var grid)
|
||
&& HakureiNorwayHeroSkillUtil.CanRecallKasenBeastGuide(actionParams.MapData,
|
||
actionParams.UnitData, grid, out _);
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams, out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParams);
|
||
}
|
||
}
|
||
|
||
public class UnitActionKasenClearBeastGuide : UnitActionAction
|
||
{
|
||
public UnitActionKasenClearBeastGuide(CommonActionId id) : base(id)
|
||
{
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
if (!CheckCan(actionParams)) return false;
|
||
return HakureiNorwayHeroSkillUtil.TryClearKasenBeastGuide(actionParams.MapData, actionParams.UnitData);
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
if (!UnitActionCheckUnitHasCP(actionParams)) return false;
|
||
return actionParams.UnitData.Grid(actionParams.MapData, out var grid)
|
||
&& HakureiNorwayHeroSkillUtil.CanClearKasenBeastGuide(actionParams.MapData,
|
||
actionParams.UnitData, grid, out _);
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams, out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParams);
|
||
}
|
||
}
|
||
|
||
public class UnitActionRemiliaAbsorb : UnitActionAction
|
||
{
|
||
public UnitActionRemiliaAbsorb(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
//Step #1 鲁棒性判断
|
||
var unit = actionParams.UnitData;
|
||
if (unit == null || !unit.Grid(actionParams.MapData,out var grid)) return false;
|
||
|
||
//Step #2 清除红雾
|
||
int count = 0;
|
||
_sharedAroundBuf ??= new List<GridData>();
|
||
_sharedAroundBuf.Clear();
|
||
actionParams.MapData.GridMap.GetAroundGridData(1, 1, grid, _sharedAroundBuf);
|
||
foreach (var tgrid in _sharedAroundBuf)
|
||
{
|
||
if (!tgrid.HasSpType(GridSpType.RemiliaGrid)) continue;
|
||
count++;
|
||
tgrid.RemoveSpType(GridSpType.RemiliaGrid,actionParams.MapData);
|
||
if (tgrid.InMainSight())
|
||
{
|
||
tgrid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
tgrid.Renderer(actionParams.MapData)?.InstantUpdateGrid();
|
||
if(tgrid.RealUnit(actionParams.MapData,out var gridUnit))
|
||
gridUnit.Renderer(actionParams.MapData)?.InstantUpdateUnit(false);
|
||
|
||
}
|
||
}
|
||
|
||
|
||
//Step #3 赋予buff
|
||
unit.AddSkill_Legacy(SkillType.REMILIABUFF3, actionParams.MapData,false,0,true,count,true,SpecialAddSkillType.AddLevel,unit.Id);
|
||
//if (unit.GetSkill(SkillType.REMILIABUFF3, out var skill))
|
||
//skill.AddLevel(actionParams.MapData, unit, unit, count);
|
||
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
//#step #2 check unit属于player 且player是斯卡雷特阵营
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
if(actionParams.PlayerData.PlayerCivId != 0) return false;
|
||
|
||
//#step #3 check unitTypeData的EnableActions里包含此action
|
||
if (!CheckUnitEnableAction(actionParams)) return false;
|
||
|
||
//#step #4 check 当前grid是否是remiliaGrid
|
||
|
||
if (!actionParams.UnitData.Grid(actionParams.MapData, out var grid))return false;
|
||
_sharedAroundBuf ??= new List<GridData>();
|
||
_sharedAroundBuf.Clear();
|
||
actionParams.MapData.GridMap.GetAroundGridData(1, 1, grid, _sharedAroundBuf);
|
||
bool hasRemiliaGrid = false;
|
||
foreach (var tgrid in _sharedAroundBuf)
|
||
if (tgrid.HasSpType(GridSpType.RemiliaGrid))
|
||
{
|
||
hasRemiliaGrid = true;
|
||
break;
|
||
}
|
||
|
||
if (!hasRemiliaGrid) return false;
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParams);
|
||
}
|
||
|
||
|
||
}
|
||
|
||
public class UnitActionKanakoSit : UnitActionAction
|
||
{
|
||
public UnitActionKanakoSit(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
//Step #1 鲁棒性判断
|
||
var unit = actionParams.UnitData;
|
||
if (unit == null || !unit.Grid(actionParams.MapData,out var grid)) return false;
|
||
|
||
//Step #2 赋予buff
|
||
unit.AddSkill_Legacy(SkillType.KANAKOSITTING, actionParams.MapData,true,-1,false,-1,false,SpecialAddSkillType.Force,0);
|
||
|
||
//Step #3 消耗CP(不需要消耗)
|
||
//unit.ClearAPMPCP();
|
||
|
||
//Step #4 刷新视觉
|
||
if (unit.InMainSight())
|
||
{
|
||
unit.Renderer(actionParams.MapData).InstantUpdateUnit(showoff: true);
|
||
grid.Renderer(actionParams.MapData).PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
//#step #3 check unitTypeData的EnableActions里包含此action,且不处在sit状态
|
||
if (!CheckUnitEnableAction(actionParams)) return false;
|
||
if (actionParams.UnitData.GetSkill(SkillType.KANAKOSITTING, out var _)) return false;
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParams);
|
||
}
|
||
|
||
|
||
}
|
||
|
||
public class UnitActionKanakoUnSit : UnitActionAction
|
||
{
|
||
public UnitActionKanakoUnSit(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
//Step #1 鲁棒性判断
|
||
var unit = actionParams.UnitData;
|
||
if (unit == null || !unit.Grid(actionParams.MapData,out var grid)) return false;
|
||
|
||
//Step #2 去除buff
|
||
unit.RemoveSkill(SkillType.KANAKOSITTING, actionParams.MapData);
|
||
|
||
//Step #3 消耗CP
|
||
//unit.ClearAPMPCP();
|
||
|
||
//Step #4 刷新视觉
|
||
if (unit.InMainSight())
|
||
{
|
||
unit.Renderer(actionParams.MapData).InstantUpdateUnit(showoff: true);
|
||
grid.Renderer(actionParams.MapData).PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
//#step #3 check 当前单位正在Sit
|
||
if (!actionParams.UnitData.GetSkill(SkillType.KANAKOSITTING, out var _)) return false;
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParams);
|
||
}
|
||
|
||
|
||
}
|
||
|
||
public class UnitActionAyaMoveAgain : UnitActionAction
|
||
{
|
||
public UnitActionAyaMoveAgain(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
//Step #1 鲁棒性判断
|
||
if (actionParams?.MapData == null) return false;
|
||
var unit = actionParams.UnitData;
|
||
if (unit == null || !unit.Grid(actionParams.MapData,out var grid) || grid == null) return false;
|
||
|
||
//Step #2 去除buff
|
||
if (!unit.GetSkill(SkillType.AYAMOVEAGAIN, out var skill) || skill == null) return false;
|
||
if (skill.Level <= 0) return false;
|
||
skill.ReduceLevel(actionParams.MapData, actionParams.UnitData, 1);
|
||
unit.AddActionPoint(ActionPointType.Move);
|
||
|
||
//Step #4 刷新视觉
|
||
if (unit.InMainSight())
|
||
{
|
||
unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(showoff: true);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
//#step #3 check 当前单位正在Sit
|
||
if (!actionParams.UnitData.GetSkill(SkillType.AYAMOVEAGAIN, out var skill) || skill.Level <= 0) return false;
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams,out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
return CheckCan(actionParams);
|
||
}
|
||
|
||
|
||
}
|
||
|
||
public class UnitActionKomeijiRinFire : UnitActionAction
|
||
{
|
||
public UnitActionKomeijiRinFire(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
var unit = actionParams.UnitData;
|
||
if (unit == null || !unit.Grid(actionParams.MapData, out var grid)) return false;
|
||
|
||
//Step #1 获取CorpseBuff层数
|
||
if (!unit.GetSkill(SkillType.CorpseBuff, out var corpseSkill)) return false;
|
||
int level = corpseSkill.Level;
|
||
if (level <= 0) return false;
|
||
|
||
//Step #2 将CorpseBuff层数增加到RinFire上
|
||
unit.AddSkill_Legacy(SkillType.RinFire, actionParams.MapData, false, 0, true, level, false, SpecialAddSkillType.AddLevel, unit.Id);
|
||
|
||
//Step #3 清除CorpseBuff
|
||
unit.RemoveSkill(SkillType.CorpseBuff, actionParams.MapData);
|
||
|
||
//Step #4 刷新视觉
|
||
if (unit.InMainSight())
|
||
{
|
||
unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
grid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
//#step #3 check unitTypeData的EnableActions里包含此action
|
||
if (!CheckUnitEnableAction(actionParams)) return false;
|
||
//#step #4 check 当前unit拥有CorpseBuff且层数>0
|
||
if (!actionParams.UnitData.GetSkill(SkillType.CorpseBuff, out var corpseSkill) || corpseSkill.Level <= 0) return false;
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams, out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
//#step #3 check unitTypeData的EnableActions里包含此action
|
||
if (!CheckUnitEnableAction(actionParams)) return false;
|
||
//#step #4 check 当前unit拥有CorpseBuff
|
||
if (!actionParams.UnitData.GetSkill(SkillType.CorpseBuff, out var _)) return false;
|
||
return true;
|
||
}
|
||
}
|
||
|
||
public class UnitActionKomeijiRinCityExp : UnitActionAction
|
||
{
|
||
public UnitActionKomeijiRinCityExp(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
var unit = actionParams.UnitData;
|
||
if (unit == null || !unit.Grid(actionParams.MapData, out var grid)) return false;
|
||
|
||
//Step #1 获取MahaCorpseBuff层数
|
||
if (!unit.GetSkill(SkillType.MahaCorpseBuff, out var mahaCorpseSkill)) return false;
|
||
int level = mahaCorpseSkill.Level;
|
||
if (level <= 0) return false;
|
||
|
||
//Step #2 获取当前所处的我方城市
|
||
if (!actionParams.MapData.GetCityDataByTerritoryGid(grid.Id, out var city)) return false;
|
||
if (!city.Player(actionParams.MapData, out var cityPlayer) || cityPlayer != actionParams.PlayerData) return false;
|
||
|
||
//Step #3 将MahaCorpseBuff层数转化为CityExp
|
||
Main.CityLogic.UpdateGrid_ViewOnly(actionParams.MapData, grid);
|
||
Main.CityLogic.GridGiveCityExp_LogicView(actionParams.MapData, actionParams.PlayerData, city.Grid(actionParams.MapData), city, level);
|
||
|
||
//Step #4 清除MahaCorpseBuff
|
||
unit.RemoveSkill(SkillType.MahaCorpseBuff, actionParams.MapData);
|
||
|
||
//Step #5 刷新视觉
|
||
if (unit.InMainSight())
|
||
{
|
||
unit.Renderer(actionParams.MapData)?.InstantUpdateUnit(true);
|
||
grid.Renderer(actionParams.MapData)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
//#step #3 check 是IndianRin英雄
|
||
if (actionParams.UnitData.GiantType != GiantType.IndianRin) return false;
|
||
//#step #4 check unitTypeData的EnableActions里包含此action
|
||
if (!CheckUnitEnableAction(actionParams)) return false;
|
||
//#step #5 check 当前unit拥有MahaCorpseBuff且层数>0
|
||
if (!actionParams.UnitData.GetSkill(SkillType.MahaCorpseBuff, out var mahaCorpseSkill) || mahaCorpseSkill.Level <= 0) return false;
|
||
//#step #6 check 当前所处我方城市领土
|
||
if (!actionParams.MapData.GetGridDataByUnitId(actionParams.UnitData.Id, out var grid)) return false;
|
||
if (!actionParams.MapData.GetCityDataByTerritoryGid(grid.Id, out var city)) return false;
|
||
if (!city.Player(actionParams.MapData, out var cityPlayer) || cityPlayer != actionParams.PlayerData) return false;
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams, out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
//#step #3 check 是IndianRin英雄
|
||
if (actionParams.UnitData.GiantType != GiantType.IndianRin) return false;
|
||
//#step #4 check unitTypeData的EnableActions里包含此action
|
||
if (!CheckUnitEnableAction(actionParams)) return false;
|
||
//#step #5 check 当前unit拥有MahaCorpseBuff且层数>0
|
||
if (!actionParams.UnitData.GetSkill(SkillType.MahaCorpseBuff, out var mahaCorpseSkill) || mahaCorpseSkill.Level <= 0) return false;
|
||
//#step #6 check 当前所处我方城市领土
|
||
if (!actionParams.MapData.GetGridDataByUnitId(actionParams.UnitData.Id, out var grid)) return false;
|
||
if (!actionParams.MapData.GetCityDataByTerritoryGid(grid.Id, out var city)) return false;
|
||
if (!city.Player(actionParams.MapData, out var cityPlayer) || cityPlayer != actionParams.PlayerData) return false;
|
||
return true;
|
||
}
|
||
}
|
||
|
||
//铃仙法式自爆:单纯消除自身,不产生任何其它效果
|
||
//语义等同于 UndeadSkill 的"消散"路径(UnitUnnaturalDie),因此无论是否持有 Undead 表现一致
|
||
public class UnitActionReisenFrenchBoom : UnitActionAction
|
||
{
|
||
public UnitActionReisenFrenchBoom(CommonActionId id) : base(id)
|
||
{
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
var unit = actionParams.UnitData;
|
||
var map = actionParams.MapData;
|
||
if (unit == null || !unit.Grid(map, out var grid)) return false;
|
||
|
||
//缓存renderer,UnitUnnaturalDie会把unit从grid解绑
|
||
var unitRenderer = unit.Renderer(map);
|
||
|
||
Main.UnitLogic.UnitUnnaturalDie(map, unit);
|
||
|
||
if (map == Main.MapData)
|
||
{
|
||
unitRenderer?.Die();
|
||
grid.Renderer(map)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Fog));
|
||
grid.Renderer(map)?.InstantUpdateGrid();
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
if (!CheckUnitEnableAction(actionParams)) return false;
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams, out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
if (!CheckUnitEnableAction(actionParams)) return false;
|
||
return true;
|
||
}
|
||
}
|
||
|
||
public class UnitActionKomeijiBonePileBoom : UnitActionAction
|
||
{
|
||
public UnitActionKomeijiBonePileBoom(CommonActionId id) : base(id)
|
||
{
|
||
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
var unit = actionParams.UnitData;
|
||
var map = actionParams.MapData;
|
||
if (unit == null || !unit.Grid(map, out var grid)) return false;
|
||
|
||
//Step #1 对周围1格范围的单位(不包括自己)造成2点溅射伤害并添加1层KomeijiFear
|
||
_sharedAroundBuf ??= new List<GridData>();
|
||
_sharedAroundBuf.Clear();
|
||
map.GridMap.GetAroundGridData(1, 1, grid, _sharedAroundBuf);
|
||
foreach (var around in _sharedAroundBuf)
|
||
{
|
||
if (!around.RealUnit(map, out var target)) continue;
|
||
if (target.Id == unit.Id) continue;
|
||
|
||
// 缓存renderer,DamageSettlement可能导致单位死亡后无法获取
|
||
var targetRenderer = target.Renderer(map);
|
||
if (map.IsLeagueOrJustBreakByUnit(unit.Id, target.Id)) continue;
|
||
var settlement = Main.UnitLogic.DamageSettlement(map, unit, target, 2, DamageType.Splash);
|
||
|
||
if (target.IsAlive())
|
||
{
|
||
// 存活:添加恐惧并刷新UI
|
||
if (!target.GetSkill(SkillType.KomeijiFearImmune, out _))
|
||
{
|
||
target.AddOrOverrideSkill(SkillType.KomeijiFear, map, unit.Id);
|
||
// 播放恐惧VFX
|
||
around.Renderer(map)?.PlayVFXInSight(new GridVFXParams(GridVFXType.KomeijiFear));
|
||
}
|
||
|
||
if (map == Main.MapData)
|
||
{
|
||
targetRenderer?.InstantUpdateUnit(false);
|
||
targetRenderer?.RenderUpdateUnitImage();
|
||
}
|
||
}
|
||
else if (map == Main.MapData)
|
||
{
|
||
// 死亡:清除渲染
|
||
targetRenderer?.Die();
|
||
around.Renderer(map)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Die));
|
||
around.Renderer(map)?.InstantUpdateGrid();
|
||
}
|
||
|
||
// 播放伤害VFX
|
||
if (map == Main.MapData && settlement != null)
|
||
{
|
||
around.Renderer(map)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Hurt));
|
||
around.Renderer(map)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Damage, 2));
|
||
}
|
||
}
|
||
|
||
//Step #2 引爆后骨堆自身死亡
|
||
var unitRenderer = unit.Renderer(map);
|
||
Main.UnitLogic.UnitUnnaturalDie(map, unit);
|
||
if (map == Main.MapData)
|
||
{
|
||
unitRenderer?.Die();
|
||
grid.Renderer(map)?.PlayVFXInSight(new GridVFXParams(GridVFXType.Die));
|
||
grid.Renderer(map)?.InstantUpdateGrid();
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
//#step #3 check unitTypeData的EnableActions里包含此action
|
||
if (!CheckUnitEnableAction(actionParams)) return false;
|
||
return true;
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams, out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
//step #1 check基本信息
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
//#step #2 check unit属于player
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
//#step #3 check unitTypeData的EnableActions里包含此action
|
||
if (!CheckUnitEnableAction(actionParams)) return false;
|
||
return true;
|
||
}
|
||
}
|
||
|
||
public class UnitActionReimuPayClearExtermination : UnitActionAction
|
||
{
|
||
public UnitActionReimuPayClearExtermination(CommonActionId id) : base(id)
|
||
{
|
||
}
|
||
|
||
protected override bool Execute(CommonActionParams actionParams)
|
||
{
|
||
return ReimuNorwaySkillUtil.TryPayClearExtermination(actionParams.MapData, actionParams.PlayerData,
|
||
actionParams.UnitData);
|
||
}
|
||
|
||
public override int GetCost(CommonActionParams actionParams)
|
||
{
|
||
return ReimuNorwaySkillUtil.GetExterminationClearCost(actionParams?.MapData, actionParams?.UnitData);
|
||
}
|
||
|
||
public override bool CheckCan(CommonActionParams actionParams)
|
||
{
|
||
if (!CheckShow(actionParams, out _)) return false;
|
||
return actionParams.PlayerData.PlayerCoin >= GetCost(actionParams);
|
||
}
|
||
|
||
public override bool CheckShow(CommonActionParams actionParams, out ShowType showType)
|
||
{
|
||
showType = ShowType.None;
|
||
if (!UnitActionCheckBaseInfo(actionParams)) return false;
|
||
if (!UnitActionCheckUnitBelongPlayer(actionParams)) return false;
|
||
if (!actionParams.UnitData.GetSkill(SkillType.ReimuExtermination, out var skill) || skill.Level <= 0)
|
||
return false;
|
||
var cost = GetCost(actionParams);
|
||
if (cost <= 0) return false;
|
||
if (actionParams.PlayerData.PlayerCoin < cost) showType = ShowType.Cost;
|
||
return true;
|
||
}
|
||
|
||
public override ActionShowState CheckShowState(CommonActionParams actionParams)
|
||
{
|
||
if (!CheckShow(actionParams, out _)) return ActionShowState.None;
|
||
return actionParams.PlayerData.PlayerCoin >= GetCost(actionParams)
|
||
? ActionShowState.Available
|
||
: ActionShowState.Expensive;
|
||
}
|
||
}
|
||
|
||
}
|