public void Name_SetNullValue_ThrowsArgumentNullException() { var terrariaProjectile = new Terraria.Projectile(); var projectile = new OrionProjectile(terrariaProjectile); Assert.Throws <ArgumentNullException>(() => projectile.Name = null !); }
public static bool Kill_KillProjectile(Terraria.Projectile __instance) { // The specially named __instance parameter is automatically filled in by Harmony to reference the Projectile instance that is calling this method. if (!PluginLoadedSuccessfully) // If there was a problem loading things for our plugin, we will abort this stub method so we dont crash Terraria. { return(true); // Allow the original method to execute } if (__instance.type == 3001) { // Instead of instantly being removed, we'll make our projectile fade out over 20 frames if (__instance.timeLeft > 30) { __instance.timeLeft = 30; // Set the projectile to disappear 30 frames from now __instance.tileCollide = false; // Disable tile collisions during this fade out period return(false); // Skip the original Kill method (so our projectile stays alive just a bit longer) } else if (__instance.timeLeft > 0) { return(false); // Don't allow the original Kill method to run (yet), since we still have frames left before timeLeft reaches 0 } } return(true); // Allow original method to run }
internal void CleanupProjectile() { if (projectile != null) { // Projectile.FreeSlot(projectile.identity, projectile.Owner, projectile.Id); projectile = null; } }
public override bool Shoot(Player player, ref Vector2 position, ref float speedX, ref float speedY, ref int type, ref int damage, ref float knockBack) { Projectile.NewProjectile(position, new Vector2(speedX, speedY), ModContent.ProjectileType <SmallExplosiveProjectile>(), item.damage, item.knockBack); //ModContent.ProjectileType<MagicBombProjectile>() item.damage = 100; return(false); }
public void Id_Get() { var terrariaProjectile = new Terraria.Projectile { type = (int)ProjectileId.CrystalBullet }; var projectile = new OrionProjectile(terrariaProjectile); Assert.Equal(ProjectileId.CrystalBullet, projectile.Id); }
public void Name_Set_Get() { var terrariaProjectile = new Terraria.Projectile(); var projectile = new OrionProjectile(terrariaProjectile); projectile.Name = "test"; Assert.Equal("test", projectile.Name); }
public void Name_Get() { var terrariaProjectile = new Terraria.Projectile { type = (int)ProjectileId.WoodenArrow }; var projectile = new OrionProjectile(terrariaProjectile); Assert.Equal("Wooden Arrow", projectile.Name); }
public void SetId() { var terrariaProjectile = new Terraria.Projectile(); var projectile = new OrionProjectile(terrariaProjectile); projectile.SetId(ProjectileId.CrystalBullet); Assert.Equal(ProjectileId.CrystalBullet, (ProjectileId)terrariaProjectile.type); }
public void Knockback_Set() { var terrariaProjectile = new Terraria.Projectile(); var projectile = new OrionProjectile(terrariaProjectile); projectile.Knockback = 2.34f; Assert.Equal(2.34f, terrariaProjectile.knockBack); }
public void Damage_Get() { var terrariaProjectile = new Terraria.Projectile { damage = 123 }; var projectile = new OrionProjectile(terrariaProjectile); Assert.Equal(123, projectile.Damage); }
public void Damage_Set() { var terrariaProjectile = new Terraria.Projectile(); var projectile = new OrionProjectile(terrariaProjectile); projectile.Damage = 123; Assert.Equal(123, terrariaProjectile.damage); }
public void Knockback_Get() { var terrariaProjectile = new Terraria.Projectile { knockBack = 2.34f }; var projectile = new OrionProjectile(terrariaProjectile); Assert.Equal(2.34f, projectile.Knockback); }
public static bool DrawProj_DrawProjectile(Terraria.Main __instance, int i) { // The specially named __instance parameter is automatically filled in by Harmony to reference the Main instance that is calling this method. // The i parameter is automatically filled in by Harmony to be the same value as the i parameter that was passed to the original method. if (!PluginLoadedSuccessfully) // If there was a problem loading things for our plugin, we will abort this stub method so we dont crash Terraria. { return(true); // Allow the original method to execute } if (Terraria.Main.projectile[i].type == 3001) // Only run this drawing code if the projectile that's trying to draw actually is our custom projectile { // Get our projectile from the main projectile array Terraria.Projectile proj = Terraria.Main.projectile[i]; // This must be called before any projectile is drawn __instance.PrepareDrawnEntityDrawing(proj, Terraria.Main.GetProjectileDesiredShader(i)); // Get how much light is at the projectile's current position (will be used for a slight color modulation effect) Color lightAtProjPos = Terraria.Lighting.GetColor((int)(proj.position.X + (proj.width * 0.5f)) / 16, (int)((proj.position.Y + (proj.height * 0.5f)) / 16)); // Lerp at a constant 75% between the tile light and pure white to slightly modulate the projectile's color Color projColorMix = Color.Lerp(lightAtProjPos, Color.White, 0.75f); // Fade out the projectile if it's close to being removed if (proj.timeLeft <= 30) { projColorMix = projColorMix * (proj.timeLeft / 30f); } // Get the projectile's texture and figure out what section contains the frame we want Texture2D projTex = Terraria.GameContent.TextureAssets.Projectile[proj.type].Value; int texFrameHeight = projTex.Height / Terraria.Main.projFrames[proj.type]; int texFrameYPos = texFrameHeight * (proj.frame / 4); // Our code in AI() makes proj.frame go up to 4x the actual max frame so that we can divide it here for 1/4 of a 60fps framerate // Find the viewportspace position to draw the projectile at Vector2 drawPosition = proj.position + (new Vector2(projTex.Width, texFrameHeight) * 0.5f) // Use the texture's dimensions instead of proj.Width and proj.Height, since our projectile's Width & Height are undersized (for collision purposes) + (Vector2.UnitY * proj.gfxOffY) - Terraria.Main.screenPosition; // Draw it Terraria.Main.EntitySpriteDraw(projTex, drawPosition, new Rectangle(0, texFrameYPos, projTex.Width, texFrameHeight), projColorMix, proj.rotation, new Vector2(projTex.Width * 0.5f, texFrameHeight * 0.5f), 1f, SpriteEffects.None, 0); return(false); // Skip over original method } return(true); // Allow original method to run }
// Gets an `IProjectile` instance corresponding to the given Terraria projectile, avoiding extra allocations // if possible. private IProjectile GetProjectile(Terraria.Projectile terrariaProjectile) { var projectileIndex = terrariaProjectile.whoAmI; Debug.Assert(projectileIndex >= 0 && projectileIndex < Count); var isConcrete = terrariaProjectile == Terraria.Main.projectile[projectileIndex]; return(isConcrete ? this[projectileIndex] : new OrionProjectile(terrariaProjectile)); }
private OTAPI.HookResult PreUpdateHandler(Terraria.Projectile terrariaProjectile, ref int projectileIndex) { Debug.Assert(projectileIndex >= 0 && projectileIndex < Count); var projectile = this[projectileIndex]; var evt = new ProjectileTickEvent(projectile); _events.Raise(evt, _log); return(evt.IsCanceled ? OTAPI.HookResult.Cancel : OTAPI.HookResult.Continue); }
public static bool AI_ProjectileUpdate(Terraria.Projectile __instance) { // The specially named __instance parameter is automatically filled in by Harmony to reference the Projectile instance that is calling this method. if (!PluginLoadedSuccessfully) // If there was a problem loading things for our plugin, we will abort this stub method so we dont crash Terraria. { return(true); // Allow the original method to execute } if (__instance.type == 3001) // Only run this update code if the projectile that's calling AI actually is our custom projectile { // Increment animation frame __instance.frame++; if (__instance.frame >= 8 * 4) // We'll let the frame variable go up to 4x the actual frame count, then divide frame by 4 in drawing code to get 1/4 of a 60fps framerate { __instance.frame = 0; } // Make some dust particles if (Terraria.Main.rand.Next(3) == 0) { float scale = 0.35f; if (Terraria.Main.rand.Next(3) == 0) { scale = 0.55f; } Terraria.Dust dust = Terraria.Dust.NewDustDirect(__instance.position, __instance.width, __instance.height, 226, // This dust type is the spark dust from the Electrosphere Launcher __instance.velocity.X * 0.75f, __instance.velocity.Y * 0.75f, 50, Color.White, scale); dust.noGravity = true; dust.velocity = Vector2.Lerp(dust.velocity, __instance.velocity, 0.3f); // Influence dust velocity slightly with our projectile velocity int speedRand = Terraria.Main.rand.Next(10); if (speedRand > 8) // Randomly boost the speed of some dust particles { dust.velocity *= 1.5f; } if (speedRand > 6) { dust.velocity *= 1.2f; } } // Add some light to at our particle's position Terraria.Lighting.AddLight(__instance.Center, 0.25f, 0.55f, 0.75f); return(false); // Skip over original method } return(true); // Allow original method to run }
public void AiValues_Set() { var terrariaProjectile = new Terraria.Projectile(); var projectile = new OrionProjectile(terrariaProjectile); projectile.AiValues[0] = 1.23f; projectile.AiValues[1] = 4.56f; Assert.Equal(1.23f, terrariaProjectile.ai[0]); Assert.Equal(4.56f, terrariaProjectile.ai[1]); }
public void AiValues_Get() { var terrariaProjectile = new Terraria.Projectile(); terrariaProjectile.ai[0] = 1.23f; terrariaProjectile.ai[1] = 4.56f; var projectile = new OrionProjectile(terrariaProjectile); Assert.Equal(2, projectile.AiValues.Length); Assert.Equal(1.23f, projectile.AiValues[0]); Assert.Equal(4.56f, projectile.AiValues[1]); }
public void Apply(Terraria.Projectile projectile) { // if (Owner < 255) // projectile.Creator = Main.player[Owner]; projectile.identity = Id; projectile.owner = Owner; projectile.damage = Damage; projectile.knockBack = Knockback; // projectile.position = new Vector2(X, Y); // projectile.velocity = new Vector2(VX, VY); projectile.ai = AI; }
// ============================================================================================================= // OTAPI hooks // private OTAPI.HookResult PreSetDefaultsByIdHandler(Terraria.Projectile terrariaProjectile, ref int projectileId) { Debug.Assert(terrariaProjectile != null); var projectile = GetProjectile(terrariaProjectile); var evt = new ProjectileDefaultsEvent(projectile) { Id = (ProjectileId)projectileId }; _events.Raise(evt, _log); if (evt.IsCanceled) { return(OTAPI.HookResult.Cancel); } projectileId = (int)evt.Id; return(OTAPI.HookResult.Continue); }
public static void SetDefaults_SetProjectileDefaults(Terraria.Projectile __instance, int Type) { // The specially named __instance parameter is automatically filled in by Harmony to reference the Projectile instance that is calling this method. // The type parameter is automatically filled in by Harmony to be the same value as the type parameter that was passed to the original method. if (!PluginLoadedSuccessfully) // If there was a problem loading things for our plugin, we will abort this stub method so we dont crash Terraria. { return; } if (Type == ProjectileID) // Only apply our custom projectile's defaults if the Projectile that had SetDefaults called on it actually is our projectile { __instance.width = 40; // Width of the projectile __instance.height = 40; // Height of the projectile // In this example, the texture frame size is actually 52x52, but I want the projectile's hitbox to be smaller (since the edges of the texture are almost fully transparent). // We'll compensate for the incorrect size in our custom drawing code. __instance.scale = 1f; // Scale of the projectile __instance.aiStyle = 1; // The type of update logic that the projectile will use // We actually don't even need to set this, because of our prefix patch for Terraria.Projectile.AI() __instance.alpha = 255; // The projectile's opacity __instance.magic = true; // Whether or not the projectile counts as a magic projectile (and is thus affected by magic dmg/crit/etc stat boosters) __instance.friendly = true; // Whether or not the projectile will damage players __instance.penetrate = 5; // How many things the projectile can pierce before despawning __instance.ignoreWater = true; // Whether or not the projectile will interact with water __instance.timeLeft = 600; // How long (in frames) until the projectile despawns __instance.extraUpdates = 1; // How many times the projectile will update per frame (i.e. run its AI() method, among other things) __instance.active = true; // The original method sets active to false for projectiles outside of the vanilla ID range, so we must set active to true here in our postfix patch __instance.maxPenetrate = __instance.penetrate; // Set initial value for maxPenetrate __instance.width = (int)((float)__instance.width * __instance.scale); // Combine design width with scale to produce initial width __instance.height = (int)((float)__instance.height * __instance.scale); // Combine design height with scale to produce initial height // Also, in case the async texture loading replaced our projectile's texture with something else, let's make sure the right texture is in our projectile's slot if (ProjectileGraphicAsset != null) { Terraria.GameContent.TextureAssets.Projectile[ProjectileID] = ProjectileGraphicAsset; // Reassign the field with the asset we created earlier } } }
public override void DoubleClick(UIMouseEvent evt) { var lp = LocalPlayer.GetModPlayer <MP>(); var pj = new Terraria.Projectile(); foreach (var _ in TUIL.cl) { for (int id = 1; id < Terraria.ModLoader.ProjectileLoader.ProjectileCount; id++) { if (_.chosen && _.pl.All(pp => pp(pj))) { if ("Melee" == _.name) { lp.melee = true; } lp.idl.Add(pj.type); } pj.SetDefaults(id); } } }
public void ProjectileDefaults_AbstractProjectile_EventTriggered() { var terrariaProjectile = new Terraria.Projectile(); var events = Mock.Of <IEventManager>(); var log = Mock.Of <ILogger>(); using var projectileService = new OrionProjectileService(events, log); Mock.Get(events) .Setup(em => em.Raise( It.Is <ProjectileDefaultsEvent>( evt => ((OrionProjectile)evt.Projectile).Wrapped == terrariaProjectile && evt.Id == ProjectileId.CrystalBullet), log)); terrariaProjectile.SetDefaults((int)ProjectileId.CrystalBullet); Assert.Equal(ProjectileId.CrystalBullet, (ProjectileId)terrariaProjectile.type); Mock.Get(events).VerifyAll(); }
public override void OnHitNPCWithProj(Terraria.Player player, SkillData data, Terraria.Projectile proj, Terraria.NPC target, int damage, float knockback, bool crit) { OnHitNPC(player, data, target, damage); }
public override void OnHitByProjectile(Terraria.Player player, SkillData data, Terraria.Projectile proj, int damage, bool crit) { data.ChangeFloat(DamageStackVar, damage); }
public override void ModifyHitNPCWithProj(Terraria.Player player, SkillData data, Terraria.Projectile proj, Terraria.NPC target, ref int damage, ref float knockback, ref bool crit, ref int hitDirection) { if (target.velocity.Y != 0 && proj.type == Terraria.ID.ProjectileID.BulletHighVelocity) { damage = (int)(damage * (1.6f + 0.2f * data.Level)); knockback += 2f; data.EndUse(); } }
internal void CleanupProjectile() { if (projectile != null) { // Projectile.FreeSlot(projectile.identity, projectile.Owner, projectile.Id); projectile = null; } }