2025-06-05 00:47:25 +08:00

495 lines
23 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

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

using System.Collections.Generic;
using Logic.Action;
using NUnit.Framework.Constraints;
using NUnit.Framework.Internal.Commands;
using UnityEngine;
using RuntimeData;
using UnityEditor;
public enum TerrainType { None,Land, ShallowSea, DeepSea } // 海陆层
public enum TerrainFeature { None, Mountain,Road } // 地形层
public enum Vegetation { None, Trees } // 植被层
public enum ResourceType { None, Fish, Starfish, Metal, Animal, Fruit, Crop, CityCenter, Treasure, Farm, Mine, LumberHut,Port,Sawmill,Forge,Windmill, Wonder,Bridge,Market,Temple,ForestTemple,MountainTemple,WaterTemple,Tower } // 资源层+建筑层
public enum AttackAnimType {None,Melee,Arrow,Bomb}
public enum MainObjectType { None,Grid,City,Unit,Player}
public enum LandType { None,LandAndPort,WaterAndAshore,LandOnly,WaterOnly,LandAndWater,Fly}
public enum MoveAttackType { None,Move,Attack,MoveToPort,MoveAshore}
public enum UnitActionType { None,Upgrade,Recover,Heal,Examine,Gather,Capture,Disband}
public enum CityLevelUpActionType{None,Explorer,Workshop,CityWall,CityWealth,Expand,Population,Park,BigGuy}
public enum SkillType
{
NONE,
PEACE,
DASH,
ESCAPE,
PERSIST,
SPLASH,
SNEAK,
STIFF,
FORTIFY,
HEAL,
CONVERT,
CARRY,
SCOUT,
STATIC,
HIDE,
CREEP,
INFILTRATE,
BOOST,
EXPLODE,
STOMP,
ATTACKUP,
SPEEDUP,
FORESTDEFENSE,
WATERDEFENSE,
OCEANDEFENSE,
MOUNTAINDEFENSE,
MOUNTAINMOVE,
WATERMOVE,
OCEANMOVE,
SURPRISE,
POISON,
POISONED,
UNIQUE,
SWAP,
AUTOHEAL,
CITYTRANSPORT,
ALLYCOUNTER,
POWERUP,
ALLYTRANSPORT,
QUARTER,
TAICHI,
POORHEALTH,
ROYALFLAMES,
VAMPIRE,
SUPERDASH,
PHOENIX,
PHOENIXEGG,
ILLUSION,
LUCK,
CRITICAL,
MOONPRINCESS,
ETERNITY,
GALAXYARROW,
WINDGOD,
WINDPRIESTESS,
MOUNTAINGOD,
CURSEGOD,
NUCLEAR,
NUCLEARFUSION,
CATCART,
RECYCLE,
THIRDEYE,
SUPERHIDE,
Max
}
public enum MoveType
{
ActiveMove,
PassiveMove,
AttackMove,
SkillMove,
PatrolMove
}
public class Table
{
public int MaxMapSize = 36;
public TechDataAssets TechDataAssets;
public ActionDataAssets ActionDataAssets;
public UnitTypeDataAssets UnitTypeDataAssets;
public GridAndResourceDataAssets GridAndResourceDataAssets;
public AnimDataAssets AnimDataAssets;
public UICenterMessageDataAssets UICenterMessageDataAssets;
public PlayerDataAssets PlayerDataAssets;
//TH1Resource路径相关
public string[] TH1HousePath = new string[16] { "RemiliaForces", "KaguyaForces", "KanakoForces", "SatoriForces", "ReimuForces", "ByakurenForces", "MikoForces", "ZanmuForces", "Zebasi", "Ai-Mo", "Aquarion", "Quetzali", "Elyrion", "Yadakk", "Polaris", "Cymanti" };
//Forces名称list
string[] TH1ForcesNameList = new string[16] {"RemiliaForces", "KaguyaForces", "KanakoForces", "SatoriForces", "ReimuForces", "ByakurenForces", "MikoForces", "ZanmuForces", "Zebasi", "Ai-Mo", "Aquarion", "Quetzali", "Elyrion", "Yadakk", "Polaris", "Cymanti" };
//Civ名称list
string[] TH1CivsNameList = new string[16] { "Egyptian", "French", "Germany", "Indian", "Norway", "British", "Persian", "Byzantine", "Zebasi", "Aimo", "Aquarion", "Quetzali", "Elyrion", "Yadakk", "Polaris", "Cymanti" };
//------------ citybuilding相关 -----------------//
//不同等级城市拥有的房屋数量
public int[] cityLevel2HouseNumber = new int[21] { 0, 0, 4, 14, 26, 35, 55, 75, 95, 115, 135, 155, 175, 195, 215, 235, 255, 275, 295, 315, 335 };
//不同等级城市的房屋边长
public int[] cityLevel2HouseEdge = new int[21] { 0, 0, 2, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 };
//不同等级城市的高度限制
public int[] cityLevel2HouseHeight = new int[]
{ 0, 0, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
//不同等级城市可以使用的房屋类型
public int[] cityLevel2HouseType = new int[]
{ 0, 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
public string[] civNameList = new string[] { "埃及帝国-斯卡雷特王朝", "法兰西帝国-蓬莱山王朝", "德意志帝国-八坂王朝", "印度帝国-古明地王朝" ,"北海帝国-博丽王朝","大不列颠帝国-白莲王朝","萨珊帝国-丰聪耳王朝","拜占庭帝国-日白王朝"};
public int cityNameLibrarySize = 20;
public int[] cityNameLibraryHat = { 0, 0, 0, 0, 0, 0, 0, 0 };
public string[,] cityNameLibrary = {//20x8目前的规模
{ "开罗","亚历山大","卢克索","阿斯旺","吉萨","达曼胡尔","苏伊士","塞得港","洪加达","阿斯旺","伊斯梅利亚","曼苏拉","坦塔","卡夫尔谢赫","本哈","法尤姆","明亚","索哈杰","基纳","艾因夏姆斯" },// 埃及
{"巴黎","马赛","里昂","图卢兹","尼斯","南特","斯特拉斯堡","蒙彼利埃","波尔多","里尔","雷恩","勒阿弗尔","兰斯","圣艾蒂安","土伦","格勒诺布尔","昂热","第戎","布雷斯特","勒芒"},// 法国
{ "柏林","汉堡","慕尼黑","法兰克福","科隆","斯图加特","不来梅","德累斯顿","莱比锡","纽伦堡","汉诺威","杜塞尔多夫","埃森","多特蒙德","波恩","美因茨","海德堡","卡尔斯鲁厄","哥尼斯堡","但泽" },// 罗马
{ "华氏城","王舍城","瞻波","俱赏弥","舍卫城","波罗奈斯","马图拉","曲女城","天帝城","呾叉始罗","普陀珞珈","德里","孟买","加尔各答","班加罗尔","金奈","海得拉巴","艾哈迈达巴德","浦那","苏拉特" },// 印度
{
"罗斯基勒","海尔辛格","卑尔根","特隆赫姆","阿尔博格","奥胡斯","乌普萨拉","林雪平",
"延雪平","斯塔万格","哈尔姆斯塔德","哥德堡","维斯比","奈斯比","法鲁","隆德",
"奥斯陆","雷克雅未克","西格图纳","泰恩河口"
}, // 北海帝国
{
"伦敦","爱丁堡","曼彻斯特","伯明翰","利物浦","布里斯托尔","格拉斯哥","卡迪夫",
"纽卡斯尔","谢菲尔德","诺丁汉","剑桥","牛津","朴茨茅斯","利兹","雷丁",
"贝尔法斯特","斯旺西","诺里奇","普利茅斯"
}, // 英国
{
"泰西封","巴比伦","苏萨","波斯波利斯","伊斯法罕","雷伊","设拉子","尼沙布尔",
"哈马丹","库特","马什哈德","胡齐斯坦","喀布尔","赫拉特","梅尔夫","巴尔赫",
"伊斯坦纳","阿斯塔拉巴德","大不里士","德黑兰"
}, // 萨珊王朝
{
"君士坦丁堡","安条克","尼西亚","特拉比松","尼科米底亚","塞萨洛尼基","埃弗所","拉奥迪刻亚",
"帕加马","米利都","凯撒利亚","赫拉克利亚","底比斯","拉文纳","亚得里亚堡","斯米尔那",
"塞浦路斯","亚历山大塔","帕特雷","多布鲁加"
} // 拜占庭帝国
};
//查询ForcesName
public string QueryForcesName(uint t) { return TH1ForcesNameList[t]; }
//查询CivsName
public string QueryCivsName(uint t) { return TH1CivsNameList[t]; }
public static Table Instance { get; private set; }
// Start is called before the first frame update
public Table()//创建单例
{
Instance = this;
//加载assetsData
TechDataAssets = Resources.Load<TechDataAssets>("Export/TechDataAssets");
ActionDataAssets = Resources.Load<ActionDataAssets>("Export/ActionDataAssets");
UnitTypeDataAssets = Resources.Load<UnitTypeDataAssets>("Export/UnitTypeDataAssets");
GridAndResourceDataAssets = Resources.Load<GridAndResourceDataAssets>("Export/GridAndResourceDataAssets");
AnimDataAssets = Resources.Load<AnimDataAssets>("Export/AnimDataAssets");
UICenterMessageDataAssets = Resources.Load<UICenterMessageDataAssets>("Export/UICenterMessageDataAssets");
PlayerDataAssets = Resources.Load<PlayerDataAssets>("Export/PlayerDataAssets");
}
public Vector2Int WorldToGrid(Vector3 worldPos,string mark = "")
{
worldPos.y -= 4.2f;
if (mark == "isUnit") worldPos.y += 1f;
float a = 5.16f;
float b = 3.05f;
float x = (worldPos.y / b + worldPos.x / a) / 2f;
float y = (worldPos.y / b - worldPos.x / a) / 2f;
// 取整以定位到哪个格子(你可以用 Mathf.Round、Floor、Ceil 视实际需求)
int gridX = Mathf.FloorToInt(x);
int gridY = Mathf.FloorToInt(y);
return new Vector2Int(gridX, gridY);
}
public Vector3 GridToWorld(GridData gridData, string mark = "")
{
Vector2Int gridPos = new Vector2Int(gridData.Pos.X, gridData.Pos.Y);
if(mark == "isUnit")
return new Vector3(-5.16f * (gridPos.y - gridPos.x), 3.05f * (gridPos.x + gridPos.y) + 8f, gridPos.x + gridPos.y + 0.06f);
if(mark == "isCityInfo")
return new Vector3(-5.16f * (gridPos.y - gridPos.x), 3.05f * (gridPos.x + gridPos.y) + 0.7f, gridPos.x + gridPos.y);
return new Vector3(-5.16f * (gridPos.y - gridPos.x), 3.05f * (gridPos.x + gridPos.y) + 9.7f, gridPos.x + gridPos.y);
}
public Sprite QueryActionIconSprite(CommonActionId commonActionId, PlayerData playerData = null)
{
foreach (var actionData in ActionDataAssets.ActionList)
if (actionData.ActionId == commonActionId)
{
if (!actionData.VarientIcon)
return actionData.Icon;
if (playerData == null)
break;
foreach (var iconInfo in actionData.IconList)
{
if ((iconInfo.IgnoreCivId || iconInfo.CivId == playerData.PlayerCivId)
&& (iconInfo.IgnoreForceId || iconInfo.ForceId == playerData.PlayerForceId))
return iconInfo.Sprite;
}
break;
}
return null;
}
public bool QueryUnitHasSkill(UnitType unitType, SkillType skillType)
{
return unitType switch
{
UnitType.Warrior => skillType == SkillType.FORTIFY|| skillType == SkillType.DASH,
UnitType.Rider => skillType == SkillType.DASH || skillType == SkillType.ESCAPE || skillType == SkillType.FORTIFY,
UnitType.Archer => skillType == SkillType.DASH || skillType == SkillType.FORTIFY,
UnitType.Defender => skillType == SkillType.FORTIFY,
UnitType.Knights => skillType == SkillType.DASH || skillType == SkillType.PERSIST || skillType == SkillType.FORTIFY,
UnitType.Catapult => skillType == SkillType.STIFF,
UnitType.Swordsman => skillType == SkillType.DASH,
UnitType.Cloak => false,
UnitType.Minder => skillType == SkillType.HEAL || skillType == SkillType.CONVERT || skillType == SkillType.STIFF,
UnitType.Boat => skillType == SkillType.CARRY || skillType == SkillType.STATIC || skillType == SkillType.STIFF,
UnitType.Ship => skillType == SkillType.DASH || skillType == SkillType.CARRY || skillType == SkillType.STATIC || skillType == SkillType.SCOUT,
UnitType.RammerShip => skillType == SkillType.DASH || skillType == SkillType.CARRY || skillType == SkillType.STATIC,
UnitType.BomberShip => skillType == SkillType.CARRY || skillType == SkillType.STATIC || skillType == SkillType.STIFF || skillType == SkillType.SPLASH,
_ => false
};
}
//public string QueryUnitSpritePath(uint civId, UnitType unitType) { return $"ArtResources/TH1Units/{TH1HousePath[civId]}/{TH1FirstSkinPath[civId]}/{TH1HousePath[civId]}_{TH1FirstSkinPath[civId]}_{UnitTypeToName(unitType)}"; }
//public string QueryFruitSpritePath(uint pid) { return $"ArtResources/TH1Fruits/TH1Fruit_{TH1CivsNameList[pid]}"; }
//public string QueryWonderSpritePath(uint pid, string wonderName) { return $"ArtResources/TH1Buildings/TH1Buildings{TH1ForcesNameList[pid]}/{TH1CivsNameList[pid]}/{TH1ForcesNameList[pid]}_{TH1CivsNameList[pid]}_{wonderName}"; }
//public string QueryAnimalSpritePath(uint cid) { return $"ArtResources/TH1Animals/TH1Animal_{TH1CivsNameList[cid]}"; }
//计算距离
public int CalcDistance(Vector2Int A, Vector2Int B){return Mathf.Max(Mathf.Abs(A.x - B.x),Mathf.Abs(A.y - B.y));}
//计算攻防
public int CalcDamage(MapData map, UnitData A, UnitData B, bool counter = false, float damagePara = 1f)
{
int Ano = QueryUnitTypeToNo(A.UnitType);
float AVeteran = A.Veteran ? 5f : 0f;
float BVeteran = B.Veteran ? 5f : 0f;
int Bno = QueryUnitTypeToNo(B.UnitType);
float attackA = UnitTypeDataAssets.GetUnitTypeInfo(A.UnitType,A.GiantType,out var AInfo)?AInfo.Attack:0;
float defenseB = UnitTypeDataAssets.GetUnitTypeInfo(B.UnitType,B.GiantType,out var BInfo)?BInfo.Defense:0;
float attackForce = attackA * (1f * A.Health / (A.GetMaxHealth() + AVeteran));
float defenseForce = defenseB * (1f * B.Health / (B.GetMaxHealth() + BVeteran)) * B.GetExtraDefense(map);
//Debug.Log(attackForce + " - " + defenseForce);
float totalDamage = attackForce + defenseForce;
int attackResult = (int)((attackForce / totalDamage) * attackA * 4.5f + 0.5f);
int defenseResult = (int)((defenseForce / totalDamage) * defenseB * 4.5f + 0.5f);
//Debug.Log((attackForce / totalDamage) * TH1UnitAttackList[Ano] * 4.5f);
if (counter) return defenseResult;
else return attackResult;
}
public float QueryDamage(int HP1,int HP2,int maxHP1,int maxHP2,int atk1,int atk2,int dfs1,int dfs2,bool counter = false)
{
return 5f;
}
//UI显示文字相关
public string[] tileInfo(GridData t)//返回tile的名称用于bottomInfoUI
{
string[] ret = new string[2];
ret[0] = t.Terrain switch
{
TerrainType.DeepSea => "深海",
TerrainType.ShallowSea => "浅海",
_ => "平原"
};
if (t.Feature == TerrainFeature.Mountain)
ret[0] = "山脉";
if (t.Vegetation == Vegetation.Trees)
ret[0] = "森林";
if (t.Resource == ResourceType.Animal)
ret[0] = "动物森林";
if (t.Resource == ResourceType.Fruit)
ret[0] = "蔬果";
if (t.Resource == ResourceType.Fish)
ret[0] = "渔业";
if (t.Resource == ResourceType.Treasure)
ret[0] = "遗迹";
if (t.Resource == ResourceType.Starfish)
ret[0] = "海星";
if (t.Resource == ResourceType.CityCenter)
ret[0] = "村庄";
if (t.Resource == ResourceType.Metal)
ret[0] = "金矿山脉";
if (t.Resource == ResourceType.Crop)
ret[0] = "庄稼";
if (t.Resource == ResourceType.Mine)
ret[0] = "采矿场";
if (t.Resource == ResourceType.LumberHut)
ret[0] = "伐木场";
if (t.Resource == ResourceType.Farm)
ret[0] = "农田";
if (t.Resource == ResourceType.Windmill)
ret[0] = "谷仓";
if (t.Resource == ResourceType.Sawmill)
ret[0] = "加工厂";
if (t.Resource == ResourceType.Forge)
ret[0] = "冶炼厂";
if (t.Resource == ResourceType.Market)
ret[0] = "市场";
if (t.Resource == ResourceType.Temple)
ret[0] = "神庙";
if (t.Resource == ResourceType.ForestTemple)
ret[0] = "森林神庙";
if (t.Resource == ResourceType.WaterTemple)
ret[0] = "海洋神庙";
if (t.Resource == ResourceType.MountainTemple)
ret[0] = "山神庙";
ret[1] = ret[0] switch
{
"深海" => "可建造神庙。需<帆船><海洋学>等科技。",
"浅海" => "可建造港口、桥梁和神庙。需<捕鱼><海洋学><道路>等科技。",
"山脉" => "可采矿或建造神庙。需<爬山><冥想>等科技。",
"港口" => "可改造船只或建立贸易路线。",
"渔业" => "可收获渔业。需<捕鱼>科技。",
"动物森林" => "可狩猎。需<狩猎>等科技。",
"森林" => "可伐木、焚林或建木材厂。需<伐木><建造>等科技。",
"蔬果" => "可采集蔬果。需<采集>科技。",
"庄稼" => "可建设农田。需<耕种>科技。",
"金矿山脉" => "可建设矿山。需<采矿>科技。",
"村庄" => "可占领并建立属于你的城市。",
"遗迹" => "可挖掘遗迹获得随机奖励。",
"海星" => "可采集海星获得金钱。需<远洋导航>科技。",
"伐木场" => "可在伐木场周围1格建设加工厂。需<数学>科技。",
"农田" => "可在农田周围1格建设谷仓。需<建造>科技。",
"谷仓" => "周围的每片农田可以提供1点城市经验。每座城市仅能拥有一个谷仓。",
"加工厂" => "周围的每座伐木场可以提供1点城市经验。每座城市仅能拥有一个加工厂。",
"采矿场" => "可在采矿场周围1格建设冶炼厂。需<采矿>科技。",
"冶炼厂" => "周围的每座伐木场可以提供2点城市经验。每座城市仅能拥有一个冶炼厂。",
"市场" => "每回合提供周围加工厂、采矿场、冶炼厂等级总和的额外金币。",
"神庙" => "每回合提供信仰分。",
"海洋神庙" => "每回合提供信仰分。",
"山神庙" => "每回合提供信仰分。",
"森林神庙" => "每回合提供信仰分。",
_ => "这是一片平原区域。解锁高阶科技完成更多建设活动。"
};
return ret;
}
public string civName(int civId) { return civNameList[civId]; }
public string[] unitInfo(UnitData u, GiantType g = GiantType.None)//返回tile的名称用于bottomInfoUI
{
string[] ret = new string[2];
ret[0] = u.UnitType switch
{
UnitType.Warrior => "步兵",
UnitType.Rider => "轻骑兵",
UnitType.Defender => "盾兵",
UnitType.Archer => "射手",
UnitType.Knights => "重骑兵",
UnitType.Catapult => "炮手",
UnitType.Swordsman => "剑士",
UnitType.Boat => "小船",
UnitType.Ship => "帆船",
UnitType.RammerShip => "冲锋艇",
UnitType.BomberShip => "战舰",
UnitType.BigGuy => "巨人",
_ => ""
};
if (g != GiantType.None)
{
ret[0] = u.GiantType switch
{
GiantType.EgyptianFlandre => "芙兰朵露·斯卡雷特",
GiantType.EgyptianMeiling => "红美铃",
GiantType.EgyptianPatchouli => "帕秋莉·诺蕾姬",
GiantType.EgyptianRemilia => "蕾米莉亚·斯卡雷特",
GiantType.EgyptianSakuya => "十六夜咲夜",
_ => ""
};
}
ret[1] = ret[0] switch
{
"步兵" => "基础单位。拥有<冲刺>和<城防>技能。",
"轻骑兵" => "高机动性单位。拥有2移动力和<冲刺><城防><遁走>技能。",
"射手" => "远程单位拥有2射程和<冲刺><城防>技能。",
"盾兵" => "防御单位。拥有3防御力和<城防>技能。",
"重骑兵" => "强力机动单位。拥有3移动力3.5攻击力和<冲刺><连续杀敌>技能。",
"炮兵" => "强力远程单位。拥有3射程4攻击力和<城防>技能。无法反击。",
"剑士" => "强力综合单位。拥有3防御力3攻击力和<冲刺>技能。",
"巨人" => "超强力综合单位。拥有40血量和4攻击力。",
"小船" => "基础海上单位。拥有2移动力无法攻击。",
"帆船" => "海上远程单位。拥有3移动力2射程和<巡洋><冲刺>技能。",
"冲锋艇" => "海上强力近战。拥有3移动力3攻击力3防御力和<冲刺>技能。",
"战舰" => "海上超强远程。拥有2移动力3.5攻击力3射程和<溅射>技能。无法反击。",
"芙兰朵露·斯卡雷特" => "<马>职阶伟人,破局者。拥有<四重存在>技能。",
"红美铃" => "<车>职阶伟人,狂战士。拥有<太极>技能。",
"帕秋莉·诺蕾姬" => "<相>职阶伟人,强大辅助。拥有<皇家烈焰>技能。",
"蕾米莉亚·斯卡雷特" => "<王>职阶伟人,铜墙铁壁。拥有<吸血盛宴>技能。",
"十六夜咲夜" => "<车>职阶伟人,超高机动性刺客,拥有<时间停止>技能。",
_ => ""
};
return ret;
}
//public string UnitTypeToName(UnitType unitType) { return TH1UnitTypeNameList[QueryUnitTypeToNo(unitType)]; }
public int QueryUnitTypeToNo(UnitType unitType)
{
return unitType switch
{
UnitType.Warrior => 0,
UnitType.Rider => 1,
UnitType.Archer => 2,
UnitType.Defender => 3,
UnitType.Knights => 4,
UnitType.Catapult => 5,
UnitType.Swordsman => 6,
UnitType.Cloak => 7,
UnitType.Minder => 8,
UnitType.Boat => 9,
UnitType.Ship => 10,
UnitType.RammerShip => 11,
UnitType.BomberShip => 12,
_ => -1
};
}
//返回每个action的cost
public int QueryActionCost(CommonActionId actionId)
{
if (actionId.ActionType == CommonActionType.Build)
{
if (actionId.ResourceType == ResourceType.LumberHut)
return 3;
if (actionId.ResourceType == ResourceType.Temple
|| actionId.ResourceType == ResourceType.ForestTemple
|| actionId.ResourceType == ResourceType.WaterTemple
|| actionId.ResourceType == ResourceType.MountainTemple )
return 20;
return 5;
}
else if (actionId.ActionType == CommonActionType.TrainUnit)
{
return UnitTypeDataAssets.GetUnitTypeInfo(actionId.UnitType,actionId.GiantType,out var Info)?Info.Cost:0;
}
else if (actionId.ActionType == CommonActionType.Gain)
{
return 2;
}
return 0;
}
public int QueryActionExp(CommonActionId actionId)
{
Debug.Log(ActionDataAssets.GetActionInfo(actionId, out var actionInfo));
Debug.Log(actionInfo.CityExp);
return actionInfo.CityExp;
}
}