public override BattleActionResult execute(BattleCreature source, List <BattleCreature> targets, double amp, double hitChanceMultiplier, double alteredChanceForSecondary) { bool interactableTargets = false; int damageDealt = 0; List <BattleCreature> hit = new List <BattleCreature>(); foreach (BattleCreature target in targets) { if (target.isInteractable()) { interactableTargets = true; if (RandomUtils.checkOdds(chanceToHit * (1 + hitChanceMultiplier))) { double typeMultiplier = damageType.getDamageMultiplierVs(target.creature.getCreatureTypes()); int damage = DamageUtils.calculateDamage(basePower * typeMultiplier, source.creature.getStats(), target.creature.getStats()); damageDealt += damage; target.changeHealth(damage); hit.Add(target); } } } return(new DamageBattleActionResult(interactableTargets, targets.Count > 0, damageDealt, damageType, source, targets, hit)); }
public virtual void Awake() { hittedObjects = new List <GameObject>(); GameObject gameManager = GameObject.FindGameObjectWithTag("GameController"); commonUtils = gameManager.GetComponentInChildren <CommonUtils>(); damageUtils = gameManager.GetComponentInChildren <DamageUtils>(); }
public bool Attack(BattleUnitsStack target) { if (_state != BattleState.InGame) { return(false); } var source = GetCurrentStack(); if (source.GetArmy() == target.GetArmy()) { return(false); } var hitPoints = DamageUtils.CalcDamageHitPoints(source, target); // Fire before attack event var beforeAttackEventArgs = new BeforeAttackEventArgs(source, target, hitPoints); EventBus.OnBeforeAttack(this, beforeAttackEventArgs); if (beforeAttackEventArgs.Cancel) { return(false); } hitPoints = beforeAttackEventArgs.HitPoints; target.Damage(hitPoints); // Fire after attack event EventBus.OnAfterAttack(this, new AfterAttackEventArgs(source, target, hitPoints)); if (target.IsAlive() && !target.IsAnswered()) { var answerHitPoints = DamageUtils.CalcDamageHitPoints(target, source); // Fire before answer event var beforeAnswerEventArgs = new BeforeAnswerEventArgs(source, target, answerHitPoints); EventBus.OnBeforeAnswer(this, beforeAnswerEventArgs); if (!beforeAnswerEventArgs.Cancel) { answerHitPoints = beforeAnswerEventArgs.HitPoints; source.Damage(answerHitPoints); target.SetAnswered(beforeAnswerEventArgs.IsAnswered); // Fire after answer event EventBus.OnAfterAnswer(this, new AfterAnswerEventArgs(source, target, hitPoints, beforeAnswerEventArgs.IsAnswered)); } } NextTurn(); return(true); }
/// <summary> /// 预先判断该武将是否会被打死 /// </summary> /// <param name="attackHero">进攻方数据</param> /// <param name="hurtHero">被攻击方数据</param> /// <returns></returns> public static bool checkRoleDead(HeroVo attackHero, HeroVo hurtHero) { int damage = DamageUtils.mathDamage(attackHero, hurtHero); hurtHero.tempHp -= damage; if (hurtHero.tempHp < 0) { hurtHero.tempHp = 0; } return((bool)(hurtHero.tempHp <= 0)); }
/// <summary> /// 攻击动作结束 /// </summary> private void attackCompleteHandler() { int damage = DamageUtils.mathDamage(this.heroVo, this.targetBr.heroVo); //范围伤害 this.rangeHurt(damage); //目标受伤 this.targetBr.hurt(damage); //移动回原位 this.moveAct(this.startPos, true, moveToTargetComplete); }
Projectile InstantiateProjectile() { Contract.Assert(ProjectileTemplate != null); Projectile instantiatedProjectile = Instantiate(ProjectileTemplate, ComputeMuzzleWorldPosition3D(), transform.rotation); if (!instantiatedProjectile) { Debug.LogError($"Failed to instantiate projectile of class \"{ProjectileTemplate?.GetType()}\""); return(null); } DamageUtils.SetInstigatorForDamageSubsystemComponents(instantiatedProjectile.gameObject, instigator); return(instantiatedProjectile); }
private void effectMoveCompleteHandler(GameObject effectGo) { this._isAttacking = false; this.isMoveBack = true; GameObject.Destroy(effectGo); effectGo = null; //执行伤害 int damage = DamageUtils.mathDamage(this.heroVo, this.targetBr.heroVo); //范围伤害 this.rangeHurt(damage); //目标受伤 this.targetBr.hurt(damage); this.moveToTargetComplete(); }
/// <summary> /// 获取被攻击目标(普通攻击) /// </summary> /// <param name="isMyTeam">是否是我方队伍攻击</param> private void getAttackTarget(bool isMyTeam) { List <BattleRole> targetList; List <BattleRole> targetAry; if (isMyTeam) { targetList = this.targetTeam; targetAry = this.targetTeamAry; } else { targetList = this.myTeam; targetAry = this.myTeamAry; } this.initRoleAttackData(isMyTeam); int count = this.attackList.Count; int targetCount = targetList.Count; //关闭列表 存放一次进攻后血量为0的角色 List <int> closeList = new List <int>(); for (int i = 0; i < count; ++i) { BattleRole attackRole = this.attackList[i]; float dis = float.MaxValue; int index = -1; //查找距离最近的对手 for (int j = 0; j < targetCount; ++j) { BattleRole targetBr = targetList[j]; if (closeList.IndexOf(targetBr.index) != -1) { continue; } float curDis = (attackRole.posIndexVector - targetBr.posIndexVector).sqrMagnitude; if (curDis < dis) { index = j; dis = curDis; } } //计算被攻击者剩余血量 如果进攻后血量为0 则放入关闭列表中 if (index != -1) { BattleRole chooseBr = targetList[index]; if (DamageUtils.checkRoleDead(attackRole.heroVo, chooseBr.heroVo)) { closeList.Add(chooseBr.index); } //将目标存放进去 attackRole.setAttackTarget(chooseBr); if (attackRole.heroVo.attackRangeType != 0) { List <BattleRole> rangeAttackRoleList = new List <BattleRole>(); bool isHorizontal = attackRole.heroVo.attackRangeType == BattleConstant.ATTACK_RANGE_HORIZONTAL; int [] rangeIndexAry = BattleFormation.getPosIndexByDirection(isHorizontal, chooseBr.index); //遍历posIndexAry 剔除 chooseBr.index 和 closeList中的索引 //判断checkRoleDead 将血为空的添加进col int length = rangeIndexAry.Length; for (int j = 0; j < length; j++) { int rangeIndex = rangeIndexAry[j]; if (rangeIndex == chooseBr.index || closeList.IndexOf(rangeIndex) != -1) { continue; } BattleRole rangeAttackRole = targetAry[rangeIndex]; if (rangeAttackRole != null && !rangeAttackRole.isDeaded) { if (DamageUtils.checkRoleDead(attackRole.heroVo, rangeAttackRole.heroVo)) { closeList.Add(chooseBr.index); } rangeAttackRoleList.Add(rangeAttackRole); } } attackRole.setAttackRangeTarget(rangeAttackRoleList); } attackRole.isAttacking = true; } } }
public void Update() { if (projectiles.Count <= 0) // If nobodys shooting, dont bother getting/setting particles { return; } numAlive = pS.GetParticles(particles); for (int i = 0; i < projectiles.Count; i++) { Projectile proj = projectiles[i]; // TODO: Also do positional hit detection for situations where a projectile slips into a unit without raycast hitting the outer shell (ie rotation) // Raycast according to movement path RaycastHit hit; if (Physics.Raycast(proj.position, proj.direction, out hit, proj.GetSpeed() * Time.deltaTime, mask)) { int projTeam = proj.GetFrom().Team; Unit unit = null; bool hitSelf = false; if (hit.collider.transform.parent) // Is this a unit? { unit = hit.collider.transform.parent.GetComponent <Unit>(); if (unit) // Is this a unit? { if (unit != proj.GetFrom()) // If we hit a unit and its not us, damage it { Status status = proj.GetStatus(); if (status != null) { if (status.statusType == StatusType.SuperlaserMark) { status.SetTimeLeft(proj.GetDamage() < gameRules.ABLY_superlaserDmgByStacks[1] ? proj.GetDamage() * SL_turretMult : proj.GetDamage() * SL_superlaserMult); // Store damage in timeLeft field of status } unit.AddStatus(status); } // If we hit an ally, do reduced damage because it was an accidental hit bool doFullDamage = DamageUtils.IgnoresFriendlyFire(proj.GetDamageType()) || unit.Team != projTeam; DamageResult result = unit.Damage(doFullDamage ? proj.GetDamage() : proj.GetDamage() * gameRules.DMG_ffDamageMult, proj.CalcRange(), proj.GetDamageType()); if (result.lastHit && proj.GetFrom()) { proj.GetFrom().AddKill(unit); } } else { // Ignore this collision hitSelf = true; } } } // Don't do anything if we are passing through the unit that fired us if (!hitSelf) { proj.position = hit.point - proj.direction * gameRules.PRJ_hitOffset; // Move to contact point particles[i].position = proj.position; particles[i].remainingLifetime = 0; // Destroy particle toDelete.Add(proj); // Destroy projectile Vector3 direction = ((-proj.direction + hit.normal) / 2).normalized; if (unit) { if (unit.GetShields().x > 0) // Shielded { vfx.SpawnEffect(VFXType.Hit_Absorbed, proj.position, direction, projTeam); } else // Normal hit { vfx.SpawnEffect(VFXType.Hit_Normal, proj.position, direction, projTeam); } } else // Terrain { vfx.SpawnEffect(VFXType.Hit_Normal, proj.position, direction, projTeam); } continue; } } //if Raycast proj.UpdateTimeAlive(Time.deltaTime); if (proj.GetTimeAlive() > gameRules.PRJ_maxTimeAlive) { particles[i].remainingLifetime = 0; // Destroy particle toDelete.Add(proj); // Destroy projectile } proj.position += proj.direction * proj.GetSpeed() * Time.deltaTime; // Update projectile position particles[i].position = proj.position; // Sync particle with projectile particles[i].velocity = proj.direction; //Debug.DrawRay(proj.position, proj.direction, Color.red); } //for for (int i = 0; i < toDelete.Count; i++) { //Instantiate(test, toDelete[i].position, Quaternion.identity); projectiles.Remove(toDelete[i]); } toDelete.Clear(); //newProjectilesThisFrame = 0; pS.SetParticles(particles, numAlive); } //Update()
// Called immediately after a hitscan is spawned float Raycast(Hitscan scan) { // Raycast according to start position, direction, and range RaycastHit hit; if (Physics.Raycast(scan.startPosition, scan.direction, out hit, scan.GetRange(), mask)) { int scanTeam = scan.GetFrom().Team; Unit unit = null; bool hitSelf = false; if (hit.collider.transform.parent) // Is this a unit? { unit = hit.collider.transform.parent.GetComponent <Unit>(); if (unit) // Is this a unit? { if (unit != scan.GetFrom()) // If we hit a unit and its not us, damage it { Status status = scan.GetStatus(); if (status != null) { if (status.statusType == StatusType.SuperlaserMark) { status.SetTimeLeft(scan.GetDamage() < gameRules.ABLY_superlaserDmgByStacks[1] ? scan.GetDamage() * SL_turretMult : scan.GetDamage() * SL_superlaserMult); // Store damage in timeLeft field of status } unit.AddStatus(status); } float actualRange = (hit.point - scan.startPosition).magnitude; // If we hit an ally, do reduced damage because it was an accidental hit bool doFullDamage = DamageUtils.IgnoresFriendlyFire(scan.GetDamageType()) || unit.Team != scanTeam; DamageResult result = unit.Damage(doFullDamage ? scan.GetDamage() : scan.GetDamage() * gameRules.DMG_ffDamageMult, actualRange, scan.GetDamageType()); if (result.lastHit && scan.GetFrom()) { scan.GetFrom().AddKill(unit); } } else { // Ignore this collision hitSelf = true; // TODO: Adapt friendly fire code for raycasting here } } } Vector3 endPosition = (hit.point - scan.direction * gameRules.PRJ_hitOffset); // Don't do anything if we are passing through the unit that fired us if (!hitSelf) { if (unit) { if (unit.GetShields().x > 0) // Shielded { vfx.SpawnEffect(VFXType.Hit_Absorbed, endPosition, -scan.direction, scanTeam); } else // Normal hit { vfx.SpawnEffect(VFXType.Hit_Normal, endPosition, -scan.direction, scanTeam); } } else // Terrain { vfx.SpawnEffect(VFXType.Hit_Normal, endPosition, -scan.direction, scanTeam); } return((scan.startPosition - endPosition).magnitude); // Return actual length of hitscan } } //if Raycast return(scan.GetRange()); }