Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/Venuska1117/Paradise
Browse files Browse the repository at this point in the history
  • Loading branch information
Venuska1117 committed Jul 17, 2023
2 parents e94d0af + a416dd8 commit d2b409d
Show file tree
Hide file tree
Showing 49 changed files with 346 additions and 216 deletions.
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
/.github/workflows/ @AffectedArc07
/code/modules/unit_tests/ @AffectedArc07
/tools/ci/ @AffectedArc07
_build_dependencies.sh @AffectedArc07

# Server Stuff
/SQL/ @AffectedArc07
Expand Down
6 changes: 0 additions & 6 deletions code/__DEFINES/dcs/signals.dm
Original file line number Diff line number Diff line change
Expand Up @@ -575,14 +575,8 @@
#define COMPONENT_BLOCK_DEFIB_DEAD (1<<0)
/// Something else: we won't have a custom message for this and should let the defib handle it.
#define COMPONENT_BLOCK_DEFIB_MISC (1<<1)
/// If our safeties are on, turn them off for this shock.
#define COMPONENT_DEFIB_BECOME_THE_DANGER (1<<2)
/// If our safeties are off, turn them on for this shock.
#define COMPONENT_DEFIB_BECOME_SAFE (1<<3)
/// Called when a defib has been successfully used, and a shock has been applied. (mob/living/user, mob/living/target, harmful, successful)
#define COMSIG_DEFIB_SHOCK_APPLIED "defib_zap"
/// Called when a defib is aborted and no shock was applied. (mob/living/user, mob/living/target, harmful)
#define COMSIG_DEFIB_ABORTED "defib_aborted"
/// Called when a defib's cooldown has run its course and it is once again ready. ()
#define COMSIG_DEFIB_READY "defib_ready"

Expand Down
4 changes: 2 additions & 2 deletions code/__DEFINES/misc_defines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -402,9 +402,9 @@

// Defib stats
/// Past this much time the patient is unrecoverable (in deciseconds).
#define DEFIB_TIME_LIMIT 300 SECONDS
#define DEFIB_TIME_LIMIT (300 SECONDS)
/// Brain damage starts setting in on the patient after some time left rotting.
#define DEFIB_TIME_LOSS 60 SECONDS
#define DEFIB_TIME_LOSS (60 SECONDS)

//different types of atom colorations
#define ADMIN_COLOUR_PRIORITY 1 //only used by rare effects like greentext coloring mobs and when admins varedit color
Expand Down
5 changes: 5 additions & 0 deletions code/__HELPERS/filters.dm
Original file line number Diff line number Diff line change
Expand Up @@ -318,3 +318,8 @@ GLOBAL_LIST_INIT(master_filter_info, list(
filter = in_atom.get_filter("wibbly-[i]")
animate(filter)
in_atom.remove_filter("wibbly-[i]")

/// Used to create rays on an item. Make sure to removefilter("rays") when done with it
/atom/proc/ray_filter_helper(_priority = 1, _size = 40, _color = "#FFFFFF", _factor = 6, _density = 20)
add_filter(name = "ray", priority = _priority, params = list(type = "rays", size = _size, color = _color , factor = _factor, density = _density))

118 changes: 49 additions & 69 deletions code/datums/components/defibrillator.dm
Original file line number Diff line number Diff line change
Expand Up @@ -113,32 +113,25 @@
* Perform a defibrillation.
*/
/datum/component/defib/proc/defibrillate(mob/living/user, mob/living/carbon/human/target)
var/tobehealed
var/threshold = -HEALTH_THRESHOLD_DEAD
// Before we do all the hard work, make sure we aren't already defibbing someone
if(busy)
return

var/parent_unit = locateUID(actual_unit_uid)
var/should_cause_harm = user.a_intent == INTENT_HARM && !safety

// find what the defib should be referring to itself as
// Find what the defib should be referring to itself as
var/atom/defib_ref
if(parent_unit)
defib_ref = parent_unit
if(!defib_ref && robotic)
else if(robotic)
defib_ref = user
if(!defib_ref)
defib_ref = parent // contingency

// before we do all the hard work, make sure we aren't already defibbing someone
if(busy)
return
if(!defib_ref) // Contingency
defib_ref = parent

// check what the unit itself has to say about how the defib went
// Check what the unit itself has to say about how the defib went
var/application_result = SEND_SIGNAL(parent, COMSIG_DEFIB_PADDLES_APPLIED, user, target, should_cause_harm)

if(!should_cause_harm && (application_result & COMPONENT_DEFIB_BECOME_THE_DANGER))
should_cause_harm = TRUE
if(should_cause_harm && (application_result & COMPONENT_DEFIB_BECOME_SAFE))
should_cause_harm = FALSE

if(application_result & COMPONENT_BLOCK_DEFIB_DEAD)
user.visible_message("<span class='notice'>[defib_ref] beeps: Unit is unpowered.</span>")
playsound(get_turf(defib_ref), 'sound/machines/defib_failed.ogg', 50, 0)
Expand All @@ -149,7 +142,7 @@
return

if(application_result & COMPONENT_BLOCK_DEFIB_MISC)
return // the unit should handle this
return // The unit should handle this

if(!istype(target))
if(robotic)
Expand All @@ -174,9 +167,8 @@
window_flash(ghost.client)
ghost << sound('sound/effects/genetics.ogg')

if(!do_after(user, 3 SECONDS * speed_multiplier, target = target)) //beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
if(!do_after(user, 3 SECONDS * speed_multiplier, target = target)) // Beginning to place the paddles on patient's chest to allow some time for people to move away to stop the process
busy = FALSE
SEND_SIGNAL(parent, COMSIG_DEFIB_ABORTED, user, target, should_cause_harm)
return

user.visible_message("<span class='notice'>[user] places [parent] on [target]'s chest.</span>", "<span class='warning'>You place [parent] on [target]'s chest.</span>")
Expand All @@ -186,46 +178,33 @@
log_debug("Ghost of name [ghost.name] is bound to [target.real_name], but lacks a client. Deleting ghost.")
QDEL_NULL(ghost)

var/tplus = world.time - target.timeofdeath
var/tlimit = DEFIB_TIME_LIMIT
var/tloss = DEFIB_TIME_LOSS
var/total_burn = 0
var/total_brute = 0

var/signal_result = SEND_SIGNAL(target, COMSIG_LIVING_PRE_DEFIB, user, parent, ghost)

if(!do_after(user, 2 SECONDS * speed_multiplier, target = target)) //placed on chest and short delay to shock for dramatic effect, revive time is 5sec total
if(!do_after(user, 2 SECONDS * speed_multiplier, target = target)) // Placed on chest and short delay to shock for dramatic effect, revive time is 5sec total
busy = FALSE
SEND_SIGNAL(parent, COMSIG_DEFIB_ABORTED, user, target, should_cause_harm)
return

signal_result |= SEND_SIGNAL(target, COMSIG_LIVING_DEFIBBED, user, parent, ghost)
if(istype(target.wear_suit, /obj/item/clothing/suit/space) && !combat)
user.visible_message("<span class='notice'>[defib_ref] buzzes: Patient's chest is obscured. Operation aborted.</span>")
playsound(get_turf(defib_ref), 'sound/machines/defib_failed.ogg', 50, 0)
busy = FALSE
SEND_SIGNAL(parent, COMSIG_DEFIB_ABORTED, user, target, should_cause_harm)
return

signal_result |= SEND_SIGNAL(target, COMSIG_LIVING_DEFIBBED, user, parent, ghost)

if(signal_result & COMPONENT_DEFIB_OVERRIDE)
// let our signal handle it
// Let our signal handle it
busy = FALSE
SEND_SIGNAL(parent, COMSIG_DEFIB_ABORTED, user, target, should_cause_harm)
return

if(target.undergoing_cardiac_arrest())
if(!target.get_int_organ(/obj/item/organ/internal/heart) && !target.get_int_organ(/obj/item/organ/internal/brain/slime)) //prevents defibing someone still alive suffering from a heart attack attack if they lack a heart
user.visible_message("<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - Failed to pick up any heart electrical activity.</span>")
playsound(get_turf(defib_ref), 'sound/machines/defib_failed.ogg', 50, 0)
SEND_SIGNAL(parent, COMSIG_DEFIB_ABORTED, user, target, should_cause_harm)
busy = FALSE
return

if(target.undergoing_cardiac_arrest()) // Can have a heart attack and heart is either missing, necrotic, or not beating
var/obj/item/organ/internal/heart/heart = target.get_int_organ(/obj/item/organ/internal/heart)
if(heart.status & ORGAN_DEAD)
if(!heart)
user.visible_message("<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - Failed to pick up any heart electrical activity.</span>")
else if(heart.status & ORGAN_DEAD)
user.visible_message("<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - Heart necrosis detected.</span>")
if(!heart || (heart.status & ORGAN_DEAD))
playsound(get_turf(defib_ref), 'sound/machines/defib_failed.ogg', 50, 0)
SEND_SIGNAL(parent, COMSIG_DEFIB_ABORTED, user, target, should_cause_harm)
busy = FALSE
return

Expand All @@ -244,29 +223,23 @@
if(target.stat != DEAD && !HAS_TRAIT(target, TRAIT_FAKEDEATH))
user.visible_message("<span class='notice'>[defib_ref] buzzes: Patient is not in a valid state. Operation aborted.</span>")
playsound(get_turf(defib_ref), 'sound/machines/defib_failed.ogg', 50, 0)
SEND_SIGNAL(parent, COMSIG_DEFIB_ABORTED, user, target, should_cause_harm)
busy = FALSE
return

var/health = target.health
target.visible_message("<span class='warning'>[target]'s body convulses a bit.</span>")
playsound(get_turf(defib_ref), "bodyfall", 50, 1)
playsound(get_turf(defib_ref), 'sound/machines/defib_zap.ogg', 50, 1, -1)
for(var/obj/item/organ/external/O in target.bodyparts)
total_brute += O.brute_dam
total_burn += O.burn_dam
ghost = target.get_ghost(TRUE) // We have to double check whether the dead guy has entered their body during the above

var/defib_success = TRUE

// run through some quick failure states after shocking.
// Run through some quick failure states after shocking.
var/time_dead = world.time - target.timeofdeath

var/obj/item/organ/internal/brain/brain_org = target.get_organ_slot("brain")

if(tplus > tlimit || (!target.get_int_organ(/obj/item/organ/internal/heart || !target.get_int_organ(/obj/item/organ/internal/brain/slime))))
if(time_dead > DEFIB_TIME_LIMIT)
user.visible_message("<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - Heart tissue damage beyond point of no return for defibrillation.</span>")
defib_success = FALSE
else if(total_burn >= 180 || total_brute >= 180)
else if(target.getBruteLoss() >= 180 || target.getFireLoss() >= 180)
user.visible_message("<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - Severe tissue damage detected.</span>")
defib_success = FALSE
else if(HAS_TRAIT(target, TRAIT_HUSK))
Expand All @@ -275,44 +248,51 @@
else if (target.blood_volume < BLOOD_VOLUME_SURVIVE)
user.visible_message("<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - Patient blood volume critically low.</span>")
defib_success = FALSE
else if(!istype(brain_org)) // so things like headless clings don't get outed
else if(!target.get_organ_slot("brain")) // So things like headless clings don't get outed
user.visible_message("<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - No brain detected within patient.</span>")
defib_success = FALSE
else if(ghost)
if(!ghost.can_reenter_corpse) // DNR or AntagHUD
if(!ghost.can_reenter_corpse || target.suiciding) // DNR or AntagHUD
user.visible_message("<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - No electrical brain activity detected.</span>")
else
user.visible_message("<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed - Patient's brain is unresponsive. Further attempts may succeed.</span>")
defib_success = FALSE
else if((signal_result & COMPONENT_BLOCK_DEFIB) || HAS_TRAIT(target, TRAIT_FAKEDEATH) || HAS_TRAIT(target, TRAIT_BADDNA)) // these are a bit more arbitrary
else if((signal_result & COMPONENT_BLOCK_DEFIB) || HAS_TRAIT(target, TRAIT_FAKEDEATH) || HAS_TRAIT(target, TRAIT_BADDNA) || target.suiciding) // these are a bit more arbitrary
user.visible_message("<span class='boldnotice'>[defib_ref] buzzes: Resuscitation failed.</span>")
defib_success = FALSE

if(!defib_success)
playsound(get_turf(defib_ref), 'sound/machines/defib_failed.ogg', 50, 0)
else
tobehealed = min(health + threshold, 0) // It's HILARIOUS without this min statqement, let me tell you
tobehealed -= 5 //They get 5 of each type of damage healed so excessive combined damage will not immediately kill them after they get revived
target.adjustOxyLoss(tobehealed)
target.adjustToxLoss(tobehealed)
target.adjustFireLoss(tobehealed)
target.adjustBruteLoss(tobehealed)
if(target.get_int_organ(/obj/item/organ/internal/brain) && target.getBrainLoss() >= 100)
// Heal each basic damage type by as much as we're under -100 health
var/damage_above_threshold = -(min(target.health, HEALTH_THRESHOLD_DEAD) - HEALTH_THRESHOLD_DEAD)
var/heal_amount = damage_above_threshold + 5
target.adjustOxyLoss(-heal_amount)
target.adjustToxLoss(-heal_amount)
target.adjustFireLoss(-heal_amount)
target.adjustBruteLoss(-heal_amount)

// Inflict some brain damage scaling with time spent dead
var/defib_time_brain_damage = min(100 * time_dead / DEFIB_TIME_LIMIT, 99) // 20 from 1 minute onward, +20 per minute up to 99
if(time_dead > DEFIB_TIME_LOSS && defib_time_brain_damage > target.getBrainLoss())
target.setBrainLoss(defib_time_brain_damage)

target.update_revive()
target.KnockOut()
target.Paralyse(10 SECONDS)
target.emote("gasp")

if(target.getBrainLoss() >= 100)
// If you want to treat this with mannitol, it'll have to metabolize while the patient is alive, so it's alright to bring them back up for a minute
playsound(get_turf(defib_ref), 'sound/machines/defib_saftyoff.ogg', 50, 0)
user.visible_message("<span class='boldnotice'>[defib_ref] chimes: Minimal brain activity detected, brain treatment recommended for full resuscitation.</span>")
else
playsound(get_turf(defib_ref), 'sound/machines/defib_success.ogg', 50, 0)

user.visible_message("<span class='boldnotice'>[defib_ref] pings: Resuscitation successful.</span>")
target.update_revive()
target.KnockOut()
target.Paralyse(10 SECONDS)
target.emote("gasp")
if(tplus > tloss)
target.setBrainLoss(max(0, min(99, ((tlimit - tplus) / tlimit * 100))))

SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK, 100)
if(ishuman(target.pulledby)) // for some reason, pulledby isnt a list despite it being possible to be pulled by multiple people
if(ishuman(target.pulledby)) // For some reason, pulledby isnt a list despite it being possible to be pulled by multiple people
excess_shock(user, target, target.pulledby, defib_ref)
for(var/obj/item/grab/G in target.grabbed_by)
if(ishuman(G.assailant))
Expand Down Expand Up @@ -344,7 +324,7 @@
target.KnockDown(10 SECONDS)
playsound(get_turf(parent), 'sound/machines/defib_zap.ogg', 50, 1, -1)
target.emote("gasp")
if(combat && prob(heart_attack_chance)) // If the victim is not having a heart attack, and a 10% chance passes, or the defib has heart attack variable to TRUE while being a combat defib, or if another 10% chance passes with combat being TRUE
if(combat && prob(heart_attack_chance))
target.set_heartattack(TRUE)
SEND_SIGNAL(target, COMSIG_LIVING_MINOR_SHOCK, 100)
add_attack_logs(user, target, "Stunned with [parent]")
Expand Down
2 changes: 1 addition & 1 deletion code/datums/uplink_items/uplink_general.dm
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
/datum/uplink_item/device_tools/singularity_beacon
name = "Power Beacon"
desc = "When screwed to wiring attached to an electric grid and activated, this large device pulls any \
active gravitational singularities or tesla balls towards it. This will not work when the engine is still \
active gravitational singularities. This will not work when the engine is still \
in containment. Because of its size, it cannot be carried. Ordering this \
sends you a small beacon that will teleport the larger beacon to your location upon activation."
reference = "SNGB"
Expand Down
19 changes: 19 additions & 0 deletions code/game/gamemodes/wizard/soulstone.dm
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,21 @@
for(var/mob/living/simple_animal/shade/A in src)
A.death()
remove_held_body()
STOP_PROCESSING(SSobj, src)
return ..()

/obj/item/soulstone/process()
. = ..()
if(held_body)
var/new_filter = isnull(get_filter("ray"))
if(!purified)
ray_filter_helper(1, 40,"#c926ae", 6, 20)
else
ray_filter_helper(1, 40,"#268dc9", 6, 20)
if(new_filter)
animate(get_filter("ray"), offset = 10, time = 10 SECONDS, loop = -1)
animate(offset = 0, time = 10 SECONDS)

//////////////////////////////Capturing////////////////////////////////////////////////////////
/obj/item/soulstone/attack(mob/living/carbon/human/M, mob/living/user)
if(M == user)
Expand Down Expand Up @@ -162,6 +175,7 @@

add_attack_logs(user, M, "Stolestone'd with [name]")
transfer_soul("VICTIM", M, user)
START_PROCESSING(SSobj, src)
return

/obj/item/soulstone/attackby(obj/item/O, mob/user)
Expand All @@ -171,6 +185,7 @@
to_chat(user, "<span class='notice'>You begin to exorcise [src].</span>")
playsound(src, 'sound/hallucinations/veryfar_noise.ogg', 40, TRUE)
if(do_after(user, 40, target = src))
remove_filter("ray")
usability = TRUE
purified = TRUE
optional = TRUE
Expand All @@ -197,6 +212,7 @@
return
to_chat(user, "<span class='notice'>You begin to cleanse [src] of holy magic.</span>")
if(do_after(user, 40, target = src))
remove_filter("ray")
usability = FALSE
purified = FALSE
optional = FALSE
Expand Down Expand Up @@ -259,6 +275,8 @@
else
to_chat(A, "<span class='userdanger'>You have been released from your prison, but you are still bound to your [purified ? "saviour" : "creator"]'s will.</span>")
was_used()
remove_filter("ray")
STOP_PROCESSING(SSobj, src)

///////////////////////////Transferring to constructs/////////////////////////////////////////////////////
/obj/structure/constructshell
Expand Down Expand Up @@ -343,6 +361,7 @@
name = "soulstone : [T.name]"
to_chat(T, "<span class='notice'>Your soul has been recaptured by the soul stone, its arcane energies are reknitting your ethereal form</span>")
to_chat(user, "<span class='notice'>Capture successful!</span> [T.name]'s has been recaptured and stored within the soul stone.")
START_PROCESSING(SSobj, src)

if("CONSTRUCT")
var/obj/structure/constructshell/shell = target
Expand Down
3 changes: 3 additions & 0 deletions code/game/machinery/computer/aifixer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@
return
switch(action)
if("fix")
if(occupant.suiciding)
to_chat(usr, "<span class='warning'>Memory corruption detected in recovery partition, likely due to a sudden self-induced shutdown. AI is unrecoverable.</span>")
return
if(active) // Prevent from starting a fix while fixing.
to_chat(usr, "<span class='warning'>You are already fixing this AI!</span>")
return
Expand Down
6 changes: 5 additions & 1 deletion code/game/machinery/doors/airlock.dm
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ GLOBAL_LIST_EMPTY(airlock_emissive_underlays)
var/prying_so_hard = FALSE
var/paintable = TRUE // If the airlock type can be painted with an airlock painter
var/heat_resistance = 1500
/// Have we created sparks too recently?
var/on_spark_cooldown = FALSE

var/mutable_appearance/old_buttons_underlay
var/mutable_appearance/old_lights_underlay
Expand Down Expand Up @@ -757,10 +759,12 @@ GLOBAL_LIST_EMPTY(airlock_emissive_underlays)
return FALSE
living_mover.forceMove(get_turf(src))
return TRUE
if(isElectrified() && density && isitem(mover))
if(isElectrified() && density && isitem(mover) && !on_spark_cooldown)
var/obj/item/I = mover
if(I.flags & CONDUCT)
on_spark_cooldown = TRUE
do_sparks(5, 1, src)
addtimer(VARSET_CALLBACK(src, on_spark_cooldown, FALSE), 1 SECONDS)
return ..()

/obj/machinery/door/airlock/attack_animal(mob/user)
Expand Down
2 changes: 2 additions & 0 deletions code/game/machinery/firealarm.dm
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,8 @@ FIRE ALARM
if(!working || !report_fire_alarms)
return
var/area/A = get_area(src)
if(!A)
return
A.firealert(src) // Manually trigger alarms if the alarm isn't reported

/obj/machinery/firealarm/New(location, direction, building)
Expand Down
Loading

0 comments on commit d2b409d

Please sign in to comment.