35 Commits

Author SHA1 Message Date
YouHaveTrouble 6f19bfa65f bump version 2026-04-29 22:57:39 +02:00
YouHaveTrouble 7925364a3d actually fix being unable to equip other accessories when ambition was equipped 2026-04-29 22:55:41 +02:00
YouHaveTrouble 1bfc61e5aa attempt to fix ambition accessories blocking other accessories from being equipped 2026-04-29 21:26:30 +02:00
YouHaveTrouble b9fc65dab2 mini reformat 2026-04-29 21:24:08 +02:00
YouHaveTrouble a1cc627246 bump version 2026-04-27 22:00:37 +02:00
YouHaveTrouble af61713ae4 fix desert scourge granting wrong credit id 2026-04-27 21:58:02 +02:00
YouHaveTrouble f208eab5be replace icons for warrior's ambition 2026-01-31 10:39:31 +01:00
YouHaveTrouble 54ae566a89 decide on defense values for calamity evil biome bosses for warrior 2026-01-30 19:16:43 +01:00
YouHaveTrouble 62ae36d4f0 an attempt at increasing melee weapon size 2026-01-30 19:16:17 +01:00
YouHaveTrouble ab37d7e410 fix references to summoner ambition 2026-01-30 18:04:33 +01:00
YouHaveTrouble 4aebc3a261 warrior's ambition item setup and locale 2026-01-28 18:22:14 +01:00
YouHaveTrouble d006a3fbaf add SlyFox to sprite credits 2026-01-27 20:13:11 +01:00
YouHaveTrouble e4a046734e fix running without calamity installed 2026-01-27 20:00:59 +01:00
YouHaveTrouble a40a3b624d bump version 2026-01-27 18:12:05 +01:00
YouHaveTrouble a338e92742 icon and a tooltip line for when ambition is fully realized 2026-01-27 18:10:28 +01:00
YouHaveTrouble a68b762f0a nimbuses spawned by summons are supposed to be friendly 2026-01-26 18:08:53 +01:00
YouHaveTrouble a545325b12 hive mind effect 2026-01-25 15:43:59 +01:00
YouHaveTrouble 09a89e7ed5 perforators bonus 2026-01-25 15:32:10 +01:00
YouHaveTrouble 28f132aca3 gather ideas for perforators and hive mind bonuses 2026-01-13 22:41:37 +01:00
YouHaveTrouble 808ce1ca15 more calamity integration and rebalancing 2026-01-12 18:39:31 +01:00
YouHaveTrouble 27898f341a first successful calamity boss perk integration 2026-01-11 16:48:13 +01:00
YouHaveTrouble 2511d7bfd0 only apply bonus whip damage if eye of cthulhu is killed 2026-01-11 14:47:58 +01:00
YouHaveTrouble c29ac8272f pre-hardmode realization now requires only one evil biome boss 2026-01-10 14:25:43 +01:00
YouHaveTrouble 9e1c05df46 fix typo 2026-01-07 19:15:57 +01:00
YouHaveTrouble 2dd603eb81 more specific types 2026-01-07 19:13:25 +01:00
YouHaveTrouble fff8b5e7f1 configure a code style that is not completely cursed 2026-01-07 19:08:34 +01:00
YouHaveTrouble a945f17711 there are multiple types of squirrels, so allow using all of them to craft summoner's ambition 2026-01-07 15:30:06 +01:00
YouHaveTrouble 9cb093d8df pre-hardmode summoner's ambition 2026-01-04 00:36:55 +01:00
YouHaveTrouble 65690a59f5 test implementation of ambition upgrade system 2026-01-03 03:42:54 +01:00
YouHaveTrouble 8bc637b9b8 fix a typo 2026-01-02 22:08:47 +01:00
YouHaveTrouble e797f803c1 fix calamity toclafane staff recipe requiring 2x souls of light and no souls of night 2026-01-02 20:17:23 +01:00
YouHaveTrouble ab5c5a2d84 bump version 2026-01-02 20:10:27 +01:00
YouHaveTrouble b252a8e3a0 use item groups in recipe and adjust recipe for calamity's altered progression 2026-01-02 19:48:09 +01:00
YouHaveTrouble c82f4648e9 make arcane missle less comically large when dropped 2026-01-02 19:05:06 +01:00
YouHaveTrouble 50d7f8b0d2 adapt ooga booga C# code style 2025-12-22 17:59:47 +01:00
31 changed files with 1114 additions and 218 deletions
+18
View File
@@ -0,0 +1,18 @@
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace YHTMod.Buffs;
public class ShroomGlowDebuff : ModBuff {
public override void SetStaticDefaults() {
Main.debuff[Type] = true;
}
public override void Update(NPC npc, ref int buffIndex) {
if (Main.netMode == NetmodeID.MultiplayerClient || Main.netMode == NetmodeID.SinglePlayer) { // client-only
Lighting.AddLight(npc.Center, 0.1f, 0.3f, 0.6f);
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

+31
View File
@@ -0,0 +1,31 @@
using Terraria;
using Terraria.Localization;
using Terraria.ModLoader;
namespace YHTMod.Buffs;
public class SummonerAmbitionBuff : ModBuff {
public override void SetStaticDefaults() {
Main.buffNoSave[Type] = true;
Main.buffNoTimeDisplay[Type] = true;
}
public override void ModifyBuffText(ref string buffName, ref string tip, ref int rare) {
YhtPlayer modPlayer = Main.LocalPlayer.TryGetModPlayer(out YhtPlayer mp) ? mp : null;
if (modPlayer == null) return;
tip = Language.GetTextValue("Mods.YHTMod.Buffs.SummonerAmbitionBuff.Description",
modPlayer.SummonerAmbitions.Count);
}
public override void Update(Player player, ref int buffIndex) {
YhtPlayer modPlayer = player.GetModPlayer<YhtPlayer>();
if (modPlayer.SummonerAmbition) {
player.buffTime[buffIndex] = 18000;
}
else {
player.DelBuff(buffIndex);
buffIndex--;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

+5 -10
View File
@@ -4,22 +4,17 @@ using YHTMod.Projectiles.Weapons;
namespace YHTMod.Buffs; namespace YHTMod.Buffs;
public class ToclafaneMinionBuff : ModBuff public class ToclafaneMinionBuff : ModBuff {
{ public override void SetStaticDefaults() {
public override void SetStaticDefaults()
{
Main.buffNoSave[Type] = true; Main.buffNoSave[Type] = true;
Main.buffNoTimeDisplay[Type] = true; Main.buffNoTimeDisplay[Type] = true;
} }
public override void Update(Player player, ref int buffIndex) public override void Update(Player player, ref int buffIndex) {
{ if (player.ownedProjectileCounts[ModContent.ProjectileType<ToclafaneMinion>()] > 0) {
if (player.ownedProjectileCounts[ModContent.ProjectileType<ToclafaneMinion>()] > 0)
{
player.buffTime[buffIndex] = 18000; player.buffTime[buffIndex] = 18000;
} }
else else {
{
player.DelBuff(buffIndex); player.DelBuff(buffIndex);
buffIndex--; buffIndex--;
} }
+31
View File
@@ -0,0 +1,31 @@
using Terraria;
using Terraria.Localization;
using Terraria.ModLoader;
namespace YHTMod.Buffs;
public class WarriorAmbitionBuff : ModBuff {
public override void SetStaticDefaults() {
Main.buffNoSave[Type] = true;
Main.buffNoTimeDisplay[Type] = true;
}
public override void ModifyBuffText(ref string buffName, ref string tip, ref int rare) {
YhtPlayer modPlayer = Main.LocalPlayer.TryGetModPlayer(out YhtPlayer mp) ? mp : null;
if (modPlayer == null) return;
tip = Language.GetTextValue("Mods.YHTMod.Buffs.WarriorAmbitionBuff.Description",
modPlayer.WarriorAmbitions.Count);
}
public override void Update(Player player, ref int buffIndex) {
YhtPlayer modPlayer = player.GetModPlayer<YhtPlayer>();
if (modPlayer.WarriorAmbition) {
player.buffTime[buffIndex] = 18000;
}
else {
player.DelBuff(buffIndex);
buffIndex--;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 621 B

+95
View File
@@ -0,0 +1,95 @@
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.Chat;
using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader;
namespace YHTMod.Changes;
[ExtendsFromMod("CalamityMod")]
public class BossKillListener : GlobalNPC {
private static readonly Dictionary<int, string> BossIds = new();
public override void Load() {
BossIds.Add(NPCID.KingSlime, "king_slime");
BossIds.Add(NPCID.EyeofCthulhu, "eye_of_cthulhu");
BossIds.Add(NPCID.EaterofWorldsHead, "eater_of_worlds");
BossIds.Add(NPCID.EaterofWorldsBody, "eater_of_worlds");
BossIds.Add(NPCID.EaterofWorldsTail, "eater_of_worlds");
BossIds.Add(NPCID.BrainofCthulhu, "brain_of_cthulhu");
BossIds.Add(NPCID.Deerclops, "deerclops");
BossIds.Add(NPCID.QueenBee, "queen_bee");
BossIds.Add(NPCID.SkeletronHead, "skeletron");
BossIds.Add(NPCID.WallofFlesh, "wall_of_flesh");
Mod calamity = CalamityHelper.GetCalamityMod();
if (calamity == null) return;
if (calamity.TryFind("DesertScourgeHead", out ModNPC desertScourgeHead)) {
BossIds.Add(desertScourgeHead.Type, "desert_scourge");
}
if (calamity.TryFind("Crabulon", out ModNPC crabulon)) {
BossIds.Add(crabulon.Type, "crabulon");
}
if (calamity.TryFind("PerforatorHive", out ModNPC perforatorHive)) {
BossIds.Add(perforatorHive.Type, "perforators");
}
if (calamity.TryFind("HiveMind", out ModNPC hiveMind)) {
BossIds.Add(hiveMind.Type, "hive_mind");
}
if (calamity.TryFind("SlimeGodCore", out ModNPC slimeGodCore)) {
BossIds.Add(slimeGodCore.Type, "slime_god");
}
}
public override void OnKill(NPC npc) {
string id = BossIds.GetValueOrDefault(npc.type, null);
switch (id) {
case null:
base.OnKill(npc);
return;
case "eater_of_worlds": {
int foundEaterSegments = 0;
foreach (NPC activeNpC in Main.ActiveNPCs) {
if (activeNpC.friendly || activeNpC.townNPC) continue;
if (activeNpC.type is not NPCID.EaterofWorldsBody
and not NPCID.EaterofWorldsHead
and not NPCID.EaterofWorldsTail
) continue;
if (++foundEaterSegments > 1) break;
}
if (foundEaterSegments > 1) {
base.OnKill(npc);
return;
}
break;
}
}
HandleBossKill(npc, id);
base.OnKill(npc);
}
private static void HandleBossKill(NPC npc, string bossKey) {
foreach (Player player in Main.ActivePlayers) {
YhtPlayer modPlayer = player.GetModPlayer<YhtPlayer>();
if (!npc.playerInteraction[player.whoAmI]) continue;
if (modPlayer.SummonerAmbition && modPlayer.SummonerAmbitions.Add(bossKey)) {
ChatHelper.SendChatMessageToClient(
NetworkText.FromLiteral("Your Summoner Ambition's potential grows stronger!"),
Color.MediumPurple,
player.whoAmI
);
} else if (modPlayer.WarriorAmbition && modPlayer.WarriorAmbitions.Add(bossKey)) {
ChatHelper.SendChatMessageToClient(
NetworkText.FromLiteral("Your Warrior Ambition's potential grows stronger!"),
Color.OrangeRed,
player.whoAmI
);
}
}
}
}
+37
View File
@@ -0,0 +1,37 @@
using System.Collections.Generic;
using Terraria.ModLoader;
namespace YHTMod.Changes;
[ExtendsFromMod("CalamityMod")]
public class CalamityHelper {
public static readonly CalamityHelper Instance = new();
private static Dictionary<string, int> _bossIconIds;
private static Mod _calamity;
private CalamityHelper() {
ModLoader.TryGetMod("CalamityMod", out Mod calamity);
_calamity = calamity;
if (_calamity == null) return;
_bossIconIds = new Dictionary<string, int> {
{ "desert_scourge", ModContent.TryFind("CalamityMod", "LoreDesertScourge", out ModItem item1) ? item1.Type : -1 },
{ "crabulon", ModContent.TryFind("CalamityMod", "LoreCrabulon", out ModItem item2) ? item2.Type : -1 },
{ "perforators", ModContent.TryFind("CalamityMod", "LorePerforators", out ModItem item3) ? item3.Type : -1 },
{ "hive_mind", ModContent.TryFind("CalamityMod", "LoreHiveMind", out ModItem item4) ? item4.Type : -1 },
{ "slime_god", ModContent.TryFind("CalamityMod", "LoreSlimeGod", out ModItem item5) ? item5.Type : -1 }
};
}
public static int GetBossIconId(string bossKey) {
return _bossIconIds.GetValueOrDefault(bossKey, -1);
}
public static Mod GetCalamityMod() {
return _calamity;
}
}
+5 -9
View File
@@ -8,19 +8,15 @@ using YHTMod.Items.ArcaneMissile;
namespace YHTMod.Changes; namespace YHTMod.Changes;
public class NpcLoot : GlobalNPC public class NpcLoot : GlobalNPC {
{ public override void ModifyNPCLoot(NPC npc, NPCLoot npcLoot) {
public override void ModifyNPCLoot(NPC npc, NPCLoot npcLoot) int id = npc.type;
{
var id = npc.type;
if (NPCID.Sets.CountsAsCritter[id]) if (NPCID.Sets.CountsAsCritter[id]) {
{
npcLoot.Add(ItemDropRule.Common(ModContent.ItemType<MithrilPebbleOfPigSmiting>(), 400)); npcLoot.Add(ItemDropRule.Common(ModContent.ItemType<MithrilPebbleOfPigSmiting>(), 400));
} }
switch (id) switch (id) {
{
case NPCID.Plantera: case NPCID.Plantera:
npcLoot.Add(ItemDropRule.Common(ItemID.ChlorophyteOre, 1, 60, 80)); npcLoot.Add(ItemDropRule.Common(ItemID.ChlorophyteOre, 1, 60, 80));
break; break;
+150
View File
@@ -0,0 +1,150 @@
using Terraria;
using Terraria.DataStructures;
using Terraria.ID;
using Terraria.ModLoader;
using YHTMod.Buffs;
using Vector2 = Microsoft.Xna.Framework.Vector2;
namespace YHTMod.Changes;
[ExtendsFromMod("CalamityMod")]
public class SummonerOnHitEffects : GlobalProjectile {
public override void OnSpawn(Projectile projectile, IEntitySource source) {
Mod calamity = CalamityHelper.GetCalamityMod();
if (calamity is null
|| source is not EntitySource_Parent { Entity: Projectile { friendly: true } parentProj }
|| parentProj.hostile
) {
base.OnSpawn(projectile, source);
return;
}
// Get Calamity projectile types safely
if (!calamity.TryFind("ShadeNimbusHostile", out ModProjectile shadeNimbus)
|| parentProj.type != shadeNimbus.Type
) {
base.OnSpawn(projectile, source);
return;
}
if (!calamity.TryFind("ShaderainHostile", out ModProjectile shaderainHostile) ||
projectile.type != shaderainHostile.Type) {
base.OnSpawn(projectile, source);
return;
}
projectile.friendly = true;
projectile.hostile = false;
projectile.DamageType = DamageClass.Summon;
projectile.damage = parentProj.damage;
base.OnSpawn(projectile, source);
}
public override void OnHitNPC(Projectile projectile, NPC target, NPC.HitInfo hit, int damageDone) {
Player player = Main.player[projectile.owner];
YhtPlayer modPlayer = player.GetModPlayer<YhtPlayer>();
// Player's own minions
if (projectile.minion && Main.myPlayer == projectile.owner) {
if (modPlayer.SummonerAmbition) {
HandleDeerclopsEffect(modPlayer, target, projectile);
HandleQueenBeeEffect(modPlayer, target);
HandlePerforatorsEffect(modPlayer, target, projectile);
HandleHiveMindEffect(modPlayer, target, projectile);
}
}
// Whips
if (modPlayer.SummonerAmbition && ProjectileID.Sets.IsAWhip[projectile.type]) {
if (modPlayer.SummonerAmbitions.Contains("eye_of_cthulhu")) {
projectile.damage = (int)(projectile.damage * 1.1);
}
if (ModLoader.HasMod("CalamityMod")) {
if (modPlayer.SummonerAmbitions.Contains("crabulon")) {
target.AddBuff(ModContent.BuffType<ShroomGlowDebuff>(), 5 * 60);
}
}
}
base.OnHitNPC(projectile, target, hit, damageDone);
}
private static void HandleDeerclopsEffect(YhtPlayer modPlayer, NPC target, Projectile projectile) {
Player player = modPlayer.Player;
if (!modPlayer.SummonerAmbitions.Contains("deerclops")) return;
if (modPlayer.SummonerAmbitionDeerclopsCooldown != 0) return;
if (!Main.rand.NextBool(10)) return;
modPlayer.SummonerAmbitionDeerclopsCooldown = 5 * 60;
Vector2 direction = new(Main.rand.NextFloat(-1f, 1f), Main.rand.NextFloat(-1f, 1f));
direction.Normalize();
direction *= Main.rand.NextFloat(4f, 8f);
Projectile.NewProjectile(
player.GetSource_OnHit(target),
target.Center,
direction,
ProjectileID.InsanityShadowFriendly,
(int) (projectile.damage * 0.5),
0f,
projectile.owner
);
}
private static void HandleQueenBeeEffect(YhtPlayer modPlayer, NPC target) {
if (!modPlayer.SummonerAmbitions.Contains("queen_bee")) return;
if (!Main.rand.NextBool(4)) return;
target.AddBuff(BuffID.Poisoned, 5 * 60);
}
private static void HandlePerforatorsEffect(YhtPlayer modPlayer, NPC target, Projectile projectile) {
if (!ModLoader.HasMod("CalamityMod")) return;
if (!modPlayer.SummonerAmbitions.Contains("perforators")) return;
if (modPlayer.SummonerAmbitionPerforatorsCooldown != 0) return;
if (!Main.rand.NextBool(10)) return;
modPlayer.SummonerAmbitionPerforatorsCooldown = 20 * 60;
Vector2 direction = new(Main.rand.NextFloat(-1f, 1f), Main.rand.NextFloat(-1f, 1f));
direction.Normalize();
direction *= Main.rand.NextFloat(4f, 5f);
int projectileType = ModContent.ProjectileType<CalamityMod.Projectiles.Boss.IchorBlob>();
int projectileId = Projectile.NewProjectile(
modPlayer.Player.GetSource_OnHit(target),
target.Center,
direction,
projectileType,
(int) (projectile.damage * 0.75f),
0f,
projectile.owner
);
Projectile blob = Main.projectile[projectileId];
blob.friendly = true;
blob.hostile = false;
blob.DamageType = DamageClass.Summon;
}
private static void HandleHiveMindEffect(YhtPlayer modPlayer, NPC target, Projectile projectile) {
if (!ModLoader.HasMod("CalamityMod")) return;
if (!modPlayer.SummonerAmbitions.Contains("hive_mind")) return;
if (modPlayer.SummonerAmbitionHiveMindCooldown != 0) return;
if (!Main.rand.NextBool(10)) return;
modPlayer.SummonerAmbitionHiveMindCooldown = 3 * 60;
int projectileType = ModContent.ProjectileType<CalamityMod.Projectiles.Boss.ShadeNimbusHostile>();
int projectileId = Projectile.NewProjectile(
modPlayer.Player.GetSource_OnHit(target),
target.Center,
new Vector2(0, -0.25f),
projectileType,
(int) (projectile.damage * 0.75f),
0f,
projectile.owner
);
Projectile blob = Main.projectile[projectileId];
blob.friendly = true;
blob.hostile = false;
blob.DamageType = DamageClass.Summon;
}
}
+51
View File
@@ -0,0 +1,51 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ModLoader;
namespace YHTMod.Changes;
public class WarriorItemEffects : GlobalItem {
public override void UseItemHitbox(Item item, Player player, ref Rectangle hitbox, ref bool noHitbox) {
YhtPlayer modPlayer = player.GetModPlayer<YhtPlayer>();
if (!modPlayer.WarriorAmbition) {
base.UseItemHitbox(item, player, ref hitbox, ref noHitbox);
return;
}
if (item.DamageType == DamageClass.Melee && !item.noMelee) {
float scale = modPlayer.GetWarriorsAmbitionMeleeSizeBonus();
if (scale > 1f) {
int newW = (int)(hitbox.Width * scale);
int newH = (int)(hitbox.Height * scale);
int cx = hitbox.X + hitbox.Width / 2;
int cy = hitbox.Y + hitbox.Height / 2;
hitbox.X = cx - newW / 2;
hitbox.Y = cy - newH / 2;
hitbox.Width = newW;
hitbox.Height = newH;
}
}
base.UseItemHitbox(item, player, ref hitbox, ref noHitbox);
}
public override void HoldItem(Item item, Player player) {
YhtPlayer modPlayer = player.GetModPlayer<YhtPlayer>();
if (!modPlayer.WarriorAmbition) {
base.HoldItem(item, player);
return;
}
if (item.DamageType == DamageClass.Melee && !item.noMelee) {
float sizeBonus = modPlayer.GetWarriorsAmbitionMeleeSizeBonus();
if (sizeBonus >= 1f)
{
item.scale *= sizeBonus;
}
}
base.HoldItem(item, player);
}
}
+7 -11
View File
@@ -5,17 +5,14 @@ using Terraria.ModLoader;
namespace YHTMod.Items.ArcaneMissile; namespace YHTMod.Items.ArcaneMissile;
public class ArcaneMissile : ModItem public class ArcaneMissile : ModItem {
{ public override void SetStaticDefaults() {
public override void SetStaticDefaults()
{
CreativeItemSacrificesCatalog.Instance.SacrificeCountNeededByItemId[Type] = 1; CreativeItemSacrificesCatalog.Instance.SacrificeCountNeededByItemId[Type] = 1;
} }
public override void SetDefaults() public override void SetDefaults() {
{ Item.width = 32;
Item.width = 64; Item.height = 32;
Item.height = 64;
Item.accessory = true; Item.accessory = true;
Item.damage = 10; Item.damage = 10;
Item.rare = ItemRarityID.LightRed; Item.rare = ItemRarityID.LightRed;
@@ -24,9 +21,8 @@ public class ArcaneMissile : ModItem
Item.noUseGraphic = true; Item.noUseGraphic = true;
} }
public override void UpdateAccessory(Player player, bool hideVisual) public override void UpdateAccessory(Player player, bool hideVisual) {
{ player.GetModPlayer<YhtPlayer>().ArcaneMissile = Item.damage;
player.GetModPlayer<YhtPlayer>().arcaneMissle = Item.damage;
base.UpdateAccessory(player, hideVisual); base.UpdateAccessory(player, hideVisual);
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

+8 -13
View File
@@ -4,32 +4,27 @@ using Terraria.ModLoader;
namespace YHTMod.Items.ArcaneMissile; namespace YHTMod.Items.ArcaneMissile;
public class ArcaneMissileBehavior : GlobalNPC public class ArcaneMissileBehavior : GlobalNPC {
{ public override void OnHitByProjectile(NPC npc, Projectile projectile, NPC.HitInfo hitInfo, int damage) {
public override void OnHitByProjectile(NPC npc, Projectile projectile, NPC.HitInfo hitInfo, int damage) if (!hitInfo.Crit) {
{
if (!hitInfo.Crit)
{
base.OnHitByProjectile(npc, projectile, hitInfo, damage); base.OnHitByProjectile(npc, projectile, hitInfo, damage);
return; return;
} }
if (Main.netMode == NetmodeID.Server) if (Main.netMode == NetmodeID.Server) {
{
return; return;
} }
var player = Main.LocalPlayer; Player player = Main.LocalPlayer;
if (player.GetModPlayer<YhtPlayer>().arcaneMissle != 0 && projectile.DamageType == DamageClass.Magic) if (player.GetModPlayer<YhtPlayer>().ArcaneMissile != 0 && projectile.DamageType == DamageClass.Magic) {
{
// player just crit with magic weapon while having arcane missile accessory // player just crit with magic weapon while having arcane missile accessory
var proj = Projectile.NewProjectileDirect( Projectile proj = Projectile.NewProjectileDirect(
projectile.GetSource_FromThis("arcaneMissile"), projectile.GetSource_FromThis("arcaneMissile"),
Main.LocalPlayer.position, Main.LocalPlayer.position,
npc.position.DirectionFrom(Main.LocalPlayer.position), npc.position.DirectionFrom(Main.LocalPlayer.position),
ProjectileID.MagicMissile, ProjectileID.MagicMissile,
player.GetModPlayer<YhtPlayer>().arcaneMissle, player.GetModPlayer<YhtPlayer>().ArcaneMissile,
0, 0,
Main.LocalPlayer.whoAmI Main.LocalPlayer.whoAmI
); );
+13 -18
View File
@@ -6,41 +6,36 @@ using Terraria.ModLoader;
namespace YHTMod.Items; namespace YHTMod.Items;
public class KatanaRedo : GlobalItem public class KatanaRedo : GlobalItem {
{ public override void ModifyTooltips(Item item, List<TooltipLine> tooltips) {
public override void ModifyTooltips(Item item, List<TooltipLine> tooltips)
{
if (item.type != ItemID.Katana) return; if (item.type != ItemID.Katana) return;
tooltips.Insert(5, new TooltipLine(YHTMod.GetInstance(), "flavor", "Nothing personel kid.")); tooltips.Insert(5, new TooltipLine(YHTMod.GetInstance(), "flavor", "Nothing personel kid."));
tooltips.Insert(6, new TooltipLine(YHTMod.GetInstance(), "usage", "Right click to teleport behind them.")); tooltips.Insert(6, new TooltipLine(YHTMod.GetInstance(), "usage", "Right click to teleport behind them."));
} }
public override bool AltFunctionUse(Item item, Player player) public override bool AltFunctionUse(Item item, Player player) {
{
return item.type == ItemID.Katana || base.AltFunctionUse(item, player); return item.type == ItemID.Katana || base.AltFunctionUse(item, player);
} }
public override bool? UseItem(Item item, Player player) public override bool? UseItem(Item item, Player player) {
{
if (item.type != ItemID.Katana || player.altFunctionUse != 2) return null; if (item.type != ItemID.Katana || player.altFunctionUse != 2) return null;
var yhtPlayer = player.GetModPlayer<YhtPlayer>(); YhtPlayer yhtPlayer = player.GetModPlayer<YhtPlayer>();
if (yhtPlayer.katanaTeleportCooldown > 0) return null; if (yhtPlayer.KatanaTeleportCooldown > 0) return null;
yhtPlayer.katanaTeleportCooldown = 300; yhtPlayer.KatanaTeleportCooldown = 300;
for (var i = 0; i < Main.maxNPCs; i++) for (int i = 0; i < Main.maxNPCs; i++) {
{ NPC npc = Main.npc[i];
var npc = Main.npc[i];
if (!npc.CanBeChasedBy()) continue; if (!npc.CanBeChasedBy()) continue;
var between = Vector2.Distance(npc.Center, player.Center); float between = Vector2.Distance(npc.Center, player.Center);
var inRange = between < 650; bool inRange = between < 650;
var lineOfSight = Collision.CanHitLine(player.position, player.width, player.height, npc.position, bool lineOfSight = Collision.CanHitLine(player.position, player.width, player.height, npc.position,
npc.width, npc.height); npc.width, npc.height);
if (!inRange || !lineOfSight) continue; if (!inRange || !lineOfSight) continue;
var tpPos = npc.position; Vector2 tpPos = npc.position;
tpPos.X += -(npc.direction * npc.width + (player.width * 2)); tpPos.X += -(npc.direction * npc.width + (player.width * 2));
if (Collision.TileCollision(tpPos, Vector2.Zero, player.width, player.height) != Vector2.Zero) return true; if (Collision.TileCollision(tpPos, Vector2.Zero, player.width, player.height) != Vector2.Zero) return true;
+163
View File
@@ -0,0 +1,163 @@
using System.Collections.Generic;
using System.Linq;
using Terraria;
using Terraria.GameContent.Creative;
using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader;
using YHTMod.Changes;
namespace YHTMod.Items;
public class SummonersAmbition : ModItem {
public override void SetStaticDefaults() {
CreativeItemSacrificesCatalog.Instance.SacrificeCountNeededByItemId[Type] = 1;
}
public override LocalizedText Tooltip => Language.GetText("");
public override void SetDefaults() {
Item.width = 32;
Item.height = 32;
Item.accessory = true;
Item.rare = ItemRarityID.White;
Item.noMelee = true;
Item.noUseGraphic = true;
ItemID.Sets.ShimmerTransformToItem[Type] = 0;
}
public override bool CanAccessoryBeEquippedWith(Item equippedItem, Item incomingItem, Player player) {
return !(YHTMod.GetAmbitionItems().Contains(incomingItem.type) && YHTMod.GetAmbitionItems().Contains(equippedItem.type));
}
public override void UpdateAccessory(Player player, bool hideVisual) {
YhtPlayer modPlayer = player.GetModPlayer<YhtPlayer>();
modPlayer.SummonerAmbition = true;
}
public override void ModifyTooltips(List<TooltipLine> tooltips) {
YhtPlayer player = Main.LocalPlayer.GetModPlayer<YhtPlayer>();
tooltips.Add(new TooltipLine(Mod, "SummonerAmbition",
Language.GetTextValue("Mods.YHTMod.Items.SummonersAmbition.Tooltip",
player.GetSummonersAmbitionMinionBonus())));
if (player.SummonerAmbitions.Contains("king_slime")) {
int bonus = 20;
if (ModLoader.HasMod("CalamityMod")) {
bonus = 10;
}
tooltips.Add(new TooltipLine(Mod, "SummonerAmbitionKingSlime",
Language.GetTextValue("Mods.YHTMod.Items.SummonersAmbition.KingSlime", bonus)));
}
if (ModLoader.HasMod("CalamityMod") && player.SummonerAmbitions.Contains("desert_scourge")) {
int id = CalamityHelper.GetBossIconId("desert_scourge");
tooltips.Add(new TooltipLine(Mod, "SummonerAmbitionDesertScourge",
Language.GetTextValue("Mods.YHTMod.Items.SummonersAmbition.DesertScourge", "[i:" + id + "]")));
}
if (player.SummonerAmbitions.Contains("eye_of_cthulhu")) {
tooltips.Add(new TooltipLine(Mod, "SummonerAmbitionEyeOfCthulhu",
Language.GetTextValue("Mods.YHTMod.Items.SummonersAmbition.EyeOfCthulhu")));
}
if (ModLoader.HasMod("CalamityMod") && player.SummonerAmbitions.Contains("crabulon")) {
int id = CalamityHelper.GetBossIconId("crabulon");
tooltips.Add(new TooltipLine(Mod, "SummonerAmbitionCrabulon",
Language.GetTextValue("Mods.YHTMod.Items.SummonersAmbition.Crabulon", "[i:" + id + "]")));
}
if (player.SummonerAmbitions.Contains("deerclops")) {
tooltips.Add(new TooltipLine(Mod, "SummonerAmbitionDeerclops",
Language.GetTextValue("Mods.YHTMod.Items.SummonersAmbition.Deerclops")));
}
if (player.SummonerAmbitions.Contains("eater_of_worlds")) {
tooltips.Add(new TooltipLine(Mod, "SummonerAmbitionEaterOfWorlds",
Language.GetTextValue("Mods.YHTMod.Items.SummonersAmbition.EaterOfWorlds")));
}
if (player.SummonerAmbitions.Contains("brain_of_cthulhu")) {
tooltips.Add(new TooltipLine(Mod, "SummonerAmbitionBrainOfCthulhu",
Language.GetTextValue("Mods.YHTMod.Items.SummonersAmbition.BrainOfCthulhu")));
}
if (ModLoader.HasMod("CalamityMod") && player.SummonerAmbitions.Contains("perforators")) {
int id = CalamityHelper.GetBossIconId("perforators");
tooltips.Add(new TooltipLine(Mod, "SummonerAmbitionPerforators",
Language.GetTextValue("Mods.YHTMod.Items.SummonersAmbition.Perforators", "[i:" + id + "]")));
}
if (ModLoader.HasMod("CalamityMod") && player.SummonerAmbitions.Contains("hive_mind")) {
int id = CalamityHelper.GetBossIconId("hive_mind");
tooltips.Add(new TooltipLine(Mod, "SummonerAmbitionHiveMind",
Language.GetTextValue("Mods.YHTMod.Items.SummonersAmbition.HiveMind", "[i:" + id + "]")));
}
if (player.SummonerAmbitions.Contains("queen_bee")) {
tooltips.Add(new TooltipLine(Mod, "SummonerAmbitionQueenBee",
Language.GetTextValue("Mods.YHTMod.Items.SummonersAmbition.QueenBee")));
}
if (player.SummonerAmbitions.Contains("skeletron")) {
tooltips.Add(new TooltipLine(Mod, "SummonerAmbitionSkeletron",
Language.GetTextValue("Mods.YHTMod.Items.SummonersAmbition.Skeletron")));
}
if (ModLoader.HasMod("CalamityMod") && player.SummonerAmbitions.Contains("slime_god")) {
int id = CalamityHelper.GetBossIconId("slime_god");
tooltips.Add(new TooltipLine(Mod, "SummonerAmbitionSlimeGod",
Language.GetTextValue("Mods.YHTMod.Items.SummonersAmbition.SlimeGod", "[i:" + id + "]")));
}
if (player.SummonerAmbitions.Contains("wall_of_flesh")) {
tooltips.Add(new TooltipLine(Mod, "SummonerAmbitionWallOfFlesh",
Language.GetTextValue("Mods.YHTMod.Items.SummonersAmbition.WallOfFlesh")));
}
if (IsPreHardmodeRealized(player.Player)) {
tooltips.Add(new TooltipLine(Mod, "SummonerAmbitionPreHardmodeRealized",
Language.GetTextValue("Mods.YHTMod.Items.SummonersAmbition.PreHardmodeRealized")));
}
}
public override void AddRecipes() {
CreateRecipe()
.AddIngredient(ItemID.Rope, 5)
.AddRecipeGroup(RecipeGroupID.Squirrels)
.AddIngredient(ItemID.Acorn, 25)
.AddTile(TileID.WorkBenches)
.Register();
}
private static bool IsPreHardmodeRealized(Player player) {
YhtPlayer modPlayer = player.GetModPlayer<YhtPlayer>();
HashSet<string> bossesToCheck = [
"king_slime",
"eye_of_cthulhu",
"deerclops",
"queen_bee",
"skeletron",
"wall_of_flesh"
];
if (!modPlayer.SummonerAmbitions.Contains("eater_of_worlds") && !modPlayer.SummonerAmbitions.Contains("brain_of_cthulhu")) {
return false;
}
if (ModLoader.HasMod("CalamityMod")) {
bossesToCheck.Add("desert_scourge");
bossesToCheck.Add("crabulon");
bossesToCheck.Add("slime_god");
if (!modPlayer.SummonerAmbitions.Contains("perforators") && !modPlayer.SummonerAmbitions.Contains("hive_mind")) {
return false;
}
}
return bossesToCheck.All(boss => modPlayer.SummonerAmbitions.Contains(boss));
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

+38 -39
View File
@@ -3,6 +3,7 @@ using Terraria;
using Terraria.DataStructures; using Terraria.DataStructures;
using Terraria.GameContent.Creative; using Terraria.GameContent.Creative;
using Terraria.ID; using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader; using Terraria.ModLoader;
using YHTMod.Buffs; using YHTMod.Buffs;
using YHTMod.Projectiles.Weapons; using YHTMod.Projectiles.Weapons;
@@ -10,9 +11,9 @@ using YHTMod.Projectiles.Weapons;
namespace YHTMod.Items; namespace YHTMod.Items;
public class ToclafaneStaff : ModItem { public class ToclafaneStaff : ModItem {
public override void SetStaticDefaults() { public override void SetStaticDefaults() {
ItemID.Sets.GamepadWholeScreenUseRange[Item.type] = true; // This lets the player target anywhere on the whole screen while using a controller. ItemID.Sets.GamepadWholeScreenUseRange[Item.type] =
true; // This lets the player target anywhere on the whole screen while using a controller.
ItemID.Sets.LockOnIgnoresCollision[Item.type] = true; ItemID.Sets.LockOnIgnoresCollision[Item.type] = true;
CreativeItemSacrificesCatalog.Instance.SacrificeCountNeededByItemId[Type] = 1; CreativeItemSacrificesCatalog.Instance.SacrificeCountNeededByItemId[Type] = 1;
} }
@@ -35,48 +36,46 @@ public class ToclafaneStaff : ModItem {
Item.shoot = ModContent.ProjectileType<ToclafaneMinion>(); Item.shoot = ModContent.ProjectileType<ToclafaneMinion>();
} }
public override bool Shoot(Player player, EntitySource_ItemUse_WithAmmo source, Vector2 position, Vector2 velocity, int type, int damage, float knockback) { public override bool Shoot(Player player, EntitySource_ItemUse_WithAmmo source, Vector2 position, Vector2 velocity,
int type, int damage, float knockback) {
player.AddBuff(Item.buffType, 2); player.AddBuff(Item.buffType, 2);
position = Main.MouseWorld; position = Main.MouseWorld;
return base.Shoot(player, source, position, velocity, type, damage, knockback); return base.Shoot(player, source, position, velocity, type, damage, knockback);
} }
public override void AddRecipes() { public override void AddRecipes() {
CreateRecipe() RecipeGroup watchGroup = new RecipeGroup(() => Language.GetTextValue("Mods.YHTMod.Recipes.AnyWatch"),
.AddIngredient(ItemID.GuideVoodooDoll, 1) ItemID.GoldWatch,
.AddIngredient(ItemID.HallowedBar, 15) ItemID.SilverWatch,
.AddIngredient(ItemID.CopperWatch) ItemID.TinWatch,
.AddTile(TileID.MythrilAnvil) ItemID.CopperWatch,
.Register(); ItemID.PlatinumWatch,
CreateRecipe() ItemID.TungstenWatch
.AddIngredient(ItemID.GuideVoodooDoll, 1) );
.AddIngredient(ItemID.HallowedBar, 15) RecipeGroup.RegisterGroup("YHTMod:Watches", watchGroup);
.AddIngredient(ItemID.TinWatch)
.AddTile(TileID.MythrilAnvil) RecipeGroup tier2BarGroup = new RecipeGroup(() => Language.GetTextValue("Mods.YHTMod.Recipes.Tier2Bars"),
.Register(); ItemID.MythrilBar,
CreateRecipe() ItemID.OrichalcumBar
.AddIngredient(ItemID.GuideVoodooDoll, 1) );
.AddIngredient(ItemID.HallowedBar, 15) RecipeGroup.RegisterGroup("YHTMod:Tier2Bars", tier2BarGroup);
.AddIngredient(ItemID.SilverWatch)
.AddTile(TileID.MythrilAnvil) Recipe recipe = CreateRecipe();
.Register();
CreateRecipe() recipe.AddRecipeGroup(watchGroup);
.AddIngredient(ItemID.GuideVoodooDoll, 1) recipe.AddIngredient(ItemID.GuideVoodooDoll);
.AddIngredient(ItemID.HallowedBar, 15) recipe.AddTile(TileID.MythrilAnvil);
.AddIngredient(ItemID.TungstenWatch)
.AddTile(TileID.MythrilAnvil) // Calamity delays when you obtain hallowed bars, so use alternate recipe if Calamity is installed
.Register(); if (ModLoader.HasMod("CalamityMod")) {
CreateRecipe() recipe.AddRecipeGroup(tier2BarGroup, 35);
.AddIngredient(ItemID.GuideVoodooDoll, 1) recipe.AddIngredient(ItemID.SoulofLight, 10);
.AddIngredient(ItemID.HallowedBar, 15) recipe.AddIngredient(ItemID.SoulofNight, 10);
.AddTile(TileID.MythrilAnvil) }
.AddIngredient(ItemID.GoldWatch) else {
.Register(); recipe.AddIngredient(ItemID.HallowedBar, 15);
CreateRecipe() }
.AddIngredient(ItemID.GuideVoodooDoll, 1)
.AddIngredient(ItemID.HallowedBar, 15) recipe.Register();
.AddIngredient(ItemID.PlatinumWatch)
.AddTile(TileID.MythrilAnvil)
.Register();
} }
} }
+150
View File
@@ -0,0 +1,150 @@
using System.Collections.Generic;
using System.Linq;
using Terraria;
using Terraria.GameContent.Creative;
using Terraria.ID;
using Terraria.Localization;
using Terraria.ModLoader;
using YHTMod.Changes;
namespace YHTMod.Items;
public class WarriorsAmbition : ModItem {
public override void SetStaticDefaults() {
CreativeItemSacrificesCatalog.Instance.SacrificeCountNeededByItemId[Type] = 1;
}
public override LocalizedText Tooltip => Language.GetText("");
public override void SetDefaults() {
Item.width = 32;
Item.height = 32;
Item.accessory = true;
Item.rare = ItemRarityID.White;
Item.noMelee = true;
Item.noUseGraphic = true;
ItemID.Sets.ShimmerTransformToItem[Type] = 0;
}
public override bool CanAccessoryBeEquippedWith(Item equippedItem, Item incomingItem, Player player) {
return !(YHTMod.GetAmbitionItems().Contains(incomingItem.type) && YHTMod.GetAmbitionItems().Contains(equippedItem.type));
}
public override void UpdateAccessory(Player player, bool hideVisual) {
YhtPlayer modPlayer = player.GetModPlayer<YhtPlayer>();
modPlayer.WarriorAmbition = true;
}
public override void ModifyTooltips(List<TooltipLine> tooltips) {
YhtPlayer player = Main.LocalPlayer.GetModPlayer<YhtPlayer>();
tooltips.Add(new TooltipLine(Mod, "WarriorsAmbition",
Language.GetTextValue("Mods.YHTMod.Items.WarriorAmbition.Tooltip")));
if (player.WarriorAmbitions.Contains("king_slime")) {
float bonus = 5f;
if (ModLoader.HasMod("CalamityMod")) {
bonus = 2.5f;
}
tooltips.Add(new TooltipLine(Mod, "WarriorAmbitionKingSlime",
Language.GetTextValue("Mods.YHTMod.Items.WarriorsAmbition.KingSlime", bonus)));
}
if (ModLoader.HasMod("CalamityMod") && player.WarriorAmbitions.Contains("desert_scourge")) {
int id = CalamityHelper.GetBossIconId("desert_scourge");
tooltips.Add(new TooltipLine(Mod, "WarriorAmbitionDesertScourge",
Language.GetTextValue("Mods.YHTMod.Items.WarriorsAmbition.DesertScourge", "[i:" + id + "]")));
}
if (player.WarriorAmbitions.Contains("eye_of_cthulhu")) {
tooltips.Add(new TooltipLine(Mod, "WarriorAmbitionEyeOfCthulhu",
Language.GetTextValue("Mods.YHTMod.Items.WarriorsAmbition.EyeOfCthulhu")));
}
if (ModLoader.HasMod("CalamityMod") && player.WarriorAmbitions.Contains("crabulon")) {
int id = CalamityHelper.GetBossIconId("crabulon");
tooltips.Add(new TooltipLine(Mod, "WarriorAmbitionCrabulon",
Language.GetTextValue("Mods.YHTMod.Items.WarriorsAmbition.Crabulon", "[i:" + id + "]")));
}
if (player.WarriorAmbitions.Contains("deerclops")) {
tooltips.Add(new TooltipLine(Mod, "WarriorAmbitionDeerclops",
Language.GetTextValue("Mods.YHTMod.Items.WarriorsAmbition.Deerclops")));
}
if (player.WarriorAmbitions.Contains("eater_of_worlds")) {
tooltips.Add(new TooltipLine(Mod, "WarriorAmbitionEaterOfWorlds",
Language.GetTextValue("Mods.YHTMod.Items.WarriorsAmbition.EaterOfWorlds")));
}
if (player.WarriorAmbitions.Contains("brain_of_cthulhu")) {
tooltips.Add(new TooltipLine(Mod, "WarriorAmbitionBrainOfCthulhu",
Language.GetTextValue("Mods.YHTMod.Items.WarriorsAmbition.BrainOfCthulhu")));
}
if (ModLoader.HasMod("CalamityMod") && player.WarriorAmbitions.Contains("perforators")) {
int id = CalamityHelper.GetBossIconId("perforators");
tooltips.Add(new TooltipLine(Mod, "WarriorAmbitionPerforators",
Language.GetTextValue("Mods.YHTMod.Items.WarriorsAmbition.Perforators", "[i:" + id + "]")));
}
if (ModLoader.HasMod("CalamityMod") && player.WarriorAmbitions.Contains("hive_mind")) {
int id = CalamityHelper.GetBossIconId("hive_mind");
tooltips.Add(new TooltipLine(Mod, "WarriorAmbitionHiveMind",
Language.GetTextValue("Mods.YHTMod.Items.WarriorsAmbition.HiveMind", "[i:" + id + "]")));
}
if (player.WarriorAmbitions.Contains("queen_bee")) {
tooltips.Add(new TooltipLine(Mod, "WarriorAmbitionQueenBee",
Language.GetTextValue("Mods.YHTMod.Items.WarriorsAmbition.QueenBee")));
}
if (player.WarriorAmbitions.Contains("skeletron")) {
tooltips.Add(new TooltipLine(Mod, "WarriorAmbitionSkeletron",
Language.GetTextValue("Mods.YHTMod.Items.WarriorsAmbition.Skeletron")));
}
if (player.WarriorAmbitions.Contains("wall_of_flesh")) {
tooltips.Add(new TooltipLine(Mod, "WarriorAmbitionWallOfFlesh",
Language.GetTextValue("Mods.YHTMod.Items.WarriorsAmbition.WallOfFlesh")));
}
if (ModLoader.HasMod("CalamityMod") && player.WarriorAmbitions.Contains("slime_god")) {
int id = CalamityHelper.GetBossIconId("slime_god");
tooltips.Add(new TooltipLine(Mod, "WarriorAmbitionSlimeGod",
Language.GetTextValue("Mods.YHTMod.Items.WarriorsAmbition.SlimeGod", "[i:" + id + "]")));
}
}
public override void AddRecipes() {
}
private static bool IsPreHardmodeRealized(Player player) {
YhtPlayer modPlayer = player.GetModPlayer<YhtPlayer>();
HashSet<string> bossesToCheck = [
"king_slime",
"eye_of_cthulhu",
"deerclops",
"queen_bee",
"skeletron",
"wall_of_flesh"
];
if (!modPlayer.WarriorAmbitions.Contains("eater_of_worlds") && !modPlayer.WarriorAmbitions.Contains("brain_of_cthulhu")) {
return false;
}
if (ModLoader.HasMod("CalamityMod")) {
bossesToCheck.Add("desert_scourge");
bossesToCheck.Add("crabulon");
bossesToCheck.Add("slime_god");
if (!modPlayer.WarriorAmbitions.Contains("perforators") && !modPlayer.WarriorAmbitions.Contains("hive_mind")) {
return false;
}
}
return bossesToCheck.All(boss => modPlayer.WarriorAmbitions.Contains(boss));
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 621 B

+83 -1
View File
@@ -1,7 +1,41 @@
Recipes: {
AnyWatch: Any Watch
Tier2Bars: Tier 2 Hardmode Bars
}
Buffs: { Buffs: {
ToclafaneMinionBuff: { ToclafaneMinionBuff: {
DisplayName: Summon Toclafane DisplayName: Summon Toclafane
Description: It came from a parallel world to fight for its Master. Description: It came from a parallel world to fight for its Master
}
SummonerAmbitionBuff: {
DisplayName: Summoner's Ambition
Description:
'''
Your power grows with your ambition
Essences absorbed: {0}
'''
}
ShroomGlowDebuff: {
DisplayName: Shroom Glow
Description:
'''
You are emitting a faint glow...
And smell like mushrooms.
'''
}
WarriorAmbitionBuff: {
DisplayName: Warrior's Ambition
Description:
'''
Your power grows with your ambition
Essences absorbed: {0}
'''
} }
} }
@@ -49,6 +83,54 @@ Items: {
DisplayName: Toclafane Staff DisplayName: Toclafane Staff
Tooltip: Summons a toclafane to remove population for you Tooltip: Summons a toclafane to remove population for you
} }
SummonersAmbition: {
DisplayName: Summoner's Ambition
Tooltip:
'''
Grants Summoner's Ambition.
"For those who seek to lead."
{$CommonItemTooltip.IncreasesMaxMinionsBy@0}
'''
KingSlime: "[i:560] {0}% increased whip size"
DesertScourge: "{0} Increases maximum life by 5"
EyeOfCthulhu: "[i:43] Increases whip damage by 10%"
Crabulon: "{0} Enemies struck by whips glow slightly"
EaterOfWorlds: "[i:70] Summon damage penetrates 5 armor"
BrainOfCthulhu: "[i:1331] 5% increased minion damage"
HiveMind: "{0} Occasionally spawns Shade Nimbus to rain on enemies"
Perforators: "{0} Occasionally spawns ichor blobs on minion hits"
QueenBee: "[i:1133] Minion hits can inflict poison"
Deerclops: "[i:5120] Minion hits can spawn shadow hands"
Skeletron: "[i:4801] Increases minion knockback"
WallOfFlesh: "[i:267] Increases max number of minions by 1"
SlimeGod: "{0} 10% increased whip size"
PreHardmodeRealized: Fully realized. Seek greater heights.
}
WarriorsAmbition: {
DisplayName: Warriors Ambition
Tooltip:
'''
Grants Warrior's Ambition.
"For those who wish to face enemy head on."
{0} defense
'''
KingSlime: "[i:560] {0}% increased true melee weapon size"
DesertScourge: "{0} Increases maximum life by 10"
EyeOfCthulhu: "[i:43] Increases melee damage by 10%"
Crabulon: "{0} Enemies struck by whips glow slightly"
EaterOfWorlds: "[i:70] Melee damage penetrates 5 armor"
BrainOfCthulhu: "[i:1331] 5% increased true melee damage"
HiveMind: "{0} +2 defense"
Perforators: "{0} +2 defense"
QueenBee: "[i:1133] Damaging debuffs expire 5% faster on you"
Deerclops: "[i:5120] Melee hits can throw debris"
Skeletron: "[i:4801] Increases melee knockback"
WallOfFlesh: "[i:267] +5 defense"
SlimeGod: "{0} 2.5% increased true melee weapon size"
PreHardmodeRealized: Fully realized. Seek greater heights.
}
} }
Projectiles: { Projectiles: {
@@ -23,8 +23,9 @@ class CopperSwordOnAStickProjectile : ModProjectile {
public override void AI() { public override void AI() {
base.AI(); base.AI();
float random = (float) (Random.Shared.NextDouble() / 5f); float random = (float)(Random.Shared.NextDouble() / 5f);
Projectile.rotation = Projectile.velocity.ToRotation() + MathHelper.PiOver2 - MathHelper.PiOver4 * Projectile.spriteDirection; Projectile.rotation = Projectile.velocity.ToRotation() + MathHelper.PiOver2 -
MathHelper.PiOver4 * Projectile.spriteDirection;
Projectile.rotation += random; Projectile.rotation += random;
DrawOriginOffsetX = 0; DrawOriginOffsetX = 0;
DrawOffsetX = 0; DrawOffsetX = 0;
@@ -24,7 +24,7 @@ class MithrilPebbleOfPigSmitingProjectile : ModProjectile {
base.AI(); base.AI();
DrawOriginOffsetX = 0; DrawOriginOffsetX = 0;
DrawOffsetX = 0; DrawOffsetX = 0;
var dust = Dust.NewDust(Projectile.Center, 1, 1, DustID.Mythril, 0f, 0f, 0, default(Color), 1f); int dust = Dust.NewDust(Projectile.Center, 1, 1, DustID.Mythril, 0f, 0f, 0, default(Color), 1f);
Main.dust[dust].noGravity = true; Main.dust[dust].noGravity = true;
Main.dust[dust].velocity *= 0.3f; Main.dust[dust].velocity *= 0.3f;
} }
+50 -81
View File
@@ -7,13 +7,11 @@ using YHTMod.Buffs;
namespace YHTMod.Projectiles.Weapons; namespace YHTMod.Projectiles.Weapons;
public class ToclafaneMinion : ModProjectile public class ToclafaneMinion : ModProjectile {
{
private int _shootCooldown = 0; private int _shootCooldown = 0;
private AttackMode _attackMode = AttackMode.Ranged; private AttackMode _attackMode = AttackMode.Ranged;
public override void SetStaticDefaults() public override void SetStaticDefaults() {
{
// Sets the amount of frames this minion has on its spritesheet // Sets the amount of frames this minion has on its spritesheet
Main.projFrames[Projectile.type] = 8; Main.projFrames[Projectile.type] = 8;
// This is necessary for right-click targeting // This is necessary for right-click targeting
@@ -23,8 +21,7 @@ public class ToclafaneMinion : ModProjectile
ProjectileID.Sets.MinionSacrificable[Projectile.type] = true; ProjectileID.Sets.MinionSacrificable[Projectile.type] = true;
} }
public sealed override void SetDefaults() public sealed override void SetDefaults() {
{
Projectile.width = 32; Projectile.width = 32;
Projectile.height = 32; Projectile.height = 32;
Projectile.scale = 0.65f; Projectile.scale = 0.65f;
@@ -37,29 +34,24 @@ public class ToclafaneMinion : ModProjectile
Projectile.penetrate = -1; Projectile.penetrate = -1;
} }
public override bool? CanCutTiles() public override bool? CanCutTiles() {
{
return false; return false;
} }
public override bool MinionContactDamage() public override bool MinionContactDamage() {
{
return true; return true;
} }
public override void AI() public override void AI() {
{ Player player = Main.player[Projectile.owner];
var player = Main.player[Projectile.owner];
#region Active check #region Active check
if (player.dead || !player.active) if (player.dead || !player.active) {
{
player.ClearBuff(ModContent.BuffType<ToclafaneMinionBuff>()); player.ClearBuff(ModContent.BuffType<ToclafaneMinionBuff>());
} }
if (player.HasBuff(ModContent.BuffType<ToclafaneMinionBuff>())) if (player.HasBuff(ModContent.BuffType<ToclafaneMinionBuff>())) {
{
Projectile.timeLeft = 2; Projectile.timeLeft = 2;
} }
@@ -67,14 +59,13 @@ public class ToclafaneMinion : ModProjectile
#region General behavior #region General behavior
if (_shootCooldown > 0) if (_shootCooldown > 0) {
{
_shootCooldown = _shootCooldown - 1; _shootCooldown = _shootCooldown - 1;
} }
_attackMode = AttackMode.Ranged; _attackMode = AttackMode.Ranged;
var idlePosition = player.Center; Vector2 idlePosition = player.Center;
idlePosition.Y -= 48f; idlePosition.Y -= 48f;
float minionPositionOffsetX = (10 + Projectile.minionPos * 40) * -player.direction; float minionPositionOffsetX = (10 + Projectile.minionPos * 40) * -player.direction;
@@ -83,10 +74,9 @@ public class ToclafaneMinion : ModProjectile
// All of this code below this line is adapted from Spazmamini code (ID 388, aiStyle 66) // All of this code below this line is adapted from Spazmamini code (ID 388, aiStyle 66)
// Teleport to player if distance is too big // Teleport to player if distance is too big
var vectorToIdlePosition = idlePosition - Projectile.Center; Vector2 vectorToIdlePosition = idlePosition - Projectile.Center;
var distanceToIdlePosition = vectorToIdlePosition.Length(); float distanceToIdlePosition = vectorToIdlePosition.Length();
if (Main.myPlayer == player.whoAmI && distanceToIdlePosition > 2000f) if (Main.myPlayer == player.whoAmI && distanceToIdlePosition > 2000f) {
{
// Whenever you deal with non-regular events that change the behavior or position drastically, make sure to only run the code on the owner of the projectile, // Whenever you deal with non-regular events that change the behavior or position drastically, make sure to only run the code on the owner of the projectile,
// and then set netUpdate to true // and then set netUpdate to true
Projectile.position = idlePosition; Projectile.position = idlePosition;
@@ -96,10 +86,9 @@ public class ToclafaneMinion : ModProjectile
// If your minion is flying, you want to do this independently of any conditions // If your minion is flying, you want to do this independently of any conditions
const float overlapVelocity = 0.04f; const float overlapVelocity = 0.04f;
for (var i = 0; i < Main.maxProjectiles; i++) for (int i = 0; i < Main.maxProjectiles; i++) {
{
// Fix overlap with other minions // Fix overlap with other minions
var other = Main.projectile[i]; Projectile other = Main.projectile[i];
if (i == Projectile.whoAmI || !other.active || other.owner != Projectile.owner || if (i == Projectile.whoAmI || !other.active || other.owner != Projectile.owner ||
!(Math.Abs(Projectile.position.X - other.position.X) + !(Math.Abs(Projectile.position.X - other.position.X) +
Math.Abs(Projectile.position.Y - other.position.Y) < Projectile.width)) continue; Math.Abs(Projectile.position.Y - other.position.Y) < Projectile.width)) continue;
@@ -114,38 +103,34 @@ public class ToclafaneMinion : ModProjectile
#region Find target #region Find target
// Starting search distance // Starting search distance
var distanceFromTarget = 700f; float distanceFromTarget = 700f;
var targetCenter = Projectile.position; Vector2 targetCenter = Projectile.position;
var foundTarget = false; bool foundTarget = false;
// This code is required if your minion weapon has the targeting feature // This code is required if your minion weapon has the targeting feature
if (player.HasMinionAttackTargetNPC) if (player.HasMinionAttackTargetNPC) {
{ NPC npc = Main.npc[player.MinionAttackTargetNPC];
var npc = Main.npc[player.MinionAttackTargetNPC]; float between = Vector2.Distance(npc.Center, Projectile.Center);
var between = Vector2.Distance(npc.Center, Projectile.Center);
// Reasonable distance away so it doesn't target across multiple screens // Reasonable distance away so it doesn't target across multiple screens
if (between < 2000f) if (between < 2000f) {
{
distanceFromTarget = between; distanceFromTarget = between;
targetCenter = npc.Center; targetCenter = npc.Center;
foundTarget = true; foundTarget = true;
} }
} }
if (!foundTarget) if (!foundTarget) {
{ for (int i = 0; i < Main.maxNPCs; i++) {
for (var i = 0; i < Main.maxNPCs; i++) NPC npc = Main.npc[i];
{
var npc = Main.npc[i];
if (!npc.CanBeChasedBy()) continue; if (!npc.CanBeChasedBy()) continue;
var between = Vector2.Distance(npc.Center, Projectile.Center); float between = Vector2.Distance(npc.Center, Projectile.Center);
var closest = Vector2.Distance(Projectile.Center, targetCenter) > between; bool closest = Vector2.Distance(Projectile.Center, targetCenter) > between;
var inRange = between < distanceFromTarget; bool inRange = between < distanceFromTarget;
var lineOfSight = Collision.CanHitLine(Projectile.position, Projectile.width, bool lineOfSight = Collision.CanHitLine(Projectile.position, Projectile.width,
Projectile.height, npc.position, npc.width, npc.height); Projectile.height, npc.position, npc.width, npc.height);
// Additional check for this specific minion behavior, otherwise it will stop attacking once it dashed through an enemy while flying though tiles afterwards // Additional check for this specific minion behavior, otherwise it will stop attacking once it dashed through an enemy while flying though tiles afterward
// The number depends on various parameters seen in the movement code below. Test different ones out until it works alright // The number depends on various parameters seen in the movement code below. Test different ones out until it works alright
var closeThroughWall = between < 100f; bool closeThroughWall = between < 100f;
if (((!closest || !inRange) && foundTarget) || (!lineOfSight && !closeThroughWall)) continue; if (((!closest || !inRange) && foundTarget) || (!lineOfSight && !closeThroughWall)) continue;
distanceFromTarget = between; distanceFromTarget = between;
targetCenter = npc.Center; targetCenter = npc.Center;
@@ -160,29 +145,25 @@ public class ToclafaneMinion : ModProjectile
#region Movement #region Movement
// Default movement parameters (here for attacking) // Default movement parameters (here for attacking)
var speed = 8f; float speed = 8f;
var inertia = 20f; float inertia = 20f;
if (foundTarget) if (foundTarget) {
{ Vector2 direction = targetCenter - Projectile.Center;
var direction = targetCenter - Projectile.Center;
direction.Normalize(); direction.Normalize();
if (distanceFromTarget > 40f) if (distanceFromTarget > 40f) {
{
// The immediate range around the target (so it doesn't latch onto it when close) // The immediate range around the target (so it doesn't latch onto it when close)
direction *= speed; direction *= speed;
Projectile.velocity = (Projectile.velocity * (inertia - 1) + direction) / inertia; Projectile.velocity = (Projectile.velocity * (inertia - 1) + direction) / inertia;
} }
switch (distanceFromTarget) switch (distanceFromTarget) {
{
case <= 120f: case <= 120f:
_attackMode = AttackMode.Melee; _attackMode = AttackMode.Melee;
break; break;
case > 120f when _shootCooldown == 0: case > 120f when _shootCooldown == 0: {
{
_shootCooldown = 60; // 1 second between shots _shootCooldown = 60; // 1 second between shots
var laser = Projectile.NewProjectileDirect(player.GetSource_FromThis(), Projectile.Center, Projectile laser = Projectile.NewProjectileDirect(player.GetSource_FromThis(), Projectile.Center,
direction, ProjectileID.DeathLaser, 30, Projectile.knockBack, Projectile.owner); direction, ProjectileID.DeathLaser, 30, Projectile.knockBack, Projectile.owner);
laser.friendly = true; laser.friendly = true;
laser.hostile = false; laser.hostile = false;
@@ -192,24 +173,20 @@ public class ToclafaneMinion : ModProjectile
} }
} }
} }
else else {
{
// Minion doesn't have a target: return to player and idle // Minion doesn't have a target: return to player and idle
if (distanceToIdlePosition > 600f) if (distanceToIdlePosition > 600f) {
{
// Speed up the minion if it's away from the player // Speed up the minion if it's away from the player
speed = 12f; speed = 12f;
inertia = 60f; inertia = 60f;
} }
else else {
{
// Slow down the minion if closer to the player // Slow down the minion if closer to the player
speed = 4f; speed = 4f;
inertia = 80f; inertia = 80f;
} }
if (distanceToIdlePosition > 20f) if (distanceToIdlePosition > 20f) {
{
// The immediate range around the player (when it passively floats about) // The immediate range around the player (when it passively floats about)
// This is a simple movement formula using the two parameters and its desired direction to create a "homing" movement // This is a simple movement formula using the two parameters and its desired direction to create a "homing" movement
@@ -217,8 +194,7 @@ public class ToclafaneMinion : ModProjectile
vectorToIdlePosition *= speed; vectorToIdlePosition *= speed;
Projectile.velocity = (Projectile.velocity * (inertia - 1) + vectorToIdlePosition) / inertia; Projectile.velocity = (Projectile.velocity * (inertia - 1) + vectorToIdlePosition) / inertia;
} }
else if (Projectile.velocity == Vector2.Zero) else if (Projectile.velocity == Vector2.Zero) {
{
// If there is a case where it's not moving at all, give it a little "poke" // If there is a case where it's not moving at all, give it a little "poke"
Projectile.velocity.X = -0.15f; Projectile.velocity.X = -0.15f;
Projectile.velocity.Y = -0.05f; Projectile.velocity.Y = -0.05f;
@@ -234,14 +210,11 @@ public class ToclafaneMinion : ModProjectile
const int frameSpeed = 8; const int frameSpeed = 8;
Projectile.frameCounter++; Projectile.frameCounter++;
if (Projectile.frameCounter >= frameSpeed) if (Projectile.frameCounter >= frameSpeed) {
{
Projectile.frameCounter = 0; Projectile.frameCounter = 0;
switch (_attackMode) switch (_attackMode) {
{
case AttackMode.Melee: case AttackMode.Melee:
switch (Projectile.frame) switch (Projectile.frame) {
{
case 0: case 0:
case 1: case 1:
case 2: case 2:
@@ -266,8 +239,7 @@ public class ToclafaneMinion : ModProjectile
break; break;
case AttackMode.Ranged: case AttackMode.Ranged:
switch (Projectile.frame) switch (Projectile.frame) {
{
case 0: case 0:
Projectile.frame = 5; Projectile.frame = 5;
break; break;
@@ -290,8 +262,6 @@ public class ToclafaneMinion : ModProjectile
break; break;
} }
break;
default:
break; break;
} }
} }
@@ -301,8 +271,7 @@ public class ToclafaneMinion : ModProjectile
#endregion #endregion
} }
private enum AttackMode private enum AttackMode {
{
Melee, Melee,
Ranged, Ranged,
} }
+15 -5
View File
@@ -1,14 +1,24 @@
using System.Collections.Generic;
using Terraria.ModLoader; using Terraria.ModLoader;
using YHTMod.Items;
namespace YHTMod;
public class YHTMod : Mod {
private static YHTMod _mod;
namespace YHTMod {
public class YHTMod : Mod {
private static YHTMod mod;
public YHTMod() { public YHTMod() {
mod = this; _mod = this;
} }
public static YHTMod GetInstance() { public static YHTMod GetInstance() {
return mod; return _mod;
} }
public static HashSet<int> GetAmbitionItems() {
return [
ModContent.ItemType<SummonersAmbition>(),
ModContent.ItemType<WarriorsAmbition>()
];
} }
} }
+4 -4
View File
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\tModLoader.targets" /> <Import Project="..\tModLoader.targets" />
<PropertyGroup> <PropertyGroup>
<AssemblyName>YHTMod</AssemblyName> <AssemblyName>YHTMod</AssemblyName>
<TargetFramework>net6.0</TargetFramework>
<PlatformTarget>AnyCPU</PlatformTarget>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="tModLoader.CodeAssist" Version="0.1.*" /> <Reference Include="CalamityMod">
<HintPath>..\ModAssemblies\CalamityMod_v2.0.7.2.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
</Project> </Project>
+136 -5
View File
@@ -1,21 +1,152 @@
using System; using System;
using System.Collections.Generic;
using Terraria.ModLoader; using Terraria.ModLoader;
using Terraria.ModLoader.IO;
using YHTMod.Buffs;
namespace YHTMod; namespace YHTMod;
public class YhtPlayer : ModPlayer { public class YhtPlayer : ModPlayer {
public int ArcaneMissile = 0;
public int KatanaTeleportCooldown = 0;
public int SummonerAmbitionDeerclopsCooldown = 0;
public int SummonerAmbitionPerforatorsCooldown = 0;
public int SummonerAmbitionHiveMindCooldown = 0;
public int arcaneMissle = 0;
public int katanaTeleportCooldown = 0; public bool SummonerAmbition = false;
public bool WarriorAmbition = false;
/**
* Set of boss and event ids for unlocking perks from Summoner's Ambition accessory
*/
public HashSet<string> SummonerAmbitions = [];
public HashSet<string> WarriorAmbitions = [];
public override void PreUpdate() { public override void PreUpdate() {
this.katanaTeleportCooldown = Math.Max(this.katanaTeleportCooldown - 1, 0); KatanaTeleportCooldown = Math.Max(KatanaTeleportCooldown - 1, 0);
SummonerAmbitionDeerclopsCooldown = Math.Max(SummonerAmbitionDeerclopsCooldown - 1, 0);
SummonerAmbitionPerforatorsCooldown = Math.Max(SummonerAmbitionPerforatorsCooldown - 1, 0);
SummonerAmbitionHiveMindCooldown = Math.Max(SummonerAmbitionHiveMindCooldown - 1, 0);
}
public override void PostUpdateEquips() {
if (SummonerAmbition) {
Player.AddBuff(ModContent.BuffType<SummonerAmbitionBuff>(), 1);
Player.maxMinions += GetSummonersAmbitionMinionBonus();
if (SummonerAmbitions.Contains("king_slime")) {
if (ModLoader.HasMod("CalamityMod")) {
Player.whipRangeMultiplier += 0.1f;
}
else {
Player.whipRangeMultiplier += 0.2f;
}
}
if (ModLoader.HasMod("CalamityMod") && SummonerAmbitions.Contains("desert_scourge")) {
Player.statLifeMax2 += 5;
}
if (SummonerAmbitions.Contains("eater_of_worlds")) {
Player.GetArmorPenetration(DamageClass.Summon) += 5;
}
if (SummonerAmbitions.Contains("brain_of_cthulhu")) {
Player.GetDamage(DamageClass.Summon) += 0.05f;
}
if (SummonerAmbitions.Contains("skeletron")) {
Player.GetKnockback(DamageClass.Summon) += 0.1f;
}
if (ModLoader.HasMod("CalamityMod") && SummonerAmbitions.Contains("slime_god")) {
Player.whipRangeMultiplier += 0.1f;
}
}
if (WarriorAmbition) {
Player.AddBuff(ModContent.BuffType<WarriorAmbitionBuff>(), 1);
Player.statDefense += GetWarriorsAmbitionDefenseBonus();
if (ModLoader.HasMod("CalamityMod") && SummonerAmbitions.Contains("desert_scourge")) {
Player.statLifeMax2 += 10;
}
}
}
public bool hasAmbitionEquipped() {
if (SummonerAmbition) return true;
if (WarriorAmbition) return true;
return false;
} }
public override void ResetEffects() { public override void ResetEffects() {
ArcaneMissile = 0;
this.arcaneMissle = 0; SummonerAmbition = false;
WarriorAmbition = false;
base.ResetEffects(); base.ResetEffects();
} }
public override void SaveData(TagCompound tag) {
tag["summonerAmbitions"] = new List<string>(SummonerAmbitions);
tag["warriorAmbitions"] = new List<string>(WarriorAmbitions);
}
public override void LoadData(TagCompound tag) {
if (tag.ContainsKey("summonerAmbitions")) {
IList<string> list = tag.GetList<string>("summonerAmbitions");
SummonerAmbitions = new HashSet<string>(list);
}
if (tag.ContainsKey("warriorAmbitions")) {
IList<string> warriorList = tag.GetList<string>("warriorAmbitions");
WarriorAmbitions = new HashSet<string>(warriorList);
}
}
public int GetSummonersAmbitionMinionBonus() {
int amount = 1;
if (SummonerAmbitions.Contains("wall_of_flesh")) {
amount += 1;
}
return amount;
}
public int GetWarriorsAmbitionDefenseBonus() {
int amount = 2;
if (ModLoader.HasMod("CalamityMod") && SummonerAmbitions.Contains("perforators")) {
amount += 2;
}
if (ModLoader.HasMod("CalamityMod") && SummonerAmbitions.Contains("hive_mind")) {
amount += 2;
}
if (WarriorAmbitions.Contains("wall_of_flesh")) {
amount += 5;
}
return amount;
}
public float GetWarriorsAmbitionMeleeSizeBonus() {
float scale = 1f;
if (WarriorAmbitions.Contains("king_slime")) {
if (ModLoader.HasMod("CalamityMod")) {
scale += 0.025f;
}
else {
scale += 0.05f;
}
}
if (ModLoader.HasMod("CalamityMod") && WarriorAmbitions.Contains("slime_god")) {
scale += 0.025f;
}
return scale;
}
} }
+2 -1
View File
@@ -1,3 +1,4 @@
displayName = YHT Mod displayName = YHT Mod
author = YouHaveTrouble author = YouHaveTrouble
version = 1.1.2 version = 1.3.2
weakReferences = CalamityMod@2.0.0.0
+1 -1
View File
@@ -6,4 +6,4 @@ Wiki: https://github.com/YouHaveTrouble/YHTMod/wiki
Source: https://github.com/YouHaveTrouble/YHTMod Source: https://github.com/YouHaveTrouble/YHTMod
Code: YouHaveTrouble Code: YouHaveTrouble
Sprites: YouHaveTrouble, Patrxon Sprites: YouHaveTrouble, Patrxon, SlyFox
+1 -1
View File
@@ -8,4 +8,4 @@ Discussion discord: [![Discord](https://img.shields.io/discord/82156510210857370
Code: YouHaveTrouble Code: YouHaveTrouble
Sprites: YouHaveTrouble, Patrxon Sprites: YouHaveTrouble, Patrxon, SlyFox