/// <summary> /// 为target添加技能效果. /// skillEffectResID为skilleffect.txt的资源ID. /// </summary> public static ErrorCode AddSkillEffectByResource(AttackerAttr attackerAttr, BattleUnit target, uint skillEffectResID) { if (skillEffectResID == uint.MaxValue) { return(ErrorCode.Succeeded); } SkillEffectTableItem effectRes = DataManager.SkillEffectTable[skillEffectResID] as SkillEffectTableItem; if (effectRes == null) { SkillUtilities.ResourceNotFound("skilleffect", skillEffectResID); return(ErrorCode.ConfigError); } System.Type T = effectRes.GetType(); for (uint i = 0; i < SkillEffectTableItem.SkillEffectCount; ++i) { SkillEffectItem item = effectRes.items[i]; if (item.effectType == SkillEffectType.Invalid || item.effectID == uint.MaxValue) { break; } ErrorHandler.Parse( target.AddSkillEffect(attackerAttr, item.effectType, item.effectID), "in AddSkillEffectByResource" ); } return(ErrorCode.Succeeded); }
public override void Explode() { ErrorHandler.Parse( SkillDetails.CreateCreationAround(mBullet.FirerAttr, mBullet.CreationOnArrive, mBullet.GetPosition(), mBullet.GetDirection()), "failed to create creature on bullet arrived" ); // 爆炸特效, 仅在子弹到达终点时播放, 即, 子弹没有命中足够的人. if (mBullet.CurrentHittedCount < mBullet.MaxHitCount) { SkillClientBehaviour.AddSceneEffect(mBullet.ExplodeEffect, mBullet.GetPosition(), mBullet.GetDirection()); } // 用碰撞来模拟爆炸, 从而使得技能效果的方向沿着子弹的飞行方向. if (mBullet.TargetSelectionOnArrive != uint.MaxValue && mBullet.SkillEffectOnArrive != uint.MaxValue) { TargetSelectionTableItem targetSel = DataManager.TargetSelectionTable[mBullet.TargetSelectionOnArrive] as TargetSelectionTableItem; ArrayList targets = SkillUtilities.SelectTargets(mBullet.FirerAttr, mBullet.GetPosition(), mBullet.GetDirection(), targetSel); AttackerAttr other = mBullet.FirerAttr; other.SetEffectStartLocation(mBullet.GetPosition(), mBullet.GetDirection()); foreach (BattleUnit t in targets) { SkillDetails.AddSkillEffectByResource(other, t, mBullet.SkillEffectOnArrive); } } }
/// <summary> /// 以目标选择的对象(而不是资源ID)作为参数, 外界可以通过直接构造该对象, 而非从数据表读取, 从而调用该方法. /// </summary> public static ErrorCode SelectTargetAndAddSkillEffect( AttackerAttr attackerAttr, Vector3 centerPosition, float direction, TargetSelectionTableItem targetSelectionRes, uint skillEffectResID, SkillUtilities.FilterTarget filter = null ) { ArrayList targets = SkillUtilities.SelectTargets(attackerAttr, centerPosition, direction, targetSelectionRes); if (filter != null) { SkillUtilities.FilterTargetsBy(targets, filter, null); } foreach (BattleUnit t in targets) { // 设置效果的起始点. attackerAttr.SetEffectStartLocation(centerPosition, Utility.Vector3ToRadian(t.GetPosition() - attackerAttr.EffectStartPosition, direction) ); ErrorHandler.Parse( AddSkillEffectByResource(attackerAttr, t, skillEffectResID), "failed to add skill effect with SelectTargetAndAddSkillEffect" ); } return(ErrorCode.Succeeded); }
public BattleUnitSkill(uint resID) { skillRes = DataManager.SkillCommonTable[resID] as SkillCommonTableItem; if (skillRes == null) { SkillUtilities.ResourceNotFound("skillcommon", resID); } }
public SkillImpactInitParam(BattleUnit owner, AttackerAttr attr, uint impactResID) : base(owner, attr) { impactResource = DataManager.ImpactTable[impactResID] as SkillImpactTableItem; if (impactResource == null) { SkillUtilities.ResourceNotFound("impact", impactResID); } }
protected override void takeAction(SkillEffect effect) { if (effect.IsAwake) { mStillRunning.Add(SkillUtilities.MakePair(effect.Type, effect.ResID)); } effect.Stop(StopReason); }
public SkillBuffInitParam(BattleUnit owner, AttackerAttr attr, uint buffResID) : base(owner, attr) { buffResource = DataManager.BuffTable[buffResID] as SkillBuffTableItem; if (buffResource == null) { SkillUtilities.ResourceNotFound("buff", buffResID); } }
/// <summary> /// <para>向targetPosition使用技能.</para> /// 如果targetPosition为zero, 那么会根据技能索敌等情况, 自动确定目标点. /// </summary> public ErrorCode UseSkill(int resID, Vector3 targetPosition) { if (mSkillContainer == null) { return(ErrorCode.InvalidParam); } if (mScene == null || mScene.isSafeScene()) { return(ErrorCode.NotBattleScene); } BattleUnitSkill skill = mSkillContainer.GetSkill(resID); if (skill == null) { return(ErrorCode.InvalidParam); } if (skill.IsRegularAttack) { // 使用武器技能时, 检查随机事件, 从而确定是否需要改变武器技能的ID. StartRegularSkillEventArg argument = new StartRegularSkillEventArg((uint)resID); ApplyRandEvent(null, RandEventTriggerType.OnStartRegularSkill, argument); if (resID != (int)argument.SkillResID && (skill = mSkillContainer.GetSkill((int)argument.SkillResID)) == null) { return(ErrorCode.InvalidParam); } } // 检查技能基本信息. ErrorCode err = SkillUtilities.CheckSkillGeneralInfo(this, skill); if (err != ErrorCode.Succeeded) { ErrorHandler.Parse(err, "failed to CheckSkillGeneralInfo"); return(err); } // 检查技能使用者的当前技能状态. if ((err = SkillUtilities.CheckUserSkillUsingState(mActionCenter, skill)) != ErrorCode.Succeeded) { ErrorHandler.Parse(err, "failed to CheckUserSkillUsingState"); return(err); } // 无效的目标点, 重新确定目标点. if (targetPosition == Vector3.zero && (!skill.skillRes.autoAim || (targetPosition = GetAimTargetPos()) == Vector3.zero)) { targetPosition = Utility.MoveVector3Towards(GetPosition(), GetDirection(), 10f); } return(StartSkill(skill, targetPosition)); }
public override bool Init(ObjectInitParam param) { if (!base.Init(param)) { return(false); } mBulletParam = (BulletInitParam)param; if ((mBulletResource = DataManager.BulletTable[mBulletParam.resID] as BulletTableItem) == null) { SkillUtilities.ResourceNotFound("bullet", mBulletParam.resID); return(false); } mCreateDelay = mBulletParam.createDelay; mFirerAttr = mBulletParam.firerAttr; FlySpeed = mBulletResource.flySpeed; StartPosition = mBulletParam.startPosition; TargetPosition = mBulletParam.targetPosition; Vector3 dir3d = TargetPosition - StartPosition; dir3d.y = 0; if (dir3d == Vector3.zero) { // 起始点与终点位置重叠, 取开火者当前朝向. BattleUnit firer = mFirerAttr.CheckedAttackerObject(); float alternative = (firer != null) ? firer.GetDirection() : mFirerAttr.AttackerDirection; dir3d = Utility.RadianToVector3(alternative); } FlyDirection = Quaternion.LookRotation(dir3d); SetRotation(FlyDirection); AccelerateDelay = mBulletResource.accelerateDelay; mFlyTargetSelection = new TargetSelectionTableItem() { resID = -1, desc = "bullet hit", leagueSel = mBulletResource.leagueSelection, //maxTargetCount = mBulletResource.flyThroughCount - (uint)mHitted.Count, shape = ShapeType.ShapeType_Rect, RectLength = mBulletResource.radiusOnCollide * 2 }; SetPosition(StartPosition); return(true); }
/// <summary> /// 当triggerType指定的事件发生时, 检查randEventContainer列表, 触发随机事件. /// </summary> /// <param name="theOther">触发事件的单位.</param> /// <param name="eventOwner">为随机事件的拥有者.</param> /// <remarks>randevent的技能效果不由任何技能发起(只可以得知该随机事件是如何被注册的)</remarks> public static void ApplyRandEvent( BattleUnit theOther, BattleUnit eventOwner, BattleUnitRandEventContainer randEventContainer, RandEventTriggerType triggerType, RandEventArg triggerArg ) { List <uint> buffNeed2Remove = new List <uint>(); List <BattleUnitRandEvent> typedContainer = randEventContainer[triggerType]; //LinkedListNode<BattleUnitRandEvent> currentNode = typedContainer.First; // SkillScript可能产生新的randevent加入容器中, 导致容器改变, 因此不能通过foreach遍历. // 获取当前指定类型的容器中的元素个数, 只遍历当前的元素(新的randevent通过AddLast加入到容器中, 因此不会被遍历到). for (int i = typedContainer.Count - 1; i >= 0; --i) { BattleUnitRandEvent randEvent = typedContainer[i]; SkillRandEventTableItem randEventRes = randEvent.randEventResource; // 检查CD. if (randEvent.cdMilliseconds != 0) { continue; } // 检查概率. if (!SkillUtilities.Random100(randEventRes.probability)) { continue; } SkillClientBehaviour.AddEffect2Object(eventOwner, randEventRes._3DEffectID, randEventRes._3DEffectBindpoint); if (randEvent.mScript != null && !randEvent.mScript.RunScript(triggerArg)) { buffNeed2Remove.Add((uint)randEvent.fromBuffRes.resID); } randEvent.cdMilliseconds = randEventRes.cdMilliseconds; } // for (int count = typedContainer.Count; count != 0; --count, currentNode = currentNode.Next) // { // // } for (int i = 0; i < buffNeed2Remove.Count; ++i) { eventOwner.RemoveSkillBuffByResID(buffNeed2Remove[i]); } /* foreach (uint id in buffNeed2Remove)*/ }
/// <summary> /// 给当前单位添加技能效果. /// </summary> /// <param name="attackerAttr">为this添加技能效果的单位的属性</param> /// <param name="type">效果类型</param> /// <param name="resID">效果ID</param> /// <returns></returns> public ErrorCode AddSkillEffect(AttackerAttr attackerAttr, SkillEffectType type, uint resID) { // 是否死亡. if (IsDead()) { return(ErrorCode.TargetIsDead); } // 由单位的本身类型, 决定的是否免疫给类型的技能效果. if (SkillEffectImmunity(type)) { return(ErrorCode.AddEffectFailedSkillEffectImmunity); } if (SkillUtilities.IsHarmfulEffect(type, resID) && IsInviolable()) { return(ErrorCode.AddEffectFailedSkillEffectImmunity); } ErrorCode err = ErrorCode.ConfigError; switch (type) { case SkillEffectType.Spasticity: #region Pending err = SkillDetails.StartSpasticity(mActionCenter, attackerAttr, resID, ref mSpasticityCd); #endregion Pending break; case SkillEffectType.Displacement: err = SkillDetails.StartDisplace(mActionCenter, attackerAttr, resID); break; case SkillEffectType.Buff: case SkillEffectType.Impact: err = SkillDetails.StartSkillEffect(attackerAttr, mSkillEffectManager, type, resID); break; default: break; } if (err == ErrorCode.Succeeded && type == SkillEffectType.Buff) { onSkillBuffAdded((uint)resID); } return(err); }
public ErrorCode CheckSkillCost(int skillID) { if (mSkillContainer == null) { return(ErrorCode.InvalidParam); } BattleUnitSkill skill = mSkillContainer.GetSkill(skillID); if (skill == null) { return(ErrorCode.InvalidParam); } return(SkillUtilities.CheckCost(this, skill)); }
/// <summary> /// 从graphCenter, 沿dirRadian方向, 通过targetSel选择目标, 并给选择到的目标添加skillEffectID标识的技能效果. /// </summary> /// <returns>命中目标个数</returns> private uint collideAt(Vector3 graphCenter, float dirRadian, TargetSelectionTableItem targetSel, uint skillEffectID) { ArrayList targets = SkillUtilities.SelectTargets(mFirerAttr, graphCenter, dirRadian, targetSel); SkillUtilities.FilterTargetsBy(targets, checkHitObject); AttackerAttr other = mFirerAttr; other.SetEffectStartLocation(graphCenter, dirRadian); foreach (BattleUnit t in targets) { SkillDetails.AddSkillEffectByResource(other, t, skillEffectID); } return((uint)targets.Count); }
protected override ErrorCode doStart(SkillEffectInitParam param) { // 如果单位免疫控制, 且该buff为控制类buff, 那么, 该buff不能被添加, // 无论该buff有什么其它的功能. if (!mOwner.CanBeStuned() && mBuffRes.IsStunBuff) { return(ErrorCode.AddEffectFailedSkillEffectImmunity); } if (mBuffRes.dotEffectTimeInterval != uint.MaxValue) { mTaskManager = new SkillUtilities.TaskManager(onTaskFinished); } mProperties = SkillUtilities.ParseProperties(mBuffRes.properties); mSkillTransform = SkillUtilities.ParseSkillTransform(mBuffRes.skillTransform); return(base.doStart(param)); }
/// <summary> /// <para>解析属性.</para> /// 多组属性之间, 用'|'分割. 属性以及操作用'+'或者'-'分割, 分别表示该属性增加或者减少指定值. /// </summary> public static List <Pair <int, int> > ParseProperties(string properties) { if (string.IsNullOrEmpty(properties)) { return(null); } List <Pair <int, int> > result = new List <Pair <int, int> >(); string[] group = properties.Split('|'); foreach (string p in group) { int sep = p.IndexOfAny(new char[] { '+', '-' }); int propID = System.Convert.ToInt32(p.Substring(0, sep)); int addValue = System.Convert.ToInt32(p.Substring(sep)); result.Add(SkillUtilities.MakePair(propID, addValue)); } return(result); }
/// <summary> /// 产生技能效果, 被task回调. /// </summary> private void skillTakeEffect(object obj) { // 将目标点缩放到最大距离和最小距离之间. Vector3 targetPosition = SkillUtilities.RoundTargetPosition(mSkillUsing.skillRes.minRange, mSkillUsing.skillRes.maxRange, mOwner.GetPosition(), SkillTargetPosition); uint skillId = dbgSkillResId; ErrorHandler.Parse( SkillDetails.SkillTakeEffect(mOwner, mSkillUsing.skillRes, targetPosition) ); if (!IsRunning) { ErrorHandler.Parse(ErrorCode.ConfigError, "技能" + skillId + "被自身所带效果异常终止!"); } else if (FirstUseState) { SkillDetails.OnSkillEffected(mOwner, mSkillUsing); } }
/// <summary> /// 根据公式, 计算并返回实际伤害(正值). /// </summary> /// <param name="critical">是否为暴击伤害</param> /// <returns></returns> private int computeDamageByFormula(out bool critical) { critical = false; LevelCommonPropertiesItem levelProperties = DataManager.LevelCommonPropertiesTable[mAttackerAttr.AttackerLevel] as LevelCommonPropertiesItem; if (levelProperties == null) { SkillUtilities.ResourceNotFound("levelcommonproperties", mAttackerAttr.AttackerLevel); return(0); } // 等级暴击系数. float levelCriticalRate = (float)levelProperties.levelCriticalRate; float levelDefanceRate = (float)levelProperties.levelDefanceRate; if (Utility.isZero(levelCriticalRate)) { ErrorHandler.Parse(ErrorCode.ConfigError, "等级暴击系数不可为0!"); levelCriticalRate = 1; } // 暴击几率 = 暴击等级 / (等级暴击系数 + 暴击等级). float criticalProp = 100f * mAttackerAttr.CriticalLevel / (mAttackerAttr.CriticalLevel + levelCriticalRate); // 是否暴击. critical = SkillUtilities.Random100((uint)criticalProp); // 免伤百分比 = 防守方真实防护 / (防守方真实防护 + 等级防护系数). float defance = (float)mOwner.GetPropertyValue((int)PropertyTypeEnum.PropertyTypeDefance); float defancePercent = defance / (defance + levelDefanceRate); // 攻击者的实际伤害, 如果暴击, 为基本伤害的CriticalDamageScale倍. float criticalDamageScale = (critical ? GameConfig.CriticalDamageScale : 1f); float realDamage = criticalDamageScale * mAttackerAttr.AttackerDamage * mImpactRes.damageAttrPercent / 100f; // 最少造成1点血量伤害. return((int)Mathf.Max(realDamage * (1f - defancePercent), 1f)); }
/// <summary> /// 添加材质特效和声音. /// </summary> public ErrorCode AddMaterialBehaviour(MaterialBehaviourDef name, ImpactDamageType impactDamageType, float dir) { // 无效的伤害类型. if (impactDamageType >= ImpactDamageType.Count) { return(ErrorCode.Succeeded); } if (name != MaterialBehaviourDef.OnMaterialDie && IsDead()) { return(ErrorCode.TargetIsDead); } if (name == MaterialBehaviourDef.OnMaterialDie) { uint materialID = GetMaterialResourceID(); if (materialID == uint.MaxValue) { ErrorHandler.Parse(ErrorCode.ConfigError, dbgGetIdentifier() + " 没有材质!"); return(ErrorCode.ConfigError); } MaterialTableItem material = DataManager.MaterialTable[materialID] as MaterialTableItem; if (material == null) { SkillUtilities.ResourceNotFound("material", materialID); return(ErrorCode.ConfigError); } if (material.deathEffectWaitTime > 0) { Scene.GetDelayBehaviourManager().AddDelayBehaviour(this, name, impactDamageType, dir, material.deathEffectWaitTime); return(ErrorCode.Succeeded); } } return(SkillDetails.AddMaterialBehaviour(this, mHitMaterialEffectCdContainer, name, impactDamageType, dir)); }
/// <summary> /// 选择目标, 并添加效果. /// </summary> /// <param name="attackerAttr">攻击者属性</param> /// <param name="centerPosition">在该位置进行目标选择</param> /// <param name= "direction">在中心位置时的朝向(如果形状是圆, 那么该参数没有作用)</param> /// <param name="targetSelection">目标选择参数</param> /// <param name="skillCommonResID">最初技能ID</param> /// <param name="skillEffectResID">为选择到的目标添加效果</param> /// <returns>对多少人添加了效果</returns> /// <remarks> /// 通过该方法产生的技能效果, 起始点和起始位置的方向会改变为技能选择中心点以及该点处的方向, /// 对之后的位移发起位置, 特效方向等产生影响. /// </remarks> public static ErrorCode SelectTargetAndAddSkillEffect( AttackerAttr attackerAttr, Vector3 centerPosition, float direction, uint targetSelection, uint skillEffectResID, SkillUtilities.FilterTarget filter = null ) { if (targetSelection == uint.MaxValue && skillEffectResID == uint.MaxValue) { return(ErrorCode.Succeeded); } TargetSelectionTableItem targetSelectionRes = DataManager.TargetSelectionTable[targetSelection] as TargetSelectionTableItem; if (targetSelectionRes == null) { SkillUtilities.ResourceNotFound("targetselection", targetSelection); return(ErrorCode.ConfigError); } return(SelectTargetAndAddSkillEffect(attackerAttr, centerPosition, direction, targetSelectionRes, skillEffectResID, filter)); }
/// <summary> /// 添加材质特效和声音. /// </summary> /// <param name="owner">被添加特效和声音的单位</param> /// <param name="cdContainer">cd的容器, 该函数会检查并设置CD.</param> /// <param name="name">添加的类型(被击, 死亡等)</param> /// <param name="impactDamageType">impact的伤害类型</param> public static ErrorCode AddMaterialBehaviour(BattleUnit owner, HitMaterialEffectCdContainer cdContainer, MaterialBehaviourDef name, ImpactDamageType impactDamageType, float dir ) { // 无效的伤害类型. if (impactDamageType >= ImpactDamageType.Count) { return(ErrorCode.Succeeded); } // CD中, 只有被击的材质特效有CD, 死亡材质特效没有CD. if (name == MaterialBehaviourDef.OnMaterialBeHit && cdContainer.IsCoolingDown(impactDamageType)) { return(ErrorCode.CoolingDown); } uint materialID = owner.GetMaterialResourceID(); if (materialID == uint.MaxValue) { ErrorHandler.Parse(ErrorCode.ConfigError, owner.dbgGetIdentifier() + " 没有材质!"); return(ErrorCode.ConfigError); } MaterialTableItem material = DataManager.MaterialTable[materialID] as MaterialTableItem; if (material == null) { SkillUtilities.ResourceNotFound("material", materialID); return(ErrorCode.ConfigError); } if (name == MaterialBehaviourDef.OnMaterialBeHit) { cdContainer.StartCd(impactDamageType); } MaterialItem item = material.items[(int)impactDamageType]; uint effectID = uint.MaxValue; uint sound = uint.MaxValue; string bindpoint = ""; switch (name) { case MaterialBehaviourDef.OnMaterialBeHit: effectID = item.hitEffect; bindpoint = material.hitEffectBindpoint; sound = item.sound; // 被击材质特效在被击者身上播放. /* SkillClientBehaviour.AddEffect2Object(owner, effectID, bindpoint, dir);*/ if (string.IsNullOrEmpty(bindpoint)) { SkillClientBehaviour.AddSceneEffect(effectID, owner.GetPosition(), dir); } else { SkillClientBehaviour.AddEffect2Object(owner, effectID, bindpoint, dir); } break; case MaterialBehaviourDef.OnMaterialDie: effectID = item.deathEffect; bindpoint = material.deathEffectBindpoint; if (string.IsNullOrEmpty(bindpoint)) { SkillClientBehaviour.AddSceneEffect(effectID, owner.GetPosition(), dir); } else { SkillClientBehaviour.AddEffect2Object(owner, effectID, bindpoint, dir); } break; default: break; } if (sound != uint.MaxValue) { SkillClientBehaviour.PlaySound(sound); } return(ErrorCode.Succeeded); }
private bool checkBuff() { DataType myName = DataType.DATA_SKILL_BUFF; IDictionaryEnumerator itr = DataManager.BuffTable.GetEnumerator(); while (itr.MoveNext()) { SkillBuffTableItem item = itr.Value as SkillBuffTableItem; if (!checkParam(item.removeCondition < BuffRemoveCondition.Count, myName, item.resID, "buff移除条件")) { return(false); } if (!checkParam(item.stackCountMax > 0, myName, item.resID, "叠加次数")) { return(false); } if (item.dotEffectTargetSelection != uint.MaxValue && !checkLink(myName, item.resID, DataType.DATA_SKILL_TARGET_SELECTION, item.dotEffectTargetSelection)) { return(false); } if (item.dotEffect2Others != uint.MaxValue && !checkLink(myName, item.resID, DataType.DATA_SKILL_EFFECT, item.dotEffect2Others)) { return(false); } if (item.randEvent != uint.MaxValue && !checkLink(myName, item.resID, DataType.DATA_SKILL_RAND_EVENT, item.randEvent)) { return(false); } if (item.newModelID != uint.MaxValue && !checkLink(myName, item.resID, DataType.DATA_MODEL, item.newModelID)) { return(false); } if (item.newWeaponID != uint.MaxValue && !checkLink(myName, item.resID, DataType.DATA_WEAPON, item.newWeaponID)) { return(false); } if (item.superNewWeaponID != uint.MaxValue && !checkLink(myName, item.resID, DataType.DATA_WEAPON, item.superNewWeaponID)) { return(false); } try { SkillUtilities.ParseProperties(item.properties); } catch (System.Exception exp) { GameDebug.LogError("buff.txt[" + item.resID + "]的属性格式错误."); } if (item.effect2OwnerOnExpired != uint.MaxValue && !checkLink(myName, item.resID, DataType.DATA_SKILL_EFFECT, item.effect2OwnerOnExpired)) { return(false); } if (item.targetSelectionOnExpired != uint.MaxValue && !checkLink(myName, item.resID, DataType.DATA_SKILL_TARGET_SELECTION, item.targetSelectionOnExpired)) { return(false); } if (item.effect2OthersOnExpired != uint.MaxValue && !checkLink(myName, item.resID, DataType.DATA_SKILL_EFFECT, item.effect2OthersOnExpired)) { return(false); } if (item._3DEffectID != uint.MaxValue && !checkLink(myName, item.resID, DataType.DATA_EFFECT, item._3DEffectID)) { return(false); } } // foreach (int key in DataManager.BuffTable.Keys) // { // // } return(true); }
private bool checkTrap() { DataType myName = DataType.DATA_TRAP; IDictionaryEnumerator itr = DataManager.TrapTable.GetEnumerator(); while (itr.MoveNext()) { TrapTableItem item = itr.Value as TrapTableItem; if (!checkParam(item.modelID != uint.MaxValue, myName, item.resID, "模型ID")) { return(false); } if (!checkLink(myName, item.resID, DataType.DATA_MODEL, item.modelID)) { return(false); } if (item.buffID != uint.MaxValue && !checkLink(myName, item.resID, DataType.DATA_SKILL_BUFF, item.buffID)) { return(false); } if (!checkParam(item.explodeDelay != uint.MaxValue, myName, item.resID, "爆炸延迟")) { return(false); } if (item.buffID != uint.MaxValue && !checkParam( !SkillUtilities.IsHarmfulEffect(SkillEffectType.Buff, item.buffID), DataType.DATA_TRAP, item.resID, "出生buff", "不能为trap添加有害的出生buff.")) { return(false); } if (item.delayEffect != uint.MaxValue && !checkLink(myName, item.resID, DataType.DATA_EFFECT, item.delayEffect)) { return(false); } if (!checkParam(item.collideRadius != uint.MaxValue, myName, item.resID, "碰撞检测半径", "无效的碰撞检测半径需要填入0")) { return(false); } if (item.targetSelectionOnExplode != uint.MaxValue && !checkLink(myName, item.resID, DataType.DATA_SKILL_TARGET_SELECTION, item.targetSelectionOnExplode)) { return(false); } if (item.skillEffectOnExplode != uint.MaxValue && !checkLink(myName, item.resID, DataType.DATA_SKILL_EFFECT, item.skillEffectOnExplode)) { return(false); } if (item._3DEffectOnExplode != uint.MaxValue && !checkLink(myName, item.resID, DataType.DATA_EFFECT, item._3DEffectOnExplode)) { return(false); } } // foreach (int key in DataManager.TrapTable.Keys) // { // TrapTableItem item = DataManager.TrapTable[key] as TrapTableItem; // if(!checkParam(item.modelID != uint.MaxValue, myName, key, "模型ID")) // return false; // // if (!checkLink(myName, key, DataType.DATA_MODEL, item.modelID)) // return false; // // if (item.buffID != uint.MaxValue // && !checkLink(myName, key, DataType.DATA_SKILL_BUFF, item.buffID)) // return false; // // if (!checkParam(item.explodeDelay != uint.MaxValue, myName, key, "爆炸延迟")) // return false; // // if (item.buffID != uint.MaxValue // && !checkParam( // !SkillUtilities.IsHarmfulEffect(SkillEffectType.Buff, item.buffID), // DataType.DATA_TRAP, key, "出生buff", "不能为trap添加有害的出生buff.")) // return false; // // if (item.delayEffect != uint.MaxValue && !checkLink(myName, key, DataType.DATA_EFFECT, item.delayEffect)) // return false; // // if (!checkParam(item.collideRadius != uint.MaxValue, myName, key, "碰撞检测半径", "无效的碰撞检测半径需要填入0")) // return false; // // if (item.targetSelectionOnExplode != uint.MaxValue // && !checkLink(myName, key, DataType.DATA_SKILL_TARGET_SELECTION, item.targetSelectionOnExplode)) // return false; // // if (item.skillEffectOnExplode != uint.MaxValue // && !checkLink(myName, key, DataType.DATA_SKILL_EFFECT, item.skillEffectOnExplode)) // return false; // // if (item._3DEffectOnExplode != uint.MaxValue // && !checkLink(myName, key, DataType.DATA_EFFECT, item._3DEffectOnExplode)) // return false; // } return(true); }
/// <summary> /// 开始位移. /// </summary> /// <param name="actionCenter">动作控制器</param> /// <param name="attackerAttr">发起这次位移的单位的属性(如果是突进, 那么是角色本身; 如果是击退, 为发起击退技能的单位)</param> /// <param name="displacementRes"></param> /// <returns></returns> public static ErrorCode StartDisplace(BattleUnitActionCenter actionCenter, AttackerAttr attackerAttr, uint displacementResID) { SkillDisplacementTableItem displacementRes = DataManager.DisplacementTable[displacementResID] as SkillDisplacementTableItem; if (displacementRes == null) { SkillUtilities.ResourceNotFound("displacement", displacementResID); return(ErrorCode.ConfigError); } // 免疫控制(有害的位移, 都视为控制). if (!actionCenter.Owner.CanBeStuned() && displacementRes.harmful) { return(ErrorCode.AddEffectFailedSkillEffectImmunity); } if ((actionCenter.GetActionByType(ActionTypeDef.ActionTypeDisplacement) as ActionDisplacement) != null) { return(ErrorCode.MaxStackCount); } Vector3 ownerPosition = actionCenter.Owner.GetPosition(); Vector3 targetPosition = ownerPosition; float distance = displacementRes.distance; if (distance < 0) { return(ErrorCode.ConfigError); } Vector3 displaceDirection = Vector3.zero; // 确定方向. switch (displacementRes.displacementType) { case SkillDisplacementType.Rush: displaceDirection = Utility.RadianToVector3(actionCenter.Owner.GetDirection()); break; case SkillDisplacementType.Beatback: displaceDirection = Utility.RadianToVector3(attackerAttr.EffectStartDirection); break; default: return(ErrorCode.ConfigError); } displaceDirection.y = 0; // 速度为负, 取反方向. if (displacementRes.speed < 0f) { displaceDirection = Vector3.zero - displaceDirection; } // beatback时, 特殊处理距离与朝向. if (displacementRes.displacementType == SkillDisplacementType.Beatback) { // 击退, 且速度为负时, 表示牵引向目标点. if (displacementRes.speed < 0f) { float magnitude = displaceDirection.magnitude; // 牵引的位置不会超过目标点的位置, 且与目标点的位置至少为0.5f. if (magnitude < distance) { distance = Mathf.Max(0f, magnitude - 0.5f); } } else // 击退时, 面朝起始点方向(后仰). { actionCenter.Owner.SetDirection(Utility.Vector3ToRadian(displaceDirection) + Mathf.PI); } } displaceDirection.Normalize(); displaceDirection *= distance; targetPosition += displaceDirection; BaseScene scn = SceneManager.Instance.GetCurScene(); if (scn == null) { return(ErrorCode.LogicError); } targetPosition = scn.FarthestWalkable(ownerPosition, targetPosition); ActionDisplacementInitParam param = new ActionDisplacementInitParam(); param.targetPosition = targetPosition; param.displacementResource = displacementRes; param.mAttackerAttr = attackerAttr; return(actionCenter.StartAction(param)); }
/// <summary> /// 开始硬直. /// </summary> public static ErrorCode StartSpasticity(BattleUnitActionCenter actionCenter, AttackerAttr attackerAttr, uint spasticityResID, ref uint cdMilliseconds ) { if (cdMilliseconds != 0) { return(ErrorCode.CoolingDown); } // 无法被控制. if (!actionCenter.Owner.CanBeStuned()) { return(ErrorCode.AddEffectFailedSkillEffectImmunity); } // 硬直抗性. int resistance = actionCenter.Owner.GetPropertyValue((int)PropertyTypeEnum.PropertyTypeSpasticityResistance); // 硬直抗性不低于抗性最大值, 无法触发硬直. if (resistance >= GameConfig.MaxSpasticityResistance) { return(ErrorCode.AddEffectFailedSkillEffectImmunity); } SkillSpasticityTableItem spasticityRes = DataManager.SkillSpasticityTable[spasticityResID] as SkillSpasticityTableItem; if (spasticityRes == null) { SkillUtilities.ResourceNotFound("skillspasticity", spasticityResID); return(ErrorCode.ConfigError); } Vector3 ownerPosition = actionCenter.Owner.GetPosition(); Vector3 targetPosition = ownerPosition; Vector3 spasticityDirection = Utility.RadianToVector3(attackerAttr.EffectStartDirection); spasticityDirection.y = 0; // 被硬直的单位的朝向为硬直位移方向的反方向. actionCenter.Owner.SetDirection(Utility.Vector3ToRadian(spasticityDirection) + Mathf.PI); // 计算硬直位移的距离. float distance = spasticityRes.distance; // 如果硬直抗性低于默认值, 击退距离 *= (100 / 抗性). if (resistance > 100) { resistance *= (100 / resistance); } spasticityDirection.Normalize(); spasticityDirection *= distance; targetPosition += spasticityDirection; BaseScene scn = SceneManager.Instance.GetCurScene(); if (scn == null) { return(ErrorCode.LogicError); } // 检测场景阻挡, 确定终点位置. targetPosition = scn.FarthestWalkable(ownerPosition, targetPosition); ActionSpasticityInitParam param = new ActionSpasticityInitParam(); param.spasticityRes = spasticityRes; param.targetPosition = targetPosition; param.mAttackerAttr = attackerAttr; // 当前的硬直动作. ActionSpasticity spasticityAction = actionCenter.GetActionByType(ActionTypeDef.ActionTypeSpasticity) as ActionSpasticity; ErrorCode err = ErrorCode.Succeeded; // 重新开始硬直. err = (spasticityAction != null) ? spasticityAction.Restart(param) : actionCenter.StartAction(param); if (err == ErrorCode.Succeeded) { // 硬直抗性, 可以用来增加硬直的CD时间. cdMilliseconds = (uint)(param.spasticityRes.cdMilliseconds * resistance / 100f); } return(err); }