public override GameObject Mutate(GameObject abilityObject, Vector3 location, Vector3 targetLocation) { // get a reference to the child's SummonEntityOnDeath component, this the component that makes the wolf SummonEntityOnDeath summoner = abilityObject.GetComponent <SummonEntityOnDeath>(); // add additional stats summoner.statList.AddRange(statList); // crit on cast buff if (critFromManaCost && mana && statBuffs) { TaggedStatsHolder.TaggableStat stat = new TaggedStatsHolder.TaggableStat(Tags.Properties.CriticalChance, null); stat.increasedValue = mana.getManaCost(ability) * 0.01f; statBuffs.addTaggedBuff(new TaggedBuff(stat, 4f, "Summon wraith mana crit")); } // add corpse consumption stats bool corpseConsumed = false; if (corpseStatList != null && corpseStatList.Count > 0 && health && health.alignmentManager && health.alignmentManager.alignment != null) { float closestDistance = float.MaxValue; Dying closestDying = null; float distance = 0f; // check all corpses to find the closest foreach (Dying dying in Dying.all) { // check that the entity is dying and is an enemy if (dying.isDying() && dying.myHealth && dying.myHealth.alignmentManager && health.alignmentManager.alignment.foes.Contains(dying.myHealth.alignmentManager.alignment)) { // find the distance distance = Maths.manhattanDistance(dying.transform.position, targetLocation); // don't consume very distant corpses if (distance <= 8f) { // if a closest one hasn't been found yet this is the closest if (closestDying == null) { closestDying = dying; closestDistance = distance; } // otherwise compare distances else { if (distance < closestDistance) { closestDying = dying; closestDistance = distance; } } } } } // consume the closest corpse if (closestDying) { closestDying.setDelays(0f, 0f); corpseConsumed = true; // apply the stats summoner.statList.AddRange(corpseStatList); // create a death vfx Instantiate(spiritEscapePrefab).transform.position = closestDying.transform.position + spiritEscapeOffset; } } float realBloodWraithChance = 0f; if (corpseConsumed) { realBloodWraithChance = bloodWraithChance; } // summon a different type of wraith if (flameWraithChance != 0 || realBloodWraithChance != 0 || putridWraithChance != 0) { float rand = Random.Range(0f, 1f); if (rand < flameWraithChance) { summoner.entity = flameWraithPrefab; } else if (rand < flameWraithChance + realBloodWraithChance) { summoner.entity = bloodWraithPrefab; } else if (rand < flameWraithChance + realBloodWraithChance + putridWraithChance) { summoner.entity = putridWraithPrefab; } } if (targetting == WraithTargetType.onSpot) { StartsTowardsTarget component = abilityObject.GetComponent <StartsTowardsTarget>(); if (component) { component.active = false; } if (summoner) { summoner.distance = 0.5f; } } if (targetting == WraithTargetType.atTarget) { StartsTowardsTarget component = abilityObject.GetComponent <StartsTowardsTarget>(); if (component) { component.active = false; } abilityObject.AddComponent <StartsAtTarget>(); } // delayed wraith casts if (delayedWraiths > 0) { CastAfterDuration cad = abilityObject.AddComponent <CastAfterDuration>(); cad.ability = ability; cad.interval = 0.5f * (1 - reducedWraithInterval); cad.limitCasts = true; cad.remainingCasts = delayedWraiths; DestroyAfterDuration dad = abilityObject.GetComponent <DestroyAfterDuration>(); dad.duration = (0.5f * (1 + delayedWraiths)) * (1f - reducedWraithInterval); SummonWraithMutator mutator = abilityObject.AddComponent <SummonWraithMutator>(); // copy stats mutator.reducedHealthDrain = reducedHealthDrain; mutator.stationary = stationary; mutator.flameWraithChance = flameWraithChance; mutator.bloodWraithChance = realBloodWraithChance; mutator.putridWraithChance = putridWraithChance; // wraith prefabs mutator.flameWraithPrefab = flameWraithPrefab; mutator.bloodWraithPrefab = bloodWraithPrefab; mutator.putridWraithPrefab = putridWraithPrefab; // delayed wraith changes mutator.targetting = WraithTargetType.onSpot; mutator.delayedWraiths = 0; mutator.reducedWraithInterval = 0f; mutator.critFromManaCost = false; mutator.healOnCrit = 0f; // stats and corpse stats (does not consume multiple corpses) mutator.statList.AddRange(statList); if (corpseConsumed) { mutator.statList.AddRange(corpseStatList); } } // change the adapter WraithAdapter adapter = abilityObject.AddComponent <WraithAdapter>(); adapter.reducedHealthDrain = reducedHealthDrain; adapter.stationary = stationary; return(abilityObject); }
public override GameObject Mutate(GameObject abilityObject, Vector3 location, Vector3 targetLocation) { // if this is a meteor shower if (additionalMeteors > 0) { Destroy(abilityObject); abilityObject = Instantiate(AbilityIDList.getAbility(AbilityID.meteorShower).abilityPrefab); abilityObject.transform.position = location; CastAtRandomPointAfterDuration meteorCaster = abilityObject.GetComponent <CastAtRandomPointAfterDuration>(); meteorCaster.duration /= (1 + increasedMeteorFrequency); meteorCaster.remainingCasts += additionalMeteors; meteorCaster.radius *= (1 + increasedShowerRadius); if (line) { StartsAtTarget sat = meteorCaster.GetComponent <StartsAtTarget>(); if (sat) { sat.active = false; Destroy(sat); } AbilityMover mover = Comp <AbilityMover> .GetOrAdd(abilityObject); mover.SetDirection(targetLocation - location); mover.speed = 10 * (1 + increasedShowerRadius); meteorCaster.radius = 0; StartsTowardsTarget stt = abilityObject.AddComponent <StartsTowardsTarget>(); stt.distance = 1f; stt.addWeaponRange = false; } // create a mutator on the meteor shower object MeteorMutator newMutator = abilityObject.AddComponent <MeteorMutator>(); // variables for all damage newMutator.moreDamageInstances = moreDamageInstances; // meteor variables (except use all mana) newMutator.increasedFallSpeed = increasedFallSpeed; newMutator.increasedCastSpeed = increasedCastSpeed; newMutator.shrapnelChance = shrapnelChance; newMutator.increasedShrapnelSpeed = increasedShrapnelSpeed; newMutator.shrapnelPierces = shrapnelPierces; newMutator.replaceFireCircle = replaceFireCircle; // aoe variables newMutator.moreDamageAgainstFullHealth = moreDamageAgainstFullHealth; newMutator.increasedShrapnelDamage = increasedShrapnelDamage; newMutator.increasedStunChance = increasedStunChance; newMutator.moreDamageInstances = new List <float>(); newMutator.moreDamageInstances.AddRange(moreDamageInstances); // apply mana variable once for all meteors if (usesAllMana && myMana) { float totalCost = myMana.getManaCost(ability); totalCost += myMana.currentMana; float proportion = totalCost / myMana.maxMana; newMutator.moreDamageInstances.Add(proportion * 2); myMana.currentMana = 0; } return(abilityObject); } // if this is a regular meteor // apply aoe variables MeteorAoEMutator aoeMutator = abilityObject.AddComponent <MeteorAoEMutator>(); aoeMutator.moreDamageAgainstFullHealth = moreDamageAgainstFullHealth; aoeMutator.increasedStunChance = increasedStunChance; aoeMutator.moreDamageInstances = new List <float>(); aoeMutator.moreDamageInstances.AddRange(moreDamageInstances); // meteor variables if (increasedFallSpeed != 0) { abilityObject.GetComponent <AbilityMover>().speed *= (1 + increasedFallSpeed); } MeteorShrapnelMutator shrapnelMutator = null; if (shrapnelChance > 0) { float rand = Random.Range(0f, 1f); if (rand < shrapnelChance) { CreateAbilityObjectOnDeath caood = abilityObject.AddComponent <CreateAbilityObjectOnDeath>(); caood.abilityToInstantiate = AbilityIDList.getAbility(AbilityID.meteorShrapnel); caood.createAtTarget = true; caood.offset = -caood.GetComponent <LocationDetector>().targetLocationOffset; shrapnelMutator = abilityObject.AddComponent <MeteorShrapnelMutator>(); shrapnelMutator.increasedDamage = increasedShrapnelDamage; shrapnelMutator.increasedSpeed = increasedShrapnelSpeed; shrapnelMutator.pierces = shrapnelPierces; shrapnelMutator.increasedStunChance = increasedStunChance; shrapnelMutator.moreDamageInstances = new List <float>(); shrapnelMutator.moreDamageInstances.AddRange(moreDamageInstances); } } if (replaceFireCircle) { CreateAtTargetLocationOnCreation component = abilityObject.GetComponent <CreateAtTargetLocationOnCreation>(); if (component) { component.objectsToCreate.Clear(); GameObject prefab = PrefabList.getPrefab("EnemyMeteorCircle"); if (prefab) { CreateAtTargetLocationOnCreation.GameObjectHolder holder = new CreateAtTargetLocationOnCreation.GameObjectHolder(); holder.gameObject = prefab; holder.destroyWhenThisDies = true; component.objectsToCreate.Add((holder)); } } } if (usesAllMana && myMana) { float totalCost = myMana.getManaCost(ability); totalCost += myMana.currentMana; float proportion = totalCost / myMana.maxMana; aoeMutator.moreDamageInstances.Add(proportion * 2); if (shrapnelMutator) { shrapnelMutator.moreDamageInstances.Add(proportion * 2); } myMana.currentMana = 0; } return(abilityObject); }