Tutorial: Rocket Poop (buff)
- 1 Introduction
- 2 The Plan!
- 3 Setting up the “Rocket Poop” Buff
- 4 Setting up the “Rotten Steak” Consumable
- 5 Setup Assets
- 6 Add the "Rocket Poop" Buff Components
- 7 Add the “Rocket Poop” Buff Graph Logic
- 7.1 Event Begin Play: Re-Assign Owner
- 7.2 Event Begin Play: Enable Keyboard Input
- 7.3 Event Begin Play: Attach to Poop Socket
- 7.4 Event Begin Play: Setup Variables
- 7.5 Capturing the "Poop Key" press and release
- 7.6 Toggle Sounds/Particles on the Clients
- 7.7 Event Buff Tick Client: Capture User Input, Send to Server
- 7.8 Event Buff Tick Server
- 7.9 Event Buff Tick Server: Speed Suppression
- 7.10 Event Buff Tick Server: Calculating the Main Thruster
- 7.11 Event Buff Tick Server: Apply Thrust, Consume Food/Health
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.
- 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.
- Capture the player’s “poop key” command.
- 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:
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:
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
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.
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:
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):
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:
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.
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.
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).
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.
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.
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:
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.
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.
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:
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.
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. =)
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:
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.
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:
And that's it! You've successfully built "Rocket Poop" logic. Your parents will be so proud.
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 (my username is "RedDwarf"), 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.