private void UpdateTicking(object sender, UpdateTickingEventArgs e) { if (!Context.IsWorldReady) { return; } GameLocation location = Game1.getPlayerOrEventFarmer().currentLocation; Netcode.NetCollection <Debris> debris = location.debris; GameTime time = new GameTime(); float rangeMult = magnetRangeMult; bool infRange = (rangeMult < 0 ? true : false); int speedMult = magnetSpeedMult; bool noBounce = noLootBounce; bool noWave = noLootWave; for (int j = 0; j < debris.Count; j++) { Debris d = debris[j]; NetObjectShrinkList <Chunk> chunks = (NetObjectShrinkList <Chunk>) typeof(Debris).GetField("chunks", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(d); if (chunks.Count == 0) { continue; } d.timeSinceDoneBouncing += (float)time.ElapsedGameTime.Milliseconds; if (d.timeSinceDoneBouncing >= (d.floppingFish ? 2500f : ((d.debrisType == Debris.DebrisType.SPRITECHUNKS || d.debrisType == Debris.DebrisType.NUMBERS) ? 1800f : (noBounce ? 0f : 600f)))) { if (d.debrisType == Debris.DebrisType.LETTERS || d.debrisType == Debris.DebrisType.NUMBERS || d.debrisType == Debris.DebrisType.SQUARES || d.debrisType == Debris.DebrisType.SPRITECHUNKS || (d.debrisType == Debris.DebrisType.CHUNKS && chunks[0].debrisType - chunks[0].debrisType % 2 != 8)) { continue; } if (d.debrisType == Debris.DebrisType.ARCHAEOLOGY || d.debrisType == Debris.DebrisType.OBJECT || d.debrisType == Debris.DebrisType.RESOURCE || d.debrisType == Debris.DebrisType.CHUNKS) { d.chunksMoveTowardPlayer = true; } d.timeSinceDoneBouncing = 0f; } if (location.farmers.Count == 0) { continue; } Vector2 total = default(Vector2); foreach (Chunk chunk in chunks) { total += chunk.position.Value; } Vector2 position = total / (float)chunks.Count; if (d.player.Value != null && (d.player.Value.currentLocation != location || !infRange && !(Math.Abs(position.X + 32f - (float)d.player.Value.getStandingX()) <= (float)d.player.Value.MagneticRadius * rangeMult && Math.Abs(position.Y + 32f - (float)d.player.Value.getStandingY()) <= (float)d.player.Value.MagneticRadius * rangeMult))) { d.player.Value = null; } Farmer farmer = d.player.Value; if (farmer == null && (Game1.IsMasterGame || location.isTemp())) { float bestDistance = float.MaxValue; Farmer bestFarmer = null; foreach (Farmer f in location.farmers) { bool pir = infRange || (Math.Abs(position.X + 32f - (float)f.getStandingX()) <= (float)f.MagneticRadius * rangeMult && Math.Abs(position.Y + 32f - (float)f.getStandingY()) <= (float)f.MagneticRadius * rangeMult); if ((f.UniqueMultiplayerID != d.DroppedByPlayerID || bestFarmer == null) && pir) { float distance = (f.Position - position).LengthSquared(); if (distance < bestDistance || (bestFarmer != null && bestFarmer.UniqueMultiplayerID == d.DroppedByPlayerID)) { bestFarmer = f; bestDistance = distance; } } } farmer = bestFarmer; } bool anyCouldMove = false; for (int i = chunks.Count - 1; i >= 0; i--) { Chunk chunk = chunks[i]; chunk.position.UpdateExtrapolation(chunk.getSpeed()); if (chunk.alpha > 0.1f && (d.debrisType == Debris.DebrisType.SPRITECHUNKS || d.debrisType == Debris.DebrisType.NUMBERS) && d.timeSinceDoneBouncing > 600f) { chunk.alpha = (1800f - d.timeSinceDoneBouncing) / 1000f; } if (chunk.position.X < -128f || chunk.position.Y < -64f || chunk.position.X >= (float)(location.map.DisplayWidth + 64) || chunk.position.Y >= (float)(location.map.DisplayHeight + 64)) { chunks.RemoveAt(i); } else { bool canMoveTowardPlayer = farmer != null; if (canMoveTowardPlayer) { Debris.DebrisType value = d.debrisType.Value; if (value - Debris.DebrisType.ARCHAEOLOGY > 1) { canMoveTowardPlayer = (value != Debris.DebrisType.RESOURCE || farmer.couldInventoryAcceptThisObject(chunk.debrisType - chunk.debrisType % 2, 1, 0)); } else if (d.item != null) { canMoveTowardPlayer = farmer.couldInventoryAcceptThisItem(d.item); } else { if (chunk.debrisType < 0) { canMoveTowardPlayer = farmer.couldInventoryAcceptThisItem(new StardewValley.Object(Vector2.Zero, chunk.debrisType * -1, false)); } else { canMoveTowardPlayer = farmer.couldInventoryAcceptThisObject(chunk.debrisType, 1, d.itemQuality); } if (chunk.debrisType == 102 && farmer.hasMenuOpen) { canMoveTowardPlayer = false; } } anyCouldMove = (anyCouldMove || canMoveTowardPlayer); if (canMoveTowardPlayer) { d.player.Value = farmer; } } if ((d.chunksMoveTowardPlayer || d.isFishable) && canMoveTowardPlayer) { if (d.player.Value.IsLocalPlayer) { if (speedMult < 0) { chunk.position.X = d.player.Value.Position.X; chunk.position.Y = d.player.Value.Position.Y; } else { for (int l = 1; l < speedMult; l++) { if (noWave) { if (chunk.position.X < d.player.Value.Position.X - 12f) { chunk.xVelocity.Value = 8f; } else if (chunk.position.X > d.player.Value.Position.X + 12f) { chunk.xVelocity.Value = -8f; } if (chunk.position.Y < d.player.Value.Position.Y - 12f) { chunk.yVelocity.Value = -8f; } else if (chunk.position.Y > d.player.Value.Position.Y + 12f) { chunk.yVelocity.Value = 8f; } } else { if (chunk.position.X < d.player.Value.Position.X - 12f) { chunk.xVelocity.Value = Math.Min(chunk.xVelocity + 0.8f, 8f); } else if (chunk.position.X > d.player.Value.Position.X + 12f) { chunk.xVelocity.Value = Math.Max(chunk.xVelocity - 0.8f, -8f); } if (chunk.position.Y + 32f < (float)(d.player.Value.getStandingY() - 12)) { chunk.yVelocity.Value = Math.Max(chunk.yVelocity - 0.8f, -8f); } else if (chunk.position.Y + 32f > (float)(d.player.Value.getStandingY() + 12)) { chunk.yVelocity.Value = Math.Min(chunk.yVelocity + 0.8f, 8f); } } chunk.position.X += chunk.xVelocity; chunk.position.Y -= chunk.yVelocity; } } } } } } typeof(Debris).GetField("chunks", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(d, chunks); } }
public bool updateChunks(GameTime time, GameLocation location) { if (chunks.Count == 0) { return(true); } timeSinceDoneBouncing += time.ElapsedGameTime.Milliseconds; if (timeSinceDoneBouncing >= (floppingFish ? 2500f : (((DebrisType)debrisType == DebrisType.SPRITECHUNKS || (DebrisType)debrisType == DebrisType.NUMBERS) ? 1800f : 600f))) { if ((DebrisType)debrisType == DebrisType.LETTERS || (DebrisType)debrisType == DebrisType.NUMBERS || (DebrisType)debrisType == DebrisType.SQUARES || (DebrisType)debrisType == DebrisType.SPRITECHUNKS || ((DebrisType)debrisType == DebrisType.CHUNKS && chunks[0].debrisType - chunks[0].debrisType % 2 != 8)) { return(true); } if ((DebrisType)debrisType == DebrisType.ARCHAEOLOGY || (DebrisType)debrisType == DebrisType.OBJECT || (DebrisType)debrisType == DebrisType.RESOURCE || (DebrisType)debrisType == DebrisType.CHUNKS) { chunksMoveTowardPlayer = true; } timeSinceDoneBouncing = 0f; } if (!location.farmers.Any() && !location.isTemp()) { return(false); } Vector2 position = approximatePosition(); Farmer farmer = player.Value; if (isEssentialItem() && shouldControlThis(location) && farmer == null) { farmer = findBestPlayer(location); } if (chunksMoveTowardPlayer && !isEssentialItem()) { if (player.Value != null && player.Value == Game1.player && !playerInRange(position, player.Value)) { player.Value = null; farmer = null; } if (shouldControlThis(location)) { if (player.Value != null && player.Value.currentLocation != location) { player.Value = null; farmer = null; } if (farmer == null) { farmer = findBestPlayer(location); } } } bool anyCouldMove = false; for (int i = chunks.Count - 1; i >= 0; i--) { Chunk chunk = chunks[i]; chunk.position.UpdateExtrapolation(chunk.getSpeed()); if (chunk.alpha > 0.1f && ((DebrisType)debrisType == DebrisType.SPRITECHUNKS || (DebrisType)debrisType == DebrisType.NUMBERS) && timeSinceDoneBouncing > 600f) { chunk.alpha = (1800f - timeSinceDoneBouncing) / 1000f; } if (chunk.position.X < -128f || chunk.position.Y < -64f || chunk.position.X >= (float)(location.map.DisplayWidth + 64) || chunk.position.Y >= (float)(location.map.DisplayHeight + 64)) { chunks.RemoveAt(i); } else { bool canMoveTowardPlayer = farmer != null; if (canMoveTowardPlayer) { switch (debrisType.Value) { case DebrisType.ARCHAEOLOGY: case DebrisType.OBJECT: if (item != null) { canMoveTowardPlayer = farmer.couldInventoryAcceptThisItem(item); break; } canMoveTowardPlayer = ((chunk.debrisType >= 0) ? farmer.couldInventoryAcceptThisObject(chunk.debrisType, 1, itemQuality) : farmer.couldInventoryAcceptThisItem(new Object(Vector2.Zero, chunk.debrisType * -1))); if (chunk.debrisType == 102 && (bool)farmer.hasMenuOpen) { canMoveTowardPlayer = false; } break; case DebrisType.RESOURCE: canMoveTowardPlayer = farmer.couldInventoryAcceptThisObject(chunk.debrisType - chunk.debrisType % 2, 1); break; default: canMoveTowardPlayer = true; break; } anyCouldMove |= canMoveTowardPlayer; if (canMoveTowardPlayer && shouldControlThis(location)) { player.Value = farmer; } } if (((chunksMoveTowardPlayer || isFishable) & canMoveTowardPlayer) && player.Value != null) { if (player.Value.IsLocalPlayer) { if (chunk.position.X < player.Value.Position.X - 12f) { chunk.xVelocity.Value = Math.Min((float)chunk.xVelocity + 0.8f, 8f); } else if (chunk.position.X > player.Value.Position.X + 12f) { chunk.xVelocity.Value = Math.Max((float)chunk.xVelocity - 0.8f, -8f); } if (chunk.position.Y + 32f < (float)(player.Value.getStandingY() - 12)) { chunk.yVelocity.Value = Math.Max((float)chunk.yVelocity - 0.8f, -8f); } else if (chunk.position.Y + 32f > (float)(player.Value.getStandingY() + 12)) { chunk.yVelocity.Value = Math.Min((float)chunk.yVelocity + 0.8f, 8f); } chunk.position.X += chunk.xVelocity; chunk.position.Y -= chunk.yVelocity; if (Math.Abs(chunk.position.X + 32f - (float)player.Value.getStandingX()) <= 64f && Math.Abs(chunk.position.Y + 32f - (float)player.Value.getStandingY()) <= 64f) { Item old = item; if (collect(player, chunk)) { if (Game1.debrisSoundInterval <= 0f) { Game1.debrisSoundInterval = 10f; if ((old == null || (int)old.parentSheetIndex != 73) && chunk.debrisType != 73) { location.localSound("coin"); } } chunks.RemoveAt(i); } } } } else { if ((DebrisType)debrisType == DebrisType.NUMBERS && toHover != null) { relativeXPosition += chunk.xVelocity; chunk.position.X = toHover.Position.X + 32f + relativeXPosition; chunk.scale = Math.Min(2f, Math.Max(1f, 0.9f + Math.Abs(chunk.position.Y - (float)chunkFinalYLevel) / 128f)); chunkFinalYLevel = toHover.getStandingY() + 8; if (timeSinceDoneBouncing > 250f) { chunk.alpha = Math.Max(0f, chunk.alpha - 0.033f); } if (!(toHover is Farmer) && !nonSpriteChunkColor.Equals(Color.Yellow) && !nonSpriteChunkColor.Equals(Color.Green)) { nonSpriteChunkColor.R = (byte)Math.Max(Math.Min(255, 200 + (int)chunkType), Math.Min(Math.Min(255, 220 + (int)chunkType), 400.0 * Math.Sin((double)timeSinceDoneBouncing / (Math.PI * 256.0) + Math.PI / 12.0))); nonSpriteChunkColor.G = (byte)Math.Max(150 - (int)chunkType, Math.Min(255 - (int)chunkType, (nonSpriteChunkColor.R > 220) ? (300.0 * Math.Sin((double)timeSinceDoneBouncing / (Math.PI * 256.0) + Math.PI / 12.0)) : 0.0)); nonSpriteChunkColor.B = (byte)Math.Max(0, Math.Min(255, (nonSpriteChunkColor.G > 200) ? (nonSpriteChunkColor.G - 20) : 0)); } } chunk.position.X += chunk.xVelocity; chunk.position.Y -= chunk.yVelocity; if (movingFinalYLevel) { chunkFinalYLevel -= (int)Math.Ceiling((float)chunk.yVelocity / 2f); if (chunkFinalYLevel <= chunkFinalYTarget) { chunkFinalYLevel = chunkFinalYTarget; movingFinalYLevel = false; } } if ((DebrisType)debrisType == DebrisType.SQUARES && chunk.position.Y < (float)(chunkFinalYLevel - 96) && Game1.random.NextDouble() < 0.1) { chunk.position.Y = chunkFinalYLevel - Game1.random.Next(1, 21); chunk.yVelocity.Value = (float)Game1.random.Next(30, 80) / 40f; chunk.position.X = Game1.random.Next((int)(chunk.position.X - chunk.position.X % 64f + 1f), (int)(chunk.position.X - chunk.position.X % 64f + 64f)); } if ((DebrisType)debrisType != DebrisType.SQUARES && chunk.bounces <= (floppingFish ? 65 : 2)) { chunk.yVelocity.Value -= 0.4f; } bool destroyThisChunk = false; if (chunk.position.Y >= (float)chunkFinalYLevel && (bool)chunk.hasPassedRestingLineOnce && chunk.bounces <= (floppingFish ? 65 : 2)) { Point tile_point = new Point((int)chunk.position.X / 64, chunkFinalYLevel / 64); if (Game1.currentLocation is IslandNorth && (debrisType.Value == DebrisType.ARCHAEOLOGY || debrisType.Value == DebrisType.OBJECT || debrisType.Value == DebrisType.RESOURCE || debrisType.Value == DebrisType.CHUNKS) && Game1.currentLocation.isTileOnMap(tile_point.X, tile_point.Y) && Game1.currentLocation.getTileIndexAt(tile_point, "Back") == -1) { chunkFinalYLevel += 48; } if ((DebrisType)debrisType != DebrisType.LETTERS && (DebrisType)debrisType != DebrisType.NUMBERS && (DebrisType)debrisType != DebrisType.SPRITECHUNKS && ((DebrisType)debrisType != 0 || chunk.debrisType - chunk.debrisType % 2 == 8) && shouldControlThis(location)) { location.playSound("shiny4"); } chunk.bounces++; if ((bool)floppingFish) { chunk.yVelocity.Value = Math.Abs(chunk.yVelocity) * ((movingUp && chunk.bounces < 2) ? 0.6f : 0.9f); chunk.xVelocity.Value = (float)Game1.random.Next(-250, 250) / 100f; } else { chunk.yVelocity.Value = Math.Abs((float)chunk.yVelocity * 2f / 3f); chunk.rotationVelocity = ((Game1.random.NextDouble() < 0.5) ? (chunk.rotationVelocity / 2f) : ((0f - chunk.rotationVelocity) * 2f / 3f)); chunk.xVelocity.Value -= (float)chunk.xVelocity / 2f; } Vector2 chunkTile = new Vector2((int)((chunk.position.X + 32f) / 64f), (int)((chunk.position.Y + 32f) / 64f)); if ((DebrisType)debrisType != DebrisType.LETTERS && (DebrisType)debrisType != DebrisType.SPRITECHUNKS && (DebrisType)debrisType != DebrisType.NUMBERS && location.doesTileSinkDebris((int)chunkTile.X, (int)chunkTile.Y, debrisType)) { destroyThisChunk = location.sinkDebris(this, chunkTile, chunk.position); } } int tile_x = (int)((chunk.position.X + 32f) / 64f); int tile_y = (int)((chunk.position.Y + 32f) / 64f); if ((!chunk.hitWall && location.Map.GetLayer("Buildings").Tiles[tile_x, tile_y] != null && location.doesTileHaveProperty(tile_x, tile_y, "Passable", "Buildings") == null) || location.Map.GetLayer("Back").Tiles[tile_x, tile_y] == null) { chunk.xVelocity.Value = 0f - (float)chunk.xVelocity; chunk.hitWall = true; } if (chunk.position.Y < (float)chunkFinalYLevel) { chunk.hasPassedRestingLineOnce.Value = true; } if (chunk.bounces > (floppingFish ? 65 : 2)) { chunk.yVelocity.Value = 0f; chunk.xVelocity.Value = 0f; chunk.rotationVelocity = 0f; } chunk.rotation += chunk.rotationVelocity; if (destroyThisChunk) { chunks.RemoveAt(i); } } } } if (!anyCouldMove && shouldControlThis(location)) { player.Value = null; } if (chunks.Count == 0) { return(true); } return(false); }