SpongeBob Roguelike Snippets
Module — 6 files
These files compile together (same module folder).
game_manager.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# A simple game manager to initialize the other verse devices on begin
game_manager := class(creative_device):
@editable PlayerAttackManager : player_attack_manager = player_attack_manager{}
@editable EnemyManager : enemy_manager = enemy_manager{}
OnBegin<override>()<suspends>:void=
PlayerAttackManager.Init()
EnemyManager.Init()
enemy_manager.verse
using { /Fortnite.com/Characters }
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# The AddEnemyAgentTagComponent function can be used to add the enemy_agent_tag_component to any agent that has an Entity. This example has
# an npc_spawner_device and guard_spawner_device, but feel free to experiment with any device that sends an agent and adding the
# enemy_agent_tag_component. This will allow the agent to be effected by the projectiles that check for this component.
enemy_manager := class(creative_device):
@editable NpcSpawnerDevice : npc_spawner_device = npc_spawner_device{}
@editable GuardSpawnerDevice : guard_spawner_device = guard_spawner_device{}
Init() : void =
NpcSpawnerDevice.SpawnedEvent.Subscribe(AddEnemyAgentTagComponent)
GuardSpawnerDevice.SpawnedEvent.Subscribe(AddEnemyAgentTagComponent)
# Adds the enemy_agent_tag_component to the Entity of the passed in agent. When the "projectiles" collide via the EntityEnteredEvent we can
# then verifiy if the entity that entered the projectile has an "enemy_agent_tag_component" added to it, and if so, damage the enemy. This
# is necessary so that we do not run code on entities we did not intend to, such as: other projectiles, the player, friendly npc's or
# any other entity that may enter it during gameplay.
AddEnemyAgentTagComponent(EnemyAgent:agent):void=
if:
EnemyFortCharacter := EnemyAgent.GetFortCharacter[]
EnemyEntity := EnemyFortCharacter.GetEntity[]
then:
EnemyAgentTagComponent := enemy_agent_tag_component{Entity := EnemyEntity}
EnemyEntity.AddComponents(array{EnemyAgentTagComponent})
player_attack_manager.verse
using { /Fortnite.com/Devices }
using { /Verse.org/SceneGraph }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# This player attack manager is used to initiate the "spawning" of the projectiles into the simulation. In this example we are using the
# input trigger, but you can use any conditions you like in order to call "SpawnProjectile" that sends an agent. You could rewrite this
# code to not require an agent, but in this case an agent is being used so we can count the elimination of enemies for the player who
# spawned the projectile.
# We are directly setting "PlayerProjectileEntity" to an entity prefab definition we have created, but you could use something like an editable
# enum with a wrapper to assign specific entity prefab defintions as you see fit. An example would be "upgrading" a projectile and using
# that entity prefab definition instead.
player_attack_manager := class(creative_device):
@editable InputTriggerPlayerAttack : input_trigger_device = input_trigger_device{}
Init(): void =
InputTriggerPlayerAttack.PressedEvent.Subscribe(SpawnProjectile)
SpawnProjectile(PlayerAgent:agent) : void =
# This is our pre made entity prefab definition, the file path will be specific to where you have placed your entity prefab definiton
# and should be replaced here.
PlayerProjectileEntity := PlayerProjectileEntities.EPD_Player_Projectile_Container_Single_Sphere_Red{}
# Attempts to add the Entity Prefab Definition to the simulation (Our pre made projectile)
if(SimulationEntity := GetSimulationEntity[]):
SimulationEntity.AddEntities(array{PlayerProjectileEntity})
# Checks if the entity has the player_projectile_component, if it does call the function "SetProjectileGlobalTransform"
# in order to set the projectiles "starting position" to be where the player is currently located
if(Component := PlayerProjectileEntity.GetComponent[projectile_container_component]):
Component.SetProjectileGlobalTransform(PlayerAgent)
file_4.verse
| | |
| --- | --- |
| | using { /Verse.org } |
| | using { /Verse.org/Native } |
| | using { /Verse.org/SceneGraph } |
| | using { /Verse.org/Simulation } |
| | |
| | # This is a simple component we will add to any agent we want to classify as an "enemy" we can do this by getting the entity of an agent |
| | # and adding this component. We can then check for this component as needed and then apply any code we want to the agent, such as |
| | # damaging them. |
| | |
| | enemy_agent_tag_component<public> := class<final_super>(component): |
projectile_container_component.verse
using { /Verse.org/Simulation }
using { /Verse.org/SceneGraph }
using { /Fortnite.com/Characters }
using { /UnrealEngine.com/Temporary/SpatialMath }
# This container component allows us to spawn a"container" entity wherever we want, in this case the players location. Once spawned
# it checks for children entities with the "projectile_component", which then handles the projectile logic on their own.
# This allows for rapid creation and iteration of projectiles, because you can simply place as many child entities within the container entity
# as you want, and as long as the container has the "projectile_container_component" and the children have the
# "projectile_component" added, they will handle all gameplay logic
projectile_container_component := class<final_super>(component):
# Spawned in entities default to the origin of the simulation, this function sets the global transform of the container entity to that of
# the players current location.
SetProjectileGlobalTransform(PlayerAgent:agent): void =
if(SpawningFortChar:= PlayerAgent.GetFortCharacter[]):
PlayerTransform := SpawningFortChar.GetTransform()
PlayerTranslation := PlayerTransform.Translation
Entity.SetGlobalTransform(FromTransform(PlayerTransform))
InitChildrenEntities(PlayerAgent)
# Checks if any of the children entities attatched to this entity have the "projectile_component" component, and if so
# runs the "InitProjectile" function.
InitChildrenEntities(PlayerAgent:agent): void =
ChildEntities := Entity.GetEntities()
for(ChildEntity:ChildEntities):
if(Component := ChildEntity.GetComponent[projectile_component]):
Component.InitProjectile(PlayerAgent)
projectile_component.verse
using { /Fortnite.com/AI }
using { /Fortnite.com/Characters }
using { /Fortnite.com/Game }
using { /Verse.org/Random }
using { /Verse.org/SceneGraph }
using { /Verse.org/SceneGraph/KeyframedMovement }
using { /Verse.org/Simulation }
using { /Verse.org/SpatialMath }
# This component will animate an entity forward from the parent or "container" entites location. In this case being the players current
# location. It then subscribes to the EntityEnteredEvent, and any time another entity enters this entity it checks for the
# "enemy_agent_tag_component". If the entered entity has this component, it will then damage that entities fort character. It also
# subscribes to the FinishedEvent of the keyframed_movement_component, and removes the entire parent (cotnainer) entity upon the animation
# completing (The projectile reaching it's maximum distance). This is a simple example, but you would likely want to add other realistic
# cases where the entity may require being destroyed before the animation had finished, and instead want to race against those conditions.
# Such as the projectiles hitting a boundry wall, the player being eliminated or removed from the game etc.
projectile_component := class<final_super>(component):
var TravelDistance : float = 3500.0
var ProjectileSpeed : float = 1500.0
var MaybePlayerAgent : ?agent = false
var MaybeParentEntity : ?entity = false
InitProjectile(PlayerAgent:agent): void =
set MaybePlayerAgent = option{PlayerAgent}
if:
ParentEntity := Entity.GetParent[]
MeshComp := Entity.GetComponent[mesh_component]
KeyComp := Entity.GetComponent[keyframed_movement_component]
then:
set MaybeParentEntity = option{ParentEntity}
MeshComp.EntityEnteredEvent.Subscribe(OnEntityEntered)
KeyComp.FinishedEvent.Subscribe(RemoveParentFromSimulation)
CalculateDestination(PlayerAgent)
# Note: This projectile component was designed for use in a "top down" view game, so there is no Z-axis accounted for in the calculations
# for the projectiles travel destination, feel free to modify the code to add account for the Z-axis if desired.
CalculateDestination(PlayerAgent:agent): void =
CurrentTransform := Entity.GetGlobalTransform()
ForwardVector := CurrentTransform.Rotation.GetForwardAxis() * TravelDistance
DestinationTranslation := CurrentTransform.Translation + ForwardVector
spawn{AnimateProjectile(ForwardVector)}
AnimateProjectile(DestinationTranslation:vector3)<suspends>: void =
TravelTime := TravelDistance/ProjectileSpeed
NewTransform:transform = transform:
Translation := DestinationTranslation
Scale := vector3{Left := 0.0, Up := 0.0, Forward := 0.0}
KeyDelta : keyframed_movement_delta = keyframed_movement_delta :
Transform := NewTransform
Duration := TravelTime
Easing := linear_easing_function{}
if(KeyComp := Entity.GetComponent[keyframed_movement_component]):
KeyComp.SetKeyframes(array{KeyDelta}, oneshot_keyframed_movement_playback_mode{})
Sleep(0.1)
KeyComp.Play()
# Note: Your static mesh in your entity prefab that is being "entered" must have collision, and a compatible collision type set, such
# as "OverlapAllDynamic" in order for the entity entered event to work, remember to check your static mesh settings in the mesh itself
# and also make sure the static mesh component in the entity is set to "collidable". It does not need to be visible, therefore you could
# if you wanted exclusively use a transparent mesh for collision checking, and use a Niagara Particle System Component for the "visible"
# part of the projectile, or use a combination of both if desired.
OnEntityEntered(EnteredEntity:entity):void =
if(EnteredEntity.GetComponent[enemy_agent_tag_component]):
for(Component:EnteredEntity.GetComponents()):
if(EnteredFortCharacter := fort_character[Component]):
DamageEnteredFortCharacter(EnteredFortCharacter)
# This removes only this specific entity from the parent entity we attatched to, not the "parent" or "container" entity.
# For example a "Spread shot" parent entity may have 3 child projectiles, but you would only want to remove this specific
# entity that collided with an "enemy", but allow the other 2 projectiles to continue moving forward until they reach the
# maximum travel distance.
Entity.RemoveFromParent()
# This damage function specifically uses damage args is for the purpose of allowing the "player" to be counted as the instigator for the
# damage done to the "entered fort character" in this case, an enemy. Using damage args allows the player to be counted as the eliminator,
# which is useful for game modes that require counting the players eliminations.
DamageEnteredFortCharacter(EnteredFortCharacter:fort_character) : void =
if:
PlayerAgent := MaybePlayerAgent?
PlayerFortCharacter := PlayerAgent.GetFortCharacter[]
then:
DamageArgs := damage_args:
Instigator := option{PlayerFortCharacter}
Source := option{PlayerFortCharacter}
Amount := 25.0
EnteredFortCharacter.Damage(DamageArgs)
# This removes the "top" level parent entity that this child entity is attatched to (The container). This is used to remove all entities
# attatched to the parent entity once they have "finished" their intended purpose, ie. Reaching their maximum distance.
RemoveParentFromSimulation() : void =
if(ParentEntity := MaybeParentEntity?):
ParentEntity.RemoveFromParent()
Sign in to download module
Copy-paste each file above is always free.