Merge branch 'master' into species-refactor

This commit is contained in:
Zandario
2020-10-02 17:19:48 -05:00
262 changed files with 169039 additions and 84967 deletions
+6 -15
View File
@@ -646,23 +646,14 @@ Traitors and the like can also be revived with the previous role mostly intact.
if(!check_rights(R_ADMIN))
return
var/heavy = input("Range of heavy pulse.", text("Input")) as num|null
if(heavy == null)
return
var/light = input("Range of light pulse.", text("Input")) as num|null
if(light == null)
var/range = input("Range.", text("Input")) as num|null
if(!range)
return
log_admin("[key_name(usr)] created an EM Pulse - log below") //because we'll just log the empulse itself
message_admins("[key_name_admin(usr)] created an EM Pulse at [AREACOORD(O)] with range [range]")
empulse_using_range(O, range, TRUE) //its details get shown too
if (heavy || light)
empulse(O, heavy, light)
log_admin("[key_name(usr)] created an EM Pulse ([heavy],[light]) at [AREACOORD(O)]")
message_admins("[key_name_admin(usr)] created an EM Pulse ([heavy],[light]) at [AREACOORD(O)]")
SSblackbox.record_feedback("tally", "admin_verb", 1, "EM Pulse") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
return
else
return
SSblackbox.record_feedback("tally", "admin_verb", 1, "EM Pulse") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
/client/proc/cmd_admin_gib(mob/M in GLOB.mob_list)
set category = "Special Verbs"
@@ -18,7 +18,7 @@
/datum/blobstrain/reagent/electromagnetic_web/death_reaction(obj/structure/blob/B, damage_flag)
if(damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser")
empulse(B.loc, 1, 3) //less than screen range, so you can stand out of range to avoid it
empulse_using_range(B.loc, 5) //less than screen range, so you can stand out of range to avoid it
/datum/reagent/blob/electromagnetic_web
name = "Electromagnetic Web"
@@ -28,6 +28,6 @@
/datum/reagent/blob/electromagnetic_web/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
reac_volume = ..()
if(prob(reac_volume*2))
M.emp_act(EMP_LIGHT)
M.emp_act(50)
if(M)
M.apply_damage(reac_volume, BURN, wound_bonus=CANT_WOUND)
@@ -204,7 +204,7 @@
if(severity > 0)
if(overmind)
overmind.blobstrain.emp_reaction(src, severity)
if(prob(100 - severity * 30))
if(prob(severity/1.5))
new /obj/effect/temp_visual/emp(get_turf(src))
/obj/structure/blob/zap_act(power)
@@ -48,6 +48,6 @@
for(var/obj/machinery/light/L in range(5, usr))
L.on = 1
L.break_light_tube()
empulse(get_turf(user), 2, 5, 1)
empulse_using_range(get_turf(user), 8, TRUE)
playsound(get_turf(user), 'sound/effects/lingempscreech.ogg', 75, TRUE, 5, soundenvwet = 0)
return TRUE
@@ -223,7 +223,7 @@
L.flash_act(1, 1)
if(issilicon(target))
var/mob/living/silicon/S = L
S.emp_act(EMP_HEAVY)
S.emp_act(80)
else //for Nar'sian weaklings
to_chat(L, "<span class='heavy_brass'>\"How does it feel to see the light, dog?\"</span>")
L.visible_message("<span class='warning'>[L]'s eyes flare with burning light!</span>", \
@@ -11,7 +11,7 @@
/obj/structure/destructible/clockwork/trap/power_nullifier/activate()
if(!activated)
activated = TRUE
empulse(get_turf(src),1,1,TRUE)
empulse_using_range(get_turf(src),1,TRUE)
/obj/structure/destructible/clockwork/trap/power_nullifier/emp_act(var/strength=1)
activate()
+3 -3
View File
@@ -165,7 +165,7 @@
/datum/action/innate/cult/blood_spell/emp/Activate()
owner.visible_message("<span class='warning'>[owner]'s hand flashes a bright blue!</span>", \
"<span class='cultitalic'>You speak the cursed words, emitting an EMP blast from your hand.</span>")
empulse(owner, 2, 5)
empulse_using_range(owner, 8)
owner.whisper(invocation, language = /datum/language/common)
charges--
if(charges<=0)
@@ -451,7 +451,7 @@
L.flash_act(1,1)
if(issilicon(target))
var/mob/living/silicon/S = L
S.emp_act(EMP_HEAVY)
S.emp_act(80)
else if(iscarbon(target))
var/mob/living/carbon/C = L
C.silent += clamp(12 - C.silent, 0, 6)
@@ -610,7 +610,7 @@
var/prev_color = candidate.color
candidate.color = "black"
if(do_after(user, 90, target = candidate))
candidate.emp_act(EMP_HEAVY)
candidate.emp_act(80)
var/construct_class = alert(user, "Please choose which type of construct you wish to create.",,"Juggernaut","Wraith","Artificer")
user.visible_message("<span class='danger'>The dark cloud receedes from what was formerly [candidate], revealing a\n [construct_class]!</span>")
switch(construct_class)
+1 -1
View File
@@ -982,7 +982,7 @@ structure_check() searches for nearby cultist structures required for the invoca
visible_message("<span class='warning'>A colossal shockwave of energy bursts from the rune, disintegrating it in the process!</span>")
for(var/mob/living/L in range(src, 3))
L.DefaultCombatKnockdown(30)
empulse(T, 0.42*(intensity), 1)
empulse_using_range(T, 0.65*(intensity))
var/list/images = list()
var/zmatch = T.z
var/datum/atom_hud/AH = GLOB.huds[DATA_HUD_SECURITY_ADVANCED]
@@ -424,8 +424,7 @@
range = -1
include_user = TRUE
charge_max = 300
emp_heavy = 6
emp_light = 10
range = 14
sound = 'sound/effects/lingscreech.ogg'
/obj/effect/proc_holder/spell/aoe_turf/fire_cascade
@@ -300,7 +300,7 @@
continue
to_chat(human, "<span class='revenwarning'>You feel [pick("your sense of direction flicker out", "a stabbing pain in your head", "your mind fill with static")].</span>")
new /obj/effect/temp_visual/revenant(human.loc)
human.emp_act(EMP_HEAVY)
human.emp_act(80)
for(var/obj/thing in T)
if(istype(thing, /obj/machinery/power/apc) || istype(thing, /obj/machinery/power/smes)) //Doesn't work on SMES and APCs, to prevent kekkery
continue
@@ -310,12 +310,12 @@
thing.emag_act(null)
else
if(!istype(thing, /obj/machinery/clonepod)) //I hate everything but mostly the fact there's no better way to do this without just not affecting it at all
thing.emp_act(EMP_HEAVY)
thing.emp_act(80)
for(var/mob/living/silicon/robot/S in T) //Only works on cyborgs, not AI
playsound(S, 'sound/machines/warning-buzzer.ogg', 50, 1)
new /obj/effect/temp_visual/revenant(S.loc)
S.spark_system.start()
S.emp_act(EMP_HEAVY)
S.emp_act(80)
//Blight: Infects nearby humans and in general messes living stuff up.
/obj/effect/proc_holder/spell/aoe_turf/revenant/blight
@@ -186,6 +186,20 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(/datum/gas/oxygen, /datum/g
moles_visible = MOLES_GAS_VISIBLE * 60
rarity = 250
/datum/gas/methane
id = "methane"
specific_heat = 30
name = "Methane"
rarity = 320
/datum/gas/methyl_bromide
id = "methyl_bromide"
specific_heat = 42
name = "Methyl Bromide"
dangerous = TRUE
rarity = 310
/obj/effect/overlay/gas
icon = 'icons/effects/atmospherics.dmi'
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
@@ -97,7 +97,7 @@
/datum/gas/oxygen = new/datum/tlv(16, 19, 135, 140), // Partial pressure, kpa
/datum/gas/nitrogen = new/datum/tlv(-1, -1, 1000, 1000),
/datum/gas/carbon_dioxide = new/datum/tlv(-1, -1, 5, 10),
/datum/gas/miasma = new/datum/tlv/(-1, -1, 2, 5),
/datum/gas/miasma = new/datum/tlv(-1, -1, 2, 5),
/datum/gas/plasma = new/datum/tlv/dangerous,
/datum/gas/nitrous_oxide = new/datum/tlv/dangerous,
/datum/gas/bz = new/datum/tlv/dangerous,
@@ -106,7 +106,9 @@
/datum/gas/tritium = new/datum/tlv/dangerous,
/datum/gas/stimulum = new/datum/tlv(-1, -1, 1000, 1000), // Stimulum has only positive effects
/datum/gas/nitryl = new/datum/tlv/dangerous,
/datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000) // Unlike oxygen, pluoxium does not fuel plasma/tritium fires
/datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000), // Unlike oxygen, pluoxium does not fuel plasma/tritium fires
/datum/gas/methane = new/datum/tlv(-1, -1, 3, 6),
/datum/gas/methyl_bromide = new/datum/tlv/dangerous
)
/obj/machinery/airalarm/server // No checks here.
@@ -125,7 +127,9 @@
/datum/gas/tritium = new/datum/tlv/no_checks,
/datum/gas/stimulum = new/datum/tlv/no_checks,
/datum/gas/nitryl = new/datum/tlv/no_checks,
/datum/gas/pluoxium = new/datum/tlv/no_checks
/datum/gas/pluoxium = new/datum/tlv/no_checks,
/datum/gas/methane = new/datum/tlv/no_checks,
/datum/gas/methyl_bromide = new/datum/tlv/no_checks
)
/obj/machinery/airalarm/kitchen_cold_room // Copypasta: to check temperatures.
@@ -144,7 +148,9 @@
/datum/gas/tritium = new/datum/tlv/dangerous,
/datum/gas/stimulum = new/datum/tlv(-1, -1, 1000, 1000), // Stimulum has only positive effects
/datum/gas/nitryl = new/datum/tlv/dangerous,
/datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000) // Unlike oxygen, pluoxium does not fuel plasma/tritium fires
/datum/gas/pluoxium = new/datum/tlv(-1, -1, 1000, 1000), // Unlike oxygen, pluoxium does not fuel plasma/tritium fires
/datum/gas/methane = new/datum/tlv(-1, -1, 3, 6),
/datum/gas/methyl_bromide = new/datum/tlv/dangerous
)
/obj/machinery/airalarm/unlocked
@@ -542,7 +548,9 @@
/datum/gas/tritium,
/datum/gas/bz,
/datum/gas/stimulum,
/datum/gas/pluoxium
/datum/gas/pluoxium,
/datum/gas/methane,
/datum/gas/methyl_bromide
),
"scrubbing" = 1,
"widenet" = 1,
@@ -50,7 +50,9 @@
"stimulum" = /obj/machinery/portable_atmospherics/canister/stimulum,
"pluoxium" = /obj/machinery/portable_atmospherics/canister/pluoxium,
"caution" = /obj/machinery/portable_atmospherics/canister,
"miasma" = /obj/machinery/portable_atmospherics/canister/miasma
"miasma" = /obj/machinery/portable_atmospherics/canister/miasma,
"methane" = /obj/machinery/portable_atmospherics/canister/methane,
"methyl bromide" = /obj/machinery/portable_atmospherics/canister/methyl_bromide
)
/obj/machinery/portable_atmospherics/canister/interact(mob/user)
@@ -62,7 +64,7 @@
/obj/machinery/portable_atmospherics/canister/nitrogen
name = "n2 canister"
desc = "Nitrogen gas. Reportedly useful for something."
desc = "Nitrogen. Reportedly useful for something."
icon_state = "red"
gas_type = /datum/gas/nitrogen
@@ -80,19 +82,19 @@
/obj/machinery/portable_atmospherics/canister/toxins
name = "plasma canister"
desc = "Plasma gas. The reason YOU are here. Highly toxic."
desc = "Plasma. The reason YOU are here. Highly toxic."
icon_state = "orange"
gas_type = /datum/gas/plasma
/obj/machinery/portable_atmospherics/canister/bz
name = "\improper BZ canister"
desc = "BZ, a powerful hallucinogenic nerve agent."
desc = "BZ. A powerful hallucinogenic nerve agent."
icon_state = "purple"
gas_type = /datum/gas/bz
/obj/machinery/portable_atmospherics/canister/nitrous_oxide
name = "n2o canister"
desc = "Nitrous oxide gas. Known to cause drowsiness."
desc = "Nitrous oxide. Known to cause drowsiness."
icon_state = "redws"
gas_type = /datum/gas/nitrous_oxide
@@ -115,7 +117,7 @@
/obj/machinery/portable_atmospherics/canister/nitryl
name = "nitryl canister"
desc = "Nitryl gas. Feels great 'til the acid eats your lungs."
desc = "Nitryl. Feels great 'til the acid eats your lungs."
icon_state = "brown"
gas_type = /datum/gas/nitryl
@@ -133,7 +135,7 @@
/obj/machinery/portable_atmospherics/canister/water_vapor
name = "water vapor canister"
desc = "Water Vapor. We get it, you vape."
desc = "Water vapor. We get it, you vape."
icon_state = "water_vapor"
gas_type = /datum/gas/water_vapor
filled = 1
@@ -145,6 +147,18 @@
gas_type = /datum/gas/miasma
filled = 1
/obj/machinery/portable_atmospherics/canister/methane
name = "methane canister"
desc = "Methane. The simplest of hydrocarbons. Non-toxic but highly flammable."
icon_state = "greyblackred"
gas_type = /datum/gas/methane
/obj/machinery/portable_atmospherics/canister/methyl_bromide
name = "methyl bromide canister"
desc = "Methyl bromide. A potent toxin to most, essential for the Kharmaan to live."
icon_state = "purplecyan"
gas_type = /datum/gas/methyl_bromide
/obj/machinery/portable_atmospherics/canister/proc/get_time_left()
if(timing)
. = round(max(0, valve_timer - world.time) / 10, 1)
@@ -63,9 +63,9 @@
if(. & EMP_PROTECT_SELF)
return
if(is_operational())
if(prob(50 / severity))
if(prob(severity/2))
on = !on
if(prob(100 / severity))
if(prob(severity))
direction = PUMP_OUT
pump.target_pressure = rand(0, 100 * ONE_ATMOSPHERE)
update_icon()
@@ -80,7 +80,6 @@
else if(on && holding && direction == PUMP_OUT)
investigate_log("[key_name(user)] started a transfer into [holding].", INVESTIGATE_ATMOS)
/obj/machinery/portable_atmospherics/pump/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
@@ -58,7 +58,7 @@
if(. & EMP_PROTECT_SELF)
return
if(is_operational())
if(prob(50 / severity))
if(prob(severity/3))
on = !on
update_icon()
+2 -1
View File
@@ -8,6 +8,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/client/parent
//doohickeys for savefiles
var/path
var/vr_path
var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used
var/max_save_slots = 16
@@ -544,7 +545,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
if(length(pref_species.allowed_limb_ids))
if(!chosen_limb_id || !(chosen_limb_id in pref_species.allowed_limb_ids))
chosen_limb_id = pref_species.id
chosen_limb_id = pref_species.limbs_id || pref_species.id
dat += "<h3>Body sprite</h3>"
dat += "<a style='display:block;width:100px' href='?_src_=prefs;preference=bodysprite;task=input'>[chosen_limb_id]</a>"
+51 -14
View File
@@ -212,26 +212,31 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
if(!ckey)
return
path = "data/player_saves/[ckey[1]]/[ckey]/[filename]"
vr_path = "data/player_saves/[ckey[1]]/[ckey]/vore"
/datum/preferences/proc/load_preferences()
if(!path)
return 0
return FALSE
if(world.time < loadprefcooldown)
if(istype(parent))
to_chat(parent, "<span class='warning'>You're attempting to load your preferences a little too fast. Wait half a second, then try again.</span>")
return 0
return FALSE
loadprefcooldown = world.time + PREF_SAVELOAD_COOLDOWN
if(!fexists(path))
return 0
return FALSE
var/savefile/S = new /savefile(path)
if(!S)
return 0
return FALSE
S.cd = "/"
var/needs_update = savefile_needs_update(S)
if(needs_update == -2) //fatal, can't load any data
return 0
var/bacpath = "[path].updatebac" //todo: if the savefile version is higher then the server, check the backup, and give the player a prompt to load the backup
if (fexists(bacpath))
fdel(bacpath) //only keep 1 version of backup
fcopy(S, bacpath) //byond helpfully lets you use a savefile for the first arg.
return FALSE
. = TRUE
@@ -293,8 +298,14 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
//try to fix any outdated data if necessary
if(needs_update >= 0)
var/bacpath = "[path].updatebac" //todo: if the savefile version is higher then the server, check the backup, and give the player a prompt to load the backup
if (fexists(bacpath))
fdel(bacpath) //only keep 1 version of backup
fcopy(S, bacpath) //byond helpfully lets you use a savefile for the first arg.
update_preferences(needs_update, S) //needs_update = savefile_version if we need an update (positive integer)
//Sanitize
ooccolor = sanitize_ooccolor(sanitize_hexcolor(ooccolor, 6, 1, initial(ooccolor)))
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
@@ -336,7 +347,25 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
verify_keybindings_valid() // one of these days this will runtime and you'll be glad that i put it in a different proc so no one gets their saves wiped
return 1
if(needs_update >= 0) //save the updated version
var/old_default_slot = default_slot
var/old_max_save_slots = max_save_slots
for (var/slot in S.dir) //but first, update all current character slots.
if (copytext(slot, 1, 10) != "character")
continue
var/slotnum = text2num(copytext(slot, 10))
if (!slotnum)
continue
max_save_slots = max(max_save_slots, slotnum) //so we can still update byond member slots after they lose memeber status
default_slot = slotnum
if (load_character()) // this updtates char slots
save_character()
default_slot = old_default_slot
max_save_slots = old_max_save_slots
save_preferences()
return TRUE
/datum/preferences/proc/verify_keybindings_valid()
// Sanitize the actual keybinds to make sure they exist.
@@ -426,17 +455,17 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
/datum/preferences/proc/load_character(slot)
if(!path)
return 0
return FALSE
if(world.time < loadcharcooldown) //This is before the check to see if the filepath exists to ensure that BYOND can't get hung up on read attempts when the hard drive is a little slow
if(istype(parent))
to_chat(parent, "<span class='warning'>You're attempting to load your character a little too fast. Wait half a second, then try again.</span>")
return "SLOW THE FUCK DOWN" //the reason this isn't null is to make sure that people don't have their character slots overridden by random chars if they accidentally double-click a slot
loadcharcooldown = world.time + PREF_SAVELOAD_COOLDOWN
if(!fexists(path))
return 0
return FALSE
var/savefile/S = new /savefile(path)
if(!S)
return 0
return FALSE
S.cd = "/"
if(!slot)
slot = default_slot
@@ -448,7 +477,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S.cd = "/character[slot]"
var/needs_update = savefile_needs_update(S)
if(needs_update == -2) //fatal, can't load any data
return 0
return FALSE
. = TRUE
@@ -466,7 +495,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
pref_species = new newtype
scars_index = rand(1,5)
scars_index = rand(1,5) // WHY
//Character
S["real_name"] >> real_name
@@ -609,8 +638,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
S["vore_flags"] >> vore_flags
S["vore_taste"] >> vore_taste
S["belly_prefs"] >> belly_prefs
var/char_vr_path = "[vr_path]/character_[default_slot]_v2.json"
if(fexists(char_vr_path))
var/list/json_from_file = json_decode(file2text(char_vr_path))
if(json_from_file)
belly_prefs = json_from_file["belly_prefs"]
//gear loadout
var/text_to_load
S["loadout"] >> text_to_load
@@ -627,6 +659,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
gear_points -= init_cost
//try to fix any outdated data if necessary
//preference updating will handle saving the updated data for us.
if(needs_update >= 0)
update_character(needs_update, S) //needs_update == savefile_version if we need an update (positive integer)
@@ -877,7 +910,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
WRITE_FILE(S["vore_flags"] , vore_flags)
WRITE_FILE(S["vore_taste"] , vore_taste)
WRITE_FILE(S["belly_prefs"] , belly_prefs)
var/char_vr_path = "[vr_path]/character_[default_slot]_v2.json"
var/belly_prefs_json = safe_json_encode(list("belly_prefs" = belly_prefs))
if(fexists(char_vr_path))
fdel(char_vr_path)
text2file(belly_prefs_json,char_vr_path)
WRITE_FILE(S["persistent_scars"] , persistent_scars)
WRITE_FILE(S["scars1"] , scars_list["1"])
@@ -62,13 +62,12 @@
if(. & EMP_PROTECT_SELF)
return
var/mob/living/carbon/human/user = src.loc
switch(severity)
if(1)
if(activated && user && ishuman(user) && (user.wear_suit == src))
to_chat(user, "<span class='danger'>E:FATAL:RAM_READ_FAIL\nE:FATAL:STACK_EMPTY\nE:FATAL:READ_NULL_POINT\nE:FATAL:PWR_BUS_OVERLOAD</span>")
to_chat(user, "<span class='userdanger'>An electromagnetic pulse disrupts your [name] and violently tears you out of time-bluespace!</span>")
user.emote("scream")
deactivate(1, 1)
if(severity >= 70)
if(activated && user && ishuman(user) && (user.wear_suit == src))
to_chat(user, "<span class='danger'>E:FATAL:RAM_READ_FAIL\nE:FATAL:STACK_EMPTY\nE:FATAL:READ_NULL_POINT\nE:FATAL:PWR_BUS_OVERLOAD</span>")
to_chat(user, "<span class='userdanger'>An electromagnetic pulse disrupts your [name] and violently tears you out of time-bluespace!</span>")
user.emote("scream")
deactivate(1, 1)
/obj/item/clothing/suit/space/chronos/proc/finish_chronowalk(mob/living/carbon/human/user, turf/to_turf)
if(!user)
@@ -525,7 +525,7 @@ Contains:
icon_state = "hunter"
item_state = "swat_suit"
allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/kitchen/knife/combat)
armor = list("melee" = 60, "bullet" = 40, "laser" = 40, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wpound" = 25)
armor = list("melee" = 60, "bullet" = 40, "laser" = 40, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 25)
strip_delay = 130
resistance_flags = FIRE_PROOF | ACID_PROOF
+17
View File
@@ -102,3 +102,20 @@
/obj/item/clothing/neck/cloak/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, poly_colors, 3)
/obj/item/clothing/neck/cloak/alt
name = "cloak"
desc = "A ragged up white cloak. It reminds you of a place not far from here."
icon_state = "cloak"
item_state = "cloak"
/obj/item/clothing/neck/cloak/alt/polychromic
name = "polychromic cloak"
desc = "A ragged up cloak. It reminds you of a place not far from here."
icon_state = "cloak"
item_state = "cloak"
var/list/poly_colors = list("#FFFFFF", "#676767", "#4C4C4C")
/obj/item/clothing/neck/cloak/alt/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, poly_colors, 3)
+34 -1
View File
@@ -117,6 +117,27 @@
icon_state = "greydet"
item_state = "greydet"
/obj/item/clothing/suit/det_suit/forensicsred
name = "red forensics coat"
icon_state = "forensics_red"
item_state = "forensics_red"
/obj/item/clothing/suit/det_suit/forensicsred/long
name = "long red forensics coat"
icon_state = "forensics_red_long"
item_state = "forensics_red_long"
/obj/item/clothing/suit/det_suit/forensicsblue
name = "blue forensics coat"
icon_state = "forensics_blue"
item_state = "forensics_blue"
/obj/item/clothing/suit/det_suit/forensicsblue/long
name = "long blue forensics coat"
icon_state = "forensics_blue_long"
item_state = "forensics_blue_long"
//Engineering
/obj/item/clothing/suit/hazardvest
name = "hazard vest"
@@ -222,4 +243,16 @@
desc = "A dark blue vest with reflective strips for emergency medical technicians."
icon_state = "labcoat_emt"
item_state = "labcoat_emt"
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
/obj/item/clothing/suit/toggle/labcoat/emt/red
name = "red emt vest"
desc = "A red vest with reflective strips for emergency medical technicians."
icon_state = "labcoat_emtred"
item_state = "labcoat_emtred"
/obj/item/clothing/suit/toggle/labcoat/emt/highvis
name = "high visibility emt vest"
desc = "a high visibility vest for emergency medical technicians."
icon_state = "labcoat_highvis"
item_state = "labcoat_highvis"
+45
View File
@@ -62,3 +62,48 @@
name = "scientist labcoat"
desc = "A suit that protects against minor chemical spills. Has a purple stripe on the shoulder."
icon_state = "labcoat_tox"
// Departmental Jackets
/obj/item/clothing/suit/toggle/labcoat/depjacket/sci
name = "science jacket"
desc = "A comfortable jacket in science purple."
icon_state = "sci_dep_jacket"
item_state = "sci_dep_jacket"
allowed = list(/obj/item/analyzer, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
/obj/item/clothing/suit/toggle/labcoat/depjacket/med
name = "medical jacket"
desc = "A comfortable jacket in medical blue."
icon_state = "med_dep_jacket"
item_state = "med_dep_jacket"
allowed = list(/obj/item/analyzer, /obj/item/sensor_device, /obj/item/stack/medical, /obj/item/dnainjector, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/syringe, /obj/item/reagent_containers/hypospray, /obj/item/healthanalyzer, /obj/item/flashlight/pen, /obj/item/reagent_containers/glass/bottle, /obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/pill, /obj/item/storage/pill_bottle, /obj/item/paper, /obj/item/melee/classic_baton/telescopic, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman)
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 50, "rad" = 0, "fire" = 0, "acid" = 45)
/obj/item/clothing/suit/toggle/labcoat/depjacket/sec
name = "security jacket"
desc = "A comfortable jacket in security red."
icon_state = "sec_dep_jacket"
item_state = "sec_dep_jacket"
armor = list("melee" = 25, "bullet" = 15, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 45)
/obj/item/clothing/suit/toggle/labcoat/depjacket/sup
name = "supply jacket"
desc = "A comfortable jacket in supply brown."
icon_state = "supply_dep_jacket"
item_state = "supply_dep_jacket"
/obj/item/clothing/suit/toggle/labcoat/depjacket/sup/qm
name = "quartermaster's jacket"
desc = "A loose covering often warn by station quartermasters."
icon_state = "qmjacket"
item_state = "qmjacket"
/obj/item/clothing/suit/toggle/labcoat/depjacket/eng
name = "engineering jacket"
desc = "A comfortable jacket in engineering yellow."
icon_state = "engi_dep_jacket"
item_state = "engi_dep_jacket"
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 20, "fire" = 30, "acid" = 45)
allowed = list(/obj/item/flashlight, /obj/item/tank/internals/emergency_oxygen, /obj/item/tank/internals/plasmaman, /obj/item/t_scanner, /obj/item/construction/rcd, /obj/item/pipe_dispenser, /obj/item/toy, /obj/item/storage/fancy/cigarettes, /obj/item/lighter)
@@ -94,6 +94,23 @@
flags_inv = HIDEJUMPSUIT
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
/obj/item/clothing/suit/tailcoat
name = "tailcoat"
desc = "A rather impractical, long coat."
icon_state = "tailcoat"
item_state = "tailcoat"
/obj/item/clothing/suit/vickyblack
name = "black victorian coat"
desc = "An overbearing black coat, it looks far older than you are."
icon_state = "vickyblack"
item_state = "vickyblack"
/obj/item/clothing/suit/vickyred
name = "red victorian coat"
desc = "An overbearing red coat, it looks far older than you are."
icon_state = "vickyred"
item_state = "vickyred"
/obj/item/clothing/suit/apron/overalls
name = "coveralls"
@@ -1064,3 +1081,9 @@
desc = "An outfit used by traditional japanese warriors."
icon_state = "samurai"
item_state = "samurai"
/obj/item/clothing/suit/bomber
name = "old bomber jacket"
desc = "It looks like someone dragged this out of a muddy lake."
icon_state = "bomberalt"
item_state = "bomberalt"
+15
View File
@@ -23,6 +23,14 @@
body_parts_covered = CHEST|GROIN|ARMS
alt_covers_chest = TRUE
/obj/item/clothing/under/rank/cargo/util
name = "cargo utility uniform"
desc = "a utility uniform for cargo personnel"
icon_state = "utilsupply"
item_state = "utilsupply"
can_adjust = FALSE
/obj/item/clothing/under/rank/cargo/tech/skirt
name = "cargo technician's jumpskirt"
desc = "Skiiiiirts! They're comfy and easy to wear"
@@ -33,6 +41,13 @@
fitted = FEMALE_UNIFORM_TOP
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
/obj/item/clothing/under/rank/cargo/tech/long
name = "cargo technician's jumpsuit (trousers)"
desc = "A variant of the cargo technician's uniform with proper trousers, suited for colder climates and modest workers."
icon_state = "cargo_long"
item_state = "lb_suit"
alt_covers_chest = TRUE
/obj/item/clothing/under/rank/cargo/miner
name = "shaft miner's jumpsuit"
desc = "It's a snappy jumpsuit with a sturdy set of overalls. It is very dirty."
@@ -23,6 +23,68 @@
fitted = FEMALE_UNIFORM_TOP
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON
/obj/item/clothing/under/rank/civilian/util
name = "generic utility uniform"
desc = "A utility uniform worn by various crew."
icon_state = "utilgen"
item_state = "utilgen"
can_adjust = FALSE
/obj/item/clothing/under/rank/civilian/util/greyshirt
name = "grey uniform"
desc = "A bland, grey uniform."
icon_state = "greyshirt"
item_state = "greyshirt"
/obj/item/clothing/under/rank/civilian/victorian_redsleeves
name = "black vest red victorian suit"
desc = "A stark red victorian suit with a black vest."
icon_state = "victorianblred"
item_state = "victorianblred"
can_adjust = FALSE
/obj/item/clothing/under/rank/civilian/victorian_redvest
name = "red-vested victorian suit"
desc = "A victorian suit with a red vest."
icon_state = "victorianredvest"
item_state = "victorianredvest"
can_adjust = FALSE
/obj/item/clothing/under/rank/civilian/victorian_vest
name = "black victorian suit"
desc = "A simple black victorian suit."
icon_state = "victorianvest"
item_state = "victorianvest"
can_adjust = FALSE
/obj/item/clothing/under/rank/civilian/victorian_purple
name = "purple victorian suit"
desc = "A victorian suit in regal purple."
icon_state = "victorianlightfire"
item_state = "victorianlightfire"
can_adjust = FALSE
/obj/item/clothing/under/rank/civilian/victorianreddress
name = "red victorian dress"
desc = "A flashy red victorian dress."
icon_state = "victorianreddress"
item_state = "victorianreddress"
can_adjust = FALSE
/obj/item/clothing/under/rank/civilian/victorianblackdress
name = "black victorian dress"
desc = "A victorian dress in somber black."
icon_state = "victorianblackdress"
item_state = "victorianblackdress"
can_adjust = FALSE
/obj/item/clothing/under/rank/civilian/dutch
name = "dutch suit"
desc = "A dapper dutch suit."
icon_state = "dutch"
item_state = "dutch"
can_adjust = FALSE
/obj/item/clothing/under/rank/civilian/chaplain
desc = "It's a black jumpsuit, often worn by religious folk."
name = "chaplain's jumpsuit"
@@ -62,6 +124,12 @@
item_state = "b_suit"
can_adjust = FALSE
/obj/item/clothing/under/rank/civilian/head_of_personnel/whimsy
name = "casual head of personnel's jumpsuit"
desc = "It's a jumpsuit worn by someone who works in the position of \"Head of Personnel\", this one seems to be a bit more casual."
icon_state = "hop_casual"
item_state = "hop_casual"
/obj/item/clothing/under/rank/civilian/head_of_personnel/skirt
name = "head of personnel's jumpskirt"
desc = "It's a jumpskirt worn by someone who works in the position of \"Head of Personnel\"."
@@ -6,6 +6,13 @@
sensor_mode = SENSOR_COORDS
random_sensor = FALSE
/obj/item/clothing/under/rank/captain/util
name = "Command Utiltiy Uniform"
desc = "A utility uniform for command personnel."
icon_state = "utilcom"
item_state = "utilcom"
can_adjust = FALSE
/obj/item/clothing/under/rank/captain/skirt
name = "captain's jumpskirt"
desc = "It's a blue jumpskirt with some gold markings denoting the rank of \"Captain\"."
@@ -42,6 +42,20 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 60, "acid" = 20, "wound" = 5)
resistance_flags = NONE
/obj/item/clothing/under/rank/engineering/engineer/mechanic
name = "mechanic's jumpsuit"
desc = "an old mechanic's jumpsuit"
icon_state = "mechanic"
item_state = "mechanic"
can_adjust = FALSE
/obj/item/clothing/under/rank/engineering/engineer/util
name = "engineering utility uniform"
desc = "a utility jumpsuit for engineering personnel"
icon_state = "utileng"
item_state = "utileng"
can_adjust = FALSE
/obj/item/clothing/under/rank/engineering/engineer/hazard
name = "engineer's hazard jumpsuit"
desc = "A high visibility jumpsuit made from heat and radiation resistant materials."
@@ -86,6 +86,12 @@
permeability_coefficient = 0.5
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
/obj/item/clothing/under/rank/medical/paramedic/red
name = "red paramedic jumpsuit"
icon_state = "pmedred"
item_state = "pmedred"
can_adjust = FALSE
/obj/item/clothing/under/rank/medical/paramedic/light
desc = "It's made of a special fiber that provides minor protection against biohazards. It has a dark blue cross on the chest denoting that the wearer is a trained paramedic."
icon_state = "paramedic-light"
@@ -124,6 +130,13 @@
permeability_coefficient = 0.5
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
/obj/item/clothing/under/rank/medical/doctor/util
name = "Medical Utility Uniform"
desc = "Utility jumpsuit for medical personnel"
icon_state = "utilmed"
item_state = "utilmed"
can_adjust = FALSE
/obj/item/clothing/under/rank/medical/doctor/blue
name = "blue medical scrubs"
desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in baby blue."
+13
View File
@@ -61,6 +61,13 @@
permeability_coefficient = 0.5
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5)
/obj/item/clothing/under/rank/rnd/scientist/util
name = "Science Utility Uniform"
desc = "A utility uniform for science personnel"
icon_state = "utilsci"
item_state = "utilsci"
can_adjust = FALSE
/obj/item/clothing/under/rank/rnd/scientist/skirt
name = "scientist's jumpskirt"
desc = "It's made of a special fiber that provides minor protection against explosives. It has markings that denote the wearer as a scientist."
@@ -78,6 +85,12 @@
item_state = "robotics"
resistance_flags = NONE
/obj/item/clothing/under/rank/rnd/roboticist/sleek
name = "sleek roboticist's jumpsuit"
icon_state = "robosleek"
item_state = "robosleek"
can_adjust = FALSE
/obj/item/clothing/under/rank/rnd/roboticist/skirt
name = "roboticist's jumpskirt"
desc = "It's a slimming black with reinforced seams; great for industrial work."
+40 -1
View File
@@ -21,6 +21,13 @@
item_state = "r_suit"
armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30, "wound" = 10)
/obj/item/clothing/under/rank/security/officer/util
name = "security utility uniform"
desc = "a grey security uniform"
icon_state = "utilsec"
item_state = "utilsec"
can_adjust = FALSE
/obj/item/clothing/under/rank/security/officer/grey
name = "grey security jumpsuit"
desc = "A tactical relic of years past before Nanotrasen decided it was cheaper to dye the suits red instead of washing out the blood."
@@ -51,6 +58,28 @@
item_state = "blueshift"
can_adjust = FALSE
/obj/item/clothing/under/rank/security/officer/blueshirt/seccorp
name = "corporate security uniform"
desc = "How positively stuffy."
icon_state = "seccorp"
item_state = "seccorp"
can_adjust = FALSE
/obj/item/clothing/under/rank/security/officer/blueshirt/seccorp/wardencorp
name = "corporate warden uniform"
icon_state = "wardencorp"
item_state = "wardencorp"
/obj/item/clothing/under/rank/security/officer/blueshirt/seccorp/hoscorp
name = "corporate head of security's uniform"
icon_state = "hoscorp"
item_state = "hoscorp"
/obj/item/clothing/under/rank/security/officer/blueshirt/seccorp/detcorp
name = "corporate detective's uniform"
icon_state = "detcorp"
item_state = "detcorp"
/obj/item/clothing/under/rank/security/officer/spacepol
name = "police uniform"
desc = "Space not controlled by megacorporations, planets, or pirates is under the jurisdiction of Spacepol."
@@ -103,6 +132,16 @@
item_state = "det"
armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 30, "acid" = 30, "wound" = 10)
/obj/item/clothing/under/rank/security/detective/brown
name = "dark boiled suit"
icon_state = "detectivebrown"
item_state = "detectivebrown"
/obj/item/clothing/under/rank/security/detective/brown/brown2
name = "padded suit"
icon_state = "detectivebrown2"
item_state = "detectivebrown2"
/obj/item/clothing/under/rank/security/detective/skirt
name = "detective's suitskirt"
desc = "Someone who wears this means business."
@@ -202,4 +241,4 @@
desc = "Space not controlled by megacorporations, planets, or pirates is under the jurisdiction of Spacepol."
icon_state = "spacepol"
item_state = "spacepol"
can_adjust = FALSE
can_adjust = FALSE
+16
View File
@@ -116,3 +116,19 @@
/obj/item/clothing/under/suit/polychromic/ComponentInitialize()
. = ..()
AddElement(/datum/element/polychromic, list("#FFFFFF", "#FFFFFF", "#808080"), 3)
/obj/item/clothing/under/suit/turtle
desc = "a debatably stylish turtleneck."
can_adjust = FALSE
/obj/item/clothing/under/suit/turtle/teal
name = "teal turtleneck"
icon_state = "tealturtle"
item_state = "tealturtle"
can_adjust = FALSE
/obj/item/clothing/under/suit/turtle/grey
name = "grey turtleneck"
icon_state = "greyturtle"
item_state = "greyturtle"
can_adjust = FALSE
@@ -23,4 +23,4 @@
/datum/round_event/communications_blackout/start()
for(var/obj/machinery/telecomms/T in GLOB.telecomms_list)
T.emp_act(EMP_HEAVY)
T.emp_act(80)
+1 -1
View File
@@ -141,7 +141,7 @@
for(var/obj/machinery/rnd/server/S in GLOB.machines)
if(S.stat & (NOPOWER|BROKEN))
continue
S.emp_act(1)
S.emp_act(80)
new /obj/effect/temp_visual/emp(get_turf(S))
/obj/machinery/shuttle_scrambler/proc/dump_loot(mob/user)
+1 -1
View File
@@ -36,4 +36,4 @@
// at all
P.ex_act(EXPLODE_DEVASTATE)
else
P.emp_act(EMP_HEAVY)
P.emp_act(80)
@@ -22,6 +22,7 @@
endurance = 25
yield = 6
potency = 5
instability = 30
icon_dead = "ambrosia-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/ambrosia/deus)
+1
View File
@@ -8,6 +8,7 @@
product = /obj/item/reagent_containers/food/snacks/grown/banana
lifespan = 50
endurance = 30
instability = 10
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
icon_dead = "banana-dead"
genes = list(/datum/plant_gene/trait/slip, /datum/plant_gene/trait/repeated_harvest)
@@ -10,6 +10,7 @@
maturation = 5
production = 5
yield = 2
instability = 30
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
icon_grow = "berry-grow" // Uses one growth icons set for all the subtypes
icon_dead = "berry-dead" // Same for the dead icon
@@ -9,6 +9,7 @@
maturation = 8
potency = 20
growthstages = 1
instability = 40
growing_icon = 'goon/icons/obj/hydroponics.dmi'
icon_grow = "cannabis-grow" // Uses one growth icons set for all the subtypes
icon_dead = "cannabis-dead" // Same for the dead icon
@@ -9,6 +9,7 @@
production = 1
yield = 4
potency = 15
instability = 20
icon_dead = "wheat-dead"
mutatelist = list(/obj/item/seeds/wheat/oat, /obj/item/seeds/wheat/meat)
reagents_add = list(/datum/reagent/consumable/nutriment = 0.04)
+1
View File
@@ -11,6 +11,7 @@
production = 5
yield = 4
potency = 20
instability = 30
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
icon_grow = "chili-grow" // Uses one growth icons set for all the subtypes
icon_dead = "chili-dead" // Same for the dead icon
@@ -10,6 +10,7 @@
maturation = 5
production = 5
yield = 2
instability = 20
growthstages = 5
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
icon_grow = "cocoapod-grow"
+1
View File
@@ -8,6 +8,7 @@
product = /obj/item/reagent_containers/food/snacks/grown/corn
maturation = 8
potency = 20
instability = 50 // Corn used to be wheatgrass, but through generations of selective cultivation...
growthstages = 3
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
icon_grow = "corn-grow" // Uses one growth icons set for all the subtypes
+1
View File
@@ -12,6 +12,7 @@
production = 1
yield = 2
potency = 50
instability = 15
growthstages = 3
growing_icon = 'icons/obj/hydroponics/growing.dmi'
icon_dead = "cotton-dead"
@@ -11,6 +11,7 @@
maturation = 2
production = 5
yield = 5
instability = 10
growthstages = 2
icon_grow = "grass-grow"
icon_dead = "grass-dead"
+1
View File
@@ -11,6 +11,7 @@
lifespan = 20
endurance = 10
yield = 4
instability = 55
growthstages = 4
rarity = 30
var/list/mutations = list()
+2 -1
View File
@@ -8,6 +8,7 @@
product = /obj/item/reagent_containers/food/snacks/grown/watermelon
lifespan = 50
endurance = 40
instability = 20
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
icon_dead = "watermelon-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
@@ -75,4 +76,4 @@
to_chat(user, "<span class='warning'>[src] rapidly turns into ash!</span>")
qdel(src)
new /obj/effect/decal/cleanable/ash(drop_location())
*/
*/
+4 -1
View File
@@ -11,6 +11,7 @@
production = 1
yield = 6
potency = 10
instability = 35
growthstages = 3
grind_results = list(/datum/reagent/mustardgrind = 1)
growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi'
@@ -111,6 +112,7 @@
maturation = 3
production = 5
yield = 4
instability = 10
growthstages = 1
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
genes = list(/datum/plant_gene/trait/repeated_harvest)
@@ -140,6 +142,7 @@
endurance = 50
maturation = 3
yield = 4
instability = 15
growthstages = 2
reagents_add = list(/datum/reagent/consumable/sugar = 0.25)
mutatelist = list(/obj/item/seeds/bamboo)
@@ -534,4 +537,4 @@
/obj/item/reagent_containers/food/snacks/grown/aloe/microwave_act(obj/machinery/microwave/M)
new /obj/item/stack/medical/aloe(drop_location(), 2)
qdel(src)
qdel(src)
+5 -1
View File
@@ -18,6 +18,7 @@
production = 5
yield = 4
potency = 15
instability = 30
growthstages = 4
genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism)
growing_icon = 'icons/obj/hydroponics/growing_mushrooms.dmi'
@@ -43,6 +44,7 @@
maturation = 10
production = 5
yield = 4
instability = 30
growthstages = 3
genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism)
growing_icon = 'icons/obj/hydroponics/growing_mushrooms.dmi'
@@ -187,6 +189,7 @@
production = 1
yield = 5
potency = 15
instability = 20
growthstages = 3
genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism)
growing_icon = 'icons/obj/hydroponics/growing_mushrooms.dmi'
@@ -244,6 +247,7 @@
production = 1
yield = 3 //-> spread
potency = 30 //-> brightness
instability = 20
growthstages = 4
rarity = 20
genes = list(/datum/plant_gene/trait/glow, /datum/plant_gene/trait/plant_type/fungal_metabolism)
@@ -334,4 +338,4 @@
/obj/item/reagent_containers/food/snacks/grown/mushroom/glowshroom/shadowshroom/attack_self(mob/user)
. = ..()
if(.)
investigate_log("was planted by [key_name(user)] at [AREACOORD(user)]", INVESTIGATE_BOTANY)
investigate_log("was planted by [key_name(user)] at [AREACOORD(user)]", INVESTIGATE_BOTANY)
+1
View File
@@ -8,6 +8,7 @@
lifespan = 30
endurance = 40 // tuff like a toiger
yield = 4
instability = 25
growthstages = 5
genes = list(/datum/plant_gene/trait/repeated_harvest, /datum/plant_gene/trait/plant_type/weed_hardy)
mutatelist = list(/obj/item/seeds/nettle/death)
+1
View File
@@ -10,6 +10,7 @@
production = 4
yield = 6
endurance = 25
instability = 10
growthstages = 3
weed_chance = 3
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
+2
View File
@@ -8,6 +8,7 @@
product = /obj/item/reagent_containers/food/snacks/grown/peas
maturation = 3
potency = 25
instability = 15
growthstages = 3
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
icon_grow = "peas-grow"
@@ -79,6 +80,7 @@
potency = 75
yield = 1
production = 10
instability = 45 //The world is a very unstable place. Constantly changing.
growthstages = 3
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
icon_grow = "worldpeas-grow"
+2
View File
@@ -9,6 +9,7 @@
maturation = 10
production = 1
yield = 5
instability = 15
growthstages = 3
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
mutatelist = list(/obj/item/seeds/carrot/parsnip)
@@ -69,6 +70,7 @@
lifespan = 60
endurance = 50
yield = 6
instability = 10
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
icon_dead = "whitebeet-dead"
mutatelist = list(/obj/item/seeds/redbeet)
@@ -79,6 +79,7 @@
maturation = 5
production = 5
yield = 5
instability = 20
growthstages = 5
icon_dead = "coffee-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
+1
View File
@@ -6,6 +6,7 @@
species = "tomato"
plantname = "Tomato Plants"
product = /obj/item/reagent_containers/food/snacks/grown/tomato
instability = 25
maturation = 8
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
icon_grow = "tomato-grow"
+20 -1
View File
@@ -1,7 +1,7 @@
// Plant analyzer
/obj/item/plant_analyzer
name = "plant analyzer"
desc = "A scanner used to evaluate a plant's various areas of growth."
desc = "A scanner used to evaluate a plant's various areas of growth, and genetic traits."
icon = 'icons/obj/device.dmi'
icon_state = "hydro"
item_state = "analyzer"
@@ -10,6 +10,25 @@
w_class = WEIGHT_CLASS_TINY
slot_flags = ITEM_SLOT_BELT
custom_materials = list(/datum/material/iron=30, /datum/material/glass=20)
var/scan_mode = PLANT_SCANMODE_STATS
/obj/item/plant_analyzer/attack_self(mob/user)
. = ..()
scan_mode = !scan_mode
to_chat(user, "<span class='notice'>You switch [src] to [scan_mode == PLANT_SCANMODE_CHEMICALS ? "scan for chemical reagents and traits" : "scan for plant growth statistics"].</span>")
/obj/item/plant_analyzer/attack(mob/living/M, mob/living/carbon/human/user)
//Checks if target is a podman
if(ispodperson(M))
user.visible_message("<span class='notice'>[user] analyzes [M]'s vitals.</span>", \
"<span class='notice'>You analyze [M]'s vitals.</span>")
if(scan_mode== PLANT_SCANMODE_STATS)
healthscan(user, M, advanced = TRUE)
else
chemscan(user, M)
add_fingerprint(user)
return
return ..()
// *************************************
// Hydroponics Tools
+160 -427
View File
@@ -6,9 +6,10 @@
pixel_z = 8
obj_flags = CAN_BE_HIT | UNIQUE_RENAME
circuit = /obj/item/circuitboard/machine/hydroponics
idle_power_usage = 0
var/waterlevel = 100 //The amount of water in the tray (max 100)
var/maxwater = 100 //The maximum amount of water in the tray
var/nutrilevel = 10 //The amount of nutrient in the tray (max 10)
var/nutridrain = 1 // How many units of nutrient will be drained in the tray
var/maxnutri = 10 //The maximum nutrient of water in the tray
var/pestlevel = 0 //The amount of pests in the tray (max 10)
var/weedlevel = 0 //The amount of weeds in the tray (max 10)
@@ -16,21 +17,25 @@
var/mutmod = 1 //Nutriment's effect on mutations
var/toxic = 0 //Toxicity in the tray?
var/age = 0 //Current age
var/dead = 0 //Is it dead?
var/dead = FALSE //Is it dead?
var/plant_health //Its health
var/lastproduce = 0 //Last time it was harvested
var/lastcycle = 0 //Used for timing of cycles.
var/cycledelay = 200 //About 10 seconds / cycle
var/harvest = 0 //Ready to harvest?
var/harvest = FALSE //Ready to harvest?
var/obj/item/seeds/myseed = null //The currently planted seed
var/rating = 1
var/unwrenchable = 1
var/unwrenchable = TRUE
var/recent_bee_visit = FALSE //Have we been visited by a bee recently, so bees dont overpollinate one plant
var/using_irrigation = FALSE //If the tray is connected to other trays via irrigation hoses
var/self_sufficiency_req = 20 //Required total dose to make a self-sufficient hydro tray. 1:1 with earthsblood.
var/self_sufficiency_progress = 0
var/mob/lastuser //Last user to add reagents to a tray. Mostly for logging.
var/self_sustaining = FALSE //If the tray generates nutrients and water on its own
var/canirrigate = TRUE //tin
// Here lies irrigation. You won't be missed, because you were never used.
/obj/machinery/hydroponics/Initialize()
//Here lies "nutrilevel", killed by ArcaneMusic 20??-2019. Finally, we strive for a better future. Please use "reagents" instead
create_reagents(20)
reagents.add_reagent(/datum/reagent/plantnutriment/eznutriment, 10) //Half filled nutrient trays for dirt trays to have more to grow with in prison/lavaland.
. = ..()
/obj/machinery/hydroponics/constructable
name = "hydroponics tray"
@@ -43,14 +48,18 @@
tmp_capacity += M.rating
for (var/obj/item/stock_parts/manipulator/M in component_parts)
rating = M.rating
maxwater = tmp_capacity * 50 // Up to 300
maxnutri = tmp_capacity * 5 // Up to 30
maxwater = tmp_capacity * 50 // Up to 400
maxnutri = (tmp_capacity * 5) + STATIC_NUTRIENT_CAPACITY // Up to 50 Maximum
reagents.maximum_volume = maxnutri
nutridrain = 1/rating
/obj/machinery/hydroponics/constructable/examine(mob/user)
. = ..()
. += "<span class='notice'>Use <b>Ctrl-Click</b> to activate autogrow. <b>Alt-Click</b> to empty the tray's nutrients.</span>"
if(in_range(user, src) || isobserver(user))
. += "<span class='notice'>The status display reads: Tray efficiency at <b>[rating*100]%</b>.</span>"
/obj/machinery/hydroponics/Destroy()
if(myseed)
qdel(myseed)
@@ -62,34 +71,11 @@
// handle opening the panel
if(default_deconstruction_screwdriver(user, icon_state, icon_state, I))
return
// handle deconstructing the machine, if permissible
if (I.tool_behaviour == TOOL_CROWBAR && using_irrigation)
to_chat(user, "<span class='warning'>Disconnect the hoses first!</span>")
return
else if(default_deconstruction_crowbar(I))
if(default_deconstruction_crowbar(I))
return
return ..()
/obj/machinery/hydroponics/proc/FindConnected()
var/list/connected = list()
var/list/processing_atoms = list(src)
while(processing_atoms.len)
var/atom/a = processing_atoms[1]
for(var/step_dir in GLOB.cardinals)
var/obj/machinery/hydroponics/h = locate() in get_step(a, step_dir)
// Soil plots aren't dense
if(h && h.using_irrigation && h.density && !(h in connected) && !(h in processing_atoms))
processing_atoms += h
processing_atoms -= a
connected += a
return connected
/obj/machinery/hydroponics/bullet_act(obj/item/projectile/Proj) //Works with the Somatoray to modify plant variables.
if(!myseed)
return ..()
@@ -107,12 +93,16 @@
if(myseed && (myseed.loc != src))
myseed.forceMove(src)
if(self_sustaining)
adjustNutri(1)
adjustWater(rand(3,5))
adjustWeeds(-2)
adjustPests(-2)
adjustToxic(-2)
if(!powered() && self_sustaining)
visible_message("<span class='warning'>[name]'s auto-grow functionality shuts off!</span>")
idle_power_usage = 0
self_sustaining = FALSE
update_icon()
else if(self_sustaining)
adjustWater(rand(1,2))
adjustWeeds(-1)
adjustPests(-1)
if(world.time > (lastcycle + cycledelay))
lastcycle = world.time
@@ -124,13 +114,17 @@
needs_update = 1
//Nutrients//////////////////////////////////////////////////////////////
// Nutrients deplete slowly
if(prob(50))
adjustNutri(-1 / rating)
//Nutrients//////////////////////////////////////////////////////////////
// Nutrients deplete at a constant rate, since new nutrients can boost stats far easier.
apply_chemicals(lastuser)
if(self_sustaining)
reagents.remove_any(min(0.5, nutridrain))
else
reagents.remove_any(nutridrain)
// Lack of nutrients hurts non-weeds
if(nutrilevel <= 0 && !myseed.get_gene(/datum/plant_gene/trait/plant_type/weed_hardy))
if(reagents.total_volume <= 0 && !myseed.get_gene(/datum/plant_gene/trait/plant_type/weed_hardy))
adjustHealth(-rand(1,3))
//Photosynthesis/////////////////////////////////////////////////////////
@@ -156,7 +150,7 @@
adjustHealth(-rand(0,2) / rating)
// Sufficient water level and nutrient level = plant healthy but also spawns weeds
else if(waterlevel > 10 && nutrilevel > 0)
else if(waterlevel > 10 && reagents.total_volume > 0)
adjustHealth(rand(1,2) / rating)
if(myseed && prob(myseed.weed_chance))
adjustWeeds(myseed.weed_rate)
@@ -201,6 +195,21 @@
if(weedlevel >= 5 && !myseed.get_gene(/datum/plant_gene/trait/plant_type/weed_hardy))
adjustHealth(-1 / rating)
//This is where stability mutations exist now.
if(myseed.instability >= 80)
var/mutation_chance = myseed.instability - 75
mutate(0, 0, 0, 0, 0, 0, 0, mutation_chance, 0) //Scaling odds of a random trait or chemical
if(myseed.instability >= 60)
if(prob((myseed.instability)/2) && !self_sustaining && length(myseed.mutatelist)) //Minimum 30%, Maximum 50% chance of mutating every age tick when not on autogrow.
mutatespecie()
myseed.instability = myseed.instability/2
if(myseed.instability >= 40)
if(prob(myseed.instability))
hardmutate()
if(myseed.instability >= 20 )
if(prob(myseed.instability))
mutate()
//Health & Age///////////////////////////////////////////////////////////
// Plant dies if plant_health <= 0
@@ -214,15 +223,14 @@
// Harvest code
if(age > myseed.production && (age - lastproduce) > myseed.production && (!harvest && !dead))
nutrimentMutation()
if(myseed && myseed.yield != -1) // Unharvestable shouldn't be harvested
harvest = 1
harvest = TRUE
else
lastproduce = age
if(prob(5)) // On each tick, there's a 5 percent chance the pest population will increase
adjustPests(1 / rating)
else
if(waterlevel > 10 && nutrilevel > 0 && prob(10)) // If there's no plant, the percentage chance is 10%
if(waterlevel > 10 && reagents.total_volume > 0 && prob(10)) // If there's no plant, the percentage chance is 10%
adjustWeeds(1 / rating)
// Weeeeeeeeeeeeeeedddssss
@@ -243,25 +251,6 @@
selectedtrait.on_grow(src)
return
/obj/machinery/hydroponics/proc/nutrimentMutation()
if (mutmod == 0)
return
if (mutmod == 1)
if(prob(80)) //80%
mutate()
else if(prob(75)) //15%
hardmutate()
return
if (mutmod == 2)
if(prob(50)) //50%
mutate()
else if(prob(50)) //25%
hardmutate()
else if(prob(50)) //12.5%
mutatespecie()
return
return
/obj/machinery/hydroponics/update_icon()
//Refreshes the icon and sets the luminosity
cut_overlays()
@@ -273,8 +262,6 @@
add_overlay(mutable_appearance('icons/obj/hydroponics/equipment.dmi', "gaia_blessing"))
set_light(3)
update_icon_hoses()
if(myseed)
update_icon_plant()
update_icon_lights()
@@ -288,15 +275,6 @@
return
/obj/machinery/hydroponics/proc/update_icon_hoses()
var/n = 0
for(var/Dir in GLOB.cardinals)
var/obj/machinery/hydroponics/t = locate() in get_step(src,Dir)
if(t && t.using_irrigation && using_irrigation)
n += Dir
icon_state = "hoses-[n]"
/obj/machinery/hydroponics/proc/update_icon_plant()
var/mutable_appearance/plant_overlay = mutable_appearance(myseed.growing_icon, layer = OBJ_LAYER + 0.01)
if(dead)
@@ -314,7 +292,7 @@
/obj/machinery/hydroponics/proc/update_icon_lights()
if(waterlevel <= 10)
add_overlay(mutable_appearance('icons/obj/hydroponics/equipment.dmi', "over_lowwater3"))
if(nutrilevel <= 2)
if(reagents.total_volume <= 2)
add_overlay(mutable_appearance('icons/obj/hydroponics/equipment.dmi', "over_lownutri3"))
if(plant_health <= (myseed.endurance / 2))
add_overlay(mutable_appearance('icons/obj/hydroponics/equipment.dmi', "over_lowhealth3"))
@@ -337,19 +315,17 @@
else
. += "<span class='info'>It's empty.</span>"
if(!self_sustaining)
. += "<span class='info'>Water: [waterlevel]/[maxwater].</span>"
. += "<span class='info'>Nutrient: [nutrilevel]/[maxnutri].</span>"
if(self_sufficiency_progress > 0)
var/percent_progress = round(self_sufficiency_progress * 100 / self_sufficiency_req)
. += "<span class='info'>Treatment for self-sustenance are [percent_progress]% complete.</span>"
else
. += "<span class='info'>It doesn't require any water or nutrients.</span>"
. += "<span class='info'>Water: [waterlevel]/[maxwater].</span>\n"+\
"<span class='info'>Nutrient: [reagents.total_volume]/[maxnutri].</span>"
if(self_sustaining)
. += "<span class='info'>The tray's autogrow is active, halving active reagent drain, and actively maintaning the plant.</span>"
if(weedlevel >= 5)
. += "<span class='warning'>It's filled with weeds!</span>"
to_chat(user, "<span class='warning'>It's filled with weeds!</span>")
if(pestlevel >= 5)
. += "<span class='warning'>It's filled with tiny worms!</span>"
to_chat(user, "<span class='warning'>It's filled with tiny worms!</span>")
to_chat(user, "" )
/obj/machinery/hydroponics/proc/weedinvasion() // If a weed growth is sufficient, this happens.
@@ -424,11 +400,7 @@
sleep(5) // Wait a while
update_icon()
visible_message("<span class='warning'>[oldPlantName] suddenly mutates into [myseed.plantname]!</span>")
name = "hydroponics tray ([myseed.plantname])"
if(myseed.product)
desc = initial(myseed.product.desc)
else
desc = initial(desc)
TRAY_NAME_UPDATE
/obj/machinery/hydroponics/proc/mutateweed() // If the weeds gets the mutagent instead. Mind you, this pretty much destroys the old plant
if( weedlevel > 5 )
@@ -448,18 +420,23 @@
sleep(5) // Wait a while
update_icon()
visible_message("<span class='warning'>The mutated weeds in [src] spawn some [myseed.plantname]!</span>")
TRAY_NAME_UPDATE
else
to_chat(usr, "<span class='warning'>The few weeds in [src] seem to react, but only for a moment...</span>")
/obj/machinery/hydroponics/proc/plantdies() // OH NOES!!!!! I put this all in one function to make things easier
/**
* Plant Death Proc.
* Cleans up various stats for the plant upon death, including pests, harvestability, and plant health.
*/
/obj/machinery/hydroponics/proc/plantdies()
plant_health = 0
harvest = 0
harvest = FALSE
pestlevel = 0 // Pests die
lastproduce = 0
if(!dead)
update_icon()
dead = 1
dead = TRUE
/obj/machinery/hydroponics/proc/mutatepest(mob/user)
@@ -471,250 +448,6 @@
else
to_chat(user, "<span class='warning'>The pests seem to behave oddly, but quickly settle down...</span>")
/obj/machinery/hydroponics/proc/applyChemicals(datum/reagents/S, mob/user)
if(myseed)
myseed.on_chem_reaction(S) //In case seeds have some special interactions with special chems, currently only used by vines
// Requires 5 mutagen to possibly change species.// Poor man's mutagen.
if(S.has_reagent(/datum/reagent/toxin/mutagen, 5) || S.has_reagent(/datum/reagent/radium, 10) || S.has_reagent(/datum/reagent/uranium, 10))
switch(rand(100))
if(91 to 100)
adjustHealth(-10)
to_chat(user, "<span class='warning'>The plant shrivels and burns.</span>")
if(81 to 90)
mutatespecie()
if(66 to 80)
hardmutate()
if(41 to 65)
mutate()
if(21 to 41)
to_chat(user, "<span class='notice'>The plants don't seem to react...</span>")
if(11 to 20)
mutateweed()
if(1 to 10)
mutatepest(user)
else
to_chat(user, "<span class='notice'>Nothing happens...</span>")
// 2 or 1 units is enough to change the yield and other stats.// Can change the yield and other stats, but requires more than mutagen
else if(S.has_reagent(/datum/reagent/toxin/mutagen, 2) || S.has_reagent(/datum/reagent/radium, 5) || S.has_reagent(/datum/reagent/uranium, 5))
hardmutate()
else if(S.has_reagent(/datum/reagent/toxin/mutagen, 1) || S.has_reagent(/datum/reagent/radium, 2) || S.has_reagent(/datum/reagent/uranium, 2))
mutate()
// After handling the mutating, we now handle the damage from adding crude radioactives...
if(S.has_reagent(/datum/reagent/uranium, 1))
adjustHealth(-round(S.get_reagent_amount(/datum/reagent/uranium) * 1))
adjustToxic(round(S.get_reagent_amount(/datum/reagent/uranium) * 2))
if(S.has_reagent(/datum/reagent/radium, 1))
adjustHealth(-round(S.get_reagent_amount(/datum/reagent/radium) * 1))
adjustToxic(round(S.get_reagent_amount(/datum/reagent/radium) * 3)) // Radium is harsher (OOC: also easier to produce)
// Nutriments
if(S.has_reagent(/datum/reagent/plantnutriment/eznutriment, 1))
yieldmod = 1
mutmod = 1
adjustNutri(round(S.get_reagent_amount(/datum/reagent/plantnutriment/eznutriment) * 1))
if(S.has_reagent(/datum/reagent/plantnutriment/left4zednutriment, 1))
yieldmod = 0
mutmod = 2
adjustNutri(round(S.get_reagent_amount(/datum/reagent/plantnutriment/left4zednutriment) * 1))
if(S.has_reagent(/datum/reagent/plantnutriment/robustharvestnutriment, 1))
yieldmod = 1.3
mutmod = 0
adjustNutri(round(S.get_reagent_amount(/datum/reagent/plantnutriment/robustharvestnutriment) *1 ))
// Ambrosia Gaia produces earthsblood.
if(S.has_reagent(/datum/reagent/medicine/earthsblood))
self_sufficiency_progress += S.get_reagent_amount(/datum/reagent/medicine/earthsblood)
if(self_sufficiency_progress >= self_sufficiency_req)
become_self_sufficient()
else if(!self_sustaining)
to_chat(user, "<span class='notice'>[src] warms as it might on a spring day under a genuine Sun.</span>")
// Antitoxin binds shit pretty well. So the tox goes significantly down
if(S.has_reagent(/datum/reagent/medicine/charcoal, 1))
adjustToxic(-round(S.get_reagent_amount(/datum/reagent/medicine/charcoal) * 2))
// Toxins, not good for anything
if(S.has_reagent(/datum/reagent/toxin, 1))
adjustToxic(round(S.get_reagent_amount(/datum/reagent/toxin) * 2))
// Milk is good for humans, but bad for plants. The sugars canot be used by plants, and the milk fat fucks up growth. Not shrooms though. I can't deal with this now...
if(S.has_reagent(/datum/reagent/consumable/milk, 1))
adjustNutri(round(S.get_reagent_amount(/datum/reagent/consumable/milk) * 0.1))
adjustWater(round(S.get_reagent_amount(/datum/reagent/consumable/milk) * 0.9))
// Beer is a chemical composition of alcohol and various other things. It's a shitty nutrient but hey, it's still one. Also alcohol is bad, mmmkay?
if(S.has_reagent(/datum/reagent/consumable/ethanol/beer, 1))
adjustHealth(-round(S.get_reagent_amount(/datum/reagent/consumable/ethanol/beer) * 0.05))
adjustNutri(round(S.get_reagent_amount(/datum/reagent/consumable/ethanol/beer) * 0.25))
adjustWater(round(S.get_reagent_amount(/datum/reagent/consumable/ethanol/beer) * 0.7))
// Fluorine one of the most corrosive and deadly gasses
if(S.has_reagent(/datum/reagent/fluorine, 1))
adjustHealth(-round(S.get_reagent_amount(/datum/reagent/fluorine) * 2))
adjustToxic(round(S.get_reagent_amount(/datum/reagent/fluorine) * 2.5))
adjustWater(-round(S.get_reagent_amount(/datum/reagent/fluorine) * 0.5))
adjustWeeds(-rand(1,4))
// Chlorine one of the most corrosive and deadly gasses
if(S.has_reagent(/datum/reagent/chlorine, 1))
adjustHealth(-round(S.get_reagent_amount(/datum/reagent/chlorine) * 1))
adjustToxic(round(S.get_reagent_amount(/datum/reagent/chlorine) * 1.5))
adjustWater(-round(S.get_reagent_amount(/datum/reagent/chlorine) * 0.5))
adjustWeeds(-rand(1,3))
// White Phosphorous + water -> phosphoric acid. That's not a good thing really.
// Phosphoric salts are beneficial though. And even if the plant suffers, in the long run the tray gets some nutrients. The benefit isn't worth that much.
if(S.has_reagent(/datum/reagent/phosphorus, 1))
adjustHealth(-round(S.get_reagent_amount(/datum/reagent/phosphorus) * 0.75))
adjustNutri(round(S.get_reagent_amount(/datum/reagent/phosphorus) * 0.1))
adjustWater(-round(S.get_reagent_amount(/datum/reagent/phosphorus) * 0.5))
adjustWeeds(-rand(1,2))
// Plants should not have sugar, they can't use it and it prevents them getting water/nutients, it is good for mold though...
if(S.has_reagent(/datum/reagent/consumable/sugar, 1))
adjustWeeds(rand(1,2))
adjustPests(rand(1,2))
adjustNutri(round(S.get_reagent_amount(/datum/reagent/consumable/sugar) * 0.1))
// It is water!
if(S.has_reagent(/datum/reagent/water, 1))
adjustWater(round(S.get_reagent_amount(/datum/reagent/water) * 1))
// Holy water. Mostly the same as water, it also heals the plant a little with the power of the spirits~
if(S.has_reagent(/datum/reagent/water/holywater, 1))
adjustWater(round(S.get_reagent_amount(/datum/reagent/water/holywater) * 1))
adjustHealth(round(S.get_reagent_amount(/datum/reagent/water/holywater) * 0.1))
// A variety of nutrients are dissolved in club soda, without sugar.
// These nutrients include carbon, oxygen, hydrogen, phosphorous, potassium, sulfur and sodium, all of which are needed for healthy plant growth.
if(S.has_reagent(/datum/reagent/consumable/sodawater, 1))
adjustWater(round(S.get_reagent_amount(/datum/reagent/consumable/sodawater) * 1))
adjustHealth(round(S.get_reagent_amount(/datum/reagent/consumable/sodawater) * 0.1))
adjustNutri(round(S.get_reagent_amount(/datum/reagent/consumable/sodawater) * 0.1))
// Sulphuric Acid
if(S.has_reagent(/datum/reagent/toxin/acid, 1))
adjustHealth(-round(S.get_reagent_amount(/datum/reagent/toxin/acid) * 1))
adjustToxic(round(S.get_reagent_amount(/datum/reagent/toxin/acid) * 1.5))
adjustWeeds(-rand(1,2))
// Acid
if(S.has_reagent(/datum/reagent/toxin/acid/fluacid, 1))
adjustHealth(-round(S.get_reagent_amount(/datum/reagent/toxin/acid/fluacid) * 2))
adjustToxic(round(S.get_reagent_amount(/datum/reagent/toxin/acid/fluacid) * 3))
adjustWeeds(-rand(1,4))
// Plant-B-Gone is just as bad
if(S.has_reagent(/datum/reagent/toxin/plantbgone, 1))
adjustHealth(-round(S.get_reagent_amount(/datum/reagent/toxin/plantbgone) * 5))
adjustToxic(round(S.get_reagent_amount(/datum/reagent/toxin/plantbgone) * 6))
adjustWeeds(-rand(4,8))
// Napalm, not known for being good for anything organic
if(S.has_reagent(/datum/reagent/napalm, 1))
if(!(myseed.resistance_flags & FIRE_PROOF))
adjustHealth(-round(S.get_reagent_amount(/datum/reagent/napalm) * 6))
adjustToxic(round(S.get_reagent_amount(/datum/reagent/napalm) * 7))
adjustWeeds(-rand(5,9))
//Weed Spray
if(S.has_reagent(/datum/reagent/toxin/plantbgone/weedkiller, 1))
adjustToxic(round(S.get_reagent_amount(/datum/reagent/toxin/plantbgone/weedkiller) * 0.5))
//old toxicity was 4, each spray is default 10 (minimal of 5) so 5 and 2.5 are the new ammounts
adjustWeeds(-rand(1,2))
//Pest Spray
if(S.has_reagent(/datum/reagent/toxin/pestkiller, 1))
adjustToxic(round(S.get_reagent_amount(/datum/reagent/toxin/pestkiller) * 0.5))
adjustPests(-rand(1,2))
// Healing
if(S.has_reagent(/datum/reagent/medicine/cryoxadone, 1))
adjustHealth(round(S.get_reagent_amount(/datum/reagent/medicine/cryoxadone) * 3))
adjustToxic(-round(S.get_reagent_amount(/datum/reagent/medicine/cryoxadone) * 3))
// Ammonia is bad ass.
if(S.has_reagent(/datum/reagent/ammonia, 1))
adjustHealth(round(S.get_reagent_amount(/datum/reagent/ammonia) * 0.5))
adjustNutri(round(S.get_reagent_amount(/datum/reagent/ammonia) * 1))
if(myseed)
myseed.adjust_yield(round(S.get_reagent_amount(/datum/reagent/ammonia) * 0.01))
// Saltpetre is used for gardening IRL, to simplify highly, it speeds up growth and strengthens plants
if(S.has_reagent(/datum/reagent/saltpetre, 1))
var/salt = S.get_reagent_amount(/datum/reagent/saltpetre)
adjustHealth(round(salt * 0.25))
if (myseed)
myseed.adjust_production(-round(salt/100)-prob(salt%100))
myseed.adjust_potency(round(salt*0.5))
// Ash is also used IRL in gardening, as a fertilizer enhancer and weed killer
if(S.has_reagent(/datum/reagent/ash, 1))
adjustHealth(round(S.get_reagent_amount(/datum/reagent/ash) * 0.25))
adjustNutri(round(S.get_reagent_amount(/datum/reagent/ash) * 0.5))
adjustWeeds(-1)
// Diethylamine is more bad ass, and pests get hurt by the corrosive nature of it, not the plant.
if(S.has_reagent(/datum/reagent/diethylamine, 1))
adjustHealth(round(S.get_reagent_amount(/datum/reagent/diethylamine) * 1))
adjustNutri(round(S.get_reagent_amount(/datum/reagent/diethylamine) * 2))
if(myseed)
myseed.adjust_yield(round(S.get_reagent_amount(/datum/reagent/diethylamine) * 0.02))
adjustPests(-rand(1,2))
// Nutriment Compost, effectively
if(S.has_reagent(/datum/reagent/consumable/nutriment, 1))
adjustHealth(round(S.get_reagent_amount(/datum/reagent/consumable/nutriment) * 0.5))
adjustNutri(round(S.get_reagent_amount(/datum/reagent/consumable/nutriment) * 1))
// Virusfood Compost for EVERYTHING
if(S.has_reagent(/datum/reagent/toxin/mutagen/mutagenvirusfood, 1))
adjustNutri(round(S.get_reagent_amount(/datum/reagent/toxin/mutagen/mutagenvirusfood) * 0.5))
adjustHealth(-round(S.get_reagent_amount(/datum/reagent/toxin/mutagen/mutagenvirusfood) * 0.5))
// Blood
if(S.has_reagent(/datum/reagent/blood, 1))
adjustNutri(round(S.get_reagent_amount(/datum/reagent/blood) * 1))
adjustPests(rand(2,4))
// Strange reagent
if(S.has_reagent(/datum/reagent/medicine/strange_reagent, 1))
spawnplant()
// Honey, Pests are dieing of sugar, so is the plant
if(S.has_reagent(/datum/reagent/consumable/honey, 1))
adjustPests(-rand(2,5))
adjustHealth(-round(S.get_reagent_amount(/datum/reagent/consumable/honey) * 1))
// Buzz Fuzz, a drink seemingly made for plants...
if(S.has_reagent(/datum/reagent/consumable/buzz_fuzz, 1))
adjustPests(-rand(2,5))
adjustHealth(round(S.get_reagent_amount(/datum/reagent/consumable/buzz_fuzz) * 0.1))
adjustNutri(round(S.get_reagent_amount(/datum/reagent/consumable/buzz_fuzz) * 0.5))
// Adminordrazine the best stuff there is. For testing/debugging.
if(S.has_reagent(/datum/reagent/medicine/adminordrazine, 1))
adjustWater(round(S.get_reagent_amount(/datum/reagent/medicine/adminordrazine) * 1))
adjustHealth(round(S.get_reagent_amount(/datum/reagent/medicine/adminordrazine) * 1))
adjustNutri(round(S.get_reagent_amount(/datum/reagent/medicine/adminordrazine) * 1))
adjustPests(-rand(1,5))
adjustWeeds(-rand(1,5))
if(S.has_reagent(/datum/reagent/medicine/adminordrazine, 5))
switch(rand(100))
if(66 to 100)
mutatespecie()
if(33 to 65)
mutateweed()
if(1 to 32)
mutatepest(user)
else
to_chat(user, "<span class='warning'>Nothing happens...</span>")
/obj/machinery/hydroponics/attackby(obj/item/O, mob/user, params)
//Called when mob user "attacks" it with object O
if(istype(O, /obj/item/reagent_containers) ) // Syringe stuff (and other reagent containers now too)
@@ -730,13 +463,20 @@
to_chat(user, "<span class='notice'>[reagent_source] is empty.</span>")
return 1
if(reagents.total_volume >= reagents.maximum_volume && !reagent_source.reagents.has_reagent(/datum/reagent/water, 1))
to_chat(user, "<span class='notice'>[src] is full.</span>")
return
var/list/trays = list(src)//makes the list just this in cases of syringes and compost etc
var/target = myseed ? myseed.plantname : src
var/visi_msg = ""
var/irrigate = 0 //How am I supposed to irrigate pill contents?
var/transfer_amount
if(istype(reagent_source, /obj/item/reagent_containers/food/snacks) || istype(reagent_source, /obj/item/reagent_containers/pill))
if(istype(reagent_source, /obj/item/reagent_containers/food/snacks))
var/obj/item/reagent_containers/food/snacks/R = reagent_source
if (R.trash)
R.generate_trash(get_turf(user))
visi_msg="[user] composts [reagent_source], spreading it through [target]"
transfer_amount = reagent_source.reagents.total_volume
else
@@ -746,41 +486,27 @@
visi_msg="[user] injects [target] with [syr]"
if(syr.reagents.total_volume <= syr.amount_per_transfer_from_this)
syr.mode = 0
else if(istype(reagent_source, /obj/item/reagent_containers/spray/))
visi_msg="[user] sprays [target] with [reagent_source]"
playsound(loc, 'sound/effects/spray3.ogg', 50, 1, -6)
irrigate = 1
else if(transfer_amount) // Droppers, cans, beakers, what have you.
visi_msg="[user] uses [reagent_source] on [target]"
irrigate = 1
// Beakers, bottles, buckets, etc.
if(reagent_source.is_drainable())
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
if(irrigate && transfer_amount > 30 && reagent_source.reagents.total_volume >= 30 && using_irrigation)
trays = FindConnected()
if (trays.len > 1)
visi_msg += ", setting off the irrigation system"
playsound(loc, 'sound/effects/slosh.ogg', 25, TRUE)
if(visi_msg)
visible_message("<span class='notice'>[visi_msg].</span>")
var/split = round(transfer_amount/trays.len)
for(var/obj/machinery/hydroponics/H in trays)
//cause I don't want to feel like im juggling 15 tamagotchis and I can get to my real work of ripping flooring apart in hopes of validating my life choices of becoming a space-gardener
var/datum/reagents/S = new /datum/reagents() //This is a strange way, but I don't know of a better one so I can't fix it at the moment...
S.my_atom = H
reagent_source.reagents.trans_to(S,split)
//This was originally in apply_chemicals, but due to apply_chemicals only holding nutrients, we handle it here now.
if(reagent_source.reagents.has_reagent(/datum/reagent/water, 1))
var/water_amt = reagent_source.reagents.get_reagent_amount(/datum/reagent/water) * transfer_amount / reagent_source.reagents.total_volume
H.adjustWater(round(water_amt))
reagent_source.reagents.remove_reagent(/datum/reagent/water, water_amt)
reagent_source.reagents.trans_to(H.reagents, transfer_amount)
if(istype(reagent_source, /obj/item/reagent_containers/food/snacks) || istype(reagent_source, /obj/item/reagent_containers/pill))
qdel(reagent_source)
H.applyChemicals(S, user)
S.clear_reagents()
qdel(S)
lastuser = user
H.update_icon()
return 1
H.update_icon()
if(reagent_source) // If the source wasn't composted and destroyed
reagent_source.update_icon()
@@ -793,39 +519,43 @@
if(!user.transferItemToLoc(O, src))
return
to_chat(user, "<span class='notice'>You plant [O].</span>")
dead = 0
dead = FALSE
myseed = O
name = "hydroponics tray ([myseed.plantname])"
if(!myseed.productdesc) //we haven't changed our produce's description
if(myseed.product)
myseed.productdesc = initial(myseed.product.desc)
else if(myseed.desc)
myseed.productdesc = myseed.desc
else
myseed.productdesc = "A fascinating specimen."
desc = myseed.productdesc
TRAY_NAME_UPDATE
age = 1
plant_health = myseed.endurance
lastcycle = world.time
update_icon()
return
else
to_chat(user, "<span class='warning'>[src] already has seeds in it!</span>")
return
else if(istype(O, /obj/item/plant_analyzer))
var/obj/item/plant_analyzer/P_analyzer = O
if(myseed)
to_chat(user, "*** <B>[myseed.plantname]</B> ***" )
to_chat(user, "- Plant Age: <span class='notice'>[age]</span>")
var/list/text_string = myseed.get_analyzer_text()
if(text_string)
to_chat(user, text_string)
if(P_analyzer.scan_mode == PLANT_SCANMODE_STATS)
to_chat(user, "*** <B>[myseed.plantname]</B> ***" )
to_chat(user, "- Plant Age: <span class='notice'>[age]</span>")
var/list/text_string = myseed.get_analyzer_text()
if(text_string)
to_chat(user, text_string)
to_chat(user, "*---------*")
if(myseed.reagents_add && P_analyzer.scan_mode == PLANT_SCANMODE_CHEMICALS)
to_chat(user, "- <B>Plant Reagents</B> -")
to_chat(user, "*---------*")
for(var/datum/plant_gene/reagent/G in myseed.genes)
to_chat(user, "<span class='notice'>- [G.get_name()] -</span>")
to_chat(user, "*---------*")
else
to_chat(user, "<B>No plant found.</B>")
to_chat(user, "- Weed level: <span class='notice'>[weedlevel] / 10</span>")
to_chat(user, "- Pest level: <span class='notice'>[pestlevel] / 10</span>")
to_chat(user, "- Toxicity level: <span class='notice'>[toxic] / 100</span>")
to_chat(user, "- Water level: <span class='notice'>[waterlevel] / [maxwater]</span>")
to_chat(user, "- Nutrition level: <span class='notice'>[nutrilevel] / [maxnutri]</span>")
to_chat(user, "- Nutrition level: <span class='notice'>[reagents.total_volume] / [maxnutri]</span>")
to_chat(user, "")
return
else if(istype(O, /obj/item/cultivator))
if(weedlevel > 0)
@@ -843,18 +573,6 @@
else if(default_unfasten_wrench(user, O))
return
else if(istype(O, /obj/item/wirecutters) && unwrenchable)
if (!anchored)
to_chat(user, "<span class='warning'>Anchor the tray first!</span>")
return
if(canirrigate)
using_irrigation = !using_irrigation
O.play_tool_sound(src)
user.visible_message("<span class='notice'>[user] [using_irrigation ? "" : "dis"]connects [src]'s irrigation hoses.</span>", \
"<span class='notice'>You [using_irrigation ? "" : "dis"]connect [src]'s irrigation hoses.</span>")
for(var/obj/machinery/hydroponics/h in range(1,src))
h.update_icon()
else if(istype(O, /obj/item/shovel/spade))
if(!myseed && !weedlevel)
to_chat(user, "<span class='warning'>[src] doesn't have any plants or weeds!</span>")
@@ -882,55 +600,75 @@
if (!unwrenchable) // case also covered by NODECONSTRUCT checks in default_unfasten_wrench
return CANT_UNFASTEN
if (using_irrigation)
if (!silent)
to_chat(user, "<span class='warning'>Disconnect the hoses first!</span>")
return FAILED_UNFASTEN
return ..()
/obj/machinery/hydroponics/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
/obj/machinery/hydroponics/attack_hand(mob/user)
. = ..()
if(.)
return
if(issilicon(user)) //How does AI know what plant is?
return
if(harvest)
return myseed.harvest(user)
myseed.harvest(user)
return
else if(dead)
dead = 0
dead = FALSE
to_chat(user, "<span class='notice'>You remove the dead plant from [src].</span>")
qdel(myseed)
myseed = null
update_icon()
name = initial(name)
desc = initial(desc)
TRAY_NAME_UPDATE
else
if(user)
examine(user)
/obj/machinery/hydroponics/CtrlClick(mob/user)
. = ..()
if(!user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
if(!powered())
to_chat(user, "<span class='warning'>[name] has no power.</span>")
return
if(!anchored)
return
self_sustaining = !self_sustaining
idle_power_usage = self_sustaining ? 2500 : 0
to_chat(user, "<span class='notice'>You [self_sustaining ? "activate" : "deactivated"] [src]'s autogrow function[self_sustaining ? ", maintaining the tray's health while using high amounts of power" : ""].")
update_icon()
/obj/machinery/hydroponics/AltClick(mob/user)
. = ..()
if(!anchored)
update_icon()
return FALSE
var/warning = alert(user, "Are you sure you wish to empty the tray's nutrient beaker?","Empty Tray Nutrients?", "Yes", "No")
if(warning == "Yes" && user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
reagents.clear_reagents()
to_chat(user, "<span class='warning'>You empty [src]'s nutrient tank.</span>")
/obj/machinery/hydroponics/proc/update_tray(mob/user)
harvest = 0
harvest = FALSE
lastproduce = age
if(istype(myseed, /obj/item/seeds/replicapod))
if(user)//runtimes
to_chat(user, "<span class='notice'>You harvest from the [myseed.plantname].</span>")
to_chat(user, "<span class='notice'>You harvest from the [myseed.plantname].</span>")
else if(myseed.getYield() <= 0)
if(user)
to_chat(user, "<span class='warning'>You fail to harvest anything useful!</span>")
to_chat(user, "<span class='warning'>You fail to harvest anything useful!</span>")
else
if(user)
to_chat(user, "<span class='notice'>You harvest [myseed.getYield()] items from the [myseed.plantname].</span>")
to_chat(user, "<span class='notice'>You harvest [myseed.getYield()] items from the [myseed.plantname].</span>")
if(!myseed.get_gene(/datum/plant_gene/trait/repeated_harvest))
qdel(myseed)
myseed = null
dead = 0
dead = FALSE
name = initial(name)
desc = initial(desc)
TRAY_NAME_UPDATE
if(self_sustaining) //No reason to pay for an empty tray.
idle_power_usage = 0
self_sustaining = FALSE
update_icon()
/// Tray Setters - The following procs adjust the tray or plants variables, and make sure that the stat doesn't go out of bounds.///
/obj/machinery/hydroponics/proc/adjustNutri(adjustamt)
nutrilevel = clamp(nutrilevel + adjustamt, 0, maxnutri)
/obj/machinery/hydroponics/proc/adjustWater(adjustamt)
waterlevel = clamp(waterlevel + adjustamt, 0, maxwater)
@@ -956,11 +694,6 @@
var/mob/living/simple_animal/hostile/C = new chosen
C.faction = list("plants")
/obj/machinery/hydroponics/proc/become_self_sufficient() // Ambrosia Gaia effect
visible_message("<span class='boldnotice'>[src] begins to glow with a beautiful light!</span>")
self_sustaining = TRUE
update_icon()
///////////////////////////////////////////////////////////////////////////////
/obj/machinery/hydroponics/soil //Not actually hydroponics at all! Honk!
name = "soil"
@@ -973,9 +706,6 @@
flags_1 = NODECONSTRUCT_1
unwrenchable = FALSE
/obj/machinery/hydroponics/soil/update_icon_hoses()
return // Has no hoses
/obj/machinery/hydroponics/soil/update_icon_lights()
return // Has no lights
@@ -985,3 +715,6 @@
qdel(src)
else
return ..()
/obj/machinery/hydroponics/soil/CtrlClick(mob/user)
return //Dirt doesn't have electricity, last I checked.
@@ -0,0 +1,32 @@
/**
*This is NOW the gradual affects that each chemical applies on every process() proc. Nutrients now use a more robust reagent holder in order to apply less insane
* stat changes as opposed to 271 lines of individual statline effects. Shoutout to the original comments on chems, I just cleaned a few up.
*/
/obj/machinery/hydroponics/proc/apply_chemicals(mob/user)
///Contains the reagents within the tray.
if(myseed)
myseed.on_chem_reaction(reagents) //In case seeds have some special interactions with special chems, currently only used by vines
for(var/c in reagents.reagent_list)
var/datum/reagent/chem = c
chem.on_hydroponics_apply(myseed, reagents, src, user)
/obj/machinery/hydroponics/proc/mutation_roll(mob/user)
switch(rand(100))
if(91 to 100)
adjustHealth(-10)
visible_message("<span class='warning'>\The [myseed.plantname] starts to wilt and burn!</span>")
return
if(41 to 90)
if(myseed && !self_sustaining) //Stability
myseed.adjust_instability(5)
return
if(21 to 40)
visible_message("<span class='notice'>\The [myseed.plantname] appears unusually reactive...</span>")
return
if(11 to 20)
mutateweed()
return
if(1 to 10)
mutatepest(user)
return
+6
View File
@@ -89,6 +89,12 @@
/datum/plant_gene/core/potency/apply_stat(obj/item/seeds/S)
S.potency = value
/datum/plant_gene/core/instability
name = "Stability"
value = 10
/datum/plant_gene/core/instability/apply_stat(obj/item/seeds/S)
S.instability = value
/datum/plant_gene/core/weed_rate
name = "Weed Growth Rate"
+74 -12
View File
@@ -24,6 +24,7 @@
var/yield = 3 // Amount of growns created per harvest. If is -1, the plant/shroom/weed is never meant to be harvested.
var/potency = 10 // The 'power' of a plant. Generally effects the amount of reagent in a plant, also used in other ways.
var/growthstages = 6 // Amount of growth sprites the plant has.
var/instability = 5 //Chance that a plant will mutate in each stage of it's life.
var/rarity = 0 // How rare the plant is. Used for giving points to cargo when shipping off to CentCom.
var/list/mutatelist = list() // The type of plants that this plant can mutate into.
var/list/genes = list() // Plant genes are stored here, see plant_genes.dm for more info.
@@ -36,6 +37,7 @@
var/weed_rate = 1 //If the chance below passes, then this many weeds sprout during growth
var/weed_chance = 5 //Percentage chance per tray update to grow weeds
var/seed_flags = MUTATE_EARLY //Determines if a plant is allowed to mutate early at 30+ instability
/obj/item/seeds/Initialize(mapload, nogenes = 0)
. = ..()
@@ -61,6 +63,7 @@
genes += new /datum/plant_gene/core/production(production)
if(potency != -1)
genes += new /datum/plant_gene/core/potency(potency)
genes += new /datum/plant_gene/core/instability(instability)
for(var/p in genes)
if(ispath(p))
@@ -74,6 +77,10 @@
/obj/item/seeds/examine(mob/user)
. = ..()
. += "<span class='notice'>Use a pen on it to rename it or change its description.</span>"
if(reagents_add && user.can_see_reagents())
. += "<span class='notice'>- Plant Reagents -</span>"
for(var/datum/plant_gene/reagent/G in genes)
. += "<span class='notice'>- [G.get_name()] -</span>"
/obj/item/seeds/proc/Copy()
var/obj/item/seeds/S = new type(null, 1)
@@ -85,6 +92,7 @@
S.yield = yield
S.potency = potency
S.weed_rate = weed_rate
S.instability = instability
S.weed_chance = weed_chance
S.name = name
S.plantname = plantname
@@ -121,18 +129,20 @@ obj/item/seeds/proc/is_gene_forbidden(typepath)
if(g)
g.mutability_flags &= ~mutability
/obj/item/seeds/proc/mutate(lifemut = 2, endmut = 5, productmut = 1, yieldmut = 2, potmut = 25, wrmut = 2, wcmut = 5, traitmut = 0)
/obj/item/seeds/proc/mutate(lifemut = 2, endmut = 5, productmut = 1, yieldmut = 2, potmut = 25, wrmut = 2, wcmut = 5, traitmut = 0, stabmut = 3)
adjust_lifespan(rand(-lifemut,lifemut))
adjust_endurance(rand(-endmut,endmut))
adjust_production(rand(-productmut,productmut))
adjust_yield(rand(-yieldmut,yieldmut))
adjust_potency(rand(-potmut,potmut))
adjust_instability(rand(-stabmut,stabmut))
adjust_weed_rate(rand(-wrmut, wrmut))
adjust_weed_chance(rand(-wcmut, wcmut))
if(prob(traitmut))
add_random_traits(1, 1)
if(prob(50))
add_random_traits(1, 1)
else
add_random_reagents(1, 1)
/obj/item/seeds/bullet_act(obj/item/projectile/Proj) //Works with the Somatoray to modify plant variables.
if(istype(Proj, /obj/item/projectile/energy/florayield))
@@ -165,13 +175,40 @@ obj/item/seeds/proc/is_gene_forbidden(typepath)
/obj/item/seeds/proc/harvest(mob/user)
///Reference to the tray/soil the seeds are planted in.
var/obj/machinery/hydroponics/parent = loc //for ease of access
///Count used for creating the correct amount of results to the harvest.
var/t_amount = 0
///List of plants all harvested from the same batch.
var/list/result = list()
///Tile of the harvester to deposit the growables.
var/output_loc = parent.Adjacent(user) ? user.loc : parent.loc //needed for TK
///Name of the grown products.
var/product_name
while(t_amount < getYield())
var/obj/item/reagent_containers/food/snacks/grown/t_prod = new product(output_loc, src)
///The Number of products produced by the plant, typically the yield.
var/product_count = getYield()
while(t_amount < product_count)
var/obj/item/reagent_containers/food/snacks/grown/t_prod
if(instability >= 30 && (seed_flags & MUTATE_EARLY) && LAZYLEN(mutatelist) && prob(instability/3))
var/obj/item/seeds/new_prod = pick(mutatelist)
t_prod = initial(new_prod.product)
if(!t_prod)
continue
t_prod = new t_prod(output_loc, src)
t_prod.seed = new new_prod
t_prod.seed.name = initial(new_prod.name)
t_prod.seed.desc = initial(new_prod.desc)
t_prod.seed.plantname = initial(new_prod.plantname)
t_prod.transform = initial(t_prod.transform)
t_prod.transform *= TRANSFORM_USING_VARIABLE(t_prod.seed.potency, 100) + 0.5
t_amount++
if(t_prod.seed)
//t_prod.seed = new new_prod
t_prod.seed.instability = round(instability * 0.5)
continue
else
t_prod = new product(output_loc, src)
if(parent.myseed.plantname != initial(parent.myseed.plantname))
t_prod.name = lowertext(parent.myseed.plantname)
if(productdesc)
@@ -186,8 +223,8 @@ obj/item/seeds/proc/is_gene_forbidden(typepath)
product_name = parent.myseed.plantname
if(getYield() >= 1)
SSblackbox.record_feedback("tally", "food_harvested", getYield(), product_name)
parent.investigate_log("[user] harvested [getYield()] of [src], with seed traits [english_list(genes)] and reagents_add [english_list(reagents_add)] and potency [potency].", INVESTIGATE_BOTANY)
parent.update_tray(user)
return result
/obj/item/seeds/proc/harvest_userless()
@@ -263,6 +300,14 @@ obj/item/seeds/proc/is_gene_forbidden(typepath)
if(C)
C.value = production
/obj/item/seeds/proc/adjust_instability(adjustamt)
if(instability == -1)
return
instability = clamp(instability + adjustamt, 0, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/instability)
if(C)
C.value = instability
/obj/item/seeds/proc/adjust_potency(adjustamt)
if(potency != -1)
potency = clamp(potency + adjustamt, 0, 100)
@@ -320,6 +365,14 @@ obj/item/seeds/proc/is_gene_forbidden(typepath)
if(C)
C.value = potency
/obj/item/seeds/proc/set_instability(adjustamt)
if(instability == -1)
return
instability = clamp(adjustamt, 0, 100)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/instability)
if(C)
C.value = instability
/obj/item/seeds/proc/set_weed_rate(adjustamt)
weed_rate = clamp(adjustamt, 0, 10)
var/datum/plant_gene/core/C = get_gene(/datum/plant_gene/core/weed_rate)
@@ -352,6 +405,7 @@ obj/item/seeds/proc/is_gene_forbidden(typepath)
text += "- Production speed: [production]\n"
text += "- Endurance: [endurance]\n"
text += "- Lifespan: [lifespan]\n"
text += "- Instability: [instability]\n"
text += "- Weed Growth Rate: [weed_rate]\n"
text += "- Weed Vulnerability: [weed_chance]\n"
if(rarity)
@@ -362,9 +416,7 @@ obj/item/seeds/proc/is_gene_forbidden(typepath)
continue
all_traits += " [traits.get_name()]"
text += "- Plant Traits:[all_traits]\n"
text += "*---------*"
return text
/obj/item/seeds/proc/on_chem_reaction(datum/reagents/S) //in case seeds have some special interaction with special chems
@@ -373,9 +425,19 @@ obj/item/seeds/proc/is_gene_forbidden(typepath)
/obj/item/seeds/attackby(obj/item/O, mob/user, params)
if (istype(O, /obj/item/plant_analyzer))
to_chat(user, "<span class='info'>*---------*\n This is \a <span class='name'>[src]</span>.</span>")
var/text = get_analyzer_text()
if(text)
to_chat(user, "<span class='notice'>[text]</span>")
var/text
var/obj/item/plant_analyzer/P_analyzer = O
if(P_analyzer.scan_mode == PLANT_SCANMODE_STATS)
text = get_analyzer_text()
if(text)
to_chat(user, "<span class='notice'>[text]</span>")
if(reagents_add && P_analyzer.scan_mode == PLANT_SCANMODE_CHEMICALS)
to_chat(user, "<span class='notice'>- Plant Reagents -</span>")
to_chat(user, "<span class='notice'>*---------*</span>")
for(var/datum/plant_gene/reagent/G in genes)
to_chat(user, "<span class='notice'>- [G.get_name()] -</span>")
to_chat(user, "<span class='notice'>*---------*</span>")
return
@@ -261,13 +261,11 @@
set_pin_data(IC_OUTPUT, 12, H.pestlevel)
set_pin_data(IC_OUTPUT, 13, H.toxic)
set_pin_data(IC_OUTPUT, 14, H.waterlevel)
set_pin_data(IC_OUTPUT, 15, H.nutrilevel)
set_pin_data(IC_OUTPUT, 15, H.reagents.total_volume)
set_pin_data(IC_OUTPUT, 16, H.harvest)
set_pin_data(IC_OUTPUT, 17, H.dead)
set_pin_data(IC_OUTPUT, 18, H.plant_health)
set_pin_data(IC_OUTPUT, 19, H.self_sustaining)
set_pin_data(IC_OUTPUT, 20, H.using_irrigation)
set_pin_data(IC_OUTPUT, 21, H.FindConnected())
push_data()
activate_pin(2)
@@ -19,30 +19,26 @@
// Hydroponics trays have no reagents holder and handle reagents in their own snowflakey way.
// This is a dirty hack to make injecting reagents into them work.
// TODO: refactor that.
/obj/item/integrated_circuit/reagent/proc/inject_tray(obj/machinery/hydroponics/tray, atom/movable/source, amount)
var/atom/movable/acting_object = get_object()
var/list/trays = list(tray)
var/visi_msg = "[acting_object] transfers fluid into [tray]"
//Time for someone to refactor this. Trays can now hold reagents.
//obj/item/integrated_circuit/reagent/proc/inject_tray(obj/machinery/hydroponics/tray, atom/movable/source, amount)
//var/atom/movable/acting_object = get_object()
//var/list/trays = list(tray)
//var/visi_msg = "[acting_object] transfers fluid into [tray]"
if(amount > 30 && source.reagents.total_volume >= 30 && tray.using_irrigation)
trays = tray.FindConnected()
if (trays.len > 1)
visi_msg += ", setting off the irrigation system"
//acting_object.visible_message("<span class='notice'>[visi_msg].</span>")
//playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
acting_object.visible_message("<span class='notice'>[visi_msg].</span>")
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
//var/split = round(amount/trays.len)
var/split = round(amount/trays.len)
//for(var/obj/machinery/hydroponics/H in trays)
//var/datum/reagents/temp_reagents = new /datum/reagents()
//temp_reagents.my_atom = H
for(var/obj/machinery/hydroponics/H in trays)
var/datum/reagents/temp_reagents = new /datum/reagents()
temp_reagents.my_atom = H
//source.reagents.trans_to(temp_reagents, split)
//H.on_hydroponics_apply(temp_reagents)
source.reagents.trans_to(temp_reagents, split)
H.applyChemicals(temp_reagents)
temp_reagents.clear_reagents()
qdel(temp_reagents)
//temp_reagents.clear_reagents()
//qdel(temp_reagents)
/obj/item/integrated_circuit/reagent/injector
name = "integrated hypo-injector"
@@ -116,10 +112,10 @@
return
if(!AM.reagents)
if(istype(AM, /obj/machinery/hydroponics) && direction_mode == SYRINGE_INJECT && reagents.total_volume && transfer_amount)//injection into tray.
inject_tray(AM, src, transfer_amount)
activate_pin(2)
return
//if(istype(AM, /obj/machinery/hydroponics) && direction_mode == SYRINGE_INJECT && reagents.total_volume && transfer_amount)//injection into tray.
//inject_tray(AM, src, transfer_amount)
//activate_pin(2)
//return
activate_pin(3)
return
@@ -242,13 +238,14 @@
if(!source.reagents)
return
if(!target.reagents)
//if(!target.reagents)
// Hydroponics trays have no reagents holder and handle reagents in their own snowflakey way.
// This is a dirty hack to make injecting reagents into them work.
if(istype(target, /obj/machinery/hydroponics) && source.reagents.total_volume)
inject_tray(target, source, transfer_amount)
activate_pin(2)
return
//Someone should redo this. Trays should hold reagents now.
//if(istype(target, /obj/machinery/hydroponics) && source.reagents.total_volume)
//inject_tray(target, source, transfer_amount)
//activate_pin(2)
//return
if(!source.is_drainable() || !target.is_refillable())
return
+14
View File
@@ -59,3 +59,17 @@
var/mob/living/silicon/robot/R = user.mob
R.uneq_active()
return TRUE
/datum/keybinding/robot/drone/can_use(client/user)
return isdrone(user.mob)
/datum/keybinding/robot/drone/quick_equip_drone // QOL: Drone quickequip
hotkey_keys = list("E")
name = "quick_equip_drone"
full_name = "Quick Equip (Drone)"
description = "Quickly puts an item in the best slot available"
/datum/keybinding/robot/drone/quick_equip_drone/down(client/user)
var/mob/living/simple_animal/drone/D = user.mob
D.quick_equip()
return TRUE
@@ -61,24 +61,18 @@
playsound(src,'sound/effects/sparks4.ogg',50,1)
qdel(src)
/obj/item/wormhole_jaunter/emp_act(power)
/obj/item/wormhole_jaunter/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
var/mob/M = loc
if(istype(M))
var/triggered = FALSE
if(M.get_item_by_slot(SLOT_BELT) == src)
if(power == 1)
triggered = TRUE
else if(power == 2 && prob(50))
triggered = TRUE
if(triggered)
M.visible_message("<span class='warning'>[src] overloads and activates!</span>")
SSblackbox.record_feedback("tally", "jaunter", 1, "EMP") // EMP accidental activation
activate(M)
if(prob(severity))
M.visible_message("<span class='warning'>[src] overloads and activates!</span>")
SSblackbox.record_feedback("tally", "jaunter", 1, "EMP") // EMP accidental activation
activate(M)
/obj/item/wormhole_jaunter/proc/chasm_react(mob/source, datum/component/chasm/C)
to_chat(source, "Your [name] activates, saving you from the chasm!</span>")
@@ -51,7 +51,7 @@
/datum/sprite_accessory/xeno_head/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
return (!H.dna.features["xenohead"] || H.dna.features["xenohead"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == BODYPART_ROBOTIC)
return (!H.dna.features["xenohead"] || H.dna.features["xenohead"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic))
/datum/sprite_accessory/xeno_head/standard
name = "Standard"
@@ -5,7 +5,7 @@
/datum/sprite_accessory/ears/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
return (!H.dna.features["ears"] || H.dna.features["ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || HD.status == BODYPART_ROBOTIC)
return (!H.dna.features["ears"] || H.dna.features["ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic))
/datum/sprite_accessory/ears/none
name = "None"
@@ -187,7 +187,7 @@
/datum/sprite_accessory/ears/mam_ears/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
return (!H.dna.features["mam_ears"] || H.dna.features["mam_ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || HD.status == BODYPART_ROBOTIC)
return (!H.dna.features["mam_ears"] || H.dna.features["mam_ears"] == "None" || H.head && (H.head.flags_inv & HIDEEARS) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEEARS)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic))
/datum/sprite_accessory/ears/mam_ears/none
name = "None"
@@ -5,7 +5,7 @@
/datum/sprite_accessory/horns/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
return (!H.dna.features["horns"] || H.dna.features["horns"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || HD.status == BODYPART_ROBOTIC)
return (!H.dna.features["horns"] || H.dna.features["horns"] == "None" || H.head && (H.head.flags_inv & HIDEHAIR) || (H.wear_mask && (H.wear_mask.flags_inv & HIDEHAIR)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic))
/datum/sprite_accessory/horns/none
name = "None"
@@ -5,7 +5,7 @@
/datum/sprite_accessory/snouts/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
return ((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || HD.status == BODYPART_ROBOTIC)
return ((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic))
/datum/sprite_accessory/snout/guilmon
name = "Guilmon"
@@ -163,7 +163,7 @@
/datum/sprite_accessory/snouts/mam_snouts/is_not_visible(var/mob/living/carbon/human/H, var/tauric)
var/obj/item/bodypart/head/HD = H.get_bodypart(BODY_ZONE_HEAD)
return ((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || HD.status == BODYPART_ROBOTIC)
return ((H.wear_mask && (H.wear_mask.flags_inv & HIDESNOUT)) || (H.head && (H.head.flags_inv & HIDESNOUT)) || !HD || (HD.status == BODYPART_ROBOTIC && !HD.render_like_organic))
/datum/sprite_accessory/snouts/mam_snouts/none
name = "None"
+1 -7
View File
@@ -169,13 +169,7 @@
if(!brainmob || iscyborg(loc))
return
else
switch(severity)
if(1)
brainmob.emp_damage = min(brainmob.emp_damage + rand(20,30), 30)
if(2)
brainmob.emp_damage = min(brainmob.emp_damage + rand(10,20), 30)
if(3)
brainmob.emp_damage = min(brainmob.emp_damage + rand(0,10), 30)
brainmob.emp_damage = min(brainmob.emp_damage + rand(-5,5) + severity/3, 30)
brainmob.emote("alarm")
/obj/item/mmi/Destroy()
@@ -284,11 +284,19 @@
QDEL_LIST(traumas)
return ..()
//other types of brains
/obj/item/organ/brain/alien
name = "alien brain"
desc = "We barely understand the brains of terrestial animals. Who knows what we may find in the brain of such an advanced species?"
icon_state = "brain-x"
/obj/item/organ/brain/ipc
name = "positronic brain"
desc = "A cube of shining metal, four inches to a side and covered in shallow grooves. It has an IPC serial number engraved on the top. It is usually slotted into the head of synthetic crewmembers."
icon = 'icons/obj/surgery.dmi'
icon_state = "posibrain-ipc"
////////////////////////////////////TRAUMAS////////////////////////////////////////
@@ -407,18 +407,16 @@
if(. & EMP_PROTECT_CONTENTS)
return
var/informed = FALSE
if(isrobotic(src))
apply_status_effect(/datum/status_effect/no_combat_mode/robotic_emp, severity / 20)
severity *= 0.5
for(var/obj/item/bodypart/L in src.bodyparts)
if(L.status == BODYPART_ROBOTIC)
if(!informed)
to_chat(src, "<span class='userdanger'>You feel a sharp pain as your robotic limbs overload.</span>")
informed = TRUE
switch(severity)
if(1)
L.receive_damage(0,10)
Stun(200)
if(2)
L.receive_damage(0,5)
Stun(100)
L.receive_damage(0,severity/10)
Stun(severity*2)
/mob/living/carbon/human/acid_act(acidpwr, acid_volume, bodyzone_hit)
var/list/damaged = list()
@@ -96,6 +96,8 @@
throw_alert("not_enough_co2", /obj/screen/alert/not_enough_co2)
else if(S.breathid == "n2")
throw_alert("not_enough_nitro", /obj/screen/alert/not_enough_nitro)
else if(S.breathid == "ch3br")
throw_alert("not_enough_ch3br", /obj/screen/alert/not_enough_ch3br)
return FALSE
else
@@ -364,8 +364,15 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
C.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/species, TRUE, multiplicative_slowdown = speedmod)
if(ROBOTIC_LIMBS in species_traits)
for(var/obj/item/bodypart/B in C.bodyparts)
B.change_bodypart_status(BODYPART_ROBOTIC, FALSE, TRUE) // Makes all Bodyparts robotic.
B.render_like_organic = TRUE
SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species)
/datum/species/proc/update_species_slowdown(mob/living/carbon/human/H)
H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/species, TRUE, multiplicative_slowdown = speedmod)
// EDIT ENDS
@@ -402,6 +409,12 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(F)
qdel(F)
if(ROBOTIC_LIMBS in species_traits)
for(var/obj/item/bodypart/B in C.bodyparts)
B.change_bodypart_status(BODYPART_ORGANIC, FALSE, TRUE)
B.render_like_organic = FALSE
SEND_SIGNAL(C, COMSIG_SPECIES_LOSS, src)
/datum/species/proc/handle_hair(mob/living/carbon/human/H, forced_colour)
@@ -422,7 +435,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/dynamic_fhair_suffix = ""
//for augmented heads
if(HD.status == BODYPART_ROBOTIC)
if(HD.status == BODYPART_ROBOTIC && !HD.render_like_organic)
return
//we check if our hat or helmet hides our facial hair.
@@ -2,7 +2,7 @@
name = "Android"
id = SPECIES_ANDROID
say_mod = "states"
species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL)
species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL,ROBOTIC_LIMBS)
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_NOFIRE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_LIMBATTACHMENT)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
meat = null
@@ -142,3 +142,4 @@
override_float = FALSE
H.pass_flags &= ~PASSTABLE
H.CloseWings()
update_species_slowdown(H)
@@ -84,11 +84,7 @@
EMPeffect = TRUE
spec_updatehealth(H)
to_chat(H, "<span class='notice'>You feel the light of your body leave you.</span>")
switch(severity)
if(EMP_LIGHT)
addtimer(CALLBACK(src, .proc/stop_emp, H), 10 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE) //We're out for 10 seconds
if(EMP_HEAVY)
addtimer(CALLBACK(src, .proc/stop_emp, H), 20 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE) //We're out for 20 seconds
addtimer(CALLBACK(src, .proc/stop_emp, H), (severity/5) SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE) //lights out
/datum/species/ethereal/proc/on_emag_act(mob/living/carbon/human/H, mob/user)
if(emageffect)
@@ -5,19 +5,26 @@
default_color = "00FF00"
blacklisted = 0
sexes = 0
species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE,HAIR)
inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD)
species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE,HAIR,ROBOTIC_LIMBS)
hair_alpha = 210
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
mutant_bodyparts = list("ipc_screen" = "Blank", "ipc_antenna" = "None")
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
gib_types = list(/obj/effect/gibspawner/ipc, /obj/effect/gibspawner/ipc/bodypartless)
mutanttongue = /obj/item/organ/tongue/robot/ipc
//Just robo looking parts.
//Just robo looking parts.
mutant_heart = /obj/item/organ/heart/ipc
mutantlungs = /obj/item/organ/lungs/ipc
mutantliver = /obj/item/organ/liver/ipc
mutantstomach = /obj/item/organ/stomach/ipc
mutanteyes = /obj/item/organ/eyes/ipc
mutantears = /obj/item/organ/ears/ipc
mutanttongue = /obj/item/organ/tongue/robot/ipc
mutant_brain = /obj/item/organ/brain/ipc
//special cybernetic organ for getting power from apcs
mutant_organs = list(/obj/item/organ/cyberimp/arm/power_cord)
exotic_bloodtype = "HF"
exotic_blood_color = BLOOD_COLOR_OIL
@@ -249,6 +249,8 @@
var/mob/living/carbon/human/spare = new /mob/living/carbon/human(H.loc)
spare.underwear = "Nude"
spare.undershirt = "Nude"
spare.socks = "Nude"
H.dna.transfer_identity(spare, transfer_SE=1)
spare.dna.features["mcolor"] = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F")
spare.real_name = spare.dna.real_name
@@ -435,6 +437,8 @@
heatmod = 1
burnmod = 1
allowed_limb_ids = list("slime","stargazer","lum")
/datum/action/innate/slime_change
name = "Alter Form"
check_flags = AB_CHECK_CONSCIOUS
@@ -184,7 +184,7 @@
else if(isliving(AM))
var/mob/living/L = AM
if(isethereal(AM))
AM.emp_act(EMP_LIGHT)
AM.emp_act(50)
if(iscyborg(AM))
var/mob/living/silicon/robot/borg = AM
if(borg.lamp_intensity)
@@ -3,18 +3,24 @@
id = SPECIES_SYNTH_LIZARD
say_mod = "beeps"
default_color = "00FF00"
species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR,HAS_FLESH,HAS_BONE)
species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR,ROBOTIC_LIMBS,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID
mutant_bodyparts = list("ipc_antenna" = "Synthetic Lizard - Antennae","mam_tail" = "Synthetic Lizard", "mam_snouts" = "Synthetic Lizard - Snout", "legs" = "Digitigrade", "mam_body_markings" = "Synthetic Lizard - Plates", "taur" = "None")
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
gib_types = list(/obj/effect/gibspawner/ipc, /obj/effect/gibspawner/ipc/bodypartless)
mutanttongue = /obj/item/organ/tongue/robot/ipc
//Just robo looking parts.
mutant_heart = /obj/item/organ/heart/ipc
mutantlungs = /obj/item/organ/lungs/ipc
mutantliver = /obj/item/organ/liver/ipc
mutantstomach = /obj/item/organ/stomach/ipc
mutanteyes = /obj/item/organ/eyes/ipc
mutantears = /obj/item/organ/ears/ipc
mutanttongue = /obj/item/organ/tongue/robot/ipc
mutant_brain = /obj/item/organ/brain/ipc
//special cybernetic organ for getting power from apcs
mutant_organs = list(/obj/item/organ/cyberimp/arm/power_cord)
exotic_bloodtype = "S"
exotic_blood_color = BLOOD_COLOR_OIL
@@ -19,13 +19,14 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
disconnect_shell()
if (prob(30))
switch(pick(1,2))
if(1)
view_core()
if(2)
SSshuttle.requestEvac(src,"ALERT: Energy surge detected in AI core! Station integrity may be compromised! Initiati--%m091#ar-BZZT")
if(severity >= 60)
disconnect_shell()
if(prob(30))
switch(pick(1,2))
if(1)
view_core()
if(2)
SSshuttle.requestEvac(src,"ALERT: Energy surge detected in AI core! Station integrity may be compromised! Initiati--%m091#ar-BZZT")
/mob/living/silicon/ai/ex_act(severity, target)
switch(severity)
@@ -7,8 +7,8 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
take_holo_damage(50/severity)
DefaultCombatKnockdown(400/severity)
take_holo_damage(severity/2)
DefaultCombatKnockdown(severity*4)
silent = max(silent, (PAI_EMP_SILENCE_DURATION) / SSmobs.wait / severity)
if(holoform)
fold_in(force = TRUE)
@@ -85,12 +85,7 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
switch(severity)
if(1)
Paralyze(160)
if(2)
Paralyze(60)
Paralyze(10 + severity/1.2)
/mob/living/silicon/robot/emag_act(mob/user)
if(user == src)//To prevent syndieborgs from emagging themselves
@@ -105,14 +105,10 @@
to_chat(src, "<span class='danger'>Warning: Electromagnetic pulse detected.</span>")
if(. & EMP_PROTECT_SELF)
return
switch(severity)
if(1)
src.take_bodypart_damage(20)
if(2)
src.take_bodypart_damage(10)
src.take_bodypart_damage(severity/5)
to_chat(src, "<span class='userdanger'>*BZZZT*</span>")
for(var/mob/living/M in buckled_mobs)
if(prob(severity*50))
if(prob(severity/2))
unbuckle_mob(M)
M.DefaultCombatKnockdown(40)
M.visible_message("<span class='boldwarning'>[M] is thrown off of [src]!</span>",
@@ -370,7 +370,7 @@
ejectpai(0)
if(on)
turn_off()
spawn(severity*300)
spawn(3 * severity)
stat &= ~EMPED
if(was_on)
turn_on()
@@ -1060,4 +1060,4 @@ Pass a positive integer as an argument to override a bot's default speed.
path.Cut(1, 2)
/mob/living/silicon/rust_heretic_act()
adjustBruteLoss(500)
adjustBruteLoss(500)
@@ -459,12 +459,10 @@ Auto Patrol[]"},
/mob/living/simple_animal/bot/ed209/emp_act(severity)
if(severity == 2 && prob(70))
severity = 1
. = ..()
if(. & EMP_PROTECT_SELF)
return
if (severity >= 2)
if (severity >= 65)
new /obj/effect/temp_visual/emp(loc)
var/list/mob/living/carbon/targets = new
for(var/mob/living/carbon/C in view(12,src))
@@ -729,7 +729,6 @@
if(load)
load.emp_act(severity)
/mob/living/simple_animal/bot/mulebot/explode()
visible_message("<span class='boldannounce'>[src] blows apart!</span>")
var/atom/Tsec = drop_location()
@@ -220,11 +220,10 @@
return
Stun(100)
to_chat(src, "<span class='danger'><b>ER@%R: MME^RY CO#RU9T!</b> R&$b@0tin)...</span>")
if(severity == 1)
if(severity >= 65)
adjustBruteLoss(heavy_emp_damage)
to_chat(src, "<span class='userdanger'>HeAV% DA%^MMA+G TO I/O CIR!%UUT!</span>")
/mob/living/simple_animal/drone/proc/triggerAlarm(class, area/A, O, obj/alarmsource)
if(alarmsource.z != z)
return
@@ -240,7 +239,6 @@
L[A.name] = list(A, list(alarmsource))
to_chat(src, "--- [class] alarm detected in [A.name]!")
/mob/living/simple_animal/drone/proc/cancelAlarm(class, area/A, obj/origin)
if(stat != DEAD)
var/list/L = alarms[class]
@@ -80,7 +80,9 @@
if(C.can_absorb_dna(owner))
C.add_new_profile(owner)
C.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null)
var/obj/effect/proc_holder/changeling/humanform/hf = new
C.purchasedpowers += hf
hf.on_purchase(origin.current, TRUE)
M.key = origin.key
owner.gib()
+7 -5
View File
@@ -485,11 +485,13 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
if(!ckey)
return
SEND_SIGNAL(new_mob, COMSIG_MOB_PRE_PLAYER_CHANGE, new_mob, src)
if (client && client.prefs && client.prefs.auto_ooc)
if (client.prefs.chat_toggles & CHAT_OOC && isliving(new_mob))
client.prefs.chat_toggles ^= CHAT_OOC
if (!(client.prefs.chat_toggles & CHAT_OOC) && isdead(new_mob))
client.prefs.chat_toggles ^= CHAT_OOC
if (client)
if(client.prefs?.auto_ooc)
if (client.prefs.chat_toggles & CHAT_OOC && isliving(new_mob))
client.prefs.chat_toggles ^= CHAT_OOC
if (!(client.prefs.chat_toggles & CHAT_OOC) && isdead(new_mob))
client.prefs.chat_toggles ^= CHAT_OOC
client.change_view(CONFIG_GET(string/default_view))
new_mob.ckey = ckey
if(send_signal)
SEND_SIGNAL(src, COMSIG_MOB_KEY_CHANGE, new_mob, src)
@@ -6,5 +6,5 @@
if(!ninjacost(250,N_STEALTH_CANCEL))
var/mob/living/carbon/human/H = affecting
playsound(H.loc, 'sound/effects/empulse.ogg', 60, 2)
empulse(H, 4, 6) //Procs sure are nice. Slightly weaker than wizard's disable tch.
empulse_using_range(H, 9) //Procs sure are nice. Slightly weaker than wizard's disable tch.
s_coold = 2
+4 -4
View File
@@ -1,10 +1,9 @@
/obj/machinery/hydroponics/constructable/automagic
name = "automated hydroponics system"
desc = "The bane of botanists everywhere. Accepts chemical reagents via plumbing, automatically harvests and removes dead plants."
icon_state = "hydrotray4"
obj_flags = CAN_BE_HIT | UNIQUE_RENAME
circuit = /obj/item/circuitboard/machine/hydroponics/automagic
self_sufficiency_req = 400 //automating hydroponics makes gaia sad so she needs more drugs to turn they tray godly.
canirrigate = FALSE
/obj/machinery/hydroponics/constructable/automagic/attackby(obj/item/O, mob/user, params)
@@ -31,18 +30,19 @@
. = ..()
START_PROCESSING(SSobj, src)
create_reagents(100 , AMOUNT_VISIBLE)
AddComponent(/datum/component/plumbing/simple_demand)
/obj/machinery/hydroponics/constructable/automagic/ComponentInitialize()
. = ..()
AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE | ROTATION_COUNTERCLOCKWISE | ROTATION_VERBS, null, CALLBACK(src, .proc/can_be_rotated))
AddComponent(/datum/component/plumbing/simple_demand)
/obj/machinery/hydroponics/constructable/proc/can_be_rotated(mob/user, rotation_type)
return !anchored
/obj/machinery/hydroponics/constructable/automagic/process()
if(reagents)
applyChemicals(reagents)
reagents.add_reagent(reagents)
reagents.clear_reagents()
if(dead)
dead = 0
+3 -22
View File
@@ -30,7 +30,6 @@
var/stored_power = 0//Power to deploy per tick
/obj/machinery/power/am_control_unit/Initialize()
. = ..()
linked_shielding = list()
@@ -44,7 +43,6 @@
QDEL_NULL(fueljar)
return ..()
/obj/machinery/power/am_control_unit/process()
if(exploding)
explosion(get_turf(src),8,12,18,12)
@@ -72,7 +70,6 @@
return
/obj/machinery/power/am_control_unit/proc/produce_power()
playsound(src.loc, 'sound/effects/bang.ogg', 25, 1)
var/core_power = reported_core_efficiency//Effectively how much fuel we can safely deal with
@@ -103,15 +100,9 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
switch(severity)
if(1)
if(active)
toggle_power()
stability -= rand(15,30)
if(2)
if(active)
toggle_power()
stability -= rand(10,20)
if(active)
toggle_power()
stability -= rand(round(severity/5),round(severity/3))
/obj/machinery/power/am_control_unit/blob_act()
stability -= 20
@@ -123,20 +114,17 @@
check_stability()
return
/obj/machinery/power/am_control_unit/ex_act(severity, target)
stability -= (80 - (severity * 20))
check_stability()
return
/obj/machinery/power/am_control_unit/bullet_act(obj/item/projectile/Proj)
. = ..()
if(Proj.flag != "bullet")
stability -= Proj.force
check_stability()
/obj/machinery/power/am_control_unit/power_change()
..()
if(stat & NOPOWER)
@@ -150,7 +138,6 @@
return
/obj/machinery/power/am_control_unit/update_icon_state()
if(active)
icon_state = "control_on"
@@ -158,7 +145,6 @@
icon_state = "control"
//No other icons for it atm
/obj/machinery/power/am_control_unit/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/wrench))
if(!anchored)
@@ -192,7 +178,6 @@
else
return ..()
/obj/machinery/power/am_control_unit/take_damage(damage, damage_type = BRUTE, sound_effect = 1)
switch(damage_type)
if(BRUTE)
@@ -221,7 +206,6 @@
update_shield_icons = 1
return 1
/obj/machinery/power/am_control_unit/proc/remove_shielding(obj/machinery/am_shielding/AMS)
if(!istype(AMS))
return 0
@@ -231,13 +215,11 @@
toggle_power()
return 1
/obj/machinery/power/am_control_unit/proc/check_stability()//TODO: make it break when low also might want to add a way to fix it like a part or such that can be replaced
if(stability <= 0)
qdel(src)
return
/obj/machinery/power/am_control_unit/proc/toggle_power(powerfail = 0)
active = !active
if(active)
@@ -249,7 +231,6 @@
update_icon()
return
/obj/machinery/power/am_control_unit/proc/check_shield_icons()//Forces icon_update for all shields
if(shield_icon_delay)
return
+1 -1
View File
@@ -1449,7 +1449,7 @@
environ = 0
update_icon()
update()
addtimer(CALLBACK(src, .proc/reset, APC_RESET_EMP), 600)
addtimer(CALLBACK(src, .proc/reset, APC_RESET_EMP), severity*8)
/obj/machinery/power/apc/blob_act(obj/structure/blob/B)
set_broken()
+6 -1
View File
@@ -549,11 +549,16 @@ By design, d1 is the smallest direction and d2 is the highest
var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected))
if(affecting && affecting.status == BODYPART_ROBOTIC)
//only heal to 25 if limb is damaged to or past 25 burn, otherwise heal normally
var/difference = affecting.burn_dam - 25
var/heal_amount = 15
if(difference >= 0)
heal_amount = difference
if(user == H)
user.visible_message("<span class='notice'>[user] starts to fix some of the wires in [H]'s [affecting.name].</span>", "<span class='notice'>You start fixing some of the wires in [H]'s [affecting.name].</span>")
if(!do_mob(user, H, 50))
return
if(item_heal_robotic(H, user, 0, 15))
if(item_heal_robotic(H, user, 0, heal_amount))
use(1)
return
else
+20 -3
View File
@@ -136,8 +136,8 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
charge -= 1000 / severity
if (charge < 0)
charge -= 10 * severity
if(charge < 0)
charge = 0
/obj/item/stock_parts/cell/ex_act(severity, target)
@@ -185,6 +185,23 @@
/obj/item/stock_parts/cell/get_part_rating()
return rating * maxcharge
// stuff so ipcs and synthlizards can eat power cells, taken from how moths can eat clothing
/obj/item/reagent_containers/food/snacks/cell
name = "oops"
desc = "If you're reading this it means I messed up. This is related to ipcs/synths eating cells and I didn't know a better way to do it than making a new food object."
list_reagents = list(/datum/reagent/consumable/nutriment = 0.5)
tastes = list("electricity" = 1, "metal" = 1)
/obj/item/stock_parts/cell/attack(mob/M, mob/user, def_zone)
if(user.a_intent != INTENT_HARM && isrobotic(M))
var/obj/item/reagent_containers/food/snacks/cell/cell_as_food = new
cell_as_food.name = name
if(cell_as_food.attack(M, user, def_zone))
take_damage(40, sound_effect=FALSE)
qdel(cell_as_food)
else
return ..()
/* Cell variants*/
/obj/item/stock_parts/cell/empty
start_charged = FALSE
@@ -359,7 +376,7 @@
. = ..()
if(. & EMP_PROTECT_SELF)
return
charge = clamp((charge-(10000/severity)),0,maxcharge)
charge = clamp((charge-(100*severity)),0,maxcharge)
/obj/item/stock_parts/cell/emergency_light
name = "miniature power cell"
+1 -1
View File
@@ -209,7 +209,7 @@
if(obj_flags & EMAGGED)
return
obj_flags |= EMAGGED
emp_act(EMP_HEAVY)
emp_act(100)
/obj/machinery/power/port_gen/pacman/attack_ai(mob/user)
interact(user)
@@ -434,7 +434,7 @@
/obj/singularity/proc/emp_area()
empulse(src, 8, 10)
empulse_using_range(src, 10)
return
/obj/singularity/singularity_act()
+1 -1
View File
@@ -407,7 +407,7 @@
outputting = output_attempt
output_level = rand(0, output_level_max)
input_level = rand(0, input_level_max)
charge -= 1e6/severity
charge -= 10000*severity
if (charge < 0)
charge = 0
update_icon()
+1 -1
View File
@@ -346,7 +346,7 @@
if(issilicon(closest_mob))
var/mob/living/silicon/S = closest_mob
if((zap_flags & ZAP_MOB_STUN) && (zap_flags & ZAP_MOB_DAMAGE))
S.emp_act(EMP_LIGHT)
S.emp_act(50)
next_range = 7 // metallic folks bounce it further
else
next_range = 5
+1 -1
View File
@@ -41,7 +41,7 @@
/obj/item/gun/energy/emp_act(severity)
. = ..()
if(!(. & EMP_PROTECT_CONTENTS))
cell.use(round(cell.charge / severity))
cell.use(round(cell.charge * severity/100))
chambered = null //we empty the chamber
recharge_newshot() //and try to charge a new shot
update_icon()

Some files were not shown because too many files have changed in this diff Show More