Merge branch 'main' of http://10.27.16.144:3000/kawagiri/TH1
This commit is contained in:
commit
3527b874ef
@ -27,7 +27,7 @@ MonoBehaviour:
|
|||||||
_version: 3.33
|
_version: 3.33
|
||||||
_category:
|
_category:
|
||||||
_comments:
|
_comments:
|
||||||
_translation: {x: 71, y: 178}
|
_translation: {x: -189, y: -71}
|
||||||
_zoomFactor: 1
|
_zoomFactor: 1
|
||||||
_haltSerialization: 0
|
_haltSerialization: 0
|
||||||
_externalSerializationFile: {fileID: 0}
|
_externalSerializationFile: {fileID: 0}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ MonoBehaviour:
|
|||||||
_version: 3.33
|
_version: 3.33
|
||||||
_category:
|
_category:
|
||||||
_comments:
|
_comments:
|
||||||
_translation: {x: 109, y: -993}
|
_translation: {x: 1016, y: 32}
|
||||||
_zoomFactor: 0.8057433
|
_zoomFactor: 0.25006658
|
||||||
_haltSerialization: 0
|
_haltSerialization: 0
|
||||||
_externalSerializationFile: {fileID: 0}
|
_externalSerializationFile: {fileID: 0}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -90,8 +90,8 @@ namespace NodeCanvas.Tasks.Actions
|
|||||||
if (unitGrid.Id == grid.Id) continue;
|
if (unitGrid.Id == grid.Id) continue;
|
||||||
if (!param.MapData.GetUnitDataByGid(grid.Id, out var unit)) continue;
|
if (!param.MapData.GetUnitDataByGid(grid.Id, out var unit)) continue;
|
||||||
var dis = param.MapData.GridMap.CalcDistance(grid, target);
|
var dis = param.MapData.GridMap.CalcDistance(grid, target);
|
||||||
if (selfUnits.Contains(unit)) selfScore += unit.GetCost() / (dis + 1f);
|
if (selfUnits.Contains(unit)) selfScore += unit.GetMilitary() / (dis + 1f);
|
||||||
else enemyScore += unit.GetCost() / (dis + 1f);
|
else enemyScore += unit.GetMilitary() / (dis + 1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
var targetScore = (selfScore - enemyScore) / path.length;
|
var targetScore = (selfScore - enemyScore) / path.length;
|
||||||
|
|||||||
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* @Author: 白哉
|
||||||
|
* @Description:
|
||||||
|
* @Date: 2025年06月06日 星期五 19:06:16
|
||||||
|
* @Modify:
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Logic;
|
||||||
|
using Logic.AI;
|
||||||
|
using NodeCanvas.Framework;
|
||||||
|
using ParadoxNotion.Design;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
|
||||||
|
namespace NodeCanvas.Tasks.Actions
|
||||||
|
{
|
||||||
|
[Category("AIAction")]
|
||||||
|
[Serializable]
|
||||||
|
public class AIParamStandingTrainUnit : ActionTask
|
||||||
|
{
|
||||||
|
protected override string info => string.Format($"常备军训练单位");
|
||||||
|
|
||||||
|
protected override void OnExecute()
|
||||||
|
{
|
||||||
|
// 直接从Blackboard获取AICalculatorData
|
||||||
|
var data = blackboard.GetVariable<AICalculatorData>("Data");
|
||||||
|
if (data?.value?.TargetParam.CityData == null || data.value.AIActions.Count == 0)
|
||||||
|
{
|
||||||
|
EndAction(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var city = data.value.TargetParam.CityData;
|
||||||
|
var count = data.value.TargetParam.MapData.GetUnitCount(city.Id);
|
||||||
|
if (count >= Mathf.Min(5, city.Level * 0.6f))
|
||||||
|
{
|
||||||
|
EndAction(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var targetUnitType = UnitType.None;
|
||||||
|
// 如果不能造剑士
|
||||||
|
bool canSwordsman = false;
|
||||||
|
foreach (var aiAction in data.value.AIActions)
|
||||||
|
{
|
||||||
|
if (aiAction.ActionLogic.ActionId.UnitType == UnitType.Swordsman) canSwordsman = true;
|
||||||
|
}
|
||||||
|
if (!canSwordsman) targetUnitType = UnitType.Warrior;
|
||||||
|
// 如果回合金 < 15
|
||||||
|
if (targetUnitType == UnitType.None && Main.PlayerLogic.GetPlayerStarsPerTurn(data.value.Map, data.value.Player.Id) < 15)
|
||||||
|
{
|
||||||
|
targetUnitType = UnitType.Warrior;
|
||||||
|
}
|
||||||
|
// 否则造剑士
|
||||||
|
if (targetUnitType == UnitType.None) targetUnitType = UnitType.Swordsman;
|
||||||
|
|
||||||
|
for (int i = data.value.AIActions.Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (data.value.AIActions[i].ActionLogic.ActionId.UnitType == targetUnitType) continue;
|
||||||
|
data.value.AIActions.RemoveAt(i);
|
||||||
|
}
|
||||||
|
EndAction(data.value.AIActions.Count > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 61a78b1e94b24f748619cf5b94d8fe93
|
||||||
|
timeCreated: 1752491476
|
||||||
@ -944,6 +944,11 @@ namespace RuntimeData
|
|||||||
public GameRecord ExportGameRecord()
|
public GameRecord ExportGameRecord()
|
||||||
{
|
{
|
||||||
var gameRecord = new GameRecord();
|
var gameRecord = new GameRecord();
|
||||||
|
gameRecord.Mode = MapConfig.GameMode;
|
||||||
|
gameRecord.AIDiff = MapConfig.AIDiff;
|
||||||
|
gameRecord.Turn = PlayerMap.SelfPlayerData.Turn;
|
||||||
|
gameRecord.PlayerCivId = PlayerMap.SelfPlayerData.PlayerCivId;
|
||||||
|
gameRecord.PlayerForceId = PlayerMap.SelfPlayerData.PlayerForceId;
|
||||||
gameRecord.Score = PlayerMap.SelfPlayerData.PlayerScore;
|
gameRecord.Score = PlayerMap.SelfPlayerData.PlayerScore;
|
||||||
DateTime now = DateTime.Now;
|
DateTime now = DateTime.Now;
|
||||||
gameRecord.Time = now.ToString("yyyy.MM.dd HH:mm");
|
gameRecord.Time = now.ToString("yyyy.MM.dd HH:mm");
|
||||||
@ -953,7 +958,6 @@ namespace RuntimeData
|
|||||||
gameRecord.MapWidth = MapConfig.Width;
|
gameRecord.MapWidth = MapConfig.Width;
|
||||||
gameRecord.MapHeight = MapConfig.Height;
|
gameRecord.MapHeight = MapConfig.Height;
|
||||||
gameRecord.PlayerCount = MapConfig.PlayerCount - 1;
|
gameRecord.PlayerCount = MapConfig.PlayerCount - 1;
|
||||||
gameRecord.AIDiff = MapConfig.AIDiff;
|
|
||||||
return gameRecord;
|
return gameRecord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,10 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Logic.Action;
|
using Logic.Action;
|
||||||
|
using Logic.AI;
|
||||||
|
using NUnit.Framework;
|
||||||
using Unity.VisualScripting;
|
using Unity.VisualScripting;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -28,6 +31,7 @@ namespace RuntimeData
|
|||||||
EYE
|
EYE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 奇观状态枚举
|
// 奇观状态枚举
|
||||||
public enum WonderState
|
public enum WonderState
|
||||||
{
|
{
|
||||||
@ -39,6 +43,28 @@ namespace RuntimeData
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 外交关系枚举
|
||||||
|
public enum DiplomacyState
|
||||||
|
{
|
||||||
|
NoDiplomacy,
|
||||||
|
Neutral,
|
||||||
|
League,
|
||||||
|
War,
|
||||||
|
LeagueRupture,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 好感状态枚举
|
||||||
|
public enum FeelingState
|
||||||
|
{
|
||||||
|
Trust,
|
||||||
|
Appreciate,
|
||||||
|
Indifferent,
|
||||||
|
Suspicion,
|
||||||
|
Terrible,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class PlayerMapData : ISerializationCallbackReceiver
|
public class PlayerMapData : ISerializationCallbackReceiver
|
||||||
{
|
{
|
||||||
@ -229,6 +255,7 @@ namespace RuntimeData
|
|||||||
public List<uint> MeetPlayers;
|
public List<uint> MeetPlayers;
|
||||||
public List<uint> CurAttackPlayers;
|
public List<uint> CurAttackPlayers;
|
||||||
public List<uint> LastAttackPlayers;
|
public List<uint> LastAttackPlayers;
|
||||||
|
public DiplomacyData DiplomacyData;
|
||||||
|
|
||||||
//用于记录是否死亡,是否要centMessage来宣告死亡信息
|
//用于记录是否死亡,是否要centMessage来宣告死亡信息
|
||||||
public bool DieMark = false;
|
public bool DieMark = false;
|
||||||
@ -239,6 +266,7 @@ namespace RuntimeData
|
|||||||
Sight = new MapSightData();
|
Sight = new MapSightData();
|
||||||
TechTree = new TechTreeData();
|
TechTree = new TechTreeData();
|
||||||
Wonder = new WonderData();
|
Wonder = new WonderData();
|
||||||
|
DiplomacyData = new DiplomacyData();
|
||||||
MeetPlayers = new List<uint>();
|
MeetPlayers = new List<uint>();
|
||||||
CurAttackPlayers = new List<uint>();
|
CurAttackPlayers = new List<uint>();
|
||||||
LastAttackPlayers = new List<uint>();
|
LastAttackPlayers = new List<uint>();
|
||||||
@ -257,6 +285,7 @@ namespace RuntimeData
|
|||||||
Sight = new MapSightData();
|
Sight = new MapSightData();
|
||||||
|
|
||||||
Wonder = new WonderData();
|
Wonder = new WonderData();
|
||||||
|
DiplomacyData = new DiplomacyData();
|
||||||
CurAttackPlayers = new List<uint>();
|
CurAttackPlayers = new List<uint>();
|
||||||
LastAttackPlayers = new List<uint>();
|
LastAttackPlayers = new List<uint>();
|
||||||
MeetPlayers = new List<uint>();
|
MeetPlayers = new List<uint>();
|
||||||
@ -277,6 +306,7 @@ namespace RuntimeData
|
|||||||
Sight = new MapSightData(copyData.Sight);
|
Sight = new MapSightData(copyData.Sight);
|
||||||
TechTree = new TechTreeData(copyData.TechTree);
|
TechTree = new TechTreeData(copyData.TechTree);
|
||||||
Wonder = new WonderData(copyData.Wonder);
|
Wonder = new WonderData(copyData.Wonder);
|
||||||
|
DiplomacyData = new DiplomacyData(copyData.DiplomacyData);
|
||||||
|
|
||||||
CurAttackPlayers = new List<uint>();
|
CurAttackPlayers = new List<uint>();
|
||||||
foreach (var id in copyData.CurAttackPlayers) CurAttackPlayers.Add(id);
|
foreach (var id in copyData.CurAttackPlayers) CurAttackPlayers.Add(id);
|
||||||
@ -305,6 +335,7 @@ namespace RuntimeData
|
|||||||
Sight.DeepCopy(copyData.Sight);
|
Sight.DeepCopy(copyData.Sight);
|
||||||
TechTree.DeepCopy(copyData.TechTree);
|
TechTree.DeepCopy(copyData.TechTree);
|
||||||
Wonder.DeepCopy(copyData.Wonder);
|
Wonder.DeepCopy(copyData.Wonder);
|
||||||
|
DiplomacyData.DeepCopy(copyData.DiplomacyData);
|
||||||
|
|
||||||
CurAttackPlayers.Clear();
|
CurAttackPlayers.Clear();
|
||||||
foreach (var id in copyData.CurAttackPlayers) CurAttackPlayers.Add(id);
|
foreach (var id in copyData.CurAttackPlayers) CurAttackPlayers.Add(id);
|
||||||
@ -358,11 +389,186 @@ namespace RuntimeData
|
|||||||
|
|
||||||
skill.OnTurnStart(this, map);
|
skill.OnTurnStart(this, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RefreshFeelingValue(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnTurnEnd(MapData map)
|
public void OnTurnEnd(MapData map)
|
||||||
{
|
{
|
||||||
foreach (var skill in Skills)skill.OnTurnEnd(this, map);
|
foreach (var skill in Skills)skill.OnTurnEnd(this, map);
|
||||||
|
foreach (var player in map.PlayerMap.PlayerDataList)
|
||||||
|
{
|
||||||
|
if (player.Id == Id) continue;
|
||||||
|
DiplomacyData.GetCountryDiplomacyInfo(player.Id, out var selfToPlayer);
|
||||||
|
if (selfToPlayer.DiplomacyState == DiplomacyState.LeagueRupture) selfToPlayer.IsLeagueRupture = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加当前回合攻击者
|
||||||
|
public void AddAttacker(uint playerId)
|
||||||
|
{
|
||||||
|
DiplomacyData.AddTurnAttacker(Turn, playerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查前几回合内是否有攻击者
|
||||||
|
public bool CheckTurnsAttacker(uint turns, uint playerId)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < turns; i++)
|
||||||
|
{
|
||||||
|
if (Turn < i) return false;
|
||||||
|
if (!DiplomacyData.CheckTurnAttacker(Turn - (uint)i, playerId)) continue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新对他国好感值
|
||||||
|
public void RefreshFeelingValue(MapData map)
|
||||||
|
{
|
||||||
|
int maxScore = 0;
|
||||||
|
uint maxScorePlayer = 0;
|
||||||
|
foreach (var player in map.PlayerMap.PlayerDataList)
|
||||||
|
{
|
||||||
|
if (player.PlayerScore <= maxScore) continue;
|
||||||
|
maxScore = player.PlayerScore;
|
||||||
|
maxScorePlayer = player.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var player in map.PlayerMap.PlayerDataList)
|
||||||
|
{
|
||||||
|
if (player.Id == Id) continue;
|
||||||
|
DiplomacyData.GetCountryDiplomacyInfo(player.Id, out var selfToPlayer);
|
||||||
|
player.DiplomacyData.GetCountryDiplomacyInfo(Id, out var playerToSelf);
|
||||||
|
if (playerToSelf == null || selfToPlayer == null) continue;
|
||||||
|
var score = 0f;
|
||||||
|
|
||||||
|
// 明智的 愚蠢的
|
||||||
|
var score1 = 0f;
|
||||||
|
foreach (var otherPlayer in map.PlayerMap.PlayerDataList)
|
||||||
|
{
|
||||||
|
if (otherPlayer.Id == Id || otherPlayer.Id == player.Id) continue;
|
||||||
|
DiplomacyData.GetCountryDiplomacyInfo(player.Id, out var selfToOtherPlayer);
|
||||||
|
if (selfToOtherPlayer.DiplomacyState == DiplomacyState.NoDiplomacy) continue;
|
||||||
|
player.DiplomacyData.GetCountryDiplomacyInfo(player.Id, out var playerToOtherPlayer);
|
||||||
|
if (playerToOtherPlayer.DiplomacyState == DiplomacyState.NoDiplomacy) continue;
|
||||||
|
|
||||||
|
if (selfToOtherPlayer.DiplomacyState == playerToOtherPlayer.DiplomacyState) score1 += 5;
|
||||||
|
else score1 -= 5;
|
||||||
|
}
|
||||||
|
if (score1 + 5 > 0) score += Mathf.Min(20, score1);
|
||||||
|
if (score1 - 5 < 0) score += Mathf.Max(-20, score1);
|
||||||
|
|
||||||
|
// 迷人的 恼人的
|
||||||
|
if (map.MapConfig.AIDiff == AIDifficult.EASY && player.Id == map.PlayerMap.SelfPlayerId &&
|
||||||
|
Id != map.PlayerMap.SelfPlayerId) score += 15;
|
||||||
|
if (map.MapConfig.AIDiff == AIDifficult.LUNATIC && player.Id == map.PlayerMap.SelfPlayerId &&
|
||||||
|
Id != map.PlayerMap.SelfPlayerId) score -= 15;
|
||||||
|
|
||||||
|
// 和平的 暴力的
|
||||||
|
if (!CheckTurnsAttacker(3, player.Id)) score += 15;
|
||||||
|
else score -= 15;
|
||||||
|
|
||||||
|
// 外交的
|
||||||
|
if (selfToPlayer.IsEmbassy || playerToSelf.IsEmbassy) score += 15;
|
||||||
|
|
||||||
|
// 强大的 弱小的
|
||||||
|
var selfScore = 0f;
|
||||||
|
var playerScore = 0f;
|
||||||
|
foreach (var gridId in Sight.SightGidSet)
|
||||||
|
{
|
||||||
|
if (!map.GetUnitDataByGid(gridId, out var unit)) continue;
|
||||||
|
if (!map.GetPlayerIdByUnitId(unit.Id, out var ownerId)) continue;
|
||||||
|
if (ownerId == Id) selfScore += unit.GetMilitary();
|
||||||
|
if (ownerId == player.Id) playerScore += unit.GetMilitary();
|
||||||
|
}
|
||||||
|
if (selfScore < playerScore) score += 15;
|
||||||
|
if (selfScore > playerScore) score -= 15;
|
||||||
|
|
||||||
|
// 勇敢的
|
||||||
|
if (maxScorePlayer != Id)
|
||||||
|
{
|
||||||
|
player.DiplomacyData.GetCountryDiplomacyInfo(maxScorePlayer, out var playerToMaxScorePlayer);
|
||||||
|
if (playerToMaxScorePlayer.DiplomacyState == DiplomacyState.War) score += 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 威胁的
|
||||||
|
var playerUnit = new HashSet<UnitData>();
|
||||||
|
map.GetUnitDataListByPlayerId(player.Id, playerUnit);
|
||||||
|
var selfTerritory = map.GetPlayerTerritoryGridIdSet(Id);
|
||||||
|
foreach (var gridId in selfTerritory)
|
||||||
|
{
|
||||||
|
if (!map.GridMap.GetGridDataByGid(gridId, out var gridData)) continue;
|
||||||
|
foreach (var unit in playerUnit)
|
||||||
|
{
|
||||||
|
if (!map.GetGridDataByUnitId(unit.Id, out var unitGrid)) continue;
|
||||||
|
var dis = map.GridMap.CalcDistance(unitGrid, gridData);
|
||||||
|
if (dis > 1) continue;
|
||||||
|
score -= 15;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 侵略的
|
||||||
|
var playerTerritory = map.GetPlayerTerritoryGridIdSet(player.Id);
|
||||||
|
foreach (var playerGridId in playerTerritory)
|
||||||
|
{
|
||||||
|
if (!map.GridMap.GetGridDataByGid(playerGridId, out var playerGrid)) continue;
|
||||||
|
foreach (var selfGridId in selfTerritory)
|
||||||
|
{
|
||||||
|
if (!map.GridMap.GetGridDataByGid(selfGridId, out var selfGrid)) continue;
|
||||||
|
var dis = map.GridMap.CalcDistance(playerGrid, selfGrid);
|
||||||
|
if (dis > 1) continue;
|
||||||
|
score -= 15;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主宰的
|
||||||
|
if (maxScorePlayer == player.Id)
|
||||||
|
{
|
||||||
|
var count = 0;
|
||||||
|
var playerCity = new HashSet<CityData>();
|
||||||
|
map.GetCityDataListByPlayerId(player.Id, playerCity);
|
||||||
|
foreach (var city in playerCity) if (city.IsCradle) count++;
|
||||||
|
if (count > 0) count--;
|
||||||
|
score -= 15 + count * 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
score = Mathf.Max(0, score);
|
||||||
|
selfToPlayer.FeelingValue = score;
|
||||||
|
if (score <= 10) selfToPlayer.FeelingState = FeelingState.Terrible;
|
||||||
|
else if (score <= 30) selfToPlayer.FeelingState = FeelingState.Suspicion;
|
||||||
|
else if (score <= 60) selfToPlayer.FeelingState = FeelingState.Indifferent;
|
||||||
|
else if (score <= 85) selfToPlayer.FeelingState = FeelingState.Appreciate;
|
||||||
|
else if (score <= 100) selfToPlayer.FeelingState = FeelingState.Trust;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新对他国的外交关系
|
||||||
|
public void RefreshDiplomacyState(MapData map)
|
||||||
|
{
|
||||||
|
foreach (var player in map.PlayerMap.PlayerDataList)
|
||||||
|
{
|
||||||
|
if (player.Id == Id) continue;
|
||||||
|
DiplomacyData.GetCountryDiplomacyInfo(player.Id, out var selfToPlayer);
|
||||||
|
player.DiplomacyData.GetCountryDiplomacyInfo(Id, out var playerToSelf);
|
||||||
|
// 如果没有外交关系,且没有见过面,则设置为无外交关系
|
||||||
|
if (!MeetPlayers.Contains(player.Id)) selfToPlayer.DiplomacyState = DiplomacyState.NoDiplomacy;
|
||||||
|
// 如果没有外交关系,且见过面,则设置为中立
|
||||||
|
else if (selfToPlayer.DiplomacyState == DiplomacyState.NoDiplomacy)
|
||||||
|
selfToPlayer.DiplomacyState = DiplomacyState.Neutral;
|
||||||
|
// 如果上一回合回合内双方未发生战斗,则该回合开始时变为中立关系
|
||||||
|
if (selfToPlayer.DiplomacyState == DiplomacyState.War && !LastAttackPlayers.Contains(player.Id))
|
||||||
|
selfToPlayer.DiplomacyState = DiplomacyState.Neutral;
|
||||||
|
if (selfToPlayer.DiplomacyState == DiplomacyState.LeagueRupture &&
|
||||||
|
playerToSelf.DiplomacyState == DiplomacyState.LeagueRupture &&
|
||||||
|
selfToPlayer.IsLeagueRupture && playerToSelf.IsLeagueRupture)
|
||||||
|
{
|
||||||
|
selfToPlayer.DiplomacyState = DiplomacyState.Neutral;
|
||||||
|
playerToSelf.DiplomacyState = DiplomacyState.Neutral;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -640,4 +846,125 @@ namespace RuntimeData
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 主动攻击我的敌人信息
|
||||||
|
[Serializable]
|
||||||
|
public class DiplomacyData : ISerializationCallbackReceiver
|
||||||
|
{
|
||||||
|
public List<CountryDiplomacyInfo> Info;
|
||||||
|
private Dictionary<uint, CountryDiplomacyInfo> _infoDict;
|
||||||
|
|
||||||
|
public DiplomacyData()
|
||||||
|
{
|
||||||
|
Info = new List<CountryDiplomacyInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiplomacyData(DiplomacyData copyData)
|
||||||
|
{
|
||||||
|
Info = new List<CountryDiplomacyInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeepCopy(DiplomacyData copyData)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < copyData.Info.Count; i++)
|
||||||
|
{
|
||||||
|
if (Info.Count <= i) Info.Add(new CountryDiplomacyInfo());
|
||||||
|
Info[i].DeepCopy(copyData.Info[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckTurnAttacker(uint turn, uint playerId)
|
||||||
|
{
|
||||||
|
GetCountryDiplomacyInfo(playerId, out var info);
|
||||||
|
if (info == null) return false;
|
||||||
|
return info.AttackTurn == 0 || info.AttackTurn < turn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddTurnAttacker(uint playerId, uint turn)
|
||||||
|
{
|
||||||
|
GetCountryDiplomacyInfo(playerId, out var info);
|
||||||
|
if (info == null) return;
|
||||||
|
info.AttackTurn = turn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetCountryDiplomacyInfo(uint playerId, out CountryDiplomacyInfo info)
|
||||||
|
{
|
||||||
|
Refresh();
|
||||||
|
if (!_infoDict.TryGetValue(playerId, out info))
|
||||||
|
{
|
||||||
|
info = new CountryDiplomacyInfo { PlayerId = playerId };
|
||||||
|
Info.Add(info);
|
||||||
|
_infoDict[playerId] = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Refresh()
|
||||||
|
{
|
||||||
|
if (_infoDict == null) _infoDict = new Dictionary<uint, CountryDiplomacyInfo>();
|
||||||
|
if (_infoDict.Count == Info.Count) return;
|
||||||
|
|
||||||
|
_infoDict.Clear();
|
||||||
|
foreach (var countryDiplomacy in Info) _infoDict[countryDiplomacy.PlayerId] = countryDiplomacy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnBeforeSerialize()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnAfterDeserialize()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 对他国的数据
|
||||||
|
[Serializable]
|
||||||
|
public class CountryDiplomacyInfo
|
||||||
|
{
|
||||||
|
public uint PlayerId;
|
||||||
|
// 我对国家 PlayerId 的外交关系
|
||||||
|
public DiplomacyState DiplomacyState;
|
||||||
|
// 我对国家 PlayerId 的好感值
|
||||||
|
public float FeelingValue;
|
||||||
|
// 我对国家 PlayerId 的好感态度
|
||||||
|
public FeelingState FeelingState;
|
||||||
|
// 国家 PlayerId 攻击我的回合记录
|
||||||
|
public uint AttackTurn;
|
||||||
|
// 国家 PlayerId 是否在我国建立了大使馆
|
||||||
|
public bool IsEmbassy;
|
||||||
|
// 联盟破裂回合结束标记
|
||||||
|
public bool IsLeagueRupture;
|
||||||
|
|
||||||
|
public CountryDiplomacyInfo()
|
||||||
|
{
|
||||||
|
AttackTurn = 0;
|
||||||
|
IsEmbassy = false;
|
||||||
|
IsLeagueRupture = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CountryDiplomacyInfo(CountryDiplomacyInfo copyData)
|
||||||
|
{
|
||||||
|
PlayerId = copyData.PlayerId;
|
||||||
|
AttackTurn = copyData.AttackTurn;
|
||||||
|
DiplomacyState = copyData.DiplomacyState;
|
||||||
|
FeelingValue = copyData.FeelingValue;
|
||||||
|
FeelingState = copyData.FeelingState;
|
||||||
|
IsEmbassy = copyData.IsEmbassy;
|
||||||
|
IsLeagueRupture = copyData.IsLeagueRupture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeepCopy(CountryDiplomacyInfo copyData)
|
||||||
|
{
|
||||||
|
PlayerId = copyData.PlayerId;
|
||||||
|
AttackTurn = copyData.AttackTurn;
|
||||||
|
DiplomacyState = copyData.DiplomacyState;
|
||||||
|
FeelingValue = copyData.FeelingValue;
|
||||||
|
FeelingState = copyData.FeelingState;
|
||||||
|
IsEmbassy = copyData.IsEmbassy;
|
||||||
|
IsLeagueRupture = copyData.IsLeagueRupture;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -206,12 +206,20 @@ namespace RuntimeData
|
|||||||
return (float)Health / GetMaxHealth();
|
return (float)Health / GetMaxHealth();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取军事分
|
||||||
|
public float GetMilitary()
|
||||||
|
{
|
||||||
|
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitType, GiantType, out var info))
|
||||||
|
return 0;
|
||||||
|
if (GetHealthRatio() <= 0.5f) return info.Cost * 0.5f;
|
||||||
|
return info.Cost;
|
||||||
|
}
|
||||||
|
|
||||||
// 获取造价
|
// 获取造价
|
||||||
public float GetCost()
|
public float GetCost()
|
||||||
{
|
{
|
||||||
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitType, GiantType, out var info))
|
if (!Table.Instance.UnitTypeDataAssets.GetUnitTypeInfo(UnitType, GiantType, out var info))
|
||||||
return 0;
|
return 0;
|
||||||
if (GetHealthRatio() <= 0.5f) return info.Cost * 0.5f;
|
|
||||||
return info.Cost;
|
return info.Cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -108,6 +108,7 @@ namespace Logic.AI
|
|||||||
TechResource,
|
TechResource,
|
||||||
CityTrainDefendAttack,
|
CityTrainDefendAttack,
|
||||||
AroundGapScoreMax,
|
AroundGapScoreMax,
|
||||||
|
CityTrainMilitary,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -118,9 +119,7 @@ namespace Logic.AI
|
|||||||
public MapData Map;
|
public MapData Map;
|
||||||
public PlayerData Player;
|
public PlayerData Player;
|
||||||
public Strategy CountryStrategy;
|
public Strategy CountryStrategy;
|
||||||
public PlayerData AttackPlayer;
|
public HashSet<PlayerData> AttackPlayerSet;
|
||||||
public CountryAttackType AttackType;
|
|
||||||
public PlayerData DefendTarget;
|
|
||||||
|
|
||||||
// 策略集合
|
// 策略集合
|
||||||
public Dictionary<CityData, Strategy> CityStrategy;
|
public Dictionary<CityData, Strategy> CityStrategy;
|
||||||
@ -203,6 +202,7 @@ namespace Logic.AI
|
|||||||
|
|
||||||
public AICalculatorData()
|
public AICalculatorData()
|
||||||
{
|
{
|
||||||
|
AttackPlayerSet = new HashSet<PlayerData>();
|
||||||
CityStrategy = new Dictionary<CityData, Strategy>();
|
CityStrategy = new Dictionary<CityData, Strategy>();
|
||||||
FreeUnitStrategy = new Dictionary<UnitData, Strategy>();
|
FreeUnitStrategy = new Dictionary<UnitData, Strategy>();
|
||||||
LegionStrategy = new Dictionary<uint, Strategy>();
|
LegionStrategy = new Dictionary<uint, Strategy>();
|
||||||
@ -255,9 +255,7 @@ namespace Logic.AI
|
|||||||
Map = map;
|
Map = map;
|
||||||
Player = player;
|
Player = player;
|
||||||
CountryStrategy = Strategy.None;
|
CountryStrategy = Strategy.None;
|
||||||
AttackPlayer = null;
|
AttackPlayerSet.Clear();
|
||||||
AttackType = CountryAttackType.None;
|
|
||||||
DefendTarget = null;
|
|
||||||
IsFinish = false;
|
IsFinish = false;
|
||||||
|
|
||||||
AIActions.Clear();
|
AIActions.Clear();
|
||||||
@ -625,7 +623,7 @@ namespace Logic.AI
|
|||||||
var score = 0f;
|
var score = 0f;
|
||||||
foreach (var unit in kv.Value)
|
foreach (var unit in kv.Value)
|
||||||
{
|
{
|
||||||
score += unit.GetCost();
|
score += unit.GetMilitary();
|
||||||
}
|
}
|
||||||
LegionScore[kv.Key] = score;
|
LegionScore[kv.Key] = score;
|
||||||
}
|
}
|
||||||
@ -637,7 +635,7 @@ namespace Logic.AI
|
|||||||
foreach (var unit in kv.Value)
|
foreach (var unit in kv.Value)
|
||||||
{
|
{
|
||||||
if (!Map.GetGridDataByUnitId(unit.Id, out var grid)) continue;
|
if (!Map.GetGridDataByUnitId(unit.Id, out var grid)) continue;
|
||||||
var ratio = unit.GetCost() / score;
|
var ratio = unit.GetMilitary() / score;
|
||||||
vec += new Vector2(grid.Pos.X, grid.Pos.Y) * ratio;
|
vec += new Vector2(grid.Pos.X, grid.Pos.Y) * ratio;
|
||||||
}
|
}
|
||||||
var center = new Vector2Int((int)Math.Round(vec.X), (int)Math.Round(vec.Y));
|
var center = new Vector2Int((int)Math.Round(vec.X), (int)Math.Round(vec.Y));
|
||||||
@ -772,6 +770,9 @@ namespace Logic.AI
|
|||||||
{
|
{
|
||||||
foreach (var cityId in CityBorder)
|
foreach (var cityId in CityBorder)
|
||||||
{
|
{
|
||||||
|
if (!Map.GetPlayerIdByCityId(cityId, out var ownerId)) continue;
|
||||||
|
if(!Map.PlayerMap.GetPlayerDataByPlayerID(ownerId, out var owner)) continue;
|
||||||
|
if (!AttackPlayerSet.Contains(owner)) continue;
|
||||||
if (!LegionCanMoveCities[legionId].Contains(cityId)) continue;
|
if (!LegionCanMoveCities[legionId].Contains(cityId)) continue;
|
||||||
if (!Map.GetGridDataByCityId(cityId, out var cityGrid)) continue;
|
if (!Map.GetGridDataByCityId(cityId, out var cityGrid)) continue;
|
||||||
var dis = Map.GridMap.CalcDistance(cityGrid, LegionGrid[legionId]) + 1;
|
var dis = Map.GridMap.CalcDistance(cityGrid, LegionGrid[legionId]) + 1;
|
||||||
@ -918,8 +919,8 @@ namespace Logic.AI
|
|||||||
foreach (var aroundGrid in aroundGrids)
|
foreach (var aroundGrid in aroundGrids)
|
||||||
{
|
{
|
||||||
if (!Map.GetUnitDataByGid(aroundGrid.Id, out var attacker)) continue;
|
if (!Map.GetUnitDataByGid(aroundGrid.Id, out var attacker)) continue;
|
||||||
if (!selfUnit.Contains(attacker)) score += attacker.GetCost();
|
if (!selfUnit.Contains(attacker)) score += attacker.GetMilitary();
|
||||||
else score -= attacker.GetCost();
|
else score -= attacker.GetMilitary();
|
||||||
}
|
}
|
||||||
if (score > 6f)
|
if (score > 6f)
|
||||||
{
|
{
|
||||||
@ -1074,7 +1075,7 @@ namespace Logic.AI
|
|||||||
var score = 0f;
|
var score = 0f;
|
||||||
var unitList = new List<UnitData>();
|
var unitList = new List<UnitData>();
|
||||||
Map.GetUnitDataListByPlayerId(player.Id, unitList);
|
Map.GetUnitDataListByPlayerId(player.Id, unitList);
|
||||||
foreach (var unit in unitList) score += unit.GetCost();
|
foreach (var unit in unitList) score += unit.GetMilitary();
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1143,140 +1144,92 @@ namespace Logic.AI
|
|||||||
// 计算两个小兵的克制分 克制分表 克制表
|
// 计算两个小兵的克制分 克制分表 克制表
|
||||||
public float CalUnitCounterScore(UnitType self, UnitType target)
|
public float CalUnitCounterScore(UnitType self, UnitType target)
|
||||||
{
|
{
|
||||||
if (self == UnitType.Warrior && target == UnitType.Warrior) return 0;
|
|
||||||
if (self == UnitType.Archer && target == UnitType.Warrior) return 1;
|
if (self == UnitType.Archer && target == UnitType.Warrior) return 1;
|
||||||
if (self == UnitType.Defender && target == UnitType.Warrior) return -0.5f;
|
if (self == UnitType.Swordsman && target == UnitType.Warrior) return 1f;
|
||||||
if (self == UnitType.Rider && target == UnitType.Warrior) return 0;
|
|
||||||
if (self == UnitType.Knights && target == UnitType.Warrior) return 3;
|
|
||||||
if (self == UnitType.Catapult && target == UnitType.Warrior) return 3;
|
|
||||||
if (self == UnitType.Swordsman && target == UnitType.Warrior) return 0.5f;
|
|
||||||
if (self == UnitType.Boat && target == UnitType.Warrior) return 0;
|
|
||||||
if (self == UnitType.RammerShip && target == UnitType.Warrior) return 0.5f;
|
|
||||||
if (self == UnitType.Ship && target == UnitType.Warrior) return 1f;
|
|
||||||
if (self == UnitType.BomberShip && target == UnitType.Warrior) return 1.5f;
|
|
||||||
|
|
||||||
if (self == UnitType.Warrior && target == UnitType.Archer) return 0.5f;
|
|
||||||
if (self == UnitType.Archer && target == UnitType.Archer) return 0;
|
|
||||||
if (self == UnitType.Defender && target == UnitType.Archer) return -0.5f;
|
|
||||||
if (self == UnitType.Rider && target == UnitType.Archer) return 1;
|
if (self == UnitType.Rider && target == UnitType.Archer) return 1;
|
||||||
if (self == UnitType.Knights && target == UnitType.Archer) return 3;
|
if (self == UnitType.Knights && target == UnitType.Archer) return 3;
|
||||||
if (self == UnitType.Catapult && target == UnitType.Archer) return 3;
|
|
||||||
if (self == UnitType.Swordsman && target == UnitType.Archer) return 3;
|
|
||||||
if (self == UnitType.Boat && target == UnitType.Archer) return 0;
|
|
||||||
if (self == UnitType.RammerShip && target == UnitType.Archer) return 3f;
|
|
||||||
if (self == UnitType.Ship && target == UnitType.Archer) return 0f;
|
|
||||||
if (self == UnitType.BomberShip && target == UnitType.Archer) return 3f;
|
|
||||||
|
|
||||||
if (self == UnitType.Warrior && target == UnitType.Defender) return -1f;
|
if (self == UnitType.Archer && target == UnitType.Defender) return 1f;
|
||||||
if (self == UnitType.Archer && target == UnitType.Defender) return 0.5f;
|
|
||||||
if (self == UnitType.Defender && target == UnitType.Defender) return -2f;
|
|
||||||
if (self == UnitType.Rider && target == UnitType.Defender) return -1.5f;
|
|
||||||
if (self == UnitType.Knights && target == UnitType.Defender) return 0;
|
|
||||||
if (self == UnitType.Catapult && target == UnitType.Defender) return 2;
|
if (self == UnitType.Catapult && target == UnitType.Defender) return 2;
|
||||||
if (self == UnitType.Swordsman && target == UnitType.Defender) return 0;
|
if (self == UnitType.Swordsman && target == UnitType.Defender) return 1;
|
||||||
if (self == UnitType.Boat && target == UnitType.Defender) return 0;
|
if (self == UnitType.RammerShip && target == UnitType.Defender) return 1;
|
||||||
if (self == UnitType.RammerShip && target == UnitType.Defender) return 0;
|
if (self == UnitType.Ship && target == UnitType.Defender) return 1f;
|
||||||
if (self == UnitType.Ship && target == UnitType.Defender) return 0.5f;
|
if (self == UnitType.BomberShip && target == UnitType.Defender) return 2f;
|
||||||
if (self == UnitType.BomberShip && target == UnitType.Defender) return 1.5f;
|
|
||||||
|
|
||||||
if (self == UnitType.Warrior && target == UnitType.Rider) return 0.5f;
|
if (self == UnitType.Archer && target == UnitType.Rider) return 1f;
|
||||||
if (self == UnitType.Archer && target == UnitType.Rider) return 1.5f;
|
|
||||||
if (self == UnitType.Defender && target == UnitType.Rider) return 0;
|
|
||||||
if (self == UnitType.Rider && target == UnitType.Rider) return 0.5f;
|
|
||||||
if (self == UnitType.Knights && target == UnitType.Rider) return 3;
|
|
||||||
if (self == UnitType.Catapult && target == UnitType.Rider) return 3;
|
|
||||||
if (self == UnitType.Swordsman && target == UnitType.Rider) return 3;
|
|
||||||
if (self == UnitType.Boat && target == UnitType.Rider) return 0;
|
|
||||||
if (self == UnitType.RammerShip && target == UnitType.Rider) return 3f;
|
|
||||||
if (self == UnitType.Ship && target == UnitType.Rider) return 1.5f;
|
|
||||||
if (self == UnitType.BomberShip && target == UnitType.Rider) return 3f;
|
|
||||||
|
|
||||||
if (self == UnitType.Warrior && target == UnitType.Knights) return 0.5f;
|
if (self == UnitType.Rider && target == UnitType.Catapult) return 1;
|
||||||
if (self == UnitType.Archer && target == UnitType.Knights) return 1.5f;
|
|
||||||
if (self == UnitType.Defender && target == UnitType.Knights) return 0f;
|
|
||||||
if (self == UnitType.Rider && target == UnitType.Knights) return 0.5f;
|
|
||||||
if (self == UnitType.Knights && target == UnitType.Knights) return 3f;
|
|
||||||
if (self == UnitType.Catapult && target == UnitType.Knights) return 3f;
|
|
||||||
if (self == UnitType.Swordsman && target == UnitType.Knights) return 3f;
|
|
||||||
if (self == UnitType.Boat && target == UnitType.Knights) return 0f;
|
|
||||||
if (self == UnitType.RammerShip && target == UnitType.Knights) return 3f;
|
|
||||||
if (self == UnitType.Ship && target == UnitType.Knights) return 1.5f;
|
|
||||||
if (self == UnitType.BomberShip && target == UnitType.Knights) return 3f;
|
|
||||||
|
|
||||||
if (self == UnitType.Warrior && target == UnitType.Catapult) return 2;
|
|
||||||
if (self == UnitType.Archer && target == UnitType.Catapult) return 2;
|
|
||||||
if (self == UnitType.Defender && target == UnitType.Catapult) return 1;
|
|
||||||
if (self == UnitType.Rider && target == UnitType.Catapult) return 2;
|
|
||||||
if (self == UnitType.Knights && target == UnitType.Catapult) return 3;
|
if (self == UnitType.Knights && target == UnitType.Catapult) return 3;
|
||||||
if (self == UnitType.Catapult && target == UnitType.Catapult) return 3;
|
|
||||||
if (self == UnitType.Swordsman && target == UnitType.Catapult) return 3;
|
|
||||||
if (self == UnitType.Boat && target == UnitType.Catapult) return 0;
|
|
||||||
if (self == UnitType.RammerShip && target == UnitType.Catapult) return 3;
|
|
||||||
if (self == UnitType.Ship && target == UnitType.Catapult) return 2f;
|
|
||||||
if (self == UnitType.BomberShip && target == UnitType.Catapult) return 3f;
|
|
||||||
|
|
||||||
if (self == UnitType.Warrior && target == UnitType.Swordsman) return -1;
|
if (self == UnitType.Catapult && target == UnitType.RammerShip) return 1;
|
||||||
if (self == UnitType.Archer && target == UnitType.Swordsman) return 0.5f;
|
if (self == UnitType.Ship && target == UnitType.RammerShip) return 1f;
|
||||||
if (self == UnitType.Defender && target == UnitType.Swordsman) return -2;
|
|
||||||
if (self == UnitType.Rider && target == UnitType.Swordsman) return -2;
|
|
||||||
if (self == UnitType.Knights && target == UnitType.Swordsman) return 1;
|
|
||||||
if (self == UnitType.Catapult && target == UnitType.Swordsman) return 2;
|
|
||||||
if (self == UnitType.Swordsman && target == UnitType.Swordsman) return 0;
|
|
||||||
if (self == UnitType.Boat && target == UnitType.Swordsman) return 0;
|
|
||||||
if (self == UnitType.RammerShip && target == UnitType.Swordsman) return 0;
|
|
||||||
if (self == UnitType.Ship && target == UnitType.Swordsman) return 0.5f;
|
|
||||||
if (self == UnitType.BomberShip && target == UnitType.Swordsman) return 1.5f;
|
|
||||||
|
|
||||||
if (self == UnitType.Warrior && target == UnitType.Boat) return 1.5f;
|
if (self == UnitType.Catapult && target == UnitType.Ship) return 1;
|
||||||
if (self == UnitType.Archer && target == UnitType.Boat) return 1.5f;
|
if (self == UnitType.RammerShip && target == UnitType.Ship) return 1;
|
||||||
if (self == UnitType.Defender && target == UnitType.Boat) return 0.5f;
|
|
||||||
if (self == UnitType.Rider && target == UnitType.Boat) return 1.5f;
|
|
||||||
if (self == UnitType.Knights && target == UnitType.Boat) return 3;
|
|
||||||
if (self == UnitType.Catapult && target == UnitType.Boat) return 3;
|
|
||||||
if (self == UnitType.Swordsman && target == UnitType.Boat) return 3;
|
|
||||||
if (self == UnitType.Boat && target == UnitType.Boat) return 0;
|
|
||||||
if (self == UnitType.RammerShip && target == UnitType.Boat) return 3;
|
|
||||||
if (self == UnitType.Ship && target == UnitType.Boat) return 1.5f;
|
|
||||||
if (self == UnitType.BomberShip && target == UnitType.Boat) return 3f;
|
|
||||||
|
|
||||||
if (self == UnitType.Warrior && target == UnitType.RammerShip) return -1;
|
if (self == UnitType.Catapult && target == UnitType.BomberShip) return 1;
|
||||||
if (self == UnitType.Archer && target == UnitType.RammerShip) return 0.5f;
|
|
||||||
if (self == UnitType.Defender && target == UnitType.RammerShip) return -2f;
|
|
||||||
if (self == UnitType.Rider && target == UnitType.RammerShip) return -2f;
|
|
||||||
if (self == UnitType.Knights && target == UnitType.RammerShip) return 1;
|
|
||||||
if (self == UnitType.Catapult && target == UnitType.RammerShip) return 3;
|
|
||||||
if (self == UnitType.Swordsman && target == UnitType.RammerShip) return 0;
|
|
||||||
if (self == UnitType.Boat && target == UnitType.RammerShip) return 0;
|
|
||||||
if (self == UnitType.RammerShip && target == UnitType.RammerShip) return 0;
|
|
||||||
if (self == UnitType.Ship && target == UnitType.RammerShip) return 0.5f;
|
|
||||||
if (self == UnitType.BomberShip && target == UnitType.RammerShip) return 1.5f;
|
|
||||||
|
|
||||||
if (self == UnitType.Warrior && target == UnitType.Ship) return 0.5f;
|
if (self == UnitType.Catapult && (target == UnitType.Giant || target == UnitType.BigGuy)) return 2;
|
||||||
if (self == UnitType.Archer && target == UnitType.Ship) return 0;
|
if (self == UnitType.Swordsman && (target == UnitType.Giant || target == UnitType.BigGuy)) return 1;
|
||||||
if (self == UnitType.Defender && target == UnitType.Ship) return -0.5f;
|
if (self == UnitType.BomberShip && (target == UnitType.Giant || target == UnitType.BigGuy)) return 2;
|
||||||
if (self == UnitType.Rider && target == UnitType.Ship) return 0;
|
|
||||||
if (self == UnitType.Knights && target == UnitType.Ship) return 3;
|
|
||||||
if (self == UnitType.Catapult && target == UnitType.Ship) return 2;
|
|
||||||
if (self == UnitType.Swordsman && target == UnitType.Ship) return 3;
|
|
||||||
if (self == UnitType.Boat && target == UnitType.Ship) return 0;
|
|
||||||
if (self == UnitType.RammerShip && target == UnitType.Ship) return 3;
|
|
||||||
if (self == UnitType.Ship && target == UnitType.Ship) return 0;
|
|
||||||
if (self == UnitType.BomberShip && target == UnitType.Ship) return 3;
|
|
||||||
|
|
||||||
if (self == UnitType.Warrior && target == UnitType.BomberShip) return 1;
|
|
||||||
if (self == UnitType.Archer && target == UnitType.BomberShip) return 1;
|
|
||||||
if (self == UnitType.Defender && target == UnitType.BomberShip) return 0.5f;
|
|
||||||
if (self == UnitType.Rider && target == UnitType.BomberShip) return 1;
|
|
||||||
if (self == UnitType.Knights && target == UnitType.BomberShip) return 3;
|
|
||||||
if (self == UnitType.Catapult && target == UnitType.BomberShip) return 3;
|
|
||||||
if (self == UnitType.Swordsman && target == UnitType.BomberShip) return 3;
|
|
||||||
if (self == UnitType.Boat && target == UnitType.BomberShip) return 0;
|
|
||||||
if (self == UnitType.RammerShip && target == UnitType.BomberShip) return 3;
|
|
||||||
if (self == UnitType.Ship && target == UnitType.BomberShip) return 1f;
|
|
||||||
if (self == UnitType.BomberShip && target == UnitType.BomberShip) return 1.5f;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 计算两个小兵的军事差距分
|
||||||
|
public float CalUnitMilitaryGapScore(MapData map, UnitData self, UnitData target)
|
||||||
|
{
|
||||||
|
var score = self.GetMilitary() - target.GetMilitary();
|
||||||
|
score += CalUnitCounterScore(self, target);
|
||||||
|
if (map.GetGridDataByUnitId(self.Id, out var selfGrid) &&
|
||||||
|
map.GetGridDataByUnitId(target.Id, out var targetGrid))
|
||||||
|
{
|
||||||
|
var selfMag = self.GetSkill(SkillType.DASH, out _)
|
||||||
|
? self.GetAttackRange() + self.MP
|
||||||
|
: self.GetAttackRange();
|
||||||
|
var dis = map.GridMap.CalcDistance(selfGrid, targetGrid);
|
||||||
|
if (dis <= selfMag)
|
||||||
|
{
|
||||||
|
var dmg = Table.Instance.CalcDamage(map, self, target);
|
||||||
|
var attackScore = (float)dmg / target.GetMaxHealth() * target.GetCost();
|
||||||
|
score += Mathf.Min(5, attackScore);
|
||||||
|
}
|
||||||
|
|
||||||
|
var targetMag = target.GetSkill(SkillType.DASH, out _)
|
||||||
|
? target.GetAttackRange() + self.MP
|
||||||
|
: target.GetAttackRange();
|
||||||
|
if (dis <= targetMag)
|
||||||
|
{
|
||||||
|
var dmg = Table.Instance.CalcDamage(map, target, self);
|
||||||
|
var attackScore = (float)dmg / self.GetMaxHealth() * self.GetCost();
|
||||||
|
score -= Mathf.Min(self.GetMilitary(), attackScore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.GetAttackRange() == 1 && map.GetPlayerIdByUnitId(self.Id, out var selfPlayerId))
|
||||||
|
{
|
||||||
|
var selfUnits = new HashSet<UnitData>();
|
||||||
|
Map.GetUnitDataListByPlayerId(selfPlayerId, selfUnits);
|
||||||
|
var count = 0;
|
||||||
|
foreach (var unit in selfUnits) if (unit.GetAttackRange() == 1) count++;
|
||||||
|
if (count / (float)selfUnits.Count < 0.6f)
|
||||||
|
score += 6 - count / (float)selfUnits.Count * 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.UnitType == UnitType.Catapult && map.GetGridDataByUnitId(self.Id, out var grid))
|
||||||
|
{
|
||||||
|
var gridList = Map.GridMap.GetAroundGridData(1, 1, grid);
|
||||||
|
bool isSea = true;
|
||||||
|
foreach (var aroundGrid in gridList)
|
||||||
|
{
|
||||||
|
if (aroundGrid.Terrain == TerrainType.Land) isSea = false;
|
||||||
|
}
|
||||||
|
if (isSea) score++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
// 计算科技对应的兵种
|
// 计算科技对应的兵种
|
||||||
public void GetUnitTypeByTech(TechType techType, out UnitType unitType, out GiantType giantType)
|
public void GetUnitTypeByTech(TechType techType, out UnitType unitType, out GiantType giantType)
|
||||||
{
|
{
|
||||||
@ -1355,7 +1308,6 @@ namespace Logic.AI
|
|||||||
if (ThreatScore[target.Id] < 10) continue;
|
if (ThreatScore[target.Id] < 10) continue;
|
||||||
if (MilitaryGapScore[target.Id] > -5) continue;
|
if (MilitaryGapScore[target.Id] > -5) continue;
|
||||||
CountryStrategy = Strategy.Defend;
|
CountryStrategy = Strategy.Defend;
|
||||||
DefendTarget = target;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1393,63 +1345,87 @@ namespace Logic.AI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int maxScore = 0;
|
||||||
|
PlayerData maxScorePlayer = null;
|
||||||
|
foreach (var player in Map.PlayerMap.PlayerDataList)
|
||||||
|
{
|
||||||
|
if (player.PlayerScore <= maxScore) continue;
|
||||||
|
maxScore = player.PlayerScore;
|
||||||
|
maxScorePlayer = player;
|
||||||
|
}
|
||||||
|
|
||||||
//然后判断是否做进攻的国家战略
|
//然后判断是否做进攻的国家战略
|
||||||
foreach (var target in Map.PlayerMap.PlayerDataList)
|
if (maxScorePlayer != null && maxScorePlayer != Player && AttackDistance[maxScorePlayer.Id] <= 5)
|
||||||
{
|
{
|
||||||
if (target == Player) continue;
|
|
||||||
if (ThreatScore[target.Id] < 10) continue;
|
|
||||||
if (MilitaryGapScore[target.Id] < 3) continue;
|
|
||||||
if (AttackDistance[target.Id] > 7) continue;
|
|
||||||
|
|
||||||
CountryStrategy = Strategy.Attack;
|
CountryStrategy = Strategy.Attack;
|
||||||
AttackPlayer = target;
|
AttackPlayerSet.Add(maxScorePlayer);
|
||||||
AttackType = CountryAttackType.CounterattackInvasions;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var target in Map.PlayerMap.PlayerDataList)
|
|
||||||
{
|
|
||||||
if (target == Player) continue;
|
|
||||||
if (MilitaryGapScore[target.Id] < 0) continue;
|
|
||||||
if (AttackDistance[target.Id] > 7) continue;
|
|
||||||
CountryStrategy = Strategy.Attack;
|
|
||||||
AttackPlayer = target;
|
|
||||||
AttackType = CountryAttackType.BullyWeak;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var target in Map.PlayerMap.PlayerDataList)
|
|
||||||
{
|
|
||||||
if (target == Player) continue;
|
|
||||||
if (MilitaryGapScore[target.Id] < 3) continue;
|
|
||||||
|
|
||||||
bool hasCityCenter = false;
|
if (maxScorePlayer != null && maxScorePlayer != Map.PlayerMap.SelfPlayerData)
|
||||||
foreach (var city in selfCity)
|
{
|
||||||
|
foreach (var target in Map.PlayerMap.PlayerDataList)
|
||||||
{
|
{
|
||||||
if (hasCityCenter) break;
|
if (target == Player) continue;
|
||||||
if(!Map.GetGridDataByCityId(city.Id,out var cityGrid)) continue;
|
if (ThreatScore[target.Id] < 10) continue;
|
||||||
var gridList = Map.GridMap.GetAroundGridData(8, 8, cityGrid);
|
if (MilitaryGapScore[target.Id] < 3) continue;
|
||||||
foreach (var grid in gridList)
|
if (AttackDistance[target.Id] > 7) continue;
|
||||||
{
|
|
||||||
if (grid.Resource != ResourceType.CityCenter) continue;
|
CountryStrategy = Strategy.Attack;
|
||||||
if (Map.GetCityDataByGid(grid.Id, out var _)) continue;
|
AttackPlayerSet.Add(target);
|
||||||
var path = PathFinder.FindPath((int)Map.MapConfig.Width, (int)Map.MapConfig.Height,
|
|
||||||
new (grid.Pos.X, grid.Pos.Y), new (cityGrid.Pos.X, cityGrid.Pos.Y), Map, Player);
|
|
||||||
if (!path.found) continue;
|
|
||||||
if (path.length > 8) continue;
|
|
||||||
hasCityCenter = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasCityCenter) continue;
|
foreach (var target in Map.PlayerMap.PlayerDataList)
|
||||||
CountryStrategy = Strategy.Attack;
|
{
|
||||||
AttackPlayer = target;
|
if (target == Player) continue;
|
||||||
AttackType = CountryAttackType.ForcedExpansion;
|
if (MilitaryGapScore[target.Id] < 0) continue;
|
||||||
return;
|
if (AttackDistance[target.Id] > 7) continue;
|
||||||
|
CountryStrategy = Strategy.Attack;
|
||||||
|
AttackPlayerSet.Add(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var target in Map.PlayerMap.PlayerDataList)
|
||||||
|
{
|
||||||
|
if (target == Player) continue;
|
||||||
|
if (MilitaryGapScore[target.Id] < 3) continue;
|
||||||
|
|
||||||
|
bool hasCityCenter = false;
|
||||||
|
foreach (var city in selfCity)
|
||||||
|
{
|
||||||
|
if (hasCityCenter) break;
|
||||||
|
if (!Map.GetGridDataByCityId(city.Id, out var cityGrid)) continue;
|
||||||
|
var gridList = Map.GridMap.GetAroundGridData(8, 8, cityGrid);
|
||||||
|
foreach (var grid in gridList)
|
||||||
|
{
|
||||||
|
if (grid.Resource != ResourceType.CityCenter) continue;
|
||||||
|
if (Map.GetCityDataByGid(grid.Id, out var _)) continue;
|
||||||
|
var path = PathFinder.FindPath((int)Map.MapConfig.Width, (int)Map.MapConfig.Height,
|
||||||
|
new(grid.Pos.X, grid.Pos.Y), new(cityGrid.Pos.X, cityGrid.Pos.Y), Map, Player);
|
||||||
|
if (!path.found) continue;
|
||||||
|
if (path.length > 8) continue;
|
||||||
|
hasCityCenter = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasCityCenter) continue;
|
||||||
|
CountryStrategy = Strategy.Attack;
|
||||||
|
AttackPlayerSet.Add(target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CountryStrategy = Strategy.Development;
|
if (maxScorePlayer != null && maxScorePlayer == Map.PlayerMap.SelfPlayerData)
|
||||||
|
{
|
||||||
|
foreach (var target in Map.PlayerMap.PlayerDataList)
|
||||||
|
{
|
||||||
|
if (target == Player) continue;
|
||||||
|
if (MilitaryGapScore[target.Id] < 0) continue;
|
||||||
|
if (AttackDistance[target.Id] > 5) continue;
|
||||||
|
CountryStrategy = Strategy.Attack;
|
||||||
|
AttackPlayerSet.Add(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CountryStrategy == Strategy.None) CountryStrategy = Strategy.Development;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算城市周围单位
|
// 计算城市周围单位
|
||||||
@ -1476,7 +1452,7 @@ namespace Logic.AI
|
|||||||
private float CalCityDefendScore(CityData city)
|
private float CalCityDefendScore(CityData city)
|
||||||
{
|
{
|
||||||
var score = 0f;
|
var score = 0f;
|
||||||
foreach (var unit in CityDefendUnits[city.Id]) score += unit.GetCost();
|
foreach (var unit in CityDefendUnits[city.Id]) score += unit.GetMilitary();
|
||||||
if (city.CityWall) score += 2;
|
if (city.CityWall) score += 2;
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
@ -1493,7 +1469,7 @@ namespace Logic.AI
|
|||||||
{
|
{
|
||||||
if (!Map.GetGridDataByUnitId(unit.Id, out var unitGrid)) continue;
|
if (!Map.GetGridDataByUnitId(unit.Id, out var unitGrid)) continue;
|
||||||
var distance = Map.GridMap.CalcDistance(cityGrid, unitGrid);
|
var distance = Map.GridMap.CalcDistance(cityGrid, unitGrid);
|
||||||
score += unit.GetCost() / (distance + 1);
|
score += unit.GetMilitary() / (distance + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return score;
|
return score;
|
||||||
@ -1503,7 +1479,7 @@ namespace Logic.AI
|
|||||||
private float CalCityEnemyScore(CityData city)
|
private float CalCityEnemyScore(CityData city)
|
||||||
{
|
{
|
||||||
var score = 0f;
|
var score = 0f;
|
||||||
foreach (var unit in CityEnemyUnits[city.Id]) score += unit.GetCost();
|
foreach (var unit in CityEnemyUnits[city.Id]) score += unit.GetMilitary();
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1542,7 +1518,7 @@ namespace Logic.AI
|
|||||||
3 => 0,
|
3 => 0,
|
||||||
_ => ratio
|
_ => ratio
|
||||||
};
|
};
|
||||||
score += unit.GetCost() * ratio;
|
score += unit.GetMilitary() * ratio;
|
||||||
}
|
}
|
||||||
foreach (var unit in CityDefendUnits[city.Id])
|
foreach (var unit in CityDefendUnits[city.Id])
|
||||||
{
|
{
|
||||||
@ -1559,7 +1535,7 @@ namespace Logic.AI
|
|||||||
3 => 0,
|
3 => 0,
|
||||||
_ => ratio
|
_ => ratio
|
||||||
};
|
};
|
||||||
score -= unit.GetCost() * ratio;
|
score -= unit.GetMilitary() * ratio;
|
||||||
}
|
}
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
@ -1701,7 +1677,7 @@ namespace Logic.AI
|
|||||||
for (int i = selfCity.Count - 1; i >= 0; i--)
|
for (int i = selfCity.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var city = selfCity[i];
|
var city = selfCity[i];
|
||||||
if (PlayerBorderDistance[city.Id] < 5) continue;
|
if (PlayerBorderDistance[city.Id] > 5) continue;
|
||||||
if (CityDangerScore[city.Id] <= 0) continue;
|
if (CityDangerScore[city.Id] <= 0) continue;
|
||||||
CityStrategy[city] = Strategy.Military;
|
CityStrategy[city] = Strategy.Military;
|
||||||
selfCity.RemoveAt(i);
|
selfCity.RemoveAt(i);
|
||||||
|
|||||||
@ -6,11 +6,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
using System;
|
||||||
using RuntimeData;
|
using RuntimeData;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Logic.Action;
|
using Logic.Action;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using Random = UnityEngine.Random;
|
||||||
|
|
||||||
|
|
||||||
namespace Logic.AI
|
namespace Logic.AI
|
||||||
@ -707,6 +709,7 @@ namespace Logic.AI
|
|||||||
|
|
||||||
if (type == CalculateType.CityTrainDefend) CalculateCityTrainDefend(data, param, result);
|
if (type == CalculateType.CityTrainDefend) CalculateCityTrainDefend(data, param, result);
|
||||||
if (type == CalculateType.CityTrainAttack) CalculateCityTrainAttack(data, param, result);
|
if (type == CalculateType.CityTrainAttack) CalculateCityTrainAttack(data, param, result);
|
||||||
|
if (type == CalculateType.CityTrainMilitary) CalculateCityTrainMilitary(data, param, result);
|
||||||
if (type == CalculateType.CityDevelopment) CalculateCityDevelopment(data, param, result);
|
if (type == CalculateType.CityDevelopment) CalculateCityDevelopment(data, param, result);
|
||||||
if (type == CalculateType.CityTrainDefendAttack) CalculateCityTrainDefendAttack(data, param, result);
|
if (type == CalculateType.CityTrainDefendAttack) CalculateCityTrainDefendAttack(data, param, result);
|
||||||
|
|
||||||
@ -806,7 +809,7 @@ namespace Logic.AI
|
|||||||
foreach (var unit in param.MapData.UnitMap.UnitList)
|
foreach (var unit in param.MapData.UnitMap.UnitList)
|
||||||
{
|
{
|
||||||
if (selfUnits.Contains(unit)) continue;
|
if (selfUnits.Contains(unit)) continue;
|
||||||
score += unit.GetCost();
|
score += unit.GetMilitary();
|
||||||
}
|
}
|
||||||
result.Score[CalculateType.LegionDevelopmentKill] = 1f / (score + 1);
|
result.Score[CalculateType.LegionDevelopmentKill] = 1f / (score + 1);
|
||||||
}
|
}
|
||||||
@ -889,7 +892,7 @@ namespace Logic.AI
|
|||||||
{
|
{
|
||||||
if (!param.MapData.GetUnitDataByGid(aroundGrid.Id, out var aroundUnit)) continue;
|
if (!param.MapData.GetUnitDataByGid(aroundGrid.Id, out var aroundUnit)) continue;
|
||||||
if (!selfUnits.Contains(aroundUnit)) continue;
|
if (!selfUnits.Contains(aroundUnit)) continue;
|
||||||
score += aroundUnit.GetCost();
|
score += aroundUnit.GetMilitary();
|
||||||
}
|
}
|
||||||
result.Score[CalculateType.LegionDefendMove] = 1 / ((float)path.length + 1) * 1000 + score / 1000f;
|
result.Score[CalculateType.LegionDefendMove] = 1 / ((float)path.length + 1) * 1000 + score / 1000f;
|
||||||
}
|
}
|
||||||
@ -925,98 +928,70 @@ namespace Logic.AI
|
|||||||
|
|
||||||
private static void CalculateCityTrainAttack(AICalculatorData data, CommonActionParams param, CalculateResult result)
|
private static void CalculateCityTrainAttack(AICalculatorData data, CommonActionParams param, CalculateResult result)
|
||||||
{
|
{
|
||||||
if (data.AttackPlayer == null) return;
|
if (!param.MapData.GetGridDataByCityId(param.CityData.Id, out var cityGrid)) return;
|
||||||
|
if (!param.MapData.GetUnitDataByGid(cityGrid.Id, out var newUnit)) return;
|
||||||
|
|
||||||
var selfUnits = new HashSet<UnitData>();
|
var selfUnits = new HashSet<UnitData>();
|
||||||
param.MapData.GetUnitDataListByPlayerId(param.PlayerData.Id, selfUnits);
|
param.MapData.GetUnitDataListByPlayerId(param.PlayerData.Id, selfUnits);
|
||||||
if (!param.MapData.GetGridDataByCityId(param.CityData.Id, out var cityGrid)) return;
|
|
||||||
|
|
||||||
var units = new HashSet<UnitData>();
|
var score = 0f;
|
||||||
var targets = new HashSet<UnitData>();
|
|
||||||
var selfScore = 0f;
|
|
||||||
var targetScore = 0f;
|
|
||||||
foreach (var unit in param.MapData.UnitMap.UnitList)
|
foreach (var unit in param.MapData.UnitMap.UnitList)
|
||||||
{
|
{
|
||||||
if (!selfUnits.Contains(unit)) continue;
|
if (selfUnits.Contains(unit)) continue;
|
||||||
if (selfUnits.Contains(unit))
|
if (!param.MapData.GetPlayerIdByUnitId(unit.Id, out var ownerId)) continue;
|
||||||
{
|
if (!param.PlayerData.LastAttackPlayers.Contains(ownerId) &&
|
||||||
units.Add(unit);
|
!param.PlayerData.CurAttackPlayers.Contains(ownerId)) continue;
|
||||||
selfScore += unit.GetCost();
|
score += data.CalUnitMilitaryGapScore(param.MapData, newUnit, unit);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
targets.Add(unit);
|
|
||||||
targetScore += unit.GetCost();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float score = selfScore - targetScore;
|
|
||||||
foreach (var selfUnit in units)
|
|
||||||
{
|
|
||||||
foreach (var target in targets)
|
|
||||||
{
|
|
||||||
score += data.CalUnitCounterScore(selfUnit, target) * 2;
|
|
||||||
score -= data.CalUnitCounterScore(target, selfUnit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Score[CalculateType.CityTrainAttack] = score;
|
result.Score[CalculateType.CityTrainAttack] = score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void CalculateCityTrainMilitary(AICalculatorData data, CommonActionParams param, CalculateResult result)
|
||||||
|
{
|
||||||
|
if (!param.MapData.GetGridDataByCityId(param.CityData.Id, out var cityGrid)) return;
|
||||||
|
if (!param.MapData.GetUnitDataByGid(cityGrid.Id, out var newUnit)) return;
|
||||||
|
|
||||||
|
var selfUnits = new HashSet<UnitData>();
|
||||||
|
param.MapData.GetUnitDataListByPlayerId(param.PlayerData.Id, selfUnits);
|
||||||
|
|
||||||
|
var score = 0f;
|
||||||
|
foreach (var unit in param.MapData.UnitMap.UnitList)
|
||||||
|
{
|
||||||
|
if (selfUnits.Contains(unit)) continue;
|
||||||
|
if (!param.MapData.GetGridDataByUnitId(unit.Id, out var unitGrid)) continue;
|
||||||
|
var dis = param.MapData.GridMap.CalcDistance(cityGrid, unitGrid);
|
||||||
|
if (dis > 3) continue;
|
||||||
|
score += data.CalUnitMilitaryGapScore(param.MapData, newUnit, unit);
|
||||||
|
}
|
||||||
|
result.Score[CalculateType.CityTrainMilitary] = score;
|
||||||
|
}
|
||||||
|
|
||||||
private static void CalculateCityTrainDefendAttack(AICalculatorData data, CommonActionParams param, CalculateResult result)
|
private static void CalculateCityTrainDefendAttack(AICalculatorData data, CommonActionParams param, CalculateResult result)
|
||||||
{
|
{
|
||||||
if (data.AttackPlayer == null) return;
|
if (!param.MapData.GetGridDataByCityId(param.CityData.Id, out var cityGrid)) return;
|
||||||
|
if (!param.MapData.GetUnitDataByGid(cityGrid.Id, out var newUnit)) return;
|
||||||
|
|
||||||
var selfUnits = new HashSet<UnitData>();
|
var selfUnits = new HashSet<UnitData>();
|
||||||
param.MapData.GetUnitDataListByPlayerId(param.PlayerData.Id, selfUnits);
|
param.MapData.GetUnitDataListByPlayerId(param.PlayerData.Id, selfUnits);
|
||||||
if (!param.MapData.GetGridDataByCityId(param.CityData.Id, out var cityGrid)) return;
|
|
||||||
|
|
||||||
var units = new HashSet<UnitData>();
|
var score = 0f;
|
||||||
var targets = new HashSet<UnitData>();
|
|
||||||
var selfScore = 0f;
|
|
||||||
var targetScore = 0f;
|
|
||||||
foreach (var unit in param.MapData.UnitMap.UnitList)
|
foreach (var unit in param.MapData.UnitMap.UnitList)
|
||||||
{
|
{
|
||||||
if (!param.MapData.GetGridDataByUnitId(unit.Id, out var unitGrid)) continue;
|
if (selfUnits.Contains(unit)) continue;
|
||||||
var dis = param.MapData.GridMap.CalcDistance(cityGrid, unitGrid);
|
if (!param.MapData.GetPlayerIdByUnitId(unit.Id, out var ownerId)) continue;
|
||||||
if (dis > 6) continue;
|
if (!param.PlayerData.LastAttackPlayers.Contains(ownerId) &&
|
||||||
if (selfUnits.Contains(unit))
|
!param.PlayerData.CurAttackPlayers.Contains(ownerId)) continue;
|
||||||
{
|
score += data.CalUnitMilitaryGapScore(param.MapData, newUnit, unit);
|
||||||
units.Add(unit);
|
|
||||||
selfScore += unit.GetCost();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
targets.Add(unit);
|
|
||||||
targetScore += unit.GetCost();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float score = selfScore - targetScore;
|
|
||||||
foreach (var selfUnit in units)
|
|
||||||
{
|
|
||||||
foreach (var target in targets)
|
|
||||||
{
|
|
||||||
score += data.CalUnitCounterScore(selfUnit, target) * 2;
|
|
||||||
score -= data.CalUnitCounterScore(target, selfUnit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Score[CalculateType.CityTrainDefendAttack] = score;
|
result.Score[CalculateType.CityTrainDefendAttack] = score;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CalculateCityTrainDefend(AICalculatorData data, CommonActionParams param, CalculateResult result)
|
private static void CalculateCityTrainDefend(AICalculatorData data, CommonActionParams param, CalculateResult result)
|
||||||
{
|
{
|
||||||
float score = 0;
|
|
||||||
var selfUnits = new HashSet<UnitData>();
|
|
||||||
param.MapData.GetUnitDataListByPlayerId(param.PlayerData.Id, selfUnits);
|
|
||||||
if (!param.MapData.GetGridDataByCityId(param.CityData.Id, out var cityGrid)) return;
|
if (!param.MapData.GetGridDataByCityId(param.CityData.Id, out var cityGrid)) return;
|
||||||
|
if (!param.MapData.GetUnitDataByGid(cityGrid.Id, out var newUnit)) return;
|
||||||
|
|
||||||
foreach (var unit in selfUnits)
|
result.Score[CalculateType.CityTrainDefend] = newUnit.GetDefenseValue(param.MapData) + newUnit.Health;
|
||||||
{
|
|
||||||
if (!param.MapData.GetGridDataByUnitId(unit.Id, out var unitGrid)) continue;
|
|
||||||
if (param.MapData.GridMap.CalcDistance(cityGrid, unitGrid) > 3) continue;
|
|
||||||
score += unit.GetDefenseValue(param.MapData) + unit.Health;
|
|
||||||
}
|
|
||||||
result.Score[CalculateType.CityTrainDefend] = score;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CalculatePlayerTechDefend(AICalculatorData data, CommonActionParams param, CalculateResult result)
|
private static void CalculatePlayerTechDefend(AICalculatorData data, CommonActionParams param, CalculateResult result)
|
||||||
|
|||||||
@ -2490,7 +2490,7 @@ namespace Logic.Action
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 小兵攻击,目前只用于 AI 的行为
|
// 小兵攻击,目前只用于 AI 的行为
|
||||||
public class UnitAttackAction : ActionLogicBase
|
public class UnitAttackAction : ActionLogicBase
|
||||||
{
|
{
|
||||||
|
|||||||
@ -113,14 +113,16 @@ namespace Logic.Editor
|
|||||||
{
|
{
|
||||||
if (_main?.MapData == null || _player == null) return;
|
if (_main?.MapData == null || _player == null) return;
|
||||||
|
|
||||||
MainEditor.Instance.GetPlayerStrategy(_player.Id, out var playerStrategy, out var targetId, out var attackType);
|
MainEditor.Instance.GetPlayerStrategy(_player.Id, out var playerStrategy, out var targetIdSet);
|
||||||
EditorGUILayout.BeginHorizontal();
|
EditorGUILayout.BeginHorizontal();
|
||||||
if (playerStrategy != Strategy.Attack)
|
if (playerStrategy != Strategy.Attack)
|
||||||
InspectorUtils.InspectorTextWidthRich($"<b>玩家ID: {_player.Id}, 国家战略为: {playerStrategy}</b>");
|
InspectorUtils.InspectorTextWidthRich($"<b>玩家ID: {_player.Id}, 国家战略为: {playerStrategy}</b>");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
var idStr = "";
|
||||||
|
foreach (var id in targetIdSet) idStr += $"{id}";
|
||||||
InspectorUtils.InspectorTextWidthRich(
|
InspectorUtils.InspectorTextWidthRich(
|
||||||
$"<b>玩家ID: {_player.Id}, 国家战略为: {playerStrategy}, 目标:{targetId}, 类型:{attackType}</b>");
|
$"<b>玩家ID: {_player.Id}, 国家战略为: {playerStrategy}, 目标:{idStr}</b>");
|
||||||
}
|
}
|
||||||
EditorGUILayout.EndHorizontal();
|
EditorGUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
|||||||
@ -70,12 +70,16 @@ namespace RuntimeData
|
|||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
public class GameRecord
|
public class GameRecord
|
||||||
{
|
{
|
||||||
|
public GameMode Mode;
|
||||||
|
public AIDifficult AIDiff;
|
||||||
|
public uint Turn;
|
||||||
|
public uint PlayerCivId;
|
||||||
|
public uint PlayerForceId;
|
||||||
public float Score;
|
public float Score;
|
||||||
public string Time;
|
public string Time;
|
||||||
public uint CityCount;
|
public uint CityCount;
|
||||||
public uint MapWidth;
|
public uint MapWidth;
|
||||||
public uint MapHeight;
|
public uint MapHeight;
|
||||||
public uint PlayerCount;
|
public uint PlayerCount;
|
||||||
public AIDifficult AIDiff;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -17,8 +17,7 @@ namespace Logic
|
|||||||
public bool IsGo = false;
|
public bool IsGo = false;
|
||||||
public AICalculatorData Data;
|
public AICalculatorData Data;
|
||||||
private Dictionary<uint, Strategy> _playerStrategy;
|
private Dictionary<uint, Strategy> _playerStrategy;
|
||||||
private Dictionary<uint, CountryAttackType> _playerAttackType;
|
private Dictionary<uint, HashSet<uint>> _playerAttackTarget;
|
||||||
private Dictionary<uint, uint> _playerAttackTarget;
|
|
||||||
private Dictionary<uint, Strategy> _cityStrategy;
|
private Dictionary<uint, Strategy> _cityStrategy;
|
||||||
private Dictionary<uint, Strategy> _unitStrategy;
|
private Dictionary<uint, Strategy> _unitStrategy;
|
||||||
private Dictionary<uint, Strategy> _legionStrategy;
|
private Dictionary<uint, Strategy> _legionStrategy;
|
||||||
@ -33,8 +32,7 @@ namespace Logic
|
|||||||
public MainEditor()
|
public MainEditor()
|
||||||
{
|
{
|
||||||
_playerStrategy = new Dictionary<uint, Strategy>();
|
_playerStrategy = new Dictionary<uint, Strategy>();
|
||||||
_playerAttackType = new Dictionary<uint, CountryAttackType>();
|
_playerAttackTarget = new Dictionary<uint, HashSet<uint>>();
|
||||||
_playerAttackTarget = new Dictionary<uint, uint>();
|
|
||||||
_cityStrategy = new Dictionary<uint, Strategy>();
|
_cityStrategy = new Dictionary<uint, Strategy>();
|
||||||
_unitStrategy = new Dictionary<uint, Strategy>();
|
_unitStrategy = new Dictionary<uint, Strategy>();
|
||||||
_legionStrategy = new Dictionary<uint, Strategy>();
|
_legionStrategy = new Dictionary<uint, Strategy>();
|
||||||
@ -62,14 +60,11 @@ namespace Logic
|
|||||||
return _actionRecord.GetValueOrDefault(cid);
|
return _actionRecord.GetValueOrDefault(cid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetPlayerStrategy(uint pid, out Strategy strategy, out uint target, out CountryAttackType attackType)
|
public void GetPlayerStrategy(uint pid, out Strategy strategy, out HashSet<uint> target)
|
||||||
{
|
{
|
||||||
strategy = Strategy.None;
|
strategy = Strategy.None;
|
||||||
target = 0;
|
|
||||||
attackType = CountryAttackType.None;
|
|
||||||
_playerStrategy.TryGetValue(pid, out strategy);
|
_playerStrategy.TryGetValue(pid, out strategy);
|
||||||
_playerAttackTarget.TryGetValue(pid, out target);
|
_playerAttackTarget.TryGetValue(pid, out target);
|
||||||
_playerAttackType.TryGetValue(pid, out attackType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetUnitStrategy(uint uid, uint legion, uint playerId, out Strategy strategy, out uint cityId, out LegionStrategyType type)
|
public void GetUnitStrategy(uint uid, uint legion, uint playerId, out Strategy strategy, out uint cityId, out LegionStrategyType type)
|
||||||
@ -113,8 +108,10 @@ namespace Logic
|
|||||||
if (Data == null) return;
|
if (Data == null) return;
|
||||||
if (Data.Player == null) return;
|
if (Data.Player == null) return;
|
||||||
_playerStrategy[Data.Player.Id] = Data.CountryStrategy;
|
_playerStrategy[Data.Player.Id] = Data.CountryStrategy;
|
||||||
_playerAttackType[Data.Player.Id] = Data.AttackType;
|
if (!_playerAttackTarget.ContainsKey(Data.Player.Id))
|
||||||
if (Data.AttackPlayer != null) _playerAttackTarget[Data.Player.Id] = Data.AttackPlayer.Id;
|
_playerAttackTarget[Data.Player.Id] = new HashSet<uint>();
|
||||||
|
_playerAttackTarget[Data.Player.Id].Clear();
|
||||||
|
foreach (var player in Data.AttackPlayerSet) _playerAttackTarget[Data.Player.Id].Add(player.Id);
|
||||||
foreach (var kv in Data.CityStrategy) _cityStrategy[kv.Key.Id] = kv.Value;
|
foreach (var kv in Data.CityStrategy) _cityStrategy[kv.Key.Id] = kv.Value;
|
||||||
foreach (var kv in Data.FreeUnitStrategy) _unitStrategy[kv.Key.Id] = kv.Value;
|
foreach (var kv in Data.FreeUnitStrategy) _unitStrategy[kv.Key.Id] = kv.Value;
|
||||||
foreach (var kv in Data.LegionStrategy) _legionStrategy[kv.Key * 10000 + Data.Player.Id] = kv.Value;
|
foreach (var kv in Data.LegionStrategy) _legionStrategy[kv.Key * 10000 + Data.Player.Id] = kv.Value;
|
||||||
|
|||||||
@ -874,7 +874,14 @@ namespace Logic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 主动建立同盟
|
||||||
|
public void SetDiplomacyLeague( PlayerData originPlayer, PlayerData targetPlayer, DiplomacyState state)
|
||||||
|
{
|
||||||
|
originPlayer.DiplomacyData.GetCountryDiplomacyInfo(targetPlayer.Id, out var player1ToPlayer2);
|
||||||
|
targetPlayer.DiplomacyData.GetCountryDiplomacyInfo(originPlayer.Id, out var player2ToPlayer1);
|
||||||
|
player1ToPlayer2.DiplomacyState = state;
|
||||||
|
player2ToPlayer1.DiplomacyState = state;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -209,8 +209,10 @@ namespace Logic
|
|||||||
if (!mapData.GetCityDataByUnitId(unit2.Id, out var city2)) return false;
|
if (!mapData.GetCityDataByUnitId(unit2.Id, out var city2)) return false;
|
||||||
if (!mapData.GetGridDataByUnitId(unit1.Id, out var grid1)) return false;
|
if (!mapData.GetGridDataByUnitId(unit1.Id, out var grid1)) return false;
|
||||||
if (!mapData.GetGridDataByUnitId(unit2.Id, out var grid2)) return false;
|
if (!mapData.GetGridDataByUnitId(unit2.Id, out var grid2)) return false;
|
||||||
|
Main.PlayerLogic.SetDiplomacyLeague(player1, player2, DiplomacyState.War);
|
||||||
player1.CurAttackPlayers.Add(player2.Id);
|
player1.CurAttackPlayers.Add(player2.Id);
|
||||||
player2.CurAttackPlayers.Add(player1.Id);
|
player2.CurAttackPlayers.Add(player1.Id);
|
||||||
|
player2.AddAttacker(player1.Id);
|
||||||
player1.TurnNoAttack = 0;
|
player1.TurnNoAttack = 0;
|
||||||
|
|
||||||
// 计算攻击伤害
|
// 计算攻击伤害
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Logic.CrashSight;
|
||||||
using RuntimeData;
|
using RuntimeData;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
@ -19,7 +20,7 @@ namespace Logic.Audio
|
|||||||
|
|
||||||
private AudioPlayer _musicPlayer;
|
private AudioPlayer _musicPlayer;
|
||||||
private List<AudioPlayer> _allPlayer;
|
private List<AudioPlayer> _allPlayer;
|
||||||
private Dictionary<string, AudioClip> _clips;
|
private Dictionary<string, List<AudioClip>> _clips;
|
||||||
private GameObject AudioRoot;
|
private GameObject AudioRoot;
|
||||||
|
|
||||||
public float MusicVolume
|
public float MusicVolume
|
||||||
@ -42,45 +43,74 @@ namespace Logic.Audio
|
|||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
_allPlayer = new List<AudioPlayer>();
|
_allPlayer = new List<AudioPlayer>();
|
||||||
_clips = new Dictionary<string, AudioClip>();
|
_clips = new Dictionary<string, List<AudioClip>>();
|
||||||
_clips["Main"] = Resources.Load<AudioClip>("Audio/Main");
|
var path = new Dictionary<string, string>();
|
||||||
_clips["RemiliaEgyptian"] = Resources.Load<AudioClip>("Audio/RemiliaEgyptian");
|
path["Main"] = "Audio/Main";
|
||||||
_clips["SatoriIndian"] = Resources.Load<AudioClip>("Audio/SatoriIndian");
|
path["RemiliaEgyptian"] = "Audio/RemiliaEgyptian";
|
||||||
_clips["KanakoGermany"] = Resources.Load<AudioClip>("Audio/KanakoGermany");
|
path["SatoriIndian"] = "Audio/SatoriIndian";
|
||||||
_clips["KaguyaFrench"] = Resources.Load<AudioClip>("Audio/KaguyaFrench");
|
path["KanakoGermany"] = "Audio/KanakoGermany";
|
||||||
_clips["SFX/UI_buttonHover"] = Resources.Load<AudioClip>("Audio/SFX/UI_buttonHover");
|
path["KaguyaFrench"] = "Audio/KaguyaFrench";
|
||||||
_clips["SFX/UI_buttonClick"] = Resources.Load<AudioClip>("Audio/SFX/UI_buttonClick");
|
path["SFX/UI_buttonHover"] = "Audio/SFX/UI_buttonHover";
|
||||||
_clips["SFX/UNIT_click"] = Resources.Load<AudioClip>("Audio/SFX/UNIT_click");
|
path["SFX/UI_buttonClick"] = "Audio/SFX/UI_buttonClick";
|
||||||
_clips["SFX/UNIT_bomb"] = Resources.Load<AudioClip>("Audio/SFX/UNIT_bomb");
|
path["SFX/UNIT_click"] = "Audio/SFX/UNIT_click";
|
||||||
_clips["SFX/UNIT_archer"] = Resources.Load<AudioClip>("Audio/SFX/UNIT_archer");
|
path["SFX/UNIT_bomb"] = "Audio/SFX/UNIT_bomb";
|
||||||
_clips["SFX/UNIT_hurt"] = Resources.Load<AudioClip>("Audio/SFX/UNIT_hurt");
|
path["SFX/UNIT_archer"] = "Audio/SFX/UNIT_archer";
|
||||||
_clips["SFX/UNIT_move"] = Resources.Load<AudioClip>("Audio/SFX/UNIT_move");
|
path["SFX/UNIT_hurt"] = "Audio/SFX/UNIT_hurt";
|
||||||
_clips["SFX/UNIT_attack"] = Resources.Load<AudioClip>("Audio/SFX/UNIT_attack");
|
path["SFX/UNIT_move"] = "Audio/SFX/UNIT_move";
|
||||||
|
path["SFX/UNIT_attack"] = "Audio/SFX/UNIT_attack";
|
||||||
_clips["SFX/ENV_sea"] = Resources.Load<AudioClip>("Audio/SFX/ENV_sea");
|
path["SFX/ENV_sea"] = "Audio/SFX/ENV_sea";
|
||||||
_clips["SFX/ENV_forest"] = Resources.Load<AudioClip>("Audio/SFX/ENV_forest");
|
path["SFX/ENV_forest"] = "Audio/SFX/ENV_forest";
|
||||||
|
foreach (var kv in path)
|
||||||
|
{
|
||||||
|
_clips[kv.Key] = new List<AudioClip>();
|
||||||
|
_clips[kv.Key].Add(Resources.Load<AudioClip>(kv.Value));
|
||||||
|
}
|
||||||
|
|
||||||
if (!AudioRoot) AudioRoot = new GameObject();
|
if (!AudioRoot) AudioRoot = new GameObject();
|
||||||
AudioRoot.name = "AudioRoot";
|
AudioRoot.name = "AudioRoot";
|
||||||
var cfg = Object.FindObjectOfType<AudioClipConfig>();
|
var cfg = Object.FindObjectOfType<AudioClipConfig>();
|
||||||
if (cfg != null) foreach (var clip in cfg.Clips) _clips[clip.name] = clip;
|
if (cfg != null)
|
||||||
|
{
|
||||||
|
foreach (var clip in cfg.Clips)
|
||||||
|
{
|
||||||
|
_clips[clip.name] = new List<AudioClip>();
|
||||||
|
_clips[clip.name].Add(clip);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
foreach (var player in _allPlayer) player.Update();
|
foreach (var player in _allPlayer)
|
||||||
|
{
|
||||||
|
player.Update();
|
||||||
|
if (player.State != PlayerState.Finished) continue;
|
||||||
|
if (!player.Clip) continue;
|
||||||
|
if (!_clips.ContainsKey(player.MusicName)) _clips[player.MusicName] = new List<AudioClip>();
|
||||||
|
_clips[player.MusicName].Add(player.Clip);
|
||||||
|
player.Clip = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PlayMusic(string musicName, float fadeIn, float fadeOut, bool isLoop)
|
public void PlayMusic(string musicName, float fadeIn, float fadeOut, bool isLoop)
|
||||||
{
|
{
|
||||||
if (!_clips.ContainsKey(musicName)) return;
|
if (!_clips.ContainsKey(musicName) || _clips[musicName].Count == 0) return;
|
||||||
if (_musicPlayer != null) _musicPlayer.Stop();
|
if (_musicPlayer != null) _musicPlayer.Stop();
|
||||||
_musicPlayer = GetPlayer();
|
else _musicPlayer = GetPlayer();
|
||||||
_musicPlayer.Clip = _clips[musicName];
|
if (_clips[musicName].Count > 1)
|
||||||
|
{
|
||||||
|
_musicPlayer.Clip = _clips[musicName][1];
|
||||||
|
_clips[musicName].RemoveAt(1);
|
||||||
|
}
|
||||||
|
else _musicPlayer.Clip = Object.Instantiate(_clips[musicName][0]);
|
||||||
|
if (!_musicPlayer.Clip)
|
||||||
|
{
|
||||||
|
LogSystem.LogError($"音乐资源 {musicName} 未找到或加载失败!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_musicPlayer.MusicName = musicName;
|
||||||
_musicPlayer.IsLoop = isLoop;
|
_musicPlayer.IsLoop = isLoop;
|
||||||
_musicPlayer.Length = _clips[musicName].length;
|
_musicPlayer.Length = _musicPlayer.Clip.length;
|
||||||
_musicPlayer.FadeInDuration = fadeIn;
|
_musicPlayer.FadeInDuration = fadeIn;
|
||||||
_musicPlayer.FadeOutDuration = fadeOut;
|
_musicPlayer.FadeOutDuration = fadeOut;
|
||||||
_musicPlayer.VolumeRatio = MusicVolume;
|
_musicPlayer.VolumeRatio = MusicVolume;
|
||||||
@ -96,9 +126,20 @@ namespace Logic.Audio
|
|||||||
{
|
{
|
||||||
if (!_clips.ContainsKey(musicName)) return;
|
if (!_clips.ContainsKey(musicName)) return;
|
||||||
var player = GetPlayer();
|
var player = GetPlayer();
|
||||||
player.Clip = _clips[musicName];
|
if (_clips[musicName].Count > 1)
|
||||||
|
{
|
||||||
|
player.Clip = _clips[musicName][1];
|
||||||
|
_clips[musicName].RemoveAt(1);
|
||||||
|
}
|
||||||
|
else player.Clip = Object.Instantiate(_clips[musicName][0]);
|
||||||
|
if (!player.Clip)
|
||||||
|
{
|
||||||
|
LogSystem.LogError($"音频资源 {musicName} 未找到或加载失败!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
player.MusicName = musicName;
|
||||||
player.IsLoop = isLoop;
|
player.IsLoop = isLoop;
|
||||||
player.Length = _clips[musicName].length;
|
player.Length = _musicPlayer.Clip.length;
|
||||||
player.FadeInDuration = fadeIn;
|
player.FadeInDuration = fadeIn;
|
||||||
player.FadeOutDuration = fadeOut;
|
player.FadeOutDuration = fadeOut;
|
||||||
_musicPlayer.VolumeRatio = AudioVolume;
|
_musicPlayer.VolumeRatio = AudioVolume;
|
||||||
@ -175,6 +216,7 @@ namespace Logic.Audio
|
|||||||
|
|
||||||
public class AudioPlayer
|
public class AudioPlayer
|
||||||
{
|
{
|
||||||
|
public string MusicName;
|
||||||
public AudioSource Source;
|
public AudioSource Source;
|
||||||
public AudioClip Clip;
|
public AudioClip Clip;
|
||||||
public bool IsLoop;
|
public bool IsLoop;
|
||||||
@ -200,6 +242,7 @@ namespace Logic.Audio
|
|||||||
public void Play()
|
public void Play()
|
||||||
{
|
{
|
||||||
StartTime = Time.time;
|
StartTime = Time.time;
|
||||||
|
Source.time = 0;
|
||||||
Source.clip = Clip;
|
Source.clip = Clip;
|
||||||
Source.volume = 0;
|
Source.volume = 0;
|
||||||
Source.loop = IsLoop;
|
Source.loop = IsLoop;
|
||||||
@ -209,7 +252,7 @@ namespace Logic.Audio
|
|||||||
|
|
||||||
public void Update()
|
public void Update()
|
||||||
{
|
{
|
||||||
if (Source == null || !Source.isPlaying) return;
|
if (Source == null) return;
|
||||||
UpdateSourceVolume();
|
UpdateSourceVolume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -85,9 +85,8 @@ namespace TH1Renderer
|
|||||||
if (MainEditor.Instance.Data != null)
|
if (MainEditor.Instance.Data != null)
|
||||||
{
|
{
|
||||||
MainEditor.Instance.GetCityStrategy(_cityId, out var cst);
|
MainEditor.Instance.GetCityStrategy(_cityId, out var cst);
|
||||||
MainEditor.Instance.GetPlayerStrategy(_playerData.Id, out var pst, out var target, out var type);
|
MainEditor.Instance.GetPlayerStrategy(_playerData.Id, out var pst, out var target);
|
||||||
_debugText.text += $"CST={cst} PST={pst}";
|
_debugText.text += $"CST={cst} PST={pst}";
|
||||||
if (pst == Strategy.Attack) _debugText.text += $"TAR={target} Type={type}";
|
|
||||||
_debugText.text += "\n";
|
_debugText.text += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user