/// <summary>
        /// <para>Sends a <see cref="ModPacket"/> with <see cref="OriPlayer"/> data.</para>
        /// <inheritdoc cref="ModPacket.Send(int, int)"/>
        /// </summary>
        /// <param name="toWho">Who to send to. <see langword="255"/> for server, <see langword="-1"/> for all players.</param>
        /// <param name="fromWho">Sender, client to ignore.</param>
        internal void SendOriState(int toWho, int fromWho)
        {
            ModPacket packet     = GetPacket(fromWho);
            OriPlayer fromPlayer = Main.player[fromWho].GetModPlayer <OriPlayer>();

            BitsByte flags = new BitsByte {
                [0] = fromPlayer.IsOri,
                [1] = fromPlayer.Transforming,
                [2] = fromPlayer.UnrestrictedMovement,
                [3] = fromPlayer.SeinMinionActive,
                [4] = fromPlayer.multiplayerPlayerLight,
            };

            packet.Write(flags);
            if (fromPlayer.Transforming)
            {
                packet.Write((ushort)fromPlayer.transformTimer);
            }

            if (fromPlayer.SeinMinionActive)
            {
                packet.Write((byte)fromPlayer.SeinMinionType);
            }

            packet.WriteRGB(fromPlayer.SpriteColorPrimary);
            packet.WriteRGBA(fromPlayer.SpriteColorSecondary);

            fromPlayer.input.WritePacket(packet);

            packet.Send(toWho, fromWho);
        }
Example #2
0
        /// <summary>
        /// Increases the level of <paramref name="player"/>'s <see cref="Ability"/> this Item represents to by 1.
        /// <para>By increasing by 1, the player can level it multiple times if they skip one, rather than having their level skip.</para>
        /// </summary>
        /// <param name="player">The player using the item.</param>
        /// <returns><see langword="true"/> if the ability can be leveled. If this returns <see langword="false"/>, this <see cref="AbilityMedallionBase"/> or the <see cref="Ability"/> must be fixed.</returns>
        public override bool UseItem(Player player)
        {
            OriPlayer oPlayer = player.GetModPlayer <OriPlayer>();
            Ability   ability = oPlayer.abilities[Id];

            if (ability is ILevelable levelable)
            {
                levelable.Level++;
                if (player.whoAmI == Main.myPlayer)
                {
                    string key = $"Mods.OriMod.Lore.{ability.GetType().Name}.{levelable.Level}";
                    if (Language.Exists(key))
                    {
                        Main.NewText(Language.GetText(key), Color.LightCyan);
                    }
                }
                string strStart = player.whoAmI == Main.myPlayer ? "You" : $"{player.name} has";
                Main.NewText(
                    levelable.Level == 1
            ? $"{strStart} unlocked {NiceName(ability)}!"
            : $"{strStart} upgraded {NiceName(ability)} to Level {levelable.Level}!", Color.LightGreen);
                return(true);
            }

            Main.NewText($"OriMod dev bug: Ability {ability.GetType().Name} cannot be leveled.", Color.Red);
            return(false);
        }
Example #3
0
        public override bool NewRightClick(int i, int j)
        {
            OriPlayer oPlayer = OriPlayer.Local;
            Player    player  = oPlayer.player;

            Main.mouseRightRelease = false;
            if (oPlayer.Transforming)
            {
                return(false);
            }
            if (!oPlayer.IsOri)
            {
                oPlayer.BeginTransformation();
                if (!oPlayer.HasTransformedOnce)
                {
                    oPlayer.PlaySound("AbilityPedestal/abilityPedestalMusic", 0.25f);
                }
            }
            else
            {
                oPlayer.IsOri = false;
                oPlayer.PlaySound("SavePoints/checkpointSpawnSound");

                Vector2 pos = player.position;
                pos.Y += 4;
                pos.X -= 2;
                for (int m = 0; m < 100; m++)
                {
                    Dust dust = Dust.NewDustDirect(pos, 30, 30, DustID.Clentaminator_Cyan, 0f, 0f, 0, new Color(255, 255, 255));
                    dust.shader = GameShaders.Armor.GetSecondaryShader(19, Main.LocalPlayer);
                }
            }
            return(true);
        }
Example #4
0
        /// <summary>
        /// Returns <see langword="true"/> if the player does not have the <see cref="Ability"/> this Item represents upgraded to the <see cref="Ability.Level"/> this Item upgrades to.
        /// </summary>
        /// <param name="player">The <see cref="Player"/> using the item.</param>
        /// <returns><see langword="true"/> if the player does not have the <see cref="Ability"/> at this <see cref="Level"/>; otherwise, <see langword="false"/>.</returns>
        public override bool CanUseItem(Player player)
        {
            // Can only use the item if the ability to be unlocked has not been unlocked
            OriPlayer oPlayer = player.GetModPlayer <OriPlayer>();

            return(oPlayer.abilities[Id].Level < Level);
        }
        internal override void HandlePacket(BinaryReader reader, int fromWho)
        {
            OriPlayer fromPlayer           = Main.player[fromWho].GetModPlayer <OriPlayer>();
            BitsByte  flags                = reader.ReadByte();
            bool      oriSet               = flags[0];
            bool      transforming         = flags[1];
            bool      unrestrictedMovement = flags[2];
            bool      seinMinionActive     = flags[3];
            bool      mpcPlayerLight       = flags[4];
            ushort    transformTimer       = transforming ? reader.ReadUInt16() : (ushort)0;
            byte      seinMinionType       = seinMinionActive ? reader.ReadByte() : (byte)0;
            Color     spriteColorPrimary   = reader.ReadRGB();
            Color     spriteColorSecondary = reader.ReadRGBA();

            fromPlayer.IsOri                  = oriSet;
            fromPlayer.Transforming           = transforming;
            fromPlayer.UnrestrictedMovement   = unrestrictedMovement;
            fromPlayer.transformTimer         = transformTimer;
            fromPlayer.SeinMinionType         = seinMinionType;
            fromPlayer.SeinMinionActive       = seinMinionActive;
            fromPlayer.multiplayerPlayerLight = mpcPlayerLight;
            fromPlayer.SpriteColorPrimary     = spriteColorPrimary;
            fromPlayer.SpriteColorSecondary   = spriteColorSecondary;

            fromPlayer.input.ReadPacket(reader);

            if (Main.netMode == NetmodeID.Server)
            {
                SendOriState(-1, fromWho);
            }
        }
Example #6
0
        public override void Action(CommandCaller caller, string input, string[] args)
        {
            OriPlayer oPlayer = caller.Player.GetModPlayer <OriPlayer>();

            oPlayer.debugMode ^= true;
            Main.NewText("Toggled debug mode to " + oPlayer.debugMode);
        }
Example #7
0
        private static void BurrowEffects(int i, int j, ref Color drawColor, OriPlayer oPlayer)
        {
            Color   orig      = drawColor;
            Vector2 playerPos = Main.LocalPlayer.Center / 16;
            float   dist      = Vector2.Distance(playerPos, new Vector2(i, j)) - InnerRange;

            dist      = Utils.Clamp((OuterRange - dist) / OuterRange, 0, 1);
            drawColor = Color.Lerp(orig, Color.White,
                                   (oPlayer.abilities.burrow.CanBurrow(Main.tile[i, j]) ? 0.8f : 0.4f) * dist);
            drawColor.A = orig.A;
        }
        /// <summary>
        /// <para>Sends a <see cref="ModPacket"/> with ability data.</para>
        /// <inheritdoc cref="ModPacket.Send(int, int)"/>
        /// </summary>
        /// <param name="toWho">Who to send to. <see langword="255"/> for server, <see langword="-1"/> for all players.</param>
        /// <param name="fromWho">Sender, client to ignore.</param>
        /// <param name="changes">List of <see cref="AbilityId"/>s for abilities that have changed.</param>
        internal void SendAbilityState(int toWho, int fromWho, List <byte> changes)
        {
            ModPacket packet     = GetPacket(fromWho);
            OriPlayer fromPlayer = Main.player[fromWho].GetModPlayer <OriPlayer>();

            packet.Write((byte)changes.Count);
            foreach (byte id in changes)
            {
                packet.Write(id);
                fromPlayer.abilities[id].PreWritePacket(packet);
            }
            packet.Send(toWho, fromWho);
        }
Example #9
0
        public override bool Shoot(Player player, ref Vector2 position, ref float speedX, ref float speedY, ref int type, ref int damage, ref float knockBack)
        {
            OriPlayer oPlayer = player.GetModPlayer <OriPlayer>();

            oPlayer.RemoveSeinBuffs();
            player.AddBuff(item.buffType, 2);
            oPlayer.SeinMinionType   = item.shoot;
            oPlayer.SeinMinionActive = true;
            if (player.altFunctionUse == 2)
            {
                player.MinionNPCTargetAim();
            }
            oPlayer.SeinMinionId = Projectile.NewProjectile(player.Center, -Vector2.UnitY, item.shoot, item.damage, item.knockBack, player.whoAmI);
            return(false);
        }
Example #10
0
        internal static Vector2 GetMouseDirection(OriPlayer oPlayer, out float angle, Vector2?direction = null, float maxAngle = (float)Math.PI)
        {
            Player  player = oPlayer.player;
            Vector2 dir    = direction ?? new Vector2(player.direction, player.gravDir);

            Vector2 offset = Main.MouseWorld;

            offset = (offset - player.Center) * dir + player.Center;

            angle = Utils.Clamp(player.AngleTo(offset), -maxAngle, maxAngle);

            Vector2 result = Vector2.UnitX.RotatedBy(angle);

            result *= dir;
            return(result);
        }
Example #11
0
        internal override void HandlePacket(BinaryReader reader, int fromWho)
        {
            OriPlayer fromPlayer = Main.player[fromWho].GetModPlayer <OriPlayer>();
            int       len        = reader.ReadByte();
            var       changes    = new List <byte>();

            for (int m = 0; m < len; m++)
            {
                byte id = reader.ReadByte();
                changes.Add(id);
                fromPlayer.abilities[id].PreReadPacket(reader);
            }
            if (Main.netMode == NetmodeID.Server)
            {
                SendAbilityState(-1, fromWho, changes);
            }
        }
Example #12
0
        public override bool UseItem(Player player)
        {
            OriPlayer oPlayer = player.GetModPlayer <OriPlayer>();

            oPlayer.IsOri ^= true;

            Vector2 pos = player.position;

            pos.Y += 4;
            pos.X -= 2;
            for (int m = 0; m < 100; m++)
            {
                Dust dust = Dust.NewDustDirect(pos, 30, 30, DustID.Clentaminator_Cyan, 0f, 0f, 0, new Color(255, 255, 255));
                dust.shader = GameShaders.Armor.GetSecondaryShader(19, Main.LocalPlayer);
            }
            oPlayer.PlaySound("SavePoints/checkpointSpawnSound");
            Item.NewItem(player.getRect(), ModContent.ItemType <OriPotionEmpty>(), noGrabDelay: true);
            return(true);
        }
Example #13
0
        internal AbilityManager(OriPlayer oPlayer)
        {
            this.oPlayer = oPlayer;

            //soulLink = new SoulLink(this);
            wallJump       = new WallJump(this);
            stomp          = new Stomp(this);
            airJump        = new AirJump(this);
            bash           = new Bash(this);
            glide          = new Glide(this);
            climb          = new Climb(this);
            chargeJump     = new ChargeJump(this);
            wallChargeJump = new WallChargeJump(this);
            dash           = new Dash(this);
            chargeDash     = new ChargeDash(this);
            lookUp         = new LookUp(this);
            crouch         = new Crouch(this);
            burrow         = new Burrow(this);
            launch         = new Launch(this);
        }
Example #14
0
        public override void DrawEffects(int i, int j, int type, SpriteBatch spriteBatch, ref Color drawColor, ref int nextSpecialDrawIndex)
        {
            OriPlayer oPlayer = OriPlayer.Local;

            if (!oPlayer.abilities.burrow)
            {
                return;
            }
            BurrowEffects(i, j, ref drawColor, oPlayer);
            if (!oPlayer.debugMode)
            {
                return;
            }
            Point pos = new Point(i, j);

            if (Burrow.InnerHitbox.Points.Contains(pos))
            {
                drawColor = Color.Red;
            }
            else if (Burrow.EnterHitbox.Points.Contains(pos))
            {
                drawColor = Color.LimeGreen;
            }
        }
Example #15
0
        private static Ability AbilityFromObject(string str, OriPlayer oPlayer)
        {
            if (int.TryParse(str, out int id))
            {
                if (id >= 0 && id <= AbilityId.Count)
                {
                    return(oPlayer.abilities[id]);
                }
                Main.NewText($"\"{id}\" does not map to a valid AbilityID.", Color.Red);
                return(null);
            }

            string testName = str.ToLower();

            foreach (Ability ab in oPlayer.abilities)
            {
                if (ab.GetType().Name.ToLower() == testName)
                {
                    return(ab);
                }
            }
            Main.NewText($"\"{str}\" is not a valid Ability.", Color.Red);
            return(null);
        }
Example #16
0
        /// <summary>
        /// Updates the player animation by one frame, and changes it depending on various conditions.
        /// </summary>
        public override void Update()
        {
            OriPlayer      oPlayer   = player.GetModPlayer <OriPlayer>();
            AbilityManager abilities = oPlayer.abilities;

            // Transformation
            if (oPlayer.Transforming)
            {
                PlayTrack("Transform", speed: oPlayer.HasTransformedOnce?OriPlayer.RepeatedTransformRate: 1);
                return;
            }
            if (!oPlayer.IsOri)
            {
                return;
            }

            // Handle some "special" movement
            // Todo, consider dedicated sprites to these actions, i.e. mounted, pulley, grapple
            if (player.pulley || player.mount.Active)
            {
                PlayTrack("Idle");
                return;
            }
            if (oPlayer.IsGrappling)
            {
                if (Math.Abs(player.velocity.X) > 0.1f)
                {
                    PlayTrack("Jump", frameIndex: 1);
                    return;
                }
                PlayTrack(oPlayer.OnWall ? "IdleAgainst" : "Default");
                return;
            }

            // Abilities
            // Start with simple cases
            if (abilities.bash)
            {
                PlayTrack("Bash");
                return;
            }
            if (abilities.chargeJump.Active)
            {
                PlayTrack("ChargeJump");
                return;
            }
            if (abilities.wallJump)
            {
                PlayTrack("WallJump");
                return;
            }
            if (abilities.airJump)
            {
                PlayTrack("AirJump", rotation: FrameTime * 0.6f *player.gravDir *player.direction);
                return;
            }
            if (abilities.burrow)
            {
                float rad = (float)Math.Atan2(abilities.burrow.velocity.X, -abilities.burrow.velocity.Y * player.gravDir);
                PlayTrack("Burrow", rotation: rad *player.gravDir);
                return;
            }
            if (abilities.dash || abilities.chargeDash)
            {
                PlayTrack("Dash", frameIndex: Math.Abs(player.velocity.X) < 12f ? 1 : 0);
                return;
            }
            if (abilities.wallChargeJump)
            {
                PlayTrack("Dash", frameIndex: 0, rotation: abilities.wallChargeJump.Angle *player.gravDir *abilities.wallChargeJump.XDirection);
                return;
            }

            // Switch-case for animations with start/mid/end segments

            if (abilities.glide)
            {
                switch (abilities.glide.AbilityState)
                {
                case Ability.State.Starting:
                    PlayTrack("GlideStart");
                    return;

                case Ability.State.Active:
                    PlayTrack("Glide");
                    return;

                case Ability.State.Ending:
                    PlayTrack("GlideStart", direction: Direction.Reverse);
                    return;
                }
            }

            if (abilities.crouch)
            {
                switch (abilities.crouch.AbilityState)
                {
                case Ability.State.Starting:
                    PlayTrack("CrouchStart");
                    return;

                case Ability.State.Active:
                    PlayTrack("Crouch");
                    return;

                case Ability.State.Ending:
                    PlayTrack("CrouchStart", direction: Direction.Reverse);
                    return;
                }
            }

            if (abilities.lookUp)
            {
                switch (abilities.lookUp.AbilityState)
                {
                case Ability.State.Starting:
                    PlayTrack("LookUpStart");
                    return;

                case Ability.State.Active:
                    PlayTrack("LookUp");
                    return;

                case Ability.State.Ending:
                    PlayTrack("LookUpStart", direction: Direction.Reverse);
                    return;
                }
            }

            // More complex animations

            if (abilities.stomp)
            {
                switch (abilities.stomp.AbilityState)
                {
                case Ability.State.Starting:
                    PlayTrack("AirJump", rotation: FrameTime * 0.8f);
                    return;

                case Ability.State.Active:
                    PlayTrack("ChargeJump", duration: 2, rotation: (float)Math.PI, loop: LoopMode.Always, direction: Direction.PingPong);
                    return;
                }
            }

            if (abilities.launch)
            {
                if (abilities.launch.Active)
                {
                    // Launch angle needs to be offset by 90 degrees since it uses Stomp animation
                    // Disable spriteeffects as launching should not be flipped
                    PlayTrack("ChargeJump", duration: 6, rotation: abilities.launch.LaunchAngle + (float)Math.PI / 2 * player.gravDir, loop: LoopMode.Always, direction: Direction.PingPong, effects: SpriteEffects.None);
                }
                else
                {
                    int   ct    = abilities.launch.CurrentTime;
                    float accel = ct * (ct < 5 ? 0.05f : ct < 20 ? 0.03f : 0.02f);
                    // Somewhat accelerating speed of rotation
                    PlayTrack("AirJump", rotation: SpriteRotation + accel * player.direction);
                }
                return;
            }

            if (abilities.climb)
            {
                if (abilities.climb.Ending)
                {
                    PlayTrack("Jump", frameIndex: 0);
                    return;
                }
                if (!abilities.climb.IsCharging)
                {
                    if (Math.Abs(player.velocity.Y) < 0.1f)
                    {
                        PlayTrack("ClimbIdle");
                    }
                    else
                    {
                        PlayTrack(player.velocity.Y * player.gravDir < 0 ? "Climb" : "WallSlide", speed: Math.Abs(player.velocity.Y) * 0.4f);
                    }
                    return;
                }

                if (!abilities.wallChargeJump.Charged)
                {
                    PlayTrack("WallChargeJumpCharge", frameIndex: abilities.wallChargeJump.Refreshed?null: (int?)0);
                    return;
                }

                // Aim angle determines frame of sprite.
                // 0 is middle (pointing straight left/right), 1-2 pointing downward, 3-4 pointing upward
                int   frame = 0;
                float angle = abilities.wallChargeJump.Angle;
                if (angle < -0.46f)
                {
                    frame = 2;
                }
                else if (angle < -0.17f)
                {
                    frame = 1;
                }
                else if (angle > 0.46f)
                {
                    frame = 4;
                }
                else if (angle > 0.17f)
                {
                    frame = 3;
                }
                PlayTrack("WallChargeJumpAim", frameIndex: frame);
                return;
            }

            // Generic/misc movement
            if (oPlayer.OnWall && !oPlayer.IsGrounded)
            {
                PlayTrack("WallSlide");
                return;
            }
            if (!oPlayer.IsGrounded)
            {
                // Probably the best way to check for jumping vs falling
                PlayTrack(player.velocity.Y * player.gravDir < 0 ? "Jump" : "Falling");
                return;
            }
            if (Math.Abs(player.velocity.X) > 0.2f)
            {
                // Movement deadzone recommended for running animations
                // Else subtle movements such as sandstorm can cause a running animation
                // Animation speed is also determined by player speed, as it should be
                PlayTrack("Running", speed: (int)Math.Abs(player.velocity.X) * 0.45f);
                return;
            }
            PlayTrack(oPlayer.OnWall ? "IdleAgainst" : "Idle");
        }
Example #17
0
        public override void Action(CommandCaller caller, string input, string[] args)
        {
            OriPlayer oPlayer = caller.Player.GetModPlayer <OriPlayer>();

            if (!oPlayer.debugMode)
            {
                Main.NewText("This command cannot be used outside of debug mode.", Color.Red);
                return;
            }

            if (args.Length < 1)
            {
                Main.NewText($"This command requires arguments. Usage: {Usage}", Color.Red);
                return;
            }

            switch (args[0])
            {
            case "unlockall":
                oPlayer.abilities.UnlockAllAbilities();
                Main.NewText("Unlocked all abilities.", Color.LightGreen);
                return;

            case "resetall":
                oPlayer.abilities.ResetAllAbilities();
                Main.NewText("Reset all abilities.", Color.LightGreen);
                return;
            }

            Ability ability = AbilityFromObject(args[0], oPlayer);

            string abilityName = ability.GetType().Name;

            if (ability is ILevelable levelable)
            {
                if (args.Length < 2)
                {
                    Main.NewText($"{abilityName}'s Level is {levelable.Level}.", Color.LightGreen);
                }
                else if (byte.TryParse(args[1], out byte level))
                {
                    levelable.Level = level;
                    if (level <= levelable.MaxLevel)
                    {
                        Main.NewText($"{abilityName}'s Level has been set to {level}.", Color.LightGreen);
                    }
                    else
                    {
                        Main.NewText($"{abilityName}'s Level has been set to {level}. Note that {abilityName}'s max level is {levelable.MaxLevel}, so this ability's behavior may be unexpected or unbalanced.", Color.GreenYellow);
                    }
                }
                else
                {
                    Main.NewText($"\"{args[1]}\" is not a valid input for level.", Color.Red);
                }
            }
            else
            {
                if (args.Length < 2)
                {
                    Main.NewText($"{abilityName}'s fixed Level is {ability.Level}.", Color.LightGreen);
                }
                else
                {
                    Main.NewText($"{abilityName} cannot have its level modified. {FailedAbilityReason(ability)}", Color.Red);
                }
            }
        }
Example #18
0
        public override bool CanUseItem(Player player)
        {
            OriPlayer oPlayer = player.GetModPlayer <OriPlayer>();

            return(player.altFunctionUse != 2 && (!oPlayer.SeinMinionActive || oPlayer.SeinMinionType != item.shoot));
        }