Tutorial: Rocket Poop (buff)

From ARK Modding Wiki
Jump to navigation Jump to search


Introduction

Greetings, fellow modders!

The theme of this modding competition was to create a “wacky, ridiculous buff.” Finally, my time has come! I decided that what I really missed about ARK was the ability to do the famous cartoony “double-jump” that Mario and many other video game characters have been able to do for decades. So, since real physics have already been thrown out the window, the real question became “How do I make this fit in the ARK universe?” – and the answer was simple: Add poop. Thus, the “Rocket Poop” buff was born! When this buff is enabled, pressing the poop key will rocket-propel a stream of poop out of your butt so fast, that you’ll take to the air in what can only be described as the world's first biological jetpack. Be warned! This will quickly empty your stomach/bowels and cause you to starve if used too much.

The Plan!

  • Make the “Rocket Poops” buff, with the following effects, when the player pushes the poop key:
    • Capture the player’s “poop key” command.
      • Keep boosting if the player holds the "poop key" down.
    • Enable a flaming poop particle emitter at the players butt (PlayerPawn’s “PoopSocket”).
    • Play a pooping/flaming sound.
    • Propel player upwards.
      • Make sure they don’t go too fast.
      • Allow player to navigate in mid-air, by factoring in the player’s input.
    • Reduce the player’s food stat (pooping requires food).
      • Subtract from the players health if they continue to poop on an empty stomach.
  • Make a consumable item called “Rotten Meat”, which give the “Rocket Poops” buff when eaten.

Setting up the “Rocket Poop” Buff

Create a blueprint called “PrimalBuff_RocketPoop” which is parented to “Primal Buff”.

Next, open the “PrimalBuff_RocketPoop” and click on the “Defaults” tab at the top, and change the following properties:


CxLJ1oP(1).png


These settings will allow the buff to last for 5 minutes (300 seconds), and also detail when/how the buff can be activated. The name, description, icon, and duration can be easily changed if you want to modify the look/feel of the item. For example, you may want to make this item look like a potion, or a magic curse, etc. It also has flags that prevent it from being used on a dino, and it is treated as a disease. And most importantly, the "Use Buff Tick Server" and "Use Buff Tick Client" have been checked -- more on that later.

Note: We will be revisiting this buff to add all the remaining logic and functionality.

But first, we need to create a consumable that will allow players to activate our buff. This will also be very helpful when testing the buff in the devkit, because this consumable can be spawned and used. For even easier testing, add the buff to the “Additional Default Buffs” array in your mod’s PrimalGameData file, and the buff will automatically appear every time you start the PIE (“Play in Editor”).

Setting up the “Rotten Steak” Consumable

To do this, create a new blueprint called “PrimalItemConsumableGeneric_RottenSteak” with “Primal Item Consumable Generic” as its parent.

Open your new “Rotten Steak” primal item and modify the following values to customize it to your needs:


TBHQXWr(1).png


Again, feel free to change the icons or descriptions to whatever you’d like. I made the recipe require 1x spoiled meat, just because that was an easy resource, and it fit thematically.

Your Rotten Steak is done! Now you can spawn it in and use it to test your buff.

Example spawn code (your path/names will probably vary): Admincheat giveitem “Blueprint'/Game/Mods/RocketPoop/Consumables/RottenSteak/PrimalItemConsumableGeneric_RottenSteak.PrimalItemConsumableGeneric_RottenSteak'” 20 0 0

Setup Assets

Before we get too far into our graph code, we need to setup a few assets that our mod will need.


"Rocket Poops" particle emitter

For this emitter, I started with a copy of the flame-thrower's main flame-thrower effect, called "Flamethrower_PS".

From this base, I disabled the larger flames and smoke, and angled the remaining particles 180 to point them downwards (since our thrust is always shooting down).

I then added a new mesh emitter, which will spawn human poops, shoot them downwards, and gives them gravity and collision so that they can skip/bounce after hitting something solid.


BqxWjUA(1).png


Tweaking particle effects is slightly outside the scope of this tutorial, but feel free to download the source code for this mod and look at the values/options I've setup for yourself.

There's also a great UE4 video that goes through particle effects in great detail, if you want to understand how they work: Intro to Cascade: Creating a Sprite Emitter | 04 | v4.2 Tutorial Series | Unreal Engine

However, in order for your particle emitter to actually use the poop mesh, we have to copy the "MIC_HumanPoop" material, and enable "Used with Mesh Particles", like so:


Qfrr2WF(1).png


You'll also need to copy the "SM_HumanPoop", and apply this new material to it. I recommend keeping these files in an "Assets" folder within your mod, and renaming the files to include the mod name, such as "MIC_RocketPoops_HumanPoop_Particle" and "SM_RocketPoops_HumanPoop", so that they're easily searchable if you need to reference them later -- and you won't get them confused for the base-game versions.

"Rocket Poops" looping Poop Sound Cue

Next, we need sound. As you would expect, you can reuse the vanilla "Flamethrower_Start_Cue" loop without any alterations.

However, the base-game "Poop_Cue" only plays a single poop sound, and it's highly irritating to play that too frequently. So let's setup a custom looping sound cue.

Copy the "Poop_Cue" to your assets folder, and add the following nodes (feel free to tweak as-needed):


RUUoQUG(1).png


For my version, I modulated the pitch down to avoid the loud/squeaky noises, and I put a delay of 0.5 to 1.0 seconds to prevent the effect from being overly annoying.

And that's it! You've now got all the assets you'll need to do this little mod.


Add the "Rocket Poop" Buff Components

Now that we have our custom assets and the Rotten Steak item setup, we need to add a few base components to the “Rocket Poop” buff, which the logic can reference later. Head back to your “PrimalBuff_RocketPoop” blueprint and open it up. Once open, click on the “Components” tab on the top right.

Here, you'll need to add a particle emitter and two audio emitters (for the flames sounds, and the poop sounds), like so:


BytiVIO(1).png


Note: It's important that all three of these components be changed so that "Auto Activate" is left unchecked. This means that they won't be playing when the buff first loads, leaving us the freedom to manually activate/deactivate them when the player presses the "poop key" later on.

Add the “Rocket Poop” Buff Graph Logic

Next, click on the "Graph" tab of your buff and pull up the Event Graph.

The very first thing we’ll need to do is setup our Event Begin Play ("EBP") event, to handle some standard buff start-up house-keeping for us. I've divided the code up into a sequence of four sections of code, so that the nodes are more readable, and so that each piece will be easier to discuss.

Note: The small delay after Event Begin Play is a common method used to help ensure that everything has been initialized correctly and that the logic is ready to execute. Without the delay after Event Begin Play, players will often encounter odd bugs which are hard to troubleshoot.


Helhpmf(1).png


Event Begin Play: Re-Assign Owner

"Buff" actors have a long and sordid history of detaching from their target whenever the user logs out. So as a best practice, we'll re-assign the owner when the buff starts up.


681oHuD(1).png


Event Begin Play: Enable Keyboard Input

By default, the buff actor will ignore input events (such as keypresses). In order to intercept and utilize the "poop key" event, we'll need to enable the client-side input (and verify that it's valid).


SBqDdmQ(1).png


Event Begin Play: Attach to Poop Socket

For the sake of ease-of-use, and because it makes me laugh, let's go ahead and attach this "RocketPoop" buff to the player's PoopSocket on the player's skeletal mesh. This is the reference location that the game uses when spawning turds, so we might as well use it too. This allows all future effects/emitters follow the location of the player's butt as it's moving, making life easy for everybody.


LIZKUoA(1).png


Event Begin Play: Setup Variables

When working with large graphs, it's often desirable to store frequently used references in variables so that you can easily use them again later, without running messy wires all over your graph.

In this case, we're going to setup the Owner Actor (the player), the Primal Character (the player, avoids future casts), the Pawn (the player's pawn), and the pawns Movement Component.


HYGS7Bo(1).png


Huzzah! You're done with the Event Begin Play logic. Now to get into the real fun!


Capturing the "Poop Key" press and release

When working in the Unreal Engine, it’s critical to always pay attention to where your code is being executed – either on the local client, or on the server. You will also have to pay close attention to data replication, which handles the transmission of data from the server to the clients.

In our case, we're using "Input Action" events (keypresses) -- and these input actions always execute on the client. In order to execute the buff logic, these keypresses must be transmitted to the server. To do that, create two custom server-side events: One to start pooping, and one to stop. We will also set the "Pooping Active" boolean client-side as well. (This variable is never replicated, because it doesn't need to. The server will update it's own copy of this variable as well, as we'll see later.)

Create custom events called “ROS_EnableRocketPooping” and “ROS_DisableRocketPooping”, with the following settings:


HtNuCVQ(1).png


Note: Many mod authors choose to write "ROS" (Run on Server), "ROC" (Run on Client), or "MULTICAST" at the beginning of their custom functions, to remind themselves where the code is being executed, and to make the nodes easier to read/understand.

Note: It’s important to setup this input action to “consume” the input, which will prevent your character from also trying to poop the normal way, which would fill your screen with lots of “not ready to poop yet” messages.

These ROS events will set the "Pooping Active" boolean on the server-side, and spawn a multicast emitter that will spawn the particle emitters and play the desired sounds. This is multicast so that all players in range will experience the event (see the stream of fire/poop, and hear the pooping sounds).

Note: Particle emitters and sounds do not need to be "played" by the server, since there's no human at the server to experience them. If you're having trouble interacting with your emitters, remember that the server needs to spawn one for each of the clients in order for everyone to see it.


RKHEwRN(1).png

Toggle Sounds/Particles on the Clients

In order to activate/deactivate the sounds and particle effects we need on the clients, we'll use our "Set Spawn Activation" multicast event. This event will also fade out the audio over 0.25 seconds, which will make the audio feel much more natural compared to a sharp cutoff.


FWUqDSO(1).png


Note: For similar datatypes you can pass multiple references to the same node. For example, the "Activate" node can accept references from 3 components, without needing 3 separate "Activate" nodes.



Event Buff Tick Client: Capture User Input, Send to Server

Rocketing yourself straight up is all well and good, but to really be fun/useful, players need the ability to steer while they're in the air. To do this, we need to capture the player's input, and transmit it to the server where it can be used later, like so:


8jeylKF(1).png


Warning: "Event Tick" events can be very taxing on your server. More on that in the next section.


Event Buff Tick Server

Next, we need to setup the "Event Buff Tick Server" to handle the physics of rocketing a player off the ground (without putting them into orbit).

But first, a huge word of caution: "Tick" events execute every single "frame" of the server's execution, so if you put heavy logic inside this function (or if there are many copies of this logic being run in multiple places -- such as 50 or 60 players all with the same buff), it will have a significant effect on your server's performance. Imagine asking your computer to do a bunch of extra math and networking between every frame in a movie that you're watching -- if you pile on too many calculations, you'll eventually see your video stutter. The same is true with ARK servers -- if you ask too much, you'll get lag/slowdowns.

Having said that, we'll be using the "Tick" event because the "Add Force" function requires it to run smoothly, and there isn't much in the way of heavy logic behind it.

Event Buff Tick Server: Speed Suppression

One of the first things we'll do is store the "Delta Time" (the time since the last tick) into a variable so we can access it later. Next, we'll check to see if the "Rocket Poop" is activated.

If the "Rocket Poop" is off, then we need to apply a dampening force to slow the player's forward progress, otherwise players can sail across the map in weird ways, and it hampers control.


JJENnXw(1).png


As you can see, the first thing we do is calculate the magnitude of the X,Y velocity vectors, which gives us an accurate measure of how fast a player is traversing across the landscape.

If the player is currently falling (but not boosting), and their speed is above a certain threshold, the dampening will kick in.

To achieve a slowing effect, we use the "Add Force" node to apply a force in the oppose direction that we're going -- sort've like a strong head-wind pushing us backwards. Once we've slowed below the threshold, the effect will end.


Event Buff Tick Server: Calculating the Main Thruster

Now we're into the nitty gritty. =)


5xM35Yb(1).png


If the "Rocket Poop" thruster is on, the we need a way to scale an appropriate force vector (direction and magnitude) for our thrust, and apply it to the player. (See above)

To do this, we're going to treat the X,Y axes separately from the Z axis. For the X,Y axes, we will multiply by the X,Y of our user input, to decide which way the player is wishing to move. This will allow for some mid-air control. Feel free to scale these values however you want, to gain more/less control.

Next, we need to handle the Z axis. For this, we have a static force of 300,000. However, this makes it difficult to stop a fall, so in the interest of fun/usability, let's add additional thrust based on the current fall speed of the character. We do this by multiplying the players downward velocity by -300.0, and adding that to our static 300,000. This allows for a quick stop when falling from great heights.

After we've got our desired thrust vector, we need to limit it's output to something reasonable (if the player isn't currently walking). The problem is that force can be cumulative, meaning that you'll keep gaining speed every time the force is re-added, and this can result in a player being rocketed off the map.

To help with that, I've created a "Velocity Clamp" function, which compares the players current velocity, and limits their thrust vector if they're going too fast, like so:


MOCVoNk(1).png


As you can see, the horizontal thrust components are both clamped if either of them is higher than 600, and the main thruster (Z component) is limited to a upwards speed of 1200. For fun, you can tweak these clamps if you don't like the default handling.

Event Buff Tick Server: Apply Thrust, Consume Food/Health

Now that we know which way we're going, the only thing left to do is apply the force to the player, and consume food/health as fuel.


It8QMu7(1).png


As you can see, the "Consume Food" function takes in the "Delta Seconds" float variable -- which allows us to remove food/health based on how many seconds the player boosted during this tick.

The "Consume Food" function:


IPJhCua(1).png


And that's it! You've successfully built "Rocket Poop" logic. Your parents will be so proud.




EDIT LINE



FtduJki(1).png

As you can see here, the looping timeline is setup to be 0.2 seconds long, with a “Attempt Poop” event at time 0. Next, create a function called “Rocket Pooping Function”, and add it to the graph as shown above. This is where most of our logic will reside. This function has been setup to accept the transform (location and rotation) of the player’s “PoopSocket” (a property of the players Skeletal Mesh), and a reference to the character, as “pass-by-reference” inputs (this will be important later). The “Rocket Pooping Function” will look like this, once we’re all said-and-done. Don’t let its size worry you, I’ll cover every piece in detail. I just want to give you the big picture before we move forward.

PqggE90(1).png

The first thing we’re going to do is setup reusable local variables which will hold the location of the poop socket, a reference to the primal character, the “Scaled User Input” (custom function, more on that later), and the poop impulse. Note: “Impulse” in Unreal Engine means an instantaneous force applied to an object once – like a bat hitting a baseball. We will be using custom vectors to determine the direction and strength of these impulses.

RIK1tf5(1).png

The “Get Pending Input Vector” gives us an indication of which direction the player wants to go (forwards, backwards, strafe left/right, etc). We can use this vector to allow the player some control while they’re in the air. The “Scale User Input” is a custom function, which scales the X and Y vectors, and creates an upward thrust vector for propelling the player. The function looks like this:

YfZ0n7L(1).png

Note: This is a “pure” function, so it does not need to be executed in the normal line of execution. Next, we need to calculate the impulse vector for the poop that we will be spawning in. This is done by adding the players current velocity with the velocity of the “Scaled User Input”, so that the poops rocket out of the players butt at the same speed that the player is moving – otherwise, the player would “out run” his own rocket poops, and that would look strange (or, even more strange than Rocket Poops). Once the vectors are added together, the final vector is passed through another custom function, called “Randomize Poop Impulse”. This function adds a small randomized amount of impulse on the X and Y axes, so that poops “splatter out” randomly, instead of just streaming out in a perfect line. It also adds a negative impulse in the Z axis, to ensure that poops are always shot downwards.

Randomized Poop Impulse:

ZvKCpEk(1).png

Now that our local variables are setup, we can add the impulse to the player and spawn a poop. Note: The impulse will be by-passed if the player is currently crouching, which allows them to “squat” to poop on things.

VbrMfKf(1).png

Before the impulse is applied to the player, the player’s current velocity and their scaled input is run through another custom function called “Impulse Clamp”, which prevents the impulse from firing if the players current velocity is too high. Without this function, players could fly off into the distance at near-infinite speed, if they kept holding down the poop button.

Impulse Clamp:

VYYnOMg(1).png

Now that the player has been “pushed” upwards, and the poop has been spawned, we need to push the newly spawned poop downwards. This can be done simply, with the built-in devkit functions, as seen below.

Dxf4z7i(1).png

Since the player just pooped, we will also need to subtract a small amount of food from their foot stat. If they do not have enough food, a small amount of health will be taken instead. To do this, create a custom function called “Consume Food” which accepts a “Primal Character” input, like so:

Uq2fzFj(1).png

The content of this function will look like this:

X1U8FkK(1).png

Now the only remaining step, add that delicious poop noise! This can be achieved very easily with a simple built-in function called “Actor Play Sound”.

REMwgF2(1).png

And you’re done!

You now have a very silly “Rocket Poop” buff which can launch you high into the sky, with nothing but yesterday’s digested meatloaf as fuel. If you have any questions, feel free to message me on the ARK Modding Discord chat, or on the “Rocket Poop” workshop page. I will be uploading this as a standalone open-source mod, so that you can download the source and play with it as an example. Happy modding!

--RedDwarf