Files

353 lines
16 KiB
C#
Raw Permalink 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;
using System.Collections.Generic; // 新增用于List<T>
using Data;
using Managers;
using UnityEngine;
using Random = UnityEngine.Random;
using Newtonsoft.Json; // 新增Newtonsoft.Json的引用
namespace EventWorkClass
{
/// <summary>
/// Event_EntityGenerater 事件的配置数据结构。
/// </summary>
[Serializable]
public class EntityGenerateConfig
{
/// <summary>
/// 要生成的实体定义列表,将从中随机选择。
/// </summary>
public List<EntityDefinitionEntry> DefinitionsToChooseFrom;
/// <summary>
/// 要生成的实体总数。
/// </summary>
public int Count = 1; // 默认生成一个
/// <summary>
/// 生成位置类型。
/// </summary>
public EntitySpawnLocationType LocationType;
// 以下是各种LocationType可能需要的配置参数
/// <summary>
/// 用于 AroundSpecificCoordinates 类型:生成中心坐标。
/// </summary>
public Vector3 CenterCoordinates;
/// <summary>
/// 用于 AroundSpecificCoordinates 或 AroundTargetEntity 类型:生成半径。
/// </summary>
public float Radius = 10f; // 默认半径
/// <summary>
/// 用于 InsideSpecificBuildingType 类型目标建筑的类型ID。
/// </summary>
public string BuildingTypeDefName;
/// <summary>
/// 用于 AroundTargetEntity 类型:目标派系的定义名 (factionDefName)。
/// </summary>
public string TargetFactionDefName;
/// <summary>
/// 用于 AtPredefinedSpawnPoint 类型预定义生成点的ID。
/// </summary>
public string SpawnPointTileMapDefName;
/// <summary>
/// 用于 OffMap 类型:距离地图边界的额外偏移量。
/// </summary>
public float OffMapOffset = 5f;
}
/// <summary>
/// 单个实体定义的配置条目。
/// </summary>
[Serializable] // 保持可序列化以便在Unity Inspector中显示
public class EntityDefinitionEntry
{
/// <summary>
/// 实体定义名 (defName)。
/// </summary>
public string DefName;
/// <summary>
/// 实体定义的具体类型名。
/// </summary>
public string DefTypeName;
}
/// <summary>
/// 定义生成器生成地图实体的可能位置类型。
/// </summary>
public enum EntitySpawnLocationType
{
/// <summary>
/// 未指定或无效的生成位置类型。
/// </summary>
None = 0,
/// <summary>
/// 在地图的可玩区域边界之外生成实体。
/// 例如:用于在地图边缘或不可见区域生成物体,然后开始移动进入地图。
/// </summary>
OffMap,
/// <summary>
/// 在指定类型建筑的内部或附近生成实体。
/// 例如:在 "工厂"、"商店"、"居住区" 等建筑内或其出入口。
/// 需要一个标识符来指定建筑类型。
/// </summary>
InsideSpecificBuildingType,
/// <summary>
/// 在指定坐标点的周围区域内生成实体。
/// 需要额外的坐标参数和半径/范围参数。
/// </summary>
AroundSpecificCoordinates,
/// <summary>
/// 在特定派系或其他指定目标实体例如NPC或特定对象的周围区域内生成实体。
/// 需要一个标识符来指定目标派系的定义名,以及一个半径/范围参数。
/// </summary>
AroundTargetEntity,
/// <summary>
/// 在地图上的随机可生成点生成实体。
/// </summary>
RandomlyOnMap,
/// <summary>
/// 在预定义的生成点Spawn Point生成实体。
/// 这些点通常由地图设计者放置并带有唯一的ID或名称。
/// </summary>
AtPredefinedSpawnPoint
}
public class Event_EntityGenerater : EventWorkClassBase
{
private EntityGenerateConfig _config;
private List<EntityDef> _validatedEntityDefs; // 用于存储所有已验证的实体定义
/// <summary>
/// 初始化实体生成器事件。
/// </summary>
/// <param name="value">包含事件配置的JSON字符串。</param>
public override void Init(string value)
{
if (string.IsNullOrEmpty(value))
{
Debug.LogError("初始化值为空或null。请提供一个JSON配置字符串。");
return;
}
try
{
_config = JsonConvert.DeserializeObject<EntityGenerateConfig>(value); // 使用Newtonsoft.Json
}
catch (Exception ex)
{
Debug.LogError($"解析配置JSON时出错: {value}。异常信息: {ex.Message}");
return; // 解析失败,直接返回
}
if (_config == null)
{
Debug.LogError($"无法解析配置JSON: {value}");
return;
}
if (_config.DefinitionsToChooseFrom == null || _config.DefinitionsToChooseFrom.Count == 0)
{
Debug.LogError($"实体生成配置中没有定义任何要生成的实体。请检查 'DefinitionsToChooseFrom' 列表。");
return;
}
_validatedEntityDefs = new List<EntityDef>();
foreach (var entry in _config.DefinitionsToChooseFrom)
{
if (string.IsNullOrEmpty(entry.DefTypeName))
{
Debug.LogWarning($"实体定义类型名为空或null (实体定义名: '{entry.DefName}')。跳过此定义。");
continue;
}
var entityDef = (EntityDef)DefineManager.Instance.FindDefine(entry.DefTypeName, entry.DefName);
if (entityDef == null)
{
Debug.LogWarning($"未找到实体定义 (名称: '{entry.DefName}', 类型: '{entry.DefTypeName}')。请检查配置。跳过此定义。");
}
else
{
_validatedEntityDefs.Add(entityDef);
}
}
if (_validatedEntityDefs.Count == 0)
{
Debug.LogError($"所有配置的实体定义都无效或未找到。事件初始化失败。");
}
}
/// <summary>
/// 运行实体生成器事件,在指定维度生成实体。
/// </summary>
/// <param name="dimensionID">要生成实体的维度ID。</param>
public override void Run(string dimensionID)
{
if (_config == null)
{
Debug.LogError("事件配置(_config)为空。Init()可能失败了。");
return;
}
if (_validatedEntityDefs == null || _validatedEntityDefs.Count == 0)
{
Debug.LogError("没有有效实体定义可供生成。请检查Init()方法和配置。");
return;
}
for (int i = 0; i < _config.Count; i++)
{
// 随机选择一个实体定义
var selectedEntityDef = _validatedEntityDefs[Random.Range(0, _validatedEntityDefs.Count)];
var position = GetPosition(dimensionID);
// 检查 GetPosition 是否返回了有效的非零位置,除非它是 AroundSpecificCoordinates 且中心点就是 Vector3.zero
if (position == Vector3.zero && (_config.LocationType != EntitySpawnLocationType.AroundSpecificCoordinates
|| _config.CenterCoordinates != Vector3.zero))
{
Debug.LogWarning($"未能为类型 {_config.LocationType} 获取有效的生成位置。实体可能在原点 (0,0,0) 生成。");
}
if (selectedEntityDef is CharacterDef characterDef)
{
EntityManage.Instance.GenerateEntity(dimensionID, characterDef, position);
continue;
}
if (selectedEntityDef is MonsterDef monsterDef)
{
EntityManage.Instance.GenerateMonsterEntity(dimensionID, monsterDef, position);
continue;
}
Debug.LogWarning($"目标实体 '{selectedEntityDef.defName}' (类型: {selectedEntityDef.GetType().Name}) 既不是 CharacterDef 也不是 MonsterDef。" +
$"如果你想生成其他类型EntityManage需要一个通用的生成实体方法。没有生成此实体。");
}
}
/// <summary>
/// 根据配置获取实体生成位置。
/// </summary>
/// <param name="dimensionID">要获取位置的维度ID。</param>
/// <returns>计算出的生成位置,如果失败则返回 Vector3.zero。</returns>
private Vector3 GetPosition(string dimensionID)
{
if (_config == null)
{
Debug.LogError("获取位置时配置为空。返回 Vector3.zero。");
return Vector3.zero;
}
var dimension = Program.Instance.GetDimension(dimensionID);
if (dimension == null)
{
Debug.LogError($"未找到维度 '{dimensionID}'。无法确定生成位置。");
return Vector3.zero;
}
var mapGenerator = dimension.mapGenerator;
if (mapGenerator == null)
{
Debug.LogError($"维度 '{dimensionID}' 的地图生成器为空。无法确定生成位置。");
return Vector3.zero;
}
switch (_config.LocationType)
{
case EntitySpawnLocationType.OffMap:
{
var size = mapGenerator.GetSize();
var dir = Random.Range(0, 4); // 0:上, 1:下, 2:左, 3:右
Vector2Int gridCoord; // 地图网格坐标
Vector2Int worldCoord2D; // GetWorldCoordinates 返回的 Vector2Int
Vector3 worldPos3D; // 最终的 Vector3 世界坐标
var offset = _config.OffMapOffset;
switch (dir)
{
case 0: // Top border (max Y)
gridCoord = new Vector2Int(Random.Range(0, size.x), size.y);
worldCoord2D = mapGenerator.GetWorldCoordinates(gridCoord);
worldPos3D = new Vector3(worldCoord2D.x, worldCoord2D.y, 0f); // 转换为 Vector3
worldPos3D.y += offset;
break;
case 1: // Bottom border (min Y)
gridCoord = new Vector2Int(Random.Range(0, size.x), 0);
worldCoord2D = mapGenerator.GetWorldCoordinates(gridCoord);
worldPos3D = new Vector3(worldCoord2D.x, worldCoord2D.y, 0f); // 转换为 Vector3
worldPos3D.y -= offset;
break;
case 2: // Left border (min X)
gridCoord = new Vector2Int(0, Random.Range(0, size.y));
worldCoord2D = mapGenerator.GetWorldCoordinates(gridCoord);
worldPos3D = new Vector3(worldCoord2D.x, worldCoord2D.y, 0f); // 转换为 Vector3
worldPos3D.x -= offset;
break;
case 3: // Right border (max X)
gridCoord = new Vector2Int(size.x, Random.Range(0, size.y));
worldCoord2D = mapGenerator.GetWorldCoordinates(gridCoord);
worldPos3D = new Vector3(worldCoord2D.x, worldCoord2D.y, 0f); // 转换为 Vector3
worldPos3D.x += offset;
break;
default:
Debug.LogError("OffMap 生成方向无效。不应该发生此情况。");
return Vector3.zero;
}
worldPos3D.x += Random.Range(-offset / 2f, offset / 2f);
worldPos3D.y += Random.Range(-offset / 2f, offset / 2f);
return worldPos3D;
}
case EntitySpawnLocationType.AroundSpecificCoordinates:
{
var center = _config.CenterCoordinates;
var radius = _config.Radius;
var randomOffset = Random.insideUnitCircle * radius;
return new Vector3(center.x + randomOffset.x, center.y + randomOffset.y, center.z);
}
case EntitySpawnLocationType.AroundTargetEntity:
{
if (string.IsNullOrEmpty(_config.TargetFactionDefName))
{
Debug.LogWarning($"配置了 'AroundTargetEntity',但 'TargetFactionDefName' 为空或null。无法找到派系实体。将在原点生成。");
return Vector3.zero;
}
var factionEntities = EntityManage.Instance.FindEntitiesByFaction(dimensionID, _config.TargetFactionDefName);
if (factionEntities == null || factionEntities.Length == 0)
{
Debug.LogWarning($"在维度 '{dimensionID}' 中未找到派系 '{_config.TargetFactionDefName}' 的任何实体。将在原点生成。");
return Vector3.zero;
}
var randomIndex = Random.Range(0, factionEntities.Length);
var targetEntityPrefab = factionEntities[randomIndex];
if (targetEntityPrefab == null || targetEntityPrefab.transform == null)
{
Debug.LogWarning($"从派系 '{_config.TargetFactionDefName}' 中随机选择的实体为空或没有Transform组件。将在原点生成。");
return Vector3.zero;
}
var center = targetEntityPrefab.transform.position;
var radius = _config.Radius;
var randomOffset = Random.insideUnitCircle * radius;
Debug.Log($"围绕派系 '{_config.TargetFactionDefName}' 的实体 (世界坐标: {center}) 生成。生成的偏移量: {randomOffset}。");
return new Vector3(center.x + randomOffset.x, center.y + randomOffset.y, center.z);
}
case EntitySpawnLocationType.RandomlyOnMap:
{
var size = mapGenerator.GetSize();
var randomGridPos = new Vector2Int(Random.Range(0, size.x), Random.Range(0, size.y));
var worldCoord2D = mapGenerator.GetWorldCoordinates(randomGridPos);
var worldPos3D = new Vector3(worldCoord2D.x, worldCoord2D.y, 0f);
Debug.Log($"随机地图生成位置: {worldPos3D} (网格坐标: {randomGridPos})。");
return worldPos3D;
}
case EntitySpawnLocationType.InsideSpecificBuildingType:
{
Debug.LogWarning($"类型为 'InsideSpecificBuildingType' ({_config.BuildingTypeDefName}) 的生成逻辑尚未实现。返回 Vector3.zero。");
return Vector3.zero;
}
case EntitySpawnLocationType.AtPredefinedSpawnPoint:
{
Debug.LogWarning($"类型为 'AtPredefinedSpawnPoint' ({_config.SpawnPointTileMapDefName}) 的生成逻辑尚未实现。返回 Vector3.zero。");
return Vector3.zero;
}
case EntitySpawnLocationType.None:
default:
Debug.LogWarning($"未知或不支持的生成位置类型: {_config.LocationType}。返回 Vector3.zero。");
return Vector3.zero;
}
}
}
}