diff --git a/Content.Server/Abilities/WoundLicking/WoundLickingComponent.cs b/Content.Server/Abilities/WoundLicking/WoundLickingComponent.cs new file mode 100644 index 00000000000..2baf3792293 --- /dev/null +++ b/Content.Server/Abilities/WoundLicking/WoundLickingComponent.cs @@ -0,0 +1,83 @@ +using System.Threading; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Server.Felinid +{ + [RegisterComponent] + [Access(typeof(WoundLickingSystem))] + public sealed partial class WoundLickingComponent : Component + { + [DataField("woundLickingAction", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string? WoundLickingAction = "ActionWoundLicking"; + + [DataField("woundLickingActionEntity")] + public EntityUid? WoundLickingActionEntity; + + /// + /// How frequent wound-licking will cause diseases. Scales with amount of reduced bleeding + /// + [DataField("diseaseChance")] + [ViewVariables(VVAccess.ReadWrite)] + public float DiseaseChance { get; set; } = 0.25f; + + /// + /// Max possible bleeding reduce. Human max bleeding is 20f, many weapons deals near 15f bleeding + /// + [DataField("maxHeal")] + [ViewVariables(VVAccess.ReadWrite)] + public float MaxHeal { get; set; } = 15f; + + /// + /// How long it requires to lick wounds + /// + [DataField("delay")] + [ViewVariables(VVAccess.ReadWrite)] + public float Delay { get; set; } = 3f; + + /// + /// If true, then wound-licking can be applied only on yourself + /// + [DataField("canApplyOnSelf")] + [ViewVariables(VVAccess.ReadWrite)] + public bool CanApplyOnSelf { get; set; } = true; + + /// + /// If true, then wound-licking can be applied only on other entities + /// + [DataField("canApplyOnOther")] + [ViewVariables(VVAccess.ReadWrite)] + public bool CanApplyOnOther { get; set; } = false; + + + + /// + /// Which diseases can be caused because of wound-licking + /// + [DataField("possibleDiseases")] + public List PossibleDiseases { get; set; } = new() + { + "Plague", + "BirdFlew", + "SpaceFlu", + "SpaceCold", + "VentCough" + }; + + /// + /// If Target's bloodstream don't use one of these reagents, then ability can't be performed on it. + /// + [DataField("reagentWhitelist")] + public List ReagentWhitelist { get; set; } = new() + { + "Blood", + "Slime" + }; + + /// + /// Token for interrupting a do-after action. If not null, implies component is + /// currently "in use". + /// + public CancellationTokenSource? CancelToken; + } +} diff --git a/Content.Server/Abilities/WoundLicking/WoundLickingSystem.cs b/Content.Server/Abilities/WoundLicking/WoundLickingSystem.cs new file mode 100644 index 00000000000..bb3ebcfab5d --- /dev/null +++ b/Content.Server/Abilities/WoundLicking/WoundLickingSystem.cs @@ -0,0 +1,206 @@ +//using Content.Server.Disease.Components; +//using Content.Server.Disease; + +using Content.Server.Body.Components; +using Content.Server.Body.Systems; +using Content.Server.Popups; +using Content.Shared.DoAfter; +using Content.Shared.Felinid; +using Content.Shared.IdentityManagement; +using Content.Shared.Actions; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs; +using Robust.Shared.Player; +using Robust.Shared.Random; +using System.Linq; +/// taken from https://github.com/Workbench-Team/space-station-14/tree/arumoon-server +namespace Content.Server.Felinid +{ + /// + /// "Lick your or other felinid wounds. Reduce bleeding, but unsanitary and can cause diseases." + /// + public sealed partial class WoundLickingSystem : EntitySystem + { + [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; + [Dependency] private readonly PopupSystem _popupSystem = default!; +// [Dependency] private readonly DiseaseSystem _disease = default!; + [Dependency] private readonly SharedActionsSystem _actionsSystem = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnInit); + SubscribeLocalEvent(OnRemove); + SubscribeLocalEvent(OnDoAfter); + SubscribeLocalEvent(OnActionPerform); + } + + private void OnInit(EntityUid uid, WoundLickingComponent comp, ComponentInit args) + { + _actionsSystem.AddAction(uid, ref comp.WoundLickingActionEntity, comp.WoundLickingAction); + } + + private void OnRemove(EntityUid uid, WoundLickingComponent comp, ComponentRemove args) + { + _actionsSystem.RemoveAction(uid, comp.WoundLickingActionEntity); + } + + protected void OnActionPerform(WoundLickingActionEvent args) + { + if (args.Handled) + return; + + args.Handled = true; + var performer = args.Performer; + var target = args.Target; + + // Ensure components + if ( + !TryComp(performer, out var woundLicking) || + !TryComp(target, out var bloodstream) || + !TryComp(target, out var mobState) + ) + return; + + // Check target + if (mobState.CurrentState == MobState.Dead) + return; + + // Check "CanApplyOnSelf" field + if (performer == target & !woundLicking.CanApplyOnSelf) + { + _popupSystem.PopupEntity(Loc.GetString("lick-wounds-yourself-impossible"), + performer, Filter.Entities(performer), true); + return; + } + + // Check "CanApplyOnOther" field + if (performer != target & !woundLicking.CanApplyOnOther) + { + _popupSystem.PopupEntity(Loc.GetString("lick-wounds-other-impossible"), + performer, Filter.Entities(performer), true); + return; + } + + if (woundLicking.ReagentWhitelist.Any() && + !woundLicking.ReagentWhitelist.Contains(bloodstream.BloodReagent) + ) return; + + // Check bloodstream + if (bloodstream.BleedAmount == 0) + { + if (performer == target) + { + _popupSystem.PopupEntity(Loc.GetString("lick-wounds-yourself-no-wounds"), + performer, performer); + return; + } + _popupSystem.PopupEntity(Loc.GetString("lick-wounds-performer-no-wounds", ("target", target)), + performer, performer); + return; + } + + // Popup + + + if (target == performer) + { + // Applied on yourself + var performerIdentity = Identity.Entity(performer, EntityManager); + var otherFilter = Filter.Pvs(performer, entityManager: EntityManager) + .RemoveWhereAttachedEntity(e => e == performer); + + _popupSystem.PopupEntity(Loc.GetString("lick-wounds-yourself-begin"), + performer, performer); + _popupSystem.PopupEntity(Loc.GetString("lick-wounds-yourself-other-begin", ("performer", performerIdentity)), + performer, otherFilter, true); + } + else + { + // Applied on someone else + var targetIdentity = Identity.Entity(target, EntityManager); + var performerIdentity = Identity.Entity(performer, EntityManager); + var otherFilter = Filter.Pvs(performer, entityManager: EntityManager) + .RemoveWhereAttachedEntity(e => e == performer || e == target); + + _popupSystem.PopupEntity(Loc.GetString("lick-wounds-performer-begin", ("target", targetIdentity)), + performer, performer); + _popupSystem.PopupEntity(Loc.GetString("lick-wounds-target-begin", ("performer", performerIdentity)), + target, target); + _popupSystem.PopupEntity(Loc.GetString("lick-wounds-other-begin", ("performer", performerIdentity), ("target", targetIdentity)), + performer, otherFilter, true); + } + + // DoAfter + _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, performer, woundLicking.Delay, new WoundLickingDoAfterEvent(), performer, target: target) + { + BreakOnMove = true, + BreakOnDamage = true + }); + } + + private void OnDoAfter(EntityUid uid, WoundLickingComponent comp, WoundLickingDoAfterEvent args) + { + if (args.Cancelled || args.Handled) + { + return; + } + if (TryComp(args.Args.Target, out var bloodstream)) + LickWound(uid, args.Args.Target.Value, bloodstream, comp); + } + + private void LickWound(EntityUid performer, EntityUid target, BloodstreamComponent bloodstream, WoundLickingComponent comp) + { + // The more you heal, the more is disease chance + // For 15 maxHeal and 50% diseaseChance + // Heal 15 > chance 50% + // Heal 7.5 > chance 25% + // Heal 0 > chance 0% + + var healed = bloodstream.BleedAmount; + if (comp.MaxHeal - bloodstream.BleedAmount < 0) healed = comp.MaxHeal; +/* var chance = comp.DiseaseChance * (1 / comp.MaxHeal * healed); + + if (comp.DiseaseChance > 0f & comp.PossibleDiseases.Any()) + { + if (TryComp(target, out var disCarrier)) + { + var diseaseName = comp.PossibleDiseases[_random.Next(0, comp.PossibleDiseases.Count)]; + _disease.TryInfect(disCarrier, diseaseName, chance); + } + } +*/ + _bloodstreamSystem.TryModifyBleedAmount(target, -healed, bloodstream); + + if (performer == target) + { + // Applied on yourself + var performerIdentity = Identity.Entity(performer, EntityManager); + var otherFilter = Filter.Pvs(performer, entityManager: EntityManager) + .RemoveWhereAttachedEntity(e => e == performer); + + _popupSystem.PopupEntity(Loc.GetString("lick-wounds-yourself-success"), + performer, performer); + _popupSystem.PopupEntity(Loc.GetString("lick-wounds-yourself-other-success", ("performer", performerIdentity)), + performer, otherFilter, true); + } + else + { + // Applied on someone else + var targetIdentity = Identity.Entity(target, EntityManager); + var performerIdentity = Identity.Entity(performer, EntityManager); + var otherFilter = Filter.Pvs(performer, entityManager: EntityManager) + .RemoveWhereAttachedEntity(e => e == performer || e == target); + + _popupSystem.PopupEntity(Loc.GetString("lick-wounds-performer-success", ("target", targetIdentity)), + performer, performer); + _popupSystem.PopupEntity(Loc.GetString("lick-wounds-target-success", ("performer", performerIdentity)), + target, target); + _popupSystem.PopupEntity(Loc.GetString("lick-wounds-other-success", ("performer", performerIdentity), ("target", targetIdentity)), + performer, otherFilter, true); + } + } + } +} diff --git a/Content.Server/Speech/Components/NyaAccentComponent.cs b/Content.Server/Speech/Components/NyaAccentComponent.cs new file mode 100644 index 00000000000..57652c257ea --- /dev/null +++ b/Content.Server/Speech/Components/NyaAccentComponent.cs @@ -0,0 +1,8 @@ +// taken from pr: Workbench-Team/space-station-14#1 +namespace Content.Server.Speech.Components +{ + [RegisterComponent] + public sealed partial class NyaAccentComponent : Component + { + } +} diff --git a/Content.Server/Speech/Components/NyaAccentSystem.cs b/Content.Server/Speech/Components/NyaAccentSystem.cs new file mode 100644 index 00000000000..c2e950ac095 --- /dev/null +++ b/Content.Server/Speech/Components/NyaAccentSystem.cs @@ -0,0 +1,123 @@ +using System.Text.RegularExpressions; +using Content.Server.Speech.Components; +using Robust.Shared.Random; +// taken from pr: https://github.com/Workbench-Team/space-station-14/pull/1 +namespace Content.Server.Speech.EntitySystems; + +public sealed class NyaAccentSystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + + private static readonly Dictionary DirectReplacements = new() { + {"иди нахуй", "хиииссс" }, + {"иди нах", "хиииссс" }, + + {"дибилы", "баки" }, + {"дибил", "бака" }, + + {"ебланище", "бакище" }, + {"ебланы", "баки" }, + {"еблан", "бака" }, + + {"хуй", "буй" }, // :skull: + {"хуе", "буе" }, + {"хуи", "буи" }, + + {"блять", "блин" }, + {"бля", "блин" }, + + {"сук", "фуг" }, + + {"внимател", "внямател"}, //внямательно + {"маги", "мяуги"}, //мяугия + {"замечател", "замурчател"}, //замурчательно + + {"синдикат", "синдикэт"}, + {"нано", "ньяно"}, //ньянотразен + {"наркотики", "кошачья мята"}, + + {"наркотик", "кошачья мята"}, + {"каргон", "кэтгон"}, // каргония + {"каргония", "кэтгония"} + }; + + private static readonly IReadOnlyList Ending = new List { + "ня", + "мяу", + "мевп", + "мев", + "мррр" + }.AsReadOnly(); + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnAccent); + } + + public string Accentuate(string message) { + var final_msg = ""; + + // Sentence ending + var sentences = AccentSystem.SentenceRegex.Split(message); + foreach (var s in sentences) + { + var new_s = s; + + if (!string.IsNullOrWhiteSpace(new_s) && _random.Prob(0.5f)) + { + // Logger.DebugS("nya", $"SENTENCE: {new_s}"); + + string last_sym = new_s.Substring(new_s.Length-1); + string punct_mark = ""; + string insert = _random.Pick(Ending); + + // Checking end of the sentence to spaces and punctuation marks + if(Regex.Matches(last_sym, "[!?.]").Count > 0) + { + punct_mark = last_sym; + new_s = new_s.Remove(new_s.Length-1); + } + + // Add comma if "s" is real sentence + if (!new_s.EndsWith(' ')) { + insert = " " + insert; + if (new_s.Length > 0 && char.IsLetterOrDigit(new_s, new_s.Length-1)) + { + insert = "," + insert; + } + } + + // Insert ending word + new_s += insert + punct_mark; + } + final_msg += new_s; + } + + // Direct replacements + foreach (var (first, replace) in DirectReplacements) + { + final_msg = final_msg.Replace(first.ToUpper(), replace.ToUpper()); + } + foreach (var (first, replace) in DirectReplacements) + { + final_msg = final_msg.Replace(first, replace, true, null); + } + + // Trimming and uppering first char (Because it can be replaced with lower char) + final_msg = final_msg.Trim(); + final_msg = char.ToUpper(final_msg[0]) + final_msg.Substring(1); + + return final_msg; + } + + private void OnAccent(EntityUid uid, NyaAccentComponent component, AccentGetEvent args) + { + args.Message = Accentuate(args.Message); + } +} + +// |\__/,| (`\ +// |_ _ |.--.) ) +// ( T ) / +// (((^_(((/(((_> diff --git a/Content.Shared/WoundLicking/WoundLickingEvents.cs b/Content.Shared/WoundLicking/WoundLickingEvents.cs new file mode 100644 index 00000000000..20ab62f83c2 --- /dev/null +++ b/Content.Shared/WoundLicking/WoundLickingEvents.cs @@ -0,0 +1,14 @@ +using Content.Shared.Actions; +using Content.Shared.DoAfter; +using Robust.Shared.Serialization; + +namespace Content.Shared.Felinid; + +[Serializable, NetSerializable] +public sealed partial class WoundLickingDoAfterEvent : SimpleDoAfterEvent +{ +} + +public sealed partial class WoundLickingActionEvent : EntityTargetActionEvent +{ +} diff --git a/Resources/Locale/ru-RU/starshine/actions/lick-wounds.ftl b/Resources/Locale/ru-RU/starshine/actions/lick-wounds.ftl new file mode 100644 index 00000000000..f828b1ec411 --- /dev/null +++ b/Resources/Locale/ru-RU/starshine/actions/lick-wounds.ftl @@ -0,0 +1,16 @@ +action-name-lick-wounds = Зализать раны +action-desc-lick-wounds = Уменьшает кровотечение, но нарушает санитарию и может вызывать заболевания. +lick-wounds-yourself-impossible = Вы не можете зализать свои раны +lick-wounds-other-impossible = Вы не можете зализать чьи-то раны +lick-wounds-yourself-no-wounds = У вас нету кровотечения +lick-wounds-yourself-begin = Вы начинаете зализывать свои раны +lick-wounds-yourself-success = Вы зализываете ваши раны, уменьшая кровотечение +lick-wounds-yourself-other-begin = { CAPITALIZE($performer) } начинает зализывать свои раны +lick-wounds-yourself-other-success = { CAPITALIZE($performer) } зализывает свои раны +lick-wounds-performer-no-wounds = { CAPITALIZE($target) } не имеет кровотечения +lick-wounds-performer-begin = Вы начинаете зализывать раны { $target } +lick-wounds-performer-success = Вы зализали раны { $target } +lick-wounds-target-begin = { CAPITALIZE($performer) } начинает зализывать ваши раны +lick-wounds-target-success = { CAPITALIZE($performer) } зализывает ваши раны, уменьшая кровотечение +lick-wounds-other-begin = { CAPITALIZE($performer) } начинает зализывать раны { $target } +lick-wounds-other-success = { CAPITALIZE($performer) } успешно зализывает раны { $target } diff --git a/Resources/Prototypes/ADT/Body/Organs/felinid.yml b/Resources/Prototypes/ADT/Body/Organs/felinid.yml new file mode 100644 index 00000000000..fe5e87d1b7b --- /dev/null +++ b/Resources/Prototypes/ADT/Body/Organs/felinid.yml @@ -0,0 +1,13 @@ +- type: entity + id: ADTOrganFelinidHeart + parent: OrganHumanHeart + name: felinid heart + description: "I feel bad for the heartless bastard who lost this." + components: + - type: Metabolizer + maxReagents: 4 + metabolizerTypes: [Felinid, Animal] + groups: + - id: Medicine + - id: Poison + - id: Narcotic \ No newline at end of file diff --git a/Resources/Prototypes/ADT/Body/Prototypes/felinid.yml b/Resources/Prototypes/ADT/Body/Prototypes/felinid.yml new file mode 100644 index 00000000000..49654c5c2ac --- /dev/null +++ b/Resources/Prototypes/ADT/Body/Prototypes/felinid.yml @@ -0,0 +1,49 @@ +- type: body + id: Felinid + name: "felinid" + root: torso + slots: + head: + part: HeadHuman + connections: + - torso + organs: + brain: OrganHumanBrain + eyes: OrganHumanEyes + torso: + part: TorsoHuman + connections: + - right arm + - left arm + - left leg + - right leg + organs: + heart: ADTOrganFelinidHeart + lungs: OrganHumanLungs + stomach: OrganReptilianStomach + liver: OrganAnimalLiver + kidneys: OrganHumanKidneys + right arm: + part: RightArmHuman + connections: + - right hand + left arm: + part: LeftArmHuman + connections: + - left hand + right hand: + part: RightHandHuman + left hand: + part: LeftHandHuman + right leg: + part: RightLegHuman + connections: + - right foot + left leg: + part: LeftLegHuman + connections: + - left foot + right foot: + part: RightFootHuman + left foot: + part: LeftFootHuman diff --git a/Resources/Prototypes/ADT/Damage/modifier_sets.yml b/Resources/Prototypes/ADT/Damage/modifier_sets.yml index ab6acb5ad4f..880d52695de 100644 --- a/Resources/Prototypes/ADT/Damage/modifier_sets.yml +++ b/Resources/Prototypes/ADT/Damage/modifier_sets.yml @@ -47,16 +47,6 @@ Heat: 1.5 Asphyxiation: 2.0 -- type: damageModifierSet - id: Felinid # мяу - coefficients: - Blunt: 1.0 - Piercing: 1.15 - Slash: 1.30 - Cold: 1.5 - Heat: 2.0 - Poison: 1.1 - - type: damageModifierSet id: BloodlossIPC coefficients: @@ -118,3 +108,13 @@ id: Ursus # мишк coefficients: Blunt: 1.0 + +- type: damageModifierSet + id: Felinid # мяу + coefficients: + Blunt: 1.0 + Piercing: 1.0 + Slash: 1.0 + Cold: 1.5 + Heat: 1.0 + Poison: 1.4 diff --git a/Resources/Prototypes/ADT/Entities/Mobs/Player/felinid.yml b/Resources/Prototypes/ADT/Entities/Mobs/Player/felinid.yml new file mode 100644 index 00000000000..6156b2fa59b --- /dev/null +++ b/Resources/Prototypes/ADT/Entities/Mobs/Player/felinid.yml @@ -0,0 +1,87 @@ +- type: entity + save: false + name: Урист МакФелинид + parent: MobFelinidBase + id: MobFelinid + components: + - type: CombatMode + - type: InteractionPopup + successChance: 1 + interactSuccessString: petting-success-generic + interactSuccessSound: /Audio/ADT/Felinid/cat_purr1.ogg + messagePerceivedByOthers: petting-success-soft-floofy-others + interactSuccessSpawn: EffectHearts + interactDelay: 4 + - type: MindContainer + showExamineInfo: true + - type: Input + context: "human" + - type: MobThresholds + thresholds: + 0: Alive + 90: Critical + 195: Dead + - type: MobMover + - type: InputMover + - type: Respirator + damage: + types: + Asphyxiation: 1.9 + damageRecovery: + types: + Asphyxiation: -1.9 + - type: Reactive + groups: + Flammable: [ Touch ] + Extinguish: [ Touch ] + Acidic: [Touch, Ingestion] + reactions: + - reagents: [Water, SpaceCleaner] + methods: [Touch] + effects: + - !type:WashCreamPieReaction + - type: StatusEffects + allowed: + - Stun + - KnockedDown + - SlowedDown + - Stutter + - SeeingRainbows + - Electrocution + - Drunk + - SlurredSpeech + - RatvarianLanguage + - PressureImmunity + - Muted + - ForcedSleep + - TemporaryBlindness + - Pacified + - StaminaModifier + - type: Alerts + - type: Actions + - type: Eye + - type: NyaAccent + - type: CameraRecoil + - type: Examiner + - type: CanHostGuardian + - type: LanguageSpeaker + speaks: + - GalacticCommon + - Nekomimetic + understands: + - GalacticCommon + - Nekomimetic + - type: NpcFactionMember + factions: + - NanoTrasen + - type: Vocal + wilhelm: "/Audio/ADT/Felinid/cat_wilhelm.ogg" + sounds: + Male: MaleFelinid + Female: FemaleFelinid + Unsexed: MaleFelinid + - type: SizeAttributeWhitelist # Frontier + tall: true + tallscale: 1 + short: true + shortscale: 0.8 diff --git a/Resources/Prototypes/ADT/Entities/Mobs/Species/felinid.yml b/Resources/Prototypes/ADT/Entities/Mobs/Species/felinid.yml new file mode 100644 index 00000000000..c44373fd522 --- /dev/null +++ b/Resources/Prototypes/ADT/Entities/Mobs/Species/felinid.yml @@ -0,0 +1,177 @@ +- type: entity + save: false + name: Base felinid + parent: BaseMobHuman + id: MobFelinidBase + abstract: true + components: + - type: Sprite + netsync: false + noRot: true + drawdepth: Mobs + scale: 0.98, 0.98 + layers: + - map: [ "enum.HumanoidVisualLayers.Chest" ] + - map: [ "enum.HumanoidVisualLayers.Head" ] + - map: [ "enum.HumanoidVisualLayers.Snout" ] + - map: [ "enum.HumanoidVisualLayers.Eyes" ] + - map: [ "enum.HumanoidVisualLayers.RArm" ] + - map: [ "enum.HumanoidVisualLayers.LArm" ] + - map: [ "enum.HumanoidVisualLayers.RLeg" ] + - map: [ "enum.HumanoidVisualLayers.LLeg" ] + - shader: StencilClear + sprite: Mobs/Species/Human/parts.rsi + state: l_leg + - shader: StencilMask + map: ["enum.HumanoidVisualLayers.StencilMask"] + sprite: Mobs/Customization/masking_helpers.rsi + state: unisex_full + visible: false + - map: [ "underwearb" ] #Sirena + - map: [ "underweart" ] #Sirena + - map: ["enum.HumanoidVisualLayers.LFoot"] + - map: ["enum.HumanoidVisualLayers.RFoot"] + - map: [ "socks" ] #Sirena + - map: [ "jumpsuit" ] + - map: [ "enum.HumanoidVisualLayers.LHand" ] + - map: [ "enum.HumanoidVisualLayers.RHand" ] + - map: [ "id" ] + - map: [ "gloves" ] + - map: [ "shoes" ] + - map: [ "ears" ] + - map: [ "outerClothing" ] + - map: [ "eyes" ] + - map: [ "belt" ] + - map: [ "neck" ] + - map: [ "back" ] + - map: [ "enum.HumanoidVisualLayers.FacialHair" ] + - map: [ "enum.HumanoidVisualLayers.Hair" ] + - map: [ "enum.HumanoidVisualLayers.HeadSide" ] + - map: [ "enum.HumanoidVisualLayers.HeadTop" ] + - map: [ "enum.HumanoidVisualLayers.Tail" ] + - map: [ "mask" ] + - map: [ "head" ] + - map: [ "pocket1" ] + - map: [ "pocket2" ] + - map: ["enum.HumanoidVisualLayers.Handcuffs"] + color: "#ffffff" + sprite: Objects/Misc/handcuffs.rsi + state: body-overlay-2 + visible: false + - map: [ "clownedon" ] + sprite: "Effects/creampie.rsi" + state: "creampie_human" + visible: false + - type: HumanoidAppearance + species: Felinid + - type: Destructible #процесс разрушения на органы + thresholds: + - trigger: + !type:DamageTypeTrigger + damageType: Blunt #при каком дамаге это происходит + damage: 300 + behaviors: + - !type:GibBehavior { } + - type: Fixtures + fixtures: # TODO: This needs a second fixture just for mob collisions. + fix1: + shape: + !type:PhysShapeCircle + radius: 0.30 + density: 160 + restitution: 0.0 + mask: + - MobMask + layer: + - MobLayer + - type: Body + prototype: Felinid + - type: Damageable + damageContainer: Biological + damageModifierSet: Felinid + - type: MeleeWeapon + soundHit: + collection: Punch + animation: WeaponArcClaw + damage: + types: + Blunt: 0.9 + Slash: 5 + - type: Blindable + - type: Speech + speechSounds: Alto + - type: DamageOnHighSpeedImpact + damage: + types: + Blunt: 0.9 + soundHit: + path: /Audio/Effects/hit_kick.ogg + - type: Perishable + - type: Butcherable + butcheringType: Spike # TODO human. + spawned: + - id: FoodMeat + - id: ClothingHeadHatCatEars + - type: WoundLicking +- type: entity + save: false + name: Felinid Dummy + parent: MobHumanDummy + id: MobFelinidDummy + noSpawn: true + description: A dummy felinid meant to be used in character setup. + components: + - type: Sprite + netsync: false + noRot: true + drawdepth: Mobs + scale: 1, 1 + layers: + # TODO BODY Turn these into individual body parts? + - map: [ "enum.HumanoidVisualLayers.Chest" ] + - map: [ "enum.HumanoidVisualLayers.Head" ] + - map: [ "enum.HumanoidVisualLayers.Snout" ] + - map: [ "enum.HumanoidVisualLayers.Eyes" ] + - map: [ "enum.HumanoidVisualLayers.RArm" ] + - map: [ "enum.HumanoidVisualLayers.LArm" ] + - map: [ "enum.HumanoidVisualLayers.RLeg" ] + - map: [ "enum.HumanoidVisualLayers.LLeg" ] + - shader: StencilClear + sprite: Mobs/Species/Human/parts.rsi + state: l_leg + - shader: StencilMask + map: ["enum.HumanoidVisualLayers.StencilMask"] + sprite: Mobs/Customization/masking_helpers.rsi + state: unisex_full + visible: false + - map: [ "underwearb" ] #Sirena + - map: [ "underweart" ] #Sirena + - map: ["enum.HumanoidVisualLayers.LFoot"] + - map: ["enum.HumanoidVisualLayers.RFoot"] + - map: [ "socks" ] #Sirena + - map: [ "jumpsuit" ] + - map: [ "enum.HumanoidVisualLayers.LHand" ] + - map: [ "enum.HumanoidVisualLayers.RHand" ] + - map: [ "enum.HumanoidVisualLayers.Handcuffs" ] + color: "#ffffff" + sprite: Objects/Misc/handcuffs.rsi + state: body-overlay-2 + visible: false + - map: [ "id" ] + - map: [ "gloves" ] + - map: [ "shoes" ] + - map: [ "ears" ] + - map: [ "outerClothing" ] + - map: [ "eyes" ] + - map: [ "belt" ] + - map: [ "neck" ] + - map: [ "back" ] + - map: [ "enum.HumanoidVisualLayers.FacialHair" ] + - map: [ "enum.HumanoidVisualLayers.Hair" ] + - map: [ "enum.HumanoidVisualLayers.HeadSide" ] + - map: [ "enum.HumanoidVisualLayers.HeadTop" ] + - map: [ "enum.HumanoidVisualLayers.Tail" ] + - map: [ "mask" ] + - map: [ "head" ] + - map: [ "pocket1" ] + - map: [ "pocket2" ] diff --git a/Resources/Prototypes/ADT/SoundCollections/emotes.yml b/Resources/Prototypes/ADT/SoundCollections/emotes.yml index 24ac3c2ebb6..c5bde96c9ef 100644 --- a/Resources/Prototypes/ADT/SoundCollections/emotes.yml +++ b/Resources/Prototypes/ADT/SoundCollections/emotes.yml @@ -14,7 +14,7 @@ id: DraskTalk files: - /Audio/ADT/Drask/drasktalk.ogg - + # IPC - type: soundCollection id: SynthYes @@ -59,7 +59,7 @@ - /Audio/ADT/Novakid/novakid_laugh03.ogg - /Audio/ADT/Novakid/novakid_laugh04.ogg - /Audio/ADT/Novakid/novakid_laugh05.ogg - + - type: soundCollection id: TajaranHisses files: @@ -175,4 +175,35 @@ - type: soundCollection id: VulpHeckaetSound files: - - /Audio/ADT/Voice/Vulpkanin/vulpkanin_hekaet1.ogg \ No newline at end of file + - /Audio/ADT/Voice/Vulpkanin/vulpkanin_hekaet1.ogg + +#feliinid + +- type: soundCollection + id: FelinidHisses + files: + - /Audio/ADT/Felinid/cat_hiss1.ogg + - /Audio/ADT/Felinid/cat_hiss2.ogg + +- type: soundCollection + id: FelinidMeows + files: + - /Audio/ADT/Felinid/cat_meow1.ogg + - /Audio/ADT/Felinid/cat_meow2.ogg + - /Audio/ADT/Felinid/cat_meow3.ogg + +- type: soundCollection + id: FelinidMews + files: + - /Audio/ADT/Felinid/cat_mew1.ogg + - /Audio/ADT/Felinid/cat_mew2.ogg + +- type: soundCollection + id: FelinidGrowls + files: + - /Audio/ADT/Felinid/cat_growl1.ogg + +- type: soundCollection + id: FelinidPurrs + files: + - /Audio/ADT/Felinid/cat_purr1.ogg diff --git a/Resources/Prototypes/ADT/SoundCollections/screams.yml b/Resources/Prototypes/ADT/SoundCollections/screams.yml index 9c8a2626346..c985000ec3c 100644 --- a/Resources/Prototypes/ADT/SoundCollections/screams.yml +++ b/Resources/Prototypes/ADT/SoundCollections/screams.yml @@ -5,7 +5,7 @@ - /Audio/ADT/Novakid/novakid_scream02.ogg - /Audio/ADT/Novakid/novakid_scream03.ogg - /Audio/ADT/Novakid/novakid_scream04.ogg - + - type: soundCollection id: TajaranMaleScreams files: @@ -21,4 +21,11 @@ files: - /Audio/ADT/Felinid/cat_scream1.ogg - /Audio/ADT/Felinid/cat_scream2.ogg - - /Audio/ADT/Felinid/cat_scream3.ogg \ No newline at end of file + - /Audio/ADT/Felinid/cat_scream3.ogg + +- type: soundCollection + id: FelinidScreams + files: + - /Audio/ADT/Felinid/cat_scream1.ogg + - /Audio/ADT/Felinid/cat_scream2.ogg + - /Audio/ADT/Felinid/cat_scream3.ogg diff --git a/Resources/Prototypes/ADT/Species/felinid.yml b/Resources/Prototypes/ADT/Species/felinid.yml new file mode 100644 index 00000000000..ac031a61134 --- /dev/null +++ b/Resources/Prototypes/ADT/Species/felinid.yml @@ -0,0 +1,38 @@ +- type: species + id: Felinid + name: Фелинид + roundStart: true + prototype: MobFelinid + sprites: MobHumanSprites + markingLimits: MobFelinidMarkingLimits + dollPrototype: MobFelinidDummy + skinColoration: HumanToned + sponsorOnly: true + + +- type: markingPoints + id: MobFelinidMarkingLimits + points: + Hair: + points: 1 + required: false + FacialHair: + points: 1 + required: false + Tail: + points: 1 + required: true + defaultMarkings: [ CatTail ] + HeadTop: + points: 1 + required: true + defaultMarkings: [ CatEars ] + Chest: + points: 1 + required: false + Legs: + points: 2 + required: false + Arms: + points: 2 + required: false diff --git a/Resources/Prototypes/ADT/Voice/speech_emote_sounds.yml b/Resources/Prototypes/ADT/Voice/speech_emote_sounds.yml index 3b0bce180b4..ea79a005330 100644 --- a/Resources/Prototypes/ADT/Voice/speech_emote_sounds.yml +++ b/Resources/Prototypes/ADT/Voice/speech_emote_sounds.yml @@ -304,11 +304,11 @@ collection: MaleCry Whistle: collection: Whistles - # ADT-Apathy Sounds. + # ADT-Apathy Sounds. Scream-apathy: collection: NovakidScreams Laugh-apathy: - collection: NovakidLaugh + collection: NovakidLaugh Sigh-apathy: collection: MaleSigh Crying-apathy: @@ -347,16 +347,16 @@ collection: FemaleCry Whistle: collection: Whistles - # ADT-Apathy Sounds. + # ADT-Apathy Sounds. Scream-apathy: collection: NovakidScreams Laugh-apathy: - collection: NovakidLaugh + collection: NovakidLaugh Sigh-apathy: collection: FemaleSigh Crying-apathy: collection: FemaleCry - + - type: emoteSounds id: UnisexIPC sounds: @@ -534,3 +534,101 @@ collection: Whistles Heckaet: collection: VulpHeckaetSound + +- type: emoteSounds + id: MaleFelinid + params: + variation: 0.125 + sounds: + Scream: + collection: FelinidScreams + Laugh: + collection: MaleLaugh + Hiss: + collection: FelinidHisses + Meow: + collection: FelinidMeows + Mew: + collection: FelinidMews + Growl: + collection: FelinidGrowls + Purr: + collection: FelinidPurrs + Sneeze: + collection: MaleSneezes + Cough: + collection: MaleCoughs + MonkeyScreeches: + collection: MonkeyScreeches + RobotBeep: + collection: RobotBeeps + Yawn: + collection: MaleYawn + Snore: + collection: Snores + Honk: + collection: BikeHorn + Sigh: + collection: MaleSigh + Crying: + collection: MaleCry + Whistle: + collection: Whistles + # ADT-Apathy Sounds. + Scream-apathy: + collection: FelinidScreams + Laugh-apathy: + collection: MaleLaugh + Sigh-apathy: + collection: MaleSigh + Crying-apathy: + collection: MaleCry + +- type: emoteSounds + id: FemaleFelinid + params: + variation: 0.125 + sounds: + Scream: + collection: FelinidScreams + Laugh: + collection: FemaleLaugh + Sneeze: + collection: FemaleSneezes + Cough: + collection: FemaleCoughs + Hiss: + collection: FelinidHisses + Meow: + collection: FelinidMeows + Mew: + collection: FelinidMews + Growl: + collection: FelinidGrowls + Purr: + collection: FelinidPurrs + MonkeyScreeches: + collection: MonkeyScreeches + RobotBeep: + collection: RobotBeeps + Yawn: + collection: FemaleYawn + Snore: + collection: Snores + Honk: + collection: CluwneHorn + Sigh: + collection: FemaleSigh + Crying: + collection: FemaleCry + Whistle: + collection: Whistles + # ADT-Apathy Sounds. + Scream-apathy: + collection: FelinidScreams + Laugh-apathy: + collection: FemaleLaugh + Sigh-apathy: + collection: FemaleSigh + Crying-apathy: + collection: FemaleCry diff --git a/Resources/Prototypes/Actions/felinid.yml b/Resources/Prototypes/Actions/felinid.yml new file mode 100644 index 00000000000..7e6a5457a40 --- /dev/null +++ b/Resources/Prototypes/Actions/felinid.yml @@ -0,0 +1,12 @@ +- type: entity + id: ActionWoundLicking + name: Lick Wound + description: Stop bleeding by licking your wounds + noSpawn: true + components: + - type: EntityTargetAction + whitelist: { components: [ HumanoidAppearance ] } + interactOnMiss: false + icon: { sprite: Mobs/Species/Human/organs.rsi, state: tongue } + priority: -1 + event: !type:WoundLickingActionEvent