/// <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 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); } }
public SkillBuffInitParam(BattleUnit owner, AttackerAttr attr, uint buffResID) : base(owner, attr) { buffResource = DataManager.BuffTable[buffResID] as SkillBuffTableItem; if (buffResource == null) { SkillUtilities.ResourceNotFound("buff", buffResID); } }
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> /// 根据公式, 计算并返回实际伤害(正值). /// </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); }
/// <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); }