Modding:Guía del Modder/Fundamentos del juego

De Stardew Valley Wiki
Ir a la navegación Ir a la búsqueda

Creación de mods SMAPI SMAPI mascot.png


Modding:Índice

Esta página explica algunos de los fundamentos de Stardew Valley que son útiles para los modders. Ver también Modding:Tareas comunes.

Conceptos

Baldosas

El mundo se presenta como una cuadrícula de baldosas. Cada baldosa tiene una coordenada (x, y) que representa su posición en el mapa, donde (0, 0) es el mosaico superior izquierdo. El valor de x aumenta hacia la derecha y el de y aumenta hacia abajo. Por ejemplo:

Modding - creating an XNB mod - tile coordinates.png

Posiciones

El juego utiliza tres sistemas de coordenadas relacionados:

sistema de coordenadas relativo a notas
posición de la baldosa esquina superior izquierda del mapa medido en baldosas; se utiliza al colocar cosas en el mapap (p.ej., location.Objects utiliza posiciones de la baldosa).
posición absoluta esquina superior izquierda del mapa medido en píxeles; se usa cuando se necesitan mediciones más granulares (p.ej., movimiento del NPC).
posición de la pantalla esquina superior izquierda visible de la pantalla medido en píxeles; se utiliza al dibujar en la pantalla.

He aquí cómo convertir entre ellos:

conversión fórmula
absoluta pantalla x - Game1.viewport.X, y - Game1.viewport.Y
absoluta baldosa x / Game1.tileSize, y / Game1.tileSize
pantalla absoluta x + Game1.viewport.X, y + Game1.viewport.Y
pantalla baldosa (x + Game1.viewport.X) / Game1.tileSize, (y + Game1.viewport.Y) / Game1.tileSize
baldosa absoluta x * Game1.tileSize, y * Game1.tileSize
baldosa pantalla (x * Game1.tileSize) - Game1.viewport.X, (y * Game1.tileSize) - Game1.viewport.Y

Campos de red

Un 'tipo de red' es cualquiera de varias clases que Stardew Valley usa para sincronizar datos entre jugadores, y un 'campo de red' es cualquier campo o propiedad de esos tipos. Se nombran por el Net prefijo en sus nombres de tipo. Los tipos de red pueden representar valores simples como NetBool, o valores complejos como NetFieldDictionary. El juego recolectará regularmente todos los campos netos accesibles desde Game1.netWorldState y sincronizarlos con otros jugadores. Eso significa que muchos cambios de mod se sincronizarán automáticamente en el modo multijugador.

Aunque los campos netos se pueden convertir implícitamente a un tipo de valor equivalente (como bool x = new NetBool(true)), sus reglas de conversión son contrarias a la intuición y propensas a errores (p.ej., item?.category == null && item?.category != null ambos pueden ser verdaderos a la vez). Para evitar errores, nunca emita implícitamente campos de red; acceda al valor subyacente directamente en su lugar. El paquete NuGet de configuración de compilación debe detectar la mayoría de las conversiones implícitas y mostrar una advertencia de compilación adecuada.

Aquí se explica cómo acceder a los datos en algunos tipos de red comunes:

tipo de red descripción
NetBool
NetColor
NetFloat
NetInt
NetPoint
NetString
Un valor sincronizado simple. Acceda al valor usando field.Value.
NetCollection<T>
NetList<T>
NetObjectList<T>
Una lista de valores T. Esto implementa las interfaces estándar como IEnumerable<T> y IList<T>, por lo que puede iterarlo directamente como el foreach (T el valor en el campo).
NetLongDictionary<TValue, TNetValue>
NetPointDictionary<TValue, TNetValue>
NetVector2Dictionary<TValue, TNetValue>
Mapas Long, Point, o Vector2 para instancias de TValue (el tipo de valor subyacente) y TNetValue (el tipo de red sincronizada). Puede iterar llaves/valor en pares como el foreach (KeyValuePair<Long, TValue> pair in field.Pairs) (reemplazando Long con Point o Vector2 si es necesario).

Nivel del zoom

El jugador puede establecer un nivel de zoom en el juego entre 75% y 200%, que ajusta el tamaño de todos los píxeles que se muestran en la pantalla. Por ejemplo, aquí hay un reproductor con el mismo tamaño de ventana en diferentes niveles de zoom:

nivel mínimo de zoom (75%) nivel máximo de zoom (200%)
Zoom level 75.png Zoom level 200.png
Efecto en los mods de SMAPI
En el código del juego, esto está representado por el campo Game1.options.zoomLevel. Las coordenadas generalmente se ajustan para el nivel de zoom automáticamente, por lo que rara vez necesita tener esto en cuenta; pero puede convertir una coordenada no ajustada usando position * (1f / Game1.options.zoomLevel) si es necesario.

Escalado del IU

El jugador puede escalar la interfaz de usuario entre un 75 % y un 150 %, por separado y junto al nivel del zoom. Eso ajusta el tamaño de los píxeles que se muestran en la pantalla solo para los elementos de la interfaz de usuario. Por ejemplo, aquí hay un reproductor con el mismo tamaño de ventana en diferentes niveles de escala de IU:

escala mínima de IU (75 %) escala máxima de IU (150%)
UI scale 75.png UI scale 150.png
Efecto en los mods de SMAPI
El juego tiene dos modos de escala distintos según el contexto: modo de interfaz de usuario y modo sin interfaz de usuario. Puedes comprobar Game1.uiMode para saber qué modo está activo. Debe tener cuidado de no mezclar coordenadas de IU y no IU para evitar cálculos complicados; por ejemplo, haga todo su trabajo en un sistema de coordenadas y luego conviértalo una vez.


Una referencia rápida de escenarios comunes:
contexto modo de la escala que se aplica
menús en los que se puede hacer click Modo de interfaz de usuario (generalmente)
elementos del HUD modo de interfaz de usuario
RenderingActiveMenu
RenderedActiveMenu
modo de interfaz de usuario
Rendering
Rendered
depende del contexto; chequear en Game1.uiMode
draw método para objetos del mundo modo sin interfaz de usuario
coordenadas de la baldosa (sin píxeles) no se ve afectado por la escala de la interfaz de usuario
Si necesita dibujar la interfaz de usuario cuando el juego no está en modo de interfaz de usuario, puede establecer explícitamente el modo de escalado de interfaz de usuario:
Game1.game1.InUIMode(() =>
{
   // su código de dibujo de UI aquí
});
En el modo de interfaz de usuario, normalmente debe reemplazar Game1.viewport con Game1.uiViewport. No haga esto si va a ajustar las posiciones para el escalado de la interfaz de usuario por separado, ya que la conversión doble le dará resultados incorrectos. Puede convertir entre coordenadas UI y no UI usando Utility.ModifyCoordinatesForUIScale y Utility.ModifyCoordinatesFromUIScale.
Puedes probar si tu mod tiene en cuenta esto correctamente ajustando el zoom al máximo y la escala de la interfaz de usuario al mínimo (es decir., teniéndolos en valores opuestos) o viceversa; en particular, verifique cualquier lógica que maneje las posiciones de los píxeles, como hacer clic en los menús.

Accesos

Llaves de cadena

Una llave de cadena identifica de forma única dónde encontrar texto traducible, en la forma <asset name>:<key>. Por ejemplo, Game1.content.GetString("Strings\\StringsFromCSFiles:spring") buscará un spring llave en Strings\StringsFromCSFiles archivo en la carpeta de contenido (que contiene "primavera"). Esto se usa comúnmente en el código del juego (a través de Game1.content.GetString y en los activos de datos que necesitan texto traducible.

Clases principales

Game1

Game1 es la lógica central del juego. La mayor parte del estado del juego se rastrea a través de esta clase. Estos son algunos de los campos más útiles:

campo tipo propósito
Game1.player Farmer El jugador actual.
Game1.currentLocation GameLocation La ubicación del juego que contiene al jugador actual. Para un jugador no principal, puede ser null al hacer la transición entre ubicaciones.
Game1.locations IList<GameLocation> Todas las ubicaciones del juego. Para un jugador no principal, use el metodo SMAPI's GetActiveLocations en su lugar.
Game1.timeOfDay
Game1.dayOfMonth
Game1.currentSeason
Game1.year
int
int
string
int
La hora, el día, la estación y el año actuales. Consulte también la utilidad de fecha de SMAPI.
Game1.itemsToShip IList<Item> No usar (esto es parte de la lógica de guardado). Ver Game1.getFarm().getShippingBin(Farmer) en su lugar.
Game1.activeClickableMenu IClickableMenu El menú modales que se muestra. Creando un IClickableMenu subclase y asignar una instancia a este campo lo mostrará.

GameLocation y otros

  • GameLocation representa una ubicación en el juego que los jugadores pueden visitar. Cada ubicación tiene un mapa (el diseño de mosaico), objetos, árboles, personajes, etc. Estos son algunos de los campos más útiles para cualquier ubicación:
    campo tipo propósito
    Name string El nombre único para esta ubicación. (Esto no es único para interiores de edificios construidos como cabañas; consulte uniqueName en su lugar.)
    IsFarm bool Si se trata de una granja, donde se pueden plantar cultivos.
    IsGreenhouse bool Si se trata de un invernadero, donde se pueden plantar y cultivar cultivos durante todo el año.
    IsOutdoors bool Si la ubicación es al aire libre (a diferencia de un invernadero, edificio, etc.).
    characters NetCollection de NPC Los aldeanos, las mascotas, los caballos y los monstruos del lugar.
    critters List of Critter Los pájaros, ardillas u otros bichos temporales en el lugar.
    debris NetCollection de Debris Los elementos flotantes en la ubicación.
    farmers FarmerCollection Los jugadores en el ubicación.
    Objects OverlaidDictionary Las cercas colocadas, las máquinas de artesanía y otros objetos en la ubicación actual. (OverlaidDictionary básicamente un NetVector2Dictionary con lógica agregada para mostrar ciertos elementos de búsqueda sobre objetos preexistentes).
    terrainFeatures NetVector2Dictionary de TerrainFeature Los árboles, árboles frutales, hierba alta, tierra cultivada (incluyendo cultivos) y pisos en el lugar. Para cada par, la clave es su posición de mosaico y el valor es la instancia de la característica del terreno.
    waterTiles bool[,] Una matriz multidimensional que indica si cada baldosa en el mapa es un baldosas de lago/río. Por ejemplo, if (location.waterTiles[10, 20]) comprueba la baldosa en la posición (10, 20).
  • BuildableGameLocation es una subclase de BuildableGame para lugares donde los jugadores pueden construir edificios. En el juego de vainilla, solo la granja es un lugar edificable. Estos son los campos más útiles:
    campo tipo propósito
    buildings NetCollection de Building Los edificios en el lugar.
  • Farm es una subclase de ambos GameLocation and BuildableGameLocation del juego para construirpara lugares donde el jugador puede tener animales y cultivar. En Vanilla, solo hay una ubicación de granja (a la que se accede mediante Game1.getFarm()). Estas son sus propiedades más útiles:
    campo tipo propósito
    animals NetLongDictionary de FarmAnimal os animales de granja actualmente en el lugar.
    resourceClumps NetCollection de ResourceClump Los cultivos gigantes, tocones grandes, rocas y meteoritos en el lugar.
    piecesOfHay NetInt La cantidad de heno almacenado en silos.
    shippingBin NetCollection de Item Los artículos en el contenedor de envío.
  • Hay una serie de subclases para una ubicación específica (como AdventureGuild) que tienen campos útiles para casos específicos.