Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reflectors #76

Merged
merged 15 commits into from
Sep 22, 2024
97 changes: 97 additions & 0 deletions Content.Server/Stories/Reflectors/RefrectorSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using System.Numerics;
using Content.Server.Weapons.Ranged.Systems;
using Content.Shared.Popups;
using Content.Shared.Projectiles;
using Direction = Robust.Shared.Maths.Direction;
using Content.Shared.Stories.Reflectors;
using Content.Shared.Whitelist;
using Content.Shared.Weapons.Ranged.Components;
using Robust.Shared.Map;
using Robust.Shared.Network;

namespace Content.Server.Stories.Reflectors;
public sealed class ReflectorSystem : EntitySystem
{
[Dependency] private readonly EntityWhitelistSystem _whitelistSystem = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly INetManager _netManager = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly GunSystem _gun = default!;

public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<ReflectorComponent, ProjectileReflectAttemptEvent>(OnReflectCollide);
}

private void OnReflectCollide(EntityUid uid, ReflectorComponent component, ref ProjectileReflectAttemptEvent args)
{
if (args.Cancelled)
return;

var collisionDirection = CalculateCollisionDirection(uid, args.ProjUid);
if (component.BlockedDirections.Contains(collisionDirection.ToString()))
return;

if (TryReflectProjectile(uid, component, args.ProjUid , collisionDirection))
args.Cancelled = true;
}
private Direction CalculateCollisionDirection(EntityUid uid, EntityUid projectile)
{
var projWorldPos = _transform.GetWorldPosition(projectile);
var uidWorldMatrix = _transform.GetInvWorldMatrix(Transform(uid));
var localCollisionPoint = Vector2.Transform(projWorldPos, uidWorldMatrix);

return localCollisionPoint.ToAngle().GetCardinalDir();

}

private bool TryReflectProjectile(EntityUid user, ReflectorComponent component , EntityUid projectile, Direction collisionDirection)
{
if (!TryComp<ReflectiveComponent>(projectile, out var reflective) ||
reflective.Reflective == 0x0 ||
!TryComp<GunComponent>(user, out var gunComponent) ||
_whitelistSystem.IsBlacklistPass(component.Blacklist, projectile) ||
_whitelistSystem.IsWhitelistFail(component.Whitelist, projectile))
{
return false;
}

var targetOffset = ReflectBasedOnType(component, collisionDirection);
if (!targetOffset.HasValue)
return false;

var xform = Transform(user);
var targetPos = new EntityCoordinates(user, targetOffset.Value);

_transform.SetLocalPosition(projectile, xform.LocalPosition + xform.LocalRotation.RotateVec(targetOffset.Value));

_gun.Shoot(user, gunComponent, projectile, xform.Coordinates, targetPos, out _);

if (_netManager.IsServer)
_popup.PopupEntity(Loc.GetString("reflect-shot"), user);

return true;
}

private Vector2 ReflectAngular(Direction collisionDirection)
{
return collisionDirection switch
{
Direction.North => Vector2.UnitY,
Direction.South => -Vector2.UnitY,
Direction.East => -Vector2.UnitX,
Direction.West => Vector2.UnitX,
_ => throw new ArgumentOutOfRangeException(nameof(collisionDirection)),
};
}
private Vector2? ReflectBasedOnType(ReflectorComponent component, Direction collisionDirection)
{
return component.State switch
{
ReflectorType.Simple => component.ReflectionDirection?.ToVec(),
ReflectorType.Angular => ReflectAngular(collisionDirection),
_ => throw new ArgumentOutOfRangeException(nameof(component.State), component.State, "Invalid ReflectorType encountered."),
};
}
}
31 changes: 31 additions & 0 deletions Content.Shared/Stories/Reflectors/RefrectorComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Content.Shared.Whitelist;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;

namespace Content.Shared.Stories.Reflectors;

[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
public sealed partial class ReflectorComponent : Component
{
[DataField]
public EntityWhitelist? Whitelist;

[DataField]
public EntityWhitelist? Blacklist;

[DataField]
public List<string> BlockedDirections = new();

[DataField]
public Direction? ReflectionDirection;

[DataField, AutoNetworkedField]
public ReflectorType State = ReflectorType.Simple;
}

[Serializable, NetSerializable]
public enum ReflectorType
{
Simple,
Angular,
}
3 changes: 3 additions & 0 deletions Resources/Prototypes/Entities/Structures/Machines/lathe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,9 @@
- MassMediaCircuitboard
- ReagentGrinderIndustrialMachineCircuitboard
- JukeboxCircuitBoard
- ReflectorBoxMachineCircuitboard # Stories
- ReflectorCornerMachineCircuitboard # Stories
- ReflectorCornerTsideMachineCircuitboard # Stories
Comment on lines +521 to +523
Copy link
Contributor

Choose a reason for hiding this comment

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

Ты добавил новую технологию, но тут не убрал.

Copy link
Contributor Author

@NikitosAseev NikitosAseev Sep 21, 2024

Choose a reason for hiding this comment

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

это dynamicRecipes , иначе говоря при изучении технологии отражения у принтера схем открывается рецепт
без него при изучении технологии - крафта плат не будет

Copy link
Contributor

Choose a reason for hiding this comment

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

Понял.

- type: EmagLatheRecipes
emagDynamicRecipes:
- ShuttleGunDusterCircuitboard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,61 @@
Manipulator: 1
materialRequirements:
Glass: 1

- type: entity
id: ReflectorBoxMachineCircuitboard
parent: BaseMachineCircuitboard
name: Отражатель, тип "Коробка"
description: Машинная плата отражателя, тип "Коробка"
components:
- type: Sprite
sprite: Stories/Objects/Misc/module.rsi
state: reflectorbox_circuitboard
- type: MachineBoard
prototype: ReflectorBox
stackRequirements:
Capacitor: 3
CableHV: 10
componentRequirements:
PowerCell:
amount: 1
defaultPrototype: PowerCellMedium

- type: entity
id: ReflectorCornerMachineCircuitboard
parent: BaseMachineCircuitboard
name: Отражатель, тип "Угловой"
description: Машинная плата отражателя, тип "Угловой"
components:
- type: Sprite
sprite: Stories/Objects/Misc/module.rsi
state: reflectorcorner_circuitboard
- type: MachineBoard
prototype: ReflectorCorner
stackRequirements:
Capacitor: 3
CableHV: 10
componentRequirements:
PowerCell:
amount: 1
defaultPrototype: PowerCellMedium

- type: entity
id: ReflectorCornerTsideMachineCircuitboard
parent: BaseMachineCircuitboard
name: Отражатель, тип "Двойной-Угловой"
description: Машинная плата отражателя, тип "Двойной-Угловой"
components:
- type: Sprite
sprite: Stories/Objects/Misc/module.rsi
state: reflectortsidecorner_circuitboard
- type: MachineBoard
prototype: ReflectoCornerTside
stackRequirements:
Capacitor: 3
CableHV: 10
componentRequirements:
PowerCell:
amount: 1
defaultPrototype: PowerCellMedium

Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
- type: entity
categories: [ HideSpawnMenu ]
id: BaseReflector
parent: [ BaseMachine, ConstructibleMachine ]
components:
- type: Transform
noRot: false
- type: Sprite
sprite: Stories/Structures/Machines/reflectors.rsi
- type: Reflector
whitelist:
tags:
- EmitterBolt
components:
- AnomalousParticle
- type: Gun
projectileSpeed: 5
soundGunshot:
path: /Audio/Weapons/Guns/Gunshots/taser2.ogg
- type: Rotatable
rotateWhileAnchored: true
- type: Lock
locked: false
- type: LockedAnchorable
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 100
behaviors:
- !type:PlaySoundBehavior
sound:
collection: MetalBreak
- !type:ChangeConstructionNodeBehavior
node: machineFrame
- !type:DoActsBehavior
acts: ["Destruction"]

- type: entity
id: ReflectorBox
parent: BaseReflector
name: Отражатель, тип "Коробка"
description: Это устройство, способное отражать снаряды, попадающие в него, в указанном направлении.
components:
- type: Sprite
state: reflector_circle
- type: Reflector
blockedDirections:
- West
reflectionDirection: South
ReflectorType: Simple
- type: Machine
board: ReflectorBoxMachineCircuitboard
- type: Rotatable
rotateWhileAnchored: true

- type: entity
id: ReflectorCorner
parent: BaseReflector
name: Отражатель, тип "Угловой"
description: Это устройство, способное отражать снаряды, попадающие в него, в указанном направлении.
components:
- type: Sprite
state: reflector_corner
- type: Reflector
blockedDirections:
- East
- North
state: Angular
- type: Machine
board: ReflectorCornerMachineCircuitboard
- type: Rotatable
rotateWhileAnchored: true
- type: Fixtures
fixtures:
fix1:
shape:
!type:PolygonShape
vertices:
- "-0.3, 0.35"
- "-0.3, -0.3"
- "0.35, 0.35"
mask:
- FullTileMask
layer:
- FullTileLayer


- type: entity
id: ReflectorCornerTside
parent: BaseReflector
name: Отражатель, тип "Двойной-Угловой"
description: Это устройство, способное отражать снаряды, попадающие в него, в указанном направлении.
components:
- type: Sprite
state: reflector_corner_tside
- type: Reflector
state: Angular
- type: Machine
board: ReflectorCornerTsideMachineCircuitboard
- type: Rotatable
rotateWhileAnchored: true
- type: Fixtures
fixtures:
fix1:
shape:
!type:PolygonShape
vertices:
- "0.15, 0.25"
- "-0.1, -0.3"
- "0.3, 0.15"
- "-0.2, -0.1"
mask:
- FullTileMask
layer:
- FullTileLayer
17 changes: 16 additions & 1 deletion Resources/Prototypes/Stories/Lathes/misc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,19 @@
completetime: 4
materials:
Steel: 100
Glass: 900
Glass: 900

- type: latheRecipe
parent: BaseCircuitboardRecipe
id: ReflectorBoxMachineCircuitboard
result: ReflectorBoxMachineCircuitboard

- type: latheRecipe
parent: BaseCircuitboardRecipe
id: ReflectorCornerMachineCircuitboard
result: ReflectorCornerMachineCircuitboard

- type: latheRecipe
parent: BaseCircuitboardRecipe
id: ReflectorCornerTsideMachineCircuitboard
result: ReflectorCornerTsideMachineCircuitboard
13 changes: 13 additions & 0 deletions Resources/Prototypes/Stories/Research/industrial.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
- type: technology
id: ReflectionTech
name: Технологии отражения
icon:
sprite: Stories/Structures/Machines/reflectors.rsi
state: reflector_circle
discipline: Industrial
tier: 2
cost: 5000
recipeUnlocks:
- ReflectorBoxMachineCircuitboard
- ReflectorCornerMachineCircuitboard
- ReflectorCornerTsideMachineCircuitboard
20 changes: 20 additions & 0 deletions Resources/Textures/Stories/Objects/Misc/module.rsi/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Space Stories",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "reflectorbox_circuitboard"
},
{
"name": "reflectorcorner_circuitboard"
},
{
"name": "reflectortsidecorner_circuitboard"
}
]
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading