Merge branch 'master' of https://github.com/YouHaveTrouble/YHTMod into feat-thekey

This commit is contained in:
2022-12-07 21:39:13 +01:00
16 changed files with 421 additions and 17 deletions
+24
View File
@@ -0,0 +1,24 @@
using Terraria;
using Terraria.ModLoader;
using YHTMod.Projectiles.Weapons;
namespace YHTMod.Buffs;
public class ToclafaneMinionBuff : ModBuff {
public override void SetStaticDefaults() {
DisplayName.SetDefault("Summon Toclafane");
Description.SetDefault("It came from a parallel world to fight for its Master.");
Main.buffNoSave[Type] = true;
Main.buffNoTimeDisplay[Type] = true;
}
public override void Update(Player player, ref int buffIndex) {
if (player.ownedProjectileCounts[ModContent.ProjectileType<ToclafaneMinion>()] > 0) {
player.buffTime[buffIndex] = 18000;
} else {
player.DelBuff(buffIndex);
buffIndex--;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

+1 -1
View File
@@ -16,4 +16,4 @@ public class NpcLoot : GlobalNPC
npcLoot.Add(ItemDropRule.Common(ModContent.ItemType<MithrilPebbleOfPigSmiting>(), 400, 1, 1));
}
}
}
}
+1 -1
View File
@@ -39,4 +39,4 @@ public class CopperSwordOnAStick : ModItem {
.AddIngredient(ItemID.CopperShortsword)
.Register();
}
}
}
+7 -10
View File
@@ -10,19 +10,16 @@ public class KatanaRedo : GlobalItem {
public override void ModifyTooltips(Item item, List<TooltipLine> tooltips)
{
if (item.type == ItemID.Katana) {
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."));
}
if (item.type != ItemID.Katana) return;
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."));
}
public override bool AltFunctionUse(Item item, Player player) {
if (item.type == ItemID.Katana) {
return true;
if (item.type != ItemID.Katana) {
return base.AltFunctionUse(item, player);
}
return base.AltFunctionUse(item, player);
return true;
}
public override bool? UseItem(Item item, Player player) {
@@ -52,4 +49,4 @@ public class KatanaRedo : GlobalItem {
return null;
}
}
}
+1 -1
View File
@@ -44,4 +44,4 @@ public class MithrilPebbleOfPigSmiting : ModItem {
Item.shootSpeed = 20f;
Item.shoot = ModContent.ProjectileType<MithrilPebbleOfPigSmitingProjectile>();
}
}
}
+84
View File
@@ -0,0 +1,84 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.DataStructures;
using Terraria.GameContent.Creative;
using Terraria.ID;
using Terraria.ModLoader;
using YHTMod.Buffs;
using YHTMod.Projectiles.Weapons;
namespace YHTMod.Items;
public class ToclafaneStaff : ModItem {
public override void SetStaticDefaults() {
DisplayName.SetDefault("Toclafane Staff");
Tooltip.SetDefault("Summons a toclafane to remove population for you");
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;
CreativeItemSacrificesCatalog.Instance.SacrificeCountNeededByItemId[Type] = 1;
}
public override void SetDefaults() {
Item.damage = 30;
Item.knockBack = 3f;
Item.mana = 10;
Item.width = 32;
Item.height = 32;
Item.useTime = 36;
Item.useAnimation = 36;
Item.useStyle = ItemUseStyleID.Swing;
Item.value = Item.buyPrice(0, 30, 0, 0);
Item.rare = ItemRarityID.Cyan;
Item.UseSound = SoundID.Item44;
Item.noMelee = true;
Item.DamageType = DamageClass.Summon;
Item.buffType = ModContent.BuffType<ToclafaneMinionBuff>();
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) {
player.AddBuff(Item.buffType, 2);
position = Main.MouseWorld;
return base.Shoot(player, source, position, velocity, type, damage, knockback);
}
public override void AddRecipes() {
CreateRecipe()
.AddIngredient(ItemID.GuideVoodooDoll, 1)
.AddIngredient(ItemID.HallowedBar, 15)
.AddIngredient(ItemID.CopperWatch)
.AddTile(TileID.MythrilAnvil)
.Register();
CreateRecipe()
.AddIngredient(ItemID.GuideVoodooDoll, 1)
.AddIngredient(ItemID.HallowedBar, 15)
.AddIngredient(ItemID.TinWatch)
.AddTile(TileID.MythrilAnvil)
.Register();
CreateRecipe()
.AddIngredient(ItemID.GuideVoodooDoll, 1)
.AddIngredient(ItemID.HallowedBar, 15)
.AddIngredient(ItemID.SilverWatch)
.AddTile(TileID.MythrilAnvil)
.Register();
CreateRecipe()
.AddIngredient(ItemID.GuideVoodooDoll, 1)
.AddIngredient(ItemID.HallowedBar, 15)
.AddIngredient(ItemID.TungstenWatch)
.AddTile(TileID.MythrilAnvil)
.Register();
CreateRecipe()
.AddIngredient(ItemID.GuideVoodooDoll, 1)
.AddIngredient(ItemID.HallowedBar, 15)
.AddTile(TileID.MythrilAnvil)
.AddIngredient(ItemID.GoldWatch)
.Register();
CreateRecipe()
.AddIngredient(ItemID.GuideVoodooDoll, 1)
.AddIngredient(ItemID.HallowedBar, 15)
.AddIngredient(ItemID.PlatinumWatch)
.AddTile(TileID.MythrilAnvil)
.Register();
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 338 B

@@ -29,4 +29,4 @@ class CopperSwordOnAStickProjectile : ModProjectile {
DrawOriginOffsetX = 0;
DrawOffsetX = 0;
}
}
}
@@ -28,4 +28,4 @@ class MithrilPebbleOfPigSmitingProjectile : ModProjectile {
Main.dust[dust].noGravity = true;
Main.dust[dust].velocity *= 0.3f;
}
}
}
+286
View File
@@ -0,0 +1,286 @@
using System;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using YHTMod.Buffs;
namespace YHTMod.Projectiles.Weapons;
public class ToclafaneMinion : ModProjectile {
private int shootCooldown = 0;
private AttackMode attackMode = AttackMode.RANGED;
public override void SetStaticDefaults() {
DisplayName.SetDefault("Toclafane Minion");
// Sets the amount of frames this minion has on its spritesheet
Main.projFrames[Projectile.type] = 8;
// This is necessary for right-click targeting
ProjectileID.Sets.MinionTargettingFeature[Projectile.type] = true;
Main.projPet[Projectile.type] = true;
ProjectileID.Sets.MinionSacrificable[Projectile.type] = true;
}
public sealed override void SetDefaults() {
Projectile.width = 32;
Projectile.height = 32;
Projectile.scale = 0.65f;
Projectile.tileCollide = false;
Projectile.friendly = true;
Projectile.minion = true;
Projectile.minionSlots = 1f;
Projectile.penetrate = -1;
}
public override bool? CanCutTiles() {
return false;
}
public override bool MinionContactDamage() {
return true;
}
public override void AI() {
Player player = Main.player[Projectile.owner];
#region Active check
if (player.dead || !player.active) {
player.ClearBuff(ModContent.BuffType<ToclafaneMinionBuff>());
}
if (player.HasBuff(ModContent.BuffType<ToclafaneMinionBuff>())) {
Projectile.timeLeft = 2;
}
#endregion
#region General behavior
if (shootCooldown > 0) {
shootCooldown = shootCooldown - 1;
}
attackMode = AttackMode.RANGED;
Vector2 idlePosition = player.Center;
idlePosition.Y -= 48f;
float minionPositionOffsetX = (10 + Projectile.minionPos * 40) * -player.direction;
idlePosition.X += minionPositionOffsetX;
// All of this code below this line is adapted from Spazmamini code (ID 388, aiStyle 66)
// Teleport to player if distance is too big
Vector2 vectorToIdlePosition = idlePosition - Projectile.Center;
float distanceToIdlePosition = vectorToIdlePosition.Length();
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,
// and then set netUpdate to true
Projectile.position = idlePosition;
Projectile.velocity *= 0.1f;
Projectile.netUpdate = true;
}
// If your minion is flying, you want to do this independently of any conditions
float overlapVelocity = 0.04f;
for (int i = 0; i < Main.maxProjectiles; i++) {
// Fix overlap with other minions
Projectile other = Main.projectile[i];
if (i != Projectile.whoAmI && other.active && other.owner == Projectile.owner &&
Math.Abs(Projectile.position.X - other.position.X) +
Math.Abs(Projectile.position.Y - other.position.Y) < Projectile.width) {
if (Projectile.position.X < other.position.X) Projectile.velocity.X -= overlapVelocity;
else Projectile.velocity.X += overlapVelocity;
if (Projectile.position.Y < other.position.Y) Projectile.velocity.Y -= overlapVelocity;
else Projectile.velocity.Y += overlapVelocity;
}
}
#endregion
#region Find target
// Starting search distance
float distanceFromTarget = 700f;
Vector2 targetCenter = Projectile.position;
bool foundTarget = false;
// This code is required if your minion weapon has the targeting feature
if (player.HasMinionAttackTargetNPC) {
NPC npc = Main.npc[player.MinionAttackTargetNPC];
float between = Vector2.Distance(npc.Center, Projectile.Center);
// Reasonable distance away so it doesn't target across multiple screens
if (between < 2000f) {
distanceFromTarget = between;
targetCenter = npc.Center;
foundTarget = true;
}
}
if (!foundTarget) {
for (int i = 0; i < Main.maxNPCs; i++) {
NPC npc = Main.npc[i];
if (npc.CanBeChasedBy()) {
float between = Vector2.Distance(npc.Center, Projectile.Center);
bool closest = Vector2.Distance(Projectile.Center, targetCenter) > between;
bool inRange = between < distanceFromTarget;
bool lineOfSight = Collision.CanHitLine(Projectile.position, Projectile.width,
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
// The number depends on various parameters seen in the movement code below. Test different ones out until it works alright
bool closeThroughWall = between < 100f;
if (((closest && inRange) || !foundTarget) && (lineOfSight || closeThroughWall)) {
distanceFromTarget = between;
targetCenter = npc.Center;
foundTarget = true;
}
}
}
}
Projectile.friendly = foundTarget;
#endregion
#region Movement
// Default movement parameters (here for attacking)
float speed = 8f;
float inertia = 20f;
if (foundTarget) {
Vector2 direction = targetCenter - Projectile.Center;
direction.Normalize();
if (distanceFromTarget > 40f) {
// The immediate range around the target (so it doesn't latch onto it when close)
direction *= speed;
Projectile.velocity = (Projectile.velocity * (inertia - 1) + direction) / inertia;
}
if (distanceFromTarget <= 120f) {
attackMode = AttackMode.MELEE;
}
if (distanceFromTarget > 120f && shootCooldown == 0) {
shootCooldown = 60; // 1 second between shots
Projectile laser = Projectile.NewProjectileDirect(player.GetSource_FromThis(), Projectile.Center,
direction, ProjectileID.DeathLaser, 30, Projectile.knockBack, Projectile.owner);
laser.friendly = true;
laser.hostile = false;
laser.penetrate = 5;
attackMode = AttackMode.RANGED;
}
}
else {
// Minion doesn't have a target: return to player and idle
if (distanceToIdlePosition > 600f) {
// Speed up the minion if it's away from the player
speed = 12f;
inertia = 60f;
}
else {
// Slow down the minion if closer to the player
speed = 4f;
inertia = 80f;
}
if (distanceToIdlePosition > 20f) {
// 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
vectorToIdlePosition.Normalize();
vectorToIdlePosition *= speed;
Projectile.velocity = (Projectile.velocity * (inertia - 1) + vectorToIdlePosition) / inertia;
}
else if (Projectile.velocity == Vector2.Zero) {
// If there is a case where it's not moving at all, give it a little "poke"
Projectile.velocity.X = -0.15f;
Projectile.velocity.Y = -0.05f;
}
}
#endregion
#region Animation and visuals
// So it will lean slightly towards the direction it's moving
Projectile.rotation = Projectile.velocity.X * 0.05f;
int frameSpeed = 8;
Projectile.frameCounter++;
if (Projectile.frameCounter >= frameSpeed) {
Projectile.frameCounter = 0;
if (attackMode == AttackMode.MELEE) {
switch (Projectile.frame) {
case 0:
Projectile.frame++;
break;
case 1:
Projectile.frame++;
break;
case 2:
Projectile.frame++;
break;
case 3:
Projectile.frame = 0;
break;
case 4:
Projectile.frame = 1;
break;
case 5:
Projectile.frame = 2;
break;
case 6:
Projectile.frame = 3;
break;
case 7:
Projectile.frame = 4;
break;
}
}
if (attackMode == AttackMode.RANGED) {
switch (Projectile.frame) {
case 0:
Projectile.frame = 5;
break;
case 1:
Projectile.frame = 6;
break;
case 2:
Projectile.frame = 7;
break;
case 3:
Projectile.frame = 4;
break;
case 4:
Projectile.frame++;
break;
case 5:
Projectile.frame++;
break;
case 6:
Projectile.frame++;
break;
case 7:
Projectile.frame = 4;
break;
}
}
}
Lighting.AddLight(Projectile.Center, Color.White.ToVector3() * 0.78f);
#endregion
}
enum AttackMode {
MELEE,
RANGED
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

+1 -1
View File
@@ -1,3 +1,3 @@
displayName = YHT Mod
author = YouHaveTrouble
version = 0.1
version = 1.0.1
+7 -1
View File
@@ -1 +1,7 @@
Bunch of random additions ranging from QoL to random references
Bunch of random additions ranging from QoL to random references
Wiki: https://github.com/YouHaveTrouble/YHTMod/wiki
Source: https://github.com/YouHaveTrouble/YHTMod
Code: YouHaveTrouble
Sprites: YouHaveTrouble, Patrxon
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 30 KiB

+7
View File
@@ -0,0 +1,7 @@
A bunch of random additions ranging from QoL to random references
Mod wiki: https://github.com/YouHaveTrouble/YHTMod/wiki
Code: YouHaveTrouble
Sprites: YouHaveTrouble, Patrxon