internal SnowWeatherDebris(XVector2 position, int which, float rotationVelocity, float dx, float dy, float rotation, float rotationRate, float scale) : base(position, which, rotationVelocity, dx, dy) { Rotation = rotation; RotationRate = rotationRate; Scale = scale; }
public XEntity PlaceObjectAt(XVector2 pos) { string prefabName = "E" + ObjectName.Replace(" ", ""); Type prefab = Type.GetType("RTS4.Environment.Entities.Prefabs." + prefabName); if (prefab == null) { Console.WriteLine("Unable to find prefab \"" + prefabName + "\""); return(null); } XEntity entity = prefab.GetConstructor(new Type[] { }) .Invoke(new object[] { }) as XEntity; var transform = entity.GetComponent <CTransform>(); if (transform != null) { transform.Transform = XMatrix.CreateTranslation(new XVector3(pos.X, 0, pos.Y)); } if (PlacedObjects == null) { PlacedObjects = new List <XEntity>(); } PlacedObjects.Add(entity); return(entity); }
private static bool ForwardDraw( XSpriteBatch @this, XTexture2D?texture, XVector2 position, XColor color, XRectangle?sourceRectangle = null, float rotation = 0f, XVector2?origin = null, XVector2?scale = null, SpriteEffects effects = SpriteEffects.None, float layerDepth = 0f ) { if (!Config.IsEnabled) { return(true); } @this.Draw( texture: texture, position: position, sourceRectangle: sourceRectangle, color: color, rotation: rotation, origin: origin ?? XVector2.Zero, scale: scale ?? XVector2.One, effects: effects, layerDepth: layerDepth ); return(false); }
public static bool OnDrawString( XSpriteBatch __instance, SpriteFont spriteFont, StringBuilder text, XVector2 position, XColor color, float rotation, XVector2 origin, XVector2 scale, SpriteEffects effects, float layerDepth ) { return(Core.OnDrawStringImpl.DrawString( __instance, spriteFont, text, position, color, rotation, origin, scale, effects, layerDepth )); }
public static bool OnDrawLast( XSpriteBatch __instance, ref XTexture2D?texture, ref XRectangle destinationRectangle, ref XRectangle?sourceRectangle, ref XColor color, float rotation, ref XVector2 origin, ref SpriteEffects effects, ref float layerDepth, ref ManagedTexture2D?__state ) { if (!Config.IsEnabled) { return(true); } return(__instance.OnDraw( texture: ref texture, destination: ref destinationRectangle, source: ref sourceRectangle, color: ref color, rotation: rotation, origin: ref origin, effects: ref effects, layerDepth: ref layerDepth, __state: ref __state )); }
public static bool WarpCharacter(NPC?character, GameLocation?targetLocation, XVector2 position) { if (!Config.IsUnconditionallyEnabled || !Config.Extras.Pathfinding.AllowNPCsOnFarm || !Config.Extras.Pathfinding.OptimizeWarpPoints) { return(true); } if (PathfindToNextScheduleLocation is null) { return(true); } if (character is null || Game1.player is not { } player) { return(true); } if (character.currentLocation is null) { return(true); } if (targetLocation is null) { return(true); } bool isFamily = false; // If the player has friendship data, check if the given character is married or a roommate. if (player.friendshipData.TryGetValue(character.Name, out var value)) { isFamily = value.IsMarried() || value.IsRoommate(); } // Check if the given character is a child. var characterChild = character as Child; if (!isFamily && (player.getChildren()?.Contains(characterChild) ?? false)) { isFamily = true; } // https://github.com/aedenthorn/StardewValleyMods/blob/master/FreeLove/FarmerPatches.cs // If the character is family, a pet, or a spouse, run the logic. if (isFamily || character == player.getSpouse() || character == player.getPet()) { // If the character is still sleeping, warp it because otherwise it just glides on the floor creepily. if (character.isSleeping.Value || character.layingDown) { return(true); } // If it's a pet, it appears that 'behavior 1' indicates sleeping. if (character is Pet { CurrentBehavior : Pet.behavior_Sleep or Pet.behavior_SitDown or Cat.behavior_Flop or Dog.behavior_SitSide })
public static bool OnDraw(XSpriteBatch __instance, XTexture2D?texture, XVector2 position, XColor color) { return(ForwardDraw( @this: __instance, texture: texture, position: position, color: color )); }
/** * Makes a line of player locations. Sometimes you will want players to be placed in a line. * Anatolia places each team on a line, while Vinlandsaga places all players in a line. * Using a line placement is not easy because there may not be enough room for player areas or resources. * X and Z determine the starting and ending locations of the line. * DistVariation determines how far from the line player areas can vary, and spacingVariation determines how much space there is among points along the line where players are placed. */ public void rmPlacePlayersLine(float x1, float z1, float x2, float z2, float distVariation, float spacingVariation) { XVector2 p1 = new XVector2(x1, z1), p2 = new XVector2(x2, z2); for (int p = 1; p < players.Count; ++p) { players[p].Position = fracToMeters(XVector2.Lerp(p1, p2, (float)(p - 1) / (players.Count - 1))); } }
// Returns a point along the surface, expected f from 0 to Length public XVector2 GetPointAlongSurface(XReal f) { for (int p = 0; p < Points.Length; ++p) { XVector2 p1 = Points[p], p2 = Points[(p + 1) % Points.Length]; XReal len = XVector2.Distance(p1, p2); if (len > f) { return(XVector2.Lerp(p1, p2, f / len)); } f -= len; } throw new Exception("rmPolygon::GetPointAlongSurface(), f is not in range!"); }
public static bool OnDraw(XSpriteBatch __instance, XTexture2D?texture, XVector2 position, XRectangle?sourceRectangle, XColor color, float rotation, XVector2 origin, float scale, SpriteEffects effects, float layerDepth) { return(ForwardDraw( @this: __instance, texture: texture, position: position, sourceRectangle: sourceRectangle, color: color, rotation: rotation, origin: origin, scale: new XVector2(scale), effects: effects, layerDepth: layerDepth )); }
public XEntity PlaceObjectAt(XVector2 pos) { string prefabName = "E" + ObjectName.Replace(" ", ""); Type prefab = Type.GetType("RTS4.Environment.Entities.Prefabs." + prefabName); if (prefab == null) { Console.WriteLine("Unable to find prefab \"" + prefabName + "\""); return null; } XEntity entity = prefab.GetConstructor(new Type[] { }) .Invoke(new object[] { }) as XEntity; var transform = entity.GetComponent<CTransform>(); if (transform != null) transform.Transform = XMatrix.CreateTranslation(new XVector3(pos.X, 0, pos.Y)); if (PlacedObjects == null) PlacedObjects = new List<XEntity>(); PlacedObjects.Add(entity); return entity; }
public override bool IsPointOk(XReal tAreaX, XReal tAreaY) { var area = Area; XReal dist = XVector2.Distance( new XVector2(tAreaX, tAreaY), area.Position ); XReal distFromEdge = dist - area.Size; if (XReal.Abs(distFromEdge) > MaxDistance || XReal.Abs(distFromEdge) < MinDistance) { return(false); } return(true); }
public static bool OnDraw(XSpriteBatch __instance, ref XTexture2D?texture, ref XVector2 position, ref XRectangle?sourceRectangle, ref XColor color, float rotation, ref XVector2 origin, ref XVector2 scale, SpriteEffects effects, float layerDepth) { if (!Config.IsEnabled) { return(true); } return(__instance.OnDraw( texture: ref texture, position: ref position, source: ref sourceRectangle, color: ref color, rotation: rotation, origin: ref origin, scale: ref scale, effects: effects, layerDepth: ref layerDepth )); }
public XReal GetHeightAt(XVector2 tpos) { int tx = (tpos.X / Scale.X).ToInt, ty = (tpos.Y / Scale.Z).ToInt; if (tx < 0) { tx = 0; } else if (tx > Width - 1) { tx = Width - 1; } if (ty < 0) { ty = 0; } else if (ty > Height - 1) { ty = Height - 1; } return(tiles[tx, ty].Height * Scale.Y); }
/** * Makes a square of player locations. Places players in a square, which automatically adjusts to a rectangle for rectangular maps. * Unlike the circle, variance here is determined by a plus or minus (the distVariation) off of the mean distance. * SpacingVariation determines whether players are equidistant or can be slightly closer or farther apart. */ public void rmPlacePlayersSquare(float dist, float distVariation, float spacingVariationfloat) { XVector2 min = new XVector2(MapSizeX * dist / 2, MapSizeZ * dist / 2); XVector2 max = new XVector2(MapSizeX - min.X, MapSizeZ - min.Y); RMPolygon poly = new RMPolygon() { Points = new[] { new XVector2(min.X, min.Y), new XVector2(min.X, max.Y), new XVector2(max.X, max.Y), new XVector2(max.X, min.Y) } }; float polyLen = poly.Length; float off = (float)rand.NextDouble(); for (int p = 1; p < players.Count; ++p) { players[p].Position = fracToMeters(tileToFrac(poly.GetPointAlongSurface( ((p - 1 + off) / (players.Count - 1)) * polyLen) )); } }
public XVector2 tileToFrac(XVector2 tile) { return tile / new XVector2(TileSizeX - 1, TileSizeZ - 1); }
public XVector2 fracToMeters(XVector2 frac) { return(frac * new XVector2(MapSizeX, MapSizeZ) * MetersPerTile); }
public XVector2 tileToFrac(XVector2 tile) { return(tile / new XVector2(MapSizeX, MapSizeZ)); }
internal static XVector2 Clamp(this XVector2 value, float min, float max) => new(value.X.Clamp(min, max), value.Y.Clamp(min, max));
public XVector2 fracToMeters(XVector2 frac) { return frac * new XVector2(TileSizeX - 1, TileSizeZ - 1) * MetersPerTile; }
internal static bool OnDraw( this XSpriteBatch @this, ref XTexture2D?texture, ref XVector2 position, ref XRectangle?source, ref XColor color, float rotation, ref XVector2 origin, ref XVector2 scale, SpriteEffects effects, ref float layerDepth ) { if (texture is null) { return(false); } GetDrawParameters( texture: texture, source: source, bounds: out var sourceRectangle, scaleFactor: out var scaleFactor ); var originalSourceRect = sourceRectangle; ManagedSpriteInstance?spriteInstance; ManagedTexture2D? resampledTexture; if (texture is ManagedTexture2D texture2D) { resampledTexture = texture2D; spriteInstance = resampledTexture.SpriteInstance; sourceRectangle = resampledTexture.Dimensions; } else if (texture.FetchScaledTexture( expectedScale: EstimateScale(scale, scaleFactor), source: ref sourceRectangle, spriteInstance: out spriteInstance, create: true )) { spriteInstance.UpdateReferenceFrame(); resampledTexture = spriteInstance.Texture !; } else { resampledTexture = null; } if (spriteInstance is null || resampledTexture is null) { return(Continue); } if (originalSourceRect.X < 0) { position.X -= originalSourceRect.X * scale.X; } if (originalSourceRect.Y < 0) { position.Y -= originalSourceRect.Y * scale.Y; } var adjustedScale = (Vector2F)scale / spriteInstance.Scale; var adjustedPosition = position; var adjustedOrigin = (Vector2F)origin; if (spriteInstance.TexType == TextureType.SlicedImage) { sourceRectangle = source ?? resampledTexture.Bounds; if (source is not null) { sourceRectangle = new Bounds( (Vector2I)source.Value.Location - spriteInstance.OriginalSourceRectangle.Offset, source.Value.Size ); sourceRectangle.Offset = (sourceRectangle.OffsetF * spriteInstance.Scale).NearestInt(); sourceRectangle.Extent = (sourceRectangle.ExtentF * spriteInstance.Scale).NearestInt(); } } if (!spriteInstance.Padding.IsZero) { var paddingX = spriteInstance.Padding.X; var paddingY = spriteInstance.Padding.Y; if (effects.HasFlag(SpriteEffects.FlipHorizontally)) { paddingX = (paddingX.Y, paddingX.X); } if (effects.HasFlag(SpriteEffects.FlipVertically)) { paddingY = (paddingY.Y, paddingY.X); } var padding = new PaddingQuad(paddingX, paddingY); var textureSize = new Vector2F(sourceRectangle.Extent); var innerSize = (Vector2F)spriteInstance.UnpaddedSize; // This is the scale factor to bring the inner size to the draw size. var innerRatio = textureSize / innerSize; // spriteInstance.InnerRatio; // Scale the... scale by the scale factor. adjustedScale *= innerRatio; adjustedOrigin *= spriteInstance.Scale; adjustedOrigin /= innerRatio; adjustedOrigin += (Vector2F)padding.Offset; } else { adjustedOrigin *= spriteInstance.Scale; } if (source.HasValue) { sourceRectangle.Invert.X = source.Value.Width < 0; sourceRectangle.Invert.Y = source.Value.Height < 0; } if (Debug.Mode.RegisterDrawForSelect( instance: spriteInstance, texture: texture, originalPosition: position, originalSource: source, position: adjustedPosition, source: sourceRectangle, color: color, rotation: rotation, originalOrigin: origin, origin: adjustedOrigin, scale: adjustedScale, effects: effects, layerDepth: layerDepth )) { color = XColor.Red; } texture = resampledTexture; source = sourceRectangle; origin = adjustedOrigin; scale = adjustedScale; position = adjustedPosition; return(Continue); }
// Takes the arguments, and checks to see if the texture is padded. If it is, it is forwarded to the correct draw call, avoiding // intervening mods altering the arguments first. internal static bool OnDrawFirst( this XSpriteBatch @this, ref XTexture2D?texture, ref XRectangle destination, ref XRectangle?source, XColor color, float rotation, ref XVector2 origin, ref SpriteEffects effects, float layerDepth, ref ManagedTexture2D?__state ) { if (texture is null) { return(false); } using var watchdogScoped = WatchDog.WatchDog.ScopedWorkingState; /* * if (destination.Width < 0 || destination.Height < 0) { * Debug.Trace("destination invert"); * } * if (source is XRectangle sourceRect && (sourceRect.Width < 0 || sourceRect.Height < 0)) { * Debug.Trace("source invert"); * } */ GetDrawParameters( texture: texture, source: source, bounds: out var sourceRectangle, scaleFactor: out var scaleFactor ); var referenceRectangle = sourceRectangle; Bounds destinationBounds = destination; var expectedScale2D = destinationBounds.ExtentF / sourceRectangle.ExtentF; var expectedScale = EstimateScale(expectedScale2D, scaleFactor); if (!texture.FetchScaledTexture( expectedScale: expectedScale, source: ref sourceRectangle, spriteInstance: out var spriteInstance, create: true )) { return(Continue); } spriteInstance.UpdateReferenceFrame(); if (referenceRectangle.X < 0) { destinationBounds.Left -= referenceRectangle.X; } if (referenceRectangle.Y < 0) { destinationBounds.Top -= referenceRectangle.Y; } var resampledTexture = spriteInstance.Texture !; if (!spriteInstance.Padding.IsZero) { // Convert the draw into the other draw style. This has to be done because the padding potentially has // subpixel accuracy when scaled to the destination rectangle. var originalSize = referenceRectangle.ExtentF; var destinationSize = destinationBounds.ExtentF; var newScale = destinationSize / originalSize; var newPosition = destinationBounds.OffsetF; if ((destinationBounds.Invert.X || destinationBounds.Invert.Y) && DrawState.CurrentRasterizerState.CullMode == CullMode.CullCounterClockwiseFace) { // Winding order is invalid return(Stop); } if (destinationBounds.Invert.X) { effects ^= SpriteEffects.FlipHorizontally; } if (destinationBounds.Invert.Y) { effects ^= SpriteEffects.FlipVertically; } // TODO handle culling here for inverted sprites? @this.Draw( texture: resampledTexture, position: newPosition, sourceRectangle: sourceRectangle, color: color, rotation: rotation, origin: origin, scale: newScale, effects: effects, layerDepth: layerDepth ); return(Stop); } __state = resampledTexture; return(Continue); }
internal static bool OnDraw( this XSpriteBatch @this, ref XTexture2D?texture, ref XRectangle destination, ref XRectangle?source, ref XColor color, float rotation, ref XVector2 origin, ref SpriteEffects effects, ref float layerDepth, ref ManagedTexture2D?__state ) { if (texture is null) { return(false); } Bounds sourceRectangle; ManagedSpriteInstance?spriteInstance; ManagedTexture2D resampledTexture; Bounds destinationBounds = destination; var referenceSource = source.GetValueOrDefault(); if (__state is null) { GetDrawParameters( texture: texture, source: source, bounds: out sourceRectangle, scaleFactor: out var scaleFactor ); var expectedScale2D = new Vector2F(destinationBounds.Extent) / new Vector2F(sourceRectangle.Extent); var expectedScale = EstimateScale(expectedScale2D, scaleFactor); if (!texture.FetchScaledTexture( expectedScale: expectedScale, source: ref sourceRectangle, spriteInstance: out spriteInstance )) { return(Continue); } if (spriteInstance.TexType == TextureType.SlicedImage) { sourceRectangle = source ?? spriteInstance.Texture !.Bounds; } spriteInstance.UpdateReferenceFrame(); resampledTexture = spriteInstance.Texture !; } else { resampledTexture = __state; spriteInstance = resampledTexture.SpriteInstance; sourceRectangle = resampledTexture.Dimensions; if (spriteInstance.TexType == TextureType.SlicedImage) { sourceRectangle = source ?? resampledTexture.Bounds; if (source.HasValue) { sourceRectangle = new Bounds( (Vector2I)source.Value.Location - spriteInstance.OriginalSourceRectangle.Offset, source.Value.Size ); sourceRectangle.Offset = (sourceRectangle.OffsetF * spriteInstance.Scale).NearestInt(); sourceRectangle.Extent = (sourceRectangle.ExtentF * spriteInstance.Scale).NearestInt(); } } } if (referenceSource.X < 0) { destination.X -= referenceSource.X; } if (referenceSource.Y < 0) { destination.Y -= referenceSource.Y; } var scaledOrigin = (Vector2F)origin * spriteInstance.Scale; if (source.HasValue) { sourceRectangle.Invert.X = source.Value.Width < 0; sourceRectangle.Invert.Y = source.Value.Height < 0; } if (Debug.Mode.RegisterDrawForSelect( instance: spriteInstance, texture: texture, originalDestination: destinationBounds, destination: destination, source: sourceRectangle, color: color, rotation: rotation, originalOrigin: origin, origin: scaledOrigin, effects: effects, layerDepth: layerDepth )) { color = XColor.Red; } source = sourceRectangle; origin = scaledOrigin; texture = resampledTexture; return(Continue); }
internal static XVector2 Saturate(this XVector2 v) => new(v.X.Saturate(), v.Y.Saturate());
/** * Makes a square of player locations. Places players in a square, which automatically adjusts to a rectangle for rectangular maps. * Unlike the circle, variance here is determined by a plus or minus (the distVariation) off of the mean distance. * SpacingVariation determines whether players are equidistant or can be slightly closer or farther apart. */ public void rmPlacePlayersSquare(XReal dist, XReal distVariation, XReal spacingVariationfloat) { XReal half = (XReal)0.5f; XVector2 min = new XVector2(TileSizeX * (half - dist), TileSizeZ * (half - dist)); XVector2 max = new XVector2(TileSizeX - min.X, TileSizeZ - min.Y); RMPolygon poly = new RMPolygon() { Points = new[] { new XVector2(min.X, min.Y), new XVector2(min.X, max.Y), new XVector2(max.X, max.Y), new XVector2(max.X, min.Y) } }; XReal polyLen = poly.Length; XReal off = (XReal)rand.NextDouble(); for (int p = 1; p < players.Count; ++p) { players[p].Position = fracToMeters(tileToFrac(poly.GetPointAlongSurface( ((p - 1 + off) / (players.Count - 1)) * polyLen) )); } }
internal static Vector2I NextInt(this XVector2 v) => Vector2I.From(v.X.NextInt(), v.Y.NextInt());
/** * Makes a line of player locations. Sometimes you will want players to be placed in a line. * Anatolia places each team on a line, while Vinlandsaga places all players in a line. * Using a line placement is not easy because there may not be enough room for player areas or resources. * X and Z determine the starting and ending locations of the line. * DistVariation determines how far from the line player areas can vary, and spacingVariation determines how much space there is among points along the line where players are placed. */ public void rmPlacePlayersLine(XReal x1, XReal z1, XReal x2, XReal z2, XReal distVariation, XReal spacingVariation) { XVector2 p1 = new XVector2(x1, z1), p2 = new XVector2(x2, z2); for (int p = 1; p < players.Count; ++p) { players[p].Position = fracToMeters(XVector2.Lerp(p1, p2, (XReal)(p - 1) / (players.Count - 1))); } }
public XPoint2 metersToTiles(XVector2 meter) { return new XPoint2( (meter.X / MetersPerTile).RoundedToInt, (meter.Y / MetersPerTile).RoundedToInt ); }
/**Place object definition per player.*/ public void rmPlaceObjectDefPerPlayer(int defID, bool playerOwned, long placeCount = 1) { for (int p = 0; p < cNumberNonGaiaPlayers; ++p) { for (int o = 0; o < placeCount; ++o) { XVector2 tpos = new XVector2(rmXFractionToMeters(rmPlayerLocXFraction(p + 1)), rmZFractionToMeters(rmPlayerLocZFraction(p + 1))); var obj = objectDefinitions[defID].PlaceObjectAt(tpos); if (obj != null) { simulation.AddObject(obj); } } } }
internal static Vector2I TruncateInt(this XVector2 v) => Vector2I.From(v.X.TruncateInt(), v.Y.TruncateInt());
public static bool OnDrawString(XSpriteBatch __instance, SpriteFont spriteFont, StringBuilder text, XVector2 position, XColor color) { __instance.DrawString( spriteFont: spriteFont, text: text, position: position, color: color, rotation: 0.0f, origin: XVector2.Zero, scale: XVector2.One, effects: SpriteEffects.None, layerDepth: 0.0f ); return(false); }