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 @@ -->
+

04 April 2019

+

Kyep updated:

+ + +

03 April 2019

+

Fox McCloud updated:

+ +

farie82 updated:

+ + +

02 April 2019

+

Alonefromhell & AffectedArc07 updated:

+ +

Arkatos updated:

+ +

AzuleUtama updated:

+ +

Fox McCloud updated:

+ +

KasparoVy updated:

+ +

Kyep updated:

+ +

Markolie updated:

+ +

Ty-Omaha updated:

+ +

farie82 updated:

+ +

01 April 2019

Arkatos updated: