Undodgeable Projectiles
A way to code enemy projectiles that cannot be dodge rolled over.
Difficulty: 1/10
Required code:
public class UndodgeableProjectile : Projectile
{
protected override void OnPreCollision(SpeculativeRigidbody myRigidbody, PixelCollider myCollider, SpeculativeRigidbody otherRigidbody, PixelCollider otherCollider)
{
if (otherRigidbody == Shooter && !allowSelfShooting)
{
PhysicsEngine.SkipCollision = true;
return;
}
if (otherRigidbody.gameActor != null && otherRigidbody.gameActor is PlayerController && (!collidesWithPlayer || (otherRigidbody.gameActor as PlayerController).IsGhost || (otherRigidbody.gameActor as PlayerController).IsEthereal))
{
PhysicsEngine.SkipCollision = true;
return;
}
if (otherRigidbody.aiActor)
{
if (Owner is PlayerController && !otherRigidbody.aiActor.IsNormalEnemy)
{
PhysicsEngine.SkipCollision = true;
return;
}
if (Owner is AIActor && !collidesWithEnemies && otherRigidbody.aiActor.IsNormalEnemy && !otherRigidbody.aiActor.HitByEnemyBullets)
{
PhysicsEngine.SkipCollision = true;
return;
}
}
if (!GameManager.PVP_ENABLED && Owner is PlayerController && otherRigidbody.GetComponent<PlayerController>() != null && !allowSelfShooting)
{
PhysicsEngine.SkipCollision = true;
return;
}
if (GameManager.Instance.InTutorial)
{
PlayerController component = otherRigidbody.GetComponent<PlayerController>();
if (component)
{
if (component.spriteAnimator.QueryInvulnerabilityFrame())
{
GameManager.BroadcastRoomTalkDoerFsmEvent("playerDodgedBullet");
}
else if (component.IsDodgeRolling)
{
GameManager.BroadcastRoomTalkDoerFsmEvent("playerAlmostDodgedBullet");
}
else
{
GameManager.BroadcastRoomTalkDoerFsmEvent("playerDidNotDodgeBullet");
}
}
}
if (collidesWithProjectiles && collidesOnlyWithPlayerProjectiles && otherRigidbody.projectile && !(otherRigidbody.projectile.Owner is PlayerController))
{
PhysicsEngine.SkipCollision = true;
return;
}
}
protected override HandleDamageResult HandleDamage(SpeculativeRigidbody rigidbody, PixelCollider hitPixelCollider, out bool killedTarget, PlayerController player, bool alreadyPlayerDelayed = false)
{
killedTarget = false;
if (rigidbody.ReflectProjectiles)
{
return HandleDamageResult.NO_HEALTH;
}
if (!rigidbody.healthHaver)
{
return HandleDamageResult.NO_HEALTH;
}
if (!alreadyPlayerDelayed && s_delayPlayerDamage && player)
{
return HandleDamageResult.HEALTH;
}
bool flag = !rigidbody.healthHaver.IsDead;
float num = ModifiedDamage;
if (Owner is AIActor && rigidbody && rigidbody.aiActor && (Owner as AIActor).IsNormalEnemy)
{
num = ProjectileData.FixedFallbackDamageToEnemies;
if (rigidbody.aiActor.HitByEnemyBullets)
{
num /= 4f;
}
}
int healthHaverHitCount = (int)ProjectileHealthHaverHitCountInfo.GetValue(this);
if (Owner is PlayerController && m_hasPierced && healthHaverHitCount >= 1)
{
int num2 = Mathf.Clamp(healthHaverHitCount - 1, 0, GameManager.Instance.PierceDamageScaling.Length - 1);
num *= GameManager.Instance.PierceDamageScaling[num2];
}
if (OnWillKillEnemy != null && num >= rigidbody.healthHaver.GetCurrentHealth())
{
OnWillKillEnemy(this, rigidbody);
}
if (rigidbody.healthHaver.IsBoss)
{
num *= BossDamageMultiplier;
}
if (BlackPhantomDamageMultiplier != 1f && rigidbody.aiActor && rigidbody.aiActor.IsBlackPhantom)
{
num *= BlackPhantomDamageMultiplier;
}
bool flag2 = false;
if (DelayedDamageToExploders)
{
flag2 = (rigidbody.GetComponent<ExplodeOnDeath>() && rigidbody.healthHaver.GetCurrentHealth() <= num);
}
if (!flag2)
{
HealthHaver healthHaver = rigidbody.healthHaver;
float damage = num;
Vector2 velocity = specRigidbody.Velocity;
string ownerName = OwnerName;
CoreDamageTypes coreDamageTypes = damageTypes;
DamageCategory damageCategory = (!IsBlackBullet) ? DamageCategory.Normal : DamageCategory.BlackBullet;
healthHaver.ApplyDamage(damage, velocity, ownerName, coreDamageTypes, damageCategory, true, hitPixelCollider, ignoreDamageCaps);
if (player && player.OnHitByProjectile != null)
{
player.OnHitByProjectile(this, player);
}
}
else
{
rigidbody.StartCoroutine((IEnumerator)ProjectileHandleDelayedDamageInfo.Invoke(this, new object[] { rigidbody, num, specRigidbody.Velocity, hitPixelCollider }));
}
if (Owner && Owner is AIActor && player)
{
(Owner as AIActor).HasDamagedPlayer = true;
}
killedTarget = (flag && rigidbody.healthHaver.IsDead);
if (!killedTarget && rigidbody.gameActor != null)
{
if (AppliesPoison && UnityEngine.Random.value < PoisonApplyChance)
{
rigidbody.gameActor.ApplyEffect(healthEffect, 1f, null);
}
if (AppliesSpeedModifier && UnityEngine.Random.value < SpeedApplyChance)
{
rigidbody.gameActor.ApplyEffect(speedEffect, 1f, null);
}
if (AppliesCharm && UnityEngine.Random.value < CharmApplyChance)
{
rigidbody.gameActor.ApplyEffect(charmEffect, 1f, null);
}
if (AppliesFreeze && UnityEngine.Random.value < FreezeApplyChance)
{
rigidbody.gameActor.ApplyEffect(freezeEffect, 1f, null);
}
if (AppliesCheese && UnityEngine.Random.value < CheeseApplyChance)
{
rigidbody.gameActor.ApplyEffect(cheeseEffect, 1f, null);
}
if (AppliesBleed && UnityEngine.Random.value < BleedApplyChance)
{
rigidbody.gameActor.ApplyEffect(bleedEffect, -1f, this);
}
if (AppliesFire && UnityEngine.Random.value < FireApplyChance)
{
rigidbody.gameActor.ApplyEffect(fireEffect, 1f, null);
}
if (AppliesStun && UnityEngine.Random.value < StunApplyChance && rigidbody.gameActor.behaviorSpeculator)
{
rigidbody.gameActor.behaviorSpeculator.Stun(AppliedStunDuration, true);
}
for (int i = 0; i < statusEffectsToApply.Count; i++)
{
rigidbody.gameActor.ApplyEffect(statusEffectsToApply[i], 1f, null);
}
}
ProjectileHealthHaverHitCountInfo.SetValue(this, healthHaverHitCount + 1);
return (!killedTarget) ? HandleDamageResult.HEALTH : HandleDamageResult.HEALTH_AND_KILLED;
}
}To spawn a bullet with this effect:
Last updated
Was this helpful?