using CommonAI.Zone.Instance;
using System;
using XmdsCommon.Message;
using XmdsCommon.Plugin;
using XmdsCommonServer.Plugin.Units;
using XmdsCommonServer.XLS.Data;
using CommonAI.Zone.Formula;
using XmdsCommonServer.Plugin.XmdsSkillTemplate.DamageCalculator;
using CommonAI.Zone;
using System.Collections.Generic;
using CommonLang;
using XmdsCommonServer.Plugin.Scene;
using static CommonAI.XmdsConstConfig;
using XmdsCommonServer.XLS;
using CommonLang.Log;
using static XmdsCommonServer.XLS.XLSRandomMonsterSkillLoader;
using static XmdsCommon.Plugin.GameSkill;
using CommonAI.Zone.Helper;
using CommonAI.Data;
using XmdsCommon.JSGModule.Interface;
namespace XmdsCommonServer.Plugin
{
public class XmdsVirtual_Monster : XmdsVirtual
{
private static Logger logger = LoggerFactory.GetLogger("MonsterData");
///
/// 个性语言.
///
protected string[] mDialogWords = null;//"(#‵′)凸|测试".
///
/// 个性语言概率.
///
protected int mDialogWordRate = 100;
///
/// 死亡个性语言.
///
protected string[] mDeadDialogWords = null;//"(#‵′)凸|测试".
///
/// 死亡个性语言概率.
///
protected int mDeadDialogWordRate = 100;
///
/// 是否为BOSS.(是否受控制技能影响).
///
private bool mIsBoss = false;
///
/// 怪物类型
///
private byte mMonsterType = 0;
private bool mIsLvRepress = false;
///
/// 怪物特殊能力列表.
///
private List mAbilityList = null;
///
/// BOSS遭受攻击伤害信息.
///
private HashMap mSufferDamageInfo = null;
///
/// 是否为共享怪
///
private bool mIsShare = false;
//随机技能类型
private byte skillType = 0;
//绑定攻击者
private InstanceUnit mBindAttakPlayer;
///
/// 滚回去的提速buffid
///
private int backSpeedBuffId = 0;
public bool IsShare
{
get { return mIsShare; }
set { mIsShare = value;}
}
public XmdsVirtual_Monster(InstanceUnit unit) : base(unit)
{
mHateSystem.SetFindHeirs(true);
}
public override string GetPlayerUUID()
{
return mUnit.ID.ToString();
}
public override PKLevel GetCurPKLevel()
{
return base.GetCurPKLevel();
}
//解析字符串里的数字
//特点之一就是不报错,字符串随便传
//特点之二就是字母数学混杂时,取最前面的数字串
//dft,取值失败时的返回
public static int ParseInt(string str, int dft = 0)
{
if (string.IsNullOrEmpty(str))
{
return dft;
}
System.Text.RegularExpressions.Match m = System.Text.RegularExpressions.Regex.Match(str, @"(\d+)");
if (m.Groups.Count >= 2)
{
try
{
return System.Convert.ToInt32(m.Groups[1].Value);
}
catch (System.Exception)
{
return dft;
}
}
return dft;
}
protected override void Init(bool pointLv)
{
if (this.mProp.LoadDataConfig == true)
{
//InitMonsterData(GetCurSceneType(), mUnit.Info.TemplateID, mUnit.Level, this.mUnit.RandomN);
InitMonsterData2(GetCurSceneType(), mUnit.Info.TemplateID, pointLv);
}
else
{
MonsterVisibleDataB2C edata = new MonsterVisibleDataB2C();
edata.SenceType = GetCurSceneType();
edata.MonsterID = mUnit.Info.TemplateID;
edata.DisplayName = mUnit.Name;
edata.AttackType = MonsterVisibleDataB2C.MonsterAttackType.Passive;
edata.Atype = MonsterVisibleDataB2C.MonsterAtype.Monster;
edata.MType = MonsterVisibleDataB2C.MonsterType.MType0;
edata.Qcolor = MonsterVisibleDataB2C.MonsterQcolor.Q0;
edata.hpPlies = (byte)ParseInt(mUnit.Info.UserTag, 1);
mUnit.SetVisibleInfo(edata);
}
//随机名字
if(this.mUnit.Info.IsRandomName)
{
string randomName = XmdsDataMgr.GetInstance().GetRanomName();
mUnit.SetDiaplayerName(randomName);
}
mHateSystem.OnHandleTargetAddEvent += MHateSystem_OnHandleTargetAddEvent;
}
private void MHateSystem_OnHandleTargetAddEvent(CommonAI.Zone.Helper.HateSystem.HateInfo target)
{
if (target.Unit != null)
{
if ((target.Unit.Virtual as XmdsVirtual).IsPlayerUnit())
{
SetCombatState(BattleStatus.PVP);
}
else
{
SetCombatState(BattleStatus.PVE);
}
}
}
public override void SetCombatState(BattleStatus value, byte reason = 0, string pvpTriggerID = "")
{
//怪物强制为PVE状态.
if (value == BattleStatus.PVP)
{
value = BattleStatus.PVE;
}
base.SetCombatState(value, reason);
}
protected override void OnCombatStateChange(BattleStatus status)
{
base.OnCombatStateChange(status);
//单位脱战条件必须是非无限追击怪物.
if (status == BattleStatus.None && this.mUnit.Info.GuardRangeLimit != 0)
{
(mUnit as CommonAI.Zone.Instance.InstanceGuard).backToOrgin();
//changeRunSpeed4back();
CleanDamageInfo();
}
if (status != BattleStatus.None)//进入战斗时触发个性化语句.
{
RandomDialogWords();
}
}
///
/// 怪物回去要提你麻痹的速
///
public void changeRunSpeed4back()
{
if(backSpeedBuffId > 0)
{
RemovePropChangeOperation(backSpeedBuffId);
}
XmdsVirtual.PropChangeOperation pco = this.CreatePropChangeOpertation(null);
pco.Type = XmdsVirtual.UnitAttributeType.MoveSpeed;
pco.Value = 5000;
pco.OpType = XmdsVirtual.PropChangeOperation.OperateType.Percent;
backSpeedBuffId = AddPropChangeOperation(pco);
}
public void onBack2PositionEnd()
{
RemovePropChangeOperation(backSpeedBuffId);
}
public override void OnUnitDead(XmdsVirtual killer)
{
//怪物死亡时,需要计算组队分享人员名单.
var u = mHateSystem.GetHeirs();
if (u != null)
{
mHateSystem.CalAtkAssistantList(mIsShare);
CheckKillGroup((u.Virtual as XmdsVirtual));
}
base.OnUnitDead(killer);
RandomDeadDialogWords();
}
public override int OnHit(XmdsVirtual attacker, AttackSource source)
{
//怪物回程状态不能被攻击.
if (this.mUnit.CurrentState is InstanceUnit.StateBackToPosition)
{
source.OutIsDamage = false;
source.OutClientState = (int)UnitHitEventState.Immunity;
return 0;
}
OnBossHit(attacker, ref source);
int ret = base.OnHit(attacker, source);
if (ret > 0)
{
OnDamageInfoCheck(attacker, ref source, ret);
}
return ret;
}
public override void SyncHeirsInfo(string name, int hpPercent, CommonAI.Data.XmdsUnitPro protype)
{
if (string.IsNullOrEmpty(name))
{
(this.mUnit.VisibleInfo as MonsterVisibleDataB2C).UnitHeirInfo = null;
SendMonsterHeirInfoChangeEventB2C(null);
}
else {
MonsterVisibleDataB2C.HeirInfo info = new MonsterVisibleDataB2C.HeirInfo();
info.Name = name;
info.hpPercent = hpPercent;
info.ProType = protype;
SendMonsterHeirInfoChangeEventB2C(info);
(this.mUnit.VisibleInfo as MonsterVisibleDataB2C).UnitHeirInfo = info;
}
}
private void SendMonsterHeirInfoChangeEventB2C(MonsterVisibleDataB2C.HeirInfo info)
{
MonsterHeirInfoChangeEventB2C evt = new MonsterHeirInfoChangeEventB2C();
evt.UnitHeirInfo = info;
this.mUnit.queueEvent(evt);
}
//怪物判断是否为队友时,直接用force.
public override bool IsTeamMember(InstanceUnit unit)
{
return IsAllies(unit.Virtual as XmdsVirtual);
}
protected override bool JudgeChangeCombatStateChange(BattleStatus status, byte reason)
{
//普通情况下,召唤物未出战斗状态,主人也处于战斗状态.
if (status == BattleStatus.None && reason == 0)
{
if (mSummonList != null && mSummonList.Count > 0)
{
for (int i = 0; i < mSummonList.Count; i++)
{
if (mSummonList[i].CombatState != BattleStatus.None)
{
return false;
}
}
}
}
return base.JudgeChangeCombatStateChange(status, reason);
}
protected override void CombatStateConnect(BattleStatus status, byte reason)
{
if (mSummonList != null && mSummonList.Count > 0)
{
for (int i = 0; i < mSummonList.Count; i++)
{
mSummonList[i].SetCombatState(status, reason);
}
}
}
protected override void Dispose()
{
UnInitBossAbilities();
CleanSummonList();
DisposeDamageInfo();
base.Dispose();
}
public override int GetVirtualTemplateID()
{
MonsterVisibleDataB2C data = (this.mUnit.VisibleInfo as MonsterVisibleDataB2C);
if (data != null)
{
return data.MonsterID;
}
else
{
return base.GetVirtualTemplateID();
}
}
public void DoUnitStateReset()
{
//野外无效.
//if (this.mUnit.GetSceneType() == CommonAI.Data.SceneType.Dungeon ||
// this.mUnit.GetSceneType() == CommonAI.Data.SceneType.GuildDungeon)
//{
// if ((this.mUnit.CurrentState is InstanceUnit.StateFollowAndAttack) || (this.mUnit.CurrentState is InstanceUnit.StateSkill))
// {
// if (CombatState != BattleStatus.None)
// {
// SetCombatState(BattleStatus.None, COMBATSTATE_CHANGE_REASON_DORESET);
// CleanDamageInfo();
// //如果是BOSS直接重新生成单位.
// if (mIsBoss)
// {
// RemoveSelfAndCreate();
// //var pos = (this.mUnit as XmdsInstanceMonster).GetOrginPosition();
// //this.mUnit.setPos(pos.x, pos.y);
// //Reset();
// }
// else
// {
// Reset();
// }
// }
// }
//}
}
private void RemoveSelfAndCreate()
{
var pos = (this.mUnit as XmdsInstanceMonster).GetOrginPosition();
float x = 0;
float y = 0;
if (pos != null)
{
x = pos.X;
y = pos.Y;
}
else
{
x = this.mUnit.X;
y = this.mUnit.Y;
}
var u = this.mUnit.Parent.AddUnit(this.mUnit.Info.ID,
this.mUnit.Name,
this.mUnit.Force,
this.mProp.ServerData.BaseInfo.UnitLv,
x,
y,
this.mUnit.Direction, false);
if (u != null)
{
u.UnitTag = this.mUnit.UnitTag;
}
this.mUnit.removeFromParent();
}
protected override void InitSkillInfo(XmdsUnitData data)
{
this.checkSkillData(data);
//初始化随机技能
if (this.skillType > 0)
{
////如果配置了技能类型,就清除boss被动
//if (mAbilityList != null)
//{
// mAbilityList.Clear();
//}
randomMonsterSkillInfo(this.mUnit.Info.ID, this.skillType);
}
//如果是boss
if(this.IsBoss())
{
this.mProp.ServerData.Skills.UnitSkills.Add(new GameSkill(XmdsComSrvData.BOSS_CARD_SKILLID, XmdsSkillType.active, false));
}
mFinishSkillInit = true;
mSkillHelper.InitSkill(data.Skills, this);
if (mAbilityList != null)
{
InitAbilityList(mAbilityList);
}
}
#region 共享相关计算.
private void CheckKillGroup(XmdsVirtual killer)
{
if (killer == null) { return; }
XmdsVirtual_Player ret = killer.GetPlayerUnit();
if (ret == null) { return; }
List lt = ret.TeamList as List;
//拿到队友列表.
if (lt != null && lt.Count > 0)
{
this.mHateSystem.ClearSharedList();
string uuid = null;
//找到当前场景队友.
for (int i = 0; i < lt.Count; i++)
{
uuid = lt[i];
var unit = this.mUnit.Parent.getPlayerByUUID(uuid);
if (unit != null)
{
float dist = CMath.getDistance(this.mUnit.X, this.mUnit.Y, unit.X, unit.Y);
//单位在范围内.
if (dist <= XmdsConfig.Instance.SHARED_AWARD_MAX_RANGE)
{
this.mHateSystem.AddSharedList(uuid);
}
}
}
}
}
#endregion
#region SummonUnit.
private List mSummonList = new List();
public void AddSummonUnitList(XmdsVirtual unit)
{
mSummonList.Add(unit);
unit.mUnit.OnDead += MUnit_OnDead;
}
private void MUnit_OnDead(CommonAI.Zone.Instance.InstanceUnit unit, CommonAI.Zone.Instance.InstanceUnit attacker)
{
XmdsVirtual v = unit.Virtual as XmdsVirtual;
if (v != null && mSummonList != null)
{
unit.OnDead -= MUnit_OnDead;
mSummonList.Remove(v);
}
}
public int GetSummonUnitListCount()
{
return mSummonList.Count;
}
public XmdsVirtual GetFirstTimesupSummonUnit()
{
if (mSummonList.Count > 0)
{
return mSummonList[0];
}
return null;
}
public List GetSummonUnits()
{
return mSummonList;
}
public void CleanSummonList()
{
if (mSummonList != null && mSummonList.Count > 0)
{
for (int i = 0; i < mSummonList.Count; i++)
{
mSummonList[i].mUnit.OnDead -= MUnit_OnDead;
mSummonList[i].mUnit.kill(null, false);
}
mSummonList.Clear();
}
}
#endregion
#region 单位能力读取加载.
protected void InitMonsterData2(string _sceneType, int templateID, bool pointLv)
{
// 读一行怪物数据
String ss = _sceneType;
if (ss == XLSMonsterDataLoader.DUNGEONHERO || ss == XLSMonsterDataLoader.DUNGEONELITE)
ss = XLSMonsterDataLoader.DUNGEONNORMAL;
MonsterData ma = XmdsDataMgr.GetInstance().GetMonsterData(ss, templateID, null, false);
//赋值特殊属性同步给客户端.
MonsterVisibleDataB2C edata = new MonsterVisibleDataB2C();
if (ma == null)
{
edata.MonsterID = templateID;
edata.DisplayName = string.Format("Cfg Err id={0}", templateID);
edata.AttackType = MonsterVisibleDataB2C.MonsterAttackType.Passive;
edata.Atype = MonsterVisibleDataB2C.MonsterAtype.Monster;
edata.MType = MonsterVisibleDataB2C.MonsterType.MType0;
edata.Qcolor = MonsterVisibleDataB2C.MonsterQcolor.Q0;
edata.hpPlies = (byte)ParseInt(mUnit.Info.UserTag, 1);
mUnit.SetVisibleInfo(edata);
return;
}
XmdsUnitProp ret = (XmdsUnitProp)mProp.ServerData.Prop;
//FateType=-1
if (ma.FateType == UnitFateType.Random)
{
ret.fateType = (UnitFateType)(this.mUnit.RandomN.Next() % (int)UnitFateType.Five + 1);
}
else
{
ret.fateType = ma.FateType;
}
XmdsServerScene scene = this.mUnit.Parent as XmdsServerScene;
SceneType sceneType = this.mUnit.GetSceneType();
int lvl_monster = pointLv ? this.mUnit.Level : ma.Level;
this.skillType = (byte)ma.SkillType;
int floor = 1;
TowerMonsterRatio tmr = null;
if (sceneType == SceneType.HaoYueJing || sceneType == SceneType.PickLotus)//monster level based on xlsconfig
{
//计算当前地图玩家等级:取平均等级
IEnumerable players = scene.AllPlayers;
int level = 0;
foreach (InstancePlayer player in players)
{
level += player.Level;
}
if (scene.AllPlayersCount == 0)
{
// 可能玩家已经都离开场景了,但是地图还在刷新怪物,为了不报错,将怪物等级默认设置为1
lvl_monster = 1;
}
else
{
level = level / scene.AllPlayersCount;
// 执行:怪物等级+=玩家等级
lvl_monster += level;
}
}
else if (sceneType == SceneType.GoblinTower)
{
floor = (int)scene.Data.MonsterAddPropPercentWithFloor;
const int MAX_FLOOR = 80;//GoblinTower max floor
if (floor < 1)
floor = 1;
if (floor > MAX_FLOOR)
floor = MAX_FLOOR;
tmr = XmdsDataMgr.GetInstance().GetTowerMonsterRatio(floor);
lvl_monster = tmr.TowMon_Lv;
}
else if (sceneType == SceneType.AbyssDungeon)
{
floor = (int)scene.Data.MonsterAddPropPercentWithFloor;
const int MAX_FLOOR = 80;//GoblinTower max floor
if (floor < 1)
floor = 1;
if (floor > MAX_FLOOR)
floor = MAX_FLOOR;
tmr = XmdsDataMgr.GetInstance().GetAbyssMonsterRatio(floor);
lvl_monster = tmr.TowMon_Lv;
}
else if (sceneType == SceneType.SourceDungeon)//资源副本怪物等级根据玩家等级上下浮动
{
//lvl_monster += (int)scene.Data.DefaultUnitLevel;
}
else if (sceneType == SceneType.GuildBoss || sceneType == SceneType.SHI_MEN_POS)//仙盟Boss
{
if (scene.Data.DefaultUnitLevel > 1)
{
lvl_monster = (int)scene.Data.DefaultUnitLevel;
}
}
this.mUnit.Level = lvl_monster;
this.mProp.ServerData.BaseInfo.UnitLv = lvl_monster;
//等级转仙阶
this.mProp.ServerData.BaseInfo.StateLv = (byte)(Math.Max(0, (lvl_monster - 70) / 10));
if (ma.Fight_Type == 1)
{
MonsterProp prop = XmdsDataMgr.GetInstance().GetSingleMonsterProp(lvl_monster, ma.Type);
initProp(prop, ma, ret);
}
else if (ma.Fight_Type == 2)
{
MonsterProp prop = XmdsDataMgr.GetInstance().GetMultipleMonsterProp(lvl_monster, ma.Type);
initProp(prop, ma, ret);
}
else if (ma.Fight_Type == 4)
{
lvl_monster = ma.Level;
MonsterProp prop = XmdsDataMgr.GetInstance().GetSingleMonsterProp(lvl_monster, ma.Type);
initProp(prop, ma, ret);
}
else
{
OrigData oData = XmdsDataMgr.GetInstance().GetOrigData(lvl_monster);
UserDefineConfig udc = XmdsDataMgr.GetInstance().GetUserDefineConfig(ma.Type);
initProp2(ma, oData, udc, ret);
}
ret.BaseMaxHP = (int)(ret.BaseMaxHP * XmdsDataMgr.GetInstance().mMonsterDynamicLoader.Mon_Hp_Ratio);
ret.BaseAttack = (int)(ret.BaseAttack * XmdsDataMgr.GetInstance().mMonsterDynamicLoader.Mon_Atk_Ratio);
restoreMa2Ret(ret, ma);
//镇妖塔层数加成
if (sceneType == SceneType.GoblinTower && tmr != null)
{
dynamicCalcBy(ret,
tmr.TowMon_Hp_Ratio,
tmr.TowMon_Atk_Ratio,
tmr.TowMon_Def_Ratio,
tmr.TowMon_Crit_Ratio,
tmr.TowMon_CritDamage_Ratio,
tmr.TowMon_IgnoreDef_Ratio);
}
else if (sceneType == SceneType.AbyssDungeon && tmr != null)
{
float extRate = 1.0F;// (float)Math.Max(1.0f, scene.Data.MonsterAddPropPercentWithFloor);
if (scene.Data.isTeam)
{
AbyssMutilAddition abyssAddition = XmdsDataMgr.GetInstance().GetAbyssMutilAddition();
tmr.TowMon_Atk_Ratio *= abyssAddition.AttackAddition;
tmr.TowMon_Def_Ratio *= abyssAddition.DefenceAddition;
tmr.TowMon_Hp_Ratio *= abyssAddition.HPAddition;
}
dynamicCalcBy(ret,
tmr.TowMon_Hp_Ratio * extRate,
tmr.TowMon_Atk_Ratio * extRate,
tmr.TowMon_Def_Ratio * extRate,
tmr.TowMon_Crit_Ratio * extRate,
tmr.TowMon_CritDamage_Ratio * extRate,
tmr.TowMon_IgnoreDef_Ratio * extRate);
}
if (sceneType == SceneType.GuildBoss)
{
GuildBossRatio gbr = XmdsDataMgr.GetInstance().GetGuildBossRatio(lvl_monster);
if (gbr != null)
{
dynamicCalcBy(ret,
gbr.GBoss_Hp_Ratio,
gbr.GBoss_Atk_Ratio,
gbr.GBoss_Def_Ratio,
gbr.GBoss_Crit_Ratio,
gbr.GBoss_CritDamage_Ratio,
gbr.GBoss_IgnoreDef_Ratio);
}
}
if (_sceneType == XLSMonsterDataLoader.DUNGEONELITE)
{
ma = XmdsDataMgr.GetInstance().GetMonsterData(_sceneType, templateID, null, true);
DungeonMonsterRatio dmr = XmdsDataMgr.GetInstance().mMonsterDynamicLoader.GetDungeonMonsterRatio(ma.Type);
dynamicCalcBy(ret,
dmr.Normal_Hp_Ratio,
dmr.Normal_Atk_Ratio,
dmr.Normal_Def_Ratio,
dmr.Normal_DM_Ratio,
dmr.Normal_DM_Ratio,
dmr.Normal_DM_Ratio);
restoreMa2Ret(ret, ma);
}
if (_sceneType == XLSMonsterDataLoader.DUNGEONHERO)
{
ma = XmdsDataMgr.GetInstance().GetMonsterData(_sceneType, templateID, null, true);
DungeonMonsterRatio dmr = XmdsDataMgr.GetInstance().mMonsterDynamicLoader.GetDungeonMonsterRatio(ma.Type);
dynamicCalcBy(ret,
dmr.Hard_Hp_Ratio,
dmr.Hard_Atk_Ratio,
dmr.Hard_Def_Ratio,
dmr.Hard_DM_Ratio,
dmr.Hard_DM_Ratio,
dmr.Hard_DM_Ratio);
restoreMa2Ret(ret, ma);
}
ret.HP = ret.BaseMaxHP;
XmdsInstanceMonster unit = this.mUnit as XmdsInstanceMonster;
if (unit != null)
{
unit.MonsterID = ma.ID;
//警戒范围控制 :是否主动攻击.0否,1是.
if (ma.isAttack == 0)
{
this.mUnit.Info.GuardRange = 0;
this.mUnit.Info.GuardRangeGroup = 0;
}
}
edata.SenceType = GetCurSceneType();
edata.MonsterID = ma.ID;
edata.DisplayName = ma.Name;
edata.Title = ma.Title;
edata.Qcolor = (MonsterVisibleDataB2C.MonsterQcolor)ma.Qcolor;
edata.AttackType = (MonsterVisibleDataB2C.MonsterAttackType)ma.isAttack;
edata.Atype = (MonsterVisibleDataB2C.MonsterAtype)ma.Atype;
edata.MType = (MonsterVisibleDataB2C.MonsterType)ma.Type;
edata.hpPlies = (byte)ParseInt(mUnit.Info.UserTag, 1);
this.mProp.ServerData.BaseInfo.name = ma.Name;
//设置个性语言.
if (!string.IsNullOrEmpty(ma.DialogWords))
{
mDialogWords = ma.DialogWords.Split('|');
mDialogWordRate = ma.DialogChance;
}
//设置死亡个性语言.
if (!string.IsNullOrEmpty(ma.DeadDialogWords))
{
mDeadDialogWords = ma.DeadDialogWords.Split('|');
mDeadDialogWordRate = ma.DeadDialogChance;
}
mIsShare = ma.ShareType == 1;
this.mMonsterType = ma.Type;
this.mIsLvRepress = (ma.LvRepress == 1) && (this.mMonsterType == (byte)MonsterVisibleDataB2C.MonsterType.MType6);
//是否为boss.
if (ma.Type >= (byte)MonsterVisibleDataB2C.MonsterType.MType4)
{
InitBossAbilities();
}
//BOSS特殊能力.
if (ma.AbilityList != null && mProp != null)
{
//之后会初始化特殊能力技能.
mAbilityList = new List(ma.AbilityList);
}
// 攻速初始化
if (ret.AttackSpeed <= 0)
{
ret.AttackSpeed = GlobalData.DEFAULT_ATTACK_SPEED;
}
//定力值
ret.ShieldValue = ma.MPValue;
mUnit.SetVisibleInfo(edata);
//printMonsterData(ret, templateID);
if (ret.MaxHP <= 0 || ret.MaxAttack <= 0 || ret.Defence <= 0)
{
log.Error("怪物属性错误:" + this.mUnit.Parent.GetSceneID() + ", " + this.mUnit.Info.ID + ", 生命:" + ret.MaxHP +
", 攻击:" + ret.MaxAttack + ", 防御:" + ret.Defence);
}
else if(this.IsBoss() || ret.MaxHP > 500000 || ret.MaxAttack > 10000)
{
log.Debug("怪属性:" + this.mUnit.Parent.GetSceneID() + ", ID: " + templateID + ", " + this.mUnit.Parent.UUID + ", UID: " + this.mUnit.ID + ", 等级: " + lvl_monster
+ ", FT:" + ma.Fight_Type + ",(攻-" + ret.BaseAttack + ", 防-" + ret.BaseDefence + ", 血-" + ret.BaseMaxHP + ", 爆-" + ret.CritRate
+ ", 爆伤-" + ret.CritDamage + ", 穿透-" + ret.IgnoreDefensePer + ")");
}
}
private void randomMonsterSkillInfo(int monsterId, int skillType)
{
MonsterSkills skillInfo = XmdsDataMgr.GetInstance().GetMonsterSkillInfo(monsterId);
if (skillInfo == null)
{
// 指定的怪物概率读不到,就去读默认的技能概率
skillInfo = XmdsDataMgr.GetInstance().GetMonsterSkillInfo();
if(skillInfo == null)
{
return;
}
}
if(this.mProp.ServerData.Skills == null)
{
this.mProp.ServerData.Skills = new XmdsUnitSkillInfo();
}
//else
//{
// this.mProp.ServerData.Skills.UnitSkills.Clear();
//}
if ((skillType & (int)MonsterRandomSkillType.OnlyActive) > 0)
{
//随机找一个技能
if (this.mUnit.RandomN.Next(10000) < skillInfo.Skill1Probability)
{
XmdsSkillData activeSkill = XmdsDataMgr.GetInstance().GetBossRandomActiveSkill(this.mUnit.RandomN);
//初始化主动技能
if (activeSkill != null)
{
this.mProp.ServerData.Skills.UnitSkills.Add(new GameSkill(activeSkill.SkillID, XmdsSkillType.active));
//log.Info("怪物:" + monsterId + ", 随机主动技能: " + activeSkill.SkillID);
}
}
}
if ((skillType & (int)MonsterRandomSkillType.OnlyPassive) > 0)
{
int[] nArray = { skillInfo.Skill2Probability, skillInfo.Skill3Probability, skillInfo.Skill4Probability };
XmdsSkillData[] passiveSkills = new XmdsSkillData[3];
int passiveIndex = 0;
for (int i = 0; i < nArray.Length; i++)
{
if (nArray[i] > 0 && this.mUnit.RandomN.Next(10000) < nArray[i] && (passiveSkills[passiveIndex] =
XmdsDataMgr.GetInstance().GetBossRandomPassiveSkill(this.mUnit.RandomN, passiveSkills)) != null)
{
passiveIndex++;
}
}
//初始化被动技能
for (int i = 0; i < passiveIndex; i++)
{
this.mProp.ServerData.Skills.UnitSkills.Add(new GameSkill(passiveSkills[i].SkillID, XmdsSkillType.passive));
//log.Info("怪物:" + monsterId + ", 随机被动技能: " + passiveSkills[i].SkillID);
}
}
}
///
/// 随机发送个性语句.
///
protected void RandomDialogWords()
{
if (mDialogWords != null && mDialogWords.Length > 0 && mDialogWordRate > 0)
{
int v = this.mUnit.RandomN.Next(0, 100);
//随机触发概率.
if (v <= mDialogWordRate)
{
//随机语句.
v = this.mUnit.RandomN.Next(0, mDialogWords.Length);
SendBubbleTipsEventB2C(mDialogWords[v]);
}
}
}
///
/// 随机发送死亡个性语句.
///
protected void RandomDeadDialogWords()
{
if (mDeadDialogWords != null && mDeadDialogWords.Length > 0 && mDeadDialogWordRate > 0)
{
int v = this.mUnit.RandomN.Next(0, 100);
//随机触发概率.
if (v <= mDeadDialogWordRate)
{
//随机语句.
v = this.mUnit.RandomN.Next(0, mDeadDialogWords.Length);
SendBubbleTipsEventB2C(mDeadDialogWords[v]);
}
}
}
///
/// 初始化单位特殊能力(AI+技能).
///
///
private void InitAbilityList(List list)
{
GameSkill gs = null;
List mlist = new List();
for (int i = 0; i < list.Count; i++)
{
gs = new GameSkill();
gs.SkillID = list[i];
gs.SkillType = XmdsSkillType.passive;
mlist.Add(gs);
}
this.SkillHelper.AddSkill(mlist);
}
public override InstanceUnit GetAtkTarget(InstanceUnit target)
{
if(mBindAttakPlayer != null)
{
if (mBindAttakPlayer.IsActive)
{
return mBindAttakPlayer;
}
// 绑定目标不存在,自杀
this.mUnit.kill();
}
else
{
string bindAttackPlayerId = this.mUnit.GetAttackPlayer();
if (bindAttackPlayerId != null)
{
mBindAttakPlayer = this.mUnit.Parent.getPlayerByUUID(bindAttackPlayerId);
if(mBindAttakPlayer == null)
{
log.Warn("GetAtkTarget有攻击目标玩家找不到:" + this.mUnit.Info.ID + ", " + mBindAttakPlayer);
this.mUnit.BindAttackPlayer(null);
this.mUnit.kill();
}
else
{
return mBindAttakPlayer;
}
}
}
return base.GetAtkTarget(target);
}
#endregion
#region BOSS能力.
private void InitBossAbilities()
{
mIsBoss = true;
GameSkill gs = new GameSkill();
gs.SkillID = 0;
this.RegistTryAddBuffEvent(OnTryAddBuffEvent, gs);
}
private void UnInitBossAbilities()
{
if (mIsBoss)
{
}
}
private bool OnTryAddBuffEvent(ref BuffTemplate buff, XmdsVirtual attacker, XmdsVirtual hitter, GameSkill skill)
{
//检索所有能力,如果为控制类,则不生效.
if (!buff.forceAdd && buff.IsHarmful && XmdsInstanceUtils.IsControlBuff_Monster(buff))
{
return false;
}
return true;
}
private void OnBossHit(XmdsVirtual attacker, ref AttackSource source)
{
if (mIsBoss)
{
if (source.OutIsDamage == true && this.mUnit.CurrentState is InstanceUnit.StateSkill)
{
this.mUnit.SetStunTimeMS(0);
}
source.OutIsDamage = false;
}
}
private void OnDamageInfoCheck(XmdsVirtual attacker, ref AttackSource source, int damage)
{
if (mIsBoss)
{
var player = attacker.GetPlayerUnit();
AddDamageInfo(player, damage);
}
}
private void AddDamageInfo(XmdsVirtual_Player attacker, int damage)
{
//保证伤害有效性.
if (attacker == null || attacker.mUnit.IsActive == false)
{
return;
}
if (mSufferDamageInfo == null)
{
mSufferDamageInfo = new HashMap();
}
PlayerDamageInfo info = null;
string uuid = attacker.GetPlayerUUID();
if (string.IsNullOrEmpty(uuid) == false)
{
if (mSufferDamageInfo.TryGetValue(uuid, out info))
{
info.Damage += damage;
info.PlayerInfo = attacker.mProp.ServerData.BaseInfo;
}
else
{
info = new PlayerDamageInfo();
info.Damage += damage;
info.PlayerInfo = attacker.mProp.ServerData.BaseInfo;
info.PlayerUUID = uuid;
mSufferDamageInfo.Add(uuid, info);
}
}
}
private void CleanDamageInfo()
{
if (mSufferDamageInfo != null)
{
mSufferDamageInfo.Clear();
}
}
private void DisposeDamageInfo()
{
CleanDamageInfo();
}
///
/// 获取怪物单位伤害排名表.
///
///
public HashMap GetSufferDamage()
{
return mSufferDamageInfo;
}
public override int GetMaType()
{
return this.mMonsterType;
}
public override bool IsLvRepress()
{
return this.mIsLvRepress;
}
public override bool IsBoss()
{
return this.mIsBoss;
}
#endregion
}
}