public void CrawlerAI(NPC n, float speed, int gravityType = 0, bool useRotation = true, bool fullSpeedOnSlopes = false) { // This AI is based on the vanilla snail AI (because it can crawl on all surfaces) // with some modifications that make it work better on slopes. // To make it work, the NPC needs the same aiStyle value of 67 // which allows it to use the same slope collision checks as that AI. n.ai[2] = 2f; // <-- So don't remove this because of potential shinanigans with vanilla code. // We also have to define our own 'rotation' and 'directionY' variables, because the vanilla code screws with them on slopes. // Also make sure this is run in PreAI and return false so that it doesn't use the full extent of the vanilla AI. float speedCheck = Math.Max(speed, 1f); if (CollideMethods.CheckCollide(n.position + new Vector2(speedCheck * n.direction, 0f), n.width, n.height)) { n.collideX = true; } if (CollideMethods.CheckCollide(n.position + new Vector2(0f, speedCheck * directionY), n.width, n.height)) { n.collideY = true; } if (n.ai[0] == 0f) { n.TargetClosest(true); directionY = 1; n.ai[0] = 1f; n.direction = 1; if (Main.rand.Next(2) == 0) { n.direction = -1; } if (n.direction > 0) { n.spriteDirection = 1; } n.netUpdate = true; } bool flag = false; //if (Main.netMode != 1) //{ if (!n.collideX && !n.collideY) { n.localAI[3] += 1f; if (n.localAI[3] > 5f) { n.ai[3] = 2f; //n.netUpdate = true; } } else { n.localAI[3] = 0f; } //} if (n.ai[3] > 0f) { n.ai[1] = 0f; n.ai[0] = 1f; if (n.velocity.Y > speed && useRotation) { rotation += (float)n.direction * 0.1f; } else { rotation = 0f; } n.spriteDirection = n.direction; n.velocity.X = speed * (float)n.direction; if (gravityType == 0) { directionY = 1; n.noGravity = false; } else if (gravityType == 1) { n.velocity.Y = speed * directionY; } if (n.collideX || n.collideY) { n.ai[3] -= 1f; } } if (n.ai[3] != 0f) { return; } n.noGravity = true; bool flag2 = false; if (CollideMethods.CheckCollide(n.position, n.width, n.height)) { flag2 = true; bool flag3 = false; if (!CollideMethods.CheckCollide(n.position + new Vector2(n.width, 0f), 1, n.height)) { n.direction = 1; } else if (!CollideMethods.CheckCollide(n.position + new Vector2(-1f, 0f), 1, n.height)) { n.direction = -1; } else { n.direction *= -1; flag3 = true; } if (!CollideMethods.CheckCollide(n.position + new Vector2(0f, n.height), n.width, 1)) { directionY = 1; } else if (CollideMethods.CheckCollide(n.position + new Vector2(0f, -1f), n.width, 1) || flag3) { directionY = -1; } else { directionY *= -1; } } else { if (n.ai[1] == 0f) { if (n.collideY) { if (n.ai[0] < 2f) { n.ai[0] = 2f; } } if (!n.collideY && n.ai[0] >= 2f) { n.ai[0] += 1f; if (n.ai[0] > 3f) { n.direction = -n.direction; n.ai[1] = 1f; n.ai[0] = 1f; } } if (n.collideX) { directionY = -directionY; n.ai[1] = 1f; } } else { if (n.collideX) { if (n.ai[0] < 2f) { n.ai[0] = 2f; } } if (!n.collideX && n.ai[0] >= 2f) { n.ai[0] += 1f; if (n.ai[0] > 3f) { directionY = -directionY; n.ai[1] = 0f; n.ai[0] = 1f; } } if (n.collideY) { n.direction = -n.direction; n.ai[1] = 0f; } } } if (!flag && useRotation) { float bottom_rot = 0f; float left_rot = 1.57f; float top_rot = 3.14f; float right_rot = 4.71f; float rot = rotation; if (directionY < 0) { if (n.direction < 0) { if (n.collideX) { rotation = left_rot; n.spriteDirection = -1; } else if (n.collideY) { rotation = top_rot; n.spriteDirection = 1; } } else if (n.collideY) { rotation = top_rot; n.spriteDirection = -1; } else if (n.collideX) { rotation = right_rot; n.spriteDirection = 1; } } else if (n.direction < 0) { if (n.collideY) { rotation = bottom_rot; n.spriteDirection = -1; } else if (n.collideX) { rotation = left_rot; n.spriteDirection = 1; } } else if (n.collideX) { rotation = right_rot; n.spriteDirection = -1; } else if (n.collideY) { rotation = bottom_rot; n.spriteDirection = 1; } float bl_slope_rot = 0.79f; float tl_slope_rot = 2.36f; float tr_slope_rot = 3.93f; float br_slope_rot = 5.50f; float offY = 0f; bool bottom = CollideMethods.CheckCollide(n.position + new Vector2(0f, 2f), n.width, n.height); bool left = CollideMethods.CheckCollide(n.position + new Vector2(-2f, 0f), n.width, n.height); bool top = CollideMethods.CheckCollide(n.position + new Vector2(0f, -2f), n.width, n.height); bool right = CollideMethods.CheckCollide(n.position + new Vector2(2f, 0f), n.width, n.height); if (left) { if (bottom) { rotation = bl_slope_rot; offY = 6f; } if (top) { rotation = tl_slope_rot; offY = 6f; } } if (right) { if (bottom) { rotation = br_slope_rot; offY = 6f; } if (top) { rotation = tr_slope_rot; offY = 6f; } } if (yOffset < offY) { yOffset = Math.Min(yOffset + 1f, offY); } else { yOffset = Math.Max(yOffset - 1f, offY); } float rot2 = rotation; rotation = rot; if ((double)rotation > 6.28) { rotation -= 6.28f; } if (rotation < 0f) { rotation += 6.28f; } float rot3 = Math.Abs(rotation - rot2); float rotRate = 0.1f; if (rotation > rot2) { if ((double)rot3 > 3.14) { rotation += rotRate; } else { rotation -= rotRate; if (rotation < rot2) { rotation = rot2; } } } if (rotation < rot2) { if ((double)rot3 > 3.14) { rotation -= rotRate; } else { rotation += rotRate; if (rotation > rot2) { rotation = rot2; } } } } float speed2 = speed; if (!CollideMethods.CheckCollide(n.position + new Vector2(speedCheck * n.direction, speedCheck * directionY), n.width, n.height) && !fullSpeedOnSlopes) { speed2 = (float)Math.Cos(Math.PI / 4) * speed; } n.velocity.X = speed2 * (float)n.direction; n.velocity.Y = speed2 * (float)directionY; if (flag2) { n.position += n.velocity; } }
public override void AI() { Projectile P = projectile; Player O = Main.player[P.owner]; Vector2 oPos = O.RotatedRelativePoint(O.MountedCenter, true); Lead = Main.projectile[(int)P.ai[0]]; if (!Lead.active || Lead.owner != P.owner || Lead.type != mod.ProjectileType("ChargeLead") || !O.controlUseItem) { P.Kill(); return; } else { if (!initialize) { initialize = true; } if (P.owner == Main.myPlayer) { if (soundInstance == null || soundInstance.State != SoundState.Playing) { Main.PlaySound(SoundLoader.customSoundType, (int)O.position.X, (int)O.position.Y, mod.GetSoundSlot(SoundType.Custom, "Sounds/SolarComboSoundStart")); soundInstance = Main.PlaySound(SoundLoader.customSoundType, (int)O.position.X, (int)O.position.Y, mod.GetSoundSlot(SoundType.Custom, "Sounds/SolarComboSoundLoop")); if (Main.soundVolume > 0f) { soundInstance.Volume = 0f; } soundInstance2 = Main.PlaySound(SoundLoader.customSoundType, (int)O.position.X, (int)O.position.Y, mod.GetSoundSlot(SoundType.Custom, "Sounds/NovaLaserLoop")); } else if (P.numUpdates == 0 && Main.soundVolume > 0f) { soundInstance.Volume = Math.Min(soundInstance.Volume + 0.05f * Main.soundVolume, 0.75f * Main.soundVolume); soundInstance2.Volume = Math.Min(soundInstance2.Volume + 0.05f * Main.soundVolume, 0.75f * Main.soundVolume); } } P.velocity = Vector2.Normalize(Lead.velocity); P.Center = oPos; P.timeLeft = 2; P.rotation = P.velocity.ToRotation() - 1.57f; maxRange = Math.Min(maxRange + 16f, Max_Range); for (P.ai[1] = 0f; P.ai[1] <= maxRange; P.ai[1] += 4f) { Vector2 end = oPos + P.velocity * P.ai[1]; if (CollideMethods.CheckCollide(end, 0, 0)) { P.ai[1] -= 4f; if (num <= 0) { end = oPos + P.velocity * P.ai[1]; int proj = Projectile.NewProjectile(end.X, end.Y, 0f, 0f, mod.ProjectileType("SolarLaserFlameTrail"), P.damage, P.knockBack, P.owner); num = 4; } break; } } if (num > 0 && P.numUpdates == 0) { num--; } float leadDist = Vector2.Distance(oPos, Lead.Center); for (float i = leadDist; i < P.ai[1]; i += P.width) { Vector2 sPos = oPos + P.velocity * i; if (sPos.X > Main.screenPosition.X - 100f && sPos.X < Main.screenPosition.X + Main.screenWidth + 100f && sPos.Y > Main.screenPosition.Y - 100f && sPos.Y < Main.screenPosition.Y + Main.screenHeight + 100f) { if (Main.rand.Next(50) == 0 && P.ai[1] > leadDist) { int numX = 1; if (Main.rand.Next(2) == 0) { numX = -1; } int proj = Projectile.NewProjectile(sPos.X, sPos.Y, P.velocity.X, P.velocity.Y, mod.ProjectileType("SolarLaserFlareShot"), P.damage, P.knockBack, P.owner); Projectile sProj = Main.projectile[proj]; sProj.ai[0] = Lead.whoAmI; sProj.ai[1] = P.whoAmI; sProj.localAI[0] = i; sProj.localAI[1] = (Main.rand.Next(50) + 60) * numX; } if (Main.rand.Next(10) == 0) { float k = Math.Min(i, P.ai[1]); Vector2 dPos = (oPos - (P.Size / 2f) * scaleUp) + P.velocity * k; Main.dust[Dust.NewDust(dPos, (int)((float)P.width * scaleUp), (int)((float)P.width * scaleUp), 6, 0, 0, 100, default(Color), 3f)].noGravity = true; } } } Vector2 dustPos = oPos - (P.Size / 2f) * scaleUp + P.velocity * P.ai[1]; int size = (int)((float)P.width * scaleUp); float num1 = P.velocity.ToRotation() + (Main.rand.Next(2) == 1 ? -1.0f : 1.0f) * 1.57f; float num2 = (float)(Main.rand.NextDouble() * 0.8f + 1.0f); Vector2 dustVel = new Vector2((float)Math.Cos(num1) * num2, (float)Math.Sin(num1) * num2); Dust dust = Main.dust[Dust.NewDust(dustPos, size, size, 6, dustVel.X, dustVel.Y, 100, default(Color), 4f)]; dust.noGravity = true; dust.velocity *= 3f; Color color = MetroidMod.novColor; DelegateMethods.v3_1 = new Vector3(color.R / 255f, color.G / 255f, color.B / 255f); Utils.PlotTileLine(P.Center, P.Center + P.velocity * P.ai[1], 26, DelegateMethods.CastLight); if (P.numUpdates == 0) { scaleUp = Math.Min(scaleUp + 0.1f, 1.7f); //2f); P.frame++; if (P.frame >= Main.projFrames[projectile.type]) { P.frame = 0; } } ChargeLead chLead = (ChargeLead)Lead.modProjectile; chLead.extraScale = 1.125f * scaleUp; } }
public override void AI() { Projectile P = projectile; Player O = Main.player[P.owner]; Vector2 oPos = O.RotatedRelativePoint(O.MountedCenter, true); Lead = Main.projectile[(int)P.ai[0]]; if (!Lead.active || Lead.owner != P.owner || Lead.type != mod.ProjectileType("ChargeLead") || !O.controlUseItem) { P.Kill(); return; } else { if (!initialize) { initialize = true; } if (P.owner == Main.myPlayer) { if (soundInstance == null || soundInstance.State != SoundState.Playing) { soundInstance = Main.PlaySound(SoundLoader.customSoundType, (int)O.position.X, (int)O.position.Y, mod.GetSoundSlot(SoundType.Custom, "Sounds/NovaLaserLoop")); } } P.velocity = Vector2.Normalize(Lead.velocity); P.Center = oPos; P.timeLeft = 2; P.rotation = P.velocity.ToRotation() - 1.57f; maxRange = Math.Min(maxRange + 16f, Max_Range); for (P.ai[1] = 0f; P.ai[1] <= maxRange; P.ai[1] += 4f) { Vector2 end = oPos + P.velocity * P.ai[1]; if (CollideMethods.CheckCollide(end, 0, 0)) { P.ai[1] -= 4f; break; } } float leadDist = Vector2.Distance(oPos, Lead.Center); for (float i = leadDist; i < P.ai[1]; i += P.width) { if (Main.rand.Next(25) == 0) { float k = Math.Min(i, P.ai[1]); Vector2 dPos = (oPos - P.Size / 2) + P.velocity * k; Main.dust[Dust.NewDust(dPos, P.width, P.width, 75, 0, 0, 100, default(Color), 2f)].noGravity = true; } } Vector2 dustPos = oPos + P.velocity * P.ai[1]; float num1 = P.velocity.ToRotation() + (Main.rand.Next(2) == 1 ? -1.0f : 1.0f) * 1.57f; float num2 = (float)(Main.rand.NextDouble() * 0.8f + 1.0f); Vector2 dustVel = new Vector2((float)Math.Cos(num1) * num2, (float)Math.Sin(num1) * num2); Dust dust = Main.dust[Dust.NewDust(dustPos, 0, 0, 75, dustVel.X, dustVel.Y, 100, default(Color), 2f)]; dust.noGravity = true; dust.velocity *= 3f; dust.position = dustPos; Color color = MetroidMod.novColor; DelegateMethods.v3_1 = new Vector3(color.R / 255f, color.G / 255f, color.B / 255f); Utils.PlotTileLine(P.Center, P.Center + P.velocity * P.ai[1], 26, DelegateMethods.CastLight); if (P.numUpdates == 0) { scaleUp = Math.Min(scaleUp + 0.1f, 1f); P.frame++; if (P.frame >= Main.projFrames[projectile.type]) { P.frame = 0; } } ChargeLead chLead = (ChargeLead)Lead.modProjectile; chLead.extraScale = 0.75f * scaleUp; } }