Merge branch 'master' into donut
This commit is contained in:
@@ -327,7 +327,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
for(var/obj/machinery/light/L in src)
|
||||
L.update()
|
||||
|
||||
/area/proc/updateicon()
|
||||
/area/proc/update_icon()
|
||||
var/weather_icon
|
||||
for(var/V in SSweather.processing)
|
||||
var/datum/weather/W = V
|
||||
@@ -337,7 +337,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
if(!weather_icon)
|
||||
icon_state = null
|
||||
|
||||
/area/space/updateicon()
|
||||
/area/space/update_icon()
|
||||
icon_state = null
|
||||
|
||||
/*
|
||||
@@ -370,7 +370,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
/area/proc/power_change()
|
||||
for(var/obj/machinery/M in src) // for each machine in the area
|
||||
M.power_change() // reverify power status (to update icons etc.)
|
||||
updateicon()
|
||||
update_icon()
|
||||
|
||||
/area/proc/usage(chan)
|
||||
var/used = 0
|
||||
|
||||
+2
-3
@@ -809,8 +809,7 @@ Proc for attack log creation, because really why not
|
||||
|
||||
// Filter stuff
|
||||
/atom/movable/proc/add_filter(name,priority,list/params)
|
||||
if(!filter_data)
|
||||
filter_data = list()
|
||||
LAZYINITLIST(filter_data)
|
||||
var/list/p = params.Copy()
|
||||
p["priority"] = priority
|
||||
filter_data[name] = p
|
||||
@@ -818,7 +817,7 @@ Proc for attack log creation, because really why not
|
||||
|
||||
/atom/movable/proc/update_filters()
|
||||
filters = null
|
||||
sortTim(filter_data,associative = TRUE)
|
||||
filter_data = sortTim(filter_data, /proc/cmp_filter_data_priority, TRUE)
|
||||
for(var/f in filter_data)
|
||||
var/list/data = filter_data[f]
|
||||
var/list/arguments = data.Copy()
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
|
||||
/datum/game_mode
|
||||
var/list/datum/mind/bloodsuckers = list() // List of minds belonging to this game mode.
|
||||
var/list/datum/mind/vassals = list() // List of minds that have been turned into Vassals.
|
||||
//var/list/datum/mind/vamphunters = list() // List of minds hunting vampires. Disabled at the moment
|
||||
var/obj/effect/sunlight/bloodsucker_sunlight // Sunlight Timer. Created on first Bloodsucker assign. Destroyed on last removed Bloodsucker.
|
||||
|
||||
// LISTS //
|
||||
var/list/vassal_allowed_antags = list(/datum/antagonist/brother, /datum/antagonist/traitor, /datum/antagonist/traitor/internal_affairs, /datum/antagonist/survivalist, \
|
||||
/datum/antagonist/rev, /datum/antagonist/nukeop, /datum/antagonist/pirate, /datum/antagonist/cult, /datum/antagonist/abductee)
|
||||
// The antags you're allowed to be if turning Vassal.
|
||||
|
||||
/datum/game_mode/bloodsucker
|
||||
name = "bloodsucker"
|
||||
config_tag = "bloodsucker"
|
||||
traitor_name = "Bloodsucker"
|
||||
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")
|
||||
required_players = 20
|
||||
required_enemies = 2
|
||||
recommended_enemies = 4
|
||||
reroll_friendly = FALSE
|
||||
enemy_minimum_age = 7
|
||||
round_ends_with_antag_death = FALSE
|
||||
|
||||
|
||||
announce_span = "danger"
|
||||
announce_text = "Filthy, bloodsucking vampires are crawling around disguised as crewmembers!\n\
|
||||
<span class='danger'>Bloodsuckers</span>: The crew are cattle, while you are both shepherd and slaughterhouse.\n\
|
||||
<span class='notice'>Crew</span>: Put an end to the undead infestation before the station is overcome!"
|
||||
|
||||
/datum/game_mode/bloodsucker/generate_report()
|
||||
return "Reports indicate that some of your crew may have toppled statues in the past week, angering the gods and becoming cursed with undeath and a desire for blood. Watch out for crewmembers that seem to shun the light or are found pale and delirious."
|
||||
|
||||
// Seems to be run by game ONCE, and finds all potential players to be antag.
|
||||
/datum/game_mode/bloodsucker/pre_setup()
|
||||
|
||||
// Set Restricted Jobs
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
restricted_jobs += protected_jobs
|
||||
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
restricted_jobs += "Assistant"
|
||||
|
||||
// Set number of Vamps
|
||||
recommended_enemies = CLAMP(round(num_players()/10), 1, 6);
|
||||
|
||||
// Select Antags
|
||||
for(var/i = 0, i < recommended_enemies, i++)
|
||||
if (!antag_candidates.len)
|
||||
break
|
||||
var/datum/mind/bloodsucker = pick(antag_candidates)
|
||||
// Can we even BE a bloodsucker?
|
||||
//if (can_make_bloodsucker(bloodsucker, display_warning=FALSE))
|
||||
bloodsuckers += bloodsucker
|
||||
bloodsucker.restricted_roles = restricted_jobs
|
||||
log_game("[bloodsucker.key] (ckey) has been selected as a Bloodsucker.")
|
||||
antag_candidates.Remove(bloodsucker) // Apparently you can also write antag_candidates -= bloodsucker
|
||||
|
||||
// Assign Hunters (as many as monsters, plus one)
|
||||
//assign_monster_hunters(bloodsuckers.len, TRUE, bloodsuckers) // Disabled for now
|
||||
|
||||
// Do we have enough vamps to continue?
|
||||
return bloodsuckers.len >= required_enemies
|
||||
|
||||
|
||||
// Gamemode is all done being set up. We have all our Vamps. We now pick objectives and let them know what's happening.
|
||||
/datum/game_mode/bloodsucker/post_setup()
|
||||
|
||||
// Sunlight (Creating Bloodsuckers manually will check to create this, too)
|
||||
check_start_sunlight()
|
||||
|
||||
// Vamps
|
||||
for(var/datum/mind/bloodsucker in bloodsuckers)
|
||||
// spawn() --> Run block of code but game continues on past it.
|
||||
// sleep() --> Run block of code and freeze code there (including whoever called us) until it's resolved.
|
||||
|
||||
//Clean Bloodsucker Species (racist?)
|
||||
//clean_invalid_species(bloodsucker)
|
||||
// TO-DO !!!
|
||||
|
||||
// Add Bloodsucker Antag Datum (or remove from list on Fail)
|
||||
if (!make_bloodsucker(bloodsucker))
|
||||
bloodsuckers -= bloodsucker
|
||||
|
||||
// NOTE: Hunters are done in ..() parent proc
|
||||
|
||||
return ..()
|
||||
|
||||
// Checking for ACTUALLY Dead Vamps
|
||||
/datum/game_mode/bloodsucker/are_special_antags_dead()
|
||||
// Bloodsucker not Final Dead
|
||||
for(var/datum/mind/bloodsucker in bloodsuckers)
|
||||
if(!bloodsucker.AmFinalDeath())
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
// Init Sunlight (called from datum_bloodsucker.on_gain(), in case game mode isn't even Bloodsucker
|
||||
/datum/game_mode/proc/check_start_sunlight()
|
||||
// Already Sunlight (and not about to cancel)
|
||||
if (istype(bloodsucker_sunlight) && !bloodsucker_sunlight.cancel_me)
|
||||
return
|
||||
bloodsucker_sunlight = new ()
|
||||
|
||||
// End Sun (last bloodsucker removed)
|
||||
/datum/game_mode/proc/check_cancel_sunlight()
|
||||
// No Sunlight
|
||||
if (!istype(bloodsucker_sunlight))
|
||||
return
|
||||
if (bloodsuckers.len <= 0)
|
||||
bloodsucker_sunlight.cancel_me = TRUE
|
||||
qdel(bloodsucker_sunlight)
|
||||
bloodsucker_sunlight = null
|
||||
|
||||
/datum/game_mode/proc/is_daylight()
|
||||
return istype(bloodsucker_sunlight) && bloodsucker_sunlight.amDay
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/datum/game_mode/proc/can_make_bloodsucker(datum/mind/bloodsucker, datum/mind/creator, display_warning=TRUE) // Creator is just here so we can display fail messages to whoever is turning us.
|
||||
// No Mind
|
||||
if(!bloodsucker || !bloodsucker.key) // KEY is client login?
|
||||
//if(creator) // REMOVED. You wouldn't see their name if there is no mind, so why say anything?
|
||||
// to_chat(creator, "<span class='danger'>[bloodsucker] isn't self-aware enough to be raised as a Bloodsucker!</span>")
|
||||
return FALSE
|
||||
// Current body is invalid
|
||||
if(!ishuman(bloodsucker.current))// && !ismonkey(bloodsucker.current))
|
||||
if(display_warning && creator)
|
||||
to_chat(creator, "<span class='danger'>[bloodsucker] isn't evolved enough to be raised as a Bloodsucker!</span>")
|
||||
return FALSE
|
||||
// Species Must have a HEART (Sorry Plasmabois)
|
||||
var/mob/living/carbon/human/H = bloodsucker.current
|
||||
if(NOBLOOD in H.dna.species.species_traits)
|
||||
if(display_warning && creator)
|
||||
to_chat(creator, "<span class='danger'>[bloodsucker]'s DNA isn't compatible!</span>")
|
||||
return FALSE
|
||||
// Already a Non-Human Antag
|
||||
if(bloodsucker.has_antag_datum(/datum/antagonist/abductor) || bloodsucker.has_antag_datum(/datum/antagonist/devil) || bloodsucker.has_antag_datum(/datum/antagonist/changeling))
|
||||
return FALSE
|
||||
// Already a vamp
|
||||
if(bloodsucker.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
|
||||
if(display_warning && creator)
|
||||
to_chat(creator, "<span class='danger'>[bloodsucker] is already a Bloodsucker!</span>")
|
||||
return FALSE
|
||||
// Not High Enough
|
||||
if(creator)
|
||||
var/datum/antagonist/bloodsucker/creator_bloodsucker = creator.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
if(!istype(creator_bloodsucker) || creator_bloodsucker.vamplevel < BLOODSUCKER_LEVEL_TO_EMBRACE)
|
||||
to_chat(creator, "<span class='danger'>Your blood is too thin to turn this corpse!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/game_mode/proc/make_bloodsucker(datum/mind/bloodsucker, datum/mind/creator = null) // NOTE: This is a game_mode/proc, NOT a game_mode/bloodsucker/proc! We need to access this function despite the game mode.
|
||||
if (!can_make_bloodsucker(bloodsucker))
|
||||
return FALSE
|
||||
|
||||
// Create Datum: Fledgling
|
||||
var/datum/antagonist/bloodsucker/A
|
||||
|
||||
// [FLEDGLING]
|
||||
if (creator)
|
||||
A = new (bloodsucker)
|
||||
A.creator = creator
|
||||
bloodsucker.add_antag_datum(A)
|
||||
// Log
|
||||
message_admins("[bloodsucker] has become a Bloodsucker, and was created by [creator].")
|
||||
log_admin("[bloodsucker] has become a Bloodsucker, and was created by [creator].")
|
||||
|
||||
// [MASTER]
|
||||
else
|
||||
A = bloodsucker.add_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/game_mode/proc/remove_bloodsucker(datum/mind/bloodsucker)
|
||||
bloodsucker.remove_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
|
||||
|
||||
/datum/game_mode/proc/clean_invalid_species(datum/mind/bloodsucker)
|
||||
// Only checking for Humans here
|
||||
if (!ishuman(bloodsucker.current) || !bloodsucker.current.client)
|
||||
return
|
||||
var/am_valid = TRUE
|
||||
var/mob/living/carbon/human/H = bloodsucker.current
|
||||
|
||||
// Check if PLASMAMAN?
|
||||
if(NOBLOOD in H.dna.species.species_traits)
|
||||
am_valid = FALSE
|
||||
|
||||
// PROBLEM:
|
||||
//
|
||||
// Setting species leaves clothes on. If you were a plasmaman, we need to reassign your entire outfit. Otherwise
|
||||
// everyone will wonder why you're a human with Plasma clothes (jk they'll know you're antag)
|
||||
|
||||
// Convert to HUMAN (along with ID and PDA)
|
||||
if (!am_valid)
|
||||
H.set_species(/datum/species/human)
|
||||
H.real_name = H.client.prefs.custom_names["human"]
|
||||
var/obj/item/card/id/ID = H.wear_id?.GetID()
|
||||
if(ID)
|
||||
ID.registered_name = H.real_name
|
||||
ID.update_label()
|
||||
|
||||
|
||||
/datum/game_mode/proc/can_make_vassal(mob/living/target, datum/mind/creator, display_warning=TRUE)//, check_antag_or_loyal=FALSE)
|
||||
// Not Correct Type: Abort
|
||||
if (!iscarbon(target) || !creator)
|
||||
return FALSE
|
||||
if (target.stat > UNCONSCIOUS)
|
||||
return FALSE
|
||||
// Check Overdose: Am I even addicted to blood? Do I even have any in me?
|
||||
//if (!target.reagents.addiction_list || !target.reagents.reagent_list)
|
||||
//message_admins("DEBUG2: can_make_vassal() Abort: No reagents")
|
||||
// return 0
|
||||
// Check Overdose: Did my current volume go over the Overdose threshold?
|
||||
//var/am_addicted = 0
|
||||
//for (var/datum/reagent/blood/vampblood/blood in target.reagents.addiction_list) // overdosed is tracked in reagent_list, not addiction_list.
|
||||
//message_admins("DEBUG3: can_make_vassal() Found Blood! [blood] [blood.overdose]")
|
||||
//if (blood.overdosed)
|
||||
// am_addicted = 1 // Blood is present in addiction? That's all we need.
|
||||
// break
|
||||
|
||||
//if (!am_addicted)
|
||||
//message_admins("DEBUG4: can_make_vassal() Abort: No Blood")
|
||||
// return 0
|
||||
// No Mind!
|
||||
if (!target.mind || !target.mind.key)
|
||||
if (display_warning)
|
||||
to_chat(creator, "<span class='danger'>[target] isn't self-aware enough to be made into a Vassal.</span>")
|
||||
return FALSE
|
||||
// Already MY Vassal
|
||||
var/datum/antagonist/vassal/V = target.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
|
||||
if (istype(V) && V.master)
|
||||
if (V.master.owner == creator)
|
||||
if (display_warning)
|
||||
to_chat(creator, "<span class='danger'>[target] is already your loyal Vassal!</span>")
|
||||
else
|
||||
if (display_warning)
|
||||
to_chat(creator, "<span class='danger'>[target] is the loyal Vassal of another Bloodsucker!</span>")
|
||||
return FALSE
|
||||
// Already Antag or Loyal (Vamp Hunters count as antags)
|
||||
if (target.mind.enslaved_to || AmInvalidAntag(target.mind)) //!VassalCheckAntagValid(target.mind, check_antag_or_loyal)) // HAS_TRAIT(target, TRAIT_MINDSHIELD, "implant") ||
|
||||
if (display_warning)
|
||||
to_chat(creator, "<span class='danger'>[target] resists the power of your blood to dominate their mind!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
|
||||
/datum/game_mode/proc/AmValidAntag(datum/mind/M)
|
||||
// No List?
|
||||
if(!islist(M.antag_datums) || M.antag_datums.len == 0)
|
||||
return FALSE
|
||||
// Am I NOT an invalid Antag? NOTE: We already excluded non-antags above. Don't worry about the "No List?" check in AmInvalidIntag()
|
||||
return !AmInvalidAntag(M)
|
||||
|
||||
/datum/game_mode/proc/AmInvalidAntag(datum/mind/M)
|
||||
// No List?
|
||||
if(!islist(M.antag_datums) || M.antag_datums.len == 0)
|
||||
return FALSE
|
||||
// Does even ONE antag appear in this mind that isn't in the list? Then FAIL!
|
||||
for(var/datum/antagonist/antag_datum in M.antag_datums)
|
||||
if (!(antag_datum.type in vassal_allowed_antags)) // vassal_allowed_antags is a list stored in the game mode, above.
|
||||
//message_admins("DEBUG VASSAL: Found Invalid: [antag_datum] // [antag_datum.type]")
|
||||
return TRUE
|
||||
//message_admins("DEBUG VASSAL: Valid Antags! (total of [M.antag_datums.len])")
|
||||
// WHEN YOU DELETE THE ABOVE: Remove the 3 second timer on converting the vassal too.
|
||||
return FALSE
|
||||
|
||||
/datum/game_mode/proc/make_vassal(mob/living/target, datum/mind/creator)
|
||||
if (!can_make_vassal(target,creator))
|
||||
return FALSE
|
||||
// Make Vassal
|
||||
var/datum/antagonist/vassal/V = new (target.mind)
|
||||
var/datum/antagonist/bloodsucker/B = creator.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
V.master = B
|
||||
target.mind.add_antag_datum(V, V.master.get_team())
|
||||
// Update Bloodsucker Title (we're a daddy now)
|
||||
B.SelectTitle(am_fledgling = FALSE) // Only works if you have no title yet.
|
||||
// Log
|
||||
message_admins("[target] has become a Vassal, and is enslaved to [creator].")
|
||||
log_admin("[target] has become a Vassal, and is enslaved to [creator].")
|
||||
return TRUE
|
||||
|
||||
/datum/game_mode/proc/remove_vassal(datum/mind/vassal)
|
||||
vassal.remove_antag_datum(ANTAG_DATUM_VASSAL)
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
|
||||
/*
|
||||
// Called from game mode pre_setup()
|
||||
/datum/game_mode/proc/assign_monster_hunters(monster_count = 4, guaranteed_hunters = FALSE, list/datum/mind/exclude_from_hunter)
|
||||
|
||||
// Not all game modes GUARANTEE a hunter
|
||||
if (rand(0,2) == 0) // 50% of the time, we get fewer or NO Hunters
|
||||
if (!guaranteed_hunters)
|
||||
return
|
||||
else
|
||||
monster_count /= 2
|
||||
|
||||
var/list/no_hunter_jobs = list("AI","Cyborg")
|
||||
|
||||
// Set Restricted Jobs
|
||||
if(CONFIG_GET(flag/protect_roles_from_antagonist))
|
||||
no_hunter_jobs += list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
|
||||
|
||||
if(CONFIG_GET(flag/protect_assistant_from_antagonist))
|
||||
no_hunter_jobs += "Assistant"
|
||||
|
||||
// Find Valid Hunters
|
||||
var/list/datum/mind/hunter_candidates = get_players_for_role(ROLE_MONSTERHUNTER)
|
||||
|
||||
// Assign Hunters (as many as vamps, plus one)
|
||||
for(var/i = 1, i < monster_count, i++) // Start at 1 so we skip Hunters if there's only one sucker.
|
||||
if (!hunter_candidates.len)
|
||||
break
|
||||
// Assign Hunter
|
||||
var/datum/mind/hunter = pick(hunter_candidates)
|
||||
hunter_candidates.Remove(hunter) // Remove Either Way
|
||||
// Already Antag? Skip
|
||||
if (islist(exclude_from_hunter) && (locate(hunter) in exclude_from_hunter)) //if (islist(hunter.antag_datums) && hunter.antag_datums.len)
|
||||
i --
|
||||
continue
|
||||
// NOTE:
|
||||
vamphunters += hunter
|
||||
hunter.restricted_roles = no_hunter_jobs
|
||||
log_game("[hunter.key] (ckey) has been selected as a Hunter.")
|
||||
|
||||
// Called from game mode post_setup()
|
||||
/datum/game_mode/proc/finalize_monster_hunters(monster_count = 4)
|
||||
var/amEvil = TRUE // First hunter is always an evil boi
|
||||
for(var/datum/mind/hunter in vamphunters)
|
||||
var/datum/antagonist/vamphunter/A = new (hunter)
|
||||
A.bad_dude = amEvil
|
||||
hunter.add_antag_datum(A)
|
||||
amEvil = FALSE // Every other hunter is just a boring greytider
|
||||
*/
|
||||
@@ -265,6 +265,7 @@
|
||||
armor = list("melee" = 40, "bullet" = 40, "laser" = 50, "energy" = 35, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
max_temperature = 35000
|
||||
operation_req_access = list(ACCESS_SYNDICATE)
|
||||
internals_req_access = list(ACCESS_SYNDICATE)
|
||||
wreckage = /obj/structure/mecha_wreckage/honker/dark
|
||||
max_equip = 3
|
||||
spawn_tracked = FALSE
|
||||
|
||||
@@ -236,6 +236,9 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
|
||||
return rule.round_result()
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/dynamic/generate_report()
|
||||
return "Mysterious signals that demonstrate strange dynamics have been detected in your sector. Watch out for oddities."
|
||||
|
||||
/datum/game_mode/dynamic/send_intercept()
|
||||
. = "<b><i>Central Command Status Summary</i></b><hr>"
|
||||
switch(round(threat_level))
|
||||
|
||||
@@ -94,11 +94,8 @@
|
||||
var/list/possible_candidates = list()
|
||||
possible_candidates.Add(dead_players)
|
||||
possible_candidates.Add(list_observers)
|
||||
send_applications(possible_candidates)
|
||||
if(assigned.len > 0)
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
var/application_successful = send_applications(possible_candidates)
|
||||
return assigned.len > 0 && application_successful
|
||||
|
||||
/// This sends a poll to ghosts if they want to be a ghost spawn from a ruleset.
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/proc/send_applications(list/possible_volunteers = list())
|
||||
@@ -113,25 +110,18 @@
|
||||
if(!candidates || candidates.len <= required_candidates)
|
||||
message_admins("The ruleset [name] did not receive enough applications.")
|
||||
log_game("DYNAMIC: The ruleset [name] did not receive enough applications.")
|
||||
mode.refund_threat(cost)
|
||||
mode.log_threat("Rule [name] refunded [cost] (not receive enough applications)",verbose=TRUE)
|
||||
mode.executed_rules -= src
|
||||
return
|
||||
return FALSE
|
||||
|
||||
message_admins("[candidates.len] players volunteered for the ruleset [name].")
|
||||
log_game("DYNAMIC: [candidates.len] players volunteered for [name].")
|
||||
review_applications()
|
||||
return TRUE
|
||||
|
||||
/// Here is where you can check if your ghost applicants are valid for the ruleset.
|
||||
/// Called by send_applications().
|
||||
/datum/dynamic_ruleset/midround/from_ghosts/proc/review_applications()
|
||||
for (var/i = 1, i <= required_candidates, i++)
|
||||
if(candidates.len <= 0)
|
||||
if(i == 1)
|
||||
// We have found no candidates so far and we are out of applicants.
|
||||
mode.refund_threat(cost)
|
||||
mode.log_threat("Rule [name] refunded [cost] (all applications invalid)",verbose=TRUE)
|
||||
mode.executed_rules -= src
|
||||
break
|
||||
var/mob/applicant = pick(candidates)
|
||||
candidates -= applicant
|
||||
@@ -744,3 +734,31 @@
|
||||
|
||||
#undef ABDUCTOR_MAX_TEAMS
|
||||
#undef REVENANT_SPAWN_THRESHOLD
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// BLOODSUCKERS //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/datum/dynamic_ruleset/latejoin/bloodsucker
|
||||
name = "Bloodsucker Infiltrator"
|
||||
config_tag = "latejoin_bloodsucker"
|
||||
antag_datum = ANTAG_DATUM_BLOODSUCKER
|
||||
antag_flag = ROLE_TRAITOR
|
||||
restricted_roles = list("AI", "Cyborg")
|
||||
protected_roles = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Chief Engineer", "Chief Medical Officer", "Research Director", "Quartermaster")
|
||||
required_candidates = 1
|
||||
weight = 3
|
||||
cost = 10
|
||||
requirements = list(90,80,70,60,55,50,45,40,35,30)
|
||||
high_population_requirement = 30
|
||||
repeatable = TRUE
|
||||
|
||||
/datum/dynamic_ruleset/latejoin/bloodsucker/execute()
|
||||
var/mob/M = pick(candidates)
|
||||
assigned += M.mind
|
||||
M.mind.special_role = antag_flag
|
||||
if(mode.make_bloodsucker(M.mind))
|
||||
mode.bloodsuckers += M
|
||||
return TRUE
|
||||
|
||||
@@ -778,3 +778,42 @@
|
||||
var/ramp_up_final = CLAMP(round(meteorminutes/rampupdelta), 1, 10)
|
||||
|
||||
spawn_meteors(ramp_up_final, wavetype)
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// //
|
||||
// BLOODSUCKERS //
|
||||
// //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
/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")
|
||||
restricted_roles = list("Cyborg", "AI")
|
||||
required_candidates = 1
|
||||
weight = 2
|
||||
cost = 15
|
||||
scaling_cost = 10
|
||||
requirements = list(90,80,70,60,50,50,50,50,50,50)
|
||||
high_population_requirement = 50
|
||||
antag_cap = list(1,1,1,1,1,2,2,2,2,2)
|
||||
|
||||
/datum/dynamic_ruleset/roundstart/bloodsucker/pre_execute()
|
||||
var/num_bloodsuckers = antag_cap[indice_pop] * (scaled_times + 1)
|
||||
for (var/i = 1 to num_bloodsuckers)
|
||||
var/mob/M = pick_n_take(candidates)
|
||||
assigned += M.mind
|
||||
M.mind.special_role = ROLE_BLOODSUCKER
|
||||
M.mind.restricted_roles = restricted_roles
|
||||
return TRUE
|
||||
|
||||
/datum/dynamic_ruleset/roundstart/bloodsucker/execute()
|
||||
mode.check_start_sunlight()
|
||||
for(var/datum/mind/M in assigned)
|
||||
if(mode.make_bloodsucker(M))
|
||||
mode.bloodsuckers += M
|
||||
return TRUE
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
|
||||
///Everyone should now be on the station and have their normal gear. This is the place to give the special roles extra things
|
||||
/datum/game_mode/proc/post_setup(report) //Gamemodes can override the intercept report. Passing TRUE as the argument will force a report.
|
||||
//finalize_monster_hunters() Disabled for now
|
||||
if(!report)
|
||||
report = !CONFIG_GET(flag/no_intercept_report)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/display_roundstart_logout_report), ROUNDSTART_LOGOUT_REPORT_TIME)
|
||||
@@ -305,48 +306,88 @@
|
||||
// The odds become:
|
||||
// Player A: 150 / 250 = 0.6 = 60%
|
||||
// Player B: 100 / 250 = 0.4 = 40%
|
||||
/datum/game_mode/proc/antag_pick(list/datum/candidates)
|
||||
|
||||
//Use return list if you want a list, with the arg being the number you want returned.
|
||||
//WARNING: THIS PROC DOES NOT TAKE INTO ACCOUNT WHAT SSPersistence ALREADY HAS FOR "ADJUST ANTAG REP". If this is used more than once
|
||||
//and the person rolls more than once, they will not get even more deduction!
|
||||
//More efficient if you use return list instead of calling this multiple times
|
||||
//fail_default_pick makes it use pick() instead of antag rep if it can't find anyone
|
||||
//allow_zero_if_insufficient allows it to pick people with zero rep if there isn't enough antags
|
||||
/datum/game_mode/proc/antag_pick(list/datum/mind/candidates, return_list = FALSE, fail_default_pick = TRUE, allow_zero_if_insufficient = TRUE)
|
||||
if(!CONFIG_GET(flag/use_antag_rep)) // || candidates.len <= 1)
|
||||
return pick(candidates)
|
||||
|
||||
// Tickets start at 100
|
||||
var/DEFAULT_ANTAG_TICKETS = CONFIG_GET(number/default_antag_tickets)
|
||||
//whoever named the config entries is a bad person :(
|
||||
|
||||
// You may use up to 100 extra tickets (double your odds)
|
||||
var/MAX_TICKETS_PER_ROLL = CONFIG_GET(number/max_tickets_per_roll)
|
||||
|
||||
|
||||
var/total_tickets = 0
|
||||
|
||||
MAX_TICKETS_PER_ROLL += DEFAULT_ANTAG_TICKETS
|
||||
|
||||
var/p_ckey
|
||||
var/p_rep
|
||||
|
||||
for(var/datum/mind/mind in candidates)
|
||||
p_ckey = ckey(mind.key)
|
||||
total_tickets += min(SSpersistence.antag_rep[p_ckey] + DEFAULT_ANTAG_TICKETS, MAX_TICKETS_PER_ROLL)
|
||||
|
||||
var/antag_select = rand(1,total_tickets)
|
||||
var/current = 1
|
||||
|
||||
for(var/datum/mind/mind in candidates)
|
||||
p_ckey = ckey(mind.key)
|
||||
p_rep = SSpersistence.antag_rep[p_ckey]
|
||||
|
||||
var/previous = current
|
||||
var/spend = min(p_rep + DEFAULT_ANTAG_TICKETS, MAX_TICKETS_PER_ROLL)
|
||||
current += spend
|
||||
|
||||
if(antag_select >= previous && antag_select <= (current-1))
|
||||
SSpersistence.antag_rep_change[p_ckey] = -(spend - DEFAULT_ANTAG_TICKETS)
|
||||
|
||||
// WARNING("AR_DEBUG: Player [mind.key] won spending [spend] tickets from starting value [SSpersistence.antag_rep[p_ckey]]")
|
||||
|
||||
return mind
|
||||
|
||||
WARNING("Something has gone terribly wrong. /datum/game_mode/proc/antag_pick failed to select a candidate. Falling back to pick()")
|
||||
return pick(candidates)
|
||||
//Tickets you get for free
|
||||
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
|
||||
var/list/datum/mind/insufficient = list() //who got cucked out of an antag roll due to not having *any* tickets
|
||||
for(var/datum/mind/M in candidates)
|
||||
var/mind_ckey = ckey(M.key)
|
||||
var/can_spend = min(prev_tickets[mind_ckey], additional_tickets) //they can only spend up to config/max_tickets_per_roll
|
||||
var/amount = can_spend + free_tickets //but they get config/default_antag_tickets for free
|
||||
if(amount <= 0) //if they don't have any
|
||||
insufficient += M //too bad!
|
||||
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))
|
||||
ckey = pickweight(curr_tickets)
|
||||
SSpersistence.antag_rep_change[ckey] = -(curr_tickets[ckey] - free_tickets) //deduct what they spent
|
||||
var/mind = ckey_to_mind[ckey] || (allow_zero_if_insufficient? pick(insufficient) : null) //we want their mind
|
||||
if(!mind) //no mind
|
||||
var/warning = "WARNING: No antagonists were successfully picked by /datum/gamemode/proc/antag_pick()![fail_default_pick? " Defaulting to pick()!":""]"
|
||||
message_admins(warning)
|
||||
log_game(warning)
|
||||
if(fail_default_pick)
|
||||
mind = pick(candidates)
|
||||
return mind
|
||||
else //the far more efficient and proper use of this, to get a list
|
||||
var/list/rolled = list()
|
||||
var/list/spend_tickets = list()
|
||||
for(var/i in 1 to return_list)
|
||||
if(!length(curr_tickets)) //ah heck, we're out of candidates..
|
||||
break
|
||||
var/ckey = pickweight(curr_tickets) //pick
|
||||
rolled += ckey //add
|
||||
spend_tickets[ckey] = curr_tickets[ckey] - free_tickets
|
||||
curr_tickets -= ckey //don't roll them again
|
||||
var/missing = return_list - length(rolled)
|
||||
var/list/add
|
||||
if((missing > 0) && allow_zero_if_insufficient) //need more..
|
||||
for(var/i in 1 to missing)
|
||||
if(!length(insufficient))
|
||||
break //still not enough
|
||||
var/datum/mind/M = pick_n_take(insufficient)
|
||||
add += M
|
||||
if(!length(rolled) && !length(add)) //if no one could normally roll AND no one can zero roll
|
||||
var/warning = "WARNING: No antagonists were successfully picked by /datum/gamemode/proc/antag_pick()![fail_default_pick? " Defaulting to pick()!":""]"
|
||||
message_admins(warning)
|
||||
log_game(warning)
|
||||
var/list/failed = list()
|
||||
if(fail_default_pick)
|
||||
var/list/C = candidates.Copy()
|
||||
for(var/i in 1 to return_list)
|
||||
if(!length(C))
|
||||
break
|
||||
failed += pick_n_take(C)
|
||||
return failed //Wew, no one qualified!
|
||||
for(var/i in 1 to length(rolled))
|
||||
var/ckey = rolled[i]
|
||||
SSpersistence.antag_rep_change[ckey] = -(spend_tickets[ckey]) //deduct what all of the folks who rolled spent
|
||||
rolled[i] = ckey_to_mind[ckey] //whoever called us wants minds, not ckeys
|
||||
if(add)
|
||||
rolled += add
|
||||
return rolled
|
||||
|
||||
/datum/game_mode/proc/get_players_for_role(role)
|
||||
var/list/players = list()
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
// update the invisibility and icon
|
||||
/obj/machinery/bluespace_beacon/hide(intact)
|
||||
invisibility = intact ? INVISIBILITY_MAXIMUM : 0
|
||||
updateicon()
|
||||
update_icon()
|
||||
|
||||
// update the icon_state
|
||||
/obj/machinery/bluespace_beacon/proc/updateicon()
|
||||
/obj/machinery/bluespace_beacon/update_icon()
|
||||
var/state="floor_beacon"
|
||||
|
||||
if(invisibility)
|
||||
@@ -45,4 +45,4 @@
|
||||
else if (Beacon.loc != loc)
|
||||
Beacon.forceMove(loc)
|
||||
|
||||
updateicon()
|
||||
update_icon()
|
||||
|
||||
@@ -181,12 +181,14 @@
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/sleeper/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !issilicon(user)))
|
||||
return
|
||||
if(state_open)
|
||||
close_machine()
|
||||
else
|
||||
open_machine()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/sleeper/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -181,8 +181,9 @@ Class Procs:
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
L.update_canmove()
|
||||
SEND_SIGNAL(src, COMSIG_MACHINE_EJECT_OCCUPANT, occupant)
|
||||
occupant = null
|
||||
if(occupant)
|
||||
SEND_SIGNAL(src, COMSIG_MACHINE_EJECT_OCCUPANT, occupant)
|
||||
occupant = null
|
||||
|
||||
/obj/machinery/proc/can_be_occupant(atom/movable/am)
|
||||
return occupant_typecache ? is_type_in_typecache(am, occupant_typecache) : isliving(am)
|
||||
|
||||
@@ -132,8 +132,8 @@
|
||||
..()
|
||||
if(!user.canUseTopic(src))
|
||||
return
|
||||
else
|
||||
eject_part(user)
|
||||
eject_part(user)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/aug_manipulator/power_change()
|
||||
..()
|
||||
|
||||
@@ -28,13 +28,6 @@
|
||||
QDEL_NULL(outbag)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/bloodbankgen/contents_explosion(severity, target)
|
||||
..()
|
||||
if(bag)
|
||||
bag.ex_act(severity, target)
|
||||
if(outbag)
|
||||
outbag.ex_act(severity, target)
|
||||
|
||||
/obj/machinery/bloodbankgen/handle_atom_del(atom/A)
|
||||
..()
|
||||
if(A == bag)
|
||||
@@ -188,7 +181,7 @@
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
return ..()
|
||||
|
||||
if(default_deconstruction_screwdriver(user, "bloodbank-off", "bloodbank-off", O))
|
||||
if(default_deconstruction_screwdriver(user, "bloodbank-off", "bloodbank-off", O) || default_unfasten_wrench(user, O, 20) == SUCCESSFUL_UNFASTEN)
|
||||
if(bag)
|
||||
var/obj/item/reagent_containers/blood/B = bag
|
||||
B.forceMove(drop_location())
|
||||
@@ -204,31 +197,37 @@
|
||||
return
|
||||
|
||||
if(istype(O, /obj/item/reagent_containers/blood))
|
||||
. = 1 //no afterattack
|
||||
. = TRUE //no afterattack
|
||||
var/msg = ""
|
||||
if(!panel_open)
|
||||
if(bag && outbag)
|
||||
to_chat(user, "<span class='warning'>This machine already has bags attached.</span>")
|
||||
|
||||
if(!bag && !outbag)
|
||||
var/choice = alert(user, "Choose where to place [O]", "", "Input", "Cancel", "Output")
|
||||
switch(choice)
|
||||
if("Cancel")
|
||||
return FALSE
|
||||
if("Input")
|
||||
attachinput(O, user)
|
||||
if("Output")
|
||||
attachoutput(O, user)
|
||||
else if(!bag)
|
||||
attachinput(O, user)
|
||||
else if(!outbag)
|
||||
attachoutput(O, user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Close the maintenance panel first.</span>")
|
||||
return
|
||||
. += "Close the maintenance panel"
|
||||
if(!anchored)
|
||||
. += "[msg ? " and a" : "A"]nchor its bolts"
|
||||
if(length(msg))
|
||||
to_chat(user, "<span class='warning'>[msg] first.</span>")
|
||||
return
|
||||
if(bag && outbag)
|
||||
to_chat(user, "<span class='warning'>This machine already has bags attached.</span>")
|
||||
|
||||
if(!bag && !outbag)
|
||||
var/choice = alert(user, "Choose where to place [O]", "", "Input", "Cancel", "Output")
|
||||
switch(choice)
|
||||
if("Cancel")
|
||||
return FALSE
|
||||
if("Input")
|
||||
attachinput(O, user)
|
||||
if("Output")
|
||||
attachoutput(O, user)
|
||||
else if(!bag)
|
||||
attachinput(O, user)
|
||||
else if(!outbag)
|
||||
attachoutput(O, user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You cannot put this in [src]!</span>")
|
||||
|
||||
/obj/machinery/bloodbankgen/is_operational()
|
||||
return ..() && anchored
|
||||
|
||||
/obj/machinery/bloodbankgen/ui_interact(mob/user)
|
||||
. = ..()
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
var/chargelevel = -1
|
||||
var/charge_rate = 500
|
||||
|
||||
/obj/machinery/cell_charger/proc/updateicon()
|
||||
/obj/machinery/cell_charger/update_icon()
|
||||
cut_overlays()
|
||||
if(charging)
|
||||
add_overlay(image(charging.icon, charging.icon_state))
|
||||
@@ -53,7 +53,7 @@
|
||||
charging = W
|
||||
user.visible_message("[user] inserts a cell into [src].", "<span class='notice'>You insert a cell into [src].</span>")
|
||||
chargelevel = -1
|
||||
updateicon()
|
||||
update_icon()
|
||||
else
|
||||
if(!charging && default_deconstruction_screwdriver(user, icon_state, icon_state, W))
|
||||
return
|
||||
@@ -76,7 +76,7 @@
|
||||
charging.update_icon()
|
||||
charging = null
|
||||
chargelevel = -1
|
||||
updateicon()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/cell_charger/attack_hand(mob/user)
|
||||
. = ..()
|
||||
@@ -127,4 +127,4 @@
|
||||
use_power(charge_rate)
|
||||
charging.give(charge_rate) //this is 2558, efficient batteries exist
|
||||
|
||||
updateicon()
|
||||
update_icon()
|
||||
|
||||
@@ -133,12 +133,13 @@
|
||||
..()
|
||||
|
||||
/obj/structure/frame/computer/AltClick(mob/user)
|
||||
..()
|
||||
. = ..()
|
||||
if(!isliving(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
|
||||
if(anchored)
|
||||
to_chat(usr, "<span class='warning'>You must unwrench [src] before rotating it!</span>")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
setDir(turn(dir, -90))
|
||||
return TRUE
|
||||
|
||||
@@ -170,19 +170,19 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/card/AltClick(mob/user)
|
||||
..()
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !issilicon(user)) || !is_operational())
|
||||
return
|
||||
if(inserted_modify_id)
|
||||
if(id_eject(user, inserted_modify_id))
|
||||
inserted_modify_id = null
|
||||
updateUsrDialog()
|
||||
return
|
||||
return TRUE
|
||||
if(inserted_scan_id)
|
||||
if(id_eject(user, inserted_scan_id))
|
||||
inserted_scan_id = null
|
||||
updateUsrDialog()
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/card/ui_interact(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -74,8 +74,8 @@
|
||||
t += "<A href='?src=[REF(src)];lowery=1;raisex=1;pad=[current_pad]'>O</A><BR>"//down-right
|
||||
t += "<BR>"
|
||||
t += "<div class='statusDisplay'>Current offset:</div><BR>"
|
||||
t += "<div class='statusDisplay'>[abs(pad.y_offset)] [pad.y_offset > 0 ? "N":"S"]</div><BR>"
|
||||
t += "<div class='statusDisplay'>[abs(pad.x_offset)] [pad.x_offset > 0 ? "E":"W"]</div><BR>"
|
||||
t += "<div class='statusDisplay'>[abs(pad.y_offset)] [pad.y_offset > 0 ? "N":"S"] <a href='?src=[REF(src)];sety=1;pad=[current_pad]'>\[SET\]</a></div><BR>"
|
||||
t += "<div class='statusDisplay'>[abs(pad.x_offset)] [pad.x_offset > 0 ? "E":"W"] <a href='?src=[REF(src)];setx=1;pad=[current_pad]'>\[SET\]</a></div><BR>"
|
||||
|
||||
t += "<BR><A href='?src=[REF(src)];launch=1;pad=[current_pad]'>Launch</A>"
|
||||
t += " <A href='?src=[REF(src)];pull=1;pad=[current_pad]'>Pull</A>"
|
||||
@@ -132,6 +132,16 @@
|
||||
if(!new_name)
|
||||
return
|
||||
pad.display_name = new_name
|
||||
|
||||
if(href_list["setx"])
|
||||
var/newx = input(usr, "Input new x offset", pad.display_name, pad.x_offset) as null|num
|
||||
if(!isnull(newx))
|
||||
pad.x_offset = CLAMP(newx, -pad.range, pad.range)
|
||||
|
||||
if(href_list["sety"])
|
||||
var/newy = input(usr, "Input new y offset", pad.display_name, pad.y_offset) as null|num
|
||||
if(!isnull(newy))
|
||||
pad.y_offset = CLAMP(newy, -pad.range, pad.range)
|
||||
|
||||
if(href_list["remove"])
|
||||
if(usr && alert(usr, "Are you sure?", "Remove Launchpad", "I'm Sure", "Abort") != "Abort")
|
||||
@@ -145,4 +155,4 @@
|
||||
sending = FALSE
|
||||
teleport(usr, pad)
|
||||
|
||||
updateDialog()
|
||||
updateDialog()
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
if(contained_id)
|
||||
contained_id.forceMove(get_turf(src))
|
||||
return ..()
|
||||
|
||||
|
||||
|
||||
/obj/machinery/computer/prisoner/examine(mob/user)
|
||||
. = ..()
|
||||
@@ -15,8 +15,9 @@
|
||||
|
||||
|
||||
/obj/machinery/computer/prisoner/AltClick(mob/user)
|
||||
..()
|
||||
id_eject(user)
|
||||
return ..()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/prisoner/proc/id_insert(mob/user, obj/item/card/id/prisoner/P)
|
||||
if(istype(P))
|
||||
|
||||
@@ -115,8 +115,10 @@
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/defibrillator_mount/AltClick(mob/living/carbon/user)
|
||||
. = ..()
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
. = TRUE
|
||||
if(!defib)
|
||||
to_chat(user, "<span class='warning'>It'd be hard to remove a defib unit from a mount that has none.</span>")
|
||||
return
|
||||
|
||||
@@ -153,9 +153,11 @@
|
||||
. += "<span class='notice'>Alt-click to toggle modes.</span>"
|
||||
|
||||
/obj/item/grenade/barrier/AltClick(mob/living/carbon/user)
|
||||
. = ..()
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
toggle_mode(user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/grenade/barrier/proc/toggle_mode(mob/user)
|
||||
switch(mode)
|
||||
|
||||
@@ -97,8 +97,10 @@
|
||||
do_the_dishes(TRUE)
|
||||
|
||||
/obj/machinery/dish_drive/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(user.canUseTopic(src, !issilicon(user)))
|
||||
do_the_dishes(TRUE)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/dish_drive/proc/do_the_dishes(manual)
|
||||
if(!contents.len)
|
||||
|
||||
@@ -164,9 +164,11 @@
|
||||
toggle_open(user)
|
||||
|
||||
/obj/machinery/dna_scannernew/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !issilicon(user)))
|
||||
return
|
||||
interact(user)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/dna_scannernew/MouseDrop_T(mob/target, mob/user)
|
||||
if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
if(voice_activated)
|
||||
flags_1 |= HEAR_1
|
||||
|
||||
/obj/machinery/door/password/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
/obj/machinery/door/password/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
|
||||
. = ..()
|
||||
if(!density || !voice_activated || radio_freq)
|
||||
return
|
||||
|
||||
@@ -51,10 +51,12 @@
|
||||
open_machine()
|
||||
|
||||
/obj/machinery/harvester/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(harvesting || !user || !isliving(user) || state_open)
|
||||
return
|
||||
if(can_harvest())
|
||||
start_harvest()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/harvester/proc/can_harvest()
|
||||
if(!powered(EQUIP) || state_open || !occupant || !iscarbon(occupant))
|
||||
|
||||
@@ -408,7 +408,7 @@ GLOBAL_LIST_EMPTY(network_holopads)
|
||||
|
||||
/*This is the proc for special two-way communication between AI and holopad/people talking near holopad.
|
||||
For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
|
||||
. = ..()
|
||||
if(speaker && LAZYLEN(masters) && !radio_freq)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios.
|
||||
for(var/mob/living/silicon/ai/master in masters)
|
||||
@@ -418,7 +418,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
if(HC.connected_holopad == src && speaker != HC.hologram)
|
||||
HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
|
||||
HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode, source)
|
||||
|
||||
if(outgoing_call && speaker == outgoing_call.user)
|
||||
outgoing_call.hologram.say(raw_message)
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
name = "light switch ([area.name])"
|
||||
|
||||
on = area.lightswitch
|
||||
updateicon()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/light_switch/proc/updateicon()
|
||||
/obj/machinery/light_switch/update_icon()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "light-p"
|
||||
else
|
||||
@@ -41,11 +41,11 @@
|
||||
on = !on
|
||||
|
||||
area.lightswitch = on
|
||||
area.updateicon()
|
||||
area.update_icon()
|
||||
|
||||
for(var/obj/machinery/light_switch/L in area)
|
||||
L.on = on
|
||||
L.updateicon()
|
||||
L.update_icon()
|
||||
|
||||
area.power_change()
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
else
|
||||
stat |= NOPOWER
|
||||
|
||||
updateicon()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/light_switch/emp_act(severity)
|
||||
. = ..()
|
||||
|
||||
@@ -46,10 +46,10 @@
|
||||
// update the invisibility and icon
|
||||
/obj/machinery/magnetic_module/hide(intact)
|
||||
invisibility = intact ? INVISIBILITY_MAXIMUM : 0
|
||||
updateicon()
|
||||
update_icon()
|
||||
|
||||
// update the icon_state
|
||||
/obj/machinery/magnetic_module/proc/updateicon()
|
||||
/obj/machinery/magnetic_module/update_icon()
|
||||
var/state="floor_magnet"
|
||||
var/onstate=""
|
||||
if(!on)
|
||||
@@ -161,7 +161,7 @@
|
||||
else
|
||||
use_power = NO_POWER_USE
|
||||
|
||||
updateicon()
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/machinery/magnetic_module/proc/magnetic_process() // proc that actually does the magneting
|
||||
|
||||
@@ -72,10 +72,10 @@
|
||||
// hide the object if turf is intact
|
||||
/obj/machinery/navbeacon/hide(intact)
|
||||
invisibility = intact ? INVISIBILITY_MAXIMUM : 0
|
||||
updateicon()
|
||||
update_icon()
|
||||
|
||||
// update the icon_state
|
||||
/obj/machinery/navbeacon/proc/updateicon()
|
||||
/obj/machinery/navbeacon/update_icon()
|
||||
var/state="navbeacon[open]"
|
||||
|
||||
if(invisibility)
|
||||
@@ -94,7 +94,7 @@
|
||||
|
||||
user.visible_message("[user] [open ? "opens" : "closes"] the beacon's cover.", "<span class='notice'>You [open ? "open" : "close"] the beacon's cover.</span>")
|
||||
|
||||
updateicon()
|
||||
update_icon()
|
||||
|
||||
else if (istype(I, /obj/item/card/id)||istype(I, /obj/item/pda))
|
||||
if(open)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
. += "<span class='notice'>Alt-click it to start a wash cycle.</span>"
|
||||
|
||||
/obj/machinery/washing_machine/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src))
|
||||
return
|
||||
|
||||
@@ -24,11 +25,11 @@
|
||||
|
||||
if(state_open)
|
||||
to_chat(user, "<span class='notice'>Close the door first</span>")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
if(bloody_mess)
|
||||
to_chat(user, "<span class='warning'>[src] must be cleaned up first.</span>")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
if(has_corgi)
|
||||
bloody_mess = 1
|
||||
@@ -37,6 +38,7 @@
|
||||
update_icon()
|
||||
addtimer(CALLBACK(src, .proc/wash_cycle), 200)
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/washing_machine/process()
|
||||
if (!busy)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
max_temperature = 35000
|
||||
leg_overload_coeff = 100
|
||||
operation_req_access = list(ACCESS_SYNDICATE)
|
||||
internals_req_access = list(ACCESS_SYNDICATE)
|
||||
wreckage = /obj/structure/mecha_wreckage/gygax/dark
|
||||
max_equip = 4
|
||||
spawn_tracked = FALSE
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
max_temperature = 25000
|
||||
infra_luminosity = 5
|
||||
operation_req_access = list(ACCESS_THEATRE)
|
||||
internals_req_access = list(ACCESS_THEATRE, ACCESS_ROBOTICS)
|
||||
wreckage = /obj/structure/mecha_wreckage/honker
|
||||
add_req_access = 0
|
||||
max_equip = 3
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
infra_luminosity = 3
|
||||
operation_req_access = list(ACCESS_CENT_SPECOPS)
|
||||
internals_req_access = list(ACCESS_CENT_SPECOPS, ACCESS_ROBOTICS)
|
||||
wreckage = /obj/structure/mecha_wreckage/marauder
|
||||
add_req_access = 0
|
||||
internal_damage_threshold = 25
|
||||
@@ -46,6 +47,7 @@
|
||||
name = "\improper Seraph"
|
||||
icon_state = "seraph"
|
||||
operation_req_access = list(ACCESS_CENT_SPECOPS)
|
||||
internals_req_access = list(ACCESS_CENT_SPECOPS, ACCESS_ROBOTICS)
|
||||
step_in = 3
|
||||
max_integrity = 550
|
||||
wreckage = /obj/structure/mecha_wreckage/seraph
|
||||
@@ -72,6 +74,7 @@
|
||||
name = "\improper Mauler"
|
||||
icon_state = "mauler"
|
||||
operation_req_access = list(ACCESS_SYNDICATE)
|
||||
internals_req_access = list(ACCESS_SYNDICATE)
|
||||
wreckage = /obj/structure/mecha_wreckage/mauler
|
||||
max_equip = 5
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
layer = ABOVE_MOB_LAYER
|
||||
breach_time = 100 //ten seconds till all goes to shit
|
||||
recharge_rate = 100
|
||||
internals_req_access = list()
|
||||
add_req_access = 0
|
||||
wreckage = /obj/structure/mecha_wreckage/durand/neovgre
|
||||
spawn_tracked = FALSE
|
||||
|
||||
@@ -47,7 +49,7 @@
|
||||
for(var/mob/M in src)
|
||||
to_chat(M, "<span class='brass'>You are consumed by the fires raging within Neovgre...</span>")
|
||||
M.dust()
|
||||
playsound(src, 'sound/magic/lightning_chargeup.ogg', 100, 0)
|
||||
playsound(src, 'sound/effects/neovgre_exploding.ogg', 100, 0)
|
||||
src.visible_message("<span class = 'userdanger'>The reactor has gone critical, its going to blow!</span>")
|
||||
addtimer(CALLBACK(src,.proc/go_critical),breach_time)
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
max_temperature = 15000
|
||||
wreckage = /obj/structure/mecha_wreckage/reticence
|
||||
operation_req_access = list(ACCESS_THEATRE)
|
||||
internals_req_access = list(ACCESS_THEATRE, ACCESS_ROBOTICS)
|
||||
add_req_access = 0
|
||||
internal_damage_threshold = 25
|
||||
max_equip = 2
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
var/internal_damage = 0 //contains bitflags
|
||||
|
||||
var/list/operation_req_access = list()//required access level for mecha operation
|
||||
var/list/internals_req_access = list(ACCESS_ENGINE,ACCESS_ROBOTICS)//REQUIRED ACCESS LEVEL TO OPEN CELL COMPARTMENT
|
||||
var/list/internals_req_access = list(ACCESS_ROBOTICS)//REQUIRED ACCESS LEVEL TO OPEN CELL COMPARTMENT
|
||||
|
||||
var/wreckage
|
||||
|
||||
@@ -409,7 +409,7 @@
|
||||
/obj/mecha/proc/drop_item()//Derpfix, but may be useful in future for engineering exosuits.
|
||||
return
|
||||
|
||||
/obj/mecha/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
/obj/mecha/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
|
||||
. = ..()
|
||||
if(speaker == occupant)
|
||||
if(radio.broadcasting)
|
||||
|
||||
@@ -138,8 +138,10 @@
|
||||
chassis.toggle_strafe()
|
||||
|
||||
/obj/mecha/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if((user == occupant) && user.canUseTopic(src))
|
||||
toggle_strafe()
|
||||
return TRUE
|
||||
|
||||
/obj/mecha/proc/toggle_strafe()
|
||||
strafe = !strafe
|
||||
|
||||
@@ -442,3 +442,10 @@
|
||||
animate(src, alpha = 0, transform = skew, time = duration)
|
||||
else
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
/obj/effect/temp_visual/slugboom
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "slugboom"
|
||||
randomdir = FALSE
|
||||
duration = 30
|
||||
pixel_x = -24
|
||||
@@ -36,3 +36,7 @@
|
||||
|
||||
/obj/effect/projectile/impact/wormhole
|
||||
icon_state = "wormhole_g"
|
||||
|
||||
/obj/effect/projectile/impact/laser/wavemotion
|
||||
name = "particle impact"
|
||||
icon_state = "impact_wavemotion"
|
||||
@@ -28,3 +28,7 @@
|
||||
|
||||
/obj/effect/projectile/muzzle/wormhole
|
||||
icon_state = "wormhole_g"
|
||||
|
||||
/obj/effect/projectile/muzzle/laser/wavemotion
|
||||
name = "particle backblast"
|
||||
icon_state = "muzzle_wavemotion"
|
||||
@@ -66,3 +66,7 @@
|
||||
|
||||
/obj/effect/projectile/tracer/wormhole
|
||||
icon_state = "wormhole_g"
|
||||
|
||||
/obj/effect/projectile/tracer/laser/wavemotion
|
||||
name = "particle trail"
|
||||
icon_state = "tracer_wavemotion"
|
||||
|
||||
@@ -133,15 +133,14 @@ RLD
|
||||
if(!(A in range(custom_range, get_turf(user))))
|
||||
to_chat(user, "<span class='warning'>The \'Out of Range\' light on [src] blinks red.</span>")
|
||||
return FALSE
|
||||
else
|
||||
return TRUE
|
||||
|
||||
/obj/item/construction/proc/prox_check(proximity)
|
||||
if(proximity)
|
||||
return TRUE
|
||||
else
|
||||
var/view_range = user.client ? user.client.view : world.view
|
||||
//if user can't be seen from A (only checks surroundings' opaqueness) and can't see A.
|
||||
//jarring, but it should stop people from targetting atoms they can't see...
|
||||
//excluding darkness, to allow RLD to be used to light pitch black dark areas.
|
||||
if(!((user in view(view_range, A)) || (user in viewers(view_range, A))))
|
||||
to_chat(user, "<span class='warning'>You focus, pointing \the [src] at whatever outside your field of vision in the given direction... to no avail.</span>")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/item/construction/rcd
|
||||
name = "rapid-construction-device (RCD)"
|
||||
@@ -523,7 +522,12 @@ RLD
|
||||
|
||||
/obj/item/construction/rcd/afterattack(atom/A, mob/user, proximity)
|
||||
. = ..()
|
||||
if(!prox_check(proximity))
|
||||
if(!proximity)
|
||||
if(!ranged || !range_check(A,user)) //early return not-in-range sanity.
|
||||
return
|
||||
if(target_check(A,user))
|
||||
user.Beam(A,icon_state="rped_upgrade",time=30)
|
||||
rcd_create(A,user)
|
||||
return
|
||||
rcd_create(A, user)
|
||||
|
||||
@@ -635,6 +639,7 @@ RLD
|
||||
max_matter = INFINITY
|
||||
matter = INFINITY
|
||||
upgrade = TRUE
|
||||
ranged = TRUE
|
||||
|
||||
// Ranged RCD
|
||||
|
||||
@@ -650,20 +655,10 @@ RLD
|
||||
item_state = "oldrcd"
|
||||
has_ammobar = FALSE
|
||||
|
||||
/obj/item/construction/rcd/arcd/afterattack(atom/A, mob/user)
|
||||
. = ..()
|
||||
if(!range_check(A,user))
|
||||
return
|
||||
if(target_check(A,user))
|
||||
user.Beam(A,icon_state="rped_upgrade",time=30)
|
||||
rcd_create(A,user)
|
||||
|
||||
|
||||
|
||||
// RAPID LIGHTING DEVICE
|
||||
|
||||
|
||||
|
||||
/obj/item/construction/rld
|
||||
name = "rapid-light-device (RLD)"
|
||||
desc = "A device used to rapidly provide lighting sources to an area. Reload with metal, plasteel, glass or compressed matter cartridges."
|
||||
|
||||
@@ -517,16 +517,17 @@ update_label("John Doe", "Clowny")
|
||||
return
|
||||
if(user.incapacitated() || !istype(user))
|
||||
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
|
||||
return
|
||||
return TRUE
|
||||
if(alert("Are you sure you want to recolor your id?", "Confirm Repaint", "Yes", "No") == "Yes")
|
||||
var/energy_color_input = input(usr,"","Choose Energy Color",id_color) as color|null
|
||||
if(!in_range(src, user) || !energy_color_input)
|
||||
return
|
||||
return TRUE
|
||||
if(user.incapacitated() || !istype(user))
|
||||
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
|
||||
return
|
||||
return TRUE
|
||||
id_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/item/card/id/knight/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -945,10 +945,12 @@
|
||||
to_chat(user, "<span class='notice'>You [suction ? "enable" : "disable"] the board's suction function.</span>")
|
||||
|
||||
/obj/item/circuitboard/machine/dish_drive/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(!user.Adjacent(src))
|
||||
return
|
||||
transmit = !transmit
|
||||
to_chat(user, "<span class='notice'>You [transmit ? "enable" : "disable"] the board's automatic disposal transmission.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/circuitboard/machine/stacking_unit_console
|
||||
name = "Stacking Machine Console (Machine Board)"
|
||||
|
||||
@@ -150,11 +150,13 @@
|
||||
ui.open()
|
||||
|
||||
/obj/item/toy/crayon/spraycan/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
if(has_cap)
|
||||
is_capped = !is_capped
|
||||
to_chat(user, "<span class='notice'>The cap on [src] is now [is_capped ? "on" : "off"].</span>")
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/item/toy/crayon/proc/staticDrawables()
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
var/pullshocksafely = FALSE //Dose the unit have the healdisk upgrade?
|
||||
var/primetime = 0 // is the defib faster
|
||||
var/timedeath = 10
|
||||
var/disarm_shock_time = 10
|
||||
var/always_emagged = FALSE
|
||||
|
||||
/obj/item/defibrillator/get_cell()
|
||||
return cell
|
||||
@@ -140,6 +142,7 @@
|
||||
|
||||
/obj/item/defibrillator/emag_act(mob/user)
|
||||
. = ..()
|
||||
always_emagged = TRUE
|
||||
safety = !safety
|
||||
to_chat(user, "<span class='warning'>You silently [safety ? "enable" : "disable"] [src]'s safety protocols with the cryptographic sequencer.</span>")
|
||||
return TRUE
|
||||
@@ -154,7 +157,7 @@
|
||||
safety = FALSE
|
||||
visible_message("<span class='notice'>[src] beeps: Safety protocols disabled!</span>")
|
||||
playsound(src, 'sound/machines/defib_saftyOff.ogg', 50, 0)
|
||||
else
|
||||
else if(!always_emagged)
|
||||
safety = TRUE
|
||||
visible_message("<span class='notice'>[src] beeps: Safety protocols enabled!</span>")
|
||||
playsound(src, 'sound/machines/defib_saftyOn.ogg', 50, 0)
|
||||
@@ -257,6 +260,8 @@
|
||||
desc = "A belt-equipped blood-red defibrillator that can be rapidly deployed. Does not have the restrictions or safeties of conventional defibrillators and can revive through space suits."
|
||||
combat = TRUE
|
||||
safety = FALSE
|
||||
always_emagged = TRUE
|
||||
disarm_shock_time = 0
|
||||
|
||||
/obj/item/defibrillator/compact/combat/loaded/Initialize()
|
||||
. = ..()
|
||||
@@ -293,6 +298,7 @@
|
||||
var/combat = FALSE //If it penetrates armor and gives additional functionality
|
||||
var/grab_ghost = FALSE
|
||||
var/tlimit = DEFIB_TIME_LIMIT * 10
|
||||
var/disarm_shock_time = 10
|
||||
|
||||
var/mob/listeningTo
|
||||
|
||||
@@ -467,7 +473,7 @@
|
||||
M.visible_message("<span class='danger'>[user] hastily places [src] on [M]'s chest!</span>", \
|
||||
"<span class='userdanger'>[user] hastily places [src] on [M]'s chest!</span>")
|
||||
busy = TRUE
|
||||
if(do_after(user, 10, target = M))
|
||||
if(do_after(user, isnull(defib?.disarm_shock_time)? disarm_shock_time : defib.disarm_shock_time, target = M))
|
||||
M.visible_message("<span class='danger'>[user] zaps [M] with [src]!</span>", \
|
||||
"<span class='userdanger'>[user] zaps [M] with [src]!</span>")
|
||||
M.adjustStaminaLoss(50)
|
||||
@@ -734,9 +740,8 @@
|
||||
/obj/item/disk/medical
|
||||
name = "Defibrillator Upgrade Disk"
|
||||
desc = "A blank upgrade disk, made for a defibrillator"
|
||||
icon = 'modular_citadel/icons/obj/defib_disks.dmi'
|
||||
icon_state = "upgrade_disk"
|
||||
item_state = "heal_disk"
|
||||
icon_state = "heal_disk"
|
||||
item_state = "defib_disk"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
/obj/item/disk/medical/defib_heal
|
||||
|
||||
@@ -828,14 +828,14 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
send_message(U,list(P))
|
||||
|
||||
/obj/item/pda/AltClick()
|
||||
..()
|
||||
|
||||
. = ..()
|
||||
if(id)
|
||||
remove_id()
|
||||
playsound(src, 'sound/machines/terminal_eject_disc.ogg', 50, 1)
|
||||
else
|
||||
remove_pen()
|
||||
playsound(src, 'sound/machines/button4.ogg', 50, 1)
|
||||
return TRUE
|
||||
|
||||
/obj/item/pda/CtrlClick()
|
||||
..()
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
. += "<span class='notice'>Can be used again to interrupt the effect early. The recharge time is the same as the time spent in desync.</span>"
|
||||
|
||||
/obj/item/desynchronizer/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
var/new_duration = input(user, "Set the duration (5-300):", "Desynchronizer", duration / 10) as null|num
|
||||
@@ -40,6 +41,7 @@
|
||||
new_duration = CLAMP(new_duration, 50, max_duration)
|
||||
duration = new_duration
|
||||
to_chat(user, "<span class='notice'>You set the duration to [DisplayTimeText(duration)].</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/desynchronizer/proc/desync(mob/living/user)
|
||||
if(sync_holder)
|
||||
|
||||
@@ -153,6 +153,7 @@
|
||||
playsound(loc, voracious ? 'sound/effects/splat.ogg' : 'sound/effects/bin_close.ogg', 50, 1)
|
||||
items_preserved.Cut()
|
||||
cleaning = FALSE
|
||||
patient = null
|
||||
if(hound)
|
||||
update_gut(hound)
|
||||
|
||||
@@ -525,5 +526,5 @@
|
||||
playsound(hound, 'sound/effects/bin_close.ogg', 80, 1)
|
||||
|
||||
/obj/item/dogborg/sleeper/K9/flavour
|
||||
name = "Mobile Sleeper"
|
||||
name = "Recreational Sleeper"
|
||||
desc = "A mounted, underslung sleeper, intended for holding willing occupants for leisurely purposes."
|
||||
@@ -182,14 +182,16 @@
|
||||
return ..()
|
||||
|
||||
/obj/item/geiger_counter/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE))
|
||||
return ..()
|
||||
return
|
||||
if(!scanning)
|
||||
to_chat(usr, "<span class='warning'>[src] must be on to reset its radiation level!</span>")
|
||||
return 0
|
||||
return TRUE
|
||||
radiation_count = 0
|
||||
to_chat(usr, "<span class='notice'>You flush [src]'s radiation counts, resetting it to normal.</span>")
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/item/geiger_counter/emag_act(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -45,9 +45,11 @@ GLOBAL_LIST_EMPTY(GPS_list)
|
||||
add_overlay("working")
|
||||
|
||||
/obj/item/gps/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
toggletracking(user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/gps/proc/toggletracking(mob/user)
|
||||
if(!user.canUseTopic(src, BE_CLOSE))
|
||||
|
||||
@@ -69,14 +69,9 @@
|
||||
if (!user.IsAdvancedToolUser())
|
||||
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
|
||||
return
|
||||
if(HAS_TRAIT(user, TRAIT_NOGUNS))
|
||||
if(HAS_TRAIT(user, TRAIT_CHUNKYFINGERS))
|
||||
to_chat(user, "<span class='warning'>Your fingers can't press the button!</span>")
|
||||
return
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.dna.check_mutation(HULK))
|
||||
to_chat(user, "<span class='warning'>Your fingers can't press the button!</span>")
|
||||
return
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
|
||||
@@ -18,12 +18,14 @@
|
||||
. += "<span class='notice'>Insert [src] into an active quantum pad to link it.</span>"
|
||||
|
||||
/obj/item/quantum_keycard/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start pressing [src]'s unlink button...</span>")
|
||||
if(do_after(user, 40, target = src))
|
||||
to_chat(user, "<span class='notice'>The keycard beeps twice and disconnects the quantum link.</span>")
|
||||
qpad = null
|
||||
return TRUE
|
||||
|
||||
/obj/item/quantum_keycard/update_icon()
|
||||
if(qpad)
|
||||
|
||||
@@ -326,8 +326,10 @@ GLOBAL_LIST_INIT(channel_tokens, list(
|
||||
secure_radio_connections[ch_name] = add_radio(src, GLOB.radiochannels[ch_name])
|
||||
|
||||
/obj/item/radio/headset/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(!istype(user) || !Adjacent(user) || user.incapacitated())
|
||||
return
|
||||
if (command)
|
||||
use_command = !use_command
|
||||
to_chat(user, "<span class='notice'>You toggle high-volume mode [use_command ? "on" : "off"].</span>")
|
||||
return TRUE
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
return TRUE
|
||||
|
||||
|
||||
/obj/item/radio/intercom/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, message_mode)
|
||||
/obj/item/radio/intercom/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
|
||||
. = ..()
|
||||
if (message_mode == MODE_INTERCOM)
|
||||
return // Avoid hearing the same thing twice
|
||||
|
||||
@@ -274,7 +274,7 @@
|
||||
signal.levels = list(T.z)
|
||||
signal.broadcast()
|
||||
|
||||
/obj/item/radio/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
/obj/item/radio/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
|
||||
. = ..()
|
||||
if(radio_freq || !broadcasting || get_dist(src, speaker) > canhear_range)
|
||||
return
|
||||
|
||||
@@ -412,7 +412,7 @@ SLIME SCANNER
|
||||
if(ishuman(C))
|
||||
if(H.bleed_rate)
|
||||
msg += "<span class='danger'>Subject is bleeding!</span>\n"
|
||||
var/blood_percent = round((C.blood_volume / (BLOOD_VOLUME_NORMAL * C.blood_ratio))*100)
|
||||
var/blood_percent = round((C.scan_blood_volume() / (BLOOD_VOLUME_NORMAL * C.blood_ratio))*100)
|
||||
var/blood_type = C.dna.blood_type
|
||||
if(blood_id != ("blood" || "jellyblood"))//special blood substance
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
|
||||
@@ -420,12 +420,12 @@ SLIME SCANNER
|
||||
blood_type = R.name
|
||||
else
|
||||
blood_type = blood_id
|
||||
if(C.blood_volume <= (BLOOD_VOLUME_SAFE*C.blood_ratio) && C.blood_volume > (BLOOD_VOLUME_OKAY*C.blood_ratio))
|
||||
msg += "<span class='danger'>LOW blood level [blood_percent] %, [C.blood_volume] cl,</span> <span class='info'>type: [blood_type]</span>\n"
|
||||
else if(C.blood_volume <= (BLOOD_VOLUME_OKAY*C.blood_ratio))
|
||||
msg += "<span class='danger'>CRITICAL blood level [blood_percent] %, [C.blood_volume] cl,</span> <span class='info'>type: [blood_type]</span>\n"
|
||||
if(C.scan_blood_volume() <= (BLOOD_VOLUME_SAFE*C.blood_ratio) && C.scan_blood_volume() > (BLOOD_VOLUME_OKAY*C.blood_ratio))
|
||||
msg += "<span class='danger'>LOW blood level [blood_percent] %, [C.scan_blood_volume()] cl,</span> <span class='info'>type: [blood_type]</span>\n"
|
||||
else if(C.scan_blood_volume() <= (BLOOD_VOLUME_OKAY*C.blood_ratio))
|
||||
msg += "<span class='danger'>CRITICAL blood level [blood_percent] %, [C.scan_blood_volume()] cl,</span> <span class='info'>type: [blood_type]</span>\n"
|
||||
else
|
||||
msg += "<span class='info'>Blood level [blood_percent] %, [C.blood_volume] cl, type: [blood_type]</span>\n"
|
||||
msg += "<span class='info'>Blood level [blood_percent] %, [C.scan_blood_volume()] cl, type: [blood_type]</span>\n"
|
||||
|
||||
var/cyberimp_detect
|
||||
for(var/obj/item/organ/cyberimp/CI in C.internal_organs)
|
||||
@@ -590,10 +590,10 @@ SLIME SCANNER
|
||||
to_chat(user, "<span class='info'>Temperature: [round(environment.temperature-T0C, 0.01)] °C ([round(environment.temperature, 0.01)] K)</span>")
|
||||
|
||||
/obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens
|
||||
..()
|
||||
. = ..()
|
||||
|
||||
if(user.canUseTopic(src))
|
||||
|
||||
. = TRUE
|
||||
if(cooldown)
|
||||
to_chat(user, "<span class='warning'>[src]'s barometer function is preparing itself.</span>")
|
||||
return
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
icon_state = "taperecorder_idle"
|
||||
|
||||
|
||||
/obj/item/taperecorder/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode)
|
||||
/obj/item/taperecorder/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode, atom/movable/source)
|
||||
. = ..()
|
||||
if(mytape && recording)
|
||||
mytape.timestamp += mytape.used_capacity
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
interact(user)
|
||||
return ..()
|
||||
|
||||
/obj/item/toy/eightball/haunted/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode)
|
||||
/obj/item/toy/eightball/haunted/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode, atom/movable/source)
|
||||
. = ..()
|
||||
last_message = raw_message
|
||||
|
||||
|
||||
@@ -138,11 +138,13 @@
|
||||
toggle_igniter(user)
|
||||
|
||||
/obj/item/flamethrower/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(ptank && isliving(user) && user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
user.put_in_hands(ptank)
|
||||
ptank = null
|
||||
to_chat(user, "<span class='notice'>You remove the plasma tank from [src]!</span>")
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/item/flamethrower/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -183,6 +183,23 @@
|
||||
explosion(user.loc, 1, 0, 2, 3, FALSE, FALSE, 2)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/book/granter/spell/nuclearfist
|
||||
spell = /obj/effect/proc_holder/spell/targeted/touch/nuclear_fist
|
||||
spellname = "nuclear fist"
|
||||
icon_state ="booknuclearfist"
|
||||
desc = "This book radiates confidence."
|
||||
remarks = list("Line them up....", ".. knock em' down...", "Dress in yellow for maximum effect... why?", "The energy comes from spinach... huh", "Work out for three years? No way!", "Oh I'll cast you a spell allright...", "What ho mighty wizard... ho ho ho...")
|
||||
|
||||
/obj/item/book/granter/spell/nuclearfist/recoil(mob/living/carbon/user)
|
||||
..()
|
||||
to_chat(user, "<span class='danger'>Your arm spontaneously detonates!</span>")
|
||||
explosion(user.loc, -1, 0, 2, -1, FALSE, FALSE, 2)
|
||||
var/obj/item/bodypart/part = user.get_holding_bodypart_of_item(src)
|
||||
if(part)
|
||||
part.dismember()
|
||||
qdel(part)
|
||||
|
||||
|
||||
/obj/item/book/granter/spell/sacredflame
|
||||
spell = /obj/effect/proc_holder/spell/targeted/sacred_flame
|
||||
spellname = "sacred flame"
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/brainwashed))
|
||||
target.mind.remove_antag_datum(/datum/antagonist/brainwashed)
|
||||
|
||||
if(target.mind.has_antag_datum(ANTAG_DATUM_VASSAL))
|
||||
SSticker.mode.remove_vassal(target.mind)
|
||||
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/rev/head) || target.mind.unconvertable || target.mind.has_antag_datum(/datum/antagonist/gang/boss))
|
||||
if(!silent)
|
||||
target.visible_message("<span class='warning'>[target] seems to resist the implant!</span>", "<span class='warning'>You feel something interfering with your mental conditioning, but you resist it!</span>")
|
||||
|
||||
@@ -320,11 +320,12 @@
|
||||
M.update_inv_hands()
|
||||
|
||||
/obj/item/melee/transforming/energy/sword/cx/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(!in_range(src, user)) //Basic checks to prevent abuse
|
||||
return
|
||||
if(user.incapacitated() || !istype(user))
|
||||
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes")
|
||||
var/energy_color_input = input(usr,"","Choose Energy Color",light_color) as color|null
|
||||
@@ -332,6 +333,7 @@
|
||||
light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
|
||||
update_icon()
|
||||
update_light()
|
||||
return TRUE
|
||||
|
||||
/obj/item/melee/transforming/energy/sword/cx/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -79,17 +79,17 @@
|
||||
final_block_chance = 0 //Don't bring a sword to a gunfight
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/sabre/on_exit_storage(obj/item/storage/S)
|
||||
..()
|
||||
var/obj/item/storage/belt/sabre/B = S
|
||||
/obj/item/melee/sabre/on_exit_storage(datum/component/storage/S)
|
||||
var/obj/item/storage/belt/sabre/B = S.parent
|
||||
if(istype(B))
|
||||
playsound(B, 'sound/items/unsheath.ogg', 25, 1)
|
||||
|
||||
/obj/item/melee/sabre/on_enter_storage(obj/item/storage/S)
|
||||
..()
|
||||
var/obj/item/storage/belt/sabre/B = S
|
||||
|
||||
/obj/item/melee/sabre/on_enter_storage(datum/component/storage/S)
|
||||
var/obj/item/storage/belt/sabre/B = S.parent
|
||||
if(istype(B))
|
||||
playsound(B, 'sound/items/sheath.ogg', 25, 1)
|
||||
..()
|
||||
|
||||
/obj/item/melee/sabre/get_belt_overlay()
|
||||
return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "sabre")
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
update_icon()
|
||||
|
||||
/obj/item/pet_carrier/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(open || !user.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
locked = !locked
|
||||
@@ -79,6 +80,7 @@
|
||||
else
|
||||
playsound(user, 'sound/machines/boltsup.ogg', 30, TRUE)
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/item/pet_carrier/attack(mob/living/target, mob/living/user)
|
||||
if(user.a_intent == INTENT_HARM)
|
||||
|
||||
@@ -213,7 +213,7 @@
|
||||
loadedWeightClass -= I.w_class
|
||||
else if (A == tank)
|
||||
tank = null
|
||||
update_icons()
|
||||
update_icon()
|
||||
|
||||
/obj/item/pneumatic_cannon/ghetto //Obtainable by improvised methods; more gas per use, less capacity, but smaller
|
||||
name = "improvised pneumatic cannon"
|
||||
@@ -239,14 +239,13 @@
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You hook \the [thetank] up to \the [src].</span>")
|
||||
tank = thetank
|
||||
update_icons()
|
||||
update_icon()
|
||||
|
||||
/obj/item/pneumatic_cannon/proc/update_icons()
|
||||
/obj/item/pneumatic_cannon/update_icon()
|
||||
cut_overlays()
|
||||
if(!tank)
|
||||
return
|
||||
add_overlay(tank.icon_state)
|
||||
update_icon()
|
||||
|
||||
/obj/item/pneumatic_cannon/proc/fill_with_type(type, amount)
|
||||
if(!ispath(type, /obj) && !ispath(type, /mob))
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
/obj/item/robot_suit/New()
|
||||
..()
|
||||
updateicon()
|
||||
update_icon()
|
||||
|
||||
/obj/item/robot_suit/prebuilt/New()
|
||||
l_arm = new(src)
|
||||
@@ -39,7 +39,7 @@
|
||||
chest.cell = new /obj/item/stock_parts/cell/high/plus(chest)
|
||||
..()
|
||||
|
||||
/obj/item/robot_suit/proc/updateicon()
|
||||
/obj/item/robot_suit/update_icon()
|
||||
cut_overlays()
|
||||
if(l_arm)
|
||||
add_overlay("[l_arm.icon_state]+o")
|
||||
@@ -96,7 +96,7 @@
|
||||
to_chat(user, "<span class='notice'>You disassemble the cyborg shell.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>There is nothing to remove from the endoskeleton.</span>")
|
||||
updateicon()
|
||||
update_icon()
|
||||
|
||||
/obj/item/robot_suit/proc/put_in_hand_or_drop(mob/living/user, obj/item/I) //normal put_in_hands() drops the item ontop of the player, this drops it at the suit's loc
|
||||
if(!user.put_in_hands(I))
|
||||
@@ -160,7 +160,7 @@
|
||||
W.icon_state = initial(W.icon_state)
|
||||
W.cut_overlays()
|
||||
src.l_leg = W
|
||||
src.updateicon()
|
||||
update_icon()
|
||||
|
||||
else if(istype(W, /obj/item/bodypart/r_leg/robot))
|
||||
if(src.r_leg)
|
||||
@@ -170,7 +170,7 @@
|
||||
W.icon_state = initial(W.icon_state)
|
||||
W.cut_overlays()
|
||||
src.r_leg = W
|
||||
src.updateicon()
|
||||
update_icon()
|
||||
|
||||
else if(istype(W, /obj/item/bodypart/l_arm/robot))
|
||||
if(src.l_arm)
|
||||
@@ -180,7 +180,7 @@
|
||||
W.icon_state = initial(W.icon_state)
|
||||
W.cut_overlays()
|
||||
src.l_arm = W
|
||||
src.updateicon()
|
||||
update_icon()
|
||||
|
||||
else if(istype(W, /obj/item/bodypart/r_arm/robot))
|
||||
if(src.r_arm)
|
||||
@@ -190,7 +190,7 @@
|
||||
W.icon_state = initial(W.icon_state)//in case it is a dismembered robotic limb
|
||||
W.cut_overlays()
|
||||
src.r_arm = W
|
||||
src.updateicon()
|
||||
update_icon()
|
||||
|
||||
else if(istype(W, /obj/item/bodypart/chest/robot))
|
||||
var/obj/item/bodypart/chest/robot/CH = W
|
||||
@@ -202,7 +202,7 @@
|
||||
CH.icon_state = initial(CH.icon_state) //in case it is a dismembered robotic limb
|
||||
CH.cut_overlays()
|
||||
src.chest = CH
|
||||
src.updateicon()
|
||||
update_icon()
|
||||
else if(!CH.wired)
|
||||
to_chat(user, "<span class='warning'>You need to attach wires to it first!</span>")
|
||||
else
|
||||
@@ -222,7 +222,7 @@
|
||||
HD.icon_state = initial(HD.icon_state)//in case it is a dismembered robotic limb
|
||||
HD.cut_overlays()
|
||||
src.head = HD
|
||||
src.updateicon()
|
||||
update_icon()
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need to attach a flash to it first!</span>")
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
/obj/item/borg/upgrade/vtec/action(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
if(.)
|
||||
if(R.speed < 0)
|
||||
if(!R.cansprint)
|
||||
to_chat(R, "<span class='notice'>A VTEC unit is already installed!</span>")
|
||||
to_chat(user, "<span class='notice'>There's no room for another VTEC unit!</span>")
|
||||
return FALSE
|
||||
@@ -82,11 +82,13 @@
|
||||
//R.speed = -2 // Gotta go fast.
|
||||
//Citadel change - makes vtecs give an ability rather than reducing the borg's speed instantly
|
||||
R.AddAbility(new/obj/effect/proc_holder/silicon/cyborg/vtecControl)
|
||||
R.cansprint = 0
|
||||
|
||||
/obj/item/borg/upgrade/vtec/deactivate(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
if (.)
|
||||
R.speed = initial(R.speed)
|
||||
R.cansprint = 1
|
||||
|
||||
/obj/item/borg/upgrade/disablercooler
|
||||
name = "cyborg rapid energy blaster cooling module"
|
||||
@@ -409,8 +411,7 @@
|
||||
icon_state = "cyborg_upgrade3"
|
||||
require_module = 1
|
||||
module_type = list(/obj/item/robot_module/medical,
|
||||
/obj/item/robot_module/syndicate_medical,
|
||||
/obj/item/robot_module/medihound)
|
||||
/obj/item/robot_module/syndicate_medical)
|
||||
var/list/additional_reagents = list()
|
||||
|
||||
/obj/item/borg/upgrade/hypospray/action(mob/living/silicon/robot/R, user = usr)
|
||||
@@ -466,23 +467,6 @@
|
||||
for(var/obj/item/reagent_containers/borghypo/H in R.module.modules)
|
||||
H.bypass_protection = initial(H.bypass_protection)
|
||||
|
||||
/obj/item/borg/upgrade/defib
|
||||
name = "medical cyborg defibrillator"
|
||||
desc = "An upgrade to the Medical module, installing a built-in \
|
||||
defibrillator, for on the scene revival."
|
||||
icon_state = "cyborg_upgrade3"
|
||||
require_module = 1
|
||||
module_type = list(/obj/item/robot_module/medical,
|
||||
/obj/item/robot_module/syndicate_medical,
|
||||
/obj/item/robot_module/medihound)
|
||||
|
||||
/obj/item/borg/upgrade/defib/action(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
if(.)
|
||||
var/obj/item/twohanded/shockpaddles/cyborg/S = new(R.module)
|
||||
R.module.basic_modules += S
|
||||
R.module.add_module(S, FALSE, TRUE)
|
||||
|
||||
/obj/item/borg/upgrade/defib/deactivate(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
if (.)
|
||||
@@ -497,8 +481,7 @@
|
||||
icon_state = "cyborg_upgrade3"
|
||||
require_module = 1
|
||||
module_type = list(/obj/item/robot_module/medical,
|
||||
/obj/item/robot_module/syndicate_medical,
|
||||
/obj/item/robot_module/medihound)
|
||||
/obj/item/robot_module/syndicate_medical)
|
||||
|
||||
/obj/item/borg/upgrade/processor/action(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
@@ -521,8 +504,7 @@
|
||||
require_module = 1
|
||||
module_type = list(
|
||||
/obj/item/robot_module/medical,
|
||||
/obj/item/robot_module/syndicate_medical,
|
||||
/obj/item/robot_module/medihound)
|
||||
/obj/item/robot_module/syndicate_medical)
|
||||
|
||||
/obj/item/borg/upgrade/advhealth/action(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
@@ -642,8 +624,7 @@
|
||||
icon_state = "pinpointer_crew"
|
||||
require_module = TRUE
|
||||
module_type = list(/obj/item/robot_module/medical,
|
||||
/obj/item/robot_module/syndicate_medical,
|
||||
/obj/item/robot_module/medihound)
|
||||
/obj/item/robot_module/syndicate_medical)
|
||||
|
||||
/obj/item/borg/upgrade/pinpointer/action(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
|
||||
@@ -39,6 +39,9 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
|
||||
/obj/item/stack/sheet/glass/fifty
|
||||
amount = 50
|
||||
|
||||
/obj/item/stack/sheet/glass/five
|
||||
amount = 5
|
||||
|
||||
/obj/item/stack/sheet/glass/Initialize(mapload, new_amount, merge = TRUE)
|
||||
recipes = GLOB.glass_recipes
|
||||
return ..()
|
||||
|
||||
@@ -55,6 +55,9 @@ GLOBAL_LIST_INIT(sandstone_recipes, list ( \
|
||||
/obj/item/stack/sheet/mineral/sandstone/thirty
|
||||
amount = 30
|
||||
|
||||
/obj/item/stack/sheet/mineral/sandstone/twelve
|
||||
amount = 12
|
||||
|
||||
/*
|
||||
* Sandbags
|
||||
*/
|
||||
|
||||
@@ -228,7 +228,7 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
|
||||
|
||||
/obj/item/stack/sheet/mineral/wood
|
||||
name = "wooden plank"
|
||||
desc = "One can only guess that this is a bunch of wood."
|
||||
desc = "One can only guess that this is a bunch of wood. You might be able to make a stake with this if you use something sharp on it"
|
||||
singular_name = "wood plank"
|
||||
icon_state = "sheet-wood"
|
||||
item_state = "sheet-wood"
|
||||
@@ -240,6 +240,35 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
|
||||
novariants = TRUE
|
||||
grind_results = list("carbon" = 20)
|
||||
|
||||
|
||||
/obj/item/stack/sheet/mineral/wood/attackby(obj/item/W, mob/user, params) // NOTE: sheet_types.dm is where the WOOD stack lives. Maybe move this over there.
|
||||
// Taken from /obj/item/stack/rods/attackby in [rods.dm]
|
||||
if(W.get_sharpness())
|
||||
user.visible_message("[user] begins whittling [src] into a pointy object.", \
|
||||
"<span class='notice'>You begin whittling [src] into a sharp point at one end.</span>", \
|
||||
"<span class='italics'>You hear wood carving.</span>")
|
||||
// 8 Second Timer
|
||||
if(!do_after(user, 80, TRUE, src))
|
||||
return
|
||||
// Make Stake
|
||||
var/obj/item/stake/basic/new_item = new(user.loc)
|
||||
user.visible_message("[user] finishes carving a stake out of [src].", \
|
||||
"<span class='notice'>You finish carving a stake out of [src].</span>")
|
||||
// Prepare to Put in Hands (if holding wood)
|
||||
var/obj/item/stack/sheet/mineral/wood/N = src
|
||||
var/replace = (user.get_inactive_held_item() == N)
|
||||
// Use Wood
|
||||
N.use(1)
|
||||
// If stack depleted, put item in that hand (if it had one)
|
||||
if (!N && replace)
|
||||
user.put_in_hands(new_item)
|
||||
if(istype(W, merge_type))
|
||||
var/obj/item/stack/S = W
|
||||
if(merge(S))
|
||||
to_chat(user, "<span class='notice'>Your [S.name] stack now contains [S.get_amount()] [S.singular_name]\s.</span>")
|
||||
else
|
||||
. = ..()
|
||||
|
||||
/obj/item/stack/sheet/mineral/wood/Initialize(mapload, new_amount, merge = TRUE)
|
||||
recipes = GLOB.wood_recipes
|
||||
return ..()
|
||||
@@ -247,6 +276,33 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \
|
||||
/obj/item/stack/sheet/mineral/wood/fifty
|
||||
amount = 50
|
||||
|
||||
/*
|
||||
* Bamboo
|
||||
*/
|
||||
|
||||
GLOBAL_LIST_INIT(bamboo_recipes, list ( \
|
||||
new/datum/stack_recipe("punji sticks trap", /obj/structure/punji_sticks, 5, time = 30, one_per_turf = TRUE, on_floor = TRUE), \
|
||||
new/datum/stack_recipe("blow gun", /obj/item/gun/syringe/blowgun, 10, time = 70), \
|
||||
))
|
||||
|
||||
/obj/item/stack/sheet/mineral/bamboo
|
||||
name = "bamboo cuttings"
|
||||
desc = "Finely cut bamboo sticks."
|
||||
singular_name = "cut bamboo"
|
||||
icon_state = "sheet-bamboo"
|
||||
item_state = "sheet-bamboo"
|
||||
icon = 'icons/obj/stack_objects.dmi'
|
||||
throwforce = 15
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 0)
|
||||
resistance_flags = FLAMMABLE
|
||||
merge_type = /obj/item/stack/sheet/mineral/bamboo
|
||||
grind_results = list("carbon" = 5)
|
||||
|
||||
/obj/item/stack/sheet/mineral/bamboo/Initialize(mapload, new_amount, merge = TRUE)
|
||||
recipes = GLOB.bamboo_recipes
|
||||
return ..()
|
||||
|
||||
|
||||
/*
|
||||
* Cloth
|
||||
*/
|
||||
@@ -696,5 +752,3 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra
|
||||
merge_type = /obj/item/stack/sheet/cotton/durathread
|
||||
pull_effort = 70
|
||||
loom_result = /obj/item/stack/sheet/durathread
|
||||
|
||||
|
||||
|
||||
@@ -350,6 +350,7 @@
|
||||
. = ..()
|
||||
|
||||
/obj/item/stack/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
if(is_cyborg)
|
||||
@@ -363,10 +364,11 @@
|
||||
max = get_amount()
|
||||
stackmaterial = min(max, stackmaterial)
|
||||
if(stackmaterial == null || stackmaterial <= 0 || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
return TRUE
|
||||
else
|
||||
change_stack(user, stackmaterial)
|
||||
to_chat(user, "<span class='notice'>You take [stackmaterial] sheets out of the stack</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/stack/proc/change_stack(mob/user, amount)
|
||||
if(!use(amount, TRUE, FALSE))
|
||||
|
||||
@@ -757,23 +757,13 @@
|
||||
STR.rustle_sound = FALSE
|
||||
STR.max_w_class = WEIGHT_CLASS_BULKY
|
||||
STR.can_hold = typecacheof(fitting_swords)
|
||||
STR.quickdraw = TRUE
|
||||
|
||||
/obj/item/storage/belt/sabre/examine(mob/user)
|
||||
. = ..()
|
||||
if(length(contents))
|
||||
. += "<span class='notice'>Alt-click it to quickly draw the blade.</span>"
|
||||
|
||||
/obj/item/storage/belt/sabre/AltClick(mob/user)
|
||||
if(!iscarbon(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
if(length(contents))
|
||||
var/obj/item/I = contents[1]
|
||||
user.visible_message("[user] takes [I] out of [src].", "<span class='notice'>You take [I] out of [src].</span>")
|
||||
user.put_in_hands(I)
|
||||
update_icon()
|
||||
else
|
||||
to_chat(user, "[src] is empty.")
|
||||
|
||||
/obj/item/storage/belt/sabre/update_icon()
|
||||
. = ..()
|
||||
if(isliving(loc))
|
||||
|
||||
@@ -901,7 +901,7 @@
|
||||
#undef HEART
|
||||
#undef SMILEY
|
||||
|
||||
/obj/item/storage/box/ingredients //This box is for the randomely chosen version the chef spawns with, it shouldn't actually exist.
|
||||
/obj/item/storage/box/ingredients //This box is for the randomly chosen version the chef spawns with, it shouldn't actually exist.
|
||||
name = "ingredients box"
|
||||
illustration = "fruit"
|
||||
var/theme_name
|
||||
|
||||
@@ -157,6 +157,7 @@
|
||||
to_chat(user, "<span class='notice'>You take \a [W] out of the pack.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>There are no [icon_type]s left in the pack.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/update_icon()
|
||||
if(fancy_open || !contents.len)
|
||||
|
||||
@@ -114,11 +114,12 @@
|
||||
. += "<span class='notice'>Alt-click to [open ? "close":"open"] it.</span>"
|
||||
|
||||
/obj/item/storage/lockbox/medal/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(user.canUseTopic(src, BE_CLOSE))
|
||||
if(!SEND_SIGNAL(src, COMSIG_IS_STORAGE_LOCKED))
|
||||
open = (open ? FALSE : TRUE)
|
||||
update_icon()
|
||||
..()
|
||||
return TRUE
|
||||
|
||||
/obj/item/storage/lockbox/medal/PopulateContents()
|
||||
new /obj/item/clothing/accessory/medal/gold/captain(src)
|
||||
|
||||
@@ -338,11 +338,12 @@
|
||||
M.update_inv_hands()
|
||||
|
||||
/obj/item/toy/sword/cx/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(!in_range(src, user)) //Basic checks to prevent abuse
|
||||
return
|
||||
if(user.incapacitated() || !istype(user))
|
||||
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
if(alert("Are you sure you want to recolor your blade?", "Confirm Repaint", "Yes", "No") == "Yes")
|
||||
var/energy_color_input = input(usr,"","Choose Energy Color",light_color) as color|null
|
||||
@@ -350,6 +351,7 @@
|
||||
light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
|
||||
update_icon()
|
||||
update_light()
|
||||
return TRUE
|
||||
|
||||
/obj/item/toy/sword/cx/worn_overlays(isinhands, icon_file)
|
||||
. = ..()
|
||||
@@ -401,6 +403,7 @@
|
||||
righthand_file = 'icons/mob/inhands/equipment/toolbox_righthand.dmi'
|
||||
var/active = FALSE
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
hitsound = 'sound/weapons/smash.ogg'
|
||||
attack_verb = list("robusted")
|
||||
|
||||
/obj/item/toy/windupToolbox/attack_self(mob/user)
|
||||
@@ -408,13 +411,33 @@
|
||||
icon_state = "his_grace_awakened"
|
||||
to_chat(user, "<span class='warning'>You wind up [src], it begins to rumble.</span>")
|
||||
active = TRUE
|
||||
playsound(src, 'sound/effects/pope_entry.ogg', 100)
|
||||
Rumble()
|
||||
addtimer(CALLBACK(src, .proc/stopRumble), 600)
|
||||
else
|
||||
to_chat(user, "[src] is already active.")
|
||||
|
||||
/obj/item/toy/windupToolbox/proc/Rumble()
|
||||
var/static/list/transforms
|
||||
if(!transforms)
|
||||
var/matrix/M1 = matrix()
|
||||
var/matrix/M2 = matrix()
|
||||
var/matrix/M3 = matrix()
|
||||
var/matrix/M4 = matrix()
|
||||
M1.Translate(-1, 0)
|
||||
M2.Translate(0, 1)
|
||||
M3.Translate(1, 0)
|
||||
M4.Translate(0, -1)
|
||||
transforms = list(M1, M2, M3, M4)
|
||||
animate(src, transform=transforms[1], time=0.2, loop=-1)
|
||||
animate(transform=transforms[2], time=0.1)
|
||||
animate(transform=transforms[3], time=0.2)
|
||||
animate(transform=transforms[4], time=0.3)
|
||||
|
||||
/obj/item/toy/windupToolbox/proc/stopRumble()
|
||||
icon_state = initial(icon_state)
|
||||
active = FALSE
|
||||
animate(src, transform=matrix())
|
||||
|
||||
/*
|
||||
* Subtype of Double-Bladed Energy Swords
|
||||
@@ -864,9 +887,10 @@
|
||||
return ..()
|
||||
|
||||
/obj/item/toy/cards/deck/MouseDrop(atom/over_object)
|
||||
. = ..()
|
||||
var/mob/living/M = usr
|
||||
if(!istype(M) || usr.incapacitated() || usr.lying)
|
||||
return ..()
|
||||
return
|
||||
if(Adjacent(usr))
|
||||
if(over_object == M && loc != M)
|
||||
M.put_in_hands(src)
|
||||
@@ -878,9 +902,7 @@
|
||||
to_chat(usr, "<span class='notice'>You pick up the deck.</span>")
|
||||
|
||||
else
|
||||
. = ..()
|
||||
if(!.)
|
||||
to_chat(usr, "<span class='warning'>You can't reach it from here!</span>")
|
||||
to_chat(usr, "<span class='warning'>You can't reach it from here!</span>")
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -541,6 +541,7 @@
|
||||
clean_blood()
|
||||
|
||||
/obj/item/twohanded/dualsaber/hypereutactic/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, BE_CLOSE, FALSE) || hacked)
|
||||
return
|
||||
if(user.incapacitated() || !istype(user))
|
||||
@@ -553,6 +554,7 @@
|
||||
light_color = sanitize_hexcolor(energy_color_input, desired_format=6, include_crunch=1)
|
||||
update_icon()
|
||||
update_light()
|
||||
return TRUE
|
||||
|
||||
/obj/item/twohanded/dualsaber/hypereutactic/worn_overlays(isinhands, icon_file)
|
||||
. = ..()
|
||||
@@ -659,6 +661,7 @@
|
||||
qdel(src)
|
||||
|
||||
/obj/item/twohanded/spear/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(user.canUseTopic(src, BE_CLOSE))
|
||||
..()
|
||||
if(!explosive)
|
||||
@@ -667,6 +670,7 @@
|
||||
var/input = stripped_input(user,"What do you want your war cry to be? You will shout it when you hit someone in melee.", ,"", 50)
|
||||
if(input)
|
||||
src.war_cry = input
|
||||
return TRUE
|
||||
|
||||
/obj/item/twohanded/spear/CheckParts(list/parts_list)
|
||||
var/obj/item/shard/tip = locate() in parts_list
|
||||
|
||||
@@ -234,6 +234,7 @@
|
||||
. = ..()
|
||||
if(unique_reskin && (!current_skin || always_reskinnable) && user.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
|
||||
reskin_obj(user)
|
||||
return TRUE
|
||||
|
||||
/obj/proc/reskin_obj(mob/M)
|
||||
if(!LAZYLEN(unique_reskin))
|
||||
|
||||
@@ -449,6 +449,9 @@
|
||||
item_chair = null
|
||||
var/turns = 0
|
||||
|
||||
/obj/structure/chair/brass/ComponentInitialize()
|
||||
return //it spins with the power of ratvar, not components.
|
||||
|
||||
/obj/structure/chair/brass/Destroy()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
. = ..()
|
||||
@@ -464,6 +467,7 @@
|
||||
return
|
||||
|
||||
/obj/structure/chair/brass/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
turns = 0
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
@@ -475,6 +479,7 @@
|
||||
user.visible_message("<span class='notice'>[user] stops [src]'s uncontrollable spinning.</span>", \
|
||||
"<span class='notice'>You grab [src] and stop its wild spinning.</span>")
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
return TRUE
|
||||
|
||||
/obj/structure/chair/bronze
|
||||
name = "brass chair"
|
||||
|
||||
@@ -342,25 +342,21 @@
|
||||
. = TRUE
|
||||
if(opened)
|
||||
if(istype(W, cutting_tool))
|
||||
var/welder = FALSE
|
||||
if(istype(W, /obj/item/weldingtool))
|
||||
if(!W.tool_start_check(user, amount=0))
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You begin cutting \the [src] apart...</span>")
|
||||
if(W.use_tool(src, user, 40, volume=50))
|
||||
if(eigen_teleport)
|
||||
to_chat(user, "<span class='notice'>The unstable nature of \the [src] makes it impossible to cut!</span>")
|
||||
return
|
||||
if(!opened)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] slices apart \the [src].</span>",
|
||||
"<span class='notice'>You cut \the [src] apart with \the [W].</span>",
|
||||
"<span class='italics'>You hear welding.</span>")
|
||||
deconstruct(TRUE)
|
||||
return
|
||||
else // for example cardboard box is cut with wirecutters
|
||||
user.visible_message("<span class='notice'>[user] cut apart \the [src].</span>", \
|
||||
"<span class='notice'>You cut \the [src] apart with \the [W].</span>")
|
||||
to_chat(user, "<span class='notice'>You begin [welder ? "slicing" : "deconstructing"] \the [src] apart...</span>")
|
||||
welder = TRUE
|
||||
if(W.use_tool(src, user, 40, volume=50))
|
||||
if(eigen_teleport)
|
||||
to_chat(user, "<span class='notice'>The unstable nature of \the [src] makes it impossible to [welder ? "slice" : "deconstruct"]!</span>")
|
||||
return
|
||||
if(!opened)
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] [welder ? "slice" : "deconstruct"]s apart \the [src].</span>",
|
||||
"<span class='notice'>You [welder ? "slice" : "deconstruct"] \the [src] apart with \the [W].</span>",
|
||||
"<span class='italics'>You hear [welder ? "welding" : "rustling of screws and metal"].</span>")
|
||||
deconstruct(TRUE)
|
||||
return
|
||||
if(user.transferItemToLoc(W, drop_location())) // so we put in unlit welder too
|
||||
@@ -526,11 +522,12 @@
|
||||
to_chat(user, "<span class='warning'>You fail to break out of [src]!</span>")
|
||||
|
||||
/obj/structure/closet/AltClick(mob/user)
|
||||
..()
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, be_close=TRUE) || !isturf(loc))
|
||||
to_chat(user, "<span class='warning'>You can't do that right now!</span>")
|
||||
return
|
||||
return TRUE
|
||||
togglelock(user)
|
||||
return TRUE
|
||||
|
||||
/obj/structure/closet/CtrlShiftClick(mob/living/user)
|
||||
if(!HAS_TRAIT(user, TRAIT_SKITTISH))
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
icon_state = "cabinet"
|
||||
resistance_flags = FLAMMABLE
|
||||
max_integrity = 70
|
||||
material_drop = /obj/item/stack/sheet/mineral/wood
|
||||
cutting_tool = /obj/item/screwdriver
|
||||
|
||||
/obj/structure/closet/acloset
|
||||
name = "strange closet"
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
icon_state = "cabinet"
|
||||
resistance_flags = FLAMMABLE
|
||||
max_integrity = 70
|
||||
material_drop = /obj/item/stack/sheet/mineral/wood
|
||||
cutting_tool = /obj/item/screwdriver
|
||||
|
||||
/obj/structure/closet/secure_closet/bar/PopulateContents()
|
||||
..()
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
icon_state = "cabinet"
|
||||
resistance_flags = FLAMMABLE
|
||||
max_integrity = 70
|
||||
material_drop = /obj/item/stack/sheet/mineral/wood
|
||||
cutting_tool = /obj/item/screwdriver
|
||||
|
||||
/obj/structure/closet/secure_closet/personal/cabinet/PopulateContents()
|
||||
new /obj/item/storage/backpack/satchel/leather/withwallet( src )
|
||||
|
||||
@@ -161,12 +161,16 @@
|
||||
..()
|
||||
new /obj/item/clothing/accessory/armband/medblue(src)
|
||||
new /obj/item/encryptionkey/headset_med(src)
|
||||
|
||||
/obj/structure/closet/secure_closet/detective
|
||||
name = "\improper detective's cabinet"
|
||||
req_access = list(ACCESS_FORENSICS_LOCKERS)
|
||||
icon_state = "cabinet"
|
||||
resistance_flags = FLAMMABLE
|
||||
max_integrity = 70
|
||||
material_drop = /obj/item/stack/sheet/mineral/wood
|
||||
cutting_tool = /obj/item/screwdriver
|
||||
|
||||
/obj/structure/closet/secure_closet/detective/PopulateContents()
|
||||
..()
|
||||
new /obj/item/clothing/under/rank/det(src)
|
||||
|
||||
@@ -79,6 +79,15 @@
|
||||
material_drop = /obj/item/stack/sheet/mineral/wood
|
||||
material_drop_amount = 5
|
||||
|
||||
/obj/structure/closet/crate/coffin/examine(mob/user)
|
||||
. = ..()
|
||||
if(user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
|
||||
. += {"<span class='cult'>This is a coffin which you can use to regenerate your burns and other wounds faster.</span>"}
|
||||
. += {"<span class='cult'>You can also thicken your blood if you survive the day, and hide from the sun safely while inside.</span>"}
|
||||
/* if(user.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
|
||||
. += {"<span class='cult'>This is a coffin which your master can use to shield himself from the unforgiving sun.\n
|
||||
You yourself are still human and dont need it. Yet.</span>"} */
|
||||
|
||||
/obj/structure/closet/crate/internals
|
||||
desc = "An internals crate."
|
||||
name = "internals crate"
|
||||
|
||||
@@ -40,11 +40,11 @@
|
||||
last_process = world.time
|
||||
to_chat(user, "<span class='notice'>The water feels warm and soothing as you touch it. The fountain immediately dries up shortly afterwards.</span>")
|
||||
user.reagents.add_reagent("godblood",20)
|
||||
update_icons()
|
||||
addtimer(CALLBACK(src, .proc/update_icons), time_between_uses)
|
||||
update_icon()
|
||||
addtimer(CALLBACK(src, .proc/update_icon), time_between_uses)
|
||||
|
||||
|
||||
/obj/structure/healingfountain/proc/update_icons()
|
||||
/obj/structure/healingfountain/update_icon()
|
||||
if(last_process + time_between_uses > world.time)
|
||||
icon_state = "fountain"
|
||||
else
|
||||
|
||||
@@ -102,9 +102,11 @@
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/structure/extinguisher_cabinet/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
toggle_cabinet(user)
|
||||
return TRUE
|
||||
|
||||
/obj/structure/extinguisher_cabinet/proc/toggle_cabinet(mob/user)
|
||||
if(opened && broken)
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
if(source_projector)
|
||||
projector = source_projector
|
||||
projector.signs += src
|
||||
SSvis_overlays.add_vis_overlay(src, icon, icon_state, ABOVE_MOB_LAYER, plane, dir, alpha, RESET_ALPHA) //you see mobs under it, but you hit them like they are above it
|
||||
alpha = 0
|
||||
SSvis_overlays.add_vis_overlay(src, icon, icon_state, ABOVE_MOB_LAYER, plane, dir, add_appearance_flags = RESET_ALPHA) //you see mobs under it, but you hit them like they are above it
|
||||
|
||||
/obj/structure/holosign/Destroy()
|
||||
if(projector)
|
||||
|
||||
@@ -20,10 +20,9 @@
|
||||
return
|
||||
if(broken || !Adjacent(user))
|
||||
return
|
||||
|
||||
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
|
||||
//see code/modules/mob/dead/new_player/preferences.dm at approx line 545 for comments!
|
||||
//this is largely copypasted from there.
|
||||
|
||||
@@ -226,9 +225,13 @@
|
||||
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return
|
||||
if(new_eye_color)
|
||||
H.eye_color = sanitize_hexcolor(new_eye_color)
|
||||
var/n_color = sanitize_hexcolor(new_eye_color)
|
||||
var/obj/item/organ/eyes/eyes = H.getorganslot(ORGAN_SLOT_EYES)
|
||||
if(eyes)
|
||||
eyes.eye_color = n_color
|
||||
H.eye_color = n_color
|
||||
H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK)
|
||||
H.update_body()
|
||||
H.dna.species.handle_body()
|
||||
if(choice)
|
||||
curse(user)
|
||||
|
||||
|
||||
@@ -167,11 +167,12 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an
|
||||
. += "<span class='notice'>The speaker is [beeper ? "enabled" : "disabled"]. Alt-click to toggle it.</span>"
|
||||
|
||||
/obj/structure/bodycontainer/morgue/AltClick(mob/user)
|
||||
..()
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !issilicon(user)))
|
||||
return
|
||||
beeper = !beeper
|
||||
to_chat(user, "<span class='notice'>You turn the speaker function [beeper ? "on" : "off"].</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/structure/bodycontainer/morgue/update_icon()
|
||||
if (!connected || connected.loc != src) // Open or tray is gone.
|
||||
|
||||
@@ -167,10 +167,12 @@
|
||||
return TRUE
|
||||
|
||||
/obj/structure/reflector/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
else if(finished)
|
||||
rotate(user)
|
||||
return TRUE
|
||||
|
||||
|
||||
//TYPES OF REFLECTORS, SINGLE, DOUBLE, BOX
|
||||
|
||||
@@ -285,6 +285,13 @@
|
||||
. += new /obj/item/shard(location)
|
||||
|
||||
/obj/structure/window/proc/can_be_rotated(mob/user,rotation_type)
|
||||
if (get_dist(src,user) > 1)
|
||||
if (iscarbon(user))
|
||||
var/mob/living/carbon/H = user
|
||||
if (!(H.dna && H.dna.check_mutation(TK) && tkMaxRangeCheck(src,H)))
|
||||
return FALSE
|
||||
else
|
||||
return FALSE
|
||||
if(anchored)
|
||||
to_chat(user, "<span class='warning'>[src] cannot be rotated while it is fastened to the floor!</span>")
|
||||
return FALSE
|
||||
|
||||
+7
-5
@@ -28,19 +28,21 @@ GLOBAL_LIST_INIT(freqtospan, list(
|
||||
language = get_default_language()
|
||||
send_speech(message, 7, src, , spans, message_language=language)
|
||||
|
||||
/atom/movable/proc/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
|
||||
/atom/movable/proc/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
|
||||
SEND_SIGNAL(src, COMSIG_MOVABLE_HEAR, args)
|
||||
|
||||
/atom/movable/proc/can_speak()
|
||||
return 1
|
||||
|
||||
/atom/movable/proc/send_speech(message, range = 7, obj/source = src, bubble_type, list/spans, datum/language/message_language = null, message_mode)
|
||||
var/rendered = compose_message(src, message_language, message, , spans, message_mode)
|
||||
/atom/movable/proc/send_speech(message, range = 7, atom/movable/source = src, bubble_type, list/spans, datum/language/message_language = null, message_mode)
|
||||
var/rendered = compose_message(src, message_language, message, , spans, message_mode, source)
|
||||
for(var/_AM in get_hearers_in_view(range, source))
|
||||
var/atom/movable/AM = _AM
|
||||
AM.Hear(rendered, src, message_language, message, , spans, message_mode)
|
||||
AM.Hear(rendered, src, message_language, message, , spans, message_mode, source)
|
||||
|
||||
/atom/movable/proc/compose_message(atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, face_name = FALSE)
|
||||
/atom/movable/proc/compose_message(atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, face_name = FALSE, atom/movable/source)
|
||||
if(!source)
|
||||
source = speaker
|
||||
//This proc uses text() because it is faster than appending strings. Thanks BYOND.
|
||||
//Basic span
|
||||
var/spanpart1 = "<span class='[radio_freq ? get_radio_span(radio_freq) : "game say"]'>"
|
||||
|
||||
@@ -176,6 +176,12 @@
|
||||
/turf/closed/mineral/uranium/volcanic = 35, /turf/closed/mineral/diamond/volcanic = 30, /turf/closed/mineral/gold/volcanic = 45, /turf/closed/mineral/titanium/volcanic = 45,
|
||||
/turf/closed/mineral/silver/volcanic = 50, /turf/closed/mineral/plasma/volcanic = 50, /turf/closed/mineral/bscrystal/volcanic = 20)
|
||||
|
||||
/turf/closed/mineral/random/high_chance/earth_like
|
||||
icon_state = "rock_highchance_oxy"
|
||||
turf_type = /turf/open/floor/plating/asteroid
|
||||
baseturfs = /turf/open/floor/plating/asteroid
|
||||
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
|
||||
defer_change = TRUE
|
||||
|
||||
|
||||
/turf/closed/mineral/random/low_chance
|
||||
@@ -186,6 +192,12 @@
|
||||
/turf/closed/mineral/silver = 6, /turf/closed/mineral/plasma = 15, /turf/closed/mineral/iron = 40,
|
||||
/turf/closed/mineral/gibtonite = 2, /turf/closed/mineral/bscrystal = 1)
|
||||
|
||||
/turf/closed/mineral/random/low_chance/earth_like
|
||||
icon_state = "rock_lowchance_oxy"
|
||||
turf_type = /turf/open/floor/plating/asteroid
|
||||
baseturfs = /turf/open/floor/plating/asteroid
|
||||
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
|
||||
defer_change = TRUE
|
||||
|
||||
/turf/closed/mineral/random/volcanic
|
||||
environment_type = "basalt"
|
||||
@@ -220,6 +232,12 @@
|
||||
/turf/closed/mineral/silver/volcanic = 20, /turf/closed/mineral/plasma/volcanic = 30, /turf/closed/mineral/bscrystal/volcanic = 1, /turf/closed/mineral/gibtonite/volcanic = 2,
|
||||
/turf/closed/mineral/iron/volcanic = 95)
|
||||
|
||||
/turf/closed/mineral/random/earth_like
|
||||
icon_state = "rock_oxy"
|
||||
turf_type = /turf/open/floor/plating/asteroid
|
||||
baseturfs = /turf/open/floor/plating/asteroid
|
||||
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
|
||||
defer_change = TRUE
|
||||
|
||||
|
||||
/turf/closed/mineral/iron
|
||||
@@ -235,6 +253,13 @@
|
||||
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
|
||||
defer_change = 1
|
||||
|
||||
/turf/closed/mineral/iron/earth_like
|
||||
icon_state = "rock_oxy"
|
||||
turf_type = /turf/open/floor/plating/asteroid
|
||||
baseturfs = /turf/open/floor/plating/asteroid
|
||||
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
|
||||
defer_change = TRUE
|
||||
|
||||
/turf/closed/mineral/iron/ice
|
||||
environment_type = "snow_cavern"
|
||||
icon_state = "icerock_iron"
|
||||
@@ -258,6 +283,13 @@
|
||||
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
|
||||
defer_change = 1
|
||||
|
||||
/turf/closed/mineral/uranium/earth_like
|
||||
icon_state = "rock_oxy"
|
||||
turf_type = /turf/open/floor/plating/asteroid
|
||||
baseturfs = /turf/open/floor/plating/asteroid
|
||||
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
|
||||
defer_change = TRUE
|
||||
|
||||
|
||||
/turf/closed/mineral/diamond
|
||||
mineralType = /obj/item/stack/ore/diamond
|
||||
@@ -272,6 +304,13 @@
|
||||
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
|
||||
defer_change = 1
|
||||
|
||||
/turf/closed/mineral/diamond/earth_like
|
||||
icon_state = "rock_oxy"
|
||||
turf_type = /turf/open/floor/plating/asteroid
|
||||
baseturfs = /turf/open/floor/plating/asteroid
|
||||
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
|
||||
defer_change = TRUE
|
||||
|
||||
/turf/closed/mineral/diamond/ice
|
||||
environment_type = "snow_cavern"
|
||||
icon_state = "icerock_diamond"
|
||||
@@ -295,6 +334,13 @@
|
||||
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
|
||||
defer_change = 1
|
||||
|
||||
/turf/closed/mineral/gold/earth_like
|
||||
icon_state = "rock_oxy"
|
||||
turf_type = /turf/open/floor/plating/asteroid
|
||||
baseturfs = /turf/open/floor/plating/asteroid
|
||||
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
|
||||
defer_change = TRUE
|
||||
|
||||
|
||||
/turf/closed/mineral/silver
|
||||
mineralType = /obj/item/stack/ore/silver
|
||||
@@ -309,6 +355,13 @@
|
||||
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
|
||||
defer_change = 1
|
||||
|
||||
/turf/closed/mineral/silver/earth_like
|
||||
icon_state = "rock_oxy"
|
||||
turf_type = /turf/open/floor/plating/asteroid
|
||||
baseturfs = /turf/open/floor/plating/asteroid
|
||||
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
|
||||
defer_change = TRUE
|
||||
|
||||
|
||||
/turf/closed/mineral/titanium
|
||||
mineralType = /obj/item/stack/ore/titanium
|
||||
@@ -323,6 +376,13 @@
|
||||
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
|
||||
defer_change = 1
|
||||
|
||||
/turf/closed/mineral/titanium/earth_like
|
||||
icon_state = "rock_oxy"
|
||||
turf_type = /turf/open/floor/plating/asteroid
|
||||
baseturfs = /turf/open/floor/plating/asteroid
|
||||
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
|
||||
defer_change = TRUE
|
||||
|
||||
|
||||
/turf/closed/mineral/plasma
|
||||
mineralType = /obj/item/stack/ore/plasma
|
||||
@@ -337,6 +397,13 @@
|
||||
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
|
||||
defer_change = 1
|
||||
|
||||
/turf/closed/mineral/plasma/earth_like
|
||||
icon_state = "rock_oxy"
|
||||
turf_type = /turf/open/floor/plating/asteroid
|
||||
baseturfs = /turf/open/floor/plating/asteroid
|
||||
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
|
||||
defer_change = TRUE
|
||||
|
||||
/turf/closed/mineral/plasma/ice
|
||||
environment_type = "snow_cavern"
|
||||
icon_state = "icerock_plasma"
|
||||
@@ -355,6 +422,12 @@
|
||||
spread = 0
|
||||
scan_state = "rock_Bananium"
|
||||
|
||||
/turf/closed/mineral/bananium/earth_like
|
||||
icon_state = "rock_oxy"
|
||||
turf_type = /turf/open/floor/plating/asteroid
|
||||
baseturfs = /turf/open/floor/plating/asteroid
|
||||
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
|
||||
defer_change = TRUE
|
||||
|
||||
/turf/closed/mineral/bscrystal
|
||||
mineralType = /obj/item/stack/ore/bluespace_crystal
|
||||
@@ -370,6 +443,13 @@
|
||||
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
|
||||
defer_change = 1
|
||||
|
||||
/turf/closed/mineral/bscrystal/earth_like
|
||||
icon_state = "rock_oxy"
|
||||
turf_type = /turf/open/floor/plating/asteroid
|
||||
baseturfs = /turf/open/floor/plating/asteroid
|
||||
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
|
||||
defer_change = TRUE
|
||||
|
||||
|
||||
/turf/closed/mineral/volcanic
|
||||
environment_type = "basalt"
|
||||
@@ -383,6 +463,13 @@
|
||||
baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface
|
||||
defer_change = 1
|
||||
|
||||
/turf/closed/mineral/earth_like
|
||||
icon_state = "rock_oxy"
|
||||
turf_type = /turf/open/floor/plating/asteroid
|
||||
baseturfs = /turf/open/floor/plating/asteroid
|
||||
initial_gas_mix = OPENTURF_DEFAULT_ATMOS
|
||||
defer_change = TRUE
|
||||
|
||||
/turf/closed/mineral/ash_rock //wall piece
|
||||
name = "rock"
|
||||
icon = 'icons/turf/mining.dmi'
|
||||
|
||||
Reference in New Issue
Block a user