public override void SafeUpdateEquip(Player player) { StarlightPlayer slp = player.GetModPlayer <StarlightPlayer>(); slp.FiftyFiveLeafClover = (short)MathHelper.Clamp(slp.FiftyFiveLeafClover + 1, 0, 600); Helper.BoostAllDamage(player, 0, (int)(((float)slp.FiftyFiveLeafClover / 600f) * 20f)); }
public sealed override bool UseItem(Player player) { StarlightPlayer mp = player.GetModPlayer <StarlightPlayer>(); Projectile.NewProjectile(Main.MouseWorld, Vector2.Zero, ProjectileType, 0, 0, player.whoAmI, mp.GuardBuff, Radius + mp.GuardRad); return(true); }
private void UpdateActiveStyle(StarlightPlayer player) { if (!Main.gameMenu) { activeStyle = lavas.FirstOrDefault(n => n.ChooseLavaStyle()); } }
private void DisableRegen(StarlightPlayer player) { if (Equipped(player.player)) { player.player.GetHandler().StaminaRegenRate = 0; } }
public sealed override void AI() { StarlightPlayer mp = Main.LocalPlayer.GetModPlayer <StarlightPlayer>(); //the local player since ability pickup visuals are clientside if (Visible) { Visuals(); if (Vector2.Distance(Main.screenPosition + new Vector2(Main.screenWidth / 2, Main.screenHeight / 2), npc.Center) <= Main.screenWidth / 2 + 100) //shader { float timer = Math.Abs((float)Math.Sin(StarlightWorld.rottime)); Filters.Scene.Activate("ShockwaveFilter", npc.Center).GetShader().UseProgress(Main.screenWidth / (float)Main.screenHeight).UseIntensity(300).UseDirection(new Vector2(0.005f + timer * 0.03f, 1 * 0.004f - timer * 0.004f)); } if (Vector2.Distance(Main.LocalPlayer.Center, npc.Center) < 200f) //music handling { for (int k = 0; k < Main.musicFade.Length; k++) { if (k == Main.curMusic) { Main.musicFade[k] = Vector2.Distance(Main.LocalPlayer.Center, npc.Center) / 200f; } } } } if (mp.PickupTarget == npc) { PickupVisuals(mp.PickupTimer); //if the player is picking this up, clientside only also } }
public override void Update(Player player, ref int buffIndex) { StarlightPlayer mp = player.GetModPlayer <StarlightPlayer>(); float level; if (mp.ironheartTimer < 1) { mp.ironheartTimer += 0.01f; level = mp.ironheartLevel; player.GetModPlayer <ShieldPlayer>().DontDrainOvershield = true; } else { mp.ironheartTimer *= 1.02f; level = (mp.ironheartLevel + 1) - mp.ironheartTimer; player.GetModPlayer <ShieldPlayer>().OvershieldDrainRate = (int)(2.2f * mp.ironheartTimer); } //Main.NewText(level + " | " + mp.ironheartTimer); //Main.NewText(level); if (level < 0.001f) { player.ClearBuff(Type); mp.ResetIronHeart(); } player.statDefense += (int)level; player.buffTime[buffIndex] = (int)level * 60;//visual time value }
private void ResetEffectsAccessory(StarlightPlayer starlightPlayer) { if (!Equipped(starlightPlayer.player)) { starlightPlayer.FiftyFiveLeafClover = 0; } }
public override void AI() { if (projectile.timeLeft == 600) { StarlightPlayer mp = Main.player[projectile.owner].GetModPlayer <StarlightPlayer>(); if (mp.Empowered) { projectile.frame = 1; //glowColor = new Color(220, 200, 255, 150); lightColor = new Vector3(0.05f, 0.1f, 0.2f); ScaleMult = 1.5f; dustType = DustType <Dusts.BlueStamina>(); projectile.velocity *= 1.25f;//TODO: This could be on on the item's side like the staff does, thats generally the better way empowered = true; } } if (projectile.timeLeft % 25 == 0)//delay between star sounds { Main.PlaySound(SoundID.Item9, projectile.Center); } projectile.rotation += 0.2f; Lighting.AddLight(projectile.Center, lightColor); if (projectile.velocity.Y < 50) { projectile.velocity.Y += 0.25f; } projectile.velocity.X *= 0.995f; }
public override void AI() { projectile.rotation = projectile.velocity.ToRotation() + 1.57f + rotationVar; rotationVar += 0.4f; StarlightPlayer mp = Main.player[projectile.owner].GetModPlayer <StarlightPlayer>(); if (!empowered && mp.empowered) { projectile.frame += 5; lightColor = new Vector3(0.05f, 0.1f, 0.2f); ScaleMult = 2f; dustType = ModContent.DustType <BlueStamina>(); projectile.velocity *= 1.25f;//TODO: This could be on on the item's side like the staff does, thats generally the better way empowered = true; } if (projectile.timeLeft % 25 == 0)//delay between star sounds { Main.PlaySound(SoundID.Item9, projectile.Center); } Lighting.AddLight(projectile.Center, lightColor); projectile.velocity.X *= 0.995f; if (projectile.velocity.Y < 50) { projectile.velocity.Y += 0.25f; } }
public override void UpdateArmorSet(Player player) { player.setBonus = "Picking up mana stars empowers starwood items"; StarlightPlayer mp = player.GetModPlayer <StarlightPlayer>(); if (mp.EmpowermentTimer > 0 && ArmorHelper.IsSetEquipped(this, player)) //checks if complete to disable empowerment if set is removed { for (int k = 0; k < 1; k++) //temp gfx { Dust.NewDustPerfect(player.position + new Vector2(Main.rand.Next(player.width), Main.rand.Next(player.height)), DustType <Dusts.BlueStamina>(), -Vector2.UnitY.RotatedByRandom(0.8f) * Main.rand.NextFloat(1.0f, 1.4f), 0, default, 1.2f);
public override void SafeUpdateEquip(Player player) { StarlightPlayer starlightPlayer = player.GetModPlayer <StarlightPlayer>(); starlightPlayer.FiftyFiveLeafClover = (int)MathHelper.Clamp(starlightPlayer.FiftyFiveLeafClover + 1, 0, 600); float progress = starlightPlayer.FiftyFiveLeafClover / 600f; player.BoostAllDamage(0, (int)(progress * 20)); }
private void ResetLiftAnimation(StarlightPlayer player) { var instance = player.player.HeldItem.modItem; if (instance is Shaker) { if ((instance as Shaker).lifting) { lifting = false; } } }
public sealed override bool CanHitPlayer(Player target, ref int cooldownSlot) { StarlightPlayer mp = target.GetModPlayer <StarlightPlayer>(); if (CanPickup(target) && target.Hitbox.Intersects(npc.Hitbox)) { PickupEffects(target); mp.PickupTarget = npc; } return(false); }
private void SpawnAnimation() //The animation which plays when the boss is spawning { rotationLocked = true; lockedRotation = 1.57f; if (checkSpecificTime(2)) { RandomizeTarget(); //pick a random target so the eyes will follow them startPos = npc.Center; if (IsInsideArena()) { StarlightPlayer mp = Main.LocalPlayer.GetModPlayer <StarlightPlayer>(); mp.ScreenMoveTarget = npc.Center + new Vector2(0, -600); mp.ScreenMoveTime = 650; } music = mod.GetSoundSlot(SoundType.Music, "Sounds/Music/VitricBossAmbient"); SetFrameX(0); SetFrameY(0); lastTwistState = 0; Helper.PlayPitched("VitricBoss/CeirosEarthquake", 0.4f, 0, npc.Center); Helper.PlayPitched("VitricBoss/CeirosRumble", 0.4f, 0, npc.Center); } if (checkSpecificTime(90)) { //Helper.PlayPitched("VitricBoss/StoneBreak", 0.25f, 0.3f, npc.Center); Helper.PlayPitched("VitricBoss/ceiroslidclose", 0.35f, 0.4f, npc.Center); } if (checkSpecificTime(120)) { if (IsInsideArena()) { StarlightPlayer mp = Main.LocalPlayer.GetModPlayer <StarlightPlayer>(); mp.Shake += 10; ZoomHandler.SetZoomAnimation(1.1f, 60); } for (int k = 0; k < 10; k++) { Gore.NewGorePerfect(arena.Center() + new Vector2(Main.rand.Next(-600, 600), -450), Vector2.UnitY * Main.rand.NextFloat(-1, 2), ModGore.GetGoreSlot(AssetDirectory.VitricBoss + "Gore/Cluster" + Main.rand.Next(1, 19))); } for (int k = 0; k < 20; k++) { Dust.NewDustPerfect(arena.Center() + new Vector2(Main.rand.Next(-600, 600), -450), DustID.Stone, Vector2.UnitY * Main.rand.NextFloat(6, 12), 0, default, Main.rand.NextFloat(1, 3));
public override void PreUpdate() { if (player.HeldItem.type == ItemType <Ultrashark>()) { Ultrashark item = (Ultrashark)player.HeldItem.modItem; if (player.releaseUseItem) { item.spinup = 0; } if (item.turretDeployed) { if (player.velocity.X <= -0.2f || player.velocity.X >= 0.2f || player.velocity.Y <= -0.2f || player.velocity.Y >= 0.2f) //cancel if moving { item.turretDeployed = false; item.turretSetup = false; item.standFrame = 0; item.sharkFrame = 0; item.spinup = 0; } } StarlightPlayer sPlayer = player.GetModPlayer <StarlightPlayer>(); if (item.turretDeployed) { if (sPlayer.Timer % 6 == 0) //animate stand { if (item.standFrame < item.standFrameCount - 1) { item.standFrame++; } else if (!item.turretSetup) { item.turretSetup = true; } } if (sPlayer.Timer - item.spinup * 6f == 0) //animate gun { if (item.sharkFrame < item.sharkFrameCount - 1) { item.sharkFrame++; } } } } }
public sealed override bool CanHitPlayer(Player target, ref int cooldownSlot) { StarlightPlayer mp = target.GetModPlayer <StarlightPlayer>(); if (CanPickup(target) && target.Hitbox.Intersects(npc.Hitbox)) { PickupEffects(target); mp.PickupTarget = npc; AbilityProgress packet = new AbilityProgress(target.whoAmI, target.GetHandler()); packet.Send(); } return(false); }
public static void CleanDebuff(Player player, int type) { StarlightPlayer slp = player.GetModPlayer <StarlightPlayer>(); short cooldown = slp.DisinfectCooldown; bool clean = false; List <int> buffs = new List <int>(); for (int i = 0; i < Player.MaxBuffs; i += 1) { if (Helper.IsValidDebuff(player, i)) { if (type == 1) { buffs.Add(i); clean = true; } if (type == 0 && slp.DisinfectCooldown < 1) { player.buffTime[i] = (int)MathHelper.Max(player.buffTime[i] - (60 * 3), 5); clean = true; } } } if (clean) { if (type == 1) { if (buffs.Count > 0) { int buffid = Main.rand.Next(0, buffs.Count); if (SanitizerSpray.SanitizeEnemies(player, player.buffType[buffid], 60 * 5, 300)) { player.buffTime[buffid] = (int)MathHelper.Max(player.buffTime[buffid] - (60 * 5), 5); MakeDusts(new Rectangle((int)player.position.X, (int)player.position.Y, player.width, player.height), 2, Color.Blue, ModContent.DustType <Air>()); } } } else { slp.DisinfectCooldown = 20; MakeDusts(new Rectangle((int)player.position.X, (int)player.position.Y, player.width, player.height), 5, Color.White, ModContent.DustType <Air>()); } Main.PlaySound(SoundID.Item, (int)player.Center.X, (int)player.Center.Y, 100, 0.65f, -Main.rand.NextFloat(0.35f, 0.75f)); } }
public Vector2 getPrismPosition(int currentPrism) { float speed = 80; float dist = 50; if (projectile.minionSlots > 2) { dist += (projectile.minionSlots - 2) * 18; } StarlightPlayer sPlayer = Main.player[projectile.owner].GetModPlayer <StarlightPlayer>(); float rot = currentPrism / (projectile.minionSlots * prismsPerSlot) * 6.28f + sPlayer.Timer % speed / speed * 6.28f; float posX = projectile.Center.X + (float)(Math.Cos(rot) * dist) * 0.25f; float posY = projectile.Center.Y - 10 + (float)(Math.Sin(rot) * dist) * 0.6f; return(new Vector2(posX, posY)); }
public override void SafeUpdateEquip(Player player) { StarlightPlayer modplayer = player.GetModPlayer <StarlightPlayer>(); if (modplayer.Timer - modplayer.LastHit >= 1200) { if (!player.HasBuff(BuffType <GhastlyCloakBuff>())) //activation thing { Main.PlaySound(SoundID.Item123, player.position); for (int i = 0; i <= 30; i++) { Dust.NewDust(player.position, player.width, player.height, 62); } } player.AddBuff(BuffType <GhastlyCloakBuff>(), 2, false); } }
public override bool Shoot(Player player, ref Vector2 position, ref float speedX, ref float speedY, ref int type, ref int damage, ref float knockBack) { StarlightPlayer mp = Main.player[player.whoAmI].GetModPlayer <StarlightPlayer>(); int amount = mp.Empowered ? 4 : 3; int projDamage = (int)(damage * (mp.Empowered ? 1.3f : 1f));//TODO: actually change the item itself's damage float projSpeedX = speedX * (mp.Empowered ? 1.05f : 1f); float projSpeedY = speedY * (mp.Empowered ? 1.05f : 1f); Vector2 staffEndPosition = player.Center + Vector2.Normalize(Main.MouseWorld - position) * 45;//this makes it spawn a distance from the player, useful for other stuff for (int k = 0; k < amount; k++) { Projectile.NewProjectile(staffEndPosition, new Vector2(projSpeedX, projSpeedY).RotatedBy(Main.rand.NextFloat(-0.05f, 0.05f) * (k * 0.10f + 1)) * Main.rand.NextFloat(0.9f, 1.1f) * (k * 0.15f + 1), type, projDamage, knockBack, player.whoAmI, Main.rand.NextFloat(-0.025f, 0.025f), Main.rand.Next(50)); } for (int k = 0; k < 10; k++) { Dust.NewDustPerfect(staffEndPosition + new Vector2(Main.rand.NextFloat(-10f, 10f), Main.rand.NextFloat(-5f, 15f)), mp.Empowered ? ModContent.DustType <Dusts.BlueStamina>() : ModContent.DustType <Dusts.Stamina>(), (new Vector2(projSpeedX, projSpeedY) * Main.rand.NextFloat(0.01f, 0.1f)).RotatedBy(Main.rand.NextFloat(-0.5f, 0.5f)) + player.velocity * 0.5f, 0, default, 1.5f);
protected override void Receive() { Player player = Main.player[fromWho]; StarlightPlayer modPlayer = player.GetModPlayer <StarlightPlayer>(); if (projIdentity == -1) { modPlayer.ModifyHitNPC(player.HeldItem, Main.npc[npcId], ref damage, ref knockback, ref crit); modPlayer.OnHitNPC(player.HeldItem, Main.npc[npcId], damage, knockback, crit); } else { //projectile arrays aren't guarenteed to align so we need to use projectile identity to match Projectile proj = null; for (int i = 0; i < Main.maxProjectiles; i++) { if (Main.projectile[i].identity == projIdentity) { proj = Main.projectile[i]; break; } } if (proj != null) { int hitDirection = 1; //we don't seem to use hitDirection at all for our modifyhitnpc custom code so its not being sent. potential TODO if we ever use hitDirection for some reason. modPlayer.ModifyHitNPCWithProj(proj, Main.npc[npcId], ref damage, ref knockback, ref crit, ref hitDirection); modPlayer.OnHitNPCWithProj(proj, Main.npc[npcId], damage, knockback, crit); } } if (Main.netMode == Terraria.ID.NetmodeID.Server && fromWho != -1) { Send(-1, fromWho, false); } }
public override void AI() { if (projectile.timeLeft == MaxTimeLeft) { StarlightPlayer mp = Main.player[projectile.owner].GetModPlayer <StarlightPlayer>(); if (mp.empowered) { projectile.frame = 1; lightColor = new Vector3(0.05f, 0.1f, 0.2f); counterScore = 2; dustType = ModContent.DustType <Dusts.BlueStamina>(); empowered = true; } } if (projectile.timeLeft % 50 == projectile.ai[1])//delay between star sounds { Main.PlaySound(SoundID.Item9, projectile.Center); } projectile.rotation += 0.3f; Lighting.AddLight(projectile.Center, lightColor); projectile.velocity = projectile.velocity.RotatedBy(Math.Sin(projectile.timeLeft * 0.2f) * projectile.ai[0]); }
public override void UpdateArmorSet(Player player) { player.setBonus = "After five (5) seconds of not taking damage, your next attack will ensnare and cause bleeding."; StarlightPlayer starlightPlayer = player.GetModPlayer <StarlightPlayer>(); //starlightPlayer.ivyArmorComplete = true; }
private void PostMovementUpdate(StarlightPlayer slp) { EngineerArmorPlayer starlightPlayer = slp.player.GetModPlayer <EngineerArmorPlayer>(); starlightPlayer.HandleEngineerArmor(); }
private void ResetInventoryGlow(StarlightPlayer player) { glowStrength = 0; }
public override void AI() { Player projOwner = Main.player[projectile.owner]; projectile.rotation += 0.3f; if (projectile.timeLeft == MaxTimeLeft) { StarlightPlayer mp = Main.player[projectile.owner].GetModPlayer <StarlightPlayer>(); if (mp.empowered) { projectile.frame = 1; lightColor = new Vector3(0.1f, 0.2f, 0.4f); ScaleMult = 3; dustType = DustType <Dusts.BlueStamina>(); empowered = true; } } Lighting.AddLight(projectile.Center, lightColor * 0.5f); switch (projectile.ai[0]) { case 0: //flying outward if (empowered) { projectile.velocity += Vector2.Normalize(Main.MouseWorld - projectile.Center); if (projectile.velocity.Length() > 10) //swap this for shootspeed or something { projectile.velocity = Vector2.Normalize(projectile.velocity) * 10; } } //cap to max speed if (projectile.timeLeft < MaxDistTime) { NextPhase(0); } break; case 1: //has hit something if (projOwner.controlUseItem || projectile.ai[1] >= maxChargeTime - 5) { if (projectile.ai[1] == 0) { Main.PlaySound(mod.GetLegacySoundSlot(SoundType.Custom, "Sounds/ImpactHeal"), projectile.Center); } chargeMult = projectile.ai[1] / (maxChargeTime + 3); projectile.ai[1]++; projectile.velocity *= 0.75f; Lighting.AddLight(projectile.Center, lightColor * chargeMult); if (projectile.ai[1] >= maxChargeTime + 3) //reset stats and start return phase { projectile.position = projectile.Center; projectile.width = 18; projectile.height = 18; projectile.Center = projectile.position; for (int k = 0; k < projectile.oldPos.Length; k++) { projectile.oldPos[k] = projectile.position; } NextPhase(1); } //ai[]s reset here else if (projectile.ai[1] == maxChargeTime) //change hitbox size, stays for 3 frames { projectile.position = projectile.Center; projectile.width = 67 * ScaleMult; projectile.height = 67 * ScaleMult; projectile.Center = projectile.position; for (int k = 0; k < projectile.oldPos.Length; k++) { projectile.oldPos[k] = projectile.position; } } else if (projectile.ai[1] == maxChargeTime - 5) //sfx { Helpers.DustHelper.DrawStar(projectile.Center, dustType, pointAmount: 5, mainSize: 2.25f * ScaleMult, dustDensity: 2, pointDepthMult: 0.3f); Lighting.AddLight(projectile.Center, lightColor * 2); Main.PlaySound(mod.GetLegacySoundSlot(SoundType.Custom, "Sounds/MagicAttack"), projectile.Center); for (int k = 0; k < 50; k++) { Dust.NewDustPerfect(projectile.Center, dustType, Vector2.One.RotatedByRandom(6.28f) * (Main.rand.NextFloat(0.25f, 1.5f) * ScaleMult), 0, default, 1.5f); } }
public override void AI() { Lighting.AddLight(npc.Center, new Vector3(1, 1, 0.8f)); GlobalTimer++; //tick our timer up constantly AttackTimer++; //tick up our attack timer if (npc.ai[0] == (int)OvergrowBossPhase.Struggle) //when the boss is trapped before spawning the first time { if (spawnPoint == Vector2.Zero) { spawnPoint = npc.Center; //sets the boss' home } npc.velocity.Y = (float)Math.Sin((GlobalTimer % 120) / 120f * 6.28f) * 0.6f; if (!Main.npc.Any(n => n.active && n.type == NPCType <OvergrowBossAnchor>())) //once the chains are broken { npc.velocity *= 0; npc.Center = spawnPoint; GlobalTimer = 0; StarlightPlayer mp = Main.LocalPlayer.GetModPlayer <StarlightPlayer>(); mp.ScreenMoveTime = 860; mp.ScreenMoveTarget = npc.Center; mp.ScreenMovePan = npc.Center + new Vector2(0, -100); Phase = (int)OvergrowBossPhase.spawnAnimation; } } if (Phase == (int)OvergrowBossPhase.spawnAnimation) //the boss' spawn animation. { if (GlobalTimer == 1) { music = mod.GetSoundSlot(SoundType.Music, "Sounds/Music/OvergrowBoss"); } if (GlobalTimer <= 120) { npc.position.Y--; } if (GlobalTimer == 120) { StarlightWorld.Flag(WorldFlags.OvergrowBossFree); } if (GlobalTimer == 500) { string message = "Faerie Guardian"; if (Main.rand.Next(10000) == 0) { message = "Titty Elongator"; // Yep } UILoader.GetUIState <TextCard>().Display("Eggshells", message, null, 220); } if (GlobalTimer >= 860) { Phase = (int)OvergrowBossPhase.Setup; } } if (Phase == (int)OvergrowBossPhase.Setup) { npc.boss = true; int index = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, NPCType <OvergrowBossFlail>()); //spawn the flail after intro (Main.npc[index].modNPC as OvergrowBossFlail).parent = this; //set the flail's parent flail = Main.npc[index].modNPC as OvergrowBossFlail; //tells the boss what flail it owns Phase = (int)OvergrowBossPhase.FirstAttack; //move on to the first attack phase GlobalTimer = 0; //reset our timer npc.ai[3] = 0; //reset our attack timer } if (flail == null) { return; //at this point, our boss should have her flail. if for some reason she dosent, this is a safety check } if (Phase == (int)OvergrowBossPhase.FirstAttack) //the first attacking phase { //attack pattern advancement logic if (AttackTimer == 1) { RandomizeTarget(); if (AttackPhase == 1) { AttackPhase++; //tick up an additional time so that we dont use 2 alternate attacks in a row. TODO: Should make a cleaner way to do this. } AttackPhase++; if (AttackPhase == 1 && Main.rand.Next(2) == 0) { AttackPhase++; } if (AttackPhase > 6) { AttackPhase = 0; } if (flail.npc.life <= 1) //move to next phase once the flail is depleated { Phase = (int)OvergrowBossPhase.FirstToss; AttackPhase = 0; ResetAttack(); //foreach (Projectile proj in Main.projectile.Where(p => p.type == ProjectileType<Projectiles.Dummies.OvergrowBossPitDummy>())) proj.ai[1] = 1; //opens the pits } } switch (AttackPhase) //attack pattern { case 0: Phase1Spin(); break; case 1: Phase1Bolts(); break; //______randonly picks between these two case 2: Phase1Trap(); break; //___| case 3: Phase1Toss(); break; case 4: Phase1Toss(); break; case 5: Phase1Bolts(); break; case 6: Phase1Toss(); break; } } if (Phase == (int)OvergrowBossPhase.FirstToss) { RapidToss(); //toss rapidly till thrown into a pit } if (Phase == (int)OvergrowBossPhase.Stun) { if (GlobalTimer == 1) { npc.alpha = 255; for (int k = 0; k < 100; k++) { Dust d = Dust.NewDustPerfect(npc.Center, 1 /*DustType<>()*/, Vector2.One.RotatedByRandom(Math.PI) * Main.rand.NextFloat(5)); d.customData = npc.Center; } npc.Center = spawnPoint + new Vector2(0, 320); flail.npc.ai[0] = 1; } if (GlobalTimer >= 120) { npc.alpha = 0; if (npc.Hitbox.Intersects(flail.npc.Hitbox)) { flail.npc.ai[0] = 0; flail.npc.ai[3] = 1; flail.npc.velocity *= 0; flail.npc.life = flail.npc.lifeMax; flail.npc.dontTakeDamage = false; flail.npc.friendly = false; npc.life -= 20000; Phase = (int)OvergrowBossPhase.SecondAttack; ResetAttack(); CombatText.NewText(npc.Hitbox, Color.Red, 20000, true); Main.PlaySound(SoundID.DD2_BetsyScream, npc.Center); Main.LocalPlayer.GetModPlayer <StarlightPlayer>().Shake += 30; for (int k = 0; k < 100; k++) { Dust d = Dust.NewDustPerfect(flail.npc.Center, DustType <Dusts.Stone>(), Vector2.One.RotatedByRandom(Math.PI) * Main.rand.NextFloat(5)); } } } } }
public override void AI() { //Ticks the timer GlobalTimer++; AttackTimer++; //twisting if (twistTimer < maxTwistTimer) { twistTimer++; } if (twistTimer == maxTwistTimer) { lastTwistState = twistTarget; } //Main AI body.UpdateBody(); //update the physics on the body Lighting.AddLight(npc.Center, new Vector3(1, 0.8f, 0.4f)); //glow if (Phase != (int)AIStates.Leaving && arena != new Rectangle() && !Main.player.Any(n => n.active && n.statLife > 0 && n.Hitbox.Intersects(arena))) //if no valid players are detected { GlobalTimer = 0; Phase = (int)AIStates.Leaving; //begone thot! crystals.ForEach(n => n.ai[2] = 4); crystals.ForEach(n => n.ai[1] = 0); } switch (Phase) { //on spawn effects case (int)AIStates.SpawnEffects: StarlightPlayer mp = Main.LocalPlayer.GetModPlayer <StarlightPlayer>(); mp.ScreenMoveTarget = npc.Center + new Vector2(0, -850); mp.ScreenMoveTime = 600; UILoader.GetUIState <TextCard>().Display(npc.FullName, Main.rand.Next(10000) == 0 ? "Glass tax returns" : "Shattered Sentinel", null, 500); //Screen pan + intro text for (int k = 0; k < Main.maxNPCs; k++) //finds all the large platforms to add them to the list of possible locations for the nuke attack { NPC npc = Main.npc[k]; if (npc?.active == true && (npc.type == NPCType <VitricBossPlatformUp>() || npc.type == NPCType <VitricBossPlatformDown>())) { crystalLocations.Add(npc.Center + new Vector2(0, -48)); } } const int arenaWidth = 1408; const int arenaHeight = 900; arena = new Rectangle((int)npc.Center.X - arenaWidth / 2, (int)npc.Center.Y - 800 - arenaHeight / 2, arenaWidth, arenaHeight); ChangePhase(AIStates.SpawnAnimation, true); break; case (int)AIStates.SpawnAnimation: //the animation that plays while the boss is spawning and the title card is shown if (GlobalTimer == 2) { npc.friendly = true; //so he wont kill you during the animation RandomizeTarget(); //pick a random target so the eyes will follow them } if (GlobalTimer <= 200) { npc.Center += new Vector2(0, -4f); //rise up } if (GlobalTimer > 280) //summon crystal babies { for (int k = 0; k <= 4; k++) { if (GlobalTimer == 280 + k * 30) { Vector2 target = new Vector2(npc.Center.X + (-100 + k * 50), StarlightWorld.VitricBiome.Top * 16 + 1100); int index = NPC.NewNPC((int)target.X, (int)target.Y, NPCType <VitricBossCrystal>(), 0, 2); //spawn in state 2: sandstone forme (Main.npc[index].modNPC as VitricBossCrystal).Parent = this; (Main.npc[index].modNPC as VitricBossCrystal).StartPos = target; (Main.npc[index].modNPC as VitricBossCrystal).TargetPos = npc.Center + new Vector2(0, -120).RotatedBy(6.28f / 4 * k); crystals.Add(Main.npc[index]); //add this crystal to the list of crystals the boss controls } } } if (GlobalTimer > 620) //start the fight { npc.dontTakeDamage = false; //make him vulnerable npc.friendly = false; //and hurt when touched homePos = npc.Center; //set the NPCs home so it can return here after attacks int index = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, NPCType <ArenaBottom>()); (Main.npc[index].modNPC as ArenaBottom).Parent = this; ChangePhase(AIStates.FirstPhase, true); ResetAttack(); } break; case (int)AIStates.FirstPhase: int healthGateAmount = npc.lifeMax / 7; if (npc.life <= npc.lifeMax - (1 + crystals.Count(n => n.ai[0] == 3 || n.ai[0] == 1)) * healthGateAmount && !npc.dontTakeDamage) { npc.dontTakeDamage = true; //boss is immune at phase gate npc.life = npc.lifeMax - (1 + crystals.Count(n => n.ai[0] == 3 || n.ai[0] == 1)) * healthGateAmount - 1; //set health at phase gate Main.PlaySound(SoundID.ForceRoar, npc.Center); } if (AttackTimer == 1) //switching out attacks { if (npc.dontTakeDamage) { AttackPhase = 0; //nuke attack once the boss turns immortal for a chance to break a crystal } else //otherwise proceed with attacking pattern { AttackPhase++; if (AttackPhase > 4) { AttackPhase = 1; } } } switch (AttackPhase) //Attacks { case 0: NukePlatforms(); break; case 1: CrystalCage(); break; case 2: CrystalSmash(); break; case 3: RandomSpikes(); break; case 4: PlatformDash(); break; } break; case (int)AIStates.Anger: //the short anger phase attack when the boss loses a crystal AngerAttack(); break; case (int)AIStates.FirstToSecond: Vignette.offset = (npc.Center - Main.LocalPlayer.Center) * 0.9f; Vignette.extraOpacity = 0.5f + (float)Math.Sin(GlobalTimer / 25f) * 0.2f; if (GlobalTimer == 2) { music = mod.GetSoundSlot(SoundType.Music, "Sounds/Music/GlassBossAmbient"); foreach (NPC crystal in crystals) { crystal.ai[0] = 0; crystal.ai[2] = 5; //turn the crystals to transform mode } } if (GlobalTimer == 120) { SetFrameX(1); foreach (NPC crystal in crystals) //kill all the crystals { crystal.Kill(); } npc.friendly = true; //so we wont get contact damage StarlightPlayer mp2 = Main.LocalPlayer.GetModPlayer <StarlightPlayer>(); mp2.ScreenMoveTarget = npc.Center; mp2.ScreenMoveTime = 660; } if (GlobalTimer > 120 && GlobalTimer < 240) { npc.Center = Vector2.SmoothStep(homePos, homePos + new Vector2(0, 650), (GlobalTimer - 120) / 120f); } if (GlobalTimer > 240 && GlobalTimer < 700 && GlobalTimer % 120 == 0) { StarlightPlayer mp2 = Main.LocalPlayer.GetModPlayer <StarlightPlayer>(); mp2.Shake += (int)(GlobalTimer / 20); } if (GlobalTimer >= 700 && GlobalTimer < 730) { npc.Center = Vector2.SmoothStep(homePos + new Vector2(0, 650), homePos, (GlobalTimer - 700) / 30f); } if (GlobalTimer == 760) { Main.PlaySound(SoundID.Roar, npc.Center); StarlightPlayer mp2 = Main.LocalPlayer.GetModPlayer <StarlightPlayer>(); mp2.Shake += 60; } if (GlobalTimer > 850) { SetFrameX(2); ChangePhase(AIStates.SecondPhase, true); //go on to the next phase ResetAttack(); //reset attack foreach (NPC wall in Main.npc.Where(n => n.modNPC is VitricBackdropLeft)) { wall.ai[1] = 3; //make the walls scroll } foreach (NPC plat in Main.npc.Where(n => n.modNPC is VitricBossPlatformUp)) { plat.ai[0] = 1; //make the platforms scroll } Vignette.visible = true; break; } break; case (int)AIStates.SecondPhase: Vignette.offset = (npc.Center - Main.LocalPlayer.Center) * 0.8f; Vignette.extraOpacity = 0.3f; if (GlobalTimer == 60) { npc.dontTakeDamage = false; //damagable again npc.friendly = false; Vignette.visible = true; } if (GlobalTimer == 1) { music = mod.GetSoundSlot(SoundType.Music, "VortexHasASmallPussy"); //handles the music transition } if (GlobalTimer == 2) { music = mod.GetSoundSlot(SoundType.Music, "Sounds/Music/GlassBoss2"); } if (GlobalTimer > 702 && GlobalTimer < 760) //no fadein { for (int k = 0; k < Main.musicFade.Length; k++) { if (k == Main.curMusic) { Main.musicFade[k] = 1; } } } if (AttackTimer == 1) //switching out attacks { AttackPhase++; if (AttackPhase > 3) { AttackPhase = 0; } } switch (AttackPhase) //switch for crystal behavior { case 0: Volley(); break; case 1: Mines(); break; case 2: Whirl(); break; case 3: Rest(); break; } break; case (int)AIStates.LastStand: if (GlobalTimer == 1) { foreach (NPC npc in Main.npc.Where(n => n.modNPC is VitricBackdropLeft || n.modNPC is VitricBossPlatformUp)) { npc.ai[1] = 4; } Vignette.extraOpacity = 0; startPos = npc.Center; } if (GlobalTimer < 60) { npc.Center = Vector2.SmoothStep(startPos, homePos + new Vector2(0, -100), GlobalTimer / 60f); } if (GlobalTimer == 90) { Twist(30); } if (GlobalTimer > 120 && GlobalTimer <= 140) { glowColor = Color.Lerp(Color.Transparent, Color.White, (GlobalTimer - 120) / 20f); } if (GlobalTimer == 140) { npc.frame.Y += 160; } if (GlobalTimer > 140 && GlobalTimer <= 200) { glowColor = Color.Lerp(Color.White, Color.Red * 0.5f, (GlobalTimer - 140) / 60f); } if (GlobalTimer > 200 && GlobalTimer <= 240) { glowColor = Color.Lerp(Color.Red * 0.5f, Color.Transparent, (GlobalTimer - 200) / 40f); } if (GlobalTimer == 300) { int i = NPC.NewNPC((int)npc.Center.X - 200, (int)npc.Center.Y - 180, NPCType <GlassMinibossHelpful>()); (Main.npc[i].modNPC as GlassMinibossHelpful).parent = this; } if (GlobalTimer > 660) { if (GlobalTimer % 120 == 0) { Main.NewText("ShootFire"); Main.PlaySound(SoundID.DD2_BetsyScream); int i = Projectile.NewProjectile(npc.Center, Vector2.Normalize(Main.player[npc.target].Center - npc.Center) * 3, ProjectileType <FinalFire>(), 100, 0, Main.myPlayer); (Main.projectile[i].modProjectile as FinalFire).parent = this; } } break; case (int)AIStates.Leaving: npc.position.Y += 7; Vignette.visible = false; if (GlobalTimer >= 180) { npc.active = false; //leave foreach (NPC npc in Main.npc.Where(n => n.modNPC is VitricBackdropLeft || n.modNPC is VitricBossPlatformUp)) { npc.active = false; //arena reset } } break; case (int)AIStates.Dying: Vignette.offset = Vector2.Zero; Vignette.extraOpacity = 0.5f + Math.Min(GlobalTimer / 60f, 0.5f); if (GlobalTimer == 60) { Main.PlaySound(mod.GetLegacySoundSlot(SoundType.Custom, "Sounds/GlassBossDeath")); } if (GlobalTimer > 60 && GlobalTimer < 120) { Main.musicFade[Main.curMusic] = 1 - (GlobalTimer - 60) / 60f; } if (GlobalTimer > 120) { Main.musicFade[Main.curMusic] = 0; for (int k = 0; k < 10; k++) { Dust.NewDustPerfect(npc.Center, DustType <Dusts.Sand>(), Vector2.One.RotatedByRandom(6.28f) * Main.rand.NextFloat(10), 40, default, 2); } for (int k = 0; k < 2; k++) { Dust.NewDustPerfect(npc.Center, DustType <Dusts.Starlight>(), Vector2.One.RotatedByRandom(6.28f) * Main.rand.NextFloat(100)); } }
public override void AI() { //Ticks the timer GlobalTimer++; AttackTimer++; if (Phase != (int)AIStates.Leaving && arena != new Rectangle() && !Main.player.Any(n => n.active && n.statLife > 0 && n.Hitbox.Intersects(arena))) //if no valid players are detected { GlobalTimer = 0; Phase = (int)AIStates.Leaving; //begone thot! crystals.ForEach(n => n.ai[2] = 4); crystals.ForEach(n => n.ai[1] = 0); } switch (Phase) { //on spawn effects case (int)AIStates.SpawnEffects: StarlightPlayer mp = Main.LocalPlayer.GetModPlayer <StarlightPlayer>(); mp.ScreenMoveTarget = npc.Center + new Vector2(0, -850); mp.ScreenMoveTime = 600; StarlightRiver.Instance.textcard.Display(npc.FullName, Main.rand.Next(10000) == 0 ? "Glass tax returns" : "Shattered Sentinel", null, 500); //Screen pan + intro text for (int k = 0; k < Main.maxNPCs; k++) //finds all the large platforms to add them to the list of possible locations for the nuke attack { NPC npc = Main.npc[k]; if (npc?.active == true && (npc.type == NPCType <VitricBossPlatformUp>() || npc.type == NPCType <VitricBossPlatformDown>())) { crystalLocations.Add(npc.Center + new Vector2(0, -48)); } } ChangePhase(AIStates.SpawnAnimation, true); break; case (int)AIStates.SpawnAnimation: //the animation that plays while the boss is spawning and the title card is shown if (GlobalTimer == 2) { npc.friendly = true; //so he wont kill you during the animation RandomizeTarget(); //pick a random target so the eyes will follow them } if (GlobalTimer <= 200) { npc.Center += new Vector2(0, -4f); //rise up } if (GlobalTimer > 200 && GlobalTimer <= 300) { npc.scale = 0.5f + (GlobalTimer - 200) / 200f; //grow } if (GlobalTimer > 280) //summon crystal babies { for (int k = 0; k <= 4; k++) { if (GlobalTimer == 280 + k * 30) { Vector2 target = new Vector2(npc.Center.X + (-100 + k * 50), StarlightWorld.VitricBiome.Top * 16 + 1100); int index = NPC.NewNPC((int)target.X, (int)target.Y, NPCType <VitricBossCrystal>(), 0, 2); //spawn in state 2: sandstone forme (Main.npc[index].modNPC as VitricBossCrystal).Parent = this; (Main.npc[index].modNPC as VitricBossCrystal).StartPos = target; (Main.npc[index].modNPC as VitricBossCrystal).TargetPos = npc.Center + new Vector2(0, -120).RotatedBy(6.28f / 4 * k); crystals.Add(Main.npc[index]); //add this crystal to the list of crystals the boss controls } } } if (GlobalTimer > 620) //start the fight { npc.dontTakeDamage = false; //make him vulnerable npc.friendly = false; //and hurt when touched homePos = npc.Center; //set the NPCs home so it can return here after attacks int index = NPC.NewNPC((int)npc.Center.X, (int)npc.Center.Y, NPCType <ArenaBottom>()); (Main.npc[index].modNPC as ArenaBottom).Parent = this; ChangePhase(AIStates.FirstPhase, true); ResetAttack(); const int arenaWidth = 1408; const int arenaHeight = 900; arena = new Rectangle((int)npc.Center.X - arenaWidth / 2, (int)npc.Center.Y - arenaHeight / 2, arenaWidth, arenaHeight); } break; case (int)AIStates.FirstPhase: int healthGateAmount = npc.lifeMax / 7; if (npc.life <= npc.lifeMax - (1 + crystals.Count(n => n.ai[0] == 3 || n.ai[0] == 1)) * healthGateAmount && !npc.dontTakeDamage) { npc.dontTakeDamage = true; //boss is immune at phase gate npc.life = npc.lifeMax - ((1 + crystals.Count(n => n.ai[0] == 3 || n.ai[0] == 1)) * healthGateAmount) - 1; //set health at phase gate Main.PlaySound(SoundID.ForceRoar, npc.Center); } if (AttackTimer == 1) //switching out attacks { if (npc.dontTakeDamage) { AttackPhase = 0; //nuke attack once the boss turns immortal for a chance to break a crystal } else //otherwise proceed with attacking pattern { AttackPhase++; if (AttackPhase > 4) { AttackPhase = 1; } } } switch (AttackPhase) //switch for crystal behavior { case 0: NukePlatforms(); break; case 1: CrystalCage(); break; case 2: CrystalSmash(); break; case 3: RandomSpikes(); break; case 4: PlatformDash(); break; } break; case (int)AIStates.Anger: //the short anger phase attack when the boss loses a crystal AngerAttack(); break; case (int)AIStates.FirstToSecond: if (GlobalTimer == 2) { foreach (NPC crystal in crystals) { crystal.ai[0] = 0; crystal.ai[2] = 5; //turn the crystals to transform mode } } if (GlobalTimer == 120) { SetFrameX(1); foreach (NPC crystal in crystals) //kill all the crystals { crystal.Kill(); } npc.friendly = true; //so we wont get contact damage } if (GlobalTimer > 120) { foreach (Player player in Main.player) { if (Abilities.AbilityHelper.CheckDash(player, npc.Hitbox)) //boss should be dashable now, when dashed: { player.immune = true; player.immuneTime = 60; SetFrameX(2); ChangePhase(AIStates.SecondPhase, true); //go on to the next phase ResetAttack(); //reset attack foreach (NPC wall in Main.npc.Where(n => n.modNPC is VitricBackdropLeft)) { wall.ai[1] = 3; //make the walls scroll } foreach (NPC plat in Main.npc.Where(n => n.modNPC is VitricBossPlatformUp)) { plat.ai[0] = 1; //make the platforms scroll } break; } } } /*if (GlobalTimer > 900) //after waiting too long, wipe all players * { * foreach (Player player in Main.player.Where(n => n.Hitbox.Intersects(arena))) * { * player.KillMe(Terraria.DataStructures.PlayerDeathReason.ByCustomReason(player.name + " was shattered..."), double.MaxValue, 0); * } * ChangePhase(AIStates.Leaving, true); * }*/ break; case (int)AIStates.SecondPhase: if (GlobalTimer == 60) { npc.dontTakeDamage = false; //damagable again npc.friendly = false; } if (GlobalTimer == 1) { music = mod.GetSoundSlot(SoundType.Music, "VortexHasASmallPussy"); //handles the music transition } if (GlobalTimer == 2) { music = mod.GetSoundSlot(SoundType.Music, "Sounds/Music/GlassBossTransition"); } if (GlobalTimer == 701) { music = mod.GetSoundSlot(SoundType.Music, "VortexHasASmallPussy"); } if (GlobalTimer == 702) { music = mod.GetSoundSlot(SoundType.Music, "Sounds/Music/GlassBoss2"); } if (GlobalTimer > 702 && GlobalTimer < 760) //no fadein { for (int k = 0; k < Main.musicFade.Length; k++) { if (k == Main.curMusic) { Main.musicFade[k] = 1; } } } if (AttackTimer == 1) //switching out attacks { AttackPhase++; if (AttackPhase > 3) { AttackPhase = 0; } } switch (AttackPhase) //switch for crystal behavior { case 0: Volley(); break; case 1: Mines(); break; case 2: Whirl(); break; case 3: Rest(); break; } break; case (int)AIStates.Leaving: npc.position.Y += 7; if (GlobalTimer >= 180) { npc.active = false; //leave foreach (NPC npc in Main.npc.Where(n => n.modNPC is VitricBackdropLeft || n.modNPC is VitricBossPlatformUp)) { npc.active = false; //arena reset } } break; case (int)AIStates.Dying: if (GlobalTimer == 1) { foreach (NPC npc in Main.npc.Where(n => n.modNPC is VitricBackdropLeft || n.modNPC is VitricBossPlatformUp)) { npc.ai[1] = 4; } startPos = npc.Center; } if (GlobalTimer < 60) { npc.Center = Vector2.SmoothStep(startPos, homePos, GlobalTimer / 60f); } if (GlobalTimer == 60) { Main.PlaySound(SoundID.DD2_WinScene, npc.Center); //SFX } if (GlobalTimer > 60 && GlobalTimer < 120) { Main.musicFade[Main.curMusic] = 1 - (GlobalTimer - 60) / 60f; } if (GlobalTimer > 120) { Main.musicFade[Main.curMusic] = 0; for (int k = 0; k < 10; k++) { Dust.NewDustPerfect(npc.Center, DustType <Dusts.Sand>(), Vector2.One.RotatedByRandom(6.28f) * Main.rand.NextFloat(10), 40, default, 2); } for (int k = 0; k < 2; k++) { Dust.NewDustPerfect(npc.Center, DustType <Dusts.Starlight>(), Vector2.One.RotatedByRandom(6.28f) * Main.rand.NextFloat(100)); } }
public override void AI() { Lighting.AddLight(projectile.Center, lightColor); AdjustDirection(); Player player = Main.player[projectile.owner]; player.ChangeDir(Main.MouseWorld.X > player.position.X ? 1 : -1); player.heldProj = projectile.whoAmI; player.itemTime = 2; player.itemAnimation = 2; if (projectile.ai[0] == 0) { StarlightPlayer mp = Main.player[projectile.owner].GetModPlayer <StarlightPlayer>(); if (mp.empowered) { empowered = true; } projectile.netUpdate = true; projectile.ai[0]++; } posToBe = player.Center + (direction * 40); Vector2 moveDirection = posToBe - projectile.Center; float speed = (float)Math.Sqrt(moveDirection.Length()); if (speed > 0.05f) { moveDirection.Normalize(); moveDirection *= speed; projectile.velocity = moveDirection; } else { projectile.velocity = Vector2.Zero; } if (player.channel && !released) { projectile.timeLeft = 15; if (charge < 1) { if ((charge + chargeRate) >= 1) { Main.PlaySound(SoundID.MaxMana, (int)projectile.Center.X, (int)projectile.Center.Y, 1, 1, -0.25f); } charge += chargeRate; } } else { if (!released) { player.itemTime = 15; player.itemAnimation = 15; released = true; } if (!fired) { for (int i = 0; i < 3; i++) { Vector2 dustVel = direction.RotatedBy(Main.rand.NextFloat(-0.2f, 0.2f)) * Main.rand.NextFloat(0.8f, 2); if (empowered) { Dust.NewDustPerfect(player.Center + (direction.RotatedBy(-0.06f) * 25), ModContent.DustType <BlueStamina>(), dustVel); } else { Dust.NewDustPerfect(player.Center + (direction.RotatedBy(-0.06f) * 25), ModContent.DustType <Stamina>(), dustVel); } } } if (projectile.timeLeft == 8) { int proj = Projectile.NewProjectile(projectile.Center, direction * Helper.LerpFloat(minVelocity, maxVelocity, charge), ModContent.ProjectileType <StarwoodSlingshotStar>(), (int)Helper.LerpFloat(minDamage, maxDamage, charge), projectile.knockBack, projectile.owner); Main.projectile[proj].frame = (int)(charge * 5) - 1; if ((int)(charge * 5) == 0) { Main.projectile[proj].frame++; } fired = true; } } }