Skip to content
Open
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
26 changes: 26 additions & 0 deletions Content.Client/Imperial/Medieval/Bonfire/BonfireSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Robust.Client.GameObjects;
using Content.Shared.Imperial.Medieval.Bonfire;

namespace Content.Client.Imperial.Medieval.Bonfire;

public sealed class BonfireSystem : EntitySystem
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<BonfireComponent, AppearanceChangeEvent>(OnAppearanceChange);
}
private void OnAppearanceChange(EntityUid uid, BonfireComponent component, ref AppearanceChangeEvent args)
{
if (args.Sprite == null)
return;

if (_appearance.TryGetData<bool>(uid, BonfireVisualLayers.Fire, out var isFireVisible, args.Component))
{
args.Sprite.LayerSetVisible(BonfireVisualLayers.Fire, isFireVisible);
}
}
}
217 changes: 217 additions & 0 deletions Content.Server/Imperial/Medieval/Bonfire/BonfireSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
using Robust.Server.GameObjects;
using Content.Shared.Interaction;
using Content.Shared.Stacks;
using Robust.Shared.Audio;
using Content.Server.Audio;
using Robust.Shared.Audio.Systems;
using Content.Shared.Imperial.Medieval.Bonfire;
using Content.Server.Imperial.Medieval.Igniter;
using Content.Shared.Examine;
using Content.Shared.Popups;
using Content.Shared.Tag;
using Content.Shared.Audio;
using Content.Shared.Placeable;
using Content.Shared.DoAfter;
using Content.Server.Temperature.Systems;

namespace Content.Server.Imperial.Medieval.Bonfire;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Система не понятно почему на сервере, это кринж


public sealed class BonfireSystem : EntitySystem
{
[Dependency] protected readonly SharedAudioSystem _audio = default!;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

зачем здесь протектед хз, нигде не наследуется

Suggested change
[Dependency] protected readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;

[Dependency] private readonly SharedPointLightSystem _lights = default!;
[Dependency] private readonly AmbientSoundSystem _ambientSound = default!;
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly TagSystem _tagSystem = default!;
[Dependency] private readonly SharedStackSystem _stack = default!;
[Dependency] private readonly TemperatureSystem _temperature = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;

private const float FuelDecreasePerSecond = 0.11f;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Почему эти данные хардкодно зашиты в системе, а не находятся в компоненте - под вопросом.
Перенести в компонент по-хорошему

private const float BoardFuelAmount = 20f;
private const float LogFuelAmount = 40f;
private const float SheetFuelAmount = 15f;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<BonfireComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<BonfireComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<BonfireComponent, IgnitionDoAfterEvent>(OnIgnitionDoAfter);
}

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

var query = EntityQueryEnumerator<BonfireComponent, ItemPlacerComponent>();
while (query.MoveNext(out var uid, out var bonfire, out var placer))
{
if (bonfire.IsLit == BonfireVisuals.Off)
continue;

var heat = bonfire.HeatingPower * frameTime;
foreach (var ent in placer.PlacedEntities)
{
_temperature.ChangeHeat(ent, heat);
}

bonfire.CurrentFuel = MathF.Max(0, bonfire.CurrentFuel - FuelDecreasePerSecond * frameTime);
UpdateBonfireVisuals(uid, bonfire);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

каждый тик обновляется визуализация костра т.е. вызываются
_lights.SetEnergy(uid, energy);
_lights.SetRadius(uid, radius, light);
что потенциально может привести к лагам.


if (bonfire.CurrentFuel <= 0)
{
bonfire.CurrentFuel = 0;
ExtinguishBonfire(uid, bonfire);
}
}
}

private void UpdateBonfireVisuals(EntityUid uid, BonfireComponent component)
{
var fuelPercentage = component.CurrentFuel / component.MaxFuel;
var radius = fuelPercentage switch
{
> 0.8f => 5f,
> 0.5f => 4.5f,
> 0.3f => 3.5f,
> 0.1f => 2.8f,
_ => 2f
};

if (TryComp<PointLightComponent>(uid, out var light))
{
_lights.SetRadius(uid, radius, light);
}

var energy = fuelPercentage switch
{
> 0.8f => 3f,
> 0.5f => 2.5f,
> 0.3f => 2f,
> 0.1f => 1.5f,
_ => 1f
};
_lights.SetEnergy(uid, energy);
}

private void OnExamined(EntityUid uid, BonfireComponent component, ExaminedEvent args)
{
if (component.IsLit == BonfireVisuals.Off)
{
args.PushText("Костёр не горит.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Хардкод локализация.
Совет:

Loc.GetString("loc-key", ("var-name", component.IsLit == BonfireVisuals.Off));
loc-key =
    { $var-name ->
        [true] Тру 
       *[other] Фолс
    }

return;
}

var fuelLevel = (int)(component.CurrentFuel / component.MaxFuel * 100);
var fuelDescription = fuelLevel switch
{
> 80 => "яркое",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Снова хардкод локализация

> 50 => "теплое",
> 20 => "обычное",
_ => "тухлое"
};

args.PushText($"У костра {fuelDescription} пламя.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тоже хардкод локализация

}

private void OnInteractUsing(EntityUid uid, BonfireComponent component, InteractUsingEvent args)
{
if (args.Handled)
return;

if (component.IsLit == BonfireVisuals.Off && HasComp<IgniterComponent>(args.Used))
{
if (component.CurrentFuel <= 0)
{
_popupSystem.PopupEntity("Нет топлива для розжига!", uid, args.User, PopupType.Medium);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Хардкод локализация

return;
}

var doAfterArgs = new DoAfterArgs(EntityManager, args.User, 2f, new IgnitionDoAfterEvent(), uid, args.Target, args.Used)
{
BreakOnMove = true,
BreakOnDamage = true,
NeedHand = true,
BreakOnDropItem = true
};

_doAfterSystem.TryStartDoAfter(doAfterArgs);
args.Handled = true;
return;
}

if (_tagSystem.HasTag(args.Used, "Wooden") || _tagSystem.HasTag(args.Used, "Log") || _tagSystem.HasTag(args.Used, "Sheet"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Потенциальные +5 ворнингов(включая свитч ниже) forbids literal values.
Должно быть в компоненте или ХОТЯ-БЫ как private const

private const string TagWooden = "Wooden";

{
float fuelAmount = 0;

switch (true)
{
case bool when _tagSystem.HasTag(args.Used, "Log"):
fuelAmount = LogFuelAmount;
break;
case bool when _tagSystem.HasTag(args.Used, "Sheet"):
fuelAmount = SheetFuelAmount;
break;
case bool when _tagSystem.HasTag(args.Used, "Wooden"):
fuelAmount = BoardFuelAmount;
break;
}

if (TryComp<StackComponent>(args.Used, out var stack) && stack.Count > 1)
{
_stack.SetCount(args.Used, stack.Count - 1);
}
else
{
EntityManager.DeleteEntity(args.Used);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
EntityManager.DeleteEntity(args.Used);
QueueDel(args.Used);

}

component.CurrentFuel = Math.Min(component.CurrentFuel + fuelAmount, component.MaxFuel);
_popupSystem.PopupEntity("Вы подложили топливо в костер", uid, args.User, PopupType.Medium);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

хардкод локализация

UpdateBonfireVisuals(uid, component);
args.Handled = true;
}
}

private void OnIgnitionDoAfter(EntityUid uid, BonfireComponent component, IgnitionDoAfterEvent args)
{
if (args.Handled || args.Cancelled)
return;

LightBonfire(uid, component);
args.Handled = true;
}

private void LightBonfire(EntityUid uid, BonfireComponent component)
{
component.IsLit = BonfireVisuals.Fire;

EnsureComp<PointLightComponent>(uid);

_lights.SetEnabled(uid, true);
_lights.SetColor(uid, Color.FromHex("#FFC90C"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

хардкод значения. Тож по хорошему должно быть в компоненте

_lights.SetEnergy(uid, 3);

UpdateBonfireVisuals(uid, component);

EnsureComp<AmbientSoundComponent>(uid);

_ambientSound.SetSound(uid, new SoundPathSpecifier("/Audio/Ambience/Objects/fireplace.ogg"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

хардкод звук, должно быть в компоненте

_ambientSound.SetRange(uid, 5);
_ambientSound.SetVolume(uid, -5);
_ambientSound.SetAmbience(uid, true);

_appearance.SetData(uid, BonfireVisualLayers.Fire, true);
_audio.PlayPvs(new SoundPathSpecifier(component.IgnitionSound), uid);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Почему SoundPathSpecifier здесь, а не в компоненте?

}

private void ExtinguishBonfire(EntityUid uid, BonfireComponent component)
{
component.IsLit = BonfireVisuals.Off;
_lights.SetEnabled(uid, false);
_ambientSound.SetAmbience(uid, false);
_appearance.SetData(uid, BonfireVisualLayers.Fire, false);
_audio.PlayPvs(new SoundPathSpecifier(component.ExtinguishSound), uid);
}
}
44 changes: 44 additions & 0 deletions Content.Shared/Imperial/Medieval/Bonfire/BonfireComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Robust.Shared.Serialization;
using Robust.Shared.GameStates;
using Content.Shared.DoAfter;

namespace Content.Shared.Imperial.Medieval.Bonfire;

[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
public sealed partial class BonfireComponent : Component
{
[DataField]
public string IgnitionSound = "/Audio/Items/Flare/flare_on.ogg";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public string IgnitionSound = "/Audio/Items/Flare/flare_on.ogg";
public SoundSpecifier IgnitionSound = new SoundPathSpecifier("/Audio/Items/Flare/flare_on.ogg");


[DataField]
public string ExtinguishSound = "/Audio/Items/candle_blowing.ogg";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

То же самое что и IgnitionSound


[DataField, AutoNetworkedField]
public BonfireVisuals IsLit = BonfireVisuals.Off;

[DataField]
public float MaxFuel = 100f;

[DataField, AutoNetworkedField]
public float CurrentFuel = 0f;

[DataField]
public float HeatingPower = 1200f;
}

[Serializable, NetSerializable]
public sealed partial class IgnitionDoAfterEvent : SimpleDoAfterEvent { }

[Serializable, NetSerializable]
public enum BonfireVisuals : byte
{
Off,
Fire
}

[Serializable, NetSerializable]
public enum BonfireVisualLayers : byte
{
Bonfire,
Fire
}
4 changes: 4 additions & 0 deletions Resources/Locale/ru-RU/Imperial/Medieval/medieval.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,10 @@ ent-MedievalShovel = лопатка
ent-MedievalCampfire = костёр
.desc = Оружие инквизиции...
.suffix = { "Средневековье, станок" }
ent-MedievalBonfire = костёр
.desc = Источник света и тепла!
.suffix = { "Средневековье" }

ent-MedievalMobFox = лиса
.desc = Она имеет густой рыжий мех и длинный хвост. Некоторые люди считают, что лисы - это коварные создания, но на самом деле они очень умные и адаптивные.
.suffix = { "Средневековье, моб" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@
- type: Produce
seedId: towercap
- type: Log
#imperial-medieval-start
- type: Tag
tags:
- Log
#imperial-medieval-end

- type: entity
name: steel-cap log
Expand Down
70 changes: 70 additions & 0 deletions Resources/Prototypes/Imperial/Medieval/medieval.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7738,3 +7738,73 @@
doAfter: 4
- node: MedievalMortarTool
entity: MedievalMortarTool

- type: entity
id: MedievalBonfire
parent: BaseStructure
name: Campfire
description: A source of light and heat!
components:
- type: Sprite
noRot: true
sprite: Imperial/Medieval/Decor/campfire.rsi
layers:
- state: wood
map: ["enum.BonfireVisualLayers.Bonfire"]
- state: fire
map: ["enum.BonfireVisualLayers.Fire"]
visible: false
- type: Appearance
- type: Damageable
damageContainer: StructuralInorganic
damageModifierSet: Wood
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 50
behaviors:
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: Construction
graph: Campfire
node: campfire
- type: Bonfire
- type: ItemPlacer
maxEntities: 2
whitelist:
components:
- Temperature
- type: PlaceableSurface

- type: construction
name: Костер
id: CampfireConstruction
graph: Campfire
startNode: start
targetNode: campfire
category: construction-category-misc
description: Тёплый огонь для ночных посиделок.
icon:
sprite: Imperial/Medieval/Decor/campfire.rsi
state: wood
objectType: Structure
placementMode: SnapgridCenter
canBuildInImpassable: false
conditions:
- !type:TileNotBlocked

- type: constructionGraph
id: Campfire
start: start
graph:
- node: start
edges:
- to: campfire
steps:
- tag: Log
name: "Бревно"
doAfter: 3

- node: campfire
entity: MedievalBonfire
3 changes: 3 additions & 0 deletions Resources/Prototypes/Imperial/Medieval/tags.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,6 @@

- type: Tag
id: GoblinArmor

- type: Tag
id: Log
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading