mirror of
https://github.com/YouHaveTrouble/YHTMod.git
synced 2026-05-11 21:56:54 +00:00
update to newest tmodloader version
This commit is contained in:
@@ -24,7 +24,7 @@ class MithrilPebbleOfPigSmitingProjectile : ModProjectile {
|
||||
base.AI();
|
||||
DrawOriginOffsetX = 0;
|
||||
DrawOffsetX = 0;
|
||||
int dust = Dust.NewDust(Projectile.Center, 1, 1, DustID.Mythril, 0f, 0f, 0, default(Color), 1f);
|
||||
var dust = Dust.NewDust(Projectile.Center, 1, 1, DustID.Mythril, 0f, 0f, 0, default(Color), 1f);
|
||||
Main.dust[dust].noGravity = true;
|
||||
Main.dust[dust].velocity *= 0.3f;
|
||||
}
|
||||
|
||||
@@ -7,13 +7,13 @@ using YHTMod.Buffs;
|
||||
|
||||
namespace YHTMod.Projectiles.Weapons;
|
||||
|
||||
public class ToclafaneMinion : ModProjectile {
|
||||
public class ToclafaneMinion : ModProjectile
|
||||
{
|
||||
private int _shootCooldown = 0;
|
||||
private AttackMode _attackMode = AttackMode.Ranged;
|
||||
|
||||
private int shootCooldown = 0;
|
||||
private AttackMode attackMode = AttackMode.RANGED;
|
||||
|
||||
public override void SetStaticDefaults() {
|
||||
DisplayName.SetDefault("Toclafane Minion");
|
||||
public override void SetStaticDefaults()
|
||||
{
|
||||
// Sets the amount of frames this minion has on its spritesheet
|
||||
Main.projFrames[Projectile.type] = 8;
|
||||
// This is necessary for right-click targeting
|
||||
@@ -23,7 +23,8 @@ public class ToclafaneMinion : ModProjectile {
|
||||
ProjectileID.Sets.MinionSacrificable[Projectile.type] = true;
|
||||
}
|
||||
|
||||
public sealed override void SetDefaults() {
|
||||
public sealed override void SetDefaults()
|
||||
{
|
||||
Projectile.width = 32;
|
||||
Projectile.height = 32;
|
||||
Projectile.scale = 0.65f;
|
||||
@@ -36,24 +37,29 @@ public class ToclafaneMinion : ModProjectile {
|
||||
Projectile.penetrate = -1;
|
||||
}
|
||||
|
||||
public override bool? CanCutTiles() {
|
||||
public override bool? CanCutTiles()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool MinionContactDamage() {
|
||||
public override bool MinionContactDamage()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void AI() {
|
||||
Player player = Main.player[Projectile.owner];
|
||||
public override void AI()
|
||||
{
|
||||
var player = Main.player[Projectile.owner];
|
||||
|
||||
#region Active check
|
||||
|
||||
if (player.dead || !player.active) {
|
||||
if (player.dead || !player.active)
|
||||
{
|
||||
player.ClearBuff(ModContent.BuffType<ToclafaneMinionBuff>());
|
||||
}
|
||||
|
||||
if (player.HasBuff(ModContent.BuffType<ToclafaneMinionBuff>())) {
|
||||
if (player.HasBuff(ModContent.BuffType<ToclafaneMinionBuff>()))
|
||||
{
|
||||
Projectile.timeLeft = 2;
|
||||
}
|
||||
|
||||
@@ -61,13 +67,14 @@ public class ToclafaneMinion : ModProjectile {
|
||||
|
||||
#region General behavior
|
||||
|
||||
if (shootCooldown > 0) {
|
||||
shootCooldown = shootCooldown - 1;
|
||||
if (_shootCooldown > 0)
|
||||
{
|
||||
_shootCooldown = _shootCooldown - 1;
|
||||
}
|
||||
|
||||
attackMode = AttackMode.RANGED;
|
||||
_attackMode = AttackMode.Ranged;
|
||||
|
||||
Vector2 idlePosition = player.Center;
|
||||
var idlePosition = player.Center;
|
||||
idlePosition.Y -= 48f;
|
||||
|
||||
float minionPositionOffsetX = (10 + Projectile.minionPos * 40) * -player.direction;
|
||||
@@ -76,9 +83,10 @@ public class ToclafaneMinion : ModProjectile {
|
||||
// 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) {
|
||||
var vectorToIdlePosition = idlePosition - Projectile.Center;
|
||||
var 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;
|
||||
@@ -87,18 +95,18 @@ public class ToclafaneMinion : ModProjectile {
|
||||
}
|
||||
|
||||
// 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++) {
|
||||
const float overlapVelocity = 0.04f;
|
||||
for (var 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;
|
||||
}
|
||||
var 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)) continue;
|
||||
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
|
||||
@@ -106,40 +114,42 @@ public class ToclafaneMinion : ModProjectile {
|
||||
#region Find target
|
||||
|
||||
// Starting search distance
|
||||
float distanceFromTarget = 700f;
|
||||
Vector2 targetCenter = Projectile.position;
|
||||
bool foundTarget = false;
|
||||
var distanceFromTarget = 700f;
|
||||
var targetCenter = Projectile.position;
|
||||
var 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);
|
||||
if (player.HasMinionAttackTargetNPC)
|
||||
{
|
||||
var npc = Main.npc[player.MinionAttackTargetNPC];
|
||||
var between = Vector2.Distance(npc.Center, Projectile.Center);
|
||||
// Reasonable distance away so it doesn't target across multiple screens
|
||||
if (between < 2000f) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (!foundTarget)
|
||||
{
|
||||
for (var i = 0; i < Main.maxNPCs; i++)
|
||||
{
|
||||
var npc = Main.npc[i];
|
||||
if (!npc.CanBeChasedBy()) continue;
|
||||
var between = Vector2.Distance(npc.Center, Projectile.Center);
|
||||
var closest = Vector2.Distance(Projectile.Center, targetCenter) > between;
|
||||
var inRange = between < distanceFromTarget;
|
||||
var 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
|
||||
var closeThroughWall = between < 100f;
|
||||
if (((!closest || !inRange) && foundTarget) || (!lineOfSight && !closeThroughWall)) continue;
|
||||
distanceFromTarget = between;
|
||||
targetCenter = npc.Center;
|
||||
foundTarget = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,46 +160,56 @@ public class ToclafaneMinion : ModProjectile {
|
||||
#region Movement
|
||||
|
||||
// Default movement parameters (here for attacking)
|
||||
float speed = 8f;
|
||||
float inertia = 20f;
|
||||
var speed = 8f;
|
||||
var inertia = 20f;
|
||||
|
||||
if (foundTarget) {
|
||||
Vector2 direction = targetCenter - Projectile.Center;
|
||||
if (foundTarget)
|
||||
{
|
||||
var direction = targetCenter - Projectile.Center;
|
||||
direction.Normalize();
|
||||
if (distanceFromTarget > 40f) {
|
||||
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;
|
||||
switch (distanceFromTarget)
|
||||
{
|
||||
case <= 120f:
|
||||
_attackMode = AttackMode.Melee;
|
||||
break;
|
||||
case > 120f when _shootCooldown == 0:
|
||||
{
|
||||
_shootCooldown = 60; // 1 second between shots
|
||||
var 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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
// 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 = 12f;
|
||||
inertia = 60f;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
// Slow down the minion if closer to the player
|
||||
speed = 4f;
|
||||
inertia = 80f;
|
||||
}
|
||||
|
||||
if (distanceToIdlePosition > 20f) {
|
||||
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
|
||||
@@ -197,7 +217,8 @@ public class ToclafaneMinion : ModProjectile {
|
||||
vectorToIdlePosition *= speed;
|
||||
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"
|
||||
Projectile.velocity.X = -0.15f;
|
||||
Projectile.velocity.Y = -0.05f;
|
||||
@@ -211,66 +232,67 @@ public class ToclafaneMinion : ModProjectile {
|
||||
// So it will lean slightly towards the direction it's moving
|
||||
Projectile.rotation = Projectile.velocity.X * 0.05f;
|
||||
|
||||
int frameSpeed = 8;
|
||||
const int frameSpeed = 8;
|
||||
Projectile.frameCounter++;
|
||||
if (Projectile.frameCounter >= frameSpeed) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
switch (_attackMode)
|
||||
{
|
||||
case AttackMode.Melee:
|
||||
switch (Projectile.frame)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case 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:
|
||||
case 5:
|
||||
case 6:
|
||||
Projectile.frame++;
|
||||
break;
|
||||
case 7:
|
||||
Projectile.frame = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,8 +301,9 @@ public class ToclafaneMinion : ModProjectile {
|
||||
#endregion
|
||||
}
|
||||
|
||||
enum AttackMode {
|
||||
MELEE,
|
||||
RANGED
|
||||
private enum AttackMode
|
||||
{
|
||||
Melee,
|
||||
Ranged,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user