Skip to main content

Restraint Plugin

See RestraintPluginModule for API

danger

This section includes some intermediate scripting

Introduction

The plugin allows you to setup restraints on your AnimationPlayer's current train model.

Script Setup

To access the restraint plugin module, get it through plugins like so:

local rtrf = require(ReplicatedStorage.rtrf)

local plugins = rtrf.plugins

local restraintPluginModule = plugins.restraint
local RestraintPlugin = restraintPluginModule.RestraintPlugin

Here we get the plugin itself, RestraintPlugin. It doesn't require a different version for if it's used on server or client. Restraints, however, do.

To get the server version:

local Restraint_Server = restraintPluginModule.Restraint_Server

To get the client version:

local Restraint_Client = restraintPluginModule.Restraint_Client

Adding it to an animation player is similar to other plugin setup.

local animPlayer = rideManager:getAnimationPlayer("Train1")

local restraintPlugin = RestraintPlugin.new(animPlugin, getRestraintsFromModel)

However, you'll notice it requires a second argument which we will refer to as getRestraintsFromModel. According to RestraintPlugin's constructor getRestraintsFromModel is a function which takes a model a returns an array of Restraint

This is where most of the complexity comes from.

getRestraintsFromModel enables us to be able to manually setup each restraint, but by being explicit in this choice, you have to add more code.

Getting restraints can usually be split into two sections:

  • Getting the restraint models
  • Setting up the restraint class for each model
note

You'll notice that this is a more functional-based approach compared to the majority object-oriented approach this

(If you don't know what each of these mean, feel free to read the wikipedia articles for Functional and Object-Oriented Programing (links not setup))

To simplify, the reason this approach was chosen is to prevent what's known as the multiple inheritance problem. I don't want to create different "Restraints" for each different type when they just share different setups.

This approach is already used in code such as AnimationPlayer.

Getting Restraints

The restraintsFromTag function gets descendants from a Model with the given CollectionService tag.

local restraintsWithTag = restraintPluginModule.restraintsWithTag

-- code
-- ...

local restraintModels = restraintsWithTag()(model)

By default, the tag it will look for will be RESTRAINT. You can change it by passing it in beforehand like so:

local restraintModels = restraintsWithTag("MY_RESTRAINT_TAG_NAME")(model)

Setting Up Restraints

Restraints modify and react to the seats they are attached to. As such, the Restraint class constructor needs to be given a RideSeat.

Getting RideSeat

Depending on how you have your seat system setup, you just need to pass the associated seat Instance like so:

local seat = restraintModel:FindFirstChildOfClass("Seat")
local rideSeat = rideSeatPlugin:getSeat(seat)

Finally, once we have our seat, we create our restraint like so. It is the same on both server and client.

Server:
local restraint = Restraint_Server.new(rideSeat, model)
Client:
local restraint = Restraint_Client.new(rideSeat, model)

Setting Up Multiple Seats

The restraintSystem also supports being able to control multiple seats per restraint.

To setup, just pass in an array of RideSeats:

local rideSeats = {}

table.insert(rideSeats, rideSeat1)
table.insert(rideSeats, rideSeat2)
--- .etc

local restraint = Restraint_Server.new(rideSeats, model)

Model Setup

  • Tag any restraint Model with the tag you want to use.
  • Setup contents for the restraint plugin you want to use.

Plugins

Similar to AnimationPlayer plugins, these extend and provide functionality to a Restraint.

Controlling Restraints

Once you have your restraints, you need to be able to control them in-game.

setIsOpen sets whether this is open or not.

restraint:setIsOpen(true)

setIsLocked sets whether this restraint is locked or not.

While it is locked, isOpen cannot be changed. This is useful if you want a player to not be able to open/close a restraint while the ride is in motion.

restraint:setIsLocked(true)

Example Code

Example Code (Server)

local restraintPluginModule = plugins.restraint
local RestraintPlugin = restraintPluginModule.RestraintPlugin
local Restraint_Server = restraintPluginModule.Restraint_Server

--- code
--- ...

-- setup restraints

local rideSeatPlugin = createRideSeatPlugin(animPlayer)
local function getRestraintsFromModel(model: Model)
local restraintModels = restraintsWithTag()(model)

local restraints = {}

for _, restraintModel in ipairs(restraintModels) do
local seat = restraintModel:FindFirstChildOfClass("Seat")
local seatWrapper = rideSeatPlugin:getSeat(seat)
local restraint = Restraint_Server.new(seatWrapper, restraintModel)

-- setup restraint plugins
-- ...

table.insert(restraints, restraint)
end

return restraints
end

local restraintPlugin = RestraintPlugin.new(animPlayer, getRestraintsFromModel)
animPlayer.RestraintPlugin = restraintPlugin -- add to animation player

Example Code (Client)

-- init

local restraintPluginModule = plugins.restraint
local RestraintPlugin = restraintPluginModule.RestraintPlugin
local Restraint_Client = restraintPluginModule.Restraint_Client

--- code
--- ...

-- setup restraints

local rideSeatPlugin = createRideSeatPlugin(animPlayer)
local function getRestraintsFromModel(model: Model)
local restraintModels = restraintsWithTag()(model)

local restraints = {}

for _, restraintModel in ipairs(restraintModels) do
local seat = restraintModel:FindFirstChildOfClass("Seat")
local seatWrapper = rideSeatPlugin:getSeat(seat)
local restraint = Restraint_Client.new(seatWrapper, restraintModel)

-- setup restraint plugins
-- ...

table.insert(restraints, restraint)
end

return restraints
end

local restraintPlugin = RestraintPlugin.new(animPlayer, getRestraintsFromModel)
animPlayer.RestraintPlugin = restraintPlugin -- add to animation player