(client) feat:添加事件定义,定义部分怪物

This commit is contained in:
m0_75251201
2025-09-03 18:13:29 +08:00
parent ce04c8cec8
commit eb9cf415f2
79 changed files with 4666 additions and 4981 deletions

View File

@ -0,0 +1,12 @@
using Base;
using UnityEngine;
namespace EventWorkClass
{
public abstract class EventWorkClassBase
{
public abstract void Init(string value);
public abstract void Run(string dimensionID);
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 1258c84f5c82460ead132b62741c0be3
timeCreated: 1756786734

View File

@ -0,0 +1,305 @@
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;
}
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: aea1fb7d2e1c45e4ac62da4ae8f81393
timeCreated: 1756789875

View File

@ -0,0 +1,273 @@
using System;
using System.Collections.Generic;
using Data;
using Managers;
using UnityEngine;
using System.Linq;
using Entity;
using Map; // 用于 LINQ
namespace EventWorkClass
{
/// <summary>
/// Event_GiveHediff 事件的配置数据结构。
/// </summary>
[Serializable]
public class GiveHediffConfig
{
/// <summary>
/// 要添加或移除的 Hediff 的定义名 (defName)。
/// </summary>
public string HediffDefName;
/// <summary>
/// 要添加或移除的 Hediff 定义的具体类型名,例如 "HediffDef" 或其子类名。
/// 用于 DefineManager 的严格类型查找。
/// </summary>
public string HediffDefTypeName;
/// <summary>
/// 要执行的操作类型:添加或移除 Hediff。
/// </summary>
public HediffActionType ActionType;
/// <summary>
/// 目标实体选择类型。
/// </summary>
public TargetEntitySelectionType TargetSelectionType;
// 以下是各种 TargetSelectionType 可能需要的配置参数
/// <summary>
/// 用于 SpecificEntityById 类型目标实体的唯一ID。
/// </summary>
public string TargetEntityId;
/// <summary>
/// 用于 AllEntitiesInFaction 或 TargetSpecificFactionLeader 类型:目标派系的定义名 (factionDefName)。
/// </summary>
public string TargetFactionDefName;
/// <summary>
/// 用于 AroundSpecificCoordinates 类型:生成中心坐标。
/// </summary>
public Vector3 CenterCoordinates;
/// <summary>
/// 用于 AroundSpecificCoordinates 类型:搜索半径。
/// </summary>
public float Radius = 10f; // 默认半径
}
/// <summary>
/// 定义针对 Hediff 的操作类型。
/// </summary>
public enum HediffActionType
{
/// <summary>
/// 添加 Hediff。
/// </summary>
Add,
/// <summary>
/// 移除 Hediff。
/// </summary>
Remove
}
/// <summary>
/// 定义目标实体选择的类型。
/// </summary>
public enum TargetEntitySelectionType
{
/// <summary>
/// 未指定或无效的目标选择类型。
/// </summary>
None = 0,
/// <summary>
/// 目标是当前玩家(如果存在)。
/// </summary>
Player,
/// <summary>
/// 目标是指定派系的所有活动实体。
/// </summary>
AllEntitiesInFaction,
/// <summary>
/// 目标是指定坐标周围半径内的所有生物。
/// </summary>
AroundSpecificCoordinates
}
/// <summary>
/// Event_GiveHediff 事件类:用于给予或移除健康状态 (Hediff)。
/// </summary>
public class Event_GiveHediff : EventWorkClassBase
{
private GiveHediffConfig _config;
private HediffDef _aimHediffDef;
/// <summary>
/// 初始化 Hediff 给予/移除事件。
/// </summary>
/// <param name="value">包含事件配置的JSON字符串。</param>
public override void Init(string value)
{
if (string.IsNullOrEmpty(value))
{
Debug.LogError("Event_GiveHediff: 初始化值为空或null。请提供一个JSON配置字符串。");
return;
}
try
{
_config = JsonUtility.FromJson<GiveHediffConfig>(value);
if (_config == null)
{
Debug.LogError($"Event_GiveHediff: 无法解析配置JSON: {value}");
return;
}
if (string.IsNullOrEmpty(_config.HediffDefTypeName) || string.IsNullOrEmpty(_config.HediffDefName))
{
Debug.LogError($"Event_GiveHediff: Hediff定义类型名或名称为空或null (名称: '{_config.HediffDefName}', 类型: '{_config.HediffDefTypeName}')。无法查找Hediff定义。");
return;
}
_aimHediffDef = (HediffDef)DefineManager.Instance.FindDefine(_config.HediffDefTypeName, _config.HediffDefName);
if (_aimHediffDef == null)
{
Debug.LogError($"Event_GiveHediff: 未找到Hediff定义 (名称: '{_config.HediffDefName}', 类型: '{_config.HediffDefTypeName}')。请检查配置。");
}
}
catch (Exception ex)
{
Debug.LogError($"Event_GiveHediff: 解析配置JSON时出错: {value}。异常信息: {ex.Message}");
}
}
/// <summary>
/// 运行 Hediff 给予/移除事件。
/// </summary>
/// <param name="dimensionID">目标实体所在的维度ID。</param>
public override void Run(string dimensionID)
{
if (_config == null)
{
Debug.LogError("Event_GiveHediff: 事件配置(_config)为空。Init()可能失败了。");
return;
}
if (_aimHediffDef == null)
{
Debug.LogError($"Event_GiveHediff: 目标Hediff定义为空 (名称: {_config.HediffDefName}, 类型: {_config.HediffDefTypeName})。无法执行操作。");
return;
}
var targetEntities = GetTargetEntities(dimensionID);
if (targetEntities == null || targetEntities.Count == 0)
{
Debug.LogWarning($"Event_GiveHediff: 在维度 '{dimensionID}' 中未找到符合条件的目标实体 (选择类型: {_config.TargetSelectionType})。");
return;
}
var successCount = 0;
var failedCount = 0;
var hediffInstance = new Hediff(_aimHediffDef); // 创建 Hediff 实例
foreach (var entity in targetEntities)
{
if (entity is LivingEntity livingEntity)
{
try
{
if (_config.ActionType == HediffActionType.Add)
{
livingEntity.AddHediff(hediffInstance);
Debug.Log($"Event_GiveHediff: 已向实体 '{livingEntity.name}' 添加 Hediff '{_aimHediffDef.defName}'。");
successCount++;
}
else if (_config.ActionType == HediffActionType.Remove)
{
livingEntity.RemoveHediff(hediffInstance);
Debug.Log($"Event_GiveHediff: 已从实体 '{livingEntity.name}' 移除 Hediff '{_aimHediffDef.defName}'。");
successCount++;
}
}
catch (Exception ex)
{
Debug.LogError($"Event_GiveHediff: 对实体 '{entity.name}' 执行 Hediff 操作时出错: {ex.Message}");
failedCount++;
}
}
else
{
Debug.LogWarning($"Event_GiveHediff: 实体 '{entity.name}' (类型: {entity.GetType().Name}) 不是 LivingEntity无法添加/移除 Hediff。");
failedCount++;
}
}
Debug.Log($"Event_GiveHediff: 完成操作。成功: {successCount},失败: {failedCount} (Hediff: {_aimHediffDef.defName}, 操作: {_config.ActionType})。");
}
/// <summary>
/// 根据配置获取目标实体列表。
/// </summary>
/// <param name="dimensionID">维度ID。</param>
/// <returns>符合条件的目标实体列表。</returns>
private List<Entity.Entity> GetTargetEntities(string dimensionID)
{
var entities = new List<Entity.Entity>();
var dimension = Program.Instance.GetDimension(dimensionID);
if (dimension == null)
{
Debug.LogError($"Event_GiveHediff: 未找到维度 '{dimensionID}'。无法获取目标实体。");
return entities;
}
switch (_config.TargetSelectionType)
{
case TargetEntitySelectionType.Player:
// 假设 PlayerManager.Instance.GetPlayerEntity(dimensionID) 返回 LivingEntity
// 或者你的玩家实体本身就是 LivingEntity
var player = dimension.focusEntity as LivingEntity; // 假设玩家是维度的一部分且是LivingEntity
if (player != null)
{
entities.Add(player);
}
else
{
Debug.LogWarning($"Event_GiveHediff: 未能找到维度 '{dimensionID}' 中的玩家实体或玩家不是 LivingEntity。");
}
break;
case TargetEntitySelectionType.AllEntitiesInFaction:
if (string.IsNullOrEmpty(_config.TargetFactionDefName))
{
Debug.LogWarning("Event_GiveHediff: 配置了 'AllEntitiesInFaction',但 'TargetFactionDefName' 为空。");
return entities;
}
entities.AddRange(EntityManage.Instance
.FindEntitiesByFaction(dimensionID, _config.TargetFactionDefName)
.Select(item => item.entity));
break;
case TargetEntitySelectionType.AroundSpecificCoordinates:
// 假设 EntityManage 提供了根据位置和半径查找实体的方法
// 或者可以直接通过场景查询(例如 Physics.OverlapSphere 或者自定义管理系统)
// 为了简化,我将假设 EntityManage 提供 FindEntitiesAroundRadius 方法
var allEntitiesInDimension = EntityManage.Instance.GetAllEntities(dimensionID)
.Select(item => item.entity);
var center = _config.CenterCoordinates;
var radius = _config.Radius;
foreach (var ent in allEntitiesInDimension)
{
// 确保实体有 Transform 且在半径内
if (ent != null && ent.transform != null && Vector3.Distance(ent.transform.position, center) <= radius)
{
entities.Add(ent);
}
}
break;
case TargetEntitySelectionType.None:
default:
Debug.LogWarning($"Event_GiveHediff: 未知或不支持的目标实体选择类型: {_config.TargetSelectionType}。");
break;
}
return entities;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 2e8b013e0825473e9dbba1f7f393e66f
timeCreated: 1756860849