private void TryInjectIntoBloodstream(BloodstreamComponent targetBloodstream, IEntity user) { if (!Owner.TryGetComponent(out SolutionContainerComponent? solution) || solution.CurrentVolume == 0) { return; } // Get transfer amount. May be smaller than _transferAmount if not enough room var realTransferAmount = ReagentUnit.Min(_transferAmount, targetBloodstream.EmptyVolume); if (realTransferAmount <= 0) { Owner.PopupMessage(user, Loc.GetString("You aren't able to inject {0:theName}!", targetBloodstream.Owner)); return; } // Move units from attackSolution to targetSolution var removedSolution = solution.SplitSolution(realTransferAmount); if (!targetBloodstream.TryTransferSolution(removedSolution)) { return; } Owner.PopupMessage(user, Loc.GetString("You inject {0}u into {1:theName}!", removedSolution.TotalVolume, targetBloodstream.Owner)); Dirty(); }
private void TryInjectIntoBloodstream(InjectorComponent component, BloodstreamComponent targetBloodstream, EntityUid user) { // Get transfer amount. May be smaller than _transferAmount if not enough room var realTransferAmount = FixedPoint2.Min(component.TransferAmount, targetBloodstream.ChemicalSolution.AvailableVolume); if (realTransferAmount <= 0) { _popup.PopupEntity(Loc.GetString("injector-component-cannot-inject-message", ("target", targetBloodstream.Owner)), component.Owner, Filter.Entities(user)); return; } // Move units from attackSolution to targetSolution var removedSolution = _solutions.SplitSolution(user, targetBloodstream.ChemicalSolution, realTransferAmount); _blood.TryAddToChemicals((targetBloodstream).Owner, removedSolution, targetBloodstream); removedSolution.DoEntityReaction(targetBloodstream.Owner, ReactionMethod.Injection); _popup.PopupEntity(Loc.GetString("injector-component-inject-success-message", ("amount", removedSolution.TotalVolume), ("target", targetBloodstream.Owner)), component.Owner, Filter.Entities(user)); Dirty(component); AfterInject(component); }
public GasMixture Clean(EntityUid uid, RespiratorComponent respirator, BloodstreamComponent bloodstream) { var gasMixture = new GasMixture(bloodstream.Air.Volume) { Temperature = bloodstream.Air.Temperature }; for (Gas gas = 0; gas < (Gas)Atmospherics.TotalNumberOfGases; gas++) { float amount; var molesInBlood = bloodstream.Air.GetMoles(gas); if (!respirator.NeedsGases.TryGetValue(gas, out var needed)) { amount = molesInBlood; } else { var overflowThreshold = needed * 5f; amount = molesInBlood > overflowThreshold ? molesInBlood - overflowThreshold : 0; } gasMixture.AdjustMoles(gas, amount); bloodstream.Air.AdjustMoles(gas, -amount); } return(gasMixture); }
private void OnReactionAttempt(EntityUid uid, BloodstreamComponent component, ReactionAttemptEvent args) { if (args.Solution.Name != BloodstreamComponent.DefaultBloodSolutionName && args.Solution.Name != BloodstreamComponent.DefaultChemicalsSolutionName && args.Solution.Name != BloodstreamComponent.DefaultBloodTemporarySolutionName) { return; } foreach (var effect in args.Reaction.Effects) { switch (effect) { case CreateEntityReactionEffect: // Prevent entities from spawning in the bloodstream case AreaReactionEffect: // No spontaneous smoke or foam leaking out of blood vessels. args.Cancel(); return; } } // The area-reaction effect canceling is part of avoiding smoke-fork-bombs (create two smoke bombs, that when // ingested by mobs create more smoke). This also used to act as a rapid chemical-purge, because all the // reagents would get carried away by the smoke/foam. This does still work for the stomach (I guess people vomit // up the smoke or spawned entities?). // TODO apply organ damage instead of just blocking the reaction? // Having cheese-clots form in your veins can't be good for you. }
private void OnComponentInit(EntityUid uid, BloodstreamComponent component, ComponentInit args) { component.Solution = _solutionContainerSystem.EnsureSolution(uid, DefaultSolutionName); if (component.Solution != null) { component.Solution.MaxVolume = component.InitialMaxVolume; } }
private void OnComponentInit(EntityUid uid, BloodstreamComponent component, ComponentInit args) { component.ChemicalSolution = _solutionContainerSystem.EnsureSolution(uid, BloodstreamComponent.DefaultChemicalsSolutionName); component.BloodSolution = _solutionContainerSystem.EnsureSolution(uid, BloodstreamComponent.DefaultBloodSolutionName); component.BloodTemporarySolution = _solutionContainerSystem.EnsureSolution(uid, BloodstreamComponent.DefaultBloodTemporarySolutionName); component.ChemicalSolution.MaxVolume = component.ChemicalMaxVolume; component.BloodSolution.MaxVolume = component.BloodMaxVolume; component.BloodTemporarySolution.MaxVolume = component.BleedPuddleThreshold * 4; // give some leeway, for chemstream as well // Fill blood solution with BLOOD _solutionContainerSystem.TryAddReagent(uid, component.BloodSolution, component.BloodReagent, component.BloodMaxVolume, out _); }
private void OnApplyMetabolicMultiplier(EntityUid uid, BloodstreamComponent component, ApplyMetabolicMultiplierEvent args) { if (args.Apply) { component.UpdateInterval *= args.Multiplier; return; } component.UpdateInterval /= args.Multiplier; // Reset the accumulator properly if (component.AccumulatedFrametime >= component.UpdateInterval) { component.AccumulatedFrametime = component.UpdateInterval; } }
private void TryInjectIntoBloodstream(BloodstreamComponent targetBloodstream, IEntity user) { if (!Owner.TryGetComponent(out SolutionContainerComponent? solution) || solution.CurrentVolume == 0) { return; } // Get transfer amount. May be smaller than _transferAmount if not enough room var realTransferAmount = ReagentUnit.Min(_transferAmount, targetBloodstream.EmptyVolume); if (realTransferAmount <= 0) { Owner.PopupMessage(user, Loc.GetString("You aren't able to inject {0:theName}!", targetBloodstream.Owner)); return; } // Move units from attackSolution to targetSolution var removedSolution = solution.SplitSolution(realTransferAmount); if (!solution.CanAddSolution(removedSolution)) { return; } // TODO: Account for partial transfer. foreach (var(reagentId, quantity) in removedSolution.Contents) { if (!_prototypeManager.TryIndex(reagentId, out ReagentPrototype reagent)) { continue; } removedSolution.RemoveReagent(reagentId, reagent.ReactionEntity(solution.Owner, ReactionMethod.Injection, quantity)); } solution.TryAddSolution(removedSolution); foreach (var(reagentId, quantity) in removedSolution.Contents) { if (!_prototypeManager.TryIndex(reagentId, out ReagentPrototype reagent)) { continue; } reagent.ReactionEntity(targetBloodstream.Owner, ReactionMethod.Injection, quantity); } Owner.PopupMessage(user, Loc.GetString("You inject {0}u into {1:theName}!", removedSolution.TotalVolume, targetBloodstream.Owner)); Dirty(); }
private void OnDamageChanged(EntityUid uid, BloodstreamComponent component, DamageChangedEvent args) { if (args.DamageDelta is null) { return; } // TODO probably cache this or something. humans get hurt a lot if (!_prototypeManager.TryIndex <DamageModifierSetPrototype>(component.DamageBleedModifiers, out var modifiers)) { return; } var bloodloss = DamageSpecifier.ApplyModifierSet(args.DamageDelta, modifiers); if (bloodloss.Empty) { return; } var oldBleedAmount = component.BleedAmount; var total = bloodloss.Total; var totalFloat = total.Float(); TryModifyBleedAmount(uid, totalFloat, component); var prob = Math.Clamp(totalFloat / 50, 0, 1); var healPopupProb = Math.Clamp(Math.Abs(totalFloat) / 25, 0, 1); if (totalFloat > 0 && _robustRandom.Prob(prob)) { TryModifyBloodLevel(uid, (-total) / 5, component); SoundSystem.Play(Filter.Pvs(uid), component.InstantBloodSound.GetSound(), uid, AudioParams.Default); } else if (totalFloat < 0 && oldBleedAmount > 0 && _robustRandom.Prob(healPopupProb)) { // Magically, this damage has healed some bleeding, likely // because it's burn damage that cauterized their wounds. // We'll play a special sound and popup for feedback. SoundSystem.Play(Filter.Pvs(uid), component.BloodHealedSound.GetSound(), uid, AudioParams.Default); _popupSystem.PopupEntity(Loc.GetString("bloodstream-component-wounds-cauterized"), uid, Filter.Entities(uid)); ; } }
private void OnHealthBeingExamined(EntityUid uid, BloodstreamComponent component, HealthBeingExaminedEvent args) { if (component.BleedAmount > 10) { args.Message.PushNewline(); args.Message.AddMarkup(Loc.GetString("bloodstream-component-profusely-bleeding", ("target", uid))); } else if (component.BleedAmount > 0) { args.Message.PushNewline(); args.Message.AddMarkup(Loc.GetString("bloodstream-component-bleeding", ("target", uid))); } if (GetBloodLevelPercentage(uid, component) < component.BloodlossThreshold) { args.Message.PushNewline(); args.Message.AddMarkup(Loc.GetString("bloodstream-component-looks-pale", ("target", uid))); } }
private void OnBeingGibbed(EntityUid uid, BloodstreamComponent component, BeingGibbedEvent args) { SpillAllSolutions(uid, component); }
private void DrawFromBlood(EntityUid user, EntityUid target, InjectorComponent component, Solution injectorSolution, BloodstreamComponent stream, FixedPoint2 transferAmount) { var drawAmount = (float)transferAmount; var bloodAmount = drawAmount; var chemAmount = 0f; if (stream.ChemicalSolution.CurrentVolume > 0f) // If they have stuff in their chem stream, we'll draw some of that { bloodAmount = drawAmount * 0.85f; chemAmount = drawAmount * 0.15f; } var bloodTemp = stream.BloodSolution.SplitSolution(bloodAmount); var chemTemp = stream.ChemicalSolution.SplitSolution(chemAmount); _solutions.TryAddSolution(component.Owner, injectorSolution, bloodTemp); _solutions.TryAddSolution(component.Owner, injectorSolution, chemTemp); _popup.PopupEntity(Loc.GetString("injector-component-draw-success-message", ("amount", transferAmount), ("target", Identity.Entity(target, EntityManager))), component.Owner, Filter.Entities(user)); Dirty(component); AfterDraw(component); }