Files
2025-09-03 18:13:29 +08:00

306 lines
15 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 Data;
using Managers;
using UnityEngine;
using Random = UnityEngine.Random;
namespace EventWorkClass
{
/// <summary>
/// Event_EntityGenerater 事件的配置数据结构。
/// </summary>
[Serializable]
public class EntityGenerateConfig
{
/// <summary>
/// 要生成的实体定义名 (defName)。
/// </summary>
public string EntityDefName;
/// <summary>
/// 要生成的实体定义的具体类型名,例如 "CharacterDef" 或 "MonsterDef"。
/// 用于 DefineManager 的严格类型查找。
/// </summary>
public string EntityDefTypeName;
/// <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 BuildingTypeId;
/// <summary>
/// 用于 AroundTargetEntity 类型:目标派系的定义名 (factionDefName)。
/// </summary>
public string TargetFactionDefName;
/// <summary>
/// 用于 AtPredefinedSpawnPoint 类型预定义生成点的ID。
/// </summary>
public string SpawnPointId;
/// <summary>
/// 用于 OffMap 类型:距离地图边界的额外偏移量。
/// </summary>
public float OffMapOffset = 5f;
}
/// <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 EntityDef _aimEntity;
/// <summary>
/// 初始化实体生成器事件。
/// </summary>
/// <param name="value">包含事件配置的JSON字符串。</param>
public override void Init(string value)
{
if (string.IsNullOrEmpty(value))
{
Debug.LogError("初始化值为空或null。请提供一个JSON配置字符串。");
return;
}
try
{
_config = JsonUtility.FromJson<EntityGenerateConfig>(value);
if (_config == null)
{
Debug.LogError($"无法解析配置JSON: {value}");
return;
}
if (string.IsNullOrEmpty(_config.EntityDefTypeName))
{
Debug.LogError($"实体定义类型名为空或null (实体定义名: '{_config.EntityDefName}')。无法查找实体定义。");
return;
}
_aimEntity = (EntityDef)DefineManager.Instance.FindDefine(_config.EntityDefTypeName,_config.EntityDefName);
if (_aimEntity == null)
{
Debug.LogError($"未找到实体定义 (名称: '{_config.EntityDefName}', 类型: '{_config.EntityDefTypeName}')。请检查配置。");
}
}
catch (Exception ex)
{
Debug.LogError($"解析配置JSON时出错: {value}。异常信息: {ex.Message}");
}
}
/// <summary>
/// 运行实体生成器事件,在指定维度生成实体。
/// </summary>
/// <param name="dimensionID">要生成实体的维度ID。</param>
public override void Run(string dimensionID)
{
if (_config == null)
{
Debug.LogError("事件配置(_config)为空。Init()可能失败了。");
return;
}
if (_aimEntity == null)
{
Debug.LogError($"目标实体定义为空 (名称: {_config.EntityDefName}, 类型: {_config.EntityDefTypeName})。无法生成实体。");
return;
}
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 (_aimEntity is CharacterDef characterDef)
{
EntityManage.Instance.GenerateEntity(dimensionID, characterDef, position);
Debug.Log($"已在维度 {dimensionID} 的 {position} 位置生成角色 '{characterDef.defName}'。");
return;
}
if (_aimEntity is MonsterDef monsterDef)
{
EntityManage.Instance.GenerateMonsterEntity(dimensionID, monsterDef, position);
Debug.Log($"已在维度 {dimensionID} 的 {position} 位置生成怪物 '{monsterDef.defName}'。");
return;
}
Debug.LogWarning($"目标实体 '{_aimEntity.defName}' (类型: {_aimEntity.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.BuildingTypeId}) 的生成逻辑尚未实现。返回 Vector3.zero。");
return Vector3.zero;
}
case EntitySpawnLocationType.AtPredefinedSpawnPoint:
{
Debug.LogWarning($"类型为 'AtPredefinedSpawnPoint' ({_config.SpawnPointId}) 的生成逻辑尚未实现。返回 Vector3.zero。");
return Vector3.zero;
}
case EntitySpawnLocationType.None:
default:
Debug.LogWarning($"未知或不支持的生成位置类型: {_config.LocationType}。返回 Vector3.zero。");
return Vector3.zero;
}
}
}
}