Merge branch 'Citadel-Station-13:master' into Projectile_Rework

This commit is contained in:
Solaris-Shade
2022-03-19 11:23:16 -04:00
committed by GitHub
32 changed files with 542 additions and 337 deletions
+1 -1
View File
@@ -182,7 +182,7 @@
////organ defines
#define STANDARD_ORGAN_THRESHOLD 100
#define STANDARD_ORGAN_HEALING (1/(15 MINUTES / (2 SECONDS)))
#define STANDARD_ORGAN_HEALING (1/(15 MINUTES / (2 SECONDS))) / 3 //Base organ healing can be amped by a factor of up to x5 via satiety. This assumes it to be somewhat in the upper center of positive satiety as base.
#define STANDARD_ORGAN_DECAY (1/(15 MINUTES / (2 SECONDS))) //designed to fail organs when left to decay for ~15 minutes. 2 SECOND is SSmobs tickrate.
+3
View File
@@ -63,6 +63,9 @@
#define THRESHOLD_UNHUSK 50 // health threshold for synthflesh/rezadone to unhusk someone
#define SYNTHTISSUE_BORROW_CAP 250 //The cap for synthtissue's borrowed health value when used on someone dead or already having borrowed health.
#define SYNTHTISSUE_DAMAGE_FLIP_CYCLES 45 //After how many cycles the damage will be pure toxdamage as opposed to clonedamage like initially. Gradually changes during its cycles.
//reagent bitflags, used for altering how they works
#define REAGENT_DEAD_PROCESS (1<<0) //calls on_mob_dead() if present in a dead body
#define REAGENT_DONOTSPLIT (1<<1) //Do not split the chem at all during processing
+3
View File
@@ -5,6 +5,9 @@
#define HIGHEST_MEDIAN_VOTING "HIGHEST_MEDIAN"
#define INSTANT_RUNOFF_VOTING "IRV"
#define VOTE_TRANSFER "Initiate Crew Transfer"
#define VOTE_CONTINUE "Continue Playing"
#define SHOW_RESULTS (1<<0)
#define SHOW_VOTES (1<<1)
#define SHOW_WINNER (1<<2)
+4
View File
@@ -109,6 +109,10 @@
if (CONFIG_GET(flag/log_attack))
WRITE_LOG(GLOB.world_attack_log, "ATTACK: [text]")
/proc/log_victim(text)
if (CONFIG_GET(flag/log_victim))
WRITE_LOG(GLOB.world_victim_log, "VICTIM: [text]")
/proc/log_manifest(ckey, datum/mind/mind,mob/body, latejoin = FALSE)
if (CONFIG_GET(flag/log_manifest))
WRITE_LOG(GLOB.world_manifest_log, "[ckey] \\ [body.real_name] \\ [mind.assigned_role] \\ [mind.special_role ? mind.special_role : "NONE"] \\ [latejoin ? "LATEJOIN":"ROUNDSTART"]")
+2
View File
@@ -11,6 +11,8 @@ GLOBAL_VAR(world_qdel_log)
GLOBAL_PROTECT(world_qdel_log)
GLOBAL_VAR(world_attack_log)
GLOBAL_PROTECT(world_attack_log)
GLOBAL_VAR(world_victim_log)
GLOBAL_PROTECT(world_victim_log)
// GLOBAL_VAR(world_econ_log)
// GLOBAL_PROTECT(world_econ_log)
GLOBAL_VAR(world_href_log)
+1 -1
View File
@@ -17,7 +17,7 @@
P.pixel_x = planet_offset_x
P.pixel_y = planet_offset_y
. += P
if(random_layer)
if(ispath(random_layer, /atom/movable/screen/parallax_layer))
. += new random_layer
if(ispath(random_layer, /atom/movable/screen/parallax_layer/space/random/space_gas))
var/atom/movable/screen/parallax_layer/space/random/space_gas/SG = locate(random_layer) in objects
@@ -1,88 +1,119 @@
/datum/config_entry/flag/log_ooc // log OOC channel
/// log OOC channel
/datum/config_entry/flag/log_ooc
config_entry_value = TRUE
/datum/config_entry/flag/log_access // log login/logout
/// log login/logout
/datum/config_entry/flag/log_access
config_entry_value = TRUE
/// Config entry which special logging of failed logins under suspicious circumstances.
/datum/config_entry/flag/log_suspicious_login
config_entry_value = TRUE
/datum/config_entry/flag/log_say // log client say
/// log client say
/datum/config_entry/flag/log_say
config_entry_value = TRUE
/datum/config_entry/flag/log_admin // log admin actions
/// log admin actions
/datum/config_entry/flag/log_admin
protection = CONFIG_ENTRY_LOCKED
config_entry_value = TRUE
/datum/config_entry/flag/log_prayer // log prayers
/// log prayers
/datum/config_entry/flag/log_prayer
config_entry_value = TRUE
/datum/config_entry/flag/log_law // log lawchanges
/// log lawchanges
/datum/config_entry/flag/log_law
config_entry_value = TRUE
/datum/config_entry/flag/log_game // log game events
/// log game events
/datum/config_entry/flag/log_game
config_entry_value = TRUE
/datum/config_entry/flag/log_virus // log virology data
/// log virology data
/datum/config_entry/flag/log_virus
config_entry_value = TRUE
/datum/config_entry/flag/log_vote // log voting
/// log voting
/datum/config_entry/flag/log_vote
config_entry_value = TRUE
/datum/config_entry/flag/log_craft // log crafting
/// log crafting
/datum/config_entry/flag/log_craft
config_entry_value = TRUE
/datum/config_entry/flag/log_whisper // log client whisper
/// log client whisper
/datum/config_entry/flag/log_whisper
config_entry_value = TRUE
/datum/config_entry/flag/log_attack // log attack messages
/// log attack messages
/datum/config_entry/flag/log_attack
config_entry_value = TRUE
/datum/config_entry/flag/log_emote // log emotes
/// log attack messages
/datum/config_entry/flag/log_victim
config_entry_value = TRUE
/datum/config_entry/flag/log_adminchat // log admin chat messages
/// log emotes
/datum/config_entry/flag/log_emote
config_entry_value = TRUE
/// log admin chat messages
/datum/config_entry/flag/log_adminchat
protection = CONFIG_ENTRY_LOCKED
/datum/config_entry/flag/log_shuttle // log shuttle related actions, ie shuttle computers, shuttle manipulator, emergency console
/// log shuttle related actions, ie shuttle computers, shuttle manipulator, emergency console
/datum/config_entry/flag/log_shuttle
config_entry_value = TRUE
/datum/config_entry/flag/log_pda // log pda messages
/// log pda messages
/datum/config_entry/flag/log_pda
config_entry_value = TRUE
/datum/config_entry/flag/log_telecomms // log telecomms messages
/// log telecomms messages
/datum/config_entry/flag/log_telecomms
config_entry_value = TRUE
/datum/config_entry/flag/log_twitter // log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
/// log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
/datum/config_entry/flag/log_twitter
config_entry_value = TRUE
/datum/config_entry/flag/log_world_topic // log all world.Topic() calls
/// log all world.Topic() calls
/datum/config_entry/flag/log_world_topic
config_entry_value = TRUE
/datum/config_entry/flag/log_manifest // log crew manifest to seperate file
/// log crew manifest to seperate file
/datum/config_entry/flag/log_manifest
config_entry_value = TRUE
/datum/config_entry/flag/log_job_debug // log roundstart divide occupations debug information to a file
/// log roundstart divide occupations debug information to a file
/datum/config_entry/flag/log_job_debug
config_entry_value = TRUE
/// log photos taken by players with a camera
/datum/config_entry/flag/log_pictures
/// This is... shitcode, literally same as above, if one of them is inactive, won't log at all, PLEASE FUCKING REMOVE THIS.
/datum/config_entry/flag/picture_logging_camera
/// forces log_href for tgui
/datum/config_entry/flag/emergency_tgui_logging
config_entry_value = FALSE
/datum/config_entry/number/error_cooldown // The "cooldown" time for each occurrence of a unique error
/// The "cooldown" time for each occurrence of a unique error
/datum/config_entry/number/error_cooldown
config_entry_value = 600
min_val = 0
/datum/config_entry/number/error_limit // How many occurrences before the next will silence them
/// How many occurrences before the next will silence them
/datum/config_entry/number/error_limit
config_entry_value = 50
/datum/config_entry/number/error_silence_time // How long a unique error will be silenced for
/// How long a unique error will be silenced for
/datum/config_entry/number/error_silence_time
config_entry_value = 6000
/datum/config_entry/number/error_msg_delay // How long to wait between messaging admins about occurrences of a unique error
/// How long to wait between messaging admins about occurrences of a unique error
/datum/config_entry/number/error_msg_delay
config_entry_value = 50
+9 -6
View File
@@ -396,12 +396,15 @@ SUBSYSTEM_DEF(air)
*/
/datum/controller/subsystem/air/proc/run_delay_heuristics()
if(!equalize_enabled)
cost_equalize = 0
if(should_do_equalization)
eq_cooldown--
if(eq_cooldown <= 0)
equalize_enabled = TRUE
if(should_do_equalization)
if(!equalize_enabled)
cost_equalize = 0
if(should_do_equalization)
eq_cooldown--
if(eq_cooldown <= 0)
equalize_enabled = TRUE
else
equalize_enabled = FALSE
var/total_thread_time = cost_turfs + cost_equalize + cost_groups + cost_post_process
if(total_thread_time)
var/wait_ms = wait * 100
+17 -5
View File
@@ -32,6 +32,8 @@ SUBSYSTEM_DEF(vote)
var/list/stored_modetier_results = list() // The aggregated tier list of the modes available in secret.
var/transfer_votes_done = 0
/datum/controller/subsystem/vote/fire() //called by master_controller
if(mode)
if(end_time < world.time)
@@ -248,8 +250,18 @@ SUBSYSTEM_DEF(vote)
if(vote_system == SCORE_VOTING)
calculate_scores(vote_title_text)
if(vote_system == HIGHEST_MEDIAN_VOTING)
calculate_highest_median(vote_title_text) // nothing uses this at the moment
var/list/winners = vote_system == INSTANT_RUNOFF_VOTING ? get_runoff_results() : get_result()
calculate_highest_median(vote_title_text)
var/list/winners = list()
if(mode == "transfer")
var/amount_required = 3 + transfer_votes_done
transfer_votes_done += 1
text += "\nExtending requires at least [amount_required] votes to win."
if(choices[VOTE_CONTINUE] < amount_required || choices[VOTE_TRANSFER] >= choices[VOTE_CONTINUE])
winners = list(VOTE_TRANSFER)
else
winners = list(VOTE_CONTINUE)
else
winners = vote_system == INSTANT_RUNOFF_VOTING ? get_runoff_results() : get_result()
var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic"
if(winners.len > 0)
if(was_roundtype_vote)
@@ -305,7 +317,7 @@ SUBSYSTEM_DEF(vote)
if(vote_system == SCHULZE_VOTING)
admintext += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!"
else if(vote_system == HIGHEST_MEDIAN_VOTING)
admintext += "\nIt should be noted that this is not a raw tally of votes but the number of runoffs done by majority judgement!"
admintext += "\nIt should be noted that this is not a raw tally of votes but rather the median score plus a tiebreaker!"
for(var/i=1,i<=choices.len,i++)
var/votes = choices[choices[i]]
admintext += "\n<b>[choices[i]]:</b> [votes]"
@@ -339,7 +351,7 @@ SUBSYSTEM_DEF(vote)
if(SSmapping.changemap(config.maplist[.]))
to_chat(world, "<span class='boldannounce'>The map vote has chosen [VM.map_name] for next round!</span>")
if("transfer") // austation begin -- Crew autotransfer vote
if(. == "Initiate Crew Transfer")
if(. == VOTE_TRANSFER)
SSshuttle.autoEnd()
var/obj/machinery/computer/communications/C = locate() in GLOB.machines
if(C)
@@ -446,7 +458,7 @@ SUBSYSTEM_DEF(vote)
continue
choices |= M
if("transfer") // austation begin -- Crew autotranfer vote
choices.Add("Initiate Crew Transfer","Continue Playing") // austation end
choices.Add(VOTE_TRANSFER,VOTE_CONTINUE) // austation end
if("roundtype") //CIT CHANGE - adds the roundstart secret/extended vote
choices.Add("dynamic", "extended")
if("custom")
+6 -2
View File
@@ -578,8 +578,12 @@
/datum/status_effect/regenerative_core/on_apply()
. = ..()
ADD_TRAIT(owner, TRAIT_IGNOREDAMAGESLOWDOWN, "regenerative_core")
if(HAS_TRAIT(owner, TRAIT_ROBOTIC_ORGANISM)) //Robots can heal from cores, but only get 1/5th of the healing. They can use this to get past the damage threshhold however, and then regularely heal from there.
var/turf/T = get_turf(owner)
if(T && is_mining_level(T.z))
if(HAS_TRAIT(owner, TRAIT_ROBOTIC_ORGANISM)) //Robots can heal from cores, though they ""only"" heal 20 brute + burn damage each instead of 25
heal_amount *= 0.8
else
duration = 10 SECONDS
heal_amount *= 0.2
owner.adjustBruteLoss(-heal_amount, only_organic = FALSE)
if(!AmBloodsucker(owner)) //use your coffin you lazy bastard
+5 -1
View File
@@ -1005,11 +1005,15 @@
/datum/status_effect/trance/proc/hypnotize(datum/source, list/hearing_args)
if(!owner.can_hear())
return
if(hearing_args[HEARING_SPEAKER] == owner)
var/mob/hearing_speaker = hearing_args[HEARING_SPEAKER]
if(hearing_speaker == owner)
return
var/mob/living/carbon/C = owner
var/hypnomsg = uncostumize_say(hearing_args[HEARING_RAW_MESSAGE], hearing_args[HEARING_MESSAGE_MODE])
C.cure_trauma_type(/datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY) //clear previous hypnosis
// The brain trauma itself does its own set of logging, but this is the only place the source of the hypnosis phrase can be found.
hearing_speaker.log_message("has hypnotised [key_name(C)] with the phrase '[hypnomsg]'", LOG_ATTACK)
C.log_message("has been hypnotised by the phrase '[hypnomsg]' spoken by [key_name(hearing_speaker)]", LOG_VICTIM, log_globally = FALSE)
addtimer(CALLBACK(C, /mob/living/carbon.proc/gain_trauma, /datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY, hypnomsg), 10)
addtimer(CALLBACK(C, /mob/living.proc/Stun, 60, TRUE, TRUE), 15) //Take some time to think about it
qdel(src)
+1 -1
View File
@@ -1243,7 +1243,7 @@
if(user != target)
var/reverse_message = "has been [what_done] by [ssource][postfix]"
target.log_message(reverse_message, LOG_ATTACK, color="orange", log_globally=FALSE)
target.log_message(reverse_message, LOG_VICTIM, color="orange", log_globally=FALSE)
/**
* log_wound() is for when someone is *attacked* and suffers a wound. Note that this only captures wounds from damage, so smites/forced wounds aren't logged, as well as demotions like cuts scabbing over
+1 -1
View File
@@ -423,7 +423,7 @@
if((!req_defib && grab_ghost) || (req_defib && defib.grab_ghost))
H.notify_ghost_cloning("Your heart is being defibrillated!")
H.grab_ghost() // Shove them back in their body.
else if(H.can_defib())
else if(H.can_revive())
H.notify_ghost_cloning("Your heart is being defibrillated. Re-enter your corpse if you want to be revived!", source = src)
do_help(H, user)
@@ -189,5 +189,7 @@
return FALSE
brainwash(C, objective)
message_admins("[ADMIN_LOOKUPFLW(user)] brainwashed [key_name_admin(C)] with objective '[objective]'.")
user.log_message("has brainwashed [key_name(C)] with the objective '[objective]' using \the [src]", LOG_ATTACK)
C.log_message("has been brainwashed with the objective '[objective]' by [key_name(user)] using \the [src]", LOG_VICTIM, log_globally = FALSE)
log_game("[key_name(user)] brainwashed [key_name(C)] with objective '[objective]'.")
return TRUE
+1
View File
@@ -115,6 +115,7 @@ GLOBAL_LIST(topic_status_cache)
GLOB.world_virus_log = "[GLOB.log_directory]/virus.log"
GLOB.world_asset_log = "[GLOB.log_directory]/asset.log"
GLOB.world_attack_log = "[GLOB.log_directory]/attack.log"
GLOB.world_victim_log = "[GLOB.log_directory]/victim.log"
GLOB.world_pda_log = "[GLOB.log_directory]/pda.log"
GLOB.world_telecomms_log = "[GLOB.log_directory]/telecomms.log"
GLOB.world_manifest_log = "[GLOB.log_directory]/manifest.log"
@@ -73,7 +73,7 @@
brainwash(C, objectives)
var/obj_list = english_list(objectives)
message_admins("[key_name_admin(admin)] has brainwashed [key_name_admin(C)] with the following objectives: [obj_list].")
C.log_message("has been force-brainwashed with the objective '[obj_list]' by admin [key_name(admin)]", LOG_ATTACK, log_globally = FALSE)
C.log_message("has been force-brainwashed with the objective '[obj_list]' by admin [key_name(admin)]", LOG_VICTIM)
log_admin("[key_name(admin)] has brainwashed [key_name(C)] with the following objectives: [obj_list].")
/datum/objective/brainwashing
+4 -4
View File
@@ -845,16 +845,16 @@
update_inv_handcuffed()
update_hud_handcuffed()
/mob/living/carbon/proc/can_defib()
/mob/living/carbon/proc/can_revive(ignore_timelimit = FALSE, maximum_brute_dam = MAX_REVIVE_BRUTE_DAMAGE, maximum_fire_dam = MAX_REVIVE_FIRE_DAMAGE, ignore_heart = FALSE)
var/tlimit = DEFIB_TIME_LIMIT * 10
var/obj/item/organ/heart = getorgan(/obj/item/organ/heart)
if(suiciding || hellbound || HAS_TRAIT(src, TRAIT_HUSK) || AmBloodsucker(src))
return
if((world.time - timeofdeath) > tlimit)
if(!ignore_timelimit && (world.time - timeofdeath) > tlimit)
return
if((getBruteLoss() >= MAX_REVIVE_BRUTE_DAMAGE) || (getFireLoss() >= MAX_REVIVE_FIRE_DAMAGE))
if((getBruteLoss() >= maximum_brute_dam) || (getFireLoss() >= maximum_fire_dam))
return
if(!heart || (heart.organ_flags & ORGAN_FAILING))
if(!ignore_heart && (!heart || (heart.organ_flags & ORGAN_FAILING)))
return
var/obj/item/organ/brain/BR = getorgan(/obj/item/organ/brain)
if(QDELETED(BR) || BR.brain_death || (BR.organ_flags & ORGAN_FAILING) || suiciding)
@@ -79,7 +79,6 @@
if(id_card?.registered_account)
if((ACCESS_HEADS in id_card.access) || (ACCESS_QM in id_card.access))
requestonly = FALSE
buyer = SSeconomy.get_dep_account(id_card.registered_account.account_job.paycheck_department)
can_approve_requests = TRUE
else
requestonly = TRUE
@@ -236,8 +235,7 @@
return
if(!self_paid && ishuman(usr) && !account)
var/obj/item/card/id/id_card = card_slot?.GetID()
account = SSeconomy.get_dep_account(id_card?.registered_account?.account_job.paycheck_department)
account = SSeconomy.get_dep_account(ACCOUNT_CAR)
var/turf/T = get_turf(src)
var/datum/supply_order/SO = new(pack, name, rank, ckey, reason, account)
@@ -263,9 +261,7 @@
var/id = text2num(params["id"])
for(var/datum/supply_order/SO in SSshuttle.requestlist)
if(SO.id == id)
var/obj/item/card/id/id_card = card_slot?.GetID()
if(id_card && id_card?.registered_account)
SO.paying_account = SSeconomy.get_dep_account(id_card?.registered_account?.account_job.paycheck_department)
SO.paying_account = SSeconomy.get_dep_account(ACCOUNT_CAR)
SSshuttle.requestlist -= SO
SSshuttle.shoppinglist += SO
. = TRUE
@@ -469,15 +469,20 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
//((((some value between 0.5 and 1 * temp - ((273.15 + 40) * some values between 1 and 10)) * some number between 0.25 and knock your socks off / 150) * 0.25
//Heat and mols account for each other, a lot of hot mols are more damaging then a few
//Mols start to have a positive effect on damage after 350
var/spaced = 0
for(var/turf/open/space/_space_turf in range(2,src))
spaced++
damage = max(damage + (max(clamp(removed.total_moles() / 200, 0.5, 1) * removed.return_temperature() - ((T0C + HEAT_PENALTY_THRESHOLD)*dynamic_heat_resistance), 0) * mole_heat_penalty / 150 ) * DAMAGE_INCREASE_MULTIPLIER, 0)
//Power only starts affecting damage when it is above 5000
damage = max(damage + (max(power - POWER_PENALTY_THRESHOLD, 0)/500) * DAMAGE_INCREASE_MULTIPLIER, 0)
//Molar count only starts affecting damage when it is above 1800
damage = max(damage + (max(combined_gas - MOLE_PENALTY_THRESHOLD, 0)/80) * DAMAGE_INCREASE_MULTIPLIER, 0)
damage = max(damage + spaced * 0.1 * DAMAGE_INCREASE_MULTIPLIER, 0)
//There might be a way to integrate healing and hurting via heat
//healing damage
if(combined_gas < MOLE_PENALTY_THRESHOLD)
if(combined_gas < MOLE_PENALTY_THRESHOLD && !spaced)
//Only has a net positive effect when the temp is below 313.15, heals up to 2 damage. Psycologists increase this temp min by up to 45
damage = max(damage + (min(removed.return_temperature() - (T0C + HEAT_PENALTY_THRESHOLD), 0) / 150), 0)
+10 -2
View File
@@ -234,6 +234,7 @@
var/transfer_amount = T.volume * part
if(preserve_data)
trans_data = copy_data(T)
post_copy_data(T)
transferred += "[T] - [transfer_amount]"
R.add_reagent(T.type, transfer_amount * multiplier, trans_data, chem_temp, T.purity, pH, no_react = TRUE, ignore_pH = TRUE) //we only handle reaction after every reagent has been transfered.
@@ -274,7 +275,8 @@
var/datum/reagent/T = reagent
var/copy_amount = T.volume * part
if(preserve_data)
trans_data = T.data
trans_data = copy_data(T)
post_copy_data(T)
R.add_reagent(T.type, copy_amount * multiplier, trans_data)
src.update_total()
@@ -301,7 +303,8 @@
var/datum/reagent/current_reagent = CR
if(current_reagent.type == reagent)
if(preserve_data)
trans_data = current_reagent.data
trans_data = copy_data(current_reagent)
post_copy_data(current_reagent)
R.add_reagent(current_reagent.type, amount, trans_data, chem_temp, current_reagent.purity, pH, no_react = TRUE)
remove_reagent(current_reagent.type, amount, 1)
if(log && amount > 0)
@@ -1152,6 +1155,11 @@
return trans_data
///
// Should be ran after using copy_data. Calls the reagent's post_copy_data, which usually does nothing.
/datum/reagents/proc/post_copy_data(datum/reagent/current_reagent)
return current_reagent.post_copy_data()
/datum/reagents/proc/get_reagent(type)
var/list/cached_reagents = reagent_list
. = locate(type) in cached_reagents
@@ -199,6 +199,10 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
M.reagents.add_reagent(impure_chem, impureVol, FALSE, other_purity = 1-cached_purity)
log_reagent("MOB ADD: on_merge() (mixed purity): merged [volume - impureVol] of [type] and [volume] of [impure_chem]")
//Ran by a reagent holder on a specific reagent after copying its data.
/datum/reagent/proc/post_copy_data()
return
/datum/reagent/proc/on_update(atom/A)
return
@@ -997,11 +997,11 @@
if(M.stat == DEAD)
if(M.suiciding || M.hellbound) //they are never coming back
M.visible_message("<span class='warning'>[M]'s body does not react...</span>")
return
return ..()
if(M.getBruteLoss() >= 100 || M.getFireLoss() >= 100 || HAS_TRAIT(M, TRAIT_HUSK)) //body is too damaged to be revived
M.visible_message("<span class='warning'>[M]'s body convulses a bit, and then falls still once more.</span>")
M.do_jitter_animation(10)
return
return ..()
else
M.visible_message("<span class='warning'>[M]'s body starts convulsing!</span>")
M.notify_ghost_cloning(source = M)
@@ -1013,27 +1013,31 @@
if(iscarbon(M))
var/mob/living/carbon/C = M
if(!(C.dna && C.dna.species && (NOBLOOD in C.dna.species.species_traits)))
C.blood_volume = max(C.blood_volume, BLOOD_VOLUME_NORMAL*C.blood_ratio) //so you don't instantly re-die from a lack of blood
for(var/organ in C.internal_organs)
var/obj/item/organ/O = organ
if(O.damage > O.maxHealth/2)
O.setOrganDamage(O.maxHealth/2) //so you don't instantly die from organ damage when being revived
C.blood_volume = max(C.blood_volume, BLOOD_VOLUME_BAD*C.blood_ratio) //so you don't instantly re-die from a lack of blood. You'll still need help if you had none though.
var/obj/item/organ/heart/H = C.getorganslot(ORGAN_SLOT_HEART)
if(H && H.organ_flags & ORGAN_FAILING)
H.applyOrganDamage(-15)
for(var/obj/item/organ/O as anything in C.internal_organs)
if(O.organ_flags & ORGAN_FAILING)
O.applyOrganDamage(-5)
M.adjustOxyLoss(-20, 0)
M.adjustToxLoss(-20, 0)
M.updatehealth()
if(iscarbon(M))
var/mob/living/carbon/C = M
if(!C.can_revive(ignore_timelimit = TRUE, maximum_brute_dam = 100, maximum_fire_dam = 100, ignore_heart = TRUE))
return
var/tplus = world.time - M.timeofdeath
if(M.revive())
M.grab_ghost()
M.emote("gasp")
log_combat(M, M, "revived", src)
var/list/policies = CONFIG_GET(keyed_list/policy)
var/timelimit = CONFIG_GET(number/defib_cmd_time_limit) * 10 //the config is in seconds, not deciseconds
var/late = timelimit && (tplus > timelimit)
var/policy = late? policies[POLICYCONFIG_ON_DEFIB_LATE] : policies[POLICYCONFIG_ON_DEFIB_INTACT]
var/policy = policies[POLICYCONFIG_ON_DEFIB_LATE] //Always causes memory loss due to the nature of strange reagent.
if(policy)
to_chat(M, policy)
M.log_message("revived using strange reagent, [tplus] deciseconds from time of death, considered [late? "late" : "memory-intact"] revival under configured policy limits.", LOG_GAME)
M.log_message("revived using strange reagent, [tplus] deciseconds from time of death, considered late revival due to usage of strange reagent.", LOG_GAME)
..()
@@ -491,7 +491,7 @@
return
var/fp_verb = mode == HYPO_SPRAY ? "spray" : "inject"
var/method = mode == HYPO_SPRAY ? TOUCH : INJECT
var/method = mode == HYPO_SPRAY ? PATCH : INJECT //Medsprays use patch when spraying, feels like an inconsistancy here.
if(L != user)
L.visible_message("<span class='danger'>[user] is trying to [fp_verb] [L] with [src]!</span>", \
@@ -1,4 +1,4 @@
#define MAX_RADIUS_REQUIRED 8000 //tritbomb
#define MAX_RADIUS_REQUIRED 175 //tritbomb
#define MIN_RADIUS_REQUIRED 20 //maxcap
/**
* # Explosive compressor machines
@@ -234,7 +234,7 @@
var/mob/living/carbon/C = host_mob
if(C.get_ghost())
return FALSE
return C.can_defib()
return C.can_revive()
/datum/nanite_program/defib/proc/zap()
var/mob/living/carbon/C = host_mob
@@ -49,6 +49,8 @@
to_chat(target, "<span class='userdanger'>A new compulsion fills your mind... you feel forced to obey it!</span>")
brainwash(target, objective)
message_admins("[ADMIN_LOOKUPFLW(user)] surgically brainwashed [ADMIN_LOOKUPFLW(target)] with the objective '[objective]'.")
user.log_message("has brainwashed [key_name(target)] with the objective '[objective]' using brainwashing surgery.", LOG_ATTACK)
target.log_message("has been brainwashed with the objective '[objective]' by [key_name(user)] using brainwashing surgery.", LOG_VICTIM, log_globally=FALSE)
log_game("[key_name(user)] surgically brainwashed [key_name(target)] with the objective '[objective]'.")
return TRUE
@@ -156,12 +156,14 @@
return FALSE
if(organ_flags & ORGAN_SYNTHETIC_EMP) //Synthetic organ has been emped, is now failing.
applyOrganDamage(maxHealth * decay_factor)
return
return FALSE
if(organ_flags & ORGAN_SYNTHETIC)
return TRUE
if(!is_cold() && damage)
///Damage decrements by a percent of its maxhealth
var/healing_amount = -(maxHealth * healing_factor)
///Damage decrements again by a percent of its maxhealth, up to a total of 4 extra times depending on the owner's satiety
healing_amount -= owner.satiety > 0 ? 4 * healing_factor * owner.satiety / MAX_SATIETY : 0
healing_amount -= owner.satiety > 0 ? 4 * (maxHealth * healing_factor) * (owner.satiety / MAX_SATIETY) : 0
if(healing_amount)
applyOrganDamage(healing_amount) //to FERMI_TWEAK
return TRUE
+7
View File
@@ -131,6 +131,13 @@
name = "ipc cell"
icon_state = "stomach-ipc"
/obj/item/organ/stomach/ipc/on_life()
. = ..()
if(!.)
return
if(HAS_TRAIT(owner, TRAIT_ROBOTIC_ORGANISM) && owner.nutrition >= NUTRITION_LEVEL_FED)
owner.satiety += 5 //We don't need to cap the value as it's already automatically capped during nutrition level handling. Also effectively only +4 as you lose 1 per life tick. 300 seconds of sufficient charge to reach full satiety.
/obj/item/organ/stomach/ipc/emp_act(severity)
. = ..()
if(!owner || . & EMP_PROTECT_SELF)