diff --git a/Content.Shared/_DV/Roles/Components/CrownedSpiritRoleComponent.cs b/Content.Shared/_DV/Roles/Components/CrownedSpiritRoleComponent.cs new file mode 100644 index 00000000000..2ef8a5b5e41 --- /dev/null +++ b/Content.Shared/_DV/Roles/Components/CrownedSpiritRoleComponent.cs @@ -0,0 +1,6 @@ +using Content.Shared.Roles.Components; + +namespace Content.Shared._DV.Roles; + +[RegisterComponent] +public sealed partial class CrownedSpiritRoleComponent : BaseMindRoleComponent; diff --git a/Resources/Locale/en-US/_DV/abilities/psionic.ftl b/Resources/Locale/en-US/_DV/abilities/psionic.ftl index b3acb17a50f..86601df6f9d 100644 --- a/Resources/Locale/en-US/_DV/abilities/psionic.ftl +++ b/Resources/Locale/en-US/_DV/abilities/psionic.ftl @@ -95,6 +95,7 @@ psionic-power-precognition-asakim-spawn-result-message = You smell stale air fro psionic-power-precognition-gnome-spawn-result-message = You hear laughter coming from the walls and quick footsteps when your back is turned. psionic-power-precognition-pitbull-spawn-result-message = You see a vision of a hundred small creatures being torn apart by bloodthirsty beasts in a maze of steel. psionic-power-precognition-hitman-spawn-result-message = You see a man in a business suit, a corpse at their feet. +psionic-power-precognition-crownedspirit-result-message = You see a blinding light and a figure standing in front of you, their features obscured by their own shadow. # Psionic Eruption psionic-eruption-begin = {CAPITALIZE(THE($user))} is being consumed by a psionic energy! diff --git a/Resources/Locale/en-US/_DV/ghost/roles/crowned-spirit.ftl b/Resources/Locale/en-US/_DV/ghost/roles/crowned-spirit.ftl new file mode 100644 index 00000000000..c52c2937c15 --- /dev/null +++ b/Resources/Locale/en-US/_DV/ghost/roles/crowned-spirit.ftl @@ -0,0 +1,12 @@ +ghost-role-information-crownedspirit-name = Crowned Spirit +ghost-role-information-crownedspirit-description = Ambition and Malice once again rears it's head. Offer it your assistance, and then end it. +ghost-role-information-crownedspirit-rules = You are a [color=red][bold]Solo Antagonist[/bold][/color]. + You should find a Traitor or other similar antagonist and offer your aid. + You should avoid killing your target without explicit orders from and the presence of the one you are aiding. + You may kill the one you are aiding after they have completed your kill objective and their own, but not before. + +crownedspirit-role-briefing = + You are a Crowned Spirit, a being born to punish the ambition and hubris of mortals. + You seek to push your target to reveal their true nature to you, ending a life simply for the power and assistance you offer. + Offer them all you can, assist them in their own goals, and keep them alive until both of your tasks are done. And then punish them for their transgressions. +crownedspirit-round-end-name = Crowned Spirit diff --git a/Resources/Locale/en-US/_DV/objectives/conditions/crowned-spirit.ftl b/Resources/Locale/en-US/_DV/objectives/conditions/crowned-spirit.ftl new file mode 100644 index 00000000000..21fdcd6bfcc --- /dev/null +++ b/Resources/Locale/en-US/_DV/objectives/conditions/crowned-spirit.ftl @@ -0,0 +1,2 @@ +objective-issuer-crownedspirit = The Ambitions +objective-condition-crownedspirit-corruption-title = Have your charge murder {$targetName}, {CAPITALIZE($job)}. diff --git a/Resources/Prototypes/_DV/Damage/modifier_sets.yml b/Resources/Prototypes/_DV/Damage/modifier_sets.yml index 9c9013924bd..d7486180551 100644 --- a/Resources/Prototypes/_DV/Damage/modifier_sets.yml +++ b/Resources/Prototypes/_DV/Damage/modifier_sets.yml @@ -138,6 +138,18 @@ Holy: 4.0 Soul: 0.0 +- type: damageModifierSet + id: RadiantSpirit + coefficients: + Cold: 2.0 + Shock: 0.2 + Blunt: 0.6 + Slash: 0.4 + Piercing: 0.55 + Heat: 0.5 + Holy: 0.0 + Soul: 3.0 + - type: damageModifierSet id: Ifrit coefficients: diff --git a/Resources/Prototypes/_DV/Entities/Markers/Spawners/ghost_roles.yml b/Resources/Prototypes/_DV/Entities/Markers/Spawners/ghost_roles.yml index d8c36492e4a..014dd862e92 100644 --- a/Resources/Prototypes/_DV/Entities/Markers/Spawners/ghost_roles.yml +++ b/Resources/Prototypes/_DV/Entities/Markers/Spawners/ghost_roles.yml @@ -202,3 +202,20 @@ rules: ghost-role-information-hitman-rules mindRoles: - MindRoleHitman + +- type: entity + categories: [ HideSpawnMenu, Spawner ] + id: SpawnPointCrownedSpirit + name: crowned spirit role spawn point + suffix: Crowned Spirit + parent: BaseAntagSpawner + components: + - type: GhostRole + name: ghost-role-information-crownedspirit-name + description: ghost-role-information-crownedspirit-description + rules: ghost-role-information-crownedspirit-rules + makeSentient: true + allowSpeech: true + allowMovement: true + mindRoles: + - MindRoleGhostRoleSoloAntagonist diff --git a/Resources/Prototypes/_DV/Entities/Mobs/NPCs/crownedspirit.yml b/Resources/Prototypes/_DV/Entities/Mobs/NPCs/crownedspirit.yml new file mode 100644 index 00000000000..282a6e8eee9 --- /dev/null +++ b/Resources/Prototypes/_DV/Entities/Mobs/NPCs/crownedspirit.yml @@ -0,0 +1,95 @@ +- type: entity + parent: [ SimpleSpaceMobBase, MobCombat ] + id: MobCrownedSpirit + name: Crowned Spirit + description: A creature of radiance. So beautiful are they, with their crown of light. + components: + - type: Sprite + drawdepth: Mobs + sprite: _DV/Mobs/Ghosts/radiantspirit.rsi + layers: + - map: ["enum.DamageStateVisualLayers.Base"] + state: radiantspirit + - type: SlowOnDamage + speedModifierThresholds: + 100: 0.9 + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 180 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - type: MobThresholds + thresholds: + 0: Alive + 210: Dead + - type: Damageable + damageContainer: BiologicalMetaphysical + damageModifierSet: RadiantSpirit + - type: Puller + needsHands: false + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeCircle + radius: 0.35 + density: 160 + mask: + - SmallMobMask + layer: + - SmallMobLayer + - type: MovementSpeedModifier + baseWalkSpeed: 3 + baseSprintSpeed: 5.5 + - type: NoSlip + - type: MovedByPressure + enabled: false + - type: CombatMode + - type: MeleeWeapon + soundHit: + path: /Audio/Weapons/Xeno/alien_claw_flesh3.ogg + angle: 90 + animation: WeaponArcSkiaLunge + wideAnimation: WeaponArcSkiaSwipe + wideAnimationRotation: -90 + swingLeft: true + attackRate: 1.5 + range: 2.0 + altDisarm: false + damage: + types: + Slash: 20 + Holy: 15 + - type: Tag + tags: + - TaserImmune + - type: Speech + speechVerb: Ghost + - type: Psionic + - type: NoosphericZapPower + - type: PsionicInvisibilityPower + - type: Emoting + - type: Insulated + - type: FlashImmunity + - type: Bloodstream + bloodReferenceSolution: + reagents: + - ReagentId: Ambrosia + Quantity: 200 + - type: PointLight + radius: 3 + energy: 2 + color: "#f5d750" + castShadows: false + - type: GhostRole + name: ghost-role-information-crownedspirit-name + description: ghost-role-information-crownedspirit-description + rules: ghost-role-information-crownedspirit-rules + mindRoles: + - MindRoleCrownedSpirit + raffle: + settings: default + - type: GhostTakeoverAvailable diff --git a/Resources/Prototypes/_DV/GameRules/events.yml b/Resources/Prototypes/_DV/GameRules/events.yml index 517f9c576aa..d41d0294f8e 100644 --- a/Resources/Prototypes/_DV/GameRules/events.yml +++ b/Resources/Prototypes/_DV/GameRules/events.yml @@ -19,6 +19,7 @@ - id: SkiaSpawn - id: RatKingSpawn - id: NTAgentSleeper + - id: CrownedSpiritSpawn # Replaces upstream meteor events until they're good - type: entity @@ -521,3 +522,34 @@ - id: MobMouse2 - id: MobMouse2 - id: MobPitbullVent + +- type: entity + parent: BaseMidRoundAntag + id: CrownedSpiritSpawn + components: + - type: StationEvent + weight: 5 + duration: null + minimumPlayers: 30 + - type: PrecognitionResult + message: psionic-power-precognition-crownedspirit-result-message + - type: AntagSpawner + prototype: MobCrownedSpirit + - type: AntagObjectives + objectives: + - CrownedSpiritServeObjective + - CrownedSpiritKillObjective + - type: AntagRandomObjectives + sets: + - groups: CrownedSpiritObjectiveGroup + maxPicks: 1 + maxDifficulty: 300 + - type: AntagSelection + agentName: crownedspirit-round-end-name + definitions: + - spawnerPrototype: SpawnPointCrownedSpirit + min: 1 + max: 1 + pickPlayer: false + mindRoles: + - MindRoleCrownedSpirit diff --git a/Resources/Prototypes/_DV/Objectives/crownedspirit.yml b/Resources/Prototypes/_DV/Objectives/crownedspirit.yml new file mode 100644 index 00000000000..14d3ca31194 --- /dev/null +++ b/Resources/Prototypes/_DV/Objectives/crownedspirit.yml @@ -0,0 +1,71 @@ +- type: entity + abstract: true + parent: BaseObjective + id: BaseCrownedSpiritObjective + components: + - type: Objective + difficulty: 1 # unused + issuer: objective-issuer-crownedspirit + icon: + sprite: Mobs/Ghosts/ghost_human.rsi + state: icon + - type: RoleRequirement + roles: + - CrownedSpiritRole + +- type: entity + parent: [BaseCrownedSpiritObjective, BaseSurviveObjective] + id: CrownedSpiritServeObjective + name: Find someone wicked to serve. + description: Find someone wicked and offer them your power.. for a price. + components: + - type: Objective + +- type: entity + parent: BaseCrownedSpiritObjective + id: CrownedSpiritKillObjective + name: Ensure their corruption. + description: Have your new charge cause your target's death. Do not kill them yourself unless your charge orders it. This must be their own decision. + components: + - type: Objective + issuer: objective-issuer-crownedspirit + unique: false + icon: + sprite: Mobs/Ghosts/ghost_human.rsi + state: icon + - type: KillPersonCondition + requireDead: true + - type: TargetObjective + title: objective-condition-crownedspirit-corruption-title + - type: PickRandomPerson + filters: + - !type:BodyMindFilter + whitelist: + components: + - CommandStaff + - !type:ObjectiveImmuneFilter + # Can't have multiple objectives to kill the same person. + - !type:TargetObjectiveMindFilter + blacklist: + components: + - KillPersonCondition + +- type: entity + parent: [BaseCrownedSpiritObjective, BaseSurviveObjective] + id: CrownedSpiritPunishObjective + name: Punish them for their actions. + description: Punish the one you have chosen to serve. Through their actions, a life you chose has been taken. Return the favor to them. + components: + - type: Objective + difficulty: 1 + unique: true + +- type: entity + parent: [BaseCrownedSpiritObjective, BaseSurviveObjective] + id: CrownedSpiritAidObjective + name: Provide support to those wronged. + description: Provide aid to those your charge has hurt, even if it comes at cost to your charge. + components: + - type: Objective + difficulty: 1 + unique: true diff --git a/Resources/Prototypes/_DV/Objectives/objectiveGroups.yml b/Resources/Prototypes/_DV/Objectives/objectiveGroups.yml index da4645aa2b4..bb941fed65b 100644 --- a/Resources/Prototypes/_DV/Objectives/objectiveGroups.yml +++ b/Resources/Prototypes/_DV/Objectives/objectiveGroups.yml @@ -241,3 +241,19 @@ TestEngineeringObjective: 1 TestMedicalObjective: 1 DefundDepartmentObjective: 1 + +- type: weightedRandom + id: CrownedSpiritObjectiveGroup + weights: + CrownedSpiritObjectiveGroupPunish: 1 + CrownedSpiritObjectiveGroupAid: 1 + +- type: weightedRandom + id: CrownedSpiritObjectiveGroupPunish + weights: + CrownedSpiritPunishObjective: 1 + +- type: weightedRandom + id: CrownedSpiritObjectiveGroupAid + weights: + CrownedSpiritAidObjective: 1 diff --git a/Resources/Prototypes/_DV/Roles/Antags/crownedspirit.yml b/Resources/Prototypes/_DV/Roles/Antags/crownedspirit.yml new file mode 100644 index 00000000000..26a9f8686f7 --- /dev/null +++ b/Resources/Prototypes/_DV/Roles/Antags/crownedspirit.yml @@ -0,0 +1,9 @@ +- type: antag + id: CrownedSpirit + name: roles-antag-crownedspirit-name + objective: roles-antag-crownedspirit-objective + antagonist: true + setPreference: true + requirements: + - !type:OverallPlaytimeRequirement + time: 24h diff --git a/Resources/Prototypes/_DV/Roles/MindRoles/mind_roles.yml b/Resources/Prototypes/_DV/Roles/MindRoles/mind_roles.yml index 2ce9150cde1..7e5afa89efd 100644 --- a/Resources/Prototypes/_DV/Roles/MindRoles/mind_roles.yml +++ b/Resources/Prototypes/_DV/Roles/MindRoles/mind_roles.yml @@ -141,3 +141,16 @@ - type: HitmanRole - type: RoleBriefing briefing: hitman-briefing + +- type: entity + parent: BaseMindRoleAntag + id: MindRoleCrownedSpirit + name: Crowned Spirit Role + components: + - type: MindRole + roleType: SoloAntagonist + antagPrototype: CrownedSpirit + exclusiveAntag: true + - type: CrownedSpiritRole + - type: RoleBriefing + briefing: crownedspirit-role-briefing diff --git a/Resources/Textures/_DV/Mobs/Ghosts/radiantspirit.rsi/meta.json b/Resources/Textures/_DV/Mobs/Ghosts/radiantspirit.rsi/meta.json new file mode 100644 index 00000000000..0875017fa47 --- /dev/null +++ b/Resources/Textures/_DV/Mobs/Ghosts/radiantspirit.rsi/meta.json @@ -0,0 +1,15 @@ +{ + "version": 1, + "size": { + "x": 32, + "y": 32 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Original art by by AeraAulin (github) for ss14", + "states": [ + { + "name": "radiantspirit", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/_DV/Mobs/Ghosts/radiantspirit.rsi/radiantspirit.png b/Resources/Textures/_DV/Mobs/Ghosts/radiantspirit.rsi/radiantspirit.png new file mode 100644 index 00000000000..f9d9c8e99e9 Binary files /dev/null and b/Resources/Textures/_DV/Mobs/Ghosts/radiantspirit.rsi/radiantspirit.png differ