This commit is contained in:
Putnam
2019-12-15 14:41:47 -08:00
266 changed files with 6741 additions and 710 deletions
@@ -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)
+50
View File
@@ -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
*/
+3
View File
@@ -239,6 +239,9 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, null)
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
@@ -756,3 +746,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
@@ -792,3 +792,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
+1
View File
@@ -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)
+2
View File
@@ -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)
. = ..()
+2 -2
View File
@@ -132,8 +132,8 @@
..()
if(!user.canUseTopic(src))
return
else
eject_part(user)
eject_part(user)
return TRUE
/obj/machinery/aug_manipulator/power_change()
..()
+27 -28
View File
@@ -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)
. = ..()
@@ -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
+3 -3
View File
@@ -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)
. = ..()
@@ -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
+2
View File
@@ -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)
+2
View File
@@ -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)
+2
View File
@@ -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())
+2
View File
@@ -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))
+4 -2
View File
@@ -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)
+2
View File
@@ -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
+14 -19
View File
@@ -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."
+4 -3
View File
@@ -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)"
+2
View File
@@ -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()
+2 -2
View File
@@ -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)
. = ..()
+2
View File
@@ -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))
@@ -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
+8 -8
View File
@@ -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)] &deg;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
+2
View File
@@ -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)
. = ..()
@@ -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>")
+3 -1
View File
@@ -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)
. = ..()
+6 -6
View File
@@ -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")
+2
View File
@@ -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)
@@ -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)
. = ..()
@@ -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 ..()
@@ -696,5 +725,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
+3 -1
View File
@@ -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))
+1 -11
View File
@@ -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))
+1
View File
@@ -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)
+2 -1
View File
@@ -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)
+3 -1
View File
@@ -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)
. = ..()
+4
View File
@@ -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
+1
View File
@@ -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"
@@ -522,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))
@@ -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"
@@ -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)
+1 -2
View File
@@ -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.
+2 -1
View File
@@ -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