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
Merged
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,
}
19 changes: 17 additions & 2 deletions Resources/Prototypes/Recipes/Lathes/electronics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
parent: BaseElectronicsRecipe
id: BaseCheapCircuitboardRecipe
materials:
Steel: 50
Glass: 250
Copy link
Contributor

Choose a reason for hiding this comment

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

Не форматируй код оффов.

Steel: 50
Glass: 250

- type: latheRecipe
abstract: true
Expand Down Expand Up @@ -596,3 +596,18 @@
parent: BaseCircuitboardRecipe
id: CutterMachineCircuitboard
result: CutterMachineCircuitboard

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

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

- type: latheRecipe
parent: BaseCircuitboardRecipe
id: ReflectorCornerTsideMachineCircuitboard
result: ReflectorCornerTsideMachineCircuitboard
Copy link
Contributor

Choose a reason for hiding this comment

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

Перенеси в Stories папку.

3 changes: 3 additions & 0 deletions Resources/Prototypes/Research/industrial.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@
recipeUnlocks:
- ThermomachineFreezerMachineCircuitBoard
- GasRecyclerMachineCircuitboard
- ReflectorBoxMachineCircuitboard
- ReflectorCornerMachineCircuitboard
- ReflectorCornerTsideMachineCircuitboard
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
- ReflectorBoxMachineCircuitboard
- ReflectorCornerMachineCircuitboard
- ReflectorCornerTsideMachineCircuitboard
- ReflectorBoxMachineCircuitboard # Stories
- ReflectorCornerMachineCircuitboard # Stories
- ReflectorCornerTsideMachineCircuitboard # Stories


- type: technology
id: RipleyAPLU
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
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