El dispositivo de transacciones dentro de la isla de Verse incluye una plantilla para las transacciones dentro de la isla. Incluye todas las implementaciones para aspectos clave del módulo del Marketplace en la API de Verse. Esto incluye objetos, ofertas, ofertas combinadas y la gestión de compras mediante el uso de la IU predeterminada de la tienda. Usa este código como guía para configurar tu tienda rápidamente.
Sigue los pasos detallados a continuación para acceder al dispositivo:
Ve al Explorador de Verse.
Haz clic con el botón derecho del mouse en el nombre de tu proyecto.
Selecciona Añadir nuevo archivo de Verse al proyecto.
Selecciona Dispositivo de transacciones dentro de la isla.
Cómo crear objetos
Los objetos se definen en Verse como productos y se dividen en una de dos categorías: objetos consumibles, que se eliminan del inventario del jugador cuando se utilizan, y objetos duraderos, que el jugador puede seguir usando sin que se eliminen de su inventario.
El módulo EntitlementInfo
Los módulos son unidades atómicas de código que se pueden redistribuir para su uso en varios archivos. Los módulos se pueden modificar con el tiempo sin romper las dependencias en un archivo en el que el módulo ya se utiliza. Puedes separar unidades de código largas o repetitivas, como definiciones de productos, en un archivo diferente y luego importarlas con la instrucción using.
El módulo EntitlementInfo recopila los nombres, las descripciones y las descripciones breves de todos los derechos en la plantilla. Incluye este módulo en cualquier archivo donde necesites definir productos sin tener que redefinir repetidamente su nombre y otras variables. Esto facilita las modificaciones a la información de los productos y reduce la complejidad al depurar tus productos.
# Setup your entitlements and offers data, in this case that's your Names, Descriptions & Short Descriptions as well as any other data you want to be constant
EntitlementInfo<public> := module:
Potion<public> := module:
Name<public><localizes>:message = "Potion"
Description<public><localizes>:message = "Adds +10 health when used. Green so you know its healthy!"
Cómo definir derechos
Cada producto de Verse tiene las siguientes propiedades:
Nombre: el nombre del derecho. Tiene un límite de 50 caracteres.
Descripción: la descripción larga que se muestra con el producto. Tiene un límite de 500 caracteres.
Descripción breve: una descripción breve que resume el producto. Tiene un límite de 100 caracteres.
Ícono: una imagen del derecho.
Si tu producto es un objeto aleatorio pago, debes incluir en la descripción las probabilidades numéricas exactas de lo que el jugador podría recibir. Para obtener más información, consulta Objetos aleatorios pagos.
Un producto de Verse también puede tener las siguientes propiedades opcionales:
MaxCount: la cantidad máxima de ese derecho que el jugador puede poseer en un momento dado.
Consumible: Si se establece en verdadero, el producto puede consumirse con
ConsumeEntitlement, lo que reduce la cantidad total de productos consumidos que el usuario tiene en los sistemas de Epic. Si se establece en No, el producto es un objeto permanente y no se consumirá con el uso.PaidArea: Si se establece en Sí, el derecho proporciona acceso a una zona de pago.
PaidRandomItem: si se establece en Sí, estos derechos se compran o canjean con contenido para obtener una recompensa aleatoria.
ConsequentialToGameplay: si se establece en Sí, el objeto proporciona una ventaja importante en tu isla. Consulta Consecuente con la jugabilidad para obtener más información.
En el fragmento que aparece a continuación, se utiliza el módulo EntitlementInfo definido anteriormente para crear las definiciones de tus derechos. Para definir un producto consumible, Consumible debe configurarse en Verdadero.
Antes de definir tus derechos, necesitas crear una clase de producto base que se utilizará para los derechos en tu experiencia.
En este caso, la clase será feature_example_entitlement.
También es necesario definir una ruta de archivo a una textura de ícono para cada definición de derecho o la definición de derecho no pasará la validación.
Entitlements<public> := module:
using {EntitlementInfo}
# The base entitlement you should define for ALL your entitlements in your experience
feature_example_entitlement<public> := class<abstract><castable>(entitlement){}
basic_sword<public> := class<concrete>(feature_example_entitlement):
var Name<override>:message = Sword.Name
De forma predeterminada, los objetos no son consumibles y tienen un MaxCount de 1. Si el objeto es un área de pago, un objeto aleatorio pago o proporciona una ventaja importante que es consecuente con la jugabilidad, los campos pertinentes deben estar definidos en tu código.
Ofertas de derechos
Una oferta especifica un precio en monedas V para un objeto o un recurso. Cada oferta tiene su propio nombre, descripción e ícono, independientes de las especificaciones de productos. Una oferta se define en Verse.
Para vender el producto, debes tener una oferta correspondiente para ese producto.
Cada oferta tiene las siguientes propiedades:
Nombre: el nombre de la oferta.
Descripción: la descripción larga que se muestra junto a la oferta.
Descripción breve: una descripción breve para resumir la oferta en cuadros de diálogo más pequeños.
Ícono: una imagen de la oferta.
EntitlementType: una declaración del derecho incluido en la oferta.
Precio: un precio en monedas V. No debe ser inferior a 50 monedas V ni superior a 5000 monedas V. El precio debe establecerse en múltiplos de 50.
Este fragmento muestra cómo definir ofertas de derechos utilizando el módulo existente EntitlementInfo para obtener información básica sobre las ofertas de derechos. También es necesario definir un ícono, el tipo de producto (EntitlementType),
que define el producto de la oferta y el precio en monedas V. También puedes definir, opcionalmente, una edad mínima de compra para una oferta, según un valor fijo, un código de país, o restringir el acceso a la oferta por familia de plataformas o una combinación de estos factores. En el siguiente fragmento, se muestran algunos ejemplos de esto.
Los códigos de subdivisión no están soportados actualmente y estarán disponibles en una versión futura.
ExampleOffers<public> := module:
using {EntitlementInfo}
basic_sword<public> := class(entitlement_offer):
var Name<override>:message = EntitlementInfo.Sword.Name
var Description<override>:message = EntitlementInfo.Sword.Description
var ShortDescription<override>:message = EntitlementInfo.Sword.ShortDescription
El precio en monedas V debe ser un múltiplo de 50 y estar entre 50 y 5000 monedas V.
Para los objetos aleatorios pagos, debes garantizar que los jugadores puedan ver las probabilidades numéricas exactas de obtener cada objeto aleatorio pago en los detalles de la oferta. De no hacerlo, se considerará una infracción del Reglamento de desarrolladores de Fortnite, y tú y tu isla estarán sujetos a las sanciones correspondientes.
Para obtener más información, consulta Restricciones de las transacciones dentro de la isla.
Ofertas por lote
Los lotes se definen en Verse y pueden contener una combinación de diferentes ofertas, conjuntos de la misma oferta o una mezcla de ambos. Al igual que las ofertas simples, las ofertas por lote especifican su propio precio, nombre y descripción, y tienen un ícono que es distinto al de los productos y las ofertas. También puedes anidar ofertas al incluir lotes dentro de una oferta por lote. Un ejemplo sería un lote por tiempo limitado que incluye una pala y un paquete de semillas de maíz. Esto te permite utilizar lotes más pequeños como bloques de construcción para lotes combinados más grandes.
Los tipos de lotes estándar son los siguientes:
Lote apilado: un lote que contiene varias ofertas del mismo derecho, normalmente a un precio con descuento.
Lote de varias ofertas: un paquete que combina ofertas para varios derechos, que también puede incluir una combinación de ofertas apiladas y ofertas normales.
Un lote contiene una matriz de tuplas de ofertas, la cual contiene la oferta definida y un int que indica el número de ofertas.
La profundidad de las ofertas anidadas no puede superar las 5, o la transacción fallará. Intenta limitar las ofertas anidadas siempre que sea posible.
El siguiente fragmento muestra la construcción de un paquete de pociones. La información de la oferta se define dentro del módulo EntitlementInfo e incluye la variable PotionCount.
ExampleOffers<public> := module:
using {EntitlementInfo}
<# --- other offer definitions above --- #>
potion_pack<public> := class(bundle_offer) :
var Name<override>:message = EntitlementInfo.PotionPack.Name
Restricción de compra
Puedes restringir las adquisiciones de productos para permitir la creación de objetos limitados para festividades, ofertas promocionales o de temporada, y crear contenido específico de la región.
GetMinPurchaseAge
Usa GetMinPurchaseAge para definir una restricción de compra personalizada para una entitlement_offer específica. Se llama automáticamente como parte de la validación de compra, por lo que solo requiere definición. Puedes definir un valor entero específico, un código de país o una familia de plataformas.
Los códigos de subdivisión no están soportados actualmente y estarán disponibles en una versión futura.
A continuación se muestran algunos ejemplos de la función GetMinPurchaseAge.
# Optional overrideable function you can use to inform Epic systems what the minimum age a player needs to be to purchase this offer
GetMinPurchaseAge<override>(CountryCode:string, SubdivisionCode:string, PlatformFamily:string)<decides><computes>:int =
# A Hypothetical example where you only want to sell swords to people who don't live in Antarctica
CountryCode <> CountryCodes.Antarctica
return 0
Cómo validar derechos del jugador
La validación de los derechos del jugador es un paso necesario para garantizar que los derechos adquiridos por los jugadores se mantengan entre sesiones. No validar correctamente los productos puede dar lugar a problemas como la duplicación de productos o la pérdida de productos, por ejemplo.
Cómo validar compras anteriores
El siguiente fragmento muestra una validación de derechos simple que se realiza cuando un jugador se une a una sesión. Primero, verifica si el jugador que ingresa está suscrito al evento OnPurchasesChanged. A continuación, se suscribirá al jugador entrante si aún no está suscrito. Por último, se recupera un registro de todos los productos adquiridos para ese jugador mediante ValidatePreviousPurchases.
Es una buena práctica realizar también verificaciones de validación de los productos de los jugadores en esta etapa, para garantizar que los datos guardados en la experiencia coincidan con lo que la API de Marketplace indica que poseen y que coincida con el inventario del jugador.
OnPlayerJoin(InPlayer:player):void =
Subscription := GetEntitlementsChangedEvent(InPlayer, Entitlements.feature_example_entitlement).Subscribe(OnPurchasesChanged)
if (set EntitlementChangeSubscription[InPlayer] = option{Subscription}):
Print("Adding entitlement Change Subscription player subscription")
# On players joining you are likely going to want to run some validation checks to make sure that any data you save
Cómo controlar las ventas
Las dos funciones principales que se utilizan para controlar las compras de productos son BuyOffer y OnPurchasesChanged. La primera función maneja la lógica para presentar una oferta al jugador y validar la compra. La segunda función maneja la lógica para una transacción o reembolso exitoso. Los siguientes fragmentos demuestran las dos funciones.
# Base Implementation of how to present players with an offer to purchase in your experience
TryBuyOffer(Player:player, Offer:entitlement_offer)<suspends>:void =
Result := BuyOffer(Player, Offer)
if (Result?):
# do nothing it should respond in the purchase subscription, see OnPurchasesChanged for details
Cómo manejar consumibles
Para consumir un derecho consumible, debes usar la función ConsumeEntitlement de la API de Verse. Una vez que el consumo sea exitoso, debes manejar la lógica para el efecto generado después del consumo. El recuento del producto que posee el jugador se reducirá según el recuento consumido en la función.
El fragmento a continuación muestra cómo se consume un producto específico por un jugador determinado.
# Base Implementation of how to flag a consumable in your experience as being consumed
TryConsumeEntitlement(Player:player, Entitlement:concrete_subtype(entitlement), NumberConsuming:int)<suspends>:void =
Result := ConsumeEntitlement(Player, Entitlement, ?Count := NumberConsuming)
if (Result?):
Print("Successfully consumed entitlement!")
No se puede consumir un derecho duradero. Si intentas hacerlo, ConsumeEntitlement fallará.
Cómo otorgar derechos
A diferencia de la compra de un derecho que requiere monedas V, también puedes otorgar derechos a jugadores con el método GrantEntitlement.
Los posibles casos de uso para otorgar un derecho incluyen objetos promocionales, muestras gratuitas de consumibles y la restauración de objetos perdidos debido a errores o fallas.
Este fragmento muestra un método para otorgar productos a tus jugadores.
# Base Implementation of how to give players a entitlement in your experience without them purchasing it
TryGrantEntitlement(Player:player, Entitlement:concrete_subtype(entitlement), NumberToGrant:int)<suspends>:void =
Result := GrantEntitlement(Player, Entitlement, ?Count := NumberToGrant)
if (Result?):
Print("Successfully granted a player your entitlement!")
Intentar otorgar más del número máximo permitido de un producto o más de uno de un producto duradero provocará que falle la concesión del producto.
Cómo mostrar tus ofertas de derechos a los jugadores
El Marketplace module proporciona una interfaz de usuario (IU) de escaparate integrada para usar en tus islas con la función ShowOffersDialog. El fragmento a continuación demuestra un método para mostrar un escaparate que expone ofertas a un jugador específico.
# Base Implementation of how to show an array of offers to the player that are available for purchase
ShowArrayOfOffers(Player:player)<suspends>:void =
ShowOffersDialog(Player, array{ExampleOffers.basic_sword{}, ExampleOffers.potion{}, ExampleOffers.potion_pack{}, ExampleOffers.potion_thanksgiving{}, ExampleOffers.potion_gib{}})Código completo
using { /Fortnite.com/Devices }
using { /Fortnite.com/Marketplace }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Verse.org/Assets }
using { /Verse.org/Simulation }