-
Notifications
You must be signed in to change notification settings - Fork 292
add medbeam #3353
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
Open
CrimeMoot
wants to merge
12
commits into
master
Choose a base branch
from
beamHeal
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
add medbeam #3353
Changes from 5 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
7814a77
add medbeam
CrimeMoot e273a6b
issue
CrimeMoot c53fe6e
Merge branch 'master' into beamHeal
CrimeMoot a91a258
optimization Update attach
CrimeMoot 77f3f5e
Merge branch 'beamHeal' of https://github.com/AdventureTimeSS14/space…
CrimeMoot 6c29a3b
fix BloodRestore and hand
CrimeMoot 24016e1
issue name and folder
CrimeMoot b2024e1
power Med-gun odyssey
CrimeMoot 99a13f5
fix FixedPoint
CrimeMoot 77969ca
fix value
CrimeMoot 6ae2d1d
fix full heal power
CrimeMoot ad33719
remove update, RobustTimer add
CrimeMoot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| using Content.Shared.ADT.Weapons.Medbeam; | ||
|
|
||
| namespace Content.Client.ADT.Weapons.Medbeam; | ||
|
|
||
| public sealed class ADTMedbeamSystem : SharedADTMedbeamSystem | ||
| { | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,210 @@ | ||
| using System.Linq; | ||
| using System.Numerics; | ||
| using Content.Server.Explosion.EntitySystems; | ||
| using Content.Shared.ADT.Weapons.Medbeam; | ||
| using Content.Shared.Body.Components; | ||
| using Content.Shared.Body.Systems; | ||
| using Content.Shared.Damage.Systems; | ||
| using Content.Shared.Examine; | ||
| using Content.Shared.FixedPoint; | ||
| using Content.Shared.Mobs.Systems; | ||
| using Content.Shared.Mech.Components; | ||
| using Robust.Shared.Map; | ||
| using Robust.Shared.Physics.Systems; | ||
|
|
||
| namespace Content.Server.ADT.Weapons.Medbeam; | ||
|
|
||
| public sealed class ADTMedbeamSystem : SharedADTMedbeamSystem | ||
| { | ||
| [Dependency] private readonly DamageableSystem _damage = default!; | ||
| [Dependency] private readonly ExamineSystemShared _examine = default!; | ||
| [Dependency] private readonly SharedBloodstreamSystem _blood = default!; | ||
| [Dependency] private readonly ExplosionSystem _explosion = default!; | ||
| [Dependency] private readonly MobStateSystem _mobState = default!; | ||
| [Dependency] private readonly SharedTransformSystem _xform = default!; | ||
|
|
||
| private readonly HashSet<EntityUid> _activeBeams = new(); | ||
|
|
||
| public override void Update(float frameTime) | ||
| { | ||
| base.Update(frameTime); | ||
|
|
||
| if (_activeBeams.Count == 0) | ||
| return; | ||
|
|
||
| foreach (var uid in _activeBeams.ToArray()) | ||
| { | ||
| if (!Exists(uid)) | ||
| { | ||
| _activeBeams.Remove(uid); | ||
| continue; | ||
| } | ||
|
|
||
| var beam = Comp<ADTMedbeamComponent>(uid); | ||
|
|
||
| beam.Accumulator += frameTime; | ||
| if (beam.Accumulator < beam.UpdateInterval) | ||
| continue; | ||
|
|
||
| beam.Accumulator = 0; | ||
| TickBeam((uid, beam)); | ||
| } | ||
| } | ||
|
|
||
| public override void AttachBeam(Entity<ADTMedbeamComponent> ent, EntityUid target) | ||
| { | ||
| base.AttachBeam(ent, target); | ||
| _activeBeams.Add(ent.Owner); | ||
| } | ||
|
|
||
| public override void DetachBeam(Entity<ADTMedbeamComponent> ent) | ||
| { | ||
| _activeBeams.Remove(ent.Owner); | ||
| base.DetachBeam(ent); | ||
| } | ||
|
|
||
| private void TickBeam(Entity<ADTMedbeamComponent> ent) | ||
| { | ||
| var target = ent.Comp.Target; | ||
| if (!Exists(target)) | ||
| { | ||
| DetachBeam(ent); | ||
| return; | ||
| } | ||
|
|
||
| if (GetHolder(ent) is not { } holder) | ||
| { | ||
| DetachBeam(ent); | ||
| return; | ||
| } | ||
|
|
||
| if (TryComp<MechComponent>(holder, out var mech)) | ||
| { | ||
| if (mech.PilotSlot.ContainedEntity is not { } pilot || !_mobState.IsAlive(pilot)) | ||
| { | ||
| DetachBeam(ent); | ||
| return; | ||
| } | ||
| } | ||
| else if (ent.Comp.RequireMech || !_mobState.IsAlive(holder)) | ||
| { | ||
| DetachBeam(ent); | ||
| return; | ||
| } | ||
|
|
||
| if (!_examine.InRangeUnOccluded(ent.Owner, target.Value, ent.Comp.MaxRange, | ||
| entity => entity == ent.Owner || entity == target.Value)) | ||
| { | ||
| DetachBeam(ent); | ||
| return; | ||
| } | ||
|
|
||
| if (TryGetCrossing(ent, target.Value, out var otherGun, out var epicenter)) | ||
| { | ||
| ExplodeBeams(ent, (otherGun, Comp<ADTMedbeamComponent>(otherGun)), epicenter); | ||
| return; | ||
| } | ||
|
|
||
| _damage.TryChangeDamage(target.Value, ent.Comp.Damage, origin: ent.Owner); | ||
|
|
||
| if (ent.Comp.BloodRestore > 0 && HasComp<BloodstreamComponent>(target.Value)) | ||
| _blood.TryModifyBloodLevel(target.Value, (FixedPoint2) ent.Comp.BloodRestore); | ||
| } | ||
|
|
||
| private bool TryGetCrossing(Entity<ADTMedbeamComponent> ent, EntityUid target, out EntityUid otherGun, out MapCoordinates epicenter) | ||
| { | ||
| otherGun = default; | ||
| epicenter = default; | ||
|
|
||
| var gunCoords = _xform.GetMapCoordinates(ent.Owner); | ||
| var targetPos = _xform.GetMapCoordinates(target).Position; | ||
|
|
||
| var query = EntityQueryEnumerator<ADTMedbeamComponent>(); | ||
| while (query.MoveNext(out var uid, out var other)) | ||
| { | ||
| if (uid == ent.Owner || other.Target == null) | ||
| continue; | ||
|
|
||
| var otherCoords = _xform.GetMapCoordinates(uid); | ||
| var otherTargetCoords = _xform.GetMapCoordinates(other.Target.Value); | ||
| if (otherCoords.MapId != gunCoords.MapId || otherTargetCoords.MapId != gunCoords.MapId) | ||
| continue; | ||
|
|
||
| if (!TrySegmentIntersect(gunCoords.Position, targetPos, otherCoords.Position, otherTargetCoords.Position, out var point)) | ||
| continue; | ||
|
|
||
| otherGun = uid; | ||
| epicenter = new MapCoordinates(point, gunCoords.MapId); | ||
| return true; | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| private void ExplodeBeams(Entity<ADTMedbeamComponent> a, Entity<ADTMedbeamComponent> b, MapCoordinates epicenter) | ||
| { | ||
| a.Comp.Target = null; | ||
| a.Comp.Accumulator = 0; | ||
| b.Comp.Target = null; | ||
| b.Comp.Accumulator = 0; | ||
| Dirty(a.Owner, a.Comp); | ||
| Dirty(b.Owner, b.Comp); | ||
|
|
||
| var explosionType = a.Comp.ExplosionType; | ||
| var totalIntensity = a.Comp.ExplosionTotalIntensity; | ||
| var slope = a.Comp.ExplosionIntensitySlope; | ||
| var maxTileIntensity = a.Comp.ExplosionMaxTileIntensity; | ||
|
|
||
| _explosion.QueueExplosion(epicenter, explosionType, totalIntensity, slope, maxTileIntensity, cause: a.Owner); | ||
| _explosion.QueueExplosion(_xform.GetMapCoordinates(a.Owner), explosionType, totalIntensity, slope, maxTileIntensity, cause: a.Owner); | ||
| _explosion.QueueExplosion(_xform.GetMapCoordinates(b.Owner), explosionType, totalIntensity, slope, maxTileIntensity, cause: b.Owner); | ||
|
|
||
| QueueDel(a.Owner); | ||
| QueueDel(b.Owner); | ||
| } | ||
|
|
||
| private static bool TrySegmentIntersect(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2, out Vector2 point) | ||
| { | ||
| point = default; | ||
|
|
||
| var r = a2 - a1; | ||
| var s = b2 - b1; | ||
| var rxs = Cross(r, s); | ||
| var qmp = b1 - a1; | ||
|
|
||
| if (MathHelper.CloseTo(rxs, 0)) | ||
| { | ||
| if (!MathHelper.CloseTo(Cross(qmp, r), 0)) | ||
| return false; | ||
|
|
||
| var denom = Vector2.Dot(r, r); | ||
| if (MathHelper.CloseTo(denom, 0)) | ||
| return false; | ||
|
|
||
| var t0 = Vector2.Dot(qmp, r) / denom; | ||
| var t1 = t0 + Vector2.Dot(s, r) / denom; | ||
| var minT = MathF.Min(t0, t1); | ||
| var maxT = MathF.Max(t0, t1); | ||
|
|
||
| if (maxT < 0 || minT > 1) | ||
| return false; | ||
|
|
||
| point = a1 + r * Math.Clamp((minT + maxT) / 2, 0, 1); | ||
| return true; | ||
| } | ||
|
|
||
| var t = Cross(qmp, s) / rxs; | ||
| var u = Cross(qmp, r) / rxs; | ||
|
|
||
| if (t < 0 || t > 1 || u < 0 || u > 1) | ||
| return false; | ||
|
|
||
| point = a1 + r * t; | ||
| return true; | ||
| } | ||
|
|
||
| private static float Cross(Vector2 a, Vector2 b) | ||
| { | ||
| return a.X * b.Y - a.Y * b.X; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| using System.Numerics; | ||
| using Content.Shared.Damage; | ||
| using Content.Shared.Explosion; | ||
| using Content.Shared.Explosion.EntitySystems; | ||
| using Robust.Shared.GameStates; | ||
| using Robust.Shared.Prototypes; | ||
| using Robust.Shared.Utility; | ||
|
|
||
| namespace Content.Shared.ADT.Weapons.Medbeam; | ||
|
|
||
| [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] | ||
| public sealed partial class ADTMedbeamComponent : Component | ||
| { | ||
| /// <summary> | ||
| /// The entity currently being healed by the beam. | ||
| /// </summary> | ||
| [DataField, AutoNetworkedField] | ||
| public EntityUid? Target; | ||
|
|
||
| /// <summary> | ||
| /// Whether the gun only works while installed inside a mech. | ||
| /// </summary> | ||
| [DataField] | ||
| public bool RequireMech; | ||
|
|
||
| /// <summary> | ||
| /// How far the beam can stretch before it breaks. | ||
| /// </summary> | ||
| [DataField] | ||
| public float MaxRange = 8f; | ||
|
|
||
| /// <summary> | ||
| /// How often the beam heals the target. | ||
| /// </summary> | ||
| [DataField] | ||
| public float UpdateInterval = 1f; | ||
|
|
||
| [ViewVariables(VVAccess.ReadWrite)] | ||
| public float Accumulator; | ||
|
|
||
| /// <summary> | ||
| /// Healing applied per tick. Negative damage heals. | ||
| /// </summary> | ||
| [DataField] | ||
| public DamageSpecifier Damage = new(); | ||
|
|
||
| /// <summary> | ||
| /// How much blood is restored per tick. | ||
| /// </summary> | ||
| [DataField] | ||
| public float BloodRestore = 5f; | ||
|
|
||
| /// <summary> | ||
| /// Explosion triggered when two beams cross. | ||
| /// </summary> | ||
| [DataField] | ||
| public ProtoId<ExplosionPrototype> ExplosionType = SharedExplosionSystem.DefaultExplosionPrototypeId; | ||
|
|
||
| [DataField] | ||
| public float ExplosionTotalIntensity = 100f; | ||
|
|
||
| [DataField] | ||
| public float ExplosionIntensitySlope = 4f; | ||
|
|
||
| [DataField] | ||
| public float ExplosionMaxTileIntensity = 10f; | ||
|
|
||
| [DataField] | ||
| public SpriteSpecifier Beam = | ||
| new SpriteSpecifier.Rsi(new ResPath("/Textures/ADT/Misc/medbeam.rsi"), "medbeam"); | ||
|
|
||
| [DataField] | ||
| public SpriteSpecifier? Start; | ||
|
|
||
| [DataField] | ||
| public SpriteSpecifier? End; | ||
|
|
||
| [DataField] | ||
| public Vector2 Scale = Vector2.One; | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.