Merge remote-tracking branch 'citadel/master' into eldritch_affairs

This commit is contained in:
kevinz000
2020-03-27 21:32:40 -07:00
917 changed files with 182662 additions and 22716 deletions
+11 -1
View File
@@ -63,6 +63,9 @@
var/xenobiology_compatible = FALSE //Can the Xenobio management console transverse this area by default?
var/list/canSmoothWithAreas //typecache to limit the areas that atoms in this area can smooth with
/// Color on minimaps, if it's null (which is default) it makes one at random.
var/minimap_color
/**
* These two vars allow for multiple unique areas to be linked to a master area
* and share some functionalities such as APC powernet nodes, fire alarms etc, without sacrificing
@@ -96,7 +99,14 @@ GLOBAL_LIST_EMPTY(teleportlocs)
// ===
/area/New()
// This interacts with the map loader, so it needs to be set immediately
if(!minimap_color) // goes in New() because otherwise it doesn't fucking work
// generate one using the icon_state
if(icon_state && icon_state != "unknown")
var/icon/I = new(icon, icon_state, dir)
I.Scale(1,1)
minimap_color = I.GetPixel(1,1)
else // no icon state? use random.
minimap_color = rgb(rand(50,70),rand(50,70),rand(50,70)) // This interacts with the map loader, so it needs to be set immediately
// rather than waiting for atoms to initialize.
if (unique)
GLOB.areas_by_type[type] = src
@@ -19,7 +19,7 @@
antag_flag = ROLE_BLOODSUCKER
false_report_weight = 1
restricted_jobs = list("AI","Cyborg")
protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
protected_jobs = list("Chaplain", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
required_players = 20
required_enemies = 2
recommended_enemies = 4
+2 -2
View File
@@ -88,13 +88,13 @@ GLOBAL_VAR(changeling_team_objective_type) //If this is not null, we hand our th
user.underwear = chosen_prof.underwear
user.undie_color = chosen_prof.undie_color
user.undershirt = chosen_prof.undershirt
user.shirt_color =chosen_prof.shirt_color
user.shirt_color = chosen_prof.shirt_color
user.socks = chosen_prof.socks
user.socks_color =chosen_prof.socks_color
chosen_dna.transfer_identity(user, 1)
user.updateappearance(mutcolor_update=1)
user.update_body()
user.update_body(TRUE)
user.domutcheck()
//vars hackery. not pretty, but better than the alternative.
+1 -1
View File
@@ -271,7 +271,7 @@ Credit where due:
//Servant of Ratvar outfit
/datum/outfit/servant_of_ratvar
name = "Servant of Ratvar"
uniform = /obj/item/clothing/under/rank/engineer //no more chameleon suit for them, as requested
uniform = /obj/item/clothing/under/rank/engineering/engineer //no more chameleon suit for them, as requested
shoes = /obj/item/clothing/shoes/sneakers/black
back = /obj/item/storage/backpack
ears = /obj/item/radio/headset
@@ -35,7 +35,7 @@
H.Stun(10)
var/obj/item/clothing/C
if(!H.w_uniform || H.dropItemToGround(H.w_uniform))
C = new /obj/item/clothing/under/rank/clown(H)
C = new /obj/item/clothing/under/rank/civilian/clown(H)
ADD_TRAIT(C, TRAIT_NODROP, CLOWN_NUKE_TRAIT)
H.equip_to_slot_or_del(C, SLOT_W_UNIFORM)
+23 -30
View File
@@ -54,9 +54,9 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
// Current storyteller
var/datum/dynamic_storyteller/storyteller = null
// Threat logging vars
/// The "threat cap", threat shouldn't normally go above this and is used in ruleset calculations
/// Target threat level right now. Events and antags will try to keep the round at this level.
var/threat_level = 0
/// Set at the beginning of the round. Spent by the mode to "purchase" rules.
/// The current antag threat. Recalculated every time a ruletype starts or ends.
var/threat = 0
/// Starting threat level, for things that increase it but can bring it back down.
var/initial_threat_level = 0
@@ -261,11 +261,11 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
. += "<b>Uncharted Space</b></center><BR>"
. += "Congratulations and thank you for participating in the NT 'Frontier' space program! Your station is actively orbiting a high value system far from the nearest support stations. Little is known about your region of space, and the opportunity to encounter the unknown invites greater glory. You are encouraged to elevate security as necessary to protect Nanotrasen assets."
set_security_level(SEC_LEVEL_BLUE)
if(80 to 99)
if(80 to 95)
. += "<b>Black Orbit</b></center><BR>"
. += "As part of a mandatory security protocol, we are required to inform you that as a result of your orbital pattern directly behind an astrological body (oriented from our nearest observatory), your station will be under decreased monitoring and support. It is anticipated that your extreme location and decreased surveillance could pose security risks. Avoid unnecessary risks and attempt to keep your station in one piece."
set_security_level(SEC_LEVEL_AMBER)
if(100)
if(96 to 100)
. += "<b>Impending Doom</b></center><BR>"
. += "Your station is somehow in the middle of hostile territory, in clear view of any enemy of the corporation. Your likelihood to survive is low, and station destruction is expected and almost inevitable. Secure any sensitive material and neutralize any enemy you will come across. It is important that you at least try to maintain the station.<BR>"
. += "Good luck."
@@ -330,7 +330,6 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
peaceful_percentage = round(LORENTZ_CUMULATIVE_DISTRIBUTION(relative_threat, GLOB.dynamic_curve_centre, GLOB.dynamic_curve_width), 0.01)*100
threat = threat_level
SSblackbox.record_feedback("tally","dynamic_threat",threat_level,"Initial threat level")
SSblackbox.record_feedback("tally","dynamic_threat",GLOB.dynamic_curve_centre,"Curve centre")
SSblackbox.record_feedback("tally","dynamic_threat",GLOB.dynamic_curve_width,"Curve width")
@@ -463,7 +462,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
log_game("DYNAMIC: Additional ruleset picked successfully, now [executed_rules.len] picked. [extra_rulesets_amount] remaining.")
else
if(threat >= 50)
if(threat_level >= 50)
message_admins("DYNAMIC: Picking first roundstart ruleset failed. You should report this.")
log_game("DYNAMIC: Picking first roundstart ruleset failed. drafted_rules.len = [drafted_rules.len] and threat = [threat]/[threat_level]")
return FALSE
@@ -509,9 +508,8 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
drafted_rules -= starting_rule
starting_rule.trim_candidates()
var/added_threat = starting_rule.scale_up(extra_rulesets_amount, threat)
starting_rule.scale_up(extra_rulesets_amount, threat)
if (starting_rule.pre_execute())
spend_threat(starting_rule.cost + added_threat)
log_threat("[starting_rule.ruletype] - <b>[starting_rule.name]</b> -[starting_rule.cost + starting_rule.scaled_times * starting_rule.scaling_cost] threat", verbose = TRUE)
if(starting_rule.flags & HIGHLANDER_RULESET)
highlander_executed = TRUE
@@ -534,8 +532,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
/datum/game_mode/dynamic/proc/execute_roundstart_rule(sent_rule)
var/datum/dynamic_ruleset/rule = sent_rule
if(rule.execute())
if(rule.persistent)
current_rules += rule
current_rules += rule
SSblackbox.record_feedback("associative","dynamic_rulesets",1,rule.get_blackbox_info())
return TRUE
rule.clean_up() // Refund threat, delete teams and so on.
@@ -607,7 +604,6 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
if ((forced || (new_rule.acceptable(current_players[CURRENT_LIVING_PLAYERS].len, threat_level) && new_rule.cost <= threat)))
new_rule.trim_candidates()
if (new_rule.ready(forced))
spend_threat(new_rule.cost)
log_threat("[new_rule.ruletype] - <b>[new_rule.name]</b> -[new_rule.cost] threat", verbose = TRUE)
if (new_rule.execute()) // This should never fail since ready() returned 1
if(new_rule.flags & HIGHLANDER_RULESET)
@@ -617,8 +613,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
log_game("DYNAMIC: Making a call to a specific ruleset...[new_rule.name]!")
SSblackbox.record_feedback("associative","dynamic_rulesets",1,new_rule.get_blackbox_info())
executed_rules += new_rule
if (new_rule.persistent)
current_rules += new_rule
current_rules += new_rule
return TRUE
else if (forced)
log_game("DYNAMIC: The ruleset [new_rule.name] couldn't be executed due to lack of eligible players.")
@@ -629,7 +624,6 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
var/datum/dynamic_ruleset/rule = sent_rule
if (rule.execute())
log_game("DYNAMIC: Injected a [rule.ruletype == "latejoin" ? "latejoin" : "midround"] ruleset [rule.name].")
spend_threat(rule.cost)
log_threat("[rule.ruletype] [rule.name] spent [rule.cost]", verbose = TRUE)
if(rule.flags & HIGHLANDER_RULESET)
highlander_executed = TRUE
@@ -647,9 +641,9 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
return TRUE
stack_trace("The [rule.ruletype] rule \"[rule.name]\" failed to execute.")
return FALSE
/datum/game_mode/dynamic/process()
if (pop_last_updated < world.time - (60 SECONDS))
if (pop_last_updated < world.time - (120 SECONDS))
pop_last_updated = world.time
update_playercounts()
@@ -658,7 +652,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
current_rules -= rule
SSblackbox.record_feedback("tally","dynamic",1,"Rulesets finished")
SSblackbox.record_feedback("associative","dynamic_rulesets_finished",1,rule.get_blackbox_info())
storyteller.do_process()
if (midround_injection_cooldown < world.time)
@@ -717,6 +711,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
current_players[CURRENT_OBSERVERS].Add(M)
continue
current_players[CURRENT_DEAD_PLAYERS].Add(M) // Players who actually died (and admins who ghosted, would be nice to avoid counting them somehow)
threat = storyteller.calculate_threat() + 50 // 50 is the centerpoint, so we want it to be around 50
/// Removes type from the list
/datum/game_mode/dynamic/proc/remove_from_list(list/type_list, type)
@@ -767,23 +762,21 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
SSblackbox.record_feedback("tally","dynamic",1,"Successful latejoin injections")
latejoin_injection_cooldown = storyteller.get_latejoin_cooldown() + world.time
/// Refund threat, but no more than threat_level.
/datum/game_mode/dynamic/proc/refund_threat(regain)
threat = min(threat_level,threat+regain)
SSblackbox.record_feedback("tally","dynamic_threat",regain,"Refunded threat")
log_threat("[regain] refunded. Threat is now [threat].", verbose = TRUE)
/// Generate threat and increase the threat_level if it goes beyond, capped at 100
/// Increase the threat level.
/datum/game_mode/dynamic/proc/create_threat(gain)
threat = min(100, threat+gain)
if(threat > threat_level)
threat_level = threat
threat_level += gain
SSblackbox.record_feedback("tally","dynamic_threat",gain,"Created threat")
log_threat("[gain] created. Threat is now [threat] and threat level is now [threat_level].", verbose = TRUE)
log_threat("[gain] created. Threat level is now [threat_level].", verbose = TRUE)
/// Expend threat, can't fall under 0.
/// Decrease the threat level.
/datum/game_mode/dynamic/proc/remove_threat(loss)
threat_level -= loss
SSblackbox.record_feedback("tally","dynamic_threat",loss,"Removed threat")
log_threat("[loss] removed. Threat level is now [threat_level].", verbose = TRUE)
/// Fill up more of the threat level.
/datum/game_mode/dynamic/proc/spend_threat(cost)
threat = max(threat-cost,0)
threat += cost
SSblackbox.record_feedback("tally","dynamic_threat",cost,"Threat spent")
log_threat("[cost] spent. Threat is now [threat].", verbose = TRUE)
@@ -174,8 +174,8 @@
/// This is called if persistent variable is true everytime SSTicker ticks.
/datum/dynamic_ruleset/proc/rule_process()
return
return TRUE
/// Called on game mode pre_setup for roundstart rulesets.
/// Do everything you need to do before job is assigned here.
/// IMPORTANT: ASSIGN special_role HERE
@@ -201,8 +201,7 @@
/// Runs from gamemode process() if ruleset fails to start, like delayed rulesets not getting valid candidates.
/// This one only handles refunding the threat, override in ruleset to clean up the rest.
/datum/dynamic_ruleset/proc/clean_up()
mode.refund_threat(cost + (scaled_times * scaling_cost))
mode.log_threat("[ruletype] [name] refunded [cost + (scaled_times * scaling_cost)]",verbose=TRUE)
return
/// Gets weight of the ruleset
/// Note that this decreases weight if repeatable is TRUE and repeatable_weight_decrease is higher than 0
@@ -2,6 +2,7 @@
ruletype = "Event"
var/typepath // typepath of the event
var/triggering
var/earliest_start = 20 MINUTES
/datum/dynamic_ruleset/event/get_blackbox_info()
var/list/ruleset_data = list()
@@ -25,8 +26,10 @@
return E
/datum/dynamic_ruleset/event/ready(forced = FALSE) // same as midround cause we're still using enemy system
/datum/dynamic_ruleset/event/ready(forced = FALSE)
if (!forced)
if(earliest_start >= world.time-SSticker.round_start_time)
return FALSE
var/job_check = 0
if (enemy_roles.len > 0)
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
@@ -56,6 +59,7 @@
required_enemies = list(2,2,1,1,0,0,0,0,0,0)
weight = 5
cost = 10
earliest_start = 30 MINUTES
blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear)
requirements = list(70,60,50,50,40,40,40,30,20,15)
property_weights = list("story_potential" = 1, "trust" = 1, "chaos" = 1)
@@ -157,17 +161,18 @@
required_enemies = list(3,3,3,3,3,3,3,3,3,3)
cost = 15
weight = 3
earliest_start = 25 MINUTES
repeatable_weight_decrease = 2
requirements = list(60,50,40,30,30,30,30,30,30,30)
high_population_requirement = 30
property_weights = list("extended" = -2)
/datum/dynamic_ruleset/event/meteor_wave/ready()
if(mode.threat_level > 40 && mode.threat >= 25 && prob(20))
if(world.time-SSticker.round_start_time > 35 MINUTES && mode.threat_level > 40 && mode.threat >= 25 && prob(30))
name = "Meteor Wave: Threatening"
cost = 25
typepath = /datum/round_event/meteor_wave/threatening
else if(mode.threat_level > 50 && mode.threat >= 40 && prob(30))
else if(world.time-SSticker.round_start_time > 45 MINUTES && mode.threat_level > 50 && mode.threat >= 40 && prob(30))
name = "Meteor Wave: Catastrophic"
cost = 40
typepath = /datum/round_event/meteor_wave/catastrophic
@@ -280,6 +285,7 @@
cost = 4
requirements = list(10,10,10,10,10,10,10,10,10,10)
high_population_requirement = 10
earliest_start = 10 MINUTES
repeatable = TRUE
property_weights = list("extended" = 1)
@@ -324,6 +330,7 @@
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
repeatable = TRUE
earliest_start = 0 MINUTES
property_weights = list("extended" = 1)
always_max_weight = TRUE
@@ -381,3 +388,67 @@
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
property_weights = list("extended" = 1,"chaos" = 1)
/datum/dynamic_ruleset/event/portal_storm_syndicate
name = "Portal Storm"
config_tag = "portal_storm"
typepath = /datum/round_event/portal_storm/syndicate_shocktroop
cost = 10
weight = 1
enemy_roles = list("Head of Security","Security Officer","AI","Captain","Shaft Miner")
required_enemies = list(2,2,2,2,2,2,2,2,2,2)
requirements = list(101,101,101,30,30,30,30,30,30,30)
high_population_requirement = 30
earliest_start = 30 MINUTES
property_weights = list("teamwork" = 1,"chaos" = 1, "extended" = -1)
/datum/dynamic_ruleset/event/wormholes
name = "Wormholes"
config_tag = "wormhole"
typepath = /datum/round_event/wormholes
cost = 3
weight = 4
enemy_roles = list("AI","Medical Doctor","Station Engineer","Head of Personnel","Captain")
required_enemies = list(2,2,2,2,2,2,2,2,2,2)
requirements = list(5,5,5,5,5,5,5,5,5,5)
high_population_requirement = 5
property_weights = list("extended" = 1)
/datum/dynamic_ruleset/event/swarmers
name = "Swarmers"
config_tag = "swarmer"
typepath = /datum/round_event/spawn_swarmer
cost = 10
weight = 1
earliest_start = 30 MINUTES
enemy_roles = list("AI","Security Officer","Head of Security","Captain","Station Engineer","Atmos Technician","Chief Engineer")
required_enemies = list(4,4,4,4,3,3,2,2,1,1)
requirements = list(101,101,101,101,101,101,101,101,101,101)
high_population_requirement = 5
property_weights = list("extended" = -2)
/datum/dynamic_ruleset/event/sentient_disease
name = "Sentient Disease"
config_tag = "sentient_disease"
typepath = /datum/round_event/ghost_role/sentient_disease
enemy_roles = list("Virologist","Chief Medical Officer","Captain","Chemist")
required_enemies = list(2,1,1,1,0,0,0,0,0,0)
required_candidates = 1
weight = 4
cost = 5
requirements = list(30,30,20,20,15,10,10,10,10,5) // yes, it can even happen in "extended"!
property_weights = list("story_potential" = 1, "extended" = 1, "valid" = -2)
high_population_requirement = 5
/datum/dynamic_ruleset/event/revenant
name = "Revenant"
config_tag = "revenant"
typepath = /datum/round_event/ghost_role/revenant
enemy_roles = list("Chief Engineer","Station Engineer","Captain","Chaplain","AI")
required_enemies = list(2,1,1,1,0,0,0,0,0,0)
required_candidates = 1
weight = 4
cost = 5
requirements = list(30,30,30,30,20,15,15,15,15,15)
high_population_requirement = 15
property_weights = list("story_potential" = -2, "extended" = -1)
@@ -34,7 +34,7 @@
living_players = trim_list(mode.current_players[CURRENT_LIVING_PLAYERS])
living_antags = trim_list(mode.current_players[CURRENT_LIVING_ANTAGS])
list_observers = trim_list(mode.current_players[CURRENT_OBSERVERS])
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(/datum/element/ghost_role_eligibility)
var/datum/element/ghost_role_eligibility/eligibility = SSdcs.GetElement(list(/datum/element/ghost_role_eligibility))
ghost_eligible = trim_list(eligibility.get_all_ghost_role_eligible())
/datum/dynamic_ruleset/midround/proc/trim_list(list/L = list())
@@ -43,7 +43,7 @@
if (!istype(M, required_type))
trimmed_list.Remove(M)
continue
if (M.GetComponent(/datum/component/virtual_reality))
if (HAS_TRAIT(M, TRAIT_NO_MIDROUND_ANTAG))
trimmed_list.Remove(M)
continue
if (!M.client) // Are they connected?
@@ -273,10 +273,14 @@
var/ion_announce = 33
var/removeDontImproveChance = 10
/datum/dynamic_ruleset/midround/malf/ready()
if(!candidates || !candidates.len)
return FALSE
return ..()
/datum/dynamic_ruleset/midround/malf/trim_candidates()
..()
living_players = candidates[CURRENT_LIVING_PLAYERS]
for(var/mob/living/player in candidates)
for(var/mob/living/player in living_players)
if(!isAI(player))
candidates -= player
continue
@@ -287,8 +291,6 @@
candidates -= player
/datum/dynamic_ruleset/midround/malf/execute()
if(!candidates || !candidates.len)
return FALSE
var/mob/living/silicon/ai/M = pick_n_take(candidates)
assigned += M.mind
var/datum/antagonist/traitor/AI = new
@@ -313,7 +315,6 @@
/datum/dynamic_ruleset/midround/from_ghosts/wizard
name = "Wizard"
config_tag = "midround_wizard"
persistent = TRUE
antag_datum = /datum/antagonist/wizard
antag_flag = ROLE_WIZARD
enemy_roles = list("Security Officer","Detective","Head of Security", "Captain")
@@ -337,11 +338,11 @@
/datum/dynamic_ruleset/midround/from_ghosts/wizard/finish_setup(mob/new_character, index)
..()
new_character.forceMove(pick(GLOB.wizardstart))
wizard = new_character.mind
/datum/dynamic_ruleset/midround/from_ghosts/wizard/rule_process() // i can literally copy this from are_special_antags_dead it's great
if(isliving(wizard.current) && wizard.current.stat!=DEAD)
return FALSE
for(var/obj/item/phylactery/P in GLOB.poi_list) //TODO : IsProperlyDead()
if(P.mind && P.mind.has_antag_datum(/datum/antagonist/wizard))
return FALSE
@@ -447,9 +448,7 @@
property_weights = list("story_potential" = -1, "trust" = 1, "chaos" = 2, "extended" = -2, "valid" = 2)
var/list/vents = list()
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/execute()
// 50% chance of being incremented by one
required_candidates += prob(50)
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/ready()
for(var/obj/machinery/atmospherics/components/unary/vent_pump/temp_vent in GLOB.machines)
if(QDELETED(temp_vent))
continue
@@ -463,6 +462,12 @@
vents += temp_vent
if(!vents.len)
return FALSE
return ..()
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/execute()
// 50% chance of being incremented by one
required_candidates += prob(50)
. = ..()
/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/generate_ruleset_body(mob/applicant)
@@ -497,7 +502,7 @@
property_weights = list("story_potential" = 1, "trust" = 1, "extended" = 1, "valid" = 2, "integrity" = 1)
var/list/spawn_locs = list()
/datum/dynamic_ruleset/midround/from_ghosts/nightmare/execute()
/datum/dynamic_ruleset/midround/from_ghosts/nightmare/ready()
for(var/X in GLOB.xeno_spawn)
var/turf/T = X
var/light_amount = T.get_lumcount()
@@ -505,7 +510,7 @@
spawn_locs += T
if(!spawn_locs.len)
return FALSE
. = ..()
return ..()
/datum/dynamic_ruleset/midround/from_ghosts/nightmare/generate_ruleset_body(mob/applicant)
var/datum/mind/player_mind = new /datum/mind(applicant.key)
@@ -523,88 +528,6 @@
log_game("DYNAMIC: [key_name(S)] was spawned as a Nightmare by the midround ruleset.")
return S
//////////////////////////////////////////////
// //
// SENTIENT DISEASE //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/midround/from_ghosts/sentient_disease
name = "Sentient Disease"
config_tag = "sentient_disease"
antag_flag = ROLE_ALIEN
enemy_roles = list("Virologist","Chief Medical Officer","Captain","Chemist")
required_enemies = list(2,1,1,1,0,0,0,0,0,0)
required_candidates = 1
weight = 4
cost = 5
requirements = list(30,30,20,20,15,10,10,10,10,5) // yes, it can even happen in "extended"!
property_weights = list("story_potential" = 1, "extended" = 1, "valid" = -2)
high_population_requirement = 5
/datum/dynamic_ruleset/midround/from_ghosts/sentient_disease/generate_ruleset_body(mob/applicant)
var/mob/camera/disease/virus = new /mob/camera/disease(SSmapping.get_station_center())
applicant.transfer_ckey(virus, FALSE)
INVOKE_ASYNC(virus, /mob/camera/disease/proc/pick_name)
message_admins("[ADMIN_LOOKUPFLW(virus)] has been made into a sentient disease by the midround ruleset.")
log_game("[key_name(virus)] was spawned as a sentient disease by the midround ruleset.")
return virus
//////////////////////////////////////////////
// //
// REVENANT //
// //
//////////////////////////////////////////////
/datum/dynamic_ruleset/midround/from_ghosts/revenant
name = "Revenant"
config_tag = "revenant"
antag_flag = ROLE_REVENANT
enemy_roles = list("Chief Engineer","Station Engineer","Captain","Chaplain","AI")
required_enemies = list(2,1,1,1,0,0,0,0,0,0)
required_candidates = 1
weight = 4
cost = 5
requirements = list(30,30,30,30,20,15,15,15,15,15)
high_population_requirement = 15
property_weights = list("story_potential" = -2, "extended" = -1)
var/list/spawn_locs = list()
/datum/dynamic_ruleset/midround/from_ghosts/revenant/acceptable(population = 0,threat = 0)
var/deadMobs = 0
for(var/mob/M in GLOB.dead_mob_list)
deadMobs++
if(deadMobs < REVENANT_SPAWN_THRESHOLD)
return FALSE
return ..()
/datum/dynamic_ruleset/midround/from_ghosts/revenant/ready(forced = FALSE)
for(var/mob/living/L in GLOB.dead_mob_list) //look for any dead bodies
var/turf/T = get_turf(L)
if(T && is_station_level(T.z))
spawn_locs += T
if(!spawn_locs.len || spawn_locs.len < 15) //look for any morgue trays, crematoriums, ect if there weren't alot of dead bodies on the station to pick from
for(var/obj/structure/bodycontainer/bc in GLOB.bodycontainers)
var/turf/T = get_turf(bc)
if(T && is_station_level(T.z))
spawn_locs += T
if(!spawn_locs.len) //If we can't find any valid spawnpoints, try the carp spawns
for(var/obj/effect/landmark/carpspawn/L in GLOB.landmarks_list)
if(isturf(L.loc))
spawn_locs += L.loc
if(!spawn_locs.len) //If we can't find THAT, then just give up and cry
return FALSE
return ..()
/datum/dynamic_ruleset/midround/from_ghosts/revenant/generate_ruleset_body(mob/applicant)
var/mob/living/simple_animal/revenant/revvie = new(pick(spawn_locs))
applicant.transfer_ckey(revvie, FALSE)
message_admins("[ADMIN_LOOKUPFLW(revvie)] has been made into a revenant by the midround ruleset.")
log_game("[key_name(revvie)] was spawned as a revenant by the midround ruleset.")
return revvie
//////////////////////////////////////////////
// //
// SLAUGHTER DEMON //
@@ -668,11 +591,11 @@
required_candidates = 2
weight = 8
cost = 10
requirements = list(101,101,70,50,40,30,30,20,15,15)
requirements = list(101,101,70,50,40,30,30,30,30,30)
blocking_rules = list(/datum/dynamic_ruleset/roundstart/nuclear,/datum/dynamic_ruleset/midround/from_ghosts/nuclear)
high_population_requirement = 15
var/datum/team/abductor_team/team
property_weights = list("story_potential" = 1, "extended" = -2, "valid" = 1, "trust" = -1, "chaos" = 2)
property_weights = list("extended" = -2, "valid" = 1, "trust" = -1, "chaos" = 2)
repeatable_weight_decrease = 4
repeatable = TRUE
@@ -741,8 +664,6 @@
Mind.transfer_to(Ninja)
var/datum/antagonist/ninja/ninjadatum = new
ninjadatum.helping_station = pick(TRUE,FALSE)
if(ninjadatum.helping_station)
mode.refund_threat(5)
Mind.add_antag_datum(ninjadatum)
if(Ninja.mind != Mind) //something has gone wrong!
@@ -751,6 +672,9 @@
message_admins("[ADMIN_LOOKUPFLW(Ninja)] has been made into a ninja by dynamic.")
log_game("[key_name(Ninja)] was spawned as a ninja by dynamic.")
return Ninja
/datum/dynamic_ruleset/midround/from_ghosts/ninja/finish_setup(mob/new_character, index)
return
#undef ABDUCTOR_MAX_TEAMS
#undef REVENANT_SPAWN_THRESHOLD
@@ -623,8 +623,7 @@
config_tag = "clownops"
antag_datum = /datum/antagonist/nukeop/clownop
antag_leader_datum = /datum/antagonist/nukeop/leader/clownop
requirements = list(101,101,101,101,101,101,101,101,101,101)
high_population_requirement = 101
weight = 1
property_weights = list("trust" = 2, "chaos" = 2, "extended" = -2, "story_potential" = 2, "valid" = 2)
@@ -803,11 +802,10 @@
/datum/dynamic_ruleset/roundstart/bloodsucker
name = "Bloodsuckers"
config_tag = "bloodsucker"
persistent = TRUE
antag_flag = ROLE_BLOODSUCKER
antag_datum = ANTAG_DATUM_BLOODSUCKER
minimum_required_age = 0
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
protected_roles = list("Chaplain", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
restricted_roles = list("Cyborg", "AI")
required_candidates = 1
weight = 2
@@ -1,16 +1,23 @@
/datum/dynamic_storyteller
var/name = "none"
var/config_tag = null
var/desc = "A coder's idiocy."
var/list/property_weights = list()
var/curve_centre = 0
var/curve_width = 1.8
var/forced_threat_level = -1
var/name = "none" // Name for voting.
var/config_tag = null // Config tag for config weights.
var/desc = "A coder's idiocy." // Description for voting.
var/list/property_weights = list() // See below.
var/curve_centre = 0 // As GLOB.dynamic_curve_centre.
var/curve_width = 1.8 // As GLOB.dynamic_curve_width.
var/forced_threat_level = -1 // As GLOB.dynamic_forced_threat_level
/*
NO_ASSASSIN: Will not have permanent assassination targets.
WAROPS_ALWAYS_ALLOWED: Can always do warops, regardless of threat level.
USE_PREF_WEIGHTS: Will use peoples' preferences to change the threat centre.
FORCE_IF_WON: If this mode won the vote, forces it
*/
var/flags = 0
var/weight = 3 // how many rounds need to have been recently played for this storyteller to be left out of the vote
var/event_frequency_lower = 6 MINUTES
var/event_frequency_upper = 20 MINUTES
var/datum/game_mode/dynamic/mode = null
var/dead_player_weight = 1 // How much dead players matter for threat calculation
var/weight = 3 // Weights for randomly picking storyteller. Multiplied by score after voting.
var/event_frequency_lower = 6 MINUTES // How rare events will be, at least.
var/event_frequency_upper = 20 MINUTES // How rare events will be, at most.
var/datum/game_mode/dynamic/mode = null // Cached as soon as it's made, by dynamic.
/**
Property weights are:
@@ -33,6 +40,27 @@ Property weights are:
var/event_injection_cooldown_middle = 0.5*(GLOB.dynamic_event_delay_max + GLOB.dynamic_event_delay_min)
mode.event_injection_cooldown = (round(CLAMP(EXP_DISTRIBUTION(event_injection_cooldown_middle), GLOB.dynamic_event_delay_min, GLOB.dynamic_event_delay_max)) + world.time)
/datum/dynamic_storyteller/proc/calculate_threat()
var/threat = 0
for(var/datum/antagonist/A in GLOB.antagonists)
if(A?.owner?.current && A.owner.current.stat != DEAD)
threat += A.threat()
for(var/r in SSevents.running)
var/datum/round_event/R = r
threat += R.threat()
for(var/mob/living/simple_animal/hostile/H in GLOB.mob_living_list)
var/turf/T = get_turf(H)
if(H.stat != DEAD && is_station_level(T.z) && !("Station" in H.faction))
threat += H.threat()
for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS])
if (M.stat != DEAD && M.mind && M.mind.assigned_role)
if(length(M.mind.antag_datums))
threat += SSjob.GetJob(M.mind.assigned_role).GetThreat()
else
threat -= SSjob.GetJob(M.mind.assigned_role).GetThreat()
threat += (mode.current_players[CURRENT_DEAD_PLAYERS].len)*dead_player_weight
return round(threat,0.1)
/datum/dynamic_storyteller/proc/do_process()
return
@@ -77,25 +105,9 @@ Property weights are:
if(mode.forced_injection)
mode.forced_injection = !dry_run
return 100
var/chance = 0
// If the high pop override is in effect, we reduce the impact of population on the antag injection chance
var/high_pop_factor = (mode.current_players[CURRENT_LIVING_PLAYERS].len >= GLOB.dynamic_high_pop_limit)
var/max_pop_per_antag = max(5,15 - round(mode.threat_level/10) - round(mode.current_players[CURRENT_LIVING_PLAYERS].len/(high_pop_factor ? 10 : 5)))
if (!mode.current_players[CURRENT_LIVING_ANTAGS].len)
chance += 80 // No antags at all? let's boost those odds!
else
var/current_pop_per_antag = mode.current_players[CURRENT_LIVING_PLAYERS].len / mode.current_players[CURRENT_LIVING_ANTAGS].len
if (current_pop_per_antag > max_pop_per_antag)
chance += min(50, 25+10*(current_pop_per_antag-max_pop_per_antag))
else
chance += 25-10*(max_pop_per_antag-current_pop_per_antag)
if (mode.current_players[CURRENT_DEAD_PLAYERS].len > mode.current_players[CURRENT_LIVING_PLAYERS].len)
chance -= 30 // More than half the crew died? ew, let's calm down on antags
if (mode.threat > 70)
chance += 15
if (mode.threat < 30)
chance -= 15
return round(max(0,chance))
var/threat_perc = mode.threat/mode.threat_level
return round(max(0,100*(1-(threat_perc*threat_perc*threat_perc))))
/datum/dynamic_storyteller/proc/roundstart_draft()
var/list/drafted_rules = list()
@@ -108,32 +120,41 @@ Property weights are:
for(var/property in property_weights)
if(property in rule.property_weights) // just treat it as 0 if it's not in there
property_weight += rule.property_weights[property] * property_weights[property]
drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
drafted_rules[rule] = (rule.get_weight() * property_weight)*rule.weight_mult
return drafted_rules
/datum/dynamic_storyteller/proc/midround_draft()
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/midround/rule in mode.midround_rules)
// if there are antags OR the rule is an antag rule, antag_acceptable will be true.
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost)
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
// Classic secret : only autotraitor/minor roles
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
continue
rule.trim_candidates()
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
/* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to
pick this particular ruleset.
Let's use a toy example: there's 60 threat level and 10 threat spent.
We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets.
Ruleset 1 has 30 cost, ruleset 2 has 5 cost.
When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1
is 2.26 times as likely to be picked, all other things considered.
Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight.
*/
var/threat_weight = 1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0))
if (rule.ready())
var/property_weight = 0
for(var/property in property_weights)
if(property in rule.property_weights)
property_weight += rule.property_weights[property] * property_weights[property]
drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
else if(mode.threat < rule.cost)
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough threat to spend")
drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1)
return drafted_rules
/datum/dynamic_storyteller/proc/latejoin_draft(mob/living/carbon/human/newPlayer)
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/latejoin/rule in mode.latejoin_rules)
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost)
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level - mode.threat))
// Classic secret : only autotraitor/minor roles
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
continue
@@ -144,59 +165,57 @@ Property weights are:
rule.candidates = list(newPlayer)
rule.trim_candidates()
var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat))
var/threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,cost_difference,0)))
if (rule.ready())
var/property_weight = 0
for(var/property in property_weights)
if(property in rule.property_weights)
property_weight += rule.property_weights[property] * property_weights[property]
drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
else if(mode.threat < rule.cost)
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough threat to spend")
drafted_rules[rule] = round(((rule.get_weight() * property_weight)*rule.weight_mult*threat_weight)*1000,1)
return drafted_rules
/datum/dynamic_storyteller/proc/event_draft()
var/list/drafted_rules = list()
for(var/datum/dynamic_ruleset/event/rule in mode.events)
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && mode.threat >= rule.cost)
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level) && (mode.threat_level - mode.threat) >= rule.cost)
if(rule.ready())
var/property_weight = 0
for(var/property in property_weights)
if(property in rule.property_weights)
property_weight += rule.property_weights[property] * property_weights[property]
drafted_rules[rule] = (rule.get_weight() + property_weight)*rule.weight_mult
else if(mode.threat < rule.cost)
SSblackbox.record_feedback("tally","dynamic",1,"Times rulesets rejected due to not enough threat to spend")
return drafted_rules
/datum/dynamic_storyteller/cowabunga
/datum/dynamic_storyteller/chaotic
name = "Chaotic"
config_tag = "chaotic"
curve_centre = 10
desc = "Chaos: high. Variation: high. Likely antags: clock cult, revs, wizard."
property_weights = list("extended" = -1, "chaos" = 10)
desc = "High chaos modes. Revs, wizard, clock cult. Multiple antags at once. Chaos is kept up all round."
property_weights = list("extended" = -1, "chaos" = 2)
weight = 1
event_frequency_lower = 2 MINUTES
event_frequency_upper = 10 MINUTES
flags = WAROPS_ALWAYS_ALLOWED
flags = WAROPS_ALWAYS_ALLOWED | FORCE_IF_WON
var/refund_cooldown = 0
/datum/dynamic_storyteller/cowabunga/get_midround_cooldown()
/datum/dynamic_storyteller/chaotic/do_process()
if(refund_cooldown < world.time)
mode.create_threat(20)
mode.log_threat("Chaotic storyteller ramped up the chaos. Threat level is now [mode.threat_level].")
refund_cooldown = world.time + 20 MINUTES
/datum/dynamic_storyteller/chaotic/get_midround_cooldown()
return ..() / 4
/datum/dynamic_storyteller/cowabunga/get_latejoin_cooldown()
/datum/dynamic_storyteller/chaotic/get_latejoin_cooldown()
return ..() / 4
/datum/dynamic_storyteller/cowabunga/do_process()
if(refund_cooldown < world.time)
mode.refund_threat(20)
mode.log_threat("Cowabunga it is. Refunded 20 threat. Threat is now [mode.threat].")
refund_cooldown = world.time + 600 SECONDS
/datum/dynamic_storyteller/team
name = "Teamwork"
config_tag = "teamwork"
desc = "Chaos: high. Variation: low. Likely antags: nukies, clockwork cult, wizard, blob, xenomorph."
desc = "Modes where the crew must band together. Nukies, xenos, blob. Only one antag threat at once."
curve_centre = 2
curve_width = 1.5
weight = 2
@@ -209,56 +228,141 @@ Property weights are:
/datum/dynamic_storyteller/conversion
name = "Conversion"
config_tag = "conversion"
desc = "Chaos: high. Variation: medium. Likely antags: cults, bloodsuckers, revs."
desc = "Conversion antags. Cults, revs."
curve_centre = 3
curve_width = 1
weight = 2
weight = 0
flags = WAROPS_ALWAYS_ALLOWED
property_weights = list("valid" = 1, "conversion" = 20)
/datum/dynamic_storyteller/classic
/datum/dynamic_storyteller/random
name = "Random"
config_tag = "random"
desc = "Chaos: varies. Variation: highest. No special weights attached."
weight = 6
flags = USE_PREF_WEIGHTS
curve_width = 4
weight = 1
desc = "No weighting at all; every ruleset has the same chance of happening. Cooldowns vary wildly. As random as it gets."
forced_threat_level = 100
/datum/dynamic_storyteller/memes
/datum/dynamic_storyteller/random/get_midround_cooldown()
return rand(GLOB.dynamic_midround_delay_min/2, GLOB.dynamic_midround_delay_max*2)
/datum/dynamic_storyteller/random/get_event_cooldown()
return rand(GLOB.dynamic_event_delay_min/2, GLOB.dynamic_event_delay_max*2)
/datum/dynamic_storyteller/random/get_latejoin_cooldown()
return rand(GLOB.dynamic_latejoin_delay_min/2, GLOB.dynamic_latejoin_delay_max*2)
/datum/dynamic_storyteller/random/get_injection_chance()
return 50 // i would do rand(0,100) but it's actually the same thing when you do the math
/datum/dynamic_storyteller/random/calculate_threat()
return 0 // what IS threat
/datum/dynamic_storyteller/random/roundstart_draft()
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/roundstart/rule in mode.roundstart_rules)
if (rule.acceptable(mode.roundstart_pop_ready, mode.threat_level)) // If we got the population and threat required
rule.candidates = mode.candidates.Copy()
rule.trim_candidates()
if (rule.ready() && rule.candidates.len > 0)
drafted_rules[rule] = 1
return drafted_rules
/datum/dynamic_storyteller/random/midround_draft()
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/midround/rule in mode.midround_rules)
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
// Classic secret : only autotraitor/minor roles
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
continue
rule.trim_candidates()
if (rule.ready())
drafted_rules[rule] = 1
return drafted_rules
/datum/dynamic_storyteller/random/latejoin_draft(mob/living/carbon/human/newPlayer)
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/latejoin/rule in mode.latejoin_rules)
if (rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
// Classic secret : only autotraitor/minor roles
if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET)))
continue
// No stacking : only one round-ender, unless threat level > stacking_limit.
if (mode.threat_level > GLOB.dynamic_stacking_limit && GLOB.dynamic_no_stacking)
if(rule.flags & HIGHLANDER_RULESET && mode.highlander_executed)
continue
rule.candidates = list(newPlayer)
rule.trim_candidates()
if (rule.ready())
drafted_rules[rule] = 1
return drafted_rules
/datum/dynamic_storyteller/random/event_draft()
var/list/drafted_rules = list()
for(var/datum/dynamic_ruleset/event/rule in mode.events)
if(rule.acceptable(mode.current_players[CURRENT_LIVING_PLAYERS].len, mode.threat_level))
if(rule.ready())
drafted_rules[rule] = 1
return drafted_rules
/datum/dynamic_storyteller/story
name = "Story"
config_tag = "story"
desc = "Chaos: varies. Variation: high. Likely antags: abductors, nukies, wizard, traitor."
weight = 4
desc = "Antags with options for loadouts and gimmicks. Traitor, wizard, nukies. Has a buildup-climax-falling action threat curve."
weight = 2
curve_width = 2
property_weights = list("story_potential" = 2)
/datum/dynamic_storyteller/story/do_process()
var/current_time = (world.time / SSautotransfer.targettime)*180
mode.threat_level = round(mode.initial_threat_level*(sin(current_time)+0.5),0.1)
/datum/dynamic_storyteller/classic
name = "Classic"
config_tag = "classic"
desc = "No special antagonist weights. Good variety, but not like random. Uses your chaos preference to weight."
flags = USE_PREF_WEIGHTS
curve_width = 4
property_weights = list("story_potential" = 10)
/datum/dynamic_storyteller/suspicion
name = "Intrigue"
config_tag = "intrigue"
desc = "Chaos: low. Variation: high. Likely antags: traitor, bloodsucker. Rare: revs, blood cult."
weight = 4
flags = USE_PREF_WEIGHTS
curve_width = 4
property_weights = list("trust" = -5)
desc = "Antags that instill distrust in the crew. Traitors, bloodsuckers."
weight = 2
curve_width = 2
dead_player_weight = 2
property_weights = list("trust" = -3)
/datum/dynamic_storyteller/liteextended
name = "Calm"
config_tag = "calm"
desc = "Chaos: low. Variation: medium. Likely antags: bloodsuckers, traitors, sentient disease, revenant."
desc = "Low-chaos round. Few antags. No conversion."
curve_centre = -3
curve_width = 0.5
flags = NO_ASSASSIN | FORCE_IF_WON
weight = 1
dead_player_weight = 5
property_weights = list("extended" = 2, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10)
/datum/dynamic_storyteller/no_antag
name = "Extended"
config_tag = "semiextended"
desc = "No standard antags. Threatening events may still spawn."
curve_centre = -5
curve_width = 0.5
flags = NO_ASSASSIN
weight = 2
property_weights = list("extended" = 1, "chaos" = -1, "valid" = -1, "story_potential" = 1, "conversion" = -10)
flags = NO_ASSASSIN | FORCE_IF_WON
weight = 1
property_weights = list("extended" = 2)
/datum/dynamic_storyteller/liteextended/get_injection_chance(dry_run = FALSE)
return ..()/2
/datum/dynamic_storyteller/no_antag/roundstart_draft()
return list()
/datum/dynamic_storyteller/no_antag/get_injection_chance(dry_run)
return 0
/datum/dynamic_storyteller/extended
name = "Extended"
name = "Super Extended"
config_tag = "extended"
desc = "Chaos: none. Variation: none. Likely antags: none."
desc = "No antags. No dangerous events."
curve_centre = -20
weight = 0
curve_width = 0.5
+3 -3
View File
@@ -323,7 +323,7 @@
var/free_tickets = CONFIG_GET(number/default_antag_tickets)
//Max extra tickets you can use
var/additional_tickets = CONFIG_GET(number/max_tickets_per_roll)
var/list/ckey_to_mind = list() //this is admittedly shitcode but I'm webediting
var/list/prev_tickets = SSpersistence.antag_rep //cache for hyper-speed in theory. how many tickets someone has stored
var/list/curr_tickets = list() //how many tickets someone has for *this* antag roll, so with the free tickets
@@ -337,7 +337,7 @@
continue
curr_tickets[mind_ckey] = amount
ckey_to_mind[mind_ckey] = M //make sure we can look them up after picking
if(!return_list) //return a single guy
var/ckey
if(length(curr_tickets))
@@ -584,7 +584,7 @@
//By default nuke just ends the round
/datum/game_mode/proc/OnNukeExplosion(off_station)
nuke_off_station = off_station
if(off_station < 2)
if(!off_station)
station_was_nuked = TRUE //Will end the round on next check.
//Additional report section in roundend report
+3 -1
View File
@@ -4,6 +4,7 @@
can_coexist_with_others = FALSE
job_rank = ROLE_GANG
antagpanel_category = "Gang"
threat = 2
var/hud_type = "gangster"
var/message_name = "Gangster"
var/datum/team/gang/gang
@@ -167,6 +168,7 @@
name = "Gang boss"
hud_type = "gang_boss"
message_name = "Leader"
threat = 10
/datum/antagonist/gang/boss/on_gain()
..()
@@ -474,4 +476,4 @@
#undef MAXIMUM_RECALLS
#undef INFLUENCE_INTERVAL
#undef INFLUENCE_INTERVAL
+6 -6
View File
@@ -21,7 +21,7 @@
/datum/team/gang/zerog
name = "Zero-G"
color = "#C0C0C0"
inner_outfits = list(/obj/item/clothing/under/suit_jacket/white)
inner_outfits = list(/obj/item/clothing/under/suit/white)
outer_outfits = list(/obj/item/clothing/suit/hooded/wintercoat)
/datum/team/gang/max
@@ -33,13 +33,13 @@
/datum/team/gang/blasto
name = "Blasto"
color = "#000080"
inner_outfits = list(/obj/item/clothing/under/suit_jacket/navy)
inner_outfits = list(/obj/item/clothing/under/suit/navy)
outer_outfits = list(/obj/item/clothing/suit/jacket/miljacket)
/datum/team/gang/waffle
name = "Waffle"
color = "#808000" //shared color with cyber, but they can keep brown cause waffles.
inner_outfits = list(/obj/item/clothing/under/suit_jacket/green)
inner_outfits = list(/obj/item/clothing/under/suit/green)
outer_outfits = list(/obj/item/clothing/suit/poncho)
/datum/team/gang/north
@@ -87,7 +87,7 @@
/datum/team/gang/tunnel
name = "Tunnel"
color = "#FF00FF" //Gave the leather jacket to the tunnel gang over diablo.
inner_outfits = list(/obj/item/clothing/under/villain)
inner_outfits = list(/obj/item/clothing/under/costume/villain)
outer_outfits = list(/obj/item/clothing/suit/jacket/leather)
/datum/team/gang/diablo
@@ -123,13 +123,13 @@
/datum/team/gang/h
name = "H"
color = "#993333"
inner_outfits = list(/obj/item/clothing/under/jabroni) //Why not?
inner_outfits = list(/obj/item/clothing/under/costume/jabroni) //Why not?
outer_outfits = list(/obj/item/clothing/suit/toggle/owlwings)
/datum/team/gang/rigatonifamily
name = "Rigatoni family"
color = "#cc9900" // p a s t a colored
inner_outfits = list(/obj/item/clothing/under/rank/chef)
inner_outfits = list(/obj/item/clothing/under/rank/civilian/chef)
outer_outfits = list(/obj/item/clothing/suit/apron/chef)
/datum/team/gang/weed
+2 -2
View File
@@ -165,7 +165,7 @@
/datum/outfit/syndicate/full
name = "Syndicate Operative - Full Kit"
glasses = /obj/item/clothing/glasses/night
glasses = /obj/item/clothing/glasses/night/syndicate
mask = /obj/item/clothing/mask/gas/syndicate
suit = /obj/item/clothing/suit/space/hardsuit/syndi
r_pocket = /obj/item/tank/internals/emergency_oxygen/engi
@@ -180,7 +180,7 @@
/datum/outfit/syndicate/lone
name = "Syndicate Operative - Lone"
glasses = /obj/item/clothing/glasses/night
glasses = /obj/item/clothing/glasses/night/syndicate
mask = /obj/item/clothing/mask/gas/syndicate
suit = /obj/item/clothing/suit/space/syndicate/black/red
head = /obj/item/clothing/head/helmet/space/syndicate/black/red
+6 -1
View File
@@ -1163,12 +1163,17 @@ GLOBAL_LIST_EMPTY(possible_sabotages)
var/payout = 0
var/payout_bonus = 0
var/area/dropoff = null
var/static/list/blacklisted_areas = typecacheof(list(/area/ai_monitored/turret_protected,
/area/solar/,
/area/ruin/, //thank you station space ruins
/area/science/test_area/,
/area/shuttle/))
/datum/objective/contract/proc/generate_dropoff() // Generate a random valid area on the station that the dropoff will happen.
var/found = FALSE
while(!found)
var/area/dropoff_area = pick(GLOB.sortedAreas)
if(dropoff_area && is_station_level(dropoff_area.z) && !dropoff_area.outdoors && !istype(dropoff_area, /area/shuttle/))
if(dropoff_area && is_station_level(dropoff_area.z) && !dropoff_area.outdoors && !is_type_in_typecache(dropoff_area, blacklisted_areas))
dropoff = dropoff_area
found = TRUE
+9 -4
View File
@@ -205,13 +205,18 @@
difficulty = 10
/datum/objective_item/special/boh
name = "a bag of holding."
name = "a type of bag of holding."
targetitem = /obj/item/storage/backpack/holding
difficulty = 10
/datum/objective_item/special/hypercell
name = "a hyper-capacity power cell."
targetitem = /obj/item/stock_parts/cell/hyper
/datum/objective_item/special/adv_surgical_drapes
name = "a set of smart surgical drapes."
targetitem = /obj/item/surgical_drapes/advanced
difficulty = 10 //would be 15 but cmo rarely have it on themselfs and leave it in their lockers...
/datum/objective_item/special/bluespace
name = "a bluespace power cell."
targetitem = /obj/item/stock_parts/cell/bluespace
difficulty = 5
/datum/objective_item/special/laserpointer
+3 -10
View File
@@ -41,16 +41,9 @@
var/count = 0
/datum/sabotage_objective/processing/power_sink/check_condition_processing()
count += 1
if(count==10 || sink_found) // doesn't need to fire that often unless a sink exists
var/sink_found_this_time = FALSE
for(var/datum/powernet/PN in GLOB.powernets)
for(var/obj/item/powersink/sink in PN.nodes)
sink_found_this_time = TRUE
won = max(won,sink.power_drained/1e8)
sink_found = sink_found_this_time
count = 0
return FALSE
for(var/s in GLOB.power_sinks)
var/obj/item/powersink/sink = s
won = max(won,sink.power_drained/1e8)
/obj/item/paper/guides/antag/supermatter_sabotage
info = "Ways to sabotage a supermatter:<br>\
+4 -5
View File
@@ -47,8 +47,8 @@
)
/obj/machinery/autolathe/Initialize()
AddComponent(/datum/component/material_container,
list(/datum/material/iron,
var/static/list/allowed_types = list(
/datum/material/iron,
/datum/material/glass,
/datum/material/gold,
/datum/material/silver,
@@ -62,10 +62,9 @@
/datum/material/plastic,
/datum/material/adamantine,
/datum/material/mythril
),
0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
)
AddComponent(/datum/component/material_container, allowed_types, _show_on_examine=TRUE, _after_insert=CALLBACK(src, .proc/AfterMaterialInsert))
. = ..()
wires = new /datum/wires/autolathe(src)
stored_research = new /datum/techweb/specialized/autounlocking/autolathe
matching_designs = list()
+11 -8
View File
@@ -77,6 +77,8 @@
name = "cloning data disk"
icon_state = "datadisk0" //Gosh I hope syndies don't mistake them for the nuke disk.
var/list/fields = list()
var/list/mutations = list()
var/max_mutations = 6
var/read_only = 0 //Well,it's still a floppy disk
//Disk stuff.
@@ -129,7 +131,7 @@
return examine(user)
//Start growing a human clone in the pod!
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, se, mindref, datum/species/mrace, list/features, factions, list/quirks)
/obj/machinery/clonepod/proc/growclone(ckey, clonename, ui, mutation_index, mindref, datum/species/mrace, list/features, factions, list/quirks)
if(panel_open)
return FALSE
if(mess || attempting)
@@ -165,8 +167,9 @@
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
H.hardset_dna(ui, se, H.real_name, null, mrace, features)
H.randmutb() //100% bad mutation. Can be cured with mutadone.
H.hardset_dna(ui, mutation_index, H.real_name, null, mrace, features)
H.easy_randmut(NEGATIVE+MINOR_NEGATIVE) //100% bad mutation. Can be cured with mutadone.
H.silent = 20 //Prevents an extreme edge case where clones could speak if they said something at exactly the right moment.
occupant = H
@@ -216,7 +219,7 @@
if(!is_operational()) //Autoeject if power is lost
if(mob_occupant)
go_out()
mob_occupant.apply_vore_prefs()
mob_occupant.copy_from_prefs_vr()
connected_message("Clone Ejected: Loss of power.")
else if(mob_occupant && (mob_occupant.loc == src))
@@ -226,7 +229,7 @@
SPEAK("The cloning has been \
aborted due to unrecoverable tissue failure.")
go_out()
mob_occupant.apply_vore_prefs()
mob_occupant.copy_from_prefs_vr()
else if(mob_occupant.cloneloss > (100 - heal_level))
mob_occupant.Unconscious(80)
@@ -272,7 +275,7 @@
BP.attach_limb(mob_occupant)
go_out()
mob_occupant.apply_vore_prefs()
mob_occupant.copy_from_prefs_vr()
else if (!mob_occupant || mob_occupant.loc != src)
occupant = null
@@ -320,7 +323,7 @@
SPEAK("An emergency ejection of the current clone has occurred. Survival not guaranteed.")
to_chat(user, "<span class='notice'>You force an emergency ejection. </span>")
go_out()
mob_occupant.apply_vore_prefs()
mob_occupant.copy_from_prefs_vr()
else
return ..()
@@ -418,7 +421,7 @@
if(mob_occupant && prob(100/(severity*efficiency)))
connected_message(Gibberish("EMP-caused Accidental Ejection", 0))
SPEAK(Gibberish("Exposure to electromagnetic fields has caused the ejection of, ERROR: John Doe, prematurely." ,0))
mob_occupant.apply_vore_prefs()
mob_occupant.copy_from_prefs_vr()
go_out()
/obj/machinery/clonepod/ex_act(severity, target)
+1 -1
View File
@@ -485,7 +485,7 @@
R.fields["id"] = copytext_char(md5(mob_occupant.real_name), 2, 6)
R.fields["UE"] = dna.unique_enzymes
R.fields["UI"] = dna.uni_identity
R.fields["SE"] = dna.struc_enzymes
R.fields["SE"] = dna.mutation_index
R.fields["blood_type"] = dna.blood_type
R.fields["features"] = dna.features
R.fields["factions"] = mob_occupant.faction
+10 -5
View File
@@ -15,6 +15,7 @@
var/message_cooldown = 0
var/ai_message_cooldown = 0
var/tmp_alertlevel = 0
var/static/security_level_cd // used to stop mass spam.
var/const/STATE_DEFAULT = 1
var/const/STATE_CALLSHUTTLE = 2
var/const/STATE_CANCELSHUTTLE = 3
@@ -94,16 +95,18 @@
I = pda.id
if (I && istype(I))
if(ACCESS_CAPTAIN in I.access)
if(security_level_cd > world.time)
to_chat(usr, "<span class='warning'>Security level protocols are currently on cooldown. Please stand by.</span>")
return
var/old_level = GLOB.security_level
if(!tmp_alertlevel)
tmp_alertlevel = SEC_LEVEL_GREEN
if(tmp_alertlevel < SEC_LEVEL_GREEN)
tmp_alertlevel = SEC_LEVEL_GREEN
if(tmp_alertlevel == SEC_LEVEL_BLUE)
tmp_alertlevel = SEC_LEVEL_BLUE
if(tmp_alertlevel > SEC_LEVEL_AMBER)
tmp_alertlevel = SEC_LEVEL_AMBER //Cannot engage delta with this
set_security_level(tmp_alertlevel)
security_level_cd = world.time + 15 SECONDS
if(GLOB.security_level != old_level)
to_chat(usr, "<span class='notice'>Authorization confirmed. Modifying security level.</span>")
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
@@ -376,19 +379,21 @@
if("ai-announce")
make_announcement(usr, 1)
if("ai-securitylevel")
if(security_level_cd > world.time)
to_chat(usr, "<span class='warning'>Security level protocols are currently on cooldown. Please stand by.</span>")
return
tmp_alertlevel = text2num( href_list["newalertlevel"] )
if(!tmp_alertlevel)
tmp_alertlevel = 0
tmp_alertlevel = SEC_LEVEL_GREEN
var/old_level = GLOB.security_level
if(!tmp_alertlevel)
tmp_alertlevel = SEC_LEVEL_GREEN
if(tmp_alertlevel < SEC_LEVEL_GREEN)
tmp_alertlevel = SEC_LEVEL_GREEN
if(tmp_alertlevel == SEC_LEVEL_BLUE)
tmp_alertlevel = SEC_LEVEL_BLUE
if(tmp_alertlevel > SEC_LEVEL_AMBER)
tmp_alertlevel = SEC_LEVEL_AMBER //Cannot engage delta with this
set_security_level(tmp_alertlevel)
security_level_cd = world.time + 15 SECONDS
if(GLOB.security_level != old_level)
//Only notify people if an actual change happened
var/security_level = get_security_level()
+594 -144
View File
@@ -1,14 +1,16 @@
#define INJECTOR_TIMEOUT 100
#define REJUVENATORS_INJECT 15
#define REJUVENATORS_MAX 90
#define NUMBER_OF_BUFFERS 3
#define SCRAMBLE_TIMEOUT 600
#define JOKER_TIMEOUT 12000 //20 minutes
#define JOKER_UPGRADE 1800
#define RADIATION_STRENGTH_MAX 15
#define RADIATION_STRENGTH_MULTIPLIER 1 //larger has a more range
#define RADIATION_STRENGTH_MULTIPLIER 1 //larger has more range
#define RADIATION_DURATION_MAX 30
#define RADIATION_ACCURACY_MULTIPLIER 3 //larger is less accurate
#define RADIATION_IRRADIATION_MULTIPLIER 1 //multiplier for how much radiation a test subject receives
#define SCANNER_ACTION_SE 1
@@ -23,22 +25,44 @@
icon_keyboard = "med_key"
density = TRUE
circuit = /obj/item/circuitboard/computer/scan_consolenew
var/radduration = 2
var/radstrength = 1
var/list/buffer[NUMBER_OF_BUFFERS]
var/injectorready = 0 //world timer cooldown var
var/current_screen = "mainmenu"
var/obj/machinery/dna_scannernew/connected = null
var/obj/item/disk/data/diskette = null
var/list/delayed_action = null
use_power = IDLE_POWER_USE
idle_power_usage = 10
active_power_usage = 400
light_color = LIGHT_COLOR_BLUE
var/datum/techweb/stored_research
var/max_storage = 6
var/combine
var/radduration = 2
var/radstrength = 1
var/max_chromosomes = 6
///Amount of mutations we can store
var/list/buffer[NUMBER_OF_BUFFERS]
///mutations we have stored
var/list/stored_mutations = list()
///chromosomes we have stored
var/list/stored_chromosomes = list()
///combinations of injectors for the 'injector selection'. format is list("Elsa" = list(Cryokinesis, Geladikinesis), "The Hulk" = list(Hulk, Gigantism), etc) Glowy and the gang being an initialized datum
var/list/injector_selection = list()
///max amount of selections you can make
var/max_injector_selections = 2
///hard-cap on the advanced dna injector
var/max_injector_mutations = 10
///the max instability of the advanced injector.
var/max_injector_instability = 50
var/injectorready = 0 //world timer cooldown var
var/jokerready = 0
var/scrambleready = 0
var/current_screen = "mainmenu"
var/current_mutation //what block are we inspecting? only used when screen = "info"
var/current_storage //what storage block are we looking at?
var/obj/machinery/dna_scannernew/connected = null
var/obj/item/disk/data/diskette = null
var/list/delayed_action = null
/obj/machinery/computer/scan_consolenew/attackby(obj/item/I, mob/user, params)
if (istype(I, /obj/item/disk/data)) //INSERT SOME DISKETTES
if (!src.diskette)
@@ -48,6 +72,28 @@
to_chat(user, "<span class='notice'>You insert [I].</span>")
src.updateUsrDialog()
return
if (istype(I, /obj/item/chromosome))
if(LAZYLEN(stored_chromosomes) < max_chromosomes)
I.forceMove(src)
stored_chromosomes += I
to_chat(user, "<span class='notice'>You insert [I].</span>")
else
to_chat(user, "<span class='warning'>You cannot store any more chromosomes!</span>")
return
if(istype(I, /obj/item/dnainjector/activator))
var/obj/item/dnainjector/activator/A = I
if(A.used)
to_chat(user,"<span class='notice'>Recycled [I].</span>")
if(A.research)
var/c_typepath = generate_chromosome()
var/obj/item/chromosome/CM = new c_typepath (drop_location())
to_chat(user,"<span class='notice'>Recycled [I].</span>")
if((LAZYLEN(stored_chromosomes) < max_chromosomes) && prob(60))
CM.forceMove(src)
stored_chromosomes += CM
to_chat(user,"<span class='notice'>[capitalize(CM.name)] added to storage.</span>")
qdel(I)
return
else
return ..()
@@ -58,12 +104,26 @@
if(!isnull(connected))
break
injectorready = world.time + INJECTOR_TIMEOUT
scrambleready = world.time + SCRAMBLE_TIMEOUT
jokerready = world.time + JOKER_TIMEOUT
stored_research = SSresearch.science_tech
/obj/machinery/computer/scan_consolenew/examine(mob/user)
. = ..()
if(jokerready < world.time)
. += "<span class='notice'>JOKER algorithm available.</span>"
else
. += "<span class='notice'>JOKER algorithm available in about [round(0.00166666667 * (jokerready - world.time))] minutes."
/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, last_change)
. = ..()
if(!user)
return
var/datum/browser/popup = new(user, "scannernew", "DNA Modifier Console", 800, 630) // Set up the popup browser window
if(user.client)
var/datum/asset/simple/assets = get_asset_datum(/datum/asset/simple/genetics)
assets.send(user.client)
if(!(in_range(src, user) || hasSiliconAccessInArea(user)))
popup.close()
return
@@ -76,7 +136,7 @@
if(connected && connected.is_operational())
if(connected.occupant) //set occupant_status message
viable_occupant = connected.occupant
if(viable_occupant.has_dna() && !HAS_TRAIT(viable_occupant, TRAIT_RADIMMUNE) && !HAS_TRAIT(viable_occupant, TRAIT_NOCLONE) || (connected.scan_level == 3)) //occupant is viable for dna modification
if(viable_occupant.has_dna() && !HAS_TRAIT_NOT_FROM(viable_occupant, TRAIT_RADIMMUNE,BLOODSUCKER_TRAIT) && !HAS_TRAIT(viable_occupant, TRAIT_NOCLONE) || (connected.scan_level == 3)) //occupant is viable for dna modification
occupant_status += "[viable_occupant.name] => "
switch(viable_occupant.stat)
if(CONSCIOUS)
@@ -88,8 +148,6 @@
occupant_status += "</div></div>"
occupant_status += "<div class='line'><div class='statusLabel'>Health:</div><div class='progressBar'><div style='width: [viable_occupant.health]%;' class='progressFill good'></div></div><div class='statusValue'>[viable_occupant.health] %</div></div>"
occupant_status += "<div class='line'><div class='statusLabel'>Radiation Level:</div><div class='progressBar'><div style='width: [viable_occupant.radiation/(RAD_MOB_SAFE/100)]%;' class='progressFill bad'></div></div><div class='statusValue'>[viable_occupant.radiation/(RAD_MOB_SAFE/100)] %</div></div>"
var/rejuvenators = viable_occupant.reagents.get_reagent_amount(/datum/reagent/medicine/potass_iodide)
occupant_status += "<div class='line'><div class='statusLabel'>Rejuvenators:</div><div class='progressBar'><div style='width: [round((rejuvenators / REJUVENATORS_MAX) * 100)]%;' class='progressFill highlight'></div></div><div class='statusValue'>[rejuvenators] units</div></div>"
occupant_status += "<div class='line'><div class='statusLabel'>Unique Enzymes :</div><div class='statusValue'><span class='highlight'>[viable_occupant.dna.unique_enzymes]</span></div></div>"
occupant_status += "<div class='line'><div class='statusLabel'>Last Operation:</div><div class='statusValue'>[last_change ? last_change : "----"]</div></div>"
else
@@ -147,28 +205,61 @@
buttons += "<a href='?src=[REF(src)];task=togglelock;'>[connected.locked ? "Unlock" : "Lock"] Scanner</a>"
else
buttons += "<span class='linkOff'>Open Scanner</span> <span class='linkOff'>Lock Scanner</span>"
if(viable_occupant)
buttons += "<a href='?src=[REF(src)];task=rejuv'>Inject Rejuvenators</a>"
if(viable_occupant && (scrambleready < world.time))
buttons += "<a href='?src=[REF(src)];task=scramble'>Scramble DNA</a>"
else
buttons += "<span class='linkOff'>Inject Rejuvenators</span>"
buttons += "<span class='linkOff'>Scramble DNA</span>"
if(diskette)
buttons += "<a href='?src=[REF(src)];task=ejectdisk'>Eject Disk</a>"
buttons += "<a href='?src=[REF(src)];task=screen;text=disk;'>Disk</a>"
else
buttons += "<span class='linkOff'>Eject Disk</span>"
if(current_screen == "buffer")
buttons += "<a href='?src=[REF(src)];task=screen;text=mainmenu;'>Radiation Emitter Menu</a>"
buttons += "<span class='linkOff'>Disk</span>"
if(current_screen == "mutations")
buttons += "<span class='linkOff'>Mutations</span>"
else
buttons += "<a href='?src=[REF(src)];task=screen;text=buffer;'>Buffer Menu</a>"
buttons += "<a href='?src=[REF(src)];task=screen;text=mutations;'>Mutations</a>"
if((current_screen == "mainmenu") || !current_screen)
buttons += "<span class='linkOff'>Genetic Sequencer</span>"
else
buttons += "<a href='?src=[REF(src)];task=screen;text=mainmenu;'>Genetic Sequencer</a>"
if(current_screen == "ui")
buttons += "<span class='linkOff'>Unique Identifiers</span>"
else
buttons += "<a href='?src=[REF(src)];task=screen;text=ui;'>Unique Identifiers</a>"
if(current_screen == "advinjector")
buttons += "<span class='linkOff'>Adv. Injectors</span>"
else
buttons += "<a href='?src=[REF(src)];task=screen;text=advinjector;'>Adv. Injectors</a>"
switch(current_screen)
if("working")
temp_html += status
temp_html += "<h1>System Busy</h1>"
temp_html += "Working ... Please wait ([DisplayTimeText(radduration*10)])"
if("buffer")
if("ui")
temp_html += status
temp_html += buttons
temp_html += "<h1>Buffer Menu</h1>"
temp_html += "<h1>Unique Identifiers</h1>"
temp_html += "<a href='?src=[REF(src)];task=setstrength;num=[radstrength-1];'>--</a> <a href='?src=[REF(src)];task=setstrength;'>Output Level</a> <a href='?src=[REF(src)];task=setstrength;num=[radstrength+1];'>++</a>"
temp_html += "<br><a href='?src=[REF(src)];task=setduration;num=[radduration-1];'>--</a> <a href='?src=[REF(src)];task=setduration;'>Pulse Duration</a> <a href='?src=[REF(src)];task=setduration;num=[radduration+1];'>++</a>"
temp_html += "<h3>Irradiate Subject</h3>"
temp_html += "<div class='line'><div class='statusLabel'>Unique Identifier:</div><div class='statusValue'><div class='clearBoth'>"
var/max_line_len = 7*DNA_BLOCK_SIZE
if(viable_occupant)
temp_html += "<div class='dnaBlockNumber'>1</div>"
var/char = ""
var/ui_text = viable_occupant.dna.uni_identity
var/len_byte = length(ui_text)
var/char_it = 0
for(var/byte_it = 1, byte_it <= len_byte, byte_it += length(char))
char_it++
char = ui_text[byte_it]
temp_html += "<a class='dnaBlock' href='?src=[REF(src)];task=pulseui;num=[char_it];'>[char]</a>"
if((char_it % max_line_len) == 0)
temp_html += "</div><div class='clearBoth'>"
if((char_it % DNA_BLOCK_SIZE) == 0 && byte_it < len_byte)
temp_html += "<div class='dnaBlockNumber'>[(char_it / DNA_BLOCK_SIZE) + 1]</div>"
else
temp_html += "---------"
temp_html += "</div></div><br><h1>Buffer Menu</h1>"
if(istype(buffer))
for(var/i=1, i<=buffer.len, i++)
@@ -188,7 +279,6 @@
temp_html += "<span class='linkOff'>Save to Disk</span>"
else
var/ui = buffer_slot["UI"]
var/se = buffer_slot["SE"]
var/ue = buffer_slot["UE"]
var/name = buffer_slot["name"]
var/label = buffer_slot["label"]
@@ -234,19 +324,6 @@
temp_html += "<a href='?src=[REF(src)];task=injector;num=[i];text=mixed'>UI+UE Injector</a>"
else
temp_html += "<span class='linkOff'>UI+UE Injector</span>"
if(se)
temp_html += "<br>\tSE: [se] "
if(viable_occupant)
temp_html += "<a href='?src=[REF(src)];task=transferbuffer;num=[i];text=se'>Occupant</a>"
else
temp_html += "<span class='linkOff'>Occupant</span>"
temp_html += "<a href='?src=[REF(src)];task=setdelayed;num=[i];delayaction=[SCANNER_ACTION_SE]'>Occupant:Delayed</a>"
if(injectorready < world.time )
temp_html += "<a href='?src=[REF(src)];task=injector;num=[i];text=se'>Injector</a>"
else
temp_html += "<span class='linkOff'>Injector</span>"
else
temp_html += "<br>\tSE: No Data"
if(viable_occupant)
temp_html += "<br><a href='?src=[REF(src)];task=setbuffer;num=[i];'>Save to Buffer</a>"
else
@@ -260,58 +337,225 @@
temp_html += "<a href='?src=[REF(src)];task=savedisk;num=[i];'>Save to Disk</a>"
else
temp_html += "<span class='linkOff'>Save to Disk</span>"
if("disk")
temp_html += status
temp_html += buttons
if(diskette)
temp_html += "<h3>[diskette.name]</h3><br>"
temp_html += "<a href='?src=[REF(src)];task=ejectdisk'>Eject Disk</a><br>"
if(LAZYLEN(diskette.mutations))
temp_html += "<table>"
for(var/datum/mutation/human/A in diskette.mutations)
temp_html += "<tr><td><span class='linkOff'>[A.name]</span></td>"
temp_html += "<td><a href='?src=[REF(src)];task=deletediskmut;num=[diskette.mutations.Find(A)];'>Delete</a></td>"
if(LAZYLEN(stored_mutations) < max_storage)
temp_html += "<td><a href='?src=[REF(src)];task=importdiskmut;num=[diskette.mutations.Find(A)];'>Import</a></td>"
else
temp_html += "<td><td><span class='linkOff'>Import</span></td>"
temp_html += "</tr>"
temp_html += "</table>"
else
temp_html += "<br>Load diskette to start ----------"
if("info")
if(LAZYLEN(stored_mutations))
if(LAZYLEN(stored_mutations) >= current_storage)
var/datum/mutation/human/HM = stored_mutations[current_storage]
if(HM)
temp_html += display_sequence(HM.type, current_storage)
else
current_screen = "mainmenu"
if("mutations")
temp_html += status
temp_html += buttons
temp_html += "<h3>Mutation Storage:<br></h3>"
temp_html += "<table>"
for(var/datum/mutation/human/HM in stored_mutations)
var/i = stored_mutations.Find(HM)
temp_html += "<tr><td><a href='?src=[REF(src)];task=inspectstorage;num=[i]'>[HM.name]</a></td>"
temp_html += "<td><a href='?src=[REF(src)];task=exportdiskmut;path=[HM.type]'>Export</a></td>"
temp_html += "<td><a href='?src=[REF(src)];task=deletemut;num=[i]'>Delete</a></td>"
if(combine == HM.type)
temp_html += "<td><span class='linkOff'>Combine</span></td></tr>"
else
temp_html += "<td><a href='?src=[REF(src)];task=combine;num=[i]'>Combine</a></td></tr>"
temp_html += "</table><br>"
temp_html += "<h3>Chromosome Storage:<br></h3>"
temp_html += "<table>"
for(var/i in 1 to stored_chromosomes.len)
var/obj/item/chromosome/CM = stored_chromosomes[i]
temp_html += "<td><a href='?src=[REF(src)];task=ejectchromosome;num=[i]'>[CM.name]</a></td><br>"
temp_html += "</table>"
if("advinjector")
temp_html += status
temp_html += buttons
temp_html += "<div class='line'><div class='statusLabel'><b>Advanced Injectors:</b></div></div><br>"
temp_html += "<div class='statusLine'><a href='?src=[REF(src)];task=add_advinjector;'>New Selection</a></div>"
for(var/A in injector_selection)
temp_html += "<div class='statusDisplay'><b>[A]</b>"
var/list/true_selection = injector_selection[A]
temp_html += "<br>"
for(var/B in true_selection)
var/datum/mutation/human/HM = B
var/mutcolor
switch(HM.quality)
if(POSITIVE)
mutcolor = "good"
if(MINOR_NEGATIVE)
mutcolor = "average"
if(NEGATIVE)
mutcolor = "bad"
temp_html += "<div class='statusLine'><span class='[mutcolor]'>[HM.name] </span>"
temp_html += "<a href='?src=[REF(src)];task=remove_from_advinjector;injector=[A];path=[HM.type];'>Remove</a></div>"
if (injectorready < world.time)
temp_html += "<div class='statusLine'> <a href='?src=[REF(src)];task=advinjector;injector=[A];'>Print Advanced Injector</a>"
else
temp_html += "<div class='statusLine'> <span class='linkOff'>Print Advanced Injector</span>"
temp_html += "<a href='?src=[REF(src)];task=remove_advinjector;injector=[A];'>Remove Injector</a></div>"
temp_html += "<br></div>"
else
temp_html += status
temp_html += buttons
temp_html += "<h1>Radiation Emitter Menu</h1>"
temp_html += "<a href='?src=[REF(src)];task=setstrength;num=[radstrength-1];'>--</a> <a href='?src=[REF(src)];task=setstrength;'>Output Level</a> <a href='?src=[REF(src)];task=setstrength;num=[radstrength+1];'>++</a>"
temp_html += "<br><a href='?src=[REF(src)];task=setduration;num=[radduration-1];'>--</a> <a href='?src=[REF(src)];task=setduration;'>Pulse Duration</a> <a href='?src=[REF(src)];task=setduration;num=[radduration+1];'>++</a>"
temp_html += "<h3>Irradiate Subject</h3>"
temp_html += "<div class='line'><div class='statusLabel'>Unique Identifier:</div><div class='statusValue'><div class='clearBoth'>"
var/max_line_len = 7*DNA_BLOCK_SIZE
temp_html += "<div class='line'><div class='statusLabel'>Genetic Sequence:</div><br>"
if(viable_occupant)
temp_html += "<div class='dnaBlockNumber'>1</div>"
var/char = ""
var/ui_text = viable_occupant.dna.uni_identity
var/len_byte = length(ui_text)
var/char_it = 0
for(var/byte_it = 1, byte_it <= len_byte, byte_it += length(char))
char_it++
char = ui_text[byte_it]
temp_html += "<a class='dnaBlock' href='?src=[REF(src)];task=pulseui;num=[char_it];'>[char]</a>"
if((char_it % max_line_len) == 0)
temp_html += "</div><div class='clearBoth'>"
if((char_it % DNA_BLOCK_SIZE) == 0 && byte_it < len_byte)
temp_html += "<div class='dnaBlockNumber'>[(char_it / DNA_BLOCK_SIZE) + 1]</div>"
if(viable_occupant)
for(var/A in get_mutation_list())
temp_html += display_inactive_sequence(A)
temp_html += "<br>"
else
temp_html += "----"
if(viable_occupant && (current_mutation in get_mutation_list(viable_occupant)))
temp_html += display_sequence(current_mutation)
temp_html += "</div><br>"
else
temp_html += "----"
temp_html += "</div></div></div><br>"
temp_html += "<br><div class='line'><div class='statusLabel'>Structural Enzymes:</div><div class='statusValue'><div class='clearBoth'>"
if(viable_occupant)
temp_html += "<div class='dnaBlockNumber'>1</div>"
var/char = ""
var/se_text = viable_occupant.dna.struc_enzymes
var/len_byte = length(se_text)
var/char_it = 0
for(var/byte_it = 1, byte_it <= len_byte, byte_it += length(char))
char_it++
char = se_text[byte_it]
temp_html += "<a class='dnaBlock' href='?src=[REF(src)];task=pulsese;num=[char_it];'>[char]</a>"
if((char_it % max_line_len) == 0)
temp_html += "</div><div class='clearBoth'>"
if((char_it % DNA_BLOCK_SIZE) == 0 && byte_it < len_byte)
temp_html += "<div class='dnaBlockNumber'>[(char_it / DNA_BLOCK_SIZE) + 1]</div>"
else
temp_html += "----"
temp_html += "</div></div></div>"
temp_html += "----------"
popup.set_content(temp_html.Join())
popup.open()
/obj/machinery/computer/scan_consolenew/proc/display_inactive_sequence(mutation)
var/temp_html = ""
var/class = "unselected"
var/mob/living/carbon/viable_occupant = get_viable_occupant()
if(!viable_occupant)
return
var/location = viable_occupant.dna.mutation_index.Find(mutation) //We do this because we dont want people using sysexp or similair tools to just read the mutations.
if(!location) //Do this only when needed, dont make a list with mutations for every iteration if you dont need to
var/list/mutations = get_mutation_list(TRUE)
if(mutation in mutations)
location = mutations.Find(mutation)
if(mutation == current_mutation)
class = "selected"
if(location > DNA_MUTATION_BLOCKS)
temp_html += "<a class='clean' href='?src=[REF(src)];task=inspect;num=[location];'><img class='[class]' src='dna_extra.gif' width = '65' alt='Extra Mutation'></a>"
else if(mutation in stored_research.discovered_mutations)
temp_html += "<a class='clean' href='?src=[REF(src)];task=inspect;num=[location];'><img class='[class]' src='dna_discovered.gif' width = '65' alt='Discovered Mutation'></a>"
else
temp_html += "<a class='clean' clean href='?src=[REF(src)];task=inspect;num=[location];'><img class='[class]' src='dna_undiscovered.gif' width = '65' alt=Undiscovered Mutation'></a>"
return temp_html
/obj/machinery/computer/scan_consolenew/proc/display_sequence(mutation, storage_slot) //Storage slot is for when viewing from the stored mutations
var/temp_html = ""
if(!mutation)
temp_html += "ERR-"
return
var/mut_name = "Unknown gene"
var/mut_desc = "No information available."
var/alias
var/discovered = FALSE
var/active = FALSE
var/scrambled = FALSE
var/instability
var/mob/living/carbon/viable_occupant = get_viable_occupant()
var/datum/mutation/human/HM = get_valid_mutation(mutation)
if(viable_occupant)
var/datum/mutation/human/M = viable_occupant.dna.get_mutation(mutation)
if(M)
scrambled = M.scrambled
active = TRUE
var/datum/mutation/human/A = GET_INITIALIZED_MUTATION(mutation)
alias = A.alias
if(active && !scrambled)
discover(mutation)
if(stored_research && (mutation in stored_research.discovered_mutations))
mut_name = A.name
mut_desc = A.desc
discovered = TRUE
instability = A.instability
var/extra
if(viable_occupant && !(storage_slot || viable_occupant.dna.mutation_in_sequence(mutation)))
extra = TRUE
if(discovered && !scrambled)
var/mutcolor
switch(A.quality)
if(POSITIVE)
mutcolor = "good"
if(MINOR_NEGATIVE)
mutcolor = "average"
if(NEGATIVE)
mutcolor = "bad"
if(HM)
instability *= GET_MUTATION_STABILIZER(HM)
temp_html += "<div class='statusDisplay'><div class='statusLine'><span class='[mutcolor]'><b>[mut_name]</b></span><small> ([alias])</small><br>"
temp_html += "<div class='statusLine'>Instability : [round(instability)]</span><br>"
else
temp_html += "<div class='statusDisplay'><div class='statusLine'><b>[alias]</b><br>"
temp_html += "<div class='statusLine'>[mut_desc]<br></div>"
if(active && !storage_slot)
if(HM?.can_chromosome && (HM in viable_occupant.dna.mutations))
var/i = viable_occupant.dna.mutations.Find(HM)
var/chromosome_name = "<a href='?src=[REF(src)];task=applychromosome;path=[mutation];num=[i];'>----</a>"
if(HM.chromosome_name)
chromosome_name = HM.chromosome_name
temp_html += "<div class='statusLine'>Chromosome status: [chromosome_name]<br></div>"
temp_html += "<div class='statusLine'>Sequence:<br><br></div>"
if(!scrambled)
for(var/block in 1 to A.blocks)
var/whole_sequence = get_valid_gene_string(mutation)
var/sequence = copytext(whole_sequence, 1+(block-1)*(DNA_SEQUENCE_LENGTH*2),(DNA_SEQUENCE_LENGTH*2*block+1))
temp_html += "<div class='statusLine'><table class='statusDisplay'><tr>"
for(var/i in 1 to DNA_SEQUENCE_LENGTH)
var/num = 1+(i-1)*2
var/genenum = num+(DNA_SEQUENCE_LENGTH*2*(block-1))
temp_html += "<td><div class='statusLine'><span class='dnaBlockNumber'><a href='?src=[REF(src)];task=pulsegene;num=[genenum];path=[mutation];'>[sequence[num]]</span></a></div></td>"
temp_html += "</tr><tr>"
for(var/i in 1 to DNA_SEQUENCE_LENGTH)
temp_html += "<td><div class='statusLine'>|</div></td>"
temp_html += "</tr><tr>"
for(var/i in 1 to DNA_SEQUENCE_LENGTH)
var/num = i*2
var/genenum = num+(DNA_SEQUENCE_LENGTH*2*(block-1))
temp_html += "<td><div class='statusLine'><span class='dnaBlockNumber'><a href='?src=[REF(src)];task=pulsegene;num=[genenum];path=[mutation];'>[sequence[num]]</span></a></div></td>"
temp_html += "</tr></table></div>"
temp_html += "<br><br><br><br><br>"
else
temp_html = "<div class='statusLine'>Sequence unreadable due to unpredictable mutation.</div>"
if((active || storage_slot) && (injectorready < world.time) && !scrambled)
temp_html += "<a href='?src=[REF(src)];task=activator;path=[mutation];slot=[storage_slot];'>Print Activator</a>"
temp_html += "<a href='?src=[REF(src)];task=mutator;path=[mutation];slot;=[storage_slot];'>Print Mutator</a>"
else
temp_html += "<span class='linkOff'>Print Activator</span>"
temp_html += "<span class='linkOff'>Print Mutator</span>"
temp_html += "<br><div class='statusLine'>"
if(storage_slot)
temp_html += "<a href='?src=[REF(src)];task=deletemut;num=[storage_slot];'>Delete</a>"
if((LAZYLEN(stored_mutations) < max_storage) && diskette && !diskette.read_only)
temp_html += "<a href='?src=[REF(src)];task=exportdiskmut;path=[mutation];'>Export</a>"
else
temp_html += "<span class='linkOff'>Export</span>"
temp_html += "<a href='?src=[REF(src)];task=screen;text=mutations;'>Back</a>"
else if(active && !scrambled)
temp_html += "<a href='?src=[REF(src)];task=savemut;path=[mutation];'>Store</a>"
temp_html += "<a href='?src=[REF(src)];task=expand_advinjector;path=[mutation];'>Adv. Injector</a>"
if(extra || scrambled)
temp_html += "<a href='?src=[REF(src)];task=nullify;'>Nullify</a>"
else
temp_html += "<span class='linkOff'>Nullify</span>"
temp_html += "</div></div>"
return temp_html
/obj/machinery/computer/scan_consolenew/Topic(href, href_list)
if(..())
@@ -350,13 +594,15 @@
radstrength = WRAP(num, 1, RADIATION_STRENGTH_MAX+1)
if("screen")
current_screen = href_list["text"]
if("rejuv")
if(viable_occupant && viable_occupant.reagents)
var/potassiodide_amount = viable_occupant.reagents.get_reagent_amount(/datum/reagent/medicine/potass_iodide)
var/can_add = max(min(REJUVENATORS_MAX - potassiodide_amount, REJUVENATORS_INJECT), 0)
viable_occupant.reagents.add_reagent(/datum/reagent/medicine/potass_iodide, can_add)
if("scramble")
if(viable_occupant && (scrambleready < world.time))
viable_occupant.dna.remove_all_mutations(list(MUT_NORMAL, MUT_EXTRA))
viable_occupant.dna.generate_dna_blocks()
scrambleready = world.time + SCRAMBLE_TIMEOUT
to_chat(usr,"<span class'notice'>DNA scrambled.</span>")
viable_occupant.radiation += RADIATION_STRENGTH_MULTIPLIER*50/(connected.damage_coeff ** 2)
if("setbufferlabel")
var/text = sanitize(input(usr, "Input a new label:", "Input an Text", null) as text|null)
var/text = sanitize(input(usr, "Input a new label:", "Input a Text", null) as text|null)
if(num && text)
num = CLAMP(num, 1, NUMBER_OF_BUFFERS)
var/list/buffer_slot = buffer[num]
@@ -368,7 +614,6 @@
buffer[num] = list(
"label"="Buffer[num]:[viable_occupant.real_name]",
"UI"=viable_occupant.dna.uni_identity,
"SE"=viable_occupant.dna.struc_enzymes,
"UE"=viable_occupant.dna.unique_enzymes,
"name"=viable_occupant.real_name,
"blood_type"=viable_occupant.dna.blood_type
@@ -382,8 +627,6 @@
if("transferbuffer")
if(num && viable_occupant)
switch(href_list["text"]) //Numbers are this high because other way upgrading laser is just not worth the hassle, and i cant think of anything better to inmrove
if("se")
apply_buffer(SCANNER_ACTION_SE,num)
if("ui")
apply_buffer(SCANNER_ACTION_UI,num)
if("ue")
@@ -397,28 +640,6 @@
if(istype(buffer_slot))
var/obj/item/dnainjector/timed/I
switch(href_list["text"])
if("se")
if(buffer_slot["SE"])
I = new /obj/item/dnainjector/timed(loc)
var/powers = 0
for(var/datum/mutation/human/HM in GLOB.good_mutations + GLOB.bad_mutations + GLOB.not_good_mutations)
if(HM.check_block_string(buffer_slot["SE"]))
I.add_mutations.Add(HM)
if(HM in GLOB.good_mutations)
powers += 1
if(HM in GLOB.bad_mutations + GLOB.not_good_mutations)
powers -= 1 //To prevent just unlocking everything to get all powers to a syringe for max tech
else
I.remove_mutations.Add(HM)
var/time_coeff
for(var/datum/mutation/human/HM in I.add_mutations)
if(!time_coeff)
time_coeff = HM.time_coeff
continue
time_coeff = min(time_coeff,HM.time_coeff)
if(connected)
I.duration = I.duration * time_coeff * connected.damage_coeff
I.damage_coeff = connected.damage_coeff
if("ui")
if(buffer_slot["UI"])
I = new /obj/item/dnainjector/timed(loc)
@@ -457,7 +678,7 @@
if("setdelayed")
if(num)
delayed_action = list("action"=text2num(href_list["delayaction"]),"buffer"=num)
if("pulseui","pulsese")
if("pulseui")
if(num && viable_occupant && connected)
radduration = WRAP(radduration, 1, RADIATION_DURATION_MAX+1)
radstrength = WRAP(radstrength, 1, RADIATION_STRENGTH_MAX+1)
@@ -469,7 +690,7 @@
ui_interact(usr)
sleep(radduration*10)
current_screen = "mainmenu"
current_screen = "ui"
if(viable_occupant && connected && connected.occupant==viable_occupant)
viable_occupant.radiation += (RADIATION_IRRADIATION_MULTIPLIER*radduration*radstrength)/(connected.damage_coeff ** 2) //Read comment in "transferbuffer" section above for explanation
@@ -478,7 +699,7 @@
var/len = length_char(viable_occupant.dna.uni_identity)
num = WRAP(num, 1, len+1)
num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len) //Each manipulator level above 1 makes randomization as accurate as selected time + manipulator lvl^2
//Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low
//Value is this high for the same reason as with laser - not worth the hassle of upgrading if the bonus is low
var/block = round((num-1)/DNA_BLOCK_SIZE)+1
var/subblock = num - block*DNA_BLOCK_SIZE
last_change = "UI #[block]-[subblock]; "
@@ -490,35 +711,229 @@
viable_occupant.dna.uni_identity = copytext_char(viable_occupant.dna.uni_identity, 1, num) + hex + copytext_char(viable_occupant.dna.uni_identity, num + 1)
viable_occupant.updateappearance(mutations_overlay_update=1)
if("pulsese")
var/len = length(viable_occupant.dna.struc_enzymes)
num = WRAP(num, 1, len+1)
num = randomize_radiation_accuracy(num, radduration + (connected.precision_coeff ** 2), len)
var/block = round((num-1)/DNA_BLOCK_SIZE)+1
var/subblock = num - block*DNA_BLOCK_SIZE
last_change = "SE #[block]-[subblock]; "
var/hex = copytext_char(viable_occupant.dna.struc_enzymes, num, num+1)
last_change += "[hex]"
hex = scramble(hex, radstrength, radduration)
last_change += "->[hex]"
viable_occupant.dna.struc_enzymes = copytext_char(viable_occupant.dna.struc_enzymes, 1, num) + hex + copytext_char(viable_occupant.dna.struc_enzymes, num + 1)
viable_occupant.domutcheck()
else
current_screen = "mainmenu"
if(connected)
connected.locked = locked_state
if("inspect")
if(viable_occupant)
var/list/mutations = get_mutation_list(TRUE)
if(current_mutation == mutations[num])
current_mutation = null
else
current_mutation = mutations[num]
if("inspectstorage")
current_storage = num
current_screen = "info"
if("savemut")
if(viable_occupant)
var/succes
if(LAZYLEN(stored_mutations) < max_storage)
var/mutation = text2path(href_list["path"])
if(ispath(mutation, /datum/mutation/human)) //sanity checks
var/datum/mutation/human/HM = viable_occupant.dna.get_mutation(mutation)
if(HM)
var/datum/mutation/human/A = new HM.type()
A.copy_mutation(HM)
succes = TRUE
stored_mutations += A
to_chat(usr,"<span class='notice'>Mutation succesfully stored.</span>")
if(!succes) //we can exactly return here
to_chat(usr,"<span class='warning'>Mutation storage is full.</span>")
if("deletemut")
var/datum/mutation/human/HM = stored_mutations[num]
if(HM)
stored_mutations.Remove(HM)
qdel(HM)
current_screen = "mutations"
if("activator")
if(injectorready < world.time)
var/mutation = text2path(href_list["path"])
if(ispath(mutation, /datum/mutation/human))
var/datum/mutation/human/HM = get_valid_mutation(mutation)
if(HM)
var/obj/item/dnainjector/activator/I = new /obj/item/dnainjector/activator(loc)
I.add_mutations += new HM.type (copymut = HM)
I.name = "[HM.name] activator"
I.research = TRUE
if(connected)
I.damage_coeff = connected.damage_coeff*4
injectorready = world.time + INJECTOR_TIMEOUT * (1 - 0.1 * connected.precision_coeff) //precision_coeff being the matter bin rating
else
injectorready = world.time + INJECTOR_TIMEOUT
if("mutator")
if(injectorready < world.time)
var/mutation = text2path(href_list["path"])
if(ispath(mutation, /datum/mutation/human))
var/datum/mutation/human/HM = get_valid_mutation(mutation)
if(HM)
var/obj/item/dnainjector/activator/I = new /obj/item/dnainjector/activator(loc)
I.add_mutations += new HM.type (copymut = HM)
I.doitanyway = TRUE
I.name = "[HM.name] injector"
if(connected)
I.damage_coeff = connected.damage_coeff
injectorready = world.time + INJECTOR_TIMEOUT * 5 * (1 - 0.1 * connected.precision_coeff)
else
injectorready = world.time + INJECTOR_TIMEOUT * 5
if("advinjector")
var/selection = href_list["injector"]
if(injectorready < world.time)
if(injector_selection.Find(selection))
var/list/true_selection = injector_selection[selection]
if(LAZYLEN(injector_selection))
var/obj/item/dnainjector/activator/I = new /obj/item/dnainjector/activator(loc)
for(var/A in true_selection)
var/datum/mutation/human/HM = A
I.add_mutations += new HM.type (copymut = HM)
I.doitanyway = TRUE
I.name = "Advanced [selection] injector"
if(connected)
I.damage_coeff = connected.damage_coeff
injectorready = world.time + INJECTOR_TIMEOUT * 8 * (1 - 0.1 * connected.precision_coeff)
else
injectorready = world.time + INJECTOR_TIMEOUT * 8
if("nullify")
if(viable_occupant)
var/datum/mutation/human/A = viable_occupant.dna.get_mutation(current_mutation)
if(A && (!viable_occupant.dna.mutation_in_sequence(current_mutation) || A.scrambled))
viable_occupant.dna.remove_mutation(current_mutation)
current_screen = "mainmenu"
current_mutation = null
if("pulsegene")
if(current_screen != "info")
var/path = text2path(href_list["path"])
if(viable_occupant && num && (path in viable_occupant.dna.mutation_index))
var/list/genes = list("A","T","G","C","X")
if(jokerready < world.time)
genes += "JOKER"
var/sequence = GET_GENE_STRING(path, viable_occupant.dna)
var/original = sequence[num]
var/new_gene = input("From [original] to-", "New block", original) as null|anything in genes
if(!new_gene)
new_gene = original
if(viable_occupant == get_viable_occupant()) //No cheesing
if((new_gene == "JOKER") && (jokerready < world.time))
var/true_genes = GET_SEQUENCE(current_mutation)
new_gene = true_genes[num]
jokerready = world.time + JOKER_TIMEOUT - (JOKER_UPGRADE * (connected.precision_coeff-1))
sequence = copytext(sequence, 1, num) + new_gene + copytext(sequence, num+1, length(sequence)+1)
viable_occupant.dna.mutation_index[path] = sequence
viable_occupant.radiation += RADIATION_STRENGTH_MULTIPLIER/connected.damage_coeff
viable_occupant.domutcheck()
if("exportdiskmut")
if(diskette && !diskette.read_only)
var/path = text2path(href_list["path"])
if(ispath(path, /datum/mutation/human))
var/datum/mutation/human/A = get_valid_mutation(path)
if(A && diskette && (LAZYLEN(diskette.mutations) < diskette.max_mutations))
var/datum/mutation/human/HM = new A.type()
diskette.mutations += HM
HM.copy_mutation(A)
to_chat(usr, "<span class='notice'>Succesfully written [A.name] to [diskette.name].</span>")
if("deletediskmut")
if(diskette && !diskette.read_only)
if(num && (LAZYLEN(diskette.mutations) >= num))
var/datum/mutation/human/A = diskette.mutations[num]
diskette.mutations.Remove(A)
qdel(A)
if("importdiskmut")
if(diskette && (LAZYLEN(diskette.mutations) >= num))
if(LAZYLEN(stored_mutations) < max_storage)
var/datum/mutation/human/A = diskette.mutations[num]
var/datum/mutation/human/HM = new A.type()
HM.copy_mutation(A)
stored_mutations += HM
to_chat(usr,"<span class='notice'>Succesfully written [A.name] to storage.")
if("combine")
if(num && (LAZYLEN(stored_mutations) >= num))
if(LAZYLEN(stored_mutations) < max_storage)
var/datum/mutation/human/A = stored_mutations[num]
var/path = A.type
if(combine)
var/result_path = get_mixed_mutation(combine, path)
if(result_path)
stored_mutations += new result_path()
to_chat(usr, "<span class='boldnotice'>Succes! New mutation has been added to storage</span>")
discover(result_path)
combine = null
else
to_chat(usr, "<span class='warning'>Failed. No mutation could be created.</span>")
combine = null
else
combine = path
to_chat(usr,"<span class='notice'>Selected [A.name] for combining</span>")
else
to_chat(usr, "<span class='warning'>Not enough space to store potential mutation.</span>")
if("ejectchromosome")
if(LAZYLEN(stored_chromosomes) <= num)
var/obj/item/chromosome/CM = stored_chromosomes[num]
CM.forceMove(drop_location())
adjust_item_drop_location(CM)
stored_chromosomes -= CM
if("applychromosome")
if(viable_occupant && (LAZYLEN(viable_occupant.dna.mutations) <= num))
var/datum/mutation/human/HM = viable_occupant.dna.mutations[num]
var/list/chromosomes = list()
for(var/obj/item/chromosome/CM in stored_chromosomes)
if(CM.can_apply(HM))
chromosomes += CM
if(chromosomes.len)
var/obj/item/chromosome/CM = input("Select a chromosome to apply", "Apply Chromosome") as null|anything in sortNames(chromosomes)
if(CM)
to_chat(usr, "<span class='notice'>You apply [CM] to [HM.name].</span>")
stored_chromosomes -= CM
CM.apply(HM)
if("expand_advinjector")
var/mutation = text2path(href_list["path"])
var/datum/mutation/human/HM = get_valid_mutation(mutation)
if(HM && LAZYLEN(injector_selection))
var/which_injector = input(usr, "Select Adv. Injector", "Advanced Injectors") as null|anything in injector_selection
if(injector_selection.Find(which_injector))
var/list/true_selection = injector_selection[which_injector]
var/total_instability
for(var/B in true_selection)
var/datum/mutation/human/mootacion = B
total_instability += mootacion.instability
total_instability += HM.instability
if((total_instability > max_injector_instability) || (true_selection.len + 1) > max_injector_mutations)
to_chat(usr, "<span class='warning'>Adding more mutations would make the advanced injector too unstable!</span>")
else
true_selection += HM //reminder that this works. because I keep forgetting this works
if("remove_from_advinjector")
var/mutation = text2path(href_list["path"])
var/selection = href_list["injector"]
if(injector_selection.Find(selection))
var/list/true_selection = injector_selection[selection]
for(var/B in true_selection)
var/datum/mutation/human/HM = B
if(HM.type == mutation)
true_selection -= HM
break
if("remove_advinjector")
var/selection = href_list["injector"]
for(selection in injector_selection)
if(selection == selection)
injector_selection.Remove(selection)
if("add_advinjector")
if(LAZYLEN(injector_selection) < max_injector_selections)
var/new_selection = input(usr, "Enter Adv. Injector name", "Advanced Injectors") as text|null
if(new_selection && !(new_selection in injector_selection))
injector_selection[new_selection] = list()
ui_interact(usr,last_change)
/obj/machinery/computer/scan_consolenew/proc/scramble(input,rs,rd)
/obj/machinery/computer/scan_consolenew/proc/scramble(input,rs,rd) //hexadecimal genetics. dont confuse with scramble button
var/length = length(input)
var/ran = gaussian(0, rs*RADIATION_STRENGTH_MULTIPLIER)
if(ran == 0)
ran = pick(-1,1) //hacky, statistically should almost never happen. 0-change makes people mad though
ran = pick(-1,1) //hacky, statistically should almost never happen. 0-chance makes people mad though
else if(ran < 0)
ran = round(ran) //negative, so floor it
else
@@ -533,7 +948,7 @@
var/mob/living/carbon/viable_occupant = null
if(connected)
viable_occupant = connected.occupant
if(!istype(viable_occupant) || !viable_occupant.dna || HAS_TRAIT(viable_occupant, TRAIT_RADIMMUNE) || HAS_TRAIT(viable_occupant, TRAIT_NOCLONE))
if(!istype(viable_occupant) || !viable_occupant.dna || HAS_TRAIT_NOT_FROM(viable_occupant, TRAIT_RADIMMUNE,BLOODSUCKER_TRAIT) || HAS_TRAIT(viable_occupant, TRAIT_NOCLONE))
viable_occupant = null
return viable_occupant
@@ -547,10 +962,6 @@
//Each laser level reduces damage by lvl^2, so no effect on 1 lvl, 4 times less damage on 2 and 9 times less damage on 3
//Numbers are this high because other way upgrading laser is just not worth the hassle, and i cant think of anything better to inmrove
switch(action)
if(SCANNER_ACTION_SE)
if(buffer_slot["SE"])
viable_occupant.dna.struc_enzymes = buffer_slot["SE"]
viable_occupant.domutcheck()
if(SCANNER_ACTION_UI)
if(buffer_slot["UI"])
viable_occupant.dna.uni_identity = buffer_slot["UI"]
@@ -572,15 +983,54 @@
viable_occupant.dna.blood_type = buffer_slot["blood_type"]
/obj/machinery/computer/scan_consolenew/proc/on_scanner_close()
if(delayed_action && connected)
if(delayed_action && get_viable_occupant())
to_chat(connected.occupant, "<span class='notice'>[src] activates!</span>")
apply_buffer(delayed_action["action"],delayed_action["buffer"])
delayed_action = null //or make it stick + reset button ?
/obj/machinery/computer/scan_consolenew/proc/get_valid_mutation(mutation)
var/mob/living/carbon/C = get_viable_occupant()
if(C)
var/datum/mutation/human/HM = C.dna.get_mutation(mutation)
if(HM)
return HM
for(var/datum/mutation/human/A in stored_mutations)
if(A.type == mutation)
return A
/obj/machinery/computer/scan_consolenew/proc/get_mutation_list(include_storage) //Returns a list of the mutation index types and any extra mutations
var/mob/living/carbon/viable_occupant = get_viable_occupant()
var/list/paths = list()
if(viable_occupant)
for(var/A in viable_occupant.dna.mutation_index)
paths += A
for(var/datum/mutation/human/A in viable_occupant.dna.mutations)
if(A.class == MUT_EXTRA)
paths += A.type
if(include_storage)
for(var/datum/mutation/human/A in stored_mutations)
paths += A.type
return paths
/obj/machinery/computer/scan_consolenew/proc/get_valid_gene_string(mutation)
var/mob/living/carbon/C = get_viable_occupant()
if(C && (mutation in C.dna.mutation_index))
return GET_GENE_STRING(mutation, C.dna)
else if(C && (LAZYLEN(C.dna.mutations)))
for(var/datum/mutation/human/A in C.dna.mutations)
if(A.type == mutation)
return GET_SEQUENCE(mutation)
for(var/datum/mutation/human/A in stored_mutations)
if(A.type == mutation)
return GET_SEQUENCE(mutation)
/obj/machinery/computer/scan_consolenew/proc/discover(mutation)
if(stored_research && !(mutation in stored_research.discovered_mutations))
stored_research.discovered_mutations += mutation
return TRUE
/////////////////////////// DNA MACHINES
#undef INJECTOR_TIMEOUT
#undef REJUVENATORS_INJECT
#undef REJUVENATORS_MAX
#undef NUMBER_OF_BUFFERS
#undef RADIATION_STRENGTH_MAX
+11 -8
View File
@@ -11,16 +11,19 @@
/obj/machinery/computer/robotics/proc/can_control(mob/user, mob/living/silicon/robot/R)
if(!istype(R))
return 0
return FALSE
if(isAI(user))
if (R.connected_ai != user)
return 0
return FALSE
if(iscyborg(user))
if (R != user)
return 0
return FALSE
if(R.scrambledcodes)
return 0
return 1
return FALSE
if (hasSiliconAccessInArea(user) && !issilicon(user))
if (!Adjacent(user))
return FALSE
return TRUE
/obj/machinery/computer/robotics/ui_interact(mob/user)
. = ..()
@@ -115,10 +118,10 @@
if(src.allowed(usr))
var/mob/living/silicon/robot/R = locate(href_list["stopbot"]) in GLOB.silicon_mobs
if(can_control(usr, R))
var/choice = input("Are you certain you wish to [R.locked_down? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
var/choice = input("Are you certain you wish to [!R.locked_down ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
if(choice == "Confirm" && can_control(usr, R) && !..())
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [R.locked_down? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
log_game("[key_name(usr)] [R.locked_down? "locked down" : "released"] [key_name(R)]!")
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [!R.locked_down ? "locked down" : "released"] [key_name(R, R.client)][ADMIN_LOOKUPFLW(R)]!</span>")
log_game("[key_name(usr)] [!R.locked_down ? "locked down" : "released"] [key_name(R)]!")
R.SetLockdown(!R.locked_down)
to_chat(R, "[!R.locked_down ? "<span class='notice'>Your lockdown has been lifted!" : "<span class='alert'>You have been locked down!"]</span>")
if(R.connected_ai)
+1 -1
View File
@@ -22,7 +22,7 @@
precision_coeff = 0
for(var/obj/item/stock_parts/scanning_module/P in component_parts)
scan_level += P.rating
for(var/obj/item/stock_parts/manipulator/P in component_parts)
for(var/obj/item/stock_parts/matter_bin/P in component_parts)
precision_coeff = P.rating
for(var/obj/item/stock_parts/micro_laser/P in component_parts)
damage_coeff = P.rating
+55 -1
View File
@@ -1,13 +1,67 @@
/obj/machinery/door/poddoor/shutters
gender = PLURAL
name = "shutters"
desc = "Heavy duty metal shutters that open mechanically."
desc = "Mechanical metal shutters operated by a button with a magnetic seal, keeping them airtight."
icon = 'icons/obj/doors/shutters.dmi'
layer = SHUTTER_LAYER
closingLayer = SHUTTER_LAYER
armor = list("melee" = 20, "bullet" = 20, "laser" = 20, "energy" = 75, "bomb" = 25, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 70)
damage_deflection = 20
max_integrity = 100
/obj/machinery/door/poddoor/shutters/preopen
icon_state = "open"
density = FALSE
opacity = 0
// The below shutters are the original ones from the TG codebase. They are remaining as "secure" shutters. If anyone wants to improve their animation, feel free.
// The original shutters are now shutters_old.dmi; copy the naming format of the files into new a new .dmi to add new shutters that work with the poddoor code for animating the doors.
// Originally, the shutters were reskins of blast doors. Eighty hits with the Cap's sabre to destroy one shutter is far too powerful considering shutters cannot be deconstructed (yet).
// If you're a mapper and want super strong shutter, use the 'old' ones.
/obj/machinery/door/poddoor/shutters/old
name = "strong shutters"
desc = "These shutters have an armoured frame; it looks like plasteel. These shutters look robust enough to survive explosions."
icon = 'icons/obj/doors/shutters_old.dmi'
icon_state = "closed"
armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 75, "bomb" = 30, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 70)
max_integrity = 300
/obj/machinery/door/poddoor/shutters/old/preopen
icon_state = "open"
density = FALSE
opacity = 0
// End of old shutter stuff. Credit for the old shutter sprites to TG.
/obj/machinery/door/poddoor/shutters/radiation
name = "radiation shutters"
desc = "Lead-lined shutters painted yellow with a radioactive hazard symbol on it. Blocks out most radiation"
icon = 'icons/obj/doors/shutters_radiation.dmi'
icon_state = "closed"
rad_insulation = 0.2
/obj/machinery/door/poddoor/shutters/radiation/preopen
icon_state = "open"
density = FALSE
opacity = 0
rad_insulation = 1
/obj/machinery/door/poddoor/shutters/radiation/do_animate(animation)
..()
switch(animation)
if("opening")
rad_insulation = 1
if("closing")
rad_insulation = 0.2
/obj/machinery/door/poddoor/shutters/window
name = "windowed shutters"
desc = "Mechanical shutters that have some form of plastic window in them, allowing you to see through the shutters at all times."
icon = 'icons/obj/doors/shutters_window.dmi'
icon_state = "closed"
opacity = 0
/obj/machinery/door/poddoor/shutters/window/preopen
icon_state = "open"
density = FALSE
+14 -14
View File
@@ -9,7 +9,7 @@
internal_radio = FALSE
//Start growing a human clone in the pod!
/obj/machinery/clonepod/experimental/growclone(ckey, clonename, ui, se, datum/species/mrace, list/features, factions)
/obj/machinery/clonepod/experimental/growclone(clonename, ui, mutation_index, mindref, last_death, blood_type, datum/species/mrace, list/features, factions, list/quirks)
if(panel_open)
return FALSE
if(mess || attempting)
@@ -20,15 +20,15 @@
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src)
H.hardset_dna(ui, se, H.real_name, null, mrace, features)
H.hardset_dna(ui, mutation_index, H.real_name, blood_type, mrace, features)
if(efficiency > 2)
var/list/unclean_mutations = (GLOB.not_good_mutations|GLOB.bad_mutations)
H.dna.remove_mutation_group(unclean_mutations)
if(efficiency > 5 && prob(20))
H.randmutvg()
H.easy_randmut(POSITIVE)
if(efficiency < 3 && prob(50))
var/mob/M = H.randmutb()
var/mob/M = H.easy_randmut(NEGATIVE+MINOR_NEGATIVE)
if(ismob(M))
H = M
@@ -42,18 +42,17 @@
icon_state = "pod_1"
//Get the clone body ready
maim_clone(H)
ADD_TRAIT(H, TRAIT_STABLEHEART, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_STABLELIVER, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_EMOTEMUTE, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_MUTE, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_NOBREATH, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, CLONING_POD_TRAIT)
ADD_TRAIT(H, TRAIT_STABLEHEART, "cloning")
ADD_TRAIT(H, TRAIT_EMOTEMUTE, "cloning")
ADD_TRAIT(H, TRAIT_MUTE, "cloning")
ADD_TRAIT(H, TRAIT_NOBREATH, "cloning")
ADD_TRAIT(H, TRAIT_NOCRITDAMAGE, "cloning")
H.Unconscious(80)
var/list/candidates = pollCandidatesForMob("Do you want and agree to play as a [clonename]'s defective clone, respect their character and not engage in ERP without permission from the original?", null, null, null, 100, H, POLL_IGNORE_CLONE)
var/list/candidates = pollCandidatesForMob("Do you want to play as [clonename]'s defective clone?", null, null, null, 100, H)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
C.transfer_ckey(H)
var/mob/C = pick(candidates)
H.key = C.key
if(grab_ghost_when == CLONER_FRESH_CLONE)
H.grab_ghost()
@@ -293,6 +292,7 @@
temp = "<font class='bad'>Cloning cycle already in progress.</font>"
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
else
pod.growclone(null, mob_occupant.real_name, dna.uni_identity, dna.struc_enzymes, clone_species, dna.features, mob_occupant.faction)
pod.growclone(mob_occupant.real_name, dna.uni_identity, dna.mutation_index, null, null, dna.blood_type, clone_species, dna.features, mob_occupant.faction)
temp = "[mob_occupant.real_name] => <font class='good'>Cloning data sent to pod.</font>"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
+2 -2
View File
@@ -316,7 +316,7 @@
if("togglemoving")
moving = !moving
if(moving)
spawn() MagnetMove()
INVOKE_ASYNC(src, .proc/MagnetMove)
updateUsrDialog()
@@ -325,7 +325,7 @@
if(looping)
return
while(moving && rpath.len >= 1)
while(moving && length(rpath) >= 1)
if(stat & (BROKEN|NOPOWER))
break
+3 -3
View File
@@ -17,7 +17,7 @@ Buildable meters
icon = 'icons/obj/atmospherics/pipes/pipe_item.dmi'
icon_state = "simple"
item_state = "buildpipe"
w_class = WEIGHT_CLASS_NORMAL
w_class = WEIGHT_CLASS_SMALL
level = 2
var/piping_layer = PIPING_LAYER_DEFAULT
var/RPD_type
@@ -63,7 +63,7 @@ Buildable meters
if(make_from.flipped)
do_a_flip()
/obj/item/pipe/dropped()
/obj/item/pipe/dropped(mob/user)
if(loc)
setPipingLayer(piping_layer)
return ..()
@@ -225,7 +225,7 @@ Buildable meters
to_chat(user, "<span class='notice'>You fasten the meter to the [loc.name].</span>")
qdel(src)
/obj/item/pipe_meter/dropped()
/obj/item/pipe_meter/dropped(mob/user)
. = ..()
if(loc)
setAttachLayer(piping_layer)
@@ -247,6 +247,7 @@
if(prob(70))
if(stored_gun)
stored_gun.forceMove(loc)
stored_gun = null
to_chat(user, "<span class='notice'>You remove the turret and salvage some components.</span>")
if(prob(50))
new /obj/item/stack/sheet/metal(loc, rand(1,4))
@@ -408,7 +409,7 @@
if(iscarbon(A))
var/mob/living/carbon/C = A
//If not emagged, only target non downed carbons
if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || C.recoveringstam))//CIT CHANGE - replaces check for lying with check for recoveringstam
if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || (C.combat_flags & COMBAT_FLAG_HARD_STAMCRIT)))//CIT CHANGE - replaces check for lying with check for recoveringstam
continue
//If emagged, target all but dead carbons
+9 -9
View File
@@ -8,7 +8,7 @@
layer = ABOVE_ALL_MOB_LAYER // Overhead
density = TRUE
circuit = /obj/item/circuitboard/machine/recycler
var/safety_mode = FALSE // Temporarily stops machine if it detects a mob
var/safety_mode = FALSE // Temporarily stops machine if it detects a mob, or upon deconstruction.
var/icon_name = "grinder-o"
var/blood = 0
var/eat_dir = WEST
@@ -24,6 +24,10 @@
update_icon()
req_one_access = get_all_accesses() + get_all_centcom_access()
/obj/machinery/recycler/deconstruct(disassembled = TRUE)
safety_mode = TRUE //to stop stock parts and circuit from being deleted.
return ..()
/obj/machinery/recycler/RefreshParts()
var/amt_made = 0
var/mat_mod = 0
@@ -97,18 +101,14 @@
. = ..()
/obj/machinery/recycler/proc/eat(atom/AM0, sound=TRUE)
if(stat & (BROKEN|NOPOWER))
return
if(safety_mode)
if(stat & (BROKEN|NOPOWER) || safety_mode)
return
var/list/to_eat
if(isitem(AM0))
to_eat = AM0.GetAllContentsIgnoring(GLOB.typecache_mob)
else
to_eat = list(AM0)
to_eat = AM0.GetAllContentsIgnoring(GLOB.typecache_mob)
var/items_recycled = 0
for(var/i in to_eat)
var/atom/movable/AM = i
var/obj/item/bodypart/head/as_head = AM
+6 -1
View File
@@ -46,7 +46,12 @@
)
/obj/machinery/autoylathe/Initialize()
AddComponent(/datum/component/material_container, list(/datum/material/iron, /datum/material/glass, /datum/material/plastic), 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
var/static/list/allowed_materials = list(
/datum/material/iron,
/datum/material/glass,
/datum/material/plastic
)
AddComponent(/datum/component/material_container, allowed_materials, 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
. = ..()
wires = new /datum/wires/autoylathe(src)
@@ -283,13 +283,13 @@
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_charge()
if(equip_ready) //disabled
return
var/area/A = get_base_area(chassis)
var/pow_chan = get_power_channel(A)
var/area/A = get_area(chassis)
var/pow_chan = get_MUTATION_POWER_channel(A)
if(pow_chan)
return 1000 //making magic
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_power_channel(var/area/A)
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/proc/get_MUTATION_POWER_channel(var/area/A)
var/pow_chan
if(A)
for(var/c in use_channels)
+13 -3
View File
@@ -35,9 +35,19 @@
)
/obj/machinery/mecha_part_fabricator/Initialize()
var/datum/component/material_container/materials = AddComponent(/datum/component/material_container,
list(/datum/material/iron, /datum/material/glass, /datum/material/silver, /datum/material/gold, /datum/material/diamond, /datum/material/plasma, /datum/material/uranium, /datum/material/bananium, /datum/material/titanium, /datum/material/bluespace), 0,
TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert))
var/static/list/allowed_types = list(
/datum/material/iron,
/datum/material/glass,
/datum/material/silver,
/datum/material/gold,
/datum/material/diamond,
/datum/material/plasma,
/datum/material/uranium,
/datum/material/bananium,
/datum/material/titanium,
/datum/material/bluespace
)
var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, allowed_types, 0, TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert))
materials.precise_insertion = TRUE
stored_research = new
return ..()
+1 -5
View File
@@ -320,11 +320,7 @@
clearInternalDamage(MECHA_INT_CONTROL_LOST)
/obj/mecha/narsie_act()
if(occupant)
var/mob/living/L = occupant
go_out(TRUE)
if(L)
L.narsie_act()
emp_act(EMP_HEAVY)
/obj/mecha/ratvar_act()
if((GLOB.ratvar_awakens || GLOB.clockwork_gateway_activated) && occupant)
+5
View File
@@ -506,3 +506,8 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/start/new_player)
/obj/effect/landmark/stationroom/box/engine/New()
. = ..()
templates = CONFIG_GET(keyed_list/box_random_engine)
// Landmark for the mining station
/obj/effect/landmark/stationroom/lavaland/station
templates = list("Public Mining Base" = 3)
icon = 'icons/rooms/Lavaland/Mining.dmi'
+16 -16
View File
@@ -24,20 +24,20 @@
/obj/effect/spawner/bundle/costume/gladiator
name = "gladiator costume spawner"
items = list(
/obj/item/clothing/under/gladiator,
/obj/item/clothing/under/costume/gladiator,
/obj/item/clothing/head/helmet/gladiator)
/obj/effect/spawner/bundle/costume/madscientist
name = "mad scientist costume spawner"
items = list(
/obj/item/clothing/under/gimmick/rank/captain/suit,
/obj/item/clothing/under/rank/captain/suit,
/obj/item/clothing/head/flatcap,
/obj/item/clothing/suit/toggle/labcoat/mad)
/obj/effect/spawner/bundle/costume/elpresidente
name = "el presidente costume spawner"
items = list(
/obj/item/clothing/under/gimmick/rank/captain/suit,
/obj/item/clothing/under/rank/captain/suit,
/obj/item/clothing/head/flatcap,
/obj/item/clothing/mask/cigarette/cigar/havana,
/obj/item/clothing/shoes/jackboots)
@@ -45,14 +45,14 @@
/obj/effect/spawner/bundle/costume/nyangirl
name = "nyangirl costume spawner"
items = list(
/obj/item/clothing/under/schoolgirl,
/obj/item/clothing/under/costume/schoolgirl,
/obj/item/clothing/head/kitty,
/obj/item/clothing/glasses/sunglasses/blindfold)
/obj/effect/spawner/bundle/costume/maid
name = "maid costume spawner"
items = list(
/obj/item/clothing/under/skirt/black,
/obj/item/clothing/under/dress/skirt,
/obj/effect/spawner/lootdrop/minor/beret_or_rabbitears,
/obj/item/clothing/glasses/sunglasses/blindfold)
@@ -61,13 +61,13 @@
name = "butler costume spawner"
items = list(
/obj/item/clothing/accessory/waistcoat,
/obj/item/clothing/under/suit_jacket,
/obj/item/clothing/under/suit/black,
/obj/item/clothing/head/that)
/obj/effect/spawner/bundle/costume/highlander
name = "highlander costume spawner"
items = list(
/obj/item/clothing/under/kilt,
/obj/item/clothing/under/costume/kilt,
/obj/item/clothing/head/beret)
/obj/effect/spawner/bundle/costume/prig
@@ -78,7 +78,7 @@
/obj/effect/spawner/lootdrop/minor/bowler_or_that,
/obj/item/clothing/shoes/sneakers/black,
/obj/item/cane,
/obj/item/clothing/under/sl_suit,
/obj/item/clothing/under/suit/sl,
/obj/item/clothing/mask/fakemoustache)
/obj/effect/spawner/bundle/costume/plaguedoctor
@@ -92,7 +92,7 @@
name = "night owl costume spawner"
items = list(
/obj/item/clothing/suit/toggle/owlwings,
/obj/item/clothing/under/owl,
/obj/item/clothing/under/costume/owl,
/obj/item/clothing/mask/gas/owl_mask)
/obj/effect/spawner/bundle/costume/griffin
@@ -100,20 +100,20 @@
items = list(
/obj/item/clothing/suit/toggle/owlwings/griffinwings,
/obj/item/clothing/shoes/griffin,
/obj/item/clothing/under/griffin,
/obj/item/clothing/under/costume/griffin,
/obj/item/clothing/head/griffin)
/obj/effect/spawner/bundle/costume/waiter
name = "waiter costume spawner"
items = list(
/obj/item/clothing/under/waiter,
/obj/item/clothing/under/suit/waiter,
/obj/effect/spawner/lootdrop/minor/kittyears_or_rabbitears,
/obj/item/clothing/suit/apron)
/obj/effect/spawner/bundle/costume/pirate
name = "pirate costume spawner"
items = list(
/obj/item/clothing/under/pirate,
/obj/item/clothing/under/costume/pirate,
/obj/item/clothing/suit/pirate,
/obj/effect/spawner/lootdrop/minor/pirate_or_bandana,
/obj/item/clothing/glasses/eyepatch)
@@ -121,7 +121,7 @@
/obj/effect/spawner/bundle/costume/commie
name = "commie costume spawner"
items = list(
/obj/item/clothing/under/soviet,
/obj/item/clothing/under/costume/soviet,
/obj/item/clothing/head/ushanka)
/obj/effect/spawner/bundle/costume/imperium_monk
@@ -145,7 +145,7 @@
/obj/effect/spawner/bundle/costume/cutewitch
name = "cute witch costume spawner"
items = list(
/obj/item/clothing/under/sundress,
/obj/item/clothing/under/dress/sundress,
/obj/item/clothing/head/witchwig,
/obj/item/staff/broom)
@@ -161,10 +161,10 @@
name = "sexy clown costume spawner"
items = list(
/obj/item/clothing/mask/gas/sexyclown,
/obj/item/clothing/under/rank/clown/sexy)
/obj/item/clothing/under/rank/civilian/clown/sexy)
/obj/effect/spawner/bundle/costume/sexymime
name = "sexy mime costume spawner"
items = list(
/obj/item/clothing/mask/gas/sexymime,
/obj/item/clothing/under/sexymime)
/obj/item/clothing/under/rank/civilian/mime/sexy)
+34
View File
@@ -28,6 +28,7 @@
take_damage(5, BURN, 0, 0)
/obj/structure/spider/stickyweb
var/genetic = FALSE
icon_state = "stickyweb1"
/obj/structure/spider/stickyweb/Initialize()
@@ -36,6 +37,8 @@
. = ..()
/obj/structure/spider/stickyweb/CanPass(atom/movable/mover, turf/target)
if (genetic)
return
if(istype(mover, /mob/living/simple_animal/hostile/poison/giant_spider))
return TRUE
else if(isliving(mover))
@@ -48,6 +51,27 @@
return prob(30)
return TRUE
/obj/structure/spider/stickyweb/genetic //for the spider genes in genetics
genetic = TRUE
var/mob/living/allowed_mob
/obj/structure/spider/stickyweb/genetic/Initialize(mapload, allowedmob)
allowed_mob = allowedmob
. = ..()
/obj/structure/spider/stickyweb/genetic/CanPass(atom/movable/mover, turf/target)
. = ..() //this is the normal spider web return aka a spider would make this TRUE
if(mover == allowed_mob)
return TRUE
else if(isliving(mover)) //we change the spider to not be able to go through here
if(mover.pulledby == allowed_mob)
return TRUE
if(prob(50))
to_chat(mover, "<span class='danger'>You get stuck in \the [src] for a moment.</span>")
return FALSE
else if(istype(mover, /obj/item/projectile))
return prob(30)
/obj/structure/spider/eggcluster
name = "egg cluster"
desc = "They seem to pulse slightly with an inner life."
@@ -128,6 +152,16 @@
else
..()
/obj/structure/spider/spiderling/attack_hand(mob/user)
. = ..()
if(user.a_intent != INTENT_HELP)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
user.visible_message("<span class='warning'>[user] splats [src].</span>", "<span class='warning'>You splat [src].</span>", "<span class='italics'>You hear a splat...</span>")
playsound(loc, 'sound/effects/snap.ogg', 25)
qdel(src)
return TRUE
/obj/structure/spider/spiderling/process()
if(travelling_in_vent)
if(isturf(loc))
@@ -52,9 +52,7 @@
pixel_y += round((cos(angle_override)+16*cos(angle_override)*2), 1)
/obj/effect/projectile_lighting
var/owner
/obj/effect/projectile_lighting/Initialize(mapload, color, range, intensity, owner_key)
/obj/effect/projectile_lighting/Initialize(mapload, color, range, intensity)
. = ..()
set_light(range, intensity, color)
owner = owner_key
@@ -1,4 +1,4 @@
/proc/generate_tracer_between_points(datum/point/starting, datum/point/ending, beam_type, color, qdel_in = 5, light_range = 2, light_color_override, light_intensity = 1, instance_key) //Do not pass z-crossing points as that will not be properly (and likely will never be properly until it's absolutely needed) supported!
/proc/generate_tracer_between_points(datum/point/starting, datum/point/ending, beam_type, color, qdel_in = 5, light_range = 2, light_color_override, light_intensity = 1, list/turfs) //Do not pass z-crossing points as that will not be properly (and likely will never be properly until it's absolutely needed) supported!
if(!istype(starting) || !istype(ending) || !ispath(beam_type))
return
var/datum/point/midpoint = point_midpoint_points(starting, ending)
@@ -9,17 +9,15 @@
. = PB
if(light_range > 0 && light_intensity > 0)
var/list/turf/line = getline(starting.return_turf(), ending.return_turf())
tracing_line:
for(var/i in line)
var/turf/T = i
for(var/obj/effect/projectile_lighting/PL in T)
if(PL.owner == instance_key)
continue tracing_line
QDEL_IN(new /obj/effect/projectile_lighting(T, light_color_override, light_range, light_intensity, instance_key), qdel_in > 0? qdel_in : 5)
for(var/i in line)
if(turfs[i])
continue
turfs[i] = TRUE
QDEL_IN(new /obj/effect/projectile_lighting(i, light_color_override, light_range, light_intensity), qdel_in > 0? qdel_in : 5)
line = null
if(qdel_in)
QDEL_IN(PB, qdel_in)
d
/obj/effect/projectile/tracer
name = "beam"
icon = 'icons/obj/projectiles_tracer.dmi'
+28 -2
View File
@@ -34,7 +34,12 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
var/usesound = null
var/throwhitsound = null
var/w_class = WEIGHT_CLASS_NORMAL
/// The amount of stamina it takes to swing an item in a normal melee attack do not lie to me and say it's for realism because it ain't. If null it will autocalculate from w_class.
var/total_mass //Total mass in arbitrary pound-like values. If there's no balance reasons for an item to have otherwise, this var should be the item's weight in pounds.
/// How long, in deciseconds, this staggers for, if null it will autocalculate from w_class and force. Unlike total mass this supports 0 and negatives.
var/stagger_force
var/slot_flags = 0 //This is used to determine on which slots an item can fit.
pass_flags = PASSTABLE
pressure_resistance = 4
@@ -399,7 +404,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
//If this were before the above checks, then trying to click on items would act a little funky and signal overrides wouldn't work.
if(iscarbon(usr))
var/mob/living/carbon/C = usr
if(C.combatmode && ((C.CanReach(src) || (src in directaccess)) && (C.CanReach(over) || (over in directaccess))))
if((C.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && ((C.CanReach(src) || (src in directaccess)) && (C.CanReach(over) || (over in directaccess))))
if(!C.get_active_held_item())
C.UnarmedAttack(src, TRUE)
if(C.get_active_held_item() == src)
@@ -496,7 +501,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
to_chat(user, "<span class='danger'>You cannot locate any organic eyes on this brain!</span>")
return
if(user.getStaminaLoss() >= STAMINA_SOFTCRIT)//CIT CHANGE - makes eyestabbing impossible if you're in stamina softcrit
if(IS_STAMCRIT(user))//CIT CHANGE - makes eyestabbing impossible if you're in stamina softcrit
to_chat(user, "<span class='danger'>You're too exhausted for that.</span>")//CIT CHANGE - ditto
return //CIT CHANGE - ditto
@@ -850,3 +855,24 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
if (HAS_TRAIT(src, TRAIT_NODROP))
return
return ..()
/obj/item/proc/embedded(mob/living/carbon/human/embedded_mob)
return
/obj/item/proc/unembedded()
return
/**
* Sets our slowdown and updates equipment slowdown of any mob we're equipped on.
*/
/obj/item/proc/set_slowdown(new_slowdown)
slowdown = new_slowdown
if(CHECK_BITFIELD(item_flags, IN_INVENTORY))
var/mob/living/L = loc
if(istype(L))
L.update_equipment_speed_mods()
/obj/item/vv_edit_var(var_name, var_value)
. = ..()
if(var_name == NAMEOF(src, slowdown))
set_slowdown(var_value) //don't care if it's a duplicate edit as slowdown'll be set, do it anyways to force normal behavior.
+1 -1
View File
@@ -117,7 +117,7 @@
. = ..()
if(!isinhands || !(loaded?.amount))
return
var/mutable_appearance/cable_overlay = mutable_appearance(icon, "rcl-[CEILING(loaded.amount/(max_amount/3), 1)]")
var/mutable_appearance/cable_overlay = mutable_appearance(icon_file, "rcl-[CEILING(loaded.amount/(max_amount/3), 1)]")
cable_overlay.color = GLOB.cable_colors[colors[current_color_index]]
. += cable_overlay
+92
View File
@@ -0,0 +1,92 @@
/obj/item/chromosome
name = "blank chromosome"
icon = 'icons/obj/chromosomes.dmi'
icon_state = ""
desc = "A tube holding chromosomic data."
force = 0
w_class = WEIGHT_CLASS_SMALL
var/stabilizer_coeff = 1 //lower is better, affects genetic stability
var/synchronizer_coeff = 1 //lower is better, affects chance to backfire
var/power_coeff = 1 //higher is better, affects "strength"
var/energy_coeff = 1 //lower is better. affects recharge time
var/weight = 5
/obj/item/chromosome/proc/can_apply(datum/mutation/human/HM)
if(!HM || !(HM.can_chromosome == CHROMOSOME_NONE))
return FALSE
if((stabilizer_coeff != 1) && (HM.stabilizer_coeff != -1)) //if the chromosome is 1, we dont change anything. If the mutation is -1, we cant change it. sorry
return TRUE
if((synchronizer_coeff != 1) && (HM.synchronizer_coeff != -1))
return TRUE
if((power_coeff != 1) && (HM.power_coeff != -1))
return TRUE
if((energy_coeff != 1) && (HM.energy_coeff != -1))
return TRUE
/obj/item/chromosome/proc/apply(datum/mutation/human/HM)
if(HM.stabilizer_coeff != -1)
HM.stabilizer_coeff = stabilizer_coeff
if(HM.synchronizer_coeff != -1)
HM.synchronizer_coeff = synchronizer_coeff
if(HM.power_coeff != -1)
HM.power_coeff = power_coeff
if(HM.energy_coeff != -1)
HM.energy_coeff = energy_coeff
HM.can_chromosome = 2
HM.chromosome_name = name
HM.modify()
qdel(src)
/proc/generate_chromosome()
var/static/list/chromosomes
if(!chromosomes)
chromosomes = list()
for(var/A in subtypesof(/obj/item/chromosome))
var/obj/item/chromosome/CM = A
if(!initial(CM.weight))
break
chromosomes[A] = initial(CM.weight)
return pickweight(chromosomes)
/obj/item/chromosome/stabilizer
name = "stabilizer chromosome"
desc = "A chromosome that adjusts to the body to reduce genetic damage by 20%."
icon_state = "stabilizer"
stabilizer_coeff = 0.8
weight = 1
/obj/item/chromosome/synchronizer
name = "synchronizer chromosome"
desc = "A chromosome that gives the mind more controle over the mutation, reducing knockback and downsides by 50%."
icon_state = "synchronizer"
synchronizer_coeff = 0.5
/obj/item/chromosome/power
name = "power chromosome"
desc = "A power chromosome for boosting certain mutation's power by 50%."
icon_state = "power"
power_coeff = 1.5
/obj/item/chromosome/energy
name = "energetic chromosome"
desc = "A chromosome that reduces cooldown on action based mutations by 50%."
icon_state = "energy"
energy_coeff = 0.5
/obj/item/chromosome/reinforcer
name = "reinforcement chromosome"
desc = "Renders the mutation immune to mutadone."
icon_state = "reinforcer"
weight = 3
/obj/item/chromosome/reinforcer/can_apply(datum/mutation/human/HM)
if(!HM || !(HM.can_chromosome == CHROMOSOME_NONE))
return FALSE
return !HM.mutadone_proof
/obj/item/chromosome/reinforcer/apply(datum/mutation/human/HM)
HM.mutadone_proof = TRUE
..()
+1 -5
View File
@@ -18,15 +18,11 @@
/obj/item/chrono_eraser/proc/pass_mind(datum/mind/M)
erased_minds += M
/obj/item/chrono_eraser/dropped()
/obj/item/chrono_eraser/dropped(mob/user)
..()
if(PA)
qdel(PA)
/obj/item/chrono_eraser/Destroy()
dropped()
return ..()
/obj/item/chrono_eraser/ui_action_click(mob/user)
if(iscarbon(user))
var/mob/living/carbon/C = user
@@ -74,7 +74,7 @@
build_path = /obj/machinery/dna_scannernew
req_components = list(
/obj/item/stock_parts/scanning_module = 1,
/obj/item/stock_parts/manipulator = 1,
/obj/item/stock_parts/matter_bin = 1,
/obj/item/stock_parts/micro_laser = 1,
/obj/item/stack/sheet/glass = 1,
/obj/item/stack/cable_coil = 2)
@@ -21,7 +21,7 @@
var/obj/item/cigbutt/butt = /obj/item/cigbutt
saved_appearance = initial(butt.appearance)
/obj/item/chameleon/dropped()
/obj/item/chameleon/dropped(mob/user)
..()
disrupt()
+10 -13
View File
@@ -170,7 +170,7 @@
flags_1 = CONDUCT_1
brightness_on = 2
light_color = "#FFDDCC"
flashlight_power = 0.3
flashlight_power = 0.5
var/holo_cooldown = 0
/obj/item/flashlight/pen/afterattack(atom/target, mob/user, proximity_flag)
@@ -227,15 +227,12 @@
custom_materials = null
on = TRUE
// green-shaded desk lamp
/obj/item/flashlight/lamp/green
desc = "A classic green-shaded desk lamp."
icon_state = "lampgreen"
item_state = "lampgreen"
/obj/item/flashlight/lamp/verb/toggle_light()
set name = "Toggle light"
set category = "Object"
@@ -258,12 +255,13 @@
desc = "A red Nanotrasen issued flare. There are instructions on the side, it reads 'pull cord, make light'."
w_class = WEIGHT_CLASS_SMALL
brightness_on = 7 // Pretty bright.
total_mass = 0.8
light_color = "#FA421A"
icon_state = "flare"
item_state = "flare"
actions_types = list()
var/fuel = 0
var/on_damage = 7
var/on_damage = 9
var/produce_heat = 1500
heat = 1000
light_color = LIGHT_COLOR_FLARE
@@ -331,14 +329,15 @@
name = "torch"
desc = "A torch fashioned from some leaves and a log."
w_class = WEIGHT_CLASS_BULKY
brightness_on = 4
brightness_on = 6 //When on were like a lantern
light_color = "#FAA44B"
icon_state = "torch"
item_state = "torch"
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
light_color = LIGHT_COLOR_ORANGE
on_damage = 10
total_mass = TOTAL_MASS_NORMAL_ITEM
on_damage = 12 //Its a log thats on fire
slot_flags = null
/obj/item/flashlight/lantern
@@ -348,10 +347,9 @@
lefthand_file = 'icons/mob/inhands/equipment/mining_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/mining_righthand.dmi'
desc = "A mining lantern."
brightness_on = 6 // luminosity when on
brightness_on = 6 // luminosity when on
light_color = "#FFAA44"
flashlight_power = 0.75
flashlight_power = 0.8
/obj/item/flashlight/slime
gender = PLURAL
@@ -372,7 +370,6 @@
var/emp_cur_charges = 4
var/charge_tick = 0
/obj/item/flashlight/emp/New()
..()
START_PROCESSING(SSobj, src)
@@ -435,7 +432,7 @@
var/fuel = 0
/obj/item/flashlight/glowstick/Initialize()
fuel = rand(1600, 2000)
fuel = rand(1000, 1500)
light_color = color
. = ..()
@@ -540,7 +537,7 @@
/obj/item/flashlight/eyelight
name = "eyelight"
desc = "This shouldn't exist outside of someone's head, how are you seeing this?"
brightness_on = 15
brightness_on = 10
flags_1 = CONDUCT_1
item_flags = DROPDEL
actions_types = list()
@@ -218,7 +218,7 @@
/obj/item/geiger_counter/cyborg/proc/redirect_rad_act(datum/source, amount)
rad_act(amount)
/obj/item/geiger_counter/cyborg/dropped()
/obj/item/geiger_counter/cyborg/dropped(mob/user)
. = ..()
if(listeningTo)
UnregisterSignal(listeningTo, COMSIG_ATOM_RAD_ACT)
@@ -1,5 +1,7 @@
// Powersink - used to drain station power
GLOBAL_LIST_EMPTY(power_sinks)
/obj/item/powersink
desc = "A nulling power sink which drains energy from electrical systems."
name = "power sink"
@@ -26,6 +28,14 @@
var/obj/structure/cable/attached // the attached cable
/obj/item/powersink/Initialize()
. = ..()
GLOB.power_sinks += src
/obj/item/powersink/Destroy()
GLOB.power_sinks -= src
. = ..()
/obj/item/powersink/update_icon_state()
icon_state = "powersink[mode == OPERATING]"
+107 -3
View File
@@ -150,7 +150,10 @@ SLIME SCANNER
msg += "\n\t<span class='alert'>Subject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage.</span>"
if(advanced)
msg += "\n\t<span class='info'>Cellular Damage Level: [M.getCloneLoss()].</span>"
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(advanced && H.has_dna())
msg += "\n\t<span class='info'>Genetic Stability: [H.dna.stability]%.</span>"
to_chat(user, msg)
msg = ""
@@ -326,8 +329,8 @@ SLIME SCANNER
breathes = FALSE
if(NOBLOOD in C.dna.species.species_traits)
blooded = FALSE
var/has_liver = (!(NOLIVER in C.dna.species.species_traits))
var/has_stomach = (!(NOSTOMACH in C.dna.species.species_traits))
var/has_liver = C.dna && !(NOLIVER in C.dna.species.species_traits)
var/has_stomach = C.dna && !(NOSTOMACH in C.dna.species.species_traits)
if(!M.getorganslot(ORGAN_SLOT_EYES))
msg += "\t<span class='alert'><b>Subject does not have eyes.</b></span>\n"
if(!M.getorganslot(ORGAN_SLOT_EARS))
@@ -776,3 +779,104 @@ SLIME SCANNER
var/response = SEND_SIGNAL(M, COMSIG_NANITE_SCAN, user, TRUE)
if(!response)
to_chat(user, "<span class='info'>No nanites detected in the subject.</span>")
/obj/item/sequence_scanner
name = "genetic sequence scanner"
icon = 'icons/obj/device.dmi'
icon_state = "gene"
item_state = "healthanalyzer"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
desc = "A hand-held scanner for analyzing someones gene sequence on the fly. Hold near a DNA console to update the internal database."
flags_1 = CONDUCT_1
item_flags = NOBLUDGEON
slot_flags = ITEM_SLOT_BELT
throwforce = 3
w_class = WEIGHT_CLASS_TINY
throw_speed = 3
throw_range = 7
custom_materials = list(/datum/material/iron=200)
var/list/discovered = list() //hit a dna console to update the scanners database
var/list/buffer
var/ready = TRUE
var/cooldown = 200
/obj/item/sequence_scanner/attack(mob/living/M, mob/living/carbon/human/user)
add_fingerprint(user)
if (!HAS_TRAIT_NOT_FROM(M, TRAIT_RADIMMUNE,BLOODSUCKER_TRAIT)) //no scanning if its a husk or DNA-less Species
user.visible_message("<span class='notice'>[user] analyzes [M]'s genetic sequence.</span>", \
"<span class='notice'>You analyze [M]'s genetic sequence.</span>")
gene_scan(M, user)
else
user.visible_message("<span class='notice'>[user] failed to analyse [M]'s genetic sequence.</span>", "<span class='warning'>[M] has no readable genetic sequence!</span>")
/obj/item/sequence_scanner/attack_self(mob/user)
display_sequence(user)
/obj/item/sequence_scanner/attack_self_tk(mob/user)
return
/obj/item/sequence_scanner/afterattack(obj/O, mob/user, proximity)
. = ..()
if(!istype(O) || !proximity)
return
if(istype(O, /obj/machinery/computer/scan_consolenew))
var/obj/machinery/computer/scan_consolenew/C = O
if(C.stored_research)
to_chat(user, "<span class='notice'>[name] linked to central research database.</span>")
discovered = C.stored_research.discovered_mutations
else
to_chat(user,"<span class='warning'>No database to update from.</span>")
/obj/item/sequence_scanner/proc/gene_scan(mob/living/carbon/C, mob/living/user)
if(!iscarbon(C) || !C.has_dna())
return
buffer = C.dna.mutation_index
to_chat(user, "<span class='notice'>Subject [C.name]'s DNA sequence has been saved to buffer.</span>")
if(LAZYLEN(buffer))
for(var/A in buffer)
to_chat(user, "<span class='notice'>[get_display_name(A)]</span>")
/obj/item/sequence_scanner/proc/display_sequence(mob/living/user)
if(!LAZYLEN(buffer) || !ready)
return
var/list/options = list()
for(var/A in buffer)
options += get_display_name(A)
var/answer = input(user, "Analyze Potential", "Sequence Analyzer") as null|anything in sortList(options)
if(answer && ready && user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
var/sequence
for(var/A in buffer) //this physically hurts but i dont know what anything else short of an assoc list
if(get_display_name(A) == answer)
sequence = buffer[A]
break
if(sequence)
var/display
for(var/i in 0 to length_char(sequence) / DNA_MUTATION_BLOCKS-1)
if(i)
display += "-"
display += copytext_char(sequence, 1 + i*DNA_MUTATION_BLOCKS, DNA_MUTATION_BLOCKS*(1+i) + 1)
to_chat(user, "<span class='boldnotice'>[display]</span><br>")
ready = FALSE
icon_state = "[icon_state]_recharging"
addtimer(CALLBACK(src, .proc/recharge), cooldown, TIMER_UNIQUE)
/obj/item/sequence_scanner/proc/recharge()
icon_state = initial(icon_state)
ready = TRUE
/obj/item/sequence_scanner/proc/get_display_name(mutation)
var/datum/mutation/human/HM = GET_INITIALIZED_MUTATION(mutation)
if(!HM)
return "ERROR"
if(mutation in discovered)
return "[HM.name] ([HM.alias])"
else
return HM.alias
@@ -63,10 +63,10 @@
if(attached_device)
attached_device.holder_movement()
/obj/item/transfer_valve/dropped()
/obj/item/transfer_valve/dropped(mob/user)
. = ..()
if(attached_device)
attached_device.dropped()
attached_device.dropped(user)
/obj/item/transfer_valve/on_found(mob/finder)
if(attached_device)
+257 -76
View File
@@ -14,33 +14,25 @@
var/list/add_mutations = list()
var/list/remove_mutations = list()
var/list/add_mutations_static = list()
var/list/remove_mutations_static = list()
var/used = 0
/obj/item/dnainjector/attack_paw(mob/user)
return attack_hand(user)
/obj/item/dnainjector/proc/prepare()
for(var/mut_key in add_mutations_static)
add_mutations.Add(GLOB.mutations_list[mut_key])
for(var/mut_key in remove_mutations_static)
remove_mutations.Add(GLOB.mutations_list[mut_key])
/obj/item/dnainjector/proc/inject(mob/living/carbon/M, mob/user)
prepare()
if(M.has_dna() && !HAS_TRAIT(M, TRAIT_RADIMMUNE) && !HAS_TRAIT(M, TRAIT_NOCLONE))
if(M.has_dna() && !HAS_TRAIT_NOT_FROM(M, TRAIT_RADIMMUNE,BLOODSUCKER_TRAIT) && !HAS_TRAIT(M, TRAIT_NOCLONE))
M.radiation += rand(20/(damage_coeff ** 2),50/(damage_coeff ** 2))
var/log_msg = "[key_name(user)] injected [key_name(M)] with the [name]"
for(var/datum/mutation/human/HM in remove_mutations)
HM.force_lose(M)
for(var/datum/mutation/human/HM in add_mutations)
if(HM.name == RACEMUT)
for(var/HM in remove_mutations)
M.dna.remove_mutation(HM)
for(var/HM in add_mutations)
if(HM == RACEMUT)
message_admins("[ADMIN_LOOKUPFLW(user)] injected [key_name_admin(M)] with the [name] <span class='danger'>(MONKEY)</span>")
log_msg += " (MONKEY)"
HM.force_give(M)
if(M.dna.mutation_in_sequence(HM))
M.dna.activate_mutation(HM)
else
M.dna.add_mutation(HM, MUT_EXTRA)
if(fields)
if(fields["name"] && fields["UE"] && fields["blood_type"])
M.real_name = fields["name"]
@@ -90,123 +82,123 @@
/obj/item/dnainjector/antihulk
name = "\improper DNA injector (Anti-Hulk)"
desc = "Cures green skin."
remove_mutations_static = list(HULK)
remove_mutations = list(HULK)
/obj/item/dnainjector/hulkmut
name = "\improper DNA injector (Hulk)"
desc = "This will make you big and strong, but give you a bad skin condition."
add_mutations_static = list(HULK)
add_mutations = list(HULK)
/obj/item/dnainjector/xraymut
name = "\improper DNA injector (X-ray)"
desc = "Finally you can see what the Captain does."
add_mutations_static = list(XRAY)
add_mutations = list(XRAY)
/obj/item/dnainjector/antixray
name = "\improper DNA injector (Anti-X-ray)"
desc = "It will make you see harder."
remove_mutations_static = list(XRAY)
remove_mutations = list(XRAY)
/////////////////////////////////////
/obj/item/dnainjector/antiglasses
name = "\improper DNA injector (Anti-Glasses)"
desc = "Toss away those glasses!"
remove_mutations_static = list(BADSIGHT)
remove_mutations = list(BADSIGHT)
/obj/item/dnainjector/glassesmut
name = "\improper DNA injector (Glasses)"
desc = "Will make you need dorkish glasses."
add_mutations_static = list(BADSIGHT)
add_mutations = list(BADSIGHT)
/obj/item/dnainjector/epimut
name = "\improper DNA injector (Epi.)"
desc = "Shake shake shake the room!"
add_mutations_static = list(EPILEPSY)
add_mutations = list(EPILEPSY)
/obj/item/dnainjector/antiepi
name = "\improper DNA injector (Anti-Epi.)"
desc = "Will fix you up from shaking the room."
remove_mutations_static = list(EPILEPSY)
remove_mutations = list(EPILEPSY)
////////////////////////////////////
/obj/item/dnainjector/anticough
name = "\improper DNA injector (Anti-Cough)"
desc = "Will stop that awful noise."
remove_mutations_static = list(COUGH)
remove_mutations = list(COUGH)
/obj/item/dnainjector/coughmut
name = "\improper DNA injector (Cough)"
desc = "Will bring forth a sound of horror from your throat."
add_mutations_static = list(COUGH)
add_mutations = list(COUGH)
/obj/item/dnainjector/antidwarf
name = "\improper DNA injector (Anti-Dwarfism)"
desc = "Helps you grow big and strong."
remove_mutations_static = list(DWARFISM)
remove_mutations = list(DWARFISM)
/obj/item/dnainjector/dwarf
name = "\improper DNA injector (Dwarfism)"
desc = "It's a small world after all."
add_mutations_static = list(DWARFISM)
add_mutations = list(DWARFISM)
/obj/item/dnainjector/clumsymut
name = "\improper DNA injector (Clumsy)"
desc = "Makes clown minions."
add_mutations_static = list(CLOWNMUT)
add_mutations = list(CLOWNMUT)
/obj/item/dnainjector/anticlumsy
name = "\improper DNA injector (Anti-Clumsy)"
desc = "Apply this for Security Clown."
remove_mutations_static = list(CLOWNMUT)
remove_mutations = list(CLOWNMUT)
/obj/item/dnainjector/antitour
name = "\improper DNA injector (Anti-Tour.)"
desc = "Will cure Tourette's."
remove_mutations_static = list(TOURETTES)
remove_mutations = list(TOURETTES)
/obj/item/dnainjector/tourmut
name = "\improper DNA injector (Tour.)"
desc = "Gives you a nasty case of Tourette's."
add_mutations_static = list(TOURETTES)
add_mutations = list(TOURETTES)
/obj/item/dnainjector/stuttmut
name = "\improper DNA injector (Stutt.)"
desc = "Makes you s-s-stuttterrr."
add_mutations_static = list(NERVOUS)
add_mutations = list(NERVOUS)
/obj/item/dnainjector/antistutt
name = "\improper DNA injector (Anti-Stutt.)"
desc = "Fixes that speaking impairment."
remove_mutations_static = list(NERVOUS)
remove_mutations = list(NERVOUS)
/obj/item/dnainjector/antifire
name = "\improper DNA injector (Anti-Fire)"
desc = "Cures fire."
remove_mutations_static = list(COLDRES)
remove_mutations = list(SPACEMUT)
/obj/item/dnainjector/firemut
name = "\improper DNA injector (Fire)"
desc = "Gives you fire."
add_mutations_static = list(COLDRES)
add_mutations = list(SPACEMUT)
/obj/item/dnainjector/blindmut
name = "\improper DNA injector (Blind)"
desc = "Makes you not see anything."
add_mutations_static = list(BLINDMUT)
add_mutations = list(BLINDMUT)
/obj/item/dnainjector/antiblind
name = "\improper DNA injector (Anti-Blind)"
desc = "IT'S A MIRACLE!!!"
remove_mutations_static = list(BLINDMUT)
remove_mutations = list(BLINDMUT)
/obj/item/dnainjector/antitele
name = "\improper DNA injector (Anti-Tele.)"
desc = "Will make you not able to control your mind."
remove_mutations_static = list(TK)
remove_mutations = list(TK)
/obj/item/dnainjector/telemut
name = "\improper DNA injector (Tele.)"
desc = "Super brain man!"
add_mutations_static = list(TK)
add_mutations = list(TK)
/obj/item/dnainjector/telemut/darkbundle
name = "\improper DNA injector"
@@ -215,100 +207,258 @@
/obj/item/dnainjector/deafmut
name = "\improper DNA injector (Deaf)"
desc = "Sorry, what did you say?"
add_mutations_static = list(DEAFMUT)
add_mutations = list(DEAFMUT)
/obj/item/dnainjector/antideaf
name = "\improper DNA injector (Anti-Deaf)"
desc = "Will make you hear once more."
remove_mutations_static = list(DEAFMUT)
remove_mutations = list(DEAFMUT)
/obj/item/dnainjector/h2m
name = "\improper DNA injector (Human > Monkey)"
desc = "Will make you a flea bag."
add_mutations_static = list(RACEMUT)
add_mutations = list(RACEMUT)
/obj/item/dnainjector/m2h
name = "\improper DNA injector (Monkey > Human)"
desc = "Will make you...less hairy."
remove_mutations_static = list(RACEMUT)
remove_mutations = list(RACEMUT)
/obj/item/dnainjector/antichameleon
name = "\improper DNA injector (Anti-Chameleon)"
remove_mutations_static = list(CHAMELEON)
remove_mutations = list(CHAMELEON)
/obj/item/dnainjector/chameleonmut
name = "\improper DNA injector (Chameleon)"
add_mutations_static = list(CHAMELEON)
add_mutations = list(CHAMELEON)
/obj/item/dnainjector/antiwacky
name = "\improper DNA injector (Anti-Wacky)"
remove_mutations_static = list(WACKY)
remove_mutations = list(WACKY)
/obj/item/dnainjector/wackymut
name = "\improper DNA injector (Wacky)"
add_mutations_static = list(WACKY)
add_mutations = list(WACKY)
/obj/item/dnainjector/antimute
name = "\improper DNA injector (Anti-Mute)"
remove_mutations_static = list(MUT_MUTE)
remove_mutations = list(MUT_MUTE)
/obj/item/dnainjector/mutemut
name = "\improper DNA injector (Mute)"
add_mutations_static = list(MUT_MUTE)
add_mutations = list(MUT_MUTE)
/obj/item/dnainjector/antismile
name = "\improper DNA injector (Anti-Smile)"
remove_mutations_static = list(SMILE)
remove_mutations = list(SMILE)
/obj/item/dnainjector/smilemut
name = "\improper DNA injector (Smile)"
add_mutations_static = list(SMILE)
add_mutations = list(SMILE)
/obj/item/dnainjector/unintelligiblemut
name = "\improper DNA injector (Unintelligible)"
add_mutations_static = list(UNINTELLIGIBLE)
add_mutations = list(UNINTELLIGIBLE)
/obj/item/dnainjector/antiunintelligible
name = "\improper DNA injector (Anti-Unintelligible)"
remove_mutations_static = list(UNINTELLIGIBLE)
remove_mutations = list(UNINTELLIGIBLE)
/obj/item/dnainjector/swedishmut
name = "\improper DNA injector (Swedish)"
add_mutations_static = list(SWEDISH)
add_mutations = list(SWEDISH)
/obj/item/dnainjector/antiswedish
name = "\improper DNA injector (Anti-Swedish)"
remove_mutations_static = list(SWEDISH)
remove_mutations = list(SWEDISH)
/obj/item/dnainjector/chavmut
name = "\improper DNA injector (Chav)"
add_mutations_static = list(CHAV)
add_mutations = list(CHAV)
/obj/item/dnainjector/antichav
name = "\improper DNA injector (Anti-Chav)"
remove_mutations_static = list(CHAV)
remove_mutations = list(CHAV)
/obj/item/dnainjector/elvismut
name = "\improper DNA injector (Elvis)"
add_mutations_static = list(ELVIS)
add_mutations = list(ELVIS)
/obj/item/dnainjector/antielvis
name = "\improper DNA injector (Anti-Elvis)"
remove_mutations_static = list(ELVIS)
remove_mutations = list(ELVIS)
/obj/item/dnainjector/lasereyesmut
name = "\improper DNA injector (Laser Eyes)"
add_mutations_static = list(LASEREYES)
add_mutations = list(LASEREYES)
/obj/item/dnainjector/antilasereyes
name = "\improper DNA injector (Anti-Laser Eyes)"
remove_mutations_static = list(LASEREYES)
remove_mutations = list(LASEREYES)
/obj/item/dnainjector/void
name = "\improper DNA injector (Void)"
add_mutations = list(VOID)
/obj/item/dnainjector/antivoid
name = "\improper DNA injector (Anti-Void)"
remove_mutations = list(VOID)
/obj/item/dnainjector/antenna
name = "\improper DNA injector (Antenna)"
add_mutations = list(ANTENNA)
/obj/item/dnainjector/antiantenna
name = "\improper DNA injector (Anti-Antenna)"
remove_mutations = list(ANTENNA)
/obj/item/dnainjector/paranoia
name = "\improper DNA injector (Paranoia)"
add_mutations = list(PARANOIA)
/obj/item/dnainjector/antiparanoia
name = "\improper DNA injector (Anti-Paranoia)"
remove_mutations = list(PARANOIA)
/obj/item/dnainjector/mindread
name = "\improper DNA injector (Mindread)"
add_mutations = list(MINDREAD)
/obj/item/dnainjector/antimindread
name = "\improper DNA injector (Anti-Mindread)"
remove_mutations = list(MINDREAD)
/obj/item/dnainjector/radioactive
name = "\improper DNA injector (Radioactive)"
add_mutations = list(RADIOACTIVE)
/obj/item/dnainjector/antiradioactive
name = "\improper DNA injector (Anti-Radioactive)"
remove_mutations = list(RADIOACTIVE)
/obj/item/dnainjector/olfaction
name = "\improper DNA injector (Olfaction)"
add_mutations = list(OLFACTION)
/obj/item/dnainjector/antiolfaction
name = "\improper DNA injector (Anti-Olfaction)"
remove_mutations = list(OLFACTION)
/obj/item/dnainjector/insulated
name = "\improper DNA injector (Insulated)"
add_mutations = list(INSULATED)
/obj/item/dnainjector/antiinsulated
name = "\improper DNA injector (Anti-Insulated)"
remove_mutations = list(INSULATED)
/obj/item/dnainjector/shock
name = "\improper DNA injector (Shock Touch)"
add_mutations = list(SHOCKTOUCH)
/obj/item/dnainjector/antishock
name = "\improper DNA injector (Anti-Shock Touch)"
remove_mutations = list(SHOCKTOUCH)
/obj/item/dnainjector/spacialinstability
name = "\improper DNA injector (Spacial Instability)"
add_mutations = list(BADBLINK)
/obj/item/dnainjector/antispacialinstability
name = "\improper DNA injector (Anti-Spacial Instability)"
remove_mutations = list(BADBLINK)
/obj/item/dnainjector/acidflesh
name = "\improper DNA injector (Acid Flesh)"
add_mutations = list(ACIDFLESH)
/obj/item/dnainjector/antiacidflesh
name = "\improper DNA injector (Acid Flesh)"
remove_mutations = list(ACIDFLESH)
/obj/item/dnainjector/gigantism
name = "\improper DNA injector (Gigantism)"
add_mutations = list(GIGANTISM)
/obj/item/dnainjector/antigigantism
name = "\improper DNA injector (Anti-Gigantism)"
remove_mutations = list(GIGANTISM)
/obj/item/dnainjector/spastic
name = "\improper DNA injector (Spastic)"
add_mutations = list(SPASTIC)
/obj/item/dnainjector/antispastic
name = "\improper DNA injector (Anti-Spastic)"
remove_mutations = list(SPASTIC)
/obj/item/dnainjector/geladikinesis
name = "\improper DNA injector (Geladikinesis)"
add_mutations = list(GELADIKINESIS)
/obj/item/dnainjector/antigeladikinesis
name = "\improper DNA injector (Anti-Geladikinesis)"
remove_mutations = list(GELADIKINESIS)
/obj/item/dnainjector/cryokinesis
name = "\improper DNA injector (Cryokinesis)"
add_mutations = list(CRYOKINESIS)
/obj/item/dnainjector/anticryokinesis
name = "\improper DNA injector (Anti-Cryokinesis)"
remove_mutations = list(CRYOKINESIS)
/obj/item/dnainjector/thermal
name = "\improper DNA injector (Thermal Vision)"
add_mutations = list(THERMAL)
/obj/item/dnainjector/antithermal
name = "\improper DNA injector (Anti-Thermal Vision)"
remove_mutations = list(THERMAL)
/obj/item/dnainjector/glow
name = "\improper DNA injector (Glowy)"
add_mutations = list(GLOWY)
/obj/item/dnainjector/removeglow
name = "\improper DNA injector (Anti-Glowy)"
remove_mutations = list(GLOWY)
/obj/item/dnainjector/antiglow
name = "\improper DNA injector (Antiglowy)"
add_mutations = list(ANTIGLOWY)
/obj/item/dnainjector/removeantiglow
name = "\improper DNA injector (Anti-Antiglowy)"
remove_mutations = list(ANTIGLOWY)
/obj/item/dnainjector/firebreath
name = "\improper DNA injector (Firebreath)"
add_mutations = list(FIREBREATH)
/obj/item/dnainjector/antifirebreath
name = "\improper DNA injector (Anti-Firebreath)"
remove_mutations = list(FIREBREATH)
/obj/item/dnainjector/tonguespike
name = "\improper DNA injector (Tongue Spike)"
add_mutations = list(TONGUESPIKE)
/obj/item/dnainjector/antitonguespike
name = "\improper DNA injector (Anti-Tongue Spike)"
remove_mutations = list(TONGUESPIKE)
/obj/item/dnainjector/spiderweb
name = "\improper DNA injector (Spider Web)"
add_mutations = list(SPIDER_WEB)
/obj/item/dnainjector/antispiderweb
name = "\improper DNA injector (Anti-Spider Web)"
remove_mutations = list(SPIDER_WEB)
/obj/item/dnainjector/timed
var/duration = 600
/obj/item/dnainjector/timed/inject(mob/living/carbon/M, mob/user)
prepare()
if(M.stat == DEAD) //prevents dead people from having their DNA changed
to_chat(user, "<span class='notice'>You can't modify [M]'s DNA while [M.p_theyre()] dead.</span>")
return FALSE
@@ -317,23 +467,22 @@
M.radiation += rand(20/(damage_coeff ** 2),50/(damage_coeff ** 2))
var/log_msg = "[key_name(user)] injected [key_name(M)] with the [name]"
var/endtime = world.time+duration
for(var/datum/mutation/human/HM in remove_mutations)
if(HM.name == RACEMUT)
for(var/mutation in remove_mutations)
if(mutation == RACEMUT)
if(ishuman(M))
continue
M = HM.force_lose(M)
M = M.dna.remove_mutation(mutation)
else
HM.force_lose(M)
for(var/datum/mutation/human/HM in add_mutations)
if((HM in M.dna.mutations) && !(M.dna.temporary_mutations[HM.name]))
M.dna.remove_mutation(mutation)
for(var/mutation in add_mutations)
if(M.dna.get_mutation(mutation))
continue //Skip permanent mutations we already have.
if(HM.name == RACEMUT && ishuman(M))
if(mutation == RACEMUT && ishuman(M))
message_admins("[ADMIN_LOOKUPFLW(user)] injected [key_name_admin(M)] with the [name] <span class='danger'>(MONKEY)</span>")
log_msg += " (MONKEY)"
M = HM.force_give(M)
M = M.dna.add_mutation(mutation, MUT_OTHER, endtime)
else
HM.force_give(M)
M.dna.temporary_mutations[HM.name] = endtime
M.dna.add_mutation(mutation, MUT_OTHER, endtime)
if(fields)
if(fields["name"] && fields["UE"] && fields["blood_type"])
if(!M.dna.previous["name"])
@@ -361,9 +510,41 @@
/obj/item/dnainjector/timed/hulk
name = "\improper DNA injector (Hulk)"
desc = "This will make you big and strong, but give you a bad skin condition."
add_mutations_static = list(HULK)
add_mutations = list(HULK)
/obj/item/dnainjector/timed/h2m
name = "\improper DNA injector (Human > Monkey)"
desc = "Will make you a flea bag."
add_mutations_static = list(RACEMUT)
add_mutations = list(RACEMUT)
/obj/item/dnainjector/activator
name = "\improper DNA activator"
desc = "Activates the current mutation on injection, if the subject has it."
var/doitanyway = FALSE
var/research = FALSE //Set to true to get expended and filled injectors for chromosomes
var/filled = FALSE
/obj/item/dnainjector/activator/inject(mob/living/carbon/M, mob/user)
if(M.has_dna() && !HAS_TRAIT_NOT_FROM(M, TRAIT_RADIMMUNE,BLOODSUCKER_TRAIT) && !HAS_TRAIT(M,TRAIT_NOCLONE))
M.radiation += rand(20/(damage_coeff ** 2),50/(damage_coeff ** 2))
var/log_msg = "[key_name(user)] injected [key_name(M)] with the [name]"
for(var/mutation in add_mutations)
var/datum/mutation/human/HM = mutation
if(istype(HM, /datum/mutation/human))
mutation = HM.type
if(!M.dna.activate_mutation(HM))
if(!doitanyway)
log_msg += "(FAILED)"
else
M.dna.add_mutation(HM, MUT_EXTRA)
name = "expended [name]"
else if(research && M.client)
filled = TRUE
name = "filled [name]"
else
name = "expended [name]"
log_msg += "([mutation])"
log_attack("[log_msg] [loc_name(user)]")
return TRUE
return FALSE
+5 -4
View File
@@ -11,7 +11,7 @@
/obj/item/book/granter/proc/turn_page(mob/user)
playsound(user, pick('sound/effects/pageturn1.ogg','sound/effects/pageturn2.ogg','sound/effects/pageturn3.ogg'), 30, 1)
if(do_after(user,50, user))
if(do_after(user,50, TRUE, user))
if(remarks.len)
to_chat(user, "<span class='notice'>[pick(remarks)]</span>")
else
@@ -53,7 +53,7 @@
on_reading_stopped()
reading = FALSE
return
if(do_after(user,50, user))
if(do_after(user,50, TRUE, user))
on_reading_finished(user)
reading = FALSE
return TRUE
@@ -402,10 +402,11 @@
martialname = "sleeping carp"
desc = "A scroll filled with strange markings. It seems to be drawings of some sort of martial art."
greet = "<span class='sciradio'>You have learned the ancient martial art of the Sleeping Carp! Your hand-to-hand combat has become much more effective, and you are now able to deflect any projectiles \
directed toward you. However, you are also unable to use any ranged weaponry. You can learn more about your newfound art by using the Recall Teachings verb in the Sleeping Carp tab.</span>"
directed toward you while in Throw Mode. Your body is also honed to protect you from damage and punctures, and even briefly survive space. \
However, you are also unable to use any ranged weaponry, and some medical supplies will prove useless to you. You can learn more about your newfound art by using the Recall Teachings verb in the Sleeping Carp tab.</span>"
icon = 'icons/obj/wizard.dmi'
icon_state = "scroll2"
remarks = list("I must prove myself worthy to the masters of the sleeping carp...", "Stance means everything...", "Focus... And you'll be able to incapacitate any foe in seconds...", "I must pierce armor for maximum damage...", "I don't think this would combine with other martial arts...", "Grab them first so they don't retaliate...", "I must prove myself worthy of this power...")
remarks = list("Wait, a high protein diet is really all it takes to become bulletproof...?", "Overwhelming force, immovable object...", "Focus... And you'll be able to incapacitate any foe in seconds...", "I must pierce armor for maximum damage...", "I don't think this would combine with other martial arts...", "Become one with the carp...", "Glub...")
/obj/item/book/granter/martial/carp/onlearned(mob/living/carbon/user)
..()
+12
View File
@@ -463,6 +463,16 @@
hitsound = 'sound/weapons/rapierhit.ogg'
var/possessed = FALSE
/obj/item/nullrod/scythe/talking/process()
for(var/mob/living/simple_animal/shade/S in contents)
if(S.mind)
return
else
qdel(S)
possessed = FALSE
visible_message("<span class='warning'>The blade makes a short sigh. The spirit within seems to have passed on...</span>")
return PROCESS_KILL
/obj/item/nullrod/scythe/talking/relaymove(mob/user)
return //stops buckled message spam for the ghost.
@@ -484,6 +494,8 @@
S.ckey = C.ckey
S.status_flags |= GODMODE
S.language_holder = user.language_holder.copy(S)
S.AddElement(/datum/element/ghost_role_eligibility)
START_PROCESSING(SSprocessing,src)
var/input = stripped_input(S,"What are you named?", ,"", MAX_NAME_LEN)
if(src && input)
+36 -8
View File
@@ -143,33 +143,61 @@
/obj/item/melee/rapier
name = "plastitanium rapier"
desc = "A impossibly thin blade made of plastitanium with a tip made of diamond. It looks to be able to cut through any armor."
desc = "A thin blade made of plastitanium with a diamond tip. It appears to be coated in a persistent layer of an unknown substance."
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "rapier"
item_state = "rapier"
lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi'
force = 25
throwforce = 35
block_chance = 0
armour_penetration = 100
force = 15
throwforce = 25
block_chance = 50
armour_penetration = 200 //Apparently this gives it the ability to pierce block
flags_1 = CONDUCT_1
obj_flags = UNIQUE_RENAME
w_class = WEIGHT_CLASS_BULKY
sharpness = IS_SHARP_ACCURATE //It cant be sharpend cook -_-
attack_verb = list("slashed", "cut", "pierces", "pokes")
total_mass = 3.4
attack_verb = list("stabs", "punctures", "pierces", "pokes")
hitsound = 'sound/weapons/rapierhit.ogg'
total_mass = 0.4
/obj/item/melee/rapier/Initialize()
. = ..()
AddComponent(/datum/component/butchering, 20, 65, 0)
/obj/item/melee/rapier/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
if(attack_type == PROJECTILE_ATTACK)
final_block_chance = 0
return ..()
/obj/item/melee/rapier/on_exit_storage(datum/component/storage/S)
var/obj/item/storage/belt/sabre/rapier/B = S.parent
if(istype(B))
playsound(B, 'sound/items/unsheath.ogg', 25, 1)
..()
/obj/item/melee/rapier/on_enter_storage(datum/component/storage/S)
var/obj/item/storage/belt/sabre/rapier/B = S.parent
if(istype(B))
playsound(B, 'sound/items/sheath.ogg', 25, 1)
..()
/obj/item/melee/rapier/get_belt_overlay()
return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "rapier")
/obj/item/melee/rapier/get_worn_belt_overlay(icon_file)
return mutable_appearance(icon_file, "-rapier")
/obj/item/melee/rapier/attack(mob/living/target, mob/living/user)
. = ..()
if(iscarbon(target))
var/mob/living/carbon/H = target
var/loss = H.getStaminaLoss()
H.Dizzy(10)
H.adjustStaminaLoss(30)
if((loss > 40) && prob(loss)) // if above 40, roll for sleep using 1% every 1 stamina damage
H.Sleeping(180)
/obj/item/melee/classic_baton
name = "police baton"
desc = "A wooden truncheon for beating criminal scum."
@@ -240,7 +268,7 @@
if(!on)
return ..()
if(user.getStaminaLoss() >= STAMINA_SOFTCRIT)//CIT CHANGE - makes batons unusuable in stamina softcrit
if(IS_STAMCRIT(user))//CIT CHANGE - makes batons unusuable in stamina softcrit
to_chat(user, "<span class='warning'>You're too exhausted for that.</span>")//CIT CHANGE - ditto
return //CIT CHANGE - ditto
+19 -4
View File
@@ -58,6 +58,21 @@
new /obj/effect/abstract/DPtarget(get_turf(src), pod)
/obj/item/choice_beacon/ingredients
name = "ingredient box delivery beacon"
desc = "Summon a box of ingredients from a wide selection!"
icon_state = "gangtool-red"
/obj/item/choice_beacon/ingredients/generate_display_names()
var/static/list/ingredientboxes
if(!ingredientboxes)
ingredientboxes = list()
var/list/templist = typesof(/obj/item/storage/box/ingredients)
for(var/V in templist)
var/obj/item/storage/box/ingredients/A = V
ingredientboxes[initial(A.theme_name)] = A
return ingredientboxes
/obj/item/choice_beacon/hero
name = "heroic beacon"
desc = "To summon heroes from the past to protect the future."
@@ -72,14 +87,13 @@
hero_item_list[initial(A.name)] = A
return hero_item_list
/obj/item/storage/box/hero
name = "Courageous Tomb Raider - 1940's."
/obj/item/storage/box/hero/PopulateContents()
new /obj/item/clothing/head/fedora/curator(src)
new /obj/item/clothing/suit/curator(src)
new /obj/item/clothing/under/rank/curator/treasure_hunter(src)
new /obj/item/clothing/under/rank/civilian/curator/treasure_hunter(src)
new /obj/item/clothing/shoes/workboots/mining(src)
new /obj/item/melee/curator_whip(src)
@@ -96,7 +110,7 @@
name = "Braveheart, the Scottish rebel - 1300's."
/obj/item/storage/box/hero/scottish/PopulateContents()
new /obj/item/clothing/under/kilt(src)
new /obj/item/clothing/under/costume/kilt(src)
new /obj/item/claymore/weak/ceremonial(src)
new /obj/item/toy/crayon/spraycan(src)
new /obj/item/clothing/shoes/sandal(src)
@@ -115,4 +129,5 @@
icon = 'icons/obj/supermatter.dmi'
icon_state = "supermatterspray"
w_class = WEIGHT_CLASS_SMALL
var/usesleft = 2
var/usesleft = 2
+1 -1
View File
@@ -42,7 +42,7 @@
var/mob/living/L = user
if(istype(L) && L.getStaminaLoss() >= STAMINA_SOFTCRIT)
if(istype(L) && IS_STAMCRIT(L))
to_chat(user, "<span class='danger'>You're too exhausted for that.</span>")
return
+4 -4
View File
@@ -80,7 +80,7 @@
else
user.visible_message("<span class='notice'>[user] hugs [M] to make [M.p_them()] feel better!</span>", \
"<span class='notice'>You hug [M] to make [M.p_them()] feel better!</span>")
if(M.resting && !M.recoveringstam)
if(M.resting && !(M.combat_flags & COMBAT_FLAG_HARD_STAMCRIT))
M.set_resting(FALSE, TRUE)
else
user.visible_message("<span class='notice'>[user] pets [M]!</span>", \
@@ -99,7 +99,7 @@
else
user.visible_message("<span class='warning'>[user] hugs [M] in a firm bear-hug! [M] looks uncomfortable...</span>", \
"<span class='warning'>You hug [M] firmly to make [M.p_them()] feel better! [M] looks uncomfortable...</span>")
if(!CHECK_MOBILITY(M, MOBILITY_STAND) && !M.recoveringstam)
if(!CHECK_MOBILITY(M, MOBILITY_STAND) && !(M.combat_flags & COMBAT_FLAG_HARD_STAMCRIT))
M.set_resting(FALSE, TRUE)
else
user.visible_message("<span class='warning'>[user] bops [M] on the head!</span>", \
@@ -357,7 +357,7 @@
/obj/item/borg/lollipop/equipped()
check_amount()
/obj/item/borg/lollipop/dropped()
/obj/item/borg/lollipop/dropped(mob/user)
check_amount()
/obj/item/borg/lollipop/proc/check_amount() //Doesn't even use processing ticks.
@@ -620,7 +620,7 @@
return host.loc
return null
/obj/item/borg/projectile_dampen/dropped()
/obj/item/borg/projectile_dampen/dropped(mob/user)
. = ..()
host = loc
@@ -173,37 +173,6 @@
R.module.basic_modules += S
R.module.add_module(S, FALSE, TRUE)
/obj/item/borg/upgrade/premiumka
name = "mining cyborg premium KA"
desc = "A premium kinetic accelerator replacement for the mining module's standard kinetic accelerator."
icon_state = "cyborg_upgrade3"
require_module = 1
module_type = list(/obj/item/robot_module/miner)
/obj/item/borg/upgrade/premiumka/action(mob/living/silicon/robot/R, user = usr)
. = ..()
if(.)
for(var/obj/item/gun/energy/kinetic_accelerator/cyborg/KA in R.module)
for(var/obj/item/borg/upgrade/modkit/M in KA.modkits)
M.uninstall(src)
R.module.remove_module(KA, TRUE)
var/obj/item/gun/energy/kinetic_accelerator/premiumka/cyborg/PKA = new /obj/item/gun/energy/kinetic_accelerator/premiumka/cyborg(R.module)
R.module.basic_modules += PKA
R.module.add_module(PKA, FALSE, TRUE)
/obj/item/borg/upgrade/premiumka/deactivate(mob/living/silicon/robot/R, user = usr)
. = ..()
if (.)
for(var/obj/item/gun/energy/kinetic_accelerator/premiumka/cyborg/PKA in R.module)
for(var/obj/item/borg/upgrade/modkit/M in PKA.modkits)
M.uninstall(src)
R.module.remove_module(PKA, TRUE)
var/obj/item/gun/energy/kinetic_accelerator/cyborg/KA = new (R.module)
R.module.basic_modules += KA
R.module.add_module(KA, FALSE, TRUE)
/obj/item/borg/upgrade/advcutter
name = "mining cyborg advanced plasma cutter"
@@ -462,7 +431,7 @@
desc = "An upgrade to the Medical module's hypospray, containing \
stronger versions of existing chemicals."
additional_reagents = list(/datum/reagent/medicine/oxandrolone, /datum/reagent/medicine/sal_acid,
/datum/reagent/medicine/rezadone, /datum/reagent/medicine/pen_acid)
/datum/reagent/medicine/rezadone, /datum/reagent/medicine/pen_acid, /datum/reagent/medicine/prussian_blue)
/obj/item/borg/upgrade/piercing_hypospray
name = "cyborg piercing hypospray"
@@ -35,7 +35,7 @@ GLOBAL_LIST_INIT(human_recipes, list( \
GLOBAL_LIST_INIT(gondola_recipes, list ( \
new/datum/stack_recipe("gondola mask", /obj/item/clothing/mask/gondola, 1), \
new/datum/stack_recipe("gondola suit", /obj/item/clothing/under/gondola, 2), \
new/datum/stack_recipe("gondola suit", /obj/item/clothing/under/costume/gondola, 2), \
new/datum/stack_recipe("gondola bedsheet", /obj/item/bedsheet/gondola, 1), \
))
@@ -120,6 +120,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
)), \
null, \
new/datum/stack_recipe("iron door", /obj/structure/mineral_door/iron, 20, one_per_turf = TRUE, on_floor = TRUE), \
new/datum/stack_recipe("pestle", /obj/item/pestle, 1, time = 50), \
new/datum/stack_recipe("floodlight frame", /obj/structure/floodlight_frame, 5, one_per_turf = TRUE, on_floor = TRUE), \
))
@@ -136,6 +137,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
merge_type = /obj/item/stack/sheet/metal
grind_results = list(/datum/reagent/iron = 20)
point_value = 2
tableVariant = /obj/structure/table
material_type = /datum/material/iron
/obj/item/stack/sheet/metal/ratvar_act()
@@ -254,6 +256,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
new/datum/stack_recipe("apiary", /obj/structure/beebox, 40, time = 50),\
null, \
new/datum/stack_recipe("picture frame", /obj/item/wallframe/picture, 1, time = 10),\
new/datum/stack_recipe("mortar", /obj/item/reagent_containers/glass/mortar, 3), \
new/datum/stack_recipe("honey frame", /obj/item/honey_frame, 5, time = 10),\
))
@@ -426,7 +429,7 @@ GLOBAL_LIST_INIT(cloth_recipes, list ( \
* Durathread
*/
GLOBAL_LIST_INIT(durathread_recipes, list ( \
new/datum/stack_recipe("durathread jumpsuit", /obj/item/clothing/under/durathread, 4, time = 40),
new/datum/stack_recipe("durathread jumpsuit", /obj/item/clothing/under/misc/durathread, 4, time = 40),
new/datum/stack_recipe("durathread beret", /obj/item/clothing/head/beret/durathread, 2, time = 40), \
new/datum/stack_recipe("durathread beanie", /obj/item/clothing/head/beanie/durathread, 2, time = 40), \
new/datum/stack_recipe("durathread bandana", /obj/item/clothing/mask/bandana/durathread, 1, time = 25), \
+2 -1
View File
@@ -219,8 +219,9 @@
O = new R.result_type(usr.drop_location())
if(O)
O.setDir(usr.dir)
log_craft("[O] crafted by [usr] at [loc_name(O.loc)]")
use(R.req_amount * multiplier)
log_craft("[O] crafted by [usr] at [loc_name(O.loc)]")
if(R.applies_mats && custom_materials && custom_materials.len)
var/list/used_materials = list()
+1 -1
View File
@@ -66,7 +66,7 @@
return
if(!istype(target))
return
if(target.anchored)
if(target.anchored || (user in target))
return
if(isitem(target))
+8 -3
View File
@@ -54,7 +54,12 @@
icon_state = "holdingsat"
item_state = "holdingsat"
species_exception = list(/datum/species/angel)
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
/obj/item/storage/backpack/holding/duffel
name = "duffel bag of holding"
desc = "A duffel bag that opens into a localized pocket of Blue Space."
icon_state = "holdingduffel"
item_state = "holdingduffel"
/obj/item/storage/backpack/holding/ComponentInitialize()
. = ..()
@@ -453,7 +458,7 @@
item_state = "duffel-syndieammo"
/obj/item/storage/backpack/duffelbag/syndie/hitman/PopulateContents()
new /obj/item/clothing/under/lawyer/blacksuit(src)
new /obj/item/clothing/under/suit/black(src)
new /obj/item/clothing/accessory/waistcoat(src)
new /obj/item/clothing/suit/toggle/lawyer/black(src)
new /obj/item/clothing/shoes/laceup(src)
@@ -625,7 +630,7 @@
/obj/item/storage/backpack/duffelbag/clown/syndie/PopulateContents()
new /obj/item/pda/clown(src)
new /obj/item/clothing/under/rank/clown(src)
new /obj/item/clothing/under/rank/civilian/clown(src)
new /obj/item/clothing/shoes/clown_shoes(src)
new /obj/item/clothing/mask/gas/clown_hat(src)
new /obj/item/bikehorn(src)
+1 -1
View File
@@ -132,7 +132,7 @@
RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/Pickup_ores)
listeningTo = user
/obj/item/storage/bag/ore/dropped()
/obj/item/storage/bag/ore/dropped(mob/user)
. = ..()
if(listeningTo)
UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED)
+1 -7
View File
@@ -795,18 +795,12 @@
/obj/item/storage/belt/sabre/rapier
name = "rapier sheath"
desc = "A black, thin sheath that looks to house only a long thin blade. Feels like its made of metal."
desc = "A sinister, thin sheath, suitable for a rapier."
icon_state = "rsheath"
item_state = "rsheath"
force = 5
throwforce = 15
block_chance = 30
w_class = WEIGHT_CLASS_BULKY
attack_verb = list("bashed", "slashes", "prods", "pokes")
fitting_swords = list(/obj/item/melee/rapier)
starting_sword = /obj/item/melee/rapier
/obj/item/storage/belt/sabre/rapier/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
if(attack_type == PROJECTILE_ATTACK)
final_block_chance = 0 //To thin to block bullets
return ..()
+45 -1
View File
@@ -946,12 +946,47 @@
/obj/item/reagent_containers/food/snacks/grown/apple,
/obj/item/reagent_containers/food/snacks/chocolatebar,
/obj/item/reagent_containers/food/snacks/grown/cherries,
/obj/item/reagent_containers/food/snacks/grown/berries,
/obj/item/reagent_containers/food/snacks/grown/banana,
/obj/item/reagent_containers/food/snacks/grown/cabbage,
/obj/item/reagent_containers/food/snacks/grown/soybeans,
/obj/item/reagent_containers/food/snacks/grown/corn,
/obj/item/reagent_containers/food/snacks/grown/mushroom/plumphelmet,
/obj/item/reagent_containers/food/snacks/grown/mushroom/chanterelle)
/obj/item/reagent_containers/food/snacks/grown/mushroom/chanterelle,
/obj/item/reagent_containers/food/snacks/faggot,
/obj/item/reagent_containers/food/snacks/grown/citrus/orange,
/obj/item/reagent_containers/food/snacks/grown/citrus/lemon,
/obj/item/reagent_containers/food/snacks/grown/citrus/lime,
/obj/item/reagent_containers/food/snacks/grown/bluecherries,
/obj/item/reagent_containers/food/snacks/grown/cocoapod,
/obj/item/reagent_containers/food/snacks/grown/vanillapod,
/obj/item/reagent_containers/food/snacks/grown/grapes,
/obj/item/reagent_containers/food/snacks/grown/strawberry,
/obj/item/reagent_containers/food/snacks/grown/whitebeet,
/obj/item/reagent_containers/food/snacks/meat/slab/bear,
/obj/item/reagent_containers/food/snacks/meat/slab/spider,
/obj/item/reagent_containers/food/snacks/spidereggs,
/obj/item/reagent_containers/food/snacks/carpmeat,
/obj/item/reagent_containers/food/snacks/meat/slab/xeno,
/obj/item/reagent_containers/food/snacks/meat/slab/corgi,
/obj/item/reagent_containers/food/snacks/grown/oat,
/obj/item/reagent_containers/food/snacks/grown/wheat,
/obj/item/reagent_containers/honeycomb,
/obj/item/reagent_containers/food/snacks/grown/watermelon,
/obj/item/reagent_containers/food/snacks/grown/onion,
/obj/item/reagent_containers/food/snacks/grown/peach,
/obj/item/reagent_containers/food/snacks/grown/peanut,
/obj/item/reagent_containers/food/snacks/grown/pineapple,
/obj/item/reagent_containers/food/snacks/grown/pumpkin,
/obj/item/reagent_containers/food/snacks/meat/rawcrab,
/obj/item/reagent_containers/food/snacks/meat/slab/goliath,
/obj/item/reagent_containers/food/snacks/meat/slab/chicken,
/obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime,
/obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/golem,
/obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/lizard,
/obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton,
/obj/item/reagent_containers/food/snacks/egg,
/obj/item/reagent_containers/food/snacks/grown/eggplant)
new randomFood(src)
/obj/item/storage/box/ingredients/fiesta
@@ -1061,6 +1096,15 @@
new /obj/item/reagent_containers/food/snacks/grown/cabbage(src)
new /obj/item/reagent_containers/food/snacks/grown/chili(src)
/obj/item/storage/box/ingredients/sushi
theme_name = "sushi"
/obj/item/storage/box/ingredients/sushi/PopulateContents()
for(var/i in 1 to 3)
new /obj/item/reagent_containers/food/snacks/sea_weed(src)
new /obj/item/reagent_containers/food/snacks/carpmeat(src)
new /obj/item/reagent_containers/food/snacks/meat/rawcrab(src)
/obj/item/storage/box/emptysandbags
name = "box of empty sandbags"
+1 -1
View File
@@ -99,7 +99,7 @@
new /obj/item/ammo_box/magazine/m10mm(src)
new /obj/item/ammo_box/magazine/m10mm/soporific(src)
new /obj/item/ammo_box/c10mm/soporific(src)
new /obj/item/clothing/under/lawyer/blacksuit(src)
new /obj/item/clothing/under/suit/black(src)
new /obj/item/clothing/accessory/waistcoat(src)
new /obj/item/clothing/suit/toggle/lawyer/black/syndie(src)
+2 -10
View File
@@ -189,7 +189,7 @@
new /obj/item/reagent_containers/medspray/silver_sulf(src)
new /obj/item/healthanalyzer/advanced(src)
new /obj/item/reagent_containers/syringe/lethal/choral(src) // what the fuck does anyone use this piece of shit for
new /obj/item/clothing/glasses/hud/health/night(src)
new /obj/item/clothing/glasses/hud/health/night/syndicate(src)
/obj/item/storage/firstaid/tactical/nukeop
name = "improved combat medical kit"
@@ -204,7 +204,7 @@
new /obj/item/reagent_containers/medspray/silver_sulf(src)
new /obj/item/healthanalyzer/advanced(src)
new /obj/item/reagent_containers/syringe/lethal/choral(src) // what the fuck does anyone use this piece of shit for
new /obj/item/clothing/glasses/hud/health/night(src)
new /obj/item/clothing/glasses/hud/health/night/syndicate(src)
/*
* Pill Bottles
@@ -525,14 +525,6 @@
desc = "A kit containing a Deluxe hypospray and Vials."
icon_state = "tactical-mini"
/obj/item/storage/hypospraykit/cmo/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.max_items = 6
STR.can_hold = typecacheof(list(
/obj/item/hypospray/mkii,
/obj/item/reagent_containers/glass/bottle/vial))
/obj/item/storage/hypospraykit/cmo/PopulateContents()
if(empty)
return
+38 -1
View File
@@ -177,7 +177,8 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
STR.max_items = 28
/obj/item/storage/toolbox/brass/prefilled/PopulateContents()
new fabricator_type(src)
if(fabricator_type)
new fabricator_type(src)
new /obj/item/screwdriver/brass(src)
new /obj/item/wirecutters/brass(src)
new /obj/item/wrench/brass(src)
@@ -259,6 +260,42 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons)
new /obj/item/ammo_box/a762(src)
new /obj/item/ammo_box/a762(src)
/obj/item/storage/toolbox/infiltrator
name = "insidious case"
desc = "Bearing the emblem of the Syndicate, this case contains a full infiltrator stealth suit, and has enough room to fit weaponry if necessary while being quite the heavy bludgeoning implement when in a pinch."
icon_state = "infiltrator_case"
item_state = "infiltrator_case"
force = 12
throwforce = 16
w_class = WEIGHT_CLASS_NORMAL
has_latches = FALSE
/obj/item/storage/toolbox/infiltrator/ComponentInitialize()
. = ..()
var/datum/component/storage/STR = GetComponent(/datum/component/storage)
STR.silent = TRUE
STR.max_items = 10
STR.max_w_class = WEIGHT_CLASS_NORMAL
STR.can_hold = typecacheof(list(
/obj/item/clothing/head/helmet/infiltrator,
/obj/item/clothing/suit/armor/vest/infiltrator,
/obj/item/clothing/under/syndicate/bloodred,
/obj/item/clothing/gloves/color/latex/nitrile/infiltrator,
/obj/item/clothing/mask/infiltrator,
/obj/item/clothing/shoes/combat/sneakboots,
/obj/item/gun/ballistic/automatic/pistol,
/obj/item/gun/ballistic/revolver,
/obj/item/ammo_box
))
/obj/item/storage/toolbox/infiltrator/PopulateContents()
new /obj/item/clothing/head/helmet/infiltrator(src)
new /obj/item/clothing/suit/armor/vest/infiltrator(src)
new /obj/item/clothing/under/syndicate/bloodred(src)
new /obj/item/clothing/gloves/color/latex/nitrile/infiltrator(src)
new /obj/item/clothing/mask/infiltrator(src)
new /obj/item/clothing/shoes/combat/sneakboots(src)
/obj/item/storage/toolbox/plastitanium/gold_real
name = "golden toolbox"
desc = "A larger then normal toolbox made of gold plated plastitanium."
+11 -6
View File
@@ -49,7 +49,7 @@
new /obj/item/grenade/plastic/c4(src)
new /obj/item/clothing/gloves/color/latex/nitrile(src)
new /obj/item/clothing/mask/gas/clown_hat(src)
new /obj/item/clothing/under/suit_jacket/really_black(src)
new /obj/item/clothing/under/suit/black_really(src)
new /obj/item/screwdriver/power(src) //2 tc item
if("murder") // 35 tc
@@ -130,7 +130,7 @@
new /obj/item/clothing/glasses/thermal/syndi(src)
new /obj/item/clothing/gloves/color/latex/nitrile(src)
new /obj/item/clothing/mask/gas/clown_hat(src)
new /obj/item/clothing/under/suit_jacket/really_black(src)
new /obj/item/clothing/under/suit/black_really(src)
if("metaops") // 30 tc
new /obj/item/clothing/suit/space/hardsuit/syndi(src) // 8 tc
@@ -343,7 +343,7 @@
new /obj/item/implanter/radio/syndicate(src)
/obj/item/storage/box/syndie_kit/centcom_costume/PopulateContents()
new /obj/item/clothing/under/rank/centcom_officer/syndicate(src)
new /obj/item/clothing/under/rank/centcom/officer/syndicate(src)
new /obj/item/clothing/shoes/sneakers/black(src)
new /obj/item/clothing/gloves/color/black(src)
new /obj/item/radio/headset/headset_cent/empty(src)
@@ -374,6 +374,12 @@
for(var/i in 1 to 3)
new /obj/item/grenade/spawnergrenade/buzzkill(src)
/obj/item/storage/box/syndie_kit/sleepytime/PopulateContents()
new /obj/item/clothing/under/syndicate/bloodred/sleepytime(src)
new /obj/item/reagent_containers/food/drinks/mug/coco(src)
new /obj/item/toy/plush/carpplushie(src)
new /obj/item/bedsheet/syndie(src)
/obj/item/storage/box/syndie_kit/kitchen_gun
name = "Kitchen Gun (TM) package"
@@ -475,13 +481,12 @@
/obj/item/storage/backpack/duffelbag/syndie/surgery,
/obj/item/encryptionkey/syndicate,
/obj/item/clothing/glasses/thermal/syndi,
/obj/item/slimepotion/slime/sentience/nuclear,
/obj/item/storage/box/syndie_kit/imp_radio,
/obj/item/storage/box/syndie_kit/imp_uplink,
/obj/item/clothing/gloves/krav_maga/combatglovesplus,
/obj/item/gun/ballistic/automatic/c20r/toy/unrestricted/riot,
/obj/item/reagent_containers/syringe/stimulants,
/obj/item/storage/box/syndie_kit/imp_freedom
/obj/item/storage/box/syndie_kit/imp_freedom,
/obj/item/storage/toolbox/infiltrator
)
var/obj/item1 = pick_n_take(item_list)
var/obj/item2 = pick_n_take(item_list)
+2 -5
View File
@@ -25,7 +25,7 @@
/obj/item/melee/baton/examine(mob/user)
. = ..()
. += "<span class='notice'>Right click attack while in combat mode or attack while in disarm intent to disarm instead of stun.</span>"
. += "<span class='notice'>Right click attack while in combat mode to disarm instead of stun.</span>"
/obj/item/melee/baton/get_cell()
. = cell
@@ -149,13 +149,11 @@
//return TRUE to interrupt attack chain.
/obj/item/melee/baton/proc/common_baton_melee(mob/M, mob/living/user, disarming = FALSE)
if(user.a_intent == INTENT_DISARM)
disarming = TRUE //override if they're in disarm intent.
if(iscyborg(M) || !isliving(M)) //can't baton cyborgs
return FALSE
if(status && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
clowning_around(user)
if(user.getStaminaLoss() >= STAMINA_SOFTCRIT) //CIT CHANGE - makes it impossible to baton in stamina softcrit
if(IS_STAMCRIT(user)) //CIT CHANGE - makes it impossible to baton in stamina softcrit
to_chat(user, "<span class='danger'>You're too exhausted for that.</span>")
return TRUE
if(ishuman(M))
@@ -284,7 +282,6 @@
throwforce = 5
stamforce = 25
hitcost = 1000
knockdown = FALSE
throw_hit_chance = 10
slot_flags = ITEM_SLOT_BACK
var/obj/item/assembly/igniter/sparkler
+12 -12
View File
@@ -58,7 +58,7 @@
var/obj/item/twohanded/offhand/O = user.get_inactive_held_item()
if(O && istype(O))
O.unwield()
slowdown -= slowdown_wielded
set_slowdown(slowdown - slowdown_wielded)
/obj/item/twohanded/proc/wield(mob/living/carbon/user)
if(wielded)
@@ -88,7 +88,7 @@
O.desc = "Your second grip on [src]."
O.wielded = TRUE
user.put_in_inactive_hand(O)
slowdown += slowdown_wielded
set_slowdown(slowdown + slowdown_wielded)
/obj/item/twohanded/dropped(mob/user)
. = ..()
@@ -246,11 +246,11 @@
user.visible_message("<span class='suicide'>[user] axes [user.p_them()]self from head to toe! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return (BRUTELOSS)
/obj/item/twohanded/fireaxe/afterattack(atom/A, mob/user, proximity)
/obj/item/twohanded/fireaxe/afterattack(atom/A, mob/living/user, proximity)
. = ..()
if(!proximity)
if(!proximity || IS_STAMCRIT(user)) //don't make stamcrit message they'll already have gotten one from the primary attack.
return
if(wielded) //destroys windows and grilles in one hit
if(wielded) //destroys windows and grilles in one hit (or more if it has a ton of health like plasmaglass)
if(istype(A, /obj/structure/window))
var/obj/structure/window/W = A
W.take_damage(200, BRUTE, "melee", 0)
@@ -1012,7 +1012,7 @@
/obj/item/twohanded/electrostaff
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "electrostaff_3"
icon_state = "electrostaff"
item_state = "electrostaff"
lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi'
@@ -1116,10 +1116,10 @@
/obj/item/twohanded/electrostaff/update_icon_state()
. = ..()
if(!wielded)
icon_state = "electrostaff_3"
icon_state = "electrostaff"
item_state = "electrostaff"
else
icon_state = item_state = (on? "electrostaff_1" : "electrostaff_3")
icon_state = item_state = (on? "electrostaff_1" : "electrostaff_0")
set_light(7, on? 1 : 0, LIGHT_COLOR_CYAN)
/obj/item/twohanded/electrostaff/examine(mob/living/user)
@@ -1171,7 +1171,7 @@
turn_off()
/obj/item/twohanded/electrostaff/attack(mob/living/target, mob/living/user)
if(user.getStaminaLoss() >= STAMINA_SOFTCRIT)//CIT CHANGE - makes it impossible to baton in stamina softcrit
if(IS_STAMCRIT(user))//CIT CHANGE - makes it impossible to baton in stamina softcrit
to_chat(user, "<span class='danger'>You're too exhausted for that.</span>")//CIT CHANGE - ditto
return //CIT CHANGE - ditto
if(on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
@@ -1217,7 +1217,7 @@
target.lastattackerckey = user.ckey
target.visible_message("<span class='danger'>[user] has shocked [target] with [src]!</span>", \
"<span class='userdanger'>[user] has shocked you with [src]!</span>")
log_combat(user, user, "stunned with an electrostaff")
log_combat(user, target, "stunned with an electrostaff")
playsound(src, 'sound/weapons/staff.ogg', 50, 1, -1)
target.apply_status_effect(stun_status_effect, stun_status_duration)
if(ishuman(user))
@@ -1242,9 +1242,9 @@
if(user)
target.lastattacker = user.real_name
target.lastattackerckey = user.ckey
target.visible_message("<span class='danger'>[user] has seared [user] with [src]!</span>", \
target.visible_message("<span class='danger'>[user] has seared [target] with [src]!</span>", \
"<span class='userdanger'>[user] has seared you with [src]!</span>")
log_combat(user, user, "burned with an electrostaff")
log_combat(user, target, "burned with an electrostaff")
playsound(src, 'sound/weapons/sear.ogg', 50, 1, -1)
return TRUE
+4 -8
View File
@@ -127,11 +127,10 @@
if ((M.client && M.machine == src))
is_in_use = TRUE
ui_interact(M)
if(isAI(usr) || iscyborg(usr) || IsAdminGhost(usr) || hasSiliconAccessInArea(usr))
if (!(usr in nearby))
if (usr.client && usr.machine==src) // && M.machine == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh.
is_in_use = TRUE
ui_interact(usr)
if(usr && hasSiliconAccessInArea(usr) && !(usr in nearby))
if (usr.client && usr.machine==src) // && M.machine == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh.
is_in_use = TRUE
ui_interact(usr)
// check for TK users
@@ -212,9 +211,6 @@
/obj/proc/check_uplink_validity()
return 1
/obj/proc/intercept_user_move(dir, mob, newLoc, oldLoc)
return
/obj/vv_get_dropdown()
. = ..()
.["Delete all of type"] = "?_src_=vars;[HrefToken()];delall=[REF(src)]"
@@ -101,7 +101,7 @@
if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
return TRUE
if(user.getStaminaLoss() >= STAMINA_SOFTCRIT)
if(IS_STAMCRIT(user))
to_chat(user, "<span class='warning'>You're too exhausted for that.</span>")
return TRUE
var/mob/living/poordude = buckled_mobs[1]
@@ -3,6 +3,7 @@
icon_state = "sofamiddle"
icon = 'icons/obj/sofa.dmi'
buildstackamount = 1
item_chair = null
var/mutable_appearance/armrest
/obj/structure/chair/sofa/Initialize()
@@ -121,7 +121,7 @@
return FALSE
var/turf/T = get_turf(src)
for(var/mob/living/L in T)
if(L.anchored || horizontal && L.mob_size > MOB_SIZE_TINY && L.density)
if(L.move_resist >= MOVE_FORCE_VERY_STRONG || (horizontal && L.mob_size > MOB_SIZE_TINY && L.density))
if(user)
to_chat(user, "<span class='danger'>There's something large on top of [src], preventing it from opening.</span>" )
return FALSE
@@ -133,7 +133,7 @@
if(closet != src && !closet.wall_mounted)
return FALSE
for(var/mob/living/L in T)
if(L.anchored || horizontal && L.mob_size > MOB_SIZE_TINY && L.density)
if(L.move_resist >= MOVE_FORCE_VERY_STRONG || horizontal && L.mob_size > MOB_SIZE_TINY && L.density)
if(user)
to_chat(user, "<span class='danger'>There's something too large in [src], preventing it from closing.</span>")
return FALSE
@@ -216,7 +216,7 @@
if(!isliving(AM)) //let's not put ghosts or camera mobs inside closets...
return FALSE
var/mob/living/L = AM
if(L.anchored || L.buckled || L.incorporeal_move || L.has_buckled_mobs())
if(L.move_resist >= MOVE_FORCE_VERY_STRONG || L.buckled || L.incorporeal_move || L.has_buckled_mobs())
return FALSE
if(L.mob_size > MOB_SIZE_TINY) // Tiny mobs are treated as items.
if(horizontal && L.density)
@@ -451,7 +451,7 @@
/obj/structure/closet/relaymove(mob/user)
if(user.stat || !isturf(loc) || !isliving(user))
return
if(locked)
if(locked || welded)
if(message_cooldown <= world.time)
message_cooldown = world.time + 50
to_chat(user, "<span class='warning'>[src]'s door won't budge!</span>")
@@ -11,10 +11,10 @@
new /obj/item/clothing/under/shorts/red(src)
new /obj/item/clothing/under/shorts/blue(src)
new /obj/item/clothing/under/shorts/green(src)
new /obj/item/clothing/under/jabroni(src)
new /obj/item/clothing/under/polychromic/shortpants(src)
new /obj/item/clothing/under/polychromic/shortpants(src)
new /obj/item/clothing/under/polychromic/shortpants(src)
new /obj/item/clothing/under/costume/jabroni(src)
new /obj/item/clothing/under/shorts/polychromic(src)
new /obj/item/clothing/under/shorts/polychromic(src)
new /obj/item/clothing/under/shorts/polychromic(src)
/obj/structure/closet/boxinggloves
@@ -27,7 +27,7 @@
for(var/i in 1 to 5)
new /obj/item/clothing/head/ushanka(src)
for(var/i in 1 to 5)
new /obj/item/clothing/under/soviet(src)
new /obj/item/clothing/under/costume/soviet(src)
/obj/structure/closet/gimmick/tacticool
name = "tacticool gear closet"
@@ -11,10 +11,10 @@
new /obj/item/radio/headset/headset_srv(src)
new /obj/item/radio/headset/headset_srv(src)
new /obj/item/clothing/head/that(src)
new /obj/item/clothing/under/sl_suit(src)
new /obj/item/clothing/under/sl_suit(src)
new /obj/item/clothing/under/rank/bartender(src)
new /obj/item/clothing/under/rank/bartender(src)
new /obj/item/clothing/under/suit/sl(src)
new /obj/item/clothing/under/suit/sl(src)
new /obj/item/clothing/under/rank/civilian/bartender(src)
new /obj/item/clothing/under/rank/civilian/bartender(src)
new /obj/item/clothing/accessory/waistcoat(src)
new /obj/item/clothing/accessory/waistcoat(src)
new /obj/item/clothing/head/soft/black(src)
@@ -37,8 +37,8 @@
/obj/structure/closet/chefcloset/PopulateContents()
..()
new /obj/item/clothing/under/waiter(src)
new /obj/item/clothing/under/waiter(src)
new /obj/item/clothing/under/suit/waiter(src)
new /obj/item/clothing/under/suit/waiter(src)
new /obj/item/radio/headset/headset_srv(src)
new /obj/item/radio/headset/headset_srv(src)
new /obj/item/clothing/accessory/waistcoat(src)
@@ -51,7 +51,7 @@
new /obj/item/storage/box/mousetraps(src)
new /obj/item/circuitboard/machine/dish_drive(src)
new /obj/item/clothing/suit/toggle/chef(src)
new /obj/item/clothing/under/rank/chef(src)
new /obj/item/clothing/under/rank/civilian/chef(src)
new /obj/item/clothing/head/chefhat(src)
new /obj/item/reagent_containers/rag(src)
@@ -62,7 +62,7 @@
/obj/structure/closet/jcloset/PopulateContents()
..()
new /obj/item/clothing/under/rank/janitor(src)
new /obj/item/clothing/under/rank/civilian/janitor(src)
new /obj/item/cartridge/janitor(src)
new /obj/item/clothing/gloves/color/black(src)
new /obj/item/clothing/head/soft/purple(src)
@@ -87,14 +87,14 @@
/obj/structure/closet/lawcloset/PopulateContents()
..()
new /obj/item/clothing/under/lawyer/female(src)
new /obj/item/clothing/under/lawyer/black(src)
new /obj/item/clothing/under/lawyer/red(src)
new /obj/item/clothing/under/lawyer/bluesuit(src)
new /obj/item/clothing/under/rank/civilian/lawyer/female(src)
new /obj/item/clothing/under/rank/civilian/lawyer/black(src)
new /obj/item/clothing/under/rank/civilian/lawyer/red(src)
new /obj/item/clothing/under/rank/civilian/lawyer/bluesuit(src)
new /obj/item/clothing/suit/toggle/lawyer(src)
new /obj/item/clothing/under/lawyer/purpsuit(src)
new /obj/item/clothing/under/rank/civilian/lawyer/purpsuit(src)
new /obj/item/clothing/suit/toggle/lawyer/purple(src)
new /obj/item/clothing/under/lawyer/blacksuit(src)
new /obj/item/clothing/under/rank/civilian/lawyer/black(src)
new /obj/item/clothing/suit/toggle/lawyer/black(src)
new /obj/item/clothing/shoes/laceup(src)
new /obj/item/clothing/shoes/laceup(src)
@@ -109,7 +109,7 @@
/obj/structure/closet/wardrobe/chaplain_black/PopulateContents()
new /obj/item/choice_beacon/holy(src)
new /obj/item/clothing/accessory/pocketprotector/cosmetology(src)
new /obj/item/clothing/under/rank/chaplain(src)
new /obj/item/clothing/under/rank/civilian/chaplain(src)
new /obj/item/clothing/shoes/sneakers/black(src)
new /obj/item/clothing/suit/chaplain/nun(src)
new /obj/item/clothing/head/nun_hood(src)
@@ -130,9 +130,9 @@
new /obj/item/storage/backpack/duffelbag/sec(src)
new /obj/item/storage/backpack/duffelbag/sec(src)
for(var/i in 1 to 3)
new /obj/item/clothing/under/rank/security(src)
new /obj/item/clothing/under/rank/security/officer(src)
for(var/i in 1 to 2)
new /obj/item/clothing/under/rank/security/skirt(src)
new /obj/item/clothing/under/rank/security/officer/skirt(src)
for(var/i in 1 to 3)
new /obj/item/clothing/shoes/jackboots(src)
for(var/i in 1 to 3)
@@ -151,7 +151,7 @@
/obj/structure/closet/wardrobe/cargotech/PopulateContents()
new /obj/item/clothing/suit/hooded/wintercoat/cargo(src)
for(var/i in 1 to 3)
new /obj/item/clothing/under/rank/cargotech(src)
new /obj/item/clothing/under/rank/cargo/tech(src)
for(var/i in 1 to 3)
new /obj/item/clothing/shoes/sneakers/black(src)
for(var/i in 1 to 3)
@@ -172,7 +172,7 @@
for(var/i in 1 to 3)
new /obj/item/clothing/suit/hooded/wintercoat/engineering/atmos(src)
for(var/i in 1 to 3)
new /obj/item/clothing/under/rank/atmospheric_technician(src)
new /obj/item/clothing/under/rank/engineering/atmospheric_technician(src)
for(var/i in 1 to 3)
new /obj/item/clothing/shoes/sneakers/black(src)
return
@@ -188,7 +188,7 @@
new /obj/item/storage/backpack/satchel/eng(src)
new /obj/item/clothing/suit/hooded/wintercoat/engineering(src)
for(var/i in 1 to 3)
new /obj/item/clothing/under/rank/engineer(src)
new /obj/item/clothing/under/rank/engineering/engineer(src)
for(var/i in 1 to 3)
new /obj/item/clothing/suit/hazardvest(src)
for(var/i in 1 to 3)
@@ -206,13 +206,13 @@
new /obj/item/storage/backpack/medic(src)
new /obj/item/storage/backpack/satchel/med(src)
new /obj/item/clothing/suit/hooded/wintercoat/medical(src)
new /obj/item/clothing/under/rank/nursesuit(src)
new /obj/item/clothing/under/rank/medical/doctor/nurse(src)
new /obj/item/clothing/head/nursehat(src)
new /obj/item/clothing/under/rank/medical/blue(src)
new /obj/item/clothing/under/rank/medical/green(src)
new /obj/item/clothing/under/rank/medical/purple(src)
new /obj/item/clothing/under/rank/medical/doctor/blue(src)
new /obj/item/clothing/under/rank/medical/doctor/green(src)
new /obj/item/clothing/under/rank/medical/doctor/purple(src)
for(var/i in 1 to 3)
new /obj/item/clothing/under/rank/medical(src)
new /obj/item/clothing/under/rank/medical/doctor(src)
for(var/i in 1 to 3)
new /obj/item/clothing/suit/toggle/labcoat(src)
for(var/i in 1 to 3)
@@ -230,8 +230,8 @@
/obj/structure/closet/wardrobe/robotics_black/PopulateContents()
new /obj/item/clothing/glasses/hud/diagnostic(src)
new /obj/item/clothing/glasses/hud/diagnostic(src)
new /obj/item/clothing/under/rank/roboticist(src)
new /obj/item/clothing/under/rank/roboticist(src)
new /obj/item/clothing/under/rank/rnd/roboticist(src)
new /obj/item/clothing/under/rank/rnd/roboticist(src)
new /obj/item/clothing/suit/toggle/labcoat(src)
new /obj/item/clothing/suit/toggle/labcoat(src)
new /obj/item/clothing/shoes/sneakers/black(src)
@@ -252,8 +252,8 @@
icon_door = "white"
/obj/structure/closet/wardrobe/chemistry_white/PopulateContents()
new /obj/item/clothing/under/rank/chemist(src)
new /obj/item/clothing/under/rank/chemist(src)
new /obj/item/clothing/under/rank/medical/chemist(src)
new /obj/item/clothing/under/rank/medical/chemist(src)
new /obj/item/clothing/shoes/sneakers/white(src)
new /obj/item/clothing/shoes/sneakers/white(src)
new /obj/item/clothing/suit/toggle/labcoat/chemist(src)
@@ -272,8 +272,8 @@
icon_door = "white"
/obj/structure/closet/wardrobe/genetics_white/PopulateContents()
new /obj/item/clothing/under/rank/geneticist(src)
new /obj/item/clothing/under/rank/geneticist(src)
new /obj/item/clothing/under/rank/medical/geneticist(src)
new /obj/item/clothing/under/rank/medical/geneticist(src)
new /obj/item/clothing/shoes/sneakers/white(src)
new /obj/item/clothing/shoes/sneakers/white(src)
new /obj/item/clothing/suit/toggle/labcoat/genetics(src)
@@ -290,8 +290,8 @@
icon_door = "white"
/obj/structure/closet/wardrobe/virology_white/PopulateContents()
new /obj/item/clothing/under/rank/virologist(src)
new /obj/item/clothing/under/rank/virologist(src)
new /obj/item/clothing/under/rank/medical/virologist(src)
new /obj/item/clothing/under/rank/medical/virologist(src)
new /obj/item/clothing/shoes/sneakers/white(src)
new /obj/item/clothing/shoes/sneakers/white(src)
new /obj/item/clothing/suit/toggle/labcoat/virologist(src)
@@ -316,7 +316,7 @@
new /obj/item/storage/backpack/satchel/tox(src)
new /obj/item/clothing/suit/hooded/wintercoat/science(src)
for(var/i in 1 to 3)
new /obj/item/clothing/under/rank/scientist(src)
new /obj/item/clothing/under/rank/rnd/scientist(src)
for(var/i in 1 to 3)
new /obj/item/clothing/suit/toggle/labcoat/science(src)
for(var/i in 1 to 3)
@@ -342,7 +342,7 @@
new /obj/item/clothing/suit/apron/overalls(src)
new /obj/item/clothing/suit/apron/overalls(src)
for(var/i in 1 to 3)
new /obj/item/clothing/under/rank/hydroponics(src)
new /obj/item/clothing/under/rank/civilian/hydroponics(src)
for(var/i in 1 to 3)
new /obj/item/clothing/mask/bandana(src)
@@ -355,7 +355,7 @@
new /obj/item/clothing/accessory/pocketprotector/full(src)
new /obj/item/clothing/head/fedora/curator(src)
new /obj/item/clothing/suit/curator(src)
new /obj/item/clothing/under/rank/curator/treasure_hunter(src)
new /obj/item/clothing/under/rank/civilian/curator/treasure_hunter(src)
new /obj/item/clothing/shoes/workboots/mining(src)
new /obj/item/storage/backpack/satchel/explorer(src)
@@ -8,8 +8,8 @@
new /obj/item/clothing/neck/cloak/qm(src)
new /obj/item/clothing/head/beret/qm(src)
new /obj/item/storage/lockbox/medal/cargo(src)
new /obj/item/clothing/under/rank/cargo(src)
new /obj/item/clothing/under/rank/cargo/skirt(src)
new /obj/item/clothing/under/rank/cargo/qm(src)
new /obj/item/clothing/under/rank/cargo/qm/skirt(src)
new /obj/item/clothing/shoes/sneakers/brown(src)
new /obj/item/radio/headset/heads/qm(src)
new /obj/item/clothing/suit/fire/firefighter(src)
@@ -7,8 +7,8 @@
..()
new /obj/item/clothing/neck/cloak/ce(src)
new /obj/item/clothing/head/beret/ce(src)
new /obj/item/clothing/under/rank/chief_engineer(src)
new /obj/item/clothing/under/rank/chief_engineer/skirt(src)
new /obj/item/clothing/under/rank/engineering/chief_engineer(src)
new /obj/item/clothing/under/rank/engineering/chief_engineer/skirt(src)
new /obj/item/clothing/head/hardhat/white(src)
new /obj/item/clothing/head/hardhat/weldhat/white(src)
new /obj/item/clothing/gloves/color/yellow(src)
@@ -60,8 +60,9 @@
new /obj/item/clothing/suit/bio_suit/cmo(src)
new /obj/item/clothing/head/bio_hood/cmo(src)
new /obj/item/clothing/suit/toggle/labcoat/cmo(src)
new /obj/item/clothing/under/rank/chief_medical_officer(src)
new /obj/item/clothing/under/rank/chief_medical_officer/skirt(src)
new /obj/item/clothing/under/rank/medical/chief_medical_officer(src)
new /obj/item/clothing/under/rank/medical/chief_medical_officer/skirt(src)
new /obj/item/clothing/under/rank/medical/chief_medical_officer/turtleneck(src)
new /obj/item/clothing/shoes/sneakers/brown (src)
new /obj/item/cartridge/cmo(src)
new /obj/item/radio/headset/heads/cmo(src)
@@ -10,12 +10,12 @@
new /obj/item/clothing/suit/bio_suit/scientist(src)
new /obj/item/clothing/head/bio_hood/scientist(src)
new /obj/item/clothing/suit/toggle/labcoat(src)
new /obj/item/clothing/under/rank/research_director(src)
new /obj/item/clothing/under/rank/research_director/skirt(src)
new /obj/item/clothing/under/rank/research_director/alt(src)
new /obj/item/clothing/under/rank/research_director/alt/skirt(src)
new /obj/item/clothing/under/rank/research_director/turtleneck(src)
new /obj/item/clothing/under/rank/research_director/turtleneck/skirt(src)
new /obj/item/clothing/under/rank/rnd/research_director(src)
new /obj/item/clothing/under/rank/rnd/research_director/skirt(src)
new /obj/item/clothing/under/rank/rnd/research_director/alt(src)
new /obj/item/clothing/under/rank/rnd/research_director/alt/skirt(src)
new /obj/item/clothing/under/rank/rnd/research_director/turtleneck(src)
new /obj/item/clothing/under/rank/rnd/research_director/turtleneck/skirt(src)
new /obj/item/clothing/shoes/sneakers/brown(src)
new /obj/item/cartridge/rd(src)
new /obj/item/clothing/gloves/color/latex(src)
@@ -25,8 +25,8 @@
/obj/structure/closet/secure_closet/hop/PopulateContents()
..()
new /obj/item/clothing/neck/cloak/hop(src)
new /obj/item/clothing/under/rank/head_of_personnel(src)
new /obj/item/clothing/under/rank/head_of_personnel/skirt(src)
new /obj/item/clothing/under/rank/civilian/head_of_personnel(src)
new /obj/item/clothing/under/rank/civilian/head_of_personnel/skirt(src)
new /obj/item/clothing/head/hopcap(src)
new /obj/item/clothing/head/hopcap/beret(src)
new /obj/item/cartridge/hop(src)
@@ -57,17 +57,17 @@
new /obj/item/clothing/neck/cloak/hos(src)
new /obj/item/cartridge/hos(src)
new /obj/item/radio/headset/heads/hos(src)
new /obj/item/clothing/under/hosparadefem(src)
new /obj/item/clothing/under/hosparademale(src)
new /obj/item/clothing/under/rank/security/head_of_security/parade/female(src)
new /obj/item/clothing/under/rank/security/head_of_security/parade(src)
new /obj/item/clothing/suit/armor/vest/leather(src)
new /obj/item/clothing/suit/armor/hos(src)
new /obj/item/clothing/under/rank/head_of_security/skirt(src)
new /obj/item/clothing/under/rank/head_of_security/alt(src)
new /obj/item/clothing/under/rank/head_of_security/alt/skirt(src)
new /obj/item/clothing/under/rank/security/head_of_security/skirt(src)
new /obj/item/clothing/under/rank/security/head_of_security/alt(src)
new /obj/item/clothing/under/rank/security/head_of_security/alt/skirt(src)
new /obj/item/clothing/head/HoS(src)
new /obj/item/clothing/glasses/hud/security/sunglasses/eyepatch(src)
new /obj/item/clothing/glasses/hud/security/sunglasses/gars/supergars(src)
new /obj/item/clothing/under/rank/head_of_security/grey(src)
new /obj/item/clothing/under/rank/security/head_of_security/grey(src)
new /obj/item/storage/lockbox/medal/sec(src)
new /obj/item/megaphone/sec(src)
new /obj/item/holosign_creator/security(src)
@@ -94,8 +94,8 @@
new /obj/item/clothing/head/warden/drill(src)
new /obj/item/clothing/head/beret/sec/navywarden(src)
new /obj/item/clothing/suit/armor/vest/warden/alt(src)
new /obj/item/clothing/under/rank/warden/navyblue(src)
new /obj/item/clothing/under/rank/warden/skirt(src)
new /obj/item/clothing/under/rank/security/warden/formal(src)
new /obj/item/clothing/under/rank/security/warden/skirt(src)
new /obj/item/clothing/glasses/hud/security/sunglasses(src)
new /obj/item/holosign_creator/security(src)
new /obj/item/clothing/mask/gas/sechailer(src)
@@ -155,13 +155,13 @@
/obj/structure/closet/secure_closet/detective/PopulateContents()
..()
new /obj/item/clothing/under/rank/det(src)
new /obj/item/clothing/under/rank/det/skirt(src)
new /obj/item/clothing/under/rank/security/detective(src)
new /obj/item/clothing/under/rank/security/detective/skirt(src)
new /obj/item/clothing/suit/det_suit(src)
new /obj/item/clothing/head/fedora/det_hat(src)
new /obj/item/clothing/gloves/color/black(src)
new /obj/item/clothing/under/rank/det/grey(src)
new /obj/item/clothing/under/rank/det/grey/skirt(src)
new /obj/item/clothing/under/rank/security/detective/grey(src)
new /obj/item/clothing/under/rank/security/detective/grey/skirt(src)
new /obj/item/clothing/accessory/waistcoat(src)
new /obj/item/clothing/suit/det_suit/grey(src)
new /obj/item/clothing/head/fedora(src)
@@ -286,7 +286,7 @@
..()
new /obj/item/clothing/suit/armor/vest(src)
new /obj/item/clothing/head/helmet/sec(src)
new /obj/item/clothing/under/rank/security(src)
new /obj/item/clothing/under/rank/security/skirt(src)
new /obj/item/clothing/under/rank/security/officer(src)
new /obj/item/clothing/under/rank/security/officer/skirt(src)
new /obj/item/clothing/glasses/hud/security/sunglasses(src)
new /obj/item/flashlight/seclite(src)
@@ -15,7 +15,7 @@
new /obj/item/ammo_box/magazine/m10mm(src)
new /obj/item/storage/belt/military(src)
new /obj/item/crowbar/red(src)
new /obj/item/clothing/glasses/night(src)
new /obj/item/clothing/glasses/night/syndicate(src)
/obj/structure/closet/syndicate/nuclear
desc = "It's a storage unit for a Syndicate boarding party."
@@ -170,7 +170,7 @@
if(prob(90))
new /obj/item/wirecutters(src)
new /obj/item/clothing/suit/bomb_suit/security(src)
new /obj/item/clothing/under/rank/security(src)
new /obj/item/clothing/under/rank/security/officer(src)
new /obj/item/clothing/shoes/jackboots(src)
new /obj/item/clothing/head/bomb_hood/security(src)
@@ -7,7 +7,7 @@
for(var/i in 1 to 3)
new /obj/item/clothing/under/color/blue(src)
for(var/i in 1 to 3)
new /obj/item/clothing/under/skirt/color/blue(src)
new /obj/item/clothing/under/color/jumpskirt/blue(src)
for(var/i in 1 to 3)
new /obj/item/clothing/shoes/sneakers/brown(src)
return
@@ -18,7 +18,7 @@
for(var/i in 1 to 3)
new /obj/item/clothing/under/color/pink(src)
for(var/i in 1 to 3)
new /obj/item/clothing/under/skirt/color/pink(src)
new /obj/item/clothing/under/color/jumpskirt/pink(src)
for(var/i in 1 to 3)
new /obj/item/clothing/shoes/sneakers/brown(src)
return
@@ -29,7 +29,7 @@
for(var/i in 1 to 3)
new /obj/item/clothing/under/color/black(src)
for(var/i in 1 to 3)
new /obj/item/clothing/under/skirt/color/black(src)
new /obj/item/clothing/under/color/jumpskirt/black(src)
if(prob(25))
new /obj/item/clothing/suit/jacket/leather(src)
if(prob(20))
@@ -52,7 +52,7 @@
for(var/i in 1 to 3)
new /obj/item/clothing/under/color/green(src)
for(var/i in 1 to 3)
new /obj/item/clothing/under/skirt/color/green(src)
new /obj/item/clothing/under/color/jumpskirt/green(src)
for(var/i in 1 to 3)
new /obj/item/clothing/shoes/sneakers/black(src)
new /obj/item/clothing/mask/bandana/green(src)
@@ -77,7 +77,7 @@
for(var/i in 1 to 3)
new /obj/item/clothing/under/color/yellow(src)
for(var/i in 1 to 3)
new /obj/item/clothing/under/skirt/color/yellow(src)
new /obj/item/clothing/under/color/jumpskirt/yellow(src)
for(var/i in 1 to 3)
new /obj/item/clothing/shoes/sneakers/orange(src)
new /obj/item/clothing/mask/bandana/gold(src)
@@ -90,7 +90,7 @@
for(var/i in 1 to 3)
new /obj/item/clothing/under/color/white(src)
for(var/i in 1 to 3)
new /obj/item/clothing/under/skirt/color/white(src)
new /obj/item/clothing/under/color/jumpskirt/white(src)
for(var/i in 1 to 3)
new /obj/item/clothing/shoes/sneakers/white(src)
for(var/i in 1 to 3)
@@ -100,10 +100,10 @@
name = "pajama wardrobe"
icon_door = "white"
/obj/structure/closet/wardrobe/pjs/PopulateContents()
new /obj/item/clothing/under/pj/red(src)
new /obj/item/clothing/under/pj/red(src)
new /obj/item/clothing/under/pj/blue(src)
new /obj/item/clothing/under/pj/blue(src)
new /obj/item/clothing/under/misc/pj/red(src)
new /obj/item/clothing/under/misc/pj/red(src)
new /obj/item/clothing/under/misc/pj/blue(src)
new /obj/item/clothing/under/misc/pj/blue(src)
for(var/i in 1 to 4)
new /obj/item/clothing/shoes/sneakers/white(src)
return
@@ -114,7 +114,7 @@
for(var/i in 1 to 3)
new /obj/item/clothing/under/color/grey(src)
for(var/i in 1 to 3)
new /obj/item/clothing/under/skirt/color/grey(src)
new /obj/item/clothing/under/color/jumpskirt/grey(src)
for(var/i in 1 to 3)
new /obj/item/clothing/shoes/sneakers/black(src)
for(var/i in 1 to 3)
@@ -125,10 +125,10 @@
new /obj/item/clothing/mask/bandana/black(src)
new /obj/item/clothing/mask/bandana/black(src)
if(prob(40))
new /obj/item/clothing/under/assistantformal(src)
new /obj/item/clothing/under/misc/assistantformal(src)
new /obj/item/clothing/suit/hooded/wintercoat/aformal(src)
if(prob(40))
new /obj/item/clothing/under/assistantformal(src)
new /obj/item/clothing/under/misc/assistantformal(src)
new /obj/item/clothing/suit/hooded/wintercoat/aformal(src)
if(prob(30))
new /obj/item/clothing/suit/hooded/wintercoat(src)
@@ -144,21 +144,21 @@
new /obj/item/clothing/suit/jacket(src)
if(prob(40))
new /obj/item/clothing/suit/jacket(src)
new /obj/item/clothing/under/polychromic/jumpsuit(src)
new /obj/item/clothing/under/polychromic/jumpsuit(src)
new /obj/item/clothing/under/polychromic/jumpsuit(src)
new /obj/item/clothing/under/polychromic/shirt(src)
new /obj/item/clothing/under/polychromic/shirt(src)
new /obj/item/clothing/under/polychromic/shirt(src)
new /obj/item/clothing/under/polychromic/kilt(src)
new /obj/item/clothing/under/polychromic/kilt(src)
new /obj/item/clothing/under/polychromic/kilt(src)
new /obj/item/clothing/under/polychromic/skirt(src)
new /obj/item/clothing/under/polychromic/skirt(src)
new /obj/item/clothing/under/polychromic/skirt(src)
new /obj/item/clothing/under/polychromic/shorts(src)
new /obj/item/clothing/under/polychromic/shorts(src)
new /obj/item/clothing/under/polychromic/shorts(src)
new /obj/item/clothing/under/misc/polyjumpsuit(src)
new /obj/item/clothing/under/misc/polyjumpsuit(src)
new /obj/item/clothing/under/misc/polyjumpsuit(src)
new /obj/item/clothing/under/misc/poly_shirt(src)
new /obj/item/clothing/under/misc/poly_shirt(src)
new /obj/item/clothing/under/misc/poly_shirt(src)
new /obj/item/clothing/under/costume/kilt/polychromic(src)
new /obj/item/clothing/under/costume/kilt/polychromic(src)
new /obj/item/clothing/under/costume/kilt/polychromic(src)
new /obj/item/clothing/under/dress/skirt/polychromic(src)
new /obj/item/clothing/under/dress/skirt/polychromic(src)
new /obj/item/clothing/under/dress/skirt/polychromic(src)
new /obj/item/clothing/under/misc/polyshorts(src)
new /obj/item/clothing/under/misc/polyshorts(src)
new /obj/item/clothing/under/misc/polyshorts(src)
new /obj/item/clothing/mask/bandana/red(src)
new /obj/item/clothing/mask/bandana/red(src)
new /obj/item/clothing/mask/bandana/blue(src)
+1 -1
View File
@@ -73,7 +73,7 @@
H.socks_color = recolor_undergarment(H, "socks", H.socks_color)
add_fingerprint(H)
H.update_body()
H.update_body(TRUE)
/obj/structure/dresser/proc/recolor_undergarment(mob/living/carbon/human/H, garment_type = "underwear", default_color)
var/n_color = input(H, "Choose your [garment_type]'\s color.", "Character Preference", default_color) as color|null
@@ -31,7 +31,7 @@
new_spawn.underwear = "Nude" //You're a plant, partner
new_spawn.undershirt = "Nude" //changing underwear/shirt/socks doesn't seem to function correctly right now because of some bug elsewhere?
new_spawn.socks = "Nude"
new_spawn.update_body()
new_spawn.update_body(TRUE)
//Ash walker eggs: Spawns in ash walker dens in lavaland. Ghosts become unbreathing lizards that worship the Necropolis and are advised to retrieve corpses to create more ash walkers.
@@ -59,6 +59,7 @@
new_spawn.real_name = random_unique_lizard_name(gender)
if(is_mining_level(z))
to_chat(new_spawn, "<b>Drag the corpses of men and beasts to your nest. It will absorb them to create more of your kind. Glory to the Necropolis!</b>")
to_chat(new_spawn, "<b>You can expand the weather proof area provided by your shelters by using the 'New Area' key near the bottom right of your HUD.</b>")
else
to_chat(new_spawn, "<span class='userdanger'>You have been born outside of your natural home! Whether you decide to return home, or make due with your new home is your own decision.</span>")
@@ -88,7 +89,7 @@
/datum/outfit/ashwalker
name ="Ashwalker"
head = /obj/item/clothing/head/helmet/gladiator
uniform = /obj/item/clothing/under/gladiator/ash_walker
uniform = /obj/item/clothing/under/costume/gladiator/ash_walker
//Timeless prisons: Spawns in Wish Granter prisons in lavaland. Ghosts become age-old users of the Wish Granter and are advised to seek repentance for their past.
@@ -194,9 +195,7 @@
return
if(isgolem(user) && can_transfer)
var/transfer_choice = alert("Transfer your soul to [src]? (Warning, your old body will die!)",,"Yes","No")
if(transfer_choice != "Yes")
return
if(QDELETED(src) || uses <= 0)
if(transfer_choice != "Yes" || QDELETED(src) || uses <= 0 || !user.canUseTopic(src, BE_CLOSE, NO_DEXTERY, NO_TK))
return
log_game("[key_name(user)] golem-swapped into [src]")
user.visible_message("<span class='notice'>A faint light leaves [user], moving to [src] and animating it!</span>","<span class='notice'>You leave your old body behind, and transfer into [src]!</span>")
@@ -244,7 +243,7 @@
flavour_text += "you were a [pick("arms dealer", "shipwright", "docking manager")]'s assistant on a small trading station several sectors from here. Raiders attacked, and there was \
only one pod left when you got to the escape bay. You took it and launched it alone, and the crowd of terrified faces crowding at the airlock door as your pod's engines burst to \
life and sent you to this hell are forever branded into your memory."
outfit.uniform = /obj/item/clothing/under/assistantformal
outfit.uniform = /obj/item/clothing/under/misc/assistantformal
outfit.shoes = /obj/item/clothing/shoes/sneakers/black
outfit.back = /obj/item/storage/backpack
if(2)
@@ -257,7 +256,7 @@
if(3)
flavour_text += "you were a doctor on one of Nanotrasen's space stations, but you left behind that damn corporation's tyranny and everything it stood for. From a metaphorical hell \
to a literal one, you find yourself nonetheless missing the recycled air and warm floors of what you left behind... but you'd still rather be here than there."
outfit.uniform = /obj/item/clothing/under/rank/medical
outfit.uniform = /obj/item/clothing/under/rank/medical/doctor
outfit.suit = /obj/item/clothing/suit/toggle/labcoat
outfit.back = /obj/item/storage/backpack/medic
outfit.shoes = /obj/item/clothing/shoes/sneakers/black
@@ -352,7 +351,7 @@
/datum/outfit/hotelstaff
name = "Hotel Staff"
uniform = /obj/item/clothing/under/telegram
uniform = /obj/item/clothing/under/suit/telegram
shoes = /obj/item/clothing/shoes/laceup
head = /obj/item/clothing/head/hotel
r_pocket = /obj/item/radio/off
@@ -372,7 +371,7 @@
/datum/outfit/hotelstaff/security
name = "Hotel Secuirty"
uniform = /obj/item/clothing/under/rank/security/blueshirt
uniform = /obj/item/clothing/under/rank/security/officer/blueshirt
shoes = /obj/item/clothing/shoes/jackboots
suit = /obj/item/clothing/suit/armor/vest/blueshirt
head = /obj/item/clothing/head/helmet/blueshirt
@@ -434,7 +433,7 @@
/datum/outfit/demonic_friend
name = "Demonic Friend"
uniform = /obj/item/clothing/under/assistantformal
uniform = /obj/item/clothing/under/misc/assistantformal
shoes = /obj/item/clothing/shoes/laceup
r_pocket = /obj/item/radio/off
back = /obj/item/storage/backpack
@@ -528,7 +527,7 @@
The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
important_info = "Work as a team with your fellow survivors and do not abandon them."
uniform = /obj/item/clothing/under/rank/security
uniform = /obj/item/clothing/under/rank/security/officer
shoes = /obj/item/clothing/shoes/jackboots
id = /obj/item/card/id/away/old/sec
r_pocket = /obj/item/restraints/handcuffs
@@ -556,7 +555,7 @@
you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
important_info = "Work as a team with your fellow survivors and do not abandon them."
uniform = /obj/item/clothing/under/rank/engineer
uniform = /obj/item/clothing/under/rank/engineering/engineer
shoes = /obj/item/clothing/shoes/workboots
id = /obj/item/card/id/away/old/eng
gloves = /obj/item/clothing/gloves/color/fyellow/old
@@ -582,7 +581,7 @@
The last thing you remember is the station's Artificial Program telling you that you would only be asleep for eight hours. As you open \
your eyes, everything seems rusted and broken, a dark feeling swells in your gut as you climb out of your pod."
important_info = "Work as a team with your fellow survivors and do not abandon them."
uniform = /obj/item/clothing/under/rank/scientist
uniform = /obj/item/clothing/under/rank/rnd/scientist
shoes = /obj/item/clothing/shoes/laceup
id = /obj/item/card/id/away/old/sci
l_pocket = /obj/item/stack/medical/bruise_pack
@@ -679,8 +678,9 @@
new_spawn.AddElement(/datum/element/dusts_on_catatonia)
new_spawn.AddElement(/datum/element/dusts_on_leaving_area,list(A.type,/area/hilbertshotel))
ADD_TRAIT(new_spawn, TRAIT_SIXTHSENSE, GHOSTROLE_TRAIT)
ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT)
ADD_TRAIT(new_spawn,TRAIT_PACIFISM,GHOSTROLE_TRAIT)
ADD_TRAIT(new_spawn, TRAIT_EXEMPT_HEALTH_EVENTS, GHOSTROLE_TRAIT)
ADD_TRAIT(new_spawn, TRAIT_NO_MIDROUND_ANTAG, GHOSTROLE_TRAIT) //The mob can't be made into a random antag, they are still elegible for ghost roles popups.
ADD_TRAIT(new_spawn, TRAIT_PACIFISM, GHOSTROLE_TRAIT)
to_chat(new_spawn,"<span class='boldwarning'>You may be sharing your cafe with some ninja-captured individuals, so make sure to only interact with the ghosts you hear as a ghost!</span>")
to_chat(new_spawn,"<span class='boldwarning'>You can turn yourself into a ghost and freely reenter your body with the ghost action.</span>")
var/datum/action/ghost/G = new(new_spawn)
@@ -703,12 +703,12 @@
if(suited)
uniform = /obj/item/clothing/under/color/grey
else
uniform = /obj/item/clothing/under/skirt/color/grey
uniform = /obj/item/clothing/under/color/jumpskirt/grey
else
if(suited)
uniform = /obj/item/clothing/under/color/random
else
uniform = /obj/item/clothing/under/skirt/color/random
uniform = /obj/item/clothing/under/color/jumpskirt/random
/obj/item/storage/box/syndie_kit/chameleon/ghostcafe
name = "ghost cafe costuming kit"
@@ -315,13 +315,8 @@
/obj/structure/windoor_assembly/ComponentInitialize()
. = ..()
AddComponent(
/datum/component/simple_rotation,
ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS,
null,
CALLBACK(src, .proc/can_be_rotated),
CALLBACK(src,.proc/after_rotation)
)
var/static/rotation_flags = ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS
AddComponent(/datum/component/simple_rotation, rotation_flags, can_be_rotated=CALLBACK(src, .proc/can_be_rotated), after_rotation=CALLBACK(src,.proc/after_rotation))
/obj/structure/windoor_assembly/proc/can_be_rotated(mob/user,rotation_type)
if(anchored)
+1 -1
View File
@@ -260,7 +260,7 @@
return FALSE
if(ishuman(C) && !(lube & SLIP_WHEN_JOGGING))
var/mob/living/carbon/human/H = C
if(!H.sprinting && H.getStaminaLoss() <= 20)
if(!(H.combat_flags & COMBAT_FLAG_SPRINT_ACTIVE) && H.getStaminaLoss() <= 20)
return FALSE
if(!(lube&SLIDE_ICE))
to_chat(C, "<span class='notice'>You slipped[ O ? " on the [O.name]" : ""]!</span>")
+2 -1
View File
@@ -70,7 +70,8 @@
/turf/closed/wall/proc/break_wall()
new sheet_type(src, sheet_amount)
return new girder_type(src)
if(girder_type)
return new girder_type(src)
/turf/closed/wall/proc/devastate_wall()
new sheet_type(src, sheet_amount)