using System;
using UnityEngine;
using Thousandto.Core.Base;
using Thousandto.Core.Asset;
using Thousandto.Cfg.Data;
using Thousandto.Code.Center;
using Thousandto.Code.Global;
using Thousandto.Core.PostEffect;
using System.Collections.Generic;
namespace Thousandto.Code.Logic
{
///
/// 怪物逻辑类
///
public class Monster : Character
{
#region//私有变量
//怪物属性模块
private MonsterProperty _propMoudleEx = null;
//角色震动模块,用于受击震动
private CharacherShaker _shaker = null;
//移动状态,true为跑,flase为走
private bool _isRunning = true;
//是否播放出生动作
private bool _isPlayBornAnum = false;
//是否已经播放了死亡特写
private bool _isPlayDeadFeature = false;
//护甲特效
private FGameObjectVFX _armorVfx = null;
//角色闪烁模块,用于受击闪烁
private HitBlinker _blinker = null;
//怪物出生时间,在此时间内不能被攻击
private float _bornTimer = 0f;
//是否正在播放镜头死亡特写
private bool _isPlayCameraDeadFeature = false;
private float _cameraOriDis = 0f;
private float _cameraOriYaw = 0f;
private float _cameraOriPitch = 0f;
private float _cameraFeatureTimer = 0f;
//是否锁定学历
private bool _isLockHP = false;
//是否使用缓存的假伤害
private bool _useCacaheDamage = false;
//缓存伤害,用于1血怪的表现
private ulong _cacheDamage = 0;
//缓存的当前血量,用于1血怪表现
private ulong _cacheCurHP = 0;
//存储当前攻击者数量,每一秒清理一次
private Dictionary _cacheAtker = new Dictionary();
#endregion
#region//静态变量
#endregion
#region 属性信息
public new MonsterProperty PropMoudle
{
get
{
if (_propMoudleEx == null)
{
_propMoudleEx = base.PropMoudle as MonsterProperty;
}
return _propMoudleEx;
}
}
//移动状态,true为跑,flase为走
public bool IsRunning
{
get
{
return _isRunning;
}
set
{
_isRunning = value;
}
}
//掉落的金币数量
public int DropGoldCount { get; set; }
//是否显示选中框
public override bool CanShowSelectUI
{
get
{
return true;
}
}
//是否可以被选择
public override bool CanBeSelect
{
get
{
if (PropMoudle.Cfg.CanBeSelect == 0)
return false;
return true;
}
}
public bool IsBoss
{
get;
private set;
}
//境界等级
public int RealmLevel
{
get
{
return PropMoudle.Cfg.StateLevel;
}
}
//是否加载完成
public bool IsLoadFinish
{
get;
private set;
}
//是否正在出生
public override bool IsBorning
{
get
{
return _bornTimer > 0f;
}
}
//角色闪烁模块,用于受击闪烁
public HitBlinker Blinker
{
get
{
return _blinker;
}
}
//当前血量
public override ulong CurHP
{
get
{
return PropMoudle.CurHP;
}
set
{
if(_useCacaheDamage)
{
if(value <= PropMoudle.CurHP)
{
//扣血
_cacheDamage += (PropMoudle.CurHP - value);
}
else
{
//回血
_cacheDamage = 0;
_cacheCurHP = value;
}
}
if (!_isLockHP && PropMoudle.CurHP != value)
{
PropMoudle.CurHP = value;
}
}
}
//血量百分比
public override float HpPercent
{
get
{
if(_useCacaheDamage)
{
if(IsDead())
{
_cacheCurHP = 0;
}
return (float)((double)_cacheCurHP / (double)PropMoudle.MaxHP);
}
return base.HpPercent;
}
}
//锁定血量
public bool LockCurHP
{
get
{
return _isLockHP;
}
set
{
_isLockHP = value;
}
}
#endregion
#region//怪物的效果设置接口 比如:出生的效果,被攻击效果,死亡效果
//接受到被击时的处理
public override void OnBeAttackedResponse(Character attacker, HitEffectInfo hitInfo, SkillHitType hitType, MSG_Fight.HitEffectInfo msgInfo)
{
//判断是否死亡
if (IsDead())
{
if(!string.IsNullOrEmpty(PropMoudle.Cfg.DeadSpeech))
{
AudioPlayer.PlaySpeech(Skin.RootGameObject, PropMoudle.Cfg.DeadSpeech);
}
if (GameCenter.GameSetting.IsEnabled(GameSettingKeyCode.EnablePostEffect) && !_isPlayDeadFeature && PropMoudle.Cfg.DeadFeature != 0)
{
//播放死亡特写
GameCenter.GameSceneSystem.DoTimeScale(0.3f, 3f);
//PostEffectManager.Instance.PlayRadiaBlur(0f, 1f, 0.6f);
_isPlayDeadFeature = true;
var cameraControl = Scene.CameraManager.SceneCameraControl;
if (cameraControl != null && !cameraControl.IsPlayAnim)
{
_isPlayCameraDeadFeature = true;
_cameraFeatureTimer = 0f;
cameraControl.FreeMode = true;
_cameraOriDis = cameraControl.CurDis;
_cameraOriYaw = cameraControl.CurYaw;
_cameraOriPitch = cameraControl.CurPitch;
}
}
}
if (IsXState(EntityStateID.Dead))
return;
if(_useCacaheDamage && _cacheDamage > 0)
{
if(attacker != null)
{
_cacheAtker[attacker.ID] = true;
}
var caCount = _cacheAtker.Count;
if(caCount <= 0)
{
caCount = 0;
}
if (IsDead())
{
_cacheDamage = 0;
_cacheCurHP = 0;
}
else
{
if(CombatUtil.IsMultipleAtk(msgInfo.effect))
{
//直接掉80%
var damageHp = (ulong)(_cacheDamage * 0.8f);
if (damageHp <= 0)
{
damageHp = 1;
}
_cacheDamage -= damageHp;
_cacheCurHP -= damageHp;
}
else
{
var damageHp = _cacheDamage / ((ulong)caCount * 5);
if (damageHp <= 0)
{
damageHp = 1;
}
_cacheDamage -= damageHp;
_cacheCurHP -= damageHp;
}
}
}
//震动效果
var shakeDir = GetFacingDirection();
if (attacker != null)
{
shakeDir = Position - attacker.Position;
}
if(PropMoudle.Cfg.HitShakePower > 0)
{
_shaker.StartShake(shakeDir, PropMoudle.Cfg.HitShakePower / 100f, 0.2f);
}
base.OnBeAttackedResponse(attacker, hitInfo, hitType, msgInfo);
if (PropMoudle.Cfg.MonsterType >= 3 && PropMoudle.Cfg.ArmorIf == 0 && PropMoudle.CurArmor > 0)
{
if (_armorVfx == null)
{
var pos = GetModelCenterPos();
_armorVfx = new FGameObjectVFX(ModelTypeCode.OtherVFX, 29);
_armorVfx.SetPosition(pos);
_armorVfx.IsFinishDestroy = false;
_armorVfx.StopIsDeactive = true;
_armorVfx.Play();
}
else
{
var pos = GetModelCenterPos();
_armorVfx.SetPosition(pos);
_armorVfx.Stop();
_armorVfx.Play();
}
}
if (!GameCenter.GameSetting.IsEnabled(GameSettingKeyCode.TPSkillBlink))
{
var setValue = GameCenter.GameSetting.GetSetting(GameSettingKeyCode.HitBlink);
if (setValue == 2 || (setValue == 1 && attacker.IsLocalPlayer()))
{
//开始闪烁
_blinker.Start(hitInfo.BlinkTime, hitInfo.BlinkPower, hitInfo.BlinkColor, hitInfo.BlinkCurve, Skin);
}
}
//只有主角或者主角宠物攻击的怪物才会显示血条
if (attacker != null && (attacker.IsLocalPlayer() || attacker.IsLocalPet() || attacker.IsLocalFlySword()))
{
if (Scene.Cfg.ShowMonsterHud != 0)
{
ShowHUD(false);
//显示血量
GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_HUD_SHOWMONSTER_HP, this);
}
}
if(attacker.IsLocalPlayer())
{
var lp = attacker as LocalPlayer;
lp.SetCurSelectBoss(this);
}
}
//设置溶解时间
public bool SetDissolvingTime(float time)
{
if (Skin.SkinStatus == FSkinStatusCode.Dead)
{
Skin.SetFloat(FSkinPartCode.Body, ShaderPropertyIDDefine.Timeline, time);
return true;
}
return false;
}
#endregion
#region//初始化,卸载,加载Skin等处理
//加载Skin
protected override FSkinBase OnSetupSkin()
{
IsLoadFinish = false;
FSkinModel skin = GameCenter.LuaSystem.Adaptor.CreateFSkinModel(FSkinTypeCode.Monster);
skin.SetLayer(LayerUtils.Monster);
skin.SetMipmapLevel(0.5f);
skin.SetActiveChangedCallBack(OnActiveChanged);
skin.SetOnSkinPartChangedHandler((x, y) =>
{
if(y == FSkinPartCode.Body)
{
IsLoadFinish = true;
//重新挂载buff特效
GameCenter.BuffSystem.ReAddAllBuffVfx(this);
if(_propMoudleEx.Cfg.PlayerModel != 0)
{
//怪物使用玩家模型,武器始终拿在手上
var body = Skin.GetSkinPart(FSkinPartCode.Body) as FGameObjectBody;
if (body != null && body.BrightWeapon)
{
body.BrightWeapon = true;
}
}
}
});
return skin;
}
//初始化之前
protected override bool OnSetupFSMBefore()
{
ResetDirection();
return base.OnSetupFSMBefore();
}
//安装设置FSM状态机
protected override bool OnSetupFSM()
{
Fsm = new EntityFSM(this);
Fsm.AddState(new Idle());
Fsm.AddState(new MonsterFSM.PathMove());
Fsm.AddState(new MonsterFSM.Dead());
Fsm.AddState(new BeHit());
Fsm.AddState(new BeHitBack());
Fsm.AddState(new BeHitFly());
Fsm.AddState(new BeHitGrab());
Fsm.AddState(new SkillMove());
Fsm.SetDefaultStateId(EntityStateID.Idle);
Fsm.Init(this);
return true;
}
//初始化
protected override bool OnInitializeAfter(EntityInitInfo baseInfo)
{
var initInfo = baseInfo as MonsterInitInfo;
base.OnInitializeAfter(baseInfo);
_shaker = new CharacherShaker(this);
_blinker = new HitBlinker();
SyncInfo(initInfo);
if (Scene.Cfg.ShowMonsterHud != 0)
{
if(!string.IsNullOrEmpty(initInfo.Cfg.Dialog))
{
//没有对话泡泡的时候不在一创建就显示
ShowHUD();
}
if (initInfo.IsBoss && _bornTimer <= 0f)
{
ShowHUD(false);
//显示血量
GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_HUD_SHOWMONSTER_HP, this);
}
}
GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_ON_MONSTER_BORN, this);
return true;
}
//卸载处理
protected override void OnUninitializeBefore()
{
HideHUD();
if (_armorVfx != null)
{
_armorVfx.Destroy();
_armorVfx = null;
}
GameCenter.DropAscriptionSystem.UpdateMonsterDropOwners(ID, null);
base.OnUninitializeBefore();
}
//初始化信息刷新
public void SyncInfo(MonsterInitInfo initInfo)
{
_useCacaheDamage = initInfo.Cfg.UseSmoothDamage != 0;
GameCenter.BuffSystem.ReAddAllBuffVfx(this);
DeadDetail = null;
_propMoudle = _propMoudleEx = new MonsterProperty(this, initInfo.Cfg);
_propMoudleEx.CurHP = (ulong)initInfo.CurHp;
_propMoudleEx.CurArmor = initInfo.CurArmor;
_propMoudleEx.SetBattleProp(AllBattleProp.MaxHP, (long)initInfo.MaxHp);
_propMoudleEx.SetBattleProp(AllBattleProp.AttackSpeed, initInfo.AttackSpeedFinal);
_propMoudleEx.SetBattleProp(AllBattleProp.MoveSpeed, initInfo.MoveSpeedFinal);
_propMoudleEx.SceneCampID = initInfo.Camp;
_cacheCurHP = _propMoudleEx.CurHP;
//Debug.Log(":::::" + _propMoudleEx.CurHP+","+ (long)initInfo.MaxHp);
if (initInfo.Cfg.Level < 0)
{
_propMoudleEx.Level = (uint)GameCenter.GameSceneSystem.GetLocalPlayerLevel();
}
else if(initInfo.Cfg.Level == 0)
{
_propMoudleEx.Level = (uint)GameCenter.LuaSystem.Adaptor.GetCurWorldLevel();
}
else
{
_propMoudleEx.Level = (uint)initInfo.Cfg.Level;
}
InitStartPose(initInfo.X, initInfo.Z, ref initInfo.PosList);
SetDirection2d(initInfo.Dir, false, true);
//设置状态
_stateManager.SetStateData(initInfo.State);
_isRunning = initInfo.IsRunning;
_isPlayBornAnum = initInfo.IsBorn;
IsBoss = initInfo.IsBoss;
if (_propMoudleEx.Cfg.PlayerModel != 0 && !String.IsNullOrEmpty(_propMoudleEx.Cfg.PlayerModelRes))
{
Skin.SkinTypeCode = FSkinTypeCode.Player;
String[] modelsparam = _propMoudleEx.Cfg.PlayerModelRes.Split('_');
int body = 0;
int weaponHead = 0;
int weaponBody = 0;
int weaponVFX = 0;
int cloak = 0;
if (modelsparam.Length > 0)
{
int.TryParse(modelsparam[0], out body);
}
if (modelsparam.Length > 1)
{
int.TryParse(modelsparam[1], out weaponHead);
}
if (modelsparam.Length > 2)
{
int.TryParse(modelsparam[2], out weaponBody);
}
if (modelsparam.Length > 3)
{
int.TryParse(modelsparam[3], out weaponVFX);
}
if (modelsparam.Length > 4)
{
int.TryParse(modelsparam[4], out cloak);
}
Skin.SetSkinPartFromCfgID(FSkinPartCode.Body, body, null, true);
Skin.SetSkinPartFromCfgID(FSkinPartCode.GodWeaponHead, weaponHead);
//Skin.SetSkinPartFromCfgID(FSkinPartCode.GodWeaponBody, weaponBody);
//Skin.SetSkinPartFromCfgID(FSkinPartCode.GodWeaponVfx, weaponVFX);
Skin.SetSkinPartFromCfgID(FSkinPartCode.Wing, cloak);
}
else
{
Skin.SkinTypeCode = FSkinTypeCode.Monster;
Skin.SetSkinPartFromCfgID(FSkinPartCode.Body, initInfo.Cfg.Res);
}
_bornTimer = 0f;
//判断是否出生
if (_isPlayBornAnum)
{
_bornTimer = PropMoudle.Cfg.BrithProtect / 1000f;
if (GameCenter.GameSetting.IsEnabled(GameSettingKeyCode.EnableMonsterGrownEffect))
{
//播放出生特效
if (PropMoudle != null && PropMoudle.Cfg != null && PropMoudle.Cfg.BrithVfx > 0)
{
Skin.PlayVFX(ModelTypeCode.OtherVFX, PropMoudle.Cfg.BrithVfx, SlotNameDefine.Origin, FSkinPartCode.Body, true, 1f,
true, false, ()=>
{
GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_ONMONSTER_BRITHVFX_PLAYED, PropMoudle.CfgID);
});
}
}
PlayAnim(AnimClipNameDefine.Born, AnimationPartType.AllBody, WrapMode.Once);
if(PropMoudle.Cfg.BrithFowardPlayer != 0)
{
var lp = GameCenter.GameSceneSystem.GetLocalPlayer();
if(lp != null)
{
SetDirection2d(lp.Position2d - Position2d, false, false);
}
}
if(!string.IsNullOrEmpty(PropMoudle.Cfg.BirthSpeech))
{
//播放出生音效
AudioPlayer.PlaySpeech(Skin.RootGameObject, PropMoudle.Cfg.BirthSpeech);
}
}
//这里如果是Boss的话,就让动作播放设置为一直播放.
//if (initInfo.IsBoss)
//{
// Skin.CullingType = AnimatorCullingMode.CullCompletely;
//}
BodyScale = PropMoudle.Cfg.SizeScale / 100f;
DropGoldCount = 0;
IsShowModel = GameObjectLimit.IsCanShow(this);
}
#endregion
#region //继承Character ,死亡等处理
public override void OnDead()
{
HideHUD();
base.OnDead();
}
#endregion
#region//是否被选择的处理
//选择
protected override void OnSelect()
{
Skin.SetSkinPart(FSkinPartCode.SelectedVfx, ModelTypeCode.OtherVFX, 920, false, null, null, null, SlotNameDefine.Origin);
//设置选择圈的大小
Skin.GetSkinPart(FSkinPartCode.SelectedVfx).SetLocalScale(new Vector3(PropMoudle.LogicBodyRadius / BodyScale, 1, PropMoudle.LogicBodyRadius / BodyScale));
if (Scene.Cfg.ShowMonsterHud != 0)
{
ShowHUD(false);
//显示血量
GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_HUD_SHOWMONSTER_HP, this);
}
}
//取消选择
protected override void OnDeselect()
{
Skin.RemoveSkinPart(FSkinPartCode.SelectedVfx);
//满血的情况下
if (!IsDead() && HpPercent >= 1.0f && !IsBoss)
{
//隐藏血量
GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_HUD_HIDEMONSTER_HP, this);
}
}
#endregion
#region//心跳处理
//心跳处理
protected override void OnUpdate(float elapsedTime)
{
if(Time.frameCount % 30 == 0)
{
_cacheAtker.Clear();
}
if(_bornTimer > 0)
{
_bornTimer -= elapsedTime;
if(IsBoss && _bornTimer <= 0f)
{
ShowHUD(false);
//显示血量
GameCenter.PushFixEvent(LogicEventDefine.EID_EVENT_HUD_SHOWMONSTER_HP, this);
}
}
//闪烁
_blinker.Update(elapsedTime);
//震动
_shaker.Update(elapsedTime);
if(_isPlayCameraDeadFeature)
{
_cameraFeatureTimer += elapsedTime / Time.timeScale;
var cameraControl = Scene.CameraManager.SceneCameraControl;
if(_cameraFeatureTimer > 4f)
{
_isPlayCameraDeadFeature = false;
cameraControl.FreeMode = false;
}
else
{
if(_cameraFeatureTimer <= 0.5f)
{
cameraControl.CurDis = Mathf.Lerp(_cameraOriDis, 15f, _cameraFeatureTimer / 0.5f);
cameraControl.CurYaw = Mathf.Lerp(_cameraOriYaw, _cameraOriYaw + 20f, _cameraFeatureTimer / 0.5f);
cameraControl.CurPitch = Mathf.Lerp(_cameraOriPitch, 10f, _cameraFeatureTimer / 0.5f);
}
else if(_cameraFeatureTimer <= 3f)
{
}
else
{
cameraControl.CurDis = Mathf.Lerp(15f, _cameraOriDis, (_cameraFeatureTimer - 3f) / 1f);
cameraControl.CurYaw = Mathf.Lerp(_cameraOriYaw + 20f, _cameraOriYaw, (_cameraFeatureTimer - 3f) / 1f);
cameraControl.CurPitch = Mathf.Lerp(10f, _cameraOriPitch, (_cameraFeatureTimer - 3f) / 1f);
}
}
}
base.OnUpdate(elapsedTime);
}
#endregion
#region//重新实现设置方向函数,用以实现某些怪物不能转向
public override void SetDirection(Vector3 direction, bool smooth = true, bool normalized = false)
{
if(PropMoudle.Cfg.IsLockDir != 0)
{
SetEulerAngle(new Vector3(0, PropMoudle.Cfg.LockDir, 0));
}
else
{
base.SetDirection(direction, smooth, normalized);
}
}
#endregion
}
}