Disclaimer: This section is unfinished and misses example videos.
Hook Functions, also known as hooks only, are a way of implementing custom scripts to the game in your server to modify the gameplay experience.
With hooks, you will be able to make events, gamemodes, making SCPs able to escape, SCP-914 tweaking/custom crafting, etc.
Currently, Hook Functions utilizes lox as it’s main language, which is extremely easy to learn.
In this page, you will learn how to use hooks and how to make your first script.
The Hook Functions panel can be accessed by typing “/hooks” in the chat, which will open up the panel.
You may only open the Hook Functions panel if you are the server owner or if the co-owner hooks permission setting is enabled.
After opening the panel, in the top right you will see the close button and two buttons named LOAD
and SAVE
. The Hooks panel will automatically load hooks once opened, but everytime you apply changes or finishing creating a script, you will have to click on SAVE
for the changes to apply.
In the left, there will be a scrollable list of Hook Events and your scripts.
A more detailed list of events can be found here.
In the editor, in the Hook Events list, you will create a script for any event you want.
For this example, we will make a new script for the OnPlayerSpawned
event.
After creating your script and naming it, you will now start typing your code.
For this example, we will make a very simple subclass system that uses rand()
.
Once you finish writing your hook/script, you will then click on the SAVE
button in the top right of the panel, close the editor and then test it.
The nil
value represents “no value”. Commonly this value is returned when you try to access a value that doesn’t exist or isn’t set.
If you define a variable (or a global variable) as nil
, they will stop existing.
In this case, ghost
should return and print nil
assuming there’s no player with that name in your server.
var ghost = GetPlayerByName("JCgurtJfgjd");
print ghost;
In this other scenario, it will print 1251
before setting the variable to have no value.
var mynumber = 1251;
print mynumber;
mynumber = nil;
A Boolean is simply a value that is either on or off, and can only return true
or false
. They are commonly returned by functions and properties, and are generally used for condition checking.
true; // Enabled.
false; // Not enabled (disabled).
The numbers value represents well, numbers. They are used for storing data that can’t be simply stored as a boolean such as player count.
We use double-precision floating point numbers, but stick to basic integers and decimal literals.
1234; // An integer.
-1234; // An negative integer.
12.34; // A decimal number.
Strings are a representation of letters, numbers, symbols, or all, which are denoted using double ("
) or single quotes ('
) although most commonly they are denoted with double quotes.
They are used to store data such as names.
"I am a string";
""; // An empty string.
"123"; // This is a string, not a number.
'Hello'; // This is also a string.
Vectors are a set of three numbers that specify a point in 3D space.
They are used for stuff such as spawning items within a specified area, teleporting players, etc.
Vec3(0,0,0);
Vec3(-94,2,64);
Vec3(1,1,1);
Vectors have alot of properties you can use. You can find them in here.
Although, from them all, we can note some important ones:
The X, Y and Z coordinates of a vector represents the position of the vector.
The x-coordinate denotes the position along the east-west axis, the y-coordinate detones the height and the z-coordinate detones the position along the north-south axis.
var myvector = Vec3(27, 21, 57);
print myvector.X; // prints 27
print myvector.Y; // prints 21
print myvector.Z; // prints 57
The magnitude of a vector represents its length in 3D space.
var myvector = Vec3(5, 5, 5);
print myvector.Magnitude; // prints a number close to 8.6
Here’s a list of functions of vectors.
Creates a new Vector3.
Returns a scalar dot product of the two vectors.
Returns the cross product of the two vectors.
Returns the same vector, but with the lowest numbers of the original components.
Returns the same vector, but with the highest numbers of the original components.
Returns the same vector, but the value is absolute. If your vector has decimals (for example 342.1), it will just remove the decimals.
Returns a Vector3 with each component as the lowest among the respective components of both provided Vector3.
Returns a Vector3 with each component as the highest among the respective components of both provided Vector3 objects.
Returns a Vector3 linearly interpolated between this Vector3 and the given goal by the given alpha.
CFrames, short for Coordinate Frames
, describes a 3D position and orientation.
There’s a few functions you can use for CFrames, it being creating one or getting a value from the position or rotation.
Position
and LookAt
are Vector3 values. This function will return a new CFrame.
If you don’t provide any parameters, it will create an empty CFrame.
var myframe = CFrameNew(5, 5, 5);
var myframe2 = CFrame(Vec3(5, 5, 5));
print myframe; // Prints 5, 5, 5
print myframe2; // Prints 5, 5, 5
This function returns a new CFrame with the position of At
and facing towards lookAt
, optionally specifying the upward direction (up
) with a default of (0, 1, 0)
.
At
, LookAt
and Up
are all Vectors.
var vector = Vec3(5, 5, 5);
var target = Vec3(10, 5, 5);
var myframe = CFrameLookAt(vector, target);
Returns a new CFrame with the position of At
and facing along direction, optionally specifying the upward direction (up
) with a default of (0, 1, 0)
.
At
, Direction
and Up
are all Vectors.
Returns a rotated CFrame from angles rx
, ry
and rz
in radians.
Returns approximate angles.
Returns a CFrame from a translation and the columns of a rotation matrix.
Returns one or more CFrames transformed from world to object space.
Returns one or more CFrames transformed from object to world space.
Returns one or more Vector3s transformed from world to object space.
Returns one or more Vector3stransformed from object to world space.
Returns an inversed copy of a CFrame.
Instances in Hook Functions are datatypes that contain data about a specific thing (such as Player Instance, which contains data about a specific player) which is represented by properties.
Instance | Type | Description |
---|---|---|
Plr.Name |
String | The name of a player. |
Plr.IsAlive |
Boolean | Whether a player is currently alive or not. |
Plr.Class |
String | The player’s class. |
Plr.Cuffed |
String or false | If the player is cuffed, it will return a string with the name of the team that cuffed the player, otherwise false. |
Plr.Health |
Number | The player’s health. |
Plr.MaxHealth |
Number | The player’s max health. |
Plr.Armor |
Number | The player’s current armor value. |
Plr.Immunity |
Number | The player’s current immunity value. |
Plr.Position |
Vector3 | Returns the position of a player. |
Plr.Holding |
String | Returns the name of the item the player is currently holding. If no item is being held, then will return as false. |
Plr.Overwatch |
Boolean | Whether a player is on overwatch/no-spawn mode or not. |
Plr.Id |
Number | Returns the player’s ROBLOX ID. |
Plr.Rank |
String | Returns the player’s rank if any, else returns nothing. Options are Helper - Mod - Admin - Coowner - If the player is the owner, this just returns "" (an empty string). |
Plr.Fuel |
Number | Returns the player’s current fuel as SCP-457. If the player is not SCP-457 it will always return 0. |
Plr.Infection |
Number | Returns the player’s SCP-610 infection percentage. |
Plr.Zone |
String | Returns the zone a player is currently at. |
Plr.MoveState |
String | Returns the player’s current movestate. Valid options are: Running - Walking - Crouching - Frozen (Frozen is used by SCP-173) |
Plr.JumpPower |
Number | Returns player’s jumppower - IMPORTANT: This is currently bugged and always prints 0 |
Plr.Speed |
Number | Returns a player’s current speed. |
Plr.BaseSpeed |
Number | Returns a player’s base speed. This, unlike Plr.Speed , is unaffected by MoveState or SCP-207. |
Plr.CameraDir |
Vector3 | Returns the direction of the player’s camera. |
Plr.CFrame |
CFrame | Returns the CFrame of the player. |
Tables are a versatile tool when it comes to storing data for your scripts.
Similar to variables, they can be accessed and modified at any point of the script.
For a list of functions for tables, click here or click on the table functions in your left side.
To create a table, you first declare a variable and assign its value to the function createtable()
which will return an empty table, turning the variable into one.
After creating a table, add key-value pairs using the square brackets []
, where the key is specified inside and the corresponding value of the key is assigned by =
. Keys and values can be strings, integers, etc. You can also create tables within tables, which are called “nested tables”.
var table = createtable(); // Creates an empty table
table[1] = "Hello!"; // Creates a new entry with key 1 and value "Hello!"
table[2] = "Greetings!"; // Creates a new entry with key 2 and value "Greetings!"
table["Hey"] = 12345; // Creates a new entry with key "Hey" and value 12345
table["Hello"] = 67890; // Creates a new entry with key "Hello" and value 67890
table[3] = createtable(); // Creates an empty table at key 3
table[3][1] = "How are you?"; // Creates a new entry in the nested table with key 1 and value "How are you?"
table[4] = createtable(); // Creates an empty table at key 4
table[4][1] = "This is a message"; // Creates a new entry in the nested table with key 1 and value "This is a message"
To access a table’s content you have to use the same square brackets notation and include the key.
// Assuming we are using the code showed above...
print(table[1]); // Prints "Hello!"
print(table[1][2]); // Prints "How are you?"
print(table[2]); // Prints "Greetings!"
print(table["Hey"]); // Prints 12345
print(table["Hello"]); // Prints 67890
print(table[3][1]); // Prints "How are you?"
print(table[4][1]); // Prints "This is a message"
While accessing a table’s content, you can use loops to iterate through it. For example, you can loop through all players on a server and print their names. Use the for
loop.
// Prints messages in this order: "Hey" "This" "Is" "A" "Message"
var table = createtable();
table[1] = "Hey";
table[2] = "This";
table[3] = "Is";
table[4] = "A";
table[5] = "Message";
var x = 0;
for (var a = 1; a <= #table; a = a + 1) {
x = a;
print(table[x]);
wait();
}
// Prints the names of all the players on the server
var playerlist = GetPlayers();
for (var a = 1; a <= #playerlist; a = a + 1) {
var plr = playerlist[a];
print(plr.Name);
}
An Operator is a symbol or a set of symbols that represent an action and are used with values to return a new value.
Arithmetic operators are simply math operations.
1 + 49; // 50 | Addition
600 - 427; // 173 | Subtraction
22 * 4; // 88 | Multiplication
100 / 5; // 20 | Division
5^2; // 25 | Exponentiation
-(-50); // 50 | Negation
Comparison Operators are Operators that compare different datatypes and can only return true
or false
.
// Can be used with all datatypes //
"Hello!" == "Bye" // false | "Equal to" Operator
"String" == 25 // false
25 != 8 // true | "Not equal to" Operator
"sus" != "innocent" // true
// Can be used only with numbers. //
314 > 50 // true | "Greater than" Operator
200 < 100 // false | "Less than" Operator
5 >= 5 // true | "Greater than or Equal to" Operator
16 <= 16 // true | "Less than or Equal to" Operator
Logical Operators are Operators that combine different values or boolean to return a boolean or a value.
// "!" Operator, This operator negates the boolean.
!true; // false
!false; // true
// "and" Operator, This operator returns true if all parts of the expression are not false.
("Hello" == "Hello") and false; // false.
true and true; // true.
((25 * 2) == 50) and (10 == 2); // false.
// "or" Operator, This operator returns true if any parts of the expression are not false.
"Hello" or false; // true.
("Hello" == "Not") or true; // true.
In Hook Functions, events are those events that trigger code inside them once their designated event happens. For example, the OnPlayerSpawn
event triggers once a player has spawned.
Some events have arguments, which can contain data such as an item’s name, a player’s message, etc, although not all events have arguments.
The HooksStarted
event triggers once cheats are enabled and hooks are started.
This event has no arguments.
The HooksStarted
event is useful for team-based functions such as creating teams and modifying them. It’s a better alternative to OnRoundStart
as it triggers every round, while HooksStarted
only once preventing errors in the Function Hooks Logs tab.
// This makes a new team named "SCP-035". This is not a fully functional SCP-035, and it spawns where SCP-049 spawns.
NewTeam("SCP-035", "Black"); wait();
ModifyTeam("SCP-035", "SpawnName", "SCP-049");
ModifyTeam("SCP-035", "pants", 150150);
ModifyTeam("SCP-035", "shirt", 150150);
The RunHook
event is run by the RunHook()
function.
You can use it’s function inside the event, but beware as it might cause unintended infinite loops.
Argument | Description |
---|---|
Message | It’s a message sent by the RunHook() function, which the RunHook() event uses, for example, to determine which code to run. |
Value | It’s defined by the second argument of RunHook() |
The message argument is defined by the RunHook()
's Message
. So you can do something like this:
// Any event that isn't RunHook
RunHook("Whats up", "bro");
// Runhook event
if (Message == "Whats up") {
Announce("Whats up " + Value);
}
// This will print "Whats up bro"
The OnRoundStart
event runs once a round is started. This event will run every time a round starts.
This event has no arguments.
The OnRoundStart
is useful for making functions such as custom containment breach announcements, playing audios, team-switching functions, etc.
Example Usage:
// OnRoundStart
PlayNamedAudio("breachsound");
if (#GetPlayers() > 10) {
Announce("There's more than 10 players this round!");
}
The OnRoundEnd
event runs once the round ends. It’s the counterpart of OnRoundStart
.
This event has no arguments.
This event might be useful for announcing stuff if a condition is met. For example, announcing what team won the round.
// Assuming that, in some part of your code, you have defined a global named "WinTeam" with the team that won the round.
if (GetGlobal("WinTeam")) { // Checks if the global exists
Announce(GetGlobal("WinTeam") + " has won this round!");
PlayNamedAudio("RoundEnd");
}
The OnNukeStart
event runs once the nuke is engaged. This doesn’t mean the code will run once the nuke detonates, but rather when the 90 seconds timer goes out.
This event has one argument:
Argument | Description |
---|---|
Plr | The player that activated the nuke if exists. |
Let be known that OnNukeStart
also triggers when the nuke is started with the admin panel, and once it occurs the Plr
argument won’t work clearly.
This might be useful for an economy system.
// Assuming you already have a set economy system that works with a "Credits" attribute.
SetAttribute(Plr, "Credits", GetAttribute(Plr, "Credits") + 15);
The OnNukeCancel
event triggers when the nuke is canceled via the button in the nuke room or a custom cancel button with custom rooms.
This event has one argument:
Argument | Description |
---|---|
Plr | The player that canceled the nuke. |
Example of usage:
if (Plr) { // Checks if a player canceled the nuke, else doesn't trigger.
Announce(Plr.Name+" has canceled the nuclear warhead!");
}
The OnNukeDetonation
event runs once the nuke is successfully detonated.
This event has no arguments.
Example of usage:
Announce("The nuclear warhead has been detonated.");
SetSpawnwaveTime(60);
The OnNukeToggle
event runs every time the nuke is toggled.
This event has one argument:
Argument | Description |
---|---|
State | A boolean, whether the nuke is on or off. |
The OnPlayerSpawn
event triggers once a player spawns. This event has 2 arguments:
Argument | Description |
---|---|
Plr | The player that spawned. |
Class | The class the player has spawned as. |
Although Class
is similar to Plr.Class
, for example, if the player was previously a spectator sometimes Plr.Class
will execute before the class change occurs. Class is safer to use overall.
Example of usage:
// Gives the player a Class-D Keycard with a 1 in 15 chance if the player is a Class-D
if (Plr.Class == "Class-D") {
if (rand(1,15) == 1) {
GiveItem(Plr, "Class-D Keycard");
}
}
The OnPlayerDeath
event triggers once a player dies. It’s similar to OnPlayerKill
, although OnPlayerDeath
focuses on the player. This event has 3 arguments:
Argument | Description |
---|---|
Plr | The player that died. |
OldClass | The player’s class before dying. |
IsLeaving | Since leaving the game triggers the OnPlayerDeath event, this will be true if the event was triggered by someone leaving the game. |
The OnPlayerDamaged
event triggers everytime a player is damaged.
By default, this event doesn’t trigger for any kind of damage, and you’ll have to use two functions to make it run properly.
These functions toggle whether OnPlayerDamaged event fires for an AttackType (or AttackSubType).
Setting a AttackType to true will make all SubTypes trigger, but if you whitelist an attacktype and then blacklist a subtype, all subtypes will trigger but that one.
A better example of this would be:
SetFireOnAttackType("gun", true);
All guns will fire the event, but now if you do SetFireOnAttackSubtype("minigun", false);
all guns will fire the event but the minigun.
Attack sub types don’t need the main Attack Type to be true. For example, SetFireOnAttackSubtype("ak", true);
will make only AK fire the event and not the rest of the guns.
List of Attack Types
Attack Type | Has SubTypes? | Description |
---|---|---|
all |
No | Makes every single attack type fire the event. |
custom |
No | For custom teams with no set AttackType |
afk |
No | When the player gets killed for being afk. |
hook |
No | It’s the damage from the TakeDamage() function. |
gun |
A gun’s item name | If you set gun attack type to true, it’ll make all guns trigger. The subtype can be any gun name. If you set gun to true, but you blacklist minigun , all guns will trigger the event except for the minigun. |
melee |
A melee item name | Same as gun but for melee items. |
explosion |
grenade , projectile , rocket , hook , candy , drink |
When an explosion occurs. |
A SCP number (049 049-2 096 106 173 610 939 1507) | No | For when a SCP damages another player. For example, SetFireOnAttackType(049, true); |
207 , 330 and 914 |
No | When 207 deals damage to the player, when you take too many candies and when SCP-914 damages a player because of the settings. |
fire and fuelloss |
No | fire is when SCP-457 attacks someone, fuelloss is when SCP-457 loses fuel. |
1770 , 1770-1 and fatherless |
No | First two are when they attack a player, fatherless is when a SCP-1770-1 is damaged because SCP-1770 isn’t nearby. (funny name) |
decay and pdportal |
No | decay is the damage the pocket dimension deals, pdportal is when you get killed for choosing the wrong portal. |
femur |
No | When SCP-106 gets femured. |
voidcup |
No | The void cup from SCP-294. |
decontamination |
No | Damage dealt because of decontamination. |
nuke |
No | The damage the nuke deals when it detonates. |
zap |
No | The damage the tesla deals. |
fall |
No | Fall damage. |
This event has 3 arguments.
Argument | Description |
---|---|
Plr | The player that received damage. |
Attacker | Can be a player, but if the player was not damaged by another player, then it’ll be false. |
DamageInfo | It’s a read-only table with specific fields. These fields contain information about the damage. |
As we said, DamageInfo is a read-only table, and it contains the following:
DamageInfo | Type | Description |
---|---|---|
Revivable | Boolean? | Is the player is revivable by 049 once it dies? |
BypassArmor | Boolean? | Did the damage bypass the player’s armor? |
BypassImmunity | Boolean? | Did the damage bypass the player’s immunity? |
Internal | Boolean? | Did the damage bypass stuff like armor, immunity and damage-processing code? (Very complex but that’s what the dev said…) |
NoArmorDamage | Boolean? | Does the damage not decrease armor health? |
AttackType | string? | Refer to the list of attack types. |
AttackSubType | string? | Refer to the list of attack sub types. |
HitPartType | "Torso" , "Head" or "Limb" |
Strings and it’s in which part of the player’s body was hit. |
Reason | string? | The death reason if the player died. |
BodyCFrame | CFrame | Where the body end up. |
IsLeaving | Boolean? | Is the player leaving? |
IsReplace | Boolean? | Was the player replaced? |
OriginalDamage | Number? | The original base damage before being changed by stuff like armor and immunity. |
Damage | Number? | The total damage inflicted to the player. |
DoneDamage | Number? | Actual inflicted damage to the player, it’s lower than Damage if the player’s health is less than Damage |
isFF | Boolean? | Was the player attacked because of Friendly Fire? |
killed | Boolean? | Did the player die. |
PlayerClass | string | The player’s class. |
AttackerClass | string | The attacker’s class. |
Here is an example of using DamageInfo.
var killed = DamageInfo.killed;
var body = DamageInfo.BodyCFrame;
if (killed) {
print Plr.Name + " was killed, spawning a red soda where they died because why not";
SpawnItem("Red Soda", body.Position);
}
OnItemPicked
triggers once a player picks up an item. This event is useful for making stuff such as an SCP-035 or avoiding a player being able to pick up an item unless the player is a certain class.
This event has two arguments:
Argument | Description |
---|---|
Plr | The player that picked up an item. |
ItemName | The name of the picked-up item as a string. |
This event fires everytime an item is dropped.
This event has two arguments:
Argument | Description |
---|---|
Plr | The player that dropped the item. |
ItemName | The name of the dropped item as a string. |
The OnItemUsed
event triggers once a player uses any item.
This event has four arguments.
Argument | Description |
---|---|
Plr | The player that triggered the event/used an item. |
Name | The name of the item used. Returns a string. |
Target | Target is a player when the item is a melee, an access name if it’s a keycard being used on a door, otherwise this will be false. |
Similar to OnPlayerDeath
, this event triggers once a player is killed. The difference between this event and OnPlayerDeath
is that this one focuses more on both the victim and the killer. OnPlayerKill
doesn’t run if a player dies from fall damage for example or TakeDamage()
and Kill()
.
This event has 3 arguments:
Argument | Description |
---|---|
Target | The player that was killed. |
TargetOldClass | The target’s class before being killed. |
Killer | The player that killed the target. |
OnPlayerKill
can run if the player accidentally grenades themselves or somehow dies to themselves in any way.
OnPlayerChatted
triggers once a player speaks in chat. This event is useful for making commands, such as a shop command or a command that announces something.
OnPlayerChatted
has 2 arguments:
Argument | Description |
---|---|
Plr | The player that has spoken. |
Message | The message said by the player. |
Example of usage:
// Announces "Pong!" if the player says "!ping"
if (Message == "!ping") {
Announce("Pong!", Plr);
}
OnPlayerLeave
triggers once a player leaves the server. Useful to make announcements for when an owner leaves for example.
This event has two arguments:
Argument | Description |
---|---|
Plr | The player that left. |
OldClass | The player’s class before leaving |
Example of usage:
// Assuming the player was an SCP before leaving.
if (strfind(OldClass, "SCP-", 1, true)) {
Announce("A SCP has left!");
}
The OnPlayerEscapeAttempt
event runs once a player tries to escape through the surface’s escape point or a custom room’s escape point.
This event has three arguments:
Argument | Description |
---|---|
Plr | The player that is trying to escape |
Cuffed | A string or false. Returns the class of the cuffer, otherwise false. |
OldClass | Player’s class while trying to escape |
OnPlayerJoin
triggers once a player joins the server. It’s the counterpart of OnPlayerLeave
.
This event has only one argument:
Argument | Description |
---|---|
Plr | The player that joined. |
This can be useful for making an announcement when you join. Example:
if (Plr.Name == "your name") {
Announce(Plr.Name+" has joined!");
}
The OnPlayer914Upgrade
event is triggered once a player utilizes SCP-914.
This event has two arguments:
Argument | Description |
---|---|
Plr | The player that used SCP-914 |
Mode | The mode used on SCP-914. Modes are “Fine”, “Very Fine”, “Rough”, “Coarse” and “1:1” |
The OnItem914Upgrade
event triggers once an item is passed through SCP-914.
Before someone says it’s “Through” and not “Trough”, the in-game event is named like this. Blame anexpia.
This event has three arguments:
Argument | Description |
---|---|
ItemName | The name of the item passed through SCP-914 |
OutPos | Vector, the output position of the item |
Mode | The mode used for SCP-914 |
This event is currently bugged, and it was used/meant to create custom crafting recipes.
OnExplosion
triggers when a grenade is detonated/explodes.
This event has a total of four arguments:
Argument | Description |
---|---|
Type | The type of the explosion. Can be Grenade, Projectile, Rocket, and nil. |
Position | Vector, the position where the explosion occurred |
Radius | Number, the radius of the explosion |
Damage | Number, the damage of the explosion |
OnSpecialAction
triggers whenever a special action (i.e. 173’s teleport) happens. The target can vary depending on the action.
Argument | Description |
---|---|
Plr | The player as a SCP |
Action | String, takes a SCP name |
Target | Any. |
Special Action | Description |
---|---|
049 (Revive) | Target is body model, you can get the name using Target.name |
096 (Trigger) | Target is the player (Plr ) who triggers 096. |
106 (PlacePortal | No Target |
106 (PDPortal) | No Target |
106 (Teleport) | No Target |
106 (HumanSense) | No Target |
106 (Trap) | No Target |
173 (Teleport) | Target is CFrame |
173 (TeleportAttack) | Target is array of players who are most likely hit |
1770 (ThrowChain) | Target is ray |
1770 (PrepareChain) | No target, cannot be disabled |
1770 (StopThrow) | No target, cannot be disabled |
457 (Burn) | Target is body model, you can get the name using Target.name |
457 (Incinerate) | Target is door model |
Variables are names that have a value associated with them that can be accessed and modified at any point in time, which can be used for storing values.
var imAVariable = "here is my value";
var iAmNil;
var breakfast = "bagels";
print breakfast; // "bagels".
breakfast = "beignets";
print breakfast; // "beignets".
Control Flow is very important while coding, as it determines which path your code should take if a condition is met or not.
if
Statements are conditional statements that execute the code inside them, only if met.
If the condition for the if
statement is not met, the else
keyword can be used to run a different path in your code.
if (2 > 1) {
print "math works";
} else {
print "uh oh, math is broken";
}
The elseif
statement uses the same conditionals as else
and if
in a single condition. If the initial condition is not met, it will run a different path that has another conditional in place.
if (2 > 5) {
print "how is this possible";
} elseif (5 > 2) {
print "math works";
}
while
loops are loops that run code inside them as long as the condition is met. If the condition is not met, the loop stops.
var a = 1;
while (a < 10) {
print a;
a = a + 1;
}
for
loops are loops that can be used to run a block of code a known number of times, unlike while
loop, which can run an indeterminate number of times.
// Prints numbers from 1 to 10
for (var a = 1; a < 10; a = a + 1) {
print a;
}
Although Hook Functions are based on lox, there’s a special variant of the for
loop very similar to LUA, which is used for iterating over tables.
var mytable = createtable();
mytable[1] = "life is good";
mytable[2] = "life is bad";
for i, v in mytable {
if (i == 1) { continue; }
print i; // prints 2
print v; // prints "life is bad"
}
The continue
statement skips the rest of the code inside a loop for the current iteration and continues the next one.
for (var a = 1; a <= 10; a = a + 1) {
if (a == 7) {
continue;
}
print(a); // prints all numbers up to 10, except 7
}
The break
statement exits a loop immediately, skipping any remaining iterations.
for (var a = 1; a < 10; a = a + 1) {
if (a == 6) {
break;
}
print(a); // prints all numbers up to 5
}
The try
block allows you to test your code for any errors, which catch
stores the error as a variable, allowing you to handle the error.
try {
var a = "hi; // This will cause an error due to an indeterminated string.
print(a);
} catch (sillyerror) {
print("An error has occured due to: " + sillyerror); // Prints "An error has occured due to" and the error message, including the line and the script name
}
Functions are blocks of code that can be run at any point in a script, which can receive multiple arguments and return a value at the end of the execution.
It’s recommended to put your functions at the start of your scripts, although it’s not necessary.
// This function will print the result of adding a and b.
function printSum(a, b) {
print a + b;
}
// This function returns the addition of a and b.
function addPair(a, b) {
return a + b;
}
// This function returns the first argument as it is.
function identity(a) {
return a;
}
// This will run the same as 'print addPair(1, 2)`,
// since the identity function will return addPair.
print identity(addPair)(1, 2); // Prints "3".
Functions can also have functions inside of them that can only be called from the first function.
function outerFunction() {
function localFunction() {
print "I'm local!";
}
localFunction(); // This will print "I'm local!"
}
localFunction(); // This will not work as localFunction is not created in the current scope.
Functions can also return functions, as seen in Identity function and the one below, However, the latter returns a function created inside which accesses a variable contained within.
function returnFunction() {
var outside = "outside";
function inner() {
print outside;
}
return inner;
}
var fn = returnFunction();
fn(); // This will print "outside"
This function returns the remainder of a division operation.
The dividend is the number being divided, and the divisor is the number by which the dividend is being divided.
// Example of Usage
print modulus(5, 2); // This will print 1, as the remainder of 5 being divided by 2 is 1
print modulus(4, 2); // This will print 0, as the remainder of 4 being divided by 2 is nothing.
print modulus(6, 10); // This will print the dividend (6)
As shown in the example above, if the dividend is smaller than the divisor it will always return the dividend.
print modulus(5, 10); // This will print 5
Returns a random number between a range.
Both the minimum and maximum arguments are numbers and specify a range to generate a number from.
This will print a random number between 1 and 10
print rand(1,10);
This function is used to check if a number is within a range, which is defined by the minimum and maximum values.
If you provide a number that is less than the minimum, it will return the minimum.
If you provide a number that is greater than the maximum, it will return the maximum.
Otherwise if the number is within the range of minimum and maximum, it will return the number itself.
In this case, the number to be checked is 2. The range is between 5 and 15.
This will return and print 5 as 2 is less than the minimum.
print clamp(2, 5, 15); // Returns 5
This will return and print 8
print clamp(15, 6, 8); // Returns 8
This will return and print 5
print clamp(5, 1, 10); // Returns 5
This function will raise a number by an exponent; a number multiplied by itself as many times as the exponent indicates.
This example below will return and print 32, as 2x2x2x2x2
is 32.
print pow(2,5); // returns 2^5 (32)
Returns the absolute value of a number, which is the same number but positive.
print abs(-2); // returns 2
Returns the lowest closest integer to the number.
print floor(2.824); // returns 2
Returns the closest integer to the number.
print round(2.7); // Returns 3
As previously mentioned, Vectors are a set of three numbers that specify a point in 3D Space.
print Vec3(3,6,2); // Returns 3,6,2
For a full list of Vector functions, go to the Datatypes section and click on “Vectors”
As previously mentioned, CFrames indicate a position and a rotation.
print CFrameNew(5, 5, 5); // Returns 5, 5, 5
For a full list of CFrame functions, go to the Datatypes section and click on “CFrames”
Sets a player’s health. If the health is equal or less than 0, it will kill the player.
// Assuming the player just spawned.
if (Plr.Class == "Class-D") {
SetHealth(Plr, 75);
}
Sets a player’s maximum health. If the health is equal or less than 0, it will kill the player.
// Assuming the player killed someone as SCP-096
if (Plr.Class == "SCP-096") {
SetMaxHealth(Plr, Plr.Health + 100);
}
Changes the transparency of a player.
This function also affects the transparency of a player’s face.
Transparency
must be a number between 0 and 1, where 0 is fully visible and 1 is fully invisible.
Assuming you have a custom SCP-966, once the nuke detonates it will make all the SCP-966s slightly visible.
// OnNukeDetonated
var x = 0;
var scp966s = GetPlayersInTeam("SCP-966"); // Gets the players from the SCP-966 team
for (var a = 1; a <= #scp966s; a = a + 1) {
x = a;
var plr = scp966s[x];
SetPlayerTransparency(plr, 0.85);
}
Sets the body color of a player using HEX color codes.
Sets a player’s face decal. This requires ImageIDs.
Modifies a player’s ammunition, giving or removing them ammo.
You can give the player any amount of ammo you want. Any number equal to or less than 0 will mean no ammo.
Valid Ammo Types | Description |
---|---|
Explosive |
Used for grenade launchers |
HeavyCaliber |
Used for light machine guns and snipers |
MediumCaliber |
Used for assault rifles and marksman snipers |
SmallCaliber |
Used for SMGs and pistols |
Shells |
Used for shotguns |
Makes the player have 10 shotgun shells.
ModifyPlayerAmmo(Plr, "Shells",10);
Makes the player have 150 Small Caliber, 200 Medium Caliber and 50 Heavy Caliber ammunition once they spawn in with a 50% chance.
Note that you can use the ModifyTeamAmmo()
function if you need to set a team’s ammunition.
// OnPlayerSpawn
if (rand(1, 2) == 2) {
ModifyPlayerAmmo(Plr, "SmallCaliber", 150);
ModifyPlayerAmmo(Plr, "MediumCaliber", 200);
ModifyPlayerAmmo(Plr, "HeavyCaliber", 50);
} else {
Announce("Too unlucky, you get no extra ammo.", Plr);
}
}
Drops all the ammo an player has.
Providing a specific type of ammunition is optional, not providing one will result in the player dropping all it’s ammo.
Valid Ammo Types | Description |
---|---|
Explosive |
Used for grenade launchers |
HeavyCaliber |
Used for light machine guns and snipers |
MediumCaliber |
Used for assault rifles and marksman snipers |
SmallCaliber |
Used for SMGs and pistols |
Shells |
Used for shotguns |
Drop all the ammunition of a player once they kill someone.
// Assuming it's put on OnPlayerKill
DropAmmo(Killer);
This code will drop every ammo of “Small Caliber” a player has
DropAmmo(Plr, "SmallCaliber");
Sets a player’s speed as studs-per-seconds.
SetSpeed(Plr, 25);
Sets a player’s jumpforce, which is how high the player can jump.
SetJump(Plr, 50);
Sets a player’s infection level, where if it’s a number equal or greater than 100, it will automatically turn the player into a SCP-610 instance.
SetInfection(Plr, 100); // Turns the player into SCP-610
Set’s a player’s armor number.
If a maximum is not provided, it will set the player’s armor and max armor to that number. Otherwise, it will set the player’s armor and then set the max armor to a different number.
// This will set the player's armor to 50
SetArmor(Plr, 50);
// This will set the player's armor to 50, and maximum to 80
SetArmor(Plr, 50, 80);
Sets a player’s immunity.
Immunity is very similar to armor, but it works in percentages. For example, if you set it to 50, it will absorb half of the damage. Immunity cannot be drained by being attacked.
SetImmunity(Plr, 50);
Sets a player’s current vest only if it’s any of the vests below.
Valid Vest Names | Description |
---|---|
Light Weight Vest |
A normal Light Weight vest, provides 100 armor. |
Insulated Vest |
A normal Insulated vest, provides 200 armor. |
Insulated Heavy Vest |
A normal Insulated Heavy vest, provides 300 armor. |
SCP |
Absorbs all damage. |
nil |
no vest. |
Gives a player an Insulated Vest once they use SCP-914 in “Very Fine”.
// OnPlayer914Upgrade
if (Mode == "Very Fine") {
SetVest(Plr, "Insulated Vest");
}
Sets a SCP-457’s fuel number, but if the player is not SCP-457 this function may error.
SetFuel(Plr, 5000);
This function will enable whether a player has noclip. If you’re on PC, to toggle noclip press I
SetNoclip(Plr, true);
Makes a player immortal. Same as SetGodmode()
.
Immortalise(Plr, true);
Makes a player immortal. Admin panel player settings’ godmode behaviour.
SetGodmode(Plr, true);
Returns a Boolean
whether player has godmode or not.
if (HasGodMode(Plr) == true) {
print Plr.Name+" has godmode!";
}
Makes players be able to bypass any door access value and open every door.
SetBypass(Plr, true);
Makes the player be in overwatch/no-spawn mode.
SetOverwatch(Plr, true);
Reduces a player’s health.
Argument | Type | Description |
---|---|---|
Plr | Player | The player whose health will be reduced. |
Amount | Number | How much health will be taken from the player. |
DeathReason? | String | If the player is killed, this will be the death reason. |
By Player? | Another Player | If the player is killed, the killer can be someone else. |
// Assuming the player picked up a Cup
if (ItemName == "Cup") {
TakeDamage(Plr, 20);
}
Returns a boolean whether a player can see another player, using the same criteria as viewing SCP-096.
// Any previous function, this is just a demonstration.
if (GetPlayerByName("Fernando121231")) { // Checks if Fernando121231 is in the server
if (CanSee(Plr, GetPlayerByName("Fernando121231"))) { // If true, runs code below
Announce("You can see Fernando!", Plr);
}
}
Kills a player, with the option to add an custom reason.
Kill(Plr, "Too silly"); // Kills the player and others can see the "Too silly" reason
Kicks a player. The Kick()
hook does NOT work with in-game staff such as moderators.
// Assuming this is put in the OnPlayerChatted event
if (Message == "!death") {
Kick(Plr, "Death!");
}
Spawns a player as a class.
// Assuming the player just spawned as a Class-D.
if (Plr.Class == "Class-D") {
var pos = Plr.Position;
var rnum = rand(1,4);
if (rnum == 2) {
SetClass(Plr, "Serpents Hand", pos);
}
}
Set the Player’s appearance to a class, sort of SCP-034 disguising.
// Makes the player look like a Janitor
SetPlayerAppearance(Plr, "Janitor");
Same behavior as SetClass()
, although ConvertToClass()
has the advantage of keeping the player in place, and giving the ability to keep their items and clothing.
Argument | Type | Description |
---|---|---|
Plr | Player | The player to be re-classed. |
ClassName | Class | The class the player will be spawned as. |
KeepClothing? | Boolean | Keeps the clothing of the player after being re-classed. |
KeepInventory? | Boolean | Keeps the items of the player after being re-classed. |
Killer? | Boolean, Player or nil | Makes the player see the death screen after getting converted. If a player is provided, they will see the death screen as if they were killed by them. Using nil will disable this death screen. |
ConvertToClass(Plr, "Class-D", true, false, nil);
Sets a player’s pants. PantsId
must be a valid asset id.
SetPants(Plr, 7477892092);
Sets a player’s shirt. ShirtId
must be a valid asset id.
SetShirt(Plr, 10922202523);
Gives the player an accessory, as long as the accessory id is a valid assetid.
AddPlayerAccessory(Plr, "Glare", 10721963880);
Removes a player’s accessory set by AddPlayerAccessory()
RemovePlayerAccessory(Plr, "Glare");
Modifies in what channel the player is talking to.
This function is compatible with ROBLOX’s rich text by modifying the channel’s appearance in the chat.
if (Message == "!SCPChannel") {
SetChannel(Plr, "SCP");
Announce("You're now talking with SCPs!", Plr);
}
Modifies the player’s chat color. Must be a valid HEX
value.
// Makes the player's chat color fully white.
SetChatColor(Plr, "#fffff");
Teleports the Player to a position on the map, specified by Vec3
.
// This will teleport the player 15 studs up when ran.
Teleport(Plr, Plr.Position + Vec3(0,15,0));
Returns the inventory of a player as a table.
Plr
must be a player currently connected to the server.
If the player has no items, it will return an empty string.
var items = GetInventory(Plr);
for i, v in items {
if (v == "Medkit") {
Announce("Yoink!", Plr);
RemoveItem(Plr, "Medkit");
break;
Does an explosion.
Argument | Type | Description |
---|---|---|
Position | Vector | Where the explosion will occur. |
Damage | Number | The damage the explosion will deal to players within the radius. |
Radius | Number | In studs, the radius of the explosion. |
Player? | Player | Assigns a player for the explosion. If the explosion kills anyone, it will count as if the player killed them. |
DeathReason? | Any | The death reason in the case the explosion kills someone. |
// Makes an explosion at the player's position, with a damage of 50 and a radius of 10, assigning the explosion to the player. If the explosion kills anyone, the death reason will be "Boom!".
Explode(Plr.Position, 50, 10, Plr, "Boom!");
Returns a table containing all the players within a server.
// Prints everyone's name from the server
var players = GetPlayers();
var x = 0;
for (var a = 0; a <= #players; a = a + 1) {
x = a;
var plr = players[x];
print plr.Name;
}
Returns a player if they are in the server, else returns nil
.
// assuming you want to kill someone with a "!kill" command
if (sub(Message, 1, 5) == "!kill") {
var plr = GetPlayerByName(sub(Message, 7, #Message));
if (plr) {
Kill(plr, "Got killed by a command");
}
}
Returns a table containing all the players inside a team. If the team isn’t a valid class (doesn’t exist), this function will error.
var players = GetPlayersInTeam("Class-D");
Returns a table containing all the players in a zone.
List of Zones | Description |
---|---|
hcz-ez |
Heavy Containment and Entrance Zone |
lcz |
Light Containment |
scz |
Surface Containment |
surface |
Surface Zone |
arena |
The Arena (where TEAM 1-4 spawn at) |
pocketdimension |
SCP-106’s pocket dimension |
var playersinzone = GetPlayersInZone("HCZ-EZ");
// Returns all players in the High Containment and Entrance zones.
Gives the a player an item. If you try to put an item that doesn’t exist or you type it wrong, it’ll error.
This function supports multiple items by adding a ,
and then another item name.
// This will give the player a flashlight when ran.
GiveItem(Plr, "Flashlight");
// This will give the player multiple items at once.
GiveItem(Plr, "AK-47", "Flashlight", "Radio", "Medkit", "Medkit", "Grenade");
Returns true if the player has any item named ItemName
, else returns false.
if (HasItem(Plr, "Flashlight")) {
print Plr.Name + " Has Flashlight";
}
If the Player has an item named ItemName
, it will be removed from their inventory.
RemoveItem(Plr, "Flashlight");
Forces the player to equip an item if its a valid item and the player has the item.
ForceEquip(Plr, "Flashlight");
Drops whatever item the player is currently holding.
// Assuming player is holding a flashlight, it drops the flashlight.
if (Plr.Holding == "Flashlight") {
DropHeld(Plr);
}
Deletes whatever the player is currently holding.
// Assuming the player is holding a Flaslight, it deletes it.
if (Plr.Holding == "Flashlight") {
DeleteHeld(Plr);
}
Drops all of a chosen item. If ItemName
is not specified it drops everything.
DropItems(Plr, "O5 Keycard");
Clears everything in the inventory of the player.
ClearInventory(Plr);
Forces player to stop holding whatever item it was helding.
Disarm(Plr);
Cuffs a player, Reason
will show up as “YOU HAVE BEEN CUFFED BY Reason
”
If the player is in the lobby class, it will only show the reason, being specially useful for stuff such as timers.
Cuff(Plr, "THE HORRORS");
Uncuffs a cuffed player.
Uncuff(Plr);
If the Attacker
can damage the Target
directly, returns true, else false.
// Assuming the variables "Attacker" and "Target" are valid players.
if (CanAttack(Attacker,Target)) {
print Attacker.Name+" Can Damage "+Target.Name;
}
Returns a Boolean
value whether Player1
is hostile towards Player2
.
// Assuming the variables "Attacker" and "Target" are valid players.
if (IsHostile(Attacker,Target)) {
print Attacker.Name+" is hostile towards "+Target.Name;
}
Returns a Boolean
value whether Player1
is friendly towards Player2
.
// Assuming the variables "Player1" and "SecondPlayer" are valid players.
if (IsFriendly(Player1,SecondPlayer)) {
print Player1.Name+" is friendly towards "+SecondPlayer.Name;
}
Returns a Boolean
value whether Player1
is neutral towards Player2
.
// Assuming the variables "Player" and "SecondPlayer" are valid players.
if (IsNeutral(Player,SecondPlayer)) {
print Player.Name+" is neutral towards "+SecondPlayer.Name;
}
Modifies the player’s scale. Default scales are 1.
Scale name | Description |
---|---|
head |
A player’s head scale. |
height |
How tall a player is. |
depth |
A player’s depth, basically making them fat (or thin) in the front and back. |
width |
A player’s width, basically being able to make them very fat or thin. |
all |
All the aforementioned scales in a single one. |
With a 10% chance, makes a player small if they are a Class-D on spawn.
if (Class == "Class-D") {
if (rand(1,10) == 10) {
SetPlayerScale(Plr, "all", 0.8);
}
}
Returns the value of a player’s scale.
Valid options are the same as SetPlayerScale()
's
Print’s a player’s height.
print(Plr.Name+" height is: " + tostring(GetPlayerScale(Plr, "height")));
Spawns the item named ItemName
if ItemName
is a valid item name at Pos
.
SpawnItem("Flashlight",Vec3(3,5,2));
Removes all items named ItemName
from the map. If ItemName
is not provided it will delete all items from the map.
// Clears all items
ClearItems();
// Clears all flashlights
ClearItems("Flashlight");
Returns a table with all the items within the game.
// Gives the player a random item
var items = GetItemList();
var numberrand = rand(1, #items);
var selecteditem = items[numberrand];
GiveItem(Plr, selecteditem);
// It's not needed to add so many variables. GetItemList()[rand(1, #GetItemList())] is enough but doesn't look good.
This function edit’s an item’s property. For example, it can change the recoil, it can make a gun have infinite ammunition, make it act like a railgun, etc.
The following properties work on any item.
Item Property | Type | Description |
---|---|---|
SpeedModifier | Number? | It slows you down when you hold the item by negative the number its set to. Basically: Speed = (Speed - SpeedModifier) |
Disabled | boolean? | If true, it’ll make the item non-usable, but can’t be used with guns. Even if the item has this property, it will trigger the OnItemUsed event. |
The following properties work only on items that are considered guns.
Gun Property | Type | Description |
---|---|---|
Ammo | Number | How much ammo a gun currently has |
AmmoType | String | Ammo the gun will use to reload, valid ammo types are: SmallCaliber - MediumCaliber - HeavyCaliber - Explosive - Shells - Rails |
ClipSize | Number | The max ammunition a gun can have |
Damage | Number | How much damage the gun will deal |
Firerate | Number | Modifies the gun’s firerate |
Recoil | Number | Modifies the gun’s recoil, higher the Number the higher your camera moves when shooting. |
Spread | Number | Modifies the gun’s spread |
Pellets | Number? | For shotguns |
Mode | String | Changes the gun’s mode, valid mode types are: Burst - Auto - Semi - Charge (Charge is like railgun) |
ChargeDuration | Number? | Optional, how much time it takes for the gun to charge (only affects guns with the Charge mode) |
Overcharge | Boolean? | Optional and will only work with guns using the Charge property. It gives you around twice the time to aim, and the behavior is exactly the same as Railgun’s overcharge. |
DamagePercentage | Number? | Optional. Adds a percentage of the target’s max health as bonus damage. Formula: Damage + (DamagePercentage x 0.01) x TotalHealth (Example: 20 + (50 x 0.01) x 100 = 20 + 50 = 70) |
Penetration | Number? | Optional. Modifies the penetration power of the projectile fired from the gun. |
Special Gun Properties | Type | Description |
---|---|---|
GrenadeLauncher | Boolean? | Makes the gun act like a Grenade Launcher |
RPG | Boolean? | Makes the gun act like an RPG |
Shotgun | Boolean? | Makes the gun act like a shotgun |
Penetration | Number? | Enables penetration, penetration acts like the railguns penetration. (Through doors and people) |
PenetrateBreak | Boolean? | toggles whether penetration breaks doors |
DeathReason | String? | When someone is killed by the gun in question, the body will display this death reason. |
For Shotguns | Type | Description |
---|---|---|
Pellets | Number? | For shotguns |
For guns with Burst | Type | Description |
---|---|---|
BurstAmount | Number? | Modifies the amount of burst |
BurstControlled | Boolean? | Modifies whether burst can be controlled or not |
BurstCooldown | Number? | Modifies cooldown between bursts |
For both guns and melees | Type | Description |
---|---|---|
Heal | Number? | makes gun heal allies |
Headshot | Number | Modifies how much damage the headshot is gonna deal, which will be modified afterward by HeadshotType |
HeadshotType | String | Modifies how the headshot works. Valid headshot types are: ad - multiply For HeadshotType , if add , Damage = (Damage + Headshot). if multiply , Damage = (Damage * Headshot) |
The following properties only work in items considered as melee weapons.
Melee Property | Type | Description |
---|---|---|
Headshot | Number | Modifies how much damage the headshot is gonna deal, which will be modified afterward by HeadshotType |
HeadshotType | String | Modifies how the headshot works. Valid headshot types are: add - multiply For HeadshotType , if add , Damage = (Damage + Headshot). if multiply , Damage = (Damage * Headshot) |
Heal | Number? | Makes melee heal allies |
MeleeDamage | Number | Modifies the damage of Melee |
The following properties are for misc. items such as medkits, vests, etc.
Vests and Shields Properties | Type | Description |
---|---|---|
Durability | number | Modifies how much durability it has |
MaxDurability | number | Modifies max durability it can have (only for the durability bar) |
Medkits Properties | Type | Description |
---|---|---|
Heal | number | Modifies how much they Heal |
The following item properties only work on items that are grenades.
Grenade Properties | Type | Description |
---|---|---|
Damage | Number | How much damage the grenade deals. |
Radius | Number | The radius of the explosion of the grenade in studs. |
Time | Number | In seconds, how much time it will take for the grenade to explode. |
The following properties are for keycards. Although it’s only one property, it’s really useful.
Access Property | Type | Level | Description |
---|---|---|---|
Access | accesstype | accesslevel (true or number) | Modifies the access of the keycard, this works like this: ModifyItem(“Researcher Keycard”, “Access”, “cont”, true); |
If it’s not an keycard, it’ll error. true
means it’ll open any door with that access, bypassing level of access.
Valid accesstypes
are:
cont
| manage
| armory
| detonate
| checkpoint
| gate
| nuke
For accesslevel
, number means it’ll open any door with that access, but only those that are equal or below to the number.
ModifyItem("Researcher Keycard", "Access", "cont", 2);
// Now, the researcher keycard can open any doors that have cont_2 or below as access.
// However, the researcher keycard can't open any doors that have cont_3 or above as access.
You can make your custom access levels with custom rooms and doors. You’ll only have to give your door an access of whatever you want and include a number if you wish.
For example, giving a door the access specialdoor
without a number.
Now, to give a keycard permission to open it, if you gave this access a number (for example specialdoor_4
), you can give it a number as well, which will indicate up to what level of said access the keycard can open, using true
will make the keycard bypass this limitation and open all instances of that access regardless of the levels of clearance.
ModifyItem("Facility Guard Keycard", "Access", "specialdoor", true);
// Now facility guard keycard can open all doors with the access "specialdoor" regardless of their access number.
ModifyItem("Facility Guard Keycard", "Access", "specialdoor", 2);
// Now facility guard keycard can open doors with the access "specialdoor_0", "specialdoor_1" and "specialdoor_2"
Returns a boolean whether a keycard is able to access a door or not.
print(CanKeycardAccess(Janitor, "manage_2"));
// Assuming the janitor can't open a manage_2 door, it'll print false.
Returns the value of an item’s property.
// Assuming UMP-45 fire rate is 2 for example.
print ("UMP-45's fire rate is " + tostring(GetItemProperty("UMP-45", "Firerate")));
// This should print "UMP-45's fire rate is 2"
Does the end win screen. Text
must be a string, and Color
is optional but must be a HEX color code.
EndRound("The Chaos Insurgency prevails", "#3D9128");
// This makes an endscreen saying "The Chaos Insurgency prevails", in a green'ish color.
Modifies the gravity of everything. The default gravity number is 50.
SetGravity(100); // Double the default gravity
Spawns a grenade that will explode. Position
is a Vec3. Type
is a string and its optional, value types are default
| smoke
| stun
| projectile
| nil
(resets to default).
Owner
is a player and is optional and it’ll make so if the grenade kills anyone, it’ll show up as the Owner killed them.
ExplodeTime
is a number, it’s the time it’ll take for the grenade to explode. Damage
is also a number and it’s the damage the explosion will do. Radius
is the radius of the explosion in studs.
SpawnGrenade(Plr.Position, "default", Plr, 0.5, 100, 15);
// Spawns a grenade at a player's position that explodes within 0.5 seconds of appearing, dealing 100 damage in a 15 studs radius.
Creates a popup with the specified message, if no player is specified it will be sent to all players.
This function is compatible with Rich Text.
Announce("This is a message everyone can see.");
Announce("This is a message only you can see.", Plr);
Creates a popup with the specified message, if no player is specified it will be sent to all players.
Only users with their age set to 13+ can see announcements sent AnnounceRestricted.
This function is compatible with Rich Text.
AnnounceRestricted("This is a message everyone can see.");
AnnounceRestricted("This is a message only you can see.", Plr);
Sends a message in chat containing a message.
Argument | Type | Description |
---|---|---|
Message | Any | The message to be announced in the chat. |
Plr | A player or false | The player to announce the message to. If false, it’ll announce for everyone in the server. |
#HEX | HEX Color Value | Gives the message color. |
These codes will announce a message where everyone can see, and then one only a single player will be able to see.
SendChatMessage("This is a message everyone can see.", false, "#bbffbb");
SendChatMessage("This is a message only you can see.", Plr, "#ffbbbb");
Same as the SendChatMessage()
function, although it can only show up for users with accounts over 13+.
Argument | Type | Description |
---|---|---|
Message | Any | The message to be announced in the chat. |
Plr | A player or false | The player to announce the message to. If false, it’ll announce for everyone in the server. |
#HEX | HEX Color Value | Gives the message color. |
These codes will announce a message where everyone can see, and then one only a single player will be able to see.
SendChatMessageRestricted("This is a message anyone 13+ can see.", false, "#22ff22");
SendChatMessageRestricted("This is a message only you can see as long you're 13+.", Plr, "#ff2222");
This function will toggle the lights on a specific zone or multiple zones at a time.
Valid zones | Description |
---|---|
hcz-ez |
Heavy Containment Zone and Entrance Zone |
lcz |
Light Containment Zone |
surface |
Surface Zone |
scz |
Surface Containment Zone |
sublevels |
LCZ’s Sublevels |
arena2 |
Small arena. |
tutorial |
Where the tutorial class spawns at. |
all |
Toggles the lights for all zones |
main |
It’s used by the blackout you would see in a normal gameplay. |
SetLights("hcz-ez", false); // Starts a blackout for HCZ and EZ only
wait(120); // Waits 2 minutes
SetLights("hcz-ez", true); // Restores the lights for HCZ and EZ
SetLights("all", false); // Starts a blackout for every zone, disabling their lights
wait(120); // Waits 2 minutes
SetLights("all", true); // Restores the lights for all zones
SetLights("main", false); // Starts a normal blackout
wait(120); // Waits 2 minutes
SetLights("main", true); // Restores the lights
Enables or disables the round lock.
If enabled, prevents the round from ending if a win condition is met.
SetRoundLock(true); // Enables Round Lock
Enables or disables the fall damage.
If enabled, any player falling from a height will take damage that scales with the distance they fell.
SetFallDamage(true); // Enables Fall Damage
Changes the type of the Chat, which can only be proxy or global.
SetChatType("proxy"); // Enables proximity chat
Modifies the range of Proximity/Area chat in studs.
SetProximityRange(80); // Players can see their messages in proxy within 80 studs from each other!
Enables the Hidden Teams option that can be found in server settings. This makes so you can’t see any team color in chat, only if they are close and you can see them.
SetHiddenTeams(true);
Enables or disables infinite ammo.
Infinite Ammo makes it so players don’t require ammo to reload a gun, basically reloading without having the needed ammo.
SetInfAmmo(true); // Enables infinite ammo
Enables or disables doors.
SetDoorsEnabled(false); // Disables doors
Enables or disables the Auto Nuke.
The Auto Nuke triggers after 20 minutes of a round start, and forces the nuke to detonate.
SetAutoNukeEnabled(false); // Disables autonuke
Enables or disables the cooldown for SCP-294.
Set294CooldownEnabled(false); // Disables 294 Cooldown
Enables or disables the decontamination.
Once decontamination occurs, if false, the decontamination gas won’t deal any damage.
SetDecontamination(false); // Disables Decontamination
Enables or disables being able to vote for FF
SetVotingEnabled(false); // Disables FF voting
Enables or disables stamina.
SetStaminaEnabled(false); // Disables stamina and players can run and jump any much they want.
Enables or disables player collisions. This makes so players can, for example, jump and make a tower or push others into the abyss.
SetPlayerCollisions(true); // Makes players be able to collide with each other
Returns a table containing all the zones in your map, including custom ones
Modifies a zone’s property.
List of Zones | Description |
---|---|
hcz-ez |
Heavy Containment and Entrance Zone |
lcz |
Light Containment |
scz |
Surface Containment |
surface |
Surface Zone |
arena |
The Arena (where TEAM 1-4 spawn at) |
arena2 |
The small arena |
sublevels |
LCZ Sublevels |
tutorial |
The place where “TUTORIAL” class spawns at |
pocketdimension |
SCP-106’s pocket dimension |
List of Zone Properties | Value | Description |
---|---|---|
hasdaylight |
Boolean | Makes the zone be able to have day time. |
hasblackout |
Boolean | Modifies whether the zone is affected by blackouts. |
daylightskyonly |
Boolean | Day time doesn’t disable lights that don’t have the _daytimeignore tag. |
hasdecontamination |
Boolean | People don’t die if decontamination occurs. |
ignorenuke |
Boolean | People don’t die if nuke happens |
Disabling blackout for HCZ and EZ
ModifyZone("hcz-ez", "hasblackout", false);
Disabling decontamination for LCZ
ModifyZone("lcz", "hasdecontamination", false);
Returns a boolean whether a zone has a property enabled.
The zones and zone properties can be found above in ModifyZone()
. This function works with custom zones as well.
if (GetZoneProperty("scz", "hasdecontamination") == false) {
Announce("SCZ is safe from the decontamination!");
}
Returns a boolean whether a zone exists or not.
// Assuming this zone doesn't exist, it should print false.
print DoesZoneExist("horrorcontainmentzone");
Removes all corpses of a player. If PlayerName
is not specified it will delete all ragdolls from the map. PlayerName
must be a valid Plr.Name
instance.
// Removes all corpses
ClearRagdolls();
// Removes all corpses of a player. Assuming this is put in OnPlayerChatted
if (Message == "!removecorp") {
ClearRagdolls(Plr.Name);
}
Changes Friendly Fire mode for the round to type
if type
is a valid type.
type options: REVERSE, ON, OFF
SetFF("ON"); // REVERSE, ON, OFF
Sets the event mode to true or false.
// Enables event mode
SetEventMode(true);
Does a spawnwave. Valid SpawnType
are:
sh
| goc
| mtf
| ci
IsInstant
must be a boolean. If IsInstant
is true, it does a spawnwave without animation or announcement.
// Does a MTF spawnwave
DoSpawnwave("mtf", false);
// Does a MTF spawnwave too, but without animation, announcement or audio.
DoSpawnwave("mtf", true);
Does a spawnwave animation without actually spawning a wave.
Animation type | Description |
---|---|
goc |
Makes the animation of the GOC plane. |
mtf |
Makes the animation of the MTF helicopter arriving. |
ci |
Makes the animation of CI’s humvees entering the facility. |
Makes the helicopter of MTF spawn and do the animation as if MTF was spawning.
DoSpawnwaveAnimation("mtf");
Makes the GOC plane appear.
DoSpawnwaveAnimation("goc");
Opens the gate where CI spawns and the cars enter the facility doing a CI spawn animation.
DoSpawnwaveAnimation("ci");
Enables or disables random spawns.
// Disables random spawns, so no spawnwaves occur naturally.
SetRandomSpawns(false);
Sets the time until a spawnwave in seconds. This timer goes down until 0 and spawns a team if RandomSpawns are enabled.
// If Randomspawns are enabled, this will spawn a team within 2 minutes.
SetSpawnwaveTime(120);
Returns the time in seconds until a spawnwave.
SetspawnwaveTime(20);
print GetTimeTillSpawnwave();
// Prints 20 (sometimes 19 as it takes a little bit of time to run all the code)
Sets the map to MapName
. If the round is on-going, next map will be MapName
.
To set custom maps, you have to use SetMap(CUSTOM_MapName
with the CUSTOM
suffix.
// Assuming there's a map named "Oscar"
SetMap("Oscar");
// Assuming you have a custom map named "FlatTerrain"
SetMap("CUSTOM_FlatTerrain");
Returns the name in a string of the current map.
print GetCurrentMap();
// If the current map is "Oscar", it's going to print out "Oscar".
Returns the name in a string of the next map in the map pool.
print GetNextMap();
// If the next map is "Catto", it's going to print out "Catto".
Creates a new map and adds it to the map pool in admin settings. This map will have the CUSTOM
suffix. To use it you need to include a Github Raw Link
. To do this, create a repository, name it whatever you want, create a file, paste in your map code and then copy the raw link of the file.
The Raw Github Link should look like this: (NOT FUNCTIONAL LINK)
https://raw.githubusercontent.com/YourName/RepoName/main/FileName
// Non-Functional code, it is just an example.
AddMap("FlatTerrain", "https://raw.githubusercontent.com/MyName/MyRepo/main/FlatTerrain");
Removes a map from the map pool.
RemoveMap("Qati-3");
Plays a named audio for everyone in the server.
PlayNamedAudio("horror");
Stops a currently playing named audio.
StopNamedAudio("horror");
Pauses a currently playing named audio. May be resumed with ResumeNamedAudio()
.
PauseNamedAudio("horror");
Resumes a named audio that was paused using PauseNamedAudio()
.
ResumeNamedAudio("horror");
Creates or modifies an already existing named audio. NamedAudio
parameter can be any name, SoundId
must be a valid Roblox Sound ID.
You can use SetNamedAudioId() to modify default audios, those are:
Audio Name | Description |
---|---|
shtheme | Serpent’s hand theme |
mtftheme | Mobile Task Force’s theme |
citheme | Chaos Insurgency’s theme |
goctheme | Global Occult Coalition’s theme |
mtfenter | The announcement for when MTF spawns. |
lczambience | The ambience for Light Containment Zone. |
hczambience | The ambience for High Containment Zone. |
ezambience | The ambience for Entrance Zone. |
surfaceambience | Surface’s Zone ambience |
pocketdimensionambience | Pocket Dimension’s ambience |
lobbyambience | Lobby’s ambience (Voting Phase) |
Sets the ambience for an zone.
Please note that this function is meant for custom zones, and will error with any default zones.
This function will error with the following functions:
Changes a named audio’s volume.
SetNamedAudioVolume("horror", 0.1);
Makes an named audio looped.
SetNamedAudioLooped("horror", true);
// Now "horror" named audio will play over and over again.
Sam as PlayNamedAudio()
but only works per-player.
// This will make only the player hear the "horror" audio.
PlayNamedAudioForPlayer(Plr, "horror");
// The entire server will hear the "horror" audio
PlayNamedAudio("horror");
Modifies an audio’s playback region. Behaviour of ROBLOX Studio’s playback region function.
SetNamedAudioPlaybackRegion("horror", 1, 2);
Modifies an audio’s loop region. Behaviour of ROBLOX Studio’s loop region function.
SetNamedAudioLoopRegion("horror", 2, 3)
Returns the assetid of an audio.
print("MTF's theme ID is: " + tostring(GetNamedAudioId("mtftheme")));
// This print's MTF theme's audio id
Sets the id to play an audio using PlayAudio()
The id must be an asset id.
SetAudioId(206438030);
Plays the audio set through SetAudioId().
PlayAudio();
Stops the audio set through SetAudioId().
StopAudio();
Returns a boolean, whether a player has an tag.
if (HasTag(Plr, "Juggernaut")) {
SetMaxHealth(Plr, 1000);
SetHealth(Plr, 1000);
}
Gives a tag to a player. This tag is only visible in the admin panel in the left, user list.
Must be a string.
// assuming the player spawned
if (!strfind(Plr.Class, "SCP") and rand(1, 10) == 5) {
GiveTag(Plr, "Juggernaut");
}
Removes a tag from a player.
// Assuming the player just died
if (HasTag(Plr, "Juggernaut")){
RemoveTag(Plr, "Juggernaut");
}
Gives the player a tag that is visible when hovered. Replaces TRAITOR
and CUFFED
tags. You may use emojis and richtext with player tags.
// Gives the player a tag named "Hook Functions are great!" which is visible when the player is hovered by another player.
SetPlayerTag(Plr, "Hook Functions are great!");
Gives a player an attribute.
Attributes can be accessed with GetAttribute()
.
// Assuming this script is placed within the OnItemPicked event
if (ItemName == "Cup") {
SetAttribute(Plr, "SCP-2923", 1);
RemoveItem(Plr, "Cup");
}
Checks if a player has the requested attribute and returns it.
// Assuming the player has the attribute "SCP-2923" and has a value of 1
if (GetAttribute(Plr, "SCP-2923") == 1) {
SetSpeed(Plr, 40);
Announce("You have acquired SCP-2923-09", Plr);
}
Runs the RunHook
event. The Message
parameter will be used for RunHook
’s Message
argument and Value
for the RunHook
’s Value
argument.
For example, you can do this:
// OnPlayerSpawn event
RunHook("hey there");
// RunHook event
if (Message == "hey there") {
print("someone spawned, they said: " + Message);
}
Shuts down the server and forces all the players inside to rejoin.
Shutdown();
Sets a global variable that can be accessed with GetGlobal()
. Global Variables are NOT permanent and will be resetted/deleted once the server shutdowns.
// This creates a global named "crazy" which value is 123, then printed.
SetGlobal("Crazy", 123);
var number = GetGlobal("Crazy");
print(number);
You may include variables inside globals, and can even add player instances such as Plr.Name
although it’s recommended to use SetAttribute()
.
// Creates a global named "TheChosenOne" along with a player's name. 50% chance
if (rand(1,2) == 2) {
SetGlobal("TheChosenOne"+Plr.Name, true);
print(Plr.Name+" is one of the chosen!");
}
Gets the value of a global variable and returns it if possible, else nil.
// Assuming the global "LaLa" doesn't exist, prints nil
print(GetGlobal("LaLa"));
// Prints "Hello world!"
SetGlobal("LaLa", "Hello world!");
print(GetGlobal("LaLa"));
Similar to SetGlobal() function although not the same.
// Difference between SetScopedGlobal() and SetGlobal()
SetScopedGlobal("heythere", "hello");
GetScopedGlobal("scope1", "hi"); // This will return nothing (scope doesnt exist)
GetScopedGlobal("heythere", "hi"); // This returns "hello".
GetGlobal("hi"); // This will return nothing.
Similar to GetGlobal() function although not the same.
// Difference between GetGlobal() and GetScopedGlobal()
SetScopedGlobal("heythere", "hello");
GetScopedGlobal("scope1", "hi"); // Returns nothing (scope doesnt exist)
GetScopedGlobal("heythere", "hi"); // Returns "hello"
GetGlobal("hi"); // Returns nothing
Clears a Scope set by SetScopedGlobal().
SetScopedGlobal("heythere", "hello");
GetScopedGlobal("heythere", "hi"); // Returns "hello"
ClearScope("heythere");
GetScopedGlobal("heythere", "hi"); // Returns nothing (scope was cleared)
Returns value
as a string if possible, else nil.
print tostring(500); // Prints "500"
Returns str
as a number if possible, else nil.
print tonumber("25"); // Prints 25
print tonumber("hi"); // Prints nil
Returns the type of value
print typeof("25"); // string
print typeof(500); // number
print typeof(tonumber("60")); // number
Returns the current time.
print tick(); // Will return a different number higher than the one before everytime it's called.
Returns in seconds the time that has passed by ever since the round has started.
Pauses execution of the code for a duration roughly equal to num
. This is useful to create scripts that have a lot of variables being simultaneously created and used as it gives times for those variables to be defined and might fix issues with “var not found”.
print "hi";
wait(2);
print "this is printed 2 seconds after";
Modifies a team’s property. List of valid PropertyNames:
Property | Type of Value | Description |
---|---|---|
BaseHealth | Number | The BaseHealth is the starting health all players from the team will spawn with. |
DisplayName | String | This is the name that displays to others. Even if you change the DisplayName, you will have to use the actual class name for functions. |
Group | Any | Group data of the team. |
GroupName | String | Name of the group the team is in. Default groups are: MTF - CI - GOC - SH - SCP - Class-D - Facility Personnel - Security - Other Groups have an already set teamdata for teams within the group unless the team already has that data specified. For example SCP group makes so teams can’t jump, crouch, etc. But if you make a custom team that is able to crouch and then put it into Group “SCP” it’ll work. |
Faction | String? | Name of the faction the team belongs to. This is independant to Groups. |
Color | Color3 | Color of the team, HEX. |
Vision | Color3 | Color of the vision, HEX (SCP-1507 vision behaviour, vision adds a layer of color on top of the screen) |
NeutralToAll | Boolean? | When loading the team, this sets alliances with every team to neutral |
VestName | String? | Which vest the team spawns with, case sensitive. |
noVisualVest | Boolean? | Does the team not show its vest upon spawning? |
Protection | Number | How much armor does the team spawn with. |
Immunity | Number | How much immunity does the team spawn with. |
WalkSpeed | Number | Starting speed while walking. |
JumpPower | Number | How high the player can jump. |
IgnoreExplosions | Boolean | Makes the team ignore explosions and not get damaged by them. |
IsGhost | Boolean? | Makes the team go through glass and doors. SCP-106 behaviour. |
GhostPenalty | Number? | If ‘IsGhost’ = true and the person goes through doors, GhostPenalty is how much the walkspeed is affected (slows them down). |
NeutralWhenFF | Boolean? | Makes it so killing the same team doesn’t count as teamkilling when FF is on. |
IsHuman | Boolean | Toggles whether the team is a human. |
IsSCP | Boolean | Toggles whether the team is a SCP. |
BodyIsBurnable | Boolean | Toggles whether the body can be burned. Bodies with ‘IsHuman = true’ are burnable by default. |
CanSeeSCPBars | Boolean? | Shows SCP HP bars in the bottom left corner if this is set to true. |
CanManuallyUncuff | Boolean? | Toggles whether the team can uncuff a non-hostile by holding E on them. |
CanCrouch | Boolean? | Changes whether the team can crouch. |
CanSprint | Boolean? | Changes whether the team can sprint. |
CanPickup | Boolean? | Changes whether the team can pick up items. |
CanDrop | Boolean? | Changes whether the team can drop items. |
EscapeClass | String? | Which class does this team become when escaping. |
SpawnImmunity | Number? | How long does spawn immunity last. |
CanSeeHealth | Boolean | Toggles whether the team can see the HP of others when hovering over them. |
StaminaDepletionThreshold | Number? | Minimum stamina before it ‘depletes’. |
StaminaDepletionRecoveryTime | Number? | How long until stamina is usable after depletion. |
MinimumStaminaBeforeSprint | Number? | The minimum amount of stamina for sprinting. |
StaminaGain | Number? | How much stamina the team gets each frame. |
StaminaLoss | Number? | How much stamina the team loses per frame when sprinting. |
MaxStamina | Number? | The stamina cap for the team. |
JumpStaminaCost | Number? | The stamina cost for jumping. |
SprintSpeedGain | Number? | The speed increase when sprinting. Walkspeed + SprintSpeedGain. |
HasNVG | Boolean? | Does the team spawn with NVG equipped? |
HasInfiniteAmmo | Boolean? | Toggles whether the team has infinite ammo without enabling the server-wide infinite ammo setting |
HasInventory | Boolean? | Toggles whether the team has an inventory or not. |
InventoryLimit | Number? | The inventory limit for the team/how many items the team can have in its inventory. |
RemoveBodyParts | String? | Valid options are true “Hands” “Legs” - Basically which bodyparts should be removed. True removes both hands and legs. |
UserCustomization | Boolean? | Toggles adding the equipped P:SCP cosmetics and the player’s face and skin color. |
Faceless | Boolean? | Toggles the team having a face or not. |
Unattackable | Boolean? | Modifies whether this team can be damaged by other players. |
Uncuffable | Boolean? | Modifies whether this team can be cuffed. |
CantContributeToSCPCount | Boolean? | When enabled, the SCP doesn’t count for ‘SCPs killed’, ‘SCP kill reward’ and GOC’s spawn condition. |
SpawnName | String? | Backup spawn location for the team if the team doesn’t have a spawn location (For example custom teams without spawn locations in custom rooms). |
UseSpawnNameOnly | Boolean? | Forces the team to only spawn at the backup spawn locations. |
SpawnText | String | The text shown upon spawning. |
VRSpawnText | String? | Same as SpawnText but different for VR. |
legacyAccess | String? | Valid options are “checkpoint”, SCPs behaviour. |
Channel | String? | The channel the team speaks in. |
PlayerCounterType | String? | It’s the text that shows how many people is alive in the top right corner. Options are "all" - "enemy" and "ally" |
SpawnwaveTimer | String? | Options are “full” “spawnonly” |
CanAttack | Boolean? | Toggles if the team can “melee attack”, SCP-049-2 or SCP-1770-1 or SCP-1507 behaviour. |
CanBreakBreakables | Boolean? | Toggles if the team can break breakables. Needs CanAttack=true. |
AttackCooldown | Number? | How long until you can attack again in seconds. |
Range | Number? | Range of attack. |
Damage | Number? | Damage of attack. |
HasNoClip | Boolean? | Changes whether the team has noclip enabled by default or not. |
HasBypass | Boolean? | Changes whether the team has bypass mode enabled by default or not. |
HasGodMode | Boolean? | Whether the team has GodMode by default or not. |
ShirtColor | Color3 | Modifies the color of the shirt. Use HEX color. |
PantsColor | Color3 | Modifies the color of the pants. Use HEX color. |
Shirt | Number | Modifies the shirt of the team. |
Pants | Number | Modifies the pants of the team. |
DeathReason | String | For custom attacks death reasons. |
AttackType | String | For custom attacks and death effects. Default options are: Decay or 106 - Railgun or 096 - Fire - 173 . Decay and 106 makes the body be decayed. Railgun and 096 makes the limbs to be deattached. Fire burns the body and 173 deattaches the head. You can use custom attack types which can be used for the OnPlayerDamaged event. |
SCP-049 Properties | Type of Value | Description |
---|---|---|
ReviveSpeed | number | Modifies how long it takes for SCP-049 to revive a body (in seconds). |
SCP-457 Properties | Type of Value | Description |
---|---|---|
FireIterations | number | How many times someone gets damaged by the fire. |
FireDelay | number | Delay between each “fire tick” |
StartingFuel | number | The starting fuel SCP-457 spawns with. |
MaxFuel | number | The fuel cap of SCP-457. |
SCP-173 Properties | Type of Value | Description |
---|---|---|
SeenRange | number | The range of attack upon being seen as SCP-173 |
BlinkTime | number | The time it takes to teleport, in seconds. |
BlinkRange | number | How far you can teleport, in studs. |
Please note that this is a very big list. It’s recommended to copy the whole code and paste it in a editor such as Notepad++ by Don Ho for better visualizing.
Example of usage:
// Assuming the team "The Fog" has been created previously
ModifyTeam("The Fog", "GroupName", "Fog");
ModifyTeam("The Fog", "BaseHealth", 550);
ModifyTeam("The Fog", "SpawnText", "Consume them all.");
ModifyTeam("The Fog", "CanAttack", true);
ModifyTeam("The Fog", "CanBreakBreakables", true);
ModifyTeam("The Fog", "Range", 6);
ModifyTeam("The Fog", "AttackCooldown", 0.5);
ModifyTeam("The Fog", "Damage", 10);
ModifyTeam("The Fog", "Death Reason", "Consumed by the fog.");
ModifyTeam("The Fog", "HasInventory", false);
ModifyTeam("The Fog", "CanPickup", false);
ModifyTeam("The Fog", "Uncuffable", false);
ModifyTeam("The Fog", "PlayerCounterType", "enemy");
This makes a basic custom team named “The Fog”. This team preset has no clothing and you will have to put them manually.
When the team is in a group and the group has set data, you don’t need to set data for the team, unless you want the team to have specified data (For example, “Nu-7 Cadet”, is in the “Nu-7” Group, but it has different BaseHealth than the one specified in the Group’s data)
Example of said above:
CreateGroup("Nu-7");
ModifyGroup("Nu-7", "BaseHealth", 120);
NewTeam("Nu-7 Cadet", "HEX COLOR HERE");
ModifyTeam("Nu-7 Cadet", "GroupName", "Nu-7");
// Right now, the Nu-7 Cadet should have 120 BaseHealth
ModifyTeam("Nu-7 Cadet", "BaseHealth", 110);
// Although the Nu-7 group has a BaseHealth set, Nu-7 Cadet now has too.
This returns the value of a team’s property. Property must be any of the properties listed above in the ModifyTeam()
function. (Click it)
print ("The fog's base health is: "+tostring(GetTeamProperty("The Fog", "BaseHealth")));
// This should print "The fog's base health is: 550"
This function returns a table with all the existing classes.
var teams = GetTeamList();
var humanteams = createtable();
var x = 0;
for (var a = 1; a <= #teams; a = a + 1) {
x = a;
var team = teams[x];
if (GetTeamProperty(team, "IsHuman") == true) {
tableinsert(humanteams, team);
}
}
Gives a team a default-set ammo when spawned. Valid AmmoName
s are:
Explosive
HeavyCaliber
MediumCaliber
SmallCaliber
Shells
ModifyTeamAmmo("Class-D", "MediumCaliber", 15);
// This gives the Class-D team 15 Medium Caliber ammunition.
Gives a team a default-set item in inventory when spawned. Position
must be a number and will be where the item will be located in inventory. ItemName
must be any item within the game.
ModifyTeamItems("Class-D", 1, "Class-D Keycard");
// This makes the Class-D team have a Class-D Keycard when spawned.
Even if there are no items in a position and you use a higher number, the item just go to the lowest position possible.
Example for better understanding:
ModifyTeamItems("Class-D", 1, "Class-D Keycard");
ModifyTeamItems("Class-D", 4, "Flashlight");
Class-D will have a Class-D Keycard again, but this time there’s a gap between positions.
The flashlight will just go all the way down to the second position.
You can also randomize between items for a single position.
ModifyTeamItems("Class-D", 1, "Class-D Keycard", "Flashlight", "nothing", "Grenade", "Medkit", false);
// This will randomize class-d's first item slot.
// False means no item.
This adds or removes an highlight a Team has over another Team, highlighting everyone in the Target Team.
Option | Description |
---|---|
ally |
Adds a green highlight. |
enemy |
Adds a red highlight. |
neutral |
Adds a white highlight. |
nil |
Removes any highlights. |
Makes SCP-173 have all Class-Ds highlighted as red. Happy snapping!
ModifyTeamHighlights("SCP-173", "Class-D", "enemy");
Adds a green highlight between every SCP-049-2.
ModifyTeamHighlights("SCP-049-2", "SCP-049-2", "ally");
Gives a team an accessory. Name
can be anything and it doesn’t have to be the accessory’s name. It can be for example “patchacc”.
AccessoryID
must be a valid asset id of an accessory.
There can’t be two accessories with the same name for a single team. It’ll error.
AddTeamAccessory("Fog", "Glare", 10721963880);
// This gives the team "Fog" an accessory named "Red Eye Glare".
// If you try to do it again with the same name, it'll error.
AddTeamAccessory("Fog", "Glare", 10722274383);
// This time it tries to give the team an accessory named "White Eye Glare", but it'll error.
Removes a team’s accessory as long as it’s a valid accessory set by AddTeamAccessory()
.
RemoveTeamAccessory("Fog", "Glare");
Clears the cache of a team’s appearance/accessories. Basically it resets whatever the team is wearing, and could be used to fix for example ghost accessories.
ClearTeamAppearanceCache("Fog");
Toggles the ability for team1
and team2
to attack each other.
SetTeamCanDamage("MTF Commander","MTF Cadet",true); // commander now damage cadet independent from the friendly fire policies
Resets the default attack behavior of team1
and team2
RemoveCanDamage("MTF Commander","MTF Cadet");
Creates a new team with the name TeamName
and the color StrColor
.
StrColor
must be either a BrickColor or a HEX color.
NewTeam("TeamName","Fog");
Removes an existing team with the name TeamName
.
DeleteTeam("MTF Cadet"); // MTF Cadet will no longer exist. (You cannot delete core teams).
Returns boolean whether team TeamName
exists or not.
if (DoesTeamExist("MTF Trainee")) {
Announce("Class exists!");
} else {
Announce("Class doesn't exist");
}
// Announces "Class exists!" if "MTF Trainee" exists. Either it doesn't.
Changes if a class can attack another class.
// Options for value are Friendly, Hostile, & Neutral.
// you can also ignore the value and put true for Friendly, & false for Hostile.
SetAlliance("SCP-049-2", "SCP-049-2", false); // Allows SCP-049-2's to attack one another.
SetAlliance("MTF Cadet", "GOC Private", "Friendly"); // MTF Cadet & GOC Private are now Friendly.
Reverts two classes alliances back to their default state.
ResetAlliance("MTF Commander", "MTF Cadet");
Returns the alliance of both teams.
print GetAlliance("MTF Commander", "MTF Cadet");
// Usually this should print friendly unless you modify the team alliances.
Groups work the same as their team-only counterpart but on the groups instead.
Creates a group with the name GroupName
which can be then used by teams using ModifyTeam()
and modified with ModifyGroup()
CreateGroup("Fog");
ModifyTeam("The Fog", "GroupName", "Fog");
// Since Fog group exists, any teams can use it now.
Removes a group incase it exists.
// Assuming the "Fog" group exists
RemoveGroup("Fog");
Modifies a group’s property. It uses the same as team properties, but it applies to every team within the group as long as the team doesn’t have that property specified within its data (Also known as using ModifyTeam()
)
ModifyGroup("Fog", "BaseHealth", 550);
// All teams in the group "Fog" will have a BaseHealth 550
// Of course assuming the teams within this group don't have BaseHealth set.
Returns the value of a group’s property if possible, else nil.
var TheProperty = GetGroupProperty("Fog", "BaseHealth");
if (TheProperty) { // Checks if it exists
print("The Fog group's BaseHealth is " + tostring(TheProperty));
}
Sets the alliance between both groups to State
.
Option | Description |
---|---|
friendly |
Makes both groups friendly, being unable to attack each other or prevent winning. |
hostile |
Makes both groups hostile. |
neutral |
Makes both groups neutral. |
true |
Works the same as friendly , makes both groups friendly. |
false |
Works the same as hostile , makes both groups hostile. |
Makes the group “Fog” and the SCPs friendly.
SetGroupAlliance("Fog", "SCP", "friendly");
Returns a table containing all the groups.
var groups = GetGroupList();
var x = 0;
var mygroups = tablecreate();
for (var a = 1; a <= #groups; a = a + 1) {
x = a;
var group = groups[x];
if (GetGroupProperty(group, "CanAttack") == true) {
tableinsert(mygroups, group);
print(group + " can attack others");
}
}
Returns a table containing all teams within a group.
Starts the nuclear warhead.
Player?
must be a player and it’ll make the player start the nuke for the nuke events.
Force?
is a boolean and if it’s enabled, even if nuke isn’t activated, it will start it. Else if false
, it’ll only start the nuke if its activated.
Sets the state of the nuke, enabling or disabling it.
State
must be a boolean. If false, it’ll stop the nuke.
Force
is also a boolean and if enabled it will ignore the "waiting"
period.
Stops the nuclear warhead.
Player?
must be a player, and it’ll make the player stops the nuke for the nuke events.
Force?
is a boolean and if enabled, it will stop the nuke even at the last 10 seconds.
Returns a number as the time remaining until explosion. If nuke is not enabled, it will always return 0
.
Returns a boolean, whether the nuke has been already detonated.
Returns a boolean, whether the nuke detonation protocol is running.
Returns a boolean, whether the nuke is ready to be started.
Returns a copy of the string after running it through the chat filter.
Returns a table with the string split into parts based on the defined separator character(s).
This will return a table containing every word including symbols next to them.
After using the function, this will return a table containing:
"Hello", "this", "is", "not", "a", "split", "string!", "for", "now"
var splitstring = strsplit("Hello, this is not a split string! for now.", " ");
This will return a table with 3 strings:
"hi", "", "bye"
var splitstring = strsplit("hi||bye", "|")
Receives zero or more integers and returns a string with length equal to the number of arguments that has each character has the internal numerical code equal to its corresponding argument.
print char(72, 101, 108, 108, 111); // prints "Hello"
Searches for any occurrence of the pattern in a string. Very similar to strfind but searches inside words.
The string to search for a pattern.
The pattern to look for inside a string.
Optional parameter, used for indicating where to start searching.
This code will set a player’s health to 120 if they are any class that contain the word "MTF"
inside of them.
if (match(Class, "MTF")) {
SetMaxHealth(Plr, 120);
SetHealth(Plr, 120);
}
Returns a sub-string that is a portion of the original string.
The string to retrieve the sub-string from.
A number, indicating in what position the sub-string should start within the string. If you didn’t understand, basically if you have a string that is 10 characters long “abcdefghij” and you specify 5
, the sub-string will start from the fifth character (in this case, e
).
The opposite of the StartIndex argument and specifies in what position the sub-string should end at.
This snippet will print "efghij"
. It extracts a substring from the original string, which is between the fifth and tenth character, resulting in "efghij"
print(sub("abcdefghijklmnopqrstuvwxyz", 5, 10)); // prints "efghij"
Searches for any occurance of a pattern within a string.
The string to be used to search a occurrance of a pattern within it.
The pattern to look for within a string.
This parameter will be used for indicating where to start searching. If you provide 1
, it will start searching from the first character.
This parameter disables searching for a pattern inside words.
For example, if you’re searching for something such as “CI” in a class name, it won’t check if there’s “CI” in “Lieutenant”, or “Commander”, etc.
This code will only give the player a radio if they are any CI class.
if (strfind(Class, "CI", 1, true)) {
GiveItem(Plr, "Radio");
}
Returns a formatted string.
Please view this site for more information.
This code will print a player’s name and “is SCP-096 and has 2951.4 HP!” after it.
print strformat("%s is %s and has %.1f HP!", "Player", "SCP-096", 2951.492);
Returns a copy of the string with all characters lowercase.
print lower("HeLLo WorLD!"); // Prints "hello world!"
Returns a copy of the string with all characters uppercase.
The string to be modified with all characters uppercase.
The following code will print “HELLO WORLD!”
print upper("HeLLo WorLD!");
This function will return a copy of a string, which all (or up to a certain limit) occurrences of a pattern are replaced with the provided replacement.
This argument will be the string which is going to be used to return a copy of it, replacing patterns within the string.
This argument is going to be the pattern that will be replaced by the third argument Replacement
.
This argument will be the replacement of all the occurences of a pattern within the string, depending if a limit is provided or not.
The replacement can be different datatypes, each used differently to determine the actual string.
By using a string… | The pattern is replaced with the string directly. |
By using a table… | The string that matched the pattern is looked up in the table as a key, and the value (a string) is the one that replaces it if it exists. |
This argument specifies the maximum number of replacements to make. For example, if you provide 2
for this argument, this function will stop after 2 replacements.
This code will print a player’s name and “is sus” after it. (For example: “Fernando121231 is sus”)
{s} is the pattern to be replaced, and Plr.Name
is the replacement. Since no limit was provided, all {s} occurrences will be replaced.
print gsub("{s} is sus", "{s}", Plr.Name);
Returns the same string from the first argument, which is repeated as many times as the second argument specifies.
print strrep("hi!", 5); // "hi!" is the string, 5 is the amount of repeats.
// Will print "hi!hi!hi!hi!hi!"
Returns a copy of a string with all characters reversed.
The string to be reversed.
This code will print "!desrever ton si txet sihT"
as it’s a reversed copy of "This text is not reversed!"
print strreverse("This text is not reversed!");
This function creates a table with a similar behavior of creating a table using classes.
ArraySize
is a number and it’s a preallocated array size, although it’s not that useful.
var mytable = createtable();
mytable[1] = "yes";
print mytable[1]; // prints "yes"
This function inserts a value at the end of a table.
The table where a value is going to be inserted into.
Number. It’s optional and if specified every value starting from the index to the end of the table is pushed back by 1, then the value is inserted at the index.
The value can be any, and it’s the value that is going to be inserted into a table.
This function removes a specific value from a table and returns it, or else removes the last value from a table and returns it.
The table where a value is going to be removed and returned.
A number. It’s optional but if it’s specified it removes the value from that given position within the table and moves next values back to fill the gap
This will print 1234
, removing the value "i will be removed"
and moving the third value to the second.
var mytable = createtable();
mytable[1] = "hi";
mytable[2] = "i will be removed";
mytable[3] = 1234;
tableremove(mytable, 2);
print mytable[2]; // prints 1234
This will print "hi how are you"
, since the last value was removed and only the first and second values remain.
var mytable = createtable();
mytable[1] = "hi";
mytable[2] = "how are you";
mytable[3] = "i will be removed";
tableremove(mytable, 3);
print tableconcat(mytable, " "); // prints "hi how are you"
This function clears a table.
In this scenario, the table would stop existing.
var mytable = createtable();
mytable[1] = "hi";
print mytable[1];
tableclear(mytable);
Transforms a table into a string.
The table to be concatenated.
A string. It’ll be the separator between each table value.
A number. It’s a position and specifies where the concatenation should start at.
A number. It’s a position and specifies where the concatenation should end.
This code will print "hi this is a table"
.
var mytable = createtable();
mytable[1] = "this wont be used sadly";
mytable[2] = "hi";
mytable[3] = "this is";
mytable[4] = "a table";
print tableconcat(mytable, " ", 2); // "hi this is a table"
This function can be used for iteration and gets something from a table. It gets the next key after the current one.
This code will print “how are you”, as “greetings” is the next key after 3
.
var mytable = createtable();
mytable["greetings"] = "how are you?";
mytable[1] = "something";
mytable[2] = "something again";
mytable[3] = "hi";
print tablenext(mytable, 3); // "greetings"
Same as the example before, but prints “hi” as 3 is the next key after 2
var mytable = createtable();
mytable["greetings"] = "how are you?";
mytable[1] = "something";
mytable[2] = "something again";
mytable[3] = "hi";
print tablenext(mytable, 2); // "hi"
https://create.roblox.com/docs/reference/engine/classes/Instance
// Creates a instance of a part
var cube = Instance.new("Part");
cube.Shape = Enum.PartType.Block; // Determines the shape
cube.Position = Plr.Position; // Where it spawns
cube.Anchored = false; // If it can be moved
cube.Parent = workspace; // Spawns in the cube
The Hook Functions are based on the lox language from the book Crafting Interpreters written by Robert Nystrom. Some code examples listed here are either slightly modified or direct copies from the book.
https://craftinginterpreters.com/