Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 3 additions & 12 deletions Content.Server/Imperial/Vampire/VampireSystem.Abilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@ private void OnStartSleep(VampireSleepEvent args)
BreakOnMove = true,
BreakOnDamage = true,
NeedHand = false,
BlockDuplicate = true
BlockDuplicate = true,
Hidden = true
};

_doAfter.TryStartDoAfter(doAfterArgs);
Expand Down Expand Up @@ -265,14 +266,6 @@ private void OnTurn(VampireTurnEvent args)
return;
}

if (vamp.GhoulQuantity < args.NecessaryGhoulQuantity)
{
_popup.PopupEntity(Loc.GetString("vampire-popup-ghoul-quantity", ("quantity", args.NecessaryGhoulQuantity - vamp.GhoulQuantity)),
args.Performer, args.Performer, PopupType.Medium);

return;
}

switch (vamp.SelectedSubgroup)
{
case VampireAbilityType.Hemomancer:
Expand Down Expand Up @@ -310,10 +303,8 @@ private void OnTurn(VampireTurnEvent args)
args.Handled = true;
}

public override void Update(float frameTime)
public void AbilitiesUpdate()
{
base.Update(frameTime);

var queryVampBat = EntityQueryEnumerator<VampireComponent>();
while (queryVampBat.MoveNext(out var uid, out var vamp))
{
Expand Down
9 changes: 1 addition & 8 deletions Content.Server/Imperial/Vampire/VampireSystem.Ghoul.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
using Content.Shared.Interaction;
using Content.Shared.Radio.Components;
using Content.Shared.Radio;
using Robust.Shared.Player;
using Content.Shared.Mind.Components;

namespace Content.Server.Imperial.Vampire;

Expand All @@ -23,13 +21,8 @@ private void OnGetDrinkingGhoul(EntityUid uid, GhoulComponent comp, GetVerbsEven
if (!args.CanAccess || !args.CanInteract || uid == args.Target || !_mobState.IsAlive(args.Target))
return;

// если у цели нет крови/разума, кнопки не добавляем
if (!HasComp<BloodstreamComponent>(args.Target) || !HasComp<MindContainerComponent>(args.Target)
|| !HasComp<ActorComponent>(args.Target))
return;

// верб для питья крови
if (!HasComp<GhoulComponent>(args.Target) && !HasComp<VampireComponent>(args.Target))
if (!HasComp<GhoulComponent>(args.Target) && !HasComp<VampireComponent>(args.Target) && HasComp<BloodstreamComponent>(args.Target))
{
var verbDrinkBloodGhoul = new InnateVerb
{
Expand Down
110 changes: 91 additions & 19 deletions Content.Server/Imperial/Vampire/VampireSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
using Content.Shared.Mindshield.Components;
using Content.Shared.Mind.Components;
using Content.Shared.Mobs;
using Content.Server.Bible.Components;
using Content.Shared.Alert;
using System.Runtime.CompilerServices;
using Content.Server.Body;
using System.Linq;
Expand All @@ -50,6 +52,7 @@ public sealed partial class VampireSystem : EntitySystem
[Dependency] private readonly MobStateSystem _mobState = default!;
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
[Dependency] private readonly AlertsSystem _alert = default!;
[Dependency] private readonly VisualBodySystem _visualBodySystem = default!;


Expand Down Expand Up @@ -80,14 +83,10 @@ private void OnGetVerbsCombined(EntityUid uid, VampireComponent vamp, GetVerbsEv
|| !_mobState.IsAlive(args.Target))
return;

// если у цели нет крови/разума, кнопки не добавляем
if (!HasComp<BloodstreamComponent>(args.Target) || !HasComp<MindContainerComponent>(args.Target)
|| !HasComp<ActorComponent>(args.Target))
return;

// верб для превращения цели в упыря
if (!HasComp<GhoulComponent>(args.Target) && !HasComp<VampireComponent>(args.Target)
&& !HasComp<MindShieldComponent>(args.Target) && !_statusEffects.HasStatusEffect(uid, vamp.CooldownStatusEffectAppealGhouls))
if (!HasComp<GhoulComponent>(args.Target) && !HasComp<VampireComponent>(args.Target) && HasComp<MindContainerComponent>(args.Target)
&& !HasComp<MindShieldComponent>(args.Target) && !_statusEffects.HasStatusEffect(uid, vamp.CooldownStatusEffectAppealGhouls)
&& HasComp<ActorComponent>(args.Target))
{
var verbConvert = new InnateVerb
{
Expand All @@ -101,7 +100,7 @@ private void OnGetVerbsCombined(EntityUid uid, VampireComponent vamp, GetVerbsEv
}

// верб для питья крови
if (!HasComp<GhoulComponent>(args.Target) && !HasComp<VampireComponent>(args.Target))
if (!HasComp<GhoulComponent>(args.Target) && !HasComp<VampireComponent>(args.Target) && HasComp<BloodstreamComponent>(args.Target))
{
var verbDrinkBlood = new InnateVerb
{
Expand Down Expand Up @@ -135,6 +134,12 @@ private void StartConversion(EntityUid vampire, EntityUid target)
if (!TryComp<VampireComponent>(vampire, out var vamp))
return;

if (vamp.GhoulQuantity == vamp.MaxNumberGhouls)
{
_popup.PopupEntity(Loc.GetString("vampire-popup-max-number-ghouls"), vampire, vampire, PopupType.Medium);
return;
}

_popup.PopupEntity(Loc.GetString("vampire-verb-envelope-vampire-transform",
("target", MetaData(target).EntityName)),
vampire, vampire, PopupType.Medium);
Expand Down Expand Up @@ -208,38 +213,70 @@ private void DrinkingComplete(EntityUid drinker, EntityUid target, float amount)
// вычисляем текущее количество крови
float currentBlood = vamp != null ? vamp.CritThreshold - vamp.BloodDamage : ghoul!.CritThreshold - ghoul.BloodDamage;

if (vamp != null && currentBlood >= 100)
if (currentBlood >= 100 || !HasComp<MindContainerComponent>(target) || !HasComp<ActorComponent>(target))
{
// мы просто засчитываем эту кровь в TotalDrunk, но BloodDamage не понижаем
vamp.TotalDrunk += amount;
_audio.PlayPvs(vamp.DrinkSound, drinker);

damage.DamageDict["Bloodloss"] = FixedPoint2.New(amount * 2);
_damage.TryChangeDamage(target, damage);
if (vamp != null)
{
// мы просто засчитываем эту кровь в TotalDrunk, но BloodDamage не понижаем
if (currentBlood >= 100 && HasComp<MindContainerComponent>(target) && HasComp<ActorComponent>(target))
{
vamp.TotalDrunk += amount;
_vampireSystem.SetBloodCounterAlert(drinker, vamp);
}
// мы просто понижаем BloodDamage, но в TotalDrunk не засчитываем
else if (!HasComp<MindContainerComponent>(target) || !HasComp<ActorComponent>(target))
{
if (currentBlood >= 100)
{
_popup.PopupEntity(Loc.GetString("vampire-popup-target-no-mind-full"), drinker, drinker, PopupType.Medium);
return;
}

vamp.BloodDamage = Math.Max(vamp.BloodDamage - amount / 2, 0);
_vampireSystem.SetBloodAlert(drinker, vamp);
_popup.PopupEntity(Loc.GetString("vampire-popup-target-no-mind"), drinker, drinker, PopupType.Medium);
}

_audio.PlayPvs(vamp.DrinkSound, drinker);

damage.DamageDict["Bloodloss"] = FixedPoint2.New(amount);
_damage.TryChangeDamage(target, damage);

var eui = new VampireRequestedEui(drinker, EntityManager, _actions, _vampireSystem, _prototypeManager);
eui.GrantAbilities(drinker, vamp.SelectedSubgroup);

// после того, как вампир выпивает кровь его глаза становятся красными
TrySetEntityEyeColor(drinker, Color.Red);

if (_mobState.IsAlive(target))
StartDrinking(drinker, target);
if (_mobState.IsAlive(target))
StartDrinking(drinker, target);

return;
return;
}
}

// увеличиваем количество крови
if (vamp != null)
{
vamp.BloodDamage = Math.Max(vamp.BloodDamage - amount, 0f);
_vampireSystem.SetBloodCounterAlert(drinker, vamp);
_vampireSystem.SetBloodAlert(drinker, vamp);
vamp.TotalDrunk += amount;
_audio.PlayPvs(vamp.DrinkSound, drinker);
}
else if (ghoul != null)
{
ghoul.BloodDamage = Math.Max(ghoul.BloodDamage - amount, 0f);
if (ghoul.BloodDamage - amount < 0)
{
_popup.PopupEntity(Loc.GetString("vampire-drinking-full-blood"), drinker, drinker, PopupType.Medium);
return;
}

if (!HasComp<MindContainerComponent>(target) || !HasComp<ActorComponent>(target))
ghoul.BloodDamage = Math.Max(ghoul.BloodDamage - amount / 2, 0);
else
ghoul.BloodDamage = Math.Max(ghoul.BloodDamage - amount, 0f);

_vampireSystem.SetGhoulBloodAlert(drinker, ghoul);
_audio.PlayPvs(ghoul.DrinkSound, drinker);
}
Expand Down Expand Up @@ -313,6 +350,41 @@ private void OnSelectingSubgroup(VampireSelectingSubgroupEvent args)
_eui.OpenEui(eui, actor.PlayerSession);
}

public override void Update(float frameTime)
{
base.Update(frameTime);

BaseUpdate(frameTime);
AbilitiesUpdate();
}

public void BaseUpdate(float frameTime)
{
var querySearch = EntityQueryEnumerator<VampireComponent>();
while (querySearch.MoveNext(out var uid, out var comp))
{
comp.UpdateDelay += frameTime;
var priests = _lookup.GetEntitiesInRange<BibleUserComponent>(Transform(uid).Coordinates, 7).FirstOrNull();

if (priests == null || _mobState.IsDead(priests.Value))
{
_alert.ClearAlert(uid, comp.AdjacentChaplainAlert);
comp.UpdateDelay = 0f;
continue;
}

if (comp.UpdateDelay < 1)
continue;

_damage.TryChangeDamage(uid, comp.DivineDamage);
_audio.PlayPvs(comp.DivineDamageSound, uid);
_popup.PopupEntity(Loc.GetString("vampire-popup-chaplain-closely"), uid, uid, PopupType.Medium);
_alert.ShowAlert(uid, comp.AdjacentChaplainAlert);

comp.UpdateDelay = 0;
}
}

private bool TrySetEntityEyeColor(EntityUid uid, Color eyeColor)
{
if (!_visualBodySystem.TryGatherMarkingsData(uid, null, out var profiles, out _, out var markings)) return false;
Expand Down
4 changes: 2 additions & 2 deletions Content.Shared/Imperial/Vampire/Components/GhoulComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public sealed partial class GhoulComponent : Component
/// Интервал между тиками потери крови
/// </summary>
[DataField]
public TimeSpan BloodDecayInterval = TimeSpan.FromSeconds(30);
public TimeSpan BloodDecayInterval = TimeSpan.FromSeconds(60);

/// <summary>
/// количество урона за каждый тик
Expand All @@ -43,7 +43,7 @@ public sealed partial class GhoulComponent : Component
/// количество выпитой крови за 1 тик
/// </summary>
[DataField("bloodPerTick")]
public float BloodPerTick = 1;
public float BloodPerTick = 3;

/// <summary>
/// сколько занимает излечение упыря
Expand Down
60 changes: 58 additions & 2 deletions Content.Shared/Imperial/Vampire/Components/VampireComponent.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Content.Shared.Alert;
using Content.Shared.Damage;
using Content.Shared.FixedPoint;
using Content.Shared.StatusIcon;
using Robust.Shared.Audio;
using Robust.Shared.GameStates;
Expand Down Expand Up @@ -91,7 +93,7 @@ public sealed partial class VampireComponent : Component
/// количество выпитой крови за 1 тик
/// </summary>
[DataField("bloodPerTick")]
public float BloodPerTick = 1;
public float BloodPerTick = 3;

/// <summary>
/// кд между призывами катаны
Expand Down Expand Up @@ -186,6 +188,32 @@ public sealed partial class VampireComponent : Component
[DataField("bloodLossDisguiseIsActive")]
public float BloodLossDisguiseIsActive = 1;

/// <summary>
/// время следующего тика потери крови
/// </summary>
public TimeSpan NextBloodDecay = TimeSpan.Zero;

/// <summary>
/// Интервал между тиками потери крови
/// </summary>
[DataField]
public TimeSpan BloodDecayInterval = TimeSpan.FromSeconds(45);

/// <summary>
/// количество урона за каждый тик
/// </summary>
[DataField]
public float BloodDecayAmount = 2f;

[DataField]
public EntProtoId GhoulPuddleID = "VampirePuddle";

/// <summary>
/// длительность тряски при критическом состоянии
/// </summary>
[DataField]
public TimeSpan ShakingTime = TimeSpan.FromSeconds(5);

[DataField]
public string VampirePuddleID = "VampirePuddle";

Expand Down Expand Up @@ -312,9 +340,37 @@ public sealed partial class VampireComponent : Component
/// длительность cooldown на обращение в упырей
/// </summary>
[DataField("cooldownTimeAppealGhouls")]
public TimeSpan CooldownTimeAppealGhouls = TimeSpan.FromMinutes(1);
public TimeSpan CooldownTimeAppealGhouls = TimeSpan.FromMinutes(2.5f);

[DataField]
public string CooldownStatusEffectAppealGhouls = "AppealGhoulsCooldown";

[DataField]
public DamageSpecifier DivineDamage = new DamageSpecifier
{
DamageDict = new Dictionary<string, FixedPoint2>
{
["Heat"] = 2
}
};

[DataField]
public SoundSpecifier DivineDamageSound = new SoundPathSpecifier("/Audio/Effects/lightburn.ogg")
{
Params = AudioParams.Default.WithVolume(3)
};

[AutoNetworkedField]
public float UpdateDelay;

[DataField]
public ProtoId<AlertPrototype> AdjacentChaplainAlert = "VampireAdjacentChaplainAlert";

/// <summary>
/// максимальное количество упырей, которое может иметь вампир
/// </summary>
[DataField]
public int MaxNumberGhouls = 5;

}
}
6 changes: 0 additions & 6 deletions Content.Shared/Imperial/Vampire/Event/VampireActionEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -343,12 +343,6 @@ public sealed partial class VampireTurnEvent : InstantActionEvent
{
[DataField("costBlood")]
public float CostBlood = 30;

/// <summary>
/// необходимо иметь упырей для обращения
/// </summary>
[DataField("necessaryGhoulQuantity")]
public int NecessaryGhoulQuantity = 25;
}

public sealed partial class VampireSwordEvent : InstantActionEvent
Expand Down
Loading
Loading