Classes - joric/supraland GitHub Wiki
This is the list of the original Supraland classes from UE4 data files. Also see Scripts.
Jumppads
Jumppad_C
Property | Type | Description |
---|---|---|
Velocity | vector3 | 3d velocity. Overrides "RelativeVelocity" (apparently only when AllowStomp=true). |
RelativeVelocity | float | Scalar velocity, always presents. Used for newer pads that don't have 3d velocity. |
RelativeVelocity? | bool | Usually false if set. Some pads don't have this flag and still use 3d velocity. |
DisableMovementInAir | bool | Disables steering. Sets jumppad to blue, if false. |
AllowStomp | bool | Allows stomping at start (also in mid-air, to drop down). Sets jumppad to blue if true. |
AllowTranslocator | bool | Whether its possible to throw a translocator ball |
CenterActor | bool | Center the projectile for precision |
PreviewPath | bool | Path preview (UE editor stuff) |
PreviewPathTime | float | Time for PreviewPath in seconds |
Is Activated? | bool | If activated (for initially disabled launchpads) |
Historically there are a few types, the legacy stuff uses a 3d velocity, the newer ones a direction and velocity (discord).
Red and blue jumppads
From the game: Orange jumppads take mid air control from you, blue ones let you steer, jump or stomp.
Jumppads are red by default. Apparently, either AllowStomp=True or DisableMovementInAir=False (or both) turn jumppad blue.
The first Supraland launchpad right after the village gates is blue because it has AllowStomp=True but it doesn't allow steering.
Jumppad target
There is no target.
I've checked the map around some of the notable landing points, there's nothing indicating target points. My guess is jump pads show a parabola curve in editor so you can adjust the landing point visually (varying velocity parameters of the pad) but there's no explicit target (confirmed).
Having a velocity and a direction combined as (vx, vy, vz) you can launch a projectile using fixed timestep:
// vx - no change
// vy - no change
vz -= g * dt
x += vx * dt;
y += vy * dt;
z += vz * dt;
It's impossible to guess where the projectile lands without a collision geometry. Latest Scripts collect marker locations in a KDTree for an improvised heightmap and use 3 points closest to a moving projectile as a collision plane to calculate z-coordinate of the fall.
Mass doesn't affect the trajectory, but g (~9.8) needs altering, probably because of the crazy scaling (the player is 0.2mm or so and the huge kid is like 20cm). Something like g * 95 works.
Example:
{
"Type": "Jumppad_C",
"Name": "Jumppad96",
"Properties": {
"Velocity": {
"X": 4800.0,
"Y": 250.0,
"Z": 3500.0
},
"RelativeVelocity": 8700.0,
"AllowTranslocator": false,
"PreviewPathTime": 15.0,
"CenterActor": true,
"Is Activated?": true,
"DisableMovementInAir": false,
}
}
You can get proper launcher direction from its matrix (column 3). Some jumppads don't have compound velocity, oddly Jumppad63/Supraland doesn't have any velocity at all (must be default).
This is red one and blue one accordingly:
"name": "Jumppad79",
"Velocity": {
"X": 0.0,
"Y": 0.0,
"Z": 1650.0
},
"RelativeVelocity": 1000.0,
"name": "Jumppad266",
"Velocity": {
"X": -2400.0,
"Y": -5200.0,
"Z": 2100.0
},
"RelativeVelocity": 5600.0,
"AllowStomp": true,
"PreviewPath": true,
"PreviewPathTime": 6.0,
More examples, the choice of vector and scalar is looked up in the Supraland community map (it shows jump targets).
Jumppad2_49 (uses vector velocity):
"RelativeVelocity?": false,
"Velocity": {
"X": 2550.0,
"Y": 5200.0,
"Z": 2100.0
},
"RelativeVelocity": 6000.0,
"AllowStomp": true,
"PreviewPath": true,
"PreviewPathTime": 6.0,
Jumppad97 (uses scalar velocity):
"Velocity": {
"X": 4800.0,
"Y": 250.0,
"Z": 3500.0
},
"RelativeVelocity": 8700.0,
"AllowTranslocator": false,
"PreviewPath": true,
"PreviewPathTime": 15.0,
Jumppad_266 (uses vector velocity):
"Velocity": {
"X": -2400.0,
"Y": -5200.0,
"Z": 2100.0
},
"RelativeVelocity": 5600.0,
"AllowStomp": true,
"PreviewPath": true,
"PreviewPathTime": 6.0,
The RelativeVelocity?
flag doesn't seem to matter (there are pads that use vector without that, e.g. Jumppad_266).
For now it seems that the only property reliably indicating legacy pad is AllowStomp
(3d Velocity is never ignored if it's set).
Pipes
Pipe teleports mostly use PipesystemNew_C
and PipesystemNewDLC_C
classes, Pipesystem_C
used just once.
Pipesystem_C
Has multiple subclasses, such as PipesystemNew_C
and PipesystemNewDLC_C
.
Example (PipeCap11 and Secret_TeleportPipe1 are the ends of the pipe):
{
"Type": "PipesystemNew_C",
"Name": "PipesystemNew39",
"Outer": "PersistentLevel",
"Properties": {
"OtherPipe": {
"ObjectName": "Secret_TeleportPipe1"
}
}
"Pipe": {
"Outer": "PipeCap11"
}
}
"OtherPipe" may be substituted with "otherPipeInOtherLevel", e.g.
"Type": "PipesystemNewDLC_C",
"Name": "Area1_FastTravelPipe",
"Outer": "PersistentLevel",
"Properties": {
"otherPipeInOtherLevel": {
"AssetPathName": "/Game/FirstPersonBP/Maps/DLC2_Complete.DLC2_Complete",
"SubPathString": "PersistentLevel.PipeToArea1"
},
}
PipeSystemBuilder_C
Some pipes (e.g. "NODE_AddChildActorComponent-1_PipesystemNewDLC_C_CAT_3" do not have "other pipe")
They are initialized in pipe system builders, PipeSystemBuilder_C
(not supported yet).
PipeCap_C
A pipe end that can be marked as activated in the save file. Not all pipes have PipeCap_C, some pipes are permanently open and don't have PipeCap_C at all, some depend on level geometry. I could not find a reliable link of a pipe system to a pipe cap except distance, so script just finds a cap nearest to the Pipesystem entity within a small range.
The load saved game is fairly broken for pipes, particularly in SIU. Turns out found status is entirely based on the Pipecaps, as one might expect, which works fine for SLC/SL but for SIU the pipecaps aren't added to the "ThingsTo" lists. However, they are added to the ActorSavedData (and ActorSavedDataStructs) so it's possible to write a regexp which explicitly searches for the set of them, bit of a hack but it works.
Misc
Relay_C
Can invoke actions indirectly using "ActorsToOpenOnOpen". E.g. "ValveSlot_2" in SIU lists relay named "Relay_OpenFastTravelSecretLavaAreaToBeamTutorial" in actors, then this relay opens a couple of pipe caps.
PlayerMapActor_C
Since SIU, there are MapWorld* nodes to store world size. It's used to scale the interactive map.
"Type": "PlayerMapActor_C",
"Name": "PlayerMapActor_2",
"MapWorldCenter": {
"X": 0.0,
"Y": -19000.0,
"Z": 10000.0
},
"MapWorldSize": 147456.0,
"MapWorldUpperLeft": {
"X": -73728.0,
"Y": -92728.0,
"Z": 10000.0
},
"MapWorldLowerRight": {
"X": 73728.0,
"Y": 54728.0,
"Z": 10000.0
},
"CaptureHeight": 30000.0,
Here it is for all three games. I don't remember where I got data for the games before SIU, because other games apparently don't have MapWorld* nodes. If you know the origin of those numbers, let me know.
"sl": {
"MapWorldCenter": { "X": 13000.0, "Y": -2000.0, "Z": 0.0 },
"MapWorldSize": 175000.0,
"MapWorldUpperLeft": { "X": -74500.0, "Y": -89500.0, "Z": 0.0 },
"MapWorldLowerRight": { "X": 100500.0, "Y": 85500.0, "Z": 0.0 },
},
"slc" : {
"MapWorldCenter": { "X": 25991.0, "Y": -16.0, "Z": 0.0 },
"MapWorldSize": 90112.0,
"MapWorldUpperLeft": { "X": -19065.0, "Y": -45040.0, "Z": 0.0 },
"MapWorldLowerRight": { "X": 71047.0, "Y": 45072.0, "Z": 0.0 },
},
"siu": {
"MapWorldCenter": { "X": 0.0, "Y": -19000.0, "Z": 10000.0 },
"MapWorldSize": 147456.0,
"MapWorldUpperLeft": { "X": -73728.0, "Y": -92728.0, "Z": 10000.0 },
"MapWorldLowerRight": { "X": 73728.0, "Y": 54728.0, "Z": 10000.0 },
},
TriggerVolume_C
Many of them, multi-purpose. Renamed to BP_TriggerVolume_C in SIU.
In SIU caps are often activated indirectly, e.g. for the first pipe in the pipe house, save file lists "BP_TriggerVolume_OpenA1Pipe" of BP_TriggerVolume_C in "ThingsToActivate". The trigger opens both caps in trigger actions ("openWhenPlayerEnters"). So to mark the pipe as available on the client we would have to add triggers to the map and access trigger actions.
Looks like we hit UE4Parse limitation here, e.g. BP_TriggerVolume42_524 doesn't have any actions in UE4Parse (UniqueActorBeginOverlap is null) but has invocation list in FModel. Looks like I'd have to move to FModel. Sadly those peeps didn't even bother to make a command line tool. Related issue: https://github.com/MinshuG/pyUE4Parse/issues/22
MinecraftBrick_C
Property | Type | Description |
---|---|---|
HitsToBreak | int | How many hits to break |
bObsidian | bool | If obsidian |
BrickType | enum | Brick type, EMinecraftBrickType::NewEnumeratorXX |
Lift1_C
Vertical lifts
Anvil_C
It looks like in SL all anvils are actually MetalBall_C with anvil model. Probably late addition. In SIU it's Anvil_C. Can be determined by "Mesh?" property (it's set to "Anvil").
RingRusty_C
Some RustyRing_C objects are pickaxes in SL. Specifically RustyRing10 - 16. Rather like some MetalBall_C are Anvils. I could not find a reliable way to tell them apart from rings.
Chest_C
Property | Type | Description |
---|---|---|
Coins | int | How many coins to hold |
Spawnthing | object | ObjectName property (string) of the object contains spawn class |
Coin_C
Property | Type | Description |
---|---|---|
Value | int | Starting from SIU, probably means coin value |
bDoesntRotate | bool | Animation |
LotsOfCoinsX_C
There's no "coin stash" entity, but there are "LotsOfCoinsX_C" classes with X varying from 5 to 200.
BP_Buy*_C
Various BP_Buy*_C classes, used as shop items. Have Cost and PriceType properties.
Property | Type | Description |
---|---|---|
Cost | int | Cost |
PriceType | enum | EPriceType::NewEnumerator5 - scrap, EPriceType::NewEnumerator6 - bones |
Button_C
Has various subclasses, such as SmallbuttonMultipleActors_C
, Smallbutton_C
, ButtonFloor_C
, SmallbuttonQuickOnoff_C
, SmallbuttonFlipFlop_C
, SmallbuttonWhile_C
, SmallbuttonOpenClose_C
, SmallbuttonOnceMultipleActors_C
, BigButton_C
, PedestalButton_C
, Smallbutton2_C
, BallButton_C
, etc.
Has mulitple actions: Actor
, Actors
, ActivateActors
, Actor To Move
, More Actors to Turn On
, ActorsToActivate
, Actors to Open
.
There's an interesting mechanic regarding moving the things, actor is a special object, MoveMesh_C
which itself has property Actor To Move
with another actor, local transform property, and time. Some buttons do it directly with Actor To Move
. Similarly with Glowline_C
actor, it links to another class in its own Actors To Enable/Disable
property, so there can be multiple levels of hierarchy and actions can be chained together.
QuestActivator_C
May be tied to button or a box volume trigger, activates quests. Contains quest prompt. Example:
{
"Type": "QuestActivator_C",
"Name": "QuestActivator_2",
"Outer": "PersistentLevel",
"Properties": {
"QuestText": {
"Namespace": "",
"Key": "C9CC6F6C498B13F11B4FF9BA14723C76",
"SourceString": "Go to the king of Blue Ville!"
},
}
},
EnemySpawn*_C
Enemy spawners, EnemySpawn1_C, EnemySpawn2_C and EnemySpawn3_C are wooden, stone and volcano accordingly. There's an issue with them when we mark it found, e.g. volcano spawners ("EnemySpawn3_C") are activated the first time they open, in the "ThingsToActivate" list, but then, when the player stomps on them and destroys them, they're added to the "ThingsToOpenForever" list, so it's absolutely required to check what list they are in.
Juicer_C
Only found in SL. Spawns things that are related to the player properties (handled by the game saving code).
- Juicer2 (red) spawns BP_DoubleHealthLoot_C, that sets PlayerDoubleHealth (see TriggerAfterDoubleHealth)
- Juicer3 (green) spawns virtual _BuyHealth+10_C, that sets PlayerDrankHealthPlusJuice (see TriggerAfterHealthPlus)
- Juicer_286 (yellow) spawns BP_A3_StrengthQuest_C, that sets PlayerStrong (see TriggerAfterStrong)
Neither BP_DoubleHealthLoot_C nor BP_A3_StrengthQuest_C get marked in the save file so we can't use those directly. But we can mark juicers using related player properties (save file sections). Example code:
const propertyMap = {
PlayerDoubleHealth: "Map:Juicer2",
PlayerDrankHealthPlusJuice: "Map:Juicer3",
PlayerStrong: "Map:Juicer_286"
}
// when marking items from sections
if(o.name && propertyMap[o.name]){
Settings.map.markedItems[propertyMap[o.name]] = true;
}
Door*_C
Various doors, where applicable. Usually triggered via actor links. Some doors are not individual classes but rather StaticMeshActor (e.g. "BlueGlassDoor6" in SIU), there are thousands of StaticMeshActors so the actual doors only can be identified by meshes or by actor relations.