[Sponsor] Pets summon book + Wanderer_ pet (#44)

* Pets summon book ready

* fix name
This commit is contained in:
HitPanda
2023-05-11 21:49:17 +03:00
committed by Aviu00
parent eb1f363f90
commit 5954d821c5
10 changed files with 341 additions and 1 deletions

View File

@@ -0,0 +1,28 @@
using Content.Shared.Actions.ActionTypes;
using Robust.Shared.Utility;
namespace Content.Server.White.Other.CustomFluffSystems.Pets;
[RegisterComponent]
public sealed class PetSummonComponent : Component
{
public InstantAction PetSummonAction = new()
{
Icon = new SpriteSpecifier.Texture(new ResPath("Objects/Misc/books.rsi/summon_book.png")),
DisplayName = "Призыв",
Description = "Призыв питомца БЕЗ возможности вселения призрака",
Event = new PetSummonActionEvent()
};
public InstantAction PetGhostSummonAction = new()
{
Icon = new SpriteSpecifier.Texture(new ResPath("Mobs/Ghosts/ghost_human.rsi/icon.png")),
DisplayName = "Призрачный призыв",
Description = "Призыв питомца С возможностью вселения призрака",
Event = new PetGhostSummonActionEvent()
};
public int UsesLeft = 10;
public EntityUid? SummonedEntity;
}

View File

@@ -0,0 +1,172 @@
using Content.Server.Ghost.Roles.Components;
using Content.Shared.ActionBlocker;
using Content.Shared.Actions;
using Content.Shared.Examine;
using Content.Shared.Item;
using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
using Content.Shared.Popups;
using Content.Shared.Verbs;
using Robust.Server.GameObjects;
namespace Content.Server.White.Other.CustomFluffSystems.Pets;
public sealed class PetSummonSystem : EntitySystem
{
[Dependency] private readonly ActionBlockerSystem _blocker = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly SharedActionsSystem _actions = default!;
private IReadOnlyDictionary<string, string> MobMap = new Dictionary<string, string>()
{
{ "Wanderer_", "KommandantPetSpider" },
};
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PetSummonComponent, GetItemActionsEvent>(GetSummonAction);
SubscribeLocalEvent<PetSummonComponent, ExaminedEvent>(OnExamine);
SubscribeLocalEvent<PetSummonComponent, GetVerbsEvent<AlternativeVerb>>(AddSummonVerb);
SubscribeLocalEvent<PetSummonComponent, PetSummonActionEvent>(OnSummon);
SubscribeLocalEvent<PetSummonComponent, PetGhostSummonActionEvent>(OnGhostSummon);
}
private void OnGhostSummon(EntityUid uid, PetSummonComponent component, PetGhostSummonActionEvent args)
{
AttemptSummon(component, args.Performer, true);
}
private void OnSummon(EntityUid uid, PetSummonComponent component, PetSummonActionEvent args)
{
AttemptSummon(component, args.Performer, false);
}
private void AddSummonVerb(EntityUid uid, PetSummonComponent component, GetVerbsEvent<AlternativeVerb> args)
{
if (!args.CanInteract || !args.CanAccess)
return;
AlternativeVerb verb = new()
{
Act = () =>
{
AttemptSummon(component, args.User, false);
},
Text = "Призвать питомца",
Priority = 2
};
AlternativeVerb ghostVerb = new()
{
Act = () =>
{
AttemptSummon(component, args.User, true);
},
Text = "Призвать питомца-призрак",
Priority = 2
};
args.Verbs.Add(verb);
args.Verbs.Add(ghostVerb);
}
private void OnExamine(EntityUid uid, PetSummonComponent component, ExaminedEvent args)
{
args.PushMarkup($"Осталось призывов: {component.UsesLeft}");
}
private void AttemptSummon(PetSummonComponent component, EntityUid user, bool ghostRole)
{
if (!_blocker.CanInteract(user, component.Owner))
return;
string? mobProto = null;
if (TryComp<ActorComponent>(user, out var actorComponent))
{
var userKey = actorComponent.PlayerSession.Name;
if (!MobMap.TryGetValue(userKey, out var proto))
{
_popupSystem.PopupEntity("Вы не достойны", user, PopupType.Medium);
return;
}
mobProto = proto;
}
if (component.UsesLeft == 0)
{
_popupSystem.PopupEntity("Больше нет зарядов!", user, PopupType.Medium);
return;
}
if (component.SummonedEntity != null)
{
if (!TryComp<MobStateComponent>(component.SummonedEntity, out var mobState))
{
component.SummonedEntity = null;
}
else
{
if (mobState.CurrentState is MobState.Dead or MobState.Invalid)
component.SummonedEntity = null;
else
{
_popupSystem.PopupEntity("Ваш питомец уже призван", user, PopupType.Medium);
return;
}
}
}
if (mobProto != null)
SummonPet(user, component, mobProto, ghostRole);
}
private void SummonPet(EntityUid user, PetSummonComponent component, string mobProto, bool ghostRole)
{
var transform = CompOrNull<TransformComponent>(user)?.Coordinates;
if (transform == null)
return;
var entity = _entityManager.SpawnEntity(mobProto, transform.Value);
component.UsesLeft--;
component.SummonedEntity = entity;
if (ghostRole)
SetupGhostRole(entity, user);
else
RemComp<GhostRoleComponent>(entity);
}
private void SetupGhostRole(EntityUid entity, EntityUid user)
{
EnsureComp<GhostTakeoverAvailableComponent>(entity);
if (!TryComp<GhostRoleComponent>(entity, out var ghostRole))
return;
var meta = MetaData(user);
ghostRole.RoleName = $"Питомец {meta.EntityName}";
ghostRole.RoleDescription = $"Следуйте за хозяином - {meta.EntityName} и выполняйте его приказы";
ghostRole.RoleRules = $"Вы должны до самого конца следовать за своим хозяином - {meta.EntityName} и послушно выполнять его приказы, иначе можете быть уничтожены.";
}
private void GetSummonAction(EntityUid uid, PetSummonComponent component, GetItemActionsEvent args)
{
args.Actions.Add(component.PetSummonAction);
args.Actions.Add(component.PetGhostSummonAction);
}
}
public sealed class PetSummonActionEvent : InstantActionEvent
{
}
public sealed class PetGhostSummonActionEvent : InstantActionEvent
{
}

View File

@@ -163,3 +163,21 @@
damage:
types:
Blunt: 0
# Pets book
- type: entity
parent: BookBase
id: PetSummonBook
name: странная потрёпанная книга
description: Книга непонятного происхождения.
suffix: Флафф
components:
- type: Sprite
sprite: Objects/Misc/books.rsi
layers:
- state: summon_book
- type: Item
size: 5
- type: Paper
content: Ego voco electi pet
- type: PetSummon

View File

@@ -57,3 +57,9 @@
id: OmntnsHammerLoadout
entity: OmntnsHammer
sponsorOnly: true
# Pets summon book
- type: loadout
id: PetsSummonBookLoadout
entity: PetSummonBook
sponsorOnly: true

View File

@@ -0,0 +1,73 @@
# Kommandant
- type: entity
parent: SimpleMobBase
id: KommandantPetSpider
name: паук Валера
description: Любит мух и деньги.
components:
- type: Faction
factions:
- PetsNT
- type: Sprite
drawdepth: Mobs
layers:
- map: [ "enum.DamageStateVisualLayers.Base" ]
state: viper
sprite: White/Mobs/Pets/Kommandant/spider.rsi
scale: "0.5, 0.5"
- type: Physics
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeCircle
radius: 0.35
density: 130
mask:
- MobMask
layer:
- MobLayer
- type: Appearance
- type: DamageStateVisuals
states:
Alive:
Base: viper
Critical:
Base: viper_dead
Dead:
Base: viper_dead
- type: MobThresholds
thresholds:
0: Alive
90: Critical
150: Dead
- type: ReplacementAccent
accent: xeno
- type: InteractionPopup
successChance: 0.5
interactSuccessString: petting-success-tarantula
interactFailureString: petting-failure-generic
- type: IgnoreSpiderWeb
- type: NoSlip
- type: CanEscapeInventory
- type: Grammar
attributes:
proper: true
gender: female
- type: Bloodstream
bloodMaxVolume: 150
bloodReagent: SpiderBlood
- type: Pacifist
- type: Tag
tags:
- CannotSuicide
- type: Item
size: 10
- type: GhostRole
makeSentient: true
allowSpeech: true
allowMovement: true
name: "Питомец"
description: "Следуйте за хозяином"
rules: "Всегда следуйте за хозяином и слушайте его приказы."

View File

@@ -101,6 +101,9 @@
},
{
"name": "book_fish"
},
{
"name": "summon_book"
}
]
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 B

View File

@@ -0,0 +1,40 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "https://github.com/frosty-dev/white",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "viper",
"directions": 4,
"delays": [
[
0.2,
0.2,
0.2
],
[
0.2,
0.2,
0.2
],
[
0.2,
0.2,
0.2
],
[
0.2,
0.2,
0.2
]
]
},
{
"name": "viper_dead"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 806 B