You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
359 lines
13 KiB
C#
359 lines
13 KiB
C#
using UnityEngine;
|
|
using Articy.Touhou;
|
|
using Articy.Touhou.Features;
|
|
|
|
public enum EEntityType
|
|
{
|
|
None,
|
|
Master,
|
|
MasterSoul,
|
|
Monster,
|
|
Door,
|
|
Npc,
|
|
Bullet,
|
|
Pt,
|
|
BlessInteract,
|
|
}
|
|
|
|
namespace Game
|
|
{
|
|
public delegate void EntityCreateHandler(GameEntity entity);
|
|
|
|
public abstract partial class Util
|
|
{
|
|
private static bool CreateEntityCheck(string cfgId)
|
|
{
|
|
if (string.IsNullOrEmpty(cfgId))
|
|
{
|
|
Util.Print("创建实体失败,cfgId为空");
|
|
return false;
|
|
}
|
|
|
|
var cfg = Util.GetConfig(cfgId);
|
|
if (cfg is null)
|
|
{
|
|
Util.Print("创建实体失败,cfgId错误:", cfgId);
|
|
return false;
|
|
}
|
|
|
|
if (!(cfg is IObjectWithFeatureEntityParam))
|
|
{
|
|
Util.Print("创建实体失败,没有实体Feature:", cfgId);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
//创建子实体
|
|
public static void CreateSubEntity(int index, int ownerId, int targetId, Vector3 direction, Vector3 pos)
|
|
{
|
|
var owner = Util.GetEntity(ownerId);
|
|
var cfgId = owner.CfgId();
|
|
if (!CreateEntityCheck(cfgId))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var cfg = Util.GetConfig(cfgId);
|
|
var battleCfg = ((IObjectWithFeatureEntityParamBattle)cfg).GetFeatureEntityParamBattle();
|
|
var subEntityList = battleCfg.SubEntityList;
|
|
if (subEntityList.Count == 0)
|
|
{
|
|
Util.Print("子实体数量为0:", cfgId);
|
|
return;
|
|
}
|
|
|
|
if (index < 0 || index >= subEntityList.Count)
|
|
{
|
|
Util.Print("子实体创建失败 序号错误:", cfgId, index, subEntityList.Count);
|
|
return;
|
|
}
|
|
|
|
var subCfgId = subEntityList[index].TechnicalName;
|
|
var team = owner.Team();
|
|
CreateEntity(subCfgId, (entity) =>
|
|
{
|
|
entity.SetTeam(team);
|
|
entity.SetOwner(ownerId);
|
|
entity.SetTarget(targetId);
|
|
Util.SetEntityPos(entity, pos);
|
|
if (entity.hasBullet)
|
|
{
|
|
entity.bullet.CastDir = direction;
|
|
Util.CastSkillBullet(entity);
|
|
}
|
|
});
|
|
}
|
|
|
|
public static void CreateEntityImmediately(string cfgId, EntityCreateHandler callback)
|
|
{
|
|
if (!CreateEntityCheck(cfgId))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var entity = Contexts.sharedInstance.game.CreateEntity();
|
|
entity.AddID(cfgId, null);
|
|
entity.iD.Data.IsCreate = false;
|
|
CreateEntityReal(entity);
|
|
callback(entity);
|
|
}
|
|
|
|
public static void CreateEntity(string cfgId, EntityCreateHandler callback)
|
|
{
|
|
if (!CreateEntityCheck(cfgId))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var entity = Contexts.sharedInstance.game.CreateEntity();
|
|
entity.AddID(cfgId, callback);
|
|
}
|
|
|
|
public static void CreateEntityReal(GameEntity entity)
|
|
{
|
|
var cfgId = entity.CfgId();
|
|
var cfg = Util.GetConfig(cfgId);
|
|
var basicCfg = ((IObjectWithFeatureEntityParam)cfg).GetFeatureEntityParam();
|
|
var entityType = (EEntityType)basicCfg.EntityType;
|
|
switch (entityType)
|
|
{
|
|
case EEntityType.Master:
|
|
UtilEntityPackage.CreateMaster(entity);
|
|
break;
|
|
case EEntityType.MasterSoul:
|
|
UtilEntityPackage.CreateMasterSoul(entity);
|
|
break;
|
|
case EEntityType.Monster:
|
|
UtilEntityPackage.CreateMonster(entity);
|
|
break;
|
|
case EEntityType.Door:
|
|
UtilEntityPackage.CreateDoor(entity);
|
|
break;
|
|
case EEntityType.Npc:
|
|
UtilEntityPackage.CreateNpc(entity);
|
|
break;
|
|
case EEntityType.BlessInteract:
|
|
UtilEntityPackage.CreateBlessInteract(entity);
|
|
break;
|
|
case EEntityType.Bullet:
|
|
UtilEntityPackage.CreateBullet(entity);
|
|
break;
|
|
case EEntityType.Pt:
|
|
UtilEntityPackage.CreatePoint(entity);
|
|
break;
|
|
}
|
|
|
|
BuildBasic(entity, basicCfg);
|
|
|
|
if (cfg is IObjectWithFeatureEntityParamBattle battle)
|
|
{
|
|
var battleCfg = battle.GetFeatureEntityParamBattle();
|
|
BuildBattle(entity, battleCfg);
|
|
}
|
|
|
|
if (cfg is IObjectWithFeatureEntityParamView view)
|
|
{
|
|
var viewCfg = view.GetFeatureEntityParamView();
|
|
BuildView(entity, viewCfg);
|
|
}
|
|
|
|
if (cfg is IObjectWithFeatureBlessInteractParam param)
|
|
{
|
|
var blessInteractCfg = param.GetFeatureBlessInteractParam();
|
|
BuildBlessInteract(entity, blessInteractCfg);
|
|
}
|
|
|
|
if (cfg is IObjectWithFeatureBullet bullet)
|
|
{
|
|
var bulletCfg = bullet.GetFeatureBullet();
|
|
BuildBullet(entity, bulletCfg);
|
|
}
|
|
|
|
if (cfg is IObjectWithFeatureEntityParamMonster monster)
|
|
{
|
|
var monsterCfg = monster.GetFeatureEntityParamMonster();
|
|
BuildMonster(entity, monsterCfg);
|
|
}
|
|
}
|
|
|
|
private static void BuildBasic(GameEntity entity, EntityParamFeature basicCfg)
|
|
{
|
|
var view = entity.view;
|
|
var offsetY = basicCfg.ViewOffset / 64f;
|
|
view.TransformViewOffset.localPosition = new Vector3(0, offsetY, 0);
|
|
view.TransformViewOther.localPosition = new Vector3(0, offsetY, 0);
|
|
view.TransformViewMain.localPosition = Vector3.zero;
|
|
|
|
var id = entity.iD;
|
|
id.Data.BasicCfg = basicCfg;
|
|
|
|
//加载动画
|
|
if (!entity.hasAnimation || string.IsNullOrEmpty(basicCfg.AnimationName))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var animation = entity.animation;
|
|
foreach (var item in GameConst.AllAnimationState)
|
|
{
|
|
var basicName = $"basic_{item}";
|
|
var name = basicCfg.AnimationName;
|
|
var nameSplit = name.Split('/');
|
|
var characterName = nameSplit[nameSplit.Length - 1];
|
|
var clipName = $"Character/{name}/{characterName}_{item}";
|
|
var clip = ResourceManager.Instance.Load<AnimationClip>(clipName);
|
|
if (!(clip is null))
|
|
{
|
|
animation.AnimatorOverrideController[basicName] = clip;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void BuildBattle(GameEntity entity, EntityParamBattleFeature cfg)
|
|
{
|
|
var moveParamCfg = cfg.MoveParam;
|
|
var shieldParamCfg = cfg.ShieldParam;
|
|
var stunParamCfg = cfg.StunParam;
|
|
var hitBoxParamCfg = cfg.HitBoxParam;
|
|
|
|
//移动
|
|
if (entity.hasMove)
|
|
{
|
|
var moveParam = entity.move.MoveParam;
|
|
var basicParam = ((IObjectWithFeatureMoveParamBasic)moveParamCfg).GetFeatureMoveParamBasic();
|
|
var jumpParam = ((IObjectWithFeatureMoveParamJump)moveParamCfg).GetFeatureMoveParamJump();
|
|
|
|
moveParam.MoveForce = basicParam.MoveForce;
|
|
moveParam.MoveSpeedMax = basicParam.SpeedMax;
|
|
moveParam.AirDrag = basicParam.AirDrag;
|
|
moveParam.GroundDrag = basicParam.GroundDrag;
|
|
moveParam.Gravity = basicParam.Gravity;
|
|
|
|
moveParam.NeedScale = basicParam.needScale;
|
|
|
|
moveParam.JumpTimeMax = jumpParam.JumpTimeMax;
|
|
moveParam.JumpTimeMin = jumpParam.JumpTimeMin;
|
|
moveParam.JumpForce = jumpParam.JumpForce;
|
|
moveParam.FallForce = jumpParam.fallSpeed;
|
|
moveParam.AirSpeedMaxRate = jumpParam.airMoveRate;
|
|
}
|
|
|
|
//血量 护盾 处决条 眩晕条
|
|
if (entity.hasHp)
|
|
{
|
|
//血量
|
|
var hp = entity.hp;
|
|
hp.HpMax.Value = cfg.HpMax;
|
|
hp.Hp.Value = cfg.HpMax;
|
|
//护盾
|
|
hp.ShieldMax.Value = cfg.ShieldMax;
|
|
hp.Shield.Value = cfg.ShieldMax;
|
|
//护盾参数
|
|
if (!(shieldParamCfg is null))
|
|
{
|
|
var shieldParam = ((IObjectWithFeatureShield)shieldParamCfg).GetFeatureShield();
|
|
hp.ShieldRecoverTimeMax = shieldParam.Time;
|
|
hp.ShieldRecoverTime = shieldParam.Time;
|
|
hp.ShieldRecover = shieldParam.RecoverSpeed;
|
|
if (entity.hasProperty)
|
|
{
|
|
Util.SetProperty(entity, EProperty.ShieldStaggerDefLevel, (int)shieldParam.StaggerDefLevel);
|
|
}
|
|
}
|
|
|
|
//眩晕参数
|
|
if (!(stunParamCfg is null))
|
|
{
|
|
var stunParam = ((IObjectWithFeatureStun)stunParamCfg).GetFeatureStun();
|
|
hp.StunRecoverTimeMax = stunParam.Time;
|
|
hp.StunRecoverTime = stunParam.Time;
|
|
hp.StunRecover = stunParam.RecoverSpeed;
|
|
hp.StunMax.Value = stunParam.StunMax;
|
|
hp.Stun.Value = 0;
|
|
}
|
|
|
|
//受击框参数
|
|
if (!(hitBoxParamCfg is null))
|
|
{
|
|
var hitBoxParam =
|
|
((IObjectWithFeatureEntityHitBoxParam)hitBoxParamCfg).GetFeatureEntityHitBoxParam();
|
|
hp.HitBoxShape = Shape.NewCircle(Vector3.zero, hitBoxParam.Height / 64f, hitBoxParam.Radius / 64f);
|
|
}
|
|
}
|
|
|
|
//基础属性
|
|
if (entity.hasProperty)
|
|
{
|
|
Util.SetProperty(entity, EProperty.BasicAttack, cfg.BasicAttack);
|
|
Util.SetProperty(entity, EProperty.BasicStun, cfg.BasicStun);
|
|
Util.SetProperty(entity, EProperty.StaggerDefLevel, (int)cfg.StaggerDefLevel);
|
|
}
|
|
}
|
|
|
|
private static void BuildView(GameEntity entity, EntityParamViewFeature cfg)
|
|
{
|
|
var view = entity.view;
|
|
if (!(cfg.Icon is null))
|
|
{
|
|
var texture = Util.LoadDraft<Texture2D>(cfg.Icon);
|
|
var rect = new Rect(0, 0, texture.width, texture.height);
|
|
//像素化
|
|
if (cfg.IsPixel)
|
|
{
|
|
texture.filterMode = FilterMode.Point;
|
|
}
|
|
|
|
var sp = Sprite.Create(texture, rect, new Vector2(0.5f, 0.5f), 64);
|
|
view.SpriteRenderer.sprite = sp;
|
|
}
|
|
|
|
//缩放
|
|
var scale = cfg.Scale;
|
|
view.TransformView.localScale = new Vector3(scale, scale, scale);
|
|
|
|
var id = entity.iD;
|
|
id.Data.Effect = cfg.Effect;
|
|
id.Data.EffectCreate = cfg.EffectCreate;
|
|
id.Data.EffectDestroy = cfg.EffectDestroy;
|
|
|
|
if (!string.IsNullOrEmpty(cfg.Effect))
|
|
{
|
|
Util.CastFollowEffect(cfg.Effect, entity.ID());
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(cfg.EffectCreate))
|
|
{
|
|
Util.CastHitEffect(cfg.EffectCreate, entity.ID());
|
|
}
|
|
}
|
|
|
|
private static void BuildBlessInteract(GameEntity entity, BlessInteractParamFeature cfg)
|
|
{
|
|
var interact = entity.interact;
|
|
// interact.TargetId = ((EElementType)cfg.Element).ToString();
|
|
}
|
|
|
|
private static void BuildBullet(GameEntity entity, BulletFeature cfg)
|
|
{
|
|
var bullet = entity.bullet;
|
|
bullet.Timeline = cfg.Timeline;
|
|
}
|
|
|
|
private static void BuildMonster(GameEntity entity, EntityParamMonsterFeature cfg)
|
|
{
|
|
var ai = entity.aI;
|
|
var view = entity.view;
|
|
ai.BehaviorTree = BehaviorTreePoolManager.Instance.CreateAIEntity(entity, cfg.AIRes);
|
|
var go = view.GameObject;
|
|
var goMonsterInfo = go.GetComponent<EntityMonsterInfo>();
|
|
if (goMonsterInfo == null)
|
|
{
|
|
goMonsterInfo = go.AddComponent<EntityMonsterInfo>();
|
|
}
|
|
|
|
goMonsterInfo.Tree = ai.BehaviorTree.AIObject.Tree();
|
|
}
|
|
}
|
|
} |