|  |  |  | 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(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |