Advertisement
Guest User

sdasdadsd

a guest
May 19th, 2019
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.36 KB | None | 0 0
  1. using Narutoria.Items.Weapons;
  2. using Microsoft.Xna.Framework;
  3. using System.Collections.Generic;
  4. using Terraria;
  5. using Terraria.ID;
  6. using Terraria.ModLoader;
  7.  
  8. namespace Narutoria.Projectiles
  9. {
  10.     public class KunaiP : ModProjectile
  11.     {
  12.         public override void SetStaticDefaults() {
  13.             DisplayName.SetDefault("KunaiP");
  14.         }
  15.  
  16.         public override void SetDefaults() {
  17.             projectile.width = 16;
  18.             projectile.height = 16;
  19.             projectile.aiStyle = -1;
  20.             projectile.friendly = true;
  21.             projectile.melee = true;
  22.             projectile.penetrate = 3;
  23.             projectile.hide = true;
  24.         }
  25.  
  26.         // See ExampleBehindTilesProjectile.
  27.         public override void DrawBehind(int index, List<int> drawCacheProjsBehindNPCsAndTiles, List<int> drawCacheProjsBehindNPCs, List<int> drawCacheProjsBehindProjectiles, List<int> drawCacheProjsOverWiresUI) {
  28.             // If attached to an NPC, draw behind tiles (and the npc) if that NPC is behind tiles, otherwise just behind the NPC.
  29.             if (projectile.ai[0] == 1f) // or if(isStickingToTarget) since we made that helper method.
  30.             {
  31.                 int npcIndex = (int)projectile.ai[1];
  32.                 if (npcIndex >= 0 && npcIndex < 200 && Main.npc[npcIndex].active) {
  33.                     if (Main.npc[npcIndex].behindTiles) {
  34.                         drawCacheProjsBehindNPCsAndTiles.Add(index);
  35.                     }
  36.                     else {
  37.                         drawCacheProjsBehindNPCs.Add(index);
  38.                     }
  39.  
  40.                     return;
  41.                 }
  42.             }
  43.             // Since we aren't attached, add to this list
  44.             drawCacheProjsBehindProjectiles.Add(index);
  45.         }
  46.  
  47.         public override bool TileCollideStyle(ref int width, ref int height, ref bool fallThrough) {
  48.             // For going through platforms and such, javelins use a tad smaller size
  49.             width = height = 10; // notice we set the width to the height, the height to 10. so both are 10
  50.             return true;
  51.         }
  52.  
  53.         public override bool? Colliding(Rectangle projHitbox, Rectangle targetHitbox) {
  54.             // Inflate some target hitboxes if they are beyond 8,8 size
  55.             if (targetHitbox.Width > 8 && targetHitbox.Height > 8) {
  56.                 targetHitbox.Inflate(-targetHitbox.Width / 8, -targetHitbox.Height / 8);
  57.             }
  58.             // Return if the hitboxes intersects, which means the javelin collides or not
  59.             return projHitbox.Intersects(targetHitbox);
  60.         }
  61.  
  62.         public override void Kill(int timeLeft) {
  63.             Main.PlaySound(0, (int)projectile.position.X, (int)projectile.position.Y); // Play a death sound
  64.             Vector2 usePos = projectile.position; // Position to use for dusts
  65.                                                   // Please note the usage of MathHelper, please use this! We subtract 90 degrees as radians to the rotation vector to offset the sprite as its default rotation in the sprite isn't aligned properly.
  66.             Vector2 rotVector =
  67.                 (projectile.rotation - MathHelper.ToRadians(90f)).ToRotationVector2(); // rotation vector to use for dust velocity
  68.             usePos += rotVector * 16f;
  69.  
  70.             // Spawn some dusts upon javelin death
  71.             for (int i = 0; i < 20; i++) {
  72.                 // Create a new dust
  73.                 Dust dust = Dust.NewDustDirect(usePos, projectile.width, projectile.height, 81);
  74.                 dust.position = (dust.position + projectile.Center) / 2f;
  75.                 dust.velocity += rotVector * 2f;
  76.                 dust.velocity *= 0.5f;
  77.                 dust.noGravity = true;
  78.                 usePos -= rotVector * 8f;
  79.             }
  80.  
  81.             // Make sure to only spawn items if you are the projectile owner.
  82.             if (projectile.owner == Main.myPlayer) {
  83.                 // Drop a javelin item, 1 in 18 chance (~5.5% chance)
  84.                 int item =
  85.                 Main.rand.NextBool(18)
  86.                     ? Item.NewItem(projectile.getRect(), mod.ItemType<Kunai>())
  87.                     : 0;
  88.  
  89.                 // Sync the drop for multiplayer
  90.                 // Note the usage of Terraria.ID.MessageID, please use this!
  91.                 if (Main.netMode == 1 && item >= 0) {
  92.                     NetMessage.SendData(MessageID.SyncItem, -1, -1, null, item, 1f);
  93.                 }
  94.             }
  95.         }
  96.  
  97.         // Here's an example on how you could make your AI even more readable, by giving AI fields more descriptive names
  98.         // These are not used in AI, but it is good practice to apply some form like this to keep things organized
  99.  
  100.         // Are we sticking to a target?
  101.         public bool isStickingToTarget {
  102.         get { return projectile.ai[0] == 1f; }
  103.         set { projectile.ai[0] = value ? 1f : 0f; }
  104.         }
  105.         // WhoAmI of the current target
  106.         public float movementFactor {
  107.         get { return projectile.ai[0]; }
  108.         set { projectile.ai[0] = value; }
  109.         }
  110.  
  111.         public override void ModifyHitNPC(NPC target, ref int damage, ref float knockback, ref bool crit,
  112.             ref int hitDirection) {
  113.             // If you'd use the example above, you'd do: isStickingToTarget = 1f;
  114.             // and: targetWhoAmI = (float)target.whoAmI;
  115.             isStickingToTarget = true; // we are sticking to a target
  116.             targetWhoAmI = (float)target.whoAmI; // Set the target whoAmI
  117.             projectile.velocity =
  118.                 (target.Center - projectile.Center) *
  119.                 0.75f; // Change velocity based on delta center of targets (difference between entity centers)
  120.             projectile.netUpdate = true; // netUpdate this javelin
  121.             target.AddBuff(mod.BuffType<Buffs.ExampleJavelin>(), 900); // Adds the ExampleJavelin debuff for a very small DoT
  122.  
  123.             projectile.damage = 0; // Makes sure the sticking javelins do not deal damage anymore
  124.  
  125.             // The following code handles the javelin sticking to the enemy hit.
  126.             int maxStickingJavelins = 6; // This is the max. amount of javelins being able to attach
  127.             Point[] stickingJavelins = new Point[maxStickingJavelins]; // The point array holding for sticking javelins
  128.             int javelinIndex = 0; // The javelin index
  129.             for (int i = 0; i < Main.maxProjectiles; i++) // Loop all projectiles
  130.             {
  131.                 Projectile currentProjectile = Main.projectile[i];
  132.                 if (i != projectile.whoAmI // Make sure the looped projectile is not the current javelin
  133.                     && currentProjectile.active // Make sure the projectile is active
  134.                     && currentProjectile.owner == Main.myPlayer // Make sure the projectile's owner is the client's player
  135.                     && currentProjectile.type == projectile.type // Make sure the projectile is of the same type as this javelin
  136.                     && currentProjectile.ai[0] == 1f // Make sure ai0 state is set to 1f (set earlier in ModifyHitNPC)
  137.                     && currentProjectile.ai[1] == (float)target.whoAmI
  138.                 ) // Make sure ai1 is set to the target whoAmI (set earlier in ModifyHitNPC)
  139.                 {
  140.                     stickingJavelins[javelinIndex++] =
  141.                         new Point(i, currentProjectile.timeLeft); // Add the current projectile's index and timeleft to the point array
  142.                     if (javelinIndex >= stickingJavelins.Length
  143.                     ) // If the javelin's index is bigger than or equal to the point array's length, break
  144.                     {
  145.                         break;
  146.                     }
  147.                 }
  148.             }
  149.             // Here we loop the other javelins if new javelin needs to take an older javelin's place.
  150.             if (javelinIndex >= stickingJavelins.Length) {
  151.                 int oldJavelinIndex = 0;
  152.                 // Loop our point array
  153.                 for (int i = 1; i < stickingJavelins.Length; i++) {
  154.                     // Remove the already existing javelin if it's timeLeft value (which is the Y value in our point array) is smaller than the new javelin's timeLeft
  155.                     if (stickingJavelins[i].Y < stickingJavelins[oldJavelinIndex].Y) {
  156.                         oldJavelinIndex = i; // Remember the index of the removed javelin
  157.                     }
  158.                 }
  159.                 // Remember that the X value in our point array was equal to the index of that javelin, so it's used here to kill it.
  160.                 Main.projectile[stickingJavelins[oldJavelinIndex].X].Kill();
  161.             }
  162.         }
  163.  
  164.         // Added these 2 constant to showcase how you could make AI code cleaner by doing this
  165.         // Change this number if you want to alter how long the javelin can travel at a constant speed
  166.         private const float maxTicks = 45f;
  167.  
  168.         // Change this number if you want to alter how the alpha changes
  169.         private const int alphaReduction = 25;
  170.  
  171.         public override void AI() {
  172.             // Slowly remove alpha as it is present
  173.             if (projectile.alpha > 0) {
  174.                 projectile.alpha -= alphaReduction;
  175.             }
  176.             // If alpha gets lower than 0, set it to 0
  177.             if (projectile.alpha < 0) {
  178.                 projectile.alpha = 0;
  179.             }
  180.             // If ai0 is 0f, run this code. This is the 'movement' code for the javelin as long as it isn't sticking to a target
  181.             if (!isStickingToTarget) {
  182.                 targetWhoAmI += 1f;
  183.                 // For a little while, the javelin will travel with the same speed, but after this, the javelin drops velocity very quickly.
  184.                 if (targetWhoAmI >= maxTicks) {
  185.                     // Change these multiplication factors to alter the javelin's movement change after reaching maxTicks
  186.                     float velXmult = 0.98f; // x velocity factor, every AI update the x velocity will be 98% of the original speed
  187.                     float
  188.                         velYmult = 0.35f; // y velocity factor, every AI update the y velocity will be be 0.35f bigger of the original speed, causing the javelin to drop to the ground
  189.                     targetWhoAmI = maxTicks; // set ai1 to maxTicks continuously
  190.                     projectile.velocity.X = projectile.velocity.X * velXmult;
  191.                     projectile.velocity.Y = projectile.velocity.Y + velYmult;
  192.                 }
  193.                 // Make sure to set the rotation accordingly to the velocity, and add some to work around the sprite's rotation
  194.                 projectile.rotation =
  195.                     projectile.velocity.ToRotation() +
  196.                     MathHelper.ToRadians(
  197.                         90f); // Please notice the MathHelper usage, offset the rotation by 90 degrees (to radians because rotation uses radians) because the sprite's rotation is not aligned!
  198.  
  199.                 // Spawn some random dusts as the javelin travels
  200.                 if (Main.rand.NextBool(3)) {
  201.                     Dust dust = Dust.NewDustDirect(projectile.position, projectile.height, projectile.width, mod.DustType<Dusts.Sparkle>(),
  202.                         projectile.velocity.X * .2f, projectile.velocity.Y * .2f, 200, Scale: 1.2f);
  203.                     dust.velocity += projectile.velocity * 0.3f;
  204.                     dust.velocity *= 0.2f;
  205.                 }
  206.                 if (Main.rand.NextBool(4)) {
  207.                     Dust dust = Dust.NewDustDirect(projectile.position, projectile.height, projectile.width, mod.DustType<Dusts.Sparkle>(),
  208.                         0, 0, 254, Scale: 0.3f);
  209.                     dust.velocity += projectile.velocity * 0.5f;
  210.                     dust.velocity *= 0.5f;
  211.                 }
  212.             }
  213.             // This code is ran when the javelin is sticking to a target
  214.             if (isStickingToTarget) {
  215.                 // These 2 could probably be moved to the ModifyNPCHit hook, but in vanilla they are present in the AI
  216.                 projectile.ignoreWater = true; // Make sure the projectile ignores water
  217.                 projectile.tileCollide = false; // Make sure the projectile doesn't collide with tiles anymore
  218.                 int aiFactor = 15; // Change this factor to change the 'lifetime' of this sticking javelin
  219.                 bool killProj = false; // if true, kill projectile at the end
  220.                 bool hitEffect = false; // if true, perform a hit effect
  221.                 projectile.localAI[0] += 1f;
  222.                 // Every 30 ticks, the javelin will perform a hit effect
  223.                 hitEffect = projectile.localAI[0] % 30f == 0f;
  224.                 int projTargetIndex = (int)targetWhoAmI;
  225.                 if (projectile.localAI[0] >= (float)(60 * aiFactor) || projTargetIndex < 0 || projTargetIndex >= 200) // If the index is past its limits, kill it
  226.                 {
  227.                     killProj = true;
  228.                 }
  229.                 else if (Main.npc[projTargetIndex].active && !Main.npc[projTargetIndex].dontTakeDamage) // If the target is active and can take damage
  230.                 {
  231.                     // Set the projectile's position relative to the target's center
  232.                     projectile.Center = Main.npc[projTargetIndex].Center - projectile.velocity * 2f;
  233.                     projectile.gfxOffY = Main.npc[projTargetIndex].gfxOffY;
  234.                     if (hitEffect) // Perform a hit effect here
  235.                     {
  236.                         Main.npc[projTargetIndex].HitEffect(0, 1.0);
  237.                     }
  238.                 }
  239.                 else // Otherwise, kill the projectile
  240.                 {
  241.                     killProj = true;
  242.                 }
  243.  
  244.                 if (killProj) // Kill the projectile
  245.                 {
  246.                     projectile.Kill();
  247.                 }
  248.             }
  249.         }
  250.     }
  251. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement