diff --git a/_maps/map_files/RandomZLevels/spacehotel.dmm b/_maps/map_files/RandomZLevels/spacehotel.dmm
index 5d8cc75019c..f5e3fa7a557 100644
--- a/_maps/map_files/RandomZLevels/spacehotel.dmm
+++ b/_maps/map_files/RandomZLevels/spacehotel.dmm
@@ -2364,42 +2364,42 @@
/area/awaymission/spacehotel)
"ev" = (
/obj/machinery/door/unpowered/hotel_door{
- icon = 'icons/obj/doors/Doorgold.dmi';
+ icon = 'icons/obj/doors/doorgold.dmi';
id = 110
},
/turf/unsimulated/floor/carpet,
/area/awaymission/spacehotel)
"ew" = (
/obj/machinery/door/unpowered/hotel_door{
- icon = 'icons/obj/doors/Doorgold.dmi';
+ icon = 'icons/obj/doors/doorgold.dmi';
id = 111
},
/turf/unsimulated/floor/carpet,
/area/awaymission/spacehotel)
"ex" = (
/obj/machinery/door/unpowered/hotel_door{
- icon = 'icons/obj/doors/Doorgold.dmi';
+ icon = 'icons/obj/doors/doorgold.dmi';
id = 112
},
/turf/unsimulated/floor/carpet,
/area/awaymission/spacehotel)
"ey" = (
/obj/machinery/door/unpowered/hotel_door{
- icon = 'icons/obj/doors/Doorgold.dmi';
+ icon = 'icons/obj/doors/doorgold.dmi';
id = 210
},
/turf/unsimulated/floor/carpet,
/area/awaymission/spacehotel)
"ez" = (
/obj/machinery/door/unpowered/hotel_door{
- icon = 'icons/obj/doors/Doorgold.dmi';
+ icon = 'icons/obj/doors/doorgold.dmi';
id = 211
},
/turf/unsimulated/floor/carpet,
/area/awaymission/spacehotel)
"eA" = (
/obj/machinery/door/unpowered/hotel_door{
- icon = 'icons/obj/doors/Doorgold.dmi';
+ icon = 'icons/obj/doors/doorgold.dmi';
id = 212
},
/turf/unsimulated/floor/carpet,
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index ebf1834246b..d8f0a39588c 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -215,6 +215,9 @@
// Automatic localhost admin disable
var/disable_localhost_admin = 0
+
+ //Start now warning
+ var/start_now_confirmation = 0
// Lavaland
var/lavaland_budget = 60
@@ -647,6 +650,9 @@
if("disable_karma")
config.disable_karma = 1
+
+ if("start_now_confirmation")
+ config.start_now_confirmation = 1
if("tick_limit_mc_init")
config.tick_limit_mc_init = text2num(value)
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index b51cfbd4a68..556e74179da 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -870,6 +870,7 @@
special_role = SPECIAL_ROLE_WIZARD
//ticker.mode.learn_basic_spells(current)
ticker.mode.update_wiz_icons_added(src)
+ SEND_SOUND(current, 'sound/ambience/antag/ragesmages.ogg')
to_chat(current, "You are a Space Wizard!")
current.faction = list("wizard")
log_admin("[key_name(usr)] has wizarded [key_name(current)]")
@@ -911,6 +912,7 @@
ticker.mode.grant_changeling_powers(current)
ticker.mode.update_change_icons_added(src)
special_role = SPECIAL_ROLE_CHANGELING
+ SEND_SOUND(current, 'sound/ambience/antag/ling_aler.ogg')
to_chat(current, "Your powers have awoken. A flash of memory returns to us... we are a changeling!")
log_admin("[key_name(usr)] has changelinged [key_name(current)]")
message_admins("[key_name_admin(usr)] has changelinged [key_name_admin(current)]")
@@ -955,6 +957,7 @@
slaved.masters += src
som = slaved //we MIGT want to mindslave someone
special_role = SPECIAL_ROLE_VAMPIRE
+ SEND_SOUND(current, 'sound/ambience/antag/vampalert.ogg')
to_chat(current, "Your powers have awoken. Your lust for blood grows... You are a Vampire!")
log_admin("[key_name(usr)] has vampired [key_name(current)]")
message_admins("[key_name_admin(usr)] has vampired [key_name_admin(current)]")
@@ -1157,6 +1160,9 @@
if(isAI(current))
var/mob/living/silicon/ai/A = current
ticker.mode.add_law_zero(A)
+ SEND_SOUND(current, 'sound/ambience/antag/malf.ogg')
+ else
+ SEND_SOUND(current, 'sound/ambience/antag/tatoralert.ogg')
ticker.mode.update_traitor_icons_added(src)
if("autoobjectives")
diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm
index 328482f9892..ec43330a8eb 100644
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -1199,7 +1199,7 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
/datum/supply_packs/organic/hydroponics/beekeeping_fullkit
name = "Beekeeping Starter Kit"
- contains = list(/obj/structure/beebox,
+ contains = list(/obj/structure/beebox/unwrenched,
/obj/item/honey_frame,
/obj/item/honey_frame,
/obj/item/honey_frame,
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index 392908127d0..9278d0d5f80 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -90,7 +90,7 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
if(hijack_only)
if(!(locate(/datum/objective/hijack) in usr.mind.objectives))
- to_chat(usr, "The Syndicate lacks resources to provide you with this item.")
+ to_chat(usr, "The Syndicate will only issue this extremely dangerous item to agents assigned the Hijack objective.")
return
if(item)
@@ -182,6 +182,14 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
cost = 3
job = list("Clown")
+/datum/uplink_item/jobspecific/trick_revolver
+ name = "Trick Revolver"
+ desc = "A revolver that will fire backwards and kill whoever attempts to use it. Perfect for those pesky vigilante or just a good laugh."
+ reference = "CTR"
+ item = /obj/item/toy/russian_revolver/trick_revolver
+ cost = 1
+ job = list("Clown")
+
//mime
/datum/uplink_item/jobspecific/caneshotgun
name = "Cane Shotgun and Assassination Shells"
@@ -921,6 +929,8 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
reference = "SB"
item = /obj/item/radio/beacon/syndicate/bomb
cost = 11
+ surplus = 0
+ cant_discount = TRUE
/datum/uplink_item/explosives/syndicate_minibomb
name = "Syndicate Minibomb"
@@ -970,13 +980,22 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
gamemodes = list(/datum/game_mode/nuclear)
surplus = 0
-/datum/uplink_item/explosives/atmosgrenades
- name = "Atmos Grenades"
- desc = "A box of two (2) grenades that wreak havoc with the atmosphere of the target area. Capable of engulfing a large area in lit plasma, or N2O. Deploy with extreme caution!"
- reference = "AGG"
- item = /obj/item/storage/box/syndie_kit/atmosgasgrenades
- cost = 11
+/datum/uplink_item/explosives/atmosn2ogrenades
+ name = "Knockout Gas Grenades"
+ desc = "A box of two (2) grenades that spread knockout gas over a large area. Equip internals before using one of these."
+ reference = "ANG"
+ item = /obj/item/storage/box/syndie_kit/atmosn2ogrenades
+ cost = 8
+
+/datum/uplink_item/explosives/atmosfiregrenades
+ name = "Plasma Fire Grenades"
+ desc = "A box of two (2) grenades that cause large plasma fires. Can be used to deny access to a large area. Most useful if you have an atmospherics hardsuit."
+ reference = "APG"
+ item = /obj/item/storage/box/syndie_kit/atmosfiregrenades
+ hijack_only = TRUE
+ cost = 12
surplus = 0
+ cant_discount = TRUE
/datum/uplink_item/explosives/emp
name = "EMP Grenades and Implanter Kit"
diff --git a/code/game/gamemodes/autotraitor/autotraitor.dm b/code/game/gamemodes/autotraitor/autotraitor.dm
index bf9fbb5a9e5..97371f6d35b 100644
--- a/code/game/gamemodes/autotraitor/autotraitor.dm
+++ b/code/game/gamemodes/autotraitor/autotraitor.dm
@@ -130,8 +130,10 @@
forge_traitor_objectives(newtraitor.mind)
if(istype(newtraitor, /mob/living/silicon))
+ SEND_SOUND(newtraitor, 'sound/ambience/antag/malf.ogg')
add_law_zero(newtraitor)
else
+ SEND_SOUND(newtraitor, 'sound/ambience/antag/tatoralert.ogg')
equip_traitor(newtraitor)
traitors += newtraitor.mind
diff --git a/code/game/gamemodes/blob/blobs/blob_mobs.dm b/code/game/gamemodes/blob/blobs/blob_mobs.dm
index 9cd3ac5343f..e6e9dfe4196 100644
--- a/code/game/gamemodes/blob/blobs/blob_mobs.dm
+++ b/code/game/gamemodes/blob/blobs/blob_mobs.dm
@@ -45,7 +45,6 @@
var/obj/structure/blob/factory/factory = null
var/list/human_overlays = list()
var/is_zombie = 0
- gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE
pressure_resistance = 100 //100 kPa difference required to push
throw_pressure_limit = 120 //120 kPa difference required to throw
@@ -68,15 +67,17 @@
/mob/living/simple_animal/hostile/blob/blobspore/Life(seconds, times_fired)
if(!is_zombie && isturf(src.loc))
- for(var/mob/living/carbon/human/H in oview(src,1)) //Only for corpse right next to/on same tile
- if(H.stat == DEAD)
+ for(var/mob/living/carbon/human/H in oview(src, 1)) //Only for corpse right next to/on same tile
+ if(H.stat == DEAD || (!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD))
Zombify(H)
break
..()
-/mob/living/simple_animal/hostile/blob/blobspore/proc/Zombify(var/mob/living/carbon/human/H)
+/mob/living/simple_animal/hostile/blob/blobspore/proc/Zombify(mob/living/carbon/human/H)
+ if(!H.check_death_method())
+ H.death()
var/obj/item/organ/external/head/head_organ = H.get_organ("head")
- is_zombie = 1
+ is_zombie = TRUE
if(H.wear_suit)
var/obj/item/clothing/suit/armor/A = H.wear_suit
if(A.armor && A.armor["melee"])
@@ -90,14 +91,15 @@
icon = H.icon
speak_emote = list("groans")
icon_state = "zombie2_s"
- head_organ.h_style = null
+ if(head_organ)
+ head_organ.h_style = null
H.update_hair()
human_overlays = H.overlays
update_icons()
- H.loc = src
+ H.forceMove(src)
pressure_resistance = 20 //5 kPa difference required to push lowered
throw_pressure_limit = 30 //15 kPa difference required to throw lowered
- loc.visible_message("The corpse of [H.name] suddenly rises!")
+ visible_message("The corpse of [H.name] suddenly rises!")
/mob/living/simple_animal/hostile/blob/blobspore/death(gibbed)
// Only execute the below if we successfuly died
@@ -174,7 +176,6 @@
force_threshold = 10
mob_size = MOB_SIZE_LARGE
environment_smash = ENVIRONMENT_SMASH_RWALLS
- gold_core_spawnable = CHEM_MOB_SPAWN_HOSTILE
pressure_resistance = 100 //100 kPa difference required to push
throw_pressure_limit = 120 //120 kPa difference required to throw
diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index 865d8e603d2..9e45cab4292 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -185,6 +185,7 @@ var/global/list/all_cults = list()
cult_mind.current.faction |= "cult"
var/datum/action/innate/cultcomm/C = new()
C.Grant(cult_mind.current)
+ SEND_SOUND(cult_mind.current, 'sound/ambience/antag/bloodcult.ogg')
cult_mind.current.create_attack_log("Has been converted to the cult!")
if(jobban_isbanned(cult_mind.current, ROLE_CULTIST) || jobban_isbanned(cult_mind.current, ROLE_SYNDICATE))
replace_jobbanned_player(cult_mind.current, ROLE_CULTIST)
diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm
index f339be06b88..cee4d92008a 100644
--- a/code/game/gamemodes/miniantags/guardian/guardian.dm
+++ b/code/game/gamemodes/miniantags/guardian/guardian.dm
@@ -60,9 +60,9 @@
/mob/living/simple_animal/hostile/guardian/Life(seconds, times_fired) //Dies if the summoner dies
..()
if(summoner)
- if(summoner.stat == DEAD)
+ if(summoner.stat == DEAD || (!summoner.check_death_method() && summoner.health <= HEALTH_THRESHOLD_DEAD))
to_chat(src, "Your summoner has died!")
- visible_message("The [src] dies along with its user!")
+ visible_message("[src] dies along with its user!")
ghostize()
qdel(src)
snapback()
diff --git a/code/game/gamemodes/wizard/rightandwrong.dm b/code/game/gamemodes/wizard/rightandwrong.dm
index 9150f25736a..aff40200c6b 100644
--- a/code/game/gamemodes/wizard/rightandwrong.dm
+++ b/code/game/gamemodes/wizard/rightandwrong.dm
@@ -1,12 +1,12 @@
-/mob/proc/rightandwrong(var/summon_type) //0 = Summon Guns, 1 = Summon Magic
- var/list/gunslist = list("taser","egun","laser","revolver","detective","c20r","nuclear","deagle","gyrojet","pulse","suppressed","cannon","doublebarrel","shotgun","combatshotgun","bulldog","mateba","sabr","crossbow","saw","car","boltaction","arg","uzi","turret","pulsecarbine","decloner","mindflayer","kinetic","advplasmacutter","wormhole","wt550","grenadelauncher","medibeam")
+/mob/proc/rightandwrong(summon_type, revolver_fight = FALSE, fake_revolver_fight = FALSE) //0 = Summon Guns, 1 = Summon Magic
+ var/list/gunslist = list("taser","egun","laser","revolver","detective","c20r","nuclear","deagle","gyrojet","pulse","suppressed","cannon","doublebarrel","shotgun","combatshotgun","bulldog","mateba","sabr","crossbow","saw","car","boltaction","arg","uzi","turret","pulsecarbine","decloner","mindflayer","kinetic","advplasmacutter","wormhole","wt550","grenadelauncher","medibeam", "fakerevolver")
var/list/magiclist = list("fireball","smoke","blind","mindswap","forcewall","knock","horsemask","charge", "summonitem", "wandnothing", "wanddeath", "wandresurrection", "wandpolymorph", "wandteleport", "wanddoor", "wandfireball", "staffhealing", "armor", "scrying", "staffdoor", "special","voodoo","special")
var/list/magicspeciallist = list("staffchange","staffanimation", "wandbelt", "contract", "staffchaos","necromantic")
to_chat(usr, "You summoned [summon_type ? "magic" : "guns"]!")
- message_admins("[key_name_admin(usr)] summoned [summon_type ? "magic" : "guns"]!")
+ message_admins("[key_name_admin(usr)] summoned [summon_type ? "magic" : "guns"]! ([revolver_fight ? "Revolver duel!" : ""] [fake_revolver_fight ? "Suicidal revolver duel!" : ""])")
for(var/mob/living/carbon/human/H in GLOB.player_list)
if(H.stat == 2 || !(H.client))
@@ -17,6 +17,13 @@
var/randomizeguns = pick(gunslist)
var/randomizemagic = pick(magiclist)
var/randomizemagicspecial = pick(magicspeciallist)
+ if(revolver_fight)
+ randomizeguns = "revolver"
+ if(fake_revolver_fight)
+ if(prob(50))
+ randomizeguns = "revolver"
+ else
+ randomizeguns = "fakerevolver"
if(!summon_type)
switch(randomizeguns)
if("taser")
@@ -88,6 +95,8 @@
new /obj/item/gun/projectile/revolver/grenadelauncher(get_turf(H))
if("medibeam")
new /obj/item/gun/medbeam(get_turf(H))
+ if("fakerevolver")
+ new /obj/item/toy/russian_revolver/trick_revolver(get_turf(H)) //lol
playsound(get_turf(H), 'sound/magic/summon_guns.ogg', 50, 1)
else
diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm
index e2cffabcfd0..ecae6919813 100644
--- a/code/game/jobs/job/engineering.dm
+++ b/code/game/jobs/job/engineering.dm
@@ -18,8 +18,8 @@
access_heads, access_construction, access_sec_doors,
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_minisat, access_mechanic, access_mineral_storeroom)
minimal_player_age = 21
- exp_requirements = 1200
- exp_type = EXP_TYPE_CREW
+ exp_requirements = 300
+ exp_type = EXP_TYPE_ENGINEERING
outfit = /datum/outfit/job/chief_engineer
/datum/outfit/job/chief_engineer
diff --git a/code/game/jobs/job/medical.dm b/code/game/jobs/job/medical.dm
index aaf1a61a2a1..49e6b4486ac 100644
--- a/code/game/jobs/job/medical.dm
+++ b/code/game/jobs/job/medical.dm
@@ -16,8 +16,8 @@
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce,
access_keycard_auth, access_sec_doors, access_psychiatrist, access_maint_tunnels, access_paramedic, access_mineral_storeroom)
minimal_player_age = 21
- exp_requirements = 1200
- exp_type = EXP_TYPE_CREW
+ exp_requirements = 300
+ exp_type = EXP_TYPE_MEDICAL
outfit = /datum/outfit/job/cmo
/datum/outfit/job/cmo
diff --git a/code/game/jobs/job/science.dm b/code/game/jobs/job/science.dm
index a1711bf4fd8..435565434c8 100644
--- a/code/game/jobs/job/science.dm
+++ b/code/game/jobs/job/science.dm
@@ -18,8 +18,8 @@
access_research, access_robotics, access_xenobiology, access_ai_upload,
access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_minisat, access_maint_tunnels, access_mineral_storeroom, access_network)
minimal_player_age = 21
- exp_requirements = 1200
- exp_type = EXP_TYPE_CREW
+ exp_requirements = 300
+ exp_type = EXP_TYPE_SCIENCE
// All science-y guys get bonuses for maxing out their tech.
required_objectives = list(
/datum/job_objective/further_research
diff --git a/code/game/jobs/job/security.dm b/code/game/jobs/job/security.dm
index b425532bf30..407393eb489 100644
--- a/code/game/jobs/job/security.dm
+++ b/code/game/jobs/job/security.dm
@@ -18,8 +18,8 @@
access_research, access_engine, access_mining, access_medical, access_construction, access_mailsorting,
access_heads, access_hos, access_RC_announce, access_keycard_auth, access_gateway, access_pilot, access_weapons)
minimal_player_age = 21
- exp_requirements = 1200
- exp_type = EXP_TYPE_CREW
+ exp_requirements = 300
+ exp_type = EXP_TYPE_SECURITY
disabilities_allowed = 0
outfit = /datum/outfit/job/hos
diff --git a/code/game/jobs/job/silicon.dm b/code/game/jobs/job/silicon.dm
index 0def40bc7b1..c239c1d3b3b 100644
--- a/code/game/jobs/job/silicon.dm
+++ b/code/game/jobs/job/silicon.dm
@@ -9,8 +9,8 @@
department_head = list("Captain")
req_admin_notify = 1
minimal_player_age = 30
- exp_requirements = 1200
- exp_type = EXP_TYPE_CREW
+ exp_requirements = 300
+ exp_type = EXP_TYPE_SILICON
/datum/job/ai/equip(mob/living/carbon/human/H)
if(!H)
diff --git a/code/game/jobs/job/supervisor.dm b/code/game/jobs/job/supervisor.dm
index 3cdbb9b7247..710835ca873 100644
--- a/code/game/jobs/job/supervisor.dm
+++ b/code/game/jobs/job/supervisor.dm
@@ -13,8 +13,8 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 0)
access = list() //See get_access()
minimal_access = list() //See get_access()
minimal_player_age = 30
- exp_requirements = 2400
- exp_type = EXP_TYPE_CREW
+ exp_requirements = 300
+ exp_type = EXP_TYPE_COMMAND
disabilities_allowed = 0
outfit = /datum/outfit/job/captain
@@ -68,8 +68,8 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 0)
req_admin_notify = 1
is_command = 1
minimal_player_age = 21
- exp_requirements = 1200
- exp_type = EXP_TYPE_CREW
+ exp_requirements = 300
+ exp_type = EXP_TYPE_COMMAND
access = list(access_security, access_sec_doors, access_brig, access_court, access_forensics_lockers,
access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
diff --git a/code/game/jobs/job_exp.dm b/code/game/jobs/job_exp.dm
index fa13fbdb4b7..218b0761eb3 100644
--- a/code/game/jobs/job_exp.dm
+++ b/code/game/jobs/job_exp.dm
@@ -100,6 +100,7 @@ var/global/list/role_playtime_requirements = list(
// Procs
/proc/role_available_in_playtime(client/C, role)
+ // "role" is a special role defined in role_playtime_requirements above. e.g: ROLE_ERT. This is *not* a job title.
if(!C)
return 0
if(!role)
@@ -121,6 +122,7 @@ var/global/list/role_playtime_requirements = list(
return req_mins
return max(0, req_mins - my_exp)
+
/datum/job/proc/available_in_playtime(client/C)
if(!C)
return 0
diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm
index c134747cd41..acdbc1110f3 100644
--- a/code/game/machinery/computer/cloning.dm
+++ b/code/game/machinery/computer/cloning.dm
@@ -36,10 +36,13 @@
if(scanner.occupant && can_autoprocess())
scan_mob(scanner.occupant)
-
+
+ if(!LAZYLEN(records))
+ return
+
for(var/obj/machinery/clonepod/pod in pods)
if(!(pod.occupant || pod.mess) && (pod.efficiency > 5))
- for(var/datum/dna2/record/R in src.records)
+ for(var/datum/dna2/record/R in records)
if(!(pod.occupant || pod.mess))
if(pod.growclone(R))
records.Remove(R)
@@ -392,6 +395,12 @@
SSnanoui.update_uis(src)
return
+ for(var/obj/machinery/clonepod/pod in pods)
+ if(pod.occupant && pod.clonemind == subject.mind)
+ scantemp = "Subject already getting cloned."
+ SSnanoui.update_uis(src)
+ return
+
subject.dna.check_integrity()
var/datum/dna2/record/R = new /datum/dna2/record()
diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm
index 53072d7e82c..7cfd8bbec45 100644
--- a/code/game/objects/effects/decals/Cleanable/humans.dm
+++ b/code/game/objects/effects/decals/Cleanable/humans.dm
@@ -192,7 +192,7 @@ var/global/list/image/splatter_cache = list()
icon = 'icons/effects/blood.dmi'
icon_state = "gibbl5"
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
- noclear = TRUE
+ no_clear = TRUE
var/fleshcolor = "#FFFFFF"
/obj/effect/decal/cleanable/blood/gibs/update_icon()
@@ -221,18 +221,11 @@ var/global/list/image/splatter_cache = list()
/obj/effect/decal/cleanable/blood/gibs/core
random_icon_states = list("gibmid1", "gibmid2", "gibmid3")
-
-/obj/effect/decal/cleanable/blood/gibs/Initialize()
- . = ..()
- reagents.add_reagent("liquidgibs", 5)
+ scoop_reagents = list("liquidgibs" = 5)
/obj/effect/decal/cleanable/blood/gibs/cleangibs //most ironic name ever...
-
-/obj/effect/decal/cleanable/blood/gibs/cleangibs/Initialize() //no reagent!
- . = ..()
- reagents.remove_reagent("liquidgibs",5)
-
+ scoop_reagents = null
/obj/effect/decal/cleanable/blood/gibs/proc/streak(var/list/directions)
set waitfor = 0
diff --git a/code/game/objects/effects/decals/Cleanable/misc.dm b/code/game/objects/effects/decals/Cleanable/misc.dm
index 0ba4f13e089..01ce637328b 100644
--- a/code/game/objects/effects/decals/Cleanable/misc.dm
+++ b/code/game/objects/effects/decals/Cleanable/misc.dm
@@ -15,10 +15,7 @@
icon = 'icons/obj/objects.dmi'
icon_state = "ash"
anchored = TRUE
-
-/obj/effect/decal/cleanable/ash/Initialize()
- . = ..()
- reagents.add_reagent("ash", 10)
+ scoop_reagents = list("ash" = 10)
/obj/effect/decal/cleanable/dirt
name = "dirt"
@@ -40,11 +37,8 @@
/obj/effect/decal/cleanable/dirt/blackpowder
name = "black powder"
mouse_opacity = TRUE
- noscoop = TRUE
-
-/obj/effect/decal/cleanable/dirt/blackpowder/Initialize()
- . = ..()
- reagents.add_reagent("blackpowder", 40) // size 2 explosion when activated
+ no_scoop = TRUE
+ scoop_reagents = list("blackpowder" = 40) // size 2 explosion when activated
/obj/effect/decal/cleanable/flour
name = "flour"
@@ -127,22 +121,15 @@
icon = 'icons/effects/blood.dmi'
icon_state = "vomit_1"
random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4")
- noclear = TRUE
-
-/obj/effect/decal/cleanable/vomit/Initialize()
- . = ..()
- reagents.add_reagent("vomit", 5)
+ no_clear = TRUE
+ scoop_reagents = list("vomit" = 5)
/obj/effect/decal/cleanable/vomit/green
name = "green vomit"
desc = "It's all gummy. Ew."
icon_state = "gvomit_1"
random_icon_states = list("gvomit_1", "gvomit_2", "gvomit_3", "gvomit_4")
-
-/obj/effect/decal/cleanable/vomit/green/Initialize()
- . = ..()
- reagents.remove_reagent("vomit", 5)
- reagents.add_reagent("green_vomit", 5)
+ scoop_reagents = list("green_vomit" = 5)
/obj/effect/decal/cleanable/tomato_smudge
name = "tomato smudge"
@@ -189,10 +176,7 @@
icon = 'icons/effects/effects.dmi'
icon_state = "flour"
color = "#D5820B"
-
-/obj/effect/decal/cleanable/fungus/Initialize()
- . = ..()
- reagents.add_reagent("fungus", 10)
+ scoop_reagents = list("fungus" = 10)
/obj/effect/decal/cleanable/confetti //PARTY TIME!
name = "confetti"
diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm
index 52ec24df16c..461273bccdb 100644
--- a/code/game/objects/effects/decals/cleanable.dm
+++ b/code/game/objects/effects/decals/cleanable.dm
@@ -1,8 +1,6 @@
/obj/effect/decal/cleanable
anchored = TRUE
var/list/random_icon_states = list()
- var/noscoop = FALSE //if it has this, don't let it be scooped up
- var/noclear = FALSE //if it has this, don't delete it when its' scooped up
/obj/effect/decal/cleanable/proc/can_bloodcrawl_in()
return FALSE
@@ -10,7 +8,6 @@
/obj/effect/decal/cleanable/New()
if(random_icon_states && length(src.random_icon_states) > 0)
src.icon_state = pick(src.random_icon_states)
- create_reagents(100)
if(smooth)
queue_smooth(src)
queue_smooth_neighbors(src)
@@ -19,25 +16,4 @@
/obj/effect/decal/cleanable/Destroy()
if(smooth)
queue_smooth_neighbors(src)
- return ..()
-
-/obj/effect/decal/cleanable/attackby(obj/item/W as obj, mob/user as mob,)
- if(istype(W, /obj/item/reagent_containers/glass) || istype(W, /obj/item/reagent_containers/food/drinks))
- if(src.reagents && W.reagents && !noscoop)
- if(!src.reagents.total_volume)
- to_chat(user, "There isn't enough [src] to scoop up!")
- return
- if(W.reagents.total_volume >= W.reagents.maximum_volume)
- to_chat(user, "[W] is full!")
- return
- to_chat(user, "You scoop the [src] into [W]!")
- reagents.trans_to(W, reagents.total_volume)
- if(!reagents.total_volume && !noclear) //scooped up all of it
- qdel(src)
- return
-
-/obj/effect/decal/cleanable/ex_act()
- if(reagents)
- for(var/datum/reagent/R in reagents.reagent_list)
- R.on_ex_act()
- ..()
\ No newline at end of file
+ return ..()
\ No newline at end of file
diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm
index 52ad55c48a4..64561630d06 100644
--- a/code/game/objects/effects/decals/misc.dm
+++ b/code/game/objects/effects/decals/misc.dm
@@ -54,3 +54,16 @@
/obj/effect/decal/straw/edge
icon_state = "strawscatterededge"
+
+/obj/effect/decal/ants
+ name = "space ants"
+ desc = "A bunch of space ants."
+ icon = 'icons/goonstation/effects/effects.dmi'
+ icon_state = "spaceants"
+ scoop_reagents = list("ants" = 20)
+
+/obj/effect/decal/ants/Initialize(mapload)
+ . = ..()
+ var/scale = (rand(2, 10) / 10) + (rand(0, 5) / 100)
+ transform = matrix(transform, scale, scale, MATRIX_SCALE)
+ setDir(pick(NORTH, SOUTH, EAST, WEST))
\ No newline at end of file
diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm
index 21b9759df62..07c7137d719 100644
--- a/code/game/objects/effects/effects.dm
+++ b/code/game/objects/effects/effects.dm
@@ -13,4 +13,38 @@
return
/obj/effect/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
- return FALSE
\ No newline at end of file
+ return FALSE
+
+/obj/effect/decal
+ var/no_scoop = FALSE //if it has this, don't let it be scooped up
+ var/no_clear = FALSE //if it has this, don't delete it when its' scooped up
+ var/list/scoop_reagents = null
+
+/obj/effect/decal/Initialize(mapload)
+ . = ..()
+ if(scoop_reagents)
+ create_reagents(100)
+ reagents.add_reagent_list(scoop_reagents)
+
+/obj/effect/decal/attackby(obj/item/I, mob/user)
+ if(istype(I, /obj/item/reagent_containers/glass) || istype(I, /obj/item/reagent_containers/food/drinks))
+ scoop(I, user)
+
+/obj/effect/decal/proc/scoop(obj/item/I, mob/user)
+ if(reagents && I.reagents && !no_scoop)
+ if(!reagents.total_volume)
+ to_chat(user, "There isn't enough [src] to scoop up!")
+ return
+ if(I.reagents.total_volume >= I.reagents.maximum_volume)
+ to_chat(user, "[I] is full!")
+ return
+ to_chat(user, "You scoop [src] into [I]!")
+ reagents.trans_to(I, reagents.total_volume)
+ if(!reagents.total_volume && !no_clear) //scooped up all of it
+ qdel(src)
+
+/obj/effect/decal/ex_act()
+ if(reagents)
+ for(var/datum/reagent/R in reagents.reagent_list)
+ R.on_ex_act()
+ ..()
\ No newline at end of file
diff --git a/code/game/objects/effects/spawners/random_spawners.dm b/code/game/objects/effects/spawners/random_spawners.dm
index 18392256fb8..510e5b90380 100644
--- a/code/game/objects/effects/spawners/random_spawners.dm
+++ b/code/game/objects/effects/spawners/random_spawners.dm
@@ -279,7 +279,7 @@
/obj/item/clothing/glasses/thermal = 1,
/obj/item/chameleon = 1,
/obj/item/reagent_containers/hypospray/autoinjector/stimulants = 1,
- /obj/item/storage/box/syndie_kit/atmosgasgrenades = 1,
+ /obj/item/storage/box/syndie_kit/atmosn2ogrenades = 1,
/obj/item/grenade/plastic/x4 = 1)
diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm
index 247b5fb1a0d..e5bbeef7686 100644
--- a/code/game/objects/items/devices/uplinks.dm
+++ b/code/game/objects/items/devices/uplinks.dm
@@ -23,7 +23,6 @@ var/list/world_uplinks = list()
var/used_TC = 0
var/job = null
- var/show_descriptions = 0
var/temp_category
var/uplink_type = "traitor"
@@ -72,7 +71,10 @@ var/list/world_uplinks = list()
if(I.job && I.job.len)
if(!(I.job.Find(job)))
continue
- dat += "[I.name] ([I.cost])
"
+ dat += "[I.name] ([I.cost])"
+ if(I.hijack_only)
+ dat += " (HIJACK ONLY)"
+ dat += "
"
category_items++
dat += "Random Item (??)
"
@@ -95,7 +97,7 @@ var/list/world_uplinks = list()
if(I.job && I.job.len)
if(!(I.job.Find(job)))
continue
- nano[nano.len]["items"] += list(list("Name" = sanitize(I.name), "Description" = sanitize(I.description()),"Cost" = I.cost, "obj_path" = I.reference))
+ nano[nano.len]["items"] += list(list("Name" = sanitize(I.name), "Description" = sanitize(I.description()),"Cost" = I.cost, "hijack_only" = I.hijack_only, "obj_path" = I.reference))
reference[I.reference] = I
var/datum/nano_item_lists/result = new
@@ -231,7 +233,6 @@ var/list/world_uplinks = list()
data["welcome"] = welcome
data["crystals"] = uses
data["menu"] = nanoui_menu
- data["descriptions"] = show_descriptions
if(!nanoui_items)
generate_items(user)
data["nano_items"] = nanoui_items
@@ -266,12 +267,6 @@ var/list/world_uplinks = list()
if(href_list["menu"])
nanoui_menu = text2num(href_list["menu"])
update_nano_data(href_list["id"])
- if(href_list["menu"])
- nanoui_menu = text2num(href_list["menu"])
- update_nano_data(href_list["id"])
- if(href_list["descriptions"])
- show_descriptions = !show_descriptions
- update_nano_data()
if(href_list["category"])
temp_category = href_list["category"]
update_nano_data()
diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm
index 150c8d93f23..eb09e72b5f0 100644
--- a/code/game/objects/items/toys.dm
+++ b/code/game/objects/items/toys.dm
@@ -1372,7 +1372,8 @@ obj/item/toy/cards/deck/syndicate/black
force = 5
origin_tech = "combat=1"
attack_verb = list("struck", "hit", "bashed")
- var/bullet_position = 1
+ var/bullets_left = 0
+ var/max_shots = 6
/obj/item/toy/russian_revolver/suicide_act(mob/user)
user.visible_message("[user] quickly loads six bullets into [src]'s cylinder and points it at [user.p_their()] head before pulling the trigger! It looks like [user.p_theyre()] trying to commit suicide.")
@@ -1380,46 +1381,70 @@ obj/item/toy/cards/deck/syndicate/black
return BRUTELOSS
/obj/item/toy/russian_revolver/New()
- spin_cylinder()
..()
-
+ spin_cylinder()
/obj/item/toy/russian_revolver/attack_self(mob/user)
- if(!bullet_position)
- user.visible_message("[user] loads a bullet into [src]'s cylinder.")
- bullet_position = 1
- else
+ if(!bullets_left)
+ user.visible_message("[user] loads a bullet into [src]'s cylinder before spinning it.")
spin_cylinder()
- user.visible_message("[user] spins the cylinder on [src]!")
-
-/obj/item/toy/russian_revolver/attack(mob/living/carbon/human/M, mob/living/carbon/human/user)
- if(M != user) //can't use this on other people
- return ..()
- if(!bullet_position)
- to_chat(user, "[src] is empty.")
- return
- if(!(user.has_organ("head"))) //For sanity
- to_chat(user, "Playing this game without a head would be classed as cheating.")
- return
- user.visible_message("[user] points [src] at [user.p_their()] head, ready to pull the trigger!")
- if(do_after(user, 30, target = user))
- if(bullet_position > 1)
- user.visible_message("*click*")
- playsound(src, 'sound/weapons/empty.ogg', 100, 1)
- bullet_position--
- return
- else
- bullet_position = null
- playsound(src, 'sound/weapons/gunshots/gunshot_strong.ogg', 50, 1)
- user.visible_message("[src] goes off!")
- user.apply_damage(200, BRUTE, "head", sharp = 1, used_weapon = "Self-inflicted gunshot wound to the head.")
- user.death()
else
- user.visible_message("[user] lowers [src] from [user.p_their()] head.")
+ user.visible_message("[user] spins the cylinder on [src]!")
+ spin_cylinder()
+
+/obj/item/toy/russian_revolver/attack(mob/M, mob/living/user)
+ return
+
+/obj/item/toy/russian_revolver/afterattack(atom/target, mob/user, proximity)
+ shoot_gun(user)
/obj/item/toy/russian_revolver/proc/spin_cylinder()
- bullet_position = rand(1,6)
+ bullets_left = rand(1, max_shots)
+/obj/item/toy/russian_revolver/proc/post_shot(mob/user)
+ return
+
+/obj/item/toy/russian_revolver/proc/shoot_gun(mob/living/carbon/human/user)
+ if(bullets_left > 1)
+ bullets_left--
+ user.visible_message("*click*")
+ playsound(src, 'sound/weapons/empty.ogg', 100, 1)
+ return FALSE
+ if(bullets_left == 1)
+ bullets_left = 0
+ var/zone = "head"
+ if(!(user.has_organ(zone))) // If they somehow don't have a head.
+ zone = "chest"
+ playsound(src, 'sound/weapons/gunshots/gunshot_strong.ogg', 50, 1)
+ user.visible_message("[src] goes off!")
+ post_shot(user)
+ user.apply_damage(300, BRUTE, zone, sharp = TRUE, used_weapon = "Self-inflicted gunshot wound to the [zone].")
+ user.bleed(BLOOD_VOLUME_NORMAL)
+ user.death() // Just in case
+ return TRUE
+ else
+ to_chat(user, "[src] needs to be reloaded.")
+ return FALSE
+
+/obj/item/toy/russian_revolver/trick_revolver
+ name = "\improper .357 revolver"
+ desc = "A suspicious revolver. Uses .357 ammo."
+ icon_state = "revolver"
+ max_shots = 1
+ var/fake_bullets = 0
+
+/obj/item/toy/russian_revolver/trick_revolver/New()
+ ..()
+ fake_bullets = rand(2, 7)
+
+/obj/item/toy/russian_revolver/trick_revolver/examine(mob/user) //Sneaky sneaky
+ ..()
+ to_chat(user, "Has [fake_bullets] round\s remaining.")
+ to_chat(user, "[fake_bullets] of those are live rounds.")
+
+/obj/item/toy/russian_revolver/trick_revolver/post_shot(user)
+ to_chat(user, "[src] did look pretty dodgey!")
+ SEND_SOUND(user, 'sound/misc/sadtrombone.ogg') //HONK
/*
* Rubber Chainsaw
*/
diff --git a/code/game/objects/items/weapons/grenades/flashbang.dm b/code/game/objects/items/weapons/grenades/flashbang.dm
index 2e7bacd4426..5ae889ceaab 100644
--- a/code/game/objects/items/weapons/grenades/flashbang.dm
+++ b/code/game/objects/items/weapons/grenades/flashbang.dm
@@ -6,6 +6,7 @@
light_power = 10
light_color = LIGHT_COLOR_WHITE
var/light_time = 2
+ var/range = 7
/obj/item/grenade/flashbang/prime()
update_mob()
@@ -15,60 +16,65 @@
set_light(7)
- for(var/mob/living/M in hearers(7, flashbang_turf))
- bang(get_turf(M), M)
+ do_sparks(rand(5, 9), FALSE, src)
+ playsound(flashbang_turf, 'sound/effects/bang.ogg', 25, 1)
+ bang(flashbang_turf, range, src)
- for(var/obj/structure/blob/B in hear(8,flashbang_turf)) //Blob damage here
- var/damage = round(30/(get_dist(B,get_turf(src))+1))
+ for(var/obj/structure/blob/B in hear(8, flashbang_turf)) //Blob damage here
+ var/damage = round(30 / (get_dist(B, get_turf(src)) + 1))
B.health -= damage
B.update_icon()
spawn(light_time)
qdel(src)
-/obj/item/grenade/flashbang/proc/bang(var/turf/T , var/mob/living/M)
- M.show_message("BANG", 2)
- playsound(loc, 'sound/effects/bang.ogg', 25, 1)
+/proc/bang(turf/T, atom/A, range = 7, flash = TRUE, bang = TRUE)
+ for(var/mob/living/M in hearers(range, T))
+ if(M.stat == DEAD)
+ continue
+ M.show_message("BANG", 2)
-//Checking for protections
- var/ear_safety = M.check_ear_prot()
- var/distance = max(1,get_dist(src,T))
+ //Checking for protections
+ var/ear_safety = M.check_ear_prot()
+ var/distance = max(1, get_dist(get_turf(A), get_turf(M)))
-//Flash
- if(M.weakeyes)
- M.visible_message("[M] screams and collapses!")
- to_chat(M, "AAAAGH!")
- M.Weaken(15) //hella stunned
- M.Stun(15)
- if(ishuman(M))
- M.emote("scream")
- var/mob/living/carbon/human/H = M
- var/obj/item/organ/internal/eyes/E = H.get_int_organ(/obj/item/organ/internal/eyes)
- if(E)
- E.receive_damage(8, 1)
+ //Flash
+ if(flash)
+ if(M.weakeyes)
+ M.visible_message("[M] screams and collapses!")
+ to_chat(M, "AAAAGH!")
+ M.Weaken(15) //hella stunned
+ M.Stun(15)
+ if(ishuman(M))
+ M.emote("scream")
+ var/mob/living/carbon/human/H = M
+ var/obj/item/organ/internal/eyes/E = H.get_int_organ(/obj/item/organ/internal/eyes)
+ if(E)
+ E.receive_damage(8, 1)
- if(M.flash_eyes(affect_silicon = 1))
- M.Stun(max(10/distance, 3))
- M.Weaken(max(10/distance, 3))
+ if(M.flash_eyes(affect_silicon = TRUE))
+ M.Stun(max(10 / distance, 3))
+ M.Weaken(max(10 / distance, 3))
-//Bang
- if(get_turf(M) == get_turf(src))//Holding on person or being exactly where lies is significantly more dangerous and voids protection
- M.Stun(10)
- M.Weaken(10)
- if(!ear_safety)
- M.Stun(max(10/distance, 3))
- M.Weaken(max(10/distance, 3))
- M.AdjustEarDamage(rand(0, 5), 15)
- if(iscarbon(M))
- var/mob/living/carbon/C = M
- var/obj/item/organ/internal/ears/ears = C.get_int_organ(/obj/item/organ/internal/ears)
- if(istype(ears))
- if(ears.ear_damage >= 15)
- to_chat(M, "Your ears start to ring badly!")
- if(prob(ears.ear_damage - 5))
- to_chat(M, "You can't hear anything!")
- M.BecomeDeaf()
- else
- if(ears.ear_damage >= 5)
- to_chat(M, "Your ears start to ring!")
+ //Bang
+ if(bang)
+ if(!distance || A.loc == M || A.loc == M.loc) //Holding on person or being exactly where lies is significantly more dangerous and voids protection
+ M.Stun(10)
+ M.Weaken(10)
+ if(!ear_safety)
+ M.Stun(max(10 / distance, 3))
+ M.Weaken(max(10 / distance, 3))
+ M.AdjustEarDamage(rand(0, 5), 15)
+ if(iscarbon(M))
+ var/mob/living/carbon/C = M
+ var/obj/item/organ/internal/ears/ears = C.get_int_organ(/obj/item/organ/internal/ears)
+ if(istype(ears))
+ if(ears.ear_damage >= 15)
+ to_chat(M, "Your ears start to ring badly!")
+ if(prob(ears.ear_damage - 5))
+ to_chat(M, "You can't hear anything!")
+ M.BecomeDeaf()
+ else
+ if(ears.ear_damage >= 5)
+ to_chat(M, "Your ears start to ring!")
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index cac42bfced7..c96271d6ddd 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -262,13 +262,24 @@
new /obj/item/spellbook/oneuse/mime/greaterwall(src)
new /obj/item/spellbook/oneuse/mime/fingergun(src)
-/obj/item/storage/box/syndie_kit/atmosgasgrenades
- name = "Atmos Grenades"
-/obj/item/storage/box/syndie_kit/atmosgasgrenades/New()
+/obj/item/storage/box/syndie_kit/atmosn2ogrenades
+ name = "Atmos N2O Grenades"
+
+/obj/item/storage/box/syndie_kit/atmosn2ogrenades/New()
+ ..()
+ new /obj/item/grenade/clusterbuster/n2o(src)
+ new /obj/item/grenade/clusterbuster/n2o(src)
+
+
+/obj/item/storage/box/syndie_kit/atmosfiregrenades
+ name = "Plasma Fire Grenades"
+
+/obj/item/storage/box/syndie_kit/atmosfiregrenades/New()
..()
new /obj/item/grenade/clusterbuster/plasma(src)
- new /obj/item/grenade/clusterbuster/n2o(src)
+ new /obj/item/grenade/clusterbuster/plasma(src)
+
/obj/item/storage/box/syndie_kit/missionary_set
name = "Missionary Starter Kit"
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 5be8c938f3e..03b0172c959 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -278,9 +278,11 @@
if(src == user.loc)
to_chat(user, "You can not [welded?"unweld":"weld"] the locker from inside.")
return
- if(!WT.remove_fuel(0,user))
+ if(!WT.remove_fuel(0, user))
to_chat(user, "You need more welding fuel to complete this task.")
return
+ if(!do_after_once(user, 15, target = src))
+ return
welded = !welded
update_icon()
for(var/mob/M in viewers(src))
diff --git a/code/game/sound.dm b/code/game/sound.dm
index d76c767593f..3846e2edeaa 100644
--- a/code/game/sound.dm
+++ b/code/game/sound.dm
@@ -19,15 +19,19 @@
listeners = listeners & hearers(maxdistance, turf_source)
for(var/P in listeners)
var/mob/M = P
- if(!M || !M.client || M.z != turf_source.z)
+ if(!M || !M.client)
continue
+
+ var/turf/T = get_turf(M) // These checks need to be changed if z-levels are ever further refactored
+ if(!T)
+ continue
+ if(T.z != turf_source.z)
+ continue
+
var/distance = get_dist(M, turf_source)
if(distance <= maxdistance)
- var/turf/T = get_turf(M)
-
- if(T && T.z == turf_source.z)
- M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S)
+ M.playsound_local(turf_source, soundin, vol, vary, frequency, falloff, channel, pressure_affected, S)
/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff, channel = 0, pressure_affected = TRUE, sound/S)
if(!client || !can_hear())
@@ -156,4 +160,4 @@
soundin = pick('sound/effects/bone_break_1.ogg', 'sound/effects/bone_break_2.ogg', 'sound/effects/bone_break_3.ogg', 'sound/effects/bone_break_4.ogg', 'sound/effects/bone_break_5.ogg', 'sound/effects/bone_break_6.ogg')
if("honkbot_e")
soundin = pick('sound/items/bikehorn.ogg', 'sound/items/AirHorn2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/items/AirHorn.ogg', 'sound/items/WEEOO1.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bcreep.ogg','sound/magic/Fireball.ogg' ,'sound/effects/pray.ogg', 'sound/voice/hiss1.ogg','sound/machines/buzz-sigh.ogg', 'sound/machines/ping.ogg', 'sound/weapons/flashbang.ogg', 'sound/weapons/bladeslice.ogg')
- return soundin
+ return soundin
\ No newline at end of file
diff --git a/code/game/world.dm b/code/game/world.dm
index 52f12a10c4e..d87ad886937 100644
--- a/code/game/world.dm
+++ b/code/game/world.dm
@@ -322,6 +322,7 @@ var/world_topic_spam_protect_time = world.timeofday
//kick_clients_in_lobby("The round came to an end with you in the lobby.", 1)
processScheduler.stop()
+ Master.Shutdown() //run SS shutdowns
shutdown_logging() // Past this point, no logging procs can be used, at risk of data loss.
for(var/client/C in GLOB.clients)
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 188a24b96fc..2dd60a674ca 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -671,8 +671,9 @@ var/global/nologevent = 0
alert("Unable to start the game as it is not set up.")
return
if(ticker.current_state == GAME_STATE_PREGAME)
- if(alert(usr, "Are you sure you want to start now?", "Start game", "Yes", "No") != "Yes")
- return
+ if(config.start_now_confirmation)
+ if(alert(usr, "This is a live server. Are you sure you want to start now?", "Start game", "Yes", "No") != "Yes")
+ return
ticker.current_state = GAME_STATE_SETTING_UP
log_admin("[key_name(usr)] has started the game.")
message_admins("[key_name_admin(usr)] has started the game.")
diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm
index fe487ae6431..cec31ffc2ac 100644
--- a/code/modules/admin/secrets.dm
+++ b/code/modules/admin/secrets.dm
@@ -113,7 +113,9 @@
Japanese Animes Mode
Egalitarian Station Mode
Summon Guns
- Summon Magic
+ Summon Magic
+ Summon Revolver Duel
+ Summon Suicidal Revolver Duel
Roll the Dice
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 8025122b2b9..a05246852ff 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -2843,11 +2843,19 @@
if("guns")
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","SG")
- usr.rightandwrong(0)
+ usr.rightandwrong(FALSE)
if("magic")
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","SM")
- usr.rightandwrong(1)
+ usr.rightandwrong(TRUE)
+ if("revolver")
+ feedback_inc("admin_secrets_fun_used", 1)
+ feedback_add_details("admin_secrets_fun_used", "SRD")
+ usr.rightandwrong(FALSE, revolver_fight = TRUE)
+ if("fakerevolver")
+ feedback_inc("admin_secrets_fun_used", 1)
+ feedback_add_details("admin_secrets_fun_used", "SFD")
+ usr.rightandwrong(FALSE, fake_revolver_fight = TRUE)
if("tdomereset")
var/delete_mobs = alert("Clear all mobs?","Confirm","Yes","No","Cancel")
if(delete_mobs == "Cancel")
diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm
index 35c5243de64..b527bb2717d 100644
--- a/code/modules/clothing/glasses/glasses.dm
+++ b/code/modules/clothing/glasses/glasses.dm
@@ -532,6 +532,10 @@
actions_types = list(/datum/action/item_action/toggle)
up = 0
tint = 0
+ species_fit = list("Vox")
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ )
/obj/item/clothing/glasses/tajblind/eng
name = "industrial veil"
diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm
index fb4f3736d6c..d778ea5e63a 100644
--- a/code/modules/clothing/glasses/hud.dm
+++ b/code/modules/clothing/glasses/hud.dm
@@ -165,6 +165,10 @@
flags_cover = GLASSESCOVERSEYES
actions_types = list(/datum/action/item_action/toggle)
up = 0
+ species_fit = list("Vox")
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ )
/obj/item/clothing/glasses/hud/security/tajblind/attack_self()
toggle_veil()
@@ -177,6 +181,10 @@
flags_cover = GLASSESCOVERSEYES
actions_types = list(/datum/action/item_action/toggle)
up = 0
+ species_fit = list("Vox")
+ sprite_sheets = list(
+ "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ )
/obj/item/clothing/glasses/hud/health/tajblind/attack_self()
toggle_veil()
diff --git a/code/modules/events/grid_check.dm b/code/modules/events/grid_check.dm
index 8c099f22a91..d8d1f46ad9b 100644
--- a/code/modules/events/grid_check.dm
+++ b/code/modules/events/grid_check.dm
@@ -1,12 +1,18 @@
/datum/event/grid_check //NOTE: Times are measured in master controller ticks!
announceWhen = 5
-
+
/datum/event/grid_check/setup()
endWhen = rand(30,120)
/datum/event/grid_check/start()
power_failure(0)
-
+ var/sound/S = sound('sound/effects/powerloss.ogg')
+ for(var/mob/living/M in GLOB.player_list)
+ var/turf/T = get_turf(M)
+ if(!M.client || !is_station_level(T.z))
+ continue
+ SEND_SOUND(M, S)
+
/datum/event/grid_check/announce()
event_announcement.Announce("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Automated Grid Check", new_sound = 'sound/AI/poweroff.ogg')
diff --git a/code/modules/examine/descriptions/weapons.dm b/code/modules/examine/descriptions/weapons.dm
index 98f60d01ac4..286391f1387 100644
--- a/code/modules/examine/descriptions/weapons.dm
+++ b/code/modules/examine/descriptions/weapons.dm
@@ -55,6 +55,11 @@
then click where you want to fire. After firing, you will need to pump the gun, by clicking on the gun in your hand. To reload, load more shotgun \
shells into the gun."
+/obj/item/toy/russian_revolver/trick_revolver //oh no
+ description_info = "This is a ballistic weapon. To fire the weapon, have your gun mode set to 'fire', \
+ then click where you want to fire. To reload, click the weapon in your hand to unload (if needed), then add the appropriate ammo. The description \
+ will tell you what caliber you need."
+
//*******
//*Melee*
//*******
diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm
index 52a4a9dcd35..785231a588d 100644
--- a/code/modules/food_and_drinks/drinks/drinks.dm
+++ b/code/modules/food_and_drinks/drinks/drinks.dm
@@ -11,6 +11,7 @@
possible_transfer_amounts = list(5,10,15,20,25,30,50)
volume = 50
burn_state = FIRE_PROOF
+ antable = FALSE
/obj/item/reagent_containers/food/drinks/New()
..()
diff --git a/code/modules/food_and_drinks/food.dm b/code/modules/food_and_drinks/food.dm
index 0ecff55cba0..e931db813cf 100644
--- a/code/modules/food_and_drinks/food.dm
+++ b/code/modules/food_and_drinks/food.dm
@@ -13,10 +13,42 @@
var/transfer_efficiency = 1.0
var/instant_application = 0 //if we want to bypass the forcedfeed delay
var/taste = TRUE//whether you can taste eating from this
+ var/antable = TRUE // Will ants come near it?
+ var/ant_location = null
+ var/ant_timer = null
burn_state = FLAMMABLE
container_type = INJECTABLE
-/obj/item/reagent_containers/food/New()
- ..()
+/obj/item/reagent_containers/food/Initialize(mapload)
+ . = ..()
pixel_x = rand(-5, 5) //Randomizes postion
pixel_y = rand(-5, 5)
+ if(antable)
+ ant_location = get_turf(src)
+ ant_timer = addtimer(CALLBACK(src, .proc/check_for_ants), 3000, TIMER_STOPPABLE)
+
+/obj/item/reagent_containers/food/Destroy()
+ ant_location = null
+ if(ant_timer)
+ deltimer(ant_timer)
+ return ..()
+
+/obj/item/reagent_containers/food/proc/check_for_ants()
+ if(!antable)
+ return
+ var/turf/T = get_turf(src)
+ if(isturf(loc) && !locate(/obj/structure/table) in T)
+ if(ant_location == T)
+ if(prob(15))
+ if(!locate(/obj/effect/decal/ants) in T)
+ new /obj/effect/decal/ants(T)
+ antable = FALSE
+ desc += " It appears to be infested with ants. Yuck!"
+ reagents.add_reagent("ants", 1) // Don't eat things with ants in i you weirdo.
+ if(ant_timer)
+ deltimer(ant_timer)
+ else
+ ant_location = T
+ if(ant_timer)
+ deltimer(ant_timer)
+ ant_timer = addtimer(CALLBACK(src, .proc/check_for_ants), 3000, TIMER_STOPPABLE)
\ No newline at end of file
diff --git a/code/modules/hydroponics/beekeeping/beebox.dm b/code/modules/hydroponics/beekeeping/beebox.dm
index 7acd3efc961..371822643a1 100644
--- a/code/modules/hydroponics/beekeeping/beebox.dm
+++ b/code/modules/hydroponics/beekeeping/beebox.dm
@@ -8,35 +8,36 @@
/mob/proc/bee_friendly()
- return 0
+ return FALSE
/mob/living/simple_animal/hostile/poison/bees/bee_friendly()
- return 1
+ return TRUE
/mob/living/simple_animal/bot/bee_friendly()
if(paicard)
- return 0
- return 1
+ return FALSE
+ return TRUE
/mob/living/simple_animal/diona/bee_friendly()
- return 1
+ return TRUE
/mob/living/carbon/human/bee_friendly()
if(isdiona(src)) //bees pollinate plants, duh.
- return 1
+ return TRUE
if((wear_suit && (wear_suit.flags & THICKMATERIAL)) && (head && (head.flags & THICKMATERIAL)))
- return 1
- return 0
+ return TRUE
+ return FALSE
/obj/structure/beebox
name = "apiary"
- desc = "Dr Miles Manners is just your average Wasp themed super hero by day, but by night he becomes DR BEES!"
+ desc = "Dr. Miles Manners is just your average wasp-themed super hero by day, but by night he becomes DR. BEES!"
icon = 'icons/obj/hydroponics/equipment.dmi'
icon_state = "beebox"
- anchored = 1
- density = 1
+ anchored = TRUE
+ density = TRUE
+ max_integrity = 300
var/mob/living/simple_animal/hostile/poison/bees/queen/queen_bee = null
var/list/bees = list() //bees owned by the box, not those inside it
var/list/honeycombs = list()
@@ -44,8 +45,8 @@
var/bee_resources = 0
-/obj/structure/beebox/New()
- ..()
+/obj/structure/beebox/Initialize(mapload)
+ . = ..()
processing_objects.Add(src)
@@ -66,12 +67,11 @@
var/random_reagent = FALSE
-/obj/structure/beebox/premade/New()
- ..()
-
+/obj/structure/beebox/premade/Initialize(mapload)
+ . = ..()
var/datum/reagent/R = null
if(random_reagent)
- R = get_random_reagent_id()
+ R = GLOB.chemical_reagents_list[get_random_reagent_id()]
queen_bee = new(src)
queen_bee.beehome = src
@@ -83,7 +83,7 @@
honey_frames += HF
for(var/i in 1 to get_max_bees())
- var/mob/living/simple_animal/hostile/poison/bees/worker/B = new(src)
+ var/mob/living/simple_animal/hostile/poison/bees/B = new(src)
bees += B
B.beehome = src
B.assign_reagent(R)
@@ -93,7 +93,7 @@
/obj/structure/beebox/process()
- if(queen_bee && (!queen_bee.beegent || !queen_bee.beegent.can_synth))
+ if(queen_bee)
if(bee_resources >= BEE_RESOURCE_HONEYCOMB_COST)
if(honeycombs.len < get_max_honeycomb())
bee_resources = max(bee_resources-BEE_RESOURCE_HONEYCOMB_COST, 0)
@@ -109,7 +109,7 @@
if((bee_resources >= BEE_RESOURCE_NEW_BEE_COST && prob(BEE_PROB_NEW_BEE)) || freebee)
if(!freebee)
bee_resources = max(bee_resources - BEE_RESOURCE_NEW_BEE_COST, 0)
- var/mob/living/simple_animal/hostile/poison/bees/worker/B = new(src)
+ var/mob/living/simple_animal/hostile/poison/bees/B = new(get_turf(src))
B.beehome = src
B.assign_reagent(queen_bee.beegent)
bees += B
@@ -152,14 +152,16 @@
if(istype(I, /obj/item/honey_frame))
var/obj/item/honey_frame/HF = I
if(honey_frames.len < BEEBOX_MAX_FRAMES)
+ if(!user.unEquip(HF))
+ return
visible_message("[user] adds a frame to the apiary.")
- user.unEquip(HF)
HF.forceMove(src)
honey_frames += HF
else
to_chat(user, "There's no room for anymore frames in the apiary!")
+ return
- if(istype(I, /obj/item/wrench))
+ if(iswrench(I))
if(default_unfasten_wrench(user, I, time = 20))
return
@@ -169,25 +171,27 @@
return
var/obj/item/queen_bee/qb = I
- user.unEquip(qb)
if(!qb.queen.beegent || (qb.queen.beegent && qb.queen.beegent.can_synth))
+ if(!user.unEquip(qb))
+ return
qb.queen.forceMove(src)
bees += qb.queen
queen_bee = qb.queen
qb.queen = null
else
visible_message("The [qb] refuses to settle down. Maybe it's something to do with its reagent?")
+ return
if(queen_bee)
visible_message("[user] sets [qb] down inside the apiary, making it [user.p_their()] new home.")
var/relocated = 0
for(var/b in bees)
- var/mob/living/simple_animal/hostile/poison/bees/worker/B = b
+ var/mob/living/simple_animal/hostile/poison/bees/B = b
if(B.reagent_incompatible(queen_bee))
bees -= B
B.beehome = null
if(B.loc == src)
- B.forceMove(get_turf(src))
+ B.forceMove(drop_location())
relocated++
if(relocated)
to_chat(user, "This queen has a different reagent to some of the bees who live here, those bees will not return to this apiary!")
@@ -196,6 +200,8 @@
to_chat(user, "The queen bee disappeared! bees disappearing has been in the news lately...")
qdel(qb)
+ return
+ return ..()
/obj/structure/beebox/attack_hand(mob/user)
@@ -208,7 +214,7 @@
if(B.isqueen)
continue
if(B.loc == src)
- B.forceMove(get_turf(src))
+ B.forceMove(drop_location())
B.target = user
bees = TRUE
if(bees)
@@ -254,3 +260,16 @@
QB.forceMove(get_turf(src))
visible_message("[user] removes the queen from the apiary.")
queen_bee = null
+
+/obj/structure/beebox/deconstruct(disassembled = TRUE)
+ new /obj/item/stack/sheet/wood(loc, 20)
+ for(var/mob/living/simple_animal/hostile/poison/bees/B in bees)
+ if(B.loc == src)
+ B.forceMove(drop_location())
+ for(var/obj/item/honey_frame/HF in honey_frames)
+ HF.forceMove(drop_location())
+ honey_frames -= HF
+ qdel(src)
+
+/obj/structure/beebox/unwrenched
+ anchored = FALSE
\ No newline at end of file
diff --git a/code/modules/hydroponics/grown/nettle.dm b/code/modules/hydroponics/grown/nettle.dm
index af829387525..444939ca861 100644
--- a/code/modules/hydroponics/grown/nettle.dm
+++ b/code/modules/hydroponics/grown/nettle.dm
@@ -95,7 +95,8 @@
force = round((5 + seed.potency / 2.5), 1)
/obj/item/grown/nettle/death/pickup(mob/living/carbon/user)
- if(..() && ishuman(user)) // If the pickup succeeded and is humanoid
+ . = ..()
+ if(. && ishuman(user)) // If the pickup succeeded and is humanoid
var/mob/living/carbon/human/H = user
if(!H.gloves && prob(50))
user.Paralyse(5)
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index e53e3c9fd4d..471f82c1511 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -35,7 +35,7 @@
/mob/proc/put_in_l_hand(var/obj/item/W)
if(!put_in_hand_check(W))
return 0
- if(!l_hand)
+ if(!l_hand && has_left_hand())
W.forceMove(src) //TODO: move to equipped?
l_hand = W
W.layer = 20 //TODO: move to equipped?
@@ -51,7 +51,7 @@
/mob/proc/put_in_r_hand(var/obj/item/W)
if(!put_in_hand_check(W))
return 0
- if(!r_hand)
+ if(!r_hand && has_right_hand())
W.forceMove(src)
r_hand = W
W.layer = 20
diff --git a/code/modules/mob/living/carbon/give.dm b/code/modules/mob/living/carbon/give.dm
index 473715367b4..c0dba9b77e5 100644
--- a/code/modules/mob/living/carbon/give.dm
+++ b/code/modules/mob/living/carbon/give.dm
@@ -4,22 +4,15 @@
if(!iscarbon(target)) //something is bypassing the give arguments, no clue what, adding a sanity check JIC
to_chat(usr, "Wait a second... \the [target] HAS NO HANDS! AHH!")//cheesy messages ftw
+ return
+ if(target.incapacitated() || usr.incapacitated() || target.client == null)
return
- if(target.stat == 2 || usr.stat == 2|| target.client == null)
- return
- var/obj/item/I
- if(!usr.hand && usr.r_hand == null)
- to_chat(usr, " You don't have anything in your right hand to give to [target.name]")
- return
- if(usr.hand && usr.l_hand == null)
- to_chat(usr, " You don't have anything in your left hand to give to [target.name]")
- return
- if(usr.hand)
- I = usr.l_hand
- else if(!usr.hand)
- I = usr.r_hand
+
+ var/obj/item/I = get_active_hand()
+
if(!I)
+ to_chat(usr, " You don't have anything in your hand to give to [target.name]")
return
if((I.flags & NODROP) || (I.flags & ABSTRACT))
to_chat(usr, "That's not exactly something you can give.")
@@ -29,35 +22,30 @@
if("Yes")
if(!I)
return
+ if(target.incapacitated() || usr.incapacitated())
+ return
if(!Adjacent(target))
to_chat(usr, " You need to stay in reaching distance while giving an object.")
to_chat(target, " [usr.name] moved too far away.")
return
- if((usr.hand && usr.l_hand != I) || (!usr.hand && usr.r_hand != I))
+ if((I.flags & NODROP) || (I.flags & ABSTRACT))
+ to_chat(usr, "[I] stays stuck to your hand when you try to give it!")
+ to_chat(target, "[I] stays stuck to [usr.name]'s hand when you try to take it!")
+ return
+ if(I != get_active_hand())
to_chat(usr, " You need to keep the item in your active hand.")
- to_chat(target, " [usr.name] seem to have given up on giving \the [I.name] to you.")
+ to_chat(target, " [usr.name] seem to have given up on giving [I] to you.")
return
if(target.r_hand != null && target.l_hand != null)
to_chat(target, " Your hands are full.")
to_chat(usr, " Their hands are full.")
return
- else
- usr.drop_item()
- if(target.r_hand == null)
- target.r_hand = I
- else
- target.l_hand = I
- I.loc = target
- I.layer = 20
- I.plane = HUD_PLANE
+ usr.unEquip(I)
+ target.put_in_hands(I)
I.add_fingerprint(target)
- src.update_inv_l_hand()
- src.update_inv_r_hand()
- target.update_inv_l_hand()
- target.update_inv_r_hand()
- target.visible_message(" [usr.name] handed \the [I.name] to [target.name].")
+ target.visible_message(" [usr.name] handed [I] to [target.name].")
I.on_give(usr, target)
if("No")
- target.visible_message(" [usr.name] tried to hand [I.name] to [target.name] but [target.name] didn't want it.")
+ target.visible_message(" [usr.name] tried to hand [I] to [target.name] but [target.name] didn't want it.")
else
to_chat(usr, " [target.name]'s hands are full.")
diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm
index b4cb92af01e..7e9739a816d 100644
--- a/code/modules/mob/living/carbon/human/human_damage.dm
+++ b/code/modules/mob/living/carbon/human/human_damage.dm
@@ -172,6 +172,7 @@
// Defined here solely to take species flags into account without having to recast at mob/living level.
/mob/living/carbon/human/adjustOxyLoss(amount)
if(NO_BREATHE in dna.species.species_traits)
+ oxyloss = 0
return FALSE
if(dna.species && amount > 0)
amount = amount * dna.species.oxy_mod
@@ -179,6 +180,7 @@
/mob/living/carbon/human/setOxyLoss(amount)
if(NO_BREATHE in dna.species.species_traits)
+ oxyloss = 0
return FALSE
if(dna.species && amount > 0)
amount = amount * dna.species.oxy_mod
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index 7d83c7eaa1d..79b41e47cc3 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -434,11 +434,11 @@
if(slot_l_hand)
if(l_hand)
return 0
- return 1
+ return !incapacitated()
if(slot_r_hand)
if(r_hand)
return 0
- return 1
+ return !incapacitated()
if(slot_wear_mask)
if(wear_mask)
return 0
diff --git a/code/modules/mob/living/carbon/human/status_procs.dm b/code/modules/mob/living/carbon/human/status_procs.dm
index 9a1c7a5bbd6..30653023751 100644
--- a/code/modules/mob/living/carbon/human/status_procs.dm
+++ b/code/modules/mob/living/carbon/human/status_procs.dm
@@ -1,5 +1,6 @@
/mob/living/carbon/human/SetLoseBreath(amount)
if(NO_BREATHE in dna.species.species_traits)
+ losebreath = 0
return FALSE
. = ..()
diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm
index e3005292c95..afca9ad8798 100644
--- a/code/modules/mob/living/damage_procs.dm
+++ b/code/modules/mob/living/damage_procs.dm
@@ -122,8 +122,10 @@
/mob/living/proc/adjustOxyLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
+ oxyloss = 0
return FALSE //godmode
if(BREATHLESS in mutations)
+ oxyloss = 0
return FALSE
var/old_oxyloss = oxyloss
oxyloss = max(oxyloss + amount, 0)
@@ -137,8 +139,10 @@
/mob/living/proc/setOxyLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
+ oxyloss = 0
return FALSE //godmode
if(BREATHLESS in mutations)
+ oxyloss = 0
return FALSE
var/old_oxyloss = oxyloss
oxyloss = amount
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 3de38568a4a..52fde3d0d9e 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -759,7 +759,7 @@
if(!silent)
visible_message("[src] tries to put [what] on [who].")
if(do_mob(src, who, what.put_on_delay))
- if(what && Adjacent(who))
+ if(what && Adjacent(who) && !(what.flags & NODROP))
unEquip(what)
who.equip_to_slot_if_possible(what, where, 0, 1)
add_attack_logs(src, who, "Equipped [what]")
diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm
index 5c6fc35be50..a84af2c8254 100644
--- a/code/modules/mob/living/silicon/robot/robot_modules.dm
+++ b/code/modules/mob/living/silicon/robot/robot_modules.dm
@@ -429,6 +429,7 @@
modules += new /obj/item/bonesetter(src)
modules += new /obj/item/surgicaldrill(src)
modules += new /obj/item/gripper/medical(src)
+ modules += new /obj/item/gun/medbeam(src)
modules += new /obj/item/melee/energy/sword/cyborg/saw(src) //Energy saw -- primary weapon
modules += new /obj/item/card/emag(src)
modules += new /obj/item/crowbar/cyborg(src)
diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm
index 4516a44a935..5ebefeba405 100644
--- a/code/modules/mob/living/simple_animal/hostile/bees.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bees.dm
@@ -11,7 +11,7 @@
/mob/living/simple_animal/hostile/poison/bees
name = "bee"
- desc = "buzzy buzzy bee, stingy sti- Ouch!"
+ desc = "Buzzy buzzy bee, stingy sti- Ouch!"
icon_state = ""
icon_living = ""
icon = 'icons/mob/bees.dmi'
@@ -33,25 +33,28 @@
environment_smash = 0
mouse_opacity = MOUSE_OPACITY_OPAQUE
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
- flying = 1
- search_objects = 1 //have to find those plant trays!
- density = 0
+ density = FALSE
mob_size = MOB_SIZE_TINY
+ flying = TRUE
+ search_objects = TRUE //have to find those plant trays!
//Spaceborn beings don't get hurt by space
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
- del_on_death = 1
+ del_on_death = TRUE
var/datum/reagent/beegent = null //hehe, beegent
var/obj/structure/beebox/beehome = null
- var/isqueen = FALSE
var/idle = 0
+ var/isqueen = FALSE
+ var/bee_syndicate = FALSE
var/icon_base = "bee"
var/static/list/bee_icons = list()
+ var/static/beehometypecache = typecacheof(/obj/structure/beebox)
+ var/static/hydroponicstypecache = typecacheof(/obj/machinery/hydroponics)
/mob/living/simple_animal/hostile/poison/bees/Process_Spacemove(movement_dir = 0)
- return 1
+ return TRUE
/mob/living/simple_animal/hostile/poison/bees/New()
..()
@@ -65,6 +68,20 @@
beehome = null
return ..()
+/mob/living/simple_animal/hostile/poison/bees/death(gibbed)
+ . = ..()
+ if(!.)
+ return
+ if(beehome)
+ if(beehome.bees)
+ beehome.bees.Remove(src)
+ beehome = null
+
+/mob/living/simple_animal/hostile/poison/bees/examine(mob/user)
+ ..()
+ if(!bee_syndicate && !beehome)
+ to_chat(user, "This bee is homeless!")
+
/mob/living/simple_animal/hostile/poison/bees/proc/generate_bee_visuals()
overlays.Cut()
@@ -94,21 +111,45 @@
//We don't attack beekeepers/people dressed as bees//Todo: bee costume
/mob/living/simple_animal/hostile/poison/bees/CanAttack(atom/the_target)
. = ..()
- return .
+ if(!.)
+ return FALSE
+ if(!bee_syndicate && isliving(the_target))
+ var/mob/living/H = the_target
+ return !H.bee_friendly()
/mob/living/simple_animal/hostile/poison/bees/Found(atom/A)
if(isliving(A))
- var/mob/living/L = A
- return !L.bee_friendly()
- return 0
+ var/mob/living/H = A
+ return !H.bee_friendly()
+ if(istype(A, /obj/machinery/hydroponics))
+ var/obj/machinery/hydroponics/Hydro = A
+ if(Hydro.myseed && !Hydro.dead && !Hydro.recent_bee_visit)
+ wanted_objects |= hydroponicstypecache //so we only hunt them while they're alive/seeded/not visisted
+ return TRUE
+ return FALSE
/mob/living/simple_animal/hostile/poison/bees/AttackingTarget()
- if(beegent && isliving(target))
- var/mob/living/L = target
- if(!isnull(target.reagents))
- beegent.reaction_mob(L, INGEST)
- L.reagents.add_reagent(beegent.id, rand(1,5))
- target.attack_animal(src)
+ //Pollinate
+ if(istype(target, /obj/machinery/hydroponics))
+ var/obj/machinery/hydroponics/Hydro = target
+ pollinate(Hydro)
+ else if(istype(target, /obj/structure/beebox))
+ if(target == beehome)
+ var/obj/structure/beebox/BB = target
+ forceMove(BB)
+ target = null
+ wanted_objects -= beehometypecache //so we don't attack beeboxes when not going home
+ return //no don't attack the goddamm box
+ else
+ ..()
+ if(isliving(target))
+ var/mob/living/L = target
+ if(L.reagents)
+ if(beegent)
+ beegent.reaction_mob(L, INGEST)
+ L.reagents.add_reagent(beegent.id, rand(1, 5))
+ else
+ L.reagents.add_reagent("spidertoxin", 5)
/mob/living/simple_animal/hostile/poison/bees/proc/assign_reagent(datum/reagent/R)
if(istype(R))
@@ -116,81 +157,13 @@
name = "[initial(name)] ([R.name])"
generate_bee_visuals()
-/mob/living/simple_animal/hostile/poison/bees/handle_automated_action()
- . = ..()
- if(!.)
- return
-
-/mob/living/simple_animal/hostile/poison/bees/proc/reagent_incompatible(mob/living/simple_animal/hostile/poison/bees/B)
- if(!B)
- return 0
- if(B.beegent && beegent && B.beegent.id != beegent.id || B.beegent && !beegent || !B.beegent && beegent)
- return 1
- return 0
-
-//Botany Worker Bees
-/mob/living/simple_animal/hostile/poison/bees/worker
- //Blank type define in case we need to give them special stuff later, plus organization (currently they are same as base type bee)
-
-
-/mob/living/simple_animal/hostile/poison/bees/worker/Destroy()
- if(beehome)
- if(beehome.bees)
- beehome.bees.Remove(src)
- beehome = null
- return ..()
-
-/mob/living/simple_animal/hostile/poison/bees/worker/death(gibbed)
- . = ..()
- if(!.)
- return
- if(beehome)
- if(beehome.bees)
- beehome.bees.Remove(src)
- beehome = null
-
-/mob/living/simple_animal/hostile/poison/bees/worker/examine(mob/user)
- ..()
-
- if(!beehome)
- to_chat(user, "This bee is homeless!")
-
-/mob/living/simple_animal/hostile/poison/bees/worker/Found(atom/A)
- if(istype(A, /obj/machinery/hydroponics))
- var/obj/machinery/hydroponics/Hydro = A
- if(Hydro.myseed && !Hydro.dead && !Hydro.recent_bee_visit && !Hydro.lid_state)
- wanted_objects |= /obj/machinery/hydroponics //so we only hunt them while they're alive/seeded/not visisted and uncovered
- return 1
- ..()
-
-/mob/living/simple_animal/hostile/poison/bees/worker/CanAttack(atom/the_target)
- . = ..()
- if(!.)
- return 0
- if(isliving(the_target)) //Should ignore ghosts and camera mobs already, but just in case
- var/mob/living/L = the_target
- return !L.bee_friendly()
-
-/mob/living/simple_animal/hostile/poison/bees/worker/AttackingTarget()
- //Pollinate
- if(istype(target, /obj/machinery/hydroponics))
- var/obj/machinery/hydroponics/Hydro = target
- pollinate(Hydro)
- else if(target == beehome)
- var/obj/structure/beebox/BB = target
- forceMove(BB)
- target = null
- wanted_objects -= /obj/structure/beebox //so we don't attack beeboxes when not going home
- else
- ..()
-
-/mob/living/simple_animal/hostile/poison/bees/worker/proc/pollinate(obj/machinery/hydroponics/Hydro)
+/mob/living/simple_animal/hostile/poison/bees/proc/pollinate(obj/machinery/hydroponics/Hydro)
if(!istype(Hydro) || !Hydro.myseed || Hydro.dead || Hydro.recent_bee_visit || Hydro.lid_state)
target = null
return
target = null //so we pick a new hydro tray next FindTarget(), instead of loving the same plant for eternity
- wanted_objects -= /obj/machinery/hydroponics //so we only hunt them while they're alive/seeded/not visisted and uncovered
+ wanted_objects -= hydroponicstypecache //so we only hunt them while they're alive/seeded/not visisted
Hydro.recent_bee_visit = TRUE
spawn(BEE_TRAY_RECENT_VISIT)
if(Hydro)
@@ -210,68 +183,79 @@
if(beehome)
beehome.bee_resources = min(beehome.bee_resources + growth, 100)
-/mob/living/simple_animal/hostile/poison/bees/worker/handle_automated_action()
+/mob/living/simple_animal/hostile/poison/bees/handle_automated_action()
. = ..()
if(!.)
return
- if(!isqueen)
- if(loc == beehome)
- idle = min(100, ++idle)
- if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM))
- forceMove(get_turf(beehome))
- else
- idle = max(0, --idle)
- if(idle <= BEE_IDLE_GOHOME && prob(BEE_PROB_GOHOME))
- if(!FindTarget())
- wanted_objects += /obj/structure/beebox //so we don't attack beeboxes when not going home
- target = beehome
- if(!beehome) //add outselves to a beebox (of the same reagent) if we have no home
- for(var/obj/structure/beebox/BB in view(vision_range, src))
- if(reagent_incompatible(BB.queen_bee) || BB.bees.len >= BB.get_max_bees())
- continue
- BB.bees |= src
- beehome = BB
-
+ if(!bee_syndicate)
+ if(!isqueen)
+ if(loc == beehome)
+ idle = min(100, ++idle)
+ if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM))
+ forceMove(beehome.drop_location())
+ else
+ idle = max(0, --idle)
+ if(idle <= BEE_IDLE_GOHOME && prob(BEE_PROB_GOHOME))
+ if(!FindTarget())
+ wanted_objects |= beehometypecache //so we don't attack beeboxes when not going home
+ target = beehome
+ if(!beehome) //add ourselves to a beebox (of the same reagent) if we have no home
+ for(var/obj/structure/beebox/BB in view(vision_range, src))
+ if(reagent_incompatible(BB.queen_bee) || BB.bees.len >= BB.get_max_bees())
+ continue
+ BB.bees |= src
+ beehome = BB
+ break // End loop after the first compatible find.
//Botany Queen Bee
/mob/living/simple_animal/hostile/poison/bees/queen
name = "queen bee"
- desc = "she's the queen of bees, BZZ BZZ"
+ desc = "She's the queen of bees, BZZ BZZ"
icon_base = "queen"
isqueen = TRUE
- //the Queen doesn't leave the box on her own, and she CERTAINLY doesn't pollinate by herself
+//the Queen doesn't leave the box on her own, and she CERTAINLY doesn't pollinate by herself
/mob/living/simple_animal/hostile/poison/bees/queen/Found(atom/A)
- return 0
+ return FALSE
+
+//leave pollination for the peasent bees
+/mob/living/simple_animal/hostile/poison/bees/queen/AttackingTarget()
+ ..()
+ if(beegent && isliving(target))
+ var/mob/living/L = target
+ beegent.reaction_mob(L, TOUCH)
+ L.reagents.add_reagent(beegent.id, rand(1, 5))
+
+//PEASENT BEES
+/mob/living/simple_animal/hostile/poison/bees/queen/pollinate()
+ return
+
+/mob/living/simple_animal/hostile/poison/bees/proc/reagent_incompatible(mob/living/simple_animal/hostile/poison/bees/B)
+ if(!B)
+ return FALSE
+ if(B.beegent && beegent && B.beegent.id != beegent.id || B.beegent && !beegent || !B.beegent && beegent)
+ return TRUE
+ return FALSE
-/mob/living/simple_animal/hostile/poison/bees/queen/CanAttack(atom/the_target)
- . = ..()
- if(!.)
- return 0
- if(isliving(the_target)) //Should ignore ghosts and camera mobs already, but just in case
- var/mob/living/L = the_target
- return !L.bee_friendly()
/obj/item/queen_bee
name = "queen bee"
- desc = "she's the queen of bees, BZZ BZZ"
+ desc = "She's the queen of bees, BZZ BZZ"
icon_state = "queen_item"
item_state = ""
icon = 'icons/mob/bees.dmi'
var/mob/living/simple_animal/hostile/poison/bees/queen/queen
+
/obj/item/queen_bee/attackby(obj/item/I, mob/user, params)
- if(istype(I,/obj/item/reagent_containers/syringe))
+ if(istype(I, /obj/item/reagent_containers/syringe))
var/obj/item/reagent_containers/syringe/S = I
if(S.reagents.has_reagent("royal_bee_jelly")) //checked twice, because I really don't want royal bee jelly to be duped
- if(S.reagents.has_reagent("royal_bee_jelly",5))
+ if(S.reagents.has_reagent("royal_bee_jelly", 5))
S.reagents.remove_reagent("royal_bee_jelly", 5)
- if(!queen.beegent.can_synth)
- to_chat(user, "You inject [src] with the royal bee jelly. It's ineffective! Maybe it's something to do with the [src] reagent.")
- return
- var/obj/item/queen_bee/qb = new(get_turf(user))
+ var/obj/item/queen_bee/qb = new(user.drop_location())
qb.queen = new(qb)
if(queen && queen.beegent)
qb.queen.assign_reagent(queen.beegent) //Bees use the global singleton instances of reagents, so we don't need to worry about one bee being deleted and her copies losing their reagents.
@@ -282,16 +266,17 @@
else
var/datum/reagent/R = GLOB.chemical_reagents_list[S.reagents.get_master_reagent_id()]
if(R && S.reagents.has_reagent(R.id, 5))
- S.reagents.remove_reagent(R.id,5)
+ S.reagents.remove_reagent(R.id, 5)
queen.assign_reagent(R)
- user.visible_message("[user] injects [src]'s genome with [R.name], mutating it's DNA!","You inject [src]'s genome with [R.name], mutating it's DNA!")
+ user.visible_message("[user] injects [src]'s genome with [R.name], mutating its DNA!", "You inject [src]'s genome with [R.name], mutating its DNA!")
name = queen.name
else
to_chat(user, "You don't have enough units of that chemical to modify the bee's DNA!")
- ..()
+ else
+ return ..()
-/obj/item/queen_bee/bought/New()
- ..()
+/obj/item/queen_bee/bought/Initialize(mapload)
+ . = ..()
queen = new(src)
/obj/item/queen_bee/Destroy()
@@ -299,7 +284,6 @@
return ..()
-
//Syndicate Bees
/mob/living/simple_animal/hostile/poison/bees/syndi
name = "syndi-bee"
@@ -309,10 +293,14 @@
maxHealth = 25
health = 25
faction = list("hostile", "syndicate")
- search_objects = 0 //these bees don't care about trivial things like plants, especially when there is havoc to sow
- beegent = new /datum/reagent/facid() //prepare to die
+ search_objects = FALSE //these bees don't care about trivial things like plants, especially when there is havoc to sow
+ bee_syndicate = TRUE
var/list/master_and_friends = list()
+/mob/living/simple_animal/hostile/poison/bees/syndi/New()
+ beegent = GLOB.chemical_reagents_list["facid"] //Prepare to die
+ ..()
+
/mob/living/simple_animal/hostile/poison/bees/syndi/Destroy()
master_and_friends.Cut()
return ..()
@@ -320,24 +308,27 @@
/mob/living/simple_animal/hostile/poison/bees/syndi/assign_reagent(datum/reagent/R)
return
-/mob/living/simple_animal/hostile/poison/bees/syndi/Found(atom/A)
- return CanAttack(A)
+/mob/living/simple_animal/hostile/poison/bees/syndi/pollinate() // No Pollination
+ return
+
+/mob/living/simple_animal/hostile/poison/bees/syndi/Found(atom/A) //Typical usual hostile mob targeting list
+ return
/mob/living/simple_animal/hostile/poison/bees/syndi/CanAttack(atom/the_target)
. = ..()
if(!.)
- return 0
+ return FALSE
if(isliving(the_target))
var/mob/living/L = the_target
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H in master_and_friends)
- return 0
- return 1
+ return FALSE
+ return TRUE
/mob/living/simple_animal/hostile/poison/bees/syndi/AttackingTarget()
..()
if(target && isliving(target))
var/mob/living/L = target
if(L.stat)
- LoseTarget()
+ LoseTarget()
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index 5390b38b959..9d2fd385c47 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -58,6 +58,7 @@
if(!targets_from)
targets_from = src
environment_target_typecache = typecacheof(environment_target_typecache)
+ wanted_objects = typecacheof(wanted_objects)
/mob/living/simple_animal/hostile/Destroy()
targets_from = null
diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm
index d4406a386b5..1dded6c4e8c 100644
--- a/code/modules/mob/living/status_procs.dm
+++ b/code/modules/mob/living/status_procs.dm
@@ -298,6 +298,7 @@
/mob/living/SetLoseBreath(amount)
if(BREATHLESS in mutations)
+ losebreath = 0
return FALSE
losebreath = max(amount, 0)
diff --git a/code/modules/projectiles/guns/medbeam.dm b/code/modules/projectiles/guns/medbeam.dm
index d77621051e2..face61e79c3 100644
--- a/code/modules/projectiles/guns/medbeam.dm
+++ b/code/modules/projectiles/guns/medbeam.dm
@@ -54,8 +54,8 @@
feedback_add_details("gun_fired","[type]")
/obj/item/gun/medbeam/process()
- var/mob/living/carbon/human/H = loc
- if(!istype(H))
+ var/source = loc
+ if(!ishuman(source) && !isrobot(source))
LoseTarget()
return
@@ -68,9 +68,9 @@
last_check = world.time
- if(get_dist(H,current_target)>max_range || !los_check(H,current_target))
+ if(get_dist(source,current_target)>max_range || !los_check(source,current_target))
LoseTarget()
- to_chat(H, "You lose control of the beam!")
+ to_chat(source, "You lose control of the beam!")
return
if(current_target)
diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm
index 6e4379d1fc9..66f010b86e3 100644
--- a/code/modules/reagents/chemistry/holder.dm
+++ b/code/modules/reagents/chemistry/holder.dm
@@ -465,8 +465,8 @@ var/const/INGEST = 2
add_reagent(S, C.result_amount * C.secondary_results[S] * multiplier)
var/list/seen = viewers(4, get_turf(my_atom))
- for(var/mob/M in seen)
- if(!C.no_message)
+ for(var/mob/living/M in seen)
+ if(C.mix_message)
to_chat(M, "[bicon(my_atom)] [C.mix_message]")
if(istype(my_atom, /obj/item/slime_extract))
@@ -478,7 +478,8 @@ var/const/INGEST = 2
ME2.name = "used slime extract"
ME2.desc = "This extract has been used up."
- playsound(get_turf(my_atom), C.mix_sound, 80, 1)
+ if(C.mix_sound)
+ playsound(get_turf(my_atom), C.mix_sound, 80, 1)
C.on_reaction(src, created_volume)
reaction_occured = 1
diff --git a/code/modules/reagents/chemistry/reagents/pyrotechnic.dm b/code/modules/reagents/chemistry/reagents/pyrotechnic.dm
index fb58e351a03..d91a76da7fc 100644
--- a/code/modules/reagents/chemistry/reagents/pyrotechnic.dm
+++ b/code/modules/reagents/chemistry/reagents/pyrotechnic.dm
@@ -262,12 +262,6 @@
T.create_reagents(50)
T.reagents.add_reagent("sorium", 5)
-/datum/reagent/sorium_vortex
- name = "sorium_vortex"
- id = "sorium_vortex"
- reagent_state = LIQUID
- color = "#FFA500"
-
/datum/reagent/liquid_dark_matter
name = "Liquid Dark Matter"
id = "liquid_dark_matter"
@@ -285,12 +279,6 @@
T.create_reagents(50)
T.reagents.add_reagent("liquid_dark_matter", 5)
-/datum/reagent/ldm_vortex
- name = "LDM Vortex"
- id = "ldm_vortex"
- reagent_state = LIQUID
- color = "#800080"
-
/datum/reagent/blackpowder
name = "Black Powder"
id = "blackpowder"
diff --git a/code/modules/reagents/chemistry/reagents/toxins.dm b/code/modules/reagents/chemistry/reagents/toxins.dm
index 7ba6ed01667..76be206f35f 100644
--- a/code/modules/reagents/chemistry/reagents/toxins.dm
+++ b/code/modules/reagents/chemistry/reagents/toxins.dm
@@ -1049,6 +1049,11 @@
update_flags |= M.adjustToxLoss(1, FALSE)
return ..() | update_flags
+/datum/reagent/pestkiller/reaction_obj(obj/O, volume)
+ if(istype(O, /obj/effect/decal/ants))
+ O.visible_message("The ants die.")
+ qdel(O)
+
/datum/reagent/pestkiller/reaction_mob(mob/living/M, method=TOUCH, volume)
if(iscarbon(M))
var/mob/living/carbon/C = M
diff --git a/code/modules/reagents/chemistry/recipes.dm b/code/modules/reagents/chemistry/recipes.dm
index 288abeb5f4d..a881f191594 100644
--- a/code/modules/reagents/chemistry/recipes.dm
+++ b/code/modules/reagents/chemistry/recipes.dm
@@ -11,13 +11,11 @@
var/required_other = 0 // an integer required for the reaction to happen
var/result_amount = 0
- var/secondary = 0 // set to nonzero if secondary reaction
var/list/secondary_results = list() //additional reagents produced by the reaction
var/min_temp = 0 //Minimum temperature required for the reaction to occur (heat to/above this). min_temp = 0 means no requirement
var/max_temp = 9999 //Maximum temperature allowed for the reaction to occur (cool to/below this).
var/mix_message = "The solution begins to bubble."
var/mix_sound = 'sound/effects/bubbles.ogg'
- var/no_message = 0
/datum/chemical_reaction/proc/on_reaction(datum/reagents/holder, created_volume)
return
diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
index 5aca554ae03..a21a7fcf1c2 100644
--- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
+++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
@@ -89,55 +89,59 @@
name = "Sorium"
id = "sorium"
result = "sorium"
- required_reagents = list("mercury" = 1, "oxygen" = 1, "nitrogen" = 1, "carbon" = 1)
+ required_reagents = list("mercury" = 1, "carbon" = 1, "nitrogen" = 1, "oxygen" = 1, "stabilizing_agent" = 1)
result_amount = 4
+ mix_message = "The mixture pops and crackles before settling down."
-/datum/chemical_reaction/sorium/on_reaction(datum/reagents/holder, created_volume)
- if(holder.has_reagent("stabilizing_agent"))
+/datum/chemical_reaction/sorium_explosion
+ name = "Sorium Explosion"
+ id = "sorium_explosion"
+ required_reagents = list("mercury" = 1, "carbon" = 1, "nitrogen" = 1, "oxygen" = 1)
+ result_amount = 1
+ mix_message = "The mixture explodes with a big bang."
+
+/datum/chemical_reaction/sorium_explosion/on_reaction(datum/reagents/holder, created_volume)
+ var/turf/T = get_turf(holder.my_atom)
+ if(!T)
return
- var/turf/simulated/T = get_turf(holder.my_atom)
goonchem_vortex(T, 0, created_volume)
- holder.remove_reagent("sorium", created_volume)
-/datum/chemical_reaction/sorium_vortex
+/datum/chemical_reaction/sorium_explosion/sorium
name = "sorium_vortex"
id = "sorium_vortex"
- result = "sorium_vortex"
required_reagents = list("sorium" = 1)
- result_amount = 1
min_temp = T0C + 200
-
-/datum/chemical_reaction/sorium_vortex/on_reaction(datum/reagents/holder, created_volume)
- var/turf/simulated/T = get_turf(holder.my_atom)
- goonchem_vortex(T, 0, created_volume)
- holder.remove_reagent("sorium_vortex", created_volume)
+ mix_sound = null
+ mix_message = null
/datum/chemical_reaction/liquid_dark_matter
name = "Liquid Dark Matter"
id = "liquid_dark_matter"
result = "liquid_dark_matter"
+ required_reagents = list("plasma" = 1, "radium" = 1, "carbon" = 1, "stabilizing_agent" = 1)
+ result_amount = 4
+ mix_message = "The mixture begins to glow in a dark purple."
+
+/datum/chemical_reaction/ldm_implosion
+ name = "Implosion"
+ id = "implosion"
required_reagents = list("plasma" = 1, "radium" = 1, "carbon" = 1)
- result_amount = 3
+ result_amount = 1
+ mix_message = "The mixture implodes suddenly."
-/datum/chemical_reaction/liquid_dark_matter/on_reaction(datum/reagents/holder, created_volume)
- if(holder.has_reagent("stabilizing_agent"))
- return
+/datum/chemical_reaction/ldm_implosion/on_reaction(datum/reagents/holder, created_volume)
var/turf/simulated/T = get_turf(holder.my_atom)
+ if(!T)
+ return
goonchem_vortex(T, 1, created_volume)
- holder.remove_reagent("liquid_dark_matter", created_volume)
-/datum/chemical_reaction/ldm_vortex
+/datum/chemical_reaction/ldm_implosion/liquid_dark_matter
name = "LDM Vortex"
id = "ldm_vortex"
- result = "ldm_vortex"
required_reagents = list("liquid_dark_matter" = 1)
- result_amount = 1
min_temp = T0C + 200
-
-/datum/chemical_reaction/ldm_vortex/on_reaction(datum/reagents/holder, created_volume)
- var/turf/simulated/T = get_turf(holder.my_atom)
- goonchem_vortex(T, 1, created_volume)
- holder.remove_reagent("ldm_vortex", created_volume)
+ mix_sound = null
+ mix_message = null
/datum/chemical_reaction/blackpowder
name = "Black Powder"
@@ -154,7 +158,7 @@
required_reagents = list("blackpowder" = 1)
result_amount = 1
min_temp = T0C + 200
- no_message = 1
+ mix_message = null
mix_sound = null
/datum/chemical_reaction/blackpowder_explosion/on_reaction(datum/reagents/holder, created_volume)
@@ -175,42 +179,35 @@
spawn(0)
qdel(holder.my_atom)
-datum/chemical_reaction/flash_powder
+/datum/chemical_reaction/flash_powder
name = "Flash powder"
id = "flash_powder"
result = "flash_powder"
- required_reagents = list("aluminum" = 1, "potassium" = 1, "sulfur" = 1, "chlorine" = 1)
- result_amount = 3
+ required_reagents = list("aluminum" = 1, "potassium" = 1, "sulfur" = 1, "chlorine" = 1, "stabilizing_agent" = 1)
+ result_amount = 5
+ mix_message = "The chemicals hiss and fizz briefly before falling still."
-/datum/chemical_reaction/flash_powder/on_reaction(datum/reagents/holder, created_volume)
- if(holder.has_reagent("stabilizing_agent"))
- return
- var/location = get_turf(holder.my_atom)
- do_sparks(2, 1, location)
- for(var/mob/living/carbon/C in viewers(5, location))
- if(C.flash_eyes())
- if(get_dist(C, location) < 4)
- C.Weaken(5)
- continue
- C.Stun(5)
- holder.remove_reagent("flash_powder", created_volume)
-
-/datum/chemical_reaction/flash_powder_flash
- name = "Flash powder activation"
- id = "flash_powder_flash"
+/datum/chemical_reaction/flash
+ name = "Flash"
+ id = "flash"
result = null
+ required_reagents = list("aluminum" = 1, "potassium" = 1, "sulfur" = 1, "chlorine" = 1)
+ mix_message = "The chemicals catch fire, burning brightly and violently!"
+ mix_sound = 'sound/effects/bang.ogg'
+
+/datum/chemical_reaction/flash/on_reaction(datum/reagents/holder, created_volume)
+ var/location = get_turf(holder.my_atom)
+ if(!location)
+ return
+ do_sparks(2, 1, location)
+ bang(location, holder.my_atom, 5, flash = TRUE, bang = FALSE)
+
+/datum/chemical_reaction/flash/flash_powder
+ name = "flash_powder_flash"
+ id = "flash_powder_flash"
required_reagents = list("flash_powder" = 1)
min_temp = T0C + 100
-
-/datum/chemical_reaction/flash_powder_flash/on_reaction(datum/reagents/holder, created_volume)
- var/location = get_turf(holder.my_atom)
- do_sparks(2, 1, location)
- for(var/mob/living/carbon/C in viewers(5, location))
- if(C.flash_eyes())
- if(get_dist(C, location) < 4)
- C.Weaken(5)
- continue
- C.Stun(5)
+ mix_message = null
/datum/chemical_reaction/phlogiston
name = "Phlogiston"
@@ -250,7 +247,7 @@ datum/chemical_reaction/flash_powder
name = "smoke_powder"
id = "smoke_powder"
result = "smoke_powder"
- required_reagents = list("stabilizing_agent" = 1, "potassium" = 1, "sugar" = 1, "phosphorus" = 1)
+ required_reagents = list("potassium" = 1, "sugar" = 1, "phosphorus" = 1, "stabilizing_agent" = 1)
result_amount = 3
mix_message = "The mixture sets into a greyish powder!"
@@ -285,7 +282,6 @@ datum/chemical_reaction/flash_powder
id = "smoke_powder_smoke"
required_reagents = list("smoke_powder" = 1)
min_temp = T0C + 100
- secondary = 1
result_amount = 1
forbidden_reagents = list("stimulants")
mix_sound = null
@@ -294,78 +290,30 @@ datum/chemical_reaction/flash_powder
name = "sonic_powder"
id = "sonic_powder"
result = "sonic_powder"
+ required_reagents = list("oxygen" = 1, "cola" = 1, "phosphorus" = 1, "stabilizing_agent" = 1)
+ result_amount = 2
+ mix_message = "The mixture begins to bubble slighly!"
+
+/datum/chemical_reaction/sonic_deafen
+ name = "sonic_deafen"
+ id = "sonic_deafen"
+ result = null
required_reagents = list("oxygen" = 1, "cola" = 1, "phosphorus" = 1)
- result_amount = 3
+ mix_message = "The mixture begins to bubble furiously!"
+ mix_sound = 'sound/effects/bang.ogg'
-/datum/chemical_reaction/sonic_powder/on_reaction(datum/reagents/holder, created_volume)
- if(holder.has_reagent("stabilizing_agent"))
- return
+/datum/chemical_reaction/sonic_deafen/on_reaction(datum/reagents/holder, created_volume)
var/location = get_turf(holder.my_atom)
- playsound(location, 'sound/effects/bang.ogg', 25, 1)
- for(var/mob/living/M in hearers(5, location))
- var/ear_safety = 0
- var/distance = max(1,get_dist(src,T))
- if(iscarbon(M))
- var/mob/living/carbon/C = M
- if(ishuman(C))
- var/mob/living/carbon/human/H = C
- if((H.r_ear && (H.r_ear.flags & EARBANGPROTECT)) || (H.l_ear && (H.l_ear.flags & EARBANGPROTECT)) || (H.head && (H.head.flags & HEADBANGPROTECT)))
- ear_safety++
- to_chat(C, "BANG")
- if(!ear_safety)
- M.Stun(max(10/distance, 3))
- M.Weaken(max(10/distance, 3))
- M.AdjustEarDamage(rand(0, 5), 15)
- if(iscarbon(M))
- var/mob/living/carbon/C = M
- var/obj/item/organ/internal/ears/ears = C.get_int_organ(/obj/item/organ/internal/ears)
- if(istype(ears))
- if(ears.ear_damage >= 15)
- to_chat(M, "Your ears start to ring badly!")
- if(prob(ears.ear_damage - 5))
- to_chat(M, "You can't hear anything!")
- M.BecomeDeaf()
- else
- if(ears.ear_damage >= 5)
- to_chat(M, "Your ears start to ring!")
- holder.remove_reagent("sonic_powder", created_volume)
+ if(!location)
+ return
+ bang(location, holder.my_atom, 5, flash = FALSE, bang = TRUE)
-/datum/chemical_reaction/sonic_powder_deafen
+/datum/chemical_reaction/sonic_deafen/sonic_powder
name = "sonic_powder_deafen"
id = "sonic_powder_deafen"
- result = null
required_reagents = list("sonic_powder" = 1)
min_temp = T0C + 100
-
-/datum/chemical_reaction/sonic_powder_deafen/on_reaction(datum/reagents/holder, created_volume)
- var/location = get_turf(holder.my_atom)
- playsound(location, 'sound/effects/bang.ogg', 25, 1)
- for(var/mob/living/M in hearers(5, location))
- var/ear_safety = 0
- var/distance = max(1,get_dist(src,T))
- if(iscarbon(M))
- var/mob/living/carbon/C = M
- if(ishuman(C))
- var/mob/living/carbon/human/H = C
- if((H.r_ear && (H.r_ear.flags & EARBANGPROTECT)) || (H.l_ear && (H.l_ear.flags & EARBANGPROTECT)) || (H.head && (H.head.flags & HEADBANGPROTECT)))
- ear_safety++
- to_chat(M, "BANG")
- if(!ear_safety)
- M.Stun(max(10/distance, 3))
- M.Weaken(max(10/distance, 3))
- M.AdjustEarDamage(rand(0, 5), 15)
- if(iscarbon(M))
- var/mob/living/carbon/C = M
- var/obj/item/organ/internal/ears/ears = C.get_int_organ(/obj/item/organ/internal/ears)
- if(istype(ears))
- if(ears.ear_damage >= 15)
- to_chat(M, "Your ears start to ring badly!")
- if(prob(ears.ear_damage - 5))
- to_chat(M, "You can't hear anything!")
- M.BecomeDeaf()
- else
- if(ears.ear_damage >= 5)
- to_chat(M, "Your ears start to ring!")
+ mix_message = null
/datum/chemical_reaction/cryostylane
name = "cryostylane"
diff --git a/code/modules/reagents/chemistry/recipes/toxins.dm b/code/modules/reagents/chemistry/recipes/toxins.dm
index 54e3ce4fdb8..1a073eae598 100644
--- a/code/modules/reagents/chemistry/recipes/toxins.dm
+++ b/code/modules/reagents/chemistry/recipes/toxins.dm
@@ -15,7 +15,7 @@
result_amount = 1
min_temp = T0C + 400
mix_sound = null
- no_message = 1
+ mix_message = null
/datum/chemical_reaction/cyanide
name = "Cyanide"
diff --git a/code/modules/reagents/reagent_containers/glass_containers.dm b/code/modules/reagents/reagent_containers/glass_containers.dm
index e00ecf5c9fb..d67d888a75b 100644
--- a/code/modules/reagents/reagent_containers/glass_containers.dm
+++ b/code/modules/reagents/reagent_containers/glass_containers.dm
@@ -113,7 +113,7 @@
to_chat(user, "You cannot fill [target] while it is sealed.")
return
- else if(istype(target, /obj/effect/decal/cleanable)) //stops splashing while scooping up fluids
+ else if(istype(target, /obj/effect/decal)) //stops splashing while scooping up fluids
return
else if(reagents.total_volume)
diff --git a/code/modules/reagents/reagent_containers/pill.dm b/code/modules/reagents/reagent_containers/pill.dm
index 9e41ce7664b..ec89b8a463a 100644
--- a/code/modules/reagents/reagent_containers/pill.dm
+++ b/code/modules/reagents/reagent_containers/pill.dm
@@ -11,6 +11,7 @@
volume = 100
consume_sound = null
taste = FALSE
+ antable = FALSE
/obj/item/reagent_containers/food/pill/New()
..()
diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm
index 8cf0f52d847..239cb71328e 100755
--- a/code/modules/recycling/sortingmachinery.dm
+++ b/code/modules/recycling/sortingmachinery.dm
@@ -177,7 +177,9 @@
var/obj/structure/closet/crate/O = target
if(O.opened)
return
- if(use(3))
+ if(amount >= 3 && do_after_once(user, 15, target = target))
+ if(O.opened || !use(3))
+ return
var/obj/structure/bigDelivery/P = new /obj/structure/bigDelivery(get_turf(O.loc))
P.icon_state = "deliverycrate"
P.wrapped = O
@@ -189,7 +191,9 @@
var/obj/structure/closet/O = target
if(O.opened)
return
- if(use(3))
+ if(amount >= 3 && do_after_once(user, 15, target = target))
+ if(O.opened || !use(3))
+ return
var/obj/structure/bigDelivery/P = new /obj/structure/bigDelivery(get_turf(O.loc))
P.wrapped = O
P.init_welded = O.welded
diff --git a/code/modules/surgery/organs/blood.dm b/code/modules/surgery/organs/blood.dm
index 0ff4273daa1..d2d758529aa 100644
--- a/code/modules/surgery/organs/blood.dm
+++ b/code/modules/surgery/organs/blood.dm
@@ -18,23 +18,11 @@
// Takes care blood loss and regeneration
/mob/living/carbon/human/handle_blood()
- var/list/blood_data = get_blood_data(get_blood_id())//PROCCEPTION
-
if(NO_BLOOD in dna.species.species_traits)
bleed_rate = 0
return
if(bodytemperature >= 225 && !(NOCLONE in mutations)) //cryosleep or husked people do not pump the blood.
-
- //Blood regeneration if there is some space
- if(blood_volume < max_blood && blood_volume)
- if(mind) //Handles vampires "eating" blood that isn't their own.
- if(mind in ticker.mode.vampires)
- if(nutrition >= NUTRITION_LEVEL_WELL_FED)
- return //We don't want blood tranfusions making vampires fat.
- if(blood_data["donor"] != src)
- nutrition += (15 * REAGENTS_METABOLISM)
- return //Only process one blood per tick, to maintain the same metabolism as nutriment for non-vampires.
if(blood_volume < BLOOD_VOLUME_NORMAL)
blood_volume += 0.1 // regenerate blood VERY slowly
@@ -56,7 +44,7 @@
if(prob(15))
Paralyse(rand(1,3))
to_chat(src, "You feel extremely [word].")
- if(0 to BLOOD_VOLUME_SURVIVE)
+ if(-INFINITY to BLOOD_VOLUME_SURVIVE)
death()
var/temp_bleed = 0
diff --git a/config/example/config.txt b/config/example/config.txt
index 1e994f50526..4eb642cf796 100644
--- a/config/example/config.txt
+++ b/config/example/config.txt
@@ -402,4 +402,7 @@ DISABLE_HIGH_POP_MC_MODE_AMOUNT 60
##DEVELOPER_EXPRESS_START
## Uncomment to disable automatic admin for localhost
-#DISABLE_LOCALHOST_ADMIN
\ No newline at end of file
+#DISABLE_LOCALHOST_ADMIN
+
+## Uncomment to give a confirmation before hitting start now
+#START_NOW_CONFIRMATION
\ No newline at end of file
diff --git a/html/changelog.html b/html/changelog.html
index 37c457468ef..af410acc732 100644
--- a/html/changelog.html
+++ b/html/changelog.html
@@ -56,6 +56,91 @@
-->