From a540b8840e7ad2493217c85037f8e719b38cdd3d Mon Sep 17 00:00:00 2001 From: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Date: Sun, 18 Aug 2024 12:22:36 -0400 Subject: [PATCH] Goliath mob (#30839) * Goliath mob * Update asteroid.yml * mcfuck yourself * add cloak * fixes * Update materials.yml --- .../Actions/ActionOnInteractSystem.cs | 17 +- .../NPCUseActionOnTargetComponent.cs | 27 +++ Content.Server/NPC/NPCBlackboard.cs | 12 +- .../NPC/Systems/NPCUseActionOnTargetSystem.cs | 68 +++++++ .../NPC/Systems/NPCUtilitySystem.cs | 8 +- .../Goliath/GoliathSummonTentacleAction.cs | 31 +++ .../Goliath/GoliathTentacleSystem.cs | 69 +++++++ Content.Shared/Actions/SharedActionsSystem.cs | 15 ++ Content.Shared/Stunnable/SharedStunSystem.cs | 30 +++ .../Stunnable/StunOnContactComponent.cs | 23 +++ Resources/Locale/en-US/abilities/goliath.ftl | 1 + .../Entities/Mobs/NPCs/asteroid.yml | 182 ++++++++++++++++++ .../Entities/Objects/Materials/materials.yml | 39 +++- Resources/Prototypes/NPCs/goliath.yml | 75 ++++++++ Resources/Prototypes/Procedural/vgroid.yml | 4 +- .../Prototypes/Stacks/Materials/materials.yml | 7 + Resources/Prototypes/tags.yml | 3 + .../Aliens/Asteroid/goliath.rsi/goliath.png | Bin 0 -> 2975 bytes .../Asteroid/goliath.rsi/goliath_alert.png | Bin 0 -> 4327 bytes .../Asteroid/goliath.rsi/goliath_dead.png | Bin 0 -> 968 bytes .../goliath.rsi/goliath_preattack.png | Bin 0 -> 4249 bytes .../goliath.rsi/goliath_tentacle_retract.png | Bin 0 -> 1926 bytes .../goliath.rsi/goliath_tentacle_spawn.png | Bin 0 -> 1944 bytes .../goliath.rsi/goliath_tentacle_wiggle.png | Bin 0 -> 2913 bytes .../Aliens/Asteroid/goliath.rsi/meta.json | 111 +++++++++++ .../Materials/hide.rsi/goliath_hide.png | Bin 0 -> 353 bytes .../Materials/hide.rsi/goliath_hide_2.png | Bin 0 -> 479 bytes .../Materials/hide.rsi/goliath_hide_3.png | Bin 0 -> 554 bytes .../Objects/Materials/hide.rsi/meta.json | 20 ++ 29 files changed, 718 insertions(+), 24 deletions(-) create mode 100644 Content.Server/NPC/Components/NPCUseActionOnTargetComponent.cs create mode 100644 Content.Server/NPC/Systems/NPCUseActionOnTargetSystem.cs create mode 100644 Content.Shared/Abilities/Goliath/GoliathSummonTentacleAction.cs create mode 100644 Content.Shared/Abilities/Goliath/GoliathTentacleSystem.cs create mode 100644 Content.Shared/Stunnable/StunOnContactComponent.cs create mode 100644 Resources/Locale/en-US/abilities/goliath.ftl create mode 100644 Resources/Prototypes/Entities/Mobs/NPCs/asteroid.yml create mode 100644 Resources/Prototypes/NPCs/goliath.yml create mode 100644 Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath.png create mode 100644 Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath_alert.png create mode 100644 Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath_dead.png create mode 100644 Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath_preattack.png create mode 100644 Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath_tentacle_retract.png create mode 100644 Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath_tentacle_spawn.png create mode 100644 Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath_tentacle_wiggle.png create mode 100644 Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/meta.json create mode 100644 Resources/Textures/Objects/Materials/hide.rsi/goliath_hide.png create mode 100644 Resources/Textures/Objects/Materials/hide.rsi/goliath_hide_2.png create mode 100644 Resources/Textures/Objects/Materials/hide.rsi/goliath_hide_3.png create mode 100644 Resources/Textures/Objects/Materials/hide.rsi/meta.json diff --git a/Content.Server/Actions/ActionOnInteractSystem.cs b/Content.Server/Actions/ActionOnInteractSystem.cs index 36e5920b32..a1f02ed1ec 100644 --- a/Content.Server/Actions/ActionOnInteractSystem.cs +++ b/Content.Server/Actions/ActionOnInteractSystem.cs @@ -154,21 +154,6 @@ public sealed class ActionOnInteractSystem : EntitySystem args.Handled = true; } - private bool ValidAction(BaseActionComponent action, bool canReach = true) - { - if (!action.Enabled) - return false; - - if (action.Charges.HasValue && action.Charges <= 0) - return false; - - var curTime = _timing.CurTime; - if (action.Cooldown.HasValue && action.Cooldown.Value.End > curTime) - return false; - - return canReach || action is BaseTargetActionComponent { CheckCanAccess: false }; - } - private List<(EntityUid Id, T Comp)> GetValidActions(List? actions, bool canReach = true) where T : BaseActionComponent { var valid = new List<(EntityUid Id, T Comp)>(); @@ -180,7 +165,7 @@ public sealed class ActionOnInteractSystem : EntitySystem { if (!_actions.TryGetActionData(id, out var baseAction) || baseAction as T is not { } action || - !ValidAction(action, canReach)) + !_actions.ValidAction(action, canReach)) { continue; } diff --git a/Content.Server/NPC/Components/NPCUseActionOnTargetComponent.cs b/Content.Server/NPC/Components/NPCUseActionOnTargetComponent.cs new file mode 100644 index 0000000000..f022a45ecc --- /dev/null +++ b/Content.Server/NPC/Components/NPCUseActionOnTargetComponent.cs @@ -0,0 +1,27 @@ +using Content.Server.NPC.Systems; +using Content.Shared.Actions; +using Robust.Shared.Prototypes; + +namespace Content.Server.NPC.Components; + +/// +/// This is used for an NPC that constantly tries to use an action on a given target. +/// +[RegisterComponent, Access(typeof(NPCUseActionOnTargetSystem))] +public sealed partial class NPCUseActionOnTargetComponent : Component +{ + /// + /// HTN blackboard key for the target entity + /// + [DataField] + public string TargetKey = "Target"; + + /// + /// Action that's going to attempt to be used. + /// + [DataField(required: true)] + public EntProtoId ActionId; + + [DataField] + public EntityUid? ActionEnt; +} diff --git a/Content.Server/NPC/NPCBlackboard.cs b/Content.Server/NPC/NPCBlackboard.cs index 322ff0f85b..ffdb55045d 100644 --- a/Content.Server/NPC/NPCBlackboard.cs +++ b/Content.Server/NPC/NPCBlackboard.cs @@ -34,6 +34,7 @@ public sealed partial class NPCBlackboard : IEnumerable @@ -269,6 +270,13 @@ public sealed partial class NPCBlackboard : IEnumerable("Target", out _, entMan) + ? AggroVisionRadius + : VisionRadius; + } + // I Ummd and Ahhd about using strings vs enums and decided on tags because // if a fork wants to do their own thing they don't need to touch the enum. @@ -317,9 +325,11 @@ public sealed partial class NPCBlackboard : IEnumerable /// A configurable "order" enum that can be given to an NPC from an external source. /// diff --git a/Content.Server/NPC/Systems/NPCUseActionOnTargetSystem.cs b/Content.Server/NPC/Systems/NPCUseActionOnTargetSystem.cs new file mode 100644 index 0000000000..f6cc2d1468 --- /dev/null +++ b/Content.Server/NPC/Systems/NPCUseActionOnTargetSystem.cs @@ -0,0 +1,68 @@ +using Content.Server.NPC.Components; +using Content.Server.NPC.HTN; +using Content.Shared.Actions; +using Robust.Shared.Timing; + +namespace Content.Server.NPC.Systems; + +public sealed class NPCUseActionOnTargetSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly SharedActionsSystem _actions = default!; + + /// + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMapInit); + } + + private void OnMapInit(Entity ent, ref MapInitEvent args) + { + ent.Comp.ActionEnt = _actions.AddAction(ent, ent.Comp.ActionId); + } + + public bool TryUseTentacleAttack(Entity user, EntityUid target) + { + if (!Resolve(user, ref user.Comp, false)) + return false; + + if (!TryComp(user.Comp.ActionEnt, out var action)) + return false; + + if (!_actions.ValidAction(action)) + return false; + + if (action.Event != null) + { + action.Event.Performer = user; + action.Event.Action = user.Comp.ActionEnt.Value; + action.Event.Coords = Transform(target).Coordinates; + } + + _actions.PerformAction(user, + null, + user.Comp.ActionEnt.Value, + action, + action.BaseEvent, + _timing.CurTime, + false); + return true; + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + // Tries to use the attack on the current target. + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var comp, out var htn)) + { + if (!htn.Blackboard.TryGetValue(comp.TargetKey, out var target, EntityManager)) + continue; + + TryUseTentacleAttack((uid, comp), target); + } + } +} diff --git a/Content.Server/NPC/Systems/NPCUtilitySystem.cs b/Content.Server/NPC/Systems/NPCUtilitySystem.cs index 5e1823227a..a2fb285ac1 100644 --- a/Content.Server/NPC/Systems/NPCUtilitySystem.cs +++ b/Content.Server/NPC/Systems/NPCUtilitySystem.cs @@ -264,7 +264,7 @@ public sealed class NPCUtilitySystem : EntitySystem } case TargetDistanceCon: { - var radius = blackboard.GetValueOrDefault(NPCBlackboard.VisionRadius, EntityManager); + var radius = blackboard.GetValueOrDefault(blackboard.GetVisionRadiusKey(EntityManager), EntityManager); if (!TryComp(targetUid, out TransformComponent? targetXform) || !TryComp(owner, out TransformComponent? xform)) @@ -309,13 +309,13 @@ public sealed class NPCUtilitySystem : EntitySystem } case TargetInLOSCon: { - var radius = blackboard.GetValueOrDefault(NPCBlackboard.VisionRadius, EntityManager); + var radius = blackboard.GetValueOrDefault(blackboard.GetVisionRadiusKey(EntityManager), EntityManager); return _examine.InRangeUnOccluded(owner, targetUid, radius + 0.5f, null) ? 1f : 0f; } case TargetInLOSOrCurrentCon: { - var radius = blackboard.GetValueOrDefault(NPCBlackboard.VisionRadius, EntityManager); + var radius = blackboard.GetValueOrDefault(blackboard.GetVisionRadiusKey(EntityManager), EntityManager); const float bufferRange = 0.5f; if (blackboard.TryGetValue("Target", out var currentTarget, EntityManager) && @@ -375,7 +375,7 @@ public sealed class NPCUtilitySystem : EntitySystem private void Add(NPCBlackboard blackboard, HashSet entities, UtilityQuery query) { var owner = blackboard.GetValue(NPCBlackboard.Owner); - var vision = blackboard.GetValueOrDefault(NPCBlackboard.VisionRadius, EntityManager); + var vision = blackboard.GetValueOrDefault(blackboard.GetVisionRadiusKey(EntityManager), EntityManager); switch (query) { diff --git a/Content.Shared/Abilities/Goliath/GoliathSummonTentacleAction.cs b/Content.Shared/Abilities/Goliath/GoliathSummonTentacleAction.cs new file mode 100644 index 0000000000..abdb0d5e10 --- /dev/null +++ b/Content.Shared/Abilities/Goliath/GoliathSummonTentacleAction.cs @@ -0,0 +1,31 @@ +using Content.Shared.Actions; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Abilities.Goliath; + +public sealed partial class GoliathSummonTentacleAction : EntityWorldTargetActionEvent +{ + /// + /// The ID of the entity that is spawned. + /// + [DataField] + public EntProtoId EntityId = "EffectGoliathTentacleSpawn"; + + /// + /// Directions determining where the entities will spawn. + /// + [DataField] + public List OffsetDirections = new() + { + Direction.North, + Direction.South, + Direction.East, + Direction.West, + }; + + /// + /// How many entities will spawn beyond the original one at the target location? + /// + [DataField] + public int ExtraSpawns = 3; +}; diff --git a/Content.Shared/Abilities/Goliath/GoliathTentacleSystem.cs b/Content.Shared/Abilities/Goliath/GoliathTentacleSystem.cs new file mode 100644 index 0000000000..98dbc5e18a --- /dev/null +++ b/Content.Shared/Abilities/Goliath/GoliathTentacleSystem.cs @@ -0,0 +1,69 @@ +using Content.Shared.Directions; +using Content.Shared.Maps; +using Content.Shared.Physics; +using Content.Shared.Popups; +using Content.Shared.Stunnable; +using Robust.Shared.Map; +using Robust.Shared.Map.Components; +using Robust.Shared.Network; +using Robust.Shared.Random; + +namespace Content.Shared.Abilities.Goliath; + +public sealed class GoliathTentacleSystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly INetManager _net = default!; + [Dependency] private readonly SharedMapSystem _map = default!; + [Dependency] private readonly SharedStunSystem _stun = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly TurfSystem _turf = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + + /// + public override void Initialize() + { + SubscribeLocalEvent(OnSummonAction); + } + + private void OnSummonAction(GoliathSummonTentacleAction args) + { + if (args.Handled || args.Coords is not { } coords) + return; + + // TODO: animation + + _popup.PopupPredicted(Loc.GetString("tentacle-ability-use-popup", ("entity", args.Performer)), args.Performer, args.Performer, type: PopupType.SmallCaution); + _stun.TryStun(args.Performer, TimeSpan.FromSeconds(0.8f), false); + + List spawnPos = new(); + spawnPos.Add(coords); + + var dirs = new List(); + dirs.AddRange(args.OffsetDirections); + + for (var i = 0; i < 3; i++) + { + var dir = _random.PickAndTake(dirs); + spawnPos.Add(coords.Offset(dir)); + } + + if (_transform.GetGrid(coords) is not { } grid || !TryComp(grid, out var gridComp)) + return; + + foreach (var pos in spawnPos) + { + if (!_map.TryGetTileRef(grid, gridComp, pos, out var tileRef) || + tileRef.IsSpace() || + _turf.IsTileBlocked(tileRef, CollisionGroup.Impassable)) + { + continue; + } + + if (_net.IsServer) + Spawn(args.EntityId, pos); + } + + args.Handled = true; + } +} diff --git a/Content.Shared/Actions/SharedActionsSystem.cs b/Content.Shared/Actions/SharedActionsSystem.cs index 635d78b8dd..fb9415096f 100644 --- a/Content.Shared/Actions/SharedActionsSystem.cs +++ b/Content.Shared/Actions/SharedActionsSystem.cs @@ -958,6 +958,21 @@ public abstract class SharedActionsSystem : EntitySystem // See client-side system for UI code. } + public bool ValidAction(BaseActionComponent action, bool canReach = true) + { + if (!action.Enabled) + return false; + + if (action.Charges.HasValue && action.Charges <= 0) + return false; + + var curTime = GameTiming.CurTime; + if (action.Cooldown.HasValue && action.Cooldown.Value.End > curTime) + return false; + + return canReach || action is BaseTargetActionComponent { CheckCanAccess: false }; + } + #endregion #region EquipHandlers diff --git a/Content.Shared/Stunnable/SharedStunSystem.cs b/Content.Shared/Stunnable/SharedStunSystem.cs index 092da8fe5a..8f828131f5 100644 --- a/Content.Shared/Stunnable/SharedStunSystem.cs +++ b/Content.Shared/Stunnable/SharedStunSystem.cs @@ -14,16 +14,22 @@ using Content.Shared.Movement.Systems; using Content.Shared.Standing; using Content.Shared.StatusEffect; using Content.Shared.Throwing; +using Content.Shared.Whitelist; using Robust.Shared.Audio.Systems; +using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Events; +using Robust.Shared.Physics.Systems; namespace Content.Shared.Stunnable; public abstract class SharedStunSystem : EntitySystem { [Dependency] private readonly ActionBlockerSystem _blocker = default!; + [Dependency] private readonly SharedBroadphaseSystem _broadphase = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!; [Dependency] private readonly StandingStateSystem _standingState = default!; [Dependency] private readonly StatusEffectsSystem _statusEffect = default!; @@ -45,6 +51,9 @@ public abstract class SharedStunSystem : EntitySystem SubscribeLocalEvent(UpdateCanMove); SubscribeLocalEvent(UpdateCanMove); + SubscribeLocalEvent(OnStunOnContactStartup); + SubscribeLocalEvent(OnStunOnContactCollide); + // helping people up if they're knocked down SubscribeLocalEvent(OnInteractHand); SubscribeLocalEvent(OnRefreshMovespeed); @@ -104,6 +113,27 @@ public abstract class SharedStunSystem : EntitySystem _blocker.UpdateCanMove(uid); } + private void OnStunOnContactStartup(Entity ent, ref ComponentStartup args) + { + if (TryComp(ent, out var body)) + _broadphase.RegenerateContacts(ent, body); + } + + private void OnStunOnContactCollide(Entity ent, ref StartCollideEvent args) + { + if (args.OurFixtureId != ent.Comp.FixtureId) + return; + + if (_entityWhitelist.IsBlacklistPass(ent.Comp.Blacklist, args.OtherEntity)) + return; + + if (!TryComp(args.OtherEntity, out var status)) + return; + + TryStun(args.OtherEntity, ent.Comp.Duration, true, status); + TryKnockdown(args.OtherEntity, ent.Comp.Duration, true, status); + } + private void OnKnockInit(EntityUid uid, KnockedDownComponent component, ComponentInit args) { _standingState.Down(uid); diff --git a/Content.Shared/Stunnable/StunOnContactComponent.cs b/Content.Shared/Stunnable/StunOnContactComponent.cs new file mode 100644 index 0000000000..cc4af53b3b --- /dev/null +++ b/Content.Shared/Stunnable/StunOnContactComponent.cs @@ -0,0 +1,23 @@ +using Content.Shared.Whitelist; +using Robust.Shared.GameStates; + +namespace Content.Shared.Stunnable; + +[RegisterComponent, NetworkedComponent, Access(typeof(SharedStunSystem))] +public sealed partial class StunOnContactComponent : Component +{ + /// + /// The fixture the entity must collide with to be stunned + /// + [DataField] + public string FixtureId = "fix"; + + /// + /// The duration of the stun. + /// + [DataField] + public TimeSpan Duration = TimeSpan.FromSeconds(5); + + [DataField] + public EntityWhitelist Blacklist = new(); +} diff --git a/Resources/Locale/en-US/abilities/goliath.ftl b/Resources/Locale/en-US/abilities/goliath.ftl new file mode 100644 index 0000000000..953d32a5c6 --- /dev/null +++ b/Resources/Locale/en-US/abilities/goliath.ftl @@ -0,0 +1 @@ +tentacle-ability-use-popup = {CAPITALIZE(THE($entity))} digs its tentacles under the ground! diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/asteroid.yml b/Resources/Prototypes/Entities/Mobs/NPCs/asteroid.yml new file mode 100644 index 0000000000..8cbd40b5cc --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/NPCs/asteroid.yml @@ -0,0 +1,182 @@ +- type: entity + id: BaseMobAsteroid + parent: + - BaseMob + - MobDamageable + - MobAtmosExposed + - MobCombat + abstract: true + components: + - type: Reactive + groups: + Flammable: [Touch] + Extinguish: [Touch] + Acidic: [Touch, Ingestion] + - type: Body + prototype: Animal + - type: Climbing + - type: NameIdentifier + group: GenericNumber + - type: StatusEffects + allowed: + - SlowedDown + - Stutter + - Stun + - Electrocution + - TemporaryBlindness + - RadiationProtection + - Drowsiness + - type: StandingState + - type: Tag + tags: + - DoorBumpOpener + +- type: entity + id: MobGoliath + parent: BaseMobAsteroid + name: goliath + description: A massive beast that uses long tentacles to ensnare its prey, threatening them is not advised under any conditions. + components: + - type: Sprite + sprite: Mobs/Aliens/Asteroid/goliath.rsi + layers: + - map: ["enum.DamageStateVisualLayers.Base"] + state: goliath + - type: DamageStateVisuals + states: + Alive: + Base: goliath + Dead: + Base: goliath_dead + - type: MovementSpeedModifier + baseWalkSpeed : 2.50 + baseSprintSpeed : 2.50 + - type: MobThresholds + thresholds: + 0: Alive + 300: Dead + - type: MeleeWeapon + soundHit: + path: "/Audio/Weapons/smash.ogg" + angle: 0 + attackRate: 0.75 + animation: WeaponArcPunch + damage: + types: + Slash: 15 + Piercing: 10 + - type: NpcFactionMember + factions: + - SimpleHostile + - type: HTN + rootTask: + task: GoliathCompound + blackboard: + VisionRadius: !type:Single + 6 + AggroVisionRadius: !type:Single + 10 + - type: NPCUseActionOnTarget + actionId: ActionGoliathTentacle + - type: Tag + tags: + - CannotSuicide + - Goliath + - FootstepSound + - type: NoSlip + - type: Butcherable + spawned: + - id: FoodMeatGoliath + amount: 3 + - id: MaterialGoliathHide1 + +- type: entity + id: ActionGoliathTentacle + name: "[color=red]Tentacle Slam[/color]" + description: Use your tentacles to grab and stun a target player! + components: + - type: EntityWorldTargetAction + raiseOnUser: true + icon: + sprite: Mobs/Aliens/Asteroid/goliath.rsi + state: goliath_tentacle_spawn + iconOn: + sprite: Mobs/Aliens/Asteroid/goliath.rsi + state: goliath_tentacle_wiggle + sound: + path: "/Audio/Weapons/slash.ogg" + event: !type:GoliathSummonTentacleAction + useDelay: 8 + range: 10 + +- type: entity + id: GoliathTentacle + name: tentacle + components: + - type: Transform + anchored: True + - type: Physics + bodyType: Static + canCollide: true + - type: InteractionOutline + - type: Sprite + sprite: Mobs/Aliens/Asteroid/goliath.rsi + layers: + - state: goliath_tentacle_wiggle + - type: StunOnContact + blacklist: + tags: + - Goliath + - type: Fixtures + fixtures: + fix: + shape: + !type:PhysShapeAabb + bounds: "-0.45,-0.45,0.45,0.45" + mask: + - Impassable + layer: + - Impassable + hard: false + - type: TimedDespawn #do this shit by hand because of fucking course. + lifetime: 0.4 + - type: SpawnOnDespawn + prototype: EffectGoliathTentacleRetract + +- type: entity + id: BaseEffectGoliathTentacleSpawn + categories: [ HideSpawnMenu ] + name: tentacle + abstract: true + components: + - type: Transform + anchored: True + - type: Physics + bodyType: Static + canCollide: false + - type: Sprite + sprite: Mobs/Aliens/Asteroid/goliath.rsi + - type: InteractionOutline + - type: TimedDespawn + lifetime: 0.7 + +- type: entity + id: EffectGoliathTentacleSpawn + parent: BaseEffectGoliathTentacleSpawn + categories: [ HideSpawnMenu ] + name: tentacle + components: + - type: Sprite + state: goliath_tentacle_spawn + - type: SpawnOnDespawn + prototype: GoliathTentacle + +- type: entity + id: EffectGoliathTentacleRetract + parent: BaseEffectGoliathTentacleSpawn + categories: [ HideSpawnMenu ] + components: + - type: Sprite + state: goliath_tentacle_retract + - type: EffectVisuals + - type: AnimationPlayer diff --git a/Resources/Prototypes/Entities/Objects/Materials/materials.yml b/Resources/Prototypes/Entities/Objects/Materials/materials.yml index e00f3e65d3..867b83f9ff 100644 --- a/Resources/Prototypes/Entities/Objects/Materials/materials.yml +++ b/Resources/Prototypes/Entities/Objects/Materials/materials.yml @@ -510,7 +510,7 @@ flavors: - banana - type: Food - trash: + trash: - TrashBananiumPeel - type: BadFood - type: SolutionContainerManager @@ -654,3 +654,40 @@ Gunpowder: 100 - type: Item size: Tiny + +- type: entity + parent: MaterialBase + id: MaterialGoliathHide + name: goliath hide plates + description: Pieces of a goliath's rocky hide, these might be able to make your suit a bit more durable to attack from the local fauna. + suffix: Full + components: + - type: Sprite + sprite: Objects/Materials/hide.rsi + layers: + - state: goliath_hide + map: [ "base" ] + - type: StaticPrice + price: 0 + - type: StackPrice + price: 1500 + - type: Appearance + - type: Stack + stackType: GoliathHide + baseLayer: base + layerStates: + - goliath_hide + - goliath_hide_2 + - goliath_hide_3 + - type: Item + size: Large + shape: + - 0,0,2,2 + +- type: entity + parent: MaterialGoliathHide + id: MaterialGoliathHide1 + suffix: 1 + components: + - type: Stack + count: 1 diff --git a/Resources/Prototypes/NPCs/goliath.yml b/Resources/Prototypes/NPCs/goliath.yml new file mode 100644 index 0000000000..0befc5d581 --- /dev/null +++ b/Resources/Prototypes/NPCs/goliath.yml @@ -0,0 +1,75 @@ +- type: htnCompound + id: GoliathCompound + branches: + - tasks: + - !type:HTNCompoundTask + task: GoliathMeleeCombatPrecondition + - tasks: + - !type:HTNCompoundTask + task: IdleCompound + +- type: htnCompound + id: GoliathMeleeCombatPrecondition + branches: + - preconditions: + - !type:BuckledPrecondition + isBuckled: true + tasks: + - !type:HTNPrimitiveTask + operator: !type:UnbuckleOperator + shutdownState: TaskFinished + + - preconditions: + - !type:InContainerPrecondition + isInContainer: true + tasks: + - !type:HTNCompoundTask + task: EscapeCompound + + - preconditions: + - !type:PulledPrecondition + isPulled: true + tasks: + - !type:HTNPrimitiveTask + operator: !type:UnPullOperator + shutdownState: TaskFinished + + - tasks: + - !type:HTNPrimitiveTask + operator: !type:UtilityOperator + proto: NearbyMeleeTargets + - !type:HTNCompoundTask + task: GoliathAttackTargetCompound + +- type: htnCompound + id: GoliathAttackTargetCompound + branches: + - preconditions: + - !type:KeyExistsPrecondition + key: Target + tasks: + - !type:HTNPrimitiveTask + operator: !type:MoveToOperator + shutdownState: PlanFinished + pathfindInPlanning: true + removeKeyOnFinish: false + targetKey: TargetCoordinates + pathfindKey: TargetPathfind + rangeKey: MeleeRange + - !type:HTNPrimitiveTask + operator: !type:JukeOperator + jukeType: AdjacentTile + - !type:HTNPrimitiveTask + operator: !type:MeleeOperator + targetKey: Target + preconditions: + - !type:KeyExistsPrecondition + key: Target + - !type:TargetInRangePrecondition + targetKey: Target + rangeKey: MeleeRange + services: + - !type:UtilityService + id: MeleeService + proto: NearbyMeleeTargets + key: Target diff --git a/Resources/Prototypes/Procedural/vgroid.yml b/Resources/Prototypes/Procedural/vgroid.yml index 4371e9cad5..315f908fad 100644 --- a/Resources/Prototypes/Procedural/vgroid.yml +++ b/Resources/Prototypes/Procedural/vgroid.yml @@ -145,7 +145,7 @@ minCount: 5 maxCount: 8 groups: - - id: MobXeno + - id: MobGoliath amount: 1 #- type: dungeonConfig @@ -175,7 +175,7 @@ minCount: 20 maxCount: 30 groups: - - id: MobXeno + - id: MobGoliath amount: 1 #- type: dungeonConfig diff --git a/Resources/Prototypes/Stacks/Materials/materials.yml b/Resources/Prototypes/Stacks/Materials/materials.yml index 1157dc3f00..049f538bcc 100644 --- a/Resources/Prototypes/Stacks/Materials/materials.yml +++ b/Resources/Prototypes/Stacks/Materials/materials.yml @@ -88,3 +88,10 @@ icon: { sprite: /Textures/Objects/Misc/reagent_fillings.rsi, state: powderpile } spawn: MaterialGunpowder maxCount: 60 + +- type: stack + id: GoliathHide + name: goliath hide + icon: { sprite: /Textures/Objects/Materials/hide.rsi, state: goliath_hide } + spawn: MaterialGoliathHide1 + maxCount: 30 diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 5e1b5cbe4d..1e3ae71958 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -656,6 +656,9 @@ - type: Tag id: Goat +- type: Tag + id: Goliath + - type: Tag id: GPS diff --git a/Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath.png b/Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath.png new file mode 100644 index 0000000000000000000000000000000000000000..5839a357960cffc8870d4fccf9ff8523d89093ac GIT binary patch literal 2975 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 VIA3;@Jre)`002ovPDHLkV1lqB+eQEY literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath_alert.png b/Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath_alert.png new file mode 100644 index 0000000000000000000000000000000000000000..c4c0b8efbeb55c660cb2f91d3d731dc828986e46 GIT binary patch literal 4327 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 ST!HcD0$^@pZHzW_d-^}}$decV literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath_dead.png b/Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath_dead.png new file mode 100644 index 0000000000000000000000000000000000000000..e6978b2890974525713217db0b5b381024fee83b GIT binary patch literal 968 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath_tentacle_retract.png b/Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath_tentacle_retract.png new file mode 100644 index 0000000000000000000000000000000000000000..d0895ccd15584b4e1db557e7dcdb637e0dd63840 GIT binary patch literal 1926 zcmV;12YL93P)06Le66j0bDs7>GU<-M$O+utXMYCCJjjYXPjY`!0q0#C6 z?#!Kx#?{%G(RA58pfiql?sv|2&bfEE=j=y`OPK(axReQSJ3(X1D;lq}(|`L=gyM<- z8h@z5hq-l4-WMYYt|NfPD-w!P91&pkHm`?Tk7=#Gr`}`5G+(SN1ps!km582J=q59v{e+VI3_?DUr|#Dr2iiTyw}#I{doU=L9yUj3Umi+ zwL4FieRiLFC2B`l^i?`~-xdMN2zBl1>e4a`OS<f#P?6e z<^3e|MbN2iO8^b9f*zZh#!6RIOUx~rpzUjGfWJcCU+iqg<5%CJzB4j1vMoE?5}>@!douq0xdsfy za`<8{izI5Wo>@gqL;=CC!;eleuBW~Z7b7|m%1chgiVq9^{U=d;v$Bc~WRMcL(g{LH zx&>dGuz|m03Q!5M%87?!HE0XQF@_`PSQp^6K?y#eUBesQmh@5co~YPXK}a+S57Q6XQE0H4^{QaL(5JI}$(-5WM#-IwFnKLp|pr>8vEc zD&PL*!-Wr%7`hRX5zu$M1*3_K_O(`tcs%YXQ58Ogh7o^!WgYKi7w~6ovm~B!Z%LEh zKY2#S?>ina({aA}a9;ep1TcSi?K`M5ITX_sVE6&65-cIuAFrrENIXf1yt|oMLhn?a z95RUoo{ce!&DNCHxFQ=pk5Pc$ay8c|jlZes!f#W?t?9{GU>i3ex*2 z7u(=Y_%vRUF0h>9+gb#XC%bDmx@g!b0{?Q z3&Rg@z~}$|xKS9stq&pYy*=p#8Cs)qp&LZ=yJxZXXiyr=m6?mv*$&|I--8mI9#}aV zg&X5Hb%7b%cWw!(LU=V@hVHx1q` zDVN4j;!-96B`#$GP~uW103|ME0#M>oCIBTaWdcy*;<`V8*V!WN5u~{44`5+(e0U32|3ykc1XyeD{G0VaS-zf(Ki3SwvGM?O4@4b? z?%J84s?l3(@58=I*&KB^6h>g-u{@eqWo#Z#%jO84-g+piNrG5B2{!u=#FaPS0L}&R8XSCsz^Bp5i)cap6o7ZMPQD8Ht*8c`y5eW@cuD!2z=v z!g?TuHNm0SM)KuYn_{~(rY5KHsfPrJ%941xzCk``<+kAsVBl)TeAlZcDXR{Q0G7en z2=Vw9$q38Z;K?&}=)BRQlb=iDWt-SL62MUIXYN%kZg@^mx>>cykd%g2y^nxiVos(~ zDObi@cNbX>Gjx!hBDbFD!z%GQHtNSUq6^Sm7e^`9Iz21IWSbuEsrN}^d#Wpi_v@rb zSe;eHNtValh*DlPOK@JL!>RT#eBCERp52yZ@$aq%1^Id<+4}BIVtWl>IGqnQ%0-aI z6TBC<#m@oRyu{9ofw7>BfR#Yh^F@$(O;RCJfz4Na5QfJ7l05_L383+O?#J`>#O+6-FXow*UYD M07*qoM6N<$f`l`U*#H0l literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath_tentacle_spawn.png b/Resources/Textures/Mobs/Aliens/Asteroid/goliath.rsi/goliath_tentacle_spawn.png new file mode 100644 index 0000000000000000000000000000000000000000..9172b0099ce49fc6915688cbf678a115402e6a0b GIT binary patch literal 1944 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/hide.rsi/goliath_hide_2.png b/Resources/Textures/Objects/Materials/hide.rsi/goliath_hide_2.png new file mode 100644 index 0000000000000000000000000000000000000000..9b03018487591e30f7d755755b0991f04658f4a9 GIT binary patch literal 479 zcmV<50U-W~P)@)Zj9(^TGIhTT7 zJyh@@BGyj26DMDGH`&mp2pK5bWH&p%?@yLY+=(>;{C|M?h1+5*zTDYh05pXbSI#|s z?C}HzkAx?*h@O z1T=;b46Q5#OM*b&f6@>Q06b)kX>J7*t_gv0zZAs8F20%Fx#{c5E$4sHsyVa3C|L>> z)+~HKKri2Mh+eND3?7R;oMs7vsm|fr_fxPZY5<7d8X;O+V`c^hwl9!50%&&p{RTud z1K0!)S;6dKQ$N{rB!K~-g;2!qrBU|z2EY2qOy z%~X~N>vRp~HCu$`sAWk4K-#UgUiyma8bGLl8Y)<86ZRD$c+L7_BuMO3JlOX@2twy# z&t(I!Pht?c`_%waN2b=l?R@VI&}MuLMFFhwA*1dDa7@!q07IB30fy2DFan$$;1`dN V+|Zid8two9002ovPDHLkV1ha3$NK;P literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Materials/hide.rsi/goliath_hide_3.png b/Resources/Textures/Objects/Materials/hide.rsi/goliath_hide_3.png new file mode 100644 index 0000000000000000000000000000000000000000..c9a53d76f24f03074c838ddfcec29e98692a0a07 GIT binary patch literal 554 zcmV+_0@eMAP)@)Zj9(|?aA?GEa zR}TsvM8vw2X4c7<-82cUQgonfn{G0{@88l++%M}N;P3(FCvJ_kcy~uX20&A2aqisR z>*m@Rh(Q2qOmho?&qF}A0$5Y4)7f>kF2n1sTn)}f65!(4tuGVbFk%Qst~Mov1@8mV zs{}NL5e%&?1WSTIUOu}aS^&7o8q?egCft((ESRPueOXA~o}Wl+T|)c4z_YyiN#+8ffO z2aq&VRVM6XbZkV;7Gb$+S*%(a$aO2CMCw)A?P{QgsWNr~SX0h=Rp0w|6n5kw)*q{a zF@vu3u?(F64Ra$-My|=!n4PbO9F+xNA5@VQtJrAl6KkT1kp_A1`ya)&{yMXv{*fM2 zq7%UPjTsMV#=@vapM