diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..7feab7a1
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,7 @@
+root = true
+
+[*.cs]
+
+#use hard tabs for indentation
+indent_style = tab
+indent_size = 4
\ No newline at end of file
diff --git a/AssPlayer.cs b/AssPlayer.cs
index f6705dfb..3e363169 100644
--- a/AssPlayer.cs
+++ b/AssPlayer.cs
@@ -1,5 +1,4 @@
using AssortedCrazyThings.Base;
-using AssortedCrazyThings.Buffs;
using AssortedCrazyThings.Effects;
using AssortedCrazyThings.Items;
using AssortedCrazyThings.Items.Pets;
@@ -20,812 +19,812 @@
namespace AssortedCrazyThings
{
- [Content(ConfigurationSystem.AllFlags, needsAllToFilter: true)]
- //[LegacyName("AssPlayer")] Maybe rename later
- public sealed class AssPlayer : AssPlayerBase
- {
- public delegate void SlainBossDelegate(Player player, int type);
- public static event SlainBossDelegate OnSlainBoss; //Runs on all sides
-
- public bool everburningCandleBuff = false;
- public bool everburningCursedCandleBuff = false;
- public bool everfrozenCandleBuff = false;
- public bool everburningShadowflameCandleBuff = false;
-
- public bool teleportHome = false;
- public bool canTeleportHome = false;
- public const short TeleportHomeTimerMax = 600; //in seconds //10 ingame minutes
- public short teleportHomeTimer = 0; //gets saved when you relog so you can't cheese it
-
- //TECHNICALLY NOT DEFENSE; YOU JUST GET 1 DAMAGE FROM EVERYTHING FOR A CERTAIN DURATION
- public bool getDefense = false;
- public bool canGetDefense = false;
- public const short GetDefenseTimerMax = 600; //in seconds //10 ingame minutes
- private const short GetDefenseDurationMax = 600; //in ticks //10 ingame seconds
- public short getDefenseDuration = 0;
- public short getDefenseTimer = 0; //gets saved when you relog so you can't cheese it
-
- private int lastSlainBossTimerSeconds = -1; //-1: never slain a boss, otherwise starts at 0 and counts
- private int lastSlainBossTimerInternal = 0; //Used for incrementing the seconds timer
- private int lastSlainBossType = 0; //Does not save
- public bool HasBossSlainTimer => lastSlainBossTimerSeconds != -1;
-
- public bool needsNearbyEnemyNumber = false;
- public int nearbyEnemyNumber = 0; //Impl of vanilla player.accThirdEyeNumber which works for all clients, shorter range
- public int nearbyEnemyTimer = 0;
-
- //soul minion stuff
- public bool soulMinion = false;
- public Item tempSoulMinion = null;
- public SoulType selectedSoulMinionType = SoulType.Dungeon;
-
- public bool slimePackMinion = false;
- public byte selectedSlimePackMinionType = 0;
-
- public byte nextMagicSlimeSlingMinion = 0;
-
- //empowering buff stuff
- public bool empoweringBuff = false;
- private const short empoweringTimerMax = 60; //in seconds //one minute until it caps out (independent of buff duration)
- private short empoweringTimer = 0;
- public static float empoweringTotal = 0.5f; //this gets modified in AssWorld.PreUpdate()
- public float empoweringStep = 0f;
-
- //enhanced hunter potion stuff
- public bool enhancedHunterBuff = false;
-
- //cute slime spawn enable buff
- public bool cuteSlimeSpawnEnable = false;
-
- public bool soulSaviorArmor = false;
-
- public bool wyvernCampfire = false;
-
- public bool droneControllerMinion = false;
-
- public const byte shieldDroneReductionMax = 35;
- public const byte ShieldIncreaseAmount = 7;
- public byte shieldDroneReduction = 0; //percentage * 100
- public float shieldDroneLerpVisual = 0; //percentage
-
- private bool drawEffectsCalledOnce = false;
-
- public bool mouseoveredDresser = false;
-
- ///
- /// Bitfield. Use .HasFlag(DroneType.SomeType) to check if its there or not
- ///
- public DroneType droneControllerUnlocked = DroneType.None;
-
- ///
- /// Contains the DroneType value
- ///
- public DroneType selectedDroneControllerMinionType = DroneType.BasicLaser;
-
- public override void ResetEffects()
- {
- everburningCandleBuff = false;
- everburningCursedCandleBuff = false;
- everfrozenCandleBuff = false;
- everburningShadowflameCandleBuff = false;
- teleportHome = false;
- getDefense = false;
- soulMinion = false;
- tempSoulMinion = null;
- slimePackMinion = false;
- empoweringBuff = false;
- enhancedHunterBuff = false;
- cuteSlimeSpawnEnable = false;
- soulSaviorArmor = false;
- droneControllerMinion = false;
- mouseoveredDresser = false;
-
- needsNearbyEnemyNumber = false;
- }
-
- public bool RightClickPressed { get { return PlayerInput.Triggers.JustPressed.MouseRight; } }
-
- public bool RightClickReleased { get { return PlayerInput.Triggers.JustReleased.MouseRight; } }
-
- public bool LeftClickPressed { get { return PlayerInput.Triggers.JustPressed.MouseLeft; } }
-
- public bool LeftClickReleased { get { return PlayerInput.Triggers.JustReleased.MouseLeft; } }
-
- public override void SaveData(TagCompound tag)
- {
- tag.Add("teleportHomeWhenLowTimer", (int)teleportHomeTimer);
- tag.Add("getDefenseTimer", (int)getDefenseTimer);
- tag.Add("lastSlainBossTimerSeconds", (int)lastSlainBossTimerSeconds);
- tag.Add("droneControllerUnlocked", (byte)droneControllerUnlocked);
- }
-
- public override void LoadData(TagCompound tag)
- {
- teleportHomeTimer = (short)tag.GetInt("teleportHomeWhenLowTimer");
- getDefenseTimer = (short)tag.GetInt("getDefenseTimer");
- string timerKey = "lastSlainBossTimerSeconds";
- if (tag.ContainsKey(timerKey))
- {
- lastSlainBossTimerSeconds = tag.GetInt("lastSlainBossTimerSeconds");
- }
- droneControllerUnlocked = (DroneType)tag.GetByte("droneControllerUnlocked");
- }
-
- //TODO get rid of this, use manual packets since setting those values happens in a singular place
- public override void clientClone(ModPlayer clientClone)
- {
- AssPlayer clone = clientClone as AssPlayer;
- clone.shieldDroneReduction = shieldDroneReduction;
- //Needs syncing because spawning drone parts depends on this serverside (See GeneralGlobalNPC.NPCLoot)
- clone.droneControllerUnlocked = droneControllerUnlocked;
- }
-
- public override void SendClientChanges(ModPlayer clientPlayer)
- {
- AssPlayer clone = clientPlayer as AssPlayer;
- if (clone.shieldDroneReduction != shieldDroneReduction ||
- clone.droneControllerUnlocked != droneControllerUnlocked)
- {
- SendClientChangesPacket();
- }
- }
-
- ///
- /// Things that are sent to the server that are needed on-change
- ///
- public void SendClientChangesPacket(int toClient = -1, int ignoreClient = -1)
- {
- if (Main.netMode != NetmodeID.SinglePlayer)
- {
- ModPacket packet = Mod.GetPacket();
- packet.Write((byte)AssMessageType.ClientChangesAssPlayer);
- packet.Write((byte)Player.whoAmI);
- packet.Write((byte)shieldDroneReduction);
- packet.Write((byte)droneControllerUnlocked);
- packet.Send(toClient, ignoreClient);
- }
- }
-
- public override void SyncPlayer(int toWho, int fromWho, bool newPlayer)
- {
- ModPacket packet = Mod.GetPacket();
- packet.Write((byte)AssMessageType.SyncAssPlayer);
- packet.Write((byte)Player.whoAmI);
-
- //Actual data here
- packet.Write((byte)shieldDroneReduction);
- packet.WriteVarInt(lastSlainBossTimerSeconds);
- packet.WriteVarInt(lastSlainBossType);
-
- packet.Send(toWho, fromWho);
- }
-
- public void ReceiveSyncPlayer(BinaryReader reader)
- {
- shieldDroneReduction = reader.ReadByte();
- lastSlainBossTimerSeconds = reader.ReadVarInt();
- lastSlainBossType = reader.ReadVarInt();
- }
-
- public override void OnEnterWorld(Player player)
- {
- SendClientChangesPacket();
- }
-
- ///
- /// Resets the empowering timer from the Empowering Buff, spawns dust, sends sync
- ///
- public void ResetEmpoweringTimer(bool fromServer = false)
- {
- if (empoweringBuff && !Player.HasBuff(BuffID.ShadowDodge))
- {
- for (int i = 0; i < empoweringTimer; i++)
- {
- Dust dust = Dust.NewDustPerfect(Player.Center, 135, new Vector2(Main.rand.NextFloat(-3f, 3f), Main.rand.NextFloat(-3f, 3f)) + (new Vector2(Main.rand.Next(-1, 1), Main.rand.Next(-1, 1)) * ((6 * empoweringTimer) / empoweringTimerMax)), 26, Color.White, Main.rand.NextFloat(1.5f, 2.4f));
- dust.noLight = true;
- dust.noGravity = true;
- dust.fadeIn = Main.rand.NextFloat(1f, 2.3f);
- }
- empoweringTimer = 0;
-
- if (Main.netMode == NetmodeID.MultiplayerClient && !fromServer)
- {
- ModPacket packet = Mod.GetPacket();
- packet.Write((byte)AssMessageType.ResetEmpoweringTimerpvp);
- packet.Write((byte)Player.whoAmI);
- packet.Send(); //send to server
- }
- }
- }
-
- ///
- /// Decreases damage based on current shield level from the Shield Drone, spawns dust
- ///
- ///
- public void DecreaseDroneShield(ref int damage)
- {
- if (shieldDroneReduction > 0)
- {
- for (int i = 0; i < shieldDroneReduction / 2; i++)
- {
- Dust dust = Dust.NewDustPerfect(Player.Center, 135, new Vector2(Main.rand.NextFloat(-3f, 3f), Main.rand.NextFloat(-3f, 3f)) + new Vector2(Main.rand.Next(-1, 1), Main.rand.Next(-1, 1)), 26, Color.White, Main.rand.NextFloat(1.5f, 2.4f));
- dust.noLight = true;
- dust.noGravity = true;
- dust.fadeIn = Main.rand.NextFloat(1f, 2.3f);
- }
-
- damage = (int)(damage * ((100 - shieldDroneReduction) / 100f));
- if (Main.netMode != NetmodeID.Server && Main.myPlayer == Player.whoAmI) shieldDroneReduction -= ShieldIncreaseAmount; //since this is only set clientside by the projectile and synced by packets
- }
- }
-
- ///
- /// Sets the isTemp on the projectile so it behaves differently
- ///
- private void PreSyncSoulTemp(Projectile proj)
- {
- if (!ContentConfig.Instance.Bosses)
- {
- return;
- }
-
- if (proj.ModProjectile is CompanionDungeonSoulMinionBase soul)
- {
- soul.isTemp = true;
- }
- }
-
- ///
- /// Spawns the temporary soul when wearing the accessory that allows it
- ///
- private void SpawnSoulTemp()
- {
- if (!ContentConfig.Instance.Bosses)
- {
- return;
- }
-
- if (tempSoulMinion != null && !tempSoulMinion.IsAir && Player.whoAmI == Main.myPlayer)
- {
- bool checkIfAlive = false;
- int spawnedType = Main.hardMode ? ModContent.ProjectileType() : ModContent.ProjectileType();
- int spawnedDamage = Main.hardMode ? (int)(EverhallowedLantern.BaseDmg * 1.1f * 2f) : ((EverhallowedLantern.BaseDmg / 2 - 1) * 2);
- for (int i = 0; i < Main.maxProjectiles; i++)
- {
- if (Main.projectile[i].active && Main.projectile[i].owner == Player.whoAmI && Main.projectile[i].type == spawnedType)
- {
- if (Main.projectile[i].minionSlots == 0f) //criteria for temp, is set by isTemp
- {
- checkIfAlive = true;
- break;
- }
- }
- }
-
- if (!checkIfAlive)
- {
- AssUtils.NewProjectile(Player.GetProjectileSource_Item(tempSoulMinion), Player.Center.X, Player.Center.Y, -Player.velocity.X, Player.velocity.Y - 6f, spawnedType, spawnedDamage, EverhallowedLantern.BaseKB, preSync: PreSyncSoulTemp);
- }
- }
- }
-
- ///
- /// Upon Soul Harvester death, convert all inert souls in inventory
- ///
- public void ConvertInertSoulsInventory()
- {
- if (!ContentConfig.Instance.Bosses)
- {
- return;
- }
-
- //this gets called once on server side for all players, and then each player calls it on itself client side
- int tempStackCount;
- int itemTypeOld = ModContent.ItemType();
- int itemTypeNew = ModContent.ItemType(); //version that is used in crafting
-
- Item[][] inventoryArray = { Player.inventory, Player.bank.item, Player.bank2.item, Player.bank3.item, Player.bank4.item }; //go though player inv
- for (int y = 0; y < inventoryArray.Length; y++)
- {
- for (int e = 0; e < inventoryArray[y].Length; e++)
- {
- Item item = inventoryArray[y][e];
- if (item.type == itemTypeOld) //find inert soul
- {
- tempStackCount = item.stack;
- item.SetDefaults(itemTypeNew); //override with awakened
- item.stack = tempStackCount;
- }
- }
- }
-
- //trash slot
- Item trashItem = Player.trashItem;
- if (trashItem.type == itemTypeOld)
- {
- tempStackCount = trashItem.stack;
- trashItem.SetDefaults(itemTypeNew);
- trashItem.stack = tempStackCount;
- }
-
- //mouse item
- Item mouseItem = Main.mouseItem;
- if (Main.netMode != NetmodeID.Server && mouseItem.type == itemTypeOld)
- {
- tempStackCount = mouseItem.stack;
- mouseItem.SetDefaults(itemTypeNew);
- mouseItem.stack = tempStackCount;
- }
- }
-
- private void UpdateTeleportHomeWhenLow()
- {
- //this code runs even when the accessory is not equipped
- canTeleportHome = teleportHomeTimer <= 0;
-
- if (!canTeleportHome && Main.GameUpdateCount % 60 == 59)
- {
- teleportHomeTimer--;
- }
- }
-
- private void UpdateGetDefenseWhenLow()
- {
- //this code runs even when the accessory is not equipped
- canGetDefense = getDefenseTimer <= 0;
-
- if (!canGetDefense && Main.GameUpdateCount % 60 == 59)
- {
- getDefenseTimer--;
- }
-
- if (getDefenseDuration != 0)
- {
- getDefenseDuration--;
- }
- }
-
- ///
- /// Sets some variables related to the Empowering Buff
- ///
- private void Empower()
- {
- if (empoweringBuff)
- {
- if (Main.GameUpdateCount % 60 == 0)
- {
- if (empoweringTimer < empoweringTimerMax)
- {
- empoweringTimer++;
- empoweringStep = (empoweringTimer * empoweringTotal) / empoweringTimerMax;
- }
- }
- }
- else
- {
- empoweringStep = 0f;
- empoweringTimer = 0;
- }
- }
-
- private bool GetDefense(double damage)
- {
- if (getDefense)
- {
- if (canGetDefense)
- {
- Player.statLife += (int)damage;
- Player.AddBuff(BuffID.RapidHealing, 600);
- CombatText.NewText(Player.getRect(), CombatText.HealLife, "Defense increased");
-
- getDefenseTimer = GetDefenseTimerMax;
- getDefenseDuration = GetDefenseDurationMax;
- return false;
- }
- }
- return true;
- }
-
- private bool TeleportHome(double damage)
- {
- if (teleportHome)
- {
- if (canTeleportHome && Player.whoAmI == Main.myPlayer)
- {
- Player.RemoveAllGrapplingHooks();
-
- //inserted before player.Spawn()
- Player.statLife += (int)damage;
-
- Player.Spawn(PlayerSpawnContext.RecallFromItem);
- for (int i = 0; i < 70; i++)
- {
- Dust.NewDust(Player.position, Player.width, Player.height, 15, 0f, 0f, 150, default(Color), 1.5f);
- }
- //end
-
- Player.AddBuff(BuffID.RapidHealing, 300, false);
-
- NetMessage.SendData(MessageID.PlayerControls, number: Player.whoAmI);
-
- teleportHomeTimer = TeleportHomeTimerMax;
- return false;
- }
- }
- return true;
- }
-
- private void ApplyCandleDebuffs(Entity victim)
- {
- if (victim is NPC npc)
- {
- if (everburningCandleBuff) npc.AddBuff(BuffID.OnFire, 120);
- if (everburningCursedCandleBuff) npc.AddBuff(BuffID.CursedInferno, 120);
- if (everfrozenCandleBuff) npc.AddBuff(BuffID.Frostburn, 120);
- if (everburningShadowflameCandleBuff) npc.AddBuff(BuffID.ShadowFlame, 60);
- }
- //else if (victim is Player)
- }
-
- #region CircleUI
-
- ///
- /// Contains a list of CircleUIHandlers that are used in CircleUIStart/End in Mod
- ///
- public List CircleUIList;
-
- public override void Initialize()
- {
- teleportHome = false;
- teleportHomeTimer = 0;
- getDefense = false;
- getDefenseDuration = 0;
- getDefenseTimer = 0;
- lastSlainBossTimerSeconds = -1;
- tempSoulMinion = null;
- selectedSoulMinionType = SoulType.Dungeon;
- selectedSlimePackMinionType = 0;
- nextMagicSlimeSlingMinion = 0;
- empoweringTimer = 0;
- empoweringStep = 0f;
- shieldDroneReduction = 0;
- shieldDroneLerpVisual = 0;
- drawEffectsCalledOnce = false;
-
- //needs to call new List() since Initialize() is called per player in the player select screen
- CircleUIList = new List();
-
- if (ContentConfig.Instance.Weapons)
- {
- CircleUIList.AddRange(new List
- {
- new CircleUIHandler(
- triggerItem: ModContent.ItemType(),
- condition: () => true,
- uiConf: SlimeHandlerKnapsack.GetUIConf,
- onUIStart: () => selectedSlimePackMinionType,
- onUIEnd: delegate
- {
- selectedSlimePackMinionType = (byte)CircleUI.returned;
- AssUtils.UIText("Selected: " + (selectedSlimePackMinionType == 0 ? "Default" : (selectedSlimePackMinionType == 1 ? "Assorted" : "Spiked")), CombatText.HealLife);
- },
- triggerLeft: false
- ),
- new CircleUIHandler(
- triggerItem: ModContent.ItemType(),
- condition: () => true,
- uiConf: DroneController.GetUIConf,
- onUIStart: delegate
- {
- if (Utils.IsPowerOfTwo((int)selectedDroneControllerMinionType))
- {
- return (int)Math.Log((int)selectedDroneControllerMinionType, 2);
- }
- return 0;
- },
- onUIEnd: delegate
- {
- selectedDroneControllerMinionType = (DroneType)(byte)Math.Pow(2, CircleUI.returned);
- AssUtils.UIText("Selected: " + DroneController.GetDroneData(selectedDroneControllerMinionType).Name, CombatText.HealLife);
- },
- triggerLeft: false
- )}
- );
- }
-
- if (ContentConfig.Instance.Bosses)
- {
- CircleUIList.Add(new CircleUIHandler(
- triggerItem: ModContent.ItemType(),
- condition: () => true,
- uiConf: EverhallowedLantern.GetUIConf,
- onUIStart: delegate
- {
- if (Utils.IsPowerOfTwo((int)selectedSoulMinionType))
- {
- return (int)Math.Log((int)selectedSoulMinionType, 2);
- }
- return 0;
- },
- onUIEnd: delegate
- {
- selectedSoulMinionType = (SoulType)(byte)Math.Pow(2, CircleUI.returned);
- AssUtils.UIText("Selected: " + EverhallowedLantern.GetSoulData(selectedSoulMinionType).Name, CombatText.HealLife);
- },
- triggerLeft: false
- ));
- }
-
- // after filling the list, set the trigger list
- for (int i = 0; i < CircleUIList.Count; i++)
- {
- CircleUIList[i].AddTriggers();
- }
- }
- #endregion
-
- ///
- /// Get proper SpriteEffects flags based on player status
- ///
- private static SpriteEffects GetSpriteEffects(Player player)
- {
- if (player.gravDir == 1f)
- {
- if (player.direction == 1)
- {
- return SpriteEffects.None;
- }
- else
- {
- return SpriteEffects.FlipHorizontally;
- }
- }
- else
- {
- if (player.direction == 1)
- {
- return SpriteEffects.FlipVertically;
- }
- else
- {
- return SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically;
- }
- }
- }
-
- public void SlainBoss(int type)
- {
- lastSlainBossTimerSeconds = 0;
- lastSlainBossType = type;
-
- OnSlainBoss?.Invoke(Player, type);
-
- if (Main.netMode == NetmodeID.Server)
- {
- ModPacket packet = Mod.GetPacket();
- packet.Write((byte)AssMessageType.SlainBoss);
- packet.WriteVarInt(lastSlainBossType);
- packet.Send(Player.whoAmI);
- }
- }
-
- public bool HasSlainBossSecondsAgo(int timeInSeconds)
- {
- return HasBossSlainTimer && lastSlainBossTimerSeconds < timeInSeconds;
- }
-
- public void UpdateSlainBossTimer()
- {
- if (HasBossSlainTimer)
- {
- lastSlainBossTimerInternal++;
- if (lastSlainBossTimerInternal >= 60)
- {
- lastSlainBossTimerInternal = 0;
-
- lastSlainBossTimerSeconds++;
- }
- }
- }
-
- public void UpdateNearbyEnemies()
- {
- float distSQ = 600 * 600;
- if (nearbyEnemyTimer == 0)
- {
- nearbyEnemyNumber = 0;
- nearbyEnemyTimer = 15;
- for (int l = 0; l < Main.maxNPCs; l++)
- {
- NPC npc = Main.npc[l];
- if (npc.active && !npc.friendly && npc.damage > 0 && npc.lifeMax > 5 && !npc.dontCountMe && (npc.Center - Player.Center).LengthSquared() < distSQ)
- {
- nearbyEnemyNumber++;
- }
- }
- }
- else
- {
- nearbyEnemyTimer--;
- }
- }
-
- public override void DrawEffects(PlayerDrawSet drawInfo, ref float r, ref float g, ref float b, ref float a, ref bool fullBright)
- {
- Player drawPlayer = drawInfo.drawPlayer;
- if (!drawEffectsCalledOnce)
- {
- drawEffectsCalledOnce = true;
- }
- else
- {
- return;
- }
- if (Main.gameMenu) return;
-
- //Other code
-
- //if (!PlayerLayer.MiscEffectsBack.visible) return;
-
- if (shieldDroneReduction > 0)
- {
- Color outer = Color.White;
- Color inner = new Color(0x03, 0xFE, 0xFE);
-
- float ratio = shieldDroneReduction / 100f;
- if (shieldDroneLerpVisual < ratio)
- {
- shieldDroneLerpVisual += 0.01f;
- }
- if (shieldDroneLerpVisual > ratio) shieldDroneLerpVisual = ratio;
-
- outer *= shieldDroneLerpVisual;
- inner *= shieldDroneLerpVisual;
- Lighting.AddLight(drawPlayer.Center, inner.ToVector3());
-
- float alpha = (255 - drawPlayer.immuneAlpha) / 255f;
- outer *= alpha;
- inner *= alpha;
- Effect shader = ShaderManager.SetupCircleEffect(new Vector2((int)drawPlayer.Center.X, (int)drawPlayer.Center.Y + drawPlayer.gfxOffY), 2 * 16, outer, inner);
-
- ShaderManager.ApplyToScreenOnce(Main.spriteBatch, shader);
- }
- }
-
- public override void ModifyHitByProjectile(Projectile proj, ref int damage, ref bool crit)
- {
- DecreaseDroneShield(ref damage);
-
- ResetEmpoweringTimer();
-
- SpawnSoulTemp();
- }
-
- public override void ModifyHitByNPC(NPC npc, ref int damage, ref bool crit)
- {
- DecreaseDroneShield(ref damage);
-
- ResetEmpoweringTimer();
-
- SpawnSoulTemp();
- }
-
- public override void ModifyHitNPC(Item item, NPC target, ref int damage, ref float knockback, ref bool crit)
- {
- if (!Main.rand.NextBool(5)) return;
- ApplyCandleDebuffs(target);
- }
-
- public override void ModifyHitNPCWithProj(Projectile proj, NPC target, ref int damage, ref float knockback, ref bool crit, ref int hitDirection)
- {
- if (!Main.rand.NextBool(5)) return;
- if (proj.minion && !Main.rand.NextBool(5)) return;
- ApplyCandleDebuffs(target);
- }
-
- public override void ModifyHitPvp(Item item, Player target, ref int damage, ref bool crit)
- {
- //ApplyCandleDebuffs(target);
- AssPlayer assPlayer = target.GetModPlayer();
- assPlayer.ResetEmpoweringTimer();
-
- assPlayer.SpawnSoulTemp();
- }
-
- public override void ModifyHitPvpWithProj(Projectile proj, Player target, ref int damage, ref bool crit)
- {
- //ApplyCandleDebuffs(target);
- AssPlayer assPlayer = target.GetModPlayer();
- assPlayer.ResetEmpoweringTimer();
-
- assPlayer.SpawnSoulTemp();
- }
-
- public override void ModifyWeaponDamage(Item item, ref StatModifier damage)
- {
- if (empoweringBuff && !item.CountsAsClass(DamageClass.Summon) && item.damage > 0) damage += empoweringStep; //summon damage gets handled in EmpoweringBuffGlobalProjectile
- }
-
- public override void ModifyWeaponCrit(Item item, ref float crit)
- {
- crit += 10 * empoweringStep;
- }
-
- public override bool PreKill(double damage, int hitDirection, bool pvp, ref bool playSound, ref bool genGore, ref PlayerDeathReason damageSource)
- {
- //getDefense before teleportHome (so you don't teleport BEFORE you gain the defense)
-
- if (!GetDefense(damage)) return false;
-
- if (!TeleportHome(damage)) return false;
-
- return base.PreKill(damage, hitDirection, pvp, ref playSound, ref genGore, ref damageSource);
- }
-
- public override bool PreHurt(bool pvp, bool quiet, ref int damage, ref int hitDirection, ref bool crit, ref bool customDamage, ref bool playSound, ref bool genGore, ref PlayerDeathReason damageSource)
- {
- if (getDefenseDuration != 0) damage = 1;
-
- DecreaseDroneShield(ref damage);
-
- if (wyvernCampfire && damageSource.SourceProjectileType == ProjectileID.HarpyFeather)
- {
- hitDirection = 0; //this cancels knockback
- }
-
- return base.PreHurt(pvp, quiet, ref damage, ref hitDirection, ref crit, ref customDamage, ref playSound, ref genGore, ref damageSource);
- }
-
- public override void CatchFish(FishingAttempt attempt, ref int itemDrop, ref int npcSpawn, ref AdvancedPopupRequest sonar, ref Vector2 sonarPosition)
- {
- bool inWater = !attempt.inHoney && !attempt.inLava;
-
- if (attempt.waterTilesCount < attempt.waterNeededToFish)
- {
- return;
- }
-
- if (ContentConfig.Instance.OtherPets)
- {
- //Match Zephyr Fish conditions
- if (attempt.legendary && !attempt.crate && inWater)
- {
- if (((int)(Player.Center.X / 16) < Main.maxTilesX * 0.08f || (int)(Player.Center.X / 16) > Main.maxTilesX * 0.92f) /*&& Main.rand.Next(1) == 0*/) //10 times more likely than zephyr fish makes it about as rare as reaver shark
- {
- itemDrop = ModContent.ItemType();
- return;
- }
- }
- }
- }
-
- public override void PostUpdateBuffs()
- {
- UpdateTeleportHomeWhenLow();
-
- UpdateGetDefenseWhenLow();
-
- Empower();
-
- UpdateSlainBossTimer();
- }
-
- public override void PreUpdate()
- {
- if (Main.netMode != NetmodeID.Server)
- {
- if (drawEffectsCalledOnce)
- {
- drawEffectsCalledOnce = false;
- }
-
- if (Main.myPlayer == Player.whoAmI && ContentConfig.Instance.Weapons)
- {
- if (Player.ownedProjectileCounts[DroneController.GetDroneData(DroneType.Shield).ProjType] < 1) shieldDroneReduction = 0;
- }
- }
-
- UpdateNearbyEnemies();
- }
- }
+ [Content(ConfigurationSystem.AllFlags, needsAllToFilter: true)]
+ //[LegacyName("AssPlayer")] Maybe rename later
+ public sealed class AssPlayer : AssPlayerBase
+ {
+ public delegate void SlainBossDelegate(Player player, int type);
+ public static event SlainBossDelegate OnSlainBoss; //Runs on all sides
+
+ public bool everburningCandleBuff = false;
+ public bool everburningCursedCandleBuff = false;
+ public bool everfrozenCandleBuff = false;
+ public bool everburningShadowflameCandleBuff = false;
+
+ public bool teleportHome = false;
+ public bool canTeleportHome = false;
+ public const short TeleportHomeTimerMax = 600; //in seconds //10 ingame minutes
+ public short teleportHomeTimer = 0; //gets saved when you relog so you can't cheese it
+
+ //TECHNICALLY NOT DEFENSE; YOU JUST GET 1 DAMAGE FROM EVERYTHING FOR A CERTAIN DURATION
+ public bool getDefense = false;
+ public bool canGetDefense = false;
+ public const short GetDefenseTimerMax = 600; //in seconds //10 ingame minutes
+ private const short GetDefenseDurationMax = 600; //in ticks //10 ingame seconds
+ public short getDefenseDuration = 0;
+ public short getDefenseTimer = 0; //gets saved when you relog so you can't cheese it
+
+ private int lastSlainBossTimerSeconds = -1; //-1: never slain a boss, otherwise starts at 0 and counts
+ private int lastSlainBossTimerInternal = 0; //Used for incrementing the seconds timer
+ private int lastSlainBossType = 0; //Does not save
+ public bool HasBossSlainTimer => lastSlainBossTimerSeconds != -1;
+
+ public bool needsNearbyEnemyNumber = false;
+ public int nearbyEnemyNumber = 0; //Impl of vanilla player.accThirdEyeNumber which works for all clients, shorter range
+ public int nearbyEnemyTimer = 0;
+
+ //soul minion stuff
+ public bool soulMinion = false;
+ public Item tempSoulMinion = null;
+ public SoulType selectedSoulMinionType = SoulType.Dungeon;
+
+ public bool slimePackMinion = false;
+ public byte selectedSlimePackMinionType = 0;
+
+ public byte nextMagicSlimeSlingMinion = 0;
+
+ //empowering buff stuff
+ public bool empoweringBuff = false;
+ private const short empoweringTimerMax = 60; //in seconds //one minute until it caps out (independent of buff duration)
+ private short empoweringTimer = 0;
+ public static float empoweringTotal = 0.5f; //this gets modified in AssWorld.PreUpdate()
+ public float empoweringStep = 0f;
+
+ //enhanced hunter potion stuff
+ public bool enhancedHunterBuff = false;
+
+ //cute slime spawn enable buff
+ public bool cuteSlimeSpawnEnable = false;
+
+ public bool soulSaviorArmor = false;
+
+ public bool wyvernCampfire = false;
+
+ public bool droneControllerMinion = false;
+
+ public const byte shieldDroneReductionMax = 35;
+ public const byte ShieldIncreaseAmount = 7;
+ public byte shieldDroneReduction = 0; //percentage * 100
+ public float shieldDroneLerpVisual = 0; //percentage
+
+ private bool drawEffectsCalledOnce = false;
+
+ public bool mouseoveredDresser = false;
+
+ ///
+ /// Bitfield. Use .HasFlag(DroneType.SomeType) to check if its there or not
+ ///
+ public DroneType droneControllerUnlocked = DroneType.None;
+
+ ///
+ /// Contains the DroneType value
+ ///
+ public DroneType selectedDroneControllerMinionType = DroneType.BasicLaser;
+
+ public override void ResetEffects()
+ {
+ everburningCandleBuff = false;
+ everburningCursedCandleBuff = false;
+ everfrozenCandleBuff = false;
+ everburningShadowflameCandleBuff = false;
+ teleportHome = false;
+ getDefense = false;
+ soulMinion = false;
+ tempSoulMinion = null;
+ slimePackMinion = false;
+ empoweringBuff = false;
+ enhancedHunterBuff = false;
+ cuteSlimeSpawnEnable = false;
+ soulSaviorArmor = false;
+ droneControllerMinion = false;
+ mouseoveredDresser = false;
+
+ needsNearbyEnemyNumber = false;
+ }
+
+ public bool RightClickPressed { get { return PlayerInput.Triggers.JustPressed.MouseRight; } }
+
+ public bool RightClickReleased { get { return PlayerInput.Triggers.JustReleased.MouseRight; } }
+
+ public bool LeftClickPressed { get { return PlayerInput.Triggers.JustPressed.MouseLeft; } }
+
+ public bool LeftClickReleased { get { return PlayerInput.Triggers.JustReleased.MouseLeft; } }
+
+ public override void SaveData(TagCompound tag)
+ {
+ tag.Add("teleportHomeWhenLowTimer", (int)teleportHomeTimer);
+ tag.Add("getDefenseTimer", (int)getDefenseTimer);
+ tag.Add("lastSlainBossTimerSeconds", (int)lastSlainBossTimerSeconds);
+ tag.Add("droneControllerUnlocked", (byte)droneControllerUnlocked);
+ }
+
+ public override void LoadData(TagCompound tag)
+ {
+ teleportHomeTimer = (short)tag.GetInt("teleportHomeWhenLowTimer");
+ getDefenseTimer = (short)tag.GetInt("getDefenseTimer");
+ string timerKey = "lastSlainBossTimerSeconds";
+ if (tag.ContainsKey(timerKey))
+ {
+ lastSlainBossTimerSeconds = tag.GetInt("lastSlainBossTimerSeconds");
+ }
+ droneControllerUnlocked = (DroneType)tag.GetByte("droneControllerUnlocked");
+ }
+
+ //TODO get rid of this, use manual packets since setting those values happens in a singular place
+ public override void clientClone(ModPlayer clientClone)
+ {
+ AssPlayer clone = clientClone as AssPlayer;
+ clone.shieldDroneReduction = shieldDroneReduction;
+ //Needs syncing because spawning drone parts depends on this serverside (See GeneralGlobalNPC.NPCLoot)
+ clone.droneControllerUnlocked = droneControllerUnlocked;
+ }
+
+ public override void SendClientChanges(ModPlayer clientPlayer)
+ {
+ AssPlayer clone = clientPlayer as AssPlayer;
+ if (clone.shieldDroneReduction != shieldDroneReduction ||
+ clone.droneControllerUnlocked != droneControllerUnlocked)
+ {
+ SendClientChangesPacket();
+ }
+ }
+
+ ///
+ /// Things that are sent to the server that are needed on-change
+ ///
+ public void SendClientChangesPacket(int toClient = -1, int ignoreClient = -1)
+ {
+ if (Main.netMode != NetmodeID.SinglePlayer)
+ {
+ ModPacket packet = Mod.GetPacket();
+ packet.Write((byte)AssMessageType.ClientChangesAssPlayer);
+ packet.Write((byte)Player.whoAmI);
+ packet.Write((byte)shieldDroneReduction);
+ packet.Write((byte)droneControllerUnlocked);
+ packet.Send(toClient, ignoreClient);
+ }
+ }
+
+ public override void SyncPlayer(int toWho, int fromWho, bool newPlayer)
+ {
+ ModPacket packet = Mod.GetPacket();
+ packet.Write((byte)AssMessageType.SyncAssPlayer);
+ packet.Write((byte)Player.whoAmI);
+
+ //Actual data here
+ packet.Write((byte)shieldDroneReduction);
+ packet.WriteVarInt(lastSlainBossTimerSeconds);
+ packet.WriteVarInt(lastSlainBossType);
+
+ packet.Send(toWho, fromWho);
+ }
+
+ public void ReceiveSyncPlayer(BinaryReader reader)
+ {
+ shieldDroneReduction = reader.ReadByte();
+ lastSlainBossTimerSeconds = reader.ReadVarInt();
+ lastSlainBossType = reader.ReadVarInt();
+ }
+
+ public override void OnEnterWorld(Player player)
+ {
+ SendClientChangesPacket();
+ }
+
+ ///
+ /// Resets the empowering timer from the Empowering Buff, spawns dust, sends sync
+ ///
+ public void ResetEmpoweringTimer(bool fromServer = false)
+ {
+ if (empoweringBuff && !Player.HasBuff(BuffID.ShadowDodge))
+ {
+ for (int i = 0; i < empoweringTimer; i++)
+ {
+ Dust dust = Dust.NewDustPerfect(Player.Center, 135, new Vector2(Main.rand.NextFloat(-3f, 3f), Main.rand.NextFloat(-3f, 3f)) + (new Vector2(Main.rand.Next(-1, 1), Main.rand.Next(-1, 1)) * ((6 * empoweringTimer) / empoweringTimerMax)), 26, Color.White, Main.rand.NextFloat(1.5f, 2.4f));
+ dust.noLight = true;
+ dust.noGravity = true;
+ dust.fadeIn = Main.rand.NextFloat(1f, 2.3f);
+ }
+ empoweringTimer = 0;
+
+ if (Main.netMode == NetmodeID.MultiplayerClient && !fromServer)
+ {
+ ModPacket packet = Mod.GetPacket();
+ packet.Write((byte)AssMessageType.ResetEmpoweringTimerpvp);
+ packet.Write((byte)Player.whoAmI);
+ packet.Send(); //send to server
+ }
+ }
+ }
+
+ ///
+ /// Decreases damage based on current shield level from the Shield Drone, spawns dust
+ ///
+ ///
+ public void DecreaseDroneShield(ref int damage)
+ {
+ if (shieldDroneReduction > 0)
+ {
+ for (int i = 0; i < shieldDroneReduction / 2; i++)
+ {
+ Dust dust = Dust.NewDustPerfect(Player.Center, 135, new Vector2(Main.rand.NextFloat(-3f, 3f), Main.rand.NextFloat(-3f, 3f)) + new Vector2(Main.rand.Next(-1, 1), Main.rand.Next(-1, 1)), 26, Color.White, Main.rand.NextFloat(1.5f, 2.4f));
+ dust.noLight = true;
+ dust.noGravity = true;
+ dust.fadeIn = Main.rand.NextFloat(1f, 2.3f);
+ }
+
+ damage = (int)(damage * ((100 - shieldDroneReduction) / 100f));
+ if (Main.netMode != NetmodeID.Server && Main.myPlayer == Player.whoAmI) shieldDroneReduction -= ShieldIncreaseAmount; //since this is only set clientside by the projectile and synced by packets
+ }
+ }
+
+ ///
+ /// Sets the isTemp on the projectile so it behaves differently
+ ///
+ private void PreSyncSoulTemp(Projectile proj)
+ {
+ if (!ContentConfig.Instance.Bosses)
+ {
+ return;
+ }
+
+ if (proj.ModProjectile is CompanionDungeonSoulMinionBase soul)
+ {
+ soul.isTemp = true;
+ }
+ }
+
+ ///
+ /// Spawns the temporary soul when wearing the accessory that allows it
+ ///
+ private void SpawnSoulTemp()
+ {
+ if (!ContentConfig.Instance.Bosses)
+ {
+ return;
+ }
+
+ if (tempSoulMinion != null && !tempSoulMinion.IsAir && Player.whoAmI == Main.myPlayer)
+ {
+ bool checkIfAlive = false;
+ int spawnedType = Main.hardMode ? ModContent.ProjectileType() : ModContent.ProjectileType();
+ int spawnedDamage = Main.hardMode ? (int)(EverhallowedLantern.BaseDmg * 1.1f * 2f) : ((EverhallowedLantern.BaseDmg / 2 - 1) * 2);
+ for (int i = 0; i < Main.maxProjectiles; i++)
+ {
+ if (Main.projectile[i].active && Main.projectile[i].owner == Player.whoAmI && Main.projectile[i].type == spawnedType)
+ {
+ if (Main.projectile[i].minionSlots == 0f) //criteria for temp, is set by isTemp
+ {
+ checkIfAlive = true;
+ break;
+ }
+ }
+ }
+
+ if (!checkIfAlive)
+ {
+ AssUtils.NewProjectile(Player.GetProjectileSource_Item(tempSoulMinion), Player.Center.X, Player.Center.Y, -Player.velocity.X, Player.velocity.Y - 6f, spawnedType, spawnedDamage, EverhallowedLantern.BaseKB, preSync: PreSyncSoulTemp);
+ }
+ }
+ }
+
+ ///
+ /// Upon Soul Harvester death, convert all inert souls in inventory
+ ///
+ public void ConvertInertSoulsInventory()
+ {
+ if (!ContentConfig.Instance.Bosses)
+ {
+ return;
+ }
+
+ //this gets called once on server side for all players, and then each player calls it on itself client side
+ int tempStackCount;
+ int itemTypeOld = ModContent.ItemType();
+ int itemTypeNew = ModContent.ItemType(); //version that is used in crafting
+
+ Item[][] inventoryArray = { Player.inventory, Player.bank.item, Player.bank2.item, Player.bank3.item, Player.bank4.item }; //go though player inv
+ for (int y = 0; y < inventoryArray.Length; y++)
+ {
+ for (int e = 0; e < inventoryArray[y].Length; e++)
+ {
+ Item item = inventoryArray[y][e];
+ if (item.type == itemTypeOld) //find inert soul
+ {
+ tempStackCount = item.stack;
+ item.SetDefaults(itemTypeNew); //override with awakened
+ item.stack = tempStackCount;
+ }
+ }
+ }
+
+ //trash slot
+ Item trashItem = Player.trashItem;
+ if (trashItem.type == itemTypeOld)
+ {
+ tempStackCount = trashItem.stack;
+ trashItem.SetDefaults(itemTypeNew);
+ trashItem.stack = tempStackCount;
+ }
+
+ //mouse item
+ Item mouseItem = Main.mouseItem;
+ if (Main.netMode != NetmodeID.Server && mouseItem.type == itemTypeOld)
+ {
+ tempStackCount = mouseItem.stack;
+ mouseItem.SetDefaults(itemTypeNew);
+ mouseItem.stack = tempStackCount;
+ }
+ }
+
+ private void UpdateTeleportHomeWhenLow()
+ {
+ //this code runs even when the accessory is not equipped
+ canTeleportHome = teleportHomeTimer <= 0;
+
+ if (!canTeleportHome && Main.GameUpdateCount % 60 == 59)
+ {
+ teleportHomeTimer--;
+ }
+ }
+
+ private void UpdateGetDefenseWhenLow()
+ {
+ //this code runs even when the accessory is not equipped
+ canGetDefense = getDefenseTimer <= 0;
+
+ if (!canGetDefense && Main.GameUpdateCount % 60 == 59)
+ {
+ getDefenseTimer--;
+ }
+
+ if (getDefenseDuration != 0)
+ {
+ getDefenseDuration--;
+ }
+ }
+
+ ///
+ /// Sets some variables related to the Empowering Buff
+ ///
+ private void Empower()
+ {
+ if (empoweringBuff)
+ {
+ if (Main.GameUpdateCount % 60 == 0)
+ {
+ if (empoweringTimer < empoweringTimerMax)
+ {
+ empoweringTimer++;
+ empoweringStep = (empoweringTimer * empoweringTotal) / empoweringTimerMax;
+ }
+ }
+ }
+ else
+ {
+ empoweringStep = 0f;
+ empoweringTimer = 0;
+ }
+ }
+
+ private bool GetDefense(double damage)
+ {
+ if (getDefense)
+ {
+ if (canGetDefense)
+ {
+ Player.statLife += (int)damage;
+ Player.AddBuff(BuffID.RapidHealing, 600);
+ CombatText.NewText(Player.getRect(), CombatText.HealLife, "Defense increased");
+
+ getDefenseTimer = GetDefenseTimerMax;
+ getDefenseDuration = GetDefenseDurationMax;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private bool TeleportHome(double damage)
+ {
+ if (teleportHome)
+ {
+ if (canTeleportHome && Player.whoAmI == Main.myPlayer)
+ {
+ Player.RemoveAllGrapplingHooks();
+
+ //inserted before player.Spawn()
+ Player.statLife += (int)damage;
+
+ Player.Spawn(PlayerSpawnContext.RecallFromItem);
+ for (int i = 0; i < 70; i++)
+ {
+ Dust.NewDust(Player.position, Player.width, Player.height, 15, 0f, 0f, 150, default(Color), 1.5f);
+ }
+ //end
+
+ Player.AddBuff(BuffID.RapidHealing, 300, false);
+
+ NetMessage.SendData(MessageID.PlayerControls, number: Player.whoAmI);
+
+ teleportHomeTimer = TeleportHomeTimerMax;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void ApplyCandleDebuffs(Entity victim)
+ {
+ if (victim is NPC npc)
+ {
+ if (everburningCandleBuff) npc.AddBuff(BuffID.OnFire, 120);
+ if (everburningCursedCandleBuff) npc.AddBuff(BuffID.CursedInferno, 120);
+ if (everfrozenCandleBuff) npc.AddBuff(BuffID.Frostburn, 120);
+ if (everburningShadowflameCandleBuff) npc.AddBuff(BuffID.ShadowFlame, 60);
+ }
+ //else if (victim is Player)
+ }
+
+ #region CircleUI
+
+ ///
+ /// Contains a list of CircleUIHandlers that are used in CircleUIStart/End in Mod
+ ///
+ public List CircleUIList;
+
+ public override void Initialize()
+ {
+ teleportHome = false;
+ teleportHomeTimer = 0;
+ getDefense = false;
+ getDefenseDuration = 0;
+ getDefenseTimer = 0;
+ lastSlainBossTimerSeconds = -1;
+ tempSoulMinion = null;
+ selectedSoulMinionType = SoulType.Dungeon;
+ selectedSlimePackMinionType = 0;
+ nextMagicSlimeSlingMinion = 0;
+ empoweringTimer = 0;
+ empoweringStep = 0f;
+ shieldDroneReduction = 0;
+ shieldDroneLerpVisual = 0;
+ drawEffectsCalledOnce = false;
+
+ //needs to call new List() since Initialize() is called per player in the player select screen
+ CircleUIList = new List();
+
+ if (ContentConfig.Instance.Weapons)
+ {
+ CircleUIList.AddRange(new List
+ {
+ new CircleUIHandler(
+ triggerItem: ModContent.ItemType(),
+ condition: () => true,
+ uiConf: SlimeHandlerKnapsack.GetUIConf,
+ onUIStart: () => selectedSlimePackMinionType,
+ onUIEnd: delegate
+ {
+ selectedSlimePackMinionType = (byte)CircleUI.returned;
+ AssUtils.UIText("Selected: " + (selectedSlimePackMinionType == 0 ? "Default" : (selectedSlimePackMinionType == 1 ? "Assorted" : "Spiked")), CombatText.HealLife);
+ },
+ triggerLeft: false
+ ),
+ new CircleUIHandler(
+ triggerItem: ModContent.ItemType(),
+ condition: () => true,
+ uiConf: DroneController.GetUIConf,
+ onUIStart: delegate
+ {
+ if (Utils.IsPowerOfTwo((int)selectedDroneControllerMinionType))
+ {
+ return (int)Math.Log((int)selectedDroneControllerMinionType, 2);
+ }
+ return 0;
+ },
+ onUIEnd: delegate
+ {
+ selectedDroneControllerMinionType = (DroneType)(byte)Math.Pow(2, CircleUI.returned);
+ AssUtils.UIText("Selected: " + DroneController.GetDroneData(selectedDroneControllerMinionType).Name, CombatText.HealLife);
+ },
+ triggerLeft: false
+ )}
+ );
+ }
+
+ if (ContentConfig.Instance.Bosses)
+ {
+ CircleUIList.Add(new CircleUIHandler(
+ triggerItem: ModContent.ItemType(),
+ condition: () => true,
+ uiConf: EverhallowedLantern.GetUIConf,
+ onUIStart: delegate
+ {
+ if (Utils.IsPowerOfTwo((int)selectedSoulMinionType))
+ {
+ return (int)Math.Log((int)selectedSoulMinionType, 2);
+ }
+ return 0;
+ },
+ onUIEnd: delegate
+ {
+ selectedSoulMinionType = (SoulType)(byte)Math.Pow(2, CircleUI.returned);
+ AssUtils.UIText("Selected: " + EverhallowedLantern.GetSoulData(selectedSoulMinionType).Name, CombatText.HealLife);
+ },
+ triggerLeft: false
+ ));
+ }
+
+ // after filling the list, set the trigger list
+ for (int i = 0; i < CircleUIList.Count; i++)
+ {
+ CircleUIList[i].AddTriggers();
+ }
+ }
+ #endregion
+
+ ///
+ /// Get proper SpriteEffects flags based on player status
+ ///
+ private static SpriteEffects GetSpriteEffects(Player player)
+ {
+ if (player.gravDir == 1f)
+ {
+ if (player.direction == 1)
+ {
+ return SpriteEffects.None;
+ }
+ else
+ {
+ return SpriteEffects.FlipHorizontally;
+ }
+ }
+ else
+ {
+ if (player.direction == 1)
+ {
+ return SpriteEffects.FlipVertically;
+ }
+ else
+ {
+ return SpriteEffects.FlipHorizontally | SpriteEffects.FlipVertically;
+ }
+ }
+ }
+
+ public void SlainBoss(int type)
+ {
+ lastSlainBossTimerSeconds = 0;
+ lastSlainBossType = type;
+
+ OnSlainBoss?.Invoke(Player, type);
+
+ if (Main.netMode == NetmodeID.Server)
+ {
+ ModPacket packet = Mod.GetPacket();
+ packet.Write((byte)AssMessageType.SlainBoss);
+ packet.WriteVarInt(lastSlainBossType);
+ packet.Send(Player.whoAmI);
+ }
+ }
+
+ public bool HasSlainBossSecondsAgo(int timeInSeconds)
+ {
+ return HasBossSlainTimer && lastSlainBossTimerSeconds < timeInSeconds;
+ }
+
+ public void UpdateSlainBossTimer()
+ {
+ if (HasBossSlainTimer)
+ {
+ lastSlainBossTimerInternal++;
+ if (lastSlainBossTimerInternal >= 60)
+ {
+ lastSlainBossTimerInternal = 0;
+
+ lastSlainBossTimerSeconds++;
+ }
+ }
+ }
+
+ public void UpdateNearbyEnemies()
+ {
+ float distSQ = 600 * 600;
+ if (nearbyEnemyTimer == 0)
+ {
+ nearbyEnemyNumber = 0;
+ nearbyEnemyTimer = 15;
+ for (int l = 0; l < Main.maxNPCs; l++)
+ {
+ NPC npc = Main.npc[l];
+ if (npc.active && !npc.friendly && npc.damage > 0 && npc.lifeMax > 5 && !npc.dontCountMe && (npc.Center - Player.Center).LengthSquared() < distSQ)
+ {
+ nearbyEnemyNumber++;
+ }
+ }
+ }
+ else
+ {
+ nearbyEnemyTimer--;
+ }
+ }
+
+ public override void DrawEffects(PlayerDrawSet drawInfo, ref float r, ref float g, ref float b, ref float a, ref bool fullBright)
+ {
+ Player drawPlayer = drawInfo.drawPlayer;
+ if (!drawEffectsCalledOnce)
+ {
+ drawEffectsCalledOnce = true;
+ }
+ else
+ {
+ return;
+ }
+ if (Main.gameMenu) return;
+
+ //Other code
+
+ //if (!PlayerLayer.MiscEffectsBack.visible) return;
+
+ if (shieldDroneReduction > 0)
+ {
+ Color outer = Color.White;
+ Color inner = new Color(0x03, 0xFE, 0xFE);
+
+ float ratio = shieldDroneReduction / 100f;
+ if (shieldDroneLerpVisual < ratio)
+ {
+ shieldDroneLerpVisual += 0.01f;
+ }
+ if (shieldDroneLerpVisual > ratio) shieldDroneLerpVisual = ratio;
+
+ outer *= shieldDroneLerpVisual;
+ inner *= shieldDroneLerpVisual;
+ Lighting.AddLight(drawPlayer.Center, inner.ToVector3());
+
+ float alpha = (255 - drawPlayer.immuneAlpha) / 255f;
+ outer *= alpha;
+ inner *= alpha;
+ Effect shader = ShaderManager.SetupCircleEffect(new Vector2((int)drawPlayer.Center.X, (int)drawPlayer.Center.Y + drawPlayer.gfxOffY), 2 * 16, outer, inner);
+
+ ShaderManager.ApplyToScreenOnce(Main.spriteBatch, shader);
+ }
+ }
+
+ public override void ModifyHitByProjectile(Projectile proj, ref int damage, ref bool crit)
+ {
+ DecreaseDroneShield(ref damage);
+
+ ResetEmpoweringTimer();
+
+ SpawnSoulTemp();
+ }
+
+ public override void ModifyHitByNPC(NPC npc, ref int damage, ref bool crit)
+ {
+ DecreaseDroneShield(ref damage);
+
+ ResetEmpoweringTimer();
+
+ SpawnSoulTemp();
+ }
+
+ public override void ModifyHitNPC(Item item, NPC target, ref int damage, ref float knockback, ref bool crit)
+ {
+ if (!Main.rand.NextBool(5)) return;
+ ApplyCandleDebuffs(target);
+ }
+
+ public override void ModifyHitNPCWithProj(Projectile proj, NPC target, ref int damage, ref float knockback, ref bool crit, ref int hitDirection)
+ {
+ if (!Main.rand.NextBool(5)) return;
+ if (proj.minion && !Main.rand.NextBool(5)) return;
+ ApplyCandleDebuffs(target);
+ }
+
+ public override void ModifyHitPvp(Item item, Player target, ref int damage, ref bool crit)
+ {
+ //ApplyCandleDebuffs(target);
+ AssPlayer assPlayer = target.GetModPlayer();
+ assPlayer.ResetEmpoweringTimer();
+
+ assPlayer.SpawnSoulTemp();
+ }
+
+ public override void ModifyHitPvpWithProj(Projectile proj, Player target, ref int damage, ref bool crit)
+ {
+ //ApplyCandleDebuffs(target);
+ AssPlayer assPlayer = target.GetModPlayer();
+ assPlayer.ResetEmpoweringTimer();
+
+ assPlayer.SpawnSoulTemp();
+ }
+
+ public override void ModifyWeaponDamage(Item item, ref StatModifier damage)
+ {
+ if (empoweringBuff && !item.CountsAsClass(DamageClass.Summon) && item.damage > 0) damage += empoweringStep; //summon damage gets handled in EmpoweringBuffGlobalProjectile
+ }
+
+ public override void ModifyWeaponCrit(Item item, ref float crit)
+ {
+ crit += 10 * empoweringStep;
+ }
+
+ public override bool PreKill(double damage, int hitDirection, bool pvp, ref bool playSound, ref bool genGore, ref PlayerDeathReason damageSource)
+ {
+ //getDefense before teleportHome (so you don't teleport BEFORE you gain the defense)
+
+ if (!GetDefense(damage)) return false;
+
+ if (!TeleportHome(damage)) return false;
+
+ return base.PreKill(damage, hitDirection, pvp, ref playSound, ref genGore, ref damageSource);
+ }
+
+ public override bool PreHurt(bool pvp, bool quiet, ref int damage, ref int hitDirection, ref bool crit, ref bool customDamage, ref bool playSound, ref bool genGore, ref PlayerDeathReason damageSource)
+ {
+ if (getDefenseDuration != 0) damage = 1;
+
+ DecreaseDroneShield(ref damage);
+
+ if (wyvernCampfire && damageSource.SourceProjectileType == ProjectileID.HarpyFeather)
+ {
+ hitDirection = 0; //this cancels knockback
+ }
+
+ return base.PreHurt(pvp, quiet, ref damage, ref hitDirection, ref crit, ref customDamage, ref playSound, ref genGore, ref damageSource);
+ }
+
+ public override void CatchFish(FishingAttempt attempt, ref int itemDrop, ref int npcSpawn, ref AdvancedPopupRequest sonar, ref Vector2 sonarPosition)
+ {
+ bool inWater = !attempt.inHoney && !attempt.inLava;
+
+ if (attempt.waterTilesCount < attempt.waterNeededToFish)
+ {
+ return;
+ }
+
+ if (ContentConfig.Instance.OtherPets)
+ {
+ //Match Zephyr Fish conditions
+ if (attempt.legendary && !attempt.crate && inWater)
+ {
+ if (((int)(Player.Center.X / 16) < Main.maxTilesX * 0.08f || (int)(Player.Center.X / 16) > Main.maxTilesX * 0.92f) /*&& Main.rand.Next(1) == 0*/) //10 times more likely than zephyr fish makes it about as rare as reaver shark
+ {
+ itemDrop = ModContent.ItemType();
+ return;
+ }
+ }
+ }
+ }
+
+ public override void PostUpdateBuffs()
+ {
+ UpdateTeleportHomeWhenLow();
+
+ UpdateGetDefenseWhenLow();
+
+ Empower();
+
+ UpdateSlainBossTimer();
+ }
+
+ public override void PreUpdate()
+ {
+ if (Main.netMode != NetmodeID.Server)
+ {
+ if (drawEffectsCalledOnce)
+ {
+ drawEffectsCalledOnce = false;
+ }
+
+ if (Main.myPlayer == Player.whoAmI && ContentConfig.Instance.Weapons)
+ {
+ if (Player.ownedProjectileCounts[DroneController.GetDroneData(DroneType.Shield).ProjType] < 1) shieldDroneReduction = 0;
+ }
+ }
+
+ UpdateNearbyEnemies();
+ }
+ }
}
diff --git a/AssUISystem.cs b/AssUISystem.cs
index 27ae78b6..026a1bdc 100644
--- a/AssUISystem.cs
+++ b/AssUISystem.cs
@@ -1,467 +1,466 @@
using AssortedCrazyThings.Base;
using AssortedCrazyThings.Items;
using AssortedCrazyThings.Items.PetAccessories;
-using AssortedCrazyThings.Items.Placeable;
using AssortedCrazyThings.UI;
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using Terraria;
+using Terraria.Audio;
using Terraria.Graphics;
using Terraria.ID;
using Terraria.ModLoader;
using Terraria.UI;
-using Terraria.Audio;
namespace AssortedCrazyThings
{
- [Content(ConfigurationSystem.AllFlags, needsAllToFilter: true)]
- public class AssUISystem : AssSystem
- {
- ///
- /// Zoom level, (for UIs). 0f == fully zoomed out, 1f == fully zoomed in
- ///
- public static Vector2 ZoomFactor;
-
- //UI stuff
- internal static UserInterface CircleUIInterface;
- internal static CircleUI CircleUI;
-
- internal static UserInterface HoverNPCUIInterface;
- internal static HoverNPCUI HoverNPCUI;
-
- internal static UserInterface HarvesterEdgeUIInterface;
-
- internal static UserInterface EnhancedHunterUIInterface;
- internal static EnhancedHunterUI EnhancedHunterUI;
-
- internal static UserInterface PetVanityUIInterface;
- internal static PetVanityUI PetVanityUI;
-
- public override void PostSetupContent()
- {
- if (!Main.dedServ && Main.netMode != NetmodeID.Server)
- {
- CircleUI = new CircleUI();
- CircleUI.Activate();
- CircleUIInterface = new UserInterface();
- CircleUIInterface.SetState(CircleUI);
-
- HoverNPCUI = new HoverNPCUI();
- HoverNPCUI.Activate();
- HoverNPCUIInterface = new UserInterface();
- HoverNPCUIInterface.SetState(HoverNPCUI);
-
- if (ContentConfig.Instance.Bosses)
- {
- EnhancedHunterUI = new EnhancedHunterUI();
- EnhancedHunterUI.Activate();
- EnhancedHunterUIInterface = new UserInterface();
- EnhancedHunterUIInterface.SetState(EnhancedHunterUI);
- }
-
- if (ContentConfig.Instance.CuteSlimes)
- {
- PetVanityUI = new PetVanityUI();
- PetVanityUI.Activate();
- PetVanityUIInterface = new UserInterface();
- PetVanityUIInterface.SetState(PetVanityUI);
- }
- }
- }
-
- public override void Unload()
- {
- if (!Main.dedServ && Main.netMode != NetmodeID.Server)
- {
- CircleUIInterface = null;
- CircleUI = null;
-
- HoverNPCUIInterface = null;
- HoverNPCUI = null;
-
- HarvesterEdgeUIInterface = null;
-
- EnhancedHunterUIInterface = null;
- EnhancedHunterUI = null;
-
- PetVanityUIInterface = null;
- PetVanityUI = null;
-
- EnhancedHunterUI.arrowTexture = null;
- PetVanityUI.redCrossTexture = null;
- CircleUI.UIConf = null;
- CircleUIHandler.TriggerListLeft.Clear();
- CircleUIHandler.TriggerListRight.Clear();
- }
- }
-
- ///
- /// Creates golden dust particles at the projectiles location with that type and LocalPlayer as owner. (Used for pets)
- ///
- private void PoofVisual(int projType)
- {
- int projIndex = -1;
- //find first occurence of a player owned projectile
- for (int i = 0; i < Main.maxProjectiles; i++)
- {
- if (Main.projectile[i].active)
- {
- if (Main.projectile[i].owner == Main.myPlayer && Main.projectile[i].type == projType)
- {
- projIndex = i;
- break;
- }
- }
- }
-
- if (projIndex != -1)
- {
- Dust dust;
- for (int i = 0; i < 14; i++)
- {
- dust = Dust.NewDustDirect(Main.projectile[projIndex].position, Main.projectile[projIndex].width, Main.projectile[projIndex].height, 204, Main.projectile[projIndex].velocity.X, Main.projectile[projIndex].velocity.Y, 0, new Color(255, 255, 255), 0.8f);
- dust.noGravity = true;
- dust.noLight = true;
- }
- }
- }
-
- ///
- /// Called when CircleUI starts
- ///
- private void CircleUIStart(int triggerType, bool triggerLeft = true, bool fromDresser = false)
- {
- AssPlayer mPlayer = Main.LocalPlayer.GetModPlayer();
- PetPlayer pPlayer = Main.LocalPlayer.GetModPlayer();
-
- //combine both lists of the players (split for organization and player load shenanigans)
- List l = mPlayer.CircleUIList;
- l.AddRange(pPlayer.CircleUIList);
-
- bool found = false;
- for (int i = 0; i < l.Count; i++)
- {
- if (l[i].Condition())
- {
- if (l[i].TriggerItem == triggerType)
- {
- if (l[i].TriggerLeft == triggerLeft)
- {
- CircleUI.UIConf = l[i].UIConf();
- CircleUI.currentSelected = l[i].OnUIStart();
- found = true;
- break;
- }
- }
- }
- }
- //extra things that happen
- if (!found)
- {
- if (triggerType == ModContent.ItemType())
- {
- AssUtils.UIText("No alt costumes found for" + (triggerLeft ? "" : " light") + " pet", CombatText.DamagedFriendly);
- return;
- }
- }
-
- //Spawn UI
- CircleUI.Start(triggerType, triggerLeft, fromDresser);
- }
-
- ///
- /// Called when CircleUI ends
- ///
- private void CircleUIEnd(bool triggerLeft = true)
- {
- AssPlayer mPlayer = Main.LocalPlayer.GetModPlayer();
- if (CircleUI.returned != CircleUI.NONE && CircleUI.returned != CircleUI.currentSelected)
- {
- //if something returned AND if the returned thing isn't the same as the current one
-
- try
- {
- SoundEngine.PlaySound(SoundID.Item4.WithVolume(0.6f), Main.LocalPlayer.position);
- }
- catch
- {
- //No idea why but this threw errors one time
- }
-
- List l = mPlayer.CircleUIList;
- for (int i = 0; i < l.Count; i++)
- {
- if (l[i].Condition())
- {
- if (l[i].TriggerItem == CircleUI.triggerItemType)
- {
- if (l[i].TriggerLeft == triggerLeft)
- {
- l[i].OnUIEnd();
- break;
- }
- }
- }
- }
- //extra things that happen
- if (CircleUI.triggerItemType == ModContent.ItemType())
- {
- PoofVisual(CircleUI.UIConf.AdditionalInfo);
- AssUtils.UIText("Selected: " + CircleUI.UIConf.Tooltips[CircleUI.returned], CombatText.HealLife);
- }
- }
-
- CircleUI.returned = CircleUI.NONE;
- CircleUI.visible = false;
- }
-
- ///
- /// Called in UpdateUI
- ///
- private void UpdateCircleUI()
- {
- Player player = Main.LocalPlayer;
- AssPlayer mPlayer = player.GetModPlayer();
-
- int triggerType = player.HeldItem.type;
- bool openWithDresser = mPlayer.mouseoveredDresser;
- if (openWithDresser)
- {
- triggerType = ModContent.ItemType();
- }
- bool? left = null;
- if (mPlayer.LeftClickPressed && (CircleUIHandler.TriggerListLeft.Contains(triggerType) || openWithDresser))
- {
- left = true;
- }
- else if (mPlayer.RightClickPressed && (CircleUIHandler.TriggerListRight.Contains(triggerType) || openWithDresser))
- {
- left = false;
- }
-
- if (left != null && AllowedToOpenUI()) CircleUIStart(triggerType, (bool)left, openWithDresser);
-
- if (CircleUI.visible)
- {
- left = null;
- if (mPlayer.LeftClickReleased)
- {
- left = true;
- }
- else if (mPlayer.RightClickReleased)
- {
- left = false;
- }
-
- if (left != null && left == CircleUI.openedWithLeft) CircleUIEnd((bool)left);
-
- if (CircleUI.triggerItemType != triggerType && !CircleUI.triggeredFromDresser) //cancel the UI when you switch items
- {
- CircleUI.returned = CircleUI.NONE;
- CircleUI.visible = false;
- }
- }
- }
-
- ///
- /// Called in UpdateUI
- ///
- private void UpdatePetVanityUI()
- {
- Player player = Main.LocalPlayer;
- AssPlayer mPlayer = player.GetModPlayer();
- PetPlayer pPlayer = player.GetModPlayer();
-
- int itemType = player.HeldItem.type;
- if (mPlayer.LeftClickPressed && AllowedToOpenUI() && PetAccessory.TryGetAccessoryFromItem(itemType, out PetAccessory petAccessory))
- {
- if (petAccessory.HasAlts && pPlayer.HasValidSlimePet(out SlimePet slimePet) &&
- !slimePet.IsSlotTypeBlacklisted[(int)petAccessory.Slot])
- {
- //Spawn UI
- PetVanityUI.Start(petAccessory);
- }
- }
-
- if (!PetVanityUI.visible)
- {
- return;
- }
-
- if (mPlayer.LeftClickReleased)
- {
- if (PetVanityUI.returned > PetVanityUI.NONE)
- {
- //if something returned AND if the returned thing isn't the same as the current one
-
- try
- {
- SoundEngine.PlaySound(SoundID.Item1, player.position);
- }
- catch
- {
- //No idea why but this threw errors one time
- }
- //UIText("Selected: " + PetVanityUI.petAccessory.AltTextureSuffixes[PetVanityUI.returned], CombatText.HealLife);
-
- PetVanityUI.petAccessory.AltTextureIndex = (byte)PetVanityUI.returned;
- pPlayer.ToggleAccessory(PetVanityUI.petAccessory);
- }
- else if (PetVanityUI.hasEquipped && PetVanityUI.returned == PetVanityUI.NONE)
- {
- //hovered over the middle and had something equipped: take accessory away
- pPlayer.DelAccessory(PetVanityUI.petAccessory);
- }
- //else if (returned == PetVanityUI.IGNORE) {nothing happens}
-
- PetVanityUI.returned = PetVanityUI.NONE;
- PetVanityUI.visible = false;
- }
-
- if (PetVanityUI.petAccessory.Type != itemType) //cancel the UI when you switch items
- {
- PetVanityUI.returned = PetVanityUI.NONE;
- PetVanityUI.visible = false;
- }
- }
-
- private void UpdateHoverNPCUI(GameTime gameTime)
- {
- HoverNPCUI.Update(gameTime);
- }
-
- private void UpdateEnhancedHunterUI(GameTime gameTime)
- {
- if (Main.LocalPlayer.GetModPlayer().enhancedHunterBuff)
- {
- EnhancedHunterUI.visible = true;
- }
- else
- {
- EnhancedHunterUI.visible = false;
- }
- EnhancedHunterUI?.Update(gameTime);
- }
-
- public override void UpdateUI(GameTime gameTime)
- {
- UpdateCircleUI();
- UpdateHoverNPCUI(gameTime);
- UpdateEnhancedHunterUI(gameTime);
- UpdatePetVanityUI();
- }
-
- ///
- /// Checks if LocalPlayer can open a UI
- ///
- private bool AllowedToOpenUI()
- {
- return Main.hasFocus &&
- !Main.gamePaused &&
- !Main.LocalPlayer.dead &&
- !Main.LocalPlayer.mouseInterface &&
- !Main.drawingPlayerChat &&
- !Main.editSign &&
- !Main.editChest &&
- !Main.blockInput &&
- !Main.mapFullscreen &&
- !Main.HoveringOverAnNPC &&
- Main.LocalPlayer.cursorItemIconID != -1 &&
- Main.LocalPlayer.talkNPC == -1 &&
- Main.LocalPlayer.itemTime == 0 && Main.LocalPlayer.itemAnimation == 0 &&
- !(Main.LocalPlayer.frozen || Main.LocalPlayer.webbed || Main.LocalPlayer.stoned);
- }
-
- public override void ModifyInterfaceLayers(List layers)
- {
- int inventoryIndex = layers.FindIndex(layer => layer.Name.Equals("Vanilla: Hotbar"));
- if (inventoryIndex != -1)
- {
- if (CircleUI.visible)
- {
- //remove the item icon when using the item while held outside the inventory
- int mouseItemIndex = layers.FindIndex(layer => layer.Name.Equals("Vanilla: Mouse Item / NPC Head"));
- if (mouseItemIndex != -1) layers.RemoveAt(mouseItemIndex);
- layers.Insert(++inventoryIndex, new LegacyGameInterfaceLayer
- (
- "ACT: Appearance Select",
- delegate
- {
- CircleUIInterface.Draw(Main.spriteBatch, new GameTime());
- return true;
- },
- InterfaceScaleType.UI)
- );
- }
-
- if (PetVanityUI.visible && PetVanityUIInterface != null)
- {
- //remove the item icon when using the item while held outside the inventory
- int mouseItemIndex = layers.FindIndex(layer => layer.Name.Equals("Vanilla: Mouse Item / NPC Head"));
- if (mouseItemIndex != -1) layers.RemoveAt(mouseItemIndex);
- layers.Insert(++inventoryIndex, new LegacyGameInterfaceLayer
- (
- "ACT: Pet Vanity Select",
- delegate
- {
- PetVanityUIInterface.Draw(Main.spriteBatch, new GameTime());
- return true;
- },
- InterfaceScaleType.UI)
- );
- }
- }
-
- int mouseOverIndex = layers.FindIndex(layer => layer.Name.Equals("Vanilla: Mouse Over"));
- if (mouseOverIndex != -1)
- {
- layers.Insert(++mouseOverIndex, new LegacyGameInterfaceLayer
- (
- "ACT: NPC Mouse Over",
- delegate
- {
- HoverNPCUIInterface.Draw(Main.spriteBatch, new GameTime());
- return true;
- },
- InterfaceScaleType.UI)
- );
-
- if (EnhancedHunterUIInterface != null)
- {
- if (EnhancedHunterUI.visible)
- {
- layers.Insert(++mouseOverIndex, new LegacyGameInterfaceLayer
- (
- "ACT: Enhanced Hunter",
- delegate
- {
- EnhancedHunterUIInterface.Draw(Main.spriteBatch, new GameTime());
- return true;
- },
- InterfaceScaleType.UI)
- );
- }
- }
-
- if (HarvesterEdgeUIInterface != null)
- {
- layers.Insert(++mouseOverIndex, new LegacyGameInterfaceLayer
- (
- "ACT: Harvester Edge",
- delegate
- {
- HarvesterEdgeUIInterface.Draw(Main.spriteBatch, new GameTime());
- return true;
- },
- InterfaceScaleType.UI)
- );
- }
- }
- }
-
- public override void ModifyTransformMatrix(ref SpriteViewMatrix Transform)
- {
- ZoomFactor = Transform.Zoom - (Vector2.UnitX + Vector2.UnitY);
- }
- }
+ [Content(ConfigurationSystem.AllFlags, needsAllToFilter: true)]
+ public class AssUISystem : AssSystem
+ {
+ ///
+ /// Zoom level, (for UIs). 0f == fully zoomed out, 1f == fully zoomed in
+ ///
+ public static Vector2 ZoomFactor;
+
+ //UI stuff
+ internal static UserInterface CircleUIInterface;
+ internal static CircleUI CircleUI;
+
+ internal static UserInterface HoverNPCUIInterface;
+ internal static HoverNPCUI HoverNPCUI;
+
+ internal static UserInterface HarvesterEdgeUIInterface;
+
+ internal static UserInterface EnhancedHunterUIInterface;
+ internal static EnhancedHunterUI EnhancedHunterUI;
+
+ internal static UserInterface PetVanityUIInterface;
+ internal static PetVanityUI PetVanityUI;
+
+ public override void PostSetupContent()
+ {
+ if (!Main.dedServ && Main.netMode != NetmodeID.Server)
+ {
+ CircleUI = new CircleUI();
+ CircleUI.Activate();
+ CircleUIInterface = new UserInterface();
+ CircleUIInterface.SetState(CircleUI);
+
+ HoverNPCUI = new HoverNPCUI();
+ HoverNPCUI.Activate();
+ HoverNPCUIInterface = new UserInterface();
+ HoverNPCUIInterface.SetState(HoverNPCUI);
+
+ if (ContentConfig.Instance.Bosses)
+ {
+ EnhancedHunterUI = new EnhancedHunterUI();
+ EnhancedHunterUI.Activate();
+ EnhancedHunterUIInterface = new UserInterface();
+ EnhancedHunterUIInterface.SetState(EnhancedHunterUI);
+ }
+
+ if (ContentConfig.Instance.CuteSlimes)
+ {
+ PetVanityUI = new PetVanityUI();
+ PetVanityUI.Activate();
+ PetVanityUIInterface = new UserInterface();
+ PetVanityUIInterface.SetState(PetVanityUI);
+ }
+ }
+ }
+
+ public override void Unload()
+ {
+ if (!Main.dedServ && Main.netMode != NetmodeID.Server)
+ {
+ CircleUIInterface = null;
+ CircleUI = null;
+
+ HoverNPCUIInterface = null;
+ HoverNPCUI = null;
+
+ HarvesterEdgeUIInterface = null;
+
+ EnhancedHunterUIInterface = null;
+ EnhancedHunterUI = null;
+
+ PetVanityUIInterface = null;
+ PetVanityUI = null;
+
+ EnhancedHunterUI.arrowTexture = null;
+ PetVanityUI.redCrossTexture = null;
+ CircleUI.UIConf = null;
+ CircleUIHandler.TriggerListLeft.Clear();
+ CircleUIHandler.TriggerListRight.Clear();
+ }
+ }
+
+ ///
+ /// Creates golden dust particles at the projectiles location with that type and LocalPlayer as owner. (Used for pets)
+ ///
+ private void PoofVisual(int projType)
+ {
+ int projIndex = -1;
+ //find first occurence of a player owned projectile
+ for (int i = 0; i < Main.maxProjectiles; i++)
+ {
+ if (Main.projectile[i].active)
+ {
+ if (Main.projectile[i].owner == Main.myPlayer && Main.projectile[i].type == projType)
+ {
+ projIndex = i;
+ break;
+ }
+ }
+ }
+
+ if (projIndex != -1)
+ {
+ Dust dust;
+ for (int i = 0; i < 14; i++)
+ {
+ dust = Dust.NewDustDirect(Main.projectile[projIndex].position, Main.projectile[projIndex].width, Main.projectile[projIndex].height, 204, Main.projectile[projIndex].velocity.X, Main.projectile[projIndex].velocity.Y, 0, new Color(255, 255, 255), 0.8f);
+ dust.noGravity = true;
+ dust.noLight = true;
+ }
+ }
+ }
+
+ ///
+ /// Called when CircleUI starts
+ ///
+ private void CircleUIStart(int triggerType, bool triggerLeft = true, bool fromDresser = false)
+ {
+ AssPlayer mPlayer = Main.LocalPlayer.GetModPlayer();
+ PetPlayer pPlayer = Main.LocalPlayer.GetModPlayer();
+
+ //combine both lists of the players (split for organization and player load shenanigans)
+ List l = mPlayer.CircleUIList;
+ l.AddRange(pPlayer.CircleUIList);
+
+ bool found = false;
+ for (int i = 0; i < l.Count; i++)
+ {
+ if (l[i].Condition())
+ {
+ if (l[i].TriggerItem == triggerType)
+ {
+ if (l[i].TriggerLeft == triggerLeft)
+ {
+ CircleUI.UIConf = l[i].UIConf();
+ CircleUI.currentSelected = l[i].OnUIStart();
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ //extra things that happen
+ if (!found)
+ {
+ if (triggerType == ModContent.ItemType())
+ {
+ AssUtils.UIText("No alt costumes found for" + (triggerLeft ? "" : " light") + " pet", CombatText.DamagedFriendly);
+ return;
+ }
+ }
+
+ //Spawn UI
+ CircleUI.Start(triggerType, triggerLeft, fromDresser);
+ }
+
+ ///
+ /// Called when CircleUI ends
+ ///
+ private void CircleUIEnd(bool triggerLeft = true)
+ {
+ AssPlayer mPlayer = Main.LocalPlayer.GetModPlayer();
+ if (CircleUI.returned != CircleUI.NONE && CircleUI.returned != CircleUI.currentSelected)
+ {
+ //if something returned AND if the returned thing isn't the same as the current one
+
+ try
+ {
+ SoundEngine.PlaySound(SoundID.Item4.WithVolume(0.6f), Main.LocalPlayer.position);
+ }
+ catch
+ {
+ //No idea why but this threw errors one time
+ }
+
+ List l = mPlayer.CircleUIList;
+ for (int i = 0; i < l.Count; i++)
+ {
+ if (l[i].Condition())
+ {
+ if (l[i].TriggerItem == CircleUI.triggerItemType)
+ {
+ if (l[i].TriggerLeft == triggerLeft)
+ {
+ l[i].OnUIEnd();
+ break;
+ }
+ }
+ }
+ }
+ //extra things that happen
+ if (CircleUI.triggerItemType == ModContent.ItemType())
+ {
+ PoofVisual(CircleUI.UIConf.AdditionalInfo);
+ AssUtils.UIText("Selected: " + CircleUI.UIConf.Tooltips[CircleUI.returned], CombatText.HealLife);
+ }
+ }
+
+ CircleUI.returned = CircleUI.NONE;
+ CircleUI.visible = false;
+ }
+
+ ///
+ /// Called in UpdateUI
+ ///
+ private void UpdateCircleUI()
+ {
+ Player player = Main.LocalPlayer;
+ AssPlayer mPlayer = player.GetModPlayer();
+
+ int triggerType = player.HeldItem.type;
+ bool openWithDresser = mPlayer.mouseoveredDresser;
+ if (openWithDresser)
+ {
+ triggerType = ModContent.ItemType();
+ }
+ bool? left = null;
+ if (mPlayer.LeftClickPressed && (CircleUIHandler.TriggerListLeft.Contains(triggerType) || openWithDresser))
+ {
+ left = true;
+ }
+ else if (mPlayer.RightClickPressed && (CircleUIHandler.TriggerListRight.Contains(triggerType) || openWithDresser))
+ {
+ left = false;
+ }
+
+ if (left != null && AllowedToOpenUI()) CircleUIStart(triggerType, (bool)left, openWithDresser);
+
+ if (CircleUI.visible)
+ {
+ left = null;
+ if (mPlayer.LeftClickReleased)
+ {
+ left = true;
+ }
+ else if (mPlayer.RightClickReleased)
+ {
+ left = false;
+ }
+
+ if (left != null && left == CircleUI.openedWithLeft) CircleUIEnd((bool)left);
+
+ if (CircleUI.triggerItemType != triggerType && !CircleUI.triggeredFromDresser) //cancel the UI when you switch items
+ {
+ CircleUI.returned = CircleUI.NONE;
+ CircleUI.visible = false;
+ }
+ }
+ }
+
+ ///
+ /// Called in UpdateUI
+ ///
+ private void UpdatePetVanityUI()
+ {
+ Player player = Main.LocalPlayer;
+ AssPlayer mPlayer = player.GetModPlayer();
+ PetPlayer pPlayer = player.GetModPlayer();
+
+ int itemType = player.HeldItem.type;
+ if (mPlayer.LeftClickPressed && AllowedToOpenUI() && PetAccessory.TryGetAccessoryFromItem(itemType, out PetAccessory petAccessory))
+ {
+ if (petAccessory.HasAlts && pPlayer.HasValidSlimePet(out SlimePet slimePet) &&
+ !slimePet.IsSlotTypeBlacklisted[(int)petAccessory.Slot])
+ {
+ //Spawn UI
+ PetVanityUI.Start(petAccessory);
+ }
+ }
+
+ if (!PetVanityUI.visible)
+ {
+ return;
+ }
+
+ if (mPlayer.LeftClickReleased)
+ {
+ if (PetVanityUI.returned > PetVanityUI.NONE)
+ {
+ //if something returned AND if the returned thing isn't the same as the current one
+
+ try
+ {
+ SoundEngine.PlaySound(SoundID.Item1, player.position);
+ }
+ catch
+ {
+ //No idea why but this threw errors one time
+ }
+ //UIText("Selected: " + PetVanityUI.petAccessory.AltTextureSuffixes[PetVanityUI.returned], CombatText.HealLife);
+
+ PetVanityUI.petAccessory.AltTextureIndex = (byte)PetVanityUI.returned;
+ pPlayer.ToggleAccessory(PetVanityUI.petAccessory);
+ }
+ else if (PetVanityUI.hasEquipped && PetVanityUI.returned == PetVanityUI.NONE)
+ {
+ //hovered over the middle and had something equipped: take accessory away
+ pPlayer.DelAccessory(PetVanityUI.petAccessory);
+ }
+ //else if (returned == PetVanityUI.IGNORE) {nothing happens}
+
+ PetVanityUI.returned = PetVanityUI.NONE;
+ PetVanityUI.visible = false;
+ }
+
+ if (PetVanityUI.petAccessory.Type != itemType) //cancel the UI when you switch items
+ {
+ PetVanityUI.returned = PetVanityUI.NONE;
+ PetVanityUI.visible = false;
+ }
+ }
+
+ private void UpdateHoverNPCUI(GameTime gameTime)
+ {
+ HoverNPCUI.Update(gameTime);
+ }
+
+ private void UpdateEnhancedHunterUI(GameTime gameTime)
+ {
+ if (Main.LocalPlayer.GetModPlayer().enhancedHunterBuff)
+ {
+ EnhancedHunterUI.visible = true;
+ }
+ else
+ {
+ EnhancedHunterUI.visible = false;
+ }
+ EnhancedHunterUI?.Update(gameTime);
+ }
+
+ public override void UpdateUI(GameTime gameTime)
+ {
+ UpdateCircleUI();
+ UpdateHoverNPCUI(gameTime);
+ UpdateEnhancedHunterUI(gameTime);
+ UpdatePetVanityUI();
+ }
+
+ ///
+ /// Checks if LocalPlayer can open a UI
+ ///
+ private bool AllowedToOpenUI()
+ {
+ return Main.hasFocus &&
+ !Main.gamePaused &&
+ !Main.LocalPlayer.dead &&
+ !Main.LocalPlayer.mouseInterface &&
+ !Main.drawingPlayerChat &&
+ !Main.editSign &&
+ !Main.editChest &&
+ !Main.blockInput &&
+ !Main.mapFullscreen &&
+ !Main.HoveringOverAnNPC &&
+ Main.LocalPlayer.cursorItemIconID != -1 &&
+ Main.LocalPlayer.talkNPC == -1 &&
+ Main.LocalPlayer.itemTime == 0 && Main.LocalPlayer.itemAnimation == 0 &&
+ !(Main.LocalPlayer.frozen || Main.LocalPlayer.webbed || Main.LocalPlayer.stoned);
+ }
+
+ public override void ModifyInterfaceLayers(List layers)
+ {
+ int inventoryIndex = layers.FindIndex(layer => layer.Name.Equals("Vanilla: Hotbar"));
+ if (inventoryIndex != -1)
+ {
+ if (CircleUI.visible)
+ {
+ //remove the item icon when using the item while held outside the inventory
+ int mouseItemIndex = layers.FindIndex(layer => layer.Name.Equals("Vanilla: Mouse Item / NPC Head"));
+ if (mouseItemIndex != -1) layers.RemoveAt(mouseItemIndex);
+ layers.Insert(++inventoryIndex, new LegacyGameInterfaceLayer
+ (
+ "ACT: Appearance Select",
+ delegate
+ {
+ CircleUIInterface.Draw(Main.spriteBatch, new GameTime());
+ return true;
+ },
+ InterfaceScaleType.UI)
+ );
+ }
+
+ if (PetVanityUI.visible && PetVanityUIInterface != null)
+ {
+ //remove the item icon when using the item while held outside the inventory
+ int mouseItemIndex = layers.FindIndex(layer => layer.Name.Equals("Vanilla: Mouse Item / NPC Head"));
+ if (mouseItemIndex != -1) layers.RemoveAt(mouseItemIndex);
+ layers.Insert(++inventoryIndex, new LegacyGameInterfaceLayer
+ (
+ "ACT: Pet Vanity Select",
+ delegate
+ {
+ PetVanityUIInterface.Draw(Main.spriteBatch, new GameTime());
+ return true;
+ },
+ InterfaceScaleType.UI)
+ );
+ }
+ }
+
+ int mouseOverIndex = layers.FindIndex(layer => layer.Name.Equals("Vanilla: Mouse Over"));
+ if (mouseOverIndex != -1)
+ {
+ layers.Insert(++mouseOverIndex, new LegacyGameInterfaceLayer
+ (
+ "ACT: NPC Mouse Over",
+ delegate
+ {
+ HoverNPCUIInterface.Draw(Main.spriteBatch, new GameTime());
+ return true;
+ },
+ InterfaceScaleType.UI)
+ );
+
+ if (EnhancedHunterUIInterface != null)
+ {
+ if (EnhancedHunterUI.visible)
+ {
+ layers.Insert(++mouseOverIndex, new LegacyGameInterfaceLayer
+ (
+ "ACT: Enhanced Hunter",
+ delegate
+ {
+ EnhancedHunterUIInterface.Draw(Main.spriteBatch, new GameTime());
+ return true;
+ },
+ InterfaceScaleType.UI)
+ );
+ }
+ }
+
+ if (HarvesterEdgeUIInterface != null)
+ {
+ layers.Insert(++mouseOverIndex, new LegacyGameInterfaceLayer
+ (
+ "ACT: Harvester Edge",
+ delegate
+ {
+ HarvesterEdgeUIInterface.Draw(Main.spriteBatch, new GameTime());
+ return true;
+ },
+ InterfaceScaleType.UI)
+ );
+ }
+ }
+ }
+
+ public override void ModifyTransformMatrix(ref SpriteViewMatrix Transform)
+ {
+ ZoomFactor = Transform.Zoom - (Vector2.UnitX + Vector2.UnitY);
+ }
+ }
}
diff --git a/AssWorld.cs b/AssWorld.cs
index e09b52f0..cae77032 100644
--- a/AssWorld.cs
+++ b/AssWorld.cs
@@ -4,242 +4,242 @@
using System.Collections.Generic;
using System.IO;
using Terraria;
+using Terraria.Audio;
+using Terraria.Chat;
using Terraria.Graphics.Effects;
using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader;
using Terraria.ModLoader.IO;
-using Terraria.Audio;
-using Terraria.Chat;
namespace AssortedCrazyThings
{
- [Content(ConfigurationSystem.AllFlags, needsAllToFilter: true)]
- public class AssWorld : AssSystem
- {
- //basically "if they were alive last update"
- public bool megalodonAlive = false;
- public bool miniocramAlive = false;
- //"are they alive this update"
- bool isMegalodonSpawned;
- bool isMiniocramSpawned;
- //static names, in case you want to change them later
- public static string megalodonName = Megalodon.name;
- public static string miniocramName = SpawnOfOcram.name;
- public static string megalodonMessage = Megalodon.message;
- public static string miniocramMessage = SpawnOfOcram.message;
- //the megalodon messages are modified down below in the Disappear message
-
- //Soul stuff
- public static bool downedHarvester;
-
- public static bool slimeRainSky = false;
-
- public override void OnWorldLoad()
- {
- downedHarvester = false;
- }
-
- public override void SaveWorldData(TagCompound tag)
- {
- var downed = new List();
- if (downedHarvester)
- {
- downed.Add("harvester");
- }
-
- tag.Add("downed", downed);
- }
-
- public override void LoadWorldData(TagCompound tag)
- {
- var downed = tag.GetList("downed");
- downedHarvester = downed.Contains("harvester");
- }
-
- public override void NetSend(BinaryWriter writer)
- {
- BitsByte flags = new BitsByte();
- flags[0] = downedHarvester;
- writer.Write(flags);
-
- }
-
- public override void NetReceive(BinaryReader reader)
- {
- BitsByte flags = reader.ReadByte();
- downedHarvester = flags[0];
- }
-
- //small methods I made for myself to not make the code cluttered since I have to use these six times
- public static void AwakeningMessage(string message, Vector2 pos = default(Vector2), int soundStyle = -1)
- {
- if (soundStyle != -1) SoundEngine.PlaySound(SoundID.Roar, pos, soundStyle); //soundStyle 2 for screech, 0 for regular roar
- Message(message, new Color(175, 75, 255));
- }
-
- public static void Message(string message, Color color)
- {
- if (Main.netMode == NetmodeID.SinglePlayer)
- {
- Main.NewText(message, color);
- }
- else if (Main.netMode == NetmodeID.Server)
- {
- ChatHelper.BroadcastChatMessage(NetworkText.FromLiteral(message), color);
- }
- }
-
- public static void ToggleSlimeRainSky()
- {
- if (!Main.slimeRain && Main.netMode != NetmodeID.MultiplayerClient)
- {
- if (!slimeRainSky)
- {
- SkyManager.Instance.Activate("Slime", default(Vector2));
- CombatText.NewText(Main.LocalPlayer.getRect(), CombatText.HealLife, "Background Activated");
- slimeRainSky = true;
- }
- else
- {
- SkyManager.Instance.Deactivate("Slime");
- CombatText.NewText(Main.LocalPlayer.getRect(), CombatText.DamagedFriendly, "Background Deactivated");
- slimeRainSky = false;
- }
- }
- }
-
- public static void DisableSlimeRainSky()
- {
- if (!Main.slimeRain && slimeRainSky && Main.netMode != NetmodeID.MultiplayerClient)
- {
- SkyManager.Instance.Deactivate("Slime");
- CombatText.NewText(Main.LocalPlayer.getRect(), CombatText.DamagedFriendly, "Background Deactivated");
- slimeRainSky = false;
- }
- }
-
- private void LimitSoulCount()
- {
- if (!ContentConfig.Instance.Bosses)
- {
- return;
- }
-
- if (Main.netMode != NetmodeID.MultiplayerClient)
- {
- if (Main.GameUpdateCount % 30 == 15 && NPC.CountNPCS(ModContent.NPCType()) > 10) //limit soul count in the world to 15
- {
- short oldest = 200;
- int timeleftmin = int.MaxValue;
- for (short j = 0; j < Main.maxNPCs; j++)
- {
- NPC npc = Main.npc[j];
- if (npc.active && npc.type == ModContent.NPCType())
- {
- if (npc.timeLeft < timeleftmin)
- {
- timeleftmin = npc.timeLeft;
- oldest = j;
- }
- }
- }
- if (oldest != Main.maxNPCs)
- {
- NPC oldestnpc = Main.npc[oldest];
- oldestnpc.active = false;
- oldestnpc.netUpdate = true;
- if (Main.netMode == NetmodeID.Server && oldest < Main.maxNPCs)
- {
- NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, oldest);
- }
- //poof visual
- for (int i = 0; i < 15; i++)
- {
- Dust dust = Dust.NewDustPerfect(oldestnpc.Center, 59, new Vector2(Main.rand.NextFloat(-2f, 2f), Main.rand.NextFloat(-2f, 1.5f)), 26, Color.White, Main.rand.NextFloat(1.5f, 2.4f));
- dust.noLight = true;
- dust.noGravity = true;
- dust.fadeIn = Main.rand.NextFloat(0.1f, 0.6f);
- }
- }
- }
- }
- }
-
- private void UpdateEmpoweringFactor()
- {
- if (NPC.downedPlantBoss && AssPlayer.empoweringTotal < 1f)
- AssPlayer.empoweringTotal = 1f;
- else if (Main.hardMode && AssPlayer.empoweringTotal < 0.75f)
- AssPlayer.empoweringTotal = 0.75f;
- }
-
- public override void ResetNearbyTileEffects()
- {
- Main.LocalPlayer.GetModPlayer().wyvernCampfire = false;
- }
-
- public override void PostUpdateWorld()
- {
- CheckSpawns();
- }
-
- private void CheckSpawns()
- {
- if (!ContentConfig.Instance.HostileNPCs)
- {
- return;
- }
-
- //this code is when I first started modding, terrible stuff
- //those flags are checked for trueness each update
- isMegalodonSpawned = false;
- isMiniocramSpawned = false;
- for (short j = 0; j < Main.maxNPCs; j++)
- {
- NPC npc = Main.npc[j];
- if (npc.active)
- {
- if (npc.TypeName == megalodonName && !isMegalodonSpawned)
- {
- isMegalodonSpawned = true;
- //check if it wasnt alive in previous update
- if (!megalodonAlive)
- {
- AwakeningMessage(megalodonMessage, npc.position, 0);
- megalodonAlive = true;
- }
- }
- if (npc.TypeName == miniocramName && !isMiniocramSpawned)
- {
- isMiniocramSpawned = true;
- if (!miniocramAlive)
- {
- AwakeningMessage(miniocramMessage, npc.position, 0);
- miniocramAlive = true;
- }
- }
- }
- }
- //after this we know that either atleast one miniboss is active or not
- //if alive, but not active, print disappear message
- if (!isMegalodonSpawned && megalodonAlive)
- {
- megalodonAlive = false;
- Message("The " + megalodonName + " disappeared... for now", new Color(175, 255, 175));
- }
- if (!isMiniocramSpawned && miniocramAlive)
- {
- miniocramAlive = false;
- Message("The " + miniocramName + " disappeared... for now", new Color(175, 255, 175));
- }
- }
-
- public override void PreUpdateWorld()
- {
- LimitSoulCount();
-
- UpdateEmpoweringFactor();
- }
- }
+ [Content(ConfigurationSystem.AllFlags, needsAllToFilter: true)]
+ public class AssWorld : AssSystem
+ {
+ //basically "if they were alive last update"
+ public bool megalodonAlive = false;
+ public bool miniocramAlive = false;
+ //"are they alive this update"
+ bool isMegalodonSpawned;
+ bool isMiniocramSpawned;
+ //static names, in case you want to change them later
+ public static string megalodonName = Megalodon.name;
+ public static string miniocramName = SpawnOfOcram.name;
+ public static string megalodonMessage = Megalodon.message;
+ public static string miniocramMessage = SpawnOfOcram.message;
+ //the megalodon messages are modified down below in the Disappear message
+
+ //Soul stuff
+ public static bool downedHarvester;
+
+ public static bool slimeRainSky = false;
+
+ public override void OnWorldLoad()
+ {
+ downedHarvester = false;
+ }
+
+ public override void SaveWorldData(TagCompound tag)
+ {
+ var downed = new List();
+ if (downedHarvester)
+ {
+ downed.Add("harvester");
+ }
+
+ tag.Add("downed", downed);
+ }
+
+ public override void LoadWorldData(TagCompound tag)
+ {
+ var downed = tag.GetList("downed");
+ downedHarvester = downed.Contains("harvester");
+ }
+
+ public override void NetSend(BinaryWriter writer)
+ {
+ BitsByte flags = new BitsByte();
+ flags[0] = downedHarvester;
+ writer.Write(flags);
+
+ }
+
+ public override void NetReceive(BinaryReader reader)
+ {
+ BitsByte flags = reader.ReadByte();
+ downedHarvester = flags[0];
+ }
+
+ //small methods I made for myself to not make the code cluttered since I have to use these six times
+ public static void AwakeningMessage(string message, Vector2 pos = default(Vector2), int soundStyle = -1)
+ {
+ if (soundStyle != -1) SoundEngine.PlaySound(SoundID.Roar, pos, soundStyle); //soundStyle 2 for screech, 0 for regular roar
+ Message(message, new Color(175, 75, 255));
+ }
+
+ public static void Message(string message, Color color)
+ {
+ if (Main.netMode == NetmodeID.SinglePlayer)
+ {
+ Main.NewText(message, color);
+ }
+ else if (Main.netMode == NetmodeID.Server)
+ {
+ ChatHelper.BroadcastChatMessage(NetworkText.FromLiteral(message), color);
+ }
+ }
+
+ public static void ToggleSlimeRainSky()
+ {
+ if (!Main.slimeRain && Main.netMode != NetmodeID.MultiplayerClient)
+ {
+ if (!slimeRainSky)
+ {
+ SkyManager.Instance.Activate("Slime", default(Vector2));
+ CombatText.NewText(Main.LocalPlayer.getRect(), CombatText.HealLife, "Background Activated");
+ slimeRainSky = true;
+ }
+ else
+ {
+ SkyManager.Instance.Deactivate("Slime");
+ CombatText.NewText(Main.LocalPlayer.getRect(), CombatText.DamagedFriendly, "Background Deactivated");
+ slimeRainSky = false;
+ }
+ }
+ }
+
+ public static void DisableSlimeRainSky()
+ {
+ if (!Main.slimeRain && slimeRainSky && Main.netMode != NetmodeID.MultiplayerClient)
+ {
+ SkyManager.Instance.Deactivate("Slime");
+ CombatText.NewText(Main.LocalPlayer.getRect(), CombatText.DamagedFriendly, "Background Deactivated");
+ slimeRainSky = false;
+ }
+ }
+
+ private void LimitSoulCount()
+ {
+ if (!ContentConfig.Instance.Bosses)
+ {
+ return;
+ }
+
+ if (Main.netMode != NetmodeID.MultiplayerClient)
+ {
+ if (Main.GameUpdateCount % 30 == 15 && NPC.CountNPCS(ModContent.NPCType()) > 10) //limit soul count in the world to 15
+ {
+ short oldest = 200;
+ int timeleftmin = int.MaxValue;
+ for (short j = 0; j < Main.maxNPCs; j++)
+ {
+ NPC npc = Main.npc[j];
+ if (npc.active && npc.type == ModContent.NPCType())
+ {
+ if (npc.timeLeft < timeleftmin)
+ {
+ timeleftmin = npc.timeLeft;
+ oldest = j;
+ }
+ }
+ }
+ if (oldest != Main.maxNPCs)
+ {
+ NPC oldestnpc = Main.npc[oldest];
+ oldestnpc.active = false;
+ oldestnpc.netUpdate = true;
+ if (Main.netMode == NetmodeID.Server && oldest < Main.maxNPCs)
+ {
+ NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, oldest);
+ }
+ //poof visual
+ for (int i = 0; i < 15; i++)
+ {
+ Dust dust = Dust.NewDustPerfect(oldestnpc.Center, 59, new Vector2(Main.rand.NextFloat(-2f, 2f), Main.rand.NextFloat(-2f, 1.5f)), 26, Color.White, Main.rand.NextFloat(1.5f, 2.4f));
+ dust.noLight = true;
+ dust.noGravity = true;
+ dust.fadeIn = Main.rand.NextFloat(0.1f, 0.6f);
+ }
+ }
+ }
+ }
+ }
+
+ private void UpdateEmpoweringFactor()
+ {
+ if (NPC.downedPlantBoss && AssPlayer.empoweringTotal < 1f)
+ AssPlayer.empoweringTotal = 1f;
+ else if (Main.hardMode && AssPlayer.empoweringTotal < 0.75f)
+ AssPlayer.empoweringTotal = 0.75f;
+ }
+
+ public override void ResetNearbyTileEffects()
+ {
+ Main.LocalPlayer.GetModPlayer().wyvernCampfire = false;
+ }
+
+ public override void PostUpdateWorld()
+ {
+ CheckSpawns();
+ }
+
+ private void CheckSpawns()
+ {
+ if (!ContentConfig.Instance.HostileNPCs)
+ {
+ return;
+ }
+
+ //this code is when I first started modding, terrible stuff
+ //those flags are checked for trueness each update
+ isMegalodonSpawned = false;
+ isMiniocramSpawned = false;
+ for (short j = 0; j < Main.maxNPCs; j++)
+ {
+ NPC npc = Main.npc[j];
+ if (npc.active)
+ {
+ if (npc.TypeName == megalodonName && !isMegalodonSpawned)
+ {
+ isMegalodonSpawned = true;
+ //check if it wasnt alive in previous update
+ if (!megalodonAlive)
+ {
+ AwakeningMessage(megalodonMessage, npc.position, 0);
+ megalodonAlive = true;
+ }
+ }
+ if (npc.TypeName == miniocramName && !isMiniocramSpawned)
+ {
+ isMiniocramSpawned = true;
+ if (!miniocramAlive)
+ {
+ AwakeningMessage(miniocramMessage, npc.position, 0);
+ miniocramAlive = true;
+ }
+ }
+ }
+ }
+ //after this we know that either atleast one miniboss is active or not
+ //if alive, but not active, print disappear message
+ if (!isMegalodonSpawned && megalodonAlive)
+ {
+ megalodonAlive = false;
+ Message("The " + megalodonName + " disappeared... for now", new Color(175, 255, 175));
+ }
+ if (!isMiniocramSpawned && miniocramAlive)
+ {
+ miniocramAlive = false;
+ Message("The " + miniocramName + " disappeared... for now", new Color(175, 255, 175));
+ }
+ }
+
+ public override void PreUpdateWorld()
+ {
+ LimitSoulCount();
+
+ UpdateEmpoweringFactor();
+ }
+ }
}
diff --git a/AssortedCrazyThings.cs b/AssortedCrazyThings.cs
index 617a4f71..7a2cc3ba 100644
--- a/AssortedCrazyThings.cs
+++ b/AssortedCrazyThings.cs
@@ -18,402 +18,402 @@
namespace AssortedCrazyThings
{
- class AssortedCrazyThings : Mod
- {
- //Soul item animated textures
- public const int animatedSoulFrameCount = 6;
- public static Asset[] animatedSoulTextures;
-
- ///
- /// Soul NPC spawn blacklist
- ///
- public static int[] soulBuffBlacklist;
-
- ///
- /// The cached type of the Harvester boss, 0 if not loaded
- ///
- public static int harvester;
- ///
- /// The cached type of the left talon of the Harvester boss, 0 if not loaded
- ///
- public static int harvesterTalonLeft;
- ///
- /// The cached type of the right talon of the Harvester boss, 0 if not loaded
- ///
- public static int harvesterTalonRight;
-
- //Mod Helpers compat
- public static string GithubUserName { get { return "Werebearguy"; } }
- public static string GithubProjectName { get { return "AssortedCrazyThings"; } }
-
- private void LoadSoulBuffBlacklist()
- {
- List tempList = new List
- {
- NPCID.Bee,
- NPCID.BeeSmall,
- NPCID.BlueSlime,
- NPCID.BlazingWheel,
- NPCID.EaterofWorldsHead,
- NPCID.EaterofWorldsBody,
- NPCID.EaterofWorldsTail,
- NPCID.Creeper,
- NPCID.GolemFistLeft,
- NPCID.GolemFistRight,
- NPCID.PlanterasHook,
- NPCID.PlanterasTentacle,
- NPCID.Probe,
- NPCID.ServantofCthulhu,
- NPCID.SlimeSpiked,
- NPCID.SpikeBall,
- NPCID.TheHungry,
- NPCID.TheHungryII,
- };
-
- soulBuffBlacklist = tempList.ToArray();
- }
-
- ///
- /// Assuming this is called after InitSoulBuffBlacklist.
- /// Adds NPC types to soulBuffBlacklist manually
- ///
- private void AddToSoulBuffBlacklist()
- {
- if (!ContentConfig.Instance.Bosses)
- {
- return;
- }
-
- //assuming this is called after InitSoulBuffBlacklist
- List tempList = new List(soulBuffBlacklist)
- {
- ModContent.NPCType(),
- ModContent.NPCType(),
- };
-
- soulBuffBlacklist = tempList.ToArray();
- Array.Sort(soulBuffBlacklist);
- }
-
- ///
- /// Fills isModdedWormBodyOrTail with types of modded NPCs which names are ending with Body or Tail (indicating they are part of something)
- ///
- private void LoadWormList()
- {
- List tempList = new List();
-
- for (int i = Main.maxNPCTypes; i < NPCLoader.NPCCount; i++)
- {
- ModNPC modNPC = NPCLoader.GetNPC(i);
- if (modNPC != null && (modNPC.GetType().Name.EndsWith("Body") || modNPC.GetType().Name.EndsWith("Tail")))
- {
- tempList.Add(modNPC.NPC.type);
- }
- }
-
- AssUtils.isModdedWormBodyOrTail = tempList.ToArray();
- Array.Sort(AssUtils.isModdedWormBodyOrTail);
- }
-
- private void LoadHarvesterTypes()
- {
- if (!ContentConfig.Instance.Bosses)
- {
- return;
- }
-
- harvester = ModContent.NPCType();
- harvesterTalonLeft = ModContent.NPCType();
- harvesterTalonRight = ModContent.NPCType();
- }
-
- private void LoadMisc()
- {
- if (!Main.dedServ && ContentConfig.Instance.Bosses)
- {
- animatedSoulTextures = new Asset[2];
-
- animatedSoulTextures[0] = Assets.Request("Items/CaughtDungeonSoulAnimated");
- animatedSoulTextures[1] = Assets.Request("Items/CaughtDungeonSoulFreedAnimated");
- }
- }
-
- private void UnloadMisc()
- {
- animatedSoulTextures = null;
-
- PetEaterofWorldsBase.wormTypes = null;
-
- PetDestroyerBase.wormTypes = null;
- }
-
- public override void Load()
- {
- ConfigurationSystem.Load();
-
- ShaderManager.Load();
-
- LoadHarvesterTypes();
-
- LoadSoulBuffBlacklist();
-
- LoadMisc();
- }
-
- public override void Unload()
- {
- ConfigurationSystem.Unload();
-
- ShaderManager.Unload();
-
- UnloadMisc();
-
- GitgudData.Unload();
-
- EverhallowedLantern.DoUnload();
- }
-
- public override void PostSetupContent()
- {
- //for things that have to be called after Load() because of Main.projFrames[projectile.type] calls (and similar)
- LoadWormList();
-
- GitgudData.Load();
-
- DroneController.DoLoad();
-
- EverhallowedLantern.DoLoad();
-
- AddToSoulBuffBlacklist();
-
- if (ContentConfig.Instance.DroppedPets)
- {
- PetEaterofWorldsBase.wormTypes = new int[]
- {
- ModContent.ProjectileType(),
- ModContent.ProjectileType(),
- ModContent.ProjectileType(),
- ModContent.ProjectileType()
- };
-
- PetDestroyerBase.wormTypes = new int[]
- {
- ModContent.ProjectileType(),
- ModContent.ProjectileType(),
- ModContent.ProjectileType(),
- ModContent.ProjectileType()
- };
- }
- }
-
- public override void AddRecipeGroups()
- {
- string any = Language.GetTextValue("LegacyMisc.37") + " ";
- if (ContentConfig.Instance.CuteSlimes && ContentConfig.Instance.PlaceablesFunctional)
- {
- RecipeGroup.RegisterGroup("ACT:RegularCuteSlimes", new RecipeGroup(() => any + "Regular Bottled Slime", new int[]
- {
- ModContent.ItemType(),
- ModContent.ItemType(),
- ModContent.ItemType(),
- ModContent.ItemType(),
- ModContent.ItemType(),
- ModContent.ItemType(),
- ModContent.ItemType(),
- ModContent.ItemType()
- }));
- }
-
- RecipeGroup.RegisterGroup("ACT:EvilWood", new RecipeGroup(() => any + Lang.GetItemNameValue(ItemID.Ebonwood), new int[]
- {
- ItemID.Ebonwood,
- ItemID.Shadewood
- }));
-
- RecipeGroup.RegisterGroup("ACT:GoldPlatinum", new RecipeGroup(() => any + Lang.GetItemNameValue(ItemID.GoldBar), new int[]
- {
- ItemID.GoldBar,
- ItemID.PlatinumBar
- }));
-
- RecipeGroup.RegisterGroup("ACT:AdamantiteTitanium", new RecipeGroup(() => any + Lang.GetItemNameValue(ItemID.AdamantiteBar), new int[]
- {
- ItemID.AdamantiteBar,
- ItemID.TitaniumBar
- }));
-
- RecipeGroup.RegisterGroup("ACT:DemoniteCrimtane", new RecipeGroup(() => any + Lang.GetItemNameValue(ItemID.DemoniteBar), new int[]
- {
- ItemID.DemoniteBar,
- ItemID.CrimtaneBar
- }));
- }
-
- public override void HandlePacket(BinaryReader reader, int whoAmI)
- {
- AssMessageType msgType = (AssMessageType)reader.ReadByte();
- byte playerNumber;
- byte npcNumber;
- AssPlayer aPlayer;
- PetPlayer petPlayer;
- byte changes;
- byte index;
-
- switch (msgType)
- {
- case AssMessageType.SyncPlayerVanity:
- playerNumber = reader.ReadByte();
- petPlayer = Main.player[playerNumber].GetModPlayer();
- //no "changes" packet
- petPlayer.RecvSyncPlayerVanitySub(reader);
- break;
- case AssMessageType.ClientChangesVanity:
- //client and server
- //getmodplayer error
- playerNumber = reader.ReadByte();
- petPlayer = Main.player[playerNumber].GetModPlayer();
- changes = reader.ReadByte();
- index = reader.ReadByte();
- petPlayer.RecvClientChangesPacketSub(reader, changes, index);
-
- //server transmits to others
- if (Main.netMode == NetmodeID.Server)
- {
- petPlayer.SendClientChangesPacketSub(changes, index, toClient: -1, ignoreClient: playerNumber);
- }
- break;
- case AssMessageType.SyncAssPlayer:
- playerNumber = reader.ReadByte();
- aPlayer = Main.player[playerNumber].GetModPlayer();
- aPlayer.ReceiveSyncPlayer(reader);
- break;
- case AssMessageType.ClientChangesAssPlayer:
- //client and server
- //getmodplayer error
- playerNumber = reader.ReadByte();
- aPlayer = Main.player[playerNumber].GetModPlayer();
- aPlayer.shieldDroneReduction = reader.ReadByte();
- aPlayer.droneControllerUnlocked = (DroneType)reader.ReadByte();
-
- //server transmits to others
- if (Main.netMode == NetmodeID.Server)
- {
- aPlayer.SendClientChangesPacket(toClient: -1, ignoreClient: playerNumber);
- }
- break;
- case AssMessageType.ConvertInertSoulsInventory:
- if (Main.netMode == NetmodeID.MultiplayerClient)
- {
- //convert souls in local inventory
- aPlayer = Main.LocalPlayer.GetModPlayer();
- aPlayer.ConvertInertSoulsInventory();
- }
- break;
- case AssMessageType.GitgudLoadCounters:
- if (Main.netMode == NetmodeID.Server)
- {
- GitgudData.RecvCounters(reader);
- }
- break;
- case AssMessageType.GitgudChangeCounters:
- if (Main.netMode == NetmodeID.MultiplayerClient)
- {
- //GitgudData.RecvReset(Main.myPlayer, reader);
- GitgudData.RecvChangeCounter(reader);
- }
- break;
- case AssMessageType.ResetEmpoweringTimerpvp:
- //client and server
- playerNumber = reader.ReadByte();
- aPlayer = Main.player[playerNumber].GetModPlayer();
- aPlayer.ResetEmpoweringTimer(fromServer: true);
-
- //server transmits to others
- if (Main.netMode == NetmodeID.Server)
- {
- ModPacket packet = GetPacket();
- packet.Write((byte)AssMessageType.ResetEmpoweringTimerpvp);
- packet.Write((byte)playerNumber);
- packet.Send(playerNumber); //send to client
- }
- break;
- case AssMessageType.WyvernCampfireKill:
- npcNumber = reader.ReadByte();
- if (npcNumber < 0 || npcNumber >= Main.maxNPCs) break;
- NPC npc = Main.npc[npcNumber];
- if (npc.type == NPCID.WyvernHead)
- {
- DungeonSoulBase.KillInstantly(npc);
- if (npcNumber < Main.maxNPCs)
- {
- NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, npcNumber);
- }
- }
- else
- {
- for (int k = 0; k < Main.maxNPCs; k++)
- {
- NPC other = Main.npc[k];
- if (other.active && other.type == NPCID.WyvernHead)
- {
- DungeonSoulBase.KillInstantly(other);
- if (k < Main.maxNPCs)
- {
- NetMessage.SendData(MessageID.SyncNPC, number: k);
- }
- break;
- }
- }
- }
- break;
- case AssMessageType.SlainBoss:
- if (Main.netMode == NetmodeID.MultiplayerClient)
- {
- int type = reader.ReadVarInt();
- Main.LocalPlayer.GetModPlayer().SlainBoss(type);
- }
- break;
- default:
- Logger.Debug("Unknown Message type: " + msgType);
- break;
- }
- }
-
- //Credit to jopojelly
- ///
- /// Makes alpha on .png textures actually properly rendered
- ///
- public static void PremultiplyTexture(Texture2D texture)
- {
- Color[] buffer = new Color[texture.Width * texture.Height];
- texture.GetData(buffer);
- for (int i = 0; i < buffer.Length; i++)
- {
- buffer[i] = Color.FromNonPremultiplied(buffer[i].R, buffer[i].G, buffer[i].B, buffer[i].A);
- }
- texture.SetData(buffer);
- }
- }
-
- public enum AssMessageType : byte
- {
- ClientChangesVanity,
- SyncPlayerVanity,
- ClientChangesAssPlayer,
- SyncAssPlayer,
- ConvertInertSoulsInventory,
- GitgudLoadCounters,
- GitgudChangeCounters,
- ResetEmpoweringTimerpvp,
- WyvernCampfireKill,
- SlainBoss
- }
-
- public enum PetPlayerChanges : byte
- {
- None,
- All,
- Slots,
- PetTypes
- }
+ class AssortedCrazyThings : Mod
+ {
+ //Soul item animated textures
+ public const int animatedSoulFrameCount = 6;
+ public static Asset[] animatedSoulTextures;
+
+ ///
+ /// Soul NPC spawn blacklist
+ ///
+ public static int[] soulBuffBlacklist;
+
+ ///
+ /// The cached type of the Harvester boss, 0 if not loaded
+ ///
+ public static int harvester;
+ ///
+ /// The cached type of the left talon of the Harvester boss, 0 if not loaded
+ ///
+ public static int harvesterTalonLeft;
+ ///
+ /// The cached type of the right talon of the Harvester boss, 0 if not loaded
+ ///
+ public static int harvesterTalonRight;
+
+ //Mod Helpers compat
+ public static string GithubUserName { get { return "Werebearguy"; } }
+ public static string GithubProjectName { get { return "AssortedCrazyThings"; } }
+
+ private void LoadSoulBuffBlacklist()
+ {
+ List tempList = new List
+ {
+ NPCID.Bee,
+ NPCID.BeeSmall,
+ NPCID.BlueSlime,
+ NPCID.BlazingWheel,
+ NPCID.EaterofWorldsHead,
+ NPCID.EaterofWorldsBody,
+ NPCID.EaterofWorldsTail,
+ NPCID.Creeper,
+ NPCID.GolemFistLeft,
+ NPCID.GolemFistRight,
+ NPCID.PlanterasHook,
+ NPCID.PlanterasTentacle,
+ NPCID.Probe,
+ NPCID.ServantofCthulhu,
+ NPCID.SlimeSpiked,
+ NPCID.SpikeBall,
+ NPCID.TheHungry,
+ NPCID.TheHungryII,
+ };
+
+ soulBuffBlacklist = tempList.ToArray();
+ }
+
+ ///
+ /// Assuming this is called after InitSoulBuffBlacklist.
+ /// Adds NPC types to soulBuffBlacklist manually
+ ///
+ private void AddToSoulBuffBlacklist()
+ {
+ if (!ContentConfig.Instance.Bosses)
+ {
+ return;
+ }
+
+ //assuming this is called after InitSoulBuffBlacklist
+ List tempList = new List(soulBuffBlacklist)
+ {
+ ModContent.NPCType(),
+ ModContent.NPCType(),
+ };
+
+ soulBuffBlacklist = tempList.ToArray();
+ Array.Sort(soulBuffBlacklist);
+ }
+
+ ///
+ /// Fills isModdedWormBodyOrTail with types of modded NPCs which names are ending with Body or Tail (indicating they are part of something)
+ ///
+ private void LoadWormList()
+ {
+ List tempList = new List();
+
+ for (int i = Main.maxNPCTypes; i < NPCLoader.NPCCount; i++)
+ {
+ ModNPC modNPC = NPCLoader.GetNPC(i);
+ if (modNPC != null && (modNPC.GetType().Name.EndsWith("Body") || modNPC.GetType().Name.EndsWith("Tail")))
+ {
+ tempList.Add(modNPC.NPC.type);
+ }
+ }
+
+ AssUtils.isModdedWormBodyOrTail = tempList.ToArray();
+ Array.Sort(AssUtils.isModdedWormBodyOrTail);
+ }
+
+ private void LoadHarvesterTypes()
+ {
+ if (!ContentConfig.Instance.Bosses)
+ {
+ return;
+ }
+
+ harvester = ModContent.NPCType();
+ harvesterTalonLeft = ModContent.NPCType();
+ harvesterTalonRight = ModContent.NPCType();
+ }
+
+ private void LoadMisc()
+ {
+ if (!Main.dedServ && ContentConfig.Instance.Bosses)
+ {
+ animatedSoulTextures = new Asset[2];
+
+ animatedSoulTextures[0] = Assets.Request("Items/CaughtDungeonSoulAnimated");
+ animatedSoulTextures[1] = Assets.Request("Items/CaughtDungeonSoulFreedAnimated");
+ }
+ }
+
+ private void UnloadMisc()
+ {
+ animatedSoulTextures = null;
+
+ PetEaterofWorldsBase.wormTypes = null;
+
+ PetDestroyerBase.wormTypes = null;
+ }
+
+ public override void Load()
+ {
+ ConfigurationSystem.Load();
+
+ ShaderManager.Load();
+
+ LoadHarvesterTypes();
+
+ LoadSoulBuffBlacklist();
+
+ LoadMisc();
+ }
+
+ public override void Unload()
+ {
+ ConfigurationSystem.Unload();
+
+ ShaderManager.Unload();
+
+ UnloadMisc();
+
+ GitgudData.Unload();
+
+ EverhallowedLantern.DoUnload();
+ }
+
+ public override void PostSetupContent()
+ {
+ //for things that have to be called after Load() because of Main.projFrames[projectile.type] calls (and similar)
+ LoadWormList();
+
+ GitgudData.Load();
+
+ DroneController.DoLoad();
+
+ EverhallowedLantern.DoLoad();
+
+ AddToSoulBuffBlacklist();
+
+ if (ContentConfig.Instance.DroppedPets)
+ {
+ PetEaterofWorldsBase.wormTypes = new int[]
+ {
+ ModContent.ProjectileType(),
+ ModContent.ProjectileType(),
+ ModContent.ProjectileType(),
+ ModContent.ProjectileType()
+ };
+
+ PetDestroyerBase.wormTypes = new int[]
+ {
+ ModContent.ProjectileType(),
+ ModContent.ProjectileType(),
+ ModContent.ProjectileType(),
+ ModContent.ProjectileType()
+ };
+ }
+ }
+
+ public override void AddRecipeGroups()
+ {
+ string any = Language.GetTextValue("LegacyMisc.37") + " ";
+ if (ContentConfig.Instance.CuteSlimes && ContentConfig.Instance.PlaceablesFunctional)
+ {
+ RecipeGroup.RegisterGroup("ACT:RegularCuteSlimes", new RecipeGroup(() => any + "Regular Bottled Slime", new int[]
+ {
+ ModContent.ItemType(),
+ ModContent.ItemType(),
+ ModContent.ItemType(),
+ ModContent.ItemType(),
+ ModContent.ItemType(),
+ ModContent.ItemType(),
+ ModContent.ItemType(),
+ ModContent.ItemType()
+ }));
+ }
+
+ RecipeGroup.RegisterGroup("ACT:EvilWood", new RecipeGroup(() => any + Lang.GetItemNameValue(ItemID.Ebonwood), new int[]
+ {
+ ItemID.Ebonwood,
+ ItemID.Shadewood
+ }));
+
+ RecipeGroup.RegisterGroup("ACT:GoldPlatinum", new RecipeGroup(() => any + Lang.GetItemNameValue(ItemID.GoldBar), new int[]
+ {
+ ItemID.GoldBar,
+ ItemID.PlatinumBar
+ }));
+
+ RecipeGroup.RegisterGroup("ACT:AdamantiteTitanium", new RecipeGroup(() => any + Lang.GetItemNameValue(ItemID.AdamantiteBar), new int[]
+ {
+ ItemID.AdamantiteBar,
+ ItemID.TitaniumBar
+ }));
+
+ RecipeGroup.RegisterGroup("ACT:DemoniteCrimtane", new RecipeGroup(() => any + Lang.GetItemNameValue(ItemID.DemoniteBar), new int[]
+ {
+ ItemID.DemoniteBar,
+ ItemID.CrimtaneBar
+ }));
+ }
+
+ public override void HandlePacket(BinaryReader reader, int whoAmI)
+ {
+ AssMessageType msgType = (AssMessageType)reader.ReadByte();
+ byte playerNumber;
+ byte npcNumber;
+ AssPlayer aPlayer;
+ PetPlayer petPlayer;
+ byte changes;
+ byte index;
+
+ switch (msgType)
+ {
+ case AssMessageType.SyncPlayerVanity:
+ playerNumber = reader.ReadByte();
+ petPlayer = Main.player[playerNumber].GetModPlayer();
+ //no "changes" packet
+ petPlayer.RecvSyncPlayerVanitySub(reader);
+ break;
+ case AssMessageType.ClientChangesVanity:
+ //client and server
+ //getmodplayer error
+ playerNumber = reader.ReadByte();
+ petPlayer = Main.player[playerNumber].GetModPlayer();
+ changes = reader.ReadByte();
+ index = reader.ReadByte();
+ petPlayer.RecvClientChangesPacketSub(reader, changes, index);
+
+ //server transmits to others
+ if (Main.netMode == NetmodeID.Server)
+ {
+ petPlayer.SendClientChangesPacketSub(changes, index, toClient: -1, ignoreClient: playerNumber);
+ }
+ break;
+ case AssMessageType.SyncAssPlayer:
+ playerNumber = reader.ReadByte();
+ aPlayer = Main.player[playerNumber].GetModPlayer();
+ aPlayer.ReceiveSyncPlayer(reader);
+ break;
+ case AssMessageType.ClientChangesAssPlayer:
+ //client and server
+ //getmodplayer error
+ playerNumber = reader.ReadByte();
+ aPlayer = Main.player[playerNumber].GetModPlayer();
+ aPlayer.shieldDroneReduction = reader.ReadByte();
+ aPlayer.droneControllerUnlocked = (DroneType)reader.ReadByte();
+
+ //server transmits to others
+ if (Main.netMode == NetmodeID.Server)
+ {
+ aPlayer.SendClientChangesPacket(toClient: -1, ignoreClient: playerNumber);
+ }
+ break;
+ case AssMessageType.ConvertInertSoulsInventory:
+ if (Main.netMode == NetmodeID.MultiplayerClient)
+ {
+ //convert souls in local inventory
+ aPlayer = Main.LocalPlayer.GetModPlayer();
+ aPlayer.ConvertInertSoulsInventory();
+ }
+ break;
+ case AssMessageType.GitgudLoadCounters:
+ if (Main.netMode == NetmodeID.Server)
+ {
+ GitgudData.RecvCounters(reader);
+ }
+ break;
+ case AssMessageType.GitgudChangeCounters:
+ if (Main.netMode == NetmodeID.MultiplayerClient)
+ {
+ //GitgudData.RecvReset(Main.myPlayer, reader);
+ GitgudData.RecvChangeCounter(reader);
+ }
+ break;
+ case AssMessageType.ResetEmpoweringTimerpvp:
+ //client and server
+ playerNumber = reader.ReadByte();
+ aPlayer = Main.player[playerNumber].GetModPlayer();
+ aPlayer.ResetEmpoweringTimer(fromServer: true);
+
+ //server transmits to others
+ if (Main.netMode == NetmodeID.Server)
+ {
+ ModPacket packet = GetPacket();
+ packet.Write((byte)AssMessageType.ResetEmpoweringTimerpvp);
+ packet.Write((byte)playerNumber);
+ packet.Send(playerNumber); //send to client
+ }
+ break;
+ case AssMessageType.WyvernCampfireKill:
+ npcNumber = reader.ReadByte();
+ if (npcNumber < 0 || npcNumber >= Main.maxNPCs) break;
+ NPC npc = Main.npc[npcNumber];
+ if (npc.type == NPCID.WyvernHead)
+ {
+ DungeonSoulBase.KillInstantly(npc);
+ if (npcNumber < Main.maxNPCs)
+ {
+ NetMessage.SendData(MessageID.SyncNPC, -1, -1, null, npcNumber);
+ }
+ }
+ else
+ {
+ for (int k = 0; k < Main.maxNPCs; k++)
+ {
+ NPC other = Main.npc[k];
+ if (other.active && other.type == NPCID.WyvernHead)
+ {
+ DungeonSoulBase.KillInstantly(other);
+ if (k < Main.maxNPCs)
+ {
+ NetMessage.SendData(MessageID.SyncNPC, number: k);
+ }
+ break;
+ }
+ }
+ }
+ break;
+ case AssMessageType.SlainBoss:
+ if (Main.netMode == NetmodeID.MultiplayerClient)
+ {
+ int type = reader.ReadVarInt();
+ Main.LocalPlayer.GetModPlayer().SlainBoss(type);
+ }
+ break;
+ default:
+ Logger.Debug("Unknown Message type: " + msgType);
+ break;
+ }
+ }
+
+ //Credit to jopojelly
+ ///
+ /// Makes alpha on .png textures actually properly rendered
+ ///
+ public static void PremultiplyTexture(Texture2D texture)
+ {
+ Color[] buffer = new Color[texture.Width * texture.Height];
+ texture.GetData(buffer);
+ for (int i = 0; i < buffer.Length; i++)
+ {
+ buffer[i] = Color.FromNonPremultiplied(buffer[i].R, buffer[i].G, buffer[i].B, buffer[i].A);
+ }
+ texture.SetData(buffer);
+ }
+ }
+
+ public enum AssMessageType : byte
+ {
+ ClientChangesVanity,
+ SyncPlayerVanity,
+ ClientChangesAssPlayer,
+ SyncAssPlayer,
+ ConvertInertSoulsInventory,
+ GitgudLoadCounters,
+ GitgudChangeCounters,
+ ResetEmpoweringTimerpvp,
+ WyvernCampfireKill,
+ SlainBoss
+ }
+
+ public enum PetPlayerChanges : byte
+ {
+ None,
+ All,
+ Slots,
+ PetTypes
+ }
}
diff --git a/Base/AssAI.cs b/Base/AssAI.cs
index 922247a1..8fb8def4 100644
--- a/Base/AssAI.cs
+++ b/Base/AssAI.cs
@@ -7,1793 +7,1793 @@
namespace AssortedCrazyThings.Base
{
- ///
- /// contains AI for stuff that only uses ai[], used with thing.aiStyle = -1
- ///
- public static class AssAI
- {
- ///
- /// Makes the projectile teleport if it is too far away from the given location
- ///
- public static bool TeleportIfTooFar(Projectile projectile, Vector2 desiredCenter, int distance = 2000)
- {
- if (projectile.DistanceSQ(desiredCenter) > distance * distance)
- {
- projectile.Center = desiredCenter;
- if (Main.myPlayer == projectile.owner) projectile.netUpdate = true;
- return true;
- }
- return false;
- }
-
- ///
- /// Finds target in range of relativeCenter. Returns index of target
- ///
- public static int FindTarget(Entity ent, Vector2 relativeCenter, float range, bool ignoreTiles = false)
- {
- int targetIndex = -1;
- float distanceFromTarget = 10000000f;
- Vector2 targetCenter = relativeCenter;
- range *= range;
- for (int k = 0; k < Main.maxNPCs; k++)
- {
- NPC npc = Main.npc[k];
- if (npc.CanBeChasedBy())
- {
- //Collision.CanHitLine(projectile.position, projectile.width, projectile.height, npc.position, npc.width, npc.height)
- float between = Vector2.DistanceSquared(npc.Center, relativeCenter);
- if ((between < range && Vector2.DistanceSquared(relativeCenter, targetCenter) > between && between < distanceFromTarget) || targetIndex == -1)
- {
- if (ignoreTiles || Collision.CanHitLine(ent.position, ent.width, ent.height, npc.position, npc.width, npc.height))
- {
- distanceFromTarget = between;
- targetCenter = npc.Center;
- targetIndex = k;
- }
- }
- }
- }
- return distanceFromTarget < range ? targetIndex : -1;
- }
-
- ///
- /// Utility for minion AI that handles a custom stuck timer for when the X coordinate doesn't change for a given duration.
- ///
- /// The projectile
- /// The X coordinate of the idle location (to not increment the timer when near that)
- /// The timer
- /// The maximum duration
- /// Returns true if the timer overflows
- public static bool HandleStuck(this Projectile projectile, float restingX, ref int stuckTimer, int stuckTimerMax)
- {
- if (projectile.position.X == projectile.oldPosition.X && Math.Abs(projectile.Center.X - restingX) >= 50)
- {
- stuckTimer++;
-
- if (stuckTimer >= stuckTimerMax)
- {
- stuckTimer = 0;
- return true;
- }
- }
- else
- {
- if (stuckTimer >= 2)
- {
- stuckTimer -= 2;
- }
- }
-
- return false;
- }
-
- #region Flickerwick
- public static void FlickerwickPetDraw(Projectile projectile, int frameCounterMaxFar, int frameCounterMaxClose)
- {
- projectile.LoopAnimation((projectile.velocity.Length() > 6f) ? frameCounterMaxFar : frameCounterMaxClose);
- }
-
- ///
- /// No use of ai[] or LocalAI[].
- /// Default offset is x = 30, y = -20
- ///
- public static void FlickerwickPetAI(Projectile projectile, bool lightPet = true, bool lightDust = true, bool staticDirection = false, bool reverseSide = false, bool vanityPet = false, float veloXToRotationFactor = 1f, float veloSpeed = 1f, float lightFactor = 1f, Vector3 lightColor = default(Vector3), float offsetX = 0f, float offsetY = 0f)
- {
- //veloSpeed not bigger than veloDistanceChange * 0.5f
- Player player = projectile.GetOwner();
- float veloDistanceChange = 2f; //6f
-
- int dir = player.direction;
- if (staticDirection)
- {
- if (reverseSide)
- {
- dir = -1;
- }
- else
- {
- dir = 1;
- }
- }
- else
- {
- if (reverseSide)
- {
- dir = -dir;
- }
- }
-
- //up and down bobbing
- //projectile.localAI[0] += 1f;
- //if (projectile.localAI[0] > 120f)
- //{
- // projectile.localAI[0] = 0f;
- //}
- //value.Y += (float)Math.Cos((double)(projectile.localAI[0] * 0.05235988f)) * 2f;
-
- Vector2 dustOffset = new Vector2((projectile.spriteDirection == -1) ? -6 : -2, -20f).RotatedBy(projectile.rotation);
-
- Vector2 desiredCenterRelative = new Vector2(dir * (offsetX + 30), -20f + offsetY);
-
- projectile.direction = projectile.spriteDirection = dir;
-
- //if (reverseSide)
- //{
- // desiredCenterRelative.X = -desiredCenterRelative.X;
- // //value2.X = -value2.X;
- // projectile.direction = -projectile.direction;
- // projectile.spriteDirection = -projectile.spriteDirection;
- //}
-
- if (lightDust && Main.rand.Next(24) == 0)
- {
- Dust dust = Dust.NewDustDirect(projectile.Center + dustOffset, 4, 4, 135, 0f, 0f, 100);
- if (Main.rand.Next(3) != 0)
- {
- dust.noGravity = true;
- dust.velocity.Y += -3f;
- dust.noLight = true;
- }
- else if (Main.rand.Next(2) != 0)
- {
- dust.noLight = true;
- }
- dust.velocity *= 0.5f;
- dust.velocity.Y += -0.9f;
- dust.scale += 0.1f + Main.rand.NextFloat() * 0.6f;
- dust.shader = GameShaders.Armor.GetSecondaryShader(Main.GetProjectileDesiredShader(projectile.whoAmI), player);
- }
-
- if (lightPet)
- {
- if (lightColor == default(Vector3)) lightColor = new Vector3(0.3f, 0.5f, 1f);
- //flickerwick is new Vector3(0.3f, 0.5f, 1f)
- Vector3 vector = DelegateMethods.v3_1 = lightColor * lightFactor;
- Utils.PlotTileLine(projectile.Center, projectile.Center + projectile.velocity * 6f, 20f, DelegateMethods.CastLightOpen);
- Utils.PlotTileLine(projectile.Left, projectile.Right, 20f, DelegateMethods.CastLightOpen);
- Utils.PlotTileLine(player.Center, player.Center + player.velocity * 6f, 40f, DelegateMethods.CastLightOpen);
- Utils.PlotTileLine(player.Left, player.Right, 40f, DelegateMethods.CastLightOpen);
- }
-
- Vector2 desiredCenter = player.MountedCenter + desiredCenterRelative;
- Vector2 betweenDirection = desiredCenter - projectile.Center;
- float betweenSQ = betweenDirection.LengthSquared();
- //if (between > 1000f)
- //{
- // projectile.Center = player.Center + desiredCenterRelative;
- //}
- TeleportIfTooFar(projectile, desiredCenter, 1000);
- if (betweenSQ < veloDistanceChange * veloDistanceChange)
- {
- projectile.velocity *= 0.25f;
- }
- if (betweenDirection != Vector2.Zero)
- {
- if (betweenSQ < (veloDistanceChange * 0.5f) * (veloDistanceChange * 0.5f))
- {
- projectile.velocity = betweenDirection * veloSpeed;
- }
- else
- {
- projectile.velocity = betweenDirection * 0.1f * veloSpeed;
- }
- }
- if (projectile.velocity.LengthSquared() > 6f * 6f)
- {
- float rotationVelo = projectile.velocity.X * 0.08f * veloXToRotationFactor + projectile.velocity.Y * projectile.spriteDirection * 0.02f;
- if (Math.Abs(projectile.rotation - rotationVelo) >= 3.14159274f)
- {
- if (rotationVelo < projectile.rotation)
- {
- projectile.rotation -= 6.28318548f;
- }
- else
- {
- projectile.rotation += 6.28318548f;
- }
- }
- float rotationAcc = 12f;
- projectile.rotation = (projectile.rotation * (rotationAcc - 1f) + rotationVelo) / rotationAcc;
- }
- else
- {
- if (projectile.rotation > 3.14159274f)
- {
- projectile.rotation -= 6.28318548f;
- }
- if (projectile.rotation > -0.005f && projectile.rotation < 0.005f)
- {
- projectile.rotation = 0f;
- }
- else
- {
- projectile.rotation *= 0.96f;
- }
- }
- }
- #endregion
-
- #region EyeSpring
-
- ///
- /// Almost proper working Eye Spring clone
- ///
- public static void EyeSpringAI(Projectile projectile, bool flyForever = false)
- {
- Player player = projectile.GetOwner();
- if (!player.active)
- {
- projectile.active = false;
- }
- else
- {
- bool flag = false;
- bool flag2 = false;
- bool flag3 = false;
- bool flag4 = false;
- int num = 85;
- if (player.position.X + (float)(player.width / 2) < projectile.position.X + (float)(projectile.width / 2) - (float)num)
- {
- flag = true;
- }
- else if (player.position.X + (float)(player.width / 2) > projectile.position.X + (float)(projectile.width / 2) + (float)num)
- {
- flag2 = true;
- }
- if (projectile.ai[1] == 0f)
- {
- int num38 = 500;
- if (player.rocketDelay2 > 0)
- {
- projectile.ai[0] = 1f;
- }
- Vector2 vector6 = new Vector2(projectile.position.X + (float)projectile.width * 0.5f, projectile.position.Y + (float)projectile.height * 0.5f);
- float num39 = player.position.X + (float)(player.width / 2) - vector6.X;
- float num40 = player.position.Y + (float)(player.height / 2) - vector6.Y;
- float num41 = (float)Math.Sqrt((double)(num39 * num39 + num40 * num40));
- if (num41 > 2000f)
- {
- TeleportIfTooFar(projectile, player.Center);
- //projectile.position.X = player.position.X + (float)(player.width / 2) - (float)(projectile.width / 2);
- //projectile.position.Y = player.position.Y + (float)(player.height / 2) - (float)(projectile.height / 2);
- }
- else if (num41 > (float)num38 || (Math.Abs(num40) > 300f) || flyForever)
- {
- projectile.ai[0] = 1f;
- }
- }
- if (projectile.ai[0] != 0f)
- {
- float num42 = 0.2f;
- int num43 = 200;
- projectile.tileCollide = false;
- Vector2 vector7 = new Vector2(projectile.position.X + (float)projectile.width * 0.5f, projectile.position.Y + (float)projectile.height * 0.5f);
- float num44 = player.position.X + (float)(player.width / 2) - vector7.X;
- float num51 = player.position.Y + (float)(player.height / 2) - vector7.Y;
- float num52 = (float)Math.Sqrt((double)(num44 * num44 + num51 * num51));
- float num53 = 10f;
- //float num54 = num52;
- if (num52 < (float)num43 && player.velocity.Y == 0f && projectile.position.Y + (float)projectile.height <= player.position.Y + (float)player.height && !Collision.SolidCollision(projectile.position, projectile.width, projectile.height))
- {
- projectile.ai[0] = 0f;
- if (projectile.velocity.Y < -6f)
- {
- projectile.velocity.Y = -6f;
- }
- }
- if (num52 < 60f)
- {
- num44 = projectile.velocity.X;
- num51 = projectile.velocity.Y;
- }
- else
- {
- num52 = num53 / num52;
- num44 *= num52;
- num51 *= num52;
- }
- if (projectile.velocity.X < num44)
- {
- projectile.velocity.X += num42;
- if (projectile.velocity.X < 0f)
- {
- projectile.velocity.X += num42 * 1.5f;
- }
- }
- if (projectile.velocity.X > num44)
- {
- projectile.velocity.X -= num42;
- if (projectile.velocity.X > 0f)
- {
- projectile.velocity.X -= num42 * 1.5f;
- }
- }
- if (projectile.velocity.Y < num51)
- {
- projectile.velocity.Y += num42;
- if (projectile.velocity.Y < 0f)
- {
- projectile.velocity.Y += num42 * 1.5f;
- }
- }
- if (projectile.velocity.Y > num51)
- {
- projectile.velocity.Y -= num42;
- if (projectile.velocity.Y > 0f)
- {
- projectile.velocity.Y -= num42 * 1.5f;
- }
- }
- if ((double)projectile.velocity.X > 0.5)
- {
- projectile.spriteDirection = -1;
- }
- else if ((double)projectile.velocity.X < -0.5)
- {
- projectile.spriteDirection = 1;
- }
- projectile.frameCounter++;
- if (projectile.frameCounter > 4)
- {
- projectile.frame++;
- projectile.frameCounter = 0;
- }
- if (projectile.frame < 6 || projectile.frame > 7)
- {
- projectile.frame = 6;
- }
- projectile.rotation = projectile.velocity.ToRotation() + 1.57f;
- }
- else
- {
- //Vector2 vector9 = Vector2.Zero;
- if (projectile.ai[1] != 0f)
- {
- flag = false;
- flag2 = false;
- }
- projectile.rotation = 0f;
- projectile.tileCollide = true;
- float num111 = 8f;
- float num110 = 0.4f;
- if (flag)
- {
- if (projectile.velocity.X > -3.5f)
- {
- projectile.velocity.X -= num110;
- }
- else
- {
- projectile.velocity.X -= num110 * 0.25f;
- }
- }
- else if (flag2)
- {
- if (projectile.velocity.X < 3.5f)
- {
- projectile.velocity.X += num110;
- }
- else
- {
- projectile.velocity.X += num110 * 0.25f;
- }
- }
- else
- {
- projectile.velocity.X *= 0.9f;
- if (projectile.velocity.X >= 0f - num110 && projectile.velocity.X <= num110)
- {
- projectile.velocity.X = 0f;
- }
- }
- if (flag | flag2)
- {
- int num112 = (int)(projectile.position.X + (float)(projectile.width / 2)) / 16;
- int j = (int)(projectile.position.Y + (float)(projectile.height / 2)) / 16;
- if (flag)
- {
- int num30 = num112;
- num112 = num30 - 1;
- }
- if (flag2)
- {
- int num30 = num112;
- num112 = num30 + 1;
- }
- num112 += (int)projectile.velocity.X;
- if (WorldGen.SolidTile(num112, j))
- {
- flag4 = true;
- }
- }
- if (player.position.Y + player.height - 8f > projectile.position.Y + projectile.height)
- {
- flag3 = true;
- }
- if (projectile.frameCounter < 10)
- {
- flag4 = false;
- }
- //projectile.stepSpeed = 1f;
- //projectile.gfxOffY = 0f;
- //Collision.StepUp(ref projectile.position, ref projectile.velocity, projectile.width, projectile.height, ref stepSpeed, ref gfxOffY);
- Collision.StepUp(ref projectile.position, ref projectile.velocity, projectile.width, projectile.height, ref projectile.stepSpeed, ref projectile.gfxOffY);
- if (projectile.velocity.Y == 0f)
- {
- if (!flag3 && (projectile.velocity.X < 0f || projectile.velocity.X > 0f))
- {
- int num113 = (int)(projectile.position.X + (projectile.width / 2)) / 16;
- int j2 = (int)(projectile.position.Y + (projectile.height / 2)) / 16 + 1;
- if (flag)
- {
- int num30 = num113;
- num113 = num30 - 1;
- }
- if (flag2)
- {
- int num30 = num113;
- num113 = num30 + 1;
- }
- WorldGen.SolidTile(num113, j2);
- }
- if (flag4)
- {
- int num114 = (int)(projectile.position.X + projectile.width / 2) / 16;
- int num115 = (int)(projectile.position.Y + projectile.height) / 16 + 1;
- if (WorldGen.SolidTile(num114, num115) || Main.tile[num114, num115].IsHalfBlock || Main.tile[num114, num115].Slope > 0)
- {
- try
- {
- num114 = (int)(projectile.position.X + projectile.width / 2) / 16;
- num115 = (int)(projectile.position.Y + projectile.height / 2) / 16;
- if (flag)
- {
- int num30 = num114;
- num114 = num30 - 1;
- }
- if (flag2)
- {
- int num30 = num114;
- num114 = num30 + 1;
- }
- num114 += (int)projectile.velocity.X;
- if (!WorldGen.SolidTile(num114, num115 - 1) && !WorldGen.SolidTile(num114, num115 - 2))
- {
- projectile.velocity.Y = -5.1f;
- }
- else if (!WorldGen.SolidTile(num114, num115 - 2))
- {
- projectile.velocity.Y = -7.1f;
- }
- else if (WorldGen.SolidTile(num114, num115 - 5))
- {
- projectile.velocity.Y = -11.1f;
- }
- else if (WorldGen.SolidTile(num114, num115 - 4))
- {
- projectile.velocity.Y = -10.1f;
- }
- else
- {
- projectile.velocity.Y = -9.1f;
- }
- }
- catch
- {
- projectile.velocity.Y = -9.1f;
- }
- }
- }
- }
- if (projectile.velocity.X > num111)
- {
- projectile.velocity.X = num111;
- }
- if (projectile.velocity.X < 0f - num111)
- {
- projectile.velocity.X = 0f - num111;
- }
- if (projectile.velocity.X < 0f)
- {
- projectile.direction = -1;
- }
- if (projectile.velocity.X > 0f)
- {
- projectile.direction = 1;
- }
- if (projectile.velocity.X > num110 && flag2)
- {
- projectile.direction = 1;
- }
- if (projectile.velocity.X < 0f - num110 && flag)
- {
- projectile.direction = -1;
- }
-
-
- //fix cause im dumb and didnt copy ai code correctly
- if (!flag && !flag2 && projectile.ai[0] == 0f)
- {
- projectile.direction = (player.Center - projectile.Center).X > 0 ? 1 : -1;
- }
-
-
- if (projectile.direction == -1)
- {
- projectile.spriteDirection = 1;
- }
- if (projectile.direction == 1)
- {
- projectile.spriteDirection = -1;
- }
-
- if (projectile.velocity.Y == 0f)
- {
- if (projectile.frame > 5)
- {
- projectile.frameCounter = 0;
- }
- if (projectile.velocity.X == 0f)
- {
- int num116 = 3;
- projectile.frameCounter++;
- if (projectile.frameCounter < num116)
- {
- projectile.frame = 0;
- }
- else if (projectile.frameCounter < num116 * 2)
- {
- projectile.frame = 1;
- }
- else if (projectile.frameCounter < num116 * 3)
- {
- projectile.frame = 2;
- }
- else if (projectile.frameCounter < num116 * 4)
- {
- projectile.frame = 3;
- }
- else
- {
- projectile.frameCounter = num116 * 4;
- }
- }
- else
- {
- projectile.velocity.X *= 0.8f;
- projectile.frameCounter++;
- int num117 = 3;
- if (projectile.frameCounter < num117)
- {
- projectile.frame = 0;
- }
- else if (projectile.frameCounter < num117 * 2)
- {
- projectile.frame = 1;
- }
- else if (projectile.frameCounter < num117 * 3)
- {
- projectile.frame = 2;
- }
- else if (projectile.frameCounter < num117 * 4)
- {
- projectile.frame = 3;
- }
- else if (flag | flag2)
- {
- projectile.velocity.X *= 2f;
- projectile.frame = 4;
- projectile.velocity.Y = -6.1f;
- projectile.frameCounter = 0;
- int num30;
- for (int num118 = 0; num118 < 4; num118 = num30 + 1)
- {
- /*int num119 = 0; Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y + (float)projectile.height - 2f), projectile.width, 4, 5)*/
- ;
- //Dust dust = Main.dust[num119];
- //dust.velocity += projectile.velocity;
- //dust = Main.dust[num119];
- //dust.velocity *= 0.4f;
- num30 = num118;
- }
- }
- else
- {
- projectile.frameCounter = num117 * 4;
- }
- }
- }
- else if (projectile.velocity.Y < 0f)
- {
- projectile.frameCounter = 0;
- projectile.frame = 5;
- }
- else
- {
- projectile.frame = 4;
- projectile.frameCounter = 3;
- }
- projectile.velocity.Y += 0.4f;
- if (projectile.velocity.Y > 10f)
- {
- projectile.velocity.Y = 10f;
- }
- }
- }
- }
- #endregion
-
- #region Zephyrfish
- public static void ZephyrfishDraw(Projectile projectile, int frameCounter = 5)
- {
- projectile.frameCounter++;
- if (projectile.frameCounter > frameCounter)
- {
- projectile.frame++;
- projectile.frameCounter = 0;
- }
- if (projectile.frame >= Main.projFrames[projectile.type]) //3
- {
- projectile.frame = 0;
- }
- }
-
- ///
- /// Stays around a certain offset position around the parent. Does not use ai/localai
- ///
- public static void ZephyrfishAI(Projectile projectile, Entity parent = null, float velocityFactor = 1f, float sway = 1f, bool random = true, byte swapSides = 0, float offsetX = 0f, float offsetY = 0f)
- {
- //velocityFactor:
- //kinda wonky, leave at 1f
-
- //sway:
- //tells by how much increase/decrease the left/right sway of the idle pet
-
- //swapSides:
- // 0: always behind
- //-1: always left
- // 1: always right
-
- //offsetX/Y
- //offsetting the desired center the pet hovers around
-
- if (parent == null) parent = projectile.GetOwner();
-
- Vector2 parentCenter = parent.Center;
- if (parent is Player)
- {
- parentCenter = ((Player)parent).MountedCenter;
- }
-
- float veloDelta = 0.3f;
- projectile.tileCollide = false; //false
- int someDistance = 100;
- Vector2 between = parentCenter - projectile.Center;
-
- Vector2 desiredCenter = random ? new Vector2(Main.rand.Next(-10, 21), Main.rand.Next(-10, 21)) : Vector2.Zero;
-
- Vector2 offset = new Vector2(60f + offsetX, -60f + offsetY);
-
- if (swapSides == 1)
- {
- offset.X = -offset.X;
- }
- else if (swapSides == 0)
- {
- offset.X *= -parent.direction;
- }
-
- //desiredCenter += new Vector2(60f * -player.direction, -60f);
- between += desiredCenter + offset;
-
- TeleportIfTooFar(projectile, parentCenter + desiredCenter + offset);
-
- float distance = between.Length();
- //float magnitude = 6f;
- if (distance < someDistance && parent.velocity.Y == 0f && projectile.position.Y + projectile.height <= parent.position.Y + parent.height && !Collision.SolidCollision(projectile.position, projectile.width, projectile.height))
- {
- //projectile.ai[0] = 0;
- if (projectile.velocity.Y < -6f)
- {
- projectile.velocity.Y = -6f;
- }
- }
- float swayDistance = 50 * sway;
- if (distance < swayDistance) //50
- {
- if (Math.Abs(projectile.velocity.X) > 2f || Math.Abs(projectile.velocity.Y) > 2f)
- {
- projectile.velocity *= 0.99f;
- }
- veloDelta = 0.01f;
- }
- else
- {
- if (distance < swayDistance * 2) //100
- {
- veloDelta = 0.1f;
- }
- //between: 0.3f
- if (distance > swayDistance * 6) //300
- {
- veloDelta = 0.4f;
- }
- between.Normalize();
- between *= 6f;
- between *= velocityFactor;
- }
- veloDelta *= velocityFactor;
- if (projectile.velocity.X < between.X)
- {
- projectile.velocity.X += veloDelta;
- if (veloDelta > 0.05f && projectile.velocity.X < 0f)
- {
- projectile.velocity.X += +veloDelta;
- }
- }
- if (projectile.velocity.X > between.X)
- {
- projectile.velocity.X += -veloDelta;
- if (veloDelta > 0.05f && projectile.velocity.X > 0f)
- {
- projectile.velocity.X += -veloDelta;
- }
- }
- if (projectile.velocity.Y < between.Y)
- {
- projectile.velocity.Y += veloDelta;
- if (veloDelta > 0.05f && projectile.velocity.Y < 0f)
- {
- projectile.velocity.Y += veloDelta * 2f;
- }
- }
- if (projectile.velocity.Y > between.Y)
- {
- projectile.velocity.Y += -veloDelta;
- if (veloDelta > 0.05f && projectile.velocity.Y > 0f)
- {
- projectile.velocity.Y += -veloDelta * 2f;
- }
- }
- projectile.manualDirectionChange = true;
- if (projectile.velocity.X > 0.25f && projectile.direction == 1)
- {
- projectile.direction = -1;
- }
- else if (projectile.velocity.X < -0.25f && projectile.direction != 1)
- {
- projectile.direction = 1;
- }
- projectile.spriteDirection = projectile.direction;
-
- //fix, direction gets set automatically by "manualDirectionChange = false" projectiled on velocity.X
- //if (projectile.velocity.X > 0.25f)
- //{
- // projectile.ai[0] = -1;
- //}
- //else if (projectile.velocity.X < -0.25f)
- //{
- // projectile.ai[0] = 1;
- //}
- //projectile.direction = (int)projectile.ai[0];
- //projectile.spriteDirection = projectile.direction;
- projectile.rotation = projectile.velocity.X * 0.05f;
- }
- #endregion
-
- #region BabyEater
- public static void BabyEaterDraw(Projectile projectile, int frameCounter = 6)
- {
- projectile.frameCounter++;
- if (projectile.frameCounter > frameCounter)
- {
- projectile.frame++;
- projectile.frameCounter = 0;
- }
- if (projectile.frame >= Main.projFrames[projectile.type]) //2
- {
- projectile.frame = 0;
- }
- }
-
- public static void BabyEaterAI(Projectile projectile, Entity parent = null, Vector2 originOffset = default(Vector2), float velocityFactor = 1f, float sway = 1f)
- {
- //velocityFactor:
- //kinda wonky, leave at 1f
-
- //sway:
- //tells by how much increase/decrease the left/right sway radius of the idle pet
-
- if (parent == null) parent = projectile.GetOwner();
-
- if (!parent.active)
- {
- projectile.active = false;
- return;
- }
-
- Vector2 parentCenter = parent.Center;
- if (parent is Player)
- {
- parentCenter = ((Player)parent).MountedCenter;
- }
- parentCenter += originOffset;
-
- float veloDelta = 0.1f;
- projectile.tileCollide = false;
- int someDistance = 300;
- Vector2 between = parentCenter - projectile.Center;
- float distance = between.Length();
- float magnitude = 7f;
-
- TeleportIfTooFar(projectile, parentCenter, 1380);
-
- if (distance < someDistance && parent.velocity.Y == 0f && projectile.position.Y + projectile.height <= parent.position.Y + parent.height + originOffset.Y && !Collision.SolidCollision(projectile.position, projectile.width, projectile.height))
- {
- if (projectile.velocity.Y < -6f)
- {
- projectile.velocity.Y = -6f;
- }
- }
- float swayDistance = 150f * sway;
- if (distance < swayDistance)
- {
- if (Math.Abs(projectile.velocity.X) > 2f || Math.Abs(projectile.velocity.Y) > 2f)
- {
- projectile.velocity *= 0.99f;
- }
- veloDelta = 0.01f;
- if (between.X < -2f)
- {
- between.X = -2f;
- }
- if (between.X > 2f)
- {
- between.X = 2f;
- }
- if (between.Y < -2f)
- {
- between.Y = -2f;
- }
- if (between.Y > 2f)
- {
- between.Y = 2f;
- }
- }
- else
- {
- if (distance > swayDistance * 2f)
- {
- veloDelta = 0.2f;
- }
- between.Normalize();
- between *= magnitude;
- }
-
- veloDelta *= velocityFactor;
-
- if (Math.Abs(between.X) > Math.Abs(between.Y))
- {
- if (projectile.velocity.X < between.X)
- {
- projectile.velocity.X += veloDelta;
- if (veloDelta > 0.05f && projectile.velocity.X < 0f)
- {
- projectile.velocity.X += veloDelta;
- }
- }
- if (projectile.velocity.X > between.X)
- {
- projectile.velocity.X += -veloDelta;
- if (veloDelta > 0.05f && projectile.velocity.X > 0f)
- {
- projectile.velocity.X += -veloDelta;
- }
- }
- }
- if (Math.Abs(between.X) <= Math.Abs(between.Y) || veloDelta == 0.05f)
- {
- if (projectile.velocity.Y < between.Y)
- {
- projectile.velocity.Y += veloDelta;
- if (veloDelta > 0.05f && projectile.velocity.Y < 0f)
- {
- projectile.velocity.Y += veloDelta;
- }
- }
- if (projectile.velocity.Y > between.Y)
- {
- projectile.velocity.Y += -veloDelta;
- if (veloDelta > 0.05f && projectile.velocity.Y > 0f)
- {
- projectile.velocity.Y += -veloDelta;
- }
- }
- }
- projectile.rotation = projectile.velocity.ToRotation() - 1.57f;
- }
- #endregion
-
- #region StardustDragon
-
-
- //ProjectileID.Sets.
- //NeedsUUID = true;
- //DontAttachHideToAlpha =true;
-
- //if minion = true:
- //ProjectileID.Sets.MinionSacrificable[projectile.type] = false, cause the replacing code for worm minions is complicated
- //damage set in NewProjectile/item
- //scales in size with the amount of segments
- public static void StardustDragonSetDefaults(Projectile projectile, int size = 24, bool minion = true, WormType wormType = WormType.None)
- {
- if (minion)
- {
- //if (projectile.type == 625 || projectile.type == 628)
- //{
- // projectile.netImportant = true;
- //}
- if (wormType == WormType.Body1 || wormType == WormType.Body2)
- {
- projectile.minionSlots = 0.5f;
- }
- projectile.DamageType = DamageClass.Summon;
- projectile.minion = true;
- //projectile.hide = true;
- projectile.netImportant = true;
- }
- projectile.Size = new Vector2(size);
- projectile.penetrate = -1;
- projectile.timeLeft *= 5;
- projectile.friendly = true;
- projectile.ignoreWater = true;
- projectile.tileCollide = false;
- projectile.alpha = 255;
- }
- //wormTypes = new int[] {head, body1, body2, tail} //projectiletype
-
- //if minion = true:
- //float scaleFactor = MathHelper.Clamp(projectile.localAI[0], 0f, 50f);
- //projectile.scale = 1f + scaleFactor * 0.01f;
- public static void StardustDragonAI(Projectile projectile, int[] wormTypes, int segmentDistance = 16)
- {
- Player player = projectile.GetOwner();
-
- if (projectile.minion && (int)Main.time % 120 == 0)
- {
- projectile.netUpdate = true;
- }
- if (!player.active)
- {
- projectile.active = false;
- return;
- }
- bool head = projectile.type == wormTypes[0];
- int defScaleFactor = 30;
- //if (Main.rand.Next(30) == 0)
- //{
- // int num1049 = Dust.NewDust(projectile.position, projectile.width, projectile.height, 135, 0f, 0f, 0, default(Color), 2f);
- // Main.dust[num1049].noGravity = true;
- // Main.dust[num1049].fadeIn = 2f;
- // Point point4 = Main.dust[num1049].position.ToTileCoordinates();
- // if (WorldGen.InWorld(point4.X, point4.Y, 5) && WorldGen.SolidTile(point4.X, point4.Y))
- // {
- // Main.dust[num1049].noLight = true;
- // }
- //}
-
- if (projectile.alpha > 0)
- {
- //for (int i = 0; i < 2; i++)
- //{
- // int dust = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y), projectile.width, projectile.height, 135, 0f, 0f, 100, default(Color), 2f);
- // Main.dust[dust].noGravity = true;
- // Main.dust[dust].noLight = true;
- //}
- projectile.alpha -= 42;
- if (projectile.alpha < 0)
- {
- projectile.alpha = 0;
- return;
- }
- }
-
- if (head)
- {
- Vector2 desiredCenter = player.Center;
- int targetIndex = -1;
- TeleportIfTooFar(projectile, desiredCenter);
- if (projectile.minion)
- {
- float maxProjDistance = 490000f;
- float maxPlayerDistance = 1000000f;
- NPC ownerMinionAttackTargetNPC5 = projectile.OwnerMinionAttackTargetNPC;
- if (ownerMinionAttackTargetNPC5 != null && ownerMinionAttackTargetNPC5.CanBeChasedBy())
- {
- float distance1 = projectile.DistanceSQ(ownerMinionAttackTargetNPC5.Center);
- if (distance1 < maxProjDistance * 2f)
- {
- targetIndex = ownerMinionAttackTargetNPC5.whoAmI;
- }
- }
- if (targetIndex < 0)
- {
- for (int i = 0; i < Main.maxNPCs; i++)
- {
- NPC npc = Main.npc[i];
- if (npc.CanBeChasedBy() && player.DistanceSQ(npc.Center) < maxPlayerDistance)
- {
- float distance2 = projectile.DistanceSQ(npc.Center);
- if (distance2 < maxProjDistance)
- {
- targetIndex = i;
- }
- }
- }
- }
- }
- if (targetIndex != -1)
- {
- NPC npc = Main.npc[targetIndex];
- Vector2 betweenNPC = npc.Center - projectile.Center;
- float veloFactor = 0.4f;
- if (betweenNPC.Length() < 600f)
- {
- veloFactor = 0.6f;
- }
- if (betweenNPC.Length() < 300f)
- {
- veloFactor = 0.8f;
- }
- if (betweenNPC.Length() > npc.Size.Length() * 0.75f)
- {
- projectile.velocity += Vector2.Normalize(betweenNPC) * veloFactor * 1.5f;
- if (Vector2.Dot(projectile.velocity, betweenNPC) < 0.25f)
- {
- projectile.velocity *= 0.8f;
- }
- }
- float targetMagnitude = 30f;
- if (projectile.velocity.Length() > targetMagnitude)
- {
- projectile.velocity = Vector2.Normalize(projectile.velocity) * targetMagnitude;
- }
- }
- else
- {
- float idleVelo = 0.2f;
- Vector2 betweenPlayer = desiredCenter - projectile.Center;
- if (betweenPlayer.Length() < 200f)
- {
- idleVelo = 0.12f;
- }
- if (betweenPlayer.Length() < 140f)
- {
- idleVelo = 0.06f;
- }
- if (betweenPlayer.Length() > 100f)
- {
- if (Math.Abs(desiredCenter.X - projectile.Center.X) > 20f)
- {
- projectile.velocity.X += idleVelo * Math.Sign(desiredCenter.X - projectile.Center.X);
- }
- if (Math.Abs(desiredCenter.Y - projectile.Center.Y) > 10f)
- {
- projectile.velocity.Y += idleVelo * Math.Sign(desiredCenter.Y - projectile.Center.Y);
- }
- }
- else if (projectile.velocity.Length() > 2f)
- {
- projectile.velocity *= 0.96f;
- }
- if (Math.Abs(projectile.velocity.Y) < 1f)
- {
- projectile.velocity.Y += -0.1f;
- }
- float idleMagnitude = 15f;
- if (projectile.velocity.Length() > idleMagnitude)
- {
- projectile.velocity = Vector2.Normalize(projectile.velocity) * idleMagnitude;
- }
- }
- projectile.rotation = projectile.velocity.ToRotation() + 1.57079637f;
- int direction = projectile.direction;
- projectile.direction = projectile.spriteDirection = (projectile.velocity.X > 0f) ? 1 : -1;
- if (projectile.minion && direction != projectile.direction)
- {
- projectile.netUpdate = true;
- }
- float scaleFactor = MathHelper.Clamp(projectile.localAI[0], 0f, 50f);
- if (!projectile.minion) scaleFactor = 0;
- projectile.position = projectile.Center;
- projectile.scale = 1f + scaleFactor * 0.01f;
- projectile.width = projectile.height = (int)(defScaleFactor * projectile.scale);
- projectile.Center = projectile.position;
- }
- else
- {
- Vector2 pCenter = Vector2.Zero;
- float parentRotation = 0f;
- float positionOffset = 0f;
- float scaleOffset = 1f;
-
- //some custom syncing it seems like, when summoning/replacing it
- if (projectile.ai[1] == 1f)
- {
- projectile.ai[1] = 0f;
- projectile.netUpdate = true;
- }
-
- Projectile parent = null;
- for (short i = 0; i < Main.maxProjectiles; i++)
- {
- Projectile proj = Main.projectile[i];
- if (proj.active && proj.owner == projectile.owner && proj.identity == (int)projectile.ai[0]/* && proj.type == projectile.type*/)
- {
- parent = proj;
- break;
- }
- }
- if (parent != null)
- {
- if (parent.active && (parent.type == wormTypes[0] || parent.type == wormTypes[1] || parent.type == wormTypes[2]))
- {
- pCenter = parent.Center;
- //Vector2 velocity2 = parent.velocity;
- parentRotation = parent.rotation;
- scaleOffset = MathHelper.Clamp(parent.scale, 0f, 50f);
- if (!projectile.minion) scaleOffset = 1;
- positionOffset = segmentDistance;
- parent.localAI[0] = projectile.localAI[0] + 1f;
- if (parent.type != wormTypes[0])
- {
- parent.localAI[1] = projectile.whoAmI;
- }
- if (projectile.owner == Main.myPlayer && parent.type == wormTypes[0] && projectile.type == wormTypes[3])
- {
- parent.Kill();
- projectile.Kill();
- return;
- }
- }
-
- projectile.velocity = Vector2.Zero;
- Vector2 newVelocity = pCenter - projectile.Center;
- if (parentRotation != projectile.rotation)
- {
- float rotatedBy = MathHelper.WrapAngle(parentRotation - projectile.rotation);
- newVelocity = newVelocity.RotatedBy(rotatedBy * 0.1f);
- }
- projectile.rotation = newVelocity.ToRotation() + 1.57079637f;
- projectile.position = projectile.Center;
- projectile.scale = scaleOffset;
- projectile.width = projectile.height = (int)(defScaleFactor * projectile.scale);
- projectile.Center = projectile.position;
- if (newVelocity != Vector2.Zero)
- {
- projectile.Center = pCenter - Vector2.Normalize(newVelocity) * positionOffset * scaleOffset;
- }
- projectile.spriteDirection = (newVelocity.X > 0f) ? 1 : -1;
- }
- }
- }
-
- #endregion
-
- public static void ModifiedGoldfishAI(NPC npc, float scareRange, bool faceAway = true)
- {
- if (npc.direction == 0)
- {
- npc.TargetClosest();
- }
- if (npc.wet)
- {
- bool hasPlayer = false;
- npc.TargetClosest(faceTarget: false);
- Vector2 centerpos = npc.Center;
- Player player = Main.player[npc.target];
- Vector2 playerpos = player.Center;
- float distancex = playerpos.X - centerpos.X;
- float distancey = playerpos.Y - centerpos.Y;
- float distSQ = distancex * distancex + distancey * distancey;
- if (player.wet && distSQ < scareRange * scareRange)
- {
- if (!player.dead)
- {
- hasPlayer = true;
- }
- }
- if (!hasPlayer)
- {
- if (npc.collideX)
- {
- npc.velocity.X *= -1;
- npc.direction *= -1;
- npc.netUpdate = true;
- }
- if (npc.collideY)
- {
- npc.netUpdate = true;
- if (npc.velocity.Y > 0f)
- {
- npc.velocity.Y = Math.Abs(npc.velocity.Y) * -1f;
- npc.directionY = -1;
- npc.ai[0] = -1f;
- }
- else if (npc.velocity.Y < 0f)
- {
- npc.velocity.Y = Math.Abs(npc.velocity.Y);
- npc.directionY = 1;
- npc.ai[0] = 1f;
- }
- }
- }
- if (hasPlayer) //if target is in water
- {
- npc.TargetClosest(faceTarget: false);
- npc.direction = (distancex >= 0f).ToDirectionInt();
- npc.directionY = (distancey >= 0f).ToDirectionInt();
-
- if (faceAway)
- {
- npc.direction *= -1;
- npc.directionY *= -1;
- }
-
- npc.velocity.X += npc.direction * 0.1f;
- npc.velocity.Y += npc.directionY * 0.1f;
-
- if (npc.velocity.X > 3f)
- {
- npc.velocity.X = 3f;
- }
- if (npc.velocity.X < -3f)
- {
- npc.velocity.X = -3f;
- }
- if (npc.velocity.Y > 2f)
- {
- npc.velocity.Y = 2f;
- }
- if (npc.velocity.Y < -2f)
- {
- npc.velocity.Y = -2f;
- }
- }
- else
- {
- npc.velocity.X += npc.direction * 0.1f;
- if (npc.velocity.X < -1f || npc.velocity.X > 1f)
- {
- npc.velocity.X *= 0.95f;
- }
- if (npc.ai[0] == -1f)
- {
- npc.velocity.Y -= 0.01f;
- if (npc.velocity.Y < -0.3f)
- {
- npc.ai[0] = 1f;
- }
- }
- else
- {
- npc.velocity.Y += 0.01f;
- if (npc.velocity.Y > 0.3f)
- {
- npc.ai[0] = -1f;
- }
- }
- int tileX = (int)npc.Center.X / 16;
- int tileY = (int)npc.Center.Y / 16;
- if (Framing.GetTileSafely(tileX, tileY - 1).LiquidAmount > 128)
- {
- if (Framing.GetTileSafely(tileX, tileY + 1).HasTile)
- {
- npc.ai[0] = -1f;
- }
- else if (Framing.GetTileSafely(tileX, tileY + 2).HasTile)
- {
- npc.ai[0] = -1f;
- }
- }
- if (npc.velocity.Y > 0.4f || npc.velocity.Y < -0.4f)
- {
- npc.velocity.Y *= 0.95f;
- }
- }
- }
- else //not wet, frantically jump around
- {
- if (npc.velocity.Y == 0f)
- {
- if (Main.netMode != NetmodeID.MultiplayerClient)
- {
- npc.velocity.Y = Main.rand.Next(-50, -20) * 0.1f;
- npc.velocity.X = Main.rand.Next(-20, 20) * 0.1f;
- npc.netUpdate = true;
- }
- }
- npc.velocity.Y += 0.3f;
- if (npc.velocity.Y > 10f)
- {
- npc.velocity.Y = 10f;
- }
- npc.ai[0] = 1f;
- }
- npc.rotation = npc.velocity.Y * npc.direction * 0.1f;
- if (npc.rotation < -0.2f)
- {
- npc.rotation = -0.2f;
- }
- if (npc.rotation > 0.2f)
- {
- npc.rotation = 0.2f;
- }
- }
-
- //TODO turn into usable method later
- public static void PirateAI(Projectile Projectile)
- {
- // //Pirate AI related:
- //public int State
- //{
- // get => (int)Projectile.ai[0];
- // set => Projectile.ai[0] = value;
- //}
-
- //public int Timer
- //{
- // get => (int)Projectile.ai[1];
- // set => Projectile.ai[1] = value;
- //}
-
- //public bool Idle => State == 0;
-
- //public bool Flying
- //{
- // get => State == 1;
- // set => State = value ? 1 : 0;
- //}
-
- //public bool Attacking
- //{
- // get => State == 2;
- // set => State = value ? 2 : 0;
- //}
- int Timer = 0;
- bool Idle = true;
- bool Flying = false;
- bool Attacking = false;
- ////End Pirate AI
-
- Player player = Main.player[Projectile.owner];
-
- int startAttackRange = 800;
- float awayFromPlayerDistMax = 500f;
- float awayFromPlayerDistYMax = 300f;
-
- Vector2 destination = player.Center;
- destination.X -= (15 + player.width / 2) * player.direction;
- destination.X -= Projectile.minionPos * 25 * player.direction;
-
- Projectile.shouldFallThrough = player.Bottom.Y - 12f > Projectile.Bottom.Y;
- Projectile.friendly = false;
- int timerReset = 0;
- int attackFrameCount = 3;
- int nextTimerValue = 5 * attackFrameCount;
- int attackTarget = -1;
-
- bool defaultstate = Idle;
-
- static bool CustomEliminationCheck_Pirates(Entity otherEntity, int currentTarget) => true;
-
- if (defaultstate)
- Projectile.Minion_FindTargetInRange(startAttackRange, ref attackTarget, skipIfCannotHitWithOwnBody: true, CustomEliminationCheck_Pirates);
-
- if (Flying)
- {
- Projectile.tileCollide = false;
- float velChange = 0.2f;
- float toPlayerSpeed = 10f;
- int maxLen = 200;
- if (toPlayerSpeed < Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y))
- toPlayerSpeed = Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y);
-
- Vector2 toPlayer = player.Center - Projectile.Center;
- float len = toPlayer.Length();
-
- AssAI.TeleportIfTooFar(Projectile, player.Center);
-
- if (len < maxLen && player.velocity.Y == 0f && Projectile.Bottom.Y <= player.Bottom.Y && !Collision.SolidCollision(Projectile.position, Projectile.width, Projectile.height))
- {
- //Reset back from flying
- Flying = false;
- Projectile.netUpdate = true;
- if (Projectile.velocity.Y < -6f)
- Projectile.velocity.Y = -6f;
- }
-
- if (!(len < 60f))
- {
- toPlayer.Normalize();
- toPlayer *= toPlayerSpeed;
- if (Projectile.velocity.X < toPlayer.X)
- {
- Projectile.velocity.X += velChange;
- if (Projectile.velocity.X < 0f)
- Projectile.velocity.X += velChange * 1.5f;
- }
-
- if (Projectile.velocity.X > toPlayer.X)
- {
- Projectile.velocity.X -= velChange;
- if (Projectile.velocity.X > 0f)
- Projectile.velocity.X -= velChange * 1.5f;
- }
-
- if (Projectile.velocity.Y < toPlayer.Y)
- {
- Projectile.velocity.Y += velChange;
- if (Projectile.velocity.Y < 0f)
- Projectile.velocity.Y += velChange * 1.5f;
- }
-
- if (Projectile.velocity.Y > toPlayer.Y)
- {
- Projectile.velocity.Y -= velChange;
- if (Projectile.velocity.Y > 0f)
- Projectile.velocity.Y -= velChange * 1.5f;
- }
- }
-
- if (Projectile.velocity.X != 0f)
- Projectile.spriteDirection = -Math.Sign(Projectile.velocity.X);
- }
-
- if (Attacking && Timer < 0)
- {
- Projectile.friendly = false;
- Timer += 1;
- if (nextTimerValue >= 0)
- {
- Timer = 0;
- Attacking = false;
- Projectile.netUpdate = true;
- return;
- }
- }
- else if (Attacking)
- {
- //Attacking animation
- Projectile.spriteDirection = -Projectile.direction;
- Projectile.rotation = 0f;
-
- Projectile.friendly = true;
- int startAttackFrame = 12;
- bool hasJumpingAttackFrames = true;
- int attackFrameNumber = (int)((float)nextTimerValue - Timer) / (nextTimerValue / attackFrameCount);
- Projectile.frame = startAttackFrame + attackFrameNumber;
- if (hasJumpingAttackFrames && Projectile.velocity.Y != 0f)
- Projectile.frame += attackFrameCount;
-
- Projectile.velocity.Y += 0.4f;
- if (Projectile.velocity.Y > 10f)
- Projectile.velocity.Y = 10f;
-
- Timer -= 1;
- if (Timer <= 0f)
- {
- if (timerReset <= 0)
- {
- Timer = 0;
- Attacking = false;
- Projectile.netUpdate = true;
- return;
- }
-
- Timer = -timerReset;
- }
- }
-
- if (attackTarget >= 0)
- {
- float maxDistance = startAttackRange;
- float toTargetMaxDist = 20f;
-
- NPC npc = Main.npc[attackTarget];
- Vector2 targetCenter = npc.Center;
- destination = targetCenter;
- if (Projectile.IsInRangeOfMeOrMyOwner(npc, maxDistance, out float _, out float _, out bool _))
- {
- Projectile.shouldFallThrough = npc.Center.Y > Projectile.Bottom.Y;
-
- bool flag11 = Projectile.velocity.Y == 0f;
- if (Projectile.wet && Projectile.velocity.Y > 0f && !Projectile.shouldFallThrough)
- flag11 = true;
-
- if (targetCenter.Y < Projectile.Center.Y - 30f && flag11)
- {
- float num25 = (targetCenter.Y - Projectile.Center.Y) * -1f;
- float num26 = 0.4f;
- float velY = (float)Math.Sqrt(num25 * 2f * num26);
- if (velY > 26f)
- velY = 26f;
-
- Projectile.velocity.Y = -velY;
- }
-
- if (Vector2.Distance(Projectile.Center, destination) < toTargetMaxDist)
- {
- float len = Projectile.velocity.Length();
- if (len > 10f)
- Projectile.velocity /= len / 10f;
-
- Attacking = true;
- Timer = nextTimerValue;
- Projectile.netUpdate = true;
- Projectile.direction = (targetCenter.X - Projectile.Center.X > 0f).ToDirectionInt();
- }
- }
- }
-
- if (Idle && attackTarget < 0)
- {
- if (player.rocketDelay2 > 0)
- {
- Flying = true;
- Projectile.netUpdate = true;
- }
-
- Vector2 toPlayer = player.Center - Projectile.Center;
- if (toPlayer.Length() > 2000f)
- {
- Projectile.Center = player.Center;
- }
- else if (toPlayer.Length() > awayFromPlayerDistMax || Math.Abs(toPlayer.Y) > awayFromPlayerDistYMax)
- {
- Flying = true;
- Projectile.netUpdate = true;
- if (Projectile.velocity.Y > 0f && toPlayer.Y < 0f)
- Projectile.velocity.Y = 0f;
-
- if (Projectile.velocity.Y < 0f && toPlayer.Y > 0f)
- Projectile.velocity.Y = 0f;
- }
- }
-
- if (Idle)
- {
- if (attackTarget < 0)
- {
- if (Projectile.Distance(player.Center) > 60f && Projectile.Distance(destination) > 60f && Math.Sign(destination.X - player.Center.X) != Math.Sign(Projectile.Center.X - player.Center.X))
- destination = player.Center;
-
- Rectangle rect = Utils.CenteredRectangle(destination, Projectile.Size);
- for (int i = 0; i < 20; i++)
- {
- if (Collision.SolidCollision(rect.TopLeft(), rect.Width, rect.Height))
- break;
-
- rect.Y += 16;
- destination.Y += 16f;
- }
-
- Vector2 position = player.Center - Projectile.Size / 2f;
- Vector2 postCollision = Collision.TileCollision(position, destination - player.Center, Projectile.width, Projectile.height);
- destination = position + postCollision;
- if (Projectile.Distance(destination) < 32f)
- {
- float distPlayerToDestination = player.Distance(destination);
- if (player.Distance(Projectile.Center) < distPlayerToDestination)
- destination = Projectile.Center;
- }
-
- Vector2 fromDestToPlayer = player.Center - destination;
- if (fromDestToPlayer.Length() > awayFromPlayerDistMax || Math.Abs(fromDestToPlayer.Y) > awayFromPlayerDistYMax)
- {
- Rectangle rect2 = Utils.CenteredRectangle(player.Center, Projectile.Size);
- Vector2 fromPlayerToDest = destination - player.Center;
- Vector2 topLeft = rect2.TopLeft();
- for (float i = 0f; i < 1f; i += 0.05f)
- {
- Vector2 newTopLeft = rect2.TopLeft() + fromPlayerToDest * i;
- if (Collision.SolidCollision(rect2.TopLeft() + fromPlayerToDest * i, rect2.Width, rect2.Height))
- break;
-
- topLeft = newTopLeft;
- }
-
- destination = topLeft + Projectile.Size / 2f;
- }
- }
-
- Projectile.tileCollide = true;
- float velXChange = 0.5f; //0.5f
- float velXChangeMargin = 4f; //4f
- float velXChangeMax = 4f; //4f
- float velXChangeSmall = 0.1f;
-
- if (attackTarget != -1)
- {
- velXChange = 0.4f; //1f
- velXChangeMargin = 5f; //8f
- velXChangeMax = 5f; //8f
- }
-
- if (velXChangeMax < Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y))
- {
- velXChangeMax = Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y);
- velXChange = 0.7f;
- }
-
- int xOff = 0;
- bool canJumpOverTiles = false;
- float toDestinationX = destination.X - Projectile.Center.X;
- Vector2 toDestination = destination - Projectile.Center;
- if (Math.Abs(toDestinationX) > 5f)
- {
- if (toDestinationX < 0f)
- {
- xOff = -1;
- if (Projectile.velocity.X > -velXChangeMargin)
- Projectile.velocity.X -= velXChange;
- else
- Projectile.velocity.X -= velXChangeSmall;
- }
- else
- {
- xOff = 1;
- if (Projectile.velocity.X < velXChangeMargin)
- Projectile.velocity.X += velXChange;
- else
- Projectile.velocity.X += velXChangeSmall;
- }
- }
- else
- {
- Projectile.velocity.X *= 0.9f;
- if (Math.Abs(Projectile.velocity.X) < velXChange * 2f)
- Projectile.velocity.X = 0f;
- }
-
- bool tryJumping = Math.Abs(toDestination.X) >= 64f || (toDestination.Y <= -48f && Math.Abs(toDestination.X) >= 8f);
- if (xOff != 0 && tryJumping)
- {
- int x = (int)Projectile.Center.X / 16;
- int y = (int)Projectile.position.Y / 16;
- x += xOff;
- x += (int)Projectile.velocity.X;
- for (int j = y; j < y + Projectile.height / 16 + 1; j++)
- {
- if (WorldGen.SolidTile(x, j))
- canJumpOverTiles = true;
- }
- }
-
- Collision.StepUp(ref Projectile.position, ref Projectile.velocity, Projectile.width, Projectile.height, ref Projectile.stepSpeed, ref Projectile.gfxOffY);
- float nextVelocityY = Utils.GetLerpValue(0f, 100f, toDestination.Y, clamped: true) * Utils.GetLerpValue(-2f, -6f, Projectile.velocity.Y, clamped: true);
- if (Projectile.velocity.Y == 0f && canJumpOverTiles)
- {
- for (int k = 0; k < 3; k++)
- {
- int num42 = (int)(Projectile.Center.X) / 16;
- if (k == 0)
- num42 = (int)Projectile.position.X / 16;
-
- if (k == 2)
- num42 = (int)(Projectile.Right.X) / 16;
-
- int num43 = (int)(Projectile.Bottom.Y) / 16;
- if (!WorldGen.SolidTile(num42, num43) && !Main.tile[num42, num43].IsHalfBlock && Main.tile[num42, num43].Slope <= 0 && (!TileID.Sets.Platforms[Main.tile[num42, num43].TileType] || !Main.tile[num42, num43].HasTile || Main.tile[num42, num43].IsActuated))
- continue;
-
- try
- {
- num42 = (int)(Projectile.Center.X) / 16;
- num43 = (int)(Projectile.Center.Y) / 16;
- num42 += xOff;
- num42 += (int)Projectile.velocity.X;
- if (!WorldGen.SolidTile(num42, num43 - 1) && !WorldGen.SolidTile(num42, num43 - 2))
- Projectile.velocity.Y = -5.1f;
- else if (!WorldGen.SolidTile(num42, num43 - 2))
- Projectile.velocity.Y = -7.1f;
- else if (WorldGen.SolidTile(num42, num43 - 5))
- Projectile.velocity.Y = -11.1f;
- else if (WorldGen.SolidTile(num42, num43 - 4))
- Projectile.velocity.Y = -10.1f;
- else
- Projectile.velocity.Y = -9.1f;
- }
- catch
- {
- Projectile.velocity.Y = -9.1f;
- }
- }
-
- if (destination.Y - Projectile.Center.Y < -48f)
- {
- float height = destination.Y - Projectile.Center.Y;
- height *= -1f;
- if (height < 60f)
- Projectile.velocity.Y = -6f;
- else if (height < 80f)
- Projectile.velocity.Y = -7f;
- else if (height < 100f)
- Projectile.velocity.Y = -8f;
- else if (height < 120f)
- Projectile.velocity.Y = -9f;
- else if (height < 140f)
- Projectile.velocity.Y = -10f;
- else if (height < 160f)
- Projectile.velocity.Y = -11f;
- else if (height < 190f)
- Projectile.velocity.Y = -12f;
- else if (height < 210f)
- Projectile.velocity.Y = -13f;
- else if (height < 270f)
- Projectile.velocity.Y = -14f;
- else if (height < 310f)
- Projectile.velocity.Y = -15f;
- else
- Projectile.velocity.Y = -16f;
- }
-
- if (Projectile.wet && nextVelocityY == 0f)
- Projectile.velocity.Y *= 2f;
- }
-
- if (Projectile.velocity.X > velXChangeMax)
- Projectile.velocity.X = velXChangeMax;
-
- if (Projectile.velocity.X < -velXChangeMax)
- Projectile.velocity.X = -velXChangeMax;
-
- if (Projectile.velocity.X < 0f)
- Projectile.direction = -1;
-
- if (Projectile.velocity.X > 0f)
- Projectile.direction = 1;
-
- if (Projectile.velocity.X == 0f)
- Projectile.direction = (player.Center.X > Projectile.Center.X).ToDirectionInt();
-
- if (Projectile.velocity.X > velXChange && xOff == 1)
- Projectile.direction = 1;
-
- if (Projectile.velocity.X < -velXChange && xOff == -1)
- Projectile.direction = -1;
-
- Projectile.spriteDirection = -Projectile.direction;
-
- Projectile.velocity.Y += 0.4f + nextVelocityY * 1f;
- if (Projectile.velocity.Y > 10f)
- {
- Projectile.velocity.Y = 10f;
- }
- }
-
- #region default animations
- /*
+ ///
+ /// contains AI for stuff that only uses ai[], used with thing.aiStyle = -1
+ ///
+ public static class AssAI
+ {
+ ///
+ /// Makes the projectile teleport if it is too far away from the given location
+ ///
+ public static bool TeleportIfTooFar(Projectile projectile, Vector2 desiredCenter, int distance = 2000)
+ {
+ if (projectile.DistanceSQ(desiredCenter) > distance * distance)
+ {
+ projectile.Center = desiredCenter;
+ if (Main.myPlayer == projectile.owner) projectile.netUpdate = true;
+ return true;
+ }
+ return false;
+ }
+
+ ///
+ /// Finds target in range of relativeCenter. Returns index of target
+ ///
+ public static int FindTarget(Entity ent, Vector2 relativeCenter, float range, bool ignoreTiles = false)
+ {
+ int targetIndex = -1;
+ float distanceFromTarget = 10000000f;
+ Vector2 targetCenter = relativeCenter;
+ range *= range;
+ for (int k = 0; k < Main.maxNPCs; k++)
+ {
+ NPC npc = Main.npc[k];
+ if (npc.CanBeChasedBy())
+ {
+ //Collision.CanHitLine(projectile.position, projectile.width, projectile.height, npc.position, npc.width, npc.height)
+ float between = Vector2.DistanceSquared(npc.Center, relativeCenter);
+ if ((between < range && Vector2.DistanceSquared(relativeCenter, targetCenter) > between && between < distanceFromTarget) || targetIndex == -1)
+ {
+ if (ignoreTiles || Collision.CanHitLine(ent.position, ent.width, ent.height, npc.position, npc.width, npc.height))
+ {
+ distanceFromTarget = between;
+ targetCenter = npc.Center;
+ targetIndex = k;
+ }
+ }
+ }
+ }
+ return distanceFromTarget < range ? targetIndex : -1;
+ }
+
+ ///
+ /// Utility for minion AI that handles a custom stuck timer for when the X coordinate doesn't change for a given duration.
+ ///
+ /// The projectile
+ /// The X coordinate of the idle location (to not increment the timer when near that)
+ /// The timer
+ /// The maximum duration
+ /// Returns true if the timer overflows
+ public static bool HandleStuck(this Projectile projectile, float restingX, ref int stuckTimer, int stuckTimerMax)
+ {
+ if (projectile.position.X == projectile.oldPosition.X && Math.Abs(projectile.Center.X - restingX) >= 50)
+ {
+ stuckTimer++;
+
+ if (stuckTimer >= stuckTimerMax)
+ {
+ stuckTimer = 0;
+ return true;
+ }
+ }
+ else
+ {
+ if (stuckTimer >= 2)
+ {
+ stuckTimer -= 2;
+ }
+ }
+
+ return false;
+ }
+
+ #region Flickerwick
+ public static void FlickerwickPetDraw(Projectile projectile, int frameCounterMaxFar, int frameCounterMaxClose)
+ {
+ projectile.LoopAnimation((projectile.velocity.Length() > 6f) ? frameCounterMaxFar : frameCounterMaxClose);
+ }
+
+ ///
+ /// No use of ai[] or LocalAI[].
+ /// Default offset is x = 30, y = -20
+ ///
+ public static void FlickerwickPetAI(Projectile projectile, bool lightPet = true, bool lightDust = true, bool staticDirection = false, bool reverseSide = false, bool vanityPet = false, float veloXToRotationFactor = 1f, float veloSpeed = 1f, float lightFactor = 1f, Vector3 lightColor = default(Vector3), float offsetX = 0f, float offsetY = 0f)
+ {
+ //veloSpeed not bigger than veloDistanceChange * 0.5f
+ Player player = projectile.GetOwner();
+ float veloDistanceChange = 2f; //6f
+
+ int dir = player.direction;
+ if (staticDirection)
+ {
+ if (reverseSide)
+ {
+ dir = -1;
+ }
+ else
+ {
+ dir = 1;
+ }
+ }
+ else
+ {
+ if (reverseSide)
+ {
+ dir = -dir;
+ }
+ }
+
+ //up and down bobbing
+ //projectile.localAI[0] += 1f;
+ //if (projectile.localAI[0] > 120f)
+ //{
+ // projectile.localAI[0] = 0f;
+ //}
+ //value.Y += (float)Math.Cos((double)(projectile.localAI[0] * 0.05235988f)) * 2f;
+
+ Vector2 dustOffset = new Vector2((projectile.spriteDirection == -1) ? -6 : -2, -20f).RotatedBy(projectile.rotation);
+
+ Vector2 desiredCenterRelative = new Vector2(dir * (offsetX + 30), -20f + offsetY);
+
+ projectile.direction = projectile.spriteDirection = dir;
+
+ //if (reverseSide)
+ //{
+ // desiredCenterRelative.X = -desiredCenterRelative.X;
+ // //value2.X = -value2.X;
+ // projectile.direction = -projectile.direction;
+ // projectile.spriteDirection = -projectile.spriteDirection;
+ //}
+
+ if (lightDust && Main.rand.Next(24) == 0)
+ {
+ Dust dust = Dust.NewDustDirect(projectile.Center + dustOffset, 4, 4, 135, 0f, 0f, 100);
+ if (Main.rand.Next(3) != 0)
+ {
+ dust.noGravity = true;
+ dust.velocity.Y += -3f;
+ dust.noLight = true;
+ }
+ else if (Main.rand.Next(2) != 0)
+ {
+ dust.noLight = true;
+ }
+ dust.velocity *= 0.5f;
+ dust.velocity.Y += -0.9f;
+ dust.scale += 0.1f + Main.rand.NextFloat() * 0.6f;
+ dust.shader = GameShaders.Armor.GetSecondaryShader(Main.GetProjectileDesiredShader(projectile.whoAmI), player);
+ }
+
+ if (lightPet)
+ {
+ if (lightColor == default(Vector3)) lightColor = new Vector3(0.3f, 0.5f, 1f);
+ //flickerwick is new Vector3(0.3f, 0.5f, 1f)
+ Vector3 vector = DelegateMethods.v3_1 = lightColor * lightFactor;
+ Utils.PlotTileLine(projectile.Center, projectile.Center + projectile.velocity * 6f, 20f, DelegateMethods.CastLightOpen);
+ Utils.PlotTileLine(projectile.Left, projectile.Right, 20f, DelegateMethods.CastLightOpen);
+ Utils.PlotTileLine(player.Center, player.Center + player.velocity * 6f, 40f, DelegateMethods.CastLightOpen);
+ Utils.PlotTileLine(player.Left, player.Right, 40f, DelegateMethods.CastLightOpen);
+ }
+
+ Vector2 desiredCenter = player.MountedCenter + desiredCenterRelative;
+ Vector2 betweenDirection = desiredCenter - projectile.Center;
+ float betweenSQ = betweenDirection.LengthSquared();
+ //if (between > 1000f)
+ //{
+ // projectile.Center = player.Center + desiredCenterRelative;
+ //}
+ TeleportIfTooFar(projectile, desiredCenter, 1000);
+ if (betweenSQ < veloDistanceChange * veloDistanceChange)
+ {
+ projectile.velocity *= 0.25f;
+ }
+ if (betweenDirection != Vector2.Zero)
+ {
+ if (betweenSQ < (veloDistanceChange * 0.5f) * (veloDistanceChange * 0.5f))
+ {
+ projectile.velocity = betweenDirection * veloSpeed;
+ }
+ else
+ {
+ projectile.velocity = betweenDirection * 0.1f * veloSpeed;
+ }
+ }
+ if (projectile.velocity.LengthSquared() > 6f * 6f)
+ {
+ float rotationVelo = projectile.velocity.X * 0.08f * veloXToRotationFactor + projectile.velocity.Y * projectile.spriteDirection * 0.02f;
+ if (Math.Abs(projectile.rotation - rotationVelo) >= 3.14159274f)
+ {
+ if (rotationVelo < projectile.rotation)
+ {
+ projectile.rotation -= 6.28318548f;
+ }
+ else
+ {
+ projectile.rotation += 6.28318548f;
+ }
+ }
+ float rotationAcc = 12f;
+ projectile.rotation = (projectile.rotation * (rotationAcc - 1f) + rotationVelo) / rotationAcc;
+ }
+ else
+ {
+ if (projectile.rotation > 3.14159274f)
+ {
+ projectile.rotation -= 6.28318548f;
+ }
+ if (projectile.rotation > -0.005f && projectile.rotation < 0.005f)
+ {
+ projectile.rotation = 0f;
+ }
+ else
+ {
+ projectile.rotation *= 0.96f;
+ }
+ }
+ }
+ #endregion
+
+ #region EyeSpring
+
+ ///
+ /// Almost proper working Eye Spring clone
+ ///
+ public static void EyeSpringAI(Projectile projectile, bool flyForever = false)
+ {
+ Player player = projectile.GetOwner();
+ if (!player.active)
+ {
+ projectile.active = false;
+ }
+ else
+ {
+ bool flag = false;
+ bool flag2 = false;
+ bool flag3 = false;
+ bool flag4 = false;
+ int num = 85;
+ if (player.position.X + (float)(player.width / 2) < projectile.position.X + (float)(projectile.width / 2) - (float)num)
+ {
+ flag = true;
+ }
+ else if (player.position.X + (float)(player.width / 2) > projectile.position.X + (float)(projectile.width / 2) + (float)num)
+ {
+ flag2 = true;
+ }
+ if (projectile.ai[1] == 0f)
+ {
+ int num38 = 500;
+ if (player.rocketDelay2 > 0)
+ {
+ projectile.ai[0] = 1f;
+ }
+ Vector2 vector6 = new Vector2(projectile.position.X + (float)projectile.width * 0.5f, projectile.position.Y + (float)projectile.height * 0.5f);
+ float num39 = player.position.X + (float)(player.width / 2) - vector6.X;
+ float num40 = player.position.Y + (float)(player.height / 2) - vector6.Y;
+ float num41 = (float)Math.Sqrt((double)(num39 * num39 + num40 * num40));
+ if (num41 > 2000f)
+ {
+ TeleportIfTooFar(projectile, player.Center);
+ //projectile.position.X = player.position.X + (float)(player.width / 2) - (float)(projectile.width / 2);
+ //projectile.position.Y = player.position.Y + (float)(player.height / 2) - (float)(projectile.height / 2);
+ }
+ else if (num41 > (float)num38 || (Math.Abs(num40) > 300f) || flyForever)
+ {
+ projectile.ai[0] = 1f;
+ }
+ }
+ if (projectile.ai[0] != 0f)
+ {
+ float num42 = 0.2f;
+ int num43 = 200;
+ projectile.tileCollide = false;
+ Vector2 vector7 = new Vector2(projectile.position.X + (float)projectile.width * 0.5f, projectile.position.Y + (float)projectile.height * 0.5f);
+ float num44 = player.position.X + (float)(player.width / 2) - vector7.X;
+ float num51 = player.position.Y + (float)(player.height / 2) - vector7.Y;
+ float num52 = (float)Math.Sqrt((double)(num44 * num44 + num51 * num51));
+ float num53 = 10f;
+ //float num54 = num52;
+ if (num52 < (float)num43 && player.velocity.Y == 0f && projectile.position.Y + (float)projectile.height <= player.position.Y + (float)player.height && !Collision.SolidCollision(projectile.position, projectile.width, projectile.height))
+ {
+ projectile.ai[0] = 0f;
+ if (projectile.velocity.Y < -6f)
+ {
+ projectile.velocity.Y = -6f;
+ }
+ }
+ if (num52 < 60f)
+ {
+ num44 = projectile.velocity.X;
+ num51 = projectile.velocity.Y;
+ }
+ else
+ {
+ num52 = num53 / num52;
+ num44 *= num52;
+ num51 *= num52;
+ }
+ if (projectile.velocity.X < num44)
+ {
+ projectile.velocity.X += num42;
+ if (projectile.velocity.X < 0f)
+ {
+ projectile.velocity.X += num42 * 1.5f;
+ }
+ }
+ if (projectile.velocity.X > num44)
+ {
+ projectile.velocity.X -= num42;
+ if (projectile.velocity.X > 0f)
+ {
+ projectile.velocity.X -= num42 * 1.5f;
+ }
+ }
+ if (projectile.velocity.Y < num51)
+ {
+ projectile.velocity.Y += num42;
+ if (projectile.velocity.Y < 0f)
+ {
+ projectile.velocity.Y += num42 * 1.5f;
+ }
+ }
+ if (projectile.velocity.Y > num51)
+ {
+ projectile.velocity.Y -= num42;
+ if (projectile.velocity.Y > 0f)
+ {
+ projectile.velocity.Y -= num42 * 1.5f;
+ }
+ }
+ if ((double)projectile.velocity.X > 0.5)
+ {
+ projectile.spriteDirection = -1;
+ }
+ else if ((double)projectile.velocity.X < -0.5)
+ {
+ projectile.spriteDirection = 1;
+ }
+ projectile.frameCounter++;
+ if (projectile.frameCounter > 4)
+ {
+ projectile.frame++;
+ projectile.frameCounter = 0;
+ }
+ if (projectile.frame < 6 || projectile.frame > 7)
+ {
+ projectile.frame = 6;
+ }
+ projectile.rotation = projectile.velocity.ToRotation() + 1.57f;
+ }
+ else
+ {
+ //Vector2 vector9 = Vector2.Zero;
+ if (projectile.ai[1] != 0f)
+ {
+ flag = false;
+ flag2 = false;
+ }
+ projectile.rotation = 0f;
+ projectile.tileCollide = true;
+ float num111 = 8f;
+ float num110 = 0.4f;
+ if (flag)
+ {
+ if (projectile.velocity.X > -3.5f)
+ {
+ projectile.velocity.X -= num110;
+ }
+ else
+ {
+ projectile.velocity.X -= num110 * 0.25f;
+ }
+ }
+ else if (flag2)
+ {
+ if (projectile.velocity.X < 3.5f)
+ {
+ projectile.velocity.X += num110;
+ }
+ else
+ {
+ projectile.velocity.X += num110 * 0.25f;
+ }
+ }
+ else
+ {
+ projectile.velocity.X *= 0.9f;
+ if (projectile.velocity.X >= 0f - num110 && projectile.velocity.X <= num110)
+ {
+ projectile.velocity.X = 0f;
+ }
+ }
+ if (flag | flag2)
+ {
+ int num112 = (int)(projectile.position.X + (float)(projectile.width / 2)) / 16;
+ int j = (int)(projectile.position.Y + (float)(projectile.height / 2)) / 16;
+ if (flag)
+ {
+ int num30 = num112;
+ num112 = num30 - 1;
+ }
+ if (flag2)
+ {
+ int num30 = num112;
+ num112 = num30 + 1;
+ }
+ num112 += (int)projectile.velocity.X;
+ if (WorldGen.SolidTile(num112, j))
+ {
+ flag4 = true;
+ }
+ }
+ if (player.position.Y + player.height - 8f > projectile.position.Y + projectile.height)
+ {
+ flag3 = true;
+ }
+ if (projectile.frameCounter < 10)
+ {
+ flag4 = false;
+ }
+ //projectile.stepSpeed = 1f;
+ //projectile.gfxOffY = 0f;
+ //Collision.StepUp(ref projectile.position, ref projectile.velocity, projectile.width, projectile.height, ref stepSpeed, ref gfxOffY);
+ Collision.StepUp(ref projectile.position, ref projectile.velocity, projectile.width, projectile.height, ref projectile.stepSpeed, ref projectile.gfxOffY);
+ if (projectile.velocity.Y == 0f)
+ {
+ if (!flag3 && (projectile.velocity.X < 0f || projectile.velocity.X > 0f))
+ {
+ int num113 = (int)(projectile.position.X + (projectile.width / 2)) / 16;
+ int j2 = (int)(projectile.position.Y + (projectile.height / 2)) / 16 + 1;
+ if (flag)
+ {
+ int num30 = num113;
+ num113 = num30 - 1;
+ }
+ if (flag2)
+ {
+ int num30 = num113;
+ num113 = num30 + 1;
+ }
+ WorldGen.SolidTile(num113, j2);
+ }
+ if (flag4)
+ {
+ int num114 = (int)(projectile.position.X + projectile.width / 2) / 16;
+ int num115 = (int)(projectile.position.Y + projectile.height) / 16 + 1;
+ if (WorldGen.SolidTile(num114, num115) || Main.tile[num114, num115].IsHalfBlock || Main.tile[num114, num115].Slope > 0)
+ {
+ try
+ {
+ num114 = (int)(projectile.position.X + projectile.width / 2) / 16;
+ num115 = (int)(projectile.position.Y + projectile.height / 2) / 16;
+ if (flag)
+ {
+ int num30 = num114;
+ num114 = num30 - 1;
+ }
+ if (flag2)
+ {
+ int num30 = num114;
+ num114 = num30 + 1;
+ }
+ num114 += (int)projectile.velocity.X;
+ if (!WorldGen.SolidTile(num114, num115 - 1) && !WorldGen.SolidTile(num114, num115 - 2))
+ {
+ projectile.velocity.Y = -5.1f;
+ }
+ else if (!WorldGen.SolidTile(num114, num115 - 2))
+ {
+ projectile.velocity.Y = -7.1f;
+ }
+ else if (WorldGen.SolidTile(num114, num115 - 5))
+ {
+ projectile.velocity.Y = -11.1f;
+ }
+ else if (WorldGen.SolidTile(num114, num115 - 4))
+ {
+ projectile.velocity.Y = -10.1f;
+ }
+ else
+ {
+ projectile.velocity.Y = -9.1f;
+ }
+ }
+ catch
+ {
+ projectile.velocity.Y = -9.1f;
+ }
+ }
+ }
+ }
+ if (projectile.velocity.X > num111)
+ {
+ projectile.velocity.X = num111;
+ }
+ if (projectile.velocity.X < 0f - num111)
+ {
+ projectile.velocity.X = 0f - num111;
+ }
+ if (projectile.velocity.X < 0f)
+ {
+ projectile.direction = -1;
+ }
+ if (projectile.velocity.X > 0f)
+ {
+ projectile.direction = 1;
+ }
+ if (projectile.velocity.X > num110 && flag2)
+ {
+ projectile.direction = 1;
+ }
+ if (projectile.velocity.X < 0f - num110 && flag)
+ {
+ projectile.direction = -1;
+ }
+
+
+ //fix cause im dumb and didnt copy ai code correctly
+ if (!flag && !flag2 && projectile.ai[0] == 0f)
+ {
+ projectile.direction = (player.Center - projectile.Center).X > 0 ? 1 : -1;
+ }
+
+
+ if (projectile.direction == -1)
+ {
+ projectile.spriteDirection = 1;
+ }
+ if (projectile.direction == 1)
+ {
+ projectile.spriteDirection = -1;
+ }
+
+ if (projectile.velocity.Y == 0f)
+ {
+ if (projectile.frame > 5)
+ {
+ projectile.frameCounter = 0;
+ }
+ if (projectile.velocity.X == 0f)
+ {
+ int num116 = 3;
+ projectile.frameCounter++;
+ if (projectile.frameCounter < num116)
+ {
+ projectile.frame = 0;
+ }
+ else if (projectile.frameCounter < num116 * 2)
+ {
+ projectile.frame = 1;
+ }
+ else if (projectile.frameCounter < num116 * 3)
+ {
+ projectile.frame = 2;
+ }
+ else if (projectile.frameCounter < num116 * 4)
+ {
+ projectile.frame = 3;
+ }
+ else
+ {
+ projectile.frameCounter = num116 * 4;
+ }
+ }
+ else
+ {
+ projectile.velocity.X *= 0.8f;
+ projectile.frameCounter++;
+ int num117 = 3;
+ if (projectile.frameCounter < num117)
+ {
+ projectile.frame = 0;
+ }
+ else if (projectile.frameCounter < num117 * 2)
+ {
+ projectile.frame = 1;
+ }
+ else if (projectile.frameCounter < num117 * 3)
+ {
+ projectile.frame = 2;
+ }
+ else if (projectile.frameCounter < num117 * 4)
+ {
+ projectile.frame = 3;
+ }
+ else if (flag | flag2)
+ {
+ projectile.velocity.X *= 2f;
+ projectile.frame = 4;
+ projectile.velocity.Y = -6.1f;
+ projectile.frameCounter = 0;
+ int num30;
+ for (int num118 = 0; num118 < 4; num118 = num30 + 1)
+ {
+ /*int num119 = 0; Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y + (float)projectile.height - 2f), projectile.width, 4, 5)*/
+ ;
+ //Dust dust = Main.dust[num119];
+ //dust.velocity += projectile.velocity;
+ //dust = Main.dust[num119];
+ //dust.velocity *= 0.4f;
+ num30 = num118;
+ }
+ }
+ else
+ {
+ projectile.frameCounter = num117 * 4;
+ }
+ }
+ }
+ else if (projectile.velocity.Y < 0f)
+ {
+ projectile.frameCounter = 0;
+ projectile.frame = 5;
+ }
+ else
+ {
+ projectile.frame = 4;
+ projectile.frameCounter = 3;
+ }
+ projectile.velocity.Y += 0.4f;
+ if (projectile.velocity.Y > 10f)
+ {
+ projectile.velocity.Y = 10f;
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region Zephyrfish
+ public static void ZephyrfishDraw(Projectile projectile, int frameCounter = 5)
+ {
+ projectile.frameCounter++;
+ if (projectile.frameCounter > frameCounter)
+ {
+ projectile.frame++;
+ projectile.frameCounter = 0;
+ }
+ if (projectile.frame >= Main.projFrames[projectile.type]) //3
+ {
+ projectile.frame = 0;
+ }
+ }
+
+ ///
+ /// Stays around a certain offset position around the parent. Does not use ai/localai
+ ///
+ public static void ZephyrfishAI(Projectile projectile, Entity parent = null, float velocityFactor = 1f, float sway = 1f, bool random = true, byte swapSides = 0, float offsetX = 0f, float offsetY = 0f)
+ {
+ //velocityFactor:
+ //kinda wonky, leave at 1f
+
+ //sway:
+ //tells by how much increase/decrease the left/right sway of the idle pet
+
+ //swapSides:
+ // 0: always behind
+ //-1: always left
+ // 1: always right
+
+ //offsetX/Y
+ //offsetting the desired center the pet hovers around
+
+ if (parent == null) parent = projectile.GetOwner();
+
+ Vector2 parentCenter = parent.Center;
+ if (parent is Player)
+ {
+ parentCenter = ((Player)parent).MountedCenter;
+ }
+
+ float veloDelta = 0.3f;
+ projectile.tileCollide = false; //false
+ int someDistance = 100;
+ Vector2 between = parentCenter - projectile.Center;
+
+ Vector2 desiredCenter = random ? new Vector2(Main.rand.Next(-10, 21), Main.rand.Next(-10, 21)) : Vector2.Zero;
+
+ Vector2 offset = new Vector2(60f + offsetX, -60f + offsetY);
+
+ if (swapSides == 1)
+ {
+ offset.X = -offset.X;
+ }
+ else if (swapSides == 0)
+ {
+ offset.X *= -parent.direction;
+ }
+
+ //desiredCenter += new Vector2(60f * -player.direction, -60f);
+ between += desiredCenter + offset;
+
+ TeleportIfTooFar(projectile, parentCenter + desiredCenter + offset);
+
+ float distance = between.Length();
+ //float magnitude = 6f;
+ if (distance < someDistance && parent.velocity.Y == 0f && projectile.position.Y + projectile.height <= parent.position.Y + parent.height && !Collision.SolidCollision(projectile.position, projectile.width, projectile.height))
+ {
+ //projectile.ai[0] = 0;
+ if (projectile.velocity.Y < -6f)
+ {
+ projectile.velocity.Y = -6f;
+ }
+ }
+ float swayDistance = 50 * sway;
+ if (distance < swayDistance) //50
+ {
+ if (Math.Abs(projectile.velocity.X) > 2f || Math.Abs(projectile.velocity.Y) > 2f)
+ {
+ projectile.velocity *= 0.99f;
+ }
+ veloDelta = 0.01f;
+ }
+ else
+ {
+ if (distance < swayDistance * 2) //100
+ {
+ veloDelta = 0.1f;
+ }
+ //between: 0.3f
+ if (distance > swayDistance * 6) //300
+ {
+ veloDelta = 0.4f;
+ }
+ between.Normalize();
+ between *= 6f;
+ between *= velocityFactor;
+ }
+ veloDelta *= velocityFactor;
+ if (projectile.velocity.X < between.X)
+ {
+ projectile.velocity.X += veloDelta;
+ if (veloDelta > 0.05f && projectile.velocity.X < 0f)
+ {
+ projectile.velocity.X += +veloDelta;
+ }
+ }
+ if (projectile.velocity.X > between.X)
+ {
+ projectile.velocity.X += -veloDelta;
+ if (veloDelta > 0.05f && projectile.velocity.X > 0f)
+ {
+ projectile.velocity.X += -veloDelta;
+ }
+ }
+ if (projectile.velocity.Y < between.Y)
+ {
+ projectile.velocity.Y += veloDelta;
+ if (veloDelta > 0.05f && projectile.velocity.Y < 0f)
+ {
+ projectile.velocity.Y += veloDelta * 2f;
+ }
+ }
+ if (projectile.velocity.Y > between.Y)
+ {
+ projectile.velocity.Y += -veloDelta;
+ if (veloDelta > 0.05f && projectile.velocity.Y > 0f)
+ {
+ projectile.velocity.Y += -veloDelta * 2f;
+ }
+ }
+ projectile.manualDirectionChange = true;
+ if (projectile.velocity.X > 0.25f && projectile.direction == 1)
+ {
+ projectile.direction = -1;
+ }
+ else if (projectile.velocity.X < -0.25f && projectile.direction != 1)
+ {
+ projectile.direction = 1;
+ }
+ projectile.spriteDirection = projectile.direction;
+
+ //fix, direction gets set automatically by "manualDirectionChange = false" projectiled on velocity.X
+ //if (projectile.velocity.X > 0.25f)
+ //{
+ // projectile.ai[0] = -1;
+ //}
+ //else if (projectile.velocity.X < -0.25f)
+ //{
+ // projectile.ai[0] = 1;
+ //}
+ //projectile.direction = (int)projectile.ai[0];
+ //projectile.spriteDirection = projectile.direction;
+ projectile.rotation = projectile.velocity.X * 0.05f;
+ }
+ #endregion
+
+ #region BabyEater
+ public static void BabyEaterDraw(Projectile projectile, int frameCounter = 6)
+ {
+ projectile.frameCounter++;
+ if (projectile.frameCounter > frameCounter)
+ {
+ projectile.frame++;
+ projectile.frameCounter = 0;
+ }
+ if (projectile.frame >= Main.projFrames[projectile.type]) //2
+ {
+ projectile.frame = 0;
+ }
+ }
+
+ public static void BabyEaterAI(Projectile projectile, Entity parent = null, Vector2 originOffset = default(Vector2), float velocityFactor = 1f, float sway = 1f)
+ {
+ //velocityFactor:
+ //kinda wonky, leave at 1f
+
+ //sway:
+ //tells by how much increase/decrease the left/right sway radius of the idle pet
+
+ if (parent == null) parent = projectile.GetOwner();
+
+ if (!parent.active)
+ {
+ projectile.active = false;
+ return;
+ }
+
+ Vector2 parentCenter = parent.Center;
+ if (parent is Player)
+ {
+ parentCenter = ((Player)parent).MountedCenter;
+ }
+ parentCenter += originOffset;
+
+ float veloDelta = 0.1f;
+ projectile.tileCollide = false;
+ int someDistance = 300;
+ Vector2 between = parentCenter - projectile.Center;
+ float distance = between.Length();
+ float magnitude = 7f;
+
+ TeleportIfTooFar(projectile, parentCenter, 1380);
+
+ if (distance < someDistance && parent.velocity.Y == 0f && projectile.position.Y + projectile.height <= parent.position.Y + parent.height + originOffset.Y && !Collision.SolidCollision(projectile.position, projectile.width, projectile.height))
+ {
+ if (projectile.velocity.Y < -6f)
+ {
+ projectile.velocity.Y = -6f;
+ }
+ }
+ float swayDistance = 150f * sway;
+ if (distance < swayDistance)
+ {
+ if (Math.Abs(projectile.velocity.X) > 2f || Math.Abs(projectile.velocity.Y) > 2f)
+ {
+ projectile.velocity *= 0.99f;
+ }
+ veloDelta = 0.01f;
+ if (between.X < -2f)
+ {
+ between.X = -2f;
+ }
+ if (between.X > 2f)
+ {
+ between.X = 2f;
+ }
+ if (between.Y < -2f)
+ {
+ between.Y = -2f;
+ }
+ if (between.Y > 2f)
+ {
+ between.Y = 2f;
+ }
+ }
+ else
+ {
+ if (distance > swayDistance * 2f)
+ {
+ veloDelta = 0.2f;
+ }
+ between.Normalize();
+ between *= magnitude;
+ }
+
+ veloDelta *= velocityFactor;
+
+ if (Math.Abs(between.X) > Math.Abs(between.Y))
+ {
+ if (projectile.velocity.X < between.X)
+ {
+ projectile.velocity.X += veloDelta;
+ if (veloDelta > 0.05f && projectile.velocity.X < 0f)
+ {
+ projectile.velocity.X += veloDelta;
+ }
+ }
+ if (projectile.velocity.X > between.X)
+ {
+ projectile.velocity.X += -veloDelta;
+ if (veloDelta > 0.05f && projectile.velocity.X > 0f)
+ {
+ projectile.velocity.X += -veloDelta;
+ }
+ }
+ }
+ if (Math.Abs(between.X) <= Math.Abs(between.Y) || veloDelta == 0.05f)
+ {
+ if (projectile.velocity.Y < between.Y)
+ {
+ projectile.velocity.Y += veloDelta;
+ if (veloDelta > 0.05f && projectile.velocity.Y < 0f)
+ {
+ projectile.velocity.Y += veloDelta;
+ }
+ }
+ if (projectile.velocity.Y > between.Y)
+ {
+ projectile.velocity.Y += -veloDelta;
+ if (veloDelta > 0.05f && projectile.velocity.Y > 0f)
+ {
+ projectile.velocity.Y += -veloDelta;
+ }
+ }
+ }
+ projectile.rotation = projectile.velocity.ToRotation() - 1.57f;
+ }
+ #endregion
+
+ #region StardustDragon
+
+
+ //ProjectileID.Sets.
+ //NeedsUUID = true;
+ //DontAttachHideToAlpha =true;
+
+ //if minion = true:
+ //ProjectileID.Sets.MinionSacrificable[projectile.type] = false, cause the replacing code for worm minions is complicated
+ //damage set in NewProjectile/item
+ //scales in size with the amount of segments
+ public static void StardustDragonSetDefaults(Projectile projectile, int size = 24, bool minion = true, WormType wormType = WormType.None)
+ {
+ if (minion)
+ {
+ //if (projectile.type == 625 || projectile.type == 628)
+ //{
+ // projectile.netImportant = true;
+ //}
+ if (wormType == WormType.Body1 || wormType == WormType.Body2)
+ {
+ projectile.minionSlots = 0.5f;
+ }
+ projectile.DamageType = DamageClass.Summon;
+ projectile.minion = true;
+ //projectile.hide = true;
+ projectile.netImportant = true;
+ }
+ projectile.Size = new Vector2(size);
+ projectile.penetrate = -1;
+ projectile.timeLeft *= 5;
+ projectile.friendly = true;
+ projectile.ignoreWater = true;
+ projectile.tileCollide = false;
+ projectile.alpha = 255;
+ }
+ //wormTypes = new int[] {head, body1, body2, tail} //projectiletype
+
+ //if minion = true:
+ //float scaleFactor = MathHelper.Clamp(projectile.localAI[0], 0f, 50f);
+ //projectile.scale = 1f + scaleFactor * 0.01f;
+ public static void StardustDragonAI(Projectile projectile, int[] wormTypes, int segmentDistance = 16)
+ {
+ Player player = projectile.GetOwner();
+
+ if (projectile.minion && (int)Main.time % 120 == 0)
+ {
+ projectile.netUpdate = true;
+ }
+ if (!player.active)
+ {
+ projectile.active = false;
+ return;
+ }
+ bool head = projectile.type == wormTypes[0];
+ int defScaleFactor = 30;
+ //if (Main.rand.Next(30) == 0)
+ //{
+ // int num1049 = Dust.NewDust(projectile.position, projectile.width, projectile.height, 135, 0f, 0f, 0, default(Color), 2f);
+ // Main.dust[num1049].noGravity = true;
+ // Main.dust[num1049].fadeIn = 2f;
+ // Point point4 = Main.dust[num1049].position.ToTileCoordinates();
+ // if (WorldGen.InWorld(point4.X, point4.Y, 5) && WorldGen.SolidTile(point4.X, point4.Y))
+ // {
+ // Main.dust[num1049].noLight = true;
+ // }
+ //}
+
+ if (projectile.alpha > 0)
+ {
+ //for (int i = 0; i < 2; i++)
+ //{
+ // int dust = Dust.NewDust(new Vector2(projectile.position.X, projectile.position.Y), projectile.width, projectile.height, 135, 0f, 0f, 100, default(Color), 2f);
+ // Main.dust[dust].noGravity = true;
+ // Main.dust[dust].noLight = true;
+ //}
+ projectile.alpha -= 42;
+ if (projectile.alpha < 0)
+ {
+ projectile.alpha = 0;
+ return;
+ }
+ }
+
+ if (head)
+ {
+ Vector2 desiredCenter = player.Center;
+ int targetIndex = -1;
+ TeleportIfTooFar(projectile, desiredCenter);
+ if (projectile.minion)
+ {
+ float maxProjDistance = 490000f;
+ float maxPlayerDistance = 1000000f;
+ NPC ownerMinionAttackTargetNPC5 = projectile.OwnerMinionAttackTargetNPC;
+ if (ownerMinionAttackTargetNPC5 != null && ownerMinionAttackTargetNPC5.CanBeChasedBy())
+ {
+ float distance1 = projectile.DistanceSQ(ownerMinionAttackTargetNPC5.Center);
+ if (distance1 < maxProjDistance * 2f)
+ {
+ targetIndex = ownerMinionAttackTargetNPC5.whoAmI;
+ }
+ }
+ if (targetIndex < 0)
+ {
+ for (int i = 0; i < Main.maxNPCs; i++)
+ {
+ NPC npc = Main.npc[i];
+ if (npc.CanBeChasedBy() && player.DistanceSQ(npc.Center) < maxPlayerDistance)
+ {
+ float distance2 = projectile.DistanceSQ(npc.Center);
+ if (distance2 < maxProjDistance)
+ {
+ targetIndex = i;
+ }
+ }
+ }
+ }
+ }
+ if (targetIndex != -1)
+ {
+ NPC npc = Main.npc[targetIndex];
+ Vector2 betweenNPC = npc.Center - projectile.Center;
+ float veloFactor = 0.4f;
+ if (betweenNPC.Length() < 600f)
+ {
+ veloFactor = 0.6f;
+ }
+ if (betweenNPC.Length() < 300f)
+ {
+ veloFactor = 0.8f;
+ }
+ if (betweenNPC.Length() > npc.Size.Length() * 0.75f)
+ {
+ projectile.velocity += Vector2.Normalize(betweenNPC) * veloFactor * 1.5f;
+ if (Vector2.Dot(projectile.velocity, betweenNPC) < 0.25f)
+ {
+ projectile.velocity *= 0.8f;
+ }
+ }
+ float targetMagnitude = 30f;
+ if (projectile.velocity.Length() > targetMagnitude)
+ {
+ projectile.velocity = Vector2.Normalize(projectile.velocity) * targetMagnitude;
+ }
+ }
+ else
+ {
+ float idleVelo = 0.2f;
+ Vector2 betweenPlayer = desiredCenter - projectile.Center;
+ if (betweenPlayer.Length() < 200f)
+ {
+ idleVelo = 0.12f;
+ }
+ if (betweenPlayer.Length() < 140f)
+ {
+ idleVelo = 0.06f;
+ }
+ if (betweenPlayer.Length() > 100f)
+ {
+ if (Math.Abs(desiredCenter.X - projectile.Center.X) > 20f)
+ {
+ projectile.velocity.X += idleVelo * Math.Sign(desiredCenter.X - projectile.Center.X);
+ }
+ if (Math.Abs(desiredCenter.Y - projectile.Center.Y) > 10f)
+ {
+ projectile.velocity.Y += idleVelo * Math.Sign(desiredCenter.Y - projectile.Center.Y);
+ }
+ }
+ else if (projectile.velocity.Length() > 2f)
+ {
+ projectile.velocity *= 0.96f;
+ }
+ if (Math.Abs(projectile.velocity.Y) < 1f)
+ {
+ projectile.velocity.Y += -0.1f;
+ }
+ float idleMagnitude = 15f;
+ if (projectile.velocity.Length() > idleMagnitude)
+ {
+ projectile.velocity = Vector2.Normalize(projectile.velocity) * idleMagnitude;
+ }
+ }
+ projectile.rotation = projectile.velocity.ToRotation() + 1.57079637f;
+ int direction = projectile.direction;
+ projectile.direction = projectile.spriteDirection = (projectile.velocity.X > 0f) ? 1 : -1;
+ if (projectile.minion && direction != projectile.direction)
+ {
+ projectile.netUpdate = true;
+ }
+ float scaleFactor = MathHelper.Clamp(projectile.localAI[0], 0f, 50f);
+ if (!projectile.minion) scaleFactor = 0;
+ projectile.position = projectile.Center;
+ projectile.scale = 1f + scaleFactor * 0.01f;
+ projectile.width = projectile.height = (int)(defScaleFactor * projectile.scale);
+ projectile.Center = projectile.position;
+ }
+ else
+ {
+ Vector2 pCenter = Vector2.Zero;
+ float parentRotation = 0f;
+ float positionOffset = 0f;
+ float scaleOffset = 1f;
+
+ //some custom syncing it seems like, when summoning/replacing it
+ if (projectile.ai[1] == 1f)
+ {
+ projectile.ai[1] = 0f;
+ projectile.netUpdate = true;
+ }
+
+ Projectile parent = null;
+ for (short i = 0; i < Main.maxProjectiles; i++)
+ {
+ Projectile proj = Main.projectile[i];
+ if (proj.active && proj.owner == projectile.owner && proj.identity == (int)projectile.ai[0]/* && proj.type == projectile.type*/)
+ {
+ parent = proj;
+ break;
+ }
+ }
+ if (parent != null)
+ {
+ if (parent.active && (parent.type == wormTypes[0] || parent.type == wormTypes[1] || parent.type == wormTypes[2]))
+ {
+ pCenter = parent.Center;
+ //Vector2 velocity2 = parent.velocity;
+ parentRotation = parent.rotation;
+ scaleOffset = MathHelper.Clamp(parent.scale, 0f, 50f);
+ if (!projectile.minion) scaleOffset = 1;
+ positionOffset = segmentDistance;
+ parent.localAI[0] = projectile.localAI[0] + 1f;
+ if (parent.type != wormTypes[0])
+ {
+ parent.localAI[1] = projectile.whoAmI;
+ }
+ if (projectile.owner == Main.myPlayer && parent.type == wormTypes[0] && projectile.type == wormTypes[3])
+ {
+ parent.Kill();
+ projectile.Kill();
+ return;
+ }
+ }
+
+ projectile.velocity = Vector2.Zero;
+ Vector2 newVelocity = pCenter - projectile.Center;
+ if (parentRotation != projectile.rotation)
+ {
+ float rotatedBy = MathHelper.WrapAngle(parentRotation - projectile.rotation);
+ newVelocity = newVelocity.RotatedBy(rotatedBy * 0.1f);
+ }
+ projectile.rotation = newVelocity.ToRotation() + 1.57079637f;
+ projectile.position = projectile.Center;
+ projectile.scale = scaleOffset;
+ projectile.width = projectile.height = (int)(defScaleFactor * projectile.scale);
+ projectile.Center = projectile.position;
+ if (newVelocity != Vector2.Zero)
+ {
+ projectile.Center = pCenter - Vector2.Normalize(newVelocity) * positionOffset * scaleOffset;
+ }
+ projectile.spriteDirection = (newVelocity.X > 0f) ? 1 : -1;
+ }
+ }
+ }
+
+ #endregion
+
+ public static void ModifiedGoldfishAI(NPC npc, float scareRange, bool faceAway = true)
+ {
+ if (npc.direction == 0)
+ {
+ npc.TargetClosest();
+ }
+ if (npc.wet)
+ {
+ bool hasPlayer = false;
+ npc.TargetClosest(faceTarget: false);
+ Vector2 centerpos = npc.Center;
+ Player player = Main.player[npc.target];
+ Vector2 playerpos = player.Center;
+ float distancex = playerpos.X - centerpos.X;
+ float distancey = playerpos.Y - centerpos.Y;
+ float distSQ = distancex * distancex + distancey * distancey;
+ if (player.wet && distSQ < scareRange * scareRange)
+ {
+ if (!player.dead)
+ {
+ hasPlayer = true;
+ }
+ }
+ if (!hasPlayer)
+ {
+ if (npc.collideX)
+ {
+ npc.velocity.X *= -1;
+ npc.direction *= -1;
+ npc.netUpdate = true;
+ }
+ if (npc.collideY)
+ {
+ npc.netUpdate = true;
+ if (npc.velocity.Y > 0f)
+ {
+ npc.velocity.Y = Math.Abs(npc.velocity.Y) * -1f;
+ npc.directionY = -1;
+ npc.ai[0] = -1f;
+ }
+ else if (npc.velocity.Y < 0f)
+ {
+ npc.velocity.Y = Math.Abs(npc.velocity.Y);
+ npc.directionY = 1;
+ npc.ai[0] = 1f;
+ }
+ }
+ }
+ if (hasPlayer) //if target is in water
+ {
+ npc.TargetClosest(faceTarget: false);
+ npc.direction = (distancex >= 0f).ToDirectionInt();
+ npc.directionY = (distancey >= 0f).ToDirectionInt();
+
+ if (faceAway)
+ {
+ npc.direction *= -1;
+ npc.directionY *= -1;
+ }
+
+ npc.velocity.X += npc.direction * 0.1f;
+ npc.velocity.Y += npc.directionY * 0.1f;
+
+ if (npc.velocity.X > 3f)
+ {
+ npc.velocity.X = 3f;
+ }
+ if (npc.velocity.X < -3f)
+ {
+ npc.velocity.X = -3f;
+ }
+ if (npc.velocity.Y > 2f)
+ {
+ npc.velocity.Y = 2f;
+ }
+ if (npc.velocity.Y < -2f)
+ {
+ npc.velocity.Y = -2f;
+ }
+ }
+ else
+ {
+ npc.velocity.X += npc.direction * 0.1f;
+ if (npc.velocity.X < -1f || npc.velocity.X > 1f)
+ {
+ npc.velocity.X *= 0.95f;
+ }
+ if (npc.ai[0] == -1f)
+ {
+ npc.velocity.Y -= 0.01f;
+ if (npc.velocity.Y < -0.3f)
+ {
+ npc.ai[0] = 1f;
+ }
+ }
+ else
+ {
+ npc.velocity.Y += 0.01f;
+ if (npc.velocity.Y > 0.3f)
+ {
+ npc.ai[0] = -1f;
+ }
+ }
+ int tileX = (int)npc.Center.X / 16;
+ int tileY = (int)npc.Center.Y / 16;
+ if (Framing.GetTileSafely(tileX, tileY - 1).LiquidAmount > 128)
+ {
+ if (Framing.GetTileSafely(tileX, tileY + 1).HasTile)
+ {
+ npc.ai[0] = -1f;
+ }
+ else if (Framing.GetTileSafely(tileX, tileY + 2).HasTile)
+ {
+ npc.ai[0] = -1f;
+ }
+ }
+ if (npc.velocity.Y > 0.4f || npc.velocity.Y < -0.4f)
+ {
+ npc.velocity.Y *= 0.95f;
+ }
+ }
+ }
+ else //not wet, frantically jump around
+ {
+ if (npc.velocity.Y == 0f)
+ {
+ if (Main.netMode != NetmodeID.MultiplayerClient)
+ {
+ npc.velocity.Y = Main.rand.Next(-50, -20) * 0.1f;
+ npc.velocity.X = Main.rand.Next(-20, 20) * 0.1f;
+ npc.netUpdate = true;
+ }
+ }
+ npc.velocity.Y += 0.3f;
+ if (npc.velocity.Y > 10f)
+ {
+ npc.velocity.Y = 10f;
+ }
+ npc.ai[0] = 1f;
+ }
+ npc.rotation = npc.velocity.Y * npc.direction * 0.1f;
+ if (npc.rotation < -0.2f)
+ {
+ npc.rotation = -0.2f;
+ }
+ if (npc.rotation > 0.2f)
+ {
+ npc.rotation = 0.2f;
+ }
+ }
+
+ //TODO turn into usable method later
+ public static void PirateAI(Projectile Projectile)
+ {
+ // //Pirate AI related:
+ //public int State
+ //{
+ // get => (int)Projectile.ai[0];
+ // set => Projectile.ai[0] = value;
+ //}
+
+ //public int Timer
+ //{
+ // get => (int)Projectile.ai[1];
+ // set => Projectile.ai[1] = value;
+ //}
+
+ //public bool Idle => State == 0;
+
+ //public bool Flying
+ //{
+ // get => State == 1;
+ // set => State = value ? 1 : 0;
+ //}
+
+ //public bool Attacking
+ //{
+ // get => State == 2;
+ // set => State = value ? 2 : 0;
+ //}
+ int Timer = 0;
+ bool Idle = true;
+ bool Flying = false;
+ bool Attacking = false;
+ ////End Pirate AI
+
+ Player player = Main.player[Projectile.owner];
+
+ int startAttackRange = 800;
+ float awayFromPlayerDistMax = 500f;
+ float awayFromPlayerDistYMax = 300f;
+
+ Vector2 destination = player.Center;
+ destination.X -= (15 + player.width / 2) * player.direction;
+ destination.X -= Projectile.minionPos * 25 * player.direction;
+
+ Projectile.shouldFallThrough = player.Bottom.Y - 12f > Projectile.Bottom.Y;
+ Projectile.friendly = false;
+ int timerReset = 0;
+ int attackFrameCount = 3;
+ int nextTimerValue = 5 * attackFrameCount;
+ int attackTarget = -1;
+
+ bool defaultstate = Idle;
+
+ static bool CustomEliminationCheck_Pirates(Entity otherEntity, int currentTarget) => true;
+
+ if (defaultstate)
+ Projectile.Minion_FindTargetInRange(startAttackRange, ref attackTarget, skipIfCannotHitWithOwnBody: true, CustomEliminationCheck_Pirates);
+
+ if (Flying)
+ {
+ Projectile.tileCollide = false;
+ float velChange = 0.2f;
+ float toPlayerSpeed = 10f;
+ int maxLen = 200;
+ if (toPlayerSpeed < Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y))
+ toPlayerSpeed = Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y);
+
+ Vector2 toPlayer = player.Center - Projectile.Center;
+ float len = toPlayer.Length();
+
+ AssAI.TeleportIfTooFar(Projectile, player.Center);
+
+ if (len < maxLen && player.velocity.Y == 0f && Projectile.Bottom.Y <= player.Bottom.Y && !Collision.SolidCollision(Projectile.position, Projectile.width, Projectile.height))
+ {
+ //Reset back from flying
+ Flying = false;
+ Projectile.netUpdate = true;
+ if (Projectile.velocity.Y < -6f)
+ Projectile.velocity.Y = -6f;
+ }
+
+ if (!(len < 60f))
+ {
+ toPlayer.Normalize();
+ toPlayer *= toPlayerSpeed;
+ if (Projectile.velocity.X < toPlayer.X)
+ {
+ Projectile.velocity.X += velChange;
+ if (Projectile.velocity.X < 0f)
+ Projectile.velocity.X += velChange * 1.5f;
+ }
+
+ if (Projectile.velocity.X > toPlayer.X)
+ {
+ Projectile.velocity.X -= velChange;
+ if (Projectile.velocity.X > 0f)
+ Projectile.velocity.X -= velChange * 1.5f;
+ }
+
+ if (Projectile.velocity.Y < toPlayer.Y)
+ {
+ Projectile.velocity.Y += velChange;
+ if (Projectile.velocity.Y < 0f)
+ Projectile.velocity.Y += velChange * 1.5f;
+ }
+
+ if (Projectile.velocity.Y > toPlayer.Y)
+ {
+ Projectile.velocity.Y -= velChange;
+ if (Projectile.velocity.Y > 0f)
+ Projectile.velocity.Y -= velChange * 1.5f;
+ }
+ }
+
+ if (Projectile.velocity.X != 0f)
+ Projectile.spriteDirection = -Math.Sign(Projectile.velocity.X);
+ }
+
+ if (Attacking && Timer < 0)
+ {
+ Projectile.friendly = false;
+ Timer += 1;
+ if (nextTimerValue >= 0)
+ {
+ Timer = 0;
+ Attacking = false;
+ Projectile.netUpdate = true;
+ return;
+ }
+ }
+ else if (Attacking)
+ {
+ //Attacking animation
+ Projectile.spriteDirection = -Projectile.direction;
+ Projectile.rotation = 0f;
+
+ Projectile.friendly = true;
+ int startAttackFrame = 12;
+ bool hasJumpingAttackFrames = true;
+ int attackFrameNumber = (int)((float)nextTimerValue - Timer) / (nextTimerValue / attackFrameCount);
+ Projectile.frame = startAttackFrame + attackFrameNumber;
+ if (hasJumpingAttackFrames && Projectile.velocity.Y != 0f)
+ Projectile.frame += attackFrameCount;
+
+ Projectile.velocity.Y += 0.4f;
+ if (Projectile.velocity.Y > 10f)
+ Projectile.velocity.Y = 10f;
+
+ Timer -= 1;
+ if (Timer <= 0f)
+ {
+ if (timerReset <= 0)
+ {
+ Timer = 0;
+ Attacking = false;
+ Projectile.netUpdate = true;
+ return;
+ }
+
+ Timer = -timerReset;
+ }
+ }
+
+ if (attackTarget >= 0)
+ {
+ float maxDistance = startAttackRange;
+ float toTargetMaxDist = 20f;
+
+ NPC npc = Main.npc[attackTarget];
+ Vector2 targetCenter = npc.Center;
+ destination = targetCenter;
+ if (Projectile.IsInRangeOfMeOrMyOwner(npc, maxDistance, out float _, out float _, out bool _))
+ {
+ Projectile.shouldFallThrough = npc.Center.Y > Projectile.Bottom.Y;
+
+ bool flag11 = Projectile.velocity.Y == 0f;
+ if (Projectile.wet && Projectile.velocity.Y > 0f && !Projectile.shouldFallThrough)
+ flag11 = true;
+
+ if (targetCenter.Y < Projectile.Center.Y - 30f && flag11)
+ {
+ float num25 = (targetCenter.Y - Projectile.Center.Y) * -1f;
+ float num26 = 0.4f;
+ float velY = (float)Math.Sqrt(num25 * 2f * num26);
+ if (velY > 26f)
+ velY = 26f;
+
+ Projectile.velocity.Y = -velY;
+ }
+
+ if (Vector2.Distance(Projectile.Center, destination) < toTargetMaxDist)
+ {
+ float len = Projectile.velocity.Length();
+ if (len > 10f)
+ Projectile.velocity /= len / 10f;
+
+ Attacking = true;
+ Timer = nextTimerValue;
+ Projectile.netUpdate = true;
+ Projectile.direction = (targetCenter.X - Projectile.Center.X > 0f).ToDirectionInt();
+ }
+ }
+ }
+
+ if (Idle && attackTarget < 0)
+ {
+ if (player.rocketDelay2 > 0)
+ {
+ Flying = true;
+ Projectile.netUpdate = true;
+ }
+
+ Vector2 toPlayer = player.Center - Projectile.Center;
+ if (toPlayer.Length() > 2000f)
+ {
+ Projectile.Center = player.Center;
+ }
+ else if (toPlayer.Length() > awayFromPlayerDistMax || Math.Abs(toPlayer.Y) > awayFromPlayerDistYMax)
+ {
+ Flying = true;
+ Projectile.netUpdate = true;
+ if (Projectile.velocity.Y > 0f && toPlayer.Y < 0f)
+ Projectile.velocity.Y = 0f;
+
+ if (Projectile.velocity.Y < 0f && toPlayer.Y > 0f)
+ Projectile.velocity.Y = 0f;
+ }
+ }
+
+ if (Idle)
+ {
+ if (attackTarget < 0)
+ {
+ if (Projectile.Distance(player.Center) > 60f && Projectile.Distance(destination) > 60f && Math.Sign(destination.X - player.Center.X) != Math.Sign(Projectile.Center.X - player.Center.X))
+ destination = player.Center;
+
+ Rectangle rect = Utils.CenteredRectangle(destination, Projectile.Size);
+ for (int i = 0; i < 20; i++)
+ {
+ if (Collision.SolidCollision(rect.TopLeft(), rect.Width, rect.Height))
+ break;
+
+ rect.Y += 16;
+ destination.Y += 16f;
+ }
+
+ Vector2 position = player.Center - Projectile.Size / 2f;
+ Vector2 postCollision = Collision.TileCollision(position, destination - player.Center, Projectile.width, Projectile.height);
+ destination = position + postCollision;
+ if (Projectile.Distance(destination) < 32f)
+ {
+ float distPlayerToDestination = player.Distance(destination);
+ if (player.Distance(Projectile.Center) < distPlayerToDestination)
+ destination = Projectile.Center;
+ }
+
+ Vector2 fromDestToPlayer = player.Center - destination;
+ if (fromDestToPlayer.Length() > awayFromPlayerDistMax || Math.Abs(fromDestToPlayer.Y) > awayFromPlayerDistYMax)
+ {
+ Rectangle rect2 = Utils.CenteredRectangle(player.Center, Projectile.Size);
+ Vector2 fromPlayerToDest = destination - player.Center;
+ Vector2 topLeft = rect2.TopLeft();
+ for (float i = 0f; i < 1f; i += 0.05f)
+ {
+ Vector2 newTopLeft = rect2.TopLeft() + fromPlayerToDest * i;
+ if (Collision.SolidCollision(rect2.TopLeft() + fromPlayerToDest * i, rect2.Width, rect2.Height))
+ break;
+
+ topLeft = newTopLeft;
+ }
+
+ destination = topLeft + Projectile.Size / 2f;
+ }
+ }
+
+ Projectile.tileCollide = true;
+ float velXChange = 0.5f; //0.5f
+ float velXChangeMargin = 4f; //4f
+ float velXChangeMax = 4f; //4f
+ float velXChangeSmall = 0.1f;
+
+ if (attackTarget != -1)
+ {
+ velXChange = 0.4f; //1f
+ velXChangeMargin = 5f; //8f
+ velXChangeMax = 5f; //8f
+ }
+
+ if (velXChangeMax < Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y))
+ {
+ velXChangeMax = Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y);
+ velXChange = 0.7f;
+ }
+
+ int xOff = 0;
+ bool canJumpOverTiles = false;
+ float toDestinationX = destination.X - Projectile.Center.X;
+ Vector2 toDestination = destination - Projectile.Center;
+ if (Math.Abs(toDestinationX) > 5f)
+ {
+ if (toDestinationX < 0f)
+ {
+ xOff = -1;
+ if (Projectile.velocity.X > -velXChangeMargin)
+ Projectile.velocity.X -= velXChange;
+ else
+ Projectile.velocity.X -= velXChangeSmall;
+ }
+ else
+ {
+ xOff = 1;
+ if (Projectile.velocity.X < velXChangeMargin)
+ Projectile.velocity.X += velXChange;
+ else
+ Projectile.velocity.X += velXChangeSmall;
+ }
+ }
+ else
+ {
+ Projectile.velocity.X *= 0.9f;
+ if (Math.Abs(Projectile.velocity.X) < velXChange * 2f)
+ Projectile.velocity.X = 0f;
+ }
+
+ bool tryJumping = Math.Abs(toDestination.X) >= 64f || (toDestination.Y <= -48f && Math.Abs(toDestination.X) >= 8f);
+ if (xOff != 0 && tryJumping)
+ {
+ int x = (int)Projectile.Center.X / 16;
+ int y = (int)Projectile.position.Y / 16;
+ x += xOff;
+ x += (int)Projectile.velocity.X;
+ for (int j = y; j < y + Projectile.height / 16 + 1; j++)
+ {
+ if (WorldGen.SolidTile(x, j))
+ canJumpOverTiles = true;
+ }
+ }
+
+ Collision.StepUp(ref Projectile.position, ref Projectile.velocity, Projectile.width, Projectile.height, ref Projectile.stepSpeed, ref Projectile.gfxOffY);
+ float nextVelocityY = Utils.GetLerpValue(0f, 100f, toDestination.Y, clamped: true) * Utils.GetLerpValue(-2f, -6f, Projectile.velocity.Y, clamped: true);
+ if (Projectile.velocity.Y == 0f && canJumpOverTiles)
+ {
+ for (int k = 0; k < 3; k++)
+ {
+ int num42 = (int)(Projectile.Center.X) / 16;
+ if (k == 0)
+ num42 = (int)Projectile.position.X / 16;
+
+ if (k == 2)
+ num42 = (int)(Projectile.Right.X) / 16;
+
+ int num43 = (int)(Projectile.Bottom.Y) / 16;
+ if (!WorldGen.SolidTile(num42, num43) && !Main.tile[num42, num43].IsHalfBlock && Main.tile[num42, num43].Slope <= 0 && (!TileID.Sets.Platforms[Main.tile[num42, num43].TileType] || !Main.tile[num42, num43].HasTile || Main.tile[num42, num43].IsActuated))
+ continue;
+
+ try
+ {
+ num42 = (int)(Projectile.Center.X) / 16;
+ num43 = (int)(Projectile.Center.Y) / 16;
+ num42 += xOff;
+ num42 += (int)Projectile.velocity.X;
+ if (!WorldGen.SolidTile(num42, num43 - 1) && !WorldGen.SolidTile(num42, num43 - 2))
+ Projectile.velocity.Y = -5.1f;
+ else if (!WorldGen.SolidTile(num42, num43 - 2))
+ Projectile.velocity.Y = -7.1f;
+ else if (WorldGen.SolidTile(num42, num43 - 5))
+ Projectile.velocity.Y = -11.1f;
+ else if (WorldGen.SolidTile(num42, num43 - 4))
+ Projectile.velocity.Y = -10.1f;
+ else
+ Projectile.velocity.Y = -9.1f;
+ }
+ catch
+ {
+ Projectile.velocity.Y = -9.1f;
+ }
+ }
+
+ if (destination.Y - Projectile.Center.Y < -48f)
+ {
+ float height = destination.Y - Projectile.Center.Y;
+ height *= -1f;
+ if (height < 60f)
+ Projectile.velocity.Y = -6f;
+ else if (height < 80f)
+ Projectile.velocity.Y = -7f;
+ else if (height < 100f)
+ Projectile.velocity.Y = -8f;
+ else if (height < 120f)
+ Projectile.velocity.Y = -9f;
+ else if (height < 140f)
+ Projectile.velocity.Y = -10f;
+ else if (height < 160f)
+ Projectile.velocity.Y = -11f;
+ else if (height < 190f)
+ Projectile.velocity.Y = -12f;
+ else if (height < 210f)
+ Projectile.velocity.Y = -13f;
+ else if (height < 270f)
+ Projectile.velocity.Y = -14f;
+ else if (height < 310f)
+ Projectile.velocity.Y = -15f;
+ else
+ Projectile.velocity.Y = -16f;
+ }
+
+ if (Projectile.wet && nextVelocityY == 0f)
+ Projectile.velocity.Y *= 2f;
+ }
+
+ if (Projectile.velocity.X > velXChangeMax)
+ Projectile.velocity.X = velXChangeMax;
+
+ if (Projectile.velocity.X < -velXChangeMax)
+ Projectile.velocity.X = -velXChangeMax;
+
+ if (Projectile.velocity.X < 0f)
+ Projectile.direction = -1;
+
+ if (Projectile.velocity.X > 0f)
+ Projectile.direction = 1;
+
+ if (Projectile.velocity.X == 0f)
+ Projectile.direction = (player.Center.X > Projectile.Center.X).ToDirectionInt();
+
+ if (Projectile.velocity.X > velXChange && xOff == 1)
+ Projectile.direction = 1;
+
+ if (Projectile.velocity.X < -velXChange && xOff == -1)
+ Projectile.direction = -1;
+
+ Projectile.spriteDirection = -Projectile.direction;
+
+ Projectile.velocity.Y += 0.4f + nextVelocityY * 1f;
+ if (Projectile.velocity.Y > 10f)
+ {
+ Projectile.velocity.Y = 10f;
+ }
+ }
+
+ #region default animations
+ /*
if (Flying)
{
//Flying animation
@@ -1848,477 +1848,477 @@ public static void PirateAI(Projectile Projectile)
}
}
*/
- #endregion
- }
-
- //TODO turn into usable method later
- public static void VampFrogAI(Projectile Projectile)
- {
- // //VampFrog AI related:
- //public int State
- //{
- // get => (int)Projectile.ai[0];
- // set => Projectile.ai[0] = value;
- //}
-
- //public int Timer
- //{
- // get => (int)Projectile.ai[1];
- // set => Projectile.ai[1] = value;
- //}
-
- //public bool Idle => State == 0;
-
- //public bool Flying
- //{
- // get => State == 1;
- // set => State = value ? 1 : 0;
- //}
-
- //public bool Attacking
- //{
- // get => State == 2;
- // set => State = value ? 2 : 0;
- //}
- int Timer = 0;
- bool Idle = true;
- bool Flying = false;
- bool Attacking = false;
- ////End VampFrog AI
-
- Player player = Main.player[Projectile.owner];
-
- int startAttackRange = 800;
- float awayFromPlayerDistMax = 500f;
- float awayFromPlayerDistYMax = 300f;
-
- Vector2 destination = player.Center;
- destination.X -= (35 + player.width / 2) * player.direction;
- destination.X -= Projectile.minionPos * 40 * player.direction;
-
- Projectile.shouldFallThrough = player.Bottom.Y - 12f > Projectile.Bottom.Y;
- Projectile.friendly = false;
- int timerReset = 0;
- int attackFrameCount = 4;
- int nextTimerValue = 5 * attackFrameCount;
- int attackTarget = -1;
-
- Projectile.friendly = true;
- timerReset = 60;
-
- bool defaultstate = Idle;
-
- static bool CustomEliminationCheck_Pirates(Entity otherEntity, int currentTarget) => true;
-
- if (defaultstate)
- Projectile.Minion_FindTargetInRange(startAttackRange, ref attackTarget, skipIfCannotHitWithOwnBody: true, CustomEliminationCheck_Pirates);
-
- if (Flying)
- {
- Projectile.tileCollide = false;
- float velChange = 0.2f;
- float toPlayerSpeed = 10f;
- int maxLen = 200;
- if (toPlayerSpeed < Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y))
- toPlayerSpeed = Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y);
-
- Vector2 toPlayer = player.Center - Projectile.Center;
- float len = toPlayer.Length();
-
- AssAI.TeleportIfTooFar(Projectile, player.Center);
-
- if (len < maxLen && player.velocity.Y == 0f && Projectile.Bottom.Y <= player.Bottom.Y && !Collision.SolidCollision(Projectile.position, Projectile.width, Projectile.height))
- {
- //Reset back from flying
- Flying = false;
- Projectile.netUpdate = true;
- if (Projectile.velocity.Y < -6f)
- Projectile.velocity.Y = -6f;
- }
-
- if (!(len < 60f))
- {
- toPlayer.Normalize();
- toPlayer *= toPlayerSpeed;
- if (Projectile.velocity.X < toPlayer.X)
- {
- Projectile.velocity.X += velChange;
- if (Projectile.velocity.X < 0f)
- Projectile.velocity.X += velChange * 1.5f;
- }
-
- if (Projectile.velocity.X > toPlayer.X)
- {
- Projectile.velocity.X -= velChange;
- if (Projectile.velocity.X > 0f)
- Projectile.velocity.X -= velChange * 1.5f;
- }
-
- if (Projectile.velocity.Y < toPlayer.Y)
- {
- Projectile.velocity.Y += velChange;
- if (Projectile.velocity.Y < 0f)
- Projectile.velocity.Y += velChange * 1.5f;
- }
-
- if (Projectile.velocity.Y > toPlayer.Y)
- {
- Projectile.velocity.Y -= velChange;
- if (Projectile.velocity.Y > 0f)
- Projectile.velocity.Y -= velChange * 1.5f;
- }
- }
-
- if (Projectile.velocity.X != 0f)
- Projectile.spriteDirection = -Math.Sign(Projectile.velocity.X);
- }
-
- if (Attacking && Timer < 0)
- {
- Projectile.friendly = false;
- Timer += 1;
- if (nextTimerValue >= 0)
- {
- Timer = 0;
- Attacking = false;
- Projectile.netUpdate = true;
- return;
- }
- }
- else if (Attacking)
- {
- //Attacking animation
- Projectile.spriteDirection = -Projectile.direction;
- Projectile.rotation = 0f;
-
- float num22 = ((float)nextTimerValue - Timer) / (float)nextTimerValue;
- if ((double)num22 > 0.25 && (double)num22 < 0.75)
- Projectile.friendly = true;
-
- int num23 = (int)(num22 * 5f);
- if (num23 > 2)
- num23 = 4 - num23;
-
- if (Projectile.velocity.Y != 0f)
- Projectile.frame = 21 + num23;
- else
- Projectile.frame = 18 + num23;
-
- if (Projectile.velocity.Y == 0f)
- Projectile.velocity.X *= 0.8f;
-
- Projectile.velocity.Y += 0.4f;
- if (Projectile.velocity.Y > 10f)
- Projectile.velocity.Y = 10f;
-
- Timer -= 1;
- if (Timer <= 0f)
- {
- if (timerReset <= 0)
- {
- Timer = 0;
- Attacking = false;
- Projectile.netUpdate = true;
- return;
- }
-
- Timer = -timerReset;
- }
- }
-
- if (attackTarget >= 0)
- {
- float maxDistance = startAttackRange;
- float toTargetMaxDist = 50f;
-
- NPC npc = Main.npc[attackTarget];
- Vector2 targetCenter = npc.Center;
- destination = targetCenter;
- if (Projectile.IsInRangeOfMeOrMyOwner(npc, maxDistance, out float _, out float _, out bool _))
- {
- Projectile.shouldFallThrough = npc.Center.Y > Projectile.Bottom.Y;
-
- bool flag11 = Projectile.velocity.Y == 0f;
- if (Projectile.wet && Projectile.velocity.Y > 0f && !Projectile.shouldFallThrough)
- flag11 = true;
-
- if (targetCenter.Y < Projectile.Center.Y - 30f && flag11)
- {
- float num25 = (targetCenter.Y - Projectile.Center.Y) * -1f;
- float num26 = 0.4f;
- float velY = (float)Math.Sqrt(num25 * 2f * num26);
- if (velY > 26f)
- velY = 26f;
-
- Projectile.velocity.Y = -velY;
- }
-
- if (Vector2.Distance(Projectile.Center, destination) < toTargetMaxDist)
- {
- float len = Projectile.velocity.Length();
- if (len > 10f)
- Projectile.velocity /= len / 10f;
-
- Attacking = true;
- Timer = nextTimerValue;
- Projectile.netUpdate = true;
- Projectile.direction = (targetCenter.X - Projectile.Center.X > 0f).ToDirectionInt();
- }
- }
-
- int dir = 1;
- if (targetCenter.X - Projectile.Center.X < 0f)
- dir = -1;
-
- destination.X += 20 * -dir;
- }
-
- if (Idle && attackTarget < 0)
- {
- if (player.rocketDelay2 > 0)
- {
- Flying = true;
- Projectile.netUpdate = true;
- }
-
- Vector2 toPlayer = player.Center - Projectile.Center;
- if (toPlayer.Length() > 2000f)
- {
- Projectile.Center = player.Center;
- }
- else if (toPlayer.Length() > awayFromPlayerDistMax || Math.Abs(toPlayer.Y) > awayFromPlayerDistYMax)
- {
- Flying = true;
- Projectile.netUpdate = true;
- if (Projectile.velocity.Y > 0f && toPlayer.Y < 0f)
- Projectile.velocity.Y = 0f;
-
- if (Projectile.velocity.Y < 0f && toPlayer.Y > 0f)
- Projectile.velocity.Y = 0f;
- }
- }
-
- if (Idle)
- {
- if (attackTarget < 0)
- {
- if (Projectile.Distance(player.Center) > 60f && Projectile.Distance(destination) > 60f && Math.Sign(destination.X - player.Center.X) != Math.Sign(Projectile.Center.X - player.Center.X))
- destination = player.Center;
-
- Rectangle rect = Utils.CenteredRectangle(destination, Projectile.Size);
- for (int i = 0; i < 20; i++)
- {
- if (Collision.SolidCollision(rect.TopLeft(), rect.Width, rect.Height))
- break;
-
- rect.Y += 16;
- destination.Y += 16f;
- }
-
- Vector2 position = player.Center - Projectile.Size / 2f;
- Vector2 postCollision = Collision.TileCollision(position, destination - player.Center, Projectile.width, Projectile.height);
- destination = position + postCollision;
- if (Projectile.Distance(destination) < 32f)
- {
- float distPlayerToDestination = player.Distance(destination);
- if (player.Distance(Projectile.Center) < distPlayerToDestination)
- destination = Projectile.Center;
- }
-
- Vector2 fromDestToPlayer = player.Center - destination;
- if (fromDestToPlayer.Length() > awayFromPlayerDistMax || Math.Abs(fromDestToPlayer.Y) > awayFromPlayerDistYMax)
- {
- Rectangle rect2 = Utils.CenteredRectangle(player.Center, Projectile.Size);
- Vector2 fromPlayerToDest = destination - player.Center;
- Vector2 topLeft = rect2.TopLeft();
- for (float i = 0f; i < 1f; i += 0.05f)
- {
- Vector2 newTopLeft = rect2.TopLeft() + fromPlayerToDest * i;
- if (Collision.SolidCollision(rect2.TopLeft() + fromPlayerToDest * i, rect2.Width, rect2.Height))
- break;
-
- topLeft = newTopLeft;
- }
-
- destination = topLeft + Projectile.Size / 2f;
- }
- }
-
- Projectile.tileCollide = true;
- float velXChange = 0.5f; //0.5f
- float velXChangeMargin = 4f; //4f
- float velXChangeMax = 4f; //4f
- float velXChangeSmall = 0.1f;
-
- if (attackTarget != -1)
- {
- velXChange = 0.7f;
- velXChangeMargin = 6f;
- velXChangeMax = 6f;
- }
-
- if (velXChangeMax < Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y))
- {
- velXChangeMax = Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y);
- velXChange = 0.7f;
- }
-
- int xOff = 0;
- bool canJumpOverTiles = false;
- float toDestinationX = destination.X - Projectile.Center.X;
- Vector2 toDestination = destination - Projectile.Center;
- if (Math.Abs(toDestinationX) > 5f)
- {
- if (toDestinationX < 0f)
- {
- xOff = -1;
- if (Projectile.velocity.X > -velXChangeMargin)
- Projectile.velocity.X -= velXChange;
- else
- Projectile.velocity.X -= velXChangeSmall;
- }
- else
- {
- xOff = 1;
- if (Projectile.velocity.X < velXChangeMargin)
- Projectile.velocity.X += velXChange;
- else
- Projectile.velocity.X += velXChangeSmall;
- }
-
- bool shouldJumpOverTiles = true;
-
- if (attackTarget == -1)
- shouldJumpOverTiles = false;
-
- if (shouldJumpOverTiles)
- canJumpOverTiles = true;
- }
- else
- {
- Projectile.velocity.X *= 0.9f;
- if (Math.Abs(Projectile.velocity.X) < velXChange * 2f)
- Projectile.velocity.X = 0f;
- }
-
- bool tryJumping = Math.Abs(toDestination.X) >= 64f || (toDestination.Y <= -48f && Math.Abs(toDestination.X) >= 8f);
- if (xOff != 0 && tryJumping)
- {
- int x = (int)Projectile.Center.X / 16;
- int y = (int)Projectile.position.Y / 16;
- x += xOff;
- x += (int)Projectile.velocity.X;
- for (int j = y; j < y + Projectile.height / 16 + 1; j++)
- {
- if (WorldGen.SolidTile(x, j))
- canJumpOverTiles = true;
- }
- }
-
- Collision.StepUp(ref Projectile.position, ref Projectile.velocity, Projectile.width, Projectile.height, ref Projectile.stepSpeed, ref Projectile.gfxOffY);
- float nextVelocityY = Utils.GetLerpValue(0f, 100f, toDestination.Y, clamped: true) * Utils.GetLerpValue(-2f, -6f, Projectile.velocity.Y, clamped: true);
- if (Projectile.velocity.Y == 0f && canJumpOverTiles)
- {
- for (int k = 0; k < 3; k++)
- {
- int num42 = (int)(Projectile.Center.X) / 16;
- if (k == 0)
- num42 = (int)Projectile.position.X / 16;
-
- if (k == 2)
- num42 = (int)(Projectile.Right.X) / 16;
-
- int num43 = (int)(Projectile.Bottom.Y) / 16;
- if (!WorldGen.SolidTile(num42, num43) && !Main.tile[num42, num43].IsHalfBlock && Main.tile[num42, num43].Slope <= 0 && (!TileID.Sets.Platforms[Main.tile[num42, num43].TileType] || !Main.tile[num42, num43].HasTile || Main.tile[num42, num43].IsActuated))
- continue;
-
- try
- {
- num42 = (int)(Projectile.Center.X) / 16;
- num43 = (int)(Projectile.Center.Y) / 16;
- num42 += xOff;
- num42 += (int)Projectile.velocity.X;
- if (!WorldGen.SolidTile(num42, num43 - 1) && !WorldGen.SolidTile(num42, num43 - 2))
- Projectile.velocity.Y = -5.1f;
- else if (!WorldGen.SolidTile(num42, num43 - 2))
- Projectile.velocity.Y = -7.1f;
- else if (WorldGen.SolidTile(num42, num43 - 5))
- Projectile.velocity.Y = -11.1f;
- else if (WorldGen.SolidTile(num42, num43 - 4))
- Projectile.velocity.Y = -10.1f;
- else
- Projectile.velocity.Y = -9.1f;
- }
- catch
- {
- Projectile.velocity.Y = -9.1f;
- }
- }
-
- if (destination.Y - Projectile.Center.Y < -48f)
- {
- float height = destination.Y - Projectile.Center.Y;
- height *= -1f;
- if (height < 60f)
- Projectile.velocity.Y = -6f;
- else if (height < 80f)
- Projectile.velocity.Y = -7f;
- else if (height < 100f)
- Projectile.velocity.Y = -8f;
- else if (height < 120f)
- Projectile.velocity.Y = -9f;
- else if (height < 140f)
- Projectile.velocity.Y = -10f;
- else if (height < 160f)
- Projectile.velocity.Y = -11f;
- else if (height < 190f)
- Projectile.velocity.Y = -12f;
- else if (height < 210f)
- Projectile.velocity.Y = -13f;
- else if (height < 270f)
- Projectile.velocity.Y = -14f;
- else if (height < 310f)
- Projectile.velocity.Y = -15f;
- else
- Projectile.velocity.Y = -16f;
- }
-
- if (Projectile.wet && nextVelocityY == 0f)
- Projectile.velocity.Y *= 2f;
- }
-
- if (Projectile.velocity.X > velXChangeMax)
- Projectile.velocity.X = velXChangeMax;
-
- if (Projectile.velocity.X < -velXChangeMax)
- Projectile.velocity.X = -velXChangeMax;
-
- if (Projectile.velocity.X < 0f)
- Projectile.direction = -1;
-
- if (Projectile.velocity.X > 0f)
- Projectile.direction = 1;
-
- if (Projectile.velocity.X == 0f)
- Projectile.direction = (player.Center.X > Projectile.Center.X).ToDirectionInt();
-
- if (Projectile.velocity.X > velXChange && xOff == 1)
- Projectile.direction = 1;
-
- if (Projectile.velocity.X < -velXChange && xOff == -1)
- Projectile.direction = -1;
-
- Projectile.spriteDirection = -Projectile.direction;
-
- Projectile.velocity.Y += 0.4f + nextVelocityY * 1f;
- if (Projectile.velocity.Y > 10f)
- {
- Projectile.velocity.Y = 10f;
- }
- }
-
- #region default animations
- /*
+ #endregion
+ }
+
+ //TODO turn into usable method later
+ public static void VampFrogAI(Projectile Projectile)
+ {
+ // //VampFrog AI related:
+ //public int State
+ //{
+ // get => (int)Projectile.ai[0];
+ // set => Projectile.ai[0] = value;
+ //}
+
+ //public int Timer
+ //{
+ // get => (int)Projectile.ai[1];
+ // set => Projectile.ai[1] = value;
+ //}
+
+ //public bool Idle => State == 0;
+
+ //public bool Flying
+ //{
+ // get => State == 1;
+ // set => State = value ? 1 : 0;
+ //}
+
+ //public bool Attacking
+ //{
+ // get => State == 2;
+ // set => State = value ? 2 : 0;
+ //}
+ int Timer = 0;
+ bool Idle = true;
+ bool Flying = false;
+ bool Attacking = false;
+ ////End VampFrog AI
+
+ Player player = Main.player[Projectile.owner];
+
+ int startAttackRange = 800;
+ float awayFromPlayerDistMax = 500f;
+ float awayFromPlayerDistYMax = 300f;
+
+ Vector2 destination = player.Center;
+ destination.X -= (35 + player.width / 2) * player.direction;
+ destination.X -= Projectile.minionPos * 40 * player.direction;
+
+ Projectile.shouldFallThrough = player.Bottom.Y - 12f > Projectile.Bottom.Y;
+ Projectile.friendly = false;
+ int timerReset = 0;
+ int attackFrameCount = 4;
+ int nextTimerValue = 5 * attackFrameCount;
+ int attackTarget = -1;
+
+ Projectile.friendly = true;
+ timerReset = 60;
+
+ bool defaultstate = Idle;
+
+ static bool CustomEliminationCheck_Pirates(Entity otherEntity, int currentTarget) => true;
+
+ if (defaultstate)
+ Projectile.Minion_FindTargetInRange(startAttackRange, ref attackTarget, skipIfCannotHitWithOwnBody: true, CustomEliminationCheck_Pirates);
+
+ if (Flying)
+ {
+ Projectile.tileCollide = false;
+ float velChange = 0.2f;
+ float toPlayerSpeed = 10f;
+ int maxLen = 200;
+ if (toPlayerSpeed < Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y))
+ toPlayerSpeed = Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y);
+
+ Vector2 toPlayer = player.Center - Projectile.Center;
+ float len = toPlayer.Length();
+
+ AssAI.TeleportIfTooFar(Projectile, player.Center);
+
+ if (len < maxLen && player.velocity.Y == 0f && Projectile.Bottom.Y <= player.Bottom.Y && !Collision.SolidCollision(Projectile.position, Projectile.width, Projectile.height))
+ {
+ //Reset back from flying
+ Flying = false;
+ Projectile.netUpdate = true;
+ if (Projectile.velocity.Y < -6f)
+ Projectile.velocity.Y = -6f;
+ }
+
+ if (!(len < 60f))
+ {
+ toPlayer.Normalize();
+ toPlayer *= toPlayerSpeed;
+ if (Projectile.velocity.X < toPlayer.X)
+ {
+ Projectile.velocity.X += velChange;
+ if (Projectile.velocity.X < 0f)
+ Projectile.velocity.X += velChange * 1.5f;
+ }
+
+ if (Projectile.velocity.X > toPlayer.X)
+ {
+ Projectile.velocity.X -= velChange;
+ if (Projectile.velocity.X > 0f)
+ Projectile.velocity.X -= velChange * 1.5f;
+ }
+
+ if (Projectile.velocity.Y < toPlayer.Y)
+ {
+ Projectile.velocity.Y += velChange;
+ if (Projectile.velocity.Y < 0f)
+ Projectile.velocity.Y += velChange * 1.5f;
+ }
+
+ if (Projectile.velocity.Y > toPlayer.Y)
+ {
+ Projectile.velocity.Y -= velChange;
+ if (Projectile.velocity.Y > 0f)
+ Projectile.velocity.Y -= velChange * 1.5f;
+ }
+ }
+
+ if (Projectile.velocity.X != 0f)
+ Projectile.spriteDirection = -Math.Sign(Projectile.velocity.X);
+ }
+
+ if (Attacking && Timer < 0)
+ {
+ Projectile.friendly = false;
+ Timer += 1;
+ if (nextTimerValue >= 0)
+ {
+ Timer = 0;
+ Attacking = false;
+ Projectile.netUpdate = true;
+ return;
+ }
+ }
+ else if (Attacking)
+ {
+ //Attacking animation
+ Projectile.spriteDirection = -Projectile.direction;
+ Projectile.rotation = 0f;
+
+ float num22 = ((float)nextTimerValue - Timer) / (float)nextTimerValue;
+ if ((double)num22 > 0.25 && (double)num22 < 0.75)
+ Projectile.friendly = true;
+
+ int num23 = (int)(num22 * 5f);
+ if (num23 > 2)
+ num23 = 4 - num23;
+
+ if (Projectile.velocity.Y != 0f)
+ Projectile.frame = 21 + num23;
+ else
+ Projectile.frame = 18 + num23;
+
+ if (Projectile.velocity.Y == 0f)
+ Projectile.velocity.X *= 0.8f;
+
+ Projectile.velocity.Y += 0.4f;
+ if (Projectile.velocity.Y > 10f)
+ Projectile.velocity.Y = 10f;
+
+ Timer -= 1;
+ if (Timer <= 0f)
+ {
+ if (timerReset <= 0)
+ {
+ Timer = 0;
+ Attacking = false;
+ Projectile.netUpdate = true;
+ return;
+ }
+
+ Timer = -timerReset;
+ }
+ }
+
+ if (attackTarget >= 0)
+ {
+ float maxDistance = startAttackRange;
+ float toTargetMaxDist = 50f;
+
+ NPC npc = Main.npc[attackTarget];
+ Vector2 targetCenter = npc.Center;
+ destination = targetCenter;
+ if (Projectile.IsInRangeOfMeOrMyOwner(npc, maxDistance, out float _, out float _, out bool _))
+ {
+ Projectile.shouldFallThrough = npc.Center.Y > Projectile.Bottom.Y;
+
+ bool flag11 = Projectile.velocity.Y == 0f;
+ if (Projectile.wet && Projectile.velocity.Y > 0f && !Projectile.shouldFallThrough)
+ flag11 = true;
+
+ if (targetCenter.Y < Projectile.Center.Y - 30f && flag11)
+ {
+ float num25 = (targetCenter.Y - Projectile.Center.Y) * -1f;
+ float num26 = 0.4f;
+ float velY = (float)Math.Sqrt(num25 * 2f * num26);
+ if (velY > 26f)
+ velY = 26f;
+
+ Projectile.velocity.Y = -velY;
+ }
+
+ if (Vector2.Distance(Projectile.Center, destination) < toTargetMaxDist)
+ {
+ float len = Projectile.velocity.Length();
+ if (len > 10f)
+ Projectile.velocity /= len / 10f;
+
+ Attacking = true;
+ Timer = nextTimerValue;
+ Projectile.netUpdate = true;
+ Projectile.direction = (targetCenter.X - Projectile.Center.X > 0f).ToDirectionInt();
+ }
+ }
+
+ int dir = 1;
+ if (targetCenter.X - Projectile.Center.X < 0f)
+ dir = -1;
+
+ destination.X += 20 * -dir;
+ }
+
+ if (Idle && attackTarget < 0)
+ {
+ if (player.rocketDelay2 > 0)
+ {
+ Flying = true;
+ Projectile.netUpdate = true;
+ }
+
+ Vector2 toPlayer = player.Center - Projectile.Center;
+ if (toPlayer.Length() > 2000f)
+ {
+ Projectile.Center = player.Center;
+ }
+ else if (toPlayer.Length() > awayFromPlayerDistMax || Math.Abs(toPlayer.Y) > awayFromPlayerDistYMax)
+ {
+ Flying = true;
+ Projectile.netUpdate = true;
+ if (Projectile.velocity.Y > 0f && toPlayer.Y < 0f)
+ Projectile.velocity.Y = 0f;
+
+ if (Projectile.velocity.Y < 0f && toPlayer.Y > 0f)
+ Projectile.velocity.Y = 0f;
+ }
+ }
+
+ if (Idle)
+ {
+ if (attackTarget < 0)
+ {
+ if (Projectile.Distance(player.Center) > 60f && Projectile.Distance(destination) > 60f && Math.Sign(destination.X - player.Center.X) != Math.Sign(Projectile.Center.X - player.Center.X))
+ destination = player.Center;
+
+ Rectangle rect = Utils.CenteredRectangle(destination, Projectile.Size);
+ for (int i = 0; i < 20; i++)
+ {
+ if (Collision.SolidCollision(rect.TopLeft(), rect.Width, rect.Height))
+ break;
+
+ rect.Y += 16;
+ destination.Y += 16f;
+ }
+
+ Vector2 position = player.Center - Projectile.Size / 2f;
+ Vector2 postCollision = Collision.TileCollision(position, destination - player.Center, Projectile.width, Projectile.height);
+ destination = position + postCollision;
+ if (Projectile.Distance(destination) < 32f)
+ {
+ float distPlayerToDestination = player.Distance(destination);
+ if (player.Distance(Projectile.Center) < distPlayerToDestination)
+ destination = Projectile.Center;
+ }
+
+ Vector2 fromDestToPlayer = player.Center - destination;
+ if (fromDestToPlayer.Length() > awayFromPlayerDistMax || Math.Abs(fromDestToPlayer.Y) > awayFromPlayerDistYMax)
+ {
+ Rectangle rect2 = Utils.CenteredRectangle(player.Center, Projectile.Size);
+ Vector2 fromPlayerToDest = destination - player.Center;
+ Vector2 topLeft = rect2.TopLeft();
+ for (float i = 0f; i < 1f; i += 0.05f)
+ {
+ Vector2 newTopLeft = rect2.TopLeft() + fromPlayerToDest * i;
+ if (Collision.SolidCollision(rect2.TopLeft() + fromPlayerToDest * i, rect2.Width, rect2.Height))
+ break;
+
+ topLeft = newTopLeft;
+ }
+
+ destination = topLeft + Projectile.Size / 2f;
+ }
+ }
+
+ Projectile.tileCollide = true;
+ float velXChange = 0.5f; //0.5f
+ float velXChangeMargin = 4f; //4f
+ float velXChangeMax = 4f; //4f
+ float velXChangeSmall = 0.1f;
+
+ if (attackTarget != -1)
+ {
+ velXChange = 0.7f;
+ velXChangeMargin = 6f;
+ velXChangeMax = 6f;
+ }
+
+ if (velXChangeMax < Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y))
+ {
+ velXChangeMax = Math.Abs(player.velocity.X) + Math.Abs(player.velocity.Y);
+ velXChange = 0.7f;
+ }
+
+ int xOff = 0;
+ bool canJumpOverTiles = false;
+ float toDestinationX = destination.X - Projectile.Center.X;
+ Vector2 toDestination = destination - Projectile.Center;
+ if (Math.Abs(toDestinationX) > 5f)
+ {
+ if (toDestinationX < 0f)
+ {
+ xOff = -1;
+ if (Projectile.velocity.X > -velXChangeMargin)
+ Projectile.velocity.X -= velXChange;
+ else
+ Projectile.velocity.X -= velXChangeSmall;
+ }
+ else
+ {
+ xOff = 1;
+ if (Projectile.velocity.X < velXChangeMargin)
+ Projectile.velocity.X += velXChange;
+ else
+ Projectile.velocity.X += velXChangeSmall;
+ }
+
+ bool shouldJumpOverTiles = true;
+
+ if (attackTarget == -1)
+ shouldJumpOverTiles = false;
+
+ if (shouldJumpOverTiles)
+ canJumpOverTiles = true;
+ }
+ else
+ {
+ Projectile.velocity.X *= 0.9f;
+ if (Math.Abs(Projectile.velocity.X) < velXChange * 2f)
+ Projectile.velocity.X = 0f;
+ }
+
+ bool tryJumping = Math.Abs(toDestination.X) >= 64f || (toDestination.Y <= -48f && Math.Abs(toDestination.X) >= 8f);
+ if (xOff != 0 && tryJumping)
+ {
+ int x = (int)Projectile.Center.X / 16;
+ int y = (int)Projectile.position.Y / 16;
+ x += xOff;
+ x += (int)Projectile.velocity.X;
+ for (int j = y; j < y + Projectile.height / 16 + 1; j++)
+ {
+ if (WorldGen.SolidTile(x, j))
+ canJumpOverTiles = true;
+ }
+ }
+
+ Collision.StepUp(ref Projectile.position, ref Projectile.velocity, Projectile.width, Projectile.height, ref Projectile.stepSpeed, ref Projectile.gfxOffY);
+ float nextVelocityY = Utils.GetLerpValue(0f, 100f, toDestination.Y, clamped: true) * Utils.GetLerpValue(-2f, -6f, Projectile.velocity.Y, clamped: true);
+ if (Projectile.velocity.Y == 0f && canJumpOverTiles)
+ {
+ for (int k = 0; k < 3; k++)
+ {
+ int num42 = (int)(Projectile.Center.X) / 16;
+ if (k == 0)
+ num42 = (int)Projectile.position.X / 16;
+
+ if (k == 2)
+ num42 = (int)(Projectile.Right.X) / 16;
+
+ int num43 = (int)(Projectile.Bottom.Y) / 16;
+ if (!WorldGen.SolidTile(num42, num43) && !Main.tile[num42, num43].IsHalfBlock && Main.tile[num42, num43].Slope <= 0 && (!TileID.Sets.Platforms[Main.tile[num42, num43].TileType] || !Main.tile[num42, num43].HasTile || Main.tile[num42, num43].IsActuated))
+ continue;
+
+ try
+ {
+ num42 = (int)(Projectile.Center.X) / 16;
+ num43 = (int)(Projectile.Center.Y) / 16;
+ num42 += xOff;
+ num42 += (int)Projectile.velocity.X;
+ if (!WorldGen.SolidTile(num42, num43 - 1) && !WorldGen.SolidTile(num42, num43 - 2))
+ Projectile.velocity.Y = -5.1f;
+ else if (!WorldGen.SolidTile(num42, num43 - 2))
+ Projectile.velocity.Y = -7.1f;
+ else if (WorldGen.SolidTile(num42, num43 - 5))
+ Projectile.velocity.Y = -11.1f;
+ else if (WorldGen.SolidTile(num42, num43 - 4))
+ Projectile.velocity.Y = -10.1f;
+ else
+ Projectile.velocity.Y = -9.1f;
+ }
+ catch
+ {
+ Projectile.velocity.Y = -9.1f;
+ }
+ }
+
+ if (destination.Y - Projectile.Center.Y < -48f)
+ {
+ float height = destination.Y - Projectile.Center.Y;
+ height *= -1f;
+ if (height < 60f)
+ Projectile.velocity.Y = -6f;
+ else if (height < 80f)
+ Projectile.velocity.Y = -7f;
+ else if (height < 100f)
+ Projectile.velocity.Y = -8f;
+ else if (height < 120f)
+ Projectile.velocity.Y = -9f;
+ else if (height < 140f)
+ Projectile.velocity.Y = -10f;
+ else if (height < 160f)
+ Projectile.velocity.Y = -11f;
+ else if (height < 190f)
+ Projectile.velocity.Y = -12f;
+ else if (height < 210f)
+ Projectile.velocity.Y = -13f;
+ else if (height < 270f)
+ Projectile.velocity.Y = -14f;
+ else if (height < 310f)
+ Projectile.velocity.Y = -15f;
+ else
+ Projectile.velocity.Y = -16f;
+ }
+
+ if (Projectile.wet && nextVelocityY == 0f)
+ Projectile.velocity.Y *= 2f;
+ }
+
+ if (Projectile.velocity.X > velXChangeMax)
+ Projectile.velocity.X = velXChangeMax;
+
+ if (Projectile.velocity.X < -velXChangeMax)
+ Projectile.velocity.X = -velXChangeMax;
+
+ if (Projectile.velocity.X < 0f)
+ Projectile.direction = -1;
+
+ if (Projectile.velocity.X > 0f)
+ Projectile.direction = 1;
+
+ if (Projectile.velocity.X == 0f)
+ Projectile.direction = (player.Center.X > Projectile.Center.X).ToDirectionInt();
+
+ if (Projectile.velocity.X > velXChange && xOff == 1)
+ Projectile.direction = 1;
+
+ if (Projectile.velocity.X < -velXChange && xOff == -1)
+ Projectile.direction = -1;
+
+ Projectile.spriteDirection = -Projectile.direction;
+
+ Projectile.velocity.Y += 0.4f + nextVelocityY * 1f;
+ if (Projectile.velocity.Y > 10f)
+ {
+ Projectile.velocity.Y = 10f;
+ }
+ }
+
+ #region default animations
+ /*
if (Flying)
{
//Flying animation
@@ -2400,16 +2400,16 @@ public static void VampFrogAI(Projectile Projectile)
}
}
*/
- #endregion
- }
- }
-
- public enum WormType : byte
- {
- None = 0,
- Head = 1,
- Body1 = 2,
- Body2 = 3,
- Tail = 4
- }
+ #endregion
+ }
+ }
+
+ public enum WormType : byte
+ {
+ None = 0,
+ Head = 1,
+ Body1 = 2,
+ Body2 = 3,
+ Tail = 4
+ }
}
diff --git a/Base/AssExtensions.cs b/Base/AssExtensions.cs
index dc395e7f..feab309f 100644
--- a/Base/AssExtensions.cs
+++ b/Base/AssExtensions.cs
@@ -3,211 +3,211 @@
namespace AssortedCrazyThings.Base
{
- ///
- /// contains Extensions for some basic tasks
- ///
- public static class AssExtensions
- {
- ///
- /// Returns the average value between the RGB (ignoring A)
- ///
- public static float GetAverage(this Color color)
- {
- return (color.R + color.G + color.B) / 3f;
- }
-
- ///
- /// Returns the Player that owns the given projectile. Only use if you are certain an owner exists and it is a player
- ///
- public static Player GetOwner(this Projectile proj)
- {
- return Main.player[proj.owner];
- }
-
- ///
- /// Copy of vanilla code for spawning a single pet and setting buffTime. Gives random velocity at spawn
- ///
- ///
- ///
- ///
- ///
- ///
- public static void AssSpawnPetIfNeededAndSetTime(this Player player, int buffIndex, ref bool petBool, int petProjID, int buffTimeToGive = 18000)
- {
- player.buffTime[buffIndex] = buffTimeToGive;
- player.AssSpawnPetIfNeeded(ref petBool, petProjID, buffIndex);
- }
-
- ///
- /// Player.HasItem + checks all banks
- ///
- ///
- ///
- ///
- public static bool HasItemWithBanks(this Player player, int type)
- {
- if (player.HasItem(type)) return true;
-
- Item[][] inventoryArray = { player.bank.item, player.bank2.item, player.bank3.item, player.bank4.item };
- for (int i = 0; i < inventoryArray.Length; i++)
- {
- Item[] inventory = inventoryArray[i];
- for (int j = 0; j < inventory.Length; j++)
- {
- Item item = inventory[j];
- if (type == item.type && item.stack > 0) return true;
- }
- }
-
- return false;
- }
-
- ///
- /// Checks if given item is present in the players inventory or equip slots
- ///
- public static bool ItemInInventoryOrEquipped(this Player player, Item item, bool ignoreVanity = false)
- {
- if (player.HasItem(item.type)) return true;
- if (item.accessory || item.headSlot > 0 || item.bodySlot > 0 || item.legSlot > 0)
- {
- int maxLength = ignoreVanity ? 10 : player.armor.Length;
- for (int i = 0; i < maxLength; i++)
- {
- if (player.armor[i].type == item.type) return true;
- }
- }
- return false;
- }
-
- ///
- /// Copy of vanilla code for spawning a single pet. Gives random velocity at spawn
- ///
- ///
- ///
- ///
- ///
- public static void AssSpawnPetIfNeeded(this Player player, ref bool petBool, int petProjID, int buffIndex)
- {
- petBool = true;
- if (player.ownedProjectileCounts[petProjID] > 0)
- {
- return;
- }
-
- if (player.whoAmI == Main.myPlayer)
- {
- Projectile.NewProjectile(player.GetProjectileSource_Buff(buffIndex), player.Center, -Vector2.UnitY.RotatedByRandom(MathHelper.PiOver2), petProjID, 0, 0f, player.whoAmI);
- }
- }
-
- public static void LoopAnimation(ref int frame, ref double frameCounter, int speed, int startFrame, int endFrame)
- {
- if (startFrame < 0)
- {
- startFrame = 0;
- }
-
- if (frame < startFrame)
- {
- frame = startFrame;
- }
- else if (frame > endFrame)
- {
- frame = endFrame;
- }
-
- frameCounter++;
- if (frameCounter >= speed)
- {
- frameCounter = 0;
- frame++;
- if (frame > endFrame)
- {
- frame = startFrame;
- }
- }
- }
-
- public static void LoopAnimationInt(ref int frame, ref int frameCounter, int speed, int startFrame, int endFrame)
- {
- if (startFrame < 0)
- {
- startFrame = 0;
- }
-
- if (frame < startFrame)
- {
- frame = startFrame;
- }
- else if (frame > endFrame)
- {
- frame = endFrame;
- }
-
- frameCounter++;
- if (frameCounter >= speed)
- {
- frameCounter = 0;
- frame++;
- if (frame > endFrame)
- {
- frame = startFrame;
- }
- }
- }
-
- ///
- /// Loops through all frames in a set speed from top to bottom and repeats
- ///
- public static void LoopAnimation(this NPC npc, int frameHeight, int speed, int startFrame = 0, int endFrame = -1)
- {
- if (endFrame == -1)
- {
- endFrame = Main.npcFrameCount[npc.type] - 1;
- }
-
- int frame = npc.frame.Y / frameHeight;
- LoopAnimation(ref frame, ref npc.frameCounter, speed, startFrame, endFrame);
- npc.frame.Y = frame * frameHeight;
- }
-
- ///
- /// Loops through all frames in a set speed from top to bottom and repeats
- ///
- public static void LoopAnimation(this Projectile proj, int speed, int startFrame = 0, int endFrame = -1)
- {
- if (endFrame == -1)
- {
- endFrame = Main.projFrames[proj.type] - 1;
- }
-
- LoopAnimationInt(ref proj.frame, ref proj.frameCounter, speed, startFrame, endFrame);
- }
-
- ///
- /// Same as LoopAnimation, but stops at the last frame. Returns true if still animating
- ///
- public static bool WaterfallAnimation(this NPC npc, int frameHeight, int speed, int startFrame = 0, int endFrame = -1)
- {
- //If no endFrame specified: take last frame on the sheet, otherwise, endFrame
- bool lastFrame = (endFrame == -1 && npc.frame.Y * frameHeight >= Main.npcFrameCount[npc.type] - 1) || (endFrame != -1);
-
- bool stillAnimating = !lastFrame;
- if (stillAnimating) npc.LoopAnimation(frameHeight, speed, startFrame, endFrame);
- return stillAnimating;
- }
-
- ///
- /// Same as LoopAnimation, but stops at the last frame. Returns true if still animating
- ///
- public static bool WaterfallAnimation(this Projectile proj, int speed, int startFrame = 0, int endFrame = -1)
- {
- //If no endFrame specified: take last frame on the sheet, otherwise, endFrame
- bool lastFrame = (endFrame == -1 && proj.frame >= Main.projFrames[proj.type] - 1) || (endFrame != -1);
-
- bool stillAnimating = !lastFrame;
- if (stillAnimating) proj.LoopAnimation(speed, startFrame, endFrame);
- return stillAnimating;
- }
- }
+ ///
+ /// contains Extensions for some basic tasks
+ ///
+ public static class AssExtensions
+ {
+ ///
+ /// Returns the average value between the RGB (ignoring A)
+ ///
+ public static float GetAverage(this Color color)
+ {
+ return (color.R + color.G + color.B) / 3f;
+ }
+
+ ///
+ /// Returns the Player that owns the given projectile. Only use if you are certain an owner exists and it is a player
+ ///
+ public static Player GetOwner(this Projectile proj)
+ {
+ return Main.player[proj.owner];
+ }
+
+ ///
+ /// Copy of vanilla code for spawning a single pet and setting buffTime. Gives random velocity at spawn
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void AssSpawnPetIfNeededAndSetTime(this Player player, int buffIndex, ref bool petBool, int petProjID, int buffTimeToGive = 18000)
+ {
+ player.buffTime[buffIndex] = buffTimeToGive;
+ player.AssSpawnPetIfNeeded(ref petBool, petProjID, buffIndex);
+ }
+
+ ///
+ /// Player.HasItem + checks all banks
+ ///
+ ///
+ ///
+ ///
+ public static bool HasItemWithBanks(this Player player, int type)
+ {
+ if (player.HasItem(type)) return true;
+
+ Item[][] inventoryArray = { player.bank.item, player.bank2.item, player.bank3.item, player.bank4.item };
+ for (int i = 0; i < inventoryArray.Length; i++)
+ {
+ Item[] inventory = inventoryArray[i];
+ for (int j = 0; j < inventory.Length; j++)
+ {
+ Item item = inventory[j];
+ if (type == item.type && item.stack > 0) return true;
+ }
+ }
+
+ return false;
+ }
+
+ ///
+ /// Checks if given item is present in the players inventory or equip slots
+ ///
+ public static bool ItemInInventoryOrEquipped(this Player player, Item item, bool ignoreVanity = false)
+ {
+ if (player.HasItem(item.type)) return true;
+ if (item.accessory || item.headSlot > 0 || item.bodySlot > 0 || item.legSlot > 0)
+ {
+ int maxLength = ignoreVanity ? 10 : player.armor.Length;
+ for (int i = 0; i < maxLength; i++)
+ {
+ if (player.armor[i].type == item.type) return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Copy of vanilla code for spawning a single pet. Gives random velocity at spawn
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static void AssSpawnPetIfNeeded(this Player player, ref bool petBool, int petProjID, int buffIndex)
+ {
+ petBool = true;
+ if (player.ownedProjectileCounts[petProjID] > 0)
+ {
+ return;
+ }
+
+ if (player.whoAmI == Main.myPlayer)
+ {
+ Projectile.NewProjectile(player.GetProjectileSource_Buff(buffIndex), player.Center, -Vector2.UnitY.RotatedByRandom(MathHelper.PiOver2), petProjID, 0, 0f, player.whoAmI);
+ }
+ }
+
+ public static void LoopAnimation(ref int frame, ref double frameCounter, int speed, int startFrame, int endFrame)
+ {
+ if (startFrame < 0)
+ {
+ startFrame = 0;
+ }
+
+ if (frame < startFrame)
+ {
+ frame = startFrame;
+ }
+ else if (frame > endFrame)
+ {
+ frame = endFrame;
+ }
+
+ frameCounter++;
+ if (frameCounter >= speed)
+ {
+ frameCounter = 0;
+ frame++;
+ if (frame > endFrame)
+ {
+ frame = startFrame;
+ }
+ }
+ }
+
+ public static void LoopAnimationInt(ref int frame, ref int frameCounter, int speed, int startFrame, int endFrame)
+ {
+ if (startFrame < 0)
+ {
+ startFrame = 0;
+ }
+
+ if (frame < startFrame)
+ {
+ frame = startFrame;
+ }
+ else if (frame > endFrame)
+ {
+ frame = endFrame;
+ }
+
+ frameCounter++;
+ if (frameCounter >= speed)
+ {
+ frameCounter = 0;
+ frame++;
+ if (frame > endFrame)
+ {
+ frame = startFrame;
+ }
+ }
+ }
+
+ ///
+ /// Loops through all frames in a set speed from top to bottom and repeats
+ ///
+ public static void LoopAnimation(this NPC npc, int frameHeight, int speed, int startFrame = 0, int endFrame = -1)
+ {
+ if (endFrame == -1)
+ {
+ endFrame = Main.npcFrameCount[npc.type] - 1;
+ }
+
+ int frame = npc.frame.Y / frameHeight;
+ LoopAnimation(ref frame, ref npc.frameCounter, speed, startFrame, endFrame);
+ npc.frame.Y = frame * frameHeight;
+ }
+
+ ///
+ /// Loops through all frames in a set speed from top to bottom and repeats
+ ///
+ public static void LoopAnimation(this Projectile proj, int speed, int startFrame = 0, int endFrame = -1)
+ {
+ if (endFrame == -1)
+ {
+ endFrame = Main.projFrames[proj.type] - 1;
+ }
+
+ LoopAnimationInt(ref proj.frame, ref proj.frameCounter, speed, startFrame, endFrame);
+ }
+
+ ///
+ /// Same as LoopAnimation, but stops at the last frame. Returns true if still animating
+ ///
+ public static bool WaterfallAnimation(this NPC npc, int frameHeight, int speed, int startFrame = 0, int endFrame = -1)
+ {
+ //If no endFrame specified: take last frame on the sheet, otherwise, endFrame
+ bool lastFrame = (endFrame == -1 && npc.frame.Y * frameHeight >= Main.npcFrameCount[npc.type] - 1) || (endFrame != -1);
+
+ bool stillAnimating = !lastFrame;
+ if (stillAnimating) npc.LoopAnimation(frameHeight, speed, startFrame, endFrame);
+ return stillAnimating;
+ }
+
+ ///
+ /// Same as LoopAnimation, but stops at the last frame. Returns true if still animating
+ ///
+ public static bool WaterfallAnimation(this Projectile proj, int speed, int startFrame = 0, int endFrame = -1)
+ {
+ //If no endFrame specified: take last frame on the sheet, otherwise, endFrame
+ bool lastFrame = (endFrame == -1 && proj.frame >= Main.projFrames[proj.type] - 1) || (endFrame != -1);
+
+ bool stillAnimating = !lastFrame;
+ if (stillAnimating) proj.LoopAnimation(speed, startFrame, endFrame);
+ return stillAnimating;
+ }
+ }
}
diff --git a/Base/AssUtils.cs b/Base/AssUtils.cs
index 03e763a1..63c85a00 100644
--- a/Base/AssUtils.cs
+++ b/Base/AssUtils.cs
@@ -11,646 +11,646 @@
namespace AssortedCrazyThings.Base
{
- static class AssUtils
- {
- ///
- /// The instance of the mod
- ///
- public static AssortedCrazyThings Instance => ModContent.GetInstance(); //just shorter writing AssUtils.Instance than AssortedCrazyThings.Instance
-
- ///
- /// Types of modded NPCs which names are ending with Body or Tail
- ///
- public static int[] isModdedWormBodyOrTail;
-
- public static void Print(object o)
- {
- if (Main.netMode == NetmodeID.Server)
- {
- Console.WriteLine(o.ToString());
- }
-
- if (Main.netMode == NetmodeID.MultiplayerClient || Main.netMode == NetmodeID.SinglePlayer)
- {
- Main.NewText(o.ToString());
- }
- }
-
- public static void UIText(string str, Color color)
- {
- CombatText.NewText(Main.LocalPlayer.getRect(), color, str);
- }
-
- public static Dust QuickDust(int dustType, Vector2 pos, Color color, Vector2 dustVelo = default(Vector2), int alpha = 0, float scale = 1f)
- {
- Dust dust = Dust.NewDustPerfect(pos, dustType, dustVelo, alpha, color, scale);
- dust.position = pos;
- dust.velocity = dustVelo;
- dust.fadeIn = 1f;
- dust.noLight = false;
- dust.noGravity = true;
- return dust;
- }
-
- public static void QuickDustLine(int dustType, Vector2 start, Vector2 end, float splits, Color color = default(Color), Vector2 dustVelo = default(Vector2), int alpha = 0, float scale = 1f)
- {
- QuickDust(dustType, start, color, dustVelo);
- float num = 1f / splits;
- for (float num2 = 0f; num2 < 1f; num2 += num)
- {
- QuickDust(dustType, Vector2.Lerp(start, end, num2), color, dustVelo, alpha, scale);
- }
- }
-
- ///
- /// Something similar to Dust.QuickDust
- ///
- public static Dust DrawDustAtPos(Vector2 pos, int dustType = 169)
- {
- //used for showing a position as a dust for debugging
- Dust dust = QuickDust(dustType, pos, Color.White);
- dust.noGravity = true;
- dust.noLight = true;
- return dust;
- }
-
- public static void DrawSkeletronLikeArms(string texString, Vector2 selfPos, Vector2 centerPos, float selfPad = 0f, float centerPad = 0f, float direction = 0f)
- {
- DrawSkeletronLikeArms(ModContent.Request(texString).Value, selfPos, centerPos, selfPad, centerPad, direction);
- }
-
- ///
- /// Draws two "arms" originating from selfPos, "attached" at centerPos
- ///
- public static void DrawSkeletronLikeArms(Texture2D tex, Vector2 selfPos, Vector2 centerPos, float selfPad = 0f, float centerPad = 0f, float direction = 0f)
- {
- //with all float params = 0f, the arm will originate below the selfPos
- //Pos parameters should be Entity.Center
- //Pad parameters are actually just y offsets
- //direction determines in what direction the elbow bends and by how much (-1 to 1 are preferred)
- //if (tex == null) tex = Main.boneArmTexture;
- Vector2 drawPos = selfPos;
- drawPos += new Vector2(-5f * direction, selfPad);
- centerPos.Y += -tex.Height / 2 + centerPad;
- for (int i = 0; i < 2; i++)
- {
- float x = centerPos.X - drawPos.X;
- float y = centerPos.Y - drawPos.Y;
- float magnitude;
- if (i == 0) //first arm piece starting at selfPos
- {
- x += -(100 + tex.Height) * direction;
- y += 100 + tex.Width;
- magnitude = (float)Math.Sqrt(x * x + y * y);
- magnitude = tex.Height / 2 / magnitude;
- drawPos.X += x * magnitude;
- drawPos.Y += y * magnitude;
- }
- else //second arm piece
- {
- x += -(30 + tex.Width / 2) * direction;
- y += 30 + tex.Height / 2;
- magnitude = (float)Math.Sqrt(x * x + y * y);
- magnitude = tex.Height / 2 / magnitude;
- drawPos.X += x * magnitude;
- drawPos.Y += y * magnitude;
- }
- float rotation = (float)Math.Atan2(y, x) - 1.57f;
- Color color = Lighting.GetColor((int)drawPos.X / 16, (int)(drawPos.Y / 16f));
- Main.spriteBatch.Draw(tex, new Vector2(drawPos.X - Main.screenPosition.X, drawPos.Y - Main.screenPosition.Y), tex.Bounds, color, rotation, tex.Bounds.Size() / 2, 1f, SpriteEffects.None, 0f);
- if (i == 0)
- {
- //padding for the second arm piece
- drawPos.X += x * magnitude * 1.1f;
- drawPos.Y += y * magnitude * 1.1f;
- }
- else if (Main.instance.IsActive) //not sure what this part does
- {
- drawPos.X += x * magnitude - 16f;
- drawPos.Y += y * magnitude - 6f;
- }
- }
- }
-
- public static void DrawTether(string texString, Vector2 start, Vector2 end)
- {
- DrawTether(ModContent.Request(texString).Value, start, end);
- }
-
- //Credit to IDGCaptainRussia
- ///
- /// Draws a "connection" between two points
- ///
- public static void DrawTether(Texture2D tex, Vector2 start, Vector2 end)
- {
- Vector2 position = start;
- Vector2 mountedCenter = end;
- float num1 = tex.Height;
- Vector2 vector2_4 = mountedCenter - position;
- Vector2 vector2_4tt = mountedCenter - position;
- float keepgoing = vector2_4tt.Length();
- Vector2 vector2t = vector2_4;
- vector2t.Normalize();
- position -= vector2t * (num1 * 0.5f);
-
- float rotation = vector2_4.ToRotation() - 1.57f;
- bool flag = true;
- if (float.IsNaN(position.X) && float.IsNaN(position.Y))
- flag = false;
- if (float.IsNaN(vector2_4.X) && float.IsNaN(vector2_4.Y))
- flag = false;
- while (flag)
- {
- if (keepgoing <= -1)
- {
- flag = false;
- }
- else
- {
- Vector2 vector2_1 = vector2_4;
- vector2_1.Normalize();
- position += vector2_1 * num1;
- keepgoing -= num1;
- vector2_4 = mountedCenter - position;
- Color color2 = Lighting.GetColor((int)position.X / 16, (int)position.Y / 16);
- color2 = new Color(color2.R, color2.G, color2.B, 255);
- Main.spriteBatch.Draw(tex, position - Main.screenPosition, new Rectangle(0, 0, tex.Width, (int)Math.Min(num1, num1 + keepgoing)), color2, rotation, tex.Bounds.Size() / 2, 1f, SpriteEffects.None, 0.0f);
- }
- }
- }
-
- ///
- /// Combines two arrays (first + second in order)
- ///
- public static T[] ConcatArray(T[] first, T[] second)
- {
- T[] combined = new T[first.Length + second.Length];
- Array.Copy(first, combined, first.Length);
- Array.Copy(second, 0, combined, first.Length, second.Length);
- return combined;
- }
-
- ///
- /// Fills an array with a default value.
- /// If array is null, creates one with the length specified.
- /// Else, overrides each element with default value
- ///
- public static void FillWithDefault(ref T[] array, T def, int length = -1)
- {
- if (array == null)
- {
- if (length == -1)
- throw new ArgumentOutOfRangeException("Array is null but length isn't specified");
- array = new T[length];
- }
- else
- {
- length = array.Length;
- }
-
- for (int i = 0; i < length; i++)
- {
- array[i] = def;
- }
- }
-
- ///
- /// Fills a list with a default value.
- /// If array is null, creates one with the length specified.
- /// Else, overrides each element with default value
- ///
- public static void FillWithDefault(ref List list, T def, int length = -1)
- {
- if (list == null)
- {
- if (length == -1)
- throw new ArgumentOutOfRangeException("List is null but length isn't specified");
- list = new List(length);
- }
- else
- {
- length = list.Count;
- }
-
- for (int i = 0; i < length; i++)
- {
- list.Add(def);
- }
- }
-
- ///
- /// Like NPC.AnyNPC, but checks for each type in the passed array.
- /// If one exists, returns true
- ///
- public static bool AnyNPCs(int[] types)
- {
- //Like AnyNPCs but checks for an array
- for (int i = 0; i < types.Length; i++)
- {
- if (NPC.AnyNPCs(types[i])) return true;
- }
- return false;
- }
-
- ///
- /// Like NPC.AnyNPC, but checks for each type in the passed list.
- /// If one exists, returns true
- ///
- public static bool AnyNPCs(List types)
- {
- return AnyNPCs(types.ToArray());
- }
-
- ///
- /// Like NPC.AnyNPC, but checks for custom condition (active already true).
- /// If one exists, returns true
- ///
- public static bool AnyNPCs(Func condition)
- {
- for (int i = 0; i < Main.maxNPCs; i++)
- {
- if (Main.npc[i].active && condition(Main.npc[i])) return true;
- }
- return false;
- }
-
- ///
- /// Counts all NPCs in the passed array
- ///
- public static int CountAllNPCs(int[] types)
- {
- int count = 0;
- for (int i = 0; i < types.Length; i++)
- {
- count += NPC.CountNPCS(types[i]);
- }
- return count;
- }
-
- ///
- /// Counts all active projectiles of the given type, and of a given owner if specified
- ///
- public static int CountProjs(int type, int owner = -1)
- {
- int count = 0;
- for (int i = 0; i < Main.maxProjectiles; i++)
- {
- Projectile proj = Main.projectile[i];
- if (proj.active && proj.type == type &&
- (owner < 0 || proj.owner == owner))
- {
- count++;
- }
- }
- return count;
- }
-
- ///
- /// Checks if given NPC is a worm body or tail
- ///
- public static bool IsWormBodyOrTail(NPC npc)
- {
- return npc.dontCountMe || Array.BinarySearch(isModdedWormBodyOrTail, npc.type) >= 0 || npc.type == NPCID.EaterofWorldsTail || npc.type == NPCID.EaterofWorldsBody/* || npc.realLife != -1*/;
- }
-
- ///
- /// Checks if player is in an evil biome (any of three)
- ///
- public static bool EvilBiome(Player player)
- {
- return player.ZoneCorrupt || player.ZoneCrimson || player.ZoneHallow;
- }
-
- ///
- /// Formats Main.time into a string representation with AM/PM
- ///
- public static string GetTimeAsString(bool accurate = true)
- {
- string suffix = "AM";
- double doubletime = Main.time;
- if (!Main.dayTime)
- {
- doubletime += 54000.0;
- }
- doubletime = doubletime / 86400.0 * 24.0;
- double wtf = 7.5;
- doubletime = doubletime - wtf - 12.0;
- if (doubletime < 0.0)
- {
- doubletime += 24.0;
- }
- if (doubletime >= 12.0)
- {
- suffix = "PM";
- }
- int hours = (int)doubletime;
- double doubleminutes = doubletime - hours;
- doubleminutes = (int)(doubleminutes * 60.0);
- string minutes = string.Concat(doubleminutes);
- if (doubleminutes < 10.0)
- {
- minutes = "0" + minutes;
- }
- if (hours > 12)
- {
- hours -= 12;
- }
- if (hours == 0)
- {
- hours = 12;
- }
- if (!accurate) minutes = (!(doubleminutes < 30.0)) ? "30" : "00";
- return Language.GetTextValue("Game.Time", hours + ":" + minutes + " " + suffix);
- }
-
- public static string GetMoonPhaseAsString(bool showNumber = false)
- {
- string suffix = "";
- if (showNumber) suffix = " (" + (Main.moonPhase + 1) + ")";
- string prefix = Lang.inter[102].Value + ": "; //can't seem to find "Moon Phase" in the lang files for GameUI
- string value = "";
- string check = "";
- switch (Main.moonPhase)
- {
- case 0:
- check = "FullMoon";
- break;
- case 1:
- check = "WaningGibbous";
- break;
- case 2:
- check = "ThirdQuarter";
- break;
- case 3:
- check = "WaningCrescent";
- break;
- case 4:
- check = "NewMoon";
- break;
- case 5:
- check = "WaxingCrescent";
- break;
- case 6:
- check = "FirstQuarter";
- break;
- case 7:
- check = "WaxingGibbous";
- break;
- default:
- break;
- }
- value = Language.GetTextValue("GameUI." + check);
- if (value != "") return prefix + value + suffix;
- return "";
- }
-
- ///
- /// Alternative NewProjectile, automatically sets owner to Main.myPlayer.
- /// Also doesn't take into account vanilla projectiles that set things like ai or timeLeft, so only use this for ModProjectiles.
- /// Use preCreate if you want to spawn or not spawn the projectile based on the projectile itself.
- /// Use preSync to set ai[0], ai[1] and other values
- ///
- public static int NewProjectile(IEntitySource source, Vector2 position, Vector2 velocity, int Type, int Damage, float Knockback, Func preCreate = null, Action preSync = null)
- {
- return NewProjectile(source, position.X, position.Y, velocity.X, velocity.Y, Type, Damage, Knockback, preCreate, preSync);
- }
-
- ///
- /// Alternative NewProjectile, automatically sets owner to Main.myPlayer.
- /// Also doesn't take into account vanilla projectiles that set things like ai or timeLeft, so only use this for ModProjectiles.
- /// Use preCreate if you want to spawn or not spawn the projectile based on the projectile itself.
- /// Use preSync to set ai[0], ai[1] and other values
- ///
- public static int NewProjectile(IEntitySource source, float X, float Y, float SpeedX, float SpeedY, int Type, int Damage, float Knockback, Func preCreate = null, Action preSync = null)
- {
- if (preCreate != null)
- {
- Projectile test = new Projectile();
- test.SetDefaults(Type);
- if (!preCreate(test)) return Main.maxProjectiles;
- }
-
- int index = Main.maxProjectiles;
- for (int i = 0; i < Main.maxProjectiles; i++)
- {
- if (!Main.projectile[i].active)
- {
- index = i;
- break;
- }
- }
-
- if (index == Main.maxProjectiles)
- index = Projectile.FindOldestProjectile();
-
- int Owner = Main.myPlayer;
- float ai0 = 0f;
- float ai1 = 0f;
-
- Projectile projectile = Main.projectile[index];
- projectile.SetDefaults(Type);
- projectile.position.X = X - projectile.width * 0.5f;
- projectile.position.Y = Y - projectile.height * 0.5f;
- projectile.owner = Owner;
- projectile.velocity.X = SpeedX;
- projectile.velocity.Y = SpeedY;
- projectile.damage = Damage;
- projectile.knockBack = Knockback;
- projectile.identity = index;
- projectile.gfxOffY = 0f;
- projectile.stepSpeed = 1f;
- projectile.wet = Collision.WetCollision(projectile.position, projectile.width, projectile.height);
- if (projectile.ignoreWater)
- {
- projectile.wet = false;
- }
- projectile.honeyWet = Collision.honey;
- Main.projectileIdentity[Owner, index] = index;
- FindBannerToAssociateTo(source, projectile);
- HandlePlayerStatModifiers(source, projectile);
- projectile.ai[0] = ai0;
- projectile.ai[1] = ai1;
- if (Type > 0)
- {
- if (ProjectileID.Sets.NeedsUUID[Type])
- {
- projectile.projUUID = projectile.identity;
- }
- }
-
- preSync?.Invoke(projectile);
-
- if (Main.netMode != NetmodeID.SinglePlayer)
- {
- NetMessage.SendData(MessageID.SyncProjectile, number: index);
- }
- return index;
- }
-
- ///
- /// If you need immediate sync, usually necessary outside of Projectile.AI (as netUpdate is set to false before it's invoked)
- ///
- ///
- public static void NetSync(this Projectile projectile)
- {
- if (Main.myPlayer == projectile.owner)
- {
- NetMessage.SendData(MessageID.SyncProjectile, -1, -1, null, projectile.whoAmI);
- projectile.netSpam = 0;
- projectile.netUpdate = false;
- projectile.netUpdate2 = false;
- }
- }
-
- //Clone from vanilla since it's private
- private static void FindBannerToAssociateTo(IEntitySource spawnSource, Projectile next)
- {
- EntitySource_Parent entitySource_Parent = spawnSource as EntitySource_Parent;
- if (entitySource_Parent == null)
- {
- return;
- }
-
- Projectile projectile = entitySource_Parent.Entity as Projectile;
- if (projectile != null)
- {
- next.bannerIdToRespondTo = projectile.bannerIdToRespondTo;
- return;
- }
-
- NPC nPC = entitySource_Parent.Entity as NPC;
- if (nPC != null)
- {
- next.bannerIdToRespondTo = Item.NPCtoBanner(nPC.BannerID());
- }
- }
-
- //Clone from tml since it's private, may need updates, keep an eye out
- private static void HandlePlayerStatModifiers(IEntitySource spawnSource, Projectile projectile)
- {
- if (spawnSource is EntitySource_ItemUse itemUseSource && itemUseSource.Entity is Player player)
- {
- projectile.CritChance += player.GetWeaponCrit(itemUseSource.Item);
- projectile.ArmorPenetration += player.GetWeaponArmorPenetration(itemUseSource.Item);
- }
- }
-
- ///
- /// Alternative, static version of npc.DropItemInstanced. Checks the playerCondition delegate before syncing/spawning the item
- ///
- public static void DropItemInstanced(NPC npc, Vector2 Position, Vector2 HitboxSize, int itemType, int itemStack = 1, Func condition = null, bool interactionRequired = true)
- {
- if (itemType > 0)
- {
- if (Main.netMode == NetmodeID.Server)
- {
- int item = Item.NewItem(npc.GetItemSource_Loot(), (int)Position.X, (int)Position.Y, (int)HitboxSize.X, (int)HitboxSize.Y, itemType, itemStack, true);
- Main.timeItemSlotCannotBeReusedFor[item] = 54000;
- for (int p = 0; p < Main.maxPlayers; p++)
- {
- if (Main.player[p].active && (npc.playerInteraction[p] || !interactionRequired))
- {
- if (condition != null && condition(npc, Main.player[p]) ||
- condition == null)
- NetMessage.SendData(MessageID.InstancedItem, p, -1, null, item);
- }
- }
- Main.item[item].active = false;
- }
- else if (Main.netMode == NetmodeID.SinglePlayer)
- {
- if (condition != null && condition(npc, Main.LocalPlayer) ||
- condition == null)
- Item.NewItem(npc.GetItemSource_Loot(), (int)Position.X, (int)Position.Y, (int)HitboxSize.X, (int)HitboxSize.Y, itemType, itemStack);
- }
- //npc.value = 0f;
- }
- }
-
- ///
- /// Draws the _Highlight texture of this tile if it exists and can be drawn
- ///
- ///
- ///
- ///
- ///
- /// Color the tile is drawn with
- ///
- ///
- public static void DrawTileHighlight(SpriteBatch spriteBatch, int i, int j, int type, Color color, Vector2 pos, Rectangle frame)
- {
- if (TileID.Sets.HasOutlines[type] && Collision.InTileBounds(i, j, Main.TileInteractionLX, Main.TileInteractionLY, Main.TileInteractionHX, Main.TileInteractionHY) && Main.SmartInteractTileCoords.Contains(new Point(i, j)))
- {
- int average = (int)color.GetAverage();
- bool selected = false;
- if (Main.SmartInteractTileCoordsSelected.Contains(new Point(i, j)))
- {
- selected = true;
- }
- if (average > 10)
- {
- Texture2D outlineTexture = TextureAssets.HighlightMask[type].Value;
- Color outlineColor;
- if (selected)
- {
- outlineColor = new Color(average, average, average / 3, average);
- }
- else
- {
- outlineColor = new Color(average / 2, average / 2, average / 2, average);
- }
-
- if (outlineTexture != null)
- {
- spriteBatch.Draw(outlineTexture, pos, frame, outlineColor, 0f, default(Vector2), 1f, SpriteEffects.None, 0f);
- }
- }
- }
- }
-
- ///
- /// Modify the velocity (that has the direction from position to targetPos) of something that is affected by gravity in a way that it will still reach targetPos
- ///
Note: This might increase the length of velocity depending on how much correction was needed, use offsetCap to limit it.
- ///
- /// Starting location
- /// Target location
- /// Gravity applied to velocity.Y
- /// Starting velocity
- /// Amount of initial ticks that velocity should NOT be updated by gravity
- /// Terminal velocity.Y
- /// Multiplier for final correction to velocity. 1f == perfect, 0f == none
- public static void ModifyVelocityForGravity(Vector2 position, Vector2 targetPos, in float gravity, ref Vector2 velocity, int ticksWithoutGravity = 0, float terminalCap = 16f, float factor = 1f, float offsetCap = 2.5f)
- {
- //Need to make the velocity + gravity hit targetPos.Y
- //Keep horizontal velocity, correct vertical velocity to account for gravity
-
- Vector2 toTarget = targetPos - position;
- int ticksToReachX = (int)(toTarget.X / velocity.X); //"Simulated time" it takes to reach target
-
- float traversedDistanceY = 0;
- float traversedDistanceYNoGravity = 0;
- float velocityYWithGravity = velocity.Y;
- for (int i = 0; i < ticksToReachX; i++)
- {
- if (i >= ticksWithoutGravity)
- {
- velocityYWithGravity += gravity;
- if (velocityYWithGravity > terminalCap)
- {
- velocityYWithGravity = terminalCap;
- }
- }
- traversedDistanceY += velocityYWithGravity;
- traversedDistanceYNoGravity += velocity.Y;
- }
-
- float offsetY = traversedDistanceY - traversedDistanceYNoGravity;
-
- float velocityYOffset = offsetY / ticksToReachX;
-
- velocityYOffset = Math.Min(velocityYOffset, offsetCap);
-
- velocity.Y -= factor * velocityYOffset;
- }
- }
+ static class AssUtils
+ {
+ ///
+ /// The instance of the mod
+ ///
+ public static AssortedCrazyThings Instance => ModContent.GetInstance(); //just shorter writing AssUtils.Instance than AssortedCrazyThings.Instance
+
+ ///
+ /// Types of modded NPCs which names are ending with Body or Tail
+ ///
+ public static int[] isModdedWormBodyOrTail;
+
+ public static void Print(object o)
+ {
+ if (Main.netMode == NetmodeID.Server)
+ {
+ Console.WriteLine(o.ToString());
+ }
+
+ if (Main.netMode == NetmodeID.MultiplayerClient || Main.netMode == NetmodeID.SinglePlayer)
+ {
+ Main.NewText(o.ToString());
+ }
+ }
+
+ public static void UIText(string str, Color color)
+ {
+ CombatText.NewText(Main.LocalPlayer.getRect(), color, str);
+ }
+
+ public static Dust QuickDust(int dustType, Vector2 pos, Color color, Vector2 dustVelo = default(Vector2), int alpha = 0, float scale = 1f)
+ {
+ Dust dust = Dust.NewDustPerfect(pos, dustType, dustVelo, alpha, color, scale);
+ dust.position = pos;
+ dust.velocity = dustVelo;
+ dust.fadeIn = 1f;
+ dust.noLight = false;
+ dust.noGravity = true;
+ return dust;
+ }
+
+ public static void QuickDustLine(int dustType, Vector2 start, Vector2 end, float splits, Color color = default(Color), Vector2 dustVelo = default(Vector2), int alpha = 0, float scale = 1f)
+ {
+ QuickDust(dustType, start, color, dustVelo);
+ float num = 1f / splits;
+ for (float num2 = 0f; num2 < 1f; num2 += num)
+ {
+ QuickDust(dustType, Vector2.Lerp(start, end, num2), color, dustVelo, alpha, scale);
+ }
+ }
+
+ ///
+ /// Something similar to Dust.QuickDust
+ ///
+ public static Dust DrawDustAtPos(Vector2 pos, int dustType = 169)
+ {
+ //used for showing a position as a dust for debugging
+ Dust dust = QuickDust(dustType, pos, Color.White);
+ dust.noGravity = true;
+ dust.noLight = true;
+ return dust;
+ }
+
+ public static void DrawSkeletronLikeArms(string texString, Vector2 selfPos, Vector2 centerPos, float selfPad = 0f, float centerPad = 0f, float direction = 0f)
+ {
+ DrawSkeletronLikeArms(ModContent.Request(texString).Value, selfPos, centerPos, selfPad, centerPad, direction);
+ }
+
+ ///
+ /// Draws two "arms" originating from selfPos, "attached" at centerPos
+ ///
+ public static void DrawSkeletronLikeArms(Texture2D tex, Vector2 selfPos, Vector2 centerPos, float selfPad = 0f, float centerPad = 0f, float direction = 0f)
+ {
+ //with all float params = 0f, the arm will originate below the selfPos
+ //Pos parameters should be Entity.Center
+ //Pad parameters are actually just y offsets
+ //direction determines in what direction the elbow bends and by how much (-1 to 1 are preferred)
+ //if (tex == null) tex = Main.boneArmTexture;
+ Vector2 drawPos = selfPos;
+ drawPos += new Vector2(-5f * direction, selfPad);
+ centerPos.Y += -tex.Height / 2 + centerPad;
+ for (int i = 0; i < 2; i++)
+ {
+ float x = centerPos.X - drawPos.X;
+ float y = centerPos.Y - drawPos.Y;
+ float magnitude;
+ if (i == 0) //first arm piece starting at selfPos
+ {
+ x += -(100 + tex.Height) * direction;
+ y += 100 + tex.Width;
+ magnitude = (float)Math.Sqrt(x * x + y * y);
+ magnitude = tex.Height / 2 / magnitude;
+ drawPos.X += x * magnitude;
+ drawPos.Y += y * magnitude;
+ }
+ else //second arm piece
+ {
+ x += -(30 + tex.Width / 2) * direction;
+ y += 30 + tex.Height / 2;
+ magnitude = (float)Math.Sqrt(x * x + y * y);
+ magnitude = tex.Height / 2 / magnitude;
+ drawPos.X += x * magnitude;
+ drawPos.Y += y * magnitude;
+ }
+ float rotation = (float)Math.Atan2(y, x) - 1.57f;
+ Color color = Lighting.GetColor((int)drawPos.X / 16, (int)(drawPos.Y / 16f));
+ Main.spriteBatch.Draw(tex, new Vector2(drawPos.X - Main.screenPosition.X, drawPos.Y - Main.screenPosition.Y), tex.Bounds, color, rotation, tex.Bounds.Size() / 2, 1f, SpriteEffects.None, 0f);
+ if (i == 0)
+ {
+ //padding for the second arm piece
+ drawPos.X += x * magnitude * 1.1f;
+ drawPos.Y += y * magnitude * 1.1f;
+ }
+ else if (Main.instance.IsActive) //not sure what this part does
+ {
+ drawPos.X += x * magnitude - 16f;
+ drawPos.Y += y * magnitude - 6f;
+ }
+ }
+ }
+
+ public static void DrawTether(string texString, Vector2 start, Vector2 end)
+ {
+ DrawTether(ModContent.Request(texString).Value, start, end);
+ }
+
+ //Credit to IDGCaptainRussia
+ ///
+ /// Draws a "connection" between two points
+ ///
+ public static void DrawTether(Texture2D tex, Vector2 start, Vector2 end)
+ {
+ Vector2 position = start;
+ Vector2 mountedCenter = end;
+ float num1 = tex.Height;
+ Vector2 vector2_4 = mountedCenter - position;
+ Vector2 vector2_4tt = mountedCenter - position;
+ float keepgoing = vector2_4tt.Length();
+ Vector2 vector2t = vector2_4;
+ vector2t.Normalize();
+ position -= vector2t * (num1 * 0.5f);
+
+ float rotation = vector2_4.ToRotation() - 1.57f;
+ bool flag = true;
+ if (float.IsNaN(position.X) && float.IsNaN(position.Y))
+ flag = false;
+ if (float.IsNaN(vector2_4.X) && float.IsNaN(vector2_4.Y))
+ flag = false;
+ while (flag)
+ {
+ if (keepgoing <= -1)
+ {
+ flag = false;
+ }
+ else
+ {
+ Vector2 vector2_1 = vector2_4;
+ vector2_1.Normalize();
+ position += vector2_1 * num1;
+ keepgoing -= num1;
+ vector2_4 = mountedCenter - position;
+ Color color2 = Lighting.GetColor((int)position.X / 16, (int)position.Y / 16);
+ color2 = new Color(color2.R, color2.G, color2.B, 255);
+ Main.spriteBatch.Draw(tex, position - Main.screenPosition, new Rectangle(0, 0, tex.Width, (int)Math.Min(num1, num1 + keepgoing)), color2, rotation, tex.Bounds.Size() / 2, 1f, SpriteEffects.None, 0.0f);
+ }
+ }
+ }
+
+ ///
+ /// Combines two arrays (first + second in order)
+ ///
+ public static T[] ConcatArray(T[] first, T[] second)
+ {
+ T[] combined = new T[first.Length + second.Length];
+ Array.Copy(first, combined, first.Length);
+ Array.Copy(second, 0, combined, first.Length, second.Length);
+ return combined;
+ }
+
+ ///
+ /// Fills an array with a default value.
+ /// If array is null, creates one with the length specified.
+ /// Else, overrides each element with default value
+ ///
+ public static void FillWithDefault(ref T[] array, T def, int length = -1)
+ {
+ if (array == null)
+ {
+ if (length == -1)
+ throw new ArgumentOutOfRangeException("Array is null but length isn't specified");
+ array = new T[length];
+ }
+ else
+ {
+ length = array.Length;
+ }
+
+ for (int i = 0; i < length; i++)
+ {
+ array[i] = def;
+ }
+ }
+
+ ///
+ /// Fills a list with a default value.
+ /// If array is null, creates one with the length specified.
+ /// Else, overrides each element with default value
+ ///
+ public static void FillWithDefault(ref List list, T def, int length = -1)
+ {
+ if (list == null)
+ {
+ if (length == -1)
+ throw new ArgumentOutOfRangeException("List is null but length isn't specified");
+ list = new List(length);
+ }
+ else
+ {
+ length = list.Count;
+ }
+
+ for (int i = 0; i < length; i++)
+ {
+ list.Add(def);
+ }
+ }
+
+ ///
+ /// Like NPC.AnyNPC, but checks for each type in the passed array.
+ /// If one exists, returns true
+ ///
+ public static bool AnyNPCs(int[] types)
+ {
+ //Like AnyNPCs but checks for an array
+ for (int i = 0; i < types.Length; i++)
+ {
+ if (NPC.AnyNPCs(types[i])) return true;
+ }
+ return false;
+ }
+
+ ///
+ /// Like NPC.AnyNPC, but checks for each type in the passed list.
+ /// If one exists, returns true
+ ///
+ public static bool AnyNPCs(List types)
+ {
+ return AnyNPCs(types.ToArray());
+ }
+
+ ///
+ /// Like NPC.AnyNPC, but checks for custom condition (active already true).
+ /// If one exists, returns true
+ ///
+ public static bool AnyNPCs(Func condition)
+ {
+ for (int i = 0; i < Main.maxNPCs; i++)
+ {
+ if (Main.npc[i].active && condition(Main.npc[i])) return true;
+ }
+ return false;
+ }
+
+ ///
+ /// Counts all NPCs in the passed array
+ ///
+ public static int CountAllNPCs(int[] types)
+ {
+ int count = 0;
+ for (int i = 0; i < types.Length; i++)
+ {
+ count += NPC.CountNPCS(types[i]);
+ }
+ return count;
+ }
+
+ ///
+ /// Counts all active projectiles of the given type, and of a given owner if specified
+ ///
+ public static int CountProjs(int type, int owner = -1)
+ {
+ int count = 0;
+ for (int i = 0; i < Main.maxProjectiles; i++)
+ {
+ Projectile proj = Main.projectile[i];
+ if (proj.active && proj.type == type &&
+ (owner < 0 || proj.owner == owner))
+ {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ ///
+ /// Checks if given NPC is a worm body or tail
+ ///
+ public static bool IsWormBodyOrTail(NPC npc)
+ {
+ return npc.dontCountMe || Array.BinarySearch(isModdedWormBodyOrTail, npc.type) >= 0 || npc.type == NPCID.EaterofWorldsTail || npc.type == NPCID.EaterofWorldsBody/* || npc.realLife != -1*/;
+ }
+
+ ///
+ /// Checks if player is in an evil biome (any of three)
+ ///
+ public static bool EvilBiome(Player player)
+ {
+ return player.ZoneCorrupt || player.ZoneCrimson || player.ZoneHallow;
+ }
+
+ ///
+ /// Formats Main.time into a string representation with AM/PM
+ ///
+ public static string GetTimeAsString(bool accurate = true)
+ {
+ string suffix = "AM";
+ double doubletime = Main.time;
+ if (!Main.dayTime)
+ {
+ doubletime += 54000.0;
+ }
+ doubletime = doubletime / 86400.0 * 24.0;
+ double wtf = 7.5;
+ doubletime = doubletime - wtf - 12.0;
+ if (doubletime < 0.0)
+ {
+ doubletime += 24.0;
+ }
+ if (doubletime >= 12.0)
+ {
+ suffix = "PM";
+ }
+ int hours = (int)doubletime;
+ double doubleminutes = doubletime - hours;
+ doubleminutes = (int)(doubleminutes * 60.0);
+ string minutes = string.Concat(doubleminutes);
+ if (doubleminutes < 10.0)
+ {
+ minutes = "0" + minutes;
+ }
+ if (hours > 12)
+ {
+ hours -= 12;
+ }
+ if (hours == 0)
+ {
+ hours = 12;
+ }
+ if (!accurate) minutes = (!(doubleminutes < 30.0)) ? "30" : "00";
+ return Language.GetTextValue("Game.Time", hours + ":" + minutes + " " + suffix);
+ }
+
+ public static string GetMoonPhaseAsString(bool showNumber = false)
+ {
+ string suffix = "";
+ if (showNumber) suffix = " (" + (Main.moonPhase + 1) + ")";
+ string prefix = Lang.inter[102].Value + ": "; //can't seem to find "Moon Phase" in the lang files for GameUI
+ string value = "";
+ string check = "";
+ switch (Main.moonPhase)
+ {
+ case 0:
+ check = "FullMoon";
+ break;
+ case 1:
+ check = "WaningGibbous";
+ break;
+ case 2:
+ check = "ThirdQuarter";
+ break;
+ case 3:
+ check = "WaningCrescent";
+ break;
+ case 4:
+ check = "NewMoon";
+ break;
+ case 5:
+ check = "WaxingCrescent";
+ break;
+ case 6:
+ check = "FirstQuarter";
+ break;
+ case 7:
+ check = "WaxingGibbous";
+ break;
+ default:
+ break;
+ }
+ value = Language.GetTextValue("GameUI." + check);
+ if (value != "") return prefix + value + suffix;
+ return "";
+ }
+
+ ///
+ /// Alternative NewProjectile, automatically sets owner to Main.myPlayer.
+ /// Also doesn't take into account vanilla projectiles that set things like ai or timeLeft, so only use this for ModProjectiles.
+ /// Use preCreate if you want to spawn or not spawn the projectile based on the projectile itself.
+ /// Use preSync to set ai[0], ai[1] and other values
+ ///
+ public static int NewProjectile(IEntitySource source, Vector2 position, Vector2 velocity, int Type, int Damage, float Knockback, Func preCreate = null, Action preSync = null)
+ {
+ return NewProjectile(source, position.X, position.Y, velocity.X, velocity.Y, Type, Damage, Knockback, preCreate, preSync);
+ }
+
+ ///
+ /// Alternative NewProjectile, automatically sets owner to Main.myPlayer.
+ /// Also doesn't take into account vanilla projectiles that set things like ai or timeLeft, so only use this for ModProjectiles.
+ /// Use preCreate if you want to spawn or not spawn the projectile based on the projectile itself.
+ /// Use preSync to set ai[0], ai[1] and other values
+ ///
+ public static int NewProjectile(IEntitySource source, float X, float Y, float SpeedX, float SpeedY, int Type, int Damage, float Knockback, Func preCreate = null, Action preSync = null)
+ {
+ if (preCreate != null)
+ {
+ Projectile test = new Projectile();
+ test.SetDefaults(Type);
+ if (!preCreate(test)) return Main.maxProjectiles;
+ }
+
+ int index = Main.maxProjectiles;
+ for (int i = 0; i < Main.maxProjectiles; i++)
+ {
+ if (!Main.projectile[i].active)
+ {
+ index = i;
+ break;
+ }
+ }
+
+ if (index == Main.maxProjectiles)
+ index = Projectile.FindOldestProjectile();
+
+ int Owner = Main.myPlayer;
+ float ai0 = 0f;
+ float ai1 = 0f;
+
+ Projectile projectile = Main.projectile[index];
+ projectile.SetDefaults(Type);
+ projectile.position.X = X - projectile.width * 0.5f;
+ projectile.position.Y = Y - projectile.height * 0.5f;
+ projectile.owner = Owner;
+ projectile.velocity.X = SpeedX;
+ projectile.velocity.Y = SpeedY;
+ projectile.damage = Damage;
+ projectile.knockBack = Knockback;
+ projectile.identity = index;
+ projectile.gfxOffY = 0f;
+ projectile.stepSpeed = 1f;
+ projectile.wet = Collision.WetCollision(projectile.position, projectile.width, projectile.height);
+ if (projectile.ignoreWater)
+ {
+ projectile.wet = false;
+ }
+ projectile.honeyWet = Collision.honey;
+ Main.projectileIdentity[Owner, index] = index;
+ FindBannerToAssociateTo(source, projectile);
+ HandlePlayerStatModifiers(source, projectile);
+ projectile.ai[0] = ai0;
+ projectile.ai[1] = ai1;
+ if (Type > 0)
+ {
+ if (ProjectileID.Sets.NeedsUUID[Type])
+ {
+ projectile.projUUID = projectile.identity;
+ }
+ }
+
+ preSync?.Invoke(projectile);
+
+ if (Main.netMode != NetmodeID.SinglePlayer)
+ {
+ NetMessage.SendData(MessageID.SyncProjectile, number: index);
+ }
+ return index;
+ }
+
+ ///
+ /// If you need immediate sync, usually necessary outside of Projectile.AI (as netUpdate is set to false before it's invoked)
+ ///
+ ///
+ public static void NetSync(this Projectile projectile)
+ {
+ if (Main.myPlayer == projectile.owner)
+ {
+ NetMessage.SendData(MessageID.SyncProjectile, -1, -1, null, projectile.whoAmI);
+ projectile.netSpam = 0;
+ projectile.netUpdate = false;
+ projectile.netUpdate2 = false;
+ }
+ }
+
+ //Clone from vanilla since it's private
+ private static void FindBannerToAssociateTo(IEntitySource spawnSource, Projectile next)
+ {
+ EntitySource_Parent entitySource_Parent = spawnSource as EntitySource_Parent;
+ if (entitySource_Parent == null)
+ {
+ return;
+ }
+
+ Projectile projectile = entitySource_Parent.Entity as Projectile;
+ if (projectile != null)
+ {
+ next.bannerIdToRespondTo = projectile.bannerIdToRespondTo;
+ return;
+ }
+
+ NPC nPC = entitySource_Parent.Entity as NPC;
+ if (nPC != null)
+ {
+ next.bannerIdToRespondTo = Item.NPCtoBanner(nPC.BannerID());
+ }
+ }
+
+ //Clone from tml since it's private, may need updates, keep an eye out
+ private static void HandlePlayerStatModifiers(IEntitySource spawnSource, Projectile projectile)
+ {
+ if (spawnSource is EntitySource_ItemUse itemUseSource && itemUseSource.Entity is Player player)
+ {
+ projectile.CritChance += player.GetWeaponCrit(itemUseSource.Item);
+ projectile.ArmorPenetration += player.GetWeaponArmorPenetration(itemUseSource.Item);
+ }
+ }
+
+ ///
+ /// Alternative, static version of npc.DropItemInstanced. Checks the playerCondition delegate before syncing/spawning the item
+ ///
+ public static void DropItemInstanced(NPC npc, Vector2 Position, Vector2 HitboxSize, int itemType, int itemStack = 1, Func condition = null, bool interactionRequired = true)
+ {
+ if (itemType > 0)
+ {
+ if (Main.netMode == NetmodeID.Server)
+ {
+ int item = Item.NewItem(npc.GetItemSource_Loot(), (int)Position.X, (int)Position.Y, (int)HitboxSize.X, (int)HitboxSize.Y, itemType, itemStack, true);
+ Main.timeItemSlotCannotBeReusedFor[item] = 54000;
+ for (int p = 0; p < Main.maxPlayers; p++)
+ {
+ if (Main.player[p].active && (npc.playerInteraction[p] || !interactionRequired))
+ {
+ if (condition != null && condition(npc, Main.player[p]) ||
+ condition == null)
+ NetMessage.SendData(MessageID.InstancedItem, p, -1, null, item);
+ }
+ }
+ Main.item[item].active = false;
+ }
+ else if (Main.netMode == NetmodeID.SinglePlayer)
+ {
+ if (condition != null && condition(npc, Main.LocalPlayer) ||
+ condition == null)
+ Item.NewItem(npc.GetItemSource_Loot(), (int)Position.X, (int)Position.Y, (int)HitboxSize.X, (int)HitboxSize.Y, itemType, itemStack);
+ }
+ //npc.value = 0f;
+ }
+ }
+
+ ///
+ /// Draws the _Highlight texture of this tile if it exists and can be drawn
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// Color the tile is drawn with
+ ///
+ ///
+ public static void DrawTileHighlight(SpriteBatch spriteBatch, int i, int j, int type, Color color, Vector2 pos, Rectangle frame)
+ {
+ if (TileID.Sets.HasOutlines[type] && Collision.InTileBounds(i, j, Main.TileInteractionLX, Main.TileInteractionLY, Main.TileInteractionHX, Main.TileInteractionHY) && Main.SmartInteractTileCoords.Contains(new Point(i, j)))
+ {
+ int average = (int)color.GetAverage();
+ bool selected = false;
+ if (Main.SmartInteractTileCoordsSelected.Contains(new Point(i, j)))
+ {
+ selected = true;
+ }
+ if (average > 10)
+ {
+ Texture2D outlineTexture = TextureAssets.HighlightMask[type].Value;
+ Color outlineColor;
+ if (selected)
+ {
+ outlineColor = new Color(average, average, average / 3, average);
+ }
+ else
+ {
+ outlineColor = new Color(average / 2, average / 2, average / 2, average);
+ }
+
+ if (outlineTexture != null)
+ {
+ spriteBatch.Draw(outlineTexture, pos, frame, outlineColor, 0f, default(Vector2), 1f, SpriteEffects.None, 0f);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Modify the velocity (that has the direction from position to targetPos) of something that is affected by gravity in a way that it will still reach targetPos
+ ///
Note: This might increase the length of velocity depending on how much correction was needed, use offsetCap to limit it.
+ ///
+ /// Starting location
+ /// Target location
+ /// Gravity applied to velocity.Y
+ /// Starting velocity
+ /// Amount of initial ticks that velocity should NOT be updated by gravity
+ /// Terminal velocity.Y
+ /// Multiplier for final correction to velocity. 1f == perfect, 0f == none
+ public static void ModifyVelocityForGravity(Vector2 position, Vector2 targetPos, in float gravity, ref Vector2 velocity, int ticksWithoutGravity = 0, float terminalCap = 16f, float factor = 1f, float offsetCap = 2.5f)
+ {
+ //Need to make the velocity + gravity hit targetPos.Y
+ //Keep horizontal velocity, correct vertical velocity to account for gravity
+
+ Vector2 toTarget = targetPos - position;
+ int ticksToReachX = (int)(toTarget.X / velocity.X); //"Simulated time" it takes to reach target
+
+ float traversedDistanceY = 0;
+ float traversedDistanceYNoGravity = 0;
+ float velocityYWithGravity = velocity.Y;
+ for (int i = 0; i < ticksToReachX; i++)
+ {
+ if (i >= ticksWithoutGravity)
+ {
+ velocityYWithGravity += gravity;
+ if (velocityYWithGravity > terminalCap)
+ {
+ velocityYWithGravity = terminalCap;
+ }
+ }
+ traversedDistanceY += velocityYWithGravity;
+ traversedDistanceYNoGravity += velocity.Y;
+ }
+
+ float offsetY = traversedDistanceY - traversedDistanceYNoGravity;
+
+ float velocityYOffset = offsetY / ticksToReachX;
+
+ velocityYOffset = Math.Min(velocityYOffset, offsetCap);
+
+ velocity.Y -= factor * velocityYOffset;
+ }
+ }
}
diff --git a/Base/Data/ModTypeIdentity.cs b/Base/Data/ModTypeIdentity.cs
index d116a8c9..b39203d9 100644
--- a/Base/Data/ModTypeIdentity.cs
+++ b/Base/Data/ModTypeIdentity.cs
@@ -7,17 +7,17 @@ namespace AssortedCrazyThings.Base.Data
///
You will need "public static readonly Func DESERIALIZER = Load;" in inheriting classes
///
public abstract class ModTypeIdentity : TagSerializable
- {
+ {
public string ModName { get; private set; }
public string Name { get; private set; }
- public ModTypeIdentity(string modName, string name)
- {
+ public ModTypeIdentity(string modName, string name)
+ {
ModName = modName;
Name = name;
- }
+ }
- public override string ToString() => "ModName: " + ModName + "; Name: " + Name;
+ public override string ToString() => "ModName: " + ModName + "; Name: " + Name;
public virtual TagCompound SerializeData()
{
diff --git a/Base/Data/PetAccessoryIdentity.cs b/Base/Data/PetAccessoryIdentity.cs
index 98afb8fd..7fb6e80b 100644
--- a/Base/Data/PetAccessoryIdentity.cs
+++ b/Base/Data/PetAccessoryIdentity.cs
@@ -3,12 +3,12 @@
namespace AssortedCrazyThings.Base.Data
{
- public class PetAccessoryIdentity : ModTypeIdentity, TagSerializable
- {
+ public class PetAccessoryIdentity : ModTypeIdentity, TagSerializable
+ {
public byte AltTextureIndex { get; set; }
- public PetAccessoryIdentity(string modName, string name, byte altTextureIndex) : base(modName, name)
- {
+ public PetAccessoryIdentity(string modName, string name, byte altTextureIndex) : base(modName, name)
+ {
AltTextureIndex = altTextureIndex;
}
diff --git a/Base/DrawLayers/CrazyBundleOfAssortedBalloonsLayer.cs b/Base/DrawLayers/CrazyBundleOfAssortedBalloonsLayer.cs
index 483c2726..3646dba0 100644
--- a/Base/DrawLayers/CrazyBundleOfAssortedBalloonsLayer.cs
+++ b/Base/DrawLayers/CrazyBundleOfAssortedBalloonsLayer.cs
@@ -9,69 +9,69 @@
namespace AssortedCrazyThings.Base.DrawLayers
{
- [Content(ContentType.Accessories)]
- public class CrazyBundleOfAssortedBalloonsLayer : AssPlayerLayer
- {
- private Asset balloonTexture;
+ [Content(ContentType.Accessories)]
+ public class CrazyBundleOfAssortedBalloonsLayer : AssPlayerLayer
+ {
+ private Asset balloonTexture;
- public override void Load()
- {
- if (!Main.dedServ)
- {
- balloonTexture = Mod.Assets.Request("Items/Accessories/Useful/CrazyBundleOfAssortedBalloons_Balloon_Proper");
- }
- }
+ public override void Load()
+ {
+ if (!Main.dedServ)
+ {
+ balloonTexture = Mod.Assets.Request("Items/Accessories/Useful/CrazyBundleOfAssortedBalloons_Balloon_Proper");
+ }
+ }
- public override void Unload()
- {
- balloonTexture = null;
- }
+ public override void Unload()
+ {
+ balloonTexture = null;
+ }
- public override bool GetDefaultVisibility(PlayerDrawSet drawInfo)
- {
- Player drawPlayer = drawInfo.drawPlayer;
- if (drawInfo.shadow != 0f || drawPlayer.dead)
- {
- return false;
- }
+ public override bool GetDefaultVisibility(PlayerDrawSet drawInfo)
+ {
+ Player drawPlayer = drawInfo.drawPlayer;
+ if (drawInfo.shadow != 0f || drawPlayer.dead)
+ {
+ return false;
+ }
- return drawPlayer.balloon == Mod.GetEquipSlot(nameof(CrazyBundleOfAssortedBalloons), EquipType.Balloon);
- }
+ return drawPlayer.balloon == Mod.GetEquipSlot(nameof(CrazyBundleOfAssortedBalloons), EquipType.Balloon);
+ }
- public override Position GetDefaultPosition()
- {
- return new AfterParent(PlayerDrawLayers.BalloonAcc);
- }
+ public override Position GetDefaultPosition()
+ {
+ return new AfterParent(PlayerDrawLayers.BalloonAcc);
+ }
- protected override void Draw(ref PlayerDrawSet drawInfo)
- {
- //Since it's supposed to replace the Autoload texture, the regular _Balloon is just blank
- Player drawPlayer = drawInfo.drawPlayer;
+ protected override void Draw(ref PlayerDrawSet drawInfo)
+ {
+ //Since it's supposed to replace the Autoload texture, the regular _Balloon is just blank
+ Player drawPlayer = drawInfo.drawPlayer;
- int frameY = (Main.hasFocus && (!Main.ingameOptionsWindow || !Main.autoPause)) ? (DateTime.Now.Millisecond % 800 / 200) : 0;
- Vector2 handOffset = Main.OffsetsPlayerOffhand[drawPlayer.bodyFrame.Y / 56];
- if (drawPlayer.direction != 1)
- {
- handOffset.X = drawPlayer.width - handOffset.X;
- }
+ int frameY = (Main.hasFocus && (!Main.ingameOptionsWindow || !Main.autoPause)) ? (DateTime.Now.Millisecond % 800 / 200) : 0;
+ Vector2 handOffset = Main.OffsetsPlayerOffhand[drawPlayer.bodyFrame.Y / 56];
+ if (drawPlayer.direction != 1)
+ {
+ handOffset.X = drawPlayer.width - handOffset.X;
+ }
- if (drawPlayer.gravDir != 1f)
- {
- handOffset.Y -= drawPlayer.height;
- }
+ if (drawPlayer.gravDir != 1f)
+ {
+ handOffset.Y -= drawPlayer.height;
+ }
- Vector2 offset = new Vector2(0f, 8f) + new Vector2(0f, 6f);
- offset += new Vector2(0f, -drawPlayer.bodyFrame.Height / 3); //Added so it's higher
- Vector2 position = drawInfo.Position - Main.screenPosition + handOffset * new Vector2(1f, drawPlayer.gravDir) + new Vector2(0f, drawPlayer.height - drawPlayer.bodyFrame.Height) + offset;
- position = position.Floor();
+ Vector2 offset = new Vector2(0f, 8f) + new Vector2(0f, 6f);
+ offset += new Vector2(0f, -drawPlayer.bodyFrame.Height / 3); //Added so it's higher
+ Vector2 position = drawInfo.Position - Main.screenPosition + handOffset * new Vector2(1f, drawPlayer.gravDir) + new Vector2(0f, drawPlayer.height - drawPlayer.bodyFrame.Height) + offset;
+ position = position.Floor();
- Rectangle frame = balloonTexture.Frame(1, 4, 0, frameY);
- Vector2 origin = new Vector2(26 + drawPlayer.direction * 4, 28f + drawPlayer.gravDir * 6f);
- DrawData data = new DrawData(balloonTexture.Value, position, frame, drawInfo.colorArmorBody, drawPlayer.bodyRotation, origin, 1f, drawInfo.playerEffect, 0)
- {
- shader = drawInfo.cBalloon
- };
- drawInfo.DrawDataCache.Add(data);
- }
- }
+ Rectangle frame = balloonTexture.Frame(1, 4, 0, frameY);
+ Vector2 origin = new Vector2(26 + drawPlayer.direction * 4, 28f + drawPlayer.gravDir * 6f);
+ DrawData data = new DrawData(balloonTexture.Value, position, frame, drawInfo.colorArmorBody, drawPlayer.bodyRotation, origin, 1f, drawInfo.playerEffect, 0)
+ {
+ shader = drawInfo.cBalloon
+ };
+ drawInfo.DrawDataCache.Add(data);
+ }
+ }
}
diff --git a/Base/DrawLayers/HarvesterWingsLayer.cs b/Base/DrawLayers/HarvesterWingsLayer.cs
index 5b57cf3b..28f0abca 100644
--- a/Base/DrawLayers/HarvesterWingsLayer.cs
+++ b/Base/DrawLayers/HarvesterWingsLayer.cs
@@ -8,88 +8,88 @@
namespace AssortedCrazyThings.Base.DrawLayers
{
- [Content(ContentType.Bosses)]
- public class HarvesterWingsLayer : AssPlayerLayer
- {
- private Asset wingAsset;
- private Asset glowAsset;
+ [Content(ContentType.Bosses)]
+ public class HarvesterWingsLayer : AssPlayerLayer
+ {
+ private Asset wingAsset;
+ private Asset glowAsset;
- public override void Load()
- {
- if (!Main.dedServ)
- {
- string common = "Items/Accessories/Useful/HarvesterWings_Wings";
- wingAsset = Mod.Assets.Request(common + "_Proper");
- glowAsset = Mod.Assets.Request(common + "_Glowmask");
- }
- }
+ public override void Load()
+ {
+ if (!Main.dedServ)
+ {
+ string common = "Items/Accessories/Useful/HarvesterWings_Wings";
+ wingAsset = Mod.Assets.Request(common + "_Proper");
+ glowAsset = Mod.Assets.Request(common + "_Glowmask");
+ }
+ }
- public override void Unload()
- {
- wingAsset = null;
- glowAsset = null;
- }
+ public override void Unload()
+ {
+ wingAsset = null;
+ glowAsset = null;
+ }
- public override bool GetDefaultVisibility(PlayerDrawSet drawInfo)
- {
- Player drawPlayer = drawInfo.drawPlayer;
- if (drawPlayer.dead)
- {
- return false;
- }
+ public override bool GetDefaultVisibility(PlayerDrawSet drawInfo)
+ {
+ Player drawPlayer = drawInfo.drawPlayer;
+ if (drawPlayer.dead)
+ {
+ return false;
+ }
- return drawInfo.drawPlayer.wings == Mod.GetEquipSlot(nameof(HarvesterWings), EquipType.Wings);
- }
+ return drawInfo.drawPlayer.wings == Mod.GetEquipSlot(nameof(HarvesterWings), EquipType.Wings);
+ }
- public override Position GetDefaultPosition()
- {
- return new AfterParent(PlayerDrawLayers.Wings);
- }
+ public override Position GetDefaultPosition()
+ {
+ return new AfterParent(PlayerDrawLayers.Wings);
+ }
- protected override void Draw(ref PlayerDrawSet drawInfo)
- {
- Player drawPlayer = drawInfo.drawPlayer;
+ protected override void Draw(ref PlayerDrawSet drawInfo)
+ {
+ Player drawPlayer = drawInfo.drawPlayer;
- Asset asset = wingAsset;
+ Asset asset = wingAsset;
- Vector2 directions = drawPlayer.Directions;
- Vector2 offset = new Vector2(0f, 7f);
+ Vector2 directions = drawPlayer.Directions;
+ Vector2 offset = new Vector2(0f, 7f);
- //bonus bobbing
- Rectangle bobFrame = drawInfo.drawPlayer.bodyFrame;
- offset += Main.OffsetsPlayerHeadgear[bobFrame.Y / bobFrame.Height] * drawPlayer.gravDir;
+ //bonus bobbing
+ Rectangle bobFrame = drawInfo.drawPlayer.bodyFrame;
+ offset += Main.OffsetsPlayerHeadgear[bobFrame.Y / bobFrame.Height] * drawPlayer.gravDir;
- Vector2 position = drawInfo.Position - Main.screenPosition + new Vector2(drawPlayer.width / 2, drawPlayer.height - drawPlayer.bodyFrame.Height / 2) + offset;
+ Vector2 position = drawInfo.Position - Main.screenPosition + new Vector2(drawPlayer.width / 2, drawPlayer.height - drawPlayer.bodyFrame.Height / 2) + offset;
- int num11 = -5;
- int num12 = -7;
- int numFrames = HarvesterWings.NumFrames;
+ int num11 = -5;
+ int num12 = -7;
+ int numFrames = HarvesterWings.NumFrames;
- Color color = drawInfo.colorArmorBody;
+ Color color = drawInfo.colorArmorBody;
- position += new Vector2(num12 - 9, num11 + 2) * directions;
- position = position.Floor();
- int totalHeight = asset.Height();
- int totalWidth = asset.Width();
- Rectangle frame = new Rectangle(0, totalHeight / numFrames * drawPlayer.wingFrame, totalWidth, totalHeight / numFrames);
- Vector2 origin = new Vector2(totalWidth / 2, totalHeight / numFrames / 2);
- float bodyRotation = drawPlayer.bodyRotation;
- SpriteEffects playerEffect = drawInfo.playerEffect;
- Texture2D texture = asset.Value;
- DrawData data = new DrawData(texture, position, frame, color, (float)bodyRotation, origin, 1f, playerEffect, 0)
- {
- shader = drawInfo.cWings
- };
- drawInfo.DrawDataCache.Add(data);
+ position += new Vector2(num12 - 9, num11 + 2) * directions;
+ position = position.Floor();
+ int totalHeight = asset.Height();
+ int totalWidth = asset.Width();
+ Rectangle frame = new Rectangle(0, totalHeight / numFrames * drawPlayer.wingFrame, totalWidth, totalHeight / numFrames);
+ Vector2 origin = new Vector2(totalWidth / 2, totalHeight / numFrames / 2);
+ float bodyRotation = drawPlayer.bodyRotation;
+ SpriteEffects playerEffect = drawInfo.playerEffect;
+ Texture2D texture = asset.Value;
+ DrawData data = new DrawData(texture, position, frame, color, (float)bodyRotation, origin, 1f, playerEffect, 0)
+ {
+ shader = drawInfo.cWings
+ };
+ drawInfo.DrawDataCache.Add(data);
- asset = glowAsset;
- texture = asset.Value;
- color = drawPlayer.GetImmuneAlpha(Color.White, drawInfo.shadow);
- data = new DrawData(texture, position, frame, color, (float)bodyRotation, origin, 1f, playerEffect, 0)
- {
- shader = drawInfo.cWings
- };
- drawInfo.DrawDataCache.Add(data);
- }
- }
+ asset = glowAsset;
+ texture = asset.Value;
+ color = drawPlayer.GetImmuneAlpha(Color.White, drawInfo.shadow);
+ data = new DrawData(texture, position, frame, color, (float)bodyRotation, origin, 1f, playerEffect, 0)
+ {
+ shader = drawInfo.cWings
+ };
+ drawInfo.DrawDataCache.Add(data);
+ }
+ }
}
diff --git a/Base/DrawLayers/SlimeHandlerKnapsackLayer.cs b/Base/DrawLayers/SlimeHandlerKnapsackLayer.cs
index dab41fe9..93a90a47 100644
--- a/Base/DrawLayers/SlimeHandlerKnapsackLayer.cs
+++ b/Base/DrawLayers/SlimeHandlerKnapsackLayer.cs
@@ -8,52 +8,52 @@
namespace AssortedCrazyThings.Base.DrawLayers
{
- [Content(ContentType.Weapons)]
- public class SlimeHandlerKnapsackLayer : AssPlayerLayer
- {
- private Asset knapsackTexture;
-
- public override void Load()
- {
- if (!Main.dedServ)
- {
- knapsackTexture = Mod.Assets.Request("Items/Weapons/SlimeHandlerKnapsack_Back");
- }
- }
-
- public override void Unload()
- {
- knapsackTexture = null;
- }
-
- public override bool GetDefaultVisibility(PlayerDrawSet drawInfo)
- {
- Player drawPlayer = drawInfo.drawPlayer;
- if (drawInfo.shadow != 0f || drawPlayer.dead)
- {
- return false;
- }
-
- return (drawPlayer.wings == 0 || drawPlayer.velocity.Y == 0f) && drawInfo.drawPlayer.HeldItem?.type == ModContent.ItemType();
- }
-
- public override Position GetDefaultPosition()
- {
- return new AfterParent(PlayerDrawLayers.Backpacks);
- }
-
- protected override void Draw(ref PlayerDrawSet drawInfo)
- {
- Player drawPlayer = drawInfo.drawPlayer;
-
- Texture2D texture = knapsackTexture.Value;
-
- Vector2 offset = new Vector2(0f, 8f);
- Vector2 position = drawInfo.Position - Main.screenPosition + drawPlayer.bodyPosition + new Vector2(drawPlayer.width / 2, drawPlayer.height - drawPlayer.bodyFrame.Height / 2) + new Vector2(0f, -4f) + offset;
- position = position.Floor();
-
- DrawData drawData = new DrawData(texture, position, drawPlayer.bodyFrame, drawInfo.colorArmorBody, drawPlayer.bodyRotation, drawInfo.bodyVect, 1f, drawInfo.playerEffect, 0);
- drawInfo.DrawDataCache.Add(drawData);
- }
- }
+ [Content(ContentType.Weapons)]
+ public class SlimeHandlerKnapsackLayer : AssPlayerLayer
+ {
+ private Asset knapsackTexture;
+
+ public override void Load()
+ {
+ if (!Main.dedServ)
+ {
+ knapsackTexture = Mod.Assets.Request("Items/Weapons/SlimeHandlerKnapsack_Back");
+ }
+ }
+
+ public override void Unload()
+ {
+ knapsackTexture = null;
+ }
+
+ public override bool GetDefaultVisibility(PlayerDrawSet drawInfo)
+ {
+ Player drawPlayer = drawInfo.drawPlayer;
+ if (drawInfo.shadow != 0f || drawPlayer.dead)
+ {
+ return false;
+ }
+
+ return (drawPlayer.wings == 0 || drawPlayer.velocity.Y == 0f) && drawInfo.drawPlayer.HeldItem?.type == ModContent.ItemType();
+ }
+
+ public override Position GetDefaultPosition()
+ {
+ return new AfterParent(PlayerDrawLayers.Backpacks);
+ }
+
+ protected override void Draw(ref PlayerDrawSet drawInfo)
+ {
+ Player drawPlayer = drawInfo.drawPlayer;
+
+ Texture2D texture = knapsackTexture.Value;
+
+ Vector2 offset = new Vector2(0f, 8f);
+ Vector2 position = drawInfo.Position - Main.screenPosition + drawPlayer.bodyPosition + new Vector2(drawPlayer.width / 2, drawPlayer.height - drawPlayer.bodyFrame.Height / 2) + new Vector2(0f, -4f) + offset;
+ position = position.Floor();
+
+ DrawData drawData = new DrawData(texture, position, drawPlayer.bodyFrame, drawInfo.colorArmorBody, drawPlayer.bodyRotation, drawInfo.bodyVect, 1f, drawInfo.playerEffect, 0);
+ drawInfo.DrawDataCache.Add(drawData);
+ }
+ }
}
diff --git a/Base/DrawLayers/SwarmDrawLayer.cs b/Base/DrawLayers/SwarmDrawLayer.cs
index e41a08ea..6f9a34fb 100644
--- a/Base/DrawLayers/SwarmDrawLayer.cs
+++ b/Base/DrawLayers/SwarmDrawLayer.cs
@@ -6,64 +6,64 @@
namespace AssortedCrazyThings.Base.DrawLayers
{
- ///
- /// These layers have to get created manually, they are loaded in SwarmDrawSet
- ///
- [Autoload(false)] //AssPlayerLayer already has false, but just for clarity
- public sealed class SwarmDrawLayer : AssPlayerLayer
- {
- private readonly string name;
- public override string Name => name;
+ ///
+ /// These layers have to get created manually, they are loaded in SwarmDrawSet
+ ///
+ [Autoload(false)] //AssPlayerLayer already has false, but just for clarity
+ public sealed class SwarmDrawLayer : AssPlayerLayer
+ {
+ private readonly string name;
+ public override string Name => name;
- ///
- /// No parameterless constructor needed since Autoload is false
- ///
- public SwarmDrawLayer(string name, bool front, Func getDrawSet)
- {
- //Important to assign name based on the instance so they won't count as duplicates
- this.name = $"{name}_{(front ? "Front" : "Back")}";
- this.front = front;
- this.getDrawSet = getDrawSet;
- }
+ ///
+ /// No parameterless constructor needed since Autoload is false
+ ///
+ public SwarmDrawLayer(string name, bool front, Func getDrawSet)
+ {
+ //Important to assign name based on the instance so they won't count as duplicates
+ this.name = $"{name}_{(front ? "Front" : "Back")}";
+ this.front = front;
+ this.getDrawSet = getDrawSet;
+ }
- public bool front;
+ public bool front;
- public Func getDrawSet;
+ public Func getDrawSet;
- public sealed override bool GetDefaultVisibility(PlayerDrawSet drawInfo)
- {
- Player drawPlayer = drawInfo.drawPlayer;
- if (getDrawSet == null || drawInfo.shadow != 0f || drawPlayer.dead)
- {
- return false;
- }
+ public sealed override bool GetDefaultVisibility(PlayerDrawSet drawInfo)
+ {
+ Player drawPlayer = drawInfo.drawPlayer;
+ if (getDrawSet == null || drawInfo.shadow != 0f || drawPlayer.dead)
+ {
+ return false;
+ }
- return getDrawSet.Invoke(drawPlayer.GetModPlayer())?.Active ?? false;
- }
+ return getDrawSet.Invoke(drawPlayer.GetModPlayer())?.Active ?? false;
+ }
- public sealed override Position GetDefaultPosition()
- {
- return front ? new AfterParent(PlayerDrawLayers.BeetleBuff) : new BeforeParent(PlayerDrawLayers.JimsCloak);
- }
+ public sealed override Position GetDefaultPosition()
+ {
+ return front ? new AfterParent(PlayerDrawLayers.BeetleBuff) : new BeforeParent(PlayerDrawLayers.JimsCloak);
+ }
- protected sealed override void Draw(ref PlayerDrawSet drawInfo)
- {
- Player drawPlayer = drawInfo.drawPlayer;
+ protected sealed override void Draw(ref PlayerDrawSet drawInfo)
+ {
+ Player drawPlayer = drawInfo.drawPlayer;
- var set = getDrawSet?.Invoke(drawInfo.drawPlayer.GetModPlayer());
+ var set = getDrawSet?.Invoke(drawInfo.drawPlayer.GetModPlayer());
- if (set == null || !set.Active)
- {
- return;
- }
+ if (set == null || !set.Active)
+ {
+ return;
+ }
- //First draw the trails
- var datas = set.TrailToDrawDatas(drawInfo, front);
- drawInfo.DrawDataCache.AddRange(datas);
+ //First draw the trails
+ var datas = set.TrailToDrawDatas(drawInfo, front);
+ drawInfo.DrawDataCache.AddRange(datas);
- //Then the actual thing
- datas = set.ToDrawDatas(drawInfo, front);
- drawInfo.DrawDataCache.AddRange(datas);
- }
- }
+ //Then the actual thing
+ datas = set.ToDrawDatas(drawInfo, front);
+ drawInfo.DrawDataCache.AddRange(datas);
+ }
+ }
}
diff --git a/Base/Handlers/SpawnedNPCHandler/SpawnedNPCSystem.cs b/Base/Handlers/SpawnedNPCHandler/SpawnedNPCSystem.cs
index 6d30bfe2..046e91b3 100644
--- a/Base/Handlers/SpawnedNPCHandler/SpawnedNPCSystem.cs
+++ b/Base/Handlers/SpawnedNPCHandler/SpawnedNPCSystem.cs
@@ -1,56 +1,55 @@
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using Terraria;
-using Terraria.ModLoader;
namespace AssortedCrazyThings.Base.Handlers.SpawnedNPCHandler
{
- [Content(ConfigurationSystem.AllFlags, needsAllToFilter: true)]
- internal class SpawnedNPCSystem : AssSystem
- {
- private int prevCount;
- private HashSet prevIdentities;
+ [Content(ConfigurationSystem.AllFlags, needsAllToFilter: true)]
+ internal class SpawnedNPCSystem : AssSystem
+ {
+ private int prevCount;
+ private HashSet prevIdentities;
- public delegate void SpawnedNPCDelegate(NPC npc);
- public static event SpawnedNPCDelegate OnSpawnedNPC;
+ public delegate void SpawnedNPCDelegate(NPC npc);
+ public static event SpawnedNPCDelegate OnSpawnedNPC;
- public override void OnWorldLoad()
- {
- prevCount = Main.maxNPCs; //Set to max so that on first tick, if NPCs already exist, it doesn't trigger
- prevIdentities = new HashSet();
- }
+ public override void OnWorldLoad()
+ {
+ prevCount = Main.maxNPCs; //Set to max so that on first tick, if NPCs already exist, it doesn't trigger
+ prevIdentities = new HashSet();
+ }
- public override void Unload()
- {
- prevIdentities = null;
- }
+ public override void Unload()
+ {
+ prevIdentities = null;
+ }
- public override void PostUpdateNPCs()
- {
- //Runs on all sides
- int curCount = 0;
- HashSet currIdentities = new HashSet();
- for (int i = 0; i < Main.maxNPCs; i++)
- {
- NPC npc = Main.npc[i];
- if (npc.active)
- {
- curCount++;
- currIdentities.Add(new Point(i, npc.type));
- }
- }
+ public override void PostUpdateNPCs()
+ {
+ //Runs on all sides
+ int curCount = 0;
+ HashSet currIdentities = new HashSet();
+ for (int i = 0; i < Main.maxNPCs; i++)
+ {
+ NPC npc = Main.npc[i];
+ if (npc.active)
+ {
+ curCount++;
+ currIdentities.Add(new Point(i, npc.type));
+ }
+ }
- if (prevCount < curCount)
- {
- currIdentities.ExceptWith(prevIdentities); //Multiple can spawn in the same tick
- foreach (var identity in currIdentities)
- {
- OnSpawnedNPC?.Invoke(Main.npc[identity.X]);
- }
- }
+ if (prevCount < curCount)
+ {
+ currIdentities.ExceptWith(prevIdentities); //Multiple can spawn in the same tick
+ foreach (var identity in currIdentities)
+ {
+ OnSpawnedNPC?.Invoke(Main.npc[identity.X]);
+ }
+ }
- prevCount = curCount;
- prevIdentities = currIdentities;
- }
- }
+ prevCount = curCount;
+ prevIdentities = currIdentities;
+ }
+ }
}
diff --git a/Base/Handlers/UnreplaceableMinionWith0SlotsHandler/UnreplaceableMinionWith0SlotsModPlayer.cs b/Base/Handlers/UnreplaceableMinionWith0SlotsHandler/UnreplaceableMinionWith0SlotsModPlayer.cs
index a4234606..f582401d 100644
--- a/Base/Handlers/UnreplaceableMinionWith0SlotsHandler/UnreplaceableMinionWith0SlotsModPlayer.cs
+++ b/Base/Handlers/UnreplaceableMinionWith0SlotsHandler/UnreplaceableMinionWith0SlotsModPlayer.cs
@@ -1,5 +1,4 @@
using Terraria;
-using Terraria.ModLoader;
namespace AssortedCrazyThings.Base.Handlers.UnreplaceableMinionWith0SlotsHandler
{
diff --git a/Base/Handlers/UnreplaceableMinionWith0SlotsHandler/UnreplaceableMinionWith0SlotsSystem.cs b/Base/Handlers/UnreplaceableMinionWith0SlotsHandler/UnreplaceableMinionWith0SlotsSystem.cs
index 32863533..68efbcdb 100644
--- a/Base/Handlers/UnreplaceableMinionWith0SlotsHandler/UnreplaceableMinionWith0SlotsSystem.cs
+++ b/Base/Handlers/UnreplaceableMinionWith0SlotsHandler/UnreplaceableMinionWith0SlotsSystem.cs
@@ -2,30 +2,30 @@
namespace AssortedCrazyThings.Base.Handlers.UnreplaceableMinionWith0SlotsHandler
{
- //Taken with permission from billybobmcbo
- [Content(ConfigurationSystem.AllFlags, needsAllToFilter: true)]
- public class UnreplaceableMinionWith0SlotsSystem : AssSystem
+ //Taken with permission from billybobmcbo
+ [Content(ConfigurationSystem.AllFlags, needsAllToFilter: true)]
+ public class UnreplaceableMinionWith0SlotsSystem : AssSystem
{
private static HashSet Minions;
- public static bool Add(int type)
- {
- return Minions.Add(type);
- }
+ public static bool Add(int type)
+ {
+ return Minions.Add(type);
+ }
- public static bool Exists(int type)
- {
- return Minions.Contains(type);
- }
+ public static bool Exists(int type)
+ {
+ return Minions.Contains(type);
+ }
- public override void OnModLoad()
- {
+ public override void OnModLoad()
+ {
Minions = new HashSet();
- }
+ }
- public override void Unload()
- {
+ public override void Unload()
+ {
Minions = null;
}
- }
+ }
}
diff --git a/Base/ModSupport/OtherModCalls.cs b/Base/ModSupport/OtherModCalls.cs
index d9d9c40e..8f5c09cd 100644
--- a/Base/ModSupport/OtherModCalls.cs
+++ b/Base/ModSupport/OtherModCalls.cs
@@ -13,30 +13,30 @@
namespace AssortedCrazyThings.Base.ModSupport
{
- [Content(ConfigurationSystem.AllFlags, needsAllToFilter: true)]
- public class OtherModCalls : AssSystem
- {
- public override void PostSetupContent()
- {
- //https://forums.terraria.org/index.php?threads/boss-checklist-in-game-progression-checklist.50668/
- if (ContentConfig.Instance.Bosses && ModLoader.TryGetMod("BossChecklist", out Mod bossChecklist))
- {
- //5.1f means just after skeletron
- if (bossChecklist.Version >= new Version(1, 3, 1))
- {
- List collection = new List()
- {
- ModContent.ItemType(),
- ModContent.ItemType(),
- ModContent.ItemType(),
- ModContent.ItemType()
- };
+ [Content(ConfigurationSystem.AllFlags, needsAllToFilter: true)]
+ public class OtherModCalls : AssSystem
+ {
+ public override void PostSetupContent()
+ {
+ //https://forums.terraria.org/index.php?threads/boss-checklist-in-game-progression-checklist.50668/
+ if (ContentConfig.Instance.Bosses && ModLoader.TryGetMod("BossChecklist", out Mod bossChecklist))
+ {
+ //5.1f means just after skeletron
+ if (bossChecklist.Version >= new Version(1, 3, 1))
+ {
+ List collection = new List()
+ {
+ ModContent.ItemType(),
+ ModContent.ItemType(),
+ ModContent.ItemType(),
+ ModContent.ItemType()
+ };
- int summonItem = ModContent.ItemType();
+ int summonItem = ModContent.ItemType();
- //TODO harvester, include 15 x ModContent.ItemType() in loot but dont spawn it
+ //TODO harvester, include 15 x ModContent.ItemType() in loot but dont spawn it
- /*
+ /*
* "AddBoss",
args[1] as Mod, // Mod
args[2] as string, // Boss Name
@@ -50,57 +50,57 @@ public override void PostSetupContent()
InterpretObjectAsStringFunction(args[10]), // Despawn message
args[11] as Action // Custom Drawing
*/
- bossChecklist.Call(
- "AddBoss",
- Mod,
- Harvester.name,
- AssortedCrazyThings.harvester,
- 5.1f,
- (Func)(() => AssWorld.downedHarvester),
- (Func)(() => true),
- collection,
- summonItem,
- $"Enter the dungeon for the first time, or use a [i:{summonItem}] in the dungeon"
- );
- }
- }
+ bossChecklist.Call(
+ "AddBoss",
+ Mod,
+ Harvester.name,
+ AssortedCrazyThings.harvester,
+ 5.1f,
+ (Func)(() => AssWorld.downedHarvester),
+ (Func)(() => true),
+ collection,
+ summonItem,
+ $"Enter the dungeon for the first time, or use a [i:{summonItem}] in the dungeon"
+ );
+ }
+ }
- if (ModLoader.TryGetMod("SummonersAssociation", out Mod summonersAssociation) && summonersAssociation.Version > new Version(0, 4, 1))
- {
- if (ContentConfig.Instance.Bosses)
- {
- int soulBuff = ModContent.BuffType();
- summonersAssociation.Call("AddMinionInfo", ModContent.ItemType(), soulBuff, ModContent.ProjectileType());
+ if (ModLoader.TryGetMod("SummonersAssociation", out Mod summonersAssociation) && summonersAssociation.Version > new Version(0, 4, 1))
+ {
+ if (ContentConfig.Instance.Bosses)
+ {
+ int soulBuff = ModContent.BuffType();
+ summonersAssociation.Call("AddMinionInfo", ModContent.ItemType(), soulBuff, ModContent.ProjectileType());
- summonersAssociation.Call("AddMinionInfo", ModContent.ItemType(), soulBuff, new List
- {
- ModContent.ProjectileType(),
- ModContent.ProjectileType(),
- ModContent.ProjectileType(),
- ModContent.ProjectileType()
- });
- }
+ summonersAssociation.Call("AddMinionInfo", ModContent.ItemType(), soulBuff, new List
+ {
+ ModContent.ProjectileType(),
+ ModContent.ProjectileType(),
+ ModContent.ProjectileType(),
+ ModContent.ProjectileType()
+ });
+ }
- if (ContentConfig.Instance.Weapons)
- {
- List slimes = new List()
- {
- ModContent.ProjectileType(),
- ModContent.ProjectileType(),
- ModContent.ProjectileType(),
- };
-
- summonersAssociation.Call("AddMinionInfo", ModContent.ItemType(), ModContent.BuffType(), slimes);
+ if (ContentConfig.Instance.Weapons)
+ {
+ List slimes = new List