Add xenoborg bio knife (#45152)

* bio knife

* fix licence

* fix damage override

* remove weird null

* Abstrac the methods

* add new icon

* add bool

* add hash set
This commit is contained in:
beck-thompson 2026-08-18 20:13:53 +00:00 • committed by GitHub
parent 6da35cafb9
commit 266f978228
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 212 additions and 2 deletions

View file

@ -340,5 +340,43 @@ public sealed partial class MetabolizerSystem : EntitySystem
return ent.Comp.MetabolizerTypes.Add(metabolizer);
}
/// <summary>
/// Checks if the given organ has the given metabolizer.
/// </summary>
/// <param name="targetOrgan">The organ we are checking.</param>
/// <param name="targetMetabolizer">The metabolizer we are checking for.</param>
/// <returns>Returns true if the organ has the given metabolizer, false if the organ doesn't (this includes it not being a metabolizer at all)</returns>
public bool HasMetabolizer(Entity<MetabolizerComponent?> targetOrgan, ProtoId<MetabolizerTypePrototype> targetMetabolizer)
{
if (!Resolve(targetOrgan.Owner, ref targetOrgan.Comp, false))
return false;
if (targetOrgan.Comp.MetabolizerTypes is null)
return false;
if (!targetOrgan.Comp.MetabolizerTypes.Contains(targetMetabolizer))
return false;
return true;
}
/// <summary>
/// Checks if a given body has a metabolizer of the target type.
/// </summary>
/// <param name="targetBody">The body we are checking for the metabolizer.</param>
/// <param name="targetMetabolizer">The metabolizer we are checking for.</param>
/// <returns></returns>
public bool BodyHasMetabolizer(EntityUid targetBody, ProtoId<MetabolizerTypePrototype> targetMetabolizer)
{
var metabolisms = _body.EnumerateOrgans<MetabolizerComponent>(targetBody);
foreach (var organ in metabolisms)
{
if (HasMetabolizer((organ, organ.Comp2), targetMetabolizer))
return true;
}
return false;
}
}

View file

@ -88,5 +88,8 @@ namespace Content.Shared.Verbs
public static readonly VerbCategory Adjust =
new("verb-categories-adjust", "/Textures/Interface/VerbIcons/screwdriver.png");
public static readonly VerbCategory Metabolizers =
new("verb-categories-select-target", "/Textures/Interface/VerbIcons/group.svg.192dpi.png");
}
}

View file

@ -0,0 +1,38 @@
using Content.Shared.Damage;
using Content.Shared.Metabolism;
using Content.Shared.Mobs;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
namespace Content.Shared.Weapons.Melee.Metabolizer;
/// <summary>
/// Deals bonus damage when hitting an entity with the selected metabolizer
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class BonusDamageOnMetabolismComponent : Component
{
/// <summary>
/// List of metabolizers that cannot be selected.
/// </summary>
[DataField]
public List<ProtoId<MetabolizerTypePrototype>> ExcludedMetabolizers = new();
/// <summary>
/// The currently selected metabolizer, can be null for none.
/// </summary>
[DataField, AutoNetworkedField]
public ProtoId<MetabolizerTypePrototype>? SelectedMetabolizer;
/// <summary>
/// Amount of extra damage to deal when hitting an entity with the SelectedMetabolizer metabolism
/// </summary>
[DataField(required: true)]
public DamageSpecifier Damage = new();
/// <summary>
/// Will only do damage to mobs in one of these states. If null, doesn't care about the state of the mob.
/// </summary>
[DataField]
public HashSet<MobState> ValidMobStates = [ MobState.Alive, MobState.Critical ];
}

View file

@ -0,0 +1,65 @@
using System.Linq;
using Content.Shared.Metabolism;
using Content.Shared.Mobs.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Verbs;
using Content.Shared.Weapons.Melee.Events;
namespace Content.Shared.Weapons.Melee.Metabolizer;
public sealed partial class BonusDamageOnMetabolismSystem : EntitySystem
{
[Dependency] private MetabolizerSystem _metabolizer = default!;
[SubscribeLocalEvent]
private void OnGetVerb(Entity<BonusDamageOnMetabolismComponent> ent, ref GetVerbsEvent<Verb> args)
{
if (!args.CanAccess || !args.CanInteract)
return;
var allMetabolizers = ProtoMan.EnumeratePrototypes<MetabolizerTypePrototype>().ToList().OrderBy(x => Loc.GetString(x.LocalizedName));
byte index = 0;
foreach (var metabolizer in allMetabolizers)
{
if (ent.Comp.ExcludedMetabolizers.Contains(metabolizer))
continue;
var currIndex = index;
var verb = new Verb
{
Priority = currIndex,
Category = VerbCategory.Metabolizers,
Disabled = ent.Comp.SelectedMetabolizer == metabolizer,
Act = () =>
{
ent.Comp.SelectedMetabolizer = metabolizer;
Dirty(ent);
},
Text = Loc.GetString(metabolizer.LocalizedName),
};
args.Verbs.Add(verb);
index++;
}
}
[SubscribeLocalEvent]
private void OnSwingTrigger(Entity<BonusDamageOnMetabolismComponent> ent, ref MeleeHitEvent args)
{
if (ent.Comp.SelectedMetabolizer is null)
return;
foreach (var hitEntity in args.HitEntities)
{
if (TryComp<MobStateComponent>(hitEntity, out var mobState) && !ent.Comp.ValidMobStates.Contains(mobState.CurrentState))
continue;
if (!_metabolizer.BodyHasMetabolizer(hitEntity, ent.Comp.SelectedMetabolizer.Value))
continue;
// Add the bonus damage and quit!
args.BonusDamage =+ ent.Comp.Damage;
return;
}
}
}

View file

@ -29,6 +29,7 @@ verb-categories-select-type = Select Type
verb-categories-fax = Set Destination
verb-categories-power-level = Power Level
verb-categories-adjust = Adjust
verb-categories-select-target = Set Target
verb-common-toggle-light = Toggle light
verb-common-close = Close

View file

@ -1827,6 +1827,23 @@
- type: BorgModuleIcon
icon: { sprite: Interface/Actions/actions_borg.rsi, state: xenoborg-sword2-module }
- type: entity
parent: [ BaseXenoborgModuleScout, BaseProviderBorgModule, BaseXenoborgContraband ]
id: XenoborgModuleBioKinfe
name: bio knife xenoborg module
description: Module with an bio knife.
components:
- type: Sprite
layers:
- state: xenoborg_scout
- state: icon-xenoborg-sword2
- type: ItemBorgModule
hands:
- item: XenoborgBioKnife
- item: JetpackXenoborg
- type: BorgModuleIcon
icon: { sprite: Interface/Actions/actions_borg.rsi, state: xenoborg-bio-knife }
- type: entity
parent: [ BaseXenoborgModuleStealth, BaseProviderBorgModule, BaseXenoborgContraband ]
id: XenoborgModuleHypo

View file

@ -188,6 +188,34 @@
sprite: Objects/Weapons/Melee/kukri_knife.rsi
storedSprite: null
- type: entity
parent: [ CombatKnife, BaseXenoborgContraband ]
id: XenoborgBioKnife
name: bio knife
description: Melds itself to specific metabolizers and will deal extra damage to those targets!
components:
- type: Sprite
sprite: Objects/Weapons/Melee/bioknife.rsi
state: icon
- type: MeleeWeapon
attackRate: 1.0
damage:
types:
Slash: 10
- type: Item
sprite: Objects/Weapons/Melee/bioknife.rsi
- type: BonusDamageOnMetabolism
selectedMetabolizer: Human
excludedMetabolizers:
- Vox # Their biology is resistant to this!
# The rest of these are just so we don't clog up the menu with useless items.
- Bloodsucker
- Dragon
- Changeling
damage:
types:
Poison: 10
- type: entity
parent: [ClothingHeadHatGreyFlatcap, BaseMinorContraband]
id: BladedFlatcapGrey

View file

@ -1,7 +1,7 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from vgstation at commit https://github.com/vgstation-coders/vgstation13/commit/cdbcb1e858b11f083994a7a269ed67ef5b452ce9, inflatable module by FungiFellow (GitHub), Module actions by Scarky0. chem, adv-chem, and adv-mining by mubururu_, xenoborg actions by Samuka-C (github), advclown by ThatGuyUSA. c20r and esword by RedBookcase on Github, artistry-module by Kittygyat, with help from TiniestShark, xenoborg-laser3-module and xenoborg-deflector-module by august-sun(GitHub), Xenoborg Nanite action by YoungThugSS14 (Gihutb)",
"copyright": "Taken from vgstation at commit https://github.com/vgstation-coders/vgstation13/commit/cdbcb1e858b11f083994a7a269ed67ef5b452ce9, inflatable module by FungiFellow (GitHub), Module actions by Scarky0. chem, adv-chem, and adv-mining by mubururu_, xenoborg actions by Samuka-C (github), advclown by ThatGuyUSA. c20r and esword by RedBookcase on Github, artistry-module by Kittygyat, with help from TiniestShark, xenoborg-laser3-module and xenoborg-deflector-module by august-sun(GitHub), Xenoborg Nanite action and xenoborg-bio-knife by YoungThugSS14 (Gihutb)",
"size": {
"x": 32,
"y": 32
@ -193,6 +193,9 @@
{
"name":"xenoborg-sword2-module"
},
{
"name":"xenoborg-bio-knife"
},
{
"name":"xenoborg-tile-module"
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 979 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 B

View file

@ -1,7 +1,7 @@
{
"version": 1,
"license": "CC0-1.0",
"copyright": "Created by EmoGarbage404 (github) for Space Station 14. icon-construction.png created by deltanedas (github). syndicateborgbomb.png created by Mangohydra (github). icon-chem.png & icon-mining-adv.png created by mubururu_ (github) icon-inflatable.png made by FungiFellow (GitHub), Xenoborg modules sprites by Samuka-C (github), icon-xenoborg-laser3 and icon-xenoborg-shield by august-sun(github), Nanite gun module sprite made by YoungThugSS14 (Github), icon-artistry by Kittygyat, icon-xenoborg-radioactive by august-sun (github)",
"copyright": "Created by EmoGarbage404 (github) for Space Station 14. icon-construction.png created by deltanedas (github). syndicateborgbomb.png created by Mangohydra (github). icon-chem.png & icon-mining-adv.png created by mubururu_ (github) icon-inflatable.png made by FungiFellow (GitHub), Xenoborg modules sprites by Samuka-C (github), icon-xenoborg-laser3 and icon-xenoborg-shield by august-sun(github), Nanite gun module sprite made by YoungThugSS14 (Github), icon-artistry by Kittygyat, icon-xenoborg-radioactive by august-sun (github), icon-xenoborg-bio beck-thompson (github)",
"size": {
"x": 32,
"y": 32
@ -172,6 +172,9 @@
{
"name": "icon-xenoborg-shield"
},
{
"name": "icon-xenoborg-bio"
},
{
"name": "icon-xenoborg-tile"
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 428 B

View file

@ -0,0 +1,14 @@
{
"version": 1,
"license": "CC-BY-SA-4.0",
"copyright": "august-sun (github)",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
}
]
}