Skip to content

Commit

Permalink
Loadout Modular Functions (And Loadout Pets) (#1366)
Browse files Browse the repository at this point in the history
# Description

This PR implements a reflection based system for applying functions
directly to entities spawned by loadouts. In order to provide an
"Example" use of this system, I have created a "LoadoutMakeFollower"
function, which can be applied to a loadout entity that happens to be an
NPC with the Follower blackboard, making it follow the player who
purchased that loadout.

Basically. Pet mouse. The pet mouse will follow its owner. 

Yes I actually have tested this ingame, and it works great. The longest
part about coding this was me spending almost 30 minutes straight
wondering why the mouse wasn't following my character, until I
remembered that I had to make a special "Pet" mouse variant that had the
right HTN root task.

This could be extended to other things. I happen to know that Nuclear14
wanted something like this for a Pet Dog.

<details><summary><h1>Media</h1></summary>
<p>


![image](https://github.com/user-attachments/assets/a18b026b-07a3-4ad7-8cce-4ea4dc4c3036)

</p>
</details>

# Changelog

:cl:
- add: Loadouts can now apply modular functions to items upon spawning
in.
- add: A new LoadoutMakeFollower function, which lets you buy NPC
followers in loadouts.
- add: added Pet Mice, Cockroach, Mothroach, and Hamster to Loadouts.
All of which use the new LoadoutMakeFollower function.

Co-authored-by: sleepyyapril <[email protected]>
  • Loading branch information
VMSolidus and sleepyyapril authored Dec 22, 2024
1 parent 35c95a5 commit 311b86e
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 1 deletion.
30 changes: 30 additions & 0 deletions Content.Server/Clothing/Systems/LoadoutSystem.Functions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using JetBrains.Annotations;
using Robust.Shared.Serialization.Manager;
using Content.Shared.Clothing.Loadouts.Prototypes;
using Content.Server.NPC.Components;
using Content.Server.NPC.Systems;
using Content.Server.NPC.HTN;
using Content.Server.NPC;
using Robust.Shared.Map;
using System.Numerics;

namespace Content.Server.Clothing.Systems;

[UsedImplicitly]
public sealed partial class LoadoutMakeFollower : LoadoutFunction
{
public override void OnPlayerSpawn(EntityUid character,
EntityUid loadoutEntity,
IComponentFactory factory,
IEntityManager entityManager,
ISerializationManager serializationManager)
{
var npc = entityManager.System<NPCSystem>();
var htn = entityManager.System<HTNSystem>();
if (!entityManager.TryGetComponent<HTNComponent>(loadoutEntity, out var hTNComponent))
return;

npc.SetBlackboard(loadoutEntity, NPCBlackboard.FollowTarget, new EntityCoordinates(character, Vector2.Zero), hTNComponent);
htn.Replan(hTNComponent);
}
}
5 changes: 4 additions & 1 deletion Content.Server/Clothing/Systems/LoadoutSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
using Content.Shared.Storage;
using Content.Shared.Storage.EntitySystems;
using Content.Shared.Traits.Assorted.Components;
using Content.Shared.Whitelist;
using Robust.Shared.Configuration;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
Expand All @@ -33,6 +32,7 @@ public sealed class LoadoutSystem : EntitySystem
[Dependency] private readonly IPrototypeManager _protoMan = default!;
[Dependency] private readonly ISerializationManager _serialization = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly IComponentFactory _componentFactory = default!;


public override void Initialize()
Expand Down Expand Up @@ -103,6 +103,9 @@ public void ApplyCharacterLoadout(
comp.Owner = loadout.Item1;
EntityManager.AddComponent(loadout.Item1, comp);
}

foreach (var function in loadoutProto.Functions)
function.OnPlayerSpawn(uid, loadout.Item1, _componentFactory, EntityManager, _serialization);
}


Expand Down
16 changes: 16 additions & 0 deletions Content.Shared/Clothing/Loadouts/Prototypes/LoadoutPrototype.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Content.Shared.Customization.Systems;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager;

namespace Content.Shared.Clothing.Loadouts.Prototypes;

Expand Down Expand Up @@ -45,4 +46,19 @@ public sealed partial class LoadoutPrototype : IPrototype

[DataField]
public string GuideEntry { get; } = "";

[DataField(serverOnly: true)]
public LoadoutFunction[] Functions { get; private set; } = Array.Empty<LoadoutFunction>();
}

/// This serves as a hook for loadout functions to modify one or more entities upon spawning in.
[ImplicitDataDefinitionForInheritors]
public abstract partial class LoadoutFunction
{
public abstract void OnPlayerSpawn(
EntityUid character,
EntityUid loadoutEntity,
IComponentFactory factory,
IEntityManager entityManager,
ISerializationManager serializationManager);
}
5 changes: 5 additions & 0 deletions Resources/Locale/en-US/loadouts/generic/items.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,8 @@ loadout-name-LoadoutItemLighterFlippo = flippo lighter (colorable)
loadout-name-LoadoutItemDrinkShinyFlask = shiny flask (colorable)
loadout-name-LoadoutItemDrinkLithiumFlask = lithium flask (colorable)
loadout-name-LoadoutItemDrinkVacuumFlask = vacuum flask (colorable)
loadout-name-LoadoutItemPetMouse = pet mouse
loadout-name-LoadoutItemPetHamster = pet hamster
loadout-name-LoadoutItemPetMothroach = pet mothroach
loadout-name-LoadoutItemPetCockroach = pet cockroach
1 change: 1 addition & 0 deletions Resources/Locale/en-US/loadouts/itemgroups.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ character-item-group-LoadoutInstrumentsAny = Musical Instruments (Non-Musician)
character-item-group-LoadoutSmokes = Smokeables
character-item-group-LoadoutBoxKits = Survival Kits
character-item-group-LoadoutWritables = Writing Tools
character-item-group-LoadoutPets = Pets
# Job Specific Template
character-item-group-LoadoutJOBBackpacks = JOB Backpacks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,16 @@
id: LoadoutBookRandom
- type: loadout
id: LoadoutPen

- type: characterItemGroup
id: LoadoutPets
maxItems: 1
items:
- type: loadout
id: LoadoutItemPetMouse
- type: loadout
id: LoadoutItemPetHamster
- type: loadout
id: LoadoutItemPetMothroach
- type: loadout
id: LoadoutItemPetCockroach
60 changes: 60 additions & 0 deletions Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,21 @@
speaks: [Hissing]
understands: [Hissing]

- type: entity
parent: MobCockroach
id: MobCockroachPet
components:
- type: HTN
rootTask:
task: FollowCompound
blackboard:
IdleRange: !type:Single
1.5
FollowCloseRange: !type:Single
1.0
FollowRange: !type:Single
2.0

- type: entity
name: glockroach
parent: MobCockroach
Expand Down Expand Up @@ -575,6 +590,21 @@
enum.SurgeryUIKey.Key:
type: SurgeryBui

- type: entity
parent: MobMothroach
id: MobMothroachPet
components:
- type: HTN
rootTask:
task: FollowCompound
blackboard:
IdleRange: !type:Single
1.5
FollowCloseRange: !type:Single
1.0
FollowRange: !type:Single
2.0

# Note that the mallard duck is actually a male drake mallard, with the brown duck being the female variant of the same species, however ss14 lacks sex specific textures
# The white duck is more akin to a pekin or call duck.

Expand Down Expand Up @@ -1769,6 +1799,21 @@
enum.SurgeryUIKey.Key:
type: SurgeryBui

- type: entity
parent: MobMouse
id: MobMousePet
components:
- type: HTN
rootTask:
task: FollowCompound
blackboard:
IdleRange: !type:Single
1.5
FollowCloseRange: !type:Single
1.0
FollowRange: !type:Single
2.0

- type: entity
parent: MobMouse
suffix: Dead
Expand Down Expand Up @@ -3418,6 +3463,21 @@
sprite: Mobs/Effects/onfire.rsi
normalState: Mouse_burning

- type: entity
parent: MobHamster
id: MobHamsterPet
components:
- type: HTN
rootTask:
task: FollowCompound
blackboard:
IdleRange: !type:Single
1.5
FollowCloseRange: !type:Single
1.0
FollowRange: !type:Single
2.0

- type: entity
name: pig
parent: SimpleMobBase
Expand Down
53 changes: 53 additions & 0 deletions Resources/Prototypes/Loadouts/Generic/items.yml
Original file line number Diff line number Diff line change
Expand Up @@ -766,3 +766,56 @@
customColorTint: true
items:
- DrinkVacuumFlask

# Pets
- type: loadout
id: LoadoutItemPetMouse
category: Items
cost: 2
canBeHeirloom: true
items:
- MobMousePet
requirements:
- !type:CharacterItemGroupRequirement
group: LoadoutPets
functions:
- !type:LoadoutMakeFollower

- type: loadout
id: LoadoutItemPetHamster
category: Items
cost: 2
canBeHeirloom: true
items:
- MobHamsterPet
requirements:
- !type:CharacterItemGroupRequirement
group: LoadoutPets
functions:
- !type:LoadoutMakeFollower

- type: loadout
id: LoadoutItemPetMothroach
category: Items
cost: 2
canBeHeirloom: true
items:
- MobMothroachPet
requirements:
- !type:CharacterItemGroupRequirement
group: LoadoutPets
functions:
- !type:LoadoutMakeFollower

- type: loadout
id: LoadoutItemPetCockroach
category: Items
cost: 2
canBeHeirloom: true
items:
- MobCockroachPet
requirements:
- !type:CharacterItemGroupRequirement
group: LoadoutPets
functions:
- !type:LoadoutMakeFollower

0 comments on commit 311b86e

Please sign in to comment.