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.