Player
Player is an object representation of the state of a player connected to the game, as well as their avatar in the world. Player also implements the Damageable interface.
Properties
Property Name | Return Type | Description | Tags |
---|---|---|---|
name | string | The Player's name. | Read-Write |
id | string | The unique id of the Player. Consistent across sessions. | Read-Only |
team | integer | The number of the team to which the Player is assigned. By default, this value is 255 in FFA mode. | Read-Write |
animationStance | string | Which set of animations to use for this Player. See Animation Stance Strings for possible values. | Read-Write |
activeEmote | string | Returns the id of the emote currently being played by the Player, or nil if no emote is playing. | Read-Only |
currentFacingMode | FacingMode | Current mode applied to player, including possible overrides. Possible values are FacingMode.FACE_AIM_WHEN_ACTIVE, FacingMode.FACE_AIM_ALWAYS, and FacingMode.FACE_MOVEMENT. See desiredFacingMode for details. | Read-Only |
desiredFacingMode | FacingMode | Which controls mode to use for this Player. May be overridden by certain movement modes like MovementMode.SWIMMING or when mounted. Possible values are FacingMode.FACE_AIM_WHEN_ACTIVE, FacingMode.FACE_AIM_ALWAYS, and FacingMode.FACE_MOVEMENT. | Read-Write, Server-Only |
defaultRotationRate | number | Determines how quickly the Player turns to match the camera's look. Set to -1 for immediate rotation. Currently only supports rotation around the Z-axis. | Read-Write, Server-Only |
currentRotationRate | number | Reports the real rotation rate that results from any active mechanics/movement overrides. | Read-Only |
hitPoints | number | Current amount of hit points. | Read-Write |
maxHitPoints | number | Maximum amount of hit points. | Read-Write |
kills | integer | The number of times the player has killed another player. | Read-Write |
deaths | integer | The number of times the player has died. | Read-Write |
stepHeight | number | Maximum height in centimeters the Player can step up. Range is 0-100. Default = 45. | Read-Write |
maxWalkSpeed | number | Maximum speed while the player is on the ground. Clients can only read. Default = 640. | Read-Write |
maxAcceleration | number | Max Acceleration (rate of change of velocity). Clients can only read. Default = 1800. Acceleration is expressed in centimeters per second squared. | Read-Write |
brakingDecelerationFalling | number | Deceleration when falling and not applying acceleration. Default = 0. | Read-Write |
brakingDecelerationWalking | number | Deceleration when walking and movement input has stopped. Default = 1000. | Read-Write |
brakingDecelerationFlying | number | Deceleration when flying and movement input has stopped. Default = 600. | Read-Write |
groundFriction | number | Friction when walking on ground. Default = 8.0 | Read-Write |
brakingFrictionFactor | number | Multiplier for friction when braking. Default = 0.6. | Read-Write |
walkableFloorAngle | number | Max walkable floor angle, in degrees. Clients can only read. Default = 44. | Read-Write |
maxJumpCount | integer | Max number of jumps, to enable multiple jumps. Set to 0 to disable jumping. | Read-Write |
shouldFlipOnMultiJump | boolean | Set to false to disable flip animation when player performs double-jump, triple-jump, etc. Defaults to true , enabling flip animation. | Read-Write |
jumpVelocity | number | Vertical speed applied to Player when they jump. Default = 900. Speed is expressed in centimeters per second. | Read-Write |
gravityScale | number | Multiplier on gravity applied. Default = 1.9. | Read-Write |
airControl | number | When falling, amount of lateral movement control available to the player. 0 is no control. 1 is full control. Default = 0.5. | Read-Write |
maxMountSpeed | number | Maximum speed while the player is mounted. Default = 1280. | Read-Write |
maxSwimSpeed | number | Maximum speed while the player is swimming. Default = 420. | Read-Write |
maxFlySpeed | number | Maximum speed while the player is flying. Default = 600. | Read-Write |
touchForceFactor | number | Force applied to physics objects when contacted with a Player. Default = 1. | Read-Write |
isCrouchEnabled | boolean | Turns crouching on/off for a Player. | Read-Write |
mass | number | Gets the mass of the Player. | Read-Only |
isAccelerating | boolean | True if the Player is accelerating, such as from input to move. | Read-Only |
isCrouching | boolean | True if the Player is crouching. | Read-Only |
isFlying | boolean | True if the Player is flying. | Read-Only |
isGrounded | boolean | True if the Player is on the ground with no upward velocity, otherwise false. | Read-Only |
isJumping | boolean | True if the Player is jumping. | Read-Only |
isMounted | boolean | True if the Player is mounted on another object. | Read-Only |
isSwimming | boolean | True if the Player is swimming in water. | Read-Only |
isWalking | boolean | True if the Player is in walking mode. | Read-Only |
isDead | boolean | True if the Player is dead, otherwise false. | Read-Only |
isSpawned | boolean | True if the player is in a spawned state, false if the player is despawned. | Read-Only |
spawnMode | SpawnMode | Specifies how a start point is selected when a player initially spawns or spawns from a despawned state. | Read-Write |
respawnMode | RespawnMode | Specifies how a start point is selected when a player respawns. | Read-Write |
respawnDelay | number | The delay in seconds from when a player dies until they respawn. | Read-Write |
respawnTimeRemaining | number | The number of seconds remaining until the player respawns. Returns 0 if the player is already spawned. | Read-Only, Server-Only |
isVisible | boolean | Defaults to true . Set to false to hide the player and any attached objects which are set to inherit visibility. Note that using this property in conjunction with the deprecated SetVisibility() function may cause unpredictable results. | Server-Only, Read-Write |
isCollidable | boolean | Defaults to true . Set to false to disable collision on the player and any attached objects set to inherit collision. | Read-Write |
isMovementEnabled | boolean | Defaults to true . Set to false to disable player movement. Unlike movementControlMode , which can disable movement input, setting isMovementEnabled to false freezes the Player in place, ignoring gravity and reactions to collision or impulses, unless the Player's transform is explicitly changed or the Player is attached to a parent CoreObject that moves. | Read-Write |
movementControlMode | MovementControlMode | Specify how players control their movement. Clients can only read. Default: MovementControlMode.LOOK_RELATIVE. MovementControlMode.NONE: Directional movement input is ignored. MovementControlMode.LOOK_RELATIVE: Forward movement follows the current player's look direction. MovementControlMode.VIEW_RELATIVE: Forward movement follows the current view's look direction. MovementControlMode.FACING_RELATIVE: Forward movement follows the current player's facing direction. MovementControlMode.FIXED_AXES: Movement axis are fixed. | Read-Write |
lookControlMode | LookControlMode | Specify how players control their look direction. Default: LookControlMode.RELATIVE. LookControlMode.NONE: Look input is ignored. LookControlMode.RELATIVE: Look input controls the current look direction. LookControlMode.LOOK_AT_CURSOR: Look input is ignored. The player's look direction is determined by drawing a line from the player to the cursor on the Cursor Plane. | Read-Write |
lookSensitivity | number | Multiplier on the Player look rotation speed relative to cursor movement. This is independent from user's preferences, both will be applied as multipliers together. Default = 1.0. | Read-Write, Client-Only |
spreadModifier | number | Modifier added to the Player's targeting spread. | Read-Write |
currentSpread | number | Gets the Player's current targeting spread. | Read-Only, Client-Only |
buoyancy | number | In water, buoyancy 1.0 is neutral (won't sink or float naturally). Less than 1 to sink, greater than 1 to float. | Read-Write |
canMount | boolean | Returns whether the Player can manually toggle on/off the mount. | Read-Write, Server-Only |
shouldDismountWhenDamaged | boolean | If true , and the Player is mounted they will dismount if they take damage. | Read-Write, Server-Only |
isVisibleToSelf | boolean | Set whether to hide the Player model on Player's own client, for sniper scope, etc. | Read-Write, Client-Only |
parentCoreObject | CoreObject | If the Player has been attached to a parent CoreObject, returns that object. Otherwise returns nil . | Read-Only |
occupiedVehicle | Vehicle | Returns the Vehicle that the player currently occupies, or nil if the player is not occupying a vehicle. | Read-Only |
isInParty | boolean | Returns whether this player is in a party. This is known regardless of if the party is public or private. | Read-Only |
isPartyLeader | boolean | Returns whether this player is the leader of a public party. | Read-Only |
ping | integer | Returns the ping value in milliseconds for this player. | Read-Only |
Functions
Function Name | Return Type | Description | Tags |
---|---|---|---|
GetWorldTransform() | Transform | The absolute Transform of this player. | None |
SetWorldTransform(Transform) | None | The absolute Transform of this player. | Server-Only |
GetWorldPosition() | Vector3 | The absolute position of this player. | None |
SetWorldPosition(Vector3) | None | The absolute position of this player. | Server-Only |
GetWorldRotation() | Rotation | The absolute rotation of this player. | None |
SetWorldRotation(Rotation) | None | The absolute rotation of this player. | Server-Only |
GetWorldScale() | Vector3 | The absolute scale of this player. | None |
SetWorldScale(Vector3) | None | The absolute scale of this player (must be uniform). | Server-Only |
AddImpulse(Vector3) | None | Adds an impulse force to the Player. | Server-Only |
GetVelocity() | Vector3 | Gets the current velocity of the Player. The velocity vector indicates the direction, with its magnitude expressed in centimeters per second. | None |
SetVelocity(Vector3) | None | Sets the Player's velocity to the given amount. The velocity vector indicates the direction, with its magnitude expressed in centimeters per second. | Server-Only |
ResetVelocity() | None | Resets the Player's velocity to zero. | Server-Only |
GetAbilities() | Array <Ability > | Array of all Abilities assigned to this Player. | None |
GetEquipment() | Array <Equipment > | Array of all Equipment assigned to this Player. | None |
ApplyDamage(Damage) | None | Damages a Player. If their hit points go below 0 they die. | Server-Only |
Die([Damage]) | None | Kills the Player. They will ragdoll and ignore further Damage. The optional Damage parameter is a way to communicate cause of death. | Server-Only |
DisableRagdoll() | None | Disables all ragdolls that have been set on the Player. | Server-Only |
SetVisibility(boolean, [boolean]) | None | This function is deprecated. Please use the .isVisible property instead. Shows or hides the Player. The second parameter is optional, defaults to true, and determines if attachments to the Player are hidden as well as the Player. | Server-Only, Deprecated |
GetVisibility() | boolean | Returns whether or not the Player is hidden. | None |
EnableRagdoll([string socketName, number weight]) | None | Enables ragdoll for the Player, starting on socketName weighted by weight (between 0.0 and 1.0). This can cause the Player capsule to detach from the mesh. All parameters are optional; socketName defaults to the root and weight defaults to 1.0. Multiple bones can have ragdoll enabled simultaneously. See Socket Names for the list of possible values. | Server-Only |
Spawn([table parameters]) | None | Resurrects a dead player or spawns a despawned player based on respawn settings in the game (default in-place). An optional table may be provided to override the following parameters:position (Vector3) : Respawn at this position. Defaults to the position of the spawn point selected based on the game's respawn settings, or the player's current position if no spawn point was selected.rotation (Rotation) : Sets the player's rotation after respawning. Defaults to the rotation of the selected spawn point, or the player's current rotation if no spawn point was selected.scale (Vector3) : Sets the player's scale after respawning. Defaults to the Player Scale Multiplier of the selected spawn point, or the player's current scale if no spawn point was selected. Player scale must be uniform. (All three components must be equal.)spawnKey (string) : Only spawn points with the given spawnKey will be considered. If omitted, only spawn points with a blank spawnKey are used. | Server-Only |
Despawn() | None | Despawns the player. While despawned, the player is invisible, has no collision, and cannot move. Use the Spawn() function to respawn the player. | Server-Only |
Respawn([table parameters]) | None | This function is deprecated. Please use Player:Spawn() instead. Resurrects a dead Player based on respawn settings in the game (default in-place). An optional table may be provided to override the following parameters:position (Vector3) : Respawn at this position. Defaults to the position of the spawn point selected based on the game's respawn settings, or the player's current position if no spawn point was selected.rotation (Rotation) : Sets the player's rotation after respawning. Defaults to the rotation of the selected spawn point, or the player's current rotation if no spawn point was selected.scale (Vector3) : Sets the player's scale after respawning. Defaults to the Player Scale Multiplier of the selected spawn point, or the player's current scale if no spawn point was selected. Player scale must be uniform. (All three components must be equal.)spawnKey (string) : Only spawn points with the given spawnKey will be considered. If omitted, only spawn points with a blank spawnKey are used. | Server-Only, Deprecated |
Respawn(Vector, Rotation) | None | This function is deprecated. Please use Player:Spawn() instead. For example: player:Spawn({position = newPosition, rotation = newRotation}) Resurrects a dead Player at a specific location and rotation. | Server-Only, Deprecated |
GetViewWorldPosition() | Vector3 | Get position of the Player's camera view. | None |
GetViewWorldRotation() | Rotation | Get rotation of the Player's camera view. | None |
GetLookWorldRotation() | Rotation | Get the rotation for the direction the Player is facing. | None |
SetLookWorldRotation(Rotation) | None | Set the rotation for the direction the Player is facing. | Client-Only |
ClearResources() | None | Removes all resources from a player. | Server-Only |
GetResources() | table <string , integer > | Returns a table containing the names and amounts of the player's resources. | None |
GetResource(string name) | integer | Returns the amount of a resource owned by a player. Returns 0 by default. | None |
SetResource(string name, integer amount) | None | Sets a specific amount of a resource on a player. | Server-Only |
AddResource(string name, integer amount) | None | Adds an amount of a resource to a player. | Server-Only |
RemoveResource(string name, integer amount) | None | Subtracts an amount of a resource from a player. Does not go below 0. | Server-Only |
TransferToGame(string) | None | Does not work in preview mode or in games played locally. Transfers player to the game specified by the passed-in game ID. Example: The game ID for the URL https://www.coregames.com/games/577d80/core-royale is 577d80/core-royale . This function will raise an error if called from a client script on a player other than the local player. | None |
TransferToGame(CoreGameInfo) | None | Does not work in preview mode or in games played locally. Transfers player to the game specified by the passed-in CoreGameInfo . This function will raise an error if called from a client script on a player other than the local player. | None |
TransferToGame(CoreGameCollectionEntry) | None | Does not work in preview mode or in games played locally. Transfers player to the game specified by the passed-in CoreGameCollectionEntry . This function will raise an error if called from a client script on a player other than the local player. | None |
TransferToScene(string sceneName, [table parameters]) | None | Does not work in preview mode or in games played locally. Transfers player to the scene specified by the passed-in scene name. The specified scene must be a scene within the same game. This function will raise an error if called from a client script on a player other than the local player. The following optional parameters are supported: spawnKey (string) : Spawns the player at a spawn point with a matching key. If an invalid key is provided, the player will spawn at the origin, (0, 0, 0). | Server-Only |
GetAttachedObjects() | Array <CoreObject > | Returns a table containing CoreObjects attached to this player. | None |
SetMounted(boolean) | None | Forces a player in or out of mounted state. | Server-Only |
GetActiveCamera() | Camera | Returns whichever camera is currently active for the Player. | Client-Only |
GetDefaultCamera() | Camera | Returns the default Camera object the Player is currently using. | Client-Only |
SetDefaultCamera(Camera, [number lerpTime = 0.0]) | None | Sets the default Camera object for the Player. | Client-Only |
GetOverrideCamera() | Camera | Returns the override Camera object the Player is currently using. | Client-Only |
SetOverrideCamera(Camera, [number lerpTime = 0.0]) | None | Sets the override Camera object for the Player. | Client-Only |
ClearOverrideCamera([number lerpTime = 0.0]) | None | Clears the override Camera object for the Player (to revert back to the default camera). | Client-Only |
ActivateFlying() | None | Activates the Player flying mode. | Server-Only |
ActivateWalking() | None | Activate the Player walking mode. | Server-Only |
IsBindingPressed(string bindingName) | boolean | This function is deprecated. Please use Input.IsActionHeld() instead, but note that it does not use the same binding names. Returns true if the player is currently pressing the named binding. Possible values of the bindings are listed on the Ability binding page. Note that when called on a client, this function will only work for the local player. | Deprecated |
HasPerk(NetReference) | boolean | Returns true if the player has one or more of the specified perk. | None |
GetPerkCount(NetReference) | integer | Returns how many of the specified perk the player owns. For non-repeatable perks, returns 1 if the player owns the perk, or 0 if the player does not. | None |
GetPerkTimeRemaining(NetReference) | number | Returns the amount of time remaining (in seconds) until a Limited Time Perk expires. Returns 0 if the player does not own the specified perk, or infinity for a permanent or repeatable perk that the player owns. | None |
AttachToCoreObject(CoreObject) | None | Attaches the Player to the given CoreObject, treating that object as a parent and disabling player movement. | Server-Only |
Detach() | None | If the Player is attached to a parent CoreObject, detaches them and re-enables player movement. | Server-Only |
GetJoinTransferData() | PlayerTransferData | Returns data indicating how a player joined the game (via browsing, portal, social invite, etc) and the game ID of their previous game if they joined directly from another game. Join data should be available during the player's entire session. | None |
GetLeaveTransferData() | PlayerTransferData | Returns data indicating how a player left the game (via browsing, portal, social invite, etc) and the game ID of their next game if they are directly joining another game. Leave data is not valid until Game.playerLeftEvent has fired for the player. | None |
SetPrivateNetworkedData(string key, value) | PrivateNetworkedDataResultCode | Sets the private networked data for this player associated with the key. Value can be any type that could be sent with a networked event. Each key is replicated independently, and this data is only sent to the owning player. | Server-Only |
GetPrivateNetworkedData(string key) | value | Returns the private networked data on this player associated with the given key or nil if no data is found. | None |
GetPrivateNetworkedDataKeys() | Array <string > | Returns an array of all keys with private data set. | None |
GetPrivateNetworkedDataSize() | integer | Returns the number of bytes used by private networked data on this player. Returns 0 if private networked data is not available. | None |
GrantRewardPoints(int rewardPoints, string activityName) | None | Adds an amount of Reward Points to a player for completing a certain activity. | Server-Only |
GetIKAnchors() | Array <IKAnchor > | Returns an array of all IKAnchor objects activated on this player. | None |
IsInPartyWith(Player) | boolean | Returns whether both players are in the same public party. | None |
GetPartyInfo() | PartyInfo | If the player is in a party, returns a PartyInfo object with data about that party. | None |
GetInventories() | Array <Inventory > | Returns a list of Inventory objects assigned to the player. If the player has no assigned inventories, this list is empty. | None |
GetInteractableTarget() | Trigger | If the player is currently focused on an interactable Trigger, returns that Trigger. Returns nil if the player is not currently focused on an interactable Trigger. | Client-Only |
GetActiveAbility() | Ability | Returns the Ability that is currently active on the player, or nil if no ability is currently active. Abilities are considered active if they are in CAST , EXECUTE , or RECOVERY phases. Abilities in COOLDOWN or READY phase are not considered active. | None |
Events
Event Name | Return Type | Description | Tags |
---|---|---|---|
damagedEvent | Event <Player player, Damage damage> | Fired when the Player takes damage. | Server-Only |
diedEvent | Event <Player player, Damage damage> | Fired when the Player dies. | Server-Only |
respawnedEvent | Event <Player player> | Fired when the Player respawns. This event has been deprecated. Please use spawnedEvent instead. | Server-Only, Deprecated |
spawnedEvent | Event <Player player, PlayerStart playerStart, string spawnKey> | Fired when the Player spawns. Indicates the start point at which they spawned and the spawn key used to select the start point. The start point may be nil if a position was specified when spawning the player. | Server-Only |
bindingPressedEvent | Event <Player player, string binding> | This event is deprecated. Please use Input.actionPressedEvent instead, but note that it does not use the same binding names. Fired when an action binding is pressed. Second parameter tells you which binding. Possible values of the bindings are listed on the Ability binding page. | Deprecated |
bindingReleasedEvent | Event <Player player, string binding> | This event is deprecated. Please use Input.actionReleasedEvent instead, but note that it does not use the same binding names. Fired when an action binding is released. Second parameter tells you which binding. | Deprecated |
resourceChangedEvent | Event <Player player, string resourceType, integer newAmount> | Fired when a resource changed, indicating the type of the resource and its new amount. | None |
perkChangedEvent | Event <Player player, NetReference perkReference> | Fired when a player's list of owned perks has changed, indicating which perk's amount has changed. Do not expect this event to fire for perks that a player already has when they join a game. Use the HasPerk(NetReference) or GetPerkCount(NetReference) function for any initial logic that needs to be handled when joining. Also, this event may not actively fire when a perk expires, but it may fire for an expired perk as a result of purchasing a different perk. | None |
movementModeChangedEvent | Event <Player player, MovementMode newMovementMode, MovementMode previousMovementMode> | Fired when a Player's movement mode changes. The first parameter is the Player being changed. The second parameter is the "new" movement mode. The third parameter is the "previous" movement mode. Possible values for MovementMode are: MovementMode.NONE, MovementMode.WALKING, MovementMode.FALLING, MovementMode.SWIMMING, MovementMode.FLYING. | None |
emoteStartedEvent | Event <Player player, string emoteId> | Fired when the Player begins playing an emote. | None |
emoteStoppedEvent | Event <Player player, string emoteId> | Fired when the Player stops playing an emote or an emote is interrupted. | None |
animationEvent | Event <Player player, string eventName, string animationName> | Some animations have events specified at important points of the animation (for example the impact point in a punch animation). This event is fired with the Player that triggered it, the name of the event at those points, and the name of the animation itself. Events generated from default stances on the player will return "animation_stance" as the animation name. | Client-Only |
privateNetworkedDataChangedEvent | Event <Player player, string key> | Fired when the player's private data changes. On the client, only the local player's private data is available. | None |
collidedEvent | Event <Player player, HitResult hitResult> | Fired when a player collides with another object. The HitResult parameter describes the collision that occurred. | None |
interactableFocusedEvent | Event <Player player, Trigger trigger> | Fired when a player has focused on an interactable Trigger and may interact with it. | Client-Only |
interactableUnfocusedEvent | Event <Player player, Trigger trigger> | Fired when a player is no longer focused on a previously focused interactable Trigger. | Client-Only |
Hooks
Hook Name | Return Type | Description | Tags |
---|---|---|---|
movementHook | Hook <Player player, table parameters> | Hook called when processing a Player's movement. The parameters table contains a Vector3 named "direction", indicating the direction the player will move. | Client-Only |
damageHook | Hook <Player player, Damage damage> | Hook called when applying damage from a call to ApplyDamage() . The incoming damage may be modified or prevented by modifying properties on the damage parameter. | Server-Only |
Additional Info
Learn more about Hooks on the Hook API page.
Examples
Example using:
actionPressedEvent
actionReleasedEvent
maxWalkSpeed
maxSwimSpeed
Normally you can leave the Core engine to handle most of the player input. You don't need to explicitly listen to jump events, to make the player jump, for example. But sometimes it's useful to listen to keypress events directly, when creating more complicated interactions.
In this example, when the player pressed the action for sprinting, it will increase the max walk speed. After the player releases the key, the speed will be reset to the baseSpeed
-- Set the action name to use for sprinting.
-- You can created custom bindings in the Bindings Manager.
local ACTION_NAME = script:GetCustomProperty("ActionName")
local baseSpeed = 640
local sprintingSpeed = 1280
function OnActionPressed(player, action)
if action == ACTION_NAME then
player.maxWalkSpeed = sprintingSpeed
end
end
function OnActionReleased(player, action)
if action == ACTION_NAME then
player.maxWalkSpeed = baseSpeed
end
end
Input.actionPressedEvent:Connect(OnActionPressed)
Input.actionReleasedEvent:Connect(OnActionReleased)
See also: Event.Connect
Example using:
animationEvent
In this example, a client script listens for animation events on the player. When one such occurs, information about the event is printed to the Event Log.
function OnAnimationEvent(player, eventName, animationName)
print(player.name .. " triggered an animation event:")
print("Event name = " .. eventName)
print("Animation name = " .. animationName)
end
Game.GetLocalPlayer().animationEvent:Connect(OnAnimationEvent)
See also: Game.GetLocalPlayer
Example using:
damagedEvent
diedEvent
spawnedEvent
ApplyDamage
Die
Spawn
There are events that fire at most major points for a player during gameplay. This example shows how to receive an event for players being damaged, dying, and spawning, as well as how to make a player automatically respawn after dying.
One important thing to note - player.damagedEvent
and player.diedEvent
only execute on the server, so if you are writing a script that runs inside of a client context, it will not receive these events.
function OnPlayerDamage(player, damage)
print("Player " .. player.name .. " just took " .. damage.amount .. " damage!")
end
function OnPlayerDied(player, damage)
print("Player " .. player.name .. " has been killed!")
-- Now, revive them after 2 seconds at a specific position and rotation:
Task.Wait(2)
local pos = Vector3.New(0, 0, 500)
local rot = Rotation.New(0, 0, 45)
player:Spawn({position = pos, rotation = rot})
end
function OnPlayerSpawn(player)
print("Player " .. player.name .. " is back!")
end
-- Set up listeners:
for _, p in pairs(Game.GetPlayers()) do
p.damagedEvent:Connect(OnPlayerDamage)
p.diedEvent:Connect(OnPlayerDied)
p.spawnedEvent:Connect(OnPlayerSpawn)
end
player:ApplyDamage(Damage.New(25))
Task.Wait(1)
player:ApplyDamage(Damage.New(50))
Task.Wait(1)
-- This will kill the player, because they only have 100 health by default.
player:ApplyDamage(Damage.New(100))
Task.Wait(2.1)
-- We can also kill the player directly, regardless of health
player:Die()
See also: Player.name | Damage.New | Task.Wait | CoreLua.print | Vector3.New | Rotation.New | Event.Connect
Example using:
emoteStartedEvent
emoteStoppedEvent
activeEmote
This example combines player emotes with chat messages. Whenever a player begins or ends an emote (Default 'B' key) the server broadcasts a chat message to all players announcing the change.
Also, whenever a player joins the game, the server counts the number of players using any dance emotes and informs the amount to the new player.
local function OnEmoteStarted(player, emoteId)
local message = player.name .. " is using " .. emoteId
Chat.BroadcastMessage(message)
end
local function OnEmoteStopped(player, emoteId)
local message = player.name .. " stopped using " .. emoteId
Chat.BroadcastMessage(message)
end
local function CountPlayersDancing()
local result = 0
for _,player in ipairs(Game.GetPlayers()) do
local emote = player.activeEmote
if emote and string.find(emote, "dance") then
result = result + 1
end
end
return result
end
local function OnPlayerJoined(player)
player.emoteStartedEvent:Connect(OnEmoteStarted)
player.emoteStoppedEvent:Connect(OnEmoteStopped)
local message = "Welcome to the server " .. player.name ..
"! There are currently " .. CountPlayersDancing() .. " players dancing."
Task.Wait(1)
-- The player may have left during the Task.Wait. Always check if valid
if Object.IsValid(player) then
Chat.BroadcastMessage(message, {players = player})
end
end
Game.playerJoinedEvent:Connect(OnPlayerJoined)
See also: Chat.BroadcastMessage | Game.GetPlayers | Task.Wait | Object.IsValid
Example using:
interactableFocusedEvent
interactableUnfocusedEvent
Similar to the other example, we show a visual indicator on top of interactable object. This time, however, we make use of the player's interactableFocusedEvent
and interactableUnfocusedEvent
events. This gives us the exact moment the interaction focus begins/ends, which is used to hide/show the VFX.
local INDICATOR_VFX = script:GetCustomProperty("IndicatorVfx"):WaitForObject()
local PLAYER = Game.GetLocalPlayer()
INDICATOR_VFX.visibility = Visibility.FORCE_OFF
function OnInteractableFocused(player, trigger)
print("Focused: " .. trigger.interactionLabel)
INDICATOR_VFX:SetWorldPosition(trigger:GetWorldPosition())
INDICATOR_VFX.visibility = Visibility.INHERIT
if INDICATOR_VFX.Play then
-- If the indicator has a Play() function, call it
INDICATOR_VFX:Play()
end
end
function OnInteractableUnfocused(player, trigger)
print("Unfocused: " .. trigger.interactionLabel)
INDICATOR_VFX.visibility = Visibility.FORCE_OFF
end
PLAYER.interactableFocusedEvent:Connect(OnInteractableFocused)
PLAYER.interactableUnfocusedEvent:Connect(OnInteractableUnfocused)
See also: Trigger.interactionLabel | Vfx.Play | Game.GetLocalPlayer | CoreObject.SetRotation
Example using:
movementModeChangedEvent
Whenever the player changes movement mode, (walking, jumping, swimming, flying), a listener is notified. We can register for that listener if we want to know whenever that happens.
This sample uses that callback to apply falling damage, whenever a player falls too far, and lands on the ground. (Which we test by checking when they transition into the jumping movement mode vs. walking.)
local jumpStartHeight = {}
local MAX_SAFE_FALL_HEIGHT = 500
local FALL_DAMAGE_MULTIPLIER = 1/10
-- Function for when the player changes mode.
function OnMovementModeChanged(player, mode)
print("change!")
if mode == MovementMode.FALLING then
print("jump")
jumpStartHeight[player] = player:GetWorldPosition().z
elseif mode == MovementMode.WALKING then
print("walk")
if jumpStartHeight[player] ~= nil then
local fallDistance = jumpStartHeight[player] - player:GetWorldPosition().z
print("Fell " ..fallDistance)
if fallDistance > MAX_SAFE_FALL_HEIGHT then
local damageFromFalling = (fallDistance - MAX_SAFE_FALL_HEIGHT) * FALL_DAMAGE_MULTIPLIER
print("Took " .. damageFromFalling .. " as fall damage!")
player:ApplyDamage(Damage.New(damageFromFalling))
end
end
jumpStartHeight[player] = nil
else
-- They started swimming or flying or something.
jumpStartHeight[player] = nil
end
end
-- Outfit all players with the movementModeChanged listener
function OnPlayerJoined(player)
player.movementModeChangedEvent:Connect(OnMovementModeChanged)
end
Game.playerJoinedEvent:Connect(OnPlayerJoined)
-- Now we fling the player into the air for testing.
-- When they land they should take ~40 damage.
print("in the air")
player:SetWorldPosition(Vector3.New(0, 0, 1000))
print("done waiting")
See also: Player.GetWorldPosition | Damage.New | Game.playerJoinedEvent | Vector3.z | Event.Connect | CoreLua.print
Example using:
resourceChangedEvent
ClearResources
GetResource
GetResources
SetResource
AddResource
RemoveResource
While scripting, you can assign "resources" to players. These are just integer values, accessed via a string key, that are tied to a player. They are useful for storing values about game-specific resources a player might have, such as coins collected, mana remaining, levels completed, puppies pet, etc.
You can manipulate these values via several methods on the player class, as well as registering for an event when they are changed.
This sample registers a listener to ensure that values are in the 0-100 range, and demonstrates several examples of how to change the values.
local resource1 = "CoinsCollected"
local resource2 = "PuppiesSeen"
-- Make sure that resources never go outside the [0, 100] range:
function OnResourceChanged(player, resourceId, newValue)
if newValue > 100 then player:SetResource(resourceId, 100) end
if newValue < 0 then player:SetResource(resourceId, 0) end
end
player.resourceChangedEvent:Connect(OnResourceChanged)
player:SetResource(resource1, 5)
-- Player now has 5 "CoinsCollected"
player:AddResource(resource1, 15)
-- Player now has 20 "CoinsCollected".
player:AddResource(resource1, 500)
-- This should give us 520 "CoinsCollected", but our event listener limits it to 100.
print("Coins collected: " .. player:GetResource(resource1))
player:SetResource(resource2, 2)
-- Player now has 2 "PuppiesSeen", as well as still having 100 "CoinsCollected"
player:RemoveResource(resource1, 10)
-- Player now has 90 "CoinsCollected"
-- We can also get all the resources in one go as a table:
local resourceTable = player:GetResources()
for k, v in pairs(resourceTable) do
print("Resource ["..k.."]: " .. v)
end
player:ClearResources()
-- All resources have been removed from the player
print("Coins collected: " .. player:GetResource(resource1))
print("Puppies seen: " .. player:GetResource(resource2))
See also: CoreLua.print | Event.Connect
Example using:
GetAttachedObjects
Whether you're building sticky-mines, or costumes, sometimes it is useful to be able to attach a CoreObject
directly to a spot on a player.
When attaching an object to a player you need to specify the "socket" you want to attach it to. The list of legal sockets can be found on its own page in the documentation.
local CUBE = script.parent
CUBE.collision = Collision.FORCE_OFF
local function OnPlayerJoined(player)
-- Attach the cube to the player's head
CUBE:AttachToPlayer(player, "head")
-- We can then ask the player for a list of attached CoreObjects:
print("Attached objects: ")
for _, v in ipairs(player:GetAttachedObjects()) do
print(tostring(v.name))
end
end
Game.playerJoinedEvent:Connect(OnPlayerJoined)
See also: CoreObject.AttachToPlayer
Example using:
damageHook
In this example, players will get armor when they join the game that adds an extra layer of protection to damage sources before it effects the player's health. By using the damageHook for the player, the amount of damage in the Damage object that is passed in can be modified before it is applied to the player.
In this case, the player has an armor resource that the damage is applied to first if the player's armor is greater than 0. Any damage the player takes will notify the source player to show the damage they have done. If the damage is to the armor, then the numbers will be green, otherwise it will be red to indicate damage is to the health.
There are 2 scripts for this example. 1 Server, and 1 Client.
-- Server script
local function ReduceArmor(player, damage)
local currentArmor = player:GetResource("armor")
local isArmor = false
local damageAmount = damage.amount
-- check the current armor amount for the player who
-- received the damaged.
if currentArmor > 0 then
-- Remove the damage.amount from the armor.
player:RemoveResource("armor", damage.amount)
-- Set the damage.amount to 0 so no damage to
-- the health is took.
damage.amount = 0
isArmor = true
print("Armor for " .. player.name .. " is " .. tostring(player:GetResource("armor")))
end
-- Broadcast to the player who is the source of the damage
-- so the damage numbers will appear on their screen.
Events.BroadcastToPlayer(damage.sourcePlayer, "ShowDamage", damageAmount, player:GetWorldPosition(), isArmor)
end
-- When the player joins, set their armor resource to 100 and
-- connect up the damageHook event.
local function OnPlayerJoined(player)
player:SetResource("armor", 100)
player.damageHook:Connect(ReduceArmor)
end
Game.playerJoinedEvent:Connect(OnPlayerJoined)
-- Client script below
-- Shows the damage numbers to the player. The color
-- of the number depends on if the damage was done to
-- the armor or the health.
local function ShowDamage(damageAmount, position, isArmor)
UI.ShowFlyUpText(tostring(damageAmount), position, {
isBig = true,
color = (isArmor and Color.GREEN) or Color.RED
})
end
Events.Connect("ShowDamage", ShowDamage)
See also: Hook.Connect | Game.playerJoinedEvent | Damage.amount | player.GetResource | Events.BroadcastToPlayer | UI.ShowFlyUpText
Example using:
movementHook
IsActionHeld
GetViewWorldRotation
In this example, a client script prevents the player from moving normally. It does so connecting to the movementHook
and setting the direction
to zero. The player will instead move forward only when the Shoot action is pressed (Left mouse button for default bindings).
local PLAYER = Game.GetLocalPlayer()
function OnPlayerMovement(player, params)
if Input.IsActionHeld(player, "Shoot") then
local direction = Quaternion.New(PLAYER:GetViewWorldRotation()):GetForwardVector()
direction.z = 0
params.direction = direction:GetNormalized()
else
params.direction = Vector3.ZERO
end
end
PLAYER.movementHook:Connect(OnPlayerMovement)
See also: Hook.Connect | Game.GetLocalPlayer | Quaternion.GetForwardVector | Vector3.GetNormalized
Example using:
ActivateFlying
ActivateWalking
You can set different movement modes for the player. ActivateWalking()
will give the player normal walking physics. (They fall down, slide down slopes, etc.) ActivateFlying
, on the other hand, makes them ignore gravity and fly around freely.
This example allows the player to toggle flying mode by pressing the binding setup.
The binding for flying will need to be networked so the input can be detected on the server.
-- Set the action name to use to toggle flying. A custom binding may needed to need to be
-- added in the Binding Manager window.
local ACTION_NAME = script:GetCustomProperty("ActionName")
function OnActionPressed(player, action)
if action == ACTION_NAME then
if player.isFlying then
player:ActivateWalking()
else
player:ActivateFlying()
end
end
end
Input.actionPressedEvent:Connect(OnActionPressed)
See also: Input.actionPressedEvent | Event.Connect
Example using:
AddImpulse
GetVelocity
SetVelocity
ResetVelocity
mass
If you want to fling a player using the physics system, it is possible to directly affect their velocity. You can either add a physics impulse to their current velocity, or just set the player's velocity directly. You can also zero out their velocity using Player.ResetVelocity()
.
Note that when using impulses to apply force to a player, we need to scale it by the player's mass
property.
-- Fling the player towards the heavens:
player:SetVelocity(Vector3.UP * 1000)
-- We can read the player's velocity in order to double it! Note that since we're adding
-- a physics impulse directly, we need to scale it by the mass of the player.
player:AddImpulse(player:GetVelocity() * player.mass)
-- Fling the player some more.
player:AddImpulse(Vector3.UP * player.mass * 1000)
Task.Wait(0.5)
-- Reset their velocity to zero.
player:ResetVelocity()
See also: Player.SetWorldPosition | Task.Wait | Vector3.ZERO
Example using:
AttachToCoreObject
Detach
parentCoreObject
In this example, the script is placed as a child of a simple networked cube. The cube is set to move slowly upwards. When a player presses the Shoot binding, they are attached to the cube and follow its movement. Pressing the binding again detaches them from the cube and they fall off.
local CUBE = script.parent
CUBE:MoveContinuous(Vector3.UP * 20)
function OnActionPressed(player, action)
if action == "Shoot" then
if player.parentCoreObject then
-- Detach from cube
player:Detach()
else
-- Attach to cube
player:AttachToCoreObject(CUBE)
end
end
end
Input.actionPressedEvent:Connect(OnActionPressed)
See also: CoreObject.parent | Vector3.UP | Input.actionPressedEvent
Example using:
DisableRagdoll
EnableRagdoll
animationStance
You can enable ragdoll on a player, and make their joints all floppy. This can be useful for various effects, such as indicating when a player has died, or otherwise needs to be limp.
Alternately, you can set the player's animation stance to one of a number of premade animation stances, and the player will move while maintaining that stance. Check out the "Player Animations" page for a complete list.
-- Set the player's limbs to flop around, but leave the main spine
-- intact, so we drag them around like a marionette:
player:EnableRagdoll("lower_spine", .4)
player:EnableRagdoll("right_shoulder", .2)
player:EnableRagdoll("left_shoulder", .6)
player:EnableRagdoll("right_hip", .6)
player:EnableRagdoll("left_hip", .6)
Task.Wait(3)
-- Back to normal!
player:DisableRagdoll()
-- Okay now let's give them a weird stance:
player.animationStance = "unarmed_sit_car_low"
Task.Wait(3)
-- Put it back to normal
player.animationStance = "unarmed_stance"
See also: Game.playerJoinedEvent | Task.Wait
Example using:
GetAbilities
GetEquipment
Lots of things can end up attached to a player. CoreObject
objects, stuck to sockets. Ability
and Equipment
objects granting them new powers. Etc.
It's possible to query the Player
object to find out exactly what is attached to a given player.
local propBasicAssaultRifle = script:GetCustomProperty("BasicAssaultRifle")
rifle = World.SpawnAsset(propBasicAssaultRifle)
rifle:Equip(player)
for _, obj in ipairs(player:GetAbilities()) do
print("Ability: " .. obj.name)
end
for k,v in pairs(player:GetAbilities()) do
print(v.name)
end
for _, obj in ipairs(player:GetEquipment()) do
print("Equipment: " .. obj.name)
end
for _, obj in ipairs(player:GetAttachedObjects()) do
print("Attached object: " .. obj.name)
end
See also: Player.GetAttachedObjects | CoreObject.GetCustomProperty | World.SpawnAsset | Equipment.Equip | Ability.name | CoreLua.print
Example using:
GetActiveAbility
In this example we have an ability that automatically activates as soon as it can. We could achieve that by calling :Activate() each frame, without verifying anything, however that would cause this ability to interrupt other abilities. By using Player.GetActiveAbility()
we can guarantee this ability only activates when there are no others playing.
local ABILITY = script:GetCustomProperty("Ability"):WaitForObject()
function Tick()
local activeAbility = ABILITY.owner:GetActiveAbility()
if activeAbility == nil and ABILITY:GetCurrentPhase() == AbilityPhase.READY then
ABILITY:Activate()
end
end
See also: Ability.Activate | CoreObject.GetCustomProperty | CoreObjectReference.WaitForObject
Example using:
GetActiveCamera
GetDefaultCamera
SetDefaultCamera
GetOverrideCamera
SetOverrideCamera
ClearOverrideCamera
It's possible to change a player's view by modifying or swapping their camera. This is client side only, and won't have any effect if done from a server context.
local propTestCamera = script:GetCustomProperty("TestCamera")
-- We can set a default camera for a player, and then their viewport
-- is seen through that camera.
local player = Game.GetLocalPlayer()
local defaultCamera = World.SpawnAsset(propTestCamera,
{ position = Vector3.New(0, -1000, 1000) })
defaultCamera:LookAtContinuous(player)
-- Wait 1 frame to make sure the default camera is initialized for the client.
Task.Wait()
print(player:GetDefaultCamera():GetWorldPosition()) -- 0, -1000, 1000
player:SetDefaultCamera(defaultCamera, 1)
Task.Wait(2)
-- Players also have an "override camera", which has higher priority
-- than the default camera. It's usually used for moving the camera
-- somewhere briefly, before reverting to the default camera.
local overrideCamera = World.SpawnAsset(propTestCamera,
{ position = Vector3.New(0, 1000, 1000) })
overrideCamera:LookAtContinuous(player)
player:SetOverrideCamera(overrideCamera, 1)
print(player:GetOverrideCamera():GetWorldPosition()) -- 0, 1000, 1000
Task.Wait(2)
player:ClearOverrideCamera()
Task.Wait()
See also: CoreObject.GetCustomProperty | Game.GetLocalPlayer | World.SpawnAsset | Vector3.New | Task.Wait | CoreLua.print
Example using:
GetInteractableTarget
In this example, a visual indicator appears on top of any object that has an interactable trigger. For example, a weapon that can be picked up. The indicator spins around its Z axis. This is a client script.
local INDICATOR_VFX = script:GetCustomProperty("IndicatorVfx"):WaitForObject()
local PLAYER = Game.GetLocalPlayer()
function Tick()
local trigger = PLAYER:GetInteractableTarget()
if trigger then
INDICATOR_VFX:SetWorldPosition(trigger:GetWorldPosition())
INDICATOR_VFX.visibility = Visibility.INHERIT
local rot = INDICATOR_VFX:GetRotation()
rot.z = time() * 360
INDICATOR_VFX:SetRotation(rot)
else
INDICATOR_VFX.visibility = Visibility.FORCE_OFF
end
end
See also: Game.GetLocalPlayer | CoreObject.SetRotation
Example using:
GetInventories
In this example, we periodically check how many inventories each player has and print the result to the Event Log.
function Tick()
for _,player in ipairs(Game.GetPlayers()) do
local inventories = player:GetInventories()
local totalItems = 0
for _,inventory in ipairs(inventories) do
totalItems = totalItems + ComputeItemCount(inventory)
end
print(player.name.." has "..totalItems.." items across "..#inventories .." inventories.")
end
Task.Wait(3)
end
function ComputeItemCount(inventory)
if inventory.occupiedSlotCount == 0 then return 0 end
local total = 0
for i = 1, inventory.occupiedSlotCount do
local item = inventory:GetItem(i)
total = total + item.count
end
return total
end
See also: Inventory.occupiedSlotCount | InventoryItem.count | Player.name | Game.GetPlayers
Example using:
GetJoinTransferData
In this example, we imagine a project with two separate scenes and players can transfer between them. When a player transfers from the first scene to the second one, we use the optional spawnKey parameter to send team informmaton that can be read from the transfer data when the player has joined the game. Based on the spawn key information the correct weapon template will be spawned for the player.
-- Server Script (Scene 1)
player:TransferToScene("YourSceneName", {
spawnKey = "Team2" -- Set spawn key to Team2 for this example
})
-- Server Script (Scene 2)
local TEAM_1_WEAPON = script:GetCustomProperty("Team1Weapon")
local TEAM_2_WEAPON = script:GetCustomProperty("Team2Weapon")
local function OnPlayerJoined(player)
local transferData = player:GetJoinTransferData()
local weaponTemplate = TEAM_1_WEAPON
if transferData.spawnKey == "Team2" then
weaponTemplate = TEAM_2_WEAPON
end
local weapon = World.SpawnAsset(weaponTemplate)
weapon:Equip(player)
end
Game.playerJoinedEvent:Connect(OnPlayerJoined)
See also: CoreObject.GetCustomProperty | World.SpawnAsset | Event.Connect | Player.TransferToScene | Game.playerJoinedEvent | Weapon.Equip | PlayerTransferData.spawnKey
Example using:
GetJoinTransferData
GetLeaveTransferData
In this example, transfer data is printed to the server log each time a player joins or leaves the game. While this works in preview mode, there will never be a gameId
in that case, and the reason
for the transfer will always be BROWSE
. Therefore, this example works best when the game is published.
To see the server logs of a published game, select the Game Settings object in the hierarchy and enable "Play Mode Profiling". When playing the published game press F4 to see the profiler and access the logs. You may need a second player joining/leaving to observe the logs while testing the various different reasons.
-- Converts the enum reason into a string, to make the log more readable
function ToStringTransferReason(reason)
-- Default reason, or player has opted out from sharing this info
if reason == PlayerTransferReason.UNKNOWN then return "UNKNOWN" end
-- If they leave to edit their character/collection
if reason == PlayerTransferReason.CHARACTER then return "CHARACTER" end
-- If they leave by pressing the "Create" tab
if reason == PlayerTransferReason.CREATE then return "CREATE" end
-- If they leave by pressing the "Shop" tab
if reason == PlayerTransferReason.SHOP then return "SHOP" end
-- If they join/leave by browsing games or from a URL
if reason == PlayerTransferReason.BROWSE then return "BROWSE" end
-- If they join/leave by joining a game their friend is playing
if reason == PlayerTransferReason.SOCIAL then return "SOCIAL" end
-- If they join/leave when a game uses player:TransferToGame()
if reason == PlayerTransferReason.PORTAL then return "PORTAL" end
-- If they leave from being inactive for longer than the AFK limit
if reason == PlayerTransferReason.AFK then return "AFK" end
-- If they close Core or log out
if reason == PlayerTransferReason.EXIT then return "EXIT" end
-- Fallback, future-proof
return "???" .. tostring(reason)
end
-- Given a game ID, retrieves the game's name and author
function FetchGameNameAndAuthor(gameId)
if gameId then
-- This yields the thread while the data is retrieved
local gameInfo = CorePlatform.GetGameInfo(gameId)
if gameInfo then
return gameInfo.name .. ", by " .. gameInfo.ownerName
end
end
return ""
end
function OnPlayerJoined(player)
-- CorePlatform.GetGameInfo creates a delay while the data is being retrieved, during
-- which time the player object may no longer be valid, so we cache the name first.
local playerName = player.name
local transferData = player:GetJoinTransferData()
local gameId = transferData.gameId
local reason = ToStringTransferReason(transferData.reason)
local gameBio = FetchGameNameAndAuthor(gameId)
print(
"\n Player joined = " .. playerName ..
"\n from game = " .. tostring(gameId) .. ":" .. gameBio ..
"\n reason = " .. reason)
end
function OnPlayerLeft(player)
-- CorePlatform.GetGameInfo creates a delay while the data is being retrieved, during
-- which time the player object may no longer be valid, so we cache the name first.
local playerName = player.name
local transferData = player:GetLeaveTransferData()
local gameId = transferData.gameId
local reason = ToStringTransferReason(transferData.reason)
local gameBio = FetchGameNameAndAuthor(gameId)
print(
"\n Player left = " .. playerName ..
"\n to game = " .. tostring(gameId) .. ":" .. gameBio ..
"\n reason = " .. reason)
end
Game.playerJoinedEvent:Connect(OnPlayerJoined)
Game.playerLeftEvent:Connect(OnPlayerLeft)
See also: PlayerTransferData.gameId | PlayerTransferReason | Player.TransferToGame | Game.TransferAllPlayersToGame | CoreGameInfo.name
Example using:
GetPartyInfo
isInParty
isPartyLeader
In this example, a trigger is setup as a teleporter that sends players to a random game. If the player entering the trigger is the leader of a party, then the entire party is transferred to the same game.
local TRIGGER = script:GetCustomProperty("Trigger"):WaitForObject()
function OnBeginOverlap(_, player)
if not player:IsA("Player") then return end
local destinationGame = GetRandomFeaturedGame()
if player.isInParty and player.isPartyLeader then
-- Transfer the whole party
local partyOfPlayers = {}
local partyInfo = player:GetPartyInfo()
for _,playerId in ipairs(partyInfo:GetMemberIds()) do
local p = Game.FindPlayer(playerId)
if p then
table.insert(partyOfPlayers, p)
end
end
Game.TransferPlayersToGame(destinationGame, partyOfPlayers)
else
-- Transfer only the player who entered the trigger
player:TransferToGame(destinationGame)
end
end
function GetRandomFeaturedGame()
local collection = CorePlatform.GetGameCollection("featured")
local rndIndex = math.random(1, #collection)
local entry = collection[rndIndex]
return entry
end
TRIGGER.beginOverlapEvent:Connect(OnBeginOverlap)
See also: PartyInfo.GetMemberIds | Game.TransferPlayersToGame | CorePlatform.GetGameCollection | Trigger.beginOverlapEvent | CoreObjectReference.WaitForObject | Other.IsA
Example using:
GetViewWorldPosition
GetViewWorldRotation
GetLookWorldRotation
SetLookWorldRotation
The direction and rotation that the player is looking can be both read and set through Lua scripts. Note that this will only work on scripts executing inside of a client context.
local player = Game.GetLocalPlayer()
-- Get the position and direction of the player's camera:
print("The player's view camera is at " .. tostring(player:GetViewWorldPosition()))
print("Its rotation is " .. tostring(player:GetViewWorldRotation()))
-- You can also directly set which direction they are looking.
-- This code snippet will force them to look 90 degrees to the right.
player:SetLookWorldRotation(player:GetLookWorldRotation() + Rotation.New(0, 0, 90))
See also: Game.GetLocalPlayer | CoreLua.print | Rotation.New
Example using:
GetWorldTransform
SetWorldTransform
GetWorldPosition
SetWorldPosition
GetWorldRotation
SetWorldRotation
It is possible to read and change the position of the player. You can either change the position or rotation directly, or change the entire transformation all at once.
-- Store off the transform of the player:
player:SetWorldTransform(Transform.IDENTITY)
local originalTransform = player:GetWorldTransform()
-- Move the player 1000 units in the air:
player:SetWorldPosition(player:GetWorldPosition() + Vector3.UP * 1000)
-- Look 90 degrees to the right
player:SetWorldRotation(player:GetWorldRotation() + Rotation.New(0, 0, 90))
-- Return the player to their original position and rotation:
player:SetWorldTransform(originalTransform)
See also: Rotation.New | Vector3.UP
Example using:
GrantRewardPoints
In this example, a player receives a daily reward of 100 points (RP) when they join the game. The reward name can be anything, so we use "Daily" here, to identify it. Lua's os.date() system is used in conjunction with Storage, to figure out if this is the first time the player has joined today.
local REWARD_AMOUNT = 100
local REWARD_NAME = "Daily"
function IsFirstJoinToday(player)
local today = os.date("*t")
local day = today.day
local month = today.month
print("Day = " .. day)
print("Month = " .. month)
local data = Storage.GetPlayerData(player)
if day ~= data.lastJoinDay
or month ~= data.lastJoinMonth then
data.lastJoinDay = day
data.lastJoinMonth = month
Storage.SetPlayerData(player, data)
return true
end
return false
end
function OnPlayerJoined(player)
if IsFirstJoinToday(player) then
player:GrantRewardPoints(REWARD_AMOUNT, REWARD_NAME)
print("Awarded")
else
print("Not awarded")
end
end
Game.playerJoinedEvent:Connect(OnPlayerJoined)
See also: Storage.GetPlayerData | Game.playerJoinedEvent
Example using:
HasPerk
In this example, limited time perks that players have purchased could still have active benefits (that is double xp) when the perk has expired while the player is still on the server. This could allow players to get extended perk benefits until they leave, or the server is closed.
To solve this issue, a task can be spawned that checks all players on the server periodically if they have the limited time perk. For example, you might be using SetResource to flag players having a Gold VIP Pass. If the limited time perk has expired, then the flag can be set to 0, which would end the benefits for the player until they repurchase the perk.
-- Server script
-- The limited time perk (net reference) to check.
local LIMITED_TIME_PERK = script:GetCustomProperty("perk")
-- Spawn the task when the server starts
local perkCheckTask = Task.Spawn(function()
-- Loop through all the players on the server.
for index, player in ipairs(Game.GetPlayers()) do
-- If the player does not have the perk, reset their vip pass.
if not player:HasPerk(LIMITED_TIME_PERK) then
-- Your code would go here to handle resetting perk benefits.
player:SetResource("goldvippass", 0)
end
end
end)
perkCheckTask.repeatCount = -1
-- The interval doesn't need to be fast
perkCheckTask.repeatInterval = (60 * 5)
See also: CoreObject.GetCustomProperty | Task.Spawn | Game.GetPlayers | Player.SetResource
Example using:
SetPrivateNetworkedData
GetPrivateNetworkedData
GetPrivateNetworkedDataKeys
privateNetworkedDataChangedEvent
In this example, a player's inventory data is transferred from server to client. The server first accesses permanent storage to see if the player has previously played the game. If not, their inventory is initialized with starting items. Then, the server uses the private networked data API to transfer this information to the client script. Client scripts cannot access storage directly, so they depend on this transfer in order to display to the user interface what's contained in the inventory. Furthermore, because the transfer is private, other players don't incur networking costs. Plus, knowing other players' inventories is not important for the gameplay in this case.
-- BEGIN REGION: Server script
function InitInventory(player, data)
if not data.inventory then
print(player.name .. " is a new player. Give them starting inventory.")
data.inventory = {
["sword"] = 1,
["shield"] = 1,
["rupies"] = 15,
}
else
print(player.name .. " already has inventory from a previous play session.")
end
player.serverUserData.inventory = data.inventory
end
function OnPlayerJoined(player)
local data = Storage.GetPlayerData(player)
InitInventory(player, data)
-- Transfer storage to the client
for key,value in pairs(data) do
local resultCode = player:SetPrivateNetworkedData(key, value)
if resultCode == PrivateNetworkedDataResultCode.FAILURE then
warn("Setting private data " .. key .. " for player " ..
player.name .. " failed.")
elseif resultCode == PrivateNetworkedDataResultCode.EXCEEDED_SIZE_LIMIT then
warn("Setting private data " .. key .. " for player " ..
player.name .. " exceeded the limit.")
end
end
end
function OnPlayerLeft(player)
local data = Storage.GetPlayerData(player)
data.inventory = player.serverUserData.inventory
Storage.SetPlayerData(player, data)
end
Game.playerJoinedEvent:Connect(OnPlayerJoined)
Game.playerLeftEvent:Connect(OnPlayerLeft)
-- END REGION: Server script
-- BEGIN REGION: Client script
local PLAYER = Game.GetLocalPlayer()
function UpdateFromNetworkedData(key)
local data = PLAYER:GetPrivateNetworkedData(key)
-- This would depend on your type of data and game system
-- For example: An inventory of items
if key == "inventory" then
for itemId,count in pairs(data) do
print(PLAYER.name .. " has " .. count .. " copies of " .. itemId)
end
PLAYER.clientUserData.inventory = data
end
end
-- React to changes in the data, or receive the initial replication in case
-- the client script loaded before the networked data had replicated
function OnPrivateNetworkedDataChanged(player, key)
UpdateFromNetworkedData(key)
end
PLAYER.privateNetworkedDataChangedEvent:Connect(OnPrivateNetworkedDataChanged)
-- In case the client script loaded after the networked data has replicated
for i,key in ipairs(PLAYER:GetPrivateNetworkedDataKeys()) do
UpdateFromNetworkedData(key)
end
-- END REGION: Client script
See also: Storage.GetPlayerData | Game.playerJoinedEvent | Player.clientUserData
Example using:
SetWorldScale
GetWorldScale
You can scale the size of the player. This sample causes all players to slowly grow until they get too big, and then reset.
Task.Spawn(function()
while true do
for _, player in pairs(Game.GetPlayers()) do
local currentScale = player:GetWorldScale()
local newScale = currentScale * 1.01
if newScale.x > 5 then newScale = Vector3.New(1.0) end
player:SetWorldScale(newScale)
end
Task.Wait()
end
end)
See also: Task.Spawn | Game.GetPlayers | Vector3.New
Example using:
TransferToGame
Sends a player to another game. The game ID can be obtained from the Core website, for example to transfer a player to Core Royale, we navigate to that game's page at https://www.coregames.com/games/577d80/core-royale
and copy the last two parts of the URL 577d80/core-royale
as the game ID.
local trigger = script.parent
function OnBeginOverlap(theTrigger, player)
-- The object's type must be checked because CoreObjects also overlap triggers
if player and player:IsA("Player") then
player:TransferToGame("e39f3e/core-world")
end
end
trigger.beginOverlapEvent:Connect(OnBeginOverlap)
See also: CoreObject.parent | Object.IsA | Trigger.beginOverlapEvent | Event.Connect
Example using:
TransferToScene
This example shows how to transfer a player to a scene called Tutorial when the player overlaps the trigger. By setting the optional spawn parameter, the player will spawn at a specific location when loading into the scene.
It's important that the scene name used, matches exactly the name for the scene you want to transfer the player too.
local PORTAL_TRIGGER = script:GetCustomProperty("PortalTrigger"):WaitForObject()
-- Name of the scene to transfer the player too.
local sceneName = "Tutorial"
-- Function will be called when the player overlaps the trigger.
local function OnTriggerOverlap(trigger, obj)
-- Check the object overlapping the trigger is a Player.
if obj:IsA("Player") then
-- Transfer the player to the scene, and set the spawn point.
obj:TransferToScene(sceneName, { spawnKey = "TutorialStart" })
end
end
PORTAL_TRIGGER.beginOverlapEvent:Connect(OnTriggerOverlap)
See also: Game.TransferAllPlayersToScene | Other.IsA | Trigger.beginOverlapEvent
Example using:
isVisible
You can make a player visible or invisible by setting the isVisible
property, as well as check on their current visibility status. This sample gives the player the ability to turn invisible by pressing a key.
-- Set the action name to use for going invisible. A custom binding may need to need to be
-- added in the Binding Manager window.
local ACTION_NAME = script:GetCustomProperty("ActionName")
function OnActionPressed(player, action)
if action == ACTION_NAME then
player.isVisible = false
end
end
function OnActionReleased(player, action)
if action == ACTION_NAME then
player.isVisible = true
end
end
Input.actionPressedEvent:Connect(OnActionPressed)
Input.actionReleasedEvent:Connect(OnActionReleased)
See also: Input.actionPressedEvent | Event.Connect | CoreObject.GetCustomProperty
Example using:
collidedEvent
Each time a player bumps into another object they fire a collidedEvent
. This example works on both server and client scripts. It shows how to connect to the event and prints the names of the objects into the Event Log.
local function OnPlayerCollided(player, hitResult)
print(player.name .. " collided with " .. hitResult.other.name)
end
local function OnPlayerJoined(player)
player.collidedEvent:Connect(OnPlayerCollided)
end
Game.playerJoinedEvent:Connect(OnPlayerJoined)
See also: HitResult.other | Game.playerJoinedEvent | Event.Connect
Example using:
currentFacingMode
desiredFacingMode
There are several modes the game can use to decide which direction the player's avatar is facing, based on the camera look direction.
-- This will make the player turn to face whatever direction they are moving.
player.desiredFacingMode = FacingMode.FACE_MOVEMENT
-- This will make the player turn to face whatever direction they are aiming.
player.desiredFacingMode = FacingMode.FACE_AIM_ALWAYS
-- This will make the player turn to face whatever direction they
-- are moving or shooting.
player.desiredFacingMode = FacingMode.FACE_AIM_WHEN_ACTIVE
--[[#description
Note that this is the _desired_ facing mode. The actual facing mode is not
always guaranteed to be this, as certain player states can override this.
(When the player is swimming, for example.
You can check the actual current facing mode using the `currentFacingMode`
property.]]
if (player.currentFacingMode == FacingMode.FACE_AIM_ALWAYS) then
print("Player's facing mode is FacingMode.FACE_AIM_ALWAYS!")
end
See also: Game.playerJoinedEvent | CoreLua.print
Example using:
hitPoints
maxHitPoints
kills
deaths
You can get various vital statistics off of the player object, such as hit points, max hit points, kills, and deaths. This sample shows how to read that data and populate a leaderboard. (The leaderboard is printed out to the event log in this sample, but it would be trivial to feed it into some kind of onscreen UI.)
-- Here's a function to print out various useful information about the player's current status
-- and score to the event log.
function PrintPlayerStats(player)
print("[" .. player.name .. "]: Health: (".. player.hitPoints .. "/" .. player.maxHitPoints
.. ") Kills: " .. player.kills
.. " Deaths: " .. player.deaths)
end
local playerList = Game.GetPlayers()
table.sort(playerList, function(a, b) return a.kills > b.kills end)
for i, p in ipairs(playerList) do
PrintPlayerStats(p)
end
See also: Player.name | Game.GetPlayers | CoreLua.print
Example using:
isAccelerating
isCrouching
isFlying
isGrounded
isJumping
isMounted
isSwimming
isWalking
isDead
You can get a lot of useful information about the player's current movement, via a series of read-only boolean properties on the Player
object.
-- Here's a function to print out various useful information about the player's current status
-- to the event log.
function CheckPlayerStatus(player)
print("The player is ...")
-- isAccelerating is true if the player is accelerating due to input.
-- IMPORTANT NOTE: isAccelerating only cares about input. It won't turn true if they
-- are falling, or otherwise accelerating from something other than player input.
if player.isAccelerating then print(" - moving!") end
if player.isCrouching then print(" - crouched!") end
if player.isFlying then print(" - flying!") end
if player.isGrounded then print(" - touching the ground!") end
if player.isJumping then print(" - in mid air!") end
if player.isMounted then print(" - riding their mount!") end
if player.isSwimming then print(" - underwater!") end
if player.isWalking then print(" - moving via walking!") end
if player.isDead then print(" - deceased!") end
end
-- For the next 10 seconds, report on a player's status flags!
for i = 0, 10 do
players = Game.GetPlayers()
if #players > 0 then
CheckPlayerStatus(players[1])
end
Task.Wait(1)
end
See also: Game.GetPlayers | CoreLua.print | Task.Wait
Example using:
isCollidable
In this example, a trigger makes the player fall through the ground when they step on it. After a short wait period, the player's collision is resumed, so they may interact with whatever else is below the ground.
local TRIGGER = script:GetCustomProperty("Trigger"):WaitForObject()
local function OnBeginOverlap(_,player)
if player:IsA("Player") then
player.isCollidable = false
Task.Wait(1.5)
player.isCollidable = true
end
end
TRIGGER.beginOverlapEvent:Connect(OnBeginOverlap)
See also: Trigger.beginOverlapEvent | CoreObject.GetCustomProperty | Task.Wait
Example using:
isInParty
isPartyLeader
IsInPartyWith
This example will teleport any players to their team leader if the leader is connected.
function OnPlayerJoined(player)
-- If the player is not in a party, stop here
if not player.isInParty then
return
end
local players = Game.GetPlayers()
-- Go through each player
for _, p in ipairs(players) do
-- If the other player is the leader
if p ~= player and p:IsInPartyWith(player) and p.isPartyLeader then
-- Teleport the player to the leader
player:SetWorldPosition(p:GetWorldPosition())
return
end
end
end
Game.playerJoinedEvent:Connect(OnPlayerJoined)
See also: Game.playerJoinedEvent | Player:IsInPartyWith
Example using:
isMovementEnabled
animationStance
serverUserData
There are different approaches to stunning a player. In this example we disable player movement with isMovementEnabled
. We keep count of the number of active stuns, in case more than one stun overlap in duration we don't want the player to exit the stun when the duration of the first one completes.
local STUN_DURATION = 1.5
function ApplyStunToPlayer(player)
player.isMovementEnabled = false
player.animationStance = "unarmed_stun_dizzy"
-- Initialize stun count if needed
if not player.serverUserData.stunCount then
player.serverUserData.stunCount = 0
end
-- Keep track of how many times stun has been called, in case multiple stuns overlap in time
player.serverUserData.stunCount = player.serverUserData.stunCount + 1
-- Duration of the stun effect
Task.Wait(STUN_DURATION)
-- Stun effect has passed. Decrease the counter
player.serverUserData.stunCount = player.serverUserData.stunCount - 1
-- If there are no more stuns active, cleanup
if player.serverUserData.stunCount <= 0 then
player.isMovementEnabled = true
-- Put the animation back to normal
player.animationStance = "unarmed_stance"
end
end
See also: Task.Wait
Example using:
isVisibleToSelf
It's possible to hide the player's model from the player controlling it. This can be especially useful for first-person games. Note that this can only be set by scripts running in the client context.
-- The player can no longer see their own model. Other players' ability
-- to see this player is unaffected.
player.isVisibleToSelf = false
See also: Game.GetLocalPlayer
Example using:
lookSensitivity
You can also make the player's input more or less sensitive, when aiming. This can be useful for aiming down sights, etc.
-- This will double the sensitivity:
player.lookSensitivity = 5
See also: Game.GetLocalPlayer
Example using:
maxAcceleration
brakingDecelerationFalling
brakingDecelerationWalking
groundFriction
brakingFrictionFactor
Through scripts, you can control the player's ability to accelerate their character.
-- The player accelerates more slowly.
player.maxAcceleration = 600
-- The player tends to fall straight down unless they specifically press a direction in mid-air now!
player.brakingDecelerationFalling = 1800
-- The player takes longer to come to rest while walking.
player.brakingDecelerationWalking = 200
-- Also they slide more!
player.groundFriction = 2
-- And more sliding - they have less grip on the ground when decelerating.
player.brakingFrictionFactor = 0.2
See also: Game.playerJoinedEvent
Example using:
movementControlMode
lookControlMode
defaultRotationRate
currentRotationRate
Player motion and facing can be set to several modes, depending on the gameplay needed.
-- The player's movement input is ignored. Player cannot move.
player.movementControlMode = MovementControlMode.NONE
-- Movement follows the player's current view direction. This is
-- the direction the camera is pointing.
player.movementControlMode = MovementControlMode.VIEW_RELATIVE
-- Movement follows the player's current look direction.
-- This is the direction the player's head is facing.
player.movementControlMode = MovementControlMode.LOOK_RELATIVE
-- Movement follows the player's current facing direction
-- This is the direction that the player's torso is facing.
player.movementControlMode = MovementControlMode.FACING_RELATIVE
player.defaultRotationRate = 200
--[[#description
You can also change how the player's look input is processed:
]]
-- Player look input is ignored. The player cannot move their view.
player.lookControlMode = LookControlMode.NONE
-- The player controls the look direction. This is the default mode.
player.lookControlMode = LookControlMode.RELATIVE
-- The player always turns to face whatever the cursor is over, in the world.
-- This works best with a third person camera.
player.lookControlMode = LookControlMode.LOOK_AT_CURSOR
See also: Game.playerJoinedEvent
Example using:
name
id
team
There is a lot of useful information you can get from the player object. Players have a name
property, which is the text display name for the player. Players can set their own names though, so there is no guarantee that name
s will be unique.
Players do, however, have a unique ID assigned to them. (Accessed via the id
property.) It is guaranteed to be distinct from other players, and it is stable across sessions, so it won't change if they log out and log back in again.
This sample grabs the list of all current players, and prints out their name, ID, and what team they are on.
local players = Game.GetPlayers()
print("---There are currently " .. tostring(#players) .. " Player(s):")
for _, p in pairs(players) do
print("Player [" .. p.name .. "]:")
print(" - id: " .. p.id)
print(" - team: " .. p.team)
print()
end
See also: Game.GetPlayers | CoreLua.print
Example using:
occupiedVehicle
In this example, we can imagine a racing game where various start points are defined for the players. When a new round starts we teleport all players who have a vehicle to the starting points, so they can begin a new race. The start point objects are all children of a common group/folder that is set as a custom property. The objects used for start points can be anything, such as an empty group. For this type of invisible "level design object", sometimes creators use a server-context with a static mesh inside, so you can see the points during edit time, but they won't appear or collide for clients.
local START_POINTS_PARENT = script:GetCustomProperty("StartPoints"):WaitForObject()
local START_POINTS = START_POINTS_PARENT:GetChildren()
function OnRoundStart()
for i,player in ipairs(Game.GetPlayers()) do
local vehicle = player.occupiedVehicle
if vehicle then
-- Teleport them to the start points
local startPoint = START_POINTS[i]
if startPoint then
local pos = startPoint:GetWorldPosition()
local rot = startPoint:GetWorldRotation()
vehicle:SetWorldPosition(pos)
vehicle:SetWorldRotation(rot)
else
warn("Insufficient start points for all players")
end
-- Stop their movement
vehicle:SetVelocity(Vector3.ZERO)
vehicle:SetAngularVelocity(Vector3.ZERO)
end
end
end
Game.roundStartEvent:Connect(OnRoundStart)
See also: CoreObject.SetVelocity | CoreObjectReference.WaitForObject | Game.GetPlayers | Vector3.ZERO
Example using:
shouldDismountWhenDamaged
SetMounted
canMount
The player can mount or dismount. We can also force the player to mount or dismount via the Player:SetMounted()
function. Also, if Player.shouldDismountWhenDamaged
is set, they will automatically dismount whenever they take damage.
This sample demonstrates how to force the player to be mounted, and how to set them to dismount when hit.
player.shouldDismountWhenDamaged = true
player:SetMounted(true)
-- Player is now mounted!
-- If they take damage, they should dismount!
player:ApplyDamage(Damage.New(1))
-- We can also disable the player's ability to mount or dismount.
-- Note that this will NOT prevent us from calling SetMounted() -
-- this only affects the player's controls.
player.canMount = false
See also: Player.ApplyDamage | Damage.New | Task.Wait
Example using:
spreadModifier
currentSpread
Players shooting weapons have a spread modifier applied to their accuracy. This can be used to simulate things like loss of aim after jumping, or other activities.
-- Whenever the player lands after a jump, they get more spread
-- on their shots for a second.
local jumpEndListener = player.movementModeChangedEvent:Connect(
function(player, movementMode)
if movementMode == MovementMode.WALKING then
print("Worse aim!")
player.spreadModifier = 2
Task.Wait(1)
print("better aim!")
player.spreadModifier = 1
end
end)
--[[#description
You can also check the player's current (total) spread,
although this only works from the client context.
]]
print(player.currentSpread)
See also: Player.movementModeChangedEvent | Task.Wait | Event.Connect | CoreLua.print
Example using:
stepHeight
walkableFloorAngle
maxJumpCount
jumpVelocity
gravityScale
buoyancy
isCrouchEnabled
Most of the aspects of a player's movement can be controlled at runtime via scripting.
-- Player can now step over 100cm ledges!
player.stepHeight = 100
-- And walk up 60-degree inclines!
player.walkableFloorAngle = 60
-- Player can now double-jump!
player.maxJumpCount = 2
-- And jump twice as high!
player.jumpVelocity = 1800
-- But gravity is twice as strong!
player.gravityScale = 3.8
-- But they are twice as buoyant in water!
player.buoyancy = 2
-- Also the player cannot crouch.
player.isCrouchEnabled = false
See also: Game.playerJoinedEvent
Example using:
touchForceFactor
When the player runs into physics objects, they exert force. You can affect how much force with the touchForceFactor
property.
-- Set the player to push five times as hard!
player.touchForceFactor = 5
See also: CoreObject.SetVelocity | StaticMesh.isSimulatingDebrisPhysics
Example using:
perkChangedEvent
GetPerkCount
Perks are a system to create in-game purchases that allow players to support game creators and enable exclusive content.
Learn more about Perks here.
Repeatable Perks - This type of Perk can be purchased any number of times by players. In this example, we implement the sale of in game currency through multiple bundles and track the purchases using storage and resources. This script will track each Perk bundle to grant users the currency/resource.
local RESOURCE_KEY = "Gem" -- Example currency, can be any resource
-- Perks, of type Net Reference, assigned by dragging from the Perks Manager window
local PERK_1 = script:GetCustomProperty("Perk1")
local PERK_2 = script:GetCustomProperty("Perk2")
local PERK_3 = script:GetCustomProperty("Perk3")
-- Reward amounts per bundle, of type Integer
local PERK_1_REWARD = script:GetCustomProperty("Perk1Reward")
local PERK_2_REWARD = script:GetCustomProperty("Perk2Reward")
local PERK_3_REWARD = script:GetCustomProperty("Perk3Reward")
-- Internal bundles data with bundle storage id and custom rewards per Perk.
-- These rewards can be changed after the game goes live.
local bundles = {}
table.insert(bundles, {perk = PERK_1, storageId = "GemBundle1", reward = PERK_1_REWARD})
table.insert(bundles, {perk = PERK_2, storageId = "GemBundle2", reward = PERK_2_REWARD})
table.insert(bundles, {perk = PERK_3, storageId = "GemBundle3", reward = PERK_3_REWARD})
-- Check if each storage bundle purchase count is different from Perk purchase count.
-- If yes, then grant currency as reward to the player.
function CheckPerkCountWithStorage(player)
local data = Storage.GetPlayerData(player)
for _, bundle in ipairs(bundles) do
local perkCount = player:GetPerkCount(bundle.perk)
local storageCount = data[RESOURCE_KEY][bundle.storageId]
if perkCount ~= storageCount then
data[RESOURCE_KEY][bundle.storageId] = perkCount
Storage.SetPlayerData(player, data)
if perkCount > storageCount then
local resourceAmount = bundle.reward * (perkCount - storageCount)
player:AddResource(RESOURCE_KEY, resourceAmount)
end
end
end
end
-- Check and see if storage purchase value is different from Perk purchase count
function UpdateStorageBalance(player)
local data = Storage.GetPlayerData(player)
data[RESOURCE_KEY].amount = player:GetResource(RESOURCE_KEY)
Storage.SetPlayerData(player, data)
end
-- If player spend and earns the currency resource, update the storage
function OnResourceChanged(player, resource)
if resource == RESOURCE_KEY then
UpdateStorageBalance(player)
end
end
-- If player's doing in game transactions, check and update
-- the balance for current currency with storage bundle tracking
function OnPerksChanged(player)
CheckPerkCountWithStorage(player)
UpdateStorageBalance(player)
end
-- Sets player resource from storage and connects player events
function OnPlayerJoined(player)
local data = Storage.GetPlayerData(player)
-- Setup player resource and save it in a table
if not data[RESOURCE_KEY] or not data[RESOURCE_KEY].amount then
data[RESOURCE_KEY] = {}
data[RESOURCE_KEY].amount = 0
end
-- Setup current Perk purchased count per bundle
for _, bundle in ipairs(bundles) do
if not data[RESOURCE_KEY][bundle.storageId] or Environment.IsLocalGame() then
data[RESOURCE_KEY][bundle.storageId] = player:GetPerkCount(bundle.perk)
end
end
Storage.SetPlayerData(player, data)
-- Set currency resource for displaying balance to player on client side
player:SetResource(RESOURCE_KEY, data[RESOURCE_KEY].amount)
-- Connect events that updates currency balance for player
player.resourceChangedEvent:Connect(OnResourceChanged)
player.perkChangedEvent:Connect(OnPerksChanged)
end
Game.playerJoinedEvent:Connect(OnPlayerJoined)
See also: Storage.GetPlayerData | Player.GetResource | Game.playerJoinedEvent | CoreObject.GetCustomProperty | Event.Connect
Example using:
perkChangedEvent
HasPerk
GetPerkCount
Perks are a system to create in-game purchases that allow players to support game creators and enable exclusive content.
Learn more about Perks here.
In the following example, a script is a child of a Perk Purchase Button, of type UIPerkPurchaseButton
. The user interface container that has the button is in a client context. The specifics of the Perk come in through the custom property MyPerk
, which is then assigned to the button with SetPerkReference()
. When the player joins we connect to the perkChangedEvent
and print out their existing perks with the LogPerks() function.
-- Perk Net Reference custom parameters
local MY_PERK = script:GetCustomProperty("MyPerk")
local TEST_LIMITED_TIME = script:GetCustomProperty("TestLimitedTime")
local TEST_PERMANENT = script:GetCustomProperty("TestPermanent")
local TEST_REPEATABLE = script:GetCustomProperty("TestRepeatable")
-- Mapping of PerkNetRefs to table of properties, in this case a name
local perkList = {}
perkList[TEST_LIMITED_TIME] = { name = "limited-time" }
perkList[TEST_PERMANENT] = { name = "permanent" }
perkList[TEST_REPEATABLE] = { name = "repeatable" }
-- Set purchase button's Perk to given custom property
script.parent:SetPerkReference(MY_PERK)
function DebugLog(msg)
print(msg)
UI.PrintToScreen(msg)
end
function OnPerkChanged(player, perkRef)
DebugLog("on perks changed " .. player.name)
if (perkList[perkRef] ~= nil) then
DebugLog("perk changed: " .. perkList[perkRef].name)
end
LogPerks(player)
end
function LogPerks(player)
-- Example of HasPerk() and GetPerkCount().
-- For non-repeatable perks checking GetPerkCount() > 0
-- is equivalent to HasPerk() == true
for perkRef, prop in pairs(perkList) do
DebugLog("-- perk: " .. prop.name)
local hasPerkMsg = " has perk?: " .. tostring(player:HasPerk(perkRef))
local perkCountMsg = " count: " .. tostring(player:GetPerkCount(perkRef))
DebugLog(hasPerkMsg)
DebugLog(perkCountMsg)
-- Example of getting Perk reference of parent Perk button
local parentPerkRef = script.parent:GetPerkReference()
if (parentPerkRef.isAssigned and perkRef == parentPerkRef) then
DebugLog("is parent perk ref")
end
end
end
function OnPlayerJoined(player)
-- Connect perkChangedEvent
player.perkChangedEvent:Connect(OnPerkChanged)
-- Log perks player has initially on join
LogPerks(player)
end
Game.playerJoinedEvent:Connect(OnPlayerJoined)
See also: UIPerkPurchaseButton.SetPerkReference | NetReference.isAssigned | Game.playerJoinedEvent | CoreObject.GetCustomProperty | Player.name | CoreLua.print | UI.PrintToScreen | Event.Connect