Example #1
0
        internal static void OfferObject(MineShaft shaft, string action, Location tileLocation, Farmer who)
        {
            string[] parts = action.Split('_').Skip(1).ToArray();

            int type = int.Parse(parts[0]);
            int cx   = int.Parse(parts[1]);
            int cy   = int.Parse(parts[2]);

            if (who.ActiveObject == null)
            {
                Game1.activeClickableMenu = new DialogueBox(helper.Translation.Get($"altar-explain-{type}"));
                return;
            }

            int value = who.ActiveObject.salePrice();

            who.reduceActiveItemByOne();
            if (value < 10)
            {
                if (type == 0)
                {
                    CollapsingFloors.collapseFloor(shaft, who.getTileLocation());
                    return;
                }
                else if (type == 1)
                {
                    Traps.TriggerRandomTrap(shaft, who.getTileLocation(), false);
                    return;
                }
            }

            string sound = "yoba";

            if (type == 0)
            {
                sound = "grunt";
            }
            else if (type == 1)
            {
                sound = "debuffSpell";
            }
            shaft.playSound(sound, SoundContext.Default);

            BuffsDisplay buffsDisplay = Game1.buffsDisplay;
            Buff         buff2        = GetBuff(value, who, shaft, type);

            buffsDisplay.addOtherBuff(buff2);
        }
        public override void behaviorAtGameTick(GameTime time)
        {
            invincibleCountdown = 1000;
            if (timeBeforeAIMovementAgain > 0f)
            {
                timeBeforeAIMovementAgain -= time.ElapsedGameTime.Milliseconds;
            }
            if (lastBuff >= 0)
            {
                lastBuff.Value -= time.ElapsedGameTime.Milliseconds;
            }

            if (wasHitCounter >= 0)
            {
                wasHitCounter.Value -= time.ElapsedGameTime.Milliseconds;
            }

            if (followingOwner)
            {
                Vector2 center       = Position + new Vector2(8, 8);
                Vector2 playerCenter = GetOwner().position + new Vector2(64, 92);
                if (Vector2.Distance(playerCenter, center) > 256)
                {
                    Position = Vector2.Distance(playerCenter, center) * 0.03f * Vector2.Normalize(playerCenter - center) + center - new Vector2(8, 8);
                }

                float xSlope = (float)(-(float)(playerCenter.X - center.X));
                float ySlope = (float)(playerCenter.Y - center.Y);
                float t      = Math.Max(1f, Math.Abs(xSlope) + Math.Abs(ySlope));
                if (t < (float)((extraVelocity > 0f) ? 192 : 64))
                {
                    xVelocity = Math.Max(-maxSpeed, Math.Min(maxSpeed, xVelocity * 1.05f));
                    yVelocity = Math.Max(-maxSpeed, Math.Min(maxSpeed, yVelocity * 1.05f));
                }
                xSlope /= t;
                ySlope /= t;
                if (wasHitCounter <= 0)
                {
                    targetRotation = (float)Math.Atan2((double)(-(double)ySlope), (double)xSlope) - 1.57079637f;
                    if ((double)(Math.Abs(targetRotation) - Math.Abs(rotation)) > 2.748893571891069 && Game1.random.NextDouble() < 0.5)
                    {
                        turningRight.Value = true;
                    }
                    else if ((double)(Math.Abs(targetRotation) - Math.Abs(rotation)) < 0.39269908169872414)
                    {
                        turningRight.Value = false;
                    }
                    if (turningRight)
                    {
                        rotation -= (float)Math.Sign(targetRotation - rotation) * 0.0490873866f;
                    }
                    else
                    {
                        rotation += (float)Math.Sign(targetRotation - rotation) * 0.0490873866f;
                    }
                    rotation           %= 6.28318548f;
                    wasHitCounter.Value = 0;
                }
                float maxAccel = Math.Min(5f, Math.Max(1f, 5f - t / 64f / 2f)) + extraVelocity;
                xSlope     = (float)Math.Cos((double)rotation + 1.5707963267948966);
                ySlope     = -(float)Math.Sin((double)rotation + 1.5707963267948966);
                xVelocity += -xSlope * maxAccel / 6f + (float)Game1.random.Next(-10, 10) / 100f;
                yVelocity += -ySlope * maxAccel / 6f + (float)Game1.random.Next(-10, 10) / 100f;
                if (Math.Abs(xVelocity) > Math.Abs(-xSlope * maxSpeed))
                {
                    xVelocity -= -xSlope * maxAccel / 6f;
                }
                if (Math.Abs(yVelocity) > Math.Abs(-ySlope * maxSpeed))
                {
                    yVelocity -= -ySlope * maxAccel / 6f;
                }
                if (lastBuff <= 0 && Vector2.Distance(GetOwner().getTileLocation(), getTileLocation()) < 3)
                {
                    if (Game1.random.NextDouble() < BuffChance())
                    {
                        if (ModEntry.Config.ButterflySoundEffects)
                        {
                            Game1.playSound("yoba");
                        }
                        BuffsDisplay buffsDisplay = Game1.buffsDisplay;
                        Buff         buff2        = GetBuff();
                        buffsDisplay.addOtherBuff(buff2);
                        AddExp(1);
                        lastBuff.Value = GetBuffInterval();
                    }
                    else
                    {
                        lastBuff.Value = 1000;
                    }
                }
            }
        }
        public static void GameLoop_UpdateTicked(object sender, UpdateTickedEventArgs e)
        {
            if (Game1.player.currentLocation == null || Game1.player == null || !Game1.displayFarmer || Game1.player.position == null)
            {
                return;
            }

            ModEntry.isUnderwater = SwimUtils.IsMapUnderwater(Game1.player.currentLocation.Name);

            if (Game1.player.currentLocation.Name == "ScubaAbigailCave")
            {
                AbigailCaveTick();
            }

            if (Game1.activeClickableMenu == null)
            {
                if (ModEntry.isUnderwater)
                {
                    if (ModEntry.oxygen >= 0)
                    {
                        if (!SwimUtils.IsWearingScubaGear())
                        {
                            ModEntry.oxygen--;
                        }
                        else
                        {
                            if (ModEntry.oxygen < SwimUtils.MaxOxygen())
                            {
                                ModEntry.oxygen++;
                            }
                            if (ModEntry.oxygen < SwimUtils.MaxOxygen())
                            {
                                ModEntry.oxygen++;
                            }
                        }
                    }
                    if (ModEntry.oxygen < 0 && !surfacing)
                    {
                        surfacing = true;
                        Game1.playSound("pullItemFromWater");
                        DiveLocation diveLocation = ModEntry.diveMaps[Game1.player.currentLocation.Name].DiveLocations.Last();
                        SwimUtils.DiveTo(diveLocation);
                    }
                }
                else
                {
                    surfacing = false;
                    if (ModEntry.oxygen < SwimUtils.MaxOxygen())
                    {
                        ModEntry.oxygen++;
                    }
                    if (ModEntry.oxygen < SwimUtils.MaxOxygen())
                    {
                        ModEntry.oxygen++;
                    }
                }
            }

            if (SwimUtils.IsWearingScubaGear())
            {
                ticksWearingScubaGear++;
                if (Config.BreatheSound && breatheEffect != null && (lastBreatheSound == 0 || ticksWearingScubaGear - lastBreatheSound > 6000 / 16))
                {
                    Monitor.Log("Playing breathe sound");
                    lastBreatheSound = ticksWearingScubaGear;
                    breatheEffect.Play(0.5f * Game1.options.soundVolumeLevel, 0f, 0f);
                }
            }
            else
            {
                if (breatheEffect != null && lastBreatheSound != 0)
                {
                    breatheEffect.Dispose();
                    LoadBreatheSound();
                }
                lastBreatheSound      = 0;
                ticksWearingScubaGear = 0;
            }

            if (isJumping)
            {
                float difx      = endJumpLoc.X - startJumpLoc.X;
                float dify      = endJumpLoc.Y - startJumpLoc.Y;
                float completed = Game1.player.freezePause / (float)Config.JumpTimeInMilliseconds;
                if (Game1.player.freezePause <= 0)
                {
                    Game1.player.position.Value = endJumpLoc;
                    isJumping = false;
                    if (ModEntry.willSwim)
                    {
                        Game1.player.currentLocation.playSound("waterSlosh", NetAudio.SoundContext.Default);
                        Game1.player.swimming.Value = true;
                    }
                    else
                    {
                        if (!Config.SwimSuitAlways)
                        {
                            Game1.player.changeOutOfSwimSuit();
                        }
                    }
                    return;
                }
                Game1.player.position.Value = new Vector2(endJumpLoc.X - (difx * completed), endJumpLoc.Y - (dify * completed) - (float)Math.Sin(completed * Math.PI) * 64);
                return;
            }

            // only if ready to swim from here on!

            if (!Config.ReadyToSwim || !Context.IsPlayerFree)
            {
                return;
            }

            if (Game1.player.swimming)
            {
                if (!SwimUtils.IsInWater() && !isJumping)
                {
                    Monitor.Log("Swimming out of water");
                    ModEntry.willSwim        = false;
                    Game1.player.freezePause = Config.JumpTimeInMilliseconds;
                    Game1.player.currentLocation.playSound("dwop", NetAudio.SoundContext.Default);
                    Game1.player.currentLocation.playSound("waterSlosh", NetAudio.SoundContext.Default);
                    isJumping    = true;
                    startJumpLoc = Game1.player.position.Value;
                    endJumpLoc   = Game1.player.position.Value;

                    Game1.player.swimming.Value = false;
                    if (Game1.player.bathingClothes && !Config.SwimSuitAlways)
                    {
                        Game1.player.changeOutOfSwimSuit();
                    }
                }

                DiveMap dm      = null;
                Point   edgePos = Game1.player.getTileLocationPoint();

                if (ModEntry.diveMaps.ContainsKey(Game1.player.currentLocation.Name))
                {
                    dm = ModEntry.diveMaps[Game1.player.currentLocation.Name];
                }

                if (Game1.player.position.Y > Game1.viewport.Y + Game1.viewport.Height - 16)
                {
                    Game1.player.position.Value = new Vector2(Game1.player.position.X, Game1.viewport.Y + Game1.viewport.Height - 17);
                    if (dm != null)
                    {
                        EdgeWarp edge = dm.EdgeWarps.Find((x) => x.ThisMapEdge == "Bottom" && x.FirstTile <= edgePos.X && x.LastTile >= edgePos.X);
                        if (edge != null)
                        {
                            Point pos = SwimUtils.GetEdgeWarpDestination(edgePos.X, edge);
                            if (pos != Point.Zero)
                            {
                                Monitor.Log("warping south");
                                Game1.warpFarmer(edge.OtherMapName, pos.X, pos.Y, false);
                            }
                        }
                    }
                }
                else if (Game1.player.position.Y < Game1.viewport.Y - 16)
                {
                    Game1.player.position.Value = new Vector2(Game1.player.position.X, Game1.viewport.Y - 15);

                    if (dm != null)
                    {
                        EdgeWarp edge = dm.EdgeWarps.Find((x) => x.ThisMapEdge == "Top" && x.FirstTile <= edgePos.X && x.LastTile >= edgePos.X);
                        if (edge != null)
                        {
                            Point pos = SwimUtils.GetEdgeWarpDestination(edgePos.X, edge);
                            if (pos != Point.Zero)
                            {
                                Monitor.Log("warping north");
                                Game1.warpFarmer(edge.OtherMapName, pos.X, pos.Y, false);
                            }
                        }
                    }
                }
                else if (Game1.player.position.X > Game1.viewport.X + Game1.viewport.Width - 32)
                {
                    Game1.player.position.Value = new Vector2(Game1.viewport.X + Game1.viewport.Width - 33, Game1.player.position.Y);

                    if (dm != null)
                    {
                        EdgeWarp edge = dm.EdgeWarps.Find((x) => x.ThisMapEdge == "Right" && x.FirstTile <= edgePos.Y && x.LastTile >= edgePos.Y);
                        if (edge != null)
                        {
                            Point pos = SwimUtils.GetEdgeWarpDestination(edgePos.Y, edge);
                            if (pos != Point.Zero)
                            {
                                Monitor.Log("warping east");
                                Game1.warpFarmer(edge.OtherMapName, pos.X, pos.Y, false);
                            }
                        }
                    }

                    if (Game1.player.currentLocation.Name == "Forest")
                    {
                        if (Game1.player.position.Y / 64 > 74)
                        {
                            Game1.warpFarmer("Beach", 0, 13, false);
                        }
                        else
                        {
                            Game1.warpFarmer("Town", 0, 100, false);
                        }
                    }
                }
                else if (Game1.player.position.X < Game1.viewport.X - 32)
                {
                    Game1.player.position.Value = new Vector2(Game1.viewport.X - 31, Game1.player.position.Y);

                    if (dm != null)
                    {
                        EdgeWarp edge = dm.EdgeWarps.Find((x) => x.ThisMapEdge == "Left" && x.FirstTile <= edgePos.X && x.LastTile >= edgePos.X);
                        if (edge != null)
                        {
                            Point pos = SwimUtils.GetEdgeWarpDestination(edgePos.Y, edge);
                            if (pos != Point.Zero)
                            {
                                Monitor.Log("warping west");
                                Game1.warpFarmer(edge.OtherMapName, pos.X, pos.Y, false);
                            }
                        }
                    }

                    if (Game1.player.currentLocation.Name == "Town")
                    {
                        Game1.warpFarmer("Forest", 119, 43, false);
                    }
                    else if (Game1.player.currentLocation.Name == "Beach")
                    {
                        Game1.warpFarmer("Forest", 119, 111, false);
                    }
                }

                if (Game1.player.bathingClothes && SwimUtils.IsWearingScubaGear() && !Config.SwimSuitAlways)
                {
                    Game1.player.changeOutOfSwimSuit();
                }
                else if (!Game1.player.bathingClothes && (!SwimUtils.IsWearingScubaGear() || Config.SwimSuitAlways))
                {
                    Game1.player.changeIntoSwimsuit();
                }

                if (Game1.player.boots.Value != null && ModEntry.scubaFinsID != -1 && Game1.player.boots.Value.indexInTileSheet == ModEntry.scubaFinsID)
                {
                    int  buffId = 42883167;
                    Buff buff   = Game1.buffsDisplay.otherBuffs.FirstOrDefault((Buff p) => p.which == buffId);
                    if (buff == null)
                    {
                        BuffsDisplay buffsDisplay = Game1.buffsDisplay;
                        Buff         buff2        = new Buff(0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, "Scuba Fins", Helper.Translation.Get("scuba-fins"));
                        buff2.which = buffId;
                        buff        = buff2;
                        buffsDisplay.addOtherBuff(buff2);
                    }
                    buff.millisecondsDuration = 50;
                }
            }
            else
            {
                if (SwimUtils.IsInWater() && !isJumping)
                {
                    Monitor.Log("In water not swimming");

                    ModEntry.willSwim        = true;
                    Game1.player.freezePause = Config.JumpTimeInMilliseconds;
                    Game1.player.currentLocation.playSound("dwop", NetAudio.SoundContext.Default);
                    isJumping    = true;
                    startJumpLoc = Game1.player.position.Value;
                    endJumpLoc   = Game1.player.position.Value;


                    Game1.player.swimming.Value = true;
                    if (!Game1.player.bathingClothes && !SwimUtils.IsWearingScubaGear())
                    {
                        Game1.player.changeIntoSwimsuit();
                    }
                }
            }

            SwimUtils.CheckIfMyButtonDown();

            if (!ModEntry.myButtonDown || Game1.player.millisecondsPlayed - lastJump < 250 || SwimUtils.IsMapUnderwater(Game1.player.currentLocation.Name))
            {
                return;
            }

            if (Helper.Input.IsDown(SButton.MouseLeft) && !Game1.player.swimming && (Game1.player.CurrentTool is WateringCan || Game1.player.CurrentTool is FishingRod))
            {
                return;
            }


            List <Vector2> tiles        = SwimUtils.GetTilesInDirection(5);
            Vector2        jumpLocation = Vector2.Zero;

            double distance    = -1;
            int    maxDistance = 0;

            switch (Game1.player.FacingDirection)
            {
            case 0:
                distance    = Math.Abs(Game1.player.position.Y - tiles.Last().Y *Game1.tileSize);
                maxDistance = 72;
                break;

            case 2:
                distance    = Math.Abs(Game1.player.position.Y - tiles.Last().Y *Game1.tileSize);
                maxDistance = 48;
                break;

            case 1:
            case 3:
                distance    = Math.Abs(Game1.player.position.X - tiles.Last().X *Game1.tileSize);
                maxDistance = 65;
                break;
            }
            if (Helper.Input.IsDown(SButton.MouseLeft))
            {
                try
                {
                    int  xTile = (Game1.viewport.X + Game1.getOldMouseX()) / 64;
                    int  yTile = (Game1.viewport.Y + Game1.getOldMouseY()) / 64;
                    bool water = Game1.player.currentLocation.waterTiles[xTile, yTile];
                    if (Game1.player.swimming != water)
                    {
                        distance = -1;
                    }
                }
                catch
                {
                }
            }
            //Monitor.Log("Distance: " + distance);

            bool nextToLand = Game1.player.swimming && !Game1.player.currentLocation.isTilePassable(new Location((int)tiles.Last().X, (int)tiles.Last().Y), Game1.viewport) && !SwimUtils.IsWaterTile(tiles[tiles.Count - 2]) && distance < maxDistance;

            bool nextToWater = false;

            try
            {
                nextToWater = !Game1.player.swimming &&
                              !SwimUtils.IsTilePassable(Game1.player.currentLocation, new Location((int)tiles.Last().X, (int)tiles.Last().Y), Game1.viewport) &&
                              (Game1.player.currentLocation.waterTiles[(int)tiles.Last().X, (int)tiles.Last().Y] ||
                               SwimUtils.IsWaterTile(tiles[tiles.Count - 2])) &&
                              distance < maxDistance;
            }
            catch
            {
                //Monitor.Log($"exception trying to get next to water: {ex}");
            }

            //Monitor.Log($"next passable {Game1.player.currentLocation.isTilePassable(new Location((int)tiles.Last().X, (int)tiles.Last().Y), Game1.viewport)} next to land: {nextToLand}, next to water: {nextToWater}");


            if (Helper.Input.IsDown(Config.SwimKey) || nextToLand || nextToWater)
            {
                //Monitor.Log("okay to jump");
                for (int i = 0; i < tiles.Count; i++)
                {
                    Vector2 tileV      = tiles[i];
                    bool    isWater    = false;
                    bool    isPassable = false;
                    try
                    {
                        Tile tile = Game1.player.currentLocation.map.GetLayer("Buildings").PickTile(new Location((int)tileV.X * Game1.tileSize, (int)tileV.Y * Game1.tileSize), Game1.viewport.Size);
                        isWater    = SwimUtils.IsWaterTile(tileV);
                        isPassable = (nextToLand && !isWater && SwimUtils.IsTilePassable(Game1.player.currentLocation, new Location((int)tileV.X, (int)tileV.Y), Game1.viewport)) || (nextToWater && isWater && (tile == null || tile.TileIndex == 76));
                        //Monitor.Log($"Trying {tileV} is passable {isPassable} isWater {isWater}");
                        if (!SwimUtils.IsTilePassable(Game1.player.currentLocation, new Location((int)tileV.X, (int)tileV.Y), Game1.viewport) && !isWater && nextToLand)
                        {
                            //Monitor.Log($"Nixing {tileV}");
                            jumpLocation = Vector2.Zero;
                        }
                    }
                    catch (Exception ex)
                    {
                        Monitor.Log("" + ex);
                    }
                    if (nextToLand && !isWater && isPassable)
                    {
                        Monitor.Log($"Jumping to {tileV}");
                        jumpLocation = tileV;
                    }

                    if (nextToWater && isWater && isPassable)
                    {
                        Monitor.Log($"Jumping to {tileV}");
                        jumpLocation = tileV;
                    }
                }
            }

            if (jumpLocation != Vector2.Zero)
            {
                lastJump = Game1.player.millisecondsPlayed;
                //Monitor.Log("got swim location");
                if (Game1.player.swimming)
                {
                    ModEntry.willSwim           = false;
                    Game1.player.swimming.Value = false;
                    Game1.player.freezePause    = Config.JumpTimeInMilliseconds;
                    Game1.player.currentLocation.playSound("dwop", NetAudio.SoundContext.Default);
                    Game1.player.currentLocation.playSound("waterSlosh", NetAudio.SoundContext.Default);
                }
                else
                {
                    ModEntry.willSwim = true;
                    if (!SwimUtils.IsWearingScubaGear())
                    {
                        Game1.player.changeIntoSwimsuit();
                    }

                    Game1.player.freezePause = Config.JumpTimeInMilliseconds;
                    Game1.player.currentLocation.playSound("dwop", NetAudio.SoundContext.Default);
                }
                isJumping    = true;
                startJumpLoc = Game1.player.position.Value;
                endJumpLoc   = new Vector2(jumpLocation.X * Game1.tileSize, jumpLocation.Y * Game1.tileSize);
            }
        }