private float GetScoreForCandidate(Actor_Player firer, Actor_Enemy candidate) { // Higher score is more likely to be picked switch (firer.minion.priority) { case TargetPriority.CLOSEST_ENEMY: { return(Core.GetLevel().GetRangedZoneMax() - candidate.transform.position.x); } case TargetPriority.FARTHEST_ENEMY: { return(candidate.transform.position.x - Core.GetLevel().GetRangedZoneMin()); } case TargetPriority.HIGHEST_HP_ENEMY: { return(candidate.minion.fCurrentHealth); } case TargetPriority.LOWEST_HP_ENEMY: { return(1.0f / candidate.minion.fCurrentHealth); } } return(-1.0f); }
protected bool TryToAttackEnemy(Actor_Player player, Actor_Enemy enemy) { if (player.fTimeSinceLastAttack >= fAttackInterval * player.GetAttackSpeedMultiplier()) { PlaySoundEffect(player); player.render.SetAnimStateAndNext(AnimState.ATTACK, AnimState.IDLE); player.fTimeSinceLastAttack = 0.0f; if (player.render.attackParticles != null) { //player.render.attackParticles.Stop(); player.render.attackParticles.Play(); } for (int i = 0; i < numAttacks; i++) { IncrementCombo(player); if (DealDamageToEnemy(player, enemy, enemy.transform.position, 0.0f)) { return(true); } } } return(false); }
public override void SimulatePlayerFixedUpdate(Actor_Player actor) { actor.fTimeSinceLastAttack += Core.GetPlayerDeltaTime(); //if (actor.currentTarget == null || actor.currentTarget.minion.fCurrentHealth <= 0.0f) { // Find new target actor.currentTarget = GetBestTarget(actor); } if (actor.minion.slot == MinionSlot.RANGED_1) { Actor_Player otherRangedMinion = Core.GetLevel().playerActors [(int)MinionSlot.RANGED_2]; if (otherRangedMinion.fTimeSinceLastAttack >= fAttackInterval) { actor.fTimeSinceLastAttack = fAttackInterval * 0.5f; } } int iSlot = actor.minion.slot == MinionSlot.RANGED_1 ? 0 : 1; Transform reticule = Core.GetLevel().instance.targets [iSlot]; Transform radius = Core.GetLevel().instance.radii [iSlot]; if (actor.currentTarget != null) { reticule.gameObject.SetActive(true); reticule.position = Vector3.Lerp(reticule.position, actor.currentTarget.transform.position + new Vector3(0.0f, 0.04f, 0.0f), Core.GetPlayerDeltaTime() * actor.minion.template.reticuleMoveSpeed * actor.GetAttackSpeedMultiplier()); float fRadius = damage.fRadius * actor.GetAttackRadiusMultiplier() * 2.0f; radius.localScale = new Vector3(fRadius, 1.0f, fRadius); if (!actor.currentTarget.IsInRangedZone()) { actor.currentTarget = null; } else if (actor.fTimeSinceLastAttack >= fAttackInterval * actor.GetAttackSpeedMultiplier()) { actor.fTimeSinceLastAttack = 0.0f; // Spawn a projectile for (int i = 0; i < numAttacks; i++) { Projectile projectile = Instantiate <Projectile>(projectilePrefab); projectile.firer = actor; projectile.firerTemplate = this; projectile.launchPos = actor.transform.position + new Vector3(0.5f * i, fProjectileLaunchHeight, 0.0f); projectile.fProgress = i * 0.1f; projectile.target = actor.currentTarget; projectile.transform.position = projectile.launchPos; } PlaySoundEffect(actor); actor.render.SetAnimStateAndNext(AnimState.ATTACK, AnimState.IDLE); } } else { //reticule.gameObject.SetActive(false); } }
protected bool DealDamageToEnemy(Actor_Player player, Actor_Enemy enemy, Vector3 position, float fRadius) { float fMultiplier = player.GetAttackDamageMultiplier(); if (position.x <= Core.GetLevel().GetMeleeZoneLimit()) { fMultiplier += player.minion.GetBuff(Stat.DAMAGE_MULTIPLIER_IN_MELEE_ZONE); } if (enemy.IsStunned()) { fMultiplier += player.minion.GetBuff(Stat.ATTACK_DAMAGE_ON_STUNNED_ENEMIES); } if (damage.IsRadial()) { Core.GetLevel().DamageRadius(damage, position, damage.fRadius * player.GetAttackRadiusMultiplier(), fMultiplier, player.GetStunTime(), player.minion.GetBuff(Stat.CRITICAL_CHANCE), player.minion.GetBuff(Stat.CRITICAL_DAMAGE), player.minion.GetBuff(Stat.VAMPIRISM), player.minion.GetBuff(Stat.ATTACK_DAMAGE_ABSOLUTE)); return(enemy == null || enemy.IsDead()); } else if (enemy != null) { if (enemy.IsDead()) { return(true); } float fElementalMultiplier = Elements.GetDamageMultiplier(damage.GetElement(), enemy.minion.template.element); float fMod = enemy.GetInherentElementalResistanceModifier(); if (fElementalMultiplier < 1.0f) { fElementalMultiplier = 1.0f - ((1.0f - fElementalMultiplier) * fMod); } fMultiplier *= fElementalMultiplier; player.OnDealtDamage(damage.fAmount * fMultiplier); return(enemy.Damage(damage, fMultiplier, player.GetStunTime(), player.minion.GetBuff(Stat.CRITICAL_CHANCE), player.minion.GetBuff(Stat.CRITICAL_DAMAGE), player.minion.GetBuff(Stat.VAMPIRISM), player.minion.GetBuff(Stat.ATTACK_DAMAGE_ABSOLUTE))); } return(true); }
public override void InitPlayer(Actor_Player actor) { base.InitPlayer(actor); if (auraPFX != null) { actor.auraPFX = Instantiate <PFX_SupportAura>(auraPFX); actor.auraPFX.transform.SetParent(actor.transform); actor.auraPFX.transform.localPosition = Vector3.zero; } actor.fTimeToNextAura = Random.Range(fTimeBetweenSFXMin, fTimeBetweenSFXMax); }
public override void SimulatePlayerFixedUpdate(Actor_Player actor) { // Default support. Do nothing. It's all in the buffs actor.fTimeToNextAura -= Core.GetPlayerDeltaTime(); if (actor.auraPFX != null && actor.fTimeToNextAura <= 0.0f) { actor.fTimeToNextAura = Random.Range(fTimeBetweenSFXMin, fTimeBetweenSFXMax); actor.auraPFX.Trigger(); if (soundEffect != null) { actor.soundEffect.PlayOneShot(soundEffect); } } List <Actor_Enemy> enemyList = new List <Actor_Enemy> (); enemyList.AddRange(Core.GetLevel().enemyActors); if (fPullSpeed > 0.0f) { foreach (Actor_Enemy enemy in enemyList) { if (enemy != null) { enemy.Move(new Vector3(-fPullSpeed, 0.0f, 0.0f), false, true); } } } if (fWaterDebuffAttractSpeed > 0.0f) { for (int i = 0; i < enemyList.Count; i++) { if (enemyList [i].HasWaterDebuff()) { for (int j = i + 1; j < enemyList.Count; j++) { if (enemyList [j].HasWaterDebuff()) { Vector3 dPos = enemyList [j].transform.position - enemyList [i].transform.position; dPos.Normalize(); dPos *= fWaterDebuffAttractSpeed; enemyList [i].Move(dPos, false, true); enemyList [j].Move(-dPos, false, true); } } } } } }
public override bool CanInteract(Actor sourceActor) { Actor_Player player = sourceActor.GetBehaviour <Actor_Player>(); if (player != null) { if (!player.isLeadPlayer) { return(false); } } return(base.CanInteract(sourceActor)); }
public override void SimulatePlayerFixedUpdate(Actor_Player actor) { if (damage.fAmount > 0.0f || damage.fPushAmount > 0.0f) // 0 means no attack { actor.fTimeSinceLastAttack += Core.GetPlayerDeltaTime(); if (actor.currentTarget == null || actor.currentTarget.minion.fCurrentHealth <= 0.0f || !actor.currentTarget.IsInMeleeZone()) { actor.currentTarget = null; // Find new target Actor_Enemy closestEnemy = Core.GetLevel().GetClosestEnemyToMeleeZone(); if (closestEnemy != null && closestEnemy.IsInMeleeZone()) { actor.currentTarget = closestEnemy; } else { // No valid target. } } int iSlot = actor.minion.slot == MinionSlot.MELEE_1 ? 0 : 1; Transform reticule = Core.GetLevel().instance.meleeTargets [iSlot]; Transform radius = Core.GetLevel().instance.meleeRadii [iSlot]; if (actor.currentTarget != null) { reticule.gameObject.SetActive(true); reticule.position = Vector3.Lerp(reticule.position, actor.currentTarget.transform.position + new Vector3(0.0f, 0.04f, 0.0f), Core.GetPlayerDeltaTime() * actor.minion.template.reticuleMoveSpeed * actor.GetAttackSpeedMultiplier()); float fRadius = damage.fRadius * actor.GetAttackRadiusMultiplier() * 2.0f; radius.localScale = new Vector3(fRadius, 1.0f, fRadius); if (TryToAttackEnemy(actor, actor.currentTarget)) { // We killed them actor.currentTarget = null; } } else { //reticule.gameObject.SetActive(false); } } }
public override void SimulatePlayerFixedUpdate(Actor_Player actor) { base.SimulatePlayer(actor); if (Core.GetCurrentRoster().afGroupHealths [(int)MinionSlotType.RANGED] / Core.GetCurrentRoster().afGroupMaxHealths [(int)MinionSlotType.RANGED] <= fHealthTrigger) { actor.fTimeToNextBurn -= Core.GetPlayerDeltaTime(); if (actor.fTimeToNextBurn <= 0.0f) { actor.fTimeToNextBurn = fTimeBetweenBurns; List <Actor_Enemy> enemies = new List <Actor_Enemy> (); enemies.AddRange(Core.GetLevel().enemyActors); foreach (Actor_Enemy enemy in enemies) { enemy.Damage(burnDamage, actor.GetAttackDamageMultiplier(), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); } } } }
public bool IsAnyoneAlive(MinionSlotType slotType) { if (Core.GetLevel() == null) { return(false); } bool bAnyoneAlive = false; for (int i = 0; i < slotType.GetNumSlots(); i++) { Actor_Player player = Core.GetLevel().playerActors [(int)slotType.GetFirst() + i]; //Debug.Assert(player == null || player.minion != null); if (player != null && player.minion != null && player.minion.fCurrentHealth > 0.0f) { bAnyoneAlive = true; } } return(bAnyoneAlive); }
protected Actor_Enemy GetBestTarget(Actor_Player firer, bool bNotInMeleeZone = false) { Actor_Player otherRangedMinion = Core.GetLevel().playerActors [firer.minion.slot == MinionSlot.RANGED_1 ? (int)MinionSlot.RANGED_2 : (int)MinionSlot.RANGED_1]; Actor_Enemy bestCandidate = null; float fBestScore = 0.0f; foreach (Actor_Enemy enemy in Core.GetLevel().enemyActors) { if (enemy == null || enemy.IsDead() || enemy.bAboutToDie) { continue; } if (!enemy.IsInRangedZone()) { continue; } if (enemy.IsInMeleeZone() && bNotInMeleeZone) { continue; } float fScore = GetScoreForCandidate(firer, enemy); if (enemy == otherRangedMinion.currentTarget) { fScore *= 0.5f; } if (fScore > fBestScore) { bestCandidate = enemy; fBestScore = fScore; } } return(bestCandidate); }
public override void SimulatePlayerFixedUpdate(Actor_Player actor) { actor.fTimeSinceLastAttack += Core.GetPlayerDeltaTime(); //if (actor.currentTarget == null || actor.currentTarget.minion.fCurrentHealth <= 0.0f) { // Find new target actor.currentTarget = GetBestTarget(actor); } if (actor.currentTarget != null) { int iSlot = actor.minion.slot == MinionSlot.RANGED_1 ? 0 : 1; Transform reticule = Core.GetLevel().instance.targets [iSlot]; Transform radius = Core.GetLevel().instance.radii [iSlot]; reticule.gameObject.SetActive(true); reticule.position = Vector3.Lerp(reticule.position, actor.currentTarget.transform.position + new Vector3(0.0f, 0.04f, 0.0f), Core.GetPlayerDeltaTime() * actor.minion.template.reticuleMoveSpeed * actor.GetAttackSpeedMultiplier()); radius.localScale = new Vector3(0.0f, 1.0f, 0.0f); if (!actor.currentTarget.IsInRangedZone()) { actor.currentTarget = null; } else if (actor.fTimeSinceLastAttack >= fAttackInterval * actor.GetAttackSpeedMultiplier()) { actor.fTimeSinceLastAttack = 0.0f; List <Vector3> pfxPositions = new List <Vector3> (); pfxPositions.Add(actor.transform.position + new Vector3(0.0f, fProjectileLaunchHeight, 0.0f)); List <Actor_Enemy> alreadyHit = new List <Actor_Enemy> (); Actor_Enemy currentTarget = actor.currentTarget; float fChainRemaining = iChain * actor.GetChainCountMultiplier(); PlaySoundEffect(actor); while (fChainRemaining > 0.0f) { DealDamageToEnemy(actor, currentTarget, currentTarget.transform.position, 0.0f); if (currentTarget.HasWaterDebuff()) { fChainRemaining -= 0.5f; } else { fChainRemaining -= 1.0f; } alreadyHit.Add(currentTarget); // Add a line Vector3 prevPos = pfxPositions [pfxPositions.Count - 1]; Vector3 newPos = currentTarget.transform.position + new Vector3(0.0f, fProjectileLaunchHeight, 0.0f); Vector3 dPos = newPos - prevPos; float fLength = dPos.magnitude; // If it is longer than 2 units, split it into segments if (fLength >= 2.0f) { dPos.Normalize(); int numSegments = Mathf.FloorToInt(fLength / 2.0f); for (int i = 0; i < numSegments; i++) { Vector3 pos = prevPos + dPos * 2.0f * (i + 1); Vector3 offset = Random.onUnitSphere; offset.y = 0.0f; pos += offset; pfxPositions.Add(pos); } } pfxPositions.Add(newPos); Actor_Enemy bestCandidate = null; float fBestDistance = fMaxChainGap * actor.GetChainGapMultiplier(); foreach (Actor_Enemy enemy in Core.GetLevel().enemyActors) { if (enemy != null && !alreadyHit.Contains(enemy)) { float fDist = (currentTarget.transform.position - enemy.transform.position).magnitude; if (fDist < fBestDistance) { fBestDistance = fDist; bestCandidate = enemy; } } } if (bestCandidate == null) { break; } currentTarget = bestCandidate; } actor.render.SetChainPFXActive(fChainPFXDuration, pfxPositions.ToArray()); actor.render.SetAnimStateAndNext(AnimState.ATTACK, AnimState.IDLE); } } }
public override void SimulateEnemyFixedUpdate(Actor_Enemy actor) { if (actor.IsFrozen() || actor.IsStunned()) { return; } actor.fTimeSinceLastAttack += Core.GetPlayerDeltaTime(); float fMin = Core.GetLevel().GetRangedZoneMin(); //GetTargetRangeMin(); float fMax = Core.GetLevel().GetRangedZoneMax(); //GetTargetRangeMax(); fMax -= (fMax - fMin) * 0.25f; bool bInRange = fMin <= actor.transform.position.x && actor.transform.position.x <= fMax; if (bInRange) { if (actor.fTimeSinceLastAttack >= fAttackInterval * actor.GetAttackSpeedMultiplier()) { actor.fTimeSinceLastAttack = 0.0f; PlaySoundEffect(actor); // Zap both player ranged characters RangedAttackPlayer(actor, damage, MinionSlot.RANGED_1); RangedAttackPlayer(actor, damage, MinionSlot.RANGED_2); List <Vector3> pfxPositions = new List <Vector3> (); pfxPositions.Add(actor.transform.position + new Vector3(0.0f, fProjectileLaunchHeight, 0.0f)); int firstHit = Random.Range(0, 2); // Add a line Vector3 prevPos = pfxPositions [pfxPositions.Count - 1]; Actor_Player firstPlayerHit = Core.GetLevel().playerActors[(int)MinionSlot.RANGED_1 + firstHit]; Actor_Player secondPlayerHit = Core.GetLevel().playerActors[(int)MinionSlot.RANGED_1 + (1 - firstHit)]; Vector3 newPos = firstPlayerHit.transform.position + new Vector3(0.0f, fProjectileLaunchHeight, 0.0f); Vector3 dPos = newPos - prevPos; float fLength = dPos.magnitude; // If it is longer than 2 units, split it into segments if (fLength >= 2.0f) { dPos.Normalize(); int numSegments = Mathf.FloorToInt(fLength / 2.0f); for (int i = 0; i < numSegments; i++) { Vector3 pos = prevPos + dPos * 2.0f * (i + 1); Vector3 offset = Random.onUnitSphere; offset.y = 0.0f; pos += offset; pfxPositions.Add(pos); } } pfxPositions.Add(firstPlayerHit.transform.position); pfxPositions.Add(secondPlayerHit.transform.position); actor.render.SetChainPFXActive(fChainPFXDuration, pfxPositions.ToArray()); actor.render.SetAnimStateAndNext(AnimState.ATTACK, AnimState.IDLE); } else if (actor.fTimeSinceLastAttack >= fAttackInterval * actor.GetAttackSpeedMultiplier() * 0.5f) { float fSpeed = fMoveSpeed; if (actor.transform.position.x - fMin < 1.0f) { fSpeed *= (actor.transform.position.x - fMin); } actor.Move(new Vector3(-fSpeed, 0.0f, 0.0f)); actor.render.SetAnimState(AnimState.WALKING, false); } } else { actor.Move(new Vector3(-fMoveSpeed, 0.0f, 0.0f)); actor.render.SetAnimState(AnimState.WALKING, false); } }
public abstract void SimulatePlayerFixedUpdate(Actor_Player actor);
public virtual void InitPlayer(Actor_Player actor) { Init(); }
public void StartLevel(TeamRoster selectedRoster) { // This oddly named object points to all sorts of useful things that exist in all levels instance = FindObjectOfType <PlayerRig>(); if (instance == null) { instance = Instantiate <PlayerRig>(Core.theCore.playerRigPrefab); instance.transform.position = Vector3.zero; } GameObject sunObject = GameObject.Find("Directional Light"); if (sunObject != null) { sun = sunObject.GetComponent <Light>(); originalSunPos = sun.transform.rotation; } instance.gameObject.SetActive(true); Range[] ranges = new Range[2] { Range.WIDE, Range.WIDE }; bool bAgainstElement = false; fMeleeZoneSize = 1.0f; Core.theCore.fEnemyTimescale = 1.0f; Core.theCore.fPlayerTimescale = 1.0f; // Spawn the player's minions immediately. Then give a countdown to start the game roster = selectedRoster; for (int i = 0; i < (int)MinionSlot.NUM_MINION_SLOTS; i++) { Transform spawnPoint = instance.playerSpawnPoints [i]; Minion minion = roster.minions [i]; if (spawnPoint != null && minion != null) { // Create new game object GameObject go = new GameObject("PlayerMinion_" + i + "_" + minion.template.name); // Fill it with actor components Actor_Player actor = go.AddComponent <Actor_Player>(); actor.InitFromMinion(minion); actor.transform.position = spawnPoint.position; // Add renderer to actor RenderActor render = Instantiate <RenderActor>(minion.template.render); render.transform.SetParent(actor.transform); render.transform.localPosition = Vector3.zero; render.transform.localScale = new Vector3(-1.0f, 1.0f, 1.0f); render.Init(actor); actor.render = render; // Add audio sources actor.soundEffect = go.AddComponent <AudioSource>(); actor.soundEffect.clip = minion.template.soundEffect; actor.soundEffect.playOnAwake = false; actor.soundEffect.outputAudioMixerGroup = Core.GetAudioManager().soundEffectGroup; // And combo numbers if ((minion.template.canCombo || minion.template.bDeathtoll || minion.template.bRelentless) && minion.template.comboNumbers != null) { ComboNumbers combo = Instantiate <ComboNumbers>(minion.template.comboNumbers); combo.transform.SetParent(actor.transform); combo.transform.localPosition = new Vector3(-0.17f, 0.215f, -0.13f); actor.comboNumbers = combo; } // Save a reference for later playerActors [i] = actor; // if (((MinionSlot)i).GetSlotType() == MinionSlotType.RANGED && (minion.template is Minion_Ranged)) { ranges [i == (int)MinionSlot.RANGED_1 ? 0 : 1] = ((Minion_Ranged)minion.template).range; } if (minion.template is Minion_Support && ((Minion_Support)(minion.template)).bWalls) { bWalls = true; } foreach (Resurrection res in minion.template.resurrectionTriggers) { singleUseResurrections.Add(new Resurrection(res)); } if (minion.template.element.GetDamageMultiplier(location.element) < 1.0f && ((MinionSlot)i).GetSlotType() != MinionSlotType.SUPPORT) { bAgainstElement = true; } Core.theCore.fEnemyTimescale += minion.GetBuff(Stat.ENEMY_TIMESCALE); Core.theCore.fPlayerTimescale += minion.GetBuff(Stat.PLAYER_TIMESCALE); fMeleeZoneSize += minion.GetBuff(Stat.MELEEZONE_SIZE); } } roster.bHasThreeResurrectsAvailable = singleUseResurrections.Count == 6; roster.bHasActiveCollector = false; // After ALL player minions are created, then calculate their passive buffs and store them off. for (int i = 0; i < (int)MinionSlot.NUM_MINION_SLOTS; i++) { if (playerActors [i] != null) { playerActors [i].CalculateMyAggregateBuffs(); playerActors [i].SetMaxHealthFromBuffs(); playerActors [i].minion.ResetTemporaryData(); } } roster.RecalculateHealths(); fRangedZoneMin = Ranges.GetMinRangeForPair(ranges [0], ranges [1]); fRangedZoneMax = Ranges.GetMaxRangeForPair(ranges [0], ranges [1]); fLaneWidth = bWalls ? 4.0f : 6.0f; InitZones(bWalls); aiNumKilledPerWave = new int[location.numWaves]; aiNumSpawnedPerWave = new int[location.numWaves]; abNewlyUnlocked = new bool[location.numWaves]; iCurrentWave = -1; AdvanceWave(); fGracePeriodDuration = location.gracePeriodDuration; instance.elementalHint.enabled = bAgainstElement; if (bAgainstElement) { instance.elementalHint.text = LocalizationManager.GetLoc(location.element.GetHintText()); } Core.GetAudioManager().SetLevelMusic(location.music); RequestState(LevelState.PLAYING); }
// Think of this as the actor being a vehicle and the minion doing the driving. Different minions will drive their actors differently public abstract void SimulatePlayer(Actor_Player actor);
// Think of this as the actor being a vehicle and the minion doing the driving. Different minions will drive their actors differently public override void SimulatePlayer(Actor_Player actor) { }
public override void SimulatePlayerFixedUpdate(Actor_Player actor) { actor.fTimeSinceLastAttack += Core.GetPlayerDeltaTime(); //if (actor.currentTarget == null || actor.currentTarget.minion.fCurrentHealth <= 0.0f) { // Find new target actor.currentTarget = GetBestTarget(actor); } if (bLoopingSoundEffect && !actor.soundEffect.isPlaying) { actor.soundEffect.loop = true; actor.soundEffect.clip = soundEffect; actor.soundEffect.Play(); } if (actor.currentTarget != null) { int iSlot = actor.minion.slot == MinionSlot.RANGED_1 ? 0 : 1; Transform reticule = Core.GetLevel().instance.targets [iSlot]; Transform radius = Core.GetLevel().instance.radii [iSlot]; reticule.gameObject.SetActive(true); reticule.position = Vector3.Lerp(reticule.position, actor.currentTarget.transform.position + new Vector3(0.0f, 0.04f, 0.0f), Core.GetPlayerDeltaTime() * actor.minion.template.reticuleMoveSpeed * actor.GetAttackSpeedMultiplier()); float fRadius = damage.fRadius * actor.GetAttackRadiusMultiplier() * 2.0f; radius.localScale = new Vector3(fRadius, 1.0f, fRadius); if (actor.iNumHitsWithSummon >= iNumHits) { actor.summon.PlayDeathAnimation(); actor.summon = null; actor.iNumHitsWithSummon = 0; reticule.position = actor.currentTarget.transform.position + new Vector3(0.0f, 0.04f, 0.0f); } if (actor.summon == null) { // TODO : Do spawn PFX actor.summon = Instantiate <RenderActor>(summonPrefab); actor.summon.transform.SetParent(reticule); actor.summon.transform.localPosition = new Vector3(0.0f, fSummonHeight, 0.0f); if (summonEffect != null) { summonEffect.Play(); } } if (!actor.currentTarget.IsInRangedZone()) { actor.currentTarget = null; } else if (actor.fTimeSinceLastAttack >= fAttackInterval * actor.GetAttackSpeedMultiplier()) { actor.fTimeSinceLastAttack = 0.0f; if (!bLoopingSoundEffect) { PlaySoundEffect(actor); } if (DealDamageToEnemy(actor, actor.currentTarget, actor.currentTarget.transform.position, 0.0f)) { // We killed them actor.currentTarget = null; } actor.iNumHitsWithSummon++; actor.summon.SetAnimStateAndNext(AnimState.ATTACK, AnimState.IDLE); } } }
private float Attack(Actor_Enemy attacker, Damage damage, float fMod, MinionSlotType slotType, MinionSlot slot) { float fTotalDealt = 0.0f; float fDamage = damage.fAmount * fMod; if (fDamage > 0.0f) { float fTotalMultiplierFromMinions = 0.0f; for (int i = 0; i < slotType.GetNumSlots(); i++) { Minion minion = minions [(int)slotType.GetFirst() + i]; if (minion != null) { float fBuffModifier = minion.GetBuff(Stats.GetStatForDamageMultiplier(damage.GetElement())); fBuffModifier += minion.GetBuff(Stat.DAMAGE_MULTIPLIER); fBuffModifier += minion.GetBuff(slotType == MinionSlotType.MELEE ? Stat.DAMAGE_MULTIPLIER_MELEE : Stat.DAMAGE_MULTIPLIER_RANGED); fBuffModifier += minion.GetBuff(Stat.DAMAGE_MULTIPLIER_PER_COMBO) * minion.iCombo; fTotalMultiplierFromMinions += (1.0f + fBuffModifier) * Elements.GetDamageMultiplier(damage.GetElement(), minion.template.element); } else { fTotalMultiplierFromMinions += 1.0f; } } float fAverageMinionMultiplier = fTotalMultiplierFromMinions / slotType.GetNumSlots(); fDamage *= fAverageMinionMultiplier; fDamage *= (1.0f + Mathf.Clamp(damage.fRadius, 0.0f, 5.0f)); if (attacker != null && attacker.minion.template.canCombo) { fDamage *= 3.0f; } float fDamageToDeal = Mathf.Min(afGroupHealths [(int)slotType], fDamage); if (fDamageToDeal > 0.0f) { float fParametricHealthPreDamage = afGroupHealths[(int)slotType] / afGroupMaxHealths[(int)slotType]; afGroupHealths [(int)slotType] -= fDamageToDeal; float fParametricHealthPostDamage = afGroupHealths[(int)slotType] / afGroupMaxHealths[(int)slotType]; if (!bHasTriggeredVolatileYet && fParametricHealthPreDamage > 0.25f && fParametricHealthPostDamage <= 0.25f) { bHasTriggeredVolatileYet = true; for (int i = 0; i < slotType.GetNumSlots(); i++) { if (minions [(int)slotType.GetFirst() + i].template.bVolatile) { // TODO: Play PFX // Play sound Core.GetLevel().KillAllEnemies(); } } } // Do damage numbers Actor_Player actorHit = null; if (slot == MinionSlot.NUM_MINION_SLOTS) { actorHit = Core.GetLevel().playerActors [(int)slotType.GetFirst() + Random.Range(0, slotType.GetNumSlots())]; } else { actorHit = Core.GetLevel().playerActors [(int)slot]; } if (actorHit != null) { int iDamage = Mathf.FloorToInt(fDamage); actorHit.MakeDamageNumbers(iDamage, Core.GetMinionTemplateManager().playerDamage); } if (afGroupHealths [(int)slotType] <= 0.0f) { KillGroup(slotType); } fDamage -= fDamageToDeal; fTotalDealt += fDamageToDeal; Core.GetLevel().bHasSomeDamageBeenTaken = true; } } return(fTotalDealt); }