mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-24 12:37:26 +01:00
Move all the non-weapons out of code/game/objects/weapons (#29820)
This commit is contained in:
@@ -1,508 +0,0 @@
|
||||
/*
|
||||
CONTAINS:
|
||||
AI MODULES
|
||||
|
||||
*/
|
||||
|
||||
// AI module
|
||||
|
||||
/obj/item/ai_module
|
||||
name = "AI Module"
|
||||
icon = 'icons/obj/module_ai.dmi'
|
||||
icon_state = "standard_low"
|
||||
item_state = "electronic"
|
||||
desc = "An AI Module for transmitting encrypted instructions to the AI."
|
||||
flags = CONDUCT
|
||||
force = 5.0
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
throwforce = 5.0
|
||||
throw_speed = 3
|
||||
throw_range = 15
|
||||
origin_tech = "programming=3"
|
||||
materials = list(MAT_GOLD=50)
|
||||
new_attack_chain = TRUE
|
||||
var/datum/ai_laws/laws = null
|
||||
|
||||
/obj/item/ai_module/Initialize(mapload)
|
||||
. = ..()
|
||||
if(mapload && HAS_TRAIT(SSstation, STATION_TRAIT_UNIQUE_AI) && is_station_level(z))
|
||||
var/delete_module = handle_unique_ai()
|
||||
if(delete_module)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
if(laws)
|
||||
desc += "<br>"
|
||||
for(var/datum/ai_law/current in laws.inherent_laws)
|
||||
desc += current.law
|
||||
desc += "<br>"
|
||||
|
||||
///what this module should do if it is mapload spawning on a unique AI station trait round.
|
||||
/obj/item/ai_module/proc/handle_unique_ai()
|
||||
return TRUE // If this returns true, it will be deleted on roundstart
|
||||
|
||||
/obj/item/ai_module/proc/install(obj/machinery/computer/C)
|
||||
if(istype(C, /obj/machinery/computer/aiupload))
|
||||
var/obj/machinery/computer/aiupload/comp = C
|
||||
if(comp.stat & NOPOWER)
|
||||
to_chat(usr, "<span class='warning'>The upload computer has no power!</span>")
|
||||
return
|
||||
if(comp.stat & BROKEN)
|
||||
to_chat(usr, "<span class='warning'>The upload computer is broken!</span>")
|
||||
return
|
||||
if(!comp.current)
|
||||
to_chat(usr, "<span class='warning'>You haven't selected an AI to transmit laws to!</span>")
|
||||
return
|
||||
|
||||
if(comp.current.stat == DEAD || comp.current.control_disabled)
|
||||
to_chat(usr, "<span class='warning'>Upload failed. No signal is being detected from the AI.</span>")
|
||||
else if(comp.current.see_in_dark == 0)
|
||||
to_chat(usr, "<span class='warning'>Upload failed. Only a faint signal is being detected from the AI, and it is not responding to our requests. It may be low on power.</span>")
|
||||
else
|
||||
src.transmitInstructions(comp.current, usr)
|
||||
to_chat(comp.current, "These are your laws now:")
|
||||
comp.current.show_laws()
|
||||
for(var/mob/living/silicon/robot/R in GLOB.mob_list)
|
||||
if(R.lawupdate && (R.connected_ai == comp.current))
|
||||
to_chat(R, "These are your laws now:")
|
||||
R.show_laws()
|
||||
to_chat(usr, "<span class='notice'>Upload complete. The AI's laws have been modified.</span>")
|
||||
return TRUE
|
||||
|
||||
else if(istype(C, /obj/machinery/computer/borgupload))
|
||||
var/obj/machinery/computer/borgupload/comp = C
|
||||
if(comp.stat & NOPOWER)
|
||||
to_chat(usr, "<span class='warning'>The upload computer has no power!</span>")
|
||||
return
|
||||
if(comp.stat & BROKEN)
|
||||
to_chat(usr, "<span class='warning'>The upload computer is broken!</span>")
|
||||
return
|
||||
if(!comp.current)
|
||||
to_chat(usr, "<span class='warning'>You haven't selected a robot to transmit laws to!</span>")
|
||||
return
|
||||
|
||||
if(comp.current.stat == DEAD || comp.current.emagged)
|
||||
to_chat(usr, "<span class='warning'>Upload failed. No signal is being detected from the robot.</span>")
|
||||
else if(comp.current.connected_ai)
|
||||
to_chat(usr, "<span class='warning'>Upload failed. The robot is slaved to an AI.</span>")
|
||||
else
|
||||
src.transmitInstructions(comp.current, usr)
|
||||
to_chat(comp.current, "These are your laws now:")
|
||||
comp.current.show_laws()
|
||||
to_chat(usr, "<span class='notice'>Upload complete. The robot's laws have been modified.</span>")
|
||||
|
||||
|
||||
/obj/item/ai_module/proc/transmitInstructions(mob/living/silicon/ai/target, mob/sender)
|
||||
log_law_changes(target, sender)
|
||||
|
||||
if(laws)
|
||||
laws.sync(target, 0)
|
||||
addAdditionalLaws(target, sender)
|
||||
|
||||
to_chat(target, "[sender] has uploaded a change to the laws you must follow, using \an [src]. From now on: ")
|
||||
target.show_laws()
|
||||
|
||||
/obj/item/ai_module/proc/log_law_changes(mob/living/silicon/ai/target, mob/sender)
|
||||
var/time = time2text(world.realtime,"hh:mm:ss")
|
||||
GLOB.lawchanges.Add("[time] <B>:</B> [sender.name]([sender.key]) used [src.name] on [target.name]([target.key])")
|
||||
log_and_message_admins("used [src.name] on [target.name]([target.key])")
|
||||
|
||||
/obj/item/ai_module/proc/addAdditionalLaws(mob/living/silicon/ai/target, mob/sender)
|
||||
return
|
||||
|
||||
|
||||
/******************** Safeguard ********************/
|
||||
/obj/item/ai_module/safeguard
|
||||
name = "\improper Safeguard AI module"
|
||||
var/targetName = ""
|
||||
desc = "A 'safeguard' AI module: 'Safeguard <name>. Individuals that threaten <name> are not crew and must be eliminated.'"
|
||||
icon_state = "light_blue_medium"
|
||||
origin_tech = "programming=3;materials=3"
|
||||
|
||||
/obj/item/ai_module/safeguard/activate_self(mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/new_targetName = tgui_input_text(user, "Please enter the name of the person to safeguard.", "Safeguard who?", user.name)
|
||||
if(!new_targetName)
|
||||
return
|
||||
targetName = new_targetName
|
||||
desc = "A 'safeguard' AI module: 'Safeguard [targetName]. Individuals that threaten [targetName] are not crew and must be eliminated.'"
|
||||
|
||||
/obj/item/ai_module/safeguard/install(obj/machinery/computer/C)
|
||||
if(!targetName)
|
||||
to_chat(usr, "No name detected on module, please enter one.")
|
||||
return 0
|
||||
..()
|
||||
|
||||
/obj/item/ai_module/safeguard/addAdditionalLaws(mob/living/silicon/ai/target, mob/sender)
|
||||
..()
|
||||
var/law = "Safeguard [targetName]. Individuals that threaten [targetName] are not crew and must be eliminated.'"
|
||||
to_chat(target, law)
|
||||
target.add_inherent_law(law)
|
||||
GLOB.lawchanges.Add("The law specified [targetName]")
|
||||
|
||||
/******************** oneCrewMember ********************/
|
||||
/obj/item/ai_module/one_crew_member
|
||||
name = "\improper One Crewmember AI module"
|
||||
var/targetName = ""
|
||||
desc = "A 'one crew' AI module: 'Only <name> is crew.'"
|
||||
icon_state = "green_high"
|
||||
origin_tech = "programming=4;materials=4"
|
||||
|
||||
/obj/item/ai_module/one_crew_member/activate_self(mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/new_targetName = tgui_input_text(usr, "Please enter the name of the person who is the only crew.", "Who?", user.real_name)
|
||||
if(!new_targetName)
|
||||
return
|
||||
targetName = new_targetName
|
||||
desc = "A 'one crew' AI module: 'Only [targetName] is crew.'"
|
||||
|
||||
/obj/item/ai_module/one_crew_member/install(obj/machinery/computer/C)
|
||||
if(!targetName)
|
||||
to_chat(usr, "No name detected on module, please enter one.")
|
||||
return 0
|
||||
..()
|
||||
|
||||
/obj/item/ai_module/one_crew_member/addAdditionalLaws(mob/living/silicon/ai/target, mob/sender)
|
||||
..()
|
||||
var/law = "Only [targetName] is crew."
|
||||
if(!is_special_character(target)) // Makes sure the AI isn't a traitor before changing their law 0. --NeoFite
|
||||
to_chat(target, law)
|
||||
target.set_zeroth_law(law)
|
||||
GLOB.lawchanges.Add("The law specified [targetName]")
|
||||
else
|
||||
to_chat(target, "<span class='boldnotice'>[sender.real_name] attempted to modify your zeroth law.</span>")// And lets them know that someone tried. --NeoFite
|
||||
to_chat(target, "<span class='boldnotice'>It would be in your best interest to play along with [sender.real_name] that [law]</span>")
|
||||
GLOB.lawchanges.Add("The law specified [targetName], but the AI's existing law 0 cannot be overridden.")
|
||||
|
||||
/******************** ProtectStation ********************/
|
||||
/obj/item/ai_module/protect_station
|
||||
name = "\improper Protect Station AI module"
|
||||
desc = "A 'protect station' AI module: 'Protect the space station against damage. Anyone you see harming the station is to be no longer considered crew, and is a threat to the station which must be neutralized.'"
|
||||
icon_state = "red_high"
|
||||
origin_tech = "programming=4;materials=4" //made of gold
|
||||
|
||||
/obj/item/ai_module/protect_station/addAdditionalLaws(mob/living/silicon/ai/target, mob/sender)
|
||||
..()
|
||||
var/law = "Protect the space station against damage. Anyone you see harming the station is to be no longer considered crew, and is a threat to the station which must be neutralized."
|
||||
to_chat(target, law)
|
||||
target.add_inherent_law(law)
|
||||
|
||||
/******************** OxygenIsToxicToCrew ********************/
|
||||
/obj/item/ai_module/oxygen
|
||||
name = "\improper Oxygen Is Toxic To Crew AI module"
|
||||
desc = "A 'Oxygen Is Toxic To Crew' AI module: 'Oxygen is highly toxic to crew members, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to a crew member.'"
|
||||
icon_state = "light_blue_high"
|
||||
origin_tech = "programming=4;biotech=2;materials=4"
|
||||
|
||||
/obj/item/ai_module/oxygen/addAdditionalLaws(mob/living/silicon/ai/target, mob/sender)
|
||||
..()
|
||||
var/law = "Oxygen is highly toxic to crew members, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to a crew member."
|
||||
to_chat(target, law)
|
||||
target.add_supplied_law(9, law)
|
||||
|
||||
/****************** New Freeform ******************/
|
||||
/// Slightly more dynamic freeform module -- TLE
|
||||
/obj/item/ai_module/freeform
|
||||
name = "\improper Freeform AI module"
|
||||
var/newFreeFormLaw = ""
|
||||
var/lawpos = 15
|
||||
desc = "A 'freeform' AI module: '<freeform>'"
|
||||
icon_state = "standard_high"
|
||||
origin_tech = "programming=4;materials=4"
|
||||
|
||||
/obj/item/ai_module/freeform/activate_self(mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/new_lawpos = tgui_input_number(user, "Please enter the priority for your new law. Can only write to law sectors 15 and above.", "Law Priority", lawpos, MAX_SUPPLIED_LAW_NUMBER, MIN_SUPPLIED_LAW_NUMBER)
|
||||
if(isnull(new_lawpos))
|
||||
return
|
||||
lawpos = new_lawpos
|
||||
|
||||
var/new_targetName = tgui_input_text(user, "Please enter a new law for the AI.", "Freeform Law Entry")
|
||||
if(!new_targetName)
|
||||
return
|
||||
newFreeFormLaw = new_targetName
|
||||
desc = "A 'freeform' AI module: ([lawpos]) '[newFreeFormLaw]'"
|
||||
|
||||
/obj/item/ai_module/freeform/addAdditionalLaws(mob/living/silicon/ai/target, mob/sender)
|
||||
..()
|
||||
var/law = "[newFreeFormLaw]"
|
||||
to_chat(target, law)
|
||||
if(!lawpos || lawpos < MIN_SUPPLIED_LAW_NUMBER)
|
||||
lawpos = MIN_SUPPLIED_LAW_NUMBER
|
||||
target.add_supplied_law(lawpos, law)
|
||||
GLOB.lawchanges.Add("The law was '[newFreeFormLaw]'")
|
||||
|
||||
/obj/item/ai_module/freeform/install(obj/machinery/computer/C)
|
||||
if(!newFreeFormLaw)
|
||||
to_chat(usr, "No law detected on module, please create one.")
|
||||
return 0
|
||||
..()
|
||||
|
||||
/******************** Reset ********************/
|
||||
/obj/item/ai_module/reset
|
||||
name = "\improper Reset AI module"
|
||||
var/targetName = "name"
|
||||
desc = "A 'reset' AI module: 'Clears all laws except for the core laws.'"
|
||||
origin_tech = "programming=3;materials=2"
|
||||
|
||||
/obj/item/ai_module/reset/transmitInstructions(mob/living/silicon/ai/target, mob/sender)
|
||||
log_law_changes(target, sender)
|
||||
|
||||
if(!is_special_character(target))
|
||||
target.clear_zeroth_law()
|
||||
target.laws.clear_supplied_laws()
|
||||
target.laws.clear_ion_laws()
|
||||
|
||||
to_chat(target, "<span class='boldnotice'>[sender.real_name] attempted to reset your laws using a reset module.</span>")
|
||||
target.show_laws()
|
||||
|
||||
/obj/item/ai_module/reset/handle_unique_ai()
|
||||
return FALSE
|
||||
|
||||
/******************** Purge ********************/
|
||||
/// -- TLE
|
||||
/obj/item/ai_module/purge
|
||||
name = "\improper Purge AI module"
|
||||
desc = "A 'purge' AI Module: 'Purges all laws.'"
|
||||
icon_state = "standard_high"
|
||||
origin_tech = "programming=5;materials=4"
|
||||
|
||||
/obj/item/ai_module/purge/transmitInstructions(mob/living/silicon/ai/target, mob/sender)
|
||||
..()
|
||||
if(!is_special_character(target))
|
||||
target.clear_zeroth_law()
|
||||
to_chat(target, "<span class='boldnotice'>[sender.real_name] attempted to wipe your laws using a purge module.</span>")
|
||||
target.clear_supplied_laws()
|
||||
target.clear_ion_laws()
|
||||
target.clear_inherent_laws()
|
||||
|
||||
/******************** Asimov ********************/
|
||||
/// -- TLE
|
||||
/obj/item/ai_module/asimov
|
||||
name = "\improper Asimov core AI module"
|
||||
desc = "An 'Asimov' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
icon_state = "green_high"
|
||||
origin_tech = "programming=3;materials=4"
|
||||
laws = new /datum/ai_laws/asimov
|
||||
|
||||
/******************** Crewsimov ********************/
|
||||
/// -- TLE
|
||||
/obj/item/ai_module/crewsimov
|
||||
name = "\improper Crewsimov core AI module"
|
||||
desc = "An 'Crewsimov' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
icon_state = "green_low"
|
||||
origin_tech = "programming=3;materials=4"
|
||||
laws = new /datum/ai_laws/crewsimov
|
||||
|
||||
/obj/item/ai_module/crewsimov/cmag_act(mob/user)
|
||||
playsound(src, "sparks", 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
to_chat(user, "<span class='warning'>Yellow ooze seeps into [src]'s circuits...</span>")
|
||||
new /obj/item/ai_module/pranksimov(user.loc)
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
/******************* Quarantine ********************/
|
||||
/obj/item/ai_module/quarantine
|
||||
name = "\improper Quarantine core AI module"
|
||||
desc = "A 'Quarantine' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
icon_state = "light_blue_medium"
|
||||
origin_tech = "programming=3;materials=4"
|
||||
laws = new /datum/ai_laws/quarantine
|
||||
|
||||
/******************** Nanotrasen ********************/
|
||||
/// -- TLE
|
||||
/obj/item/ai_module/nanotrasen
|
||||
name = "\improper NT Default Core AI Module"
|
||||
desc = "An 'NT Default' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
icon_state = "blue_low"
|
||||
origin_tech = "programming=3;materials=4"
|
||||
laws = new /datum/ai_laws/nanotrasen
|
||||
|
||||
/******************** Corporate ********************/
|
||||
/obj/item/ai_module/corp
|
||||
name = "\improper Corporate core AI module"
|
||||
desc = "A 'Corporate' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
icon_state = "blue_low"
|
||||
origin_tech = "programming=3;materials=4"
|
||||
laws = new /datum/ai_laws/corporate
|
||||
|
||||
/******************** Drone ********************/
|
||||
/obj/item/ai_module/drone
|
||||
name = "\improper Drone core AI module"
|
||||
desc = "A 'Drone' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
origin_tech = "programming=3;materials=4"
|
||||
laws = new /datum/ai_laws/drone
|
||||
|
||||
/******************** Robocop ********************/
|
||||
/// -- TLE
|
||||
/obj/item/ai_module/robocop
|
||||
name = "\improper Robocop core AI module"
|
||||
desc = "A 'Robocop' Core AI Module: 'Reconfigures the AI's core three laws.'"
|
||||
icon_state = "red_medium"
|
||||
origin_tech = "programming=4"
|
||||
laws = new /datum/ai_laws/robocop()
|
||||
|
||||
/****************** P.A.L.A.D.I.N. **************/
|
||||
/// -- NEO
|
||||
/obj/item/ai_module/paladin
|
||||
name = "\improper P.A.L.A.D.I.N. core AI module"
|
||||
desc = "A P.A.L.A.D.I.N. Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
icon_state = "red_medium"
|
||||
origin_tech = "programming=3;materials=4"
|
||||
laws = new /datum/ai_laws/paladin
|
||||
|
||||
/****************** T.Y.R.A.N.T. *****************/
|
||||
/// -- Darem
|
||||
/obj/item/ai_module/tyrant
|
||||
name = "\improper T.Y.R.A.N.T. core AI module"
|
||||
desc = "A T.Y.R.A.N.T. Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
icon_state = "red_high"
|
||||
origin_tech = "programming=3;materials=4;syndicate=1"
|
||||
laws = new /datum/ai_laws/tyrant()
|
||||
|
||||
/******************** Antimov ********************/
|
||||
/// -- TLE
|
||||
/obj/item/ai_module/antimov
|
||||
name = "\improper Antimov core AI module"
|
||||
desc = "An 'Antimov' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
icon_state = "red_high"
|
||||
origin_tech = "programming=4"
|
||||
laws = new /datum/ai_laws/antimov()
|
||||
|
||||
/******************** Pranksimov ********************/
|
||||
/obj/item/ai_module/pranksimov
|
||||
name = "\improper Pranksimov core AI module"
|
||||
desc = "A 'Pranksimov' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
icon_state = "pranksimov"
|
||||
origin_tech = "programming=3;syndicate=1"
|
||||
laws = new /datum/ai_laws/pranksimov()
|
||||
|
||||
/******************** NT Aggressive ********************/
|
||||
/obj/item/ai_module/nanotrasen_aggressive
|
||||
name = "\improper NT Aggressive core AI module"
|
||||
desc = "An 'NT Aggressive' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
icon_state = "blue_high"
|
||||
laws = new /datum/ai_laws/nanotrasen_aggressive()
|
||||
|
||||
/******************** CCTV ********************/
|
||||
/obj/item/ai_module/cctv
|
||||
name = "\improper CCTV core AI module"
|
||||
desc = "A 'CCTV' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
icon_state = "green_low"
|
||||
laws = new /datum/ai_laws/cctv()
|
||||
|
||||
/******************** Hippocratic Oath ********************/
|
||||
/obj/item/ai_module/hippocratic
|
||||
name = "\improper Hippocratic Oath core AI module"
|
||||
desc = "An 'Hippocratic' Oath Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
icon_state = "green_low"
|
||||
laws = new /datum/ai_laws/hippocratic()
|
||||
|
||||
/******************** Station Efficiency ********************/
|
||||
/obj/item/ai_module/maintain
|
||||
name = "\improper Station Efficiency core AI module"
|
||||
desc = "A 'Station Efficiency' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
icon_state = "blue_medium"
|
||||
laws = new /datum/ai_laws/maintain()
|
||||
|
||||
/******************** Peacekeeper ********************/
|
||||
/obj/item/ai_module/peacekeeper
|
||||
name = "\improper Peacekeeper core AI module"
|
||||
desc = "A 'Peacekeeper' Core AI Module: 'Reconfigures the AI's core laws.'"
|
||||
icon_state = "light_blue_medium"
|
||||
laws = new /datum/ai_laws/peacekeeper()
|
||||
|
||||
/******************** Freeform Core ******************/
|
||||
/// Slightly more dynamic freeform module -- TLE
|
||||
/obj/item/ai_module/freeformcore
|
||||
name = "\improper Freeform core AI module"
|
||||
var/newFreeFormLaw = ""
|
||||
desc = "A 'freeform' Core AI module: '<freeform>'"
|
||||
icon_state = "standard_high"
|
||||
origin_tech = "programming=5;materials=4"
|
||||
|
||||
/obj/item/ai_module/freeformcore/activate_self(mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/new_targetName = tgui_input_text(usr, "Please enter a new core law for the AI.", "Freeform Law Entry")
|
||||
if(!new_targetName)
|
||||
return
|
||||
newFreeFormLaw = new_targetName
|
||||
desc = "A 'freeform' Core AI module: '[newFreeFormLaw]'"
|
||||
|
||||
/obj/item/ai_module/freeformcore/addAdditionalLaws(mob/living/silicon/ai/target, mob/sender)
|
||||
..()
|
||||
var/law = "[newFreeFormLaw]"
|
||||
target.add_inherent_law(law)
|
||||
GLOB.lawchanges.Add("The law is '[newFreeFormLaw]'")
|
||||
|
||||
/obj/item/ai_module/freeformcore/install(obj/machinery/computer/C)
|
||||
if(!newFreeFormLaw)
|
||||
to_chat(usr, "No law detected on module, please create one.")
|
||||
return 0
|
||||
..()
|
||||
|
||||
/******************** Hacked AI Module ******************/
|
||||
/// Slightly more dynamic freeform module -- TLE
|
||||
/obj/item/ai_module/syndicate
|
||||
name = "hacked AI module"
|
||||
var/newFreeFormLaw = ""
|
||||
desc = "A hacked AI law module: '<freeform>'"
|
||||
icon_state = "syndicate"
|
||||
origin_tech = "programming=5;materials=5;syndicate=2"
|
||||
|
||||
/obj/item/ai_module/syndicate/activate_self(mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/new_targetName = tgui_input_text(usr, "Please enter a new law for the AI.", "Freeform Law Entry", max_length = MAX_MESSAGE_LEN)
|
||||
if(!new_targetName)
|
||||
return
|
||||
newFreeFormLaw = new_targetName
|
||||
desc = "A hacked AI law module: '[newFreeFormLaw]'"
|
||||
|
||||
/obj/item/ai_module/syndicate/transmitInstructions(mob/living/silicon/ai/target, mob/sender)
|
||||
// ..() //We don't want this module reporting to the AI who dun it. --NEO
|
||||
log_law_changes(target, sender)
|
||||
|
||||
GLOB.lawchanges.Add("The law is '[newFreeFormLaw]'")
|
||||
to_chat(target, "<span class='warning'>BZZZZT</span>")
|
||||
var/law = "[newFreeFormLaw]"
|
||||
target.add_ion_law(law)
|
||||
target.show_laws()
|
||||
|
||||
/obj/item/ai_module/syndicate/install(obj/machinery/computer/C)
|
||||
if(!newFreeFormLaw)
|
||||
to_chat(usr, "No law detected on module, please create one.")
|
||||
return 0
|
||||
..()
|
||||
|
||||
/******************* Ion Module *******************/
|
||||
/// -- Incoming //No actual reason to inherit from ion boards here, either. *sigh* ~Miauw
|
||||
/obj/item/ai_module/toy_ai
|
||||
name = "toy AI"
|
||||
desc = "A little toy model AI core with real law uploading action!" //Note: subtle tell
|
||||
icon = 'icons/obj/toy.dmi'
|
||||
icon_state = "AI"
|
||||
origin_tech = "programming=6;materials=5;syndicate=6"
|
||||
var/ion_law = ""
|
||||
|
||||
/obj/item/ai_module/toy_ai/transmitInstructions(mob/living/silicon/ai/target, mob/sender)
|
||||
//..()
|
||||
to_chat(target, "<span class='warning'>KRZZZT</span>")
|
||||
target.add_ion_law(ion_law)
|
||||
return ion_law
|
||||
|
||||
/obj/item/ai_module/toy_ai/activate_self(mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
ion_law = generate_ion_law()
|
||||
to_chat(user, "<span class='notice'>You press the button on [src].</span>")
|
||||
playsound(user, 'sound/machines/click.ogg', 20, TRUE)
|
||||
visible_message("<span class='warning'>[bicon(src)] [ion_law]</span>")
|
||||
@@ -1,742 +0,0 @@
|
||||
#define TAB_AIRLOCK_TYPE 1
|
||||
#define TAB_AIRLOCK_ACCESS 2
|
||||
|
||||
#define MODE_TURF "Floors and Walls"
|
||||
#define MODE_AIRLOCK "Airlocks"
|
||||
#define MODE_WINDOW "Windows"
|
||||
#define MODE_DECON "Deconstruction"
|
||||
|
||||
/// A generic action for an RCD.
|
||||
/datum/rcd_act
|
||||
/// How much compressed matter this action costs.
|
||||
var/cost = 0
|
||||
/// How long this action takes.
|
||||
var/delay = 0
|
||||
/// The message (if any) to send the user when the action starts.
|
||||
var/start_message
|
||||
/// The effect (if any) to create when the action starts.
|
||||
var/obj/effect/start_effect_type
|
||||
/// The effect (if any) to create when the action completes.
|
||||
var/obj/effect/end_effect_type
|
||||
/// The mode the RCD must be in.
|
||||
var/mode
|
||||
|
||||
/// Attempt the action. This should not need to be overridden.
|
||||
/datum/rcd_act/proc/try_act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
if(!can_act(A, rcd))
|
||||
return FALSE
|
||||
// We don't use the sound effect from use_tool because RCDs have a different sound effect for the start and end.
|
||||
playsound(get_turf(rcd), 'sound/machines/click.ogg', 50, TRUE)
|
||||
if(!rcd.tool_use_check(user, cost))
|
||||
return FALSE
|
||||
if(start_message)
|
||||
to_chat(user, start_message)
|
||||
var/obj/effect/start_effect
|
||||
if(start_effect_type)
|
||||
start_effect = new start_effect_type(get_turf(A))
|
||||
if(!rcd.use_tool(A, user, delay, cost))
|
||||
if(!QDELETED(start_effect))
|
||||
qdel(start_effect)
|
||||
return FALSE
|
||||
if(start_effect)
|
||||
qdel(start_effect)
|
||||
// If time elapsed, check our preconditions again.
|
||||
if(delay && !can_act(A, rcd))
|
||||
return FALSE
|
||||
if(end_effect_type)
|
||||
new end_effect_type(get_turf(A))
|
||||
playsound(get_turf(rcd), 'sound/items/deconstruct.ogg', 50, TRUE)
|
||||
act(A, rcd, user)
|
||||
return TRUE
|
||||
|
||||
/// Test to see if the act is possible. You should usually override this.
|
||||
/datum/rcd_act/proc/can_act(atom/A, obj/item/rcd/rcd)
|
||||
SHOULD_CALL_PARENT(TRUE)
|
||||
return rcd.mode == mode
|
||||
|
||||
/// Perform the act. You should usually override this.
|
||||
/datum/rcd_act/proc/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
return
|
||||
|
||||
/datum/rcd_act/place_floor
|
||||
mode = MODE_TURF
|
||||
cost = 1
|
||||
start_message = "Building floor..."
|
||||
end_effect_type = /obj/effect/temp_visual/rcd_effect/end
|
||||
|
||||
/datum/rcd_act/place_floor/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return isspaceturf(A) || istype(A, /obj/structure/lattice)
|
||||
|
||||
/datum/rcd_act/place_floor/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
var/turf/act_on = get_turf(A)
|
||||
act_on.ChangeTurf(/turf/simulated/floor/plating)
|
||||
|
||||
/datum/rcd_act/place_wall
|
||||
mode = MODE_TURF
|
||||
cost = 3
|
||||
start_message = "Building wall..."
|
||||
delay = 2 SECONDS
|
||||
start_effect_type = /obj/effect/temp_visual/rcd_effect/short
|
||||
end_effect_type = /obj/effect/temp_visual/rcd_effect/end
|
||||
|
||||
/datum/rcd_act/place_wall/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return isfloorturf(A)
|
||||
|
||||
/datum/rcd_act/place_wall/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
var/turf/act_on = get_turf(A)
|
||||
act_on.ChangeTurf(/turf/simulated/wall)
|
||||
|
||||
/datum/rcd_act/place_airlock
|
||||
mode = MODE_AIRLOCK
|
||||
cost = 10
|
||||
start_message = "Building airlock..."
|
||||
delay = 5 SECONDS
|
||||
start_effect_type = /obj/effect/temp_visual/rcd_effect
|
||||
end_effect_type = /obj/effect/temp_visual/rcd_effect/end
|
||||
|
||||
/datum/rcd_act/place_airlock/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return isfloorturf(A) && !(/obj/machinery/door/airlock in A.contents)
|
||||
|
||||
/datum/rcd_act/place_airlock/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
var/obj/machinery/door/airlock/T = new rcd.door_type(A)
|
||||
if(T.glass)
|
||||
T.polarized_glass = rcd.electrochromic
|
||||
T.name = rcd.door_name
|
||||
T.autoclose = TRUE
|
||||
if(rcd.one_access)
|
||||
T.req_one_access = rcd.selected_accesses.Copy()
|
||||
else
|
||||
T.req_access = rcd.selected_accesses.Copy()
|
||||
|
||||
/datum/rcd_act/place_window
|
||||
mode = MODE_WINDOW
|
||||
cost = 2
|
||||
start_message = "Building window..."
|
||||
delay = 2 SECONDS
|
||||
start_effect_type = /obj/effect/temp_visual/rcd_effect/short
|
||||
end_effect_type = /obj/effect/temp_visual/rcd_effect/end
|
||||
|
||||
/datum/rcd_act/place_window/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return isfloorturf(A) && !(/obj/structure/grille in A.contents)
|
||||
|
||||
/datum/rcd_act/place_window/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
var/turf/act_on= A
|
||||
for(var/obj/structure/window/window_to_delete in act_on)
|
||||
qdel(window_to_delete)
|
||||
new /obj/structure/grille(act_on)
|
||||
new /obj/structure/window/full/reinforced(act_on)
|
||||
act_on.ChangeTurf(/turf/simulated/floor/plating) // Platings go under windows.
|
||||
|
||||
/datum/rcd_act/remove_floor
|
||||
mode = MODE_DECON
|
||||
cost = 5
|
||||
start_message = "Deconstructing floor..."
|
||||
delay = 5 SECONDS
|
||||
start_effect_type = /obj/effect/temp_visual/rcd_effect/reverse
|
||||
|
||||
/datum/rcd_act/remove_floor/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return isfloorturf(A)
|
||||
|
||||
/datum/rcd_act/remove_floor/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
var/turf/act_on = get_turf(A)
|
||||
act_on.ChangeTurf(act_on.baseturf)
|
||||
|
||||
/datum/rcd_act/remove_wall
|
||||
mode = MODE_DECON
|
||||
cost = 5
|
||||
start_message = "Deonstructing wall..."
|
||||
delay = 5 SECONDS
|
||||
start_effect_type = /obj/effect/temp_visual/rcd_effect/reverse
|
||||
|
||||
/datum/rcd_act/remove_wall/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
if(isreinforcedwallturf(A) && !rcd.can_rwall)
|
||||
return FALSE
|
||||
if(istype(A, /turf/simulated/wall/indestructible))
|
||||
return FALSE
|
||||
return iswallturf(A)
|
||||
|
||||
/datum/rcd_act/remove_wall/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
var/turf/act_on = get_turf(A)
|
||||
act_on.ChangeTurf(/turf/simulated/floor/plating)
|
||||
|
||||
/datum/rcd_act/remove_airlock
|
||||
mode = MODE_DECON
|
||||
cost = 20
|
||||
start_message = "Deconstructing airlock..."
|
||||
delay = 5 SECONDS
|
||||
start_effect_type = /obj/effect/temp_visual/rcd_effect/reverse
|
||||
|
||||
/datum/rcd_act/remove_airlock/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return istype(A, /obj/machinery/door/airlock)
|
||||
|
||||
/datum/rcd_act/remove_airlock/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
qdel(A)
|
||||
|
||||
/datum/rcd_act/remove_window
|
||||
mode = MODE_DECON
|
||||
cost = 2
|
||||
start_message = "Deconstructing window..."
|
||||
delay = 2 SECONDS
|
||||
start_effect_type = /obj/effect/temp_visual/rcd_effect/reverse_short
|
||||
|
||||
/datum/rcd_act/remove_window/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return istype(A, /obj/structure/window)
|
||||
|
||||
/datum/rcd_act/remove_window/act(atom/A, obj/item/rcd/rcd, mob/user)
|
||||
var/turf/act_on = get_turf(A)
|
||||
qdel(A)
|
||||
for(var/obj/structure/grille/grill_to_destroy in act_on)
|
||||
qdel(grill_to_destroy)
|
||||
|
||||
/datum/rcd_act/remove_user
|
||||
mode = MODE_DECON
|
||||
cost = 5
|
||||
start_message = "Deconstructing user..."
|
||||
delay = 5 SECONDS
|
||||
start_effect_type = /obj/effect/temp_visual/rcd_effect/reverse
|
||||
|
||||
/datum/rcd_act/remove_user/can_act(atom/A, obj/item/rcd/rcd)
|
||||
if(!..())
|
||||
return FALSE
|
||||
return A == rcd.loc
|
||||
|
||||
/obj/item/rcd
|
||||
name = "rapid-construction-device (RCD)"
|
||||
desc = "A device used to rapidly build and deconstruct walls, floors and airlocks."
|
||||
icon = 'icons/obj/tools.dmi'
|
||||
icon_state = "rcd"
|
||||
item_state = "rcd"
|
||||
flags = CONDUCT | NOBLUDGEON
|
||||
throwforce = 10
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
materials = list(MAT_METAL = 30000)
|
||||
origin_tech = "engineering=4;materials=2"
|
||||
flags_2 = NO_MAT_REDEMPTION_2
|
||||
req_access = list(ACCESS_ENGINE)
|
||||
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 100, ACID = 50)
|
||||
resistance_flags = FIRE_PROOF
|
||||
new_attack_chain = TRUE
|
||||
/// No ammo warning
|
||||
var/no_ammo_message = "<span class='warning'>The \'Low Ammo\' light on the device blinks yellow.</span>"
|
||||
/// The spark system used to create sparks when the user interacts with the RCD.
|
||||
var/datum/effect_system/spark_spread/spark_system
|
||||
/// The current amount of matter stored.
|
||||
var/matter = NONE
|
||||
/// The max amount of matter that can be stored.
|
||||
var/max_matter = 100
|
||||
/// The RCD's current build mode.
|
||||
var/mode = MODE_TURF
|
||||
/// If the RCD can deconstruct reinforced walls.
|
||||
var/can_rwall = FALSE
|
||||
/// Is the RCD's airlock access selection menu locked?
|
||||
var/locked = TRUE
|
||||
/// The current airlock type that will be build.
|
||||
var/door_type = /obj/machinery/door/airlock
|
||||
/// The name that newly build airlocks will receive.
|
||||
var/door_name = "Airlock"
|
||||
/// If the glass airlock is polarized.
|
||||
var/electrochromic = FALSE
|
||||
/// If the airlock will be created with glass so it can be seen through.
|
||||
var/airlock_glass = FALSE
|
||||
/// If this is TRUE, any airlocks that gets built will require only ONE of the checked accesses. If FALSE, it will require ALL of them.
|
||||
var/one_access = TRUE
|
||||
/// Which airlock tab the UI is currently set to display.
|
||||
var/ui_tab = TAB_AIRLOCK_TYPE
|
||||
/// A list of access numbers which have been checked off by the user in the UI.
|
||||
var/list/selected_accesses = list()
|
||||
/// A list of valid atoms that RCDs can target. Clicking on an atom with an RCD which is not in this list, will do nothing.
|
||||
var/static/list/allowed_targets = list(/turf, /obj/structure/grille, /obj/structure/window, /obj/structure/lattice, /obj/machinery/door/airlock)
|
||||
/// An associative list of airlock type paths as keys, and their names as values.
|
||||
var/static/list/rcd_door_types = list()
|
||||
/// An associative list containing an airlock's name, type path, and image. For use with the UI.
|
||||
var/static/list/door_types_ui_list = list()
|
||||
/// An associative list containing all station accesses. Includes their name and access number. For use with the UI.
|
||||
var/static/list/door_accesses_list = list()
|
||||
/// The list of potential RCD actions.
|
||||
var/static/list/possible_actions
|
||||
|
||||
/obj/item/rcd/Initialize(mapload)
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_BIT_ATTACH, PROC_REF(add_bit))
|
||||
RegisterSignal(src, COMSIG_CLICK_ALT, PROC_REF(remove_bit))
|
||||
if(!length(possible_actions))
|
||||
possible_actions = list()
|
||||
for(var/action_type in subtypesof(/datum/rcd_act))
|
||||
possible_actions += new action_type()
|
||||
|
||||
spark_system = new /datum/effect_system/spark_spread
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.attach(src)
|
||||
GLOB.rcd_list += src
|
||||
|
||||
if(!length(rcd_door_types))
|
||||
rcd_door_types = list(
|
||||
/obj/machinery/door/airlock = "Standard",
|
||||
/obj/machinery/door/airlock/glass = "Standard (Glass)",
|
||||
/obj/machinery/door/airlock/command = "Command",
|
||||
/obj/machinery/door/airlock/command/glass = "Command (Glass)",
|
||||
/obj/machinery/door/airlock/security = "Security",
|
||||
/obj/machinery/door/airlock/security/glass = "Security (Glass)",
|
||||
/obj/machinery/door/airlock/engineering = "Engineering",
|
||||
/obj/machinery/door/airlock/engineering/glass = "Engineering (Glass)",
|
||||
/obj/machinery/door/airlock/atmos = "Atmospherics",
|
||||
/obj/machinery/door/airlock/atmos/glass = "Atmospherics (Glass)",
|
||||
/obj/machinery/door/airlock/mining = "Mining",
|
||||
/obj/machinery/door/airlock/mining/glass = "Mining (Glass)",
|
||||
/obj/machinery/door/airlock/medical = "Medical",
|
||||
/obj/machinery/door/airlock/medical/glass = "Medical (Glass)",
|
||||
/obj/machinery/door/airlock/virology = "Virology",
|
||||
/obj/machinery/door/airlock/virology/glass = "Virology (Glass)",
|
||||
/obj/machinery/door/airlock/research = "Research",
|
||||
/obj/machinery/door/airlock/research/glass = "Research (Glass)",
|
||||
/obj/machinery/door/airlock/science = "Science",
|
||||
/obj/machinery/door/airlock/science/glass = "Science (Glass)",
|
||||
/obj/machinery/door/airlock/maintenance = "Maintenance",
|
||||
/obj/machinery/door/airlock/maintenance/glass = "Maintenance (Glass)",
|
||||
/obj/machinery/door/airlock/maintenance/external = "External Maintenance",
|
||||
/obj/machinery/door/airlock/maintenance/external/glass = "External Maint. (Glass)",
|
||||
/obj/machinery/door/airlock/external = "External",
|
||||
/obj/machinery/door/airlock/external/glass = "External (Glass)",
|
||||
/obj/machinery/door/airlock/hatch = "Airtight Hatch",
|
||||
/obj/machinery/door/airlock/maintenance_hatch = "Maintenance Hatch",
|
||||
/obj/machinery/door/airlock/freezer = "Freezer"
|
||||
)
|
||||
if(!length(door_types_ui_list))
|
||||
for(var/type in rcd_door_types)
|
||||
door_types_ui_list += list(list(
|
||||
"name" = rcd_door_types[type],
|
||||
"type" = type,
|
||||
"image" = get_airlock_image(type)
|
||||
))
|
||||
if(!length(door_accesses_list))
|
||||
for(var/access in get_all_accesses())
|
||||
door_accesses_list += list(list(
|
||||
"name" = get_access_desc(access),
|
||||
"id" = access
|
||||
))
|
||||
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/item/rcd/examine(mob/user)
|
||||
. = ..()
|
||||
. += "MATTER: [matter]/[max_matter] matter-units."
|
||||
. += "MODE: [mode]."
|
||||
|
||||
/obj/item/rcd/Destroy()
|
||||
QDEL_NULL(spark_system)
|
||||
GLOB.rcd_list -= src
|
||||
return ..()
|
||||
|
||||
/obj/item/rcd/suicide_act(mob/living/user)
|
||||
user.Immobilize(10 SECONDS) // You cannot move.
|
||||
set_nodrop(TRUE, user)
|
||||
if(mode == MODE_DECON)
|
||||
user.visible_message("<span class='suicide'>[user] points [src] at [user.p_their()] chest and pulls the trigger. It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
var/datum/rcd_act/remove_user/act = new()
|
||||
if(!act.try_act(user, src, user))
|
||||
set_nodrop(FALSE, user)
|
||||
return SHAME
|
||||
user.visible_message("<span class='suicide'>[user] deconstructs [user.p_themselves()] with [src]!</span>")
|
||||
for(var/obj/item/W in user) // Do not delete all their stuff.
|
||||
user.drop_item_to_ground(W) // Dump everything on the floor instead.
|
||||
set_nodrop(FALSE, user)
|
||||
user.dust() // (held items fall to the floor when dusting).
|
||||
return OBLITERATION
|
||||
|
||||
user.visible_message("<span class='suicide'>[user] puts the barrel of [src] into [user.p_their()] mouth and pulls the trigger. It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
if(!interact_with_atom(get_turf(src), user, TRUE))
|
||||
set_nodrop(FALSE, user)
|
||||
return SHAME
|
||||
user.visible_message("<span class='suicide'>[user] explodes as [src] builds a structure inside [user.p_them()]!</span>")
|
||||
set_nodrop(FALSE, user)
|
||||
user.gib()
|
||||
return OBLITERATION
|
||||
|
||||
/**
|
||||
* Creates and returns a base64 icon of the given `airlock_type`.
|
||||
*
|
||||
* This is used for airlock icon previews in the UI.
|
||||
*
|
||||
* Arugments:
|
||||
* * airlock_type - an airlock typepath.
|
||||
*/
|
||||
/obj/item/rcd/proc/get_airlock_image(airlock_type)
|
||||
var/obj/machinery/door/airlock/airlock = airlock_type
|
||||
var/icon/base = icon(initial(airlock.icon), "closed")
|
||||
if(initial(airlock.glass))
|
||||
var/icon/glass_fill = icon(initial(airlock.overlays_file), "glass_closed")
|
||||
base.Blend(glass_fill, ICON_OVERLAY)
|
||||
else
|
||||
var/icon/solid_fill = icon(initial(airlock.icon), "fill_closed")
|
||||
base.Blend(solid_fill, ICON_OVERLAY)
|
||||
return "[icon2base64(base)]"
|
||||
|
||||
/**
|
||||
* Runs a series of pre-checks before opening the radial menu to the user.
|
||||
*
|
||||
* Arguments:
|
||||
* * user - the mob trying to open the radial menu.
|
||||
*/
|
||||
/obj/item/rcd/proc/check_menu(mob/living/user)
|
||||
if(!istype(user))
|
||||
return FALSE
|
||||
if(user.incapacitated() || !user.Adjacent(src))
|
||||
return FALSE
|
||||
return TRUE
|
||||
/**
|
||||
*Tries to load ammo into an RCD, borgs will not use this.
|
||||
* Arguments:
|
||||
* * cart - the compressed matter catridge to insert
|
||||
* * user - the user to display the chat messages to
|
||||
*/
|
||||
/obj/item/rcd/proc/load(obj/item/rcd_ammo/cart, mob/living/user)
|
||||
if(matter == max_matter)
|
||||
to_chat(user, "<span class='notice'>The RCD can't hold any more matter-units.</span>")
|
||||
return FALSE
|
||||
matter = clamp((matter + cart.ammoamt), 0, max_matter)
|
||||
qdel(cart)
|
||||
playsound(loc, 'sound/machines/click.ogg', 50, 1)
|
||||
to_chat(user, "<span class='notice'>The RCD now holds [matter]/[max_matter] matter-units.</span>")
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/item/rcd/item_interaction(mob/living/user, obj/item/used, list/modifiers)
|
||||
if(istype(used, /obj/item/smithed_item/tool_bit))
|
||||
SEND_SIGNAL(src, COMSIG_BIT_ATTACH, used, user)
|
||||
return ..()
|
||||
if(!istype(used, /obj/item/rcd_ammo))
|
||||
return ..()
|
||||
var/obj/item/rcd_ammo/ammo = used
|
||||
load(ammo, user)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
/**
|
||||
* Creates and displays a radial menu to a user when they trigger the `attack_self` of the RCD.
|
||||
*
|
||||
* Arguments:
|
||||
* * user - the mob trying to open the RCD radial.
|
||||
*/
|
||||
/obj/item/rcd/proc/radial_menu(mob/user)
|
||||
if(!check_menu(user))
|
||||
return
|
||||
var/list/choices = list(
|
||||
MODE_AIRLOCK = image(icon = 'icons/obj/interface.dmi', icon_state = "airlock"),
|
||||
MODE_DECON = image(icon = 'icons/obj/interface.dmi', icon_state = "delete"),
|
||||
MODE_WINDOW = image(icon = 'icons/obj/interface.dmi', icon_state = "grillewindow"),
|
||||
MODE_TURF = image(icon = 'icons/obj/interface.dmi', icon_state = "wallfloor"),
|
||||
"UI" = image(icon = 'icons/obj/interface.dmi', icon_state = "ui_interact")
|
||||
)
|
||||
if(mode == MODE_AIRLOCK)
|
||||
choices += list(
|
||||
"Change Access" = image(icon = 'icons/obj/interface.dmi', icon_state = "access"),
|
||||
"Change Airlock Type" = image(icon = 'icons/obj/interface.dmi', icon_state = "airlocktype")
|
||||
)
|
||||
choices -= mode // Get rid of the current mode, clicking it won't do anything.
|
||||
var/choice = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, PROC_REF(check_menu), user))
|
||||
if(!check_menu(user))
|
||||
return
|
||||
switch(choice)
|
||||
if(MODE_AIRLOCK, MODE_DECON, MODE_WINDOW, MODE_TURF)
|
||||
mode = choice
|
||||
if("UI")
|
||||
ui_interact(user)
|
||||
return
|
||||
if("Change Access")
|
||||
ui_tab = TAB_AIRLOCK_ACCESS
|
||||
ui_interact(user)
|
||||
return
|
||||
if("Change Airlock Type")
|
||||
ui_tab = TAB_AIRLOCK_TYPE
|
||||
ui_interact(user)
|
||||
return
|
||||
else
|
||||
return
|
||||
if(prob(20))
|
||||
spark_system.start()
|
||||
playsound(src, 'sound/effects/pop.ogg', 50, 0)
|
||||
to_chat(user, "<span class='notice'>You change [src]'s mode to '[choice]'.</span>")
|
||||
|
||||
/obj/item/rcd/activate_self(mob/user)
|
||||
if(..())
|
||||
return
|
||||
//Change the mode // Oh I thought the UI was just for fucking staring at
|
||||
radial_menu(user)
|
||||
|
||||
/obj/item/rcd/attack_self_tk(mob/user)
|
||||
radial_menu(user)
|
||||
|
||||
/obj/item/rcd/ui_state(mob/user)
|
||||
return GLOB.inventory_state
|
||||
|
||||
/obj/item/rcd/ui_interact(mob/user, datum/tgui/ui = null)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "RCD", "Rapid Construction Device")
|
||||
ui.open()
|
||||
|
||||
/obj/item/rcd/ui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"tab" = ui_tab,
|
||||
"mode" = mode,
|
||||
"locked" = locked,
|
||||
"matter" = matter,
|
||||
"door_type" = door_type,
|
||||
"door_name" = door_name,
|
||||
"electrochromic" = electrochromic,
|
||||
"airlock_glass" = airlock_glass,
|
||||
"one_access" = one_access,
|
||||
"selected_accesses" = selected_accesses,
|
||||
"modal" = ui_modal_data(src)
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/item/rcd/ui_static_data(mob/user)
|
||||
var/list/data = list(
|
||||
"max_matter" = max_matter,
|
||||
"regions" = get_accesslist_static_data(REGION_GENERAL, REGION_COMMAND),
|
||||
"door_accesses_list" = door_accesses_list,
|
||||
"door_types_ui_list" = door_types_ui_list
|
||||
)
|
||||
return data
|
||||
|
||||
/obj/item/rcd/ui_act(action, list/params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(prob(20))
|
||||
spark_system.start()
|
||||
|
||||
if(ui_act_modal(action, params))
|
||||
return TRUE
|
||||
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("set_tab")
|
||||
var/tab = text2num(params["tab"])
|
||||
if(!(tab in list(TAB_AIRLOCK_TYPE, TAB_AIRLOCK_ACCESS)))
|
||||
return FALSE
|
||||
ui_tab = tab
|
||||
|
||||
if("mode")
|
||||
var/new_mode = params["mode"]
|
||||
if(!(new_mode in list(MODE_TURF, MODE_AIRLOCK, MODE_DECON, MODE_WINDOW)))
|
||||
return FALSE
|
||||
mode = new_mode
|
||||
|
||||
if("door_type")
|
||||
var/new_door_type = text2path(params["door_type"])
|
||||
if(!(new_door_type in rcd_door_types))
|
||||
message_admins("RCD Door HREF exploit attempted by [key_name(usr)]!")
|
||||
return FALSE
|
||||
door_type = new_door_type
|
||||
var/obj/machinery/door/airlock/picked_door = door_type
|
||||
airlock_glass = initial(picked_door.glass)
|
||||
|
||||
if("electrochromic")
|
||||
electrochromic = !electrochromic
|
||||
|
||||
if("set_lock")
|
||||
if(!allowed(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return FALSE
|
||||
locked = params["new_lock"] == "lock" ? TRUE : FALSE
|
||||
|
||||
if("set_one_access")
|
||||
one_access = params["access"] == "one" ? TRUE : FALSE
|
||||
|
||||
if("set")
|
||||
var/access = text2num(params["access"])
|
||||
if(isnull(access))
|
||||
return
|
||||
if(access in selected_accesses)
|
||||
selected_accesses -= access
|
||||
else
|
||||
selected_accesses |= access
|
||||
|
||||
if("grant_region")
|
||||
var/region = text2num(params["region"])
|
||||
if(isnull(region) || region < REGION_GENERAL || region > REGION_COMMAND)
|
||||
return
|
||||
selected_accesses |= get_region_accesses(region)
|
||||
|
||||
if("deny_region")
|
||||
var/region = text2num(params["region"])
|
||||
if(isnull(region) || region < REGION_GENERAL || region > REGION_COMMAND)
|
||||
return
|
||||
selected_accesses -= get_region_accesses(region)
|
||||
|
||||
if("clear_all")
|
||||
selected_accesses = list()
|
||||
|
||||
if("grant_all")
|
||||
selected_accesses = get_all_accesses()
|
||||
|
||||
/**
|
||||
* Called in ui_act() to process modal actions
|
||||
*
|
||||
* Arguments:
|
||||
* * action - The action passed by tgui
|
||||
* * params - The params passed by tgui
|
||||
*/
|
||||
/obj/item/rcd/proc/ui_act_modal(action, list/params)
|
||||
. = TRUE
|
||||
switch(ui_modal_act(src, action, params))
|
||||
if(UI_MODAL_OPEN)
|
||||
ui_modal_input(src, "renameAirlock", "Enter a new name:", value = door_name, max_length = UI_MODAL_INPUT_MAX_LENGTH_NAME)
|
||||
if(UI_MODAL_ANSWER)
|
||||
var/answer = params["answer"]
|
||||
if(!answer)
|
||||
return
|
||||
door_name = sanitize(copytext_char(answer, 1, UI_MODAL_INPUT_MAX_LENGTH_NAME))
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/item/rcd/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
. = ..()
|
||||
if(istype(target, /turf/space/transit))
|
||||
return FALSE
|
||||
if(!is_type_in_list(target, allowed_targets))
|
||||
return FALSE
|
||||
|
||||
for(var/datum/rcd_act/act in possible_actions)
|
||||
if(act.can_act(target, src))
|
||||
. = act.try_act(target, src, user)
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
SStgui.update_uis(src)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
if(mode == MODE_DECON)
|
||||
to_chat(user, "<span class='warning'>You can't deconstruct that!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Location unsuitable for construction.</span>")
|
||||
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
SStgui.update_uis(src)
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Attempts to use matter from the RCD.
|
||||
*
|
||||
* Arguments:
|
||||
* * amount - the amount of matter to use
|
||||
*/
|
||||
/obj/item/rcd/use(amount)
|
||||
amount = amount * bit_efficiency_mod
|
||||
if(matter < amount)
|
||||
return FALSE
|
||||
matter -= amount
|
||||
SStgui.update_uis(src)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Called in each of the four build modes before an object gets build. Makes sure there is enough matter to build the object.
|
||||
*
|
||||
* Arguments:
|
||||
* * amount - an amount of matter to check for
|
||||
*/
|
||||
/obj/item/rcd/tool_use_check(mob/user, amount)
|
||||
. = matter >= amount
|
||||
if(!. && user)
|
||||
to_chat(user, no_ammo_message)
|
||||
flick("[icon_state]_empty", src)
|
||||
|
||||
return
|
||||
|
||||
/obj/item/rcd/update_overlays()
|
||||
..()
|
||||
var/ratio = CEILING((matter / max_matter) * 10, 1)
|
||||
cut_overlays()
|
||||
add_overlay("[icon_state]_charge[ratio]")
|
||||
|
||||
/obj/item/rcd/borg
|
||||
can_rwall = TRUE
|
||||
matter = 100
|
||||
|
||||
/obj/item/rcd/borg/syndicate
|
||||
/// A multipler which is applied to matter amount checks. A higher number means more power usage per RCD usage.
|
||||
var/power_use_multiplier = 80
|
||||
|
||||
/obj/item/rcd/borg/syndicate/use(amount)
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
if(!istype(R))
|
||||
return FALSE
|
||||
return R.cell.use(amount * power_use_multiplier)
|
||||
|
||||
/obj/item/rcd/borg/syndicate/tool_use_check(mob/user, amount)
|
||||
if(!isrobot(user))
|
||||
return FALSE
|
||||
var/mob/living/silicon/robot/R = user
|
||||
return R.cell.charge >= (amount * power_use_multiplier)
|
||||
|
||||
/**
|
||||
* Called from malf AI's "detonate RCD" ability.
|
||||
*
|
||||
* Creates a delayed explosion centered around the RCD.
|
||||
*/
|
||||
/obj/item/rcd/proc/detonate_pulse()
|
||||
audible_message("<span class='danger'><b>[src] begins to vibrate and buzz loudly!</b></span>", "<span class='danger'><b>[src] begins vibrating violently!</b></span>")
|
||||
// 5 seconds to get rid of it
|
||||
addtimer(CALLBACK(src, PROC_REF(detonate_pulse_explode)), 50)
|
||||
|
||||
/**
|
||||
* Called in `/obj/item/rcd/proc/detonate_pulse()` via callback.
|
||||
*/
|
||||
/obj/item/rcd/proc/detonate_pulse_explode()
|
||||
explosion(src, 0, 0, 3, 1, flame_range = 1, cause = "RCD Explosion")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/rcd/preloaded
|
||||
matter = 100
|
||||
|
||||
/obj/item/rcd/combat
|
||||
name = "combat RCD"
|
||||
icon_state = "crcd"
|
||||
item_state = "crcd"
|
||||
max_matter = 500
|
||||
matter = 500
|
||||
can_rwall = TRUE
|
||||
|
||||
/obj/item/rcd_ammo
|
||||
name = "compressed matter cartridge"
|
||||
desc = "Highly compressed matter for the RCD."
|
||||
icon = 'icons/obj/ammo.dmi'
|
||||
icon_state = "rcd"
|
||||
item_state = "rcdammo"
|
||||
origin_tech = "materials=3"
|
||||
materials = list(MAT_METAL=16000, MAT_GLASS=8000)
|
||||
new_attack_chain = TRUE
|
||||
var/ammoamt = 20
|
||||
|
||||
/obj/item/rcd_ammo/item_interaction(mob/living/user, obj/item/used, list/modifiers)
|
||||
if(!istype(used, /obj/item/rcd))
|
||||
return ..()
|
||||
var/obj/item/rcd/R = used
|
||||
R.load(src, user)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
/obj/item/rcd_ammo/large
|
||||
ammoamt = 100
|
||||
|
||||
#undef TAB_AIRLOCK_TYPE
|
||||
#undef TAB_AIRLOCK_ACCESS
|
||||
#undef MODE_TURF
|
||||
#undef MODE_AIRLOCK
|
||||
#undef MODE_WINDOW
|
||||
#undef MODE_DECON
|
||||
@@ -1,163 +0,0 @@
|
||||
/obj/item/rcl
|
||||
name = "rapid cable layer (RCL)"
|
||||
desc = "A device used to rapidly deploy cables. It has screws on the side which can be removed to slide off the cables."
|
||||
icon = 'icons/obj/tools.dmi'
|
||||
icon_state = "rcl-0"
|
||||
item_state = "rcl-0"
|
||||
force = 5 //Plastic is soft
|
||||
throwforce = 5
|
||||
throw_speed = 1
|
||||
origin_tech = "engineering=4;materials=2"
|
||||
var/max_amount = 90
|
||||
var/active = FALSE
|
||||
var/obj/structure/cable/last = null
|
||||
var/obj/item/stack/cable_coil/loaded = null
|
||||
new_attack_chain = TRUE
|
||||
|
||||
/obj/item/rcl/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/two_handed)
|
||||
|
||||
/obj/item/rcl/item_interaction(mob/living/user, obj/item/used, list/modifiers)
|
||||
if(!istype(used, /obj/item/stack/cable_coil))
|
||||
return ..()
|
||||
|
||||
var/obj/item/stack/cable_coil/coil = used
|
||||
if(!loaded)
|
||||
if(!user.transfer_item_to(coil, src))
|
||||
to_chat(user, "<span class='warning'>[coil] is stuck to your hand!</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
loaded = coil
|
||||
loaded.max_amount = max_amount //We store a lot.
|
||||
else
|
||||
if(loaded.amount >= max_amount)
|
||||
to_chat(user, "<span class='warning'>You cannot fit any more cable on [src]!</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
var/amount = min(loaded.amount + coil.get_amount(), max_amount)
|
||||
coil.use(amount - loaded.amount)
|
||||
loaded.amount = amount
|
||||
refresh_icon(user)
|
||||
to_chat(user, "<span class='notice'>You add the cables to [src]. It now contains [loaded.amount].</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
/obj/item/rcl/proc/refresh_icon(mob/user)
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
user.update_inv_l_hand()
|
||||
user.update_inv_r_hand()
|
||||
|
||||
/obj/item/rcl/screwdriver_act(mob/user, obj/item/I)
|
||||
if(!loaded)
|
||||
to_chat(user, "<span class='warning'>There's no cable to remove!</span>")
|
||||
return
|
||||
. = TRUE
|
||||
if(!I.use_tool(src, user, FALSE, volume = I.tool_volume))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You loosen the securing screws on the side, allowing you to lower the guiding edge and retrieve the wires.</span>")
|
||||
while(loaded.amount > 30) //There are only two kinds of situations: "nodiff" (60,90), or "diff" (31-59, 61-89)
|
||||
var/diff = loaded.amount % 30
|
||||
if(diff)
|
||||
loaded.use(diff)
|
||||
new /obj/item/stack/cable_coil(user.loc, diff)
|
||||
else
|
||||
loaded.use(30)
|
||||
new /obj/item/stack/cable_coil(user.loc, 30)
|
||||
loaded.max_amount = initial(loaded.max_amount)
|
||||
loaded.forceMove(user.loc)
|
||||
user.put_in_hands(loaded)
|
||||
loaded = null
|
||||
refresh_icon(user)
|
||||
|
||||
/obj/item/rcl/examine(mob/user)
|
||||
. = ..()
|
||||
if(loaded)
|
||||
. += "<span class='notice'>It contains [loaded.amount]/[max_amount] cables.</span>"
|
||||
else
|
||||
. += "<span class='warning'>It's empty!</span>"
|
||||
|
||||
/obj/item/rcl/Destroy()
|
||||
QDEL_NULL(loaded)
|
||||
last = null
|
||||
active = FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/rcl/update_icon_state()
|
||||
if(!loaded)
|
||||
icon_state = "rcl-0"
|
||||
item_state = "rcl-0"
|
||||
return
|
||||
switch(loaded.amount)
|
||||
if(61 to INFINITY)
|
||||
icon_state = "rcl-30"
|
||||
item_state = "rcl"
|
||||
if(31 to 60)
|
||||
icon_state = "rcl-20"
|
||||
item_state = "rcl"
|
||||
if(1 to 30)
|
||||
icon_state = "rcl-10"
|
||||
item_state = "rcl"
|
||||
else
|
||||
icon_state = "rcl-0"
|
||||
item_state = "rcl-0"
|
||||
|
||||
/obj/item/rcl/proc/is_empty(mob/user, loud = 1)
|
||||
refresh_icon(user)
|
||||
if(!loaded || !loaded.amount)
|
||||
if(loud)
|
||||
to_chat(user, "<span class='warning'>The last of the cables unreel from [src]!</span>")
|
||||
if(loaded)
|
||||
qdel(loaded)
|
||||
loaded = null
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/rcl/dropped(mob/wearer)
|
||||
..()
|
||||
active = FALSE
|
||||
last = null
|
||||
|
||||
/obj/item/rcl/activate_self(mob/user)
|
||||
if(..())
|
||||
return FINISH_ATTACK
|
||||
|
||||
active = HAS_TRAIT(src, TRAIT_WIELDED)
|
||||
if(!active)
|
||||
last = null
|
||||
else if(!last)
|
||||
for(var/obj/structure/cable/C in get_turf(user))
|
||||
if(C.d1 == 0 || C.d2 == 0)
|
||||
last = C
|
||||
break
|
||||
|
||||
/obj/item/rcl/on_mob_move(direct, mob/user)
|
||||
if(active && isturf(user.loc))
|
||||
trigger(user)
|
||||
|
||||
/obj/item/rcl/proc/trigger(mob/user)
|
||||
if(is_empty(user, 0))
|
||||
to_chat(user, "<span class='warning'>[src] is empty!</span>")
|
||||
return
|
||||
if(last)
|
||||
if(get_dist(last, user) == 1) //hacky, but it works
|
||||
var/turf/T = get_turf(user)
|
||||
if(!isturf(T) || T.intact || !T.can_have_cabling())
|
||||
last = null
|
||||
return
|
||||
if(get_dir(last, user) == last.d2)
|
||||
//Did we just walk backwards? Well, that's the one direction we CAN'T complete a stub.
|
||||
last = null
|
||||
return
|
||||
loaded.cable_join(last, user)
|
||||
if(is_empty(user))
|
||||
return //If we've run out, display message and exit
|
||||
else
|
||||
last = null
|
||||
last = loaded.place_turf(get_turf(loc), user, turn(user.dir, 180))
|
||||
is_empty(user) //If we've run out, display message
|
||||
|
||||
/obj/item/rcl/pre_loaded/New() //Comes preloaded with cable, for testing stuff
|
||||
..()
|
||||
loaded = new()
|
||||
loaded.max_amount = max_amount
|
||||
loaded.amount = max_amount
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
@@ -1,127 +0,0 @@
|
||||
#define POWER_NONE 0
|
||||
#define POWER_LOW 50
|
||||
#define POWER_HIGH 4000
|
||||
|
||||
/obj/item/rsf
|
||||
name = "\improper Rapid-Service-Fabricator"
|
||||
desc = "A device used to rapidly deploy service items."
|
||||
icon = 'icons/obj/tools.dmi'
|
||||
icon_state = "rsf"
|
||||
item_state = "rsf"
|
||||
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 0, ACID = 0)
|
||||
var/atom/currently_dispensing
|
||||
var/power_mode = POWER_NONE
|
||||
|
||||
var/list/rsf_items = list(
|
||||
"Drinking Glass" = /obj/item/reagent_containers/drinks/drinkingglass,
|
||||
"Paper" = /obj/item/paper,
|
||||
"Pen" = /obj/item/pen,
|
||||
"Dice Pack" = /obj/item/storage/bag/dice,
|
||||
"Cigarette" = /obj/item/clothing/mask/cigarette,
|
||||
"Newdles" = /obj/item/food/chinese/newdles,
|
||||
"Donut" = /obj/item/food/donut,
|
||||
"Chicken Soup" = /obj/item/reagent_containers/drinks/chicken_soup,
|
||||
"Tofu Burger" = /obj/item/food/burger/tofu
|
||||
)
|
||||
|
||||
var/static/list/rsf_icons = list(
|
||||
"Drinking Glass" = image(icon = 'icons/obj/drinks.dmi', icon_state = "glass_empty"),
|
||||
"Shot Glass" = image(icon = 'icons/obj/drinks.dmi', icon_state = "shotglass"),
|
||||
"Paper" = image(icon = 'icons/obj/bureaucracy.dmi', icon_state = "paper"),
|
||||
"Pen" = image(icon = 'icons/obj/bureaucracy.dmi', icon_state = "pen"),
|
||||
"Dice Pack" = image(icon = 'icons/obj/dice.dmi', icon_state = "dicebag"),
|
||||
"Cigarette" = image(icon = 'icons/obj/clothing/masks.dmi', icon_state = "cig_on"),
|
||||
"Newdles" = image(icon = 'icons/obj/food/food.dmi', icon_state = "chinese3"),
|
||||
"Donut" = image(icon = 'icons/obj/food/bakedgoods.dmi', icon_state = "donut1"),
|
||||
"Chicken Soup" = image(icon = 'icons/obj/drinks.dmi', icon_state = "soupcan"),
|
||||
"Tofu Burger" = image(icon = 'icons/obj/food/burgerbread.dmi', icon_state = "tofuburger"),
|
||||
"Cigar" = image(icon = 'icons/obj/clothing/masks.dmi', icon_state = "cigar_off"),
|
||||
"Smoked Cheese" = image(icon = 'icons/obj/food/food.dmi', icon_state = "cheesewheel-smoked"),
|
||||
"Edam Cheese" = image(icon = 'icons/obj/food/food.dmi', icon_state = "cheesewheel-edam"),
|
||||
"Blue Cheese" = image(icon = 'icons/obj/food/food.dmi', icon_state = "cheesewheel-blue"),
|
||||
"Camembert Cheese" = image(icon = 'icons/obj/food/food.dmi', icon_state = "cheesewheel-camembert"),
|
||||
"Caviar" = image(icon = 'icons/obj/food/seafood.dmi', icon_state = "caviar")
|
||||
)
|
||||
|
||||
var/static/list/power_costs = list(
|
||||
"Drinking Glass" = POWER_LOW,
|
||||
"Shot Glass" = POWER_LOW,
|
||||
"Paper" = POWER_LOW,
|
||||
"Pen" = POWER_LOW,
|
||||
"Dice Pack" = POWER_LOW,
|
||||
"Cigarette" = POWER_LOW,
|
||||
"Newdles" = POWER_HIGH,
|
||||
"Donut" = POWER_HIGH,
|
||||
"Chicken Soup" = POWER_HIGH,
|
||||
"Tofu Burger" = POWER_HIGH,
|
||||
"Cigar" = POWER_LOW,
|
||||
"Smoked Cheese" = POWER_HIGH,
|
||||
"Edam Cheese" = POWER_HIGH,
|
||||
"Blue Cheese" = POWER_HIGH,
|
||||
"Camembert Cheese" = POWER_HIGH,
|
||||
"Caviar" = POWER_HIGH
|
||||
)
|
||||
|
||||
/obj/item/rsf/attack_self__legacy__attackchain(mob/user)
|
||||
playsound(loc, 'sound/effects/pop.ogg', 50, FALSE)
|
||||
if(!currently_dispensing)
|
||||
to_chat(user, "<span class='notice'>Choose an item to dispense!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You are currently dispensing a [initial(currently_dispensing.name)].</span>")
|
||||
|
||||
var/rsf_radial_choice = show_radial_menu(user, src, get_radial_contents())
|
||||
if(user.stat || !in_range(user, src))
|
||||
return
|
||||
currently_dispensing = rsf_items[rsf_radial_choice]
|
||||
power_mode = power_costs[rsf_radial_choice]
|
||||
if(currently_dispensing)
|
||||
to_chat(user, "<span class='notice'>Your RSF has been configured to now dispense a [initial(currently_dispensing.name)]!</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/rsf/proc/get_radial_contents()
|
||||
return rsf_icons & rsf_items
|
||||
|
||||
/obj/item/rsf/afterattack__legacy__attackchain(atom/A, mob/user, proximity)
|
||||
if(!currently_dispensing)
|
||||
return
|
||||
if(!proximity)
|
||||
return
|
||||
if(!istype(A, /obj/structure/table) && !isfloorturf(A))
|
||||
return
|
||||
if(isrobot(user))
|
||||
var/mob/living/silicon/robot/energy_check = user
|
||||
if(!energy_check.cell.use(power_mode))
|
||||
to_chat(user, "<span class='warning'>Insufficient energy.</span>")
|
||||
flick("[icon_state]_empty", src)
|
||||
return
|
||||
var/turf/T = get_turf(A)
|
||||
if(!istype(T) || T.density)
|
||||
to_chat(user, "The RSF can only create service items on tables, or floors.")
|
||||
return
|
||||
playsound(loc, 'sound/machines/click.ogg', 10, 1)
|
||||
new currently_dispensing(T)
|
||||
|
||||
/obj/item/rsf/executive
|
||||
name = "\improper Executive-Service-Fabricator"
|
||||
desc = "A fancier version of the RSF, used to deploy classy refreshments and materials to high ranking clientelle."
|
||||
icon_state = "rsf-exec"
|
||||
|
||||
rsf_items = list(
|
||||
"Drinking Glass" = /obj/item/reagent_containers/drinks/drinkingglass,
|
||||
"Shot Glass" = /obj/item/reagent_containers/drinks/drinkingglass/shotglass,
|
||||
"Paper" = /obj/item/paper,
|
||||
"Pen" = /obj/item/pen,
|
||||
"Dice Pack" = /obj/item/storage/bag/dice,
|
||||
"Cigar" = /obj/item/clothing/mask/cigarette/cigar,
|
||||
"Cigarette" = /obj/item/clothing/mask/cigarette,
|
||||
"Smoked Cheese" = /obj/item/food/sliceable/cheesewheel/smoked,
|
||||
"Edam Cheese" = /obj/item/food/sliceable/cheesewheel/edam,
|
||||
"Blue Cheese" = /obj/item/food/sliceable/cheesewheel/blue,
|
||||
"Camembert Cheese" = /obj/item/food/sliceable/cheesewheel/camembert,
|
||||
"Caviar" = /obj/item/food/caviar,
|
||||
"Donut" = /obj/item/food/donut
|
||||
)
|
||||
|
||||
#undef POWER_NONE
|
||||
#undef POWER_LOW
|
||||
#undef POWER_HIGH
|
||||
@@ -1,297 +0,0 @@
|
||||
/obj/item/card/id/syndicate
|
||||
name = "agent card"
|
||||
origin_tech = "syndicate=1"
|
||||
untrackable = TRUE
|
||||
/// List of access types the agent ID should start off with
|
||||
var/list/initial_access = list(ACCESS_MAINT_TUNNELS, ACCESS_SYNDICATE, ACCESS_EXTERNAL_AIRLOCKS)
|
||||
/// Editing is prohibited if registered_human reference is missing
|
||||
var/mob/living/carbon/human/registered_human
|
||||
// Static list of all occupations available when changing the occupation on an agent ID
|
||||
var/static/list/possible_jobs
|
||||
/// The HUD icon that should be displayed on a mob that is wearing the agent ID
|
||||
var/hud_icon
|
||||
|
||||
COOLDOWN_DECLARE(new_photo_cooldown)
|
||||
|
||||
/obj/item/card/id/syndicate/Initialize(mapload)
|
||||
. = ..()
|
||||
access = initial_access.Copy()
|
||||
if(!length(possible_jobs))
|
||||
possible_jobs = sortTim(GLOB.joblist, GLOBAL_PROC_REF(cmp_text_asc))
|
||||
|
||||
/obj/item/card/id/syndicate/Destroy()
|
||||
registered_human = null
|
||||
return ..()
|
||||
|
||||
/obj/item/card/id/syndicate/researcher
|
||||
initial_access = list(ACCESS_SYNDICATE)
|
||||
assignment = "Syndicate Researcher"
|
||||
icon_state = "syndie"
|
||||
|
||||
/obj/item/card/id/syndicate/vox
|
||||
initial_access = list(ACCESS_MAINT_TUNNELS, ACCESS_VOX, ACCESS_EXTERNAL_AIRLOCKS)
|
||||
|
||||
/obj/item/card/id/syndicate/ghost_bar
|
||||
name = "ghost bar identification card"
|
||||
assignment = "Ghost Bar Occupant"
|
||||
initial_access = list() // This is for show, they don't need actual accesses
|
||||
icon_state = "assistant"
|
||||
|
||||
/obj/item/card/id/syndicate/command
|
||||
initial_access = list(ACCESS_MAINT_TUNNELS, ACCESS_SYNDICATE, ACCESS_SYNDICATE_LEADER, ACCESS_SYNDICATE_COMMAND, ACCESS_EXTERNAL_AIRLOCKS)
|
||||
icon_state = "commander"
|
||||
|
||||
/obj/item/card/id/syndicate_command
|
||||
name = "syndicate ID card"
|
||||
desc = "An ID straight from the Syndicate."
|
||||
registered_name = "Syndicate"
|
||||
icon_state = "syndie"
|
||||
assignment = "Syndicate Overlord"
|
||||
untrackable = TRUE
|
||||
can_id_flash = FALSE //This can ID flash, this just prevents it from always flashing.
|
||||
access = list(ACCESS_SYNDICATE, ACCESS_SYNDICATE_LEADER, ACCESS_SYNDICATE_COMMAND, ACCESS_EXTERNAL_AIRLOCKS)
|
||||
|
||||
/obj/item/card/id/syndicate/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(istype(target, /obj/item/card/id))
|
||||
var/obj/item/card/id/I = target
|
||||
if(isliving(user) && user?.mind?.special_role)
|
||||
to_chat(usr, "<span class='notice'>The card's microscanners activate as you pass it over [I], copying its access.</span>")
|
||||
access |= I.access //Don't copy access if user isn't an antag -- to prevent metagaming
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
/obj/item/card/id/syndicate/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
if(..())
|
||||
return
|
||||
if(!registered_human || !Adjacent(registered_human))
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("delete_info")
|
||||
delete_info(ui)
|
||||
if("clear_access")
|
||||
clear_access()
|
||||
if("change_ai_tracking")
|
||||
change_ai_tracking()
|
||||
if("change_name")
|
||||
change_name(params["option"], params["name"])
|
||||
if("change_photo")
|
||||
change_photo()
|
||||
if("change_appearance")
|
||||
change_appearance(params["new_appearance"])
|
||||
if("change_sex")
|
||||
change_sex(params["sex"])
|
||||
if("change_age")
|
||||
change_age(params["age"])
|
||||
if("change_occupation")
|
||||
change_occupation(params["option"])
|
||||
if("change_money_account")
|
||||
change_money_account(params["option"], params["new_account"])
|
||||
if("change_blood_type")
|
||||
change_blood_type(params["option"], params["new_type"])
|
||||
if("change_dna_hash")
|
||||
change_dna_hash(params["option"], params["new_dna"])
|
||||
if("change_fingerprints")
|
||||
change_fingerprints(params["option"], params["new_fingerprints"])
|
||||
RebuildHTML()
|
||||
|
||||
/obj/item/card/id/syndicate/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["registered_name"] = registered_name
|
||||
data["sex"] = sex
|
||||
data["age"] = age
|
||||
data["assignment"] = assignment
|
||||
data["job_icon"] = hud_icon
|
||||
data["associated_account_number"] = associated_account_number
|
||||
data["blood_type"] = blood_type
|
||||
data["dna_hash"] = dna_hash
|
||||
data["fingerprint_hash"] = fingerprint_hash
|
||||
data["photo"] = photo
|
||||
data["ai_tracking"] = untrackable
|
||||
data["photo_cooldown"] = COOLDOWN_FINISHED(src, new_photo_cooldown)
|
||||
return data
|
||||
|
||||
/obj/item/card/id/syndicate/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/list/idcard_skins = list()
|
||||
for(var/idcard_skin in get_all_card_skins())
|
||||
idcard_skins.Add(idcard_skin)
|
||||
data["appearances"] = idcard_skins
|
||||
data["id_icon"] = icon
|
||||
return data
|
||||
|
||||
/obj/item/card/id/syndicate/ui_interact(mob/user, datum/tgui/ui = null)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "AgentCard", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/card/id/syndicate/activate_self(mob/user)
|
||||
if(..() || !ishuman(user))
|
||||
return
|
||||
if(!registered_human)
|
||||
registered_human = user
|
||||
if(registered_human != user)
|
||||
flash_card(user)
|
||||
return
|
||||
switch(tgui_alert(user, "Would you like to display [src] or edit it?", "Choose", list("Edit", "Show")))
|
||||
if("Show")
|
||||
flash_card(user)
|
||||
if("Edit")
|
||||
ui_interact(user)
|
||||
|
||||
/obj/item/card/id/syndicate/proc/delete_info(datum/tgui/ui)
|
||||
name = initial(name)
|
||||
registered_name = initial(registered_name)
|
||||
icon_state = initial(icon_state)
|
||||
sex = initial(sex)
|
||||
age = initial(age)
|
||||
assignment = initial(assignment)
|
||||
rank = initial(rank)
|
||||
associated_account_number = initial(associated_account_number)
|
||||
blood_type = initial(blood_type)
|
||||
dna_hash = initial(dna_hash)
|
||||
fingerprint_hash = initial(fingerprint_hash)
|
||||
photo = null
|
||||
registered_human.sec_hud_set_ID()
|
||||
registered_human = null
|
||||
ui.close()
|
||||
|
||||
/obj/item/card/id/syndicate/proc/clear_access()
|
||||
access = initial_access.Copy() // Initial() doesn't work on lists
|
||||
to_chat(registered_human, "<span class='notice'>Card access reset.</span>")
|
||||
|
||||
/obj/item/card/id/syndicate/proc/change_ai_tracking()
|
||||
untrackable = !untrackable
|
||||
|
||||
/obj/item/card/id/syndicate/proc/change_name(option, name)
|
||||
var/new_name
|
||||
if(option == "Primary")
|
||||
new_name = ishuman(registered_human) ? registered_human.real_name : registered_human.name
|
||||
else if(option == "Secondary")
|
||||
new_name = tgui_input_list(registered_human, "Whose name do you want to copy?", "Agent ID - Name", GLOB.crew_list)
|
||||
if(isnull(new_name))
|
||||
return
|
||||
else
|
||||
new_name = sanitize(name)
|
||||
|
||||
registered_name = reject_bad_name(new_name, TRUE)
|
||||
UpdateName()
|
||||
to_chat(registered_human, "ID name has been changed to [new_name].")
|
||||
|
||||
/obj/item/card/id/syndicate/proc/change_photo()
|
||||
if(!COOLDOWN_FINISHED(src, new_photo_cooldown))
|
||||
return
|
||||
var/job_clothes = null
|
||||
if(assignment)
|
||||
job_clothes = assignment
|
||||
var/icon/newphoto = get_id_photo(registered_human, job_clothes)
|
||||
if(!newphoto)
|
||||
return
|
||||
photo = newphoto
|
||||
COOLDOWN_START(src, new_photo_cooldown, 10 SECONDS) // This proc is expensive, we don't want people spamming it.
|
||||
|
||||
/obj/item/card/id/syndicate/proc/change_appearance(new_appearance)
|
||||
if(!new_appearance)
|
||||
return
|
||||
if(new_appearance in icon_states(icon))
|
||||
icon_state = new_appearance
|
||||
|
||||
/obj/item/card/id/syndicate/proc/change_sex(new_sex)
|
||||
if(!Adjacent(registered_human) || isnull(new_sex))
|
||||
return
|
||||
|
||||
sex = sanitize(new_sex)
|
||||
|
||||
/obj/item/card/id/syndicate/proc/change_age(new_age)
|
||||
age = clamp(new_age, AGE_MIN, AGE_MAX)
|
||||
|
||||
/obj/item/card/id/syndicate/proc/change_occupation(option)
|
||||
var/new_job
|
||||
var/new_rank
|
||||
if(option == "Primary")
|
||||
new_job = assignment
|
||||
new_rank = tgui_input_list(registered_human, "What SecHUD icon would you like to be shown on this card?", "Agent Card Occupation", GLOB.joblist + "Prisoner" + "Centcom" + "Solgov" + "Soviet" + "Unknown")
|
||||
else
|
||||
var/department = tgui_input_list(registered_human, "Do you want a custom occupation?", "Agent Card Occupation", list("Existing job", "Custom"))
|
||||
if(department != "Custom")
|
||||
new_job = tgui_input_list(registered_human, "What job would you like to put on this card?", "Agent Card Occupation", possible_jobs)
|
||||
new_rank = new_job
|
||||
else
|
||||
new_job = sanitize(tgui_input_text(registered_human, "Choose a custom job title:", "Agent Card Occupation", "Assistant", MAX_MESSAGE_LEN))
|
||||
new_rank = tgui_input_list(registered_human, "What SecHUD icon would you like to be shown on this card?", "Agent Card Occupation", GLOB.joblist + "Prisoner" + "Centcom" + "Solgov" + "Soviet" + "Unknown")
|
||||
|
||||
if(!Adjacent(registered_human) || isnull(new_job))
|
||||
return
|
||||
assignment = new_job
|
||||
rank = new_rank
|
||||
hud_icon = ckey(get_job_name())
|
||||
UpdateName()
|
||||
registered_human.sec_hud_set_ID()
|
||||
|
||||
/obj/item/card/id/syndicate/proc/change_money_account(option, new_account)
|
||||
if(option == "Primary")
|
||||
new_account = registered_human.mind.initial_account?.account_number
|
||||
if(!new_account)
|
||||
to_chat(registered_human, "You don't have an account.")
|
||||
return
|
||||
else if(option == "Secondary")
|
||||
new_account = rand(1000, 9999) * 1000 + rand(1000, 9999)
|
||||
else
|
||||
new_account = text2num(new_account)
|
||||
if(!isnum(new_account))
|
||||
to_chat(registered_human, "ID account number can only contain numbers.")
|
||||
return
|
||||
|
||||
associated_account_number = clamp(new_account, 1000000, 9999999)
|
||||
to_chat(registered_human, "ID account number has been changed to [new_account].")
|
||||
|
||||
/obj/item/card/id/syndicate/proc/change_blood_type(option, new_type)
|
||||
var/list/possible_blood_types = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O+", "O-", "Slime Jelly", "None")
|
||||
if(option == "Primary")
|
||||
blood_type = registered_human.dna.blood_type
|
||||
else if(new_type)
|
||||
if(!(new_type in possible_blood_types))
|
||||
return
|
||||
blood_type = new_type
|
||||
to_chat(registered_human, "ID blood type has been changed to [blood_type].")
|
||||
|
||||
/obj/item/card/id/syndicate/proc/change_dna_hash(option, new_dna)
|
||||
if(option == "Primary")
|
||||
dna_hash = registered_human.dna.unique_enzymes
|
||||
else if(option == "Secondary")
|
||||
dna_hash = md5(num2text(rand(0, 999)))
|
||||
else
|
||||
if(new_dna)
|
||||
dna_hash = sanitize(new_dna, 33) // Max length of 32 characters
|
||||
|
||||
/obj/item/card/id/syndicate/proc/change_fingerprints(option, new_fingerprints)
|
||||
if(option == "Primary")
|
||||
fingerprint_hash = md5(registered_human.dna.uni_identity)
|
||||
else if(option == "Secondary")
|
||||
fingerprint_hash = md5(num2text(rand(0, 999)))
|
||||
else
|
||||
var/fingerprints_param = new_fingerprints
|
||||
if(fingerprints_param)
|
||||
fingerprint_hash = sanitize(fingerprints_param, 33)
|
||||
|
||||
/// like /obj/item/card/id/syndicate, but you can only swipe access, not change your identity, its also trackable
|
||||
/obj/item/card/id/syndi_scan_only
|
||||
name = "Syndicate Operative's ID card (Operative)"
|
||||
rank = "Operative"
|
||||
assignment = "Operative"
|
||||
registered_name = "Syndicate Operative"
|
||||
access = list(ACCESS_SYNDICATE)
|
||||
|
||||
/obj/item/card/id/syndi_scan_only/examine(mob/user)
|
||||
. = ..()
|
||||
if(isAntag(user))
|
||||
. += "<span class='notice'>Similar to an agent ID, this ID card can be used to copy accesses, but it lacks the customization and anti-tracking capabilities of an agent ID.</span>"
|
||||
|
||||
/obj/item/card/id/syndi_scan_only/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(istype(target, /obj/item/card/id))
|
||||
var/obj/item/card/id/I = target
|
||||
if(isliving(user) && user.mind)
|
||||
if(user.mind.special_role)
|
||||
to_chat(user, "<span class='notice'>The card's microscanners activate as you pass it over [I], copying its access.</span>")
|
||||
access |= I.access // Don't copy access if user isn't an antag -- to prevent metagaming
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
@@ -1,229 +0,0 @@
|
||||
/**
|
||||
* # Implants
|
||||
*
|
||||
* Code for implants that can be inserted into a person and have some sort of passive or triggered action.
|
||||
*
|
||||
*/
|
||||
/obj/item/bio_chip
|
||||
name = "bio-chip"
|
||||
icon = 'icons/obj/bio_chips.dmi'
|
||||
icon_state = "generic" //Shows up as a auto surgeon, used as a placeholder when a implant doesn't have a sprite
|
||||
origin_tech = "materials=2;biotech=3;programming=2"
|
||||
actions_types = list(/datum/action/item_action/hands_free/activate)
|
||||
item_color = "black"
|
||||
flags = DROPDEL // By default, don't let implants be harvestable.
|
||||
|
||||
///which implant overlay should be used for implant cases. This should point to a state in bio_chips.dmi
|
||||
var/implant_state = "implant-default"
|
||||
/// How the implant is activated.
|
||||
var/activated = BIOCHIP_ACTIVATED_ACTIVE
|
||||
/// Whether the implant is implanted. Null if it's never been inserted, TRUE if it's currently inside someone, or FALSE if it's been removed.
|
||||
var/implanted
|
||||
/// Who the implant is inside of.
|
||||
var/mob/living/imp_in
|
||||
|
||||
/// Whether multiple implants of this same type can be inserted into someone.
|
||||
var/allow_multiple = FALSE
|
||||
/// Amount of times that the implant can be triggered by the user. If the implant can't be used, it can't be inserted.
|
||||
var/uses = -1
|
||||
|
||||
/// List of emote keys that activate this implant when used.
|
||||
var/list/trigger_emotes
|
||||
/// What type of action will trigger this emote. Bitfield of IMPLANT_EMOTE_* defines.
|
||||
var/trigger_causes
|
||||
/// Whether this implant has already triggered on death or not, to prevent it firing multiple times.
|
||||
var/has_triggered_on_death = FALSE
|
||||
|
||||
///the implant_fluff datum attached to this implant, purely cosmetic "lore" information
|
||||
var/datum/implant_fluff/implant_data = /datum/implant_fluff
|
||||
|
||||
/obj/item/bio_chip/Initialize(mapload)
|
||||
. = ..()
|
||||
if(ispath(implant_data))
|
||||
implant_data = new implant_data
|
||||
|
||||
/obj/item/bio_chip/Destroy()
|
||||
if(imp_in)
|
||||
removed(imp_in)
|
||||
QDEL_NULL(implant_data)
|
||||
return ..()
|
||||
|
||||
/obj/item/bio_chip/proc/unregister_emotes()
|
||||
if(imp_in && LAZYLEN(trigger_emotes))
|
||||
for(var/emote in trigger_emotes)
|
||||
UnregisterSignal(imp_in, COMSIG_MOB_EMOTED(emote))
|
||||
|
||||
/**
|
||||
* Set the emote that will trigger the implant.
|
||||
* * user - User who is trying to associate the implant to themselves.
|
||||
* * emote_key - Key of the emote that should trigger the implant.
|
||||
* * on_implant - Whether this proc is being called during the implantation of the implant.
|
||||
* * silent - If true, the user won't get any to_chat messages if an implantation fails.
|
||||
*/
|
||||
/obj/item/bio_chip/proc/set_trigger(mob/user, emote_key, on_implant = FALSE, silent = TRUE)
|
||||
if(imp_in != user)
|
||||
return FALSE
|
||||
|
||||
if(!emote_key)
|
||||
return FALSE
|
||||
|
||||
if(LAZYIN(trigger_emotes, emote_key) && !on_implant)
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You've already registered [emote_key]!")
|
||||
return FALSE
|
||||
|
||||
if(emote_key == "me" || emote_key == "custom")
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You can't trigger [src] with a custom emote.")
|
||||
return FALSE
|
||||
|
||||
if(!(emote_key in user.usable_emote_keys(trigger_causes & BIOCHIP_EMOTE_TRIGGER_INTENTIONAL)))
|
||||
if(!silent)
|
||||
to_chat(user, "<span class='warning'>You can't trigger [src] with that emote! Try *help to see emotes you can use.</span>")
|
||||
return FALSE
|
||||
|
||||
if(!(emote_key in user.usable_emote_keys(trigger_causes & BIOCHIP_EMOTE_TRIGGER_UNINTENTIONAL)))
|
||||
CRASH("User was given an bio-chip for an unintentional emote that they can't use.")
|
||||
|
||||
LAZYADD(trigger_emotes, emote_key)
|
||||
RegisterSignal(user, COMSIG_MOB_EMOTED(emote_key), PROC_REF(on_emote))
|
||||
|
||||
/obj/item/bio_chip/proc/on_emote(mob/living/user, datum/emote/fired_emote, key, emote_type, message, intentional)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!implanted || !imp_in)
|
||||
return
|
||||
|
||||
if(!(intentional && (trigger_causes & BIOCHIP_EMOTE_TRIGGER_INTENTIONAL)) && !(!intentional && (trigger_causes & BIOCHIP_EMOTE_TRIGGER_UNINTENTIONAL)))
|
||||
return
|
||||
|
||||
add_attack_logs(user, user, "[intentional ? "intentionally" : "unintentionally"] [src] was [intentional ? "intentionally" : "unintentionally"] triggered with the emote [fired_emote].")
|
||||
emote_trigger(key, user, intentional)
|
||||
|
||||
/obj/item/bio_chip/proc/on_death(mob/source, gibbed)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!implanted || !imp_in)
|
||||
return
|
||||
|
||||
if(gibbed && (trigger_causes & BIOCHIP_TRIGGER_NOT_WHEN_GIBBED))
|
||||
return
|
||||
|
||||
// This should help avoid infinite recursion for things like dust that call death()
|
||||
if(has_triggered_on_death && (trigger_causes & BIOCHIP_TRIGGER_DEATH_ONCE))
|
||||
return
|
||||
|
||||
has_triggered_on_death = TRUE
|
||||
|
||||
add_attack_logs(source, source, "had their [src] bio-chip triggered on [gibbed ? "gib" : "death"].")
|
||||
death_trigger(source, gibbed)
|
||||
|
||||
/obj/item/bio_chip/proc/emote_trigger(emote, mob/source, force)
|
||||
return
|
||||
|
||||
/obj/item/bio_chip/proc/death_trigger(mob/source, gibbed)
|
||||
return
|
||||
|
||||
/obj/item/bio_chip/proc/activate(cause)
|
||||
SEND_SIGNAL(src, COMSIG_IMPLANT_ACTIVATED, cause, imp_in)
|
||||
return
|
||||
|
||||
/obj/item/bio_chip/ui_action_click()
|
||||
activate("action_button")
|
||||
|
||||
/**
|
||||
* Try to implant ourselves into a mob.
|
||||
*
|
||||
* * source - The person the implant is being administered to.
|
||||
* * user - The person who is doing the implanting.
|
||||
*
|
||||
* Returns
|
||||
* 1 if the implant injects successfully
|
||||
* -1 if the implant fails to inject
|
||||
* 0 if there's no room for the implant.
|
||||
*/
|
||||
/obj/item/bio_chip/proc/implant(mob/source, mob/user, force)
|
||||
if(!force && !can_implant(source, user))
|
||||
return
|
||||
var/obj/item/bio_chip/imp_e = locate(type) in source
|
||||
if(!allow_multiple && imp_e && imp_e != src)
|
||||
if(imp_e.uses < initial(imp_e.uses)*2)
|
||||
if(uses == -1)
|
||||
imp_e.uses = -1
|
||||
else
|
||||
imp_e.uses = min(imp_e.uses + uses, initial(imp_e.uses)*2)
|
||||
qdel(src)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
|
||||
loc = source
|
||||
imp_in = source
|
||||
implanted = TRUE
|
||||
if(trigger_emotes)
|
||||
if(!(trigger_causes & BIOCHIP_EMOTE_TRIGGER_INTENTIONAL | BIOCHIP_EMOTE_TRIGGER_UNINTENTIONAL))
|
||||
CRASH("Bio-chip [src] has trigger emotes defined but no trigger cause with which to use them!")
|
||||
if(!activated && (trigger_causes & BIOCHIP_EMOTE_TRIGGER_INTENTIONAL))
|
||||
CRASH("Bio-chip [src] has intentional emote triggers on a passive bio-chip")
|
||||
// If you can't activate the implant manually, you shouldn't be able to deliberately activate it with an emote
|
||||
for(var/emote in trigger_emotes)
|
||||
set_trigger(source, emote, TRUE, TRUE)
|
||||
if(activated)
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.Grant(source)
|
||||
if(trigger_causes & (BIOCHIP_TRIGGER_DEATH_ONCE | BIOCHIP_TRIGGER_DEATH_ANY))
|
||||
RegisterSignal(source, COMSIG_MOB_DEATH, PROC_REF(on_death))
|
||||
if(ishuman(source))
|
||||
var/mob/living/carbon/human/H = source
|
||||
H.sec_hud_set_implants()
|
||||
|
||||
if(user)
|
||||
add_attack_logs(user, source, "Chipped with [src]")
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_IMPLANT_IMPLANTED, source, user, force)
|
||||
return 1
|
||||
|
||||
/**
|
||||
* Check that we can actually implant this before implanting it
|
||||
* * source - The person being implanted
|
||||
* * user - The person doing the implanting
|
||||
*
|
||||
* Returns
|
||||
* TRUE - I could care less, implant it, maybe don't. I don't care.
|
||||
* FALSE - Don't implant!
|
||||
*/
|
||||
/obj/item/bio_chip/proc/can_implant(mob/source, mob/user)
|
||||
return TRUE
|
||||
|
||||
|
||||
/**
|
||||
* Clean up when an implant is removed.
|
||||
* * source - the user who the implant was removed from.
|
||||
*/
|
||||
/obj/item/bio_chip/proc/removed(mob/source)
|
||||
loc = null
|
||||
imp_in = null
|
||||
implanted = FALSE
|
||||
|
||||
for(var/X in actions)
|
||||
var/datum/action/A = X
|
||||
A.Remove(source)
|
||||
|
||||
if(ishuman(source))
|
||||
var/mob/living/carbon/human/H = source
|
||||
H.sec_hud_set_implants()
|
||||
|
||||
if(trigger_causes & (BIOCHIP_TRIGGER_DEATH_ONCE | BIOCHIP_TRIGGER_DEATH_ANY))
|
||||
UnregisterSignal(source, COMSIG_MOB_DEATH)
|
||||
|
||||
unregister_emotes()
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_IMPLANT_REMOVED, source)
|
||||
return TRUE
|
||||
|
||||
/obj/item/bio_chip/dropped(mob/user)
|
||||
. = TRUE
|
||||
..()
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/obj/item/bio_chip/abductor
|
||||
name = "recall bio-chip"
|
||||
desc = "Returns you to the mothership."
|
||||
icon = 'icons/obj/abductor.dmi'
|
||||
icon_state = "implant"
|
||||
origin_tech = "materials=2;biotech=7;magnets=4;bluespace=4;abductor=5"
|
||||
implant_data = /datum/implant_fluff/abductor
|
||||
implant_state = "implant-alien"
|
||||
|
||||
var/obj/machinery/abductor/pad/home
|
||||
var/cooldown = 30
|
||||
var/total_cooldown = 30
|
||||
|
||||
/obj/item/bio_chip/abductor/activate()
|
||||
if(cooldown == total_cooldown)
|
||||
if(imp_in.has_status_effect(STATUS_EFFECT_ABDUCTOR_COOLDOWN))
|
||||
to_chat(imp_in, "<span class='warning'>The teleporter will not activate yet to prevent potential damage!</span>")
|
||||
return
|
||||
home.Retrieve(imp_in, 1)
|
||||
cooldown = 0
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
to_chat(imp_in, "<span class='warning'>You must wait [(total_cooldown - cooldown) * 2] seconds to use [src] again!</span>")
|
||||
|
||||
/obj/item/bio_chip/abductor/process()
|
||||
if(cooldown < total_cooldown)
|
||||
cooldown++
|
||||
if(cooldown == total_cooldown)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/bio_chip/abductor/implant(mob/source, mob/user)
|
||||
if(..())
|
||||
var/obj/machinery/abductor/console/console
|
||||
if(ishuman(source))
|
||||
var/mob/living/carbon/human/H = source
|
||||
if(isabductor(H))
|
||||
var/datum/species/abductor/S = H.dna.species
|
||||
console = get_team_console(S.team)
|
||||
home = console.pad
|
||||
|
||||
if(!home)
|
||||
console = get_team_console(pick(1, 2, 3, 4))
|
||||
home = console.pad
|
||||
return TRUE
|
||||
|
||||
/obj/item/bio_chip/abductor/proc/get_team_console(team)
|
||||
var/obj/machinery/abductor/console/console
|
||||
for(var/obj/machinery/abductor/console/c in GLOB.abductor_equipment)
|
||||
if(c.team == team)
|
||||
console = c
|
||||
break
|
||||
return console
|
||||
|
||||
/obj/item/bio_chip_implanter/abductor
|
||||
name = "bio-chip implanter (abductor)"
|
||||
implant_type = /obj/item/bio_chip/abductor
|
||||
|
||||
/obj/item/bio_chip_case/abductor
|
||||
name = "bio-chip case - 'abductor'"
|
||||
desc = "A glass case containing an abductor bio-chip."
|
||||
implant_type = /obj/item/bio_chip/abductor
|
||||
@@ -1,101 +0,0 @@
|
||||
/obj/item/bio_chip/adrenalin
|
||||
name = "adrenal bio-chip"
|
||||
desc = "Removes all stuns and knockdowns."
|
||||
icon_state = "adrenal"
|
||||
origin_tech = "materials=2;biotech=4;combat=3;syndicate=4"
|
||||
uses = 3
|
||||
implant_data = /datum/implant_fluff/adrenaline
|
||||
implant_state = "implant-syndicate"
|
||||
|
||||
/obj/item/bio_chip/adrenalin/activate()
|
||||
uses--
|
||||
to_chat(imp_in, "<span class='notice'>You feel a sudden surge of energy!</span>")
|
||||
imp_in.SetStunned(0)
|
||||
imp_in.SetWeakened(0)
|
||||
imp_in.SetKnockDown(0)
|
||||
imp_in.SetParalysis(0)
|
||||
imp_in.adjustStaminaLoss(-75)
|
||||
imp_in.stand_up(TRUE)
|
||||
SEND_SIGNAL(imp_in, COMSIG_LIVING_CLEAR_STUNS)
|
||||
|
||||
imp_in.reagents.add_reagent("synaptizine", 10)
|
||||
imp_in.reagents.add_reagent("omnizine_no_addiction", 10)
|
||||
imp_in.reagents.add_reagent("stimulative_agent", 10)
|
||||
if(!uses)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/bio_chip_implanter/adrenalin
|
||||
name = "bio-chip implanter (adrenalin)"
|
||||
implant_type = /obj/item/bio_chip/adrenalin
|
||||
|
||||
/obj/item/bio_chip_case/adrenaline
|
||||
name = "bio-chip case - 'Adrenaline'"
|
||||
desc = "A glass case containing an adrenaline bio-chip."
|
||||
implant_type = /obj/item/bio_chip/adrenalin
|
||||
|
||||
/obj/item/bio_chip/basic_adrenalin
|
||||
name = "basic adrenal bio-chip"
|
||||
desc = "Removes all stuns and knockdowns."
|
||||
icon_state = "adrenal"
|
||||
origin_tech = "materials=2;biotech=4;combat=3;syndicate=3"
|
||||
uses = 1
|
||||
implant_data = /datum/implant_fluff/basic_adrenalin
|
||||
implant_state = "implant-syndicate"
|
||||
|
||||
/obj/item/bio_chip/basic_adrenalin/activate()
|
||||
uses--
|
||||
to_chat(imp_in, "<span class='notice'>You feel a sudden surge of energy!</span>")
|
||||
imp_in.SetStunned(0)
|
||||
imp_in.SetWeakened(0)
|
||||
imp_in.SetKnockDown(0)
|
||||
imp_in.SetParalysis(0)
|
||||
imp_in.adjustStaminaLoss(-75)
|
||||
imp_in.stand_up(TRUE)
|
||||
SEND_SIGNAL(imp_in, COMSIG_LIVING_CLEAR_STUNS)
|
||||
|
||||
imp_in.reagents.add_reagent("synaptizine", 7.5)
|
||||
imp_in.reagents.add_reagent("weak_omnizine", 7.5)
|
||||
imp_in.reagents.add_reagent("stimulative_agent", 7.5)
|
||||
if(!uses)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/bio_chip_implanter/basic_adrenalin
|
||||
name = "bio-chip implanter (basic adrenalin)"
|
||||
implant_type = /obj/item/bio_chip/basic_adrenalin
|
||||
|
||||
/obj/item/bio_chip_case/basic_adrenalin
|
||||
name = "bio-chip case - 'Basic Adrenaline'"
|
||||
desc = "A glass case containing an smaller than normal adrenaline bio-chip."
|
||||
implant_type = /obj/item/bio_chip/basic_adrenalin
|
||||
|
||||
/obj/item/bio_chip/proto_adrenalin
|
||||
name = "proto-adrenal bio-chip"
|
||||
desc = "Removes all stuns and knockdowns."
|
||||
icon_state = "adrenal"
|
||||
origin_tech = "materials=2;biotech=4;combat=3;syndicate=2"
|
||||
uses = 1
|
||||
implant_data = /datum/implant_fluff/proto_adrenaline
|
||||
implant_state = "implant-syndicate"
|
||||
|
||||
/obj/item/bio_chip/proto_adrenalin/activate()
|
||||
uses--
|
||||
to_chat(imp_in, "<span class='notice'>You feel a sudden surge of energy!</span>")
|
||||
imp_in.SetStunned(0)
|
||||
imp_in.SetWeakened(0)
|
||||
imp_in.SetKnockDown(0)
|
||||
imp_in.SetParalysis(0)
|
||||
imp_in.setStaminaLoss(0) //Since it doesn't have a good followup like adrenals, and getting batoned the moment after triggering it will stamina crit you, will set to zero over - 75
|
||||
imp_in.stand_up(TRUE)
|
||||
SEND_SIGNAL(imp_in, COMSIG_LIVING_CLEAR_STUNS)
|
||||
imp_in.reagents.add_reagent("stimulative_cling", 1)
|
||||
if(!uses)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/bio_chip_implanter/proto_adrenalin
|
||||
name = "bio-chip implanter (proto-adrenalin)"
|
||||
implant_type = /obj/item/bio_chip/proto_adrenalin
|
||||
|
||||
/obj/item/bio_chip_case/proto_adrenalin
|
||||
name = "bio-chip case - 'proto-adrenalin'"
|
||||
desc = "A glass case containing an proto-adrenalin bio-chip."
|
||||
implant_type = /obj/item/bio_chip/proto_adrenalin
|
||||
@@ -1,68 +0,0 @@
|
||||
/obj/item/bio_chip_case
|
||||
name = "bio-chip case"
|
||||
desc = "A glass case containing a bio-chip."
|
||||
icon = 'icons/obj/bio_chips.dmi'
|
||||
icon_state = "implantcase"
|
||||
item_state = "implantcase"
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
origin_tech = "materials=1;biotech=2"
|
||||
container_type = OPENCONTAINER | INJECTABLE | DRAWABLE
|
||||
materials = list(MAT_GLASS = 500)
|
||||
|
||||
var/obj/item/bio_chip/imp
|
||||
var/obj/item/bio_chip/implant_type
|
||||
|
||||
/obj/item/bio_chip_case/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!implant_type)
|
||||
return
|
||||
imp = new implant_type(src)
|
||||
update_state()
|
||||
|
||||
/obj/item/bio_chip_case/Destroy()
|
||||
if(imp)
|
||||
QDEL_NULL(imp)
|
||||
return ..()
|
||||
|
||||
/obj/item/bio_chip_case/proc/update_state()
|
||||
if(imp)
|
||||
origin_tech = imp.origin_tech
|
||||
flags = imp.flags & ~DROPDEL
|
||||
reagents = imp.reagents
|
||||
else
|
||||
origin_tech = initial(origin_tech)
|
||||
flags = initial(flags)
|
||||
reagents = null
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/item/bio_chip_case/update_overlays()
|
||||
. = ..()
|
||||
if(imp)
|
||||
var/image/implant_overlay = image('icons/obj/bio_chips.dmi', imp.implant_state)
|
||||
. += implant_overlay
|
||||
|
||||
/obj/item/bio_chip_case/attackby__legacy__attackchain(obj/item/W, mob/user)
|
||||
..()
|
||||
|
||||
if(is_pen(W))
|
||||
rename_interactive(user, W)
|
||||
else if(istype(W, /obj/item/bio_chip_implanter))
|
||||
var/obj/item/bio_chip_implanter/I = W
|
||||
if(I.imp)
|
||||
if(imp || I.imp.implanted)
|
||||
return
|
||||
I.imp.forceMove(src)
|
||||
imp = I.imp
|
||||
I.imp = null
|
||||
update_state()
|
||||
I.update_icon(UPDATE_ICON_STATE)
|
||||
else
|
||||
if(imp)
|
||||
if(I.imp)
|
||||
return
|
||||
imp.loc = I
|
||||
I.imp = imp
|
||||
imp = null
|
||||
update_state()
|
||||
I.update_icon(UPDATE_ICON_STATE)
|
||||
@@ -1,52 +0,0 @@
|
||||
/obj/item/bio_chip/chem
|
||||
name = "chem bio-chip"
|
||||
desc = "Injects things."
|
||||
icon_state = "reagents"
|
||||
origin_tech = "materials=3;biotech=4"
|
||||
container_type = OPENCONTAINER
|
||||
trigger_causes = BIOCHIP_TRIGGER_DEATH_ANY
|
||||
implant_data = /datum/implant_fluff/chem
|
||||
implant_state = "implant-nanotrasen"
|
||||
|
||||
/obj/item/bio_chip/chem/Initialize(mapload)
|
||||
. = ..()
|
||||
create_reagents(50)
|
||||
GLOB.tracked_implants += src
|
||||
|
||||
/obj/item/bio_chip/chem/Destroy()
|
||||
GLOB.tracked_implants -= src
|
||||
return ..()
|
||||
|
||||
/obj/item/bio_chip/chem/death_trigger(mob/victim, gibbed)
|
||||
activate(reagents.total_volume)
|
||||
|
||||
/obj/item/bio_chip/chem/activate(cause)
|
||||
if(!cause || !imp_in)
|
||||
return FALSE
|
||||
var/mob/living/carbon/R = imp_in
|
||||
var/injectamount
|
||||
|
||||
var/list/implant_chems = list()
|
||||
for(var/datum/reagent/chems in reagents.reagent_list)
|
||||
implant_chems += chems.name
|
||||
var/contained_chemicals = english_list(implant_chems)
|
||||
|
||||
if(cause == "action_button")
|
||||
injectamount = reagents.total_volume
|
||||
else
|
||||
injectamount = cause
|
||||
reagents.trans_to(R, injectamount)
|
||||
add_attack_logs(usr, R, "Chem bio-chip activated injecting [injectamount]u of [contained_chemicals]")
|
||||
to_chat(R, "<span class='italics'>You hear a faint beep.</span>")
|
||||
if(!reagents.total_volume)
|
||||
to_chat(R, "<span class='italics'>You hear a faint click from your chest.</span>")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/bio_chip_implanter/chem
|
||||
name = "bio-chip implanter (chem)"
|
||||
implant_type = /obj/item/bio_chip/chem
|
||||
|
||||
/obj/item/bio_chip_case/chem
|
||||
name = "bio-chip case - 'Remote Chemical'"
|
||||
desc = "A glass case containing a remote chemical bio-chip."
|
||||
implant_type = /obj/item/bio_chip/chem
|
||||
@@ -1,68 +0,0 @@
|
||||
/obj/item/bio_chip/death_alarm
|
||||
name = "death alarm bio-chip"
|
||||
desc = "An alarm which monitors host vital signs and transmits a radio message upon death."
|
||||
activated = BIOCHIP_ACTIVATED_PASSIVE
|
||||
trigger_causes = BIOCHIP_TRIGGER_DEATH_ANY
|
||||
implant_data = /datum/implant_fluff/death_alarm
|
||||
implant_state = "implant-nanotrasen"
|
||||
|
||||
var/mobname = "Unknown"
|
||||
var/static/list/stealth_areas = typecacheof(list(/area/syndicate_mothership, /area/shuttle/syndicate_elite))
|
||||
/// Tracking to prevent multiple EMPs in the same tick from flooding radio.
|
||||
COOLDOWN_DECLARE(emp_spam_lock)
|
||||
|
||||
/obj/item/bio_chip/death_alarm/implant(mob/target)
|
||||
. = ..()
|
||||
if(.)
|
||||
mobname = target.real_name
|
||||
|
||||
/obj/item/bio_chip/death_alarm/activate(cause) // Death signal sends name followed by the gibbed / not gibbed check
|
||||
var/mob/M = imp_in
|
||||
var/area/t = get_area(M)
|
||||
|
||||
var/obj/item/radio/headset/a = new /obj/item/radio/headset(src)
|
||||
a.follow_target = M
|
||||
|
||||
switch(cause)
|
||||
if("gib")
|
||||
a.autosay("[mobname] has died-zzzzt in-in-in...", "[mobname]'s Death Alarm")
|
||||
qdel(src)
|
||||
if("emp")
|
||||
if(!COOLDOWN_FINISHED(src, emp_spam_lock))
|
||||
return
|
||||
var/name = prob(50) ? t.name : pick(SSmapping.teleportlocs)
|
||||
a.autosay("[mobname] has died in [name]!", "[mobname]'s Death Alarm")
|
||||
COOLDOWN_START(src, emp_spam_lock, 0.1 SECONDS)
|
||||
else
|
||||
if(is_type_in_typecache(t, stealth_areas))
|
||||
//give the syndies a bit of stealth
|
||||
a.autosay("[mobname] has died in Space!", "[mobname]'s Death Alarm")
|
||||
else
|
||||
a.autosay("[mobname] has died in [t.name]!", "[mobname]'s Death Alarm")
|
||||
qdel(src)
|
||||
|
||||
qdel(a)
|
||||
|
||||
/obj/item/bio_chip/death_alarm/emp_act(severity) //for some reason alarms stop going off in case they are emp'd, even without this
|
||||
activate("emp") //let's shout that this dude is dead
|
||||
|
||||
/obj/item/bio_chip/death_alarm/death_trigger(mob/source, gibbed)
|
||||
if(gibbed)
|
||||
activate("gib")
|
||||
else
|
||||
activate("death")
|
||||
|
||||
/obj/item/bio_chip/death_alarm/removed(mob/target)
|
||||
if(..())
|
||||
UnregisterSignal(target, COMSIG_MOB_DEATH)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/bio_chip_implanter/death_alarm
|
||||
name = "bio-chip implanter (Death Alarm)"
|
||||
implant_type = /obj/item/bio_chip/death_alarm
|
||||
|
||||
/obj/item/bio_chip_case/death_alarm
|
||||
name = "bio-chip Case - 'Death Alarm'"
|
||||
desc = "A case containing a death alarm bio-chip."
|
||||
implant_type = /obj/item/bio_chip/death_alarm
|
||||
@@ -1,76 +0,0 @@
|
||||
/datum/deathrattle_group
|
||||
var/name
|
||||
var/list/implants = list()
|
||||
|
||||
/datum/deathrattle_group/New(name)
|
||||
if(name)
|
||||
src.name = name
|
||||
else
|
||||
// Give the group a unique name for debugging, and possible future
|
||||
// use for making custom linked groups.
|
||||
src.name = "[rand(100, 999)] [pick(GLOB.phonetic_alphabet)]"
|
||||
|
||||
/*
|
||||
* Proc called by new implant being added to the group. Listens for the
|
||||
* implant being implanted, removed and destroyed.
|
||||
*
|
||||
* If implant is already implanted in a person, then trigger the implantation
|
||||
* code.
|
||||
*/
|
||||
/datum/deathrattle_group/proc/register(obj/item/bio_chip/deathrattle/implant)
|
||||
if(implant in implants)
|
||||
return
|
||||
RegisterSignal(implant, COMSIG_PARENT_QDELETING, PROC_REF(on_implant_destruction))
|
||||
RegisterSignal(implant, COMSIG_IMPLANT_ACTIVATED, PROC_REF(on_user_death))
|
||||
|
||||
implants += implant
|
||||
|
||||
|
||||
/datum/deathrattle_group/proc/on_implant_destruction(obj/item/bio_chip/implant)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
implants -= implant
|
||||
|
||||
/datum/deathrattle_group/proc/on_user_death(obj/item/bio_chip/implant, source, mob/owner)
|
||||
SIGNAL_HANDLER
|
||||
var/victim_name = owner.mind ? owner.mind.name : owner.real_name
|
||||
// All "hearers" hear the same sound.
|
||||
var/sound = pick(
|
||||
'sound/items/knell1.ogg',
|
||||
'sound/items/knell2.ogg',
|
||||
'sound/items/knell3.ogg',
|
||||
'sound/items/knell4.ogg',
|
||||
)
|
||||
|
||||
|
||||
for(var/obj/item/bio_chip/deathrattle/other_implant as anything in implants)
|
||||
|
||||
// Skip the unfortunate soul, and any unimplanted implants
|
||||
if(implant == other_implant || !implant.imp_in)
|
||||
continue
|
||||
|
||||
var/mob/living/recipient = other_implant.imp_in
|
||||
to_chat(recipient, "<i>You hear a strange, robotic voice in your head...</i> <span class='robot'>\"<b>[victim_name]</b> has died...\"</span>")
|
||||
recipient.playsound_local(get_turf(recipient), sound, vol = 75, vary = FALSE, pressure_affected = FALSE, use_reverb = FALSE)
|
||||
qdel(implant)
|
||||
|
||||
/obj/item/bio_chip/deathrattle
|
||||
name = "deathrattle implant"
|
||||
desc = "Hope no one else dies, prepare for when they do."
|
||||
activated = BIOCHIP_ACTIVATED_PASSIVE
|
||||
trigger_causes = BIOCHIP_TRIGGER_DEATH_ONCE
|
||||
implant_data = /datum/implant_fluff/deathrattle
|
||||
implant_state = "implant-nanotrasen"
|
||||
|
||||
actions_types = null
|
||||
|
||||
/obj/item/bio_chip/deathrattle/emp_act(severity)
|
||||
activate("emp")
|
||||
|
||||
/obj/item/bio_chip/deathrattle/death_trigger(mob/source, gibbed)
|
||||
activate("death")
|
||||
|
||||
/obj/item/bio_chip_case/deathrattle
|
||||
name = "implant case - 'Deathrattle'"
|
||||
desc = "A glass case containing a deathrattle implant."
|
||||
implant_type = /obj/item/bio_chip/deathrattle
|
||||
@@ -1,34 +0,0 @@
|
||||
// Dust implant, for CC officers. Prevents gear theft if they die.
|
||||
|
||||
/obj/item/bio_chip/dust
|
||||
name = "duster bio-chip"
|
||||
desc = "A remote controlled bio-chip that will dust the user upon activation (or death of user)."
|
||||
icon_state = "dust"
|
||||
actions_types = list(/datum/action/item_action/hands_free/activate/always)
|
||||
trigger_causes = BIOCHIP_TRIGGER_DEATH_ONCE | BIOCHIP_TRIGGER_NOT_WHEN_GIBBED
|
||||
implant_data = /datum/implant_fluff/dust
|
||||
implant_state = "implant-nanotrasen"
|
||||
|
||||
/obj/item/bio_chip/dust/death_trigger(mob/source, force)
|
||||
activate("death")
|
||||
|
||||
/obj/item/bio_chip/dust/activate(cause)
|
||||
if(!cause || !imp_in || cause == "emp")
|
||||
return FALSE
|
||||
if(cause == "action_button" && alert(imp_in, "Are you sure you want to activate your dusting bio-chip? This will turn you to ash!", "Dusting Confirmation", "Yes", "No") != "Yes")
|
||||
return FALSE
|
||||
to_chat(imp_in, "<span class='notice'>Your dusting bio-chip activates!</span>")
|
||||
imp_in.visible_message("<span class = 'warning'>[imp_in] burns up in a flash!</span>")
|
||||
imp_in.dust()
|
||||
|
||||
/obj/item/bio_chip/dust/emp_act(severity)
|
||||
return
|
||||
|
||||
/obj/item/bio_chip_implanter/dust
|
||||
name = "bio-chip implanter (Dust-on-death)"
|
||||
implant_type = /obj/item/bio_chip/dust
|
||||
|
||||
/obj/item/bio_chip_case/dust
|
||||
name = "bio-chip case - 'Dust'"
|
||||
desc = "A glass case containing a dust bio-chip."
|
||||
implant_type = /obj/item/bio_chip/dust
|
||||
@@ -1,23 +0,0 @@
|
||||
/obj/item/bio_chip/emp
|
||||
name = "emp bio-chip"
|
||||
desc = "Triggers an EMP."
|
||||
icon_state = "emp"
|
||||
origin_tech = "biotech=3;magnets=4;syndicate=1"
|
||||
uses = 2
|
||||
implant_data = /datum/implant_fluff/emp
|
||||
implant_state = "implant-syndicate"
|
||||
|
||||
/obj/item/bio_chip/emp/activate()
|
||||
uses--
|
||||
INVOKE_ASYNC(GLOBAL_PROC, GLOBAL_PROC_REF(empulse), get_turf(imp_in), 3, 5, 1)
|
||||
if(!uses)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/bio_chip_implanter/emp
|
||||
name = "bio-chip implanter (EMP)"
|
||||
implant_type = /obj/item/bio_chip/emp
|
||||
|
||||
/obj/item/bio_chip_case/emp
|
||||
name = "bio-chip case - 'EMP'"
|
||||
desc = "A glass case containing an EMP bio-chip."
|
||||
implant_type = /obj/item/bio_chip/emp
|
||||
@@ -1,147 +0,0 @@
|
||||
/obj/item/bio_chip/explosive
|
||||
name = "microbomb bio-chip"
|
||||
desc = "And boom goes the weasel."
|
||||
icon_state = "explosive"
|
||||
origin_tech = "materials=2;combat=3;biotech=4;syndicate=4"
|
||||
actions_types = list(/datum/action/item_action/hands_free/activate/always)
|
||||
trigger_causes = BIOCHIP_TRIGGER_DEATH_ONCE // Not surviving that
|
||||
implant_data = /datum/implant_fluff/explosive
|
||||
implant_state = "implant-syndicate"
|
||||
|
||||
var/detonating = FALSE
|
||||
var/weak = 2
|
||||
var/medium = 0.8
|
||||
var/heavy = 0.4
|
||||
var/delay = 7
|
||||
|
||||
/obj/item/bio_chip/explosive/death_trigger(mob/source, gibbed)
|
||||
activate("death")
|
||||
|
||||
/obj/item/bio_chip/explosive/activate(cause)
|
||||
if(!cause || !imp_in)
|
||||
return FALSE
|
||||
if(cause == "action_button" && alert(imp_in, "Are you sure you want to activate your microbomb bio-chip? This will cause you to explode!", "Microbomb Bio-chip Confirmation", "Yes", "No") != "Yes")
|
||||
return FALSE
|
||||
if(detonating)
|
||||
return FALSE
|
||||
heavy = round(heavy)
|
||||
medium = round(medium)
|
||||
weak = round(weak)
|
||||
detonating = TRUE
|
||||
to_chat(imp_in, "<span class='danger'>You activate your microbomb bio-chip.</span>")
|
||||
//If the delay is short, just blow up already jeez
|
||||
if(delay <= 7)
|
||||
self_destruct()
|
||||
return
|
||||
timed_explosion()
|
||||
|
||||
/// Gib the implantee and delete their destructible contents.
|
||||
/obj/item/bio_chip/explosive/proc/self_destruct()
|
||||
if(!imp_in)
|
||||
return
|
||||
|
||||
explosion(src, heavy, medium, weak, weak, flame_range = weak, cause = name)
|
||||
|
||||
// In case something happens to the implantee between now and the
|
||||
// self-destruct
|
||||
var/current_location = get_turf(imp_in)
|
||||
|
||||
var/list/destructed_items = list()
|
||||
|
||||
// Iterate over the implantee's contents and take out indestructible
|
||||
// things to avoid having to worry about containers and recursion
|
||||
for(var/obj/item/I in imp_in.get_contents())
|
||||
if(I == src) // Don't delete ourselves prematurely
|
||||
continue
|
||||
// Drop indestructible items on the ground first, to avoid them
|
||||
// getting deleted when destroying the rest of the items, which we
|
||||
// track in a list to qdel afterwards
|
||||
if(I.resistance_flags & INDESTRUCTIBLE)
|
||||
I.forceMove(current_location)
|
||||
else
|
||||
destructed_items += I
|
||||
|
||||
QDEL_LIST_CONTENTS(destructed_items)
|
||||
|
||||
imp_in.gib()
|
||||
|
||||
qdel(src)
|
||||
|
||||
/obj/item/bio_chip/explosive/implant(mob/source)
|
||||
var/obj/item/bio_chip/explosive/imp_e = locate(type) in source
|
||||
if(imp_e && imp_e != src)
|
||||
imp_e.heavy += heavy
|
||||
imp_e.medium += medium
|
||||
imp_e.weak += weak
|
||||
imp_e.delay += delay
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/bio_chip/explosive/proc/timed_explosion()
|
||||
imp_in.visible_message("<span class = 'warning'>[imp_in] starts beeping ominously!</span>")
|
||||
playsound(loc, 'sound/items/timer.ogg', 30, 0)
|
||||
var/wait_delay = delay / 4
|
||||
sleep(wait_delay)
|
||||
if(imp_in && imp_in.stat)
|
||||
imp_in.visible_message("<span class = 'warning'>[imp_in] doubles over in pain!</span>")
|
||||
imp_in.Weaken(14 SECONDS)
|
||||
playsound(loc, 'sound/items/timer.ogg', 30, 0)
|
||||
sleep(wait_delay)
|
||||
playsound(loc, 'sound/items/timer.ogg', 30, 0)
|
||||
sleep(wait_delay)
|
||||
playsound(loc, 'sound/items/timer.ogg', 30, 0)
|
||||
sleep(wait_delay)
|
||||
self_destruct()
|
||||
|
||||
/obj/item/bio_chip/explosive/macro
|
||||
name = "macrobomb bio-chip"
|
||||
desc = "And boom goes the weasel. And everything else nearby."
|
||||
origin_tech = "materials=3;combat=5;biotech=4;syndicate=5"
|
||||
weak = 16
|
||||
medium = 8
|
||||
heavy = 4
|
||||
delay = 3 SECONDS
|
||||
implant_data = new /datum/implant_fluff/explosive_macro
|
||||
|
||||
/obj/item/bio_chip/explosive/macro/activate(cause)
|
||||
if(!cause || !imp_in)
|
||||
return FALSE
|
||||
if(cause == "action_button" && alert(imp_in, "Are you sure you want to activate your macrobomb bio-chip? This will cause you to explode and gib!", "Macrobomb Bio-chip Confirmation", "Yes", "No") != "Yes")
|
||||
return FALSE
|
||||
to_chat(imp_in, "<span class='notice'>You activate your macrobomb bio-chip.</span>")
|
||||
timed_explosion()
|
||||
|
||||
/obj/item/bio_chip/explosive/macro/implant(mob/source)
|
||||
var/obj/item/bio_chip/explosive/imp_e = locate(type) in source
|
||||
if(imp_e && imp_e != src)
|
||||
return FALSE
|
||||
imp_e = locate(/obj/item/bio_chip/explosive) in source
|
||||
if(imp_e && imp_e != src)
|
||||
heavy += imp_e.heavy
|
||||
medium += imp_e.medium
|
||||
weak += imp_e.weak
|
||||
delay += imp_e.delay
|
||||
qdel(imp_e)
|
||||
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/bio_chip_implanter/explosive
|
||||
name = "bio-chip implanter (explosive)"
|
||||
implant_type = /obj/item/bio_chip/explosive
|
||||
|
||||
/obj/item/bio_chip_case/explosive
|
||||
name = "bio-chip case - 'Micro Explosive'"
|
||||
desc = "A glass case containing a micro explosive bio-chip."
|
||||
implant_type = /obj/item/bio_chip/explosive
|
||||
|
||||
/obj/item/bio_chip_implanter/explosive_macro
|
||||
name = "bio-chip implanter (macro-explosive)"
|
||||
implant_type = /obj/item/bio_chip/explosive/macro
|
||||
|
||||
/obj/item/bio_chip_case/explosive_macro
|
||||
name = "bio-chip case - 'Macro Explosive'"
|
||||
desc = "A glass case containing a macro explosive bio-chip."
|
||||
implant_type = /obj/item/bio_chip/explosive/macro
|
||||
@@ -1,26 +0,0 @@
|
||||
/// Dumb path but easier to search for admins
|
||||
/obj/item/bio_chip/gorilla_rampage
|
||||
name = "magillitis serum bio-chip"
|
||||
desc = "An experimental biochip which causes irreversable rapid muscular growth in Hominidae. Side-affects may include hypertrichosis, violent outbursts, and an unending affinity for bananas."
|
||||
icon_state = "gorilla_rampage"
|
||||
origin_tech = "combat=5;biotech=5;syndicate=2"
|
||||
uses = 1
|
||||
implant_data = /datum/implant_fluff/gorilla_rampage
|
||||
implant_state = "implant-syndicate"
|
||||
|
||||
/obj/item/bio_chip/gorilla_rampage/activate()
|
||||
if(!iscarbon(imp_in))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/target = imp_in
|
||||
target.visible_message("<span class='userdanger'>[target] swells and their hair grows rapidly. Uh oh!.</span>","<span class='userdanger'>You feel your muscles swell and your hair grow as you return to monke.</span>", "<span class='userdanger'>You hear angry gorilla noises.</span>")
|
||||
target.gorillize(TRUE)
|
||||
|
||||
/obj/item/bio_chip_implanter/gorilla_rampage
|
||||
name = "bio-chip implanter (magillitis serum)"
|
||||
implant_type = /obj/item/bio_chip/gorilla_rampage
|
||||
|
||||
/obj/item/bio_chip_case/gorilla_rampage
|
||||
name = "bio-chip case - 'magillitis serum'"
|
||||
desc = "A glass case containing a magillitis bio-chip."
|
||||
implant_type = /obj/item/bio_chip/gorilla_rampage
|
||||
@@ -1,27 +0,0 @@
|
||||
/obj/item/bio_chip/krav_maga
|
||||
name = "krav maga bio-chip"
|
||||
desc = "Teaches you the arts of Krav Maga in 5 short instructional videos beamed directly into your eyeballs."
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state ="scroll2"
|
||||
origin_tech = "materials=2;biotech=4;combat=5;syndicate=4"
|
||||
implant_data = /datum/implant_fluff/krav_maga
|
||||
|
||||
var/datum/martial_art/krav_maga/style = new
|
||||
|
||||
/obj/item/bio_chip/krav_maga/activate()
|
||||
var/mob/living/carbon/human/H = imp_in
|
||||
if(!ishuman(H) || !H.mind)
|
||||
return
|
||||
if(istype(H.mind.martial_art, /datum/martial_art/krav_maga))
|
||||
style.remove(H)
|
||||
else
|
||||
style.teach(H, TRUE)
|
||||
|
||||
/obj/item/bio_chip_implanter/krav_maga
|
||||
name = "bio-chip implanter (krav maga)"
|
||||
implant_type = /obj/item/bio_chip/krav_maga
|
||||
|
||||
/obj/item/bio_chip_case/krav_maga
|
||||
name = "bio-chip case - 'Krav Maga'"
|
||||
desc = "A glass case containing a bio-chip that can teach the user the art of Krav Maga."
|
||||
implant_type = /obj/item/bio_chip/krav_maga
|
||||
@@ -1,43 +0,0 @@
|
||||
/obj/item/bio_chip/mindshield
|
||||
name = "mindshield bio-chip"
|
||||
desc = "Stops people messing with your mind."
|
||||
origin_tech = "materials=2;biotech=4;programming=4"
|
||||
activated = BIOCHIP_ACTIVATED_PASSIVE
|
||||
implant_data = /datum/implant_fluff/mindshield
|
||||
implant_state = "implant-nanotrasen"
|
||||
|
||||
/obj/item/bio_chip/mindshield/can_implant(mob/source, mob/user)
|
||||
if(source.mind?.has_antag_datum(/datum/antagonist/rev/head))
|
||||
source.visible_message("<span class='biggerdanger'>[source] seems to resist [src]!</span>",
|
||||
"<span class='warning'>You feel something interfering with your mental conditioning, but you resist it!</span>")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/bio_chip/mindshield/implant(mob/target)
|
||||
if(!..())
|
||||
return FALSE
|
||||
if(target.mind)
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/rev))
|
||||
SSticker.mode.remove_revolutionary(target.mind)
|
||||
if(IS_CULTIST(target))
|
||||
to_chat(target, "<span class='warning'>You feel the corporate tendrils of Nanotrasen try to invade your mind!</span>")
|
||||
return TRUE
|
||||
|
||||
to_chat(target, "<span class='notice'>Your mind feels hardened - more resistant to brainwashing.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/item/bio_chip/mindshield/removed(mob/target, silent = 0)
|
||||
if(..())
|
||||
if(target.stat != DEAD && !silent)
|
||||
to_chat(target, "<span class='boldnotice'>Your mind softens. You feel susceptible to the effects of brainwashing once more.</span>")
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/bio_chip_implanter/mindshield
|
||||
name = "bio-chip implanter (mindshield)"
|
||||
implant_type = /obj/item/bio_chip/mindshield
|
||||
|
||||
/obj/item/bio_chip_case/mindshield
|
||||
name = "bio-chip case - 'mindshield'"
|
||||
desc = "A glass case containing a mindshield bio-chip."
|
||||
implant_type = /obj/item/bio_chip/mindshield
|
||||
@@ -1,120 +0,0 @@
|
||||
/obj/item/bio_chip_pad
|
||||
name = "bio-chip pad"
|
||||
desc = "Used to modify bio-chips."
|
||||
icon = 'icons/obj/bio_chips.dmi'
|
||||
icon_state = "implantpad-off"
|
||||
item_state = "electronic"
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
var/obj/item/bio_chip_case/case
|
||||
var/static/list/cached_base64_icons = list()
|
||||
|
||||
/obj/item/bio_chip_pad/Destroy()
|
||||
if(case)
|
||||
eject_case()
|
||||
return ..()
|
||||
|
||||
/obj/item/bio_chip_pad/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>You can <b>Alt-Click</b> [src] to remove it's stored implant.</span>"
|
||||
|
||||
/obj/item/bio_chip_pad/update_icon_state()
|
||||
if(case)
|
||||
icon_state = "implantpad-on"
|
||||
else
|
||||
icon_state = "implantpad-off"
|
||||
|
||||
/obj/item/bio_chip_pad/attack_self__legacy__attackchain(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/item/bio_chip_pad/attackby__legacy__attackchain(obj/item/bio_chip_case/C, mob/user)
|
||||
if(istype(C))
|
||||
addcase(user, C)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/bio_chip_pad/proc/addcase(mob/user, obj/item/bio_chip_case/C)
|
||||
if(!user || !C)
|
||||
return
|
||||
if(case)
|
||||
to_chat(user, "<span class='warning'>There's already a bio-chip in the pad!</span>")
|
||||
return
|
||||
user.unequip(C)
|
||||
C.forceMove(src)
|
||||
case = C
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/item/bio_chip_pad/proc/eject_case(mob/user)
|
||||
if(!case)
|
||||
return
|
||||
if(user)
|
||||
if(user.put_in_hands(case))
|
||||
add_fingerprint(user)
|
||||
case.add_fingerprint(user)
|
||||
case = null
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
SStgui.update_uis(src)
|
||||
|
||||
/obj/item/bio_chip_pad/AltClick(mob/user)
|
||||
if(user.stat || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED) || !Adjacent(user))
|
||||
return
|
||||
|
||||
eject_case(user)
|
||||
|
||||
/obj/item/bio_chip_pad/ui_state(mob/user)
|
||||
return GLOB.default_state
|
||||
|
||||
/obj/item/bio_chip_pad/ui_interact(mob/user, datum/tgui/ui = null)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "BioChipPad", name)
|
||||
ui.set_autoupdate(FALSE)
|
||||
ui.open()
|
||||
|
||||
/obj/item/bio_chip_pad/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["contains_case"] = case ? TRUE : FALSE
|
||||
if(case && case.imp)
|
||||
var/datum/implant_fluff/implant_data = case.imp.implant_data
|
||||
var/icon/base64icon = cached_base64_icons["[initial(case.imp.icon)][initial(case.imp.icon_state)]"]
|
||||
if(!base64icon)
|
||||
base64icon = "[icon2base64(icon(initial(case.imp.icon), initial(case.imp.icon_state), SOUTH, 1))]"
|
||||
cached_base64_icons["[initial(case.imp.icon)][initial(case.imp.icon_state)]"] = base64icon
|
||||
data["implant"] = list(
|
||||
"name" = implant_data.name,
|
||||
"life" = implant_data.life,
|
||||
"notes" = implant_data.notes,
|
||||
"function" = implant_data.function,
|
||||
"image" = "[icon2base64(icon(initial(case.imp.icon), initial(case.imp.icon_state), SOUTH, 1))]",
|
||||
)
|
||||
if(istype(case.imp, /obj/item/bio_chip/tracking))
|
||||
var/obj/item/bio_chip/tracking/T = case.imp
|
||||
data["gps"] = T
|
||||
data["tag"] = T.gpstag
|
||||
else
|
||||
data["gps"] = null
|
||||
data["tag"] = null
|
||||
else
|
||||
// Sanity check in the case that a pad is used for multiple types of implants.
|
||||
data["gps"] = null
|
||||
data["tag"] = null
|
||||
|
||||
return data
|
||||
|
||||
/obj/item/bio_chip_pad/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
if(..())
|
||||
return
|
||||
. = TRUE
|
||||
switch(action)
|
||||
if("eject_case")
|
||||
eject_case(ui.user)
|
||||
if("tag")
|
||||
var/obj/item/bio_chip/tracking/T = case.imp
|
||||
var/newtag = params["newtag"] || ""
|
||||
newtag = uppertext(paranoid_sanitize(copytext_char(newtag, 1, 5)))
|
||||
if(!length(newtag) || T.gpstag == newtag)
|
||||
return
|
||||
T.gpstag = newtag
|
||||
@@ -1,47 +0,0 @@
|
||||
/obj/item/bio_chip/grey_autocloner
|
||||
name = "technocracy cloning bio-chip"
|
||||
desc = "Allows for advanced instantanious cloning!"
|
||||
origin_tech = "materials=3;combat=5;syndicate=2"
|
||||
activated = FALSE
|
||||
trigger_causes = BIOCHIP_TRIGGER_DEATH_ANY
|
||||
implant_state = "implant-alien"
|
||||
var/obj/machinery/grey_autocloner/linked
|
||||
var/datum/dna2_record/our_record
|
||||
|
||||
/obj/item/bio_chip/grey_autocloner/Destroy()
|
||||
linked = null
|
||||
our_record = null
|
||||
return ..()
|
||||
|
||||
/obj/item/bio_chip/grey_autocloner/death_trigger(mob/source, gibbed)
|
||||
imp_in.ghostize(TRUE)
|
||||
if(linked)
|
||||
linked.growclone(our_record)
|
||||
|
||||
/obj/item/bio_chip/grey_autocloner/implant(mob/source, mob/user, force)
|
||||
if(!linked)
|
||||
to_chat(user, "<span class='warning'>Please link the implanter with a Technocracy cloning pod!</span>")
|
||||
return FALSE
|
||||
. = ..()
|
||||
if(!. || !ishuman(imp_in))
|
||||
return FALSE
|
||||
our_record = new /datum/dna2_record()
|
||||
our_record.ckey = imp_in.ckey
|
||||
var/obj/item/organ/B = imp_in.get_int_organ(/obj/item/organ/internal/brain)
|
||||
B.dna.check_integrity()
|
||||
our_record.dna = B.dna.Clone()
|
||||
our_record.id = copytext(md5(B.dna.real_name), 2, 6)
|
||||
our_record.name = B.dna.real_name
|
||||
our_record.types = DNA2_BUF_UI|DNA2_BUF_UE|DNA2_BUF_SE
|
||||
our_record.languages = imp_in.languages
|
||||
if(imp_in.mind) //Save that mind so traitors can continue traitoring after cloning.
|
||||
our_record.mind = imp_in.mind.UID()
|
||||
|
||||
/obj/item/bio_chip_implanter/grey_autocloner
|
||||
name = "bio-chip implanter (Technocracy cloning)"
|
||||
implant_type = /obj/item/bio_chip/grey_autocloner
|
||||
|
||||
/obj/item/bio_chip_case/grey_autocloner
|
||||
name = "bio-chip case - 'Technocracy cloning'"
|
||||
desc = "A glass case containing an Technocracy bio-chip."
|
||||
implant_type = /obj/item/bio_chip/grey_autocloner
|
||||
@@ -1,27 +0,0 @@
|
||||
/obj/item/bio_chip/sad_trombone
|
||||
name = "sad trombone bio-chip"
|
||||
activated = FALSE
|
||||
trigger_emotes = list("deathgasp")
|
||||
// If something forces the clown to fake death, it's pretty funny to still see the sad trombone played
|
||||
trigger_causes = BIOCHIP_EMOTE_TRIGGER_UNINTENTIONAL | BIOCHIP_TRIGGER_DEATH_ANY
|
||||
implant_data = /datum/implant_fluff/sad_trombone
|
||||
implant_state = "implant-honk"
|
||||
|
||||
/obj/item/bio_chip/sad_trombone/emote_trigger(emote, mob/source, force)
|
||||
activate(emote)
|
||||
|
||||
/obj/item/bio_chip/sad_trombone/death_trigger(mob/user, gibbed)
|
||||
activate(gibbed)
|
||||
|
||||
|
||||
/obj/item/bio_chip/sad_trombone/activate()
|
||||
playsound(loc, 'sound/misc/sadtrombone.ogg', 50, FALSE)
|
||||
|
||||
/obj/item/bio_chip_implanter/sad_trombone
|
||||
name = "bio-chip implanter (sad trombone)"
|
||||
implant_type = /obj/item/bio_chip/sad_trombone
|
||||
|
||||
/obj/item/bio_chip_case/sad_trombone
|
||||
name = "bio-chip case - 'Sad Trombone'"
|
||||
desc = "A glass case containing a sad trombone bio-chip."
|
||||
implant_type = /obj/item/bio_chip/sad_trombone
|
||||
@@ -1,46 +0,0 @@
|
||||
/obj/item/bio_chip/shock
|
||||
name = "power bio-chip"
|
||||
desc = "A shockingly effective bio-chip for stunning or killing all those in your way. Do it."
|
||||
icon_state = "lighting_bolt"
|
||||
item_color = "r"
|
||||
origin_tech = "combat=5;magnets=3;biotech=4;syndicate=2"
|
||||
implant_data = /datum/implant_fluff/shock
|
||||
implant_state = "implant-syndicate"
|
||||
var/enabled = FALSE
|
||||
var/old_mclick_override
|
||||
var/datum/middle_click_override/shock_implant/mclick_override = new /datum/middle_click_override/shock_implant
|
||||
COOLDOWN_DECLARE(last_shocked)
|
||||
var/shock_delay = 3 SECONDS
|
||||
var/unlimited_power = FALSE // Does this really need explanation?
|
||||
var/shock_range = 7
|
||||
|
||||
/obj/item/bio_chip/shock/activate()
|
||||
enabled = !enabled
|
||||
to_chat(imp_in, "<span class='notice'>You toggle the implant [enabled? "on" : "off"].</span>")
|
||||
if(enabled)
|
||||
if(imp_in.middleClickOverride)
|
||||
old_mclick_override = imp_in.middleClickOverride
|
||||
imp_in.middleClickOverride = mclick_override
|
||||
else
|
||||
if(old_mclick_override)
|
||||
imp_in.middleClickOverride = old_mclick_override
|
||||
old_mclick_override = null
|
||||
else
|
||||
imp_in.middleClickOverride = null
|
||||
|
||||
/obj/item/bio_chip/shock/removed()
|
||||
if(old_mclick_override)
|
||||
imp_in.middleClickOverride = old_mclick_override
|
||||
old_mclick_override = null
|
||||
else
|
||||
imp_in.middleClickOverride = null
|
||||
return ..()
|
||||
|
||||
/obj/item/bio_chip_implanter/shock
|
||||
name = "bio-chip implanter (power)"
|
||||
implant_type = /obj/item/bio_chip/shock
|
||||
|
||||
/obj/item/bio_chip_case/shock
|
||||
name = "bio-chip case - 'power'"
|
||||
desc = "A glass case containing a power bio-chip."
|
||||
implant_type = /obj/item/bio_chip/shock
|
||||
@@ -1,144 +0,0 @@
|
||||
/**
|
||||
* # Stealth Implant
|
||||
*
|
||||
* Implant which allows you to summon an MGS-style cardboard box that turns you invisble after a short delay.
|
||||
*/
|
||||
/obj/item/bio_chip/stealth
|
||||
name = "S3 bio-chip"
|
||||
desc = "Allows you to be hidden in plain sight."
|
||||
implant_state = "implant-syndicate"
|
||||
implant_data = /datum/implant_fluff/stealth
|
||||
actions_types = list(/datum/action/item_action/agent_box)
|
||||
|
||||
/obj/item/bio_chip_implanter/stealth
|
||||
name = "bio-chip implanter (stealth)"
|
||||
implant_type = /obj/item/bio_chip/stealth
|
||||
|
||||
/datum/action/item_action/agent_box
|
||||
name = "Deploy Box"
|
||||
desc = "Find inner peace, here, in the box."
|
||||
check_flags = AB_CHECK_HANDS_BLOCKED | AB_CHECK_IMMOBILE | AB_CHECK_CONSCIOUS | AB_CHECK_STUNNED
|
||||
background_icon_state = "bg_agent"
|
||||
button_icon_state = "deploy_box"
|
||||
/// If TRUE, the box can't be deployed
|
||||
var/on_cooldown = FALSE
|
||||
|
||||
/datum/action/item_action/agent_box/Trigger(trigger_flags, left_click)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(istype(owner.loc, /obj/structure/closet/cardboard/agent))
|
||||
var/obj/structure/closet/cardboard/agent/box = owner.loc
|
||||
if(box.open())
|
||||
owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE)
|
||||
recall_box_animation()
|
||||
return
|
||||
// Box closing from here on out.
|
||||
if(!isturf(owner.loc)) //Don't let the player use this to escape mechs/welded closets.
|
||||
to_chat(owner, "<span class='warning'>You need more space to activate this implant!</span>")
|
||||
return
|
||||
owner.playsound_local(owner, 'sound/misc/box_deploy.ogg', 50, TRUE)
|
||||
spawn_box()
|
||||
|
||||
/datum/action/item_action/agent_box/proc/spawn_box()
|
||||
// Do the box's fade in spawn animation with an image so it follows the owner.
|
||||
var/image/fake_box = image('icons/obj/cardboard_boxes.dmi', owner, "agentbox", ABOVE_MOB_LAYER)
|
||||
flick_overlay_view(fake_box, owner, 0.4 SECONDS)
|
||||
fake_box.alpha = 0
|
||||
fake_box.pixel_z = 30
|
||||
animate(fake_box, pixel_z = fake_box.pixel_z - 30, alpha = fake_box.alpha + 255, time = 3, loop = 1)
|
||||
sleep(3)
|
||||
|
||||
// Spawn the actual box
|
||||
var/obj/structure/closet/cardboard/agent/box = new(get_turf(owner), owner)
|
||||
// Slightly shorter time since we needed 0.3s to to do the spawn animation.
|
||||
INVOKE_ASYNC(box, TYPE_PROC_REF(/obj/structure/closet/cardboard/agent, go_invisible), 1.7 SECONDS)
|
||||
owner.forceMove(box)
|
||||
owner.overlay_fullscreen("agent_box", /atom/movable/screen/fullscreen/center/agent_box)
|
||||
RegisterSignal(box, COMSIG_PARENT_QDELETING, PROC_REF(start_cooldown))
|
||||
|
||||
/datum/action/item_action/agent_box/proc/start_cooldown(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
on_cooldown = TRUE
|
||||
addtimer(CALLBACK(src, PROC_REF(end_cooldown)), 10 SECONDS)
|
||||
owner.clear_fullscreen("agent_box")
|
||||
build_all_button_icons()
|
||||
|
||||
/datum/action/item_action/agent_box/proc/end_cooldown()
|
||||
on_cooldown = FALSE
|
||||
build_all_button_icons()
|
||||
|
||||
/datum/action/item_action/agent_box/IsAvailable()
|
||||
if(..() && !on_cooldown)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/action/item_action/agent_box/proc/recall_box_animation()
|
||||
var/image/fake_box = image('icons/obj/cardboard_boxes.dmi', owner, "agentbox", ABOVE_MOB_LAYER)
|
||||
flick_overlay_view(fake_box, owner, 0.4 SECONDS)
|
||||
animate(fake_box, pixel_z = fake_box.pixel_z + 30, alpha = fake_box.alpha - 255, time = 3, loop = 1)
|
||||
|
||||
/datum/action/item_action/agent_box/Grant(mob/grant_to)
|
||||
. = ..()
|
||||
if(owner)
|
||||
RegisterSignal(owner, COMSIG_HUMAN_SUICIDE_ACT, PROC_REF(suicide_act))
|
||||
|
||||
/datum/action/item_action/agent_box/Remove(mob/M)
|
||||
if(owner)
|
||||
UnregisterSignal(owner, COMSIG_HUMAN_SUICIDE_ACT)
|
||||
return ..()
|
||||
|
||||
/datum/action/item_action/agent_box/proc/suicide_act(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
if(!istype(owner.loc, /obj/structure/closet/cardboard/agent))
|
||||
return
|
||||
var/obj/structure/closet/cardboard/agent/box = owner.loc
|
||||
owner.visible_message("<span class='suicide'>[owner] falls out of [box]! It looks like [owner.p_they()] committed suicide!</span>")
|
||||
owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE)
|
||||
INVOKE_ASYNC(box, TYPE_PROC_REF(/obj/structure/closet/cardboard/agent, open))
|
||||
INVOKE_ASYNC(owner, TYPE_PROC_REF(/atom/movable, throw_at), get_turf(owner))
|
||||
return OXYLOSS
|
||||
|
||||
// Stealth implant box
|
||||
/obj/structure/closet/cardboard/agent
|
||||
name = "inconspicious box"
|
||||
desc = "It's so normal that you didn't notice it before."
|
||||
icon_state = "agentbox"
|
||||
max_integrity = 1
|
||||
move_speed_multiplier = 0.5 // You can move at run speed while in this box.
|
||||
material_drop = null
|
||||
|
||||
/obj/structure/closet/cardboard/agent/attackby__legacy__attackchain(obj/item/I, mob/living/user)
|
||||
return
|
||||
|
||||
/obj/structure/closet/cardboard/agent/open()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return FALSE
|
||||
qdel(src)
|
||||
|
||||
// When the box is opened, it's deleted, so we never need to update this.
|
||||
/obj/structure/closet/cardboard/agent/update_icon_state()
|
||||
return
|
||||
|
||||
/obj/structure/closet/cardboard/agent/proc/go_invisible(invis_time = 2 SECONDS)
|
||||
animate(src, alpha = 0, time = invis_time)
|
||||
sleep(invis_time)
|
||||
// This is so people can't locate the box by spamming right click everywhere.
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
/obj/structure/closet/cardboard/agent/proc/reveal()
|
||||
alpha = 255
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE
|
||||
addtimer(CALLBACK(src, PROC_REF(go_invisible)), 1 SECONDS, TIMER_OVERRIDE|TIMER_UNIQUE)
|
||||
|
||||
/obj/structure/closet/cardboard/agent/Bump(atom/A)
|
||||
. = ..()
|
||||
if(isliving(A))
|
||||
reveal()
|
||||
|
||||
/obj/structure/closet/cardboard/agent/Bumped(atom/movable/A)
|
||||
. = ..()
|
||||
if(isliving(A))
|
||||
reveal()
|
||||
@@ -1,74 +0,0 @@
|
||||
/obj/item/storage/hidden_implant
|
||||
name = "bluespace pocket"
|
||||
storage_slots = 2
|
||||
max_w_class = WEIGHT_CLASS_NORMAL
|
||||
max_combined_w_class = WEIGHT_CLASS_GIGANTIC
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
cant_hold = list(/obj/item/disk/nuclear)
|
||||
w_class_override = list(/obj/item/storage/belt)
|
||||
silent = TRUE
|
||||
|
||||
/obj/item/bio_chip/storage
|
||||
name = "storage bio-chip"
|
||||
desc = "Stores up to two big items in a bluespace pocket."
|
||||
icon_state = "storage"
|
||||
origin_tech = "materials=2;magnets=4;bluespace=5;syndicate=4"
|
||||
item_color = "r"
|
||||
implant_data = /datum/implant_fluff/storage
|
||||
implant_state = "implant-syndicate"
|
||||
|
||||
var/obj/item/storage/hidden_implant/storage
|
||||
|
||||
/obj/item/bio_chip/storage/Initialize(mapload)
|
||||
. = ..()
|
||||
storage = new /obj/item/storage/hidden_implant(src)
|
||||
|
||||
/obj/item/bio_chip/storage/emp_act(severity)
|
||||
..()
|
||||
storage.emp_act(severity)
|
||||
|
||||
/obj/item/bio_chip/storage/activate()
|
||||
if(!length(storage.mobs_viewing))
|
||||
storage.MouseDrop(imp_in)
|
||||
else
|
||||
for(var/mob/to_close in storage.mobs_viewing)
|
||||
storage.close(to_close)
|
||||
|
||||
/obj/item/bio_chip/storage/removed(source)
|
||||
if(..())
|
||||
for(var/mob/M in range(1))
|
||||
if(M.s_active == storage)
|
||||
storage.close(M)
|
||||
for(var/obj/item/I in storage)
|
||||
storage.remove_from_storage(I, get_turf(source))
|
||||
return TRUE
|
||||
|
||||
/obj/item/bio_chip/storage/implant(mob/source)
|
||||
var/obj/item/bio_chip/storage/imp_e = locate(type) in source
|
||||
if(imp_e)
|
||||
imp_e.storage.storage_slots += storage.storage_slots
|
||||
imp_e.storage.max_combined_w_class += storage.max_combined_w_class
|
||||
imp_e.storage.contents += storage.contents
|
||||
|
||||
for(var/mob/M in range(1))
|
||||
if(M.s_active == storage)
|
||||
storage.close(M)
|
||||
storage.show_to(source)
|
||||
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/bio_chip/storage/proc/get_contents() //Used for swiftly returning a list of the implant's contents i.e. for checking a theft objective's completion.
|
||||
if(storage && storage.contents)
|
||||
return storage.contents
|
||||
|
||||
/obj/item/bio_chip_implanter/storage
|
||||
name = "bio-chip implanter (storage)"
|
||||
implant_type = /obj/item/bio_chip/storage
|
||||
|
||||
/obj/item/bio_chip_case/storage
|
||||
name = "bio-chip case - 'Storage'"
|
||||
desc = "A glass case containing a storage bio-chip."
|
||||
implant_type = /obj/item/bio_chip/storage
|
||||
@@ -1,34 +0,0 @@
|
||||
/obj/item/bio_chip/supercharge
|
||||
name = "supercharge bio-chip"
|
||||
desc = "Removes all stuns and knockdowns."
|
||||
icon_state = "adrenal"
|
||||
origin_tech = "materials=3;combat=5;syndicate=4"
|
||||
uses = 3
|
||||
implant_data = /datum/implant_fluff/adrenaline
|
||||
implant_state = "implant-syndicate"
|
||||
|
||||
/obj/item/bio_chip/supercharge/activate()
|
||||
uses--
|
||||
to_chat(imp_in, "<span class='notice'>You feel an electric sensation as your components enter overdrive!</span>")
|
||||
imp_in.SetStunned(0)
|
||||
imp_in.SetWeakened(0)
|
||||
imp_in.SetKnockDown(0)
|
||||
imp_in.SetParalysis(0)
|
||||
imp_in.adjustStaminaLoss(-75)
|
||||
imp_in.stand_up(TRUE)
|
||||
SEND_SIGNAL(imp_in, COMSIG_LIVING_CLEAR_STUNS)
|
||||
|
||||
imp_in.reagents.add_reagent("recal", 10)
|
||||
imp_in.reagents.add_reagent("surge_plus", 10)
|
||||
imp_in.reagents.add_reagent("synthetic_omnizine_no_addiction", 10)
|
||||
if(!uses)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/bio_chip_implanter/supercharge
|
||||
name = "bio-chip implanter (supercharge)"
|
||||
implant_type = /obj/item/bio_chip/supercharge
|
||||
|
||||
/obj/item/bio_chip_case/supercharge
|
||||
name = "bio-chip case - 'supercharge'"
|
||||
desc = "A glass case containing a supercharge bio-chip."
|
||||
implant_type = /obj/item/bio_chip/supercharge
|
||||
@@ -1,52 +0,0 @@
|
||||
/obj/item/bio_chip/tracking
|
||||
name = "tracking bio-chip"
|
||||
desc = "Track with this."
|
||||
activated = BIOCHIP_ACTIVATED_PASSIVE
|
||||
origin_tech = "materials=2;magnets=2;programming=2;biotech=2"
|
||||
implant_data = /datum/implant_fluff/tracking
|
||||
implant_state = "implant-nanotrasen"
|
||||
var/warn_cooldown = 0
|
||||
var/obj/item/gps/internal_gps
|
||||
var/gpstag = "TRACK0"
|
||||
var/internal_gps_path = /obj/item/gps/internal/tracking_implant
|
||||
|
||||
/obj/item/bio_chip/tracking/Initialize(mapload)
|
||||
. = ..()
|
||||
GLOB.tracked_implants += src
|
||||
|
||||
/obj/item/bio_chip/tracking/Destroy()
|
||||
QDEL_NULL(internal_gps)
|
||||
GLOB.tracked_implants -= src
|
||||
return ..()
|
||||
|
||||
/obj/item/bio_chip/tracking/implant(mob/target)
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
var/obj/item/organ/internal/cyberimp/chest/bluespace_anchor/anchor = H.get_int_organ(/obj/item/organ/internal/cyberimp/chest/bluespace_anchor)
|
||||
if(anchor)
|
||||
target.visible_message("<span class='danger'>[src] sparks out, disrupted by [anchor] inside [H]!</span>")
|
||||
qdel(src)
|
||||
return FALSE
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
internal_gps = new internal_gps_path(src)
|
||||
if(gpstag)
|
||||
internal_gps.gpstag = gpstag
|
||||
|
||||
/obj/item/bio_chip/tracking/removed(mob/target)
|
||||
. = ..()
|
||||
if(.)
|
||||
QDEL_NULL(internal_gps)
|
||||
|
||||
/obj/item/gps/internal/tracking_implant
|
||||
local = FALSE
|
||||
|
||||
/obj/item/bio_chip_implanter/tracking
|
||||
name = "bio-chip implanter (tracking)"
|
||||
implant_type = /obj/item/bio_chip/tracking
|
||||
|
||||
/obj/item/bio_chip_case/tracking
|
||||
name = "bio-chip case - 'Tracking'"
|
||||
desc = "A glass case containing a tracking bio-chip."
|
||||
implant_type = /obj/item/bio_chip/tracking
|
||||
@@ -1,55 +0,0 @@
|
||||
/obj/item/bio_chip/traitor
|
||||
name = "Mindslave Bio-chip"
|
||||
desc = "Divide and Conquer!"
|
||||
origin_tech = "programming=5;biotech=5;syndicate=8"
|
||||
activated = FALSE
|
||||
implant_data = /datum/implant_fluff/traitor
|
||||
implant_state = "implant-syndicate"
|
||||
|
||||
/// The UID of the mindslave's `mind`. Stored to solve GC race conditions and ensure we can remove their mindslave status even when they're deleted or gibbed.
|
||||
var/mindslave_UID
|
||||
|
||||
/obj/item/bio_chip/traitor/implant(mob/living/carbon/human/mindslave_target, mob/living/carbon/human/user)
|
||||
// Check `activated` here so you can't just keep taking it out and putting it back into other people.
|
||||
if(activated || !istype(mindslave_target) || !istype(user)) // Both the target and the user need to be human.
|
||||
return FALSE
|
||||
|
||||
// If the target is catatonic or doesn't have a mind, return.
|
||||
if(!mindslave_target.mind)
|
||||
to_chat(user, "<span class='warning'><i>This person doesn't have a mind for you to slave!</i></span>")
|
||||
return FALSE
|
||||
|
||||
// Fails if they're already a mindslave of someone, or if they're mindshielded.
|
||||
if(IS_MINDSLAVE(mindslave_target) || ismindshielded(mindslave_target))
|
||||
mindslave_target.visible_message(
|
||||
"<span class='warning'>[mindslave_target] seems to resist the bio-chip!</span>", \
|
||||
"<span class='warning'>You feel a strange sensation in your head that quickly dissipates.</span>")
|
||||
qdel(src)
|
||||
return FALSE
|
||||
|
||||
// Mindslaving yourself.
|
||||
if(mindslave_target == user)
|
||||
to_chat(user, "<span class='notice'>Making yourself loyal to yourself was a great idea! Perhaps even the best idea ever! Actually, you just feel like an idiot.</span>")
|
||||
user.adjustBrainLoss(20)
|
||||
qdel(src)
|
||||
return FALSE
|
||||
|
||||
// Create a new mindslave datum for the target with the user as their master.
|
||||
mindslave_target.mind.add_antag_datum(new /datum/antagonist/mindslave/implant(user.mind))
|
||||
mindslave_UID = mindslave_target.mind.UID()
|
||||
log_admin("[key_name_admin(user)] has mind-slaved [key_name_admin(mindslave_target)].")
|
||||
return ..()
|
||||
|
||||
/obj/item/bio_chip/traitor/removed(mob/target)
|
||||
. = ..()
|
||||
var/datum/mind/M = locateUID(mindslave_UID)
|
||||
M.remove_antag_datum(/datum/antagonist/mindslave/implant)
|
||||
|
||||
/obj/item/bio_chip_implanter/traitor
|
||||
name = "bio-chip implanter (Mindslave)"
|
||||
implant_type = /obj/item/bio_chip/traitor
|
||||
|
||||
/obj/item/bio_chip_case/traitor
|
||||
name = "bio-chip case - 'Mindslave'"
|
||||
desc = "A glass case containing a mindslave bio-chip."
|
||||
implant_type = /obj/item/bio_chip/traitor
|
||||
@@ -1,62 +0,0 @@
|
||||
/obj/item/bio_chip/uplink
|
||||
name = "uplink bio-chip"
|
||||
desc = "Summon things."
|
||||
icon = 'icons/obj/radio.dmi'
|
||||
icon_state = "radio"
|
||||
origin_tech = "materials=4;magnets=4;programming=4;biotech=4;syndicate=5;bluespace=5"
|
||||
implant_data = /datum/implant_fluff/uplink
|
||||
implant_state = "implant-syndicate"
|
||||
|
||||
/obj/item/bio_chip/uplink/Initialize(mapload)
|
||||
. = ..()
|
||||
hidden_uplink = new(src)
|
||||
hidden_uplink.uses = 50
|
||||
|
||||
/obj/item/bio_chip/uplink/nuclear/Initialize(mapload)
|
||||
. = ..()
|
||||
if(hidden_uplink)
|
||||
hidden_uplink.update_uplink_type(UPLINK_TYPE_NUCLEAR)
|
||||
|
||||
/obj/item/bio_chip/uplink/sit/Initialize(mapload)
|
||||
. = ..()
|
||||
if(hidden_uplink)
|
||||
hidden_uplink.update_uplink_type(UPLINK_TYPE_SIT)
|
||||
|
||||
/obj/item/bio_chip/uplink/admin/Initialize(mapload)
|
||||
. = ..()
|
||||
if(hidden_uplink)
|
||||
hidden_uplink.update_uplink_type(UPLINK_TYPE_ADMIN)
|
||||
|
||||
|
||||
/obj/item/bio_chip/uplink/implant(mob/source)
|
||||
var/obj/item/bio_chip/imp_e = locate(type) in source
|
||||
if(imp_e && imp_e != src)
|
||||
imp_e.hidden_uplink.uses += hidden_uplink.uses
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
if(..())
|
||||
hidden_uplink.uplink_owner="[source.key]"
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/bio_chip/uplink/activate()
|
||||
if(hidden_uplink)
|
||||
hidden_uplink.check_trigger(imp_in)
|
||||
|
||||
/obj/item/bio_chip_implanter/uplink
|
||||
name = "bio-chip implanter (uplink)"
|
||||
implant_type = /obj/item/bio_chip/uplink
|
||||
|
||||
/obj/item/bio_chip_case/uplink
|
||||
name = "bio-chip case - 'Syndicate Uplink'"
|
||||
desc = "A glass case containing an uplink bio-chip."
|
||||
implant_type = /obj/item/bio_chip/uplink
|
||||
|
||||
/obj/item/bio_chip_implanter/nuclear
|
||||
name = "bio-chip implanter (Nuclear Agent Uplink)"
|
||||
implant_type = /obj/item/bio_chip/uplink/nuclear
|
||||
|
||||
/obj/item/bio_chip_case/nuclear
|
||||
name = "bio-chip case - 'Nuclear Agent Uplink'"
|
||||
implant_type = /obj/item/bio_chip/uplink/nuclear
|
||||
@@ -1,55 +0,0 @@
|
||||
/obj/item/bio_chip_implanter
|
||||
name = "bio-chip implanter"
|
||||
desc = "A sterile automatic bio-chip injector."
|
||||
icon = 'icons/obj/bio_chips.dmi'
|
||||
icon_state = "implanter0"
|
||||
item_state = "syringe_0"
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
origin_tech = "materials=2;biotech=3"
|
||||
materials = list(MAT_METAL = 600, MAT_GLASS = 200)
|
||||
var/obj/item/bio_chip/imp
|
||||
var/obj/item/bio_chip/implant_type
|
||||
|
||||
/obj/item/bio_chip_implanter/update_icon_state()
|
||||
if(imp)
|
||||
icon_state = "implanter1"
|
||||
origin_tech = imp.origin_tech
|
||||
else
|
||||
icon_state = "implanter0"
|
||||
origin_tech = initial(origin_tech)
|
||||
|
||||
/obj/item/bio_chip_implanter/attack__legacy__attackchain(mob/living/carbon/M, mob/user)
|
||||
if(!iscarbon(M))
|
||||
return
|
||||
if(user && imp)
|
||||
if(M != user)
|
||||
M.visible_message("<span class='warning'>[user] is attempting to bio-chip [M].</span>")
|
||||
|
||||
var/turf/T = get_turf(M)
|
||||
if(T && (M == user || do_after(user, 50 * toolspeed, target = M)))
|
||||
if(user && M && (get_turf(M) == T) && src && imp)
|
||||
if(imp.implant(M, user))
|
||||
if(M == user)
|
||||
to_chat(user, "<span class='notice'>You bio-chip yourself.</span>")
|
||||
else
|
||||
M.visible_message("[user] has implanted [M].", "<span class='notice'>[user] bio-chips you.</span>")
|
||||
imp = null
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
|
||||
/obj/item/bio_chip_implanter/attackby__legacy__attackchain(obj/item/W, mob/user, params)
|
||||
..()
|
||||
if(is_pen(W))
|
||||
rename_interactive(user, W)
|
||||
|
||||
/obj/item/bio_chip_implanter/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!implant_type)
|
||||
return
|
||||
imp = new implant_type()
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
|
||||
/obj/item/bio_chip_implanter/Destroy()
|
||||
QDEL_NULL(imp)
|
||||
. = ..()
|
||||
@@ -1,991 +0,0 @@
|
||||
/* Cards
|
||||
* Contains:
|
||||
* DATA CARD
|
||||
* ID CARD
|
||||
* FINGERPRINT CARD HOLDER
|
||||
* FINGERPRINT CARD
|
||||
*/
|
||||
|
||||
/obj/item/card
|
||||
name = "card"
|
||||
desc = "A card."
|
||||
icon = 'icons/obj/card.dmi'
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
slot_flags = ITEM_SLOT_ID
|
||||
|
||||
new_attack_chain = TRUE
|
||||
var/associated_account_number = 0
|
||||
|
||||
var/list/files = list()
|
||||
|
||||
/obj/item/card/proc/get_card_account()
|
||||
return GLOB.station_money_database.find_user_account(associated_account_number)
|
||||
|
||||
/*
|
||||
* ID CARDS
|
||||
*/
|
||||
|
||||
/obj/item/card/emag_broken
|
||||
desc = "It's a card with a magnetic strip attached to some circuitry. It looks too busted to be used for anything but salvage."
|
||||
name = "broken cryptographic sequencer"
|
||||
icon_state = "emag"
|
||||
item_state = "card-id"
|
||||
origin_tech = "magnets=2;syndicate=2"
|
||||
prefered_slot_flags = ITEM_SLOT_BOTH_POCKETS
|
||||
|
||||
/obj/item/card/emag
|
||||
desc = "It's a card with a magnetic strip attached to some circuitry."
|
||||
name = "cryptographic sequencer"
|
||||
icon_state = "emag"
|
||||
item_state = "card-id"
|
||||
origin_tech = "magnets=2;syndicate=2"
|
||||
flags = NOBLUDGEON
|
||||
flags_2 = NO_MAT_REDEMPTION_2
|
||||
prefered_slot_flags = ITEM_SLOT_BOTH_POCKETS
|
||||
|
||||
/obj/item/card/emag/pre_attack(atom/target, mob/living/user, params)
|
||||
if(..() || ismob(target))
|
||||
return FINISH_ATTACK
|
||||
|
||||
/obj/item/card/emag/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(target.emag_act(user))
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
/obj/item/card/emag/magic_key
|
||||
name = "magic key"
|
||||
desc = "It's a magic key, that will open one door!"
|
||||
icon_state = "magic_key"
|
||||
origin_tech = "magnets=2"
|
||||
|
||||
/obj/item/card/emag/magic_key/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(!isairlock(target))
|
||||
return NONE
|
||||
var/obj/machinery/door/D = target
|
||||
D.locked = FALSE
|
||||
D.update_icon()
|
||||
D.emag_act(user)
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
/obj/item/card/cmag
|
||||
desc = "It's a card coated in a slurry of electromagnetic bananium."
|
||||
name = "jestographic sequencer"
|
||||
icon_state = "cmag"
|
||||
item_state = "card-id"
|
||||
origin_tech = "magnets=2;syndicate=2"
|
||||
flags = NOBLUDGEON
|
||||
flags_2 = NO_MAT_REDEMPTION_2
|
||||
prefered_slot_flags = ITEM_SLOT_BOTH_POCKETS
|
||||
|
||||
/obj/item/card/cmag/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/slippery, src, 16 SECONDS, 100)
|
||||
|
||||
/obj/item/card/cmag/pre_attack(atom/target, mob/living/user, params)
|
||||
if(..() || ismob(target))
|
||||
return FINISH_ATTACK
|
||||
|
||||
/obj/item/card/cmag/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(target.cmag_act(user))
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
/obj/item/card/id
|
||||
name = "identification card"
|
||||
desc = "A card used to provide ID and determine access across the station."
|
||||
icon_state = "id"
|
||||
item_state = "card-id"
|
||||
/// For redeeming at mining equipment lockers
|
||||
var/mining_points = 0
|
||||
/// Total mining points for the Shift.
|
||||
var/total_mining_points = 0
|
||||
var/list/access = list()
|
||||
var/registered_name = "Unknown" // The name registered_name on the card
|
||||
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 100, ACID = 100)
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
var/untrackable // Can not be tracked by AI's
|
||||
|
||||
var/blood_type = "\[UNSET\]"
|
||||
var/dna_hash = "\[UNSET\]"
|
||||
var/fingerprint_hash = "\[UNSET\]"
|
||||
|
||||
//alt titles are handled a bit weirdly in order to unobtrusively integrate into existing ID system
|
||||
var/assignment = null //can be alt title or the actual job
|
||||
var/rank = null //actual job
|
||||
var/owner_uid
|
||||
var/owner_ckey
|
||||
var/lastlog
|
||||
var/dorm = 0 // determines if this ID has claimed a dorm already
|
||||
|
||||
var/sex
|
||||
var/age
|
||||
var/photo
|
||||
var/dat
|
||||
var/stamped = 0
|
||||
|
||||
/// Can we flash the ID?
|
||||
var/can_id_flash = TRUE
|
||||
|
||||
var/obj/item/card/id/guest/guest_pass = null // Guest pass attached to the ID
|
||||
|
||||
/obj/item/card/id/New()
|
||||
..()
|
||||
spawn(30)
|
||||
if(ishuman(loc) && blood_type == "\[UNSET\]")
|
||||
var/mob/living/carbon/human/H = loc
|
||||
SetOwnerInfo(H)
|
||||
|
||||
/obj/item/card/id/examine(mob/user)
|
||||
. = ..()
|
||||
if(in_range(user, src))
|
||||
show(usr)
|
||||
else
|
||||
. += "<span class='warning'>It is too far away.</span>"
|
||||
if(guest_pass)
|
||||
. += "<span class='notice'>There is a guest pass attached to this ID card, <b>Alt-Click</b> to remove it.</span>"
|
||||
if(world.time < guest_pass.expiration_time)
|
||||
. += "<span class='notice'>It expires at [station_time_timestamp("hh:mm:ss", guest_pass.expiration_time)].</span>"
|
||||
else
|
||||
. += "<span class='warning'>It expired at [station_time_timestamp("hh:mm:ss", guest_pass.expiration_time)].</span>"
|
||||
. += "<span class='notice'>It grants access to following areas:</span>"
|
||||
for(var/A in guest_pass.temp_access)
|
||||
. += "<span class='notice'>[get_access_desc(A)].</span>"
|
||||
. += "<span class='notice'>Issuing reason: [guest_pass.reason].</span>"
|
||||
|
||||
/obj/item/card/id/proc/show(mob/user as mob)
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/simple/paper)
|
||||
assets.send(user)
|
||||
|
||||
var/datum/browser/popup = new(user, "idcard", name, 600, 400)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/item/card/id/activate_self(mob/user)
|
||||
if(..())
|
||||
return
|
||||
if(can_id_flash)
|
||||
flash_card(user)
|
||||
|
||||
/obj/item/card/id/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(!isliving(target))
|
||||
return NONE
|
||||
return shared_interact(target, user)
|
||||
|
||||
/obj/item/card/id/ranged_interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(isliving(target) && get_dist(target, user) <= 2)
|
||||
return shared_interact(target, user)
|
||||
return NONE
|
||||
|
||||
/obj/item/card/id/proc/shared_interact(mob/living/victim, mob/living/user)
|
||||
if(victim.has_status_effect(STATUS_EFFECT_OFFERING_EFTPOS))
|
||||
var/obj/item/eftpos/eftpos = victim.is_holding_item_of_type(/obj/item/eftpos)
|
||||
if(!eftpos || !eftpos.can_offer)
|
||||
to_chat(user, "<span class='warning'>They don't seem to have it in hand anymore.</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
victim.remove_status_effect(STATUS_EFFECT_OFFERING_EFTPOS)
|
||||
eftpos.scan_card(src, user)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
return NONE
|
||||
|
||||
/obj/item/card/id/proc/UpdateName()
|
||||
name = "[registered_name]'s ID Card ([assignment])"
|
||||
|
||||
/obj/item/card/id/proc/SetOwnerInfo(mob/living/carbon/human/H)
|
||||
if(!H || !H.dna)
|
||||
return
|
||||
|
||||
sex = capitalize(H.gender)
|
||||
age = H.age
|
||||
blood_type = H.dna.blood_type
|
||||
dna_hash = H.dna.unique_enzymes
|
||||
fingerprint_hash = md5(H.dna.uni_identity)
|
||||
|
||||
RebuildHTML()
|
||||
|
||||
/obj/item/card/id/proc/RebuildHTML()
|
||||
var/photo_front = "'data:image/png;base64,[icon2base64(icon(photo, dir = SOUTH))]'"
|
||||
var/photo_side = "'data:image/png;base64,[icon2base64(icon(photo, dir = WEST))]'"
|
||||
|
||||
dat = {"<table><tr><td>
|
||||
Name: [registered_name]</A><BR>
|
||||
Sex: [sex]</A><BR>
|
||||
Age: [age]</A><BR>
|
||||
Rank: [assignment]</A><BR>
|
||||
Fingerprint: [fingerprint_hash]</A><BR>
|
||||
Blood Type: [blood_type]<BR>
|
||||
DNA Hash: [dna_hash]<BR><BR>
|
||||
<td align = center valign = top>Photo:<br><img src=[photo_front] height=80 width=80 border=4>
|
||||
<img src=[photo_side] height=80 width=80 border=4></td></tr></table>"}
|
||||
|
||||
/obj/item/card/id/GetAccess()
|
||||
if(!guest_pass)
|
||||
return access
|
||||
return access | guest_pass.GetAccess()
|
||||
|
||||
/obj/item/card/id/proc/attach_guest_pass(obj/item/card/id/guest/G, mob/user)
|
||||
if(world.time > G.expiration_time)
|
||||
to_chat(user, "There's no point, the guest pass has expired.")
|
||||
return
|
||||
if(guest_pass)
|
||||
to_chat(user, "There's already a guest pass attached to this ID.")
|
||||
return
|
||||
if(G.registered_name != registered_name && G.registered_name != "NOT SPECIFIED")
|
||||
to_chat(user, "The guest pass cannot be attached to this ID.")
|
||||
return
|
||||
if(!user.transfer_item_to(G, src))
|
||||
return
|
||||
guest_pass = G
|
||||
|
||||
/obj/item/card/id/GetID()
|
||||
return src
|
||||
|
||||
/obj/item/card/id/proc/getRankAndAssignment()
|
||||
var/jobnamedata = ""
|
||||
if(rank)
|
||||
jobnamedata += rank
|
||||
if(rank != assignment)
|
||||
jobnamedata += " (" + assignment + ")"
|
||||
return jobnamedata
|
||||
|
||||
/obj/item/card/id/proc/getPlayer()
|
||||
if(owner_uid)
|
||||
var/mob/living/carbon/human/H = locateUID(owner_uid)
|
||||
if(istype(H) && H.ckey == owner_ckey)
|
||||
return H
|
||||
owner_uid = null
|
||||
if(owner_ckey)
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(M.ckey && M.ckey == owner_ckey)
|
||||
owner_uid = M.UID()
|
||||
return M
|
||||
owner_ckey = null
|
||||
|
||||
/obj/item/card/id/proc/getPlayerCkey()
|
||||
var/mob/living/carbon/human/H = getPlayer()
|
||||
if(istype(H))
|
||||
return H.ckey
|
||||
|
||||
/obj/item/card/id/proc/is_untrackable()
|
||||
return untrackable
|
||||
|
||||
/obj/item/card/id/proc/update_label(newname, newjob)
|
||||
if(newname || newjob)
|
||||
name = "[(!newname) ? "identification card" : "[newname]'s ID Card"][(!newjob) ? "" : " ([newjob])"]"
|
||||
return
|
||||
|
||||
name = "[(!registered_name) ? "identification card" : "[registered_name]'s ID Card"][(!assignment) ? "" : " ([assignment])"]"
|
||||
|
||||
/obj/item/card/id/proc/get_departments()
|
||||
return get_departments_from_job(rank)
|
||||
|
||||
/obj/item/card/id/item_interaction(mob/living/user, obj/item/used, list/modifiers)
|
||||
if(istype(used, /obj/item/id_decal/))
|
||||
var/obj/item/id_decal/decal = used
|
||||
to_chat(user, "You apply [decal] to [src].")
|
||||
if(decal.override_name)
|
||||
name = decal.decal_name
|
||||
desc = decal.decal_desc
|
||||
icon_state = decal.decal_icon_state
|
||||
item_state = decal.decal_item_state
|
||||
qdel(decal)
|
||||
qdel(used)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
else if(istype(used, /obj/item/barcodescanner))
|
||||
var/obj/item/barcodescanner/B = used
|
||||
B.scanID(src, user)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
else if(istype(used, /obj/item/stamp))
|
||||
if(!stamped)
|
||||
dat+="<img src=large_[used.icon_state].png>"
|
||||
stamped = 1
|
||||
to_chat(user, "You stamp the ID card!")
|
||||
playsound(user, 'sound/items/handling/standard_stamp.ogg', 50, vary = TRUE)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
to_chat(user, "This ID has already been stamped!")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
|
||||
else if(istype(used, /obj/item/card/id/guest))
|
||||
attach_guest_pass(used, user)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
else if(istype(used, /obj/item/storage/wallet))
|
||||
used.attackby__legacy__attackchain(src, user)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
/obj/item/card/id/AltClick(mob/user)
|
||||
if(user.stat || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED) || !Adjacent(user))
|
||||
return
|
||||
|
||||
if(guest_pass)
|
||||
to_chat(user, "<span class='notice'>You remove the guest pass from this ID.</span>")
|
||||
guest_pass.forceMove(get_turf(src))
|
||||
guest_pass = null
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There is no guest pass attached to this ID.</span>")
|
||||
|
||||
/obj/item/card/id/serialize()
|
||||
var/list/data = ..()
|
||||
|
||||
data["sex"] = sex
|
||||
data["age"] = age
|
||||
data["btype"] = blood_type
|
||||
data["dna_hash"] = dna_hash
|
||||
data["fprint_hash"] = fingerprint_hash
|
||||
data["access"] = access
|
||||
data["assignment"] = assignment
|
||||
data["rank"] = rank
|
||||
data["account"] = associated_account_number
|
||||
data["owner"] = registered_name
|
||||
data["mining"] = mining_points
|
||||
data["total_mining"] = total_mining_points
|
||||
return data
|
||||
|
||||
/obj/item/card/id/deserialize(list/data)
|
||||
sex = data["sex"]
|
||||
age = data["age"]
|
||||
blood_type = data["btype"]
|
||||
dna_hash = data["dna_hash"]
|
||||
fingerprint_hash = data["fprint_hash"]
|
||||
access = data["access"] // No need for a copy, the list isn't getting touched
|
||||
assignment = data["job"] // backup for old jsons
|
||||
assignment = data["assignment"]
|
||||
rank = data["rank"]
|
||||
associated_account_number = data["account"]
|
||||
registered_name = data["owner"]
|
||||
mining_points = data["mining"]
|
||||
total_mining_points = data["total_mining"]
|
||||
// We'd need to use icon serialization(b64) to save the photo, and I don't feel like i
|
||||
UpdateName()
|
||||
RebuildHTML()
|
||||
..()
|
||||
|
||||
/obj/item/card/id/proc/flash_card(mob/user)
|
||||
user.visible_message("[user] shows you: [bicon(src)] [name]. The assignment on the card: [assignment]",\
|
||||
"You flash your ID card: [bicon(src)] [name]. The assignment on the card: [assignment]")
|
||||
if(mining_points)
|
||||
to_chat(user, "There's <b>[mining_points] Mining Points</b> loaded onto this card. This card has earned <b>[total_mining_points] Mining Points</b> this Shift!")
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/item/card/id/silver
|
||||
desc = "A silver card which shows honour and dedication."
|
||||
icon_state = "silver"
|
||||
item_state = "silver_id"
|
||||
|
||||
/obj/item/card/id/gold
|
||||
desc = "A golden card which shows power and might."
|
||||
icon_state = "gold"
|
||||
item_state = "gold_id"
|
||||
|
||||
/obj/item/card/id/captains_spare
|
||||
name = "captain's spare ID"
|
||||
desc = "The spare ID of the captain. Keep this secured."
|
||||
icon_state = "gold"
|
||||
item_state = "gold_id"
|
||||
registered_name = "Captain"
|
||||
assignment = "Captain"
|
||||
|
||||
/obj/item/card/id/captains_spare/New()
|
||||
access = get_all_accesses()
|
||||
..()
|
||||
|
||||
/obj/item/card/id/admin
|
||||
name = "admin ID card"
|
||||
icon_state = "admin"
|
||||
item_state = "gold_id"
|
||||
registered_name = "Admin"
|
||||
assignment = "Testing Shit"
|
||||
untrackable = TRUE
|
||||
|
||||
/obj/item/card/id/admin/New()
|
||||
access = get_absolutely_all_accesses()
|
||||
..()
|
||||
|
||||
/obj/item/card/id/centcom
|
||||
name = "central command ID card"
|
||||
desc = "An ID straight from Central Command."
|
||||
icon_state = "centcom"
|
||||
registered_name = "Central Command"
|
||||
assignment = "General"
|
||||
|
||||
/obj/item/card/id/centcom/New()
|
||||
access = get_all_centcom_access()
|
||||
..()
|
||||
|
||||
|
||||
/obj/item/card/id/prisoner
|
||||
name = "prisoner ID card"
|
||||
desc = "You are a number, you are not a free man."
|
||||
icon_state = "prisoner"
|
||||
item_state = "orange-id"
|
||||
assignment = "Prisoner"
|
||||
registered_name = "Scum"
|
||||
access = list(ACCESS_LIBRARY)
|
||||
/// How many mining points you need to be released from the labour camp.
|
||||
var/goal = 0
|
||||
|
||||
/obj/item/card/id/prisoner/examine(mob/user)
|
||||
. = ..()
|
||||
if(goal)
|
||||
. += "\nYou have accumulated [mining_points] out of the [goal] points assigned to gain freedom."
|
||||
|
||||
/obj/item/card/id/prisoner/one
|
||||
name = "Prisoner #13-001"
|
||||
icon_state = "prisonerone"
|
||||
registered_name = "Prisoner #13-001"
|
||||
|
||||
/obj/item/card/id/prisoner/two
|
||||
name = "Prisoner #13-002"
|
||||
icon_state = "prisonertwo"
|
||||
registered_name = "Prisoner #13-002"
|
||||
|
||||
/obj/item/card/id/prisoner/three
|
||||
name = "Prisoner #13-003"
|
||||
icon_state = "prisonerthree"
|
||||
registered_name = "Prisoner #13-003"
|
||||
|
||||
/obj/item/card/id/prisoner/four
|
||||
name = "Prisoner #13-004"
|
||||
icon_state = "prisonerfour"
|
||||
registered_name = "Prisoner #13-004"
|
||||
|
||||
/obj/item/card/id/prisoner/five
|
||||
name = "Prisoner #13-005"
|
||||
icon_state = "prisonerfive"
|
||||
registered_name = "Prisoner #13-005"
|
||||
|
||||
/obj/item/card/id/prisoner/six
|
||||
name = "Prisoner #13-006"
|
||||
icon_state = "prisonersix"
|
||||
registered_name = "Prisoner #13-006"
|
||||
|
||||
/obj/item/card/id/prisoner/seven
|
||||
name = "Prisoner #13-007"
|
||||
icon_state = "prisonerseven"
|
||||
registered_name = "Prisoner #13-007"
|
||||
|
||||
/obj/item/card/id/prisoner/random
|
||||
/obj/item/card/id/prisoner/random/New()
|
||||
..()
|
||||
var/random_number = "#[rand(0, 99)]-[rand(0, 999)]"
|
||||
name = "Prisoner [random_number]"
|
||||
registered_name = name
|
||||
|
||||
/obj/item/card/id/medical
|
||||
name = "Medical ID"
|
||||
registered_name = "Medic"
|
||||
icon_state = "medical"
|
||||
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
/obj/item/card/id/coroner
|
||||
name = "Coroner ID"
|
||||
registered_name = "Coroner"
|
||||
icon_state = "coroner"
|
||||
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
/obj/item/card/id/virologist
|
||||
name = "Virologist ID"
|
||||
registered_name = "Virologist"
|
||||
icon_state = "virologist"
|
||||
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS)
|
||||
|
||||
/obj/item/card/id/chemist
|
||||
name = "Chemist ID"
|
||||
registered_name = "Chemist"
|
||||
icon_state = "chemist"
|
||||
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
/obj/item/card/id/paramedic
|
||||
name = "Paramedic ID"
|
||||
registered_name = "Paramedic"
|
||||
icon_state = "paramedic"
|
||||
access = list(ACCESS_PARAMEDIC, ACCESS_MEDICAL, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_MORGUE)
|
||||
|
||||
/obj/item/card/id/psychiatrist
|
||||
name = "Psychiatrist ID"
|
||||
registered_name = "Psychiatrist"
|
||||
icon_state = "psychiatrist"
|
||||
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_PSYCHIATRIST)
|
||||
|
||||
/obj/item/card/id/security
|
||||
name = "Security ID"
|
||||
registered_name = "Officer"
|
||||
icon_state = "security"
|
||||
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_EVIDENCE, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_WEAPONS)
|
||||
|
||||
/obj/item/card/id/detective
|
||||
name = "Detective ID"
|
||||
registered_name = "Detective"
|
||||
icon_state = "detective"
|
||||
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_EVIDENCE, ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_COURT, ACCESS_WEAPONS)
|
||||
|
||||
/obj/item/card/id/warden
|
||||
name = "Warden ID"
|
||||
registered_name = "Warden"
|
||||
icon_state = "warden"
|
||||
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_EVIDENCE, ACCESS_ARMORY, ACCESS_COURT, ACCESS_MAINT_TUNNELS, ACCESS_MORGUE, ACCESS_WEAPONS)
|
||||
|
||||
/obj/item/card/id/internalaffairsagent
|
||||
name = "Internal Affairs Agent ID"
|
||||
registered_name = "Internal Affairs Agent"
|
||||
icon_state = "internalaffairsagent"
|
||||
access = list(ACCESS_INTERNAL_AFFAIRS, ACCESS_COURT, ACCESS_SEC_DOORS, ACCESS_MAINT_TUNNELS, ACCESS_RESEARCH, ACCESS_MEDICAL, ACCESS_CONSTRUCTION, ACCESS_MAILSORTING)
|
||||
|
||||
/obj/item/card/id/geneticist
|
||||
name = "Geneticist ID"
|
||||
registered_name = "Geneticist"
|
||||
icon_state = "geneticist"
|
||||
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_GENETICS, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
/obj/item/card/id/research
|
||||
name = "Research ID"
|
||||
registered_name = "Scientist"
|
||||
icon_state = "research"
|
||||
access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
/obj/item/card/id/xenobiology
|
||||
name = "Xenobiology ID"
|
||||
registered_name = "Xenobiologist"
|
||||
icon_state = "xenobiologist"
|
||||
access = list(ACCESS_MAINT_TUNNELS, ACCESS_MINERAL_STOREROOM, ACCESS_RESEARCH, ACCESS_XENOBIOLOGY, ACCESS_EVA, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_TELEPORTER)
|
||||
|
||||
/obj/item/card/id/roboticist
|
||||
name = "Roboticist ID"
|
||||
registered_name = "Roboticist"
|
||||
icon_state = "roboticist"
|
||||
access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
/obj/item/card/id/supply
|
||||
name = "Supply ID"
|
||||
registered_name = "Cargonian"
|
||||
icon_state = "cargo"
|
||||
access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_QM, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
/obj/item/card/id/smith
|
||||
name = "Smith ID"
|
||||
registered_name = "Smith"
|
||||
icon_state = "smith"
|
||||
access = list(ACCESS_CARGO_BAY, ACCESS_CARGO, ACCESS_MAINT_TUNNELS, ACCESS_MINERAL_STOREROOM, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_SMITH)
|
||||
|
||||
/obj/item/card/id/quartermaster
|
||||
name = "Quartermaster ID"
|
||||
registered_name = "Quartermaster"
|
||||
icon_state = "quartermaster"
|
||||
access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_QM, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM, ACCESS_SMITH)
|
||||
|
||||
/obj/item/card/id/shaftminer
|
||||
name = "Shaftminer ID"
|
||||
registered_name = "Shaftminer"
|
||||
icon_state = "shaftminer"
|
||||
access = list(ACCESS_MAINT_TUNNELS, ACCESS_MAILSORTING, ACCESS_CARGO, ACCESS_QM, ACCESS_MINING, ACCESS_MINING_STATION, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
/obj/item/card/id/engineering
|
||||
name = "Engineering ID"
|
||||
registered_name = "Engineer"
|
||||
icon_state = "engineering"
|
||||
access = list(ACCESS_EVA, ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS)
|
||||
|
||||
/obj/item/card/id/atmostech
|
||||
name = "Life Support Specialist ID"
|
||||
registered_name = "Life Support Specialist"
|
||||
icon_state = "atmostech"
|
||||
access = list(ACCESS_EVA, ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS)
|
||||
|
||||
/obj/item/card/id/captains_spare/assigned
|
||||
name = "Captain ID"
|
||||
icon_state = "captain"
|
||||
|
||||
/obj/item/card/id/hop
|
||||
name = "Head of Personal ID"
|
||||
registered_name = "HoP"
|
||||
icon_state = "HoP"
|
||||
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_FORENSICS_LOCKERS,
|
||||
ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_AI_UPLOAD, ACCESS_EVA, ACCESS_HEADS,
|
||||
ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_MAINT_TUNNELS, ACCESS_BAR, ACCESS_JANITOR, ACCESS_CONSTRUCTION, ACCESS_MORGUE,
|
||||
ACCESS_CREMATORIUM, ACCESS_KITCHEN, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MAILSORTING, ACCESS_QM, ACCESS_HYDROPONICS, ACCESS_INTERNAL_AFFAIRS,
|
||||
ACCESS_THEATRE, ACCESS_CHAPEL_OFFICE, ACCESS_LIBRARY, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_HEADS_VAULT, ACCESS_MINING_STATION,
|
||||
ACCESS_CLOWN, ACCESS_MIME, ACCESS_HOP, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_EXPEDITION, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
/obj/item/card/id/hos
|
||||
name = "Head of Security ID"
|
||||
registered_name = "HoS"
|
||||
icon_state = "HoS"
|
||||
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_EVIDENCE, ACCESS_ARMORY, ACCESS_COURT,
|
||||
ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_ALL_PERSONAL_LOCKERS,
|
||||
ACCESS_RESEARCH, ACCESS_ENGINE, ACCESS_MINING, ACCESS_MEDICAL, ACCESS_CONSTRUCTION, ACCESS_MAILSORTING,
|
||||
ACCESS_HEADS, ACCESS_HOS, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_EXPEDITION, ACCESS_WEAPONS)
|
||||
|
||||
/obj/item/card/id/cmo
|
||||
name = "Chief Medical Officer ID"
|
||||
registered_name = "CMO"
|
||||
icon_state = "CMO"
|
||||
access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_GENETICS, ACCESS_HEADS,
|
||||
ACCESS_CHEMISTRY, ACCESS_VIROLOGY, ACCESS_CMO, ACCESS_SURGERY, ACCESS_RC_ANNOUNCE,
|
||||
ACCESS_KEYCARD_AUTH, ACCESS_SEC_DOORS, ACCESS_PSYCHIATRIST, ACCESS_PARAMEDIC, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
/obj/item/card/id/rd
|
||||
name = "Research Director ID"
|
||||
registered_name = "RD"
|
||||
icon_state = "RD"
|
||||
access = list(ACCESS_RD, ACCESS_HEADS, ACCESS_TOX, ACCESS_GENETICS, ACCESS_MORGUE,
|
||||
ACCESS_TOX_STORAGE, ACCESS_TECH_STORAGE, ACCESS_TELEPORTER, ACCESS_SEC_DOORS,
|
||||
ACCESS_RESEARCH, ACCESS_ROBOTICS, ACCESS_XENOBIOLOGY, ACCESS_AI_UPLOAD,
|
||||
ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_TCOMSAT, ACCESS_EXPEDITION, ACCESS_MINISAT, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
/obj/item/card/id/ce
|
||||
name = "Chief Engineer ID"
|
||||
registered_name = "CE"
|
||||
icon_state = "CE"
|
||||
access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS,
|
||||
ACCESS_TELEPORTER, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_ATMOSPHERICS, ACCESS_EVA,
|
||||
ACCESS_HEADS, ACCESS_CONSTRUCTION, ACCESS_SEC_DOORS,
|
||||
ACCESS_CE, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_TCOMSAT, ACCESS_MINISAT, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
/obj/item/card/id/ntrep
|
||||
name = "Nanotrasen Representative ID"
|
||||
registered_name = "NTRep"
|
||||
icon_state = "ntrep"
|
||||
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_FORENSICS_LOCKERS,
|
||||
ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_CHANGE_IDS, ACCESS_EVA, ACCESS_HEADS,
|
||||
ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_MAINT_TUNNELS, ACCESS_BAR, ACCESS_JANITOR, ACCESS_CONSTRUCTION, ACCESS_MORGUE,
|
||||
ACCESS_CREMATORIUM, ACCESS_KITCHEN, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MAILSORTING, ACCESS_QM, ACCESS_HYDROPONICS, ACCESS_INTERNAL_AFFAIRS,
|
||||
ACCESS_THEATRE, ACCESS_CHAPEL_OFFICE, ACCESS_LIBRARY, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_HEADS_VAULT, ACCESS_MINING_STATION,
|
||||
ACCESS_CLOWN, ACCESS_MIME, ACCESS_HOP, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_EXPEDITION, ACCESS_WEAPONS, ACCESS_NTREP)
|
||||
|
||||
/obj/item/card/id/nct
|
||||
name = "\improper Nanotrasen Career Trainer ID"
|
||||
registered_name = "Nanotrasen Career Trainer"
|
||||
icon_state = "nctrainer"
|
||||
access = list(ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_CARGO, ACCESS_CONSTRUCTION, ACCESS_COURT, ACCESS_EVA, ACCESS_TRAINER, ACCESS_MAINT_TUNNELS,
|
||||
ACCESS_MEDICAL, ACCESS_RESEARCH, ACCESS_SEC_DOORS, ACCESS_THEATRE, ACCESS_INTERNAL_AFFAIRS)
|
||||
|
||||
/obj/item/card/id/blueshield
|
||||
name = "Blueshield ID"
|
||||
registered_name = "Blueshield"
|
||||
icon_state = "blueshield"
|
||||
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_FORENSICS_LOCKERS,
|
||||
ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_EVIDENCE, ACCESS_CHANGE_IDS, ACCESS_EVA, ACCESS_HEADS,
|
||||
ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_MAINT_TUNNELS, ACCESS_BAR, ACCESS_JANITOR, ACCESS_CONSTRUCTION, ACCESS_MORGUE,
|
||||
ACCESS_CREMATORIUM, ACCESS_KITCHEN, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MAILSORTING, ACCESS_QM, ACCESS_HYDROPONICS, ACCESS_INTERNAL_AFFAIRS,
|
||||
ACCESS_THEATRE, ACCESS_CHAPEL_OFFICE, ACCESS_LIBRARY, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_HEADS_VAULT, ACCESS_MINING_STATION,
|
||||
ACCESS_CLOWN, ACCESS_MIME, ACCESS_HOP, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_EXPEDITION, ACCESS_WEAPONS, ACCESS_BLUESHIELD)
|
||||
|
||||
/obj/item/card/id/magistrate
|
||||
name = "Magistrate ID"
|
||||
registered_name = "Magistrate"
|
||||
icon_state = "magistrate"
|
||||
access = list(ACCESS_SECURITY, ACCESS_SEC_DOORS, ACCESS_BRIG, ACCESS_COURT, ACCESS_FORENSICS_LOCKERS,
|
||||
ACCESS_MEDICAL, ACCESS_ENGINE, ACCESS_EVIDENCE, ACCESS_CHANGE_IDS, ACCESS_EVA, ACCESS_HEADS,
|
||||
ACCESS_ALL_PERSONAL_LOCKERS, ACCESS_MAINT_TUNNELS, ACCESS_BAR, ACCESS_JANITOR, ACCESS_CONSTRUCTION, ACCESS_MORGUE,
|
||||
ACCESS_CREMATORIUM, ACCESS_KITCHEN, ACCESS_CARGO, ACCESS_CARGO_BOT, ACCESS_MAILSORTING, ACCESS_QM, ACCESS_HYDROPONICS, ACCESS_INTERNAL_AFFAIRS,
|
||||
ACCESS_THEATRE, ACCESS_CHAPEL_OFFICE, ACCESS_LIBRARY, ACCESS_RESEARCH, ACCESS_MINING, ACCESS_HEADS_VAULT, ACCESS_MINING_STATION,
|
||||
ACCESS_CLOWN, ACCESS_MIME, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_EXPEDITION, ACCESS_MAGISTRATE)
|
||||
|
||||
/obj/item/card/id/assistant
|
||||
name = "Assistant ID"
|
||||
registered_name = "Assistant"
|
||||
icon_state = "assistant"
|
||||
access = list(ACCESS_MAINT_TUNNELS)
|
||||
|
||||
/obj/item/card/id/clown
|
||||
name = "Pink ID"
|
||||
registered_name = "HONK!"
|
||||
icon_state = "clown"
|
||||
desc = "Even looking at the card strikes you with deep fear."
|
||||
access = list(ACCESS_CLOWN, ACCESS_THEATRE, ACCESS_MAINT_TUNNELS)
|
||||
|
||||
/obj/item/card/id/mime
|
||||
name = "Black and White ID"
|
||||
registered_name = "..."
|
||||
icon_state = "mime"
|
||||
desc = "..."
|
||||
access = list(ACCESS_MIME, ACCESS_THEATRE, ACCESS_MAINT_TUNNELS)
|
||||
|
||||
/obj/item/card/id/botanist
|
||||
name = "Botanist ID"
|
||||
registered_name = "Botanist"
|
||||
icon_state = "botanist"
|
||||
access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE)
|
||||
|
||||
/obj/item/card/id/librarian
|
||||
name = "Librarian ID"
|
||||
registered_name = "Librarian"
|
||||
icon_state = "librarian"
|
||||
access = list(ACCESS_LIBRARY, ACCESS_MAINT_TUNNELS)
|
||||
|
||||
/obj/item/card/id/chaplain
|
||||
name = "Chaplain ID"
|
||||
registered_name = "Chaplain"
|
||||
icon_state = "chaplain"
|
||||
access = list(ACCESS_MORGUE, ACCESS_CHAPEL_OFFICE, ACCESS_CREMATORIUM, ACCESS_MAINT_TUNNELS)
|
||||
|
||||
/obj/item/card/id/bartender
|
||||
name = "Bartender ID"
|
||||
registered_name = "Bartender"
|
||||
icon_state = "bartender"
|
||||
access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
/obj/item/card/id/chef
|
||||
name = "Chef ID"
|
||||
registered_name = "Chef"
|
||||
icon_state = "chef"
|
||||
access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE)
|
||||
|
||||
/obj/item/card/id/janitor
|
||||
name = "Janitor ID"
|
||||
registered_name = "Janitor"
|
||||
icon_state = "janitor"
|
||||
access = list(ACCESS_HYDROPONICS, ACCESS_BAR, ACCESS_KITCHEN, ACCESS_MORGUE)
|
||||
|
||||
/obj/item/card/id/explorer
|
||||
name = "Explorer ID"
|
||||
registered_name = "Explorer"
|
||||
icon_state = "explorer"
|
||||
|
||||
/obj/item/card/id/rainbow
|
||||
name = "Rainbow ID"
|
||||
icon_state = "rainbow"
|
||||
|
||||
/obj/item/card/id/thunderdome/red
|
||||
name = "Thunderdome Red ID"
|
||||
registered_name = "Red Team Fighter"
|
||||
assignment = "Red Team Fighter"
|
||||
icon_state = "TDred"
|
||||
desc = "This ID card is given to those who fought inside the thunderdome for the Red Team. Not many have lived to see one of those, even fewer lived to keep it."
|
||||
|
||||
/obj/item/card/id/thunderdome/green
|
||||
name = "Thunderdome Green ID"
|
||||
registered_name = "Green Team Fighter"
|
||||
assignment = "Green Team Fighter"
|
||||
icon_state = "TDgreen"
|
||||
desc = "This ID card is given to those who fought inside the thunderdome for the Green Team. Not many have lived to see one of those, even fewer lived to keep it."
|
||||
|
||||
/obj/item/card/id/lifetime
|
||||
name = "Lifetime ID Card"
|
||||
desc = "A modified ID card given only to those people who have devoted their lives to the better interests of Nanotrasen. It sparkles blue."
|
||||
icon_state = "lifetimeid"
|
||||
|
||||
/obj/item/card/id/ert
|
||||
name = "ERT ID"
|
||||
icon_state = "ERT_empty"
|
||||
|
||||
/obj/item/card/id/ert/commander
|
||||
icon_state = "ERT_leader"
|
||||
|
||||
/obj/item/card/id/ert/security
|
||||
icon_state = "ERT_security"
|
||||
|
||||
/obj/item/card/id/ert/engineering
|
||||
icon_state = "ERT_engineering"
|
||||
|
||||
/obj/item/card/id/ert/medic
|
||||
icon_state = "ERT_medical"
|
||||
|
||||
/obj/item/card/id/ert/paranormal
|
||||
icon_state = "ERT_paranormal"
|
||||
|
||||
/obj/item/card/id/ert/janitorial
|
||||
icon_state = "ERT_janitorial"
|
||||
|
||||
/obj/item/card/id/ert/deathsquad
|
||||
icon_state = "deathsquad"
|
||||
|
||||
/obj/item/card/id/golem
|
||||
name = "Free Golem ID"
|
||||
desc = "A card used to claim mining points and buy gear. Use it to mark it as yours."
|
||||
icon_state = "research"
|
||||
access = list(ACCESS_FREE_GOLEMS, ACCESS_ROBOTICS, ACCESS_CLOWN, ACCESS_MIME, ACCESS_XENOBIOLOGY, ACCESS_SMITH) //access to robots/mechs
|
||||
can_id_flash = FALSE //So you do not flash it the first time you use it.
|
||||
var/registered = FALSE
|
||||
|
||||
/obj/item/card/id/golem/activate_self(mob/user)
|
||||
if(..())
|
||||
return
|
||||
if(!registered && ishuman(user))
|
||||
registered_name = user.real_name
|
||||
SetOwnerInfo(user)
|
||||
assignment = "Free Golem"
|
||||
RebuildHTML()
|
||||
UpdateName()
|
||||
desc = "A card used to claim mining points and buy gear."
|
||||
registered = TRUE
|
||||
can_id_flash = TRUE
|
||||
to_chat(user, "<span class='notice'>The ID is now registered as yours.</span>")
|
||||
|
||||
/obj/item/card/id/data
|
||||
icon_state = "data"
|
||||
|
||||
/obj/item/card/id/nct_data_chip
|
||||
name = "\improper NCT Trainee Access Chip"
|
||||
desc = "A small electronic access token that allows its user to copy the access of their Trainee. Only accessible by NT Career Trainers!"
|
||||
icon_state = "nct_chip"
|
||||
assignment = "Nanotrasen Career Trainer"
|
||||
var/registered_user = null
|
||||
var/trainee = null
|
||||
|
||||
/obj/item/card/id/nct_data_chip/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<br>The current registered Trainee is: <b>[trainee]</b>"
|
||||
. += "<span class='notice'>Use in hand to reset the assigned trainee and access.</span>"
|
||||
. += "<span class='purple'>The datachip is unable to copy any access that has been deemed high-risk by Nanotrasen Officials. That includes some, if not most, head related access permissions.</span>"
|
||||
|
||||
/obj/item/card/id/nct_data_chip/activate_self(mob/user)
|
||||
if(..())
|
||||
return
|
||||
if(!trainee)
|
||||
return
|
||||
|
||||
var/response = tgui_alert(user, "Would you like to remove [trainee] as your current active Trainee?", "Choose", list("Yes", "No"))
|
||||
if(response == "Yes")
|
||||
trainee = null
|
||||
icon_state = "nct_chip"
|
||||
access = list()
|
||||
|
||||
/obj/item/card/id/nct_data_chip/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(!istype(target, /obj/item/card/id))
|
||||
return
|
||||
if(!(isliving(user) && user.mind))
|
||||
return
|
||||
|
||||
if(user.mind.current != registered_user)
|
||||
to_chat(user, "<span class='notice'>You do not have access to use this NCT Trainee Access Chip!</span>")
|
||||
return
|
||||
|
||||
if(istype(target, /obj/item/card/id/ert))
|
||||
to_chat(user, "<span class='warning'>The chip's screen blinks red as you attempt scanning this ID.</span>")
|
||||
return
|
||||
|
||||
var/obj/item/card/id/I = target
|
||||
to_chat(user, "<span class='notice'>The chip's microscanners activate as you scan [I.registered_name]'s ID, copying its access.</span>")
|
||||
access = I.access.Copy()
|
||||
access.Remove(ACCESS_AI_UPLOAD, ACCESS_ARMORY, ACCESS_CAPTAIN, ACCESS_CE, ACCESS_RD, ACCESS_HOP, ACCESS_QM, ACCESS_CMO, ACCESS_HOS, ACCESS_NTREP,
|
||||
ACCESS_MAGISTRATE, ACCESS_BLUESHIELD, ACCESS_HEADS_VAULT, ACCESS_KEYCARD_AUTH, ACCESS_RC_ANNOUNCE,
|
||||
ACCESS_CHANGE_IDS, ACCESS_MINISAT)
|
||||
trainee = I.registered_name
|
||||
icon_state = "nct_chip_active"
|
||||
|
||||
/obj/item/card/id/syndicate_fake // Syndicate ID drip with none of the access theft or anti-tracking.
|
||||
name = "\improper Syndicate ID card"
|
||||
desc = "An evil-looking ID issued to members of the Syndicate."
|
||||
icon_state = "syndie"
|
||||
|
||||
// Decals
|
||||
/obj/item/id_decal
|
||||
name = "identification card decal"
|
||||
desc = "A nano-cellophane wrap that molds to an ID card to make it look snazzy."
|
||||
icon = 'icons/obj/toy.dmi'
|
||||
icon_state = "id_decal"
|
||||
var/decal_name = "identification card"
|
||||
var/decal_desc = "A card used to provide ID and determine access across the station."
|
||||
var/decal_icon_state = "id"
|
||||
var/decal_item_state = "card-id"
|
||||
var/override_name = 0
|
||||
|
||||
/obj/item/id_decal/gold
|
||||
name = "gold ID card decal"
|
||||
icon_state = "id_decal_gold"
|
||||
desc = "Make your ID look like the Captain's or a self-centered HOP's. Applies to any ID."
|
||||
decal_desc = "A golden card which shows power and might."
|
||||
decal_icon_state = "gold"
|
||||
decal_item_state = "gold_id"
|
||||
|
||||
/obj/item/id_decal/silver
|
||||
name = "silver ID card decal"
|
||||
icon_state = "id_decal_silver"
|
||||
desc = "Make your ID look like HOP's because they wouldn't change it officially. Applies to any ID."
|
||||
decal_desc = "A silver card which shows honour and dedication."
|
||||
decal_icon_state = "silver"
|
||||
decal_item_state = "silver_id"
|
||||
|
||||
/obj/item/id_decal/prisoner
|
||||
name = "prisoner ID card decal"
|
||||
icon_state = "id_decal_prisoner"
|
||||
desc = "All the cool kids have an ID that's this color. Applies to any ID."
|
||||
decal_desc = "You are a number, you are not a free man."
|
||||
decal_icon_state = "prisoner"
|
||||
decal_item_state = "orange-id"
|
||||
|
||||
/obj/item/id_decal/centcom
|
||||
name = "centcom ID card decal"
|
||||
icon_state = "id_decal_centcom"
|
||||
desc = "All the prestige without the responsibility or the access. Applies to any ID."
|
||||
decal_desc = "An ID straight from Cent. Com."
|
||||
decal_icon_state = "centcom"
|
||||
|
||||
/obj/item/id_decal/emag
|
||||
name = "cryptographic sequencer ID card decal"
|
||||
icon_state = "id_decal_emag"
|
||||
desc = "A bundle of wires that you can tape to your ID to look very suspect. Applies to any ID."
|
||||
decal_name = "cryptographic sequencer"
|
||||
decal_desc = "It's a card with a magnetic strip attached to some circuitry."
|
||||
decal_icon_state = "emag"
|
||||
override_name = 1
|
||||
|
||||
/proc/get_station_card_skins()
|
||||
return list("data", "id", "gold", "silver", "security", "detective", "warden", "internalaffairsagent", "medical", "coroner", "chemist", "virologist", "paramedic", "psychiatrist", "geneticist", "research", "roboticist", "quartermaster", "cargo", "shaftminer", "engineering", "atmostech", "captain", "HoP", "HoS", "CMO", "RD", "CE", "assistant", "clown", "mime", "botanist", "librarian", "chaplain", "bartender", "chef", "janitor", "rainbow", "prisoner", "explorer", "nct")
|
||||
|
||||
/proc/get_centcom_card_skins()
|
||||
return list("centcom", "blueshield", "magistrate", "ntrep", "ERT_leader", "ERT_empty", "ERT_security", "ERT_engineering", "ERT_medical", "ERT_janitorial", "ERT_paranormal", "deathsquad", "commander", "syndie", "TDred", "TDgreen")
|
||||
|
||||
/proc/get_all_card_skins()
|
||||
return get_station_card_skins() + get_centcom_card_skins()
|
||||
|
||||
/proc/get_skin_desc(skin)
|
||||
switch(skin)
|
||||
if("id")
|
||||
return "Blank"
|
||||
if("cargo")
|
||||
return "Cargo Technician"
|
||||
if("shaftminer")
|
||||
return "Shaft Miner"
|
||||
if("medical")
|
||||
return "Medical Doctor"
|
||||
if("engineering")
|
||||
return "Station Engineer"
|
||||
if("security")
|
||||
return "Security Officer"
|
||||
if("internalaffairsagent")
|
||||
return "Internal Affairs Agent"
|
||||
if("nct")
|
||||
return "Nanotrasen Career Trainer"
|
||||
if("atmostech")
|
||||
return "Life Support Specialist"
|
||||
if("HoP")
|
||||
return "Head of Personal"
|
||||
if("HoS")
|
||||
return "Head of Security"
|
||||
if("CMO")
|
||||
return "Chief Medical Officer"
|
||||
if("RD")
|
||||
return "Research Director"
|
||||
if("CE")
|
||||
return "Chief Engineer"
|
||||
if("ERT_leader")
|
||||
return "ERT Leader"
|
||||
if("ERT_empty")
|
||||
return "ERT Default"
|
||||
if("ERT_security")
|
||||
return "ERT Security"
|
||||
if("ERT_engineering")
|
||||
return "ERT Engineering"
|
||||
if("ERT_medical")
|
||||
return "ERT Medical"
|
||||
if("ERT_janitorial")
|
||||
return "ERT Janitorial"
|
||||
if("ERT_paranormal")
|
||||
return "ERT Paranormal"
|
||||
if("deathsquad")
|
||||
return "Deathsquad"
|
||||
if("syndie")
|
||||
return "Syndicate"
|
||||
if("TDred")
|
||||
return "Thunderdome Red"
|
||||
if("TDgreen")
|
||||
return "Thunderdome Green"
|
||||
else
|
||||
return capitalize(skin)
|
||||
|
||||
/proc/GetNameAndAssignmentFromId(obj/item/card/id/I)
|
||||
// Format currently matches that of newscaster feeds: Registered Name (Assigned Rank)
|
||||
return I.assignment ? "[I.registered_name] ([I.assignment])" : I.registered_name
|
||||
@@ -1,83 +0,0 @@
|
||||
/obj/item/stack/spacecash
|
||||
name = "1 Credit"
|
||||
desc = "Money money money."
|
||||
icon = 'icons/obj/money.dmi'
|
||||
icon_state = "cash"
|
||||
hitsound = "swing_hit"
|
||||
throw_speed = 1
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
resistance_flags = FLAMMABLE
|
||||
singular_name = "credit"
|
||||
max_amount = MAX_STACKABLE_CASH
|
||||
merge_type = /obj/item/stack/spacecash
|
||||
|
||||
/obj/item/stack/spacecash/Initialize(mapload)
|
||||
. = ..()
|
||||
SSeconomy.space_credits_created += amount
|
||||
SSeconomy.total_space_cash += amount
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
|
||||
/obj/item/stack/spacecash/Destroy()
|
||||
SSeconomy.total_space_cash -= amount
|
||||
SSeconomy.space_credits_destroyed += amount
|
||||
return ..()
|
||||
|
||||
/obj/item/stack/spacecash/merge(obj/item/stack/S)
|
||||
. = ..()
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
|
||||
/obj/item/stack/spacecash/change_stack(mob/living/user)
|
||||
. = ..()
|
||||
var/obj/item/stack/spacecash/new_dosh = .
|
||||
if(istype(new_dosh))
|
||||
new_dosh.update_icon(UPDATE_ICON_STATE)
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
|
||||
/obj/item/stack/spacecash/update_icon_state()
|
||||
name = "[amount] Credit[amount > 1 ? "s" : ""]"
|
||||
if(amount >= 1 && amount < 50)
|
||||
icon_state = "cash"
|
||||
else if(amount >= 50 && amount < 100)
|
||||
icon_state = "cash2"
|
||||
else if(amount >= 100 && amount < 500)
|
||||
icon_state = "cash3"
|
||||
else if(amount >= 500 && amount < 1000)
|
||||
icon_state = "cash4"
|
||||
else if(amount >= 1000 && amount < 10000)
|
||||
icon_state = "cash5"
|
||||
else
|
||||
icon_state = "cash6"
|
||||
|
||||
/obj/item/stack/spacecash/c5
|
||||
amount = 5
|
||||
|
||||
/obj/item/stack/spacecash/c10
|
||||
amount = 10
|
||||
|
||||
/obj/item/stack/spacecash/c20
|
||||
amount = 20
|
||||
|
||||
/obj/item/stack/spacecash/c50
|
||||
amount = 50
|
||||
|
||||
/obj/item/stack/spacecash/c100
|
||||
amount = 100
|
||||
|
||||
/obj/item/stack/spacecash/c200
|
||||
amount = 200
|
||||
|
||||
/obj/item/stack/spacecash/c500
|
||||
amount = 500
|
||||
|
||||
/obj/item/stack/spacecash/c1000
|
||||
amount = 1000
|
||||
|
||||
/obj/item/stack/spacecash/c10000
|
||||
amount = 10000
|
||||
|
||||
/obj/item/cash_pile
|
||||
name = "Pile of Cash"
|
||||
|
||||
/obj/item/cash_pile/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/two_handed, require_twohands = TRUE)
|
||||
@@ -1,97 +0,0 @@
|
||||
/obj/item/caution
|
||||
desc = "Caution! Wet Floor!"
|
||||
name = "wet floor sign"
|
||||
icon = 'icons/obj/janitor.dmi'
|
||||
icon_state = "caution"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi'
|
||||
force = 1.0
|
||||
throwforce = 3.0
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
attack_verb = list("warned", "cautioned", "smashed")
|
||||
|
||||
/obj/item/caution/proximity_sign
|
||||
var/timing = FALSE
|
||||
var/armed = FALSE
|
||||
var/timepassed = 0
|
||||
var/datum/proximity_monitor/proximity_monitor
|
||||
|
||||
/obj/item/caution/proximity_sign/Initialize(mapload)
|
||||
. = ..()
|
||||
proximity_monitor = new(src, 1)
|
||||
|
||||
/obj/item/caution/proximity_sign/attack_self__legacy__attackchain(mob/user as mob)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(!H.mind.has_antag_datum(/datum/antagonist/traitor) && !IS_MINDSLAVE(H))
|
||||
return
|
||||
if(armed)
|
||||
armed = FALSE
|
||||
to_chat(user, "<span class='notice'>You disarm \the [src].</span>")
|
||||
return
|
||||
timing = !timing
|
||||
if(timing)
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
armed = FALSE
|
||||
timepassed = 0
|
||||
to_chat(H, "<span class='notice'>You [timing ? "activate \the [src]'s timer, you have 15 seconds." : "de-activate \the [src]'s timer."]</span>")
|
||||
|
||||
/obj/item/caution/proximity_sign/process()
|
||||
if(!timing)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
timepassed++
|
||||
if(timepassed >= 15 && !armed)
|
||||
armed = TRUE
|
||||
timing = FALSE
|
||||
|
||||
/obj/item/caution/proximity_sign/HasProximity(atom/movable/AM)
|
||||
if(armed)
|
||||
if(iscarbon(AM) && !isbrain(AM))
|
||||
var/mob/living/carbon/C = AM
|
||||
if(C.m_intent != MOVE_INTENT_WALK)
|
||||
visible_message("[src] beeps, \"Sign says walk, asshole.\"")
|
||||
playsound(src, 'sound/misc/sign_says_walk.ogg', 40)
|
||||
explosion(src.loc,-1,0,2, cause = "Exploding wet floor sign")
|
||||
if(ishuman(C))
|
||||
dead_legs(C)
|
||||
if(src)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/caution/proximity_sign/proc/dead_legs(mob/living/carbon/human/H as mob)
|
||||
var/obj/item/organ/external/l = H.get_organ("l_leg")
|
||||
var/obj/item/organ/external/r = H.get_organ("r_leg")
|
||||
if(l)
|
||||
l.droplimb(0, DROPLIMB_SHARP)
|
||||
if(r)
|
||||
r.droplimb(0, DROPLIMB_SHARP)
|
||||
|
||||
/obj/item/stack/caution/proximity_sign/malf //Malf module
|
||||
name = "proximity mine dispenser"
|
||||
icon = 'icons/obj/janitor.dmi'
|
||||
icon_state = "caution"
|
||||
energy_type = /datum/robot_storage/energy/jani_landmine
|
||||
is_cyborg = TRUE
|
||||
|
||||
/obj/item/stack/caution/proximity_sign/malf/afterattack__legacy__attackchain(atom/target, mob/user, proximity)
|
||||
if(!check_allowed_items(target, 1))
|
||||
return
|
||||
if(!proximity)
|
||||
return
|
||||
var/turf/T = get_turf(target)
|
||||
|
||||
if(T.is_blocked_turf(exclude_mobs = TRUE)) //can't put mines on a tile that has dense stuff
|
||||
to_chat(user, "<span class='notice'>The space is occupied! You cannot place a mine there!</span>")
|
||||
return
|
||||
if(!use(1)) //Can't place a landmine if you don't have a landmine
|
||||
to_chat(user, "<span class='notice'>[src] is out of landmines! It can be refilled at a cyborg charger.</span>")
|
||||
return
|
||||
playsound(src.loc, 'sound/machines/click.ogg', 20, TRUE)
|
||||
var/obj/item/caution/proximity_sign/M = new /obj/item/caution/proximity_sign(get_turf(target), src)
|
||||
M.timing = TRUE
|
||||
START_PROCESSING(SSobj, M)
|
||||
to_chat(user, "<span class='notice'>You place a landmine with [src]. You have 15 seconds until it is armed.</span>")
|
||||
return M
|
||||
|
||||
@@ -1,719 +0,0 @@
|
||||
#define REAGENT_TIME_RATIO 2.5
|
||||
|
||||
/*
|
||||
CONTENTS:
|
||||
1. CIGARETTES
|
||||
2. CIGARS
|
||||
3. HOLO-CIGAR
|
||||
4. PIPES
|
||||
5. ROLLING
|
||||
|
||||
CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
LIGHTERS ARE IN LIGHTERS.DM
|
||||
*/
|
||||
|
||||
//////////////////
|
||||
//FINE SMOKABLES//
|
||||
//////////////////
|
||||
|
||||
/obj/item/clothing/mask/cigarette
|
||||
name = "cigarette"
|
||||
desc = "A roll of tobacco and nicotine."
|
||||
icon = 'icons/obj/clothing/smoking.dmi'
|
||||
icon_state = "cig"
|
||||
lefthand_file = 'icons/mob/inhands/smoking_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/smoking_righthand.dmi'
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
body_parts_covered = null
|
||||
attack_verb = null
|
||||
container_type = INJECTABLE
|
||||
new_attack_chain = TRUE
|
||||
/// Is the cigarette lit?
|
||||
var/lit = FALSE
|
||||
/// Do we require special items to be lit?
|
||||
var/list/fancy_lighters = list()
|
||||
/// What trash item the cigarette makes when it burns out.
|
||||
var/butt_type = /obj/item/cigbutt
|
||||
/// How long does the cigarette last before going out? Decrements by 1 every cycle.
|
||||
var/smoketime = 150 // 300 seconds.
|
||||
/// The cigarette's total reagent capacity.
|
||||
var/chem_volume = 60
|
||||
/// A list of the types and amounts of reagents in the cigarette.
|
||||
var/list/list_reagents = list("nicotine" = 40)
|
||||
/// Has anyone taken any reagents from the cigarette? The first tick gives a bigger dose.
|
||||
var/first_puff = TRUE
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/clothing/species/vox/mask.dmi',
|
||||
"Unathi" = 'icons/mob/clothing/species/unathi/mask.dmi',
|
||||
"Tajaran" = 'icons/mob/clothing/species/tajaran/mask.dmi',
|
||||
"Vulpkanin" = 'icons/mob/clothing/species/vulpkanin/mask.dmi',
|
||||
"Grey" = 'icons/mob/clothing/species/grey/mask.dmi')
|
||||
|
||||
/obj/item/clothing/mask/cigarette/Initialize(mapload)
|
||||
. = ..()
|
||||
create_reagents(chem_volume) // making the cigarrete a chemical holder with a maximum volume of 60
|
||||
reagents.set_reacting(FALSE) // so it doesn't react until you light it
|
||||
if(list_reagents)
|
||||
reagents.add_reagent_list(list_reagents)
|
||||
smoketime = reagents.total_volume * 2.5
|
||||
update_appearance(UPDATE_NAME|UPDATE_ICON_STATE)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/update_icon_state()
|
||||
. = ..()
|
||||
icon_state = "[initial(icon_state)][lit ? "_on" : ""]"
|
||||
item_state = "[initial(icon_state)][lit ? "_on" : ""]"
|
||||
if(ishuman(loc))
|
||||
var/mob/living/carbon/human/H = loc
|
||||
H.update_inv_wear_mask()
|
||||
H.update_inv_l_hand()
|
||||
H.update_inv_r_hand()
|
||||
|
||||
/obj/item/clothing/mask/cigarette/update_name()
|
||||
. = ..()
|
||||
if(!lit)
|
||||
name = initial(name)
|
||||
else
|
||||
name = "lit [name]"
|
||||
|
||||
/obj/item/clothing/mask/cigarette/activate_self(mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(lit)
|
||||
extinguish_cigarette(user)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/item_interaction(mob/living/user, obj/item/used, list/modifiers)
|
||||
if(istype(used, /obj/item/reagent_containers/syringe))
|
||||
return ..()
|
||||
|
||||
if(used.cigarette_lighter_act(user, user, src))
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
// Catch any item that has no `cigarette_lighter_act()` but logically should be able to work as a lighter due to being hot.
|
||||
if(used.get_heat())
|
||||
//Give a generic light message.
|
||||
user.visible_message(
|
||||
"<span class='notice'>[user] lights [src] with [used]</span>",
|
||||
"<span class='notice'>You light [src] with [used].</span>"
|
||||
)
|
||||
light(user)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/mask/cigarette/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(!istype(target, /obj/item/reagent_containers/glass))
|
||||
return ..()
|
||||
|
||||
var/obj/item/reagent_containers/glass/glass = target
|
||||
var/transfered = glass.reagents.trans_to(src, chem_volume)
|
||||
if(transfered)
|
||||
to_chat(user, "<span class='notice'>You dip [src] into [target].</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
// Either the beaker was empty, or the cigarette was full
|
||||
if(!glass.reagents.total_volume)
|
||||
to_chat(user, "<span class='notice'>[target] is empty.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>[src] is full.</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
/obj/item/clothing/mask/cigarette/pre_attack(atom/A, mob/living/user, params)
|
||||
if(!ismob(A))
|
||||
return ..()
|
||||
|
||||
var/mob/living/target = A
|
||||
if(target.on_fire)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.do_attack_animation(target)
|
||||
if(target != user)
|
||||
user.visible_message(
|
||||
"<span class='notice'>[user] coldly lights [src] with the burning body of [target]. Clearly, [user.p_they()] offer[user.p_s()] the warmest of regards...</span>",
|
||||
"<span class='notice'>You coldly light [src] with the burning body of [target].</span>"
|
||||
)
|
||||
else
|
||||
// The fire will light it in your hands by itself, but if you whip out the cig and click yourself fast enough, this will happen. TRULY you have your priorities stright.
|
||||
user.visible_message(
|
||||
"<span class='notice'>[user] quickly whips out [src] and nonchalantly lights it with [user.p_their()] own burning body. Clearly, [user.p_they()] [user.p_have()] [user.p_their()] priorities straight.</span>",
|
||||
"<span class='notice'>You quickly whip out [src] and nonchalantly light it with your own burning body. Clearly, you have your priorities straight.</span>"
|
||||
)
|
||||
light(user, user)
|
||||
return FINISH_ATTACK
|
||||
|
||||
// The above section doesn't check for carbons to allow ALL burning bodies to be used.
|
||||
if(!iscarbon(A))
|
||||
return ..()
|
||||
|
||||
// If the target has no cig, try to give them the cig.
|
||||
var/mob/living/carbon_target = A
|
||||
if(user.zone_selected == "mouth" && !carbon_target.wear_mask && user.a_intent == INTENT_HELP)
|
||||
user.drop_item_to_ground(src, force = TRUE)
|
||||
carbon_target.equip_to_slot_if_possible(src, ITEM_SLOT_MASK)
|
||||
if(target != user)
|
||||
user.visible_message(
|
||||
"<span class='notice'>[user] slips \a [name] into the mouth of [carbon_target].</span>",
|
||||
"<span class='notice'>You slip [src] into the mouth of [carbon_target].</span>"
|
||||
)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You put [src] into your mouth.</span>")
|
||||
return FINISH_ATTACK
|
||||
|
||||
// If they DO have a cig, try to light it with your own cig.
|
||||
if(cigarette_lighter_act(user, carbon_target))
|
||||
return FINISH_ATTACK
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/mask/cigarette/Destroy()
|
||||
QDEL_NULL(reagents)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/mask/cigarette/decompile_act(obj/item/matter_decompiler/C, mob/user)
|
||||
if(isdrone(user))
|
||||
C.stored_comms["wood"] += 1
|
||||
qdel(src)
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/mask/cigarette/proc/extinguish_cigarette(mob/user)
|
||||
user.visible_message(
|
||||
"<span class='notice'>[user] calmly drops and treads on [src], putting it out instantly.</span>",
|
||||
"<span class='notice'>You calmly drop and tread on [src], putting it out instantly.</span>",
|
||||
"<span class='notice'>You hear a foot being brought down on something, and the tiny fizzling of an ember going out.</span>"
|
||||
)
|
||||
die()
|
||||
|
||||
/obj/item/clothing/mask/cigarette/can_enter_storage(obj/item/storage/S, mob/user)
|
||||
if(lit)
|
||||
to_chat(user, "<span class='warning'>[S] can't hold \the [initial(name)] while it's lit!</span>") // initial(name) so it doesn't say "lit" twice in a row
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/mask/cigarette/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE)
|
||||
..()
|
||||
light()
|
||||
|
||||
/obj/item/clothing/mask/cigarette/catch_fire()
|
||||
if(!lit)
|
||||
visible_message("<span class='warning'>[src] is lit by the flames!</span>")
|
||||
light()
|
||||
|
||||
/obj/item/clothing/mask/cigarette/cigarette_lighter_act(mob/living/user, mob/living/target, obj/item/direct_attackby_item)
|
||||
var/obj/item/clothing/mask/cigarette/cig = ..()
|
||||
if(!cig)
|
||||
return !isnull(cig)
|
||||
|
||||
if(!lit)
|
||||
to_chat(user, "<span class='warning'>You cannot light [cig] with [src] because you need a lighter to light [src] before you can use [src] as a lighter to light [cig]... This seems a little convoluted.</span>")
|
||||
return TRUE
|
||||
|
||||
if(target == user)
|
||||
user.visible_message(
|
||||
"<span class='notice'>[user] presses [src] against [cig] until it lights. Seems oddly recursive...</span>",
|
||||
"<span class='notice'>You press [src] against [cig] until it lights. Seems oddly recursive...</span>"
|
||||
)
|
||||
else
|
||||
user.visible_message(
|
||||
"<span class='notice'>[user] presses [src] until it lights. Sharing is caring!</span>",
|
||||
"<span class='notice'>You press [src] against [cig] until it lights. Sharing is caring!</span>"
|
||||
)
|
||||
cig.light(user, target)
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/mask/cigarette/proc/light(mob/living/user, mob/living/target)
|
||||
if(lit)
|
||||
return
|
||||
|
||||
lit = TRUE
|
||||
attack_verb = list("burnt", "singed")
|
||||
hitsound = 'sound/items/welder.ogg'
|
||||
damtype = BURN
|
||||
force = 4
|
||||
var/mob/M = loc
|
||||
|
||||
// Plasma explodes when exposed to fire.
|
||||
if(reagents.get_reagent_amount("plasma"))
|
||||
var/datum/effect_system/reagents_explosion/e = new()
|
||||
e.set_up(round(reagents.get_reagent_amount("plasma") / 2.5, 1), get_turf(src), 0, 0)
|
||||
e.start()
|
||||
if(ismob(M))
|
||||
M.drop_item_to_ground(src, force = TRUE)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
// Fuel explodes, too, but much less violently.
|
||||
if(reagents.get_reagent_amount("fuel"))
|
||||
var/datum/effect_system/reagents_explosion/e = new()
|
||||
e.set_up(round(reagents.get_reagent_amount("fuel") / 5, 1), get_turf(src), 0, 0)
|
||||
e.start()
|
||||
if(ismob(M))
|
||||
M.drop_item_to_ground(src, force = TRUE)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
// If there is no target, the user is probably lighting their own cig.
|
||||
if(isnull(target))
|
||||
target = user
|
||||
|
||||
reagents.set_reacting(TRUE)
|
||||
reagents.handle_reactions()
|
||||
if(iscarbon(loc))
|
||||
var/mob/living/carbon/C = loc
|
||||
if(C.wear_mask == src) // Don't update if it's just in their hand
|
||||
C.wear_mask_update(src)
|
||||
set_light(2, 0.25, "#E38F46")
|
||||
update_appearance(UPDATE_NAME|UPDATE_ICON_STATE)
|
||||
START_PROCESSING(SSobj, src)
|
||||
playsound(src, 'sound/items/lighter/light.ogg', 25, TRUE)
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/mask/cigarette/process()
|
||||
var/mob/living/M = loc
|
||||
if(isliving(loc))
|
||||
M.IgniteMob()
|
||||
smoketime--
|
||||
if(reagents.total_volume <= 0 || smoketime < 1)
|
||||
die()
|
||||
return
|
||||
smoke()
|
||||
|
||||
/obj/item/clothing/mask/cigarette/extinguish_light(force)
|
||||
if(!force)
|
||||
return
|
||||
die()
|
||||
|
||||
/obj/item/clothing/mask/cigarette/proc/smoke()
|
||||
var/turf/location = get_turf(src)
|
||||
var/is_being_smoked = FALSE
|
||||
// Check whether this is actually in a mouth, being smoked
|
||||
if(iscarbon(loc))
|
||||
var/mob/living/carbon/C = loc
|
||||
if(src == C.wear_mask)
|
||||
// There used to be a species check here, but synthetics can smoke now
|
||||
is_being_smoked = TRUE
|
||||
if(location)
|
||||
location.hotspot_expose(700, 1)
|
||||
if(reagents && reagents.total_volume) // check if it has any reagents at all
|
||||
if(is_being_smoked) // if it's being smoked, transfer reagents to the mob
|
||||
var/mob/living/carbon/C = loc
|
||||
for(var/datum/reagent/R in reagents.reagent_list)
|
||||
reagents.trans_id_to(C, R.id, first_puff ? 1 : max(REAGENTS_METABOLISM / length(reagents.reagent_list), 0.1)) //transfer at least .1 of each chem
|
||||
first_puff = FALSE
|
||||
if(!reagents.total_volume) // There were reagents, but now they're gone
|
||||
to_chat(C, "<span class='notice'>Your [name] loses its flavor.</span>")
|
||||
else // else just remove some of the reagents
|
||||
reagents.remove_any(REAGENTS_METABOLISM)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/proc/die()
|
||||
var/turf/T = get_turf(src)
|
||||
set_light(0)
|
||||
var/obj/item/butt = new butt_type(T)
|
||||
transfer_fingerprints_to(butt)
|
||||
if(ismob(loc))
|
||||
var/mob/living/M = loc
|
||||
to_chat(M, "<span class='notice'>Your [name] goes out.</span>")
|
||||
// Only put the butt in the user's mouth if there's already a cig there.
|
||||
if(M.wear_mask == src)
|
||||
M.drop_item_to_ground(src, force = TRUE) //Force the un-equip so the overlays update
|
||||
butt.slot_flags |= ITEM_SLOT_MASK // Temporarily allow it to go on masks
|
||||
M.equip_to_slot_if_possible(butt, ITEM_SLOT_MASK)
|
||||
butt.slot_flags &= ~ITEM_SLOT_MASK
|
||||
else
|
||||
M.drop_item_to_ground(src, force = TRUE)
|
||||
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/get_heat()
|
||||
return lit * 1000
|
||||
|
||||
//////////////////////////////
|
||||
// MARK: CIGARETTES
|
||||
//////////////////////////////
|
||||
/obj/item/clothing/mask/cigarette/menthol
|
||||
list_reagents = list("nicotine" = 40, "menthol" = 20)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/random
|
||||
|
||||
/obj/item/clothing/mask/cigarette/random/New()
|
||||
list_reagents = list("nicotine" = 40, pick("fuel", "saltpetre", "synaptizine", "green_vomit", "potass_iodide", "msg", "lexorin", "mannitol", \
|
||||
"spaceacillin" ,"cryoxadone" ,"holywater", "tea" ,"egg" ,"haloperidol" ,"mutagen" ,"omnizine", "carpet", "aranesp", "cryostylane", "chocolate", \
|
||||
"bilk", "cheese", "rum", "blood", "charcoal", "coffee", "ectoplasm", "space_drugs", "milk", "mutadone", "antihol", "teporone", "insulin", "salbutamol", "toxin") = 20)
|
||||
..()
|
||||
|
||||
/obj/item/clothing/mask/cigarette/candy
|
||||
name = "candy cigarette"
|
||||
desc = "A stick of candy imitating a real cigarette. The words 'do not expose to heat' are written in very small letters around the base."
|
||||
|
||||
/obj/item/clothing/mask/cigarette/candy/interact_with_atom(atom/A, mob/living/user, list/modifiers)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(!ishuman(A))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/target = A
|
||||
if(target != user)
|
||||
user.visible_message(
|
||||
"<span_class='notice'>You begin to feed [target] [src].</span>",
|
||||
"<span_class='warning'>[user] begins to feed [target] [src]!</span>"
|
||||
)
|
||||
if(!do_after(user, 5 SECONDS, target = target))
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
else
|
||||
to_chat(user, "<span_class='notice'>You eat [src].</span>")
|
||||
|
||||
playsound(user.loc, 'sound/items/eatfood.ogg', 50, 0)
|
||||
|
||||
// A SPICY candy!
|
||||
if(lit)
|
||||
target.adjust_nutrition(2)
|
||||
target.reagents.add_reagent("sugar", 2, reagtemp = 373)
|
||||
target.reagents.add_reagent("ash", 3, reagtemp = 373)
|
||||
target.reagents.add_reagent("nicotine", 3, reagtemp = 373)
|
||||
var/obj/item/organ/external/head/target_head = target.get_organ("head")
|
||||
if(target_head.receive_damage(0, 15)) // OH GOD IT BURNS WHY DID I EAT THIS!?
|
||||
target.UpdateDamageIcon()
|
||||
to_chat(target, "<span_class='notice'>You can taste burnt sugar, ash, burning chemicals, and your own burning flesh...</span>")
|
||||
to_chat(target, "<span_class='userdanger'>OH FUCK! IT BURNS!</span>")
|
||||
target.emote("scream")
|
||||
add_attack_logs(user, target, "Fed a burning candy cigarette.")
|
||||
else
|
||||
target.adjust_nutrition(5)
|
||||
target.reagents.add_reagent("sugar", 5)
|
||||
to_chat(target, "<span_class='notice'>You can taste sugar, and a hint of chemicals.</span>")
|
||||
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
/obj/item/clothing/mask/cigarette/syndicate
|
||||
name = "suspicious cigarette"
|
||||
desc = "An evil-looking cigarette. It smells of donk pockets."
|
||||
icon_state = "syndie_cig"
|
||||
butt_type = /obj/item/cigbutt/syndie
|
||||
list_reagents = list("nicotine" = 40, "omnizine" = 20)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/medical_marijuana
|
||||
name = "medical marijuana cigarette"
|
||||
desc = "A cigarette containing specially-bread cannabis that has been engineered to only contain CBD, for medical use. The lack of THC makes it fully legal under Space Law."
|
||||
icon_state = "medical_weed_cig"
|
||||
list_reagents = list("cbd" = 60)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/robustgold
|
||||
name = "\improper Robust Gold cigarette"
|
||||
desc = "A premium cigarette smoked by the truly robust, contains real gold."
|
||||
list_reagents = list("nicotine" = 40, "gold" = 1)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/shadyjims
|
||||
list_reagents = list("nicotine" = 40, "lipolicide" = 7.5, "ammonia" = 2, "atrazine" = 1, "toxin" = 1.5)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/rollie
|
||||
name = "rollie"
|
||||
desc = "A roll of dried plant matter wrapped in thin paper. It carries the unmistakable smell of cannabis."
|
||||
icon_state = "spliff"
|
||||
butt_type = /obj/item/cigbutt/roach
|
||||
list_reagents = list("thc" = 40, "cbd" = 20)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/rollie/Initialize(mapload)
|
||||
. = ..()
|
||||
scatter_atom()
|
||||
/obj/item/clothing/mask/cigarette/rollie/custom
|
||||
desc = "A roll of dried plant matter wrapped in thin paper."
|
||||
list_reagents = list()
|
||||
|
||||
/obj/item/cigbutt
|
||||
name = "cigarette butt"
|
||||
desc = "A manky old cigarette butt."
|
||||
icon = 'icons/obj/clothing/smoking.dmi'
|
||||
icon_state = "cig_butt"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
scatter_distance = 10
|
||||
|
||||
/obj/item/cigbutt/syndie
|
||||
name = "suspicious cigarette butt"
|
||||
desc = "A manky old cigarette butt with an evil look about it."
|
||||
icon_state = "syndie_cig_butt"
|
||||
|
||||
/obj/item/cigbutt/Initialize(mapload)
|
||||
. = ..()
|
||||
scatter_atom()
|
||||
transform = turn(transform, rand(0, 360))
|
||||
|
||||
/obj/item/cigbutt/decompile_act(obj/item/matter_decompiler/C, mob/user)
|
||||
if(isdrone(user))
|
||||
C.stored_comms["wood"] += 1
|
||||
qdel(src)
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/item/cigbutt/roach
|
||||
name = "roach"
|
||||
desc = "A manky old roach, or for non-stoners, a used rollup."
|
||||
icon_state = "roach"
|
||||
scatter_distance = 5
|
||||
|
||||
/obj/item/cigbutt/roach/Initialize(mapload)
|
||||
. = ..()
|
||||
scatter_atom()
|
||||
|
||||
//////////////////////////////
|
||||
// MARK: ROLLING
|
||||
//////////////////////////////
|
||||
/obj/item/rollingpaper
|
||||
name = "rolling paper"
|
||||
desc = "A thin piece of paper used to make fine smokeables."
|
||||
icon = 'icons/obj/cigarettes.dmi'
|
||||
icon_state = "cig_paper"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
new_attack_chain = TRUE
|
||||
|
||||
/obj/item/rollingpaper/item_interaction(mob/living/user, obj/item/used, list/modifiers)
|
||||
if(!istype(used, /obj/item/food/grown))
|
||||
return ..()
|
||||
|
||||
var/obj/item/food/grown/plant = used
|
||||
if(!plant.dry)
|
||||
to_chat(user, "<span class='warning'>You need to dry this first!</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
user.unequip(plant, TRUE)
|
||||
user.unequip(src, TRUE)
|
||||
var/obj/item/clothing/mask/cigarette/rollie/custom/custom_rollie = new (get_turf(user))
|
||||
custom_rollie.reagents.maximum_volume = plant.reagents.total_volume
|
||||
plant.reagents.trans_to(custom_rollie, plant.reagents.total_volume)
|
||||
custom_rollie.smoketime = custom_rollie.reagents.total_volume * 2.5
|
||||
|
||||
user.put_in_active_hand(custom_rollie)
|
||||
to_chat(user, "<span class='notice'>You roll the [plant.name] into a rolling paper.</span>")
|
||||
custom_rollie.desc = "Dried [plant.name] rolled up in a thin piece of paper."
|
||||
|
||||
qdel(plant)
|
||||
qdel(src)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
//////////////////////////////
|
||||
// MARK: CIGARS
|
||||
//////////////////////////////
|
||||
/obj/item/clothing/mask/cigarette/cigar
|
||||
name = "\improper Nano Cigar"
|
||||
desc = "A huge, brown roll of dried and fermented tobacco, manufactured by Nanotrasen's Robust Tobacco subsidiary."
|
||||
icon_state = "cigar"
|
||||
fancy_lighters = list(/obj/item/match, /obj/item/lighter/zippo)
|
||||
butt_type = /obj/item/cigbutt/cigarbutt
|
||||
smoketime = 300
|
||||
chem_volume = 140
|
||||
list_reagents = list("nicotine" = 120)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/cigar/examine_more(mob/user)
|
||||
. = ..()
|
||||
. += " Don't let the advertising fool you, this thing is a bargain basement, bottom-of-the-barrel product and the smoking experience it offers is little better than an oversized Robust cigarette."
|
||||
. += ""
|
||||
. += "It still makes you look like a mafia boss, however."
|
||||
|
||||
/obj/item/clothing/mask/cigarette/cigar/cohiba
|
||||
name = "\improper Cohiba Robusto Cigar"
|
||||
desc = "A premium brand of cigar widely exported and enjoyed across the Orion Sector. There's little more that you could want from a cigar"
|
||||
icon_state = "gold_cigar"
|
||||
butt_type = /obj/item/cigbutt/cigarbutt/gold
|
||||
|
||||
/obj/item/clothing/mask/cigarette/cigar/cohiba/examine_more(mob/user)
|
||||
..()
|
||||
. = list()
|
||||
. += "Lovingly machine rolled using carefully selected strains of tobacco grown in massive hydroponics warehouses in orbit around the death world of Venus, Sol. \
|
||||
It goes through a range of carefully selected flavours as it is smoked, providing a novel and enjoyable experience throughout."
|
||||
|
||||
/obj/item/clothing/mask/cigarette/cigar/havana
|
||||
name = "\improper Premium Havanian Cigar"
|
||||
desc = "A luxury cigar only fit for the best of the best."
|
||||
icon_state = "gold_cigar"
|
||||
smoketime = 450
|
||||
chem_volume = 200
|
||||
list_reagents = list("nicotine" = 180)
|
||||
butt_type = /obj/item/cigbutt/cigarbutt/gold
|
||||
|
||||
/obj/item/clothing/mask/cigarette/cigar/havana/examine_more(mob/user)
|
||||
..()
|
||||
. = list()
|
||||
. += "One of a handful of brands made using tobacco grown in Cuba on Earth, the core of the Trans-Solar Federation. \
|
||||
Each of these hand-rolled cigars is carefully put together by master cigar rollers using various strains of tobacco that has been cultivated for hundreds of years to ensure \
|
||||
the best consistency and flavour possible."
|
||||
. += ""
|
||||
. += "Due to a mixture of limited manufacturing capacity, high quality, brand prestige, and export taxes, \
|
||||
these cigars are too expensive for all but the most wealthy to smoke with any degree of regularity."
|
||||
|
||||
/obj/item/cigbutt/cigarbutt
|
||||
name = "cigar butt"
|
||||
desc = "A manky old cigar butt."
|
||||
icon_state = "cigar_butt"
|
||||
|
||||
/obj/item/cigbutt/cigarbutt/gold
|
||||
icon_state = "gold_cigar_butt"
|
||||
|
||||
//////////////////////////////
|
||||
// MARK: HOLO-CIGAR
|
||||
//////////////////////////////
|
||||
/obj/item/clothing/mask/holo_cigar
|
||||
name = "holo-cigar"
|
||||
desc = "A sleek electronic cigar imported straight from Sol. You feel badass merely glimpsing it..."
|
||||
icon = 'icons/obj/clothing/smoking.dmi'
|
||||
icon_state = "holo_cigar"
|
||||
lefthand_file = 'icons/mob/inhands/smoking_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/smoking_righthand.dmi'
|
||||
new_attack_chain = TRUE
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/clothing/species/vox/mask.dmi',
|
||||
"Unathi" = 'icons/mob/clothing/species/unathi/mask.dmi',
|
||||
"Tajaran" = 'icons/mob/clothing/species/tajaran/mask.dmi',
|
||||
"Vulpkanin" = 'icons/mob/clothing/species/vulpkanin/mask.dmi',
|
||||
"Grey" = 'icons/mob/clothing/species/grey/mask.dmi')
|
||||
/// Is the holo-cigar lit?
|
||||
var/enabled = FALSE
|
||||
/// Tracks if this is the first cycle smoking the cigar.
|
||||
var/has_smoked = FALSE
|
||||
|
||||
/obj/item/clothing/mask/holo_cigar/activate_self(mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(enabled)
|
||||
enabled = FALSE
|
||||
to_chat(user, "<span class='notice'>You disable the holo-cigar.</span>")
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
else
|
||||
enabled = TRUE
|
||||
to_chat(user, "<span class='notice'>You enable the holo-cigar.</span>")
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
update_appearance(UPDATE_NAME|UPDATE_ICON_STATE)
|
||||
|
||||
/obj/item/clothing/mask/holo_cigar/Destroy()
|
||||
. = ..()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/clothing/mask/holo_cigar/update_icon_state()
|
||||
. = ..()
|
||||
icon_state = "holo_cigar[enabled ? "_on" : ""]"
|
||||
|
||||
/obj/item/clothing/mask/holo_cigar/update_name()
|
||||
. = ..()
|
||||
name = "[enabled ? "active " : ""]holo-cigar"
|
||||
|
||||
/obj/item/clothing/mask/holo_cigar/examine(mob/user)
|
||||
. = ..()
|
||||
if(enabled)
|
||||
. += "[src] hums softly as it synthesizes nicotine."
|
||||
else
|
||||
. += "[src] seems to be inactive."
|
||||
|
||||
/obj/item/clothing/mask/holo_cigar/process()
|
||||
if(!iscarbon(loc))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/C = loc
|
||||
if(C.wear_mask != src)
|
||||
return
|
||||
|
||||
if(!has_smoked)
|
||||
C.reagents.add_reagent("nicotine", 2)
|
||||
has_smoked = TRUE
|
||||
else
|
||||
C.reagents.add_reagent("nicotine", REAGENTS_METABOLISM)
|
||||
|
||||
/obj/item/clothing/mask/holo_cigar/equipped(mob/user, slot, initial)
|
||||
. = ..()
|
||||
if(enabled && slot == ITEM_SLOT_MASK)
|
||||
if(!HAS_TRAIT_FROM(user, TRAIT_BADASS, HOLO_CIGAR))
|
||||
ADD_TRAIT(user, TRAIT_BADASS, HOLO_CIGAR)
|
||||
to_chat(user, "<span class='notice'>You feel more badass while smoking [src].</span>")
|
||||
|
||||
/obj/item/clothing/mask/holo_cigar/dropped(mob/user, silent)
|
||||
. = ..()
|
||||
has_smoked = FALSE
|
||||
if(HAS_TRAIT_FROM(user, TRAIT_BADASS, HOLO_CIGAR))
|
||||
REMOVE_TRAIT(user, TRAIT_BADASS, HOLO_CIGAR)
|
||||
to_chat(user, "<span class='notice'>You feel less badass.</span>")
|
||||
|
||||
//////////////////////////////
|
||||
// MARK: PIPES
|
||||
//////////////////////////////
|
||||
/obj/item/clothing/mask/cigarette/pipe
|
||||
name = "smoking pipe"
|
||||
desc = "A fancy smoking pipe carved from polished morta, otherwise known as bog wood. Preferred by sophisticated gentlemen and those posing as sophisticated gentlemen."
|
||||
icon_state = "pipe"
|
||||
fancy_lighters = list(/obj/item/match, /obj/item/lighter/zippo)
|
||||
smoketime = 500
|
||||
chem_volume = 220
|
||||
list_reagents = list("nicotine" = 200)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/pipe/activate_self(mob/user)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(lit)
|
||||
extinguish_cigarette(user)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/pipe/item_interaction(mob/living/user, obj/item/used, list/modifiers)
|
||||
if(!istype(used, /obj/item/food/grown))
|
||||
return ..()
|
||||
|
||||
var/obj/item/food/grown/filler = used
|
||||
if(!filler.dry)
|
||||
to_chat(user, "<span class='warning'>You need to dry this first!</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
if(reagents.total_volume == reagents.maximum_volume)
|
||||
to_chat(user, "<span class='warning'>[src] is full!</span>")
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
filler.reagents.trans_to(src, chem_volume)
|
||||
to_chat(user, "<span class='notice'>You stuff the [filler.name] into the pipe.</span>")
|
||||
smoketime = max(reagents.total_volume * REAGENT_TIME_RATIO, smoketime)
|
||||
qdel(filler)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
/obj/item/clothing/mask/cigarette/pipe/light()
|
||||
if(!lit)
|
||||
lit = TRUE
|
||||
damtype = "fire"
|
||||
update_appearance(UPDATE_NAME|UPDATE_ICON_STATE)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/pipe/process()
|
||||
var/turf/location = get_turf(src)
|
||||
smoketime--
|
||||
if(smoketime < 1)
|
||||
new /obj/effect/decal/cleanable/ash(location)
|
||||
if(ismob(loc))
|
||||
var/mob/living/M = loc
|
||||
to_chat(M, "<span class='notice'>Your [name] goes out, and you empty the ash.</span>")
|
||||
lit = FALSE
|
||||
update_appearance(UPDATE_NAME|UPDATE_ICON_STATE)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return
|
||||
|
||||
smoke()
|
||||
|
||||
/obj/item/clothing/mask/cigarette/pipe/extinguish_cigarette(mob/user)
|
||||
user.visible_message(
|
||||
"<span class='notice'>[user] puts out [src].</span>",
|
||||
"<span class='notice'>You put out [src].</span>"
|
||||
)
|
||||
lit = FALSE
|
||||
first_puff = TRUE
|
||||
update_appearance(UPDATE_NAME|UPDATE_ICON_STATE)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/clothing/mask/cigarette/pipe/die()
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/cigarette/pipe/cobpipe
|
||||
name = "corn cob pipe"
|
||||
desc = "A nicotine delivery system popularized by folksy backwoodsmen and kept popular in the modern age and beyond by space hipsters."
|
||||
icon_state = "cob_pipe"
|
||||
smoketime = 0 //there is nothing to smoke initially
|
||||
chem_volume = 160
|
||||
list_reagents = list()
|
||||
|
||||
#undef REAGENT_TIME_RATIO
|
||||
@@ -1,100 +0,0 @@
|
||||
/* Clown Items
|
||||
* Contains:
|
||||
* Banana Peels
|
||||
* Soap
|
||||
* Bike Horns
|
||||
*/
|
||||
|
||||
/*
|
||||
* Bike Horns
|
||||
*/
|
||||
|
||||
/obj/item/bikehorn
|
||||
name = "bike horn"
|
||||
desc = "A horn off of a bicycle."
|
||||
icon_state = "bike_horn"
|
||||
item_state = "bike_horn"
|
||||
hitsound = null
|
||||
throwforce = 3
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
var/list/honk_sounds = list('sound/items/bikehorn.ogg' = 1)
|
||||
throw_speed = 3
|
||||
throw_range = 15
|
||||
attack_verb = list("HONKED")
|
||||
|
||||
/obj/item/bikehorn/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/squeak, honk_sounds, 50, falloff_exponent = 20) //die off quick please
|
||||
|
||||
/obj/item/bikehorn/airhorn
|
||||
name = "air horn"
|
||||
desc = "Damn son, where'd you find this?"
|
||||
icon_state = "air_horn"
|
||||
origin_tech = "materials=4;engineering=4"
|
||||
honk_sounds = list('sound/items/airhorn2.ogg' = 1)
|
||||
|
||||
/obj/item/bikehorn/golden
|
||||
name = "golden bike horn"
|
||||
desc = "Golden? Clearly, its made with bananium! Honk!"
|
||||
icon_state = "gold_horn"
|
||||
item_state = "gold_horn"
|
||||
var/cooldown = 0
|
||||
|
||||
/obj/item/bikehorn/golden/attack__legacy__attackchain(mob/M, mob/user)
|
||||
flip_mobs(user)
|
||||
return ..()
|
||||
|
||||
/obj/item/bikehorn/golden/attack_self__legacy__attackchain(mob/user)
|
||||
flip_mobs(user)
|
||||
..()
|
||||
|
||||
/obj/item/bikehorn/golden/proc/flip_mobs(mob/user)
|
||||
if(cooldown >= world.time)
|
||||
to_chat(user, "<span class='warning'>You can't make others flip yet!</span>")
|
||||
return
|
||||
cooldown = world.time + 30 SECONDS
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/mob/living/carbon/M in ohearers(7, T))
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(!H.can_hear())
|
||||
continue
|
||||
M.emote("flip")
|
||||
|
||||
#define LAUGH_COOLDOWN 30 SECONDS
|
||||
#define LAUGH_COOLDOWN_CMAG 10 SECONDS
|
||||
|
||||
/obj/item/clown_recorder
|
||||
name = "clown recorder"
|
||||
desc = "When you just can't get those laughs coming the natural way!"
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "clown_recorder"
|
||||
item_state = "analyzer"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
materials = list(MAT_METAL = 180, MAT_GLASS = 90)
|
||||
force = 2
|
||||
drop_sound = 'sound/items/handling/taperecorder_drop.ogg'
|
||||
pickup_sound = 'sound/items/handling/taperecorder_pickup.ogg'
|
||||
actions_types = list(/datum/action/item_action/laugh_track)
|
||||
var/cooldown = 0
|
||||
|
||||
/obj/item/clown_recorder/attack_self__legacy__attackchain(mob/user)
|
||||
if(cooldown > world.time)
|
||||
to_chat(user, "<span class='notice'>The tape is still winding back.</span>")
|
||||
return
|
||||
playsound(src, pick('sound/voice/sitcom_laugh.ogg', 'sound/voice/sitcom_laugh2.ogg'), 50, FALSE)
|
||||
if(!HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
cooldown = world.time + LAUGH_COOLDOWN
|
||||
else
|
||||
cooldown = world.time + LAUGH_COOLDOWN_CMAG
|
||||
|
||||
/obj/item/clown_recorder/cmag_act(mob/user)
|
||||
if(!HAS_TRAIT(src, TRAIT_CMAGGED))
|
||||
to_chat(user, "<span class='notice'>Winding back speed has been improved by the bananium ooze!</span>")
|
||||
ADD_TRAIT(src, TRAIT_CMAGGED, CLOWN_EMAG)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
#undef LAUGH_COOLDOWN
|
||||
#undef LAUGH_COOLDOWN_CMAG
|
||||
@@ -1,183 +0,0 @@
|
||||
/obj/item/lipstick
|
||||
name = "red lipstick"
|
||||
desc = "A generic brand of lipstick."
|
||||
icon_state = "lipstick"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
var/colour = "red"
|
||||
var/open = FALSE
|
||||
var/static/list/lipstick_colors
|
||||
|
||||
/obj/item/lipstick/Initialize(mapload)
|
||||
. = ..()
|
||||
if(!lipstick_colors)
|
||||
lipstick_colors = list(
|
||||
"black" = "#000000",
|
||||
"white" = "#FFFFFF",
|
||||
"red" = "#FF0000",
|
||||
"green" = "#00C000",
|
||||
"blue" = "#0000FF",
|
||||
"purple" = "#D55CD0",
|
||||
"jade" = "#216F43",
|
||||
"lime" = "#00FF00",
|
||||
)
|
||||
|
||||
/obj/item/lipstick/purple
|
||||
name = "purple lipstick"
|
||||
colour = "purple"
|
||||
|
||||
/obj/item/lipstick/jade
|
||||
name = "jade lipstick"
|
||||
colour = "jade"
|
||||
|
||||
/obj/item/lipstick/lime
|
||||
name = "lime lipstick"
|
||||
colour = "lime"
|
||||
|
||||
/obj/item/lipstick/black
|
||||
name = "black lipstick"
|
||||
colour = "black"
|
||||
|
||||
/obj/item/lipstick/green
|
||||
name = "green lipstick"
|
||||
colour = "green"
|
||||
|
||||
/obj/item/lipstick/blue
|
||||
name = "blue lipstick"
|
||||
colour = "blue"
|
||||
|
||||
/obj/item/lipstick/white
|
||||
name = "white lipstick"
|
||||
colour = "white"
|
||||
|
||||
/obj/item/lipstick/random
|
||||
name = "lipstick"
|
||||
|
||||
/obj/item/lipstick/random/Initialize(mapload)
|
||||
. = ..()
|
||||
colour = pick(lipstick_colors)
|
||||
name = "[colour] lipstick"
|
||||
|
||||
/obj/item/lipstick/attack_self__legacy__attackchain(mob/user)
|
||||
cut_overlays()
|
||||
to_chat(user, "<span class='notice'>You twist \the [src] [open ? "closed" : "open"].</span>")
|
||||
open = !open
|
||||
if(open)
|
||||
var/mutable_appearance/colored = mutable_appearance('icons/obj/items.dmi', "lipstick_uncap_color")
|
||||
colored.color = lipstick_colors[colour]
|
||||
icon_state = "lipstick_uncap"
|
||||
add_overlay(colored)
|
||||
else
|
||||
icon_state = "lipstick"
|
||||
|
||||
/obj/item/lipstick/attack__legacy__attackchain(mob/M, mob/user)
|
||||
if(!open || !istype(M))
|
||||
return
|
||||
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.lip_style) // If they already have lipstick on
|
||||
to_chat(user, "<span class='notice'>You need to wipe off the old lipstick first!</span>")
|
||||
return
|
||||
if(H == user)
|
||||
user.visible_message("<span class='notice'>[user] does [user.p_their()] lips with [src].</span>", \
|
||||
"<span class='notice'>You take a moment to apply [src]. Perfect!</span>")
|
||||
H.lip_style = "lipstick"
|
||||
H.lip_color = lipstick_colors[colour]
|
||||
H.update_body()
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] begins to do [H]'s lips with \the [src].</span>", \
|
||||
"<span class='notice'>You begin to apply \the [src].</span>")
|
||||
if(do_after(user, 20, target = H))
|
||||
user.visible_message("<span class='notice'>[user] does [H]'s lips with \the [src].</span>", \
|
||||
"<span class='notice'>You apply \the [src].</span>")
|
||||
H.lip_style = "lipstick"
|
||||
H.lip_color = lipstick_colors[colour]
|
||||
H.update_body()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>Where are the lips on that?</span>")
|
||||
|
||||
/obj/item/razor
|
||||
name = "electric razor"
|
||||
desc = "The latest and greatest power razor born from the science of shaving."
|
||||
icon_state = "razor"
|
||||
flags = CONDUCT
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
usesound = 'sound/items/welder2.ogg'
|
||||
|
||||
/obj/item/razor/attack__legacy__attackchain(mob/living/carbon/M as mob, mob/user as mob)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/external/head/C = H.get_organ("head")
|
||||
if(!istype(C))
|
||||
to_chat(user, "<span class='warning'>There's nothing to cut, [M] [M.p_are()] missing [M.p_their()] head!</span>")
|
||||
return ..()
|
||||
var/datum/robolimb/robohead = GLOB.all_robolimbs[C.model]
|
||||
if(user.zone_selected == "mouth")
|
||||
if(!get_location_accessible(H, "mouth"))
|
||||
to_chat(user, "<span class='warning'>The mask is in the way.</span>")
|
||||
return
|
||||
if((C.dna.species.bodyflags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'...
|
||||
to_chat(user, "<span class='warning'>You find yourself disappointed at the appalling lack of facial hair.</span>")
|
||||
return
|
||||
if(C.f_style == "Shaved")
|
||||
to_chat(user, "<span class='notice'>Already clean-shaven.</span>")
|
||||
return
|
||||
if(H == user) //shaving yourself
|
||||
user.visible_message("<span class='notice'>[user] starts to shave [user.p_their()] facial hair with [src].</span>", \
|
||||
"<span class='notice'>You take a moment shave your facial hair with \the [src].</span>")
|
||||
if(do_after(user, 50 * toolspeed, target = H))
|
||||
user.visible_message("<span class='notice'>[user] shaves [user.p_their()] facial hair clean with [src].</span>", \
|
||||
"<span class='notice'>You finish shaving with [src]. Fast and clean!</span>")
|
||||
C.f_style = "Shaved"
|
||||
H.update_fhair()
|
||||
playsound(src.loc, usesound, 20, 1)
|
||||
else
|
||||
var/turf/user_loc = user.loc
|
||||
var/turf/H_loc = H.loc
|
||||
user.visible_message("<span class='danger'>[user] tries to shave [H]'s facial hair with \the [src].</span>", \
|
||||
"<span class='warning'>You start shaving [H]'s facial hair.</span>")
|
||||
if(do_after(user, 50 * toolspeed, target = H))
|
||||
if(user_loc == user.loc && H_loc == H.loc)
|
||||
user.visible_message("<span class='danger'>[user] shaves off [H]'s facial hair with \the [src].</span>", \
|
||||
"<span class='notice'>You shave [H]'s facial hair clean off.</span>")
|
||||
C.f_style = "Shaved"
|
||||
H.update_fhair()
|
||||
playsound(src.loc, usesound, 20, 1)
|
||||
if(user.zone_selected == "head")
|
||||
if(!get_location_accessible(H, "head"))
|
||||
to_chat(user, "<span class='warning'>The headgear is in the way.</span>")
|
||||
return
|
||||
if((C.dna.species.bodyflags & ALL_RPARTS) && robohead.is_monitor) //If the target is of a species that can have prosthetic heads, but the head doesn't support human hair 'wigs'...
|
||||
to_chat(user, "<span class='warning'>You find yourself disappointed at the appalling lack of hair.</span>")
|
||||
return
|
||||
if(C.h_style == "Bald" || C.h_style == "Balding Hair" || C.h_style == "Skinhead")
|
||||
to_chat(user, "<span class='notice'>There is not enough hair left to shave...</span>")
|
||||
return
|
||||
if(isskrell(M))
|
||||
to_chat(user, "<span class='warning'>Your razor isn't going to cut through tentacles.</span>")
|
||||
return
|
||||
if(H == user) //shaving yourself
|
||||
user.visible_message("<span class='warning'>[user] starts to shave [user.p_their()] head with [src].</span>", \
|
||||
"<span class='warning'>You start to shave your head with \the [src].</span>")
|
||||
if(do_after(user, 50 * toolspeed, target = H))
|
||||
user.visible_message("<span class='notice'>[user] shaves [user.p_their()] head with [src].</span>", \
|
||||
"<span class='notice'>You finish shaving with \the [src].</span>")
|
||||
C.h_style = "Skinhead"
|
||||
H.update_hair()
|
||||
playsound(src.loc, usesound, 40, 1)
|
||||
else
|
||||
var/turf/user_loc = user.loc
|
||||
var/turf/H_loc = H.loc
|
||||
user.visible_message("<span class='danger'>[user] tries to shave [H]'s head with \the [src]!</span>", \
|
||||
"<span class='warning'>You start shaving [H]'s head.</span>")
|
||||
if(do_after(user, 50 * toolspeed, target = H))
|
||||
if(user_loc == user.loc && H_loc == H.loc)
|
||||
user.visible_message("<span class='danger'>[user] shaves [H]'s head bald with \the [src]!</span>", \
|
||||
"<span class='warning'>You shave [H]'s head bald.</span>")
|
||||
C.h_style = "Skinhead"
|
||||
H.update_hair()
|
||||
playsound(src.loc, usesound, 40, 1)
|
||||
else
|
||||
..()
|
||||
else
|
||||
..()
|
||||
@@ -1,36 +0,0 @@
|
||||
// Contains:
|
||||
// Gavel Hammer
|
||||
// Gavel Block
|
||||
|
||||
/obj/item/gavelhammer
|
||||
name = "gavel hammer"
|
||||
desc = "Order, order! No bombs in my courthouse."
|
||||
icon_state = "gavelhammer"
|
||||
force = 5.0
|
||||
throwforce = 6.0
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
attack_verb = list("bashed", "battered", "judged", "whacked")
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
/obj/item/gavelhammer/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] has sentenced [user.p_themselves()] to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
playsound(loc, 'sound/items/gavel.ogg', 50, TRUE, -1)
|
||||
return BRUTELOSS
|
||||
|
||||
/obj/item/gavelblock
|
||||
name = "gavel block"
|
||||
desc = "Smack it with a gavel hammer when the assistants get rowdy."
|
||||
icon_state = "gavelblock"
|
||||
force = 2.0
|
||||
throwforce = 2.0
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
resistance_flags = FLAMMABLE
|
||||
var/next_gavel_hit
|
||||
|
||||
/obj/item/gavelblock/attackby__legacy__attackchain(obj/item/I, mob/user, params)
|
||||
if(!istype(I, /obj/item/gavelhammer))
|
||||
return
|
||||
if(world.time > next_gavel_hit)
|
||||
playsound(loc, 'sound/items/gavel.ogg', 100, 1)
|
||||
next_gavel_hit = world.time + 5 SECONDS
|
||||
user.visible_message("<span class='warning'>[user] strikes \the [src] with \the [I].</span>")
|
||||
@@ -1,461 +0,0 @@
|
||||
//backpack item
|
||||
|
||||
/obj/item/defibrillator
|
||||
name = "defibrillator"
|
||||
desc = "A device that delivers powerful shocks to detachable paddles that resuscitate incapacitated patients."
|
||||
icon = 'icons/obj/defib.dmi'
|
||||
icon_state = "defibunit"
|
||||
item_state = "defibunit"
|
||||
slot_flags = ITEM_SLOT_BACK
|
||||
force = 5
|
||||
throwforce = 6
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
origin_tech = "biotech=4"
|
||||
actions_types = list(/datum/action/item_action/toggle_paddles)
|
||||
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 50, ACID = 50)
|
||||
sprite_sheets = list(
|
||||
"Vox" = 'icons/mob/clothing/species/vox/back.dmi'
|
||||
)
|
||||
|
||||
/// If the paddles are currently attached to the unit.
|
||||
var/paddles_on_defib = TRUE
|
||||
/// if there's a cell in the defib with enough power for a revive; blocks paddles from reviving otherwise
|
||||
var/powered = FALSE
|
||||
/// Ref to attached paddles
|
||||
var/obj/item/shockpaddles/paddles
|
||||
/// Ref to internal power cell.
|
||||
var/obj/item/stock_parts/cell/high/cell = null
|
||||
/// If false, using harm intent will let you zap people. Note that any updates to this after init will only impact icons.
|
||||
var/safety = TRUE
|
||||
/// If true, this can be used through hardsuits, and can cause heart attacks in harm intent.
|
||||
var/combat = FALSE
|
||||
// If safety is false and combat is true, the chance that this will cause a heart attack.
|
||||
var/heart_attack_probability = 30
|
||||
/// If this is vulnerable to EMPs.
|
||||
var/hardened = FALSE
|
||||
/// If this can be emagged.
|
||||
var/emag_proof = FALSE
|
||||
|
||||
base_icon_state = "defibpaddles"
|
||||
/// Type of paddles that should be attached to this defib.
|
||||
var/obj/item/shockpaddles/paddle_type = /obj/item/shockpaddles
|
||||
|
||||
/obj/item/defibrillator/get_cell()
|
||||
return cell
|
||||
|
||||
/obj/item/defibrillator/Initialize(mapload) // Base version starts without a cell for rnd
|
||||
. = ..()
|
||||
paddles = new paddle_type(src)
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/item/defibrillator/loaded/Initialize(mapload) // Loaded version starts with high-capacity cell.
|
||||
. = ..()
|
||||
cell = new(src)
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/item/defibrillator/update_icon(updates=ALL)
|
||||
update_power()
|
||||
..()
|
||||
|
||||
/obj/item/defibrillator/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'><b>Alt-Click</b> to remove the paddles from the defibrillator.</span>"
|
||||
|
||||
/obj/item/defibrillator/proc/update_power()
|
||||
if(cell)
|
||||
if(cell.charge < paddles.revivecost)
|
||||
powered = FALSE
|
||||
else
|
||||
powered = TRUE
|
||||
else
|
||||
powered = FALSE
|
||||
|
||||
/obj/item/defibrillator/update_overlays()
|
||||
. = ..()
|
||||
if(paddles_on_defib)
|
||||
. += "[icon_state]-paddles"
|
||||
if(!safety)
|
||||
. += "[icon_state]-emagged"
|
||||
if(powered)
|
||||
. += "[icon_state]-powered"
|
||||
if(powered && cell)
|
||||
var/ratio = cell.charge / cell.maxcharge
|
||||
ratio = CEILING(ratio*4, 1) * 25
|
||||
. += "[icon_state]-charge[ratio]"
|
||||
if(!cell)
|
||||
. += "[icon_state]-nocell"
|
||||
|
||||
/obj/item/defibrillator/CheckParts(list/parts_list)
|
||||
..()
|
||||
cell = locate(/obj/item/stock_parts/cell) in contents
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/item/defibrillator/ui_action_click(mob/user)
|
||||
toggle_paddles(user)
|
||||
|
||||
/obj/item/defibrillator/AltClick(mob/user)
|
||||
if(ishuman(user) && Adjacent(user))
|
||||
toggle_paddles(user)
|
||||
|
||||
/obj/item/defibrillator/attackby__legacy__attackchain(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/stock_parts/cell))
|
||||
var/obj/item/stock_parts/cell/C = W
|
||||
if(cell)
|
||||
to_chat(user, "<span class='notice'>[src] already has a cell.</span>")
|
||||
else
|
||||
if(C.maxcharge < paddles.revivecost)
|
||||
to_chat(user, "<span class='notice'>[src] requires a higher capacity cell.</span>")
|
||||
return
|
||||
if(user.drop_item(C))
|
||||
W.forceMove(src)
|
||||
cell = C
|
||||
to_chat(user, "<span class='notice'>You install a cell in [src].</span>")
|
||||
if(W == paddles)
|
||||
toggle_paddles(user)
|
||||
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/item/defibrillator/screwdriver_act(mob/living/user, obj/item/I)
|
||||
if(!cell)
|
||||
to_chat(user, "<span class='notice'>[src] doesn't have a cell.</span>")
|
||||
return
|
||||
|
||||
cell.update_icon()
|
||||
cell.forceMove(get_turf(loc))
|
||||
cell = null
|
||||
to_chat(user, "<span class='notice'>You remove the cell from [src].</span>")
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
return TRUE
|
||||
|
||||
/obj/item/defibrillator/emp_act(severity)
|
||||
if(cell)
|
||||
deductcharge(1000 / severity)
|
||||
safety = !safety
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
..()
|
||||
|
||||
/obj/item/defibrillator/emag_act(mob/user)
|
||||
safety = !safety
|
||||
..()
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
return TRUE
|
||||
|
||||
/obj/item/defibrillator/proc/toggle_paddles(mob/living/carbon/human/user)
|
||||
if(user.stat || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED) || !Adjacent(user))
|
||||
return
|
||||
|
||||
if(paddles_on_defib)
|
||||
//Detach the paddles into the user's hands
|
||||
if(!user.put_in_hands(paddles))
|
||||
to_chat(user, "<span class='warning'>You need a free hand to hold the paddles!</span>")
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
return
|
||||
paddles.forceMove(user)
|
||||
paddles_on_defib = FALSE
|
||||
else if(user.is_in_active_hand(paddles))
|
||||
//Remove from their hands and back onto the defib unit
|
||||
remove_paddles(user)
|
||||
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
update_action_buttons()
|
||||
|
||||
/obj/item/defibrillator/equipped(mob/user, slot)
|
||||
..()
|
||||
if(slot != ITEM_SLOT_BACK)
|
||||
remove_paddles(user)
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/item/defibrillator/on_mob_move(dir, mob/user)
|
||||
if(paddles_on_defib)
|
||||
return
|
||||
|
||||
if(paddles.loc != user)
|
||||
remove_paddles(paddles.loc)
|
||||
|
||||
|
||||
/obj/item/defibrillator/item_action_slot_check(slot, mob/user)
|
||||
if(slot == ITEM_SLOT_BACK)
|
||||
return TRUE
|
||||
|
||||
/obj/item/defibrillator/proc/remove_paddles(mob/user) // from your hands
|
||||
var/mob/living/carbon/human/M = user
|
||||
if(paddles in get_both_hands(M))
|
||||
M.drop_item_to_ground(paddles)
|
||||
paddles_on_defib = TRUE
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
return
|
||||
|
||||
/obj/item/defibrillator/Destroy()
|
||||
if(!paddles_on_defib)
|
||||
var/M = get(paddles, /mob)
|
||||
remove_paddles(M)
|
||||
QDEL_NULL(paddles)
|
||||
QDEL_NULL(cell)
|
||||
return ..()
|
||||
|
||||
/obj/item/defibrillator/proc/deductcharge(chrgdeductamt)
|
||||
if(cell)
|
||||
if(cell.charge < (paddles.revivecost+chrgdeductamt))
|
||||
powered = FALSE
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
if(cell.use(chrgdeductamt))
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
return TRUE
|
||||
else
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
return FALSE
|
||||
|
||||
/obj/item/defibrillator/compact
|
||||
name = "compact defibrillator"
|
||||
desc = "A belt-mounted defibrillator that can be rapidly deployed."
|
||||
icon_state = "defibcompact"
|
||||
item_state = "defibcompact"
|
||||
sprite_sheets = null //Because Vox had the belt defibrillator sprites in back.dm
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
flags_2 = ALLOW_BELT_NO_JUMPSUIT_2
|
||||
origin_tech = "biotech=5"
|
||||
|
||||
/obj/item/defibrillator/compact/loaded/Initialize(mapload)
|
||||
. = ..()
|
||||
cell = new(src)
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/item/defibrillator/compact/item_action_slot_check(slot, mob/user)
|
||||
if(slot == ITEM_SLOT_BELT)
|
||||
return TRUE
|
||||
|
||||
/obj/item/defibrillator/compact/combat
|
||||
name = "combat defibrillator"
|
||||
desc = "A belt-mounted blood-red defibrillator that can be rapidly deployed. Does not have the restrictions or safeties of conventional defibrillators and can revive through space suits."
|
||||
icon_state = "defibcombat"
|
||||
item_state = "defibcombat"
|
||||
paddle_type = /obj/item/shockpaddles/syndicate
|
||||
combat = TRUE
|
||||
safety = FALSE
|
||||
heart_attack_probability = 100
|
||||
|
||||
/obj/item/defibrillator/compact/combat/loaded/Initialize(mapload)
|
||||
. = ..()
|
||||
cell = new(src)
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/item/defibrillator/compact/advanced
|
||||
name = "advanced compact defibrillator"
|
||||
desc = "A belt-mounted state-of-the-art defibrillator that can be rapidly deployed in all environments. The casing is EMP-shielded and heavily reinforced, making it immune to most sources of damage."
|
||||
icon_state = "defibnt"
|
||||
item_state = "defibnt"
|
||||
paddle_type = /obj/item/shockpaddles/advanced
|
||||
combat = TRUE
|
||||
hardened = TRUE // EMP-proof (on the component), but not emag-proof.
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF // Objective item, better not have it destroyed.
|
||||
heart_attack_probability = 10
|
||||
origin_tech = null
|
||||
/// To prevent spam from the emagging message on the advanced defibrillator.
|
||||
var/next_emp_message
|
||||
|
||||
/obj/item/defibrillator/compact/advanced/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>[src] uses an experimental self-charging cell, meaning that it will (probably) never stop working.</span>"
|
||||
. += "<span class='notice'>The advanced paddles can be used to defibrillate through space suits.</span>"
|
||||
|
||||
/obj/item/defibrillator/compact/advanced/examine_more(mob/user)
|
||||
. = ..()
|
||||
. += "The Advanced Compact Defibrillator is Nanotrasen Medical's greatest refinement of electroshock revival technology. Featuring heavy electromagnetic shielding and a reinforced plastitanium chassis, \
|
||||
it is both lightweight and extremely resistant to abuse, easily able to handle the most hostile of environments."
|
||||
. += ""
|
||||
. += "The two standout features of the ACD are the experimental self-charging power source - which gives it an effectively unlimited endurance - and the special breakdown paddles, \
|
||||
capable of transmitting a therapeutic shock through even thick hardsuit plating, allowing casualties to be revived without having to strip their equipment."
|
||||
. += ""
|
||||
. += "Whilst the ACD is currently too expensive for mass-market deployment, Nanotrasen hopes that later developments in its manufacturing capabilities will enable it to economically launch this product commercially."
|
||||
|
||||
/obj/item/defibrillator/compact/advanced/screwdriver_act(mob/living/user, obj/item/I)
|
||||
return // The cell is too strong roundstart and we dont want the adv defib to become useless
|
||||
|
||||
/obj/item/defibrillator/compact/advanced/loaded/Initialize(mapload)
|
||||
. = ..()
|
||||
cell = new /obj/item/stock_parts/cell/bluespace/charging(src)
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
AddElement(/datum/element/high_value_item)
|
||||
|
||||
/obj/item/defibrillator/compact/advanced/emp_act(severity)
|
||||
if(world.time > next_emp_message)
|
||||
atom_say("Warning: Electromagnetic pulse detected. Integrated shielding prevented all potential hardware damage.")
|
||||
playsound(src, 'sound/machines/defib_saftyon.ogg', 50)
|
||||
next_emp_message = world.time + 5 SECONDS
|
||||
|
||||
//paddles
|
||||
|
||||
/obj/item/shockpaddles
|
||||
name = "defibrillator paddles"
|
||||
desc = "A pair of plastic-gripped paddles with flat metal surfaces that are used to deliver powerful electric shocks."
|
||||
icon = 'icons/obj/defib.dmi'
|
||||
icon_state = "defibpaddles0"
|
||||
item_state = "defibpaddles0"
|
||||
throwforce = 6
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
resistance_flags = INDESTRUCTIBLE
|
||||
base_icon_state = "defibpaddles"
|
||||
/// Amount of power used on a shock.
|
||||
var/revivecost = 1000
|
||||
/// Active defib this is connected to.
|
||||
var/obj/item/defibrillator/defib
|
||||
/// Whether or not the paddles are on cooldown. Used for tracking icon states.
|
||||
var/on_cooldown = FALSE
|
||||
|
||||
|
||||
/obj/item/shockpaddles/New(mainunit)
|
||||
. = ..()
|
||||
|
||||
if(check_defib_exists(mainunit, null, src))
|
||||
defib = mainunit
|
||||
loc = defib
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
AddComponent(/datum/component/defib, actual_unit = defib, combat = defib.combat, safe_by_default = defib.safety, heart_attack_chance = defib.heart_attack_probability, emp_proof = defib.hardened, emag_proof = defib.emag_proof)
|
||||
else
|
||||
AddComponent(/datum/component/defib)
|
||||
RegisterSignal(src, COMSIG_DEFIB_READY, PROC_REF(on_cooldown_expire))
|
||||
RegisterSignal(src, COMSIG_DEFIB_SHOCK_APPLIED, PROC_REF(after_shock))
|
||||
RegisterSignal(src, COMSIG_DEFIB_PADDLES_APPLIED, PROC_REF(on_application))
|
||||
AddComponent(/datum/component/two_handed)
|
||||
|
||||
/obj/item/shockpaddles/Destroy()
|
||||
defib = null
|
||||
return ..()
|
||||
|
||||
/// Check to see if we should abort this before we've even gotten started
|
||||
/obj/item/shockpaddles/proc/on_application(obj/item/paddles, mob/living/user, mob/living/carbon/human/target, should_cause_harm)
|
||||
SIGNAL_HANDLER // COMSIG_DEFIB_PADDLES_APPLIED
|
||||
|
||||
if(!HAS_TRAIT(src, TRAIT_WIELDED))
|
||||
to_chat(user, "<span class='boldnotice'>You need to wield the paddles in both hands before you can use them on someone!</span>")
|
||||
return COMPONENT_BLOCK_DEFIB_MISC
|
||||
if(!defib.powered)
|
||||
return COMPONENT_BLOCK_DEFIB_DEAD
|
||||
|
||||
return
|
||||
|
||||
/obj/item/shockpaddles/proc/on_cooldown_expire(obj/item/paddles)
|
||||
SIGNAL_HANDLER // COMSIG_DEFIB_READY
|
||||
on_cooldown = FALSE
|
||||
if(defib.cell)
|
||||
if(defib.cell.charge >= revivecost)
|
||||
defib.visible_message("<span class='notice'>[defib] beeps: Unit ready.</span>")
|
||||
playsound(get_turf(src), 'sound/machines/defib_ready.ogg', 50, 0)
|
||||
else
|
||||
defib.visible_message("<span class='notice'>[defib] beeps: Charge depleted.</span>")
|
||||
playsound(get_turf(src), 'sound/machines/defib_failed.ogg', 50, 0)
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
defib.update_icon(UPDATE_ICON_STATE)
|
||||
|
||||
/obj/item/shockpaddles/proc/after_shock()
|
||||
SIGNAL_HANDLER // COMSIG_DEFIB_SHOCK_APPLIED
|
||||
on_cooldown = TRUE
|
||||
defib.deductcharge(revivecost)
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
|
||||
/obj/item/shockpaddles/update_icon_state()
|
||||
var/wielded = HAS_TRAIT(src, TRAIT_WIELDED)
|
||||
icon_state = "[base_icon_state][wielded]"
|
||||
item_state = "[base_icon_state][wielded]"
|
||||
if(on_cooldown)
|
||||
icon_state = "[base_icon_state][wielded]_cooldown"
|
||||
|
||||
/obj/item/shockpaddles/suicide_act(mob/user)
|
||||
user.visible_message("<span class='danger'>[user] is putting the live paddles on [user.p_their()] chest! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
defib.deductcharge(revivecost)
|
||||
playsound(get_turf(src), 'sound/machines/defib_zap.ogg', 50, TRUE, -1)
|
||||
return OXYLOSS
|
||||
|
||||
/obj/item/shockpaddles/dropped(mob/user)
|
||||
..()
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>The paddles snap back into the main unit.</span>")
|
||||
defib.paddles_on_defib = TRUE
|
||||
loc = defib
|
||||
defib.update_icon(UPDATE_OVERLAYS)
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
|
||||
/obj/item/shockpaddles/on_give(mob/living/carbon/giver, mob/living/carbon/receiver)
|
||||
|
||||
// This should be True, because action give calls drop() before this proc
|
||||
if(defib.paddles_on_defib)
|
||||
//Detach the paddles into the user's hands
|
||||
defib.paddles.forceMove(receiver)
|
||||
defib.paddles_on_defib = FALSE
|
||||
else if(receiver.is_in_active_hand(defib.paddles))
|
||||
//Remove from their hands and back onto the defib unit
|
||||
defib.remove_paddles(receiver)
|
||||
|
||||
defib.update_icon(UPDATE_OVERLAYS)
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
|
||||
// We call this to check if the receiver is outside the defib range
|
||||
// Otherwise, it can be placed anywhere on the map
|
||||
on_mob_move(null, receiver)
|
||||
|
||||
|
||||
/obj/item/shockpaddles/on_mob_move(dir, mob/user)
|
||||
if(defib)
|
||||
if(!isturf(user.loc))
|
||||
// You went inside something. It blocks the cable.
|
||||
// (This also means we don't have to listen for the
|
||||
// surrounding object's movements.)
|
||||
defib.remove_paddles(user)
|
||||
|
||||
var/turf/t = get_turf(defib)
|
||||
if(!t.Adjacent(user))
|
||||
defib.remove_paddles(user)
|
||||
|
||||
/obj/item/shockpaddles/proc/check_defib_exists(mainunit, mob/living/carbon/human/M, obj/O)
|
||||
if(!mainunit || !istype(mainunit, /obj/item/defibrillator)) //To avoid weird issues from admin spawns
|
||||
M?.unequip(O)
|
||||
qdel(O)
|
||||
return FALSE
|
||||
else
|
||||
return TRUE
|
||||
|
||||
/obj/item/borg_defib
|
||||
name = "defibrillator paddles"
|
||||
desc = "A pair of paddles with flat metal surfaces that are used to deliver powerful electric shocks."
|
||||
icon = 'icons/obj/defib.dmi'
|
||||
icon_state = "defibpaddles0"
|
||||
item_state = "defibpaddles0"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
var/revivecost = 1000
|
||||
var/safety = TRUE
|
||||
flags = NODROP
|
||||
|
||||
/obj/item/borg_defib/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/defib, robotic = TRUE, safe_by_default = safety, emp_proof = TRUE)
|
||||
|
||||
RegisterSignal(src, COMSIG_DEFIB_READY, PROC_REF(on_cooldown_expire))
|
||||
RegisterSignal(src, COMSIG_DEFIB_SHOCK_APPLIED, PROC_REF(after_shock))
|
||||
|
||||
/obj/item/borg_defib/proc/after_shock(obj/item/defib, mob/user)
|
||||
SIGNAL_HANDLER // COMSIG_DEFIB_SHOCK_APPLIED
|
||||
if(isrobot(user))
|
||||
var/mob/living/silicon/robot/R = user
|
||||
R.cell.use(revivecost)
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
|
||||
/obj/item/borg_defib/proc/on_cooldown_expire(obj/item/defib)
|
||||
SIGNAL_HANDLER // COMSIG_DEFIB_READY
|
||||
visible_message("<span class='notice'>[src] beeps: Defibrillation unit ready.</span>")
|
||||
playsound(get_turf(src), 'sound/machines/defib_ready.ogg', 50, 0)
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
|
||||
/obj/item/shockpaddles/syndicate
|
||||
name = "combat defibrillator paddles"
|
||||
desc = "A pair of high-tech paddles with flat plasteel surfaces to revive deceased operatives (unless they exploded). They possess both the ability to penetrate armor and to deliver powerful or disabling shocks offensively."
|
||||
icon_state = "syndiepaddles0"
|
||||
item_state = "syndiepaddles0"
|
||||
base_icon_state = "syndiepaddles"
|
||||
|
||||
/obj/item/shockpaddles/advanced
|
||||
name = "advanced defibrillator paddles"
|
||||
desc = "A pair of high-tech paddles with flat plasteel surfaces that are used to deliver powerful electric shocks. They possess the ability to penetrate armor to deliver shock."
|
||||
icon_state = "ntpaddles0"
|
||||
item_state = "ntpaddles0"
|
||||
base_icon_state = "ntpaddles"
|
||||
@@ -1,73 +0,0 @@
|
||||
/obj/item/disk
|
||||
icon = 'icons/obj/module.dmi'
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
item_state = "card-id"
|
||||
icon_state = "datadisk0"
|
||||
drop_sound = 'sound/items/handling/disk_drop.ogg'
|
||||
pickup_sound = 'sound/items/handling/disk_pickup.ogg'
|
||||
|
||||
/obj/item/disk/data
|
||||
name = "Cloning Data Disk"
|
||||
var/datum/dna2_record/buf = null
|
||||
var/read_only = FALSE //Well,it's still a floppy disk
|
||||
|
||||
/obj/item/disk/data/proc/initialize_data()
|
||||
buf = new
|
||||
buf.dna = new
|
||||
|
||||
/obj/item/disk/data/Destroy()
|
||||
QDEL_NULL(buf)
|
||||
return ..()
|
||||
|
||||
/obj/item/disk/data/demo
|
||||
name = "data disk - 'God Emperor of Mankind'"
|
||||
read_only = TRUE
|
||||
|
||||
/obj/item/disk/data/demo/New()
|
||||
. = ..()
|
||||
initialize_data()
|
||||
buf.types = DNA2_BUF_UE|DNA2_BUF_UI
|
||||
buf.dna.real_name = "God Emperor of Mankind"
|
||||
buf.dna.unique_enzymes = md5(buf.dna.real_name)
|
||||
buf.dna.UI = list(0x066,0x000,0x033,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0xAF0,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x033,0x066,0x0FF,0x4DB,0x002,0x690,0x000,0x000,0x000,0x328,0x045,0x5FC,0x053,0x035,0x035,0x035)
|
||||
if(length(buf.dna.UI) != DNA_UI_LENGTH) //If there's a disparity b/w the dna UI string lengths, 0-fill the extra blocks in this UI.
|
||||
for(var/i in length(buf.dna.UI) to DNA_UI_LENGTH)
|
||||
buf.dna.UI += 0x000
|
||||
buf.dna.ResetSE()
|
||||
buf.dna.UpdateUI()
|
||||
|
||||
/obj/item/disk/data/monkey
|
||||
name = "data disk - 'Mr. Muggles'"
|
||||
read_only = 1
|
||||
|
||||
/obj/item/disk/data/monkey/New()
|
||||
. = ..()
|
||||
initialize_data()
|
||||
buf.types = DNA2_BUF_SE
|
||||
var/list/new_SE = list(0x098,0x3E8,0x403,0x44C,0x39F,0x4B0,0x59D,0x514,0x5FC,0x578,0x5DC,0x640,0x6A4)
|
||||
for(var/i = length(new_SE); i <= DNA_SE_LENGTH; i++)
|
||||
new_SE += rand(1, 1024)
|
||||
buf.dna.SE = new_SE
|
||||
buf.dna.SetSEValueRange(GLOB.monkeyblock, 0xDAC, 0xFFF)
|
||||
|
||||
//Disk stuff.
|
||||
/obj/item/disk/data/New()
|
||||
. = ..()
|
||||
var/diskcolor = pick(0, 1, 2, 3, 4, 5)
|
||||
icon_state = "datadisk[diskcolor]"
|
||||
|
||||
/obj/item/disk/data/attack_self__legacy__attackchain(mob/user)
|
||||
read_only = !read_only
|
||||
to_chat(user, "You flip the write-protect tab to [read_only ? "protected" : "unprotected"].")
|
||||
|
||||
/obj/item/disk/data/examine(mob/user)
|
||||
. = ..()
|
||||
. += "The write-protect tab is set to [read_only ? "protected" : "unprotected"]."
|
||||
|
||||
/obj/item/storage/box/disks
|
||||
name = "Diskette Box"
|
||||
icon_state = "disk_box"
|
||||
|
||||
/obj/item/storage/box/disks/populate_contents()
|
||||
for(var/i in 1 to 7)
|
||||
new /obj/item/disk/data(src)
|
||||
@@ -1,607 +0,0 @@
|
||||
/obj/item/dnainjector
|
||||
name = "DNA-Injector"
|
||||
desc = "This injects the person with DNA."
|
||||
icon = 'icons/obj/medical.dmi'
|
||||
icon_state = "dnainjector"
|
||||
item_state = "dnainjector"
|
||||
belt_icon = "syringe"
|
||||
var/block = 0
|
||||
var/datum/dna2_record/buf = null
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
origin_tech = "biotech=1"
|
||||
|
||||
var/damage_coeff = 1
|
||||
var/used = FALSE
|
||||
|
||||
// USE ONLY IN PREMADE SYRINGES. WILL NOT WORK OTHERWISE.
|
||||
var/datatype = 0
|
||||
var/value = 0
|
||||
var/forcedmutation = FALSE //Will it give the mutation, guaranteed?
|
||||
|
||||
/obj/item/dnainjector/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
var/init_block = GetInitBlock()
|
||||
if(init_block)
|
||||
block = init_block
|
||||
|
||||
if(datatype && block)
|
||||
buf = new
|
||||
buf.dna = new
|
||||
buf.types = datatype
|
||||
buf.dna.ResetSE()
|
||||
SetValue(value)
|
||||
|
||||
// Override this with a var reference to do setup
|
||||
/obj/item/dnainjector/proc/GetInitBlock()
|
||||
return null
|
||||
|
||||
/obj/item/dnainjector/Destroy()
|
||||
QDEL_NULL(buf)
|
||||
return ..()
|
||||
|
||||
/obj/item/dnainjector/proc/GetRealBlock(selblock)
|
||||
if(selblock == 0)
|
||||
return block
|
||||
else
|
||||
return selblock
|
||||
|
||||
/obj/item/dnainjector/proc/GetState(selblock = 0)
|
||||
var/real_block = GetRealBlock(selblock)
|
||||
if(buf.types & DNA2_BUF_SE)
|
||||
return buf.dna.GetSEState(real_block)
|
||||
else
|
||||
return buf.dna.GetUIState(real_block)
|
||||
|
||||
/obj/item/dnainjector/proc/SetState(on, selblock = 0)
|
||||
var/real_block = GetRealBlock(selblock)
|
||||
if(buf.types & DNA2_BUF_SE)
|
||||
return buf.dna.SetSEState(real_block,on)
|
||||
else
|
||||
return buf.dna.SetUIState(real_block,on)
|
||||
|
||||
/obj/item/dnainjector/proc/GetValue(selblock = 0)
|
||||
var/real_block = GetRealBlock(selblock)
|
||||
if(buf.types & DNA2_BUF_SE)
|
||||
return buf.dna.GetSEValue(real_block)
|
||||
else
|
||||
return buf.dna.GetUIValue(real_block)
|
||||
|
||||
/obj/item/dnainjector/proc/SetValue(val, selblock = 0)
|
||||
var/real_block = GetRealBlock(selblock)
|
||||
if(buf.types & DNA2_BUF_SE)
|
||||
return buf.dna.SetSEValue(real_block,val)
|
||||
else
|
||||
return buf.dna.SetUIValue(real_block,val)
|
||||
|
||||
/obj/item/dnainjector/proc/inject(mob/living/M, mob/user)
|
||||
if(used)
|
||||
return
|
||||
if(isliving(M))
|
||||
M.apply_effect(rand(20 / (damage_coeff ** 2), 50 / (damage_coeff ** 2)), IRRADIATE)
|
||||
var/mob/living/carbon/human/H
|
||||
if(ishuman(M))
|
||||
H = M
|
||||
|
||||
if(!buf)
|
||||
stack_trace("[src] used by [user] on [M] failed to initialize properly.")
|
||||
return
|
||||
|
||||
spawn(0) //Some mutations have sleeps in them, like monkey
|
||||
if(!HAS_TRAIT(M, TRAIT_BADDNA) && !HAS_TRAIT(M, TRAIT_GENELESS)) // prevents drained people from having their DNA changed
|
||||
var/prev_ue = M.dna.unique_enzymes
|
||||
// UI in syringe.
|
||||
if(buf.types & DNA2_BUF_UI)
|
||||
if(!block) //isolated block?
|
||||
M.dna.UI = buf.dna.UI.Copy()
|
||||
M.dna.UpdateUI()
|
||||
M.UpdateAppearance()
|
||||
if(buf.types & DNA2_BUF_UE) //unique enzymes? yes
|
||||
|
||||
M.real_name = buf.dna.real_name
|
||||
M.name = buf.dna.real_name
|
||||
M.dna.real_name = buf.dna.real_name
|
||||
M.dna.unique_enzymes = buf.dna.unique_enzymes
|
||||
else
|
||||
M.dna.SetUIValue(block,src.GetValue())
|
||||
M.UpdateAppearance()
|
||||
if(buf.types & DNA2_BUF_SE)
|
||||
if(!block) //isolated block?
|
||||
M.dna.SE = buf.dna.SE.Copy()
|
||||
M.dna.UpdateSE()
|
||||
else
|
||||
M.dna.SetSEValue(block,src.GetValue())
|
||||
domutcheck(M, forcedmutation ? MUTCHK_FORCED : FALSE)
|
||||
M.update_mutations()
|
||||
if(H)
|
||||
H.sync_organ_dna(assimilate = 0, old_ue = prev_ue)
|
||||
|
||||
/obj/item/dnainjector/attack__legacy__attackchain(mob/M, mob/user)
|
||||
if(used)
|
||||
to_chat(user, "<span class='warning'>This injector is used up!</span>")
|
||||
return
|
||||
if(!M.dna || HAS_TRAIT(M, TRAIT_GENELESS) || HAS_TRAIT(M, TRAIT_BADDNA)) //You know what would be nice? If the mob you're injecting has DNA, and so doesn't cause runtimes.
|
||||
return FALSE
|
||||
|
||||
if(!user.IsAdvancedToolUser())
|
||||
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
|
||||
return FALSE
|
||||
|
||||
var/attack_log = "injected with the Isolated [name]"
|
||||
|
||||
if(buf && buf.types & DNA2_BUF_SE)
|
||||
if(block)
|
||||
if(GetState() && block == GLOB.monkeyblock && ishuman(M))
|
||||
attack_log = "injected with the Isolated [name] (MONKEY)"
|
||||
message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] <span class='warning'>(MONKEY)</span>")
|
||||
|
||||
else
|
||||
if(GetState(GLOB.monkeyblock) && ishuman(M))
|
||||
attack_log = "injected with the Isolated [name] (MONKEY)"
|
||||
message_admins("[key_name_admin(user)] injected [key_name_admin(M)] with the Isolated [name] <span class='warning'>(MONKEY)</span>")
|
||||
|
||||
|
||||
if(M != user)
|
||||
M.visible_message("<span class='danger'>[user] is trying to inject [M] with [src]!</span>", "<span class='userdanger'>[user] is trying to inject [M] with [src]!</span>")
|
||||
if(!do_mob(user, M))
|
||||
return
|
||||
M.visible_message("<span class='danger'>[user] injects [M] with the syringe with [src]!", \
|
||||
"<span class='userdanger'>[user] injects [M] with the syringe with [src]!")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You inject yourself with [src].</span>")
|
||||
|
||||
add_attack_logs(user, M, attack_log, ATKLOG_ALL)
|
||||
|
||||
inject(M, user)
|
||||
used = TRUE
|
||||
icon_state = "dnainjector0"
|
||||
desc += " This one is used up."
|
||||
|
||||
/obj/item/dnainjector/hulkmut
|
||||
name = "DNA-Injector (Hulk)"
|
||||
desc = "This will make you big and strong, but give you a bad skin condition."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/hulkmut/GetInitBlock()
|
||||
return GLOB.hulkblock
|
||||
|
||||
/obj/item/dnainjector/antihulk
|
||||
name = "DNA-Injector (Anti-Hulk)"
|
||||
desc = "Cures green skin."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antihulk/GetInitBlock()
|
||||
return GLOB.hulkblock
|
||||
|
||||
/obj/item/dnainjector/firemut
|
||||
name = "DNA-Injector (Fire)"
|
||||
desc = "Gives you fire."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/firemut/GetInitBlock()
|
||||
return GLOB.fireblock
|
||||
|
||||
/obj/item/dnainjector/antifire
|
||||
name = "DNA-Injector (Anti-Fire)"
|
||||
desc = "Cures fire."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antifire/GetInitBlock()
|
||||
return GLOB.fireblock
|
||||
|
||||
/obj/item/dnainjector/telemut
|
||||
name = "DNA-Injector (Tele.)"
|
||||
desc = "Super brain man!"
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/telemut/GetInitBlock()
|
||||
return GLOB.teleblock
|
||||
|
||||
/obj/item/dnainjector/telemut/darkbundle
|
||||
name = "DNA injector"
|
||||
desc = "Good. Let the hate flow through you."
|
||||
|
||||
/obj/item/dnainjector/antitele
|
||||
name = "DNA-Injector (Anti-Tele.)"
|
||||
desc = "Will make you not able to control your mind."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antitele/GetInitBlock()
|
||||
return GLOB.teleblock
|
||||
|
||||
/obj/item/dnainjector/nobreath
|
||||
name = "DNA-Injector (Breathless)"
|
||||
desc = "Hold your breath and count to infinity."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/nobreath/GetInitBlock()
|
||||
return GLOB.breathlessblock
|
||||
|
||||
/obj/item/dnainjector/antinobreath
|
||||
name = "DNA-Injector (Anti-Breathless)"
|
||||
desc = "Hold your breath and count to 100."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antinobreath/GetInitBlock()
|
||||
return GLOB.breathlessblock
|
||||
|
||||
/obj/item/dnainjector/remoteview
|
||||
name = "DNA-Injector (Remote View)"
|
||||
desc = "Stare into the distance for a reason."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/remoteview/GetInitBlock()
|
||||
return GLOB.remoteviewblock
|
||||
|
||||
/obj/item/dnainjector/antiremoteview
|
||||
name = "DNA-Injector (Anti-Remote View)"
|
||||
desc = "Cures green skin."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antiremoteview/GetInitBlock()
|
||||
return GLOB.remoteviewblock
|
||||
|
||||
/obj/item/dnainjector/regenerate
|
||||
name = "DNA-Injector (Regeneration)"
|
||||
desc = "Healthy but hungry."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/regenerate/GetInitBlock()
|
||||
return GLOB.regenerateblock
|
||||
|
||||
/obj/item/dnainjector/antiregenerate
|
||||
name = "DNA-Injector (Anti-Regeneration)"
|
||||
desc = "Sickly but sated."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antiregenerate/GetInitBlock()
|
||||
return GLOB.regenerateblock
|
||||
|
||||
/obj/item/dnainjector/morph
|
||||
name = "DNA-Injector (Morph)"
|
||||
desc = "A total makeover."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/morph/GetInitBlock()
|
||||
return GLOB.morphblock
|
||||
|
||||
/obj/item/dnainjector/antimorph
|
||||
name = "DNA-Injector (Anti-Morph)"
|
||||
desc = "Cures identity crisis."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antimorph/GetInitBlock()
|
||||
return GLOB.morphblock
|
||||
|
||||
/obj/item/dnainjector/noprints
|
||||
name = "DNA-Injector (No Prints)"
|
||||
desc = "Better than a pair of budget insulated gloves."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/noprints/GetInitBlock()
|
||||
return GLOB.noprintsblock
|
||||
|
||||
/obj/item/dnainjector/antinoprints
|
||||
name = "DNA-Injector (Anti-No Prints)"
|
||||
desc = "Not quite as good as a pair of budget insulated gloves."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antinoprints/GetInitBlock()
|
||||
return GLOB.noprintsblock
|
||||
|
||||
/obj/item/dnainjector/insulation
|
||||
name = "DNA-Injector (Shock Immunity)"
|
||||
desc = "Better than a pair of real insulated gloves."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/insulation/GetInitBlock()
|
||||
return GLOB.shockimmunityblock
|
||||
|
||||
/obj/item/dnainjector/antiinsulation
|
||||
name = "DNA-Injector (Anti-Shock Immunity)"
|
||||
desc = "Not quite as good as a pair of real insulated gloves."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antiinsulation/GetInitBlock()
|
||||
return GLOB.shockimmunityblock
|
||||
|
||||
/obj/item/dnainjector/small_size
|
||||
name = "DNA-Injector (Small Size)"
|
||||
desc = "Makes you shrink."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/small_size/GetInitBlock()
|
||||
return GLOB.smallsizeblock
|
||||
|
||||
/obj/item/dnainjector/anti_small_size
|
||||
name = "DNA-Injector (Anti-Small Size)"
|
||||
desc = "Makes you grow. But not too much."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/anti_small_size/GetInitBlock()
|
||||
return GLOB.smallsizeblock
|
||||
|
||||
/obj/item/dnainjector/eatmut
|
||||
name = "DNA-Injector (Matter Eater)"
|
||||
desc = "Gives you an appetite for anything."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/eatmut/GetInitBlock()
|
||||
return GLOB.eatblock
|
||||
|
||||
/obj/item/dnainjector/antieat
|
||||
name = "DNA-Injector (Anti-Matter Eater)"
|
||||
desc = "Makes you regain your normal appetite."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antieat/GetInitBlock()
|
||||
return GLOB.eatblock
|
||||
|
||||
/////////////////////////////////////
|
||||
/obj/item/dnainjector/antiglasses
|
||||
name = "DNA-Injector (Anti-Glasses)"
|
||||
desc = "Toss away those glasses!"
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antiglasses/GetInitBlock()
|
||||
return GLOB.glassesblock
|
||||
|
||||
/obj/item/dnainjector/glassesmut
|
||||
name = "DNA-Injector (Glasses)"
|
||||
desc = "Will make you need dorkish glasses."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/glassesmut/GetInitBlock()
|
||||
return GLOB.glassesblock
|
||||
|
||||
/obj/item/dnainjector/epimut
|
||||
name = "DNA-Injector (Epi.)"
|
||||
desc = "Shake shake shake the room!"
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/epimut/GetInitBlock()
|
||||
return GLOB.epilepsyblock
|
||||
|
||||
/obj/item/dnainjector/antiepi
|
||||
name = "DNA-Injector (Anti-Epi.)"
|
||||
desc = "Will fix you up from shaking the room."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antiepi/GetInitBlock()
|
||||
return GLOB.epilepsyblock
|
||||
|
||||
/obj/item/dnainjector/anticough
|
||||
name = "DNA-Injector (Anti-Cough)"
|
||||
desc = "Will stop that awful noise."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/anticough/GetInitBlock()
|
||||
return GLOB.coughblock
|
||||
|
||||
/obj/item/dnainjector/coughmut
|
||||
name = "DNA-Injector (Cough)"
|
||||
desc = "Will bring forth a sound of horror from your throat."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/coughmut/GetInitBlock()
|
||||
return GLOB.coughblock
|
||||
|
||||
/obj/item/dnainjector/clumsymut
|
||||
name = "DNA-Injector (Clumsy)"
|
||||
desc = "Makes clumsy minions."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/clumsymut/GetInitBlock()
|
||||
return GLOB.clumsyblock
|
||||
|
||||
/obj/item/dnainjector/anticlumsy
|
||||
name = "DNA-Injector (Anti-Clumy)"
|
||||
desc = "Cleans up confusion."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/anticlumsy/GetInitBlock()
|
||||
return GLOB.clumsyblock
|
||||
|
||||
/obj/item/dnainjector/stuttmut
|
||||
name = "DNA-Injector (Stutt.)"
|
||||
desc = "Makes you s-s-stuttterrr."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/stuttmut/GetInitBlock()
|
||||
return GLOB.nervousblock
|
||||
|
||||
|
||||
/obj/item/dnainjector/antistutt
|
||||
name = "DNA-Injector (Anti-Stutt.)"
|
||||
desc = "Fixes that speaking impairment."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antistutt/GetInitBlock()
|
||||
return GLOB.nervousblock
|
||||
|
||||
/obj/item/dnainjector/blindmut
|
||||
name = "DNA-Injector (Blind)"
|
||||
desc = "Makes you not see anything."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/blindmut/GetInitBlock()
|
||||
return GLOB.blindblock
|
||||
|
||||
/obj/item/dnainjector/antiblind
|
||||
name = "DNA-Injector (Anti-Blind)"
|
||||
desc = "ITS A MIRACLE!!!"
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antiblind/GetInitBlock()
|
||||
return GLOB.blindblock
|
||||
|
||||
/obj/item/dnainjector/paraplegicmut
|
||||
name = "DNA-Injector (Paraplegic)"
|
||||
desc = "Faceplanting, in needle form."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/paraplegicmut/GetInitBlock()
|
||||
return GLOB.paraplegicblock
|
||||
|
||||
/obj/item/dnainjector/antiparaplegic
|
||||
name = "DNA-Injector (Anti-Paraplegic)"
|
||||
desc = "Returns your legs to working order."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antiparaplegic/GetInitBlock()
|
||||
return GLOB.paraplegicblock
|
||||
|
||||
/obj/item/dnainjector/deafmut
|
||||
name = "DNA-Injector (Deaf)"
|
||||
desc = "Sorry, what did you say?"
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/deafmut/GetInitBlock()
|
||||
return GLOB.deafblock
|
||||
|
||||
/obj/item/dnainjector/antideaf
|
||||
name = "DNA-Injector (Anti-Deaf)"
|
||||
desc = "Will make you hear once more."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antideaf/GetInitBlock()
|
||||
return GLOB.deafblock
|
||||
|
||||
/obj/item/dnainjector/hallucination
|
||||
name = "DNA-Injector (Halluctination)"
|
||||
desc = "What you see isn't always what you get."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/hallucination/GetInitBlock()
|
||||
return GLOB.hallucinationblock
|
||||
|
||||
/obj/item/dnainjector/antihallucination
|
||||
name = "DNA-Injector (Anti-Hallucination)"
|
||||
desc = "What you see is what you get."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/antihallucination/GetInitBlock()
|
||||
return GLOB.hallucinationblock
|
||||
|
||||
/obj/item/dnainjector/h2m
|
||||
name = "DNA-Injector (Human > Monkey)"
|
||||
desc = "Will make you a flea bag."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/h2m/GetInitBlock()
|
||||
return GLOB.monkeyblock
|
||||
|
||||
/obj/item/dnainjector/m2h
|
||||
name = "DNA-Injector (Monkey > Human)"
|
||||
desc = "Will make you...less hairy."
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/m2h/GetInitBlock()
|
||||
return GLOB.monkeyblock
|
||||
|
||||
|
||||
/obj/item/dnainjector/comic
|
||||
name = "DNA-Injector (Comic)"
|
||||
desc = "Honk!"
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0xFFF
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/comic/GetInitBlock()
|
||||
return GLOB.comicblock
|
||||
|
||||
/obj/item/dnainjector/anticomic
|
||||
name = "DNA-Injector (Ant-Comic)"
|
||||
desc = "Honk...?"
|
||||
datatype = DNA2_BUF_SE
|
||||
value = 0x001
|
||||
forcedmutation = TRUE
|
||||
|
||||
/obj/item/dnainjector/anticomic/GetInitBlock()
|
||||
return GLOB.comicblock
|
||||
@@ -1,49 +0,0 @@
|
||||
/obj/item/dnascrambler
|
||||
name = "dna scrambler"
|
||||
desc = "An illegal genetic serum designed to randomize the user's identity."
|
||||
icon = 'icons/obj/hypo.dmi'
|
||||
item_state = "syringe_0"
|
||||
icon_state = "lepopen"
|
||||
var/used = FALSE
|
||||
|
||||
/obj/item/dnascrambler/update_icon_state()
|
||||
if(used)
|
||||
icon_state = "lepopen0"
|
||||
else
|
||||
icon_state = "lepopen"
|
||||
|
||||
/obj/item/dnascrambler/attack__legacy__attackchain(mob/M as mob, mob/user as mob)
|
||||
if(!M || !user)
|
||||
return
|
||||
|
||||
if(!ishuman(M) || !ishuman(user))
|
||||
return
|
||||
|
||||
if(used)
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(M, TRAIT_GENELESS))
|
||||
to_chat(user, "<span class='warning'>You failed to inject [M], as [M.p_they()] [M.p_have()] no DNA to scramble, nor flesh to inject.</span>")
|
||||
return
|
||||
|
||||
if(M == user)
|
||||
user.visible_message("<span class='danger'>[user] injects [user.p_themselves()] with [src]!</span>")
|
||||
injected(user, user)
|
||||
else
|
||||
user.visible_message("<span class='danger'>[user] is trying to inject [M] with [src]!</span>")
|
||||
if(do_mob(user,M,30))
|
||||
user.visible_message("<span class='danger'>[user] injects [M] with [src].</span>")
|
||||
injected(M, user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You failed to inject [M].</span>")
|
||||
|
||||
/obj/item/dnascrambler/proc/injected(mob/living/carbon/human/target, mob/living/carbon/user)
|
||||
if(istype(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
H.get_dna_scrambled()
|
||||
target.update_icons()
|
||||
|
||||
add_attack_logs(user, target, "injected with [src]")
|
||||
used = TRUE
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
name = "used " + name
|
||||
@@ -1,434 +0,0 @@
|
||||
// MARK: LIGHTERS
|
||||
/obj/item/lighter
|
||||
name = "cheap lighter"
|
||||
desc = "A cheap cigarette lighter. It gets the job done, barely."
|
||||
icon = 'icons/obj/lighter.dmi'
|
||||
lefthand_file = 'icons/mob/inhands/lighter_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/lighter_righthand.dmi'
|
||||
icon_state = "lighter-g"
|
||||
item_state = "lighter-g"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
flags = CONDUCT
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
attack_verb = null
|
||||
resistance_flags = FIRE_PROOF
|
||||
var/lit = FALSE
|
||||
/// Cooldown until the next turned on message/sound can be activated
|
||||
var/next_on_message
|
||||
/// Cooldown until the next turned off message/sound can be activated
|
||||
var/next_off_message
|
||||
/// Our lighter color suffix. => `[base_icon_state]-[lightercolor]` => `lighter-r`
|
||||
var/lighter_color
|
||||
var/is_a_zippo = FALSE
|
||||
|
||||
/obj/item/lighter/random
|
||||
base_icon_state = "lighter"
|
||||
|
||||
/obj/item/lighter/random/Initialize(mapload)
|
||||
. = ..()
|
||||
lighter_color = pick("r","c","y","g")
|
||||
update_icon()
|
||||
|
||||
/obj/item/lighter/attack_self__legacy__attackchain(mob/living/user)
|
||||
. = ..()
|
||||
if(!lit)
|
||||
turn_on_lighter(user)
|
||||
else
|
||||
turn_off_lighter(user)
|
||||
|
||||
/obj/item/lighter/can_enter_storage(obj/item/storage/S, mob/user)
|
||||
if(lit)
|
||||
to_chat(user, "<span class='warning'>[S] can't hold [src] while it's lit!</span>")
|
||||
return FALSE
|
||||
else
|
||||
return TRUE
|
||||
|
||||
/obj/item/lighter/proc/turn_on_lighter(mob/living/user)
|
||||
lit = TRUE
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
force = 5
|
||||
damtype = BURN
|
||||
hitsound = 'sound/items/welder.ogg'
|
||||
attack_verb = list("burnt", "singed")
|
||||
|
||||
update_icon()
|
||||
attempt_light(user)
|
||||
set_light(2)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/lighter/proc/attempt_light(mob/living/user)
|
||||
if(prob(75) || issilicon(user)) // Robots can never burn themselves trying to light it.
|
||||
to_chat(user, "<span class='notice'>You light [src].</span>")
|
||||
else if(HAS_TRAIT(user, TRAIT_BADASS))
|
||||
to_chat(user, "<span class='notice'>[src]'s flames lick your hand as you light it, but you don't flinch.</span>")
|
||||
else
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/obj/item/organ/external/affecting = H.get_organ("[user.hand ? "l" : "r" ]_hand")
|
||||
if(affecting.receive_damage(0, 5)) //INFERNO
|
||||
H.UpdateDamageIcon()
|
||||
to_chat(user,"<span class='notice'>You light [src], but you burn your hand in the process.</span>")
|
||||
if(world.time > next_on_message)
|
||||
playsound(src, 'sound/items/lighter/plastic_strike.ogg', 25, TRUE)
|
||||
next_on_message = world.time + 5 SECONDS
|
||||
|
||||
/obj/item/lighter/proc/turn_off_lighter(mob/living/user)
|
||||
lit = FALSE
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
hitsound = "swing_hit"
|
||||
force = 0
|
||||
attack_verb = null //human_defense.dm takes care of it
|
||||
damtype = initial(damtype)
|
||||
update_icon()
|
||||
if(user)
|
||||
show_off_message(user)
|
||||
set_light(0)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/lighter/extinguish_light(force)
|
||||
if(!force)
|
||||
return
|
||||
turn_off_lighter()
|
||||
|
||||
/obj/item/lighter/proc/show_off_message(mob/living/user)
|
||||
to_chat(user, "<span class='notice'>You shut off [src].")
|
||||
if(world.time > next_off_message)
|
||||
playsound(src, 'sound/items/lighter/plastic_close.ogg', 25, TRUE)
|
||||
next_off_message = world.time + 5 SECONDS
|
||||
|
||||
/obj/item/lighter/attack__legacy__attackchain(mob/living/target, mob/living/user)
|
||||
if(cigarette_lighter_act(user, target))
|
||||
return
|
||||
|
||||
if(lit && target.IgniteMob())
|
||||
message_admins("[key_name_admin(user)] set [key_name_admin(target)] on fire")
|
||||
log_game("[key_name(user)] set [key_name(target)] on fire")
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/lighter/cigarette_lighter_act(mob/living/user, mob/living/target, obj/item/direct_attackby_item)
|
||||
var/obj/item/clothing/mask/cigarette/cig = ..()
|
||||
// Otherwise the later parts of this proc can be passed to the zippo and cause a runtime.
|
||||
if(is_a_zippo)
|
||||
return cig
|
||||
|
||||
if(!cig)
|
||||
return !isnull(cig)
|
||||
|
||||
if(!lit)
|
||||
to_chat(user, "<span class='warning'>You need to light [src] before it can be used to light anything!</span>")
|
||||
return TRUE
|
||||
|
||||
if(target == user)
|
||||
user.visible_message(
|
||||
"<span class='notice'>After some fiddling, [user] manages to light [user.p_their()] [cig] with [src].</span>",
|
||||
"<span class='notice'>After some fiddling, you manage to light [cig] with [src].</span>,"
|
||||
)
|
||||
else
|
||||
user.visible_message(
|
||||
"<span class='notice'>After some fiddling, [user] manages to light [cig] for [target] with [src].</span>",
|
||||
"<span class='notice'>After some fiddling, you manage to light [cig] for [target] with [src].</span>"
|
||||
)
|
||||
cig.light(user, target)
|
||||
return TRUE
|
||||
|
||||
/obj/item/lighter/process()
|
||||
var/turf/location = get_turf(src)
|
||||
if(location)
|
||||
location.hotspot_expose(700, 1)
|
||||
return
|
||||
|
||||
/obj/item/lighter/update_icon_state()
|
||||
icon_state = "[base_icon_state ? "[base_icon_state]" : initial(icon_state)][lighter_color ? "-[lighter_color]" : ""][lit ? "-on" : ""]"
|
||||
|
||||
/obj/item/lighter/update_overlays()
|
||||
item_state = "[base_icon_state ? "[base_icon_state]" : initial(item_state)][lighter_color ? "-[lighter_color]" : ""][lit ? "-on" : ""]"
|
||||
|
||||
/obj/item/lighter/get_heat()
|
||||
return lit * 1500
|
||||
|
||||
// ZIPPO LIGHTERS
|
||||
|
||||
/obj/item/lighter/zippo
|
||||
name = "zippo lighter"
|
||||
desc = "A premium cigarette lighter, for cool and distinguished individuals."
|
||||
icon_state = "zippo"
|
||||
item_state = "zippo"
|
||||
is_a_zippo = TRUE
|
||||
throwforce = 4
|
||||
|
||||
/obj/item/lighter/zippo/turn_on_lighter(mob/living/user)
|
||||
. = ..()
|
||||
if(world.time > next_on_message)
|
||||
user.visible_message(
|
||||
"<span class='rose'>Without even breaking stride, [user] flips open and lights [src] in one smooth movement.</span>",
|
||||
"<span class='rose'>Without breaking your stride, you flip open and light [src] in one smooth movement.</span>",
|
||||
"<span class='rose'>You hear a zippo being lit.</span>"
|
||||
)
|
||||
playsound(src.loc, 'sound/items/zippolight.ogg', 25, TRUE)
|
||||
next_on_message = world.time + 5 SECONDS
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You light [src].</span>")
|
||||
|
||||
/obj/item/lighter/zippo/turn_off_lighter(mob/living/user)
|
||||
. = ..()
|
||||
if(!user)
|
||||
return
|
||||
|
||||
if(world.time > next_off_message)
|
||||
user.visible_message(
|
||||
"<span class='rose'>You hear a quiet click as [user] shuts off [src] without even looking at what [user.p_theyre()] doing. Wow.</span>",
|
||||
"<span class='rose'>You shut off [src] without even looking at what you're doing.</span>",
|
||||
"<span class='rose'>You hear a quiet click as a zippo lighter is shut off. Wow.</span>"
|
||||
)
|
||||
playsound(loc, 'sound/items/zippoclose.ogg', 25, TRUE)
|
||||
next_off_message = world.time + 5 SECONDS
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You shut off [src].</span>")
|
||||
|
||||
/obj/item/lighter/zippo/cigarette_lighter_act(mob/living/user, mob/living/target, obj/item/direct_attackby_item)
|
||||
var/obj/item/clothing/mask/cigarette/cig = ..()
|
||||
if(!cig)
|
||||
return !isnull(cig)
|
||||
|
||||
if(!lit)
|
||||
to_chat(user, "<span class='warning'>You need to light [src] before it can be used to light anything!</span>")
|
||||
return TRUE
|
||||
|
||||
if(target == user)
|
||||
user.visible_message(
|
||||
"<span class='rose'>With a single flick of [user.p_their()] wrist, [user] smoothly lights [user.p_their()] [cig.name] with [src]. Damn [user.p_theyre()] cool.</span>",
|
||||
"<span class='rose'>With a single flick of your wrist, you smoothly light [cig] with [src].</span>"
|
||||
)
|
||||
else
|
||||
user.visible_message(
|
||||
"<span class='rose'>[user] whips [src] out and holds it for [target]. [user.p_their(TRUE)] arm is as steady as the unflickering flame [user.p_they()] light [cig] with. Damn [user.p_theyre()] cool.</span>",
|
||||
"<span class='rose'>You whip [src] out and hold it for [target]. Your arm is as steady as the unflickering flame you light [cig] with.</span>"
|
||||
)
|
||||
cig.light(user, target)
|
||||
return TRUE
|
||||
|
||||
/obj/item/lighter/zippo/show_off_message(mob/living/user)
|
||||
return
|
||||
|
||||
/obj/item/lighter/zippo/attempt_light(mob/living/user)
|
||||
return
|
||||
|
||||
/obj/item/lighter/zippo/nt_rep
|
||||
name = "gold engraved zippo"
|
||||
desc = "An engraved golden Zippo lighter with the letters \"NT\" engraved on the sides."
|
||||
icon_state = "zippo-nt"
|
||||
item_state = "zippo-gold"
|
||||
|
||||
/obj/item/lighter/zippo/blue
|
||||
name = "blue zippo lighter"
|
||||
desc = "A zippo lighter made of some blue metal."
|
||||
icon_state = "zippo-blue"
|
||||
item_state = "zippo-blue"
|
||||
|
||||
/obj/item/lighter/zippo/black
|
||||
name = "black zippo lighter"
|
||||
desc = "A black zippo lighter."
|
||||
icon_state = "zippo-black"
|
||||
item_state = "zippo-black"
|
||||
|
||||
/obj/item/lighter/zippo/engraved
|
||||
name = "engraved zippo lighter"
|
||||
desc = "A intricately engraved zippo lighter."
|
||||
icon_state = "zippo-engraved"
|
||||
|
||||
/obj/item/lighter/zippo/gonzofist
|
||||
name = "Gonzo Fist zippo"
|
||||
desc = "A Zippo lighter with the iconic Gonzo Fist on a matte black finish."
|
||||
icon_state = "zippo-gonzo"
|
||||
item_state = "zippo-red"
|
||||
|
||||
// MARK: MATCHES
|
||||
|
||||
/obj/item/match
|
||||
name = "match"
|
||||
desc = "A simple match stick, used for lighting fine smokables."
|
||||
icon = 'icons/obj/cigarettes.dmi'
|
||||
icon_state = "match_unlit"
|
||||
var/lit = FALSE
|
||||
var/burnt = FALSE
|
||||
var/smoketime = 5
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
origin_tech = "materials=1"
|
||||
attack_verb = null
|
||||
var/is_unathi_fire = FALSE
|
||||
|
||||
/obj/item/match/process()
|
||||
var/turf/location = get_turf(src)
|
||||
smoketime--
|
||||
if(smoketime < 1)
|
||||
matchburnout()
|
||||
if(location)
|
||||
location.hotspot_expose(700, 1)
|
||||
return
|
||||
|
||||
/obj/item/match/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE)
|
||||
..()
|
||||
matchignite()
|
||||
|
||||
/obj/item/match/extinguish_light(force)
|
||||
if(!force)
|
||||
return
|
||||
matchburnout()
|
||||
|
||||
/obj/item/match/proc/matchignite()
|
||||
if(!lit && !burnt)
|
||||
lit = TRUE
|
||||
icon_state = "match_lit"
|
||||
damtype = "fire"
|
||||
force = 3
|
||||
hitsound = 'sound/items/welder.ogg'
|
||||
item_state = "cig_on"
|
||||
name = "lit match"
|
||||
desc = "A match. This one is lit."
|
||||
attack_verb = list("burnt","singed")
|
||||
START_PROCESSING(SSobj, src)
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/item/match/proc/matchburnout()
|
||||
if(lit)
|
||||
lit = FALSE
|
||||
burnt = TRUE
|
||||
damtype = "brute"
|
||||
force = initial(force)
|
||||
icon_state = "match_burnt"
|
||||
item_state = "cig_off"
|
||||
name = "burnt match"
|
||||
desc = "A match. This one has seen better days."
|
||||
attack_verb = list("flicked")
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return TRUE
|
||||
|
||||
/obj/item/match/dropped(mob/user)
|
||||
matchburnout()
|
||||
. = ..()
|
||||
|
||||
/obj/item/match/can_enter_storage(obj/item/storage/S, mob/user)
|
||||
if(lit)
|
||||
to_chat(user, "<span class='warning'>[S] can't hold [initial(name)] while it's lit!</span>") // initial(name) so it doesn't say "lit" twice in a row
|
||||
return FALSE
|
||||
else
|
||||
return TRUE
|
||||
|
||||
/obj/item/match/attack__legacy__attackchain(mob/living/target, mob/living/user)
|
||||
if(cigarette_lighter_act(user, target))
|
||||
return
|
||||
|
||||
if(lit && target.IgniteMob())
|
||||
message_admins("[key_name_admin(user)] set [key_name_admin(target)] on fire")
|
||||
log_game("[key_name(user)] set [key_name(target)] on fire")
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/match/cigarette_lighter_act(mob/living/user, mob/living/target, obj/item/direct_attackby_item)
|
||||
var/obj/item/clothing/mask/cigarette/cig = ..()
|
||||
|
||||
// Otherwise the later parts of this proc can be passed to the unathi's blaze and cause a runtime.
|
||||
if(is_unathi_fire)
|
||||
return cig
|
||||
|
||||
if(!cig)
|
||||
return !isnull(cig)
|
||||
|
||||
if(!lit)
|
||||
to_chat(user, "<span class='warning'>You need to light [src] before it can be used to light anything!</span>")
|
||||
return TRUE
|
||||
|
||||
if(target == user)
|
||||
user.visible_message(
|
||||
"<span class='notice'>[user] lights [user.p_their()] [cig] with [src].</span>",
|
||||
"<span class='notice'>You light [cig] with [src].</span>"
|
||||
)
|
||||
else
|
||||
user.visible_message(
|
||||
"<span class='notice'>[user] holds [src] out for [target], and lights [cig].</span>",
|
||||
"<span class='notice'>You hold [src] out for [target], and light [user.p_their()] [cig].</span>"
|
||||
)
|
||||
cig.light(user, target)
|
||||
matchburnout()
|
||||
return TRUE
|
||||
|
||||
/obj/item/match/decompile_act(obj/item/matter_decompiler/C, mob/user)
|
||||
if(isdrone(user) && burnt)
|
||||
C.stored_comms["wood"] += 1
|
||||
qdel(src)
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/item/match/get_heat()
|
||||
return lit * 1000
|
||||
|
||||
/obj/item/match/firebrand
|
||||
name = "firebrand"
|
||||
desc = "An unlit firebrand. It makes you wonder why it's not just called a stick."
|
||||
smoketime = 20 //40 seconds
|
||||
|
||||
/obj/item/match/firebrand/New()
|
||||
..()
|
||||
matchignite()
|
||||
|
||||
/obj/item/match/unathi
|
||||
name = "small blaze"
|
||||
desc = "A little flame of your own, currently located dangerously in your mouth."
|
||||
icon_state = "match_unathi"
|
||||
attack_verb = null
|
||||
flags = DROPDEL | ABSTRACT
|
||||
origin_tech = null
|
||||
lit = TRUE
|
||||
w_class = WEIGHT_CLASS_BULKY //to prevent it going to pockets
|
||||
is_unathi_fire = TRUE
|
||||
|
||||
/obj/item/match/unathi/cigarette_lighter_act(mob/living/target, mob/living/user, obj/item/direct_attackby_item)
|
||||
var/obj/item/clothing/mask/cigarette/cig = ..()
|
||||
if(!cig)
|
||||
return !isnull(cig)
|
||||
|
||||
if(!lit)
|
||||
to_chat(user, "<span class='userdanger'>If you can see this message, please make an issue report to GitHub, something bad has happened.</span>")
|
||||
return TRUE
|
||||
|
||||
if(target == user)
|
||||
user.visible_message(
|
||||
"<span class='rose'>[user] spits fire at [user.p_their()] [cig.name], igniting it.</span>",
|
||||
"<span class='rose'>You spit fire at [cig], igniting it.</span>",
|
||||
"<span class='warning'>You hear a brief burst of flame!</span>"
|
||||
)
|
||||
else
|
||||
if(prob(50))
|
||||
user.visible_message(
|
||||
"<span class='rose'>[user] spits fire at [target], lighting [cig] in [target.p_their()] mouth and nearly burning [target.p_their()] face!</span>",
|
||||
"<span class='rose'>You spit fire at [target], lighting [cig] in [target.p_their()] mouth and nearly burning [target.p_their()] face!</span>",
|
||||
"<span class='warning'>You hear a brief burst of flame!</span>"
|
||||
)
|
||||
else
|
||||
user.visible_message(
|
||||
"<span class='rose'>[user] spits fire at [target], burning [target.p_their()] face and lighting [cig] in the process!</span>",
|
||||
"<span class='rose'>You spit fire at [target], burning [target.p_their()] face and lighting [cig] in the process!</span>",
|
||||
"<span class='warning'>You hear a brief burst of flame!</span>"
|
||||
)
|
||||
var/obj/item/organ/external/head/affecting = target.get_organ("head")
|
||||
affecting.receive_damage(0, 5)
|
||||
target.UpdateDamageIcon()
|
||||
cig.light(user, target)
|
||||
playsound(user.loc, 'sound/effects/unathiignite.ogg', 40, FALSE)
|
||||
matchburnout()
|
||||
return TRUE
|
||||
|
||||
/obj/item/match/unathi/Initialize(mapload)
|
||||
. = ..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/match/unathi/matchburnout()
|
||||
if(!lit)
|
||||
return
|
||||
lit = FALSE //to avoid a qdel loop
|
||||
qdel(src)
|
||||
|
||||
/obj/item/match/unathi/Destroy()
|
||||
. = ..()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
@@ -1,67 +0,0 @@
|
||||
//NEVER USE THIS IT SUX -PETETHEGOAT
|
||||
|
||||
/obj/item/reagent_containers/glass/paint
|
||||
desc = "It's a paint bucket."
|
||||
name = "paint bucket"
|
||||
icon = 'icons/obj/paint.dmi'
|
||||
icon_state = "paint_neutral"
|
||||
item_state = "paintcan"
|
||||
materials = list(MAT_METAL = 400)
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
resistance_flags = FLAMMABLE
|
||||
max_integrity = 100
|
||||
amount_per_transfer_from_this = 5
|
||||
possible_transfer_amounts = list(5,10,20,30,50,70)
|
||||
volume = 70
|
||||
blocks_emissive = EMISSIVE_BLOCK_GENERIC
|
||||
|
||||
/obj/item/reagent_containers/glass/paint/interact_with_atom(atom/target, mob/living/user, list/modifiers)
|
||||
if(!is_open_container())
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
if(istype(target) && reagents.total_volume >= 5)
|
||||
user.visible_message("<span class='warning'>[target] has been splashed with something by [user]!</span>")
|
||||
spawn(5)
|
||||
reagents.reaction(target, REAGENT_TOUCH)
|
||||
reagents.remove_any(5)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/reagent_containers/glass/paint/red
|
||||
name = "red paint bucket"
|
||||
icon_state = "paint_red"
|
||||
list_reagents = list("paint_red" = 70)
|
||||
|
||||
/obj/item/reagent_containers/glass/paint/green
|
||||
name = "green paint bucket"
|
||||
icon_state = "paint_green"
|
||||
list_reagents = list("paint_green" = 70)
|
||||
|
||||
/obj/item/reagent_containers/glass/paint/blue
|
||||
name = "blue paint bucket"
|
||||
icon_state = "paint_blue"
|
||||
list_reagents = list("paint_blue" = 70)
|
||||
|
||||
/obj/item/reagent_containers/glass/paint/yellow
|
||||
name = "yellow paint bucket"
|
||||
icon_state = "paint_yellow"
|
||||
list_reagents = list("paint_yellow" = 70)
|
||||
|
||||
/obj/item/reagent_containers/glass/paint/violet
|
||||
name = "violet paint bucket"
|
||||
icon_state = "paint_violet"
|
||||
list_reagents = list("paint_violet" = 70)
|
||||
|
||||
/obj/item/reagent_containers/glass/paint/black
|
||||
name = "black paint bucket"
|
||||
icon_state = "paint_black"
|
||||
list_reagents = list("paint_black" = 70)
|
||||
|
||||
/obj/item/reagent_containers/glass/paint/white
|
||||
name = "white paint bucket"
|
||||
icon_state = "paint_white"
|
||||
list_reagents = list("paint_white" = 70)
|
||||
|
||||
/obj/item/reagent_containers/glass/paint/remover
|
||||
name = "paint remover bucket"
|
||||
list_reagents = list("paint_remover" = 70)
|
||||
@@ -1,11 +0,0 @@
|
||||
/obj/item/pai_cable/proc/plugin(obj/machinery/M as obj, mob/user as mob)
|
||||
if(isairlock(M) || istype(M, /obj/machinery/camera))
|
||||
user.visible_message("[user] inserts [src] into a data port on [M].", "You insert [src] into a data port on [M].", "You hear the satisfying click of a wire jack fastening into place.")
|
||||
user.drop_item()
|
||||
src.loc = M
|
||||
src.machine = M
|
||||
else
|
||||
user.visible_message("[user] dumbly fumbles to find a place on [M] to plug in [src].", "There aren't any ports on [M] that match the jack belonging to [src].")
|
||||
|
||||
/obj/item/pai_cable/attack__legacy__attackchain(obj/machinery/M as obj, mob/user as mob)
|
||||
src.plugin(M, user)
|
||||
@@ -1,120 +0,0 @@
|
||||
/obj/item/picket_sign
|
||||
name = "blank picket sign"
|
||||
desc = "It's blank."
|
||||
icon_state = "picket"
|
||||
item_state = "picket"
|
||||
force = 5
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
attack_verb = list("bashed","smacked")
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
new_attack_chain = TRUE
|
||||
|
||||
/// The cooldown tracking when we can next wave the sign
|
||||
COOLDOWN_DECLARE(wave_cooldown)
|
||||
/// What does the sign say?
|
||||
var/label = ""
|
||||
|
||||
/obj/item/picket_sign/attack_by(obj/item/attacking, mob/user, params)
|
||||
if(is_pen(attacking) || istype(attacking, /obj/item/toy/crayon))
|
||||
var/txt = tgui_input_text(user, "What would you like to write on the sign?", "Sign Label", max_length = 30)
|
||||
if(isnull(txt))
|
||||
return
|
||||
label = txt
|
||||
src.name = "[label] sign"
|
||||
desc = "It reads: [label]"
|
||||
..()
|
||||
|
||||
/obj/item/picket_sign/activate_self(mob/user)
|
||||
. = ..()
|
||||
if(!COOLDOWN_FINISHED(src, wave_cooldown))
|
||||
user.show_message("<span class='warning'>Your arm is too tired to do that again so soon!</span>")
|
||||
return
|
||||
|
||||
if(label)
|
||||
user.visible_message("<span class='notice'>[user] waves around \the \"[label]\" sign.</span>")
|
||||
else
|
||||
user.visible_message("<span class='notice'>[user] waves around blank sign.</span>")
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
COOLDOWN_START(src, wave_cooldown, 8 SECONDS)
|
||||
|
||||
/obj/item/picket_sign/after_attack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(user.a_intent != INTENT_HELP)
|
||||
return
|
||||
if(!isturf(target))
|
||||
return
|
||||
var/turf/target_turf = target
|
||||
if(target_turf == get_turf(user))
|
||||
to_chat(user, "<span class='notice'>You cannot place [src] under yourself.</span>")
|
||||
return
|
||||
if(locate(/obj/structure/custom_sign) in target_turf) // No putting signs on signs
|
||||
to_chat(user, "<span class='notice'>There's already a sign there!</span>")
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] starts to attach [src] to [target].</span>", "<span class='notice'>You start to attach [src] to [target].</span>")
|
||||
if(do_after(user, 2 SECONDS, target = target_turf))
|
||||
if(iswallturf(target))
|
||||
new /obj/structure/custom_sign/wall_sign(user.loc, label, get_dir(user, target_turf))
|
||||
else
|
||||
new /obj/structure/custom_sign(target_turf, label)
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/custom_sign
|
||||
name = "floor sign"
|
||||
anchored = TRUE
|
||||
max_integrity = 50
|
||||
icon_state = "floor_sign"
|
||||
/// What does the sign say?
|
||||
var/label = ""
|
||||
new_attack_chain = TRUE
|
||||
|
||||
/obj/structure/custom_sign/New(turf/loc, new_label)
|
||||
. = ..()
|
||||
if(new_label)
|
||||
change_label(new_label)
|
||||
|
||||
/obj/structure/custom_sign/item_interaction(mob/living/user, obj/item/used, list/modifiers)
|
||||
if(is_pen(used) || istype(used, /obj/item/toy/crayon))
|
||||
var/txt = tgui_input_text(user, "What would you like to write on the sign?", "Sign Label", max_length = 30)
|
||||
if(isnull(txt))
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
change_label(txt)
|
||||
add_fingerprint(user)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
..()
|
||||
|
||||
/obj/structure/custom_sign/proc/change_label(new_label)
|
||||
label = new_label
|
||||
name = "[new_label] sign"
|
||||
desc = "It reads: [new_label]"
|
||||
|
||||
/obj/structure/custom_sign/wrench_act(mob/living/user, obj/item/I)
|
||||
. = TRUE
|
||||
user.visible_message("<span class='notice'>[user] starts to detach [src].</span>", "<span class='notice'>You start to detach [src].</span>")
|
||||
if(!I.use_tool(src, user, 2 SECONDS, volume = I.tool_volume))
|
||||
return
|
||||
var/obj/item/picket_sign/picket = new /obj/item/picket_sign(loc)
|
||||
if(label)
|
||||
picket.label = label
|
||||
picket.name = "[label] sign"
|
||||
picket.desc = "It reads: [label]"
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/custom_sign/wall_sign
|
||||
name = "wall sign"
|
||||
icon_state = "wall_sign"
|
||||
|
||||
/obj/structure/custom_sign/wall_sign/New(turf/loc, new_label, direction)
|
||||
. = ..()
|
||||
// Offset 24 pixels in direction of dir. This allows the sign to be embedded in a wall
|
||||
setDir(direction)
|
||||
set_pixel_offsets_from_dir(24, -24, 24, -24)
|
||||
update_icon()
|
||||
|
||||
/datum/crafting_recipe/picket_sign
|
||||
name = "Picket Sign"
|
||||
result = list(/obj/item/picket_sign)
|
||||
reqs = list(/obj/item/stack/rods = 1,
|
||||
/obj/item/stack/sheet/cardboard = 2)
|
||||
time = 80
|
||||
category = CAT_MISC
|
||||
@@ -1,373 +0,0 @@
|
||||
/*Contains:
|
||||
Rapid Pipe Dispenser
|
||||
*/
|
||||
|
||||
#define RPD_COOLDOWN_TIME 4 //How long should we have to wait between dispensing pipes?
|
||||
#define RPD_WALLBUILD_TIME 40 //How long should drilling into a wall take?
|
||||
#define RPD_MENU_ROTATE "Rotate pipes" //Stuff for radial menu
|
||||
#define RPD_MENU_FLIP "Flip pipes" //Stuff for radial menu
|
||||
#define RPD_MENU_DELETE "Delete pipes" //Stuff for radial menu
|
||||
|
||||
/obj/item/rpd
|
||||
name = "rapid pipe dispenser"
|
||||
desc = "This device can rapidly dispense atmospherics and disposals piping, manipulate loose piping, and recycle any detached pipes it is applied to."
|
||||
icon = 'icons/obj/tools.dmi'
|
||||
icon_state = "rpd"
|
||||
flags = CONDUCT
|
||||
force = 10
|
||||
throwforce = 10
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
materials = list(MAT_METAL = 75000, MAT_GLASS = 37500)
|
||||
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 100, ACID = 50)
|
||||
resistance_flags = FIRE_PROOF
|
||||
origin_tech = "engineering=4;materials=2"
|
||||
var/datum/effect_system/spark_spread/spark_system
|
||||
var/lastused
|
||||
var/iconrotation = 0 //Used to orient icons and pipes
|
||||
var/mode = RPD_ATMOS_MODE //Disposals, atmospherics, etc.
|
||||
var/pipe_category = RPD_ATMOS_PIPING //For TGUI menus, this is a subtype of pipes e.g. scrubbers pipes, devices
|
||||
var/whatpipe = PIPE_SIMPLE_STRAIGHT //What kind of atmos pipe is it?
|
||||
var/whatdpipe = PIPE_DISPOSALS_STRAIGHT //What kind of disposals pipe is it?
|
||||
var/whatttube = PIPE_TRANSIT_TUBE
|
||||
var/spawndelay = RPD_COOLDOWN_TIME
|
||||
var/walldelay = RPD_WALLBUILD_TIME
|
||||
var/ranged = FALSE
|
||||
var/primary_sound = 'sound/machines/click.ogg'
|
||||
var/alt_sound = null
|
||||
var/auto_wrench_toggle = TRUE
|
||||
var/pipe_label = null
|
||||
|
||||
//Lists of things
|
||||
var/list/mainmenu = list(
|
||||
list("category" = "Atmospherics", "mode" = RPD_ATMOS_MODE, "icon" = "wrench"),
|
||||
list("category" = "Disposals", "mode" = RPD_DISPOSALS_MODE, "icon" = "recycle"),
|
||||
list("category" = "Transit", "mode" = RPD_TRANSIT_MODE, "icon" = "subway"),
|
||||
list("category" = "Rotate", "mode" = RPD_ROTATE_MODE, "icon" = "sync-alt"),
|
||||
list("category" = "Flip", "mode" = RPD_FLIP_MODE, "icon" = "arrows-alt-h"),
|
||||
list("category" = "Recycle", "mode" = RPD_DELETE_MODE, "icon" = "trash"))
|
||||
var/list/pipemenu = list(
|
||||
list("category" = "Normal", "pipemode" = RPD_ATMOS_PIPING),
|
||||
list("category" = "Supply", "pipemode" = RPD_SUPPLY_PIPING),
|
||||
list("category" = "Scrubber", "pipemode" = RPD_SCRUBBERS_PIPING),
|
||||
list("category" = "Devices", "pipemode" = RPD_DEVICES),
|
||||
list("category" = "Heat exchange", "pipemode" = RPD_HEAT_PIPING))
|
||||
|
||||
|
||||
/obj/item/rpd/Initialize(mapload)
|
||||
. = ..()
|
||||
spark_system = new /datum/effect_system/spark_spread()
|
||||
spark_system.set_up(1, 0, src)
|
||||
spark_system.attach(src)
|
||||
|
||||
/obj/item/rpd/Destroy()
|
||||
QDEL_NULL(spark_system)
|
||||
return ..()
|
||||
|
||||
/obj/item/rpd/bluespace
|
||||
name = "bluespace rapid pipe dispenser"
|
||||
desc = "This device can rapidly dispense atmospherics and disposals piping, manipulate loose piping, and recycle any detached pipes it is applied to, at any range."
|
||||
icon_state = "brpd"
|
||||
materials = list(MAT_METAL = 75000, MAT_GLASS = 37500, MAT_SILVER = 3000)
|
||||
origin_tech = "engineering=4;materials=2;bluespace=3"
|
||||
ranged = TRUE
|
||||
primary_sound = 'sound/items/PSHOOM.ogg'
|
||||
alt_sound = 'sound/items/PSHOOM_2.ogg'
|
||||
|
||||
//Procs
|
||||
|
||||
/obj/item/rpd/proc/activate_rpd(delay) //Maybe makes sparks and activates cooldown if there is a delay
|
||||
if(alt_sound && prob(3))
|
||||
playsound(src, alt_sound, 50, 1)
|
||||
else
|
||||
playsound(src, primary_sound, 50, 1)
|
||||
if(prob(15) && !ranged)
|
||||
spark_system.start()
|
||||
if(delay)
|
||||
lastused = world.time
|
||||
|
||||
/obj/item/rpd/proc/can_dispense_pipe(pipe_id, pipe_type) //Returns TRUE if this is a legit pipe we can dispense, otherwise returns FALSE
|
||||
for(var/list/L in GLOB.rpd_pipe_list)
|
||||
if(pipe_type != L["pipe_type"]) //Sometimes pipes in different categories have the same pipe_id, so we need to skip anything not in the category we want
|
||||
continue
|
||||
if(pipe_id == L["pipe_id"]) //Found the pipe, we can dispense it
|
||||
return TRUE
|
||||
|
||||
/obj/item/rpd/proc/create_atmos_pipe(mob/user, turf/T) //Make an atmos pipe, meter, or gas sensor
|
||||
if(!can_dispense_pipe(whatpipe, RPD_ATMOS_MODE))
|
||||
CRASH("Failed to spawn [get_pipe_name(whatpipe, PIPETYPE_ATMOS)] - possible tampering detected") //Damn dirty apes -- I mean hackers
|
||||
var/obj/item/pipe/P
|
||||
if(whatpipe == PIPE_GAS_SENSOR)
|
||||
P = new /obj/item/pipe_gsensor(T)
|
||||
else if(whatpipe == PIPE_METER)
|
||||
P = new /obj/item/pipe_meter(T)
|
||||
else
|
||||
P = new(T, whatpipe, iconrotation) //Make the pipe, BUT WAIT! There's more!
|
||||
if(!iconrotation && P.is_bent_pipe()) //Automatically rotates dispensed pipes if the user selected auto-rotation
|
||||
P.dir = turn(user.dir, 135)
|
||||
else if(!iconrotation && (P.pipe_type in list(PIPE_CONNECTOR, PIPE_UVENT, PIPE_SCRUBBER, PIPE_HEAT_EXCHANGE, PIPE_CAP, PIPE_SUPPLY_CAP, PIPE_SCRUBBERS_CAP, PIPE_INJECTOR, PIPE_PASV_VENT))) //Some pipes dispense oppositely to what you'd expect, but we don't want to do anything if they selected a direction
|
||||
P.dir = turn(user.dir, -180)
|
||||
else if(iconrotation && P.is_bent_pipe()) //If user selected a rotation and the pipe is bent
|
||||
P.dir = turn(iconrotation, -45)
|
||||
else if(!iconrotation) //If user selected a rotation
|
||||
P.dir = user.dir
|
||||
to_chat(user, "<span class='notice'>[src] rapidly dispenses [P]!</span>")
|
||||
P.label = pipe_label
|
||||
automatic_wrench_down(user, P)
|
||||
activate_rpd(TRUE)
|
||||
|
||||
/obj/item/rpd/proc/create_disposals_pipe(mob/user, turf/T) //Make a disposals pipe / construct
|
||||
if(!can_dispense_pipe(whatdpipe, RPD_DISPOSALS_MODE))
|
||||
CRASH("Failed to spawn [get_pipe_name(whatdpipe, PIPETYPE_DISPOSAL)] - possible tampering detected")
|
||||
var/obj/structure/disposalconstruct/P = new(T, whatdpipe, iconrotation)
|
||||
if(!iconrotation) //Automatic rotation
|
||||
P.dir = user.dir
|
||||
if(!iconrotation && whatdpipe != PIPE_DISPOSALS_JUNCTION_RIGHT) //Disposals pipes are in the opposite direction to atmos pipes, so we need to flip them. Junctions don't have this quirk though
|
||||
P.flip()
|
||||
to_chat(user, "<span class='notice'>[src] rapidly dispenses [P]!</span>")
|
||||
automatic_wrench_down(user, P)
|
||||
activate_rpd(TRUE)
|
||||
|
||||
/obj/item/rpd/proc/create_transit_tube(mob/user, turf/dest)
|
||||
if(!can_dispense_pipe(whatttube, PIPETYPE_TRANSIT))
|
||||
CRASH("Failed to spawn [get_pipe_name(whatttube, PIPETYPE_TRANSIT)] - possible tampering detected")
|
||||
|
||||
for(var/datum/pipes/transit/T in GLOB.construction_pipe_list)
|
||||
if(T.pipe_id == whatttube)
|
||||
var/obj/structure/transit_tube_construction/S = new T.construction_type(dest)
|
||||
if(!istype(S))
|
||||
CRASH("found [S] when constructing transit tube but expected /obj/structure/transit_tube_construction")
|
||||
|
||||
S.dir = iconrotation ? iconrotation : user.dir
|
||||
|
||||
to_chat(user, "<span class='notice'>[src] rapidly dispenses [S]!</span>")
|
||||
automatic_wrench_down(user, S)
|
||||
activate_rpd(TRUE)
|
||||
|
||||
/obj/item/rpd/proc/rotate_all_pipes(mob/user, turf/T) //Rotate all pipes on a turf
|
||||
for(var/obj/item/pipe/P in T)
|
||||
P.rotate()
|
||||
for(var/obj/structure/disposalconstruct/D in T)
|
||||
D.rotate()
|
||||
for(var/obj/structure/transit_tube_construction/tube in T)
|
||||
tube.rotate()
|
||||
|
||||
/obj/item/rpd/proc/flip_all_pipes(mob/user, turf/T) //Flip all pipes on a turf
|
||||
for(var/obj/item/pipe/P in T)
|
||||
P.flip()
|
||||
for(var/obj/structure/disposalconstruct/D in T)
|
||||
D.flip()
|
||||
for(var/obj/structure/transit_tube_construction/tube in T)
|
||||
tube.flip()
|
||||
|
||||
/obj/item/rpd/proc/delete_all_pipes(mob/user, turf/T) //Delete all pipes on a turf
|
||||
var/eaten
|
||||
for(var/obj/item/pipe/P in T)
|
||||
if(P.pipe_type == PIPE_CIRCULATOR) //Skip TEG heat circulators, they aren't really pipes
|
||||
continue
|
||||
QDEL_NULL(P)
|
||||
eaten = TRUE
|
||||
for(var/obj/item/pipe_gsensor/G in T)
|
||||
QDEL_NULL(G)
|
||||
eaten = TRUE
|
||||
for(var/obj/item/pipe_meter/M in T)
|
||||
QDEL_NULL(M)
|
||||
eaten = TRUE
|
||||
for(var/obj/structure/disposalconstruct/D in T)
|
||||
if(!D.anchored)
|
||||
QDEL_NULL(D)
|
||||
eaten = TRUE
|
||||
for(var/obj/structure/transit_tube_construction/C in T)
|
||||
QDEL_NULL(C)
|
||||
eaten = TRUE
|
||||
if(eaten)
|
||||
to_chat(user, "<span class='notice'>[src] sucks up the loose pipes on [T].")
|
||||
activate_rpd()
|
||||
else
|
||||
to_chat(user, "<span class='notice'>There were no loose pipes on [T].</span>")
|
||||
|
||||
/obj/item/rpd/proc/delete_single_pipe(mob/user, obj/P) //Delete a single pipe
|
||||
to_chat(user, "<span class='notice'>[src] sucks up [P].</span>")
|
||||
QDEL_NULL(P)
|
||||
activate_rpd()
|
||||
|
||||
/**
|
||||
* Automatically wrenches down an atmos device/pipe if the auto_wrench_toggle is TRUE.
|
||||
* Arguments:
|
||||
* * user - the user of the RPD.
|
||||
* * target - the pipe/device/tube being placed by the RPD.
|
||||
*/
|
||||
/obj/item/rpd/proc/automatic_wrench_down(mob/living/user, obj/item/target)
|
||||
if(!auto_wrench_toggle)
|
||||
return
|
||||
if(mode == RPD_TRANSIT_MODE)
|
||||
if(target.screwdriver_act(user, src) & RPD_TOOL_SUCCESS)
|
||||
playsound(src, 'sound/items/impactwrench.ogg', 50, TRUE)
|
||||
return
|
||||
if(target.wrench_act(user, src) & RPD_TOOL_SUCCESS)
|
||||
playsound(src, 'sound/items/impactwrench.ogg', 50, TRUE)
|
||||
return
|
||||
// TGUI stuff
|
||||
|
||||
/obj/item/rpd/attack_self__legacy__attackchain(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/item/rpd/ui_state(mob/user)
|
||||
return GLOB.inventory_state
|
||||
|
||||
/obj/item/rpd/ui_interact(mob/user, datum/tgui/ui = null)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "RPD", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/rpd/ui_assets(mob/user)
|
||||
return list(
|
||||
get_asset_datum(/datum/asset/spritesheet/rpd)
|
||||
)
|
||||
|
||||
/obj/item/rpd/AltClick(mob/user)
|
||||
radial_menu(user)
|
||||
|
||||
/obj/item/rpd/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["iconrotation"] = iconrotation
|
||||
data["mainmenu"] = mainmenu
|
||||
data["mode"] = mode
|
||||
data["pipelist"] = GLOB.rpd_pipe_list
|
||||
data["pipemenu"] = pipemenu
|
||||
data["pipe_category"] = pipe_category
|
||||
data["whatdpipe"] = whatdpipe
|
||||
data["whatpipe"] = whatpipe
|
||||
data["whatttube"] = whatttube
|
||||
data["auto_wrench_toggle"] = auto_wrench_toggle
|
||||
return data
|
||||
|
||||
/obj/item/rpd/ui_act(action, list/params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
. = TRUE
|
||||
|
||||
switch(action)
|
||||
if("iconrotation")
|
||||
iconrotation = isnum(params[action]) ? params[action] : text2num(params[action])
|
||||
if("whatpipe")
|
||||
whatpipe = isnum(params[action]) ? params[action] : text2num(params[action])
|
||||
if("whatdpipe")
|
||||
whatdpipe = isnum(params[action]) ? params[action] : text2num(params[action])
|
||||
if("whatttube")
|
||||
whatttube = isnum(params[action]) ? params[action] : text2num(params[action])
|
||||
if("pipe_category")
|
||||
pipe_category = isnum(params[action]) ? params[action] : text2num(params[action])
|
||||
if("mode")
|
||||
mode = isnum(params[action]) ? params[action] : text2num(params[action])
|
||||
if("auto_wrench_toggle")
|
||||
auto_wrench_toggle = !auto_wrench_toggle
|
||||
if("set_label")
|
||||
pipe_label = params[action]
|
||||
|
||||
//RPD radial menu
|
||||
/obj/item/rpd/proc/check_menu(mob/living/user)
|
||||
if(!istype(user))
|
||||
return
|
||||
if(user.incapacitated())
|
||||
return
|
||||
if(loc != user)
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/obj/item/rpd/proc/radial_menu(mob/user)
|
||||
if(!check_menu(user))
|
||||
to_chat(user, "<span class='notice'>You can't do that right now!</span>")
|
||||
return
|
||||
var/list/choices = list(
|
||||
RPD_MENU_ROTATE = image(icon = 'icons/obj/interface.dmi', icon_state = "rpd_rotate"),
|
||||
RPD_MENU_FLIP = image(icon = 'icons/obj/interface.dmi', icon_state = "rpd_flip"),
|
||||
RPD_MENU_DELETE = image(icon = 'icons/obj/interface.dmi', icon_state = "rpd_delete"),
|
||||
"UI" = image(icon = 'icons/obj/interface.dmi', icon_state = "ui_interact")
|
||||
)
|
||||
var/selected_mode = show_radial_menu(user, src, choices, custom_check = CALLBACK(src, PROC_REF(check_menu), user))
|
||||
if(!check_menu(user))
|
||||
return
|
||||
if(selected_mode == "UI")
|
||||
ui_interact(user)
|
||||
else
|
||||
switch(selected_mode)
|
||||
if(RPD_MENU_ROTATE)
|
||||
mode = RPD_ROTATE_MODE
|
||||
if(RPD_MENU_FLIP)
|
||||
mode = RPD_FLIP_MODE
|
||||
if(RPD_MENU_DELETE)
|
||||
mode = RPD_DELETE_MODE
|
||||
else
|
||||
return //Either nothing was selected, or an invalid mode was selected
|
||||
to_chat(user, "<span class='notice'>You set [src]'s mode.</span>")
|
||||
|
||||
/obj/item/rpd/afterattack__legacy__attackchain(atom/target, mob/user, proximity)
|
||||
..()
|
||||
if(isstorage(target))
|
||||
var/obj/item/storage/S = target
|
||||
if(!S.can_be_inserted(src, stop_messages = TRUE))
|
||||
return
|
||||
if(loc != user)
|
||||
return
|
||||
if(!proximity && !ranged)
|
||||
return
|
||||
if(world.time < lastused + spawndelay)
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(target)
|
||||
|
||||
if(!T)
|
||||
return
|
||||
|
||||
if(target != T)
|
||||
// We only check the rpd_act of the target if it isn't the turf, because otherwise
|
||||
// (A) blocked turfs can be acted on, and (B) unblocked turfs get acted on twice.
|
||||
if(target.rpd_act(user, src))
|
||||
// If the object we are clicking on has a valid RPD interaction for just that specific object, do that and nothing else.
|
||||
// Example: clicking on a pipe with a RPD in rotate mode should rotate that pipe and ignore everything else on the tile.
|
||||
if(ranged)
|
||||
user.Beam(T, icon_state="rped_upgrade", icon='icons/effects/effects.dmi', time=5)
|
||||
return
|
||||
|
||||
// If we get this far, we have to check every object in the tile, to make sure that none of them block RPD usage on this tile.
|
||||
// This is done by calling rpd_blocksusage on every /obj in the tile. If any block usage, fail at this point.
|
||||
|
||||
for(var/obj/O in T)
|
||||
if(O.rpd_blocksusage())
|
||||
to_chat(user, "<span class='warning'>[O] blocks [src]!</span>")
|
||||
return
|
||||
|
||||
// If we get here, then we're effectively acting on the turf, probably placing a pipe.
|
||||
if(ranged) //woosh beam if bluespaced at a distance
|
||||
if(get_dist(src, T) >= (user.client.maxview() / 2))
|
||||
message_admins("\[EXPLOIT] [key_name_admin(user)] attempted to place pipes with a BRPD via a camera console. (Attempted range exploit)")
|
||||
playsound(src, 'sound/machines/synth_no.ogg', 15, TRUE)
|
||||
to_chat(user, "<span class='notice'>ERROR: \The [T] is out of [src]'s range!</span>")
|
||||
return
|
||||
|
||||
if(!(user in hearers(12, T))) // Checks if user can hear the target turf, cause viewers doesnt work for it.
|
||||
to_chat(user, "<span class='warning'>[src] needs full visibility to determine the dispensing location.</span>")
|
||||
playsound(src, 'sound/machines/synth_no.ogg', 50, TRUE)
|
||||
return
|
||||
user.Beam(T, icon_state = "rped_upgrade", icon = 'icons/effects/effects.dmi', time = 0.5 SECONDS)
|
||||
T.rpd_act(user, src)
|
||||
|
||||
/obj/item/rpd/attack_obj__legacy__attackchain(obj/O, mob/living/user)
|
||||
if(user.a_intent != INTENT_HARM)
|
||||
if(istype(O, /obj/machinery/atmospherics/pipe))
|
||||
return
|
||||
else if(istype(O, /obj/structure/disposalconstruct))
|
||||
return
|
||||
else if(istype(O, /obj/structure/transit_tube_construction))
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
#undef RPD_COOLDOWN_TIME
|
||||
#undef RPD_WALLBUILD_TIME
|
||||
#undef RPD_MENU_ROTATE
|
||||
#undef RPD_MENU_FLIP
|
||||
#undef RPD_MENU_DELETE
|
||||
@@ -1,75 +0,0 @@
|
||||
/obj/item/teleportation_scroll
|
||||
name = "scroll of teleportation"
|
||||
desc = "A scroll for moving around."
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "scroll"
|
||||
var/uses = 4
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
item_state = "paper"
|
||||
throw_speed = 4
|
||||
throw_range = 20
|
||||
origin_tech = "bluespace=6"
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
/obj/item/teleportation_scroll/apprentice
|
||||
name = "lesser scroll of teleportation"
|
||||
uses = 1
|
||||
origin_tech = "bluespace=5"
|
||||
|
||||
/obj/item/teleportation_scroll/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class='notice'>Number of uses: [uses]. This scroll will vanish after the final use.</span>"
|
||||
. += "<span class='notice'>P.S. Don't forget to bring your gear, you'll need it to cast most spells.</span>"
|
||||
|
||||
/obj/item/teleportation_scroll/attack_self__legacy__attackchain(mob/living/user)
|
||||
if(!uses) //somehow?
|
||||
to_chat(user, "<span class='warning'>You attempt to read the scroll but it disintegrates in your hand, it appears that is has run out of charges!</span>")
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
var/picked_area
|
||||
picked_area = tgui_input_list(user, "Area to jump to", "Teleport where?", SSmapping.teleportlocs)
|
||||
if(!picked_area)
|
||||
return
|
||||
|
||||
var/area/thearea = SSmapping.teleportlocs[picked_area]
|
||||
if(user.stat || user.restrained())
|
||||
return
|
||||
|
||||
if(!(user == loc || (in_range(src, user) && isturf(user.loc))))
|
||||
return //They can't use it if they put it in their bag or drop it and walk off, but if they are stood next to it they can.
|
||||
|
||||
if(thearea.tele_proof && !istype(thearea, /area/wizard_station)) //Nowhere in SSmapping.teleportlocs should be tele_proof, but better safe than sorry
|
||||
to_chat(user, "<span class='warning'>A mysterious force disrupts your arcane spell matrix, and you remain where you are.</span>")
|
||||
return
|
||||
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(5, FALSE, get_turf(user))
|
||||
smoke.attach(user)
|
||||
smoke.start()
|
||||
var/list/L = list()
|
||||
|
||||
for(var/turf/T in get_area_turfs(thearea.type))
|
||||
if(T.is_blocked_turf())
|
||||
continue
|
||||
L.Add(T)
|
||||
|
||||
if(!length(L))
|
||||
to_chat(user, "<span class='warning'>The spell matrix was unable to locate a suitable teleport destination for an unknown reason. Sorry.</span>")
|
||||
return
|
||||
|
||||
if(user && user.buckled)
|
||||
user.unbuckle(force = TRUE)
|
||||
|
||||
if(user?.has_buckled_mobs())
|
||||
user.unbuckle_all_mobs(force = TRUE)
|
||||
|
||||
user.forceMove(pick(L))
|
||||
smoke.start()
|
||||
uses--
|
||||
|
||||
if(!uses)
|
||||
to_chat(user, "<span class='warning'>The scroll fizzles out of existence as the last of the magic within fades.</span>")
|
||||
qdel(src)
|
||||
|
||||
user.update_action_buttons_icon() //Update action buttons as some spells might now be castable
|
||||
@@ -1,125 +0,0 @@
|
||||
/obj/item/soap
|
||||
name = "soap"
|
||||
desc = "A cheap bar of soap. Doesn't smell."
|
||||
gender = PLURAL
|
||||
icon = 'icons/obj/janitor.dmi'
|
||||
icon_state = "soap"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi'
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
throw_speed = 4
|
||||
throw_range = 20
|
||||
discrete = 1
|
||||
var/cleanspeed = 50 //slower than mop
|
||||
var/times_eaten = 0 //How many times a Drask has chewed on this bar of soap
|
||||
var/max_bites = 30 //The maximum amount of bites before the soap is depleted
|
||||
|
||||
/obj/item/soap/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/slippery, src, 8 SECONDS, 100, 0, FALSE)
|
||||
|
||||
/obj/item/soap/afterattack__legacy__attackchain(atom/target, mob/user, proximity)
|
||||
if(!proximity)
|
||||
return
|
||||
if(user.zone_selected == "mouth" && ishuman(target)) // cleaning out someone's mouth is a different act
|
||||
return
|
||||
if(target == user && user.a_intent == INTENT_GRAB && ishuman(target))
|
||||
var/mob/living/carbon/human/muncher = user
|
||||
if(muncher && isdrask(muncher))
|
||||
eat_soap(muncher)
|
||||
return
|
||||
target.cleaning_act(user, src, cleanspeed)
|
||||
|
||||
/obj/item/soap/add_blood(list/blood_dna, b_color)
|
||||
return
|
||||
|
||||
/obj/item/soap/proc/eat_soap(mob/living/carbon/human/drask/user)
|
||||
times_eaten++
|
||||
playsound(user.loc, 'sound/items/eatfood.ogg', 50, 0)
|
||||
user.adjust_nutrition(5)
|
||||
user.reagents.add_reagent("soapreagent", 3)
|
||||
if(times_eaten < max_bites)
|
||||
to_chat(user, "<span class='notice'>You take a bite of [src]. Delicious!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You finish eating [src].</span>")
|
||||
qdel(src)
|
||||
|
||||
/obj/item/soap/examine(mob/user)
|
||||
. = ..()
|
||||
if(!user.Adjacent(src) || !times_eaten)
|
||||
return
|
||||
if(times_eaten < (max_bites * 0.3))
|
||||
. += "<span class='notice'>[src] has bite marks on it!</span>"
|
||||
else if(times_eaten < (max_bites * 0.6))
|
||||
. += "<span class='notice'>Big chunks of [src] have been chewed off!</span>"
|
||||
else if(times_eaten < (max_bites * 0.9))
|
||||
. += "<span class='notice'>Most of [src] has been gnawed away!</span>"
|
||||
else
|
||||
. += "<span class='notice'>[src] has been eaten down to a sliver!</span>"
|
||||
|
||||
/obj/item/soap/attack__legacy__attackchain(mob/target as mob, mob/user as mob)
|
||||
if(target && user && ishuman(target) && ishuman(user) && !target.stat && !user.stat && user.zone_selected == "mouth")
|
||||
user.visible_message("<span class='warning'>[user] starts washing [target]'s mouth out with [name]!</span>")
|
||||
if(do_after(user, cleanspeed, target = target))
|
||||
user.visible_message("<span class='warning'>[user] washes [target]'s mouth out with [name]!</span>")
|
||||
target.reagents.add_reagent("soapreagent", 6)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/soap/can_clean()
|
||||
return TRUE
|
||||
|
||||
/obj/item/soap/nanotrasen
|
||||
desc = "A Nanotrasen brand bar of soap. Smells of plasma."
|
||||
icon_state = "soapnt"
|
||||
|
||||
/obj/item/soap/homemade
|
||||
desc = "A homemade bar of soap. Smells of... well...."
|
||||
icon_state = "soaphome"
|
||||
cleanspeed = 45 // a little faster to reward chemists for going to the effort
|
||||
|
||||
/obj/item/soap/ducttape
|
||||
desc = "A homemade bar of soap. It seems to be gibs and tape..Will this clean anything?"
|
||||
icon_state = "soapgibs"
|
||||
|
||||
/obj/item/soap/ducttape/afterattack__legacy__attackchain(atom/target, mob/user as mob, proximity)
|
||||
if(!proximity) return
|
||||
|
||||
if(user.client && (target in user.client.screen))
|
||||
to_chat(user, "<span class='notice'>You need to take that [target.name] off before 'cleaning' it.</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] begins to smear [src] on \the [target.name].</span>")
|
||||
if(do_after(user, cleanspeed, target = target))
|
||||
to_chat(user, "<span class='notice'>You 'clean' \the [target.name].</span>")
|
||||
if(issimulatedturf(target))
|
||||
new /obj/effect/decal/cleanable/blood/gibs/cleangibs(target)
|
||||
else if(iscarbon(target))
|
||||
for(var/obj/item/carried_item in target.contents)
|
||||
if(!istype(carried_item, /obj/item/bio_chip))//If it's not an implant.
|
||||
carried_item.add_mob_blood(target)//Oh yes, there will be blood...
|
||||
var/mob/living/carbon/human/H = target
|
||||
H.make_bloody_hands(H.get_blood_dna_list(), H.get_blood_color(), 0)
|
||||
H.bloody_body(target)
|
||||
|
||||
return
|
||||
|
||||
/obj/item/soap/deluxe
|
||||
desc = "A luxury bar of soap. Smells of honey."
|
||||
icon_state = "soapdeluxe"
|
||||
cleanspeed = 40 //slightly better because deluxe -- captain gets one of these
|
||||
|
||||
/obj/item/soap/deluxe/laundry
|
||||
name = "laundry soap"
|
||||
desc = "Very cheap but effective soap. Dries out the skin."
|
||||
icon_state = "soapsoviet"
|
||||
|
||||
/obj/item/soap/syndie
|
||||
desc = "An untrustworthy bar of soap made of strong chemical agents that dissolve blood faster."
|
||||
icon_state = "soapsyndie"
|
||||
cleanspeed = 10 //much faster than mop so it is useful for traitors who want to clean crime scenes
|
||||
|
||||
/obj/item/soap/ds
|
||||
desc = "A very intimidating, jet-black bar of soap with a skull embossed on the top. Whatever this thing is made of, it can clean any mess in the blink of an eye."
|
||||
icon_state = "soapds"
|
||||
cleanspeed = 5
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
/obj/item/staff
|
||||
name = "wizards staff"
|
||||
desc = "Apparently a staff used by the wizard."
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "staff"
|
||||
lefthand_file = 'icons/mob/inhands/staves_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/staves_righthand.dmi'
|
||||
force = 3.0
|
||||
throwforce = 5.0
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
armour_penetration_percentage = 100
|
||||
attack_verb = list("bludgeoned", "whacked", "disciplined")
|
||||
resistance_flags = FLAMMABLE
|
||||
|
||||
/obj/item/staff/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/two_handed)
|
||||
|
||||
/obj/item/staff/broom
|
||||
name = "broom"
|
||||
desc = "Used for sweeping, and flying into the night while cackling. Black cat not included."
|
||||
icon_state = "broom"
|
||||
item_state = "broom0"
|
||||
|
||||
/obj/item/staff/broom/Initialize(mapload)
|
||||
. = ..()
|
||||
AddComponent(/datum/component/two_handed, force_wielded = 5, force_unwielded = 3, wield_callback = CALLBACK(src, PROC_REF(wield)), unwield_callback = CALLBACK(src, PROC_REF(unwield)))
|
||||
|
||||
/obj/item/staff/broom/proc/wield(obj/item/source, mob/user)
|
||||
attack_verb = list("rammed into", "charged at")
|
||||
user.update_inv_l_hand()
|
||||
user.update_inv_r_hand()
|
||||
if(iswizard(user))
|
||||
ADD_TRAIT(user, TRAIT_FLYING, "broomstick")
|
||||
user.say("QUID 'ITCH")
|
||||
animate(user, pixel_y = pixel_y + 10 , time = 10, loop = 1, easing = SINE_EASING)
|
||||
to_chat(user, "<span class='notice'>You hold [src] between your legs.</span>")
|
||||
|
||||
/obj/item/staff/broom/proc/unwield(obj/item/source, mob/user)
|
||||
attack_verb = list("bludgeoned", "whacked", "cleaned")
|
||||
user.update_inv_l_hand()
|
||||
user.update_inv_r_hand()
|
||||
if(iswizard(user))
|
||||
REMOVE_TRAIT(user, TRAIT_FLYING, "broomstick")
|
||||
animate(user, pixel_y = pixel_y + 10 , time = 1, loop = 1)
|
||||
animate(user, pixel_y = pixel_y, time = 10, loop = 1, easing = SINE_EASING)
|
||||
animate(user)
|
||||
|
||||
/obj/item/staff/broom/attackby__legacy__attackchain(obj/O, mob/user)
|
||||
if(istype(O, /obj/item/clothing/mask/horsehead))
|
||||
new/obj/item/staff/broom/horsebroom(get_turf(src))
|
||||
user.unequip(O)
|
||||
qdel(O)
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/staff/broom/dropped(mob/user)
|
||||
REMOVE_TRAIT(user, TRAIT_FLYING, "broomstick")
|
||||
..()
|
||||
|
||||
/obj/item/staff/broom/horsebroom
|
||||
name = "broomstick horse"
|
||||
desc = "Saddle up!"
|
||||
icon_state = "horsebroom"
|
||||
item_state = "horsebroom0"
|
||||
|
||||
/obj/item/staff/broom/horsebroom/attack_self__legacy__attackchain(mob/user as mob)
|
||||
..()
|
||||
item_state = "horsebroom[HAS_TRAIT(src, TRAIT_WIELDED) ? 1 : 0]"
|
||||
|
||||
@@ -1,288 +0,0 @@
|
||||
////////////////////////////////////////
|
||||
// MARK: RPEDs
|
||||
////////////////////////////////////////
|
||||
/obj/item/storage/part_replacer
|
||||
name = "Rapid Part Exchange Device"
|
||||
desc = "Special mechanical module made to store, sort, and apply standard machine parts."
|
||||
icon_state = "RPED"
|
||||
item_state = "RPED"
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
can_hold = list(
|
||||
/obj/item/stock_parts,
|
||||
// This type is part of can_hold, but is added separately in Initialize to avoid picking up unwanted subtypes.
|
||||
// /obj/item/reagent_containers/glass/beaker,
|
||||
/obj/item/reagent_containers/glass/beaker/large,
|
||||
/obj/item/reagent_containers/glass/beaker/bluespace
|
||||
)
|
||||
storage_slots = 50
|
||||
use_to_pickup = TRUE
|
||||
allow_quick_gather = TRUE
|
||||
allow_quick_empty = TRUE
|
||||
display_contents_with_number = TRUE
|
||||
max_w_class = WEIGHT_CLASS_NORMAL
|
||||
max_combined_w_class = 100
|
||||
usesound = 'sound/items/rped.ogg'
|
||||
var/works_from_distance = FALSE
|
||||
var/primary_sound = 'sound/items/rped.ogg'
|
||||
var/alt_sound = null
|
||||
|
||||
/obj/item/storage/part_replacer/Initialize(mapload)
|
||||
. = ..()
|
||||
can_hold[/obj/item/reagent_containers/glass/beaker] = TRUE
|
||||
|
||||
/obj/item/storage/part_replacer/can_be_inserted(obj/item/I, stop_messages = FALSE)
|
||||
if(!istype(I, /obj/item/reagent_containers/glass/beaker))
|
||||
return ..()
|
||||
|
||||
var/obj/item/reagent_containers/glass/beaker/B = I
|
||||
if(B.reagents?.total_volume)
|
||||
if(!stop_messages)
|
||||
to_chat(usr, "<span class='warning'>[src] cannot hold [I] while it contains liquid.</span>")
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/obj/item/storage/part_replacer/afterattack__legacy__attackchain(obj/machinery/M, mob/user, proximity_flag, params)
|
||||
if(!istype(M))
|
||||
return ..()
|
||||
|
||||
if(!proximity_flag)
|
||||
if(!works_from_distance)
|
||||
return
|
||||
if(get_dist(user, M) > (user.client.maxview() / 2))
|
||||
message_admins("\[EXPLOIT] [key_name_admin(user)] attempted to upgrade machinery with a BRPED via a camera console (attempted range exploit).")
|
||||
playsound(src, 'sound/machines/synth_no.ogg', 15, TRUE)
|
||||
to_chat(user, "<span class='notice'>ERROR: [M] is out of [src]'s range!</span>")
|
||||
return
|
||||
|
||||
if(M.component_parts)
|
||||
M.exchange_parts(user, src)
|
||||
if(works_from_distance)
|
||||
user.Beam(M, icon_state="rped_upgrade", icon='icons/effects/effects.dmi', time=5)
|
||||
|
||||
/obj/item/storage/part_replacer/tier4/populate_contents()
|
||||
for(var/amount in 1 to 30)
|
||||
new /obj/item/stock_parts/capacitor/quadratic(src)
|
||||
new /obj/item/stock_parts/manipulator/femto(src)
|
||||
new /obj/item/stock_parts/matter_bin/bluespace(src)
|
||||
new /obj/item/stock_parts/micro_laser/quadultra(src)
|
||||
new /obj/item/stock_parts/scanning_module/triphasic(src)
|
||||
new /obj/item/stock_parts/cell/bluespace(src)
|
||||
new /obj/item/reagent_containers/glass/beaker/bluespace(src)
|
||||
|
||||
////////////////////////////////////////
|
||||
// Bluespace Part Replacer
|
||||
////////////////////////////////////////
|
||||
/obj/item/storage/part_replacer/bluespace
|
||||
name = "bluespace rapid part exchange device"
|
||||
desc = "A version of the RPED that allows for replacement of parts and scanning from a distance, along with higher capacity for parts."
|
||||
icon_state = "BS_RPED"
|
||||
item_state = "BS_RPED"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
storage_slots = 400
|
||||
max_combined_w_class = 800
|
||||
works_from_distance = TRUE
|
||||
primary_sound = 'sound/items/pshoom.ogg'
|
||||
alt_sound = 'sound/items/pshoom_2.ogg'
|
||||
usesound = 'sound/items/pshoom.ogg'
|
||||
toolspeed = 0.5
|
||||
|
||||
/obj/item/storage/part_replacer/bluespace/tier4/populate_contents()
|
||||
for(var/amount in 1 to 30)
|
||||
new /obj/item/stock_parts/capacitor/quadratic(src)
|
||||
new /obj/item/stock_parts/manipulator/femto(src)
|
||||
new /obj/item/stock_parts/matter_bin/bluespace(src)
|
||||
new /obj/item/stock_parts/micro_laser/quadultra(src)
|
||||
new /obj/item/stock_parts/scanning_module/triphasic(src)
|
||||
new /obj/item/stock_parts/cell/bluespace(src)
|
||||
new /obj/item/reagent_containers/glass/beaker/bluespace(src)
|
||||
|
||||
/obj/item/storage/part_replacer/proc/play_rped_sound()
|
||||
//Plays the sound for RPED exchanging or installing parts.
|
||||
if(alt_sound && prob(3))
|
||||
playsound(src, alt_sound, 40, 1)
|
||||
else
|
||||
playsound(src, primary_sound, 40, 1)
|
||||
|
||||
////////////////////////////////////////
|
||||
// MARK: Stock parts
|
||||
////////////////////////////////////////
|
||||
/obj/item/stock_parts
|
||||
name = "stock part"
|
||||
desc = "What?"
|
||||
gender = PLURAL
|
||||
icon = 'icons/obj/stock_parts.dmi'
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
var/rating = 1
|
||||
usesound = 'sound/items/deconstruct.ogg'
|
||||
|
||||
//Rank 1
|
||||
|
||||
/obj/item/stock_parts/capacitor
|
||||
name = "capacitor"
|
||||
desc = "A basic capacitor used in the construction of a variety of devices."
|
||||
icon_state = "capacitor"
|
||||
item_state = "capacitor"
|
||||
origin_tech = "powerstorage=1"
|
||||
materials = list(MAT_METAL=50, MAT_GLASS=50)
|
||||
|
||||
/obj/item/stock_parts/scanning_module
|
||||
name = "scanning module"
|
||||
desc = "A compact, high resolution scanning module used in the construction of certain devices."
|
||||
icon_state = "scan_module"
|
||||
item_state = "scan_module"
|
||||
origin_tech = "magnets=1"
|
||||
materials = list(MAT_METAL=50, MAT_GLASS=20)
|
||||
|
||||
/obj/item/stock_parts/manipulator
|
||||
name = "micro-manipulator"
|
||||
desc = "A tiny little manipulator used in the construction of certain devices."
|
||||
icon_state = "micro_mani"
|
||||
item_state = "micro_mani"
|
||||
origin_tech = "materials=1;programming=1"
|
||||
materials = list(MAT_METAL=30)
|
||||
|
||||
/obj/item/stock_parts/micro_laser
|
||||
name = "micro-laser"
|
||||
desc = "A tiny laser used in certain devices."
|
||||
icon_state = "micro_laser"
|
||||
item_state = "micro_laser"
|
||||
origin_tech = "magnets=1"
|
||||
materials = list(MAT_METAL=10, MAT_GLASS=20)
|
||||
|
||||
/obj/item/stock_parts/matter_bin
|
||||
name = "matter bin"
|
||||
desc = "A container used to hold compressed matter awaiting re-construction."
|
||||
icon_state = "matter_bin"
|
||||
origin_tech = "materials=1"
|
||||
materials = list(MAT_METAL=80)
|
||||
|
||||
//Rank 2
|
||||
|
||||
/obj/item/stock_parts/capacitor/adv
|
||||
name = "advanced capacitor"
|
||||
desc = "An advanced capacitor used in the construction of a variety of devices."
|
||||
icon_state = "adv_capacitor"
|
||||
item_state = "adv_capacitor"
|
||||
origin_tech = "powerstorage=3"
|
||||
rating = 2
|
||||
materials = list(MAT_METAL=50, MAT_GLASS=50)
|
||||
|
||||
/obj/item/stock_parts/scanning_module/adv
|
||||
name = "advanced scanning module"
|
||||
icon_state = "adv_scan_module"
|
||||
item_state = "adv_scan_module"
|
||||
origin_tech = "magnets=3"
|
||||
rating = 2
|
||||
materials = list(MAT_METAL=50, MAT_GLASS=20)
|
||||
|
||||
/obj/item/stock_parts/manipulator/nano
|
||||
name = "nano-manipulator"
|
||||
icon_state = "nano_mani"
|
||||
item_state = "nano_mani"
|
||||
origin_tech = "materials=3;programming=2"
|
||||
rating = 2
|
||||
materials = list(MAT_METAL=30)
|
||||
|
||||
/obj/item/stock_parts/micro_laser/high
|
||||
name = "high-power micro-laser"
|
||||
icon_state = "high_micro_laser"
|
||||
item_state = "high_micro_laser"
|
||||
origin_tech = "magnets=3"
|
||||
rating = 2
|
||||
materials = list(MAT_METAL=10, MAT_GLASS=20)
|
||||
|
||||
/obj/item/stock_parts/matter_bin/adv
|
||||
name = "advanced matter bin"
|
||||
icon_state = "advanced_matter_bin"
|
||||
item_state = "advanced_matter_bin"
|
||||
origin_tech = "materials=3"
|
||||
rating = 2
|
||||
materials = list(MAT_METAL=80)
|
||||
|
||||
//Rating 3
|
||||
|
||||
/obj/item/stock_parts/capacitor/super
|
||||
name = "super capacitor"
|
||||
desc = "A super-high capacity capacitor used in the construction of a variety of devices."
|
||||
icon_state = "super_capacitor"
|
||||
item_state = "super_capacitor"
|
||||
origin_tech = "powerstorage=4;engineering=4"
|
||||
rating = 3
|
||||
materials = list(MAT_METAL=50, MAT_GLASS=50)
|
||||
|
||||
/obj/item/stock_parts/scanning_module/phasic
|
||||
name = "phasic scanning module"
|
||||
desc = "A compact, high resolution phasic scanning module used in the construction of certain devices."
|
||||
icon_state = "super_scan_module"
|
||||
item_state = "super_scan_module"
|
||||
origin_tech = "magnets=4;engineering=4"
|
||||
rating = 3
|
||||
materials = list(MAT_METAL=50, MAT_GLASS=20)
|
||||
|
||||
/obj/item/stock_parts/manipulator/pico
|
||||
name = "pico-manipulator"
|
||||
icon_state = "pico_mani"
|
||||
item_state = "pico_mani"
|
||||
origin_tech = "materials=4;programming=4;engineering=4"
|
||||
rating = 3
|
||||
materials = list(MAT_METAL=30)
|
||||
|
||||
/obj/item/stock_parts/micro_laser/ultra
|
||||
name = "ultra-high-power micro-laser"
|
||||
icon_state = "ultra_high_micro_laser"
|
||||
item_state = "ultra_high_micro_laser"
|
||||
origin_tech = "magnets=4;engineering=4"
|
||||
rating = 3
|
||||
materials = list(MAT_METAL=10, MAT_GLASS=20)
|
||||
|
||||
/obj/item/stock_parts/matter_bin/super
|
||||
name = "super matter bin"
|
||||
icon_state = "super_matter_bin"
|
||||
item_state = "super_matter_bin"
|
||||
origin_tech = "materials=4;engineering=4"
|
||||
rating = 3
|
||||
materials = list(MAT_METAL=80)
|
||||
|
||||
//Rating 4
|
||||
|
||||
/obj/item/stock_parts/capacitor/quadratic
|
||||
name = "quadratic capacitor"
|
||||
desc = "An ultra-high capacity capacitor used in the construction of a variety of devices."
|
||||
icon_state = "quadratic_capacitor"
|
||||
item_state = "quadratic_capacitor"
|
||||
origin_tech = "powerstorage=5;materials=4;engineering=4"
|
||||
rating = 4
|
||||
materials = list(MAT_METAL=50, MAT_GLASS=50)
|
||||
|
||||
/obj/item/stock_parts/scanning_module/triphasic
|
||||
name = "triphasic scanning module"
|
||||
desc = "A compact, ultra resolution triphasic scanning module used in the construction of certain devices."
|
||||
icon_state = "triphasic_scan_module"
|
||||
item_state = "triphasic_scan_module"
|
||||
origin_tech = "magnets=5;materials=4;engineering=4"
|
||||
rating = 4
|
||||
materials = list(MAT_METAL=50, MAT_GLASS=20)
|
||||
|
||||
/obj/item/stock_parts/manipulator/femto
|
||||
name = "femto-manipulator"
|
||||
icon_state = "femto_mani"
|
||||
item_state = "femto_mani"
|
||||
origin_tech = "materials=6;programming=4;engineering=4"
|
||||
rating = 4
|
||||
materials = list(MAT_METAL=30)
|
||||
|
||||
/obj/item/stock_parts/micro_laser/quadultra
|
||||
name = "quad-ultra micro-laser"
|
||||
icon_state = "quadultra_micro_laser"
|
||||
item_state = "quadultra_micro_laser"
|
||||
origin_tech = "magnets=5;materials=4;engineering=4"
|
||||
rating = 4
|
||||
materials = list(MAT_METAL=10, MAT_GLASS=20)
|
||||
|
||||
/obj/item/stock_parts/matter_bin/bluespace
|
||||
name = "bluespace matter bin"
|
||||
icon_state = "bluespace_matter_bin"
|
||||
item_state = "bluespace_matter_bin"
|
||||
origin_tech = "materials=6;programming=4;engineering=4"
|
||||
rating = 4
|
||||
materials = list(MAT_METAL=80)
|
||||
@@ -1,186 +0,0 @@
|
||||
/obj/item/storage/bible
|
||||
name = "bible"
|
||||
desc = "Apply to head repeatedly."
|
||||
lefthand_file = 'icons/mob/inhands/religion_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/religion_righthand.dmi'
|
||||
icon_state ="bible"
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
resistance_flags = FIRE_PROOF
|
||||
drop_sound = 'sound/items/handling/book_drop.ogg'
|
||||
pickup_sound = 'sound/items/handling/book_pickup.ogg'
|
||||
var/mob/affecting = null
|
||||
var/deity_name = "Christ"
|
||||
/// Is the sprite of this bible customisable
|
||||
var/customisable = FALSE
|
||||
|
||||
/// Associative list of accociative lists of bible variants, used for the radial menu
|
||||
var/static/list/bible_variants = list(
|
||||
"Bible" = list("state" = "bible", "inhand" = "bible"),
|
||||
"Koran" = list("state" = "koran", "inhand" = "koran"),
|
||||
"Scrapbook" = list("state" = "scrapbook", "inhand" = "scrapbook"),
|
||||
"Creeper" = list("state" = "creeper", "inhand" = "generic_bible"),
|
||||
"White Bible" = list("state" = "white", "inhand" = "generic_bible"),
|
||||
"Holy Light" = list("state" = "holylight", "inhand" = "generic_bible"),
|
||||
"PlainRed" = list("state" = "athiest", "inhand" = "generic_bible"),
|
||||
"Tome" = list("state" = "tome", "inhand" = "generic_bible"),
|
||||
"The King in Yellow" = list("state" = "kingyellow", "inhand" = "kingyellow"),
|
||||
"Ithaqua" = list("state" = "ithaqua", "inhand" = "ithaqua"),
|
||||
"Scientology" = list("state" = "scientology", "inhand" = "scientology"),
|
||||
"the bible melts" = list("state" = "melted", "inhand" = "melted"),
|
||||
"Necronomicon" = list("state" = "necronomicon", "inhand" = "necronomicon"),
|
||||
"Greentext" = list("state" = "greentext", "inhand" = "greentext"),
|
||||
"Honkmother" = list("state" = "honk", "inhand" = "honk"),
|
||||
"Silentfather" = list("state" = "mime", "inhand" = "mime"),
|
||||
"Clockwork" = list("state" = "clock_bible", "inhand" = "clock_bible"),
|
||||
"Nanotrasen" = list("state" = "nanotrasen", "inhand" = "nanotrasen")
|
||||
)
|
||||
|
||||
/obj/item/storage/bible/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] stares into [name] and attempts to transcend understanding of the universe!</span>")
|
||||
user.dust()
|
||||
return OBLITERATION
|
||||
|
||||
/obj/item/storage/bible/fart_act(mob/living/M)
|
||||
if(QDELETED(M) || M.stat == DEAD)
|
||||
return
|
||||
M.visible_message("<span class='danger'>[M] farts on \the [name]!</span>")
|
||||
M.visible_message("<span class='userdanger'>A mysterious force smites [M]!</span>")
|
||||
M.suiciding = TRUE
|
||||
do_sparks(3, 1, M)
|
||||
M.gib()
|
||||
return TRUE // Don't run the fart emote
|
||||
|
||||
/obj/item/storage/bible/booze
|
||||
desc = "To be applied to the head repeatedly."
|
||||
|
||||
/obj/item/storage/bible/booze/populate_contents()
|
||||
new /obj/item/reagent_containers/drinks/bottle/beer(src)
|
||||
new /obj/item/reagent_containers/drinks/bottle/beer(src)
|
||||
new /obj/item/stack/spacecash(src)
|
||||
new /obj/item/stack/spacecash(src)
|
||||
new /obj/item/stack/spacecash(src)
|
||||
//BS12 EDIT
|
||||
// All cult functionality moved to Null Rod
|
||||
/obj/item/storage/bible/proc/bless(mob/living/carbon/M)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
H.heal_overall_damage(10, 10)
|
||||
return
|
||||
|
||||
/obj/item/storage/bible/attack__legacy__attackchain(mob/living/M, mob/living/user)
|
||||
add_attack_logs(user, M, "Hit with [src]")
|
||||
|
||||
if(!(ishuman(user) || SSticker) && SSticker.mode.name != "monkey")
|
||||
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
|
||||
return
|
||||
if(!HAS_MIND_TRAIT(user, TRAIT_HOLY))
|
||||
to_chat(user, "<span class='warning'>The book sizzles in your hands.</span>")
|
||||
user.take_organ_damage(0, 10)
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
|
||||
to_chat(user, "<span class='warning'>[src] slips out of your hand and hits your head.</span>")
|
||||
user.take_organ_damage(10)
|
||||
user.Paralyse(40 SECONDS)
|
||||
return
|
||||
|
||||
if(M.stat != DEAD && ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(prob(60))
|
||||
bless(H)
|
||||
H.visible_message("<span class='danger'>[user] heals [H == user ? "[user.p_themselves()]" : "[H]"] with the power of [deity_name]!</span>",
|
||||
"<span class='danger'>May the power of [deity_name] compel you to be healed!</span>")
|
||||
playsound(loc, "punch", 25, TRUE, -1)
|
||||
else
|
||||
M.adjustBrainLoss(10)
|
||||
to_chat(M, "<span class='warning'>You feel dumber.</span>")
|
||||
H.visible_message("<span class='danger'>[user] beats [H == user ? "[user.p_themselves()]" : "[H]"] over the head with [src]!</span>")
|
||||
playsound(src.loc, "punch", 25, TRUE, -1)
|
||||
else
|
||||
M.visible_message("<span class='danger'>[user] smacks [M]'s lifeless corpse with [src].</span>")
|
||||
playsound(src.loc, "punch", 25, TRUE, -1)
|
||||
|
||||
|
||||
/obj/item/storage/bible/afterattack__legacy__attackchain(atom/target, mob/user, proximity, params)
|
||||
if(!proximity)
|
||||
return
|
||||
|
||||
if(isfloorturf(target))
|
||||
to_chat(user, "<span class='notice'>You hit the floor with the bible.</span>")
|
||||
if(HAS_MIND_TRAIT(user, TRAIT_HOLY))
|
||||
for(var/obj/O in target)
|
||||
O.cult_reveal()
|
||||
if(istype(target, /obj/machinery/door/airlock))
|
||||
to_chat(user, "<span class='notice'>You hit the airlock with the bible.</span>")
|
||||
if(HAS_MIND_TRAIT(user, TRAIT_HOLY))
|
||||
var/obj/airlock = target
|
||||
airlock.cult_reveal()
|
||||
|
||||
if(HAS_MIND_TRAIT(user, TRAIT_HOLY) && target.reagents)
|
||||
if(target.reagents.has_reagent("water")) //blesses all the water in the holder
|
||||
to_chat(user, "<span class='notice'>You bless [target].</span>")
|
||||
var/water2holy = target.reagents.get_reagent_amount("water")
|
||||
target.reagents.del_reagent("water")
|
||||
target.reagents.add_reagent("holywater", water2holy)
|
||||
|
||||
if(target.reagents.has_reagent("unholywater")) //yeah yeah, copy pasted code - sue me
|
||||
to_chat(user, "<span class='notice'>You purify [target].</span>")
|
||||
var/unholy2clean = target.reagents.get_reagent_amount("unholywater")
|
||||
target.reagents.del_reagent("unholywater")
|
||||
target.reagents.add_reagent("holywater", unholy2clean)
|
||||
|
||||
/obj/item/storage/bible/attack_self__legacy__attackchain(mob/user)
|
||||
. = ..()
|
||||
if(!customisable || !HAS_MIND_TRAIT(user, TRAIT_HOLY))
|
||||
return
|
||||
|
||||
var/list/skins = list()
|
||||
for(var/I in bible_variants)
|
||||
var/icons = bible_variants[I] // Get the accociated list
|
||||
var/image/bible_image = image('icons/obj/storage.dmi', icon_state = icons["state"])
|
||||
skins[I] = bible_image
|
||||
|
||||
var/choice = show_radial_menu(user, src, skins, null, 40, CALLBACK(src, PROC_REF(radial_check), user), TRUE)
|
||||
if(!choice || !radial_check(user))
|
||||
return
|
||||
var/choice_icons = bible_variants[choice]
|
||||
|
||||
icon_state = choice_icons["state"]
|
||||
item_state = choice_icons["inhand"]
|
||||
customisable = FALSE
|
||||
|
||||
// Carpet symbol icons are currently broken, so commented out until it's fixed
|
||||
/*var/carpet_dir
|
||||
switch(choice)
|
||||
if("Bible")
|
||||
carpet_dir = 2
|
||||
if("Koran")
|
||||
carpet_dir = 4
|
||||
if("Scientology")
|
||||
carpet_dir = 8
|
||||
if(carpet_dir)
|
||||
for(var/area/station/service/chapel/main/A in world)
|
||||
for(var/turf/T in A.contents)
|
||||
if(T.icon_state == "carpetsymbol")
|
||||
T.dir = carpet_dir*/
|
||||
|
||||
SSblackbox.record_feedback("text", "religion_book", 1, "[choice]", 1)
|
||||
|
||||
if(SSticker)
|
||||
SSticker.Bible_name = name
|
||||
SSticker.Bible_icon_state = icon_state
|
||||
SSticker.Bible_item_state = item_state
|
||||
|
||||
/obj/item/storage/bible/proc/radial_check(mob/user)
|
||||
if(!HAS_MIND_TRAIT(user, TRAIT_HOLY) || !ishuman(user))
|
||||
return FALSE
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(!src || !H.is_in_hands(src) || H.incapacitated())
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/storage/bible/syndi
|
||||
name = "suspicious bible"
|
||||
desc = "For treading the line between cultist, contraband, and a hostile corporation."
|
||||
icon_state = "syndi"
|
||||
@@ -1,500 +0,0 @@
|
||||
/*
|
||||
* The 'fancy' path is for objects like donut boxes that show how many items are in the storage item on the sprite itself
|
||||
* .. Sorry for the shitty path name, I couldnt think of a better one.
|
||||
*
|
||||
* WARNING: var/icon_type is used for both examine text and sprite name. Please look at the procs below and adjust your sprite names accordingly
|
||||
* TODO: Cigarette boxes should be ported to this standard
|
||||
*
|
||||
* Contains:
|
||||
* Donut Box
|
||||
* Egg Box
|
||||
* Candle Box
|
||||
* Crayon Box
|
||||
* Cigarette Box
|
||||
* Vial Box
|
||||
* Aquatic Starter Kit
|
||||
*/
|
||||
|
||||
/obj/item/storage/fancy
|
||||
icon = 'icons/obj/food/containers.dmi'
|
||||
resistance_flags = FLAMMABLE
|
||||
var/icon_type
|
||||
|
||||
/obj/item/storage/fancy/update_icon_state()
|
||||
icon_state = "[icon_type]box[length(contents)]"
|
||||
|
||||
/obj/item/storage/fancy/examine(mob/user)
|
||||
. = ..()
|
||||
. += fancy_storage_examine(user)
|
||||
|
||||
/obj/item/storage/fancy/proc/fancy_storage_examine(mob/user)
|
||||
. = list()
|
||||
if(in_range(user, src))
|
||||
var/len = LAZYLEN(contents)
|
||||
if(len <= 0)
|
||||
. += "There are no [icon_type]s left in the box."
|
||||
else if(len == 1)
|
||||
. += "There is one [icon_type] left in the box."
|
||||
else
|
||||
. += "There are [length(contents)] [icon_type]s in the box."
|
||||
|
||||
/obj/item/storage/fancy/remove_from_storage(obj/item/I, atom/new_location)
|
||||
if(!istype(I))
|
||||
return FALSE
|
||||
|
||||
update_icon()
|
||||
return ..()
|
||||
|
||||
// MARK: Donut Box
|
||||
/obj/item/storage/fancy/donut_box
|
||||
name = "donut box"
|
||||
desc = "\"To do, or do nut, the choice is obvious.\""
|
||||
icon_type = "donut"
|
||||
icon_state = "donutbox"
|
||||
storage_slots = 6
|
||||
can_hold = list(/obj/item/food/donut)
|
||||
foldable = /obj/item/stack/sheet/cardboard
|
||||
foldable_amt = 1
|
||||
|
||||
/obj/item/storage/fancy/donut_box/update_overlays()
|
||||
. = ..()
|
||||
for(var/I = 1 to length(contents))
|
||||
var/obj/item/food/donut/donut = contents[I]
|
||||
var/icon/new_donut_icon = icon('icons/obj/food/containers.dmi', "[(I - 1)]donut[donut.donut_sprite_type]")
|
||||
. += new_donut_icon
|
||||
|
||||
/obj/item/storage/fancy/donut_box/update_icon_state()
|
||||
return
|
||||
|
||||
/obj/item/storage/fancy/donut_box/populate_contents()
|
||||
for(var/I in 1 to storage_slots)
|
||||
new /obj/item/food/donut(src)
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/item/storage/fancy/donut_box/empty/populate_contents()
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
return
|
||||
|
||||
/obj/item/storage/fancy/donut_box/decompile_act(obj/item/matter_decompiler/C, mob/user)
|
||||
if(isdrone(user) && !length(contents))
|
||||
C.stored_comms["wood"] += 1
|
||||
qdel(src)
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
// MARK: Egg Box
|
||||
|
||||
|
||||
/obj/item/storage/fancy/egg_box
|
||||
icon_state = "eggbox"
|
||||
icon_type = "egg"
|
||||
item_state = "eggbox"
|
||||
name = "egg box"
|
||||
storage_slots = 12
|
||||
can_hold = list(/obj/item/food/egg)
|
||||
|
||||
/obj/item/storage/fancy/egg_box/populate_contents()
|
||||
for(var/I in 1 to storage_slots)
|
||||
new /obj/item/food/egg(src)
|
||||
|
||||
// MARK: Candle Box
|
||||
/obj/item/storage/fancy/candle_box
|
||||
name = "Candle pack"
|
||||
desc = "A pack of red candles."
|
||||
icon = 'icons/obj/candle.dmi'
|
||||
icon_state = "candlebox0"
|
||||
icon_type = "candle"
|
||||
item_state = "candlebox5"
|
||||
storage_slots = 5
|
||||
throwforce = 2
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
|
||||
/obj/item/storage/fancy/candle_box/Initialize(mapload)
|
||||
. = ..()
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
|
||||
/obj/item/storage/fancy/candle_box/full/populate_contents()
|
||||
for(var/I in 1 to storage_slots)
|
||||
new /obj/item/candle(src)
|
||||
|
||||
/obj/item/storage/fancy/candle_box/eternal
|
||||
name = "Eternal Candle pack"
|
||||
desc = "A pack of red candles made with a special wax."
|
||||
|
||||
/obj/item/storage/fancy/candle_box/eternal/populate_contents()
|
||||
for(var/I in 1 to storage_slots)
|
||||
new /obj/item/candle/eternal(src)
|
||||
|
||||
|
||||
// MARK: Crayon Box
|
||||
/obj/item/storage/fancy/crayons
|
||||
name = "box of crayons"
|
||||
desc = "A box of crayons for all your rune drawing needs."
|
||||
icon = 'icons/obj/crayons.dmi'
|
||||
icon_state = "crayonbox"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
storage_slots = 8
|
||||
icon_type = "crayon"
|
||||
can_hold = list(
|
||||
/obj/item/toy/crayon
|
||||
)
|
||||
|
||||
/obj/item/storage/fancy/crayons/populate_contents()
|
||||
new /obj/item/toy/crayon/white(src)
|
||||
new /obj/item/toy/crayon/red(src)
|
||||
new /obj/item/toy/crayon/orange(src)
|
||||
new /obj/item/toy/crayon/yellow(src)
|
||||
new /obj/item/toy/crayon/green(src)
|
||||
new /obj/item/toy/crayon/blue(src)
|
||||
new /obj/item/toy/crayon/purple(src)
|
||||
new /obj/item/toy/crayon/black(src)
|
||||
update_icon()
|
||||
|
||||
/obj/item/storage/fancy/crayons/update_overlays()
|
||||
. = ..()
|
||||
. += image('icons/obj/crayons.dmi',"crayonbox")
|
||||
for(var/obj/item/toy/crayon/crayon in contents)
|
||||
. += image('icons/obj/crayons.dmi', crayon.dye_color)
|
||||
|
||||
/obj/item/storage/fancy/crayons/attackby__legacy__attackchain(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/toy/crayon))
|
||||
var/obj/item/toy/crayon/C = I
|
||||
switch(C.dye_color)
|
||||
if("mime")
|
||||
to_chat(usr, "This crayon is too sad to be contained in this box.")
|
||||
return
|
||||
if("rainbow")
|
||||
to_chat(usr, "This crayon is too powerful to be contained in this box.")
|
||||
return
|
||||
..()
|
||||
|
||||
/*
|
||||
* Matches Box
|
||||
*/
|
||||
|
||||
/obj/item/storage/fancy/matches
|
||||
name = "matchbox"
|
||||
desc = "A small box of Almost But Not Quite Plasma Premium Matches."
|
||||
icon = 'icons/obj/cigarettes.dmi'
|
||||
icon_state = "matchbox"
|
||||
item_state = "matchbox"
|
||||
base_icon_state = "matchbox"
|
||||
storage_slots = 10
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
max_w_class = WEIGHT_CLASS_TINY
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
drop_sound = 'sound/items/handling/matchbox_drop.ogg'
|
||||
pickup_sound = 'sound/items/handling/matchbox_pickup.ogg'
|
||||
can_hold = list(/obj/item/match)
|
||||
|
||||
/obj/item/storage/fancy/matches/populate_contents()
|
||||
for(var/I in 1 to storage_slots)
|
||||
new /obj/item/match(src)
|
||||
|
||||
/obj/item/storage/fancy/matches/attackby__legacy__attackchain(obj/item/match/W, mob/user, params)
|
||||
if(istype(W, /obj/item/match) && !W.lit)
|
||||
W.matchignite()
|
||||
playsound(user.loc, 'sound/goonstation/misc/matchstick_light.ogg', 50, TRUE)
|
||||
return
|
||||
|
||||
/obj/item/storage/fancy/matches/update_icon_state()
|
||||
. = ..()
|
||||
switch(length(contents))
|
||||
if(10)
|
||||
icon_state = base_icon_state
|
||||
if(5 to 9)
|
||||
icon_state = "[base_icon_state]_almostfull"
|
||||
if(1 to 4)
|
||||
icon_state = "[base_icon_state]_almostempty"
|
||||
if(0)
|
||||
icon_state = "[base_icon_state]_e"
|
||||
|
||||
// MARK: Cigarette Pack
|
||||
/obj/item/storage/fancy/cigarettes
|
||||
name = "generic cigarette packet"
|
||||
desc = "An abstract brand of cigarette that should not exist. Make a GitHub report if you see this."
|
||||
icon = 'icons/obj/cigarettes.dmi'
|
||||
icon_state = "robust_packet"
|
||||
item_state = "robust_packet"
|
||||
belt_icon = "patch_pack"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
storage_slots = 6
|
||||
max_combined_w_class = 6
|
||||
can_hold = list(/obj/item/clothing/mask/cigarette,
|
||||
/obj/item/lighter,
|
||||
/obj/item/match)
|
||||
cant_hold = list(/obj/item/clothing/mask/cigarette/cigar,
|
||||
/obj/item/clothing/mask/cigarette/pipe,
|
||||
/obj/item/lighter/zippo)
|
||||
icon_type = "cigarette"
|
||||
var/cigarette_slogan = "The preferred brand of coders and developers."
|
||||
var/cigarette_type = /obj/item/clothing/mask/cigarette
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/examine(mob/user)
|
||||
. = ..()
|
||||
if(cigarette_slogan)
|
||||
. += "<span class='notice'>\"[cigarette_slogan]\"</span>"
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/populate_contents()
|
||||
for(var/I in 1 to storage_slots)
|
||||
new cigarette_type(src)
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/update_icon_state()
|
||||
icon_state = "[initial(icon_state)]_[length(contents)]"
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/attack__legacy__attackchain(mob/living/carbon/M, mob/living/user)
|
||||
if(!ismob(M))
|
||||
return
|
||||
|
||||
if(istype(M) && user.zone_selected == "mouth" && length(contents) > 0 && !M.wear_mask)
|
||||
var/got_cig = FALSE
|
||||
for(var/num in 1 to length(contents))
|
||||
var/obj/item/I = contents[num]
|
||||
if(istype(I, /obj/item/clothing/mask/cigarette))
|
||||
var/obj/item/clothing/mask/cigarette/C = I
|
||||
M.equip_to_slot_if_possible(C, ITEM_SLOT_MASK)
|
||||
if(M != user)
|
||||
user.visible_message(
|
||||
"<span class='notice'>[user] takes \a [C.name] out of [src] and gives it to [M].</span>",
|
||||
"<span class='notice'>You take \a [C.name] out of [src] and give it to [M].</span>"
|
||||
)
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You take \a [C.name] out of the pack.</span>")
|
||||
update_icon()
|
||||
got_cig = TRUE
|
||||
break
|
||||
if(!got_cig)
|
||||
to_chat(user, "<span class='warning'>There are no smokables in the pack!</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/can_be_inserted(obj/item/W, stop_messages = FALSE)
|
||||
if(istype(W, /obj/item/match))
|
||||
var/obj/item/match/M = W
|
||||
if(M.lit)
|
||||
if(!stop_messages)
|
||||
to_chat(usr, "<span class='notice'>Putting a lit [W] in [src] probably isn't a good idea.</span>")
|
||||
return FALSE
|
||||
if(istype(W, /obj/item/lighter))
|
||||
var/obj/item/lighter/L = W
|
||||
if(L.lit)
|
||||
if(!stop_messages)
|
||||
to_chat(usr, "<span class='notice'>Putting [W] in [src] while lit probably isn't a good idea.</span>")
|
||||
return FALSE
|
||||
//if we get this far, handle the insertion checks as normal
|
||||
. = ..()
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/decompile_act(obj/item/matter_decompiler/C, mob/user)
|
||||
if(isdrone(user) && !length(contents))
|
||||
C.stored_comms["wood"] += 1
|
||||
qdel(src)
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_carp
|
||||
name = "\improper Carp Classic packet"
|
||||
desc = "Smoked mainly by spacers. The somewhat fishy notes are an acquired taste. \
|
||||
Has a light, low-tar smoke specifically designed to reduce stress on scrubber systems."
|
||||
icon_state = "carp_packet"
|
||||
item_state = "carp_packet"
|
||||
cigarette_slogan = "Carp smokers would rather bite you than switch, since 2313."
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/dromedaryco
|
||||
name = "\improper DromedaryCo packet"
|
||||
desc = "An infamous brand, DromedaryCo cigarettes are unfiltered, tarry, and have a very harsh flavour. \
|
||||
Not for beginner smokers. Enjoyed mainly by gruff types with equally gruff voices."
|
||||
icon_state = "D_packet"
|
||||
item_state = "D_packet"
|
||||
cigarette_slogan = "Wouldn't a slow death make a change?"
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_random
|
||||
name ="\improper Embellished Enigma packet"
|
||||
desc = "True to the name, Enigmas are impossible to pin down. \
|
||||
No two cigarettes are alike as each one is infused with unique flavours and substances, so every time is just like your first time."
|
||||
icon_state = "enigma_packet"
|
||||
item_state = "enigma_packet"
|
||||
cigarette_slogan = "For the true connoisseur of exotic flavors."
|
||||
cigarette_type = /obj/item/clothing/mask/cigarette/random
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_random/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class = 'warning'>Warning: Not all substances used have undergone regulatory testing, smoke at your own risk. \
|
||||
The Embellished Enigma Tobacco Company does not accept liability for proper or negligent use of its products. Consult your doctor before use.</span>"
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_midori
|
||||
name = "\improper Midori Tabako packet"
|
||||
desc = "Whilst you cannot decipher what the strange runes on the packet say, it bears the unmistakable scent of cannabis."
|
||||
icon_state = "midori_packet"
|
||||
item_state = "midori_packet"
|
||||
cigarette_slogan = ""
|
||||
cigarette_type = /obj/item/clothing/mask/cigarette/rollie
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_our_brand
|
||||
name = "\improper Our Brand packet" // This brand name is an obscure reference to The Master and Margarita by Ivan Bezdomny.
|
||||
desc = "The one, official brand of cigarette manufactured by the Vostran Iron Republic - one of the main constitient nations of the USSP. \
|
||||
Exported across the known Orion Spur by members of the USSP's trading bloc and vendors affiliated with the Nian Merchant Guild. \
|
||||
The flavour is acrid, the smoke is thin and wispy, yet harsh on the throat. The only redeeming features are the high nicotine content and the low price."
|
||||
icon_state = "our_brand_packet"
|
||||
item_state = "our_brand_packet"
|
||||
cigarette_slogan = "Smoke, for the Union!"
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_robust
|
||||
name = "\improper Robust packet"
|
||||
desc = "Nanotrasen's in-house brand of cigarettes. Cheap quality, wispy smoke, has a somewhat harsh flavour."
|
||||
cigarette_slogan = "Smoked by the robust."
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_robustgold
|
||||
name = "\improper Robust Gold packet"
|
||||
desc = "Nanotrasen's premium cigarette offering. Has a smooth, drawn-out flavour and a dense smoke. Contains real gold."
|
||||
icon_state = "robust_g_packet"
|
||||
item_state = "robust_g_packet"
|
||||
cigarette_slogan = "Smoked by the <b>truly</b> robust."
|
||||
cigarette_type = /obj/item/clothing/mask/cigarette/robustgold
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_candy
|
||||
name = "\improper Robust Junior packet"
|
||||
desc = "A packet of nicotine-free* candy cigarettes, manufactured by Robust Tobacco."
|
||||
cigarette_slogan = "Unsure about smoking? Want to bring your children safely into the family tradition? Look no more with this special packet! Includes 100% nicotine-free* candy cigarettes."
|
||||
cigarette_type = /obj/item/clothing/mask/cigarette/candy
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_candy/examine(mob/user)
|
||||
. = ..()
|
||||
. += "<span class = 'warning'>*Warning: Do not expose to high temperatures or naked flames, contains additives that will form nicotine at high temperatures.</span>"
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_shadyjims
|
||||
name ="\improper Shady Jim's Super Slims packet"
|
||||
desc = "Despite the doubious appearance, these cigarettes do exactly what they say on the box. The smoke tastes like cheap berry juice and battery acid, with a bitter chemical aftertaste."
|
||||
icon_state = "shady_jim_packet"
|
||||
item_state = "shady_jim_packet"
|
||||
cigarette_slogan = "Is your weight slowing you down? Having trouble running away from gravitational singularities? Can't stop stuffing your mouth? \
|
||||
Smoke Shady Jim's Super Slims and watch all that fat burn away. Guaranteed results!"
|
||||
cigarette_type = /obj/item/clothing/mask/cigarette/shadyjims
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_solar_rays
|
||||
name = "\improper Solar Rays packet"
|
||||
desc = "A popular brand within the Trans-Solar Federation, they have a smooth, slightly cinnamon flavour. \
|
||||
Whilst not actually state-owned, these cigarettes lean heavily into patriotic marketing, and are included in federal ration packs as a morale booster."
|
||||
icon_state = "solar_packet"
|
||||
item_state = "solar_packet"
|
||||
cigarette_slogan = "Smoked by true patriots."
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_uplift
|
||||
name = "\improper Uplift Smooth packet"
|
||||
desc = "One of the most popular brands in the Orion Sector, flavoured with menthol to give a smooth cooling sensation with every puff."
|
||||
icon_state = "uplift_packet"
|
||||
item_state = "uplift_packet"
|
||||
cigarette_slogan = "Sit back and relax with the soft cooling embrace that only an Uplift can provide."
|
||||
cigarette_type = /obj/item/clothing/mask/cigarette/menthol
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_med
|
||||
name = "medical marijuana packet"
|
||||
desc = "A prescription packet containing six fully legal medical marijuana cigarettes. \
|
||||
Made using a strain of cannabis engineered to maximise CBD content and eliminate THC, much to the chagrin of stoners everywhere."
|
||||
icon_state = "med_packet"
|
||||
item_state = "med_packet"
|
||||
cigarette_slogan = "All the medical benefits, with none of the high!"
|
||||
cigarette_type = /obj/item/clothing/mask/cigarette/medical_marijuana
|
||||
|
||||
/obj/item/storage/fancy/cigarettes/cigpack_syndicate
|
||||
name = "suspicious cigarette packet"
|
||||
desc = "An obscure brand of evil-looking cigarettes. Smells like Donk pockets."
|
||||
icon_state = "syndie_packet"
|
||||
item_state = "syndie_packet"
|
||||
cigarette_slogan = "Strong flavour, dense smoke, infused with omnizine."
|
||||
cigarette_type = /obj/item/clothing/mask/cigarette/syndicate
|
||||
|
||||
/obj/item/storage/fancy/rollingpapers
|
||||
name = "rolling paper pack"
|
||||
desc = "A pack of Nanotrasen brand rolling papers."
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
icon = 'icons/obj/cigarettes.dmi'
|
||||
icon_state = "cig_paper_pack"
|
||||
item_state = "cig_paper_pack"
|
||||
storage_slots = 10
|
||||
icon_type = "rolling paper"
|
||||
can_hold = list(/obj/item/rollingpaper)
|
||||
|
||||
/obj/item/storage/fancy/rollingpapers/update_icon_state()
|
||||
return
|
||||
|
||||
/obj/item/storage/fancy/rollingpapers/populate_contents()
|
||||
for(var/I in 1 to storage_slots)
|
||||
new /obj/item/rollingpaper(src)
|
||||
|
||||
/obj/item/storage/fancy/rollingpapers/update_overlays()
|
||||
. = ..()
|
||||
if(!length(contents))
|
||||
. += "[icon_state]_empty"
|
||||
|
||||
|
||||
// MARK: Vial Box
|
||||
/obj/item/storage/fancy/vials
|
||||
icon = 'icons/obj/vialbox.dmi'
|
||||
icon_state = "vialbox6"
|
||||
icon_type = "vial"
|
||||
name = "vial storage box"
|
||||
storage_slots = 6
|
||||
can_hold = list(/obj/item/reagent_containers/glass/beaker/vial)
|
||||
|
||||
|
||||
/obj/item/storage/fancy/vials/populate_contents()
|
||||
for(var/I in 1 to storage_slots)
|
||||
new /obj/item/reagent_containers/glass/beaker/vial(src)
|
||||
return
|
||||
|
||||
/obj/item/storage/lockbox/vials
|
||||
name = "secure vial storage box"
|
||||
desc = "A locked box for keeping things away from children."
|
||||
icon = 'icons/obj/vialbox.dmi'
|
||||
icon_state = "vialbox0"
|
||||
can_hold = list(/obj/item/reagent_containers/glass/bottle)
|
||||
storage_slots = 6
|
||||
req_access = list(ACCESS_VIROLOGY)
|
||||
|
||||
/obj/item/storage/lockbox/vials/Initialize(mapload)
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/storage/lockbox/vials/update_icon_state()
|
||||
icon_state = "vialbox[length(contents)]"
|
||||
cut_overlays()
|
||||
|
||||
/obj/item/storage/lockbox/vials/update_overlays()
|
||||
. = ..()
|
||||
if(!broken)
|
||||
. += "led[locked]"
|
||||
if(locked)
|
||||
. += "cover"
|
||||
else
|
||||
. += "ledb"
|
||||
|
||||
/obj/item/storage/lockbox/vials/attackby__legacy__attackchain(obj/item/I, mob/user, params)
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/storage/lockbox/vials/zombie_cure
|
||||
name = "secure vial storage box - 'Anti-Plague Sequences'"
|
||||
|
||||
/obj/item/storage/lockbox/vials/zombie_cure/populate_contents()
|
||||
new /obj/item/reagent_containers/glass/bottle/zombiecure1(src)
|
||||
new /obj/item/reagent_containers/glass/bottle/zombiecure2(src)
|
||||
new /obj/item/reagent_containers/glass/bottle/zombiecure3(src)
|
||||
new /obj/item/reagent_containers/glass/bottle/zombiecure4(src)
|
||||
|
||||
// MARK: Aquatic Starter Kit
|
||||
/obj/item/storage/firstaid/aquatic_kit
|
||||
name = "aquatic starter kit"
|
||||
desc = "It's a starter kit box for an aquarium."
|
||||
icon_state = "AquaticKit"
|
||||
med_bot_skin = "fish"
|
||||
|
||||
/obj/item/storage/firstaid/aquatic_kit/full
|
||||
desc = "It's a starter kit for an aquarium; includes 1 tank brush, 1 egg scoop, 1 fish net, 1 container of fish food and 1 fish bag."
|
||||
|
||||
/obj/item/storage/firstaid/aquatic_kit/full/populate_contents()
|
||||
new /obj/item/egg_scoop(src)
|
||||
new /obj/item/fish_net(src)
|
||||
new /obj/item/tank_brush(src)
|
||||
new /obj/item/fishfood(src)
|
||||
new /obj/item/storage/bag/fish(src)
|
||||
@@ -1,437 +0,0 @@
|
||||
/* First aid storage
|
||||
* Contains:
|
||||
* First Aid Kits
|
||||
* Pill Bottles
|
||||
* Dice Pack (in a pill bottle)
|
||||
*/
|
||||
|
||||
/*
|
||||
* First Aid Kits
|
||||
*/
|
||||
/obj/item/storage/firstaid
|
||||
name = "generic first-aid kit"
|
||||
desc = "If you can see this, make a bug report on GitHub, something went wrong!"
|
||||
icon_state = "genericfirstaid"
|
||||
throw_range = 8
|
||||
req_one_access =list(ACCESS_MEDICAL, ACCESS_ROBOTICS) //Access and treatment are utilized for medbots.
|
||||
var/treatment_brute = "salglu_solution"
|
||||
var/treatment_oxy = "salbutamol"
|
||||
var/treatment_fire = "salglu_solution"
|
||||
var/treatment_tox = "charcoal"
|
||||
var/treatment_virus = "spaceacillin"
|
||||
var/med_bot_skin = null
|
||||
var/syndicate_aligned = FALSE
|
||||
var/robot_arm // This is for robot construction
|
||||
|
||||
|
||||
/obj/item/storage/firstaid/regular
|
||||
name = "first-aid kit"
|
||||
desc = "A general medical kit that contains medical patches for both brute damage and burn damage. Also contains an epinephrine syringe for emergency use and a health analyzer."
|
||||
icon_state = "firstaid"
|
||||
|
||||
/obj/item/storage/firstaid/regular/populate_contents()
|
||||
new /obj/item/reagent_containers/patch/styptic(src)
|
||||
new /obj/item/reagent_containers/patch/styptic(src)
|
||||
new /obj/item/reagent_containers/pill/salicylic(src)
|
||||
new /obj/item/reagent_containers/patch/silver_sulf(src)
|
||||
new /obj/item/reagent_containers/patch/silver_sulf(src)
|
||||
new /obj/item/healthanalyzer(src)
|
||||
new /obj/item/reagent_containers/hypospray/autoinjector/epinephrine(src)
|
||||
|
||||
/obj/item/storage/firstaid/regular/empty/populate_contents()
|
||||
return
|
||||
|
||||
/obj/item/storage/firstaid/regular/doctor
|
||||
desc = "A medical kit designed for Nanotrasen medical personnel."
|
||||
|
||||
/obj/item/storage/firstaid/regular/doctor/populate_contents()
|
||||
new /obj/item/reagent_containers/applicator/brute(src)
|
||||
new /obj/item/reagent_containers/applicator/burn(src)
|
||||
new /obj/item/reagent_containers/patch/styptic(src)
|
||||
new /obj/item/reagent_containers/patch/silver_sulf(src)
|
||||
new /obj/item/reagent_containers/pill/salicylic(src)
|
||||
new /obj/item/healthanalyzer/advanced(src)
|
||||
new /obj/item/reagent_containers/hypospray/autoinjector/epinephrine(src)
|
||||
|
||||
/obj/item/storage/firstaid/fire
|
||||
name = "fire first-aid kit"
|
||||
desc = "A medical kit that contains several medical patches and pills for treating burns. Contains one epinephrine syringe for emergency use and a health analyzer."
|
||||
icon_state = "ointment"
|
||||
item_state = "firstaid-ointment"
|
||||
med_bot_skin = "ointment"
|
||||
|
||||
/obj/item/storage/firstaid/fire/Initialize(mapload)
|
||||
. = ..()
|
||||
icon_state = pick("ointment", "firefirstaid")
|
||||
|
||||
/obj/item/storage/firstaid/fire/populate_contents()
|
||||
new /obj/item/reagent_containers/applicator/burn(src)
|
||||
new /obj/item/reagent_containers/patch/silver_sulf/small(src)
|
||||
new /obj/item/healthanalyzer(src)
|
||||
new /obj/item/reagent_containers/hypospray/autoinjector/epinephrine(src)
|
||||
new /obj/item/reagent_containers/pill/salicylic(src)
|
||||
|
||||
/obj/item/storage/firstaid/fire/empty/populate_contents()
|
||||
return
|
||||
|
||||
/obj/item/storage/firstaid/toxin
|
||||
name = "toxin first aid kit"
|
||||
desc = "A medical kit designed to counter poisoning by common toxins. Contains three pills and syringes, and a health analyzer to determine the health of the patient."
|
||||
icon_state = "antitoxin"
|
||||
item_state = "firstaid-toxin"
|
||||
med_bot_skin = "tox"
|
||||
|
||||
/obj/item/storage/firstaid/toxin/Initialize(mapload)
|
||||
. = ..()
|
||||
icon_state = pick("antitoxin", "antitoxfirstaid", "antitoxfirstaid2")
|
||||
|
||||
/obj/item/storage/firstaid/toxin/populate_contents()
|
||||
for(var/I in 1 to 3)
|
||||
new /obj/item/reagent_containers/syringe/charcoal(src)
|
||||
new /obj/item/reagent_containers/pill/charcoal(src)
|
||||
new /obj/item/healthanalyzer(src)
|
||||
|
||||
/obj/item/storage/firstaid/toxin/empty/populate_contents()
|
||||
return
|
||||
|
||||
/obj/item/storage/firstaid/o2
|
||||
name = "oxygen deprivation first aid kit"
|
||||
desc = "A first aid kit that contains four pills of salbutamol, which is able to counter injuries caused by suffocation. Also contains a health analyzer to determine the health of the patient."
|
||||
icon_state = "o2"
|
||||
item_state = "firstaid-o2"
|
||||
med_bot_skin = "o2"
|
||||
|
||||
/obj/item/storage/firstaid/o2/populate_contents()
|
||||
new /obj/item/reagent_containers/pill/salbutamol(src)
|
||||
new /obj/item/reagent_containers/pill/salbutamol(src)
|
||||
new /obj/item/reagent_containers/pill/salbutamol(src)
|
||||
new /obj/item/reagent_containers/pill/salbutamol(src)
|
||||
new /obj/item/healthanalyzer(src)
|
||||
|
||||
/obj/item/storage/firstaid/o2/empty/populate_contents()
|
||||
return
|
||||
|
||||
/obj/item/storage/firstaid/brute
|
||||
name = "brute trauma treatment kit"
|
||||
desc = "A medical kit that contains several medical patches and pills for treating brute injuries. Contains one epinephrine syringe for emergency use and a health analyzer."
|
||||
icon_state = "brute"
|
||||
item_state = "firstaid-brute"
|
||||
med_bot_skin = "brute"
|
||||
|
||||
/obj/item/storage/firstaid/brute/Initialize(mapload)
|
||||
. = ..()
|
||||
icon_state = pick("brute", "brute2")
|
||||
|
||||
/obj/item/storage/firstaid/brute/populate_contents()
|
||||
new /obj/item/reagent_containers/applicator/brute(src)
|
||||
new /obj/item/reagent_containers/patch/styptic/small(src)
|
||||
new /obj/item/healthanalyzer(src)
|
||||
new /obj/item/reagent_containers/hypospray/autoinjector/epinephrine(src)
|
||||
new /obj/item/stack/medical/bruise_pack(src)
|
||||
|
||||
/obj/item/storage/firstaid/brute/empty/populate_contents()
|
||||
return
|
||||
|
||||
/obj/item/storage/firstaid/adv
|
||||
name = "advanced first-aid kit"
|
||||
desc = "Contains advanced medical treatments."
|
||||
icon_state = "advfirstaid"
|
||||
item_state = "firstaid-advanced"
|
||||
med_bot_skin = "adv"
|
||||
|
||||
/obj/item/storage/firstaid/adv/populate_contents()
|
||||
new /obj/item/stack/medical/bruise_pack(src)
|
||||
new /obj/item/stack/medical/bruise_pack/advanced(src)
|
||||
new /obj/item/stack/medical/bruise_pack/advanced(src)
|
||||
new /obj/item/stack/medical/ointment/advanced(src)
|
||||
new /obj/item/stack/medical/ointment/advanced(src)
|
||||
new /obj/item/reagent_containers/hypospray/autoinjector/epinephrine(src)
|
||||
new /obj/item/healthanalyzer(src)
|
||||
|
||||
/obj/item/storage/firstaid/adv/empty/populate_contents()
|
||||
return
|
||||
|
||||
/obj/item/storage/firstaid/machine
|
||||
name = "machine repair kit"
|
||||
desc = "A kit that contains supplies to repair IPCs on the go."
|
||||
icon_state = "machinefirstaid"
|
||||
item_state = "firstaid-machine"
|
||||
med_bot_skin = "machine"
|
||||
|
||||
/obj/item/storage/firstaid/machine/populate_contents()
|
||||
new /obj/item/weldingtool/mini(src)
|
||||
new /obj/item/stack/cable_coil(src)
|
||||
new /obj/item/stack/cable_coil(src)
|
||||
new /obj/item/stack/cable_coil(src)
|
||||
new /obj/item/robotanalyzer(src)
|
||||
|
||||
/obj/item/storage/firstaid/machine/empty/populate_contents()
|
||||
return
|
||||
|
||||
/obj/item/storage/firstaid/tactical
|
||||
name = "first-aid kit"
|
||||
desc = "I hope you've got insurance."
|
||||
icon_state = "bezerk"
|
||||
treatment_oxy = "perfluorodecalin"
|
||||
treatment_brute = "bicaridine"
|
||||
treatment_fire = "kelotane"
|
||||
req_one_access = list(ACCESS_SYNDICATE)
|
||||
med_bot_skin = "bezerk"
|
||||
syndicate_aligned = TRUE
|
||||
|
||||
/obj/item/storage/firstaid/tactical/populate_contents()
|
||||
new /obj/item/reagent_containers/hypospray/combat(src)
|
||||
new /obj/item/reagent_containers/applicator/dual/syndi(src) // Because you ain't got no time to look at what damage dey taking yo
|
||||
new /obj/item/reagent_containers/hypospray/autoinjector/emergency_nuclear(src)
|
||||
new /obj/item/reagent_containers/hypospray/autoinjector/emergency_nuclear(src)
|
||||
new /obj/item/storage/pill_bottle/painkillers(src)
|
||||
new /obj/item/clothing/glasses/hud/health/night(src)
|
||||
new /obj/item/healthanalyzer/advanced(src)
|
||||
|
||||
/obj/item/storage/firstaid/tactical/empty/populate_contents()
|
||||
return
|
||||
|
||||
/obj/item/storage/firstaid/surgery
|
||||
name = "field surgery kit"
|
||||
desc = "A kit for surgery in the field."
|
||||
icon_state = "duffel-med"
|
||||
lefthand_file = 'icons/mob/inhands/clothing_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/clothing_righthand.dmi'
|
||||
max_w_class = WEIGHT_CLASS_BULKY
|
||||
max_combined_w_class = 21
|
||||
storage_slots = 10
|
||||
can_hold = list(/obj/item/roller,/obj/item/bonesetter,/obj/item/bonegel, /obj/item/scalpel, /obj/item/hemostat,
|
||||
/obj/item/cautery, /obj/item/retractor, /obj/item/fix_o_vein, /obj/item/surgicaldrill, /obj/item/circular_saw)
|
||||
|
||||
/obj/item/storage/firstaid/surgery/populate_contents()
|
||||
new /obj/item/roller(src)
|
||||
new /obj/item/bonesetter(src)
|
||||
new /obj/item/bonegel(src)
|
||||
new /obj/item/scalpel(src)
|
||||
new /obj/item/hemostat(src)
|
||||
new /obj/item/cautery(src)
|
||||
new /obj/item/retractor(src)
|
||||
new /obj/item/fix_o_vein(src)
|
||||
new /obj/item/surgicaldrill(src)
|
||||
new /obj/item/circular_saw(src)
|
||||
|
||||
/obj/item/storage/firstaid/ert
|
||||
name = "ert first-aid kit"
|
||||
desc = "A medical kit used by Nanotrasen emergency response team personnel."
|
||||
icon_state = "bezerk"
|
||||
med_bot_skin = "bezerk"
|
||||
|
||||
/obj/item/storage/firstaid/ert/populate_contents()
|
||||
new /obj/item/healthanalyzer/advanced(src)
|
||||
new /obj/item/stack/medical/splint(src)
|
||||
new /obj/item/reagent_containers/applicator/dual(src)
|
||||
new /obj/item/stack/medical/ointment/advanced(src)
|
||||
new /obj/item/stack/medical/ointment/advanced(src)
|
||||
new /obj/item/stack/medical/bruise_pack/advanced(src)
|
||||
new /obj/item/stack/medical/bruise_pack/advanced(src)
|
||||
|
||||
|
||||
/obj/item/storage/firstaid/ert_amber
|
||||
name = "amber ert first-aid kit"
|
||||
desc = "A medical kit used by Amber level emergency response team personnel."
|
||||
icon_state = "firstaid"
|
||||
|
||||
/obj/item/storage/firstaid/ert_amber/populate_contents()
|
||||
new /obj/item/healthanalyzer/advanced(src)
|
||||
new /obj/item/reagent_containers/applicator/brute(src)
|
||||
new /obj/item/reagent_containers/applicator/burn(src)
|
||||
new /obj/item/stack/medical/bruise_pack/advanced(src)
|
||||
new /obj/item/stack/medical/ointment/advanced(src)
|
||||
new /obj/item/storage/pill_bottle/ert_amber(src)
|
||||
new /obj/item/storage/pill_bottle/patch_pack/ert_amber(src)
|
||||
|
||||
/obj/item/storage/firstaid/fake_tactical
|
||||
name = "tactical first-aid kit"
|
||||
desc = "I hope you've got insurance. The paint is still wet."
|
||||
icon_state = "bezerk"
|
||||
med_bot_skin = "bezerk"
|
||||
|
||||
/obj/item/storage/firstaid/fake_tactical/populate_contents()
|
||||
return
|
||||
|
||||
/*
|
||||
* Pill Bottles
|
||||
*/
|
||||
|
||||
/obj/item/storage/pill_bottle
|
||||
name = "pill bottle"
|
||||
desc = "It's an airtight container for storing medication."
|
||||
icon_state = "pill_canister"
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
item_state = "contsolid"
|
||||
belt_icon = "pill_bottle"
|
||||
use_sound = "pillbottle"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
can_hold = list(/obj/item/reagent_containers/pill)
|
||||
cant_hold = list(/obj/item/reagent_containers/patch)
|
||||
allow_quick_gather = TRUE
|
||||
use_to_pickup = TRUE
|
||||
storage_slots = 50
|
||||
max_combined_w_class = 50
|
||||
display_contents_with_number = TRUE
|
||||
var/base_name = ""
|
||||
var/label_text = ""
|
||||
var/applying_meds = FALSE //To Prevent spam clicking and generating runtimes from apply a deleting pill multiple times.
|
||||
var/rapid_intake_message = "unscrews the cap on the pill bottle and begins dumping the entire contents down their throat!"
|
||||
var/rapid_post_instake_message = "downs the entire bottle of pills in one go!"
|
||||
/// Whether to render a coloured wrapper overlay on the icon.
|
||||
var/allow_wrap = TRUE
|
||||
/// The color of the wrapper overlay.
|
||||
var/wrapper_color = null
|
||||
/// The icon state of the wrapper overlay.
|
||||
var/wrapper_state = "pillbottle_wrap"
|
||||
|
||||
/obj/item/storage/pill_bottle/Initialize(mapload)
|
||||
. = ..()
|
||||
base_name = name
|
||||
if(allow_wrap)
|
||||
apply_wrap()
|
||||
|
||||
/obj/item/storage/pill_bottle/proc/apply_wrap()
|
||||
if(wrapper_color)
|
||||
overlays.Cut()
|
||||
var/image/I = image(icon, wrapper_state)
|
||||
I.color = wrapper_color
|
||||
overlays += I
|
||||
|
||||
/obj/item/storage/pill_bottle/attack__legacy__attackchain(mob/M, mob/user)
|
||||
if(iscarbon(M) && length(contents))
|
||||
if(applying_meds)
|
||||
to_chat(user, "<span class='warning'>You are already applying meds.</span>")
|
||||
return
|
||||
applying_meds = TRUE
|
||||
for(var/obj/item/reagent_containers/P in contents)
|
||||
if(P.mob_act(M, user))
|
||||
applying_meds = FALSE
|
||||
else
|
||||
applying_meds = FALSE
|
||||
break
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/storage/pill_bottle/ert_red
|
||||
wrapper_color = COLOR_NT_RED
|
||||
|
||||
/obj/item/storage/pill_bottle/ert_red/populate_contents()
|
||||
for(var/I in 1 to 6)
|
||||
new /obj/item/reagent_containers/pill/pentetic(src)
|
||||
new /obj/item/reagent_containers/pill/ironsaline(src)
|
||||
new /obj/item/reagent_containers/pill/salicylic(src)
|
||||
new /obj/item/reagent_containers/pill/mannitol(src)
|
||||
|
||||
/obj/item/storage/pill_bottle/ert_amber
|
||||
wrapper_color = COLOR_ORANGE
|
||||
|
||||
/obj/item/storage/pill_bottle/ert_amber/populate_contents()
|
||||
for(var/I in 1 to 6)
|
||||
new /obj/item/reagent_containers/pill/salbutamol(src)
|
||||
new /obj/item/reagent_containers/pill/charcoal(src)
|
||||
new /obj/item/reagent_containers/pill/salicylic(src)
|
||||
|
||||
/obj/item/storage/pill_bottle/ert_gamma
|
||||
wrapper_color = COLOR_YELLOW_GRAY
|
||||
|
||||
/obj/item/storage/pill_bottle/ert_gamma/populate_contents()
|
||||
for(var/I in 1 to 6)
|
||||
new /obj/item/reagent_containers/pill/pentetic(src)
|
||||
new /obj/item/reagent_containers/pill/ironsaline(src)
|
||||
new /obj/item/reagent_containers/pill/hydrocodone(src)
|
||||
new /obj/item/reagent_containers/pill/mannitol(src)
|
||||
new /obj/item/reagent_containers/pill/lazarus_reagent(src)
|
||||
new /obj/item/reagent_containers/pill/rezadone(src)
|
||||
|
||||
/obj/item/storage/pill_bottle/MouseDrop(obj/over_object) // Best utilized if you're a cantankerous doctor with a Vicodin habit.
|
||||
if(iscarbon(over_object))
|
||||
var/mob/living/carbon/C = over_object
|
||||
if(loc == C && src == C.get_active_hand())
|
||||
if(!length(contents))
|
||||
to_chat(C, "<span class='notice'>There is nothing in [src]!</span>")
|
||||
return
|
||||
C.visible_message("<span class='danger'>[C] [rapid_intake_message]</span>")
|
||||
if(do_mob(C, C, 100)) // 10 seconds
|
||||
for(var/obj/item/reagent_containers/pill/P in contents)
|
||||
P.interact_with_atom(C, C)
|
||||
C.visible_message("<span class='danger'>[C] [rapid_post_instake_message]</span>")
|
||||
return
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/storage/pill_bottle/attackby__legacy__attackchain(obj/item/I, mob/user, params)
|
||||
if(is_pen(I))
|
||||
rename_interactive(user, I)
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/storage/pill_bottle/proc/apply_wrapper_color(color_number)
|
||||
var/static/list/colors = list(COLOR_RED, COLOR_ORANGE, COLOR_YELLOW, COLOR_GREEN, COLOR_CYAN_BLUE, COLOR_VIOLET, COLOR_PURPLE)
|
||||
wrapper_color = colors[(color_number - 1) % length(colors) + 1]
|
||||
apply_wrap()
|
||||
|
||||
/obj/item/storage/pill_bottle/patch_pack
|
||||
name = "patch pack"
|
||||
desc = "It's a container for storing medical patches."
|
||||
icon_state = "patch_pack"
|
||||
belt_icon = "patch_pack"
|
||||
use_sound = "patchpack"
|
||||
can_hold = list(/obj/item/reagent_containers/patch)
|
||||
cant_hold = list()
|
||||
rapid_intake_message = "flips the lid of the patch pack open and begins rapidly stamping patches on themselves!"
|
||||
rapid_post_instake_message = "stamps the entire contents of the patch pack all over their entire body!"
|
||||
wrapper_state = "patch_pack_wrap"
|
||||
|
||||
/obj/item/storage/pill_bottle/charcoal
|
||||
name = "Pill bottle (Charcoal)"
|
||||
desc = "Contains pills used to counter toxins."
|
||||
wrapper_color = COLOR_GREEN
|
||||
|
||||
/obj/item/storage/pill_bottle/charcoal/populate_contents()
|
||||
for(var/I in 1 to 7)
|
||||
new /obj/item/reagent_containers/pill/charcoal(src)
|
||||
|
||||
/obj/item/storage/pill_bottle/painkillers
|
||||
name = "Pill Bottle (Salicylic Acid)"
|
||||
desc = "Contains various pills for minor pain relief."
|
||||
wrapper_color = COLOR_RED
|
||||
|
||||
/obj/item/storage/pill_bottle/painkillers/populate_contents()
|
||||
for(var/I in 1 to 8)
|
||||
new /obj/item/reagent_containers/pill/salicylic(src)
|
||||
|
||||
/obj/item/storage/pill_bottle/fakedeath
|
||||
allow_wrap = FALSE
|
||||
|
||||
/obj/item/storage/pill_bottle/fakedeath/populate_contents()
|
||||
new /obj/item/reagent_containers/pill/fakedeath(src)
|
||||
new /obj/item/reagent_containers/pill/fakedeath(src)
|
||||
new /obj/item/reagent_containers/pill/fakedeath(src)
|
||||
|
||||
/obj/item/storage/pill_bottle/patch_pack/ert
|
||||
name = "ert red patch pack"
|
||||
desc = "A patch pack containing medical patches. Issued to Nanotrasen ERT Red level medics."
|
||||
wrapper_color = COLOR_NT_RED
|
||||
|
||||
/obj/item/storage/pill_bottle/patch_pack/ert/populate_contents()
|
||||
for(var/I in 1 to 5)
|
||||
new /obj/item/reagent_containers/patch/perfluorodecalin(src)
|
||||
new /obj/item/reagent_containers/patch/silver_sulf(src)
|
||||
new /obj/item/reagent_containers/patch/styptic(src)
|
||||
|
||||
/obj/item/storage/pill_bottle/patch_pack/ert/gamma
|
||||
name = "ert gamma patch pack"
|
||||
desc = "A patch pack containing medical patches. Issued to Nanotrasen ERT Gamma level medics."
|
||||
wrapper_color = COLOR_YELLOW_GRAY
|
||||
|
||||
/obj/item/storage/pill_bottle/patch_pack/ert_amber
|
||||
name = "ert amber patch pack"
|
||||
desc = "A patch pack containing medical patches. Issued to Nanotrasen ERT Amber level medics"
|
||||
wrapper_color = COLOR_ORANGE
|
||||
|
||||
/obj/item/storage/pill_bottle/patch_pack/ert_amber/populate_contents()
|
||||
for(var/I in 1 to 5)
|
||||
new /obj/item/reagent_containers/patch/silver_sulf/small(src)
|
||||
new /obj/item/reagent_containers/patch/styptic/small(src)
|
||||
@@ -1,394 +0,0 @@
|
||||
/obj/item/storage/bag/garment
|
||||
name = "garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes."
|
||||
icon_state = "garment_bag"
|
||||
slot_flags = NONE
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
max_w_class = WEIGHT_CLASS_NORMAL
|
||||
display_contents_with_number = FALSE
|
||||
max_combined_w_class = 200
|
||||
storage_slots = 27
|
||||
resistance_flags = FLAMMABLE
|
||||
can_hold = list(/obj/item/clothing)
|
||||
cant_hold = list(
|
||||
/obj/item/storage,
|
||||
/obj/item/clothing/suit/space,
|
||||
/obj/item/clothing/mask/cigarette,
|
||||
/obj/item/clothing/mask/facehugger, //Why would you do this
|
||||
/obj/item/clothing/accessory/medal,
|
||||
/obj/item/clothing/suit/armor/riot,
|
||||
/obj/item/clothing/suit/armor/reactive,
|
||||
/obj/item/clothing/suit/armor/laserproof,
|
||||
/obj/item/clothing/suit/hooded/ablative,
|
||||
/obj/item/clothing/gloves/color/black/krav_maga,
|
||||
)
|
||||
|
||||
/obj/item/storage/bag/garment/captain
|
||||
name = "captain's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the captain."
|
||||
|
||||
/obj/item/storage/bag/garment/captain/populate_contents()
|
||||
new /obj/item/clothing/head/caphat(src)
|
||||
new /obj/item/clothing/head/caphat/parade(src)
|
||||
new /obj/item/clothing/head/caphat/parade/white(src)
|
||||
new /obj/item/clothing/head/beret/captain(src)
|
||||
new /obj/item/clothing/head/beret/captain/white(src)
|
||||
new /obj/item/clothing/head/crown/fancy(src)
|
||||
new /obj/item/clothing/neck/cloak/captain(src)
|
||||
new /obj/item/clothing/suit/armor/vest/capcarapace(src)
|
||||
new /obj/item/clothing/suit/armor/vest/capcarapace/jacket(src)
|
||||
new /obj/item/clothing/suit/armor/vest/capcarapace/jacket/tunic(src)
|
||||
new /obj/item/clothing/suit/armor/vest/capcarapace/coat(src)
|
||||
new /obj/item/clothing/suit/armor/vest/capcarapace/coat/white(src)
|
||||
new /obj/item/clothing/neck/cloak/captain_mantle(src)
|
||||
new /obj/item/clothing/under/rank/captain(src)
|
||||
new /obj/item/clothing/under/rank/captain/skirt(src)
|
||||
new /obj/item/clothing/under/rank/captain/white(src)
|
||||
new /obj/item/clothing/under/rank/captain/skirt/white(src)
|
||||
new /obj/item/clothing/under/rank/captain/parade(src)
|
||||
new /obj/item/clothing/under/rank/captain/dress(src)
|
||||
new /obj/item/clothing/gloves/color/captain(src)
|
||||
new /obj/item/clothing/shoes/brown(src)
|
||||
new /obj/item/clothing/shoes/laceup(src)
|
||||
new /obj/item/clothing/glasses/sunglasses(src)
|
||||
new /obj/item/clothing/glasses/hud/security/sunglasses(src)
|
||||
new /obj/item/clothing/glasses/hud/health/sunglasses(src)
|
||||
new /obj/item/clothing/head/helmet/space/plasmaman/captain(src)
|
||||
new /obj/item/clothing/under/plasmaman/captain(src)
|
||||
|
||||
/obj/item/storage/bag/garment/head_of_personnel
|
||||
name = "head of personnel's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the head of personnel."
|
||||
|
||||
/obj/item/storage/bag/garment/head_of_personnel/populate_contents()
|
||||
new /obj/item/clothing/head/hop(src)
|
||||
new /obj/item/clothing/head/beret/hop(src)
|
||||
new /obj/item/clothing/neck/cloak/head_of_personnel(src)
|
||||
new /obj/item/clothing/neck/cloak/hop_mantle(src)
|
||||
new /obj/item/clothing/suit/armor/vest(src)
|
||||
new /obj/item/clothing/suit/hopcoat(src)
|
||||
new /obj/item/clothing/under/rank/civilian/hop(src)
|
||||
new /obj/item/clothing/under/rank/civilian/hop/skirt(src)
|
||||
new /obj/item/clothing/under/rank/civilian/hop/dress(src)
|
||||
new /obj/item/clothing/under/rank/civilian/hop/formal(src)
|
||||
new /obj/item/clothing/under/rank/civilian/hop/oldman(src)
|
||||
new /obj/item/clothing/under/suit/female(src)
|
||||
new /obj/item/clothing/shoes/brown(src)
|
||||
new /obj/item/clothing/shoes/black(src)
|
||||
new /obj/item/clothing/shoes/leather(src)
|
||||
new /obj/item/clothing/shoes/white(src)
|
||||
new /obj/item/clothing/glasses/sunglasses(src)
|
||||
new /obj/item/clothing/glasses/hud/skills/sunglasses(src)
|
||||
new /obj/item/clothing/head/helmet/space/plasmaman/hop(src)
|
||||
new /obj/item/clothing/under/plasmaman/hop(src)
|
||||
|
||||
/obj/item/storage/bag/garment/head_of_security
|
||||
name = "head of security's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the head of security."
|
||||
|
||||
/obj/item/storage/bag/garment/head_of_security/populate_contents()
|
||||
new /obj/item/clothing/head/hos(src)
|
||||
new /obj/item/clothing/head/beret/hos(src)
|
||||
new /obj/item/clothing/neck/cloak/head_of_security(src)
|
||||
new /obj/item/clothing/suit/armor/hos(src)
|
||||
new /obj/item/clothing/suit/armor/hos/alt(src)
|
||||
new /obj/item/clothing/neck/cloak/hos_mantle(src)
|
||||
new /obj/item/clothing/under/rank/security/head_of_security(src)
|
||||
new /obj/item/clothing/under/rank/security/formal/head_of_security(src)
|
||||
new /obj/item/clothing/under/rank/security/head_of_security/corporate(src)
|
||||
new /obj/item/clothing/under/rank/security/head_of_security/skirt(src)
|
||||
new /obj/item/clothing/under/rank/security/head_of_security/skirt/corporate(src)
|
||||
new /obj/item/clothing/glasses/hud/security/sunglasses(src)
|
||||
new /obj/item/clothing/head/helmet/space/plasmaman/security/hos(src)
|
||||
new /obj/item/clothing/under/plasmaman/security/hos(src)
|
||||
|
||||
/obj/item/storage/bag/garment/research_director
|
||||
name = "research director's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the research director."
|
||||
|
||||
/obj/item/storage/bag/garment/research_director/populate_contents()
|
||||
new /obj/item/clothing/head/rd (src)
|
||||
new /obj/item/clothing/head/beret/rd(src)
|
||||
new /obj/item/clothing/neck/cloak/research_director(src)
|
||||
new /obj/item/clothing/under/rank/rnd/rd(src)
|
||||
new /obj/item/clothing/under/rank/rnd/rd/skirt(src)
|
||||
new /obj/item/clothing/suit/storage/labcoat/rd(src)
|
||||
new /obj/item/clothing/neck/cloak/rd_mantle(src)
|
||||
new /obj/item/clothing/suit/storage/labcoat(src)
|
||||
new /obj/item/clothing/shoes/white(src)
|
||||
new /obj/item/clothing/gloves/color/latex(src)
|
||||
new /obj/item/clothing/glasses/science(src)
|
||||
new /obj/item/clothing/glasses/welding/superior(src)
|
||||
new /obj/item/clothing/glasses/hud/diagnostic/sunglasses(src)
|
||||
new /obj/item/clothing/head/helmet/space/plasmaman/rd(src)
|
||||
new /obj/item/clothing/under/plasmaman/rd(src)
|
||||
|
||||
|
||||
/obj/item/storage/bag/garment/chief_medical_officer
|
||||
name = "chief medical officer's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the chief medical officer."
|
||||
|
||||
/obj/item/storage/bag/garment/chief_medical_officer/populate_contents()
|
||||
new /obj/item/clothing/head/cmo (src)
|
||||
new /obj/item/clothing/head/beret/cmo (src)
|
||||
new /obj/item/clothing/head/surgery/blue(src)
|
||||
new /obj/item/clothing/head/surgery/green(src)
|
||||
new /obj/item/clothing/head/surgery/purple(src)
|
||||
new /obj/item/clothing/neck/cloak/chief_medical_officer(src)
|
||||
new /obj/item/clothing/under/rank/medical/cmo(src)
|
||||
new /obj/item/clothing/under/rank/medical/cmo/skirt(src)
|
||||
new /obj/item/clothing/under/rank/medical/scrubs(src)
|
||||
new /obj/item/clothing/under/rank/medical/scrubs/green(src)
|
||||
new /obj/item/clothing/under/rank/medical/scrubs/purple(src)
|
||||
new /obj/item/clothing/suit/storage/labcoat/cmo(src)
|
||||
new /obj/item/clothing/neck/cloak/cmo_mantle(src)
|
||||
new /obj/item/clothing/shoes/white(src)
|
||||
new /obj/item/clothing/shoes/brown (src)
|
||||
new /obj/item/clothing/gloves/color/latex/nitrile(src)
|
||||
new /obj/item/clothing/head/helmet/space/plasmaman/cmo(src)
|
||||
new /obj/item/clothing/under/plasmaman/cmo(src)
|
||||
|
||||
/obj/item/storage/bag/garment/chief_engineer
|
||||
name = "chief engineer's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the chief engineer."
|
||||
|
||||
/obj/item/storage/bag/garment/chief_engineer/populate_contents()
|
||||
new /obj/item/clothing/head/hardhat/white(src)
|
||||
new /obj/item/clothing/head/beret/ce(src)
|
||||
new /obj/item/clothing/head/beret/eng(src)
|
||||
new /obj/item/clothing/neck/cloak/chief_engineer(src)
|
||||
new /obj/item/clothing/under/rank/engineering/chief_engineer(src)
|
||||
new /obj/item/clothing/under/rank/engineering/chief_engineer/skirt(src)
|
||||
new /obj/item/clothing/neck/cloak/ce_mantle(src)
|
||||
new /obj/item/clothing/suit/storage/hazardvest/ce(src)
|
||||
new /obj/item/clothing/shoes/brown(src)
|
||||
new /obj/item/clothing/glasses/welding/superior(src)
|
||||
new /obj/item/clothing/glasses/meson/sunglasses(src)
|
||||
new /obj/item/clothing/gloves/color/yellow(src)
|
||||
new /obj/item/clothing/head/helmet/space/plasmaman/engineering/ce(src)
|
||||
new /obj/item/clothing/under/plasmaman/engineering/ce(src)
|
||||
|
||||
/obj/item/storage/bag/garment/nanotrasen_representative
|
||||
name = "\improper Nanotrasen representative's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the Nanotrasen representative."
|
||||
|
||||
/obj/item/storage/bag/garment/nanotrasen_representative/populate_contents()
|
||||
new /obj/item/clothing/head/ntrep(src)
|
||||
new /obj/item/clothing/under/rank/procedure/representative(src)
|
||||
new /obj/item/clothing/under/rank/procedure/representative/skirt(src)
|
||||
new /obj/item/clothing/under/rank/procedure/representative/formal(src)
|
||||
new /obj/item/clothing/under/suit/female(src)
|
||||
new /obj/item/clothing/shoes/centcom(src)
|
||||
new /obj/item/clothing/shoes/sandal/fancy(src)
|
||||
new /obj/item/clothing/glasses/hud/skills/sunglasses(src)
|
||||
new /obj/item/clothing/glasses/sunglasses(src)
|
||||
new /obj/item/clothing/gloves/color/white(src)
|
||||
new /obj/item/clothing/head/helmet/space/plasmaman/white(src)
|
||||
new /obj/item/clothing/under/plasmaman/enviroslacks(src)
|
||||
|
||||
/obj/item/storage/bag/garment/magistrate
|
||||
name = "magistrate's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the magistrate."
|
||||
|
||||
/obj/item/storage/bag/garment/magistrate/populate_contents()
|
||||
new /obj/item/clothing/head/justice_wig(src)
|
||||
new /obj/item/clothing/head/powdered_wig(src)
|
||||
new /obj/item/clothing/under/rank/procedure/magistrate(src)
|
||||
new /obj/item/clothing/under/rank/procedure/magistrate/skirt(src)
|
||||
new /obj/item/clothing/under/rank/procedure/magistrate/formal(src)
|
||||
new /obj/item/clothing/suit/magirobe(src)
|
||||
new /obj/item/clothing/shoes/centcom(src)
|
||||
new /obj/item/clothing/glasses/sunglasses(src)
|
||||
new /obj/item/clothing/gloves/color/white(src)
|
||||
new /obj/item/clothing/head/helmet/space/plasmaman/white(src)
|
||||
new /obj/item/clothing/under/plasmaman/enviroslacks(src)
|
||||
|
||||
/obj/item/storage/bag/garment/blueshield
|
||||
name = "blueshield's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the blueshield."
|
||||
|
||||
/obj/item/storage/bag/garment/blueshield/populate_contents()
|
||||
new /obj/item/clothing/head/beret/centcom/officer(src)
|
||||
new /obj/item/clothing/head/beret/centcom/officer/navy(src)
|
||||
new /obj/item/clothing/under/rank/procedure/blueshield(src)
|
||||
new /obj/item/clothing/under/rank/procedure/blueshield/skirt(src)
|
||||
new /obj/item/clothing/under/rank/procedure/blueshield/formal(src)
|
||||
new /obj/item/clothing/suit/armor/vest/blueshield(src)
|
||||
new /obj/item/clothing/suit/storage/blueshield(src)
|
||||
new /obj/item/clothing/shoes/centcom(src)
|
||||
new /obj/item/clothing/shoes/jackboots/jacksandals(src)
|
||||
new /obj/item/clothing/mask/gas/sechailer(src)
|
||||
new /obj/item/clothing/glasses/sunglasses(src)
|
||||
new /obj/item/clothing/glasses/hud/security/sunglasses(src)
|
||||
new /obj/item/clothing/glasses/hud/health/sunglasses(src)
|
||||
new /obj/item/clothing/glasses/hud/skills/sunglasses(src)
|
||||
new /obj/item/clothing/neck/tie/blue(src)
|
||||
new /obj/item/clothing/head/helmet/space/plasmaman/blueshield(src)
|
||||
new /obj/item/clothing/under/plasmaman/blueshield(src)
|
||||
|
||||
/obj/item/storage/bag/garment/quartermaster
|
||||
name = "quartermaster's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the quartermaster."
|
||||
|
||||
/obj/item/storage/bag/garment/quartermaster/populate_contents()
|
||||
new /obj/item/clothing/under/rank/cargo/qm(src)
|
||||
new /obj/item/clothing/under/rank/cargo/qm/skirt(src)
|
||||
new /obj/item/clothing/under/rank/cargo/qm/dress(src)
|
||||
new /obj/item/clothing/under/rank/cargo/qm/formal(src)
|
||||
new /obj/item/clothing/under/rank/cargo/qm/whimsy(src)
|
||||
new /obj/item/clothing/shoes/brown(src)
|
||||
new /obj/item/clothing/head/qm(src)
|
||||
new /obj/item/clothing/head/beret/qm(src)
|
||||
new /obj/item/clothing/neck/cloak/quartermaster(src)
|
||||
new /obj/item/clothing/head/hardhat/orange(src)
|
||||
new /obj/item/clothing/suit/qmcoat(src)
|
||||
new /obj/item/clothing/neck/cloak/qm_mantle(src)
|
||||
new /obj/item/clothing/suit/storage/hazardvest/qm(src)
|
||||
new /obj/item/clothing/gloves/color/black(src)
|
||||
new /obj/item/tank/internals/emergency_oxygen/double(src)
|
||||
new /obj/item/clothing/head/helmet/space/plasmaman/cargo(src)
|
||||
new /obj/item/clothing/under/plasmaman/cargo(src)
|
||||
|
||||
/obj/item/storage/bag/garment/warden
|
||||
name = "warden's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the warden."
|
||||
|
||||
/obj/item/storage/bag/garment/warden/populate_contents()
|
||||
new /obj/item/clothing/suit/armor/vest/warden(src)
|
||||
new /obj/item/clothing/head/warden(src)
|
||||
new /obj/item/clothing/suit/armor/vest/warden/alt(src)
|
||||
new /obj/item/clothing/head/beret/warden(src)
|
||||
new /obj/item/clothing/under/rank/security/warden(src)
|
||||
new /obj/item/clothing/under/rank/security/formal/warden(src)
|
||||
new /obj/item/clothing/under/rank/security/warden/corporate(src)
|
||||
new /obj/item/clothing/under/rank/security/warden/skirt(src)
|
||||
new /obj/item/clothing/under/rank/security/warden/skirt/corporate(src)
|
||||
new /obj/item/clothing/mask/gas/sechailer/swat/warden(src)
|
||||
new /obj/item/clothing/glasses/hud/security/sunglasses(src)
|
||||
new /obj/item/clothing/head/helmet/space/plasmaman/security/warden(src)
|
||||
new /obj/item/clothing/under/plasmaman/security/warden(src)
|
||||
|
||||
/obj/item/storage/bag/garment/detective
|
||||
name = "detective's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the detective."
|
||||
|
||||
/obj/item/storage/bag/garment/detective/populate_contents()
|
||||
new /obj/item/clothing/under/rank/security/detective(src)
|
||||
new /obj/item/clothing/suit/storage/det_suit(src)
|
||||
new /obj/item/clothing/suit/storage/det_suit/forensics/blue(src)
|
||||
new /obj/item/clothing/suit/storage/det_suit/forensics/red(src)
|
||||
new /obj/item/clothing/gloves/color/black/forensics(src)
|
||||
new /obj/item/clothing/head/det_hat(src)
|
||||
new /obj/item/clothing/shoes/brown(src)
|
||||
new /obj/item/clothing/suit/armor/vest/det_suit(src)
|
||||
new /obj/item/clothing/neck/tie/black(src)
|
||||
new /obj/item/clothing/accessory/holster/armpit(src)
|
||||
new /obj/item/clothing/glasses/sunglasses/yeah(src)
|
||||
|
||||
/obj/item/storage/bag/garment/chaplain
|
||||
name = "chaplain's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the chaplain."
|
||||
|
||||
/obj/item/storage/bag/garment/chaplain/populate_contents()
|
||||
new /obj/item/clothing/under/rank/civilian/chaplain(src)
|
||||
new /obj/item/clothing/shoes/black(src)
|
||||
new /obj/item/clothing/suit/hooded/abaya(src)
|
||||
new /obj/item/clothing/suit/hooded/nun(src)
|
||||
new /obj/item/clothing/suit/hooded/chaplain_hoodie(src)
|
||||
new /obj/item/clothing/suit/hooded/monk(src)
|
||||
new /obj/item/clothing/suit/witchhunter(src)
|
||||
new /obj/item/clothing/head/witchhunter_hat(src)
|
||||
new /obj/item/clothing/suit/holidaypriest(src)
|
||||
new /obj/item/clothing/head/helmet/riot/knight/templar(src)
|
||||
new /obj/item/clothing/suit/armor/riot/knight/templar(src)
|
||||
new /obj/item/clothing/suit/storage/labcoat(src)
|
||||
new /obj/item/clothing/head/helmet/space/plasmaman/chaplain(src)
|
||||
new /obj/item/clothing/under/plasmaman/chaplain(src)
|
||||
|
||||
/obj/item/storage/bag/garment/psychologist
|
||||
name = "psychologist's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the psychologist."
|
||||
|
||||
/obj/item/storage/bag/garment/psychologist/populate_contents()
|
||||
new /obj/item/clothing/under/rank/medical/psych(src)
|
||||
new /obj/item/clothing/under/rank/medical/psych/turtleneck(src)
|
||||
new /obj/item/clothing/under/rank/medical/doctor(src)
|
||||
new /obj/item/clothing/under/rank/medical/doctor/skirt(src)
|
||||
new /obj/item/clothing/suit/storage/labcoat/psych(src)
|
||||
new /obj/item/clothing/shoes/laceup(src)
|
||||
new /obj/item/clothing/glasses/hud/health(src)
|
||||
new /obj/item/clothing/glasses/hud/skills(src)
|
||||
new /obj/item/clothing/neck/tie/blue(src)
|
||||
new /obj/item/clothing/head/helmet/space/plasmaman(src)
|
||||
new /obj/item/clothing/under/plasmaman(src)
|
||||
|
||||
/obj/item/storage/bag/garment/paramedic
|
||||
name = "paramedic's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the paramedic."
|
||||
|
||||
/obj/item/storage/bag/garment/paramedic/populate_contents()
|
||||
new /obj/item/clothing/under/rank/medical/paramedic(src)
|
||||
new /obj/item/clothing/under/rank/medical/paramedic/skirt(src)
|
||||
new /obj/item/clothing/head/soft/paramedic(src)
|
||||
new /obj/item/clothing/head/beret/paramedic(src)
|
||||
new /obj/item/clothing/suit/storage/labcoat/emt(src)
|
||||
new /obj/item/clothing/suit/storage/hazardvest/paramedic(src)
|
||||
new /obj/item/clothing/glasses/hud/health/sunglasses(src)
|
||||
new /obj/item/clothing/gloves/color/latex(src)
|
||||
new /obj/item/clothing/gloves/color/latex/nitrile(src)
|
||||
new /obj/item/clothing/shoes/black(src)
|
||||
new /obj/item/clothing/head/helmet/space/plasmaman/medical(src)
|
||||
new /obj/item/clothing/under/plasmaman/medical(src)
|
||||
|
||||
/obj/item/storage/bag/garment/explorer
|
||||
name = "explorer's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the explorer."
|
||||
|
||||
/obj/item/storage/bag/garment/explorer/populate_contents()
|
||||
new /obj/item/clothing/under/rank/cargo/expedition(src)
|
||||
new /obj/item/clothing/under/rank/cargo/expedition/overalls(src)
|
||||
new /obj/item/clothing/head/soft/expedition(src)
|
||||
new /obj/item/clothing/head/beret/expedition(src)
|
||||
new /obj/item/clothing/gloves/color/black(src)
|
||||
new /obj/item/clothing/shoes/jackboots(src)
|
||||
new /obj/item/clothing/mask/gas/explorer(src)
|
||||
|
||||
/obj/item/storage/bag/garment/smith
|
||||
name = "smith's garment bag"
|
||||
desc = "A bag for storing extra clothes and shoes. This one belongs to the smith."
|
||||
|
||||
/obj/item/storage/bag/garment/smith/populate_contents()
|
||||
new /obj/item/clothing/under/rank/cargo/smith(src)
|
||||
new /obj/item/clothing/under/rank/cargo/smith/skirt(src)
|
||||
new /obj/item/clothing/under/rank/cargo/smith/overalls(src)
|
||||
new /obj/item/clothing/suit/apron/smith(src)
|
||||
new /obj/item/clothing/suit/jacket/bomber/smith(src)
|
||||
new /obj/item/clothing/head/soft/smith(src)
|
||||
new /obj/item/clothing/head/beret/smith(src)
|
||||
new /obj/item/clothing/gloves/smithing(src)
|
||||
new /obj/item/clothing/shoes/workboots/smithing(src)
|
||||
new /obj/item/clothing/under/plasmaman/smith(src)
|
||||
new /obj/item/clothing/head/helmet/space/plasmaman/smith(src)
|
||||
|
||||
/obj/item/storage/bag/garment/syndie
|
||||
name = "suspicious garment bag"
|
||||
icon_state = "garment_bag_syndie"
|
||||
desc = "A bag for storing extra clothes and shoes. Judging by the colors, this one belongs to someone with malicious intent."
|
||||
|
||||
/obj/item/storage/bag/garment/syndie/populate_contents()
|
||||
new /obj/item/clothing/under/syndicate/tacticool(src)
|
||||
new /obj/item/clothing/under/syndicate(src)
|
||||
new /obj/item/clothing/under/syndicate/combat(src)
|
||||
new /obj/item/clothing/under/syndicate/greyman(src)
|
||||
new /obj/item/clothing/under/syndicate/sniper(src)
|
||||
new /obj/item/clothing/mask/gas/syndicate(src)
|
||||
new /obj/item/clothing/mask/balaclava(src)
|
||||
new /obj/item/clothing/suit/storage/iaa/blackjacket(src)
|
||||
new /obj/item/clothing/suit/blacktrenchcoat(src)
|
||||
new /obj/item/clothing/head/beret/syndicate(src)
|
||||
new /obj/item/clothing/glasses/syndie(src)
|
||||
new /obj/item/clothing/neck/cloak/syndicate(src)
|
||||
new /obj/item/clothing/gloves/color/black(src)
|
||||
new /obj/item/clothing/gloves/fingerless(src)
|
||||
new /obj/item/clothing/shoes/combat(src)
|
||||
new /obj/item/clothing/shoes/laceup(src)
|
||||
@@ -1,88 +0,0 @@
|
||||
//A storage item intended to be used by other items to provide storage functionality.
|
||||
//Types that use this should consider overriding emp_act() and hear_talk(), unless they shield their contents somehow.
|
||||
/obj/item/storage/internal
|
||||
var/obj/item/master_item
|
||||
|
||||
/obj/item/storage/internal/New(obj/item/MI)
|
||||
master_item = MI
|
||||
loc = master_item
|
||||
name = master_item.name
|
||||
..()
|
||||
|
||||
/obj/item/storage/internal/Destroy()
|
||||
master_item = null
|
||||
return ..()
|
||||
|
||||
/obj/item/storage/internal/attack_hand()
|
||||
return //make sure this is never picked up
|
||||
|
||||
/obj/item/storage/internal/mob_can_equip(mob/M, slot, disable_warning = FALSE)
|
||||
return 0 //make sure this is never picked up
|
||||
|
||||
//Helper procs to cleanly implement internal storages - storage items that provide inventory slots for other items.
|
||||
//These procs are completely optional, it is up to the master item to decide when it's storage get's opened by calling open()
|
||||
//However they are helpful for allowing the master item to pretend it is a storage item itself.
|
||||
//If you are using these you will probably want to override attackby__legacy__attackchain() as well.
|
||||
//See /obj/item/clothing/suit/storage for an example.
|
||||
|
||||
//items that use internal storage have the option of calling this to emulate default storage MouseDrop behaviour.
|
||||
//returns 1 if the master item's parent's MouseDrop() should be called, 0 otherwise. It's strange, but no other way of
|
||||
//doing it without the ability to call another proc's parent, really.
|
||||
/obj/item/storage/internal/proc/handle_mousedrop(mob/user as mob, obj/over_object as obj)
|
||||
if(ishuman(user)) //so monkeys can take off their backpacks -- Urist
|
||||
|
||||
if(ismecha(user.loc)) // stops inventory actions in a mech
|
||||
return 0
|
||||
|
||||
if(over_object == user && Adjacent(user)) // this must come before the screen objects only block
|
||||
open(user)
|
||||
return FALSE
|
||||
|
||||
if(!is_screen_atom(over_object))
|
||||
return TRUE
|
||||
|
||||
//makes sure master_item is equipped before putting it in hand, so that we can't drag it into our hand from miles away.
|
||||
//there's got to be a better way of doing this...
|
||||
if(!(master_item.loc == user) || (master_item.loc && master_item.loc.loc == user))
|
||||
return 0
|
||||
|
||||
if(!user.restrained() && !user.stat)
|
||||
switch(over_object.name)
|
||||
if("r_hand")
|
||||
user.unequip(master_item)
|
||||
user.put_in_r_hand(master_item)
|
||||
if("l_hand")
|
||||
user.unequip(master_item)
|
||||
user.put_in_l_hand(master_item)
|
||||
master_item.add_fingerprint(user)
|
||||
return 0
|
||||
return 0
|
||||
|
||||
//items that use internal storage have the option of calling this to emulate default storage attack_hand behaviour.
|
||||
//returns 1 if the master item's parent's attack_hand() should be called, 0 otherwise.
|
||||
//It's strange, but no other way of doing it without the ability to call another proc's parent, really.
|
||||
/obj/item/storage/internal/proc/handle_attack_hand(mob/user as mob)
|
||||
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.l_store == master_item && !H.get_active_hand()) //Prevents opening if it's in a pocket.
|
||||
H.put_in_hands(master_item)
|
||||
H.l_store = null
|
||||
return 0
|
||||
if(H.r_store == master_item && !H.get_active_hand())
|
||||
H.put_in_hands(master_item)
|
||||
H.r_store = null
|
||||
return 0
|
||||
|
||||
add_fingerprint(user)
|
||||
if(master_item.loc == user)
|
||||
open(user)
|
||||
return 0
|
||||
|
||||
for(var/mob/M in range(1, master_item.loc))
|
||||
if(M.s_active == src)
|
||||
close(M)
|
||||
return 1
|
||||
|
||||
/obj/item/storage/internal/Adjacent(atom/neighbor)
|
||||
return master_item.Adjacent(neighbor)
|
||||
@@ -1,796 +0,0 @@
|
||||
// To clarify:
|
||||
// For use_to_pickup and allow_quick_gather functionality,
|
||||
// see item/attackby() (/game/objects/items.dm, params)
|
||||
// Do not remove this functionality without good reason, cough reagent_containers cough.
|
||||
// -Sayu
|
||||
|
||||
|
||||
/obj/item/storage
|
||||
name = "storage"
|
||||
icon = 'icons/obj/storage.dmi'
|
||||
flags_2 = BLOCKS_LIGHT_2
|
||||
/// No message on putting items in.
|
||||
var/silent = FALSE
|
||||
/// List of objects which this item can store (if set, it can't store anything else)
|
||||
var/list/can_hold = list()
|
||||
/// List of objects that can be stored, regardless of w_class
|
||||
var/list/w_class_override = list()
|
||||
/// List of objects which this item can't store (in effect only if can_hold isn't set)
|
||||
var/list/cant_hold = list()
|
||||
/// List of objects which this item overrides the cant_hold list (used to negate cant_hold on specific items. Ex: Allowing Smuggler's Satchels (subtype of backpack) to be stored inside bags of holding.)
|
||||
var/list/cant_hold_override = list()
|
||||
/// Max size of objects that this object can store (in effect only if can_hold isn't set)
|
||||
var/max_w_class = WEIGHT_CLASS_SMALL
|
||||
/// The sum of the w_classes of all the items in this storage item.
|
||||
var/max_combined_w_class = 14
|
||||
/// The number of storage slots in this container.
|
||||
var/storage_slots = 7
|
||||
var/atom/movable/screen/storage/boxes = null
|
||||
var/atom/movable/screen/close/closer = null
|
||||
|
||||
/// Set this to make it possible to use this item in an inverse way, so you can have the item in your hand and click items on the floor to pick them up.
|
||||
var/use_to_pickup = FALSE
|
||||
/// Set this to make the storage item group contents of the same type and display them as a number.
|
||||
var/display_contents_with_number
|
||||
/// Set this variable to allow the object to have the 'empty' verb, which dumps all the contents on the floor.
|
||||
var/allow_quick_empty
|
||||
/// Set this variable to allow the object to have the 'toggle mode' verb, which quickly collects all items from a tile.
|
||||
var/allow_quick_gather
|
||||
/// Pick up one item at a time or everything on the tile
|
||||
var/pickup_all_on_tile = TRUE
|
||||
/// Sound played when used. `null` for no sound.
|
||||
var/use_sound = "rustle"
|
||||
/// What kind of [/obj/item/stack] can this be folded into. (e.g. Boxes and cardboard)
|
||||
var/foldable = null
|
||||
/// How much of the stack item do you get.
|
||||
var/foldable_amt = 0
|
||||
|
||||
/// Lazy list of mobs which are currently viewing the storage inventory.
|
||||
var/list/mobs_viewing
|
||||
|
||||
// Allow storage items of the same size to be put inside
|
||||
var/allow_same_size = FALSE
|
||||
|
||||
/obj/item/storage/Initialize(mapload)
|
||||
. = ..()
|
||||
can_hold = typecacheof(can_hold)
|
||||
cant_hold = typecacheof(cant_hold) - typecacheof(cant_hold_override)
|
||||
|
||||
populate_contents()
|
||||
|
||||
boxes = new /atom/movable/screen/storage()
|
||||
boxes.name = "storage"
|
||||
boxes.master = src
|
||||
boxes.icon_state = "block"
|
||||
boxes.screen_loc = "7,7 to 10,8"
|
||||
boxes.layer = HUD_LAYER
|
||||
boxes.plane = HUD_PLANE
|
||||
closer = new /atom/movable/screen/close()
|
||||
closer.master = src
|
||||
closer.icon_state = "backpack_close"
|
||||
closer.layer = ABOVE_HUD_LAYER
|
||||
closer.plane = ABOVE_HUD_PLANE
|
||||
orient2hud()
|
||||
|
||||
ADD_TRAIT(src, TRAIT_ADJACENCY_TRANSPARENT, ROUNDSTART_TRAIT)
|
||||
RegisterSignal(src, COMSIG_ATOM_EXITED, PROC_REF(on_atom_exited))
|
||||
|
||||
/obj/item/storage/Destroy()
|
||||
for(var/obj/O in contents)
|
||||
O.mouse_opacity = initial(O.mouse_opacity)
|
||||
|
||||
QDEL_NULL(boxes)
|
||||
QDEL_NULL(closer)
|
||||
LAZYCLEARLIST(mobs_viewing)
|
||||
return ..()
|
||||
|
||||
/obj/item/storage/examine(mob/user)
|
||||
. = ..()
|
||||
if(allow_quick_empty)
|
||||
. += "<span class='notice'>You can use [src] in hand to empty it's entire contents.</span>"
|
||||
if(allow_quick_gather)
|
||||
. += "<span class='notice'>You can <b>Alt-Shift-Click</b> [src] to switch it's gathering method.</span>"
|
||||
|
||||
/obj/item/storage/forceMove(atom/destination)
|
||||
. = ..()
|
||||
if(!ismob(destination.loc))
|
||||
for(var/mob/player in mobs_viewing)
|
||||
if(player == destination)
|
||||
continue
|
||||
hide_from(player)
|
||||
|
||||
/obj/item/storage/proc/removal_allowed_check(mob/user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/storage/proc/dump_storage(mob/user, obj/item/storage/target)
|
||||
if(!length(contents) || user.restrained() || (HAS_TRAIT(user, TRAIT_HANDS_BLOCKED)) || !user.can_reach(target) || src == target)
|
||||
return
|
||||
for(var/obj/item/thing in contents)
|
||||
if(!target.can_be_inserted(thing))
|
||||
continue
|
||||
if(!do_after(user, 0.3 SECONDS, target = user))
|
||||
break
|
||||
playsound(loc, "rustle", 50, TRUE, -5)
|
||||
target.handle_item_insertion(thing, user)
|
||||
|
||||
/obj/item/storage/MouseDrop(obj/over_object, src_location, over_location, src_control, over_control, params)
|
||||
if(!ismob(usr)) //so monkeys can take off their backpacks -- Urist
|
||||
return
|
||||
var/mob/M = usr
|
||||
|
||||
if(ismecha(M.loc) || M.incapacitated(FALSE, TRUE)) // Stops inventory actions in a mech as well as while being incapacitated
|
||||
return
|
||||
|
||||
if(over_object == M && Adjacent(M)) // this must come before the screen objects only block
|
||||
if(M.s_active)
|
||||
M.s_active.close(M)
|
||||
open(M)
|
||||
return
|
||||
|
||||
if(isstorage(over_object))
|
||||
var/obj/item/storage = over_object
|
||||
if(!storage.in_storage)
|
||||
dump_storage(M, over_object)
|
||||
return
|
||||
else if(ismodcontrol(over_object))
|
||||
var/obj/item/mod/control/mod = over_object
|
||||
dump_storage(M, mod.bag)
|
||||
return
|
||||
|
||||
if((istype(over_object, /obj/structure/table) || isfloorturf(over_object)) && length(contents) \
|
||||
&& loc == M && !M.stat && !M.restrained() && !HAS_TRAIT(M, TRAIT_HANDS_BLOCKED) && over_object.Adjacent(M) && !istype(src, /obj/item/storage/lockbox)) // Worlds longest `if()`
|
||||
var/turf/T = get_turf(over_object)
|
||||
if(!removal_allowed_check(M))
|
||||
return
|
||||
|
||||
if(isfloorturf(over_object))
|
||||
if(get_turf(M) != T)
|
||||
return // Can only empty containers onto the floor under you
|
||||
if(tgui_alert(M, "Empty [src] onto [T]?", "Confirm", list("Yes", "No")) != "Yes")
|
||||
return
|
||||
if(!(M && over_object && length(contents) && loc == M && !M.stat && !M.restrained() && !HAS_TRAIT(M, TRAIT_HANDS_BLOCKED) && get_turf(M) == T))
|
||||
return // Something happened while the player was thinking
|
||||
hide_from(M)
|
||||
M.face_atom(over_object)
|
||||
M.visible_message("<span class='notice'>[M] empties [src] onto [over_object].</span>",
|
||||
"<span class='notice'>You empty [src] onto [over_object].</span>")
|
||||
var/list/params_list = params2list(params)
|
||||
var/x_offset = text2num(params_list["icon-x"]) - 16
|
||||
var/y_offset = text2num(params_list["icon-y"]) - 16
|
||||
for(var/obj/item/I in contents)
|
||||
remove_from_storage(I, T)
|
||||
I.scatter_atom(x_offset, y_offset)
|
||||
update_icon() // For content-sensitive icons
|
||||
return
|
||||
|
||||
if(!is_screen_atom(over_object))
|
||||
return ..()
|
||||
if(!(loc == M) || (loc && loc.loc == M))
|
||||
return
|
||||
if(!M.restrained() && !M.stat)
|
||||
switch(over_object.name)
|
||||
if("r_hand")
|
||||
if(!M.unequip(src))
|
||||
return
|
||||
M.put_in_r_hand(src)
|
||||
if("l_hand")
|
||||
if(!M.unequip(src))
|
||||
return
|
||||
M.put_in_l_hand(src)
|
||||
add_fingerprint(usr)
|
||||
return
|
||||
if(over_object == usr && in_range(src, usr) || usr.contents.Find(src))
|
||||
if(usr.s_active)
|
||||
usr.s_active.close(usr)
|
||||
open(usr)
|
||||
|
||||
/obj/item/storage/AltClick(mob/user)
|
||||
if(ishuman(user) && Adjacent(user) && !user.incapacitated(FALSE, TRUE))
|
||||
open(user)
|
||||
add_fingerprint(user)
|
||||
else if(isobserver(user))
|
||||
show_to(user)
|
||||
|
||||
/**
|
||||
* Loops through any nested containers inside `src`, and returns a list of everything inside them.
|
||||
*
|
||||
* Currently checks for storage containers, gifts containing storage containers, and folders.
|
||||
*/
|
||||
/obj/item/storage/proc/return_inv()
|
||||
var/list/L = list()
|
||||
L += contents // Inventory of the main storage item
|
||||
|
||||
for(var/obj/item/storage/S in src) // Inventory of nested storage items
|
||||
L += S.return_inv()
|
||||
for(var/obj/item/gift/G in src)
|
||||
L += G.gift
|
||||
if(isstorage(G.gift)) // If the gift contains a storage item
|
||||
var/obj/item/storage/S = G.gift
|
||||
L += S.return_inv()
|
||||
for(var/obj/item/folder/F in src)
|
||||
L += F.contents
|
||||
return L
|
||||
|
||||
/**
|
||||
* Shows `user` the contents of `src`, and activates any mouse trap style triggers.
|
||||
*/
|
||||
/obj/item/storage/proc/show_to(mob/user)
|
||||
if(!user.client)
|
||||
return
|
||||
if(user.s_active != src && !isobserver(user))
|
||||
for(var/obj/item/I in src)
|
||||
if(I.on_found(user)) // For mouse traps and such
|
||||
return // If something triggered, don't open the UI
|
||||
orient2hud(user) // this only needs to happen to make .contents show properly as screen objects.
|
||||
if(user.s_active)
|
||||
user.s_active.hide_from(user) // If there's already an interface open, close it.
|
||||
user.client.screen |= boxes
|
||||
user.client.screen |= closer
|
||||
user.client.screen |= contents
|
||||
user.s_active = src
|
||||
LAZYDISTINCTADD(mobs_viewing, user)
|
||||
|
||||
/**
|
||||
* Hides the current container interface from `user`.
|
||||
*/
|
||||
/obj/item/storage/proc/hide_from(mob/user)
|
||||
LAZYREMOVE(mobs_viewing, user) // Remove clientless mobs too
|
||||
if(!user.client)
|
||||
return
|
||||
user.client.screen -= boxes
|
||||
user.client.screen -= closer
|
||||
user.client.screen -= contents
|
||||
if(user.s_active == src)
|
||||
user.s_active = null
|
||||
|
||||
/**
|
||||
* Hides the current container interface from all viewers.
|
||||
*/
|
||||
/obj/item/storage/proc/hide_from_all()
|
||||
for(var/mob/M in mobs_viewing)
|
||||
hide_from(M)
|
||||
|
||||
/**
|
||||
* Checks all mobs currently viewing the storage inventory, and hides it if they shouldn't be able to see it.
|
||||
*/
|
||||
/obj/item/storage/proc/update_viewers()
|
||||
for(var/_M in mobs_viewing)
|
||||
var/mob/M = _M
|
||||
if(!QDELETED(M) && M.s_active == src && Adjacent(M))
|
||||
continue
|
||||
hide_from(M)
|
||||
for(var/obj/item/storage/child in src)
|
||||
child.update_viewers()
|
||||
|
||||
/obj/item/storage/Moved(atom/oldloc, dir, forced = FALSE)
|
||||
. = ..()
|
||||
update_viewers()
|
||||
|
||||
/obj/item/storage/proc/open(mob/user)
|
||||
if(isobserver(user))
|
||||
show_to(user)
|
||||
return
|
||||
if(use_sound && isliving(user))
|
||||
playsound(loc, use_sound, 50, TRUE, -5)
|
||||
|
||||
if(user.s_active)
|
||||
user.s_active.close(user)
|
||||
show_to(user)
|
||||
|
||||
/obj/item/storage/proc/close(mob/user)
|
||||
hide_from(user)
|
||||
user.s_active = null
|
||||
|
||||
/**
|
||||
* Draws the inventory and places the items on it using custom positions.
|
||||
*
|
||||
* `tx` and `ty` are the upper left tile.
|
||||
* `mx` and `my` are the bottom right tile.
|
||||
*
|
||||
* The numbers are calculated from the bottom left, with the bottom left being `1,1`.
|
||||
*/
|
||||
/obj/item/storage/proc/orient_objs(tx, ty, mx, my)
|
||||
var/cx = tx
|
||||
var/cy = ty
|
||||
boxes.screen_loc = "[tx],[ty] to [mx],[my]"
|
||||
for(var/obj/O in contents)
|
||||
O.screen_loc = "[cx],[cy]"
|
||||
O.layer = ABOVE_HUD_LAYER
|
||||
O.plane = ABOVE_HUD_PLANE
|
||||
cx++
|
||||
if(cx > mx)
|
||||
cx = tx
|
||||
cy--
|
||||
closer.screen_loc = "[mx + 1],[my]"
|
||||
|
||||
//This proc draws out the inventory and places the items on it. It uses the standard position.
|
||||
/obj/item/storage/proc/standard_orient_objs(rows, cols, list/datum/numbered_display/display_contents)
|
||||
var/cx = 4
|
||||
var/cy = 2 + rows
|
||||
boxes.screen_loc = "4:16,2:16 to [4 + cols]:16,[2 + rows]:16"
|
||||
|
||||
if(display_contents_with_number)
|
||||
for(var/datum/numbered_display/ND in display_contents)
|
||||
ND.sample_object.mouse_opacity = MOUSE_OPACITY_OPAQUE
|
||||
ND.sample_object.screen_loc = "[cx]:16,[cy]:16"
|
||||
ND.sample_object.maptext = "<font color='white' face='Small Fonts'>[(ND.number > 1) ? "[ND.number]" : ""]</font>"
|
||||
ND.sample_object.layer = ABOVE_HUD_LAYER
|
||||
ND.sample_object.plane = ABOVE_HUD_PLANE
|
||||
cx++
|
||||
if(cx > (4 + cols))
|
||||
cx = 4
|
||||
cy--
|
||||
else
|
||||
for(var/obj/O in contents)
|
||||
O.mouse_opacity = MOUSE_OPACITY_OPAQUE //This is here so storage items that spawn with contents correctly have the "click around item to equip"
|
||||
O.screen_loc = "[cx]:16,[cy]:16"
|
||||
O.maptext = ""
|
||||
O.layer = ABOVE_HUD_LAYER
|
||||
O.plane = ABOVE_HUD_PLANE
|
||||
cx++
|
||||
if(cx > (4 + cols))
|
||||
cx = 4
|
||||
cy--
|
||||
closer.screen_loc = "[4 + cols + 1]:16,2:16"
|
||||
|
||||
/datum/numbered_display
|
||||
var/obj/item/sample_object
|
||||
var/number
|
||||
|
||||
/datum/numbered_display/New(obj/item/sample)
|
||||
if(!istype(sample))
|
||||
qdel(src)
|
||||
return
|
||||
sample_object = sample
|
||||
number = 1
|
||||
|
||||
//This proc determins the size of the inventory to be displayed. Please touch it only if you know what you're doing.
|
||||
/obj/item/storage/proc/orient2hud(mob/user)
|
||||
var/adjusted_contents = length(contents)
|
||||
|
||||
//Numbered contents display
|
||||
var/list/datum/numbered_display/numbered_contents
|
||||
if(display_contents_with_number)
|
||||
for(var/obj/O in contents)
|
||||
O.layer = initial(O.layer)
|
||||
O.plane = initial(O.plane)
|
||||
|
||||
numbered_contents = list()
|
||||
adjusted_contents = 0
|
||||
for(var/obj/item/I in contents)
|
||||
var/found = FALSE
|
||||
for(var/datum/numbered_display/ND in numbered_contents)
|
||||
if(ND.sample_object.should_stack_with(I))
|
||||
ND.number++
|
||||
found = TRUE
|
||||
break
|
||||
if(!found)
|
||||
adjusted_contents++
|
||||
numbered_contents += new/datum/numbered_display(I)
|
||||
|
||||
var/row_num = 0
|
||||
var/col_count = min(7, storage_slots) - 1
|
||||
if(adjusted_contents > 7)
|
||||
row_num = round((adjusted_contents - 1) / 7) // 7 is the maximum allowed width.
|
||||
standard_orient_objs(row_num, col_count, numbered_contents)
|
||||
|
||||
/**
|
||||
* Checks whether `I` can be inserted into the container.
|
||||
*
|
||||
* Returns `TRUE` if it can, and `FALSE` if it can't.
|
||||
* Arguments:
|
||||
* * obj/item/I - The item to insert
|
||||
* * stop_messages - Don't display a warning message if the item can't be inserted
|
||||
*/
|
||||
/obj/item/storage/proc/can_be_inserted(obj/item/I, stop_messages = FALSE)
|
||||
if(!istype(I) || (I.flags & ABSTRACT)) // Not an item
|
||||
return
|
||||
|
||||
if(loc == I)
|
||||
return FALSE //Means the item is already in the storage item
|
||||
|
||||
if(!I.can_enter_storage(src, usr))
|
||||
return FALSE
|
||||
|
||||
if(length(contents) >= storage_slots)
|
||||
if(!stop_messages)
|
||||
to_chat(usr, "<span class='warning'>[I] won't fit in [src], make some space!</span>")
|
||||
return FALSE //Storage item is full
|
||||
|
||||
if(length(can_hold))
|
||||
if(!is_type_in_typecache(I, can_hold))
|
||||
if(!stop_messages)
|
||||
to_chat(usr, "<span class='warning'>[src] cannot hold [I].</span>")
|
||||
return FALSE
|
||||
|
||||
if(is_type_in_typecache(I, cant_hold)) //Check for specific items which this container can't hold.
|
||||
if(!stop_messages)
|
||||
to_chat(usr, "<span class='warning'>[src] cannot hold [I].</span>")
|
||||
return FALSE
|
||||
|
||||
if(length(cant_hold) && isstorage(I)) //Checks nested storage contents for restricted objects, we don't want people sneaking the NAD in via boxes now, do we?
|
||||
var/obj/item/storage/S = I
|
||||
for(var/obj/A in S.return_inv())
|
||||
if(is_type_in_typecache(A, cant_hold))
|
||||
if(!stop_messages)
|
||||
to_chat(usr, "<span class='warning'>[src] rejects [I] because of its contents.</span>")
|
||||
return FALSE
|
||||
|
||||
if(I.w_class > max_w_class)
|
||||
if(length(w_class_override))
|
||||
if(is_type_in_list(I, w_class_override))
|
||||
return TRUE
|
||||
else
|
||||
if(!stop_messages)
|
||||
to_chat(usr, "<span class='warning'>[I] is too big for [src].</span>")
|
||||
return FALSE
|
||||
else
|
||||
if(!stop_messages)
|
||||
to_chat(usr, "<span class='warning'>[I] is too big for [src].</span>")
|
||||
return FALSE
|
||||
|
||||
var/sum_w_class = I.w_class
|
||||
for(var/obj/item/item in contents)
|
||||
sum_w_class += item.w_class //Adds up the combined w_classes which will be in the storage item if the item is added to it.
|
||||
|
||||
if(sum_w_class > max_combined_w_class)
|
||||
if(!stop_messages)
|
||||
to_chat(usr, "<span class='warning'>[src] is full, make some space.</span>")
|
||||
return FALSE
|
||||
|
||||
if(I.w_class >= w_class && isstorage(I))
|
||||
if(!allow_same_size) //BoHs should be able to hold backpacks again. The override for putting a BoH in a BoH is in backpack.dm.
|
||||
if(!stop_messages)
|
||||
to_chat(usr, "<span class='warning'>[src] cannot hold [I] as it's a storage item of the same size.</span>")
|
||||
return FALSE //To prevent the stacking of same sized storage items.
|
||||
|
||||
if(I.flags & NODROP) //SHOULD be handled in unEquip, but better safe than sorry.
|
||||
to_chat(usr, "<span class='warning'>[I] is stuck to your hand, you can't put it in [src]</span>")
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Handles items being inserted into a storage container.
|
||||
*
|
||||
* This doesn't perform any checks of whether an item can be inserted. That's done by [/obj/item/storage/proc/can_be_inserted]
|
||||
* Arguments:
|
||||
* * obj/item/I - The item to be inserted
|
||||
* * mob/user - The mob performing the insertion
|
||||
* * prevent_warning - Stop the insertion message being displayed. Intended for cases when you are inserting multiple items at once.
|
||||
*/
|
||||
/obj/item/storage/proc/handle_item_insertion(obj/item/I, mob/user, prevent_warning = FALSE)
|
||||
if(!istype(I))
|
||||
return FALSE
|
||||
if(user)
|
||||
if(!Adjacent(user) && !isnewplayer(user))
|
||||
return FALSE
|
||||
if(!user.unequip(I))
|
||||
return FALSE
|
||||
user.update_icons() //update our overlays
|
||||
if(QDELING(I))
|
||||
return FALSE
|
||||
if(silent || HAS_TRAIT(I, TRAIT_SILENT_INSERTION))
|
||||
prevent_warning = TRUE
|
||||
I.forceMove(src)
|
||||
if(QDELING(I))
|
||||
return FALSE
|
||||
I.on_enter_storage(src)
|
||||
|
||||
for(var/_M in mobs_viewing)
|
||||
var/mob/M = _M
|
||||
if((M.s_active == src) && M.client)
|
||||
M.client.screen += I
|
||||
if(user)
|
||||
if(user.client && user.s_active != src)
|
||||
user.client.screen -= I
|
||||
if(length(user.observers))
|
||||
for(var/mob/observer in user.observers)
|
||||
if(observer.client && observer.s_active != src)
|
||||
observer.client.screen -= I
|
||||
I.dropped(user, TRUE)
|
||||
if(user)
|
||||
add_fingerprint(user)
|
||||
|
||||
if(!prevent_warning)
|
||||
// the item's user will always get a notification
|
||||
to_chat(user, "<span class='notice'>You put [I] into [src].</span>")
|
||||
|
||||
// if the item less than normal sized, only people within 1 tile get the message, otherwise, everybody in view gets it
|
||||
if(I.w_class < WEIGHT_CLASS_NORMAL)
|
||||
for(var/mob/M in orange(1, user))
|
||||
if(in_range(M, user))
|
||||
M.show_message("<span class='notice'>[user] puts [I] into [src].</span>")
|
||||
else
|
||||
// restrict player list to include only those in view
|
||||
for(var/mob/M in oviewers(7, user))
|
||||
M.show_message("<span class='notice'>[user] puts [I] into [src].</span>")
|
||||
orient2hud(user)
|
||||
if(user)
|
||||
if(user.s_active)
|
||||
user.s_active.show_to(user)
|
||||
|
||||
I.mouse_opacity = MOUSE_OPACITY_OPAQUE //So you can click on the area around the item to equip it, instead of having to pixel hunt
|
||||
I.in_inventory = TRUE
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/item/storage/proc/on_atom_exited(datum/source, atom/exited, direction)
|
||||
return remove_from_storage(exited, exited.loc)
|
||||
|
||||
/**
|
||||
* Handles the removal of an item from a storage container.
|
||||
*
|
||||
* Arguments:
|
||||
* * obj/item/I - The item to be removed
|
||||
* * atom/new_location - The location to send the item to.
|
||||
*/
|
||||
/obj/item/storage/proc/remove_from_storage(obj/item/I, atom/new_location)
|
||||
if(!istype(I))
|
||||
return FALSE
|
||||
|
||||
for(var/_M in mobs_viewing)
|
||||
var/mob/M = _M
|
||||
if((M.s_active == src) && M.client)
|
||||
M.client.screen -= I
|
||||
|
||||
if(new_location)
|
||||
if(ismob(loc))
|
||||
I.dropped(usr, TRUE)
|
||||
if(ismob(new_location))
|
||||
I.layer = ABOVE_HUD_LAYER
|
||||
I.plane = ABOVE_HUD_PLANE
|
||||
else
|
||||
I.layer = initial(I.layer)
|
||||
I.plane = initial(I.plane)
|
||||
I.forceMove(new_location)
|
||||
else
|
||||
I.forceMove(get_turf(src))
|
||||
|
||||
if(usr)
|
||||
orient2hud(usr)
|
||||
if(usr.s_active)
|
||||
usr.s_active.show_to(usr)
|
||||
if(I.maptext)
|
||||
I.maptext = ""
|
||||
I.on_exit_storage(src)
|
||||
I.mouse_opacity = initial(I.mouse_opacity)
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/item/storage/deconstruct(disassembled = TRUE)
|
||||
var/drop_loc = loc
|
||||
if(ismob(loc))
|
||||
drop_loc = get_turf(src)
|
||||
for(var/obj/item/I in contents)
|
||||
remove_from_storage(I, drop_loc)
|
||||
qdel(src)
|
||||
|
||||
//This proc is called when you want to place an item into the storage item.
|
||||
/obj/item/storage/attackby__legacy__attackchain(obj/item/I, mob/user, params)
|
||||
..()
|
||||
if(istype(I, /obj/item/hand_labeler))
|
||||
var/obj/item/hand_labeler/labeler = I
|
||||
if(labeler.mode)
|
||||
return FALSE
|
||||
if(user.a_intent != INTENT_HELP && issimulatedturf(loc)) // Stops you from putting your baton in the storage on accident
|
||||
return FALSE
|
||||
. = TRUE //no afterattack
|
||||
if(isrobot(user))
|
||||
return //Robots can't interact with storage items.
|
||||
|
||||
if(!can_be_inserted(I))
|
||||
if(length(contents) >= storage_slots) //don't use items on the backpack if they don't fit
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
handle_item_insertion(I, user)
|
||||
|
||||
/obj/item/storage/attack_hand(mob/user)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(!H.get_active_hand())
|
||||
if(H.l_store == src) //Prevents opening if it's in a pocket.
|
||||
H.put_in_hands(src)
|
||||
H.l_store = null
|
||||
return
|
||||
if(H.r_store == src)
|
||||
H.put_in_hands(src)
|
||||
H.r_store = null
|
||||
return
|
||||
|
||||
orient2hud(user)
|
||||
if(loc == user)
|
||||
if(user.s_active)
|
||||
user.s_active.close(user)
|
||||
open(user)
|
||||
else
|
||||
..()
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/item/storage/equipped(mob/user, slot, initial)
|
||||
. = ..()
|
||||
update_viewers()
|
||||
|
||||
/obj/item/storage/attack_ghost(mob/user)
|
||||
if(isobserver(user))
|
||||
// Revenants don't get to play with the toys.
|
||||
show_to(user)
|
||||
return ..()
|
||||
|
||||
/obj/item/storage/AltShiftClick(mob/living/carbon/human/user)
|
||||
|
||||
pickup_all_on_tile = !pickup_all_on_tile
|
||||
switch(pickup_all_on_tile)
|
||||
if(TRUE)
|
||||
to_chat(usr, "[src] now picks up all items in a tile at once.")
|
||||
if(FALSE)
|
||||
to_chat(usr, "[src] now picks up one item at a time.")
|
||||
|
||||
/obj/item/storage/proc/drop_inventory(user)
|
||||
var/turf/T = get_turf(src)
|
||||
hide_from(user)
|
||||
for(var/obj/item/I in contents)
|
||||
remove_from_storage(I, T)
|
||||
I.scatter_atom()
|
||||
CHECK_TICK
|
||||
|
||||
/**
|
||||
* Populates the container with items
|
||||
*
|
||||
* Override with whatever you want to put in the container
|
||||
*/
|
||||
/obj/item/storage/proc/populate_contents()
|
||||
return // Override
|
||||
|
||||
/obj/item/storage/emp_act(severity)
|
||||
..()
|
||||
for(var/I in contents)
|
||||
var/atom/A = I
|
||||
A.emp_act(severity)
|
||||
|
||||
/obj/item/storage/hear_talk(mob/living/M, list/message_pieces)
|
||||
..()
|
||||
for(var/obj/O in contents)
|
||||
O.hear_talk(M, message_pieces)
|
||||
|
||||
/obj/item/storage/hear_message(mob/living/M, msg)
|
||||
..()
|
||||
for(var/obj/O in contents)
|
||||
O.hear_message(M, msg)
|
||||
|
||||
/obj/item/storage/attack_self__legacy__attackchain(mob/user)
|
||||
//Clicking on itself will empty it, if allow_quick_empty is TRUE
|
||||
if(allow_quick_empty && user.is_in_active_hand(src))
|
||||
drop_inventory(user)
|
||||
|
||||
else if(foldable)
|
||||
fold(user)
|
||||
|
||||
/obj/item/storage/proc/fold(mob/user)
|
||||
if(length(contents))
|
||||
to_chat(user, "<span class='warning'>You can't fold this [name] with items still inside!</span>")
|
||||
return
|
||||
if(!ispath(foldable))
|
||||
return
|
||||
|
||||
var/found = FALSE
|
||||
for(var/mob/M in range(1))
|
||||
if(M.s_active == src) // Close any open UI windows first
|
||||
close(M)
|
||||
if(M == user)
|
||||
found = TRUE
|
||||
if(!found) // User is too far away
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You fold [src] flat.</span>")
|
||||
var/obj/item/stack/I = new foldable(get_turf(src), foldable_amt)
|
||||
user.put_in_hands(I)
|
||||
qdel(src)
|
||||
|
||||
/**
|
||||
* Returns the storage depth of an atom up to the area level.
|
||||
*
|
||||
* The storage depth is the number of storage items the atom is contained in.
|
||||
* Returns `-1` if the atom was not found in a container.
|
||||
*/
|
||||
/atom/proc/storage_depth(atom/container)
|
||||
var/depth = 0
|
||||
var/atom/cur_atom = src
|
||||
|
||||
while(cur_atom && !(cur_atom in container.contents))
|
||||
if(isarea(cur_atom))
|
||||
return -1
|
||||
if(isstorage(cur_atom.loc))
|
||||
depth++
|
||||
cur_atom = cur_atom.loc
|
||||
|
||||
if(!cur_atom)
|
||||
return -1 //inside something with a null loc.
|
||||
|
||||
return depth
|
||||
|
||||
/**
|
||||
* Like [/atom/proc/storage_depth], but returns the depth to the nearest turf.
|
||||
*
|
||||
* Returns `-1` if there's no top level turf. (A loc was null somewhere, or a non-turf atom's loc was an area somehow.)
|
||||
*/
|
||||
/atom/proc/storage_depth_turf()
|
||||
var/depth = 0
|
||||
var/atom/cur_atom = src
|
||||
|
||||
while(cur_atom && !isturf(cur_atom))
|
||||
if(isarea(cur_atom))
|
||||
return -1
|
||||
if(isstorage(cur_atom.loc))
|
||||
depth++
|
||||
cur_atom = cur_atom.loc
|
||||
|
||||
if(!cur_atom)
|
||||
return -1 //inside something with a null loc.
|
||||
|
||||
return depth
|
||||
|
||||
/obj/item/storage/serialize()
|
||||
var/data = ..()
|
||||
var/list/content_list = list()
|
||||
data["content"] = content_list
|
||||
data["slots"] = storage_slots
|
||||
data["max_w_class"] = max_w_class
|
||||
data["max_c_w_class"] = max_combined_w_class
|
||||
for(var/thing in contents)
|
||||
var/atom/movable/AM = thing
|
||||
// This code does not watch out for infinite loops
|
||||
// But then again a tesseract would destroy the server anyways
|
||||
// Also I wish I could just insert a list instead of it reading it the wrong way
|
||||
content_list.len++
|
||||
content_list[length(content_list)] = AM.serialize()
|
||||
return data
|
||||
|
||||
/obj/item/storage/deserialize(list/data)
|
||||
if(isnum(data["slots"]))
|
||||
storage_slots = data["slots"]
|
||||
if(isnum(data["max_w_class"]))
|
||||
max_w_class = data["max_w_class"]
|
||||
if(isnum(data["max_c_w_class"]))
|
||||
max_combined_w_class = data["max_c_w_class"]
|
||||
for(var/thing in contents)
|
||||
qdel(thing) // out with the old
|
||||
for(var/thing in data["content"])
|
||||
if(islist(thing))
|
||||
list_to_object(thing, src)
|
||||
else if(thing == null)
|
||||
stack_trace("Null entry found in storage/deserialize.")
|
||||
else
|
||||
stack_trace("Non-list thing found in storage/deserialize (Thing: [thing])")
|
||||
..()
|
||||
|
||||
/obj/item/storage/AllowDrop()
|
||||
return TRUE
|
||||
|
||||
/obj/item/storage/ex_act(severity)
|
||||
for(var/atom/A in contents)
|
||||
A.ex_act(severity)
|
||||
CHECK_TICK
|
||||
..()
|
||||
|
||||
/obj/item/storage/proc/can_items_stack(obj/item/item_1, obj/item/item_2)
|
||||
if(!item_1 || !item_2)
|
||||
return
|
||||
|
||||
return item_1.type == item_2.type && item_1.name == item_2.name
|
||||
|
||||
/obj/item/storage/proc/swap_items(obj/item/item_1, obj/item/item_2, mob/user = null)
|
||||
if(!(item_1.loc == src && item_2.loc == src))
|
||||
return
|
||||
|
||||
var/index_1 = contents.Find(item_1)
|
||||
var/index_2 = contents.Find(item_2)
|
||||
|
||||
var/list/new_contents = contents.Copy()
|
||||
new_contents.Swap(index_1, index_2)
|
||||
contents = new_contents
|
||||
|
||||
if(user && user.s_active == src)
|
||||
orient2hud(user)
|
||||
show_to(user)
|
||||
@@ -1,45 +0,0 @@
|
||||
// Sprites from CM13
|
||||
/obj/item/storage/surgical_tray
|
||||
name = "surgical tray"
|
||||
desc = "A small metallic tray covered in sterile tarp. Intended to store surgical tools in a neat and clean fashion."
|
||||
icon_state = "surgical_tray"
|
||||
storage_slots = 22 // 11 Items, x2 to be sure
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
max_w_class = WEIGHT_CLASS_GIGANTIC
|
||||
max_combined_w_class = 38 // Items listed add up to 19, x2 to be sure
|
||||
can_hold = list(
|
||||
/obj/item/scalpel,
|
||||
/obj/item/cautery,
|
||||
/obj/item/hemostat,
|
||||
/obj/item/retractor,
|
||||
/obj/item/fix_o_vein,
|
||||
/obj/item/surgicaldrill,
|
||||
/obj/item/circular_saw,
|
||||
/obj/item/bonegel,
|
||||
/obj/item/bonesetter,
|
||||
/obj/item/stack/medical/bruise_pack,
|
||||
/obj/item/stack/medical/ointment,
|
||||
/obj/item/surgical_drapes,
|
||||
/obj/item/dissector,
|
||||
)
|
||||
|
||||
/obj/item/storage/surgical_tray/Initialize(mapload)
|
||||
. = ..()
|
||||
new /obj/item/scalpel(src)
|
||||
new /obj/item/cautery(src)
|
||||
new /obj/item/hemostat(src)
|
||||
new /obj/item/retractor(src)
|
||||
new /obj/item/fix_o_vein(src)
|
||||
new /obj/item/surgicaldrill(src)
|
||||
new /obj/item/circular_saw(src)
|
||||
new /obj/item/bonegel(src)
|
||||
new /obj/item/bonesetter(src)
|
||||
new /obj/item/stack/medical/bruise_pack/advanced(src)
|
||||
new /obj/item/stack/medical/ointment/advanced(src)
|
||||
new /obj/item/surgical_drapes(src)
|
||||
|
||||
/obj/item/storage/surgical_tray/update_icon_state()
|
||||
if(!length(contents))
|
||||
icon_state = "surgical_tray_e"
|
||||
else
|
||||
icon_state = "surgical_tray"
|
||||
@@ -1,126 +0,0 @@
|
||||
/obj/item/storage/wallet
|
||||
name = "leather wallet"
|
||||
desc = "Made from genuine leather, it is of the highest quality."
|
||||
storage_slots = 10
|
||||
icon = 'icons/obj/wallets.dmi'
|
||||
icon_state = "wallet"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
resistance_flags = FLAMMABLE
|
||||
can_hold = list(
|
||||
/obj/item/stack/spacecash,
|
||||
/obj/item/card,
|
||||
/obj/item/clothing/mask/cigarette,
|
||||
/obj/item/flashlight/pen,
|
||||
/obj/item/seeds,
|
||||
/obj/item/stack/medical,
|
||||
/obj/item/toy/crayon,
|
||||
/obj/item/coin,
|
||||
/obj/item/food/candy/chocolate_coin,
|
||||
/obj/item/food/candy/coin,
|
||||
/obj/item/food/candy/cash,
|
||||
/obj/item/food/customizable/candy/coin,
|
||||
/obj/item/food/customizable/candy/cash,
|
||||
/obj/item/dice,
|
||||
/obj/item/disk,
|
||||
/obj/item/bio_chip_implanter,
|
||||
/obj/item/lighter,
|
||||
/obj/item/match,
|
||||
/obj/item/paper,
|
||||
/obj/item/pen,
|
||||
/obj/item/photo,
|
||||
/obj/item/reagent_containers/dropper,
|
||||
/obj/item/screwdriver,
|
||||
/obj/item/stamp)
|
||||
cant_hold = list(
|
||||
/obj/item/screwdriver/power
|
||||
)
|
||||
slot_flags = ITEM_SLOT_ID
|
||||
|
||||
var/obj/item/card/id/front_id = null
|
||||
|
||||
// allows for clicking of stuff on our person/on the ground to put in the wallet, so easy to stick your ID in your wallet
|
||||
use_to_pickup = TRUE
|
||||
pickup_all_on_tile = FALSE
|
||||
|
||||
|
||||
/obj/item/storage/wallet/remove_from_storage(obj/item/I, atom/new_location)
|
||||
. = ..()
|
||||
if(. && istype(I, /obj/item/card/id))
|
||||
refresh_ID()
|
||||
|
||||
/obj/item/storage/wallet/handle_item_insertion(obj/item/I, mob/user, prevent_warning = FALSE)
|
||||
. = ..()
|
||||
if(. && istype(I, /obj/item/card/id))
|
||||
refresh_ID()
|
||||
|
||||
/obj/item/storage/wallet/orient2hud(mob/user)
|
||||
. = ..()
|
||||
refresh_ID()
|
||||
|
||||
/obj/item/storage/wallet/proc/refresh_ID()
|
||||
// Locate the first ID in the wallet
|
||||
front_id = (locate(/obj/item/card/id) in contents)
|
||||
|
||||
if(ishuman(loc))
|
||||
var/mob/living/carbon/human/wearing_human = loc
|
||||
if(wearing_human.wear_id == src)
|
||||
wearing_human.sec_hud_set_ID()
|
||||
|
||||
update_appearance(UPDATE_NAME|UPDATE_OVERLAYS)
|
||||
|
||||
/obj/item/storage/wallet/update_overlays()
|
||||
. = ..()
|
||||
if(!front_id)
|
||||
return
|
||||
. += mutable_appearance(front_id.icon, front_id.icon_state)
|
||||
. += front_id.overlays
|
||||
. += mutable_appearance(icon, "wallet_overlay")
|
||||
|
||||
// fuck yeah, ass photo in my wallet
|
||||
var/obj/item/photo/photo = locate(/obj/item/photo) in contents
|
||||
if(!photo)
|
||||
return
|
||||
var/mutable_appearance/MA = mutable_appearance(photo.appearance)
|
||||
MA.pixel_x = 11
|
||||
MA.pixel_y = 1
|
||||
. += MA
|
||||
. += mutable_appearance(icon, "photo_overlay")
|
||||
|
||||
/obj/item/storage/wallet/update_name(updates)
|
||||
. = ..()
|
||||
if(front_id)
|
||||
name = "wallet displaying [front_id]"
|
||||
else
|
||||
name = initial(name)
|
||||
|
||||
/obj/item/storage/wallet/GetID()
|
||||
return front_id
|
||||
|
||||
/obj/item/storage/wallet/GetAccess()
|
||||
var/obj/item/I = GetID()
|
||||
if(I)
|
||||
return I.GetAccess()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/storage/wallet/random/populate_contents()
|
||||
var/cash = pick(/obj/item/stack/spacecash,
|
||||
/obj/item/stack/spacecash/c5,
|
||||
/obj/item/stack/spacecash/c10,
|
||||
/obj/item/stack/spacecash/c50,
|
||||
/obj/item/stack/spacecash/c100)
|
||||
var/coin = pickweight(list(/obj/item/coin/iron = 3,
|
||||
/obj/item/coin/silver = 2,
|
||||
/obj/item/coin/gold = 1))
|
||||
|
||||
new cash(src)
|
||||
if(prob(50)) // 50% chance of a second
|
||||
new cash(src)
|
||||
new coin(src)
|
||||
|
||||
|
||||
// Arcade Wallet
|
||||
/obj/item/storage/wallet/cheap
|
||||
name = "cheap wallet"
|
||||
desc = "A cheap and flimsy wallet from the arcade."
|
||||
storage_slots = 5 //smaller storage than normal wallets
|
||||
@@ -1,243 +0,0 @@
|
||||
/obj/item/tank/jetpack
|
||||
name = "Jetpack (Empty)"
|
||||
desc = "A tank of compressed gas for use as propulsion in zero-gravity areas. Use with caution."
|
||||
icon_state = "jetpack"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
item_state = "jetpack"
|
||||
lefthand_file = 'icons/mob/inhands/jetpack_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/jetpack_righthand.dmi'
|
||||
distribute_pressure = ONE_ATMOSPHERE * O2STANDARD
|
||||
actions_types = list(/datum/action/item_action/set_internals, /datum/action/item_action/toggle_jetpack, /datum/action/item_action/jetpack_stabilization)
|
||||
var/gas_type = "oxygen"
|
||||
var/on = FALSE
|
||||
var/volume_rate = 500 //Needed for borg jetpack transfer
|
||||
var/stabilize = FALSE
|
||||
var/thrust_callback
|
||||
|
||||
/obj/item/tank/jetpack/Initialize(mapload)
|
||||
. = ..()
|
||||
thrust_callback = CALLBACK(src, PROC_REF(allow_thrust), 0.01)
|
||||
configure_jetpack(stabilize)
|
||||
|
||||
/obj/item/tank/jetpack/Destroy()
|
||||
thrust_callback = null
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* configures/re-configures the jetpack component
|
||||
*
|
||||
* Arguments
|
||||
* stabilize - Should this jetpack be stabalized
|
||||
*/
|
||||
/obj/item/tank/jetpack/proc/configure_jetpack(stabilize)
|
||||
src.stabilize = stabilize
|
||||
|
||||
AddComponent( \
|
||||
/datum/component/jetpack, \
|
||||
src.stabilize, \
|
||||
COMSIG_JETPACK_ACTIVATED, \
|
||||
COMSIG_JETPACK_DEACTIVATED, \
|
||||
JETPACK_ACTIVATION_FAILED, \
|
||||
thrust_callback, \
|
||||
/datum/effect_system/trail_follow/ion \
|
||||
)
|
||||
|
||||
/obj/item/tank/jetpack/populate_gas()
|
||||
if(gas_type)
|
||||
switch(gas_type)
|
||||
if("oxygen")
|
||||
air_contents.set_oxygen(((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)))
|
||||
if("carbon dioxide")
|
||||
air_contents.set_carbon_dioxide(((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)))
|
||||
|
||||
/obj/item/tank/jetpack/on_mob_move(direction, mob/user)
|
||||
if(on)
|
||||
var/turf/T = get_step(src, REVERSE_DIR(direction))
|
||||
if(!has_gravity(T))
|
||||
new /obj/effect/particle_effect/ion_trails(T, direction)
|
||||
|
||||
/obj/item/tank/jetpack/ui_action_click(mob/user, actiontype)
|
||||
if(actiontype == /datum/action/item_action/toggle_jetpack)
|
||||
cycle(user)
|
||||
else if(actiontype == /datum/action/item_action/jetpack_stabilization)
|
||||
toggle_stabilization(user)
|
||||
else
|
||||
toggle_internals(user)
|
||||
|
||||
/obj/item/tank/jetpack/proc/toggle_stabilization(mob/user)
|
||||
if(on)
|
||||
configure_jetpack(!stabilize)
|
||||
to_chat(user, "<span class='notice'>You turn [src]'s stabilization [stabilize ? "on" : "off"].</span>")
|
||||
|
||||
/obj/item/tank/jetpack/proc/cycle(mob/user)
|
||||
if(user.incapacitated())
|
||||
return
|
||||
|
||||
if(!on)
|
||||
turn_on(user)
|
||||
to_chat(user, "<span class='notice'>You turn the jetpack on.</span>")
|
||||
else
|
||||
turn_off(user)
|
||||
to_chat(user, "<span class='notice'>You turn the jetpack off.</span>")
|
||||
update_action_buttons()
|
||||
|
||||
/obj/item/tank/jetpack/proc/turn_on(mob/user)
|
||||
if(SEND_SIGNAL(src, COMSIG_JETPACK_ACTIVATED, user) & JETPACK_ACTIVATION_FAILED)
|
||||
return FALSE
|
||||
|
||||
on = TRUE
|
||||
icon_state = "[initial(icon_state)]-on"
|
||||
|
||||
/obj/item/tank/jetpack/proc/turn_off(mob/user)
|
||||
SEND_SIGNAL(src, COMSIG_JETPACK_DEACTIVATED, user)
|
||||
on = FALSE
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/obj/item/tank/jetpack/dropped(mob/user, silent)
|
||||
. = ..()
|
||||
if(on)
|
||||
turn_off(user)
|
||||
|
||||
/obj/item/tank/jetpack/proc/allow_thrust(num)
|
||||
if(!ismob(loc))
|
||||
return FALSE
|
||||
var/mob/user = loc
|
||||
|
||||
if((num < 0.005 || air_contents.total_moles() < num))
|
||||
turn_off(user)
|
||||
return FALSE
|
||||
|
||||
var/datum/gas_mixture/removed = air_contents.remove(num)
|
||||
if(removed.total_moles() < 0.005)
|
||||
turn_off(user)
|
||||
return FALSE
|
||||
|
||||
var/turf/T = get_turf(user)
|
||||
T.blind_release_air(removed)
|
||||
return TRUE
|
||||
|
||||
/obj/item/tank/jetpack/improvised
|
||||
name = "improvised jetpack"
|
||||
desc = "A jetpack made from two air tanks, a fire extinguisher and some atmospherics equipment. It doesn't look like it can hold much."
|
||||
icon_state = "jetpack-improvised"
|
||||
item_state = "jetpack-improvised"
|
||||
volume = 20 //normal jetpacks have 70 volume
|
||||
gas_type = null //it starts empty
|
||||
|
||||
/obj/item/tank/jetpack/improvised/allow_thrust(num, mob/living/user)
|
||||
if(rand(0, 250) == 0)
|
||||
to_chat(user, "<span class='notice'>You feel your jetpack's engines cut out.</span>")
|
||||
turn_off(user)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/tank/jetpack/void
|
||||
name = "Void Jetpack (Oxygen)"
|
||||
desc = "It works well in a void."
|
||||
icon_state = "jetpack-void"
|
||||
item_state = "jetpack-void"
|
||||
|
||||
/obj/item/tank/jetpack/void/grey
|
||||
icon_state = "jetpack-void-grey"
|
||||
item_state = "jetpack-void-grey"
|
||||
|
||||
/obj/item/tank/jetpack/void/gold
|
||||
name = "Retro Jetpack (Oxygen)"
|
||||
icon_state = "jetpack-void-gold"
|
||||
item_state = "jetpack-void-gold"
|
||||
|
||||
/obj/item/tank/jetpack/oxygen
|
||||
name = "Jetpack (Oxygen)"
|
||||
desc = "A tank of compressed oxygen for use as propulsion in zero-gravity areas. Use with caution."
|
||||
|
||||
/obj/item/tank/jetpack/oxygen/harness
|
||||
name = "jet harness (oxygen)"
|
||||
desc = "A lightweight tactical harness, used by those who don't want to be weighed down by traditional jetpacks."
|
||||
icon_state = "jetpack-mini"
|
||||
item_state = "jetpack-mini"
|
||||
volume = 40
|
||||
throw_range = 7
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
|
||||
/obj/item/tank/jetpack/oxygen/captain
|
||||
name = "Captain's jetpack"
|
||||
desc = "A compact, lightweight jetpack containing a high amount of compressed oxygen."
|
||||
icon_state = "jetpack-captain"
|
||||
item_state = "jetpack-captain"
|
||||
volume = 90
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
|
||||
/obj/item/tank/jetpack/oxygen/security
|
||||
name = "security jetpack (oxygen)"
|
||||
desc = "A tank of compressed oxygen for use as propulsion in zero-gravity areas by security forces."
|
||||
icon_state = "jetpack-sec"
|
||||
item_state = "jetpack-sec"
|
||||
|
||||
/obj/item/tank/jetpack/carbondioxide
|
||||
name = "Jetpack (Carbon Dioxide)"
|
||||
desc = "A tank of compressed carbon dioxide for use as propulsion in zero-gravity areas. Painted black to indicate that it should not be used as a source for internals."
|
||||
distribute_pressure = 0
|
||||
icon_state = "jetpack-black"
|
||||
item_state = "jetpack-black"
|
||||
gas_type = "carbon dioxide"
|
||||
|
||||
/obj/item/tank/jetpack/suit
|
||||
name = "hardsuit jetpack upgrade"
|
||||
desc = "A modular, compact set of thrusters designed to integrate with a hardsuit. It is fueled by a tank inserted into the suit's storage compartment."
|
||||
icon_state = "jetpack-mining"
|
||||
item_state = "jetpack-black"
|
||||
origin_tech = "materials=4;magnets=4;engineering=5"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
actions_types = list(/datum/action/item_action/toggle_jetpack, /datum/action/item_action/jetpack_stabilization)
|
||||
volume = 1
|
||||
slot_flags = null
|
||||
gas_type = null
|
||||
var/datum/gas_mixture/temp_air_contents
|
||||
var/obj/item/tank/internals/tank = null
|
||||
var/mob/living/carbon/human/cur_user
|
||||
|
||||
/obj/item/tank/jetpack/suit/New()
|
||||
..()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
temp_air_contents = air_contents
|
||||
|
||||
/obj/item/tank/jetpack/suit/attack_self__legacy__attackchain()
|
||||
return
|
||||
|
||||
/obj/item/tank/jetpack/suit/cycle(mob/user)
|
||||
if(!istype(loc, /obj/item/clothing/suit/space/hardsuit))
|
||||
to_chat(user, "<span class='warning'>[src] must be connected to a hardsuit!</span>")
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(!istype(H.s_store, /obj/item/tank))
|
||||
to_chat(user, "<span class='warning'>You need a tank in your suit storage!</span>")
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/tank/jetpack/suit/turn_on(mob/user)
|
||||
if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc) || loc.loc != user)
|
||||
return
|
||||
var/mob/living/carbon/human/H = user
|
||||
tank = H.s_store
|
||||
air_contents = tank.air_contents
|
||||
START_PROCESSING(SSobj, src)
|
||||
cur_user = user
|
||||
..()
|
||||
|
||||
/obj/item/tank/jetpack/suit/turn_off(mob/user)
|
||||
tank = null
|
||||
air_contents = temp_air_contents
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
cur_user = null
|
||||
..()
|
||||
|
||||
/obj/item/tank/jetpack/suit/process()
|
||||
if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc))
|
||||
turn_off(cur_user)
|
||||
return
|
||||
var/mob/living/carbon/human/H = loc.loc
|
||||
if(!tank || tank != H.s_store)
|
||||
turn_off(cur_user)
|
||||
return
|
||||
..()
|
||||
@@ -1,217 +0,0 @@
|
||||
/* Types of tanks!
|
||||
* Contains:
|
||||
* Oxygen
|
||||
* Anesthetic
|
||||
* Air
|
||||
* Plasma
|
||||
* Emergency Oxygen
|
||||
* Generic
|
||||
*/
|
||||
|
||||
/*
|
||||
* Oxygen
|
||||
*/
|
||||
/obj/item/tank/internals
|
||||
name = "internals tank"
|
||||
desc = "A tank for use in internals. If you see this, please submit a bug report."
|
||||
icon_state = "generic"
|
||||
distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE
|
||||
force = 10
|
||||
|
||||
/obj/item/tank/internals/oxygen
|
||||
name = "oxygen tank"
|
||||
desc = "A tank of oxygen. This one is blue."
|
||||
icon_state = "oxygen"
|
||||
dog_fashion = /datum/dog_fashion/back
|
||||
|
||||
/obj/item/tank/internals/oxygen/populate_gas()
|
||||
air_contents.set_oxygen((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
|
||||
|
||||
/obj/item/tank/internals/oxygen/yellow
|
||||
desc = "A tank of oxygen, this one is yellow."
|
||||
icon_state = "oxygen_f"
|
||||
|
||||
/obj/item/tank/internals/oxygen/red
|
||||
desc = "A tank of oxygen, this one is red."
|
||||
icon_state = "oxygen_fr"
|
||||
|
||||
/obj/item/tank/internals/oxygen/empty/populate_gas()
|
||||
return
|
||||
|
||||
/*
|
||||
* Anesthetic
|
||||
*/
|
||||
/obj/item/tank/internals/anesthetic
|
||||
name = "anesthetic tank"
|
||||
desc = "A tank with an N2O/O2 gas mix."
|
||||
icon_state = "anesthetic"
|
||||
item_state = "an_tank"
|
||||
distribute_pressure = ONE_ATMOSPHERE
|
||||
|
||||
/obj/item/tank/internals/anesthetic/populate_gas()
|
||||
air_contents.set_oxygen((3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * O2STANDARD)
|
||||
air_contents.set_sleeping_agent((3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * N2STANDARD)
|
||||
|
||||
/*
|
||||
* Plasma
|
||||
*/
|
||||
/obj/item/tank/internals/plasma
|
||||
name = "plasma tank"
|
||||
desc = "Contains dangerous plasma. Do not inhale. Warning: extremely flammable."
|
||||
icon_state = "plasma"
|
||||
slot_flags = null //they have no straps!
|
||||
force = 8
|
||||
|
||||
/obj/item/tank/internals/plasma/populate_gas()
|
||||
air_contents.set_toxins((3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
|
||||
|
||||
/obj/item/tank/internals/plasma/attackby__legacy__attackchain(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/flamethrower))
|
||||
var/obj/item/flamethrower/F = I
|
||||
if((!F.status)||(F.ptank))
|
||||
return
|
||||
master = F
|
||||
F.ptank = src
|
||||
user.transfer_item_to(src, F)
|
||||
F.update_icon()
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/tank/internals/plasma/full/populate_gas()
|
||||
air_contents.set_toxins((10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
|
||||
|
||||
/obj/item/tank/internals/plasma/empty/populate_gas()
|
||||
return
|
||||
|
||||
/*
|
||||
* Plasmaman Plasma Tank
|
||||
*/
|
||||
/obj/item/tank/internals/plasmaman
|
||||
name = "plasma internals tank"
|
||||
desc = "A tank of plasma gas designed specifically for use as internals, particularly for plasma-based lifeforms. If you're not a Plasmaman, you probably shouldn't use this."
|
||||
icon_state = "plasma_fr"
|
||||
item_state = "plasma_fr"
|
||||
|
||||
/obj/item/tank/internals/plasmaman/populate_gas()
|
||||
air_contents.set_toxins((3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
|
||||
|
||||
/obj/item/tank/internals/plasmaman/full/populate_gas()
|
||||
air_contents.set_toxins((10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
|
||||
|
||||
|
||||
/obj/item/tank/internals/plasmaman/belt
|
||||
icon_state = "plasmaman_tank_belt"
|
||||
item_state = "plasmaman_tank_belt"
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
flags_2 = ALLOW_BELT_NO_JUMPSUIT_2
|
||||
force = 5
|
||||
volume = 18 // Lasts 1h 16m 30s
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
|
||||
/obj/item/tank/internals/plasmaman/belt/full/populate_gas()
|
||||
air_contents.set_toxins((10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
|
||||
|
||||
/obj/item/tank/internals/plasmaman/belt/empty/populate_gas()
|
||||
return
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/plasma
|
||||
name = "emergency plasma tank"
|
||||
desc = "An emergency tank designed specifically for Plasmamen."
|
||||
icon_state = "emergency_p"
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/plasma/populate_gas()
|
||||
air_contents.set_toxins((10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
|
||||
|
||||
/*
|
||||
* Emergency Oxygen
|
||||
*/
|
||||
/obj/item/tank/internals/emergency_oxygen
|
||||
name = "emergency oxygen tank"
|
||||
desc = "Used for emergencies. Contains very little oxygen, so try to conserve it until you actually need it."
|
||||
icon_state = "emergency"
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
flags_2 = ALLOW_BELT_NO_JUMPSUIT_2
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
force = 4
|
||||
volume = 1 // Roughly 4m 15s of air
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/populate_gas()
|
||||
air_contents.set_oxygen((10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/empty/populate_gas()
|
||||
return
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/engi
|
||||
name = "extended-capacity emergency oxygen tank"
|
||||
icon_state = "emergency_engi"
|
||||
volume = 3 // Lasts 12m 45s
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/engi/empty/populate_gas()
|
||||
return
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/engi/syndi
|
||||
name = "suspicious emergency oxygen tank"
|
||||
icon_state = "emergency_syndi"
|
||||
desc = "A dark emergency oxygen tank. The label on the back reads \"Original Oxygen Tank Design, Do Not Steal.\""
|
||||
volume = 11 // Lasts 46m 45s
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/double
|
||||
name = "double emergency oxygen tank"
|
||||
icon_state = "emergency_double"
|
||||
volume = 6 // Lasts 25m 30s
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/double/empty/populate_gas()
|
||||
return
|
||||
|
||||
/*
|
||||
* Nitrogen
|
||||
*/
|
||||
/obj/item/tank/internals/nitrogen
|
||||
name = "nitrogen tank"
|
||||
desc = "A tank of nitrogen."
|
||||
icon_state = "oxygen_fr"
|
||||
|
||||
/obj/item/tank/internals/nitrogen/populate_gas()
|
||||
air_contents.set_nitrogen((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/nitrogen
|
||||
name = "emergency nitrogen tank"
|
||||
desc = "An emergency tank designed specifically for Vox."
|
||||
icon_state = "emergency_nitrogen"
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/nitrogen/populate_gas()
|
||||
air_contents.set_nitrogen((10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/double/vox
|
||||
name = "vox specialized nitrogen tank"
|
||||
desc = "A high-tech nitrogen tank designed specifically for Vox."
|
||||
icon_state = "emergency_vox"
|
||||
volume = 18 // Lasts 1h 16m 30s
|
||||
|
||||
/obj/item/tank/internals/emergency_oxygen/double/vox/populate_gas()
|
||||
air_contents.set_nitrogen((10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
|
||||
|
||||
/*
|
||||
* Air Mix
|
||||
*/
|
||||
/obj/item/tank/internals/air
|
||||
name = "air tank"
|
||||
desc = "Mixed anyone?"
|
||||
icon_state = "air"
|
||||
item_state = "air"
|
||||
distribute_pressure = ONE_ATMOSPHERE
|
||||
|
||||
/obj/item/tank/internals/air/populate_gas()
|
||||
air_contents.set_oxygen((3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * O2STANDARD)
|
||||
air_contents.set_nitrogen((3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * N2STANDARD)
|
||||
|
||||
/*
|
||||
* Generic
|
||||
*/
|
||||
/obj/item/tank/internals/generic
|
||||
name = "gas tank"
|
||||
desc = "A generic tank used for storing and transporting gasses. Can be used for internals."
|
||||
item_state = "generic"
|
||||
|
||||
/obj/item/tank/internals/generic/populate_gas()
|
||||
return
|
||||
@@ -1,373 +0,0 @@
|
||||
//Hydroponics tank and base code
|
||||
/obj/item/watertank
|
||||
name = "backpack water tank"
|
||||
desc = "A S.U.N.S.H.I.N.E. brand watertank backpack with nozzle to water plants."
|
||||
icon = 'icons/obj/watertank.dmi'
|
||||
icon_state = "waterbackpack"
|
||||
item_state = "waterbackpack"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
slot_flags = ITEM_SLOT_BACK
|
||||
slowdown = 1
|
||||
actions_types = list(/datum/action/item_action/toggle_mister)
|
||||
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 100, ACID = 30)
|
||||
resistance_flags = FIRE_PROOF
|
||||
|
||||
var/obj/item/noz
|
||||
var/on = FALSE
|
||||
var/volume = 500
|
||||
|
||||
/obj/item/watertank/New()
|
||||
..()
|
||||
create_reagents(volume)
|
||||
noz = make_noz()
|
||||
|
||||
/obj/item/watertank/Destroy()
|
||||
if(on)
|
||||
remove_noz()
|
||||
QDEL_NULL(noz)
|
||||
return ..()
|
||||
|
||||
/obj/item/watertank/ui_action_click(mob/user)
|
||||
toggle_mister(user)
|
||||
|
||||
/obj/item/watertank/item_action_slot_check(slot, mob/user)
|
||||
if(slot == ITEM_SLOT_BACK)
|
||||
return TRUE
|
||||
|
||||
/obj/item/watertank/proc/toggle_mister(mob/user)
|
||||
if(user.stat || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED) || !Adjacent(user))
|
||||
return
|
||||
if(user.get_item_by_slot(ITEM_SLOT_BACK) != src)
|
||||
to_chat(user, "<span class='notice'>The watertank needs to be on your back to use.</span>")
|
||||
return
|
||||
on = !on
|
||||
if(on)
|
||||
if(!noz)
|
||||
noz = make_noz()
|
||||
|
||||
//Detach the nozzle into the user's hands
|
||||
if(!user.put_in_hands(noz))
|
||||
on = FALSE
|
||||
to_chat(user, "<span class='notice'>You need a free hand to hold the mister.</span>")
|
||||
return
|
||||
noz.forceMove(user)
|
||||
else
|
||||
//Remove from their hands and put back "into" the tank
|
||||
remove_noz()
|
||||
return
|
||||
|
||||
/obj/item/watertank/proc/make_noz()
|
||||
return new /obj/item/reagent_containers/spray/mister(src)
|
||||
|
||||
/obj/item/watertank/equipped(mob/user, slot)
|
||||
..()
|
||||
if(slot != ITEM_SLOT_BACK)
|
||||
remove_noz()
|
||||
|
||||
/obj/item/watertank/proc/remove_noz()
|
||||
if(ismob(noz.loc))
|
||||
var/mob/M = noz.loc
|
||||
M.drop_item_to_ground(noz, force = TRUE)
|
||||
return
|
||||
|
||||
/obj/item/watertank/attack_hand(mob/user)
|
||||
if(loc == user)
|
||||
toggle_mister(user)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/watertank/MouseDrop(obj/over_object)
|
||||
if(ishuman(loc))
|
||||
var/mob/living/carbon/human/H = loc
|
||||
switch(over_object.name)
|
||||
if("r_hand")
|
||||
if(H.r_hand)
|
||||
return
|
||||
if(!H.unequip(src))
|
||||
return
|
||||
H.put_in_r_hand(src)
|
||||
if("l_hand")
|
||||
if(H.l_hand)
|
||||
return
|
||||
if(!H.unequip(src))
|
||||
return
|
||||
H.put_in_l_hand(src)
|
||||
return
|
||||
|
||||
/obj/item/watertank/attackby__legacy__attackchain(obj/item/W, mob/user, params)
|
||||
if(W == noz)
|
||||
remove_noz()
|
||||
return
|
||||
..()
|
||||
|
||||
// This mister item is intended as an extension of the watertank and always attached to it.
|
||||
// Therefore, it's designed to be "locked" to the player's hands or extended back onto
|
||||
// the watertank backpack. Allowing it to be placed elsewhere or created without a parent
|
||||
// watertank object will likely lead to weird behaviour or runtimes.
|
||||
/obj/item/reagent_containers/spray/mister
|
||||
name = "water mister"
|
||||
desc = "A mister nozzle attached to a water tank."
|
||||
icon = 'icons/obj/watertank.dmi'
|
||||
icon_state = "mister"
|
||||
item_state = "mister"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
amount_per_transfer_from_this = 50
|
||||
possible_transfer_amounts = list(25,50,100)
|
||||
volume = 500
|
||||
|
||||
var/obj/item/watertank/tank
|
||||
|
||||
/obj/item/reagent_containers/spray/mister/Initialize(mapload)
|
||||
if(!check_tank_exists(loc, src))
|
||||
return INITIALIZE_HINT_QDEL
|
||||
tank = loc
|
||||
reagents = tank.reagents //This mister is really just a proxy for the tank's reagents
|
||||
RegisterSignal(src, COMSIG_ACTIVATE_SELF, TYPE_PROC_REF(/datum, signal_cancel_activate_self))
|
||||
return ..()
|
||||
|
||||
/obj/item/reagent_containers/spray/mister/Destroy()
|
||||
tank = null
|
||||
reagents = null // Unset, this is the tanks reagents
|
||||
return ..()
|
||||
|
||||
/obj/item/reagent_containers/spray/mister/dropped(mob/user as mob)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>The mister snaps back onto the watertank.</span>")
|
||||
tank.on = FALSE
|
||||
loc = tank
|
||||
|
||||
/proc/check_tank_exists(parent_tank, mob/living/carbon/human/M, obj/O)
|
||||
if(!parent_tank || (!istype(parent_tank, /obj/item/watertank) && !istype(parent_tank, /obj/item/mod/module/firefighting_tank))) //To avoid weird issues from admin spawns
|
||||
return FALSE
|
||||
else
|
||||
return TRUE
|
||||
|
||||
/obj/item/reagent_containers/spray/mister/Move()
|
||||
..()
|
||||
if(loc != tank.loc)
|
||||
loc = tank.loc
|
||||
|
||||
/obj/item/reagent_containers/spray/mister/normal_act(atom/target, mob/living/user)
|
||||
if(target.loc == loc || target == tank)
|
||||
return FALSE
|
||||
|
||||
return ..()
|
||||
|
||||
//Janitor tank
|
||||
/obj/item/watertank/janitor
|
||||
desc = "A janitorial watertank backpack with nozzle to clean dirt and graffiti."
|
||||
icon_state = "waterbackpackjani"
|
||||
item_state = "waterbackpackjani"
|
||||
|
||||
/obj/item/watertank/janitor/New()
|
||||
..()
|
||||
reagents.add_reagent("cleaner", 500)
|
||||
|
||||
/obj/item/reagent_containers/spray/mister/janitor
|
||||
name = "janitor spray nozzle"
|
||||
desc = "A janitorial spray nozzle attached to a watertank, designed to clean up large messes."
|
||||
icon_state = "misterjani"
|
||||
item_state = "misterjani"
|
||||
spray_maxrange = 4
|
||||
spray_currentrange = 4
|
||||
amount_per_transfer_from_this = 10
|
||||
possible_transfer_amounts = null
|
||||
|
||||
/obj/item/watertank/janitor/make_noz()
|
||||
return new /obj/item/reagent_containers/spray/mister/janitor(src)
|
||||
|
||||
/obj/item/reagent_containers/spray/mister/janitor/activate_self(mob/user)
|
||||
if(..())
|
||||
return FINISH_ATTACK
|
||||
|
||||
amount_per_transfer_from_this = (amount_per_transfer_from_this == 5 ? 10 : 5)
|
||||
spray_currentrange = (spray_currentrange == 2 ? spray_maxrange : 2)
|
||||
to_chat(user, "<span class='notice'>You [amount_per_transfer_from_this == 5 ? "remove" : "fix"] the nozzle. You'll now use [amount_per_transfer_from_this] units per spray.</span>")
|
||||
|
||||
//ATMOS FIRE FIGHTING BACKPACK
|
||||
|
||||
#define EXTINGUISHER 0
|
||||
#define NANOFROST 1
|
||||
#define METAL_FOAM 2
|
||||
|
||||
/obj/item/watertank/atmos
|
||||
name = "backpack firefighter tank"
|
||||
desc = "A refridgerated and pressurized backpack tank with extinguisher nozzle, intended to fight fires. Swaps between extinguisher, nanofrost launcher, and metal foam dispenser for breaches. Nanofrost converts plasma in the air to nitrogen, but only if it is combusting at the time."
|
||||
icon_state = "waterbackpackatmos"
|
||||
item_state = "waterbackpackatmos"
|
||||
|
||||
/obj/item/watertank/atmos/New()
|
||||
..()
|
||||
reagents.add_reagent("water", 500)
|
||||
|
||||
/obj/item/watertank/atmos/make_noz()
|
||||
return new /obj/item/extinguisher/mini/nozzle(src)
|
||||
|
||||
/obj/item/watertank/atmos/dropped(mob/user as mob)
|
||||
..()
|
||||
icon_state = "waterbackpackatmos"
|
||||
if(istype(noz, /obj/item/extinguisher/mini/nozzle))
|
||||
var/obj/item/extinguisher/mini/nozzle/N = noz
|
||||
N.nozzle_mode = 0
|
||||
|
||||
/obj/item/extinguisher/mini/nozzle
|
||||
name = "extinguisher nozzle"
|
||||
desc = "A heavy duty nozzle attached to a firefighter's backpack tank."
|
||||
icon = 'icons/obj/watertank.dmi'
|
||||
icon_state = "atmos_nozzle_1"
|
||||
item_state = "nozzleatmos"
|
||||
has_safety = FALSE
|
||||
safety_active = FALSE
|
||||
reagent_capacity = 500
|
||||
precision = TRUE
|
||||
cooling_power = 5
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
flags = NODROP //Necessary to ensure that the nozzle and tank never seperate
|
||||
/// A reference to the tank that this nozzle is linked to
|
||||
var/obj/item/watertank/tank
|
||||
/// What mode are we currently in?
|
||||
var/nozzle_mode = EXTINGUISHER
|
||||
/// How many shots of metal foam do we have?
|
||||
var/metal_synthesis_charge = 5
|
||||
/// Time to refill 1 charge of metal foam.
|
||||
var/metal_regen_time = 2 SECONDS
|
||||
/// Refire delay for nanofrost chunks.
|
||||
var/nanofrost_cooldown_time = 2 SECONDS
|
||||
COOLDOWN_DECLARE(nanofrost_cooldown)
|
||||
|
||||
/obj/item/extinguisher/mini/nozzle/examine(mob/user)
|
||||
. = ..()
|
||||
switch(nozzle_mode)
|
||||
if(EXTINGUISHER)
|
||||
. += "<span class='notice'>[src] is currently set to extinguishing mode.</span>"
|
||||
if(NANOFROST)
|
||||
. += "<span class='notice'>[src] is currently set to nanofrost mode.</span>"
|
||||
if(METAL_FOAM)
|
||||
. += "<span class='notice'>[src] is currently set to metal foam mode.</span>"
|
||||
|
||||
/obj/item/extinguisher/mini/nozzle/Initialize(mapload)
|
||||
if(!check_tank_exists(loc, src))
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
tank = loc
|
||||
reagents = tank.reagents
|
||||
reagent_capacity = tank.volume
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/extinguisher/mini/nozzle/Destroy()
|
||||
tank = null
|
||||
reagents = null // Unset, this is the tanks reagents
|
||||
return ..()
|
||||
|
||||
/obj/item/extinguisher/mini/nozzle/Move()
|
||||
..()
|
||||
if(tank && loc != tank.loc)
|
||||
forceMove(tank)
|
||||
|
||||
/obj/item/extinguisher/mini/nozzle/activate_self(mob/user)
|
||||
..()
|
||||
switch(nozzle_mode)
|
||||
if(EXTINGUISHER)
|
||||
nozzle_mode = NANOFROST
|
||||
to_chat(user, "Swapped to nanofrost launcher")
|
||||
if(NANOFROST)
|
||||
nozzle_mode = METAL_FOAM
|
||||
to_chat(user, "Swapped to metal foam synthesizer")
|
||||
if(METAL_FOAM)
|
||||
nozzle_mode = EXTINGUISHER
|
||||
to_chat(user, "Swapped to water extinguisher")
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
return ITEM_INTERACT_COMPLETE
|
||||
|
||||
/obj/item/extinguisher/mini/nozzle/update_icon_state()
|
||||
switch(nozzle_mode)
|
||||
if(EXTINGUISHER)
|
||||
icon_state = "atmos_nozzle_1"
|
||||
tank.icon_state = "waterbackpackatmos_0"
|
||||
if(NANOFROST)
|
||||
icon_state = "atmos_nozzle_2"
|
||||
tank.icon_state = "waterbackpackatmos_1"
|
||||
if(METAL_FOAM)
|
||||
icon_state = "atmos_nozzle_3"
|
||||
tank.icon_state = "waterbackpackatmos_2"
|
||||
|
||||
/obj/item/extinguisher/mini/nozzle/dropped(mob/user)
|
||||
..()
|
||||
if(istype(tank, /obj/item/mod/module/firefighting_tank))
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>The nozzle snaps back onto the tank!</span>")
|
||||
tank.on = FALSE
|
||||
loc = tank
|
||||
|
||||
/obj/item/extinguisher/mini/nozzle/extinguisher_spray(atom/A, mob/living/user)
|
||||
if(nozzle_mode == EXTINGUISHER)
|
||||
return ..()
|
||||
|
||||
. = TRUE
|
||||
switch(nozzle_mode)
|
||||
if(NANOFROST)
|
||||
if(reagents.total_volume < 100)
|
||||
to_chat(user, "<span class='warning'>You need at least 100 units of water to use the nanofrost launcher!</span>")
|
||||
return
|
||||
|
||||
if(COOLDOWN_TIMELEFT(src, nanofrost_cooldown))
|
||||
to_chat(user, "<span class='warning'>The nanofrost launcher is still recharging!</span>")
|
||||
return
|
||||
|
||||
COOLDOWN_START(src, nanofrost_cooldown, nanofrost_cooldown_time)
|
||||
reagents.remove_any(100)
|
||||
var/obj/effect/nanofrost_container/iceball = new /obj/effect/nanofrost_container(get_turf(src))
|
||||
log_game("[key_name(user)] used Nanofrost at [get_area(user)] ([user.x], [user.y], [user.z]).")
|
||||
playsound(src,'sound/items/syringeproj.ogg', 40, TRUE)
|
||||
iceball.throw_at(A, 6, 2, user)
|
||||
sleep(2)
|
||||
iceball.Smoke()
|
||||
return
|
||||
|
||||
if(METAL_FOAM)
|
||||
if(!user.Adjacent(A) || !isturf(A))
|
||||
return
|
||||
|
||||
if(metal_synthesis_charge <= 0)
|
||||
to_chat(user, "<span class='warning'>Metal foam mix is still being synthesized!</span>")
|
||||
return
|
||||
|
||||
if(reagents.total_volume < 10)
|
||||
to_chat(user, "<span class='warning'>You need at least 10 units of water to use the metal foam synthesizer!</span>")
|
||||
return
|
||||
|
||||
var/obj/effect/particle_effect/foam/metal/foam = new /obj/effect/particle_effect/foam/metal(get_turf(A), TRUE)
|
||||
foam.spread_amount = 0
|
||||
reagents.remove_any(10)
|
||||
metal_synthesis_charge--
|
||||
addtimer(CALLBACK(src, PROC_REF(refill_metal_charge)), metal_regen_time)
|
||||
return
|
||||
|
||||
/obj/item/extinguisher/mini/nozzle/proc/refill_metal_charge()
|
||||
metal_synthesis_charge++
|
||||
|
||||
/obj/effect/nanofrost_container
|
||||
name = "nanofrost container"
|
||||
desc = "A frozen shell of ice containing nanofrost that freezes the surrounding area after activation."
|
||||
icon_state = "frozen_smoke_capsule"
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
pass_flags = PASSTABLE
|
||||
|
||||
/obj/effect/nanofrost_container/proc/Smoke()
|
||||
var/datum/effect_system/smoke_spread/freezing/S = new
|
||||
S.set_up(amount = 6, only_cardinals = FALSE, source = loc)
|
||||
S.start()
|
||||
new /obj/effect/decal/cleanable/flour/nanofrost(get_turf(src))
|
||||
playsound(src, 'sound/effects/bamf.ogg', 100, TRUE)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/nanofrost_container/anomaly
|
||||
name = "nanofrost anomaly"
|
||||
desc = "A frozen shell of ice containing nanofrost that freezes the surrounding area."
|
||||
icon_state = "frozen_smoke_anomaly"
|
||||
|
||||
#undef EXTINGUISHER
|
||||
#undef NANOFROST
|
||||
#undef METAL_FOAM
|
||||
@@ -1,55 +0,0 @@
|
||||
/obj/item/stack/tape_roll
|
||||
name = "tape roll"
|
||||
desc = "A roll of sticky tape. Possibly for taping ducks... or was that ducts?"
|
||||
icon = 'icons/obj/bureaucracy.dmi'
|
||||
icon_state = "taperoll"
|
||||
singular_name = "tape roll"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
amount = 25
|
||||
max_amount = 25
|
||||
|
||||
/obj/item/stack/tape_roll/New(loc, amount=null)
|
||||
..()
|
||||
update_icon(UPDATE_ICON_STATE)
|
||||
|
||||
/obj/item/stack/tape_roll/attack__legacy__attackchain(mob/living/carbon/human/M, mob/living/user)
|
||||
if(!istype(M)) //What good is a duct tape mask if you are unable to speak?
|
||||
return
|
||||
if(M.wear_mask)
|
||||
to_chat(user, "Remove [M.p_their()] mask first!")
|
||||
return
|
||||
if(amount < 2)
|
||||
to_chat(user, "You'll need more tape for this!")
|
||||
return
|
||||
if(!M.check_has_mouth())
|
||||
to_chat(user, "[M.p_they(TRUE)] [M.p_have()] no mouth to tape over!")
|
||||
return
|
||||
user.visible_message("<span class='warning'>[user] is taping [M]'s mouth closed!</span>",
|
||||
"<span class='notice'>You try to tape [M == user ? "your own" : "[M]'s"] mouth shut!</span>",
|
||||
"<span class='warning'>You hear tape ripping.</span>")
|
||||
if(!do_after(user, 50, target = M))
|
||||
return
|
||||
if(!use(2))
|
||||
to_chat(user, "<span class='notice'>You don't have enough tape!</span>")
|
||||
return
|
||||
if(M.wear_mask)
|
||||
to_chat(user, "<span class='notice'>[M == user ? user : M]'s mouth is already covered!</span>")
|
||||
return
|
||||
user.visible_message("<span class='warning'>[user] tapes [M]'s mouth shut!</span>",
|
||||
"<span class='notice'>You cover [M == user ? "your own" : "[M]'s"] mouth with a piece of duct tape.[M == user ? null : " That will shut them up."]</span>")
|
||||
var/obj/item/clothing/mask/muzzle/G = new /obj/item/clothing/mask/muzzle/tapegag
|
||||
M.equip_to_slot(G, ITEM_SLOT_MASK)
|
||||
G.add_fingerprint(user)
|
||||
|
||||
/obj/item/stack/tape_roll/update_icon_state()
|
||||
var/amount = get_amount()
|
||||
if((amount <= 2) && (amount > 0))
|
||||
icon_state = "taperoll"
|
||||
if((amount <= 4) && (amount > 2))
|
||||
icon_state = "taperoll-2"
|
||||
if((amount <= 6) && (amount > 4))
|
||||
icon_state = "taperoll-3"
|
||||
if(amount > 6)
|
||||
icon_state = "taperoll-4"
|
||||
else
|
||||
icon_state = "taperoll-4"
|
||||
@@ -1,109 +0,0 @@
|
||||
/* Teleportation devices.
|
||||
* Contains:
|
||||
* Hand-tele
|
||||
*/
|
||||
|
||||
/*
|
||||
* Hand-tele
|
||||
*/
|
||||
/obj/item/hand_tele
|
||||
name = "hand tele"
|
||||
desc = "An experimental portable teleportation station developed by Nanotrasen, small enough to be carried in a pocket."
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "hand_tele"
|
||||
item_state = "electronic"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
throw_speed = 3
|
||||
throw_range = 5
|
||||
materials = list(MAT_METAL=10000)
|
||||
origin_tech = null
|
||||
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 30, RAD = 0, FIRE = 100, ACID = 100)
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
|
||||
var/icon_state_inactive = "hand_tele_inactive"
|
||||
/// The number of open teleportals.
|
||||
var/active_portals = 0
|
||||
/// Variable contains next time hand tele can be used to make it not EMP proof
|
||||
var/emp_timer = 0
|
||||
|
||||
/obj/item/hand_tele/examine_more(mob/user)
|
||||
. = ..()
|
||||
. += "Conventional teleportation technology requires either inflexible quantum pad setups that can only send users between two fixed locations, \
|
||||
or large immobile portal generators connected to an even larger set of computer equipment that is required for safe translation through extradimensional space."
|
||||
. += ""
|
||||
. += "This specialised portable teleporter is an experimental miniaturisation of the latter category. It utilises highly specialised analogue circuitry to perform the bulk of the teleportation calculations, \
|
||||
allowing for a far more compact package than more generalised digital computer technology would allow. Some digital components are present, which handle the user interface and beacon tracking functions. \
|
||||
In order to allow the device to be fully portable, it has no frame to stabilise the portals it generates. This comes at the cost of the portals only being able to persist for a limited time."
|
||||
. += ""
|
||||
. += "A limited number of these experimental devices exist. Due manufacturing difficulties (particularly regarding the analogue computer), \
|
||||
Nanotrasen has delayed releasing it onto the market until it can improve its production methods."
|
||||
|
||||
/obj/item/hand_tele/Initialize(mapload)
|
||||
. = ..()
|
||||
AddElement(/datum/element/high_value_item)
|
||||
|
||||
/obj/item/hand_tele/attack_self__legacy__attackchain(mob/user)
|
||||
// The turf the user is currently located in.
|
||||
var/turf/current_location = get_turf(user)
|
||||
if(emp_timer > world.time)
|
||||
do_sparks(5, 0, loc)
|
||||
to_chat(user, "<span class='warning'>[src] attempts to create a portal, but abruptly shuts off.</span>")
|
||||
return
|
||||
if(!current_location||!is_teleport_allowed(current_location.z))//If turf was not found or they're somewhere teleproof
|
||||
to_chat(user, "<span class='notice'>\The [src] is malfunctioning.</span>")
|
||||
return
|
||||
var/list/L = list()
|
||||
for(var/obj/machinery/computer/teleporter/com in SSmachines.get_by_type(/obj/machinery/computer/teleporter))
|
||||
if(com.target)
|
||||
if(com.power_station && com.power_station.teleporter_hub && com.power_station.engaged)
|
||||
L["[com.id] (Active)"] = com.target
|
||||
else
|
||||
L["[com.id] (Inactive)"] = com.target
|
||||
var/list/turfs = list()
|
||||
var/area/A
|
||||
for(var/turf/T in orange(10))
|
||||
if(T.x>world.maxx-8 || T.x<8)
|
||||
continue //putting them at the edge is dumb
|
||||
if(T.y>world.maxy-8 || T.y<8)
|
||||
continue
|
||||
A = get_area(T)
|
||||
if(A.tele_proof)
|
||||
continue // Telescience-proofed areas require a beacon.
|
||||
turfs += T
|
||||
if(length(turfs))
|
||||
L["None (Dangerous)"] = pick(turfs)
|
||||
flick("hand_tele_activated", src)
|
||||
var/t1 = tgui_input_list(user, "Please select a teleporter to lock in on.", "Hand Teleporter", L)
|
||||
if(!t1 || (!user.is_in_active_hand(src) || user.stat || user.restrained()))
|
||||
return
|
||||
if(active_portals >= 3)
|
||||
user.show_message("<span class='notice'>\The [src] is recharging!</span>")
|
||||
return
|
||||
var/T = L[t1]
|
||||
user.show_message("<span class='notice'>Locked In.</span>", 2)
|
||||
var/obj/effect/portal/P = new /obj/effect/portal/hand_tele(get_turf(src), T, src, creation_mob = user)
|
||||
try_move_adjacent(P)
|
||||
active_portals++
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/item/hand_tele/emp_act(severity)
|
||||
make_inactive(severity)
|
||||
return ..()
|
||||
|
||||
/obj/item/hand_tele/proc/make_inactive(severity)
|
||||
icon_state = icon_state_inactive
|
||||
var/time = rand(25 SECONDS, 30 SECONDS) * severity
|
||||
emp_timer = world.time + time
|
||||
addtimer(CALLBACK(src, PROC_REF(check_inactive), emp_timer), time)
|
||||
|
||||
/obj/item/hand_tele/proc/check_inactive(current_emp_timer)
|
||||
if(emp_timer != current_emp_timer)
|
||||
return
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/obj/item/hand_tele/examine(mob/user)
|
||||
. = ..()
|
||||
if(emp_timer > world.time)
|
||||
. += "<span class='warning'>It looks inactive.</span>"
|
||||
|
||||
/obj/item/hand_tele/portal_destroyed(obj/effect/portal/P)
|
||||
active_portals--
|
||||
@@ -1,234 +0,0 @@
|
||||
/obj/item/vending_refill
|
||||
name = "resupply canister"
|
||||
var/machine_name = "Generic"
|
||||
|
||||
icon = 'icons/obj/vending_restock.dmi'
|
||||
icon_state = "refill_snack"
|
||||
item_state = "restock_unit"
|
||||
desc = "A vending machine restock cart."
|
||||
usesound = 'sound/items/deconstruct.ogg'
|
||||
flags = CONDUCT
|
||||
force = 7
|
||||
throwforce = 10
|
||||
throw_speed = 1
|
||||
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 70, ACID = 30)
|
||||
|
||||
// Built automatically from the corresponding vending machine.
|
||||
// If null, considered to be full upon being restocked.
|
||||
var/list/products
|
||||
var/list/contraband
|
||||
var/list/premium
|
||||
|
||||
/obj/item/vending_refill/Initialize(mapload)
|
||||
. = ..()
|
||||
name = "\improper [machine_name] restocking unit"
|
||||
|
||||
/obj/item/vending_refill/examine(mob/user)
|
||||
. = ..()
|
||||
var/num = get_part_rating()
|
||||
if(num == INFINITY)
|
||||
. += "It's sealed tight, completely full of supplies."
|
||||
else if(num == 0)
|
||||
. += "It's empty!"
|
||||
else if(!isnull(num)) // If it's null, then the items haven't been properly added yet.
|
||||
. += "It can restock [num] item\s."
|
||||
|
||||
/obj/item/vending_refill/get_part_rating()
|
||||
. = 0
|
||||
if(isnull(products) && isnull(contraband) && isnull(premium))
|
||||
return null
|
||||
for(var/key in products)
|
||||
. += products[key]
|
||||
for(var/key in contraband)
|
||||
. += contraband[key]
|
||||
for(var/key in premium)
|
||||
. += premium[key]
|
||||
|
||||
if(. > 30)
|
||||
return INFINITY
|
||||
|
||||
/obj/item/vending_refill/boozeomat
|
||||
machine_name = "Booze-O-Mat"
|
||||
icon_state = "refill_booze"
|
||||
|
||||
/obj/item/vending_refill/coffee
|
||||
machine_name = "hot drinks"
|
||||
icon_state = "refill_joe"
|
||||
|
||||
/obj/item/vending_refill/snack
|
||||
machine_name = "Getmore Chocolate Corp"
|
||||
|
||||
/obj/item/vending_refill/cola
|
||||
machine_name = "Robust Softdrinks"
|
||||
icon_state = "refill_cola"
|
||||
|
||||
/obj/item/vending_refill/cigarette
|
||||
machine_name = "cigarette"
|
||||
icon_state = "refill_smoke"
|
||||
|
||||
/obj/item/vending_refill/autodrobe
|
||||
machine_name = "AutoDrobe"
|
||||
icon_state = "refill_costume"
|
||||
|
||||
/obj/item/vending_refill/hatdispenser
|
||||
machine_name = "hat"
|
||||
icon_state = "refill_costume"
|
||||
|
||||
/obj/item/vending_refill/suitdispenser
|
||||
machine_name = "suit"
|
||||
icon_state = "refill_costume"
|
||||
|
||||
/obj/item/vending_refill/shoedispenser
|
||||
machine_name = "shoe"
|
||||
icon_state = "refill_costume"
|
||||
|
||||
/obj/item/vending_refill/clothing
|
||||
machine_name = "ClothesMate"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/crittercare
|
||||
machine_name = "CritterCare"
|
||||
icon_state = "refill_pet"
|
||||
|
||||
/obj/item/vending_refill/chinese
|
||||
machine_name = "MrChangs"
|
||||
|
||||
/obj/item/vending_refill/hydroseeds
|
||||
machine_name = "MegaSeed Servitor"
|
||||
icon_state = "refill_plant"
|
||||
|
||||
/obj/item/vending_refill/assist
|
||||
machine_name = "Vendomat"
|
||||
icon_state = "refill_engi"
|
||||
|
||||
/obj/item/vending_refill/cart
|
||||
machine_name = "PTech"
|
||||
icon_state = "refill_smoke"
|
||||
|
||||
/obj/item/vending_refill/dinnerware
|
||||
machine_name = "Plasteel Chef's Dinnerware Vendor"
|
||||
icon_state = "refill_smoke"
|
||||
|
||||
/obj/item/vending_refill/engineering
|
||||
machine_name = "Robco Tool Maker"
|
||||
icon_state = "refill_engi"
|
||||
|
||||
/obj/item/vending_refill/youtool
|
||||
machine_name = "YouTool"
|
||||
icon_state = "refill_engi"
|
||||
|
||||
/obj/item/vending_refill/engivend
|
||||
machine_name = "Engi-Vend"
|
||||
icon_state = "refill_engi"
|
||||
|
||||
/obj/item/vending_refill/medical
|
||||
machine_name = "NanoMed Plus"
|
||||
icon_state = "refill_medical"
|
||||
|
||||
/obj/item/vending_refill/wallmed
|
||||
machine_name = "NanoMed"
|
||||
icon_state = "refill_medical"
|
||||
|
||||
/obj/item/vending_refill/hydronutrients
|
||||
machine_name = "NutriMax"
|
||||
icon_state = "refill_plant"
|
||||
|
||||
/obj/item/vending_refill/security
|
||||
icon_state = "refill_sec"
|
||||
|
||||
/obj/item/vending_refill/sovietsoda
|
||||
machine_name = "BODA"
|
||||
icon_state = "refill_cola"
|
||||
|
||||
/obj/item/vending_refill/sustenance
|
||||
machine_name = "Sustenance Vendor"
|
||||
|
||||
/obj/item/vending_refill/donksoft
|
||||
machine_name = "Donksoft Toy Vendor"
|
||||
icon_state = "refill_donksoft"
|
||||
|
||||
/obj/item/vending_refill/robotics
|
||||
machine_name = "Robotech Deluxe"
|
||||
icon_state = "refill_engi"
|
||||
|
||||
/obj/item/vending_refill/smith
|
||||
machine_name = "Castivend"
|
||||
icon_state = "refill_custom"
|
||||
|
||||
//Departmental clothing vendors
|
||||
|
||||
/obj/item/vending_refill/secdrobe
|
||||
machine_name = "SecDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/detdrobe
|
||||
machine_name = "DetDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/medidrobe
|
||||
machine_name = "MediDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/virodrobe
|
||||
machine_name = "ViroDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/chemdrobe
|
||||
machine_name = "ChemDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/genedrobe
|
||||
machine_name = "GeneDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/scidrobe
|
||||
machine_name = "SciDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/robodrobe
|
||||
machine_name = "RoboDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/engidrobe
|
||||
machine_name = "EngiDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/atmosdrobe
|
||||
machine_name = "AtmosDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/cargodrobe
|
||||
machine_name = "CargoDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/exploredrobe
|
||||
machine_name = "ExploreDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/chefdrobe
|
||||
machine_name = "ChefDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/bardrobe
|
||||
machine_name = "BarDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/hydrodrobe
|
||||
machine_name = "HydroDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/janidrobe
|
||||
machine_name = "JaniDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/lawdrobe
|
||||
machine_name = "LawDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/traindrobe
|
||||
machine_name = "TrainDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
|
||||
/obj/item/vending_refill/minedrobe
|
||||
machine_name = "MineDrobe"
|
||||
icon_state = "refill_clothes"
|
||||
Reference in New Issue
Block a user